CONFIG_BLK_SCSI_REQUEST=y
# CONFIG_BRCMSTB_THERMAL is not set
CONFIG_BRCM_CHAR_DRIVERS=y
-# CONFIG_BT_MTKUART is not set
CONFIG_BUILD_BIN2C=y
# CONFIG_CACHE_L2X0 is not set
CONFIG_CC_HAS_ASM_GOTO=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_UID16=y
CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
-# CONFIG_HID_BIGBEN_FF is not set
CONFIG_HW_CONSOLE=y
CONFIG_HZ_FIXED=0
CONFIG_I2C=y
CONFIG_TIMER_PROBE=y
CONFIG_TINY_SRCU=y
CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_TOUCHSCREEN_RPI_FT5406 is not set
CONFIG_UEVENT_HELPER_PATH=""
# CONFIG_UID16 is not set
CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
CONFIG_BRCMSTB_THERMAL=y
CONFIG_BRCM_CHAR_DRIVERS=y
CONFIG_BROADCOM_PHY=y
-# CONFIG_BT_MTKUART is not set
CONFIG_BUILD_BIN2C=y
# CONFIG_CACHE_L2X0 is not set
CONFIG_CC_HAS_ASM_GOTO=y
CONFIG_EDAC_ATOMIC_SCRUB=y
CONFIG_EDAC_SUPPORT=y
CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_EXTCON_ARIZONA is not set
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_UID16=y
CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
-# CONFIG_HID_BIGBEN_FF is not set
CONFIG_HIGHMEM=y
CONFIG_HIGHPTE=y
CONFIG_HOTPLUG_CPU=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
CONFIG_JBD2=y
-CONFIG_KERNEL_GZIP=y
-# CONFIG_KERNEL_XZ is not set
# CONFIG_LCD_CLASS_DEVICE is not set
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGER_INPUT=y
CONFIG_PADATA=y
CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PCI=y
+CONFIG_PCIEAER=y
+CONFIG_PCIEPORTBUS=y
CONFIG_PCIE_BRCMSTB=y
+CONFIG_PCIE_PME=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DOMAINS_GENERIC=y
CONFIG_PCI_MSI=y
CONFIG_PM_SLEEP_SMP=y
CONFIG_POWER_SUPPLY=y
CONFIG_PRINTK_TIME=y
+CONFIG_RAS=y
CONFIG_RASPBERRYPI_FIRMWARE=y
CONFIG_RASPBERRYPI_POWER=y
CONFIG_RATIONAL=y
CONFIG_TIMER_OF=y
CONFIG_TIMER_PROBE=y
CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_TOUCHSCREEN_RPI_FT5406 is not set
CONFIG_TREE_RCU=y
CONFIG_TREE_SRCU=y
CONFIG_UEVENT_HELPER_PATH=""
CONFIG_XPS=y
CONFIG_XZ_DEC_ARM=y
CONFIG_XZ_DEC_BCJ=y
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ZBOOT_ROM_TEXT=0
CONFIG_BLK_SCSI_REQUEST=y
CONFIG_BRCMSTB_THERMAL=y
CONFIG_BRCM_CHAR_DRIVERS=y
-# CONFIG_BT_MTKUART is not set
CONFIG_BUILD_BIN2C=y
CONFIG_CAVIUM_ERRATUM_22375=y
CONFIG_CAVIUM_ERRATUM_23154=y
CONFIG_DMA_DIRECT_OPS=y
CONFIG_DMA_ENGINE=y
CONFIG_DMA_OF=y
+CONFIG_DMA_SHARED_BUFFER=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
CONFIG_DNOTIFY=y
CONFIG_DTC=y
CONFIG_DUMMY_CONSOLE=y
CONFIG_EDAC_SUPPORT=y
CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_EXTCON_ARIZONA is not set
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_HAVE_RSEQ=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
-# CONFIG_HID_BIGBEN_FF is not set
CONFIG_HOLES_IN_ZONE=y
CONFIG_HOTPLUG_CPU=y
# CONFIG_HUGETLBFS is not set
CONFIG_TIMER_OF=y
CONFIG_TIMER_PROBE=y
CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_TOUCHSCREEN_RPI_FT5406 is not set
CONFIG_TREE_RCU=y
CONFIG_TREE_SRCU=y
CONFIG_UEVENT_HELPER_PATH=""
$(eval $(call KernelPackage,sound-soc-hifiberry-dacplusadc))
+define KernelPackage/sound-soc-hifiberry-dacplusadc-pro
+ TITLE:=Support for HifiBerry DAC+ADC PRO
+ KCONFIG:= \
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO \
+ CONFIG_SND_SOC_PCM186X \
+ CONFIG_SND_SOC_PCM186X_I2C \
+ CONFIG_SND_SOC_PCM512x \
+ CONFIG_SND_SOC_PCM512x_I2C
+ FILES:= \
+ $(LINUX_DIR)/sound/soc/bcm/snd-soc-hifiberry-dacplusadcpro.ko \
+ $(LINUX_DIR)/sound/soc/codecs/snd-soc-pcm186x.ko \
+ $(LINUX_DIR)/sound/soc/codecs/snd-soc-pcm186x-i2c.ko \
+ $(LINUX_DIR)/sound/soc/codecs/snd-soc-pcm512x.ko \
+ $(LINUX_DIR)/sound/soc/codecs/snd-soc-pcm512x-i2c.ko
+ AUTOLOAD:=$(call AutoLoad,68,snd-soc-pcm186x snd-soc-pcm186x-i2c \
+ snd-soc-pcm512x snd-soc-pcm512x-i2c snd-soc-hifiberry-dacplusadcpro)
+ DEPENDS:= \
+ kmod-sound-soc-bcm2835-i2s \
+ +kmod-i2c-bcm2835 \
+ +kmod-regmap-i2c
+ $(call AddDepends/sound)
+endef
+
+define KernelPackage/sound-soc-hifiberry-dacplusadc-pro/description
+ This package contains support for HifiBerry DAC+ADC PRO
+endef
+
+$(eval $(call KernelPackage,sound-soc-hifiberry-dacplusadc-pro))
+
+
define KernelPackage/sound-soc-hifiberry-digi
TITLE:=Support for HifiBerry Digi / Digi+ / Digi+ Pro
KCONFIG:= \
--- a/drivers/net/can/spi/mcp251x.c
+++ b/drivers/net/can/spi/mcp251x.c
-@@ -951,6 +951,9 @@ static int mcp251x_open(struct net_devic
+@@ -952,6 +952,9 @@ static int mcp251x_open(struct net_devic
priv->tx_skb = NULL;
priv->tx_len = 0;
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
-@@ -850,6 +850,10 @@ struct net_device *gether_setup_name_def
+@@ -848,6 +848,10 @@ struct net_device *gether_setup_name_def
net->ethtool_ops = &ops;
SET_NETDEV_DEVTYPE(net, &gadget_type);
-From d76972193fe88bb13028ba8277736a6aec4b8c8a Mon Sep 17 00:00:00 2001
+From 623cca7c1ef73b6b164d487d3bb3b2bddc60abab Mon Sep 17 00:00:00 2001
From: Dan Pasanen <dan.pasanen@gmail.com>
Date: Thu, 21 Sep 2017 09:55:42 -0500
-Subject: [PATCH 001/703] arm: partially revert
+Subject: [PATCH 001/725] arm: partially revert
702b94bff3c50542a6e4ab9a4f4cef093262fe65
* Re-expose some dmi APIs for use in VCSM
-From 8f4948a1503a76cbeb5823d8b17990bf3a3c57a6 Mon Sep 17 00:00:00 2001
+From b356c22b7c3cce97ba7c20af22f508510387a3f2 Mon Sep 17 00:00:00 2001
From: Steve Glendinning <steve.glendinning@smsc.com>
Date: Thu, 19 Feb 2015 18:47:12 +0000
-Subject: [PATCH 002/703] smsx95xx: fix crimes against truesize
+Subject: [PATCH 002/725] 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.
-From 623b0f5e0a439af4beef58317b224d4d3d2a969c Mon Sep 17 00:00:00 2001
+From 440ed9d083956067ffbaaefd3e2411b746126593 Mon Sep 17 00:00:00 2001
From: Sam Nazarko <email@samnazarko.co.uk>
Date: Fri, 1 Apr 2016 17:27:21 +0100
-Subject: [PATCH 003/703] smsc95xx: Experimental: Enable turbo_mode and
+Subject: [PATCH 003/725] smsc95xx: Experimental: Enable turbo_mode and
packetsize=2560 by default
See: http://forum.kodi.tv/showthread.php?tid=285288
-From 80592905099a4f0fa5d166d58785eacef968ba4e Mon Sep 17 00:00:00 2001
+From 3590eb29c3b4307a50daf24c1d58e188b1aaf65d Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 26 Mar 2013 17:26:38 +0000
-Subject: [PATCH 004/703] Allow mac address to be set in smsc95xx
+Subject: [PATCH 004/725] Allow mac address to be set in smsc95xx
Signed-off-by: popcornmix <popcornmix@gmail.com>
---
-From b5e65f6a5a75c72d56d98c9543ff549710aa2d72 Mon Sep 17 00:00:00 2001
+From 42773929bcec27d195b93b11c10527be7fccd2d8 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Fri, 13 Mar 2015 12:43:36 +0000
-Subject: [PATCH 005/703] Protect __release_resource against resources without
+Subject: [PATCH 005/725] Protect __release_resource against resources without
parents
Without this patch, removing a device tree overlay can crash here.
-From da00086d33452442af1009580f8e40164fc4e97f Mon Sep 17 00:00:00 2001
+From ca08ef4827614912c6f07fa734a2eede3420a9c6 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Fri, 4 Dec 2015 17:41:50 +0000
-Subject: [PATCH 006/703] irq-bcm2836: Prevent spurious interrupts, and trap
+Subject: [PATCH 006/725] irq-bcm2836: Prevent spurious interrupts, and trap
them early
The old arch-specific IRQ macros included a dsb to ensure the
-From 23f28161eadbc84b976b1a6ff4c8e4fdfa38aa93 Mon Sep 17 00:00:00 2001
+From b3b97bc061e22d03569cd7eedaf7cc1b4fb403f3 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Thu, 9 Feb 2017 14:33:30 +0000
-Subject: [PATCH 007/703] irq-bcm2836: Avoid "Invalid trigger warning"
+Subject: [PATCH 007/725] irq-bcm2836: Avoid "Invalid trigger warning"
Initialise the level for each IRQ to avoid a warning from the
arm arch timer code.
-From 06cc1d14e061ef7169947f09f1e356cec9e0a790 Mon Sep 17 00:00:00 2001
+From 9920e74cfd7571c36fce1caf84736f89e275fe22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
Date: Fri, 12 Jun 2015 19:01:05 +0200
-Subject: [PATCH 008/703] irqchip: bcm2835: Add FIQ support
+Subject: [PATCH 008/725] irqchip: bcm2835: Add FIQ support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 9c8894afe627b270aad44c64f4e70c659468d7ed Mon Sep 17 00:00:00 2001
+From b08bd87913c001b0f3d7f86d73abfc2074b0cab2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
Date: Fri, 23 Oct 2015 16:26:55 +0200
-Subject: [PATCH 009/703] irqchip: irq-bcm2835: Add 2836 FIQ support
+Subject: [PATCH 009/725] irqchip: irq-bcm2835: Add 2836 FIQ support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 97e88641862862585d6ae8aaae034946ceab8ceb Mon Sep 17 00:00:00 2001
+From e73e4e6923289a3055d5fd10c7726fbe358505ad Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 14 Jul 2015 10:26:09 +0100
-Subject: [PATCH 010/703] spidev: Add "spidev" compatible string to silence
+Subject: [PATCH 010/725] spidev: Add "spidev" compatible string to silence
warning
See: https://github.com/raspberrypi/linux/issues/1054
-From 5d9d6d510a0e7d2e3eee1ed663f0157c719c90ec Mon Sep 17 00:00:00 2001
+From e1ebc1b8dcb6990e2541e3503cb2cdd3f5edfc1e Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Wed, 24 Jun 2015 14:10:44 +0100
-Subject: [PATCH 011/703] spi-bcm2835: Support pin groups other than 7-11
+Subject: [PATCH 011/725] 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
-From 8d654c03c8e0730e67fc4e7d6435da05ddf4e284 Mon Sep 17 00:00:00 2001
+From e901e4ff32c1f3c10342b4607579a1d9613c3c66 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Fri, 1 Jul 2016 22:09:24 +0100
-Subject: [PATCH 012/703] spi-bcm2835: Disable forced software CS
+Subject: [PATCH 012/725] 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
-From 5a6dcccb576167d1e50c922bfb7bf6cffbdaa671 Mon Sep 17 00:00:00 2001
+From f1b841cc75bcd8c655c9cd6c3dbed439a1f4d24a Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 8 Nov 2016 21:35:38 +0000
-Subject: [PATCH 013/703] spi-bcm2835: Remove unused code
+Subject: [PATCH 013/725] spi-bcm2835: Remove unused code
---
drivers/spi/spi-bcm2835.c | 61 ---------------------------------------
-From abbc7f81bb68293439c0a325b5a590d28b91b819 Mon Sep 17 00:00:00 2001
+From 568609dad2f29b45931c2fc869f87d4abb6c7486 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
Date: Sat, 3 Oct 2015 22:22:55 +0200
-Subject: [PATCH 014/703] dmaengine: bcm2835: Load driver early and support
+Subject: [PATCH 014/725] dmaengine: bcm2835: Load driver early and support
legacy API
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
-From 8d00375a0645102bc58fc5c8e4c05efbcfbbbd71 Mon Sep 17 00:00:00 2001
+From 8151b76346ed89410b20db4fb4bc8f1784e0fd19 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 25 Jan 2016 17:25:12 +0000
-Subject: [PATCH 015/703] firmware: Updated mailbox header
+Subject: [PATCH 015/725] firmware: Updated mailbox header
---
include/soc/bcm2835/raspberrypi-firmware.h | 5 +++++
-From afbee813c2e801c74c1732eb4511e5fd32027245 Mon Sep 17 00:00:00 2001
+From 0af4ce25fc884c07db940d61e7677bba37a4130d Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Wed, 15 Jun 2016 16:48:41 +0100
-Subject: [PATCH 016/703] rtc: Add SPI alias for pcf2123 driver
+Subject: [PATCH 016/725] rtc: Add SPI alias for pcf2123 driver
Without this alias, Device Tree won't cause the driver
to be loaded.
-From 3091f3a65590ab446e9c637377efa55dc3b8996f Mon Sep 17 00:00:00 2001
+From 726d38c5f2aee110f7e3b0f03fc17e5fc69aa8c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
Date: Fri, 7 Oct 2016 16:50:59 +0200
-Subject: [PATCH 017/703] watchdog: bcm2835: Support setting reboot partition
+Subject: [PATCH 017/725] watchdog: bcm2835: Support setting reboot partition
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 49dc030939b6332a4d1dca0c2b12ea9f559dcf2f Mon Sep 17 00:00:00 2001
+From a48963920cbab4a54fb8c1a12cab6f51249c8938 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 5 Apr 2016 19:40:12 +0100
-Subject: [PATCH 018/703] reboot: Use power off rather than busy spinning when
+Subject: [PATCH 018/725] reboot: Use power off rather than busy spinning when
halt is requested
---
-From 9fdc1aa7e5d82029afb4e14c3ef3613264f6eca0 Mon Sep 17 00:00:00 2001
+From 5b4c3e8bea1e40ae39e8e1d557f71c2262e41740 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 9 Nov 2016 13:02:52 +0000
-Subject: [PATCH 019/703] bcm: Make RASPBERRYPI_POWER depend on PM
+Subject: [PATCH 019/725] bcm: Make RASPBERRYPI_POWER depend on PM
---
drivers/soc/bcm/Kconfig | 1 +
-From 4900c14f9c0f514162496e6a3f71c51a50e7b376 Mon Sep 17 00:00:00 2001
+From 2d35d5929c505731a490ea56a6a78f487c082e01 Mon Sep 17 00:00:00 2001
From: Martin Sperl <kernel@martin.sperl.org>
Date: Fri, 2 Sep 2016 16:45:27 +0100
-Subject: [PATCH 020/703] Register the clocks early during the boot process, so
+Subject: [PATCH 020/725] 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.
-From bc5b619aa9eaa634e49483c95b3681171cb4d900 Mon Sep 17 00:00:00 2001
+From 241096d58e818f8f471eb141b1183e8b5e8ffea8 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 6 Dec 2016 17:05:39 +0000
-Subject: [PATCH 021/703] bcm2835-rng: Avoid initialising if already enabled
+Subject: [PATCH 021/725] bcm2835-rng: Avoid initialising if already enabled
Avoids the 0x40000 cycles of warmup again if firmware has already used it
---
-From 30a4c0ff154b3ce8fd0df9054d03cee55dacc8d0 Mon Sep 17 00:00:00 2001
+From 8bf56ee660bf07a25ba3a2081d9a498435d16a32 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Wed, 24 Aug 2016 16:28:44 +0100
-Subject: [PATCH 022/703] kbuild: Ignore dtco targets when filtering symbols
+Subject: [PATCH 022/725] kbuild: Ignore dtco targets when filtering symbols
---
scripts/Kbuild.include | 2 +-
-From 06ad042c1d3b3471c478fee39a7539ac39b752ff Mon Sep 17 00:00:00 2001
+From a87e7ca656f8b80caf7db0056ba4b6191018359f Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 13 Feb 2017 17:20:08 +0000
-Subject: [PATCH 023/703] clk-bcm2835: Mark used PLLs and dividers CRITICAL
+Subject: [PATCH 023/725] 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
-From 14e1d51f1737da7b2bf59df95db6f977179e0497 Mon Sep 17 00:00:00 2001
+From b0d7a3297087a0a78e12e9e8fc41e9c91a114304 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 13 Feb 2017 17:20:08 +0000
-Subject: [PATCH 024/703] clk-bcm2835: Add claim-clocks property
+Subject: [PATCH 024/725] 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,
-From 9e24627b07ac0553c9fc00a069fcc10c22a3cb6f Mon Sep 17 00:00:00 2001
+From 91e0734c2ca8c8629b0537329c7e6d538fa1c085 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 6 Mar 2017 09:06:18 +0000
-Subject: [PATCH 025/703] clk-bcm2835: Read max core clock from firmware
+Subject: [PATCH 025/725] 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
-From fabb3595bd356f058329ff94a3c5e31df5d84217 Mon Sep 17 00:00:00 2001
+From e61099f2c51b1583663e5868f87056d4c11b6e9d Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Mon, 9 May 2016 17:28:18 -0700
-Subject: [PATCH 026/703] clk: bcm2835: Mark GPIO clocks enabled at boot as
+Subject: [PATCH 026/725] clk: bcm2835: Mark GPIO clocks enabled at boot as
critical.
These divide off of PLLD_PER and are used for the ethernet and wifi
-From 34dfe2b3ea493bc57c2b85280c28dbe0b3c1d1dc Mon Sep 17 00:00:00 2001
+From 4d94da034003c8f8ba44ba4a8abdf5c9cf56d684 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Thu, 9 Feb 2017 14:36:44 +0000
-Subject: [PATCH 027/703] sound: Demote deferral errors to INFO level
+Subject: [PATCH 027/725] 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.
-From dae5f48d60cccc2214a09c11b84373988e57e2f5 Mon Sep 17 00:00:00 2001
+From be7a5d79d1f4d8f8db39f092e7f07d8cb05eebf7 Mon Sep 17 00:00:00 2001
From: Claggy3 <stephen.maclagan@hotmail.com>
Date: Sat, 11 Feb 2017 14:00:30 +0000
-Subject: [PATCH 028/703] Update vfpmodule.c
+Subject: [PATCH 028/725] 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
-From c7e79d0b9906e274e220f568ed49e5f00ee5187f Mon Sep 17 00:00:00 2001
+From 97549c7735e937cafdbeff241c9aac738fa560ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
Date: Tue, 1 Nov 2016 15:15:41 +0100
-Subject: [PATCH 029/703] i2c: bcm2835: Add debug support
+Subject: [PATCH 029/725] i2c: bcm2835: Add debug support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 72ed3b77a672a8a94dab5d08739fac5b4df488d2 Mon Sep 17 00:00:00 2001
+From 41dda0f0591a3b2e73439a3af562ac937927dd15 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Thu, 18 Dec 2014 16:07:15 -0800
-Subject: [PATCH 030/703] mm: Remove the PFN busy warning
+Subject: [PATCH 030/725] mm: Remove the PFN busy warning
See commit dae803e165a11bc88ca8dbc07a11077caf97bbcb -- the warning is
expected sometimes when using CMA. However, that commit still spams
-From 14e894cf24f588a4066b171b846934ebe44afc5d Mon Sep 17 00:00:00 2001
+From 9d9d7ba0d4296bb2b0270a1e5dfbc8a3eb7cf192 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Thu, 23 Mar 2017 10:06:56 +0000
-Subject: [PATCH 031/703] ASoC: Add prompt for ICS43432 codec
+Subject: [PATCH 031/725] 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
-From a580882d64f92ec0b025f6ddcfcea985412eb430 Mon Sep 17 00:00:00 2001
+From 1c14a9ccc7c3b57c55374295a4a7a9a80090b095 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 23 Jan 2018 16:52:45 +0000
-Subject: [PATCH 032/703] irqchip: irq-bcm2836: Remove regmap and syscon use
+Subject: [PATCH 032/725] irqchip: irq-bcm2836: Remove regmap and syscon use
The syscon node defines a register range that duplicates that used by
the local_intc node on bcm2836/7. Since irq-bcm2835 and irq-bcm2836 are
-From a3d3dea9ca36f4f5adbf741f36b06ce05b70c2bb Mon Sep 17 00:00:00 2001
+From 37be14f62e3545c46cd86a11ba68cc036f34c638 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 17 Oct 2017 15:04:29 +0100
-Subject: [PATCH 033/703] lan78xx: Enable LEDs and auto-negotiation
+Subject: [PATCH 033/725] lan78xx: Enable LEDs and auto-negotiation
For applications of the LAN78xx that don't have valid programmed
EEPROMs or OTPs, enabling both LEDs and auto-negotiation by default
-From 3ff31acbe9b371f1b9247cc50e7751eaf98b4cef Mon Sep 17 00:00:00 2001
+From 00a9f57a05b9f62c1c8b44479b6e700958ef1400 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 23 Feb 2016 17:26:48 +0000
-Subject: [PATCH 034/703] amba_pl011: Don't use DT aliases for numbering
+Subject: [PATCH 034/725] amba_pl011: Don't use DT aliases for numbering
The pl011 driver looks for DT aliases of the form "serial<n>",
and if found uses <n> as the device ID. This can cause
-From 5f626b06eb9efa01ca364a60378b3998d12e2f99 Mon Sep 17 00:00:00 2001
+From f6c9045d3e326e9b3f6c5d93fe09f517443d9075 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Wed, 1 Mar 2017 16:07:39 +0000
-Subject: [PATCH 035/703] amba_pl011: Round input clock up
+Subject: [PATCH 035/725] 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
-From 0ebd5e2c627c3c41a1081f6c1b7e7caa13e5b12e Mon Sep 17 00:00:00 2001
+From 95ea844e0a7addac38e0385f5ab4215921e1c86b Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Fri, 29 Sep 2017 10:32:19 +0100
-Subject: [PATCH 036/703] amba_pl011: Insert mb() for correct FIFO handling
+Subject: [PATCH 036/725] amba_pl011: Insert mb() for correct FIFO handling
The pl011 register accessor functions use the _relaxed versions of the
standard readl() and writel() functions, meaning that there are no
-From 9106531665bc17788096fcbc00dac3dd8a4ba2e8 Mon Sep 17 00:00:00 2001
+From 92cd7f1608ffea6325748373f9464a035743c3c3 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Fri, 29 Sep 2017 10:32:19 +0100
-Subject: [PATCH 037/703] amba_pl011: Add cts-event-workaround DT property
+Subject: [PATCH 037/725] amba_pl011: Add cts-event-workaround DT property
The BCM2835 PL011 implementation seems to have a bug that can lead to a
transmission lockup if CTS changes frequently. A workaround was added to
-From d52da4747de6ca008f86a73fbf153526c164c0ee Mon Sep 17 00:00:00 2001
+From af8d6777f0c606b8c6a472651e4d00c595db8cdf Mon Sep 17 00:00:00 2001
From: notro <notro@tronnes.org>
Date: Thu, 10 Jul 2014 13:59:47 +0200
-Subject: [PATCH 038/703] pinctrl-bcm2835: Set base to 0 give expected gpio
+Subject: [PATCH 038/725] pinctrl-bcm2835: Set base to 0 give expected gpio
numbering
Signed-off-by: Noralf Tronnes <notro@tronnes.org>
-From 712b8ef1f284c70fc5612894c1a793c7d6b96eae Mon Sep 17 00:00:00 2001
+From f395eddcb1dad5b6b2905efa3ccb3916f91cadb9 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Sun, 12 May 2013 12:24:19 +0100
-Subject: [PATCH 039/703] Main bcm2708/bcm2709 linux port
+Subject: [PATCH 039/725] Main bcm2708/bcm2709 linux port
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 21ea0e6ad04f26557d5d707f2848c576534d2fa0 Mon Sep 17 00:00:00 2001
+From 7d7d160ca73faa35ab961ce201194ea6c419e9af Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 1 May 2013 19:46:17 +0100
-Subject: [PATCH 040/703] Add dwc_otg driver
+Subject: [PATCH 040/725] Add dwc_otg driver
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From a79eeea4c9cecd4770ee03ba8444c01cea34b3c1 Mon Sep 17 00:00:00 2001
+From 051c5a36a676f82455f356ef42279814992fca50 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 17 Jun 2015 17:06:34 +0100
-Subject: [PATCH 041/703] bcm2708 framebuffer driver
+Subject: [PATCH 041/725] bcm2708 framebuffer driver
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From a1e59cb06aaa97771f2d39777017f8de6f237507 Mon Sep 17 00:00:00 2001
+From d73294bd1cceb3b51801d136b3ba8b38d3d23b59 Mon Sep 17 00:00:00 2001
From: Harm Hanemaaijer <fgenfb@yahoo.com>
Date: Thu, 20 Jun 2013 20:21:39 +0200
-Subject: [PATCH 042/703] Speed up console framebuffer imageblit function
+Subject: [PATCH 042/725] 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
-From 3b7f7192307a3cc84215a42c42065758dd638986 Mon Sep 17 00:00:00 2001
+From 4a615d508ab20ee974c7f787739157ad86fcd410 Mon Sep 17 00:00:00 2001
From: Florian Meier <florian.meier@koalo.de>
Date: Fri, 22 Nov 2013 14:22:53 +0100
-Subject: [PATCH 043/703] dmaengine: Add support for BCM2708
+Subject: [PATCH 043/725] dmaengine: Add support for BCM2708
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From c34520567bf3dbca64cb871dacab7230c61726f6 Mon Sep 17 00:00:00 2001
+From b780980e2f381fd19c8d42af07d3d0b8aac3a8e2 Mon Sep 17 00:00:00 2001
From: gellert <gellert@raspberrypi.org>
Date: Fri, 15 Aug 2014 16:35:06 +0100
-Subject: [PATCH 044/703] MMC: added alternative MMC driver
+Subject: [PATCH 044/725] MMC: added alternative MMC driver
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 878b9058f3939881f570d84e8584f5ff9f79a847 Mon Sep 17 00:00:00 2001
+From d09bc280308712a775258a4ddf6198ba0d3bcfd5 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Wed, 25 Mar 2015 17:49:47 +0000
-Subject: [PATCH 045/703] Adding bcm2835-sdhost driver, and an overlay to
+Subject: [PATCH 045/725] Adding bcm2835-sdhost driver, and an overlay to
enable it
BCM2835 has two SD card interfaces. This driver uses the other one.
-From 93e55dab09f9790d4cb547a9ac0a3c4803e682db Mon Sep 17 00:00:00 2001
+From 754aa63cbba18514970ea307d54fdfe4eb7072ea Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Fri, 28 Oct 2016 15:36:43 +0100
-Subject: [PATCH 046/703] vc_mem: Add vc_mem driver for querying firmware
+Subject: [PATCH 046/725] vc_mem: Add vc_mem driver for querying firmware
memory addresses
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
-From 949b8ddbdd7d0865f71b93cc3774b738f229062a Mon Sep 17 00:00:00 2001
+From 42afc949534ce6402c3e2e13d7c939af45573376 Mon Sep 17 00:00:00 2001
From: Tim Gover <tgover@broadcom.com>
Date: Tue, 22 Jul 2014 15:41:04 +0100
-Subject: [PATCH 047/703] vcsm: VideoCore shared memory service for BCM2835
+Subject: [PATCH 047/725] vcsm: VideoCore shared memory service for BCM2835
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 1a2c16ef68cbba94eee5d916e77269bca572830d Mon Sep 17 00:00:00 2001
+From 66a15ff847fb92d85deb19e694d999ad5d806401 Mon Sep 17 00:00:00 2001
From: Luke Wren <luke@raspberrypi.org>
Date: Fri, 21 Aug 2015 23:14:48 +0100
-Subject: [PATCH 048/703] Add /dev/gpiomem device for rootless user GPIO access
+Subject: [PATCH 048/725] Add /dev/gpiomem device for rootless user GPIO access
Signed-off-by: Luke Wren <luke@raspberrypi.org>
-From edaa95330a802b1bcc26cfcd90404ebadd82965b Mon Sep 17 00:00:00 2001
+From dfb42085ee75db965bffe304287bea68b93b4b39 Mon Sep 17 00:00:00 2001
From: Luke Wren <wren6991@gmail.com>
Date: Sat, 5 Sep 2015 01:14:45 +0100
-Subject: [PATCH 049/703] Add SMI driver
+Subject: [PATCH 049/725] Add SMI driver
Signed-off-by: Luke Wren <wren6991@gmail.com>
---
-From 1216c1cccdd7e1eafd6859c9522cdef5c2e4ac8d Mon Sep 17 00:00:00 2001
+From f468b36a6b998cf9848bfcc24370cf13b2730b93 Mon Sep 17 00:00:00 2001
From: Martin Sperl <kernel@martin.sperl.org>
Date: Tue, 26 Apr 2016 14:59:21 +0000
-Subject: [PATCH 050/703] MISC: bcm2835: smi: use clock manager and fix reload
+Subject: [PATCH 050/725] MISC: bcm2835: smi: use clock manager and fix reload
issues
Use clock manager instead of self-made clockmanager.
-From a3f0263e2d5deb675dfe7fb0c31167e86d762e27 Mon Sep 17 00:00:00 2001
+From 680df120e2054ce209e24415795a972bf76826b3 Mon Sep 17 00:00:00 2001
From: Luke Wren <wren6991@gmail.com>
Date: Sat, 5 Sep 2015 01:16:10 +0100
-Subject: [PATCH 051/703] Add SMI NAND driver
+Subject: [PATCH 051/725] Add SMI NAND driver
Signed-off-by: Luke Wren <wren6991@gmail.com>
---
-From 6ae7a56fdff2578805c6f17f03b5bc1b1f9d45a8 Mon Sep 17 00:00:00 2001
+From 7e52446393c3cc4200fa08dcfd1ea555d77c7068 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 3 Jul 2013 00:49:20 +0100
-Subject: [PATCH 052/703] Add cpufreq driver
+Subject: [PATCH 052/725] Add cpufreq driver
Signed-off-by: popcornmix <popcornmix@gmail.com>
-From 3ae115e0812cdaaa3404c84354f40f1e1402fadf Mon Sep 17 00:00:00 2001
+From 92480253067c3534b16f4827f075f5590120b046 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 17 Jun 2015 15:44:08 +0100
-Subject: [PATCH 053/703] Add Chris Boot's i2c driver
+Subject: [PATCH 053/725] Add Chris Boot's i2c driver
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 9fc71e9f5ee71c3f91b43c8c94a0db17349b938c Mon Sep 17 00:00:00 2001
+From a9c2c59a13c9138494b3adb1ce918def9825c376 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
Date: Fri, 26 Jun 2015 14:27:06 +0200
-Subject: [PATCH 054/703] char: broadcom: Add vcio module
+Subject: [PATCH 054/725] char: broadcom: Add vcio module
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 2df6434c1ff682a80f65bde7a9e026f4e0d20df1 Mon Sep 17 00:00:00 2001
+From c31f46a51f80fe435de05dc07859291d3540c096 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
Date: Fri, 26 Jun 2015 14:25:01 +0200
-Subject: [PATCH 055/703] firmware: bcm2835: Support ARCH_BCM270x
+Subject: [PATCH 055/725] firmware: bcm2835: Support ARCH_BCM270x
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From bce7a71e1f399b6dcea8a145cc5fff4653450c50 Mon Sep 17 00:00:00 2001
+From 429e2d968172360c0b7a443229503158910abb92 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 11 May 2015 09:00:42 +0100
-Subject: [PATCH 056/703] scripts: Add mkknlimg and knlinfo scripts from tools
+Subject: [PATCH 056/725] scripts: Add mkknlimg and knlinfo scripts from tools
repo
The Raspberry Pi firmware looks for a trailer on the kernel image to
-From ef38e1a2b9c83fb10ac6fffdfa26da71776a3abb Mon Sep 17 00:00:00 2001
+From 2b8bc69a15a59b93330d37fb8629ae113231a0fb Mon Sep 17 00:00:00 2001
From: notro <notro@tronnes.org>
Date: Wed, 9 Jul 2014 14:46:08 +0200
-Subject: [PATCH 057/703] BCM2708: Add core Device Tree support
+Subject: [PATCH 057/725] BCM2708: Add core Device Tree support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 28644cb31e076ccc6645c692a7ff43414230f361 Mon Sep 17 00:00:00 2001
+From ed4300c1a1c2432efd902454146e2ca909b23192 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Fri, 6 Feb 2015 13:50:57 +0000
-Subject: [PATCH 058/703] BCM270x_DT: Add pwr_led, and the required "input"
+Subject: [PATCH 058/725] BCM270x_DT: Add pwr_led, and the required "input"
trigger
The "input" trigger makes the associated GPIO an input. This is to support
-From cdec439b6dd76c5e1ccbe49636882067971abd0d Mon Sep 17 00:00:00 2001
+From 4f3938a0decb1d939978df44ac060deaa886b7c1 Mon Sep 17 00:00:00 2001
From: Siarhei Siamashka <siarhei.siamashka@gmail.com>
Date: Mon, 17 Jun 2013 13:32:11 +0300
-Subject: [PATCH 059/703] fbdev: add FBIOCOPYAREA ioctl
+Subject: [PATCH 059/725] fbdev: add FBIOCOPYAREA ioctl
Based on the patch authored by Ali Gholami Rudi at
https://lkml.org/lkml/2009/7/13/153
-From 4052b5ba9b502747a6326b43e7f1437be36843b7 Mon Sep 17 00:00:00 2001
+From e408564fff425286f3acf9f625aa763d5cb8408b Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 3 Jul 2013 00:54:08 +0100
-Subject: [PATCH 060/703] Added Device IDs for August DVB-T 205
+Subject: [PATCH 060/725] Added Device IDs for August DVB-T 205
---
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 4 ++++
-From adc948965c7c2c52df7c93acffe5bd1d71dce462 Mon Sep 17 00:00:00 2001
+From e04d6501cf52bc69d75adef77482d6f6b027032d Mon Sep 17 00:00:00 2001
From: Gordon Hollingworth <gordon@raspberrypi.org>
Date: Tue, 12 May 2015 14:47:56 +0100
-Subject: [PATCH 061/703] rpi-ft5406: Add touchscreen driver for pi LCD display
+Subject: [PATCH 061/725] 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
-From e182f20d9faf1853dde2ab827a228011fa1dbc80 Mon Sep 17 00:00:00 2001
+From 4db2d4944e658ce809e6366a3a1338d0c2939231 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 28 Nov 2016 16:50:04 +0000
-Subject: [PATCH 062/703] Improve __copy_to_user and __copy_from_user
+Subject: [PATCH 062/725] Improve __copy_to_user and __copy_from_user
performance
Provide a __copy_from_user that uses memcpy. On BCM2708, use
-From 985bdee303c68ce16a6ad0b0e317c86b9669ab1a Mon Sep 17 00:00:00 2001
+From 799527e3596ebb96f5df8174818c193a8ca68781 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Thu, 25 Jun 2015 12:16:11 +0100
-Subject: [PATCH 063/703] gpio-poweroff: Allow it to work on Raspberry Pi
+Subject: [PATCH 063/725] 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
-From cc60f52641f8debefb1c37b59379ccdc84e1938f Mon Sep 17 00:00:00 2001
+From 8d80ce248d128b583244b0b00ce89ffa39598fe7 Mon Sep 17 00:00:00 2001
From: Phil Elwell <pelwell@users.noreply.github.com>
Date: Tue, 14 Jul 2015 14:32:47 +0100
-Subject: [PATCH 064/703] mfd: Add Raspberry Pi Sense HAT core driver
+Subject: [PATCH 064/725] mfd: Add Raspberry Pi Sense HAT core driver
---
drivers/input/joystick/Kconfig | 8 +
-From 099cc7ff40bca5c9203100aaca2ab69bc7b669ac Mon Sep 17 00:00:00 2001
+From b63482e725f4dd2c6adcda4878e5eadac238f05b Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Thu, 22 Feb 2018 11:55:06 +0100
-Subject: [PATCH 065/703] ASoC: pcm512x: implement set_tdm_slot interface
+Subject: [PATCH 065/725] ASoC: pcm512x: implement set_tdm_slot interface
PCM512x can accept data padded with additional BCLK cycles
but the driver currently lacks an interface to configure this.
-From 2112d06f09c1ecd601de065351bc60b08fc53bca Mon Sep 17 00:00:00 2001
+From 5a5287ced8232a84e624c198b4595684134ff8f7 Mon Sep 17 00:00:00 2001
From: Florian Meier <florian.meier@koalo.de>
Date: Mon, 25 Jan 2016 15:48:59 +0000
-Subject: [PATCH 066/703] ASoC: Add support for Rpi-DAC
+Subject: [PATCH 066/725] ASoC: Add support for Rpi-DAC
---
sound/soc/codecs/Kconfig | 5 +++
-From c8aa8a71618c103d09ae7fa05d5f65c111581194 Mon Sep 17 00:00:00 2001
+From 6cea04a434dfd4f3fbf02fdb5652d50a24586b18 Mon Sep 17 00:00:00 2001
From: Gordon Garrity <gordon@iqaudio.com>
Date: Sat, 8 Mar 2014 16:56:57 +0000
-Subject: [PATCH 067/703] Add IQaudIO Sound Card support for Raspberry Pi
+Subject: [PATCH 067/725] Add IQaudIO Sound Card support for Raspberry Pi
Set a limit of 0dB on Digital Volume Control
-From c383086fd519fcf61f3c5a35e937685f6f34832e Mon Sep 17 00:00:00 2001
+From 015277e926834c77787f4b6b15871f72e7b22d47 Mon Sep 17 00:00:00 2001
From: Daniel Matuschek <info@crazy-audio.com>
Date: Mon, 4 Aug 2014 10:06:56 +0200
-Subject: [PATCH 068/703] Added support for HiFiBerry DAC+
+Subject: [PATCH 068/725] 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.
-From 32df84e8c6f0f747c1182774fadbf4e9ef1794e2 Mon Sep 17 00:00:00 2001
+From 87a94fcef688251a514e9fa209a8c4ff63cdee73 Mon Sep 17 00:00:00 2001
From: Daniel Matuschek <info@crazy-audio.com>
Date: Mon, 4 Aug 2014 11:09:58 +0200
-Subject: [PATCH 069/703] Added driver for HiFiBerry Amp amplifier add-on board
+Subject: [PATCH 069/725] 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.
-From 0a8842f908f015bd889e3c0cee5115db1c451990 Mon Sep 17 00:00:00 2001
+From 931b6e6c23f08ac08c5542ae2fae4ae6ab6eeec1 Mon Sep 17 00:00:00 2001
From: Waldemar Brodkorb <wbrodkorb@conet.de>
Date: Wed, 25 Mar 2015 09:26:17 +0100
-Subject: [PATCH 070/703] Add driver for rpi-proto
+Subject: [PATCH 070/725] 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
-From 71cd216db9c7c05f05c8dd7c7afdfb24f718be74 Mon Sep 17 00:00:00 2001
+From dc3e8f3e1d03f43d2af2709b6d5f09d72ef8d47e Mon Sep 17 00:00:00 2001
From: Aaron Shaw <shawaj@gmail.com>
Date: Thu, 7 Apr 2016 21:26:21 +0100
-Subject: [PATCH 071/703] Add Support for JustBoom Audio boards
+Subject: [PATCH 071/725] Add Support for JustBoom Audio boards
justboom-dac: Adjust for ALSA API change
-From 075e259919f36828473a97a231cdafcec073b63b Mon Sep 17 00:00:00 2001
+From 7a3906eb4db44354f2a3f7a330c1648964e51681 Mon Sep 17 00:00:00 2001
From: Matt Flax <flatmax@flatmax.org>
Date: Mon, 16 May 2016 21:36:31 +1000
-Subject: [PATCH 072/703] New AudioInjector.net Pi soundcard with low jitter
+Subject: [PATCH 072/725] 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.
-From 3f5b5702b2245c639439607ab4e64d654edaa864 Mon Sep 17 00:00:00 2001
+From c2c45a480f012a6d939f39470e9d3a5e689b8b03 Mon Sep 17 00:00:00 2001
From: escalator2015 <jmtasende@gmail.com>
Date: Tue, 24 May 2016 16:20:09 +0100
-Subject: [PATCH 073/703] New driver for RRA DigiDAC1 soundcard using WM8741 +
+Subject: [PATCH 073/725] New driver for RRA DigiDAC1 soundcard using WM8741 +
WM8804
---
-From 63f29d95488d5bbebc704f904e3f4d12ba90fe42 Mon Sep 17 00:00:00 2001
+From 54fc10a745ca32f55c504e6b08238da56ec3fa83 Mon Sep 17 00:00:00 2001
From: DigitalDreamtime <clive.messer@digitaldreamtime.co.uk>
Date: Sat, 2 Jul 2016 16:26:19 +0100
-Subject: [PATCH 074/703] Add support for Dion Audio LOCO DAC-AMP HAT
+Subject: [PATCH 074/725] Add support for Dion Audio LOCO DAC-AMP HAT
Using dedicated machine driver and pcm5102a codec driver.
-From befd64b81a740cba0ad23a6732dd56b2e67dda84 Mon Sep 17 00:00:00 2001
+From 45f28f47c5b4a3fabf33304c3660496da0b9dbcd Mon Sep 17 00:00:00 2001
From: Clive Messer <clive.m.messer@gmail.com>
Date: Mon, 19 Sep 2016 14:01:04 +0100
-Subject: [PATCH 075/703] Allo Piano DAC boards: Initial 2 channel (stereo)
+Subject: [PATCH 075/725] 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,
-From 9a43360b6f8d6073b0bd67077229fe1d63076733 Mon Sep 17 00:00:00 2001
+From 9659dfa0a5626b730b3b72431204ce541392e9f7 Mon Sep 17 00:00:00 2001
From: Raashid Muhammed <raashidmuhammed@zilogic.com>
Date: Mon, 27 Mar 2017 12:35:00 +0530
-Subject: [PATCH 076/703] Add support for Allo Piano DAC 2.1 plus add-on board
+Subject: [PATCH 076/725] 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.
-From f9b56b66913621c3ecba0a5379381fd1e33e1914 Mon Sep 17 00:00:00 2001
+From 337c790ae688ad33941262b852a1ab88c3a9960b Mon Sep 17 00:00:00 2001
From: BabuSubashChandar <babuenir@gmail.com>
Date: Tue, 28 Mar 2017 20:04:42 +0530
-Subject: [PATCH 077/703] Add support for Allo Boss DAC add-on board for
+Subject: [PATCH 077/725] Add support for Allo Boss DAC add-on board for
Raspberry Pi. (#1924)
Signed-off-by: Baswaraj K <jaikumar@cem-solutions.net>
-From 1b7248a956f0322a9b39d13cdddf83a7c0524ae9 Mon Sep 17 00:00:00 2001
+From 225c4a483b34eb88cab2d617a961fef9cb5a876e Mon Sep 17 00:00:00 2001
From: gtrainavicius <gtrainavicius@users.noreply.github.com>
Date: Sun, 23 Oct 2016 12:06:53 +0300
-Subject: [PATCH 078/703] Support for Blokas Labs pisound board
+Subject: [PATCH 078/725] Support for Blokas Labs pisound board
Pisound dynamic overlay (#1760)
-From 9dea6c4e76e3bace9cbc62fd452de72ce0362034 Mon Sep 17 00:00:00 2001
+From 8341fbb96fa8a6802b316530d00799e2eeaf2962 Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Sun, 22 Jan 2017 12:49:37 +0100
-Subject: [PATCH 079/703] ASoC: Add driver for Cirrus Logic Audio Card
+Subject: [PATCH 079/725] 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
-From 3e2070202a0607fe572f565ed4c18aa964fc18e5 Mon Sep 17 00:00:00 2001
+From 261e3e2577768d848277489e26759f3f37b25aae Mon Sep 17 00:00:00 2001
From: Miquel <miquelblauw@hotmail.com>
Date: Fri, 24 Feb 2017 20:51:06 +0100
-Subject: [PATCH 080/703] sound: Support for Dion Audio LOCO-V2 DAC-AMP HAT
+Subject: [PATCH 080/725] sound: Support for Dion Audio LOCO-V2 DAC-AMP HAT
Signed-off-by: Miquel Blauw <info@dionaudio.nl>
-From 0719be99171119689b89d117141b65e849a49239 Mon Sep 17 00:00:00 2001
+From 132ffc095977fbd3e3b4099deaba2b80ed4d13ed Mon Sep 17 00:00:00 2001
From: Fe-Pi <fe-pi@cox.net>
Date: Wed, 1 Mar 2017 04:42:43 -0700
-Subject: [PATCH 081/703] Add support for Fe-Pi audio sound card. (#1867)
+Subject: [PATCH 081/725] 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.
-From e95def09872db37a8e577da0882a113f68476af4 Mon Sep 17 00:00:00 2001
+From 3c3d9b8ffa1f47da2225262dc2bac5decc043f6d Mon Sep 17 00:00:00 2001
From: Matt Flax <flatmax@flatmax.org>
Date: Wed, 8 Mar 2017 20:04:13 +1100
-Subject: [PATCH 082/703] Add support for the AudioInjector.net Octo sound card
+Subject: [PATCH 082/725] Add support for the AudioInjector.net Octo sound card
AudioInjector Octo: sample rates, regulators, reset
-From 7a03cd841be6b35ae99b7a4a1b415786df98da88 Mon Sep 17 00:00:00 2001
+From 18914c73280bbb74c77f7d5fef622e26ea4e4ffc Mon Sep 17 00:00:00 2001
From: Peter Malkin <petermalkin@google.com>
Date: Mon, 27 Mar 2017 16:38:21 -0700
-Subject: [PATCH 083/703] Driver support for Google voiceHAT soundcard.
+Subject: [PATCH 083/725] Driver support for Google voiceHAT soundcard.
ASoC: googlevoicehat-codec: Use correct device when grabbing GPIO
-From b64cde33b275ddda0e024a218cd31456a54cdd09 Mon Sep 17 00:00:00 2001
+From 414559d38e5fb6fe74e8a54a2b9de22f6d238a05 Mon Sep 17 00:00:00 2001
From: allocom <sparky-dev@allo.com>
Date: Thu, 19 Apr 2018 12:12:26 +0530
-Subject: [PATCH 084/703] Driver and overlay for Allo Katana DAC
+Subject: [PATCH 084/725] Driver and overlay for Allo Katana DAC
Allo Katana DAC: Updated default values
-From 567ae821d7e3e4bcca95ac69847f23e9b4929570 Mon Sep 17 00:00:00 2001
+From 0d0387de52b82694b9df90476e21e6828025d1e9 Mon Sep 17 00:00:00 2001
From: Daniel Matuschek <info@crazy-audio.com>
Date: Wed, 15 Jan 2014 21:41:23 +0100
-Subject: [PATCH 085/703] ASoC: wm8804: MCLK configuration options, 32-bit
+Subject: [PATCH 085/725] ASoC: wm8804: MCLK configuration options, 32-bit
WM8804 can run with PLL frequencies of 256xfs and 128xfs for most sample
rates. At 192kHz only 128xfs is supported. The existing driver selects
-From fb0eaa75f3a486dd0a5cb126c198db047a768a5d Mon Sep 17 00:00:00 2001
+From 49d8b4eebd733c26bdd95f44352c0344af5b4472 Mon Sep 17 00:00:00 2001
From: Tim Gover <tim.gover@raspberrypi.org>
Date: Wed, 27 Jun 2018 15:59:12 +0100
-Subject: [PATCH 086/703] ASoC: Add generic RPI driver for simple soundcards.
+Subject: [PATCH 086/725] ASoC: Add generic RPI driver for simple soundcards.
The RPI simple sound card driver provides a generic ALSA SOC card driver
supporting a variety of Pi HAT soundcards. The intention is to avoid
-From c95f1fca6bf35548cddf4909a505a6427f6f41ef Mon Sep 17 00:00:00 2001
+From 3f31d54804aebb748f200841dafdc8ff1f05b7a7 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 3 Sep 2018 17:00:36 +0100
-Subject: [PATCH 087/703] ASoC: Add Kconfig and Makefile for sound/soc/bcm
+Subject: [PATCH 087/725] ASoC: Add Kconfig and Makefile for sound/soc/bcm
Signed-off-by: popcornmix <popcornmix@gmail.com>
---
-From 1fb18379184ab1c039cc7b366901f3816f2ab768 Mon Sep 17 00:00:00 2001
+From 5b797e80e454e59af7381b579305cc25f70871d8 Mon Sep 17 00:00:00 2001
From: Tim Gover <tim.gover@raspberrypi.org>
Date: Sat, 21 Jul 2018 20:07:46 +0100
-Subject: [PATCH 088/703] ASoC: Create a generic Pi Hat WM8804 driver
+Subject: [PATCH 088/725] ASoC: Create a generic Pi Hat WM8804 driver
Reduce the amount of duplicated code by creating a generic driver for
Pi Hat digi cards using the WM8804 codec.
-From 7a0c9202a0bd363d49ba0b4a31d843f3a2cac66d Mon Sep 17 00:00:00 2001
+From a9adc2921cd7b460c25c4149374c7e94675d04fc Mon Sep 17 00:00:00 2001
From: P33M <P33M@github.com>
Date: Wed, 21 Oct 2015 14:55:21 +0100
-Subject: [PATCH 089/703] rpi_display: add backlight driver and overlay
+Subject: [PATCH 089/725] 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
-From ae7c0b0955e96a7231ad4b6d909124fa7f7713e8 Mon Sep 17 00:00:00 2001
+From 2839c328b46a97314f6f9cfb5cd0c1be9bc174f3 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 23 Feb 2016 19:56:04 +0000
-Subject: [PATCH 090/703] bcm2835-virtgpio: Virtual GPIO driver
+Subject: [PATCH 090/725] bcm2835-virtgpio: Virtual GPIO driver
Add a virtual GPIO driver that uses the firmware mailbox interface to
request that the VPU toggles LEDs.
-From 004fa06eecc1162dcb717bdce943a08c25c0922c Mon Sep 17 00:00:00 2001
+From de205caf53ef335d29f3d68f18f7bf996d1e0728 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 3 Sep 2012 17:10:23 +0100
-Subject: [PATCH 091/703] net: Add non-mainline source for rtl8192cu wlan
+Subject: [PATCH 091/725] net: Add non-mainline source for rtl8192cu wlan
We are now syncing with version from:
https://github.com/pvaret/rtl8192cu-fixes
-From 1889a5e0d20a7f58b95cb41c682bf1a09a37d4f6 Mon Sep 17 00:00:00 2001
+From 40d6d85f902e7de4721db52394da172d3d5f2724 Mon Sep 17 00:00:00 2001
From: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Date: Wed, 3 Dec 2014 13:23:28 +0200
-Subject: [PATCH 092/703] OF: DT-Overlay configfs interface
+Subject: [PATCH 092/725] 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.
-From fe1028f8aa31decab2a006c977598bd75eb42b40 Mon Sep 17 00:00:00 2001
+From 7f688c61d8a1f881e58ae32af51506141a64b1e2 Mon Sep 17 00:00:00 2001
From: Cheong2K <cheong@redbear.cc>
Date: Fri, 26 Feb 2016 18:20:10 +0800
-Subject: [PATCH 093/703] brcm: adds support for BCM43341 wifi
+Subject: [PATCH 093/725] brcm: adds support for BCM43341 wifi
brcmfmac: Disable power management
-From 06ec5a8827bec5fc4b7f2b322088c47963a782e4 Mon Sep 17 00:00:00 2001
+From 99150b44461c1b5a988297cab7f0188a291afec9 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Fri, 17 Feb 2017 15:26:13 +0000
-Subject: [PATCH 094/703] brcmfmac: Mute expected startup 'errors'
+Subject: [PATCH 094/725] brcmfmac: Mute expected startup 'errors'
The brcmfmac WiFi driver always complains about the '00' country code.
Modify the driver to ignore '00' silently.
-From 04398740be915fbbbc794b3b34aa36d11a85a0ab Mon Sep 17 00:00:00 2001
+From bddfcc074a6f46d2d107d5c6b06c5b6c906bbe19 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Thu, 17 Dec 2015 13:37:07 +0000
-Subject: [PATCH 095/703] hci_h5: Don't send conf_req when ACTIVE
+Subject: [PATCH 095/725] 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.
-From 0c0a0d6d576db08b15281aa7263ebb4f26344d9f Mon Sep 17 00:00:00 2001
+From 97cc0418de0e851cf4a850a99878f8ddf31f8a64 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 13 Apr 2015 17:16:29 +0100
-Subject: [PATCH 096/703] config: Add default configs
+Subject: [PATCH 096/725] config: Add default configs
---
arch/arm/configs/bcm2709_defconfig | 1360 ++++++++++++++++++++++++++++
-From 8a3aa5b6a470f7c89025e51d5fc2f2827e8efc00 Mon Sep 17 00:00:00 2001
+From 974e489f199d585ebe57440969ab9661ce2156c9 Mon Sep 17 00:00:00 2001
From: Michael Zoran <mzoran@crowfest.net>
Date: Wed, 24 Aug 2016 03:35:56 -0700
-Subject: [PATCH 097/703] Add arm64 configuration and device tree differences.
+Subject: [PATCH 097/725] Add arm64 configuration and device tree differences.
Disable MMC_BCM2835_SDHOST and MMC_BCM2835 since these drivers are crashing
at the moment.
-From 3d6c0c835d5e1b2983a0e4dec0dc779cd67db922 Mon Sep 17 00:00:00 2001
+From e65d132bca6b87ae1606ef156581f1de76b80962 Mon Sep 17 00:00:00 2001
From: Michael Zoran <mzoran@crowfest.net>
Date: Sat, 14 Jan 2017 21:33:51 -0800
-Subject: [PATCH 098/703] ARM64/DWC_OTG: Port dwc_otg driver to ARM64
+Subject: [PATCH 098/725] 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
-From 67ba0d1572d1ca3874cbe8ebd57f5141178eb55c Mon Sep 17 00:00:00 2001
+From 6b47138814b0e244c65c9d06d08fa9aca67b7904 Mon Sep 17 00:00:00 2001
From: Michael Zoran <mzoran@crowfest.net>
Date: Sat, 14 Jan 2017 21:43:57 -0800
-Subject: [PATCH 099/703] ARM64: Round-Robin dispatch IRQs between CPUs.
+Subject: [PATCH 099/725] 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
-From 303b20724f8691db1c6b575f127d47d5953359f2 Mon Sep 17 00:00:00 2001
+From 89c5a60b701b67a5bb3458fbe99a45da1d718e47 Mon Sep 17 00:00:00 2001
From: Michael Zoran <mzoran@crowfest.net>
Date: Sat, 11 Feb 2017 01:18:31 -0800
-Subject: [PATCH 100/703] ARM64: Force hardware emulation of deprecated
+Subject: [PATCH 100/725] ARM64: Force hardware emulation of deprecated
instructions.
---
-From ab40577b4601c0eeeedb5c3688cf0719b2bc582e Mon Sep 17 00:00:00 2001
+From 0a1ea6126555abaf874f76c7d0c45f8d34b9c7a4 Mon Sep 17 00:00:00 2001
From: Khem Raj <raj.khem@gmail.com>
Date: Fri, 10 Feb 2017 17:57:08 -0800
-Subject: [PATCH 101/703] build/arm64: Add rules for .dtbo files for dts
+Subject: [PATCH 101/725] build/arm64: Add rules for .dtbo files for dts
overlays
We now create overlays as .dtbo files.
-From e8cf1886f2434ec0e5a672d9b94a96f7fea80789 Mon Sep 17 00:00:00 2001
+From 007008145da2e877e32090a4861440f56bc40080 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Fri, 25 Aug 2017 19:18:13 +0100
-Subject: [PATCH 102/703] cache: export clean and invalidate
+Subject: [PATCH 102/725] cache: export clean and invalidate
---
arch/arm/mm/cache-v6.S | 4 ++--
-From 93664cd3cee57e93c1d354c3263773a6b832db22 Mon Sep 17 00:00:00 2001
+From a7a7bff51039648f4d09d690bb037d02b26e593c Mon Sep 17 00:00:00 2001
From: James Hughes <JamesH65@users.noreply.github.com>
Date: Tue, 14 Nov 2017 15:13:15 +0000
-Subject: [PATCH 103/703] AXI performance monitor driver (#2222)
+Subject: [PATCH 103/725] AXI performance monitor driver (#2222)
Uses the debugfs I/F to provide access to the AXI
bus performance monitors.
-From a3ba7e3519d3dce17a0224b552fb88b7728f7061 Mon Sep 17 00:00:00 2001
+From 8ad27448ac0130fe78dbe1eaa1ce2d640669fb05 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 14 Nov 2017 11:03:22 +0000
-Subject: [PATCH 104/703] mcp2515: Use DT-supplied interrupt flags
+Subject: [PATCH 104/725] mcp2515: Use DT-supplied interrupt flags
The MCP2515 datasheet clearly describes a level-triggered interrupt
pin. Therefore the receiving interrupt controller must also be
-From c391ccaadd8928a79986e67ebc23cd6670b83d85 Mon Sep 17 00:00:00 2001
+From 4d326f3b4817e2a29d4ae69239c1ec2ef4a321a1 Mon Sep 17 00:00:00 2001
From: James Hughes <JamesH65@users.noreply.github.com>
Date: Thu, 16 Nov 2017 15:56:17 +0000
-Subject: [PATCH 105/703] Tidy up of the ft5406 driver to use DT (#2189)
+Subject: [PATCH 105/725] Tidy up of the ft5406 driver to use DT (#2189)
Driver was using a fixed resolution, this commit
adds touchscreen size, and coordinate flip and swap
-From db9b15f3d930b045998c276c68f32645f7bade9f Mon Sep 17 00:00:00 2001
+From 15dc7e960b0de2d10a312e2be3ed6674f440cf61 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 27 Nov 2017 17:14:54 +0000
-Subject: [PATCH 106/703] cgroup: Disable cgroup "memory" by default
+Subject: [PATCH 106/725] cgroup: Disable cgroup "memory" by default
Some Raspberry Pis have limited RAM and most users won't use the
cgroup memory support so it is disabled by default. Enable with:
-From 6ddffcf9c288513943680b958307b3bb267ea939 Mon Sep 17 00:00:00 2001
+From 5f4a7f6cabf2f7fdd75f8dba64394ed3f5c96d09 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
Date: Wed, 3 Jun 2015 12:26:13 +0200
-Subject: [PATCH 107/703] ARM: bcm2835: Set Serial number and Revision
+Subject: [PATCH 107/725] ARM: bcm2835: Set Serial number and Revision
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 84ae50c70c296998d39b819d1d5f3e2e4a355098 Mon Sep 17 00:00:00 2001
+From 83846923572c7b606ba85dfe613e38236e8bd695 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 11 Dec 2017 09:18:32 +0000
-Subject: [PATCH 108/703] ARM: Activate FIQs to avoid __irq_startup warnings
+Subject: [PATCH 108/725] ARM: Activate FIQs to avoid __irq_startup warnings
There is a new test in __irq_startup that the IRQ is activated, which
hasn't been the case for FIQs since they bypass some of the usual setup.
-From 2f7074d8ae9b0867535fcfc56b4332073aee07f7 Mon Sep 17 00:00:00 2001
+From 3d00548e917e42a5d9da031c8dab8a52ff3cd1cc Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 22 Jan 2018 17:26:38 +0000
-Subject: [PATCH 109/703] serial: 8250: bcm2835aux - suppress EPROBE_DEFER
+Subject: [PATCH 109/725] serial: 8250: bcm2835aux - suppress EPROBE_DEFER
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From 48ce2d8a89c63f31a63b636b119a98c3ddbc66e1 Mon Sep 17 00:00:00 2001
+From 46828eb52e1d51dafb26f9073bd2b36dcf18596b Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Wed, 14 Sep 2016 09:16:19 +0100
-Subject: [PATCH 110/703] raspberrypi-firmware: Export the general transaction
+Subject: [PATCH 110/725] raspberrypi-firmware: Export the general transaction
function.
The vc4-firmware-kms module is going to be doing the MBOX FB call.
-From cf4d9b0e5f081408edf3340b3f46171f5b56dbff Mon Sep 17 00:00:00 2001
+From c8ae9b8e203f05c0a87f2576a58dbc6c747527c4 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Wed, 14 Sep 2016 08:39:33 +0100
-Subject: [PATCH 111/703] drm/vc4: Add a mode for using the closed firmware for
+Subject: [PATCH 111/725] drm/vc4: Add a mode for using the closed firmware for
display.
Signed-off-by: Eric Anholt <eric@anholt.net>
-From 9d538f69eca5ed335235fe89ba56966fdf07334d Mon Sep 17 00:00:00 2001
+From f42394aee8bcd3b7159029a4b9c66fcf35b16ba8 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Wed, 1 Feb 2017 17:09:18 -0800
-Subject: [PATCH 112/703] drm/vc4: Name the primary and cursor planes in fkms.
+Subject: [PATCH 112/725] drm/vc4: Name the primary and cursor planes in fkms.
This makes debugging nicer, compared to trying to remember what the
IDs are.
-From 94f9a45df23146c709d7a08191e97ee31d6dd8e9 Mon Sep 17 00:00:00 2001
+From a54d059398df5799cc17789f11d40817f2cca3ed Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Wed, 1 Feb 2017 17:10:09 -0800
-Subject: [PATCH 113/703] drm/vc4: Add DRM_DEBUG_ATOMIC for the insides of
+Subject: [PATCH 113/725] drm/vc4: Add DRM_DEBUG_ATOMIC for the insides of
fkms.
Trying to debug weston on fkms involved figuring out what calls I was
-From 96cfb9903f60e98d964c3547ac0cf5b920083c04 Mon Sep 17 00:00:00 2001
+From d36cddb19f380051aae81cc384fce9b49625798f Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Thu, 2 Feb 2017 09:42:18 -0800
-Subject: [PATCH 114/703] drm/vc4: Fix sending of page flip completion events
+Subject: [PATCH 114/725] 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
-From 9f05f9c3a564cedbb3c5f3dd0d5b95f247b63c71 Mon Sep 17 00:00:00 2001
+From dbf8328dec97e1df1a61ca75e98b8b60e4e2e68e Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Thu, 6 Jul 2017 11:45:48 -0700
-Subject: [PATCH 115/703] drm/vc4: Add support for setting DPMS in firmwarekms.
+Subject: [PATCH 115/725] drm/vc4: Add support for setting DPMS in firmwarekms.
This ensures that the screen goes blank during DPMS (screensaver),
including the cursor. Planes don't necessarily get disabled during
-From ac5599d66654d69497945cb29e183824d9988e29 Mon Sep 17 00:00:00 2001
+From ba6bffb620f0f25868ed7d84add448f771201947 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Wed, 7 Jun 2017 14:39:49 -0700
-Subject: [PATCH 116/703] drm/vc4: Add FB modifier support to firmwarekms.
+Subject: [PATCH 116/725] drm/vc4: Add FB modifier support to firmwarekms.
Signed-off-by: Eric Anholt <eric@anholt.net>
(cherry picked from commit 11752d73488e08aaeb65fe8289a9c016acde26c2)
-From 7815410d46ef8c5462eadbeff59d8c7e43639b03 Mon Sep 17 00:00:00 2001
+From 46652925942d2947afabc11abfdfb5d42d1559d5 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Tue, 30 Jan 2018 14:21:02 -0800
-Subject: [PATCH 117/703] drm/vc4: Add missing enable/disable vblank handlers
+Subject: [PATCH 117/725] drm/vc4: Add missing enable/disable vblank handlers
in fkms.
Fixes hang at boot in 4.14.
-From 7c7cf2b1b7ea7189b18eb042e6a04ca90e07e658 Mon Sep 17 00:00:00 2001
+From e1ce159091e4bc8ce78ed9838d5935534dc40dbe Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 18 Apr 2017 21:43:46 +0100
-Subject: [PATCH 118/703] vc4_fkms: Apply firmware overscan offset to hardware
+Subject: [PATCH 118/725] vc4_fkms: Apply firmware overscan offset to hardware
cursor
---
-From b69ecf0b7259675e57be13836713946f1329f20c Mon Sep 17 00:00:00 2001
+From fd2b049cb8beed1b80e9f314e55116db2d960eef Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Mon, 5 Feb 2018 18:01:02 +0000
-Subject: [PATCH 119/703] drm/vc4: Fix warning about vblank interrupts before
+Subject: [PATCH 119/725] drm/vc4: Fix warning about vblank interrupts before
DRM core is ready.
The SMICS interrupt fires continuously, but since it's 1/100 the rate
-From b77d51293dce1ff08da64c4bb95c13d2cb4c3ee7 Mon Sep 17 00:00:00 2001
+From 2d976e5035d98f5ada75f088a3e16079c8eee99a Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Mon, 5 Feb 2018 18:02:30 +0000
-Subject: [PATCH 120/703] drm/vc4: Skip SET_CURSOR_INFO when the cursor
+Subject: [PATCH 120/725] drm/vc4: Skip SET_CURSOR_INFO when the cursor
contents didn't change.
Signed-off-by: Eric Anholt <eric@anholt.net>
-From be3a851fe4c6f2e91a7d7b0738ad1873074eab43 Mon Sep 17 00:00:00 2001
+From 9c3d03b62cec67df4f3c989a2eceb38c1415fa71 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Mon, 5 Feb 2018 18:22:03 +0000
-Subject: [PATCH 121/703] drm/vc4: Remove duplicate primary/cursor fields from
+Subject: [PATCH 121/725] drm/vc4: Remove duplicate primary/cursor fields from
FKMS driver.
The CRTC has those fields and we can just use them.
-From 0f628b54b7f10997437a0e3f34eea2a0b2827250 Mon Sep 17 00:00:00 2001
+From 9c0ae7d4e7e70bd0b30073f66045a66bfabdb307 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Sun, 17 Jun 2018 13:22:07 +0100
-Subject: [PATCH 122/703] vc4_firmware_kms: fix build
+Subject: [PATCH 122/725] vc4_firmware_kms: fix build
---
drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 ++++--
-From 708821a5d04805bf61b036e869663d8650ca578c Mon Sep 17 00:00:00 2001
+From 48d20770b1aa96c6e3095316f493eab948e68c19 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 20 Feb 2018 20:53:46 +0000
-Subject: [PATCH 123/703] hack: cache: Fix linker error
+Subject: [PATCH 123/725] hack: cache: Fix linker error
---
arch/arm/mm/cache-v7.S | 2 ++
-From ec510c1562ff8326e032a9f0d9ae26ff0e54dd1c Mon Sep 17 00:00:00 2001
+From b6109ee12acbda2c79f7a7a7b76806aebfcd9ed9 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 20 Feb 2018 10:07:27 +0000
-Subject: [PATCH 124/703] i2c-gpio: Also set bus numbers from reg property
+Subject: [PATCH 124/725] i2c-gpio: Also set bus numbers from reg property
I2C busses can be assigned specific bus numbers using aliases in
Device Tree - string properties where the name is the alias and the
-From 943530f05c0bb81679b1413c4a545e4600f61f71 Mon Sep 17 00:00:00 2001
+From 2b43c222f32b1a51a36a7511ea610adb9a51fb2b Mon Sep 17 00:00:00 2001
From: Nathan Chancellor <natechancellor@gmail.com>
Date: Sun, 4 Mar 2018 17:20:25 -0700
-Subject: [PATCH 125/703] sound: bcm: Fix memset dereference warning
+Subject: [PATCH 125/725] sound: bcm: Fix memset dereference warning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From ba23c2430362ba947a69c946b8b7bbe5c2eda914 Mon Sep 17 00:00:00 2001
+From 876356d4be81b4341cbc53a42c8a88dc49d7b56d Mon Sep 17 00:00:00 2001
From: hdoverobinson <hdoverobinson@gmail.com>
Date: Tue, 13 Mar 2018 06:58:39 -0400
-Subject: [PATCH 126/703] added capture_clear option to pps-gpio via dtoverlay
+Subject: [PATCH 126/725] added capture_clear option to pps-gpio via dtoverlay
(#2433)
---
-From 73b2c9d517072023cdc4e8331694b1e62234b09d Mon Sep 17 00:00:00 2001
+From c2da5c5af7a2d872d2b55c818cf9e67e34923a65 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Fri, 9 Mar 2018 12:01:00 +0000
-Subject: [PATCH 127/703] lan78xx: Read initial EEE status from DT
+Subject: [PATCH 127/725] lan78xx: Read initial EEE status from DT
Add two new DT properties:
* microchip,eee-enabled - a boolean to enable EEE
-From e5af3fc88a539cabf03c3e676689282f662d1a08 Mon Sep 17 00:00:00 2001
+From 827f677549361a68c8bed46ae9bc3c6210273ace Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 14 Jul 2014 22:02:09 +0100
-Subject: [PATCH 128/703] hid: Reduce default mouse polling interval to 60Hz
+Subject: [PATCH 128/725] hid: Reduce default mouse polling interval to 60Hz
Reduces overhead when using X
---
-From 4535e6abd37c89a7f21623497b9e656845aad4c0 Mon Sep 17 00:00:00 2001
+From 886c2877fcd6fdbff3c8cdec0e68bbb7570bc8ff Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 24 Apr 2018 14:42:27 +0100
-Subject: [PATCH 129/703] gpiolib: Don't prevent IRQ usage of output GPIOs
+Subject: [PATCH 129/725] gpiolib: Don't prevent IRQ usage of output GPIOs
Upstream Linux deems using output GPIOs to generate IRQs as a bogus
use case, even though the BCM2835 GPIO controller is capable of doing
-From cacdfc573c523a3e7e7e6ed708f459781228ccd1 Mon Sep 17 00:00:00 2001
+From 3e25c39320a501e57a5e232f6e98740357bd5bc6 Mon Sep 17 00:00:00 2001
From: Nick Bulleid <nedbulleid@fastmail.com>
Date: Thu, 10 May 2018 21:57:02 +0100
-Subject: [PATCH 130/703] Add ability to export gpio used by gpio-poweroff
+Subject: [PATCH 130/725] Add ability to export gpio used by gpio-poweroff
Signed-off-by: Nick Bulleid <nedbulleid@fastmail.com>
-From 8e3109c37fc00a087aba08b92da9a416eb2cd37a Mon Sep 17 00:00:00 2001
+From ab5a0cc750eefdabd58b67c2558c46029ceb2a51 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Sat, 12 May 2018 21:35:43 +0100
-Subject: [PATCH 131/703] firmware/raspberrypi: Notify firmware of a reboot
+Subject: [PATCH 131/725] firmware/raspberrypi: Notify firmware of a reboot
Register for reboot notifications, sending RPI_FIRMWARE_NOTIFY_REBOOT
over the mailbox interface on reception.
-From 73a2cd01254c251fe07c1a124b47105c1d1a7730 Mon Sep 17 00:00:00 2001
+From af6f3cf33a864c397f6ab43c0403b0a92797694e Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Thu, 14 Jun 2018 11:21:04 +0100
-Subject: [PATCH 132/703] irqchip: irq-bcm2835: Calc. FIQ_START at boot-time
+Subject: [PATCH 132/725] irqchip: irq-bcm2835: Calc. FIQ_START at boot-time
ad83c7cb2f37 ("irqchip/irq-bcm2836: Add support for DT interrupt polarity")
changed the way that the BCM2836/7 local interrupts are mapped; instead
-From 8d90ea3c51ab934802afe45eba16800f6c620cee Mon Sep 17 00:00:00 2001
+From 3a05e59e7c1866f46df63f0f11c46d3187d3adc9 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Thu, 14 Jun 2018 15:07:26 +0100
-Subject: [PATCH 133/703] of: configfs: Use of_overlay_fdt_apply API call
+Subject: [PATCH 133/725] of: configfs: Use of_overlay_fdt_apply API call
The published API to the dynamic overlay application mechanism now
takes a Flattened Device Tree blob as input so that it can manage the
-From 48c17759c12fead4c4643e895582fb44b9b8ec15 Mon Sep 17 00:00:00 2001
+From aa624ea88f53750c15729e82c0ac380b2b0768ac Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 13 Jun 2018 15:21:10 +0100
-Subject: [PATCH 134/703] net: lan78xx: Disable TCP Segmentation Offload (TSO)
+Subject: [PATCH 134/725] net: lan78xx: Disable TCP Segmentation Offload (TSO)
TSO seems to be having issues when packets are dropped and the
remote end uses Selective Acknowledge (SACK) to denote that
-From 8bb29ed53937d3608e68f75d269d648ca0b22dcf Mon Sep 17 00:00:00 2001
+From 5ef577082ea0d6fb498e5189bd55071aed9696e7 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Wed, 20 Jun 2018 12:20:01 +0100
-Subject: [PATCH 135/703] brcmfmac: Re-enable firmware roaming support
+Subject: [PATCH 135/725] brcmfmac: Re-enable firmware roaming support
As of 4.18, a firmware that implements the update_connect_params
method but doesn't claim to support roaming causes an error. We
-From 16ca74df16214e51080a6102388fbbaaae713c5e Mon Sep 17 00:00:00 2001
+From 95e0c441040464722e1abb50a365224e7bf9058d Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Thu, 5 Apr 2018 14:46:11 +0100
-Subject: [PATCH 136/703] lan78xx: Move enabling of EEE into PHY init code
+Subject: [PATCH 136/725] lan78xx: Move enabling of EEE into PHY init code
Enable EEE mode as soon as possible after connecting to the PHY, and
before phy_start. This avoids a second link negotiation, which speeds
-From 3e89900d7dd7c851400e0afeea326f94bba1cd84 Mon Sep 17 00:00:00 2001
+From 3e9ee1b0f8b5b8ad3fc688e785de479cbde00b5c Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 28 Aug 2018 10:40:40 +0100
-Subject: [PATCH 137/703] staging/vc04_services: Derive g_cache_line_size
+Subject: [PATCH 137/725] staging/vc04_services: Derive g_cache_line_size
The ARM coprocessor registers include dcache line size, but there is no
function to expose this value. Rather than create a new one, use the
-From ae762f7cc705c20c8320613425a7179c3e6f47f3 Mon Sep 17 00:00:00 2001
+From 1c1f26355604567bc11084cb3c4db204d7420941 Mon Sep 17 00:00:00 2001
From: Serge Schneider <serge@raspberrypi.org>
Date: Mon, 9 Jul 2018 12:54:25 +0100
-Subject: [PATCH 138/703] Add rpi-poe-fan driver
+Subject: [PATCH 138/725] Add rpi-poe-fan driver
Signed-off-by: Serge Schneider <serge@raspberrypi.org>
-From 6b7588fb541726ea05baf7f553deafa907263a6e Mon Sep 17 00:00:00 2001
+From f78d450f7ce53a644fae11f359c133fd015cda12 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 17 Sep 2018 17:31:18 +0100
-Subject: [PATCH 139/703] cxd2880: CXD2880_SPI_DRV should select DVB_CXD2880
+Subject: [PATCH 139/725] cxd2880: CXD2880_SPI_DRV should select DVB_CXD2880
with MEDIA_SUBDRV_AUTOSELECT
---
-From 7de09525583f90004ba236345bae3ad3274d23da Mon Sep 17 00:00:00 2001
+From 572ba427304c769cdf4d19d8d93c3d413ad57f72 Mon Sep 17 00:00:00 2001
From: wm4 <wm4@nowhere>
Date: Wed, 13 Jan 2016 19:44:47 +0100
-Subject: [PATCH 140/703] bcm2835: interpolate audio delay
+Subject: [PATCH 140/725] bcm2835: interpolate audio delay
It appears the GPU only sends us a message all 10ms to update
the playback progress. Other than this, the playback position
-From 8a9e2054d3ecf11044136daa5644d803db486dd4 Mon Sep 17 00:00:00 2001
+From 77b81e05d19c1c25d8139eddc45c0a2da0585be2 Mon Sep 17 00:00:00 2001
From: detule <ogjoneski@gmail.com>
Date: Tue, 2 Oct 2018 04:10:08 -0400
-Subject: [PATCH 141/703] vchiq_2835_arm: Implement a DMA pool for small bulk
+Subject: [PATCH 141/725] vchiq_2835_arm: Implement a DMA pool for small bulk
transfers (#2699)
During a bulk transfer we request a DMA allocation to hold the
-From e40969b6e1a0818b016646c449d3fbc7e5c8b608 Mon Sep 17 00:00:00 2001
+From fdac3a95e9af79a125e41d7c16e4deac80742ac5 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 8 Oct 2018 12:20:36 +0100
-Subject: [PATCH 142/703] BCM2708_DT: Use upstreamed GPIO expander driver
+Subject: [PATCH 142/725] BCM2708_DT: Use upstreamed GPIO expander driver
The upstreamed driver for the GPIO expander has a different compatible
string. Change the relevant Device Tree files to match.
-From 17ded7b344a73b5a590ca8dc4599ac1ad3c1edb7 Mon Sep 17 00:00:00 2001
+From 920732ad22a1e352b757d854aec4814c95d061a9 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 8 Oct 2018 17:16:28 +0100
-Subject: [PATCH 143/703] overlays: Fix a few dtc warnings
+Subject: [PATCH 143/725] overlays: Fix a few dtc warnings
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From 158c6b75bd52edff52b9499313935c9d0f154eb2 Mon Sep 17 00:00:00 2001
+From d659979d89c1de698fa7c7e28951c4f09f9dfafd Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 17 Oct 2018 16:32:52 +0100
-Subject: [PATCH 144/703] bcm2708-rpi: Disable txp interrupt unless using
+Subject: [PATCH 144/725] bcm2708-rpi: Disable txp interrupt unless using
vc4-kms-v3d overlay
Signed-off-by: popcornmix <popcornmix@gmail.com>
-From 3af123f416cbd52069f8479ece21e0564317cbb3 Mon Sep 17 00:00:00 2001
+From 0bb32ea31ade963bfe81c67dbb2a4dbb090895c2 Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Sat, 6 Oct 2018 16:45:41 +0200
-Subject: [PATCH 145/703] config: Enable Raspberry Pi voltage monitor
+Subject: [PATCH 145/725] config: Enable Raspberry Pi voltage monitor
This enables the Raspberry Pi voltage monitor as a replacement
for the get_trottled sysfs approach in the firmware driver.
-From 639d584d74593084469286e33cbf8c6b2be9d1a5 Mon Sep 17 00:00:00 2001
+From af7c9bdc7c407c585fd3c6eac2ad42e78e1fb08c Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Sat, 6 Oct 2018 16:46:18 +0200
-Subject: [PATCH 146/703] hwmon: raspberrypi: Prevent voltage low warnings from
+Subject: [PATCH 146/725] hwmon: raspberrypi: Prevent voltage low warnings from
filling log
Although the correct fix for low voltage warnings is to
-From 2f40de9f47b7bcf5677a110d4207bbf65e02049c Mon Sep 17 00:00:00 2001
+From 53250b67aca386f2e01881623c192089226bbae3 Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Sat, 13 Oct 2018 13:31:21 +0200
-Subject: [PATCH 147/703] firmware: raspberrypi: Add backward compatible
+Subject: [PATCH 147/725] firmware: raspberrypi: Add backward compatible
get_throttled
Avoid a hard userspace ABI change by adding a compatible get_throttled
-From bee18e4688b1ac325f91dd4aee8672f6201d0a8d Mon Sep 17 00:00:00 2001
+From 5ff0d8351ea1bae67c1fd8d565bb4912cf201a71 Mon Sep 17 00:00:00 2001
From: James Hughes <james.hughes@raspberrypi.org>
Date: Wed, 31 Oct 2018 13:00:46 +0000
-Subject: [PATCH 148/703] Increase firmware call buffer size to 48 bytes
+Subject: [PATCH 148/725] Increase firmware call buffer size to 48 bytes
An assumption was made in commit a1547e0bc that 32 bytes
would be enough data buffer size for all firmware calls. However,
-From 6a47065f2c10f857ec32786d0c4f2e1c46aed98b Mon Sep 17 00:00:00 2001
+From 692350cd48454616db5bde755b6d2ef29946ade7 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 6 Nov 2018 12:57:48 +0000
-Subject: [PATCH 149/703] sc16is7xx: Don't spin if no data received
+Subject: [PATCH 149/725] sc16is7xx: Don't spin if no data received
See: https://github.com/raspberrypi/linux/issues/2676
-From 00fd230b49fe86d0458b3fbd92b9c556c1433fe4 Mon Sep 17 00:00:00 2001
+From 049db5dc012f133a8838503426a0cfa1cf9367a6 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 12 Nov 2018 21:42:00 +0000
-Subject: [PATCH 150/703] configs: Rebuild bcmrpi3_defconfig to fix warnings
+Subject: [PATCH 150/725] configs: Rebuild bcmrpi3_defconfig to fix warnings
Also disable CONFIG_MMC_BCM2835 to avoid a runtime conflict.
-From 80cebfc3a14a2645e99baa0a72587e25961e178f Mon Sep 17 00:00:00 2001
+From f54f72309a110bbb583335dd72d84908b1f56043 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Thu, 24 Aug 2017 16:16:16 +0100
-Subject: [PATCH 151/703] brcmfmac: Disable ARP offloading when promiscuous
+Subject: [PATCH 151/725] brcmfmac: Disable ARP offloading when promiscuous
This is a test patch for brcmfmac from Franky Lin at Broadcom to disable
ARP offloading when in promiscuous mode, re-enabling the ability to
-From 3267c6df89133ad70bd8bb1e55a5754be716df0e Mon Sep 17 00:00:00 2001
+From d96b4839eea5d6d0a776bed39d3fb6d8cc198662 Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Tue, 6 Feb 2018 15:37:22 +0100
-Subject: [PATCH 152/703] config: enable Audio Graph Card module
+Subject: [PATCH 152/725] config: enable Audio Graph Card module
Signed-off-by: Matthias Reichl <hias@horus.com>
---
-From 0de1fec9e76eabe6079fb9984a012cbdee9164a6 Mon Sep 17 00:00:00 2001
+From 52c06bef6f690f7fd5ab3fde9049a022344cb0bb Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Thu, 29 Mar 2018 16:05:28 +0100
-Subject: [PATCH 153/703] config: Add IPVLAN module
+Subject: [PATCH 153/725] config: Add IPVLAN module
---
arch/arm/configs/bcm2709_defconfig | 1 +
-From 61df97bfcb573b2361fdbbe0282ba1c5671988dc Mon Sep 17 00:00:00 2001
+From 511b2e25825ff53cb5dbb5d224c747c8dd37dc8b Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Fri, 27 Apr 2018 16:21:33 +0100
-Subject: [PATCH 154/703] config: Add I2C_TINY_USB=m
+Subject: [PATCH 154/725] config: Add I2C_TINY_USB=m
Enable the I2C Tiny USB module.
-From 0950d997c40aa9428b886d7e1af46730b0366513 Mon Sep 17 00:00:00 2001
+From c02e400776f6cba9abef5bfec91765e694f35d3b Mon Sep 17 00:00:00 2001
From: Jasper Boomer <jasperboomer@gmail.com>
Date: Sun, 24 Jun 2018 12:20:27 -0400
-Subject: [PATCH 155/703] Add device tree overlay for HD44780
+Subject: [PATCH 155/725] Add device tree overlay for HD44780
---
arch/arm/boot/dts/overlays/Makefile | 1 +
-From 3b04201f52d7a717828ab10a92610edbb99abd23 Mon Sep 17 00:00:00 2001
+From a7523a743a928748b2961de56fe5345f653da15e Mon Sep 17 00:00:00 2001
From: Jasper Boomer <jasperboomer@gmail.com>
Date: Mon, 2 Jul 2018 13:16:22 -0400
-Subject: [PATCH 156/703] Add hd44780 module to defconfig
+Subject: [PATCH 156/725] Add hd44780 module to defconfig
---
arch/arm/configs/bcm2709_defconfig | 2 ++
-From ac46f67a7cd528da77a0483989ad41a71af1d9e5 Mon Sep 17 00:00:00 2001
+From 7eaf324bc93496bb2462da74aa575a4b5c6b39da Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 9 Jul 2018 21:11:32 +0100
-Subject: [PATCH 157/703] overlays: Add addr parameter to i2c-rtc (& -gpio)
+Subject: [PATCH 157/725] overlays: Add addr parameter to i2c-rtc (& -gpio)
See: https://github.com/raspberrypi/linux/issues/2611
-From 74cbdede7a4a3eed31d508c02503ce06a1d0e7b2 Mon Sep 17 00:00:00 2001
+From c4620c94d1a5ec51908bb670968b68fd1aa692b1 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Fri, 9 Mar 2018 14:24:05 -0800
-Subject: [PATCH 158/703] ARM: BCM270X: Add the 18-bit DPI pinmux to the RPI
+Subject: [PATCH 158/725] ARM: BCM270X: Add the 18-bit DPI pinmux to the RPI
DTs.
This doesn't do anything by default, but trying to put the node in an
-From 7c8ccff2dfef1f42ac9e1592a4750b4d9b78ad62 Mon Sep 17 00:00:00 2001
+From 2fc67f0d898fb7be4e68bdb94959fdebe07b529d Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Fri, 9 Mar 2018 13:20:21 -0800
-Subject: [PATCH 159/703] overlays: Add an overlay for the Adafruit Kippah with
+Subject: [PATCH 159/725] overlays: Add an overlay for the Adafruit Kippah with
their 7" panel
Signed-off-by: Eric Anholt <eric@anholt.net>
-From 27d6a0828bacfd0f1d3e0b64176be91a55d2f3ae Mon Sep 17 00:00:00 2001
+From e5d4483bb784c5602ba585692cbdde1d0fbbfff9 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Fri, 9 Mar 2018 13:26:33 -0800
-Subject: [PATCH 160/703] overlays: Remove stale notes about vc4's CMA
+Subject: [PATCH 160/725] overlays: Remove stale notes about vc4's CMA
alignment in the README.
We haven't needed alignment since
-From ac1bfbc3e45d83d617ce9fbae7522bbd0be3a075 Mon Sep 17 00:00:00 2001
+From 2910d986df71ea75845706084fd257d2b9127e74 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 3 Jul 2018 14:23:47 +0100
-Subject: [PATCH 161/703] spi: Make GPIO CSs honour the SPI_NO_CS flag
+Subject: [PATCH 161/725] spi: Make GPIO CSs honour the SPI_NO_CS flag
The SPI configuration state includes an SPI_NO_CS flag that disables
all CS line manipulation, for applications that want to manage their
-From 90e4534cb3d7b7f1810c160734b11adc79dd6422 Mon Sep 17 00:00:00 2001
+From bb5657317c40a44f4a550f7f7101edc6fe5f50af Mon Sep 17 00:00:00 2001
From: Steve Pavao <stevep@korgrd.com>
Date: Fri, 10 Aug 2018 17:09:50 -0400
-Subject: [PATCH 162/703] devicetree: add RPi CM3 dts to arm64; mimic the RPi
+Subject: [PATCH 162/725] devicetree: add RPi CM3 dts to arm64; mimic the RPi
3B arm64 dts implementation, by referring to the actual dts file in the arm
directory
-From 5565106f860262bde33a49e866090bec4d2602e0 Mon Sep 17 00:00:00 2001
+From 4accaf8828da84a10053475c100a07ae91d75c8e Mon Sep 17 00:00:00 2001
From: Matt Flax <flatmax@flatmax.org>
Date: Tue, 28 Aug 2018 18:42:13 +1000
-Subject: [PATCH 163/703] Add support for audioinjector.net ultra soundcard.
+Subject: [PATCH 163/725] Add support for audioinjector.net ultra soundcard.
(#2664)
Uses the simple-audio-card ALSA machine driver. Sets up the machine
-From 42d8389b1b8b22be93aefd995f8a1b818bf1dac5 Mon Sep 17 00:00:00 2001
+From 84e563dc0f76f480dc00ec72c04621810cf2bcb1 Mon Sep 17 00:00:00 2001
From: Matt Flax <flatmax@flatmax.org>
Date: Thu, 30 Aug 2018 09:38:02 +1000
-Subject: [PATCH 164/703] ASoC: cs4265: Add a S/PDIF enable switch
+Subject: [PATCH 164/725] ASoC: cs4265: Add a S/PDIF enable switch
commit f853d6b3ba345297974d877d8ed0f4a91eaca739 upstream.
-From acee6587af4d29f9c95fa79f2bbf9cab3a96842e Mon Sep 17 00:00:00 2001
+From 515db674b59d2d693b8a6dd8fc9bb2827a71335e Mon Sep 17 00:00:00 2001
From: Matt Flax <flatmax@flatmax.org>
Date: Thu, 30 Aug 2018 09:38:01 +1000
-Subject: [PATCH 165/703] ASoC: cs4265: Add native 32bit I2S transport
+Subject: [PATCH 165/725] ASoC: cs4265: Add native 32bit I2S transport
commit be47e75eb1419ffc1d9c26230963fd5fa3055097 upstream.
-From b505a24b00c20ca89877ed20599dd4846a7dea83 Mon Sep 17 00:00:00 2001
+From 160ed28c5e56e859e8e1c415e1012a9cab451af1 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 18 Sep 2018 11:03:20 +0100
-Subject: [PATCH 166/703] configs: Add SENSOR_GPIO_FAN=m
+Subject: [PATCH 166/725] configs: Add SENSOR_GPIO_FAN=m
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From 0bcb443fca933a3b5e3c16065696a1949ea8f5eb Mon Sep 17 00:00:00 2001
+From 8b33ef9c1afe19c6d7e3f833e73a4bd3afa0225d Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 18 Sep 2018 11:08:07 +0100
-Subject: [PATCH 167/703] BCM270X_DT: Add gpio-fan overlay
+Subject: [PATCH 167/725] BCM270X_DT: Add gpio-fan overlay
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From acb48e74935371e095b98d5d8d4c97a577e46b63 Mon Sep 17 00:00:00 2001
+From 2403affd9cfe04af6326ccc9ba7ee64832b1881d Mon Sep 17 00:00:00 2001
From: Hanno Zulla <abos@hanno.de>
Date: Thu, 23 Aug 2018 17:03:38 +0200
-Subject: [PATCH 168/703] HID: hid-bigbenff: driver for BigBen Interactive
+Subject: [PATCH 168/725] HID: hid-bigbenff: driver for BigBen Interactive
PS3OFMINIPAD gamepad
commit 256a90ed9e46b270bbc4e15ef05216ff049c3721 upstream.
-From 8bf8320c86fd8601dccb0ea6dc677a6d2256a50e Mon Sep 17 00:00:00 2001
+From f8ce06486d1946376160c956d1bc1784c9472fdb Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 24 Sep 2018 14:56:58 +0100
-Subject: [PATCH 169/703] configs: Add CONFIG_HID_BIGBEN_FF=m
+Subject: [PATCH 169/725] configs: Add CONFIG_HID_BIGBEN_FF=m
See: https://github.com/raspberrypi/linux/issues/2690
-From 42808db6f458ddfca3367ed1167550241d2feb57 Mon Sep 17 00:00:00 2001
+From 8a868455243fec7abfe55d4f6af9eeb94755d4b7 Mon Sep 17 00:00:00 2001
From: Matt Flax <flatmax@flatmax.org>
Date: Fri, 28 Sep 2018 15:13:28 +1000
-Subject: [PATCH 170/703] ASoC: cs4265: Add a MIC pre. route (#2696)
+Subject: [PATCH 170/725] ASoC: cs4265: Add a MIC pre. route (#2696)
Commit b0ef5011b981ece1fde8063243a56d3038b87adb upstream.
-From 45466299c8b39d5d37b3a84c2db74834539ddc4b Mon Sep 17 00:00:00 2001
+From e4c16c37899bacb3a1a10c5830459fc09f3135d9 Mon Sep 17 00:00:00 2001
From: Paul <paulenuta@users.noreply.github.com>
Date: Thu, 11 Oct 2018 12:17:20 +0300
-Subject: [PATCH 171/703] Update gpio-fan-overlay.dts (#2711)
+Subject: [PATCH 171/725] Update gpio-fan-overlay.dts (#2711)
Add references, links, clear details, some typo correction.
---
-From 5d58e2d4e99f2ad2107b3aaca93fda6e758dc1ba Mon Sep 17 00:00:00 2001
+From 158b0f9b48e2974cbe8b83ab0024a05ebcefbe99 Mon Sep 17 00:00:00 2001
From: Ram Chandrasekar <rkumbako@codeaurora.org>
Date: Mon, 7 May 2018 11:54:08 -0600
-Subject: [PATCH 172/703] drivers: thermal: step_wise: add support for
+Subject: [PATCH 172/725] drivers: thermal: step_wise: add support for
hysteresis
From: Ram Chandrasekar <rkumbako@codeaurora.org>
-From 71eb84af0905c95ae67e957f8af81e131e534ea9 Mon Sep 17 00:00:00 2001
+From e381db8721f2658d7c90183b4685bb62e96db6fe Mon Sep 17 00:00:00 2001
From: Serge Schneider <serge@raspberrypi.org>
Date: Tue, 2 Oct 2018 11:14:15 +0100
-Subject: [PATCH 173/703] drivers: thermal: step_wise: avoid throttling at
+Subject: [PATCH 173/725] drivers: thermal: step_wise: avoid throttling at
hysteresis temperature after dropping below it
Signed-off-by: Serge Schneider <serge@raspberrypi.org>
-From 981040d773878289ce9cd7bb15a78f4205317ab1 Mon Sep 17 00:00:00 2001
+From 6699b062f9bebb291c65f8402a62e99c71402ed0 Mon Sep 17 00:00:00 2001
From: Serge Schneider <serge@raspberrypi.org>
Date: Wed, 26 Sep 2018 19:44:59 +0100
-Subject: [PATCH 174/703] hwmon: adjust rpi-poe-fan overlay trip points
+Subject: [PATCH 174/725] hwmon: adjust rpi-poe-fan overlay trip points
Signed-off-by: Serge Schneider <serge@raspberrypi.org>
---
-From ca2ef312a9bb95596a2f69186f4ca210a8160c1a Mon Sep 17 00:00:00 2001
+From db562e1eaed352231730eebcdc22b5c305e42338 Mon Sep 17 00:00:00 2001
From: Serge Schneider <serge@raspberrypi.org>
Date: Tue, 2 Oct 2018 17:13:48 +0100
-Subject: [PATCH 175/703] overlays: add overrides for PoE HAT fan control
+Subject: [PATCH 175/725] overlays: add overrides for PoE HAT fan control
Signed-off-by: Serge Schneider <serge@raspberrypi.org>
---
-From deb8928a66ab048325b52a00c36bd8a69cd63bea Mon Sep 17 00:00:00 2001
+From dc7881193fbee4ac1235d5a87af7d3abef3bee14 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Wed, 18 Jul 2018 17:25:00 +0100
-Subject: [PATCH 176/703] overlays: Add gpio-no-bank0-irq overlay
+Subject: [PATCH 176/725] overlays: Add gpio-no-bank0-irq overlay
See: https://github.com/raspberrypi/linux/issues/2590
-From e296ac154f037f09fd100150d8eb113942661f58 Mon Sep 17 00:00:00 2001
+From ea5d66b73d721b0a21d6b3eb677dd8f65cb8a3dd Mon Sep 17 00:00:00 2001
From: Hans-Wilhelm Warlo <5417271+hanswilw@users.noreply.github.com>
Date: Tue, 16 Oct 2018 18:20:48 +0200
-Subject: [PATCH 177/703] Add hy28b 2017 model device tree overlay (#2721)
+Subject: [PATCH 177/725] Add hy28b 2017 model device tree overlay (#2721)
The 2017 version of the hy28b display requires a different
initialisation sequence.
-From b457a3f171ce59b613250751775c56b390995c71 Mon Sep 17 00:00:00 2001
+From e7010b9f0497dd34e8b054b321d82e44925594dc Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Thu, 25 Oct 2018 14:08:43 +0100
-Subject: [PATCH 178/703] config: Add CONFIG_USBIP_VUDC
+Subject: [PATCH 178/725] config: Add CONFIG_USBIP_VUDC
See: https://github.com/raspberrypi/firmware/issues/353
---
-From 999a38346e7d54c6d8323965e91e2218d0e6d716 Mon Sep 17 00:00:00 2001
+From d5188bb19c7c3a01091e0779a94c67c2b6314005 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Fri, 26 Oct 2018 17:29:51 +0100
-Subject: [PATCH 179/703] mmc/bcm2835-sdhost: Recover from MMC_SEND_EXT_CSD
+Subject: [PATCH 179/725] mmc/bcm2835-sdhost: Recover from MMC_SEND_EXT_CSD
If the user issues an "mmc extcsd read", the SD controller receives
what it thinks is a SEND_IF_COND command with an unexpected data block.
-From 3bbbf9c1d2e2459c9a74adf0e7b771ac2b9f7451 Mon Sep 17 00:00:00 2001
+From 4f60a9f26c17f3722c6cc6b4af149ff8db4f6e47 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 29 Oct 2018 10:38:31 +0000
-Subject: [PATCH 180/703] overlays: pi3-disable-bt: Clear out bt_pins node
+Subject: [PATCH 180/725] overlays: pi3-disable-bt: Clear out bt_pins node
The pi3-disable-bt overlay does not (and cannot) delete the bt_pins
node, but emptying its properties (including brcm,pins) is a way of
-From 5e3cd6eeb1af7da0424290cb77e355755e17729c Mon Sep 17 00:00:00 2001
+From 759061b16cf853b38c8cce3688fb8566b3e8b413 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 29 Oct 2018 14:45:45 +0000
-Subject: [PATCH 181/703] Revert "rtc: pcf8523: properly handle oscillator stop
+Subject: [PATCH 181/725] Revert "rtc: pcf8523: properly handle oscillator stop
bit"
This reverts commit ede44c908d44b166a5b6bd7caacd105c2ff5a70f.
-From f77461fb11af8f37a15832032c58a256e21ff311 Mon Sep 17 00:00:00 2001
+From 70971c0ca8a15bca1ff755494bc83b161cf363f6 Mon Sep 17 00:00:00 2001
From: James Hughes <JamesH65@users.noreply.github.com>
Date: Fri, 2 Nov 2018 11:55:49 +0000
-Subject: [PATCH 182/703] Update issue templates (#2736)
+Subject: [PATCH 182/725] Update issue templates (#2736)
---
.github/ISSUE_TEMPLATE/bug_report.md | 34 ++++++++++++++++++++++++++++
-From bd2af9087e825313f2c2d2cf4ff74c7421a705d2 Mon Sep 17 00:00:00 2001
+From 964ca9ac6a8e55a3563734d0e9c1219bc6e42813 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Wed, 7 Nov 2018 17:43:10 +0000
-Subject: [PATCH 183/703] overlays: uart0 - return GPIOs 14 and 15 to inputs
+Subject: [PATCH 183/725] overlays: uart0 - return GPIOs 14 and 15 to inputs
In the event that alternate pins are used (only useful on Compute
Modules), return the standard pins to inputs to avoid double-mapping
-From 59782472a3e41e591492ef219abb3f0fc082d08f Mon Sep 17 00:00:00 2001
+From cebac10c14079ce87b94a9e7caa77cdbf883f458 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 12 Nov 2018 22:54:40 +0000
-Subject: [PATCH 184/703] mmc: bcm2835-sdhost: Fix warnings on arm64
+Subject: [PATCH 184/725] mmc: bcm2835-sdhost: Fix warnings on arm64
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From bb7479c2adc27bd21e5fae14df21d4f9e89a8aac Mon Sep 17 00:00:00 2001
+From 2a1d1f77ccfc4e5f4b2b4df23504df77d5aceda1 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 12 Nov 2018 22:56:35 +0000
-Subject: [PATCH 185/703] Fix warning in bcm2835-smi-nand
+Subject: [PATCH 185/725] Fix warning in bcm2835-smi-nand
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From 7ee204d064e56592409ea3ff7ba930a00fe51a0f Mon Sep 17 00:00:00 2001
+From 5d582dbe8344f87fb726b4e35620dc0ca554337f Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 14:55:37 +0000
-Subject: [PATCH 186/703] media: ov5647: Add set_fmt and get_fmt calls.
+Subject: [PATCH 186/725] media: ov5647: Add set_fmt and get_fmt calls.
There's no way to query the subdevice for the supported
resolutions.
-From 3a40a450f896c003be6b4fc7ce020f64716c2e2b Mon Sep 17 00:00:00 2001
+From 31f9d16b849bc50df1a0393a5b858fe3e56e7809 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 14:55:59 +0000
-Subject: [PATCH 187/703] [media] Documentation: DT: add device tree for PWDN
+Subject: [PATCH 187/725] [media] Documentation: DT: add device tree for PWDN
control
Add optional GPIO pwdn to connect to the PWDN line on the sensor.
-From 7c6fef835e14a484f24a41f5095bbef492aa433c Mon Sep 17 00:00:00 2001
+From 7330f9a31cb271e4b148bf171cec1ce32c25338a Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 14:56:33 +0000
-Subject: [PATCH 188/703] media: ov5647: Add support for PWDN GPIO.
+Subject: [PATCH 188/725] media: ov5647: Add support for PWDN GPIO.
Add support for an optional GPIO connected to PWDN on the sensor.
-From d8eb44c8aa81de883c154c46b3323895e6a70a35 Mon Sep 17 00:00:00 2001
+From 39de5418b771d8506e2836fec7d4296983fee954 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 14:56:47 +0000
-Subject: [PATCH 189/703] media: ov5647: Add support for non-continuous clock
+Subject: [PATCH 189/725] media: ov5647: Add support for non-continuous clock
mode
The driver was only supporting continuous clock mode
-From 74cfa3689511a7befa86ab18ff4d4d9662472c08 Mon Sep 17 00:00:00 2001
+From 9774cb0c44ed8d6394b6cb7c742517a2c7989f09 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 14:56:59 +0000
-Subject: [PATCH 190/703] media: tc358743: Increase FIFO level to 374.
+Subject: [PATCH 190/725] media: tc358743: Increase FIFO level to 374.
The existing fixed value of 16 worked for UYVY 720P60 over
2 lanes at 594MHz, or UYVY 1080P60 over 4 lanes. (RGB888
-From 5223be7b3a1ee9849730657ade5767bd3f6cf3bd Mon Sep 17 00:00:00 2001
+From 5edf7cf2cfe901e8df2d698eaf518f856308313f Mon Sep 17 00:00:00 2001
From: Philipp Zabel <p.zabel@pengutronix.de>
Date: Thu, 21 Sep 2017 17:30:24 +0200
-Subject: [PATCH 191/703] media: tc358743: fix connected/active CSI-2 lane
+Subject: [PATCH 191/725] media: tc358743: fix connected/active CSI-2 lane
reporting
g_mbus_config was supposed to indicate all supported lane numbers, not
-From 518faafd6f8b692a3448b6ca6e5e473f55d5360e Mon Sep 17 00:00:00 2001
+From f372eaac56da0592bef997c681b05525f1950745 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 14:57:21 +0000
-Subject: [PATCH 192/703] media: tc358743: Add support for 972Mbit/s link freq.
+Subject: [PATCH 192/725] media: tc358743: Add support for 972Mbit/s link freq.
Adds register setups for running the CSI lanes at 972Mbit/s,
which allows 1080P50 UYVY down 2 lanes.
-From 0b01e856bf06b8cd40e0edd37b4f3d47935fe09c Mon Sep 17 00:00:00 2001
+From 02d715b6d479f2f67244056d731f37c5b1475f37 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 14:57:34 +0000
-Subject: [PATCH 193/703] media: tc358743: Check I2C succeeded during probe.
+Subject: [PATCH 193/725] media: tc358743: Check I2C succeeded during probe.
The probe for the TC358743 reads the CHIPID register from
the device and compares it to the expected value of 0.
-From cb7c2b320a18a8129092e6b452e72716fa083878 Mon Sep 17 00:00:00 2001
+From 156dcf0046229d377ab882094f7ea7b80c411eaa Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 14:57:46 +0000
-Subject: [PATCH 194/703] media: adv7180: Default to the first valid input
+Subject: [PATCH 194/725] media: adv7180: Default to the first valid input
The hardware default is differential CVBS on AIN1 & 2, which
isn't very useful.
-From 17310ae3261766d68d778d353b13970fb6c25810 Mon Sep 17 00:00:00 2001
+From 888202a50fd8f8eb16e57d2f35621bdcaff3c0c5 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 14:57:56 +0000
-Subject: [PATCH 195/703] media: adv7180: Add YPrPb support for ADV7282M
+Subject: [PATCH 195/725] media: adv7180: Add YPrPb support for ADV7282M
The ADV7282M can support YPbPr on AIN1-3, but this was
not selectable from the driver. Add it to the list of
-From f776604fdd061358ccdc420ba8babcc6fbe76baa Mon Sep 17 00:00:00 2001
+From 37a1cdda51bc5989510ccfe28ccf149a1e5c3f76 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 14:58:08 +0000
-Subject: [PATCH 196/703] media: videodev2: Add helper defines for printing
+Subject: [PATCH 196/725] media: videodev2: Add helper defines for printing
FOURCCs
New helper defines that allow printing of a FOURCC using
-From 1adfe2e2d3e1cd6a13e32763e347284c08f6707b Mon Sep 17 00:00:00 2001
+From 1f7138cdbf10ca6225ba4b1df6ab4e3c7db996bc Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 14:59:06 +0000
-Subject: [PATCH 197/703] dt-bindings: Document BCM283x CSI2/CCP2 receiver
+Subject: [PATCH 197/725] dt-bindings: Document BCM283x CSI2/CCP2 receiver
Document the DT bindings for the CSI2/CCP2 receiver peripheral
(known as Unicam) on BCM283x SoCs.
-From f37e8a66e3cd8eafc8b233ae250e2ac159b6870b Mon Sep 17 00:00:00 2001
+From c43d7b532dd2e502330fa1457e5e952ef307504e Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 14:59:22 +0000
-Subject: [PATCH 198/703] media: bcm2835-unicam: Driver for CCP2/CSI2 camera
+Subject: [PATCH 198/725] media: bcm2835-unicam: Driver for CCP2/CSI2 camera
interface
Add driver for the Unicam camera receiver block on
-From 602457089d7a0ee10df402370a50e469b213da02 Mon Sep 17 00:00:00 2001
+From f363e576611799627bd2f5dbe3cf07c4792ccf84 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 14:59:40 +0000
-Subject: [PATCH 199/703] MAINTAINERS: Add entry for BCM2835 Unicam driver
+Subject: [PATCH 199/725] MAINTAINERS: Add entry for BCM2835 Unicam driver
Adds entry for the new BCM2835 Unicam (CSI-2 receiver) driver
-From 52fca9e13ca8fe69a2c181982bafe09688a42de4 Mon Sep 17 00:00:00 2001
+From ba8758df732d320e5647d23f245a8a134dde92e1 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 14:59:51 +0000
-Subject: [PATCH 200/703] defconfig: Enable Unicam driver and various sources
+Subject: [PATCH 200/725] defconfig: Enable Unicam driver and various sources
on Pi platforms.
Enable:
-From b14afe8c3c5c85e3114617eba49751e21b9cbe47 Mon Sep 17 00:00:00 2001
+From 63714d94e345ffeaf2042cfe552fa2a00ed8764c Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 15:00:04 +0000
-Subject: [PATCH 201/703] media: adv7180: Nasty hack to allow input selection.
+Subject: [PATCH 201/725] media: adv7180: Nasty hack to allow input selection.
Whilst the adv7180 driver support s_routing, nothing else
does, and there is a missing lump of framework code to
-From e2bd21a4b01db45b8b3ecf5d1e0716c608266065 Mon Sep 17 00:00:00 2001
+From 5672dd9e874730f5a0db0b7697e5f66a7707e130 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 15:00:20 +0000
-Subject: [PATCH 202/703] BCM283x DT: Add CSI nodes to the device tree.
+Subject: [PATCH 202/725] BCM283x DT: Add CSI nodes to the device tree.
Adds CSI nodes to all the upstream device tree configs
-From 1778c46d5542576ba3335c00502c7ccf9035b42c Mon Sep 17 00:00:00 2001
+From 5da3b99c82d6a93af9490e759fa83caecc11550f Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 15:00:45 +0000
-Subject: [PATCH 203/703] BCM270X_DT: Add CSI defines for all the downstream Pi
+Subject: [PATCH 203/725] BCM270X_DT: Add CSI defines for all the downstream Pi
platforms
Adds the CSI device includes for the bcm27xx platform DTS files
-From db902a4ec646e0ab4dee6168c3d1ef2d121c5865 Mon Sep 17 00:00:00 2001
+From ba7e742c925b5a46ac63fe0c6e3d988eb6ea3e79 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 15:01:59 +0000
-Subject: [PATCH 204/703] arm: dt: Add DT overlays for ADV7282M, OV5647, and
+Subject: [PATCH 204/725] arm: dt: Add DT overlays for ADV7282M, OV5647, and
TC358743
DT overlays to setup the above devices via i2c_arm and csi1.
-From 4f00a0c8bef152e0d2f3a382bbe02cc49bc8287e Mon Sep 17 00:00:00 2001
+From 9ab30d7658ba3c6ddf77661b6ca4440ef2d6e38d Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 31 Oct 2018 15:02:18 +0000
-Subject: [PATCH 205/703] dtoverlays: Add support for ADV7280-M, ADV7281-M and
+Subject: [PATCH 205/725] dtoverlays: Add support for ADV7280-M, ADV7281-M and
ADV7281-MA chips.
The driver that supports the ADV7282-M also supports the ADV7280-M,
-From 3090cdd55e3a36f545409814cbee08761b93640c Mon Sep 17 00:00:00 2001
+From 2491694e7b0b8c09b13130f9c165a812b773e57e Mon Sep 17 00:00:00 2001
From: James Hughes <JamesH65@users.noreply.github.com>
Date: Tue, 13 Nov 2018 17:27:00 +0000
-Subject: [PATCH 206/703] Mailbox firmware calls now use kmalloc (#2749)
+Subject: [PATCH 206/725] Mailbox firmware calls now use kmalloc (#2749)
A previous change moved away from variable stack
allocation of a data buffer to a fixed maximum size.
-From fb5cef781e09bb78ca095f8f5780952f996115f1 Mon Sep 17 00:00:00 2001
+From c050abb666638d8f9eaa7b5557713e7d9335495f Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 14 Nov 2018 11:54:46 +0000
-Subject: [PATCH 207/703] vcsm: Fix an NULL dereference in the import_dmabuf
+Subject: [PATCH 207/725] vcsm: Fix an NULL dereference in the import_dmabuf
error path
resource was dereferenced even though it was NULL.
-From 150489867949c6059436b7f96f36b11c5e75692a Mon Sep 17 00:00:00 2001
+From 74e24f7ba3e0443ffc4d026e96848c9ec51e2dcf Mon Sep 17 00:00:00 2001
From: James Hughes <JamesH65@users.noreply.github.com>
Date: Tue, 13 Nov 2018 16:51:21 +0000
-Subject: [PATCH 208/703] Update README (#2750)
+Subject: [PATCH 208/725] Update README (#2750)
Small update to the DT blob docs to include the axiperf option.
-From 18ac45909a08b7d4a67a4863a1a4c5e5ea7475dd Mon Sep 17 00:00:00 2001
+From 755f5c2690bd5c2b4db803600815cb1007057326 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Wed, 14 Nov 2018 09:53:25 +0000
-Subject: [PATCH 209/703] overlays: Remove superfluous #address/size-cells
+Subject: [PATCH 209/725] overlays: Remove superfluous #address/size-cells
Newer versions of dtc warn about unnecessary usage of #address-cells
and #size-cells, so remove them.
-From 636b64caee57e3afbe0c92c723ff266c9d4391b1 Mon Sep 17 00:00:00 2001
+From dbe949065c6b3de54cc172f6b2a906135392a4c1 Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Sun, 18 Nov 2018 13:21:26 +0100
-Subject: [PATCH 210/703] Revert "ASoC: wm8804: MCLK configuration options,
+Subject: [PATCH 210/725] Revert "ASoC: wm8804: MCLK configuration options,
32-bit"
This reverts commit 3b12dcf797f5a4635aecd7f5c090dc507b124ffd.
-From 3ee2530bf8c00154ba00eb70bbb6c0276fbb0ca2 Mon Sep 17 00:00:00 2001
+From a93fcdaf72291fea4661690cc35e1a45834e3cb7 Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Sun, 18 Nov 2018 15:24:16 +0100
-Subject: [PATCH 211/703] rpi-wm8804-soundcard: drop PWRDN register writes
+Subject: [PATCH 211/725] rpi-wm8804-soundcard: drop PWRDN register writes
Since kernel 4.0 the PWRDN register bits are under DAPM
control from the wm8804 driver.
-From c56c1c63927b4fafb51b45df92d6a58eeb08141a Mon Sep 17 00:00:00 2001
+From cf634513d2b238ae041d4fd836e48c63b94c0e6b Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Sun, 18 Nov 2018 15:32:28 +0100
-Subject: [PATCH 212/703] rpi-wm8804-soundcard: configure wm8804 clocks only on
+Subject: [PATCH 212/725] rpi-wm8804-soundcard: configure wm8804 clocks only on
rate change
This should avoid clicks when stopping and immediately afterwards
-From 0676c7a6270df8f3bdc0cfee0025959e155c8c2a Mon Sep 17 00:00:00 2001
+From c305b2c14d9ec6f297062a0410010325d783eec6 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Mon, 26 Nov 2018 17:02:15 +0000
-Subject: [PATCH 213/703] dtoverlays: Add i2c on 0&1 option to TC358743,
+Subject: [PATCH 213/725] dtoverlays: Add i2c on 0&1 option to TC358743,
ADV7282 and OV5647
Adds the option of configuring i2c0 to be on GPIOs 0&1 as
-From dcc96e7fc22e361aa7f242dd3ca6db1f04a4c364 Mon Sep 17 00:00:00 2001
+From be3c95b4f638fc037188705615fabe0d3f25e72c Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 26 Nov 2018 20:15:16 +0000
-Subject: [PATCH 214/703] overlays: Update upstream overlay
+Subject: [PATCH 214/725] overlays: Update upstream overlay
The vc4-kms-v3d overlay gained an extra fragment enabling the txp node,
so rebuild the upstream overlay to match.
-From 2a98edd2e5a5477d9649f0682c9b195c8b6c7656 Mon Sep 17 00:00:00 2001
+From 16bf1291c3ffcdee88ee4838b2aa77f18bcfdd02 Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Wed, 28 Nov 2018 10:36:01 +0100
-Subject: [PATCH 215/703] BCM2708_DT: update firmware node binding
+Subject: [PATCH 215/725] BCM2708_DT: update firmware node binding
The upstreamed version of the firmware node has been updated to present
it as a "simple-bus". We need to get this in order to accomodate other
-From 57fdcf2049630157495c84a1440632c476016687 Mon Sep 17 00:00:00 2001
+From d167329afba66f1c7ac58a60941f6ee716e303b2 Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Tue, 27 Nov 2018 16:59:10 +0100
-Subject: [PATCH 216/703] BCM2710_DT: fix gpio expander bindings
+Subject: [PATCH 216/725] BCM2710_DT: fix gpio expander bindings
The upstreamed driver for the GPIO expander expects to be a children of
the "firmware" node.
-From 1606baa0882db5b08b493b59eaa2377703e536d2 Mon Sep 17 00:00:00 2001
+From 3cb3a4cf65c1daf812e5b29447e3282e953f308b Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 27 Nov 2018 16:33:31 +0000
-Subject: [PATCH 217/703] ARM: dts: bcm283x: The lan7515 PHY node has moved
+Subject: [PATCH 217/725] ARM: dts: bcm283x: The lan7515 PHY node has moved
The DT node describing the LAN7800s PHY has now moved inside an "mdio"
node. Update the DT declarations accordingly.
-From cfbb056c0c1445496f3434daf8324cad652d09be Mon Sep 17 00:00:00 2001
+From 0c5f8dac2daa64a5bc4793ec5c39004ae077b739 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 26 Nov 2018 19:46:58 +0000
-Subject: [PATCH 218/703] net: lan78xx: Support auto-downshift to 100Mb/s
+Subject: [PATCH 218/725] net: lan78xx: Support auto-downshift to 100Mb/s
Ethernet cables with faulty or missing pairs (specifically pairs C and
D) allow auto-negotiation to 1000Mbs, but do not support the successful
-From c8fee0e0a910f0286d6aa059b27c4d59109b978a Mon Sep 17 00:00:00 2001
+From 557a6998397903dd9416fdc717fa8016ef6b6d31 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Wed, 28 Nov 2018 15:51:41 +0000
-Subject: [PATCH 219/703] dt-bindings: Document microchip,downshift-after
+Subject: [PATCH 219/725] dt-bindings: Document microchip,downshift-after
Document the optional downshift-after property of the lan78xx's PHY.
-From 464f47a7c83ea253304b7fd43f56302db8071593 Mon Sep 17 00:00:00 2001
+From 1ee1b7cac821e90ac203c4274623fc03154be42d Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 27 Nov 2018 16:55:14 +0000
-Subject: [PATCH 220/703] ARM: dts: bcm283x: Set downshift-after for Pi 3B+
+Subject: [PATCH 220/725] ARM: dts: bcm283x: Set downshift-after for Pi 3B+
Enable the auto-downshift feature on Raspberry Pi 3B+ so that a link
can eventually be established using a cable with pairs C and/or D
-From 64c215470c985bd740e378cc3cd6963e15f0a927 Mon Sep 17 00:00:00 2001
+From 398295a34e3ee4b8817f868b4b81ae0462e6abe0 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 27 Nov 2018 16:56:50 +0000
-Subject: [PATCH 221/703] BCM270X_DT: Add new Ethernet DT parameters
+Subject: [PATCH 221/725] BCM270X_DT: Add new Ethernet DT parameters
Add "eth_downshift_after" DT parameter to allow the delay before the
downshift to be specified. The default is 2 auto-negotiation cycles,
-From 50086a7018911acdd58d627050127bfa7c5ec7de Mon Sep 17 00:00:00 2001
+From cb156dbcbd7fd138d0abb96855e2e472cb1ba3d3 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Thu, 29 Nov 2018 16:00:22 +0000
-Subject: [PATCH 222/703] BCM270X_DT: Mark eth_downshift_after as an integer
+Subject: [PATCH 222/725] BCM270X_DT: Mark eth_downshift_after as an integer
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From 71ffaebfc05366238b7b3777e572dc77ec6f78f6 Mon Sep 17 00:00:00 2001
+From e0cb60557d0127240de57893416068d60e90757a Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Mon, 16 Jul 2018 14:40:13 +0100
-Subject: [PATCH 223/703] dwc-otg: FIQ: Fix "bad mode in data abort handler"
+Subject: [PATCH 223/725] dwc-otg: FIQ: Fix "bad mode in data abort handler"
Create a semi-static mapping for the USB registers early in the boot
process, before additional kernel threads are started, so all threads
-From e2c77b86039e8f16d6dd75e06a50dc7290e95233 Mon Sep 17 00:00:00 2001
+From 06a217704d5b7acc8680b9ff4cb837f8dd7b4b5d Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Fri, 30 Nov 2018 18:55:23 +0000
-Subject: [PATCH 224/703] lirc-rpi: Remove in favour of gpio-ir
+Subject: [PATCH 224/725] lirc-rpi: Remove in favour of gpio-ir
---
arch/arm/boot/dts/overlays/Makefile | 1 -
-From b30282f720fddb3175a46726bd18ac691b172d32 Mon Sep 17 00:00:00 2001
+From 9e280b87eaf77735f0b9d1fd56a72ec11e7230cb Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Thu, 22 Nov 2018 17:28:02 +0000
-Subject: [PATCH 225/703] media: bcm2835-unicam: Pass through the colorspace on
+Subject: [PATCH 225/725] media: bcm2835-unicam: Pass through the colorspace on
try_fmt
The current colorspace was always returned from try_fmt for no
-From 8f84df14dc88580bfdce95999ab0167d3871ff7c Mon Sep 17 00:00:00 2001
+From 88ebe04c5b8feff596e3d373eb3d779fa13ff8c9 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Thu, 22 Nov 2018 17:31:06 +0000
-Subject: [PATCH 226/703] media: tc358743: Return an appropriate colorspace
+Subject: [PATCH 226/725] media: tc358743: Return an appropriate colorspace
from tc358743_set_fmt
When calling tc358743_set_fmt, the code was calling tc358743_get_fmt
-From 99b24dda7eb97f1c094abc942241ff1a7428b639 Mon Sep 17 00:00:00 2001
+From d248e54f2c13facdde31e13ab8c3acb26f63a8cd Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Sat, 20 Oct 2018 19:26:18 +0200
-Subject: [PATCH 227/703] staging: bcm2835-camera: fix module autoloading
+Subject: [PATCH 227/725] staging: bcm2835-camera: fix module autoloading
In order to make the module bcm2835-camera load automatically, we need to
add a module alias.
-From 9aa76a475dad23bcec194a08d063c9b19e54187e Mon Sep 17 00:00:00 2001
+From 87c91dbd458eb312449a9b300e13d7ca43ba9105 Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Sat, 20 Oct 2018 19:31:00 +0200
-Subject: [PATCH 228/703] staging: bcm2835-camera: Move module info to the end
+Subject: [PATCH 228/725] staging: bcm2835-camera: Move module info to the end
In order to have this more consistent between the vc04 services move
the module information to the end of the file.
-From e70e5563e9db4cb2cf081f40373b0b0df40b1c5c Mon Sep 17 00:00:00 2001
+From f5072609c720b1f50098d69e208113735f6b31fa Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Sat, 13 Oct 2018 20:51:23 +0200
-Subject: [PATCH 229/703] staging: vchiq_arm: Fix platform device
+Subject: [PATCH 229/725] staging: vchiq_arm: Fix platform device
unregistration
In error case platform_device_register_data would return an ERR_PTR
-From 1134ea85e8c3870ee3d31bb6acb4326d0f674d6a Mon Sep 17 00:00:00 2001
+From c9adbf27cebcbd0bd144eb3c282f9d9115121526 Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Mon, 22 Oct 2018 15:16:51 +0200
-Subject: [PATCH 230/703] staging: vchiq_arm: Fix camera device registration
+Subject: [PATCH 230/725] staging: vchiq_arm: Fix camera device registration
Since the camera driver isn't probed via DT, we need to properly setup DMA.
-From 1f7a4bfbb20d1775eac5b7db7545c0ab35b7642d Mon Sep 17 00:00:00 2001
+From 9a52240005032514c0df20bbcbac6a2efdc1ba04 Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Sat, 20 Oct 2018 20:25:41 +0200
-Subject: [PATCH 231/703] staging: vchiq_arm: Register a platform device for
+Subject: [PATCH 231/725] staging: vchiq_arm: Register a platform device for
the audio driver
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-From 4055954ff0be5159876c33f4841be686b4f730ab Mon Sep 17 00:00:00 2001
+From fb56caeb8f51fd08ff898bb679ac53bb5d9eb04e Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Sat, 13 Oct 2018 20:19:13 +0200
-Subject: [PATCH 232/703] staging: bcm2835-audio: Enable compile test
+Subject: [PATCH 232/725] staging: bcm2835-audio: Enable compile test
Enable the compilation test for bcm2835-audio.
-From ff285113caa9279101db3b6eb31dfc3d94e57d3d Mon Sep 17 00:00:00 2001
+From 57d6f481243f83f9ee1d62e0581d20d54005fb90 Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Thu, 18 Oct 2018 19:47:29 +0200
-Subject: [PATCH 233/703] staging: bcm2835-audio: use module_platform_driver()
+Subject: [PATCH 233/725] staging: bcm2835-audio: use module_platform_driver()
macro
There is not much value behind this boilerplate, so use
-From 4f0fb18ee7b5479b673257d15fe7bec3b3d90aac Mon Sep 17 00:00:00 2001
+From c396f36045c306f7d928c487455d0450585bbf4e Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Thu, 18 Oct 2018 19:54:01 +0200
-Subject: [PATCH 234/703] staging: bcm2835-audio: Drop DT dependency
+Subject: [PATCH 234/725] staging: bcm2835-audio: Drop DT dependency
Just like the bcm2835-video make this a platform driver which is probed
by vchiq. In order to change the number of channels use a module
-From a6646e496feed4fd7affe3fc5d4fc3e2591046d6 Mon Sep 17 00:00:00 2001
+From acf4b3ea7ec32069d8f3bd2b541ccb56ed1d0db5 Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Sun, 21 Oct 2018 18:40:07 +0200
-Subject: [PATCH 235/703] staging: bcm2835-camera: Provide more specific probe
+Subject: [PATCH 235/725] staging: bcm2835-camera: Provide more specific probe
error messages
Currently there is only a catch-all info message which print the
-From 477275011a3c1720683e3f9e6014ed2e76d921b7 Mon Sep 17 00:00:00 2001
+From 362ea23e6c338b589e9fcc5e91e942b00c37a93b Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Sun, 21 Oct 2018 19:08:29 +0200
-Subject: [PATCH 236/703] staging: bcm2835-camera: Add hint about possible
+Subject: [PATCH 236/725] staging: bcm2835-camera: Add hint about possible
faulty GPU mem config
As per default the GPU memory config of the Raspberry Pi isn't sufficient
-From 55c9d1a762b9cbb5a4c574918fb41a9cde6bb491 Mon Sep 17 00:00:00 2001
+From eb3b747986fbc23defe3942b91e24d3b0e007e3e Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Mon, 22 Oct 2018 11:09:18 +0200
-Subject: [PATCH 237/703] staging: bcm2835: Don't probe if no camera is
+Subject: [PATCH 237/725] staging: bcm2835: Don't probe if no camera is
detected
It is a waste of resources to load the camera driver in case there isn't
-From f83ac752b3898e65614d8b643ac57e828e1c5668 Mon Sep 17 00:00:00 2001
+From 8c25a73d376b538692aa0128d57ff95c71479561 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Mon, 3 Dec 2018 12:50:38 +0000
-Subject: [PATCH 238/703] staging: vchiq_arm: Improve error handling on loading
+Subject: [PATCH 238/725] staging: vchiq_arm: Improve error handling on loading
drivers
The handling of loading platform drivers requires checking IS_ERR
-From 7cd2d38371edd4a04401c02c098a0e436816f3af Mon Sep 17 00:00:00 2001
+From c668ed917ce492f9448245078e0a2e9f9f4eef3a Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 14 Feb 2018 17:04:26 +0000
-Subject: [PATCH 239/703] staging: bcm2835-camera: Do not bulk receive from
+Subject: [PATCH 239/725] staging: bcm2835-camera: Do not bulk receive from
service thread
vchi_bulk_queue_receive will queue up to a default of 4
-From 1e07591a39c73d5aec191a5d4065f33167483dd2 Mon Sep 17 00:00:00 2001
+From 873220449e4532c76d9ff86a75a482d1f78887db Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Mon, 29 Oct 2018 14:21:04 +0000
-Subject: [PATCH 240/703] staging: bcm2835-camera: Ensure H264 header bytes get
+Subject: [PATCH 240/725] staging: bcm2835-camera: Ensure H264 header bytes get
a sensible timestamp
H264 header come from VC with 0 timestamps, which means they get a
-From e66266218dca0b30e730f7b97240119cd140b92f Mon Sep 17 00:00:00 2001
+From 4bbbd45f2e47c52b89cd77c6b7cd7b5075836f86 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Mon, 13 Feb 2017 13:11:41 +0000
-Subject: [PATCH 241/703] staging: bcm2835-camera: Correctly denote key frames
+Subject: [PATCH 241/725] staging: bcm2835-camera: Correctly denote key frames
in encoded data
Forward MMAL key frame flags to the V4L2 buffers.
-From 83ba21bb6043c5afc3d497e9be4e128b3e1adf93 Mon Sep 17 00:00:00 2001
+From 7270f7555eb3d8144844c110e10f20558e563de6 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Fri, 10 Mar 2017 17:27:56 +0000
-Subject: [PATCH 242/703] staging: bcm2835-camera: Return early on errors
+Subject: [PATCH 242/725] staging: bcm2835-camera: Return early on errors
Fix several instances where it is easier to return
early on error conditions than handle it as an else
-From b7c48c78192d20fadb46b41a4628cb2a239017c1 Mon Sep 17 00:00:00 2001
+From fbea466b9b1178cf7b20607a3aa4ba7e98090e72 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Fri, 10 Mar 2017 17:35:38 +0000
-Subject: [PATCH 243/703] staging: bcm2835-camera: Remove dead email addresses
+Subject: [PATCH 243/725] staging: bcm2835-camera: Remove dead email addresses
None of the listed author email addresses were valid.
Keep list of authors and the companies they represented.
-From d1f1713c45091e779b29ee64e8900c9fac9e6339 Mon Sep 17 00:00:00 2001
+From d6c47fa1f829bfd7d85829bf5b507ac5aafe1172 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 21 Feb 2018 13:49:32 +0000
-Subject: [PATCH 244/703] staging: bcm2835-camera: Fix comment style
+Subject: [PATCH 244/725] staging: bcm2835-camera: Fix comment style
violations.
Fix comment style violations in the header files.
-From 587b76ecb097da6d7d386a0c228230d9175bc1e4 Mon Sep 17 00:00:00 2001
+From 9b4f48ebb4bad6ed87d15874967d446327b0e65f Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 21 Feb 2018 14:13:03 +0000
-Subject: [PATCH 245/703] staging: bcm2835-camera: Fix spacing around operators
+Subject: [PATCH 245/725] staging: bcm2835-camera: Fix spacing around operators
Fix checkpatch warnings over spaces around operators.
Many were around operations that can be replaced with the
-From 12692997f0508b8c3c31c23f8ab6983380888f5e Mon Sep 17 00:00:00 2001
+From 562d78a33091aaeb7c2f2a975a262438d4b6ff30 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 21 Feb 2018 15:23:35 +0000
-Subject: [PATCH 246/703] staging: bcm2835-camera: Reduce length of enum names
+Subject: [PATCH 246/725] staging: bcm2835-camera: Reduce length of enum names
We have numerous lines over 80 chars, or oddly split. Many
of these are due to using long enum names such as
-From 169d3b165889c1531227e2bb1e5df0f10ca9c83a Mon Sep 17 00:00:00 2001
+From bec59483afd1d335649fd26c83e448aae6602e4a Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 21 Feb 2018 15:28:07 +0000
-Subject: [PATCH 247/703] staging: bcm2835-camera: Fix multiple line
+Subject: [PATCH 247/725] staging: bcm2835-camera: Fix multiple line
dereference errors
Fix checkpatch errors "Avoid multiple line dereference"
-From b9702c9018656a2145bf18ad997d59f03f606bee Mon Sep 17 00:00:00 2001
+From c6fd809a48f06d2319c2391bafef0cf912fd9aa9 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 21 Feb 2018 15:37:11 +0000
-Subject: [PATCH 248/703] staging: bcm2835-camera: Fix brace style issues.
+Subject: [PATCH 248/725] staging: bcm2835-camera: Fix brace style issues.
Fix mismatched or missing brace issues flagged by checkpatch.
-From 153f1bd423b29c9c5ea0ab23ca4c1beb272dab31 Mon Sep 17 00:00:00 2001
+From cd004c183f3080cd6ec13337e63dded7a625bee4 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 21 Feb 2018 15:39:26 +0000
-Subject: [PATCH 249/703] staging: bcm2835-camera: Fix missing lines between
+Subject: [PATCH 249/725] staging: bcm2835-camera: Fix missing lines between
items
Fix checkpatch errors for missing blank lines after variable
-From b628d79fb130da3cbae59b4aaa14fbaf599a5e7c Mon Sep 17 00:00:00 2001
+From 1a1fb6d6e25aa33db217c5109aa6b440fedee415 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 21 Feb 2018 15:48:54 +0000
-Subject: [PATCH 250/703] staging: bcm2835-camera: Fix logical continuation
+Subject: [PATCH 250/725] staging: bcm2835-camera: Fix logical continuation
splits
Fix checkpatch errors for "Logical continuations should be
-From 1e5564239201bed6be0b57d50c6f95e8f3907512 Mon Sep 17 00:00:00 2001
+From 636f4fad6c786c006e32c86b2f0d769c19177414 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 21 Feb 2018 15:53:59 +0000
-Subject: [PATCH 251/703] staging: bcm2835-camera: Fix open parenthesis
+Subject: [PATCH 251/725] staging: bcm2835-camera: Fix open parenthesis
alignment
Fix checkpatch "Alignment should match open parenthesis"
--- /dev/null
+From 12f0df5a07a37ebc3669784fe234e7a24d5867c3 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 21 Jun 2018 17:02:14 +0100
+Subject: [PATCH 252/725] staging: bcm2835-camera: Set sequence number
+ correctly
+
+Set the sequence number in vb2_v4l2_buffer mainly so the
+latest v4l2-ctl reports the frame rate correctly.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 4 ++++
+ drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h | 2 ++
+ 2 files changed, 6 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -409,6 +409,7 @@ static void buffer_cb(struct vchiq_mmal_
+ }
+ }
+ dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
++ buf->vb.sequence = dev->capture.sequence++;
+
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
+ if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
+@@ -537,6 +538,9 @@ static int start_streaming(struct vb2_qu
+ /* enable frame capture */
+ dev->capture.frame_count = 1;
+
++ /* reset sequence number */
++ dev->capture.sequence = 0;
++
+ /* if the preview is not already running, wait for a few frames for AGC
+ * to settle down.
+ */
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
+@@ -93,6 +93,8 @@ struct bm2835_mmal_dev {
+ ktime_t kernel_start_ts;
+ /* Timestamp of last frame */
+ u64 last_timestamp;
++ /* Sequence number of last buffer */
++ u32 sequence;
+
+ struct vchiq_mmal_port *port; /* port being used for capture */
+ /* camera port being used for capture */
--- /dev/null
+From b29685ae7838b052cab7c7e26ff16e249edea294 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 24 Jul 2018 12:08:29 +0100
+Subject: [PATCH 253/725] staging: bcm2835-camera: Ensure timestamps never go
+ backwards.
+
+There is an awkward situation with H264 header bytes. Currently
+they are returned with a PTS of 0 because they aren't associated
+with a timestamped frame to encode. These are handled by either
+returning the timestamp of the last buffer to have been received,
+or in the case of the first buffer the timestamp taken at
+start_streaming.
+This results in a race where the current frame may have started
+before we take the start time, which results in the first encoded
+frame having an earlier timestamp than the header bytes.
+
+Ensure that we never return a negative delta to the user by checking
+against the previous timestamp.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -393,6 +393,11 @@ static void buffer_cb(struct vchiq_mmal_
+ ktime_to_ns(dev->capture.kernel_start_ts),
+ dev->capture.vc_start_timestamp, pts,
+ ktime_to_ns(timestamp));
++ if (timestamp < dev->capture.last_timestamp) {
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "Negative delta - using last time\n");
++ timestamp = dev->capture.last_timestamp;
++ }
+ buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp);
+ } else {
+ if (dev->capture.last_timestamp) {
--- /dev/null
+From 4ae496b855e158789383247cde55591fe9ce4ceb Mon Sep 17 00:00:00 2001
+From: Nathan Chancellor <natechancellor@gmail.com>
+Date: Thu, 27 Sep 2018 17:50:39 -0700
+Subject: [PATCH 254/725] staging: bcm2835-camera: Avoid unneeded internal
+ declaration warning
+
+Clang warns:
+
+drivers/staging/vc04_services/bcm2835-camera/controls.c:59:18: warning:
+variable 'mains_freq_qmenu' is not needed and will not be emitted
+[-Wunneeded-internal-declaration]
+static const s64 mains_freq_qmenu[] = {
+ ^
+1 warning generated.
+
+This is because mains_freq_qmenu is currently only used in an ARRAY_SIZE
+macro, which is a compile time evaluation in this case. Avoid this by
+adding mains_freq_qmenu as the imenu member of this structure, which
+matches all other controls that uses the ARRAY_SIZE macro in v4l2_ctrls.
+This turns out to be a no-op because V4L2_CID_MPEG_VIDEO_BITRATE_MODE is
+defined as a MMAL_CONTROL_TYPE_STD_MENU, which does not pass the imenu
+definition along to v4l2_ctrl_new in bm2835_mmal_init_controls.
+
+Link: https://github.com/ClangBuiltLinux/linux/issues/122
+Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/controls.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -1109,7 +1109,7 @@ static const struct bm2835_mmal_v4l2_ctr
+ {
+ V4L2_CID_POWER_LINE_FREQUENCY, MMAL_CONTROL_TYPE_STD_MENU,
+ 0, ARRAY_SIZE(mains_freq_qmenu) - 1,
+- 1, 1, NULL,
++ 1, 1, mains_freq_qmenu,
+ MMAL_PARAMETER_FLICKER_AVOID,
+ &ctrl_set_flicker_avoidance,
+ false
--- /dev/null
+From 66becb1e25c43817c0f46e401557955d2f763d07 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 16:21:06 +0100
+Subject: [PATCH 255/725] staging: bcm2835-camera: Add multiple inclusion
+ protection to headers
+
+mmal-common.h and mmal-msg.h didn't have the normal
+ifndef FOO / define FOO / endif protection to stop it being
+included multiple times. Add it.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/mmal-common.h | 3 +++
+ drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h | 3 +++
+ 2 files changed, 6 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
+@@ -13,6 +13,8 @@
+ * MMAL structures
+ *
+ */
++#ifndef MMAL_COMMON_H
++#define MMAL_COMMON_H
+
+ #define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
+ #define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l')
+@@ -56,3 +58,4 @@ struct mmal_colourfx {
+ u32 u;
+ u32 v;
+ };
++#endif
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
+@@ -23,6 +23,8 @@
+ * implementation uses fixed size types and not the enums (though the
+ * comments have the actual enum type
+ */
++#ifndef MMAL_MSG_H
++#define MMAL_MSG_H
+
+ #define VC_MMAL_VER 15
+ #define VC_MMAL_MIN_VER 10
+@@ -401,3 +403,4 @@ struct mmal_msg {
+ u8 payload[MMAL_MSG_MAX_PAYLOAD];
+ } u;
+ };
++#endif
+++ /dev/null
-From 06ef8c73a0898576b90db697007bca999acad2fe Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 21 Jun 2018 17:02:14 +0100
-Subject: [PATCH 255/703] staging: bcm2835-camera: Set sequence number
- correctly
-
-Set the sequence number in vb2_v4l2_buffer mainly so the
-latest v4l2-ctl reports the frame rate correctly.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 4 ++++
- drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h | 2 ++
- 2 files changed, 6 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -409,6 +409,7 @@ static void buffer_cb(struct vchiq_mmal_
- }
- }
- dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
-+ buf->vb.sequence = dev->capture.sequence++;
-
- vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
- if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
-@@ -537,6 +538,9 @@ static int start_streaming(struct vb2_qu
- /* enable frame capture */
- dev->capture.frame_count = 1;
-
-+ /* reset sequence number */
-+ dev->capture.sequence = 0;
-+
- /* if the preview is not already running, wait for a few frames for AGC
- * to settle down.
- */
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
-@@ -93,6 +93,8 @@ struct bm2835_mmal_dev {
- ktime_t kernel_start_ts;
- /* Timestamp of last frame */
- u64 last_timestamp;
-+ /* Sequence number of last buffer */
-+ u32 sequence;
-
- struct vchiq_mmal_port *port; /* port being used for capture */
- /* camera port being used for capture */
+++ /dev/null
-From 04224f83b7285caf63afbbc4dab2917118ce6667 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 24 Jul 2018 12:08:29 +0100
-Subject: [PATCH 256/703] staging: bcm2835-camera: Ensure timestamps never go
- backwards.
-
-There is an awkward situation with H264 header bytes. Currently
-they are returned with a PTS of 0 because they aren't associated
-with a timestamped frame to encode. These are handled by either
-returning the timestamp of the last buffer to have been received,
-or in the case of the first buffer the timestamp taken at
-start_streaming.
-This results in a race where the current frame may have started
-before we take the start time, which results in the first encoded
-frame having an earlier timestamp than the header bytes.
-
-Ensure that we never return a negative delta to the user by checking
-against the previous timestamp.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -393,6 +393,11 @@ static void buffer_cb(struct vchiq_mmal_
- ktime_to_ns(dev->capture.kernel_start_ts),
- dev->capture.vc_start_timestamp, pts,
- ktime_to_ns(timestamp));
-+ if (timestamp < dev->capture.last_timestamp) {
-+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-+ "Negative delta - using last time\n");
-+ timestamp = dev->capture.last_timestamp;
-+ }
- buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp);
- } else {
- if (dev->capture.last_timestamp) {
--- /dev/null
+From dc86a3318afa6e113b3094380fdab904d900c90b Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 3 Dec 2018 13:15:20 +0000
+Subject: [PATCH 256/725] staging: bcm2835-camera: Unify header inclusion
+ defines
+
+Most of the headers use ifndef FOO_H, whilst mmal-parameters.h
+used ifndef __FOO_H.
+
+Revise mmal-parameters.h to drop the underscores and make the
+headers all consistent.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-camera/mmal-parameters.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
+@@ -19,8 +19,8 @@
+ * @{
+ */
+
+-#ifndef __MMAL_PARAMETERS_H
+-#define __MMAL_PARAMETERS_H
++#ifndef MMAL_PARAMETERS_H
++#define MMAL_PARAMETERS_H
+
+ /** Common parameter ID group, used with many types of component. */
+ #define MMAL_PARAMETER_GROUP_COMMON (0 << 16)
--- /dev/null
+From 8f2e8949f937462d749e19b28a8208e286caf605 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Oct 2018 15:50:50 +0000
+Subject: [PATCH 257/725] ARM: bcm2835_defconfig: Enable bcm2835-camera
+
+Enables the V4L2 camera driver as a module.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm/configs/bcm2835_defconfig | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/configs/bcm2835_defconfig
++++ b/arch/arm/configs/bcm2835_defconfig
+@@ -91,6 +91,8 @@ CONFIG_THERMAL=y
+ CONFIG_BCM2835_THERMAL=y
+ CONFIG_WATCHDOG=y
+ CONFIG_BCM2835_WDT=y
++CONFIG_MEDIA_SUPPORT=m
++CONFIG_MEDIA_CAMERA_SUPPORT=y
+ CONFIG_DRM=y
+ CONFIG_DRM_VC4=y
+ CONFIG_FB_SIMPLE=y
+@@ -128,7 +130,8 @@ CONFIG_LEDS_TRIGGER_CAMERA=y
+ CONFIG_DMADEVICES=y
+ CONFIG_DMA_BCM2835=y
+ CONFIG_STAGING=y
+-CONFIG_BCM2835_VCHIQ=m
++CONFIG_SND_BCM2835=m
++CONFIG_VIDEO_BCM2835=m
+ CONFIG_MAILBOX=y
+ CONFIG_BCM2835_MBOX=y
+ # CONFIG_IOMMU_SUPPORT is not set
+++ /dev/null
-From bb6d0d223ef1579a13eae3cffc66db9ede83bbd1 Mon Sep 17 00:00:00 2001
-From: Nathan Chancellor <natechancellor@gmail.com>
-Date: Thu, 27 Sep 2018 17:50:39 -0700
-Subject: [PATCH 257/703] staging: bcm2835-camera: Avoid unneeded internal
- declaration warning
-
-Clang warns:
-
-drivers/staging/vc04_services/bcm2835-camera/controls.c:59:18: warning:
-variable 'mains_freq_qmenu' is not needed and will not be emitted
-[-Wunneeded-internal-declaration]
-static const s64 mains_freq_qmenu[] = {
- ^
-1 warning generated.
-
-This is because mains_freq_qmenu is currently only used in an ARRAY_SIZE
-macro, which is a compile time evaluation in this case. Avoid this by
-adding mains_freq_qmenu as the imenu member of this structure, which
-matches all other controls that uses the ARRAY_SIZE macro in v4l2_ctrls.
-This turns out to be a no-op because V4L2_CID_MPEG_VIDEO_BITRATE_MODE is
-defined as a MMAL_CONTROL_TYPE_STD_MENU, which does not pass the imenu
-definition along to v4l2_ctrl_new in bm2835_mmal_init_controls.
-
-Link: https://github.com/ClangBuiltLinux/linux/issues/122
-Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-camera/controls.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -1109,7 +1109,7 @@ static const struct bm2835_mmal_v4l2_ctr
- {
- V4L2_CID_POWER_LINE_FREQUENCY, MMAL_CONTROL_TYPE_STD_MENU,
- 0, ARRAY_SIZE(mains_freq_qmenu) - 1,
-- 1, 1, NULL,
-+ 1, 1, mains_freq_qmenu,
- MMAL_PARAMETER_FLICKER_AVOID,
- &ctrl_set_flicker_avoidance,
- false
+++ /dev/null
-From 74a68a4cabb8dc516c6d1a9860043b9285d4f661 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Sep 2018 16:21:06 +0100
-Subject: [PATCH 258/703] staging: bcm2835-camera: Add multiple inclusion
- protection to headers
-
-mmal-common.h and mmal-msg.h didn't have the normal
-ifndef FOO / define FOO / endif protection to stop it being
-included multiple times. Add it.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/bcm2835-camera/mmal-common.h | 3 +++
- drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h | 3 +++
- 2 files changed, 6 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
-@@ -13,6 +13,8 @@
- * MMAL structures
- *
- */
-+#ifndef MMAL_COMMON_H
-+#define MMAL_COMMON_H
-
- #define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
- #define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l')
-@@ -56,3 +58,4 @@ struct mmal_colourfx {
- u32 u;
- u32 v;
- };
-+#endif
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
-@@ -23,6 +23,8 @@
- * implementation uses fixed size types and not the enums (though the
- * comments have the actual enum type
- */
-+#ifndef MMAL_MSG_H
-+#define MMAL_MSG_H
-
- #define VC_MMAL_VER 15
- #define VC_MMAL_MIN_VER 10
-@@ -401,3 +403,4 @@ struct mmal_msg {
- u8 payload[MMAL_MSG_MAX_PAYLOAD];
- } u;
- };
-+#endif
--- /dev/null
+From d8c77a920cd800c375e1040f61ed15ec53219c1c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Oct 2018 15:55:42 +0000
+Subject: [PATCH 258/725] staging: bcm2835-camera: Fix alignment should match
+ open parenthesis
+
+Fix up checkpatch "Alignment should match open parenthesis" errors
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -1934,7 +1934,7 @@ static int bcm2835_mmal_probe(struct pla
+ ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler);
+ if (ret < 0) {
+ v4l2_err(&dev->v4l2_dev, "%s: could not init controls: %d\n",
+- __func__, ret);
++ __func__, ret);
+ goto unreg_dev;
+ }
+ dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler;
+@@ -1944,7 +1944,7 @@ static int bcm2835_mmal_probe(struct pla
+ ret = mmal_init(dev);
+ if (ret < 0) {
+ v4l2_err(&dev->v4l2_dev, "%s: mmal init failed: %d\n",
+- __func__, ret);
++ __func__, ret);
+ goto unreg_dev;
+ }
+ /* initialize queue */
+@@ -1966,7 +1966,7 @@ static int bcm2835_mmal_probe(struct pla
+ ret = bm2835_mmal_init_device(dev, &dev->vdev);
+ if (ret < 0) {
+ v4l2_err(&dev->v4l2_dev, "%s: could not init device: %d\n",
+- __func__, ret);
++ __func__, ret);
+ goto unreg_dev;
+ }
+
+@@ -1976,7 +1976,7 @@ static int bcm2835_mmal_probe(struct pla
+ ret = mmal_setup_components(dev, &default_v4l2_format);
+ if (ret < 0) {
+ v4l2_err(&dev->v4l2_dev, "%s: could not setup components: %d\n",
+- __func__, ret);
++ __func__, ret);
+ goto unreg_dev;
+ }
+
--- /dev/null
+From 816336e4081a5180c5b8524b2839e31f43a5ddf8 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Oct 2018 15:58:14 +0000
+Subject: [PATCH 259/725] staging: bcm2835-camera: Fix multiple assignments
+ should be avoided
+
+Clear checkpatch complaints of "multiple assignments should be avoided"
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -1065,11 +1065,12 @@ static int mmal_setup_components(struct
+ /* 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 =
++ camera_port =
+ &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO];
+ else
+- camera_port = port =
++ camera_port =
+ &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
++ port = camera_port;
+ break;
+ case COMP_IMAGE_ENCODE:
+ encode_component = dev->component[COMP_IMAGE_ENCODE];
+++ /dev/null
-From 8e7b28ae807a4f727ea9a1232705b2bdb6752c1f Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 3 Dec 2018 13:15:20 +0000
-Subject: [PATCH 259/703] staging: bcm2835-camera: Unify header inclusion
- defines
-
-Most of the headers use ifndef FOO_H, whilst mmal-parameters.h
-used ifndef __FOO_H.
-
-Revise mmal-parameters.h to drop the underscores and make the
-headers all consistent.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/bcm2835-camera/mmal-parameters.h | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
-@@ -19,8 +19,8 @@
- * @{
- */
-
--#ifndef __MMAL_PARAMETERS_H
--#define __MMAL_PARAMETERS_H
-+#ifndef MMAL_PARAMETERS_H
-+#define MMAL_PARAMETERS_H
-
- /** Common parameter ID group, used with many types of component. */
- #define MMAL_PARAMETER_GROUP_COMMON (0 << 16)
+++ /dev/null
-From 62b19c662d048c575fc9aef23560f31f4d72767b Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Oct 2018 15:50:50 +0000
-Subject: [PATCH 260/703] ARM: bcm2835_defconfig: Enable bcm2835-camera
-
-Enables the V4L2 camera driver as a module.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm/configs/bcm2835_defconfig | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
---- a/arch/arm/configs/bcm2835_defconfig
-+++ b/arch/arm/configs/bcm2835_defconfig
-@@ -91,6 +91,8 @@ CONFIG_THERMAL=y
- CONFIG_BCM2835_THERMAL=y
- CONFIG_WATCHDOG=y
- CONFIG_BCM2835_WDT=y
-+CONFIG_MEDIA_SUPPORT=m
-+CONFIG_MEDIA_CAMERA_SUPPORT=y
- CONFIG_DRM=y
- CONFIG_DRM_VC4=y
- CONFIG_FB_SIMPLE=y
-@@ -128,7 +130,8 @@ CONFIG_LEDS_TRIGGER_CAMERA=y
- CONFIG_DMADEVICES=y
- CONFIG_DMA_BCM2835=y
- CONFIG_STAGING=y
--CONFIG_BCM2835_VCHIQ=m
-+CONFIG_SND_BCM2835=m
-+CONFIG_VIDEO_BCM2835=m
- CONFIG_MAILBOX=y
- CONFIG_BCM2835_MBOX=y
- # CONFIG_IOMMU_SUPPORT is not set
--- /dev/null
+From 2af5efec3dd9186edee08f14dffcee638955c909 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Oct 2018 16:08:41 +0000
+Subject: [PATCH 260/725] staging: bcm2835-camera: Fix up all formatting in
+ mmal-paramters.h
+
+Fixes up all checkpatch errors in mmal-parameters.h
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-camera/mmal-parameters.h | 273 +++++++++++-------
+ 1 file changed, 165 insertions(+), 108 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
+@@ -23,148 +23,204 @@
+ #define MMAL_PARAMETERS_H
+
+ /** Common parameter ID group, used with many types of component. */
+-#define MMAL_PARAMETER_GROUP_COMMON (0 << 16)
++#define MMAL_PARAMETER_GROUP_COMMON (0 << 16)
+ /** Camera-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_CAMERA (1 << 16)
++#define MMAL_PARAMETER_GROUP_CAMERA (1 << 16)
+ /** Video-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_VIDEO (2 << 16)
++#define MMAL_PARAMETER_GROUP_VIDEO (2 << 16)
+ /** Audio-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_AUDIO (3 << 16)
++#define MMAL_PARAMETER_GROUP_AUDIO (3 << 16)
+ /** Clock-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_CLOCK (4 << 16)
++#define MMAL_PARAMETER_GROUP_CLOCK (4 << 16)
+ /** Miracast-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_MIRACAST (5 << 16)
++#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 */
++ /**< Never a valid parameter ID */
++ MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON,
+
+- /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
++ /**< MMAL_PARAMETER_ENCODING_T */
++ MMAL_PARAMETER_SUPPORTED_ENCODINGS,
++ /**< MMAL_PARAMETER_URI_T */
++ MMAL_PARAMETER_URI,
++ /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
+ MMAL_PARAMETER_CHANGE_EVENT_REQUEST,
+-
+- /** MMAL_PARAMETER_BOOLEAN_T */
++ /** MMAL_PARAMETER_BOOLEAN_T */
+ MMAL_PARAMETER_ZERO_COPY,
+-
+- /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
++ /**< 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 */
++ /**< MMAL_PARAMETER_STATISTICS_T */
++ MMAL_PARAMETER_STATISTICS,
++ /**< MMAL_PARAMETER_CORE_STATISTICS_T */
++ MMAL_PARAMETER_CORE_STATISTICS,
++ /**< MMAL_PARAMETER_MEM_USAGE_T */
++ MMAL_PARAMETER_MEM_USAGE,
++ /**< MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_BUFFER_FLAG_FILTER,
++ /**< MMAL_PARAMETER_SEEK_T */
++ MMAL_PARAMETER_SEEK,
++ /**< MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_POWERMON_ENABLE,
++ /**< MMAL_PARAMETER_LOGGING_T */
++ MMAL_PARAMETER_LOGGING,
++ /**< MMAL_PARAMETER_UINT64_T */
++ MMAL_PARAMETER_SYSTEM_TIME,
++ /**< MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_NO_IMAGE_PADDING,
+ };
+
+ /* 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 */
++ /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
++ MMAL_PARAMETER_THUMBNAIL_CONFIGURATION =
++ MMAL_PARAMETER_GROUP_CAMERA,
++ /**< Unused? */
++ MMAL_PARAMETER_CAPTURE_QUALITY,
++ /**< @ref MMAL_PARAMETER_INT32_T */
++ MMAL_PARAMETER_ROTATION,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_EXIF_DISABLE,
++ /**< @ref MMAL_PARAMETER_EXIF_T */
++ MMAL_PARAMETER_EXIF,
++ /**< @ref MMAL_PARAM_AWBMODE_T */
++ MMAL_PARAMETER_AWB_MODE,
++ /**< @ref MMAL_PARAMETER_IMAGEFX_T */
++ MMAL_PARAMETER_IMAGE_EFFECT,
++ /**< @ref MMAL_PARAMETER_COLOURFX_T */
++ MMAL_PARAMETER_COLOUR_EFFECT,
++ /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
++ MMAL_PARAMETER_FLICKER_AVOID,
++ /**< @ref MMAL_PARAMETER_FLASH_T */
++ MMAL_PARAMETER_FLASH,
++ /**< @ref MMAL_PARAMETER_REDEYE_T */
++ MMAL_PARAMETER_REDEYE,
++ /**< @ref MMAL_PARAMETER_FOCUS_T */
++ MMAL_PARAMETER_FOCUS,
++ /**< Unused? */
++ MMAL_PARAMETER_FOCAL_LENGTHS,
++ /**< @ref MMAL_PARAMETER_INT32_T */
++ MMAL_PARAMETER_EXPOSURE_COMP,
++ /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
++ MMAL_PARAMETER_ZOOM,
++ /**< @ref MMAL_PARAMETER_MIRROR_T */
++ MMAL_PARAMETER_MIRROR,
+
+ /* 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 */
++ /**< @ref MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_CAMERA_NUM,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_CAPTURE,
++ /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
++ MMAL_PARAMETER_EXPOSURE_MODE,
++ /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
++ MMAL_PARAMETER_EXP_METERING_MODE,
++ /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
++ MMAL_PARAMETER_FOCUS_STATUS,
++ /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
++ MMAL_PARAMETER_CAMERA_CONFIG,
++ /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
++ MMAL_PARAMETER_CAPTURE_STATUS,
++ /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
++ MMAL_PARAMETER_FACE_TRACK,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
++ /**< @ref MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_JPEG_Q_FACTOR,
++ /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
++ MMAL_PARAMETER_FRAME_RATE,
++ /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
++ MMAL_PARAMETER_USE_STC,
++ /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
++ MMAL_PARAMETER_CAMERA_INFO,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_VIDEO_STABILISATION,
++ /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
++ MMAL_PARAMETER_FACE_TRACK_RESULTS,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_ENABLE_RAW_CAPTURE,
+
+ /* 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 */
++ /**< @ref MMAL_PARAMETER_URI_T */
++ MMAL_PARAMETER_DPF_FILE,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_ENABLE_DPF_FILE,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
++ /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
++ MMAL_PARAMETER_CAPTURE_MODE,
++ /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
++ MMAL_PARAMETER_FOCUS_REGIONS,
++ /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
++ MMAL_PARAMETER_INPUT_CROP,
++ /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
++ MMAL_PARAMETER_SENSOR_INFORMATION,
++ /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
++ MMAL_PARAMETER_FLASH_SELECT,
++ /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
++ MMAL_PARAMETER_FIELD_OF_VIEW,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
++ /**< @ref MMAL_PARAMETER_DRC_T */
++ MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,
++ /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
++ MMAL_PARAMETER_ALGORITHM_CONTROL,
++ /**< @ref MMAL_PARAMETER_RATIONAL_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,
+
+ /* 0x30 */
+- MMAL_PARAMETER_ISO, /**< @ref MMAL_PARAMETER_UINT32_T */
+- MMAL_PARAMETER_ANTISHAKE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-
+- /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
++ /**< @ref MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_ISO,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_ANTISHAKE,
++ /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
+ MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
+-
+- /** @ref MMAL_PARAMETER_BOOLEAN_T */
++ /** @ref MMAL_PARAMETER_BOOLEAN_T */
+ MMAL_PARAMETER_CAMERA_BURST_CAPTURE,
+-
+- /** @ref MMAL_PARAMETER_UINT32_T */
++ /** @ref MMAL_PARAMETER_UINT32_T */
+ MMAL_PARAMETER_CAMERA_MIN_ISO,
+-
+- /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
++ /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
+ MMAL_PARAMETER_CAMERA_USE_CASE,
+-
+- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+ MMAL_PARAMETER_CAPTURE_STATS_PASS,
+-
+- /** @ref MMAL_PARAMETER_UINT32_T */
++ /** @ref MMAL_PARAMETER_UINT32_T */
+ MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG,
+-
+- /** @ref MMAL_PARAMETER_BOOLEAN_T */
++ /** @ref MMAL_PARAMETER_BOOLEAN_T */
+ MMAL_PARAMETER_ENABLE_REGISTER_FILE,
+-
+- /** @ref MMAL_PARAMETER_BOOLEAN_T */
++ /** @ref MMAL_PARAMETER_BOOLEAN_T */
+ MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL,
+-
+- /** @ref MMAL_PARAMETER_CONFIGFILE_T */
++ /** @ref MMAL_PARAMETER_CONFIGFILE_T */
+ MMAL_PARAMETER_CONFIGFILE_REGISTERS,
+-
+- /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
++ /** @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 */
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_JPEG_ATTACH_LOG,
++ /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
++ MMAL_PARAMETER_ZERO_SHUTTER_LAG,
++ /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
++ MMAL_PARAMETER_FPS_RANGE,
++ /**< @ref MMAL_PARAMETER_INT32_T */
++ MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP,
+
+ /* 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 */
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_SW_SHARPEN_DISABLE,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_FLASH_REQUIRED,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_SW_SATURATION_DISABLE,
++ /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_SHUTTER_SPEED,
++ /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
++ MMAL_PARAMETER_CUSTOM_AWB_GAINS,
+ };
+
+ struct mmal_parameter_rational {
+@@ -411,7 +467,8 @@ enum mmal_parameter_video_type {
+ MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
+
+ /** @ref MMAL_PARAMETER_UINT32_T.
+- * Setting the value to zero resets to the default (one slice per frame).
++ * Setting the value to zero resets to the default (one slice per
++ * frame).
+ */
+ MMAL_PARAMETER_MB_ROWS_PER_SLICE,
+
+++ /dev/null
-From eef1625f7bbf1d7073860159fb9317725cd680dc Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Oct 2018 15:55:42 +0000
-Subject: [PATCH 261/703] staging: bcm2835-camera: Fix alignment should match
- open parenthesis
-
-Fix up checkpatch "Alignment should match open parenthesis" errors
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -1934,7 +1934,7 @@ static int bcm2835_mmal_probe(struct pla
- ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler);
- if (ret < 0) {
- v4l2_err(&dev->v4l2_dev, "%s: could not init controls: %d\n",
-- __func__, ret);
-+ __func__, ret);
- goto unreg_dev;
- }
- dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler;
-@@ -1944,7 +1944,7 @@ static int bcm2835_mmal_probe(struct pla
- ret = mmal_init(dev);
- if (ret < 0) {
- v4l2_err(&dev->v4l2_dev, "%s: mmal init failed: %d\n",
-- __func__, ret);
-+ __func__, ret);
- goto unreg_dev;
- }
- /* initialize queue */
-@@ -1966,7 +1966,7 @@ static int bcm2835_mmal_probe(struct pla
- ret = bm2835_mmal_init_device(dev, &dev->vdev);
- if (ret < 0) {
- v4l2_err(&dev->v4l2_dev, "%s: could not init device: %d\n",
-- __func__, ret);
-+ __func__, ret);
- goto unreg_dev;
- }
-
-@@ -1976,7 +1976,7 @@ static int bcm2835_mmal_probe(struct pla
- ret = mmal_setup_components(dev, &default_v4l2_format);
- if (ret < 0) {
- v4l2_err(&dev->v4l2_dev, "%s: could not setup components: %d\n",
-- __func__, ret);
-+ __func__, ret);
- goto unreg_dev;
- }
-
--- /dev/null
+From 8d81b25c2bdc73f4d5d0985c0ec8e2d19f181768 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 28 Sep 2018 10:17:11 +0100
+Subject: [PATCH 261/725] staging: bcm2835-camera: Use enums for max value in
+ controls
+
+Controls of type MMAL_CONTROL_TYPE_STD_MENU call v4l2_ctrl_new_std_menu
+with a max value and a mask. The max value is one of the defined
+values for the control, however in the config array there are several
+entries where raw numbers have been used instead. Replace these
+with the appropriate enum.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-camera/controls.c | 37 +++++++------------
+ 1 file changed, 13 insertions(+), 24 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -58,19 +58,6 @@ 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,
+@@ -966,8 +953,8 @@ static const struct bm2835_mmal_v4l2_ctr
+ },
+ {
+ V4L2_CID_ISO_SENSITIVITY_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
+- 0, 1, V4L2_ISO_SENSITIVITY_AUTO, 1, NULL,
+- MMAL_PARAMETER_ISO,
++ 0, V4L2_ISO_SENSITIVITY_AUTO, V4L2_ISO_SENSITIVITY_AUTO, 1,
++ NULL, MMAL_PARAMETER_ISO,
+ &ctrl_set_iso,
+ false
+ },
+@@ -984,8 +971,8 @@ static const struct bm2835_mmal_v4l2_ctr
+ */
+ {
+ V4L2_CID_EXPOSURE_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
+- ~0x03, 3, V4L2_EXPOSURE_AUTO, 0, NULL,
+- MMAL_PARAMETER_EXPOSURE_MODE,
++ ~0x03, V4L2_EXPOSURE_APERTURE_PRIORITY, V4L2_EXPOSURE_AUTO, 0,
++ NULL, MMAL_PARAMETER_EXPOSURE_MODE,
+ &ctrl_set_exposure,
+ false
+ },
+@@ -1021,7 +1008,8 @@ static const struct bm2835_mmal_v4l2_ctr
+ {
+ V4L2_CID_EXPOSURE_METERING,
+ MMAL_CONTROL_TYPE_STD_MENU,
+- ~0x7, 2, V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL,
++ ~0x7, V4L2_EXPOSURE_METERING_SPOT,
++ V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL,
+ MMAL_PARAMETER_EXP_METERING_MODE,
+ &ctrl_set_metering_mode,
+ false
+@@ -1029,7 +1017,8 @@ static const struct bm2835_mmal_v4l2_ctr
+ {
+ V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
+ MMAL_CONTROL_TYPE_STD_MENU,
+- ~0x3ff, 9, V4L2_WHITE_BALANCE_AUTO, 0, NULL,
++ ~0x3ff, V4L2_WHITE_BALANCE_SHADE, V4L2_WHITE_BALANCE_AUTO, 0,
++ NULL,
+ MMAL_PARAMETER_AWB_MODE,
+ &ctrl_set_awb_mode,
+ false
+@@ -1050,7 +1039,7 @@ static const struct bm2835_mmal_v4l2_ctr
+ },
+ {
+ V4L2_CID_COLORFX, MMAL_CONTROL_TYPE_STD_MENU,
+- 0, 15, V4L2_COLORFX_NONE, 0, NULL,
++ 0, V4L2_COLORFX_SET_CBCR, V4L2_COLORFX_NONE, 0, NULL,
+ MMAL_PARAMETER_IMAGE_EFFECT,
+ &ctrl_set_image_effect,
+ false
+@@ -1085,8 +1074,8 @@ static const struct bm2835_mmal_v4l2_ctr
+ },
+ {
+ V4L2_CID_MPEG_VIDEO_BITRATE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
+- 0, ARRAY_SIZE(bitrate_mode_qmenu) - 1,
+- 0, 0, bitrate_mode_qmenu,
++ 0, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
++ 0, 0, NULL,
+ MMAL_PARAMETER_RATECONTROL,
+ &ctrl_set_bitrate_mode,
+ false
+@@ -1108,8 +1097,8 @@ static const struct bm2835_mmal_v4l2_ctr
+ },
+ {
+ V4L2_CID_POWER_LINE_FREQUENCY, MMAL_CONTROL_TYPE_STD_MENU,
+- 0, ARRAY_SIZE(mains_freq_qmenu) - 1,
+- 1, 1, mains_freq_qmenu,
++ 0, V4L2_CID_POWER_LINE_FREQUENCY_AUTO,
++ 1, 1, NULL,
+ MMAL_PARAMETER_FLICKER_AVOID,
+ &ctrl_set_flicker_avoidance,
+ false
--- /dev/null
+From d0b848e7dde7eb67abd7cd14a2746ee09ffcfacb Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 8 Oct 2018 18:26:15 +0100
+Subject: [PATCH 262/725] staging: bcm2835-camera: Correct
+ V4L2_CID_COLORFX_CBCR behaviour
+
+With V4L2_CID_COLORFX_CBCR calling ctrl_set_colfx it was incorrectly
+assigning the colour values to the enable field of dev->colourfx
+instead of the u and v fields.
+
+Correct the assignments.
+
+Reported as a Coverity issue
+Detected by CoverityScan CID#1419711 ("Unused value")
+
+Reported-by: Colin Ian King <colin.king@canonical.com>
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/controls.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -578,8 +578,8 @@ static int ctrl_set_colfx(struct bm2835_
+
+ control = &dev->component[COMP_CAMERA]->control;
+
+- dev->colourfx.enable = (ctrl->val & 0xff00) >> 8;
+- dev->colourfx.enable = ctrl->val & 0xff;
++ dev->colourfx.u = (ctrl->val & 0xff00) >> 8;
++ dev->colourfx.v = ctrl->val & 0xff;
+
+ ret = vchiq_mmal_port_parameter_set(dev->instance, control,
+ MMAL_PARAMETER_COLOUR_EFFECT,
+++ /dev/null
-From 39d27efce4fe6c36ae65c34b73ff1024ec4fbf0e Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Oct 2018 15:58:14 +0000
-Subject: [PATCH 262/703] staging: bcm2835-camera: Fix multiple assignments
- should be avoided
-
-Clear checkpatch complaints of "multiple assignments should be avoided"
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -1065,11 +1065,12 @@ static int mmal_setup_components(struct
- /* 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 =
-+ camera_port =
- &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO];
- else
-- camera_port = port =
-+ camera_port =
- &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
-+ port = camera_port;
- break;
- case COMP_IMAGE_ENCODE:
- encode_component = dev->component[COMP_IMAGE_ENCODE];
+++ /dev/null
-From 9ae2700167c495dba01b1625ab62e407b660c86c Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Oct 2018 16:08:41 +0000
-Subject: [PATCH 263/703] staging: bcm2835-camera: Fix up all formatting in
- mmal-paramters.h
-
-Fixes up all checkpatch errors in mmal-parameters.h
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-camera/mmal-parameters.h | 273 +++++++++++-------
- 1 file changed, 165 insertions(+), 108 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
-+++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
-@@ -23,148 +23,204 @@
- #define MMAL_PARAMETERS_H
-
- /** Common parameter ID group, used with many types of component. */
--#define MMAL_PARAMETER_GROUP_COMMON (0 << 16)
-+#define MMAL_PARAMETER_GROUP_COMMON (0 << 16)
- /** Camera-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_CAMERA (1 << 16)
-+#define MMAL_PARAMETER_GROUP_CAMERA (1 << 16)
- /** Video-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_VIDEO (2 << 16)
-+#define MMAL_PARAMETER_GROUP_VIDEO (2 << 16)
- /** Audio-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_AUDIO (3 << 16)
-+#define MMAL_PARAMETER_GROUP_AUDIO (3 << 16)
- /** Clock-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_CLOCK (4 << 16)
-+#define MMAL_PARAMETER_GROUP_CLOCK (4 << 16)
- /** Miracast-specific parameter ID group. */
--#define MMAL_PARAMETER_GROUP_MIRACAST (5 << 16)
-+#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 */
-+ /**< Never a valid parameter ID */
-+ MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON,
-
-- /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
-+ /**< MMAL_PARAMETER_ENCODING_T */
-+ MMAL_PARAMETER_SUPPORTED_ENCODINGS,
-+ /**< MMAL_PARAMETER_URI_T */
-+ MMAL_PARAMETER_URI,
-+ /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
- MMAL_PARAMETER_CHANGE_EVENT_REQUEST,
--
-- /** MMAL_PARAMETER_BOOLEAN_T */
-+ /** MMAL_PARAMETER_BOOLEAN_T */
- MMAL_PARAMETER_ZERO_COPY,
--
-- /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
-+ /**< 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 */
-+ /**< MMAL_PARAMETER_STATISTICS_T */
-+ MMAL_PARAMETER_STATISTICS,
-+ /**< MMAL_PARAMETER_CORE_STATISTICS_T */
-+ MMAL_PARAMETER_CORE_STATISTICS,
-+ /**< MMAL_PARAMETER_MEM_USAGE_T */
-+ MMAL_PARAMETER_MEM_USAGE,
-+ /**< MMAL_PARAMETER_UINT32_T */
-+ MMAL_PARAMETER_BUFFER_FLAG_FILTER,
-+ /**< MMAL_PARAMETER_SEEK_T */
-+ MMAL_PARAMETER_SEEK,
-+ /**< MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_POWERMON_ENABLE,
-+ /**< MMAL_PARAMETER_LOGGING_T */
-+ MMAL_PARAMETER_LOGGING,
-+ /**< MMAL_PARAMETER_UINT64_T */
-+ MMAL_PARAMETER_SYSTEM_TIME,
-+ /**< MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_NO_IMAGE_PADDING,
- };
-
- /* 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 */
-+ /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
-+ MMAL_PARAMETER_THUMBNAIL_CONFIGURATION =
-+ MMAL_PARAMETER_GROUP_CAMERA,
-+ /**< Unused? */
-+ MMAL_PARAMETER_CAPTURE_QUALITY,
-+ /**< @ref MMAL_PARAMETER_INT32_T */
-+ MMAL_PARAMETER_ROTATION,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_EXIF_DISABLE,
-+ /**< @ref MMAL_PARAMETER_EXIF_T */
-+ MMAL_PARAMETER_EXIF,
-+ /**< @ref MMAL_PARAM_AWBMODE_T */
-+ MMAL_PARAMETER_AWB_MODE,
-+ /**< @ref MMAL_PARAMETER_IMAGEFX_T */
-+ MMAL_PARAMETER_IMAGE_EFFECT,
-+ /**< @ref MMAL_PARAMETER_COLOURFX_T */
-+ MMAL_PARAMETER_COLOUR_EFFECT,
-+ /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
-+ MMAL_PARAMETER_FLICKER_AVOID,
-+ /**< @ref MMAL_PARAMETER_FLASH_T */
-+ MMAL_PARAMETER_FLASH,
-+ /**< @ref MMAL_PARAMETER_REDEYE_T */
-+ MMAL_PARAMETER_REDEYE,
-+ /**< @ref MMAL_PARAMETER_FOCUS_T */
-+ MMAL_PARAMETER_FOCUS,
-+ /**< Unused? */
-+ MMAL_PARAMETER_FOCAL_LENGTHS,
-+ /**< @ref MMAL_PARAMETER_INT32_T */
-+ MMAL_PARAMETER_EXPOSURE_COMP,
-+ /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
-+ MMAL_PARAMETER_ZOOM,
-+ /**< @ref MMAL_PARAMETER_MIRROR_T */
-+ MMAL_PARAMETER_MIRROR,
-
- /* 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 */
-+ /**< @ref MMAL_PARAMETER_UINT32_T */
-+ MMAL_PARAMETER_CAMERA_NUM,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_CAPTURE,
-+ /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
-+ MMAL_PARAMETER_EXPOSURE_MODE,
-+ /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
-+ MMAL_PARAMETER_EXP_METERING_MODE,
-+ /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
-+ MMAL_PARAMETER_FOCUS_STATUS,
-+ /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
-+ MMAL_PARAMETER_CAMERA_CONFIG,
-+ /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
-+ MMAL_PARAMETER_CAPTURE_STATUS,
-+ /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
-+ MMAL_PARAMETER_FACE_TRACK,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
-+ /**< @ref MMAL_PARAMETER_UINT32_T */
-+ MMAL_PARAMETER_JPEG_Q_FACTOR,
-+ /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
-+ MMAL_PARAMETER_FRAME_RATE,
-+ /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
-+ MMAL_PARAMETER_USE_STC,
-+ /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
-+ MMAL_PARAMETER_CAMERA_INFO,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_VIDEO_STABILISATION,
-+ /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
-+ MMAL_PARAMETER_FACE_TRACK_RESULTS,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_ENABLE_RAW_CAPTURE,
-
- /* 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 */
-+ /**< @ref MMAL_PARAMETER_URI_T */
-+ MMAL_PARAMETER_DPF_FILE,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_ENABLE_DPF_FILE,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
-+ /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
-+ MMAL_PARAMETER_CAPTURE_MODE,
-+ /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
-+ MMAL_PARAMETER_FOCUS_REGIONS,
-+ /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
-+ MMAL_PARAMETER_INPUT_CROP,
-+ /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
-+ MMAL_PARAMETER_SENSOR_INFORMATION,
-+ /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
-+ MMAL_PARAMETER_FLASH_SELECT,
-+ /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
-+ MMAL_PARAMETER_FIELD_OF_VIEW,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
-+ /**< @ref MMAL_PARAMETER_DRC_T */
-+ MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,
-+ /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
-+ MMAL_PARAMETER_ALGORITHM_CONTROL,
-+ /**< @ref MMAL_PARAMETER_RATIONAL_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,
-
- /* 0x30 */
-- MMAL_PARAMETER_ISO, /**< @ref MMAL_PARAMETER_UINT32_T */
-- MMAL_PARAMETER_ANTISHAKE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
--
-- /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
-+ /**< @ref MMAL_PARAMETER_UINT32_T */
-+ MMAL_PARAMETER_ISO,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_ANTISHAKE,
-+ /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
- MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
--
-- /** @ref MMAL_PARAMETER_BOOLEAN_T */
-+ /** @ref MMAL_PARAMETER_BOOLEAN_T */
- MMAL_PARAMETER_CAMERA_BURST_CAPTURE,
--
-- /** @ref MMAL_PARAMETER_UINT32_T */
-+ /** @ref MMAL_PARAMETER_UINT32_T */
- MMAL_PARAMETER_CAMERA_MIN_ISO,
--
-- /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
-+ /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
- MMAL_PARAMETER_CAMERA_USE_CASE,
--
-- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
- MMAL_PARAMETER_CAPTURE_STATS_PASS,
--
-- /** @ref MMAL_PARAMETER_UINT32_T */
-+ /** @ref MMAL_PARAMETER_UINT32_T */
- MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG,
--
-- /** @ref MMAL_PARAMETER_BOOLEAN_T */
-+ /** @ref MMAL_PARAMETER_BOOLEAN_T */
- MMAL_PARAMETER_ENABLE_REGISTER_FILE,
--
-- /** @ref MMAL_PARAMETER_BOOLEAN_T */
-+ /** @ref MMAL_PARAMETER_BOOLEAN_T */
- MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL,
--
-- /** @ref MMAL_PARAMETER_CONFIGFILE_T */
-+ /** @ref MMAL_PARAMETER_CONFIGFILE_T */
- MMAL_PARAMETER_CONFIGFILE_REGISTERS,
--
-- /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
-+ /** @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 */
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_JPEG_ATTACH_LOG,
-+ /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
-+ MMAL_PARAMETER_ZERO_SHUTTER_LAG,
-+ /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
-+ MMAL_PARAMETER_FPS_RANGE,
-+ /**< @ref MMAL_PARAMETER_INT32_T */
-+ MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP,
-
- /* 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 */
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_SW_SHARPEN_DISABLE,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_FLASH_REQUIRED,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_SW_SATURATION_DISABLE,
-+ /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
-+ MMAL_PARAMETER_SHUTTER_SPEED,
-+ /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
-+ MMAL_PARAMETER_CUSTOM_AWB_GAINS,
- };
-
- struct mmal_parameter_rational {
-@@ -411,7 +467,8 @@ enum mmal_parameter_video_type {
- MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
-
- /** @ref MMAL_PARAMETER_UINT32_T.
-- * Setting the value to zero resets to the default (one slice per frame).
-+ * Setting the value to zero resets to the default (one slice per
-+ * frame).
- */
- MMAL_PARAMETER_MB_ROWS_PER_SLICE,
-
--- /dev/null
+From f214d9ca66942c23a839e5ba54524fa39a8e08b1 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 28 Sep 2018 10:22:26 +0100
+Subject: [PATCH 263/725] staging: bcm2835-camera: Remove/amend some obsolete
+ comments
+
+Remove a todo which has been done.
+Remove a template line that was redundant.
+Make a comment clearer as to the non-obvious meaning of a field.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-camera/controls.c | 11 +----------
+ 1 file changed, 1 insertion(+), 10 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -965,10 +965,6 @@ static const struct bm2835_mmal_v4l2_ctr
+ &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, V4L2_EXPOSURE_APERTURE_PRIORITY, V4L2_EXPOSURE_AUTO, 0,
+@@ -976,11 +972,6 @@ static const struct bm2835_mmal_v4l2_ctr
+ &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 */
+@@ -1146,7 +1137,7 @@ static const struct bm2835_mmal_v4l2_ctr
+ },
+ {
+ V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
+- -1, /* Min is computed at runtime */
++ -1, /* Min (mask) is computed at runtime */
+ V4L2_SCENE_MODE_TEXT,
+ V4L2_SCENE_MODE_NONE, 1, NULL,
+ MMAL_PARAMETER_PROFILE,
+++ /dev/null
-From cbfd21871e5882f8ffa73a7b5c96018409b683ea Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 28 Sep 2018 10:17:11 +0100
-Subject: [PATCH 264/703] staging: bcm2835-camera: Use enums for max value in
- controls
-
-Controls of type MMAL_CONTROL_TYPE_STD_MENU call v4l2_ctrl_new_std_menu
-with a max value and a mask. The max value is one of the defined
-values for the control, however in the config array there are several
-entries where raw numbers have been used instead. Replace these
-with the appropriate enum.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-camera/controls.c | 37 +++++++------------
- 1 file changed, 13 insertions(+), 24 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -58,19 +58,6 @@ 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,
-@@ -966,8 +953,8 @@ static const struct bm2835_mmal_v4l2_ctr
- },
- {
- V4L2_CID_ISO_SENSITIVITY_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
-- 0, 1, V4L2_ISO_SENSITIVITY_AUTO, 1, NULL,
-- MMAL_PARAMETER_ISO,
-+ 0, V4L2_ISO_SENSITIVITY_AUTO, V4L2_ISO_SENSITIVITY_AUTO, 1,
-+ NULL, MMAL_PARAMETER_ISO,
- &ctrl_set_iso,
- false
- },
-@@ -984,8 +971,8 @@ static const struct bm2835_mmal_v4l2_ctr
- */
- {
- V4L2_CID_EXPOSURE_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
-- ~0x03, 3, V4L2_EXPOSURE_AUTO, 0, NULL,
-- MMAL_PARAMETER_EXPOSURE_MODE,
-+ ~0x03, V4L2_EXPOSURE_APERTURE_PRIORITY, V4L2_EXPOSURE_AUTO, 0,
-+ NULL, MMAL_PARAMETER_EXPOSURE_MODE,
- &ctrl_set_exposure,
- false
- },
-@@ -1021,7 +1008,8 @@ static const struct bm2835_mmal_v4l2_ctr
- {
- V4L2_CID_EXPOSURE_METERING,
- MMAL_CONTROL_TYPE_STD_MENU,
-- ~0x7, 2, V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL,
-+ ~0x7, V4L2_EXPOSURE_METERING_SPOT,
-+ V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL,
- MMAL_PARAMETER_EXP_METERING_MODE,
- &ctrl_set_metering_mode,
- false
-@@ -1029,7 +1017,8 @@ static const struct bm2835_mmal_v4l2_ctr
- {
- V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
- MMAL_CONTROL_TYPE_STD_MENU,
-- ~0x3ff, 9, V4L2_WHITE_BALANCE_AUTO, 0, NULL,
-+ ~0x3ff, V4L2_WHITE_BALANCE_SHADE, V4L2_WHITE_BALANCE_AUTO, 0,
-+ NULL,
- MMAL_PARAMETER_AWB_MODE,
- &ctrl_set_awb_mode,
- false
-@@ -1050,7 +1039,7 @@ static const struct bm2835_mmal_v4l2_ctr
- },
- {
- V4L2_CID_COLORFX, MMAL_CONTROL_TYPE_STD_MENU,
-- 0, 15, V4L2_COLORFX_NONE, 0, NULL,
-+ 0, V4L2_COLORFX_SET_CBCR, V4L2_COLORFX_NONE, 0, NULL,
- MMAL_PARAMETER_IMAGE_EFFECT,
- &ctrl_set_image_effect,
- false
-@@ -1085,8 +1074,8 @@ static const struct bm2835_mmal_v4l2_ctr
- },
- {
- V4L2_CID_MPEG_VIDEO_BITRATE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
-- 0, ARRAY_SIZE(bitrate_mode_qmenu) - 1,
-- 0, 0, bitrate_mode_qmenu,
-+ 0, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
-+ 0, 0, NULL,
- MMAL_PARAMETER_RATECONTROL,
- &ctrl_set_bitrate_mode,
- false
-@@ -1108,8 +1097,8 @@ static const struct bm2835_mmal_v4l2_ctr
- },
- {
- V4L2_CID_POWER_LINE_FREQUENCY, MMAL_CONTROL_TYPE_STD_MENU,
-- 0, ARRAY_SIZE(mains_freq_qmenu) - 1,
-- 1, 1, mains_freq_qmenu,
-+ 0, V4L2_CID_POWER_LINE_FREQUENCY_AUTO,
-+ 1, 1, NULL,
- MMAL_PARAMETER_FLICKER_AVOID,
- &ctrl_set_flicker_avoidance,
- false
--- /dev/null
+From 5ba9f10bdb359e285f9052484814ef61a7bcb276 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 16:30:37 +0100
+Subject: [PATCH 264/725] staging: vc04_services: Split vchiq-mmal into a
+ module
+
+In preparation for adding a video codec V4L2 module which also
+wants to use vchiq-mmal functions, split it out into an
+independent module.
+The minimum number of changes have been made to achieve this
+(eg straight moves where possible) so existing checkpatch
+errors will still be present.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/Kconfig | 1 +
+ drivers/staging/vc04_services/Makefile | 1 +
+ .../vc04_services/bcm2835-camera/Kconfig | 2 +-
+ .../vc04_services/bcm2835-camera/Makefile | 4 ++--
+ .../staging/vc04_services/vchiq-mmal/Kconfig | 7 ++++++
+ .../staging/vc04_services/vchiq-mmal/Makefile | 8 +++++++
+ .../mmal-common.h | 0
+ .../mmal-encodings.h | 0
+ .../mmal-msg-common.h | 0
+ .../mmal-msg-format.h | 0
+ .../mmal-msg-port.h | 0
+ .../{bcm2835-camera => vchiq-mmal}/mmal-msg.h | 0
+ .../mmal-parameters.h | 0
+ .../mmal-vchiq.c | 22 +++++++++++++++++++
+ .../mmal-vchiq.h | 0
+ 15 files changed, 42 insertions(+), 3 deletions(-)
+ create mode 100644 drivers/staging/vc04_services/vchiq-mmal/Kconfig
+ create mode 100644 drivers/staging/vc04_services/vchiq-mmal/Makefile
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-common.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-encodings.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-common.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-format.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-port.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-parameters.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-vchiq.c (98%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-vchiq.h (100%)
+
+--- a/drivers/staging/vc04_services/Kconfig
++++ b/drivers/staging/vc04_services/Kconfig
+@@ -21,6 +21,7 @@ config BCM2835_VCHIQ
+ source "drivers/staging/vc04_services/bcm2835-audio/Kconfig"
+
+ source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
++source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
+
+ endif
+
+--- a/drivers/staging/vc04_services/Makefile
++++ b/drivers/staging/vc04_services/Makefile
+@@ -12,6 +12,7 @@ vchiq-objs := \
+
+ obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/
+ obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/
++obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
+
+ ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/Kconfig
++++ b/drivers/staging/vc04_services/bcm2835-camera/Kconfig
+@@ -2,7 +2,7 @@ config VIDEO_BCM2835
+ tristate "BCM2835 Camera"
+ depends on MEDIA_SUPPORT
+ depends on VIDEO_V4L2 && (ARCH_BCM2835 || COMPILE_TEST)
+- select BCM2835_VCHIQ
++ select BCM2835_VCHIQ_MMAL
+ select VIDEOBUF2_VMALLOC
+ select BTREE
+ help
+--- a/drivers/staging/vc04_services/bcm2835-camera/Makefile
++++ b/drivers/staging/vc04_services/bcm2835-camera/Makefile
+@@ -1,11 +1,11 @@
+ # SPDX-License-Identifier: GPL-2.0
+ bcm2835-v4l2-$(CONFIG_VIDEO_BCM2835) := \
+ bcm2835-camera.o \
+- controls.o \
+- mmal-vchiq.o
++ controls.o
+
+ obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-v4l2.o
+
+ ccflags-y += \
+ -Idrivers/staging/vc04_services \
++ -Idrivers/staging/vc04_services/vchiq-mmal \
+ -D__VCCOREVER__=0x04000000
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/Kconfig
+@@ -0,0 +1,7 @@
++config BCM2835_VCHIQ_MMAL
++ tristate "BCM2835 MMAL VCHIQ service"
++ depends on (ARCH_BCM2835 || COMPILE_TEST)
++ select BCM2835_VCHIQ
++ help
++ Enables the MMAL API over VCHIQ as used for the
++ majority of the multimedia services on VideoCore.
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/Makefile
+@@ -0,0 +1,8 @@
++# SPDX-License-Identifier: GPL-2.0
++bcm2835-mmal-vchiq-objs := mmal-vchiq.o
++
++obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += bcm2835-mmal-vchiq.o
++
++ccflags-y += \
++ -Idrivers/staging/vc04_services \
++ -D__VCCOREVER__=0x04000000
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
++++ /dev/null
+@@ -1,1899 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- * Dave Stevenson @ Broadcom
+- * (now dave.stevenson@raspberrypi.org)
+- * Simon Mellor @ Broadcom
+- * Luke Diamand @ Broadcom
+- *
+- * V4L2 driver MMAL vchiq interface code
+- */
+-
+-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+-
+-#include <linux/errno.h>
+-#include <linux/kernel.h>
+-#include <linux/mutex.h>
+-#include <linux/mm.h>
+-#include <linux/slab.h>
+-#include <linux/completion.h>
+-#include <linux/vmalloc.h>
+-#include <asm/cacheflush.h>
+-#include <media/videobuf2-vmalloc.h>
+-
+-#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: ", DUMP_PREFIX_OFFSET, \
+- 16, 4, (MSG), \
+- sizeof(struct mmal_msg_header), 1); \
+- print_hex_dump(KERN_DEBUG, "<<p: ", DUMP_PREFIX_OFFSET, \
+- 16, 4, \
+- ((u8 *)(MSG)) + sizeof(struct mmal_msg_header),\
+- (MSG_LEN) - sizeof(struct mmal_msg_header), 1); \
+- } while (0)
+-#else
+-#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE) \
+- { \
+- pr_debug(TITLE" type:%s(%d) length:%d\n", \
+- msg_type_names[(MSG)->h.type], \
+- (MSG)->h.type, (MSG_LEN)); \
+- }
+-#endif
+-#else
+-#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)
+-#endif
+-
+-struct vchiq_mmal_instance;
+-
+-/* normal message context */
+-struct mmal_msg_context {
+- struct vchiq_mmal_instance *instance;
+-
+- /* Index in the context_map idr so that we can find the
+- * mmal_msg_context again when servicing the VCHI reply.
+- */
+- int handle;
+-
+- union {
+- struct {
+- /* work struct for buffer_cb callback */
+- struct work_struct work;
+- /* work struct for deferred callback */
+- struct work_struct buffer_to_host_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;
+-
+- /* vmalloc page to receive scratch bulk xfers into */
+- void *bulk_scratch;
+-
+- struct idr context_map;
+- /* protect accesses to context_map */
+- struct mutex context_map_lock;
+-
+- /* component to use next */
+- int component_idx;
+- struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
+-
+- /* ordered workqueue to process all bulk operations */
+- struct workqueue_struct *bulk_wq;
+-};
+-
+-static struct mmal_msg_context *
+-get_msg_context(struct vchiq_mmal_instance *instance)
+-{
+- struct mmal_msg_context *msg_context;
+- int handle;
+-
+- /* todo: should this be allocated from a pool to avoid kzalloc */
+- msg_context = kzalloc(sizeof(*msg_context), GFP_KERNEL);
+-
+- if (!msg_context)
+- return ERR_PTR(-ENOMEM);
+-
+- /* Create an ID that will be passed along with our message so
+- * that when we service the VCHI reply, we can look up what
+- * message is being replied to.
+- */
+- mutex_lock(&instance->context_map_lock);
+- handle = idr_alloc(&instance->context_map, msg_context,
+- 0, 0, GFP_KERNEL);
+- mutex_unlock(&instance->context_map_lock);
+-
+- if (handle < 0) {
+- kfree(msg_context);
+- return ERR_PTR(handle);
+- }
+-
+- msg_context->instance = instance;
+- msg_context->handle = handle;
+-
+- return msg_context;
+-}
+-
+-static struct mmal_msg_context *
+-lookup_msg_context(struct vchiq_mmal_instance *instance, int handle)
+-{
+- return idr_find(&instance->context_map, handle);
+-}
+-
+-static void
+-release_msg_context(struct mmal_msg_context *msg_context)
+-{
+- struct vchiq_mmal_instance *instance = msg_context->instance;
+-
+- mutex_lock(&instance->context_map_lock);
+- idr_remove(&instance->context_map, msg_context->handle);
+- mutex_unlock(&instance->context_map_lock);
+- 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:%u 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 =
+- container_of(work, struct mmal_msg_context, u.bulk.work);
+-
+- atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
+-
+- 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);
+-}
+-
+-/* workqueue scheduled callback to handle receiving buffers
+- *
+- * VCHI will allow up to 4 bulk receives to be scheduled before blocking.
+- * If we block in the service_callback context then we can't process the
+- * VCHI_CALLBACK_BULK_RECEIVED message that would otherwise allow the blocked
+- * vchi_bulk_queue_receive() call to complete.
+- */
+-static void buffer_to_host_work_cb(struct work_struct *work)
+-{
+- struct mmal_msg_context *msg_context =
+- container_of(work, struct mmal_msg_context,
+- u.bulk.buffer_to_host_work);
+- struct vchiq_mmal_instance *instance = msg_context->instance;
+- unsigned long len = msg_context->u.bulk.buffer_used;
+- int ret;
+-
+- if (!len)
+- /* Dummy receive to ensure the buffers remain in order */
+- len = 8;
+- /* 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
+- */
+- (len + 3) & ~3,
+- VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
+- VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
+- msg_context);
+-
+- vchi_service_release(instance->handle);
+-
+- if (ret != 0)
+- pr_err("%s: ctx: %p, vchi_bulk_queue_receive failed %d\n",
+- __func__, msg_context, ret);
+-}
+-
+-/* 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;
+-
+- rd_len = msg->u.buffer_from_host.buffer_header.length;
+-
+- if (!msg_context->u.bulk.buffer) {
+- pr_err("bulk.buffer not configured - error in buffer_from_host\n");
+-
+- /* todo: this is a serious error, we should never have
+- * committed 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?
+- */
+-
+- return -EINVAL;
+- }
+-
+- /* 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.dts = msg->u.buffer_from_host.buffer_header.dts;
+- msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
+-
+- queue_work(msg_context->instance->bulk_wq,
+- &msg_context->u.bulk.buffer_to_host_work);
+-
+- return 0;
+-}
+-
+-/* 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)
+-{
+- 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;
+-
+- if (!port->enabled)
+- return -EINVAL;
+-
+- pr_debug("instance:%p buffer:%p\n", instance->handle, buf);
+-
+- /* get context */
+- if (!buf->msg_context) {
+- pr_err("%s: msg_context not allocated, buf %p\n", __func__,
+- buf);
+- return -EINVAL;
+- }
+- msg_context = buf->msg_context;
+-
+- /* 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 = buf;
+- msg_context->u.bulk.buffer_used = 0;
+-
+- /* initialise work structure ready to schedule callback */
+- INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
+- INIT_WORK(&msg_context->u.bulk.buffer_to_host_work,
+- buffer_to_host_work_cb);
+-
+- atomic_inc(&port->buffers_with_vpu);
+-
+- /* 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->handle;
+- 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->handle;
+-
+- /* buffer header */
+- m.u.buffer_from_host.buffer_header.cmd = 0;
+- m.u.buffer_from_host.buffer_header.data =
+- (u32)(unsigned long)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_queue_kernel_message(instance->handle,
+- &m,
+- sizeof(struct mmal_msg_header) +
+- sizeof(m.u.buffer_from_host));
+-
+- vchi_service_release(instance->handle);
+-
+- 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;
+- u32 handle;
+-
+- pr_debug("%s: instance:%p msg:%p msg_len:%d\n",
+- __func__, instance, msg, msg_len);
+-
+- if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
+- handle = msg->u.buffer_from_host.drvbuf.client_context;
+- msg_context = lookup_msg_context(instance, handle);
+-
+- if (!msg_context) {
+- pr_err("drvbuf.client_context(%u) is invalid\n",
+- handle);
+- return;
+- }
+- } else {
+- pr_err("MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n");
+- return;
+- }
+-
+- msg_context->u.bulk.mmal_flags =
+- msg->u.buffer_from_host.buffer_header.flags;
+-
+- 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 =
+- bulk_receive(instance, msg, 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;
+- }
+-
+- /* 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)
+-{
+- 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);
+-
+- 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;
+- struct mmal_msg_context *msg_context;
+-
+- 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 dependent on header context to complete */
+- if (!msg->h.context) {
+- pr_err("received message context was null!\n");
+- vchi_held_msg_release(&msg_handle);
+- break;
+- }
+-
+- msg_context = lookup_msg_context(instance,
+- msg->h.context);
+- if (!msg_context) {
+- pr_err("received invalid message context %u!\n",
+- msg->h.context);
+- vchi_held_msg_release(&msg_handle);
+- break;
+- }
+-
+- /* fill in context values */
+- msg_context->u.sync.msg_handle = msg_handle;
+- msg_context->u.sync.msg = msg;
+- msg_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_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;
+- unsigned long timeout;
+-
+- /* 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,
+- (int)(MMAL_MSG_MAX_SIZE -
+- sizeof(struct mmal_msg_header)));
+- return -EINVAL;
+- }
+-
+- msg_context = get_msg_context(instance);
+- if (IS_ERR(msg_context))
+- return PTR_ERR(msg_context);
+-
+- init_completion(&msg_context->u.sync.cmplt);
+-
+- msg->h.magic = MMAL_MAGIC;
+- msg->h.context = msg_context->handle;
+- msg->h.status = 0;
+-
+- DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len),
+- ">>> sync message");
+-
+- vchi_service_use(instance->handle);
+-
+- ret = vchi_queue_kernel_message(instance->handle,
+- msg,
+- sizeof(struct mmal_msg_header) +
+- payload_len);
+-
+- vchi_service_release(instance->handle);
+-
+- if (ret) {
+- pr_err("error %d queuing message\n", ret);
+- release_msg_context(msg_context);
+- return ret;
+- }
+-
+- timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt,
+- 3 * HZ);
+- if (timeout == 0) {
+- pr_err("timed out waiting for sync completion\n");
+- ret = -ETIME;
+- /* todo: what happens if the message arrives after aborting */
+- release_msg_context(msg_context);
+- return ret;
+- }
+-
+- *msg_out = msg_context->u.sync.msg;
+- *msg_handle_out = msg_context->u.sync.msg_handle;
+- release_msg_context(msg_context);
+-
+- 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("elementary stream: type:%d encoding:0x%x variant: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 = (u32)(unsigned long)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);
+-
+- /* elementary 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 retrieve 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 because
+- * 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;
+-
+- /* elementary 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 = (u32)(unsigned long)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;
+- /* 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
+- */
+- 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. This should only
+- * apply to buffers that have been queued before the port
+- * has been enabled. If the port has been enabled and buffers
+- * passed, then the buffers should have been removed from this
+- * list, and we should get the relevant callbacks via VCHIQ
+- * to release the buffers.
+- */
+- 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 *q, *buf_head;
+- int ret;
+-
+- if (port->enabled)
+- return 0;
+-
+- 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_safe(buf_head, q, &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;
+-
+- list_del(buf_head);
+- 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) {
+- 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) {
+- /* 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;
+- int ret;
+-
+- ret = buffer_from_host(instance, port, buffer);
+- if (ret == -EINVAL) {
+- /* Port is disabled. Queue for when it is enabled. */
+- spin_lock_irqsave(&port->slock, flags);
+- list_add_tail(&buffer->list, &port->buffers);
+- spin_unlock_irqrestore(&port->slock, flags);
+- }
+-
+- return 0;
+-}
+-
+-int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
+- struct mmal_buffer *buf)
+-{
+- struct mmal_msg_context *msg_context = get_msg_context(instance);
+-
+- if (IS_ERR(msg_context))
+- return (PTR_ERR(msg_context));
+-
+- buf->msg_context = msg_context;
+- return 0;
+-}
+-
+-int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
+-{
+- struct mmal_msg_context *msg_context = buf->msg_context;
+-
+- if (msg_context)
+- release_msg_context(msg_context);
+- buf->msg_context = NULL;
+-
+- 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) {
+- pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
+- __func__, ret);
+- 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)
+- 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\n");
+-
+- mutex_unlock(&instance->vchiq_mutex);
+-
+- flush_workqueue(instance->bulk_wq);
+- destroy_workqueue(instance->bulk_wq);
+-
+- vfree(instance->bulk_scratch);
+-
+- idr_destroy(&instance->context_map);
+-
+- 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 = {
+- .version = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
+- .service_id = VC_MMAL_SERVER_NAME,
+- .connection = vchi_connection,
+- .rx_fifo_size = 0,
+- .tx_fifo_size = 0,
+- .callback = service_callback,
+- .callback_param = NULL,
+- .want_unaligned_bulk_rx = 1,
+- .want_unaligned_bulk_tx = 1,
+- .want_crc = 0
+- };
+-
+- /* 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 = kzalloc(sizeof(*instance), GFP_KERNEL);
+-
+- if (!instance)
+- return -ENOMEM;
+-
+- mutex_init(&instance->vchiq_mutex);
+-
+- instance->bulk_scratch = vmalloc(PAGE_SIZE);
+-
+- mutex_init(&instance->context_map_lock);
+- idr_init_base(&instance->context_map, 1);
+-
+- params.callback_param = instance;
+-
+- instance->bulk_wq = alloc_ordered_workqueue("mmal-vchiq",
+- WQ_MEM_RECLAIM);
+- if (!instance->bulk_wq)
+- goto err_free;
+-
+- 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);
+- destroy_workqueue(instance->bulk_wq);
+-err_free:
+- vfree(instance->bulk_scratch);
+- kfree(instance);
+- return -ENODEV;
+-}
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -0,0 +1,1921 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ * Dave Stevenson @ Broadcom
++ * (now dave.stevenson@raspberrypi.org)
++ * Simon Mellor @ Broadcom
++ * Luke Diamand @ Broadcom
++ *
++ * V4L2 driver MMAL vchiq interface code
++ */
++
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/completion.h>
++#include <linux/vmalloc.h>
++#include <asm/cacheflush.h>
++#include <media/videobuf2-vmalloc.h>
++
++#include "mmal-common.h"
++#include "mmal-vchiq.h"
++#include "mmal-msg.h"
++
++#define USE_VCHIQ_ARM
++#include "interface/vchi/vchi.h"
++
++MODULE_DESCRIPTION("BCM2835 MMAL VCHIQ interface");
++MODULE_AUTHOR("Dave Stevenson, <dave.stevenson@raspberrypi.org>");
++MODULE_LICENSE("GPL");
++MODULE_VERSION("0.0.1");
++
++/* 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: ", DUMP_PREFIX_OFFSET, \
++ 16, 4, (MSG), \
++ sizeof(struct mmal_msg_header), 1); \
++ print_hex_dump(KERN_DEBUG, "<<p: ", DUMP_PREFIX_OFFSET, \
++ 16, 4, \
++ ((u8 *)(MSG)) + sizeof(struct mmal_msg_header),\
++ (MSG_LEN) - sizeof(struct mmal_msg_header), 1); \
++ } while (0)
++#else
++#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE) \
++ { \
++ pr_debug(TITLE" type:%s(%d) length:%d\n", \
++ msg_type_names[(MSG)->h.type], \
++ (MSG)->h.type, (MSG_LEN)); \
++ }
++#endif
++#else
++#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)
++#endif
++
++struct vchiq_mmal_instance;
++
++/* normal message context */
++struct mmal_msg_context {
++ struct vchiq_mmal_instance *instance;
++
++ /* Index in the context_map idr so that we can find the
++ * mmal_msg_context again when servicing the VCHI reply.
++ */
++ int handle;
++
++ union {
++ struct {
++ /* work struct for buffer_cb callback */
++ struct work_struct work;
++ /* work struct for deferred callback */
++ struct work_struct buffer_to_host_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;
++
++ /* vmalloc page to receive scratch bulk xfers into */
++ void *bulk_scratch;
++
++ struct idr context_map;
++ /* protect accesses to context_map */
++ struct mutex context_map_lock;
++
++ /* component to use next */
++ int component_idx;
++ struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
++
++ /* ordered workqueue to process all bulk operations */
++ struct workqueue_struct *bulk_wq;
++};
++
++static struct mmal_msg_context *
++get_msg_context(struct vchiq_mmal_instance *instance)
++{
++ struct mmal_msg_context *msg_context;
++ int handle;
++
++ /* todo: should this be allocated from a pool to avoid kzalloc */
++ msg_context = kzalloc(sizeof(*msg_context), GFP_KERNEL);
++
++ if (!msg_context)
++ return ERR_PTR(-ENOMEM);
++
++ /* Create an ID that will be passed along with our message so
++ * that when we service the VCHI reply, we can look up what
++ * message is being replied to.
++ */
++ mutex_lock(&instance->context_map_lock);
++ handle = idr_alloc(&instance->context_map, msg_context,
++ 0, 0, GFP_KERNEL);
++ mutex_unlock(&instance->context_map_lock);
++
++ if (handle < 0) {
++ kfree(msg_context);
++ return ERR_PTR(handle);
++ }
++
++ msg_context->instance = instance;
++ msg_context->handle = handle;
++
++ return msg_context;
++}
++
++static struct mmal_msg_context *
++lookup_msg_context(struct vchiq_mmal_instance *instance, int handle)
++{
++ return idr_find(&instance->context_map, handle);
++}
++
++static void
++release_msg_context(struct mmal_msg_context *msg_context)
++{
++ struct vchiq_mmal_instance *instance = msg_context->instance;
++
++ mutex_lock(&instance->context_map_lock);
++ idr_remove(&instance->context_map, msg_context->handle);
++ mutex_unlock(&instance->context_map_lock);
++ 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:%u 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 =
++ container_of(work, struct mmal_msg_context, u.bulk.work);
++
++ atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
++
++ 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);
++}
++
++/* workqueue scheduled callback to handle receiving buffers
++ *
++ * VCHI will allow up to 4 bulk receives to be scheduled before blocking.
++ * If we block in the service_callback context then we can't process the
++ * VCHI_CALLBACK_BULK_RECEIVED message that would otherwise allow the blocked
++ * vchi_bulk_queue_receive() call to complete.
++ */
++static void buffer_to_host_work_cb(struct work_struct *work)
++{
++ struct mmal_msg_context *msg_context =
++ container_of(work, struct mmal_msg_context,
++ u.bulk.buffer_to_host_work);
++ struct vchiq_mmal_instance *instance = msg_context->instance;
++ unsigned long len = msg_context->u.bulk.buffer_used;
++ int ret;
++
++ if (!len)
++ /* Dummy receive to ensure the buffers remain in order */
++ len = 8;
++ /* 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
++ */
++ (len + 3) & ~3,
++ VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
++ msg_context);
++
++ vchi_service_release(instance->handle);
++
++ if (ret != 0)
++ pr_err("%s: ctx: %p, vchi_bulk_queue_receive failed %d\n",
++ __func__, msg_context, ret);
++}
++
++/* 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;
++
++ rd_len = msg->u.buffer_from_host.buffer_header.length;
++
++ if (!msg_context->u.bulk.buffer) {
++ pr_err("bulk.buffer not configured - error in buffer_from_host\n");
++
++ /* todo: this is a serious error, we should never have
++ * committed 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?
++ */
++
++ return -EINVAL;
++ }
++
++ /* 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.dts = msg->u.buffer_from_host.buffer_header.dts;
++ msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
++
++ queue_work(msg_context->instance->bulk_wq,
++ &msg_context->u.bulk.buffer_to_host_work);
++
++ return 0;
++}
++
++/* 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)
++{
++ 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;
++
++ if (!port->enabled)
++ return -EINVAL;
++
++ pr_debug("instance:%p buffer:%p\n", instance->handle, buf);
++
++ /* get context */
++ if (!buf->msg_context) {
++ pr_err("%s: msg_context not allocated, buf %p\n", __func__,
++ buf);
++ return -EINVAL;
++ }
++ msg_context = buf->msg_context;
++
++ /* 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 = buf;
++ msg_context->u.bulk.buffer_used = 0;
++
++ /* initialise work structure ready to schedule callback */
++ INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
++ INIT_WORK(&msg_context->u.bulk.buffer_to_host_work,
++ buffer_to_host_work_cb);
++
++ atomic_inc(&port->buffers_with_vpu);
++
++ /* 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->handle;
++ 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->handle;
++
++ /* buffer header */
++ m.u.buffer_from_host.buffer_header.cmd = 0;
++ m.u.buffer_from_host.buffer_header.data =
++ (u32)(unsigned long)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_queue_kernel_message(instance->handle,
++ &m,
++ sizeof(struct mmal_msg_header) +
++ sizeof(m.u.buffer_from_host));
++
++ vchi_service_release(instance->handle);
++
++ 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;
++ u32 handle;
++
++ pr_debug("%s: instance:%p msg:%p msg_len:%d\n",
++ __func__, instance, msg, msg_len);
++
++ if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
++ handle = msg->u.buffer_from_host.drvbuf.client_context;
++ msg_context = lookup_msg_context(instance, handle);
++
++ if (!msg_context) {
++ pr_err("drvbuf.client_context(%u) is invalid\n",
++ handle);
++ return;
++ }
++ } else {
++ pr_err("MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n");
++ return;
++ }
++
++ msg_context->u.bulk.mmal_flags =
++ msg->u.buffer_from_host.buffer_header.flags;
++
++ 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 =
++ bulk_receive(instance, msg, 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;
++ }
++
++ /* 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)
++{
++ 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);
++
++ 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;
++ struct mmal_msg_context *msg_context;
++
++ 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 dependent on header context to complete */
++ if (!msg->h.context) {
++ pr_err("received message context was null!\n");
++ vchi_held_msg_release(&msg_handle);
++ break;
++ }
++
++ msg_context = lookup_msg_context(instance,
++ msg->h.context);
++ if (!msg_context) {
++ pr_err("received invalid message context %u!\n",
++ msg->h.context);
++ vchi_held_msg_release(&msg_handle);
++ break;
++ }
++
++ /* fill in context values */
++ msg_context->u.sync.msg_handle = msg_handle;
++ msg_context->u.sync.msg = msg;
++ msg_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_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;
++ unsigned long timeout;
++
++ /* 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,
++ (int)(MMAL_MSG_MAX_SIZE -
++ sizeof(struct mmal_msg_header)));
++ return -EINVAL;
++ }
++
++ msg_context = get_msg_context(instance);
++ if (IS_ERR(msg_context))
++ return PTR_ERR(msg_context);
++
++ init_completion(&msg_context->u.sync.cmplt);
++
++ msg->h.magic = MMAL_MAGIC;
++ msg->h.context = msg_context->handle;
++ msg->h.status = 0;
++
++ DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len),
++ ">>> sync message");
++
++ vchi_service_use(instance->handle);
++
++ ret = vchi_queue_kernel_message(instance->handle,
++ msg,
++ sizeof(struct mmal_msg_header) +
++ payload_len);
++
++ vchi_service_release(instance->handle);
++
++ if (ret) {
++ pr_err("error %d queuing message\n", ret);
++ release_msg_context(msg_context);
++ return ret;
++ }
++
++ timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt,
++ 3 * HZ);
++ if (timeout == 0) {
++ pr_err("timed out waiting for sync completion\n");
++ ret = -ETIME;
++ /* todo: what happens if the message arrives after aborting */
++ release_msg_context(msg_context);
++ return ret;
++ }
++
++ *msg_out = msg_context->u.sync.msg;
++ *msg_handle_out = msg_context->u.sync.msg_handle;
++ release_msg_context(msg_context);
++
++ 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("elementary stream: type:%d encoding:0x%x variant: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 = (u32)(unsigned long)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);
++
++ /* elementary 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 retrieve 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 because
++ * 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;
++
++ /* elementary 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 = (u32)(unsigned long)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;
++ /* 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
++ */
++ 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. This should only
++ * apply to buffers that have been queued before the port
++ * has been enabled. If the port has been enabled and buffers
++ * passed, then the buffers should have been removed from this
++ * list, and we should get the relevant callbacks via VCHIQ
++ * to release the buffers.
++ */
++ 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 *q, *buf_head;
++ int ret;
++
++ if (port->enabled)
++ return 0;
++
++ 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_safe(buf_head, q, &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;
++
++ list_del(buf_head);
++ 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;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_set_format);
++
++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;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set);
++
++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;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_get);
++
++/* 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;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_enable);
++
++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;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_disable);
++
++/* 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) {
++ 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) {
++ /* 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;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_connect_tunnel);
++
++int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
++ struct vchiq_mmal_port *port,
++ struct mmal_buffer *buffer)
++{
++ unsigned long flags = 0;
++ int ret;
++
++ ret = buffer_from_host(instance, port, buffer);
++ if (ret == -EINVAL) {
++ /* Port is disabled. Queue for when it is enabled. */
++ spin_lock_irqsave(&port->slock, flags);
++ list_add_tail(&buffer->list, &port->buffers);
++ spin_unlock_irqrestore(&port->slock, flags);
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_submit_buffer);
++
++int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
++ struct mmal_buffer *buf)
++{
++ struct mmal_msg_context *msg_context = get_msg_context(instance);
++
++ if (IS_ERR(msg_context))
++ return (PTR_ERR(msg_context));
++
++ buf->msg_context = msg_context;
++ return 0;
++}
++EXPORT_SYMBOL_GPL(mmal_vchi_buffer_init);
++
++int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
++{
++ struct mmal_msg_context *msg_context = buf->msg_context;
++
++ if (msg_context)
++ release_msg_context(msg_context);
++ buf->msg_context = NULL;
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
++
++/* 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) {
++ pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
++ __func__, ret);
++ 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;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_component_init);
++
++/*
++ * 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;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_component_finalise);
++
++/*
++ * 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;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_component_enable);
++
++/*
++ * 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;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_component_disable);
++
++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;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_version);
++
++int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance)
++{
++ int status = 0;
++
++ if (!instance)
++ 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\n");
++
++ mutex_unlock(&instance->vchiq_mutex);
++
++ flush_workqueue(instance->bulk_wq);
++ destroy_workqueue(instance->bulk_wq);
++
++ vfree(instance->bulk_scratch);
++
++ idr_destroy(&instance->context_map);
++
++ kfree(instance);
++
++ return status;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_finalise);
++
++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 = {
++ .version = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
++ .service_id = VC_MMAL_SERVER_NAME,
++ .connection = vchi_connection,
++ .rx_fifo_size = 0,
++ .tx_fifo_size = 0,
++ .callback = service_callback,
++ .callback_param = NULL,
++ .want_unaligned_bulk_rx = 1,
++ .want_unaligned_bulk_tx = 1,
++ .want_crc = 0
++ };
++
++ /* 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 = kzalloc(sizeof(*instance), GFP_KERNEL);
++
++ if (!instance)
++ return -ENOMEM;
++
++ mutex_init(&instance->vchiq_mutex);
++
++ instance->bulk_scratch = vmalloc(PAGE_SIZE);
++
++ mutex_init(&instance->context_map_lock);
++ idr_init_base(&instance->context_map, 1);
++
++ params.callback_param = instance;
++
++ instance->bulk_wq = alloc_ordered_workqueue("mmal-vchiq",
++ WQ_MEM_RECLAIM);
++ if (!instance->bulk_wq)
++ goto err_free;
++
++ 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);
++ destroy_workqueue(instance->bulk_wq);
++err_free:
++ vfree(instance->bulk_scratch);
++ kfree(instance);
++ return -ENODEV;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_init);
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
++++ /dev/null
+@@ -1,61 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- * Dave Stevenson @ Broadcom
+- * (now dave.stevenson@raspberrypi.org)
+- * Simon Mellor @ Broadcom
+- * Luke Diamand @ Broadcom
+- *
+- * MMAL structures
+- *
+- */
+-#ifndef MMAL_COMMON_H
+-#define MMAL_COMMON_H
+-
+-#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 BIT_ULL(63)
+-
+-struct mmal_msg_context;
+-
+-/* 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 */
+- bool remove_padding; /* Does the GPU have to remove padding,
+- * or can we do hide padding via bytesperline.
+- */
+-};
+-
+-/* 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_msg_context *msg_context;
+-};
+-
+-/* */
+-struct mmal_colourfx {
+- s32 enable;
+- u32 u;
+- u32 v;
+-};
+-#endif
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-encodings.h
++++ /dev/null
+@@ -1,124 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- * Dave Stevenson @ Broadcom
+- * (now dave.stevenson@raspberrypi.org)
+- * Simon Mellor @ Broadcom
+- * Luke Diamand @ Broadcom
+- */
+-#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 */
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-common.h
++++ /dev/null
+@@ -1,48 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- * Dave Stevenson @ Broadcom
+- * (now dave.stevenson@raspberrypi.org)
+- * Simon Mellor @ Broadcom
+- * Luke Diamand @ Broadcom
+- */
+-
+-#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 */
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h
++++ /dev/null
+@@ -1,106 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- * Dave Stevenson @ Broadcom
+- * (now dave.stevenson@raspberrypi.org)
+- * Simon Mellor @ Broadcom
+- * Luke Diamand @ Broadcom
+- */
+-
+-#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
+- * 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_local {
+- 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; /* 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 */
+-};
+-
+-/* Remote 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.
+- */
+-
+- u32 es; /* 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 */
+- u32 extradata; /* Codec specific data */
+-};
+-
+-#endif /* MMAL_MSG_FORMAT_H */
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h
++++ /dev/null
+@@ -1,109 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- * Dave Stevenson @ Broadcom
+- * (now dave.stevenson@raspberrypi.org)
+- * Simon Mellor @ Broadcom
+- * Luke Diamand @ Broadcom
+- */
+-
+-/* 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
+- * structures within the message. When used to set values only the
+- * buffer_num, buffer_size and userdata parameters are writable.
+- */
+-struct mmal_port {
+- u32 priv; /* Private member used by the framework */
+- u32 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) */
+- u32 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.
+- */
+-
+- u32 component; /* Component this port belongs to (Read Only) */
+-
+- u32 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.
+- */
+-};
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
++++ /dev/null
+@@ -1,406 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- * Dave Stevenson @ Broadcom
+- * (now dave.stevenson@raspberrypi.org)
+- * Simon Mellor @ Broadcom
+- * Luke Diamand @ Broadcom
+- */
+-
+-/*
+- * 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
+- */
+-#ifndef MMAL_MSG_H
+-#define MMAL_MSG_H
+-
+-#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, /* Unknown 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 */
+- u32 control_service;
+-
+- u32 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 {
+- u32 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; /* elementary 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 BIT(0)
+-/* Signals that the start of the current payload starts a frame */
+-#define MMAL_BUFFER_HEADER_FLAG_FRAME_START BIT(1)
+-/* Signals that the end of the current payload ends a frame */
+-#define MMAL_BUFFER_HEADER_FLAG_FRAME_END BIT(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 BIT(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 BIT(4)
+-/*
+- * Signals a buffer containing some kind of config data for the component
+- * (e.g. codec config data)
+- */
+-#define MMAL_BUFFER_HEADER_FLAG_CONFIG BIT(5)
+-/* Signals an encrypted payload */
+-#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED BIT(6)
+-/* Signals a buffer containing side information */
+-#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO BIT(7)
+-/*
+- * Signals a buffer which is the snapshot/postview image from a stills
+- * capture
+- */
+-#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT BIT(8)
+-/* Signals a buffer which contains data known to be corrupted */
+-#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED BIT(9)
+-/* Signals that a buffer failed to be transmitted */
+-#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED BIT(10)
+-
+-struct mmal_driver_buffer {
+- u32 magic;
+- u32 component_handle;
+- u32 port_handle;
+- u32 client_context;
+-};
+-
+-/* buffer header */
+-struct mmal_buffer_header {
+- u32 next; /* next header */
+- u32 priv; /* framework private data */
+- u32 cmd;
+- u32 data;
+- u32 alloc_size;
+- u32 length;
+- u32 offset;
+- u32 flags;
+- s64 pts;
+- s64 dts;
+- u32 type;
+- u32 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 {
+- u32 client_component; /* component context */
+-
+- u32 port_type;
+- u32 port_num;
+-
+- u32 cmd;
+- u32 length;
+- u8 data[MMAL_WORKER_EVENT_SPACE];
+- u32 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;
+-};
+-#endif
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
++++ /dev/null
+@@ -1,755 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- * Dave Stevenson @ Broadcom
+- * (now dave.stevenson@raspberrypi.org)
+- * Simon Mellor @ Broadcom
+- * Luke Diamand @ Broadcom
+- */
+-
+-/* common parameters */
+-
+-/** @name Parameter groups
+- * Parameters are divided into groups, and then allocated sequentially within
+- * a group using an enum.
+- * @{
+- */
+-
+-#ifndef MMAL_PARAMETERS_H
+-#define MMAL_PARAMETERS_H
+-
+-/** 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 {
+- /**< Never a valid parameter ID */
+- MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON,
+-
+- /**< MMAL_PARAMETER_ENCODING_T */
+- MMAL_PARAMETER_SUPPORTED_ENCODINGS,
+- /**< MMAL_PARAMETER_URI_T */
+- MMAL_PARAMETER_URI,
+- /** 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_T */
+- MMAL_PARAMETER_STATISTICS,
+- /**< MMAL_PARAMETER_CORE_STATISTICS_T */
+- MMAL_PARAMETER_CORE_STATISTICS,
+- /**< MMAL_PARAMETER_MEM_USAGE_T */
+- MMAL_PARAMETER_MEM_USAGE,
+- /**< MMAL_PARAMETER_UINT32_T */
+- MMAL_PARAMETER_BUFFER_FLAG_FILTER,
+- /**< MMAL_PARAMETER_SEEK_T */
+- MMAL_PARAMETER_SEEK,
+- /**< MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_POWERMON_ENABLE,
+- /**< MMAL_PARAMETER_LOGGING_T */
+- MMAL_PARAMETER_LOGGING,
+- /**< MMAL_PARAMETER_UINT64_T */
+- MMAL_PARAMETER_SYSTEM_TIME,
+- /**< MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_NO_IMAGE_PADDING,
+-};
+-
+-/* camera parameters */
+-
+-enum mmal_parameter_camera_type {
+- /* 0 */
+- /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
+- MMAL_PARAMETER_THUMBNAIL_CONFIGURATION =
+- MMAL_PARAMETER_GROUP_CAMERA,
+- /**< Unused? */
+- MMAL_PARAMETER_CAPTURE_QUALITY,
+- /**< @ref MMAL_PARAMETER_INT32_T */
+- MMAL_PARAMETER_ROTATION,
+- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_EXIF_DISABLE,
+- /**< @ref MMAL_PARAMETER_EXIF_T */
+- MMAL_PARAMETER_EXIF,
+- /**< @ref MMAL_PARAM_AWBMODE_T */
+- MMAL_PARAMETER_AWB_MODE,
+- /**< @ref MMAL_PARAMETER_IMAGEFX_T */
+- MMAL_PARAMETER_IMAGE_EFFECT,
+- /**< @ref MMAL_PARAMETER_COLOURFX_T */
+- MMAL_PARAMETER_COLOUR_EFFECT,
+- /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
+- MMAL_PARAMETER_FLICKER_AVOID,
+- /**< @ref MMAL_PARAMETER_FLASH_T */
+- MMAL_PARAMETER_FLASH,
+- /**< @ref MMAL_PARAMETER_REDEYE_T */
+- MMAL_PARAMETER_REDEYE,
+- /**< @ref MMAL_PARAMETER_FOCUS_T */
+- MMAL_PARAMETER_FOCUS,
+- /**< Unused? */
+- MMAL_PARAMETER_FOCAL_LENGTHS,
+- /**< @ref MMAL_PARAMETER_INT32_T */
+- MMAL_PARAMETER_EXPOSURE_COMP,
+- /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
+- MMAL_PARAMETER_ZOOM,
+- /**< @ref MMAL_PARAMETER_MIRROR_T */
+- MMAL_PARAMETER_MIRROR,
+-
+- /* 0x10 */
+- /**< @ref MMAL_PARAMETER_UINT32_T */
+- MMAL_PARAMETER_CAMERA_NUM,
+- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_CAPTURE,
+- /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
+- MMAL_PARAMETER_EXPOSURE_MODE,
+- /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
+- MMAL_PARAMETER_EXP_METERING_MODE,
+- /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
+- MMAL_PARAMETER_FOCUS_STATUS,
+- /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
+- MMAL_PARAMETER_CAMERA_CONFIG,
+- /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
+- MMAL_PARAMETER_CAPTURE_STATUS,
+- /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
+- MMAL_PARAMETER_FACE_TRACK,
+- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
+- /**< @ref MMAL_PARAMETER_UINT32_T */
+- MMAL_PARAMETER_JPEG_Q_FACTOR,
+- /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
+- MMAL_PARAMETER_FRAME_RATE,
+- /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
+- MMAL_PARAMETER_USE_STC,
+- /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
+- MMAL_PARAMETER_CAMERA_INFO,
+- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_VIDEO_STABILISATION,
+- /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
+- MMAL_PARAMETER_FACE_TRACK_RESULTS,
+- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_ENABLE_RAW_CAPTURE,
+-
+- /* 0x20 */
+- /**< @ref MMAL_PARAMETER_URI_T */
+- MMAL_PARAMETER_DPF_FILE,
+- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_ENABLE_DPF_FILE,
+- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
+- /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
+- MMAL_PARAMETER_CAPTURE_MODE,
+- /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
+- MMAL_PARAMETER_FOCUS_REGIONS,
+- /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
+- MMAL_PARAMETER_INPUT_CROP,
+- /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
+- MMAL_PARAMETER_SENSOR_INFORMATION,
+- /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
+- MMAL_PARAMETER_FLASH_SELECT,
+- /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
+- MMAL_PARAMETER_FIELD_OF_VIEW,
+- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
+- /**< @ref MMAL_PARAMETER_DRC_T */
+- MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,
+- /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
+- MMAL_PARAMETER_ALGORITHM_CONTROL,
+- /**< @ref MMAL_PARAMETER_RATIONAL_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,
+-
+- /* 0x30 */
+- /**< @ref MMAL_PARAMETER_UINT32_T */
+- MMAL_PARAMETER_ISO,
+- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_ANTISHAKE,
+- /** @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,
+- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_JPEG_ATTACH_LOG,
+- /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
+- MMAL_PARAMETER_ZERO_SHUTTER_LAG,
+- /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
+- MMAL_PARAMETER_FPS_RANGE,
+- /**< @ref MMAL_PARAMETER_INT32_T */
+- MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP,
+-
+- /* 0x40 */
+- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_SW_SHARPEN_DISABLE,
+- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_FLASH_REQUIRED,
+- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_SW_SATURATION_DISABLE,
+- /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
+- MMAL_PARAMETER_SHUTTER_SPEED,
+- /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
+- MMAL_PARAMETER_CUSTOM_AWB_GAINS,
+-};
+-
+-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,
+-};
+-
+-/* rectangle, used lots so it gets its own struct */
+-struct vchiq_mmal_rect {
+- s32 x;
+- s32 y;
+- s32 width;
+- s32 height;
+-};
+-
+-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];
+-};
+-
+-#endif
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
++++ /dev/null
+@@ -1,166 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- * Dave Stevenson @ Broadcom
+- * (now dave.stevenson@raspberrypi.org)
+- * Simon Mellor @ Broadcom
+- * Luke Diamand @ Broadcom
+- *
+- * 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 */
+-};
+-
+-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_local format;
+- /* elementary 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 buffers the VPU has yet to return */
+- atomic_t buffers_with_vpu;
+- /* 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 appropriate 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);
+-
+-int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
+- struct mmal_buffer *buf);
+-int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf);
+-#endif /* MMAL_VCHIQ_H */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
+@@ -0,0 +1,61 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ * Dave Stevenson @ Broadcom
++ * (now dave.stevenson@raspberrypi.org)
++ * Simon Mellor @ Broadcom
++ * Luke Diamand @ Broadcom
++ *
++ * MMAL structures
++ *
++ */
++#ifndef MMAL_COMMON_H
++#define MMAL_COMMON_H
++
++#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 BIT_ULL(63)
++
++struct mmal_msg_context;
++
++/* 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 */
++ bool remove_padding; /* Does the GPU have to remove padding,
++ * or can we do hide padding via bytesperline.
++ */
++};
++
++/* 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_msg_context *msg_context;
++};
++
++/* */
++struct mmal_colourfx {
++ s32 enable;
++ u32 u;
++ u32 v;
++};
++#endif
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
+@@ -0,0 +1,124 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ * Dave Stevenson @ Broadcom
++ * (now dave.stevenson@raspberrypi.org)
++ * Simon Mellor @ Broadcom
++ * Luke Diamand @ Broadcom
++ */
++#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 */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h
+@@ -0,0 +1,48 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ * Dave Stevenson @ Broadcom
++ * (now dave.stevenson@raspberrypi.org)
++ * Simon Mellor @ Broadcom
++ * Luke Diamand @ Broadcom
++ */
++
++#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 */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h
+@@ -0,0 +1,106 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ * Dave Stevenson @ Broadcom
++ * (now dave.stevenson@raspberrypi.org)
++ * Simon Mellor @ Broadcom
++ * Luke Diamand @ Broadcom
++ */
++
++#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
++ * 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_local {
++ 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; /* 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 */
++};
++
++/* Remote 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.
++ */
++
++ u32 es; /* 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 */
++ u32 extradata; /* Codec specific data */
++};
++
++#endif /* MMAL_MSG_FORMAT_H */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h
+@@ -0,0 +1,109 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ * Dave Stevenson @ Broadcom
++ * (now dave.stevenson@raspberrypi.org)
++ * Simon Mellor @ Broadcom
++ * Luke Diamand @ Broadcom
++ */
++
++/* 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
++ * structures within the message. When used to set values only the
++ * buffer_num, buffer_size and userdata parameters are writable.
++ */
++struct mmal_port {
++ u32 priv; /* Private member used by the framework */
++ u32 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) */
++ u32 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.
++ */
++
++ u32 component; /* Component this port belongs to (Read Only) */
++
++ u32 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.
++ */
++};
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
+@@ -0,0 +1,406 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ * Dave Stevenson @ Broadcom
++ * (now dave.stevenson@raspberrypi.org)
++ * Simon Mellor @ Broadcom
++ * Luke Diamand @ Broadcom
++ */
++
++/*
++ * 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
++ */
++#ifndef MMAL_MSG_H
++#define MMAL_MSG_H
++
++#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, /* Unknown 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 */
++ u32 control_service;
++
++ u32 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 {
++ u32 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; /* elementary 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 BIT(0)
++/* Signals that the start of the current payload starts a frame */
++#define MMAL_BUFFER_HEADER_FLAG_FRAME_START BIT(1)
++/* Signals that the end of the current payload ends a frame */
++#define MMAL_BUFFER_HEADER_FLAG_FRAME_END BIT(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 BIT(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 BIT(4)
++/*
++ * Signals a buffer containing some kind of config data for the component
++ * (e.g. codec config data)
++ */
++#define MMAL_BUFFER_HEADER_FLAG_CONFIG BIT(5)
++/* Signals an encrypted payload */
++#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED BIT(6)
++/* Signals a buffer containing side information */
++#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO BIT(7)
++/*
++ * Signals a buffer which is the snapshot/postview image from a stills
++ * capture
++ */
++#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT BIT(8)
++/* Signals a buffer which contains data known to be corrupted */
++#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED BIT(9)
++/* Signals that a buffer failed to be transmitted */
++#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED BIT(10)
++
++struct mmal_driver_buffer {
++ u32 magic;
++ u32 component_handle;
++ u32 port_handle;
++ u32 client_context;
++};
++
++/* buffer header */
++struct mmal_buffer_header {
++ u32 next; /* next header */
++ u32 priv; /* framework private data */
++ u32 cmd;
++ u32 data;
++ u32 alloc_size;
++ u32 length;
++ u32 offset;
++ u32 flags;
++ s64 pts;
++ s64 dts;
++ u32 type;
++ u32 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 {
++ u32 client_component; /* component context */
++
++ u32 port_type;
++ u32 port_num;
++
++ u32 cmd;
++ u32 length;
++ u8 data[MMAL_WORKER_EVENT_SPACE];
++ u32 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;
++};
++#endif
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
+@@ -0,0 +1,755 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ * Dave Stevenson @ Broadcom
++ * (now dave.stevenson@raspberrypi.org)
++ * Simon Mellor @ Broadcom
++ * Luke Diamand @ Broadcom
++ */
++
++/* common parameters */
++
++/** @name Parameter groups
++ * Parameters are divided into groups, and then allocated sequentially within
++ * a group using an enum.
++ * @{
++ */
++
++#ifndef MMAL_PARAMETERS_H
++#define MMAL_PARAMETERS_H
++
++/** 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 {
++ /**< Never a valid parameter ID */
++ MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON,
++
++ /**< MMAL_PARAMETER_ENCODING_T */
++ MMAL_PARAMETER_SUPPORTED_ENCODINGS,
++ /**< MMAL_PARAMETER_URI_T */
++ MMAL_PARAMETER_URI,
++ /** 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_T */
++ MMAL_PARAMETER_STATISTICS,
++ /**< MMAL_PARAMETER_CORE_STATISTICS_T */
++ MMAL_PARAMETER_CORE_STATISTICS,
++ /**< MMAL_PARAMETER_MEM_USAGE_T */
++ MMAL_PARAMETER_MEM_USAGE,
++ /**< MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_BUFFER_FLAG_FILTER,
++ /**< MMAL_PARAMETER_SEEK_T */
++ MMAL_PARAMETER_SEEK,
++ /**< MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_POWERMON_ENABLE,
++ /**< MMAL_PARAMETER_LOGGING_T */
++ MMAL_PARAMETER_LOGGING,
++ /**< MMAL_PARAMETER_UINT64_T */
++ MMAL_PARAMETER_SYSTEM_TIME,
++ /**< MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_NO_IMAGE_PADDING,
++};
++
++/* camera parameters */
++
++enum mmal_parameter_camera_type {
++ /* 0 */
++ /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
++ MMAL_PARAMETER_THUMBNAIL_CONFIGURATION =
++ MMAL_PARAMETER_GROUP_CAMERA,
++ /**< Unused? */
++ MMAL_PARAMETER_CAPTURE_QUALITY,
++ /**< @ref MMAL_PARAMETER_INT32_T */
++ MMAL_PARAMETER_ROTATION,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_EXIF_DISABLE,
++ /**< @ref MMAL_PARAMETER_EXIF_T */
++ MMAL_PARAMETER_EXIF,
++ /**< @ref MMAL_PARAM_AWBMODE_T */
++ MMAL_PARAMETER_AWB_MODE,
++ /**< @ref MMAL_PARAMETER_IMAGEFX_T */
++ MMAL_PARAMETER_IMAGE_EFFECT,
++ /**< @ref MMAL_PARAMETER_COLOURFX_T */
++ MMAL_PARAMETER_COLOUR_EFFECT,
++ /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
++ MMAL_PARAMETER_FLICKER_AVOID,
++ /**< @ref MMAL_PARAMETER_FLASH_T */
++ MMAL_PARAMETER_FLASH,
++ /**< @ref MMAL_PARAMETER_REDEYE_T */
++ MMAL_PARAMETER_REDEYE,
++ /**< @ref MMAL_PARAMETER_FOCUS_T */
++ MMAL_PARAMETER_FOCUS,
++ /**< Unused? */
++ MMAL_PARAMETER_FOCAL_LENGTHS,
++ /**< @ref MMAL_PARAMETER_INT32_T */
++ MMAL_PARAMETER_EXPOSURE_COMP,
++ /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
++ MMAL_PARAMETER_ZOOM,
++ /**< @ref MMAL_PARAMETER_MIRROR_T */
++ MMAL_PARAMETER_MIRROR,
++
++ /* 0x10 */
++ /**< @ref MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_CAMERA_NUM,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_CAPTURE,
++ /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
++ MMAL_PARAMETER_EXPOSURE_MODE,
++ /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
++ MMAL_PARAMETER_EXP_METERING_MODE,
++ /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
++ MMAL_PARAMETER_FOCUS_STATUS,
++ /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
++ MMAL_PARAMETER_CAMERA_CONFIG,
++ /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
++ MMAL_PARAMETER_CAPTURE_STATUS,
++ /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
++ MMAL_PARAMETER_FACE_TRACK,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
++ /**< @ref MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_JPEG_Q_FACTOR,
++ /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
++ MMAL_PARAMETER_FRAME_RATE,
++ /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
++ MMAL_PARAMETER_USE_STC,
++ /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
++ MMAL_PARAMETER_CAMERA_INFO,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_VIDEO_STABILISATION,
++ /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
++ MMAL_PARAMETER_FACE_TRACK_RESULTS,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_ENABLE_RAW_CAPTURE,
++
++ /* 0x20 */
++ /**< @ref MMAL_PARAMETER_URI_T */
++ MMAL_PARAMETER_DPF_FILE,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_ENABLE_DPF_FILE,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
++ /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
++ MMAL_PARAMETER_CAPTURE_MODE,
++ /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
++ MMAL_PARAMETER_FOCUS_REGIONS,
++ /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
++ MMAL_PARAMETER_INPUT_CROP,
++ /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
++ MMAL_PARAMETER_SENSOR_INFORMATION,
++ /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
++ MMAL_PARAMETER_FLASH_SELECT,
++ /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
++ MMAL_PARAMETER_FIELD_OF_VIEW,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
++ /**< @ref MMAL_PARAMETER_DRC_T */
++ MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,
++ /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
++ MMAL_PARAMETER_ALGORITHM_CONTROL,
++ /**< @ref MMAL_PARAMETER_RATIONAL_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,
++
++ /* 0x30 */
++ /**< @ref MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_ISO,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_ANTISHAKE,
++ /** @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,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_JPEG_ATTACH_LOG,
++ /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
++ MMAL_PARAMETER_ZERO_SHUTTER_LAG,
++ /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
++ MMAL_PARAMETER_FPS_RANGE,
++ /**< @ref MMAL_PARAMETER_INT32_T */
++ MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP,
++
++ /* 0x40 */
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_SW_SHARPEN_DISABLE,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_FLASH_REQUIRED,
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_SW_SATURATION_DISABLE,
++ /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_SHUTTER_SPEED,
++ /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
++ MMAL_PARAMETER_CUSTOM_AWB_GAINS,
++};
++
++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,
++};
++
++/* rectangle, used lots so it gets its own struct */
++struct vchiq_mmal_rect {
++ s32 x;
++ s32 y;
++ s32 width;
++ s32 height;
++};
++
++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];
++};
++
++#endif
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -0,0 +1,166 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ * Dave Stevenson @ Broadcom
++ * (now dave.stevenson@raspberrypi.org)
++ * Simon Mellor @ Broadcom
++ * Luke Diamand @ Broadcom
++ *
++ * 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 */
++};
++
++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_local format;
++ /* elementary 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 buffers the VPU has yet to return */
++ atomic_t buffers_with_vpu;
++ /* 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 appropriate 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);
++
++int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
++ struct mmal_buffer *buf);
++int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf);
++#endif /* MMAL_VCHIQ_H */
+++ /dev/null
-From d62b10483e89fbd3adc2cde272234ad5300d9a42 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 8 Oct 2018 18:26:15 +0100
-Subject: [PATCH 265/703] staging: bcm2835-camera: Correct
- V4L2_CID_COLORFX_CBCR behaviour
-
-With V4L2_CID_COLORFX_CBCR calling ctrl_set_colfx it was incorrectly
-assigning the colour values to the enable field of dev->colourfx
-instead of the u and v fields.
-
-Correct the assignments.
-
-Reported as a Coverity issue
-Detected by CoverityScan CID#1419711 ("Unused value")
-
-Reported-by: Colin Ian King <colin.king@canonical.com>
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/bcm2835-camera/controls.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -578,8 +578,8 @@ static int ctrl_set_colfx(struct bm2835_
-
- control = &dev->component[COMP_CAMERA]->control;
-
-- dev->colourfx.enable = (ctrl->val & 0xff00) >> 8;
-- dev->colourfx.enable = ctrl->val & 0xff;
-+ dev->colourfx.u = (ctrl->val & 0xff00) >> 8;
-+ dev->colourfx.v = ctrl->val & 0xff;
-
- ret = vchiq_mmal_port_parameter_set(dev->instance, control,
- MMAL_PARAMETER_COLOUR_EFFECT,
--- /dev/null
+From 0be8a2fb0d0986f48ba31375f9c5a8620aa82edd Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 16:51:13 +0100
+Subject: [PATCH 265/725] staging: mmal-vchiq: Allocate and free components as
+ required
+
+The existing code assumed that there would only ever be 4 components,
+and never freed the entries once used.
+Allow arbitrary creation and destruction of components.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/vchiq-mmal/mmal-vchiq.c | 29 ++++++++++++-------
+ .../vc04_services/vchiq-mmal/mmal-vchiq.h | 1 +
+ 2 files changed, 20 insertions(+), 10 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -38,8 +38,11 @@ MODULE_AUTHOR("Dave Stevenson, <dave.ste
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION("0.0.1");
+
+-/* maximum number of components supported */
+-#define VCHIQ_MMAL_MAX_COMPONENTS 4
++/*
++ * maximum number of components supported.
++ * This matches the maximum permitted by default on the VPU
++ */
++#define VCHIQ_MMAL_MAX_COMPONENTS 64
+
+ /*#define FULL_MSG_DUMP 1*/
+
+@@ -174,8 +177,6 @@ struct vchiq_mmal_instance {
+ /* protect accesses to context_map */
+ struct mutex context_map_lock;
+
+- /* component to use next */
+- int component_idx;
+ struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
+
+ /* ordered workqueue to process all bulk operations */
+@@ -1632,18 +1633,24 @@ int vchiq_mmal_component_init(struct vch
+ {
+ int ret;
+ int idx; /* port index */
+- struct vchiq_mmal_component *component;
++ struct vchiq_mmal_component *component = NULL;
+
+ if (mutex_lock_interruptible(&instance->vchiq_mutex))
+ return -EINTR;
+
+- if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) {
++ for (idx = 0; idx < VCHIQ_MMAL_MAX_COMPONENTS; idx++) {
++ if (!instance->component[idx].in_use) {
++ component = &instance->component[idx];
++ component->in_use = 1;
++ break;
++ }
++ }
++
++ if (!component) {
+ ret = -EINVAL; /* todo is this correct error? */
+ goto unlock;
+ }
+
+- component = &instance->component[instance->component_idx];
+-
+ ret = create_component(instance, component, name);
+ if (ret < 0) {
+ pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
+@@ -1694,8 +1701,6 @@ int vchiq_mmal_component_init(struct vch
+ goto release_component;
+ }
+
+- instance->component_idx++;
+-
+ *component_out = component;
+
+ mutex_unlock(&instance->vchiq_mutex);
+@@ -1705,6 +1710,8 @@ int vchiq_mmal_component_init(struct vch
+ release_component:
+ destroy_component(instance, component);
+ unlock:
++ if (component)
++ component->in_use = 0;
+ mutex_unlock(&instance->vchiq_mutex);
+
+ return ret;
+@@ -1727,6 +1734,8 @@ int vchiq_mmal_component_finalise(struct
+
+ ret = destroy_component(instance, component);
+
++ component->in_use = 0;
++
+ mutex_unlock(&instance->vchiq_mutex);
+
+ return ret;
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -82,6 +82,7 @@ struct vchiq_mmal_port {
+ };
+
+ struct vchiq_mmal_component {
++ u32 in_use:1;
+ bool enabled;
+ u32 handle; /* VideoCore handle for component */
+ u32 inputs; /* Number of input ports */
+++ /dev/null
-From dac082334ccbfa6a051fdc48700f64e8412169d5 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 28 Sep 2018 10:22:26 +0100
-Subject: [PATCH 266/703] staging: bcm2835-camera: Remove/amend some obsolete
- comments
-
-Remove a todo which has been done.
-Remove a template line that was redundant.
-Make a comment clearer as to the non-obvious meaning of a field.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/bcm2835-camera/controls.c | 11 +----------
- 1 file changed, 1 insertion(+), 10 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -965,10 +965,6 @@ static const struct bm2835_mmal_v4l2_ctr
- &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, V4L2_EXPOSURE_APERTURE_PRIORITY, V4L2_EXPOSURE_AUTO, 0,
-@@ -976,11 +972,6 @@ static const struct bm2835_mmal_v4l2_ctr
- &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 */
-@@ -1146,7 +1137,7 @@ static const struct bm2835_mmal_v4l2_ctr
- },
- {
- V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
-- -1, /* Min is computed at runtime */
-+ -1, /* Min (mask) is computed at runtime */
- V4L2_SCENE_MODE_TEXT,
- V4L2_SCENE_MODE_NONE, 1, NULL,
- MMAL_PARAMETER_PROFILE,
--- /dev/null
+From 4938924a490f11659b8661bbe9a7f250c2a62237 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Oct 2018 16:20:46 +0000
+Subject: [PATCH 266/725] staging: mmal-vchiq: Avoid use of bool in structures
+
+Fixes up a checkpatch error "Avoid using bool structure members
+because of possible alignment issues".
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 14 +++++++-------
+ .../staging/vc04_services/vchiq-mmal/mmal-vchiq.h | 4 ++--
+ 2 files changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -861,9 +861,9 @@ static int port_info_get(struct vchiq_mm
+ goto release_msg;
+
+ if (rmsg->u.port_info_get_reply.port.is_enabled == 0)
+- port->enabled = false;
++ port->enabled = 0;
+ else
+- port->enabled = true;
++ port->enabled = 1;
+
+ /* copy the values out of the message */
+ port->handle = rmsg->u.port_info_get_reply.port_handle;
+@@ -1300,7 +1300,7 @@ static int port_disable(struct vchiq_mma
+ if (!port->enabled)
+ return 0;
+
+- port->enabled = false;
++ port->enabled = 0;
+
+ ret = port_action_port(instance, port,
+ MMAL_MSG_PORT_ACTION_TYPE_DISABLE);
+@@ -1352,7 +1352,7 @@ static int port_enable(struct vchiq_mmal
+ if (ret)
+ goto done;
+
+- port->enabled = true;
++ port->enabled = 1;
+
+ if (port->buffer_cb) {
+ /* send buffer headers to videocore */
+@@ -1524,7 +1524,7 @@ int vchiq_mmal_port_connect_tunnel(struc
+ pr_err("failed disconnecting src port\n");
+ goto release_unlock;
+ }
+- src->connected->enabled = false;
++ src->connected->enabled = 0;
+ src->connected = NULL;
+ }
+
+@@ -1760,7 +1760,7 @@ int vchiq_mmal_component_enable(struct v
+
+ ret = enable_component(instance, component);
+ if (ret == 0)
+- component->enabled = true;
++ component->enabled = 1;
+
+ mutex_unlock(&instance->vchiq_mutex);
+
+@@ -1786,7 +1786,7 @@ int vchiq_mmal_component_disable(struct
+
+ ret = disable_component(instance, component);
+ if (ret == 0)
+- component->enabled = false;
++ component->enabled = 0;
+
+ mutex_unlock(&instance->vchiq_mutex);
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -48,7 +48,7 @@ typedef void (*vchiq_mmal_buffer_cb)(
+ unsigned long length, u32 mmal_flags, s64 dts, s64 pts);
+
+ struct vchiq_mmal_port {
+- bool enabled;
++ u32 enabled:1;
+ u32 handle;
+ u32 type; /* port type, cached to use on port info set */
+ u32 index; /* port index, cached to use on port info set */
+@@ -83,7 +83,7 @@ struct vchiq_mmal_port {
+
+ struct vchiq_mmal_component {
+ u32 in_use:1;
+- bool enabled;
++ u32 enabled:1;
+ u32 handle; /* VideoCore handle for component */
+ u32 inputs; /* Number of input ports */
+ u32 outputs; /* Number of output ports */
--- /dev/null
+From 609bd5dbe6c1f9cbe2fc50124e4e8a99e4a5042a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 16:57:09 +0100
+Subject: [PATCH 267/725] staging: mmal-vchiq: Make timeout a defined parameter
+
+The timeout period for VPU communications is a useful thing
+to extend when debugging.
+Set it via a define, rather than a magic number buried in the code.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -44,6 +44,12 @@ MODULE_VERSION("0.0.1");
+ */
+ #define VCHIQ_MMAL_MAX_COMPONENTS 64
+
++/*
++ * Timeout for synchronous msg responses in seconds.
++ * Helpful to increase this if stopping in the VPU debugger.
++ */
++#define SYNC_MSG_TIMEOUT 3
++
+ /*#define FULL_MSG_DUMP 1*/
+
+ #ifdef DEBUG
+@@ -692,7 +698,7 @@ static int send_synchronous_mmal_msg(str
+ }
+
+ timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt,
+- 3 * HZ);
++ SYNC_MSG_TIMEOUT * HZ);
+ if (timeout == 0) {
+ pr_err("timed out waiting for sync completion\n");
+ ret = -ETIME;
+++ /dev/null
-From abd417b71f4b157cb183cab26620d08c303ce805 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Sep 2018 16:30:37 +0100
-Subject: [PATCH 267/703] staging: vc04_services: Split vchiq-mmal into a
- module
-
-In preparation for adding a video codec V4L2 module which also
-wants to use vchiq-mmal functions, split it out into an
-independent module.
-The minimum number of changes have been made to achieve this
-(eg straight moves where possible) so existing checkpatch
-errors will still be present.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/Kconfig | 1 +
- drivers/staging/vc04_services/Makefile | 1 +
- .../vc04_services/bcm2835-camera/Kconfig | 2 +-
- .../vc04_services/bcm2835-camera/Makefile | 4 ++--
- .../staging/vc04_services/vchiq-mmal/Kconfig | 7 ++++++
- .../staging/vc04_services/vchiq-mmal/Makefile | 8 +++++++
- .../mmal-common.h | 0
- .../mmal-encodings.h | 0
- .../mmal-msg-common.h | 0
- .../mmal-msg-format.h | 0
- .../mmal-msg-port.h | 0
- .../{bcm2835-camera => vchiq-mmal}/mmal-msg.h | 0
- .../mmal-parameters.h | 0
- .../mmal-vchiq.c | 22 +++++++++++++++++++
- .../mmal-vchiq.h | 0
- 15 files changed, 42 insertions(+), 3 deletions(-)
- create mode 100644 drivers/staging/vc04_services/vchiq-mmal/Kconfig
- create mode 100644 drivers/staging/vc04_services/vchiq-mmal/Makefile
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-common.h (100%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-encodings.h (100%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-common.h (100%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-format.h (100%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-port.h (100%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg.h (100%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-parameters.h (100%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-vchiq.c (98%)
- rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-vchiq.h (100%)
-
---- a/drivers/staging/vc04_services/Kconfig
-+++ b/drivers/staging/vc04_services/Kconfig
-@@ -21,6 +21,7 @@ config BCM2835_VCHIQ
- source "drivers/staging/vc04_services/bcm2835-audio/Kconfig"
-
- source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
-+source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
-
- endif
-
---- a/drivers/staging/vc04_services/Makefile
-+++ b/drivers/staging/vc04_services/Makefile
-@@ -12,6 +12,7 @@ vchiq-objs := \
-
- obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/
- obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/
-+obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
-
- ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000
-
---- a/drivers/staging/vc04_services/bcm2835-camera/Kconfig
-+++ b/drivers/staging/vc04_services/bcm2835-camera/Kconfig
-@@ -2,7 +2,7 @@ config VIDEO_BCM2835
- tristate "BCM2835 Camera"
- depends on MEDIA_SUPPORT
- depends on VIDEO_V4L2 && (ARCH_BCM2835 || COMPILE_TEST)
-- select BCM2835_VCHIQ
-+ select BCM2835_VCHIQ_MMAL
- select VIDEOBUF2_VMALLOC
- select BTREE
- help
---- a/drivers/staging/vc04_services/bcm2835-camera/Makefile
-+++ b/drivers/staging/vc04_services/bcm2835-camera/Makefile
-@@ -1,11 +1,11 @@
- # SPDX-License-Identifier: GPL-2.0
- bcm2835-v4l2-$(CONFIG_VIDEO_BCM2835) := \
- bcm2835-camera.o \
-- controls.o \
-- mmal-vchiq.o
-+ controls.o
-
- obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-v4l2.o
-
- ccflags-y += \
- -Idrivers/staging/vc04_services \
-+ -Idrivers/staging/vc04_services/vchiq-mmal \
- -D__VCCOREVER__=0x04000000
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/Kconfig
-@@ -0,0 +1,7 @@
-+config BCM2835_VCHIQ_MMAL
-+ tristate "BCM2835 MMAL VCHIQ service"
-+ depends on (ARCH_BCM2835 || COMPILE_TEST)
-+ select BCM2835_VCHIQ
-+ help
-+ Enables the MMAL API over VCHIQ as used for the
-+ majority of the multimedia services on VideoCore.
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/Makefile
-@@ -0,0 +1,8 @@
-+# SPDX-License-Identifier: GPL-2.0
-+bcm2835-mmal-vchiq-objs := mmal-vchiq.o
-+
-+obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += bcm2835-mmal-vchiq.o
-+
-+ccflags-y += \
-+ -Idrivers/staging/vc04_services \
-+ -D__VCCOREVER__=0x04000000
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -0,0 +1,1921 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ * Dave Stevenson @ Broadcom
-+ * (now dave.stevenson@raspberrypi.org)
-+ * Simon Mellor @ Broadcom
-+ * Luke Diamand @ Broadcom
-+ *
-+ * V4L2 driver MMAL vchiq interface code
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/errno.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/mutex.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/completion.h>
-+#include <linux/vmalloc.h>
-+#include <asm/cacheflush.h>
-+#include <media/videobuf2-vmalloc.h>
-+
-+#include "mmal-common.h"
-+#include "mmal-vchiq.h"
-+#include "mmal-msg.h"
-+
-+#define USE_VCHIQ_ARM
-+#include "interface/vchi/vchi.h"
-+
-+MODULE_DESCRIPTION("BCM2835 MMAL VCHIQ interface");
-+MODULE_AUTHOR("Dave Stevenson, <dave.stevenson@raspberrypi.org>");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION("0.0.1");
-+
-+/* 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: ", DUMP_PREFIX_OFFSET, \
-+ 16, 4, (MSG), \
-+ sizeof(struct mmal_msg_header), 1); \
-+ print_hex_dump(KERN_DEBUG, "<<p: ", DUMP_PREFIX_OFFSET, \
-+ 16, 4, \
-+ ((u8 *)(MSG)) + sizeof(struct mmal_msg_header),\
-+ (MSG_LEN) - sizeof(struct mmal_msg_header), 1); \
-+ } while (0)
-+#else
-+#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE) \
-+ { \
-+ pr_debug(TITLE" type:%s(%d) length:%d\n", \
-+ msg_type_names[(MSG)->h.type], \
-+ (MSG)->h.type, (MSG_LEN)); \
-+ }
-+#endif
-+#else
-+#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)
-+#endif
-+
-+struct vchiq_mmal_instance;
-+
-+/* normal message context */
-+struct mmal_msg_context {
-+ struct vchiq_mmal_instance *instance;
-+
-+ /* Index in the context_map idr so that we can find the
-+ * mmal_msg_context again when servicing the VCHI reply.
-+ */
-+ int handle;
-+
-+ union {
-+ struct {
-+ /* work struct for buffer_cb callback */
-+ struct work_struct work;
-+ /* work struct for deferred callback */
-+ struct work_struct buffer_to_host_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;
-+
-+ /* vmalloc page to receive scratch bulk xfers into */
-+ void *bulk_scratch;
-+
-+ struct idr context_map;
-+ /* protect accesses to context_map */
-+ struct mutex context_map_lock;
-+
-+ /* component to use next */
-+ int component_idx;
-+ struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
-+
-+ /* ordered workqueue to process all bulk operations */
-+ struct workqueue_struct *bulk_wq;
-+};
-+
-+static struct mmal_msg_context *
-+get_msg_context(struct vchiq_mmal_instance *instance)
-+{
-+ struct mmal_msg_context *msg_context;
-+ int handle;
-+
-+ /* todo: should this be allocated from a pool to avoid kzalloc */
-+ msg_context = kzalloc(sizeof(*msg_context), GFP_KERNEL);
-+
-+ if (!msg_context)
-+ return ERR_PTR(-ENOMEM);
-+
-+ /* Create an ID that will be passed along with our message so
-+ * that when we service the VCHI reply, we can look up what
-+ * message is being replied to.
-+ */
-+ mutex_lock(&instance->context_map_lock);
-+ handle = idr_alloc(&instance->context_map, msg_context,
-+ 0, 0, GFP_KERNEL);
-+ mutex_unlock(&instance->context_map_lock);
-+
-+ if (handle < 0) {
-+ kfree(msg_context);
-+ return ERR_PTR(handle);
-+ }
-+
-+ msg_context->instance = instance;
-+ msg_context->handle = handle;
-+
-+ return msg_context;
-+}
-+
-+static struct mmal_msg_context *
-+lookup_msg_context(struct vchiq_mmal_instance *instance, int handle)
-+{
-+ return idr_find(&instance->context_map, handle);
-+}
-+
-+static void
-+release_msg_context(struct mmal_msg_context *msg_context)
-+{
-+ struct vchiq_mmal_instance *instance = msg_context->instance;
-+
-+ mutex_lock(&instance->context_map_lock);
-+ idr_remove(&instance->context_map, msg_context->handle);
-+ mutex_unlock(&instance->context_map_lock);
-+ 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:%u 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 =
-+ container_of(work, struct mmal_msg_context, u.bulk.work);
-+
-+ atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
-+
-+ 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);
-+}
-+
-+/* workqueue scheduled callback to handle receiving buffers
-+ *
-+ * VCHI will allow up to 4 bulk receives to be scheduled before blocking.
-+ * If we block in the service_callback context then we can't process the
-+ * VCHI_CALLBACK_BULK_RECEIVED message that would otherwise allow the blocked
-+ * vchi_bulk_queue_receive() call to complete.
-+ */
-+static void buffer_to_host_work_cb(struct work_struct *work)
-+{
-+ struct mmal_msg_context *msg_context =
-+ container_of(work, struct mmal_msg_context,
-+ u.bulk.buffer_to_host_work);
-+ struct vchiq_mmal_instance *instance = msg_context->instance;
-+ unsigned long len = msg_context->u.bulk.buffer_used;
-+ int ret;
-+
-+ if (!len)
-+ /* Dummy receive to ensure the buffers remain in order */
-+ len = 8;
-+ /* 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
-+ */
-+ (len + 3) & ~3,
-+ VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
-+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
-+ msg_context);
-+
-+ vchi_service_release(instance->handle);
-+
-+ if (ret != 0)
-+ pr_err("%s: ctx: %p, vchi_bulk_queue_receive failed %d\n",
-+ __func__, msg_context, ret);
-+}
-+
-+/* 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;
-+
-+ rd_len = msg->u.buffer_from_host.buffer_header.length;
-+
-+ if (!msg_context->u.bulk.buffer) {
-+ pr_err("bulk.buffer not configured - error in buffer_from_host\n");
-+
-+ /* todo: this is a serious error, we should never have
-+ * committed 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?
-+ */
-+
-+ return -EINVAL;
-+ }
-+
-+ /* 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.dts = msg->u.buffer_from_host.buffer_header.dts;
-+ msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
-+
-+ queue_work(msg_context->instance->bulk_wq,
-+ &msg_context->u.bulk.buffer_to_host_work);
-+
-+ return 0;
-+}
-+
-+/* 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)
-+{
-+ 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;
-+
-+ if (!port->enabled)
-+ return -EINVAL;
-+
-+ pr_debug("instance:%p buffer:%p\n", instance->handle, buf);
-+
-+ /* get context */
-+ if (!buf->msg_context) {
-+ pr_err("%s: msg_context not allocated, buf %p\n", __func__,
-+ buf);
-+ return -EINVAL;
-+ }
-+ msg_context = buf->msg_context;
-+
-+ /* 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 = buf;
-+ msg_context->u.bulk.buffer_used = 0;
-+
-+ /* initialise work structure ready to schedule callback */
-+ INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
-+ INIT_WORK(&msg_context->u.bulk.buffer_to_host_work,
-+ buffer_to_host_work_cb);
-+
-+ atomic_inc(&port->buffers_with_vpu);
-+
-+ /* 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->handle;
-+ 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->handle;
-+
-+ /* buffer header */
-+ m.u.buffer_from_host.buffer_header.cmd = 0;
-+ m.u.buffer_from_host.buffer_header.data =
-+ (u32)(unsigned long)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_queue_kernel_message(instance->handle,
-+ &m,
-+ sizeof(struct mmal_msg_header) +
-+ sizeof(m.u.buffer_from_host));
-+
-+ vchi_service_release(instance->handle);
-+
-+ 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;
-+ u32 handle;
-+
-+ pr_debug("%s: instance:%p msg:%p msg_len:%d\n",
-+ __func__, instance, msg, msg_len);
-+
-+ if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
-+ handle = msg->u.buffer_from_host.drvbuf.client_context;
-+ msg_context = lookup_msg_context(instance, handle);
-+
-+ if (!msg_context) {
-+ pr_err("drvbuf.client_context(%u) is invalid\n",
-+ handle);
-+ return;
-+ }
-+ } else {
-+ pr_err("MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n");
-+ return;
-+ }
-+
-+ msg_context->u.bulk.mmal_flags =
-+ msg->u.buffer_from_host.buffer_header.flags;
-+
-+ 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 =
-+ bulk_receive(instance, msg, 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;
-+ }
-+
-+ /* 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)
-+{
-+ 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);
-+
-+ 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;
-+ struct mmal_msg_context *msg_context;
-+
-+ 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 dependent on header context to complete */
-+ if (!msg->h.context) {
-+ pr_err("received message context was null!\n");
-+ vchi_held_msg_release(&msg_handle);
-+ break;
-+ }
-+
-+ msg_context = lookup_msg_context(instance,
-+ msg->h.context);
-+ if (!msg_context) {
-+ pr_err("received invalid message context %u!\n",
-+ msg->h.context);
-+ vchi_held_msg_release(&msg_handle);
-+ break;
-+ }
-+
-+ /* fill in context values */
-+ msg_context->u.sync.msg_handle = msg_handle;
-+ msg_context->u.sync.msg = msg;
-+ msg_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_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;
-+ unsigned long timeout;
-+
-+ /* 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,
-+ (int)(MMAL_MSG_MAX_SIZE -
-+ sizeof(struct mmal_msg_header)));
-+ return -EINVAL;
-+ }
-+
-+ msg_context = get_msg_context(instance);
-+ if (IS_ERR(msg_context))
-+ return PTR_ERR(msg_context);
-+
-+ init_completion(&msg_context->u.sync.cmplt);
-+
-+ msg->h.magic = MMAL_MAGIC;
-+ msg->h.context = msg_context->handle;
-+ msg->h.status = 0;
-+
-+ DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len),
-+ ">>> sync message");
-+
-+ vchi_service_use(instance->handle);
-+
-+ ret = vchi_queue_kernel_message(instance->handle,
-+ msg,
-+ sizeof(struct mmal_msg_header) +
-+ payload_len);
-+
-+ vchi_service_release(instance->handle);
-+
-+ if (ret) {
-+ pr_err("error %d queuing message\n", ret);
-+ release_msg_context(msg_context);
-+ return ret;
-+ }
-+
-+ timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt,
-+ 3 * HZ);
-+ if (timeout == 0) {
-+ pr_err("timed out waiting for sync completion\n");
-+ ret = -ETIME;
-+ /* todo: what happens if the message arrives after aborting */
-+ release_msg_context(msg_context);
-+ return ret;
-+ }
-+
-+ *msg_out = msg_context->u.sync.msg;
-+ *msg_handle_out = msg_context->u.sync.msg_handle;
-+ release_msg_context(msg_context);
-+
-+ 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("elementary stream: type:%d encoding:0x%x variant: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 = (u32)(unsigned long)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);
-+
-+ /* elementary 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 retrieve 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 because
-+ * 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;
-+
-+ /* elementary 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 = (u32)(unsigned long)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;
-+ /* 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
-+ */
-+ 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. This should only
-+ * apply to buffers that have been queued before the port
-+ * has been enabled. If the port has been enabled and buffers
-+ * passed, then the buffers should have been removed from this
-+ * list, and we should get the relevant callbacks via VCHIQ
-+ * to release the buffers.
-+ */
-+ 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 *q, *buf_head;
-+ int ret;
-+
-+ if (port->enabled)
-+ return 0;
-+
-+ 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_safe(buf_head, q, &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;
-+
-+ list_del(buf_head);
-+ 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;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_port_set_format);
-+
-+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;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set);
-+
-+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;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_get);
-+
-+/* 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;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_port_enable);
-+
-+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;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_port_disable);
-+
-+/* 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) {
-+ 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) {
-+ /* 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;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_port_connect_tunnel);
-+
-+int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
-+ struct vchiq_mmal_port *port,
-+ struct mmal_buffer *buffer)
-+{
-+ unsigned long flags = 0;
-+ int ret;
-+
-+ ret = buffer_from_host(instance, port, buffer);
-+ if (ret == -EINVAL) {
-+ /* Port is disabled. Queue for when it is enabled. */
-+ spin_lock_irqsave(&port->slock, flags);
-+ list_add_tail(&buffer->list, &port->buffers);
-+ spin_unlock_irqrestore(&port->slock, flags);
-+ }
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_submit_buffer);
-+
-+int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
-+ struct mmal_buffer *buf)
-+{
-+ struct mmal_msg_context *msg_context = get_msg_context(instance);
-+
-+ if (IS_ERR(msg_context))
-+ return (PTR_ERR(msg_context));
-+
-+ buf->msg_context = msg_context;
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(mmal_vchi_buffer_init);
-+
-+int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
-+{
-+ struct mmal_msg_context *msg_context = buf->msg_context;
-+
-+ if (msg_context)
-+ release_msg_context(msg_context);
-+ buf->msg_context = NULL;
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
-+
-+/* 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) {
-+ pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
-+ __func__, ret);
-+ 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;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_component_init);
-+
-+/*
-+ * 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;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_component_finalise);
-+
-+/*
-+ * 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;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_component_enable);
-+
-+/*
-+ * 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;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_component_disable);
-+
-+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;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_version);
-+
-+int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance)
-+{
-+ int status = 0;
-+
-+ if (!instance)
-+ 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\n");
-+
-+ mutex_unlock(&instance->vchiq_mutex);
-+
-+ flush_workqueue(instance->bulk_wq);
-+ destroy_workqueue(instance->bulk_wq);
-+
-+ vfree(instance->bulk_scratch);
-+
-+ idr_destroy(&instance->context_map);
-+
-+ kfree(instance);
-+
-+ return status;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_finalise);
-+
-+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 = {
-+ .version = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
-+ .service_id = VC_MMAL_SERVER_NAME,
-+ .connection = vchi_connection,
-+ .rx_fifo_size = 0,
-+ .tx_fifo_size = 0,
-+ .callback = service_callback,
-+ .callback_param = NULL,
-+ .want_unaligned_bulk_rx = 1,
-+ .want_unaligned_bulk_tx = 1,
-+ .want_crc = 0
-+ };
-+
-+ /* 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 = kzalloc(sizeof(*instance), GFP_KERNEL);
-+
-+ if (!instance)
-+ return -ENOMEM;
-+
-+ mutex_init(&instance->vchiq_mutex);
-+
-+ instance->bulk_scratch = vmalloc(PAGE_SIZE);
-+
-+ mutex_init(&instance->context_map_lock);
-+ idr_init_base(&instance->context_map, 1);
-+
-+ params.callback_param = instance;
-+
-+ instance->bulk_wq = alloc_ordered_workqueue("mmal-vchiq",
-+ WQ_MEM_RECLAIM);
-+ if (!instance->bulk_wq)
-+ goto err_free;
-+
-+ 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);
-+ destroy_workqueue(instance->bulk_wq);
-+err_free:
-+ vfree(instance->bulk_scratch);
-+ kfree(instance);
-+ return -ENODEV;
-+}
-+EXPORT_SYMBOL_GPL(vchiq_mmal_init);
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
-+++ /dev/null
-@@ -1,61 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- * Dave Stevenson @ Broadcom
-- * (now dave.stevenson@raspberrypi.org)
-- * Simon Mellor @ Broadcom
-- * Luke Diamand @ Broadcom
-- *
-- * MMAL structures
-- *
-- */
--#ifndef MMAL_COMMON_H
--#define MMAL_COMMON_H
--
--#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 BIT_ULL(63)
--
--struct mmal_msg_context;
--
--/* 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 */
-- bool remove_padding; /* Does the GPU have to remove padding,
-- * or can we do hide padding via bytesperline.
-- */
--};
--
--/* 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_msg_context *msg_context;
--};
--
--/* */
--struct mmal_colourfx {
-- s32 enable;
-- u32 u;
-- u32 v;
--};
--#endif
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-encodings.h
-+++ /dev/null
-@@ -1,124 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- * Dave Stevenson @ Broadcom
-- * (now dave.stevenson@raspberrypi.org)
-- * Simon Mellor @ Broadcom
-- * Luke Diamand @ Broadcom
-- */
--#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 */
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-common.h
-+++ /dev/null
-@@ -1,48 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- * Dave Stevenson @ Broadcom
-- * (now dave.stevenson@raspberrypi.org)
-- * Simon Mellor @ Broadcom
-- * Luke Diamand @ Broadcom
-- */
--
--#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 */
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h
-+++ /dev/null
-@@ -1,106 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- * Dave Stevenson @ Broadcom
-- * (now dave.stevenson@raspberrypi.org)
-- * Simon Mellor @ Broadcom
-- * Luke Diamand @ Broadcom
-- */
--
--#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
-- * 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_local {
-- 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; /* 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 */
--};
--
--/* Remote 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.
-- */
--
-- u32 es; /* 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 */
-- u32 extradata; /* Codec specific data */
--};
--
--#endif /* MMAL_MSG_FORMAT_H */
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h
-+++ /dev/null
-@@ -1,109 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- * Dave Stevenson @ Broadcom
-- * (now dave.stevenson@raspberrypi.org)
-- * Simon Mellor @ Broadcom
-- * Luke Diamand @ Broadcom
-- */
--
--/* 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
-- * structures within the message. When used to set values only the
-- * buffer_num, buffer_size and userdata parameters are writable.
-- */
--struct mmal_port {
-- u32 priv; /* Private member used by the framework */
-- u32 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) */
-- u32 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.
-- */
--
-- u32 component; /* Component this port belongs to (Read Only) */
--
-- u32 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.
-- */
--};
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
-+++ /dev/null
-@@ -1,406 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- * Dave Stevenson @ Broadcom
-- * (now dave.stevenson@raspberrypi.org)
-- * Simon Mellor @ Broadcom
-- * Luke Diamand @ Broadcom
-- */
--
--/*
-- * 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
-- */
--#ifndef MMAL_MSG_H
--#define MMAL_MSG_H
--
--#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, /* Unknown 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 */
-- u32 control_service;
--
-- u32 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 {
-- u32 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; /* elementary 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 BIT(0)
--/* Signals that the start of the current payload starts a frame */
--#define MMAL_BUFFER_HEADER_FLAG_FRAME_START BIT(1)
--/* Signals that the end of the current payload ends a frame */
--#define MMAL_BUFFER_HEADER_FLAG_FRAME_END BIT(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 BIT(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 BIT(4)
--/*
-- * Signals a buffer containing some kind of config data for the component
-- * (e.g. codec config data)
-- */
--#define MMAL_BUFFER_HEADER_FLAG_CONFIG BIT(5)
--/* Signals an encrypted payload */
--#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED BIT(6)
--/* Signals a buffer containing side information */
--#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO BIT(7)
--/*
-- * Signals a buffer which is the snapshot/postview image from a stills
-- * capture
-- */
--#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT BIT(8)
--/* Signals a buffer which contains data known to be corrupted */
--#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED BIT(9)
--/* Signals that a buffer failed to be transmitted */
--#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED BIT(10)
--
--struct mmal_driver_buffer {
-- u32 magic;
-- u32 component_handle;
-- u32 port_handle;
-- u32 client_context;
--};
--
--/* buffer header */
--struct mmal_buffer_header {
-- u32 next; /* next header */
-- u32 priv; /* framework private data */
-- u32 cmd;
-- u32 data;
-- u32 alloc_size;
-- u32 length;
-- u32 offset;
-- u32 flags;
-- s64 pts;
-- s64 dts;
-- u32 type;
-- u32 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 {
-- u32 client_component; /* component context */
--
-- u32 port_type;
-- u32 port_num;
--
-- u32 cmd;
-- u32 length;
-- u8 data[MMAL_WORKER_EVENT_SPACE];
-- u32 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;
--};
--#endif
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
-+++ /dev/null
-@@ -1,755 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- * Dave Stevenson @ Broadcom
-- * (now dave.stevenson@raspberrypi.org)
-- * Simon Mellor @ Broadcom
-- * Luke Diamand @ Broadcom
-- */
--
--/* common parameters */
--
--/** @name Parameter groups
-- * Parameters are divided into groups, and then allocated sequentially within
-- * a group using an enum.
-- * @{
-- */
--
--#ifndef MMAL_PARAMETERS_H
--#define MMAL_PARAMETERS_H
--
--/** 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 {
-- /**< Never a valid parameter ID */
-- MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON,
--
-- /**< MMAL_PARAMETER_ENCODING_T */
-- MMAL_PARAMETER_SUPPORTED_ENCODINGS,
-- /**< MMAL_PARAMETER_URI_T */
-- MMAL_PARAMETER_URI,
-- /** 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_T */
-- MMAL_PARAMETER_STATISTICS,
-- /**< MMAL_PARAMETER_CORE_STATISTICS_T */
-- MMAL_PARAMETER_CORE_STATISTICS,
-- /**< MMAL_PARAMETER_MEM_USAGE_T */
-- MMAL_PARAMETER_MEM_USAGE,
-- /**< MMAL_PARAMETER_UINT32_T */
-- MMAL_PARAMETER_BUFFER_FLAG_FILTER,
-- /**< MMAL_PARAMETER_SEEK_T */
-- MMAL_PARAMETER_SEEK,
-- /**< MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_POWERMON_ENABLE,
-- /**< MMAL_PARAMETER_LOGGING_T */
-- MMAL_PARAMETER_LOGGING,
-- /**< MMAL_PARAMETER_UINT64_T */
-- MMAL_PARAMETER_SYSTEM_TIME,
-- /**< MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_NO_IMAGE_PADDING,
--};
--
--/* camera parameters */
--
--enum mmal_parameter_camera_type {
-- /* 0 */
-- /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
-- MMAL_PARAMETER_THUMBNAIL_CONFIGURATION =
-- MMAL_PARAMETER_GROUP_CAMERA,
-- /**< Unused? */
-- MMAL_PARAMETER_CAPTURE_QUALITY,
-- /**< @ref MMAL_PARAMETER_INT32_T */
-- MMAL_PARAMETER_ROTATION,
-- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_EXIF_DISABLE,
-- /**< @ref MMAL_PARAMETER_EXIF_T */
-- MMAL_PARAMETER_EXIF,
-- /**< @ref MMAL_PARAM_AWBMODE_T */
-- MMAL_PARAMETER_AWB_MODE,
-- /**< @ref MMAL_PARAMETER_IMAGEFX_T */
-- MMAL_PARAMETER_IMAGE_EFFECT,
-- /**< @ref MMAL_PARAMETER_COLOURFX_T */
-- MMAL_PARAMETER_COLOUR_EFFECT,
-- /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
-- MMAL_PARAMETER_FLICKER_AVOID,
-- /**< @ref MMAL_PARAMETER_FLASH_T */
-- MMAL_PARAMETER_FLASH,
-- /**< @ref MMAL_PARAMETER_REDEYE_T */
-- MMAL_PARAMETER_REDEYE,
-- /**< @ref MMAL_PARAMETER_FOCUS_T */
-- MMAL_PARAMETER_FOCUS,
-- /**< Unused? */
-- MMAL_PARAMETER_FOCAL_LENGTHS,
-- /**< @ref MMAL_PARAMETER_INT32_T */
-- MMAL_PARAMETER_EXPOSURE_COMP,
-- /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
-- MMAL_PARAMETER_ZOOM,
-- /**< @ref MMAL_PARAMETER_MIRROR_T */
-- MMAL_PARAMETER_MIRROR,
--
-- /* 0x10 */
-- /**< @ref MMAL_PARAMETER_UINT32_T */
-- MMAL_PARAMETER_CAMERA_NUM,
-- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_CAPTURE,
-- /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
-- MMAL_PARAMETER_EXPOSURE_MODE,
-- /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
-- MMAL_PARAMETER_EXP_METERING_MODE,
-- /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
-- MMAL_PARAMETER_FOCUS_STATUS,
-- /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
-- MMAL_PARAMETER_CAMERA_CONFIG,
-- /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
-- MMAL_PARAMETER_CAPTURE_STATUS,
-- /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
-- MMAL_PARAMETER_FACE_TRACK,
-- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
-- /**< @ref MMAL_PARAMETER_UINT32_T */
-- MMAL_PARAMETER_JPEG_Q_FACTOR,
-- /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
-- MMAL_PARAMETER_FRAME_RATE,
-- /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
-- MMAL_PARAMETER_USE_STC,
-- /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
-- MMAL_PARAMETER_CAMERA_INFO,
-- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_VIDEO_STABILISATION,
-- /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
-- MMAL_PARAMETER_FACE_TRACK_RESULTS,
-- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_ENABLE_RAW_CAPTURE,
--
-- /* 0x20 */
-- /**< @ref MMAL_PARAMETER_URI_T */
-- MMAL_PARAMETER_DPF_FILE,
-- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_ENABLE_DPF_FILE,
-- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
-- /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
-- MMAL_PARAMETER_CAPTURE_MODE,
-- /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
-- MMAL_PARAMETER_FOCUS_REGIONS,
-- /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
-- MMAL_PARAMETER_INPUT_CROP,
-- /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
-- MMAL_PARAMETER_SENSOR_INFORMATION,
-- /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
-- MMAL_PARAMETER_FLASH_SELECT,
-- /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
-- MMAL_PARAMETER_FIELD_OF_VIEW,
-- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
-- /**< @ref MMAL_PARAMETER_DRC_T */
-- MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,
-- /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
-- MMAL_PARAMETER_ALGORITHM_CONTROL,
-- /**< @ref MMAL_PARAMETER_RATIONAL_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,
--
-- /* 0x30 */
-- /**< @ref MMAL_PARAMETER_UINT32_T */
-- MMAL_PARAMETER_ISO,
-- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_ANTISHAKE,
-- /** @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,
-- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_JPEG_ATTACH_LOG,
-- /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
-- MMAL_PARAMETER_ZERO_SHUTTER_LAG,
-- /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
-- MMAL_PARAMETER_FPS_RANGE,
-- /**< @ref MMAL_PARAMETER_INT32_T */
-- MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP,
--
-- /* 0x40 */
-- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_SW_SHARPEN_DISABLE,
-- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_FLASH_REQUIRED,
-- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_SW_SATURATION_DISABLE,
-- /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
-- MMAL_PARAMETER_SHUTTER_SPEED,
-- /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
-- MMAL_PARAMETER_CUSTOM_AWB_GAINS,
--};
--
--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,
--};
--
--/* rectangle, used lots so it gets its own struct */
--struct vchiq_mmal_rect {
-- s32 x;
-- s32 y;
-- s32 width;
-- s32 height;
--};
--
--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];
--};
--
--#endif
---- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
-+++ /dev/null
-@@ -1,166 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * Broadcom BM2835 V4L2 driver
-- *
-- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-- *
-- * Authors: Vincent Sanders @ Collabora
-- * Dave Stevenson @ Broadcom
-- * (now dave.stevenson@raspberrypi.org)
-- * Simon Mellor @ Broadcom
-- * Luke Diamand @ Broadcom
-- *
-- * 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 */
--};
--
--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_local format;
-- /* elementary 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 buffers the VPU has yet to return */
-- atomic_t buffers_with_vpu;
-- /* 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 appropriate 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);
--
--int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
-- struct mmal_buffer *buf);
--int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf);
--#endif /* MMAL_VCHIQ_H */
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-@@ -0,0 +1,61 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ * Dave Stevenson @ Broadcom
-+ * (now dave.stevenson@raspberrypi.org)
-+ * Simon Mellor @ Broadcom
-+ * Luke Diamand @ Broadcom
-+ *
-+ * MMAL structures
-+ *
-+ */
-+#ifndef MMAL_COMMON_H
-+#define MMAL_COMMON_H
-+
-+#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 BIT_ULL(63)
-+
-+struct mmal_msg_context;
-+
-+/* 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 */
-+ bool remove_padding; /* Does the GPU have to remove padding,
-+ * or can we do hide padding via bytesperline.
-+ */
-+};
-+
-+/* 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_msg_context *msg_context;
-+};
-+
-+/* */
-+struct mmal_colourfx {
-+ s32 enable;
-+ u32 u;
-+ u32 v;
-+};
-+#endif
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
-@@ -0,0 +1,124 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ * Dave Stevenson @ Broadcom
-+ * (now dave.stevenson@raspberrypi.org)
-+ * Simon Mellor @ Broadcom
-+ * Luke Diamand @ Broadcom
-+ */
-+#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 */
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h
-@@ -0,0 +1,48 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ * Dave Stevenson @ Broadcom
-+ * (now dave.stevenson@raspberrypi.org)
-+ * Simon Mellor @ Broadcom
-+ * Luke Diamand @ Broadcom
-+ */
-+
-+#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 */
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h
-@@ -0,0 +1,106 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ * Dave Stevenson @ Broadcom
-+ * (now dave.stevenson@raspberrypi.org)
-+ * Simon Mellor @ Broadcom
-+ * Luke Diamand @ Broadcom
-+ */
-+
-+#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
-+ * 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_local {
-+ 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; /* 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 */
-+};
-+
-+/* Remote 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.
-+ */
-+
-+ u32 es; /* 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 */
-+ u32 extradata; /* Codec specific data */
-+};
-+
-+#endif /* MMAL_MSG_FORMAT_H */
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h
-@@ -0,0 +1,109 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ * Dave Stevenson @ Broadcom
-+ * (now dave.stevenson@raspberrypi.org)
-+ * Simon Mellor @ Broadcom
-+ * Luke Diamand @ Broadcom
-+ */
-+
-+/* 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
-+ * structures within the message. When used to set values only the
-+ * buffer_num, buffer_size and userdata parameters are writable.
-+ */
-+struct mmal_port {
-+ u32 priv; /* Private member used by the framework */
-+ u32 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) */
-+ u32 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.
-+ */
-+
-+ u32 component; /* Component this port belongs to (Read Only) */
-+
-+ u32 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.
-+ */
-+};
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
-@@ -0,0 +1,406 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ * Dave Stevenson @ Broadcom
-+ * (now dave.stevenson@raspberrypi.org)
-+ * Simon Mellor @ Broadcom
-+ * Luke Diamand @ Broadcom
-+ */
-+
-+/*
-+ * 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
-+ */
-+#ifndef MMAL_MSG_H
-+#define MMAL_MSG_H
-+
-+#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, /* Unknown 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 */
-+ u32 control_service;
-+
-+ u32 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 {
-+ u32 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; /* elementary 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 BIT(0)
-+/* Signals that the start of the current payload starts a frame */
-+#define MMAL_BUFFER_HEADER_FLAG_FRAME_START BIT(1)
-+/* Signals that the end of the current payload ends a frame */
-+#define MMAL_BUFFER_HEADER_FLAG_FRAME_END BIT(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 BIT(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 BIT(4)
-+/*
-+ * Signals a buffer containing some kind of config data for the component
-+ * (e.g. codec config data)
-+ */
-+#define MMAL_BUFFER_HEADER_FLAG_CONFIG BIT(5)
-+/* Signals an encrypted payload */
-+#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED BIT(6)
-+/* Signals a buffer containing side information */
-+#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO BIT(7)
-+/*
-+ * Signals a buffer which is the snapshot/postview image from a stills
-+ * capture
-+ */
-+#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT BIT(8)
-+/* Signals a buffer which contains data known to be corrupted */
-+#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED BIT(9)
-+/* Signals that a buffer failed to be transmitted */
-+#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED BIT(10)
-+
-+struct mmal_driver_buffer {
-+ u32 magic;
-+ u32 component_handle;
-+ u32 port_handle;
-+ u32 client_context;
-+};
-+
-+/* buffer header */
-+struct mmal_buffer_header {
-+ u32 next; /* next header */
-+ u32 priv; /* framework private data */
-+ u32 cmd;
-+ u32 data;
-+ u32 alloc_size;
-+ u32 length;
-+ u32 offset;
-+ u32 flags;
-+ s64 pts;
-+ s64 dts;
-+ u32 type;
-+ u32 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 {
-+ u32 client_component; /* component context */
-+
-+ u32 port_type;
-+ u32 port_num;
-+
-+ u32 cmd;
-+ u32 length;
-+ u8 data[MMAL_WORKER_EVENT_SPACE];
-+ u32 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;
-+};
-+#endif
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
-@@ -0,0 +1,755 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ * Dave Stevenson @ Broadcom
-+ * (now dave.stevenson@raspberrypi.org)
-+ * Simon Mellor @ Broadcom
-+ * Luke Diamand @ Broadcom
-+ */
-+
-+/* common parameters */
-+
-+/** @name Parameter groups
-+ * Parameters are divided into groups, and then allocated sequentially within
-+ * a group using an enum.
-+ * @{
-+ */
-+
-+#ifndef MMAL_PARAMETERS_H
-+#define MMAL_PARAMETERS_H
-+
-+/** 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 {
-+ /**< Never a valid parameter ID */
-+ MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON,
-+
-+ /**< MMAL_PARAMETER_ENCODING_T */
-+ MMAL_PARAMETER_SUPPORTED_ENCODINGS,
-+ /**< MMAL_PARAMETER_URI_T */
-+ MMAL_PARAMETER_URI,
-+ /** 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_T */
-+ MMAL_PARAMETER_STATISTICS,
-+ /**< MMAL_PARAMETER_CORE_STATISTICS_T */
-+ MMAL_PARAMETER_CORE_STATISTICS,
-+ /**< MMAL_PARAMETER_MEM_USAGE_T */
-+ MMAL_PARAMETER_MEM_USAGE,
-+ /**< MMAL_PARAMETER_UINT32_T */
-+ MMAL_PARAMETER_BUFFER_FLAG_FILTER,
-+ /**< MMAL_PARAMETER_SEEK_T */
-+ MMAL_PARAMETER_SEEK,
-+ /**< MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_POWERMON_ENABLE,
-+ /**< MMAL_PARAMETER_LOGGING_T */
-+ MMAL_PARAMETER_LOGGING,
-+ /**< MMAL_PARAMETER_UINT64_T */
-+ MMAL_PARAMETER_SYSTEM_TIME,
-+ /**< MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_NO_IMAGE_PADDING,
-+};
-+
-+/* camera parameters */
-+
-+enum mmal_parameter_camera_type {
-+ /* 0 */
-+ /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
-+ MMAL_PARAMETER_THUMBNAIL_CONFIGURATION =
-+ MMAL_PARAMETER_GROUP_CAMERA,
-+ /**< Unused? */
-+ MMAL_PARAMETER_CAPTURE_QUALITY,
-+ /**< @ref MMAL_PARAMETER_INT32_T */
-+ MMAL_PARAMETER_ROTATION,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_EXIF_DISABLE,
-+ /**< @ref MMAL_PARAMETER_EXIF_T */
-+ MMAL_PARAMETER_EXIF,
-+ /**< @ref MMAL_PARAM_AWBMODE_T */
-+ MMAL_PARAMETER_AWB_MODE,
-+ /**< @ref MMAL_PARAMETER_IMAGEFX_T */
-+ MMAL_PARAMETER_IMAGE_EFFECT,
-+ /**< @ref MMAL_PARAMETER_COLOURFX_T */
-+ MMAL_PARAMETER_COLOUR_EFFECT,
-+ /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
-+ MMAL_PARAMETER_FLICKER_AVOID,
-+ /**< @ref MMAL_PARAMETER_FLASH_T */
-+ MMAL_PARAMETER_FLASH,
-+ /**< @ref MMAL_PARAMETER_REDEYE_T */
-+ MMAL_PARAMETER_REDEYE,
-+ /**< @ref MMAL_PARAMETER_FOCUS_T */
-+ MMAL_PARAMETER_FOCUS,
-+ /**< Unused? */
-+ MMAL_PARAMETER_FOCAL_LENGTHS,
-+ /**< @ref MMAL_PARAMETER_INT32_T */
-+ MMAL_PARAMETER_EXPOSURE_COMP,
-+ /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
-+ MMAL_PARAMETER_ZOOM,
-+ /**< @ref MMAL_PARAMETER_MIRROR_T */
-+ MMAL_PARAMETER_MIRROR,
-+
-+ /* 0x10 */
-+ /**< @ref MMAL_PARAMETER_UINT32_T */
-+ MMAL_PARAMETER_CAMERA_NUM,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_CAPTURE,
-+ /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
-+ MMAL_PARAMETER_EXPOSURE_MODE,
-+ /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
-+ MMAL_PARAMETER_EXP_METERING_MODE,
-+ /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
-+ MMAL_PARAMETER_FOCUS_STATUS,
-+ /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
-+ MMAL_PARAMETER_CAMERA_CONFIG,
-+ /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
-+ MMAL_PARAMETER_CAPTURE_STATUS,
-+ /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
-+ MMAL_PARAMETER_FACE_TRACK,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
-+ /**< @ref MMAL_PARAMETER_UINT32_T */
-+ MMAL_PARAMETER_JPEG_Q_FACTOR,
-+ /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
-+ MMAL_PARAMETER_FRAME_RATE,
-+ /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
-+ MMAL_PARAMETER_USE_STC,
-+ /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
-+ MMAL_PARAMETER_CAMERA_INFO,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_VIDEO_STABILISATION,
-+ /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
-+ MMAL_PARAMETER_FACE_TRACK_RESULTS,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_ENABLE_RAW_CAPTURE,
-+
-+ /* 0x20 */
-+ /**< @ref MMAL_PARAMETER_URI_T */
-+ MMAL_PARAMETER_DPF_FILE,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_ENABLE_DPF_FILE,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
-+ /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
-+ MMAL_PARAMETER_CAPTURE_MODE,
-+ /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
-+ MMAL_PARAMETER_FOCUS_REGIONS,
-+ /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
-+ MMAL_PARAMETER_INPUT_CROP,
-+ /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
-+ MMAL_PARAMETER_SENSOR_INFORMATION,
-+ /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
-+ MMAL_PARAMETER_FLASH_SELECT,
-+ /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
-+ MMAL_PARAMETER_FIELD_OF_VIEW,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
-+ /**< @ref MMAL_PARAMETER_DRC_T */
-+ MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,
-+ /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
-+ MMAL_PARAMETER_ALGORITHM_CONTROL,
-+ /**< @ref MMAL_PARAMETER_RATIONAL_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,
-+
-+ /* 0x30 */
-+ /**< @ref MMAL_PARAMETER_UINT32_T */
-+ MMAL_PARAMETER_ISO,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_ANTISHAKE,
-+ /** @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,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_JPEG_ATTACH_LOG,
-+ /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
-+ MMAL_PARAMETER_ZERO_SHUTTER_LAG,
-+ /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
-+ MMAL_PARAMETER_FPS_RANGE,
-+ /**< @ref MMAL_PARAMETER_INT32_T */
-+ MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP,
-+
-+ /* 0x40 */
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_SW_SHARPEN_DISABLE,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_FLASH_REQUIRED,
-+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_SW_SATURATION_DISABLE,
-+ /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
-+ MMAL_PARAMETER_SHUTTER_SPEED,
-+ /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
-+ MMAL_PARAMETER_CUSTOM_AWB_GAINS,
-+};
-+
-+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,
-+};
-+
-+/* rectangle, used lots so it gets its own struct */
-+struct vchiq_mmal_rect {
-+ s32 x;
-+ s32 y;
-+ s32 width;
-+ s32 height;
-+};
-+
-+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];
-+};
-+
-+#endif
---- /dev/null
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -0,0 +1,166 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Broadcom BM2835 V4L2 driver
-+ *
-+ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Authors: Vincent Sanders @ Collabora
-+ * Dave Stevenson @ Broadcom
-+ * (now dave.stevenson@raspberrypi.org)
-+ * Simon Mellor @ Broadcom
-+ * Luke Diamand @ Broadcom
-+ *
-+ * 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 */
-+};
-+
-+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_local format;
-+ /* elementary 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 buffers the VPU has yet to return */
-+ atomic_t buffers_with_vpu;
-+ /* 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 appropriate 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);
-+
-+int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
-+ struct mmal_buffer *buf);
-+int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf);
-+#endif /* MMAL_VCHIQ_H */
+++ /dev/null
-From 9daa20076f689c9d3f32446b5a73a0f0e20651ca Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Sep 2018 16:51:13 +0100
-Subject: [PATCH 268/703] staging: mmal-vchiq: Allocate and free components as
- required
-
-The existing code assumed that there would only ever be 4 components,
-and never freed the entries once used.
-Allow arbitrary creation and destruction of components.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/vchiq-mmal/mmal-vchiq.c | 29 ++++++++++++-------
- .../vc04_services/vchiq-mmal/mmal-vchiq.h | 1 +
- 2 files changed, 20 insertions(+), 10 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -38,8 +38,11 @@ MODULE_AUTHOR("Dave Stevenson, <dave.ste
- MODULE_LICENSE("GPL");
- MODULE_VERSION("0.0.1");
-
--/* maximum number of components supported */
--#define VCHIQ_MMAL_MAX_COMPONENTS 4
-+/*
-+ * maximum number of components supported.
-+ * This matches the maximum permitted by default on the VPU
-+ */
-+#define VCHIQ_MMAL_MAX_COMPONENTS 64
-
- /*#define FULL_MSG_DUMP 1*/
-
-@@ -174,8 +177,6 @@ struct vchiq_mmal_instance {
- /* protect accesses to context_map */
- struct mutex context_map_lock;
-
-- /* component to use next */
-- int component_idx;
- struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
-
- /* ordered workqueue to process all bulk operations */
-@@ -1632,18 +1633,24 @@ int vchiq_mmal_component_init(struct vch
- {
- int ret;
- int idx; /* port index */
-- struct vchiq_mmal_component *component;
-+ struct vchiq_mmal_component *component = NULL;
-
- if (mutex_lock_interruptible(&instance->vchiq_mutex))
- return -EINTR;
-
-- if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) {
-+ for (idx = 0; idx < VCHIQ_MMAL_MAX_COMPONENTS; idx++) {
-+ if (!instance->component[idx].in_use) {
-+ component = &instance->component[idx];
-+ component->in_use = 1;
-+ break;
-+ }
-+ }
-+
-+ if (!component) {
- ret = -EINVAL; /* todo is this correct error? */
- goto unlock;
- }
-
-- component = &instance->component[instance->component_idx];
--
- ret = create_component(instance, component, name);
- if (ret < 0) {
- pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
-@@ -1694,8 +1701,6 @@ int vchiq_mmal_component_init(struct vch
- goto release_component;
- }
-
-- instance->component_idx++;
--
- *component_out = component;
-
- mutex_unlock(&instance->vchiq_mutex);
-@@ -1705,6 +1710,8 @@ int vchiq_mmal_component_init(struct vch
- release_component:
- destroy_component(instance, component);
- unlock:
-+ if (component)
-+ component->in_use = 0;
- mutex_unlock(&instance->vchiq_mutex);
-
- return ret;
-@@ -1727,6 +1734,8 @@ int vchiq_mmal_component_finalise(struct
-
- ret = destroy_component(instance, component);
-
-+ component->in_use = 0;
-+
- mutex_unlock(&instance->vchiq_mutex);
-
- return ret;
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -82,6 +82,7 @@ struct vchiq_mmal_port {
- };
-
- struct vchiq_mmal_component {
-+ u32 in_use:1;
- bool enabled;
- u32 handle; /* VideoCore handle for component */
- u32 inputs; /* Number of input ports */
--- /dev/null
+From 2fba609cb0baec25ef32de6ca340951e55aea464 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 17:33:37 +0100
+Subject: [PATCH 268/725] staging: mmal-vchiq: Make a mmal_buf struct for
+ passing parameters
+
+The callback from vchi_mmal to the client was growing lots of extra
+parameters. Consolidate them into a single struct instead of
+growing the list further.
+The struct is associated with the client buffer, therefore there
+are various changes to setup various containers for the struct,
+and pass the appropriate members.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-camera/bcm2835-camera.c | 62 ++++++++++++-------
+ .../vc04_services/vchiq-mmal/mmal-common.h | 5 ++
+ .../vc04_services/vchiq-mmal/mmal-vchiq.c | 29 ++++++---
+ .../vc04_services/vchiq-mmal/mmal-vchiq.h | 3 +-
+ 4 files changed, 64 insertions(+), 35 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -72,6 +72,12 @@ static const struct v4l2_fract
+ tpf_max = {.numerator = 1, .denominator = FPS_MIN},
+ tpf_default = {.numerator = 1000, .denominator = 30000};
+
++/* Container for MMAL and VB2 buffers*/
++struct vb2_mmal_buffer {
++ struct vb2_v4l2_buffer vb;
++ struct mmal_buffer mmal;
++};
++
+ /* video formats */
+ static struct mmal_fmt formats[] = {
+ {
+@@ -267,14 +273,15 @@ static int buffer_init(struct vb2_buffer
+ {
+ 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);
++ struct vb2_mmal_buffer *buf =
++ container_of(vb2, struct vb2_mmal_buffer, vb);
+
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
+ __func__, dev, vb);
+- buf->buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
+- buf->buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
++ buf->mmal.buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
++ buf->mmal.buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
+
+- return mmal_vchi_buffer_init(dev->instance, buf);
++ return mmal_vchi_buffer_init(dev->instance, &buf->mmal);
+ }
+
+ static int buffer_prepare(struct vb2_buffer *vb)
+@@ -303,11 +310,13 @@ static void buffer_cleanup(struct vb2_bu
+ {
+ 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);
++ struct vb2_mmal_buffer *buf =
++ container_of(vb2, struct vb2_mmal_buffer, vb);
+
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
+ __func__, dev, vb);
+- mmal_vchi_buffer_cleanup(buf);
++
++ mmal_vchi_buffer_cleanup(&buf->mmal);
+ }
+
+ static inline bool is_capturing(struct bm2835_mmal_dev *dev)
+@@ -319,14 +328,16 @@ static inline bool is_capturing(struct b
+ 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 mmal_buffer *mmal_buf)
+ {
+ struct bm2835_mmal_dev *dev = port->cb_ctx;
++ struct vb2_mmal_buffer *buf =
++ container_of(mmal_buf, struct vb2_mmal_buffer, mmal);
+
+ 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);
++ __func__, status, buf, mmal_buf->length, mmal_buf->mmal_flags,
++ mmal_buf->pts);
+
+ if (status != 0) {
+ /* error in transfer */
+@@ -337,7 +348,7 @@ static void buffer_cb(struct vchiq_mmal_
+ return;
+ }
+
+- if (length == 0) {
++ if (mmal_buf->length == 0) {
+ /* stream ended */
+ if (dev->capture.frame_count) {
+ /* empty buffer whilst capturing - expected to be an
+@@ -353,7 +364,8 @@ static void buffer_cb(struct vchiq_mmal_
+ &dev->capture.frame_count,
+ sizeof(dev->capture.frame_count));
+ }
+- if (vchiq_mmal_submit_buffer(instance, port, buf))
++ if (vchiq_mmal_submit_buffer(instance, port,
++ &buf->mmal))
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+ "Failed to return EOS buffer");
+ } else {
+@@ -382,16 +394,16 @@ static void buffer_cb(struct vchiq_mmal_
+ 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) {
++ } else if (mmal_buf->pts != 0) {
+ ktime_t timestamp;
+- s64 runtime_us = pts -
++ s64 runtime_us = mmal_buf->pts -
+ dev->capture.vc_start_timestamp;
+ timestamp = ktime_add_us(dev->capture.kernel_start_ts,
+ runtime_us);
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+ "Convert start time %llu and %llu with offset %llu to %llu\n",
+ ktime_to_ns(dev->capture.kernel_start_ts),
+- dev->capture.vc_start_timestamp, pts,
++ dev->capture.vc_start_timestamp, mmal_buf->pts,
+ ktime_to_ns(timestamp));
+ if (timestamp < dev->capture.last_timestamp) {
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+@@ -416,15 +428,15 @@ static void buffer_cb(struct vchiq_mmal_
+ dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
+ buf->vb.sequence = dev->capture.sequence++;
+
+- vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
+- if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
++ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, mmal_buf->length);
++ if (mmal_buf->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);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+
+- if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
++ if (mmal_buf->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");
+@@ -507,14 +519,16 @@ static void buffer_queue(struct vb2_buff
+ {
+ 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);
++ struct vb2_mmal_buffer *buf =
++ container_of(vb2, struct vb2_mmal_buffer, vb);
+ int ret;
+
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+ "%s: dev:%p buf:%p, idx %u\n",
+ __func__, dev, buf, vb2->vb2_buf.index);
+
+- ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, buf);
++ ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port,
++ &buf->mmal);
+ if (ret < 0)
+ v4l2_err(&dev->v4l2_dev, "%s: error submitting buffer\n",
+ __func__);
+@@ -628,7 +642,7 @@ static void stop_streaming(struct vb2_qu
+ dev->capture.frame_count = 0;
+
+ /* ensure a format has actually been set */
+- if (!dev->capture.port) {
++ if (!port) {
+ v4l2_err(&dev->v4l2_dev,
+ "no capture port - stream not started?\n");
+ return;
+@@ -648,11 +662,11 @@ static void stop_streaming(struct vb2_qu
+
+ /* 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) {
++ if (!ret && dev->capture.camera_port != 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) {
++ ret = vchiq_mmal_port_disable(dev->instance, port);
++ } else if (dev->capture.camera_port != port) {
+ v4l2_err(&dev->v4l2_dev, "port_disable failed, error %d\n",
+ ret);
+ }
+@@ -1954,7 +1968,7 @@ static int bcm2835_mmal_probe(struct pla
+ 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->buf_struct_size = sizeof(struct vb2_mmal_buffer);
+ q->ops = &bm2835_mmal_video_qops;
+ q->mem_ops = &vb2_vmalloc_memops;
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
+@@ -50,6 +50,11 @@ struct mmal_buffer {
+ unsigned long buffer_size; /* size of allocated buffer */
+
+ struct mmal_msg_context *msg_context;
++
++ unsigned long length;
++ u32 mmal_flags;
++ s64 dts;
++ s64 pts;
+ };
+
+ /* */
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -259,17 +259,25 @@ static void buffer_work_cb(struct work_s
+ {
+ struct mmal_msg_context *msg_context =
+ container_of(work, struct mmal_msg_context, u.bulk.work);
++ struct mmal_buffer *buffer = msg_context->u.bulk.buffer;
++
++ if (!buffer) {
++ pr_err("%s: ctx: %p, No mmal buffer to pass details\n",
++ __func__, msg_context);
++ return;
++ }
++
++ buffer->length = msg_context->u.bulk.buffer_used;
++ buffer->mmal_flags = msg_context->u.bulk.mmal_flags;
++ buffer->dts = msg_context->u.bulk.dts;
++ buffer->pts = msg_context->u.bulk.pts;
+
+ atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
+
+ 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);
++ msg_context->u.bulk.buffer);
+ }
+
+ /* workqueue scheduled callback to handle receiving buffers
+@@ -1327,11 +1335,14 @@ static int port_disable(struct vchiq_mma
+ mmalbuf = list_entry(buf_head, struct mmal_buffer,
+ list);
+ list_del(buf_head);
+- if (port->buffer_cb)
++ if (port->buffer_cb) {
++ mmalbuf->length = 0;
++ mmalbuf->mmal_flags = 0;
++ mmalbuf->dts = MMAL_TIME_UNKNOWN;
++ mmalbuf->pts = MMAL_TIME_UNKNOWN;
+ port->buffer_cb(instance,
+- port, 0, mmalbuf, 0, 0,
+- MMAL_TIME_UNKNOWN,
+- MMAL_TIME_UNKNOWN);
++ port, 0, mmalbuf);
++ }
+ }
+
+ spin_unlock_irqrestore(&port->slock, flags);
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -44,8 +44,7 @@ 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);
++ int status, struct mmal_buffer *buffer);
+
+ struct vchiq_mmal_port {
+ u32 enabled:1;
--- /dev/null
+From 4b5f21b730dae52710a930a295c405044557e319 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 18:15:38 +0100
+Subject: [PATCH 269/725] staging: mmal-vchiq: Add support for event callbacks.
+
+(Preparation for the codec driver).
+The codec uses the event mechanism to report things such as
+resolution changes. It is signalled by the cmd field of the buffer
+being non-zero.
+
+Add support for passing this information out to the client.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/vchiq-mmal/mmal-common.h | 1 +
+ .../vc04_services/vchiq-mmal/mmal-msg.h | 35 ++++
+ .../vc04_services/vchiq-mmal/mmal-vchiq.c | 170 ++++++++++++++++--
+ .../vc04_services/vchiq-mmal/mmal-vchiq.h | 4 +
+ 4 files changed, 196 insertions(+), 14 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
+@@ -51,6 +51,7 @@ struct mmal_buffer {
+
+ struct mmal_msg_context *msg_context;
+
++ u32 cmd; /* MMAL command. 0=data. */
+ unsigned long length;
+ u32 mmal_flags;
+ s64 dts;
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
+@@ -346,6 +346,41 @@ struct mmal_msg_port_parameter_get_reply
+ /* event messages */
+ #define MMAL_WORKER_EVENT_SPACE 256
+
++/* Four CC's for events */
++#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
++
++#define MMAL_EVENT_ERROR MMAL_FOURCC('E', 'R', 'R', 'O')
++#define MMAL_EVENT_EOS MMAL_FOURCC('E', 'E', 'O', 'S')
++#define MMAL_EVENT_FORMAT_CHANGED MMAL_FOURCC('E', 'F', 'C', 'H')
++#define MMAL_EVENT_PARAMETER_CHANGED MMAL_FOURCC('E', 'P', 'C', 'H')
++
++/* Structs for each of the event message payloads */
++struct mmal_msg_event_eos {
++ u32 port_type; /**< Type of port that received the end of stream */
++ u32 port_index; /**< Index of port that received the end of stream */
++};
++
++/** Format changed event data. */
++struct mmal_msg_event_format_changed {
++ /* Minimum size of buffers the port requires */
++ u32 buffer_size_min;
++ /* Minimum number of buffers the port requires */
++ u32 buffer_num_min;
++ /* Size of buffers the port recommends for optimal performance.
++ * A value of zero means no special recommendation.
++ */
++ u32 buffer_size_recommended;
++ /* Number of buffers the port recommends for optimal
++ * performance. A value of zero means no special recommendation.
++ */
++ u32 buffer_num_recommended;
++
++ u32 es_ptr;
++ struct mmal_es_format format;
++ union mmal_es_specific_format es;
++ u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
++};
++
+ struct mmal_msg_event_to_host {
+ u32 client_component; /* component context */
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -151,6 +151,8 @@ struct mmal_msg_context {
+ /* Presentation and Decode timestamps */
+ s64 pts;
+ s64 dts;
++ /* MMAL buffer command flag */
++ u32 cmd;
+
+ int status; /* context status */
+
+@@ -238,18 +240,6 @@ release_msg_context(struct mmal_msg_cont
+ 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:%u 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
+@@ -271,13 +261,18 @@ static void buffer_work_cb(struct work_s
+ buffer->mmal_flags = msg_context->u.bulk.mmal_flags;
+ buffer->dts = msg_context->u.bulk.dts;
+ buffer->pts = msg_context->u.bulk.pts;
++ buffer->cmd = msg_context->u.bulk.cmd;
+
+- atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
++ if (!buffer->cmd)
++ atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
+
+ 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);
++
++ if (buffer->cmd)
++ mutex_unlock(&msg_context->u.bulk.port->event_context_mutex);
+ }
+
+ /* workqueue scheduled callback to handle receiving buffers
+@@ -356,6 +351,7 @@ static int bulk_receive(struct vchiq_mma
+ msg_context->u.bulk.buffer_used = rd_len;
+ 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;
++ msg_context->u.bulk.cmd = msg->u.buffer_from_host.buffer_header.cmd;
+
+ queue_work(msg_context->instance->bulk_wq,
+ &msg_context->u.bulk.buffer_to_host_work);
+@@ -457,6 +453,103 @@ buffer_from_host(struct vchiq_mmal_insta
+ return ret;
+ }
+
++/* 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)
++{
++ /* FIXME: Not going to work on 64 bit */
++ struct vchiq_mmal_component *component =
++ (struct vchiq_mmal_component *)msg->u.event_to_host.client_component;
++ struct vchiq_mmal_port *port = NULL;
++ struct mmal_msg_context *msg_context;
++ u32 port_num = msg->u.event_to_host.port_num;
++
++ if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
++ pr_err("%s: MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n",
++ __func__);
++ return;
++ }
++
++ switch (msg->u.event_to_host.port_type) {
++ case MMAL_PORT_TYPE_CONTROL:
++ if (port_num) {
++ pr_err("%s: port_num of %u >= number of ports 1",
++ __func__, port_num);
++ return;
++ }
++ port = &component->control;
++ break;
++ case MMAL_PORT_TYPE_INPUT:
++ if (port_num >= component->inputs) {
++ pr_err("%s: port_num of %u >= number of ports %u",
++ __func__, port_num,
++ port_num >= component->inputs);
++ return;
++ }
++ port = &component->input[port_num];
++ break;
++ case MMAL_PORT_TYPE_OUTPUT:
++ if (port_num >= component->outputs) {
++ pr_err("%s: port_num of %u >= number of ports %u",
++ __func__, port_num,
++ port_num >= component->outputs);
++ return;
++ }
++ port = &component->output[port_num];
++ break;
++ case MMAL_PORT_TYPE_CLOCK:
++ if (port_num >= component->clocks) {
++ pr_err("%s: port_num of %u >= number of ports %u",
++ __func__, port_num,
++ port_num >= component->clocks);
++ return;
++ }
++ port = &component->clock[port_num];
++ break;
++ default:
++ break;
++ }
++
++ if (!mutex_trylock(&port->event_context_mutex)) {
++ pr_err("dropping event 0x%x\n", msg->u.event_to_host.cmd);
++ return;
++ }
++ msg_context = port->event_context;
++
++ if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
++ /* message reception had an error */
++ //pr_warn
++ pr_err("%s: error %d in reply\n", __func__, msg->h.status);
++
++ msg_context->u.bulk.status = msg->h.status;
++ } else if (msg->u.event_to_host.length > MMAL_WORKER_EVENT_SPACE) {
++ /* data is not in message, queue a bulk receive */
++ pr_err("%s: payload not in message - bulk receive??! NOT SUPPORTED\n",
++ __func__);
++ msg_context->u.bulk.status = -1;
++ } else {
++ memcpy(msg_context->u.bulk.buffer->buffer,
++ msg->u.event_to_host.data,
++ msg->u.event_to_host.length);
++
++ msg_context->u.bulk.buffer_used =
++ msg->u.event_to_host.length;
++
++ msg_context->u.bulk.mmal_flags = 0;
++ msg_context->u.bulk.dts = MMAL_TIME_UNKNOWN;
++ msg_context->u.bulk.pts = MMAL_TIME_UNKNOWN;
++ msg_context->u.bulk.cmd = msg->u.event_to_host.cmd;
++
++ pr_debug("event component:%u 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);
++ }
++
++ schedule_work(&msg_context->u.bulk.work);
++}
++
+ /* 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)
+@@ -1340,6 +1433,7 @@ static int port_disable(struct vchiq_mma
+ mmalbuf->mmal_flags = 0;
+ mmalbuf->dts = MMAL_TIME_UNKNOWN;
+ mmalbuf->pts = MMAL_TIME_UNKNOWN;
++ mmalbuf->cmd = 0;
+ port->buffer_cb(instance,
+ port, 0, mmalbuf);
+ }
+@@ -1641,6 +1735,43 @@ int mmal_vchi_buffer_cleanup(struct mmal
+ }
+ EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
+
++static void init_event_context(struct vchiq_mmal_instance *instance,
++ struct vchiq_mmal_port *port)
++{
++ struct mmal_msg_context *ctx = get_msg_context(instance);
++
++ mutex_init(&port->event_context_mutex);
++
++ port->event_context = ctx;
++ ctx->u.bulk.instance = instance;
++ ctx->u.bulk.port = port;
++ ctx->u.bulk.buffer =
++ kzalloc(sizeof(*ctx->u.bulk.buffer), GFP_KERNEL);
++ if (!ctx->u.bulk.buffer)
++ goto release_msg_context;
++ ctx->u.bulk.buffer->buffer = kzalloc(MMAL_WORKER_EVENT_SPACE,
++ GFP_KERNEL);
++ if (!ctx->u.bulk.buffer->buffer)
++ goto release_buffer;
++
++ INIT_WORK(&ctx->u.bulk.work, buffer_work_cb);
++ return;
++
++release_buffer:
++ kfree(ctx->u.bulk.buffer);
++release_msg_context:
++ release_msg_context(ctx);
++}
++
++static void free_event_context(struct vchiq_mmal_port *port)
++{
++ struct mmal_msg_context *ctx = port->event_context;
++
++ kfree(ctx->u.bulk.buffer->buffer);
++ kfree(ctx->u.bulk.buffer);
++ release_msg_context(ctx);
++}
++
+ /* Initialise a mmal component and its ports
+ *
+ */
+@@ -1684,6 +1815,7 @@ int vchiq_mmal_component_init(struct vch
+ ret = port_info_get(instance, &component->control);
+ if (ret < 0)
+ goto release_component;
++ init_event_context(instance, &component->control);
+
+ for (idx = 0; idx < component->inputs; idx++) {
+ component->input[idx].type = MMAL_PORT_TYPE_INPUT;
+@@ -1694,6 +1826,7 @@ int vchiq_mmal_component_init(struct vch
+ ret = port_info_get(instance, &component->input[idx]);
+ if (ret < 0)
+ goto release_component;
++ init_event_context(instance, &component->input[idx]);
+ }
+
+ for (idx = 0; idx < component->outputs; idx++) {
+@@ -1705,6 +1838,7 @@ int vchiq_mmal_component_init(struct vch
+ ret = port_info_get(instance, &component->output[idx]);
+ if (ret < 0)
+ goto release_component;
++ init_event_context(instance, &component->output[idx]);
+ }
+
+ for (idx = 0; idx < component->clocks; idx++) {
+@@ -1716,6 +1850,7 @@ int vchiq_mmal_component_init(struct vch
+ ret = port_info_get(instance, &component->clock[idx]);
+ if (ret < 0)
+ goto release_component;
++ init_event_context(instance, &component->clock[idx]);
+ }
+
+ *component_out = component;
+@@ -1741,7 +1876,7 @@ EXPORT_SYMBOL_GPL(vchiq_mmal_component_i
+ int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
+ struct vchiq_mmal_component *component)
+ {
+- int ret;
++ int ret, idx;
+
+ if (mutex_lock_interruptible(&instance->vchiq_mutex))
+ return -EINTR;
+@@ -1753,6 +1888,13 @@ int vchiq_mmal_component_finalise(struct
+
+ component->in_use = 0;
+
++ for (idx = 0; idx < component->inputs; idx++)
++ free_event_context(&component->input[idx]);
++ for (idx = 0; idx < component->outputs; idx++)
++ free_event_context(&component->output[idx]);
++ for (idx = 0; idx < component->clocks; idx++)
++ free_event_context(&component->clock[idx]);
++
+ mutex_unlock(&instance->vchiq_mutex);
+
+ return ret;
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -78,6 +78,10 @@ struct vchiq_mmal_port {
+ vchiq_mmal_buffer_cb buffer_cb;
+ /* callback context */
+ void *cb_ctx;
++
++ /* ensure serialised use of the one event context structure */
++ struct mutex event_context_mutex;
++ struct mmal_msg_context *event_context;
+ };
+
+ struct vchiq_mmal_component {
+++ /dev/null
-From 504d899794febbec7f371a2ef3d1b18e991d18e5 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Oct 2018 16:20:46 +0000
-Subject: [PATCH 269/703] staging: mmal-vchiq: Avoid use of bool in structures
-
-Fixes up a checkpatch error "Avoid using bool structure members
-because of possible alignment issues".
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 14 +++++++-------
- .../staging/vc04_services/vchiq-mmal/mmal-vchiq.h | 4 ++--
- 2 files changed, 9 insertions(+), 9 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -861,9 +861,9 @@ static int port_info_get(struct vchiq_mm
- goto release_msg;
-
- if (rmsg->u.port_info_get_reply.port.is_enabled == 0)
-- port->enabled = false;
-+ port->enabled = 0;
- else
-- port->enabled = true;
-+ port->enabled = 1;
-
- /* copy the values out of the message */
- port->handle = rmsg->u.port_info_get_reply.port_handle;
-@@ -1300,7 +1300,7 @@ static int port_disable(struct vchiq_mma
- if (!port->enabled)
- return 0;
-
-- port->enabled = false;
-+ port->enabled = 0;
-
- ret = port_action_port(instance, port,
- MMAL_MSG_PORT_ACTION_TYPE_DISABLE);
-@@ -1352,7 +1352,7 @@ static int port_enable(struct vchiq_mmal
- if (ret)
- goto done;
-
-- port->enabled = true;
-+ port->enabled = 1;
-
- if (port->buffer_cb) {
- /* send buffer headers to videocore */
-@@ -1524,7 +1524,7 @@ int vchiq_mmal_port_connect_tunnel(struc
- pr_err("failed disconnecting src port\n");
- goto release_unlock;
- }
-- src->connected->enabled = false;
-+ src->connected->enabled = 0;
- src->connected = NULL;
- }
-
-@@ -1760,7 +1760,7 @@ int vchiq_mmal_component_enable(struct v
-
- ret = enable_component(instance, component);
- if (ret == 0)
-- component->enabled = true;
-+ component->enabled = 1;
-
- mutex_unlock(&instance->vchiq_mutex);
-
-@@ -1786,7 +1786,7 @@ int vchiq_mmal_component_disable(struct
-
- ret = disable_component(instance, component);
- if (ret == 0)
-- component->enabled = false;
-+ component->enabled = 0;
-
- mutex_unlock(&instance->vchiq_mutex);
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -48,7 +48,7 @@ typedef void (*vchiq_mmal_buffer_cb)(
- unsigned long length, u32 mmal_flags, s64 dts, s64 pts);
-
- struct vchiq_mmal_port {
-- bool enabled;
-+ u32 enabled:1;
- u32 handle;
- u32 type; /* port type, cached to use on port info set */
- u32 index; /* port index, cached to use on port info set */
-@@ -83,7 +83,7 @@ struct vchiq_mmal_port {
-
- struct vchiq_mmal_component {
- u32 in_use:1;
-- bool enabled;
-+ u32 enabled:1;
- u32 handle; /* VideoCore handle for component */
- u32 inputs; /* Number of input ports */
- u32 outputs; /* Number of output ports */
+++ /dev/null
-From 11937ca9b223ffa394f04940b245b3689172537f Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Sep 2018 16:57:09 +0100
-Subject: [PATCH 270/703] staging: mmal-vchiq: Make timeout a defined parameter
-
-The timeout period for VPU communications is a useful thing
-to extend when debugging.
-Set it via a define, rather than a magic number buried in the code.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -44,6 +44,12 @@ MODULE_VERSION("0.0.1");
- */
- #define VCHIQ_MMAL_MAX_COMPONENTS 64
-
-+/*
-+ * Timeout for synchronous msg responses in seconds.
-+ * Helpful to increase this if stopping in the VPU debugger.
-+ */
-+#define SYNC_MSG_TIMEOUT 3
-+
- /*#define FULL_MSG_DUMP 1*/
-
- #ifdef DEBUG
-@@ -692,7 +698,7 @@ static int send_synchronous_mmal_msg(str
- }
-
- timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt,
-- 3 * HZ);
-+ SYNC_MSG_TIMEOUT * HZ);
- if (timeout == 0) {
- pr_err("timed out waiting for sync completion\n");
- ret = -ETIME;
--- /dev/null
+From c117bd7886d4d4079f33fb27b07ddd9add7310ee Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 18:26:02 +0100
+Subject: [PATCH 270/725] staging: vc04_services: Support sending data to MMAL
+ ports
+
+Add the ability to send data to ports. This only supports
+zero copy mode as the required bulk transfer setup calls
+are not done.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/vchiq-mmal/mmal-vchiq.c | 18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -428,11 +428,19 @@ buffer_from_host(struct vchiq_mmal_insta
+ m.u.buffer_from_host.buffer_header.data =
+ (u32)(unsigned long)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;
++ if (port->type == MMAL_PORT_TYPE_OUTPUT) {
++ m.u.buffer_from_host.buffer_header.length = 0;
++ m.u.buffer_from_host.buffer_header.offset = 0;
++ m.u.buffer_from_host.buffer_header.flags = 0;
++ m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN;
++ m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN;
++ } else {
++ m.u.buffer_from_host.buffer_header.length = buf->length;
++ m.u.buffer_from_host.buffer_header.offset = 0;
++ m.u.buffer_from_host.buffer_header.flags = buf->mmal_flags;
++ m.u.buffer_from_host.buffer_header.pts = buf->pts;
++ m.u.buffer_from_host.buffer_header.dts = buf->dts;
++ }
+
+ /* clear buffer type sepecific data */
+ memset(&m.u.buffer_from_host.buffer_header_type_specific, 0,
+++ /dev/null
-From 32d3fb2930b7e6f47959f0765c13f7cfda2baa7e Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Sep 2018 17:33:37 +0100
-Subject: [PATCH 271/703] staging: mmal-vchiq: Make a mmal_buf struct for
- passing parameters
-
-The callback from vchi_mmal to the client was growing lots of extra
-parameters. Consolidate them into a single struct instead of
-growing the list further.
-The struct is associated with the client buffer, therefore there
-are various changes to setup various containers for the struct,
-and pass the appropriate members.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-camera/bcm2835-camera.c | 62 ++++++++++++-------
- .../vc04_services/vchiq-mmal/mmal-common.h | 5 ++
- .../vc04_services/vchiq-mmal/mmal-vchiq.c | 29 ++++++---
- .../vc04_services/vchiq-mmal/mmal-vchiq.h | 3 +-
- 4 files changed, 64 insertions(+), 35 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -72,6 +72,12 @@ static const struct v4l2_fract
- tpf_max = {.numerator = 1, .denominator = FPS_MIN},
- tpf_default = {.numerator = 1000, .denominator = 30000};
-
-+/* Container for MMAL and VB2 buffers*/
-+struct vb2_mmal_buffer {
-+ struct vb2_v4l2_buffer vb;
-+ struct mmal_buffer mmal;
-+};
-+
- /* video formats */
- static struct mmal_fmt formats[] = {
- {
-@@ -267,14 +273,15 @@ static int buffer_init(struct vb2_buffer
- {
- 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);
-+ struct vb2_mmal_buffer *buf =
-+ container_of(vb2, struct vb2_mmal_buffer, vb);
-
- v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
- __func__, dev, vb);
-- buf->buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
-- buf->buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
-+ buf->mmal.buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
-+ buf->mmal.buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
-
-- return mmal_vchi_buffer_init(dev->instance, buf);
-+ return mmal_vchi_buffer_init(dev->instance, &buf->mmal);
- }
-
- static int buffer_prepare(struct vb2_buffer *vb)
-@@ -303,11 +310,13 @@ static void buffer_cleanup(struct vb2_bu
- {
- 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);
-+ struct vb2_mmal_buffer *buf =
-+ container_of(vb2, struct vb2_mmal_buffer, vb);
-
- v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
- __func__, dev, vb);
-- mmal_vchi_buffer_cleanup(buf);
-+
-+ mmal_vchi_buffer_cleanup(&buf->mmal);
- }
-
- static inline bool is_capturing(struct bm2835_mmal_dev *dev)
-@@ -319,14 +328,16 @@ static inline bool is_capturing(struct b
- 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 mmal_buffer *mmal_buf)
- {
- struct bm2835_mmal_dev *dev = port->cb_ctx;
-+ struct vb2_mmal_buffer *buf =
-+ container_of(mmal_buf, struct vb2_mmal_buffer, mmal);
-
- 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);
-+ __func__, status, buf, mmal_buf->length, mmal_buf->mmal_flags,
-+ mmal_buf->pts);
-
- if (status != 0) {
- /* error in transfer */
-@@ -337,7 +348,7 @@ static void buffer_cb(struct vchiq_mmal_
- return;
- }
-
-- if (length == 0) {
-+ if (mmal_buf->length == 0) {
- /* stream ended */
- if (dev->capture.frame_count) {
- /* empty buffer whilst capturing - expected to be an
-@@ -353,7 +364,8 @@ static void buffer_cb(struct vchiq_mmal_
- &dev->capture.frame_count,
- sizeof(dev->capture.frame_count));
- }
-- if (vchiq_mmal_submit_buffer(instance, port, buf))
-+ if (vchiq_mmal_submit_buffer(instance, port,
-+ &buf->mmal))
- v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
- "Failed to return EOS buffer");
- } else {
-@@ -382,16 +394,16 @@ static void buffer_cb(struct vchiq_mmal_
- 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) {
-+ } else if (mmal_buf->pts != 0) {
- ktime_t timestamp;
-- s64 runtime_us = pts -
-+ s64 runtime_us = mmal_buf->pts -
- dev->capture.vc_start_timestamp;
- timestamp = ktime_add_us(dev->capture.kernel_start_ts,
- runtime_us);
- v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
- "Convert start time %llu and %llu with offset %llu to %llu\n",
- ktime_to_ns(dev->capture.kernel_start_ts),
-- dev->capture.vc_start_timestamp, pts,
-+ dev->capture.vc_start_timestamp, mmal_buf->pts,
- ktime_to_ns(timestamp));
- if (timestamp < dev->capture.last_timestamp) {
- v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-@@ -416,15 +428,15 @@ static void buffer_cb(struct vchiq_mmal_
- dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
- buf->vb.sequence = dev->capture.sequence++;
-
-- vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
-- if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
-+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, mmal_buf->length);
-+ if (mmal_buf->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);
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
-
-- if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
-+ if (mmal_buf->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");
-@@ -507,14 +519,16 @@ static void buffer_queue(struct vb2_buff
- {
- 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);
-+ struct vb2_mmal_buffer *buf =
-+ container_of(vb2, struct vb2_mmal_buffer, vb);
- int ret;
-
- v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
- "%s: dev:%p buf:%p, idx %u\n",
- __func__, dev, buf, vb2->vb2_buf.index);
-
-- ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, buf);
-+ ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port,
-+ &buf->mmal);
- if (ret < 0)
- v4l2_err(&dev->v4l2_dev, "%s: error submitting buffer\n",
- __func__);
-@@ -628,7 +642,7 @@ static void stop_streaming(struct vb2_qu
- dev->capture.frame_count = 0;
-
- /* ensure a format has actually been set */
-- if (!dev->capture.port) {
-+ if (!port) {
- v4l2_err(&dev->v4l2_dev,
- "no capture port - stream not started?\n");
- return;
-@@ -648,11 +662,11 @@ static void stop_streaming(struct vb2_qu
-
- /* 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) {
-+ if (!ret && dev->capture.camera_port != 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) {
-+ ret = vchiq_mmal_port_disable(dev->instance, port);
-+ } else if (dev->capture.camera_port != port) {
- v4l2_err(&dev->v4l2_dev, "port_disable failed, error %d\n",
- ret);
- }
-@@ -1954,7 +1968,7 @@ static int bcm2835_mmal_probe(struct pla
- 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->buf_struct_size = sizeof(struct vb2_mmal_buffer);
- q->ops = &bm2835_mmal_video_qops;
- q->mem_ops = &vb2_vmalloc_memops;
- q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-@@ -50,6 +50,11 @@ struct mmal_buffer {
- unsigned long buffer_size; /* size of allocated buffer */
-
- struct mmal_msg_context *msg_context;
-+
-+ unsigned long length;
-+ u32 mmal_flags;
-+ s64 dts;
-+ s64 pts;
- };
-
- /* */
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -259,17 +259,25 @@ static void buffer_work_cb(struct work_s
- {
- struct mmal_msg_context *msg_context =
- container_of(work, struct mmal_msg_context, u.bulk.work);
-+ struct mmal_buffer *buffer = msg_context->u.bulk.buffer;
-+
-+ if (!buffer) {
-+ pr_err("%s: ctx: %p, No mmal buffer to pass details\n",
-+ __func__, msg_context);
-+ return;
-+ }
-+
-+ buffer->length = msg_context->u.bulk.buffer_used;
-+ buffer->mmal_flags = msg_context->u.bulk.mmal_flags;
-+ buffer->dts = msg_context->u.bulk.dts;
-+ buffer->pts = msg_context->u.bulk.pts;
-
- atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
-
- 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);
-+ msg_context->u.bulk.buffer);
- }
-
- /* workqueue scheduled callback to handle receiving buffers
-@@ -1327,11 +1335,14 @@ static int port_disable(struct vchiq_mma
- mmalbuf = list_entry(buf_head, struct mmal_buffer,
- list);
- list_del(buf_head);
-- if (port->buffer_cb)
-+ if (port->buffer_cb) {
-+ mmalbuf->length = 0;
-+ mmalbuf->mmal_flags = 0;
-+ mmalbuf->dts = MMAL_TIME_UNKNOWN;
-+ mmalbuf->pts = MMAL_TIME_UNKNOWN;
- port->buffer_cb(instance,
-- port, 0, mmalbuf, 0, 0,
-- MMAL_TIME_UNKNOWN,
-- MMAL_TIME_UNKNOWN);
-+ port, 0, mmalbuf);
-+ }
- }
-
- spin_unlock_irqrestore(&port->slock, flags);
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -44,8 +44,7 @@ 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);
-+ int status, struct mmal_buffer *buffer);
-
- struct vchiq_mmal_port {
- u32 enabled:1;
--- /dev/null
+From e28f85053dc8de18935993bee4c9e5d9483787bd Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 25 Sep 2018 16:57:40 +0100
+Subject: [PATCH 271/725] staging: vc04_services: Fixup vchiq-mmal include
+ ordering
+
+There were dependencies on including the headers in the correct
+order. Fix up the headers so that they include the other
+headers that they depend on themselves.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h | 1 +
+ drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
+@@ -38,6 +38,7 @@
+ #include "mmal-msg-common.h"
+ #include "mmal-msg-format.h"
+ #include "mmal-msg-port.h"
++#include "mmal-vchiq.h"
+
+ enum mmal_msg_type {
+ MMAL_MSG_TYPE_QUIT = 1,
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -16,6 +16,7 @@
+ #ifndef MMAL_VCHIQ_H
+ #define MMAL_VCHIQ_H
+
++#include "mmal-common.h"
+ #include "mmal-msg-format.h"
+
+ #define MAX_PORT_COUNT 4
+++ /dev/null
-From 903a6c2047aef7eba69ca04e6e3488ba3de0d9f9 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Sep 2018 18:15:38 +0100
-Subject: [PATCH 272/703] staging: mmal-vchiq: Add support for event callbacks.
-
-(Preparation for the codec driver).
-The codec uses the event mechanism to report things such as
-resolution changes. It is signalled by the cmd field of the buffer
-being non-zero.
-
-Add support for passing this information out to the client.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/vchiq-mmal/mmal-common.h | 1 +
- .../vc04_services/vchiq-mmal/mmal-msg.h | 35 ++++
- .../vc04_services/vchiq-mmal/mmal-vchiq.c | 170 ++++++++++++++++--
- .../vc04_services/vchiq-mmal/mmal-vchiq.h | 4 +
- 4 files changed, 196 insertions(+), 14 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-@@ -51,6 +51,7 @@ struct mmal_buffer {
-
- struct mmal_msg_context *msg_context;
-
-+ u32 cmd; /* MMAL command. 0=data. */
- unsigned long length;
- u32 mmal_flags;
- s64 dts;
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
-@@ -346,6 +346,41 @@ struct mmal_msg_port_parameter_get_reply
- /* event messages */
- #define MMAL_WORKER_EVENT_SPACE 256
-
-+/* Four CC's for events */
-+#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
-+
-+#define MMAL_EVENT_ERROR MMAL_FOURCC('E', 'R', 'R', 'O')
-+#define MMAL_EVENT_EOS MMAL_FOURCC('E', 'E', 'O', 'S')
-+#define MMAL_EVENT_FORMAT_CHANGED MMAL_FOURCC('E', 'F', 'C', 'H')
-+#define MMAL_EVENT_PARAMETER_CHANGED MMAL_FOURCC('E', 'P', 'C', 'H')
-+
-+/* Structs for each of the event message payloads */
-+struct mmal_msg_event_eos {
-+ u32 port_type; /**< Type of port that received the end of stream */
-+ u32 port_index; /**< Index of port that received the end of stream */
-+};
-+
-+/** Format changed event data. */
-+struct mmal_msg_event_format_changed {
-+ /* Minimum size of buffers the port requires */
-+ u32 buffer_size_min;
-+ /* Minimum number of buffers the port requires */
-+ u32 buffer_num_min;
-+ /* Size of buffers the port recommends for optimal performance.
-+ * A value of zero means no special recommendation.
-+ */
-+ u32 buffer_size_recommended;
-+ /* Number of buffers the port recommends for optimal
-+ * performance. A value of zero means no special recommendation.
-+ */
-+ u32 buffer_num_recommended;
-+
-+ u32 es_ptr;
-+ struct mmal_es_format format;
-+ union mmal_es_specific_format es;
-+ u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
-+};
-+
- struct mmal_msg_event_to_host {
- u32 client_component; /* component context */
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -151,6 +151,8 @@ struct mmal_msg_context {
- /* Presentation and Decode timestamps */
- s64 pts;
- s64 dts;
-+ /* MMAL buffer command flag */
-+ u32 cmd;
-
- int status; /* context status */
-
-@@ -238,18 +240,6 @@ release_msg_context(struct mmal_msg_cont
- 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:%u 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
-@@ -271,13 +261,18 @@ static void buffer_work_cb(struct work_s
- buffer->mmal_flags = msg_context->u.bulk.mmal_flags;
- buffer->dts = msg_context->u.bulk.dts;
- buffer->pts = msg_context->u.bulk.pts;
-+ buffer->cmd = msg_context->u.bulk.cmd;
-
-- atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
-+ if (!buffer->cmd)
-+ atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
-
- 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);
-+
-+ if (buffer->cmd)
-+ mutex_unlock(&msg_context->u.bulk.port->event_context_mutex);
- }
-
- /* workqueue scheduled callback to handle receiving buffers
-@@ -356,6 +351,7 @@ static int bulk_receive(struct vchiq_mma
- msg_context->u.bulk.buffer_used = rd_len;
- 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;
-+ msg_context->u.bulk.cmd = msg->u.buffer_from_host.buffer_header.cmd;
-
- queue_work(msg_context->instance->bulk_wq,
- &msg_context->u.bulk.buffer_to_host_work);
-@@ -457,6 +453,103 @@ buffer_from_host(struct vchiq_mmal_insta
- return ret;
- }
-
-+/* 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)
-+{
-+ /* FIXME: Not going to work on 64 bit */
-+ struct vchiq_mmal_component *component =
-+ (struct vchiq_mmal_component *)msg->u.event_to_host.client_component;
-+ struct vchiq_mmal_port *port = NULL;
-+ struct mmal_msg_context *msg_context;
-+ u32 port_num = msg->u.event_to_host.port_num;
-+
-+ if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
-+ pr_err("%s: MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n",
-+ __func__);
-+ return;
-+ }
-+
-+ switch (msg->u.event_to_host.port_type) {
-+ case MMAL_PORT_TYPE_CONTROL:
-+ if (port_num) {
-+ pr_err("%s: port_num of %u >= number of ports 1",
-+ __func__, port_num);
-+ return;
-+ }
-+ port = &component->control;
-+ break;
-+ case MMAL_PORT_TYPE_INPUT:
-+ if (port_num >= component->inputs) {
-+ pr_err("%s: port_num of %u >= number of ports %u",
-+ __func__, port_num,
-+ port_num >= component->inputs);
-+ return;
-+ }
-+ port = &component->input[port_num];
-+ break;
-+ case MMAL_PORT_TYPE_OUTPUT:
-+ if (port_num >= component->outputs) {
-+ pr_err("%s: port_num of %u >= number of ports %u",
-+ __func__, port_num,
-+ port_num >= component->outputs);
-+ return;
-+ }
-+ port = &component->output[port_num];
-+ break;
-+ case MMAL_PORT_TYPE_CLOCK:
-+ if (port_num >= component->clocks) {
-+ pr_err("%s: port_num of %u >= number of ports %u",
-+ __func__, port_num,
-+ port_num >= component->clocks);
-+ return;
-+ }
-+ port = &component->clock[port_num];
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ if (!mutex_trylock(&port->event_context_mutex)) {
-+ pr_err("dropping event 0x%x\n", msg->u.event_to_host.cmd);
-+ return;
-+ }
-+ msg_context = port->event_context;
-+
-+ if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
-+ /* message reception had an error */
-+ //pr_warn
-+ pr_err("%s: error %d in reply\n", __func__, msg->h.status);
-+
-+ msg_context->u.bulk.status = msg->h.status;
-+ } else if (msg->u.event_to_host.length > MMAL_WORKER_EVENT_SPACE) {
-+ /* data is not in message, queue a bulk receive */
-+ pr_err("%s: payload not in message - bulk receive??! NOT SUPPORTED\n",
-+ __func__);
-+ msg_context->u.bulk.status = -1;
-+ } else {
-+ memcpy(msg_context->u.bulk.buffer->buffer,
-+ msg->u.event_to_host.data,
-+ msg->u.event_to_host.length);
-+
-+ msg_context->u.bulk.buffer_used =
-+ msg->u.event_to_host.length;
-+
-+ msg_context->u.bulk.mmal_flags = 0;
-+ msg_context->u.bulk.dts = MMAL_TIME_UNKNOWN;
-+ msg_context->u.bulk.pts = MMAL_TIME_UNKNOWN;
-+ msg_context->u.bulk.cmd = msg->u.event_to_host.cmd;
-+
-+ pr_debug("event component:%u 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);
-+ }
-+
-+ schedule_work(&msg_context->u.bulk.work);
-+}
-+
- /* 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)
-@@ -1340,6 +1433,7 @@ static int port_disable(struct vchiq_mma
- mmalbuf->mmal_flags = 0;
- mmalbuf->dts = MMAL_TIME_UNKNOWN;
- mmalbuf->pts = MMAL_TIME_UNKNOWN;
-+ mmalbuf->cmd = 0;
- port->buffer_cb(instance,
- port, 0, mmalbuf);
- }
-@@ -1641,6 +1735,43 @@ int mmal_vchi_buffer_cleanup(struct mmal
- }
- EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
-
-+static void init_event_context(struct vchiq_mmal_instance *instance,
-+ struct vchiq_mmal_port *port)
-+{
-+ struct mmal_msg_context *ctx = get_msg_context(instance);
-+
-+ mutex_init(&port->event_context_mutex);
-+
-+ port->event_context = ctx;
-+ ctx->u.bulk.instance = instance;
-+ ctx->u.bulk.port = port;
-+ ctx->u.bulk.buffer =
-+ kzalloc(sizeof(*ctx->u.bulk.buffer), GFP_KERNEL);
-+ if (!ctx->u.bulk.buffer)
-+ goto release_msg_context;
-+ ctx->u.bulk.buffer->buffer = kzalloc(MMAL_WORKER_EVENT_SPACE,
-+ GFP_KERNEL);
-+ if (!ctx->u.bulk.buffer->buffer)
-+ goto release_buffer;
-+
-+ INIT_WORK(&ctx->u.bulk.work, buffer_work_cb);
-+ return;
-+
-+release_buffer:
-+ kfree(ctx->u.bulk.buffer);
-+release_msg_context:
-+ release_msg_context(ctx);
-+}
-+
-+static void free_event_context(struct vchiq_mmal_port *port)
-+{
-+ struct mmal_msg_context *ctx = port->event_context;
-+
-+ kfree(ctx->u.bulk.buffer->buffer);
-+ kfree(ctx->u.bulk.buffer);
-+ release_msg_context(ctx);
-+}
-+
- /* Initialise a mmal component and its ports
- *
- */
-@@ -1684,6 +1815,7 @@ int vchiq_mmal_component_init(struct vch
- ret = port_info_get(instance, &component->control);
- if (ret < 0)
- goto release_component;
-+ init_event_context(instance, &component->control);
-
- for (idx = 0; idx < component->inputs; idx++) {
- component->input[idx].type = MMAL_PORT_TYPE_INPUT;
-@@ -1694,6 +1826,7 @@ int vchiq_mmal_component_init(struct vch
- ret = port_info_get(instance, &component->input[idx]);
- if (ret < 0)
- goto release_component;
-+ init_event_context(instance, &component->input[idx]);
- }
-
- for (idx = 0; idx < component->outputs; idx++) {
-@@ -1705,6 +1838,7 @@ int vchiq_mmal_component_init(struct vch
- ret = port_info_get(instance, &component->output[idx]);
- if (ret < 0)
- goto release_component;
-+ init_event_context(instance, &component->output[idx]);
- }
-
- for (idx = 0; idx < component->clocks; idx++) {
-@@ -1716,6 +1850,7 @@ int vchiq_mmal_component_init(struct vch
- ret = port_info_get(instance, &component->clock[idx]);
- if (ret < 0)
- goto release_component;
-+ init_event_context(instance, &component->clock[idx]);
- }
-
- *component_out = component;
-@@ -1741,7 +1876,7 @@ EXPORT_SYMBOL_GPL(vchiq_mmal_component_i
- int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
- struct vchiq_mmal_component *component)
- {
-- int ret;
-+ int ret, idx;
-
- if (mutex_lock_interruptible(&instance->vchiq_mutex))
- return -EINTR;
-@@ -1753,6 +1888,13 @@ int vchiq_mmal_component_finalise(struct
-
- component->in_use = 0;
-
-+ for (idx = 0; idx < component->inputs; idx++)
-+ free_event_context(&component->input[idx]);
-+ for (idx = 0; idx < component->outputs; idx++)
-+ free_event_context(&component->output[idx]);
-+ for (idx = 0; idx < component->clocks; idx++)
-+ free_event_context(&component->clock[idx]);
-+
- mutex_unlock(&instance->vchiq_mutex);
-
- return ret;
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -78,6 +78,10 @@ struct vchiq_mmal_port {
- vchiq_mmal_buffer_cb buffer_cb;
- /* callback context */
- void *cb_ctx;
-+
-+ /* ensure serialised use of the one event context structure */
-+ struct mutex event_context_mutex;
-+ struct mmal_msg_context *event_context;
- };
-
- struct vchiq_mmal_component {
--- /dev/null
+From 3b89c864ffec186fc4b3d31ddb575533e97225eb Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 25 Sep 2018 10:27:11 +0100
+Subject: [PATCH 272/725] staging: vc04_services: Add new vc-sm-cma driver
+
+This new driver allows contiguous memory blocks to be imported
+into the VideoCore VPU memory map, and manages the lifetime of
+those objects, only releasing the source dmabuf once the VPU has
+confirmed it has finished with it.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/Kconfig | 1 +
+ drivers/staging/vc04_services/Makefile | 1 +
+ .../staging/vc04_services/vc-sm-cma/Kconfig | 10 +
+ .../staging/vc04_services/vc-sm-cma/Makefile | 8 +
+ drivers/staging/vc04_services/vc-sm-cma/TODO | 2 +
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c | 838 ++++++++++++++++++
+ .../staging/vc04_services/vc-sm-cma/vc_sm.h | 59 ++
+ .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c | 498 +++++++++++
+ .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.h | 59 ++
+ .../vc04_services/vc-sm-cma/vc_sm_defs.h | 298 +++++++
+ .../vc04_services/vc-sm-cma/vc_sm_knl.h | 28 +
+ 11 files changed, 1802 insertions(+)
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/Kconfig
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/Makefile
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/TODO
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
+
+--- a/drivers/staging/vc04_services/Kconfig
++++ b/drivers/staging/vc04_services/Kconfig
+@@ -22,6 +22,7 @@ source "drivers/staging/vc04_services/bc
+
+ source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
+ source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
++source "drivers/staging/vc04_services/vc-sm-cma/Kconfig"
+
+ endif
+
+--- a/drivers/staging/vc04_services/Makefile
++++ b/drivers/staging/vc04_services/Makefile
+@@ -13,6 +13,7 @@ vchiq-objs := \
+ obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/
+ obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/
+ obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
++obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma/
+
+ ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000
+
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/Kconfig
+@@ -0,0 +1,10 @@
++config BCM_VC_SM_CMA
++ tristate "VideoCore Shared Memory (CMA) driver"
++ depends on BCM2835_VCHIQ
++ select RBTREE
++ select DMA_SHARED_BUFFER
++ help
++ Say Y here to enable the shared memory interface that
++ supports sharing dmabufs with VideoCore.
++ This operates over the VCHIQ interface to a service
++ running on VideoCore.
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/Makefile
+@@ -0,0 +1,8 @@
++ccflags-y += -Idrivers/staging/vc04_services -Idrivers/staging/vc04_services/interface/vchi -Idrivers/staging/vc04_services/interface/vchiq_arm
++# -I"drivers/staging/android/ion/" -I"$(srctree)/fs/"
++ccflags-y += -D__VCCOREVER__=0
++
++vc-sm-cma-$(CONFIG_BCM_VC_SM_CMA) := \
++ vc_sm.o vc_sm_cma_vchi.o
++
++obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma.o
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/TODO
+@@ -0,0 +1,2 @@
++1) Convert to a platform driver.
++
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -0,0 +1,838 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * VideoCore Shared Memory driver using CMA.
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ * Dave Stevenson <dave.stevenson@raspberrypi.org>
++ *
++ * Based on vmcs_sm driver from Broadcom Corporation for some API,
++ * and taking some code for CMA/dmabuf handling from the Android Ion
++ * driver (Google/Linaro).
++ *
++ * This is cut down version to only support import of dma_bufs from
++ * other kernel drivers. A more complete implementation of the old
++ * vmcs_sm functionality can follow later.
++ *
++ */
++
++/* ---- Include Files ----------------------------------------------------- */
++#include <linux/cdev.h>
++#include <linux/device.h>
++#include <linux/debugfs.h>
++#include <linux/dma-mapping.h>
++#include <linux/dma-buf.h>
++#include <linux/errno.h>
++#include <linux/fs.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/miscdevice.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/proc_fs.h>
++#include <linux/slab.h>
++#include <linux/seq_file.h>
++#include <linux/syscalls.h>
++#include <linux/types.h>
++
++#include "vchiq_connected.h"
++#include "vc_sm_cma_vchi.h"
++
++#include "vc_sm.h"
++#include "vc_sm_knl.h"
++
++/* ---- Private Constants and Types --------------------------------------- */
++
++#define DEVICE_NAME "vcsm-cma"
++#define DEVICE_MINOR 0
++
++#define VC_SM_RESOURCE_NAME_DEFAULT "sm-host-resource"
++
++#define VC_SM_DIR_ROOT_NAME "vcsm-cma"
++#define VC_SM_STATE "state"
++
++/* Private file data associated with each opened device. */
++struct vc_sm_privdata_t {
++ pid_t pid; /* PID of creator. */
++
++ int restart_sys; /* Tracks restart on interrupt. */
++ enum vc_sm_msg_type int_action; /* Interrupted action. */
++ u32 int_trans_id; /* Interrupted transaction. */
++};
++
++typedef int (*VC_SM_SHOW) (struct seq_file *s, void *v);
++struct sm_pde_t {
++ VC_SM_SHOW show; /* Debug fs function hookup. */
++ struct dentry *dir_entry; /* Debug fs directory entry. */
++ void *priv_data; /* Private data */
++};
++
++/* Global state information. */
++struct sm_state_t {
++ struct platform_device *pdev;
++
++ struct miscdevice dev;
++ struct sm_instance *sm_handle; /* Handle for videocore service. */
++
++ struct mutex map_lock; /* Global map lock. */
++ struct list_head buffer_list; /* List of buffer. */
++
++ struct vc_sm_privdata_t *data_knl; /* Kernel internal data tracking. */
++ struct dentry *dir_root; /* Debug fs entries root. */
++ struct sm_pde_t dir_state; /* Debug fs entries state sub-tree. */
++
++ bool require_released_callback; /* VPU will send a released msg when it
++ * has finished with a resource.
++ */
++ u32 int_trans_id; /* Interrupted transaction. */
++};
++
++/* ---- Private Variables ----------------------------------------------- */
++
++static struct sm_state_t *sm_state;
++static int sm_inited;
++
++/* ---- Private Function Prototypes -------------------------------------- */
++
++/* ---- Private Functions ------------------------------------------------ */
++
++static int vc_sm_cma_seq_file_show(struct seq_file *s, void *v)
++{
++ struct sm_pde_t *sm_pde;
++
++ sm_pde = (struct sm_pde_t *)(s->private);
++
++ if (sm_pde && sm_pde->show)
++ sm_pde->show(s, v);
++
++ return 0;
++}
++
++static int vc_sm_cma_single_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, vc_sm_cma_seq_file_show, inode->i_private);
++}
++
++static const struct file_operations vc_sm_cma_debug_fs_fops = {
++ .open = vc_sm_cma_single_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int vc_sm_cma_global_state_show(struct seq_file *s, void *v)
++{
++ struct vc_sm_buffer *resource = NULL;
++ int resource_count = 0;
++
++ if (!sm_state)
++ return 0;
++
++ seq_printf(s, "\nVC-ServiceHandle 0x%x\n",
++ (unsigned int)sm_state->sm_handle);
++
++ /* Log all applicable mapping(s). */
++
++ mutex_lock(&sm_state->map_lock);
++ seq_puts(s, "\nResources\n");
++ if (!list_empty(&sm_state->buffer_list)) {
++ list_for_each_entry(resource, &sm_state->buffer_list,
++ global_buffer_list) {
++ resource_count++;
++
++ seq_printf(s, "\nResource %p\n",
++ resource);
++ seq_printf(s, " NAME %s\n",
++ resource->name);
++ seq_printf(s, " SIZE %d\n",
++ resource->size);
++ seq_printf(s, " DMABUF %p\n",
++ resource->dma_buf);
++ seq_printf(s, " ATTACH %p\n",
++ resource->attach);
++ seq_printf(s, " SG_TABLE %p\n",
++ resource->sg_table);
++ seq_printf(s, " SGT %p\n",
++ resource->sgt);
++ seq_printf(s, " DMA_ADDR %pad\n",
++ &resource->dma_addr);
++ seq_printf(s, " VC_HANDLE %08x\n",
++ resource->vc_handle);
++ seq_printf(s, " VC_MAPPING %d\n",
++ resource->vpu_state);
++ }
++ }
++ seq_printf(s, "\n\nTotal resource count: %d\n\n", resource_count);
++
++ mutex_unlock(&sm_state->map_lock);
++
++ return 0;
++}
++
++/*
++ * Adds a buffer to the private data list which tracks all the allocated
++ * data.
++ */
++static void vc_sm_add_resource(struct vc_sm_privdata_t *privdata,
++ struct vc_sm_buffer *buffer)
++{
++ mutex_lock(&sm_state->map_lock);
++ list_add(&buffer->global_buffer_list, &sm_state->buffer_list);
++ mutex_unlock(&sm_state->map_lock);
++
++ pr_debug("[%s]: added buffer %p (name %s, size %d)\n",
++ __func__, buffer, buffer->name, buffer->size);
++}
++
++/*
++ * Release an allocation.
++ * All refcounting is done via the dma buf object.
++ */
++static void vc_sm_release_resource(struct vc_sm_buffer *buffer, int force)
++{
++ mutex_lock(&sm_state->map_lock);
++ mutex_lock(&buffer->lock);
++
++ pr_debug("[%s]: buffer %p (name %s, size %d)\n",
++ __func__, buffer, buffer->name, buffer->size);
++
++ if (buffer->vc_handle && buffer->vpu_state == VPU_MAPPED) {
++ struct vc_sm_free_t free = { buffer->vc_handle, 0 };
++ int status = vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
++ &sm_state->int_trans_id);
++ if (status != 0 && status != -EINTR) {
++ pr_err("[%s]: failed to free memory on videocore (status: %u, trans_id: %u)\n",
++ __func__, status, sm_state->int_trans_id);
++ }
++
++ if (sm_state->require_released_callback) {
++ /* Need to wait for the VPU to confirm the free */
++
++ /* Retain a reference on this until the VPU has
++ * released it
++ */
++ buffer->vpu_state = VPU_UNMAPPING;
++ goto defer;
++ }
++ buffer->vpu_state = VPU_NOT_MAPPED;
++ buffer->vc_handle = 0;
++ }
++ if (buffer->vc_handle) {
++ /* We've sent the unmap request but not had the response. */
++ pr_err("[%s]: Waiting for VPU unmap response on %p\n",
++ __func__, buffer);
++ goto defer;
++ }
++ if (buffer->in_use) {
++ /* Don't release dmabuf here - we await the release */
++ pr_err("[%s]: buffer %p is still in use\n",
++ __func__, buffer);
++ goto defer;
++ }
++
++ /* Handle cleaning up imported dmabufs */
++ if (buffer->sgt) {
++ dma_buf_unmap_attachment(buffer->attach, buffer->sgt,
++ DMA_BIDIRECTIONAL);
++ buffer->sgt = NULL;
++ }
++ if (buffer->attach) {
++ dma_buf_detach(buffer->dma_buf, buffer->attach);
++ buffer->attach = NULL;
++ }
++
++ /* Release the dma_buf (whether ours or imported) */
++ if (buffer->import_dma_buf) {
++ dma_buf_put(buffer->import_dma_buf);
++ buffer->import_dma_buf = NULL;
++ buffer->dma_buf = NULL;
++ } else if (buffer->dma_buf) {
++ dma_buf_put(buffer->dma_buf);
++ buffer->dma_buf = NULL;
++ }
++
++ if (buffer->sg_table && !buffer->import_dma_buf) {
++ /* Our own allocation that we need to dma_unmap_sg */
++ dma_unmap_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
++ buffer->sg_table->nents, DMA_BIDIRECTIONAL);
++ }
++
++ /* Free the local resource. Start by removing it from the list */
++ buffer->private = NULL;
++ list_del(&buffer->global_buffer_list);
++
++ mutex_unlock(&buffer->lock);
++ mutex_unlock(&sm_state->map_lock);
++
++ mutex_destroy(&buffer->lock);
++
++ kfree(buffer);
++ return;
++
++defer:
++ mutex_unlock(&buffer->lock);
++ mutex_unlock(&sm_state->map_lock);
++}
++
++/* Create support for private data tracking. */
++static struct vc_sm_privdata_t *vc_sm_cma_create_priv_data(pid_t id)
++{
++ char alloc_name[32];
++ struct vc_sm_privdata_t *file_data = NULL;
++
++ /* Allocate private structure. */
++ file_data = kzalloc(sizeof(*file_data), GFP_KERNEL);
++
++ if (!file_data)
++ return NULL;
++
++ snprintf(alloc_name, sizeof(alloc_name), "%d", id);
++
++ file_data->pid = id;
++
++ return file_data;
++}
++
++/* Dma_buf operations for chaining through to an imported dma_buf */
++static
++int vc_sm_import_dma_buf_attach(struct dma_buf *dmabuf,
++ struct dma_buf_attachment *attachment)
++{
++ struct vc_sm_buffer *res = dmabuf->priv;
++
++ if (!res->import_dma_buf)
++ return -EINVAL;
++ return res->import_dma_buf->ops->attach(res->import_dma_buf,
++ attachment);
++}
++
++static
++void vc_sm_import_dma_buf_detatch(struct dma_buf *dmabuf,
++ struct dma_buf_attachment *attachment)
++{
++ struct vc_sm_buffer *res = dmabuf->priv;
++
++ if (!res->import_dma_buf)
++ return;
++ res->import_dma_buf->ops->detach(res->import_dma_buf, attachment);
++}
++
++static
++struct sg_table *vc_sm_import_map_dma_buf(struct dma_buf_attachment *attachment,
++ enum dma_data_direction direction)
++{
++ struct vc_sm_buffer *res = attachment->dmabuf->priv;
++
++ if (!res->import_dma_buf)
++ return NULL;
++ return res->import_dma_buf->ops->map_dma_buf(attachment, direction);
++}
++
++static
++void vc_sm_import_unmap_dma_buf(struct dma_buf_attachment *attachment,
++ struct sg_table *table,
++ enum dma_data_direction direction)
++{
++ struct vc_sm_buffer *res = attachment->dmabuf->priv;
++
++ if (!res->import_dma_buf)
++ return;
++ res->import_dma_buf->ops->unmap_dma_buf(attachment, table, direction);
++}
++
++static
++int vc_sm_import_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
++{
++ struct vc_sm_buffer *res = dmabuf->priv;
++
++ pr_debug("%s: mmap dma_buf %p, res %p, imported db %p\n", __func__,
++ dmabuf, res, res->import_dma_buf);
++ if (!res->import_dma_buf) {
++ pr_err("%s: mmap dma_buf %p- not an imported buffer\n",
++ __func__, dmabuf);
++ return -EINVAL;
++ }
++ return res->import_dma_buf->ops->mmap(res->import_dma_buf, vma);
++}
++
++static
++void vc_sm_import_dma_buf_release(struct dma_buf *dmabuf)
++{
++ struct vc_sm_buffer *res = dmabuf->priv;
++
++ pr_debug("%s: Relasing dma_buf %p\n", __func__, dmabuf);
++ if (!res->import_dma_buf)
++ return;
++
++ res->in_use = 0;
++
++ vc_sm_release_resource(res, 0);
++}
++
++static
++void *vc_sm_import_dma_buf_kmap(struct dma_buf *dmabuf,
++ unsigned long offset)
++{
++ struct vc_sm_buffer *res = dmabuf->priv;
++
++ if (!res->import_dma_buf)
++ return NULL;
++ return res->import_dma_buf->ops->map(res->import_dma_buf,
++ offset);
++}
++
++static
++void vc_sm_import_dma_buf_kunmap(struct dma_buf *dmabuf,
++ unsigned long offset, void *ptr)
++{
++ struct vc_sm_buffer *res = dmabuf->priv;
++
++ if (!res->import_dma_buf)
++ return;
++ res->import_dma_buf->ops->unmap(res->import_dma_buf,
++ offset, ptr);
++}
++
++static
++int vc_sm_import_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
++ enum dma_data_direction direction)
++{
++ struct vc_sm_buffer *res = dmabuf->priv;
++
++ if (!res->import_dma_buf)
++ return -EINVAL;
++ return res->import_dma_buf->ops->begin_cpu_access(res->import_dma_buf,
++ direction);
++}
++
++static
++int vc_sm_import_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
++ enum dma_data_direction direction)
++{
++ struct vc_sm_buffer *res = dmabuf->priv;
++
++ if (!res->import_dma_buf)
++ return -EINVAL;
++ return res->import_dma_buf->ops->end_cpu_access(res->import_dma_buf,
++ direction);
++}
++
++static const struct dma_buf_ops dma_buf_import_ops = {
++ .map_dma_buf = vc_sm_import_map_dma_buf,
++ .unmap_dma_buf = vc_sm_import_unmap_dma_buf,
++ .mmap = vc_sm_import_dmabuf_mmap,
++ .release = vc_sm_import_dma_buf_release,
++ .attach = vc_sm_import_dma_buf_attach,
++ .detach = vc_sm_import_dma_buf_detatch,
++ .begin_cpu_access = vc_sm_import_dma_buf_begin_cpu_access,
++ .end_cpu_access = vc_sm_import_dma_buf_end_cpu_access,
++ .map = vc_sm_import_dma_buf_kmap,
++ .unmap = vc_sm_import_dma_buf_kunmap,
++};
++
++/* Import a dma_buf to be shared with VC. */
++int
++vc_sm_cma_import_dmabuf_internal(struct vc_sm_privdata_t *private,
++ struct dma_buf *dma_buf,
++ struct dma_buf **imported_buf)
++{
++ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
++ struct vc_sm_buffer *buffer = NULL;
++ struct vc_sm_import import = { };
++ struct vc_sm_import_result result = { };
++ struct dma_buf_attachment *attach = NULL;
++ struct sg_table *sgt = NULL;
++ int ret = 0;
++ int status;
++
++ /* Setup our allocation parameters */
++ pr_debug("%s: importing dma_buf %p\n", __func__, dma_buf);
++
++ get_dma_buf(dma_buf);
++ dma_buf = dma_buf;
++
++ attach = dma_buf_attach(dma_buf, &sm_state->pdev->dev);
++ if (IS_ERR(attach)) {
++ ret = PTR_ERR(attach);
++ goto error;
++ }
++
++ sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
++ if (IS_ERR(sgt)) {
++ ret = PTR_ERR(sgt);
++ goto error;
++ }
++
++ /* Verify that the address block is contiguous */
++ if (sgt->nents != 1) {
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ /* Allocate local buffer to track this allocation. */
++ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
++ if (!buffer) {
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ import.type = VC_SM_ALLOC_NON_CACHED;
++ import.addr = (uint32_t)sg_dma_address(sgt->sgl);
++ if ((import.addr & 0xC0000000) != 0xC0000000) {
++ pr_err("%s: Expecting an uncached alias for dma_addr %08x\n",
++ __func__, import.addr);
++ import.addr |= 0xC0000000;
++ }
++ import.size = sg_dma_len(sgt->sgl);
++ import.allocator = current->tgid;
++ import.kernel_id = (uint32_t)buffer; //FIXME: 64 bit support needed.
++
++ memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
++ sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
++
++ pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %p, size %u\n",
++ __func__, import.name, import.type, (void *)import.addr,
++ import.size);
++
++ /* Allocate the videocore buffer. */
++ status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
++ &sm_state->int_trans_id);
++ if (status == -EINTR) {
++ pr_debug("[%s]: requesting import memory action restart (trans_id: %u)\n",
++ __func__, sm_state->int_trans_id);
++ ret = -ERESTARTSYS;
++ private->restart_sys = -EINTR;
++ private->int_action = VC_SM_MSG_TYPE_IMPORT;
++ goto error;
++ } else if (status || !result.res_handle) {
++ pr_debug("[%s]: failed to import memory on videocore (status: %u, trans_id: %u)\n",
++ __func__, status, sm_state->int_trans_id);
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ mutex_init(&buffer->lock);
++ INIT_LIST_HEAD(&buffer->attachments);
++ memcpy(buffer->name, import.name,
++ min(sizeof(buffer->name), sizeof(import.name) - 1));
++
++ /* Keep track of the buffer we created. */
++ buffer->private = private;
++ buffer->vc_handle = result.res_handle;
++ buffer->size = import.size;
++ buffer->vpu_state = VPU_MAPPED;
++
++ buffer->import_dma_buf = dma_buf;
++
++ buffer->attach = attach;
++ buffer->sgt = sgt;
++ buffer->dma_addr = sg_dma_address(sgt->sgl);
++ buffer->in_use = 1;
++
++ /*
++ * We're done - we need to export a new dmabuf chaining through most
++ * functions, but enabling us to release our own internal references
++ * here.
++ */
++ exp_info.ops = &dma_buf_import_ops;
++ exp_info.size = import.size;
++ exp_info.flags = O_RDWR;
++ exp_info.priv = buffer;
++
++ buffer->dma_buf = dma_buf_export(&exp_info);
++ if (IS_ERR(buffer->dma_buf)) {
++ ret = PTR_ERR(buffer->dma_buf);
++ goto error;
++ }
++
++ vc_sm_add_resource(private, buffer);
++
++ *imported_buf = buffer->dma_buf;
++
++ return 0;
++
++error:
++ if (result.res_handle) {
++ struct vc_sm_free_t free = { result.res_handle, 0 };
++
++ vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
++ &sm_state->int_trans_id);
++ }
++ kfree(buffer);
++ if (sgt)
++ dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
++ if (attach)
++ dma_buf_detach(dma_buf, attach);
++ dma_buf_put(dma_buf);
++ return ret;
++}
++
++/* FIXME: Pass a function pointer to this into vc_vchi_sm.c */
++void
++vc_sm_vpu_event(struct sm_instance *instance, struct vc_sm_result_t *reply,
++ int reply_len)
++{
++ switch (reply->trans_id & ~0x80000000) {
++ case VC_SM_MSG_TYPE_CLIENT_VERSION:
++ {
++ /* Acknowledge that the firmware supports the version command */
++ pr_debug("%s: firmware acked version msg. Require release cb\n",
++ __func__);
++ sm_state->require_released_callback = true;
++ }
++ break;
++ case VC_SM_MSG_TYPE_RELEASED:
++ {
++ struct vc_sm_released *release = (struct vc_sm_released *)reply;
++ struct vc_sm_buffer *buffer =
++ (struct vc_sm_buffer *)release->kernel_id;
++
++ /*
++ * FIXME: Need to check buffer is still valid and allocated
++ * before continuing
++ */
++ pr_debug("%s: Released addr %08x, size %u, id %08x, mem_handle %08x\n",
++ __func__, release->addr, release->size,
++ release->kernel_id, release->vc_handle);
++ mutex_lock(&buffer->lock);
++ buffer->vc_handle = 0;
++ buffer->vpu_state = VPU_NOT_MAPPED;
++ mutex_unlock(&buffer->lock);
++
++ vc_sm_release_resource(buffer, 0);
++ }
++ break;
++ default:
++ pr_err("%s: Unknown vpu cmd %x\n", __func__, reply->trans_id);
++ break;
++ }
++}
++
++/* Videocore connected. */
++static void vc_sm_connected_init(void)
++{
++ int ret;
++ VCHI_INSTANCE_T vchi_instance;
++ struct vc_sm_version version;
++ struct vc_sm_result_t version_result;
++
++ pr_info("[%s]: start\n", __func__);
++
++ /*
++ * Initialize and create a VCHI connection for the shared memory service
++ * running on videocore.
++ */
++ ret = vchi_initialise(&vchi_instance);
++ if (ret) {
++ pr_err("[%s]: failed to initialise VCHI instance (ret=%d)\n",
++ __func__, ret);
++
++ ret = -EIO;
++ goto err_free_mem;
++ }
++
++ ret = vchi_connect(vchi_instance);
++ if (ret) {
++ pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n",
++ __func__, ret);
++
++ ret = -EIO;
++ goto err_free_mem;
++ }
++
++ /* Initialize an instance of the shared memory service. */
++ sm_state->sm_handle = vc_sm_cma_vchi_init(vchi_instance, 1,
++ vc_sm_vpu_event);
++ if (!sm_state->sm_handle) {
++ pr_err("[%s]: failed to initialize shared memory service\n",
++ __func__);
++
++ ret = -EPERM;
++ goto err_free_mem;
++ }
++
++ /* Create a debug fs directory entry (root). */
++ sm_state->dir_root = debugfs_create_dir(VC_SM_DIR_ROOT_NAME, NULL);
++ if (!sm_state->dir_root) {
++ pr_err("[%s]: failed to create \'%s\' directory entry\n",
++ __func__, VC_SM_DIR_ROOT_NAME);
++
++ ret = -EPERM;
++ goto err_stop_sm_service;
++ }
++
++ sm_state->dir_state.show = &vc_sm_cma_global_state_show;
++ sm_state->dir_state.dir_entry =
++ debugfs_create_file(VC_SM_STATE, 0444, sm_state->dir_root,
++ &sm_state->dir_state,
++ &vc_sm_cma_debug_fs_fops);
++
++ INIT_LIST_HEAD(&sm_state->buffer_list);
++
++ sm_state->data_knl = vc_sm_cma_create_priv_data(0);
++ if (!sm_state->data_knl) {
++ pr_err("[%s]: failed to create kernel private data tracker\n",
++ __func__);
++ goto err_remove_shared_memory;
++ }
++
++ version.version = 1;
++ ret = vc_sm_cma_vchi_client_version(sm_state->sm_handle, &version,
++ &version_result,
++ &sm_state->int_trans_id);
++ if (ret) {
++ pr_err("[%s]: Failed to send version request %d\n", __func__,
++ ret);
++ }
++
++ /* Done! */
++ sm_inited = 1;
++ pr_info("[%s]: installed successfully\n", __func__);
++ return;
++
++err_remove_shared_memory:
++ debugfs_remove_recursive(sm_state->dir_root);
++err_stop_sm_service:
++ vc_sm_cma_vchi_stop(&sm_state->sm_handle);
++err_free_mem:
++ kfree(sm_state);
++ pr_info("[%s]: failed, ret %d\n", __func__, ret);
++}
++
++/* Driver loading. */
++static int bcm2835_vc_sm_cma_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ int err;
++
++ pr_info("%s: Videocore shared memory driver\n", __func__);
++
++ sm_state = kzalloc(sizeof(*sm_state), GFP_KERNEL);
++ if (!sm_state)
++ return -ENOMEM;
++ sm_state->pdev = pdev;
++ mutex_init(&sm_state->map_lock);
++
++ dev->coherent_dma_mask = DMA_BIT_MASK(32);
++ dev->dma_mask = &dev->coherent_dma_mask;
++ err = of_dma_configure(dev, NULL, true);
++ if (err) {
++ dev_err(dev, "Unable to setup DMA: %d\n", err);
++ return err;
++ }
++
++ vchiq_add_connected_callback(vc_sm_connected_init);
++ return 0;
++}
++
++/* Driver unloading. */
++static int bcm2835_vc_sm_cma_remove(struct platform_device *pdev)
++{
++ pr_debug("[%s]: start\n", __func__);
++ if (sm_inited) {
++ /* Remove shared memory device. */
++ misc_deregister(&sm_state->dev);
++
++ /* Remove all proc entries. */
++ //debugfs_remove_recursive(sm_state->dir_root);
++
++ /* Stop the videocore shared memory service. */
++ vc_sm_cma_vchi_stop(&sm_state->sm_handle);
++
++ /* Free the memory for the state structure. */
++ mutex_destroy(&sm_state->map_lock);
++ kfree(sm_state);
++ }
++
++ pr_debug("[%s]: end\n", __func__);
++ return 0;
++}
++
++/* Get an internal resource handle mapped from the external one. */
++int vc_sm_cma_int_handle(int handle)
++{
++ struct dma_buf *dma_buf = (struct dma_buf *)handle;
++ struct vc_sm_buffer *res;
++
++ /* Validate we can work with this device. */
++ if (!sm_state || !handle) {
++ pr_err("[%s]: invalid input\n", __func__);
++ return 0;
++ }
++
++ res = (struct vc_sm_buffer *)dma_buf->priv;
++ return res->vc_handle;
++}
++EXPORT_SYMBOL_GPL(vc_sm_cma_int_handle);
++
++/* Free a previously allocated shared memory handle and block. */
++int vc_sm_cma_free(int handle)
++{
++ struct dma_buf *dma_buf = (struct dma_buf *)handle;
++
++ /* Validate we can work with this device. */
++ if (!sm_state || !handle) {
++ pr_err("[%s]: invalid input\n", __func__);
++ return -EPERM;
++ }
++
++ pr_debug("%s: handle %08x/dmabuf %p\n", __func__, handle, dma_buf);
++
++ dma_buf_put(dma_buf);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(vc_sm_cma_free);
++
++/* Import a dmabuf to be shared with VC. */
++int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, int *handle)
++{
++ struct dma_buf *new_dma_buf;
++ struct vc_sm_buffer *res;
++ int ret;
++
++ /* Validate we can work with this device. */
++ if (!sm_state || !src_dmabuf || !handle) {
++ pr_err("[%s]: invalid input\n", __func__);
++ return -EPERM;
++ }
++
++ ret = vc_sm_cma_import_dmabuf_internal(sm_state->data_knl, src_dmabuf,
++ &new_dma_buf);
++
++ if (!ret) {
++ pr_debug("%s: imported to ptr %p\n", __func__, new_dma_buf);
++ res = (struct vc_sm_buffer *)new_dma_buf->priv;
++
++ /* Assign valid handle at this time.*/
++ *handle = (int)new_dma_buf;
++ } else {
++ /*
++ * succeeded in importing the dma_buf, but then
++ * failed to look it up again. How?
++ * Release the fd again.
++ */
++ pr_err("%s: imported vc_sm_cma_get_buffer failed %d\n",
++ __func__, ret);
++ }
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(vc_sm_cma_import_dmabuf);
++
++static struct platform_driver bcm2835_vcsm_cma_driver = {
++ .probe = bcm2835_vc_sm_cma_probe,
++ .remove = bcm2835_vc_sm_cma_remove,
++ .driver = {
++ .name = DEVICE_NAME,
++ .owner = THIS_MODULE,
++ },
++};
++
++module_platform_driver(bcm2835_vcsm_cma_driver);
++
++MODULE_AUTHOR("Dave Stevenson");
++MODULE_DESCRIPTION("VideoCore CMA Shared Memory Driver");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:vcsm-cma");
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
+@@ -0,0 +1,59 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++/*
++ * VideoCore Shared Memory driver using CMA.
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ *
++ */
++
++#ifndef VC_SM_H
++#define VC_SM_H
++
++#include <linux/device.h>
++#include <linux/dma-direction.h>
++#include <linux/kref.h>
++#include <linux/mm_types.h>
++#include <linux/mutex.h>
++#include <linux/rbtree.h>
++#include <linux/sched.h>
++#include <linux/shrinker.h>
++#include <linux/types.h>
++#include <linux/miscdevice.h>
++
++#define VC_SM_MAX_NAME_LEN 32
++
++enum vc_sm_vpu_mapping_state {
++ VPU_NOT_MAPPED,
++ VPU_MAPPED,
++ VPU_UNMAPPING
++};
++
++struct vc_sm_buffer {
++ struct list_head global_buffer_list; /* Global list of buffers. */
++
++ size_t size;
++
++ /* Lock over all the following state for this buffer */
++ struct mutex lock;
++ struct sg_table *sg_table;
++ struct list_head attachments;
++
++ char name[VC_SM_MAX_NAME_LEN];
++
++ int in_use:1; /* Kernel is still using this resource */
++
++ enum vc_sm_vpu_mapping_state vpu_state;
++ u32 vc_handle; /* VideoCore handle for this buffer */
++
++ /* DMABUF related fields */
++ struct dma_buf *import_dma_buf;
++ struct dma_buf *dma_buf;
++ struct dma_buf_attachment *attach;
++ struct sg_table *sgt;
++ dma_addr_t dma_addr;
++
++ struct vc_sm_privdata_t *private;
++};
++
++#endif
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
+@@ -0,0 +1,498 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * VideoCore Shared Memory CMA allocator
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ * Copyright 2011-2012 Broadcom Corporation. All rights reserved.
++ *
++ * Based on vmcs_sm driver from Broadcom Corporation.
++ *
++ */
++
++/* ---- Include Files ----------------------------------------------------- */
++#include <linux/completion.h>
++#include <linux/kernel.h>
++#include <linux/kthread.h>
++#include <linux/list.h>
++#include <linux/mutex.h>
++#include <linux/semaphore.h>
++#include <linux/slab.h>
++#include <linux/types.h>
++
++#include "vc_sm_cma_vchi.h"
++
++#define VC_SM_VER 1
++#define VC_SM_MIN_VER 0
++
++/* ---- Private Constants and Types -------------------------------------- */
++
++/* Command blocks come from a pool */
++#define SM_MAX_NUM_CMD_RSP_BLKS 32
++
++struct sm_cmd_rsp_blk {
++ struct list_head head; /* To create lists */
++ /* To be signaled when the response is there */
++ struct completion cmplt;
++
++ u16 id;
++ u16 length;
++
++ u8 msg[VC_SM_MAX_MSG_LEN];
++
++ uint32_t wait:1;
++ uint32_t sent:1;
++ uint32_t alloc:1;
++
++};
++
++struct sm_instance {
++ u32 num_connections;
++ VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS];
++ struct task_struct *io_thread;
++ struct completion io_cmplt;
++
++ vpu_event_cb vpu_event;
++
++ /* Mutex over the following lists */
++ struct mutex lock;
++ u32 trans_id;
++ struct list_head cmd_list;
++ struct list_head rsp_list;
++ struct list_head dead_list;
++
++ struct sm_cmd_rsp_blk free_blk[SM_MAX_NUM_CMD_RSP_BLKS];
++
++ /* Mutex over the free_list */
++ struct mutex free_lock;
++ struct list_head free_list;
++
++ struct semaphore free_sema;
++
++};
++
++/* ---- Private Variables ------------------------------------------------ */
++
++/* ---- 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,
++ enum vc_sm_msg_type id, void *msg,
++ u32 size, int wait)
++{
++ struct sm_cmd_rsp_blk *blk;
++ struct vc_sm_msg_hdr_t *hdr;
++
++ if (down_interruptible(&instance->free_sema)) {
++ blk = kmalloc(sizeof(*blk), GFP_KERNEL);
++ if (!blk)
++ return NULL;
++
++ blk->alloc = 1;
++ init_completion(&blk->cmplt);
++ } else {
++ mutex_lock(&instance->free_lock);
++ blk =
++ list_first_entry(&instance->free_list,
++ struct sm_cmd_rsp_blk, head);
++ list_del(&blk->head);
++ mutex_unlock(&instance->free_lock);
++ }
++
++ blk->sent = 0;
++ blk->wait = wait;
++ blk->length = sizeof(*hdr) + size;
++
++ hdr = (struct vc_sm_msg_hdr_t *)blk->msg;
++ hdr->type = id;
++ mutex_lock(&instance->lock);
++ instance->trans_id++;
++ /*
++ * Retain the top bit for identifying asynchronous events, or VPU cmds.
++ */
++ instance->trans_id &= ~0x80000000;
++ hdr->trans_id = instance->trans_id;
++ blk->id = instance->trans_id;
++ mutex_unlock(&instance->lock);
++
++ if (size)
++ memcpy(hdr->body, msg, size);
++
++ return blk;
++}
++
++static void
++vc_vchi_cmd_delete(struct sm_instance *instance, struct sm_cmd_rsp_blk *blk)
++{
++ if (blk->alloc) {
++ kfree(blk);
++ return;
++ }
++
++ mutex_lock(&instance->free_lock);
++ list_add(&blk->head, &instance->free_list);
++ mutex_unlock(&instance->free_lock);
++ up(&instance->free_sema);
++}
++
++static void vc_sm_cma_vchi_rx_ack(struct sm_instance *instance,
++ struct sm_cmd_rsp_blk *cmd,
++ struct vc_sm_result_t *reply,
++ u32 reply_len)
++{
++ mutex_lock(&instance->lock);
++ list_for_each_entry(cmd,
++ &instance->rsp_list,
++ head) {
++ if (cmd->id == reply->trans_id)
++ break;
++ }
++ mutex_unlock(&instance->lock);
++
++ if (&cmd->head == &instance->rsp_list) {
++ //pr_debug("%s: received response %u, throw away...",
++ pr_err("%s: received response %u, throw away...",
++ __func__,
++ reply->trans_id);
++ } else if (reply_len > sizeof(cmd->msg)) {
++ pr_err("%s: reply too big (%u) %u, throw away...",
++ __func__, reply_len,
++ reply->trans_id);
++ } else {
++ memcpy(cmd->msg, reply,
++ reply_len);
++ complete(&cmd->cmplt);
++ }
++}
++
++static int vc_sm_cma_vchi_videocore_io(void *arg)
++{
++ struct sm_instance *instance = arg;
++ struct sm_cmd_rsp_blk *cmd = NULL, *cmd_tmp;
++ struct vc_sm_result_t *reply;
++ u32 reply_len;
++ s32 status;
++ int svc_use = 1;
++
++ while (1) {
++ if (svc_use)
++ vchi_service_release(instance->vchi_handle[0]);
++ svc_use = 0;
++ if (!wait_for_completion_interruptible(&instance->io_cmplt)) {
++ vchi_service_use(instance->vchi_handle[0]);
++ svc_use = 1;
++
++ do {
++ /*
++ * Get new command and move it to response list
++ */
++ mutex_lock(&instance->lock);
++ if (list_empty(&instance->cmd_list)) {
++ /* no more commands to process */
++ mutex_unlock(&instance->lock);
++ break;
++ }
++ cmd =
++ list_first_entry(&instance->cmd_list,
++ struct sm_cmd_rsp_blk,
++ head);
++ list_move(&cmd->head, &instance->rsp_list);
++ cmd->sent = 1;
++ mutex_unlock(&instance->lock);
++
++ /* Send the command */
++ status = bcm2835_vchi_msg_queue(
++ instance->vchi_handle[0],
++ cmd->msg, cmd->length);
++ if (status) {
++ pr_err("%s: failed to queue message (%d)",
++ __func__, status);
++ }
++
++ /* If no reply is needed then we're done */
++ if (!cmd->wait) {
++ mutex_lock(&instance->lock);
++ list_del(&cmd->head);
++ mutex_unlock(&instance->lock);
++ vc_vchi_cmd_delete(instance, cmd);
++ continue;
++ }
++
++ if (status) {
++ complete(&cmd->cmplt);
++ continue;
++ }
++
++ } while (1);
++
++ while (!vchi_msg_peek(instance->vchi_handle[0],
++ (void **)&reply, &reply_len,
++ VCHI_FLAGS_NONE)) {
++ if (reply->trans_id & 0x80000000) {
++ /* Async event or cmd from the VPU */
++ if (instance->vpu_event)
++ instance->vpu_event(
++ instance, reply,
++ reply_len);
++ } else {
++ vc_sm_cma_vchi_rx_ack(instance, cmd,
++ reply, reply_len);
++ }
++
++ vchi_msg_remove(instance->vchi_handle[0]);
++ }
++
++ /* Go through the dead list and free them */
++ mutex_lock(&instance->lock);
++ list_for_each_entry_safe(cmd, cmd_tmp,
++ &instance->dead_list, head) {
++ list_del(&cmd->head);
++ vc_vchi_cmd_delete(instance, cmd);
++ }
++ mutex_unlock(&instance->lock);
++ }
++ }
++
++ return 0;
++}
++
++static void vc_sm_cma_vchi_callback(void *param,
++ const VCHI_CALLBACK_REASON_T reason,
++ void *msg_handle)
++{
++ struct sm_instance *instance = param;
++
++ (void)msg_handle;
++
++ switch (reason) {
++ case VCHI_CALLBACK_MSG_AVAILABLE:
++ complete(&instance->io_cmplt);
++ break;
++
++ case VCHI_CALLBACK_SERVICE_CLOSED:
++ pr_info("%s: service CLOSED!!", __func__);
++ default:
++ break;
++ }
++}
++
++struct sm_instance *vc_sm_cma_vchi_init(VCHI_INSTANCE_T vchi_instance,
++ unsigned int num_connections,
++ vpu_event_cb vpu_event)
++{
++ u32 i;
++ struct sm_instance *instance;
++ int status;
++
++ pr_debug("%s: start", __func__);
++
++ if (num_connections > VCHI_MAX_NUM_CONNECTIONS) {
++ pr_err("%s: unsupported number of connections %u (max=%u)",
++ __func__, num_connections, VCHI_MAX_NUM_CONNECTIONS);
++
++ goto err_null;
++ }
++ /* Allocate memory for this instance */
++ instance = kzalloc(sizeof(*instance), GFP_KERNEL);
++
++ /* Misc initialisations */
++ mutex_init(&instance->lock);
++ init_completion(&instance->io_cmplt);
++ INIT_LIST_HEAD(&instance->cmd_list);
++ INIT_LIST_HEAD(&instance->rsp_list);
++ INIT_LIST_HEAD(&instance->dead_list);
++ INIT_LIST_HEAD(&instance->free_list);
++ sema_init(&instance->free_sema, SM_MAX_NUM_CMD_RSP_BLKS);
++ mutex_init(&instance->free_lock);
++ for (i = 0; i < SM_MAX_NUM_CMD_RSP_BLKS; i++) {
++ init_completion(&instance->free_blk[i].cmplt);
++ list_add(&instance->free_blk[i].head, &instance->free_list);
++ }
++
++ /* Open the VCHI service connections */
++ instance->num_connections = num_connections;
++ for (i = 0; i < num_connections; i++) {
++ SERVICE_CREATION_T params = {
++ .version = VCHI_VERSION_EX(VC_SM_VER, VC_SM_MIN_VER),
++ .service_id = VC_SM_SERVER_NAME,
++ .callback = vc_sm_cma_vchi_callback,
++ .callback_param = instance,
++ };
++
++ status = vchi_service_open(vchi_instance,
++ ¶ms, &instance->vchi_handle[i]);
++ if (status) {
++ pr_err("%s: failed to open VCHI service (%d)",
++ __func__, status);
++
++ goto err_close_services;
++ }
++ }
++
++ /* Create the thread which takes care of all io to/from videoocore. */
++ instance->io_thread = kthread_create(&vc_sm_cma_vchi_videocore_io,
++ (void *)instance, "SMIO");
++ if (!instance->io_thread) {
++ pr_err("%s: failed to create SMIO thread", __func__);
++
++ goto err_close_services;
++ }
++ instance->vpu_event = vpu_event;
++ set_user_nice(instance->io_thread, -10);
++ wake_up_process(instance->io_thread);
++
++ pr_debug("%s: success - instance 0x%x", __func__,
++ (unsigned int)instance);
++ return instance;
++
++err_close_services:
++ for (i = 0; i < instance->num_connections; i++) {
++ if (instance->vchi_handle[i])
++ vchi_service_close(instance->vchi_handle[i]);
++ }
++ kfree(instance);
++err_null:
++ pr_debug("%s: FAILED", __func__);
++ return NULL;
++}
++
++int vc_sm_cma_vchi_stop(struct sm_instance **handle)
++{
++ struct sm_instance *instance;
++ u32 i;
++
++ if (!handle) {
++ pr_err("%s: invalid pointer to handle %p", __func__, handle);
++ goto lock;
++ }
++
++ if (!*handle) {
++ pr_err("%s: invalid handle %p", __func__, *handle);
++ goto lock;
++ }
++
++ instance = *handle;
++
++ /* Close all VCHI service connections */
++ for (i = 0; i < instance->num_connections; i++) {
++ s32 success;
++
++ vchi_service_use(instance->vchi_handle[i]);
++
++ success = vchi_service_close(instance->vchi_handle[i]);
++ }
++
++ kfree(instance);
++
++ *handle = NULL;
++ return 0;
++
++lock:
++ return -EINVAL;
++}
++
++static int vc_sm_cma_vchi_send_msg(struct sm_instance *handle,
++ enum vc_sm_msg_type msg_id, void *msg,
++ u32 msg_size, void *result, u32 result_size,
++ u32 *cur_trans_id, u8 wait_reply)
++{
++ int status = 0;
++ struct sm_instance *instance = handle;
++ struct sm_cmd_rsp_blk *cmd_blk;
++
++ if (!handle) {
++ pr_err("%s: invalid handle", __func__);
++ return -EINVAL;
++ }
++ if (!msg) {
++ pr_err("%s: invalid msg pointer", __func__);
++ return -EINVAL;
++ }
++
++ cmd_blk =
++ vc_vchi_cmd_create(instance, msg_id, msg, msg_size, wait_reply);
++ if (!cmd_blk) {
++ pr_err("[%s]: failed to allocate global tracking resource",
++ __func__);
++ return -ENOMEM;
++ }
++
++ if (cur_trans_id)
++ *cur_trans_id = cmd_blk->id;
++
++ mutex_lock(&instance->lock);
++ list_add_tail(&cmd_blk->head, &instance->cmd_list);
++ mutex_unlock(&instance->lock);
++ complete(&instance->io_cmplt);
++
++ if (!wait_reply)
++ /* We're done */
++ return 0;
++
++ /* Wait for the response */
++ if (wait_for_completion_interruptible(&cmd_blk->cmplt)) {
++ mutex_lock(&instance->lock);
++ if (!cmd_blk->sent) {
++ list_del(&cmd_blk->head);
++ mutex_unlock(&instance->lock);
++ vc_vchi_cmd_delete(instance, cmd_blk);
++ return -ENXIO;
++ }
++
++ list_move(&cmd_blk->head, &instance->dead_list);
++ mutex_unlock(&instance->lock);
++ complete(&instance->io_cmplt);
++ return -EINTR; /* We're done */
++ }
++
++ if (result && result_size) {
++ memcpy(result, cmd_blk->msg, result_size);
++ } else {
++ struct vc_sm_result_t *res =
++ (struct vc_sm_result_t *)cmd_blk->msg;
++ status = (res->success == 0) ? 0 : -ENXIO;
++ }
++
++ mutex_lock(&instance->lock);
++ list_del(&cmd_blk->head);
++ mutex_unlock(&instance->lock);
++ vc_vchi_cmd_delete(instance, cmd_blk);
++ return status;
++}
++
++int vc_sm_cma_vchi_free(struct sm_instance *handle, struct vc_sm_free_t *msg,
++ u32 *cur_trans_id)
++{
++ return vc_sm_cma_vchi_send_msg(handle, VC_SM_MSG_TYPE_FREE,
++ msg, sizeof(*msg), 0, 0, cur_trans_id, 0);
++}
++
++int vc_sm_cma_vchi_import(struct sm_instance *handle, struct vc_sm_import *msg,
++ struct vc_sm_import_result *result, u32 *cur_trans_id)
++{
++ return vc_sm_cma_vchi_send_msg(handle, VC_SM_MSG_TYPE_IMPORT,
++ msg, sizeof(*msg), result, sizeof(*result),
++ cur_trans_id, 1);
++}
++
++int vc_sm_cma_vchi_client_version(struct sm_instance *handle,
++ struct vc_sm_version *msg,
++ struct vc_sm_result_t *result,
++ u32 *cur_trans_id)
++{
++ return vc_sm_cma_vchi_send_msg(handle, VC_SM_MSG_TYPE_CLIENT_VERSION,
++ //msg, sizeof(*msg), result, sizeof(*result),
++ //cur_trans_id, 1);
++ msg, sizeof(*msg), NULL, 0,
++ cur_trans_id, 0);
++}
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
+@@ -0,0 +1,59 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++/*
++ * VideoCore Shared Memory CMA allocator
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ * Copyright 2011-2012 Broadcom Corporation. All rights reserved.
++ *
++ * Based on vmcs_sm driver from Broadcom Corporation.
++ *
++ */
++
++#ifndef __VC_SM_CMA_VCHI_H__INCLUDED__
++#define __VC_SM_CMA_VCHI_H__INCLUDED__
++
++#include "interface/vchi/vchi.h"
++
++#include "vc_sm_defs.h"
++
++/*
++ * Forward declare.
++ */
++struct sm_instance;
++
++typedef void (*vpu_event_cb)(struct sm_instance *instance,
++ struct vc_sm_result_t *reply, int reply_len);
++
++/*
++ * Initialize the shared memory service, opens up vchi connection to talk to it.
++ */
++struct sm_instance *vc_sm_cma_vchi_init(VCHI_INSTANCE_T vchi_instance,
++ unsigned int num_connections,
++ vpu_event_cb vpu_event);
++
++/*
++ * Terminates the shared memory service.
++ */
++int vc_sm_cma_vchi_stop(struct sm_instance **handle);
++
++/*
++ * Ask the shared memory service to free up some memory that was previously
++ * allocated by the vc_sm_cma_vchi_alloc function call.
++ */
++int vc_sm_cma_vchi_free(struct sm_instance *handle, struct vc_sm_free_t *msg,
++ u32 *cur_trans_id);
++
++/*
++ * Import a contiguous block of memory and wrap it in a GPU MEM_HANDLE_T.
++ */
++int vc_sm_cma_vchi_import(struct sm_instance *handle, struct vc_sm_import *msg,
++ struct vc_sm_import_result *result,
++ u32 *cur_trans_id);
++
++int vc_sm_cma_vchi_client_version(struct sm_instance *handle,
++ struct vc_sm_version *msg,
++ struct vc_sm_result_t *result,
++ u32 *cur_trans_id);
++
++#endif /* __VC_SM_CMA_VCHI_H__INCLUDED__ */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
+@@ -0,0 +1,298 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++/*
++ * VideoCore Shared Memory CMA allocator
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ *
++ * Based on vc_sm_defs.h from the vmcs_sm driver Copyright Broadcom Corporation.
++ * All IPC messages are copied across to this file, even if the vc-sm-cma
++ * driver is not currently using them.
++ *
++ ****************************************************************************
++ */
++
++#ifndef __VC_SM_DEFS_H__INCLUDED__
++#define __VC_SM_DEFS_H__INCLUDED__
++
++/* FourCC code used for VCHI connection */
++#define VC_SM_SERVER_NAME MAKE_FOURCC("SMEM")
++
++/* Maximum message length */
++#define VC_SM_MAX_MSG_LEN (sizeof(union vc_sm_msg_union_t) + \
++ sizeof(struct vc_sm_msg_hdr_t))
++#define VC_SM_MAX_RSP_LEN (sizeof(union vc_sm_msg_union_t))
++
++/* Resource name maximum size */
++#define VC_SM_RESOURCE_NAME 32
++
++/*
++ * Version to be reported to the VPU
++ * VPU assumes 0 (aka 1) which does not require the released callback, nor
++ * expect the client to handle VC_MEM_REQUESTS.
++ * Version 2 requires the released callback, and must support VC_MEM_REQUESTS.
++ */
++#define VC_SM_PROTOCOL_VERSION 2
++
++enum vc_sm_msg_type {
++ /* Message types supported for HOST->VC direction */
++
++ /* Allocate shared memory block */
++ VC_SM_MSG_TYPE_ALLOC,
++ /* Lock allocated shared memory block */
++ VC_SM_MSG_TYPE_LOCK,
++ /* Unlock allocated shared memory block */
++ VC_SM_MSG_TYPE_UNLOCK,
++ /* Unlock allocated shared memory block, do not answer command */
++ VC_SM_MSG_TYPE_UNLOCK_NOANS,
++ /* Free shared memory block */
++ VC_SM_MSG_TYPE_FREE,
++ /* Resize a shared memory block */
++ VC_SM_MSG_TYPE_RESIZE,
++ /* Walk the allocated shared memory block(s) */
++ VC_SM_MSG_TYPE_WALK_ALLOC,
++
++ /* A previously applied action will need to be reverted */
++ VC_SM_MSG_TYPE_ACTION_CLEAN,
++
++ /*
++ * Import a physical address and wrap into a MEM_HANDLE_T.
++ * Release with VC_SM_MSG_TYPE_FREE.
++ */
++ VC_SM_MSG_TYPE_IMPORT,
++ /*
++ *Tells VC the protocol version supported by this client.
++ * 2 supports the async/cmd messages from the VPU for final release
++ * of memory, and for VC allocations.
++ */
++ VC_SM_MSG_TYPE_CLIENT_VERSION,
++ /* Response to VC request for memory */
++ VC_SM_MSG_TYPE_VC_MEM_REQUEST_REPLY,
++
++ /*
++ * Asynchronous/cmd messages supported for VC->HOST direction.
++ * Signalled by setting the top bit in vc_sm_result_t trans_id.
++ */
++
++ /*
++ * VC has finished with an imported memory allocation.
++ * Release any Linux reference counts on the underlying block.
++ */
++ VC_SM_MSG_TYPE_RELEASED,
++ /* VC request for memory */
++ VC_SM_MSG_TYPE_VC_MEM_REQUEST,
++
++ VC_SM_MSG_TYPE_MAX
++};
++
++/* Type of memory to be allocated */
++enum vc_sm_alloc_type_t {
++ VC_SM_ALLOC_CACHED,
++ VC_SM_ALLOC_NON_CACHED,
++};
++
++/* Message header for all messages in HOST->VC direction */
++struct vc_sm_msg_hdr_t {
++ u32 type;
++ u32 trans_id;
++ u8 body[0];
++
++};
++
++/* Request to allocate memory (HOST->VC) */
++struct vc_sm_alloc_t {
++ /* type of memory to allocate */
++ enum vc_sm_alloc_type_t type;
++ /* byte amount of data to allocate per unit */
++ u32 base_unit;
++ /* number of unit to allocate */
++ u32 num_unit;
++ /* alignment to be applied on allocation */
++ u32 alignment;
++ /* identity of who allocated this block */
++ u32 allocator;
++ /* resource name (for easier tracking on vc side) */
++ char name[VC_SM_RESOURCE_NAME];
++
++};
++
++/* Result of a requested memory allocation (VC->HOST) */
++struct vc_sm_alloc_result_t {
++ /* Transaction identifier */
++ u32 trans_id;
++
++ /* Resource handle */
++ u32 res_handle;
++ /* Pointer to resource buffer */
++ u32 res_mem;
++ /* Resource base size (bytes) */
++ u32 res_base_size;
++ /* Resource number */
++ u32 res_num;
++
++};
++
++/* Request to free a previously allocated memory (HOST->VC) */
++struct vc_sm_free_t {
++ /* Resource handle (returned from alloc) */
++ u32 res_handle;
++ /* Resource buffer (returned from alloc) */
++ u32 res_mem;
++
++};
++
++/* Request to lock a previously allocated memory (HOST->VC) */
++struct vc_sm_lock_unlock_t {
++ /* Resource handle (returned from alloc) */
++ u32 res_handle;
++ /* Resource buffer (returned from alloc) */
++ u32 res_mem;
++
++};
++
++/* Request to resize a previously allocated memory (HOST->VC) */
++struct vc_sm_resize_t {
++ /* Resource handle (returned from alloc) */
++ u32 res_handle;
++ /* Resource buffer (returned from alloc) */
++ u32 res_mem;
++ /* Resource *new* size requested (bytes) */
++ u32 res_new_size;
++
++};
++
++/* Result of a requested memory lock (VC->HOST) */
++struct vc_sm_lock_result_t {
++ /* Transaction identifier */
++ u32 trans_id;
++
++ /* Resource handle */
++ u32 res_handle;
++ /* Pointer to resource buffer */
++ u32 res_mem;
++ /*
++ * Pointer to former resource buffer if the memory
++ * was reallocated
++ */
++ u32 res_old_mem;
++
++};
++
++/* Generic result for a request (VC->HOST) */
++struct vc_sm_result_t {
++ /* Transaction identifier */
++ u32 trans_id;
++
++ s32 success;
++
++};
++
++/* Request to revert a previously applied action (HOST->VC) */
++struct vc_sm_action_clean_t {
++ /* Action of interest */
++ enum vc_sm_msg_type res_action;
++ /* Transaction identifier for the action of interest */
++ u32 action_trans_id;
++
++};
++
++/* Request to remove all data associated with a given allocator (HOST->VC) */
++struct vc_sm_free_all_t {
++ /* Allocator identifier */
++ u32 allocator;
++};
++
++/* Request to import memory (HOST->VC) */
++struct vc_sm_import {
++ /* type of memory to allocate */
++ enum vc_sm_alloc_type_t type;
++ /* pointer to the VC (ie physical) address of the allocated memory */
++ u32 addr;
++ /* size of buffer */
++ u32 size;
++ /* opaque handle returned in RELEASED messages */
++ u32 kernel_id;
++ /* Allocator identifier */
++ u32 allocator;
++ /* resource name (for easier tracking on vc side) */
++ char name[VC_SM_RESOURCE_NAME];
++};
++
++/* Result of a requested memory import (VC->HOST) */
++struct vc_sm_import_result {
++ /* Transaction identifier */
++ u32 trans_id;
++
++ /* Resource handle */
++ u32 res_handle;
++};
++
++/* Notification that VC has finished with an allocation (VC->HOST) */
++struct vc_sm_released {
++ /* cmd type / trans_id */
++ u32 cmd;
++
++ /* pointer to the VC (ie physical) address of the allocated memory */
++ u32 addr;
++ /* size of buffer */
++ u32 size;
++ /* opaque handle returned in RELEASED messages */
++ u32 kernel_id;
++ u32 vc_handle;
++};
++
++/*
++ * Client informing VC as to the protocol version it supports.
++ * >=2 requires the released callback, and supports VC asking for memory.
++ * Failure means that the firmware doesn't support this call, and therefore the
++ * client should either fail, or NOT rely on getting the released callback.
++ */
++struct vc_sm_version {
++ u32 version;
++};
++
++/* Request FROM VideoCore for some memory */
++struct vc_sm_vc_mem_request {
++ /* cmd type */
++ u32 cmd;
++
++ /* trans_id (from VPU) */
++ u32 trans_id;
++ /* size of buffer */
++ u32 size;
++ /* alignment of buffer */
++ u32 align;
++ /* resource name (for easier tracking) */
++ char name[VC_SM_RESOURCE_NAME];
++};
++
++/* Response from the kernel to provide the VPU with some memory */
++struct vc_sm_vc_mem_request_result {
++ /* Transaction identifier for the VPU */
++ u32 trans_id;
++ /* pointer to the physical address of the allocated memory */
++ u32 addr;
++ /* opaque handle returned in RELEASED messages */
++ u32 kernel_id;
++};
++
++/* Union of ALL messages */
++union vc_sm_msg_union_t {
++ struct vc_sm_alloc_t alloc;
++ struct vc_sm_alloc_result_t alloc_result;
++ struct vc_sm_free_t free;
++ struct vc_sm_lock_unlock_t lock_unlock;
++ struct vc_sm_action_clean_t action_clean;
++ struct vc_sm_resize_t resize;
++ struct vc_sm_lock_result_t lock_result;
++ struct vc_sm_result_t result;
++ struct vc_sm_free_all_t free_all;
++ struct vc_sm_import import;
++ struct vc_sm_import_result import_result;
++ struct vc_sm_version version;
++ struct vc_sm_released released;
++ struct vc_sm_vc_mem_request vc_request;
++ struct vc_sm_vc_mem_request_result vc_request_result;
++};
++
++#endif /* __VC_SM_DEFS_H__INCLUDED__ */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
+@@ -0,0 +1,28 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++/*
++ * VideoCore Shared Memory CMA allocator
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ *
++ * Based on vc_sm_defs.h from the vmcs_sm driver Copyright Broadcom Corporation.
++ *
++ */
++
++#ifndef __VC_SM_KNL_H__INCLUDED__
++#define __VC_SM_KNL_H__INCLUDED__
++
++#if !defined(__KERNEL__)
++#error "This interface is for kernel use only..."
++#endif
++
++/* Free a previously allocated or imported shared memory handle and block. */
++int vc_sm_cma_free(int handle);
++
++/* Get an internal resource handle mapped from the external one. */
++int vc_sm_cma_int_handle(int handle);
++
++/* Import a block of memory into the GPU space. */
++int vc_sm_cma_import_dmabuf(struct dma_buf *dmabuf, int *handle);
++
++#endif /* __VC_SM_KNL_H__INCLUDED__ */
--- /dev/null
+From 0a36165c509c40a0551831efdbd2e957cba12f80 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 30 Oct 2018 11:42:48 +0000
+Subject: [PATCH 273/725] staging: vc-sm-cma: Fixup driver for older VCHI APIs
+
+Original patch was based off staging which included some cleanups
+of the VCHI APIs. Those aren't present here, so switch back to
+the older API.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 2 +-
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c | 5 +++++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -632,7 +632,7 @@ static void vc_sm_connected_init(void)
+ goto err_free_mem;
+ }
+
+- ret = vchi_connect(vchi_instance);
++ ret = vchi_connect(NULL, 0, vchi_instance);
+ if (ret) {
+ pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n",
+ __func__, ret);
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
+@@ -325,8 +325,13 @@ struct sm_instance *vc_sm_cma_vchi_init(
+ SERVICE_CREATION_T params = {
+ .version = VCHI_VERSION_EX(VC_SM_VER, VC_SM_MIN_VER),
+ .service_id = VC_SM_SERVER_NAME,
++ .rx_fifo_size = 0,
++ .tx_fifo_size = 0,
+ .callback = vc_sm_cma_vchi_callback,
+ .callback_param = instance,
++ .want_unaligned_bulk_rx = 0,
++ .want_unaligned_bulk_tx = 0,
++ .want_crc = 0
+ };
+
+ status = vchi_service_open(vchi_instance,
+++ /dev/null
-From 6a64ea8c2097cbe835fae209906a26c9a1896742 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Sep 2018 18:26:02 +0100
-Subject: [PATCH 273/703] staging: vc04_services: Support sending data to MMAL
- ports
-
-Add the ability to send data to ports. This only supports
-zero copy mode as the required bulk transfer setup calls
-are not done.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/vchiq-mmal/mmal-vchiq.c | 18 +++++++++++++-----
- 1 file changed, 13 insertions(+), 5 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -428,11 +428,19 @@ buffer_from_host(struct vchiq_mmal_insta
- m.u.buffer_from_host.buffer_header.data =
- (u32)(unsigned long)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;
-+ if (port->type == MMAL_PORT_TYPE_OUTPUT) {
-+ m.u.buffer_from_host.buffer_header.length = 0;
-+ m.u.buffer_from_host.buffer_header.offset = 0;
-+ m.u.buffer_from_host.buffer_header.flags = 0;
-+ m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN;
-+ m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN;
-+ } else {
-+ m.u.buffer_from_host.buffer_header.length = buf->length;
-+ m.u.buffer_from_host.buffer_header.offset = 0;
-+ m.u.buffer_from_host.buffer_header.flags = buf->mmal_flags;
-+ m.u.buffer_from_host.buffer_header.pts = buf->pts;
-+ m.u.buffer_from_host.buffer_header.dts = buf->dts;
-+ }
-
- /* clear buffer type sepecific data */
- memset(&m.u.buffer_from_host.buffer_header_type_specific, 0,
+++ /dev/null
-From e84380e8791d0a7a6cc4057269f2a2885a4ae8c1 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 25 Sep 2018 16:57:40 +0100
-Subject: [PATCH 274/703] staging: vc04_services: Fixup vchiq-mmal include
- ordering
-
-There were dependencies on including the headers in the correct
-order. Fix up the headers so that they include the other
-headers that they depend on themselves.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h | 1 +
- drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h | 1 +
- 2 files changed, 2 insertions(+)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
-@@ -38,6 +38,7 @@
- #include "mmal-msg-common.h"
- #include "mmal-msg-format.h"
- #include "mmal-msg-port.h"
-+#include "mmal-vchiq.h"
-
- enum mmal_msg_type {
- MMAL_MSG_TYPE_QUIT = 1,
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -16,6 +16,7 @@
- #ifndef MMAL_VCHIQ_H
- #define MMAL_VCHIQ_H
-
-+#include "mmal-common.h"
- #include "mmal-msg-format.h"
-
- #define MAX_PORT_COUNT 4
--- /dev/null
+From b821e47df883a3325062a68cbe1504bf62129fd6 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 25 Sep 2018 16:07:55 +0100
+Subject: [PATCH 274/725] staging: vc04_services: Use vc-sm-cma to support zero
+ copy
+
+With the vc-sm-cma driver we can support zero copy of buffers between
+the kernel and VPU. Add this support to vchiq-mmal.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vchiq-mmal/Kconfig | 1 +
+ .../vc04_services/vchiq-mmal/mmal-common.h | 4 ++
+ .../vc04_services/vchiq-mmal/mmal-vchiq.c | 66 ++++++++++++++++++-
+ .../vc04_services/vchiq-mmal/mmal-vchiq.h | 1 +
+ 4 files changed, 70 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/Kconfig
++++ b/drivers/staging/vc04_services/vchiq-mmal/Kconfig
+@@ -2,6 +2,7 @@ config BCM2835_VCHIQ_MMAL
+ tristate "BCM2835 MMAL VCHIQ service"
+ depends on (ARCH_BCM2835 || COMPILE_TEST)
+ select BCM2835_VCHIQ
++ select BCM_VC_SM_CMA
+ help
+ Enables the MMAL API over VCHIQ as used for the
+ majority of the multimedia services on VideoCore.
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
+@@ -51,6 +51,10 @@ struct mmal_buffer {
+
+ struct mmal_msg_context *msg_context;
+
++ struct dma_buf *dma_buf;/* Exported dmabuf fd from videobuf2 */
++ int vcsm_handle; /* VCSM handle having imported the dmabuf */
++ u32 vc_handle; /* VC handle to that dmabuf */
++
+ u32 cmd; /* MMAL command. 0=data. */
+ unsigned long length;
+ u32 mmal_flags;
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -27,9 +27,12 @@
+ #include <media/videobuf2-vmalloc.h>
+
+ #include "mmal-common.h"
++#include "mmal-parameters.h"
+ #include "mmal-vchiq.h"
+ #include "mmal-msg.h"
+
++#include "vc-sm-cma/vc_sm_knl.h"
++
+ #define USE_VCHIQ_ARM
+ #include "interface/vchi/vchi.h"
+
+@@ -425,8 +428,13 @@ buffer_from_host(struct vchiq_mmal_insta
+
+ /* buffer header */
+ m.u.buffer_from_host.buffer_header.cmd = 0;
+- m.u.buffer_from_host.buffer_header.data =
+- (u32)(unsigned long)buf->buffer;
++ if (port->zero_copy) {
++ m.u.buffer_from_host.buffer_header.data = buf->vc_handle;
++ } else {
++ m.u.buffer_from_host.buffer_header.data =
++ (u32)(unsigned long)buf->buffer;
++ }
++
+ m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
+ if (port->type == MMAL_PORT_TYPE_OUTPUT) {
+ m.u.buffer_from_host.buffer_header.length = 0;
+@@ -591,6 +599,22 @@ static void buffer_to_host_cb(struct vch
+
+ msg_context->u.bulk.status = msg->h.status;
+
++ } else if (msg->u.buffer_from_host.is_zero_copy) {
++ /*
++ * Zero copy buffer, so nothing to do.
++ * Copy buffer info and make callback.
++ */
++ msg_context->u.bulk.buffer_used =
++ msg->u.buffer_from_host.buffer_header.length;
++ 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;
++ msg_context->u.bulk.cmd =
++ msg->u.buffer_from_host.buffer_header.cmd;
++
+ } else if (msg->u.buffer_from_host.buffer_header.length == 0) {
+ /* empty buffer */
+ if (msg->u.buffer_from_host.buffer_header.flags &
+@@ -1538,6 +1562,9 @@ int vchiq_mmal_port_parameter_set(struct
+
+ mutex_unlock(&instance->vchiq_mutex);
+
++ if (parameter == MMAL_PARAMETER_ZERO_COPY && !ret)
++ port->zero_copy = !!(*(bool *)value);
++
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set);
+@@ -1706,6 +1733,31 @@ int vchiq_mmal_submit_buffer(struct vchi
+ unsigned long flags = 0;
+ int ret;
+
++ /*
++ * We really want to do this in mmal_vchi_buffer_init but can't as
++ * videobuf2 won't let us have the dmabuf there.
++ */
++ if (port->zero_copy && buffer->dma_buf && !buffer->vcsm_handle) {
++ pr_debug("%s: import dmabuf %p\n", __func__, buffer->dma_buf);
++ ret = vc_sm_cma_import_dmabuf(buffer->dma_buf,
++ &buffer->vcsm_handle);
++ if (ret) {
++ pr_err("%s: vc_sm_import_dmabuf_fd failed, ret %d\n",
++ __func__, ret);
++ return ret;
++ }
++
++ buffer->vc_handle = vc_sm_cma_int_handle(buffer->vcsm_handle);
++ if (!buffer->vc_handle) {
++ pr_err("%s: vc_sm_int_handle failed %d\n",
++ __func__, ret);
++ vc_sm_cma_free(buffer->vcsm_handle);
++ return ret;
++ }
++ pr_debug("%s: import dmabuf %p - got vc handle %08X\n",
++ __func__, buffer->dma_buf, buffer->vc_handle);
++ }
++
+ ret = buffer_from_host(instance, port, buffer);
+ if (ret == -EINVAL) {
+ /* Port is disabled. Queue for when it is enabled. */
+@@ -1739,6 +1791,16 @@ int mmal_vchi_buffer_cleanup(struct mmal
+ release_msg_context(msg_context);
+ buf->msg_context = NULL;
+
++ if (buf->vcsm_handle) {
++ int ret;
++
++ pr_debug("%s: vc_sm_cma_free on handle %08X\n", __func__,
++ buf->vcsm_handle);
++ ret = vc_sm_cma_free(buf->vcsm_handle);
++ if (ret)
++ pr_err("%s: vcsm_free failed, ret %d\n", __func__, ret);
++ buf->vcsm_handle = 0;
++ }
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -49,6 +49,7 @@ typedef void (*vchiq_mmal_buffer_cb)(
+
+ struct vchiq_mmal_port {
+ u32 enabled:1;
++ u32 zero_copy:1;
+ u32 handle;
+ u32 type; /* port type, cached to use on port info set */
+ u32 index; /* port index, cached to use on port info set */
--- /dev/null
+From 46f9f09f99867b8211974aa2426bd68fe5ddb2d6 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Oct 2018 17:57:45 +0000
+Subject: [PATCH 275/725] media: videobuf2: Allow exporting of a struct dmabuf
+
+videobuf2 only allowed exporting a dmabuf as a file descriptor,
+but there are instances where having the struct dma_buf is
+useful within the kernel.
+
+Split the current implementation into two, one step which
+exports a struct dma_buf, and the second which converts that
+into an fd.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../media/common/videobuf2/videobuf2-core.c | 21 ++++++++++++++++---
+ include/media/videobuf2-core.h | 15 +++++++++++++
+ 2 files changed, 33 insertions(+), 3 deletions(-)
+
+--- a/drivers/media/common/videobuf2/videobuf2-core.c
++++ b/drivers/media/common/videobuf2/videobuf2-core.c
+@@ -1851,12 +1851,12 @@ static int __find_plane_by_offset(struct
+ return -EINVAL;
+ }
+
+-int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
+- unsigned int index, unsigned int plane, unsigned int flags)
++int vb2_core_expbuf_dmabuf(struct vb2_queue *q, unsigned int type,
++ unsigned int index, unsigned int plane,
++ unsigned int flags, struct dma_buf **dmabuf)
+ {
+ struct vb2_buffer *vb = NULL;
+ struct vb2_plane *vb_plane;
+- int ret;
+ struct dma_buf *dbuf;
+
+ if (q->memory != VB2_MEMORY_MMAP) {
+@@ -1906,6 +1906,21 @@ int vb2_core_expbuf(struct vb2_queue *q,
+ return -EINVAL;
+ }
+
++ *dmabuf = dbuf;
++ return 0;
++}
++EXPORT_SYMBOL_GPL(vb2_core_expbuf_dmabuf);
++
++int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
++ unsigned int index, unsigned int plane, unsigned int flags)
++{
++ struct dma_buf *dbuf;
++ int ret;
++
++ ret = vb2_core_expbuf_dmabuf(q, type, index, plane, flags, &dbuf);
++ if (ret)
++ return ret;
++
+ ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE);
+ if (ret < 0) {
+ dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
+--- a/include/media/videobuf2-core.h
++++ b/include/media/videobuf2-core.h
+@@ -825,6 +825,21 @@ int vb2_core_streamon(struct vb2_queue *
+ int vb2_core_streamoff(struct vb2_queue *q, unsigned int type);
+
+ /**
++ * vb2_core_expbuf_dmabuf() - Export a buffer as a dma_buf structure
++ * @q: videobuf2 queue
++ * @type: buffer type
++ * @index: id number of the buffer
++ * @plane: index of the plane to be exported, 0 for single plane queues
++ * @flags: flags for newly created file, currently only O_CLOEXEC is
++ * supported, refer to manual of open syscall for more details
++ * @dmabuf: Returns the dmabuf pointer
++ *
++ */
++int vb2_core_expbuf_dmabuf(struct vb2_queue *q, unsigned int type,
++ unsigned int index, unsigned int plane,
++ unsigned int flags, struct dma_buf **dmabuf);
++
++/**
+ * vb2_core_expbuf() - Export a buffer as a file descriptor.
+ * @q: pointer to &struct vb2_queue with videobuf2 queue.
+ * @fd: pointer to the file descriptor associated with DMABUF
+++ /dev/null
-From b9607d33b3efa9a85268961cadc6df5b5c9b042b Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 25 Sep 2018 10:27:11 +0100
-Subject: [PATCH 275/703] staging: vc04_services: Add new vc-sm-cma driver
-
-This new driver allows contiguous memory blocks to be imported
-into the VideoCore VPU memory map, and manages the lifetime of
-those objects, only releasing the source dmabuf once the VPU has
-confirmed it has finished with it.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/Kconfig | 1 +
- drivers/staging/vc04_services/Makefile | 1 +
- .../staging/vc04_services/vc-sm-cma/Kconfig | 10 +
- .../staging/vc04_services/vc-sm-cma/Makefile | 8 +
- drivers/staging/vc04_services/vc-sm-cma/TODO | 2 +
- .../staging/vc04_services/vc-sm-cma/vc_sm.c | 838 ++++++++++++++++++
- .../staging/vc04_services/vc-sm-cma/vc_sm.h | 59 ++
- .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c | 498 +++++++++++
- .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.h | 59 ++
- .../vc04_services/vc-sm-cma/vc_sm_defs.h | 298 +++++++
- .../vc04_services/vc-sm-cma/vc_sm_knl.h | 28 +
- 11 files changed, 1802 insertions(+)
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/Kconfig
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/Makefile
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/TODO
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
-
---- a/drivers/staging/vc04_services/Kconfig
-+++ b/drivers/staging/vc04_services/Kconfig
-@@ -22,6 +22,7 @@ source "drivers/staging/vc04_services/bc
-
- source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
- source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
-+source "drivers/staging/vc04_services/vc-sm-cma/Kconfig"
-
- endif
-
---- a/drivers/staging/vc04_services/Makefile
-+++ b/drivers/staging/vc04_services/Makefile
-@@ -13,6 +13,7 @@ vchiq-objs := \
- obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/
- obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/
- obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
-+obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma/
-
- ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000
-
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/Kconfig
-@@ -0,0 +1,10 @@
-+config BCM_VC_SM_CMA
-+ tristate "VideoCore Shared Memory (CMA) driver"
-+ depends on BCM2835_VCHIQ
-+ select RBTREE
-+ select DMA_SHARED_BUFFER
-+ help
-+ Say Y here to enable the shared memory interface that
-+ supports sharing dmabufs with VideoCore.
-+ This operates over the VCHIQ interface to a service
-+ running on VideoCore.
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/Makefile
-@@ -0,0 +1,8 @@
-+ccflags-y += -Idrivers/staging/vc04_services -Idrivers/staging/vc04_services/interface/vchi -Idrivers/staging/vc04_services/interface/vchiq_arm
-+# -I"drivers/staging/android/ion/" -I"$(srctree)/fs/"
-+ccflags-y += -D__VCCOREVER__=0
-+
-+vc-sm-cma-$(CONFIG_BCM_VC_SM_CMA) := \
-+ vc_sm.o vc_sm_cma_vchi.o
-+
-+obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma.o
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/TODO
-@@ -0,0 +1,2 @@
-+1) Convert to a platform driver.
-+
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -0,0 +1,838 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * VideoCore Shared Memory driver using CMA.
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ * Dave Stevenson <dave.stevenson@raspberrypi.org>
-+ *
-+ * Based on vmcs_sm driver from Broadcom Corporation for some API,
-+ * and taking some code for CMA/dmabuf handling from the Android Ion
-+ * driver (Google/Linaro).
-+ *
-+ * This is cut down version to only support import of dma_bufs from
-+ * other kernel drivers. A more complete implementation of the old
-+ * vmcs_sm functionality can follow later.
-+ *
-+ */
-+
-+/* ---- Include Files ----------------------------------------------------- */
-+#include <linux/cdev.h>
-+#include <linux/device.h>
-+#include <linux/debugfs.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/dma-buf.h>
-+#include <linux/errno.h>
-+#include <linux/fs.h>
-+#include <linux/kernel.h>
-+#include <linux/list.h>
-+#include <linux/miscdevice.h>
-+#include <linux/module.h>
-+#include <linux/mm.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_device.h>
-+#include <linux/proc_fs.h>
-+#include <linux/slab.h>
-+#include <linux/seq_file.h>
-+#include <linux/syscalls.h>
-+#include <linux/types.h>
-+
-+#include "vchiq_connected.h"
-+#include "vc_sm_cma_vchi.h"
-+
-+#include "vc_sm.h"
-+#include "vc_sm_knl.h"
-+
-+/* ---- Private Constants and Types --------------------------------------- */
-+
-+#define DEVICE_NAME "vcsm-cma"
-+#define DEVICE_MINOR 0
-+
-+#define VC_SM_RESOURCE_NAME_DEFAULT "sm-host-resource"
-+
-+#define VC_SM_DIR_ROOT_NAME "vcsm-cma"
-+#define VC_SM_STATE "state"
-+
-+/* Private file data associated with each opened device. */
-+struct vc_sm_privdata_t {
-+ pid_t pid; /* PID of creator. */
-+
-+ int restart_sys; /* Tracks restart on interrupt. */
-+ enum vc_sm_msg_type int_action; /* Interrupted action. */
-+ u32 int_trans_id; /* Interrupted transaction. */
-+};
-+
-+typedef int (*VC_SM_SHOW) (struct seq_file *s, void *v);
-+struct sm_pde_t {
-+ VC_SM_SHOW show; /* Debug fs function hookup. */
-+ struct dentry *dir_entry; /* Debug fs directory entry. */
-+ void *priv_data; /* Private data */
-+};
-+
-+/* Global state information. */
-+struct sm_state_t {
-+ struct platform_device *pdev;
-+
-+ struct miscdevice dev;
-+ struct sm_instance *sm_handle; /* Handle for videocore service. */
-+
-+ struct mutex map_lock; /* Global map lock. */
-+ struct list_head buffer_list; /* List of buffer. */
-+
-+ struct vc_sm_privdata_t *data_knl; /* Kernel internal data tracking. */
-+ struct dentry *dir_root; /* Debug fs entries root. */
-+ struct sm_pde_t dir_state; /* Debug fs entries state sub-tree. */
-+
-+ bool require_released_callback; /* VPU will send a released msg when it
-+ * has finished with a resource.
-+ */
-+ u32 int_trans_id; /* Interrupted transaction. */
-+};
-+
-+/* ---- Private Variables ----------------------------------------------- */
-+
-+static struct sm_state_t *sm_state;
-+static int sm_inited;
-+
-+/* ---- Private Function Prototypes -------------------------------------- */
-+
-+/* ---- Private Functions ------------------------------------------------ */
-+
-+static int vc_sm_cma_seq_file_show(struct seq_file *s, void *v)
-+{
-+ struct sm_pde_t *sm_pde;
-+
-+ sm_pde = (struct sm_pde_t *)(s->private);
-+
-+ if (sm_pde && sm_pde->show)
-+ sm_pde->show(s, v);
-+
-+ return 0;
-+}
-+
-+static int vc_sm_cma_single_open(struct inode *inode, struct file *file)
-+{
-+ return single_open(file, vc_sm_cma_seq_file_show, inode->i_private);
-+}
-+
-+static const struct file_operations vc_sm_cma_debug_fs_fops = {
-+ .open = vc_sm_cma_single_open,
-+ .read = seq_read,
-+ .llseek = seq_lseek,
-+ .release = single_release,
-+};
-+
-+static int vc_sm_cma_global_state_show(struct seq_file *s, void *v)
-+{
-+ struct vc_sm_buffer *resource = NULL;
-+ int resource_count = 0;
-+
-+ if (!sm_state)
-+ return 0;
-+
-+ seq_printf(s, "\nVC-ServiceHandle 0x%x\n",
-+ (unsigned int)sm_state->sm_handle);
-+
-+ /* Log all applicable mapping(s). */
-+
-+ mutex_lock(&sm_state->map_lock);
-+ seq_puts(s, "\nResources\n");
-+ if (!list_empty(&sm_state->buffer_list)) {
-+ list_for_each_entry(resource, &sm_state->buffer_list,
-+ global_buffer_list) {
-+ resource_count++;
-+
-+ seq_printf(s, "\nResource %p\n",
-+ resource);
-+ seq_printf(s, " NAME %s\n",
-+ resource->name);
-+ seq_printf(s, " SIZE %d\n",
-+ resource->size);
-+ seq_printf(s, " DMABUF %p\n",
-+ resource->dma_buf);
-+ seq_printf(s, " ATTACH %p\n",
-+ resource->attach);
-+ seq_printf(s, " SG_TABLE %p\n",
-+ resource->sg_table);
-+ seq_printf(s, " SGT %p\n",
-+ resource->sgt);
-+ seq_printf(s, " DMA_ADDR %pad\n",
-+ &resource->dma_addr);
-+ seq_printf(s, " VC_HANDLE %08x\n",
-+ resource->vc_handle);
-+ seq_printf(s, " VC_MAPPING %d\n",
-+ resource->vpu_state);
-+ }
-+ }
-+ seq_printf(s, "\n\nTotal resource count: %d\n\n", resource_count);
-+
-+ mutex_unlock(&sm_state->map_lock);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Adds a buffer to the private data list which tracks all the allocated
-+ * data.
-+ */
-+static void vc_sm_add_resource(struct vc_sm_privdata_t *privdata,
-+ struct vc_sm_buffer *buffer)
-+{
-+ mutex_lock(&sm_state->map_lock);
-+ list_add(&buffer->global_buffer_list, &sm_state->buffer_list);
-+ mutex_unlock(&sm_state->map_lock);
-+
-+ pr_debug("[%s]: added buffer %p (name %s, size %d)\n",
-+ __func__, buffer, buffer->name, buffer->size);
-+}
-+
-+/*
-+ * Release an allocation.
-+ * All refcounting is done via the dma buf object.
-+ */
-+static void vc_sm_release_resource(struct vc_sm_buffer *buffer, int force)
-+{
-+ mutex_lock(&sm_state->map_lock);
-+ mutex_lock(&buffer->lock);
-+
-+ pr_debug("[%s]: buffer %p (name %s, size %d)\n",
-+ __func__, buffer, buffer->name, buffer->size);
-+
-+ if (buffer->vc_handle && buffer->vpu_state == VPU_MAPPED) {
-+ struct vc_sm_free_t free = { buffer->vc_handle, 0 };
-+ int status = vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
-+ &sm_state->int_trans_id);
-+ if (status != 0 && status != -EINTR) {
-+ pr_err("[%s]: failed to free memory on videocore (status: %u, trans_id: %u)\n",
-+ __func__, status, sm_state->int_trans_id);
-+ }
-+
-+ if (sm_state->require_released_callback) {
-+ /* Need to wait for the VPU to confirm the free */
-+
-+ /* Retain a reference on this until the VPU has
-+ * released it
-+ */
-+ buffer->vpu_state = VPU_UNMAPPING;
-+ goto defer;
-+ }
-+ buffer->vpu_state = VPU_NOT_MAPPED;
-+ buffer->vc_handle = 0;
-+ }
-+ if (buffer->vc_handle) {
-+ /* We've sent the unmap request but not had the response. */
-+ pr_err("[%s]: Waiting for VPU unmap response on %p\n",
-+ __func__, buffer);
-+ goto defer;
-+ }
-+ if (buffer->in_use) {
-+ /* Don't release dmabuf here - we await the release */
-+ pr_err("[%s]: buffer %p is still in use\n",
-+ __func__, buffer);
-+ goto defer;
-+ }
-+
-+ /* Handle cleaning up imported dmabufs */
-+ if (buffer->sgt) {
-+ dma_buf_unmap_attachment(buffer->attach, buffer->sgt,
-+ DMA_BIDIRECTIONAL);
-+ buffer->sgt = NULL;
-+ }
-+ if (buffer->attach) {
-+ dma_buf_detach(buffer->dma_buf, buffer->attach);
-+ buffer->attach = NULL;
-+ }
-+
-+ /* Release the dma_buf (whether ours or imported) */
-+ if (buffer->import_dma_buf) {
-+ dma_buf_put(buffer->import_dma_buf);
-+ buffer->import_dma_buf = NULL;
-+ buffer->dma_buf = NULL;
-+ } else if (buffer->dma_buf) {
-+ dma_buf_put(buffer->dma_buf);
-+ buffer->dma_buf = NULL;
-+ }
-+
-+ if (buffer->sg_table && !buffer->import_dma_buf) {
-+ /* Our own allocation that we need to dma_unmap_sg */
-+ dma_unmap_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
-+ buffer->sg_table->nents, DMA_BIDIRECTIONAL);
-+ }
-+
-+ /* Free the local resource. Start by removing it from the list */
-+ buffer->private = NULL;
-+ list_del(&buffer->global_buffer_list);
-+
-+ mutex_unlock(&buffer->lock);
-+ mutex_unlock(&sm_state->map_lock);
-+
-+ mutex_destroy(&buffer->lock);
-+
-+ kfree(buffer);
-+ return;
-+
-+defer:
-+ mutex_unlock(&buffer->lock);
-+ mutex_unlock(&sm_state->map_lock);
-+}
-+
-+/* Create support for private data tracking. */
-+static struct vc_sm_privdata_t *vc_sm_cma_create_priv_data(pid_t id)
-+{
-+ char alloc_name[32];
-+ struct vc_sm_privdata_t *file_data = NULL;
-+
-+ /* Allocate private structure. */
-+ file_data = kzalloc(sizeof(*file_data), GFP_KERNEL);
-+
-+ if (!file_data)
-+ return NULL;
-+
-+ snprintf(alloc_name, sizeof(alloc_name), "%d", id);
-+
-+ file_data->pid = id;
-+
-+ return file_data;
-+}
-+
-+/* Dma_buf operations for chaining through to an imported dma_buf */
-+static
-+int vc_sm_import_dma_buf_attach(struct dma_buf *dmabuf,
-+ struct dma_buf_attachment *attachment)
-+{
-+ struct vc_sm_buffer *res = dmabuf->priv;
-+
-+ if (!res->import_dma_buf)
-+ return -EINVAL;
-+ return res->import_dma_buf->ops->attach(res->import_dma_buf,
-+ attachment);
-+}
-+
-+static
-+void vc_sm_import_dma_buf_detatch(struct dma_buf *dmabuf,
-+ struct dma_buf_attachment *attachment)
-+{
-+ struct vc_sm_buffer *res = dmabuf->priv;
-+
-+ if (!res->import_dma_buf)
-+ return;
-+ res->import_dma_buf->ops->detach(res->import_dma_buf, attachment);
-+}
-+
-+static
-+struct sg_table *vc_sm_import_map_dma_buf(struct dma_buf_attachment *attachment,
-+ enum dma_data_direction direction)
-+{
-+ struct vc_sm_buffer *res = attachment->dmabuf->priv;
-+
-+ if (!res->import_dma_buf)
-+ return NULL;
-+ return res->import_dma_buf->ops->map_dma_buf(attachment, direction);
-+}
-+
-+static
-+void vc_sm_import_unmap_dma_buf(struct dma_buf_attachment *attachment,
-+ struct sg_table *table,
-+ enum dma_data_direction direction)
-+{
-+ struct vc_sm_buffer *res = attachment->dmabuf->priv;
-+
-+ if (!res->import_dma_buf)
-+ return;
-+ res->import_dma_buf->ops->unmap_dma_buf(attachment, table, direction);
-+}
-+
-+static
-+int vc_sm_import_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
-+{
-+ struct vc_sm_buffer *res = dmabuf->priv;
-+
-+ pr_debug("%s: mmap dma_buf %p, res %p, imported db %p\n", __func__,
-+ dmabuf, res, res->import_dma_buf);
-+ if (!res->import_dma_buf) {
-+ pr_err("%s: mmap dma_buf %p- not an imported buffer\n",
-+ __func__, dmabuf);
-+ return -EINVAL;
-+ }
-+ return res->import_dma_buf->ops->mmap(res->import_dma_buf, vma);
-+}
-+
-+static
-+void vc_sm_import_dma_buf_release(struct dma_buf *dmabuf)
-+{
-+ struct vc_sm_buffer *res = dmabuf->priv;
-+
-+ pr_debug("%s: Relasing dma_buf %p\n", __func__, dmabuf);
-+ if (!res->import_dma_buf)
-+ return;
-+
-+ res->in_use = 0;
-+
-+ vc_sm_release_resource(res, 0);
-+}
-+
-+static
-+void *vc_sm_import_dma_buf_kmap(struct dma_buf *dmabuf,
-+ unsigned long offset)
-+{
-+ struct vc_sm_buffer *res = dmabuf->priv;
-+
-+ if (!res->import_dma_buf)
-+ return NULL;
-+ return res->import_dma_buf->ops->map(res->import_dma_buf,
-+ offset);
-+}
-+
-+static
-+void vc_sm_import_dma_buf_kunmap(struct dma_buf *dmabuf,
-+ unsigned long offset, void *ptr)
-+{
-+ struct vc_sm_buffer *res = dmabuf->priv;
-+
-+ if (!res->import_dma_buf)
-+ return;
-+ res->import_dma_buf->ops->unmap(res->import_dma_buf,
-+ offset, ptr);
-+}
-+
-+static
-+int vc_sm_import_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
-+ enum dma_data_direction direction)
-+{
-+ struct vc_sm_buffer *res = dmabuf->priv;
-+
-+ if (!res->import_dma_buf)
-+ return -EINVAL;
-+ return res->import_dma_buf->ops->begin_cpu_access(res->import_dma_buf,
-+ direction);
-+}
-+
-+static
-+int vc_sm_import_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
-+ enum dma_data_direction direction)
-+{
-+ struct vc_sm_buffer *res = dmabuf->priv;
-+
-+ if (!res->import_dma_buf)
-+ return -EINVAL;
-+ return res->import_dma_buf->ops->end_cpu_access(res->import_dma_buf,
-+ direction);
-+}
-+
-+static const struct dma_buf_ops dma_buf_import_ops = {
-+ .map_dma_buf = vc_sm_import_map_dma_buf,
-+ .unmap_dma_buf = vc_sm_import_unmap_dma_buf,
-+ .mmap = vc_sm_import_dmabuf_mmap,
-+ .release = vc_sm_import_dma_buf_release,
-+ .attach = vc_sm_import_dma_buf_attach,
-+ .detach = vc_sm_import_dma_buf_detatch,
-+ .begin_cpu_access = vc_sm_import_dma_buf_begin_cpu_access,
-+ .end_cpu_access = vc_sm_import_dma_buf_end_cpu_access,
-+ .map = vc_sm_import_dma_buf_kmap,
-+ .unmap = vc_sm_import_dma_buf_kunmap,
-+};
-+
-+/* Import a dma_buf to be shared with VC. */
-+int
-+vc_sm_cma_import_dmabuf_internal(struct vc_sm_privdata_t *private,
-+ struct dma_buf *dma_buf,
-+ struct dma_buf **imported_buf)
-+{
-+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-+ struct vc_sm_buffer *buffer = NULL;
-+ struct vc_sm_import import = { };
-+ struct vc_sm_import_result result = { };
-+ struct dma_buf_attachment *attach = NULL;
-+ struct sg_table *sgt = NULL;
-+ int ret = 0;
-+ int status;
-+
-+ /* Setup our allocation parameters */
-+ pr_debug("%s: importing dma_buf %p\n", __func__, dma_buf);
-+
-+ get_dma_buf(dma_buf);
-+ dma_buf = dma_buf;
-+
-+ attach = dma_buf_attach(dma_buf, &sm_state->pdev->dev);
-+ if (IS_ERR(attach)) {
-+ ret = PTR_ERR(attach);
-+ goto error;
-+ }
-+
-+ sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
-+ if (IS_ERR(sgt)) {
-+ ret = PTR_ERR(sgt);
-+ goto error;
-+ }
-+
-+ /* Verify that the address block is contiguous */
-+ if (sgt->nents != 1) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ /* Allocate local buffer to track this allocation. */
-+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
-+ if (!buffer) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ import.type = VC_SM_ALLOC_NON_CACHED;
-+ import.addr = (uint32_t)sg_dma_address(sgt->sgl);
-+ if ((import.addr & 0xC0000000) != 0xC0000000) {
-+ pr_err("%s: Expecting an uncached alias for dma_addr %08x\n",
-+ __func__, import.addr);
-+ import.addr |= 0xC0000000;
-+ }
-+ import.size = sg_dma_len(sgt->sgl);
-+ import.allocator = current->tgid;
-+ import.kernel_id = (uint32_t)buffer; //FIXME: 64 bit support needed.
-+
-+ memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
-+ sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
-+
-+ pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %p, size %u\n",
-+ __func__, import.name, import.type, (void *)import.addr,
-+ import.size);
-+
-+ /* Allocate the videocore buffer. */
-+ status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
-+ &sm_state->int_trans_id);
-+ if (status == -EINTR) {
-+ pr_debug("[%s]: requesting import memory action restart (trans_id: %u)\n",
-+ __func__, sm_state->int_trans_id);
-+ ret = -ERESTARTSYS;
-+ private->restart_sys = -EINTR;
-+ private->int_action = VC_SM_MSG_TYPE_IMPORT;
-+ goto error;
-+ } else if (status || !result.res_handle) {
-+ pr_debug("[%s]: failed to import memory on videocore (status: %u, trans_id: %u)\n",
-+ __func__, status, sm_state->int_trans_id);
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ mutex_init(&buffer->lock);
-+ INIT_LIST_HEAD(&buffer->attachments);
-+ memcpy(buffer->name, import.name,
-+ min(sizeof(buffer->name), sizeof(import.name) - 1));
-+
-+ /* Keep track of the buffer we created. */
-+ buffer->private = private;
-+ buffer->vc_handle = result.res_handle;
-+ buffer->size = import.size;
-+ buffer->vpu_state = VPU_MAPPED;
-+
-+ buffer->import_dma_buf = dma_buf;
-+
-+ buffer->attach = attach;
-+ buffer->sgt = sgt;
-+ buffer->dma_addr = sg_dma_address(sgt->sgl);
-+ buffer->in_use = 1;
-+
-+ /*
-+ * We're done - we need to export a new dmabuf chaining through most
-+ * functions, but enabling us to release our own internal references
-+ * here.
-+ */
-+ exp_info.ops = &dma_buf_import_ops;
-+ exp_info.size = import.size;
-+ exp_info.flags = O_RDWR;
-+ exp_info.priv = buffer;
-+
-+ buffer->dma_buf = dma_buf_export(&exp_info);
-+ if (IS_ERR(buffer->dma_buf)) {
-+ ret = PTR_ERR(buffer->dma_buf);
-+ goto error;
-+ }
-+
-+ vc_sm_add_resource(private, buffer);
-+
-+ *imported_buf = buffer->dma_buf;
-+
-+ return 0;
-+
-+error:
-+ if (result.res_handle) {
-+ struct vc_sm_free_t free = { result.res_handle, 0 };
-+
-+ vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
-+ &sm_state->int_trans_id);
-+ }
-+ kfree(buffer);
-+ if (sgt)
-+ dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
-+ if (attach)
-+ dma_buf_detach(dma_buf, attach);
-+ dma_buf_put(dma_buf);
-+ return ret;
-+}
-+
-+/* FIXME: Pass a function pointer to this into vc_vchi_sm.c */
-+void
-+vc_sm_vpu_event(struct sm_instance *instance, struct vc_sm_result_t *reply,
-+ int reply_len)
-+{
-+ switch (reply->trans_id & ~0x80000000) {
-+ case VC_SM_MSG_TYPE_CLIENT_VERSION:
-+ {
-+ /* Acknowledge that the firmware supports the version command */
-+ pr_debug("%s: firmware acked version msg. Require release cb\n",
-+ __func__);
-+ sm_state->require_released_callback = true;
-+ }
-+ break;
-+ case VC_SM_MSG_TYPE_RELEASED:
-+ {
-+ struct vc_sm_released *release = (struct vc_sm_released *)reply;
-+ struct vc_sm_buffer *buffer =
-+ (struct vc_sm_buffer *)release->kernel_id;
-+
-+ /*
-+ * FIXME: Need to check buffer is still valid and allocated
-+ * before continuing
-+ */
-+ pr_debug("%s: Released addr %08x, size %u, id %08x, mem_handle %08x\n",
-+ __func__, release->addr, release->size,
-+ release->kernel_id, release->vc_handle);
-+ mutex_lock(&buffer->lock);
-+ buffer->vc_handle = 0;
-+ buffer->vpu_state = VPU_NOT_MAPPED;
-+ mutex_unlock(&buffer->lock);
-+
-+ vc_sm_release_resource(buffer, 0);
-+ }
-+ break;
-+ default:
-+ pr_err("%s: Unknown vpu cmd %x\n", __func__, reply->trans_id);
-+ break;
-+ }
-+}
-+
-+/* Videocore connected. */
-+static void vc_sm_connected_init(void)
-+{
-+ int ret;
-+ VCHI_INSTANCE_T vchi_instance;
-+ struct vc_sm_version version;
-+ struct vc_sm_result_t version_result;
-+
-+ pr_info("[%s]: start\n", __func__);
-+
-+ /*
-+ * Initialize and create a VCHI connection for the shared memory service
-+ * running on videocore.
-+ */
-+ ret = vchi_initialise(&vchi_instance);
-+ if (ret) {
-+ pr_err("[%s]: failed to initialise VCHI instance (ret=%d)\n",
-+ __func__, ret);
-+
-+ ret = -EIO;
-+ goto err_free_mem;
-+ }
-+
-+ ret = vchi_connect(vchi_instance);
-+ if (ret) {
-+ pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n",
-+ __func__, ret);
-+
-+ ret = -EIO;
-+ goto err_free_mem;
-+ }
-+
-+ /* Initialize an instance of the shared memory service. */
-+ sm_state->sm_handle = vc_sm_cma_vchi_init(vchi_instance, 1,
-+ vc_sm_vpu_event);
-+ if (!sm_state->sm_handle) {
-+ pr_err("[%s]: failed to initialize shared memory service\n",
-+ __func__);
-+
-+ ret = -EPERM;
-+ goto err_free_mem;
-+ }
-+
-+ /* Create a debug fs directory entry (root). */
-+ sm_state->dir_root = debugfs_create_dir(VC_SM_DIR_ROOT_NAME, NULL);
-+ if (!sm_state->dir_root) {
-+ pr_err("[%s]: failed to create \'%s\' directory entry\n",
-+ __func__, VC_SM_DIR_ROOT_NAME);
-+
-+ ret = -EPERM;
-+ goto err_stop_sm_service;
-+ }
-+
-+ sm_state->dir_state.show = &vc_sm_cma_global_state_show;
-+ sm_state->dir_state.dir_entry =
-+ debugfs_create_file(VC_SM_STATE, 0444, sm_state->dir_root,
-+ &sm_state->dir_state,
-+ &vc_sm_cma_debug_fs_fops);
-+
-+ INIT_LIST_HEAD(&sm_state->buffer_list);
-+
-+ sm_state->data_knl = vc_sm_cma_create_priv_data(0);
-+ if (!sm_state->data_knl) {
-+ pr_err("[%s]: failed to create kernel private data tracker\n",
-+ __func__);
-+ goto err_remove_shared_memory;
-+ }
-+
-+ version.version = 1;
-+ ret = vc_sm_cma_vchi_client_version(sm_state->sm_handle, &version,
-+ &version_result,
-+ &sm_state->int_trans_id);
-+ if (ret) {
-+ pr_err("[%s]: Failed to send version request %d\n", __func__,
-+ ret);
-+ }
-+
-+ /* Done! */
-+ sm_inited = 1;
-+ pr_info("[%s]: installed successfully\n", __func__);
-+ return;
-+
-+err_remove_shared_memory:
-+ debugfs_remove_recursive(sm_state->dir_root);
-+err_stop_sm_service:
-+ vc_sm_cma_vchi_stop(&sm_state->sm_handle);
-+err_free_mem:
-+ kfree(sm_state);
-+ pr_info("[%s]: failed, ret %d\n", __func__, ret);
-+}
-+
-+/* Driver loading. */
-+static int bcm2835_vc_sm_cma_probe(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ int err;
-+
-+ pr_info("%s: Videocore shared memory driver\n", __func__);
-+
-+ sm_state = kzalloc(sizeof(*sm_state), GFP_KERNEL);
-+ if (!sm_state)
-+ return -ENOMEM;
-+ sm_state->pdev = pdev;
-+ mutex_init(&sm_state->map_lock);
-+
-+ dev->coherent_dma_mask = DMA_BIT_MASK(32);
-+ dev->dma_mask = &dev->coherent_dma_mask;
-+ err = of_dma_configure(dev, NULL, true);
-+ if (err) {
-+ dev_err(dev, "Unable to setup DMA: %d\n", err);
-+ return err;
-+ }
-+
-+ vchiq_add_connected_callback(vc_sm_connected_init);
-+ return 0;
-+}
-+
-+/* Driver unloading. */
-+static int bcm2835_vc_sm_cma_remove(struct platform_device *pdev)
-+{
-+ pr_debug("[%s]: start\n", __func__);
-+ if (sm_inited) {
-+ /* Remove shared memory device. */
-+ misc_deregister(&sm_state->dev);
-+
-+ /* Remove all proc entries. */
-+ //debugfs_remove_recursive(sm_state->dir_root);
-+
-+ /* Stop the videocore shared memory service. */
-+ vc_sm_cma_vchi_stop(&sm_state->sm_handle);
-+
-+ /* Free the memory for the state structure. */
-+ mutex_destroy(&sm_state->map_lock);
-+ kfree(sm_state);
-+ }
-+
-+ pr_debug("[%s]: end\n", __func__);
-+ return 0;
-+}
-+
-+/* Get an internal resource handle mapped from the external one. */
-+int vc_sm_cma_int_handle(int handle)
-+{
-+ struct dma_buf *dma_buf = (struct dma_buf *)handle;
-+ struct vc_sm_buffer *res;
-+
-+ /* Validate we can work with this device. */
-+ if (!sm_state || !handle) {
-+ pr_err("[%s]: invalid input\n", __func__);
-+ return 0;
-+ }
-+
-+ res = (struct vc_sm_buffer *)dma_buf->priv;
-+ return res->vc_handle;
-+}
-+EXPORT_SYMBOL_GPL(vc_sm_cma_int_handle);
-+
-+/* Free a previously allocated shared memory handle and block. */
-+int vc_sm_cma_free(int handle)
-+{
-+ struct dma_buf *dma_buf = (struct dma_buf *)handle;
-+
-+ /* Validate we can work with this device. */
-+ if (!sm_state || !handle) {
-+ pr_err("[%s]: invalid input\n", __func__);
-+ return -EPERM;
-+ }
-+
-+ pr_debug("%s: handle %08x/dmabuf %p\n", __func__, handle, dma_buf);
-+
-+ dma_buf_put(dma_buf);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(vc_sm_cma_free);
-+
-+/* Import a dmabuf to be shared with VC. */
-+int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, int *handle)
-+{
-+ struct dma_buf *new_dma_buf;
-+ struct vc_sm_buffer *res;
-+ int ret;
-+
-+ /* Validate we can work with this device. */
-+ if (!sm_state || !src_dmabuf || !handle) {
-+ pr_err("[%s]: invalid input\n", __func__);
-+ return -EPERM;
-+ }
-+
-+ ret = vc_sm_cma_import_dmabuf_internal(sm_state->data_knl, src_dmabuf,
-+ &new_dma_buf);
-+
-+ if (!ret) {
-+ pr_debug("%s: imported to ptr %p\n", __func__, new_dma_buf);
-+ res = (struct vc_sm_buffer *)new_dma_buf->priv;
-+
-+ /* Assign valid handle at this time.*/
-+ *handle = (int)new_dma_buf;
-+ } else {
-+ /*
-+ * succeeded in importing the dma_buf, but then
-+ * failed to look it up again. How?
-+ * Release the fd again.
-+ */
-+ pr_err("%s: imported vc_sm_cma_get_buffer failed %d\n",
-+ __func__, ret);
-+ }
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(vc_sm_cma_import_dmabuf);
-+
-+static struct platform_driver bcm2835_vcsm_cma_driver = {
-+ .probe = bcm2835_vc_sm_cma_probe,
-+ .remove = bcm2835_vc_sm_cma_remove,
-+ .driver = {
-+ .name = DEVICE_NAME,
-+ .owner = THIS_MODULE,
-+ },
-+};
-+
-+module_platform_driver(bcm2835_vcsm_cma_driver);
-+
-+MODULE_AUTHOR("Dave Stevenson");
-+MODULE_DESCRIPTION("VideoCore CMA Shared Memory Driver");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:vcsm-cma");
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
-@@ -0,0 +1,59 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/*
-+ * VideoCore Shared Memory driver using CMA.
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ *
-+ */
-+
-+#ifndef VC_SM_H
-+#define VC_SM_H
-+
-+#include <linux/device.h>
-+#include <linux/dma-direction.h>
-+#include <linux/kref.h>
-+#include <linux/mm_types.h>
-+#include <linux/mutex.h>
-+#include <linux/rbtree.h>
-+#include <linux/sched.h>
-+#include <linux/shrinker.h>
-+#include <linux/types.h>
-+#include <linux/miscdevice.h>
-+
-+#define VC_SM_MAX_NAME_LEN 32
-+
-+enum vc_sm_vpu_mapping_state {
-+ VPU_NOT_MAPPED,
-+ VPU_MAPPED,
-+ VPU_UNMAPPING
-+};
-+
-+struct vc_sm_buffer {
-+ struct list_head global_buffer_list; /* Global list of buffers. */
-+
-+ size_t size;
-+
-+ /* Lock over all the following state for this buffer */
-+ struct mutex lock;
-+ struct sg_table *sg_table;
-+ struct list_head attachments;
-+
-+ char name[VC_SM_MAX_NAME_LEN];
-+
-+ int in_use:1; /* Kernel is still using this resource */
-+
-+ enum vc_sm_vpu_mapping_state vpu_state;
-+ u32 vc_handle; /* VideoCore handle for this buffer */
-+
-+ /* DMABUF related fields */
-+ struct dma_buf *import_dma_buf;
-+ struct dma_buf *dma_buf;
-+ struct dma_buf_attachment *attach;
-+ struct sg_table *sgt;
-+ dma_addr_t dma_addr;
-+
-+ struct vc_sm_privdata_t *private;
-+};
-+
-+#endif
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-@@ -0,0 +1,498 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * VideoCore Shared Memory CMA allocator
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ * Copyright 2011-2012 Broadcom Corporation. All rights reserved.
-+ *
-+ * Based on vmcs_sm driver from Broadcom Corporation.
-+ *
-+ */
-+
-+/* ---- Include Files ----------------------------------------------------- */
-+#include <linux/completion.h>
-+#include <linux/kernel.h>
-+#include <linux/kthread.h>
-+#include <linux/list.h>
-+#include <linux/mutex.h>
-+#include <linux/semaphore.h>
-+#include <linux/slab.h>
-+#include <linux/types.h>
-+
-+#include "vc_sm_cma_vchi.h"
-+
-+#define VC_SM_VER 1
-+#define VC_SM_MIN_VER 0
-+
-+/* ---- Private Constants and Types -------------------------------------- */
-+
-+/* Command blocks come from a pool */
-+#define SM_MAX_NUM_CMD_RSP_BLKS 32
-+
-+struct sm_cmd_rsp_blk {
-+ struct list_head head; /* To create lists */
-+ /* To be signaled when the response is there */
-+ struct completion cmplt;
-+
-+ u16 id;
-+ u16 length;
-+
-+ u8 msg[VC_SM_MAX_MSG_LEN];
-+
-+ uint32_t wait:1;
-+ uint32_t sent:1;
-+ uint32_t alloc:1;
-+
-+};
-+
-+struct sm_instance {
-+ u32 num_connections;
-+ VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS];
-+ struct task_struct *io_thread;
-+ struct completion io_cmplt;
-+
-+ vpu_event_cb vpu_event;
-+
-+ /* Mutex over the following lists */
-+ struct mutex lock;
-+ u32 trans_id;
-+ struct list_head cmd_list;
-+ struct list_head rsp_list;
-+ struct list_head dead_list;
-+
-+ struct sm_cmd_rsp_blk free_blk[SM_MAX_NUM_CMD_RSP_BLKS];
-+
-+ /* Mutex over the free_list */
-+ struct mutex free_lock;
-+ struct list_head free_list;
-+
-+ struct semaphore free_sema;
-+
-+};
-+
-+/* ---- Private Variables ------------------------------------------------ */
-+
-+/* ---- 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,
-+ enum vc_sm_msg_type id, void *msg,
-+ u32 size, int wait)
-+{
-+ struct sm_cmd_rsp_blk *blk;
-+ struct vc_sm_msg_hdr_t *hdr;
-+
-+ if (down_interruptible(&instance->free_sema)) {
-+ blk = kmalloc(sizeof(*blk), GFP_KERNEL);
-+ if (!blk)
-+ return NULL;
-+
-+ blk->alloc = 1;
-+ init_completion(&blk->cmplt);
-+ } else {
-+ mutex_lock(&instance->free_lock);
-+ blk =
-+ list_first_entry(&instance->free_list,
-+ struct sm_cmd_rsp_blk, head);
-+ list_del(&blk->head);
-+ mutex_unlock(&instance->free_lock);
-+ }
-+
-+ blk->sent = 0;
-+ blk->wait = wait;
-+ blk->length = sizeof(*hdr) + size;
-+
-+ hdr = (struct vc_sm_msg_hdr_t *)blk->msg;
-+ hdr->type = id;
-+ mutex_lock(&instance->lock);
-+ instance->trans_id++;
-+ /*
-+ * Retain the top bit for identifying asynchronous events, or VPU cmds.
-+ */
-+ instance->trans_id &= ~0x80000000;
-+ hdr->trans_id = instance->trans_id;
-+ blk->id = instance->trans_id;
-+ mutex_unlock(&instance->lock);
-+
-+ if (size)
-+ memcpy(hdr->body, msg, size);
-+
-+ return blk;
-+}
-+
-+static void
-+vc_vchi_cmd_delete(struct sm_instance *instance, struct sm_cmd_rsp_blk *blk)
-+{
-+ if (blk->alloc) {
-+ kfree(blk);
-+ return;
-+ }
-+
-+ mutex_lock(&instance->free_lock);
-+ list_add(&blk->head, &instance->free_list);
-+ mutex_unlock(&instance->free_lock);
-+ up(&instance->free_sema);
-+}
-+
-+static void vc_sm_cma_vchi_rx_ack(struct sm_instance *instance,
-+ struct sm_cmd_rsp_blk *cmd,
-+ struct vc_sm_result_t *reply,
-+ u32 reply_len)
-+{
-+ mutex_lock(&instance->lock);
-+ list_for_each_entry(cmd,
-+ &instance->rsp_list,
-+ head) {
-+ if (cmd->id == reply->trans_id)
-+ break;
-+ }
-+ mutex_unlock(&instance->lock);
-+
-+ if (&cmd->head == &instance->rsp_list) {
-+ //pr_debug("%s: received response %u, throw away...",
-+ pr_err("%s: received response %u, throw away...",
-+ __func__,
-+ reply->trans_id);
-+ } else if (reply_len > sizeof(cmd->msg)) {
-+ pr_err("%s: reply too big (%u) %u, throw away...",
-+ __func__, reply_len,
-+ reply->trans_id);
-+ } else {
-+ memcpy(cmd->msg, reply,
-+ reply_len);
-+ complete(&cmd->cmplt);
-+ }
-+}
-+
-+static int vc_sm_cma_vchi_videocore_io(void *arg)
-+{
-+ struct sm_instance *instance = arg;
-+ struct sm_cmd_rsp_blk *cmd = NULL, *cmd_tmp;
-+ struct vc_sm_result_t *reply;
-+ u32 reply_len;
-+ s32 status;
-+ int svc_use = 1;
-+
-+ while (1) {
-+ if (svc_use)
-+ vchi_service_release(instance->vchi_handle[0]);
-+ svc_use = 0;
-+ if (!wait_for_completion_interruptible(&instance->io_cmplt)) {
-+ vchi_service_use(instance->vchi_handle[0]);
-+ svc_use = 1;
-+
-+ do {
-+ /*
-+ * Get new command and move it to response list
-+ */
-+ mutex_lock(&instance->lock);
-+ if (list_empty(&instance->cmd_list)) {
-+ /* no more commands to process */
-+ mutex_unlock(&instance->lock);
-+ break;
-+ }
-+ cmd =
-+ list_first_entry(&instance->cmd_list,
-+ struct sm_cmd_rsp_blk,
-+ head);
-+ list_move(&cmd->head, &instance->rsp_list);
-+ cmd->sent = 1;
-+ mutex_unlock(&instance->lock);
-+
-+ /* Send the command */
-+ status = bcm2835_vchi_msg_queue(
-+ instance->vchi_handle[0],
-+ cmd->msg, cmd->length);
-+ if (status) {
-+ pr_err("%s: failed to queue message (%d)",
-+ __func__, status);
-+ }
-+
-+ /* If no reply is needed then we're done */
-+ if (!cmd->wait) {
-+ mutex_lock(&instance->lock);
-+ list_del(&cmd->head);
-+ mutex_unlock(&instance->lock);
-+ vc_vchi_cmd_delete(instance, cmd);
-+ continue;
-+ }
-+
-+ if (status) {
-+ complete(&cmd->cmplt);
-+ continue;
-+ }
-+
-+ } while (1);
-+
-+ while (!vchi_msg_peek(instance->vchi_handle[0],
-+ (void **)&reply, &reply_len,
-+ VCHI_FLAGS_NONE)) {
-+ if (reply->trans_id & 0x80000000) {
-+ /* Async event or cmd from the VPU */
-+ if (instance->vpu_event)
-+ instance->vpu_event(
-+ instance, reply,
-+ reply_len);
-+ } else {
-+ vc_sm_cma_vchi_rx_ack(instance, cmd,
-+ reply, reply_len);
-+ }
-+
-+ vchi_msg_remove(instance->vchi_handle[0]);
-+ }
-+
-+ /* Go through the dead list and free them */
-+ mutex_lock(&instance->lock);
-+ list_for_each_entry_safe(cmd, cmd_tmp,
-+ &instance->dead_list, head) {
-+ list_del(&cmd->head);
-+ vc_vchi_cmd_delete(instance, cmd);
-+ }
-+ mutex_unlock(&instance->lock);
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static void vc_sm_cma_vchi_callback(void *param,
-+ const VCHI_CALLBACK_REASON_T reason,
-+ void *msg_handle)
-+{
-+ struct sm_instance *instance = param;
-+
-+ (void)msg_handle;
-+
-+ switch (reason) {
-+ case VCHI_CALLBACK_MSG_AVAILABLE:
-+ complete(&instance->io_cmplt);
-+ break;
-+
-+ case VCHI_CALLBACK_SERVICE_CLOSED:
-+ pr_info("%s: service CLOSED!!", __func__);
-+ default:
-+ break;
-+ }
-+}
-+
-+struct sm_instance *vc_sm_cma_vchi_init(VCHI_INSTANCE_T vchi_instance,
-+ unsigned int num_connections,
-+ vpu_event_cb vpu_event)
-+{
-+ u32 i;
-+ struct sm_instance *instance;
-+ int status;
-+
-+ pr_debug("%s: start", __func__);
-+
-+ if (num_connections > VCHI_MAX_NUM_CONNECTIONS) {
-+ pr_err("%s: unsupported number of connections %u (max=%u)",
-+ __func__, num_connections, VCHI_MAX_NUM_CONNECTIONS);
-+
-+ goto err_null;
-+ }
-+ /* Allocate memory for this instance */
-+ instance = kzalloc(sizeof(*instance), GFP_KERNEL);
-+
-+ /* Misc initialisations */
-+ mutex_init(&instance->lock);
-+ init_completion(&instance->io_cmplt);
-+ INIT_LIST_HEAD(&instance->cmd_list);
-+ INIT_LIST_HEAD(&instance->rsp_list);
-+ INIT_LIST_HEAD(&instance->dead_list);
-+ INIT_LIST_HEAD(&instance->free_list);
-+ sema_init(&instance->free_sema, SM_MAX_NUM_CMD_RSP_BLKS);
-+ mutex_init(&instance->free_lock);
-+ for (i = 0; i < SM_MAX_NUM_CMD_RSP_BLKS; i++) {
-+ init_completion(&instance->free_blk[i].cmplt);
-+ list_add(&instance->free_blk[i].head, &instance->free_list);
-+ }
-+
-+ /* Open the VCHI service connections */
-+ instance->num_connections = num_connections;
-+ for (i = 0; i < num_connections; i++) {
-+ SERVICE_CREATION_T params = {
-+ .version = VCHI_VERSION_EX(VC_SM_VER, VC_SM_MIN_VER),
-+ .service_id = VC_SM_SERVER_NAME,
-+ .callback = vc_sm_cma_vchi_callback,
-+ .callback_param = instance,
-+ };
-+
-+ status = vchi_service_open(vchi_instance,
-+ ¶ms, &instance->vchi_handle[i]);
-+ if (status) {
-+ pr_err("%s: failed to open VCHI service (%d)",
-+ __func__, status);
-+
-+ goto err_close_services;
-+ }
-+ }
-+
-+ /* Create the thread which takes care of all io to/from videoocore. */
-+ instance->io_thread = kthread_create(&vc_sm_cma_vchi_videocore_io,
-+ (void *)instance, "SMIO");
-+ if (!instance->io_thread) {
-+ pr_err("%s: failed to create SMIO thread", __func__);
-+
-+ goto err_close_services;
-+ }
-+ instance->vpu_event = vpu_event;
-+ set_user_nice(instance->io_thread, -10);
-+ wake_up_process(instance->io_thread);
-+
-+ pr_debug("%s: success - instance 0x%x", __func__,
-+ (unsigned int)instance);
-+ return instance;
-+
-+err_close_services:
-+ for (i = 0; i < instance->num_connections; i++) {
-+ if (instance->vchi_handle[i])
-+ vchi_service_close(instance->vchi_handle[i]);
-+ }
-+ kfree(instance);
-+err_null:
-+ pr_debug("%s: FAILED", __func__);
-+ return NULL;
-+}
-+
-+int vc_sm_cma_vchi_stop(struct sm_instance **handle)
-+{
-+ struct sm_instance *instance;
-+ u32 i;
-+
-+ if (!handle) {
-+ pr_err("%s: invalid pointer to handle %p", __func__, handle);
-+ goto lock;
-+ }
-+
-+ if (!*handle) {
-+ pr_err("%s: invalid handle %p", __func__, *handle);
-+ goto lock;
-+ }
-+
-+ instance = *handle;
-+
-+ /* Close all VCHI service connections */
-+ for (i = 0; i < instance->num_connections; i++) {
-+ s32 success;
-+
-+ vchi_service_use(instance->vchi_handle[i]);
-+
-+ success = vchi_service_close(instance->vchi_handle[i]);
-+ }
-+
-+ kfree(instance);
-+
-+ *handle = NULL;
-+ return 0;
-+
-+lock:
-+ return -EINVAL;
-+}
-+
-+static int vc_sm_cma_vchi_send_msg(struct sm_instance *handle,
-+ enum vc_sm_msg_type msg_id, void *msg,
-+ u32 msg_size, void *result, u32 result_size,
-+ u32 *cur_trans_id, u8 wait_reply)
-+{
-+ int status = 0;
-+ struct sm_instance *instance = handle;
-+ struct sm_cmd_rsp_blk *cmd_blk;
-+
-+ if (!handle) {
-+ pr_err("%s: invalid handle", __func__);
-+ return -EINVAL;
-+ }
-+ if (!msg) {
-+ pr_err("%s: invalid msg pointer", __func__);
-+ return -EINVAL;
-+ }
-+
-+ cmd_blk =
-+ vc_vchi_cmd_create(instance, msg_id, msg, msg_size, wait_reply);
-+ if (!cmd_blk) {
-+ pr_err("[%s]: failed to allocate global tracking resource",
-+ __func__);
-+ return -ENOMEM;
-+ }
-+
-+ if (cur_trans_id)
-+ *cur_trans_id = cmd_blk->id;
-+
-+ mutex_lock(&instance->lock);
-+ list_add_tail(&cmd_blk->head, &instance->cmd_list);
-+ mutex_unlock(&instance->lock);
-+ complete(&instance->io_cmplt);
-+
-+ if (!wait_reply)
-+ /* We're done */
-+ return 0;
-+
-+ /* Wait for the response */
-+ if (wait_for_completion_interruptible(&cmd_blk->cmplt)) {
-+ mutex_lock(&instance->lock);
-+ if (!cmd_blk->sent) {
-+ list_del(&cmd_blk->head);
-+ mutex_unlock(&instance->lock);
-+ vc_vchi_cmd_delete(instance, cmd_blk);
-+ return -ENXIO;
-+ }
-+
-+ list_move(&cmd_blk->head, &instance->dead_list);
-+ mutex_unlock(&instance->lock);
-+ complete(&instance->io_cmplt);
-+ return -EINTR; /* We're done */
-+ }
-+
-+ if (result && result_size) {
-+ memcpy(result, cmd_blk->msg, result_size);
-+ } else {
-+ struct vc_sm_result_t *res =
-+ (struct vc_sm_result_t *)cmd_blk->msg;
-+ status = (res->success == 0) ? 0 : -ENXIO;
-+ }
-+
-+ mutex_lock(&instance->lock);
-+ list_del(&cmd_blk->head);
-+ mutex_unlock(&instance->lock);
-+ vc_vchi_cmd_delete(instance, cmd_blk);
-+ return status;
-+}
-+
-+int vc_sm_cma_vchi_free(struct sm_instance *handle, struct vc_sm_free_t *msg,
-+ u32 *cur_trans_id)
-+{
-+ return vc_sm_cma_vchi_send_msg(handle, VC_SM_MSG_TYPE_FREE,
-+ msg, sizeof(*msg), 0, 0, cur_trans_id, 0);
-+}
-+
-+int vc_sm_cma_vchi_import(struct sm_instance *handle, struct vc_sm_import *msg,
-+ struct vc_sm_import_result *result, u32 *cur_trans_id)
-+{
-+ return vc_sm_cma_vchi_send_msg(handle, VC_SM_MSG_TYPE_IMPORT,
-+ msg, sizeof(*msg), result, sizeof(*result),
-+ cur_trans_id, 1);
-+}
-+
-+int vc_sm_cma_vchi_client_version(struct sm_instance *handle,
-+ struct vc_sm_version *msg,
-+ struct vc_sm_result_t *result,
-+ u32 *cur_trans_id)
-+{
-+ return vc_sm_cma_vchi_send_msg(handle, VC_SM_MSG_TYPE_CLIENT_VERSION,
-+ //msg, sizeof(*msg), result, sizeof(*result),
-+ //cur_trans_id, 1);
-+ msg, sizeof(*msg), NULL, 0,
-+ cur_trans_id, 0);
-+}
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
-@@ -0,0 +1,59 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/*
-+ * VideoCore Shared Memory CMA allocator
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ * Copyright 2011-2012 Broadcom Corporation. All rights reserved.
-+ *
-+ * Based on vmcs_sm driver from Broadcom Corporation.
-+ *
-+ */
-+
-+#ifndef __VC_SM_CMA_VCHI_H__INCLUDED__
-+#define __VC_SM_CMA_VCHI_H__INCLUDED__
-+
-+#include "interface/vchi/vchi.h"
-+
-+#include "vc_sm_defs.h"
-+
-+/*
-+ * Forward declare.
-+ */
-+struct sm_instance;
-+
-+typedef void (*vpu_event_cb)(struct sm_instance *instance,
-+ struct vc_sm_result_t *reply, int reply_len);
-+
-+/*
-+ * Initialize the shared memory service, opens up vchi connection to talk to it.
-+ */
-+struct sm_instance *vc_sm_cma_vchi_init(VCHI_INSTANCE_T vchi_instance,
-+ unsigned int num_connections,
-+ vpu_event_cb vpu_event);
-+
-+/*
-+ * Terminates the shared memory service.
-+ */
-+int vc_sm_cma_vchi_stop(struct sm_instance **handle);
-+
-+/*
-+ * Ask the shared memory service to free up some memory that was previously
-+ * allocated by the vc_sm_cma_vchi_alloc function call.
-+ */
-+int vc_sm_cma_vchi_free(struct sm_instance *handle, struct vc_sm_free_t *msg,
-+ u32 *cur_trans_id);
-+
-+/*
-+ * Import a contiguous block of memory and wrap it in a GPU MEM_HANDLE_T.
-+ */
-+int vc_sm_cma_vchi_import(struct sm_instance *handle, struct vc_sm_import *msg,
-+ struct vc_sm_import_result *result,
-+ u32 *cur_trans_id);
-+
-+int vc_sm_cma_vchi_client_version(struct sm_instance *handle,
-+ struct vc_sm_version *msg,
-+ struct vc_sm_result_t *result,
-+ u32 *cur_trans_id);
-+
-+#endif /* __VC_SM_CMA_VCHI_H__INCLUDED__ */
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
-@@ -0,0 +1,298 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/*
-+ * VideoCore Shared Memory CMA allocator
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ *
-+ * Based on vc_sm_defs.h from the vmcs_sm driver Copyright Broadcom Corporation.
-+ * All IPC messages are copied across to this file, even if the vc-sm-cma
-+ * driver is not currently using them.
-+ *
-+ ****************************************************************************
-+ */
-+
-+#ifndef __VC_SM_DEFS_H__INCLUDED__
-+#define __VC_SM_DEFS_H__INCLUDED__
-+
-+/* FourCC code used for VCHI connection */
-+#define VC_SM_SERVER_NAME MAKE_FOURCC("SMEM")
-+
-+/* Maximum message length */
-+#define VC_SM_MAX_MSG_LEN (sizeof(union vc_sm_msg_union_t) + \
-+ sizeof(struct vc_sm_msg_hdr_t))
-+#define VC_SM_MAX_RSP_LEN (sizeof(union vc_sm_msg_union_t))
-+
-+/* Resource name maximum size */
-+#define VC_SM_RESOURCE_NAME 32
-+
-+/*
-+ * Version to be reported to the VPU
-+ * VPU assumes 0 (aka 1) which does not require the released callback, nor
-+ * expect the client to handle VC_MEM_REQUESTS.
-+ * Version 2 requires the released callback, and must support VC_MEM_REQUESTS.
-+ */
-+#define VC_SM_PROTOCOL_VERSION 2
-+
-+enum vc_sm_msg_type {
-+ /* Message types supported for HOST->VC direction */
-+
-+ /* Allocate shared memory block */
-+ VC_SM_MSG_TYPE_ALLOC,
-+ /* Lock allocated shared memory block */
-+ VC_SM_MSG_TYPE_LOCK,
-+ /* Unlock allocated shared memory block */
-+ VC_SM_MSG_TYPE_UNLOCK,
-+ /* Unlock allocated shared memory block, do not answer command */
-+ VC_SM_MSG_TYPE_UNLOCK_NOANS,
-+ /* Free shared memory block */
-+ VC_SM_MSG_TYPE_FREE,
-+ /* Resize a shared memory block */
-+ VC_SM_MSG_TYPE_RESIZE,
-+ /* Walk the allocated shared memory block(s) */
-+ VC_SM_MSG_TYPE_WALK_ALLOC,
-+
-+ /* A previously applied action will need to be reverted */
-+ VC_SM_MSG_TYPE_ACTION_CLEAN,
-+
-+ /*
-+ * Import a physical address and wrap into a MEM_HANDLE_T.
-+ * Release with VC_SM_MSG_TYPE_FREE.
-+ */
-+ VC_SM_MSG_TYPE_IMPORT,
-+ /*
-+ *Tells VC the protocol version supported by this client.
-+ * 2 supports the async/cmd messages from the VPU for final release
-+ * of memory, and for VC allocations.
-+ */
-+ VC_SM_MSG_TYPE_CLIENT_VERSION,
-+ /* Response to VC request for memory */
-+ VC_SM_MSG_TYPE_VC_MEM_REQUEST_REPLY,
-+
-+ /*
-+ * Asynchronous/cmd messages supported for VC->HOST direction.
-+ * Signalled by setting the top bit in vc_sm_result_t trans_id.
-+ */
-+
-+ /*
-+ * VC has finished with an imported memory allocation.
-+ * Release any Linux reference counts on the underlying block.
-+ */
-+ VC_SM_MSG_TYPE_RELEASED,
-+ /* VC request for memory */
-+ VC_SM_MSG_TYPE_VC_MEM_REQUEST,
-+
-+ VC_SM_MSG_TYPE_MAX
-+};
-+
-+/* Type of memory to be allocated */
-+enum vc_sm_alloc_type_t {
-+ VC_SM_ALLOC_CACHED,
-+ VC_SM_ALLOC_NON_CACHED,
-+};
-+
-+/* Message header for all messages in HOST->VC direction */
-+struct vc_sm_msg_hdr_t {
-+ u32 type;
-+ u32 trans_id;
-+ u8 body[0];
-+
-+};
-+
-+/* Request to allocate memory (HOST->VC) */
-+struct vc_sm_alloc_t {
-+ /* type of memory to allocate */
-+ enum vc_sm_alloc_type_t type;
-+ /* byte amount of data to allocate per unit */
-+ u32 base_unit;
-+ /* number of unit to allocate */
-+ u32 num_unit;
-+ /* alignment to be applied on allocation */
-+ u32 alignment;
-+ /* identity of who allocated this block */
-+ u32 allocator;
-+ /* resource name (for easier tracking on vc side) */
-+ char name[VC_SM_RESOURCE_NAME];
-+
-+};
-+
-+/* Result of a requested memory allocation (VC->HOST) */
-+struct vc_sm_alloc_result_t {
-+ /* Transaction identifier */
-+ u32 trans_id;
-+
-+ /* Resource handle */
-+ u32 res_handle;
-+ /* Pointer to resource buffer */
-+ u32 res_mem;
-+ /* Resource base size (bytes) */
-+ u32 res_base_size;
-+ /* Resource number */
-+ u32 res_num;
-+
-+};
-+
-+/* Request to free a previously allocated memory (HOST->VC) */
-+struct vc_sm_free_t {
-+ /* Resource handle (returned from alloc) */
-+ u32 res_handle;
-+ /* Resource buffer (returned from alloc) */
-+ u32 res_mem;
-+
-+};
-+
-+/* Request to lock a previously allocated memory (HOST->VC) */
-+struct vc_sm_lock_unlock_t {
-+ /* Resource handle (returned from alloc) */
-+ u32 res_handle;
-+ /* Resource buffer (returned from alloc) */
-+ u32 res_mem;
-+
-+};
-+
-+/* Request to resize a previously allocated memory (HOST->VC) */
-+struct vc_sm_resize_t {
-+ /* Resource handle (returned from alloc) */
-+ u32 res_handle;
-+ /* Resource buffer (returned from alloc) */
-+ u32 res_mem;
-+ /* Resource *new* size requested (bytes) */
-+ u32 res_new_size;
-+
-+};
-+
-+/* Result of a requested memory lock (VC->HOST) */
-+struct vc_sm_lock_result_t {
-+ /* Transaction identifier */
-+ u32 trans_id;
-+
-+ /* Resource handle */
-+ u32 res_handle;
-+ /* Pointer to resource buffer */
-+ u32 res_mem;
-+ /*
-+ * Pointer to former resource buffer if the memory
-+ * was reallocated
-+ */
-+ u32 res_old_mem;
-+
-+};
-+
-+/* Generic result for a request (VC->HOST) */
-+struct vc_sm_result_t {
-+ /* Transaction identifier */
-+ u32 trans_id;
-+
-+ s32 success;
-+
-+};
-+
-+/* Request to revert a previously applied action (HOST->VC) */
-+struct vc_sm_action_clean_t {
-+ /* Action of interest */
-+ enum vc_sm_msg_type res_action;
-+ /* Transaction identifier for the action of interest */
-+ u32 action_trans_id;
-+
-+};
-+
-+/* Request to remove all data associated with a given allocator (HOST->VC) */
-+struct vc_sm_free_all_t {
-+ /* Allocator identifier */
-+ u32 allocator;
-+};
-+
-+/* Request to import memory (HOST->VC) */
-+struct vc_sm_import {
-+ /* type of memory to allocate */
-+ enum vc_sm_alloc_type_t type;
-+ /* pointer to the VC (ie physical) address of the allocated memory */
-+ u32 addr;
-+ /* size of buffer */
-+ u32 size;
-+ /* opaque handle returned in RELEASED messages */
-+ u32 kernel_id;
-+ /* Allocator identifier */
-+ u32 allocator;
-+ /* resource name (for easier tracking on vc side) */
-+ char name[VC_SM_RESOURCE_NAME];
-+};
-+
-+/* Result of a requested memory import (VC->HOST) */
-+struct vc_sm_import_result {
-+ /* Transaction identifier */
-+ u32 trans_id;
-+
-+ /* Resource handle */
-+ u32 res_handle;
-+};
-+
-+/* Notification that VC has finished with an allocation (VC->HOST) */
-+struct vc_sm_released {
-+ /* cmd type / trans_id */
-+ u32 cmd;
-+
-+ /* pointer to the VC (ie physical) address of the allocated memory */
-+ u32 addr;
-+ /* size of buffer */
-+ u32 size;
-+ /* opaque handle returned in RELEASED messages */
-+ u32 kernel_id;
-+ u32 vc_handle;
-+};
-+
-+/*
-+ * Client informing VC as to the protocol version it supports.
-+ * >=2 requires the released callback, and supports VC asking for memory.
-+ * Failure means that the firmware doesn't support this call, and therefore the
-+ * client should either fail, or NOT rely on getting the released callback.
-+ */
-+struct vc_sm_version {
-+ u32 version;
-+};
-+
-+/* Request FROM VideoCore for some memory */
-+struct vc_sm_vc_mem_request {
-+ /* cmd type */
-+ u32 cmd;
-+
-+ /* trans_id (from VPU) */
-+ u32 trans_id;
-+ /* size of buffer */
-+ u32 size;
-+ /* alignment of buffer */
-+ u32 align;
-+ /* resource name (for easier tracking) */
-+ char name[VC_SM_RESOURCE_NAME];
-+};
-+
-+/* Response from the kernel to provide the VPU with some memory */
-+struct vc_sm_vc_mem_request_result {
-+ /* Transaction identifier for the VPU */
-+ u32 trans_id;
-+ /* pointer to the physical address of the allocated memory */
-+ u32 addr;
-+ /* opaque handle returned in RELEASED messages */
-+ u32 kernel_id;
-+};
-+
-+/* Union of ALL messages */
-+union vc_sm_msg_union_t {
-+ struct vc_sm_alloc_t alloc;
-+ struct vc_sm_alloc_result_t alloc_result;
-+ struct vc_sm_free_t free;
-+ struct vc_sm_lock_unlock_t lock_unlock;
-+ struct vc_sm_action_clean_t action_clean;
-+ struct vc_sm_resize_t resize;
-+ struct vc_sm_lock_result_t lock_result;
-+ struct vc_sm_result_t result;
-+ struct vc_sm_free_all_t free_all;
-+ struct vc_sm_import import;
-+ struct vc_sm_import_result import_result;
-+ struct vc_sm_version version;
-+ struct vc_sm_released released;
-+ struct vc_sm_vc_mem_request vc_request;
-+ struct vc_sm_vc_mem_request_result vc_request_result;
-+};
-+
-+#endif /* __VC_SM_DEFS_H__INCLUDED__ */
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/*
-+ * VideoCore Shared Memory CMA allocator
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ *
-+ * Based on vc_sm_defs.h from the vmcs_sm driver Copyright Broadcom Corporation.
-+ *
-+ */
-+
-+#ifndef __VC_SM_KNL_H__INCLUDED__
-+#define __VC_SM_KNL_H__INCLUDED__
-+
-+#if !defined(__KERNEL__)
-+#error "This interface is for kernel use only..."
-+#endif
-+
-+/* Free a previously allocated or imported shared memory handle and block. */
-+int vc_sm_cma_free(int handle);
-+
-+/* Get an internal resource handle mapped from the external one. */
-+int vc_sm_cma_int_handle(int handle);
-+
-+/* Import a block of memory into the GPU space. */
-+int vc_sm_cma_import_dmabuf(struct dma_buf *dmabuf, int *handle);
-+
-+#endif /* __VC_SM_KNL_H__INCLUDED__ */
+++ /dev/null
-From 474a6207d432c230ffa4f9b1a8ff0d9673bd89bb Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 30 Oct 2018 11:42:48 +0000
-Subject: [PATCH 276/703] staging: vc-sm-cma: Fixup driver for older VCHI APIs
-
-Original patch was based off staging which included some cleanups
-of the VCHI APIs. Those aren't present here, so switch back to
-the older API.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 2 +-
- drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c | 5 +++++
- 2 files changed, 6 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -632,7 +632,7 @@ static void vc_sm_connected_init(void)
- goto err_free_mem;
- }
-
-- ret = vchi_connect(vchi_instance);
-+ ret = vchi_connect(NULL, 0, vchi_instance);
- if (ret) {
- pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n",
- __func__, ret);
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-@@ -325,8 +325,13 @@ struct sm_instance *vc_sm_cma_vchi_init(
- SERVICE_CREATION_T params = {
- .version = VCHI_VERSION_EX(VC_SM_VER, VC_SM_MIN_VER),
- .service_id = VC_SM_SERVER_NAME,
-+ .rx_fifo_size = 0,
-+ .tx_fifo_size = 0,
- .callback = vc_sm_cma_vchi_callback,
- .callback_param = instance,
-+ .want_unaligned_bulk_rx = 0,
-+ .want_unaligned_bulk_tx = 0,
-+ .want_crc = 0
- };
-
- status = vchi_service_open(vchi_instance,
--- /dev/null
+From e99f0a65a7159b35cd8dbf753d7e12b3331b0ca4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 25 Sep 2018 14:53:49 +0100
+Subject: [PATCH 276/725] staging: vc04_services: Add a V4L2 M2M codec driver
+
+This adds a V4L2 memory to memory device that wraps the MMAL
+video decode and video_encode components for H264 and MJPEG encode
+and decode, MPEG4, H263, and VP8 decode (and MPEG2 decode
+if the appropriate licence has been purchased).
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/Kconfig | 1 +
+ drivers/staging/vc04_services/Makefile | 9 +-
+ .../vc04_services/bcm2835-codec/Kconfig | 11 +
+ .../vc04_services/bcm2835-codec/Makefile | 8 +
+ .../staging/vc04_services/bcm2835-codec/TODO | 24 +
+ .../bcm2835-codec/bcm2835-v4l2-codec.c | 2359 +++++++++++++++++
+ 6 files changed, 2408 insertions(+), 4 deletions(-)
+ create mode 100644 drivers/staging/vc04_services/bcm2835-codec/Kconfig
+ create mode 100644 drivers/staging/vc04_services/bcm2835-codec/Makefile
+ create mode 100644 drivers/staging/vc04_services/bcm2835-codec/TODO
+ create mode 100644 drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+
+--- a/drivers/staging/vc04_services/Kconfig
++++ b/drivers/staging/vc04_services/Kconfig
+@@ -23,6 +23,7 @@ source "drivers/staging/vc04_services/bc
+ source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
+ source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
+ source "drivers/staging/vc04_services/vc-sm-cma/Kconfig"
++source "drivers/staging/vc04_services/bcm2835-codec/Kconfig"
+
+ endif
+
+--- a/drivers/staging/vc04_services/Makefile
++++ b/drivers/staging/vc04_services/Makefile
+@@ -10,10 +10,11 @@ vchiq-objs := \
+ interface/vchiq_arm/vchiq_util.o \
+ interface/vchiq_arm/vchiq_connected.o \
+
+-obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/
+-obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/
+-obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
+-obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma/
++obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/
++obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/
++obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
++obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma/
++obj-$(CONFIG_VIDEO_CODEC_BCM2835) += bcm2835-codec/
+
+ ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000
+
+--- /dev/null
++++ b/drivers/staging/vc04_services/bcm2835-codec/Kconfig
+@@ -0,0 +1,11 @@
++config VIDEO_CODEC_BCM2835
++ tristate "BCM2835 Video codec support"
++ depends on MEDIA_SUPPORT
++ depends on VIDEO_V4L2 && (ARCH_BCM2835 || COMPILE_TEST)
++ select BCM2835_VCHIQ_MMAL
++ select VIDEOBUF2_DMA_CONTIG
++ select V4L2_MEM2MEM_DEV
++ help
++ Say Y here to enable the V4L2 video codecs for
++ Broadcom BCM2835 SoC. This operates over the VCHIQ interface
++ to a service running on VideoCore.
+--- /dev/null
++++ b/drivers/staging/vc04_services/bcm2835-codec/Makefile
+@@ -0,0 +1,8 @@
++# SPDX-License-Identifier: GPL-2.0
++bcm2835-codec-objs := bcm2835-v4l2-codec.o
++
++obj-$(CONFIG_VIDEO_CODEC_BCM2835) += bcm2835-codec.o
++
++ccflags-y += \
++ -Idrivers/staging/vc04_services \
++ -D__VCCOREVER__=0x04000000
+--- /dev/null
++++ b/drivers/staging/vc04_services/bcm2835-codec/TODO
+@@ -0,0 +1,24 @@
++1) Convert to be a platform driver.
++
++Right now when the module probes, it tries to initialize VCHI and
++errors out if it wasn't ready yet. If bcm2835-v4l2 was built in, then
++VCHI generally isn't ready because it depends on both the firmware and
++mailbox drivers having already loaded.
++
++We should have VCHI create a platform device once it's initialized,
++and have this driver bind to it, so that we automatically load the
++v4l2 module after VCHI loads.
++
++2) Support SELECTION API to define crop region on the image for encode.
++
++Particularly for resolutions that aren't a multiple of the macroblock
++size, the codec will report a resolution that is a multiple of the macroblock
++size (it has to have the memory to decode into), and then a different crop
++region within that buffer.
++The most common example is 1080P, where the buffer will be 1920x1088 with a
++crop region of 1920x1080.
++
++3) Refactor so that the component creation is only on queue_setup, not open.
++
++Fixes v4l2-compliance failure on trying to open 100 instances of the
++device.
+\ No newline at end of file
+--- /dev/null
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -0,0 +1,2359 @@
++// SPDX-License-Identifier: GPL-2.0
++
++/*
++ * A v4l2-mem2mem device that wraps the video codec MMAL component.
++ *
++ * Copyright 2018 Raspberry Pi (Trading) Ltd.
++ * Author: Dave Stevenson (dave.stevenson@raspberrypi.org)
++ *
++ * Loosely based on the vim2m virtual driver by Pawel Osciak
++ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
++ * Pawel Osciak, <pawel@osciak.com>
++ * Marek Szyprowski, <m.szyprowski@samsung.com>
++ *
++ * Whilst this driver uses the v4l2_mem2mem framework, it does not need the
++ * scheduling aspects, so will always take the buffers, pass them to the VPU,
++ * and then signal the job as complete.
++ *
++ * 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 <linux/module.h>
++#include <linux/delay.h>
++#include <linux/fs.h>
++#include <linux/timer.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/platform_device.h>
++#include <linux/syscalls.h>
++
++#include <media/v4l2-mem2mem.h>
++#include <media/v4l2-device.h>
++#include <media/v4l2-ioctl.h>
++#include <media/v4l2-ctrls.h>
++#include <media/v4l2-event.h>
++#include <media/videobuf2-dma-contig.h>
++
++#include "vchiq-mmal/mmal-encodings.h"
++#include "vchiq-mmal/mmal-msg.h"
++#include "vchiq-mmal/mmal-parameters.h"
++#include "vchiq-mmal/mmal-vchiq.h"
++
++/*
++ * Default /dev/videoN node numbers for decode and encode.
++ * Deliberately avoid the very low numbers as these are often taken by webcams
++ * etc, and simple apps tend to only go for /dev/video0.
++ */
++static int decode_video_nr = 10;
++module_param(decode_video_nr, int, 0644);
++MODULE_PARM_DESC(decode_video_nr, "decoder video device number");
++
++static int encode_video_nr = 11;
++module_param(encode_video_nr, int, 0644);
++MODULE_PARM_DESC(encode_video_nr, "encoder video device number");
++
++static unsigned int debug;
++module_param(debug, uint, 0644);
++MODULE_PARM_DESC(debug, "activates debug info (0-3)");
++
++#define MIN_W 32
++#define MIN_H 32
++#define MAX_W 1920
++#define MAX_H 1088
++#define BPL_ALIGN 32
++#define DEFAULT_WIDTH 640
++#define DEFAULT_HEIGHT 480
++/*
++ * The unanswered question - what is the maximum size of a compressed frame?
++ * V4L2 mandates that the encoded frame must fit in a single buffer. Sizing
++ * that buffer is a compromise between wasting memory and risking not fitting.
++ * The 1080P version of Big Buck Bunny has some frames that exceed 512kB.
++ * Adopt a moderately arbitrary split at 720P for switching between 512 and
++ * 768kB buffers.
++ */
++#define DEF_COMP_BUF_SIZE_GREATER_720P (768 << 10)
++#define DEF_COMP_BUF_SIZE_720P_OR_LESS (512 << 10)
++
++/* Flags that indicate a format can be used for capture/output */
++#define MEM2MEM_CAPTURE BIT(0)
++#define MEM2MEM_OUTPUT BIT(1)
++
++#define MEM2MEM_NAME "bcm2835-codec"
++
++struct bcm2835_codec_fmt {
++ u32 fourcc;
++ int depth;
++ int bytesperline_align;
++ u32 flags;
++ u32 mmal_fmt;
++ bool decode_only;
++ bool encode_only;
++ int size_multiplier_x2;
++};
++
++/* Supported raw pixel formats. Those supported for both encode and decode
++ * must come first, with those only supported for decode coming after (there
++ * are no formats supported for encode only).
++ */
++static struct bcm2835_codec_fmt raw_formats[] = {
++ {
++ .fourcc = V4L2_PIX_FMT_YUV420,
++ .depth = 8,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_I420,
++ .size_multiplier_x2 = 3,
++ }, {
++ .fourcc = V4L2_PIX_FMT_YVU420,
++ .depth = 8,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_YV12,
++ .size_multiplier_x2 = 3,
++ }, {
++ .fourcc = V4L2_PIX_FMT_NV12,
++ .depth = 8,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_NV12,
++ .size_multiplier_x2 = 3,
++ }, {
++ .fourcc = V4L2_PIX_FMT_NV21,
++ .depth = 8,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_NV21,
++ .size_multiplier_x2 = 3,
++ }, {
++ .fourcc = V4L2_PIX_FMT_RGB565,
++ .depth = 16,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_RGB16,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_YUYV,
++ .depth = 16,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_YUYV,
++ .encode_only = true,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_UYVY,
++ .depth = 16,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_UYVY,
++ .encode_only = true,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_YVYU,
++ .depth = 16,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_YVYU,
++ .encode_only = true,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_VYUY,
++ .depth = 16,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_VYUY,
++ .encode_only = true,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_RGB24,
++ .depth = 24,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_RGB24,
++ .encode_only = true,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_BGR24,
++ .depth = 24,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BGR24,
++ .encode_only = true,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_BGR32,
++ .depth = 32,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BGRA,
++ .encode_only = true,
++ .size_multiplier_x2 = 2,
++ },
++};
++
++/* Supported encoded formats. Those supported for both encode and decode
++ * must come first, with those only supported for decode coming after (there
++ * are no formats supported for encode only).
++ */
++static struct bcm2835_codec_fmt encoded_formats[] = {
++ {
++ .fourcc = V4L2_PIX_FMT_H264,
++ .depth = 0,
++ .flags = V4L2_FMT_FLAG_COMPRESSED,
++ .mmal_fmt = MMAL_ENCODING_H264,
++ }, {
++ .fourcc = V4L2_PIX_FMT_MJPEG,
++ .depth = 0,
++ .flags = V4L2_FMT_FLAG_COMPRESSED,
++ .mmal_fmt = MMAL_ENCODING_MJPEG,
++ }, {
++ .fourcc = V4L2_PIX_FMT_MPEG4,
++ .depth = 0,
++ .flags = V4L2_FMT_FLAG_COMPRESSED,
++ .mmal_fmt = MMAL_ENCODING_MP4V,
++ .decode_only = true,
++ }, {
++ .fourcc = V4L2_PIX_FMT_H263,
++ .depth = 0,
++ .flags = V4L2_FMT_FLAG_COMPRESSED,
++ .mmal_fmt = MMAL_ENCODING_H263,
++ .decode_only = true,
++ }, {
++ .fourcc = V4L2_PIX_FMT_MPEG2,
++ .depth = 0,
++ .flags = V4L2_FMT_FLAG_COMPRESSED,
++ .mmal_fmt = MMAL_ENCODING_MP2V,
++ .decode_only = true,
++ }, {
++ .fourcc = V4L2_PIX_FMT_VP8,
++ .depth = 0,
++ .flags = V4L2_FMT_FLAG_COMPRESSED,
++ .mmal_fmt = MMAL_ENCODING_VP8,
++ .decode_only = true,
++ },
++ /*
++ * This list couold include VP6 and Theorafor decode, but V4L2 doesn't
++ * support them.
++ */
++};
++
++struct bcm2835_codec_fmt_list {
++ struct bcm2835_codec_fmt *list;
++ unsigned int num_entries;
++};
++
++#define RAW_LIST 0
++#define ENCODED_LIST 1
++
++struct bcm2835_codec_fmt_list formats[] = {
++ {
++ .list = raw_formats,
++ .num_entries = ARRAY_SIZE(raw_formats),
++ }, {
++ .list = encoded_formats,
++ .num_entries = ARRAY_SIZE(encoded_formats),
++ },
++};
++
++struct m2m_mmal_buffer {
++ struct v4l2_m2m_buffer m2m;
++ struct mmal_buffer mmal;
++};
++
++/* Per-queue, driver-specific private data */
++struct bcm2835_codec_q_data {
++ /*
++ * These parameters should be treated as gospel, with everything else
++ * being determined from them.
++ */
++ /* Buffer width/height */
++ unsigned int bytesperline;
++ unsigned int height;
++ /* Crop size used for selection handling */
++ unsigned int crop_width;
++ unsigned int crop_height;
++ bool selection_set;
++
++ unsigned int sizeimage;
++ unsigned int sequence;
++ struct bcm2835_codec_fmt *fmt;
++
++ /* One extra buffer header so we can send an EOS. */
++ struct m2m_mmal_buffer eos_buffer;
++ bool eos_buffer_in_use; /* debug only */
++};
++
++enum {
++ V4L2_M2M_SRC = 0,
++ V4L2_M2M_DST = 1,
++};
++
++static inline struct bcm2835_codec_fmt_list *get_format_list(bool decode,
++ bool capture)
++{
++ return decode ^ capture ? &formats[ENCODED_LIST] : &formats[RAW_LIST];
++}
++
++static struct bcm2835_codec_fmt *get_default_format(bool decode, bool capture)
++{
++ return &get_format_list(decode, capture)->list[0];
++}
++
++static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f, bool decode,
++ bool capture)
++{
++ struct bcm2835_codec_fmt *fmt;
++ unsigned int k;
++ struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
++
++ for (k = 0; k < fmts->num_entries; k++) {
++ fmt = &fmts->list[k];
++ if (fmt->fourcc == f->fmt.pix.pixelformat)
++ break;
++ }
++
++ /*
++ * Some compressed formats are only supported for decoding, not
++ * encoding.
++ */
++ if (!decode && fmts->list[k].decode_only)
++ return NULL;
++
++ /* Some pixel formats are only supported for encoding, not decoding. */
++ if (decode && fmts->list[k].encode_only)
++ return NULL;
++
++ if (k == fmts->num_entries)
++ return NULL;
++
++ return &fmts->list[k];
++}
++
++struct bcm2835_codec_dev {
++ struct platform_device *pdev;
++
++ /* v4l2 devices */
++ struct v4l2_device v4l2_dev;
++ struct video_device vfd;
++ /* mutex for the v4l2 device */
++ struct mutex dev_mutex;
++ atomic_t num_inst;
++
++ /* allocated mmal instance and components */
++ bool decode; /* Is this instance a decoder? */
++ struct vchiq_mmal_instance *instance;
++
++ struct v4l2_m2m_dev *m2m_dev;
++};
++
++struct bcm2835_codec_ctx {
++ struct v4l2_fh fh;
++ struct bcm2835_codec_dev *dev;
++
++ struct v4l2_ctrl_handler hdl;
++
++ struct vchiq_mmal_component *component;
++ bool component_enabled;
++
++ enum v4l2_colorspace colorspace;
++ enum v4l2_ycbcr_encoding ycbcr_enc;
++ enum v4l2_xfer_func xfer_func;
++ enum v4l2_quantization quant;
++
++ /* Source and destination queue data */
++ struct bcm2835_codec_q_data q_data[2];
++ s32 bitrate;
++
++ bool aborting;
++ int num_ip_buffers;
++ int num_op_buffers;
++ struct completion frame_cmplt;
++};
++
++struct bcm2835_codec_driver {
++ struct bcm2835_codec_dev *encode;
++ struct bcm2835_codec_dev *decode;
++};
++
++static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
++{
++ return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
++}
++
++static struct bcm2835_codec_q_data *get_q_data(struct bcm2835_codec_ctx *ctx,
++ enum v4l2_buf_type type)
++{
++ switch (type) {
++ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
++ return &ctx->q_data[V4L2_M2M_SRC];
++ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++ return &ctx->q_data[V4L2_M2M_DST];
++ default:
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
++ __func__, type);
++ break;
++ }
++ return NULL;
++}
++
++static struct vchiq_mmal_port *get_port_data(struct bcm2835_codec_ctx *ctx,
++ enum v4l2_buf_type type)
++{
++ if (!ctx->component)
++ return NULL;
++
++ switch (type) {
++ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
++ return &ctx->component->input[0];
++ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++ return &ctx->component->output[0];
++ default:
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
++ __func__, type);
++ break;
++ }
++ return NULL;
++}
++
++/*
++ * mem2mem callbacks
++ */
++
++/**
++ * job_ready() - check whether an instance is ready to be scheduled to run
++ */
++static int job_ready(void *priv)
++{
++ struct bcm2835_codec_ctx *ctx = priv;
++
++ if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) &&
++ !v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx))
++ return 0;
++
++ return 1;
++}
++
++static void job_abort(void *priv)
++{
++ struct bcm2835_codec_ctx *ctx = priv;
++
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s\n", __func__);
++ /* Will cancel the transaction in the next interrupt handler */
++ ctx->aborting = 1;
++}
++
++static inline unsigned int get_sizeimage(int bpl, int height,
++ struct bcm2835_codec_fmt *fmt)
++{
++ return (bpl * height * fmt->size_multiplier_x2) >> 1;
++}
++
++static inline unsigned int get_bytesperline(int width,
++ struct bcm2835_codec_fmt *fmt)
++{
++ return ALIGN((width * fmt->depth) >> 3, fmt->bytesperline_align);
++}
++
++static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
++ bool decode,
++ struct bcm2835_codec_q_data *q_data,
++ struct vchiq_mmal_port *port)
++{
++ port->format.encoding = q_data->fmt->mmal_fmt;
++
++ if (!(q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED)) {
++ /* Raw image format - set width/height */
++ port->es.video.width = q_data->bytesperline /
++ (q_data->fmt->depth >> 3);
++ port->es.video.height = q_data->height;
++ port->es.video.crop.width = q_data->crop_width;
++ port->es.video.crop.height = q_data->crop_height;
++ port->es.video.frame_rate.num = 0;
++ port->es.video.frame_rate.den = 1;
++ } else {
++ /* Compressed format - leave resolution as 0 for decode */
++ if (decode) {
++ port->es.video.width = 0;
++ port->es.video.height = 0;
++ port->es.video.crop.width = 0;
++ port->es.video.crop.height = 0;
++ } else {
++ port->es.video.width = q_data->crop_width;
++ port->es.video.height = q_data->height;
++ port->es.video.crop.width = q_data->crop_width;
++ port->es.video.crop.height = q_data->crop_height;
++ port->format.bitrate = ctx->bitrate;
++ }
++ port->es.video.frame_rate.num = 0;
++ port->es.video.frame_rate.den = 1;
++ }
++ port->es.video.crop.x = 0;
++ port->es.video.crop.y = 0;
++
++ port->current_buffer.size = q_data->sizeimage;
++};
++
++static void ip_buffer_cb(struct vchiq_mmal_instance *instance,
++ struct vchiq_mmal_port *port, int status,
++ struct mmal_buffer *mmal_buf)
++{
++ struct bcm2835_codec_ctx *ctx = port->cb_ctx/*, *curr_ctx*/;
++ struct m2m_mmal_buffer *buf =
++ container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
++
++ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: port %p buf %p length %lu, flags %x\n",
++ __func__, port, mmal_buf, mmal_buf->length,
++ mmal_buf->mmal_flags);
++
++ if (buf == &ctx->q_data[V4L2_M2M_SRC].eos_buffer) {
++ /* Do we need to add lcoking to prevent multiple submission of
++ * the EOS, and therefore handle mutliple return here?
++ */
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: eos buffer returned.\n",
++ __func__);
++ ctx->q_data[V4L2_M2M_SRC].eos_buffer_in_use = false;
++ return;
++ }
++
++ if (status) {
++ /* error in transfer */
++ if (buf)
++ /* there was a buffer with the error so return it */
++ vb2_buffer_done(&buf->m2m.vb.vb2_buf,
++ VB2_BUF_STATE_ERROR);
++ return;
++ }
++ if (mmal_buf->cmd) {
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Not expecting cmd msgs on ip callback - %08x\n",
++ __func__, mmal_buf->cmd);
++ /*
++ * CHECKME: Should we return here. The buffer shouldn't have a
++ * message context or vb2 buf associated.
++ */
++ }
++
++ v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: no error. Return buffer %p\n",
++ __func__, &buf->m2m.vb.vb2_buf);
++ vb2_buffer_done(&buf->m2m.vb.vb2_buf, VB2_BUF_STATE_DONE);
++
++ ctx->num_ip_buffers++;
++ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: done %d input buffers\n",
++ __func__, ctx->num_ip_buffers);
++
++ if (!port->enabled)
++ complete(&ctx->frame_cmplt);
++}
++
++static void queue_res_chg_event(struct bcm2835_codec_ctx *ctx)
++{
++ static const struct v4l2_event ev_src_ch = {
++ .type = V4L2_EVENT_SOURCE_CHANGE,
++ .u.src_change.changes =
++ V4L2_EVENT_SRC_CH_RESOLUTION,
++ };
++
++ v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
++}
++
++static void send_eos_event(struct bcm2835_codec_ctx *ctx)
++{
++ static const struct v4l2_event ev = {
++ .type = V4L2_EVENT_EOS,
++ };
++
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Sending EOS event\n");
++
++ v4l2_event_queue_fh(&ctx->fh, &ev);
++}
++
++static void color_mmal2v4l(struct bcm2835_codec_ctx *ctx, u32 mmal_color_space)
++{
++ switch (mmal_color_space) {
++ case MMAL_COLOR_SPACE_ITUR_BT601:
++ ctx->colorspace = V4L2_COLORSPACE_REC709;
++ ctx->xfer_func = V4L2_XFER_FUNC_709;
++ ctx->ycbcr_enc = V4L2_YCBCR_ENC_601;
++ ctx->quant = V4L2_QUANTIZATION_LIM_RANGE;
++ break;
++
++ case MMAL_COLOR_SPACE_ITUR_BT709:
++ ctx->colorspace = V4L2_COLORSPACE_REC709;
++ ctx->xfer_func = V4L2_XFER_FUNC_709;
++ ctx->ycbcr_enc = V4L2_YCBCR_ENC_709;
++ ctx->quant = V4L2_QUANTIZATION_LIM_RANGE;
++ break;
++ }
++}
++
++static void handle_fmt_changed(struct bcm2835_codec_ctx *ctx,
++ struct mmal_buffer *mmal_buf)
++{
++ struct bcm2835_codec_q_data *q_data;
++ struct mmal_msg_event_format_changed *format =
++ (struct mmal_msg_event_format_changed *)mmal_buf->buffer;
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed: buff size min %u, rec %u, buff num min %u, rec %u\n",
++ __func__,
++ format->buffer_size_min,
++ format->buffer_size_recommended,
++ format->buffer_num_min,
++ format->buffer_num_recommended
++ );
++ if (format->format.type != MMAL_ES_TYPE_VIDEO) {
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed but not video %u\n",
++ __func__, format->format.type);
++ return;
++ }
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed to %ux%u, crop %ux%u, colourspace %08X\n",
++ __func__, format->es.video.width, format->es.video.height,
++ format->es.video.crop.width, format->es.video.crop.height,
++ format->es.video.color_space);
++
++ q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
++ q_data->crop_width = format->es.video.crop.width;
++ q_data->crop_height = format->es.video.crop.height;
++ q_data->bytesperline = format->es.video.crop.width;
++ q_data->height = format->es.video.height;
++ q_data->sizeimage = format->buffer_size_min;
++ if (format->es.video.color_space)
++ color_mmal2v4l(ctx, format->es.video.color_space);
++
++ queue_res_chg_event(ctx);
++}
++
++static void op_buffer_cb(struct vchiq_mmal_instance *instance,
++ struct vchiq_mmal_port *port, int status,
++ struct mmal_buffer *mmal_buf)
++{
++ struct bcm2835_codec_ctx *ctx = port->cb_ctx;
++ struct m2m_mmal_buffer *buf;
++ struct vb2_v4l2_buffer *vb2;
++
++ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev,
++ "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n",
++ __func__, status, mmal_buf, mmal_buf->length,
++ mmal_buf->mmal_flags, mmal_buf->pts);
++
++ if (status) {
++ /* error in transfer */
++ if (vb2) {
++ /* there was a buffer with the error so return it */
++ vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_ERROR);
++ }
++ return;
++ }
++
++ if (mmal_buf->cmd) {
++ switch (mmal_buf->cmd) {
++ case MMAL_EVENT_FORMAT_CHANGED:
++ {
++ handle_fmt_changed(ctx, mmal_buf);
++ break;
++ }
++ default:
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Unexpected event on output callback - %08x\n",
++ __func__, mmal_buf->cmd);
++ break;
++ }
++ return;
++ }
++
++ buf = container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
++ vb2 = &buf->m2m.vb;
++
++ v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: length %lu, flags %x, idx %u\n",
++ __func__, mmal_buf->length, mmal_buf->mmal_flags,
++ vb2->vb2_buf.index);
++
++ if (mmal_buf->length == 0) {
++ /* stream ended, or buffer being returned during disable. */
++ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: Empty buffer - flags %04x",
++ __func__, mmal_buf->mmal_flags);
++ if (!mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS) {
++ vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_ERROR);
++ if (!port->enabled)
++ complete(&ctx->frame_cmplt);
++ return;
++ }
++ }
++ if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS) {
++ /* EOS packet from the VPU */
++ send_eos_event(ctx);
++ vb2->flags |= V4L2_BUF_FLAG_LAST;
++ }
++
++ vb2->vb2_buf.timestamp = mmal_buf->pts;
++
++ vb2_set_plane_payload(&vb2->vb2_buf, 0, mmal_buf->length);
++ if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
++ vb2->flags |= V4L2_BUF_FLAG_KEYFRAME;
++
++ vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_DONE);
++ ctx->num_op_buffers++;
++
++ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: done %d output buffers\n",
++ __func__, ctx->num_op_buffers);
++
++ if (!port->enabled)
++ complete(&ctx->frame_cmplt);
++}
++
++/* vb2_to_mmal_buffer() - converts vb2 buffer header to MMAL
++ *
++ * Copies all the required fields from a VB2 buffer to the MMAL buffer header,
++ * ready for sending to the VPU.
++ */
++static void vb2_to_mmal_buffer(struct m2m_mmal_buffer *buf,
++ struct vb2_v4l2_buffer *vb2)
++{
++ buf->mmal.mmal_flags = 0;
++ if (vb2->flags & V4L2_BUF_FLAG_KEYFRAME)
++ buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_KEYFRAME;
++
++ /*
++ * Adding this means that the data must be framed correctly as one frame
++ * per buffer. The underlying decoder has no such requirement, but it
++ * will reduce latency as the bistream parser will be kicked immediately
++ * to parse the frame, rather than relying on its own heuristics for
++ * when to wake up.
++ */
++ buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;
++
++ buf->mmal.length = vb2->vb2_buf.planes[0].bytesused;
++ /*
++ * Minor ambiguity in the V4L2 spec as to whether passing in a 0 length
++ * buffer, or one with V4L2_BUF_FLAG_LAST set denotes end of stream.
++ * Handle either.
++ */
++ if (!buf->mmal.length || vb2->flags & V4L2_BUF_FLAG_LAST)
++ buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
++
++ buf->mmal.pts = vb2->vb2_buf.timestamp;
++ buf->mmal.dts = MMAL_TIME_UNKNOWN;
++}
++
++/* device_run() - prepares and starts the device
++ *
++ * This simulates all the immediate preparations required before starting
++ * a device. This will be called by the framework when it decides to schedule
++ * a particular instance.
++ */
++static void device_run(void *priv)
++{
++ struct bcm2835_codec_ctx *ctx = priv;
++ struct bcm2835_codec_dev *dev = ctx->dev;
++ struct vb2_v4l2_buffer *src_buf, *dst_buf;
++ struct m2m_mmal_buffer *src_m2m_buf, *dst_m2m_buf;
++ struct v4l2_m2m_buffer *m2m;
++ int ret;
++
++ v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: off we go\n", __func__);
++
++ src_buf = v4l2_m2m_buf_remove(&ctx->fh.m2m_ctx->out_q_ctx);
++ if (src_buf) {
++ m2m = container_of(src_buf, struct v4l2_m2m_buffer, vb);
++ src_m2m_buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
++ vb2_to_mmal_buffer(src_m2m_buf, src_buf);
++
++ ret = vchiq_mmal_submit_buffer(dev->instance,
++ &ctx->component->input[0],
++ &src_m2m_buf->mmal);
++ v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: Submitted ip buffer len %lu, pts %llu, flags %04x\n",
++ __func__, src_m2m_buf->mmal.length,
++ src_m2m_buf->mmal.pts, src_m2m_buf->mmal.mmal_flags);
++ if (ret)
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed submitting ip buffer\n",
++ __func__);
++ }
++
++ dst_buf = v4l2_m2m_buf_remove(&ctx->fh.m2m_ctx->cap_q_ctx);
++ if (dst_buf) {
++ m2m = container_of(dst_buf, struct v4l2_m2m_buffer, vb);
++ dst_m2m_buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
++ vb2_to_mmal_buffer(dst_m2m_buf, dst_buf);
++
++ ret = vchiq_mmal_submit_buffer(dev->instance,
++ &ctx->component->output[0],
++ &dst_m2m_buf->mmal);
++ if (ret)
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed submitting op buffer\n",
++ __func__);
++ }
++
++ v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: Submitted src %p, dst %p\n",
++ __func__, src_m2m_buf, dst_m2m_buf);
++
++ /* Complete the job here. */
++ v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
++}
++
++/*
++ * video ioctls
++ */
++static int vidioc_querycap(struct file *file, void *priv,
++ struct v4l2_capability *cap)
++{
++ strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
++ strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
++ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
++ MEM2MEM_NAME);
++ cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
++ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
++ return 0;
++}
++
++static int enum_fmt(struct v4l2_fmtdesc *f, bool decode, bool capture)
++{
++ struct bcm2835_codec_fmt *fmt;
++ struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
++
++ if (f->index < fmts->num_entries) {
++ /* Format found */
++ /* Check format isn't a decode only format when encoding */
++ if (!decode &&
++ fmts->list[f->index].decode_only)
++ return -EINVAL;
++ /* Check format isn't a decode only format when encoding */
++ if (decode &&
++ fmts->list[f->index].encode_only)
++ return -EINVAL;
++
++ fmt = &fmts->list[f->index];
++ f->pixelformat = fmt->fourcc;
++ f->flags = fmt->flags;
++ return 0;
++ }
++
++ /* Format not found */
++ return -EINVAL;
++}
++
++static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
++ struct v4l2_fmtdesc *f)
++{
++ struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++ return enum_fmt(f, ctx->dev->decode, true);
++}
++
++static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
++ struct v4l2_fmtdesc *f)
++{
++ struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++ return enum_fmt(f, ctx->dev->decode, false);
++}
++
++static int vidioc_g_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f)
++{
++ struct vb2_queue *vq;
++ struct bcm2835_codec_q_data *q_data;
++
++ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
++ if (!vq)
++ return -EINVAL;
++
++ q_data = get_q_data(ctx, f->type);
++
++ f->fmt.pix.width = q_data->crop_width;
++ f->fmt.pix.height = q_data->height;
++ f->fmt.pix.field = V4L2_FIELD_NONE;
++ f->fmt.pix.pixelformat = q_data->fmt->fourcc;
++ f->fmt.pix.bytesperline = q_data->bytesperline;
++ f->fmt.pix.sizeimage = q_data->sizeimage;
++ f->fmt.pix.colorspace = ctx->colorspace;
++ f->fmt.pix.xfer_func = ctx->xfer_func;
++ f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc;
++ f->fmt.pix.quantization = ctx->quant;
++
++ return 0;
++}
++
++static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
++ struct v4l2_format *f)
++{
++ return vidioc_g_fmt(file2ctx(file), f);
++}
++
++static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
++ struct v4l2_format *f)
++{
++ return vidioc_g_fmt(file2ctx(file), f);
++}
++
++static int vidioc_try_fmt(struct v4l2_format *f, struct bcm2835_codec_fmt *fmt)
++{
++ /*
++ * The V4L2 specification requires the driver to correct the format
++ * struct if any of the dimensions is unsupported
++ */
++ if (f->fmt.pix.width > MAX_W)
++ f->fmt.pix.width = MAX_W;
++ if (f->fmt.pix.height > MAX_H)
++ f->fmt.pix.height = MAX_H;
++
++ if (!fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
++ /* Only clip min w/h on capture. Treat 0x0 as unknown. */
++ if (f->fmt.pix.width < MIN_W)
++ f->fmt.pix.width = MIN_W;
++ if (f->fmt.pix.height < MIN_H)
++ f->fmt.pix.height = MIN_H;
++
++ /*
++ * Buffer must have a vertical alignment of 16 lines.
++ * The selection will reflect any cropping rectangle when only
++ * some of the pixels are active.
++ */
++ f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
++
++ f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
++ fmt);
++ f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
++ f->fmt.pix.height,
++ fmt);
++ } else {
++ u32 min_size = f->fmt.pix.width > 1280 ||
++ f->fmt.pix.height > 720 ?
++ DEF_COMP_BUF_SIZE_GREATER_720P :
++ DEF_COMP_BUF_SIZE_720P_OR_LESS;
++
++ f->fmt.pix.bytesperline = 0;
++ if (f->fmt.pix.sizeimage < min_size)
++ f->fmt.pix.sizeimage = min_size;
++ }
++
++ f->fmt.pix.field = V4L2_FIELD_NONE;
++
++ return 0;
++}
++
++static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
++ struct v4l2_format *f)
++{
++ struct bcm2835_codec_fmt *fmt;
++ struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++ fmt = find_format(f, ctx->dev->decode, true);
++ if (!fmt) {
++ f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
++ true)->fourcc;
++ fmt = find_format(f, ctx->dev->decode, true);
++ }
++
++ return vidioc_try_fmt(f, fmt);
++}
++
++static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
++ struct v4l2_format *f)
++{
++ struct bcm2835_codec_fmt *fmt;
++ struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++ fmt = find_format(f, ctx->dev->decode, false);
++ if (!fmt) {
++ f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
++ false)->fourcc;
++ fmt = find_format(f, ctx->dev->decode, false);
++ }
++
++ if (!f->fmt.pix.colorspace)
++ f->fmt.pix.colorspace = ctx->colorspace;
++
++ return vidioc_try_fmt(f, fmt);
++}
++
++static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
++ unsigned int requested_height)
++{
++ struct bcm2835_codec_q_data *q_data;
++ struct vb2_queue *vq;
++ struct vchiq_mmal_port *port;
++ bool update_capture_port = false;
++ int ret;
++
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
++ f->type, f->fmt.pix.width, f->fmt.pix.height,
++ f->fmt.pix.pixelformat, f->fmt.pix.sizeimage);
++
++ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
++ if (!vq)
++ return -EINVAL;
++
++ q_data = get_q_data(ctx, f->type);
++ if (!q_data)
++ return -EINVAL;
++
++ if (vb2_is_busy(vq)) {
++ v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
++ return -EBUSY;
++ }
++
++ q_data->fmt = find_format(f, ctx->dev->decode,
++ f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
++ q_data->crop_width = f->fmt.pix.width;
++ q_data->height = f->fmt.pix.height;
++ if (!q_data->selection_set)
++ q_data->crop_height = requested_height;
++
++ /*
++ * Copying the behaviour of vicodec which retains a single set of
++ * colorspace parameters for both input and output.
++ */
++ ctx->colorspace = f->fmt.pix.colorspace;
++ ctx->xfer_func = f->fmt.pix.xfer_func;
++ ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
++ ctx->quant = f->fmt.pix.quantization;
++
++ /* All parameters should have been set correctly by try_fmt */
++ q_data->bytesperline = f->fmt.pix.bytesperline;
++ q_data->sizeimage = f->fmt.pix.sizeimage;
++
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
++ q_data->bytesperline, q_data->sizeimage);
++
++ if (ctx->dev->decode && q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
++ f->fmt.pix.width && f->fmt.pix.height) {
++ /*
++ * On the decoder, if provided with a resolution on the input
++ * side, then replicate that to the output side.
++ * GStreamer appears not to support V4L2_EVENT_SOURCE_CHANGE,
++ * nor set up a resolution on the output side, therefore
++ * we can't decode anything at a resolution other than the
++ * default one.
++ */
++ struct bcm2835_codec_q_data *q_data_dst =
++ &ctx->q_data[V4L2_M2M_DST];
++
++ q_data_dst->crop_width = q_data->crop_width;
++ q_data_dst->crop_height = q_data->crop_height;
++ q_data_dst->height = ALIGN(q_data->crop_height, 16);
++
++ q_data_dst->bytesperline =
++ get_bytesperline(f->fmt.pix.width, q_data_dst->fmt);
++ q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
++ q_data_dst->height,
++ q_data_dst->fmt);
++ update_capture_port = true;
++ }
++
++ /* If we have a component then setup the port as well */
++ port = get_port_data(ctx, vq->type);
++ if (!port)
++ return 0;
++
++ setup_mmal_port_format(ctx, ctx->dev->decode, q_data, port);
++ ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
++ if (ret) {
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on port, ret %d\n",
++ __func__, ret);
++ ret = -EINVAL;
++ }
++
++ if (q_data->sizeimage < port->minimum_buffer.size) {
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Current buffer size of %u < min buf size %u - driver mismatch to MMAL\n",
++ __func__, q_data->sizeimage,
++ port->minimum_buffer.size);
++ }
++
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Set format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
++ f->type, q_data->crop_width, q_data->height,
++ q_data->fmt->fourcc, q_data->sizeimage);
++
++ if (update_capture_port) {
++ struct vchiq_mmal_port *port_dst = &ctx->component->output[0];
++ struct bcm2835_codec_q_data *q_data_dst =
++ &ctx->q_data[V4L2_M2M_DST];
++
++ setup_mmal_port_format(ctx, ctx->dev->decode, q_data_dst,
++ port_dst);
++ ret = vchiq_mmal_port_set_format(ctx->dev->instance, port_dst);
++ if (ret) {
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on output port, ret %d\n",
++ __func__, ret);
++ ret = -EINVAL;
++ }
++ }
++ return ret;
++}
++
++static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
++ struct v4l2_format *f)
++{
++ unsigned int height = f->fmt.pix.height;
++ int ret;
++
++ ret = vidioc_try_fmt_vid_cap(file, priv, f);
++ if (ret)
++ return ret;
++
++ return vidioc_s_fmt(file2ctx(file), f, height);
++}
++
++static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
++ struct v4l2_format *f)
++{
++ unsigned int height = f->fmt.pix.height;
++ int ret;
++
++ ret = vidioc_try_fmt_vid_out(file, priv, f);
++ if (ret)
++ return ret;
++
++ ret = vidioc_s_fmt(file2ctx(file), f, height);
++ return ret;
++}
++
++static int vidioc_g_selection(struct file *file, void *priv,
++ struct v4l2_selection *s)
++{
++ struct bcm2835_codec_ctx *ctx = file2ctx(file);
++ struct bcm2835_codec_q_data *q_data;
++ bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
++ true : false;
++
++ if (capture_queue ^ ctx->dev->decode)
++ /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
++ return -EINVAL;
++
++ q_data = get_q_data(ctx, s->type);
++ if (!q_data)
++ return -EINVAL;
++
++ if (ctx->dev->decode) {
++ switch (s->target) {
++ case V4L2_SEL_TGT_COMPOSE_DEFAULT:
++ case V4L2_SEL_TGT_COMPOSE:
++ s->r.left = 0;
++ s->r.top = 0;
++ s->r.width = q_data->crop_width;
++ s->r.height = q_data->crop_height;
++ break;
++ case V4L2_SEL_TGT_COMPOSE_BOUNDS:
++ s->r.left = 0;
++ s->r.top = 0;
++ s->r.width = q_data->crop_width;
++ s->r.height = q_data->crop_height;
++ break;
++ default:
++ return -EINVAL;
++ }
++ } else {
++ switch (s->target) {
++ case V4L2_SEL_TGT_CROP_DEFAULT:
++ case V4L2_SEL_TGT_CROP_BOUNDS:
++ s->r.top = 0;
++ s->r.left = 0;
++ s->r.width = q_data->bytesperline;
++ s->r.height = q_data->height;
++ break;
++ case V4L2_SEL_TGT_CROP:
++ s->r.top = 0;
++ s->r.left = 0;
++ s->r.width = q_data->crop_width;
++ s->r.height = q_data->crop_height;
++ break;
++ default:
++ return -EINVAL;
++ }
++ }
++
++ return 0;
++}
++
++static int vidioc_s_selection(struct file *file, void *priv,
++ struct v4l2_selection *s)
++{
++ struct bcm2835_codec_ctx *ctx = file2ctx(file);
++ struct bcm2835_codec_q_data *q_data = NULL;
++ bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
++ true : false;
++
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: ctx %p, type %d, q_data %p, target %d, rect x/y %d/%d, w/h %ux%u\n",
++ __func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
++ s->r.width, s->r.height);
++
++ if (capture_queue ^ ctx->dev->decode)
++ /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
++ return -EINVAL;
++
++ q_data = get_q_data(ctx, s->type);
++ if (!q_data)
++ return -EINVAL;
++
++ if (ctx->dev->decode) {
++ switch (s->target) {
++ case V4L2_SEL_TGT_COMPOSE:
++ /* Accept cropped image */
++ s->r.left = 0;
++ s->r.top = 0;
++ s->r.width = min(s->r.width, q_data->crop_width);
++ s->r.height = min(s->r.height, q_data->height);
++ q_data->crop_width = s->r.width;
++ q_data->crop_height = s->r.height;
++ q_data->selection_set = true;
++ break;
++ default:
++ return -EINVAL;
++ }
++ } else {
++ switch (s->target) {
++ case V4L2_SEL_TGT_CROP:
++ /* Only support crop from (0,0) */
++ s->r.top = 0;
++ s->r.left = 0;
++ s->r.width = min(s->r.width, q_data->crop_width);
++ s->r.height = min(s->r.height, q_data->crop_height);
++ q_data->crop_width = s->r.width;
++ q_data->crop_height = s->r.height;
++ q_data->selection_set = true;
++ break;
++ default:
++ return -EINVAL;
++ }
++ }
++
++ return 0;
++}
++
++static int vidioc_subscribe_evt(struct v4l2_fh *fh,
++ const struct v4l2_event_subscription *sub)
++{
++ switch (sub->type) {
++ case V4L2_EVENT_EOS:
++ return v4l2_event_subscribe(fh, sub, 2, NULL);
++ case V4L2_EVENT_SOURCE_CHANGE:
++ return v4l2_src_change_event_subscribe(fh, sub);
++ default:
++ return v4l2_ctrl_subscribe_event(fh, sub);
++ }
++}
++
++static int bcm2835_codec_set_level_profile(struct bcm2835_codec_ctx *ctx,
++ struct v4l2_ctrl *ctrl)
++{
++ struct mmal_parameter_video_profile param;
++ int param_size = sizeof(param);
++ int ret;
++
++ /*
++ * Level and Profile are set via the same MMAL parameter.
++ * Retrieve the current settings and amend the one that has changed.
++ */
++ ret = vchiq_mmal_port_parameter_get(ctx->dev->instance,
++ &ctx->component->output[0],
++ MMAL_PARAMETER_PROFILE,
++ ¶m,
++ ¶m_size);
++ if (ret)
++ return ret;
++
++ switch (ctrl->id) {
++ case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
++ switch (ctrl->val) {
++ 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;
++ }
++ break;
++
++ case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
++ switch (ctrl->val) {
++ 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(ctx->dev->instance,
++ &ctx->component->output[0],
++ MMAL_PARAMETER_PROFILE,
++ ¶m,
++ param_size);
++
++ return ret;
++}
++
++static int bcm2835_codec_s_ctrl(struct v4l2_ctrl *ctrl)
++{
++ struct bcm2835_codec_ctx *ctx =
++ container_of(ctrl->handler, struct bcm2835_codec_ctx, hdl);
++ int ret = 0;
++
++ switch (ctrl->id) {
++ case V4L2_CID_MPEG_VIDEO_BITRATE:
++ ctx->bitrate = ctrl->val;
++ if (!ctx->component)
++ break;
++
++ ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
++ &ctx->component->output[0],
++ MMAL_PARAMETER_VIDEO_BIT_RATE,
++ &ctrl->val,
++ sizeof(ctrl->val));
++ break;
++
++ case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: {
++ u32 bitrate_mode;
++
++ if (!ctx->component)
++ break;
++
++ 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;
++ }
++
++ ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
++ &ctx->component->output[0],
++ MMAL_PARAMETER_RATECONTROL,
++ &bitrate_mode,
++ sizeof(bitrate_mode));
++ break;
++ }
++ case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:
++ if (!ctx->component)
++ break;
++
++ ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
++ &ctx->component->output[0],
++ MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
++ &ctrl->val,
++ sizeof(ctrl->val));
++ break;
++
++ case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
++ if (!ctx->component)
++ break;
++
++ ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
++ &ctx->component->output[0],
++ MMAL_PARAMETER_INTRAPERIOD,
++ &ctrl->val,
++ sizeof(ctrl->val));
++ break;
++
++ case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
++ case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
++ if (!ctx->component)
++ break;
++
++ ret = bcm2835_codec_set_level_profile(ctx, ctrl);
++ break;
++
++ default:
++ v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
++ return -EINVAL;
++ }
++
++ if (ret)
++ v4l2_err(&ctx->dev->v4l2_dev, "Failed setting ctrl %08x, ret %d\n",
++ ctrl->id, ret);
++ return ret ? -EINVAL : 0;
++}
++
++static const struct v4l2_ctrl_ops bcm2835_codec_ctrl_ops = {
++ .s_ctrl = bcm2835_codec_s_ctrl,
++};
++
++static int vidioc_try_decoder_cmd(struct file *file, void *priv,
++ struct v4l2_decoder_cmd *cmd)
++{
++ struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++ if (!ctx->dev->decode)
++ return -EINVAL;
++
++ switch (cmd->cmd) {
++ case V4L2_DEC_CMD_STOP:
++ if (cmd->flags & V4L2_DEC_CMD_STOP_TO_BLACK) {
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: DEC cmd->flags=%u stop to black not supported",
++ __func__, cmd->flags);
++ return -EINVAL;
++ }
++ break;
++ case V4L2_DEC_CMD_START:
++ break;
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int vidioc_decoder_cmd(struct file *file, void *priv,
++ struct v4l2_decoder_cmd *cmd)
++{
++ struct bcm2835_codec_ctx *ctx = file2ctx(file);
++ struct bcm2835_codec_q_data *q_data = &ctx->q_data[V4L2_M2M_SRC];
++ int ret;
++
++ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s, cmd %u", __func__,
++ cmd->cmd);
++ ret = vidioc_try_decoder_cmd(file, priv, cmd);
++ if (ret)
++ return ret;
++
++ switch (cmd->cmd) {
++ case V4L2_DEC_CMD_STOP:
++ if (q_data->eos_buffer_in_use)
++ v4l2_err(&ctx->dev->v4l2_dev, "EOS buffers already in use\n");
++ q_data->eos_buffer_in_use = true;
++
++ q_data->eos_buffer.mmal.buffer_size = 0;
++ q_data->eos_buffer.mmal.length = 0;
++ q_data->eos_buffer.mmal.mmal_flags =
++ MMAL_BUFFER_HEADER_FLAG_EOS;
++ q_data->eos_buffer.mmal.pts = 0;
++ q_data->eos_buffer.mmal.dts = 0;
++
++ if (!ctx->component)
++ break;
++
++ ret = vchiq_mmal_submit_buffer(ctx->dev->instance,
++ &ctx->component->input[0],
++ &q_data->eos_buffer.mmal);
++ if (ret)
++ v4l2_err(&ctx->dev->v4l2_dev,
++ "%s: EOS buffer submit failed %d\n",
++ __func__, ret);
++
++ break;
++
++ case V4L2_DEC_CMD_START:
++ /* Do we need to do anything here? */
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int vidioc_try_encoder_cmd(struct file *file, void *priv,
++ struct v4l2_encoder_cmd *cmd)
++{
++ struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++ if (ctx->dev->decode)
++ return -EINVAL;
++
++ switch (cmd->cmd) {
++ case V4L2_ENC_CMD_STOP:
++ break;
++
++ case V4L2_ENC_CMD_START:
++ /* Do we need to do anything here? */
++ break;
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int vidioc_encoder_cmd(struct file *file, void *priv,
++ struct v4l2_encoder_cmd *cmd)
++{
++ struct bcm2835_codec_ctx *ctx = file2ctx(file);
++ struct bcm2835_codec_q_data *q_data = &ctx->q_data[V4L2_M2M_SRC];
++ int ret;
++
++ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s, cmd %u", __func__,
++ cmd->cmd);
++ ret = vidioc_try_encoder_cmd(file, priv, cmd);
++ if (ret)
++ return ret;
++
++ switch (cmd->cmd) {
++ case V4L2_ENC_CMD_STOP:
++ if (q_data->eos_buffer_in_use)
++ v4l2_err(&ctx->dev->v4l2_dev, "EOS buffers already in use\n");
++ q_data->eos_buffer_in_use = true;
++
++ q_data->eos_buffer.mmal.buffer_size = 0;
++ q_data->eos_buffer.mmal.length = 0;
++ q_data->eos_buffer.mmal.mmal_flags =
++ MMAL_BUFFER_HEADER_FLAG_EOS;
++ q_data->eos_buffer.mmal.pts = 0;
++ q_data->eos_buffer.mmal.dts = 0;
++
++ if (!ctx->component)
++ break;
++
++ ret = vchiq_mmal_submit_buffer(ctx->dev->instance,
++ &ctx->component->input[0],
++ &q_data->eos_buffer.mmal);
++ if (ret)
++ v4l2_err(&ctx->dev->v4l2_dev,
++ "%s: EOS buffer submit failed %d\n",
++ __func__, ret);
++
++ break;
++ case V4L2_ENC_CMD_START:
++ /* Do we need to do anything here? */
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static const struct v4l2_ioctl_ops bcm2835_codec_ioctl_ops = {
++ .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,
++
++ .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
++ .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out,
++ .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
++ .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
++
++ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
++ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
++ .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
++ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
++ .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
++ .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
++ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
++
++ .vidioc_streamon = v4l2_m2m_ioctl_streamon,
++ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
++
++ .vidioc_g_selection = vidioc_g_selection,
++ .vidioc_s_selection = vidioc_s_selection,
++
++ .vidioc_subscribe_event = vidioc_subscribe_evt,
++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
++
++ .vidioc_decoder_cmd = vidioc_decoder_cmd,
++ .vidioc_try_decoder_cmd = vidioc_try_decoder_cmd,
++ .vidioc_encoder_cmd = vidioc_encoder_cmd,
++ .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd,
++};
++
++static int bcm2835_codec_set_ctrls(struct bcm2835_codec_ctx *ctx)
++{
++ /*
++ * Query the control handler for the value of the various controls and
++ * set them.
++ */
++ const u32 control_ids[] = {
++ V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
++ V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER,
++ V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
++ V4L2_CID_MPEG_VIDEO_H264_LEVEL,
++ V4L2_CID_MPEG_VIDEO_H264_PROFILE,
++ };
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(control_ids); i++) {
++ struct v4l2_ctrl *ctrl;
++
++ ctrl = v4l2_ctrl_find(&ctx->hdl, control_ids[i]);
++ if (ctrl)
++ bcm2835_codec_s_ctrl(ctrl);
++ }
++
++ return 0;
++}
++
++static int bcm2835_codec_create_component(struct bcm2835_codec_ctx *ctx)
++{
++ struct bcm2835_codec_dev *dev = ctx->dev;
++ unsigned int enable = 1;
++ int ret;
++
++ ret = vchiq_mmal_component_init(dev->instance, dev->decode ?
++ "ril.video_decode" : "ril.video_encode",
++ &ctx->component);
++ if (ret < 0) {
++ v4l2_err(&dev->v4l2_dev, "%s: failed to create component for %s\n",
++ __func__, dev->decode ? "decode" : "encode");
++ return -ENOMEM;
++ }
++
++ vchiq_mmal_port_parameter_set(dev->instance, &ctx->component->input[0],
++ MMAL_PARAMETER_ZERO_COPY, &enable,
++ sizeof(enable));
++ vchiq_mmal_port_parameter_set(dev->instance, &ctx->component->output[0],
++ MMAL_PARAMETER_ZERO_COPY, &enable,
++ sizeof(enable));
++
++ setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_SRC],
++ &ctx->component->input[0]);
++
++ setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_DST],
++ &ctx->component->output[0]);
++
++ ret = vchiq_mmal_port_set_format(dev->instance,
++ &ctx->component->input[0]);
++ if (ret < 0)
++ goto destroy_component;
++
++ ret = vchiq_mmal_port_set_format(dev->instance,
++ &ctx->component->output[0]);
++ if (ret < 0)
++ goto destroy_component;
++
++ if (dev->decode) {
++ if (ctx->q_data[V4L2_M2M_DST].sizeimage <
++ ctx->component->output[0].minimum_buffer.size)
++ v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
++ ctx->q_data[V4L2_M2M_DST].sizeimage,
++ ctx->component->output[0].minimum_buffer.size);
++ } else {
++ if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
++ ctx->component->output[0].minimum_buffer.size)
++ v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
++ ctx->q_data[V4L2_M2M_SRC].sizeimage,
++ ctx->component->output[0].minimum_buffer.size);
++
++ /* Now we have a component we can set all the ctrls */
++ bcm2835_codec_set_ctrls(ctx);
++ }
++
++ return 0;
++
++destroy_component:
++ vchiq_mmal_component_finalise(ctx->dev->instance, ctx->component);
++
++ return ret;
++}
++
++/*
++ * Queue operations
++ */
++
++static int bcm2835_codec_queue_setup(struct vb2_queue *vq,
++ unsigned int *nbuffers,
++ unsigned int *nplanes,
++ unsigned int sizes[],
++ struct device *alloc_devs[])
++{
++ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vq);
++ struct bcm2835_codec_q_data *q_data;
++ struct vchiq_mmal_port *port;
++ unsigned int size;
++
++ q_data = get_q_data(ctx, vq->type);
++ if (!q_data)
++ return -EINVAL;
++
++ if (!ctx->component)
++ if (bcm2835_codec_create_component(ctx))
++ return -EINVAL;
++
++ port = get_port_data(ctx, vq->type);
++
++ size = q_data->sizeimage;
++
++ if (*nplanes)
++ return sizes[0] < size ? -EINVAL : 0;
++
++ *nplanes = 1;
++
++ sizes[0] = size;
++ port->current_buffer.size = size;
++
++ if (*nbuffers < port->minimum_buffer.num)
++ *nbuffers = port->minimum_buffer.num;
++ /* Add one buffer to take an EOS */
++ port->current_buffer.num = *nbuffers + 1;
++
++ return 0;
++}
++
++static int bcm2835_codec_buf_init(struct vb2_buffer *vb)
++{
++ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
++ struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
++ struct v4l2_m2m_buffer *m2m = container_of(vb2, struct v4l2_m2m_buffer,
++ vb);
++ struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
++ m2m);
++
++ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
++ __func__, ctx, vb);
++ buf->mmal.buffer = vb2_plane_vaddr(&buf->m2m.vb.vb2_buf, 0);
++ buf->mmal.buffer_size = vb2_plane_size(&buf->m2m.vb.vb2_buf, 0);
++
++ mmal_vchi_buffer_init(ctx->dev->instance, &buf->mmal);
++
++ return 0;
++}
++
++static int bcm2835_codec_buf_prepare(struct vb2_buffer *vb)
++{
++ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
++ struct bcm2835_codec_q_data *q_data;
++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
++ struct v4l2_m2m_buffer *m2m = container_of(vbuf, struct v4l2_m2m_buffer,
++ vb);
++ struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
++ m2m);
++ int ret;
++
++ v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p\n",
++ __func__, vb->vb2_queue->type, vb);
++
++ q_data = get_q_data(ctx, vb->vb2_queue->type);
++ if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
++ if (vbuf->field == V4L2_FIELD_ANY)
++ vbuf->field = V4L2_FIELD_NONE;
++ if (vbuf->field != V4L2_FIELD_NONE) {
++ v4l2_err(&ctx->dev->v4l2_dev, "%s field isn't supported\n",
++ __func__);
++ return -EINVAL;
++ }
++ }
++
++ if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
++ v4l2_err(&ctx->dev->v4l2_dev, "%s data will not fit into plane (%lu < %lu)\n",
++ __func__, vb2_plane_size(vb, 0),
++ (long)q_data->sizeimage);
++ return -EINVAL;
++ }
++
++ if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
++ vb2_set_plane_payload(vb, 0, q_data->sizeimage);
++
++ /*
++ * We want to do this at init, but vb2_core_expbuf checks that the
++ * index < q->num_buffers, and q->num_buffers only gets updated once
++ * all the buffers are allocated.
++ */
++ if (!buf->mmal.dma_buf) {
++ ret = vb2_core_expbuf_dmabuf(vb->vb2_queue,
++ vb->vb2_queue->type, vb->index, 0,
++ O_CLOEXEC, &buf->mmal.dma_buf);
++ if (ret)
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed to expbuf idx %d, ret %d\n",
++ __func__, vb->index, ret);
++ } else {
++ ret = 0;
++ }
++
++ return ret;
++}
++
++static void bcm2835_codec_buf_queue(struct vb2_buffer *vb)
++{
++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
++ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
++
++ v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p vbuf->flags %u, seq %u, bytesused %u\n",
++ __func__, vb->vb2_queue->type, vb, vbuf->flags, vbuf->sequence,
++ vb->planes[0].bytesused);
++ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
++}
++
++static void bcm2835_codec_buffer_cleanup(struct vb2_buffer *vb)
++{
++ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
++ struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
++ struct v4l2_m2m_buffer *m2m = container_of(vb2, struct v4l2_m2m_buffer,
++ vb);
++ struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
++ m2m);
++
++ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
++ __func__, ctx, vb);
++
++ mmal_vchi_buffer_cleanup(&buf->mmal);
++
++ if (buf->mmal.dma_buf) {
++ dma_buf_put(buf->mmal.dma_buf);
++ buf->mmal.dma_buf = NULL;
++ }
++}
++
++static int bcm2835_codec_start_streaming(struct vb2_queue *q,
++ unsigned int count)
++{
++ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(q);
++ struct bcm2835_codec_dev *dev = ctx->dev;
++ struct bcm2835_codec_q_data *q_data = get_q_data(ctx, q->type);
++ int ret;
++
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d count %d\n",
++ __func__, q->type, count);
++ q_data->sequence = 0;
++
++ if (!ctx->component_enabled) {
++ ret = vchiq_mmal_component_enable(dev->instance,
++ ctx->component);
++ if (ret)
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling component, ret %d\n",
++ __func__, ret);
++ ctx->component_enabled = true;
++ }
++
++ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
++ /*
++ * Create the EOS buffer.
++ * We only need the MMAL part, and want to NOT attach a memory
++ * buffer to it as it should only take flags.
++ */
++ memset(&q_data->eos_buffer, 0, sizeof(q_data->eos_buffer));
++ mmal_vchi_buffer_init(dev->instance,
++ &q_data->eos_buffer.mmal);
++ q_data->eos_buffer_in_use = false;
++
++ ctx->component->input[0].cb_ctx = ctx;
++ ret = vchiq_mmal_port_enable(dev->instance,
++ &ctx->component->input[0],
++ ip_buffer_cb);
++ if (ret)
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling i/p port, ret %d\n",
++ __func__, ret);
++ } else {
++ ctx->component->output[0].cb_ctx = ctx;
++ ret = vchiq_mmal_port_enable(dev->instance,
++ &ctx->component->output[0],
++ op_buffer_cb);
++ if (ret)
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
++ __func__, ret);
++ }
++ return ret;
++}
++
++static void bcm2835_codec_stop_streaming(struct vb2_queue *q)
++{
++ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(q);
++ struct bcm2835_codec_dev *dev = ctx->dev;
++ struct bcm2835_codec_q_data *q_data = get_q_data(ctx, q->type);
++ struct vchiq_mmal_port *port = get_port_data(ctx, q->type);
++ struct vb2_v4l2_buffer *vbuf;
++ struct vb2_v4l2_buffer *vb2;
++ struct v4l2_m2m_buffer *m2m;
++ struct m2m_mmal_buffer *buf;
++ int ret, i;
++
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d - return buffers\n",
++ __func__, q->type);
++
++ init_completion(&ctx->frame_cmplt);
++
++ /* Clear out all buffers held by m2m framework */
++ for (;;) {
++ if (V4L2_TYPE_IS_OUTPUT(q->type))
++ vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
++ else
++ vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
++ if (!vbuf)
++ break;
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: return buffer %p\n",
++ __func__, vbuf);
++
++ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
++ }
++
++ /* Disable MMAL port - this will flush buffers back */
++ ret = vchiq_mmal_port_disable(dev->instance, port);
++ if (ret)
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed disabling %s port, ret %d\n",
++ __func__, V4L2_TYPE_IS_OUTPUT(q->type) ? "i/p" : "o/p",
++ ret);
++
++ while (atomic_read(&port->buffers_with_vpu)) {
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Waiting for buffers to be returned - %d outstanding\n",
++ __func__, atomic_read(&port->buffers_with_vpu));
++ ret = wait_for_completion_timeout(&ctx->frame_cmplt, HZ);
++ if (ret <= 0) {
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n",
++ __func__,
++ atomic_read(&port->buffers_with_vpu));
++ break;
++ }
++ }
++
++ /*
++ * Release the VCSM handle here as otherwise REQBUFS(0) aborts because
++ * someone is using the dmabuf before giving the driver a chance to do
++ * anything about it.
++ */
++ for (i = 0; i < q->num_buffers; i++) {
++ vb2 = to_vb2_v4l2_buffer(q->bufs[i]);
++ m2m = container_of(vb2, struct v4l2_m2m_buffer, vb);
++ buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
++
++ mmal_vchi_buffer_cleanup(&buf->mmal);
++ if (buf->mmal.dma_buf) {
++ dma_buf_put(buf->mmal.dma_buf);
++ buf->mmal.dma_buf = NULL;
++ }
++ }
++
++ /* If both ports disabled, then disable the component */
++ if (!ctx->component->input[0].enabled &&
++ !ctx->component->output[0].enabled) {
++ ret = vchiq_mmal_component_disable(dev->instance,
++ ctx->component);
++ if (ret)
++ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling component, ret %d\n",
++ __func__, ret);
++ }
++
++ if (V4L2_TYPE_IS_OUTPUT(q->type))
++ mmal_vchi_buffer_cleanup(&q_data->eos_buffer.mmal);
++
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: done\n", __func__);
++}
++
++static const struct vb2_ops bcm2835_codec_qops = {
++ .queue_setup = bcm2835_codec_queue_setup,
++ .buf_init = bcm2835_codec_buf_init,
++ .buf_prepare = bcm2835_codec_buf_prepare,
++ .buf_queue = bcm2835_codec_buf_queue,
++ .buf_cleanup = bcm2835_codec_buffer_cleanup,
++ .start_streaming = bcm2835_codec_start_streaming,
++ .stop_streaming = bcm2835_codec_stop_streaming,
++ .wait_prepare = vb2_ops_wait_prepare,
++ .wait_finish = vb2_ops_wait_finish,
++};
++
++static int queue_init(void *priv, struct vb2_queue *src_vq,
++ struct vb2_queue *dst_vq)
++{
++ struct bcm2835_codec_ctx *ctx = priv;
++ int ret;
++
++ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
++ src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
++ src_vq->drv_priv = ctx;
++ src_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
++ src_vq->ops = &bcm2835_codec_qops;
++ src_vq->mem_ops = &vb2_dma_contig_memops;
++ src_vq->dev = &ctx->dev->pdev->dev;
++ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
++ src_vq->lock = &ctx->dev->dev_mutex;
++
++ ret = vb2_queue_init(src_vq);
++ if (ret)
++ return ret;
++
++ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
++ dst_vq->drv_priv = ctx;
++ dst_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
++ dst_vq->ops = &bcm2835_codec_qops;
++ dst_vq->mem_ops = &vb2_dma_contig_memops;
++ dst_vq->dev = &ctx->dev->pdev->dev;
++ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
++ dst_vq->lock = &ctx->dev->dev_mutex;
++
++ return vb2_queue_init(dst_vq);
++}
++
++/*
++ * File operations
++ */
++static int bcm2835_codec_open(struct file *file)
++{
++ struct bcm2835_codec_dev *dev = video_drvdata(file);
++ struct bcm2835_codec_ctx *ctx = NULL;
++ struct v4l2_ctrl_handler *hdl;
++ int rc = 0;
++
++ v4l2_dbg(1, debug, &dev->v4l2_dev, "Creating instance for %s\n",
++ dev->decode ? "decode" : "encode");
++ if (mutex_lock_interruptible(&dev->dev_mutex)) {
++ v4l2_err(&dev->v4l2_dev, "Mutex fail\n");
++ return -ERESTARTSYS;
++ }
++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
++ if (!ctx) {
++ rc = -ENOMEM;
++ goto open_unlock;
++ }
++
++ ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev->decode, false);
++ ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev->decode, true);
++ if (dev->decode) {
++ /*
++ * Input width and height are irrelevant as they will be defined
++ * by the bitstream not the format. Required by V4L2 though.
++ */
++ ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
++ ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
++ ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
++ ctx->q_data[V4L2_M2M_SRC].bytesperline = 0;
++ ctx->q_data[V4L2_M2M_SRC].sizeimage =
++ DEF_COMP_BUF_SIZE_720P_OR_LESS;
++
++ ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
++ ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
++ ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
++ ctx->q_data[V4L2_M2M_DST].bytesperline =
++ get_bytesperline(DEFAULT_WIDTH,
++ ctx->q_data[V4L2_M2M_DST].fmt);
++ ctx->q_data[V4L2_M2M_DST].sizeimage =
++ get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
++ ctx->q_data[V4L2_M2M_DST].height,
++ ctx->q_data[V4L2_M2M_DST].fmt);
++ } else {
++ ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
++ ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
++ ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
++ ctx->q_data[V4L2_M2M_SRC].bytesperline =
++ get_bytesperline(DEFAULT_WIDTH,
++ ctx->q_data[V4L2_M2M_SRC].fmt);
++ ctx->q_data[V4L2_M2M_SRC].sizeimage =
++ get_sizeimage(ctx->q_data[V4L2_M2M_SRC].bytesperline,
++ ctx->q_data[V4L2_M2M_SRC].height,
++ ctx->q_data[V4L2_M2M_SRC].fmt);
++
++ ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
++ ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
++ ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
++ ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
++ ctx->q_data[V4L2_M2M_DST].sizeimage =
++ DEF_COMP_BUF_SIZE_720P_OR_LESS;
++ }
++
++ ctx->colorspace = V4L2_COLORSPACE_REC709;
++ ctx->bitrate = 10 * 1000 * 1000;
++
++ /* Initialise V4L2 contexts */
++ v4l2_fh_init(&ctx->fh, video_devdata(file));
++ file->private_data = &ctx->fh;
++ ctx->dev = dev;
++ hdl = &ctx->hdl;
++ if (!dev->decode) {
++ /* Encode controls */
++ v4l2_ctrl_handler_init(hdl, 6);
++
++ v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
++ V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
++ V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
++ V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
++ v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
++ V4L2_CID_MPEG_VIDEO_BITRATE,
++ 25 * 1000, 25 * 1000 * 1000,
++ 25 * 1000, 10 * 1000 * 1000);
++ v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
++ V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER,
++ 0, 1,
++ 1, 0);
++ v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
++ V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
++ 0, 0x7FFFFFFF,
++ 1, 60);
++ v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
++ V4L2_CID_MPEG_VIDEO_H264_LEVEL,
++ V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
++ ~(BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2)),
++ V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
++ v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
++ V4L2_CID_MPEG_VIDEO_H264_PROFILE,
++ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
++ ~(BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
++ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
++ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
++ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
++ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
++ if (hdl->error) {
++ rc = hdl->error;
++ goto free_ctrl_handler;
++ }
++ ctx->fh.ctrl_handler = hdl;
++ v4l2_ctrl_handler_setup(hdl);
++ }
++
++ ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
++
++ if (IS_ERR(ctx->fh.m2m_ctx)) {
++ rc = PTR_ERR(ctx->fh.m2m_ctx);
++
++ goto free_ctrl_handler;
++ }
++
++ /* Set both queues as buffered as we have buffering in the VPU. That
++ * means that we will be scheduled whenever either an input or output
++ * buffer is available (otherwise one of each are required).
++ */
++ v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
++ v4l2_m2m_set_dst_buffered(ctx->fh.m2m_ctx, true);
++
++ v4l2_fh_add(&ctx->fh);
++ atomic_inc(&dev->num_inst);
++
++ mutex_unlock(&dev->dev_mutex);
++ return 0;
++
++free_ctrl_handler:
++ v4l2_ctrl_handler_free(hdl);
++ kfree(ctx);
++open_unlock:
++ mutex_unlock(&dev->dev_mutex);
++ return rc;
++}
++
++static int bcm2835_codec_release(struct file *file)
++{
++ struct bcm2835_codec_dev *dev = video_drvdata(file);
++ struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++ v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: Releasing instance %p\n",
++ __func__, ctx);
++
++ v4l2_fh_del(&ctx->fh);
++ v4l2_fh_exit(&ctx->fh);
++ v4l2_ctrl_handler_free(&ctx->hdl);
++ mutex_lock(&dev->dev_mutex);
++ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
++
++ if (ctx->component)
++ vchiq_mmal_component_finalise(dev->instance, ctx->component);
++
++ mutex_unlock(&dev->dev_mutex);
++ kfree(ctx);
++
++ atomic_dec(&dev->num_inst);
++
++ return 0;
++}
++
++static const struct v4l2_file_operations bcm2835_codec_fops = {
++ .owner = THIS_MODULE,
++ .open = bcm2835_codec_open,
++ .release = bcm2835_codec_release,
++ .poll = v4l2_m2m_fop_poll,
++ .unlocked_ioctl = video_ioctl2,
++ .mmap = v4l2_m2m_fop_mmap,
++};
++
++static const struct video_device bcm2835_codec_videodev = {
++ .name = MEM2MEM_NAME,
++ .vfl_dir = VFL_DIR_M2M,
++ .fops = &bcm2835_codec_fops,
++ .ioctl_ops = &bcm2835_codec_ioctl_ops,
++ .minor = -1,
++ .release = video_device_release_empty,
++};
++
++static const struct v4l2_m2m_ops m2m_ops = {
++ .device_run = device_run,
++ .job_ready = job_ready,
++ .job_abort = job_abort,
++};
++
++static int bcm2835_codec_create(struct platform_device *pdev,
++ struct bcm2835_codec_dev **new_dev,
++ bool decode)
++{
++ struct bcm2835_codec_dev *dev;
++ struct video_device *vfd;
++ struct vchiq_mmal_instance *instance = NULL;
++ int video_nr;
++ int ret;
++
++ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
++ if (!dev)
++ return -ENOMEM;
++
++ dev->pdev = pdev;
++
++ dev->decode = decode;
++
++ ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
++ if (ret)
++ return ret;
++
++ atomic_set(&dev->num_inst, 0);
++ mutex_init(&dev->dev_mutex);
++
++ dev->vfd = bcm2835_codec_videodev;
++ vfd = &dev->vfd;
++ vfd->lock = &dev->dev_mutex;
++ vfd->v4l2_dev = &dev->v4l2_dev;
++
++ if (dev->decode) {
++ v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
++ v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
++ video_nr = decode_video_nr;
++ } else {
++ v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
++ v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
++ video_nr = encode_video_nr;
++ }
++
++ ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
++ if (ret) {
++ v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
++ goto unreg_dev;
++ }
++
++ video_set_drvdata(vfd, dev);
++ snprintf(vfd->name, sizeof(vfd->name), "%s",
++ bcm2835_codec_videodev.name);
++ v4l2_info(&dev->v4l2_dev, "Device registered as /dev/video%d\n",
++ vfd->num);
++
++ *new_dev = dev;
++
++ dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
++ if (IS_ERR(dev->m2m_dev)) {
++ v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
++ ret = PTR_ERR(dev->m2m_dev);
++ goto err_m2m;
++ }
++
++ ret = vchiq_mmal_init(&instance);
++ if (ret < 0)
++ goto err_m2m;
++ dev->instance = instance;
++
++ v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s codec\n",
++ dev->decode ? "decode" : "encode");
++ return 0;
++
++err_m2m:
++ v4l2_m2m_release(dev->m2m_dev);
++ video_unregister_device(&dev->vfd);
++unreg_dev:
++ v4l2_device_unregister(&dev->v4l2_dev);
++
++ return ret;
++}
++
++static int bcm2835_codec_destroy(struct bcm2835_codec_dev *dev)
++{
++ if (!dev)
++ return -ENODEV;
++
++ v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
++ v4l2_m2m_release(dev->m2m_dev);
++ video_unregister_device(&dev->vfd);
++ v4l2_device_unregister(&dev->v4l2_dev);
++
++ return 0;
++}
++
++static int bcm2835_codec_probe(struct platform_device *pdev)
++{
++ struct bcm2835_codec_driver *drv;
++ int ret = 0;
++
++ drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
++ if (!drv)
++ return -ENOMEM;
++
++ ret = bcm2835_codec_create(pdev, &drv->encode, false);
++ if (ret)
++ goto out;
++
++ ret = bcm2835_codec_create(pdev, &drv->decode, true);
++ if (ret)
++ goto out;
++
++ platform_set_drvdata(pdev, drv);
++
++ return 0;
++
++out:
++ if (drv->encode) {
++ bcm2835_codec_destroy(drv->encode);
++ drv->encode = NULL;
++ }
++ return ret;
++}
++
++static int bcm2835_codec_remove(struct platform_device *pdev)
++{
++ struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
++
++ bcm2835_codec_destroy(drv->encode);
++
++ bcm2835_codec_destroy(drv->decode);
++
++ return 0;
++}
++
++static struct platform_driver bcm2835_v4l2_codec_driver = {
++ .probe = bcm2835_codec_probe,
++ .remove = bcm2835_codec_remove,
++ .driver = {
++ .name = "bcm2835-codec",
++ .owner = THIS_MODULE,
++ },
++};
++
++module_platform_driver(bcm2835_v4l2_codec_driver);
++
++MODULE_DESCRIPTION("BCM2835 codec V4L2 driver");
++MODULE_AUTHOR("Dave Stevenson, <dave.stevenson@raspberrypi.org>");
++MODULE_LICENSE("GPL");
++MODULE_VERSION("0.0.1");
++MODULE_ALIAS("platform:bcm2835-codec");
+++ /dev/null
-From d3c99e301ac57e6c1a5e13b341baacd7182a5763 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 25 Sep 2018 16:07:55 +0100
-Subject: [PATCH 277/703] staging: vc04_services: Use vc-sm-cma to support zero
- copy
-
-With the vc-sm-cma driver we can support zero copy of buffers between
-the kernel and VPU. Add this support to vchiq-mmal.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vchiq-mmal/Kconfig | 1 +
- .../vc04_services/vchiq-mmal/mmal-common.h | 4 ++
- .../vc04_services/vchiq-mmal/mmal-vchiq.c | 66 ++++++++++++++++++-
- .../vc04_services/vchiq-mmal/mmal-vchiq.h | 1 +
- 4 files changed, 70 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/Kconfig
-+++ b/drivers/staging/vc04_services/vchiq-mmal/Kconfig
-@@ -2,6 +2,7 @@ config BCM2835_VCHIQ_MMAL
- tristate "BCM2835 MMAL VCHIQ service"
- depends on (ARCH_BCM2835 || COMPILE_TEST)
- select BCM2835_VCHIQ
-+ select BCM_VC_SM_CMA
- help
- Enables the MMAL API over VCHIQ as used for the
- majority of the multimedia services on VideoCore.
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-@@ -51,6 +51,10 @@ struct mmal_buffer {
-
- struct mmal_msg_context *msg_context;
-
-+ struct dma_buf *dma_buf;/* Exported dmabuf fd from videobuf2 */
-+ int vcsm_handle; /* VCSM handle having imported the dmabuf */
-+ u32 vc_handle; /* VC handle to that dmabuf */
-+
- u32 cmd; /* MMAL command. 0=data. */
- unsigned long length;
- u32 mmal_flags;
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -27,9 +27,12 @@
- #include <media/videobuf2-vmalloc.h>
-
- #include "mmal-common.h"
-+#include "mmal-parameters.h"
- #include "mmal-vchiq.h"
- #include "mmal-msg.h"
-
-+#include "vc-sm-cma/vc_sm_knl.h"
-+
- #define USE_VCHIQ_ARM
- #include "interface/vchi/vchi.h"
-
-@@ -425,8 +428,13 @@ buffer_from_host(struct vchiq_mmal_insta
-
- /* buffer header */
- m.u.buffer_from_host.buffer_header.cmd = 0;
-- m.u.buffer_from_host.buffer_header.data =
-- (u32)(unsigned long)buf->buffer;
-+ if (port->zero_copy) {
-+ m.u.buffer_from_host.buffer_header.data = buf->vc_handle;
-+ } else {
-+ m.u.buffer_from_host.buffer_header.data =
-+ (u32)(unsigned long)buf->buffer;
-+ }
-+
- m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
- if (port->type == MMAL_PORT_TYPE_OUTPUT) {
- m.u.buffer_from_host.buffer_header.length = 0;
-@@ -591,6 +599,22 @@ static void buffer_to_host_cb(struct vch
-
- msg_context->u.bulk.status = msg->h.status;
-
-+ } else if (msg->u.buffer_from_host.is_zero_copy) {
-+ /*
-+ * Zero copy buffer, so nothing to do.
-+ * Copy buffer info and make callback.
-+ */
-+ msg_context->u.bulk.buffer_used =
-+ msg->u.buffer_from_host.buffer_header.length;
-+ 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;
-+ msg_context->u.bulk.cmd =
-+ msg->u.buffer_from_host.buffer_header.cmd;
-+
- } else if (msg->u.buffer_from_host.buffer_header.length == 0) {
- /* empty buffer */
- if (msg->u.buffer_from_host.buffer_header.flags &
-@@ -1538,6 +1562,9 @@ int vchiq_mmal_port_parameter_set(struct
-
- mutex_unlock(&instance->vchiq_mutex);
-
-+ if (parameter == MMAL_PARAMETER_ZERO_COPY && !ret)
-+ port->zero_copy = !!(*(bool *)value);
-+
- return ret;
- }
- EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set);
-@@ -1706,6 +1733,31 @@ int vchiq_mmal_submit_buffer(struct vchi
- unsigned long flags = 0;
- int ret;
-
-+ /*
-+ * We really want to do this in mmal_vchi_buffer_init but can't as
-+ * videobuf2 won't let us have the dmabuf there.
-+ */
-+ if (port->zero_copy && buffer->dma_buf && !buffer->vcsm_handle) {
-+ pr_debug("%s: import dmabuf %p\n", __func__, buffer->dma_buf);
-+ ret = vc_sm_cma_import_dmabuf(buffer->dma_buf,
-+ &buffer->vcsm_handle);
-+ if (ret) {
-+ pr_err("%s: vc_sm_import_dmabuf_fd failed, ret %d\n",
-+ __func__, ret);
-+ return ret;
-+ }
-+
-+ buffer->vc_handle = vc_sm_cma_int_handle(buffer->vcsm_handle);
-+ if (!buffer->vc_handle) {
-+ pr_err("%s: vc_sm_int_handle failed %d\n",
-+ __func__, ret);
-+ vc_sm_cma_free(buffer->vcsm_handle);
-+ return ret;
-+ }
-+ pr_debug("%s: import dmabuf %p - got vc handle %08X\n",
-+ __func__, buffer->dma_buf, buffer->vc_handle);
-+ }
-+
- ret = buffer_from_host(instance, port, buffer);
- if (ret == -EINVAL) {
- /* Port is disabled. Queue for when it is enabled. */
-@@ -1739,6 +1791,16 @@ int mmal_vchi_buffer_cleanup(struct mmal
- release_msg_context(msg_context);
- buf->msg_context = NULL;
-
-+ if (buf->vcsm_handle) {
-+ int ret;
-+
-+ pr_debug("%s: vc_sm_cma_free on handle %08X\n", __func__,
-+ buf->vcsm_handle);
-+ ret = vc_sm_cma_free(buf->vcsm_handle);
-+ if (ret)
-+ pr_err("%s: vcsm_free failed, ret %d\n", __func__, ret);
-+ buf->vcsm_handle = 0;
-+ }
- return 0;
- }
- EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -49,6 +49,7 @@ typedef void (*vchiq_mmal_buffer_cb)(
-
- struct vchiq_mmal_port {
- u32 enabled:1;
-+ u32 zero_copy:1;
- u32 handle;
- u32 type; /* port type, cached to use on port info set */
- u32 index; /* port index, cached to use on port info set */
--- /dev/null
+From d5e800f52f43d8be95d78d4f95b0e5825bc5c4fb Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 26 Oct 2018 15:14:16 +0100
+Subject: [PATCH 277/725] staging: vchiq_arm: Register bcm2835-codec as a
+ platform driver
+
+Following the same pattern as bcm2835-camera and bcm2835-audio,
+register the V4L2 codec driver as a platform driver
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -171,6 +171,7 @@ static struct device *vchiq_dev;
+ static DEFINE_SPINLOCK(msg_queue_spinlock);
+ static struct platform_device *bcm2835_camera;
+ static struct platform_device *bcm2835_audio;
++static struct platform_device *bcm2835_codec;
+
+ static const char *const ioctl_names[] = {
+ "CONNECT",
+@@ -3660,6 +3661,9 @@ static int vchiq_probe(struct platform_d
+ bcm2835_audio = vchiq_register_child(pdev, "bcm2835_audio");
+ if (IS_ERR(bcm2835_audio))
+ bcm2835_audio = NULL;
++ bcm2835_codec = vchiq_register_child(pdev, "bcm2835-codec");
++ if (IS_ERR(bcm2835_codec))
++ bcm2835_codec = NULL;
+
+ return 0;
+
+++ /dev/null
-From 2fada970d893db4a8800bae31d6ed8c01b4c4173 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Oct 2018 17:57:45 +0000
-Subject: [PATCH 278/703] media: videobuf2: Allow exporting of a struct dmabuf
-
-videobuf2 only allowed exporting a dmabuf as a file descriptor,
-but there are instances where having the struct dma_buf is
-useful within the kernel.
-
-Split the current implementation into two, one step which
-exports a struct dma_buf, and the second which converts that
-into an fd.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../media/common/videobuf2/videobuf2-core.c | 21 ++++++++++++++++---
- include/media/videobuf2-core.h | 15 +++++++++++++
- 2 files changed, 33 insertions(+), 3 deletions(-)
-
---- a/drivers/media/common/videobuf2/videobuf2-core.c
-+++ b/drivers/media/common/videobuf2/videobuf2-core.c
-@@ -1851,12 +1851,12 @@ static int __find_plane_by_offset(struct
- return -EINVAL;
- }
-
--int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
-- unsigned int index, unsigned int plane, unsigned int flags)
-+int vb2_core_expbuf_dmabuf(struct vb2_queue *q, unsigned int type,
-+ unsigned int index, unsigned int plane,
-+ unsigned int flags, struct dma_buf **dmabuf)
- {
- struct vb2_buffer *vb = NULL;
- struct vb2_plane *vb_plane;
-- int ret;
- struct dma_buf *dbuf;
-
- if (q->memory != VB2_MEMORY_MMAP) {
-@@ -1906,6 +1906,21 @@ int vb2_core_expbuf(struct vb2_queue *q,
- return -EINVAL;
- }
-
-+ *dmabuf = dbuf;
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(vb2_core_expbuf_dmabuf);
-+
-+int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
-+ unsigned int index, unsigned int plane, unsigned int flags)
-+{
-+ struct dma_buf *dbuf;
-+ int ret;
-+
-+ ret = vb2_core_expbuf_dmabuf(q, type, index, plane, flags, &dbuf);
-+ if (ret)
-+ return ret;
-+
- ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE);
- if (ret < 0) {
- dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
---- a/include/media/videobuf2-core.h
-+++ b/include/media/videobuf2-core.h
-@@ -825,6 +825,21 @@ int vb2_core_streamon(struct vb2_queue *
- int vb2_core_streamoff(struct vb2_queue *q, unsigned int type);
-
- /**
-+ * vb2_core_expbuf_dmabuf() - Export a buffer as a dma_buf structure
-+ * @q: videobuf2 queue
-+ * @type: buffer type
-+ * @index: id number of the buffer
-+ * @plane: index of the plane to be exported, 0 for single plane queues
-+ * @flags: flags for newly created file, currently only O_CLOEXEC is
-+ * supported, refer to manual of open syscall for more details
-+ * @dmabuf: Returns the dmabuf pointer
-+ *
-+ */
-+int vb2_core_expbuf_dmabuf(struct vb2_queue *q, unsigned int type,
-+ unsigned int index, unsigned int plane,
-+ unsigned int flags, struct dma_buf **dmabuf);
-+
-+/**
- * vb2_core_expbuf() - Export a buffer as a file descriptor.
- * @q: pointer to &struct vb2_queue with videobuf2 queue.
- * @fd: pointer to the file descriptor associated with DMABUF
--- /dev/null
+From 37dfe69edd33c0ed92770207f55f97ae3fa77607 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 26 Oct 2018 15:19:40 +0100
+Subject: [PATCH 278/725] staging: vchiq_arm: Register vcsm-cma as a platform
+ driver
+
+Following the same pattern as bcm2835-camera and bcm2835-audio,
+register the vcsm-cma driver as a platform driver
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -172,6 +172,7 @@ static DEFINE_SPINLOCK(msg_queue_spinloc
+ static struct platform_device *bcm2835_camera;
+ static struct platform_device *bcm2835_audio;
+ static struct platform_device *bcm2835_codec;
++static struct platform_device *vcsm_cma;
+
+ static const char *const ioctl_names[] = {
+ "CONNECT",
+@@ -3655,6 +3656,9 @@ static int vchiq_probe(struct platform_d
+ VCHIQ_VERSION, VCHIQ_VERSION_MIN,
+ MAJOR(vchiq_devid), MINOR(vchiq_devid));
+
++ vcsm_cma = vchiq_register_child(pdev, "vcsm-cma");
++ if (IS_ERR(vcsm_cma))
++ vcsm_cma = NULL;
+ bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera");
+ if (IS_ERR(bcm2835_camera))
+ bcm2835_camera = NULL;
--- /dev/null
+From 73ba32bae3b1afd20a8b9c116c620d47020f1720 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Oct 2018 17:49:04 +0000
+Subject: [PATCH 279/725] ARM: bcm2835_defconfig: Enable bcm2835-codec
+
+Enables the V4L2 M2M codec driver as a module.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm/configs/bcm2835_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/configs/bcm2835_defconfig
++++ b/arch/arm/configs/bcm2835_defconfig
+@@ -132,6 +132,7 @@ CONFIG_DMA_BCM2835=y
+ CONFIG_STAGING=y
+ CONFIG_SND_BCM2835=m
+ CONFIG_VIDEO_BCM2835=m
++CONFIG_VIDEO_CODEC_BCM2835=m
+ CONFIG_MAILBOX=y
+ CONFIG_BCM2835_MBOX=y
+ # CONFIG_IOMMU_SUPPORT is not set
+++ /dev/null
-From ce40b5f18f770684fcfe2b02e5bd9a73f7716a8f Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 25 Sep 2018 14:53:49 +0100
-Subject: [PATCH 279/703] staging: vc04_services: Add a V4L2 M2M codec driver
-
-This adds a V4L2 memory to memory device that wraps the MMAL
-video decode and video_encode components for H264 and MJPEG encode
-and decode, MPEG4, H263, and VP8 decode (and MPEG2 decode
-if the appropriate licence has been purchased).
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/Kconfig | 1 +
- drivers/staging/vc04_services/Makefile | 9 +-
- .../vc04_services/bcm2835-codec/Kconfig | 11 +
- .../vc04_services/bcm2835-codec/Makefile | 8 +
- .../staging/vc04_services/bcm2835-codec/TODO | 24 +
- .../bcm2835-codec/bcm2835-v4l2-codec.c | 2359 +++++++++++++++++
- 6 files changed, 2408 insertions(+), 4 deletions(-)
- create mode 100644 drivers/staging/vc04_services/bcm2835-codec/Kconfig
- create mode 100644 drivers/staging/vc04_services/bcm2835-codec/Makefile
- create mode 100644 drivers/staging/vc04_services/bcm2835-codec/TODO
- create mode 100644 drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-
---- a/drivers/staging/vc04_services/Kconfig
-+++ b/drivers/staging/vc04_services/Kconfig
-@@ -23,6 +23,7 @@ source "drivers/staging/vc04_services/bc
- source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
- source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
- source "drivers/staging/vc04_services/vc-sm-cma/Kconfig"
-+source "drivers/staging/vc04_services/bcm2835-codec/Kconfig"
-
- endif
-
---- a/drivers/staging/vc04_services/Makefile
-+++ b/drivers/staging/vc04_services/Makefile
-@@ -10,10 +10,11 @@ vchiq-objs := \
- interface/vchiq_arm/vchiq_util.o \
- interface/vchiq_arm/vchiq_connected.o \
-
--obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/
--obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/
--obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
--obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma/
-+obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/
-+obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/
-+obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
-+obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma/
-+obj-$(CONFIG_VIDEO_CODEC_BCM2835) += bcm2835-codec/
-
- ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000
-
---- /dev/null
-+++ b/drivers/staging/vc04_services/bcm2835-codec/Kconfig
-@@ -0,0 +1,11 @@
-+config VIDEO_CODEC_BCM2835
-+ tristate "BCM2835 Video codec support"
-+ depends on MEDIA_SUPPORT
-+ depends on VIDEO_V4L2 && (ARCH_BCM2835 || COMPILE_TEST)
-+ select BCM2835_VCHIQ_MMAL
-+ select VIDEOBUF2_DMA_CONTIG
-+ select V4L2_MEM2MEM_DEV
-+ help
-+ Say Y here to enable the V4L2 video codecs for
-+ Broadcom BCM2835 SoC. This operates over the VCHIQ interface
-+ to a service running on VideoCore.
---- /dev/null
-+++ b/drivers/staging/vc04_services/bcm2835-codec/Makefile
-@@ -0,0 +1,8 @@
-+# SPDX-License-Identifier: GPL-2.0
-+bcm2835-codec-objs := bcm2835-v4l2-codec.o
-+
-+obj-$(CONFIG_VIDEO_CODEC_BCM2835) += bcm2835-codec.o
-+
-+ccflags-y += \
-+ -Idrivers/staging/vc04_services \
-+ -D__VCCOREVER__=0x04000000
---- /dev/null
-+++ b/drivers/staging/vc04_services/bcm2835-codec/TODO
-@@ -0,0 +1,24 @@
-+1) Convert to be a platform driver.
-+
-+Right now when the module probes, it tries to initialize VCHI and
-+errors out if it wasn't ready yet. If bcm2835-v4l2 was built in, then
-+VCHI generally isn't ready because it depends on both the firmware and
-+mailbox drivers having already loaded.
-+
-+We should have VCHI create a platform device once it's initialized,
-+and have this driver bind to it, so that we automatically load the
-+v4l2 module after VCHI loads.
-+
-+2) Support SELECTION API to define crop region on the image for encode.
-+
-+Particularly for resolutions that aren't a multiple of the macroblock
-+size, the codec will report a resolution that is a multiple of the macroblock
-+size (it has to have the memory to decode into), and then a different crop
-+region within that buffer.
-+The most common example is 1080P, where the buffer will be 1920x1088 with a
-+crop region of 1920x1080.
-+
-+3) Refactor so that the component creation is only on queue_setup, not open.
-+
-+Fixes v4l2-compliance failure on trying to open 100 instances of the
-+device.
-\ No newline at end of file
---- /dev/null
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -0,0 +1,2359 @@
-+// SPDX-License-Identifier: GPL-2.0
-+
-+/*
-+ * A v4l2-mem2mem device that wraps the video codec MMAL component.
-+ *
-+ * Copyright 2018 Raspberry Pi (Trading) Ltd.
-+ * Author: Dave Stevenson (dave.stevenson@raspberrypi.org)
-+ *
-+ * Loosely based on the vim2m virtual driver by Pawel Osciak
-+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
-+ * Pawel Osciak, <pawel@osciak.com>
-+ * Marek Szyprowski, <m.szyprowski@samsung.com>
-+ *
-+ * Whilst this driver uses the v4l2_mem2mem framework, it does not need the
-+ * scheduling aspects, so will always take the buffers, pass them to the VPU,
-+ * and then signal the job as complete.
-+ *
-+ * 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 <linux/module.h>
-+#include <linux/delay.h>
-+#include <linux/fs.h>
-+#include <linux/timer.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/platform_device.h>
-+#include <linux/syscalls.h>
-+
-+#include <media/v4l2-mem2mem.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-ioctl.h>
-+#include <media/v4l2-ctrls.h>
-+#include <media/v4l2-event.h>
-+#include <media/videobuf2-dma-contig.h>
-+
-+#include "vchiq-mmal/mmal-encodings.h"
-+#include "vchiq-mmal/mmal-msg.h"
-+#include "vchiq-mmal/mmal-parameters.h"
-+#include "vchiq-mmal/mmal-vchiq.h"
-+
-+/*
-+ * Default /dev/videoN node numbers for decode and encode.
-+ * Deliberately avoid the very low numbers as these are often taken by webcams
-+ * etc, and simple apps tend to only go for /dev/video0.
-+ */
-+static int decode_video_nr = 10;
-+module_param(decode_video_nr, int, 0644);
-+MODULE_PARM_DESC(decode_video_nr, "decoder video device number");
-+
-+static int encode_video_nr = 11;
-+module_param(encode_video_nr, int, 0644);
-+MODULE_PARM_DESC(encode_video_nr, "encoder video device number");
-+
-+static unsigned int debug;
-+module_param(debug, uint, 0644);
-+MODULE_PARM_DESC(debug, "activates debug info (0-3)");
-+
-+#define MIN_W 32
-+#define MIN_H 32
-+#define MAX_W 1920
-+#define MAX_H 1088
-+#define BPL_ALIGN 32
-+#define DEFAULT_WIDTH 640
-+#define DEFAULT_HEIGHT 480
-+/*
-+ * The unanswered question - what is the maximum size of a compressed frame?
-+ * V4L2 mandates that the encoded frame must fit in a single buffer. Sizing
-+ * that buffer is a compromise between wasting memory and risking not fitting.
-+ * The 1080P version of Big Buck Bunny has some frames that exceed 512kB.
-+ * Adopt a moderately arbitrary split at 720P for switching between 512 and
-+ * 768kB buffers.
-+ */
-+#define DEF_COMP_BUF_SIZE_GREATER_720P (768 << 10)
-+#define DEF_COMP_BUF_SIZE_720P_OR_LESS (512 << 10)
-+
-+/* Flags that indicate a format can be used for capture/output */
-+#define MEM2MEM_CAPTURE BIT(0)
-+#define MEM2MEM_OUTPUT BIT(1)
-+
-+#define MEM2MEM_NAME "bcm2835-codec"
-+
-+struct bcm2835_codec_fmt {
-+ u32 fourcc;
-+ int depth;
-+ int bytesperline_align;
-+ u32 flags;
-+ u32 mmal_fmt;
-+ bool decode_only;
-+ bool encode_only;
-+ int size_multiplier_x2;
-+};
-+
-+/* Supported raw pixel formats. Those supported for both encode and decode
-+ * must come first, with those only supported for decode coming after (there
-+ * are no formats supported for encode only).
-+ */
-+static struct bcm2835_codec_fmt raw_formats[] = {
-+ {
-+ .fourcc = V4L2_PIX_FMT_YUV420,
-+ .depth = 8,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_I420,
-+ .size_multiplier_x2 = 3,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_YVU420,
-+ .depth = 8,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_YV12,
-+ .size_multiplier_x2 = 3,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_NV12,
-+ .depth = 8,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_NV12,
-+ .size_multiplier_x2 = 3,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_NV21,
-+ .depth = 8,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_NV21,
-+ .size_multiplier_x2 = 3,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_RGB565,
-+ .depth = 16,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_RGB16,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_YUYV,
-+ .depth = 16,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_YUYV,
-+ .encode_only = true,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_UYVY,
-+ .depth = 16,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_UYVY,
-+ .encode_only = true,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_YVYU,
-+ .depth = 16,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_YVYU,
-+ .encode_only = true,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_VYUY,
-+ .depth = 16,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_VYUY,
-+ .encode_only = true,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_RGB24,
-+ .depth = 24,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_RGB24,
-+ .encode_only = true,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_BGR24,
-+ .depth = 24,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BGR24,
-+ .encode_only = true,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_BGR32,
-+ .depth = 32,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BGRA,
-+ .encode_only = true,
-+ .size_multiplier_x2 = 2,
-+ },
-+};
-+
-+/* Supported encoded formats. Those supported for both encode and decode
-+ * must come first, with those only supported for decode coming after (there
-+ * are no formats supported for encode only).
-+ */
-+static struct bcm2835_codec_fmt encoded_formats[] = {
-+ {
-+ .fourcc = V4L2_PIX_FMT_H264,
-+ .depth = 0,
-+ .flags = V4L2_FMT_FLAG_COMPRESSED,
-+ .mmal_fmt = MMAL_ENCODING_H264,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_MJPEG,
-+ .depth = 0,
-+ .flags = V4L2_FMT_FLAG_COMPRESSED,
-+ .mmal_fmt = MMAL_ENCODING_MJPEG,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_MPEG4,
-+ .depth = 0,
-+ .flags = V4L2_FMT_FLAG_COMPRESSED,
-+ .mmal_fmt = MMAL_ENCODING_MP4V,
-+ .decode_only = true,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_H263,
-+ .depth = 0,
-+ .flags = V4L2_FMT_FLAG_COMPRESSED,
-+ .mmal_fmt = MMAL_ENCODING_H263,
-+ .decode_only = true,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_MPEG2,
-+ .depth = 0,
-+ .flags = V4L2_FMT_FLAG_COMPRESSED,
-+ .mmal_fmt = MMAL_ENCODING_MP2V,
-+ .decode_only = true,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_VP8,
-+ .depth = 0,
-+ .flags = V4L2_FMT_FLAG_COMPRESSED,
-+ .mmal_fmt = MMAL_ENCODING_VP8,
-+ .decode_only = true,
-+ },
-+ /*
-+ * This list couold include VP6 and Theorafor decode, but V4L2 doesn't
-+ * support them.
-+ */
-+};
-+
-+struct bcm2835_codec_fmt_list {
-+ struct bcm2835_codec_fmt *list;
-+ unsigned int num_entries;
-+};
-+
-+#define RAW_LIST 0
-+#define ENCODED_LIST 1
-+
-+struct bcm2835_codec_fmt_list formats[] = {
-+ {
-+ .list = raw_formats,
-+ .num_entries = ARRAY_SIZE(raw_formats),
-+ }, {
-+ .list = encoded_formats,
-+ .num_entries = ARRAY_SIZE(encoded_formats),
-+ },
-+};
-+
-+struct m2m_mmal_buffer {
-+ struct v4l2_m2m_buffer m2m;
-+ struct mmal_buffer mmal;
-+};
-+
-+/* Per-queue, driver-specific private data */
-+struct bcm2835_codec_q_data {
-+ /*
-+ * These parameters should be treated as gospel, with everything else
-+ * being determined from them.
-+ */
-+ /* Buffer width/height */
-+ unsigned int bytesperline;
-+ unsigned int height;
-+ /* Crop size used for selection handling */
-+ unsigned int crop_width;
-+ unsigned int crop_height;
-+ bool selection_set;
-+
-+ unsigned int sizeimage;
-+ unsigned int sequence;
-+ struct bcm2835_codec_fmt *fmt;
-+
-+ /* One extra buffer header so we can send an EOS. */
-+ struct m2m_mmal_buffer eos_buffer;
-+ bool eos_buffer_in_use; /* debug only */
-+};
-+
-+enum {
-+ V4L2_M2M_SRC = 0,
-+ V4L2_M2M_DST = 1,
-+};
-+
-+static inline struct bcm2835_codec_fmt_list *get_format_list(bool decode,
-+ bool capture)
-+{
-+ return decode ^ capture ? &formats[ENCODED_LIST] : &formats[RAW_LIST];
-+}
-+
-+static struct bcm2835_codec_fmt *get_default_format(bool decode, bool capture)
-+{
-+ return &get_format_list(decode, capture)->list[0];
-+}
-+
-+static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f, bool decode,
-+ bool capture)
-+{
-+ struct bcm2835_codec_fmt *fmt;
-+ unsigned int k;
-+ struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
-+
-+ for (k = 0; k < fmts->num_entries; k++) {
-+ fmt = &fmts->list[k];
-+ if (fmt->fourcc == f->fmt.pix.pixelformat)
-+ break;
-+ }
-+
-+ /*
-+ * Some compressed formats are only supported for decoding, not
-+ * encoding.
-+ */
-+ if (!decode && fmts->list[k].decode_only)
-+ return NULL;
-+
-+ /* Some pixel formats are only supported for encoding, not decoding. */
-+ if (decode && fmts->list[k].encode_only)
-+ return NULL;
-+
-+ if (k == fmts->num_entries)
-+ return NULL;
-+
-+ return &fmts->list[k];
-+}
-+
-+struct bcm2835_codec_dev {
-+ struct platform_device *pdev;
-+
-+ /* v4l2 devices */
-+ struct v4l2_device v4l2_dev;
-+ struct video_device vfd;
-+ /* mutex for the v4l2 device */
-+ struct mutex dev_mutex;
-+ atomic_t num_inst;
-+
-+ /* allocated mmal instance and components */
-+ bool decode; /* Is this instance a decoder? */
-+ struct vchiq_mmal_instance *instance;
-+
-+ struct v4l2_m2m_dev *m2m_dev;
-+};
-+
-+struct bcm2835_codec_ctx {
-+ struct v4l2_fh fh;
-+ struct bcm2835_codec_dev *dev;
-+
-+ struct v4l2_ctrl_handler hdl;
-+
-+ struct vchiq_mmal_component *component;
-+ bool component_enabled;
-+
-+ enum v4l2_colorspace colorspace;
-+ enum v4l2_ycbcr_encoding ycbcr_enc;
-+ enum v4l2_xfer_func xfer_func;
-+ enum v4l2_quantization quant;
-+
-+ /* Source and destination queue data */
-+ struct bcm2835_codec_q_data q_data[2];
-+ s32 bitrate;
-+
-+ bool aborting;
-+ int num_ip_buffers;
-+ int num_op_buffers;
-+ struct completion frame_cmplt;
-+};
-+
-+struct bcm2835_codec_driver {
-+ struct bcm2835_codec_dev *encode;
-+ struct bcm2835_codec_dev *decode;
-+};
-+
-+static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
-+{
-+ return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
-+}
-+
-+static struct bcm2835_codec_q_data *get_q_data(struct bcm2835_codec_ctx *ctx,
-+ enum v4l2_buf_type type)
-+{
-+ switch (type) {
-+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-+ return &ctx->q_data[V4L2_M2M_SRC];
-+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-+ return &ctx->q_data[V4L2_M2M_DST];
-+ default:
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
-+ __func__, type);
-+ break;
-+ }
-+ return NULL;
-+}
-+
-+static struct vchiq_mmal_port *get_port_data(struct bcm2835_codec_ctx *ctx,
-+ enum v4l2_buf_type type)
-+{
-+ if (!ctx->component)
-+ return NULL;
-+
-+ switch (type) {
-+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-+ return &ctx->component->input[0];
-+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-+ return &ctx->component->output[0];
-+ default:
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
-+ __func__, type);
-+ break;
-+ }
-+ return NULL;
-+}
-+
-+/*
-+ * mem2mem callbacks
-+ */
-+
-+/**
-+ * job_ready() - check whether an instance is ready to be scheduled to run
-+ */
-+static int job_ready(void *priv)
-+{
-+ struct bcm2835_codec_ctx *ctx = priv;
-+
-+ if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) &&
-+ !v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx))
-+ return 0;
-+
-+ return 1;
-+}
-+
-+static void job_abort(void *priv)
-+{
-+ struct bcm2835_codec_ctx *ctx = priv;
-+
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s\n", __func__);
-+ /* Will cancel the transaction in the next interrupt handler */
-+ ctx->aborting = 1;
-+}
-+
-+static inline unsigned int get_sizeimage(int bpl, int height,
-+ struct bcm2835_codec_fmt *fmt)
-+{
-+ return (bpl * height * fmt->size_multiplier_x2) >> 1;
-+}
-+
-+static inline unsigned int get_bytesperline(int width,
-+ struct bcm2835_codec_fmt *fmt)
-+{
-+ return ALIGN((width * fmt->depth) >> 3, fmt->bytesperline_align);
-+}
-+
-+static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
-+ bool decode,
-+ struct bcm2835_codec_q_data *q_data,
-+ struct vchiq_mmal_port *port)
-+{
-+ port->format.encoding = q_data->fmt->mmal_fmt;
-+
-+ if (!(q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED)) {
-+ /* Raw image format - set width/height */
-+ port->es.video.width = q_data->bytesperline /
-+ (q_data->fmt->depth >> 3);
-+ port->es.video.height = q_data->height;
-+ port->es.video.crop.width = q_data->crop_width;
-+ port->es.video.crop.height = q_data->crop_height;
-+ port->es.video.frame_rate.num = 0;
-+ port->es.video.frame_rate.den = 1;
-+ } else {
-+ /* Compressed format - leave resolution as 0 for decode */
-+ if (decode) {
-+ port->es.video.width = 0;
-+ port->es.video.height = 0;
-+ port->es.video.crop.width = 0;
-+ port->es.video.crop.height = 0;
-+ } else {
-+ port->es.video.width = q_data->crop_width;
-+ port->es.video.height = q_data->height;
-+ port->es.video.crop.width = q_data->crop_width;
-+ port->es.video.crop.height = q_data->crop_height;
-+ port->format.bitrate = ctx->bitrate;
-+ }
-+ port->es.video.frame_rate.num = 0;
-+ port->es.video.frame_rate.den = 1;
-+ }
-+ port->es.video.crop.x = 0;
-+ port->es.video.crop.y = 0;
-+
-+ port->current_buffer.size = q_data->sizeimage;
-+};
-+
-+static void ip_buffer_cb(struct vchiq_mmal_instance *instance,
-+ struct vchiq_mmal_port *port, int status,
-+ struct mmal_buffer *mmal_buf)
-+{
-+ struct bcm2835_codec_ctx *ctx = port->cb_ctx/*, *curr_ctx*/;
-+ struct m2m_mmal_buffer *buf =
-+ container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
-+
-+ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: port %p buf %p length %lu, flags %x\n",
-+ __func__, port, mmal_buf, mmal_buf->length,
-+ mmal_buf->mmal_flags);
-+
-+ if (buf == &ctx->q_data[V4L2_M2M_SRC].eos_buffer) {
-+ /* Do we need to add lcoking to prevent multiple submission of
-+ * the EOS, and therefore handle mutliple return here?
-+ */
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: eos buffer returned.\n",
-+ __func__);
-+ ctx->q_data[V4L2_M2M_SRC].eos_buffer_in_use = false;
-+ return;
-+ }
-+
-+ if (status) {
-+ /* error in transfer */
-+ if (buf)
-+ /* there was a buffer with the error so return it */
-+ vb2_buffer_done(&buf->m2m.vb.vb2_buf,
-+ VB2_BUF_STATE_ERROR);
-+ return;
-+ }
-+ if (mmal_buf->cmd) {
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Not expecting cmd msgs on ip callback - %08x\n",
-+ __func__, mmal_buf->cmd);
-+ /*
-+ * CHECKME: Should we return here. The buffer shouldn't have a
-+ * message context or vb2 buf associated.
-+ */
-+ }
-+
-+ v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: no error. Return buffer %p\n",
-+ __func__, &buf->m2m.vb.vb2_buf);
-+ vb2_buffer_done(&buf->m2m.vb.vb2_buf, VB2_BUF_STATE_DONE);
-+
-+ ctx->num_ip_buffers++;
-+ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: done %d input buffers\n",
-+ __func__, ctx->num_ip_buffers);
-+
-+ if (!port->enabled)
-+ complete(&ctx->frame_cmplt);
-+}
-+
-+static void queue_res_chg_event(struct bcm2835_codec_ctx *ctx)
-+{
-+ static const struct v4l2_event ev_src_ch = {
-+ .type = V4L2_EVENT_SOURCE_CHANGE,
-+ .u.src_change.changes =
-+ V4L2_EVENT_SRC_CH_RESOLUTION,
-+ };
-+
-+ v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
-+}
-+
-+static void send_eos_event(struct bcm2835_codec_ctx *ctx)
-+{
-+ static const struct v4l2_event ev = {
-+ .type = V4L2_EVENT_EOS,
-+ };
-+
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Sending EOS event\n");
-+
-+ v4l2_event_queue_fh(&ctx->fh, &ev);
-+}
-+
-+static void color_mmal2v4l(struct bcm2835_codec_ctx *ctx, u32 mmal_color_space)
-+{
-+ switch (mmal_color_space) {
-+ case MMAL_COLOR_SPACE_ITUR_BT601:
-+ ctx->colorspace = V4L2_COLORSPACE_REC709;
-+ ctx->xfer_func = V4L2_XFER_FUNC_709;
-+ ctx->ycbcr_enc = V4L2_YCBCR_ENC_601;
-+ ctx->quant = V4L2_QUANTIZATION_LIM_RANGE;
-+ break;
-+
-+ case MMAL_COLOR_SPACE_ITUR_BT709:
-+ ctx->colorspace = V4L2_COLORSPACE_REC709;
-+ ctx->xfer_func = V4L2_XFER_FUNC_709;
-+ ctx->ycbcr_enc = V4L2_YCBCR_ENC_709;
-+ ctx->quant = V4L2_QUANTIZATION_LIM_RANGE;
-+ break;
-+ }
-+}
-+
-+static void handle_fmt_changed(struct bcm2835_codec_ctx *ctx,
-+ struct mmal_buffer *mmal_buf)
-+{
-+ struct bcm2835_codec_q_data *q_data;
-+ struct mmal_msg_event_format_changed *format =
-+ (struct mmal_msg_event_format_changed *)mmal_buf->buffer;
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed: buff size min %u, rec %u, buff num min %u, rec %u\n",
-+ __func__,
-+ format->buffer_size_min,
-+ format->buffer_size_recommended,
-+ format->buffer_num_min,
-+ format->buffer_num_recommended
-+ );
-+ if (format->format.type != MMAL_ES_TYPE_VIDEO) {
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed but not video %u\n",
-+ __func__, format->format.type);
-+ return;
-+ }
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed to %ux%u, crop %ux%u, colourspace %08X\n",
-+ __func__, format->es.video.width, format->es.video.height,
-+ format->es.video.crop.width, format->es.video.crop.height,
-+ format->es.video.color_space);
-+
-+ q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-+ q_data->crop_width = format->es.video.crop.width;
-+ q_data->crop_height = format->es.video.crop.height;
-+ q_data->bytesperline = format->es.video.crop.width;
-+ q_data->height = format->es.video.height;
-+ q_data->sizeimage = format->buffer_size_min;
-+ if (format->es.video.color_space)
-+ color_mmal2v4l(ctx, format->es.video.color_space);
-+
-+ queue_res_chg_event(ctx);
-+}
-+
-+static void op_buffer_cb(struct vchiq_mmal_instance *instance,
-+ struct vchiq_mmal_port *port, int status,
-+ struct mmal_buffer *mmal_buf)
-+{
-+ struct bcm2835_codec_ctx *ctx = port->cb_ctx;
-+ struct m2m_mmal_buffer *buf;
-+ struct vb2_v4l2_buffer *vb2;
-+
-+ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev,
-+ "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n",
-+ __func__, status, mmal_buf, mmal_buf->length,
-+ mmal_buf->mmal_flags, mmal_buf->pts);
-+
-+ if (status) {
-+ /* error in transfer */
-+ if (vb2) {
-+ /* there was a buffer with the error so return it */
-+ vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_ERROR);
-+ }
-+ return;
-+ }
-+
-+ if (mmal_buf->cmd) {
-+ switch (mmal_buf->cmd) {
-+ case MMAL_EVENT_FORMAT_CHANGED:
-+ {
-+ handle_fmt_changed(ctx, mmal_buf);
-+ break;
-+ }
-+ default:
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Unexpected event on output callback - %08x\n",
-+ __func__, mmal_buf->cmd);
-+ break;
-+ }
-+ return;
-+ }
-+
-+ buf = container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
-+ vb2 = &buf->m2m.vb;
-+
-+ v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: length %lu, flags %x, idx %u\n",
-+ __func__, mmal_buf->length, mmal_buf->mmal_flags,
-+ vb2->vb2_buf.index);
-+
-+ if (mmal_buf->length == 0) {
-+ /* stream ended, or buffer being returned during disable. */
-+ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: Empty buffer - flags %04x",
-+ __func__, mmal_buf->mmal_flags);
-+ if (!mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS) {
-+ vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_ERROR);
-+ if (!port->enabled)
-+ complete(&ctx->frame_cmplt);
-+ return;
-+ }
-+ }
-+ if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS) {
-+ /* EOS packet from the VPU */
-+ send_eos_event(ctx);
-+ vb2->flags |= V4L2_BUF_FLAG_LAST;
-+ }
-+
-+ vb2->vb2_buf.timestamp = mmal_buf->pts;
-+
-+ vb2_set_plane_payload(&vb2->vb2_buf, 0, mmal_buf->length);
-+ if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
-+ vb2->flags |= V4L2_BUF_FLAG_KEYFRAME;
-+
-+ vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_DONE);
-+ ctx->num_op_buffers++;
-+
-+ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: done %d output buffers\n",
-+ __func__, ctx->num_op_buffers);
-+
-+ if (!port->enabled)
-+ complete(&ctx->frame_cmplt);
-+}
-+
-+/* vb2_to_mmal_buffer() - converts vb2 buffer header to MMAL
-+ *
-+ * Copies all the required fields from a VB2 buffer to the MMAL buffer header,
-+ * ready for sending to the VPU.
-+ */
-+static void vb2_to_mmal_buffer(struct m2m_mmal_buffer *buf,
-+ struct vb2_v4l2_buffer *vb2)
-+{
-+ buf->mmal.mmal_flags = 0;
-+ if (vb2->flags & V4L2_BUF_FLAG_KEYFRAME)
-+ buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_KEYFRAME;
-+
-+ /*
-+ * Adding this means that the data must be framed correctly as one frame
-+ * per buffer. The underlying decoder has no such requirement, but it
-+ * will reduce latency as the bistream parser will be kicked immediately
-+ * to parse the frame, rather than relying on its own heuristics for
-+ * when to wake up.
-+ */
-+ buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;
-+
-+ buf->mmal.length = vb2->vb2_buf.planes[0].bytesused;
-+ /*
-+ * Minor ambiguity in the V4L2 spec as to whether passing in a 0 length
-+ * buffer, or one with V4L2_BUF_FLAG_LAST set denotes end of stream.
-+ * Handle either.
-+ */
-+ if (!buf->mmal.length || vb2->flags & V4L2_BUF_FLAG_LAST)
-+ buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
-+
-+ buf->mmal.pts = vb2->vb2_buf.timestamp;
-+ buf->mmal.dts = MMAL_TIME_UNKNOWN;
-+}
-+
-+/* device_run() - prepares and starts the device
-+ *
-+ * This simulates all the immediate preparations required before starting
-+ * a device. This will be called by the framework when it decides to schedule
-+ * a particular instance.
-+ */
-+static void device_run(void *priv)
-+{
-+ struct bcm2835_codec_ctx *ctx = priv;
-+ struct bcm2835_codec_dev *dev = ctx->dev;
-+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
-+ struct m2m_mmal_buffer *src_m2m_buf, *dst_m2m_buf;
-+ struct v4l2_m2m_buffer *m2m;
-+ int ret;
-+
-+ v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: off we go\n", __func__);
-+
-+ src_buf = v4l2_m2m_buf_remove(&ctx->fh.m2m_ctx->out_q_ctx);
-+ if (src_buf) {
-+ m2m = container_of(src_buf, struct v4l2_m2m_buffer, vb);
-+ src_m2m_buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
-+ vb2_to_mmal_buffer(src_m2m_buf, src_buf);
-+
-+ ret = vchiq_mmal_submit_buffer(dev->instance,
-+ &ctx->component->input[0],
-+ &src_m2m_buf->mmal);
-+ v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: Submitted ip buffer len %lu, pts %llu, flags %04x\n",
-+ __func__, src_m2m_buf->mmal.length,
-+ src_m2m_buf->mmal.pts, src_m2m_buf->mmal.mmal_flags);
-+ if (ret)
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed submitting ip buffer\n",
-+ __func__);
-+ }
-+
-+ dst_buf = v4l2_m2m_buf_remove(&ctx->fh.m2m_ctx->cap_q_ctx);
-+ if (dst_buf) {
-+ m2m = container_of(dst_buf, struct v4l2_m2m_buffer, vb);
-+ dst_m2m_buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
-+ vb2_to_mmal_buffer(dst_m2m_buf, dst_buf);
-+
-+ ret = vchiq_mmal_submit_buffer(dev->instance,
-+ &ctx->component->output[0],
-+ &dst_m2m_buf->mmal);
-+ if (ret)
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed submitting op buffer\n",
-+ __func__);
-+ }
-+
-+ v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: Submitted src %p, dst %p\n",
-+ __func__, src_m2m_buf, dst_m2m_buf);
-+
-+ /* Complete the job here. */
-+ v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
-+}
-+
-+/*
-+ * video ioctls
-+ */
-+static int vidioc_querycap(struct file *file, void *priv,
-+ struct v4l2_capability *cap)
-+{
-+ strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
-+ strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
-+ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
-+ MEM2MEM_NAME);
-+ cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
-+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-+ return 0;
-+}
-+
-+static int enum_fmt(struct v4l2_fmtdesc *f, bool decode, bool capture)
-+{
-+ struct bcm2835_codec_fmt *fmt;
-+ struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
-+
-+ if (f->index < fmts->num_entries) {
-+ /* Format found */
-+ /* Check format isn't a decode only format when encoding */
-+ if (!decode &&
-+ fmts->list[f->index].decode_only)
-+ return -EINVAL;
-+ /* Check format isn't a decode only format when encoding */
-+ if (decode &&
-+ fmts->list[f->index].encode_only)
-+ return -EINVAL;
-+
-+ fmt = &fmts->list[f->index];
-+ f->pixelformat = fmt->fourcc;
-+ f->flags = fmt->flags;
-+ return 0;
-+ }
-+
-+ /* Format not found */
-+ return -EINVAL;
-+}
-+
-+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
-+ struct v4l2_fmtdesc *f)
-+{
-+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+ return enum_fmt(f, ctx->dev->decode, true);
-+}
-+
-+static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
-+ struct v4l2_fmtdesc *f)
-+{
-+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+ return enum_fmt(f, ctx->dev->decode, false);
-+}
-+
-+static int vidioc_g_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f)
-+{
-+ struct vb2_queue *vq;
-+ struct bcm2835_codec_q_data *q_data;
-+
-+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-+ if (!vq)
-+ return -EINVAL;
-+
-+ q_data = get_q_data(ctx, f->type);
-+
-+ f->fmt.pix.width = q_data->crop_width;
-+ f->fmt.pix.height = q_data->height;
-+ f->fmt.pix.field = V4L2_FIELD_NONE;
-+ f->fmt.pix.pixelformat = q_data->fmt->fourcc;
-+ f->fmt.pix.bytesperline = q_data->bytesperline;
-+ f->fmt.pix.sizeimage = q_data->sizeimage;
-+ f->fmt.pix.colorspace = ctx->colorspace;
-+ f->fmt.pix.xfer_func = ctx->xfer_func;
-+ f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc;
-+ f->fmt.pix.quantization = ctx->quant;
-+
-+ return 0;
-+}
-+
-+static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
-+ struct v4l2_format *f)
-+{
-+ return vidioc_g_fmt(file2ctx(file), f);
-+}
-+
-+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-+ struct v4l2_format *f)
-+{
-+ return vidioc_g_fmt(file2ctx(file), f);
-+}
-+
-+static int vidioc_try_fmt(struct v4l2_format *f, struct bcm2835_codec_fmt *fmt)
-+{
-+ /*
-+ * The V4L2 specification requires the driver to correct the format
-+ * struct if any of the dimensions is unsupported
-+ */
-+ if (f->fmt.pix.width > MAX_W)
-+ f->fmt.pix.width = MAX_W;
-+ if (f->fmt.pix.height > MAX_H)
-+ f->fmt.pix.height = MAX_H;
-+
-+ if (!fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
-+ /* Only clip min w/h on capture. Treat 0x0 as unknown. */
-+ if (f->fmt.pix.width < MIN_W)
-+ f->fmt.pix.width = MIN_W;
-+ if (f->fmt.pix.height < MIN_H)
-+ f->fmt.pix.height = MIN_H;
-+
-+ /*
-+ * Buffer must have a vertical alignment of 16 lines.
-+ * The selection will reflect any cropping rectangle when only
-+ * some of the pixels are active.
-+ */
-+ f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
-+
-+ f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
-+ fmt);
-+ f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
-+ f->fmt.pix.height,
-+ fmt);
-+ } else {
-+ u32 min_size = f->fmt.pix.width > 1280 ||
-+ f->fmt.pix.height > 720 ?
-+ DEF_COMP_BUF_SIZE_GREATER_720P :
-+ DEF_COMP_BUF_SIZE_720P_OR_LESS;
-+
-+ f->fmt.pix.bytesperline = 0;
-+ if (f->fmt.pix.sizeimage < min_size)
-+ f->fmt.pix.sizeimage = min_size;
-+ }
-+
-+ f->fmt.pix.field = V4L2_FIELD_NONE;
-+
-+ return 0;
-+}
-+
-+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-+ struct v4l2_format *f)
-+{
-+ struct bcm2835_codec_fmt *fmt;
-+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+ fmt = find_format(f, ctx->dev->decode, true);
-+ if (!fmt) {
-+ f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
-+ true)->fourcc;
-+ fmt = find_format(f, ctx->dev->decode, true);
-+ }
-+
-+ return vidioc_try_fmt(f, fmt);
-+}
-+
-+static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
-+ struct v4l2_format *f)
-+{
-+ struct bcm2835_codec_fmt *fmt;
-+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+ fmt = find_format(f, ctx->dev->decode, false);
-+ if (!fmt) {
-+ f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
-+ false)->fourcc;
-+ fmt = find_format(f, ctx->dev->decode, false);
-+ }
-+
-+ if (!f->fmt.pix.colorspace)
-+ f->fmt.pix.colorspace = ctx->colorspace;
-+
-+ return vidioc_try_fmt(f, fmt);
-+}
-+
-+static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
-+ unsigned int requested_height)
-+{
-+ struct bcm2835_codec_q_data *q_data;
-+ struct vb2_queue *vq;
-+ struct vchiq_mmal_port *port;
-+ bool update_capture_port = false;
-+ int ret;
-+
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
-+ f->type, f->fmt.pix.width, f->fmt.pix.height,
-+ f->fmt.pix.pixelformat, f->fmt.pix.sizeimage);
-+
-+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-+ if (!vq)
-+ return -EINVAL;
-+
-+ q_data = get_q_data(ctx, f->type);
-+ if (!q_data)
-+ return -EINVAL;
-+
-+ if (vb2_is_busy(vq)) {
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
-+ return -EBUSY;
-+ }
-+
-+ q_data->fmt = find_format(f, ctx->dev->decode,
-+ f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
-+ q_data->crop_width = f->fmt.pix.width;
-+ q_data->height = f->fmt.pix.height;
-+ if (!q_data->selection_set)
-+ q_data->crop_height = requested_height;
-+
-+ /*
-+ * Copying the behaviour of vicodec which retains a single set of
-+ * colorspace parameters for both input and output.
-+ */
-+ ctx->colorspace = f->fmt.pix.colorspace;
-+ ctx->xfer_func = f->fmt.pix.xfer_func;
-+ ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
-+ ctx->quant = f->fmt.pix.quantization;
-+
-+ /* All parameters should have been set correctly by try_fmt */
-+ q_data->bytesperline = f->fmt.pix.bytesperline;
-+ q_data->sizeimage = f->fmt.pix.sizeimage;
-+
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
-+ q_data->bytesperline, q_data->sizeimage);
-+
-+ if (ctx->dev->decode && q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
-+ f->fmt.pix.width && f->fmt.pix.height) {
-+ /*
-+ * On the decoder, if provided with a resolution on the input
-+ * side, then replicate that to the output side.
-+ * GStreamer appears not to support V4L2_EVENT_SOURCE_CHANGE,
-+ * nor set up a resolution on the output side, therefore
-+ * we can't decode anything at a resolution other than the
-+ * default one.
-+ */
-+ struct bcm2835_codec_q_data *q_data_dst =
-+ &ctx->q_data[V4L2_M2M_DST];
-+
-+ q_data_dst->crop_width = q_data->crop_width;
-+ q_data_dst->crop_height = q_data->crop_height;
-+ q_data_dst->height = ALIGN(q_data->crop_height, 16);
-+
-+ q_data_dst->bytesperline =
-+ get_bytesperline(f->fmt.pix.width, q_data_dst->fmt);
-+ q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
-+ q_data_dst->height,
-+ q_data_dst->fmt);
-+ update_capture_port = true;
-+ }
-+
-+ /* If we have a component then setup the port as well */
-+ port = get_port_data(ctx, vq->type);
-+ if (!port)
-+ return 0;
-+
-+ setup_mmal_port_format(ctx, ctx->dev->decode, q_data, port);
-+ ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
-+ if (ret) {
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on port, ret %d\n",
-+ __func__, ret);
-+ ret = -EINVAL;
-+ }
-+
-+ if (q_data->sizeimage < port->minimum_buffer.size) {
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Current buffer size of %u < min buf size %u - driver mismatch to MMAL\n",
-+ __func__, q_data->sizeimage,
-+ port->minimum_buffer.size);
-+ }
-+
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Set format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
-+ f->type, q_data->crop_width, q_data->height,
-+ q_data->fmt->fourcc, q_data->sizeimage);
-+
-+ if (update_capture_port) {
-+ struct vchiq_mmal_port *port_dst = &ctx->component->output[0];
-+ struct bcm2835_codec_q_data *q_data_dst =
-+ &ctx->q_data[V4L2_M2M_DST];
-+
-+ setup_mmal_port_format(ctx, ctx->dev->decode, q_data_dst,
-+ port_dst);
-+ ret = vchiq_mmal_port_set_format(ctx->dev->instance, port_dst);
-+ if (ret) {
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on output port, ret %d\n",
-+ __func__, ret);
-+ ret = -EINVAL;
-+ }
-+ }
-+ return ret;
-+}
-+
-+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-+ struct v4l2_format *f)
-+{
-+ unsigned int height = f->fmt.pix.height;
-+ int ret;
-+
-+ ret = vidioc_try_fmt_vid_cap(file, priv, f);
-+ if (ret)
-+ return ret;
-+
-+ return vidioc_s_fmt(file2ctx(file), f, height);
-+}
-+
-+static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
-+ struct v4l2_format *f)
-+{
-+ unsigned int height = f->fmt.pix.height;
-+ int ret;
-+
-+ ret = vidioc_try_fmt_vid_out(file, priv, f);
-+ if (ret)
-+ return ret;
-+
-+ ret = vidioc_s_fmt(file2ctx(file), f, height);
-+ return ret;
-+}
-+
-+static int vidioc_g_selection(struct file *file, void *priv,
-+ struct v4l2_selection *s)
-+{
-+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+ struct bcm2835_codec_q_data *q_data;
-+ bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
-+ true : false;
-+
-+ if (capture_queue ^ ctx->dev->decode)
-+ /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
-+ return -EINVAL;
-+
-+ q_data = get_q_data(ctx, s->type);
-+ if (!q_data)
-+ return -EINVAL;
-+
-+ if (ctx->dev->decode) {
-+ switch (s->target) {
-+ case V4L2_SEL_TGT_COMPOSE_DEFAULT:
-+ case V4L2_SEL_TGT_COMPOSE:
-+ s->r.left = 0;
-+ s->r.top = 0;
-+ s->r.width = q_data->crop_width;
-+ s->r.height = q_data->crop_height;
-+ break;
-+ case V4L2_SEL_TGT_COMPOSE_BOUNDS:
-+ s->r.left = 0;
-+ s->r.top = 0;
-+ s->r.width = q_data->crop_width;
-+ s->r.height = q_data->crop_height;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ } else {
-+ switch (s->target) {
-+ case V4L2_SEL_TGT_CROP_DEFAULT:
-+ case V4L2_SEL_TGT_CROP_BOUNDS:
-+ s->r.top = 0;
-+ s->r.left = 0;
-+ s->r.width = q_data->bytesperline;
-+ s->r.height = q_data->height;
-+ break;
-+ case V4L2_SEL_TGT_CROP:
-+ s->r.top = 0;
-+ s->r.left = 0;
-+ s->r.width = q_data->crop_width;
-+ s->r.height = q_data->crop_height;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static int vidioc_s_selection(struct file *file, void *priv,
-+ struct v4l2_selection *s)
-+{
-+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+ struct bcm2835_codec_q_data *q_data = NULL;
-+ bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
-+ true : false;
-+
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: ctx %p, type %d, q_data %p, target %d, rect x/y %d/%d, w/h %ux%u\n",
-+ __func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
-+ s->r.width, s->r.height);
-+
-+ if (capture_queue ^ ctx->dev->decode)
-+ /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
-+ return -EINVAL;
-+
-+ q_data = get_q_data(ctx, s->type);
-+ if (!q_data)
-+ return -EINVAL;
-+
-+ if (ctx->dev->decode) {
-+ switch (s->target) {
-+ case V4L2_SEL_TGT_COMPOSE:
-+ /* Accept cropped image */
-+ s->r.left = 0;
-+ s->r.top = 0;
-+ s->r.width = min(s->r.width, q_data->crop_width);
-+ s->r.height = min(s->r.height, q_data->height);
-+ q_data->crop_width = s->r.width;
-+ q_data->crop_height = s->r.height;
-+ q_data->selection_set = true;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ } else {
-+ switch (s->target) {
-+ case V4L2_SEL_TGT_CROP:
-+ /* Only support crop from (0,0) */
-+ s->r.top = 0;
-+ s->r.left = 0;
-+ s->r.width = min(s->r.width, q_data->crop_width);
-+ s->r.height = min(s->r.height, q_data->crop_height);
-+ q_data->crop_width = s->r.width;
-+ q_data->crop_height = s->r.height;
-+ q_data->selection_set = true;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static int vidioc_subscribe_evt(struct v4l2_fh *fh,
-+ const struct v4l2_event_subscription *sub)
-+{
-+ switch (sub->type) {
-+ case V4L2_EVENT_EOS:
-+ return v4l2_event_subscribe(fh, sub, 2, NULL);
-+ case V4L2_EVENT_SOURCE_CHANGE:
-+ return v4l2_src_change_event_subscribe(fh, sub);
-+ default:
-+ return v4l2_ctrl_subscribe_event(fh, sub);
-+ }
-+}
-+
-+static int bcm2835_codec_set_level_profile(struct bcm2835_codec_ctx *ctx,
-+ struct v4l2_ctrl *ctrl)
-+{
-+ struct mmal_parameter_video_profile param;
-+ int param_size = sizeof(param);
-+ int ret;
-+
-+ /*
-+ * Level and Profile are set via the same MMAL parameter.
-+ * Retrieve the current settings and amend the one that has changed.
-+ */
-+ ret = vchiq_mmal_port_parameter_get(ctx->dev->instance,
-+ &ctx->component->output[0],
-+ MMAL_PARAMETER_PROFILE,
-+ ¶m,
-+ ¶m_size);
-+ if (ret)
-+ return ret;
-+
-+ switch (ctrl->id) {
-+ case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
-+ switch (ctrl->val) {
-+ 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;
-+ }
-+ break;
-+
-+ case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
-+ switch (ctrl->val) {
-+ 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(ctx->dev->instance,
-+ &ctx->component->output[0],
-+ MMAL_PARAMETER_PROFILE,
-+ ¶m,
-+ param_size);
-+
-+ return ret;
-+}
-+
-+static int bcm2835_codec_s_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+ struct bcm2835_codec_ctx *ctx =
-+ container_of(ctrl->handler, struct bcm2835_codec_ctx, hdl);
-+ int ret = 0;
-+
-+ switch (ctrl->id) {
-+ case V4L2_CID_MPEG_VIDEO_BITRATE:
-+ ctx->bitrate = ctrl->val;
-+ if (!ctx->component)
-+ break;
-+
-+ ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
-+ &ctx->component->output[0],
-+ MMAL_PARAMETER_VIDEO_BIT_RATE,
-+ &ctrl->val,
-+ sizeof(ctrl->val));
-+ break;
-+
-+ case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: {
-+ u32 bitrate_mode;
-+
-+ if (!ctx->component)
-+ break;
-+
-+ 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;
-+ }
-+
-+ ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
-+ &ctx->component->output[0],
-+ MMAL_PARAMETER_RATECONTROL,
-+ &bitrate_mode,
-+ sizeof(bitrate_mode));
-+ break;
-+ }
-+ case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:
-+ if (!ctx->component)
-+ break;
-+
-+ ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
-+ &ctx->component->output[0],
-+ MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
-+ &ctrl->val,
-+ sizeof(ctrl->val));
-+ break;
-+
-+ case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
-+ if (!ctx->component)
-+ break;
-+
-+ ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
-+ &ctx->component->output[0],
-+ MMAL_PARAMETER_INTRAPERIOD,
-+ &ctrl->val,
-+ sizeof(ctrl->val));
-+ break;
-+
-+ case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
-+ case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
-+ if (!ctx->component)
-+ break;
-+
-+ ret = bcm2835_codec_set_level_profile(ctx, ctrl);
-+ break;
-+
-+ default:
-+ v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
-+ return -EINVAL;
-+ }
-+
-+ if (ret)
-+ v4l2_err(&ctx->dev->v4l2_dev, "Failed setting ctrl %08x, ret %d\n",
-+ ctrl->id, ret);
-+ return ret ? -EINVAL : 0;
-+}
-+
-+static const struct v4l2_ctrl_ops bcm2835_codec_ctrl_ops = {
-+ .s_ctrl = bcm2835_codec_s_ctrl,
-+};
-+
-+static int vidioc_try_decoder_cmd(struct file *file, void *priv,
-+ struct v4l2_decoder_cmd *cmd)
-+{
-+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+ if (!ctx->dev->decode)
-+ return -EINVAL;
-+
-+ switch (cmd->cmd) {
-+ case V4L2_DEC_CMD_STOP:
-+ if (cmd->flags & V4L2_DEC_CMD_STOP_TO_BLACK) {
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: DEC cmd->flags=%u stop to black not supported",
-+ __func__, cmd->flags);
-+ return -EINVAL;
-+ }
-+ break;
-+ case V4L2_DEC_CMD_START:
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+
-+static int vidioc_decoder_cmd(struct file *file, void *priv,
-+ struct v4l2_decoder_cmd *cmd)
-+{
-+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+ struct bcm2835_codec_q_data *q_data = &ctx->q_data[V4L2_M2M_SRC];
-+ int ret;
-+
-+ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s, cmd %u", __func__,
-+ cmd->cmd);
-+ ret = vidioc_try_decoder_cmd(file, priv, cmd);
-+ if (ret)
-+ return ret;
-+
-+ switch (cmd->cmd) {
-+ case V4L2_DEC_CMD_STOP:
-+ if (q_data->eos_buffer_in_use)
-+ v4l2_err(&ctx->dev->v4l2_dev, "EOS buffers already in use\n");
-+ q_data->eos_buffer_in_use = true;
-+
-+ q_data->eos_buffer.mmal.buffer_size = 0;
-+ q_data->eos_buffer.mmal.length = 0;
-+ q_data->eos_buffer.mmal.mmal_flags =
-+ MMAL_BUFFER_HEADER_FLAG_EOS;
-+ q_data->eos_buffer.mmal.pts = 0;
-+ q_data->eos_buffer.mmal.dts = 0;
-+
-+ if (!ctx->component)
-+ break;
-+
-+ ret = vchiq_mmal_submit_buffer(ctx->dev->instance,
-+ &ctx->component->input[0],
-+ &q_data->eos_buffer.mmal);
-+ if (ret)
-+ v4l2_err(&ctx->dev->v4l2_dev,
-+ "%s: EOS buffer submit failed %d\n",
-+ __func__, ret);
-+
-+ break;
-+
-+ case V4L2_DEC_CMD_START:
-+ /* Do we need to do anything here? */
-+ break;
-+
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static int vidioc_try_encoder_cmd(struct file *file, void *priv,
-+ struct v4l2_encoder_cmd *cmd)
-+{
-+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+ if (ctx->dev->decode)
-+ return -EINVAL;
-+
-+ switch (cmd->cmd) {
-+ case V4L2_ENC_CMD_STOP:
-+ break;
-+
-+ case V4L2_ENC_CMD_START:
-+ /* Do we need to do anything here? */
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+
-+static int vidioc_encoder_cmd(struct file *file, void *priv,
-+ struct v4l2_encoder_cmd *cmd)
-+{
-+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+ struct bcm2835_codec_q_data *q_data = &ctx->q_data[V4L2_M2M_SRC];
-+ int ret;
-+
-+ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s, cmd %u", __func__,
-+ cmd->cmd);
-+ ret = vidioc_try_encoder_cmd(file, priv, cmd);
-+ if (ret)
-+ return ret;
-+
-+ switch (cmd->cmd) {
-+ case V4L2_ENC_CMD_STOP:
-+ if (q_data->eos_buffer_in_use)
-+ v4l2_err(&ctx->dev->v4l2_dev, "EOS buffers already in use\n");
-+ q_data->eos_buffer_in_use = true;
-+
-+ q_data->eos_buffer.mmal.buffer_size = 0;
-+ q_data->eos_buffer.mmal.length = 0;
-+ q_data->eos_buffer.mmal.mmal_flags =
-+ MMAL_BUFFER_HEADER_FLAG_EOS;
-+ q_data->eos_buffer.mmal.pts = 0;
-+ q_data->eos_buffer.mmal.dts = 0;
-+
-+ if (!ctx->component)
-+ break;
-+
-+ ret = vchiq_mmal_submit_buffer(ctx->dev->instance,
-+ &ctx->component->input[0],
-+ &q_data->eos_buffer.mmal);
-+ if (ret)
-+ v4l2_err(&ctx->dev->v4l2_dev,
-+ "%s: EOS buffer submit failed %d\n",
-+ __func__, ret);
-+
-+ break;
-+ case V4L2_ENC_CMD_START:
-+ /* Do we need to do anything here? */
-+ break;
-+
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static const struct v4l2_ioctl_ops bcm2835_codec_ioctl_ops = {
-+ .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,
-+
-+ .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
-+ .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out,
-+ .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
-+ .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
-+
-+ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
-+ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
-+ .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
-+ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
-+ .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
-+ .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
-+ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
-+
-+ .vidioc_streamon = v4l2_m2m_ioctl_streamon,
-+ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
-+
-+ .vidioc_g_selection = vidioc_g_selection,
-+ .vidioc_s_selection = vidioc_s_selection,
-+
-+ .vidioc_subscribe_event = vidioc_subscribe_evt,
-+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-+
-+ .vidioc_decoder_cmd = vidioc_decoder_cmd,
-+ .vidioc_try_decoder_cmd = vidioc_try_decoder_cmd,
-+ .vidioc_encoder_cmd = vidioc_encoder_cmd,
-+ .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd,
-+};
-+
-+static int bcm2835_codec_set_ctrls(struct bcm2835_codec_ctx *ctx)
-+{
-+ /*
-+ * Query the control handler for the value of the various controls and
-+ * set them.
-+ */
-+ const u32 control_ids[] = {
-+ V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
-+ V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER,
-+ V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
-+ V4L2_CID_MPEG_VIDEO_H264_LEVEL,
-+ V4L2_CID_MPEG_VIDEO_H264_PROFILE,
-+ };
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(control_ids); i++) {
-+ struct v4l2_ctrl *ctrl;
-+
-+ ctrl = v4l2_ctrl_find(&ctx->hdl, control_ids[i]);
-+ if (ctrl)
-+ bcm2835_codec_s_ctrl(ctrl);
-+ }
-+
-+ return 0;
-+}
-+
-+static int bcm2835_codec_create_component(struct bcm2835_codec_ctx *ctx)
-+{
-+ struct bcm2835_codec_dev *dev = ctx->dev;
-+ unsigned int enable = 1;
-+ int ret;
-+
-+ ret = vchiq_mmal_component_init(dev->instance, dev->decode ?
-+ "ril.video_decode" : "ril.video_encode",
-+ &ctx->component);
-+ if (ret < 0) {
-+ v4l2_err(&dev->v4l2_dev, "%s: failed to create component for %s\n",
-+ __func__, dev->decode ? "decode" : "encode");
-+ return -ENOMEM;
-+ }
-+
-+ vchiq_mmal_port_parameter_set(dev->instance, &ctx->component->input[0],
-+ MMAL_PARAMETER_ZERO_COPY, &enable,
-+ sizeof(enable));
-+ vchiq_mmal_port_parameter_set(dev->instance, &ctx->component->output[0],
-+ MMAL_PARAMETER_ZERO_COPY, &enable,
-+ sizeof(enable));
-+
-+ setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_SRC],
-+ &ctx->component->input[0]);
-+
-+ setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_DST],
-+ &ctx->component->output[0]);
-+
-+ ret = vchiq_mmal_port_set_format(dev->instance,
-+ &ctx->component->input[0]);
-+ if (ret < 0)
-+ goto destroy_component;
-+
-+ ret = vchiq_mmal_port_set_format(dev->instance,
-+ &ctx->component->output[0]);
-+ if (ret < 0)
-+ goto destroy_component;
-+
-+ if (dev->decode) {
-+ if (ctx->q_data[V4L2_M2M_DST].sizeimage <
-+ ctx->component->output[0].minimum_buffer.size)
-+ v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
-+ ctx->q_data[V4L2_M2M_DST].sizeimage,
-+ ctx->component->output[0].minimum_buffer.size);
-+ } else {
-+ if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
-+ ctx->component->output[0].minimum_buffer.size)
-+ v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
-+ ctx->q_data[V4L2_M2M_SRC].sizeimage,
-+ ctx->component->output[0].minimum_buffer.size);
-+
-+ /* Now we have a component we can set all the ctrls */
-+ bcm2835_codec_set_ctrls(ctx);
-+ }
-+
-+ return 0;
-+
-+destroy_component:
-+ vchiq_mmal_component_finalise(ctx->dev->instance, ctx->component);
-+
-+ return ret;
-+}
-+
-+/*
-+ * Queue operations
-+ */
-+
-+static int bcm2835_codec_queue_setup(struct vb2_queue *vq,
-+ unsigned int *nbuffers,
-+ unsigned int *nplanes,
-+ unsigned int sizes[],
-+ struct device *alloc_devs[])
-+{
-+ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vq);
-+ struct bcm2835_codec_q_data *q_data;
-+ struct vchiq_mmal_port *port;
-+ unsigned int size;
-+
-+ q_data = get_q_data(ctx, vq->type);
-+ if (!q_data)
-+ return -EINVAL;
-+
-+ if (!ctx->component)
-+ if (bcm2835_codec_create_component(ctx))
-+ return -EINVAL;
-+
-+ port = get_port_data(ctx, vq->type);
-+
-+ size = q_data->sizeimage;
-+
-+ if (*nplanes)
-+ return sizes[0] < size ? -EINVAL : 0;
-+
-+ *nplanes = 1;
-+
-+ sizes[0] = size;
-+ port->current_buffer.size = size;
-+
-+ if (*nbuffers < port->minimum_buffer.num)
-+ *nbuffers = port->minimum_buffer.num;
-+ /* Add one buffer to take an EOS */
-+ port->current_buffer.num = *nbuffers + 1;
-+
-+ return 0;
-+}
-+
-+static int bcm2835_codec_buf_init(struct vb2_buffer *vb)
-+{
-+ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-+ struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
-+ struct v4l2_m2m_buffer *m2m = container_of(vb2, struct v4l2_m2m_buffer,
-+ vb);
-+ struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
-+ m2m);
-+
-+ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
-+ __func__, ctx, vb);
-+ buf->mmal.buffer = vb2_plane_vaddr(&buf->m2m.vb.vb2_buf, 0);
-+ buf->mmal.buffer_size = vb2_plane_size(&buf->m2m.vb.vb2_buf, 0);
-+
-+ mmal_vchi_buffer_init(ctx->dev->instance, &buf->mmal);
-+
-+ return 0;
-+}
-+
-+static int bcm2835_codec_buf_prepare(struct vb2_buffer *vb)
-+{
-+ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-+ struct bcm2835_codec_q_data *q_data;
-+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-+ struct v4l2_m2m_buffer *m2m = container_of(vbuf, struct v4l2_m2m_buffer,
-+ vb);
-+ struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
-+ m2m);
-+ int ret;
-+
-+ v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p\n",
-+ __func__, vb->vb2_queue->type, vb);
-+
-+ q_data = get_q_data(ctx, vb->vb2_queue->type);
-+ if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
-+ if (vbuf->field == V4L2_FIELD_ANY)
-+ vbuf->field = V4L2_FIELD_NONE;
-+ if (vbuf->field != V4L2_FIELD_NONE) {
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s field isn't supported\n",
-+ __func__);
-+ return -EINVAL;
-+ }
-+ }
-+
-+ if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s data will not fit into plane (%lu < %lu)\n",
-+ __func__, vb2_plane_size(vb, 0),
-+ (long)q_data->sizeimage);
-+ return -EINVAL;
-+ }
-+
-+ if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
-+ vb2_set_plane_payload(vb, 0, q_data->sizeimage);
-+
-+ /*
-+ * We want to do this at init, but vb2_core_expbuf checks that the
-+ * index < q->num_buffers, and q->num_buffers only gets updated once
-+ * all the buffers are allocated.
-+ */
-+ if (!buf->mmal.dma_buf) {
-+ ret = vb2_core_expbuf_dmabuf(vb->vb2_queue,
-+ vb->vb2_queue->type, vb->index, 0,
-+ O_CLOEXEC, &buf->mmal.dma_buf);
-+ if (ret)
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed to expbuf idx %d, ret %d\n",
-+ __func__, vb->index, ret);
-+ } else {
-+ ret = 0;
-+ }
-+
-+ return ret;
-+}
-+
-+static void bcm2835_codec_buf_queue(struct vb2_buffer *vb)
-+{
-+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-+ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-+
-+ v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p vbuf->flags %u, seq %u, bytesused %u\n",
-+ __func__, vb->vb2_queue->type, vb, vbuf->flags, vbuf->sequence,
-+ vb->planes[0].bytesused);
-+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
-+}
-+
-+static void bcm2835_codec_buffer_cleanup(struct vb2_buffer *vb)
-+{
-+ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-+ struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
-+ struct v4l2_m2m_buffer *m2m = container_of(vb2, struct v4l2_m2m_buffer,
-+ vb);
-+ struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
-+ m2m);
-+
-+ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
-+ __func__, ctx, vb);
-+
-+ mmal_vchi_buffer_cleanup(&buf->mmal);
-+
-+ if (buf->mmal.dma_buf) {
-+ dma_buf_put(buf->mmal.dma_buf);
-+ buf->mmal.dma_buf = NULL;
-+ }
-+}
-+
-+static int bcm2835_codec_start_streaming(struct vb2_queue *q,
-+ unsigned int count)
-+{
-+ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(q);
-+ struct bcm2835_codec_dev *dev = ctx->dev;
-+ struct bcm2835_codec_q_data *q_data = get_q_data(ctx, q->type);
-+ int ret;
-+
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d count %d\n",
-+ __func__, q->type, count);
-+ q_data->sequence = 0;
-+
-+ if (!ctx->component_enabled) {
-+ ret = vchiq_mmal_component_enable(dev->instance,
-+ ctx->component);
-+ if (ret)
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling component, ret %d\n",
-+ __func__, ret);
-+ ctx->component_enabled = true;
-+ }
-+
-+ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-+ /*
-+ * Create the EOS buffer.
-+ * We only need the MMAL part, and want to NOT attach a memory
-+ * buffer to it as it should only take flags.
-+ */
-+ memset(&q_data->eos_buffer, 0, sizeof(q_data->eos_buffer));
-+ mmal_vchi_buffer_init(dev->instance,
-+ &q_data->eos_buffer.mmal);
-+ q_data->eos_buffer_in_use = false;
-+
-+ ctx->component->input[0].cb_ctx = ctx;
-+ ret = vchiq_mmal_port_enable(dev->instance,
-+ &ctx->component->input[0],
-+ ip_buffer_cb);
-+ if (ret)
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling i/p port, ret %d\n",
-+ __func__, ret);
-+ } else {
-+ ctx->component->output[0].cb_ctx = ctx;
-+ ret = vchiq_mmal_port_enable(dev->instance,
-+ &ctx->component->output[0],
-+ op_buffer_cb);
-+ if (ret)
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
-+ __func__, ret);
-+ }
-+ return ret;
-+}
-+
-+static void bcm2835_codec_stop_streaming(struct vb2_queue *q)
-+{
-+ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(q);
-+ struct bcm2835_codec_dev *dev = ctx->dev;
-+ struct bcm2835_codec_q_data *q_data = get_q_data(ctx, q->type);
-+ struct vchiq_mmal_port *port = get_port_data(ctx, q->type);
-+ struct vb2_v4l2_buffer *vbuf;
-+ struct vb2_v4l2_buffer *vb2;
-+ struct v4l2_m2m_buffer *m2m;
-+ struct m2m_mmal_buffer *buf;
-+ int ret, i;
-+
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d - return buffers\n",
-+ __func__, q->type);
-+
-+ init_completion(&ctx->frame_cmplt);
-+
-+ /* Clear out all buffers held by m2m framework */
-+ for (;;) {
-+ if (V4L2_TYPE_IS_OUTPUT(q->type))
-+ vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-+ else
-+ vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-+ if (!vbuf)
-+ break;
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: return buffer %p\n",
-+ __func__, vbuf);
-+
-+ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
-+ }
-+
-+ /* Disable MMAL port - this will flush buffers back */
-+ ret = vchiq_mmal_port_disable(dev->instance, port);
-+ if (ret)
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed disabling %s port, ret %d\n",
-+ __func__, V4L2_TYPE_IS_OUTPUT(q->type) ? "i/p" : "o/p",
-+ ret);
-+
-+ while (atomic_read(&port->buffers_with_vpu)) {
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Waiting for buffers to be returned - %d outstanding\n",
-+ __func__, atomic_read(&port->buffers_with_vpu));
-+ ret = wait_for_completion_timeout(&ctx->frame_cmplt, HZ);
-+ if (ret <= 0) {
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n",
-+ __func__,
-+ atomic_read(&port->buffers_with_vpu));
-+ break;
-+ }
-+ }
-+
-+ /*
-+ * Release the VCSM handle here as otherwise REQBUFS(0) aborts because
-+ * someone is using the dmabuf before giving the driver a chance to do
-+ * anything about it.
-+ */
-+ for (i = 0; i < q->num_buffers; i++) {
-+ vb2 = to_vb2_v4l2_buffer(q->bufs[i]);
-+ m2m = container_of(vb2, struct v4l2_m2m_buffer, vb);
-+ buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
-+
-+ mmal_vchi_buffer_cleanup(&buf->mmal);
-+ if (buf->mmal.dma_buf) {
-+ dma_buf_put(buf->mmal.dma_buf);
-+ buf->mmal.dma_buf = NULL;
-+ }
-+ }
-+
-+ /* If both ports disabled, then disable the component */
-+ if (!ctx->component->input[0].enabled &&
-+ !ctx->component->output[0].enabled) {
-+ ret = vchiq_mmal_component_disable(dev->instance,
-+ ctx->component);
-+ if (ret)
-+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling component, ret %d\n",
-+ __func__, ret);
-+ }
-+
-+ if (V4L2_TYPE_IS_OUTPUT(q->type))
-+ mmal_vchi_buffer_cleanup(&q_data->eos_buffer.mmal);
-+
-+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: done\n", __func__);
-+}
-+
-+static const struct vb2_ops bcm2835_codec_qops = {
-+ .queue_setup = bcm2835_codec_queue_setup,
-+ .buf_init = bcm2835_codec_buf_init,
-+ .buf_prepare = bcm2835_codec_buf_prepare,
-+ .buf_queue = bcm2835_codec_buf_queue,
-+ .buf_cleanup = bcm2835_codec_buffer_cleanup,
-+ .start_streaming = bcm2835_codec_start_streaming,
-+ .stop_streaming = bcm2835_codec_stop_streaming,
-+ .wait_prepare = vb2_ops_wait_prepare,
-+ .wait_finish = vb2_ops_wait_finish,
-+};
-+
-+static int queue_init(void *priv, struct vb2_queue *src_vq,
-+ struct vb2_queue *dst_vq)
-+{
-+ struct bcm2835_codec_ctx *ctx = priv;
-+ int ret;
-+
-+ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-+ src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
-+ src_vq->drv_priv = ctx;
-+ src_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
-+ src_vq->ops = &bcm2835_codec_qops;
-+ src_vq->mem_ops = &vb2_dma_contig_memops;
-+ src_vq->dev = &ctx->dev->pdev->dev;
-+ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-+ src_vq->lock = &ctx->dev->dev_mutex;
-+
-+ ret = vb2_queue_init(src_vq);
-+ if (ret)
-+ return ret;
-+
-+ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-+ dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
-+ dst_vq->drv_priv = ctx;
-+ dst_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
-+ dst_vq->ops = &bcm2835_codec_qops;
-+ dst_vq->mem_ops = &vb2_dma_contig_memops;
-+ dst_vq->dev = &ctx->dev->pdev->dev;
-+ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-+ dst_vq->lock = &ctx->dev->dev_mutex;
-+
-+ return vb2_queue_init(dst_vq);
-+}
-+
-+/*
-+ * File operations
-+ */
-+static int bcm2835_codec_open(struct file *file)
-+{
-+ struct bcm2835_codec_dev *dev = video_drvdata(file);
-+ struct bcm2835_codec_ctx *ctx = NULL;
-+ struct v4l2_ctrl_handler *hdl;
-+ int rc = 0;
-+
-+ v4l2_dbg(1, debug, &dev->v4l2_dev, "Creating instance for %s\n",
-+ dev->decode ? "decode" : "encode");
-+ if (mutex_lock_interruptible(&dev->dev_mutex)) {
-+ v4l2_err(&dev->v4l2_dev, "Mutex fail\n");
-+ return -ERESTARTSYS;
-+ }
-+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-+ if (!ctx) {
-+ rc = -ENOMEM;
-+ goto open_unlock;
-+ }
-+
-+ ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev->decode, false);
-+ ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev->decode, true);
-+ if (dev->decode) {
-+ /*
-+ * Input width and height are irrelevant as they will be defined
-+ * by the bitstream not the format. Required by V4L2 though.
-+ */
-+ ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
-+ ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
-+ ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
-+ ctx->q_data[V4L2_M2M_SRC].bytesperline = 0;
-+ ctx->q_data[V4L2_M2M_SRC].sizeimage =
-+ DEF_COMP_BUF_SIZE_720P_OR_LESS;
-+
-+ ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
-+ ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
-+ ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
-+ ctx->q_data[V4L2_M2M_DST].bytesperline =
-+ get_bytesperline(DEFAULT_WIDTH,
-+ ctx->q_data[V4L2_M2M_DST].fmt);
-+ ctx->q_data[V4L2_M2M_DST].sizeimage =
-+ get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
-+ ctx->q_data[V4L2_M2M_DST].height,
-+ ctx->q_data[V4L2_M2M_DST].fmt);
-+ } else {
-+ ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
-+ ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
-+ ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
-+ ctx->q_data[V4L2_M2M_SRC].bytesperline =
-+ get_bytesperline(DEFAULT_WIDTH,
-+ ctx->q_data[V4L2_M2M_SRC].fmt);
-+ ctx->q_data[V4L2_M2M_SRC].sizeimage =
-+ get_sizeimage(ctx->q_data[V4L2_M2M_SRC].bytesperline,
-+ ctx->q_data[V4L2_M2M_SRC].height,
-+ ctx->q_data[V4L2_M2M_SRC].fmt);
-+
-+ ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
-+ ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
-+ ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
-+ ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
-+ ctx->q_data[V4L2_M2M_DST].sizeimage =
-+ DEF_COMP_BUF_SIZE_720P_OR_LESS;
-+ }
-+
-+ ctx->colorspace = V4L2_COLORSPACE_REC709;
-+ ctx->bitrate = 10 * 1000 * 1000;
-+
-+ /* Initialise V4L2 contexts */
-+ v4l2_fh_init(&ctx->fh, video_devdata(file));
-+ file->private_data = &ctx->fh;
-+ ctx->dev = dev;
-+ hdl = &ctx->hdl;
-+ if (!dev->decode) {
-+ /* Encode controls */
-+ v4l2_ctrl_handler_init(hdl, 6);
-+
-+ v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
-+ V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
-+ V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
-+ V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
-+ v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
-+ V4L2_CID_MPEG_VIDEO_BITRATE,
-+ 25 * 1000, 25 * 1000 * 1000,
-+ 25 * 1000, 10 * 1000 * 1000);
-+ v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
-+ V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER,
-+ 0, 1,
-+ 1, 0);
-+ v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
-+ V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
-+ 0, 0x7FFFFFFF,
-+ 1, 60);
-+ v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
-+ V4L2_CID_MPEG_VIDEO_H264_LEVEL,
-+ V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
-+ ~(BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
-+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
-+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
-+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
-+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
-+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
-+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
-+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
-+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
-+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
-+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
-+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
-+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
-+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2)),
-+ V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
-+ v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
-+ V4L2_CID_MPEG_VIDEO_H264_PROFILE,
-+ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
-+ ~(BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
-+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
-+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
-+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
-+ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
-+ if (hdl->error) {
-+ rc = hdl->error;
-+ goto free_ctrl_handler;
-+ }
-+ ctx->fh.ctrl_handler = hdl;
-+ v4l2_ctrl_handler_setup(hdl);
-+ }
-+
-+ ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
-+
-+ if (IS_ERR(ctx->fh.m2m_ctx)) {
-+ rc = PTR_ERR(ctx->fh.m2m_ctx);
-+
-+ goto free_ctrl_handler;
-+ }
-+
-+ /* Set both queues as buffered as we have buffering in the VPU. That
-+ * means that we will be scheduled whenever either an input or output
-+ * buffer is available (otherwise one of each are required).
-+ */
-+ v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
-+ v4l2_m2m_set_dst_buffered(ctx->fh.m2m_ctx, true);
-+
-+ v4l2_fh_add(&ctx->fh);
-+ atomic_inc(&dev->num_inst);
-+
-+ mutex_unlock(&dev->dev_mutex);
-+ return 0;
-+
-+free_ctrl_handler:
-+ v4l2_ctrl_handler_free(hdl);
-+ kfree(ctx);
-+open_unlock:
-+ mutex_unlock(&dev->dev_mutex);
-+ return rc;
-+}
-+
-+static int bcm2835_codec_release(struct file *file)
-+{
-+ struct bcm2835_codec_dev *dev = video_drvdata(file);
-+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+ v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: Releasing instance %p\n",
-+ __func__, ctx);
-+
-+ v4l2_fh_del(&ctx->fh);
-+ v4l2_fh_exit(&ctx->fh);
-+ v4l2_ctrl_handler_free(&ctx->hdl);
-+ mutex_lock(&dev->dev_mutex);
-+ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
-+
-+ if (ctx->component)
-+ vchiq_mmal_component_finalise(dev->instance, ctx->component);
-+
-+ mutex_unlock(&dev->dev_mutex);
-+ kfree(ctx);
-+
-+ atomic_dec(&dev->num_inst);
-+
-+ return 0;
-+}
-+
-+static const struct v4l2_file_operations bcm2835_codec_fops = {
-+ .owner = THIS_MODULE,
-+ .open = bcm2835_codec_open,
-+ .release = bcm2835_codec_release,
-+ .poll = v4l2_m2m_fop_poll,
-+ .unlocked_ioctl = video_ioctl2,
-+ .mmap = v4l2_m2m_fop_mmap,
-+};
-+
-+static const struct video_device bcm2835_codec_videodev = {
-+ .name = MEM2MEM_NAME,
-+ .vfl_dir = VFL_DIR_M2M,
-+ .fops = &bcm2835_codec_fops,
-+ .ioctl_ops = &bcm2835_codec_ioctl_ops,
-+ .minor = -1,
-+ .release = video_device_release_empty,
-+};
-+
-+static const struct v4l2_m2m_ops m2m_ops = {
-+ .device_run = device_run,
-+ .job_ready = job_ready,
-+ .job_abort = job_abort,
-+};
-+
-+static int bcm2835_codec_create(struct platform_device *pdev,
-+ struct bcm2835_codec_dev **new_dev,
-+ bool decode)
-+{
-+ struct bcm2835_codec_dev *dev;
-+ struct video_device *vfd;
-+ struct vchiq_mmal_instance *instance = NULL;
-+ int video_nr;
-+ int ret;
-+
-+ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-+ if (!dev)
-+ return -ENOMEM;
-+
-+ dev->pdev = pdev;
-+
-+ dev->decode = decode;
-+
-+ ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
-+ if (ret)
-+ return ret;
-+
-+ atomic_set(&dev->num_inst, 0);
-+ mutex_init(&dev->dev_mutex);
-+
-+ dev->vfd = bcm2835_codec_videodev;
-+ vfd = &dev->vfd;
-+ vfd->lock = &dev->dev_mutex;
-+ vfd->v4l2_dev = &dev->v4l2_dev;
-+
-+ if (dev->decode) {
-+ v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
-+ v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
-+ video_nr = decode_video_nr;
-+ } else {
-+ v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
-+ v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
-+ video_nr = encode_video_nr;
-+ }
-+
-+ ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
-+ if (ret) {
-+ v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
-+ goto unreg_dev;
-+ }
-+
-+ video_set_drvdata(vfd, dev);
-+ snprintf(vfd->name, sizeof(vfd->name), "%s",
-+ bcm2835_codec_videodev.name);
-+ v4l2_info(&dev->v4l2_dev, "Device registered as /dev/video%d\n",
-+ vfd->num);
-+
-+ *new_dev = dev;
-+
-+ dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
-+ if (IS_ERR(dev->m2m_dev)) {
-+ v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
-+ ret = PTR_ERR(dev->m2m_dev);
-+ goto err_m2m;
-+ }
-+
-+ ret = vchiq_mmal_init(&instance);
-+ if (ret < 0)
-+ goto err_m2m;
-+ dev->instance = instance;
-+
-+ v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s codec\n",
-+ dev->decode ? "decode" : "encode");
-+ return 0;
-+
-+err_m2m:
-+ v4l2_m2m_release(dev->m2m_dev);
-+ video_unregister_device(&dev->vfd);
-+unreg_dev:
-+ v4l2_device_unregister(&dev->v4l2_dev);
-+
-+ return ret;
-+}
-+
-+static int bcm2835_codec_destroy(struct bcm2835_codec_dev *dev)
-+{
-+ if (!dev)
-+ return -ENODEV;
-+
-+ v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
-+ v4l2_m2m_release(dev->m2m_dev);
-+ video_unregister_device(&dev->vfd);
-+ v4l2_device_unregister(&dev->v4l2_dev);
-+
-+ return 0;
-+}
-+
-+static int bcm2835_codec_probe(struct platform_device *pdev)
-+{
-+ struct bcm2835_codec_driver *drv;
-+ int ret = 0;
-+
-+ drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
-+ if (!drv)
-+ return -ENOMEM;
-+
-+ ret = bcm2835_codec_create(pdev, &drv->encode, false);
-+ if (ret)
-+ goto out;
-+
-+ ret = bcm2835_codec_create(pdev, &drv->decode, true);
-+ if (ret)
-+ goto out;
-+
-+ platform_set_drvdata(pdev, drv);
-+
-+ return 0;
-+
-+out:
-+ if (drv->encode) {
-+ bcm2835_codec_destroy(drv->encode);
-+ drv->encode = NULL;
-+ }
-+ return ret;
-+}
-+
-+static int bcm2835_codec_remove(struct platform_device *pdev)
-+{
-+ struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
-+
-+ bcm2835_codec_destroy(drv->encode);
-+
-+ bcm2835_codec_destroy(drv->decode);
-+
-+ return 0;
-+}
-+
-+static struct platform_driver bcm2835_v4l2_codec_driver = {
-+ .probe = bcm2835_codec_probe,
-+ .remove = bcm2835_codec_remove,
-+ .driver = {
-+ .name = "bcm2835-codec",
-+ .owner = THIS_MODULE,
-+ },
-+};
-+
-+module_platform_driver(bcm2835_v4l2_codec_driver);
-+
-+MODULE_DESCRIPTION("BCM2835 codec V4L2 driver");
-+MODULE_AUTHOR("Dave Stevenson, <dave.stevenson@raspberrypi.org>");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION("0.0.1");
-+MODULE_ALIAS("platform:bcm2835-codec");
--- /dev/null
+From 1e3afe8e33c7ea7d2d64298d7800291766e17a15 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 30 Oct 2018 12:23:26 +0000
+Subject: [PATCH 280/725] config: Add bcm2835-codec to Pi defconfigs.
+
+Adds the V4L2 M2M codec driver to the config.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -1210,6 +1210,7 @@ CONFIG_FB_TFT_FBTFT_DEVICE=m
+ CONFIG_BCM2835_VCHIQ=y
+ CONFIG_SND_BCM2835=m
+ CONFIG_VIDEO_BCM2835=m
++CONFIG_VIDEO_CODEC_BCM2835=m
+ CONFIG_MAILBOX=y
+ CONFIG_BCM2835_MBOX=y
+ # CONFIG_IOMMU_SUPPORT is not set
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -1203,6 +1203,7 @@ CONFIG_FB_TFT_FBTFT_DEVICE=m
+ CONFIG_BCM2835_VCHIQ=y
+ CONFIG_SND_BCM2835=m
+ CONFIG_VIDEO_BCM2835=m
++CONFIG_VIDEO_CODEC_BCM2835=m
+ CONFIG_MAILBOX=y
+ CONFIG_BCM2835_MBOX=y
+ # CONFIG_IOMMU_SUPPORT is not set
+++ /dev/null
-From 7dc3f0727d394ae8eaef363808b7525e9f760310 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 26 Oct 2018 15:14:16 +0100
-Subject: [PATCH 280/703] staging: vchiq_arm: Register bcm2835-codec as a
- platform driver
-
-Following the same pattern as bcm2835-camera and bcm2835-audio,
-register the V4L2 codec driver as a platform driver
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -171,6 +171,7 @@ static struct device *vchiq_dev;
- static DEFINE_SPINLOCK(msg_queue_spinlock);
- static struct platform_device *bcm2835_camera;
- static struct platform_device *bcm2835_audio;
-+static struct platform_device *bcm2835_codec;
-
- static const char *const ioctl_names[] = {
- "CONNECT",
-@@ -3660,6 +3661,9 @@ static int vchiq_probe(struct platform_d
- bcm2835_audio = vchiq_register_child(pdev, "bcm2835_audio");
- if (IS_ERR(bcm2835_audio))
- bcm2835_audio = NULL;
-+ bcm2835_codec = vchiq_register_child(pdev, "bcm2835-codec");
-+ if (IS_ERR(bcm2835_codec))
-+ bcm2835_codec = NULL;
-
- return 0;
-
--- /dev/null
+From f82bc2707af229ea9b55c5b9ec7b489aad928232 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 30 Nov 2018 16:00:54 +0000
+Subject: [PATCH 281/725] staging: bcm2835-camera: Fix stride on RGB3/BGR3
+ formats
+
+RGB3/BGR3 end up being 3 bytes per pixel, which meant that
+the alignment code ended up trying to align using bitmasking
+with a mask of 96.
+That doesn't work, so switch to an arithmetic alignment for
+those formats.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-camera/bcm2835-camera.c | 26 ++++++++++++++-----
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -1008,13 +1008,27 @@ static int vidioc_try_fmt_vid_cap(struct
+ 1, 0);
+ f->fmt.pix.bytesperline = f->fmt.pix.width * mfmt->ybbp;
+ if (!mfmt->remove_padding) {
+- int align_mask = ((32 * mfmt->depth) >> 3) - 1;
+- /* GPU isn't removing padding, so stride is aligned to 32 */
+- f->fmt.pix.bytesperline =
+- (f->fmt.pix.bytesperline + align_mask) & ~align_mask;
++ if (mfmt->depth == 24) {
++ /*
++ * 24bpp is a pain as we can't use simple masking.
++ * Min stride is width aligned to 16, times 24bpp.
++ */
++ f->fmt.pix.bytesperline =
++ ((f->fmt.pix.width + 15) & ~15) * 3;
++ } else {
++ /*
++ * GPU isn't removing padding, so stride is aligned to
++ * 32
++ */
++ int align_mask = ((32 * mfmt->depth) >> 3) - 1;
++
++ f->fmt.pix.bytesperline =
++ (f->fmt.pix.bytesperline + align_mask) &
++ ~align_mask;
++ }
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+- "Not removing padding, so bytes/line = %d, (align_mask %d)\n",
+- f->fmt.pix.bytesperline, align_mask);
++ "Not removing padding, so bytes/line = %d\n",
++ f->fmt.pix.bytesperline);
+ }
+
+ /* Image buffer has to be padded to allow for alignment, even though
+++ /dev/null
-From e0f22704bdcaa4b0033e65ce00f585e8b07b26af Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 26 Oct 2018 15:19:40 +0100
-Subject: [PATCH 281/703] staging: vchiq_arm: Register vcsm-cma as a platform
- driver
-
-Following the same pattern as bcm2835-camera and bcm2835-audio,
-register the vcsm-cma driver as a platform driver
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -172,6 +172,7 @@ static DEFINE_SPINLOCK(msg_queue_spinloc
- static struct platform_device *bcm2835_camera;
- static struct platform_device *bcm2835_audio;
- static struct platform_device *bcm2835_codec;
-+static struct platform_device *vcsm_cma;
-
- static const char *const ioctl_names[] = {
- "CONNECT",
-@@ -3655,6 +3656,9 @@ static int vchiq_probe(struct platform_d
- VCHIQ_VERSION, VCHIQ_VERSION_MIN,
- MAJOR(vchiq_devid), MINOR(vchiq_devid));
-
-+ vcsm_cma = vchiq_register_child(pdev, "vcsm-cma");
-+ if (IS_ERR(vcsm_cma))
-+ vcsm_cma = NULL;
- bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera");
- if (IS_ERR(bcm2835_camera))
- bcm2835_camera = NULL;
+++ /dev/null
-From 940f1ba9a06ccff70f10459803efe140baa7896d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Oct 2018 17:49:04 +0000
-Subject: [PATCH 282/703] ARM: bcm2835_defconfig: Enable bcm2835-codec
-
-Enables the V4L2 M2M codec driver as a module.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm/configs/bcm2835_defconfig | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/configs/bcm2835_defconfig
-+++ b/arch/arm/configs/bcm2835_defconfig
-@@ -132,6 +132,7 @@ CONFIG_DMA_BCM2835=y
- CONFIG_STAGING=y
- CONFIG_SND_BCM2835=m
- CONFIG_VIDEO_BCM2835=m
-+CONFIG_VIDEO_CODEC_BCM2835=m
- CONFIG_MAILBOX=y
- CONFIG_BCM2835_MBOX=y
- # CONFIG_IOMMU_SUPPORT is not set
--- /dev/null
+From b326f198daeac021ba83802b5e4502f8b22c1604 Mon Sep 17 00:00:00 2001
+From: John Sheu <sheu@chromium.org>
+Date: Thu, 15 Oct 2015 18:05:25 +0900
+Subject: [PATCH 282/725] media: vb2: Allow reqbufs(0) with "in use" MMAP
+ buffers
+
+Videobuf2 presently does not allow VIDIOC_REQBUFS to destroy outstanding
+buffers if the queue is of type V4L2_MEMORY_MMAP, and if the buffers are
+considered "in use". This is different behavior than for other memory
+types and prevents us from deallocating buffers in following two cases:
+
+1) There are outstanding mmap()ed views on the buffer. However even if
+ we put the buffer in reqbufs(0), there will be remaining references,
+ due to vma .open/close() adjusting vb2 buffer refcount appropriately.
+ This means that the buffer will be in fact freed only when the last
+ mmap()ed view is unmapped.
+
+2) Buffer has been exported as a DMABUF. Refcount of the vb2 buffer
+ is managed properly by VB2 DMABUF ops, i.e. incremented on DMABUF
+ get and decremented on DMABUF release. This means that the buffer
+ will be alive until all importers release it.
+
+Considering both cases above, there does not seem to be any need to
+prevent reqbufs(0) operation, because buffer lifetime is already
+properly managed by both mmap() and DMABUF code paths. Let's remove it
+and allow userspace freeing the queue (and potentially allocating a new
+one) even though old buffers might be still in processing.
+
+Signed-off-by: John Sheu <sheu@chromium.org>
+Reviewed-by: Pawel Osciak <posciak@chromium.org>
+Reviewed-by: Tomasz Figa <tfiga@chromium.org>
+Signed-off-by: Tomasz Figa <tfiga@chromium.org>
+---
+ .../media/common/videobuf2/videobuf2-core.c | 23 -------------------
+ 1 file changed, 23 deletions(-)
+
+--- a/drivers/media/common/videobuf2/videobuf2-core.c
++++ b/drivers/media/common/videobuf2/videobuf2-core.c
+@@ -554,20 +554,6 @@ bool vb2_buffer_in_use(struct vb2_queue
+ }
+ EXPORT_SYMBOL(vb2_buffer_in_use);
+
+-/*
+- * __buffers_in_use() - return true if any buffers on the queue are in use and
+- * the queue cannot be freed (by the means of REQBUFS(0)) call
+- */
+-static bool __buffers_in_use(struct vb2_queue *q)
+-{
+- unsigned int buffer;
+- for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+- if (vb2_buffer_in_use(q, q->bufs[buffer]))
+- return true;
+- }
+- return false;
+-}
+-
+ void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
+ {
+ call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
+@@ -679,16 +665,7 @@ int vb2_core_reqbufs(struct vb2_queue *q
+
+ if (*count == 0 || q->num_buffers != 0 ||
+ (q->memory != VB2_MEMORY_UNKNOWN && q->memory != memory)) {
+- /*
+- * We already have buffers allocated, so first check if they
+- * are not in use and can be freed.
+- */
+ mutex_lock(&q->mmap_lock);
+- if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
+- mutex_unlock(&q->mmap_lock);
+- dprintk(1, "memory in use, cannot free\n");
+- return -EBUSY;
+- }
+
+ /*
+ * Call queue_cancel to clean up any buffers in the PREPARED or
+++ /dev/null
-From 7047db2bf3ea962ccd4b3e197b1a812aab491a79 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 30 Oct 2018 12:23:26 +0000
-Subject: [PATCH 283/703] config: Add bcm2835-codec to Pi defconfigs.
-
-Adds the V4L2 M2M codec driver to the config.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- 2 files changed, 2 insertions(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -1210,6 +1210,7 @@ CONFIG_FB_TFT_FBTFT_DEVICE=m
- CONFIG_BCM2835_VCHIQ=y
- CONFIG_SND_BCM2835=m
- CONFIG_VIDEO_BCM2835=m
-+CONFIG_VIDEO_CODEC_BCM2835=m
- CONFIG_MAILBOX=y
- CONFIG_BCM2835_MBOX=y
- # CONFIG_IOMMU_SUPPORT is not set
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -1203,6 +1203,7 @@ CONFIG_FB_TFT_FBTFT_DEVICE=m
- CONFIG_BCM2835_VCHIQ=y
- CONFIG_SND_BCM2835=m
- CONFIG_VIDEO_BCM2835=m
-+CONFIG_VIDEO_CODEC_BCM2835=m
- CONFIG_MAILBOX=y
- CONFIG_BCM2835_MBOX=y
- # CONFIG_IOMMU_SUPPORT is not set
--- /dev/null
+From 710a31a64daa6929cf1940a7664609be39f442bc Mon Sep 17 00:00:00 2001
+From: Peter Huewe <peterhuewe@gmx.de>
+Date: Mon, 3 Sep 2018 21:51:51 +0200
+Subject: [PATCH 283/725] tpm: Make SECURITYFS a weak dependency
+
+commit 2f7d8dbb11287cbe9da6380ca14ed5d38c9ed91f upstream.
+
+While having SECURITYFS enabled for the tpm subsystem is beneficial in
+most cases, it is not strictly necessary to have it enabled at all.
+Especially on platforms without any boot firmware integration of the TPM
+(e.g. raspberry pi) it does not add any value for the tpm subsystem,
+as there is no eventlog present.
+
+By turning it from 'select' to 'imply' it still gets selected per
+default, but enables users who want to save some kb of ram by turning
+SECURITYFS off.
+
+Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+---
+ drivers/char/tpm/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/char/tpm/Kconfig
++++ b/drivers/char/tpm/Kconfig
+@@ -5,7 +5,7 @@
+ menuconfig TCG_TPM
+ tristate "TPM Hardware Support"
+ depends on HAS_IOMEM
+- select SECURITYFS
++ imply SECURITYFS
+ select CRYPTO
+ select CRYPTO_HASH_INFO
+ ---help---
--- /dev/null
+From 63015baea6a1b3c2cb4c84d18efdbb43ff838028 Mon Sep 17 00:00:00 2001
+From: Peter Huewe <peterhuewe@gmx.de>
+Date: Thu, 14 Jun 2018 22:42:18 +0200
+Subject: [PATCH 284/725] Enable TPM TIS SPI support for TPM1.2 and TPM2.0
+ chips
+
+This patch enables the support for SPI TPMs which follow the TCG TIS
+FIFO/PTP specification like the SLB9670.
+In order to decrease ram usage the weak dependency on CONFIG_SECURITFS
+is explictly set to 'n'.
+
+Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
+---
+ arch/arm/configs/bcm2709_defconfig | 5 +++--
+ arch/arm/configs/bcmrpi_defconfig | 5 +++--
+ arch/arm64/configs/bcmrpi3_defconfig | 3 +++
+ 3 files changed, 9 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -350,7 +350,6 @@ CONFIG_NET_ACT_SKBEDIT=m
+ CONFIG_NET_ACT_CSUM=m
+ CONFIG_BATMAN_ADV=m
+ CONFIG_OPENVSWITCH=m
+-CONFIG_NET_L3_MASTER_DEV=y
+ CONFIG_NET_PKTGEN=m
+ CONFIG_HAMRADIO=y
+ CONFIG_AX25=m
+@@ -610,6 +609,8 @@ CONFIG_SERIAL_DEV_BUS=m
+ CONFIG_TTY_PRINTK=y
+ CONFIG_HW_RANDOM=y
+ CONFIG_RAW_DRIVER=y
++CONFIG_TCG_TPM=m
++CONFIG_TCG_TIS_SPI=m
+ CONFIG_I2C=y
+ CONFIG_I2C_CHARDEV=m
+ CONFIG_I2C_MUX=m
+@@ -1343,12 +1344,12 @@ CONFIG_NLS_ISO8859_15=m
+ CONFIG_NLS_KOI8_R=m
+ CONFIG_NLS_KOI8_U=m
+ CONFIG_DLM=m
++# CONFIG_SECURITYFS is not set
+ CONFIG_CRYPTO_USER=m
+ CONFIG_CRYPTO_CBC=y
+ CONFIG_CRYPTO_CTS=m
+ CONFIG_CRYPTO_XTS=m
+ CONFIG_CRYPTO_XCBC=m
+-CONFIG_CRYPTO_SHA512=m
+ CONFIG_CRYPTO_TGR192=m
+ CONFIG_CRYPTO_WP512=m
+ CONFIG_CRYPTO_CAST5=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -344,7 +344,6 @@ CONFIG_NET_ACT_SKBEDIT=m
+ CONFIG_NET_ACT_CSUM=m
+ CONFIG_BATMAN_ADV=m
+ CONFIG_OPENVSWITCH=m
+-CONFIG_NET_L3_MASTER_DEV=y
+ CONFIG_NET_PKTGEN=m
+ CONFIG_HAMRADIO=y
+ CONFIG_AX25=m
+@@ -604,6 +603,8 @@ CONFIG_SERIAL_DEV_BUS=m
+ CONFIG_TTY_PRINTK=y
+ CONFIG_HW_RANDOM=y
+ CONFIG_RAW_DRIVER=y
++CONFIG_TCG_TPM=m
++CONFIG_TCG_TIS_SPI=m
+ CONFIG_I2C=y
+ CONFIG_I2C_CHARDEV=m
+ CONFIG_I2C_MUX=m
+@@ -1336,13 +1337,13 @@ CONFIG_NLS_ISO8859_15=m
+ CONFIG_NLS_KOI8_R=m
+ CONFIG_NLS_KOI8_U=m
+ CONFIG_DLM=m
++# CONFIG_SECURITYFS is not set
+ CONFIG_CRYPTO_USER=m
+ CONFIG_CRYPTO_CRYPTD=m
+ CONFIG_CRYPTO_CBC=y
+ CONFIG_CRYPTO_CTS=m
+ CONFIG_CRYPTO_XTS=m
+ CONFIG_CRYPTO_XCBC=m
+-CONFIG_CRYPTO_SHA512=m
+ CONFIG_CRYPTO_TGR192=m
+ CONFIG_CRYPTO_WP512=m
+ CONFIG_CRYPTO_CAST5=m
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -589,6 +589,8 @@ CONFIG_SERIAL_DEV_BUS=m
+ CONFIG_TTY_PRINTK=y
+ CONFIG_HW_RANDOM=y
+ CONFIG_RAW_DRIVER=y
++CONFIG_TCG_TPM=m
++CONFIG_TCG_TIS_SPI=m
+ CONFIG_I2C=y
+ CONFIG_I2C_CHARDEV=m
+ CONFIG_I2C_BCM2708=m
+@@ -1187,6 +1189,7 @@ CONFIG_NLS_ISO8859_15=m
+ CONFIG_NLS_KOI8_R=m
+ CONFIG_NLS_KOI8_U=m
+ CONFIG_DLM=m
++# CONFIG_SECURITYFS is not set
+ CONFIG_CRYPTO_USER=m
+ CONFIG_CRYPTO_CBC=y
+ CONFIG_CRYPTO_CTS=m
+++ /dev/null
-From a81fd46f130118ac4e18588eec81a630623145f6 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 30 Nov 2018 16:00:54 +0000
-Subject: [PATCH 284/703] staging: bcm2835-camera: Fix stride on RGB3/BGR3
- formats
-
-RGB3/BGR3 end up being 3 bytes per pixel, which meant that
-the alignment code ended up trying to align using bitmasking
-with a mask of 96.
-That doesn't work, so switch to an arithmetic alignment for
-those formats.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-camera/bcm2835-camera.c | 26 ++++++++++++++-----
- 1 file changed, 20 insertions(+), 6 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -1008,13 +1008,27 @@ static int vidioc_try_fmt_vid_cap(struct
- 1, 0);
- f->fmt.pix.bytesperline = f->fmt.pix.width * mfmt->ybbp;
- if (!mfmt->remove_padding) {
-- int align_mask = ((32 * mfmt->depth) >> 3) - 1;
-- /* GPU isn't removing padding, so stride is aligned to 32 */
-- f->fmt.pix.bytesperline =
-- (f->fmt.pix.bytesperline + align_mask) & ~align_mask;
-+ if (mfmt->depth == 24) {
-+ /*
-+ * 24bpp is a pain as we can't use simple masking.
-+ * Min stride is width aligned to 16, times 24bpp.
-+ */
-+ f->fmt.pix.bytesperline =
-+ ((f->fmt.pix.width + 15) & ~15) * 3;
-+ } else {
-+ /*
-+ * GPU isn't removing padding, so stride is aligned to
-+ * 32
-+ */
-+ int align_mask = ((32 * mfmt->depth) >> 3) - 1;
-+
-+ f->fmt.pix.bytesperline =
-+ (f->fmt.pix.bytesperline + align_mask) &
-+ ~align_mask;
-+ }
- v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-- "Not removing padding, so bytes/line = %d, (align_mask %d)\n",
-- f->fmt.pix.bytesperline, align_mask);
-+ "Not removing padding, so bytes/line = %d\n",
-+ f->fmt.pix.bytesperline);
- }
-
- /* Image buffer has to be padded to allow for alignment, even though
--- /dev/null
+From d3bff43fb2a1a1ba28c7770daa28565cfc2abd5e Mon Sep 17 00:00:00 2001
+From: Peter Huewe <peterhuewe@gmx.de>
+Date: Thu, 14 Jun 2018 22:51:24 +0200
+Subject: [PATCH 285/725] Add overlay for SLB9760 Iridium /LetsTrust TPM
+
+Device Tree overlay for the Infineon SLB9670 Trusted Platform Module add-on
+boards, which can be used as a secure key storage and hwrng.
+available as "Iridium SLB9670" by Infineon and "LetsTrust TPM" by
+pi3g.
+
+Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 8 ++++
+ .../boot/dts/overlays/tpm-slb9670-overlay.dts | 44 +++++++++++++++++++
+ 3 files changed, 53 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -137,6 +137,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ tc358743.dtbo \
+ tc358743-audio.dtbo \
+ tinylcd35.dtbo \
++ tpm-slb9670.dtbo \
+ uart0.dtbo \
+ uart1.dtbo \
+ upstream.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2012,6 +2012,14 @@ Params: speed Display
+ dtoverlay=tinylcd35,touch,touchgpio=3
+
+
++Name: tpm-slb9670
++Info: Enables support for Infineon SLB9670 Trusted Platform Module add-on
++ boards, which can be used as a secure key storage and hwrng,
++ available as "Iridium SLB9670" by Infineon and "LetsTrust TPM" by pi3g.
++Load: dtoverlay=tpm-slb9670
++Params: <None>
++
++
+ Name: uart0
+ Info: Change the pin usage of uart0
+ Load: dtoverlay=uart0,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
+@@ -0,0 +1,44 @@
++/*
++ * Device Tree overlay for the Infineon SLB9670 Trusted Platform Module add-on
++ * boards, which can be used as a secure key storage and hwrng.
++ * available as "Iridium SLB9670" by Infineon and "LetsTrust TPM" by pi3g.
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++
++ fragment@0 {
++ target = <&spi0>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@1 {
++ target = <&spidev1>;
++ __overlay__ {
++ status = "disabled";
++ };
++ };
++
++ fragment@2 {
++ target = <&spi0>;
++ __overlay__ {
++ /* needed to avoid dtc warning */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ slb9670: slb9670@1 {
++ compatible = "infineon,slb9670";
++ reg = <1>; /* CE1 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <32000000>;
++ status = "okay";
++ };
++
++ };
++ };
++};
+++ /dev/null
-From 0f4f3fca8bb1e8283d5342d63e6758f6ac16d68d Mon Sep 17 00:00:00 2001
-From: John Sheu <sheu@chromium.org>
-Date: Thu, 15 Oct 2015 18:05:25 +0900
-Subject: [PATCH 285/703] media: vb2: Allow reqbufs(0) with "in use" MMAP
- buffers
-
-Videobuf2 presently does not allow VIDIOC_REQBUFS to destroy outstanding
-buffers if the queue is of type V4L2_MEMORY_MMAP, and if the buffers are
-considered "in use". This is different behavior than for other memory
-types and prevents us from deallocating buffers in following two cases:
-
-1) There are outstanding mmap()ed views on the buffer. However even if
- we put the buffer in reqbufs(0), there will be remaining references,
- due to vma .open/close() adjusting vb2 buffer refcount appropriately.
- This means that the buffer will be in fact freed only when the last
- mmap()ed view is unmapped.
-
-2) Buffer has been exported as a DMABUF. Refcount of the vb2 buffer
- is managed properly by VB2 DMABUF ops, i.e. incremented on DMABUF
- get and decremented on DMABUF release. This means that the buffer
- will be alive until all importers release it.
-
-Considering both cases above, there does not seem to be any need to
-prevent reqbufs(0) operation, because buffer lifetime is already
-properly managed by both mmap() and DMABUF code paths. Let's remove it
-and allow userspace freeing the queue (and potentially allocating a new
-one) even though old buffers might be still in processing.
-
-Signed-off-by: John Sheu <sheu@chromium.org>
-Reviewed-by: Pawel Osciak <posciak@chromium.org>
-Reviewed-by: Tomasz Figa <tfiga@chromium.org>
-Signed-off-by: Tomasz Figa <tfiga@chromium.org>
----
- .../media/common/videobuf2/videobuf2-core.c | 23 -------------------
- 1 file changed, 23 deletions(-)
-
---- a/drivers/media/common/videobuf2/videobuf2-core.c
-+++ b/drivers/media/common/videobuf2/videobuf2-core.c
-@@ -554,20 +554,6 @@ bool vb2_buffer_in_use(struct vb2_queue
- }
- EXPORT_SYMBOL(vb2_buffer_in_use);
-
--/*
-- * __buffers_in_use() - return true if any buffers on the queue are in use and
-- * the queue cannot be freed (by the means of REQBUFS(0)) call
-- */
--static bool __buffers_in_use(struct vb2_queue *q)
--{
-- unsigned int buffer;
-- for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-- if (vb2_buffer_in_use(q, q->bufs[buffer]))
-- return true;
-- }
-- return false;
--}
--
- void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
- {
- call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
-@@ -679,16 +665,7 @@ int vb2_core_reqbufs(struct vb2_queue *q
-
- if (*count == 0 || q->num_buffers != 0 ||
- (q->memory != VB2_MEMORY_UNKNOWN && q->memory != memory)) {
-- /*
-- * We already have buffers allocated, so first check if they
-- * are not in use and can be freed.
-- */
- mutex_lock(&q->mmap_lock);
-- if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
-- mutex_unlock(&q->mmap_lock);
-- dprintk(1, "memory in use, cannot free\n");
-- return -EBUSY;
-- }
-
- /*
- * Call queue_cancel to clean up any buffers in the PREPARED or
--- /dev/null
+From d77f611dd04cab8310455d93106c503cde89175e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 4 Dec 2018 19:40:12 +0000
+Subject: [PATCH 286/725] Revert "staging: vchiq_arm: Register a platform
+ device for the audio driver"
+
+This reverts commit ab59590ed562b89db51fe46cee5db96b9bc5abd8.
+
+Issues have been observed in LibreElec as this was unconditionally
+loading the audio driver instead of having the DT parameter to
+enable it.
+
+Includes a partial revert of 2147700eb7a1b9e55e0684f0749114ce35d61571
+which fixed up the error handling.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -170,7 +170,6 @@ static struct class *vchiq_class;
+ static struct device *vchiq_dev;
+ static DEFINE_SPINLOCK(msg_queue_spinlock);
+ static struct platform_device *bcm2835_camera;
+-static struct platform_device *bcm2835_audio;
+ static struct platform_device *bcm2835_codec;
+ static struct platform_device *vcsm_cma;
+
+@@ -3662,9 +3661,6 @@ static int vchiq_probe(struct platform_d
+ bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera");
+ if (IS_ERR(bcm2835_camera))
+ bcm2835_camera = NULL;
+- bcm2835_audio = vchiq_register_child(pdev, "bcm2835_audio");
+- if (IS_ERR(bcm2835_audio))
+- bcm2835_audio = NULL;
+ bcm2835_codec = vchiq_register_child(pdev, "bcm2835-codec");
+ if (IS_ERR(bcm2835_codec))
+ bcm2835_codec = NULL;
+@@ -3685,7 +3681,6 @@ failed_platform_init:
+ static int vchiq_remove(struct platform_device *pdev)
+ {
+ platform_device_unregister(bcm2835_codec);
+- platform_device_unregister(bcm2835_audio);
+ platform_device_unregister(bcm2835_camera);
+ platform_device_unregister(vcsm_cma);
+ vchiq_debugfs_deinit();
+++ /dev/null
-From bcff673c2438f78cb41ab282ce969e4151e00f69 Mon Sep 17 00:00:00 2001
-From: Peter Huewe <peterhuewe@gmx.de>
-Date: Mon, 3 Sep 2018 21:51:51 +0200
-Subject: [PATCH 286/703] tpm: Make SECURITYFS a weak dependency
-
-commit 2f7d8dbb11287cbe9da6380ca14ed5d38c9ed91f upstream.
-
-While having SECURITYFS enabled for the tpm subsystem is beneficial in
-most cases, it is not strictly necessary to have it enabled at all.
-Especially on platforms without any boot firmware integration of the TPM
-(e.g. raspberry pi) it does not add any value for the tpm subsystem,
-as there is no eventlog present.
-
-By turning it from 'select' to 'imply' it still gets selected per
-default, but enables users who want to save some kb of ram by turning
-SECURITYFS off.
-
-Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
-Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
-Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
----
- drivers/char/tpm/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/char/tpm/Kconfig
-+++ b/drivers/char/tpm/Kconfig
-@@ -5,7 +5,7 @@
- menuconfig TCG_TPM
- tristate "TPM Hardware Support"
- depends on HAS_IOMEM
-- select SECURITYFS
-+ imply SECURITYFS
- select CRYPTO
- select CRYPTO_HASH_INFO
- ---help---
+++ /dev/null
-From 6fd45140dfb490a231a71994d92d0f0f86703b56 Mon Sep 17 00:00:00 2001
-From: Peter Huewe <peterhuewe@gmx.de>
-Date: Thu, 14 Jun 2018 22:42:18 +0200
-Subject: [PATCH 287/703] Enable TPM TIS SPI support for TPM1.2 and TPM2.0
- chips
-
-This patch enables the support for SPI TPMs which follow the TCG TIS
-FIFO/PTP specification like the SLB9670.
-In order to decrease ram usage the weak dependency on CONFIG_SECURITFS
-is explictly set to 'n'.
-
-Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
----
- arch/arm/configs/bcm2709_defconfig | 5 +++--
- arch/arm/configs/bcmrpi_defconfig | 5 +++--
- arch/arm64/configs/bcmrpi3_defconfig | 3 +++
- 3 files changed, 9 insertions(+), 4 deletions(-)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -350,7 +350,6 @@ CONFIG_NET_ACT_SKBEDIT=m
- CONFIG_NET_ACT_CSUM=m
- CONFIG_BATMAN_ADV=m
- CONFIG_OPENVSWITCH=m
--CONFIG_NET_L3_MASTER_DEV=y
- CONFIG_NET_PKTGEN=m
- CONFIG_HAMRADIO=y
- CONFIG_AX25=m
-@@ -610,6 +609,8 @@ CONFIG_SERIAL_DEV_BUS=m
- CONFIG_TTY_PRINTK=y
- CONFIG_HW_RANDOM=y
- CONFIG_RAW_DRIVER=y
-+CONFIG_TCG_TPM=m
-+CONFIG_TCG_TIS_SPI=m
- CONFIG_I2C=y
- CONFIG_I2C_CHARDEV=m
- CONFIG_I2C_MUX=m
-@@ -1343,12 +1344,12 @@ CONFIG_NLS_ISO8859_15=m
- CONFIG_NLS_KOI8_R=m
- CONFIG_NLS_KOI8_U=m
- CONFIG_DLM=m
-+# CONFIG_SECURITYFS is not set
- CONFIG_CRYPTO_USER=m
- CONFIG_CRYPTO_CBC=y
- CONFIG_CRYPTO_CTS=m
- CONFIG_CRYPTO_XTS=m
- CONFIG_CRYPTO_XCBC=m
--CONFIG_CRYPTO_SHA512=m
- CONFIG_CRYPTO_TGR192=m
- CONFIG_CRYPTO_WP512=m
- CONFIG_CRYPTO_CAST5=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -344,7 +344,6 @@ CONFIG_NET_ACT_SKBEDIT=m
- CONFIG_NET_ACT_CSUM=m
- CONFIG_BATMAN_ADV=m
- CONFIG_OPENVSWITCH=m
--CONFIG_NET_L3_MASTER_DEV=y
- CONFIG_NET_PKTGEN=m
- CONFIG_HAMRADIO=y
- CONFIG_AX25=m
-@@ -604,6 +603,8 @@ CONFIG_SERIAL_DEV_BUS=m
- CONFIG_TTY_PRINTK=y
- CONFIG_HW_RANDOM=y
- CONFIG_RAW_DRIVER=y
-+CONFIG_TCG_TPM=m
-+CONFIG_TCG_TIS_SPI=m
- CONFIG_I2C=y
- CONFIG_I2C_CHARDEV=m
- CONFIG_I2C_MUX=m
-@@ -1336,13 +1337,13 @@ CONFIG_NLS_ISO8859_15=m
- CONFIG_NLS_KOI8_R=m
- CONFIG_NLS_KOI8_U=m
- CONFIG_DLM=m
-+# CONFIG_SECURITYFS is not set
- CONFIG_CRYPTO_USER=m
- CONFIG_CRYPTO_CRYPTD=m
- CONFIG_CRYPTO_CBC=y
- CONFIG_CRYPTO_CTS=m
- CONFIG_CRYPTO_XTS=m
- CONFIG_CRYPTO_XCBC=m
--CONFIG_CRYPTO_SHA512=m
- CONFIG_CRYPTO_TGR192=m
- CONFIG_CRYPTO_WP512=m
- CONFIG_CRYPTO_CAST5=m
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -589,6 +589,8 @@ CONFIG_SERIAL_DEV_BUS=m
- CONFIG_TTY_PRINTK=y
- CONFIG_HW_RANDOM=y
- CONFIG_RAW_DRIVER=y
-+CONFIG_TCG_TPM=m
-+CONFIG_TCG_TIS_SPI=m
- CONFIG_I2C=y
- CONFIG_I2C_CHARDEV=m
- CONFIG_I2C_BCM2708=m
-@@ -1187,6 +1189,7 @@ CONFIG_NLS_ISO8859_15=m
- CONFIG_NLS_KOI8_R=m
- CONFIG_NLS_KOI8_U=m
- CONFIG_DLM=m
-+# CONFIG_SECURITYFS is not set
- CONFIG_CRYPTO_USER=m
- CONFIG_CRYPTO_CBC=y
- CONFIG_CRYPTO_CTS=m
--- /dev/null
+From 3005ff34fcaea926cfc0c062c44f875568828ca7 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 4 Dec 2018 20:41:19 +0000
+Subject: [PATCH 287/725] Revert "staging: bcm2835-audio: Drop DT dependency"
+
+This reverts commit 933bc853bb764e476b0b0f633588f46d20f1f76a.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835.c | 41 ++++++++++---------
+ 1 file changed, 22 insertions(+), 19 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -4,17 +4,15 @@
+ #include <linux/platform_device.h>
+
+ #include <linux/init.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/of_device.h>
+ #include <linux/slab.h>
+ #include <linux/module.h>
++#include <linux/of.h>
+
+ #include "bcm2835.h"
+
+ static bool enable_hdmi;
+ static bool enable_headphones;
+ static bool enable_compat_alsa = true;
+-static int num_channels = MAX_SUBSTREAMS;
+
+ module_param(enable_hdmi, bool, 0444);
+ MODULE_PARM_DESC(enable_hdmi, "Enables HDMI virtual audio device");
+@@ -23,8 +21,6 @@ MODULE_PARM_DESC(enable_headphones, "Ena
+ module_param(enable_compat_alsa, bool, 0444);
+ MODULE_PARM_DESC(enable_compat_alsa,
+ "Enables ALSA compatibility virtual audio device");
+-module_param(num_channels, int, 0644);
+-MODULE_PARM_DESC(num_channels, "Number of audio channels (default: 8)");
+
+ static void snd_devm_unregister_child(struct device *dev, void *res)
+ {
+@@ -411,30 +407,31 @@ static int snd_add_child_devices(struct
+ return 0;
+ }
+
+-static int snd_bcm2835_alsa_probe(struct platform_device *pdev)
++static int snd_bcm2835_alsa_probe_dt(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
++ u32 numchans;
+ int err;
+
+- if (num_channels <= 0 || num_channels > MAX_SUBSTREAMS) {
+- num_channels = MAX_SUBSTREAMS;
+- dev_warn(dev, "Illegal num_channels value, will use %u\n",
+- num_channels);
+- }
+-
+- dev->coherent_dma_mask = DMA_BIT_MASK(32);
+- dev->dma_mask = &dev->coherent_dma_mask;
+- err = of_dma_configure(dev, NULL, true);
++ err = of_property_read_u32(dev->of_node, "brcm,pwm-channels",
++ &numchans);
+ if (err) {
+- dev_err(dev, "Unable to setup DMA: %d\n", 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 = bcm2835_devm_add_vchi_ctx(dev);
+ if (err)
+ return err;
+
+- err = snd_add_child_devices(dev, num_channels);
++ err = snd_add_child_devices(dev, numchans);
+ if (err)
+ return err;
+
+@@ -456,14 +453,21 @@ static int snd_bcm2835_alsa_resume(struc
+
+ #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,
++ .probe = snd_bcm2835_alsa_probe_dt,
+ #ifdef CONFIG_PM
+ .suspend = snd_bcm2835_alsa_suspend,
+ .resume = snd_bcm2835_alsa_resume,
+ #endif
+ .driver = {
+ .name = "bcm2835_audio",
++ .of_match_table = snd_bcm2835_of_match_table,
+ },
+ };
+ module_platform_driver(bcm2835_alsa0_driver);
+@@ -471,4 +475,3 @@ module_platform_driver(bcm2835_alsa0_dri
+ MODULE_AUTHOR("Dom Cobley");
+ MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform:bcm2835_audio");
--- /dev/null
+From d3a8ba2147f62a30eba236976ce9ff6291ed9636 Mon Sep 17 00:00:00 2001
+From: dev-3Dlab <45081440+dev-3Dlab@users.noreply.github.com>
+Date: Wed, 5 Dec 2018 10:59:11 +0100
+Subject: [PATCH 288/725] ASoC: add driver for 3Dlab Nano soundcard (#2758)
+
+Signed-off-by: GT <dev@3d-lab-av.com>
+---
+ .../overlays/3dlab-nano-player-overlay.dts | 32 ++
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 6 +
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ sound/soc/bcm/3dlab-nano-player.c | 370 ++++++++++++++++++
+ sound/soc/bcm/Kconfig | 6 +
+ sound/soc/bcm/Makefile | 2 +
+ 8 files changed, 419 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
+ create mode 100644 sound/soc/bcm/3dlab-nano-player.c
+
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
+@@ -0,0 +1,32 @@
++// Definitions for 3Dlab Nano Player
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "brcm,bcm2708";
++
++ fragment@0 {
++ target = <&i2s>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@1 {
++ target = <&i2c>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ nano-player@41 {
++ compatible = "3dlab,nano-player";
++ reg = <0x41>;
++ i2s-controller = <&i2s>;
++ status = "okay";
++ };
++ };
++ };
++};
++
++// EOF
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -1,6 +1,7 @@
+ # Overlays for the Raspberry Pi platform
+
+ dtbo-$(CONFIG_ARCH_BCM2835) += \
++ 3dlab-nano-player.dtbo \
+ adau1977-adc.dtbo \
+ adau7002-simple.dtbo \
+ ads1015.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -199,6 +199,12 @@ Params:
+ and the other i2c baudrate parameters.
+
+
++Name: 3dlab-nano-player
++Info: Configures the 3Dlab Nano Player
++Load: dtoverlay=3dlab-nano-player
++Params: <None>
++
++
+ Name: adau1977-adc
+ Info: Overlay for activation of ADAU1977 ADC codec over I2C for control
+ and I2S for data.
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -902,6 +902,7 @@ CONFIG_SND_USB_6FIRE=m
+ CONFIG_SND_USB_HIFACE=m
+ CONFIG_SND_SOC=m
+ CONFIG_SND_BCM2835_SOC_I2S=m
++CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
+ CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -895,6 +895,7 @@ CONFIG_SND_USB_6FIRE=m
+ CONFIG_SND_USB_HIFACE=m
+ CONFIG_SND_SOC=m
+ CONFIG_SND_BCM2835_SOC_I2S=m
++CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
+ CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
+--- /dev/null
++++ b/sound/soc/bcm/3dlab-nano-player.c
+@@ -0,0 +1,370 @@
++/*
++ * 3Dlab Nano Player ALSA SoC Audio driver.
++ *
++ * Copyright (C) 2018 3Dlab.
++ *
++ * Author: GT <dev@3d-lab-av.com>
++ *
++ * 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 <linux/module.h>
++#include <linux/i2c.h>
++#include <sound/soc.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/control.h>
++
++#define NANO_ID 0x00
++#define NANO_VER 0x01
++#define NANO_CFG 0x02
++#define NANO_STATUS 0x03
++#define NANO_SPI_ADDR 0x04
++#define NANO_SPI_DATA 0x05
++
++#define NANO_ID_VAL 0x3D
++#define NANO_CFG_OFF 0x00
++#define NANO_CFG_MULT1 0
++#define NANO_CFG_MULT2 1
++#define NANO_CFG_MULT4 2
++#define NANO_CFG_MULT8 3
++#define NANO_CFG_MULT16 4
++#define NANO_CFG_CLK22 0
++#define NANO_CFG_CLK24 BIT(3)
++#define NANO_CFG_DSD BIT(4)
++#define NANO_CFG_ENA BIT(5)
++#define NANO_CFG_BLINK BIT(6)
++#define NANO_STATUS_P1 BIT(0)
++#define NANO_STATUS_P2 BIT(1)
++#define NANO_STATUS_FLG BIT(2)
++#define NANO_STATUS_CLK BIT(3)
++#define NANO_SPI_READ 0
++#define NANO_SPI_WRITE BIT(5)
++
++#define NANO_DAC_CTRL1 0x00
++#define NANO_DAC_CTRL2 0x01
++#define NANO_DAC_CTRL3 0x02
++#define NANO_DAC_LATT 0x03
++#define NANO_DAC_RATT 0x04
++
++#define NANO_CTRL2_VAL 0x22
++
++static int nano_player_spi_write(struct regmap *map,
++ unsigned int reg, unsigned int val)
++{
++ /* indirect register access */
++ regmap_write(map, NANO_SPI_DATA, val);
++ regmap_write(map, NANO_SPI_ADDR, reg | NANO_SPI_WRITE);
++ return 0;
++}
++
++static int nano_player_ctrl_info(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++ /* describe control element */
++ if (strstr(kcontrol->id.name, "Volume")) {
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 100;
++ } else {
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 1;
++ }
++
++ return 0;
++}
++
++static int nano_player_ctrl_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ /* program control value to hardware */
++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
++ struct regmap *regmap = snd_soc_card_get_drvdata(card);
++
++ if (strstr(kcontrol->id.name, "Volume")) {
++ unsigned int vol = ucontrol->value.integer.value[0];
++ unsigned int att = 255 - (2 * (100 - vol));
++
++ nano_player_spi_write(regmap, NANO_DAC_LATT, att);
++ nano_player_spi_write(regmap, NANO_DAC_RATT, att);
++ kcontrol->private_value = vol;
++ } else {
++ unsigned int mute = ucontrol->value.integer.value[0];
++ unsigned int reg = NANO_CTRL2_VAL | mute;
++
++ nano_player_spi_write(regmap, NANO_DAC_CTRL2, reg);
++ kcontrol->private_value = mute;
++ }
++ return 0;
++}
++
++static int nano_player_ctrl_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ /* return last programmed value */
++ ucontrol->value.integer.value[0] = kcontrol->private_value;
++ return 0;
++}
++
++#define SOC_NANO_PLAYER_CTRL(xname) \
++{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
++ .info = nano_player_ctrl_info, \
++ .put = nano_player_ctrl_put, \
++ .get = nano_player_ctrl_get }
++
++static const struct snd_kcontrol_new nano_player_controls[] = {
++ SOC_NANO_PLAYER_CTRL("Master Playback Volume"),
++ SOC_NANO_PLAYER_CTRL("Master Playback Switch"),
++};
++
++static const unsigned int nano_player_rates[] = {
++ 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000,
++ 705600, 768000 /* only possible with fast clocks */
++};
++
++static struct snd_pcm_hw_constraint_list nano_player_constraint_rates = {
++ .list = nano_player_rates,
++ .count = ARRAY_SIZE(nano_player_rates),
++};
++
++static int nano_player_init(struct snd_soc_pcm_runtime *rtd)
++{
++ struct snd_soc_card *card = rtd->card;
++ struct regmap *regmap = snd_soc_card_get_drvdata(card);
++ struct snd_soc_pcm_stream *cpu = &rtd->cpu_dai->driver->playback;
++ struct snd_soc_pcm_stream *codec = &rtd->codec_dai->driver->playback;
++ unsigned int sample_bits = 32;
++ unsigned int val;
++
++ /* configure cpu dai */
++ cpu->formats |= SNDRV_PCM_FMTBIT_DSD_U32_LE;
++ cpu->rate_max = 768000;
++
++ /* configure dummy codec dai */
++ codec->rate_min = 44100;
++ codec->rates = SNDRV_PCM_RATE_KNOT;
++ codec->formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_DSD_U32_LE;
++
++ /* configure max supported rate */
++ regmap_read(regmap, NANO_STATUS, &val);
++ if (val & NANO_STATUS_CLK) {
++ dev_notice(card->dev, "Board with fast clocks installed\n");
++ codec->rate_max = 768000;
++ } else {
++ dev_notice(card->dev, "Board with normal clocks installed\n");
++ codec->rate_max = 384000;
++ }
++
++ /* frame length enforced by hardware */
++ return snd_soc_dai_set_bclk_ratio(rtd->cpu_dai, sample_bits * 2);
++}
++
++static int nano_player_startup(struct snd_pcm_substream *substream)
++{
++ return snd_pcm_hw_constraint_list(substream->runtime, 0,
++ SNDRV_PCM_HW_PARAM_RATE,
++ &nano_player_constraint_rates);
++}
++
++static int nano_player_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 regmap *regmap = snd_soc_card_get_drvdata(card);
++ unsigned int config = NANO_CFG_ENA;
++ struct snd_mask *fmt;
++
++ /* configure PCM or DSD */
++ fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
++ if (snd_mask_test(fmt, SNDRV_PCM_FORMAT_DSD_U32_LE)) {
++ /* embed DSD in PCM data */
++ snd_mask_none(fmt);
++ snd_mask_set(fmt, SNDRV_PCM_FORMAT_S32_LE);
++ /* enable DSD mode */
++ config |= NANO_CFG_DSD;
++ }
++
++ /* configure clocks */
++ switch (params_rate(params)) {
++ case 44100:
++ config |= NANO_CFG_MULT1 | NANO_CFG_CLK22;
++ break;
++ case 88200:
++ config |= NANO_CFG_MULT2 | NANO_CFG_CLK22;
++ break;
++ case 176400:
++ config |= NANO_CFG_MULT4 | NANO_CFG_CLK22;
++ break;
++ case 352800:
++ config |= NANO_CFG_MULT8 | NANO_CFG_CLK22;
++ break;
++ case 705600:
++ config |= NANO_CFG_MULT16 | NANO_CFG_CLK22;
++ break;
++ case 48000:
++ config |= NANO_CFG_MULT1 | NANO_CFG_CLK24;
++ break;
++ case 96000:
++ config |= NANO_CFG_MULT2 | NANO_CFG_CLK24;
++ break;
++ case 192000:
++ config |= NANO_CFG_MULT4 | NANO_CFG_CLK24;
++ break;
++ case 384000:
++ config |= NANO_CFG_MULT8 | NANO_CFG_CLK24;
++ break;
++ case 768000:
++ config |= NANO_CFG_MULT16 | NANO_CFG_CLK24;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ dev_dbg(card->dev, "Send CFG register 0x%02X\n", config);
++ return regmap_write(regmap, NANO_CFG, config);
++}
++
++static struct snd_soc_ops nano_player_ops = {
++ .startup = nano_player_startup,
++ .hw_params = nano_player_hw_params,
++};
++
++static struct snd_soc_dai_link nano_player_link = {
++ .name = "3Dlab Nano Player",
++ .stream_name = "3Dlab Nano Player HiFi",
++ .platform_name = "bcm2708-i2s.0",
++ .cpu_dai_name = "bcm2708-i2s.0",
++ .codec_name = "snd-soc-dummy",
++ .codec_dai_name = "snd-soc-dummy-dai",
++ .dai_fmt = SND_SOC_DAIFMT_I2S |
++ SND_SOC_DAIFMT_CONT |
++ SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBM_CFM,
++ .init = nano_player_init,
++ .ops = &nano_player_ops,
++};
++
++static const struct regmap_config nano_player_regmap = {
++ .reg_bits = 8,
++ .val_bits = 8,
++ .max_register = 128,
++ .cache_type = REGCACHE_RBTREE,
++};
++
++static int nano_player_card_probe(struct snd_soc_card *card)
++{
++ struct regmap *regmap = snd_soc_card_get_drvdata(card);
++ unsigned int val;
++
++ /* check hardware integrity */
++ regmap_read(regmap, NANO_ID, &val);
++ if (val != NANO_ID_VAL) {
++ dev_err(card->dev, "Invalid ID register 0x%02X\n", val);
++ return -ENODEV;
++ }
++
++ /* report version to the user */
++ regmap_read(regmap, NANO_VER, &val);
++ dev_notice(card->dev, "Started 3Dlab Nano Player driver (v%d)\n", val);
++
++ /* enable internal audio bus and blink status LED */
++ return regmap_write(regmap, NANO_CFG, NANO_CFG_ENA | NANO_CFG_BLINK);
++}
++
++static int nano_player_card_remove(struct snd_soc_card *card)
++{
++ /* disable internal audio bus */
++ struct regmap *regmap = snd_soc_card_get_drvdata(card);
++
++ return regmap_write(regmap, NANO_CFG, NANO_CFG_OFF);
++}
++
++static struct snd_soc_card nano_player_card = {
++ .name = "3Dlab_Nano_Player",
++ .owner = THIS_MODULE,
++ .dai_link = &nano_player_link,
++ .num_links = 1,
++ .controls = nano_player_controls,
++ .num_controls = ARRAY_SIZE(nano_player_controls),
++ .probe = nano_player_card_probe,
++ .remove = nano_player_card_remove,
++};
++
++static int nano_player_i2c_probe(struct i2c_client *i2c,
++ const struct i2c_device_id *id)
++{
++ struct regmap *regmap;
++ int ret;
++
++ regmap = devm_regmap_init_i2c(i2c, &nano_player_regmap);
++ if (IS_ERR(regmap)) {
++ ret = PTR_ERR(regmap);
++ dev_err(&i2c->dev, "Failed to init regmap %d\n", ret);
++ return ret;
++ }
++
++ if (i2c->dev.of_node) {
++ struct snd_soc_dai_link *dai = &nano_player_link;
++ struct device_node *node;
++
++ /* cpu handle configured by device tree */
++ node = of_parse_phandle(i2c->dev.of_node, "i2s-controller", 0);
++ if (node) {
++ dai->platform_name = NULL;
++ dai->platform_of_node = node;
++ dai->cpu_dai_name = NULL;
++ dai->cpu_of_node = node;
++ }
++ }
++
++ nano_player_card.dev = &i2c->dev;
++ snd_soc_card_set_drvdata(&nano_player_card, regmap);
++ ret = devm_snd_soc_register_card(&i2c->dev, &nano_player_card);
++
++ if (ret && ret != -EPROBE_DEFER)
++ dev_err(&i2c->dev, "Failed to register card %d\n", ret);
++
++ return ret;
++}
++
++static const struct of_device_id nano_player_of_match[] = {
++ { .compatible = "3dlab,nano-player", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, nano_player_of_match);
++
++static const struct i2c_device_id nano_player_i2c_id[] = {
++ { "nano-player", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, nano_player_i2c_id);
++
++static struct i2c_driver nano_player_i2c_driver = {
++ .probe = nano_player_i2c_probe,
++ .id_table = nano_player_i2c_id,
++ .driver = {
++ .name = "nano-player",
++ .owner = THIS_MODULE,
++ .of_match_table = nano_player_of_match,
++ },
++};
++
++module_i2c_driver(nano_player_i2c_driver);
++
++MODULE_DESCRIPTION("ASoC 3Dlab Nano Player driver");
++MODULE_AUTHOR("GT <dev@3d-lab-av.com>");
++MODULE_LICENSE("GPL v2");
++
++/* EOF */
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -17,6 +17,12 @@ config SND_SOC_CYGNUS
+
+ If you don't know what to do here, say N.
+
++config SND_BCM2708_SOC_3DLAB_NANO_PLAYER
++ tristate "Support for 3Dlab Nano Player"
++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++ help
++ Say Y or M if you want to add support for 3Dlab Nano Player.
++
+ config SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD
+ tristate "Support for Google voiceHAT soundcard"
+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -12,6 +12,7 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-
+ snd-soc-googlevoicehat-codec-objs := googlevoicehat-codec.o
+
+ # BCM2708 Machine Support
++snd-soc-3dlab-nano-player-objs := 3dlab-nano-player.o
+ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
+ snd-soc-justboom-dac-objs := justboom-dac.o
+ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
+@@ -31,6 +32,7 @@ snd-soc-fe-pi-audio-objs := fe-pi-audio.
+ snd-soc-rpi-simple-soundcard-objs := rpi-simple-soundcard.o
+ snd-soc-rpi-wm8804-soundcard-objs := rpi-wm8804-soundcard.o
+
++obj-$(CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER) += snd-soc-3dlab-nano-player.o
+ obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD) += snd-soc-googlevoicehat-codec.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
+++ /dev/null
-From 0ca744a930b9aed72b2f291796140339eaf6ea33 Mon Sep 17 00:00:00 2001
-From: Peter Huewe <peterhuewe@gmx.de>
-Date: Thu, 14 Jun 2018 22:51:24 +0200
-Subject: [PATCH 288/703] Add overlay for SLB9760 Iridium /LetsTrust TPM
-
-Device Tree overlay for the Infineon SLB9670 Trusted Platform Module add-on
-boards, which can be used as a secure key storage and hwrng.
-available as "Iridium SLB9670" by Infineon and "LetsTrust TPM" by
-pi3g.
-
-Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
----
- arch/arm/boot/dts/overlays/Makefile | 1 +
- arch/arm/boot/dts/overlays/README | 8 ++++
- .../boot/dts/overlays/tpm-slb9670-overlay.dts | 44 +++++++++++++++++++
- 3 files changed, 53 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -137,6 +137,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- tc358743.dtbo \
- tc358743-audio.dtbo \
- tinylcd35.dtbo \
-+ tpm-slb9670.dtbo \
- uart0.dtbo \
- uart1.dtbo \
- upstream.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -2012,6 +2012,14 @@ Params: speed Display
- dtoverlay=tinylcd35,touch,touchgpio=3
-
-
-+Name: tpm-slb9670
-+Info: Enables support for Infineon SLB9670 Trusted Platform Module add-on
-+ boards, which can be used as a secure key storage and hwrng,
-+ available as "Iridium SLB9670" by Infineon and "LetsTrust TPM" by pi3g.
-+Load: dtoverlay=tpm-slb9670
-+Params: <None>
-+
-+
- Name: uart0
- Info: Change the pin usage of uart0
- Load: dtoverlay=uart0,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
-@@ -0,0 +1,44 @@
-+/*
-+ * Device Tree overlay for the Infineon SLB9670 Trusted Platform Module add-on
-+ * boards, which can be used as a secure key storage and hwrng.
-+ * available as "Iridium SLB9670" by Infineon and "LetsTrust TPM" by pi3g.
-+ */
-+
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+
-+ fragment@0 {
-+ target = <&spi0>;
-+ __overlay__ {
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&spidev1>;
-+ __overlay__ {
-+ status = "disabled";
-+ };
-+ };
-+
-+ fragment@2 {
-+ target = <&spi0>;
-+ __overlay__ {
-+ /* needed to avoid dtc warning */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ slb9670: slb9670@1 {
-+ compatible = "infineon,slb9670";
-+ reg = <1>; /* CE1 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <32000000>;
-+ status = "okay";
-+ };
-+
-+ };
-+ };
-+};
+++ /dev/null
-From f70b874a07779f015befed503790417c6bc1cfd2 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 4 Dec 2018 19:40:12 +0000
-Subject: [PATCH 289/703] Revert "staging: vchiq_arm: Register a platform
- device for the audio driver"
-
-This reverts commit ab59590ed562b89db51fe46cee5db96b9bc5abd8.
-
-Issues have been observed in LibreElec as this was unconditionally
-loading the audio driver instead of having the DT parameter to
-enable it.
-
-Includes a partial revert of 2147700eb7a1b9e55e0684f0749114ce35d61571
-which fixed up the error handling.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 5 -----
- 1 file changed, 5 deletions(-)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -170,7 +170,6 @@ static struct class *vchiq_class;
- static struct device *vchiq_dev;
- static DEFINE_SPINLOCK(msg_queue_spinlock);
- static struct platform_device *bcm2835_camera;
--static struct platform_device *bcm2835_audio;
- static struct platform_device *bcm2835_codec;
- static struct platform_device *vcsm_cma;
-
-@@ -3662,9 +3661,6 @@ static int vchiq_probe(struct platform_d
- bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera");
- if (IS_ERR(bcm2835_camera))
- bcm2835_camera = NULL;
-- bcm2835_audio = vchiq_register_child(pdev, "bcm2835_audio");
-- if (IS_ERR(bcm2835_audio))
-- bcm2835_audio = NULL;
- bcm2835_codec = vchiq_register_child(pdev, "bcm2835-codec");
- if (IS_ERR(bcm2835_codec))
- bcm2835_codec = NULL;
-@@ -3685,7 +3681,6 @@ failed_platform_init:
- static int vchiq_remove(struct platform_device *pdev)
- {
- platform_device_unregister(bcm2835_codec);
-- platform_device_unregister(bcm2835_audio);
- platform_device_unregister(bcm2835_camera);
- platform_device_unregister(vcsm_cma);
- vchiq_debugfs_deinit();
--- /dev/null
+From 2a7770becf1b2bf289836ea19dcc2f6744d7e413 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 5 Dec 2018 11:56:40 +0000
+Subject: [PATCH 289/725] overlays: Update README with removal of lirc-rpi
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README | 57 ++++++++++++-------------------
+ 1 file changed, 21 insertions(+), 36 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -56,23 +56,29 @@ have its contents deleted (or commented
+ Using Overlays
+ ==============
+
+-Overlays are loaded using the "dtoverlay" directive. As an example, consider
+-the popular lirc-rpi module, the Linux Infrared Remote Control driver. In the
+-pre-DT world this would be loaded from /etc/modules, with an explicit
+-"modprobe lirc-rpi" command, or programmatically by lircd. With DT enabled,
+-this becomes a line in config.txt:
+-
+- dtoverlay=lirc-rpi
+-
+-This causes the file /boot/overlays/lirc-rpi.dtbo to be loaded. By
+-default it will use GPIOs 17 (out) and 18 (in), but this can be modified using
+-DT parameters:
+-
+- dtoverlay=lirc-rpi,gpio_out_pin=17,gpio_in_pin=13
+-
+-Parameters always have default values, although in some cases (e.g. "w1-gpio")
+-it is necessary to provided multiple overlays in order to get the desired
+-behaviour. See the list of overlays below for a description of the parameters
++Overlays are loaded using the "dtoverlay" config.txt setting. As an example,
++consider I2C Real Time Clock drivers. In the pre-DT world these would be loaded
++by writing a magic string comprising a device identifier and an I2C address to
++a special file in /sys/class/i2c-adapter, having first loaded the driver for
++the I2C interface and the RTC device - something like this:
++
++ modprobe i2c-bcm2835
++ modprobe rtc-ds1307
++ echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
++
++With DT enabled, this becomes a line in config.txt:
++
++ dtoverlay=i2c-rtc,ds1307
++
++This causes the file /boot/overlays/i2c-rtc.dtbo to be loaded and a "node"
++describing the DS1307 I2C device to be added to the Device Tree for the Pi. By
++default it usees address 0x68, but this can be modified with an additional DT
++parameter:
++
++ dtoverlay=i2c-rtc,ds1307,addr=0x68
++
++Parameters usually have default values, although certain parameters are
++mandatory. See the list of overlays below for a description of the parameters
+ and their defaults.
+
+ The Overlay and Parameter Reference
+@@ -1135,29 +1141,8 @@ Params: <None>
+
+
+ Name: lirc-rpi
+-Info: Configures lirc-rpi (Linux Infrared Remote Control for Raspberry Pi)
+- Consult the module documentation for more details.
+-Load: dtoverlay=lirc-rpi,<param>=<val>
+-Params: gpio_out_pin GPIO for output (default "17")
+-
+- gpio_in_pin GPIO for input (default "18")
+-
+- gpio_in_pull Pull up/down/off on the input pin
+- (default "down")
+-
+- sense Override the IR receive auto-detection logic:
+- "0" = force active-high
+- "1" = force active-low
+- "-1" = use auto-detection
+- (default "-1")
+-
+- softcarrier Turn the software carrier "on" or "off"
+- (default "on")
+-
+- invert "on" = invert the output pin (default "off")
+-
+- debug "on" = enable additional debug messages
+- (default "off")
++Info: This overlay has been deprecated and removed - see gpio-ir
++Load: <Deprecated>
+
+
+ Name: ltc294x
+++ /dev/null
-From 4a208b7269c8713ac3e9cb9348af76b2bb03e919 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 4 Dec 2018 20:41:19 +0000
-Subject: [PATCH 290/703] Revert "staging: bcm2835-audio: Drop DT dependency"
-
-This reverts commit 933bc853bb764e476b0b0f633588f46d20f1f76a.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-audio/bcm2835.c | 41 ++++++++++---------
- 1 file changed, 22 insertions(+), 19 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -4,17 +4,15 @@
- #include <linux/platform_device.h>
-
- #include <linux/init.h>
--#include <linux/dma-mapping.h>
--#include <linux/of_device.h>
- #include <linux/slab.h>
- #include <linux/module.h>
-+#include <linux/of.h>
-
- #include "bcm2835.h"
-
- static bool enable_hdmi;
- static bool enable_headphones;
- static bool enable_compat_alsa = true;
--static int num_channels = MAX_SUBSTREAMS;
-
- module_param(enable_hdmi, bool, 0444);
- MODULE_PARM_DESC(enable_hdmi, "Enables HDMI virtual audio device");
-@@ -23,8 +21,6 @@ MODULE_PARM_DESC(enable_headphones, "Ena
- module_param(enable_compat_alsa, bool, 0444);
- MODULE_PARM_DESC(enable_compat_alsa,
- "Enables ALSA compatibility virtual audio device");
--module_param(num_channels, int, 0644);
--MODULE_PARM_DESC(num_channels, "Number of audio channels (default: 8)");
-
- static void snd_devm_unregister_child(struct device *dev, void *res)
- {
-@@ -411,30 +407,31 @@ static int snd_add_child_devices(struct
- return 0;
- }
-
--static int snd_bcm2835_alsa_probe(struct platform_device *pdev)
-+static int snd_bcm2835_alsa_probe_dt(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
-+ u32 numchans;
- int err;
-
-- if (num_channels <= 0 || num_channels > MAX_SUBSTREAMS) {
-- num_channels = MAX_SUBSTREAMS;
-- dev_warn(dev, "Illegal num_channels value, will use %u\n",
-- num_channels);
-- }
--
-- dev->coherent_dma_mask = DMA_BIT_MASK(32);
-- dev->dma_mask = &dev->coherent_dma_mask;
-- err = of_dma_configure(dev, NULL, true);
-+ err = of_property_read_u32(dev->of_node, "brcm,pwm-channels",
-+ &numchans);
- if (err) {
-- dev_err(dev, "Unable to setup DMA: %d\n", 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 = bcm2835_devm_add_vchi_ctx(dev);
- if (err)
- return err;
-
-- err = snd_add_child_devices(dev, num_channels);
-+ err = snd_add_child_devices(dev, numchans);
- if (err)
- return err;
-
-@@ -456,14 +453,21 @@ static int snd_bcm2835_alsa_resume(struc
-
- #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,
-+ .probe = snd_bcm2835_alsa_probe_dt,
- #ifdef CONFIG_PM
- .suspend = snd_bcm2835_alsa_suspend,
- .resume = snd_bcm2835_alsa_resume,
- #endif
- .driver = {
- .name = "bcm2835_audio",
-+ .of_match_table = snd_bcm2835_of_match_table,
- },
- };
- module_platform_driver(bcm2835_alsa0_driver);
-@@ -471,4 +475,3 @@ module_platform_driver(bcm2835_alsa0_dri
- MODULE_AUTHOR("Dom Cobley");
- MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
- MODULE_LICENSE("GPL");
--MODULE_ALIAS("platform:bcm2835_audio");
--- /dev/null
+From c38a34a4f9465df9bfeff355772555efa0cd574b Mon Sep 17 00:00:00 2001
+From: 6by9 <6by9@users.noreply.github.com>
+Date: Tue, 11 Dec 2018 15:18:02 +0000
+Subject: [PATCH 290/725] staging: bcm2835-camera: Check the error for
+ REPEAT_SEQ_HEADER (#2782)
+
+When handling for V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER was added
+the firmware would reject the setting if H264 hadn't already been
+selected. This was fixed in the firmware at that point, but to
+enable backwards compatibility the returned error was ignored.
+
+That was Dec 2013, so the chances of having a firmware that still
+has that issue is so close to zero that the workaround can be
+removed.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/controls.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -1100,7 +1100,7 @@ static const struct bm2835_mmal_v4l2_ctr
+ 0, 1, NULL,
+ MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
+ &ctrl_set_video_encode_param_output,
+- true /* Errors ignored as requires latest firmware to work */
++ false
+ },
+ {
+ V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+++ /dev/null
-From b459fc35cd584d7f1c02da9f83f9238caa742c97 Mon Sep 17 00:00:00 2001
-From: dev-3Dlab <45081440+dev-3Dlab@users.noreply.github.com>
-Date: Wed, 5 Dec 2018 10:59:11 +0100
-Subject: [PATCH 291/703] ASoC: add driver for 3Dlab Nano soundcard (#2758)
-
-Signed-off-by: GT <dev@3d-lab-av.com>
----
- .../overlays/3dlab-nano-player-overlay.dts | 32 ++
- arch/arm/boot/dts/overlays/Makefile | 1 +
- arch/arm/boot/dts/overlays/README | 6 +
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- sound/soc/bcm/3dlab-nano-player.c | 370 ++++++++++++++++++
- sound/soc/bcm/Kconfig | 6 +
- sound/soc/bcm/Makefile | 2 +
- 8 files changed, 419 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
- create mode 100644 sound/soc/bcm/3dlab-nano-player.c
-
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
-@@ -0,0 +1,32 @@
-+// Definitions for 3Dlab Nano Player
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+ compatible = "brcm,bcm2708";
-+
-+ fragment@0 {
-+ target = <&i2s>;
-+ __overlay__ {
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&i2c>;
-+ __overlay__ {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "okay";
-+
-+ nano-player@41 {
-+ compatible = "3dlab,nano-player";
-+ reg = <0x41>;
-+ i2s-controller = <&i2s>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+};
-+
-+// EOF
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -1,6 +1,7 @@
- # Overlays for the Raspberry Pi platform
-
- dtbo-$(CONFIG_ARCH_BCM2835) += \
-+ 3dlab-nano-player.dtbo \
- adau1977-adc.dtbo \
- adau7002-simple.dtbo \
- ads1015.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -199,6 +199,12 @@ Params:
- and the other i2c baudrate parameters.
-
-
-+Name: 3dlab-nano-player
-+Info: Configures the 3Dlab Nano Player
-+Load: dtoverlay=3dlab-nano-player
-+Params: <None>
-+
-+
- Name: adau1977-adc
- Info: Overlay for activation of ADAU1977 ADC codec over I2C for control
- and I2S for data.
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -902,6 +902,7 @@ CONFIG_SND_USB_6FIRE=m
- CONFIG_SND_USB_HIFACE=m
- CONFIG_SND_SOC=m
- CONFIG_SND_BCM2835_SOC_I2S=m
-+CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
- CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -895,6 +895,7 @@ CONFIG_SND_USB_6FIRE=m
- CONFIG_SND_USB_HIFACE=m
- CONFIG_SND_SOC=m
- CONFIG_SND_BCM2835_SOC_I2S=m
-+CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
- CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
---- /dev/null
-+++ b/sound/soc/bcm/3dlab-nano-player.c
-@@ -0,0 +1,370 @@
-+/*
-+ * 3Dlab Nano Player ALSA SoC Audio driver.
-+ *
-+ * Copyright (C) 2018 3Dlab.
-+ *
-+ * Author: GT <dev@3d-lab-av.com>
-+ *
-+ * 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 <linux/module.h>
-+#include <linux/i2c.h>
-+#include <sound/soc.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/control.h>
-+
-+#define NANO_ID 0x00
-+#define NANO_VER 0x01
-+#define NANO_CFG 0x02
-+#define NANO_STATUS 0x03
-+#define NANO_SPI_ADDR 0x04
-+#define NANO_SPI_DATA 0x05
-+
-+#define NANO_ID_VAL 0x3D
-+#define NANO_CFG_OFF 0x00
-+#define NANO_CFG_MULT1 0
-+#define NANO_CFG_MULT2 1
-+#define NANO_CFG_MULT4 2
-+#define NANO_CFG_MULT8 3
-+#define NANO_CFG_MULT16 4
-+#define NANO_CFG_CLK22 0
-+#define NANO_CFG_CLK24 BIT(3)
-+#define NANO_CFG_DSD BIT(4)
-+#define NANO_CFG_ENA BIT(5)
-+#define NANO_CFG_BLINK BIT(6)
-+#define NANO_STATUS_P1 BIT(0)
-+#define NANO_STATUS_P2 BIT(1)
-+#define NANO_STATUS_FLG BIT(2)
-+#define NANO_STATUS_CLK BIT(3)
-+#define NANO_SPI_READ 0
-+#define NANO_SPI_WRITE BIT(5)
-+
-+#define NANO_DAC_CTRL1 0x00
-+#define NANO_DAC_CTRL2 0x01
-+#define NANO_DAC_CTRL3 0x02
-+#define NANO_DAC_LATT 0x03
-+#define NANO_DAC_RATT 0x04
-+
-+#define NANO_CTRL2_VAL 0x22
-+
-+static int nano_player_spi_write(struct regmap *map,
-+ unsigned int reg, unsigned int val)
-+{
-+ /* indirect register access */
-+ regmap_write(map, NANO_SPI_DATA, val);
-+ regmap_write(map, NANO_SPI_ADDR, reg | NANO_SPI_WRITE);
-+ return 0;
-+}
-+
-+static int nano_player_ctrl_info(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_info *uinfo)
-+{
-+ /* describe control element */
-+ if (strstr(kcontrol->id.name, "Volume")) {
-+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-+ uinfo->count = 1;
-+ uinfo->value.integer.min = 0;
-+ uinfo->value.integer.max = 100;
-+ } else {
-+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-+ uinfo->count = 1;
-+ uinfo->value.integer.min = 0;
-+ uinfo->value.integer.max = 1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int nano_player_ctrl_put(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *ucontrol)
-+{
-+ /* program control value to hardware */
-+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
-+ struct regmap *regmap = snd_soc_card_get_drvdata(card);
-+
-+ if (strstr(kcontrol->id.name, "Volume")) {
-+ unsigned int vol = ucontrol->value.integer.value[0];
-+ unsigned int att = 255 - (2 * (100 - vol));
-+
-+ nano_player_spi_write(regmap, NANO_DAC_LATT, att);
-+ nano_player_spi_write(regmap, NANO_DAC_RATT, att);
-+ kcontrol->private_value = vol;
-+ } else {
-+ unsigned int mute = ucontrol->value.integer.value[0];
-+ unsigned int reg = NANO_CTRL2_VAL | mute;
-+
-+ nano_player_spi_write(regmap, NANO_DAC_CTRL2, reg);
-+ kcontrol->private_value = mute;
-+ }
-+ return 0;
-+}
-+
-+static int nano_player_ctrl_get(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *ucontrol)
-+{
-+ /* return last programmed value */
-+ ucontrol->value.integer.value[0] = kcontrol->private_value;
-+ return 0;
-+}
-+
-+#define SOC_NANO_PLAYER_CTRL(xname) \
-+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
-+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
-+ .info = nano_player_ctrl_info, \
-+ .put = nano_player_ctrl_put, \
-+ .get = nano_player_ctrl_get }
-+
-+static const struct snd_kcontrol_new nano_player_controls[] = {
-+ SOC_NANO_PLAYER_CTRL("Master Playback Volume"),
-+ SOC_NANO_PLAYER_CTRL("Master Playback Switch"),
-+};
-+
-+static const unsigned int nano_player_rates[] = {
-+ 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000,
-+ 705600, 768000 /* only possible with fast clocks */
-+};
-+
-+static struct snd_pcm_hw_constraint_list nano_player_constraint_rates = {
-+ .list = nano_player_rates,
-+ .count = ARRAY_SIZE(nano_player_rates),
-+};
-+
-+static int nano_player_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+ struct snd_soc_card *card = rtd->card;
-+ struct regmap *regmap = snd_soc_card_get_drvdata(card);
-+ struct snd_soc_pcm_stream *cpu = &rtd->cpu_dai->driver->playback;
-+ struct snd_soc_pcm_stream *codec = &rtd->codec_dai->driver->playback;
-+ unsigned int sample_bits = 32;
-+ unsigned int val;
-+
-+ /* configure cpu dai */
-+ cpu->formats |= SNDRV_PCM_FMTBIT_DSD_U32_LE;
-+ cpu->rate_max = 768000;
-+
-+ /* configure dummy codec dai */
-+ codec->rate_min = 44100;
-+ codec->rates = SNDRV_PCM_RATE_KNOT;
-+ codec->formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_DSD_U32_LE;
-+
-+ /* configure max supported rate */
-+ regmap_read(regmap, NANO_STATUS, &val);
-+ if (val & NANO_STATUS_CLK) {
-+ dev_notice(card->dev, "Board with fast clocks installed\n");
-+ codec->rate_max = 768000;
-+ } else {
-+ dev_notice(card->dev, "Board with normal clocks installed\n");
-+ codec->rate_max = 384000;
-+ }
-+
-+ /* frame length enforced by hardware */
-+ return snd_soc_dai_set_bclk_ratio(rtd->cpu_dai, sample_bits * 2);
-+}
-+
-+static int nano_player_startup(struct snd_pcm_substream *substream)
-+{
-+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
-+ SNDRV_PCM_HW_PARAM_RATE,
-+ &nano_player_constraint_rates);
-+}
-+
-+static int nano_player_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 regmap *regmap = snd_soc_card_get_drvdata(card);
-+ unsigned int config = NANO_CFG_ENA;
-+ struct snd_mask *fmt;
-+
-+ /* configure PCM or DSD */
-+ fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
-+ if (snd_mask_test(fmt, SNDRV_PCM_FORMAT_DSD_U32_LE)) {
-+ /* embed DSD in PCM data */
-+ snd_mask_none(fmt);
-+ snd_mask_set(fmt, SNDRV_PCM_FORMAT_S32_LE);
-+ /* enable DSD mode */
-+ config |= NANO_CFG_DSD;
-+ }
-+
-+ /* configure clocks */
-+ switch (params_rate(params)) {
-+ case 44100:
-+ config |= NANO_CFG_MULT1 | NANO_CFG_CLK22;
-+ break;
-+ case 88200:
-+ config |= NANO_CFG_MULT2 | NANO_CFG_CLK22;
-+ break;
-+ case 176400:
-+ config |= NANO_CFG_MULT4 | NANO_CFG_CLK22;
-+ break;
-+ case 352800:
-+ config |= NANO_CFG_MULT8 | NANO_CFG_CLK22;
-+ break;
-+ case 705600:
-+ config |= NANO_CFG_MULT16 | NANO_CFG_CLK22;
-+ break;
-+ case 48000:
-+ config |= NANO_CFG_MULT1 | NANO_CFG_CLK24;
-+ break;
-+ case 96000:
-+ config |= NANO_CFG_MULT2 | NANO_CFG_CLK24;
-+ break;
-+ case 192000:
-+ config |= NANO_CFG_MULT4 | NANO_CFG_CLK24;
-+ break;
-+ case 384000:
-+ config |= NANO_CFG_MULT8 | NANO_CFG_CLK24;
-+ break;
-+ case 768000:
-+ config |= NANO_CFG_MULT16 | NANO_CFG_CLK24;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ dev_dbg(card->dev, "Send CFG register 0x%02X\n", config);
-+ return regmap_write(regmap, NANO_CFG, config);
-+}
-+
-+static struct snd_soc_ops nano_player_ops = {
-+ .startup = nano_player_startup,
-+ .hw_params = nano_player_hw_params,
-+};
-+
-+static struct snd_soc_dai_link nano_player_link = {
-+ .name = "3Dlab Nano Player",
-+ .stream_name = "3Dlab Nano Player HiFi",
-+ .platform_name = "bcm2708-i2s.0",
-+ .cpu_dai_name = "bcm2708-i2s.0",
-+ .codec_name = "snd-soc-dummy",
-+ .codec_dai_name = "snd-soc-dummy-dai",
-+ .dai_fmt = SND_SOC_DAIFMT_I2S |
-+ SND_SOC_DAIFMT_CONT |
-+ SND_SOC_DAIFMT_NB_NF |
-+ SND_SOC_DAIFMT_CBM_CFM,
-+ .init = nano_player_init,
-+ .ops = &nano_player_ops,
-+};
-+
-+static const struct regmap_config nano_player_regmap = {
-+ .reg_bits = 8,
-+ .val_bits = 8,
-+ .max_register = 128,
-+ .cache_type = REGCACHE_RBTREE,
-+};
-+
-+static int nano_player_card_probe(struct snd_soc_card *card)
-+{
-+ struct regmap *regmap = snd_soc_card_get_drvdata(card);
-+ unsigned int val;
-+
-+ /* check hardware integrity */
-+ regmap_read(regmap, NANO_ID, &val);
-+ if (val != NANO_ID_VAL) {
-+ dev_err(card->dev, "Invalid ID register 0x%02X\n", val);
-+ return -ENODEV;
-+ }
-+
-+ /* report version to the user */
-+ regmap_read(regmap, NANO_VER, &val);
-+ dev_notice(card->dev, "Started 3Dlab Nano Player driver (v%d)\n", val);
-+
-+ /* enable internal audio bus and blink status LED */
-+ return regmap_write(regmap, NANO_CFG, NANO_CFG_ENA | NANO_CFG_BLINK);
-+}
-+
-+static int nano_player_card_remove(struct snd_soc_card *card)
-+{
-+ /* disable internal audio bus */
-+ struct regmap *regmap = snd_soc_card_get_drvdata(card);
-+
-+ return regmap_write(regmap, NANO_CFG, NANO_CFG_OFF);
-+}
-+
-+static struct snd_soc_card nano_player_card = {
-+ .name = "3Dlab_Nano_Player",
-+ .owner = THIS_MODULE,
-+ .dai_link = &nano_player_link,
-+ .num_links = 1,
-+ .controls = nano_player_controls,
-+ .num_controls = ARRAY_SIZE(nano_player_controls),
-+ .probe = nano_player_card_probe,
-+ .remove = nano_player_card_remove,
-+};
-+
-+static int nano_player_i2c_probe(struct i2c_client *i2c,
-+ const struct i2c_device_id *id)
-+{
-+ struct regmap *regmap;
-+ int ret;
-+
-+ regmap = devm_regmap_init_i2c(i2c, &nano_player_regmap);
-+ if (IS_ERR(regmap)) {
-+ ret = PTR_ERR(regmap);
-+ dev_err(&i2c->dev, "Failed to init regmap %d\n", ret);
-+ return ret;
-+ }
-+
-+ if (i2c->dev.of_node) {
-+ struct snd_soc_dai_link *dai = &nano_player_link;
-+ struct device_node *node;
-+
-+ /* cpu handle configured by device tree */
-+ node = of_parse_phandle(i2c->dev.of_node, "i2s-controller", 0);
-+ if (node) {
-+ dai->platform_name = NULL;
-+ dai->platform_of_node = node;
-+ dai->cpu_dai_name = NULL;
-+ dai->cpu_of_node = node;
-+ }
-+ }
-+
-+ nano_player_card.dev = &i2c->dev;
-+ snd_soc_card_set_drvdata(&nano_player_card, regmap);
-+ ret = devm_snd_soc_register_card(&i2c->dev, &nano_player_card);
-+
-+ if (ret && ret != -EPROBE_DEFER)
-+ dev_err(&i2c->dev, "Failed to register card %d\n", ret);
-+
-+ return ret;
-+}
-+
-+static const struct of_device_id nano_player_of_match[] = {
-+ { .compatible = "3dlab,nano-player", },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, nano_player_of_match);
-+
-+static const struct i2c_device_id nano_player_i2c_id[] = {
-+ { "nano-player", 0 },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(i2c, nano_player_i2c_id);
-+
-+static struct i2c_driver nano_player_i2c_driver = {
-+ .probe = nano_player_i2c_probe,
-+ .id_table = nano_player_i2c_id,
-+ .driver = {
-+ .name = "nano-player",
-+ .owner = THIS_MODULE,
-+ .of_match_table = nano_player_of_match,
-+ },
-+};
-+
-+module_i2c_driver(nano_player_i2c_driver);
-+
-+MODULE_DESCRIPTION("ASoC 3Dlab Nano Player driver");
-+MODULE_AUTHOR("GT <dev@3d-lab-av.com>");
-+MODULE_LICENSE("GPL v2");
-+
-+/* EOF */
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -17,6 +17,12 @@ config SND_SOC_CYGNUS
-
- If you don't know what to do here, say N.
-
-+config SND_BCM2708_SOC_3DLAB_NANO_PLAYER
-+ tristate "Support for 3Dlab Nano Player"
-+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+ help
-+ Say Y or M if you want to add support for 3Dlab Nano Player.
-+
- config SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD
- tristate "Support for Google voiceHAT soundcard"
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -12,6 +12,7 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-
- snd-soc-googlevoicehat-codec-objs := googlevoicehat-codec.o
-
- # BCM2708 Machine Support
-+snd-soc-3dlab-nano-player-objs := 3dlab-nano-player.o
- snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
- snd-soc-justboom-dac-objs := justboom-dac.o
- snd-soc-rpi-cirrus-objs := rpi-cirrus.o
-@@ -31,6 +32,7 @@ snd-soc-fe-pi-audio-objs := fe-pi-audio.
- snd-soc-rpi-simple-soundcard-objs := rpi-simple-soundcard.o
- snd-soc-rpi-wm8804-soundcard-objs := rpi-wm8804-soundcard.o
-
-+obj-$(CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER) += snd-soc-3dlab-nano-player.o
- obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD) += snd-soc-googlevoicehat-codec.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
- obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
--- /dev/null
+From 92ac07c588df68c6cbc6c7965b679ba02d3c994b Mon Sep 17 00:00:00 2001
+From: Matthias Reichl <hias@horus.com>
+Date: Wed, 9 Jan 2019 14:51:01 +0100
+Subject: [PATCH 291/725] gpio-ir: change default pull configuration to up
+
+IR receivers like the TSOP series from Vishay and compatible ones
+have active-low open collector outputs with an internal pull up of
+about 30k (according to the TSOP datasheets).
+
+Activating a pull-down resistor on the GPIO will make it work against
+the pull-up in the IR receiver and brings the idle input voltage down
+to about 1.9V (measured on a RPi3B+ with a TSOP4438). While that's
+usually enough to make the RPi see a high signal it's certainly not
+optimal and may even fail when using an IR receiver with a weaker pull-up.
+
+Switching the default GPIO pull to "up" results in an input voltage
+level of about 3.3V and ensures that an idle state (high signal) will
+be detected if no IR receiver is attached.
+
+Signed-off-by: Matthias Reichl <hias@horus.com>
+---
+ arch/arm/boot/dts/overlays/README | 2 +-
+ arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -611,7 +611,7 @@ Load: dtoverlay=gpio-ir,<param>=<val>
+ Params: gpio_pin Input pin number. Default is 18.
+
+ gpio_pull Desired pull-up/down state (off, down, up)
+- Default is "down".
++ Default is "up".
+
+ rc-map-name Default rc keymap (can also be changed by
+ ir-keytable), defaults to "rc-rc6-mce"
+--- a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
+@@ -30,7 +30,7 @@
+ gpio_ir_pins: gpio_ir_pins@12 {
+ brcm,pins = <18>; // pin 18
+ brcm,function = <0>; // in
+- brcm,pull = <1>; // down
++ brcm,pull = <2>; // up
+ };
+ };
+ };
--- /dev/null
+From bf6b1c361f3e01a5d7ce6ac2c6cb29ece28bf41a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 10 Jan 2019 17:58:06 +0000
+Subject: [PATCH 292/725] firmware: raspberrypi: Report the fw variant during
+ probe
+
+The driver already reported the firmware build date during probe.
+The mailbox calls have been extended to also report the variant
+ 1 = standard start.elf
+ 2 = start_x.elf (includes camera stack)
+ 3 = start_db.elf (includes assert logging)
+ 4 = start_cd.elf (cutdown version for smallest memory footprint).
+Log the variant during probe.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/firmware/raspberrypi.c | 32 +++++++++++++++++-----
+ include/soc/bcm2835/raspberrypi-firmware.h | 1 +
+ 2 files changed, 26 insertions(+), 7 deletions(-)
+
+--- a/drivers/firmware/raspberrypi.c
++++ b/drivers/firmware/raspberrypi.c
+@@ -227,21 +227,39 @@ static const struct attribute_group rpi_
+ static void
+ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
+ {
++ static const char * const variant_strs[] = {
++ "unknown",
++ "start",
++ "start_x",
++ "start_db",
++ "start_cd",
++ };
++ const char *variant_str = "cmd unsupported";
+ u32 packet;
++ u32 variant;
++ struct tm tm;
+ int ret = rpi_firmware_property(fw,
+ RPI_FIRMWARE_GET_FIRMWARE_REVISION,
+ &packet, sizeof(packet));
+
+- if (ret == 0) {
+- struct tm tm;
++ if (ret)
++ return;
+
+- time64_to_tm(packet, 0, &tm);
++ ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_FIRMWARE_VARIANT,
++ &variant, sizeof(variant));
+
+- dev_info(fw->cl.dev,
+- "Attached to firmware from %04ld-%02d-%02d %02d:%02d\n",
+- tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+- tm.tm_hour, tm.tm_min);
++ if (!ret) {
++ if (variant >= ARRAY_SIZE(variant_strs))
++ variant = 0;
++ variant_str = variant_strs[variant];
+ }
++
++ time64_to_tm(packet, 0, &tm);
++
++ dev_info(fw->cl.dev,
++ "Attached to firmware from %04ld-%02d-%02d %02d:%02d, variant %s\n",
++ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
++ tm.tm_min, variant_str);
+ }
+
+ static void
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -41,6 +41,7 @@ struct rpi_firmware_property_tag_header
+ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_PROPERTY_END = 0,
+ RPI_FIRMWARE_GET_FIRMWARE_REVISION = 0x00000001,
++ RPI_FIRMWARE_GET_FIRMWARE_VARIANT = 0x00000002,
+
+ RPI_FIRMWARE_SET_CURSOR_INFO = 0x00008010,
+ RPI_FIRMWARE_SET_CURSOR_STATE = 0x00008011,
+++ /dev/null
-From a7544b1d73143b69134dd9ec665d0013775aca50 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 5 Dec 2018 11:56:40 +0000
-Subject: [PATCH 292/703] overlays: Update README with removal of lirc-rpi
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README | 57 ++++++++++++-------------------
- 1 file changed, 21 insertions(+), 36 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -56,23 +56,29 @@ have its contents deleted (or commented
- Using Overlays
- ==============
-
--Overlays are loaded using the "dtoverlay" directive. As an example, consider
--the popular lirc-rpi module, the Linux Infrared Remote Control driver. In the
--pre-DT world this would be loaded from /etc/modules, with an explicit
--"modprobe lirc-rpi" command, or programmatically by lircd. With DT enabled,
--this becomes a line in config.txt:
--
-- dtoverlay=lirc-rpi
--
--This causes the file /boot/overlays/lirc-rpi.dtbo to be loaded. By
--default it will use GPIOs 17 (out) and 18 (in), but this can be modified using
--DT parameters:
--
-- dtoverlay=lirc-rpi,gpio_out_pin=17,gpio_in_pin=13
--
--Parameters always have default values, although in some cases (e.g. "w1-gpio")
--it is necessary to provided multiple overlays in order to get the desired
--behaviour. See the list of overlays below for a description of the parameters
-+Overlays are loaded using the "dtoverlay" config.txt setting. As an example,
-+consider I2C Real Time Clock drivers. In the pre-DT world these would be loaded
-+by writing a magic string comprising a device identifier and an I2C address to
-+a special file in /sys/class/i2c-adapter, having first loaded the driver for
-+the I2C interface and the RTC device - something like this:
-+
-+ modprobe i2c-bcm2835
-+ modprobe rtc-ds1307
-+ echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
-+
-+With DT enabled, this becomes a line in config.txt:
-+
-+ dtoverlay=i2c-rtc,ds1307
-+
-+This causes the file /boot/overlays/i2c-rtc.dtbo to be loaded and a "node"
-+describing the DS1307 I2C device to be added to the Device Tree for the Pi. By
-+default it usees address 0x68, but this can be modified with an additional DT
-+parameter:
-+
-+ dtoverlay=i2c-rtc,ds1307,addr=0x68
-+
-+Parameters usually have default values, although certain parameters are
-+mandatory. See the list of overlays below for a description of the parameters
- and their defaults.
-
- The Overlay and Parameter Reference
-@@ -1135,29 +1141,8 @@ Params: <None>
-
-
- Name: lirc-rpi
--Info: Configures lirc-rpi (Linux Infrared Remote Control for Raspberry Pi)
-- Consult the module documentation for more details.
--Load: dtoverlay=lirc-rpi,<param>=<val>
--Params: gpio_out_pin GPIO for output (default "17")
--
-- gpio_in_pin GPIO for input (default "18")
--
-- gpio_in_pull Pull up/down/off on the input pin
-- (default "down")
--
-- sense Override the IR receive auto-detection logic:
-- "0" = force active-high
-- "1" = force active-low
-- "-1" = use auto-detection
-- (default "-1")
--
-- softcarrier Turn the software carrier "on" or "off"
-- (default "on")
--
-- invert "on" = invert the output pin (default "off")
--
-- debug "on" = enable additional debug messages
-- (default "off")
-+Info: This overlay has been deprecated and removed - see gpio-ir
-+Load: <Deprecated>
-
-
- Name: ltc294x
--- /dev/null
+From 6a9b19e48f8503ca3ac0c4ef29f34d6b6a96dfac Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 10 Jan 2019 18:48:54 +0000
+Subject: [PATCH 293/725] firmware: raspberrypi: Report the fw git hash during
+ probe
+
+The firmware can now report the git hash from which it was built
+via the mailbox, so report it during probe.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/firmware/raspberrypi.c | 17 +++++++++++++++++
+ include/soc/bcm2835/raspberrypi-firmware.h | 1 +
+ 2 files changed, 18 insertions(+)
+
+--- a/drivers/firmware/raspberrypi.c
++++ b/drivers/firmware/raspberrypi.c
+@@ -263,6 +263,22 @@ rpi_firmware_print_firmware_revision(str
+ }
+
+ static void
++rpi_firmware_print_firmware_hash(struct rpi_firmware *fw)
++{
++ u32 hash[5];
++ int ret = rpi_firmware_property(fw,
++ RPI_FIRMWARE_GET_FIRMWARE_HASH,
++ hash, sizeof(hash));
++
++ if (ret)
++ return;
++
++ dev_info(fw->cl.dev,
++ "Firmware hash is %08x%08x%08x%08x%08x\n",
++ hash[0], hash[1], hash[2], hash[3], hash[4]);
++}
++
++static void
+ rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
+ {
+ u32 packet;
+@@ -308,6 +324,7 @@ static int rpi_firmware_probe(struct pla
+ g_pdev = pdev;
+
+ rpi_firmware_print_firmware_revision(fw);
++ rpi_firmware_print_firmware_hash(fw);
+ rpi_register_hwmon_driver(dev, fw);
+
+ return 0;
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -42,6 +42,7 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_PROPERTY_END = 0,
+ RPI_FIRMWARE_GET_FIRMWARE_REVISION = 0x00000001,
+ RPI_FIRMWARE_GET_FIRMWARE_VARIANT = 0x00000002,
++ RPI_FIRMWARE_GET_FIRMWARE_HASH = 0x00000003,
+
+ RPI_FIRMWARE_SET_CURSOR_INFO = 0x00008010,
+ RPI_FIRMWARE_SET_CURSOR_STATE = 0x00008011,
+++ /dev/null
-From c2423f2fef7098dac416a1b49b3f9efbbbbd3293 Mon Sep 17 00:00:00 2001
-From: 6by9 <6by9@users.noreply.github.com>
-Date: Tue, 11 Dec 2018 15:18:02 +0000
-Subject: [PATCH 293/703] staging: bcm2835-camera: Check the error for
- REPEAT_SEQ_HEADER (#2782)
-
-When handling for V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER was added
-the firmware would reject the setting if H264 hadn't already been
-selected. This was fixed in the firmware at that point, but to
-enable backwards compatibility the returned error was ignored.
-
-That was Dec 2013, so the chances of having a firmware that still
-has that issue is so close to zero that the workaround can be
-removed.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/bcm2835-camera/controls.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -1100,7 +1100,7 @@ static const struct bm2835_mmal_v4l2_ctr
- 0, 1, NULL,
- MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
- &ctrl_set_video_encode_param_output,
-- true /* Errors ignored as requires latest firmware to work */
-+ false
- },
- {
- V4L2_CID_MPEG_VIDEO_H264_PROFILE,
--- /dev/null
+From 848168d31f850623d2837c2cc154587189a5fd47 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 15 Jan 2019 09:56:41 +0000
+Subject: [PATCH 294/725] arm64: dts: broadcom: Enable fixups for overlays
+
+See: https://github.com/raspberrypi/linux/pull/2733
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm64/boot/dts/broadcom/Makefile | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/arch/arm64/boot/dts/broadcom/Makefile
++++ b/arch/arm64/boot/dts/broadcom/Makefile
+@@ -9,3 +9,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rp
+
+ subdir-y += northstar2
+ subdir-y += stingray
++
++# Enable fixups to support overlays on BCM2835 platforms
++ifeq ($(CONFIG_ARCH_BCM2835),y)
++ DTC_FLAGS ?= -@
++endif
+++ /dev/null
-From 550dce51930fca1d5dc2a00a7a6f172fbb4e5b56 Mon Sep 17 00:00:00 2001
-From: Matthias Reichl <hias@horus.com>
-Date: Wed, 9 Jan 2019 14:51:01 +0100
-Subject: [PATCH 294/703] gpio-ir: change default pull configuration to up
-
-IR receivers like the TSOP series from Vishay and compatible ones
-have active-low open collector outputs with an internal pull up of
-about 30k (according to the TSOP datasheets).
-
-Activating a pull-down resistor on the GPIO will make it work against
-the pull-up in the IR receiver and brings the idle input voltage down
-to about 1.9V (measured on a RPi3B+ with a TSOP4438). While that's
-usually enough to make the RPi see a high signal it's certainly not
-optimal and may even fail when using an IR receiver with a weaker pull-up.
-
-Switching the default GPIO pull to "up" results in an input voltage
-level of about 3.3V and ensures that an idle state (high signal) will
-be detected if no IR receiver is attached.
-
-Signed-off-by: Matthias Reichl <hias@horus.com>
----
- arch/arm/boot/dts/overlays/README | 2 +-
- arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -611,7 +611,7 @@ Load: dtoverlay=gpio-ir,<param>=<val>
- Params: gpio_pin Input pin number. Default is 18.
-
- gpio_pull Desired pull-up/down state (off, down, up)
-- Default is "down".
-+ Default is "up".
-
- rc-map-name Default rc keymap (can also be changed by
- ir-keytable), defaults to "rc-rc6-mce"
---- a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
-@@ -30,7 +30,7 @@
- gpio_ir_pins: gpio_ir_pins@12 {
- brcm,pins = <18>; // pin 18
- brcm,function = <0>; // in
-- brcm,pull = <1>; // down
-+ brcm,pull = <2>; // up
- };
- };
- };
+++ /dev/null
-From 127e0899869365f5dc078e1ed84429ce81df90dc Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 10 Jan 2019 17:58:06 +0000
-Subject: [PATCH 295/703] firmware: raspberrypi: Report the fw variant during
- probe
-
-The driver already reported the firmware build date during probe.
-The mailbox calls have been extended to also report the variant
- 1 = standard start.elf
- 2 = start_x.elf (includes camera stack)
- 3 = start_db.elf (includes assert logging)
- 4 = start_cd.elf (cutdown version for smallest memory footprint).
-Log the variant during probe.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/firmware/raspberrypi.c | 32 +++++++++++++++++-----
- include/soc/bcm2835/raspberrypi-firmware.h | 1 +
- 2 files changed, 26 insertions(+), 7 deletions(-)
-
---- a/drivers/firmware/raspberrypi.c
-+++ b/drivers/firmware/raspberrypi.c
-@@ -227,21 +227,39 @@ static const struct attribute_group rpi_
- static void
- rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
- {
-+ static const char * const variant_strs[] = {
-+ "unknown",
-+ "start",
-+ "start_x",
-+ "start_db",
-+ "start_cd",
-+ };
-+ const char *variant_str = "cmd unsupported";
- u32 packet;
-+ u32 variant;
-+ struct tm tm;
- int ret = rpi_firmware_property(fw,
- RPI_FIRMWARE_GET_FIRMWARE_REVISION,
- &packet, sizeof(packet));
-
-- if (ret == 0) {
-- struct tm tm;
-+ if (ret)
-+ return;
-
-- time64_to_tm(packet, 0, &tm);
-+ ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_FIRMWARE_VARIANT,
-+ &variant, sizeof(variant));
-
-- dev_info(fw->cl.dev,
-- "Attached to firmware from %04ld-%02d-%02d %02d:%02d\n",
-- tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-- tm.tm_hour, tm.tm_min);
-+ if (!ret) {
-+ if (variant >= ARRAY_SIZE(variant_strs))
-+ variant = 0;
-+ variant_str = variant_strs[variant];
- }
-+
-+ time64_to_tm(packet, 0, &tm);
-+
-+ dev_info(fw->cl.dev,
-+ "Attached to firmware from %04ld-%02d-%02d %02d:%02d, variant %s\n",
-+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
-+ tm.tm_min, variant_str);
- }
-
- static void
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -41,6 +41,7 @@ struct rpi_firmware_property_tag_header
- enum rpi_firmware_property_tag {
- RPI_FIRMWARE_PROPERTY_END = 0,
- RPI_FIRMWARE_GET_FIRMWARE_REVISION = 0x00000001,
-+ RPI_FIRMWARE_GET_FIRMWARE_VARIANT = 0x00000002,
-
- RPI_FIRMWARE_SET_CURSOR_INFO = 0x00008010,
- RPI_FIRMWARE_SET_CURSOR_STATE = 0x00008011,
--- /dev/null
+From 699bca131fe01413d547e40a9e0d1db57b56e697 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 18 May 2018 10:26:59 +0100
+Subject: [PATCH 295/725] sc16is7xx: Fix for "Unexpected interrupt: 8"
+
+The SC16IS752 has an Enhanced Feature Register which is aliased at the
+same address as the Interrupt Identification Register; accessing it
+requires that a magic value is written to the Line Configuration
+Register. If an interrupt is raised while the EFR is mapped in then
+the ISR won't be able to access the IIR, leading to the "Unexpected
+interrupt" error messages.
+
+Avoid the problem by claiming a mutex around accesses to the EFR
+register, also claiming the mutex in the interrupt handler work
+item (this is equivalent to disabling interrupts to interlock against
+a non-threaded interrupt handler).
+
+See: https://github.com/raspberrypi/linux/issues/2529
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/tty/serial/sc16is7xx.c | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+--- a/drivers/tty/serial/sc16is7xx.c
++++ b/drivers/tty/serial/sc16is7xx.c
+@@ -328,6 +328,7 @@ struct sc16is7xx_port {
+ struct kthread_worker kworker;
+ struct task_struct *kworker_task;
+ struct kthread_work irq_work;
++ struct mutex efr_lock;
+ struct sc16is7xx_one p[0];
+ };
+
+@@ -499,6 +500,21 @@ static int sc16is7xx_set_baud(struct uar
+ div /= 4;
+ }
+
++ /* In an amazing feat of design, the Enhanced Features Register shares
++ * the address of the Interrupt Identification Register, and is
++ * switched in by writing a magic value (0xbf) to the Line Control
++ * Register. Any interrupt firing during this time will see the EFR
++ * where it expects the IIR to be, leading to "Unexpected interrupt"
++ * messages.
++ *
++ * Prevent this possibility by claiming a mutex while accessing the
++ * EFR, and claiming the same mutex from within the interrupt handler.
++ * This is similar to disabling the interrupt, but that doesn't work
++ * because the bulk of the interrupt processing is run as a workqueue
++ * job in thread context.
++ */
++ mutex_lock(&s->efr_lock);
++
+ lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG);
+
+ /* Open the LCR divisors for configuration */
+@@ -514,6 +530,8 @@ static int sc16is7xx_set_baud(struct uar
+ /* Put LCR back to the normal mode */
+ sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
+
++ mutex_unlock(&s->efr_lock);
++
+ sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
+ SC16IS7XX_MCR_CLKSEL_BIT,
+ prescaler);
+@@ -698,6 +716,8 @@ static void sc16is7xx_ist(struct kthread
+ {
+ struct sc16is7xx_port *s = to_sc16is7xx_port(ws, irq_work);
+
++ mutex_lock(&s->efr_lock);
++
+ while (1) {
+ bool keep_polling = false;
+ int i;
+@@ -707,6 +727,8 @@ static void sc16is7xx_ist(struct kthread
+ if (!keep_polling)
+ break;
+ }
++
++ mutex_unlock(&s->efr_lock);
+ }
+
+ static irqreturn_t sc16is7xx_irq(int irq, void *dev_id)
+@@ -901,6 +923,9 @@ static void sc16is7xx_set_termios(struct
+ if (!(termios->c_cflag & CREAD))
+ port->ignore_status_mask |= SC16IS7XX_LSR_BRK_ERROR_MASK;
+
++ /* As above, claim the mutex while accessing the EFR. */
++ mutex_lock(&s->efr_lock);
++
+ sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
+ SC16IS7XX_LCR_CONF_MODE_B);
+
+@@ -922,6 +947,8 @@ static void sc16is7xx_set_termios(struct
+ /* Update LCR register */
+ sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
+
++ mutex_unlock(&s->efr_lock);
++
+ /* Get baud rate generator configuration */
+ baud = uart_get_baud_rate(port, termios, old,
+ port->uartclk / 16 / 4 / 0xffff,
+@@ -1187,6 +1214,7 @@ static int sc16is7xx_probe(struct device
+ s->regmap = regmap;
+ s->devtype = devtype;
+ dev_set_drvdata(dev, s);
++ mutex_init(&s->efr_lock);
+
+ kthread_init_worker(&s->kworker);
+ kthread_init_work(&s->irq_work, sc16is7xx_ist);
--- /dev/null
+From 4db271be1ee58a646878a17aa1007533897c095b Mon Sep 17 00:00:00 2001
+From: Ben Wolsieffer <benwolsieffer@gmail.com>
+Date: Sun, 9 Dec 2018 16:46:00 -0500
+Subject: [PATCH 296/725] dtoverlays: fe-pi-audio: fix sgtl5000 compatible
+ string
+
+The compatible string was set to "fepi,sgtl5000", which worked for some
+reason in 4.14, but does not work in 4.19, presumably due to some
+change in the kernel matching logic. The correct string is
+"fsl,sgtl5000".
+
+Signed-off-by: Ben Wolsieffer <benwolsieffer@gmail.com>
+---
+ arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
+@@ -39,7 +39,7 @@
+
+ sgtl5000@0a {
+ #sound-dai-cells = <0>;
+- compatible = "fepi,sgtl5000";
++ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ clocks = <&sgtl5000_mclk>;
+ micbias-resistor-k-ohms = <2>;
+++ /dev/null
-From 66d4a3ecb20bca91bc9e209cc8dc7730dffb0b57 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 10 Jan 2019 18:48:54 +0000
-Subject: [PATCH 296/703] firmware: raspberrypi: Report the fw git hash during
- probe
-
-The firmware can now report the git hash from which it was built
-via the mailbox, so report it during probe.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/firmware/raspberrypi.c | 17 +++++++++++++++++
- include/soc/bcm2835/raspberrypi-firmware.h | 1 +
- 2 files changed, 18 insertions(+)
-
---- a/drivers/firmware/raspberrypi.c
-+++ b/drivers/firmware/raspberrypi.c
-@@ -263,6 +263,22 @@ rpi_firmware_print_firmware_revision(str
- }
-
- static void
-+rpi_firmware_print_firmware_hash(struct rpi_firmware *fw)
-+{
-+ u32 hash[5];
-+ int ret = rpi_firmware_property(fw,
-+ RPI_FIRMWARE_GET_FIRMWARE_HASH,
-+ hash, sizeof(hash));
-+
-+ if (ret)
-+ return;
-+
-+ dev_info(fw->cl.dev,
-+ "Firmware hash is %08x%08x%08x%08x%08x\n",
-+ hash[0], hash[1], hash[2], hash[3], hash[4]);
-+}
-+
-+static void
- rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
- {
- u32 packet;
-@@ -308,6 +324,7 @@ static int rpi_firmware_probe(struct pla
- g_pdev = pdev;
-
- rpi_firmware_print_firmware_revision(fw);
-+ rpi_firmware_print_firmware_hash(fw);
- rpi_register_hwmon_driver(dev, fw);
-
- return 0;
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -42,6 +42,7 @@ enum rpi_firmware_property_tag {
- RPI_FIRMWARE_PROPERTY_END = 0,
- RPI_FIRMWARE_GET_FIRMWARE_REVISION = 0x00000001,
- RPI_FIRMWARE_GET_FIRMWARE_VARIANT = 0x00000002,
-+ RPI_FIRMWARE_GET_FIRMWARE_HASH = 0x00000003,
-
- RPI_FIRMWARE_SET_CURSOR_INFO = 0x00008010,
- RPI_FIRMWARE_SET_CURSOR_STATE = 0x00008011,
+++ /dev/null
-From e09f9e3d46d8a393d54e414a718d232d13169a29 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 15 Jan 2019 09:56:41 +0000
-Subject: [PATCH 297/703] arm64: dts: broadcom: Enable fixups for overlays
-
-See: https://github.com/raspberrypi/linux/pull/2733
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm64/boot/dts/broadcom/Makefile | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/arch/arm64/boot/dts/broadcom/Makefile
-+++ b/arch/arm64/boot/dts/broadcom/Makefile
-@@ -9,3 +9,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rp
-
- subdir-y += northstar2
- subdir-y += stingray
-+
-+# Enable fixups to support overlays on BCM2835 platforms
-+ifeq ($(CONFIG_ARCH_BCM2835),y)
-+ DTC_FLAGS ?= -@
-+endif
--- /dev/null
+From 4e11b14186707dfb88be344f227737eaf8adc608 Mon Sep 17 00:00:00 2001
+From: Ezekiel Bethel <zek@9net.org>
+Date: Wed, 12 Dec 2018 19:11:13 +0000
+Subject: [PATCH 297/725] bcm2835_smi: re-add dereference to fix DMA transfers
+
+---
+ drivers/misc/bcm2835_smi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/misc/bcm2835_smi.c
++++ b/drivers/misc/bcm2835_smi.c
+@@ -879,7 +879,7 @@ static int bcm2835_smi_probe(struct plat
+ goto err;
+ }
+ addr = of_get_address(node, 0, NULL, NULL);
+- inst->smi_regs_busaddr = be32_to_cpu(addr);
++ inst->smi_regs_busaddr = be32_to_cpu(*addr);
+
+ err = bcm2835_smi_dma_setup(inst);
+ if (err)
--- /dev/null
+From a1bcab7b0deee8cf7d7bec2707cb50c269070d41 Mon Sep 17 00:00:00 2001
+From: Joshua Emele <jemele@acm.org>
+Date: Wed, 7 Nov 2018 16:07:40 -0800
+Subject: [PATCH 298/725] lan78xx: Debounce link events to minimize poll storm
+
+The bInterval is set to 4 (i.e. 8 microframes => 1ms) and the only bit
+that the driver pays attention to is "link was reset". If there's a
+flapping status bit in that endpoint data, (such as if PHY negotiation
+needs a few tries to get a stable link) then polling at a slower rate
+would act as a de-bounce.
+
+See: https://github.com/raspberrypi/linux/issues/2447
+---
+ drivers/net/usb/lan78xx.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -448,6 +448,11 @@ static bool enable_tso;
+ module_param(enable_tso, bool, 0644);
+ MODULE_PARM_DESC(enable_tso, "Enables TCP segmentation offload");
+
++#define INT_URB_MICROFRAMES_PER_MS 8
++static int int_urb_interval_ms = 8;
++module_param(int_urb_interval_ms, int, 0);
++MODULE_PARM_DESC(int_urb_interval_ms, "Override usb interrupt urb interval");
++
+ static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data)
+ {
+ u32 *buf = kmalloc(sizeof(u32), GFP_KERNEL);
+@@ -3816,7 +3821,12 @@ static int lan78xx_probe(struct usb_inte
+ dev->pipe_intr = usb_rcvintpipe(dev->udev,
+ dev->ep_intr->desc.bEndpointAddress &
+ USB_ENDPOINT_NUMBER_MASK);
+- period = dev->ep_intr->desc.bInterval;
++ if (int_urb_interval_ms <= 0)
++ period = dev->ep_intr->desc.bInterval;
++ else
++ period = int_urb_interval_ms * INT_URB_MICROFRAMES_PER_MS;
++
++ netif_notice(dev, probe, netdev, "int urb period %d\n", period);
+
+ maxp = usb_maxpacket(dev->udev, dev->pipe_intr, 0);
+ buf = kmalloc(maxp, GFP_KERNEL);
+++ /dev/null
-From 2328af8468b09a20258488b2126449aa8539ee5a Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 18 May 2018 10:26:59 +0100
-Subject: [PATCH 298/703] sc16is7xx: Fix for "Unexpected interrupt: 8"
-
-The SC16IS752 has an Enhanced Feature Register which is aliased at the
-same address as the Interrupt Identification Register; accessing it
-requires that a magic value is written to the Line Configuration
-Register. If an interrupt is raised while the EFR is mapped in then
-the ISR won't be able to access the IIR, leading to the "Unexpected
-interrupt" error messages.
-
-Avoid the problem by claiming a mutex around accesses to the EFR
-register, also claiming the mutex in the interrupt handler work
-item (this is equivalent to disabling interrupts to interlock against
-a non-threaded interrupt handler).
-
-See: https://github.com/raspberrypi/linux/issues/2529
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/tty/serial/sc16is7xx.c | 28 ++++++++++++++++++++++++++++
- 1 file changed, 28 insertions(+)
-
---- a/drivers/tty/serial/sc16is7xx.c
-+++ b/drivers/tty/serial/sc16is7xx.c
-@@ -328,6 +328,7 @@ struct sc16is7xx_port {
- struct kthread_worker kworker;
- struct task_struct *kworker_task;
- struct kthread_work irq_work;
-+ struct mutex efr_lock;
- struct sc16is7xx_one p[0];
- };
-
-@@ -499,6 +500,21 @@ static int sc16is7xx_set_baud(struct uar
- div /= 4;
- }
-
-+ /* In an amazing feat of design, the Enhanced Features Register shares
-+ * the address of the Interrupt Identification Register, and is
-+ * switched in by writing a magic value (0xbf) to the Line Control
-+ * Register. Any interrupt firing during this time will see the EFR
-+ * where it expects the IIR to be, leading to "Unexpected interrupt"
-+ * messages.
-+ *
-+ * Prevent this possibility by claiming a mutex while accessing the
-+ * EFR, and claiming the same mutex from within the interrupt handler.
-+ * This is similar to disabling the interrupt, but that doesn't work
-+ * because the bulk of the interrupt processing is run as a workqueue
-+ * job in thread context.
-+ */
-+ mutex_lock(&s->efr_lock);
-+
- lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG);
-
- /* Open the LCR divisors for configuration */
-@@ -514,6 +530,8 @@ static int sc16is7xx_set_baud(struct uar
- /* Put LCR back to the normal mode */
- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
-
-+ mutex_unlock(&s->efr_lock);
-+
- sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
- SC16IS7XX_MCR_CLKSEL_BIT,
- prescaler);
-@@ -698,6 +716,8 @@ static void sc16is7xx_ist(struct kthread
- {
- struct sc16is7xx_port *s = to_sc16is7xx_port(ws, irq_work);
-
-+ mutex_lock(&s->efr_lock);
-+
- while (1) {
- bool keep_polling = false;
- int i;
-@@ -707,6 +727,8 @@ static void sc16is7xx_ist(struct kthread
- if (!keep_polling)
- break;
- }
-+
-+ mutex_unlock(&s->efr_lock);
- }
-
- static irqreturn_t sc16is7xx_irq(int irq, void *dev_id)
-@@ -901,6 +923,9 @@ static void sc16is7xx_set_termios(struct
- if (!(termios->c_cflag & CREAD))
- port->ignore_status_mask |= SC16IS7XX_LSR_BRK_ERROR_MASK;
-
-+ /* As above, claim the mutex while accessing the EFR. */
-+ mutex_lock(&s->efr_lock);
-+
- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
- SC16IS7XX_LCR_CONF_MODE_B);
-
-@@ -922,6 +947,8 @@ static void sc16is7xx_set_termios(struct
- /* Update LCR register */
- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
-
-+ mutex_unlock(&s->efr_lock);
-+
- /* Get baud rate generator configuration */
- baud = uart_get_baud_rate(port, termios, old,
- port->uartclk / 16 / 4 / 0xffff,
-@@ -1187,6 +1214,7 @@ static int sc16is7xx_probe(struct device
- s->regmap = regmap;
- s->devtype = devtype;
- dev_set_drvdata(dev, s);
-+ mutex_init(&s->efr_lock);
-
- kthread_init_worker(&s->kworker);
- kthread_init_work(&s->irq_work, sc16is7xx_ist);
--- /dev/null
+From 93952495f34e255ab4a3ce4631edd1520200f586 Mon Sep 17 00:00:00 2001
+From: b-ak <anur.bhargav@gmail.com>
+Date: Thu, 3 Jan 2019 00:01:08 +0530
+Subject: [PATCH 299/725] ASoC: Add support for AudioSense-Pi add-on soundcard
+
+AudioSense-Pi is a RPi HAT based on a TI's TLV320AIC32x4 stereo codec
+
+This hardware provides multiple audio I/O capabilities to the RPi.
+The codec connects to the RPi's SoC through the I2S Bus.
+
+The following devices can be connected through a 3.5mm jack
+ 1. Line-In: Plain old audio in from mobile phones, PCs, etc.,
+ 2. Mic-In: Connect a microphone
+ 3. Line-Out: Connect the output to a speaker
+ 4. Headphones: Connect a Headphone w or w/o microphones
+
+Multiple Inputs:
+ It supports the following combinations
+ 1. Two stereo Line-Inputs and a microphone
+ 2. One stereo Line-Input and two microphones
+ 3. Two stereo Line-Inputs, a microphone and
+ one mono line-input (with h/w hack)
+ 4. One stereo Line-Input, two microphones and
+ one mono line-input (with h/w hack)
+
+Multiple Outputs:
+ Audio output can be routed to the headphones or
+ speakers (with additional hardware)
+
+Signed-off-by: b-ak <anur.bhargav@gmail.com>
+---
+ sound/soc/bcm/Kconfig | 7 +
+ sound/soc/bcm/Makefile | 2 +
+ sound/soc/bcm/audiosense-pi.c | 246 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 255 insertions(+)
+ create mode 100644 sound/soc/bcm/audiosense-pi.c
+
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -137,6 +137,13 @@ config SND_AUDIOINJECTOR_OCTO_SOUNDCARD
+ help
+ Say Y or M if you want to add support for audioinjector.net octo add on
+
++config SND_AUDIOSENSE_PI
++ tristate "Support for AudioSense Add-On Soundcard"
++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++ select SND_SOC_TLV320AIC32X4_I2C
++ help
++ Say Y or M if you want to add support for tlv320aic32x4 add-on
++
+ config SND_DIGIDAC1_SOUNDCARD
+ tristate "Support for Red Rocks Audio DigiDAC1"
+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -20,6 +20,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o
+ snd-soc-iqaudio-dac-objs := iqaudio-dac.o
+ snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
+ snd-soc-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o
++snd-soc-audiosense-pi-objs := audiosense-pi.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
+@@ -41,6 +42,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO)
+ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.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_AUDIOSENSE_PI) += snd-soc-audiosense-pi.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
+--- /dev/null
++++ b/sound/soc/bcm/audiosense-pi.c
+@@ -0,0 +1,246 @@
++/*
++ * ASoC Driver for AudioSense add on soundcard
++ * Author:
++ * Bhargav A K <anur.bhargav@gmail.com>
++ * Copyright 2017
++ *
++ * 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 <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/clk.h>
++#include <linux/i2c.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/jack.h>
++#include <sound/control.h>
++
++#include <sound/tlv320aic32x4.h>
++#include "../codecs/tlv320aic32x4.h"
++
++#define AIC32X4_SYSCLK_XTAL 0x00
++
++/*
++ * Setup Codec Sample Rates and Channels
++ * Supported Rates:
++ * 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000,
++ */
++static const unsigned int audiosense_pi_rate[] = {
++ 48000,
++};
++
++static struct snd_pcm_hw_constraint_list audiosense_constraints_rates = {
++ .list = audiosense_pi_rate,
++ .count = ARRAY_SIZE(audiosense_pi_rate),
++};
++
++static const unsigned int audiosense_pi_channels[] = {
++ 2,
++};
++
++static struct snd_pcm_hw_constraint_list audiosense_constraints_ch = {
++ .count = ARRAY_SIZE(audiosense_pi_channels),
++ .list = audiosense_pi_channels,
++ .mask = 0,
++};
++
++/* Setup DAPM widgets and paths */
++static const struct snd_soc_dapm_widget audiosense_pi_dapm_widgets[] = {
++ SND_SOC_DAPM_HP("Headphone Jack", NULL),
++ SND_SOC_DAPM_LINE("Line Out", NULL),
++ SND_SOC_DAPM_LINE("Line In", NULL),
++ SND_SOC_DAPM_INPUT("CM_L"),
++ SND_SOC_DAPM_INPUT("CM_R"),
++};
++
++static const struct snd_soc_dapm_route audiosense_pi_audio_map[] = {
++ /* Line Inputs are connected to
++ * (IN1_L | IN1_R)
++ * (IN2_L | IN2_R)
++ * (IN3_L | IN3_R)
++ */
++ {"IN1_L", NULL, "Line In"},
++ {"IN1_R", NULL, "Line In"},
++ {"IN2_L", NULL, "Line In"},
++ {"IN2_R", NULL, "Line In"},
++ {"IN3_L", NULL, "Line In"},
++ {"IN3_R", NULL, "Line In"},
++
++ /* Mic is connected to IN2_L and IN2_R */
++ {"Left ADC", NULL, "Mic Bias"},
++ {"Right ADC", NULL, "Mic Bias"},
++
++ /* Headphone connected to HPL, HPR */
++ {"Headphone Jack", NULL, "HPL"},
++ {"Headphone Jack", NULL, "HPR"},
++
++ /* Speakers connected to LOL and LOR */
++ {"Line Out", NULL, "LOL"},
++ {"Line Out", NULL, "LOR"},
++};
++
++static int audiosense_pi_card_init(struct snd_soc_pcm_runtime *rtd)
++{
++ /* TODO: init of the codec specific dapm data, ignore suspend/resume */
++ struct snd_soc_component *component = rtd->codec_dai->component;
++
++ snd_soc_component_update_bits(component, AIC32X4_MICBIAS, 0x78,
++ AIC32X4_MICBIAS_LDOIN |
++ AIC32X4_MICBIAS_2075V);
++ snd_soc_component_update_bits(component, AIC32X4_PWRCFG, 0x08,
++ AIC32X4_AVDDWEAKDISABLE);
++ snd_soc_component_update_bits(component, AIC32X4_LDOCTL, 0x01,
++ AIC32X4_LDOCTLEN);
++
++ return 0;
++}
++
++static int audiosense_pi_card_hw_params(
++ struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ int ret = 0;
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_dai *codec_dai = rtd->codec_dai;
++
++ /* Set the codec system clock, there is a 12 MHz XTAL on the board */
++ ret = snd_soc_dai_set_sysclk(codec_dai, AIC32X4_SYSCLK_XTAL,
++ 12000000, SND_SOC_CLOCK_IN);
++ if (ret) {
++ dev_err(rtd->card->dev,
++ "could not set codec driver clock params\n");
++ return ret;
++ }
++ return 0;
++}
++
++static int audiosense_pi_card_startup(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++
++ /*
++ * Set codec to 48Khz Sampling, Stereo I/O and 16 bit audio
++ */
++ runtime->hw.channels_max = 2;
++ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
++ &audiosense_constraints_ch);
++
++ runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
++ snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
++
++
++ snd_pcm_hw_constraint_list(substream->runtime, 0,
++ SNDRV_PCM_HW_PARAM_RATE,
++ &audiosense_constraints_rates);
++ return 0;
++}
++
++static struct snd_soc_ops audiosense_pi_card_ops = {
++ .startup = audiosense_pi_card_startup,
++ .hw_params = audiosense_pi_card_hw_params,
++};
++
++static struct snd_soc_dai_link audiosense_pi_card_dai[] = {
++ {
++ .name = "TLV320AIC3204 Audio",
++ .stream_name = "TLV320AIC3204 Hifi Audio",
++ .cpu_dai_name = "bcm2708-i2s.0",
++ .codec_dai_name = "tlv320aic32x4-hifi",
++ .platform_name = "bcm2708-i2s.0",
++ .codec_name = "tlv320aic32x4.1-0018",
++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBM_CFM,
++ .ops = &audiosense_pi_card_ops,
++ .init = audiosense_pi_card_init,
++ },
++};
++
++static struct snd_soc_card audiosense_pi_card = {
++ .name = "audiosense-pi",
++ .driver_name = "audiosense-pi",
++ .dai_link = audiosense_pi_card_dai,
++ .owner = THIS_MODULE,
++ .num_links = ARRAY_SIZE(audiosense_pi_card_dai),
++ .dapm_widgets = audiosense_pi_dapm_widgets,
++ .num_dapm_widgets = ARRAY_SIZE(audiosense_pi_dapm_widgets),
++ .dapm_routes = audiosense_pi_audio_map,
++ .num_dapm_routes = ARRAY_SIZE(audiosense_pi_audio_map),
++};
++
++static int audiosense_pi_card_probe(struct platform_device *pdev)
++{
++ int ret = 0;
++ struct snd_soc_card *card = &audiosense_pi_card;
++ struct snd_soc_dai_link *dai = &audiosense_pi_card_dai[0];
++ struct device_node *i2s_node = pdev->dev.of_node;
++
++ card->dev = &pdev->dev;
++
++ if (!dai) {
++ dev_err(&pdev->dev, "DAI not found. Missing or Invalid\n");
++ return -EINVAL;
++ }
++
++ i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0);
++ if (!i2s_node) {
++ dev_err(&pdev->dev,
++ "Property 'i2s-controller' 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);
++
++ 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 audiosense_pi_card_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 audiosense_pi_card_of_match[] = {
++ { .compatible = "as,audiosense-pi", },
++ {},
++};
++MODULE_DEVICE_TABLE(of, audiosense_pi_card_of_match);
++
++static struct platform_driver audiosense_pi_card_driver = {
++ .driver = {
++ .name = "audiosense-snd-card",
++ .owner = THIS_MODULE,
++ .of_match_table = audiosense_pi_card_of_match,
++ },
++ .probe = audiosense_pi_card_probe,
++ .remove = audiosense_pi_card_remove,
++};
++
++module_platform_driver(audiosense_pi_card_driver);
++
++MODULE_AUTHOR("Bhargav AK <anur.bhargav@gmail.com>");
++MODULE_DESCRIPTION("ASoC Driver for TLV320AIC3204 Audio");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:audiosense-pi");
++
+++ /dev/null
-From 4e7767bc63406cf8a4cb2cdcf86c2592c07440f6 Mon Sep 17 00:00:00 2001
-From: Ben Wolsieffer <benwolsieffer@gmail.com>
-Date: Sun, 9 Dec 2018 16:46:00 -0500
-Subject: [PATCH 299/703] dtoverlays: fe-pi-audio: fix sgtl5000 compatible
- string
-
-The compatible string was set to "fepi,sgtl5000", which worked for some
-reason in 4.14, but does not work in 4.19, presumably due to some
-change in the kernel matching logic. The correct string is
-"fsl,sgtl5000".
-
-Signed-off-by: Ben Wolsieffer <benwolsieffer@gmail.com>
----
- arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
-@@ -39,7 +39,7 @@
-
- sgtl5000@0a {
- #sound-dai-cells = <0>;
-- compatible = "fepi,sgtl5000";
-+ compatible = "fsl,sgtl5000";
- reg = <0x0a>;
- clocks = <&sgtl5000_mclk>;
- micbias-resistor-k-ohms = <2>;
--- /dev/null
+From 92192e0410d1c38596ca387c1680ff37847dcdc3 Mon Sep 17 00:00:00 2001
+From: b-ak <anur.bhargav@gmail.com>
+Date: Thu, 3 Jan 2019 00:29:14 +0530
+Subject: [PATCH 300/725] BCM270X: Adding device tree support for AudioSense-Pi
+ add-on soundcard
+
+Device tree overlay for AudioSense-Pi card.
+
+To enable support for the hardware add the following
+line to the RPi /boot/config.txt:
+
+ dtoverlay=audiosense-pi
+
+More documentation @ arch/arm/boot/dts/overlays/README
+
+Signed-off-by: b-ak <anur.bhargav@gmail.com>
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 8 ++
+ .../dts/overlays/audiosense-pi-overlay.dts | 82 +++++++++++++++++++
+ 3 files changed, 91 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -20,6 +20,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ audioinjector-addons.dtbo \
+ audioinjector-ultra.dtbo \
+ audioinjector-wm8731-audio.dtbo \
++ audiosense-pi.dtbo \
+ audremap.dtbo \
+ balena-fin.dtbo \
+ bmp085_i2c-sensor.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -453,6 +453,14 @@ Load: dtoverlay=audioinjector-wm8731-a
+ Params: <None>
+
+
++Name: audiosense-pi
++Info: Configures the audiosense-pi add on soundcard
++ For more information refer to
++ https://gitlab.com/kakar0t/audiosense-pi
++Load: dtoverlay=audiosense-pi
++Params: <None>
++
++
+ Name: audremap
+ Info: Switches PWM sound output to pins 12 (Right) & 13 (Left)
+ Load: dtoverlay=audremap,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
+@@ -0,0 +1,82 @@
++// Definitions for audiosense add on soundcard
++/dts-v1/;
++/plugin/;
++#include <dt-bindings/pinctrl/bcm2835.h>
++#include <dt-bindings/gpio/gpio.h>
++
++/ {
++ compatible = "brcm,bcm2837", "brcm,bcm2836", "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++
++ fragment@0 {
++ target = <&i2s>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@1 {
++ target-path = "/";
++ __overlay__ {
++ codec_reg_1v8: codec-reg-1v8 {
++ compatible = "regulator-fixed";
++ regulator-name = "tlv320aic3204_1v8";
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <1800000>;
++ regulator-always-on;
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&gpio>;
++ __overlay__ {
++ codec_rst: codec-rst {
++ brcm,pins = <26>;
++ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++ };
++ };
++ };
++
++ fragment@3 {
++ target = <&i2c1>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ /* audio external oscillator */
++ codec_osc: codec_osc {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <12000000>; /* 12 MHz */
++ };
++
++ codec: tlv320aic32x4@18 {
++ #sound-dai-cells = <0>;
++ compatible = "ti,tlv320aic32x4";
++ reg = <0x18>;
++
++ clocks = <&codec_osc>;
++ clock-names = "mclk";
++
++ iov-supply = <&vdd_3v3_reg>;
++ ldoin-supply = <&vdd_3v3_reg>;
++
++ gpio-controller;
++ #gpio-cells = <2>;
++ reset-gpios = <&gpio 26 GPIO_ACTIVE_HIGH>;
++
++ status = "okay";
++ };
++ };
++ };
++
++ fragment@4 {
++ target = <&sound>;
++ __overlay__ {
++ compatible = "as,audiosense-pi";
++ i2s-controller = <&i2s>;
++ status = "okay";
++ };
++ };
++};
+++ /dev/null
-From 6edc58ab2e73fc38ba380de57e8a416cfaaba512 Mon Sep 17 00:00:00 2001
-From: Ezekiel Bethel <zek@9net.org>
-Date: Wed, 12 Dec 2018 19:11:13 +0000
-Subject: [PATCH 300/703] bcm2835_smi: re-add dereference to fix DMA transfers
-
----
- drivers/misc/bcm2835_smi.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/misc/bcm2835_smi.c
-+++ b/drivers/misc/bcm2835_smi.c
-@@ -879,7 +879,7 @@ static int bcm2835_smi_probe(struct plat
- goto err;
- }
- addr = of_get_address(node, 0, NULL, NULL);
-- inst->smi_regs_busaddr = be32_to_cpu(addr);
-+ inst->smi_regs_busaddr = be32_to_cpu(*addr);
-
- err = bcm2835_smi_dma_setup(inst);
- if (err)
--- /dev/null
+From f737d88ed6add8f6197bf1a26ace908b13a19d96 Mon Sep 17 00:00:00 2001
+From: b-ak <anur.bhargav@gmail.com>
+Date: Fri, 4 Jan 2019 00:12:51 +0530
+Subject: [PATCH 301/725] configs: Add CONFIG_SND_AUDIOSENSE_PI=m
+
+AudioSense-Pi add on soundcard configuration definitions
+
+Signed-off-by: b-ak <anur.bhargav@gmail.com>
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ 3 files changed, 3 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -918,6 +918,7 @@ CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
+ CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
+ CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m
+ CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m
++CONFIG_SND_AUDIOSENSE_PI=m
+ CONFIG_SND_DIGIDAC1_SOUNDCARD=m
+ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m
+ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -911,6 +911,7 @@ CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
+ CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
+ CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m
+ CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m
++CONFIG_SND_AUDIOSENSE_PI=m
+ CONFIG_SND_DIGIDAC1_SOUNDCARD=m
+ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m
+ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -800,6 +800,7 @@ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
+ CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
+ CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m
++CONFIG_SND_AUDIOSENSE_PI=m
+ CONFIG_SND_DIGIDAC1_SOUNDCARD=m
+ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m
+ CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m
+++ /dev/null
-From 643d2b5c276c5d2967b857256a983ae7860607a1 Mon Sep 17 00:00:00 2001
-From: Joshua Emele <jemele@acm.org>
-Date: Wed, 7 Nov 2018 16:07:40 -0800
-Subject: [PATCH 301/703] lan78xx: Debounce link events to minimize poll storm
-
-The bInterval is set to 4 (i.e. 8 microframes => 1ms) and the only bit
-that the driver pays attention to is "link was reset". If there's a
-flapping status bit in that endpoint data, (such as if PHY negotiation
-needs a few tries to get a stable link) then polling at a slower rate
-would act as a de-bounce.
-
-See: https://github.com/raspberrypi/linux/issues/2447
----
- drivers/net/usb/lan78xx.c | 12 +++++++++++-
- 1 file changed, 11 insertions(+), 1 deletion(-)
-
---- a/drivers/net/usb/lan78xx.c
-+++ b/drivers/net/usb/lan78xx.c
-@@ -448,6 +448,11 @@ static bool enable_tso;
- module_param(enable_tso, bool, 0644);
- MODULE_PARM_DESC(enable_tso, "Enables TCP segmentation offload");
-
-+#define INT_URB_MICROFRAMES_PER_MS 8
-+static int int_urb_interval_ms = 8;
-+module_param(int_urb_interval_ms, int, 0);
-+MODULE_PARM_DESC(int_urb_interval_ms, "Override usb interrupt urb interval");
-+
- static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data)
- {
- u32 *buf = kmalloc(sizeof(u32), GFP_KERNEL);
-@@ -3816,7 +3821,12 @@ static int lan78xx_probe(struct usb_inte
- dev->pipe_intr = usb_rcvintpipe(dev->udev,
- dev->ep_intr->desc.bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK);
-- period = dev->ep_intr->desc.bInterval;
-+ if (int_urb_interval_ms <= 0)
-+ period = dev->ep_intr->desc.bInterval;
-+ else
-+ period = int_urb_interval_ms * INT_URB_MICROFRAMES_PER_MS;
-+
-+ netif_notice(dev, probe, netdev, "int urb period %d\n", period);
-
- maxp = usb_maxpacket(dev->udev, dev->pipe_intr, 0);
- buf = kmalloc(maxp, GFP_KERNEL);
+++ /dev/null
-From 99324d4b613b3ee56683446abbd96623c6a64887 Mon Sep 17 00:00:00 2001
-From: b-ak <anur.bhargav@gmail.com>
-Date: Thu, 3 Jan 2019 00:01:08 +0530
-Subject: [PATCH 302/703] ASoC: Add support for AudioSense-Pi add-on soundcard
-
-AudioSense-Pi is a RPi HAT based on a TI's TLV320AIC32x4 stereo codec
-
-This hardware provides multiple audio I/O capabilities to the RPi.
-The codec connects to the RPi's SoC through the I2S Bus.
-
-The following devices can be connected through a 3.5mm jack
- 1. Line-In: Plain old audio in from mobile phones, PCs, etc.,
- 2. Mic-In: Connect a microphone
- 3. Line-Out: Connect the output to a speaker
- 4. Headphones: Connect a Headphone w or w/o microphones
-
-Multiple Inputs:
- It supports the following combinations
- 1. Two stereo Line-Inputs and a microphone
- 2. One stereo Line-Input and two microphones
- 3. Two stereo Line-Inputs, a microphone and
- one mono line-input (with h/w hack)
- 4. One stereo Line-Input, two microphones and
- one mono line-input (with h/w hack)
-
-Multiple Outputs:
- Audio output can be routed to the headphones or
- speakers (with additional hardware)
-
-Signed-off-by: b-ak <anur.bhargav@gmail.com>
----
- sound/soc/bcm/Kconfig | 7 +
- sound/soc/bcm/Makefile | 2 +
- sound/soc/bcm/audiosense-pi.c | 246 ++++++++++++++++++++++++++++++++++
- 3 files changed, 255 insertions(+)
- create mode 100644 sound/soc/bcm/audiosense-pi.c
-
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -137,6 +137,13 @@ config SND_AUDIOINJECTOR_OCTO_SOUNDCARD
- help
- Say Y or M if you want to add support for audioinjector.net octo add on
-
-+config SND_AUDIOSENSE_PI
-+ tristate "Support for AudioSense Add-On Soundcard"
-+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+ select SND_SOC_TLV320AIC32X4_I2C
-+ help
-+ Say Y or M if you want to add support for tlv320aic32x4 add-on
-+
- config SND_DIGIDAC1_SOUNDCARD
- tristate "Support for Red Rocks Audio DigiDAC1"
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -20,6 +20,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o
- snd-soc-iqaudio-dac-objs := iqaudio-dac.o
- snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
- snd-soc-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o
-+snd-soc-audiosense-pi-objs := audiosense-pi.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
-@@ -41,6 +42,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO)
- obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.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_AUDIOSENSE_PI) += snd-soc-audiosense-pi.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
---- /dev/null
-+++ b/sound/soc/bcm/audiosense-pi.c
-@@ -0,0 +1,246 @@
-+/*
-+ * ASoC Driver for AudioSense add on soundcard
-+ * Author:
-+ * Bhargav A K <anur.bhargav@gmail.com>
-+ * Copyright 2017
-+ *
-+ * 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 <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/clk.h>
-+#include <linux/i2c.h>
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/jack.h>
-+#include <sound/control.h>
-+
-+#include <sound/tlv320aic32x4.h>
-+#include "../codecs/tlv320aic32x4.h"
-+
-+#define AIC32X4_SYSCLK_XTAL 0x00
-+
-+/*
-+ * Setup Codec Sample Rates and Channels
-+ * Supported Rates:
-+ * 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000,
-+ */
-+static const unsigned int audiosense_pi_rate[] = {
-+ 48000,
-+};
-+
-+static struct snd_pcm_hw_constraint_list audiosense_constraints_rates = {
-+ .list = audiosense_pi_rate,
-+ .count = ARRAY_SIZE(audiosense_pi_rate),
-+};
-+
-+static const unsigned int audiosense_pi_channels[] = {
-+ 2,
-+};
-+
-+static struct snd_pcm_hw_constraint_list audiosense_constraints_ch = {
-+ .count = ARRAY_SIZE(audiosense_pi_channels),
-+ .list = audiosense_pi_channels,
-+ .mask = 0,
-+};
-+
-+/* Setup DAPM widgets and paths */
-+static const struct snd_soc_dapm_widget audiosense_pi_dapm_widgets[] = {
-+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
-+ SND_SOC_DAPM_LINE("Line Out", NULL),
-+ SND_SOC_DAPM_LINE("Line In", NULL),
-+ SND_SOC_DAPM_INPUT("CM_L"),
-+ SND_SOC_DAPM_INPUT("CM_R"),
-+};
-+
-+static const struct snd_soc_dapm_route audiosense_pi_audio_map[] = {
-+ /* Line Inputs are connected to
-+ * (IN1_L | IN1_R)
-+ * (IN2_L | IN2_R)
-+ * (IN3_L | IN3_R)
-+ */
-+ {"IN1_L", NULL, "Line In"},
-+ {"IN1_R", NULL, "Line In"},
-+ {"IN2_L", NULL, "Line In"},
-+ {"IN2_R", NULL, "Line In"},
-+ {"IN3_L", NULL, "Line In"},
-+ {"IN3_R", NULL, "Line In"},
-+
-+ /* Mic is connected to IN2_L and IN2_R */
-+ {"Left ADC", NULL, "Mic Bias"},
-+ {"Right ADC", NULL, "Mic Bias"},
-+
-+ /* Headphone connected to HPL, HPR */
-+ {"Headphone Jack", NULL, "HPL"},
-+ {"Headphone Jack", NULL, "HPR"},
-+
-+ /* Speakers connected to LOL and LOR */
-+ {"Line Out", NULL, "LOL"},
-+ {"Line Out", NULL, "LOR"},
-+};
-+
-+static int audiosense_pi_card_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+ /* TODO: init of the codec specific dapm data, ignore suspend/resume */
-+ struct snd_soc_component *component = rtd->codec_dai->component;
-+
-+ snd_soc_component_update_bits(component, AIC32X4_MICBIAS, 0x78,
-+ AIC32X4_MICBIAS_LDOIN |
-+ AIC32X4_MICBIAS_2075V);
-+ snd_soc_component_update_bits(component, AIC32X4_PWRCFG, 0x08,
-+ AIC32X4_AVDDWEAKDISABLE);
-+ snd_soc_component_update_bits(component, AIC32X4_LDOCTL, 0x01,
-+ AIC32X4_LDOCTLEN);
-+
-+ return 0;
-+}
-+
-+static int audiosense_pi_card_hw_params(
-+ struct snd_pcm_substream *substream,
-+ struct snd_pcm_hw_params *params)
-+{
-+ int ret = 0;
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
-+
-+ /* Set the codec system clock, there is a 12 MHz XTAL on the board */
-+ ret = snd_soc_dai_set_sysclk(codec_dai, AIC32X4_SYSCLK_XTAL,
-+ 12000000, SND_SOC_CLOCK_IN);
-+ if (ret) {
-+ dev_err(rtd->card->dev,
-+ "could not set codec driver clock params\n");
-+ return ret;
-+ }
-+ return 0;
-+}
-+
-+static int audiosense_pi_card_startup(struct snd_pcm_substream *substream)
-+{
-+ struct snd_pcm_runtime *runtime = substream->runtime;
-+
-+ /*
-+ * Set codec to 48Khz Sampling, Stereo I/O and 16 bit audio
-+ */
-+ runtime->hw.channels_max = 2;
-+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
-+ &audiosense_constraints_ch);
-+
-+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
-+ snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
-+
-+
-+ snd_pcm_hw_constraint_list(substream->runtime, 0,
-+ SNDRV_PCM_HW_PARAM_RATE,
-+ &audiosense_constraints_rates);
-+ return 0;
-+}
-+
-+static struct snd_soc_ops audiosense_pi_card_ops = {
-+ .startup = audiosense_pi_card_startup,
-+ .hw_params = audiosense_pi_card_hw_params,
-+};
-+
-+static struct snd_soc_dai_link audiosense_pi_card_dai[] = {
-+ {
-+ .name = "TLV320AIC3204 Audio",
-+ .stream_name = "TLV320AIC3204 Hifi Audio",
-+ .cpu_dai_name = "bcm2708-i2s.0",
-+ .codec_dai_name = "tlv320aic32x4-hifi",
-+ .platform_name = "bcm2708-i2s.0",
-+ .codec_name = "tlv320aic32x4.1-0018",
-+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-+ SND_SOC_DAIFMT_CBM_CFM,
-+ .ops = &audiosense_pi_card_ops,
-+ .init = audiosense_pi_card_init,
-+ },
-+};
-+
-+static struct snd_soc_card audiosense_pi_card = {
-+ .name = "audiosense-pi",
-+ .driver_name = "audiosense-pi",
-+ .dai_link = audiosense_pi_card_dai,
-+ .owner = THIS_MODULE,
-+ .num_links = ARRAY_SIZE(audiosense_pi_card_dai),
-+ .dapm_widgets = audiosense_pi_dapm_widgets,
-+ .num_dapm_widgets = ARRAY_SIZE(audiosense_pi_dapm_widgets),
-+ .dapm_routes = audiosense_pi_audio_map,
-+ .num_dapm_routes = ARRAY_SIZE(audiosense_pi_audio_map),
-+};
-+
-+static int audiosense_pi_card_probe(struct platform_device *pdev)
-+{
-+ int ret = 0;
-+ struct snd_soc_card *card = &audiosense_pi_card;
-+ struct snd_soc_dai_link *dai = &audiosense_pi_card_dai[0];
-+ struct device_node *i2s_node = pdev->dev.of_node;
-+
-+ card->dev = &pdev->dev;
-+
-+ if (!dai) {
-+ dev_err(&pdev->dev, "DAI not found. Missing or Invalid\n");
-+ return -EINVAL;
-+ }
-+
-+ i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0);
-+ if (!i2s_node) {
-+ dev_err(&pdev->dev,
-+ "Property 'i2s-controller' 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);
-+
-+ 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 audiosense_pi_card_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 audiosense_pi_card_of_match[] = {
-+ { .compatible = "as,audiosense-pi", },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, audiosense_pi_card_of_match);
-+
-+static struct platform_driver audiosense_pi_card_driver = {
-+ .driver = {
-+ .name = "audiosense-snd-card",
-+ .owner = THIS_MODULE,
-+ .of_match_table = audiosense_pi_card_of_match,
-+ },
-+ .probe = audiosense_pi_card_probe,
-+ .remove = audiosense_pi_card_remove,
-+};
-+
-+module_platform_driver(audiosense_pi_card_driver);
-+
-+MODULE_AUTHOR("Bhargav AK <anur.bhargav@gmail.com>");
-+MODULE_DESCRIPTION("ASoC Driver for TLV320AIC3204 Audio");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:audiosense-pi");
-+
--- /dev/null
+From 3e9204fb393ff539359a1dd1da228d2817116f3a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 14 Jan 2019 08:50:55 +0000
+Subject: [PATCH 302/725] configs: Add CONFIG_USB_TMC=m
+
+Enable the Test & Measurement Class USB driver module.
+
+See: https://github.com/raspberrypi/linux/firmware/issues/929
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/configs/bcm2709_defconfig | 2 +-
+ arch/arm/configs/bcmrpi_defconfig | 2 +-
+ arch/arm64/configs/bcmrpi3_defconfig | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -1002,6 +1002,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+ CONFIG_USB_MON=m
+ CONFIG_USB_DWCOTG=y
+ CONFIG_USB_PRINTER=m
++CONFIG_USB_TMC=m
+ CONFIG_USB_STORAGE=y
+ CONFIG_USB_STORAGE_REALTEK=m
+ CONFIG_USB_STORAGE_DATAFAB=m
+@@ -1301,7 +1302,6 @@ CONFIG_CIFS=m
+ CONFIG_CIFS_WEAK_PW_HASH=y
+ CONFIG_CIFS_UPCALL=y
+ CONFIG_CIFS_XATTR=y
+-CONFIG_CIFS_POSIX=y
+ CONFIG_CIFS_ACL=y
+ CONFIG_CIFS_DFS_UPCALL=y
+ CONFIG_CIFS_FSCACHE=y
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -995,6 +995,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+ CONFIG_USB_MON=m
+ CONFIG_USB_DWCOTG=y
+ CONFIG_USB_PRINTER=m
++CONFIG_USB_TMC=m
+ CONFIG_USB_STORAGE=y
+ CONFIG_USB_STORAGE_REALTEK=m
+ CONFIG_USB_STORAGE_DATAFAB=m
+@@ -1294,7 +1295,6 @@ CONFIG_CIFS=m
+ CONFIG_CIFS_WEAK_PW_HASH=y
+ CONFIG_CIFS_UPCALL=y
+ CONFIG_CIFS_XATTR=y
+-CONFIG_CIFS_POSIX=y
+ CONFIG_CIFS_ACL=y
+ CONFIG_CIFS_DFS_UPCALL=y
+ CONFIG_CIFS_FSCACHE=y
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -871,6 +871,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+ CONFIG_USB_MON=m
+ CONFIG_USB_DWCOTG=y
+ CONFIG_USB_PRINTER=m
++CONFIG_USB_TMC=m
+ CONFIG_USB_STORAGE=y
+ CONFIG_USB_STORAGE_REALTEK=m
+ CONFIG_USB_STORAGE_DATAFAB=m
+@@ -1145,7 +1146,6 @@ CONFIG_CIFS=m
+ CONFIG_CIFS_WEAK_PW_HASH=y
+ CONFIG_CIFS_UPCALL=y
+ CONFIG_CIFS_XATTR=y
+-CONFIG_CIFS_POSIX=y
+ CONFIG_CIFS_ACL=y
+ CONFIG_CIFS_DFS_UPCALL=y
+ CONFIG_CIFS_FSCACHE=y
+++ /dev/null
-From 43f0013d9050a0011c05370c9b6123eb059f235b Mon Sep 17 00:00:00 2001
-From: b-ak <anur.bhargav@gmail.com>
-Date: Thu, 3 Jan 2019 00:29:14 +0530
-Subject: [PATCH 303/703] BCM270X: Adding device tree support for AudioSense-Pi
- add-on soundcard
-
-Device tree overlay for AudioSense-Pi card.
-
-To enable support for the hardware add the following
-line to the RPi /boot/config.txt:
-
- dtoverlay=audiosense-pi
-
-More documentation @ arch/arm/boot/dts/overlays/README
-
-Signed-off-by: b-ak <anur.bhargav@gmail.com>
----
- arch/arm/boot/dts/overlays/Makefile | 1 +
- arch/arm/boot/dts/overlays/README | 8 ++
- .../dts/overlays/audiosense-pi-overlay.dts | 82 +++++++++++++++++++
- 3 files changed, 91 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -20,6 +20,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- audioinjector-addons.dtbo \
- audioinjector-ultra.dtbo \
- audioinjector-wm8731-audio.dtbo \
-+ audiosense-pi.dtbo \
- audremap.dtbo \
- balena-fin.dtbo \
- bmp085_i2c-sensor.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -453,6 +453,14 @@ Load: dtoverlay=audioinjector-wm8731-a
- Params: <None>
-
-
-+Name: audiosense-pi
-+Info: Configures the audiosense-pi add on soundcard
-+ For more information refer to
-+ https://gitlab.com/kakar0t/audiosense-pi
-+Load: dtoverlay=audiosense-pi
-+Params: <None>
-+
-+
- Name: audremap
- Info: Switches PWM sound output to pins 12 (Right) & 13 (Left)
- Load: dtoverlay=audremap,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
-@@ -0,0 +1,82 @@
-+// Definitions for audiosense add on soundcard
-+/dts-v1/;
-+/plugin/;
-+#include <dt-bindings/pinctrl/bcm2835.h>
-+#include <dt-bindings/gpio/gpio.h>
-+
-+/ {
-+ compatible = "brcm,bcm2837", "brcm,bcm2836", "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+
-+ fragment@0 {
-+ target = <&i2s>;
-+ __overlay__ {
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@1 {
-+ target-path = "/";
-+ __overlay__ {
-+ codec_reg_1v8: codec-reg-1v8 {
-+ compatible = "regulator-fixed";
-+ regulator-name = "tlv320aic3204_1v8";
-+ regulator-min-microvolt = <1800000>;
-+ regulator-max-microvolt = <1800000>;
-+ regulator-always-on;
-+ };
-+ };
-+ };
-+
-+ fragment@2 {
-+ target = <&gpio>;
-+ __overlay__ {
-+ codec_rst: codec-rst {
-+ brcm,pins = <26>;
-+ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
-+ };
-+ };
-+ };
-+
-+ fragment@3 {
-+ target = <&i2c1>;
-+ __overlay__ {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "okay";
-+
-+ /* audio external oscillator */
-+ codec_osc: codec_osc {
-+ compatible = "fixed-clock";
-+ #clock-cells = <0>;
-+ clock-frequency = <12000000>; /* 12 MHz */
-+ };
-+
-+ codec: tlv320aic32x4@18 {
-+ #sound-dai-cells = <0>;
-+ compatible = "ti,tlv320aic32x4";
-+ reg = <0x18>;
-+
-+ clocks = <&codec_osc>;
-+ clock-names = "mclk";
-+
-+ iov-supply = <&vdd_3v3_reg>;
-+ ldoin-supply = <&vdd_3v3_reg>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+ reset-gpios = <&gpio 26 GPIO_ACTIVE_HIGH>;
-+
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ fragment@4 {
-+ target = <&sound>;
-+ __overlay__ {
-+ compatible = "as,audiosense-pi";
-+ i2s-controller = <&i2s>;
-+ status = "okay";
-+ };
-+ };
-+};
--- /dev/null
+From d92f631ece6e1fca95462d8b0ffd3fee97be257a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 10 Jan 2019 15:27:56 +0000
+Subject: [PATCH 303/725] overlays: sdio: Add enhanced 1-bit support
+
+"dtoverlay=sdio,bus_width=1,gpios_22_25" is equivalent to the sdio-1bit
+overlay, which is now deprecated.
+
+"dtoverlay=sdio,bus_width=1,gpios_34_37" enables 1-bit mode on GPIOs 34-37.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README | 24 +++++++++++----------
+ arch/arm/boot/dts/overlays/sdio-overlay.dts | 20 ++++++++++++++++-
+ 2 files changed, 32 insertions(+), 12 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -479,8 +479,7 @@ Params: <None>
+
+ Name: bmp085_i2c-sensor
+ Info: This overlay is now deprecated - see i2c-sensor
+-Load: dtoverlay=bmp085_i2c-sensor
+-Params: <None>
++Load: <Deprecated>
+
+
+ Name: dht11
+@@ -1737,7 +1736,8 @@ Params: overclock_50 Clock (i
+
+ Name: sdio
+ Info: Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock,
+- and enables SDIO via GPIOs 22-27.
++ and enables SDIO via GPIOs 22-27. An example of use in 1-bit mode is
++ "dtoverlay=sdio,bus_width=1,gpios_22_25"
+ Load: dtoverlay=sdio,<param>=<val>
+ Params: sdio_overclock SDIO Clock (in MHz) to use when the MMC
+ framework requests 50MHz
+@@ -1747,16 +1747,18 @@ Params: sdio_overclock SDIO Clo
+
+ bus_width Set the SDIO host bus width (default 4 bits)
+
++ gpios_22_25 Select GPIOs 22-25 for 1-bit mode. Must be used
++ with bus_width=1. This replaces the sdio-1bit
++ overlay, which is now deprecated.
+
+-Name: sdio-1bit
+-Info: Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock,
+- and enables 1-bit SDIO via GPIOs 22-25.
+-Load: dtoverlay=sdio-1bit,<param>=<val>
+-Params: sdio_overclock SDIO Clock (in MHz) to use when the MMC
+- framework requests 50MHz
++ gpios_34_37 Select GPIOs 34-37 for 1-bit mode. Must be used
++ with bus_width=1.
+
+- poll_once Disable SDIO-device polling every second
+- (default on: polling once at boot-time)
++
++Name: sdio-1bit
++Info: This overlay is now deprecated. Use
++ "dtoverlay=sdio,bus_width=1,gpios_22_25" instead.
++Load: <Deprecated>
+
+
+ Name: sdtweak
+--- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
+@@ -32,7 +32,7 @@
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio_ovl_pins>;
+ non-removable;
+- bus-width = <1>;
++ bus-width = <4>;
+ };
+ };
+ };
+@@ -49,6 +49,22 @@
+ };
+
+ fragment@3 {
++ target = <&sdio_ovl_pins>;
++ __dormant__ {
++ brcm,pins = <22 23 24 25>;
++ brcm,pull = <0 2 2 2>;
++ };
++ };
++
++ fragment@4 {
++ target = <&sdio_ovl_pins>;
++ __dormant__ {
++ brcm,pins = <34 35 36 37>;
++ brcm,pull = <0 2 2 2>;
++ };
++ };
++
++ fragment@6 {
+ target-path = "/aliases";
+ __overlay__ {
+ mmc1 = "/soc/sdio@7e300000";
+@@ -59,5 +75,7 @@
+ poll_once = <&sdio_ovl>,"non-removable?";
+ bus_width = <&sdio_ovl>,"bus-width:0";
+ sdio_overclock = <&sdio_ovl>,"brcm,overclock-50:0";
++ gpios_22_25 = <0>,"=3";
++ gpios_34_37 = <0>,"=4";
+ };
+ };
+++ /dev/null
-From 3e7e88225ea313a8a79773383b4004b714b07bc2 Mon Sep 17 00:00:00 2001
-From: b-ak <anur.bhargav@gmail.com>
-Date: Fri, 4 Jan 2019 00:12:51 +0530
-Subject: [PATCH 304/703] configs: Add CONFIG_SND_AUDIOSENSE_PI=m
-
-AudioSense-Pi add on soundcard configuration definitions
-
-Signed-off-by: b-ak <anur.bhargav@gmail.com>
----
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- 3 files changed, 3 insertions(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -918,6 +918,7 @@ CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
- CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
- CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m
- CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m
-+CONFIG_SND_AUDIOSENSE_PI=m
- CONFIG_SND_DIGIDAC1_SOUNDCARD=m
- CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m
- CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -911,6 +911,7 @@ CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
- CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
- CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m
- CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m
-+CONFIG_SND_AUDIOSENSE_PI=m
- CONFIG_SND_DIGIDAC1_SOUNDCARD=m
- CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m
- CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -800,6 +800,7 @@ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
- CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
- CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m
-+CONFIG_SND_AUDIOSENSE_PI=m
- CONFIG_SND_DIGIDAC1_SOUNDCARD=m
- CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m
- CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m
--- /dev/null
+From 0384e9ec7b5a3d8e6e2162ce8adf019d0f5c94cf Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Wed, 16 Jan 2019 10:17:52 +0000
+Subject: [PATCH 304/725] dwc_otg: fix bug with port_addr assignment for
+ single-TT hubs
+
+See https://github.com/raspberrypi/linux/issues/2734
+
+The "Hub Port" field in the split transaction packet was always set
+to 1 for single-TT hubs. The majority of single-TT hub products
+apparently ignore this field and broadcast to all downstream enabled
+ports, which masked the issue. A subset of hub devices apparently
+need the port number to be exact or split transactions will fail.
+---
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+@@ -232,7 +232,7 @@ static int _hub_info(dwc_otg_hcd_t * hcd
+ else
+ *hub_addr = urb->dev->tt->hub->devnum;
+ }
+- *port_addr = urb->dev->tt->multi ? urb->dev->ttport : 1;
++ *port_addr = urb->dev->ttport;
+ } else {
+ *hub_addr = 0;
+ *port_addr = urb->dev->ttport;
+++ /dev/null
-From 5822a95be9ca76e9f467392f9010fd10635f86cd Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 14 Jan 2019 08:50:55 +0000
-Subject: [PATCH 305/703] configs: Add CONFIG_USB_TMC=m
-
-Enable the Test & Measurement Class USB driver module.
-
-See: https://github.com/raspberrypi/linux/firmware/issues/929
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/configs/bcm2709_defconfig | 2 +-
- arch/arm/configs/bcmrpi_defconfig | 2 +-
- arch/arm64/configs/bcmrpi3_defconfig | 2 +-
- 3 files changed, 3 insertions(+), 3 deletions(-)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -1002,6 +1002,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
- CONFIG_USB_MON=m
- CONFIG_USB_DWCOTG=y
- CONFIG_USB_PRINTER=m
-+CONFIG_USB_TMC=m
- CONFIG_USB_STORAGE=y
- CONFIG_USB_STORAGE_REALTEK=m
- CONFIG_USB_STORAGE_DATAFAB=m
-@@ -1301,7 +1302,6 @@ CONFIG_CIFS=m
- CONFIG_CIFS_WEAK_PW_HASH=y
- CONFIG_CIFS_UPCALL=y
- CONFIG_CIFS_XATTR=y
--CONFIG_CIFS_POSIX=y
- CONFIG_CIFS_ACL=y
- CONFIG_CIFS_DFS_UPCALL=y
- CONFIG_CIFS_FSCACHE=y
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -995,6 +995,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
- CONFIG_USB_MON=m
- CONFIG_USB_DWCOTG=y
- CONFIG_USB_PRINTER=m
-+CONFIG_USB_TMC=m
- CONFIG_USB_STORAGE=y
- CONFIG_USB_STORAGE_REALTEK=m
- CONFIG_USB_STORAGE_DATAFAB=m
-@@ -1294,7 +1295,6 @@ CONFIG_CIFS=m
- CONFIG_CIFS_WEAK_PW_HASH=y
- CONFIG_CIFS_UPCALL=y
- CONFIG_CIFS_XATTR=y
--CONFIG_CIFS_POSIX=y
- CONFIG_CIFS_ACL=y
- CONFIG_CIFS_DFS_UPCALL=y
- CONFIG_CIFS_FSCACHE=y
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -871,6 +871,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
- CONFIG_USB_MON=m
- CONFIG_USB_DWCOTG=y
- CONFIG_USB_PRINTER=m
-+CONFIG_USB_TMC=m
- CONFIG_USB_STORAGE=y
- CONFIG_USB_STORAGE_REALTEK=m
- CONFIG_USB_STORAGE_DATAFAB=m
-@@ -1145,7 +1146,6 @@ CONFIG_CIFS=m
- CONFIG_CIFS_WEAK_PW_HASH=y
- CONFIG_CIFS_UPCALL=y
- CONFIG_CIFS_XATTR=y
--CONFIG_CIFS_POSIX=y
- CONFIG_CIFS_ACL=y
- CONFIG_CIFS_DFS_UPCALL=y
- CONFIG_CIFS_FSCACHE=y
--- /dev/null
+From e775807c64a610be5f2fcb82e152109d9b9d30f8 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 16 Jan 2019 21:26:13 +0000
+Subject: [PATCH 305/725] configs: Add CONFIG_USB_UAS=m
+
+Enable support for USB-attached-SCSI devicess.
+
+See: https://github.com/raspberrypi/linux/issues/2813
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ 3 files changed, 3 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -1017,6 +1017,7 @@ CONFIG_USB_STORAGE_ONETOUCH=m
+ CONFIG_USB_STORAGE_KARMA=m
+ CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+ CONFIG_USB_STORAGE_ENE_UB6250=m
++CONFIG_USB_UAS=m
+ CONFIG_USB_MDC800=m
+ CONFIG_USB_MICROTEK=m
+ CONFIG_USBIP_CORE=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -1010,6 +1010,7 @@ CONFIG_USB_STORAGE_ONETOUCH=m
+ CONFIG_USB_STORAGE_KARMA=m
+ CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+ CONFIG_USB_STORAGE_ENE_UB6250=m
++CONFIG_USB_UAS=m
+ CONFIG_USB_MDC800=m
+ CONFIG_USB_MICROTEK=m
+ CONFIG_USBIP_CORE=m
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -886,6 +886,7 @@ CONFIG_USB_STORAGE_ONETOUCH=m
+ CONFIG_USB_STORAGE_KARMA=m
+ CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+ CONFIG_USB_STORAGE_ENE_UB6250=m
++CONFIG_USB_UAS=m
+ CONFIG_USB_MDC800=m
+ CONFIG_USB_MICROTEK=m
+ CONFIG_USBIP_CORE=m
--- /dev/null
+From a4bda3453c292c7b75ca0e3163daa7879d5fa952 Mon Sep 17 00:00:00 2001
+From: HiFiBerry <info@hifiberry.com>
+Date: Mon, 8 Oct 2018 18:10:12 +0200
+Subject: [PATCH 306/725] Added driver for the HiFiBerry DAC+ ADC (#2694)
+
+Signed-off-by: Daniel Matuschek <daniel@hifiberry.com>
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 21 +
+ .../overlays/hifiberry-dacplusadc-overlay.dts | 71 +++
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ sound/soc/bcm/Kconfig | 8 +
+ sound/soc/bcm/Makefile | 2 +
+ sound/soc/bcm/hifiberry_dacplusadc.c | 407 ++++++++++++++++++
+ 8 files changed, 512 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
+ create mode 100644 sound/soc/bcm/hifiberry_dacplusadc.c
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -49,6 +49,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ hifiberry-amp.dtbo \
+ hifiberry-dac.dtbo \
+ hifiberry-dacplus.dtbo \
++ hifiberry-dacplusadc.dtbo \
+ hifiberry-digi.dtbo \
+ hifiberry-digi-pro.dtbo \
+ hy28a.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -779,6 +779,27 @@ Params: 24db_digital_gain Allow ga
+ master for bit clock and frame clock.
+
+
++Name: hifiberry-dacplusadc
++Info: Configures the HifiBerry DAC+ADC audio card
++Load: dtoverlay=hifiberry-dacplusadc,<param>=<val>
++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!)
++ slave Force DAC+ Pro into slave mode, using Pi as
++ master for bit clock and frame clock.
++
++
+ Name: hifiberry-digi
+ Info: Configures the HifiBerry Digi and Digi+ audio card
+ Load: dtoverlay=hifiberry-digi
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
+@@ -0,0 +1,71 @@
++// Definitions for HiFiBerry DAC+ADC
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "brcm,bcm2708";
++
++ fragment@0 {
++ target-path = "/clocks";
++ __overlay__ {
++ dacpro_osc: dacpro_osc {
++ compatible = "hifiberry,dacpro-clk";
++ #clock-cells = <0>;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&i2s>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&i2c1>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ pcm_codec: pcm5122@4d {
++ #sound-dai-cells = <0>;
++ 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";
++ };
++ };
++ };
++
++ fragment@3 {
++ target-path = "/";
++ __overlay__ {
++ dmic {
++ #sound-dai-cells = <0>;
++ compatible = "dmic-codec";
++ num-channels = <2>;
++ status = "okay";
++ };
++ };
++ };
++
++ fragment@4 {
++ target = <&sound>;
++ hifiberry_dacplusadc: __overlay__ {
++ compatible = "hifiberry,hifiberry-dacplusadc";
++ i2s-controller = <&i2s>;
++ status = "okay";
++ };
++ };
++
++ __overrides__ {
++ 24db_digital_gain =
++ <&hifiberry_dacplusadc>,"hifiberry,24db_digital_gain?";
++ slave = <&hifiberry_dacplusadc>,"hifiberry-dacplusadc,slave?";
++ };
++};
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -905,6 +905,7 @@ CONFIG_SND_BCM2835_SOC_I2S=m
+ CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
+ CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -898,6 +898,7 @@ CONFIG_SND_BCM2835_SOC_I2S=m
+ CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
+ CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -46,6 +46,14 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
+ help
+ Say Y or M if you want to add support for HifiBerry DAC+.
+
++config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC
++ tristate "Support for HifiBerry DAC+ADC"
++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++ select SND_SOC_PCM512x_I2C
++ select SND_SOC_DMIC
++ help
++ Say Y or M if you want to add support for HifiBerry DAC+ADC.
++
+ config SND_BCM2708_SOC_HIFIBERRY_DIGI
+ tristate "Support for HifiBerry Digi"
+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -14,6 +14,7 @@ snd-soc-googlevoicehat-codec-objs := goo
+ # BCM2708 Machine Support
+ snd-soc-3dlab-nano-player-objs := 3dlab-nano-player.o
+ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
++snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
+ snd-soc-justboom-dac-objs := justboom-dac.o
+ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
+ snd-soc-rpi-proto-objs := rpi-proto.o
+@@ -36,6 +37,7 @@ snd-soc-rpi-wm8804-soundcard-objs := rpi
+ obj-$(CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER) += snd-soc-3dlab-nano-player.o
+ obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD) += snd-soc-googlevoicehat-codec.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
+ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
+--- /dev/null
++++ b/sound/soc/bcm/hifiberry_dacplusadc.c
+@@ -0,0 +1,407 @@
++/*
++ * ASoC Driver for HiFiBerry DAC+ / DAC Pro with ADC
++ *
++ * Author: Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
++ * Copyright 2014-2015
++ * based on code by Florian Meier <florian.meier@koalo.de>
++ * ADC added by Joerg Schambacher <joscha@schambacher.com>
++ * Copyright 2018
++ *
++ * 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 <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/kernel.h>
++#include <linux/clk.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/jack.h>
++
++#include "../codecs/pcm512x.h"
++
++#define HIFIBERRY_DACPRO_NOCLOCK 0
++#define HIFIBERRY_DACPRO_CLK44EN 1
++#define HIFIBERRY_DACPRO_CLK48EN 2
++
++struct platform_device *dmic_codec_dev;
++
++struct pcm512x_priv {
++ struct regmap *regmap;
++ struct clk *sclk;
++};
++
++/* Clock rate of CLK44EN attached to GPIO6 pin */
++#define CLK_44EN_RATE 22579200UL
++/* Clock rate of CLK48EN attached to GPIO3 pin */
++#define CLK_48EN_RATE 24576000UL
++
++static bool slave;
++static bool snd_rpi_hifiberry_is_dacpro;
++static bool digital_gain_0db_limit = true;
++
++static void snd_rpi_hifiberry_dacplusadc_select_clk(struct snd_soc_component *component,
++ int clk_id)
++{
++ switch (clk_id) {
++ case HIFIBERRY_DACPRO_NOCLOCK:
++ snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
++ break;
++ case HIFIBERRY_DACPRO_CLK44EN:
++ snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
++ break;
++ case HIFIBERRY_DACPRO_CLK48EN:
++ snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
++ break;
++ }
++}
++
++static void snd_rpi_hifiberry_dacplusadc_clk_gpio(struct snd_soc_component *component)
++{
++ snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
++ snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
++ snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
++}
++
++static bool snd_rpi_hifiberry_dacplusadc_is_sclk(struct snd_soc_component *component)
++{
++ unsigned int sck;
++
++ snd_soc_component_read(component, PCM512x_RATE_DET_4, &sck);
++ return (!(sck & 0x40));
++}
++
++static bool snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(
++ struct snd_soc_component *component)
++{
++ msleep(2);
++ return snd_rpi_hifiberry_dacplusadc_is_sclk(component);
++}
++
++static bool snd_rpi_hifiberry_dacplusadc_is_pro_card(struct snd_soc_component *component)
++{
++ bool isClk44EN, isClk48En, isNoClk;
++
++ snd_rpi_hifiberry_dacplusadc_clk_gpio(component);
++
++ snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
++ isClk44EN = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
++
++ snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
++ isNoClk = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
++
++ snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
++ isClk48En = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
++
++ return (isClk44EN && isClk48En && !isNoClk);
++}
++
++static int snd_rpi_hifiberry_dacplusadc_clk_for_rate(int sample_rate)
++{
++ int type;
++
++ switch (sample_rate) {
++ case 11025:
++ case 22050:
++ case 44100:
++ case 88200:
++ case 176400:
++ case 352800:
++ type = HIFIBERRY_DACPRO_CLK44EN;
++ break;
++ default:
++ type = HIFIBERRY_DACPRO_CLK48EN;
++ break;
++ }
++ return type;
++}
++
++static void snd_rpi_hifiberry_dacplusadc_set_sclk(struct snd_soc_component *component,
++ int sample_rate)
++{
++ struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
++
++ if (!IS_ERR(pcm512x->sclk)) {
++ int ctype;
++
++ ctype = snd_rpi_hifiberry_dacplusadc_clk_for_rate(sample_rate);
++ clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN)
++ ? CLK_44EN_RATE : CLK_48EN_RATE);
++ snd_rpi_hifiberry_dacplusadc_select_clk(component, ctype);
++ }
++}
++
++static int snd_rpi_hifiberry_dacplusadc_init(struct snd_soc_pcm_runtime *rtd)
++{
++ struct snd_soc_component *component = rtd->codec_dai->component;
++ struct pcm512x_priv *priv;
++
++ if (slave)
++ snd_rpi_hifiberry_is_dacpro = false;
++ else
++ snd_rpi_hifiberry_is_dacpro =
++ snd_rpi_hifiberry_dacplusadc_is_pro_card(component);
++
++ if (snd_rpi_hifiberry_is_dacpro) {
++ struct snd_soc_dai_link *dai = rtd->dai_link;
++
++ dai->name = "HiFiBerry ADCDAC+ Pro";
++ dai->stream_name = "HiFiBerry ADCDAC+ Pro HiFi";
++ dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
++ | SND_SOC_DAIFMT_CBM_CFM;
++
++ snd_soc_component_update_bits(component, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
++ snd_soc_component_update_bits(component, PCM512x_MASTER_MODE, 0x03, 0x03);
++ snd_soc_component_update_bits(component, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
++ } else {
++ priv = snd_soc_component_get_drvdata(component);
++ priv->sclk = ERR_PTR(-ENOENT);
++ }
++
++ snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x08, 0x08);
++ snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
++ snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
++
++ if (digital_gain_0db_limit) {
++ int ret;
++ struct snd_soc_card *card = rtd->card;
++
++ ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
++ if (ret < 0)
++ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
++ }
++
++ return 0;
++}
++
++static int snd_rpi_hifiberry_dacplusadc_update_rate_den(
++ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_component *component = rtd->codec_dai->component;
++ struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
++ struct snd_ratnum *rats_no_pll;
++ unsigned int num = 0, den = 0;
++ int err;
++
++ rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
++ if (!rats_no_pll)
++ return -ENOMEM;
++
++ rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
++ rats_no_pll->den_min = 1;
++ rats_no_pll->den_max = 128;
++ rats_no_pll->den_step = 1;
++
++ err = snd_interval_ratnum(hw_param_interval(params,
++ SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
++ if (err >= 0 && den) {
++ params->rate_num = num;
++ params->rate_den = den;
++ }
++
++ devm_kfree(rtd->dev, rats_no_pll);
++ return 0;
++}
++
++static int snd_rpi_hifiberry_dacplusadc_hw_params(
++ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
++{
++ int ret = 0;
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ int channels = params_channels(params);
++ int width = 32;
++
++ if (snd_rpi_hifiberry_is_dacpro) {
++ struct snd_soc_component *component = rtd->codec_dai->component;
++
++ width = snd_pcm_format_physical_width(params_format(params));
++
++ snd_rpi_hifiberry_dacplusadc_set_sclk(component,
++ params_rate(params));
++
++ ret = snd_rpi_hifiberry_dacplusadc_update_rate_den(
++ substream, params);
++ }
++
++ ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x03, 0x03,
++ channels, width);
++ if (ret)
++ return ret;
++ ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0x03, 0x03,
++ channels, width);
++ return ret;
++}
++
++static int hifiberry_dacplusadc_LED_cnt;
++
++static int snd_rpi_hifiberry_dacplusadc_startup(
++ struct snd_pcm_substream *substream)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_component *component = rtd->codec_dai->component;
++
++ snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1,
++ 0x08, 0x08);
++ hifiberry_dacplusadc_LED_cnt++;
++ return 0;
++}
++
++static void snd_rpi_hifiberry_dacplusadc_shutdown(
++ struct snd_pcm_substream *substream)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_component *component = rtd->codec_dai->component;
++
++ hifiberry_dacplusadc_LED_cnt--;
++ if (!hifiberry_dacplusadc_LED_cnt)
++ snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1,
++ 0x08, 0x00);
++}
++
++/* machine stream operations */
++static struct snd_soc_ops snd_rpi_hifiberry_dacplusadc_ops = {
++ .hw_params = snd_rpi_hifiberry_dacplusadc_hw_params,
++ .startup = snd_rpi_hifiberry_dacplusadc_startup,
++ .shutdown = snd_rpi_hifiberry_dacplusadc_shutdown,
++};
++
++static struct snd_soc_dai_link_component snd_rpi_hifiberry_dacplusadc_codecs[] = {
++ {
++ .name = "pcm512x.1-004d",
++ .dai_name = "pcm512x-hifi",
++ },
++ {
++ .name = "dmic-codec",
++ .dai_name = "dmic-hifi",
++ },
++};
++
++static struct snd_soc_dai_link snd_rpi_hifiberry_dacplusadc_dai[] = {
++{
++ .name = "HiFiBerry DAC+ADC",
++ .stream_name = "HiFiBerry DAC+ADC HiFi",
++ .cpu_dai_name = "bcm2708-i2s.0",
++ .platform_name = "bcm2708-i2s.0",
++ .codecs = snd_rpi_hifiberry_dacplusadc_codecs,
++ .num_codecs = 2,
++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBS_CFS,
++ .ops = &snd_rpi_hifiberry_dacplusadc_ops,
++ .init = snd_rpi_hifiberry_dacplusadc_init,
++},
++};
++
++/* audio machine driver */
++static struct snd_soc_card snd_rpi_hifiberry_dacplusadc = {
++ .name = "snd_rpi_hifiberry_dacplusadc",
++ .driver_name = "HifiberryDacpAdc",
++ .owner = THIS_MODULE,
++ .dai_link = snd_rpi_hifiberry_dacplusadc_dai,
++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplusadc_dai),
++};
++
++
++static int snd_rpi_hifiberry_dacplusadc_probe(struct platform_device *pdev)
++{
++ int ret = 0;
++
++ snd_rpi_hifiberry_dacplusadc.dev = &pdev->dev;
++ if (pdev->dev.of_node) {
++ struct device_node *i2s_node;
++ struct snd_soc_dai_link *dai;
++
++ dai = &snd_rpi_hifiberry_dacplusadc_dai[0];
++ i2s_node = of_parse_phandle(pdev->dev.of_node,
++ "i2s-controller", 0);
++ if (i2s_node) {
++ dai->cpu_of_node = i2s_node;
++ dai->platform_of_node = i2s_node;
++ dai->cpu_dai_name = NULL;
++ dai->platform_name = NULL;
++ }
++ dai = &snd_rpi_hifiberry_dacplusadc_dai[1];
++ i2s_node = of_parse_phandle(pdev->dev.of_node, "dmic", 0);
++ if (i2s_node) {
++ dai->cpu_of_node = i2s_node;
++ dai->platform_of_node = i2s_node;
++ }
++
++ }
++ digital_gain_0db_limit = !of_property_read_bool(
++ pdev->dev.of_node, "hifiberry,24db_digital_gain");
++ slave = of_property_read_bool(pdev->dev.of_node,
++ "hifiberry-dacplusadc,slave");
++
++ ret = devm_snd_soc_register_card(&pdev->dev,
++ &snd_rpi_hifiberry_dacplusadc);
++ if (ret && ret != -EPROBE_DEFER)
++ dev_err(&pdev->dev,
++ "snd_soc_register_card() failed: %d\n", ret);
++
++ return ret;
++}
++
++static const struct of_device_id snd_rpi_hifiberry_dacplusadc_of_match[] = {
++ { .compatible = "hifiberry,hifiberry-dacplusadc", },
++ {},
++};
++
++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplusadc_of_match);
++
++static struct platform_driver snd_rpi_hifiberry_dacplusadc_driver = {
++ .driver = {
++ .name = "snd-rpi-hifiberry-dacplusadc",
++ .owner = THIS_MODULE,
++ .of_match_table = snd_rpi_hifiberry_dacplusadc_of_match,
++ },
++ .probe = snd_rpi_hifiberry_dacplusadc_probe,
++};
++
++static int __init hifiberry_dacplusadc_init(void)
++{
++ int ret;
++
++ dmic_codec_dev = platform_device_register_simple("dmic-codec", -1, NULL,
++ 0);
++ if (IS_ERR(dmic_codec_dev)) {
++ pr_err("%s: dmic-codec device registration failed\n", __func__);
++ return PTR_ERR(dmic_codec_dev);
++ }
++
++ ret = platform_driver_register(&snd_rpi_hifiberry_dacplusadc_driver);
++ if (ret) {
++ pr_err("%s: platform driver registration failed\n", __func__);
++ platform_device_unregister(dmic_codec_dev);
++ }
++
++ return ret;
++}
++module_init(hifiberry_dacplusadc_init);
++
++static void __exit hifiberry_dacplusadc_exit(void)
++{
++ platform_driver_unregister(&snd_rpi_hifiberry_dacplusadc_driver);
++ platform_device_unregister(dmic_codec_dev);
++}
++module_exit(hifiberry_dacplusadc_exit);
++
++MODULE_AUTHOR("Joerg Schambacher <joscha@schambacher.com>");
++MODULE_AUTHOR("Daniel Matuschek <daniel@hifiberry.com>");
++MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ADC");
++MODULE_LICENSE("GPL v2");
+++ /dev/null
-From 510aeba93fa3dde1e2890d49409bd1be2d72f3fe Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 10 Jan 2019 15:27:56 +0000
-Subject: [PATCH 306/703] overlays: sdio: Add enhanced 1-bit support
-
-"dtoverlay=sdio,bus_width=1,gpios_22_25" is equivalent to the sdio-1bit
-overlay, which is now deprecated.
-
-"dtoverlay=sdio,bus_width=1,gpios_34_37" enables 1-bit mode on GPIOs 34-37.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README | 24 +++++++++++----------
- arch/arm/boot/dts/overlays/sdio-overlay.dts | 20 ++++++++++++++++-
- 2 files changed, 32 insertions(+), 12 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -479,8 +479,7 @@ Params: <None>
-
- Name: bmp085_i2c-sensor
- Info: This overlay is now deprecated - see i2c-sensor
--Load: dtoverlay=bmp085_i2c-sensor
--Params: <None>
-+Load: <Deprecated>
-
-
- Name: dht11
-@@ -1737,7 +1736,8 @@ Params: overclock_50 Clock (i
-
- Name: sdio
- Info: Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock,
-- and enables SDIO via GPIOs 22-27.
-+ and enables SDIO via GPIOs 22-27. An example of use in 1-bit mode is
-+ "dtoverlay=sdio,bus_width=1,gpios_22_25"
- Load: dtoverlay=sdio,<param>=<val>
- Params: sdio_overclock SDIO Clock (in MHz) to use when the MMC
- framework requests 50MHz
-@@ -1747,16 +1747,18 @@ Params: sdio_overclock SDIO Clo
-
- bus_width Set the SDIO host bus width (default 4 bits)
-
-+ gpios_22_25 Select GPIOs 22-25 for 1-bit mode. Must be used
-+ with bus_width=1. This replaces the sdio-1bit
-+ overlay, which is now deprecated.
-
--Name: sdio-1bit
--Info: Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock,
-- and enables 1-bit SDIO via GPIOs 22-25.
--Load: dtoverlay=sdio-1bit,<param>=<val>
--Params: sdio_overclock SDIO Clock (in MHz) to use when the MMC
-- framework requests 50MHz
-+ gpios_34_37 Select GPIOs 34-37 for 1-bit mode. Must be used
-+ with bus_width=1.
-
-- poll_once Disable SDIO-device polling every second
-- (default on: polling once at boot-time)
-+
-+Name: sdio-1bit
-+Info: This overlay is now deprecated. Use
-+ "dtoverlay=sdio,bus_width=1,gpios_22_25" instead.
-+Load: <Deprecated>
-
-
- Name: sdtweak
---- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
-@@ -32,7 +32,7 @@
- pinctrl-names = "default";
- pinctrl-0 = <&sdio_ovl_pins>;
- non-removable;
-- bus-width = <1>;
-+ bus-width = <4>;
- };
- };
- };
-@@ -49,6 +49,22 @@
- };
-
- fragment@3 {
-+ target = <&sdio_ovl_pins>;
-+ __dormant__ {
-+ brcm,pins = <22 23 24 25>;
-+ brcm,pull = <0 2 2 2>;
-+ };
-+ };
-+
-+ fragment@4 {
-+ target = <&sdio_ovl_pins>;
-+ __dormant__ {
-+ brcm,pins = <34 35 36 37>;
-+ brcm,pull = <0 2 2 2>;
-+ };
-+ };
-+
-+ fragment@6 {
- target-path = "/aliases";
- __overlay__ {
- mmc1 = "/soc/sdio@7e300000";
-@@ -59,5 +75,7 @@
- poll_once = <&sdio_ovl>,"non-removable?";
- bus_width = <&sdio_ovl>,"bus-width:0";
- sdio_overclock = <&sdio_ovl>,"brcm,overclock-50:0";
-+ gpios_22_25 = <0>,"=3";
-+ gpios_34_37 = <0>,"=4";
- };
- };
--- /dev/null
+From 01a031fa350f9fa197451a3b4aed04c43c46c50e Mon Sep 17 00:00:00 2001
+From: Fabrice Gasnier <fabrice.gasnier@st.com>
+Date: Mon, 1 Oct 2018 15:23:56 +0200
+Subject: [PATCH 307/725] Revert "pwm: Set class for exported channels in
+ sysfs"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit c289d6625237aa785b484b4e94c23b3b91ea7e60 upstream.
+
+This reverts commit 7e5d1fd75c3dde9fc10c4472b9368089d1b81d00 ("pwm: Set
+class for exported channels in sysfs") as it causes regression with
+multiple pwm chip[1], when exporting a pwm channel (echo X > export):
+
+- ABI (Documentation/ABI/testing/sysfs-class-pwm) states pwmX should be
+ created in /sys/class/pwm/pwmchipN/pwmX
+- Reverted patch causes new entry to be also created directly in
+ /sys/class/pwm/pwmX
+- 1st time, exporting pwmX will create an entry in /sys/class/pwm/pwmX
+- class attributes are added under pwmX folder, such as export, unexport
+ npwm, symlinks. This is wrong as it belongs to pwmchipN. It may cause
+ bad behavior and report wrong values.
+- when another export happens on another pwmchip, it can't be created
+ (e.g. -EEXIST). This is causing the issue with multiple pwmchip.
+
+Example on stm32 (stm32429i-eval) platform:
+$ ls /sys/class/pwm
+pwmchip0 pwmchip4
+
+$ cd /sys/class/pwm/pwmchip0/
+$ echo 0 > export
+$ ls /sys/class/pwm
+pwm0 pwmchip0 pwmchip4
+
+$ cd /sys/class/pwm/pwmchip4/
+$ echo 0 > export
+sysfs: cannot create duplicate filename '/class/pwm/pwm0'
+...Exception stack follows...
+
+This is also seen on other platform [2]
+
+[1] https://lkml.org/lkml/2018/9/25/713
+[2] https://lkml.org/lkml/2018/9/25/447
+
+Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
+Tested-by: Gottfried Haider <gottfried.haider@gmail.com>
+Tested-by: Michal Vokáč <michal.vokac@ysoft.com>
+Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
+---
+ drivers/pwm/sysfs.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/pwm/sysfs.c
++++ b/drivers/pwm/sysfs.c
+@@ -263,7 +263,6 @@ static int pwm_export_child(struct devic
+ export->pwm = pwm;
+ mutex_init(&export->lock);
+
+- export->child.class = parent->class;
+ export->child.release = pwm_export_release;
+ export->child.parent = parent;
+ export->child.devt = MKDEV(0, 0);
+++ /dev/null
-From 0efd687c78d47645956af472eac1b8d8f3a973d5 Mon Sep 17 00:00:00 2001
-From: P33M <p33m@github.com>
-Date: Wed, 16 Jan 2019 10:17:52 +0000
-Subject: [PATCH 307/703] dwc_otg: fix bug with port_addr assignment for
- single-TT hubs
-
-See https://github.com/raspberrypi/linux/issues/2734
-
-The "Hub Port" field in the split transaction packet was always set
-to 1 for single-TT hubs. The majority of single-TT hub products
-apparently ignore this field and broadcast to all downstream enabled
-ports, which masked the issue. A subset of hub devices apparently
-need the port number to be exact or split transactions will fail.
----
- drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-@@ -232,7 +232,7 @@ static int _hub_info(dwc_otg_hcd_t * hcd
- else
- *hub_addr = urb->dev->tt->hub->devnum;
- }
-- *port_addr = urb->dev->tt->multi ? urb->dev->ttport : 1;
-+ *port_addr = urb->dev->ttport;
- } else {
- *hub_addr = 0;
- *port_addr = urb->dev->ttport;
+++ /dev/null
-From a87e24f59adb93d2701e56245adefe599e8eef86 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 16 Jan 2019 21:26:13 +0000
-Subject: [PATCH 308/703] configs: Add CONFIG_USB_UAS=m
-
-Enable support for USB-attached-SCSI devicess.
-
-See: https://github.com/raspberrypi/linux/issues/2813
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- 3 files changed, 3 insertions(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -1017,6 +1017,7 @@ CONFIG_USB_STORAGE_ONETOUCH=m
- CONFIG_USB_STORAGE_KARMA=m
- CONFIG_USB_STORAGE_CYPRESS_ATACB=m
- CONFIG_USB_STORAGE_ENE_UB6250=m
-+CONFIG_USB_UAS=m
- CONFIG_USB_MDC800=m
- CONFIG_USB_MICROTEK=m
- CONFIG_USBIP_CORE=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -1010,6 +1010,7 @@ CONFIG_USB_STORAGE_ONETOUCH=m
- CONFIG_USB_STORAGE_KARMA=m
- CONFIG_USB_STORAGE_CYPRESS_ATACB=m
- CONFIG_USB_STORAGE_ENE_UB6250=m
-+CONFIG_USB_UAS=m
- CONFIG_USB_MDC800=m
- CONFIG_USB_MICROTEK=m
- CONFIG_USBIP_CORE=m
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -886,6 +886,7 @@ CONFIG_USB_STORAGE_ONETOUCH=m
- CONFIG_USB_STORAGE_KARMA=m
- CONFIG_USB_STORAGE_CYPRESS_ATACB=m
- CONFIG_USB_STORAGE_ENE_UB6250=m
-+CONFIG_USB_UAS=m
- CONFIG_USB_MDC800=m
- CONFIG_USB_MICROTEK=m
- CONFIG_USBIP_CORE=m
--- /dev/null
+From 30759f3a1d9090c99769dc76964ea414b5129d85 Mon Sep 17 00:00:00 2001
+From: Fabrice Gasnier <fabrice.gasnier@st.com>
+Date: Mon, 1 Oct 2018 15:23:57 +0200
+Subject: [PATCH 308/725] pwm: Send a uevent on the pwmchip device upon channel
+ sysfs (un)export
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit 552c02e3e7cfe2744b59de285aaea70021ae95c9 upstream.
+
+This patch sends a uevent (KOBJ_CHANGE) on the pwmchipN device,
+everytime a pwmX channel has been exported/unexported via sysfs. This
+allows udev to implement rules on such events, like:
+
+SUBSYSTEM=="pwm*", PROGRAM="/bin/sh -c '\
+ chown -R root:gpio /sys/class/pwm && chmod -R 770 /sys/class/pwm;\
+ chown -R root:gpio
+/sys/devices/platform/soc/*.pwm/pwm/pwmchip* && chmod -R 770
+/sys/devices/platform/soc/*.pwm/pwm/pwmchip*\
+'"
+
+This is a replacement patch for commit 7e5d1fd75c3d ("pwm: Set class for
+exported channels in sysfs"), see [1].
+
+basic testing:
+$ udevadm monitor --environment &
+$ echo 0 > /sys/class/pwm/pwmchip0/export
+KERNEL[197.321736] change /devices/.../pwm/pwmchip0 (pwm)
+ACTION=change
+DEVPATH=/devices/.../pwm/pwmchip0
+EXPORT=pwm0
+SEQNUM=2045
+SUBSYSTEM=pwm
+
+[1] https://lkml.org/lkml/2018/9/25/713
+
+Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
+Tested-by: Gottfried Haider <gottfried.haider@gmail.com>
+Tested-by: Michal Vokáč <michal.vokac@ysoft.com>
+Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
+---
+ drivers/pwm/sysfs.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/drivers/pwm/sysfs.c
++++ b/drivers/pwm/sysfs.c
+@@ -249,6 +249,7 @@ static void pwm_export_release(struct de
+ static int pwm_export_child(struct device *parent, struct pwm_device *pwm)
+ {
+ struct pwm_export *export;
++ char *pwm_prop[2];
+ int ret;
+
+ if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags))
+@@ -276,6 +277,10 @@ static int pwm_export_child(struct devic
+ export = NULL;
+ return ret;
+ }
++ pwm_prop[0] = kasprintf(GFP_KERNEL, "EXPORT=pwm%u", pwm->hwpwm);
++ pwm_prop[1] = NULL;
++ kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop);
++ kfree(pwm_prop[0]);
+
+ return 0;
+ }
+@@ -288,6 +293,7 @@ static int pwm_unexport_match(struct dev
+ static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm)
+ {
+ struct device *child;
++ char *pwm_prop[2];
+
+ if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags))
+ return -ENODEV;
+@@ -296,6 +302,11 @@ static int pwm_unexport_child(struct dev
+ if (!child)
+ return -ENODEV;
+
++ pwm_prop[0] = kasprintf(GFP_KERNEL, "UNEXPORT=pwm%u", pwm->hwpwm);
++ pwm_prop[1] = NULL;
++ kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop);
++ kfree(pwm_prop[0]);
++
+ /* for device_find_child() */
+ put_device(child);
+ device_unregister(child);
+++ /dev/null
-From e4b9a8f537b069bd3017f30b21bceb811263c979 Mon Sep 17 00:00:00 2001
-From: HiFiBerry <info@hifiberry.com>
-Date: Mon, 8 Oct 2018 18:10:12 +0200
-Subject: [PATCH 309/703] Added driver for the HiFiBerry DAC+ ADC (#2694)
-
-Signed-off-by: Daniel Matuschek <daniel@hifiberry.com>
----
- arch/arm/boot/dts/overlays/Makefile | 1 +
- arch/arm/boot/dts/overlays/README | 21 +
- .../overlays/hifiberry-dacplusadc-overlay.dts | 71 +++
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- sound/soc/bcm/Kconfig | 8 +
- sound/soc/bcm/Makefile | 2 +
- sound/soc/bcm/hifiberry_dacplusadc.c | 407 ++++++++++++++++++
- 8 files changed, 512 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
- create mode 100644 sound/soc/bcm/hifiberry_dacplusadc.c
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -49,6 +49,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- hifiberry-amp.dtbo \
- hifiberry-dac.dtbo \
- hifiberry-dacplus.dtbo \
-+ hifiberry-dacplusadc.dtbo \
- hifiberry-digi.dtbo \
- hifiberry-digi-pro.dtbo \
- hy28a.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -779,6 +779,27 @@ Params: 24db_digital_gain Allow ga
- master for bit clock and frame clock.
-
-
-+Name: hifiberry-dacplusadc
-+Info: Configures the HifiBerry DAC+ADC audio card
-+Load: dtoverlay=hifiberry-dacplusadc,<param>=<val>
-+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!)
-+ slave Force DAC+ Pro into slave mode, using Pi as
-+ master for bit clock and frame clock.
-+
-+
- Name: hifiberry-digi
- Info: Configures the HifiBerry Digi and Digi+ audio card
- Load: dtoverlay=hifiberry-digi
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
-@@ -0,0 +1,71 @@
-+// Definitions for HiFiBerry DAC+ADC
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+ compatible = "brcm,bcm2708";
-+
-+ fragment@0 {
-+ target-path = "/clocks";
-+ __overlay__ {
-+ dacpro_osc: dacpro_osc {
-+ compatible = "hifiberry,dacpro-clk";
-+ #clock-cells = <0>;
-+ };
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&i2s>;
-+ __overlay__ {
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@2 {
-+ target = <&i2c1>;
-+ __overlay__ {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "okay";
-+
-+ pcm_codec: pcm5122@4d {
-+ #sound-dai-cells = <0>;
-+ 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";
-+ };
-+ };
-+ };
-+
-+ fragment@3 {
-+ target-path = "/";
-+ __overlay__ {
-+ dmic {
-+ #sound-dai-cells = <0>;
-+ compatible = "dmic-codec";
-+ num-channels = <2>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ fragment@4 {
-+ target = <&sound>;
-+ hifiberry_dacplusadc: __overlay__ {
-+ compatible = "hifiberry,hifiberry-dacplusadc";
-+ i2s-controller = <&i2s>;
-+ status = "okay";
-+ };
-+ };
-+
-+ __overrides__ {
-+ 24db_digital_gain =
-+ <&hifiberry_dacplusadc>,"hifiberry,24db_digital_gain?";
-+ slave = <&hifiberry_dacplusadc>,"hifiberry-dacplusadc,slave?";
-+ };
-+};
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -905,6 +905,7 @@ CONFIG_SND_BCM2835_SOC_I2S=m
- CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
- CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
-+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -898,6 +898,7 @@ CONFIG_SND_BCM2835_SOC_I2S=m
- CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
- CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
-+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -46,6 +46,14 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
- help
- Say Y or M if you want to add support for HifiBerry DAC+.
-
-+config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC
-+ tristate "Support for HifiBerry DAC+ADC"
-+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+ select SND_SOC_PCM512x_I2C
-+ select SND_SOC_DMIC
-+ help
-+ Say Y or M if you want to add support for HifiBerry DAC+ADC.
-+
- config SND_BCM2708_SOC_HIFIBERRY_DIGI
- tristate "Support for HifiBerry Digi"
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -14,6 +14,7 @@ snd-soc-googlevoicehat-codec-objs := goo
- # BCM2708 Machine Support
- snd-soc-3dlab-nano-player-objs := 3dlab-nano-player.o
- snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
-+snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
- snd-soc-justboom-dac-objs := justboom-dac.o
- snd-soc-rpi-cirrus-objs := rpi-cirrus.o
- snd-soc-rpi-proto-objs := rpi-proto.o
-@@ -36,6 +37,7 @@ snd-soc-rpi-wm8804-soundcard-objs := rpi
- obj-$(CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER) += snd-soc-3dlab-nano-player.o
- obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD) += snd-soc-googlevoicehat-codec.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
-+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
- obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
---- /dev/null
-+++ b/sound/soc/bcm/hifiberry_dacplusadc.c
-@@ -0,0 +1,407 @@
-+/*
-+ * ASoC Driver for HiFiBerry DAC+ / DAC Pro with ADC
-+ *
-+ * Author: Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
-+ * Copyright 2014-2015
-+ * based on code by Florian Meier <florian.meier@koalo.de>
-+ * ADC added by Joerg Schambacher <joscha@schambacher.com>
-+ * Copyright 2018
-+ *
-+ * 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 <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/kernel.h>
-+#include <linux/clk.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/slab.h>
-+#include <linux/delay.h>
-+
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/jack.h>
-+
-+#include "../codecs/pcm512x.h"
-+
-+#define HIFIBERRY_DACPRO_NOCLOCK 0
-+#define HIFIBERRY_DACPRO_CLK44EN 1
-+#define HIFIBERRY_DACPRO_CLK48EN 2
-+
-+struct platform_device *dmic_codec_dev;
-+
-+struct pcm512x_priv {
-+ struct regmap *regmap;
-+ struct clk *sclk;
-+};
-+
-+/* Clock rate of CLK44EN attached to GPIO6 pin */
-+#define CLK_44EN_RATE 22579200UL
-+/* Clock rate of CLK48EN attached to GPIO3 pin */
-+#define CLK_48EN_RATE 24576000UL
-+
-+static bool slave;
-+static bool snd_rpi_hifiberry_is_dacpro;
-+static bool digital_gain_0db_limit = true;
-+
-+static void snd_rpi_hifiberry_dacplusadc_select_clk(struct snd_soc_component *component,
-+ int clk_id)
-+{
-+ switch (clk_id) {
-+ case HIFIBERRY_DACPRO_NOCLOCK:
-+ snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
-+ break;
-+ case HIFIBERRY_DACPRO_CLK44EN:
-+ snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
-+ break;
-+ case HIFIBERRY_DACPRO_CLK48EN:
-+ snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
-+ break;
-+ }
-+}
-+
-+static void snd_rpi_hifiberry_dacplusadc_clk_gpio(struct snd_soc_component *component)
-+{
-+ snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
-+ snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
-+ snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
-+}
-+
-+static bool snd_rpi_hifiberry_dacplusadc_is_sclk(struct snd_soc_component *component)
-+{
-+ unsigned int sck;
-+
-+ snd_soc_component_read(component, PCM512x_RATE_DET_4, &sck);
-+ return (!(sck & 0x40));
-+}
-+
-+static bool snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(
-+ struct snd_soc_component *component)
-+{
-+ msleep(2);
-+ return snd_rpi_hifiberry_dacplusadc_is_sclk(component);
-+}
-+
-+static bool snd_rpi_hifiberry_dacplusadc_is_pro_card(struct snd_soc_component *component)
-+{
-+ bool isClk44EN, isClk48En, isNoClk;
-+
-+ snd_rpi_hifiberry_dacplusadc_clk_gpio(component);
-+
-+ snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
-+ isClk44EN = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
-+
-+ snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
-+ isNoClk = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
-+
-+ snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
-+ isClk48En = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
-+
-+ return (isClk44EN && isClk48En && !isNoClk);
-+}
-+
-+static int snd_rpi_hifiberry_dacplusadc_clk_for_rate(int sample_rate)
-+{
-+ int type;
-+
-+ switch (sample_rate) {
-+ case 11025:
-+ case 22050:
-+ case 44100:
-+ case 88200:
-+ case 176400:
-+ case 352800:
-+ type = HIFIBERRY_DACPRO_CLK44EN;
-+ break;
-+ default:
-+ type = HIFIBERRY_DACPRO_CLK48EN;
-+ break;
-+ }
-+ return type;
-+}
-+
-+static void snd_rpi_hifiberry_dacplusadc_set_sclk(struct snd_soc_component *component,
-+ int sample_rate)
-+{
-+ struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
-+
-+ if (!IS_ERR(pcm512x->sclk)) {
-+ int ctype;
-+
-+ ctype = snd_rpi_hifiberry_dacplusadc_clk_for_rate(sample_rate);
-+ clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN)
-+ ? CLK_44EN_RATE : CLK_48EN_RATE);
-+ snd_rpi_hifiberry_dacplusadc_select_clk(component, ctype);
-+ }
-+}
-+
-+static int snd_rpi_hifiberry_dacplusadc_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+ struct snd_soc_component *component = rtd->codec_dai->component;
-+ struct pcm512x_priv *priv;
-+
-+ if (slave)
-+ snd_rpi_hifiberry_is_dacpro = false;
-+ else
-+ snd_rpi_hifiberry_is_dacpro =
-+ snd_rpi_hifiberry_dacplusadc_is_pro_card(component);
-+
-+ if (snd_rpi_hifiberry_is_dacpro) {
-+ struct snd_soc_dai_link *dai = rtd->dai_link;
-+
-+ dai->name = "HiFiBerry ADCDAC+ Pro";
-+ dai->stream_name = "HiFiBerry ADCDAC+ Pro HiFi";
-+ dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
-+ | SND_SOC_DAIFMT_CBM_CFM;
-+
-+ snd_soc_component_update_bits(component, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
-+ snd_soc_component_update_bits(component, PCM512x_MASTER_MODE, 0x03, 0x03);
-+ snd_soc_component_update_bits(component, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
-+ } else {
-+ priv = snd_soc_component_get_drvdata(component);
-+ priv->sclk = ERR_PTR(-ENOENT);
-+ }
-+
-+ snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x08, 0x08);
-+ snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
-+ snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
-+
-+ if (digital_gain_0db_limit) {
-+ int ret;
-+ struct snd_soc_card *card = rtd->card;
-+
-+ ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
-+ if (ret < 0)
-+ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
-+ }
-+
-+ return 0;
-+}
-+
-+static int snd_rpi_hifiberry_dacplusadc_update_rate_den(
-+ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
-+{
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct snd_soc_component *component = rtd->codec_dai->component;
-+ struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
-+ struct snd_ratnum *rats_no_pll;
-+ unsigned int num = 0, den = 0;
-+ int err;
-+
-+ rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
-+ if (!rats_no_pll)
-+ return -ENOMEM;
-+
-+ rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
-+ rats_no_pll->den_min = 1;
-+ rats_no_pll->den_max = 128;
-+ rats_no_pll->den_step = 1;
-+
-+ err = snd_interval_ratnum(hw_param_interval(params,
-+ SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
-+ if (err >= 0 && den) {
-+ params->rate_num = num;
-+ params->rate_den = den;
-+ }
-+
-+ devm_kfree(rtd->dev, rats_no_pll);
-+ return 0;
-+}
-+
-+static int snd_rpi_hifiberry_dacplusadc_hw_params(
-+ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
-+{
-+ int ret = 0;
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ int channels = params_channels(params);
-+ int width = 32;
-+
-+ if (snd_rpi_hifiberry_is_dacpro) {
-+ struct snd_soc_component *component = rtd->codec_dai->component;
-+
-+ width = snd_pcm_format_physical_width(params_format(params));
-+
-+ snd_rpi_hifiberry_dacplusadc_set_sclk(component,
-+ params_rate(params));
-+
-+ ret = snd_rpi_hifiberry_dacplusadc_update_rate_den(
-+ substream, params);
-+ }
-+
-+ ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x03, 0x03,
-+ channels, width);
-+ if (ret)
-+ return ret;
-+ ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0x03, 0x03,
-+ channels, width);
-+ return ret;
-+}
-+
-+static int hifiberry_dacplusadc_LED_cnt;
-+
-+static int snd_rpi_hifiberry_dacplusadc_startup(
-+ struct snd_pcm_substream *substream)
-+{
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct snd_soc_component *component = rtd->codec_dai->component;
-+
-+ snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1,
-+ 0x08, 0x08);
-+ hifiberry_dacplusadc_LED_cnt++;
-+ return 0;
-+}
-+
-+static void snd_rpi_hifiberry_dacplusadc_shutdown(
-+ struct snd_pcm_substream *substream)
-+{
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct snd_soc_component *component = rtd->codec_dai->component;
-+
-+ hifiberry_dacplusadc_LED_cnt--;
-+ if (!hifiberry_dacplusadc_LED_cnt)
-+ snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1,
-+ 0x08, 0x00);
-+}
-+
-+/* machine stream operations */
-+static struct snd_soc_ops snd_rpi_hifiberry_dacplusadc_ops = {
-+ .hw_params = snd_rpi_hifiberry_dacplusadc_hw_params,
-+ .startup = snd_rpi_hifiberry_dacplusadc_startup,
-+ .shutdown = snd_rpi_hifiberry_dacplusadc_shutdown,
-+};
-+
-+static struct snd_soc_dai_link_component snd_rpi_hifiberry_dacplusadc_codecs[] = {
-+ {
-+ .name = "pcm512x.1-004d",
-+ .dai_name = "pcm512x-hifi",
-+ },
-+ {
-+ .name = "dmic-codec",
-+ .dai_name = "dmic-hifi",
-+ },
-+};
-+
-+static struct snd_soc_dai_link snd_rpi_hifiberry_dacplusadc_dai[] = {
-+{
-+ .name = "HiFiBerry DAC+ADC",
-+ .stream_name = "HiFiBerry DAC+ADC HiFi",
-+ .cpu_dai_name = "bcm2708-i2s.0",
-+ .platform_name = "bcm2708-i2s.0",
-+ .codecs = snd_rpi_hifiberry_dacplusadc_codecs,
-+ .num_codecs = 2,
-+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-+ SND_SOC_DAIFMT_CBS_CFS,
-+ .ops = &snd_rpi_hifiberry_dacplusadc_ops,
-+ .init = snd_rpi_hifiberry_dacplusadc_init,
-+},
-+};
-+
-+/* audio machine driver */
-+static struct snd_soc_card snd_rpi_hifiberry_dacplusadc = {
-+ .name = "snd_rpi_hifiberry_dacplusadc",
-+ .driver_name = "HifiberryDacpAdc",
-+ .owner = THIS_MODULE,
-+ .dai_link = snd_rpi_hifiberry_dacplusadc_dai,
-+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplusadc_dai),
-+};
-+
-+
-+static int snd_rpi_hifiberry_dacplusadc_probe(struct platform_device *pdev)
-+{
-+ int ret = 0;
-+
-+ snd_rpi_hifiberry_dacplusadc.dev = &pdev->dev;
-+ if (pdev->dev.of_node) {
-+ struct device_node *i2s_node;
-+ struct snd_soc_dai_link *dai;
-+
-+ dai = &snd_rpi_hifiberry_dacplusadc_dai[0];
-+ i2s_node = of_parse_phandle(pdev->dev.of_node,
-+ "i2s-controller", 0);
-+ if (i2s_node) {
-+ dai->cpu_of_node = i2s_node;
-+ dai->platform_of_node = i2s_node;
-+ dai->cpu_dai_name = NULL;
-+ dai->platform_name = NULL;
-+ }
-+ dai = &snd_rpi_hifiberry_dacplusadc_dai[1];
-+ i2s_node = of_parse_phandle(pdev->dev.of_node, "dmic", 0);
-+ if (i2s_node) {
-+ dai->cpu_of_node = i2s_node;
-+ dai->platform_of_node = i2s_node;
-+ }
-+
-+ }
-+ digital_gain_0db_limit = !of_property_read_bool(
-+ pdev->dev.of_node, "hifiberry,24db_digital_gain");
-+ slave = of_property_read_bool(pdev->dev.of_node,
-+ "hifiberry-dacplusadc,slave");
-+
-+ ret = devm_snd_soc_register_card(&pdev->dev,
-+ &snd_rpi_hifiberry_dacplusadc);
-+ if (ret && ret != -EPROBE_DEFER)
-+ dev_err(&pdev->dev,
-+ "snd_soc_register_card() failed: %d\n", ret);
-+
-+ return ret;
-+}
-+
-+static const struct of_device_id snd_rpi_hifiberry_dacplusadc_of_match[] = {
-+ { .compatible = "hifiberry,hifiberry-dacplusadc", },
-+ {},
-+};
-+
-+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplusadc_of_match);
-+
-+static struct platform_driver snd_rpi_hifiberry_dacplusadc_driver = {
-+ .driver = {
-+ .name = "snd-rpi-hifiberry-dacplusadc",
-+ .owner = THIS_MODULE,
-+ .of_match_table = snd_rpi_hifiberry_dacplusadc_of_match,
-+ },
-+ .probe = snd_rpi_hifiberry_dacplusadc_probe,
-+};
-+
-+static int __init hifiberry_dacplusadc_init(void)
-+{
-+ int ret;
-+
-+ dmic_codec_dev = platform_device_register_simple("dmic-codec", -1, NULL,
-+ 0);
-+ if (IS_ERR(dmic_codec_dev)) {
-+ pr_err("%s: dmic-codec device registration failed\n", __func__);
-+ return PTR_ERR(dmic_codec_dev);
-+ }
-+
-+ ret = platform_driver_register(&snd_rpi_hifiberry_dacplusadc_driver);
-+ if (ret) {
-+ pr_err("%s: platform driver registration failed\n", __func__);
-+ platform_device_unregister(dmic_codec_dev);
-+ }
-+
-+ return ret;
-+}
-+module_init(hifiberry_dacplusadc_init);
-+
-+static void __exit hifiberry_dacplusadc_exit(void)
-+{
-+ platform_driver_unregister(&snd_rpi_hifiberry_dacplusadc_driver);
-+ platform_device_unregister(dmic_codec_dev);
-+}
-+module_exit(hifiberry_dacplusadc_exit);
-+
-+MODULE_AUTHOR("Joerg Schambacher <joscha@schambacher.com>");
-+MODULE_AUTHOR("Daniel Matuschek <daniel@hifiberry.com>");
-+MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ADC");
-+MODULE_LICENSE("GPL v2");
--- /dev/null
+From 635c5ee81a0595cf3504e7ae4fce5e91d7e17da4 Mon Sep 17 00:00:00 2001
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Date: Wed, 19 Sep 2018 18:13:52 +0400
+Subject: [PATCH 309/725] usb: dwc2: Disable all EP's on disconnect
+
+commit dccf1bad4be7eaa096c1f3697bd37883f9a08ecb upstream.
+
+Disabling all EP's allow to reset EP's to initial state.
+On disconnect disable all EP's instead of just killing
+all requests. Because of some platform didn't catch
+disconnect event, same stuff added to
+dwc2_hsotg_core_init_disconnected() function when USB
+reset detected on the bus.
+
+Changed from version 1:
+Changed lock acquire flow in dwc2_hsotg_ep_disable()
+function.
+
+Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+---
+ drivers/usb/dwc2/gadget.c | 30 +++++++++++++++++++++++-------
+ 1 file changed, 23 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/dwc2/gadget.c
++++ b/drivers/usb/dwc2/gadget.c
+@@ -3107,6 +3107,8 @@ static void kill_all_requests(struct dwc
+ dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index);
+ }
+
++static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
++
+ /**
+ * dwc2_hsotg_disconnect - disconnect service
+ * @hsotg: The device state.
+@@ -3125,13 +3127,12 @@ void dwc2_hsotg_disconnect(struct dwc2_h
+ hsotg->connected = 0;
+ hsotg->test_mode = 0;
+
++ /* all endpoints should be shutdown */
+ for (ep = 0; ep < hsotg->num_of_eps; ep++) {
+ if (hsotg->eps_in[ep])
+- kill_all_requests(hsotg, hsotg->eps_in[ep],
+- -ESHUTDOWN);
++ dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
+ if (hsotg->eps_out[ep])
+- kill_all_requests(hsotg, hsotg->eps_out[ep],
+- -ESHUTDOWN);
++ dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
+ }
+
+ call_gadget(hsotg, disconnect);
+@@ -3189,13 +3190,23 @@ void dwc2_hsotg_core_init_disconnected(s
+ u32 val;
+ u32 usbcfg;
+ u32 dcfg = 0;
++ int ep;
+
+ /* Kill any ep0 requests as controller will be reinitialized */
+ kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
+
+- if (!is_usb_reset)
++ if (!is_usb_reset) {
+ if (dwc2_core_reset(hsotg, true))
+ return;
++ } else {
++ /* all endpoints should be shutdown */
++ for (ep = 1; ep < hsotg->num_of_eps; ep++) {
++ if (hsotg->eps_in[ep])
++ dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
++ if (hsotg->eps_out[ep])
++ dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
++ }
++ }
+
+ /*
+ * we must now enable ep0 ready for host detection and then
+@@ -3996,6 +4007,7 @@ static int dwc2_hsotg_ep_disable(struct
+ unsigned long flags;
+ u32 epctrl_reg;
+ u32 ctrl;
++ int locked;
+
+ dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep);
+
+@@ -4011,7 +4023,9 @@ static int dwc2_hsotg_ep_disable(struct
+
+ epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
+
+- spin_lock_irqsave(&hsotg->lock, flags);
++ locked = spin_is_locked(&hsotg->lock);
++ if (!locked)
++ spin_lock_irqsave(&hsotg->lock, flags);
+
+ ctrl = dwc2_readl(hsotg, epctrl_reg);
+
+@@ -4035,7 +4049,9 @@ static int dwc2_hsotg_ep_disable(struct
+ hs_ep->fifo_index = 0;
+ hs_ep->fifo_size = 0;
+
+- spin_unlock_irqrestore(&hsotg->lock, flags);
++ if (!locked)
++ spin_unlock_irqrestore(&hsotg->lock, flags);
++
+ return 0;
+ }
+
+++ /dev/null
-From d499c8f6171122d78a90c3a6403ac7c0c1f50887 Mon Sep 17 00:00:00 2001
-From: Fabrice Gasnier <fabrice.gasnier@st.com>
-Date: Mon, 1 Oct 2018 15:23:56 +0200
-Subject: [PATCH 310/703] Revert "pwm: Set class for exported channels in
- sysfs"
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-commit c289d6625237aa785b484b4e94c23b3b91ea7e60 upstream.
-
-This reverts commit 7e5d1fd75c3dde9fc10c4472b9368089d1b81d00 ("pwm: Set
-class for exported channels in sysfs") as it causes regression with
-multiple pwm chip[1], when exporting a pwm channel (echo X > export):
-
-- ABI (Documentation/ABI/testing/sysfs-class-pwm) states pwmX should be
- created in /sys/class/pwm/pwmchipN/pwmX
-- Reverted patch causes new entry to be also created directly in
- /sys/class/pwm/pwmX
-- 1st time, exporting pwmX will create an entry in /sys/class/pwm/pwmX
-- class attributes are added under pwmX folder, such as export, unexport
- npwm, symlinks. This is wrong as it belongs to pwmchipN. It may cause
- bad behavior and report wrong values.
-- when another export happens on another pwmchip, it can't be created
- (e.g. -EEXIST). This is causing the issue with multiple pwmchip.
-
-Example on stm32 (stm32429i-eval) platform:
-$ ls /sys/class/pwm
-pwmchip0 pwmchip4
-
-$ cd /sys/class/pwm/pwmchip0/
-$ echo 0 > export
-$ ls /sys/class/pwm
-pwm0 pwmchip0 pwmchip4
-
-$ cd /sys/class/pwm/pwmchip4/
-$ echo 0 > export
-sysfs: cannot create duplicate filename '/class/pwm/pwm0'
-...Exception stack follows...
-
-This is also seen on other platform [2]
-
-[1] https://lkml.org/lkml/2018/9/25/713
-[2] https://lkml.org/lkml/2018/9/25/447
-
-Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
-Tested-by: Gottfried Haider <gottfried.haider@gmail.com>
-Tested-by: Michal Vokáč <michal.vokac@ysoft.com>
-Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
----
- drivers/pwm/sysfs.c | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/drivers/pwm/sysfs.c
-+++ b/drivers/pwm/sysfs.c
-@@ -263,7 +263,6 @@ static int pwm_export_child(struct devic
- export->pwm = pwm;
- mutex_init(&export->lock);
-
-- export->child.class = parent->class;
- export->child.release = pwm_export_release;
- export->child.parent = parent;
- export->child.devt = MKDEV(0, 0);
--- /dev/null
+From ef5163a16655fba7490d8853172ecf91e8c8cc1a Mon Sep 17 00:00:00 2001
+From: Minas Harutyunyan <minas.harutyunyan@synopsys.com>
+Date: Mon, 10 Dec 2018 18:09:32 +0400
+Subject: [PATCH 310/725] usb: dwc2: Fix disable all EP's on disconnect
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit 4fe4f9fecc36956fd53c8edf96dd0c691ef98ff9 upstream.
+
+Disabling all EP's allow to reset EP's to initial state.
+Introduced new function dwc2_hsotg_ep_disable_lock() which
+before calling dwc2_hsotg_ep_disable() function acquire
+hsotg->lock and release on exiting.
+From dwc2_hsotg_ep_disable() function removed acquiring
+hsotg->lock.
+In dwc2_hsotg_core_init_disconnected() function when USB
+reset interrupt asserted disabling all ep’s by
+dwc2_hsotg_ep_disable() function.
+This updates eliminating sparse imbalance warnings.
+
+Reverted changes in dwc2_hostg_disconnect() function.
+Introduced new function dwc2_hsotg_ep_disable_lock().
+Changed dwc2_hsotg_ep_ops. Now disable point to
+dwc2_hsotg_ep_disable_lock() function.
+In functions dwc2_hsotg_udc_stop() and dwc2_hsotg_suspend()
+dwc2_hsotg_ep_disable() function replaced by
+dwc2_hsotg_ep_disable_lock() function.
+In dwc2_hsotg_ep_disable() function removed acquiring
+of hsotg->lock.
+
+Fixes: dccf1bad4be7 ("usb: dwc2: Disable all EP's on disconnect")
+Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+---
+ drivers/usb/dwc2/gadget.c | 41 ++++++++++++++++++++++-----------------
+ 1 file changed, 23 insertions(+), 18 deletions(-)
+
+--- a/drivers/usb/dwc2/gadget.c
++++ b/drivers/usb/dwc2/gadget.c
+@@ -3107,8 +3107,6 @@ static void kill_all_requests(struct dwc
+ dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index);
+ }
+
+-static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
+-
+ /**
+ * dwc2_hsotg_disconnect - disconnect service
+ * @hsotg: The device state.
+@@ -3130,9 +3128,11 @@ void dwc2_hsotg_disconnect(struct dwc2_h
+ /* all endpoints should be shutdown */
+ for (ep = 0; ep < hsotg->num_of_eps; ep++) {
+ if (hsotg->eps_in[ep])
+- dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
++ kill_all_requests(hsotg, hsotg->eps_in[ep],
++ -ESHUTDOWN);
+ if (hsotg->eps_out[ep])
+- dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
++ kill_all_requests(hsotg, hsotg->eps_out[ep],
++ -ESHUTDOWN);
+ }
+
+ call_gadget(hsotg, disconnect);
+@@ -3176,6 +3176,7 @@ static void dwc2_hsotg_irq_fifoempty(str
+ GINTSTS_PTXFEMP | \
+ GINTSTS_RXFLVL)
+
++static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
+ /**
+ * dwc2_hsotg_core_init - issue softreset to the core
+ * @hsotg: The device state
+@@ -4004,10 +4005,8 @@ static int dwc2_hsotg_ep_disable(struct
+ struct dwc2_hsotg *hsotg = hs_ep->parent;
+ int dir_in = hs_ep->dir_in;
+ int index = hs_ep->index;
+- unsigned long flags;
+ u32 epctrl_reg;
+ u32 ctrl;
+- int locked;
+
+ dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep);
+
+@@ -4023,10 +4022,6 @@ static int dwc2_hsotg_ep_disable(struct
+
+ epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
+
+- locked = spin_is_locked(&hsotg->lock);
+- if (!locked)
+- spin_lock_irqsave(&hsotg->lock, flags);
+-
+ ctrl = dwc2_readl(hsotg, epctrl_reg);
+
+ if (ctrl & DXEPCTL_EPENA)
+@@ -4049,12 +4044,22 @@ static int dwc2_hsotg_ep_disable(struct
+ hs_ep->fifo_index = 0;
+ hs_ep->fifo_size = 0;
+
+- if (!locked)
+- spin_unlock_irqrestore(&hsotg->lock, flags);
+-
+ return 0;
+ }
+
++static int dwc2_hsotg_ep_disable_lock(struct usb_ep *ep)
++{
++ struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
++ struct dwc2_hsotg *hsotg = hs_ep->parent;
++ unsigned long flags;
++ int ret;
++
++ spin_lock_irqsave(&hsotg->lock, flags);
++ ret = dwc2_hsotg_ep_disable(ep);
++ spin_unlock_irqrestore(&hsotg->lock, flags);
++ return ret;
++}
++
+ /**
+ * on_list - check request is on the given endpoint
+ * @ep: The endpoint to check.
+@@ -4202,7 +4207,7 @@ static int dwc2_hsotg_ep_sethalt_lock(st
+
+ static const struct usb_ep_ops dwc2_hsotg_ep_ops = {
+ .enable = dwc2_hsotg_ep_enable,
+- .disable = dwc2_hsotg_ep_disable,
++ .disable = dwc2_hsotg_ep_disable_lock,
+ .alloc_request = dwc2_hsotg_ep_alloc_request,
+ .free_request = dwc2_hsotg_ep_free_request,
+ .queue = dwc2_hsotg_ep_queue_lock,
+@@ -4342,9 +4347,9 @@ static int dwc2_hsotg_udc_stop(struct us
+ /* all endpoints should be shutdown */
+ for (ep = 1; ep < hsotg->num_of_eps; ep++) {
+ if (hsotg->eps_in[ep])
+- dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
++ dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep);
+ if (hsotg->eps_out[ep])
+- dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
++ dwc2_hsotg_ep_disable_lock(&hsotg->eps_out[ep]->ep);
+ }
+
+ spin_lock_irqsave(&hsotg->lock, flags);
+@@ -4792,9 +4797,9 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg
+
+ for (ep = 0; ep < hsotg->num_of_eps; ep++) {
+ if (hsotg->eps_in[ep])
+- dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
++ dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep);
+ if (hsotg->eps_out[ep])
+- dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
++ dwc2_hsotg_ep_disable_lock(&hsotg->eps_out[ep]->ep);
+ }
+ }
+
--- /dev/null
+From 365b69204bfbfdf4060f8f88d9c54d65c82efc61 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 21 Jan 2019 21:17:27 +0000
+Subject: [PATCH 311/725] overlays: Add ssd1306 overlay for OLED display
+
+See: https://github.com/raspberrypi/firmware/issues/1098
+
+Signed-off-by: mincepi <mincepi@gmail.com>
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 31 ++++++++++++++++
+ .../arm/boot/dts/overlays/ssd1306-overlay.dts | 36 +++++++++++++++++++
+ 3 files changed, 68 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/ssd1306-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -135,6 +135,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ spi2-1cs.dtbo \
+ spi2-2cs.dtbo \
+ spi2-3cs.dtbo \
++ ssd1306.dtbo \
+ superaudioboard.dtbo \
+ sx150x.dtbo \
+ tc358743.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1950,6 +1950,37 @@ Params: cs0_pin GPIO pin
+ is 'okay' or enabled).
+
+
++Name: ssd1306
++Info: Overlay for activation of SSD1306 over I2C OLED display framebuffer.
++Load: dtoverlay=ssd1306,<param>=<val>
++Params: address Location in display memory of first character.
++ (default=0)
++ width Width of display. (default=128)
++ height Height of display. (default=64)
++ offset virtual channel a. (default=0)
++ normal Has no effect on displays tested. (default=not
++ set)
++ sequential Set this if every other scan line is missing.
++ (default=not set)
++ remapped Set this if display is garbled. (default=not
++ set)
++ inverted Set this if display is inverted and mirrored.
++ (default=not set)
++
++ Examples:
++ Typical usage for 128x64 display: dtoverlay=ssd1306,inverted
++
++ Typical usage for 128x32 display: dtoverlay=ssd1306,inverted,sequential
++
++ i2c_baudrate=400000 will speed up the display.
++
++ i2c_baudrate=1000000 seems to work even though it's not officially
++ supported by the hardware, and is faster still.
++
++ For more information refer to the device datasheet at:
++ https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf
++
++
+ Name: superaudioboard
+ Info: Configures the SuperAudioBoard sound card
+ Load: dtoverlay=superaudioboard,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/ssd1306-overlay.dts
+@@ -0,0 +1,36 @@
++// Overlay for SSD1306 128x64 and 128x32 OLED displays
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "brcm,bcm2718";
++
++ fragment@0 {
++ target = <&i2c1>;
++ __overlay__ {
++ status = "okay";
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ ssd1306: oled@3c{
++ compatible = "solomon,ssd1306fb-i2c";
++ reg = <0x3c>;
++ solomon,width = <128>;
++ solomon,height = <64>;
++ solomon,page-offset = <0>;
++ };
++ };
++ };
++
++ __overrides__ {
++ address = <&ssd1306>,"reg:0";
++ width = <&ssd1306>,"solomon,width:0";
++ height = <&ssd1306>,"solomon,height:0";
++ offset = <&ssd1306>,"solomon,page-offset:0";
++ normal = <&ssd1306>,"solomon,segment-no-remap?";
++ sequential = <&ssd1306>,"solomon,com-seq?";
++ remapped = <&ssd1306>,"solomon,com-lrremap?";
++ inverted = <&ssd1306>,"solomon,com-invdir?";
++ };
++};
+++ /dev/null
-From f88cefba19bb7ad7f92f721b94fcd9782f49a3c1 Mon Sep 17 00:00:00 2001
-From: Fabrice Gasnier <fabrice.gasnier@st.com>
-Date: Mon, 1 Oct 2018 15:23:57 +0200
-Subject: [PATCH 311/703] pwm: Send a uevent on the pwmchip device upon channel
- sysfs (un)export
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-commit 552c02e3e7cfe2744b59de285aaea70021ae95c9 upstream.
-
-This patch sends a uevent (KOBJ_CHANGE) on the pwmchipN device,
-everytime a pwmX channel has been exported/unexported via sysfs. This
-allows udev to implement rules on such events, like:
-
-SUBSYSTEM=="pwm*", PROGRAM="/bin/sh -c '\
- chown -R root:gpio /sys/class/pwm && chmod -R 770 /sys/class/pwm;\
- chown -R root:gpio
-/sys/devices/platform/soc/*.pwm/pwm/pwmchip* && chmod -R 770
-/sys/devices/platform/soc/*.pwm/pwm/pwmchip*\
-'"
-
-This is a replacement patch for commit 7e5d1fd75c3d ("pwm: Set class for
-exported channels in sysfs"), see [1].
-
-basic testing:
-$ udevadm monitor --environment &
-$ echo 0 > /sys/class/pwm/pwmchip0/export
-KERNEL[197.321736] change /devices/.../pwm/pwmchip0 (pwm)
-ACTION=change
-DEVPATH=/devices/.../pwm/pwmchip0
-EXPORT=pwm0
-SEQNUM=2045
-SUBSYSTEM=pwm
-
-[1] https://lkml.org/lkml/2018/9/25/713
-
-Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
-Tested-by: Gottfried Haider <gottfried.haider@gmail.com>
-Tested-by: Michal Vokáč <michal.vokac@ysoft.com>
-Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
----
- drivers/pwm/sysfs.c | 11 +++++++++++
- 1 file changed, 11 insertions(+)
-
---- a/drivers/pwm/sysfs.c
-+++ b/drivers/pwm/sysfs.c
-@@ -249,6 +249,7 @@ static void pwm_export_release(struct de
- static int pwm_export_child(struct device *parent, struct pwm_device *pwm)
- {
- struct pwm_export *export;
-+ char *pwm_prop[2];
- int ret;
-
- if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags))
-@@ -276,6 +277,10 @@ static int pwm_export_child(struct devic
- export = NULL;
- return ret;
- }
-+ pwm_prop[0] = kasprintf(GFP_KERNEL, "EXPORT=pwm%u", pwm->hwpwm);
-+ pwm_prop[1] = NULL;
-+ kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop);
-+ kfree(pwm_prop[0]);
-
- return 0;
- }
-@@ -288,6 +293,7 @@ static int pwm_unexport_match(struct dev
- static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm)
- {
- struct device *child;
-+ char *pwm_prop[2];
-
- if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags))
- return -ENODEV;
-@@ -296,6 +302,11 @@ static int pwm_unexport_child(struct dev
- if (!child)
- return -ENODEV;
-
-+ pwm_prop[0] = kasprintf(GFP_KERNEL, "UNEXPORT=pwm%u", pwm->hwpwm);
-+ pwm_prop[1] = NULL;
-+ kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop);
-+ kfree(pwm_prop[0]);
-+
- /* for device_find_child() */
- put_device(child);
- device_unregister(child);
--- /dev/null
+From b2fbf557758e2643df53d67d3855107dbfcae2f1 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 21 Jan 2019 12:19:57 +0000
+Subject: [PATCH 312/725] overlays: mcp23017: Support the MCP23008
+
+Add an 'mcp23008' parameter to enable support for the MCP23008 device.
+
+See: https://github.com/raspberrypi/linux/issues/2818
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README | 2 ++
+ arch/arm/boot/dts/overlays/mcp23017-overlay.dts | 10 +++++++++-
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1212,6 +1212,8 @@ Params: gpiopin Gpio pin
+
+ addr I2C address of the MCP23017 (default: 0x20)
+
++ mcp23008 Configure an MCP23008 instead.
++
+
+ Name: mcp23s17
+ Info: Configures the MCP23S08/17 SPI GPIO expanders.
+--- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
+@@ -44,11 +44,19 @@
+ };
+ };
+ };
+-
++
++ fragment@3 {
++ target = <&mcp23017>;
++ __dormant__ {
++ compatible = "microchip,mcp23008";
++ };
++ };
++
+ __overrides__ {
+ gpiopin = <&mcp23017_pins>,"brcm,pins:0",
+ <&mcp23017>,"interrupts:0";
+ addr = <&mcp23017>,"reg:0";
++ mcp23008 = <0>,"=3";
+ };
+ };
+
+++ /dev/null
-From e87be7d6627b4dc1ebd9173b1bf29c16b4ebd93f Mon Sep 17 00:00:00 2001
-From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
-Date: Wed, 19 Sep 2018 18:13:52 +0400
-Subject: [PATCH 312/703] usb: dwc2: Disable all EP's on disconnect
-
-commit dccf1bad4be7eaa096c1f3697bd37883f9a08ecb upstream.
-
-Disabling all EP's allow to reset EP's to initial state.
-On disconnect disable all EP's instead of just killing
-all requests. Because of some platform didn't catch
-disconnect event, same stuff added to
-dwc2_hsotg_core_init_disconnected() function when USB
-reset detected on the bus.
-
-Changed from version 1:
-Changed lock acquire flow in dwc2_hsotg_ep_disable()
-function.
-
-Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
-Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
----
- drivers/usb/dwc2/gadget.c | 30 +++++++++++++++++++++++-------
- 1 file changed, 23 insertions(+), 7 deletions(-)
-
---- a/drivers/usb/dwc2/gadget.c
-+++ b/drivers/usb/dwc2/gadget.c
-@@ -3107,6 +3107,8 @@ static void kill_all_requests(struct dwc
- dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index);
- }
-
-+static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
-+
- /**
- * dwc2_hsotg_disconnect - disconnect service
- * @hsotg: The device state.
-@@ -3125,13 +3127,12 @@ void dwc2_hsotg_disconnect(struct dwc2_h
- hsotg->connected = 0;
- hsotg->test_mode = 0;
-
-+ /* all endpoints should be shutdown */
- for (ep = 0; ep < hsotg->num_of_eps; ep++) {
- if (hsotg->eps_in[ep])
-- kill_all_requests(hsotg, hsotg->eps_in[ep],
-- -ESHUTDOWN);
-+ dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
- if (hsotg->eps_out[ep])
-- kill_all_requests(hsotg, hsotg->eps_out[ep],
-- -ESHUTDOWN);
-+ dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
- }
-
- call_gadget(hsotg, disconnect);
-@@ -3189,13 +3190,23 @@ void dwc2_hsotg_core_init_disconnected(s
- u32 val;
- u32 usbcfg;
- u32 dcfg = 0;
-+ int ep;
-
- /* Kill any ep0 requests as controller will be reinitialized */
- kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
-
-- if (!is_usb_reset)
-+ if (!is_usb_reset) {
- if (dwc2_core_reset(hsotg, true))
- return;
-+ } else {
-+ /* all endpoints should be shutdown */
-+ for (ep = 1; ep < hsotg->num_of_eps; ep++) {
-+ if (hsotg->eps_in[ep])
-+ dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
-+ if (hsotg->eps_out[ep])
-+ dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
-+ }
-+ }
-
- /*
- * we must now enable ep0 ready for host detection and then
-@@ -3996,6 +4007,7 @@ static int dwc2_hsotg_ep_disable(struct
- unsigned long flags;
- u32 epctrl_reg;
- u32 ctrl;
-+ int locked;
-
- dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep);
-
-@@ -4011,7 +4023,9 @@ static int dwc2_hsotg_ep_disable(struct
-
- epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
-
-- spin_lock_irqsave(&hsotg->lock, flags);
-+ locked = spin_is_locked(&hsotg->lock);
-+ if (!locked)
-+ spin_lock_irqsave(&hsotg->lock, flags);
-
- ctrl = dwc2_readl(hsotg, epctrl_reg);
-
-@@ -4035,7 +4049,9 @@ static int dwc2_hsotg_ep_disable(struct
- hs_ep->fifo_index = 0;
- hs_ep->fifo_size = 0;
-
-- spin_unlock_irqrestore(&hsotg->lock, flags);
-+ if (!locked)
-+ spin_unlock_irqrestore(&hsotg->lock, flags);
-+
- return 0;
- }
-
--- /dev/null
+From f4d829afbb2bec39b872a706fe5f1382ca3864e5 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 21 Jan 2019 12:23:55 +0000
+Subject: [PATCH 313/725] overlays: Add mcp342x overlay
+
+Support the MCP342x family of ADCs from Microchip.
+
+See: https://github.com/raspberrypi/linux/issues/2819
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 16 ++++
+ .../arm/boot/dts/overlays/mcp342x-overlay.dts | 93 +++++++++++++++++++
+ 3 files changed, 110 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/mcp342x-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -79,6 +79,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ mcp2515-can1.dtbo \
+ mcp3008.dtbo \
+ mcp3202.dtbo \
++ mcp342x.dtbo \
+ media-center.dtbo \
+ midi-uart0.dtbo \
+ midi-uart1.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1277,6 +1277,22 @@ Params: spi<n>-<m>-present boolean,
+ spi<n>-<m>-speed integer, set the spi bus speed for this device
+
+
++Name: mcp342x
++Info: Overlay for activation of Microchip MCP3421-3428 ADCs over I2C
++Load: dtoverlay=mcp342x,<param>=<val>
++Params: addr I2C bus address of device, for devices with
++ addresses that are configurable, e.g. by
++ hardware links (default=0x68)
++ mcp3421 The device is an MCP3421
++ mcp3422 The device is an MCP3422
++ mcp3423 The device is an MCP3423
++ mcp3424 The device is an MCP3424
++ mcp3425 The device is an MCP3425
++ mcp3426 The device is an MCP3426
++ mcp3427 The device is an MCP3427
++ mcp3428 The device is an MCP3428
++
++
+ Name: media-center
+ Info: Media Center HAT - 2.83" Touch Display + extras by Pi Supply
+ Load: dtoverlay=media-center,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
+@@ -0,0 +1,93 @@
++// Overlay for MCP3421-8 ADCs from Microchip Semiconductor
++
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++
++ fragment@0 {
++ target = <&i2c1>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "okay";
++
++ mcp342x: mcp@68 {
++ reg = <0x68>;
++
++ status = "okay";
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&mcp342x>;
++ __dormant__ {
++ compatible = "microchip,mcp3421";
++ };
++ };
++
++ fragment@2 {
++ target = <&mcp342x>;
++ __dormant__ {
++ compatible = "microchip,mcp3422";
++ };
++ };
++
++ fragment@3 {
++ target = <&mcp342x>;
++ __dormant__ {
++ compatible = "microchip,mcp3423";
++ };
++ };
++
++ fragment@4 {
++ target = <&mcp342x>;
++ __dormant__ {
++ compatible = "microchip,mcp3424";
++ };
++ };
++
++ fragment@5 {
++ target = <&mcp342x>;
++ __dormant__ {
++ compatible = "microchip,mcp3425";
++ };
++ };
++
++ fragment@6 {
++ target = <&mcp342x>;
++ __dormant__ {
++ compatible = "microchip,mcp3426";
++ };
++ };
++
++ fragment@7 {
++ target = <&mcp342x>;
++ __dormant__ {
++ compatible = "microchip,mcp3427";
++ };
++ };
++
++ fragment@8 {
++ target = <&mcp342x>;
++ __dormant__ {
++ compatible = "microchip,mcp3428";
++ };
++ };
++
++ __overrides__ {
++ addr = <&mcp342x>,"reg:0";
++ mcp3421 = <0>,"=1";
++ mcp3422 = <0>,"=2";
++ mcp3423 = <0>,"=3";
++ mcp3424 = <0>,"=4";
++ mcp3425 = <0>,"=5";
++ mcp3426 = <0>,"=6";
++ mcp3427 = <0>,"=7";
++ mcp3428 = <0>,"=8";
++ };
++};
++
+++ /dev/null
-From c28c22b965a3c129fd4ba70a5e6b1b2353282d46 Mon Sep 17 00:00:00 2001
-From: Minas Harutyunyan <minas.harutyunyan@synopsys.com>
-Date: Mon, 10 Dec 2018 18:09:32 +0400
-Subject: [PATCH 313/703] usb: dwc2: Fix disable all EP's on disconnect
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-commit 4fe4f9fecc36956fd53c8edf96dd0c691ef98ff9 upstream.
-
-Disabling all EP's allow to reset EP's to initial state.
-Introduced new function dwc2_hsotg_ep_disable_lock() which
-before calling dwc2_hsotg_ep_disable() function acquire
-hsotg->lock and release on exiting.
-From dwc2_hsotg_ep_disable() function removed acquiring
-hsotg->lock.
-In dwc2_hsotg_core_init_disconnected() function when USB
-reset interrupt asserted disabling all ep’s by
-dwc2_hsotg_ep_disable() function.
-This updates eliminating sparse imbalance warnings.
-
-Reverted changes in dwc2_hostg_disconnect() function.
-Introduced new function dwc2_hsotg_ep_disable_lock().
-Changed dwc2_hsotg_ep_ops. Now disable point to
-dwc2_hsotg_ep_disable_lock() function.
-In functions dwc2_hsotg_udc_stop() and dwc2_hsotg_suspend()
-dwc2_hsotg_ep_disable() function replaced by
-dwc2_hsotg_ep_disable_lock() function.
-In dwc2_hsotg_ep_disable() function removed acquiring
-of hsotg->lock.
-
-Fixes: dccf1bad4be7 ("usb: dwc2: Disable all EP's on disconnect")
-Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
-Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
----
- drivers/usb/dwc2/gadget.c | 41 ++++++++++++++++++++++-----------------
- 1 file changed, 23 insertions(+), 18 deletions(-)
-
---- a/drivers/usb/dwc2/gadget.c
-+++ b/drivers/usb/dwc2/gadget.c
-@@ -3107,8 +3107,6 @@ static void kill_all_requests(struct dwc
- dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index);
- }
-
--static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
--
- /**
- * dwc2_hsotg_disconnect - disconnect service
- * @hsotg: The device state.
-@@ -3130,9 +3128,11 @@ void dwc2_hsotg_disconnect(struct dwc2_h
- /* all endpoints should be shutdown */
- for (ep = 0; ep < hsotg->num_of_eps; ep++) {
- if (hsotg->eps_in[ep])
-- dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
-+ kill_all_requests(hsotg, hsotg->eps_in[ep],
-+ -ESHUTDOWN);
- if (hsotg->eps_out[ep])
-- dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
-+ kill_all_requests(hsotg, hsotg->eps_out[ep],
-+ -ESHUTDOWN);
- }
-
- call_gadget(hsotg, disconnect);
-@@ -3176,6 +3176,7 @@ static void dwc2_hsotg_irq_fifoempty(str
- GINTSTS_PTXFEMP | \
- GINTSTS_RXFLVL)
-
-+static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
- /**
- * dwc2_hsotg_core_init - issue softreset to the core
- * @hsotg: The device state
-@@ -4004,10 +4005,8 @@ static int dwc2_hsotg_ep_disable(struct
- struct dwc2_hsotg *hsotg = hs_ep->parent;
- int dir_in = hs_ep->dir_in;
- int index = hs_ep->index;
-- unsigned long flags;
- u32 epctrl_reg;
- u32 ctrl;
-- int locked;
-
- dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep);
-
-@@ -4023,10 +4022,6 @@ static int dwc2_hsotg_ep_disable(struct
-
- epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
-
-- locked = spin_is_locked(&hsotg->lock);
-- if (!locked)
-- spin_lock_irqsave(&hsotg->lock, flags);
--
- ctrl = dwc2_readl(hsotg, epctrl_reg);
-
- if (ctrl & DXEPCTL_EPENA)
-@@ -4049,12 +4044,22 @@ static int dwc2_hsotg_ep_disable(struct
- hs_ep->fifo_index = 0;
- hs_ep->fifo_size = 0;
-
-- if (!locked)
-- spin_unlock_irqrestore(&hsotg->lock, flags);
--
- return 0;
- }
-
-+static int dwc2_hsotg_ep_disable_lock(struct usb_ep *ep)
-+{
-+ struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
-+ struct dwc2_hsotg *hsotg = hs_ep->parent;
-+ unsigned long flags;
-+ int ret;
-+
-+ spin_lock_irqsave(&hsotg->lock, flags);
-+ ret = dwc2_hsotg_ep_disable(ep);
-+ spin_unlock_irqrestore(&hsotg->lock, flags);
-+ return ret;
-+}
-+
- /**
- * on_list - check request is on the given endpoint
- * @ep: The endpoint to check.
-@@ -4202,7 +4207,7 @@ static int dwc2_hsotg_ep_sethalt_lock(st
-
- static const struct usb_ep_ops dwc2_hsotg_ep_ops = {
- .enable = dwc2_hsotg_ep_enable,
-- .disable = dwc2_hsotg_ep_disable,
-+ .disable = dwc2_hsotg_ep_disable_lock,
- .alloc_request = dwc2_hsotg_ep_alloc_request,
- .free_request = dwc2_hsotg_ep_free_request,
- .queue = dwc2_hsotg_ep_queue_lock,
-@@ -4342,9 +4347,9 @@ static int dwc2_hsotg_udc_stop(struct us
- /* all endpoints should be shutdown */
- for (ep = 1; ep < hsotg->num_of_eps; ep++) {
- if (hsotg->eps_in[ep])
-- dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
-+ dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep);
- if (hsotg->eps_out[ep])
-- dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
-+ dwc2_hsotg_ep_disable_lock(&hsotg->eps_out[ep]->ep);
- }
-
- spin_lock_irqsave(&hsotg->lock, flags);
-@@ -4792,9 +4797,9 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg
-
- for (ep = 0; ep < hsotg->num_of_eps; ep++) {
- if (hsotg->eps_in[ep])
-- dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
-+ dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep);
- if (hsotg->eps_out[ep])
-- dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
-+ dwc2_hsotg_ep_disable_lock(&hsotg->eps_out[ep]->ep);
- }
- }
-
--- /dev/null
+From cc33f2492b4b2c0d377f99c19a46207297004631 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 24 Jan 2019 13:56:30 +0000
+Subject: [PATCH 314/725] char: vcio: Add compat ioctl handling
+
+There was no compat ioctl handler, so 32 bit userspace on a
+64 bit kernel failed as IOCTL_MBOX_PROPERTY used the size
+of char*.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/char/broadcom/vcio.c | 22 +++++++++++++++++++++-
+ 1 file changed, 21 insertions(+), 1 deletion(-)
+
+--- a/drivers/char/broadcom/vcio.c
++++ b/drivers/char/broadcom/vcio.c
+@@ -24,6 +24,9 @@
+
+ #define VCIO_IOC_MAGIC 100
+ #define IOCTL_MBOX_PROPERTY _IOWR(VCIO_IOC_MAGIC, 0, char *)
++#ifdef CONFIG_COMPAT
++#define IOCTL_MBOX_PROPERTY32 _IOWR(VCIO_IOC_MAGIC, 0, compat_uptr_t)
++#endif
+
+ static struct {
+ dev_t devt;
+@@ -87,13 +90,30 @@ static long vcio_device_ioctl(struct fil
+ case IOCTL_MBOX_PROPERTY:
+ return vcio_user_property_list((void *)ioctl_param);
+ default:
+- pr_err("unknown ioctl: %d\n", ioctl_num);
++ pr_err("unknown ioctl: %x\n", ioctl_num);
+ return -EINVAL;
+ }
+ }
+
++#ifdef CONFIG_COMPAT
++static long vcio_device_compat_ioctl(struct file *file, unsigned int ioctl_num,
++ unsigned long ioctl_param)
++{
++ switch (ioctl_num) {
++ case IOCTL_MBOX_PROPERTY32:
++ return vcio_user_property_list(compat_ptr(ioctl_param));
++ default:
++ pr_err("unknown ioctl: %x\n", ioctl_num);
++ return -EINVAL;
++ }
++}
++#endif
++
+ const struct file_operations vcio_fops = {
+ .unlocked_ioctl = vcio_device_ioctl,
++#ifdef CONFIG_COMPAT
++ .compat_ioctl = vcio_device_compat_ioctl,
++#endif
+ .open = vcio_device_open,
+ .release = vcio_device_release,
+ };
+++ /dev/null
-From f6ed9ece5ed29ca16dc021ce0e9ab64bf4c879cb Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 21 Jan 2019 21:17:27 +0000
-Subject: [PATCH 314/703] overlays: Add ssd1306 overlay for OLED display
-
-See: https://github.com/raspberrypi/firmware/issues/1098
-
-Signed-off-by: mincepi <mincepi@gmail.com>
----
- arch/arm/boot/dts/overlays/Makefile | 1 +
- arch/arm/boot/dts/overlays/README | 31 ++++++++++++++++
- .../arm/boot/dts/overlays/ssd1306-overlay.dts | 36 +++++++++++++++++++
- 3 files changed, 68 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/ssd1306-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -135,6 +135,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- spi2-1cs.dtbo \
- spi2-2cs.dtbo \
- spi2-3cs.dtbo \
-+ ssd1306.dtbo \
- superaudioboard.dtbo \
- sx150x.dtbo \
- tc358743.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1950,6 +1950,37 @@ Params: cs0_pin GPIO pin
- is 'okay' or enabled).
-
-
-+Name: ssd1306
-+Info: Overlay for activation of SSD1306 over I2C OLED display framebuffer.
-+Load: dtoverlay=ssd1306,<param>=<val>
-+Params: address Location in display memory of first character.
-+ (default=0)
-+ width Width of display. (default=128)
-+ height Height of display. (default=64)
-+ offset virtual channel a. (default=0)
-+ normal Has no effect on displays tested. (default=not
-+ set)
-+ sequential Set this if every other scan line is missing.
-+ (default=not set)
-+ remapped Set this if display is garbled. (default=not
-+ set)
-+ inverted Set this if display is inverted and mirrored.
-+ (default=not set)
-+
-+ Examples:
-+ Typical usage for 128x64 display: dtoverlay=ssd1306,inverted
-+
-+ Typical usage for 128x32 display: dtoverlay=ssd1306,inverted,sequential
-+
-+ i2c_baudrate=400000 will speed up the display.
-+
-+ i2c_baudrate=1000000 seems to work even though it's not officially
-+ supported by the hardware, and is faster still.
-+
-+ For more information refer to the device datasheet at:
-+ https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf
-+
-+
- Name: superaudioboard
- Info: Configures the SuperAudioBoard sound card
- Load: dtoverlay=superaudioboard,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/ssd1306-overlay.dts
-@@ -0,0 +1,36 @@
-+// Overlay for SSD1306 128x64 and 128x32 OLED displays
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+ compatible = "brcm,bcm2718";
-+
-+ fragment@0 {
-+ target = <&i2c1>;
-+ __overlay__ {
-+ status = "okay";
-+
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ ssd1306: oled@3c{
-+ compatible = "solomon,ssd1306fb-i2c";
-+ reg = <0x3c>;
-+ solomon,width = <128>;
-+ solomon,height = <64>;
-+ solomon,page-offset = <0>;
-+ };
-+ };
-+ };
-+
-+ __overrides__ {
-+ address = <&ssd1306>,"reg:0";
-+ width = <&ssd1306>,"solomon,width:0";
-+ height = <&ssd1306>,"solomon,height:0";
-+ offset = <&ssd1306>,"solomon,page-offset:0";
-+ normal = <&ssd1306>,"solomon,segment-no-remap?";
-+ sequential = <&ssd1306>,"solomon,com-seq?";
-+ remapped = <&ssd1306>,"solomon,com-lrremap?";
-+ inverted = <&ssd1306>,"solomon,com-invdir?";
-+ };
-+};
--- /dev/null
+From b6dcbc7b76285b6e599cc9a4e75e544fb23fe5f7 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 24 Jan 2019 14:03:28 +0000
+Subject: [PATCH 315/725] char: vcio: Fail probe if rpi_firmware is not found.
+
+Device Tree is now the only supported config mechanism, therefore
+uncomment the block of code that fails the probe if the
+firmware node can't be found.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/char/broadcom/vcio.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/char/broadcom/vcio.c
++++ b/drivers/char/broadcom/vcio.c
+@@ -126,10 +126,9 @@ static int __init vcio_init(void)
+
+ np = of_find_compatible_node(NULL, NULL,
+ "raspberrypi,bcm2835-firmware");
+-/* Uncomment this when we only boot with Device Tree
+ if (!of_device_is_available(np))
+ return -ENODEV;
+-*/
++
+ vcio.fw = rpi_firmware_get(np);
+ if (!vcio.fw)
+ return -ENODEV;
+++ /dev/null
-From 1cfb681bddf0f63b99296987b155a8a9efdb7bbf Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 21 Jan 2019 12:19:57 +0000
-Subject: [PATCH 315/703] overlays: mcp23017: Support the MCP23008
-
-Add an 'mcp23008' parameter to enable support for the MCP23008 device.
-
-See: https://github.com/raspberrypi/linux/issues/2818
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README | 2 ++
- arch/arm/boot/dts/overlays/mcp23017-overlay.dts | 10 +++++++++-
- 2 files changed, 11 insertions(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1212,6 +1212,8 @@ Params: gpiopin Gpio pin
-
- addr I2C address of the MCP23017 (default: 0x20)
-
-+ mcp23008 Configure an MCP23008 instead.
-+
-
- Name: mcp23s17
- Info: Configures the MCP23S08/17 SPI GPIO expanders.
---- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
-@@ -44,11 +44,19 @@
- };
- };
- };
--
-+
-+ fragment@3 {
-+ target = <&mcp23017>;
-+ __dormant__ {
-+ compatible = "microchip,mcp23008";
-+ };
-+ };
-+
- __overrides__ {
- gpiopin = <&mcp23017_pins>,"brcm,pins:0",
- <&mcp23017>,"interrupts:0";
- addr = <&mcp23017>,"reg:0";
-+ mcp23008 = <0>,"=3";
- };
- };
-
+++ /dev/null
-From 62f5819191c114130ce67a4b8f33abd35403f777 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 21 Jan 2019 12:23:55 +0000
-Subject: [PATCH 316/703] overlays: Add mcp342x overlay
-
-Support the MCP342x family of ADCs from Microchip.
-
-See: https://github.com/raspberrypi/linux/issues/2819
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/Makefile | 1 +
- arch/arm/boot/dts/overlays/README | 16 ++++
- .../arm/boot/dts/overlays/mcp342x-overlay.dts | 93 +++++++++++++++++++
- 3 files changed, 110 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/mcp342x-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -79,6 +79,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- mcp2515-can1.dtbo \
- mcp3008.dtbo \
- mcp3202.dtbo \
-+ mcp342x.dtbo \
- media-center.dtbo \
- midi-uart0.dtbo \
- midi-uart1.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1277,6 +1277,22 @@ Params: spi<n>-<m>-present boolean,
- spi<n>-<m>-speed integer, set the spi bus speed for this device
-
-
-+Name: mcp342x
-+Info: Overlay for activation of Microchip MCP3421-3428 ADCs over I2C
-+Load: dtoverlay=mcp342x,<param>=<val>
-+Params: addr I2C bus address of device, for devices with
-+ addresses that are configurable, e.g. by
-+ hardware links (default=0x68)
-+ mcp3421 The device is an MCP3421
-+ mcp3422 The device is an MCP3422
-+ mcp3423 The device is an MCP3423
-+ mcp3424 The device is an MCP3424
-+ mcp3425 The device is an MCP3425
-+ mcp3426 The device is an MCP3426
-+ mcp3427 The device is an MCP3427
-+ mcp3428 The device is an MCP3428
-+
-+
- Name: media-center
- Info: Media Center HAT - 2.83" Touch Display + extras by Pi Supply
- Load: dtoverlay=media-center,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
-@@ -0,0 +1,93 @@
-+// Overlay for MCP3421-8 ADCs from Microchip Semiconductor
-+
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+
-+ fragment@0 {
-+ target = <&i2c1>;
-+ __overlay__ {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ status = "okay";
-+
-+ mcp342x: mcp@68 {
-+ reg = <0x68>;
-+
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&mcp342x>;
-+ __dormant__ {
-+ compatible = "microchip,mcp3421";
-+ };
-+ };
-+
-+ fragment@2 {
-+ target = <&mcp342x>;
-+ __dormant__ {
-+ compatible = "microchip,mcp3422";
-+ };
-+ };
-+
-+ fragment@3 {
-+ target = <&mcp342x>;
-+ __dormant__ {
-+ compatible = "microchip,mcp3423";
-+ };
-+ };
-+
-+ fragment@4 {
-+ target = <&mcp342x>;
-+ __dormant__ {
-+ compatible = "microchip,mcp3424";
-+ };
-+ };
-+
-+ fragment@5 {
-+ target = <&mcp342x>;
-+ __dormant__ {
-+ compatible = "microchip,mcp3425";
-+ };
-+ };
-+
-+ fragment@6 {
-+ target = <&mcp342x>;
-+ __dormant__ {
-+ compatible = "microchip,mcp3426";
-+ };
-+ };
-+
-+ fragment@7 {
-+ target = <&mcp342x>;
-+ __dormant__ {
-+ compatible = "microchip,mcp3427";
-+ };
-+ };
-+
-+ fragment@8 {
-+ target = <&mcp342x>;
-+ __dormant__ {
-+ compatible = "microchip,mcp3428";
-+ };
-+ };
-+
-+ __overrides__ {
-+ addr = <&mcp342x>,"reg:0";
-+ mcp3421 = <0>,"=1";
-+ mcp3422 = <0>,"=2";
-+ mcp3423 = <0>,"=3";
-+ mcp3424 = <0>,"=4";
-+ mcp3425 = <0>,"=5";
-+ mcp3426 = <0>,"=6";
-+ mcp3427 = <0>,"=7";
-+ mcp3428 = <0>,"=8";
-+ };
-+};
-+
--- /dev/null
+From 211b9373ea9e8094d16a1eb9d0c2c18ab70c89de Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 22 Jan 2019 12:04:09 +0000
+Subject: [PATCH 316/725] staging: mmal-vchiq: Fix client_component for 64 bit
+ kernel
+
+The MMAL client_component field is used with the event
+mechanism to allow the client to identify the component for
+which the event is generated.
+The field is only 32bits in size, therefore we can't use a
+pointer to the component in a 64 bit kernel.
+
+Component handles are already held in an array per VCHI
+instance, so use the array index as the client_component handle
+to avoid having to create a new IDR for this purpose.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 12 +++++++++---
+ .../staging/vc04_services/vchiq-mmal/mmal-vchiq.h | 1 +
+ 2 files changed, 10 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -473,9 +473,9 @@ buffer_from_host(struct vchiq_mmal_insta
+ static void event_to_host_cb(struct vchiq_mmal_instance *instance,
+ struct mmal_msg *msg, u32 msg_len)
+ {
+- /* FIXME: Not going to work on 64 bit */
++ int comp_idx = msg->u.event_to_host.client_component;
+ struct vchiq_mmal_component *component =
+- (struct vchiq_mmal_component *)msg->u.event_to_host.client_component;
++ &instance->component[comp_idx];
+ struct vchiq_mmal_port *port = NULL;
+ struct mmal_msg_context *msg_context;
+ u32 port_num = msg->u.event_to_host.port_num;
+@@ -1074,7 +1074,7 @@ static int create_component(struct vchiq
+
+ /* build component create message */
+ m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE;
+- m.u.component_create.client_component = (u32)(unsigned long)component;
++ m.u.component_create.client_component = component->client_component;
+ strncpy(m.u.component_create.name, name,
+ sizeof(m.u.component_create.name));
+
+@@ -1869,6 +1869,12 @@ int vchiq_mmal_component_init(struct vch
+ goto unlock;
+ }
+
++ /* We need a handle to reference back to our component structure.
++ * Use the array index in instance->component rather than rolling
++ * another IDR.
++ */
++ component->client_component = idx;
++
+ ret = create_component(instance, component, name);
+ if (ret < 0) {
+ pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -97,6 +97,7 @@ struct vchiq_mmal_component {
+ 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 */
++ u32 client_component; /* Used to ref back to client struct */
+ };
+
+ int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance);
+++ /dev/null
-From ee233473783f700db1c795d8114facae23ed776b Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 24 Jan 2019 13:56:30 +0000
-Subject: [PATCH 317/703] char: vcio: Add compat ioctl handling
-
-There was no compat ioctl handler, so 32 bit userspace on a
-64 bit kernel failed as IOCTL_MBOX_PROPERTY used the size
-of char*.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/char/broadcom/vcio.c | 22 +++++++++++++++++++++-
- 1 file changed, 21 insertions(+), 1 deletion(-)
-
---- a/drivers/char/broadcom/vcio.c
-+++ b/drivers/char/broadcom/vcio.c
-@@ -24,6 +24,9 @@
-
- #define VCIO_IOC_MAGIC 100
- #define IOCTL_MBOX_PROPERTY _IOWR(VCIO_IOC_MAGIC, 0, char *)
-+#ifdef CONFIG_COMPAT
-+#define IOCTL_MBOX_PROPERTY32 _IOWR(VCIO_IOC_MAGIC, 0, compat_uptr_t)
-+#endif
-
- static struct {
- dev_t devt;
-@@ -87,13 +90,30 @@ static long vcio_device_ioctl(struct fil
- case IOCTL_MBOX_PROPERTY:
- return vcio_user_property_list((void *)ioctl_param);
- default:
-- pr_err("unknown ioctl: %d\n", ioctl_num);
-+ pr_err("unknown ioctl: %x\n", ioctl_num);
- return -EINVAL;
- }
- }
-
-+#ifdef CONFIG_COMPAT
-+static long vcio_device_compat_ioctl(struct file *file, unsigned int ioctl_num,
-+ unsigned long ioctl_param)
-+{
-+ switch (ioctl_num) {
-+ case IOCTL_MBOX_PROPERTY32:
-+ return vcio_user_property_list(compat_ptr(ioctl_param));
-+ default:
-+ pr_err("unknown ioctl: %x\n", ioctl_num);
-+ return -EINVAL;
-+ }
-+}
-+#endif
-+
- const struct file_operations vcio_fops = {
- .unlocked_ioctl = vcio_device_ioctl,
-+#ifdef CONFIG_COMPAT
-+ .compat_ioctl = vcio_device_compat_ioctl,
-+#endif
- .open = vcio_device_open,
- .release = vcio_device_release,
- };
--- /dev/null
+From c75de411b5c596c6323174c1a403e2f811410b31 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 15 Jan 2019 15:35:24 +0000
+Subject: [PATCH 317/725] staging: bcm2835-camera: Add sanity checks for
+ queue_setup/CREATE_BUFS
+
+Fixes a v4l2-compliance failure when passed a buffer that is
+too small.
+queue_setup wasn't handling the case where !(*nplanes), as
+used from CREATE_BUFS and requiring the driver to sanity
+check the provided buffer parameters. It was assuming that
+it was always being used in the REQBUFS case where it provides
+the buffer properties.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-camera/bcm2835-camera.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -242,6 +242,22 @@ static int queue_setup(struct vb2_queue
+ return -EINVAL;
+ }
+
++ /* Handle CREATE_BUFS situation - *nplanes != 0 */
++ if (*nplanes) {
++ if (*nplanes != 1 ||
++ sizes[0] < dev->capture.port->current_buffer.size) {
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "%s: dev:%p Invalid buffer request from CREATE_BUFS, size %u < %u, nplanes %u != 1\n",
++ __func__, dev, sizes[0],
++ dev->capture.port->current_buffer.size,
++ *nplanes);
++ return -EINVAL;
++ } else {
++ return 0;
++ }
++ }
++
++ /* Handle REQBUFS situation */
+ size = dev->capture.port->current_buffer.size;
+ if (size == 0) {
+ v4l2_err(&dev->v4l2_dev,
+++ /dev/null
-From 4742e81159d5a54494f497a79834cf746f236681 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 24 Jan 2019 14:03:28 +0000
-Subject: [PATCH 318/703] char: vcio: Fail probe if rpi_firmware is not found.
-
-Device Tree is now the only supported config mechanism, therefore
-uncomment the block of code that fails the probe if the
-firmware node can't be found.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/char/broadcom/vcio.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
---- a/drivers/char/broadcom/vcio.c
-+++ b/drivers/char/broadcom/vcio.c
-@@ -126,10 +126,9 @@ static int __init vcio_init(void)
-
- np = of_find_compatible_node(NULL, NULL,
- "raspberrypi,bcm2835-firmware");
--/* Uncomment this when we only boot with Device Tree
- if (!of_device_is_available(np))
- return -ENODEV;
--*/
-+
- vcio.fw = rpi_firmware_get(np);
- if (!vcio.fw)
- return -ENODEV;
--- /dev/null
+From b600d9b815e728a8451848a0bbf032083622305c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 15 Jan 2019 16:32:33 +0000
+Subject: [PATCH 318/725] staging: bcm2835-camera: Set the field value within
+ each buffer
+
+Fixes a v4l2-compliance failure
+v4l2-test-buffers.cpp(415): g_field() == V4L2_FIELD_ANY
+
+The driver only ever produces progresive frames, so field should
+always be set to V4L2_FIELD_NONE.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -443,6 +443,7 @@ static void buffer_cb(struct vchiq_mmal_
+ }
+ dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
+ buf->vb.sequence = dev->capture.sequence++;
++ buf->vb.field = V4L2_FIELD_NONE;
+
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, mmal_buf->length);
+ if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
--- /dev/null
+From 8dabeeeca0cd56ca8980b594e3ce938c4540f1d5 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 23 Jan 2019 18:25:50 +0000
+Subject: [PATCH 319/725] char: vc_mem: Fix up compat ioctls for 64bit kernel
+
+compat_ioctl wasn't defined, so 32bit user/64bit kernel
+always failed.
+VC_MEM_IOC_MEM_PHYS_ADDR was defined with parameter size
+unsigned long, so the ioctl cmd changes between sizes.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/char/broadcom/vc_mem.c | 40 +++++++++++++++++++++++++++++----
+ include/linux/broadcom/vc_mem.h | 4 ++++
+ 2 files changed, 40 insertions(+), 4 deletions(-)
+
+--- a/drivers/char/broadcom/vc_mem.c
++++ b/drivers/char/broadcom/vc_mem.c
+@@ -148,7 +148,7 @@ vc_mem_ioctl(struct file *file, unsigned
+ (void) cmd;
+ (void) arg;
+
+- pr_debug("%s: called file = 0x%p\n", __func__, file);
++ pr_debug("%s: called file = 0x%p, cmd %08x\n", __func__, file, cmd);
+
+ switch (cmd) {
+ case VC_MEM_IOC_MEM_PHYS_ADDR:
+@@ -167,7 +167,7 @@ vc_mem_ioctl(struct file *file, unsigned
+ // Get the videocore memory size first
+ vc_mem_get_size();
+
+- pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__,
++ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%x\n", __func__,
+ mm_vc_mem_size);
+
+ if (copy_to_user((void *) arg, &mm_vc_mem_size,
+@@ -181,7 +181,7 @@ vc_mem_ioctl(struct file *file, unsigned
+ // Get the videocore memory base
+ vc_mem_get_base();
+
+- pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__,
++ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%x\n", __func__,
+ mm_vc_mem_base);
+
+ if (copy_to_user((void *) arg, &mm_vc_mem_base,
+@@ -195,7 +195,7 @@ vc_mem_ioctl(struct file *file, unsigned
+ // Get the videocore memory base
+ vc_mem_get_base();
+
+- pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__,
++ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%x\n", __func__,
+ mm_vc_mem_base);
+
+ if (copy_to_user((void *) arg, &mm_vc_mem_base,
+@@ -214,6 +214,35 @@ vc_mem_ioctl(struct file *file, unsigned
+ return rc;
+ }
+
++#ifdef CONFIG_COMPAT
++static long
++vc_mem_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++ int rc = 0;
++
++ switch (cmd) {
++ case VC_MEM_IOC_MEM_PHYS_ADDR32:
++ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR32=0x%p\n",
++ __func__, (void *)mm_vc_mem_phys_addr);
++
++ /* This isn't correct, but will cover us for now as
++ * VideoCore is 32bit only.
++ */
++ if (copy_to_user((void *)arg, &mm_vc_mem_phys_addr,
++ sizeof(compat_ulong_t)))
++ rc = -EFAULT;
++
++ break;
++
++ default:
++ rc = vc_mem_ioctl(file, cmd, arg);
++ break;
++ }
++
++ return rc;
++}
++#endif
++
+ /****************************************************************************
+ *
+ * vc_mem_mmap
+@@ -259,6 +288,9 @@ static const struct file_operations vc_m
+ .open = vc_mem_open,
+ .release = vc_mem_release,
+ .unlocked_ioctl = vc_mem_ioctl,
++#ifdef CONFIG_COMPAT
++ .compat_ioctl = vc_mem_compat_ioctl,
++#endif
+ .mmap = vc_mem_mmap,
+ };
+
+--- a/include/linux/broadcom/vc_mem.h
++++ b/include/linux/broadcom/vc_mem.h
+@@ -32,4 +32,8 @@ extern unsigned int mm_vc_mem_size;
+ extern int vc_mem_get_current_size( void );
+ #endif
+
++#ifdef CONFIG_COMPAT
++#define VC_MEM_IOC_MEM_PHYS_ADDR32 _IOR(VC_MEM_IOC_MAGIC, 0, compat_ulong_t)
++#endif
++
+ #endif /* _VC_MEM_H */
+++ /dev/null
-From 4be57b2f957bfe584752bc59c3a7bdee1d615b98 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 22 Jan 2019 12:04:09 +0000
-Subject: [PATCH 319/703] staging: mmal-vchiq: Fix client_component for 64 bit
- kernel
-
-The MMAL client_component field is used with the event
-mechanism to allow the client to identify the component for
-which the event is generated.
-The field is only 32bits in size, therefore we can't use a
-pointer to the component in a 64 bit kernel.
-
-Component handles are already held in an array per VCHI
-instance, so use the array index as the client_component handle
-to avoid having to create a new IDR for this purpose.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 12 +++++++++---
- .../staging/vc04_services/vchiq-mmal/mmal-vchiq.h | 1 +
- 2 files changed, 10 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -473,9 +473,9 @@ buffer_from_host(struct vchiq_mmal_insta
- static void event_to_host_cb(struct vchiq_mmal_instance *instance,
- struct mmal_msg *msg, u32 msg_len)
- {
-- /* FIXME: Not going to work on 64 bit */
-+ int comp_idx = msg->u.event_to_host.client_component;
- struct vchiq_mmal_component *component =
-- (struct vchiq_mmal_component *)msg->u.event_to_host.client_component;
-+ &instance->component[comp_idx];
- struct vchiq_mmal_port *port = NULL;
- struct mmal_msg_context *msg_context;
- u32 port_num = msg->u.event_to_host.port_num;
-@@ -1074,7 +1074,7 @@ static int create_component(struct vchiq
-
- /* build component create message */
- m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE;
-- m.u.component_create.client_component = (u32)(unsigned long)component;
-+ m.u.component_create.client_component = component->client_component;
- strncpy(m.u.component_create.name, name,
- sizeof(m.u.component_create.name));
-
-@@ -1869,6 +1869,12 @@ int vchiq_mmal_component_init(struct vch
- goto unlock;
- }
-
-+ /* We need a handle to reference back to our component structure.
-+ * Use the array index in instance->component rather than rolling
-+ * another IDR.
-+ */
-+ component->client_component = idx;
-+
- ret = create_component(instance, component, name);
- if (ret < 0) {
- pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -97,6 +97,7 @@ struct vchiq_mmal_component {
- 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 */
-+ u32 client_component; /* Used to ref back to client struct */
- };
-
- int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance);
--- /dev/null
+From 26120a2fdc44fe84dcc0092cd6f00aa23e79bbb1 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 23 Jan 2019 18:37:29 +0000
+Subject: [PATCH 320/725] char: vc_mem: Fix all coding style issues.
+
+Cleans up all checkpatch errors in vc_mem.c and vc_mem.h
+No functional change to the code.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/char/broadcom/vc_mem.c | 177 +++++++++++---------------------
+ include/linux/broadcom/vc_mem.h | 38 +++----
+ 2 files changed, 77 insertions(+), 138 deletions(-)
+
+--- a/drivers/char/broadcom/vc_mem.c
++++ b/drivers/char/broadcom/vc_mem.c
+@@ -1,16 +1,16 @@
+-/*****************************************************************************
+-* Copyright 2010 - 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.
+-*****************************************************************************/
++/*
++ * Copyright 2010 - 2011 Broadcom Corporation. All rights reserved.
++ *
++ * Unless you and Broadcom execute a separate written software license
++ * agreement governing use of this software, this software is licensed to you
++ * under the terms of the GNU General Public License version 2, available at
++ * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++ *
++ * Notwithstanding the above, under no circumstances may you combine this
++ * software in any way with any other Broadcom software provided under a
++ * license other than the GPL, without Broadcom's express prior written
++ * consent.
++ */
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -26,11 +26,11 @@
+
+ #define DRIVER_NAME "vc-mem"
+
+-// Device (/dev) related variables
+-static dev_t vc_mem_devnum = 0;
+-static struct class *vc_mem_class = NULL;
++/* Device (/dev) related variables */
++static dev_t vc_mem_devnum;
++static struct class *vc_mem_class;
+ static struct cdev vc_mem_cdev;
+-static int vc_mem_inited = 0;
++static int vc_mem_inited;
+
+ #ifdef CONFIG_DEBUG_FS
+ static struct dentry *vc_mem_debugfs_entry;
+@@ -50,96 +50,55 @@ static struct dentry *vc_mem_debugfs_ent
+ * bootloader (and/or kernel). When that happens, the values of these variables
+ * would be calculated and assigned in the init function.
+ */
+-// in the 2835 VC in mapped above ARM, but ARM has full access to VC space
+-unsigned long mm_vc_mem_phys_addr = 0x00000000;
+-unsigned int mm_vc_mem_size = 0;
+-unsigned int mm_vc_mem_base = 0;
+-
++/* In the 2835 VC in mapped above ARM, but ARM has full access to VC space */
++unsigned long mm_vc_mem_phys_addr;
+ EXPORT_SYMBOL(mm_vc_mem_phys_addr);
++unsigned int mm_vc_mem_size;
+ EXPORT_SYMBOL(mm_vc_mem_size);
++unsigned int mm_vc_mem_base;
+ EXPORT_SYMBOL(mm_vc_mem_base);
+
+-static uint phys_addr = 0;
+-static uint mem_size = 0;
+-static uint mem_base = 0;
+-
+-
+-/****************************************************************************
+-*
+-* vc_mem_open
+-*
+-***************************************************************************/
++static uint phys_addr;
++static uint mem_size;
++static uint mem_base;
+
+ static int
+ vc_mem_open(struct inode *inode, struct file *file)
+ {
+- (void) inode;
+- (void) file;
++ (void)inode;
+
+ pr_debug("%s: called file = 0x%p\n", __func__, file);
+
+ return 0;
+ }
+
+-/****************************************************************************
+-*
+-* vc_mem_release
+-*
+-***************************************************************************/
+-
+ static int
+ vc_mem_release(struct inode *inode, struct file *file)
+ {
+- (void) inode;
+- (void) file;
++ (void)inode;
+
+ pr_debug("%s: called file = 0x%p\n", __func__, file);
+
+ return 0;
+ }
+
+-/****************************************************************************
+-*
+-* vc_mem_get_size
+-*
+-***************************************************************************/
+-
+ static void
+ vc_mem_get_size(void)
+ {
+ }
+
+-/****************************************************************************
+-*
+-* vc_mem_get_base
+-*
+-***************************************************************************/
+-
+ static void
+ vc_mem_get_base(void)
+ {
+ }
+
+-/****************************************************************************
+-*
+-* vc_mem_get_current_size
+-*
+-***************************************************************************/
+-
+ int
+ vc_mem_get_current_size(void)
+ {
+ return mm_vc_mem_size;
+ }
+-
+ EXPORT_SYMBOL_GPL(vc_mem_get_current_size);
+
+-/****************************************************************************
+-*
+-* vc_mem_ioctl
+-*
+-***************************************************************************/
+-
+ static long
+ vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+@@ -154,52 +113,52 @@ vc_mem_ioctl(struct file *file, unsigned
+ case VC_MEM_IOC_MEM_PHYS_ADDR:
+ {
+ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n",
+- __func__, (void *) mm_vc_mem_phys_addr);
++ __func__, (void *)mm_vc_mem_phys_addr);
+
+- if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr,
+- sizeof (mm_vc_mem_phys_addr)) != 0) {
++ if (copy_to_user((void *)arg, &mm_vc_mem_phys_addr,
++ sizeof(mm_vc_mem_phys_addr))) {
+ rc = -EFAULT;
+ }
+ break;
+ }
+ case VC_MEM_IOC_MEM_SIZE:
+ {
+- // Get the videocore memory size first
++ /* Get the videocore memory size first */
+ vc_mem_get_size();
+
+ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%x\n", __func__,
+- mm_vc_mem_size);
++ mm_vc_mem_size);
+
+- if (copy_to_user((void *) arg, &mm_vc_mem_size,
+- sizeof (mm_vc_mem_size)) != 0) {
++ if (copy_to_user((void *)arg, &mm_vc_mem_size,
++ sizeof(mm_vc_mem_size))) {
+ rc = -EFAULT;
+ }
+ break;
+ }
+ case VC_MEM_IOC_MEM_BASE:
+ {
+- // Get the videocore memory base
++ /* Get the videocore memory base */
+ vc_mem_get_base();
+
+ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%x\n", __func__,
+- mm_vc_mem_base);
++ mm_vc_mem_base);
+
+- if (copy_to_user((void *) arg, &mm_vc_mem_base,
+- sizeof (mm_vc_mem_base)) != 0) {
++ if (copy_to_user((void *)arg, &mm_vc_mem_base,
++ sizeof(mm_vc_mem_base))) {
+ rc = -EFAULT;
+ }
+ break;
+ }
+ case VC_MEM_IOC_MEM_LOAD:
+ {
+- // Get the videocore memory base
++ /* Get the videocore memory base */
+ vc_mem_get_base();
+
+ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%x\n", __func__,
+ mm_vc_mem_base);
+
+- if (copy_to_user((void *) arg, &mm_vc_mem_base,
+- sizeof (mm_vc_mem_base)) != 0) {
++ if (copy_to_user((void *)arg, &mm_vc_mem_base,
++ sizeof(mm_vc_mem_base))) {
+ rc = -EFAULT;
+ }
+ break;
+@@ -243,12 +202,6 @@ vc_mem_compat_ioctl(struct file *file, u
+ }
+ #endif
+
+-/****************************************************************************
+-*
+-* vc_mem_mmap
+-*
+-***************************************************************************/
+-
+ static int
+ vc_mem_mmap(struct file *filp, struct vm_area_struct *vma)
+ {
+@@ -257,32 +210,26 @@ vc_mem_mmap(struct file *filp, struct vm
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+ pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n",
+- __func__, (long) vma->vm_start, (long) vma->vm_end,
+- (long) vma->vm_pgoff);
++ __func__, (long)vma->vm_start, (long)vma->vm_end,
++ (long)vma->vm_pgoff);
+
+ if (offset + length > mm_vc_mem_size) {
+ pr_err("%s: length %ld is too big\n", __func__, length);
+ return -EINVAL;
+ }
+- // Do not cache the memory map
++ /* Do not cache the memory map */
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ rc = remap_pfn_range(vma, vma->vm_start,
+ (mm_vc_mem_phys_addr >> PAGE_SHIFT) +
+ vma->vm_pgoff, length, vma->vm_page_prot);
+- if (rc != 0) {
++ if (rc)
+ pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc);
+- }
+
+ return rc;
+ }
+
+-/****************************************************************************
+-*
+-* File Operations for the driver.
+-*
+-***************************************************************************/
+-
++/* File Operations for the driver. */
+ static const struct file_operations vc_mem_fops = {
+ .owner = THIS_MODULE,
+ .open = vc_mem_open,
+@@ -316,7 +263,7 @@ static int vc_mem_debugfs_init(
+ vc_mem_debugfs_entry,
+ (u32 *)&mm_vc_mem_phys_addr)) {
+ dev_warn(dev, "%s:could not create vc_mem_phys entry\n",
+- __func__);
++ __func__);
+ goto fail;
+ }
+
+@@ -325,7 +272,7 @@ static int vc_mem_debugfs_init(
+ vc_mem_debugfs_entry,
+ (u32 *)&mm_vc_mem_size)) {
+ dev_warn(dev, "%s:could not create vc_mem_size entry\n",
+- __func__);
++ __func__);
+ goto fail;
+ }
+
+@@ -347,12 +294,7 @@ fail:
+
+ #endif /* CONFIG_DEBUG_FS */
+
+-
+-/****************************************************************************
+-*
+-* vc_mem_init
+-*
+-***************************************************************************/
++/* Module load/unload functions */
+
+ static int __init
+ vc_mem_init(void)
+@@ -369,16 +311,19 @@ vc_mem_init(void)
+ vc_mem_get_size();
+
+ pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n",
+- mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024));
++ mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size,
++ mm_vc_mem_size / (1024 * 1024));
+
+- if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) {
++ rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME);
++ if (rc < 0) {
+ pr_err("%s: alloc_chrdev_region failed (rc=%d)\n",
+ __func__, rc);
+ goto out_err;
+ }
+
+ cdev_init(&vc_mem_cdev, &vc_mem_fops);
+- if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) {
++ rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1);
++ if (rc) {
+ pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc);
+ goto out_unregister;
+ }
+@@ -408,26 +353,20 @@ vc_mem_init(void)
+
+ device_destroy(vc_mem_class, vc_mem_devnum);
+
+- out_class_destroy:
++out_class_destroy:
+ class_destroy(vc_mem_class);
+ vc_mem_class = NULL;
+
+- out_cdev_del:
++out_cdev_del:
+ cdev_del(&vc_mem_cdev);
+
+- out_unregister:
++out_unregister:
+ unregister_chrdev_region(vc_mem_devnum, 1);
+
+- out_err:
++out_err:
+ return -1;
+ }
+
+-/****************************************************************************
+-*
+-* vc_mem_exit
+-*
+-***************************************************************************/
+-
+ static void __exit
+ vc_mem_exit(void)
+ {
+--- a/include/linux/broadcom/vc_mem.h
++++ b/include/linux/broadcom/vc_mem.h
+@@ -1,16 +1,16 @@
+-/*****************************************************************************
+-* Copyright 2010 - 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.
+-*****************************************************************************/
++/*
++ * Copyright 2010 - 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_MEM_H
+ #define _VC_MEM_H
+@@ -19,17 +19,17 @@
+
+ #define VC_MEM_IOC_MAGIC 'v'
+
+-#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long )
+-#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int )
+-#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int )
+-#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int )
++#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR(VC_MEM_IOC_MAGIC, 0, unsigned long)
++#define VC_MEM_IOC_MEM_SIZE _IOR(VC_MEM_IOC_MAGIC, 1, unsigned int)
++#define VC_MEM_IOC_MEM_BASE _IOR(VC_MEM_IOC_MAGIC, 2, unsigned int)
++#define VC_MEM_IOC_MEM_LOAD _IOR(VC_MEM_IOC_MAGIC, 3, unsigned int)
+
+-#if defined( __KERNEL__ )
++#ifdef __KERNEL__
+ #define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF
+
+ extern unsigned long mm_vc_mem_phys_addr;
+ extern unsigned int mm_vc_mem_size;
+-extern int vc_mem_get_current_size( void );
++extern int vc_mem_get_current_size(void);
+ #endif
+
+ #ifdef CONFIG_COMPAT
+++ /dev/null
-From cd78829bc64d03ae095636e1c5ed851e9fd7abf2 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 15 Jan 2019 15:35:24 +0000
-Subject: [PATCH 320/703] staging: bcm2835-camera: Add sanity checks for
- queue_setup/CREATE_BUFS
-
-Fixes a v4l2-compliance failure when passed a buffer that is
-too small.
-queue_setup wasn't handling the case where !(*nplanes), as
-used from CREATE_BUFS and requiring the driver to sanity
-check the provided buffer parameters. It was assuming that
-it was always being used in the REQBUFS case where it provides
-the buffer properties.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-camera/bcm2835-camera.c | 16 ++++++++++++++++
- 1 file changed, 16 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -242,6 +242,22 @@ static int queue_setup(struct vb2_queue
- return -EINVAL;
- }
-
-+ /* Handle CREATE_BUFS situation - *nplanes != 0 */
-+ if (*nplanes) {
-+ if (*nplanes != 1 ||
-+ sizes[0] < dev->capture.port->current_buffer.size) {
-+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-+ "%s: dev:%p Invalid buffer request from CREATE_BUFS, size %u < %u, nplanes %u != 1\n",
-+ __func__, dev, sizes[0],
-+ dev->capture.port->current_buffer.size,
-+ *nplanes);
-+ return -EINVAL;
-+ } else {
-+ return 0;
-+ }
-+ }
-+
-+ /* Handle REQBUFS situation */
- size = dev->capture.port->current_buffer.size;
- if (size == 0) {
- v4l2_err(&dev->v4l2_dev,
--- /dev/null
+From a279fd3a9e17e2306f7c585cdc070913a456e9fa Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 24 Jan 2019 15:09:28 +0000
+Subject: [PATCH 321/725] clk: clk-bcm2835: Use %zd when printing size_t
+
+The debug text for how many clocks have been registered
+uses "%d" with a size_t. Correct it to "%zd".
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -2271,7 +2271,7 @@ static int bcm2835_clk_probe(struct plat
+ return ret;
+
+ /* note that we have registered all the clocks */
+- dev_dbg(dev, "registered %d clocks\n", asize);
++ dev_dbg(dev, "registered %zd clocks\n", asize);
+
+ return 0;
+ }
+++ /dev/null
-From a470862bbbcc79c925933bf3e5beb7265e9aef48 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 15 Jan 2019 16:32:33 +0000
-Subject: [PATCH 321/703] staging: bcm2835-camera: Set the field value within
- each buffer
-
-Fixes a v4l2-compliance failure
-v4l2-test-buffers.cpp(415): g_field() == V4L2_FIELD_ANY
-
-The driver only ever produces progresive frames, so field should
-always be set to V4L2_FIELD_NONE.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
-@@ -443,6 +443,7 @@ static void buffer_cb(struct vchiq_mmal_
- }
- dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
- buf->vb.sequence = dev->capture.sequence++;
-+ buf->vb.field = V4L2_FIELD_NONE;
-
- vb2_set_plane_payload(&buf->vb.vb2_buf, 0, mmal_buf->length);
- if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
+++ /dev/null
-From e2387d73874182f3aa3b0748bfa19b5cb292f97c Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 23 Jan 2019 18:25:50 +0000
-Subject: [PATCH 322/703] char: vc_mem: Fix up compat ioctls for 64bit kernel
-
-compat_ioctl wasn't defined, so 32bit user/64bit kernel
-always failed.
-VC_MEM_IOC_MEM_PHYS_ADDR was defined with parameter size
-unsigned long, so the ioctl cmd changes between sizes.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/char/broadcom/vc_mem.c | 40 +++++++++++++++++++++++++++++----
- include/linux/broadcom/vc_mem.h | 4 ++++
- 2 files changed, 40 insertions(+), 4 deletions(-)
-
---- a/drivers/char/broadcom/vc_mem.c
-+++ b/drivers/char/broadcom/vc_mem.c
-@@ -148,7 +148,7 @@ vc_mem_ioctl(struct file *file, unsigned
- (void) cmd;
- (void) arg;
-
-- pr_debug("%s: called file = 0x%p\n", __func__, file);
-+ pr_debug("%s: called file = 0x%p, cmd %08x\n", __func__, file, cmd);
-
- switch (cmd) {
- case VC_MEM_IOC_MEM_PHYS_ADDR:
-@@ -167,7 +167,7 @@ vc_mem_ioctl(struct file *file, unsigned
- // Get the videocore memory size first
- vc_mem_get_size();
-
-- pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__,
-+ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%x\n", __func__,
- mm_vc_mem_size);
-
- if (copy_to_user((void *) arg, &mm_vc_mem_size,
-@@ -181,7 +181,7 @@ vc_mem_ioctl(struct file *file, unsigned
- // Get the videocore memory base
- vc_mem_get_base();
-
-- pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__,
-+ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%x\n", __func__,
- mm_vc_mem_base);
-
- if (copy_to_user((void *) arg, &mm_vc_mem_base,
-@@ -195,7 +195,7 @@ vc_mem_ioctl(struct file *file, unsigned
- // Get the videocore memory base
- vc_mem_get_base();
-
-- pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__,
-+ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%x\n", __func__,
- mm_vc_mem_base);
-
- if (copy_to_user((void *) arg, &mm_vc_mem_base,
-@@ -214,6 +214,35 @@ vc_mem_ioctl(struct file *file, unsigned
- return rc;
- }
-
-+#ifdef CONFIG_COMPAT
-+static long
-+vc_mem_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+ int rc = 0;
-+
-+ switch (cmd) {
-+ case VC_MEM_IOC_MEM_PHYS_ADDR32:
-+ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR32=0x%p\n",
-+ __func__, (void *)mm_vc_mem_phys_addr);
-+
-+ /* This isn't correct, but will cover us for now as
-+ * VideoCore is 32bit only.
-+ */
-+ if (copy_to_user((void *)arg, &mm_vc_mem_phys_addr,
-+ sizeof(compat_ulong_t)))
-+ rc = -EFAULT;
-+
-+ break;
-+
-+ default:
-+ rc = vc_mem_ioctl(file, cmd, arg);
-+ break;
-+ }
-+
-+ return rc;
-+}
-+#endif
-+
- /****************************************************************************
- *
- * vc_mem_mmap
-@@ -259,6 +288,9 @@ static const struct file_operations vc_m
- .open = vc_mem_open,
- .release = vc_mem_release,
- .unlocked_ioctl = vc_mem_ioctl,
-+#ifdef CONFIG_COMPAT
-+ .compat_ioctl = vc_mem_compat_ioctl,
-+#endif
- .mmap = vc_mem_mmap,
- };
-
---- a/include/linux/broadcom/vc_mem.h
-+++ b/include/linux/broadcom/vc_mem.h
-@@ -32,4 +32,8 @@ extern unsigned int mm_vc_mem_size;
- extern int vc_mem_get_current_size( void );
- #endif
-
-+#ifdef CONFIG_COMPAT
-+#define VC_MEM_IOC_MEM_PHYS_ADDR32 _IOR(VC_MEM_IOC_MAGIC, 0, compat_ulong_t)
-+#endif
-+
- #endif /* _VC_MEM_H */
--- /dev/null
+From d80feb505001d17a4643c93ef342ec5d61e0122c Mon Sep 17 00:00:00 2001
+From: Serge Schneider <serge@raspberrypi.org>
+Date: Tue, 29 Jan 2019 12:05:49 +0000
+Subject: [PATCH 322/725] mfd: Add rpi_sense_core of compatible string
+
+---
+ drivers/mfd/rpisense-core.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/mfd/rpisense-core.c
++++ b/drivers/mfd/rpisense-core.c
+@@ -138,6 +138,14 @@ static const struct i2c_device_id rpisen
+ };
+ MODULE_DEVICE_TABLE(i2c, rpisense_i2c_id);
+
++#ifdef CONFIG_OF
++static const struct of_device_id rpisense_core_id[] = {
++ { .compatible = "rpi,rpi-sense" },
++ { },
++};
++MODULE_DEVICE_TABLE(of, rpisense_core_id);
++#endif
++
+
+ static struct i2c_driver rpisense_driver = {
+ .driver = {
+++ /dev/null
-From 89452f1b5d1ebad50b1aab2eac896730ec2debfd Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 23 Jan 2019 18:37:29 +0000
-Subject: [PATCH 323/703] char: vc_mem: Fix all coding style issues.
-
-Cleans up all checkpatch errors in vc_mem.c and vc_mem.h
-No functional change to the code.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/char/broadcom/vc_mem.c | 177 +++++++++++---------------------
- include/linux/broadcom/vc_mem.h | 38 +++----
- 2 files changed, 77 insertions(+), 138 deletions(-)
-
---- a/drivers/char/broadcom/vc_mem.c
-+++ b/drivers/char/broadcom/vc_mem.c
-@@ -1,16 +1,16 @@
--/*****************************************************************************
--* Copyright 2010 - 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.
--*****************************************************************************/
-+/*
-+ * Copyright 2010 - 2011 Broadcom Corporation. All rights reserved.
-+ *
-+ * Unless you and Broadcom execute a separate written software license
-+ * agreement governing use of this software, this software is licensed to you
-+ * under the terms of the GNU General Public License version 2, available at
-+ * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-+ *
-+ * Notwithstanding the above, under no circumstances may you combine this
-+ * software in any way with any other Broadcom software provided under a
-+ * license other than the GPL, without Broadcom's express prior written
-+ * consent.
-+ */
-
- #include <linux/kernel.h>
- #include <linux/module.h>
-@@ -26,11 +26,11 @@
-
- #define DRIVER_NAME "vc-mem"
-
--// Device (/dev) related variables
--static dev_t vc_mem_devnum = 0;
--static struct class *vc_mem_class = NULL;
-+/* Device (/dev) related variables */
-+static dev_t vc_mem_devnum;
-+static struct class *vc_mem_class;
- static struct cdev vc_mem_cdev;
--static int vc_mem_inited = 0;
-+static int vc_mem_inited;
-
- #ifdef CONFIG_DEBUG_FS
- static struct dentry *vc_mem_debugfs_entry;
-@@ -50,96 +50,55 @@ static struct dentry *vc_mem_debugfs_ent
- * bootloader (and/or kernel). When that happens, the values of these variables
- * would be calculated and assigned in the init function.
- */
--// in the 2835 VC in mapped above ARM, but ARM has full access to VC space
--unsigned long mm_vc_mem_phys_addr = 0x00000000;
--unsigned int mm_vc_mem_size = 0;
--unsigned int mm_vc_mem_base = 0;
--
-+/* In the 2835 VC in mapped above ARM, but ARM has full access to VC space */
-+unsigned long mm_vc_mem_phys_addr;
- EXPORT_SYMBOL(mm_vc_mem_phys_addr);
-+unsigned int mm_vc_mem_size;
- EXPORT_SYMBOL(mm_vc_mem_size);
-+unsigned int mm_vc_mem_base;
- EXPORT_SYMBOL(mm_vc_mem_base);
-
--static uint phys_addr = 0;
--static uint mem_size = 0;
--static uint mem_base = 0;
--
--
--/****************************************************************************
--*
--* vc_mem_open
--*
--***************************************************************************/
-+static uint phys_addr;
-+static uint mem_size;
-+static uint mem_base;
-
- static int
- vc_mem_open(struct inode *inode, struct file *file)
- {
-- (void) inode;
-- (void) file;
-+ (void)inode;
-
- pr_debug("%s: called file = 0x%p\n", __func__, file);
-
- return 0;
- }
-
--/****************************************************************************
--*
--* vc_mem_release
--*
--***************************************************************************/
--
- static int
- vc_mem_release(struct inode *inode, struct file *file)
- {
-- (void) inode;
-- (void) file;
-+ (void)inode;
-
- pr_debug("%s: called file = 0x%p\n", __func__, file);
-
- return 0;
- }
-
--/****************************************************************************
--*
--* vc_mem_get_size
--*
--***************************************************************************/
--
- static void
- vc_mem_get_size(void)
- {
- }
-
--/****************************************************************************
--*
--* vc_mem_get_base
--*
--***************************************************************************/
--
- static void
- vc_mem_get_base(void)
- {
- }
-
--/****************************************************************************
--*
--* vc_mem_get_current_size
--*
--***************************************************************************/
--
- int
- vc_mem_get_current_size(void)
- {
- return mm_vc_mem_size;
- }
--
- EXPORT_SYMBOL_GPL(vc_mem_get_current_size);
-
--/****************************************************************************
--*
--* vc_mem_ioctl
--*
--***************************************************************************/
--
- static long
- vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
- {
-@@ -154,52 +113,52 @@ vc_mem_ioctl(struct file *file, unsigned
- case VC_MEM_IOC_MEM_PHYS_ADDR:
- {
- pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n",
-- __func__, (void *) mm_vc_mem_phys_addr);
-+ __func__, (void *)mm_vc_mem_phys_addr);
-
-- if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr,
-- sizeof (mm_vc_mem_phys_addr)) != 0) {
-+ if (copy_to_user((void *)arg, &mm_vc_mem_phys_addr,
-+ sizeof(mm_vc_mem_phys_addr))) {
- rc = -EFAULT;
- }
- break;
- }
- case VC_MEM_IOC_MEM_SIZE:
- {
-- // Get the videocore memory size first
-+ /* Get the videocore memory size first */
- vc_mem_get_size();
-
- pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%x\n", __func__,
-- mm_vc_mem_size);
-+ mm_vc_mem_size);
-
-- if (copy_to_user((void *) arg, &mm_vc_mem_size,
-- sizeof (mm_vc_mem_size)) != 0) {
-+ if (copy_to_user((void *)arg, &mm_vc_mem_size,
-+ sizeof(mm_vc_mem_size))) {
- rc = -EFAULT;
- }
- break;
- }
- case VC_MEM_IOC_MEM_BASE:
- {
-- // Get the videocore memory base
-+ /* Get the videocore memory base */
- vc_mem_get_base();
-
- pr_debug("%s: VC_MEM_IOC_MEM_BASE=%x\n", __func__,
-- mm_vc_mem_base);
-+ mm_vc_mem_base);
-
-- if (copy_to_user((void *) arg, &mm_vc_mem_base,
-- sizeof (mm_vc_mem_base)) != 0) {
-+ if (copy_to_user((void *)arg, &mm_vc_mem_base,
-+ sizeof(mm_vc_mem_base))) {
- rc = -EFAULT;
- }
- break;
- }
- case VC_MEM_IOC_MEM_LOAD:
- {
-- // Get the videocore memory base
-+ /* Get the videocore memory base */
- vc_mem_get_base();
-
- pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%x\n", __func__,
- mm_vc_mem_base);
-
-- if (copy_to_user((void *) arg, &mm_vc_mem_base,
-- sizeof (mm_vc_mem_base)) != 0) {
-+ if (copy_to_user((void *)arg, &mm_vc_mem_base,
-+ sizeof(mm_vc_mem_base))) {
- rc = -EFAULT;
- }
- break;
-@@ -243,12 +202,6 @@ vc_mem_compat_ioctl(struct file *file, u
- }
- #endif
-
--/****************************************************************************
--*
--* vc_mem_mmap
--*
--***************************************************************************/
--
- static int
- vc_mem_mmap(struct file *filp, struct vm_area_struct *vma)
- {
-@@ -257,32 +210,26 @@ vc_mem_mmap(struct file *filp, struct vm
- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-
- pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n",
-- __func__, (long) vma->vm_start, (long) vma->vm_end,
-- (long) vma->vm_pgoff);
-+ __func__, (long)vma->vm_start, (long)vma->vm_end,
-+ (long)vma->vm_pgoff);
-
- if (offset + length > mm_vc_mem_size) {
- pr_err("%s: length %ld is too big\n", __func__, length);
- return -EINVAL;
- }
-- // Do not cache the memory map
-+ /* Do not cache the memory map */
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- rc = remap_pfn_range(vma, vma->vm_start,
- (mm_vc_mem_phys_addr >> PAGE_SHIFT) +
- vma->vm_pgoff, length, vma->vm_page_prot);
-- if (rc != 0) {
-+ if (rc)
- pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc);
-- }
-
- return rc;
- }
-
--/****************************************************************************
--*
--* File Operations for the driver.
--*
--***************************************************************************/
--
-+/* File Operations for the driver. */
- static const struct file_operations vc_mem_fops = {
- .owner = THIS_MODULE,
- .open = vc_mem_open,
-@@ -316,7 +263,7 @@ static int vc_mem_debugfs_init(
- vc_mem_debugfs_entry,
- (u32 *)&mm_vc_mem_phys_addr)) {
- dev_warn(dev, "%s:could not create vc_mem_phys entry\n",
-- __func__);
-+ __func__);
- goto fail;
- }
-
-@@ -325,7 +272,7 @@ static int vc_mem_debugfs_init(
- vc_mem_debugfs_entry,
- (u32 *)&mm_vc_mem_size)) {
- dev_warn(dev, "%s:could not create vc_mem_size entry\n",
-- __func__);
-+ __func__);
- goto fail;
- }
-
-@@ -347,12 +294,7 @@ fail:
-
- #endif /* CONFIG_DEBUG_FS */
-
--
--/****************************************************************************
--*
--* vc_mem_init
--*
--***************************************************************************/
-+/* Module load/unload functions */
-
- static int __init
- vc_mem_init(void)
-@@ -369,16 +311,19 @@ vc_mem_init(void)
- vc_mem_get_size();
-
- pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n",
-- mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024));
-+ mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size,
-+ mm_vc_mem_size / (1024 * 1024));
-
-- if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) {
-+ rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME);
-+ if (rc < 0) {
- pr_err("%s: alloc_chrdev_region failed (rc=%d)\n",
- __func__, rc);
- goto out_err;
- }
-
- cdev_init(&vc_mem_cdev, &vc_mem_fops);
-- if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) {
-+ rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1);
-+ if (rc) {
- pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc);
- goto out_unregister;
- }
-@@ -408,26 +353,20 @@ vc_mem_init(void)
-
- device_destroy(vc_mem_class, vc_mem_devnum);
-
-- out_class_destroy:
-+out_class_destroy:
- class_destroy(vc_mem_class);
- vc_mem_class = NULL;
-
-- out_cdev_del:
-+out_cdev_del:
- cdev_del(&vc_mem_cdev);
-
-- out_unregister:
-+out_unregister:
- unregister_chrdev_region(vc_mem_devnum, 1);
-
-- out_err:
-+out_err:
- return -1;
- }
-
--/****************************************************************************
--*
--* vc_mem_exit
--*
--***************************************************************************/
--
- static void __exit
- vc_mem_exit(void)
- {
---- a/include/linux/broadcom/vc_mem.h
-+++ b/include/linux/broadcom/vc_mem.h
-@@ -1,16 +1,16 @@
--/*****************************************************************************
--* Copyright 2010 - 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.
--*****************************************************************************/
-+/*
-+ * Copyright 2010 - 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_MEM_H
- #define _VC_MEM_H
-@@ -19,17 +19,17 @@
-
- #define VC_MEM_IOC_MAGIC 'v'
-
--#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long )
--#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int )
--#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int )
--#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int )
-+#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR(VC_MEM_IOC_MAGIC, 0, unsigned long)
-+#define VC_MEM_IOC_MEM_SIZE _IOR(VC_MEM_IOC_MAGIC, 1, unsigned int)
-+#define VC_MEM_IOC_MEM_BASE _IOR(VC_MEM_IOC_MAGIC, 2, unsigned int)
-+#define VC_MEM_IOC_MEM_LOAD _IOR(VC_MEM_IOC_MAGIC, 3, unsigned int)
-
--#if defined( __KERNEL__ )
-+#ifdef __KERNEL__
- #define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF
-
- extern unsigned long mm_vc_mem_phys_addr;
- extern unsigned int mm_vc_mem_size;
--extern int vc_mem_get_current_size( void );
-+extern int vc_mem_get_current_size(void);
- #endif
-
- #ifdef CONFIG_COMPAT
--- /dev/null
+From f5f2adb60536b902d5c8ed8e0d93209062313a74 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 28 Jan 2019 14:40:16 +0000
+Subject: [PATCH 323/725] gpu: vc4_firmware_kms: Fix up 64 bit compile
+ warnings.
+
+Resolve two build warnings with regard using incorrectly
+sized parameters in logging messages on 64 bit builds.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -160,14 +160,14 @@ static void vc4_primary_plane_atomic_upd
+ 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",
++ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%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],
++ &fbinfo->base,
+ fb->pitches[0]);
+
+ ret = rpi_firmware_transaction(vc4->firmware,
+@@ -197,6 +197,7 @@ static void vc4_cursor_plane_atomic_upda
+ 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);
++ dma_addr_t addr = bo->paddr + fb->offsets[0];
+ int ret;
+ u32 packet_state[] = {
+ state->crtc->state->active,
+@@ -206,13 +207,13 @@ static void vc4_cursor_plane_atomic_upda
+ };
+ WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4);
+
+- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%08x/%d)",
++ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%pad/%d)",
+ plane->base.id, plane->name,
+ state->crtc_w,
+ state->crtc_h,
+ state->crtc_x,
+ state->crtc_y,
+- bo->paddr + fb->offsets[0],
++ &addr,
+ fb->pitches[0]);
+
+ /* add on the top/left offsets when overscan is active */
+@@ -238,7 +239,7 @@ static void vc4_cursor_plane_atomic_upda
+ fb != old_state->fb) {
+ u32 packet_info[] = { state->crtc_w, state->crtc_h,
+ 0, /* unused */
+- bo->paddr + fb->offsets[0],
++ addr,
+ 0, 0, /* hotx, hoty */};
+
+ ret = rpi_firmware_property(vc4->firmware,
+++ /dev/null
-From efb7d0e1c98be0715d57d6fd41f2d8f9ec7b9afd Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 24 Jan 2019 15:09:28 +0000
-Subject: [PATCH 324/703] clk: clk-bcm2835: Use %zd when printing size_t
-
-The debug text for how many clocks have been registered
-uses "%d" with a size_t. Correct it to "%zd".
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/clk/bcm/clk-bcm2835.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -2271,7 +2271,7 @@ static int bcm2835_clk_probe(struct plat
- return ret;
-
- /* note that we have registered all the clocks */
-- dev_dbg(dev, "registered %d clocks\n", asize);
-+ dev_dbg(dev, "registered %zd clocks\n", asize);
-
- return 0;
- }
--- /dev/null
+From 27447f66107940248d7875c908bf37384d9efd99 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 28 Jan 2019 14:42:34 +0000
+Subject: [PATCH 324/725] input: rpi-ft5406: Clear build warning on 64 bit
+ builds.
+
+Resolve 64 bit build warning over using %x with a dma_addr_t.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/input/touchscreen/rpi-ft5406.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/input/touchscreen/rpi-ft5406.c
++++ b/drivers/input/touchscreen/rpi-ft5406.c
+@@ -218,8 +218,8 @@ static int ft5406_probe(struct platform_
+
+ if (!ts->ts_base) {
+ dev_warn(dev,
+- "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%x)\n",
+- err, touchbuf, ts->ts_base, ts->bus_addr);
++ "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%pad)\n",
++ err, touchbuf, ts->ts_base, &ts->bus_addr);
+
+ err = rpi_firmware_property(
+ fw,
--- /dev/null
+From 63f283b8c56f4eaa2df0f46c9bdd174797316aa3 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 18 Sep 2018 10:47:38 +0100
+Subject: [PATCH 325/725] dtoverlays: Correct DT handling camera GPIOs
+
+The firmware has support for updating overrides with the correct
+GPIO settings for the camera GPIOs, but the wrong device tree
+setup ended up being merged.
+Correct the DT configuration so that the firmware does set it
+up correctly.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm270x.dtsi | 7 +++++++
+ arch/arm/boot/dts/overlays/README | 10 +---------
+ arch/arm/boot/dts/overlays/ov5647-overlay.dts | 14 +++++++++++---
+ 3 files changed, 19 insertions(+), 12 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -152,6 +152,13 @@
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
++
++ __overrides__ {
++ cam0-pwdn-ctrl;
++ cam0-pwdn;
++ cam0-led-ctrl;
++ cam0-led;
++ };
+ };
+
+ &vc4 {
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1366,15 +1366,7 @@ Info: Omnivision OV5647 camera module.
+ Uses Unicam 1, which is the standard camera connector on most Pi
+ variants.
+ Load: dtoverlay=ov5647,<param>=<val>
+-Params: cam0-pwdn GPIO used to control the sensor powerdown line.
+-
+- cam0-led GPIO used to control the sensor led
+- Both these fields should be automatically filled
+- in by the firmware to reflect the default GPIO
+- configuration of the particular Pi variant in
+- use.
+-
+- i2c_pins_0_1 Use pins 0&1 for the I2C instead of 44&45.
++Params: i2c_pins_0_1 Use pins 0&1 for the I2C instead of 44&45.
+ Useful on Compute Modules.
+
+ i2c_pins_28_29 Use pins 28&29 for the I2C instead of 44&45.
+--- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts
+@@ -14,7 +14,7 @@
+ status = "okay";
+
+ ov5647: ov5647@36 {
+- compatible = "ov5647";
++ compatible = "ovti,ov5647";
+ reg = <0x36>;
+ status = "okay";
+
+@@ -82,10 +82,18 @@
+ };
+ };
+
++ fragment@6 {
++ target-path="/__overrides__";
++ __overlay__ {
++ cam0-pwdn-ctrl = <&ov5647>,"pwdn-gpios:0";
++ cam0-pwdn = <&ov5647>,"pwdn-gpios:4";
++ cam0-led-ctrl = <&ov5647>,"pwdn-gpios:12";
++ cam0-led = <&ov5647>,"pwdn-gpios:16";
++ };
++ };
++
+ __overrides__ {
+ i2c_pins_0_1 = <0>,"-2-3+4";
+ i2c_pins_28_29 = <0>,"+2-3-4";
+- cam0-pwdn = <&ov5647>,"pwdn-gpios:4";
+- cam0-led = <&ov5647>,"pwdn-gpios:16";
+ };
+ };
+++ /dev/null
-From 9f4e8de5ea95750736cda32007e7e5f099429396 Mon Sep 17 00:00:00 2001
-From: Serge Schneider <serge@raspberrypi.org>
-Date: Tue, 29 Jan 2019 12:05:49 +0000
-Subject: [PATCH 325/703] mfd: Add rpi_sense_core of compatible string
-
----
- drivers/mfd/rpisense-core.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/drivers/mfd/rpisense-core.c
-+++ b/drivers/mfd/rpisense-core.c
-@@ -138,6 +138,14 @@ static const struct i2c_device_id rpisen
- };
- MODULE_DEVICE_TABLE(i2c, rpisense_i2c_id);
-
-+#ifdef CONFIG_OF
-+static const struct of_device_id rpisense_core_id[] = {
-+ { .compatible = "rpi,rpi-sense" },
-+ { },
-+};
-+MODULE_DEVICE_TABLE(of, rpisense_core_id);
-+#endif
-+
-
- static struct i2c_driver rpisense_driver = {
- .driver = {
+++ /dev/null
-From dacca227ccf7120b91dac51cdb863aa6bcab9c2f Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 28 Jan 2019 14:40:16 +0000
-Subject: [PATCH 326/703] gpu: vc4_firmware_kms: Fix up 64 bit compile
- warnings.
-
-Resolve two build warnings with regard using incorrectly
-sized parameters in logging messages on 64 bit builds.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 11 ++++++-----
- 1 file changed, 6 insertions(+), 5 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -160,14 +160,14 @@ static void vc4_primary_plane_atomic_upd
- 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",
-+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%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],
-+ &fbinfo->base,
- fb->pitches[0]);
-
- ret = rpi_firmware_transaction(vc4->firmware,
-@@ -197,6 +197,7 @@ static void vc4_cursor_plane_atomic_upda
- 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);
-+ dma_addr_t addr = bo->paddr + fb->offsets[0];
- int ret;
- u32 packet_state[] = {
- state->crtc->state->active,
-@@ -206,13 +207,13 @@ static void vc4_cursor_plane_atomic_upda
- };
- WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4);
-
-- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%08x/%d)",
-+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%pad/%d)",
- plane->base.id, plane->name,
- state->crtc_w,
- state->crtc_h,
- state->crtc_x,
- state->crtc_y,
-- bo->paddr + fb->offsets[0],
-+ &addr,
- fb->pitches[0]);
-
- /* add on the top/left offsets when overscan is active */
-@@ -238,7 +239,7 @@ static void vc4_cursor_plane_atomic_upda
- fb != old_state->fb) {
- u32 packet_info[] = { state->crtc_w, state->crtc_h,
- 0, /* unused */
-- bo->paddr + fb->offsets[0],
-+ addr,
- 0, 0, /* hotx, hoty */};
-
- ret = rpi_firmware_property(vc4->firmware,
--- /dev/null
+From 31ef5a3641c54ac06d1d5bc9fffcdb96d892cbf0 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 18 Sep 2018 11:08:51 +0100
+Subject: [PATCH 326/725] media: ov5647: Use gpiod_set_value_cansleep
+
+All calls to the gpio library are in contexts that can sleep,
+therefore there is no issue with having those GPIOs controlled
+by controllers which require sleeping (eg I2C GPIO expanders).
+
+Switch to using gpiod_set_value_cansleep instead of gpiod_set_value
+to avoid triggering the warning in gpiolib should the GPIO
+controller need to sleep.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/media/i2c/ov5647.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/media/i2c/ov5647.c
++++ b/drivers/media/i2c/ov5647.c
+@@ -373,7 +373,7 @@ static int ov5647_sensor_power(struct v4
+ dev_dbg(&client->dev, "OV5647 power on\n");
+
+ if (ov5647->pwdn) {
+- gpiod_set_value(ov5647->pwdn, 0);
++ gpiod_set_value_cansleep(ov5647->pwdn, 0);
+ msleep(PWDN_ACTIVE_DELAY_MS);
+ }
+
+@@ -415,7 +415,7 @@ static int ov5647_sensor_power(struct v4
+
+ clk_disable_unprepare(ov5647->xclk);
+
+- gpiod_set_value(ov5647->pwdn, 1);
++ gpiod_set_value_cansleep(ov5647->pwdn, 1);
+ }
+
+ /* Update the power count. */
+@@ -649,13 +649,13 @@ static int ov5647_probe(struct i2c_clien
+ goto mutex_remove;
+
+ if (sensor->pwdn) {
+- gpiod_set_value(sensor->pwdn, 0);
++ gpiod_set_value_cansleep(sensor->pwdn, 0);
+ msleep(PWDN_ACTIVE_DELAY_MS);
+ }
+
+ ret = ov5647_detect(sd);
+
+- gpiod_set_value(sensor->pwdn, 1);
++ gpiod_set_value_cansleep(sensor->pwdn, 1);
+
+ if (ret < 0)
+ goto error;
+++ /dev/null
-From 9611b3067bd576a4a02bf503baf57db681571e3d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 28 Jan 2019 14:42:34 +0000
-Subject: [PATCH 327/703] input: rpi-ft5406: Clear build warning on 64 bit
- builds.
-
-Resolve 64 bit build warning over using %x with a dma_addr_t.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/input/touchscreen/rpi-ft5406.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/input/touchscreen/rpi-ft5406.c
-+++ b/drivers/input/touchscreen/rpi-ft5406.c
-@@ -218,8 +218,8 @@ static int ft5406_probe(struct platform_
-
- if (!ts->ts_base) {
- dev_warn(dev,
-- "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%x)\n",
-- err, touchbuf, ts->ts_base, ts->bus_addr);
-+ "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%pad)\n",
-+ err, touchbuf, ts->ts_base, &ts->bus_addr);
-
- err = rpi_firmware_property(
- fw,
--- /dev/null
+From b5157050b90e884345d1d5ca9662cb8686f72b4a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 29 Jan 2019 15:56:10 +0000
+Subject: [PATCH 327/725] media:bcm2835-unicam: Power on subdev on
+ open/release, not streaming
+
+The driver was powering on the source subdevice as part of STREAMON,
+and powering it off in STREAMOFF. This isn't so great if there is a
+significant amount of setup required for your device.
+
+Copy the approach taken in the Atmel ISC driver where s_power(1) is called
+on first file handle open, and s_power(0) is called on the last release.
+
+See https://www.raspberrypi.org/forums/viewtopic.php?f=43&t=232437
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../media/platform/bcm2835/bcm2835-unicam.c | 68 +++++++++++++++----
+ 1 file changed, 54 insertions(+), 14 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -1237,11 +1237,6 @@ static int unicam_start_streaming(struct
+ unicam_err(dev, "Failed to enable CSI clock: %d\n", ret);
+ goto err_pm_put;
+ }
+- ret = v4l2_subdev_call(dev->sensor, core, s_power, 1);
+- if (ret < 0 && ret != -ENOIOCTLCMD) {
+- unicam_err(dev, "power on failed in subdev\n");
+- goto err_clock_unprepare;
+- }
+ dev->streaming = 1;
+
+ unicam_start_rx(dev, addr);
+@@ -1256,8 +1251,6 @@ static int unicam_start_streaming(struct
+
+ err_disable_unicam:
+ unicam_disable(dev);
+- v4l2_subdev_call(dev->sensor, core, s_power, 0);
+-err_clock_unprepare:
+ clk_disable_unprepare(dev->clock);
+ err_pm_put:
+ unicam_runtime_put(dev);
+@@ -1306,11 +1299,6 @@ static void unicam_stop_streaming(struct
+ dev->next_frm = NULL;
+ spin_unlock_irqrestore(&dev->dma_queue_lock, flags);
+
+- if (v4l2_subdev_has_op(dev->sensor, core, s_power)) {
+- if (v4l2_subdev_call(dev->sensor, core, s_power, 0) < 0)
+- unicam_err(dev, "power off failed in subdev\n");
+- }
+-
+ clk_disable_unprepare(dev->clock);
+ unicam_runtime_put(dev);
+ }
+@@ -1543,11 +1531,63 @@ static const struct vb2_ops unicam_video
+ .stop_streaming = unicam_stop_streaming,
+ };
+
++/*
++ * unicam_open : This function is based on the v4l2_fh_open helper function.
++ * It has been augmented to handle sensor subdevice power management,
++ */
++static int unicam_open(struct file *file)
++{
++ struct unicam_device *dev = video_drvdata(file);
++ int ret;
++
++ mutex_lock(&dev->lock);
++
++ ret = v4l2_fh_open(file);
++ if (ret) {
++ unicam_err(dev, "v4l2_fh_open failed\n");
++ goto unlock;
++ }
++
++ if (!v4l2_fh_is_singular_file(file))
++ goto unlock;
++
++ ret = v4l2_subdev_call(dev->sensor, core, s_power, 1);
++ if (ret < 0 && ret != -ENOIOCTLCMD) {
++ v4l2_fh_release(file);
++ goto unlock;
++ }
++
++unlock:
++ mutex_unlock(&dev->lock);
++ return ret;
++}
++
++static int unicam_release(struct file *file)
++{
++ struct unicam_device *dev = video_drvdata(file);
++ struct v4l2_subdev *sd = dev->sensor;
++ bool fh_singular;
++ int ret;
++
++ mutex_lock(&dev->lock);
++
++ fh_singular = v4l2_fh_is_singular_file(file);
++
++ ret = _vb2_fop_release(file, NULL);
++
++ if (fh_singular)
++ v4l2_subdev_call(sd, core, s_power, 0);
++
++ mutex_unlock(&dev->lock);
++
++ return ret;
++}
++
+ /* unicam capture driver file operations */
+ static const struct v4l2_file_operations unicam_fops = {
+ .owner = THIS_MODULE,
+- .open = v4l2_fh_open,
+- .release = vb2_fop_release,
++ .open = unicam_open,
++ .release = unicam_release,
+ .read = vb2_fop_read,
+ .poll = vb2_fop_poll,
+ .unlocked_ioctl = video_ioctl2,
--- /dev/null
+From 61225ddd346ff0633ced7774a4f65583fbeebc5c Mon Sep 17 00:00:00 2001
+From: Matt Flax <flatmax@flatmax.org>
+Date: Tue, 29 Jan 2019 14:56:03 +1100
+Subject: [PATCH 328/725] audioinjector-octo: revert to dummy supplies
+
+The Audio Injector Octo has had a lot of reports of not coming up on power cycles. By reverting to dummy supplies, the card comes up reliably.
+---
+ arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts | 4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
+@@ -25,10 +25,6 @@
+ reg = <0x48>;
+ clocks = <&cs42448_mclk>;
+ clock-names = "mclk";
+- VA-supply = <&vdd_5v0_reg>;
+- VD-supply = <&vdd_3v3_reg>;
+- VLS-supply = <&vdd_3v3_reg>;
+- VLC-supply = <&vdd_3v3_reg>;
+ status = "okay";
+ };
+
+++ /dev/null
-From 7ca9fd2d5c0488279fb746ef17c99f737416949d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 18 Sep 2018 10:47:38 +0100
-Subject: [PATCH 328/703] dtoverlays: Correct DT handling camera GPIOs
-
-The firmware has support for updating overrides with the correct
-GPIO settings for the camera GPIOs, but the wrong device tree
-setup ended up being merged.
-Correct the DT configuration so that the firmware does set it
-up correctly.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm/boot/dts/bcm270x.dtsi | 7 +++++++
- arch/arm/boot/dts/overlays/README | 10 +---------
- arch/arm/boot/dts/overlays/ov5647-overlay.dts | 14 +++++++++++---
- 3 files changed, 19 insertions(+), 12 deletions(-)
-
---- a/arch/arm/boot/dts/bcm270x.dtsi
-+++ b/arch/arm/boot/dts/bcm270x.dtsi
-@@ -152,6 +152,13 @@
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
-+
-+ __overrides__ {
-+ cam0-pwdn-ctrl;
-+ cam0-pwdn;
-+ cam0-led-ctrl;
-+ cam0-led;
-+ };
- };
-
- &vc4 {
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1366,15 +1366,7 @@ Info: Omnivision OV5647 camera module.
- Uses Unicam 1, which is the standard camera connector on most Pi
- variants.
- Load: dtoverlay=ov5647,<param>=<val>
--Params: cam0-pwdn GPIO used to control the sensor powerdown line.
--
-- cam0-led GPIO used to control the sensor led
-- Both these fields should be automatically filled
-- in by the firmware to reflect the default GPIO
-- configuration of the particular Pi variant in
-- use.
--
-- i2c_pins_0_1 Use pins 0&1 for the I2C instead of 44&45.
-+Params: i2c_pins_0_1 Use pins 0&1 for the I2C instead of 44&45.
- Useful on Compute Modules.
-
- i2c_pins_28_29 Use pins 28&29 for the I2C instead of 44&45.
---- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts
-@@ -14,7 +14,7 @@
- status = "okay";
-
- ov5647: ov5647@36 {
-- compatible = "ov5647";
-+ compatible = "ovti,ov5647";
- reg = <0x36>;
- status = "okay";
-
-@@ -82,10 +82,18 @@
- };
- };
-
-+ fragment@6 {
-+ target-path="/__overrides__";
-+ __overlay__ {
-+ cam0-pwdn-ctrl = <&ov5647>,"pwdn-gpios:0";
-+ cam0-pwdn = <&ov5647>,"pwdn-gpios:4";
-+ cam0-led-ctrl = <&ov5647>,"pwdn-gpios:12";
-+ cam0-led = <&ov5647>,"pwdn-gpios:16";
-+ };
-+ };
-+
- __overrides__ {
- i2c_pins_0_1 = <0>,"-2-3+4";
- i2c_pins_28_29 = <0>,"+2-3-4";
-- cam0-pwdn = <&ov5647>,"pwdn-gpios:4";
-- cam0-led = <&ov5647>,"pwdn-gpios:16";
- };
- };
+++ /dev/null
-From eca3d1380c02a49273c89ce988532dd23a964860 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 18 Sep 2018 11:08:51 +0100
-Subject: [PATCH 329/703] media: ov5647: Use gpiod_set_value_cansleep
-
-All calls to the gpio library are in contexts that can sleep,
-therefore there is no issue with having those GPIOs controlled
-by controllers which require sleeping (eg I2C GPIO expanders).
-
-Switch to using gpiod_set_value_cansleep instead of gpiod_set_value
-to avoid triggering the warning in gpiolib should the GPIO
-controller need to sleep.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/media/i2c/ov5647.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
---- a/drivers/media/i2c/ov5647.c
-+++ b/drivers/media/i2c/ov5647.c
-@@ -373,7 +373,7 @@ static int ov5647_sensor_power(struct v4
- dev_dbg(&client->dev, "OV5647 power on\n");
-
- if (ov5647->pwdn) {
-- gpiod_set_value(ov5647->pwdn, 0);
-+ gpiod_set_value_cansleep(ov5647->pwdn, 0);
- msleep(PWDN_ACTIVE_DELAY_MS);
- }
-
-@@ -415,7 +415,7 @@ static int ov5647_sensor_power(struct v4
-
- clk_disable_unprepare(ov5647->xclk);
-
-- gpiod_set_value(ov5647->pwdn, 1);
-+ gpiod_set_value_cansleep(ov5647->pwdn, 1);
- }
-
- /* Update the power count. */
-@@ -649,13 +649,13 @@ static int ov5647_probe(struct i2c_clien
- goto mutex_remove;
-
- if (sensor->pwdn) {
-- gpiod_set_value(sensor->pwdn, 0);
-+ gpiod_set_value_cansleep(sensor->pwdn, 0);
- msleep(PWDN_ACTIVE_DELAY_MS);
- }
-
- ret = ov5647_detect(sd);
-
-- gpiod_set_value(sensor->pwdn, 1);
-+ gpiod_set_value_cansleep(sensor->pwdn, 1);
-
- if (ret < 0)
- goto error;
--- /dev/null
+From 18d7a1b078978858569a03e4c0d373ac50f6d283 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 24 Jan 2019 16:20:38 +0000
+Subject: [PATCH 329/725] staging: bcm2835-camera: Correct ctrl
+ min/max/step/def to 64bit
+
+The V4L2 control API was expanded to take 64 bit values in commit
+0ba2aeb6dab (Apr 16 2014), but as this driver wasn't in the mainline
+kernel at that point this was overlooked.
+
+Update to use 64 bit values. This also fixes a couple of warnings
+in 64 bit builds.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-camera/controls.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -78,10 +78,10 @@ struct bm2835_mmal_v4l2_ctrl {
+ /* 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 */
++ s64 min;
++ s64 max; /* maximum value of control */
++ s64 def; /* default value of control */
++ u64 step; /* step size of the control */
+ const s64 *imenu; /* integer menu array */
+ u32 mmal_id; /* mmal parameter id */
+ bm2835_mmal_v4l2_ctrl_cb *setter;
+@@ -1244,7 +1244,7 @@ int bm2835_mmal_init_controls(struct bm2
+
+ case MMAL_CONTROL_TYPE_STD_MENU:
+ {
+- int mask = ctrl->min;
++ u64 mask = ctrl->min;
+
+ if (ctrl->id == V4L2_CID_SCENE_MODE) {
+ /* Special handling to work out the mask
+@@ -1254,11 +1254,11 @@ int bm2835_mmal_init_controls(struct bm2
+ */
+ int i;
+
+- mask = 1 << V4L2_SCENE_MODE_NONE;
++ mask = BIT(V4L2_SCENE_MODE_NONE);
+ for (i = 0;
+ i < ARRAY_SIZE(scene_configs);
+ i++) {
+- mask |= 1 << scene_configs[i].v4l2_scene;
++ mask |= BIT(scene_configs[i].v4l2_scene);
+ }
+ mask = ~mask;
+ }
+++ /dev/null
-From e627fc071de98ec50c88869b579bb90f15043e3d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 29 Jan 2019 15:56:10 +0000
-Subject: [PATCH 330/703] media:bcm2835-unicam: Power on subdev on
- open/release, not streaming
-
-The driver was powering on the source subdevice as part of STREAMON,
-and powering it off in STREAMOFF. This isn't so great if there is a
-significant amount of setup required for your device.
-
-Copy the approach taken in the Atmel ISC driver where s_power(1) is called
-on first file handle open, and s_power(0) is called on the last release.
-
-See https://www.raspberrypi.org/forums/viewtopic.php?f=43&t=232437
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../media/platform/bcm2835/bcm2835-unicam.c | 68 +++++++++++++++----
- 1 file changed, 54 insertions(+), 14 deletions(-)
-
---- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
-+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
-@@ -1237,11 +1237,6 @@ static int unicam_start_streaming(struct
- unicam_err(dev, "Failed to enable CSI clock: %d\n", ret);
- goto err_pm_put;
- }
-- ret = v4l2_subdev_call(dev->sensor, core, s_power, 1);
-- if (ret < 0 && ret != -ENOIOCTLCMD) {
-- unicam_err(dev, "power on failed in subdev\n");
-- goto err_clock_unprepare;
-- }
- dev->streaming = 1;
-
- unicam_start_rx(dev, addr);
-@@ -1256,8 +1251,6 @@ static int unicam_start_streaming(struct
-
- err_disable_unicam:
- unicam_disable(dev);
-- v4l2_subdev_call(dev->sensor, core, s_power, 0);
--err_clock_unprepare:
- clk_disable_unprepare(dev->clock);
- err_pm_put:
- unicam_runtime_put(dev);
-@@ -1306,11 +1299,6 @@ static void unicam_stop_streaming(struct
- dev->next_frm = NULL;
- spin_unlock_irqrestore(&dev->dma_queue_lock, flags);
-
-- if (v4l2_subdev_has_op(dev->sensor, core, s_power)) {
-- if (v4l2_subdev_call(dev->sensor, core, s_power, 0) < 0)
-- unicam_err(dev, "power off failed in subdev\n");
-- }
--
- clk_disable_unprepare(dev->clock);
- unicam_runtime_put(dev);
- }
-@@ -1543,11 +1531,63 @@ static const struct vb2_ops unicam_video
- .stop_streaming = unicam_stop_streaming,
- };
-
-+/*
-+ * unicam_open : This function is based on the v4l2_fh_open helper function.
-+ * It has been augmented to handle sensor subdevice power management,
-+ */
-+static int unicam_open(struct file *file)
-+{
-+ struct unicam_device *dev = video_drvdata(file);
-+ int ret;
-+
-+ mutex_lock(&dev->lock);
-+
-+ ret = v4l2_fh_open(file);
-+ if (ret) {
-+ unicam_err(dev, "v4l2_fh_open failed\n");
-+ goto unlock;
-+ }
-+
-+ if (!v4l2_fh_is_singular_file(file))
-+ goto unlock;
-+
-+ ret = v4l2_subdev_call(dev->sensor, core, s_power, 1);
-+ if (ret < 0 && ret != -ENOIOCTLCMD) {
-+ v4l2_fh_release(file);
-+ goto unlock;
-+ }
-+
-+unlock:
-+ mutex_unlock(&dev->lock);
-+ return ret;
-+}
-+
-+static int unicam_release(struct file *file)
-+{
-+ struct unicam_device *dev = video_drvdata(file);
-+ struct v4l2_subdev *sd = dev->sensor;
-+ bool fh_singular;
-+ int ret;
-+
-+ mutex_lock(&dev->lock);
-+
-+ fh_singular = v4l2_fh_is_singular_file(file);
-+
-+ ret = _vb2_fop_release(file, NULL);
-+
-+ if (fh_singular)
-+ v4l2_subdev_call(sd, core, s_power, 0);
-+
-+ mutex_unlock(&dev->lock);
-+
-+ return ret;
-+}
-+
- /* unicam capture driver file operations */
- static const struct v4l2_file_operations unicam_fops = {
- .owner = THIS_MODULE,
-- .open = v4l2_fh_open,
-- .release = vb2_fop_release,
-+ .open = unicam_open,
-+ .release = unicam_release,
- .read = vb2_fop_read,
- .poll = vb2_fop_poll,
- .unlocked_ioctl = video_ioctl2,
--- /dev/null
+From 9de4607bb5558db3856298e6f3674d9b794ed3bf Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 24 Jan 2019 16:40:01 +0000
+Subject: [PATCH 330/725] staging: bcm2835-codec: variable vb2 may be used
+ uninitialised
+
+In op_buffer_cb, the failure path checked whether there was
+an associated vb2 buffer before the variable vb2 had been
+assigned.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -634,6 +634,9 @@ static void op_buffer_cb(struct vchiq_mm
+ __func__, status, mmal_buf, mmal_buf->length,
+ mmal_buf->mmal_flags, mmal_buf->pts);
+
++ buf = container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
++ vb2 = &buf->m2m.vb;
++
+ if (status) {
+ /* error in transfer */
+ if (vb2) {
+@@ -658,9 +661,6 @@ static void op_buffer_cb(struct vchiq_mm
+ return;
+ }
+
+- buf = container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
+- vb2 = &buf->m2m.vb;
+-
+ v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: length %lu, flags %x, idx %u\n",
+ __func__, mmal_buf->length, mmal_buf->mmal_flags,
+ vb2->vb2_buf.index);
+++ /dev/null
-From 6fcdc4686f212cb572a0b93a293f6b6fb2a49992 Mon Sep 17 00:00:00 2001
-From: Matt Flax <flatmax@flatmax.org>
-Date: Tue, 29 Jan 2019 14:56:03 +1100
-Subject: [PATCH 331/703] audioinjector-octo: revert to dummy supplies
-
-The Audio Injector Octo has had a lot of reports of not coming up on power cycles. By reverting to dummy supplies, the card comes up reliably.
----
- arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts | 4 ----
- 1 file changed, 4 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
-@@ -25,10 +25,6 @@
- reg = <0x48>;
- clocks = <&cs42448_mclk>;
- clock-names = "mclk";
-- VA-supply = <&vdd_5v0_reg>;
-- VD-supply = <&vdd_3v3_reg>;
-- VLS-supply = <&vdd_3v3_reg>;
-- VLC-supply = <&vdd_3v3_reg>;
- status = "okay";
- };
-
--- /dev/null
+From ba444bcaef82a4ffb43d6400459b213c9c696566 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 24 Jan 2019 16:36:19 +0000
+Subject: [PATCH 331/725] staging: bcm2835-codec: Fix potentially uninitialised
+ vars
+
+src_m2m_buf and dst_m2m_buf were printed in log messages
+when there are code paths that don't initialise them.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -743,7 +743,7 @@ static void device_run(void *priv)
+ struct bcm2835_codec_ctx *ctx = priv;
+ struct bcm2835_codec_dev *dev = ctx->dev;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
+- struct m2m_mmal_buffer *src_m2m_buf, *dst_m2m_buf;
++ struct m2m_mmal_buffer *src_m2m_buf = NULL, *dst_m2m_buf = NULL;
+ struct v4l2_m2m_buffer *m2m;
+ int ret;
+
+++ /dev/null
-From 0bdc8ddc14e97955e91c999b42f90f420a190027 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 24 Jan 2019 16:20:38 +0000
-Subject: [PATCH 332/703] staging: bcm2835-camera: Correct ctrl
- min/max/step/def to 64bit
-
-The V4L2 control API was expanded to take 64 bit values in commit
-0ba2aeb6dab (Apr 16 2014), but as this driver wasn't in the mainline
-kernel at that point this was overlooked.
-
-Update to use 64 bit values. This also fixes a couple of warnings
-in 64 bit builds.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-camera/controls.c | 14 +++++++-------
- 1 file changed, 7 insertions(+), 7 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
-+++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
-@@ -78,10 +78,10 @@ struct bm2835_mmal_v4l2_ctrl {
- /* 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 */
-+ s64 min;
-+ s64 max; /* maximum value of control */
-+ s64 def; /* default value of control */
-+ u64 step; /* step size of the control */
- const s64 *imenu; /* integer menu array */
- u32 mmal_id; /* mmal parameter id */
- bm2835_mmal_v4l2_ctrl_cb *setter;
-@@ -1244,7 +1244,7 @@ int bm2835_mmal_init_controls(struct bm2
-
- case MMAL_CONTROL_TYPE_STD_MENU:
- {
-- int mask = ctrl->min;
-+ u64 mask = ctrl->min;
-
- if (ctrl->id == V4L2_CID_SCENE_MODE) {
- /* Special handling to work out the mask
-@@ -1254,11 +1254,11 @@ int bm2835_mmal_init_controls(struct bm2
- */
- int i;
-
-- mask = 1 << V4L2_SCENE_MODE_NONE;
-+ mask = BIT(V4L2_SCENE_MODE_NONE);
- for (i = 0;
- i < ARRAY_SIZE(scene_configs);
- i++) {
-- mask |= 1 << scene_configs[i].v4l2_scene;
-+ mask |= BIT(scene_configs[i].v4l2_scene);
- }
- mask = ~mask;
- }
--- /dev/null
+From de3edf2e5a0d2f8c9d20b8449e91d086ccf0514b Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 25 Jan 2019 17:12:54 +0000
+Subject: [PATCH 332/725] video: bcm2708_fb: Add compat_ioctl support.
+
+When using a 64 bit kernel with 32 bit userspace we need
+compat ioctl handling for FBIODMACOPY as one of the
+parameters is a pointer.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/video/fbdev/bcm2708_fb.c | 87 ++++++++++++++++++++++++--------
+ 1 file changed, 66 insertions(+), 21 deletions(-)
+
+--- a/drivers/video/fbdev/bcm2708_fb.c
++++ b/drivers/video/fbdev/bcm2708_fb.c
+@@ -482,9 +482,8 @@ static void dma_memcpy(struct bcm2708_fb
+ /* cache coherent but non-allocating in L1 and L2 */
+ #define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000)
+
+-static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg)
++static long vc_mem_copy(struct bcm2708_fb *fb, struct fb_dmacopy *ioparam)
+ {
+- struct fb_dmacopy ioparam;
+ size_t size = PAGE_SIZE;
+ u32 *buf = NULL;
+ dma_addr_t bus_addr;
+@@ -497,26 +496,16 @@ static long vc_mem_copy(struct bcm2708_f
+ goto out;
+ }
+
+- /* Get the parameter data.
+- */
+- if (copy_from_user
+- (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
+- pr_err("[%s]: failed to copy-from-user\n",
+- __func__);
+- rc = -EFAULT;
+- goto out;
+- }
+-
+- if (fb->gpu.base == 0 || fb->gpu.length == 0) {
++ if (!fb->gpu.base || !fb->gpu.length) {
+ pr_err("[%s]: Unable to determine gpu memory (%x,%x)\n",
+ __func__, fb->gpu.base, fb->gpu.length);
+ return -EFAULT;
+ }
+
+- if (INTALIAS_NORMAL(ioparam.src) < fb->gpu.base ||
+- INTALIAS_NORMAL(ioparam.src) >= fb->gpu.base + fb->gpu.length) {
++ if (INTALIAS_NORMAL(ioparam->src) < fb->gpu.base ||
++ INTALIAS_NORMAL(ioparam->src) >= fb->gpu.base + fb->gpu.length) {
+ pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__,
+- INTALIAS_NORMAL(ioparam.src), fb->gpu.base,
++ INTALIAS_NORMAL(ioparam->src), fb->gpu.base,
+ fb->gpu.base + fb->gpu.length);
+ return -EFAULT;
+ }
+@@ -530,11 +519,11 @@ static long vc_mem_copy(struct bcm2708_f
+ goto out;
+ }
+
+- for (offset = 0; offset < ioparam.length; offset += size) {
+- size_t remaining = ioparam.length - offset;
++ for (offset = 0; offset < ioparam->length; offset += size) {
++ size_t remaining = ioparam->length - offset;
+ size_t s = min(size, remaining);
+- unsigned char *p = (unsigned char *)ioparam.src + offset;
+- unsigned char *q = (unsigned char *)ioparam.dst + offset;
++ u8 *p = (u8 *)((uintptr_t)ioparam->src + offset);
++ u8 *q = (u8 *)ioparam->dst + offset;
+
+ dma_memcpy(fb, bus_addr,
+ INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size);
+@@ -566,8 +555,19 @@ static int bcm2708_ioctl(struct fb_info
+ &dummy, sizeof(dummy));
+ break;
+ case FBIODMACOPY:
+- ret = vc_mem_copy(fb, arg);
++ {
++ struct fb_dmacopy ioparam;
++ /* Get the parameter data.
++ */
++ if (copy_from_user
++ (&ioparam, (void *)arg, sizeof(ioparam))) {
++ pr_err("[%s]: failed to copy-from-user\n", __func__);
++ ret = -EFAULT;
++ break;
++ }
++ ret = vc_mem_copy(fb, &ioparam);
+ break;
++ }
+ default:
+ dev_dbg(info->device, "Unknown ioctl 0x%x\n", cmd);
+ return -ENOTTY;
+@@ -578,6 +578,48 @@ static int bcm2708_ioctl(struct fb_info
+
+ return ret;
+ }
++
++#ifdef CONFIG_COMPAT
++struct fb_dmacopy32 {
++ compat_uptr_t dst;
++ __u32 src;
++ __u32 length;
++};
++
++#define FBIODMACOPY32 _IOW('z', 0x22, struct fb_dmacopy32)
++
++static int bcm2708_compat_ioctl(struct fb_info *info, unsigned int cmd,
++ unsigned long arg)
++{
++ struct bcm2708_fb *fb = to_bcm2708(info);
++ int ret;
++
++ switch (cmd) {
++ case FBIODMACOPY32:
++ {
++ struct fb_dmacopy32 param32;
++ struct fb_dmacopy param;
++ /* Get the parameter data.
++ */
++ if (copy_from_user(¶m32, (void *)arg, sizeof(param32))) {
++ pr_err("[%s]: failed to copy-from-user\n", __func__);
++ ret = -EFAULT;
++ break;
++ }
++ param.dst = compat_ptr(param32.dst);
++ param.src = param32.src;
++ param.length = param32.length;
++ ret = vc_mem_copy(fb, ¶m);
++ break;
++ }
++ default:
++ ret = bcm2708_ioctl(info, cmd, arg);
++ break;
++ }
++ return ret;
++}
++#endif
++
+ static void bcm2708_fb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect)
+ {
+@@ -768,6 +810,9 @@ static struct fb_ops bcm2708_fb_ops = {
+ .fb_imageblit = bcm2708_fb_imageblit,
+ .fb_pan_display = bcm2708_fb_pan_display,
+ .fb_ioctl = bcm2708_ioctl,
++#ifdef CONFIG_COMPAT
++ .fb_compat_ioctl = bcm2708_compat_ioctl,
++#endif
+ };
+
+ static int bcm2708_fb_register(struct bcm2708_fb *fb)
+++ /dev/null
-From e53e03707c6de4230a67633e5eb534e244d21b9e Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 24 Jan 2019 16:40:01 +0000
-Subject: [PATCH 333/703] staging: bcm2835-codec: variable vb2 may be used
- uninitialised
-
-In op_buffer_cb, the failure path checked whether there was
-an associated vb2 buffer before the variable vb2 had been
-assigned.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -634,6 +634,9 @@ static void op_buffer_cb(struct vchiq_mm
- __func__, status, mmal_buf, mmal_buf->length,
- mmal_buf->mmal_flags, mmal_buf->pts);
-
-+ buf = container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
-+ vb2 = &buf->m2m.vb;
-+
- if (status) {
- /* error in transfer */
- if (vb2) {
-@@ -658,9 +661,6 @@ static void op_buffer_cb(struct vchiq_mm
- return;
- }
-
-- buf = container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
-- vb2 = &buf->m2m.vb;
--
- v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: length %lu, flags %x, idx %u\n",
- __func__, mmal_buf->length, mmal_buf->mmal_flags,
- vb2->vb2_buf.index);
--- /dev/null
+From adc3f3ca7e12a464413ccb451cdcd928a1018229 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 25 Jan 2019 17:11:39 +0000
+Subject: [PATCH 333/725] video: bcm2708_fb: Fix warnings on 64 bit builds
+
+Fix up logging lines where the wrong format specifiers were
+being used.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/video/fbdev/bcm2708_fb.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/drivers/video/fbdev/bcm2708_fb.c
++++ b/drivers/video/fbdev/bcm2708_fb.c
+@@ -513,8 +513,8 @@ static long vc_mem_copy(struct bcm2708_f
+ buf = dma_alloc_coherent(fb->fb.device, PAGE_ALIGN(size), &bus_addr,
+ GFP_ATOMIC);
+ if (!buf) {
+- pr_err("[%s]: failed to dma_alloc_coherent(%d)\n",
+- __func__, size);
++ pr_err("[%s]: failed to dma_alloc_coherent(%zd)\n", __func__,
++ size);
+ rc = -ENOMEM;
+ goto out;
+ }
+@@ -910,8 +910,7 @@ static int bcm2708_fb_probe(struct platf
+ goto free_fb;
+ }
+
+- pr_info("BCM2708FB: allocated DMA memory %08x\n",
+- fb->cb_handle);
++ pr_info("BCM2708FB: allocated DMA memory %pad\n", &fb->cb_handle);
+
+ ret = bcm_dma_chan_alloc(BCM_DMA_FEATURE_BULK,
+ &fb->dma_chan_base, &fb->dma_irq);
+@@ -929,8 +928,7 @@ static int bcm2708_fb_probe(struct platf
+ }
+
+
+- pr_info("BCM2708FB: allocated DMA channel %d @ %p\n",
+- fb->dma_chan, fb->dma_chan_base);
++ pr_info("BCM2708FB: allocated DMA channel %d\n", fb->dma_chan);
+
+ fb->dev = dev;
+ fb->fb.device = &dev->dev;
+++ /dev/null
-From ee043e469252c42db198e66f4e4c290dcd48d4a0 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 24 Jan 2019 16:36:19 +0000
-Subject: [PATCH 334/703] staging: bcm2835-codec: Fix potentially uninitialised
- vars
-
-src_m2m_buf and dst_m2m_buf were printed in log messages
-when there are code paths that don't initialise them.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -743,7 +743,7 @@ static void device_run(void *priv)
- struct bcm2835_codec_ctx *ctx = priv;
- struct bcm2835_codec_dev *dev = ctx->dev;
- struct vb2_v4l2_buffer *src_buf, *dst_buf;
-- struct m2m_mmal_buffer *src_m2m_buf, *dst_m2m_buf;
-+ struct m2m_mmal_buffer *src_m2m_buf = NULL, *dst_m2m_buf = NULL;
- struct v4l2_m2m_buffer *m2m;
- int ret;
-
--- /dev/null
+From 48ec221a8e6a5f8386e4b5346ca5bc89651588a2 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 25 Jan 2019 17:32:54 +0000
+Subject: [PATCH 334/725] video: bcm2708_fb: Clean up coding style issues
+
+Now checkpatch clean except for 2 long lines, missing
+SPDX header, and no DT documentation.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/video/fbdev/bcm2708_fb.c | 96 ++++++++++++++------------------
+ 1 file changed, 42 insertions(+), 54 deletions(-)
+
+--- a/drivers/video/fbdev/bcm2708_fb.c
++++ b/drivers/video/fbdev/bcm2708_fb.c
+@@ -41,7 +41,7 @@
+ #define MODULE_NAME "bcm2708_fb"
+
+ #ifdef BCM2708_FB_DEBUG
+-#define print_debug(fmt, ...) pr_debug("%s:%s:%d: "fmt, \
++#define print_debug(fmt, ...) pr_debug("%s:%s:%d: " fmt, \
+ MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)
+ #else
+ #define print_debug(fmt, ...)
+@@ -57,7 +57,7 @@ static int fbheight = 480; /* module par
+ static int fbdepth = 32; /* module parameter */
+ static int fbswap; /* module parameter */
+
+-static u32 dma_busy_wait_threshold = 1<<15;
++static u32 dma_busy_wait_threshold = 1 << 15;
+ module_param(dma_busy_wait_threshold, int, 0644);
+ MODULE_PARM_DESC(dma_busy_wait_threshold, "Busy-wait for DMA completion below this area");
+
+@@ -132,8 +132,8 @@ static int bcm2708_fb_debugfs_init(struc
+ fb->stats.regset.nregs = ARRAY_SIZE(stats_registers);
+ fb->stats.regset.base = &fb->stats;
+
+- if (!debugfs_create_regset32(
+- "stats", 0444, fb->debugfs_dir, &fb->stats.regset)) {
++ if (!debugfs_create_regset32("stats", 0444, fb->debugfs_dir,
++ &fb->stats.regset)) {
+ pr_warn("%s: could not create statistics registers\n",
+ __func__);
+ goto fail;
+@@ -223,25 +223,22 @@ static int bcm2708_fb_check_var(struct f
+ {
+ /* info input, var output */
+ print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n",
+- __func__,
+- info,
+- info->var.xres, info->var.yres, info->var.xres_virtual,
+- info->var.yres_virtual, (int)info->screen_size,
+- info->var.bits_per_pixel);
+- print_debug("%s(%p) %dx%d (%dx%d), %d\n", __func__, var,
+- var->xres, var->yres, var->xres_virtual, var->yres_virtual,
+- var->bits_per_pixel);
++ __func__, info, info->var.xres, info->var.yres,
++ info->var.xres_virtual, info->var.yres_virtual,
++ (int)info->screen_size, info->var.bits_per_pixel);
++ print_debug("%s(%p) %dx%d (%dx%d), %d\n", __func__, var, var->xres,
++ var->yres, var->xres_virtual, var->yres_virtual,
++ var->bits_per_pixel);
+
+ if (!var->bits_per_pixel)
+ var->bits_per_pixel = 16;
+
+ if (bcm2708_fb_set_bitfields(var) != 0) {
+ pr_err("%s: invalid bits_per_pixel %d\n", __func__,
+- var->bits_per_pixel);
++ var->bits_per_pixel);
+ return -EINVAL;
+ }
+
+-
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
+ /* use highest possible virtual resolution */
+@@ -249,7 +246,7 @@ static int bcm2708_fb_check_var(struct f
+ var->yres_virtual = 480;
+
+ pr_err("%s: virtual resolution set to maximum of %dx%d\n",
+- __func__, var->xres_virtual, var->yres_virtual);
++ __func__, var->xres_virtual, var->yres_virtual);
+ }
+ if (var->yres_virtual < var->yres)
+ var->yres_virtual = var->yres;
+@@ -294,9 +291,9 @@ static int bcm2708_fb_set_par(struct fb_
+ int ret;
+
+ print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
+- info->var.xres, info->var.yres, info->var.xres_virtual,
+- info->var.yres_virtual, (int)info->screen_size,
+- info->var.bits_per_pixel);
++ info->var.xres, info->var.yres, info->var.xres_virtual,
++ info->var.yres_virtual, (int)info->screen_size,
++ info->var.bits_per_pixel);
+
+ ret = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo));
+ if (ret) {
+@@ -328,12 +325,10 @@ static int bcm2708_fb_set_par(struct fb_
+ return -ENOMEM;
+ }
+
+- print_debug(
+- "%s: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d\n",
+- __func__,
+- (void *)fb->fb.screen_base, (void *)fb->fb_bus_address,
+- fbinfo.xres, fbinfo.yres, fbinfo.bpp,
+- fbinfo.pitch, (int)fb->fb.screen_size);
++ print_debug("%s: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d\n",
++ __func__, (void *)fb->fb.screen_base,
++ (void *)fb->fb_bus_address, fbinfo.xres, fbinfo.yres,
++ fbinfo.bpp, fbinfo.pitch, (int)fb->fb.screen_size);
+
+ return 0;
+ }
+@@ -345,7 +340,6 @@ static inline u32 convert_bitfield(int v
+ return (val >> (16 - bf->length) & mask) << bf->offset;
+ }
+
+-
+ static int bcm2708_fb_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp, struct fb_info *info)
+@@ -379,11 +373,11 @@ static int bcm2708_fb_setcolreg(unsigned
+ packet->offset = 0;
+ packet->length = regno + 1;
+ memcpy(packet->cmap, fb->gpu_cmap,
+- sizeof(packet->cmap));
++ sizeof(packet->cmap));
+ ret = rpi_firmware_property(fb->fw,
+- RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE,
+- packet,
+- (2 + packet->length) * sizeof(u32));
++ RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE,
++ packet,
++ (2 + packet->length) * sizeof(u32));
+ if (ret || packet->offset)
+ dev_err(info->device,
+ "Failed to set palette (%d,%u)\n",
+@@ -392,9 +386,9 @@ static int bcm2708_fb_setcolreg(unsigned
+ }
+ } else if (regno < 16) {
+ fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
+- convert_bitfield(blue, &fb->fb.var.blue) |
+- convert_bitfield(green, &fb->fb.var.green) |
+- convert_bitfield(red, &fb->fb.var.red);
++ convert_bitfield(blue, &fb->fb.var.blue) |
++ convert_bitfield(green, &fb->fb.var.green) |
++ convert_bitfield(red, &fb->fb.var.red);
+ }
+ return regno > 255;
+ }
+@@ -437,8 +431,8 @@ static int bcm2708_fb_pan_display(struct
+ info->var.yoffset = var->yoffset;
+ result = bcm2708_fb_set_par(info);
+ if (result != 0)
+- pr_err("%s(%d,%d) returns=%d\n", __func__,
+- var->xoffset, var->yoffset, result);
++ pr_err("%s(%d,%d) returns=%d\n", __func__, var->xoffset,
++ var->yoffset, result);
+ return result;
+ }
+
+@@ -468,9 +462,8 @@ static void dma_memcpy(struct bcm2708_fb
+ cb->info |= BCM2708_DMA_INT_EN;
+ bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
+ while (bcm_dma_is_busy(dma_chan)) {
+- wait_event_interruptible(
+- fb->dma_waitq,
+- !bcm_dma_is_busy(dma_chan));
++ wait_event_interruptible(fb->dma_waitq,
++ !bcm_dma_is_busy(dma_chan));
+ }
+ fb->stats.dma_irqs++;
+ }
+@@ -478,9 +471,9 @@ static void dma_memcpy(struct bcm2708_fb
+ }
+
+ /* address with no aliases */
+-#define INTALIAS_NORMAL(x) ((x)&~0xc0000000)
++#define INTALIAS_NORMAL(x) ((x) & ~0xc0000000)
+ /* cache coherent but non-allocating in L1 and L2 */
+-#define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000)
++#define INTALIAS_L1L2_NONALLOCATING(x) (((x) & ~0xc0000000) | 0x80000000)
+
+ static long vc_mem_copy(struct bcm2708_fb *fb, struct fb_dmacopy *ioparam)
+ {
+@@ -498,15 +491,15 @@ static long vc_mem_copy(struct bcm2708_f
+
+ if (!fb->gpu.base || !fb->gpu.length) {
+ pr_err("[%s]: Unable to determine gpu memory (%x,%x)\n",
+- __func__, fb->gpu.base, fb->gpu.length);
++ __func__, fb->gpu.base, fb->gpu.length);
+ return -EFAULT;
+ }
+
+ if (INTALIAS_NORMAL(ioparam->src) < fb->gpu.base ||
+ INTALIAS_NORMAL(ioparam->src) >= fb->gpu.base + fb->gpu.length) {
+ pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__,
+- INTALIAS_NORMAL(ioparam->src), fb->gpu.base,
+- fb->gpu.base + fb->gpu.length);
++ INTALIAS_NORMAL(ioparam->src), fb->gpu.base,
++ fb->gpu.base + fb->gpu.length);
+ return -EFAULT;
+ }
+
+@@ -528,8 +521,7 @@ static long vc_mem_copy(struct bcm2708_f
+ dma_memcpy(fb, bus_addr,
+ INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size);
+ if (copy_to_user(q, buf, s) != 0) {
+- pr_err("[%s]: failed to copy-to-user\n",
+- __func__);
++ pr_err("[%s]: failed to copy-to-user\n", __func__);
+ rc = -EFAULT;
+ goto out;
+ }
+@@ -755,7 +747,6 @@ static void bcm2708_fb_copyarea(struct f
+ /* end of dma control blocks chain */
+ cb->next = 0;
+
+-
+ if (pixels < dma_busy_wait_threshold) {
+ bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
+ bcm_dma_wait_idle(fb->dma_chan_base);
+@@ -765,9 +756,8 @@ static void bcm2708_fb_copyarea(struct f
+ cb->info |= BCM2708_DMA_INT_EN;
+ bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
+ while (bcm_dma_is_busy(dma_chan)) {
+- wait_event_interruptible(
+- fb->dma_waitq,
+- !bcm_dma_is_busy(dma_chan));
++ wait_event_interruptible(fb->dma_waitq,
++ !bcm_dma_is_busy(dma_chan));
+ }
+ fb->stats.dma_irqs++;
+ }
+@@ -863,7 +853,7 @@ static int bcm2708_fb_register(struct bc
+ return ret;
+
+ print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n",
+- fbwidth, fbheight, fbdepth, fbswap);
++ fbwidth, fbheight, fbdepth, fbswap);
+
+ ret = register_framebuffer(&fb->fb);
+ print_debug("BCM2708FB: register framebuffer (%d)\n", ret);
+@@ -893,7 +883,7 @@ static int bcm2708_fb_probe(struct platf
+ if (!fw)
+ return -EPROBE_DEFER;
+
+- fb = kzalloc(sizeof(struct bcm2708_fb), GFP_KERNEL);
++ fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+ if (!fb) {
+ ret = -ENOMEM;
+ goto free_region;
+@@ -927,7 +917,6 @@ static int bcm2708_fb_probe(struct platf
+ goto free_dma_chan;
+ }
+
+-
+ pr_info("BCM2708FB: allocated DMA channel %d\n", fb->dma_chan);
+
+ fb->dev = dev;
+@@ -936,9 +925,8 @@ static int bcm2708_fb_probe(struct platf
+ /* failure here isn't fatal, but we'll fail in vc_mem_copy if
+ * fb->gpu is not valid
+ */
+- rpi_firmware_property(fb->fw,
+- RPI_FIRMWARE_GET_VC_MEMORY,
+- &fb->gpu, sizeof(fb->gpu));
++ rpi_firmware_property(fb->fw, RPI_FIRMWARE_GET_VC_MEMORY, &fb->gpu,
++ sizeof(fb->gpu));
+
+ ret = bcm2708_fb_register(fb);
+ if (ret == 0) {
--- /dev/null
+From 579a73d009e45d7078246d01e5f311a79d04d291 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 20 Jul 2018 22:03:41 +0100
+Subject: [PATCH 335/725] bcm2835-dma: Add support for per-channel flags
+
+Add the ability to interpret the high bits of the dreq specifier as
+flags to be included in the DMA_CS register. The motivation for this
+change is the ability to set the DISDEBUG flag for SD card transfers
+to avoid corruption when using the VPU debugger.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/dma/bcm2835-dma.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/dma/bcm2835-dma.c
++++ b/drivers/dma/bcm2835-dma.c
+@@ -146,6 +146,10 @@ struct bcm2835_desc {
+ #define BCM2835_DMA_S_DREQ BIT(10) /* enable SREQ for source */
+ #define BCM2835_DMA_S_IGNORE BIT(11) /* ignore source reads - read 0 */
+ #define BCM2835_DMA_BURST_LENGTH(x) ((x & 15) << 12)
++#define BCM2835_DMA_CS_FLAGS(x) (x & (BCM2835_DMA_PRIORITY(15) | \
++ BCM2835_DMA_PANIC_PRIORITY(15) | \
++ BCM2835_DMA_WAIT_FOR_WRITES | \
++ BCM2835_DMA_DIS_DEBUG))
+ #define BCM2835_DMA_PER_MAP(x) ((x & 31) << 16) /* REQ source */
+ #define BCM2835_DMA_WAIT(x) ((x & 31) << 21) /* add DMA-wait cycles */
+ #define BCM2835_DMA_NO_WIDE_BURSTS BIT(26) /* no 2 beat write bursts */
+@@ -461,7 +465,8 @@ static void bcm2835_dma_start_desc(struc
+ c->desc = d = to_bcm2835_dma_desc(&vd->tx);
+
+ writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
+- writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS);
++ writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq),
++ c->chan_base + BCM2835_DMA_CS);
+ }
+
+ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
+@@ -488,7 +493,8 @@ static irqreturn_t bcm2835_dma_callback(
+ * if this IRQ handler is threaded.) If the channel is finished, it
+ * will remain idle despite the ACTIVE flag being set.
+ */
+- writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE,
++ writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE |
++ BCM2835_DMA_CS_FLAGS(c->dreq),
+ c->chan_base + BCM2835_DMA_CS);
+
+ d = c->desc;
+++ /dev/null
-From 5bdb5d6229725a096d7ded73a47034d8bb7f70be Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 25 Jan 2019 17:12:54 +0000
-Subject: [PATCH 335/703] video: bcm2708_fb: Add compat_ioctl support.
-
-When using a 64 bit kernel with 32 bit userspace we need
-compat ioctl handling for FBIODMACOPY as one of the
-parameters is a pointer.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/video/fbdev/bcm2708_fb.c | 87 ++++++++++++++++++++++++--------
- 1 file changed, 66 insertions(+), 21 deletions(-)
-
---- a/drivers/video/fbdev/bcm2708_fb.c
-+++ b/drivers/video/fbdev/bcm2708_fb.c
-@@ -482,9 +482,8 @@ static void dma_memcpy(struct bcm2708_fb
- /* cache coherent but non-allocating in L1 and L2 */
- #define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000)
-
--static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg)
-+static long vc_mem_copy(struct bcm2708_fb *fb, struct fb_dmacopy *ioparam)
- {
-- struct fb_dmacopy ioparam;
- size_t size = PAGE_SIZE;
- u32 *buf = NULL;
- dma_addr_t bus_addr;
-@@ -497,26 +496,16 @@ static long vc_mem_copy(struct bcm2708_f
- goto out;
- }
-
-- /* Get the parameter data.
-- */
-- if (copy_from_user
-- (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
-- pr_err("[%s]: failed to copy-from-user\n",
-- __func__);
-- rc = -EFAULT;
-- goto out;
-- }
--
-- if (fb->gpu.base == 0 || fb->gpu.length == 0) {
-+ if (!fb->gpu.base || !fb->gpu.length) {
- pr_err("[%s]: Unable to determine gpu memory (%x,%x)\n",
- __func__, fb->gpu.base, fb->gpu.length);
- return -EFAULT;
- }
-
-- if (INTALIAS_NORMAL(ioparam.src) < fb->gpu.base ||
-- INTALIAS_NORMAL(ioparam.src) >= fb->gpu.base + fb->gpu.length) {
-+ if (INTALIAS_NORMAL(ioparam->src) < fb->gpu.base ||
-+ INTALIAS_NORMAL(ioparam->src) >= fb->gpu.base + fb->gpu.length) {
- pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__,
-- INTALIAS_NORMAL(ioparam.src), fb->gpu.base,
-+ INTALIAS_NORMAL(ioparam->src), fb->gpu.base,
- fb->gpu.base + fb->gpu.length);
- return -EFAULT;
- }
-@@ -530,11 +519,11 @@ static long vc_mem_copy(struct bcm2708_f
- goto out;
- }
-
-- for (offset = 0; offset < ioparam.length; offset += size) {
-- size_t remaining = ioparam.length - offset;
-+ for (offset = 0; offset < ioparam->length; offset += size) {
-+ size_t remaining = ioparam->length - offset;
- size_t s = min(size, remaining);
-- unsigned char *p = (unsigned char *)ioparam.src + offset;
-- unsigned char *q = (unsigned char *)ioparam.dst + offset;
-+ u8 *p = (u8 *)((uintptr_t)ioparam->src + offset);
-+ u8 *q = (u8 *)ioparam->dst + offset;
-
- dma_memcpy(fb, bus_addr,
- INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size);
-@@ -566,8 +555,19 @@ static int bcm2708_ioctl(struct fb_info
- &dummy, sizeof(dummy));
- break;
- case FBIODMACOPY:
-- ret = vc_mem_copy(fb, arg);
-+ {
-+ struct fb_dmacopy ioparam;
-+ /* Get the parameter data.
-+ */
-+ if (copy_from_user
-+ (&ioparam, (void *)arg, sizeof(ioparam))) {
-+ pr_err("[%s]: failed to copy-from-user\n", __func__);
-+ ret = -EFAULT;
-+ break;
-+ }
-+ ret = vc_mem_copy(fb, &ioparam);
- break;
-+ }
- default:
- dev_dbg(info->device, "Unknown ioctl 0x%x\n", cmd);
- return -ENOTTY;
-@@ -578,6 +578,48 @@ static int bcm2708_ioctl(struct fb_info
-
- return ret;
- }
-+
-+#ifdef CONFIG_COMPAT
-+struct fb_dmacopy32 {
-+ compat_uptr_t dst;
-+ __u32 src;
-+ __u32 length;
-+};
-+
-+#define FBIODMACOPY32 _IOW('z', 0x22, struct fb_dmacopy32)
-+
-+static int bcm2708_compat_ioctl(struct fb_info *info, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ struct bcm2708_fb *fb = to_bcm2708(info);
-+ int ret;
-+
-+ switch (cmd) {
-+ case FBIODMACOPY32:
-+ {
-+ struct fb_dmacopy32 param32;
-+ struct fb_dmacopy param;
-+ /* Get the parameter data.
-+ */
-+ if (copy_from_user(¶m32, (void *)arg, sizeof(param32))) {
-+ pr_err("[%s]: failed to copy-from-user\n", __func__);
-+ ret = -EFAULT;
-+ break;
-+ }
-+ param.dst = compat_ptr(param32.dst);
-+ param.src = param32.src;
-+ param.length = param32.length;
-+ ret = vc_mem_copy(fb, ¶m);
-+ break;
-+ }
-+ default:
-+ ret = bcm2708_ioctl(info, cmd, arg);
-+ break;
-+ }
-+ return ret;
-+}
-+#endif
-+
- static void bcm2708_fb_fillrect(struct fb_info *info,
- const struct fb_fillrect *rect)
- {
-@@ -768,6 +810,9 @@ static struct fb_ops bcm2708_fb_ops = {
- .fb_imageblit = bcm2708_fb_imageblit,
- .fb_pan_display = bcm2708_fb_pan_display,
- .fb_ioctl = bcm2708_ioctl,
-+#ifdef CONFIG_COMPAT
-+ .fb_compat_ioctl = bcm2708_compat_ioctl,
-+#endif
- };
-
- static int bcm2708_fb_register(struct bcm2708_fb *fb)
--- /dev/null
+From b8c21591d254d10e730b40eb0b1bc87dfbe7cd4b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 20 Jul 2018 22:08:05 +0100
+Subject: [PATCH 336/725] bcm283x: Set the DISDEBUG flag for SD transfers
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm283x.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -400,7 +400,7 @@
+ reg = <0x7e202000 0x100>;
+ interrupts = <2 24>;
+ clocks = <&clocks BCM2835_CLOCK_VPU>;
+- dmas = <&dma 13>;
++ dmas = <&dma (13|(1<<29))>;
+ dma-names = "rx-tx";
+ status = "disabled";
+ };
+++ /dev/null
-From 3695125662f57ce208b6769418bcda80bedbd5b6 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 25 Jan 2019 17:11:39 +0000
-Subject: [PATCH 336/703] video: bcm2708_fb: Fix warnings on 64 bit builds
-
-Fix up logging lines where the wrong format specifiers were
-being used.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/video/fbdev/bcm2708_fb.c | 10 ++++------
- 1 file changed, 4 insertions(+), 6 deletions(-)
-
---- a/drivers/video/fbdev/bcm2708_fb.c
-+++ b/drivers/video/fbdev/bcm2708_fb.c
-@@ -513,8 +513,8 @@ static long vc_mem_copy(struct bcm2708_f
- buf = dma_alloc_coherent(fb->fb.device, PAGE_ALIGN(size), &bus_addr,
- GFP_ATOMIC);
- if (!buf) {
-- pr_err("[%s]: failed to dma_alloc_coherent(%d)\n",
-- __func__, size);
-+ pr_err("[%s]: failed to dma_alloc_coherent(%zd)\n", __func__,
-+ size);
- rc = -ENOMEM;
- goto out;
- }
-@@ -910,8 +910,7 @@ static int bcm2708_fb_probe(struct platf
- goto free_fb;
- }
-
-- pr_info("BCM2708FB: allocated DMA memory %08x\n",
-- fb->cb_handle);
-+ pr_info("BCM2708FB: allocated DMA memory %pad\n", &fb->cb_handle);
-
- ret = bcm_dma_chan_alloc(BCM_DMA_FEATURE_BULK,
- &fb->dma_chan_base, &fb->dma_irq);
-@@ -929,8 +928,7 @@ static int bcm2708_fb_probe(struct platf
- }
-
-
-- pr_info("BCM2708FB: allocated DMA channel %d @ %p\n",
-- fb->dma_chan, fb->dma_chan_base);
-+ pr_info("BCM2708FB: allocated DMA channel %d\n", fb->dma_chan);
-
- fb->dev = dev;
- fb->fb.device = &dev->dev;
--- /dev/null
+From 911ef52ced060fd14d56d5a2cb816b0732da9b46 Mon Sep 17 00:00:00 2001
+From: Dimitris Papavasiliou <dpapavas@gmail.com>
+Date: Sat, 24 Nov 2018 22:05:42 +0200
+Subject: [PATCH 337/725] ASoC: pcm512x: Implement the digital_mute interface
+
+[ Upstream commit 3500f1c589e92e0b6b1f8d31b4084fbde08d49cb ]
+
+Clicks and pops of various volumes can be produced while the device is
+opened, closed, put into and taken out of standby, or reconfigured.
+Fix this, by implementing the digital_mute interface, so that the
+output is muted during such operations.
+
+Signed-off-by: Dimitris Papavasiliou <dpapavas@gmail.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/pcm512x.c | 121 ++++++++++++++++++++++++++++++++++++-
+ sound/soc/codecs/pcm512x.h | 2 +
+ 2 files changed, 121 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/codecs/pcm512x.c
++++ b/sound/soc/codecs/pcm512x.c
+@@ -53,6 +53,8 @@ struct pcm512x_priv {
+ unsigned long overclock_pll;
+ unsigned long overclock_dac;
+ unsigned long overclock_dsp;
++ int mute;
++ struct mutex mutex;
+ int lrclk_div;
+ };
+
+@@ -385,6 +387,61 @@ static const struct soc_enum pcm512x_ved
+ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4,
+ pcm512x_ramp_step_text);
+
++static int pcm512x_update_mute(struct pcm512x_priv *pcm512x)
++{
++ return regmap_update_bits(
++ pcm512x->regmap, PCM512x_MUTE, PCM512x_RQML | PCM512x_RQMR,
++ (!!(pcm512x->mute & 0x5) << PCM512x_RQML_SHIFT)
++ | (!!(pcm512x->mute & 0x3) << PCM512x_RQMR_SHIFT));
++}
++
++static int pcm512x_digital_playback_switch_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
++ struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
++
++ mutex_lock(&pcm512x->mutex);
++ ucontrol->value.integer.value[0] = !(pcm512x->mute & 0x4);
++ ucontrol->value.integer.value[1] = !(pcm512x->mute & 0x2);
++ mutex_unlock(&pcm512x->mutex);
++
++ return 0;
++}
++
++static int pcm512x_digital_playback_switch_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
++ struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
++ int ret, changed = 0;
++
++ mutex_lock(&pcm512x->mutex);
++
++ if ((pcm512x->mute & 0x4) == (ucontrol->value.integer.value[0] << 2)) {
++ pcm512x->mute ^= 0x4;
++ changed = 1;
++ }
++ if ((pcm512x->mute & 0x2) == (ucontrol->value.integer.value[1] << 1)) {
++ pcm512x->mute ^= 0x2;
++ changed = 1;
++ }
++
++ if (changed) {
++ ret = pcm512x_update_mute(pcm512x);
++ if (ret != 0) {
++ dev_err(component->dev,
++ "Failed to update digital mute: %d\n", ret);
++ mutex_unlock(&pcm512x->mutex);
++ return ret;
++ }
++ }
++
++ mutex_unlock(&pcm512x->mutex);
++
++ return changed;
++}
++
+ static const struct snd_kcontrol_new pcm512x_controls[] = {
+ SOC_DOUBLE_R_TLV("Digital Playback Volume", PCM512x_DIGITAL_VOLUME_2,
+ PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv),
+@@ -392,8 +449,15 @@ SOC_DOUBLE_TLV("Analogue Playback Volume
+ PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv),
+ SOC_DOUBLE_TLV("Analogue Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST,
+ PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv),
+-SOC_DOUBLE("Digital Playback Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT,
+- PCM512x_RQMR_SHIFT, 1, 1),
++{
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Digital Playback Switch",
++ .index = 0,
++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
++ .info = snd_ctl_boolean_stereo_info,
++ .get = pcm512x_digital_playback_switch_get,
++ .put = pcm512x_digital_playback_switch_put
++},
+
+ SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1),
+ SOC_ENUM("DSP Program", pcm512x_dsp_program),
+@@ -1323,6 +1387,56 @@ static int pcm512x_set_fmt(struct snd_so
+ return 0;
+ }
+
++static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
++{
++ struct snd_soc_component *component = dai->component;
++ struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
++ int ret;
++ unsigned int mute_det;
++
++ mutex_lock(&pcm512x->mutex);
++
++ if (mute) {
++ pcm512x->mute |= 0x1;
++ ret = regmap_update_bits(pcm512x->regmap, PCM512x_MUTE,
++ PCM512x_RQML | PCM512x_RQMR,
++ PCM512x_RQML | PCM512x_RQMR);
++ if (ret != 0) {
++ dev_err(component->dev,
++ "Failed to set digital mute: %d\n", ret);
++ mutex_unlock(&pcm512x->mutex);
++ return ret;
++ }
++
++ regmap_read_poll_timeout(pcm512x->regmap,
++ PCM512x_ANALOG_MUTE_DET,
++ mute_det, (mute_det & 0x3) == 0,
++ 200, 10000);
++
++ mutex_unlock(&pcm512x->mutex);
++ } else {
++ pcm512x->mute &= ~0x1;
++ ret = pcm512x_update_mute(pcm512x);
++ if (ret != 0) {
++ dev_err(component->dev,
++ "Failed to update digital mute: %d\n", ret);
++ mutex_unlock(&pcm512x->mutex);
++ return ret;
++ }
++
++ regmap_read_poll_timeout(pcm512x->regmap,
++ PCM512x_ANALOG_MUTE_DET,
++ mute_det,
++ (mute_det & 0x3)
++ == ((~pcm512x->mute >> 1) & 0x3),
++ 200, 10000);
++ }
++
++ mutex_unlock(&pcm512x->mutex);
++
++ return 0;
++}
++
+ static int pcm512x_set_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int tx_mask, unsigned int rx_mask,
+ int slots, int width)
+@@ -1348,6 +1462,7 @@ static const struct snd_soc_dai_ops pcm5
+ .startup = pcm512x_dai_startup,
+ .hw_params = pcm512x_hw_params,
+ .set_fmt = pcm512x_set_fmt,
++ .digital_mute = pcm512x_digital_mute,
+ .set_tdm_slot = pcm512x_set_tdm_slot,
+ };
+
+@@ -1414,6 +1529,8 @@ int pcm512x_probe(struct device *dev, st
+ if (!pcm512x)
+ return -ENOMEM;
+
++ mutex_init(&pcm512x->mutex);
++
+ dev_set_drvdata(dev, pcm512x);
+ pcm512x->regmap = regmap;
+
+--- a/sound/soc/codecs/pcm512x.h
++++ b/sound/soc/codecs/pcm512x.h
+@@ -112,7 +112,9 @@
+ #define PCM512x_RQST_SHIFT 4
+
+ /* Page 0, Register 3 - mute */
++#define PCM512x_RQMR (1 << 0)
+ #define PCM512x_RQMR_SHIFT 0
++#define PCM512x_RQML (1 << 4)
+ #define PCM512x_RQML_SHIFT 4
+
+ /* Page 0, Register 4 - PLL */
+++ /dev/null
-From 9236c0f31f2052bbcd6386367ace3ebfad57da3d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 25 Jan 2019 17:32:54 +0000
-Subject: [PATCH 337/703] video: bcm2708_fb: Clean up coding style issues
-
-Now checkpatch clean except for 2 long lines, missing
-SPDX header, and no DT documentation.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/video/fbdev/bcm2708_fb.c | 96 ++++++++++++++------------------
- 1 file changed, 42 insertions(+), 54 deletions(-)
-
---- a/drivers/video/fbdev/bcm2708_fb.c
-+++ b/drivers/video/fbdev/bcm2708_fb.c
-@@ -41,7 +41,7 @@
- #define MODULE_NAME "bcm2708_fb"
-
- #ifdef BCM2708_FB_DEBUG
--#define print_debug(fmt, ...) pr_debug("%s:%s:%d: "fmt, \
-+#define print_debug(fmt, ...) pr_debug("%s:%s:%d: " fmt, \
- MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)
- #else
- #define print_debug(fmt, ...)
-@@ -57,7 +57,7 @@ static int fbheight = 480; /* module par
- static int fbdepth = 32; /* module parameter */
- static int fbswap; /* module parameter */
-
--static u32 dma_busy_wait_threshold = 1<<15;
-+static u32 dma_busy_wait_threshold = 1 << 15;
- module_param(dma_busy_wait_threshold, int, 0644);
- MODULE_PARM_DESC(dma_busy_wait_threshold, "Busy-wait for DMA completion below this area");
-
-@@ -132,8 +132,8 @@ static int bcm2708_fb_debugfs_init(struc
- fb->stats.regset.nregs = ARRAY_SIZE(stats_registers);
- fb->stats.regset.base = &fb->stats;
-
-- if (!debugfs_create_regset32(
-- "stats", 0444, fb->debugfs_dir, &fb->stats.regset)) {
-+ if (!debugfs_create_regset32("stats", 0444, fb->debugfs_dir,
-+ &fb->stats.regset)) {
- pr_warn("%s: could not create statistics registers\n",
- __func__);
- goto fail;
-@@ -223,25 +223,22 @@ static int bcm2708_fb_check_var(struct f
- {
- /* info input, var output */
- print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n",
-- __func__,
-- info,
-- info->var.xres, info->var.yres, info->var.xres_virtual,
-- info->var.yres_virtual, (int)info->screen_size,
-- info->var.bits_per_pixel);
-- print_debug("%s(%p) %dx%d (%dx%d), %d\n", __func__, var,
-- var->xres, var->yres, var->xres_virtual, var->yres_virtual,
-- var->bits_per_pixel);
-+ __func__, info, info->var.xres, info->var.yres,
-+ info->var.xres_virtual, info->var.yres_virtual,
-+ (int)info->screen_size, info->var.bits_per_pixel);
-+ print_debug("%s(%p) %dx%d (%dx%d), %d\n", __func__, var, var->xres,
-+ var->yres, var->xres_virtual, var->yres_virtual,
-+ var->bits_per_pixel);
-
- if (!var->bits_per_pixel)
- var->bits_per_pixel = 16;
-
- if (bcm2708_fb_set_bitfields(var) != 0) {
- pr_err("%s: invalid bits_per_pixel %d\n", __func__,
-- var->bits_per_pixel);
-+ var->bits_per_pixel);
- return -EINVAL;
- }
-
--
- if (var->xres_virtual < var->xres)
- var->xres_virtual = var->xres;
- /* use highest possible virtual resolution */
-@@ -249,7 +246,7 @@ static int bcm2708_fb_check_var(struct f
- var->yres_virtual = 480;
-
- pr_err("%s: virtual resolution set to maximum of %dx%d\n",
-- __func__, var->xres_virtual, var->yres_virtual);
-+ __func__, var->xres_virtual, var->yres_virtual);
- }
- if (var->yres_virtual < var->yres)
- var->yres_virtual = var->yres;
-@@ -294,9 +291,9 @@ static int bcm2708_fb_set_par(struct fb_
- int ret;
-
- print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
-- info->var.xres, info->var.yres, info->var.xres_virtual,
-- info->var.yres_virtual, (int)info->screen_size,
-- info->var.bits_per_pixel);
-+ info->var.xres, info->var.yres, info->var.xres_virtual,
-+ info->var.yres_virtual, (int)info->screen_size,
-+ info->var.bits_per_pixel);
-
- ret = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo));
- if (ret) {
-@@ -328,12 +325,10 @@ static int bcm2708_fb_set_par(struct fb_
- return -ENOMEM;
- }
-
-- print_debug(
-- "%s: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d\n",
-- __func__,
-- (void *)fb->fb.screen_base, (void *)fb->fb_bus_address,
-- fbinfo.xres, fbinfo.yres, fbinfo.bpp,
-- fbinfo.pitch, (int)fb->fb.screen_size);
-+ print_debug("%s: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d\n",
-+ __func__, (void *)fb->fb.screen_base,
-+ (void *)fb->fb_bus_address, fbinfo.xres, fbinfo.yres,
-+ fbinfo.bpp, fbinfo.pitch, (int)fb->fb.screen_size);
-
- return 0;
- }
-@@ -345,7 +340,6 @@ static inline u32 convert_bitfield(int v
- return (val >> (16 - bf->length) & mask) << bf->offset;
- }
-
--
- static int bcm2708_fb_setcolreg(unsigned int regno, unsigned int red,
- unsigned int green, unsigned int blue,
- unsigned int transp, struct fb_info *info)
-@@ -379,11 +373,11 @@ static int bcm2708_fb_setcolreg(unsigned
- packet->offset = 0;
- packet->length = regno + 1;
- memcpy(packet->cmap, fb->gpu_cmap,
-- sizeof(packet->cmap));
-+ sizeof(packet->cmap));
- ret = rpi_firmware_property(fb->fw,
-- RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE,
-- packet,
-- (2 + packet->length) * sizeof(u32));
-+ RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE,
-+ packet,
-+ (2 + packet->length) * sizeof(u32));
- if (ret || packet->offset)
- dev_err(info->device,
- "Failed to set palette (%d,%u)\n",
-@@ -392,9 +386,9 @@ static int bcm2708_fb_setcolreg(unsigned
- }
- } else if (regno < 16) {
- fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
-- convert_bitfield(blue, &fb->fb.var.blue) |
-- convert_bitfield(green, &fb->fb.var.green) |
-- convert_bitfield(red, &fb->fb.var.red);
-+ convert_bitfield(blue, &fb->fb.var.blue) |
-+ convert_bitfield(green, &fb->fb.var.green) |
-+ convert_bitfield(red, &fb->fb.var.red);
- }
- return regno > 255;
- }
-@@ -437,8 +431,8 @@ static int bcm2708_fb_pan_display(struct
- info->var.yoffset = var->yoffset;
- result = bcm2708_fb_set_par(info);
- if (result != 0)
-- pr_err("%s(%d,%d) returns=%d\n", __func__,
-- var->xoffset, var->yoffset, result);
-+ pr_err("%s(%d,%d) returns=%d\n", __func__, var->xoffset,
-+ var->yoffset, result);
- return result;
- }
-
-@@ -468,9 +462,8 @@ static void dma_memcpy(struct bcm2708_fb
- cb->info |= BCM2708_DMA_INT_EN;
- bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
- while (bcm_dma_is_busy(dma_chan)) {
-- wait_event_interruptible(
-- fb->dma_waitq,
-- !bcm_dma_is_busy(dma_chan));
-+ wait_event_interruptible(fb->dma_waitq,
-+ !bcm_dma_is_busy(dma_chan));
- }
- fb->stats.dma_irqs++;
- }
-@@ -478,9 +471,9 @@ static void dma_memcpy(struct bcm2708_fb
- }
-
- /* address with no aliases */
--#define INTALIAS_NORMAL(x) ((x)&~0xc0000000)
-+#define INTALIAS_NORMAL(x) ((x) & ~0xc0000000)
- /* cache coherent but non-allocating in L1 and L2 */
--#define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000)
-+#define INTALIAS_L1L2_NONALLOCATING(x) (((x) & ~0xc0000000) | 0x80000000)
-
- static long vc_mem_copy(struct bcm2708_fb *fb, struct fb_dmacopy *ioparam)
- {
-@@ -498,15 +491,15 @@ static long vc_mem_copy(struct bcm2708_f
-
- if (!fb->gpu.base || !fb->gpu.length) {
- pr_err("[%s]: Unable to determine gpu memory (%x,%x)\n",
-- __func__, fb->gpu.base, fb->gpu.length);
-+ __func__, fb->gpu.base, fb->gpu.length);
- return -EFAULT;
- }
-
- if (INTALIAS_NORMAL(ioparam->src) < fb->gpu.base ||
- INTALIAS_NORMAL(ioparam->src) >= fb->gpu.base + fb->gpu.length) {
- pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__,
-- INTALIAS_NORMAL(ioparam->src), fb->gpu.base,
-- fb->gpu.base + fb->gpu.length);
-+ INTALIAS_NORMAL(ioparam->src), fb->gpu.base,
-+ fb->gpu.base + fb->gpu.length);
- return -EFAULT;
- }
-
-@@ -528,8 +521,7 @@ static long vc_mem_copy(struct bcm2708_f
- dma_memcpy(fb, bus_addr,
- INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size);
- if (copy_to_user(q, buf, s) != 0) {
-- pr_err("[%s]: failed to copy-to-user\n",
-- __func__);
-+ pr_err("[%s]: failed to copy-to-user\n", __func__);
- rc = -EFAULT;
- goto out;
- }
-@@ -755,7 +747,6 @@ static void bcm2708_fb_copyarea(struct f
- /* end of dma control blocks chain */
- cb->next = 0;
-
--
- if (pixels < dma_busy_wait_threshold) {
- bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
- bcm_dma_wait_idle(fb->dma_chan_base);
-@@ -765,9 +756,8 @@ static void bcm2708_fb_copyarea(struct f
- cb->info |= BCM2708_DMA_INT_EN;
- bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
- while (bcm_dma_is_busy(dma_chan)) {
-- wait_event_interruptible(
-- fb->dma_waitq,
-- !bcm_dma_is_busy(dma_chan));
-+ wait_event_interruptible(fb->dma_waitq,
-+ !bcm_dma_is_busy(dma_chan));
- }
- fb->stats.dma_irqs++;
- }
-@@ -863,7 +853,7 @@ static int bcm2708_fb_register(struct bc
- return ret;
-
- print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n",
-- fbwidth, fbheight, fbdepth, fbswap);
-+ fbwidth, fbheight, fbdepth, fbswap);
-
- ret = register_framebuffer(&fb->fb);
- print_debug("BCM2708FB: register framebuffer (%d)\n", ret);
-@@ -893,7 +883,7 @@ static int bcm2708_fb_probe(struct platf
- if (!fw)
- return -EPROBE_DEFER;
-
-- fb = kzalloc(sizeof(struct bcm2708_fb), GFP_KERNEL);
-+ fb = kzalloc(sizeof(*fb), GFP_KERNEL);
- if (!fb) {
- ret = -ENOMEM;
- goto free_region;
-@@ -927,7 +917,6 @@ static int bcm2708_fb_probe(struct platf
- goto free_dma_chan;
- }
-
--
- pr_info("BCM2708FB: allocated DMA channel %d\n", fb->dma_chan);
-
- fb->dev = dev;
-@@ -936,9 +925,8 @@ static int bcm2708_fb_probe(struct platf
- /* failure here isn't fatal, but we'll fail in vc_mem_copy if
- * fb->gpu is not valid
- */
-- rpi_firmware_property(fb->fw,
-- RPI_FIRMWARE_GET_VC_MEMORY,
-- &fb->gpu, sizeof(fb->gpu));
-+ rpi_firmware_property(fb->fw, RPI_FIRMWARE_GET_VC_MEMORY, &fb->gpu,
-+ sizeof(fb->gpu));
-
- ret = bcm2708_fb_register(fb);
- if (ret == 0) {
--- /dev/null
+From b55252c4bca64c4c9df97b302cd52ffec3ee01b5 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Fri, 21 Dec 2018 12:11:20 +0300
+Subject: [PATCH 338/725] ASoC: pcm512x: Fix a double unlock in
+ pcm512x_digital_mute()
+
+[ Upstream commit 28b698b7342c7d5300cfe217cd77ff7d2a55e03d ]
+
+We accidentally call mutex_unlock(&pcm512x->mutex); twice in a row.
+
+I re-wrote the error handling to use "goto unlock;" instead of returning
+directly. Hopefully, it makes the code a little simpler.
+
+Fixes: 3500f1c589e9 ("ASoC: pcm512x: Implement the digital_mute interface")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Reviwed-by: Dimitris Papavasiliou <dpapavas@gmail.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/pcm512x.c | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+--- a/sound/soc/codecs/pcm512x.c
++++ b/sound/soc/codecs/pcm512x.c
+@@ -1404,24 +1404,20 @@ static int pcm512x_digital_mute(struct s
+ if (ret != 0) {
+ dev_err(component->dev,
+ "Failed to set digital mute: %d\n", ret);
+- mutex_unlock(&pcm512x->mutex);
+- return ret;
++ goto unlock;
+ }
+
+ regmap_read_poll_timeout(pcm512x->regmap,
+ PCM512x_ANALOG_MUTE_DET,
+ mute_det, (mute_det & 0x3) == 0,
+ 200, 10000);
+-
+- mutex_unlock(&pcm512x->mutex);
+ } else {
+ pcm512x->mute &= ~0x1;
+ ret = pcm512x_update_mute(pcm512x);
+ if (ret != 0) {
+ dev_err(component->dev,
+ "Failed to update digital mute: %d\n", ret);
+- mutex_unlock(&pcm512x->mutex);
+- return ret;
++ goto unlock;
+ }
+
+ regmap_read_poll_timeout(pcm512x->regmap,
+@@ -1432,9 +1428,10 @@ static int pcm512x_digital_mute(struct s
+ 200, 10000);
+ }
+
++unlock:
+ mutex_unlock(&pcm512x->mutex);
+
+- return 0;
++ return ret;
+ }
+
+ static int pcm512x_set_tdm_slot(struct snd_soc_dai *dai,
+++ /dev/null
-From f1eb781eb15506a49307cd80ad5b70533622ee68 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 20 Jul 2018 22:03:41 +0100
-Subject: [PATCH 338/703] bcm2835-dma: Add support for per-channel flags
-
-Add the ability to interpret the high bits of the dreq specifier as
-flags to be included in the DMA_CS register. The motivation for this
-change is the ability to set the DISDEBUG flag for SD card transfers
-to avoid corruption when using the VPU debugger.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/dma/bcm2835-dma.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
---- a/drivers/dma/bcm2835-dma.c
-+++ b/drivers/dma/bcm2835-dma.c
-@@ -146,6 +146,10 @@ struct bcm2835_desc {
- #define BCM2835_DMA_S_DREQ BIT(10) /* enable SREQ for source */
- #define BCM2835_DMA_S_IGNORE BIT(11) /* ignore source reads - read 0 */
- #define BCM2835_DMA_BURST_LENGTH(x) ((x & 15) << 12)
-+#define BCM2835_DMA_CS_FLAGS(x) (x & (BCM2835_DMA_PRIORITY(15) | \
-+ BCM2835_DMA_PANIC_PRIORITY(15) | \
-+ BCM2835_DMA_WAIT_FOR_WRITES | \
-+ BCM2835_DMA_DIS_DEBUG))
- #define BCM2835_DMA_PER_MAP(x) ((x & 31) << 16) /* REQ source */
- #define BCM2835_DMA_WAIT(x) ((x & 31) << 21) /* add DMA-wait cycles */
- #define BCM2835_DMA_NO_WIDE_BURSTS BIT(26) /* no 2 beat write bursts */
-@@ -461,7 +465,8 @@ static void bcm2835_dma_start_desc(struc
- c->desc = d = to_bcm2835_dma_desc(&vd->tx);
-
- writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
-- writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS);
-+ writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq),
-+ c->chan_base + BCM2835_DMA_CS);
- }
-
- static irqreturn_t bcm2835_dma_callback(int irq, void *data)
-@@ -488,7 +493,8 @@ static irqreturn_t bcm2835_dma_callback(
- * if this IRQ handler is threaded.) If the channel is finished, it
- * will remain idle despite the ACTIVE flag being set.
- */
-- writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE,
-+ writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE |
-+ BCM2835_DMA_CS_FLAGS(c->dreq),
- c->chan_base + BCM2835_DMA_CS);
-
- d = c->desc;
+++ /dev/null
-From 393156f30a06f1cd3e739e31b92e0f9a62857ea9 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 20 Jul 2018 22:08:05 +0100
-Subject: [PATCH 339/703] bcm283x: Set the DISDEBUG flag for SD transfers
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm283x.dtsi | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/bcm283x.dtsi
-+++ b/arch/arm/boot/dts/bcm283x.dtsi
-@@ -400,7 +400,7 @@
- reg = <0x7e202000 0x100>;
- interrupts = <2 24>;
- clocks = <&clocks BCM2835_CLOCK_VPU>;
-- dmas = <&dma 13>;
-+ dmas = <&dma (13|(1<<29))>;
- dma-names = "rx-tx";
- status = "disabled";
- };
--- /dev/null
+From 12c338acee0c756cbb4c8453882341cc0e8581e7 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 25 Jan 2019 16:03:31 +0000
+Subject: [PATCH 339/725] usb: dwc_otg: Clean up build warnings on 64bit
+ kernels
+
+No functional changes. Almost all are changes to logging lines.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_driver.c | 3 +--
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 2 +-
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 19 ++++++++++++++-----
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 10 ++++------
+ 4 files changed, 20 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
+@@ -837,8 +837,7 @@ static int dwc_otg_driver_probe(
+ retval = -ENOMEM;
+ goto fail;
+ }
+- dev_info(&_dev->dev, "base=0x%08x\n",
+- (unsigned)dwc_otg_device->os_dep.base);
++ dev_info(&_dev->dev, "base=%p\n", dwc_otg_device->os_dep.base);
+ #endif
+
+ /*
+--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
+@@ -301,7 +301,7 @@ static int notrace fiq_iso_out_advance(s
+ last = 1;
+
+ /* New DMA address - address of bounce buffer referred to in index */
+- hcdma.d32 = (uint32_t) &blob->channel[n].index[i].buf[0];
++ hcdma.d32 = (dma_addr_t) blob->channel[n].index[i].buf;
+ //hcdma.d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HC_DMA);
+ //hcdma.d32 += st->channel[n].dma_info.slot_len[i];
+ fiq_print(FIQDBG_INT, st, "LAST: %01d ", last);
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+@@ -1041,8 +1041,8 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
+ * moderately readable array casts.
+ */
+ hcd->fiq_dmab = DWC_DMA_ALLOC(dev, (sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base);
+- DWC_WARN("FIQ DMA bounce buffers: virt = 0x%08x dma = 0x%08x len=%d",
+- (unsigned int)hcd->fiq_dmab, (unsigned int)hcd->fiq_state->dma_base,
++ DWC_WARN("FIQ DMA bounce buffers: virt = %px dma = %pad len=%zu",
++ hcd->fiq_dmab, &hcd->fiq_state->dma_base,
+ sizeof(struct fiq_dma_channel) * num_channels);
+
+ DWC_MEMSET(hcd->fiq_dmab, 0x6b, 9024);
+@@ -1522,9 +1522,12 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
+ /*
+ * Set dma_regs to bounce buffer. FIQ will update the
+ * state depending on transaction progress.
++ * Pointer arithmetic on hcd->fiq_state->dma_base (a dma_addr_t)
++ * to point it to the correct offset in the allocated buffers.
+ */
+ blob = (struct fiq_dma_blob *) hcd->fiq_state->dma_base;
+- st->hcdma_copy.d32 = (uint32_t) &blob->channel[hc->hc_num].index[0].buf[0];
++ st->hcdma_copy.d32 = (dma_addr_t) blob->channel[hc->hc_num].index[0].buf;
++
+ /* Calculate the max number of CSPLITS such that the FIQ can time out
+ * a transaction if it fails.
+ */
+@@ -1571,9 +1574,15 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
+ st->nrpackets = i;
+ }
+ ptr = qtd->urb->buf + frame_desc->offset;
+- /* Point the HC at the DMA address of the bounce buffers */
++ /*
++ * Point the HC at the DMA address of the bounce buffers
++ *
++ * Pointer arithmetic on hcd->fiq_state->dma_base (a
++ * dma_addr_t) to point it to the correct offset in the
++ * allocated buffers.
++ */
+ blob = (struct fiq_dma_blob *) hcd->fiq_state->dma_base;
+- st->hcdma_copy.d32 = (uint32_t) &blob->channel[hc->hc_num].index[0].buf[0];
++ st->hcdma_copy.d32 = (dma_addr_t) blob->channel[hc->hc_num].index[0].buf;
+
+ /* fixup xfersize to the actual packet size */
+ st->hctsiz_copy.b.pid = 0;
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+@@ -454,11 +454,9 @@ static void hcd_init_fiq(void *cookie)
+ DWC_ERROR("Can't claim FIQ");
+ BUG();
+ }
+- DWC_WARN("FIQ on core %d at 0x%08x",
+- smp_processor_id(),
+- (fiq_fsm_enable ? (int)&dwc_otg_fiq_fsm : (int)&dwc_otg_fiq_nop));
+- DWC_WARN("FIQ ASM at 0x%08x length %d", (int)&_dwc_otg_fiq_stub, (int)(&_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub));
+- set_fiq_handler((void *) &_dwc_otg_fiq_stub, &_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub);
++ DWC_WARN("FIQ on core %d", smp_processor_id());
++ DWC_WARN("FIQ ASM at %px length %d", &_dwc_otg_fiq_stub, (int)(&_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub));
++ set_fiq_handler((void *) &_dwc_otg_fiq_stub, &_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub);
+ memset(®s,0,sizeof(regs));
+
+ regs.ARM_r8 = (long) dwc_otg_hcd->fiq_state;
+@@ -483,7 +481,7 @@ static void hcd_init_fiq(void *cookie)
+ dwc_otg_hcd->fiq_state->mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c;
+ dwc_otg_hcd->fiq_state->mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
+ dwc_otg_hcd->fiq_state->dwc_regs_base = otg_dev->os_dep.base;
+- DWC_WARN("MPHI regs_base at 0x%08x", (int)dwc_otg_hcd->fiq_state->mphi_regs.base);
++ DWC_WARN("MPHI regs_base at %px", dwc_otg_hcd->fiq_state->mphi_regs.base);
+ //Enable mphi peripheral
+ writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
+ #ifdef DEBUG
+++ /dev/null
-From 9912d38ec8ef31866f61d526e1d3c001c657964e Mon Sep 17 00:00:00 2001
-From: Dimitris Papavasiliou <dpapavas@gmail.com>
-Date: Sat, 24 Nov 2018 22:05:42 +0200
-Subject: [PATCH 340/703] ASoC: pcm512x: Implement the digital_mute interface
-
-[ Upstream commit 3500f1c589e92e0b6b1f8d31b4084fbde08d49cb ]
-
-Clicks and pops of various volumes can be produced while the device is
-opened, closed, put into and taken out of standby, or reconfigured.
-Fix this, by implementing the digital_mute interface, so that the
-output is muted during such operations.
-
-Signed-off-by: Dimitris Papavasiliou <dpapavas@gmail.com>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/pcm512x.c | 121 ++++++++++++++++++++++++++++++++++++-
- sound/soc/codecs/pcm512x.h | 2 +
- 2 files changed, 121 insertions(+), 2 deletions(-)
-
---- a/sound/soc/codecs/pcm512x.c
-+++ b/sound/soc/codecs/pcm512x.c
-@@ -53,6 +53,8 @@ struct pcm512x_priv {
- unsigned long overclock_pll;
- unsigned long overclock_dac;
- unsigned long overclock_dsp;
-+ int mute;
-+ struct mutex mutex;
- int lrclk_div;
- };
-
-@@ -385,6 +387,61 @@ static const struct soc_enum pcm512x_ved
- SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4,
- pcm512x_ramp_step_text);
-
-+static int pcm512x_update_mute(struct pcm512x_priv *pcm512x)
-+{
-+ return regmap_update_bits(
-+ pcm512x->regmap, PCM512x_MUTE, PCM512x_RQML | PCM512x_RQMR,
-+ (!!(pcm512x->mute & 0x5) << PCM512x_RQML_SHIFT)
-+ | (!!(pcm512x->mute & 0x3) << PCM512x_RQMR_SHIFT));
-+}
-+
-+static int pcm512x_digital_playback_switch_get(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *ucontrol)
-+{
-+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
-+ struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
-+
-+ mutex_lock(&pcm512x->mutex);
-+ ucontrol->value.integer.value[0] = !(pcm512x->mute & 0x4);
-+ ucontrol->value.integer.value[1] = !(pcm512x->mute & 0x2);
-+ mutex_unlock(&pcm512x->mutex);
-+
-+ return 0;
-+}
-+
-+static int pcm512x_digital_playback_switch_put(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *ucontrol)
-+{
-+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
-+ struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
-+ int ret, changed = 0;
-+
-+ mutex_lock(&pcm512x->mutex);
-+
-+ if ((pcm512x->mute & 0x4) == (ucontrol->value.integer.value[0] << 2)) {
-+ pcm512x->mute ^= 0x4;
-+ changed = 1;
-+ }
-+ if ((pcm512x->mute & 0x2) == (ucontrol->value.integer.value[1] << 1)) {
-+ pcm512x->mute ^= 0x2;
-+ changed = 1;
-+ }
-+
-+ if (changed) {
-+ ret = pcm512x_update_mute(pcm512x);
-+ if (ret != 0) {
-+ dev_err(component->dev,
-+ "Failed to update digital mute: %d\n", ret);
-+ mutex_unlock(&pcm512x->mutex);
-+ return ret;
-+ }
-+ }
-+
-+ mutex_unlock(&pcm512x->mutex);
-+
-+ return changed;
-+}
-+
- static const struct snd_kcontrol_new pcm512x_controls[] = {
- SOC_DOUBLE_R_TLV("Digital Playback Volume", PCM512x_DIGITAL_VOLUME_2,
- PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv),
-@@ -392,8 +449,15 @@ SOC_DOUBLE_TLV("Analogue Playback Volume
- PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv),
- SOC_DOUBLE_TLV("Analogue Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST,
- PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv),
--SOC_DOUBLE("Digital Playback Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT,
-- PCM512x_RQMR_SHIFT, 1, 1),
-+{
-+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+ .name = "Digital Playback Switch",
-+ .index = 0,
-+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+ .info = snd_ctl_boolean_stereo_info,
-+ .get = pcm512x_digital_playback_switch_get,
-+ .put = pcm512x_digital_playback_switch_put
-+},
-
- SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1),
- SOC_ENUM("DSP Program", pcm512x_dsp_program),
-@@ -1323,6 +1387,56 @@ static int pcm512x_set_fmt(struct snd_so
- return 0;
- }
-
-+static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
-+{
-+ struct snd_soc_component *component = dai->component;
-+ struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
-+ int ret;
-+ unsigned int mute_det;
-+
-+ mutex_lock(&pcm512x->mutex);
-+
-+ if (mute) {
-+ pcm512x->mute |= 0x1;
-+ ret = regmap_update_bits(pcm512x->regmap, PCM512x_MUTE,
-+ PCM512x_RQML | PCM512x_RQMR,
-+ PCM512x_RQML | PCM512x_RQMR);
-+ if (ret != 0) {
-+ dev_err(component->dev,
-+ "Failed to set digital mute: %d\n", ret);
-+ mutex_unlock(&pcm512x->mutex);
-+ return ret;
-+ }
-+
-+ regmap_read_poll_timeout(pcm512x->regmap,
-+ PCM512x_ANALOG_MUTE_DET,
-+ mute_det, (mute_det & 0x3) == 0,
-+ 200, 10000);
-+
-+ mutex_unlock(&pcm512x->mutex);
-+ } else {
-+ pcm512x->mute &= ~0x1;
-+ ret = pcm512x_update_mute(pcm512x);
-+ if (ret != 0) {
-+ dev_err(component->dev,
-+ "Failed to update digital mute: %d\n", ret);
-+ mutex_unlock(&pcm512x->mutex);
-+ return ret;
-+ }
-+
-+ regmap_read_poll_timeout(pcm512x->regmap,
-+ PCM512x_ANALOG_MUTE_DET,
-+ mute_det,
-+ (mute_det & 0x3)
-+ == ((~pcm512x->mute >> 1) & 0x3),
-+ 200, 10000);
-+ }
-+
-+ mutex_unlock(&pcm512x->mutex);
-+
-+ return 0;
-+}
-+
- static int pcm512x_set_tdm_slot(struct snd_soc_dai *dai,
- unsigned int tx_mask, unsigned int rx_mask,
- int slots, int width)
-@@ -1348,6 +1462,7 @@ static const struct snd_soc_dai_ops pcm5
- .startup = pcm512x_dai_startup,
- .hw_params = pcm512x_hw_params,
- .set_fmt = pcm512x_set_fmt,
-+ .digital_mute = pcm512x_digital_mute,
- .set_tdm_slot = pcm512x_set_tdm_slot,
- };
-
-@@ -1414,6 +1529,8 @@ int pcm512x_probe(struct device *dev, st
- if (!pcm512x)
- return -ENOMEM;
-
-+ mutex_init(&pcm512x->mutex);
-+
- dev_set_drvdata(dev, pcm512x);
- pcm512x->regmap = regmap;
-
---- a/sound/soc/codecs/pcm512x.h
-+++ b/sound/soc/codecs/pcm512x.h
-@@ -112,7 +112,9 @@
- #define PCM512x_RQST_SHIFT 4
-
- /* Page 0, Register 3 - mute */
-+#define PCM512x_RQMR (1 << 0)
- #define PCM512x_RQMR_SHIFT 0
-+#define PCM512x_RQML (1 << 4)
- #define PCM512x_RQML_SHIFT 4
-
- /* Page 0, Register 4 - PLL */
--- /dev/null
+From 17d7702409b1627d408bf2242af57ade58b5b0f9 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 30 Jan 2019 17:47:51 +0000
+Subject: [PATCH 340/725] usb: dwc_otg: Use dma allocation for mphi dummy_send
+ buffer
+
+The FIQ driver used a kzalloc'ed buffer for dummy_send,
+passing a kernel virtual address to the hardware block.
+The buffer is only ever used for a dummy read, so it
+should be harmless, but there is the chance that it will
+cause exceptions.
+
+Use a dma allocation so that we have a genuine bus address,
+and read from that.
+Free the allocation when done for good measure.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 4 ++--
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 1 +
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 5 ++++-
+ 3 files changed, 7 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
+@@ -1347,7 +1347,7 @@ void notrace dwc_otg_fiq_fsm(struct fiq_
+ /* We got an interrupt, didn't handle it. */
+ if (kick_irq) {
+ state->mphi_int_count++;
+- FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send);
++ FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
+ FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
+
+ }
+@@ -1408,7 +1408,7 @@ void notrace dwc_otg_fiq_nop(struct fiq_
+ FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32);
+ /* Force a clear before another dummy send */
+ FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
+- FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send);
++ FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
+ FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
+
+ }
+--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
+@@ -352,6 +352,7 @@ struct fiq_state {
+ dma_addr_t dma_base;
+ struct fiq_dma_blob *fiq_dmab;
+ void *dummy_send;
++ dma_addr_t dummy_send_dma;
+ gintmsk_data_t gintmsk_saved;
+ haintmsk_data_t haintmsk_saved;
+ int mphi_int_count;
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+@@ -929,6 +929,8 @@ static void dwc_otg_hcd_free(dwc_otg_hcd
+ DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
+ DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
+ DWC_TASK_FREE(dwc_otg_hcd->completion_tasklet);
++ DWC_DMA_FREE(dev, 16, dwc_otg_hcd->fiq_state->dummy_send,
++ dwc_otg_hcd->fiq_state->dummy_send_dma);
+ DWC_FREE(dwc_otg_hcd->fiq_state);
+
+ #ifdef DWC_DEV_SRPCAP
+@@ -1021,7 +1023,8 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
+ for (i = 0; i < num_channels; i++) {
+ hcd->fiq_state->channel[i].fsm = FIQ_PASSTHROUGH;
+ }
+- hcd->fiq_state->dummy_send = DWC_ALLOC_ATOMIC(16);
++ hcd->fiq_state->dummy_send = DWC_DMA_ALLOC_ATOMIC(dev, 16,
++ &hcd->fiq_state->dummy_send_dma);
+
+ hcd->fiq_stack = DWC_ALLOC(sizeof(struct fiq_stack));
+ if (!hcd->fiq_stack) {
+++ /dev/null
-From e0d60424f966b62d61300cec4ba7fd070abaf772 Mon Sep 17 00:00:00 2001
-From: Dan Carpenter <dan.carpenter@oracle.com>
-Date: Fri, 21 Dec 2018 12:11:20 +0300
-Subject: [PATCH 341/703] ASoC: pcm512x: Fix a double unlock in
- pcm512x_digital_mute()
-
-[ Upstream commit 28b698b7342c7d5300cfe217cd77ff7d2a55e03d ]
-
-We accidentally call mutex_unlock(&pcm512x->mutex); twice in a row.
-
-I re-wrote the error handling to use "goto unlock;" instead of returning
-directly. Hopefully, it makes the code a little simpler.
-
-Fixes: 3500f1c589e9 ("ASoC: pcm512x: Implement the digital_mute interface")
-Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
-Reviwed-by: Dimitris Papavasiliou <dpapavas@gmail.com>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/pcm512x.c | 11 ++++-------
- 1 file changed, 4 insertions(+), 7 deletions(-)
-
---- a/sound/soc/codecs/pcm512x.c
-+++ b/sound/soc/codecs/pcm512x.c
-@@ -1404,24 +1404,20 @@ static int pcm512x_digital_mute(struct s
- if (ret != 0) {
- dev_err(component->dev,
- "Failed to set digital mute: %d\n", ret);
-- mutex_unlock(&pcm512x->mutex);
-- return ret;
-+ goto unlock;
- }
-
- regmap_read_poll_timeout(pcm512x->regmap,
- PCM512x_ANALOG_MUTE_DET,
- mute_det, (mute_det & 0x3) == 0,
- 200, 10000);
--
-- mutex_unlock(&pcm512x->mutex);
- } else {
- pcm512x->mute &= ~0x1;
- ret = pcm512x_update_mute(pcm512x);
- if (ret != 0) {
- dev_err(component->dev,
- "Failed to update digital mute: %d\n", ret);
-- mutex_unlock(&pcm512x->mutex);
-- return ret;
-+ goto unlock;
- }
-
- regmap_read_poll_timeout(pcm512x->regmap,
-@@ -1432,9 +1428,10 @@ static int pcm512x_digital_mute(struct s
- 200, 10000);
- }
-
-+unlock:
- mutex_unlock(&pcm512x->mutex);
-
-- return 0;
-+ return ret;
- }
-
- static int pcm512x_set_tdm_slot(struct snd_soc_dai *dai,
--- /dev/null
+From a42314a829d8a17ccfd533c90339348b09e85de8 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 29 Jan 2019 16:13:25 +0000
+Subject: [PATCH 341/725] staging: vchiq_arm: Set up dma ranges on child
+ devices
+
+The VCHIQ driver now loads the audio, camera, codec, and vc-sm
+drivers as platform drivers. However they were not being given
+the correct DMA configuration.
+
+Call of_dma_configure with the parent (VCHIQ) parameters to be
+inherited by the child.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -3585,6 +3585,7 @@ static struct platform_device *
+ vchiq_register_child(struct platform_device *pdev, const char *name)
+ {
+ struct platform_device_info pdevinfo;
++ struct platform_device *new_dev;
+
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+
+@@ -3593,7 +3594,17 @@ vchiq_register_child(struct platform_dev
+ pdevinfo.id = PLATFORM_DEVID_NONE;
+ pdevinfo.dma_mask = DMA_BIT_MASK(32);
+
+- return platform_device_register_full(&pdevinfo);
++ new_dev = platform_device_register_full(&pdevinfo);
++ if (!new_dev)
++ return NULL;
++
++ /*
++ * We want the dma-ranges etc to be copied from the parent VCHIQ device
++ * to be passed on to the children too.
++ */
++ of_dma_configure(&new_dev->dev, pdev->dev.of_node, true);
++
++ return new_dev;
+ }
+
+ static int vchiq_probe(struct platform_device *pdev)
--- /dev/null
+From f1c5c628f7cab20490bec1cdafc53048b10b65f2 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 29 Jan 2019 16:24:41 +0000
+Subject: [PATCH 342/725] staging: vc-sm-cma: Correct DMA configuration.
+
+Now that VCHIQ is setting up the DMA configuration as our
+parent device, don't try to configure it during probe.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 15 +++++----------
+ 1 file changed, 5 insertions(+), 10 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -703,9 +703,6 @@ err_free_mem:
+ /* Driver loading. */
+ static int bcm2835_vc_sm_cma_probe(struct platform_device *pdev)
+ {
+- struct device *dev = &pdev->dev;
+- int err;
+-
+ pr_info("%s: Videocore shared memory driver\n", __func__);
+
+ sm_state = kzalloc(sizeof(*sm_state), GFP_KERNEL);
+@@ -714,13 +711,11 @@ static int bcm2835_vc_sm_cma_probe(struc
+ sm_state->pdev = pdev;
+ mutex_init(&sm_state->map_lock);
+
+- dev->coherent_dma_mask = DMA_BIT_MASK(32);
+- dev->dma_mask = &dev->coherent_dma_mask;
+- err = of_dma_configure(dev, NULL, true);
+- if (err) {
+- dev_err(dev, "Unable to setup DMA: %d\n", err);
+- return err;
+- }
++ pdev->dev.dma_parms = devm_kzalloc(&pdev->dev,
++ sizeof(*pdev->dev.dma_parms),
++ GFP_KERNEL);
++ /* dma_set_max_seg_size checks if dma_parms is NULL. */
++ dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF);
+
+ vchiq_add_connected_callback(vc_sm_connected_init);
+ return 0;
+++ /dev/null
-From b10441b7ce4abbdb0f870f705cbb7d3520a57044 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 25 Jan 2019 16:03:31 +0000
-Subject: [PATCH 342/703] usb: dwc_otg: Clean up build warnings on 64bit
- kernels
-
-No functional changes. Almost all are changes to logging lines.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/usb/host/dwc_otg/dwc_otg_driver.c | 3 +--
- drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 2 +-
- drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 19 ++++++++++++++-----
- drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 10 ++++------
- 4 files changed, 20 insertions(+), 14 deletions(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
-@@ -837,8 +837,7 @@ static int dwc_otg_driver_probe(
- retval = -ENOMEM;
- goto fail;
- }
-- dev_info(&_dev->dev, "base=0x%08x\n",
-- (unsigned)dwc_otg_device->os_dep.base);
-+ dev_info(&_dev->dev, "base=%p\n", dwc_otg_device->os_dep.base);
- #endif
-
- /*
---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
-@@ -301,7 +301,7 @@ static int notrace fiq_iso_out_advance(s
- last = 1;
-
- /* New DMA address - address of bounce buffer referred to in index */
-- hcdma.d32 = (uint32_t) &blob->channel[n].index[i].buf[0];
-+ hcdma.d32 = (dma_addr_t) blob->channel[n].index[i].buf;
- //hcdma.d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HC_DMA);
- //hcdma.d32 += st->channel[n].dma_info.slot_len[i];
- fiq_print(FIQDBG_INT, st, "LAST: %01d ", last);
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-@@ -1041,8 +1041,8 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
- * moderately readable array casts.
- */
- hcd->fiq_dmab = DWC_DMA_ALLOC(dev, (sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base);
-- DWC_WARN("FIQ DMA bounce buffers: virt = 0x%08x dma = 0x%08x len=%d",
-- (unsigned int)hcd->fiq_dmab, (unsigned int)hcd->fiq_state->dma_base,
-+ DWC_WARN("FIQ DMA bounce buffers: virt = %px dma = %pad len=%zu",
-+ hcd->fiq_dmab, &hcd->fiq_state->dma_base,
- sizeof(struct fiq_dma_channel) * num_channels);
-
- DWC_MEMSET(hcd->fiq_dmab, 0x6b, 9024);
-@@ -1522,9 +1522,12 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
- /*
- * Set dma_regs to bounce buffer. FIQ will update the
- * state depending on transaction progress.
-+ * Pointer arithmetic on hcd->fiq_state->dma_base (a dma_addr_t)
-+ * to point it to the correct offset in the allocated buffers.
- */
- blob = (struct fiq_dma_blob *) hcd->fiq_state->dma_base;
-- st->hcdma_copy.d32 = (uint32_t) &blob->channel[hc->hc_num].index[0].buf[0];
-+ st->hcdma_copy.d32 = (dma_addr_t) blob->channel[hc->hc_num].index[0].buf;
-+
- /* Calculate the max number of CSPLITS such that the FIQ can time out
- * a transaction if it fails.
- */
-@@ -1571,9 +1574,15 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
- st->nrpackets = i;
- }
- ptr = qtd->urb->buf + frame_desc->offset;
-- /* Point the HC at the DMA address of the bounce buffers */
-+ /*
-+ * Point the HC at the DMA address of the bounce buffers
-+ *
-+ * Pointer arithmetic on hcd->fiq_state->dma_base (a
-+ * dma_addr_t) to point it to the correct offset in the
-+ * allocated buffers.
-+ */
- blob = (struct fiq_dma_blob *) hcd->fiq_state->dma_base;
-- st->hcdma_copy.d32 = (uint32_t) &blob->channel[hc->hc_num].index[0].buf[0];
-+ st->hcdma_copy.d32 = (dma_addr_t) blob->channel[hc->hc_num].index[0].buf;
-
- /* fixup xfersize to the actual packet size */
- st->hctsiz_copy.b.pid = 0;
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-@@ -454,11 +454,9 @@ static void hcd_init_fiq(void *cookie)
- DWC_ERROR("Can't claim FIQ");
- BUG();
- }
-- DWC_WARN("FIQ on core %d at 0x%08x",
-- smp_processor_id(),
-- (fiq_fsm_enable ? (int)&dwc_otg_fiq_fsm : (int)&dwc_otg_fiq_nop));
-- DWC_WARN("FIQ ASM at 0x%08x length %d", (int)&_dwc_otg_fiq_stub, (int)(&_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub));
-- set_fiq_handler((void *) &_dwc_otg_fiq_stub, &_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub);
-+ DWC_WARN("FIQ on core %d", smp_processor_id());
-+ DWC_WARN("FIQ ASM at %px length %d", &_dwc_otg_fiq_stub, (int)(&_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub));
-+ set_fiq_handler((void *) &_dwc_otg_fiq_stub, &_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub);
- memset(®s,0,sizeof(regs));
-
- regs.ARM_r8 = (long) dwc_otg_hcd->fiq_state;
-@@ -483,7 +481,7 @@ static void hcd_init_fiq(void *cookie)
- dwc_otg_hcd->fiq_state->mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c;
- dwc_otg_hcd->fiq_state->mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
- dwc_otg_hcd->fiq_state->dwc_regs_base = otg_dev->os_dep.base;
-- DWC_WARN("MPHI regs_base at 0x%08x", (int)dwc_otg_hcd->fiq_state->mphi_regs.base);
-+ DWC_WARN("MPHI regs_base at %px", dwc_otg_hcd->fiq_state->mphi_regs.base);
- //Enable mphi peripheral
- writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
- #ifdef DEBUG
--- /dev/null
+From 6d7ababea249987cb3014e62b54d8ee577179107 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 29 Jan 2019 16:29:00 +0000
+Subject: [PATCH 343/725] staging: vc-sm-cma: Use a void* pointer as the handle
+ within the kernel
+
+The driver was using an unsigned int as the handle to the outside world,
+and doing a nasty cast to the struct dmabuf when handed it back.
+This breaks badly with a 64 bit kernel where the pointer doesn't fit
+in an unsigned int.
+
+Switch to using a void* within the kernel. Reality is that it is
+a struct dma_buf*, but advertising it as such to other drivers seems
+to encourage the use of it as such, and I'm not sure on the implications
+of that.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 10 +++++-----
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h | 6 +++---
+ drivers/staging/vc04_services/vchiq-mmal/mmal-common.h | 2 +-
+ drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 2 +-
+ 4 files changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -745,7 +745,7 @@ static int bcm2835_vc_sm_cma_remove(stru
+ }
+
+ /* Get an internal resource handle mapped from the external one. */
+-int vc_sm_cma_int_handle(int handle)
++int vc_sm_cma_int_handle(void *handle)
+ {
+ struct dma_buf *dma_buf = (struct dma_buf *)handle;
+ struct vc_sm_buffer *res;
+@@ -762,7 +762,7 @@ int vc_sm_cma_int_handle(int handle)
+ EXPORT_SYMBOL_GPL(vc_sm_cma_int_handle);
+
+ /* Free a previously allocated shared memory handle and block. */
+-int vc_sm_cma_free(int handle)
++int vc_sm_cma_free(void *handle)
+ {
+ struct dma_buf *dma_buf = (struct dma_buf *)handle;
+
+@@ -772,7 +772,7 @@ int vc_sm_cma_free(int handle)
+ return -EPERM;
+ }
+
+- pr_debug("%s: handle %08x/dmabuf %p\n", __func__, handle, dma_buf);
++ pr_debug("%s: handle %p/dmabuf %p\n", __func__, handle, dma_buf);
+
+ dma_buf_put(dma_buf);
+
+@@ -781,7 +781,7 @@ int vc_sm_cma_free(int handle)
+ EXPORT_SYMBOL_GPL(vc_sm_cma_free);
+
+ /* Import a dmabuf to be shared with VC. */
+-int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, int *handle)
++int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, void **handle)
+ {
+ struct dma_buf *new_dma_buf;
+ struct vc_sm_buffer *res;
+@@ -801,7 +801,7 @@ int vc_sm_cma_import_dmabuf(struct dma_b
+ res = (struct vc_sm_buffer *)new_dma_buf->priv;
+
+ /* Assign valid handle at this time.*/
+- *handle = (int)new_dma_buf;
++ *handle = new_dma_buf;
+ } else {
+ /*
+ * succeeded in importing the dma_buf, but then
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
+@@ -17,12 +17,12 @@
+ #endif
+
+ /* Free a previously allocated or imported shared memory handle and block. */
+-int vc_sm_cma_free(int handle);
++int vc_sm_cma_free(void *handle);
+
+ /* Get an internal resource handle mapped from the external one. */
+-int vc_sm_cma_int_handle(int handle);
++int vc_sm_cma_int_handle(void *handle);
+
+ /* Import a block of memory into the GPU space. */
+-int vc_sm_cma_import_dmabuf(struct dma_buf *dmabuf, int *handle);
++int vc_sm_cma_import_dmabuf(struct dma_buf *dmabuf, void **handle);
+
+ #endif /* __VC_SM_KNL_H__INCLUDED__ */
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
+@@ -52,7 +52,7 @@ struct mmal_buffer {
+ struct mmal_msg_context *msg_context;
+
+ struct dma_buf *dma_buf;/* Exported dmabuf fd from videobuf2 */
+- int vcsm_handle; /* VCSM handle having imported the dmabuf */
++ void *vcsm_handle; /* VCSM handle having imported the dmabuf */
+ u32 vc_handle; /* VC handle to that dmabuf */
+
+ u32 cmd; /* MMAL command. 0=data. */
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -1794,7 +1794,7 @@ int mmal_vchi_buffer_cleanup(struct mmal
+ if (buf->vcsm_handle) {
+ int ret;
+
+- pr_debug("%s: vc_sm_cma_free on handle %08X\n", __func__,
++ pr_debug("%s: vc_sm_cma_free on handle %p\n", __func__,
+ buf->vcsm_handle);
+ ret = vc_sm_cma_free(buf->vcsm_handle);
+ if (ret)
+++ /dev/null
-From 2aa9b698ab642535989a1bd69300f9a6e13395c9 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 30 Jan 2019 17:47:51 +0000
-Subject: [PATCH 343/703] usb: dwc_otg: Use dma allocation for mphi dummy_send
- buffer
-
-The FIQ driver used a kzalloc'ed buffer for dummy_send,
-passing a kernel virtual address to the hardware block.
-The buffer is only ever used for a dummy read, so it
-should be harmless, but there is the chance that it will
-cause exceptions.
-
-Use a dma allocation so that we have a genuine bus address,
-and read from that.
-Free the allocation when done for good measure.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 4 ++--
- drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 1 +
- drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 5 ++++-
- 3 files changed, 7 insertions(+), 3 deletions(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
-@@ -1347,7 +1347,7 @@ void notrace dwc_otg_fiq_fsm(struct fiq_
- /* We got an interrupt, didn't handle it. */
- if (kick_irq) {
- state->mphi_int_count++;
-- FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send);
-+ FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
- FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
-
- }
-@@ -1408,7 +1408,7 @@ void notrace dwc_otg_fiq_nop(struct fiq_
- FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32);
- /* Force a clear before another dummy send */
- FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
-- FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send);
-+ FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
- FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
-
- }
---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
-@@ -352,6 +352,7 @@ struct fiq_state {
- dma_addr_t dma_base;
- struct fiq_dma_blob *fiq_dmab;
- void *dummy_send;
-+ dma_addr_t dummy_send_dma;
- gintmsk_data_t gintmsk_saved;
- haintmsk_data_t haintmsk_saved;
- int mphi_int_count;
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-@@ -929,6 +929,8 @@ static void dwc_otg_hcd_free(dwc_otg_hcd
- DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
- DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
- DWC_TASK_FREE(dwc_otg_hcd->completion_tasklet);
-+ DWC_DMA_FREE(dev, 16, dwc_otg_hcd->fiq_state->dummy_send,
-+ dwc_otg_hcd->fiq_state->dummy_send_dma);
- DWC_FREE(dwc_otg_hcd->fiq_state);
-
- #ifdef DWC_DEV_SRPCAP
-@@ -1021,7 +1023,8 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
- for (i = 0; i < num_channels; i++) {
- hcd->fiq_state->channel[i].fsm = FIQ_PASSTHROUGH;
- }
-- hcd->fiq_state->dummy_send = DWC_ALLOC_ATOMIC(16);
-+ hcd->fiq_state->dummy_send = DWC_DMA_ALLOC_ATOMIC(dev, 16,
-+ &hcd->fiq_state->dummy_send_dma);
-
- hcd->fiq_stack = DWC_ALLOC(sizeof(struct fiq_stack));
- if (!hcd->fiq_stack) {
--- /dev/null
+From 8da5f5ca322c3b6c5c9055381af9db67f724bdc3 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 29 Jan 2019 16:32:57 +0000
+Subject: [PATCH 344/725] staging: vc-sm-cma: Fix up for 64bit builds
+
+There were a number of logging lines that were using
+inappropriate formatting under 64bit kernels.
+
+The kernel_id field passed to/from the VPU was being
+abused for storing the struct vc_sm_buffer *.
+This breaks with 64bit kernels, so change to using an IDR.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c | 60 +++++++++++++++----
+ .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c | 3 +-
+ 2 files changed, 48 insertions(+), 15 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -75,6 +75,9 @@ struct sm_state_t {
+ struct miscdevice dev;
+ struct sm_instance *sm_handle; /* Handle for videocore service. */
+
++ spinlock_t kernelid_map_lock; /* Spinlock protecting kernelid_map */
++ struct idr kernelid_map;
++
+ struct mutex map_lock; /* Global map lock. */
+ struct list_head buffer_list; /* List of buffer. */
+
+@@ -97,6 +100,29 @@ static int sm_inited;
+
+ /* ---- Private Functions ------------------------------------------------ */
+
++static int get_kernel_id(struct vc_sm_buffer *buffer)
++{
++ int handle;
++
++ spin_lock(&sm_state->kernelid_map_lock);
++ handle = idr_alloc(&sm_state->kernelid_map, buffer, 0, 0, GFP_KERNEL);
++ spin_unlock(&sm_state->kernelid_map_lock);
++
++ return handle;
++}
++
++static struct vc_sm_buffer *lookup_kernel_id(int handle)
++{
++ return idr_find(&sm_state->kernelid_map, handle);
++}
++
++static void free_kernel_id(int handle)
++{
++ spin_lock(&sm_state->kernelid_map_lock);
++ idr_remove(&sm_state->kernelid_map, handle);
++ spin_unlock(&sm_state->kernelid_map_lock);
++}
++
+ static int vc_sm_cma_seq_file_show(struct seq_file *s, void *v)
+ {
+ struct sm_pde_t *sm_pde;
+@@ -129,8 +155,7 @@ static int vc_sm_cma_global_state_show(s
+ if (!sm_state)
+ return 0;
+
+- seq_printf(s, "\nVC-ServiceHandle 0x%x\n",
+- (unsigned int)sm_state->sm_handle);
++ seq_printf(s, "\nVC-ServiceHandle %p\n", sm_state->sm_handle);
+
+ /* Log all applicable mapping(s). */
+
+@@ -145,7 +170,7 @@ static int vc_sm_cma_global_state_show(s
+ resource);
+ seq_printf(s, " NAME %s\n",
+ resource->name);
+- seq_printf(s, " SIZE %d\n",
++ seq_printf(s, " SIZE %zu\n",
+ resource->size);
+ seq_printf(s, " DMABUF %p\n",
+ resource->dma_buf);
+@@ -181,7 +206,7 @@ static void vc_sm_add_resource(struct vc
+ list_add(&buffer->global_buffer_list, &sm_state->buffer_list);
+ mutex_unlock(&sm_state->map_lock);
+
+- pr_debug("[%s]: added buffer %p (name %s, size %d)\n",
++ pr_debug("[%s]: added buffer %p (name %s, size %zu)\n",
+ __func__, buffer, buffer->name, buffer->size);
+ }
+
+@@ -194,7 +219,7 @@ static void vc_sm_release_resource(struc
+ mutex_lock(&sm_state->map_lock);
+ mutex_lock(&buffer->lock);
+
+- pr_debug("[%s]: buffer %p (name %s, size %d)\n",
++ pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
+ __func__, buffer, buffer->name, buffer->size);
+
+ if (buffer->vc_handle && buffer->vpu_state == VPU_MAPPED) {
+@@ -443,6 +468,7 @@ vc_sm_cma_import_dmabuf_internal(struct
+ struct vc_sm_import_result result = { };
+ struct dma_buf_attachment *attach = NULL;
+ struct sg_table *sgt = NULL;
++ dma_addr_t dma_addr;
+ int ret = 0;
+ int status;
+
+@@ -478,21 +504,22 @@ vc_sm_cma_import_dmabuf_internal(struct
+ }
+
+ import.type = VC_SM_ALLOC_NON_CACHED;
+- import.addr = (uint32_t)sg_dma_address(sgt->sgl);
++ dma_addr = sg_dma_address(sgt->sgl);
++ import.addr = (uint32_t)dma_addr;
+ if ((import.addr & 0xC0000000) != 0xC0000000) {
+- pr_err("%s: Expecting an uncached alias for dma_addr %08x\n",
+- __func__, import.addr);
++ pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
++ __func__, &dma_addr);
+ import.addr |= 0xC0000000;
+ }
+ import.size = sg_dma_len(sgt->sgl);
+ import.allocator = current->tgid;
+- import.kernel_id = (uint32_t)buffer; //FIXME: 64 bit support needed.
++ import.kernel_id = get_kernel_id(buffer);
+
+ memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
+ sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
+
+- pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %p, size %u\n",
+- __func__, import.name, import.type, (void *)import.addr,
++ pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %pad, size %u\n",
++ __func__, import.name, import.type, &dma_addr,
+ import.size);
+
+ /* Allocate the videocore buffer. */
+@@ -527,7 +554,7 @@ vc_sm_cma_import_dmabuf_internal(struct
+
+ buffer->attach = attach;
+ buffer->sgt = sgt;
+- buffer->dma_addr = sg_dma_address(sgt->sgl);
++ buffer->dma_addr = dma_addr;
+ buffer->in_use = 1;
+
+ /*
+@@ -559,6 +586,7 @@ error:
+ vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
+ &sm_state->int_trans_id);
+ }
++ free_kernel_id(import.kernel_id);
+ kfree(buffer);
+ if (sgt)
+ dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+@@ -586,7 +614,7 @@ vc_sm_vpu_event(struct sm_instance *inst
+ {
+ struct vc_sm_released *release = (struct vc_sm_released *)reply;
+ struct vc_sm_buffer *buffer =
+- (struct vc_sm_buffer *)release->kernel_id;
++ lookup_kernel_id(release->kernel_id);
+
+ /*
+ * FIXME: Need to check buffer is still valid and allocated
+@@ -599,6 +627,7 @@ vc_sm_vpu_event(struct sm_instance *inst
+ buffer->vc_handle = 0;
+ buffer->vpu_state = VPU_NOT_MAPPED;
+ mutex_unlock(&buffer->lock);
++ free_kernel_id(release->kernel_id);
+
+ vc_sm_release_resource(buffer, 0);
+ }
+@@ -711,6 +740,9 @@ static int bcm2835_vc_sm_cma_probe(struc
+ sm_state->pdev = pdev;
+ mutex_init(&sm_state->map_lock);
+
++ spin_lock_init(&sm_state->kernelid_map_lock);
++ idr_init_base(&sm_state->kernelid_map, 1);
++
+ pdev->dev.dma_parms = devm_kzalloc(&pdev->dev,
+ sizeof(*pdev->dev.dma_parms),
+ GFP_KERNEL);
+@@ -735,6 +767,8 @@ static int bcm2835_vc_sm_cma_remove(stru
+ /* Stop the videocore shared memory service. */
+ vc_sm_cma_vchi_stop(&sm_state->sm_handle);
+
++ idr_destroy(&sm_state->kernelid_map);
++
+ /* Free the memory for the state structure. */
+ mutex_destroy(&sm_state->map_lock);
+ kfree(sm_state);
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
+@@ -356,8 +356,7 @@ struct sm_instance *vc_sm_cma_vchi_init(
+ set_user_nice(instance->io_thread, -10);
+ wake_up_process(instance->io_thread);
+
+- pr_debug("%s: success - instance 0x%x", __func__,
+- (unsigned int)instance);
++ pr_debug("%s: success - instance %p", __func__, instance);
+ return instance;
+
+ err_close_services:
+++ /dev/null
-From 0a0aaf192a20f9c5552c0fca4f5b29c3d31784ab Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 29 Jan 2019 16:13:25 +0000
-Subject: [PATCH 344/703] staging: vchiq_arm: Set up dma ranges on child
- devices
-
-The VCHIQ driver now loads the audio, camera, codec, and vc-sm
-drivers as platform drivers. However they were not being given
-the correct DMA configuration.
-
-Call of_dma_configure with the parent (VCHIQ) parameters to be
-inherited by the child.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 13 ++++++++++++-
- 1 file changed, 12 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -3585,6 +3585,7 @@ static struct platform_device *
- vchiq_register_child(struct platform_device *pdev, const char *name)
- {
- struct platform_device_info pdevinfo;
-+ struct platform_device *new_dev;
-
- memset(&pdevinfo, 0, sizeof(pdevinfo));
-
-@@ -3593,7 +3594,17 @@ vchiq_register_child(struct platform_dev
- pdevinfo.id = PLATFORM_DEVID_NONE;
- pdevinfo.dma_mask = DMA_BIT_MASK(32);
-
-- return platform_device_register_full(&pdevinfo);
-+ new_dev = platform_device_register_full(&pdevinfo);
-+ if (!new_dev)
-+ return NULL;
-+
-+ /*
-+ * We want the dma-ranges etc to be copied from the parent VCHIQ device
-+ * to be passed on to the children too.
-+ */
-+ of_dma_configure(&new_dev->dev, pdev->dev.of_node, true);
-+
-+ return new_dev;
- }
-
- static int vchiq_probe(struct platform_device *pdev)
--- /dev/null
+From e8ee011946b8c53828e512c3bf2a964934073a4e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 4 Feb 2019 12:35:06 +0000
+Subject: [PATCH 345/725] configs: Add Unicam and subdevices to
+ bcmrpi3_defconfig
+
+The bcm2835-unicam, tc358743, adv7180 (for adv7282m) and ov5647
+have been tested on a 64bit kernel and shown to work.
+Add them to the config.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm64/configs/bcmrpi3_defconfig | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -645,6 +645,7 @@ CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
+ CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+ CONFIG_MEDIA_RADIO_SUPPORT=y
+ CONFIG_MEDIA_CONTROLLER=y
++CONFIG_VIDEO_V4L2_SUBDEV_API=y
+ CONFIG_MEDIA_USB_SUPPORT=y
+ CONFIG_USB_VIDEO_CLASS=m
+ CONFIG_USB_M5602=m
+@@ -727,6 +728,7 @@ CONFIG_VIDEO_EM28XX_V4L2=m
+ CONFIG_VIDEO_EM28XX_ALSA=m
+ CONFIG_VIDEO_EM28XX_DVB=m
+ CONFIG_V4L_PLATFORM_DRIVERS=y
++CONFIG_VIDEO_BCM2835_UNICAM=m
+ CONFIG_RADIO_SI470X=m
+ CONFIG_USB_SI470X=m
+ CONFIG_I2C_SI470X=m
+@@ -746,10 +748,13 @@ CONFIG_RADIO_WL128X=m
+ # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
+ CONFIG_VIDEO_UDA1342=m
+ CONFIG_VIDEO_SONY_BTF_MPX=m
++CONFIG_VIDEO_ADV7180=m
++CONFIG_VIDEO_TC358743=m
+ CONFIG_VIDEO_TVP5150=m
+ CONFIG_VIDEO_TW2804=m
+ CONFIG_VIDEO_TW9903=m
+ CONFIG_VIDEO_TW9906=m
++CONFIG_VIDEO_OV5647=m
+ CONFIG_VIDEO_OV7640=m
+ CONFIG_VIDEO_MT9V011=m
+ CONFIG_DRM=m
+++ /dev/null
-From 6fab727ac8fd457541d36edf07e6615c20341372 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 29 Jan 2019 16:24:41 +0000
-Subject: [PATCH 345/703] staging: vc-sm-cma: Correct DMA configuration.
-
-Now that VCHIQ is setting up the DMA configuration as our
-parent device, don't try to configure it during probe.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 15 +++++----------
- 1 file changed, 5 insertions(+), 10 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -703,9 +703,6 @@ err_free_mem:
- /* Driver loading. */
- static int bcm2835_vc_sm_cma_probe(struct platform_device *pdev)
- {
-- struct device *dev = &pdev->dev;
-- int err;
--
- pr_info("%s: Videocore shared memory driver\n", __func__);
-
- sm_state = kzalloc(sizeof(*sm_state), GFP_KERNEL);
-@@ -714,13 +711,11 @@ static int bcm2835_vc_sm_cma_probe(struc
- sm_state->pdev = pdev;
- mutex_init(&sm_state->map_lock);
-
-- dev->coherent_dma_mask = DMA_BIT_MASK(32);
-- dev->dma_mask = &dev->coherent_dma_mask;
-- err = of_dma_configure(dev, NULL, true);
-- if (err) {
-- dev_err(dev, "Unable to setup DMA: %d\n", err);
-- return err;
-- }
-+ pdev->dev.dma_parms = devm_kzalloc(&pdev->dev,
-+ sizeof(*pdev->dev.dma_parms),
-+ GFP_KERNEL);
-+ /* dma_set_max_seg_size checks if dma_parms is NULL. */
-+ dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF);
-
- vchiq_add_connected_callback(vc_sm_connected_init);
- return 0;
--- /dev/null
+From bfd4f57fa06a92d61ca39d3fde743cdac35b03f9 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 4 Feb 2019 12:45:25 +0000
+Subject: [PATCH 346/725] configs: Add VIDEO_BCM2835 to bcmrpi3_defconfig
+
+This is now shown to work with 64 bit kernels, so add it to
+the defconfig.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -1070,6 +1070,7 @@ CONFIG_FB_TFT_WATTEROTT=m
+ CONFIG_FB_FLEX=m
+ CONFIG_FB_TFT_FBTFT_DEVICE=m
+ CONFIG_SND_BCM2835=m
++CONFIG_VIDEO_BCM2835=m
+ CONFIG_MAILBOX=y
+ CONFIG_BCM2835_MBOX=y
+ # CONFIG_IOMMU_SUPPORT is not set
+++ /dev/null
-From 0bdf03ed6435089119a3d502f84f8943a12f65ac Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 29 Jan 2019 16:29:00 +0000
-Subject: [PATCH 346/703] staging: vc-sm-cma: Use a void* pointer as the handle
- within the kernel
-
-The driver was using an unsigned int as the handle to the outside world,
-and doing a nasty cast to the struct dmabuf when handed it back.
-This breaks badly with a 64 bit kernel where the pointer doesn't fit
-in an unsigned int.
-
-Switch to using a void* within the kernel. Reality is that it is
-a struct dma_buf*, but advertising it as such to other drivers seems
-to encourage the use of it as such, and I'm not sure on the implications
-of that.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 10 +++++-----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h | 6 +++---
- drivers/staging/vc04_services/vchiq-mmal/mmal-common.h | 2 +-
- drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 2 +-
- 4 files changed, 10 insertions(+), 10 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -745,7 +745,7 @@ static int bcm2835_vc_sm_cma_remove(stru
- }
-
- /* Get an internal resource handle mapped from the external one. */
--int vc_sm_cma_int_handle(int handle)
-+int vc_sm_cma_int_handle(void *handle)
- {
- struct dma_buf *dma_buf = (struct dma_buf *)handle;
- struct vc_sm_buffer *res;
-@@ -762,7 +762,7 @@ int vc_sm_cma_int_handle(int handle)
- EXPORT_SYMBOL_GPL(vc_sm_cma_int_handle);
-
- /* Free a previously allocated shared memory handle and block. */
--int vc_sm_cma_free(int handle)
-+int vc_sm_cma_free(void *handle)
- {
- struct dma_buf *dma_buf = (struct dma_buf *)handle;
-
-@@ -772,7 +772,7 @@ int vc_sm_cma_free(int handle)
- return -EPERM;
- }
-
-- pr_debug("%s: handle %08x/dmabuf %p\n", __func__, handle, dma_buf);
-+ pr_debug("%s: handle %p/dmabuf %p\n", __func__, handle, dma_buf);
-
- dma_buf_put(dma_buf);
-
-@@ -781,7 +781,7 @@ int vc_sm_cma_free(int handle)
- EXPORT_SYMBOL_GPL(vc_sm_cma_free);
-
- /* Import a dmabuf to be shared with VC. */
--int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, int *handle)
-+int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, void **handle)
- {
- struct dma_buf *new_dma_buf;
- struct vc_sm_buffer *res;
-@@ -801,7 +801,7 @@ int vc_sm_cma_import_dmabuf(struct dma_b
- res = (struct vc_sm_buffer *)new_dma_buf->priv;
-
- /* Assign valid handle at this time.*/
-- *handle = (int)new_dma_buf;
-+ *handle = new_dma_buf;
- } else {
- /*
- * succeeded in importing the dma_buf, but then
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_knl.h
-@@ -17,12 +17,12 @@
- #endif
-
- /* Free a previously allocated or imported shared memory handle and block. */
--int vc_sm_cma_free(int handle);
-+int vc_sm_cma_free(void *handle);
-
- /* Get an internal resource handle mapped from the external one. */
--int vc_sm_cma_int_handle(int handle);
-+int vc_sm_cma_int_handle(void *handle);
-
- /* Import a block of memory into the GPU space. */
--int vc_sm_cma_import_dmabuf(struct dma_buf *dmabuf, int *handle);
-+int vc_sm_cma_import_dmabuf(struct dma_buf *dmabuf, void **handle);
-
- #endif /* __VC_SM_KNL_H__INCLUDED__ */
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
-@@ -52,7 +52,7 @@ struct mmal_buffer {
- struct mmal_msg_context *msg_context;
-
- struct dma_buf *dma_buf;/* Exported dmabuf fd from videobuf2 */
-- int vcsm_handle; /* VCSM handle having imported the dmabuf */
-+ void *vcsm_handle; /* VCSM handle having imported the dmabuf */
- u32 vc_handle; /* VC handle to that dmabuf */
-
- u32 cmd; /* MMAL command. 0=data. */
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -1794,7 +1794,7 @@ int mmal_vchi_buffer_cleanup(struct mmal
- if (buf->vcsm_handle) {
- int ret;
-
-- pr_debug("%s: vc_sm_cma_free on handle %08X\n", __func__,
-+ pr_debug("%s: vc_sm_cma_free on handle %p\n", __func__,
- buf->vcsm_handle);
- ret = vc_sm_cma_free(buf->vcsm_handle);
- if (ret)
--- /dev/null
+From b12753c64741f12e50380ac8f6d8da36766904d5 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 4 Feb 2019 13:42:51 +0000
+Subject: [PATCH 347/725] configs: Add V4L2 codec driver to bcmrpi3_defconfig
+
+As this is now fixed to work with 64bit kernels, add it to the
+defconfig.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -1071,6 +1071,7 @@ CONFIG_FB_FLEX=m
+ CONFIG_FB_TFT_FBTFT_DEVICE=m
+ CONFIG_SND_BCM2835=m
+ CONFIG_VIDEO_BCM2835=m
++CONFIG_VIDEO_CODEC_BCM2835=m
+ CONFIG_MAILBOX=y
+ CONFIG_BCM2835_MBOX=y
+ # CONFIG_IOMMU_SUPPORT is not set
+++ /dev/null
-From 857c68b05d9b99e26d1dd460f349ed33857dbf71 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 29 Jan 2019 16:32:57 +0000
-Subject: [PATCH 347/703] staging: vc-sm-cma: Fix up for 64bit builds
-
-There were a number of logging lines that were using
-inappropriate formatting under 64bit kernels.
-
-The kernel_id field passed to/from the VPU was being
-abused for storing the struct vc_sm_buffer *.
-This breaks with 64bit kernels, so change to using an IDR.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vc-sm-cma/vc_sm.c | 60 +++++++++++++++----
- .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c | 3 +-
- 2 files changed, 48 insertions(+), 15 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -75,6 +75,9 @@ struct sm_state_t {
- struct miscdevice dev;
- struct sm_instance *sm_handle; /* Handle for videocore service. */
-
-+ spinlock_t kernelid_map_lock; /* Spinlock protecting kernelid_map */
-+ struct idr kernelid_map;
-+
- struct mutex map_lock; /* Global map lock. */
- struct list_head buffer_list; /* List of buffer. */
-
-@@ -97,6 +100,29 @@ static int sm_inited;
-
- /* ---- Private Functions ------------------------------------------------ */
-
-+static int get_kernel_id(struct vc_sm_buffer *buffer)
-+{
-+ int handle;
-+
-+ spin_lock(&sm_state->kernelid_map_lock);
-+ handle = idr_alloc(&sm_state->kernelid_map, buffer, 0, 0, GFP_KERNEL);
-+ spin_unlock(&sm_state->kernelid_map_lock);
-+
-+ return handle;
-+}
-+
-+static struct vc_sm_buffer *lookup_kernel_id(int handle)
-+{
-+ return idr_find(&sm_state->kernelid_map, handle);
-+}
-+
-+static void free_kernel_id(int handle)
-+{
-+ spin_lock(&sm_state->kernelid_map_lock);
-+ idr_remove(&sm_state->kernelid_map, handle);
-+ spin_unlock(&sm_state->kernelid_map_lock);
-+}
-+
- static int vc_sm_cma_seq_file_show(struct seq_file *s, void *v)
- {
- struct sm_pde_t *sm_pde;
-@@ -129,8 +155,7 @@ static int vc_sm_cma_global_state_show(s
- if (!sm_state)
- return 0;
-
-- seq_printf(s, "\nVC-ServiceHandle 0x%x\n",
-- (unsigned int)sm_state->sm_handle);
-+ seq_printf(s, "\nVC-ServiceHandle %p\n", sm_state->sm_handle);
-
- /* Log all applicable mapping(s). */
-
-@@ -145,7 +170,7 @@ static int vc_sm_cma_global_state_show(s
- resource);
- seq_printf(s, " NAME %s\n",
- resource->name);
-- seq_printf(s, " SIZE %d\n",
-+ seq_printf(s, " SIZE %zu\n",
- resource->size);
- seq_printf(s, " DMABUF %p\n",
- resource->dma_buf);
-@@ -181,7 +206,7 @@ static void vc_sm_add_resource(struct vc
- list_add(&buffer->global_buffer_list, &sm_state->buffer_list);
- mutex_unlock(&sm_state->map_lock);
-
-- pr_debug("[%s]: added buffer %p (name %s, size %d)\n",
-+ pr_debug("[%s]: added buffer %p (name %s, size %zu)\n",
- __func__, buffer, buffer->name, buffer->size);
- }
-
-@@ -194,7 +219,7 @@ static void vc_sm_release_resource(struc
- mutex_lock(&sm_state->map_lock);
- mutex_lock(&buffer->lock);
-
-- pr_debug("[%s]: buffer %p (name %s, size %d)\n",
-+ pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
- __func__, buffer, buffer->name, buffer->size);
-
- if (buffer->vc_handle && buffer->vpu_state == VPU_MAPPED) {
-@@ -443,6 +468,7 @@ vc_sm_cma_import_dmabuf_internal(struct
- struct vc_sm_import_result result = { };
- struct dma_buf_attachment *attach = NULL;
- struct sg_table *sgt = NULL;
-+ dma_addr_t dma_addr;
- int ret = 0;
- int status;
-
-@@ -478,21 +504,22 @@ vc_sm_cma_import_dmabuf_internal(struct
- }
-
- import.type = VC_SM_ALLOC_NON_CACHED;
-- import.addr = (uint32_t)sg_dma_address(sgt->sgl);
-+ dma_addr = sg_dma_address(sgt->sgl);
-+ import.addr = (uint32_t)dma_addr;
- if ((import.addr & 0xC0000000) != 0xC0000000) {
-- pr_err("%s: Expecting an uncached alias for dma_addr %08x\n",
-- __func__, import.addr);
-+ pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
-+ __func__, &dma_addr);
- import.addr |= 0xC0000000;
- }
- import.size = sg_dma_len(sgt->sgl);
- import.allocator = current->tgid;
-- import.kernel_id = (uint32_t)buffer; //FIXME: 64 bit support needed.
-+ import.kernel_id = get_kernel_id(buffer);
-
- memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
- sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
-
-- pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %p, size %u\n",
-- __func__, import.name, import.type, (void *)import.addr,
-+ pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %pad, size %u\n",
-+ __func__, import.name, import.type, &dma_addr,
- import.size);
-
- /* Allocate the videocore buffer. */
-@@ -527,7 +554,7 @@ vc_sm_cma_import_dmabuf_internal(struct
-
- buffer->attach = attach;
- buffer->sgt = sgt;
-- buffer->dma_addr = sg_dma_address(sgt->sgl);
-+ buffer->dma_addr = dma_addr;
- buffer->in_use = 1;
-
- /*
-@@ -559,6 +586,7 @@ error:
- vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
- &sm_state->int_trans_id);
- }
-+ free_kernel_id(import.kernel_id);
- kfree(buffer);
- if (sgt)
- dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
-@@ -586,7 +614,7 @@ vc_sm_vpu_event(struct sm_instance *inst
- {
- struct vc_sm_released *release = (struct vc_sm_released *)reply;
- struct vc_sm_buffer *buffer =
-- (struct vc_sm_buffer *)release->kernel_id;
-+ lookup_kernel_id(release->kernel_id);
-
- /*
- * FIXME: Need to check buffer is still valid and allocated
-@@ -599,6 +627,7 @@ vc_sm_vpu_event(struct sm_instance *inst
- buffer->vc_handle = 0;
- buffer->vpu_state = VPU_NOT_MAPPED;
- mutex_unlock(&buffer->lock);
-+ free_kernel_id(release->kernel_id);
-
- vc_sm_release_resource(buffer, 0);
- }
-@@ -711,6 +740,9 @@ static int bcm2835_vc_sm_cma_probe(struc
- sm_state->pdev = pdev;
- mutex_init(&sm_state->map_lock);
-
-+ spin_lock_init(&sm_state->kernelid_map_lock);
-+ idr_init_base(&sm_state->kernelid_map, 1);
-+
- pdev->dev.dma_parms = devm_kzalloc(&pdev->dev,
- sizeof(*pdev->dev.dma_parms),
- GFP_KERNEL);
-@@ -735,6 +767,8 @@ static int bcm2835_vc_sm_cma_remove(stru
- /* Stop the videocore shared memory service. */
- vc_sm_cma_vchi_stop(&sm_state->sm_handle);
-
-+ idr_destroy(&sm_state->kernelid_map);
-+
- /* Free the memory for the state structure. */
- mutex_destroy(&sm_state->map_lock);
- kfree(sm_state);
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-@@ -356,8 +356,7 @@ struct sm_instance *vc_sm_cma_vchi_init(
- set_user_nice(instance->io_thread, -10);
- wake_up_process(instance->io_thread);
-
-- pr_debug("%s: success - instance 0x%x", __func__,
-- (unsigned int)instance);
-+ pr_debug("%s: success - instance %p", __func__, instance);
- return instance;
-
- err_close_services:
--- /dev/null
+From 3a9bd6dd0db77f25d3bcbc2fd92ccd96cda854a8 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 5 Feb 2019 12:31:23 +0000
+Subject: [PATCH 348/725] config: Add IPVLAN module to bcmrpi3_defconfig
+
+It's built for the 32bit kernels, but not for the 64bit ones.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -430,6 +430,7 @@ CONFIG_BONDING=m
+ CONFIG_DUMMY=m
+ CONFIG_IFB=m
+ CONFIG_MACVLAN=m
++CONFIG_IPVLAN=m
+ CONFIG_VXLAN=m
+ CONFIG_NETCONSOLE=m
+ CONFIG_TUN=m
+++ /dev/null
-From a707e82004fa7e421a531690d3b072e53fa05819 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 4 Feb 2019 12:35:06 +0000
-Subject: [PATCH 348/703] configs: Add Unicam and subdevices to
- bcmrpi3_defconfig
-
-The bcm2835-unicam, tc358743, adv7180 (for adv7282m) and ov5647
-have been tested on a 64bit kernel and shown to work.
-Add them to the config.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm64/configs/bcmrpi3_defconfig | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -645,6 +645,7 @@ CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
- CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
- CONFIG_MEDIA_RADIO_SUPPORT=y
- CONFIG_MEDIA_CONTROLLER=y
-+CONFIG_VIDEO_V4L2_SUBDEV_API=y
- CONFIG_MEDIA_USB_SUPPORT=y
- CONFIG_USB_VIDEO_CLASS=m
- CONFIG_USB_M5602=m
-@@ -727,6 +728,7 @@ CONFIG_VIDEO_EM28XX_V4L2=m
- CONFIG_VIDEO_EM28XX_ALSA=m
- CONFIG_VIDEO_EM28XX_DVB=m
- CONFIG_V4L_PLATFORM_DRIVERS=y
-+CONFIG_VIDEO_BCM2835_UNICAM=m
- CONFIG_RADIO_SI470X=m
- CONFIG_USB_SI470X=m
- CONFIG_I2C_SI470X=m
-@@ -746,10 +748,13 @@ CONFIG_RADIO_WL128X=m
- # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
- CONFIG_VIDEO_UDA1342=m
- CONFIG_VIDEO_SONY_BTF_MPX=m
-+CONFIG_VIDEO_ADV7180=m
-+CONFIG_VIDEO_TC358743=m
- CONFIG_VIDEO_TVP5150=m
- CONFIG_VIDEO_TW2804=m
- CONFIG_VIDEO_TW9903=m
- CONFIG_VIDEO_TW9906=m
-+CONFIG_VIDEO_OV5647=m
- CONFIG_VIDEO_OV7640=m
- CONFIG_VIDEO_MT9V011=m
- CONFIG_DRM=m
+++ /dev/null
-From a44812330b02d78a28b17f1e364e73d827f4a872 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 4 Feb 2019 12:45:25 +0000
-Subject: [PATCH 349/703] configs: Add VIDEO_BCM2835 to bcmrpi3_defconfig
-
-This is now shown to work with 64 bit kernels, so add it to
-the defconfig.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -1070,6 +1070,7 @@ CONFIG_FB_TFT_WATTEROTT=m
- CONFIG_FB_FLEX=m
- CONFIG_FB_TFT_FBTFT_DEVICE=m
- CONFIG_SND_BCM2835=m
-+CONFIG_VIDEO_BCM2835=m
- CONFIG_MAILBOX=y
- CONFIG_BCM2835_MBOX=y
- # CONFIG_IOMMU_SUPPORT is not set
--- /dev/null
+From b3f3a83a0db08c6f4f68645f466cc3c64331b982 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 7 Feb 2019 18:16:25 +0000
+Subject: [PATCH 349/725] configs: Enable the AD193x codecs
+
+See: https://github.com/raspberrypi/linux/issues/2850
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/configs/bcm2709_defconfig | 2 ++
+ arch/arm/configs/bcmrpi_defconfig | 2 ++
+ arch/arm64/configs/bcmrpi3_defconfig | 2 ++
+ sound/soc/codecs/Kconfig | 4 ++--
+ 4 files changed, 8 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -930,6 +930,8 @@ CONFIG_SND_BCM2708_SOC_ALLO_DIGIONE=m
+ CONFIG_SND_BCM2708_SOC_ALLO_KATANA_DAC=m
+ CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m
+ CONFIG_SND_PISOUND=m
++CONFIG_SND_SOC_AD193X_SPI=m
++CONFIG_SND_SOC_AD193X_I2C=m
+ CONFIG_SND_SOC_ADAU1701=m
+ CONFIG_SND_SOC_ADAU7002=m
+ CONFIG_SND_SOC_AK4554=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -923,6 +923,8 @@ CONFIG_SND_BCM2708_SOC_ALLO_DIGIONE=m
+ CONFIG_SND_BCM2708_SOC_ALLO_KATANA_DAC=m
+ CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m
+ CONFIG_SND_PISOUND=m
++CONFIG_SND_SOC_AD193X_SPI=m
++CONFIG_SND_SOC_AD193X_I2C=m
+ CONFIG_SND_SOC_ADAU1701=m
+ CONFIG_SND_SOC_ADAU7002=m
+ CONFIG_SND_SOC_AK4554=m
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -811,6 +811,8 @@ CONFIG_SND_DIGIDAC1_SOUNDCARD=m
+ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m
+ CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m
+ CONFIG_SND_PISOUND=m
++CONFIG_SND_SOC_AD193X_SPI=m
++CONFIG_SND_SOC_AD193X_I2C=m
+ CONFIG_SND_SOC_ADAU1701=m
+ CONFIG_SND_SOC_AK4554=m
+ CONFIG_SND_SOC_CS4271_I2C=m
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -295,11 +295,11 @@ config SND_SOC_AD193X
+ tristate
+
+ config SND_SOC_AD193X_SPI
+- tristate
++ tristate "Analog Devices AU193X CODEC - SPI"
+ select SND_SOC_AD193X
+
+ config SND_SOC_AD193X_I2C
+- tristate
++ tristate "Analog Devices AU193X CODEC - I2C"
+ select SND_SOC_AD193X
+
+ config SND_SOC_AD1980
+++ /dev/null
-From 426d55354b0d23a514ee80596f22d1ea2a58b811 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 4 Feb 2019 13:42:51 +0000
-Subject: [PATCH 350/703] configs: Add V4L2 codec driver to bcmrpi3_defconfig
-
-As this is now fixed to work with 64bit kernels, add it to the
-defconfig.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -1071,6 +1071,7 @@ CONFIG_FB_FLEX=m
- CONFIG_FB_TFT_FBTFT_DEVICE=m
- CONFIG_SND_BCM2835=m
- CONFIG_VIDEO_BCM2835=m
-+CONFIG_VIDEO_CODEC_BCM2835=m
- CONFIG_MAILBOX=y
- CONFIG_BCM2835_MBOX=y
- # CONFIG_IOMMU_SUPPORT is not set
--- /dev/null
+From 0bafdbbfcc0a583808997ffff5110a10b9d8b49e Mon Sep 17 00:00:00 2001
+From: Zahari Petkov <zahari@balena.io>
+Date: Fri, 8 Feb 2019 13:03:38 +0200
+Subject: [PATCH 350/725] overlays: balenaFin v1.1.0 carrier board update
+
+A backward compatible update for the balenaFin carrier board for the
+Raspberry Pi Compute Module 3/3+ Lite.
+
+The updated overlay includes:
+ * support for the newly introduced RGB LEDs
+ * i2c-gpio and SDIO improvements
+ * DT based Marvell 88W8887 configuration
+
+Signed-off-by: Zahari Petkov <zahari@balena.io>
+---
+ arch/arm/boot/dts/overlays/README | 2 +-
+ .../boot/dts/overlays/balena-fin-overlay.dts | 46 ++++++++++++++++++-
+ 2 files changed, 45 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -472,7 +472,7 @@ Params: swap_lr Reverse
+
+ Name: balena-fin
+ Info: Overlay that enables WiFi, Bluetooth and the GPIO expander on the
+- Balena Fin board.
++ balenaFin carrier board for the Raspberry Pi Compute Module 3/3+ Lite.
+ Load: dtoverlay=balena-fin
+ Params: <None>
+
+--- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
++++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
+@@ -11,6 +11,7 @@
+ pinctrl-0 = <&sdio_pins>;
+ bus-width = <4>;
+ brcm,overclock-50 = <35>;
++ non-removable;
+ status = "okay";
+ };
+ };
+@@ -34,7 +35,8 @@
+ fragment@2 {
+ target-path = "/";
+ __overlay__ {
+- // We should investigate how to switch to mmc-pwrseq-sd8787
++ // We should switch to mmc-pwrseq-sd8787 after making it
++ // compatible with sd8887
+ // Currently that module requires two GPIOs to function since it
+ // targets a slightly different chip
+ power_ctrl: power_ctrl {
+@@ -46,10 +48,21 @@
+ i2c_soft: i2c@0 {
+ compatible = "i2c-gpio";
+ gpios = <&gpio 43 0 /* sda */ &gpio 42 0 /* scl */>;
+- i2c-gpio,delay-us = <2>; /* ~100 kHz */
++ i2c-gpio,delay-us = <5>;
++ i2c-gpio,scl-open-drain;
++ i2c-gpio,sda-open-drain;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
++
++ sd8xxx-wlan {
++ drvdbg = <0x6>;
++ drv_mode = <0x1>;
++ cfg80211_wext = <0xf>;
++ sta_name = "wlan";
++ wfd_name = "p2p";
++ cal_data_cfg = "none";
++ };
+ };
+ };
+
+@@ -74,6 +87,35 @@
+ reg = <0x68>;
+ status = "okay";
+ };
++
++ // RGB LEDs (>= v1.1.0)
++ pca9633: pca9633@62 {
++ compatible = "nxp,pca9633";
++ reg = <0x62>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ red@0 {
++ label = "red";
++ reg = <0>;
++ linux,default-trigger = "none";
++ };
++ green@1 {
++ label = "green";
++ reg = <1>;
++ linux,default-trigger = "none";
++ };
++ blue@2 {
++ label = "blue";
++ reg = <2>;
++ linux,default-trigger = "none";
++ };
++ unused@3 {
++ label = "unused";
++ reg = <3>;
++ linux,default-trigger = "none";
++ };
++ };
+ };
+ };
+ };
+++ /dev/null
-From ba6462e05310a26c30e22aab737db4eb5ae938a8 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 5 Feb 2019 12:31:23 +0000
-Subject: [PATCH 351/703] config: Add IPVLAN module to bcmrpi3_defconfig
-
-It's built for the 32bit kernels, but not for the 64bit ones.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -430,6 +430,7 @@ CONFIG_BONDING=m
- CONFIG_DUMMY=m
- CONFIG_IFB=m
- CONFIG_MACVLAN=m
-+CONFIG_IPVLAN=m
- CONFIG_VXLAN=m
- CONFIG_NETCONSOLE=m
- CONFIG_TUN=m
--- /dev/null
+From 6f7b49f8483bfbda41b7a33037729df18f2b84c7 Mon Sep 17 00:00:00 2001
+From: Zahari Petkov <zahari@balena.io>
+Date: Fri, 8 Feb 2019 13:33:47 +0200
+Subject: [PATCH 351/725] configs: Add CONFIG_LEDS_PCA963X=m
+
+Enable support for PCA963x I2C chip.
+
+Needed for the balenaFin v1.1.0 carrier board for the
+Raspberry Pi Compute Module 3/3+ Lite.
+
+Signed-off-by: Zahari Petkov <zahari@balena.io>
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ 3 files changed, 3 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -1124,6 +1124,7 @@ CONFIG_MMC_SDHCI_PLTFM=y
+ CONFIG_MMC_SPI=m
+ CONFIG_LEDS_CLASS=y
+ CONFIG_LEDS_GPIO=y
++CONFIG_LEDS_PCA963X=m
+ CONFIG_LEDS_TRIGGER_TIMER=y
+ CONFIG_LEDS_TRIGGER_ONESHOT=y
+ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -1117,6 +1117,7 @@ CONFIG_MMC_SDHCI_PLTFM=y
+ CONFIG_MMC_SPI=m
+ CONFIG_LEDS_CLASS=y
+ CONFIG_LEDS_GPIO=y
++CONFIG_LEDS_PCA963X=m
+ CONFIG_LEDS_TRIGGER_TIMER=y
+ CONFIG_LEDS_TRIGGER_ONESHOT=y
+ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -984,6 +984,7 @@ CONFIG_MMC_SDHCI_IPROC=m
+ CONFIG_MMC_SPI=m
+ CONFIG_LEDS_CLASS=y
+ CONFIG_LEDS_GPIO=y
++CONFIG_LEDS_PCA963X=m
+ CONFIG_LEDS_TRIGGER_TIMER=y
+ CONFIG_LEDS_TRIGGER_ONESHOT=y
+ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
--- /dev/null
+From 0f8f6eb08cb335806221680471fcaa9afe7ddd02 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 18 Feb 2019 15:43:30 +0000
+Subject: [PATCH 352/725] Revert "brcmfmac: Mute expected startup 'errors'"
+
+This reverts commit 34eba9138ccf8d84552ab9dae37d8f348640e663.
+
+Upstream patch 26e537884a ("brcmfmac: Do not complain about country code "00")
+fixes the same issue, so drop this downstream patch.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -6844,8 +6844,6 @@ static void brcmf_cfg80211_reg_notifier(
+ /* ignore non-ISO3166 country codes */
+ for (i = 0; i < 2; i++)
+ if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
+- if (req->alpha2[0] == '0' && req->alpha2[1] == '0')
+- return;
+ brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n",
+ req->alpha2[0], req->alpha2[1]);
+ return;
+++ /dev/null
-From 09e5438e80f821df067895228f0a78d28da17846 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 7 Feb 2019 18:16:25 +0000
-Subject: [PATCH 352/703] configs: Enable the AD193x codecs
-
-See: https://github.com/raspberrypi/linux/issues/2850
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/configs/bcm2709_defconfig | 2 ++
- arch/arm/configs/bcmrpi_defconfig | 2 ++
- arch/arm64/configs/bcmrpi3_defconfig | 2 ++
- sound/soc/codecs/Kconfig | 4 ++--
- 4 files changed, 8 insertions(+), 2 deletions(-)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -930,6 +930,8 @@ CONFIG_SND_BCM2708_SOC_ALLO_DIGIONE=m
- CONFIG_SND_BCM2708_SOC_ALLO_KATANA_DAC=m
- CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m
- CONFIG_SND_PISOUND=m
-+CONFIG_SND_SOC_AD193X_SPI=m
-+CONFIG_SND_SOC_AD193X_I2C=m
- CONFIG_SND_SOC_ADAU1701=m
- CONFIG_SND_SOC_ADAU7002=m
- CONFIG_SND_SOC_AK4554=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -923,6 +923,8 @@ CONFIG_SND_BCM2708_SOC_ALLO_DIGIONE=m
- CONFIG_SND_BCM2708_SOC_ALLO_KATANA_DAC=m
- CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m
- CONFIG_SND_PISOUND=m
-+CONFIG_SND_SOC_AD193X_SPI=m
-+CONFIG_SND_SOC_AD193X_I2C=m
- CONFIG_SND_SOC_ADAU1701=m
- CONFIG_SND_SOC_ADAU7002=m
- CONFIG_SND_SOC_AK4554=m
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -811,6 +811,8 @@ CONFIG_SND_DIGIDAC1_SOUNDCARD=m
- CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m
- CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m
- CONFIG_SND_PISOUND=m
-+CONFIG_SND_SOC_AD193X_SPI=m
-+CONFIG_SND_SOC_AD193X_I2C=m
- CONFIG_SND_SOC_ADAU1701=m
- CONFIG_SND_SOC_AK4554=m
- CONFIG_SND_SOC_CS4271_I2C=m
---- a/sound/soc/codecs/Kconfig
-+++ b/sound/soc/codecs/Kconfig
-@@ -295,11 +295,11 @@ config SND_SOC_AD193X
- tristate
-
- config SND_SOC_AD193X_SPI
-- tristate
-+ tristate "Analog Devices AU193X CODEC - SPI"
- select SND_SOC_AD193X
-
- config SND_SOC_AD193X_I2C
-- tristate
-+ tristate "Analog Devices AU193X CODEC - I2C"
- select SND_SOC_AD193X
-
- config SND_SOC_AD1980
--- /dev/null
+From fc900e617330d4d1763c517cec2d46c6ea59f29d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 19 Feb 2019 15:06:31 +0000
+Subject: [PATCH 353/725] gpu:vc4-fkms: Update driver to not use plane->crtc.
+
+Following on from
+commit 2f958af7fc248 ("drm/vc4: Stop updating plane->fb/crtc")
+do the same in the firmwarekms driver and look at plane_state->crtc
+instead.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -193,8 +193,8 @@ static void vc4_cursor_plane_atomic_upda
+ struct drm_plane_state *old_state)
+ {
+ struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
+- struct vc4_crtc *vc4_crtc = to_vc4_crtc(plane->crtc);
+ struct drm_plane_state *state = plane->state;
++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
+ struct drm_framebuffer *fb = state->fb;
+ struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
+ dma_addr_t addr = bo->paddr + fb->offsets[0];
+@@ -682,8 +682,6 @@ static int vc4_fkms_bind(struct device *
+ 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_encoder = devm_kzalloc(dev, sizeof(*vc4_encoder), GFP_KERNEL);
+ if (!vc4_encoder)
+++ /dev/null
-From d9e484de16eef5f3daa61a8df462ff35ebe1aedc Mon Sep 17 00:00:00 2001
-From: Zahari Petkov <zahari@balena.io>
-Date: Fri, 8 Feb 2019 13:03:38 +0200
-Subject: [PATCH 353/703] overlays: balenaFin v1.1.0 carrier board update
-
-A backward compatible update for the balenaFin carrier board for the
-Raspberry Pi Compute Module 3/3+ Lite.
-
-The updated overlay includes:
- * support for the newly introduced RGB LEDs
- * i2c-gpio and SDIO improvements
- * DT based Marvell 88W8887 configuration
-
-Signed-off-by: Zahari Petkov <zahari@balena.io>
----
- arch/arm/boot/dts/overlays/README | 2 +-
- .../boot/dts/overlays/balena-fin-overlay.dts | 46 ++++++++++++++++++-
- 2 files changed, 45 insertions(+), 3 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -472,7 +472,7 @@ Params: swap_lr Reverse
-
- Name: balena-fin
- Info: Overlay that enables WiFi, Bluetooth and the GPIO expander on the
-- Balena Fin board.
-+ balenaFin carrier board for the Raspberry Pi Compute Module 3/3+ Lite.
- Load: dtoverlay=balena-fin
- Params: <None>
-
---- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-@@ -11,6 +11,7 @@
- pinctrl-0 = <&sdio_pins>;
- bus-width = <4>;
- brcm,overclock-50 = <35>;
-+ non-removable;
- status = "okay";
- };
- };
-@@ -34,7 +35,8 @@
- fragment@2 {
- target-path = "/";
- __overlay__ {
-- // We should investigate how to switch to mmc-pwrseq-sd8787
-+ // We should switch to mmc-pwrseq-sd8787 after making it
-+ // compatible with sd8887
- // Currently that module requires two GPIOs to function since it
- // targets a slightly different chip
- power_ctrl: power_ctrl {
-@@ -46,10 +48,21 @@
- i2c_soft: i2c@0 {
- compatible = "i2c-gpio";
- gpios = <&gpio 43 0 /* sda */ &gpio 42 0 /* scl */>;
-- i2c-gpio,delay-us = <2>; /* ~100 kHz */
-+ i2c-gpio,delay-us = <5>;
-+ i2c-gpio,scl-open-drain;
-+ i2c-gpio,sda-open-drain;
- #address-cells = <1>;
- #size-cells = <0>;
- };
-+
-+ sd8xxx-wlan {
-+ drvdbg = <0x6>;
-+ drv_mode = <0x1>;
-+ cfg80211_wext = <0xf>;
-+ sta_name = "wlan";
-+ wfd_name = "p2p";
-+ cal_data_cfg = "none";
-+ };
- };
- };
-
-@@ -74,6 +87,35 @@
- reg = <0x68>;
- status = "okay";
- };
-+
-+ // RGB LEDs (>= v1.1.0)
-+ pca9633: pca9633@62 {
-+ compatible = "nxp,pca9633";
-+ reg = <0x62>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ red@0 {
-+ label = "red";
-+ reg = <0>;
-+ linux,default-trigger = "none";
-+ };
-+ green@1 {
-+ label = "green";
-+ reg = <1>;
-+ linux,default-trigger = "none";
-+ };
-+ blue@2 {
-+ label = "blue";
-+ reg = <2>;
-+ linux,default-trigger = "none";
-+ };
-+ unused@3 {
-+ label = "unused";
-+ reg = <3>;
-+ linux,default-trigger = "none";
-+ };
-+ };
- };
- };
- };
+++ /dev/null
-From dbf219eac8302d979a6602b7f2f48ca58a0225e7 Mon Sep 17 00:00:00 2001
-From: Zahari Petkov <zahari@balena.io>
-Date: Fri, 8 Feb 2019 13:33:47 +0200
-Subject: [PATCH 354/703] configs: Add CONFIG_LEDS_PCA963X=m
-
-Enable support for PCA963x I2C chip.
-
-Needed for the balenaFin v1.1.0 carrier board for the
-Raspberry Pi Compute Module 3/3+ Lite.
-
-Signed-off-by: Zahari Petkov <zahari@balena.io>
----
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- 3 files changed, 3 insertions(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -1124,6 +1124,7 @@ CONFIG_MMC_SDHCI_PLTFM=y
- CONFIG_MMC_SPI=m
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
-+CONFIG_LEDS_PCA963X=m
- CONFIG_LEDS_TRIGGER_TIMER=y
- CONFIG_LEDS_TRIGGER_ONESHOT=y
- CONFIG_LEDS_TRIGGER_HEARTBEAT=y
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -1117,6 +1117,7 @@ CONFIG_MMC_SDHCI_PLTFM=y
- CONFIG_MMC_SPI=m
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
-+CONFIG_LEDS_PCA963X=m
- CONFIG_LEDS_TRIGGER_TIMER=y
- CONFIG_LEDS_TRIGGER_ONESHOT=y
- CONFIG_LEDS_TRIGGER_HEARTBEAT=y
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -984,6 +984,7 @@ CONFIG_MMC_SDHCI_IPROC=m
- CONFIG_MMC_SPI=m
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
-+CONFIG_LEDS_PCA963X=m
- CONFIG_LEDS_TRIGGER_TIMER=y
- CONFIG_LEDS_TRIGGER_ONESHOT=y
- CONFIG_LEDS_TRIGGER_HEARTBEAT=y
--- /dev/null
+From 85081cca82099c3fc27c3eaa9342928ca99e2ede Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 19 Feb 2019 15:18:25 +0000
+Subject: [PATCH 354/725] drm: vc4: Programming the CTM is conditional on
+ running full KMS
+
+vc4_ctm_commit writes to HVS registers, so this is only applicable
+when in full KMS mode, not in firmware KMS mode. Add this conditional.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_kms.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -147,7 +147,8 @@ vc4_atomic_complete_commit(struct drm_at
+
+ drm_atomic_helper_commit_modeset_disables(dev, state);
+
+- vc4_ctm_commit(vc4, state);
++ if (!vc4->firmware_kms)
++ vc4_ctm_commit(vc4, state);
+
+ drm_atomic_helper_commit_planes(dev, state, 0);
+
+++ /dev/null
-From a0ee8937092bd619a1b99cc5e39dc579be5fdd9a Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 18 Feb 2019 15:43:30 +0000
-Subject: [PATCH 355/703] Revert "brcmfmac: Mute expected startup 'errors'"
-
-This reverts commit 34eba9138ccf8d84552ab9dae37d8f348640e663.
-
-Upstream patch 26e537884a ("brcmfmac: Do not complain about country code "00")
-fixes the same issue, so drop this downstream patch.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 --
- 1 file changed, 2 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -6844,8 +6844,6 @@ static void brcmf_cfg80211_reg_notifier(
- /* ignore non-ISO3166 country codes */
- for (i = 0; i < 2; i++)
- if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
-- if (req->alpha2[0] == '0' && req->alpha2[1] == '0')
-- return;
- brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n",
- req->alpha2[0], req->alpha2[1]);
- return;
--- /dev/null
+From 52c981d9c8330fe6c34d436083bee9ecc9d5c80c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 13 Feb 2019 12:33:29 +0000
+Subject: [PATCH 355/725] staging: mmal_vchiq: Add in the Bayer encoding
+ formats
+
+The list of formats was copied before Bayer support was added.
+The ISP supports Bayer and is being supported by the bcm2835_codec
+driver, so add in the encodings for them.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/vchiq-mmal/mmal-encodings.h | 27 +++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
+@@ -69,6 +69,33 @@
+ */
+ #define MMAL_ENCODING_OPAQUE MMAL_FOURCC('O', 'P', 'Q', 'V')
+
++/* Bayer formats
++ * FourCC values copied from V4L2 where defined.
++ */
++/* 8 bit per pixel Bayer formats. */
++#define MMAL_ENCODING_BAYER_SBGGR8 MMAL_FOURCC('B', 'A', '8', '1')
++#define MMAL_ENCODING_BAYER_SGBRG8 MMAL_FOURCC('G', 'B', 'R', 'G')
++#define MMAL_ENCODING_BAYER_SGRBG8 MMAL_FOURCC('G', 'R', 'B', 'G')
++#define MMAL_ENCODING_BAYER_SRGGB8 MMAL_FOURCC('R', 'G', 'G', 'B')
++
++/* 10 bit per pixel packed Bayer formats. */
++#define MMAL_ENCODING_BAYER_SBGGR10P MMAL_FOURCC('p', 'B', 'A', 'A')
++#define MMAL_ENCODING_BAYER_SGRBG10P MMAL_FOURCC('p', 'g', 'A', 'A')
++#define MMAL_ENCODING_BAYER_SGBRG10P MMAL_FOURCC('p', 'G', 'A', 'A')
++#define MMAL_ENCODING_BAYER_SRGGB10P MMAL_FOURCC('p', 'R', 'A', 'A')
++
++/* 12 bit per pixel packed Bayer formats. */
++#define MMAL_ENCODING_BAYER_SBGGR12P MMAL_FOURCC('p', 'B', '1', '2')
++#define MMAL_ENCODING_BAYER_SGRBG12P MMAL_FOURCC('p', 'g', '1', '2')
++#define MMAL_ENCODING_BAYER_SGBRG12P MMAL_FOURCC('p', 'G', '1', '2')
++#define MMAL_ENCODING_BAYER_SRGGB12P MMAL_FOURCC('p', 'R', '1', '2')
++
++/* 16 bit per pixel Bayer formats. */
++#define MMAL_ENCODING_BAYER_SBGGR16 MMAL_FOURCC('B', 'G', '1', '6')
++#define MMAL_ENCODING_BAYER_SGBRG16 MMAL_FOURCC('G', 'B', '1', '6')
++#define MMAL_ENCODING_BAYER_SGRBG16 MMAL_FOURCC('G', 'R', '1', '6')
++#define MMAL_ENCODING_BAYER_SRGGB16 MMAL_FOURCC('R', 'G', '1', '6')
++
+ /** An EGL image handle
+ */
+ #define MMAL_ENCODING_EGL_IMAGE MMAL_FOURCC('E', 'G', 'L', 'I')
+++ /dev/null
-From 477a46fa014209503a601add47994f7bc4b2093a Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 19 Feb 2019 15:06:31 +0000
-Subject: [PATCH 356/703] gpu:vc4-fkms: Update driver to not use plane->crtc.
-
-Following on from
-commit 2f958af7fc248 ("drm/vc4: Stop updating plane->fb/crtc")
-do the same in the firmwarekms driver and look at plane_state->crtc
-instead.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 4 +---
- 1 file changed, 1 insertion(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -193,8 +193,8 @@ static void vc4_cursor_plane_atomic_upda
- struct drm_plane_state *old_state)
- {
- struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
-- struct vc4_crtc *vc4_crtc = to_vc4_crtc(plane->crtc);
- struct drm_plane_state *state = plane->state;
-+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
- struct drm_framebuffer *fb = state->fb;
- struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
- dma_addr_t addr = bo->paddr + fb->offsets[0];
-@@ -682,8 +682,6 @@ static int vc4_fkms_bind(struct device *
- 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_encoder = devm_kzalloc(dev, sizeof(*vc4_encoder), GFP_KERNEL);
- if (!vc4_encoder)
--- /dev/null
+From ffdd605fc5bf096855bd24311bb0f112257dd53e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 13 Feb 2019 12:36:56 +0000
+Subject: [PATCH 356/725] staging: mmal-vchiq: Always return the param size
+ from param_get
+
+mmal-vchiq is a reimplementation of the userland library for MMAL.
+When getting a parameter, the client provides the storage and
+the size of the storage. The VPU then returns the size of the
+parameter that it wished to return, and as much as possible of
+that parameter is returned to the client.
+
+The implementation previously only returned the size provided
+by the VPU should it exceed the buffer size. So for parameters
+such as the supported encodings list the client had no idea
+how much of the provided storage had been populated.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -1413,11 +1413,12 @@ static int port_parameter_get(struct vch
+ */
+ 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);
+ }
++ /* Always report the size of the returned parameter to the caller */
++ *value_size = 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);
+++ /dev/null
-From d75d01225814a7c722affe33f3bfe0ba72fe49a8 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 19 Feb 2019 15:18:25 +0000
-Subject: [PATCH 357/703] drm: vc4: Programming the CTM is conditional on
- running full KMS
-
-vc4_ctm_commit writes to HVS registers, so this is only applicable
-when in full KMS mode, not in firmware KMS mode. Add this conditional.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_kms.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -147,7 +147,8 @@ vc4_atomic_complete_commit(struct drm_at
-
- drm_atomic_helper_commit_modeset_disables(dev, state);
-
-- vc4_ctm_commit(vc4, state);
-+ if (!vc4->firmware_kms)
-+ vc4_ctm_commit(vc4, state);
-
- drm_atomic_helper_commit_planes(dev, state, 0);
-
--- /dev/null
+From 778f855d699bd67e1eb177c7a0bcc30af550ce6a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 13 Feb 2019 12:51:03 +0000
+Subject: [PATCH 357/725] staging: mmal-vchiq: If the VPU returns an error,
+ don't negate it
+
+There is an enum for the errors that the VPU can return.
+port_parameter_get was negating that value, but also using -EINVAL
+from the Linux error codes.
+Pass the VPU error code as positive values. Should the function
+need to pass a Linux failure, then return that as negative.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -1401,7 +1401,8 @@ static int port_parameter_get(struct vch
+ goto release_msg;
+ }
+
+- ret = -rmsg->u.port_parameter_get_reply.status;
++ ret = rmsg->u.port_parameter_get_reply.status;
++
+ /* port_parameter_get_reply.size includes the header,
+ * whilst *value_size doesn't.
+ */
--- /dev/null
+From b39574e09f52569d27b1904771a433f02bf5e547 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 13 Feb 2019 13:44:00 +0000
+Subject: [PATCH 358/725] staging: bcm2835_codec: Query supported formats from
+ the component
+
+The driver was previously working with hard coded tables of
+which video formats were supported by each component.
+The components advertise this information via a MMAL parameter,
+so retrieve the information from there during probe, and store
+in the state structure for that device.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c | 455 +++++++++++++-----
+ 1 file changed, 327 insertions(+), 128 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -88,17 +88,12 @@ struct bcm2835_codec_fmt {
+ int bytesperline_align;
+ u32 flags;
+ u32 mmal_fmt;
+- bool decode_only;
+- bool encode_only;
+ int size_multiplier_x2;
+ };
+
+-/* Supported raw pixel formats. Those supported for both encode and decode
+- * must come first, with those only supported for decode coming after (there
+- * are no formats supported for encode only).
+- */
+-static struct bcm2835_codec_fmt raw_formats[] = {
++static const struct bcm2835_codec_fmt supported_formats[] = {
+ {
++ /* YUV formats */
+ .fourcc = V4L2_PIX_FMT_YUV420,
+ .depth = 8,
+ .bytesperline_align = 32,
+@@ -139,7 +134,6 @@ static struct bcm2835_codec_fmt raw_form
+ .bytesperline_align = 32,
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_YUYV,
+- .encode_only = true,
+ .size_multiplier_x2 = 2,
+ }, {
+ .fourcc = V4L2_PIX_FMT_UYVY,
+@@ -147,7 +141,6 @@ static struct bcm2835_codec_fmt raw_form
+ .bytesperline_align = 32,
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_UYVY,
+- .encode_only = true,
+ .size_multiplier_x2 = 2,
+ }, {
+ .fourcc = V4L2_PIX_FMT_YVYU,
+@@ -155,7 +148,6 @@ static struct bcm2835_codec_fmt raw_form
+ .bytesperline_align = 32,
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_YVYU,
+- .encode_only = true,
+ .size_multiplier_x2 = 2,
+ }, {
+ .fourcc = V4L2_PIX_FMT_VYUY,
+@@ -163,15 +155,14 @@ static struct bcm2835_codec_fmt raw_form
+ .bytesperline_align = 32,
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_VYUY,
+- .encode_only = true,
+ .size_multiplier_x2 = 2,
+ }, {
++ /* RGB formats */
+ .fourcc = V4L2_PIX_FMT_RGB24,
+ .depth = 24,
+ .bytesperline_align = 32,
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_RGB24,
+- .encode_only = true,
+ .size_multiplier_x2 = 2,
+ }, {
+ .fourcc = V4L2_PIX_FMT_BGR24,
+@@ -179,7 +170,6 @@ static struct bcm2835_codec_fmt raw_form
+ .bytesperline_align = 32,
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BGR24,
+- .encode_only = true,
+ .size_multiplier_x2 = 2,
+ }, {
+ .fourcc = V4L2_PIX_FMT_BGR32,
+@@ -187,17 +177,126 @@ static struct bcm2835_codec_fmt raw_form
+ .bytesperline_align = 32,
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BGRA,
+- .encode_only = true,
+ .size_multiplier_x2 = 2,
+- },
+-};
+-
+-/* Supported encoded formats. Those supported for both encode and decode
+- * must come first, with those only supported for decode coming after (there
+- * are no formats supported for encode only).
+- */
+-static struct bcm2835_codec_fmt encoded_formats[] = {
+- {
++ }, {
++ /* Bayer formats */
++ /* 8 bit */
++ .fourcc = V4L2_PIX_FMT_SRGGB8,
++ .depth = 8,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB8,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SBGGR8,
++ .depth = 8,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR8,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGRBG8,
++ .depth = 8,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG8,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGBRG8,
++ .depth = 8,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG8,
++ .size_multiplier_x2 = 2,
++ }, {
++ /* 10 bit */
++ .fourcc = V4L2_PIX_FMT_SRGGB10P,
++ .depth = 10,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB10P,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SBGGR10P,
++ .depth = 10,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR10P,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGRBG10P,
++ .depth = 10,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG10P,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGBRG10P,
++ .depth = 10,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG10P,
++ .size_multiplier_x2 = 2,
++ }, {
++ /* 12 bit */
++ .fourcc = V4L2_PIX_FMT_SRGGB12P,
++ .depth = 12,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB12P,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SBGGR12P,
++ .depth = 12,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR12P,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGRBG12P,
++ .depth = 12,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG12P,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGBRG12P,
++ .depth = 12,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG12P,
++ .size_multiplier_x2 = 2,
++ }, {
++ /* 16 bit */
++ .fourcc = V4L2_PIX_FMT_SRGGB16,
++ .depth = 16,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB16,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SBGGR16,
++ .depth = 16,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR16,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGRBG16,
++ .depth = 16,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG16,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGBRG16,
++ .depth = 16,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG16,
++ .size_multiplier_x2 = 2,
++ }, {
++ /* Compressed formats */
+ .fourcc = V4L2_PIX_FMT_H264,
+ .depth = 0,
+ .flags = V4L2_FMT_FLAG_COMPRESSED,
+@@ -212,30 +311,22 @@ static struct bcm2835_codec_fmt encoded_
+ .depth = 0,
+ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal_fmt = MMAL_ENCODING_MP4V,
+- .decode_only = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_H263,
+ .depth = 0,
+ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal_fmt = MMAL_ENCODING_H263,
+- .decode_only = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_MPEG2,
+ .depth = 0,
+ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal_fmt = MMAL_ENCODING_MP2V,
+- .decode_only = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_VP8,
+ .depth = 0,
+ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal_fmt = MMAL_ENCODING_VP8,
+- .decode_only = true,
+ },
+- /*
+- * This list couold include VP6 and Theorafor decode, but V4L2 doesn't
+- * support them.
+- */
+ };
+
+ struct bcm2835_codec_fmt_list {
+@@ -243,19 +334,6 @@ struct bcm2835_codec_fmt_list {
+ unsigned int num_entries;
+ };
+
+-#define RAW_LIST 0
+-#define ENCODED_LIST 1
+-
+-struct bcm2835_codec_fmt_list formats[] = {
+- {
+- .list = raw_formats,
+- .num_entries = ARRAY_SIZE(raw_formats),
+- }, {
+- .list = encoded_formats,
+- .num_entries = ARRAY_SIZE(encoded_formats),
+- },
+-};
+-
+ struct m2m_mmal_buffer {
+ struct v4l2_m2m_buffer m2m;
+ struct mmal_buffer mmal;
+@@ -284,52 +362,6 @@ struct bcm2835_codec_q_data {
+ bool eos_buffer_in_use; /* debug only */
+ };
+
+-enum {
+- V4L2_M2M_SRC = 0,
+- V4L2_M2M_DST = 1,
+-};
+-
+-static inline struct bcm2835_codec_fmt_list *get_format_list(bool decode,
+- bool capture)
+-{
+- return decode ^ capture ? &formats[ENCODED_LIST] : &formats[RAW_LIST];
+-}
+-
+-static struct bcm2835_codec_fmt *get_default_format(bool decode, bool capture)
+-{
+- return &get_format_list(decode, capture)->list[0];
+-}
+-
+-static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f, bool decode,
+- bool capture)
+-{
+- struct bcm2835_codec_fmt *fmt;
+- unsigned int k;
+- struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
+-
+- for (k = 0; k < fmts->num_entries; k++) {
+- fmt = &fmts->list[k];
+- if (fmt->fourcc == f->fmt.pix.pixelformat)
+- break;
+- }
+-
+- /*
+- * Some compressed formats are only supported for decoding, not
+- * encoding.
+- */
+- if (!decode && fmts->list[k].decode_only)
+- return NULL;
+-
+- /* Some pixel formats are only supported for encoding, not decoding. */
+- if (decode && fmts->list[k].encode_only)
+- return NULL;
+-
+- if (k == fmts->num_entries)
+- return NULL;
+-
+- return &fmts->list[k];
+-}
+-
+ struct bcm2835_codec_dev {
+ struct platform_device *pdev;
+
+@@ -342,6 +374,9 @@ struct bcm2835_codec_dev {
+
+ /* allocated mmal instance and components */
+ bool decode; /* Is this instance a decoder? */
++ /* The list of formats supported on input and output queues. */
++ struct bcm2835_codec_fmt_list supported_fmts[2];
++
+ struct vchiq_mmal_instance *instance;
+
+ struct v4l2_m2m_dev *m2m_dev;
+@@ -374,8 +409,59 @@ struct bcm2835_codec_ctx {
+ struct bcm2835_codec_driver {
+ struct bcm2835_codec_dev *encode;
+ struct bcm2835_codec_dev *decode;
++ struct bcm2835_codec_dev *isp;
++};
++
++enum {
++ V4L2_M2M_SRC = 0,
++ V4L2_M2M_DST = 1,
+ };
+
++static const struct bcm2835_codec_fmt *get_fmt(u32 mmal_fmt)
++{
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
++ if (supported_formats[i].mmal_fmt == mmal_fmt)
++ return &supported_formats[i];
++ }
++ return NULL;
++}
++
++static inline
++struct bcm2835_codec_fmt_list *get_format_list(struct bcm2835_codec_dev *dev,
++ bool capture)
++{
++ return &dev->supported_fmts[capture ? 1 : 0];
++}
++
++static
++struct bcm2835_codec_fmt *get_default_format(struct bcm2835_codec_dev *dev,
++ bool capture)
++{
++ return &dev->supported_fmts[capture ? 1 : 0].list[0];
++}
++
++static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f,
++ struct bcm2835_codec_dev *dev,
++ bool capture)
++{
++ struct bcm2835_codec_fmt *fmt;
++ unsigned int k;
++ struct bcm2835_codec_fmt_list *fmts =
++ &dev->supported_fmts[capture ? 1 : 0];
++
++ for (k = 0; k < fmts->num_entries; k++) {
++ fmt = &fmts->list[k];
++ if (fmt->fourcc == f->fmt.pix.pixelformat)
++ break;
++ }
++ if (k == fmts->num_entries)
++ return NULL;
++
++ return &fmts->list[k];
++}
++
+ static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
+ {
+ return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
+@@ -456,7 +542,6 @@ static inline unsigned int get_bytesperl
+ }
+
+ static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
+- bool decode,
+ struct bcm2835_codec_q_data *q_data,
+ struct vchiq_mmal_port *port)
+ {
+@@ -473,7 +558,7 @@ static void setup_mmal_port_format(struc
+ port->es.video.frame_rate.den = 1;
+ } else {
+ /* Compressed format - leave resolution as 0 for decode */
+- if (decode) {
++ if (ctx->dev->decode) {
+ port->es.video.width = 0;
+ port->es.video.height = 0;
+ port->es.video.crop.width = 0;
+@@ -802,22 +887,15 @@ static int vidioc_querycap(struct file *
+ return 0;
+ }
+
+-static int enum_fmt(struct v4l2_fmtdesc *f, bool decode, bool capture)
++static int enum_fmt(struct v4l2_fmtdesc *f, struct bcm2835_codec_ctx *ctx,
++ bool capture)
+ {
+ struct bcm2835_codec_fmt *fmt;
+- struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
++ struct bcm2835_codec_fmt_list *fmts =
++ get_format_list(ctx->dev, capture);
+
+ if (f->index < fmts->num_entries) {
+ /* Format found */
+- /* Check format isn't a decode only format when encoding */
+- if (!decode &&
+- fmts->list[f->index].decode_only)
+- return -EINVAL;
+- /* Check format isn't a decode only format when encoding */
+- if (decode &&
+- fmts->list[f->index].encode_only)
+- return -EINVAL;
+-
+ fmt = &fmts->list[f->index];
+ f->pixelformat = fmt->fourcc;
+ f->flags = fmt->flags;
+@@ -833,7 +911,7 @@ static int vidioc_enum_fmt_vid_cap(struc
+ {
+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
+
+- return enum_fmt(f, ctx->dev->decode, true);
++ return enum_fmt(f, ctx, true);
+ }
+
+ static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
+@@ -841,7 +919,7 @@ static int vidioc_enum_fmt_vid_out(struc
+ {
+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
+
+- return enum_fmt(f, ctx->dev->decode, false);
++ return enum_fmt(f, ctx, false);
+ }
+
+ static int vidioc_g_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f)
+@@ -933,11 +1011,11 @@ static int vidioc_try_fmt_vid_cap(struct
+ struct bcm2835_codec_fmt *fmt;
+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
+
+- fmt = find_format(f, ctx->dev->decode, true);
++ fmt = find_format(f, ctx->dev, true);
+ if (!fmt) {
+- f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
++ f->fmt.pix.pixelformat = get_default_format(ctx->dev,
+ true)->fourcc;
+- fmt = find_format(f, ctx->dev->decode, true);
++ fmt = find_format(f, ctx->dev, true);
+ }
+
+ return vidioc_try_fmt(f, fmt);
+@@ -949,11 +1027,11 @@ static int vidioc_try_fmt_vid_out(struct
+ struct bcm2835_codec_fmt *fmt;
+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
+
+- fmt = find_format(f, ctx->dev->decode, false);
++ fmt = find_format(f, ctx->dev, false);
+ if (!fmt) {
+- f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
++ f->fmt.pix.pixelformat = get_default_format(ctx->dev,
+ false)->fourcc;
+- fmt = find_format(f, ctx->dev->decode, false);
++ fmt = find_format(f, ctx->dev, false);
+ }
+
+ if (!f->fmt.pix.colorspace)
+@@ -988,7 +1066,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+ return -EBUSY;
+ }
+
+- q_data->fmt = find_format(f, ctx->dev->decode,
++ q_data->fmt = find_format(f, ctx->dev,
+ f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ q_data->crop_width = f->fmt.pix.width;
+ q_data->height = f->fmt.pix.height;
+@@ -1041,7 +1119,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+ if (!port)
+ return 0;
+
+- setup_mmal_port_format(ctx, ctx->dev->decode, q_data, port);
++ setup_mmal_port_format(ctx, q_data, port);
+ ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
+ if (ret) {
+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on port, ret %d\n",
+@@ -1064,8 +1142,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+ struct bcm2835_codec_q_data *q_data_dst =
+ &ctx->q_data[V4L2_M2M_DST];
+
+- setup_mmal_port_format(ctx, ctx->dev->decode, q_data_dst,
+- port_dst);
++ setup_mmal_port_format(ctx, q_data_dst, port_dst);
+ ret = vchiq_mmal_port_set_format(ctx->dev->instance, port_dst);
+ if (ret) {
+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on output port, ret %d\n",
+@@ -1636,10 +1713,10 @@ static int bcm2835_codec_create_componen
+ MMAL_PARAMETER_ZERO_COPY, &enable,
+ sizeof(enable));
+
+- setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_SRC],
++ setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_SRC],
+ &ctx->component->input[0]);
+
+- setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_DST],
++ setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_DST],
+ &ctx->component->output[0]);
+
+ ret = vchiq_mmal_port_set_format(dev->instance,
+@@ -2025,8 +2102,8 @@ static int bcm2835_codec_open(struct fil
+ goto open_unlock;
+ }
+
+- ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev->decode, false);
+- ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev->decode, true);
++ ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
++ ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
+ if (dev->decode) {
+ /*
+ * Input width and height are irrelevant as they will be defined
+@@ -2209,13 +2286,130 @@ static const struct v4l2_m2m_ops m2m_ops
+ .job_abort = job_abort,
+ };
+
++/* Size of the array to provide to the VPU when asking for the list of supported
++ * formats.
++ * The ISP component currently advertises 33 input formats, so add a small
++ * overhead on that.
++ */
++#define MAX_SUPPORTED_ENCODINGS 40
++
++/* Populate dev->supported_fmts with the formats supported by those ports. */
++static int bcm2835_codec_get_supported_fmts(struct bcm2835_codec_dev *dev)
++{
++ struct bcm2835_codec_fmt *list;
++ struct vchiq_mmal_component *component;
++ u32 fourccs[MAX_SUPPORTED_ENCODINGS];
++ u32 param_size = sizeof(fourccs);
++ unsigned int i, j, num_encodings;
++ int ret;
++
++ ret = vchiq_mmal_component_init(dev->instance,
++ dev->decode ?
++ "ril.video_decode" :
++ "ril.video_encode",
++ &component);
++ if (ret < 0) {
++ v4l2_err(&dev->v4l2_dev, "%s: failed to create component\n",
++ __func__);
++ return -ENOMEM;
++ }
++
++ ret = vchiq_mmal_port_parameter_get(dev->instance,
++ &component->input[0],
++ MMAL_PARAMETER_SUPPORTED_ENCODINGS,
++ &fourccs,
++ ¶m_size);
++
++ if (ret) {
++ if (ret == MMAL_MSG_STATUS_ENOSPC) {
++ v4l2_err(&dev->v4l2_dev, "%s: port has more encoding than we provided space for. Some are dropped.\n",
++ __func__);
++ num_encodings = MAX_SUPPORTED_ENCODINGS;
++ } else {
++ v4l2_err(&dev->v4l2_dev, "%s: get_param ret %u.\n",
++ __func__, ret);
++ ret = -EINVAL;
++ goto destroy_component;
++ }
++ } else {
++ num_encodings = param_size / sizeof(u32);
++ }
++
++ /* Assume at this stage that all encodings will be supported in V4L2.
++ * Any that aren't supported will waste a very small amount of memory.
++ */
++ list = devm_kzalloc(&dev->pdev->dev,
++ sizeof(struct bcm2835_codec_fmt) * num_encodings,
++ GFP_KERNEL);
++ if (!list) {
++ ret = -ENOMEM;
++ goto destroy_component;
++ }
++ dev->supported_fmts[0].list = list;
++
++ for (i = 0, j = 0; i < num_encodings; i++) {
++ const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
++
++ if (fmt) {
++ list[j] = *fmt;
++ j++;
++ }
++ }
++ dev->supported_fmts[0].num_entries = j;
++
++ param_size = sizeof(fourccs);
++ ret = vchiq_mmal_port_parameter_get(dev->instance,
++ &component->output[0],
++ MMAL_PARAMETER_SUPPORTED_ENCODINGS,
++ &fourccs,
++ ¶m_size);
++
++ if (ret) {
++ if (ret == MMAL_MSG_STATUS_ENOSPC) {
++ v4l2_err(&dev->v4l2_dev, "%s: port has more encoding than we provided space for. Some are dropped.\n",
++ __func__);
++ num_encodings = MAX_SUPPORTED_ENCODINGS;
++ } else {
++ ret = -EINVAL;
++ goto destroy_component;
++ }
++ } else {
++ num_encodings = param_size / sizeof(u32);
++ }
++ /* Assume at this stage that all encodings will be supported in V4L2. */
++ list = devm_kzalloc(&dev->pdev->dev,
++ sizeof(struct bcm2835_codec_fmt) * num_encodings,
++ GFP_KERNEL);
++ if (!list) {
++ ret = -ENOMEM;
++ goto destroy_component;
++ }
++ dev->supported_fmts[1].list = list;
++
++ for (i = 0, j = 0; i < num_encodings; i++) {
++ const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
++
++ if (fmt) {
++ list[j] = *fmt;
++ j++;
++ }
++ }
++ dev->supported_fmts[1].num_entries = j;
++
++ ret = 0;
++
++destroy_component:
++ vchiq_mmal_component_finalise(dev->instance, component);
++
++ return ret;
++}
++
+ static int bcm2835_codec_create(struct platform_device *pdev,
+ struct bcm2835_codec_dev **new_dev,
+ bool decode)
+ {
+ struct bcm2835_codec_dev *dev;
+ struct video_device *vfd;
+- struct vchiq_mmal_instance *instance = NULL;
+ int video_nr;
+ int ret;
+
+@@ -2227,10 +2421,18 @@ static int bcm2835_codec_create(struct p
+
+ dev->decode = decode;
+
+- ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
++ ret = vchiq_mmal_init(&dev->instance);
+ if (ret)
+ return ret;
+
++ ret = bcm2835_codec_get_supported_fmts(dev);
++ if (ret)
++ goto vchiq_finalise;
++
++ ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
++ if (ret)
++ goto vchiq_finalise;
++
+ atomic_set(&dev->num_inst, 0);
+ mutex_init(&dev->dev_mutex);
+
+@@ -2270,12 +2472,7 @@ static int bcm2835_codec_create(struct p
+ goto err_m2m;
+ }
+
+- ret = vchiq_mmal_init(&instance);
+- if (ret < 0)
+- goto err_m2m;
+- dev->instance = instance;
+-
+- v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s codec\n",
++ v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
+ dev->decode ? "decode" : "encode");
+ return 0;
+
+@@ -2284,7 +2481,8 @@ err_m2m:
+ video_unregister_device(&dev->vfd);
+ unreg_dev:
+ v4l2_device_unregister(&dev->v4l2_dev);
+-
++vchiq_finalise:
++ vchiq_mmal_finalise(dev->instance);
+ return ret;
+ }
+
+@@ -2297,6 +2495,7 @@ static int bcm2835_codec_destroy(struct
+ v4l2_m2m_release(dev->m2m_dev);
+ video_unregister_device(&dev->vfd);
+ v4l2_device_unregister(&dev->v4l2_dev);
++ vchiq_mmal_finalise(dev->instance);
+
+ return 0;
+ }
+++ /dev/null
-From f65a0ba774c5ef012f45ea3136565713aa4884d5 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 13 Feb 2019 12:33:29 +0000
-Subject: [PATCH 358/703] staging: mmal_vchiq: Add in the Bayer encoding
- formats
-
-The list of formats was copied before Bayer support was added.
-The ISP supports Bayer and is being supported by the bcm2835_codec
-driver, so add in the encodings for them.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/vchiq-mmal/mmal-encodings.h | 27 +++++++++++++++++++
- 1 file changed, 27 insertions(+)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
-@@ -69,6 +69,33 @@
- */
- #define MMAL_ENCODING_OPAQUE MMAL_FOURCC('O', 'P', 'Q', 'V')
-
-+/* Bayer formats
-+ * FourCC values copied from V4L2 where defined.
-+ */
-+/* 8 bit per pixel Bayer formats. */
-+#define MMAL_ENCODING_BAYER_SBGGR8 MMAL_FOURCC('B', 'A', '8', '1')
-+#define MMAL_ENCODING_BAYER_SGBRG8 MMAL_FOURCC('G', 'B', 'R', 'G')
-+#define MMAL_ENCODING_BAYER_SGRBG8 MMAL_FOURCC('G', 'R', 'B', 'G')
-+#define MMAL_ENCODING_BAYER_SRGGB8 MMAL_FOURCC('R', 'G', 'G', 'B')
-+
-+/* 10 bit per pixel packed Bayer formats. */
-+#define MMAL_ENCODING_BAYER_SBGGR10P MMAL_FOURCC('p', 'B', 'A', 'A')
-+#define MMAL_ENCODING_BAYER_SGRBG10P MMAL_FOURCC('p', 'g', 'A', 'A')
-+#define MMAL_ENCODING_BAYER_SGBRG10P MMAL_FOURCC('p', 'G', 'A', 'A')
-+#define MMAL_ENCODING_BAYER_SRGGB10P MMAL_FOURCC('p', 'R', 'A', 'A')
-+
-+/* 12 bit per pixel packed Bayer formats. */
-+#define MMAL_ENCODING_BAYER_SBGGR12P MMAL_FOURCC('p', 'B', '1', '2')
-+#define MMAL_ENCODING_BAYER_SGRBG12P MMAL_FOURCC('p', 'g', '1', '2')
-+#define MMAL_ENCODING_BAYER_SGBRG12P MMAL_FOURCC('p', 'G', '1', '2')
-+#define MMAL_ENCODING_BAYER_SRGGB12P MMAL_FOURCC('p', 'R', '1', '2')
-+
-+/* 16 bit per pixel Bayer formats. */
-+#define MMAL_ENCODING_BAYER_SBGGR16 MMAL_FOURCC('B', 'G', '1', '6')
-+#define MMAL_ENCODING_BAYER_SGBRG16 MMAL_FOURCC('G', 'B', '1', '6')
-+#define MMAL_ENCODING_BAYER_SGRBG16 MMAL_FOURCC('G', 'R', '1', '6')
-+#define MMAL_ENCODING_BAYER_SRGGB16 MMAL_FOURCC('R', 'G', '1', '6')
-+
- /** An EGL image handle
- */
- #define MMAL_ENCODING_EGL_IMAGE MMAL_FOURCC('E', 'G', 'L', 'I')
--- /dev/null
+From e65784b32dfce82b3eb6c5e700675e7417c4d3c4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 13 Feb 2019 14:07:52 +0000
+Subject: [PATCH 359/725] staging: bcm2835_codec: Add support for the ISP as an
+ M2M device
+
+The MMAL ISP component can also use this same V4L2 wrapper to
+provide a M2M format conversion and resizer.
+Instantiate 3 V4L2 devices now, one for each of decode, encode,
+and isp.
+The ISP currently doesn't expose any controls via V4L2, but this
+can be extended in the future.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c | 132 ++++++++++++------
+ 1 file changed, 92 insertions(+), 40 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -54,10 +54,26 @@ static int encode_video_nr = 11;
+ module_param(encode_video_nr, int, 0644);
+ MODULE_PARM_DESC(encode_video_nr, "encoder video device number");
+
++static int isp_video_nr = 12;
++module_param(isp_video_nr, int, 0644);
++MODULE_PARM_DESC(isp_video_nr, "isp video device number");
++
+ static unsigned int debug;
+ module_param(debug, uint, 0644);
+ MODULE_PARM_DESC(debug, "activates debug info (0-3)");
+
++enum bcm2835_codec_role {
++ DECODE,
++ ENCODE,
++ ISP,
++};
++
++static const char * const components[] = {
++ "ril.video_decode",
++ "ril.video_encode",
++ "ril.isp",
++};
++
+ #define MIN_W 32
+ #define MIN_H 32
+ #define MAX_W 1920
+@@ -373,7 +389,7 @@ struct bcm2835_codec_dev {
+ atomic_t num_inst;
+
+ /* allocated mmal instance and components */
+- bool decode; /* Is this instance a decoder? */
++ enum bcm2835_codec_role role;
+ /* The list of formats supported on input and output queues. */
+ struct bcm2835_codec_fmt_list supported_fmts[2];
+
+@@ -558,7 +574,7 @@ static void setup_mmal_port_format(struc
+ port->es.video.frame_rate.den = 1;
+ } else {
+ /* Compressed format - leave resolution as 0 for decode */
+- if (ctx->dev->decode) {
++ if (ctx->dev->role == DECODE) {
+ port->es.video.width = 0;
+ port->es.video.height = 0;
+ port->es.video.crop.width = 0;
+@@ -1089,7 +1105,8 @@ static int vidioc_s_fmt(struct bcm2835_c
+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
+ q_data->bytesperline, q_data->sizeimage);
+
+- if (ctx->dev->decode && q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
++ if (ctx->dev->role == DECODE &&
++ q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
+ f->fmt.pix.width && f->fmt.pix.height) {
+ /*
+ * On the decoder, if provided with a resolution on the input
+@@ -1188,7 +1205,8 @@ static int vidioc_g_selection(struct fil
+ bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
+ true : false;
+
+- if (capture_queue ^ ctx->dev->decode)
++ if ((ctx->dev->role == DECODE && !capture_queue) ||
++ (ctx->dev->role == ENCODE && capture_queue))
+ /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
+ return -EINVAL;
+
+@@ -1196,7 +1214,8 @@ static int vidioc_g_selection(struct fil
+ if (!q_data)
+ return -EINVAL;
+
+- if (ctx->dev->decode) {
++ switch (ctx->dev->role) {
++ case DECODE:
+ switch (s->target) {
+ case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+ case V4L2_SEL_TGT_COMPOSE:
+@@ -1214,7 +1233,8 @@ static int vidioc_g_selection(struct fil
+ default:
+ return -EINVAL;
+ }
+- } else {
++ break;
++ case ENCODE:
+ switch (s->target) {
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+@@ -1232,6 +1252,9 @@ static int vidioc_g_selection(struct fil
+ default:
+ return -EINVAL;
+ }
++ break;
++ case ISP:
++ break;
+ }
+
+ return 0;
+@@ -1249,7 +1272,8 @@ static int vidioc_s_selection(struct fil
+ __func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
+ s->r.width, s->r.height);
+
+- if (capture_queue ^ ctx->dev->decode)
++ if ((ctx->dev->role == DECODE && !capture_queue) ||
++ (ctx->dev->role == ENCODE && capture_queue))
+ /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
+ return -EINVAL;
+
+@@ -1257,7 +1281,8 @@ static int vidioc_s_selection(struct fil
+ if (!q_data)
+ return -EINVAL;
+
+- if (ctx->dev->decode) {
++ switch (ctx->dev->role) {
++ case DECODE:
+ switch (s->target) {
+ case V4L2_SEL_TGT_COMPOSE:
+ /* Accept cropped image */
+@@ -1272,7 +1297,8 @@ static int vidioc_s_selection(struct fil
+ default:
+ return -EINVAL;
+ }
+- } else {
++ break;
++ case ENCODE:
+ switch (s->target) {
+ case V4L2_SEL_TGT_CROP:
+ /* Only support crop from (0,0) */
+@@ -1287,6 +1313,9 @@ static int vidioc_s_selection(struct fil
+ default:
+ return -EINVAL;
+ }
++ break;
++ case ISP:
++ break;
+ }
+
+ return 0;
+@@ -1490,7 +1519,7 @@ static int vidioc_try_decoder_cmd(struct
+ {
+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
+
+- if (!ctx->dev->decode)
++ if (ctx->dev->role != DECODE)
+ return -EINVAL;
+
+ switch (cmd->cmd) {
+@@ -1564,7 +1593,7 @@ static int vidioc_try_encoder_cmd(struct
+ {
+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
+
+- if (ctx->dev->decode)
++ if (ctx->dev->role != ENCODE)
+ return -EINVAL;
+
+ switch (cmd->cmd) {
+@@ -1697,12 +1726,11 @@ static int bcm2835_codec_create_componen
+ unsigned int enable = 1;
+ int ret;
+
+- ret = vchiq_mmal_component_init(dev->instance, dev->decode ?
+- "ril.video_decode" : "ril.video_encode",
++ ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
+ &ctx->component);
+ if (ret < 0) {
+- v4l2_err(&dev->v4l2_dev, "%s: failed to create component for %s\n",
+- __func__, dev->decode ? "decode" : "encode");
++ v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
++ __func__, components[dev->role]);
+ return -ENOMEM;
+ }
+
+@@ -1729,13 +1757,7 @@ static int bcm2835_codec_create_componen
+ if (ret < 0)
+ goto destroy_component;
+
+- if (dev->decode) {
+- if (ctx->q_data[V4L2_M2M_DST].sizeimage <
+- ctx->component->output[0].minimum_buffer.size)
+- v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
+- ctx->q_data[V4L2_M2M_DST].sizeimage,
+- ctx->component->output[0].minimum_buffer.size);
+- } else {
++ if (dev->role == ENCODE) {
+ if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
+ ctx->component->output[0].minimum_buffer.size)
+ v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
+@@ -1744,6 +1766,12 @@ static int bcm2835_codec_create_componen
+
+ /* Now we have a component we can set all the ctrls */
+ bcm2835_codec_set_ctrls(ctx);
++ } else {
++ if (ctx->q_data[V4L2_M2M_DST].sizeimage <
++ ctx->component->output[0].minimum_buffer.size)
++ v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
++ ctx->q_data[V4L2_M2M_DST].sizeimage,
++ ctx->component->output[0].minimum_buffer.size);
+ }
+
+ return 0;
+@@ -2090,8 +2118,6 @@ static int bcm2835_codec_open(struct fil
+ struct v4l2_ctrl_handler *hdl;
+ int rc = 0;
+
+- v4l2_dbg(1, debug, &dev->v4l2_dev, "Creating instance for %s\n",
+- dev->decode ? "decode" : "encode");
+ if (mutex_lock_interruptible(&dev->dev_mutex)) {
+ v4l2_err(&dev->v4l2_dev, "Mutex fail\n");
+ return -ERESTARTSYS;
+@@ -2104,7 +2130,8 @@ static int bcm2835_codec_open(struct fil
+
+ ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
+ ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
+- if (dev->decode) {
++ switch (dev->role) {
++ case DECODE:
+ /*
+ * Input width and height are irrelevant as they will be defined
+ * by the bitstream not the format. Required by V4L2 though.
+@@ -2126,7 +2153,8 @@ static int bcm2835_codec_open(struct fil
+ get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
+ ctx->q_data[V4L2_M2M_DST].height,
+ ctx->q_data[V4L2_M2M_DST].fmt);
+- } else {
++ break;
++ case ENCODE:
+ ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
+ ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
+ ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
+@@ -2144,6 +2172,9 @@ static int bcm2835_codec_open(struct fil
+ ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
+ ctx->q_data[V4L2_M2M_DST].sizeimage =
+ DEF_COMP_BUF_SIZE_720P_OR_LESS;
++ break;
++ case ISP:
++ break;
+ }
+
+ ctx->colorspace = V4L2_COLORSPACE_REC709;
+@@ -2154,7 +2185,7 @@ static int bcm2835_codec_open(struct fil
+ file->private_data = &ctx->fh;
+ ctx->dev = dev;
+ hdl = &ctx->hdl;
+- if (!dev->decode) {
++ if (dev->role == ENCODE) {
+ /* Encode controls */
+ v4l2_ctrl_handler_init(hdl, 6);
+
+@@ -2303,14 +2334,11 @@ static int bcm2835_codec_get_supported_f
+ unsigned int i, j, num_encodings;
+ int ret;
+
+- ret = vchiq_mmal_component_init(dev->instance,
+- dev->decode ?
+- "ril.video_decode" :
+- "ril.video_encode",
++ ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
+ &component);
+ if (ret < 0) {
+- v4l2_err(&dev->v4l2_dev, "%s: failed to create component\n",
+- __func__);
++ v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
++ __func__, components[dev->role]);
+ return -ENOMEM;
+ }
+
+@@ -2406,12 +2434,13 @@ destroy_component:
+
+ static int bcm2835_codec_create(struct platform_device *pdev,
+ struct bcm2835_codec_dev **new_dev,
+- bool decode)
++ enum bcm2835_codec_role role)
+ {
+ struct bcm2835_codec_dev *dev;
+ struct video_device *vfd;
+ int video_nr;
+ int ret;
++ const static char *roles[] = {"decode", "encode", "isp"};
+
+ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+@@ -2419,7 +2448,7 @@ static int bcm2835_codec_create(struct p
+
+ dev->pdev = pdev;
+
+- dev->decode = decode;
++ dev->role = role;
+
+ ret = vchiq_mmal_init(&dev->instance);
+ if (ret)
+@@ -2441,14 +2470,27 @@ static int bcm2835_codec_create(struct p
+ vfd->lock = &dev->dev_mutex;
+ vfd->v4l2_dev = &dev->v4l2_dev;
+
+- if (dev->decode) {
++ switch (role) {
++ case DECODE:
+ v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
+ v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
+ video_nr = decode_video_nr;
+- } else {
++ break;
++ case ENCODE:
+ v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
+ v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
+ video_nr = encode_video_nr;
++ break;
++ case ISP:
++ v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
++ v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
++ v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
++ v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
++ video_nr = isp_video_nr;
++ break;
++ default:
++ ret = -EINVAL;
++ goto unreg_dev;
+ }
+
+ ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
+@@ -2473,7 +2515,7 @@ static int bcm2835_codec_create(struct p
+ }
+
+ v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
+- dev->decode ? "decode" : "encode");
++ roles[role]);
+ return 0;
+
+ err_m2m:
+@@ -2509,11 +2551,15 @@ static int bcm2835_codec_probe(struct pl
+ if (!drv)
+ return -ENOMEM;
+
+- ret = bcm2835_codec_create(pdev, &drv->encode, false);
++ ret = bcm2835_codec_create(pdev, &drv->decode, DECODE);
+ if (ret)
+ goto out;
+
+- ret = bcm2835_codec_create(pdev, &drv->decode, true);
++ ret = bcm2835_codec_create(pdev, &drv->encode, ENCODE);
++ if (ret)
++ goto out;
++
++ ret = bcm2835_codec_create(pdev, &drv->isp, ISP);
+ if (ret)
+ goto out;
+
+@@ -2526,6 +2572,10 @@ out:
+ bcm2835_codec_destroy(drv->encode);
+ drv->encode = NULL;
+ }
++ if (drv->decode) {
++ bcm2835_codec_destroy(drv->decode);
++ drv->decode = NULL;
++ }
+ return ret;
+ }
+
+@@ -2533,6 +2583,8 @@ static int bcm2835_codec_remove(struct p
+ {
+ struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
+
++ bcm2835_codec_destroy(drv->isp);
++
+ bcm2835_codec_destroy(drv->encode);
+
+ bcm2835_codec_destroy(drv->decode);
+++ /dev/null
-From c6d50172818f5fdc61d561ba9124c72a2ae49718 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 13 Feb 2019 12:36:56 +0000
-Subject: [PATCH 359/703] staging: mmal-vchiq: Always return the param size
- from param_get
-
-mmal-vchiq is a reimplementation of the userland library for MMAL.
-When getting a parameter, the client provides the storage and
-the size of the storage. The VPU then returns the size of the
-parameter that it wished to return, and as much as possible of
-that parameter is returned to the client.
-
-The implementation previously only returned the size provided
-by the VPU should it exceed the buffer size. So for parameters
-such as the supported encodings list the client had no idea
-how much of the provided storage had been populated.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -1413,11 +1413,12 @@ static int port_parameter_get(struct vch
- */
- 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);
- }
-+ /* Always report the size of the returned parameter to the caller */
-+ *value_size = 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);
--- /dev/null
+From 262f0a84a1d213c703c4f527d569687bec912fe4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 15 Feb 2019 11:36:14 +0000
+Subject: [PATCH 360/725] staging: bcm2835_codec: Add an option for ignoring
+ Bayer formats.
+
+This is a workaround for GStreamer currently not identifying Bayer
+as a raw format, therefore any device that supports it does not
+match the criteria for v4l2convert.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c | 29 ++++++++++++++++++-
+ 1 file changed, 28 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -58,6 +58,15 @@ static int isp_video_nr = 12;
+ module_param(isp_video_nr, int, 0644);
+ MODULE_PARM_DESC(isp_video_nr, "isp video device number");
+
++/*
++ * Workaround for GStreamer v4l2convert component not considering Bayer formats
++ * as raw, and therefore not considering a V4L2 device that supports them as
++ * as a suitable candidate.
++ */
++static bool disable_bayer;
++module_param(disable_bayer, bool, 0644);
++MODULE_PARM_DESC(disable_bayer, "Disable support for Bayer formats");
++
+ static unsigned int debug;
+ module_param(debug, uint, 0644);
+ MODULE_PARM_DESC(debug, "activates debug info (0-3)");
+@@ -105,6 +114,7 @@ struct bcm2835_codec_fmt {
+ u32 flags;
+ u32 mmal_fmt;
+ int size_multiplier_x2;
++ bool is_bayer;
+ };
+
+ static const struct bcm2835_codec_fmt supported_formats[] = {
+@@ -203,6 +213,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB8,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SBGGR8,
+ .depth = 8,
+@@ -210,6 +221,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR8,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGRBG8,
+ .depth = 8,
+@@ -217,6 +229,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG8,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGBRG8,
+ .depth = 8,
+@@ -224,6 +237,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG8,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ /* 10 bit */
+ .fourcc = V4L2_PIX_FMT_SRGGB10P,
+@@ -232,6 +246,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB10P,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SBGGR10P,
+ .depth = 10,
+@@ -239,6 +254,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR10P,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGRBG10P,
+ .depth = 10,
+@@ -246,6 +262,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG10P,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGBRG10P,
+ .depth = 10,
+@@ -253,6 +270,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG10P,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ /* 12 bit */
+ .fourcc = V4L2_PIX_FMT_SRGGB12P,
+@@ -261,6 +279,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB12P,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SBGGR12P,
+ .depth = 12,
+@@ -268,6 +287,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR12P,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGRBG12P,
+ .depth = 12,
+@@ -275,6 +295,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG12P,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGBRG12P,
+ .depth = 12,
+@@ -282,6 +303,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG12P,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ /* 16 bit */
+ .fourcc = V4L2_PIX_FMT_SRGGB16,
+@@ -290,6 +312,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB16,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SBGGR16,
+ .depth = 16,
+@@ -297,6 +320,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR16,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGRBG16,
+ .depth = 16,
+@@ -304,6 +328,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG16,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGBRG16,
+ .depth = 16,
+@@ -311,6 +336,7 @@ static const struct bcm2835_codec_fmt su
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG16,
+ .size_multiplier_x2 = 2,
++ .is_bayer = true,
+ }, {
+ /* Compressed formats */
+ .fourcc = V4L2_PIX_FMT_H264,
+@@ -438,7 +464,8 @@ static const struct bcm2835_codec_fmt *g
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
+- if (supported_formats[i].mmal_fmt == mmal_fmt)
++ if (supported_formats[i].mmal_fmt == mmal_fmt &&
++ (!disable_bayer || !supported_formats[i].is_bayer))
+ return &supported_formats[i];
+ }
+ return NULL;
+++ /dev/null
-From 351eab98f47fae8172a91cb8d65237dd1fd41a11 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 13 Feb 2019 12:51:03 +0000
-Subject: [PATCH 360/703] staging: mmal-vchiq: If the VPU returns an error,
- don't negate it
-
-There is an enum for the errors that the VPU can return.
-port_parameter_get was negating that value, but also using -EINVAL
-from the Linux error codes.
-Pass the VPU error code as positive values. Should the function
-need to pass a Linux failure, then return that as negative.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -1401,7 +1401,8 @@ static int port_parameter_get(struct vch
- goto release_msg;
- }
-
-- ret = -rmsg->u.port_parameter_get_reply.status;
-+ ret = rmsg->u.port_parameter_get_reply.status;
-+
- /* port_parameter_get_reply.size includes the header,
- * whilst *value_size doesn't.
- */
--- /dev/null
+From bb88b7400187b6878bd077b8950d3b03dd5b1d02 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 15 Feb 2019 11:38:45 +0000
+Subject: [PATCH 361/725] staging: bcm2835_codec: Fix handling of
+ VB2_MEMORY_DMABUF buffers
+
+If the queue is configured as VB2_MEMORY_DMABUF then vb2_core_expbuf
+fails as it ensures the queue is defined as VB2_MEMORY_MMAP.
+
+Correct the handling so that we unmap the buffer from vcsm and the
+VPU on cleanup, and then correctly get the dma buf of the new buffer.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c | 80 +++++++++++++------
+ .../vc04_services/vchiq-mmal/mmal-vchiq.c | 21 +++--
+ .../vc04_services/vchiq-mmal/mmal-vchiq.h | 2 +
+ 3 files changed, 73 insertions(+), 30 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -1852,6 +1852,18 @@ static int bcm2835_codec_queue_setup(str
+ return 0;
+ }
+
++static int bcm2835_codec_mmal_buf_cleanup(struct mmal_buffer *mmal_buf)
++{
++ mmal_vchi_buffer_cleanup(mmal_buf);
++
++ if (mmal_buf->dma_buf) {
++ dma_buf_put(mmal_buf->dma_buf);
++ mmal_buf->dma_buf = NULL;
++ }
++
++ return 0;
++}
++
+ static int bcm2835_codec_buf_init(struct vb2_buffer *vb)
+ {
+ struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+@@ -1880,6 +1892,7 @@ static int bcm2835_codec_buf_prepare(str
+ vb);
+ struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
+ m2m);
++ struct dma_buf *dma_buf;
+ int ret;
+
+ v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p\n",
+@@ -1906,20 +1919,48 @@ static int bcm2835_codec_buf_prepare(str
+ if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
+ vb2_set_plane_payload(vb, 0, q_data->sizeimage);
+
+- /*
+- * We want to do this at init, but vb2_core_expbuf checks that the
+- * index < q->num_buffers, and q->num_buffers only gets updated once
+- * all the buffers are allocated.
+- */
+- if (!buf->mmal.dma_buf) {
+- ret = vb2_core_expbuf_dmabuf(vb->vb2_queue,
+- vb->vb2_queue->type, vb->index, 0,
+- O_CLOEXEC, &buf->mmal.dma_buf);
+- if (ret)
+- v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed to expbuf idx %d, ret %d\n",
+- __func__, vb->index, ret);
+- } else {
++ switch (vb->memory) {
++ case VB2_MEMORY_DMABUF:
++ dma_buf = dma_buf_get(vb->planes[0].m.fd);
++
++ if (dma_buf != buf->mmal.dma_buf) {
++ /* dmabuf either hasn't already been mapped, or it has
++ * changed.
++ */
++ if (buf->mmal.dma_buf) {
++ v4l2_err(&ctx->dev->v4l2_dev,
++ "%s Buffer changed - why did the core not call cleanup?\n",
++ __func__);
++ bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
++ }
++
++ buf->mmal.dma_buf = dma_buf;
++ }
+ ret = 0;
++ break;
++ case VB2_MEMORY_MMAP:
++ /*
++ * We want to do this at init, but vb2_core_expbuf checks that
++ * the index < q->num_buffers, and q->num_buffers only gets
++ * updated once all the buffers are allocated.
++ */
++ if (!buf->mmal.dma_buf) {
++ ret = vb2_core_expbuf_dmabuf(vb->vb2_queue,
++ vb->vb2_queue->type,
++ vb->index, 0,
++ O_CLOEXEC,
++ &buf->mmal.dma_buf);
++ if (ret)
++ v4l2_err(&ctx->dev->v4l2_dev,
++ "%s: Failed to expbuf idx %d, ret %d\n",
++ __func__, vb->index, ret);
++ } else {
++ ret = 0;
++ }
++ break;
++ default:
++ ret = -EINVAL;
++ break;
+ }
+
+ return ret;
+@@ -1948,12 +1989,7 @@ static void bcm2835_codec_buffer_cleanup
+ v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
+ __func__, ctx, vb);
+
+- mmal_vchi_buffer_cleanup(&buf->mmal);
+-
+- if (buf->mmal.dma_buf) {
+- dma_buf_put(buf->mmal.dma_buf);
+- buf->mmal.dma_buf = NULL;
+- }
++ bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
+ }
+
+ static int bcm2835_codec_start_streaming(struct vb2_queue *q,
+@@ -2067,11 +2103,7 @@ static void bcm2835_codec_stop_streaming
+ m2m = container_of(vb2, struct v4l2_m2m_buffer, vb);
+ buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
+
+- mmal_vchi_buffer_cleanup(&buf->mmal);
+- if (buf->mmal.dma_buf) {
+- dma_buf_put(buf->mmal.dma_buf);
+- buf->mmal.dma_buf = NULL;
+- }
++ bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
+ }
+
+ /* If both ports disabled, then disable the component */
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -1785,13 +1785,9 @@ int mmal_vchi_buffer_init(struct vchiq_m
+ }
+ EXPORT_SYMBOL_GPL(mmal_vchi_buffer_init);
+
+-int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
++int mmal_vchi_buffer_unmap(struct mmal_buffer *buf)
+ {
+- struct mmal_msg_context *msg_context = buf->msg_context;
+-
+- if (msg_context)
+- release_msg_context(msg_context);
+- buf->msg_context = NULL;
++ int ret = 0;
+
+ if (buf->vcsm_handle) {
+ int ret;
+@@ -1803,6 +1799,19 @@ int mmal_vchi_buffer_cleanup(struct mmal
+ pr_err("%s: vcsm_free failed, ret %d\n", __func__, ret);
+ buf->vcsm_handle = 0;
+ }
++ return ret;
++}
++EXPORT_SYMBOL_GPL(mmal_vchi_buffer_unmap);
++
++int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
++{
++ struct mmal_msg_context *msg_context = buf->msg_context;
++
++ if (msg_context)
++ release_msg_context(msg_context);
++ buf->msg_context = NULL;
++
++ mmal_vchi_buffer_unmap(buf);
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -167,6 +167,8 @@ int vchiq_mmal_submit_buffer(struct vchi
+ struct vchiq_mmal_port *port,
+ struct mmal_buffer *buf);
+
++int mmal_vchi_buffer_unmap(struct mmal_buffer *buf);
++
+ int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
+ struct mmal_buffer *buf);
+ int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf);
+++ /dev/null
-From 467255263f6d2c85b43a98300d283869d72a3ac3 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 13 Feb 2019 13:44:00 +0000
-Subject: [PATCH 361/703] staging: bcm2835_codec: Query supported formats from
- the component
-
-The driver was previously working with hard coded tables of
-which video formats were supported by each component.
-The components advertise this information via a MMAL parameter,
-so retrieve the information from there during probe, and store
-in the state structure for that device.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c | 455 +++++++++++++-----
- 1 file changed, 327 insertions(+), 128 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -88,17 +88,12 @@ struct bcm2835_codec_fmt {
- int bytesperline_align;
- u32 flags;
- u32 mmal_fmt;
-- bool decode_only;
-- bool encode_only;
- int size_multiplier_x2;
- };
-
--/* Supported raw pixel formats. Those supported for both encode and decode
-- * must come first, with those only supported for decode coming after (there
-- * are no formats supported for encode only).
-- */
--static struct bcm2835_codec_fmt raw_formats[] = {
-+static const struct bcm2835_codec_fmt supported_formats[] = {
- {
-+ /* YUV formats */
- .fourcc = V4L2_PIX_FMT_YUV420,
- .depth = 8,
- .bytesperline_align = 32,
-@@ -139,7 +134,6 @@ static struct bcm2835_codec_fmt raw_form
- .bytesperline_align = 32,
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_YUYV,
-- .encode_only = true,
- .size_multiplier_x2 = 2,
- }, {
- .fourcc = V4L2_PIX_FMT_UYVY,
-@@ -147,7 +141,6 @@ static struct bcm2835_codec_fmt raw_form
- .bytesperline_align = 32,
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_UYVY,
-- .encode_only = true,
- .size_multiplier_x2 = 2,
- }, {
- .fourcc = V4L2_PIX_FMT_YVYU,
-@@ -155,7 +148,6 @@ static struct bcm2835_codec_fmt raw_form
- .bytesperline_align = 32,
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_YVYU,
-- .encode_only = true,
- .size_multiplier_x2 = 2,
- }, {
- .fourcc = V4L2_PIX_FMT_VYUY,
-@@ -163,15 +155,14 @@ static struct bcm2835_codec_fmt raw_form
- .bytesperline_align = 32,
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_VYUY,
-- .encode_only = true,
- .size_multiplier_x2 = 2,
- }, {
-+ /* RGB formats */
- .fourcc = V4L2_PIX_FMT_RGB24,
- .depth = 24,
- .bytesperline_align = 32,
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_RGB24,
-- .encode_only = true,
- .size_multiplier_x2 = 2,
- }, {
- .fourcc = V4L2_PIX_FMT_BGR24,
-@@ -179,7 +170,6 @@ static struct bcm2835_codec_fmt raw_form
- .bytesperline_align = 32,
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BGR24,
-- .encode_only = true,
- .size_multiplier_x2 = 2,
- }, {
- .fourcc = V4L2_PIX_FMT_BGR32,
-@@ -187,17 +177,126 @@ static struct bcm2835_codec_fmt raw_form
- .bytesperline_align = 32,
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BGRA,
-- .encode_only = true,
- .size_multiplier_x2 = 2,
-- },
--};
--
--/* Supported encoded formats. Those supported for both encode and decode
-- * must come first, with those only supported for decode coming after (there
-- * are no formats supported for encode only).
-- */
--static struct bcm2835_codec_fmt encoded_formats[] = {
-- {
-+ }, {
-+ /* Bayer formats */
-+ /* 8 bit */
-+ .fourcc = V4L2_PIX_FMT_SRGGB8,
-+ .depth = 8,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB8,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_SBGGR8,
-+ .depth = 8,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR8,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_SGRBG8,
-+ .depth = 8,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG8,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_SGBRG8,
-+ .depth = 8,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG8,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ /* 10 bit */
-+ .fourcc = V4L2_PIX_FMT_SRGGB10P,
-+ .depth = 10,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB10P,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_SBGGR10P,
-+ .depth = 10,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR10P,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_SGRBG10P,
-+ .depth = 10,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG10P,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_SGBRG10P,
-+ .depth = 10,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG10P,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ /* 12 bit */
-+ .fourcc = V4L2_PIX_FMT_SRGGB12P,
-+ .depth = 12,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB12P,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_SBGGR12P,
-+ .depth = 12,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR12P,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_SGRBG12P,
-+ .depth = 12,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG12P,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_SGBRG12P,
-+ .depth = 12,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG12P,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ /* 16 bit */
-+ .fourcc = V4L2_PIX_FMT_SRGGB16,
-+ .depth = 16,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB16,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_SBGGR16,
-+ .depth = 16,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR16,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_SGRBG16,
-+ .depth = 16,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG16,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ .fourcc = V4L2_PIX_FMT_SGBRG16,
-+ .depth = 16,
-+ .bytesperline_align = 32,
-+ .flags = 0,
-+ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG16,
-+ .size_multiplier_x2 = 2,
-+ }, {
-+ /* Compressed formats */
- .fourcc = V4L2_PIX_FMT_H264,
- .depth = 0,
- .flags = V4L2_FMT_FLAG_COMPRESSED,
-@@ -212,30 +311,22 @@ static struct bcm2835_codec_fmt encoded_
- .depth = 0,
- .flags = V4L2_FMT_FLAG_COMPRESSED,
- .mmal_fmt = MMAL_ENCODING_MP4V,
-- .decode_only = true,
- }, {
- .fourcc = V4L2_PIX_FMT_H263,
- .depth = 0,
- .flags = V4L2_FMT_FLAG_COMPRESSED,
- .mmal_fmt = MMAL_ENCODING_H263,
-- .decode_only = true,
- }, {
- .fourcc = V4L2_PIX_FMT_MPEG2,
- .depth = 0,
- .flags = V4L2_FMT_FLAG_COMPRESSED,
- .mmal_fmt = MMAL_ENCODING_MP2V,
-- .decode_only = true,
- }, {
- .fourcc = V4L2_PIX_FMT_VP8,
- .depth = 0,
- .flags = V4L2_FMT_FLAG_COMPRESSED,
- .mmal_fmt = MMAL_ENCODING_VP8,
-- .decode_only = true,
- },
-- /*
-- * This list couold include VP6 and Theorafor decode, but V4L2 doesn't
-- * support them.
-- */
- };
-
- struct bcm2835_codec_fmt_list {
-@@ -243,19 +334,6 @@ struct bcm2835_codec_fmt_list {
- unsigned int num_entries;
- };
-
--#define RAW_LIST 0
--#define ENCODED_LIST 1
--
--struct bcm2835_codec_fmt_list formats[] = {
-- {
-- .list = raw_formats,
-- .num_entries = ARRAY_SIZE(raw_formats),
-- }, {
-- .list = encoded_formats,
-- .num_entries = ARRAY_SIZE(encoded_formats),
-- },
--};
--
- struct m2m_mmal_buffer {
- struct v4l2_m2m_buffer m2m;
- struct mmal_buffer mmal;
-@@ -284,52 +362,6 @@ struct bcm2835_codec_q_data {
- bool eos_buffer_in_use; /* debug only */
- };
-
--enum {
-- V4L2_M2M_SRC = 0,
-- V4L2_M2M_DST = 1,
--};
--
--static inline struct bcm2835_codec_fmt_list *get_format_list(bool decode,
-- bool capture)
--{
-- return decode ^ capture ? &formats[ENCODED_LIST] : &formats[RAW_LIST];
--}
--
--static struct bcm2835_codec_fmt *get_default_format(bool decode, bool capture)
--{
-- return &get_format_list(decode, capture)->list[0];
--}
--
--static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f, bool decode,
-- bool capture)
--{
-- struct bcm2835_codec_fmt *fmt;
-- unsigned int k;
-- struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
--
-- for (k = 0; k < fmts->num_entries; k++) {
-- fmt = &fmts->list[k];
-- if (fmt->fourcc == f->fmt.pix.pixelformat)
-- break;
-- }
--
-- /*
-- * Some compressed formats are only supported for decoding, not
-- * encoding.
-- */
-- if (!decode && fmts->list[k].decode_only)
-- return NULL;
--
-- /* Some pixel formats are only supported for encoding, not decoding. */
-- if (decode && fmts->list[k].encode_only)
-- return NULL;
--
-- if (k == fmts->num_entries)
-- return NULL;
--
-- return &fmts->list[k];
--}
--
- struct bcm2835_codec_dev {
- struct platform_device *pdev;
-
-@@ -342,6 +374,9 @@ struct bcm2835_codec_dev {
-
- /* allocated mmal instance and components */
- bool decode; /* Is this instance a decoder? */
-+ /* The list of formats supported on input and output queues. */
-+ struct bcm2835_codec_fmt_list supported_fmts[2];
-+
- struct vchiq_mmal_instance *instance;
-
- struct v4l2_m2m_dev *m2m_dev;
-@@ -374,8 +409,59 @@ struct bcm2835_codec_ctx {
- struct bcm2835_codec_driver {
- struct bcm2835_codec_dev *encode;
- struct bcm2835_codec_dev *decode;
-+ struct bcm2835_codec_dev *isp;
-+};
-+
-+enum {
-+ V4L2_M2M_SRC = 0,
-+ V4L2_M2M_DST = 1,
- };
-
-+static const struct bcm2835_codec_fmt *get_fmt(u32 mmal_fmt)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
-+ if (supported_formats[i].mmal_fmt == mmal_fmt)
-+ return &supported_formats[i];
-+ }
-+ return NULL;
-+}
-+
-+static inline
-+struct bcm2835_codec_fmt_list *get_format_list(struct bcm2835_codec_dev *dev,
-+ bool capture)
-+{
-+ return &dev->supported_fmts[capture ? 1 : 0];
-+}
-+
-+static
-+struct bcm2835_codec_fmt *get_default_format(struct bcm2835_codec_dev *dev,
-+ bool capture)
-+{
-+ return &dev->supported_fmts[capture ? 1 : 0].list[0];
-+}
-+
-+static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f,
-+ struct bcm2835_codec_dev *dev,
-+ bool capture)
-+{
-+ struct bcm2835_codec_fmt *fmt;
-+ unsigned int k;
-+ struct bcm2835_codec_fmt_list *fmts =
-+ &dev->supported_fmts[capture ? 1 : 0];
-+
-+ for (k = 0; k < fmts->num_entries; k++) {
-+ fmt = &fmts->list[k];
-+ if (fmt->fourcc == f->fmt.pix.pixelformat)
-+ break;
-+ }
-+ if (k == fmts->num_entries)
-+ return NULL;
-+
-+ return &fmts->list[k];
-+}
-+
- static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
- {
- return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
-@@ -456,7 +542,6 @@ static inline unsigned int get_bytesperl
- }
-
- static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
-- bool decode,
- struct bcm2835_codec_q_data *q_data,
- struct vchiq_mmal_port *port)
- {
-@@ -473,7 +558,7 @@ static void setup_mmal_port_format(struc
- port->es.video.frame_rate.den = 1;
- } else {
- /* Compressed format - leave resolution as 0 for decode */
-- if (decode) {
-+ if (ctx->dev->decode) {
- port->es.video.width = 0;
- port->es.video.height = 0;
- port->es.video.crop.width = 0;
-@@ -802,22 +887,15 @@ static int vidioc_querycap(struct file *
- return 0;
- }
-
--static int enum_fmt(struct v4l2_fmtdesc *f, bool decode, bool capture)
-+static int enum_fmt(struct v4l2_fmtdesc *f, struct bcm2835_codec_ctx *ctx,
-+ bool capture)
- {
- struct bcm2835_codec_fmt *fmt;
-- struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
-+ struct bcm2835_codec_fmt_list *fmts =
-+ get_format_list(ctx->dev, capture);
-
- if (f->index < fmts->num_entries) {
- /* Format found */
-- /* Check format isn't a decode only format when encoding */
-- if (!decode &&
-- fmts->list[f->index].decode_only)
-- return -EINVAL;
-- /* Check format isn't a decode only format when encoding */
-- if (decode &&
-- fmts->list[f->index].encode_only)
-- return -EINVAL;
--
- fmt = &fmts->list[f->index];
- f->pixelformat = fmt->fourcc;
- f->flags = fmt->flags;
-@@ -833,7 +911,7 @@ static int vidioc_enum_fmt_vid_cap(struc
- {
- struct bcm2835_codec_ctx *ctx = file2ctx(file);
-
-- return enum_fmt(f, ctx->dev->decode, true);
-+ return enum_fmt(f, ctx, true);
- }
-
- static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
-@@ -841,7 +919,7 @@ static int vidioc_enum_fmt_vid_out(struc
- {
- struct bcm2835_codec_ctx *ctx = file2ctx(file);
-
-- return enum_fmt(f, ctx->dev->decode, false);
-+ return enum_fmt(f, ctx, false);
- }
-
- static int vidioc_g_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f)
-@@ -933,11 +1011,11 @@ static int vidioc_try_fmt_vid_cap(struct
- struct bcm2835_codec_fmt *fmt;
- struct bcm2835_codec_ctx *ctx = file2ctx(file);
-
-- fmt = find_format(f, ctx->dev->decode, true);
-+ fmt = find_format(f, ctx->dev, true);
- if (!fmt) {
-- f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
-+ f->fmt.pix.pixelformat = get_default_format(ctx->dev,
- true)->fourcc;
-- fmt = find_format(f, ctx->dev->decode, true);
-+ fmt = find_format(f, ctx->dev, true);
- }
-
- return vidioc_try_fmt(f, fmt);
-@@ -949,11 +1027,11 @@ static int vidioc_try_fmt_vid_out(struct
- struct bcm2835_codec_fmt *fmt;
- struct bcm2835_codec_ctx *ctx = file2ctx(file);
-
-- fmt = find_format(f, ctx->dev->decode, false);
-+ fmt = find_format(f, ctx->dev, false);
- if (!fmt) {
-- f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
-+ f->fmt.pix.pixelformat = get_default_format(ctx->dev,
- false)->fourcc;
-- fmt = find_format(f, ctx->dev->decode, false);
-+ fmt = find_format(f, ctx->dev, false);
- }
-
- if (!f->fmt.pix.colorspace)
-@@ -988,7 +1066,7 @@ static int vidioc_s_fmt(struct bcm2835_c
- return -EBUSY;
- }
-
-- q_data->fmt = find_format(f, ctx->dev->decode,
-+ q_data->fmt = find_format(f, ctx->dev,
- f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
- q_data->crop_width = f->fmt.pix.width;
- q_data->height = f->fmt.pix.height;
-@@ -1041,7 +1119,7 @@ static int vidioc_s_fmt(struct bcm2835_c
- if (!port)
- return 0;
-
-- setup_mmal_port_format(ctx, ctx->dev->decode, q_data, port);
-+ setup_mmal_port_format(ctx, q_data, port);
- ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
- if (ret) {
- v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on port, ret %d\n",
-@@ -1064,8 +1142,7 @@ static int vidioc_s_fmt(struct bcm2835_c
- struct bcm2835_codec_q_data *q_data_dst =
- &ctx->q_data[V4L2_M2M_DST];
-
-- setup_mmal_port_format(ctx, ctx->dev->decode, q_data_dst,
-- port_dst);
-+ setup_mmal_port_format(ctx, q_data_dst, port_dst);
- ret = vchiq_mmal_port_set_format(ctx->dev->instance, port_dst);
- if (ret) {
- v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on output port, ret %d\n",
-@@ -1636,10 +1713,10 @@ static int bcm2835_codec_create_componen
- MMAL_PARAMETER_ZERO_COPY, &enable,
- sizeof(enable));
-
-- setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_SRC],
-+ setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_SRC],
- &ctx->component->input[0]);
-
-- setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_DST],
-+ setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_DST],
- &ctx->component->output[0]);
-
- ret = vchiq_mmal_port_set_format(dev->instance,
-@@ -2025,8 +2102,8 @@ static int bcm2835_codec_open(struct fil
- goto open_unlock;
- }
-
-- ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev->decode, false);
-- ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev->decode, true);
-+ ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
-+ ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
- if (dev->decode) {
- /*
- * Input width and height are irrelevant as they will be defined
-@@ -2209,13 +2286,130 @@ static const struct v4l2_m2m_ops m2m_ops
- .job_abort = job_abort,
- };
-
-+/* Size of the array to provide to the VPU when asking for the list of supported
-+ * formats.
-+ * The ISP component currently advertises 33 input formats, so add a small
-+ * overhead on that.
-+ */
-+#define MAX_SUPPORTED_ENCODINGS 40
-+
-+/* Populate dev->supported_fmts with the formats supported by those ports. */
-+static int bcm2835_codec_get_supported_fmts(struct bcm2835_codec_dev *dev)
-+{
-+ struct bcm2835_codec_fmt *list;
-+ struct vchiq_mmal_component *component;
-+ u32 fourccs[MAX_SUPPORTED_ENCODINGS];
-+ u32 param_size = sizeof(fourccs);
-+ unsigned int i, j, num_encodings;
-+ int ret;
-+
-+ ret = vchiq_mmal_component_init(dev->instance,
-+ dev->decode ?
-+ "ril.video_decode" :
-+ "ril.video_encode",
-+ &component);
-+ if (ret < 0) {
-+ v4l2_err(&dev->v4l2_dev, "%s: failed to create component\n",
-+ __func__);
-+ return -ENOMEM;
-+ }
-+
-+ ret = vchiq_mmal_port_parameter_get(dev->instance,
-+ &component->input[0],
-+ MMAL_PARAMETER_SUPPORTED_ENCODINGS,
-+ &fourccs,
-+ ¶m_size);
-+
-+ if (ret) {
-+ if (ret == MMAL_MSG_STATUS_ENOSPC) {
-+ v4l2_err(&dev->v4l2_dev, "%s: port has more encoding than we provided space for. Some are dropped.\n",
-+ __func__);
-+ num_encodings = MAX_SUPPORTED_ENCODINGS;
-+ } else {
-+ v4l2_err(&dev->v4l2_dev, "%s: get_param ret %u.\n",
-+ __func__, ret);
-+ ret = -EINVAL;
-+ goto destroy_component;
-+ }
-+ } else {
-+ num_encodings = param_size / sizeof(u32);
-+ }
-+
-+ /* Assume at this stage that all encodings will be supported in V4L2.
-+ * Any that aren't supported will waste a very small amount of memory.
-+ */
-+ list = devm_kzalloc(&dev->pdev->dev,
-+ sizeof(struct bcm2835_codec_fmt) * num_encodings,
-+ GFP_KERNEL);
-+ if (!list) {
-+ ret = -ENOMEM;
-+ goto destroy_component;
-+ }
-+ dev->supported_fmts[0].list = list;
-+
-+ for (i = 0, j = 0; i < num_encodings; i++) {
-+ const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
-+
-+ if (fmt) {
-+ list[j] = *fmt;
-+ j++;
-+ }
-+ }
-+ dev->supported_fmts[0].num_entries = j;
-+
-+ param_size = sizeof(fourccs);
-+ ret = vchiq_mmal_port_parameter_get(dev->instance,
-+ &component->output[0],
-+ MMAL_PARAMETER_SUPPORTED_ENCODINGS,
-+ &fourccs,
-+ ¶m_size);
-+
-+ if (ret) {
-+ if (ret == MMAL_MSG_STATUS_ENOSPC) {
-+ v4l2_err(&dev->v4l2_dev, "%s: port has more encoding than we provided space for. Some are dropped.\n",
-+ __func__);
-+ num_encodings = MAX_SUPPORTED_ENCODINGS;
-+ } else {
-+ ret = -EINVAL;
-+ goto destroy_component;
-+ }
-+ } else {
-+ num_encodings = param_size / sizeof(u32);
-+ }
-+ /* Assume at this stage that all encodings will be supported in V4L2. */
-+ list = devm_kzalloc(&dev->pdev->dev,
-+ sizeof(struct bcm2835_codec_fmt) * num_encodings,
-+ GFP_KERNEL);
-+ if (!list) {
-+ ret = -ENOMEM;
-+ goto destroy_component;
-+ }
-+ dev->supported_fmts[1].list = list;
-+
-+ for (i = 0, j = 0; i < num_encodings; i++) {
-+ const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
-+
-+ if (fmt) {
-+ list[j] = *fmt;
-+ j++;
-+ }
-+ }
-+ dev->supported_fmts[1].num_entries = j;
-+
-+ ret = 0;
-+
-+destroy_component:
-+ vchiq_mmal_component_finalise(dev->instance, component);
-+
-+ return ret;
-+}
-+
- static int bcm2835_codec_create(struct platform_device *pdev,
- struct bcm2835_codec_dev **new_dev,
- bool decode)
- {
- struct bcm2835_codec_dev *dev;
- struct video_device *vfd;
-- struct vchiq_mmal_instance *instance = NULL;
- int video_nr;
- int ret;
-
-@@ -2227,10 +2421,18 @@ static int bcm2835_codec_create(struct p
-
- dev->decode = decode;
-
-- ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
-+ ret = vchiq_mmal_init(&dev->instance);
- if (ret)
- return ret;
-
-+ ret = bcm2835_codec_get_supported_fmts(dev);
-+ if (ret)
-+ goto vchiq_finalise;
-+
-+ ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
-+ if (ret)
-+ goto vchiq_finalise;
-+
- atomic_set(&dev->num_inst, 0);
- mutex_init(&dev->dev_mutex);
-
-@@ -2270,12 +2472,7 @@ static int bcm2835_codec_create(struct p
- goto err_m2m;
- }
-
-- ret = vchiq_mmal_init(&instance);
-- if (ret < 0)
-- goto err_m2m;
-- dev->instance = instance;
--
-- v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s codec\n",
-+ v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
- dev->decode ? "decode" : "encode");
- return 0;
-
-@@ -2284,7 +2481,8 @@ err_m2m:
- video_unregister_device(&dev->vfd);
- unreg_dev:
- v4l2_device_unregister(&dev->v4l2_dev);
--
-+vchiq_finalise:
-+ vchiq_mmal_finalise(dev->instance);
- return ret;
- }
-
-@@ -2297,6 +2495,7 @@ static int bcm2835_codec_destroy(struct
- v4l2_m2m_release(dev->m2m_dev);
- video_unregister_device(&dev->vfd);
- v4l2_device_unregister(&dev->v4l2_dev);
-+ vchiq_mmal_finalise(dev->instance);
-
- return 0;
- }
+++ /dev/null
-From dd3aa42c6ca22eae1b91f78f6de85935bcd6ab0e Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 13 Feb 2019 14:07:52 +0000
-Subject: [PATCH 362/703] staging: bcm2835_codec: Add support for the ISP as an
- M2M device
-
-The MMAL ISP component can also use this same V4L2 wrapper to
-provide a M2M format conversion and resizer.
-Instantiate 3 V4L2 devices now, one for each of decode, encode,
-and isp.
-The ISP currently doesn't expose any controls via V4L2, but this
-can be extended in the future.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c | 132 ++++++++++++------
- 1 file changed, 92 insertions(+), 40 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -54,10 +54,26 @@ static int encode_video_nr = 11;
- module_param(encode_video_nr, int, 0644);
- MODULE_PARM_DESC(encode_video_nr, "encoder video device number");
-
-+static int isp_video_nr = 12;
-+module_param(isp_video_nr, int, 0644);
-+MODULE_PARM_DESC(isp_video_nr, "isp video device number");
-+
- static unsigned int debug;
- module_param(debug, uint, 0644);
- MODULE_PARM_DESC(debug, "activates debug info (0-3)");
-
-+enum bcm2835_codec_role {
-+ DECODE,
-+ ENCODE,
-+ ISP,
-+};
-+
-+static const char * const components[] = {
-+ "ril.video_decode",
-+ "ril.video_encode",
-+ "ril.isp",
-+};
-+
- #define MIN_W 32
- #define MIN_H 32
- #define MAX_W 1920
-@@ -373,7 +389,7 @@ struct bcm2835_codec_dev {
- atomic_t num_inst;
-
- /* allocated mmal instance and components */
-- bool decode; /* Is this instance a decoder? */
-+ enum bcm2835_codec_role role;
- /* The list of formats supported on input and output queues. */
- struct bcm2835_codec_fmt_list supported_fmts[2];
-
-@@ -558,7 +574,7 @@ static void setup_mmal_port_format(struc
- port->es.video.frame_rate.den = 1;
- } else {
- /* Compressed format - leave resolution as 0 for decode */
-- if (ctx->dev->decode) {
-+ if (ctx->dev->role == DECODE) {
- port->es.video.width = 0;
- port->es.video.height = 0;
- port->es.video.crop.width = 0;
-@@ -1089,7 +1105,8 @@ static int vidioc_s_fmt(struct bcm2835_c
- v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
- q_data->bytesperline, q_data->sizeimage);
-
-- if (ctx->dev->decode && q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
-+ if (ctx->dev->role == DECODE &&
-+ q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
- f->fmt.pix.width && f->fmt.pix.height) {
- /*
- * On the decoder, if provided with a resolution on the input
-@@ -1188,7 +1205,8 @@ static int vidioc_g_selection(struct fil
- bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
- true : false;
-
-- if (capture_queue ^ ctx->dev->decode)
-+ if ((ctx->dev->role == DECODE && !capture_queue) ||
-+ (ctx->dev->role == ENCODE && capture_queue))
- /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
- return -EINVAL;
-
-@@ -1196,7 +1214,8 @@ static int vidioc_g_selection(struct fil
- if (!q_data)
- return -EINVAL;
-
-- if (ctx->dev->decode) {
-+ switch (ctx->dev->role) {
-+ case DECODE:
- switch (s->target) {
- case V4L2_SEL_TGT_COMPOSE_DEFAULT:
- case V4L2_SEL_TGT_COMPOSE:
-@@ -1214,7 +1233,8 @@ static int vidioc_g_selection(struct fil
- default:
- return -EINVAL;
- }
-- } else {
-+ break;
-+ case ENCODE:
- switch (s->target) {
- case V4L2_SEL_TGT_CROP_DEFAULT:
- case V4L2_SEL_TGT_CROP_BOUNDS:
-@@ -1232,6 +1252,9 @@ static int vidioc_g_selection(struct fil
- default:
- return -EINVAL;
- }
-+ break;
-+ case ISP:
-+ break;
- }
-
- return 0;
-@@ -1249,7 +1272,8 @@ static int vidioc_s_selection(struct fil
- __func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
- s->r.width, s->r.height);
-
-- if (capture_queue ^ ctx->dev->decode)
-+ if ((ctx->dev->role == DECODE && !capture_queue) ||
-+ (ctx->dev->role == ENCODE && capture_queue))
- /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
- return -EINVAL;
-
-@@ -1257,7 +1281,8 @@ static int vidioc_s_selection(struct fil
- if (!q_data)
- return -EINVAL;
-
-- if (ctx->dev->decode) {
-+ switch (ctx->dev->role) {
-+ case DECODE:
- switch (s->target) {
- case V4L2_SEL_TGT_COMPOSE:
- /* Accept cropped image */
-@@ -1272,7 +1297,8 @@ static int vidioc_s_selection(struct fil
- default:
- return -EINVAL;
- }
-- } else {
-+ break;
-+ case ENCODE:
- switch (s->target) {
- case V4L2_SEL_TGT_CROP:
- /* Only support crop from (0,0) */
-@@ -1287,6 +1313,9 @@ static int vidioc_s_selection(struct fil
- default:
- return -EINVAL;
- }
-+ break;
-+ case ISP:
-+ break;
- }
-
- return 0;
-@@ -1490,7 +1519,7 @@ static int vidioc_try_decoder_cmd(struct
- {
- struct bcm2835_codec_ctx *ctx = file2ctx(file);
-
-- if (!ctx->dev->decode)
-+ if (ctx->dev->role != DECODE)
- return -EINVAL;
-
- switch (cmd->cmd) {
-@@ -1564,7 +1593,7 @@ static int vidioc_try_encoder_cmd(struct
- {
- struct bcm2835_codec_ctx *ctx = file2ctx(file);
-
-- if (ctx->dev->decode)
-+ if (ctx->dev->role != ENCODE)
- return -EINVAL;
-
- switch (cmd->cmd) {
-@@ -1697,12 +1726,11 @@ static int bcm2835_codec_create_componen
- unsigned int enable = 1;
- int ret;
-
-- ret = vchiq_mmal_component_init(dev->instance, dev->decode ?
-- "ril.video_decode" : "ril.video_encode",
-+ ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
- &ctx->component);
- if (ret < 0) {
-- v4l2_err(&dev->v4l2_dev, "%s: failed to create component for %s\n",
-- __func__, dev->decode ? "decode" : "encode");
-+ v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
-+ __func__, components[dev->role]);
- return -ENOMEM;
- }
-
-@@ -1729,13 +1757,7 @@ static int bcm2835_codec_create_componen
- if (ret < 0)
- goto destroy_component;
-
-- if (dev->decode) {
-- if (ctx->q_data[V4L2_M2M_DST].sizeimage <
-- ctx->component->output[0].minimum_buffer.size)
-- v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
-- ctx->q_data[V4L2_M2M_DST].sizeimage,
-- ctx->component->output[0].minimum_buffer.size);
-- } else {
-+ if (dev->role == ENCODE) {
- if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
- ctx->component->output[0].minimum_buffer.size)
- v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
-@@ -1744,6 +1766,12 @@ static int bcm2835_codec_create_componen
-
- /* Now we have a component we can set all the ctrls */
- bcm2835_codec_set_ctrls(ctx);
-+ } else {
-+ if (ctx->q_data[V4L2_M2M_DST].sizeimage <
-+ ctx->component->output[0].minimum_buffer.size)
-+ v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
-+ ctx->q_data[V4L2_M2M_DST].sizeimage,
-+ ctx->component->output[0].minimum_buffer.size);
- }
-
- return 0;
-@@ -2090,8 +2118,6 @@ static int bcm2835_codec_open(struct fil
- struct v4l2_ctrl_handler *hdl;
- int rc = 0;
-
-- v4l2_dbg(1, debug, &dev->v4l2_dev, "Creating instance for %s\n",
-- dev->decode ? "decode" : "encode");
- if (mutex_lock_interruptible(&dev->dev_mutex)) {
- v4l2_err(&dev->v4l2_dev, "Mutex fail\n");
- return -ERESTARTSYS;
-@@ -2104,7 +2130,8 @@ static int bcm2835_codec_open(struct fil
-
- ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
- ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
-- if (dev->decode) {
-+ switch (dev->role) {
-+ case DECODE:
- /*
- * Input width and height are irrelevant as they will be defined
- * by the bitstream not the format. Required by V4L2 though.
-@@ -2126,7 +2153,8 @@ static int bcm2835_codec_open(struct fil
- get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
- ctx->q_data[V4L2_M2M_DST].height,
- ctx->q_data[V4L2_M2M_DST].fmt);
-- } else {
-+ break;
-+ case ENCODE:
- ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
- ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
- ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
-@@ -2144,6 +2172,9 @@ static int bcm2835_codec_open(struct fil
- ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
- ctx->q_data[V4L2_M2M_DST].sizeimage =
- DEF_COMP_BUF_SIZE_720P_OR_LESS;
-+ break;
-+ case ISP:
-+ break;
- }
-
- ctx->colorspace = V4L2_COLORSPACE_REC709;
-@@ -2154,7 +2185,7 @@ static int bcm2835_codec_open(struct fil
- file->private_data = &ctx->fh;
- ctx->dev = dev;
- hdl = &ctx->hdl;
-- if (!dev->decode) {
-+ if (dev->role == ENCODE) {
- /* Encode controls */
- v4l2_ctrl_handler_init(hdl, 6);
-
-@@ -2303,14 +2334,11 @@ static int bcm2835_codec_get_supported_f
- unsigned int i, j, num_encodings;
- int ret;
-
-- ret = vchiq_mmal_component_init(dev->instance,
-- dev->decode ?
-- "ril.video_decode" :
-- "ril.video_encode",
-+ ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
- &component);
- if (ret < 0) {
-- v4l2_err(&dev->v4l2_dev, "%s: failed to create component\n",
-- __func__);
-+ v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
-+ __func__, components[dev->role]);
- return -ENOMEM;
- }
-
-@@ -2406,12 +2434,13 @@ destroy_component:
-
- static int bcm2835_codec_create(struct platform_device *pdev,
- struct bcm2835_codec_dev **new_dev,
-- bool decode)
-+ enum bcm2835_codec_role role)
- {
- struct bcm2835_codec_dev *dev;
- struct video_device *vfd;
- int video_nr;
- int ret;
-+ const static char *roles[] = {"decode", "encode", "isp"};
-
- dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
- if (!dev)
-@@ -2419,7 +2448,7 @@ static int bcm2835_codec_create(struct p
-
- dev->pdev = pdev;
-
-- dev->decode = decode;
-+ dev->role = role;
-
- ret = vchiq_mmal_init(&dev->instance);
- if (ret)
-@@ -2441,14 +2470,27 @@ static int bcm2835_codec_create(struct p
- vfd->lock = &dev->dev_mutex;
- vfd->v4l2_dev = &dev->v4l2_dev;
-
-- if (dev->decode) {
-+ switch (role) {
-+ case DECODE:
- v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
- v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
- video_nr = decode_video_nr;
-- } else {
-+ break;
-+ case ENCODE:
- v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
- v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
- video_nr = encode_video_nr;
-+ break;
-+ case ISP:
-+ v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
-+ v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
-+ v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
-+ v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
-+ video_nr = isp_video_nr;
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ goto unreg_dev;
- }
-
- ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
-@@ -2473,7 +2515,7 @@ static int bcm2835_codec_create(struct p
- }
-
- v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
-- dev->decode ? "decode" : "encode");
-+ roles[role]);
- return 0;
-
- err_m2m:
-@@ -2509,11 +2551,15 @@ static int bcm2835_codec_probe(struct pl
- if (!drv)
- return -ENOMEM;
-
-- ret = bcm2835_codec_create(pdev, &drv->encode, false);
-+ ret = bcm2835_codec_create(pdev, &drv->decode, DECODE);
- if (ret)
- goto out;
-
-- ret = bcm2835_codec_create(pdev, &drv->decode, true);
-+ ret = bcm2835_codec_create(pdev, &drv->encode, ENCODE);
-+ if (ret)
-+ goto out;
-+
-+ ret = bcm2835_codec_create(pdev, &drv->isp, ISP);
- if (ret)
- goto out;
-
-@@ -2526,6 +2572,10 @@ out:
- bcm2835_codec_destroy(drv->encode);
- drv->encode = NULL;
- }
-+ if (drv->decode) {
-+ bcm2835_codec_destroy(drv->decode);
-+ drv->decode = NULL;
-+ }
- return ret;
- }
-
-@@ -2533,6 +2583,8 @@ static int bcm2835_codec_remove(struct p
- {
- struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
-
-+ bcm2835_codec_destroy(drv->isp);
-+
- bcm2835_codec_destroy(drv->encode);
-
- bcm2835_codec_destroy(drv->decode);
--- /dev/null
+From d5e64fca8218f9553172720752629c8145c91b9e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 18 Feb 2019 15:52:29 +0000
+Subject: [PATCH 362/725] staging: mmal-vchiq: Update mmal_parameters.h with
+ recently defined params
+
+mmal_parameters.h hasn't been updated to reflect additions made
+over the last few years. Update it to reflect the currently
+supported parameters.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vchiq-mmal/mmal-parameters.h | 32 ++++++++++++++++++-
+ 1 file changed, 31 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
+@@ -580,7 +580,37 @@ enum mmal_parameter_video_type {
+ MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG,
+
+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+- MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER
++ MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
++
++ /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
++ MMAL_PARAMETER_VIDEO_ENCODE_SEI_ENABLE,
++
++ /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
++ MMAL_PARAMETER_VIDEO_ENCODE_INLINE_VECTORS,
++
++ /**< Take a @ref MMAL_PARAMETER_VIDEO_RENDER_STATS_T. */
++ MMAL_PARAMETER_VIDEO_RENDER_STATS,
++
++ /**< Take a @ref MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T. */
++ MMAL_PARAMETER_VIDEO_INTERLACE_TYPE,
++
++ /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_VIDEO_INTERPOLATE_TIMESTAMPS,
++
++ /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING,
++
++ /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS,
++
++ /**< Takes a @ref MMAL_PARAMETER_SOURCE_PATTERN_T */
++ MMAL_PARAMETER_VIDEO_SOURCE_PATTERN,
++
++ /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_VIDEO_ENCODE_SEPARATE_NAL_BUFS,
++
++ /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAME_LENGTH,
+ };
+
+ /** Valid mirror modes */
+++ /dev/null
-From bb5864d9cbab452b7946b5ef97e781cf6e18e8b9 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 15 Feb 2019 11:36:14 +0000
-Subject: [PATCH 363/703] staging: bcm2835_codec: Add an option for ignoring
- Bayer formats.
-
-This is a workaround for GStreamer currently not identifying Bayer
-as a raw format, therefore any device that supports it does not
-match the criteria for v4l2convert.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c | 29 ++++++++++++++++++-
- 1 file changed, 28 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -58,6 +58,15 @@ static int isp_video_nr = 12;
- module_param(isp_video_nr, int, 0644);
- MODULE_PARM_DESC(isp_video_nr, "isp video device number");
-
-+/*
-+ * Workaround for GStreamer v4l2convert component not considering Bayer formats
-+ * as raw, and therefore not considering a V4L2 device that supports them as
-+ * as a suitable candidate.
-+ */
-+static bool disable_bayer;
-+module_param(disable_bayer, bool, 0644);
-+MODULE_PARM_DESC(disable_bayer, "Disable support for Bayer formats");
-+
- static unsigned int debug;
- module_param(debug, uint, 0644);
- MODULE_PARM_DESC(debug, "activates debug info (0-3)");
-@@ -105,6 +114,7 @@ struct bcm2835_codec_fmt {
- u32 flags;
- u32 mmal_fmt;
- int size_multiplier_x2;
-+ bool is_bayer;
- };
-
- static const struct bcm2835_codec_fmt supported_formats[] = {
-@@ -203,6 +213,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB8,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- .fourcc = V4L2_PIX_FMT_SBGGR8,
- .depth = 8,
-@@ -210,6 +221,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR8,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- .fourcc = V4L2_PIX_FMT_SGRBG8,
- .depth = 8,
-@@ -217,6 +229,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG8,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- .fourcc = V4L2_PIX_FMT_SGBRG8,
- .depth = 8,
-@@ -224,6 +237,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG8,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- /* 10 bit */
- .fourcc = V4L2_PIX_FMT_SRGGB10P,
-@@ -232,6 +246,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB10P,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- .fourcc = V4L2_PIX_FMT_SBGGR10P,
- .depth = 10,
-@@ -239,6 +254,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR10P,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- .fourcc = V4L2_PIX_FMT_SGRBG10P,
- .depth = 10,
-@@ -246,6 +262,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG10P,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- .fourcc = V4L2_PIX_FMT_SGBRG10P,
- .depth = 10,
-@@ -253,6 +270,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG10P,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- /* 12 bit */
- .fourcc = V4L2_PIX_FMT_SRGGB12P,
-@@ -261,6 +279,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB12P,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- .fourcc = V4L2_PIX_FMT_SBGGR12P,
- .depth = 12,
-@@ -268,6 +287,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR12P,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- .fourcc = V4L2_PIX_FMT_SGRBG12P,
- .depth = 12,
-@@ -275,6 +295,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG12P,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- .fourcc = V4L2_PIX_FMT_SGBRG12P,
- .depth = 12,
-@@ -282,6 +303,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG12P,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- /* 16 bit */
- .fourcc = V4L2_PIX_FMT_SRGGB16,
-@@ -290,6 +312,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB16,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- .fourcc = V4L2_PIX_FMT_SBGGR16,
- .depth = 16,
-@@ -297,6 +320,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR16,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- .fourcc = V4L2_PIX_FMT_SGRBG16,
- .depth = 16,
-@@ -304,6 +328,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG16,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- .fourcc = V4L2_PIX_FMT_SGBRG16,
- .depth = 16,
-@@ -311,6 +336,7 @@ static const struct bcm2835_codec_fmt su
- .flags = 0,
- .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG16,
- .size_multiplier_x2 = 2,
-+ .is_bayer = true,
- }, {
- /* Compressed formats */
- .fourcc = V4L2_PIX_FMT_H264,
-@@ -438,7 +464,8 @@ static const struct bcm2835_codec_fmt *g
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
-- if (supported_formats[i].mmal_fmt == mmal_fmt)
-+ if (supported_formats[i].mmal_fmt == mmal_fmt &&
-+ (!disable_bayer || !supported_formats[i].is_bayer))
- return &supported_formats[i];
- }
- return NULL;
--- /dev/null
+From 87a65d77b96f9d87d0df9da9505a3dbbadf70baf Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 18 Feb 2019 15:56:42 +0000
+Subject: [PATCH 363/725] staging: bcm2835_codec: Include timing info in SPS
+ headers
+
+Inserting timing information into the VUI block of the SPS is
+optional with the VPU encoder.
+GStreamer appears to require them when using V4L2 M2M, therefore
+set the option to enable them from the encoder.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -1785,6 +1785,8 @@ static int bcm2835_codec_create_componen
+ goto destroy_component;
+
+ if (dev->role == ENCODE) {
++ u32 param = 1;
++
+ if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
+ ctx->component->output[0].minimum_buffer.size)
+ v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
+@@ -1793,6 +1795,16 @@ static int bcm2835_codec_create_componen
+
+ /* Now we have a component we can set all the ctrls */
+ bcm2835_codec_set_ctrls(ctx);
++
++ /* Enable SPS Timing header so framerate information is encoded
++ * in the H264 header.
++ */
++ vchiq_mmal_port_parameter_set(
++ ctx->dev->instance,
++ &ctx->component->output[0],
++ MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING,
++ ¶m, sizeof(param));
++
+ } else {
+ if (ctx->q_data[V4L2_M2M_DST].sizeimage <
+ ctx->component->output[0].minimum_buffer.size)
--- /dev/null
+From 7f97b8d48bb2c2f67c8f7a81983e7223c91adfb0 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 5 Feb 2018 18:53:18 +0000
+Subject: [PATCH 364/725] drm/vc4: Don't wait for vblank on fkms cursor
+ updates.
+
+We don't use the same async update path between fkms and normal kms,
+and the normal kms workaround ended up making us wait. This became a
+larger problem in rpi-4.14.y, as the USB HID update rate throttling
+got (accidentally?) dropped.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_kms.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -222,7 +222,8 @@ static int vc4_atomic_commit(struct drm_
+ * drm_atomic_helper_setup_commit() from auto-completing
+ * commit->flip_done.
+ */
+- state->legacy_cursor_update = false;
++ if (!vc4->firmware_kms)
++ state->legacy_cursor_update = false;
+ ret = drm_atomic_helper_setup_commit(state, nonblock);
+ if (ret)
+ return ret;
+++ /dev/null
-From d103cd3b55e4285f2c0ad937cf31bea9ebaa4d21 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 15 Feb 2019 11:38:45 +0000
-Subject: [PATCH 364/703] staging: bcm2835_codec: Fix handling of
- VB2_MEMORY_DMABUF buffers
-
-If the queue is configured as VB2_MEMORY_DMABUF then vb2_core_expbuf
-fails as it ensures the queue is defined as VB2_MEMORY_MMAP.
-
-Correct the handling so that we unmap the buffer from vcsm and the
-VPU on cleanup, and then correctly get the dma buf of the new buffer.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c | 80 +++++++++++++------
- .../vc04_services/vchiq-mmal/mmal-vchiq.c | 21 +++--
- .../vc04_services/vchiq-mmal/mmal-vchiq.h | 2 +
- 3 files changed, 73 insertions(+), 30 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -1852,6 +1852,18 @@ static int bcm2835_codec_queue_setup(str
- return 0;
- }
-
-+static int bcm2835_codec_mmal_buf_cleanup(struct mmal_buffer *mmal_buf)
-+{
-+ mmal_vchi_buffer_cleanup(mmal_buf);
-+
-+ if (mmal_buf->dma_buf) {
-+ dma_buf_put(mmal_buf->dma_buf);
-+ mmal_buf->dma_buf = NULL;
-+ }
-+
-+ return 0;
-+}
-+
- static int bcm2835_codec_buf_init(struct vb2_buffer *vb)
- {
- struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-@@ -1880,6 +1892,7 @@ static int bcm2835_codec_buf_prepare(str
- vb);
- struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
- m2m);
-+ struct dma_buf *dma_buf;
- int ret;
-
- v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p\n",
-@@ -1906,20 +1919,48 @@ static int bcm2835_codec_buf_prepare(str
- if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
- vb2_set_plane_payload(vb, 0, q_data->sizeimage);
-
-- /*
-- * We want to do this at init, but vb2_core_expbuf checks that the
-- * index < q->num_buffers, and q->num_buffers only gets updated once
-- * all the buffers are allocated.
-- */
-- if (!buf->mmal.dma_buf) {
-- ret = vb2_core_expbuf_dmabuf(vb->vb2_queue,
-- vb->vb2_queue->type, vb->index, 0,
-- O_CLOEXEC, &buf->mmal.dma_buf);
-- if (ret)
-- v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed to expbuf idx %d, ret %d\n",
-- __func__, vb->index, ret);
-- } else {
-+ switch (vb->memory) {
-+ case VB2_MEMORY_DMABUF:
-+ dma_buf = dma_buf_get(vb->planes[0].m.fd);
-+
-+ if (dma_buf != buf->mmal.dma_buf) {
-+ /* dmabuf either hasn't already been mapped, or it has
-+ * changed.
-+ */
-+ if (buf->mmal.dma_buf) {
-+ v4l2_err(&ctx->dev->v4l2_dev,
-+ "%s Buffer changed - why did the core not call cleanup?\n",
-+ __func__);
-+ bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
-+ }
-+
-+ buf->mmal.dma_buf = dma_buf;
-+ }
- ret = 0;
-+ break;
-+ case VB2_MEMORY_MMAP:
-+ /*
-+ * We want to do this at init, but vb2_core_expbuf checks that
-+ * the index < q->num_buffers, and q->num_buffers only gets
-+ * updated once all the buffers are allocated.
-+ */
-+ if (!buf->mmal.dma_buf) {
-+ ret = vb2_core_expbuf_dmabuf(vb->vb2_queue,
-+ vb->vb2_queue->type,
-+ vb->index, 0,
-+ O_CLOEXEC,
-+ &buf->mmal.dma_buf);
-+ if (ret)
-+ v4l2_err(&ctx->dev->v4l2_dev,
-+ "%s: Failed to expbuf idx %d, ret %d\n",
-+ __func__, vb->index, ret);
-+ } else {
-+ ret = 0;
-+ }
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ break;
- }
-
- return ret;
-@@ -1948,12 +1989,7 @@ static void bcm2835_codec_buffer_cleanup
- v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
- __func__, ctx, vb);
-
-- mmal_vchi_buffer_cleanup(&buf->mmal);
--
-- if (buf->mmal.dma_buf) {
-- dma_buf_put(buf->mmal.dma_buf);
-- buf->mmal.dma_buf = NULL;
-- }
-+ bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
- }
-
- static int bcm2835_codec_start_streaming(struct vb2_queue *q,
-@@ -2067,11 +2103,7 @@ static void bcm2835_codec_stop_streaming
- m2m = container_of(vb2, struct v4l2_m2m_buffer, vb);
- buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
-
-- mmal_vchi_buffer_cleanup(&buf->mmal);
-- if (buf->mmal.dma_buf) {
-- dma_buf_put(buf->mmal.dma_buf);
-- buf->mmal.dma_buf = NULL;
-- }
-+ bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
- }
-
- /* If both ports disabled, then disable the component */
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -1785,13 +1785,9 @@ int mmal_vchi_buffer_init(struct vchiq_m
- }
- EXPORT_SYMBOL_GPL(mmal_vchi_buffer_init);
-
--int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
-+int mmal_vchi_buffer_unmap(struct mmal_buffer *buf)
- {
-- struct mmal_msg_context *msg_context = buf->msg_context;
--
-- if (msg_context)
-- release_msg_context(msg_context);
-- buf->msg_context = NULL;
-+ int ret = 0;
-
- if (buf->vcsm_handle) {
- int ret;
-@@ -1803,6 +1799,19 @@ int mmal_vchi_buffer_cleanup(struct mmal
- pr_err("%s: vcsm_free failed, ret %d\n", __func__, ret);
- buf->vcsm_handle = 0;
- }
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(mmal_vchi_buffer_unmap);
-+
-+int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
-+{
-+ struct mmal_msg_context *msg_context = buf->msg_context;
-+
-+ if (msg_context)
-+ release_msg_context(msg_context);
-+ buf->msg_context = NULL;
-+
-+ mmal_vchi_buffer_unmap(buf);
- return 0;
- }
- EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
-@@ -167,6 +167,8 @@ int vchiq_mmal_submit_buffer(struct vchi
- struct vchiq_mmal_port *port,
- struct mmal_buffer *buf);
-
-+int mmal_vchi_buffer_unmap(struct mmal_buffer *buf);
-+
- int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
- struct mmal_buffer *buf);
- int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf);
--- /dev/null
+From 482738fa793cdc446e827233edc24d3db86ab1c0 Mon Sep 17 00:00:00 2001
+From: Giedrius <giedrius@blokas.io>
+Date: Wed, 27 Feb 2019 14:27:28 +0000
+Subject: [PATCH 365/725] Fix for Pisound kernel module in Real Time kernel
+ configuration.
+
+When handler of data_available interrupt is fired, queue_work ends up
+getting called and it can block on a spin lock which is not allowed in
+interrupt context. The fix was to run the handler from a thread context
+instead.
+---
+ sound/soc/bcm/pisound.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/sound/soc/bcm/pisound.c
++++ b/sound/soc/bcm/pisound.c
+@@ -1,6 +1,6 @@
+ /*
+ * Pisound Linux kernel module.
+- * Copyright (C) 2016-2017 Vilniaus Blokas UAB, https://blokas.io/pisound
++ * Copyright (C) 2016-2019 Vilniaus Blokas UAB, https://blokas.io/pisound
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+@@ -532,10 +532,10 @@ static void pisnd_spi_gpio_uninit(void)
+
+ static int pisnd_spi_gpio_irq_init(struct device *dev)
+ {
+- return request_irq(
+- gpiod_to_irq(data_available),
++ return request_threaded_irq(
++ gpiod_to_irq(data_available), NULL,
+ data_available_interrupt_handler,
+- IRQF_TIMER | IRQF_TRIGGER_RISING,
++ IRQF_TIMER | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "data_available_int",
+ NULL
+ );
+++ /dev/null
-From c295d66017878afeee903f9f324b59e847dfb69b Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 18 Feb 2019 15:52:29 +0000
-Subject: [PATCH 365/703] staging: mmal-vchiq: Update mmal_parameters.h with
- recently defined params
-
-mmal_parameters.h hasn't been updated to reflect additions made
-over the last few years. Update it to reflect the currently
-supported parameters.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vchiq-mmal/mmal-parameters.h | 32 ++++++++++++++++++-
- 1 file changed, 31 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
-@@ -580,7 +580,37 @@ enum mmal_parameter_video_type {
- MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG,
-
- /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-- MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER
-+ MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
-+
-+ /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
-+ MMAL_PARAMETER_VIDEO_ENCODE_SEI_ENABLE,
-+
-+ /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
-+ MMAL_PARAMETER_VIDEO_ENCODE_INLINE_VECTORS,
-+
-+ /**< Take a @ref MMAL_PARAMETER_VIDEO_RENDER_STATS_T. */
-+ MMAL_PARAMETER_VIDEO_RENDER_STATS,
-+
-+ /**< Take a @ref MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T. */
-+ MMAL_PARAMETER_VIDEO_INTERLACE_TYPE,
-+
-+ /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_VIDEO_INTERPOLATE_TIMESTAMPS,
-+
-+ /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING,
-+
-+ /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
-+ MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS,
-+
-+ /**< Takes a @ref MMAL_PARAMETER_SOURCE_PATTERN_T */
-+ MMAL_PARAMETER_VIDEO_SOURCE_PATTERN,
-+
-+ /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_VIDEO_ENCODE_SEPARATE_NAL_BUFS,
-+
-+ /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
-+ MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAME_LENGTH,
- };
-
- /** Valid mirror modes */
--- /dev/null
+From 2ff0243b891590549f6669104be51b76325ce167 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 27 Feb 2019 20:08:48 +0000
+Subject: [PATCH 366/725] config: Add CONFIG_FB_TFT_SH1106=m
+
+See: https://github.com/raspberrypi/linux/issues/2876
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/configs/bcm2709_defconfig | 3 ++-
+ arch/arm/configs/bcmrpi_defconfig | 3 ++-
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ 3 files changed, 5 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -905,8 +905,8 @@ CONFIG_SND_BCM2835_SOC_I2S=m
+ CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
+ CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
+-CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
+ CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m
+@@ -1203,6 +1203,7 @@ CONFIG_FB_TFT_PCD8544=m
+ CONFIG_FB_TFT_RA8875=m
+ CONFIG_FB_TFT_S6D02A1=m
+ CONFIG_FB_TFT_S6D1121=m
++CONFIG_FB_TFT_SH1106=m
+ CONFIG_FB_TFT_SSD1289=m
+ CONFIG_FB_TFT_SSD1306=m
+ CONFIG_FB_TFT_SSD1331=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -898,8 +898,8 @@ CONFIG_SND_BCM2835_SOC_I2S=m
+ CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
+ CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
+-CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
+ CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m
+@@ -1196,6 +1196,7 @@ CONFIG_FB_TFT_PCD8544=m
+ CONFIG_FB_TFT_RA8875=m
+ CONFIG_FB_TFT_S6D02A1=m
+ CONFIG_FB_TFT_S6D1121=m
++CONFIG_FB_TFT_SH1106=m
+ CONFIG_FB_TFT_SSD1289=m
+ CONFIG_FB_TFT_SSD1306=m
+ CONFIG_FB_TFT_SSD1331=m
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -1061,6 +1061,7 @@ CONFIG_FB_TFT_PCD8544=m
+ CONFIG_FB_TFT_RA8875=m
+ CONFIG_FB_TFT_S6D02A1=m
+ CONFIG_FB_TFT_S6D1121=m
++CONFIG_FB_TFT_SH1106=m
+ CONFIG_FB_TFT_SSD1289=m
+ CONFIG_FB_TFT_SSD1306=m
+ CONFIG_FB_TFT_SSD1331=m
+++ /dev/null
-From 90a411bf61170375a4392b603e6f085ff0c68927 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 18 Feb 2019 15:56:42 +0000
-Subject: [PATCH 366/703] staging: bcm2835_codec: Include timing info in SPS
- headers
-
-Inserting timing information into the VUI block of the SPS is
-optional with the VPU encoder.
-GStreamer appears to require them when using V4L2 M2M, therefore
-set the option to enable them from the encoder.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -1785,6 +1785,8 @@ static int bcm2835_codec_create_componen
- goto destroy_component;
-
- if (dev->role == ENCODE) {
-+ u32 param = 1;
-+
- if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
- ctx->component->output[0].minimum_buffer.size)
- v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
-@@ -1793,6 +1795,16 @@ static int bcm2835_codec_create_componen
-
- /* Now we have a component we can set all the ctrls */
- bcm2835_codec_set_ctrls(ctx);
-+
-+ /* Enable SPS Timing header so framerate information is encoded
-+ * in the H264 header.
-+ */
-+ vchiq_mmal_port_parameter_set(
-+ ctx->dev->instance,
-+ &ctx->component->output[0],
-+ MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING,
-+ ¶m, sizeof(param));
-+
- } else {
- if (ctx->q_data[V4L2_M2M_DST].sizeimage <
- ctx->component->output[0].minimum_buffer.size)
--- /dev/null
+From c5d112f24ec5bc168f8af900f7ed0cd7341ef6ba Mon Sep 17 00:00:00 2001
+From: Jaikumar <jaikumar@cem-solutions.net>
+Date: Thu, 7 Jun 2018 21:22:45 +0530
+Subject: [PATCH 367/725] Added mute stream func
+
+Signed-off-by: Jaikumar <jaikumar@cem-solutions.net>
+---
+ sound/soc/bcm/allo-katana-codec.c | 60 ++++++++++++++++++++++---------
+ 1 file changed, 44 insertions(+), 16 deletions(-)
+
+--- a/sound/soc/bcm/allo-katana-codec.c
++++ b/sound/soc/bcm/allo-katana-codec.c
+@@ -31,21 +31,23 @@
+
+ #define KATANA_CODEC_CHIP_ID 0x30
+ #define KATANA_CODEC_VIRT_BASE 0x100
+-#define KATANA_CODEC_PAGE 0
++#define KATANA_CODEC_PAGE 0
+
+ #define KATANA_CODEC_CHIP_ID_REG (KATANA_CODEC_VIRT_BASE + 0)
+-#define KATANA_CODEC_RESET (KATANA_CODEC_VIRT_BASE + 1)
++#define KATANA_CODEC_RESET (KATANA_CODEC_VIRT_BASE + 1)
+ #define KATANA_CODEC_VOLUME_1 (KATANA_CODEC_VIRT_BASE + 2)
+ #define KATANA_CODEC_VOLUME_2 (KATANA_CODEC_VIRT_BASE + 3)
+-#define KATANA_CODEC_MUTE (KATANA_CODEC_VIRT_BASE + 4)
++#define KATANA_CODEC_MUTE (KATANA_CODEC_VIRT_BASE + 4)
+ #define KATANA_CODEC_DSP_PROGRAM (KATANA_CODEC_VIRT_BASE + 5)
+ #define KATANA_CODEC_DEEMPHASIS (KATANA_CODEC_VIRT_BASE + 6)
+-#define KATANA_CODEC_DOP (KATANA_CODEC_VIRT_BASE + 7)
+-#define KATANA_CODEC_FORMAT (KATANA_CODEC_VIRT_BASE + 8)
++#define KATANA_CODEC_DOP (KATANA_CODEC_VIRT_BASE + 7)
++#define KATANA_CODEC_FORMAT (KATANA_CODEC_VIRT_BASE + 8)
+ #define KATANA_CODEC_COMMAND (KATANA_CODEC_VIRT_BASE + 9)
+-#define KATANA_CODEC_MAX_REGISTER (KATANA_CODEC_VIRT_BASE + 9)
++#define KATANA_CODEC_MUTE_STREAM (KATANA_CODEC_VIRT_BASE + 10)
+
+-#define KATANA_CODEC_FMT 0xff
++#define KATANA_CODEC_MAX_REGISTER (KATANA_CODEC_VIRT_BASE + 10)
++
++#define KATANA_CODEC_FMT 0xff
+ #define KATANA_CODEC_CHAN_MONO 0x00
+ #define KATANA_CODEC_CHAN_STEREO 0x80
+ #define KATANA_CODEC_ALEN_16 0x10
+@@ -135,7 +137,8 @@ static const struct snd_kcontrol_new kat
+ SOC_SINGLE("DoP Playback Switch", KATANA_CODEC_DOP, 0, 1, 1)
+ };
+
+-static bool katana_codec_readable_register(struct device *dev, unsigned int reg)
++static bool katana_codec_readable_register(struct device *dev,
++ unsigned int reg)
+ {
+ switch (reg) {
+ case KATANA_CODEC_CHIP_ID_REG:
+@@ -150,13 +153,15 @@ static int katana_codec_hw_params(struct
+ struct snd_soc_dai *dai)
+ {
+ struct snd_soc_component *component = dai->component;
+- struct katana_codec_priv *katana_codec = snd_soc_component_get_drvdata(component);
++ struct katana_codec_priv *katana_codec =
++ snd_soc_component_get_drvdata(component);
+ int fmt = 0;
+ int ret;
+
+- dev_dbg(component->card->dev, "hw_params %u Hz, %u channels\n",
++ dev_dbg(component->card->dev, "hw_params %u Hz, %u channels, %u bits\n",
+ params_rate(params),
+- params_channels(params));
++ params_channels(params),
++ params_width(params));
+
+ switch (katana_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM: // master
+@@ -212,13 +217,17 @@ static int katana_codec_hw_params(struct
+ return -EINVAL;
+ }
+
+- ret = regmap_write(katana_codec->regmap, KATANA_CODEC_FORMAT, fmt);
++ ret = regmap_write(katana_codec->regmap, KATANA_CODEC_FORMAT,
++ fmt);
+ if (ret != 0) {
+ dev_err(component->card->dev, "Failed to set format: %d\n", ret);
+ return ret;
+ }
+ break;
+
++ case SND_SOC_DAIFMT_CBS_CFS:
++ break;
++
+ default:
+ return -EINVAL;
+ }
+@@ -229,14 +238,33 @@ static int katana_codec_hw_params(struct
+ static int katana_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+ {
+ struct snd_soc_component *component = dai->component;
+- struct katana_codec_priv *katana_codec = snd_soc_component_get_drvdata(component);
++ struct katana_codec_priv *katana_codec =
++ snd_soc_component_get_drvdata(component);
+
+ katana_codec->fmt = fmt;
+
+ return 0;
+ }
+
++int katana_codec_dai_mute_stream(struct snd_soc_dai *dai, int mute,
++ int stream)
++{
++ struct snd_soc_component *component = dai->component;
++ struct katana_codec_priv *katana_codec =
++ snd_soc_component_get_drvdata(component);
++ int ret = 0;
++
++ ret = regmap_write(katana_codec->regmap, KATANA_CODEC_MUTE_STREAM,
++ mute);
++ if (ret != 0) {
++ dev_err(component->card->dev, "Failed to set mute: %d\n", ret);
++ return ret;
++ }
++ return ret;
++}
++
+ static const struct snd_soc_dai_ops katana_codec_dai_ops = {
++ .mute_stream = katana_codec_dai_mute_stream,
+ .hw_params = katana_codec_hw_params,
+ .set_fmt = katana_codec_set_fmt,
+ };
+@@ -300,7 +328,7 @@ static int allo_katana_component_probe(s
+ return PTR_ERR(regmap);
+
+ katana_codec = devm_kzalloc(dev, sizeof(struct katana_codec_priv),
+- GFP_KERNEL);
++ GFP_KERNEL);
+ if (!katana_codec)
+ return -ENOMEM;
+
+@@ -348,8 +376,8 @@ static struct i2c_driver allo_katana_com
+ .remove = allo_katana_component_remove,
+ .id_table = allo_katana_component_id,
+ .driver = {
+- .name = "allo-katana-codec",
+- .of_match_table = allo_katana_codec_of_match,
++ .name = "allo-katana-codec",
++ .of_match_table = allo_katana_codec_of_match,
+ },
+ };
+
+++ /dev/null
-From 2e2eb767bf98517b95fc7d7e1d28b802b41bfcd9 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 5 Feb 2018 18:53:18 +0000
-Subject: [PATCH 367/703] drm/vc4: Don't wait for vblank on fkms cursor
- updates.
-
-We don't use the same async update path between fkms and normal kms,
-and the normal kms workaround ended up making us wait. This became a
-larger problem in rpi-4.14.y, as the USB HID update rate throttling
-got (accidentally?) dropped.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_kms.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -222,7 +222,8 @@ static int vc4_atomic_commit(struct drm_
- * drm_atomic_helper_setup_commit() from auto-completing
- * commit->flip_done.
- */
-- state->legacy_cursor_update = false;
-+ if (!vc4->firmware_kms)
-+ state->legacy_cursor_update = false;
- ret = drm_atomic_helper_setup_commit(state, nonblock);
- if (ret)
- return ret;
+++ /dev/null
-From 3e9ce629c2f5f9f58c0b869261226ab811e2d5a7 Mon Sep 17 00:00:00 2001
-From: Giedrius <giedrius@blokas.io>
-Date: Wed, 27 Feb 2019 14:27:28 +0000
-Subject: [PATCH 368/703] Fix for Pisound kernel module in Real Time kernel
- configuration.
-
-When handler of data_available interrupt is fired, queue_work ends up
-getting called and it can block on a spin lock which is not allowed in
-interrupt context. The fix was to run the handler from a thread context
-instead.
----
- sound/soc/bcm/pisound.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
---- a/sound/soc/bcm/pisound.c
-+++ b/sound/soc/bcm/pisound.c
-@@ -1,6 +1,6 @@
- /*
- * Pisound Linux kernel module.
-- * Copyright (C) 2016-2017 Vilniaus Blokas UAB, https://blokas.io/pisound
-+ * Copyright (C) 2016-2019 Vilniaus Blokas UAB, https://blokas.io/pisound
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
-@@ -532,10 +532,10 @@ static void pisnd_spi_gpio_uninit(void)
-
- static int pisnd_spi_gpio_irq_init(struct device *dev)
- {
-- return request_irq(
-- gpiod_to_irq(data_available),
-+ return request_threaded_irq(
-+ gpiod_to_irq(data_available), NULL,
- data_available_interrupt_handler,
-- IRQF_TIMER | IRQF_TRIGGER_RISING,
-+ IRQF_TIMER | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
- "data_available_int",
- NULL
- );
--- /dev/null
+From 6a63c8e17c19fe3aa7b112a0f63fd5ad8b2f9d9c Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 5 Mar 2019 09:51:22 +0000
+Subject: [PATCH 368/725] lan78xx: EEE support is now a PHY property
+
+Now that EEE support is a property of the PHY, use the PHY's DT node
+when querying the EEE-related properties.
+
+See: https://github.com/raspberrypi/linux/issues/2882
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/net/usb/lan78xx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -2191,7 +2191,7 @@ static int lan78xx_phy_init(struct lan78
+ mii_adv = (u32)mii_advertise_flowctrl(dev->fc_request_control);
+ phydev->advertising |= mii_adv_to_ethtool_adv_t(mii_adv);
+
+- if (of_property_read_bool(dev->udev->dev.of_node,
++ if (of_property_read_bool(phydev->mdio.dev.of_node,
+ "microchip,eee-enabled")) {
+ struct ethtool_eee edata;
+ memset(&edata, 0, sizeof(edata));
+++ /dev/null
-From 9a9dd897e8de1bbf48dae13f1bdaa99996ab3b52 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 27 Feb 2019 20:08:48 +0000
-Subject: [PATCH 369/703] config: Add CONFIG_FB_TFT_SH1106=m
-
-See: https://github.com/raspberrypi/linux/issues/2876
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/configs/bcm2709_defconfig | 3 ++-
- arch/arm/configs/bcmrpi_defconfig | 3 ++-
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- 3 files changed, 5 insertions(+), 2 deletions(-)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -905,8 +905,8 @@ CONFIG_SND_BCM2835_SOC_I2S=m
- CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
- CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
--CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
-+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
- CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m
-@@ -1203,6 +1203,7 @@ CONFIG_FB_TFT_PCD8544=m
- CONFIG_FB_TFT_RA8875=m
- CONFIG_FB_TFT_S6D02A1=m
- CONFIG_FB_TFT_S6D1121=m
-+CONFIG_FB_TFT_SH1106=m
- CONFIG_FB_TFT_SSD1289=m
- CONFIG_FB_TFT_SSD1306=m
- CONFIG_FB_TFT_SSD1331=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -898,8 +898,8 @@ CONFIG_SND_BCM2835_SOC_I2S=m
- CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
- CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
--CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
-+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
- CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m
-@@ -1196,6 +1196,7 @@ CONFIG_FB_TFT_PCD8544=m
- CONFIG_FB_TFT_RA8875=m
- CONFIG_FB_TFT_S6D02A1=m
- CONFIG_FB_TFT_S6D1121=m
-+CONFIG_FB_TFT_SH1106=m
- CONFIG_FB_TFT_SSD1289=m
- CONFIG_FB_TFT_SSD1306=m
- CONFIG_FB_TFT_SSD1331=m
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -1061,6 +1061,7 @@ CONFIG_FB_TFT_PCD8544=m
- CONFIG_FB_TFT_RA8875=m
- CONFIG_FB_TFT_S6D02A1=m
- CONFIG_FB_TFT_S6D1121=m
-+CONFIG_FB_TFT_SH1106=m
- CONFIG_FB_TFT_SSD1289=m
- CONFIG_FB_TFT_SSD1306=m
- CONFIG_FB_TFT_SSD1331=m
--- /dev/null
+From 2f1aba45a3100491bc06f5ce8b9d1e49a5bc261d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 27 Feb 2019 17:30:33 +0000
+Subject: [PATCH 369/725] video: bcm2708_fb: Try allocating on the ARM and
+ passing to VPU
+
+Currently the VPU allocates the contiguous buffer for the
+framebuffer.
+Try an alternate path first where we use dma_alloc_coherent
+and pass the buffer to the VPU. Should the VPU firmware not
+support that path, then free the buffer and revert to the
+old behaviour of using the VPU allocation.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/video/fbdev/bcm2708_fb.c | 102 ++++++++++++++++++---
+ include/soc/bcm2835/raspberrypi-firmware.h | 1 +
+ 2 files changed, 91 insertions(+), 12 deletions(-)
+
+--- a/drivers/video/fbdev/bcm2708_fb.c
++++ b/drivers/video/fbdev/bcm2708_fb.c
+@@ -98,6 +98,11 @@ struct bcm2708_fb {
+ struct bcm2708_fb_stats stats;
+ unsigned long fb_bus_address;
+ struct { u32 base, length; } gpu;
++
++ bool disable_arm_alloc;
++ unsigned int image_size;
++ dma_addr_t dma_addr;
++ void *cpuaddr;
+ };
+
+ #define to_bcm2708(info) container_of(info, struct bcm2708_fb, fb)
+@@ -283,23 +288,88 @@ static int bcm2708_fb_set_par(struct fb_
+ .xoffset = info->var.xoffset,
+ .yoffset = info->var.yoffset,
+ .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
+- .base = 0,
+- .screen_size = 0,
+- .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
+- .pitch = 0,
++ /* base and screen_size will be initialised later */
++ .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
++ /* pitch will be initialised later */
+ };
+- int ret;
++ int ret, image_size;
++
+
+ print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
+ info->var.xres, info->var.yres, info->var.xres_virtual,
+ info->var.yres_virtual, (int)info->screen_size,
+ info->var.bits_per_pixel);
+
+- ret = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo));
++ /* Try allocating our own buffer. We can specify all the parameters */
++ image_size = ((info->var.xres * info->var.yres) *
++ info->var.bits_per_pixel) >> 3;
++
++ if (!fb->disable_arm_alloc &&
++ (image_size != fb->image_size || !fb->dma_addr)) {
++ if (fb->dma_addr) {
++ dma_free_coherent(info->device, fb->image_size,
++ fb->cpuaddr, fb->dma_addr);
++ fb->image_size = 0;
++ fb->cpuaddr = NULL;
++ fb->dma_addr = 0;
++ }
++
++ fb->cpuaddr = dma_alloc_coherent(info->device, image_size,
++ &fb->dma_addr, GFP_KERNEL);
++
++ if (!fb->cpuaddr) {
++ fb->dma_addr = 0;
++ fb->disable_arm_alloc = true;
++ } else {
++ fb->image_size = image_size;
++ }
++ }
++
++ if (fb->cpuaddr) {
++ fbinfo.base = fb->dma_addr;
++ fbinfo.screen_size = image_size;
++ fbinfo.pitch = (info->var.xres * info->var.bits_per_pixel) >> 3;
++
++ ret = rpi_firmware_property_list(fb->fw, &fbinfo,
++ sizeof(fbinfo));
++ if (ret || fbinfo.base != fb->dma_addr) {
++ /* Firmware either failed, or assigned a different base
++ * address (ie it doesn't support being passed an FB
++ * allocation).
++ * Destroy the allocation, and don't try again.
++ */
++ dma_free_coherent(info->device, fb->image_size,
++ fb->cpuaddr, fb->dma_addr);
++ fb->image_size = 0;
++ fb->cpuaddr = NULL;
++ fb->dma_addr = 0;
++ fb->disable_arm_alloc = true;
++ }
++ } else {
++ /* Our allocation failed - drop into the old scheme of
++ * allocation by the VPU.
++ */
++ ret = -ENOMEM;
++ }
++
+ if (ret) {
+- dev_err(info->device,
+- "Failed to allocate GPU framebuffer (%d)\n", ret);
+- return ret;
++ /* Old scheme:
++ * - FRAMEBUFFER_ALLOCATE passes 0 for base and screen_size.
++ * - GET_PITCH instead of SET_PITCH.
++ */
++ fbinfo.base = 0;
++ fbinfo.screen_size = 0;
++ fbinfo.tag6.tag = RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH;
++ fbinfo.pitch = 0;
++
++ ret = rpi_firmware_property_list(fb->fw, &fbinfo,
++ sizeof(fbinfo));
++ if (ret) {
++ dev_err(info->device,
++ "Failed to allocate GPU framebuffer (%d)\n",
++ ret);
++ return ret;
++ }
+ }
+
+ if (info->var.bits_per_pixel <= 8)
+@@ -314,9 +384,17 @@ static int bcm2708_fb_set_par(struct fb_
+ fb->fb.fix.smem_start = fbinfo.base;
+ fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual;
+ fb->fb.screen_size = fbinfo.screen_size;
+- if (fb->fb.screen_base)
+- iounmap(fb->fb.screen_base);
+- fb->fb.screen_base = ioremap_wc(fbinfo.base, fb->fb.screen_size);
++
++ if (!fb->dma_addr) {
++ if (fb->fb.screen_base)
++ iounmap(fb->fb.screen_base);
++
++ fb->fb.screen_base = ioremap_wc(fbinfo.base,
++ fb->fb.screen_size);
++ } else {
++ fb->fb.screen_base = fb->cpuaddr;
++ }
++
+ if (!fb->fb.screen_base) {
+ /* the console may currently be locked */
+ console_trylock();
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -128,6 +128,7 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
++ RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH = 0x00048008,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
+++ /dev/null
-From ac5d3c0f1d947302f4d518187357720711f4961d Mon Sep 17 00:00:00 2001
-From: Jaikumar <jaikumar@cem-solutions.net>
-Date: Thu, 7 Jun 2018 21:22:45 +0530
-Subject: [PATCH 370/703] Added mute stream func
-
-Signed-off-by: Jaikumar <jaikumar@cem-solutions.net>
----
- sound/soc/bcm/allo-katana-codec.c | 60 ++++++++++++++++++++++---------
- 1 file changed, 44 insertions(+), 16 deletions(-)
-
---- a/sound/soc/bcm/allo-katana-codec.c
-+++ b/sound/soc/bcm/allo-katana-codec.c
-@@ -31,21 +31,23 @@
-
- #define KATANA_CODEC_CHIP_ID 0x30
- #define KATANA_CODEC_VIRT_BASE 0x100
--#define KATANA_CODEC_PAGE 0
-+#define KATANA_CODEC_PAGE 0
-
- #define KATANA_CODEC_CHIP_ID_REG (KATANA_CODEC_VIRT_BASE + 0)
--#define KATANA_CODEC_RESET (KATANA_CODEC_VIRT_BASE + 1)
-+#define KATANA_CODEC_RESET (KATANA_CODEC_VIRT_BASE + 1)
- #define KATANA_CODEC_VOLUME_1 (KATANA_CODEC_VIRT_BASE + 2)
- #define KATANA_CODEC_VOLUME_2 (KATANA_CODEC_VIRT_BASE + 3)
--#define KATANA_CODEC_MUTE (KATANA_CODEC_VIRT_BASE + 4)
-+#define KATANA_CODEC_MUTE (KATANA_CODEC_VIRT_BASE + 4)
- #define KATANA_CODEC_DSP_PROGRAM (KATANA_CODEC_VIRT_BASE + 5)
- #define KATANA_CODEC_DEEMPHASIS (KATANA_CODEC_VIRT_BASE + 6)
--#define KATANA_CODEC_DOP (KATANA_CODEC_VIRT_BASE + 7)
--#define KATANA_CODEC_FORMAT (KATANA_CODEC_VIRT_BASE + 8)
-+#define KATANA_CODEC_DOP (KATANA_CODEC_VIRT_BASE + 7)
-+#define KATANA_CODEC_FORMAT (KATANA_CODEC_VIRT_BASE + 8)
- #define KATANA_CODEC_COMMAND (KATANA_CODEC_VIRT_BASE + 9)
--#define KATANA_CODEC_MAX_REGISTER (KATANA_CODEC_VIRT_BASE + 9)
-+#define KATANA_CODEC_MUTE_STREAM (KATANA_CODEC_VIRT_BASE + 10)
-
--#define KATANA_CODEC_FMT 0xff
-+#define KATANA_CODEC_MAX_REGISTER (KATANA_CODEC_VIRT_BASE + 10)
-+
-+#define KATANA_CODEC_FMT 0xff
- #define KATANA_CODEC_CHAN_MONO 0x00
- #define KATANA_CODEC_CHAN_STEREO 0x80
- #define KATANA_CODEC_ALEN_16 0x10
-@@ -135,7 +137,8 @@ static const struct snd_kcontrol_new kat
- SOC_SINGLE("DoP Playback Switch", KATANA_CODEC_DOP, 0, 1, 1)
- };
-
--static bool katana_codec_readable_register(struct device *dev, unsigned int reg)
-+static bool katana_codec_readable_register(struct device *dev,
-+ unsigned int reg)
- {
- switch (reg) {
- case KATANA_CODEC_CHIP_ID_REG:
-@@ -150,13 +153,15 @@ static int katana_codec_hw_params(struct
- struct snd_soc_dai *dai)
- {
- struct snd_soc_component *component = dai->component;
-- struct katana_codec_priv *katana_codec = snd_soc_component_get_drvdata(component);
-+ struct katana_codec_priv *katana_codec =
-+ snd_soc_component_get_drvdata(component);
- int fmt = 0;
- int ret;
-
-- dev_dbg(component->card->dev, "hw_params %u Hz, %u channels\n",
-+ dev_dbg(component->card->dev, "hw_params %u Hz, %u channels, %u bits\n",
- params_rate(params),
-- params_channels(params));
-+ params_channels(params),
-+ params_width(params));
-
- switch (katana_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBM_CFM: // master
-@@ -212,13 +217,17 @@ static int katana_codec_hw_params(struct
- return -EINVAL;
- }
-
-- ret = regmap_write(katana_codec->regmap, KATANA_CODEC_FORMAT, fmt);
-+ ret = regmap_write(katana_codec->regmap, KATANA_CODEC_FORMAT,
-+ fmt);
- if (ret != 0) {
- dev_err(component->card->dev, "Failed to set format: %d\n", ret);
- return ret;
- }
- break;
-
-+ case SND_SOC_DAIFMT_CBS_CFS:
-+ break;
-+
- default:
- return -EINVAL;
- }
-@@ -229,14 +238,33 @@ static int katana_codec_hw_params(struct
- static int katana_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
- {
- struct snd_soc_component *component = dai->component;
-- struct katana_codec_priv *katana_codec = snd_soc_component_get_drvdata(component);
-+ struct katana_codec_priv *katana_codec =
-+ snd_soc_component_get_drvdata(component);
-
- katana_codec->fmt = fmt;
-
- return 0;
- }
-
-+int katana_codec_dai_mute_stream(struct snd_soc_dai *dai, int mute,
-+ int stream)
-+{
-+ struct snd_soc_component *component = dai->component;
-+ struct katana_codec_priv *katana_codec =
-+ snd_soc_component_get_drvdata(component);
-+ int ret = 0;
-+
-+ ret = regmap_write(katana_codec->regmap, KATANA_CODEC_MUTE_STREAM,
-+ mute);
-+ if (ret != 0) {
-+ dev_err(component->card->dev, "Failed to set mute: %d\n", ret);
-+ return ret;
-+ }
-+ return ret;
-+}
-+
- static const struct snd_soc_dai_ops katana_codec_dai_ops = {
-+ .mute_stream = katana_codec_dai_mute_stream,
- .hw_params = katana_codec_hw_params,
- .set_fmt = katana_codec_set_fmt,
- };
-@@ -300,7 +328,7 @@ static int allo_katana_component_probe(s
- return PTR_ERR(regmap);
-
- katana_codec = devm_kzalloc(dev, sizeof(struct katana_codec_priv),
-- GFP_KERNEL);
-+ GFP_KERNEL);
- if (!katana_codec)
- return -ENOMEM;
-
-@@ -348,8 +376,8 @@ static struct i2c_driver allo_katana_com
- .remove = allo_katana_component_remove,
- .id_table = allo_katana_component_id,
- .driver = {
-- .name = "allo-katana-codec",
-- .of_match_table = allo_katana_codec_of_match,
-+ .name = "allo-katana-codec",
-+ .of_match_table = allo_katana_codec_of_match,
- },
- };
-
--- /dev/null
+From 619a09baf2013206075d950ed54093b5573c0886 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 8 Mar 2019 10:38:59 +0000
+Subject: [PATCH 370/725] staging: vc_sm_cma: Remove erroneous misc_deregister
+
+Code from the misc /dev node was still present in
+bcm2835_vc_sm_cma_remove, which caused a NULL deref.
+Remove it.
+
+See #2885.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -25,7 +25,6 @@
+ #include <linux/fs.h>
+ #include <linux/kernel.h>
+ #include <linux/list.h>
+-#include <linux/miscdevice.h>
+ #include <linux/module.h>
+ #include <linux/mm.h>
+ #include <linux/of_device.h>
+@@ -72,7 +71,6 @@ struct sm_pde_t {
+ struct sm_state_t {
+ struct platform_device *pdev;
+
+- struct miscdevice dev;
+ struct sm_instance *sm_handle; /* Handle for videocore service. */
+
+ spinlock_t kernelid_map_lock; /* Spinlock protecting kernelid_map */
+@@ -758,9 +756,6 @@ static int bcm2835_vc_sm_cma_remove(stru
+ {
+ pr_debug("[%s]: start\n", __func__);
+ if (sm_inited) {
+- /* Remove shared memory device. */
+- misc_deregister(&sm_state->dev);
+-
+ /* Remove all proc entries. */
+ //debugfs_remove_recursive(sm_state->dir_root);
+
+++ /dev/null
-From 9fc96f927bdcefe90e8646c23c6eea65b07e72ab Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 5 Mar 2019 09:51:22 +0000
-Subject: [PATCH 371/703] lan78xx: EEE support is now a PHY property
-
-Now that EEE support is a property of the PHY, use the PHY's DT node
-when querying the EEE-related properties.
-
-See: https://github.com/raspberrypi/linux/issues/2882
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/net/usb/lan78xx.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/usb/lan78xx.c
-+++ b/drivers/net/usb/lan78xx.c
-@@ -2191,7 +2191,7 @@ static int lan78xx_phy_init(struct lan78
- mii_adv = (u32)mii_advertise_flowctrl(dev->fc_request_control);
- phydev->advertising |= mii_adv_to_ethtool_adv_t(mii_adv);
-
-- if (of_property_read_bool(dev->udev->dev.of_node,
-+ if (of_property_read_bool(phydev->mdio.dev.of_node,
- "microchip,eee-enabled")) {
- struct ethtool_eee edata;
- memset(&edata, 0, sizeof(edata));
--- /dev/null
+From b099a5f2e10c96955495398cf0605dde36b96a77 Mon Sep 17 00:00:00 2001
+From: Kieran Bingham <kieran.bingham@ideasonboard.com>
+Date: Mon, 18 Mar 2019 17:14:51 +0000
+Subject: [PATCH 371/725] vcsm: Fix makefile include on out-of-tree builds
+
+The vc_sm module tries to include the 'fs' directory from the
+$(srctree). $(srctree) is already provided by the build system, and
+causes the include path to be duplicated.
+
+With -Werror this fails to compile.
+
+Remove the unnecessary variable.
+
+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
+---
+ drivers/char/broadcom/vc_sm/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/char/broadcom/vc_sm/Makefile
++++ b/drivers/char/broadcom/vc_sm/Makefile
+@@ -1,5 +1,5 @@
+ ccflags-$(CONFIG_BCM_VC_SM) += -Werror -Wall -Wstrict-prototypes -Wno-trigraphs -O2
+-ccflags-$(CONFIG_BCM_VC_SM) += -I"drivers/staging/vc04_services" -I"drivers/staging/vc04_services/interface/vchi" -I"drivers/staging/vc04_services/interface/vchiq_arm" -I"$(srctree)/fs/"
++ccflags-$(CONFIG_BCM_VC_SM) += -I"drivers/staging/vc04_services" -I"drivers/staging/vc04_services/interface/vchi" -I"drivers/staging/vc04_services/interface/vchiq_arm" -I"fs"
+ ccflags-$(CONFIG_BCM_VC_SM) += -DOS_ASSERT_FAILURE -D__STDC_VERSION=199901L -D__STDC_VERSION__=199901L -D__VCCOREVER__=0 -D__KERNEL__ -D__linux__
+
+ obj-$(CONFIG_BCM_VC_SM) := vc-sm.o
--- /dev/null
+From 43825a3d741e4c4f4c010349ad59a437cc8de9a8 Mon Sep 17 00:00:00 2001
+From: Kieran Bingham <kieran.bingham@ideasonboard.com>
+Date: Mon, 18 Mar 2019 17:16:41 +0000
+Subject: [PATCH 372/725] vcsm: Remove set but unused variable
+
+The 'success' variable is set by the call to vchi_service_close() but never checked.
+Remove it, keeping the call in place.
+
+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
+---
+ drivers/char/broadcom/vc_sm/vc_vchi_sm.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
++++ b/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
+@@ -361,11 +361,9 @@ int vc_vchi_sm_stop(struct sm_instance *
+
+ /* Close all VCHI service connections */
+ for (i = 0; i < instance->num_connections; i++) {
+- int32_t success;
+-
+ vchi_service_use(instance->vchi_handle[i]);
+
+- success = vchi_service_close(instance->vchi_handle[i]);
++ vchi_service_close(instance->vchi_handle[i]);
+ }
+
+ kfree(instance);
+++ /dev/null
-From 7e709c572681a79ed9f906ceeb01a9cc8ca77049 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 27 Feb 2019 17:30:33 +0000
-Subject: [PATCH 372/703] video: bcm2708_fb: Try allocating on the ARM and
- passing to VPU
-
-Currently the VPU allocates the contiguous buffer for the
-framebuffer.
-Try an alternate path first where we use dma_alloc_coherent
-and pass the buffer to the VPU. Should the VPU firmware not
-support that path, then free the buffer and revert to the
-old behaviour of using the VPU allocation.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/video/fbdev/bcm2708_fb.c | 102 ++++++++++++++++++---
- include/soc/bcm2835/raspberrypi-firmware.h | 1 +
- 2 files changed, 91 insertions(+), 12 deletions(-)
-
---- a/drivers/video/fbdev/bcm2708_fb.c
-+++ b/drivers/video/fbdev/bcm2708_fb.c
-@@ -98,6 +98,11 @@ struct bcm2708_fb {
- struct bcm2708_fb_stats stats;
- unsigned long fb_bus_address;
- struct { u32 base, length; } gpu;
-+
-+ bool disable_arm_alloc;
-+ unsigned int image_size;
-+ dma_addr_t dma_addr;
-+ void *cpuaddr;
- };
-
- #define to_bcm2708(info) container_of(info, struct bcm2708_fb, fb)
-@@ -283,23 +288,88 @@ static int bcm2708_fb_set_par(struct fb_
- .xoffset = info->var.xoffset,
- .yoffset = info->var.yoffset,
- .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
-- .base = 0,
-- .screen_size = 0,
-- .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
-- .pitch = 0,
-+ /* base and screen_size will be initialised later */
-+ .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
-+ /* pitch will be initialised later */
- };
-- int ret;
-+ int ret, image_size;
-+
-
- print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
- info->var.xres, info->var.yres, info->var.xres_virtual,
- info->var.yres_virtual, (int)info->screen_size,
- info->var.bits_per_pixel);
-
-- ret = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo));
-+ /* Try allocating our own buffer. We can specify all the parameters */
-+ image_size = ((info->var.xres * info->var.yres) *
-+ info->var.bits_per_pixel) >> 3;
-+
-+ if (!fb->disable_arm_alloc &&
-+ (image_size != fb->image_size || !fb->dma_addr)) {
-+ if (fb->dma_addr) {
-+ dma_free_coherent(info->device, fb->image_size,
-+ fb->cpuaddr, fb->dma_addr);
-+ fb->image_size = 0;
-+ fb->cpuaddr = NULL;
-+ fb->dma_addr = 0;
-+ }
-+
-+ fb->cpuaddr = dma_alloc_coherent(info->device, image_size,
-+ &fb->dma_addr, GFP_KERNEL);
-+
-+ if (!fb->cpuaddr) {
-+ fb->dma_addr = 0;
-+ fb->disable_arm_alloc = true;
-+ } else {
-+ fb->image_size = image_size;
-+ }
-+ }
-+
-+ if (fb->cpuaddr) {
-+ fbinfo.base = fb->dma_addr;
-+ fbinfo.screen_size = image_size;
-+ fbinfo.pitch = (info->var.xres * info->var.bits_per_pixel) >> 3;
-+
-+ ret = rpi_firmware_property_list(fb->fw, &fbinfo,
-+ sizeof(fbinfo));
-+ if (ret || fbinfo.base != fb->dma_addr) {
-+ /* Firmware either failed, or assigned a different base
-+ * address (ie it doesn't support being passed an FB
-+ * allocation).
-+ * Destroy the allocation, and don't try again.
-+ */
-+ dma_free_coherent(info->device, fb->image_size,
-+ fb->cpuaddr, fb->dma_addr);
-+ fb->image_size = 0;
-+ fb->cpuaddr = NULL;
-+ fb->dma_addr = 0;
-+ fb->disable_arm_alloc = true;
-+ }
-+ } else {
-+ /* Our allocation failed - drop into the old scheme of
-+ * allocation by the VPU.
-+ */
-+ ret = -ENOMEM;
-+ }
-+
- if (ret) {
-- dev_err(info->device,
-- "Failed to allocate GPU framebuffer (%d)\n", ret);
-- return ret;
-+ /* Old scheme:
-+ * - FRAMEBUFFER_ALLOCATE passes 0 for base and screen_size.
-+ * - GET_PITCH instead of SET_PITCH.
-+ */
-+ fbinfo.base = 0;
-+ fbinfo.screen_size = 0;
-+ fbinfo.tag6.tag = RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH;
-+ fbinfo.pitch = 0;
-+
-+ ret = rpi_firmware_property_list(fb->fw, &fbinfo,
-+ sizeof(fbinfo));
-+ if (ret) {
-+ dev_err(info->device,
-+ "Failed to allocate GPU framebuffer (%d)\n",
-+ ret);
-+ return ret;
-+ }
- }
-
- if (info->var.bits_per_pixel <= 8)
-@@ -314,9 +384,17 @@ static int bcm2708_fb_set_par(struct fb_
- fb->fb.fix.smem_start = fbinfo.base;
- fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual;
- fb->fb.screen_size = fbinfo.screen_size;
-- if (fb->fb.screen_base)
-- iounmap(fb->fb.screen_base);
-- fb->fb.screen_base = ioremap_wc(fbinfo.base, fb->fb.screen_size);
-+
-+ if (!fb->dma_addr) {
-+ if (fb->fb.screen_base)
-+ iounmap(fb->fb.screen_base);
-+
-+ fb->fb.screen_base = ioremap_wc(fbinfo.base,
-+ fb->fb.screen_size);
-+ } else {
-+ fb->fb.screen_base = fb->cpuaddr;
-+ }
-+
- if (!fb->fb.screen_base) {
- /* the console may currently be locked */
- console_trylock();
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -128,6 +128,7 @@ enum rpi_firmware_property_tag {
- RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
- RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
- RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
-+ RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH = 0x00048008,
- RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
- RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
- RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
+++ /dev/null
-From d5fc03cec741a893fd37150f3fecef0cbb6ecb19 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 8 Mar 2019 10:38:59 +0000
-Subject: [PATCH 373/703] staging: vc_sm_cma: Remove erroneous misc_deregister
-
-Code from the misc /dev node was still present in
-bcm2835_vc_sm_cma_remove, which caused a NULL deref.
-Remove it.
-
-See #2885.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 5 -----
- 1 file changed, 5 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -25,7 +25,6 @@
- #include <linux/fs.h>
- #include <linux/kernel.h>
- #include <linux/list.h>
--#include <linux/miscdevice.h>
- #include <linux/module.h>
- #include <linux/mm.h>
- #include <linux/of_device.h>
-@@ -72,7 +71,6 @@ struct sm_pde_t {
- struct sm_state_t {
- struct platform_device *pdev;
-
-- struct miscdevice dev;
- struct sm_instance *sm_handle; /* Handle for videocore service. */
-
- spinlock_t kernelid_map_lock; /* Spinlock protecting kernelid_map */
-@@ -758,9 +756,6 @@ static int bcm2835_vc_sm_cma_remove(stru
- {
- pr_debug("[%s]: start\n", __func__);
- if (sm_inited) {
-- /* Remove shared memory device. */
-- misc_deregister(&sm_state->dev);
--
- /* Remove all proc entries. */
- //debugfs_remove_recursive(sm_state->dir_root);
-
--- /dev/null
+From 6a0844db98dec3f03b6af8a91d0da108dadda602 Mon Sep 17 00:00:00 2001
+From: Kieran Bingham <kieran.bingham@ideasonboard.com>
+Date: Mon, 18 Mar 2019 17:17:40 +0000
+Subject: [PATCH 373/725] vcsm: Reduce scope of local functions
+
+The functions:
+
+ vc_vchi_sm_send_msg
+ vc_sm_ioctl_alloc
+ vc_sm_ioctl_alloc_share
+ vc_sm_ioctl_import_dmabuf
+
+Are declared without a prototype. They are not used outside of this
+module, thus - convert them to static functions.
+
+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
+---
+ drivers/char/broadcom/vc_sm/vc_vchi_sm.c | 2 +-
+ drivers/char/broadcom/vc_sm/vmcs_sm.c | 14 +++++++-------
+ 2 files changed, 8 insertions(+), 8 deletions(-)
+
+--- a/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
++++ b/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
+@@ -375,7 +375,7 @@ lock:
+ return -EINVAL;
+ }
+
+-int vc_vchi_sm_send_msg(struct sm_instance *handle,
++static int vc_vchi_sm_send_msg(struct sm_instance *handle,
+ enum vc_sm_msg_type msg_id,
+ void *msg, uint32_t msg_size,
+ void *result, uint32_t result_size,
+--- a/drivers/char/broadcom/vc_sm/vmcs_sm.c
++++ b/drivers/char/broadcom/vc_sm/vmcs_sm.c
+@@ -1574,8 +1574,8 @@ error:
+ }
+
+ /* Allocate a shared memory handle and block. */
+-int vc_sm_ioctl_alloc(struct sm_priv_data_t *private,
+- struct vmcs_sm_ioctl_alloc *ioparam)
++static int vc_sm_ioctl_alloc(struct sm_priv_data_t *private,
++ struct vmcs_sm_ioctl_alloc *ioparam)
+ {
+ int ret = 0;
+ int status;
+@@ -1685,8 +1685,8 @@ error:
+ }
+
+ /* Share an allocate memory handle and block.*/
+-int vc_sm_ioctl_alloc_share(struct sm_priv_data_t *private,
+- struct vmcs_sm_ioctl_alloc_share *ioparam)
++static int vc_sm_ioctl_alloc_share(struct sm_priv_data_t *private,
++ struct vmcs_sm_ioctl_alloc_share *ioparam)
+ {
+ struct sm_resource_t *resource, *shared_resource;
+ int ret = 0;
+@@ -2200,9 +2200,9 @@ error:
+ }
+
+ /* Import a contiguous block of memory to be shared with VC. */
+-int vc_sm_ioctl_import_dmabuf(struct sm_priv_data_t *private,
+- struct vmcs_sm_ioctl_import_dmabuf *ioparam,
+- struct dma_buf *src_dma_buf)
++static int vc_sm_ioctl_import_dmabuf(struct sm_priv_data_t *private,
++ struct vmcs_sm_ioctl_import_dmabuf *ioparam,
++ struct dma_buf *src_dma_buf)
+ {
+ int ret = 0;
+ int status;
--- /dev/null
+From 4bf51ec794b95f976557ecafbc278bc00952fc32 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 19 Mar 2019 17:55:09 +0000
+Subject: [PATCH 374/725] staging: bcm2835-codec: NULL component handle on
+ queue_setup failure
+
+queue_setup tries creating the relevant MMAL component and configures
+the input and output ports as we're expecting to start streaming.
+If the port configuration failed then it destroyed the component,
+but failed to clear the component handle, therefore release tried
+destroying the component again.
+Adds some logging should the port config fail as well.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -1776,13 +1776,21 @@ static int bcm2835_codec_create_componen
+
+ ret = vchiq_mmal_port_set_format(dev->instance,
+ &ctx->component->input[0]);
+- if (ret < 0)
++ if (ret < 0) {
++ v4l2_dbg(1, debug, &dev->v4l2_dev,
++ "%s: vchiq_mmal_port_set_format ip port failed\n",
++ __func__);
+ goto destroy_component;
++ }
+
+ ret = vchiq_mmal_port_set_format(dev->instance,
+ &ctx->component->output[0]);
+- if (ret < 0)
++ if (ret < 0) {
++ v4l2_dbg(1, debug, &dev->v4l2_dev,
++ "%s: vchiq_mmal_port_set_format op port failed\n",
++ __func__);
+ goto destroy_component;
++ }
+
+ if (dev->role == ENCODE) {
+ u32 param = 1;
+@@ -1812,11 +1820,14 @@ static int bcm2835_codec_create_componen
+ ctx->q_data[V4L2_M2M_DST].sizeimage,
+ ctx->component->output[0].minimum_buffer.size);
+ }
++ v4l2_dbg(2, debug, &dev->v4l2_dev, "%s: component created as %s\n",
++ __func__, components[dev->role]);
+
+ return 0;
+
+ destroy_component:
+ vchiq_mmal_component_finalise(ctx->dev->instance, ctx->component);
++ ctx->component = NULL;
+
+ return ret;
+ }
+++ /dev/null
-From 902c22fdf3bf32f26412cef747bc7d657abcf194 Mon Sep 17 00:00:00 2001
-From: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Date: Mon, 18 Mar 2019 17:14:51 +0000
-Subject: [PATCH 374/703] vcsm: Fix makefile include on out-of-tree builds
-
-The vc_sm module tries to include the 'fs' directory from the
-$(srctree). $(srctree) is already provided by the build system, and
-causes the include path to be duplicated.
-
-With -Werror this fails to compile.
-
-Remove the unnecessary variable.
-
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
----
- drivers/char/broadcom/vc_sm/Makefile | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/char/broadcom/vc_sm/Makefile
-+++ b/drivers/char/broadcom/vc_sm/Makefile
-@@ -1,5 +1,5 @@
- ccflags-$(CONFIG_BCM_VC_SM) += -Werror -Wall -Wstrict-prototypes -Wno-trigraphs -O2
--ccflags-$(CONFIG_BCM_VC_SM) += -I"drivers/staging/vc04_services" -I"drivers/staging/vc04_services/interface/vchi" -I"drivers/staging/vc04_services/interface/vchiq_arm" -I"$(srctree)/fs/"
-+ccflags-$(CONFIG_BCM_VC_SM) += -I"drivers/staging/vc04_services" -I"drivers/staging/vc04_services/interface/vchi" -I"drivers/staging/vc04_services/interface/vchiq_arm" -I"fs"
- ccflags-$(CONFIG_BCM_VC_SM) += -DOS_ASSERT_FAILURE -D__STDC_VERSION=199901L -D__STDC_VERSION__=199901L -D__VCCOREVER__=0 -D__KERNEL__ -D__linux__
-
- obj-$(CONFIG_BCM_VC_SM) := vc-sm.o
--- /dev/null
+From 5dad012904e526aea593b8d70788f22c91c33f19 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 8 Mar 2019 10:49:17 +0000
+Subject: [PATCH 375/725] staging: vc-sm-cma: Remove the debugfs directory on
+ remove
+
+Without removing that, reloading the driver fails.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -757,7 +757,7 @@ static int bcm2835_vc_sm_cma_remove(stru
+ pr_debug("[%s]: start\n", __func__);
+ if (sm_inited) {
+ /* Remove all proc entries. */
+- //debugfs_remove_recursive(sm_state->dir_root);
++ debugfs_remove_recursive(sm_state->dir_root);
+
+ /* Stop the videocore shared memory service. */
+ vc_sm_cma_vchi_stop(&sm_state->sm_handle);
+++ /dev/null
-From ea8f08311188a54cafb0ad39702c173ae7c2a3e3 Mon Sep 17 00:00:00 2001
-From: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Date: Mon, 18 Mar 2019 17:16:41 +0000
-Subject: [PATCH 375/703] vcsm: Remove set but unused variable
-
-The 'success' variable is set by the call to vchi_service_close() but never checked.
-Remove it, keeping the call in place.
-
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
----
- drivers/char/broadcom/vc_sm/vc_vchi_sm.c | 4 +---
- 1 file changed, 1 insertion(+), 3 deletions(-)
-
---- a/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
-+++ b/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
-@@ -361,11 +361,9 @@ int vc_vchi_sm_stop(struct sm_instance *
-
- /* Close all VCHI service connections */
- for (i = 0; i < instance->num_connections; i++) {
-- int32_t success;
--
- vchi_service_use(instance->vchi_handle[i]);
-
-- success = vchi_service_close(instance->vchi_handle[i]);
-+ vchi_service_close(instance->vchi_handle[i]);
- }
-
- kfree(instance);
--- /dev/null
+From 6c76990e7f308e56f1e11413f6bbf852963c2113 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 8 Mar 2019 11:06:41 +0000
+Subject: [PATCH 376/725] staging: vc-sm-cma: Use devm_ allocs for sm_state.
+
+Use managed allocations for sm_state, removing reliance on
+manual management.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -656,7 +656,7 @@ static void vc_sm_connected_init(void)
+ __func__, ret);
+
+ ret = -EIO;
+- goto err_free_mem;
++ goto err_failed;
+ }
+
+ ret = vchi_connect(NULL, 0, vchi_instance);
+@@ -665,7 +665,7 @@ static void vc_sm_connected_init(void)
+ __func__, ret);
+
+ ret = -EIO;
+- goto err_free_mem;
++ goto err_failed;
+ }
+
+ /* Initialize an instance of the shared memory service. */
+@@ -676,7 +676,7 @@ static void vc_sm_connected_init(void)
+ __func__);
+
+ ret = -EPERM;
+- goto err_free_mem;
++ goto err_failed;
+ }
+
+ /* Create a debug fs directory entry (root). */
+@@ -722,8 +722,7 @@ err_remove_shared_memory:
+ debugfs_remove_recursive(sm_state->dir_root);
+ err_stop_sm_service:
+ vc_sm_cma_vchi_stop(&sm_state->sm_handle);
+-err_free_mem:
+- kfree(sm_state);
++err_failed:
+ pr_info("[%s]: failed, ret %d\n", __func__, ret);
+ }
+
+@@ -732,7 +731,7 @@ static int bcm2835_vc_sm_cma_probe(struc
+ {
+ pr_info("%s: Videocore shared memory driver\n", __func__);
+
+- sm_state = kzalloc(sizeof(*sm_state), GFP_KERNEL);
++ sm_state = devm_kzalloc(&pdev->dev, sizeof(*sm_state), GFP_KERNEL);
+ if (!sm_state)
+ return -ENOMEM;
+ sm_state->pdev = pdev;
+@@ -766,7 +765,6 @@ static int bcm2835_vc_sm_cma_remove(stru
+
+ /* Free the memory for the state structure. */
+ mutex_destroy(&sm_state->map_lock);
+- kfree(sm_state);
+ }
+
+ pr_debug("[%s]: end\n", __func__);
+++ /dev/null
-From 84195d1efab9720f7d378cd4e01a57eb5b864a2e Mon Sep 17 00:00:00 2001
-From: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Date: Mon, 18 Mar 2019 17:17:40 +0000
-Subject: [PATCH 376/703] vcsm: Reduce scope of local functions
-
-The functions:
-
- vc_vchi_sm_send_msg
- vc_sm_ioctl_alloc
- vc_sm_ioctl_alloc_share
- vc_sm_ioctl_import_dmabuf
-
-Are declared without a prototype. They are not used outside of this
-module, thus - convert them to static functions.
-
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
----
- drivers/char/broadcom/vc_sm/vc_vchi_sm.c | 2 +-
- drivers/char/broadcom/vc_sm/vmcs_sm.c | 14 +++++++-------
- 2 files changed, 8 insertions(+), 8 deletions(-)
-
---- a/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
-+++ b/drivers/char/broadcom/vc_sm/vc_vchi_sm.c
-@@ -375,7 +375,7 @@ lock:
- return -EINVAL;
- }
-
--int vc_vchi_sm_send_msg(struct sm_instance *handle,
-+static int vc_vchi_sm_send_msg(struct sm_instance *handle,
- enum vc_sm_msg_type msg_id,
- void *msg, uint32_t msg_size,
- void *result, uint32_t result_size,
---- a/drivers/char/broadcom/vc_sm/vmcs_sm.c
-+++ b/drivers/char/broadcom/vc_sm/vmcs_sm.c
-@@ -1574,8 +1574,8 @@ error:
- }
-
- /* Allocate a shared memory handle and block. */
--int vc_sm_ioctl_alloc(struct sm_priv_data_t *private,
-- struct vmcs_sm_ioctl_alloc *ioparam)
-+static int vc_sm_ioctl_alloc(struct sm_priv_data_t *private,
-+ struct vmcs_sm_ioctl_alloc *ioparam)
- {
- int ret = 0;
- int status;
-@@ -1685,8 +1685,8 @@ error:
- }
-
- /* Share an allocate memory handle and block.*/
--int vc_sm_ioctl_alloc_share(struct sm_priv_data_t *private,
-- struct vmcs_sm_ioctl_alloc_share *ioparam)
-+static int vc_sm_ioctl_alloc_share(struct sm_priv_data_t *private,
-+ struct vmcs_sm_ioctl_alloc_share *ioparam)
- {
- struct sm_resource_t *resource, *shared_resource;
- int ret = 0;
-@@ -2200,9 +2200,9 @@ error:
- }
-
- /* Import a contiguous block of memory to be shared with VC. */
--int vc_sm_ioctl_import_dmabuf(struct sm_priv_data_t *private,
-- struct vmcs_sm_ioctl_import_dmabuf *ioparam,
-- struct dma_buf *src_dma_buf)
-+static int vc_sm_ioctl_import_dmabuf(struct sm_priv_data_t *private,
-+ struct vmcs_sm_ioctl_import_dmabuf *ioparam,
-+ struct dma_buf *src_dma_buf)
- {
- int ret = 0;
- int status;
+++ /dev/null
-From 521d98b25f82438027cb6b88bdbb76d552426aae Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 19 Mar 2019 17:55:09 +0000
-Subject: [PATCH 377/703] staging: bcm2835-codec: NULL component handle on
- queue_setup failure
-
-queue_setup tries creating the relevant MMAL component and configures
-the input and output ports as we're expecting to start streaming.
-If the port configuration failed then it destroyed the component,
-but failed to clear the component handle, therefore release tried
-destroying the component again.
-Adds some logging should the port config fail as well.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c | 15 +++++++++++++--
- 1 file changed, 13 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -1776,13 +1776,21 @@ static int bcm2835_codec_create_componen
-
- ret = vchiq_mmal_port_set_format(dev->instance,
- &ctx->component->input[0]);
-- if (ret < 0)
-+ if (ret < 0) {
-+ v4l2_dbg(1, debug, &dev->v4l2_dev,
-+ "%s: vchiq_mmal_port_set_format ip port failed\n",
-+ __func__);
- goto destroy_component;
-+ }
-
- ret = vchiq_mmal_port_set_format(dev->instance,
- &ctx->component->output[0]);
-- if (ret < 0)
-+ if (ret < 0) {
-+ v4l2_dbg(1, debug, &dev->v4l2_dev,
-+ "%s: vchiq_mmal_port_set_format op port failed\n",
-+ __func__);
- goto destroy_component;
-+ }
-
- if (dev->role == ENCODE) {
- u32 param = 1;
-@@ -1812,11 +1820,14 @@ static int bcm2835_codec_create_componen
- ctx->q_data[V4L2_M2M_DST].sizeimage,
- ctx->component->output[0].minimum_buffer.size);
- }
-+ v4l2_dbg(2, debug, &dev->v4l2_dev, "%s: component created as %s\n",
-+ __func__, components[dev->role]);
-
- return 0;
-
- destroy_component:
- vchiq_mmal_component_finalise(ctx->dev->instance, ctx->component);
-+ ctx->component = NULL;
-
- return ret;
- }
--- /dev/null
+From 0631e31c3eb8c6d7ca996cac1cb207d25c4cfa75 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 8 Mar 2019 11:09:49 +0000
+Subject: [PATCH 377/725] staging: vc-sm-cma: Don't fail if debugfs calls fail.
+
+Return codes from debugfs calls should never alter the
+flow of the main code.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 8 --------
+ 1 file changed, 8 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -681,13 +681,6 @@ static void vc_sm_connected_init(void)
+
+ /* Create a debug fs directory entry (root). */
+ sm_state->dir_root = debugfs_create_dir(VC_SM_DIR_ROOT_NAME, NULL);
+- if (!sm_state->dir_root) {
+- pr_err("[%s]: failed to create \'%s\' directory entry\n",
+- __func__, VC_SM_DIR_ROOT_NAME);
+-
+- ret = -EPERM;
+- goto err_stop_sm_service;
+- }
+
+ sm_state->dir_state.show = &vc_sm_cma_global_state_show;
+ sm_state->dir_state.dir_entry =
+@@ -720,7 +713,6 @@ static void vc_sm_connected_init(void)
+
+ err_remove_shared_memory:
+ debugfs_remove_recursive(sm_state->dir_root);
+-err_stop_sm_service:
+ vc_sm_cma_vchi_stop(&sm_state->sm_handle);
+ err_failed:
+ pr_info("[%s]: failed, ret %d\n", __func__, ret);
--- /dev/null
+From 00c129ebdf07e600f112197e62435aa6485a2e59 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 8 Mar 2019 11:11:46 +0000
+Subject: [PATCH 378/725] staging: vc-sm-cma: Ensure mutex and idr are
+ destroyed
+
+map_lock and kernelid_map are created in probe, but not released
+in release should the vcsm service not connect (eg running the
+cutdown firmware).
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -752,7 +752,9 @@ static int bcm2835_vc_sm_cma_remove(stru
+
+ /* Stop the videocore shared memory service. */
+ vc_sm_cma_vchi_stop(&sm_state->sm_handle);
++ }
+
++ if (sm_state) {
+ idr_destroy(&sm_state->kernelid_map);
+
+ /* Free the memory for the state structure. */
+++ /dev/null
-From efa4c15a8012b80f3c1a63d7b79bfbaf013bf404 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 8 Mar 2019 10:49:17 +0000
-Subject: [PATCH 378/703] staging: vc-sm-cma: Remove the debugfs directory on
- remove
-
-Without removing that, reloading the driver fails.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -757,7 +757,7 @@ static int bcm2835_vc_sm_cma_remove(stru
- pr_debug("[%s]: start\n", __func__);
- if (sm_inited) {
- /* Remove all proc entries. */
-- //debugfs_remove_recursive(sm_state->dir_root);
-+ debugfs_remove_recursive(sm_state->dir_root);
-
- /* Stop the videocore shared memory service. */
- vc_sm_cma_vchi_stop(&sm_state->sm_handle);
--- /dev/null
+From 3c6328c7e96f5422a772c1d07f04dbebdc99955b Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 8 Mar 2019 11:26:00 +0000
+Subject: [PATCH 379/725] staging: bcm2835_codec: Clean up logging on unloading
+ the driver
+
+The log line was missing a closing \n, so wasn't added to the
+log immediately.
+Adds the function of the V4L2 device that is being unregistered
+too.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -77,6 +77,12 @@ enum bcm2835_codec_role {
+ ISP,
+ };
+
++const static char *roles[] = {
++ "decode",
++ "encode",
++ "isp"
++};
++
+ static const char * const components[] = {
+ "ril.video_decode",
+ "ril.video_encode",
+@@ -2522,7 +2528,6 @@ static int bcm2835_codec_create(struct p
+ struct video_device *vfd;
+ int video_nr;
+ int ret;
+- const static char *roles[] = {"decode", "encode", "isp"};
+
+ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+@@ -2615,7 +2620,8 @@ static int bcm2835_codec_destroy(struct
+ if (!dev)
+ return -ENODEV;
+
+- v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
++ v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME ", %s\n",
++ roles[dev->role]);
+ v4l2_m2m_release(dev->m2m_dev);
+ video_unregister_device(&dev->vfd);
+ v4l2_device_unregister(&dev->v4l2_dev);
+++ /dev/null
-From 95d0b2763bc5b18a8e9f7dc2db1ff101364056ef Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 8 Mar 2019 11:06:41 +0000
-Subject: [PATCH 379/703] staging: vc-sm-cma: Use devm_ allocs for sm_state.
-
-Use managed allocations for sm_state, removing reliance on
-manual management.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 12 +++++-------
- 1 file changed, 5 insertions(+), 7 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -656,7 +656,7 @@ static void vc_sm_connected_init(void)
- __func__, ret);
-
- ret = -EIO;
-- goto err_free_mem;
-+ goto err_failed;
- }
-
- ret = vchi_connect(NULL, 0, vchi_instance);
-@@ -665,7 +665,7 @@ static void vc_sm_connected_init(void)
- __func__, ret);
-
- ret = -EIO;
-- goto err_free_mem;
-+ goto err_failed;
- }
-
- /* Initialize an instance of the shared memory service. */
-@@ -676,7 +676,7 @@ static void vc_sm_connected_init(void)
- __func__);
-
- ret = -EPERM;
-- goto err_free_mem;
-+ goto err_failed;
- }
-
- /* Create a debug fs directory entry (root). */
-@@ -722,8 +722,7 @@ err_remove_shared_memory:
- debugfs_remove_recursive(sm_state->dir_root);
- err_stop_sm_service:
- vc_sm_cma_vchi_stop(&sm_state->sm_handle);
--err_free_mem:
-- kfree(sm_state);
-+err_failed:
- pr_info("[%s]: failed, ret %d\n", __func__, ret);
- }
-
-@@ -732,7 +731,7 @@ static int bcm2835_vc_sm_cma_probe(struc
- {
- pr_info("%s: Videocore shared memory driver\n", __func__);
-
-- sm_state = kzalloc(sizeof(*sm_state), GFP_KERNEL);
-+ sm_state = devm_kzalloc(&pdev->dev, sizeof(*sm_state), GFP_KERNEL);
- if (!sm_state)
- return -ENOMEM;
- sm_state->pdev = pdev;
-@@ -766,7 +765,6 @@ static int bcm2835_vc_sm_cma_remove(stru
-
- /* Free the memory for the state structure. */
- mutex_destroy(&sm_state->map_lock);
-- kfree(sm_state);
- }
-
- pr_debug("[%s]: end\n", __func__);
--- /dev/null
+From cbdcfb234a1fff16c988f2c4660ac8a6755b63d8 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Thu, 7 Mar 2019 19:27:05 +0100
+Subject: [PATCH 380/725] configs: Enable MT76 USB wifi
+
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+---
+ arch/arm/configs/bcm2709_defconfig | 2 ++
+ arch/arm/configs/bcmrpi_defconfig | 2 ++
+ arch/arm64/configs/bcmrpi3_defconfig | 2 ++
+ 3 files changed, 6 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -526,6 +526,8 @@ CONFIG_LIBERTAS_THINFIRM_USB=m
+ CONFIG_MWIFIEX=m
+ CONFIG_MWIFIEX_SDIO=m
+ CONFIG_MT7601U=m
++CONFIG_MT76x0U=m
++CONFIG_MT76x2U=m
+ CONFIG_RT2X00=m
+ CONFIG_RT2500USB=m
+ CONFIG_RT73USB=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -520,6 +520,8 @@ CONFIG_LIBERTAS_THINFIRM_USB=m
+ CONFIG_MWIFIEX=m
+ CONFIG_MWIFIEX_SDIO=m
+ CONFIG_MT7601U=m
++CONFIG_MT76x0U=m
++CONFIG_MT76x2U=m
+ CONFIG_RT2X00=m
+ CONFIG_RT2500USB=m
+ CONFIG_RT73USB=m
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -512,6 +512,8 @@ CONFIG_LIBERTAS_THINFIRM_USB=m
+ CONFIG_MWIFIEX=m
+ CONFIG_MWIFIEX_SDIO=m
+ CONFIG_MT7601U=m
++CONFIG_MT76x0U=m
++CONFIG_MT76x2U=m
+ CONFIG_RT2X00=m
+ CONFIG_RT2500USB=m
+ CONFIG_RT73USB=m
+++ /dev/null
-From 367e360d68d9dfd7f1b213a47576139ffb6028c8 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 8 Mar 2019 11:09:49 +0000
-Subject: [PATCH 380/703] staging: vc-sm-cma: Don't fail if debugfs calls fail.
-
-Return codes from debugfs calls should never alter the
-flow of the main code.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 8 --------
- 1 file changed, 8 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -681,13 +681,6 @@ static void vc_sm_connected_init(void)
-
- /* Create a debug fs directory entry (root). */
- sm_state->dir_root = debugfs_create_dir(VC_SM_DIR_ROOT_NAME, NULL);
-- if (!sm_state->dir_root) {
-- pr_err("[%s]: failed to create \'%s\' directory entry\n",
-- __func__, VC_SM_DIR_ROOT_NAME);
--
-- ret = -EPERM;
-- goto err_stop_sm_service;
-- }
-
- sm_state->dir_state.show = &vc_sm_cma_global_state_show;
- sm_state->dir_state.dir_entry =
-@@ -720,7 +713,6 @@ static void vc_sm_connected_init(void)
-
- err_remove_shared_memory:
- debugfs_remove_recursive(sm_state->dir_root);
--err_stop_sm_service:
- vc_sm_cma_vchi_stop(&sm_state->sm_handle);
- err_failed:
- pr_info("[%s]: failed, ret %d\n", __func__, ret);
--- /dev/null
+From d107d70cd01d1cd93fe0c61d8c0fc0ff7a2fc064 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 13 Mar 2019 14:19:11 +0000
+Subject: [PATCH 381/725] bcm2835-sdhost: Allow for sg entries that cross pages
+
+The dma_complete handling code calculates a virtual address for a page
+then adds an offset, but if the offset is more than a page and HIGHMEM
+is in use then the summed address could be in an unmapped (or just
+incorrect) page.
+
+The upstream SDHOST driver allows for this possibility - copy the code
+that does so.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/mmc/host/bcm2835-sdhost.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/mmc/host/bcm2835-sdhost.c
++++ b/drivers/mmc/host/bcm2835-sdhost.c
+@@ -543,6 +543,11 @@ static void bcm2835_sdhost_dma_complete(
+ void *page;
+ u32 *buf;
+
++ if (host->drain_offset & PAGE_MASK) {
++ host->drain_page += host->drain_offset >> PAGE_SHIFT;
++ host->drain_offset &= ~PAGE_MASK;
++ }
++
+ page = kmap_atomic(host->drain_page);
+ buf = page + host->drain_offset;
+
+++ /dev/null
-From 47046caff7455c46f07b7fd816cdd23ab9801842 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 8 Mar 2019 11:11:46 +0000
-Subject: [PATCH 381/703] staging: vc-sm-cma: Ensure mutex and idr are
- destroyed
-
-map_lock and kernelid_map are created in probe, but not released
-in release should the vcsm service not connect (eg running the
-cutdown firmware).
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -752,7 +752,9 @@ static int bcm2835_vc_sm_cma_remove(stru
-
- /* Stop the videocore shared memory service. */
- vc_sm_cma_vchi_stop(&sm_state->sm_handle);
-+ }
-
-+ if (sm_state) {
- idr_destroy(&sm_state->kernelid_map);
-
- /* Free the memory for the state structure. */
--- /dev/null
+From 71b44014034d34752cc9dcd23b364da15e059b54 Mon Sep 17 00:00:00 2001
+From: Adrien RICCIARDI <RICCIARDI-Adrien@users.noreply.github.com>
+Date: Fri, 22 Mar 2019 11:35:30 +0100
+Subject: [PATCH 382/725] overlays: sdio: Added 4-bit support on GPIOs 34-39.
+ (#2903)
+
+---
+ arch/arm/boot/dts/overlays/README | 3 +++
+ arch/arm/boot/dts/overlays/sdio-overlay.dts | 9 +++++++++
+ 2 files changed, 12 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1785,6 +1785,9 @@ Params: sdio_overclock SDIO Clo
+ gpios_34_37 Select GPIOs 34-37 for 1-bit mode. Must be used
+ with bus_width=1.
+
++ gpios_34_39 Select GPIOs 34-39 for 4-bit mode. Must be used
++ with bus_width=4 (the default).
++
+
+ Name: sdio-1bit
+ Info: This overlay is now deprecated. Use
+--- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
+@@ -64,6 +64,14 @@
+ };
+ };
+
++ fragment@5 {
++ target = <&sdio_ovl_pins>;
++ __dormant__ {
++ brcm,pins = <34 35 36 37 38 39>;
++ brcm,pull = <0 2 2 2 2 2>;
++ };
++ };
++
+ fragment@6 {
+ target-path = "/aliases";
+ __overlay__ {
+@@ -77,5 +85,6 @@
+ sdio_overclock = <&sdio_ovl>,"brcm,overclock-50:0";
+ gpios_22_25 = <0>,"=3";
+ gpios_34_37 = <0>,"=4";
++ gpios_34_39 = <0>,"=5";
+ };
+ };
+++ /dev/null
-From 7b588426000023ff56672cb1e2811e382cb49032 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 8 Mar 2019 11:26:00 +0000
-Subject: [PATCH 382/703] staging: bcm2835_codec: Clean up logging on unloading
- the driver
-
-The log line was missing a closing \n, so wasn't added to the
-log immediately.
-Adds the function of the V4L2 device that is being unregistered
-too.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -77,6 +77,12 @@ enum bcm2835_codec_role {
- ISP,
- };
-
-+const static char *roles[] = {
-+ "decode",
-+ "encode",
-+ "isp"
-+};
-+
- static const char * const components[] = {
- "ril.video_decode",
- "ril.video_encode",
-@@ -2522,7 +2528,6 @@ static int bcm2835_codec_create(struct p
- struct video_device *vfd;
- int video_nr;
- int ret;
-- const static char *roles[] = {"decode", "encode", "isp"};
-
- dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
- if (!dev)
-@@ -2615,7 +2620,8 @@ static int bcm2835_codec_destroy(struct
- if (!dev)
- return -ENODEV;
-
-- v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
-+ v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME ", %s\n",
-+ roles[dev->role]);
- v4l2_m2m_release(dev->m2m_dev);
- video_unregister_device(&dev->vfd);
- v4l2_device_unregister(&dev->v4l2_dev);
+++ /dev/null
-From 942452eb02558e142288e4e9476281d5a5554cb2 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Thu, 7 Mar 2019 19:27:05 +0100
-Subject: [PATCH 383/703] configs: Enable MT76 USB wifi
-
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
----
- arch/arm/configs/bcm2709_defconfig | 2 ++
- arch/arm/configs/bcmrpi_defconfig | 2 ++
- arch/arm64/configs/bcmrpi3_defconfig | 2 ++
- 3 files changed, 6 insertions(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -526,6 +526,8 @@ CONFIG_LIBERTAS_THINFIRM_USB=m
- CONFIG_MWIFIEX=m
- CONFIG_MWIFIEX_SDIO=m
- CONFIG_MT7601U=m
-+CONFIG_MT76x0U=m
-+CONFIG_MT76x2U=m
- CONFIG_RT2X00=m
- CONFIG_RT2500USB=m
- CONFIG_RT73USB=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -520,6 +520,8 @@ CONFIG_LIBERTAS_THINFIRM_USB=m
- CONFIG_MWIFIEX=m
- CONFIG_MWIFIEX_SDIO=m
- CONFIG_MT7601U=m
-+CONFIG_MT76x0U=m
-+CONFIG_MT76x2U=m
- CONFIG_RT2X00=m
- CONFIG_RT2500USB=m
- CONFIG_RT73USB=m
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -512,6 +512,8 @@ CONFIG_LIBERTAS_THINFIRM_USB=m
- CONFIG_MWIFIEX=m
- CONFIG_MWIFIEX_SDIO=m
- CONFIG_MT7601U=m
-+CONFIG_MT76x0U=m
-+CONFIG_MT76x2U=m
- CONFIG_RT2X00=m
- CONFIG_RT2500USB=m
- CONFIG_RT73USB=m
--- /dev/null
+From 94090199a0033419d35c90cd23ff9450f77b19e8 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 22 Mar 2019 16:44:47 +0000
+Subject: [PATCH 383/725] overlays: Fix multiple-instantiation of sc16is7xx*
+
+The registration of the fixed clocks uses the node name as the clock
+name, causing a clash if two clock nodes have the same name, regardless
+of the path to the node. Fix the issue by overwriting the clock node
+names using the value of the "addr" parameter, providing a crude
+disambiguation. (A bit of string pasting to form "sc16is752_clk_<addr>"
+would have been nice, but that is outside the abilities of the overlay
+parameter mechanism.)
+
+Also give the sc16is750-i2c overlay the xtal parameter for symmetry.
+
+See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=235650
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README | 1 +
+ arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts | 3 ++-
+ arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts | 2 +-
+ 3 files changed, 4 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1725,6 +1725,7 @@ Info: Overlay for the NXP SC16IS750 UA
+ Load: dtoverlay=sc16is750-i2c,<param>=<val>
+ Params: int_pin GPIO used for IRQ (default 24)
+ addr Address (default 0x48)
++ xtal On-board crystal frequency (default 14745600)
+
+
+ Name: sc16is752-i2c
+--- a/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
+@@ -31,7 +31,8 @@
+
+ __overrides__ {
+ int_pin = <&sc16is750>,"interrupts:0";
+- addr = <&sc16is750>,"reg:0";
++ addr = <&sc16is750>,"reg:0",<&sc16is750_clk>,"name";
++ xtal = <&sc16is750>,"clock-frequency:0";
+ };
+
+ };
+--- a/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
+@@ -34,7 +34,7 @@
+
+ __overrides__ {
+ int_pin = <&sc16is752>,"interrupts:0";
+- addr = <&sc16is752>,"reg:0";
++ addr = <&sc16is752>,"reg:0",<&sc16is752_clk>,"name";
+ xtal = <&sc16is752>,"clock-frequency:0";
+ };
+ };
+++ /dev/null
-From 7d87e7c1dbf0be8015daec4ae7eb2a87147915d5 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 13 Mar 2019 14:19:11 +0000
-Subject: [PATCH 384/703] bcm2835-sdhost: Allow for sg entries that cross pages
-
-The dma_complete handling code calculates a virtual address for a page
-then adds an offset, but if the offset is more than a page and HIGHMEM
-is in use then the summed address could be in an unmapped (or just
-incorrect) page.
-
-The upstream SDHOST driver allows for this possibility - copy the code
-that does so.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/mmc/host/bcm2835-sdhost.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/drivers/mmc/host/bcm2835-sdhost.c
-+++ b/drivers/mmc/host/bcm2835-sdhost.c
-@@ -543,6 +543,11 @@ static void bcm2835_sdhost_dma_complete(
- void *page;
- u32 *buf;
-
-+ if (host->drain_offset & PAGE_MASK) {
-+ host->drain_page += host->drain_offset >> PAGE_SHIFT;
-+ host->drain_offset &= ~PAGE_MASK;
-+ }
-+
- page = kmap_atomic(host->drain_page);
- buf = page + host->drain_offset;
-
--- /dev/null
+From d5175a2f4c71f99a997aff9a1b441152896d34bd Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Sun, 24 Mar 2019 20:54:25 +0000
+Subject: [PATCH 384/725] configs: Re-enable CONFIG_NETFILTER_XT_MATCH_SOCKET
+
+A Kconfig change in 4.10 caused the xt_socket module to no-longer be
+included in Raspbian builds. Fix the defconfigs to re-enable it.
+
+See: https://github.com/raspberrypi/linux/issues/2905
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ 3 files changed, 3 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -186,6 +186,7 @@ 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
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -180,6 +180,7 @@ 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
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -181,6 +181,7 @@ 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
--- /dev/null
+From d41f9c275d6cded64675a2b97084e9fdba8484f3 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Wed, 16 Jan 2019 12:22:32 +0100
+Subject: [PATCH 385/725] bcm2835-mmc: Fix DMA channel leak
+
+The BCM2835 MMC host driver requests a DMA channel on probe but neglects
+to release the channel in the probe error path and on driver unbind.
+
+I'm seeing this happen on every boot of the Compute Module 3: On first
+driver probe, DMA channel 2 is allocated and then leaked with a "could
+not get clk, deferring probe" message. On second driver probe, channel 4
+is allocated.
+
+Fix it.
+
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Cc: Frank Pavlic <f.pavlic@kunbus.de>
+---
+ drivers/mmc/host/bcm2835-mmc.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/mmc/host/bcm2835-mmc.c
++++ b/drivers/mmc/host/bcm2835-mmc.c
+@@ -1503,6 +1503,8 @@ static int bcm2835_mmc_probe(struct plat
+
+ return 0;
+ err:
++ if (host->dma_chan_rxtx)
++ dma_release_channel(host->dma_chan_rxtx);
+ mmc_free_host(mmc);
+
+ return ret;
+@@ -1548,6 +1550,9 @@ static int bcm2835_mmc_remove(struct pla
+
+ tasklet_kill(&host->finish_tasklet);
+
++ if (host->dma_chan_rxtx)
++ dma_release_channel(host->dma_chan_rxtx);
++
+ mmc_free_host(host->mmc);
+ platform_set_drvdata(pdev, NULL);
+
+++ /dev/null
-From 693450014feff59f24614f8032e7e1b798d8694c Mon Sep 17 00:00:00 2001
-From: Adrien RICCIARDI <RICCIARDI-Adrien@users.noreply.github.com>
-Date: Fri, 22 Mar 2019 11:35:30 +0100
-Subject: [PATCH 385/703] overlays: sdio: Added 4-bit support on GPIOs 34-39.
- (#2903)
-
----
- arch/arm/boot/dts/overlays/README | 3 +++
- arch/arm/boot/dts/overlays/sdio-overlay.dts | 9 +++++++++
- 2 files changed, 12 insertions(+)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1785,6 +1785,9 @@ Params: sdio_overclock SDIO Clo
- gpios_34_37 Select GPIOs 34-37 for 1-bit mode. Must be used
- with bus_width=1.
-
-+ gpios_34_39 Select GPIOs 34-39 for 4-bit mode. Must be used
-+ with bus_width=4 (the default).
-+
-
- Name: sdio-1bit
- Info: This overlay is now deprecated. Use
---- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
-@@ -64,6 +64,14 @@
- };
- };
-
-+ fragment@5 {
-+ target = <&sdio_ovl_pins>;
-+ __dormant__ {
-+ brcm,pins = <34 35 36 37 38 39>;
-+ brcm,pull = <0 2 2 2 2 2>;
-+ };
-+ };
-+
- fragment@6 {
- target-path = "/aliases";
- __overlay__ {
-@@ -77,5 +85,6 @@
- sdio_overclock = <&sdio_ovl>,"brcm,overclock-50:0";
- gpios_22_25 = <0>,"=3";
- gpios_34_37 = <0>,"=4";
-+ gpios_34_39 = <0>,"=5";
- };
- };
--- /dev/null
+From 1a0d67591fc1b7a33e7769caaba13f9a08ca4f25 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Sat, 19 Jan 2019 08:06:48 +0100
+Subject: [PATCH 386/725] bcm2835-mmc: Fix struct mmc_host leak on probe
+
+The BCM2835 MMC host driver requests the bus address of the host's
+register map on probe. If that fails, the driver leaks the struct
+mmc_host allocated earlier.
+
+Fix it.
+
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Cc: Frank Pavlic <f.pavlic@kunbus.de>
+---
+ drivers/mmc/host/bcm2835-mmc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/mmc/host/bcm2835-mmc.c
++++ b/drivers/mmc/host/bcm2835-mmc.c
+@@ -1439,7 +1439,8 @@ static int bcm2835_mmc_probe(struct plat
+ addr = of_get_address(node, 0, NULL, NULL);
+ if (!addr) {
+ dev_err(dev, "could not get DMA-register address\n");
+- return -ENODEV;
++ ret = -ENODEV;
++ goto err;
+ }
+ host->bus_addr = be32_to_cpup(addr);
+ pr_debug(" - ioaddr %lx, iomem->start %lx, bus_addr %lx\n",
+++ /dev/null
-From 018329c19febff752bf09820eda6465748ae9c65 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 22 Mar 2019 16:44:47 +0000
-Subject: [PATCH 386/703] overlays: Fix multiple-instantiation of sc16is7xx*
-
-The registration of the fixed clocks uses the node name as the clock
-name, causing a clash if two clock nodes have the same name, regardless
-of the path to the node. Fix the issue by overwriting the clock node
-names using the value of the "addr" parameter, providing a crude
-disambiguation. (A bit of string pasting to form "sc16is752_clk_<addr>"
-would have been nice, but that is outside the abilities of the overlay
-parameter mechanism.)
-
-Also give the sc16is750-i2c overlay the xtal parameter for symmetry.
-
-See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=235650
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README | 1 +
- arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts | 3 ++-
- arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts | 2 +-
- 3 files changed, 4 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1725,6 +1725,7 @@ Info: Overlay for the NXP SC16IS750 UA
- Load: dtoverlay=sc16is750-i2c,<param>=<val>
- Params: int_pin GPIO used for IRQ (default 24)
- addr Address (default 0x48)
-+ xtal On-board crystal frequency (default 14745600)
-
-
- Name: sc16is752-i2c
---- a/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
-@@ -31,7 +31,8 @@
-
- __overrides__ {
- int_pin = <&sc16is750>,"interrupts:0";
-- addr = <&sc16is750>,"reg:0";
-+ addr = <&sc16is750>,"reg:0",<&sc16is750_clk>,"name";
-+ xtal = <&sc16is750>,"clock-frequency:0";
- };
-
- };
---- a/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
-@@ -34,7 +34,7 @@
-
- __overrides__ {
- int_pin = <&sc16is752>,"interrupts:0";
-- addr = <&sc16is752>,"reg:0";
-+ addr = <&sc16is752>,"reg:0",<&sc16is752_clk>,"name";
- xtal = <&sc16is752>,"clock-frequency:0";
- };
- };
--- /dev/null
+From 56b3d0e6446f081d0c3e8c52e651f8d45d488b45 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Sat, 19 Jan 2019 09:00:26 +0100
+Subject: [PATCH 387/725] bcm2835-mmc: Fix duplicate free_irq() on remove
+
+The BCM2835 MMC host driver requests its interrupt as a device-managed
+resource, so the interrupt is automatically freed after the driver is
+unbound.
+
+However on driver unbind, bcm2835_mmc_remove() frees the interrupt
+explicitly to avoid invocation of the interrupt handler after driver
+structures have been torn down.
+
+The interrupt is thus freed twice, leading to a WARN splat in
+__free_irq(). Fix by not requesting the interrupt as a device-managed
+resource.
+
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Cc: Frank Pavlic <f.pavlic@kunbus.de>
+---
+ drivers/mmc/host/bcm2835-mmc.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/mmc/host/bcm2835-mmc.c
++++ b/drivers/mmc/host/bcm2835-mmc.c
+@@ -1389,9 +1389,9 @@ static int bcm2835_mmc_add_host(struct b
+ init_waitqueue_head(&host->buf_ready_int);
+
+ bcm2835_mmc_init(host, 0);
+- ret = devm_request_threaded_irq(dev, host->irq, bcm2835_mmc_irq,
+- bcm2835_mmc_thread_irq, IRQF_SHARED,
+- mmc_hostname(mmc), host);
++ ret = request_threaded_irq(host->irq, bcm2835_mmc_irq,
++ bcm2835_mmc_thread_irq, IRQF_SHARED,
++ mmc_hostname(mmc), host);
+ if (ret) {
+ dev_err(dev, "Failed to request IRQ %d: %d\n", host->irq, ret);
+ goto untasklet;
+++ /dev/null
-From 59f78628ccd725312dd1ff24d1b0952fa8203ee2 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Sun, 24 Mar 2019 20:54:25 +0000
-Subject: [PATCH 387/703] configs: Re-enable CONFIG_NETFILTER_XT_MATCH_SOCKET
-
-A Kconfig change in 4.10 caused the xt_socket module to no-longer be
-included in Raspbian builds. Fix the defconfigs to re-enable it.
-
-See: https://github.com/raspberrypi/linux/issues/2905
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- 3 files changed, 3 insertions(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -186,6 +186,7 @@ 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
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -180,6 +180,7 @@ 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
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -181,6 +181,7 @@ 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
+++ /dev/null
-From 94a6414f6aaef2575eeb36149d65c79c13b85922 Mon Sep 17 00:00:00 2001
-From: Lukas Wunner <lukas@wunner.de>
-Date: Wed, 16 Jan 2019 12:22:32 +0100
-Subject: [PATCH 388/703] bcm2835-mmc: Fix DMA channel leak
-
-The BCM2835 MMC host driver requests a DMA channel on probe but neglects
-to release the channel in the probe error path and on driver unbind.
-
-I'm seeing this happen on every boot of the Compute Module 3: On first
-driver probe, DMA channel 2 is allocated and then leaked with a "could
-not get clk, deferring probe" message. On second driver probe, channel 4
-is allocated.
-
-Fix it.
-
-Signed-off-by: Lukas Wunner <lukas@wunner.de>
-Cc: Frank Pavlic <f.pavlic@kunbus.de>
----
- drivers/mmc/host/bcm2835-mmc.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/drivers/mmc/host/bcm2835-mmc.c
-+++ b/drivers/mmc/host/bcm2835-mmc.c
-@@ -1503,6 +1503,8 @@ static int bcm2835_mmc_probe(struct plat
-
- return 0;
- err:
-+ if (host->dma_chan_rxtx)
-+ dma_release_channel(host->dma_chan_rxtx);
- mmc_free_host(mmc);
-
- return ret;
-@@ -1548,6 +1550,9 @@ static int bcm2835_mmc_remove(struct pla
-
- tasklet_kill(&host->finish_tasklet);
-
-+ if (host->dma_chan_rxtx)
-+ dma_release_channel(host->dma_chan_rxtx);
-+
- mmc_free_host(host->mmc);
- platform_set_drvdata(pdev, NULL);
-
--- /dev/null
+From b4a62a0eae7852a4dde5f055bb89833ea80d554a Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Tue, 22 Jan 2019 12:29:45 +0100
+Subject: [PATCH 388/725] bcm2835-mmc: Handle mmc_add_host() errors
+
+The BCM2835 MMC host driver calls mmc_add_host() but doesn't check its
+return value. Errors occurring in that function are therefore not
+handled. Fix it.
+
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Cc: Frank Pavlic <f.pavlic@kunbus.de>
+---
+ drivers/mmc/host/bcm2835-mmc.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/mmc/host/bcm2835-mmc.c
++++ b/drivers/mmc/host/bcm2835-mmc.c
+@@ -1398,10 +1398,16 @@ static int bcm2835_mmc_add_host(struct b
+ }
+
+ mmiowb();
+- mmc_add_host(mmc);
++ ret = mmc_add_host(mmc);
++ if (ret) {
++ dev_err(dev, "could not add MMC host\n");
++ goto free_irq;
++ }
+
+ return 0;
+
++free_irq:
++ free_irq(host->irq, host);
+ untasklet:
+ tasklet_kill(&host->finish_tasklet);
+
--- /dev/null
+From 3f0851774265e0097e015672ee860983608c9b14 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Sat, 19 Jan 2019 08:42:40 +0100
+Subject: [PATCH 389/725] bcm2835-mmc: Deduplicate reset of driver data on
+ remove
+
+The BCM2835 MMC host driver sets the device's driver data pointer to
+NULL on ->remove() even though the driver core subsequently does the
+same in __device_release_driver(). Drop the duplicate assignment.
+
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Cc: Frank Pavlic <f.pavlic@kunbus.de>
+---
+ drivers/mmc/host/bcm2835-mmc.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/mmc/host/bcm2835-mmc.c
++++ b/drivers/mmc/host/bcm2835-mmc.c
+@@ -1561,7 +1561,6 @@ static int bcm2835_mmc_remove(struct pla
+ dma_release_channel(host->dma_chan_rxtx);
+
+ mmc_free_host(host->mmc);
+- platform_set_drvdata(pdev, NULL);
+
+ return 0;
+ }
+++ /dev/null
-From eaea13d958263b1fae8a96ffe184f91b0ca526cd Mon Sep 17 00:00:00 2001
-From: Lukas Wunner <lukas@wunner.de>
-Date: Sat, 19 Jan 2019 08:06:48 +0100
-Subject: [PATCH 389/703] bcm2835-mmc: Fix struct mmc_host leak on probe
-
-The BCM2835 MMC host driver requests the bus address of the host's
-register map on probe. If that fails, the driver leaks the struct
-mmc_host allocated earlier.
-
-Fix it.
-
-Signed-off-by: Lukas Wunner <lukas@wunner.de>
-Cc: Frank Pavlic <f.pavlic@kunbus.de>
----
- drivers/mmc/host/bcm2835-mmc.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/mmc/host/bcm2835-mmc.c
-+++ b/drivers/mmc/host/bcm2835-mmc.c
-@@ -1439,7 +1439,8 @@ static int bcm2835_mmc_probe(struct plat
- addr = of_get_address(node, 0, NULL, NULL);
- if (!addr) {
- dev_err(dev, "could not get DMA-register address\n");
-- return -ENODEV;
-+ ret = -ENODEV;
-+ goto err;
- }
- host->bus_addr = be32_to_cpup(addr);
- pr_debug(" - ioaddr %lx, iomem->start %lx, bus_addr %lx\n",
+++ /dev/null
-From d2ba7664d279bf06ad8ffc281cbefe29ddc180e7 Mon Sep 17 00:00:00 2001
-From: Lukas Wunner <lukas@wunner.de>
-Date: Sat, 19 Jan 2019 09:00:26 +0100
-Subject: [PATCH 390/703] bcm2835-mmc: Fix duplicate free_irq() on remove
-
-The BCM2835 MMC host driver requests its interrupt as a device-managed
-resource, so the interrupt is automatically freed after the driver is
-unbound.
-
-However on driver unbind, bcm2835_mmc_remove() frees the interrupt
-explicitly to avoid invocation of the interrupt handler after driver
-structures have been torn down.
-
-The interrupt is thus freed twice, leading to a WARN splat in
-__free_irq(). Fix by not requesting the interrupt as a device-managed
-resource.
-
-Signed-off-by: Lukas Wunner <lukas@wunner.de>
-Cc: Frank Pavlic <f.pavlic@kunbus.de>
----
- drivers/mmc/host/bcm2835-mmc.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/drivers/mmc/host/bcm2835-mmc.c
-+++ b/drivers/mmc/host/bcm2835-mmc.c
-@@ -1389,9 +1389,9 @@ static int bcm2835_mmc_add_host(struct b
- init_waitqueue_head(&host->buf_ready_int);
-
- bcm2835_mmc_init(host, 0);
-- ret = devm_request_threaded_irq(dev, host->irq, bcm2835_mmc_irq,
-- bcm2835_mmc_thread_irq, IRQF_SHARED,
-- mmc_hostname(mmc), host);
-+ ret = request_threaded_irq(host->irq, bcm2835_mmc_irq,
-+ bcm2835_mmc_thread_irq, IRQF_SHARED,
-+ mmc_hostname(mmc), host);
- if (ret) {
- dev_err(dev, "Failed to request IRQ %d: %d\n", host->irq, ret);
- goto untasklet;
--- /dev/null
+From a6d3c7bab1486b7d4b0b8b410c5267ed63894861 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 25 Mar 2019 17:54:05 +0000
+Subject: [PATCH 390/725] configs: Add CONFIG_BATTERY_MAX17040
+
+See: https://github.com/raspberrypi/linux/issues/2906
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ 3 files changed, 3 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -659,6 +659,7 @@ CONFIG_W1_SLAVE_DS28E04=m
+ CONFIG_POWER_RESET=y
+ CONFIG_POWER_RESET_GPIO=y
+ CONFIG_BATTERY_DS2760=m
++CONFIG_BATTERY_MAX17040=m
+ CONFIG_BATTERY_GAUGE_LTC2941=m
+ CONFIG_HWMON=m
+ CONFIG_SENSORS_DS1621=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -652,6 +652,7 @@ CONFIG_W1_SLAVE_DS28E04=m
+ CONFIG_POWER_RESET=y
+ CONFIG_POWER_RESET_GPIO=y
+ CONFIG_BATTERY_DS2760=m
++CONFIG_BATTERY_MAX17040=m
+ CONFIG_BATTERY_GAUGE_LTC2941=m
+ CONFIG_HWMON=m
+ CONFIG_SENSORS_DS1621=m
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -629,6 +629,7 @@ CONFIG_W1_SLAVE_DS2781=m
+ CONFIG_W1_SLAVE_DS28E04=m
+ CONFIG_POWER_RESET_GPIO=y
+ CONFIG_BATTERY_DS2760=m
++CONFIG_BATTERY_MAX17040=m
+ CONFIG_HWMON=m
+ CONFIG_SENSORS_LM75=m
+ CONFIG_SENSORS_SHT21=m
+++ /dev/null
-From 3c29f09811abafef65e431bc70a66ef78625c08a Mon Sep 17 00:00:00 2001
-From: Lukas Wunner <lukas@wunner.de>
-Date: Tue, 22 Jan 2019 12:29:45 +0100
-Subject: [PATCH 391/703] bcm2835-mmc: Handle mmc_add_host() errors
-
-The BCM2835 MMC host driver calls mmc_add_host() but doesn't check its
-return value. Errors occurring in that function are therefore not
-handled. Fix it.
-
-Signed-off-by: Lukas Wunner <lukas@wunner.de>
-Cc: Frank Pavlic <f.pavlic@kunbus.de>
----
- drivers/mmc/host/bcm2835-mmc.c | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
---- a/drivers/mmc/host/bcm2835-mmc.c
-+++ b/drivers/mmc/host/bcm2835-mmc.c
-@@ -1398,10 +1398,16 @@ static int bcm2835_mmc_add_host(struct b
- }
-
- mmiowb();
-- mmc_add_host(mmc);
-+ ret = mmc_add_host(mmc);
-+ if (ret) {
-+ dev_err(dev, "could not add MMC host\n");
-+ goto free_irq;
-+ }
-
- return 0;
-
-+free_irq:
-+ free_irq(host->irq, host);
- untasklet:
- tasklet_kill(&host->finish_tasklet);
-
--- /dev/null
+From a8034b01d807e4c393356d7b46183dd5d2b40df3 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 25 Mar 2019 18:03:48 +0000
+Subject: [PATCH 391/725] overlays: Add max17040 support to i2c-sensor
+
+See: https://github.com/raspberrypi/linux/issues/2906
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README | 3 +++
+ .../arm/boot/dts/overlays/i2c-sensor-overlay.dts | 16 ++++++++++++++++
+ 2 files changed, 19 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1030,6 +1030,9 @@ Params: addr Set the
+
+ lm75addr Deprecated - use addr parameter instead
+
++ max17040 Select the Maxim Integrated MAX17040 battery
++ monitor
++
+ sht3x Select the Sensiron SHT3x temperature and
+ humidity sensor. Valid addresses 0x44-0x45,
+ default 0x44
+--- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
+@@ -201,6 +201,21 @@
+ };
+ };
+
++ fragment@13 {
++ target = <&i2c_arm>;
++ __dormant__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ max17040: max17040@36 {
++ compatible = "maxim,max17040";
++ reg = <0x36>;
++ status = "okay";
++ };
++ };
++ };
++
+ __overrides__ {
+ addr = <&bme280>,"reg:0", <&bmp280>,"reg:0", <&tmp102>,"reg:0",
+ <&lm75>,"reg:0", <&hdc100x>,"reg:0", <&sht3x>,"reg:0",
+@@ -219,5 +234,6 @@
+ veml6070 = <0>,"+10";
+ sht3x = <0>,"+11";
+ ds1621 = <0>,"+12";
++ max17040 = <0>,"+13";
+ };
+ };
+++ /dev/null
-From 706fb772745fae3b0ea6a36830cc92eaf1c22606 Mon Sep 17 00:00:00 2001
-From: Lukas Wunner <lukas@wunner.de>
-Date: Sat, 19 Jan 2019 08:42:40 +0100
-Subject: [PATCH 392/703] bcm2835-mmc: Deduplicate reset of driver data on
- remove
-
-The BCM2835 MMC host driver sets the device's driver data pointer to
-NULL on ->remove() even though the driver core subsequently does the
-same in __device_release_driver(). Drop the duplicate assignment.
-
-Signed-off-by: Lukas Wunner <lukas@wunner.de>
-Cc: Frank Pavlic <f.pavlic@kunbus.de>
----
- drivers/mmc/host/bcm2835-mmc.c | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/drivers/mmc/host/bcm2835-mmc.c
-+++ b/drivers/mmc/host/bcm2835-mmc.c
-@@ -1561,7 +1561,6 @@ static int bcm2835_mmc_remove(struct pla
- dma_release_channel(host->dma_chan_rxtx);
-
- mmc_free_host(host->mmc);
-- platform_set_drvdata(pdev, NULL);
-
- return 0;
- }
--- /dev/null
+From 38bdf55c84e6f388db3dfb96d3c6617abcc10067 Mon Sep 17 00:00:00 2001
+From: P33M <P33M@users.noreply.github.com>
+Date: Tue, 26 Mar 2019 09:48:25 +0000
+Subject: [PATCH 392/725] defconfigs: disable memory and IO cgroups (#2908)
+
+Due to an upstream bug, memory is leaked in the inode cache when cgroups
+are enabled. Disable as this is causing crashes.
+
+See: https://github.com/raspberrypi/linux/issues/2829
+---
+ arch/arm/configs/bcm2709_defconfig | 4 ----
+ arch/arm/configs/bcmrpi_defconfig | 4 ----
+ arch/arm64/configs/bcmrpi3_defconfig | 4 ----
+ 3 files changed, 12 deletions(-)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -14,8 +14,6 @@ CONFIG_TASK_XACCT=y
+ CONFIG_TASK_IO_ACCOUNTING=y
+ CONFIG_IKCONFIG=m
+ CONFIG_IKCONFIG_PROC=y
+-CONFIG_MEMCG=y
+-CONFIG_BLK_CGROUP=y
+ CONFIG_CGROUP_FREEZER=y
+ CONFIG_CPUSETS=y
+ CONFIG_CGROUP_DEVICE=y
+@@ -64,10 +62,8 @@ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_MODULE_SRCVERSION_ALL=y
+-CONFIG_BLK_DEV_THROTTLING=y
+ CONFIG_PARTITION_ADVANCED=y
+ CONFIG_MAC_PARTITION=y
+-CONFIG_CFQ_GROUP_IOSCHED=y
+ CONFIG_BINFMT_MISC=m
+ CONFIG_CLEANCACHE=y
+ CONFIG_FRONTSWAP=y
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -13,8 +13,6 @@ CONFIG_TASK_XACCT=y
+ CONFIG_TASK_IO_ACCOUNTING=y
+ CONFIG_IKCONFIG=m
+ CONFIG_IKCONFIG_PROC=y
+-CONFIG_MEMCG=y
+-CONFIG_BLK_CGROUP=y
+ CONFIG_CGROUP_FREEZER=y
+ CONFIG_CGROUP_DEVICE=y
+ CONFIG_CGROUP_CPUACCT=y
+@@ -58,10 +56,8 @@ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_MODULE_SRCVERSION_ALL=y
+-CONFIG_BLK_DEV_THROTTLING=y
+ CONFIG_PARTITION_ADVANCED=y
+ CONFIG_MAC_PARTITION=y
+-CONFIG_CFQ_GROUP_IOSCHED=y
+ CONFIG_BINFMT_MISC=m
+ CONFIG_CLEANCACHE=y
+ CONFIG_FRONTSWAP=y
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -13,8 +13,6 @@ CONFIG_TASK_XACCT=y
+ CONFIG_TASK_IO_ACCOUNTING=y
+ CONFIG_IKCONFIG=m
+ CONFIG_IKCONFIG_PROC=y
+-CONFIG_MEMCG=y
+-CONFIG_BLK_CGROUP=y
+ CONFIG_CGROUP_FREEZER=y
+ CONFIG_CPUSETS=y
+ CONFIG_CGROUP_DEVICE=y
+@@ -62,10 +60,8 @@ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_MODULE_SRCVERSION_ALL=y
+-CONFIG_BLK_DEV_THROTTLING=y
+ CONFIG_PARTITION_ADVANCED=y
+ CONFIG_MAC_PARTITION=y
+-CONFIG_CFQ_GROUP_IOSCHED=y
+ CONFIG_BINFMT_MISC=y
+ CONFIG_CLEANCACHE=y
+ CONFIG_FRONTSWAP=y
+++ /dev/null
-From 034896f9b6faf8107788575990c2cec2a6ef964e Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 25 Mar 2019 17:54:05 +0000
-Subject: [PATCH 393/703] configs: Add CONFIG_BATTERY_MAX17040
-
-See: https://github.com/raspberrypi/linux/issues/2906
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- 3 files changed, 3 insertions(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -659,6 +659,7 @@ CONFIG_W1_SLAVE_DS28E04=m
- CONFIG_POWER_RESET=y
- CONFIG_POWER_RESET_GPIO=y
- CONFIG_BATTERY_DS2760=m
-+CONFIG_BATTERY_MAX17040=m
- CONFIG_BATTERY_GAUGE_LTC2941=m
- CONFIG_HWMON=m
- CONFIG_SENSORS_DS1621=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -652,6 +652,7 @@ CONFIG_W1_SLAVE_DS28E04=m
- CONFIG_POWER_RESET=y
- CONFIG_POWER_RESET_GPIO=y
- CONFIG_BATTERY_DS2760=m
-+CONFIG_BATTERY_MAX17040=m
- CONFIG_BATTERY_GAUGE_LTC2941=m
- CONFIG_HWMON=m
- CONFIG_SENSORS_DS1621=m
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -629,6 +629,7 @@ CONFIG_W1_SLAVE_DS2781=m
- CONFIG_W1_SLAVE_DS28E04=m
- CONFIG_POWER_RESET_GPIO=y
- CONFIG_BATTERY_DS2760=m
-+CONFIG_BATTERY_MAX17040=m
- CONFIG_HWMON=m
- CONFIG_SENSORS_LM75=m
- CONFIG_SENSORS_SHT21=m
--- /dev/null
+From 4ee5be44a136685a674ef2e3560e4062a26a2bfb Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 5 Mar 2019 15:43:27 +0000
+Subject: [PATCH 393/725] media: bcm2835-unicam: Add support for enum
+ framesizes and frameintervals
+
+vidioc_enum_framesizes and vidioc_enum_frameintervals weren't implemented,
+therefore clients couldn't enumerate the supported resolutions.
+
+Implement them by forwarding on to the sensor driver.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../media/platform/bcm2835/bcm2835-unicam.c | 94 +++++++++++++++++++
+ 1 file changed, 94 insertions(+)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -1406,6 +1406,84 @@ static int unicam_g_edid(struct file *fi
+ return v4l2_subdev_call(dev->sensor, pad, get_edid, edid);
+ }
+
++static int unicam_enum_framesizes(struct file *file, void *priv,
++ struct v4l2_frmsizeenum *fsize)
++{
++ struct unicam_device *dev = video_drvdata(file);
++ const struct unicam_fmt *fmt;
++ struct v4l2_subdev_frame_size_enum fse;
++ int ret;
++
++ /* check for valid format */
++ fmt = find_format_by_pix(dev, fsize->pixel_format);
++ if (!fmt) {
++ unicam_dbg(3, dev, "Invalid pixel code: %x\n",
++ fsize->pixel_format);
++ return -EINVAL;
++ }
++
++ fse.index = fsize->index;
++ fse.pad = 0;
++ fse.code = fmt->code;
++
++ ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_size, NULL, &fse);
++ if (ret)
++ return ret;
++
++ unicam_dbg(1, dev, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n",
++ __func__, fse.index, fse.code, fse.min_width, fse.max_width,
++ fse.min_height, fse.max_height);
++
++ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
++ fsize->discrete.width = fse.max_width;
++ fsize->discrete.height = fse.max_height;
++
++ return 0;
++}
++
++static int unicam_enum_frameintervals(struct file *file, void *priv,
++ struct v4l2_frmivalenum *fival)
++{
++ struct unicam_device *dev = video_drvdata(file);
++ const struct unicam_fmt *fmt;
++ struct v4l2_subdev_frame_interval_enum fie = {
++ .index = fival->index,
++ .width = fival->width,
++ .height = fival->height,
++ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
++ };
++ int ret;
++
++ fmt = find_format_by_pix(dev, fival->pixel_format);
++ if (!fmt)
++ return -EINVAL;
++
++ fie.code = fmt->code;
++ ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_interval,
++ NULL, &fie);
++ if (ret)
++ return ret;
++
++ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
++ fival->discrete = fie.interval;
++
++ return 0;
++}
++
++static int unicam_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
++{
++ struct unicam_device *dev = video_drvdata(file);
++
++ return v4l2_g_parm_cap(video_devdata(file), dev->sensor, a);
++}
++
++static int unicam_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
++{
++ struct unicam_device *dev = video_drvdata(file);
++
++ return v4l2_s_parm_cap(video_devdata(file), dev->sensor, a);
++}
++
+ static int unicam_g_dv_timings(struct file *file, void *priv,
+ struct v4l2_dv_timings *timings)
+ {
+@@ -1613,6 +1691,12 @@ static const struct v4l2_ioctl_ops unica
+ .vidioc_g_edid = unicam_g_edid,
+ .vidioc_s_edid = unicam_s_edid,
+
++ .vidioc_enum_framesizes = unicam_enum_framesizes,
++ .vidioc_enum_frameintervals = unicam_enum_frameintervals,
++
++ .vidioc_g_parm = unicam_g_parm,
++ .vidioc_s_parm = unicam_s_parm,
++
+ .vidioc_s_dv_timings = unicam_s_dv_timings,
+ .vidioc_g_dv_timings = unicam_g_dv_timings,
+ .vidioc_query_dv_timings = unicam_query_dv_timings,
+@@ -1850,6 +1934,16 @@ static int unicam_probe_complete(struct
+ v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_ENUM_DV_TIMINGS);
+ v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_QUERY_DV_TIMINGS);
+ }
++ if (!v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_interval))
++ v4l2_disable_ioctl(&unicam->video_dev,
++ VIDIOC_ENUM_FRAMEINTERVALS);
++ if (!v4l2_subdev_has_op(unicam->sensor, video, g_frame_interval))
++ v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_G_PARM);
++ if (!v4l2_subdev_has_op(unicam->sensor, video, s_frame_interval))
++ v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_S_PARM);
++
++ if (!v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_size))
++ v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_ENUM_FRAMESIZES);
+
+ ret = v4l2_device_register_subdev_nodes(&unicam->v4l2_dev);
+ if (ret) {
+++ /dev/null
-From 1ec52e16794513c5802ad219d317ac1f825b6346 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 25 Mar 2019 18:03:48 +0000
-Subject: [PATCH 394/703] overlays: Add max17040 support to i2c-sensor
-
-See: https://github.com/raspberrypi/linux/issues/2906
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README | 3 +++
- .../arm/boot/dts/overlays/i2c-sensor-overlay.dts | 16 ++++++++++++++++
- 2 files changed, 19 insertions(+)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1030,6 +1030,9 @@ Params: addr Set the
-
- lm75addr Deprecated - use addr parameter instead
-
-+ max17040 Select the Maxim Integrated MAX17040 battery
-+ monitor
-+
- sht3x Select the Sensiron SHT3x temperature and
- humidity sensor. Valid addresses 0x44-0x45,
- default 0x44
---- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
-@@ -201,6 +201,21 @@
- };
- };
-
-+ fragment@13 {
-+ target = <&i2c_arm>;
-+ __dormant__ {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "okay";
-+
-+ max17040: max17040@36 {
-+ compatible = "maxim,max17040";
-+ reg = <0x36>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
- __overrides__ {
- addr = <&bme280>,"reg:0", <&bmp280>,"reg:0", <&tmp102>,"reg:0",
- <&lm75>,"reg:0", <&hdc100x>,"reg:0", <&sht3x>,"reg:0",
-@@ -219,5 +234,6 @@
- veml6070 = <0>,"+10";
- sht3x = <0>,"+11";
- ds1621 = <0>,"+12";
-+ max17040 = <0>,"+13";
- };
- };
--- /dev/null
+From 3307d285c4e10366fbd310203c19260d5e320b97 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 20 Mar 2019 10:06:51 +0000
+Subject: [PATCH 394/725] staging: bcm2835-codec: Refactor default resolution
+ code
+
+The default resolution code was different for each role
+as compressed formats need to pass bytesperline as 0 and
+set up customised buffer sizes.
+This is common setup, therefore amend get_sizeimage and
+get_bytesperline to do the correct thing whether compressed
+or uncompressed.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c | 103 +++++++-----------
+ 1 file changed, 40 insertions(+), 63 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -578,10 +578,17 @@ static void job_abort(void *priv)
+ ctx->aborting = 1;
+ }
+
+-static inline unsigned int get_sizeimage(int bpl, int height,
++static inline unsigned int get_sizeimage(int bpl, int width, int height,
+ struct bcm2835_codec_fmt *fmt)
+ {
+- return (bpl * height * fmt->size_multiplier_x2) >> 1;
++ if (fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
++ if (width * height > 1280 * 720)
++ return DEF_COMP_BUF_SIZE_GREATER_720P;
++ else
++ return DEF_COMP_BUF_SIZE_720P_OR_LESS;
++ } else {
++ return (bpl * height * fmt->size_multiplier_x2) >> 1;
++ }
+ }
+
+ static inline unsigned int get_bytesperline(int width,
+@@ -1032,22 +1039,13 @@ static int vidioc_try_fmt(struct v4l2_fo
+ * some of the pixels are active.
+ */
+ f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
+-
+- f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
+- fmt);
+- f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
+- f->fmt.pix.height,
+- fmt);
+- } else {
+- u32 min_size = f->fmt.pix.width > 1280 ||
+- f->fmt.pix.height > 720 ?
+- DEF_COMP_BUF_SIZE_GREATER_720P :
+- DEF_COMP_BUF_SIZE_720P_OR_LESS;
+-
+- f->fmt.pix.bytesperline = 0;
+- if (f->fmt.pix.sizeimage < min_size)
+- f->fmt.pix.sizeimage = min_size;
+ }
++ f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
++ fmt);
++ f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
++ f->fmt.pix.width,
++ f->fmt.pix.height,
++ fmt);
+
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+
+@@ -1159,6 +1157,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+ q_data_dst->bytesperline =
+ get_bytesperline(f->fmt.pix.width, q_data_dst->fmt);
+ q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
++ q_data_dst->crop_width,
+ q_data_dst->height,
+ q_data_dst->fmt);
+ update_capture_port = true;
+@@ -2218,52 +2217,30 @@ static int bcm2835_codec_open(struct fil
+
+ ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
+ ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
+- switch (dev->role) {
+- case DECODE:
+- /*
+- * Input width and height are irrelevant as they will be defined
+- * by the bitstream not the format. Required by V4L2 though.
+- */
+- ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
+- ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
+- ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
+- ctx->q_data[V4L2_M2M_SRC].bytesperline = 0;
+- ctx->q_data[V4L2_M2M_SRC].sizeimage =
+- DEF_COMP_BUF_SIZE_720P_OR_LESS;
+-
+- ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
+- ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
+- ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
+- ctx->q_data[V4L2_M2M_DST].bytesperline =
+- get_bytesperline(DEFAULT_WIDTH,
+- ctx->q_data[V4L2_M2M_DST].fmt);
+- ctx->q_data[V4L2_M2M_DST].sizeimage =
+- get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
+- ctx->q_data[V4L2_M2M_DST].height,
+- ctx->q_data[V4L2_M2M_DST].fmt);
+- break;
+- case ENCODE:
+- ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
+- ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
+- ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
+- ctx->q_data[V4L2_M2M_SRC].bytesperline =
+- get_bytesperline(DEFAULT_WIDTH,
+- ctx->q_data[V4L2_M2M_SRC].fmt);
+- ctx->q_data[V4L2_M2M_SRC].sizeimage =
+- get_sizeimage(ctx->q_data[V4L2_M2M_SRC].bytesperline,
+- ctx->q_data[V4L2_M2M_SRC].height,
+- ctx->q_data[V4L2_M2M_SRC].fmt);
+-
+- ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
+- ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
+- ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
+- ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
+- ctx->q_data[V4L2_M2M_DST].sizeimage =
+- DEF_COMP_BUF_SIZE_720P_OR_LESS;
+- break;
+- case ISP:
+- break;
+- }
++
++ ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
++ ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
++ ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
++ ctx->q_data[V4L2_M2M_SRC].bytesperline =
++ get_bytesperline(DEFAULT_WIDTH,
++ ctx->q_data[V4L2_M2M_SRC].fmt);
++ ctx->q_data[V4L2_M2M_SRC].sizeimage =
++ get_sizeimage(ctx->q_data[V4L2_M2M_SRC].bytesperline,
++ ctx->q_data[V4L2_M2M_SRC].crop_width,
++ ctx->q_data[V4L2_M2M_SRC].height,
++ ctx->q_data[V4L2_M2M_SRC].fmt);
++
++ ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
++ ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
++ ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
++ ctx->q_data[V4L2_M2M_DST].bytesperline =
++ get_bytesperline(DEFAULT_WIDTH,
++ ctx->q_data[V4L2_M2M_DST].fmt);
++ ctx->q_data[V4L2_M2M_DST].sizeimage =
++ get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
++ ctx->q_data[V4L2_M2M_DST].crop_width,
++ ctx->q_data[V4L2_M2M_DST].height,
++ ctx->q_data[V4L2_M2M_DST].fmt);
+
+ ctx->colorspace = V4L2_COLORSPACE_REC709;
+ ctx->bitrate = 10 * 1000 * 1000;
+++ /dev/null
-From 77816ef138e56144d51a5948d5a9646a4e1f2aa8 Mon Sep 17 00:00:00 2001
-From: P33M <P33M@users.noreply.github.com>
-Date: Tue, 26 Mar 2019 09:48:25 +0000
-Subject: [PATCH 395/703] defconfigs: disable memory and IO cgroups (#2908)
-
-Due to an upstream bug, memory is leaked in the inode cache when cgroups
-are enabled. Disable as this is causing crashes.
-
-See: https://github.com/raspberrypi/linux/issues/2829
----
- arch/arm/configs/bcm2709_defconfig | 4 ----
- arch/arm/configs/bcmrpi_defconfig | 4 ----
- arch/arm64/configs/bcmrpi3_defconfig | 4 ----
- 3 files changed, 12 deletions(-)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -14,8 +14,6 @@ CONFIG_TASK_XACCT=y
- CONFIG_TASK_IO_ACCOUNTING=y
- CONFIG_IKCONFIG=m
- CONFIG_IKCONFIG_PROC=y
--CONFIG_MEMCG=y
--CONFIG_BLK_CGROUP=y
- CONFIG_CGROUP_FREEZER=y
- CONFIG_CPUSETS=y
- CONFIG_CGROUP_DEVICE=y
-@@ -64,10 +62,8 @@ CONFIG_MODULES=y
- CONFIG_MODULE_UNLOAD=y
- CONFIG_MODVERSIONS=y
- CONFIG_MODULE_SRCVERSION_ALL=y
--CONFIG_BLK_DEV_THROTTLING=y
- CONFIG_PARTITION_ADVANCED=y
- CONFIG_MAC_PARTITION=y
--CONFIG_CFQ_GROUP_IOSCHED=y
- CONFIG_BINFMT_MISC=m
- CONFIG_CLEANCACHE=y
- CONFIG_FRONTSWAP=y
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -13,8 +13,6 @@ CONFIG_TASK_XACCT=y
- CONFIG_TASK_IO_ACCOUNTING=y
- CONFIG_IKCONFIG=m
- CONFIG_IKCONFIG_PROC=y
--CONFIG_MEMCG=y
--CONFIG_BLK_CGROUP=y
- CONFIG_CGROUP_FREEZER=y
- CONFIG_CGROUP_DEVICE=y
- CONFIG_CGROUP_CPUACCT=y
-@@ -58,10 +56,8 @@ CONFIG_MODULES=y
- CONFIG_MODULE_UNLOAD=y
- CONFIG_MODVERSIONS=y
- CONFIG_MODULE_SRCVERSION_ALL=y
--CONFIG_BLK_DEV_THROTTLING=y
- CONFIG_PARTITION_ADVANCED=y
- CONFIG_MAC_PARTITION=y
--CONFIG_CFQ_GROUP_IOSCHED=y
- CONFIG_BINFMT_MISC=m
- CONFIG_CLEANCACHE=y
- CONFIG_FRONTSWAP=y
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -13,8 +13,6 @@ CONFIG_TASK_XACCT=y
- CONFIG_TASK_IO_ACCOUNTING=y
- CONFIG_IKCONFIG=m
- CONFIG_IKCONFIG_PROC=y
--CONFIG_MEMCG=y
--CONFIG_BLK_CGROUP=y
- CONFIG_CGROUP_FREEZER=y
- CONFIG_CPUSETS=y
- CONFIG_CGROUP_DEVICE=y
-@@ -62,10 +60,8 @@ CONFIG_MODULES=y
- CONFIG_MODULE_UNLOAD=y
- CONFIG_MODVERSIONS=y
- CONFIG_MODULE_SRCVERSION_ALL=y
--CONFIG_BLK_DEV_THROTTLING=y
- CONFIG_PARTITION_ADVANCED=y
- CONFIG_MAC_PARTITION=y
--CONFIG_CFQ_GROUP_IOSCHED=y
- CONFIG_BINFMT_MISC=y
- CONFIG_CLEANCACHE=y
- CONFIG_FRONTSWAP=y
--- /dev/null
+From b3acb96a394db9adcc13aae8321e3d18bbd7d30d Mon Sep 17 00:00:00 2001
+From: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Date: Fri, 30 Nov 2018 11:53:20 +0000
+Subject: [PATCH 395/725] nvmem: add type attribute
+
+commit 16688453661b6d5159be558a1f8c1f54463a420f upstream.
+
+Add a type attribute so userspace is able to know how the data is stored as
+this can help taking the correct decision when selecting which device to
+use. This will also help program display the proper warnings when burning
+fuses for example.
+
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvmem/core.c | 21 +++++++++++++++++++++
+ include/linux/nvmem-provider.h | 16 ++++++++++++++++
+ 2 files changed, 37 insertions(+)
+
+--- a/drivers/nvmem/core.c
++++ b/drivers/nvmem/core.c
+@@ -36,6 +36,7 @@ struct nvmem_device {
+ size_t size;
+ bool read_only;
+ int flags;
++ enum nvmem_type type;
+ struct bin_attribute eeprom;
+ struct device *base_dev;
+ nvmem_reg_read_t reg_read;
+@@ -84,6 +85,21 @@ static int nvmem_reg_write(struct nvmem_
+ return -EINVAL;
+ }
+
++static ssize_t type_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct nvmem_device *nvmem = to_nvmem_device(dev);
++
++ return sprintf(buf, "%s\n", nvmem_type_str[nvmem->type]);
++}
++
++static DEVICE_ATTR_RO(type);
++
++static struct attribute *nvmem_attrs[] = {
++ &dev_attr_type.attr,
++ NULL,
++};
++
+ static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t pos, size_t count)
+@@ -169,6 +185,7 @@ static struct bin_attribute *nvmem_bin_r
+
+ static const struct attribute_group nvmem_bin_rw_group = {
+ .bin_attrs = nvmem_bin_rw_attributes,
++ .attrs = nvmem_attrs,
+ };
+
+ static const struct attribute_group *nvmem_rw_dev_groups[] = {
+@@ -192,6 +209,7 @@ static struct bin_attribute *nvmem_bin_r
+
+ static const struct attribute_group nvmem_bin_ro_group = {
+ .bin_attrs = nvmem_bin_ro_attributes,
++ .attrs = nvmem_attrs,
+ };
+
+ static const struct attribute_group *nvmem_ro_dev_groups[] = {
+@@ -216,6 +234,7 @@ static struct bin_attribute *nvmem_bin_r
+
+ static const struct attribute_group nvmem_bin_rw_root_group = {
+ .bin_attrs = nvmem_bin_rw_root_attributes,
++ .attrs = nvmem_attrs,
+ };
+
+ static const struct attribute_group *nvmem_rw_root_dev_groups[] = {
+@@ -239,6 +258,7 @@ static struct bin_attribute *nvmem_bin_r
+
+ static const struct attribute_group nvmem_bin_ro_root_group = {
+ .bin_attrs = nvmem_bin_ro_root_attributes,
++ .attrs = nvmem_attrs,
+ };
+
+ static const struct attribute_group *nvmem_ro_root_dev_groups[] = {
+@@ -478,6 +498,7 @@ struct nvmem_device *nvmem_register(cons
+ nvmem->dev.bus = &nvmem_bus_type;
+ nvmem->dev.parent = config->dev;
+ nvmem->priv = config->priv;
++ nvmem->type = config->type;
+ nvmem->reg_read = config->reg_read;
+ nvmem->reg_write = config->reg_write;
+ nvmem->dev.of_node = config->dev->of_node;
+--- a/include/linux/nvmem-provider.h
++++ b/include/linux/nvmem-provider.h
+@@ -22,6 +22,20 @@ typedef int (*nvmem_reg_read_t)(void *pr
+ typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
+ void *val, size_t bytes);
+
++enum nvmem_type {
++ NVMEM_TYPE_UNKNOWN = 0,
++ NVMEM_TYPE_EEPROM,
++ NVMEM_TYPE_OTP,
++ NVMEM_TYPE_BATTERY_BACKED,
++};
++
++static const char * const nvmem_type_str[] = {
++ [NVMEM_TYPE_UNKNOWN] = "Unknown",
++ [NVMEM_TYPE_EEPROM] = "EEPROM",
++ [NVMEM_TYPE_OTP] = "OTP",
++ [NVMEM_TYPE_BATTERY_BACKED] = "Battery backed",
++};
++
+ /**
+ * struct nvmem_config - NVMEM device configuration
+ *
+@@ -31,6 +45,7 @@ typedef int (*nvmem_reg_write_t)(void *p
+ * @owner: Pointer to exporter module. Used for refcounting.
+ * @cells: Optional array of pre-defined NVMEM cells.
+ * @ncells: Number of elements in cells.
++ * @type: Type of the nvmem storage
+ * @read_only: Device is read-only.
+ * @root_only: Device is accessibly to root only.
+ * @reg_read: Callback to read data.
+@@ -54,6 +69,7 @@ struct nvmem_config {
+ struct module *owner;
+ const struct nvmem_cell_info *cells;
+ int ncells;
++ enum nvmem_type type;
+ bool read_only;
+ bool root_only;
+ nvmem_reg_read_t reg_read;
+++ /dev/null
-From 99e2a119c5dc323c698f8b7f699c20599c05e23e Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 5 Mar 2019 15:43:27 +0000
-Subject: [PATCH 396/703] media: bcm2835-unicam: Add support for enum
- framesizes and frameintervals
-
-vidioc_enum_framesizes and vidioc_enum_frameintervals weren't implemented,
-therefore clients couldn't enumerate the supported resolutions.
-
-Implement them by forwarding on to the sensor driver.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../media/platform/bcm2835/bcm2835-unicam.c | 94 +++++++++++++++++++
- 1 file changed, 94 insertions(+)
-
---- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
-+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
-@@ -1406,6 +1406,84 @@ static int unicam_g_edid(struct file *fi
- return v4l2_subdev_call(dev->sensor, pad, get_edid, edid);
- }
-
-+static int unicam_enum_framesizes(struct file *file, void *priv,
-+ struct v4l2_frmsizeenum *fsize)
-+{
-+ struct unicam_device *dev = video_drvdata(file);
-+ const struct unicam_fmt *fmt;
-+ struct v4l2_subdev_frame_size_enum fse;
-+ int ret;
-+
-+ /* check for valid format */
-+ fmt = find_format_by_pix(dev, fsize->pixel_format);
-+ if (!fmt) {
-+ unicam_dbg(3, dev, "Invalid pixel code: %x\n",
-+ fsize->pixel_format);
-+ return -EINVAL;
-+ }
-+
-+ fse.index = fsize->index;
-+ fse.pad = 0;
-+ fse.code = fmt->code;
-+
-+ ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_size, NULL, &fse);
-+ if (ret)
-+ return ret;
-+
-+ unicam_dbg(1, dev, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n",
-+ __func__, fse.index, fse.code, fse.min_width, fse.max_width,
-+ fse.min_height, fse.max_height);
-+
-+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-+ fsize->discrete.width = fse.max_width;
-+ fsize->discrete.height = fse.max_height;
-+
-+ return 0;
-+}
-+
-+static int unicam_enum_frameintervals(struct file *file, void *priv,
-+ struct v4l2_frmivalenum *fival)
-+{
-+ struct unicam_device *dev = video_drvdata(file);
-+ const struct unicam_fmt *fmt;
-+ struct v4l2_subdev_frame_interval_enum fie = {
-+ .index = fival->index,
-+ .width = fival->width,
-+ .height = fival->height,
-+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
-+ };
-+ int ret;
-+
-+ fmt = find_format_by_pix(dev, fival->pixel_format);
-+ if (!fmt)
-+ return -EINVAL;
-+
-+ fie.code = fmt->code;
-+ ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_interval,
-+ NULL, &fie);
-+ if (ret)
-+ return ret;
-+
-+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-+ fival->discrete = fie.interval;
-+
-+ return 0;
-+}
-+
-+static int unicam_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
-+{
-+ struct unicam_device *dev = video_drvdata(file);
-+
-+ return v4l2_g_parm_cap(video_devdata(file), dev->sensor, a);
-+}
-+
-+static int unicam_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
-+{
-+ struct unicam_device *dev = video_drvdata(file);
-+
-+ return v4l2_s_parm_cap(video_devdata(file), dev->sensor, a);
-+}
-+
- static int unicam_g_dv_timings(struct file *file, void *priv,
- struct v4l2_dv_timings *timings)
- {
-@@ -1613,6 +1691,12 @@ static const struct v4l2_ioctl_ops unica
- .vidioc_g_edid = unicam_g_edid,
- .vidioc_s_edid = unicam_s_edid,
-
-+ .vidioc_enum_framesizes = unicam_enum_framesizes,
-+ .vidioc_enum_frameintervals = unicam_enum_frameintervals,
-+
-+ .vidioc_g_parm = unicam_g_parm,
-+ .vidioc_s_parm = unicam_s_parm,
-+
- .vidioc_s_dv_timings = unicam_s_dv_timings,
- .vidioc_g_dv_timings = unicam_g_dv_timings,
- .vidioc_query_dv_timings = unicam_query_dv_timings,
-@@ -1850,6 +1934,16 @@ static int unicam_probe_complete(struct
- v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_ENUM_DV_TIMINGS);
- v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_QUERY_DV_TIMINGS);
- }
-+ if (!v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_interval))
-+ v4l2_disable_ioctl(&unicam->video_dev,
-+ VIDIOC_ENUM_FRAMEINTERVALS);
-+ if (!v4l2_subdev_has_op(unicam->sensor, video, g_frame_interval))
-+ v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_G_PARM);
-+ if (!v4l2_subdev_has_op(unicam->sensor, video, s_frame_interval))
-+ v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_S_PARM);
-+
-+ if (!v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_size))
-+ v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_ENUM_FRAMESIZES);
-
- ret = v4l2_device_register_subdev_nodes(&unicam->v4l2_dev);
- if (ret) {
--- /dev/null
+From 5437fefa8d11d8c2f9da39e393c83417cadabf83 Mon Sep 17 00:00:00 2001
+From: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Date: Wed, 13 Feb 2019 00:21:36 +0100
+Subject: [PATCH 396/725] rtc: rv3028: add new driver
+
+upstream commit e6e7376cfd7b3f9b63de3a22792f64d9bfb2ab53.
+
+Add a driver for the MicroCrystal RV-3028. It is a SMT Real-Time Clock
+Module that incorporates an integrated CMOS circuit together with an XTAL.
+It has an i2c interface.
+
+The driver handles date/time, alarms, trickle charging, timestamping,
+frequency offset correction, EEPROM and NVRAM.
+
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+---
+ Documentation/devicetree/bindings/rtc/rtc.txt | 69 ++
+ drivers/rtc/Kconfig | 9 +
+ drivers/rtc/Makefile | 1 +
+ drivers/rtc/rtc-rv3028.c | 733 ++++++++++++++++++
+ 4 files changed, 812 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/rtc/rtc.txt
+ create mode 100644 drivers/rtc/rtc-rv3028.c
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/rtc/rtc.txt
+@@ -0,0 +1,69 @@
++Generic device tree bindings for Real Time Clock devices
++========================================================
++
++This document describes generic bindings which can be used to describe Real Time
++Clock devices in a device tree.
++
++Required properties
++-------------------
++
++- compatible : name of RTC device following generic names recommended practice.
++
++For other required properties e.g. to describe register sets,
++clocks, etc. check the binding documentation of the specific driver.
++
++Optional properties
++-------------------
++
++- start-year : if provided, the default hardware range supported by the RTC is
++ shifted so the first usable year is the specified one.
++
++The following properties may not be supported by all drivers. However, if a
++driver wants to support one of the below features, it should adapt the bindings
++below.
++- trickle-resistor-ohms : Selected resistor for trickle charger. Should be given
++ if trickle charger should be enabled
++- trickle-diode-disable : Do not use internal trickle charger diode Should be
++ given if internal trickle charger diode should be
++ disabled
++- wakeup-source : Enables wake up of host system on alarm
++- quartz-load-femtofarads : The capacitive load of the quartz(x-tal),
++ expressed in femto Farad (fF).
++ The default value shall be listed (if optional),
++ and likewise all valid values.
++
++Trivial RTCs
++------------
++
++This is a list of trivial RTC devices that have simple device tree
++bindings, consisting only of a compatible field, an address and
++possibly an interrupt line.
++
++
++Compatible Vendor / Chip
++========== =============
++abracon,abb5zes3 AB-RTCMC-32.768kHz-B5ZE-S3: Real Time Clock/Calendar Module with I2C Interface
++dallas,ds1374 I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output
++dallas,ds1672 Dallas DS1672 Real-time Clock
++dallas,ds3232 Extremely Accurate I²C RTC with Integrated Crystal and SRAM
++epson,rx8010 I2C-BUS INTERFACE REAL TIME CLOCK MODULE
++epson,rx8581 I2C-BUS INTERFACE REAL TIME CLOCK MODULE
++emmicro,em3027 EM Microelectronic EM3027 Real-time Clock
++isil,isl1208 Intersil ISL1208 Low Power RTC with Battery Backed SRAM
++isil,isl1218 Intersil ISL1218 Low Power RTC with Battery Backed SRAM
++isil,isl12022 Intersil ISL12022 Real-time Clock
++microcrystal,rv3028 Real Time Clock Module with I2C-Bus
++microcrystal,rv3029 Real Time Clock Module with I2C-Bus
++microcrystal,rv8523 Real Time Clock
++nxp,pcf2127 Real-time clock
++nxp,pcf2129 Real-time clock
++nxp,pcf8563 Real-time clock/calendar
++pericom,pt7c4338 Real-time Clock Module
++ricoh,r2025sd I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
++ricoh,r2221tl I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
++ricoh,rs5c372a I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
++ricoh,rs5c372b I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
++ricoh,rv5c386 I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
++ricoh,rv5c387a I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
++sii,s35390a 2-wire CMOS real-time clock
++whwave,sd3078 I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
+--- a/drivers/rtc/Kconfig
++++ b/drivers/rtc/Kconfig
+@@ -625,6 +625,15 @@ config RTC_DRV_EM3027
+ This driver can also be built as a module. If so, the module
+ will be called rtc-em3027.
+
++config RTC_DRV_RV3028
++ tristate "Micro Crystal RV3028"
++ help
++ If you say yes here you get support for the Micro Crystal
++ RV3028.
++
++ This driver can also be built as a module. If so, the module
++ will be called rtc-rv3028.
++
+ config RTC_DRV_RV8803
+ tristate "Micro Crystal RV8803, Epson RX8900"
+ help
+--- a/drivers/rtc/Makefile
++++ b/drivers/rtc/Makefile
+@@ -136,6 +136,7 @@ obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5
+ obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
+ obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
+ obj-$(CONFIG_RTC_DRV_RTD119X) += rtc-rtd119x.o
++obj-$(CONFIG_RTC_DRV_RV3028) += rtc-rv3028.o
+ obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o
+ obj-$(CONFIG_RTC_DRV_RV8803) += rtc-rv8803.o
+ obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o
+--- /dev/null
++++ b/drivers/rtc/rtc-rv3028.c
+@@ -0,0 +1,733 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * RTC driver for the Micro Crystal RV3028
++ *
++ * Copyright (C) 2019 Micro Crystal SA
++ *
++ * Alexandre Belloni <alexandre.belloni@bootlin.com>
++ *
++ */
++
++#include <linux/bcd.h>
++#include <linux/bitops.h>
++#include <linux/i2c.h>
++#include <linux/interrupt.h>
++#include <linux/kernel.h>
++#include <linux/log2.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++#include <linux/regmap.h>
++#include <linux/rtc.h>
++#include "rtc-core.h"
++
++#define RV3028_SEC 0x00
++#define RV3028_MIN 0x01
++#define RV3028_HOUR 0x02
++#define RV3028_WDAY 0x03
++#define RV3028_DAY 0x04
++#define RV3028_MONTH 0x05
++#define RV3028_YEAR 0x06
++#define RV3028_ALARM_MIN 0x07
++#define RV3028_ALARM_HOUR 0x08
++#define RV3028_ALARM_DAY 0x09
++#define RV3028_STATUS 0x0E
++#define RV3028_CTRL1 0x0F
++#define RV3028_CTRL2 0x10
++#define RV3028_EVT_CTRL 0x13
++#define RV3028_TS_COUNT 0x14
++#define RV3028_TS_SEC 0x15
++#define RV3028_RAM1 0x1F
++#define RV3028_EEPROM_ADDR 0x25
++#define RV3028_EEPROM_DATA 0x26
++#define RV3028_EEPROM_CMD 0x27
++#define RV3028_CLKOUT 0x35
++#define RV3028_OFFSET 0x36
++#define RV3028_BACKUP 0x37
++
++#define RV3028_STATUS_PORF BIT(0)
++#define RV3028_STATUS_EVF BIT(1)
++#define RV3028_STATUS_AF BIT(2)
++#define RV3028_STATUS_TF BIT(3)
++#define RV3028_STATUS_UF BIT(4)
++#define RV3028_STATUS_BSF BIT(5)
++#define RV3028_STATUS_CLKF BIT(6)
++#define RV3028_STATUS_EEBUSY BIT(7)
++
++#define RV3028_CTRL1_EERD BIT(3)
++#define RV3028_CTRL1_WADA BIT(5)
++
++#define RV3028_CTRL2_RESET BIT(0)
++#define RV3028_CTRL2_12_24 BIT(1)
++#define RV3028_CTRL2_EIE BIT(2)
++#define RV3028_CTRL2_AIE BIT(3)
++#define RV3028_CTRL2_TIE BIT(4)
++#define RV3028_CTRL2_UIE BIT(5)
++#define RV3028_CTRL2_TSE BIT(7)
++
++#define RV3028_EVT_CTRL_TSR BIT(2)
++
++#define RV3028_EEPROM_CMD_WRITE 0x21
++#define RV3028_EEPROM_CMD_READ 0x22
++
++#define RV3028_EEBUSY_POLL 10000
++#define RV3028_EEBUSY_TIMEOUT 100000
++
++#define RV3028_BACKUP_TCE BIT(5)
++#define RV3028_BACKUP_TCR_MASK GENMASK(1,0)
++
++#define OFFSET_STEP_PPT 953674
++
++enum rv3028_type {
++ rv_3028,
++};
++
++struct rv3028_data {
++ struct regmap *regmap;
++ struct rtc_device *rtc;
++ enum rv3028_type type;
++};
++
++static u16 rv3028_trickle_resistors[] = {1000, 3000, 6000, 11000};
++
++static ssize_t timestamp0_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
++
++ regmap_update_bits(rv3028->regmap, RV3028_EVT_CTRL, RV3028_EVT_CTRL_TSR,
++ RV3028_EVT_CTRL_TSR);
++
++ return count;
++};
++
++static ssize_t timestamp0_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
++ struct rtc_time tm;
++ int ret, count;
++ u8 date[6];
++
++ ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count);
++ if (ret)
++ return ret;
++
++ if (!count)
++ return 0;
++
++ ret = regmap_bulk_read(rv3028->regmap, RV3028_TS_SEC, date,
++ sizeof(date));
++ if (ret)
++ return ret;
++
++ tm.tm_sec = bcd2bin(date[0]);
++ tm.tm_min = bcd2bin(date[1]);
++ tm.tm_hour = bcd2bin(date[2]);
++ tm.tm_mday = bcd2bin(date[3]);
++ tm.tm_mon = bcd2bin(date[4]) - 1;
++ tm.tm_year = bcd2bin(date[5]) + 100;
++
++ ret = rtc_valid_tm(&tm);
++ if (ret)
++ return ret;
++
++ return sprintf(buf, "%llu\n",
++ (unsigned long long)rtc_tm_to_time64(&tm));
++};
++
++static DEVICE_ATTR_RW(timestamp0);
++
++static ssize_t timestamp0_count_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
++ int ret, count;
++
++ ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count);
++ if (ret)
++ return ret;
++
++ return sprintf(buf, "%u\n", count);
++};
++
++static DEVICE_ATTR_RO(timestamp0_count);
++
++static struct attribute *rv3028_attrs[] = {
++ &dev_attr_timestamp0.attr,
++ &dev_attr_timestamp0_count.attr,
++ NULL
++};
++
++static const struct attribute_group rv3028_attr_group = {
++ .attrs = rv3028_attrs,
++};
++
++static irqreturn_t rv3028_handle_irq(int irq, void *dev_id)
++{
++ struct rv3028_data *rv3028 = dev_id;
++ unsigned long events = 0;
++ u32 status = 0, ctrl = 0;
++
++ if (regmap_read(rv3028->regmap, RV3028_STATUS, &status) < 0 ||
++ status == 0) {
++ return IRQ_NONE;
++ }
++
++ if (status & RV3028_STATUS_PORF)
++ dev_warn(&rv3028->rtc->dev, "Voltage low, data loss detected.\n");
++
++ if (status & RV3028_STATUS_TF) {
++ status |= RV3028_STATUS_TF;
++ ctrl |= RV3028_CTRL2_TIE;
++ events |= RTC_PF;
++ }
++
++ if (status & RV3028_STATUS_AF) {
++ status |= RV3028_STATUS_AF;
++ ctrl |= RV3028_CTRL2_AIE;
++ events |= RTC_AF;
++ }
++
++ if (status & RV3028_STATUS_UF) {
++ status |= RV3028_STATUS_UF;
++ ctrl |= RV3028_CTRL2_UIE;
++ events |= RTC_UF;
++ }
++
++ if (events) {
++ rtc_update_irq(rv3028->rtc, 1, events);
++ regmap_update_bits(rv3028->regmap, RV3028_STATUS, status, 0);
++ regmap_update_bits(rv3028->regmap, RV3028_CTRL2, ctrl, 0);
++ }
++
++ if (status & RV3028_STATUS_EVF) {
++ sysfs_notify(&rv3028->rtc->dev.kobj, NULL,
++ dev_attr_timestamp0.attr.name);
++ dev_warn(&rv3028->rtc->dev, "event detected");
++ }
++
++ return IRQ_HANDLED;
++}
++
++static int rv3028_get_time(struct device *dev, struct rtc_time *tm)
++{
++ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++ u8 date[7];
++ int ret, status;
++
++ ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
++ if (ret < 0)
++ return ret;
++
++ if (status & RV3028_STATUS_PORF) {
++ dev_warn(dev, "Voltage low, data is invalid.\n");
++ return -EINVAL;
++ }
++
++ ret = regmap_bulk_read(rv3028->regmap, RV3028_SEC, date, sizeof(date));
++ if (ret)
++ return ret;
++
++ tm->tm_sec = bcd2bin(date[RV3028_SEC] & 0x7f);
++ tm->tm_min = bcd2bin(date[RV3028_MIN] & 0x7f);
++ tm->tm_hour = bcd2bin(date[RV3028_HOUR] & 0x3f);
++ tm->tm_wday = ilog2(date[RV3028_WDAY] & 0x7f);
++ tm->tm_mday = bcd2bin(date[RV3028_DAY] & 0x3f);
++ tm->tm_mon = bcd2bin(date[RV3028_MONTH] & 0x1f) - 1;
++ tm->tm_year = bcd2bin(date[RV3028_YEAR]) + 100;
++
++ return 0;
++}
++
++static int rv3028_set_time(struct device *dev, struct rtc_time *tm)
++{
++ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++ u8 date[7];
++ int ret;
++
++ date[RV3028_SEC] = bin2bcd(tm->tm_sec);
++ date[RV3028_MIN] = bin2bcd(tm->tm_min);
++ date[RV3028_HOUR] = bin2bcd(tm->tm_hour);
++ date[RV3028_WDAY] = 1 << (tm->tm_wday);
++ date[RV3028_DAY] = bin2bcd(tm->tm_mday);
++ date[RV3028_MONTH] = bin2bcd(tm->tm_mon + 1);
++ date[RV3028_YEAR] = bin2bcd(tm->tm_year - 100);
++
++ /*
++ * Writing to the Seconds register has the same effect as setting RESET
++ * bit to 1
++ */
++ ret = regmap_bulk_write(rv3028->regmap, RV3028_SEC, date,
++ sizeof(date));
++ if (ret)
++ return ret;
++
++ ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
++ RV3028_STATUS_PORF, 0);
++
++ return ret;
++}
++
++static int rv3028_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
++{
++ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++ u8 alarmvals[3];
++ int status, ctrl, ret;
++
++ ret = regmap_bulk_read(rv3028->regmap, RV3028_ALARM_MIN, alarmvals,
++ sizeof(alarmvals));
++ if (ret)
++ return ret;
++
++ ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
++ if (ret < 0)
++ return ret;
++
++ ret = regmap_read(rv3028->regmap, RV3028_CTRL2, &ctrl);
++ if (ret < 0)
++ return ret;
++
++ alrm->time.tm_sec = 0;
++ alrm->time.tm_min = bcd2bin(alarmvals[0] & 0x7f);
++ alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
++ alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f);
++
++ alrm->enabled = !!(ctrl & RV3028_CTRL2_AIE);
++ alrm->pending = (status & RV3028_STATUS_AF) && alrm->enabled;
++
++ return 0;
++}
++
++static int rv3028_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
++{
++ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++ u8 alarmvals[3];
++ u8 ctrl = 0;
++ int ret;
++
++ /* The alarm has no seconds, round up to nearest minute */
++ if (alrm->time.tm_sec) {
++ time64_t alarm_time = rtc_tm_to_time64(&alrm->time);
++
++ alarm_time += 60 - alrm->time.tm_sec;
++ rtc_time64_to_tm(alarm_time, &alrm->time);
++ }
++
++ ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
++ RV3028_CTRL2_AIE | RV3028_CTRL2_UIE, 0);
++ if (ret)
++ return ret;
++
++ alarmvals[0] = bin2bcd(alrm->time.tm_min);
++ alarmvals[1] = bin2bcd(alrm->time.tm_hour);
++ alarmvals[2] = bin2bcd(alrm->time.tm_mday);
++
++ ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
++ RV3028_STATUS_AF, 0);
++ if (ret)
++ return ret;
++
++ ret = regmap_bulk_write(rv3028->regmap, RV3028_ALARM_MIN, alarmvals,
++ sizeof(alarmvals));
++ if (ret)
++ return ret;
++
++ if (alrm->enabled) {
++ if (rv3028->rtc->uie_rtctimer.enabled)
++ ctrl |= RV3028_CTRL2_UIE;
++ if (rv3028->rtc->aie_timer.enabled)
++ ctrl |= RV3028_CTRL2_AIE;
++ }
++
++ ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
++ RV3028_CTRL2_UIE | RV3028_CTRL2_AIE, ctrl);
++
++ return ret;
++}
++
++static int rv3028_alarm_irq_enable(struct device *dev, unsigned int enabled)
++{
++ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++ int ctrl = 0, ret;
++
++ if (enabled) {
++ if (rv3028->rtc->uie_rtctimer.enabled)
++ ctrl |= RV3028_CTRL2_UIE;
++ if (rv3028->rtc->aie_timer.enabled)
++ ctrl |= RV3028_CTRL2_AIE;
++ }
++
++ ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
++ RV3028_STATUS_AF | RV3028_STATUS_UF, 0);
++ if (ret)
++ return ret;
++
++ ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
++ RV3028_CTRL2_UIE | RV3028_CTRL2_AIE, ctrl);
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
++static int rv3028_read_offset(struct device *dev, long *offset)
++{
++ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++ int ret, value, steps;
++
++ ret = regmap_read(rv3028->regmap, RV3028_OFFSET, &value);
++ if (ret < 0)
++ return ret;
++
++ steps = sign_extend32(value << 1, 8);
++
++ ret = regmap_read(rv3028->regmap, RV3028_BACKUP, &value);
++ if (ret < 0)
++ return ret;
++
++ steps += value >> 7;
++
++ *offset = DIV_ROUND_CLOSEST(steps * OFFSET_STEP_PPT, 1000);
++
++ return 0;
++}
++
++static int rv3028_set_offset(struct device *dev, long offset)
++{
++ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++ int ret;
++
++ offset = clamp(offset, -244141L, 243187L) * 1000;
++ offset = DIV_ROUND_CLOSEST(offset, OFFSET_STEP_PPT);
++
++ ret = regmap_write(rv3028->regmap, RV3028_OFFSET, offset >> 1);
++ if (ret < 0)
++ return ret;
++
++ return regmap_update_bits(rv3028->regmap, RV3028_BACKUP, BIT(7),
++ offset << 7);
++}
++
++static int rv3028_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
++{
++ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
++ int status, ret = 0;
++
++ switch (cmd) {
++ case RTC_VL_READ:
++ ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
++ if (ret < 0)
++ return ret;
++
++ if (status & RV3028_STATUS_PORF)
++ dev_warn(&rv3028->rtc->dev, "Voltage low, data loss detected.\n");
++
++ status &= RV3028_STATUS_PORF;
++
++ if (copy_to_user((void __user *)arg, &status, sizeof(int)))
++ return -EFAULT;
++
++ return 0;
++
++ case RTC_VL_CLR:
++ ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
++ RV3028_STATUS_PORF, 0);
++
++ return ret;
++
++ default:
++ return -ENOIOCTLCMD;
++ }
++}
++
++static int rv3028_nvram_write(void *priv, unsigned int offset, void *val,
++ size_t bytes)
++{
++ return regmap_bulk_write(priv, RV3028_RAM1 + offset, val, bytes);
++}
++
++static int rv3028_nvram_read(void *priv, unsigned int offset, void *val,
++ size_t bytes)
++{
++ return regmap_bulk_read(priv, RV3028_RAM1 + offset, val, bytes);
++}
++
++static int rv3028_eeprom_write(void *priv, unsigned int offset, void *val,
++ size_t bytes)
++{
++ u32 status, ctrl1;
++ int i, ret, err;
++ u8 *buf = val;
++
++ ret = regmap_read(priv, RV3028_CTRL1, &ctrl1);
++ if (ret)
++ return ret;
++
++ if (!(ctrl1 & RV3028_CTRL1_EERD)) {
++ ret = regmap_update_bits(priv, RV3028_CTRL1,
++ RV3028_CTRL1_EERD, RV3028_CTRL1_EERD);
++ if (ret)
++ return ret;
++
++ ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
++ !(status & RV3028_STATUS_EEBUSY),
++ RV3028_EEBUSY_POLL,
++ RV3028_EEBUSY_TIMEOUT);
++ if (ret)
++ goto restore_eerd;
++ }
++
++ for (i = 0; i < bytes; i++) {
++ ret = regmap_write(priv, RV3028_EEPROM_ADDR, offset + i);
++ if (ret)
++ goto restore_eerd;
++
++ ret = regmap_write(priv, RV3028_EEPROM_DATA, buf[i]);
++ if (ret)
++ goto restore_eerd;
++
++ ret = regmap_write(priv, RV3028_EEPROM_CMD, 0x0);
++ if (ret)
++ goto restore_eerd;
++
++ ret = regmap_write(priv, RV3028_EEPROM_CMD,
++ RV3028_EEPROM_CMD_WRITE);
++ if (ret)
++ goto restore_eerd;
++
++ usleep_range(RV3028_EEBUSY_POLL, RV3028_EEBUSY_TIMEOUT);
++
++ ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
++ !(status & RV3028_STATUS_EEBUSY),
++ RV3028_EEBUSY_POLL,
++ RV3028_EEBUSY_TIMEOUT);
++ if (ret)
++ goto restore_eerd;
++ }
++
++restore_eerd:
++ if (!(ctrl1 & RV3028_CTRL1_EERD))
++ {
++ err = regmap_update_bits(priv, RV3028_CTRL1, RV3028_CTRL1_EERD,
++ 0);
++ if (err && !ret)
++ ret = err;
++ }
++
++ return ret;
++}
++
++static int rv3028_eeprom_read(void *priv, unsigned int offset, void *val,
++ size_t bytes)
++{
++ u32 status, ctrl1, data;
++ int i, ret, err;
++ u8 *buf = val;
++
++ ret = regmap_read(priv, RV3028_CTRL1, &ctrl1);
++ if (ret)
++ return ret;
++
++ if (!(ctrl1 & RV3028_CTRL1_EERD)) {
++ ret = regmap_update_bits(priv, RV3028_CTRL1,
++ RV3028_CTRL1_EERD, RV3028_CTRL1_EERD);
++ if (ret)
++ return ret;
++
++ ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
++ !(status & RV3028_STATUS_EEBUSY),
++ RV3028_EEBUSY_POLL,
++ RV3028_EEBUSY_TIMEOUT);
++ if (ret)
++ goto restore_eerd;
++ }
++
++ for (i = 0; i < bytes; i++) {
++ ret = regmap_write(priv, RV3028_EEPROM_ADDR, offset + i);
++ if (ret)
++ goto restore_eerd;
++
++ ret = regmap_write(priv, RV3028_EEPROM_CMD, 0x0);
++ if (ret)
++ goto restore_eerd;
++
++ ret = regmap_write(priv, RV3028_EEPROM_CMD,
++ RV3028_EEPROM_CMD_READ);
++ if (ret)
++ goto restore_eerd;
++
++ ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
++ !(status & RV3028_STATUS_EEBUSY),
++ RV3028_EEBUSY_POLL,
++ RV3028_EEBUSY_TIMEOUT);
++ if (ret)
++ goto restore_eerd;
++
++ ret = regmap_read(priv, RV3028_EEPROM_DATA, &data);
++ if (ret)
++ goto restore_eerd;
++ buf[i] = data;
++ }
++
++restore_eerd:
++ if (!(ctrl1 & RV3028_CTRL1_EERD))
++ {
++ err = regmap_update_bits(priv, RV3028_CTRL1, RV3028_CTRL1_EERD,
++ 0);
++ if (err && !ret)
++ ret = err;
++ }
++
++ return ret;
++}
++
++static struct rtc_class_ops rv3028_rtc_ops = {
++ .read_time = rv3028_get_time,
++ .set_time = rv3028_set_time,
++ .read_offset = rv3028_read_offset,
++ .set_offset = rv3028_set_offset,
++ .ioctl = rv3028_ioctl,
++};
++
++static const struct regmap_config regmap_config = {
++ .reg_bits = 8,
++ .val_bits = 8,
++ .max_register = 0x37,
++};
++
++static int rv3028_probe(struct i2c_client *client)
++{
++ struct rv3028_data *rv3028;
++ int ret, status;
++ u32 ohms;
++ struct nvmem_config nvmem_cfg = {
++ .name = "rv3028_nvram",
++ .word_size = 1,
++ .stride = 1,
++ .size = 2,
++ .type = NVMEM_TYPE_BATTERY_BACKED,
++ .reg_read = rv3028_nvram_read,
++ .reg_write = rv3028_nvram_write,
++ };
++ struct nvmem_config eeprom_cfg = {
++ .name = "rv3028_eeprom",
++ .word_size = 1,
++ .stride = 1,
++ .size = 43,
++ .type = NVMEM_TYPE_EEPROM,
++ .reg_read = rv3028_eeprom_read,
++ .reg_write = rv3028_eeprom_write,
++ };
++
++ rv3028 = devm_kzalloc(&client->dev, sizeof(struct rv3028_data),
++ GFP_KERNEL);
++ if (!rv3028)
++ return -ENOMEM;
++
++ rv3028->regmap = devm_regmap_init_i2c(client, ®map_config);
++
++ i2c_set_clientdata(client, rv3028);
++
++ ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
++ if (ret < 0)
++ return ret;
++
++ if (status & RV3028_STATUS_PORF)
++ dev_warn(&client->dev, "Voltage low, data loss detected.\n");
++
++ if (status & RV3028_STATUS_AF)
++ dev_warn(&client->dev, "An alarm may have been missed.\n");
++
++ rv3028->rtc = devm_rtc_allocate_device(&client->dev);
++ if (IS_ERR(rv3028->rtc)) {
++ return PTR_ERR(rv3028->rtc);
++ }
++
++ if (client->irq > 0) {
++ ret = devm_request_threaded_irq(&client->dev, client->irq,
++ NULL, rv3028_handle_irq,
++ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
++ "rv3028", rv3028);
++ if (ret) {
++ dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
++ client->irq = 0;
++ } else {
++ rv3028_rtc_ops.read_alarm = rv3028_get_alarm;
++ rv3028_rtc_ops.set_alarm = rv3028_set_alarm;
++ rv3028_rtc_ops.alarm_irq_enable = rv3028_alarm_irq_enable;
++ }
++ }
++
++ ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL1,
++ RV3028_CTRL1_WADA, RV3028_CTRL1_WADA);
++ if (ret)
++ return ret;
++
++ /* setup timestamping */
++ ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
++ RV3028_CTRL2_EIE | RV3028_CTRL2_TSE,
++ RV3028_CTRL2_EIE | RV3028_CTRL2_TSE);
++ if (ret)
++ return ret;
++
++ /* setup trickle charger */
++ if (!device_property_read_u32(&client->dev, "trickle-resistor-ohms",
++ &ohms)) {
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(rv3028_trickle_resistors); i++)
++ if (ohms == rv3028_trickle_resistors[i])
++ break;
++
++ if (i < ARRAY_SIZE(rv3028_trickle_resistors)) {
++ ret = regmap_update_bits(rv3028->regmap, RV3028_BACKUP,
++ RV3028_BACKUP_TCE |
++ RV3028_BACKUP_TCR_MASK,
++ RV3028_BACKUP_TCE | i);
++ if (ret)
++ return ret;
++ } else {
++ dev_warn(&client->dev, "invalid trickle resistor value\n");
++ }
++ }
++
++ ret = rtc_add_group(rv3028->rtc, &rv3028_attr_group);
++ if (ret)
++ return ret;
++
++ rv3028->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
++ rv3028->rtc->range_max = RTC_TIMESTAMP_END_2099;
++ rv3028->rtc->ops = &rv3028_rtc_ops;
++ ret = rtc_register_device(rv3028->rtc);
++ if (ret)
++ return ret;
++
++ nvmem_cfg.priv = rv3028->regmap;
++ rtc_nvmem_register(rv3028->rtc, &nvmem_cfg);
++ eeprom_cfg.priv = rv3028->regmap;
++ rtc_nvmem_register(rv3028->rtc, &eeprom_cfg);
++
++ rv3028->rtc->max_user_freq = 1;
++
++ return 0;
++}
++
++static const struct of_device_id rv3028_of_match[] = {
++ { .compatible = "microcrystal,rv3028", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, rv3028_of_match);
++
++static struct i2c_driver rv3028_driver = {
++ .driver = {
++ .name = "rtc-rv3028",
++ .of_match_table = of_match_ptr(rv3028_of_match),
++ },
++ .probe_new = rv3028_probe,
++};
++module_i2c_driver(rv3028_driver);
++
++MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>");
++MODULE_DESCRIPTION("Micro Crystal RV3028 RTC driver");
++MODULE_LICENSE("GPL v2");
--- /dev/null
+From bfb96e21b688b5c798db9a6082ad76e72721693e Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 28 Mar 2019 13:13:52 +0000
+Subject: [PATCH 397/725] configs: Add RTC_DRV_RV3028=m
+
+See: https://github.com/raspberrypi/linux/issues/2912
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ 3 files changed, 3 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -1157,6 +1157,7 @@ CONFIG_RTC_DRV_FM3130=m
+ CONFIG_RTC_DRV_RX8581=m
+ CONFIG_RTC_DRV_RX8025=m
+ CONFIG_RTC_DRV_EM3027=m
++CONFIG_RTC_DRV_RV3028=m
+ CONFIG_RTC_DRV_M41T93=m
+ CONFIG_RTC_DRV_M41T94=m
+ CONFIG_RTC_DRV_DS1302=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -1150,6 +1150,7 @@ CONFIG_RTC_DRV_FM3130=m
+ CONFIG_RTC_DRV_RX8581=m
+ CONFIG_RTC_DRV_RX8025=m
+ CONFIG_RTC_DRV_EM3027=m
++CONFIG_RTC_DRV_RV3028=m
+ CONFIG_RTC_DRV_M41T93=m
+ CONFIG_RTC_DRV_M41T94=m
+ CONFIG_RTC_DRV_DS1302=m
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -1017,6 +1017,7 @@ CONFIG_RTC_DRV_FM3130=m
+ CONFIG_RTC_DRV_RX8581=m
+ CONFIG_RTC_DRV_RX8025=m
+ CONFIG_RTC_DRV_EM3027=m
++CONFIG_RTC_DRV_RV3028=m
+ CONFIG_RTC_DRV_M41T93=m
+ CONFIG_RTC_DRV_M41T94=m
+ CONFIG_RTC_DRV_DS1302=m
+++ /dev/null
-From a0019271c4c0b0a156770fdb53267010627f03b1 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 20 Mar 2019 10:06:51 +0000
-Subject: [PATCH 397/703] staging: bcm2835-codec: Refactor default resolution
- code
-
-The default resolution code was different for each role
-as compressed formats need to pass bytesperline as 0 and
-set up customised buffer sizes.
-This is common setup, therefore amend get_sizeimage and
-get_bytesperline to do the correct thing whether compressed
-or uncompressed.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c | 103 +++++++-----------
- 1 file changed, 40 insertions(+), 63 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -578,10 +578,17 @@ static void job_abort(void *priv)
- ctx->aborting = 1;
- }
-
--static inline unsigned int get_sizeimage(int bpl, int height,
-+static inline unsigned int get_sizeimage(int bpl, int width, int height,
- struct bcm2835_codec_fmt *fmt)
- {
-- return (bpl * height * fmt->size_multiplier_x2) >> 1;
-+ if (fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
-+ if (width * height > 1280 * 720)
-+ return DEF_COMP_BUF_SIZE_GREATER_720P;
-+ else
-+ return DEF_COMP_BUF_SIZE_720P_OR_LESS;
-+ } else {
-+ return (bpl * height * fmt->size_multiplier_x2) >> 1;
-+ }
- }
-
- static inline unsigned int get_bytesperline(int width,
-@@ -1032,22 +1039,13 @@ static int vidioc_try_fmt(struct v4l2_fo
- * some of the pixels are active.
- */
- f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
--
-- f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
-- fmt);
-- f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
-- f->fmt.pix.height,
-- fmt);
-- } else {
-- u32 min_size = f->fmt.pix.width > 1280 ||
-- f->fmt.pix.height > 720 ?
-- DEF_COMP_BUF_SIZE_GREATER_720P :
-- DEF_COMP_BUF_SIZE_720P_OR_LESS;
--
-- f->fmt.pix.bytesperline = 0;
-- if (f->fmt.pix.sizeimage < min_size)
-- f->fmt.pix.sizeimage = min_size;
- }
-+ f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
-+ fmt);
-+ f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
-+ f->fmt.pix.width,
-+ f->fmt.pix.height,
-+ fmt);
-
- f->fmt.pix.field = V4L2_FIELD_NONE;
-
-@@ -1159,6 +1157,7 @@ static int vidioc_s_fmt(struct bcm2835_c
- q_data_dst->bytesperline =
- get_bytesperline(f->fmt.pix.width, q_data_dst->fmt);
- q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
-+ q_data_dst->crop_width,
- q_data_dst->height,
- q_data_dst->fmt);
- update_capture_port = true;
-@@ -2218,52 +2217,30 @@ static int bcm2835_codec_open(struct fil
-
- ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
- ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
-- switch (dev->role) {
-- case DECODE:
-- /*
-- * Input width and height are irrelevant as they will be defined
-- * by the bitstream not the format. Required by V4L2 though.
-- */
-- ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
-- ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
-- ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
-- ctx->q_data[V4L2_M2M_SRC].bytesperline = 0;
-- ctx->q_data[V4L2_M2M_SRC].sizeimage =
-- DEF_COMP_BUF_SIZE_720P_OR_LESS;
--
-- ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
-- ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
-- ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
-- ctx->q_data[V4L2_M2M_DST].bytesperline =
-- get_bytesperline(DEFAULT_WIDTH,
-- ctx->q_data[V4L2_M2M_DST].fmt);
-- ctx->q_data[V4L2_M2M_DST].sizeimage =
-- get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
-- ctx->q_data[V4L2_M2M_DST].height,
-- ctx->q_data[V4L2_M2M_DST].fmt);
-- break;
-- case ENCODE:
-- ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
-- ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
-- ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
-- ctx->q_data[V4L2_M2M_SRC].bytesperline =
-- get_bytesperline(DEFAULT_WIDTH,
-- ctx->q_data[V4L2_M2M_SRC].fmt);
-- ctx->q_data[V4L2_M2M_SRC].sizeimage =
-- get_sizeimage(ctx->q_data[V4L2_M2M_SRC].bytesperline,
-- ctx->q_data[V4L2_M2M_SRC].height,
-- ctx->q_data[V4L2_M2M_SRC].fmt);
--
-- ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
-- ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
-- ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
-- ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
-- ctx->q_data[V4L2_M2M_DST].sizeimage =
-- DEF_COMP_BUF_SIZE_720P_OR_LESS;
-- break;
-- case ISP:
-- break;
-- }
-+
-+ ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
-+ ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
-+ ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
-+ ctx->q_data[V4L2_M2M_SRC].bytesperline =
-+ get_bytesperline(DEFAULT_WIDTH,
-+ ctx->q_data[V4L2_M2M_SRC].fmt);
-+ ctx->q_data[V4L2_M2M_SRC].sizeimage =
-+ get_sizeimage(ctx->q_data[V4L2_M2M_SRC].bytesperline,
-+ ctx->q_data[V4L2_M2M_SRC].crop_width,
-+ ctx->q_data[V4L2_M2M_SRC].height,
-+ ctx->q_data[V4L2_M2M_SRC].fmt);
-+
-+ ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
-+ ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
-+ ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
-+ ctx->q_data[V4L2_M2M_DST].bytesperline =
-+ get_bytesperline(DEFAULT_WIDTH,
-+ ctx->q_data[V4L2_M2M_DST].fmt);
-+ ctx->q_data[V4L2_M2M_DST].sizeimage =
-+ get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
-+ ctx->q_data[V4L2_M2M_DST].crop_width,
-+ ctx->q_data[V4L2_M2M_DST].height,
-+ ctx->q_data[V4L2_M2M_DST].fmt);
-
- ctx->colorspace = V4L2_COLORSPACE_REC709;
- ctx->bitrate = 10 * 1000 * 1000;
+++ /dev/null
-From 8d82ada47578fd867da43108fadcd77e3f57f056 Mon Sep 17 00:00:00 2001
-From: Alexandre Belloni <alexandre.belloni@bootlin.com>
-Date: Fri, 30 Nov 2018 11:53:20 +0000
-Subject: [PATCH 398/703] nvmem: add type attribute
-
-commit 16688453661b6d5159be558a1f8c1f54463a420f upstream.
-
-Add a type attribute so userspace is able to know how the data is stored as
-this can help taking the correct decision when selecting which device to
-use. This will also help program display the proper warnings when burning
-fuses for example.
-
-Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/nvmem/core.c | 21 +++++++++++++++++++++
- include/linux/nvmem-provider.h | 16 ++++++++++++++++
- 2 files changed, 37 insertions(+)
-
---- a/drivers/nvmem/core.c
-+++ b/drivers/nvmem/core.c
-@@ -36,6 +36,7 @@ struct nvmem_device {
- size_t size;
- bool read_only;
- int flags;
-+ enum nvmem_type type;
- struct bin_attribute eeprom;
- struct device *base_dev;
- nvmem_reg_read_t reg_read;
-@@ -84,6 +85,21 @@ static int nvmem_reg_write(struct nvmem_
- return -EINVAL;
- }
-
-+static ssize_t type_show(struct device *dev,
-+ struct device_attribute *attr, char *buf)
-+{
-+ struct nvmem_device *nvmem = to_nvmem_device(dev);
-+
-+ return sprintf(buf, "%s\n", nvmem_type_str[nvmem->type]);
-+}
-+
-+static DEVICE_ATTR_RO(type);
-+
-+static struct attribute *nvmem_attrs[] = {
-+ &dev_attr_type.attr,
-+ NULL,
-+};
-+
- static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
- char *buf, loff_t pos, size_t count)
-@@ -169,6 +185,7 @@ static struct bin_attribute *nvmem_bin_r
-
- static const struct attribute_group nvmem_bin_rw_group = {
- .bin_attrs = nvmem_bin_rw_attributes,
-+ .attrs = nvmem_attrs,
- };
-
- static const struct attribute_group *nvmem_rw_dev_groups[] = {
-@@ -192,6 +209,7 @@ static struct bin_attribute *nvmem_bin_r
-
- static const struct attribute_group nvmem_bin_ro_group = {
- .bin_attrs = nvmem_bin_ro_attributes,
-+ .attrs = nvmem_attrs,
- };
-
- static const struct attribute_group *nvmem_ro_dev_groups[] = {
-@@ -216,6 +234,7 @@ static struct bin_attribute *nvmem_bin_r
-
- static const struct attribute_group nvmem_bin_rw_root_group = {
- .bin_attrs = nvmem_bin_rw_root_attributes,
-+ .attrs = nvmem_attrs,
- };
-
- static const struct attribute_group *nvmem_rw_root_dev_groups[] = {
-@@ -239,6 +258,7 @@ static struct bin_attribute *nvmem_bin_r
-
- static const struct attribute_group nvmem_bin_ro_root_group = {
- .bin_attrs = nvmem_bin_ro_root_attributes,
-+ .attrs = nvmem_attrs,
- };
-
- static const struct attribute_group *nvmem_ro_root_dev_groups[] = {
-@@ -478,6 +498,7 @@ struct nvmem_device *nvmem_register(cons
- nvmem->dev.bus = &nvmem_bus_type;
- nvmem->dev.parent = config->dev;
- nvmem->priv = config->priv;
-+ nvmem->type = config->type;
- nvmem->reg_read = config->reg_read;
- nvmem->reg_write = config->reg_write;
- nvmem->dev.of_node = config->dev->of_node;
---- a/include/linux/nvmem-provider.h
-+++ b/include/linux/nvmem-provider.h
-@@ -22,6 +22,20 @@ typedef int (*nvmem_reg_read_t)(void *pr
- typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
- void *val, size_t bytes);
-
-+enum nvmem_type {
-+ NVMEM_TYPE_UNKNOWN = 0,
-+ NVMEM_TYPE_EEPROM,
-+ NVMEM_TYPE_OTP,
-+ NVMEM_TYPE_BATTERY_BACKED,
-+};
-+
-+static const char * const nvmem_type_str[] = {
-+ [NVMEM_TYPE_UNKNOWN] = "Unknown",
-+ [NVMEM_TYPE_EEPROM] = "EEPROM",
-+ [NVMEM_TYPE_OTP] = "OTP",
-+ [NVMEM_TYPE_BATTERY_BACKED] = "Battery backed",
-+};
-+
- /**
- * struct nvmem_config - NVMEM device configuration
- *
-@@ -31,6 +45,7 @@ typedef int (*nvmem_reg_write_t)(void *p
- * @owner: Pointer to exporter module. Used for refcounting.
- * @cells: Optional array of pre-defined NVMEM cells.
- * @ncells: Number of elements in cells.
-+ * @type: Type of the nvmem storage
- * @read_only: Device is read-only.
- * @root_only: Device is accessibly to root only.
- * @reg_read: Callback to read data.
-@@ -54,6 +69,7 @@ struct nvmem_config {
- struct module *owner;
- const struct nvmem_cell_info *cells;
- int ncells;
-+ enum nvmem_type type;
- bool read_only;
- bool root_only;
- nvmem_reg_read_t reg_read;
--- /dev/null
+From cf17a30d916eedceda8a4be81259e3813c5a3490 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 28 Mar 2019 13:26:59 +0000
+Subject: [PATCH 398/725] overlays: Add rv3028 to i2c-rtc
+
+See: https://github.com/raspberrypi/linux/issues/2912
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README | 4 +++-
+ .../arm/boot/dts/overlays/i2c-rtc-overlay.dts | 19 ++++++++++++++++++-
+ 2 files changed, 21 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -939,6 +939,8 @@ Params: abx80x Select o
+
+ pcf8563 Select the PCF8563 device
+
++ rv3028 Select the Micro Crystal RV3028 device
++
+ addr Sets the address for the RTC. Note that the
+ device must be configured to use the specified
+ address.
+@@ -947,7 +949,7 @@ Params: abx80x Select o
+ "schottky" (ABx80x only)
+
+ trickle-resistor-ohms Resistor value for trickle charge (DS1339,
+- ABx80x)
++ ABx80x, RV3028)
+
+ wakeup-source Specify that the RTC can be used as a wakeup
+ source
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -158,6 +158,21 @@
+ };
+ };
+
++ fragment@10 {
++ target = <&i2c_arm>;
++ __dormant__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ rv3028: rv3028@52 {
++ compatible = "microcrystal,rv3028";
++ reg = <0x52>;
++ status = "okay";
++ };
++ };
++ };
++
+ __overrides__ {
+ abx80x = <0>,"+0";
+ ds1307 = <0>,"+1";
+@@ -169,6 +184,7 @@
+ pcf8523 = <0>,"+7";
+ pcf8563 = <0>,"+8";
+ m41t62 = <0>,"+9";
++ rv3028 = <0>,"+10";
+
+ addr = <&abx80x>, "reg:0",
+ <&ds1307>, "reg:0",
+@@ -182,7 +198,8 @@
+ <&m41t62>, "reg:0";
+ trickle-diode-type = <&abx80x>,"abracon,tc-diode";
+ trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0",
+- <&abx80x>,"abracon,tc-resistor";
++ <&abx80x>,"abracon,tc-resistor",
++ <&rv3028>,"trickle-resistor-ohms:0";
+ wakeup-source = <&ds1339>,"wakeup-source?",
+ <&ds3231>,"wakeup-source?",
+ <&mcp7940x>,"wakeup-source?",
--- /dev/null
+From aa84e9cf563d82701357486ed17fd390fe28e692 Mon Sep 17 00:00:00 2001
+From: b-ak <anur.bhargav@gmail.com>
+Date: Wed, 9 Jan 2019 22:41:21 +0530
+Subject: [PATCH 399/725] ASoC: tlv320aic32x4: SND_SOC_DAPM_MICBIAS is
+ deprecated
+
+commit 04d979d7a7bac2f645cd827ea37e5ffa5b4e1f97 upstream.
+
+SND_SOC_DAPM_MICBIAS is deprecated, replace it with SND_SOC_DAPM_SUPPLY.
+
+MICBIAS voltage wasn't supplied to the microphone with the older
+SND_SOC_DAPM_MICBIAS widget, hence the microphone wouldn't work.
+
+This patch fixes the problem.
+
+Signed-off-by: b-ak <anur.bhargav@gmail.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 30 +++++++++++++++++++++++++++++-
+ sound/soc/codecs/tlv320aic32x4.h | 1 +
+ 2 files changed, 30 insertions(+), 1 deletion(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -79,6 +79,32 @@ struct aic32x4_priv {
+ struct device *dev;
+ };
+
++static int mic_bias_event(struct snd_soc_dapm_widget *w,
++ struct snd_kcontrol *kcontrol, int event)
++{
++ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
++
++ switch (event) {
++ case SND_SOC_DAPM_POST_PMU:
++ /* Change Mic Bias Registor */
++ snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
++ AIC32x4_MICBIAS_MASK,
++ AIC32X4_MICBIAS_LDOIN |
++ AIC32X4_MICBIAS_2075V);
++ printk(KERN_DEBUG "%s: Mic Bias will be turned ON\n", __func__);
++ break;
++ case SND_SOC_DAPM_PRE_PMD:
++ snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
++ AIC32x4_MICBIAS_MASK, 0);
++ printk(KERN_DEBUG "%s: Mic Bias will be turned OFF\n",
++ __func__);
++ break;
++ }
++
++ return 0;
++}
++
++
+ static int aic32x4_get_mfp1_gpio(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -450,7 +476,9 @@ static const struct snd_soc_dapm_widget
+ SND_SOC_DAPM_MUX("IN3_R to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
+ in3r_to_lmixer_controls),
+
+- SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0),
++ SND_SOC_DAPM_SUPPLY("Mic Bias", AIC32X4_MICBIAS, 6, 0, mic_bias_event,
++ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
++
+
+ SND_SOC_DAPM_OUTPUT("HPL"),
+ SND_SOC_DAPM_OUTPUT("HPR"),
+--- a/sound/soc/codecs/tlv320aic32x4.h
++++ b/sound/soc/codecs/tlv320aic32x4.h
+@@ -195,6 +195,7 @@ int aic32x4_remove(struct device *dev);
+ /* AIC32X4_MICBIAS */
+ #define AIC32X4_MICBIAS_LDOIN BIT(3)
+ #define AIC32X4_MICBIAS_2075V 0x60
++#define AIC32x4_MICBIAS_MASK GENMASK(6, 3)
+
+ /* AIC32X4_LMICPGANIN */
+ #define AIC32X4_LMICPGANIN_IN2R_10K 0x10
+++ /dev/null
-From f2e44f13f6524a60c5d3c1395ba3e323f72eff6d Mon Sep 17 00:00:00 2001
-From: Alexandre Belloni <alexandre.belloni@bootlin.com>
-Date: Wed, 13 Feb 2019 00:21:36 +0100
-Subject: [PATCH 399/703] rtc: rv3028: add new driver
-
-upstream commit e6e7376cfd7b3f9b63de3a22792f64d9bfb2ab53.
-
-Add a driver for the MicroCrystal RV-3028. It is a SMT Real-Time Clock
-Module that incorporates an integrated CMOS circuit together with an XTAL.
-It has an i2c interface.
-
-The driver handles date/time, alarms, trickle charging, timestamping,
-frequency offset correction, EEPROM and NVRAM.
-
-Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
----
- Documentation/devicetree/bindings/rtc/rtc.txt | 69 ++
- drivers/rtc/Kconfig | 9 +
- drivers/rtc/Makefile | 1 +
- drivers/rtc/rtc-rv3028.c | 733 ++++++++++++++++++
- 4 files changed, 812 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/rtc/rtc.txt
- create mode 100644 drivers/rtc/rtc-rv3028.c
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/rtc/rtc.txt
-@@ -0,0 +1,69 @@
-+Generic device tree bindings for Real Time Clock devices
-+========================================================
-+
-+This document describes generic bindings which can be used to describe Real Time
-+Clock devices in a device tree.
-+
-+Required properties
-+-------------------
-+
-+- compatible : name of RTC device following generic names recommended practice.
-+
-+For other required properties e.g. to describe register sets,
-+clocks, etc. check the binding documentation of the specific driver.
-+
-+Optional properties
-+-------------------
-+
-+- start-year : if provided, the default hardware range supported by the RTC is
-+ shifted so the first usable year is the specified one.
-+
-+The following properties may not be supported by all drivers. However, if a
-+driver wants to support one of the below features, it should adapt the bindings
-+below.
-+- trickle-resistor-ohms : Selected resistor for trickle charger. Should be given
-+ if trickle charger should be enabled
-+- trickle-diode-disable : Do not use internal trickle charger diode Should be
-+ given if internal trickle charger diode should be
-+ disabled
-+- wakeup-source : Enables wake up of host system on alarm
-+- quartz-load-femtofarads : The capacitive load of the quartz(x-tal),
-+ expressed in femto Farad (fF).
-+ The default value shall be listed (if optional),
-+ and likewise all valid values.
-+
-+Trivial RTCs
-+------------
-+
-+This is a list of trivial RTC devices that have simple device tree
-+bindings, consisting only of a compatible field, an address and
-+possibly an interrupt line.
-+
-+
-+Compatible Vendor / Chip
-+========== =============
-+abracon,abb5zes3 AB-RTCMC-32.768kHz-B5ZE-S3: Real Time Clock/Calendar Module with I2C Interface
-+dallas,ds1374 I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output
-+dallas,ds1672 Dallas DS1672 Real-time Clock
-+dallas,ds3232 Extremely Accurate I²C RTC with Integrated Crystal and SRAM
-+epson,rx8010 I2C-BUS INTERFACE REAL TIME CLOCK MODULE
-+epson,rx8581 I2C-BUS INTERFACE REAL TIME CLOCK MODULE
-+emmicro,em3027 EM Microelectronic EM3027 Real-time Clock
-+isil,isl1208 Intersil ISL1208 Low Power RTC with Battery Backed SRAM
-+isil,isl1218 Intersil ISL1218 Low Power RTC with Battery Backed SRAM
-+isil,isl12022 Intersil ISL12022 Real-time Clock
-+microcrystal,rv3028 Real Time Clock Module with I2C-Bus
-+microcrystal,rv3029 Real Time Clock Module with I2C-Bus
-+microcrystal,rv8523 Real Time Clock
-+nxp,pcf2127 Real-time clock
-+nxp,pcf2129 Real-time clock
-+nxp,pcf8563 Real-time clock/calendar
-+pericom,pt7c4338 Real-time Clock Module
-+ricoh,r2025sd I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-+ricoh,r2221tl I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-+ricoh,rs5c372a I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-+ricoh,rs5c372b I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-+ricoh,rv5c386 I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-+ricoh,rv5c387a I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
-+sii,s35390a 2-wire CMOS real-time clock
-+whwave,sd3078 I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
---- a/drivers/rtc/Kconfig
-+++ b/drivers/rtc/Kconfig
-@@ -625,6 +625,15 @@ config RTC_DRV_EM3027
- This driver can also be built as a module. If so, the module
- will be called rtc-em3027.
-
-+config RTC_DRV_RV3028
-+ tristate "Micro Crystal RV3028"
-+ help
-+ If you say yes here you get support for the Micro Crystal
-+ RV3028.
-+
-+ This driver can also be built as a module. If so, the module
-+ will be called rtc-rv3028.
-+
- config RTC_DRV_RV8803
- tristate "Micro Crystal RV8803, Epson RX8900"
- help
---- a/drivers/rtc/Makefile
-+++ b/drivers/rtc/Makefile
-@@ -136,6 +136,7 @@ obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5
- obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
- obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
- obj-$(CONFIG_RTC_DRV_RTD119X) += rtc-rtd119x.o
-+obj-$(CONFIG_RTC_DRV_RV3028) += rtc-rv3028.o
- obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o
- obj-$(CONFIG_RTC_DRV_RV8803) += rtc-rv8803.o
- obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o
---- /dev/null
-+++ b/drivers/rtc/rtc-rv3028.c
-@@ -0,0 +1,733 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * RTC driver for the Micro Crystal RV3028
-+ *
-+ * Copyright (C) 2019 Micro Crystal SA
-+ *
-+ * Alexandre Belloni <alexandre.belloni@bootlin.com>
-+ *
-+ */
-+
-+#include <linux/bcd.h>
-+#include <linux/bitops.h>
-+#include <linux/i2c.h>
-+#include <linux/interrupt.h>
-+#include <linux/kernel.h>
-+#include <linux/log2.h>
-+#include <linux/module.h>
-+#include <linux/of_device.h>
-+#include <linux/regmap.h>
-+#include <linux/rtc.h>
-+#include "rtc-core.h"
-+
-+#define RV3028_SEC 0x00
-+#define RV3028_MIN 0x01
-+#define RV3028_HOUR 0x02
-+#define RV3028_WDAY 0x03
-+#define RV3028_DAY 0x04
-+#define RV3028_MONTH 0x05
-+#define RV3028_YEAR 0x06
-+#define RV3028_ALARM_MIN 0x07
-+#define RV3028_ALARM_HOUR 0x08
-+#define RV3028_ALARM_DAY 0x09
-+#define RV3028_STATUS 0x0E
-+#define RV3028_CTRL1 0x0F
-+#define RV3028_CTRL2 0x10
-+#define RV3028_EVT_CTRL 0x13
-+#define RV3028_TS_COUNT 0x14
-+#define RV3028_TS_SEC 0x15
-+#define RV3028_RAM1 0x1F
-+#define RV3028_EEPROM_ADDR 0x25
-+#define RV3028_EEPROM_DATA 0x26
-+#define RV3028_EEPROM_CMD 0x27
-+#define RV3028_CLKOUT 0x35
-+#define RV3028_OFFSET 0x36
-+#define RV3028_BACKUP 0x37
-+
-+#define RV3028_STATUS_PORF BIT(0)
-+#define RV3028_STATUS_EVF BIT(1)
-+#define RV3028_STATUS_AF BIT(2)
-+#define RV3028_STATUS_TF BIT(3)
-+#define RV3028_STATUS_UF BIT(4)
-+#define RV3028_STATUS_BSF BIT(5)
-+#define RV3028_STATUS_CLKF BIT(6)
-+#define RV3028_STATUS_EEBUSY BIT(7)
-+
-+#define RV3028_CTRL1_EERD BIT(3)
-+#define RV3028_CTRL1_WADA BIT(5)
-+
-+#define RV3028_CTRL2_RESET BIT(0)
-+#define RV3028_CTRL2_12_24 BIT(1)
-+#define RV3028_CTRL2_EIE BIT(2)
-+#define RV3028_CTRL2_AIE BIT(3)
-+#define RV3028_CTRL2_TIE BIT(4)
-+#define RV3028_CTRL2_UIE BIT(5)
-+#define RV3028_CTRL2_TSE BIT(7)
-+
-+#define RV3028_EVT_CTRL_TSR BIT(2)
-+
-+#define RV3028_EEPROM_CMD_WRITE 0x21
-+#define RV3028_EEPROM_CMD_READ 0x22
-+
-+#define RV3028_EEBUSY_POLL 10000
-+#define RV3028_EEBUSY_TIMEOUT 100000
-+
-+#define RV3028_BACKUP_TCE BIT(5)
-+#define RV3028_BACKUP_TCR_MASK GENMASK(1,0)
-+
-+#define OFFSET_STEP_PPT 953674
-+
-+enum rv3028_type {
-+ rv_3028,
-+};
-+
-+struct rv3028_data {
-+ struct regmap *regmap;
-+ struct rtc_device *rtc;
-+ enum rv3028_type type;
-+};
-+
-+static u16 rv3028_trickle_resistors[] = {1000, 3000, 6000, 11000};
-+
-+static ssize_t timestamp0_store(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
-+
-+ regmap_update_bits(rv3028->regmap, RV3028_EVT_CTRL, RV3028_EVT_CTRL_TSR,
-+ RV3028_EVT_CTRL_TSR);
-+
-+ return count;
-+};
-+
-+static ssize_t timestamp0_show(struct device *dev,
-+ struct device_attribute *attr, char *buf)
-+{
-+ struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
-+ struct rtc_time tm;
-+ int ret, count;
-+ u8 date[6];
-+
-+ ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count);
-+ if (ret)
-+ return ret;
-+
-+ if (!count)
-+ return 0;
-+
-+ ret = regmap_bulk_read(rv3028->regmap, RV3028_TS_SEC, date,
-+ sizeof(date));
-+ if (ret)
-+ return ret;
-+
-+ tm.tm_sec = bcd2bin(date[0]);
-+ tm.tm_min = bcd2bin(date[1]);
-+ tm.tm_hour = bcd2bin(date[2]);
-+ tm.tm_mday = bcd2bin(date[3]);
-+ tm.tm_mon = bcd2bin(date[4]) - 1;
-+ tm.tm_year = bcd2bin(date[5]) + 100;
-+
-+ ret = rtc_valid_tm(&tm);
-+ if (ret)
-+ return ret;
-+
-+ return sprintf(buf, "%llu\n",
-+ (unsigned long long)rtc_tm_to_time64(&tm));
-+};
-+
-+static DEVICE_ATTR_RW(timestamp0);
-+
-+static ssize_t timestamp0_count_show(struct device *dev,
-+ struct device_attribute *attr, char *buf)
-+{
-+ struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
-+ int ret, count;
-+
-+ ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count);
-+ if (ret)
-+ return ret;
-+
-+ return sprintf(buf, "%u\n", count);
-+};
-+
-+static DEVICE_ATTR_RO(timestamp0_count);
-+
-+static struct attribute *rv3028_attrs[] = {
-+ &dev_attr_timestamp0.attr,
-+ &dev_attr_timestamp0_count.attr,
-+ NULL
-+};
-+
-+static const struct attribute_group rv3028_attr_group = {
-+ .attrs = rv3028_attrs,
-+};
-+
-+static irqreturn_t rv3028_handle_irq(int irq, void *dev_id)
-+{
-+ struct rv3028_data *rv3028 = dev_id;
-+ unsigned long events = 0;
-+ u32 status = 0, ctrl = 0;
-+
-+ if (regmap_read(rv3028->regmap, RV3028_STATUS, &status) < 0 ||
-+ status == 0) {
-+ return IRQ_NONE;
-+ }
-+
-+ if (status & RV3028_STATUS_PORF)
-+ dev_warn(&rv3028->rtc->dev, "Voltage low, data loss detected.\n");
-+
-+ if (status & RV3028_STATUS_TF) {
-+ status |= RV3028_STATUS_TF;
-+ ctrl |= RV3028_CTRL2_TIE;
-+ events |= RTC_PF;
-+ }
-+
-+ if (status & RV3028_STATUS_AF) {
-+ status |= RV3028_STATUS_AF;
-+ ctrl |= RV3028_CTRL2_AIE;
-+ events |= RTC_AF;
-+ }
-+
-+ if (status & RV3028_STATUS_UF) {
-+ status |= RV3028_STATUS_UF;
-+ ctrl |= RV3028_CTRL2_UIE;
-+ events |= RTC_UF;
-+ }
-+
-+ if (events) {
-+ rtc_update_irq(rv3028->rtc, 1, events);
-+ regmap_update_bits(rv3028->regmap, RV3028_STATUS, status, 0);
-+ regmap_update_bits(rv3028->regmap, RV3028_CTRL2, ctrl, 0);
-+ }
-+
-+ if (status & RV3028_STATUS_EVF) {
-+ sysfs_notify(&rv3028->rtc->dev.kobj, NULL,
-+ dev_attr_timestamp0.attr.name);
-+ dev_warn(&rv3028->rtc->dev, "event detected");
-+ }
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static int rv3028_get_time(struct device *dev, struct rtc_time *tm)
-+{
-+ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+ u8 date[7];
-+ int ret, status;
-+
-+ ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
-+ if (ret < 0)
-+ return ret;
-+
-+ if (status & RV3028_STATUS_PORF) {
-+ dev_warn(dev, "Voltage low, data is invalid.\n");
-+ return -EINVAL;
-+ }
-+
-+ ret = regmap_bulk_read(rv3028->regmap, RV3028_SEC, date, sizeof(date));
-+ if (ret)
-+ return ret;
-+
-+ tm->tm_sec = bcd2bin(date[RV3028_SEC] & 0x7f);
-+ tm->tm_min = bcd2bin(date[RV3028_MIN] & 0x7f);
-+ tm->tm_hour = bcd2bin(date[RV3028_HOUR] & 0x3f);
-+ tm->tm_wday = ilog2(date[RV3028_WDAY] & 0x7f);
-+ tm->tm_mday = bcd2bin(date[RV3028_DAY] & 0x3f);
-+ tm->tm_mon = bcd2bin(date[RV3028_MONTH] & 0x1f) - 1;
-+ tm->tm_year = bcd2bin(date[RV3028_YEAR]) + 100;
-+
-+ return 0;
-+}
-+
-+static int rv3028_set_time(struct device *dev, struct rtc_time *tm)
-+{
-+ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+ u8 date[7];
-+ int ret;
-+
-+ date[RV3028_SEC] = bin2bcd(tm->tm_sec);
-+ date[RV3028_MIN] = bin2bcd(tm->tm_min);
-+ date[RV3028_HOUR] = bin2bcd(tm->tm_hour);
-+ date[RV3028_WDAY] = 1 << (tm->tm_wday);
-+ date[RV3028_DAY] = bin2bcd(tm->tm_mday);
-+ date[RV3028_MONTH] = bin2bcd(tm->tm_mon + 1);
-+ date[RV3028_YEAR] = bin2bcd(tm->tm_year - 100);
-+
-+ /*
-+ * Writing to the Seconds register has the same effect as setting RESET
-+ * bit to 1
-+ */
-+ ret = regmap_bulk_write(rv3028->regmap, RV3028_SEC, date,
-+ sizeof(date));
-+ if (ret)
-+ return ret;
-+
-+ ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
-+ RV3028_STATUS_PORF, 0);
-+
-+ return ret;
-+}
-+
-+static int rv3028_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-+{
-+ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+ u8 alarmvals[3];
-+ int status, ctrl, ret;
-+
-+ ret = regmap_bulk_read(rv3028->regmap, RV3028_ALARM_MIN, alarmvals,
-+ sizeof(alarmvals));
-+ if (ret)
-+ return ret;
-+
-+ ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = regmap_read(rv3028->regmap, RV3028_CTRL2, &ctrl);
-+ if (ret < 0)
-+ return ret;
-+
-+ alrm->time.tm_sec = 0;
-+ alrm->time.tm_min = bcd2bin(alarmvals[0] & 0x7f);
-+ alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
-+ alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f);
-+
-+ alrm->enabled = !!(ctrl & RV3028_CTRL2_AIE);
-+ alrm->pending = (status & RV3028_STATUS_AF) && alrm->enabled;
-+
-+ return 0;
-+}
-+
-+static int rv3028_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-+{
-+ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+ u8 alarmvals[3];
-+ u8 ctrl = 0;
-+ int ret;
-+
-+ /* The alarm has no seconds, round up to nearest minute */
-+ if (alrm->time.tm_sec) {
-+ time64_t alarm_time = rtc_tm_to_time64(&alrm->time);
-+
-+ alarm_time += 60 - alrm->time.tm_sec;
-+ rtc_time64_to_tm(alarm_time, &alrm->time);
-+ }
-+
-+ ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
-+ RV3028_CTRL2_AIE | RV3028_CTRL2_UIE, 0);
-+ if (ret)
-+ return ret;
-+
-+ alarmvals[0] = bin2bcd(alrm->time.tm_min);
-+ alarmvals[1] = bin2bcd(alrm->time.tm_hour);
-+ alarmvals[2] = bin2bcd(alrm->time.tm_mday);
-+
-+ ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
-+ RV3028_STATUS_AF, 0);
-+ if (ret)
-+ return ret;
-+
-+ ret = regmap_bulk_write(rv3028->regmap, RV3028_ALARM_MIN, alarmvals,
-+ sizeof(alarmvals));
-+ if (ret)
-+ return ret;
-+
-+ if (alrm->enabled) {
-+ if (rv3028->rtc->uie_rtctimer.enabled)
-+ ctrl |= RV3028_CTRL2_UIE;
-+ if (rv3028->rtc->aie_timer.enabled)
-+ ctrl |= RV3028_CTRL2_AIE;
-+ }
-+
-+ ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
-+ RV3028_CTRL2_UIE | RV3028_CTRL2_AIE, ctrl);
-+
-+ return ret;
-+}
-+
-+static int rv3028_alarm_irq_enable(struct device *dev, unsigned int enabled)
-+{
-+ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+ int ctrl = 0, ret;
-+
-+ if (enabled) {
-+ if (rv3028->rtc->uie_rtctimer.enabled)
-+ ctrl |= RV3028_CTRL2_UIE;
-+ if (rv3028->rtc->aie_timer.enabled)
-+ ctrl |= RV3028_CTRL2_AIE;
-+ }
-+
-+ ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
-+ RV3028_STATUS_AF | RV3028_STATUS_UF, 0);
-+ if (ret)
-+ return ret;
-+
-+ ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
-+ RV3028_CTRL2_UIE | RV3028_CTRL2_AIE, ctrl);
-+ if (ret)
-+ return ret;
-+
-+ return 0;
-+}
-+
-+static int rv3028_read_offset(struct device *dev, long *offset)
-+{
-+ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+ int ret, value, steps;
-+
-+ ret = regmap_read(rv3028->regmap, RV3028_OFFSET, &value);
-+ if (ret < 0)
-+ return ret;
-+
-+ steps = sign_extend32(value << 1, 8);
-+
-+ ret = regmap_read(rv3028->regmap, RV3028_BACKUP, &value);
-+ if (ret < 0)
-+ return ret;
-+
-+ steps += value >> 7;
-+
-+ *offset = DIV_ROUND_CLOSEST(steps * OFFSET_STEP_PPT, 1000);
-+
-+ return 0;
-+}
-+
-+static int rv3028_set_offset(struct device *dev, long offset)
-+{
-+ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+ int ret;
-+
-+ offset = clamp(offset, -244141L, 243187L) * 1000;
-+ offset = DIV_ROUND_CLOSEST(offset, OFFSET_STEP_PPT);
-+
-+ ret = regmap_write(rv3028->regmap, RV3028_OFFSET, offset >> 1);
-+ if (ret < 0)
-+ return ret;
-+
-+ return regmap_update_bits(rv3028->regmap, RV3028_BACKUP, BIT(7),
-+ offset << 7);
-+}
-+
-+static int rv3028_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
-+{
-+ struct rv3028_data *rv3028 = dev_get_drvdata(dev);
-+ int status, ret = 0;
-+
-+ switch (cmd) {
-+ case RTC_VL_READ:
-+ ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
-+ if (ret < 0)
-+ return ret;
-+
-+ if (status & RV3028_STATUS_PORF)
-+ dev_warn(&rv3028->rtc->dev, "Voltage low, data loss detected.\n");
-+
-+ status &= RV3028_STATUS_PORF;
-+
-+ if (copy_to_user((void __user *)arg, &status, sizeof(int)))
-+ return -EFAULT;
-+
-+ return 0;
-+
-+ case RTC_VL_CLR:
-+ ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
-+ RV3028_STATUS_PORF, 0);
-+
-+ return ret;
-+
-+ default:
-+ return -ENOIOCTLCMD;
-+ }
-+}
-+
-+static int rv3028_nvram_write(void *priv, unsigned int offset, void *val,
-+ size_t bytes)
-+{
-+ return regmap_bulk_write(priv, RV3028_RAM1 + offset, val, bytes);
-+}
-+
-+static int rv3028_nvram_read(void *priv, unsigned int offset, void *val,
-+ size_t bytes)
-+{
-+ return regmap_bulk_read(priv, RV3028_RAM1 + offset, val, bytes);
-+}
-+
-+static int rv3028_eeprom_write(void *priv, unsigned int offset, void *val,
-+ size_t bytes)
-+{
-+ u32 status, ctrl1;
-+ int i, ret, err;
-+ u8 *buf = val;
-+
-+ ret = regmap_read(priv, RV3028_CTRL1, &ctrl1);
-+ if (ret)
-+ return ret;
-+
-+ if (!(ctrl1 & RV3028_CTRL1_EERD)) {
-+ ret = regmap_update_bits(priv, RV3028_CTRL1,
-+ RV3028_CTRL1_EERD, RV3028_CTRL1_EERD);
-+ if (ret)
-+ return ret;
-+
-+ ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
-+ !(status & RV3028_STATUS_EEBUSY),
-+ RV3028_EEBUSY_POLL,
-+ RV3028_EEBUSY_TIMEOUT);
-+ if (ret)
-+ goto restore_eerd;
-+ }
-+
-+ for (i = 0; i < bytes; i++) {
-+ ret = regmap_write(priv, RV3028_EEPROM_ADDR, offset + i);
-+ if (ret)
-+ goto restore_eerd;
-+
-+ ret = regmap_write(priv, RV3028_EEPROM_DATA, buf[i]);
-+ if (ret)
-+ goto restore_eerd;
-+
-+ ret = regmap_write(priv, RV3028_EEPROM_CMD, 0x0);
-+ if (ret)
-+ goto restore_eerd;
-+
-+ ret = regmap_write(priv, RV3028_EEPROM_CMD,
-+ RV3028_EEPROM_CMD_WRITE);
-+ if (ret)
-+ goto restore_eerd;
-+
-+ usleep_range(RV3028_EEBUSY_POLL, RV3028_EEBUSY_TIMEOUT);
-+
-+ ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
-+ !(status & RV3028_STATUS_EEBUSY),
-+ RV3028_EEBUSY_POLL,
-+ RV3028_EEBUSY_TIMEOUT);
-+ if (ret)
-+ goto restore_eerd;
-+ }
-+
-+restore_eerd:
-+ if (!(ctrl1 & RV3028_CTRL1_EERD))
-+ {
-+ err = regmap_update_bits(priv, RV3028_CTRL1, RV3028_CTRL1_EERD,
-+ 0);
-+ if (err && !ret)
-+ ret = err;
-+ }
-+
-+ return ret;
-+}
-+
-+static int rv3028_eeprom_read(void *priv, unsigned int offset, void *val,
-+ size_t bytes)
-+{
-+ u32 status, ctrl1, data;
-+ int i, ret, err;
-+ u8 *buf = val;
-+
-+ ret = regmap_read(priv, RV3028_CTRL1, &ctrl1);
-+ if (ret)
-+ return ret;
-+
-+ if (!(ctrl1 & RV3028_CTRL1_EERD)) {
-+ ret = regmap_update_bits(priv, RV3028_CTRL1,
-+ RV3028_CTRL1_EERD, RV3028_CTRL1_EERD);
-+ if (ret)
-+ return ret;
-+
-+ ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
-+ !(status & RV3028_STATUS_EEBUSY),
-+ RV3028_EEBUSY_POLL,
-+ RV3028_EEBUSY_TIMEOUT);
-+ if (ret)
-+ goto restore_eerd;
-+ }
-+
-+ for (i = 0; i < bytes; i++) {
-+ ret = regmap_write(priv, RV3028_EEPROM_ADDR, offset + i);
-+ if (ret)
-+ goto restore_eerd;
-+
-+ ret = regmap_write(priv, RV3028_EEPROM_CMD, 0x0);
-+ if (ret)
-+ goto restore_eerd;
-+
-+ ret = regmap_write(priv, RV3028_EEPROM_CMD,
-+ RV3028_EEPROM_CMD_READ);
-+ if (ret)
-+ goto restore_eerd;
-+
-+ ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
-+ !(status & RV3028_STATUS_EEBUSY),
-+ RV3028_EEBUSY_POLL,
-+ RV3028_EEBUSY_TIMEOUT);
-+ if (ret)
-+ goto restore_eerd;
-+
-+ ret = regmap_read(priv, RV3028_EEPROM_DATA, &data);
-+ if (ret)
-+ goto restore_eerd;
-+ buf[i] = data;
-+ }
-+
-+restore_eerd:
-+ if (!(ctrl1 & RV3028_CTRL1_EERD))
-+ {
-+ err = regmap_update_bits(priv, RV3028_CTRL1, RV3028_CTRL1_EERD,
-+ 0);
-+ if (err && !ret)
-+ ret = err;
-+ }
-+
-+ return ret;
-+}
-+
-+static struct rtc_class_ops rv3028_rtc_ops = {
-+ .read_time = rv3028_get_time,
-+ .set_time = rv3028_set_time,
-+ .read_offset = rv3028_read_offset,
-+ .set_offset = rv3028_set_offset,
-+ .ioctl = rv3028_ioctl,
-+};
-+
-+static const struct regmap_config regmap_config = {
-+ .reg_bits = 8,
-+ .val_bits = 8,
-+ .max_register = 0x37,
-+};
-+
-+static int rv3028_probe(struct i2c_client *client)
-+{
-+ struct rv3028_data *rv3028;
-+ int ret, status;
-+ u32 ohms;
-+ struct nvmem_config nvmem_cfg = {
-+ .name = "rv3028_nvram",
-+ .word_size = 1,
-+ .stride = 1,
-+ .size = 2,
-+ .type = NVMEM_TYPE_BATTERY_BACKED,
-+ .reg_read = rv3028_nvram_read,
-+ .reg_write = rv3028_nvram_write,
-+ };
-+ struct nvmem_config eeprom_cfg = {
-+ .name = "rv3028_eeprom",
-+ .word_size = 1,
-+ .stride = 1,
-+ .size = 43,
-+ .type = NVMEM_TYPE_EEPROM,
-+ .reg_read = rv3028_eeprom_read,
-+ .reg_write = rv3028_eeprom_write,
-+ };
-+
-+ rv3028 = devm_kzalloc(&client->dev, sizeof(struct rv3028_data),
-+ GFP_KERNEL);
-+ if (!rv3028)
-+ return -ENOMEM;
-+
-+ rv3028->regmap = devm_regmap_init_i2c(client, ®map_config);
-+
-+ i2c_set_clientdata(client, rv3028);
-+
-+ ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
-+ if (ret < 0)
-+ return ret;
-+
-+ if (status & RV3028_STATUS_PORF)
-+ dev_warn(&client->dev, "Voltage low, data loss detected.\n");
-+
-+ if (status & RV3028_STATUS_AF)
-+ dev_warn(&client->dev, "An alarm may have been missed.\n");
-+
-+ rv3028->rtc = devm_rtc_allocate_device(&client->dev);
-+ if (IS_ERR(rv3028->rtc)) {
-+ return PTR_ERR(rv3028->rtc);
-+ }
-+
-+ if (client->irq > 0) {
-+ ret = devm_request_threaded_irq(&client->dev, client->irq,
-+ NULL, rv3028_handle_irq,
-+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-+ "rv3028", rv3028);
-+ if (ret) {
-+ dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
-+ client->irq = 0;
-+ } else {
-+ rv3028_rtc_ops.read_alarm = rv3028_get_alarm;
-+ rv3028_rtc_ops.set_alarm = rv3028_set_alarm;
-+ rv3028_rtc_ops.alarm_irq_enable = rv3028_alarm_irq_enable;
-+ }
-+ }
-+
-+ ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL1,
-+ RV3028_CTRL1_WADA, RV3028_CTRL1_WADA);
-+ if (ret)
-+ return ret;
-+
-+ /* setup timestamping */
-+ ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
-+ RV3028_CTRL2_EIE | RV3028_CTRL2_TSE,
-+ RV3028_CTRL2_EIE | RV3028_CTRL2_TSE);
-+ if (ret)
-+ return ret;
-+
-+ /* setup trickle charger */
-+ if (!device_property_read_u32(&client->dev, "trickle-resistor-ohms",
-+ &ohms)) {
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(rv3028_trickle_resistors); i++)
-+ if (ohms == rv3028_trickle_resistors[i])
-+ break;
-+
-+ if (i < ARRAY_SIZE(rv3028_trickle_resistors)) {
-+ ret = regmap_update_bits(rv3028->regmap, RV3028_BACKUP,
-+ RV3028_BACKUP_TCE |
-+ RV3028_BACKUP_TCR_MASK,
-+ RV3028_BACKUP_TCE | i);
-+ if (ret)
-+ return ret;
-+ } else {
-+ dev_warn(&client->dev, "invalid trickle resistor value\n");
-+ }
-+ }
-+
-+ ret = rtc_add_group(rv3028->rtc, &rv3028_attr_group);
-+ if (ret)
-+ return ret;
-+
-+ rv3028->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
-+ rv3028->rtc->range_max = RTC_TIMESTAMP_END_2099;
-+ rv3028->rtc->ops = &rv3028_rtc_ops;
-+ ret = rtc_register_device(rv3028->rtc);
-+ if (ret)
-+ return ret;
-+
-+ nvmem_cfg.priv = rv3028->regmap;
-+ rtc_nvmem_register(rv3028->rtc, &nvmem_cfg);
-+ eeprom_cfg.priv = rv3028->regmap;
-+ rtc_nvmem_register(rv3028->rtc, &eeprom_cfg);
-+
-+ rv3028->rtc->max_user_freq = 1;
-+
-+ return 0;
-+}
-+
-+static const struct of_device_id rv3028_of_match[] = {
-+ { .compatible = "microcrystal,rv3028", },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, rv3028_of_match);
-+
-+static struct i2c_driver rv3028_driver = {
-+ .driver = {
-+ .name = "rtc-rv3028",
-+ .of_match_table = of_match_ptr(rv3028_of_match),
-+ },
-+ .probe_new = rv3028_probe,
-+};
-+module_i2c_driver(rv3028_driver);
-+
-+MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>");
-+MODULE_DESCRIPTION("Micro Crystal RV3028 RTC driver");
-+MODULE_LICENSE("GPL v2");
--- /dev/null
+From b1658d7dba649351779a09c99c5db424f6a44ee1 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Mon, 18 Mar 2019 20:37:44 -0700
+Subject: [PATCH 400/725] ASoC: tlv320aic32x4: Break out clock setting into
+ separate function
+
+commit bf31cbfbe25001036e1e096b1c260bf871766ea5 upstream.
+
+Break the clock setting logic out from the main hw_params. It's
+rather large and unweildy and makes for a large function. This
+also better enables some of the following changes to the clock
+tree access in the driver.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 26 ++++++++++++++++++--------
+ 1 file changed, 18 insertions(+), 8 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -698,17 +698,13 @@ static int aic32x4_set_dai_fmt(struct sn
+ return 0;
+ }
+
+-static int aic32x4_hw_params(struct snd_pcm_substream *substream,
+- struct snd_pcm_hw_params *params,
+- struct snd_soc_dai *dai)
++static int aic32x4_setup_clocks(struct snd_soc_component *component,
++ unsigned int sample_rate,
++ unsigned int parent_rate)
+ {
+- struct snd_soc_component *component = dai->component;
+- struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
+- u8 iface1_reg = 0;
+- u8 dacsetup_reg = 0;
+ int i;
+
+- i = aic32x4_get_divs(aic32x4->sysclk, params_rate(params));
++ i = aic32x4_get_divs(parent_rate, sample_rate);
+ if (i < 0) {
+ printk(KERN_ERR "aic32x4: sampling rate not supported\n");
+ return i;
+@@ -765,6 +761,20 @@ static int aic32x4_hw_params(struct snd_
+ snd_soc_component_update_bits(component, AIC32X4_BCLKN,
+ AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
+
++ return 0;
++}
++
++static int aic32x4_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params,
++ struct snd_soc_dai *dai)
++{
++ struct snd_soc_component *component = dai->component;
++ struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
++ u8 iface1_reg = 0;
++ u8 dacsetup_reg = 0;
++
++ aic32x4_setup_clocks(component, params_rate(params), aic32x4->sysclk);
++
+ switch (params_width(params)) {
+ case 16:
+ iface1_reg |= (AIC32X4_WORD_LEN_16BITS <<
+++ /dev/null
-From 709dd35519e82a34da3fdbb9053f3173e7319167 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 28 Mar 2019 13:13:52 +0000
-Subject: [PATCH 400/703] configs: Add RTC_DRV_RV3028=m
-
-See: https://github.com/raspberrypi/linux/issues/2912
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- 3 files changed, 3 insertions(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -1157,6 +1157,7 @@ CONFIG_RTC_DRV_FM3130=m
- CONFIG_RTC_DRV_RX8581=m
- CONFIG_RTC_DRV_RX8025=m
- CONFIG_RTC_DRV_EM3027=m
-+CONFIG_RTC_DRV_RV3028=m
- CONFIG_RTC_DRV_M41T93=m
- CONFIG_RTC_DRV_M41T94=m
- CONFIG_RTC_DRV_DS1302=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -1150,6 +1150,7 @@ CONFIG_RTC_DRV_FM3130=m
- CONFIG_RTC_DRV_RX8581=m
- CONFIG_RTC_DRV_RX8025=m
- CONFIG_RTC_DRV_EM3027=m
-+CONFIG_RTC_DRV_RV3028=m
- CONFIG_RTC_DRV_M41T93=m
- CONFIG_RTC_DRV_M41T94=m
- CONFIG_RTC_DRV_DS1302=m
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -1017,6 +1017,7 @@ CONFIG_RTC_DRV_FM3130=m
- CONFIG_RTC_DRV_RX8581=m
- CONFIG_RTC_DRV_RX8025=m
- CONFIG_RTC_DRV_EM3027=m
-+CONFIG_RTC_DRV_RV3028=m
- CONFIG_RTC_DRV_M41T93=m
- CONFIG_RTC_DRV_M41T94=m
- CONFIG_RTC_DRV_DS1302=m
--- /dev/null
+From 09a140eacfbdb3d3b02f97ef6f226a00780f12ea Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 20 Mar 2019 19:38:44 -0700
+Subject: [PATCH 401/725] ASoC: tlv320aic32x4: Properly Set Processing Blocks
+
+commit c95e3a4b96293403a427b5185e60fad28af51fdd upstream.
+
+Different processing blocks are required for different sampling
+rates and power parameters. Set the processing blocks based
+on this information.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 56 ++++++++++++++++++++------------
+ 1 file changed, 36 insertions(+), 20 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -59,6 +59,8 @@ struct aic32x4_rate_divs {
+ u8 nadc;
+ u8 madc;
+ u8 blck_N;
++ u8 r_block;
++ u8 p_block;
+ };
+
+ struct aic32x4_priv {
+@@ -307,34 +309,34 @@ static const struct snd_kcontrol_new aic
+
+ static const struct aic32x4_rate_divs aic32x4_divs[] = {
+ /* 8k rate */
+- {12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24},
+- {24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24},
+- {25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24},
++ {12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24, 1, 1},
++ {24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24, 1, 1},
++ {25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24, 1, 1},
+ /* 11.025k rate */
+- {12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16},
+- {24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16},
++ {12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16, 1, 1},
++ {24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16, 1, 1},
+ /* 16k rate */
+- {12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12},
+- {24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12},
+- {25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12},
++ {12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12, 1, 1},
++ {24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12, 1, 1},
++ {25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12, 1, 1},
+ /* 22.05k rate */
+- {12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8},
+- {24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8},
+- {25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8},
++ {12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8, 1, 1},
++ {24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8, 1, 1},
++ {25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8, 1, 1},
+ /* 32k rate */
+- {12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6},
+- {24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6},
++ {12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6, 1, 1},
++ {24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6, 1, 1},
+ /* 44.1k rate */
+- {12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4},
+- {24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4},
+- {25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4},
++ {12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4, 1, 1},
++ {24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4, 1, 1},
++ {25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4, 1, 1},
+ /* 48k rate */
+- {12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4},
+- {24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4},
+- {25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4},
++ {12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4, 1, 1},
++ {24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4, 1, 1},
++ {25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4, 1, 1},
+
+ /* 96k rate */
+- {25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1},
++ {25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1, 1, 9},
+ };
+
+ static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
+@@ -698,6 +700,18 @@ static int aic32x4_set_dai_fmt(struct sn
+ return 0;
+ }
+
++static int aic32x4_set_processing_blocks(struct snd_soc_component *component,
++ u8 r_block, u8 p_block)
++{
++ if (r_block > 18 || p_block > 25)
++ return -EINVAL;
++
++ snd_soc_component_write(component, AIC32X4_ADCSPB, r_block);
++ snd_soc_component_write(component, AIC32X4_DACSPB, p_block);
++
++ return 0;
++}
++
+ static int aic32x4_setup_clocks(struct snd_soc_component *component,
+ unsigned int sample_rate,
+ unsigned int parent_rate)
+@@ -710,6 +724,8 @@ static int aic32x4_setup_clocks(struct s
+ return i;
+ }
+
++ aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
++
+ /* MCLK as PLL_CLKIN */
+ snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_PLL_CLKIN_MASK,
+ AIC32X4_PLL_CLKIN_MCLK << AIC32X4_PLL_CLKIN_SHIFT);
+++ /dev/null
-From 7eab8a839b1994c2b16c955af4ad805022acccb7 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 28 Mar 2019 13:26:59 +0000
-Subject: [PATCH 401/703] overlays: Add rv3028 to i2c-rtc
-
-See: https://github.com/raspberrypi/linux/issues/2912
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README | 4 +++-
- .../arm/boot/dts/overlays/i2c-rtc-overlay.dts | 19 ++++++++++++++++++-
- 2 files changed, 21 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -939,6 +939,8 @@ Params: abx80x Select o
-
- pcf8563 Select the PCF8563 device
-
-+ rv3028 Select the Micro Crystal RV3028 device
-+
- addr Sets the address for the RTC. Note that the
- device must be configured to use the specified
- address.
-@@ -947,7 +949,7 @@ Params: abx80x Select o
- "schottky" (ABx80x only)
-
- trickle-resistor-ohms Resistor value for trickle charge (DS1339,
-- ABx80x)
-+ ABx80x, RV3028)
-
- wakeup-source Specify that the RTC can be used as a wakeup
- source
---- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-@@ -158,6 +158,21 @@
- };
- };
-
-+ fragment@10 {
-+ target = <&i2c_arm>;
-+ __dormant__ {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "okay";
-+
-+ rv3028: rv3028@52 {
-+ compatible = "microcrystal,rv3028";
-+ reg = <0x52>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
- __overrides__ {
- abx80x = <0>,"+0";
- ds1307 = <0>,"+1";
-@@ -169,6 +184,7 @@
- pcf8523 = <0>,"+7";
- pcf8563 = <0>,"+8";
- m41t62 = <0>,"+9";
-+ rv3028 = <0>,"+10";
-
- addr = <&abx80x>, "reg:0",
- <&ds1307>, "reg:0",
-@@ -182,7 +198,8 @@
- <&m41t62>, "reg:0";
- trickle-diode-type = <&abx80x>,"abracon,tc-diode";
- trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0",
-- <&abx80x>,"abracon,tc-resistor";
-+ <&abx80x>,"abracon,tc-resistor",
-+ <&rv3028>,"trickle-resistor-ohms:0";
- wakeup-source = <&ds1339>,"wakeup-source?",
- <&ds3231>,"wakeup-source?",
- <&mcp7940x>,"wakeup-source?",
--- /dev/null
+From 721de503c943a8c9f0b957e27099c7b2ec38a37a Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:45 -0700
+Subject: [PATCH 402/725] ASoC: tlv320aic32x4: Model PLL in CCF
+
+commit 514b044cba667e4b7c383ec79b42b997e624b91d upstream.
+
+Model and manage the on-board PLL as a component in the Core
+Clock Framework. This should allow us to do some more complex
+clock management and power control. Also, some of the
+on-board chip clocks can be exposed to the outside, and this
+change will make those clocks easier to consume by other
+parts of the kernel.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/Kconfig | 1 +
+ sound/soc/codecs/Makefile | 2 +-
+ sound/soc/codecs/tlv320aic32x4-clk.c | 323 +++++++++++++++++++++++++++
+ sound/soc/codecs/tlv320aic32x4.c | 195 ++++++++--------
+ sound/soc/codecs/tlv320aic32x4.h | 5 +
+ 5 files changed, 431 insertions(+), 95 deletions(-)
+ create mode 100644 sound/soc/codecs/tlv320aic32x4-clk.c
+
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -1025,6 +1025,7 @@ config SND_SOC_TLV320AIC31XX
+
+ config SND_SOC_TLV320AIC32X4
+ tristate
++ depends on COMMON_CLK
+
+ config SND_SOC_TLV320AIC32X4_I2C
+ tristate "Texas Instruments TLV320AIC32x4 audio CODECs - I2C"
+--- a/sound/soc/codecs/Makefile
++++ b/sound/soc/codecs/Makefile
+@@ -182,7 +182,7 @@ snd-soc-tlv320aic23-i2c-objs := tlv320ai
+ snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o
+ snd-soc-tlv320aic26-objs := tlv320aic26.o
+ snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o
+-snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
++snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o tlv320aic32x4-clk.o
+ snd-soc-tlv320aic32x4-i2c-objs := tlv320aic32x4-i2c.o
+ snd-soc-tlv320aic32x4-spi-objs := tlv320aic32x4-spi.o
+ snd-soc-tlv320aic3x-objs := tlv320aic3x.o
+--- /dev/null
++++ b/sound/soc/codecs/tlv320aic32x4-clk.c
+@@ -0,0 +1,323 @@
++/* SPDX-License-Identifier: GPL-2.0
++ *
++ * Clock Tree for the Texas Instruments TLV320AIC32x4
++ *
++ * Copyright 2019 Annaliese McDermond
++ *
++ * Author: Annaliese McDermond <nh6z@nh6z.net>
++ */
++
++#include <linux/clk-provider.h>
++#include <linux/clkdev.h>
++#include <linux/regmap.h>
++#include <linux/device.h>
++
++#include "tlv320aic32x4.h"
++
++#define to_clk_aic32x4(_hw) container_of(_hw, struct clk_aic32x4, hw)
++struct clk_aic32x4 {
++ struct clk_hw hw;
++ struct device *dev;
++ struct regmap *regmap;
++ unsigned int reg;
++};
++
++/*
++ * struct clk_aic32x4_pll_muldiv - Multiplier/divider settings
++ * @p: Divider
++ * @r: first multiplier
++ * @j: integer part of second multiplier
++ * @d: decimal part of second multiplier
++ */
++struct clk_aic32x4_pll_muldiv {
++ u8 p;
++ u16 r;
++ u8 j;
++ u16 d;
++};
++
++struct aic32x4_clkdesc {
++ const char *name;
++ const char * const *parent_names;
++ unsigned int num_parents;
++ const struct clk_ops *ops;
++ unsigned int reg;
++};
++
++static int clk_aic32x4_pll_prepare(struct clk_hw *hw)
++{
++ struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
++
++ return regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
++ AIC32X4_PLLEN, AIC32X4_PLLEN);
++}
++
++static void clk_aic32x4_pll_unprepare(struct clk_hw *hw)
++{
++ struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
++
++ regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
++ AIC32X4_PLLEN, 0);
++}
++
++static int clk_aic32x4_pll_is_prepared(struct clk_hw *hw)
++{
++ struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
++
++ unsigned int val;
++ int ret;
++
++ ret = regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
++ if (ret < 0)
++ return ret;
++
++ return !!(val & AIC32X4_PLLEN);
++}
++
++static int clk_aic32x4_pll_get_muldiv(struct clk_aic32x4 *pll,
++ struct clk_aic32x4_pll_muldiv *settings)
++{
++ /* Change to use regmap_bulk_read? */
++ unsigned int val;
++ int ret;
++
++ ret = regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
++ if (ret)
++ return ret;
++ settings->r = val & AIC32X4_PLL_R_MASK;
++ settings->p = (val & AIC32X4_PLL_P_MASK) >> AIC32X4_PLL_P_SHIFT;
++
++ ret = regmap_read(pll->regmap, AIC32X4_PLLJ, &val);
++ if (ret < 0)
++ return ret;
++ settings->j = val;
++
++ ret = regmap_read(pll->regmap, AIC32X4_PLLDMSB, &val);
++ if (ret < 0)
++ return ret;
++ settings->d = val << 8;
++
++ ret = regmap_read(pll->regmap, AIC32X4_PLLDLSB, &val);
++ if (ret < 0)
++ return ret;
++ settings->d |= val;
++
++ return 0;
++}
++
++static int clk_aic32x4_pll_set_muldiv(struct clk_aic32x4 *pll,
++ struct clk_aic32x4_pll_muldiv *settings)
++{
++ int ret;
++ /* Change to use regmap_bulk_write for some if not all? */
++
++ ret = regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
++ AIC32X4_PLL_R_MASK, settings->r);
++ if (ret < 0)
++ return ret;
++
++ ret = regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
++ AIC32X4_PLL_P_MASK,
++ settings->p << AIC32X4_PLL_P_SHIFT);
++ if (ret < 0)
++ return ret;
++
++ ret = regmap_write(pll->regmap, AIC32X4_PLLJ, settings->j);
++ if (ret < 0)
++ return ret;
++
++ ret = regmap_write(pll->regmap, AIC32X4_PLLDMSB, (settings->d >> 8));
++ if (ret < 0)
++ return ret;
++ ret = regmap_write(pll->regmap, AIC32X4_PLLDLSB, (settings->d & 0xff));
++ if (ret < 0)
++ return ret;
++
++ return 0;
++}
++
++static unsigned long clk_aic32x4_pll_calc_rate(
++ struct clk_aic32x4_pll_muldiv *settings,
++ unsigned long parent_rate)
++{
++ u64 rate;
++ /*
++ * We scale j by 10000 to account for the decimal part of P and divide
++ * it back out later.
++ */
++ rate = (u64) parent_rate * settings->r *
++ ((settings->j * 10000) + settings->d);
++
++ return (unsigned long) DIV_ROUND_UP_ULL(rate, settings->p * 10000);
++}
++
++static int clk_aic32x4_pll_calc_muldiv(struct clk_aic32x4_pll_muldiv *settings,
++ unsigned long rate, unsigned long parent_rate)
++{
++ u64 multiplier;
++
++ settings->p = parent_rate / AIC32X4_MAX_PLL_CLKIN + 1;
++ if (settings->p > 8)
++ return -1;
++
++ /*
++ * We scale this figure by 10000 so that we can get the decimal part
++ * of the multiplier. This is because we can't do floating point
++ * math in the kernel.
++ */
++ multiplier = (u64) rate * settings->p * 10000;
++ do_div(multiplier, parent_rate);
++
++ /*
++ * J can't be over 64, so R can scale this.
++ * R can't be greater than 4.
++ */
++ settings->r = ((u32) multiplier / 640000) + 1;
++ if (settings->r > 4)
++ return -1;
++ do_div(multiplier, settings->r);
++
++ /*
++ * J can't be < 1.
++ */
++ if (multiplier < 10000)
++ return -1;
++
++ /* Figure out the integer part, J, and the fractional part, D. */
++ settings->j = (u32) multiplier / 10000;
++ settings->d = (u32) multiplier % 10000;
++
++ return 0;
++}
++
++static unsigned long clk_aic32x4_pll_recalc_rate(struct clk_hw *hw,
++ unsigned long parent_rate)
++{
++ struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
++ struct clk_aic32x4_pll_muldiv settings;
++ int ret;
++
++ ret = clk_aic32x4_pll_get_muldiv(pll, &settings);
++ if (ret < 0)
++ return 0;
++
++ return clk_aic32x4_pll_calc_rate(&settings, parent_rate);
++}
++
++static long clk_aic32x4_pll_round_rate(struct clk_hw *hw,
++ unsigned long rate,
++ unsigned long *parent_rate)
++{
++ struct clk_aic32x4_pll_muldiv settings;
++ int ret;
++
++ ret = clk_aic32x4_pll_calc_muldiv(&settings, rate, *parent_rate);
++ if (ret < 0)
++ return 0;
++
++ return clk_aic32x4_pll_calc_rate(&settings, *parent_rate);
++}
++
++static int clk_aic32x4_pll_set_rate(struct clk_hw *hw,
++ unsigned long rate,
++ unsigned long parent_rate)
++{
++ struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
++ struct clk_aic32x4_pll_muldiv settings;
++ int ret;
++
++ ret = clk_aic32x4_pll_calc_muldiv(&settings, rate, parent_rate);
++ if (ret < 0)
++ return -EINVAL;
++
++ return clk_aic32x4_pll_set_muldiv(pll, &settings);
++}
++
++static int clk_aic32x4_pll_set_parent(struct clk_hw *hw, u8 index)
++{
++ struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
++
++ return regmap_update_bits(pll->regmap,
++ AIC32X4_CLKMUX,
++ AIC32X4_PLL_CLKIN_MASK,
++ index << AIC32X4_PLL_CLKIN_SHIFT);
++}
++
++static u8 clk_aic32x4_pll_get_parent(struct clk_hw *hw)
++{
++ struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
++ unsigned int val;
++
++ regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
++
++ return (val & AIC32X4_PLL_CLKIN_MASK) >> AIC32X4_PLL_CLKIN_SHIFT;
++}
++
++
++static const struct clk_ops aic32x4_pll_ops = {
++ .prepare = clk_aic32x4_pll_prepare,
++ .unprepare = clk_aic32x4_pll_unprepare,
++ .is_prepared = clk_aic32x4_pll_is_prepared,
++ .recalc_rate = clk_aic32x4_pll_recalc_rate,
++ .round_rate = clk_aic32x4_pll_round_rate,
++ .set_rate = clk_aic32x4_pll_set_rate,
++ .set_parent = clk_aic32x4_pll_set_parent,
++ .get_parent = clk_aic32x4_pll_get_parent,
++};
++
++static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
++ {
++ .name = "pll",
++ .parent_names =
++ (const char* []) { "mclk", "bclk", "gpio", "din" },
++ .num_parents = 4,
++ .ops = &aic32x4_pll_ops,
++ .reg = 0,
++ },
++};
++
++static struct clk *aic32x4_register_clk(struct device *dev,
++ struct aic32x4_clkdesc *desc)
++{
++ struct clk_init_data init;
++ struct clk_aic32x4 *priv;
++ const char *devname = dev_name(dev);
++
++ init.ops = desc->ops;
++ init.name = desc->name;
++ init.parent_names = desc->parent_names;
++ init.num_parents = desc->num_parents;
++ init.flags = 0;
++
++ priv = devm_kzalloc(dev, sizeof(struct clk_aic32x4), GFP_KERNEL);
++ if (priv == NULL)
++ return (struct clk *) -ENOMEM;
++
++ priv->dev = dev;
++ priv->hw.init = &init;
++ priv->regmap = dev_get_regmap(dev, NULL);
++ priv->reg = desc->reg;
++
++ clk_hw_register_clkdev(&priv->hw, desc->name, devname);
++ return devm_clk_register(dev, &priv->hw);
++}
++
++int aic32x4_register_clocks(struct device *dev, const char *mclk_name)
++{
++ int i;
++
++ /*
++ * These lines are here to preserve the current functionality of
++ * the driver with regard to the DT. These should eventually be set
++ * by DT nodes so that the connections can be set up in configuration
++ * rather than code.
++ */
++ aic32x4_clkdesc_array[0].parent_names =
++ (const char* []) { mclk_name, "bclk", "gpio", "din" };
++
++ for (i = 0; i < ARRAY_SIZE(aic32x4_clkdesc_array); ++i)
++ aic32x4_register_clk(dev, &aic32x4_clkdesc_array[i]);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(aic32x4_register_clocks);
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -14,7 +14,7 @@
+ *
+ * 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
++ * 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
+@@ -33,6 +33,7 @@
+ #include <linux/cdev.h>
+ #include <linux/slab.h>
+ #include <linux/clk.h>
++#include <linux/of_clk.h>
+ #include <linux/regulator/consumer.h>
+
+ #include <sound/tlv320aic32x4.h>
+@@ -49,9 +50,7 @@
+ struct aic32x4_rate_divs {
+ u32 mclk;
+ u32 rate;
+- u8 p_val;
+- u8 pll_j;
+- u16 pll_d;
++ unsigned long pll_rate;
+ u16 dosr;
+ u8 ndac;
+ u8 mdac;
+@@ -71,6 +70,7 @@ struct aic32x4_priv {
+ bool swapdacs;
+ int rstn_gpio;
+ struct clk *mclk;
++ const char *mclk_name;
+
+ struct regulator *supply_ldo;
+ struct regulator *supply_iov;
+@@ -309,34 +309,34 @@ static const struct snd_kcontrol_new aic
+
+ static const struct aic32x4_rate_divs aic32x4_divs[] = {
+ /* 8k rate */
+- {12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24, 1, 1},
+- {24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24, 1, 1},
+- {25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24, 1, 1},
++ { 12000000, 8000, 57120000, 768, 5, 3, 128, 5, 18, 24, 1, 1 },
++ { 24000000, 8000, 57120000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
++ { 25000000, 8000, 32620000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
+ /* 11.025k rate */
+- {12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16, 1, 1},
+- {24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16, 1, 1},
++ { 12000000, 11025, 44217600, 512, 8, 2, 128, 8, 8, 16, 1, 1 },
++ { 24000000, 11025, 44217600, 512, 16, 1, 64, 32, 4, 16, 1, 1 },
+ /* 16k rate */
+- {12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12, 1, 1},
+- {24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12, 1, 1},
+- {25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12, 1, 1},
++ { 12000000, 16000, 57120000, 384, 5, 3, 128, 5, 9, 12, 1, 1 },
++ { 24000000, 16000, 57120000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
++ { 25000000, 16000, 32620000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
+ /* 22.05k rate */
+- {12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8, 1, 1},
+- {24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8, 1, 1},
+- {25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8, 1, 1},
++ { 12000000, 22050, 44217600, 256, 4, 4, 128, 4, 8, 8, 1, 1 },
++ { 24000000, 22050, 44217600, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
++ { 25000000, 22050, 19713750, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
+ /* 32k rate */
+- {12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6, 1, 1},
+- {24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6, 1, 1},
++ { 12000000, 32000, 14112000, 192, 2, 7, 64, 2, 21, 6, 1, 1 },
++ { 24000000, 32000, 14112000, 192, 7, 2, 64, 7, 6, 6, 1, 1 },
+ /* 44.1k rate */
+- {12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4, 1, 1},
+- {24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4, 1, 1},
+- {25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4, 1, 1},
++ { 12000000, 44100, 44217600, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
++ { 24000000, 44100, 44217600, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
++ { 25000000, 44100, 19713750, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
+ /* 48k rate */
+- {12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4, 1, 1},
+- {24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4, 1, 1},
+- {25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4, 1, 1},
++ { 12000000, 48000, 18432000, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
++ { 24000000, 48000, 18432000, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
++ { 25000000, 48000, 75626250, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
+
+ /* 96k rate */
+- {25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1, 1, 9},
++ { 25000000, 96000, 75626250, 64, 4, 4, 64, 4, 4, 1, 1, 9 },
+ };
+
+ static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
+@@ -393,7 +393,7 @@ static const struct snd_kcontrol_new in3
+ SOC_DAPM_ENUM("IN3_R L- Switch", in3r_lpga_n_enum),
+ };
+
+-/* Right mixer pins */
++/* Right mixer pins */
+ static SOC_ENUM_SINGLE_DECL(in1r_rpga_p_enum, AIC32X4_RMICPGAPIN, 6, resistor_text);
+ static SOC_ENUM_SINGLE_DECL(in2r_rpga_p_enum, AIC32X4_RMICPGAPIN, 4, resistor_text);
+ static SOC_ENUM_SINGLE_DECL(in3r_rpga_p_enum, AIC32X4_RMICPGAPIN, 2, resistor_text);
+@@ -597,7 +597,7 @@ static const struct snd_soc_dapm_route a
+ static const struct regmap_range_cfg aic32x4_regmap_pages[] = {
+ {
+ .selector_reg = 0,
+- .selector_mask = 0xff,
++ .selector_mask = 0xff,
+ .window_start = 0,
+ .window_len = 128,
+ .range_min = 0,
+@@ -618,7 +618,7 @@ static inline int aic32x4_get_divs(int m
+
+ for (i = 0; i < ARRAY_SIZE(aic32x4_divs); i++) {
+ if ((aic32x4_divs[i].rate == rate)
+- && (aic32x4_divs[i].mclk == mclk)) {
++ && (aic32x4_divs[i].mclk == mclk)) {
+ return i;
+ }
+ }
+@@ -690,12 +690,12 @@ static int aic32x4_set_dai_fmt(struct sn
+ }
+
+ snd_soc_component_update_bits(component, AIC32X4_IFACE1,
+- AIC32X4_IFACE1_DATATYPE_MASK |
+- AIC32X4_IFACE1_MASTER_MASK, iface_reg_1);
++ AIC32X4_IFACE1_DATATYPE_MASK |
++ AIC32X4_IFACE1_MASTER_MASK, iface_reg_1);
+ snd_soc_component_update_bits(component, AIC32X4_IFACE2,
+- AIC32X4_DATA_OFFSET_MASK, iface_reg_2);
++ AIC32X4_DATA_OFFSET_MASK, iface_reg_2);
+ snd_soc_component_update_bits(component, AIC32X4_IFACE3,
+- AIC32X4_BCLKINV_MASK, iface_reg_3);
++ AIC32X4_BCLKINV_MASK, iface_reg_3);
+
+ return 0;
+ }
+@@ -717,6 +717,11 @@ static int aic32x4_setup_clocks(struct s
+ unsigned int parent_rate)
+ {
+ int i;
++ int ret;
++
++ struct clk_bulk_data clocks[] = {
++ { .id = "pll" },
++ };
+
+ i = aic32x4_get_divs(parent_rate, sample_rate);
+ if (i < 0) {
+@@ -724,39 +729,29 @@ static int aic32x4_setup_clocks(struct s
+ return i;
+ }
+
++ ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
++ if (ret)
++ return ret;
++
++ clk_set_rate(clocks[0].clk, sample_rate);
++
+ aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
+
+- /* MCLK as PLL_CLKIN */
+- snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_PLL_CLKIN_MASK,
+- AIC32X4_PLL_CLKIN_MCLK << AIC32X4_PLL_CLKIN_SHIFT);
+ /* PLL as CODEC_CLKIN */
+- snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_CODEC_CLKIN_MASK,
+- AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT);
++ snd_soc_component_update_bits(component, AIC32X4_CLKMUX,
++ AIC32X4_CODEC_CLKIN_MASK,
++ AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT);
+ /* DAC_MOD_CLK as BDIV_CLKIN */
+ snd_soc_component_update_bits(component, AIC32X4_IFACE3, AIC32X4_BDIVCLK_MASK,
+- AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
+-
+- /* We will fix R value to 1 and will make P & J=K.D as variable */
+- snd_soc_component_update_bits(component, AIC32X4_PLLPR, AIC32X4_PLL_R_MASK, 0x01);
+-
+- /* PLL P value */
+- snd_soc_component_update_bits(component, AIC32X4_PLLPR, AIC32X4_PLL_P_MASK,
+- aic32x4_divs[i].p_val << AIC32X4_PLL_P_SHIFT);
+-
+- /* PLL J value */
+- snd_soc_component_write(component, AIC32X4_PLLJ, aic32x4_divs[i].pll_j);
+-
+- /* PLL D value */
+- snd_soc_component_write(component, AIC32X4_PLLDMSB, (aic32x4_divs[i].pll_d >> 8));
+- snd_soc_component_write(component, AIC32X4_PLLDLSB, (aic32x4_divs[i].pll_d & 0xff));
++ AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
+
+ /* NDAC divider value */
+ snd_soc_component_update_bits(component, AIC32X4_NDAC,
+- AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac);
++ AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac);
+
+ /* MDAC divider value */
+ snd_soc_component_update_bits(component, AIC32X4_MDAC,
+- AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac);
++ AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac);
+
+ /* DOSR MSB & LSB values */
+ snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
+@@ -764,18 +759,18 @@ static int aic32x4_setup_clocks(struct s
+
+ /* NADC divider value */
+ snd_soc_component_update_bits(component, AIC32X4_NADC,
+- AIC32X4_NADC_MASK, aic32x4_divs[i].nadc);
++ AIC32X4_NADC_MASK, aic32x4_divs[i].nadc);
+
+ /* MADC divider value */
+ snd_soc_component_update_bits(component, AIC32X4_MADC,
+- AIC32X4_MADC_MASK, aic32x4_divs[i].madc);
++ AIC32X4_MADC_MASK, aic32x4_divs[i].madc);
+
+ /* AOSR value */
+ snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
+
+ /* BCLK N divider */
+ snd_soc_component_update_bits(component, AIC32X4_BCLKN,
+- AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
++ AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
+
+ return 0;
+ }
+@@ -794,23 +789,23 @@ static int aic32x4_hw_params(struct snd_
+ switch (params_width(params)) {
+ case 16:
+ iface1_reg |= (AIC32X4_WORD_LEN_16BITS <<
+- AIC32X4_IFACE1_DATALEN_SHIFT);
++ AIC32X4_IFACE1_DATALEN_SHIFT);
+ break;
+ case 20:
+ iface1_reg |= (AIC32X4_WORD_LEN_20BITS <<
+- AIC32X4_IFACE1_DATALEN_SHIFT);
++ AIC32X4_IFACE1_DATALEN_SHIFT);
+ break;
+ case 24:
+ iface1_reg |= (AIC32X4_WORD_LEN_24BITS <<
+- AIC32X4_IFACE1_DATALEN_SHIFT);
++ AIC32X4_IFACE1_DATALEN_SHIFT);
+ break;
+ case 32:
+ iface1_reg |= (AIC32X4_WORD_LEN_32BITS <<
+- AIC32X4_IFACE1_DATALEN_SHIFT);
++ AIC32X4_IFACE1_DATALEN_SHIFT);
+ break;
+ }
+ snd_soc_component_update_bits(component, AIC32X4_IFACE1,
+- AIC32X4_IFACE1_DATALEN_MASK, iface1_reg);
++ AIC32X4_IFACE1_DATALEN_MASK, iface1_reg);
+
+ if (params_channels(params) == 1) {
+ dacsetup_reg = AIC32X4_RDAC2LCHN | AIC32X4_LDAC2LCHN;
+@@ -821,7 +816,7 @@ static int aic32x4_hw_params(struct snd_
+ dacsetup_reg = AIC32X4_LDAC2LCHN | AIC32X4_RDAC2RCHN;
+ }
+ snd_soc_component_update_bits(component, AIC32X4_DACSETUP,
+- AIC32X4_DAC_CHAN_MASK, dacsetup_reg);
++ AIC32X4_DAC_CHAN_MASK, dacsetup_reg);
+
+ return 0;
+ }
+@@ -831,7 +826,7 @@ static int aic32x4_mute(struct snd_soc_d
+ struct snd_soc_component *component = dai->component;
+
+ snd_soc_component_update_bits(component, AIC32X4_DACMUTE,
+- AIC32X4_MUTEON, mute ? AIC32X4_MUTEON : 0);
++ AIC32X4_MUTEON, mute ? AIC32X4_MUTEON : 0);
+
+ return 0;
+ }
+@@ -853,27 +848,27 @@ static int aic32x4_set_bias_level(struct
+
+ /* Switch on PLL */
+ snd_soc_component_update_bits(component, AIC32X4_PLLPR,
+- AIC32X4_PLLEN, AIC32X4_PLLEN);
++ AIC32X4_PLLEN, AIC32X4_PLLEN);
+
+ /* Switch on NDAC Divider */
+ snd_soc_component_update_bits(component, AIC32X4_NDAC,
+- AIC32X4_NDACEN, AIC32X4_NDACEN);
++ AIC32X4_NDACEN, AIC32X4_NDACEN);
+
+ /* Switch on MDAC Divider */
+ snd_soc_component_update_bits(component, AIC32X4_MDAC,
+- AIC32X4_MDACEN, AIC32X4_MDACEN);
++ AIC32X4_MDACEN, AIC32X4_MDACEN);
+
+ /* Switch on NADC Divider */
+ snd_soc_component_update_bits(component, AIC32X4_NADC,
+- AIC32X4_NADCEN, AIC32X4_NADCEN);
++ AIC32X4_NADCEN, AIC32X4_NADCEN);
+
+ /* Switch on MADC Divider */
+ snd_soc_component_update_bits(component, AIC32X4_MADC,
+- AIC32X4_MADCEN, AIC32X4_MADCEN);
++ AIC32X4_MADCEN, AIC32X4_MADCEN);
+
+ /* Switch on BCLK_N Divider */
+ snd_soc_component_update_bits(component, AIC32X4_BCLKN,
+- AIC32X4_BCLKEN, AIC32X4_BCLKEN);
++ AIC32X4_BCLKEN, AIC32X4_BCLKEN);
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ break;
+@@ -884,27 +879,27 @@ static int aic32x4_set_bias_level(struct
+
+ /* Switch off BCLK_N Divider */
+ snd_soc_component_update_bits(component, AIC32X4_BCLKN,
+- AIC32X4_BCLKEN, 0);
++ AIC32X4_BCLKEN, 0);
+
+ /* Switch off MADC Divider */
+ snd_soc_component_update_bits(component, AIC32X4_MADC,
+- AIC32X4_MADCEN, 0);
++ AIC32X4_MADCEN, 0);
+
+ /* Switch off NADC Divider */
+ snd_soc_component_update_bits(component, AIC32X4_NADC,
+- AIC32X4_NADCEN, 0);
++ AIC32X4_NADCEN, 0);
+
+ /* Switch off MDAC Divider */
+ snd_soc_component_update_bits(component, AIC32X4_MDAC,
+- AIC32X4_MDACEN, 0);
++ AIC32X4_MDACEN, 0);
+
+ /* Switch off NDAC Divider */
+ snd_soc_component_update_bits(component, AIC32X4_NDAC,
+- AIC32X4_NDACEN, 0);
++ AIC32X4_NDACEN, 0);
+
+ /* Switch off PLL */
+ snd_soc_component_update_bits(component, AIC32X4_PLLPR,
+- AIC32X4_PLLEN, 0);
++ AIC32X4_PLLEN, 0);
+
+ /* Switch off master clock */
+ clk_disable_unprepare(aic32x4->mclk);
+@@ -916,7 +911,7 @@ static int aic32x4_set_bias_level(struct
+ }
+
+ #define AIC32X4_RATES SNDRV_PCM_RATE_8000_96000
+-#define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
++#define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
+ | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+ static const struct snd_soc_dai_ops aic32x4_ops = {
+@@ -929,17 +924,17 @@ static const struct snd_soc_dai_ops aic3
+ static struct snd_soc_dai_driver aic32x4_dai = {
+ .name = "tlv320aic32x4-hifi",
+ .playback = {
+- .stream_name = "Playback",
+- .channels_min = 1,
+- .channels_max = 2,
+- .rates = AIC32X4_RATES,
+- .formats = AIC32X4_FORMATS,},
++ .stream_name = "Playback",
++ .channels_min = 1,
++ .channels_max = 2,
++ .rates = AIC32X4_RATES,
++ .formats = AIC32X4_FORMATS,},
+ .capture = {
+- .stream_name = "Capture",
+- .channels_min = 1,
+- .channels_max = 2,
+- .rates = AIC32X4_RATES,
+- .formats = AIC32X4_FORMATS,},
++ .stream_name = "Capture",
++ .channels_min = 1,
++ .channels_max = 2,
++ .rates = AIC32X4_RATES,
++ .formats = AIC32X4_FORMATS,},
+ .ops = &aic32x4_ops,
+ .symmetric_rates = 1,
+ };
+@@ -952,7 +947,7 @@ static void aic32x4_setup_gpios(struct s
+ /* MFP1 */
+ if (aic32x4->setup->gpio_func[0] != AIC32X4_MFPX_DEFAULT_VALUE) {
+ snd_soc_component_write(component, AIC32X4_DINCTL,
+- aic32x4->setup->gpio_func[0]);
++ aic32x4->setup->gpio_func[0]);
+ snd_soc_add_component_controls(component, aic32x4_mfp1,
+ ARRAY_SIZE(aic32x4_mfp1));
+ }
+@@ -960,7 +955,7 @@ static void aic32x4_setup_gpios(struct s
+ /* MFP2 */
+ if (aic32x4->setup->gpio_func[1] != AIC32X4_MFPX_DEFAULT_VALUE) {
+ snd_soc_component_write(component, AIC32X4_DOUTCTL,
+- aic32x4->setup->gpio_func[1]);
++ aic32x4->setup->gpio_func[1]);
+ snd_soc_add_component_controls(component, aic32x4_mfp2,
+ ARRAY_SIZE(aic32x4_mfp2));
+ }
+@@ -968,7 +963,7 @@ static void aic32x4_setup_gpios(struct s
+ /* MFP3 */
+ if (aic32x4->setup->gpio_func[2] != AIC32X4_MFPX_DEFAULT_VALUE) {
+ snd_soc_component_write(component, AIC32X4_SCLKCTL,
+- aic32x4->setup->gpio_func[2]);
++ aic32x4->setup->gpio_func[2]);
+ snd_soc_add_component_controls(component, aic32x4_mfp3,
+ ARRAY_SIZE(aic32x4_mfp3));
+ }
+@@ -976,7 +971,7 @@ static void aic32x4_setup_gpios(struct s
+ /* MFP4 */
+ if (aic32x4->setup->gpio_func[3] != AIC32X4_MFPX_DEFAULT_VALUE) {
+ snd_soc_component_write(component, AIC32X4_MISOCTL,
+- aic32x4->setup->gpio_func[3]);
++ aic32x4->setup->gpio_func[3]);
+ snd_soc_add_component_controls(component, aic32x4_mfp4,
+ ARRAY_SIZE(aic32x4_mfp4));
+ }
+@@ -984,7 +979,7 @@ static void aic32x4_setup_gpios(struct s
+ /* MFP5 */
+ if (aic32x4->setup->gpio_func[4] != AIC32X4_MFPX_DEFAULT_VALUE) {
+ snd_soc_component_write(component, AIC32X4_GPIOCTL,
+- aic32x4->setup->gpio_func[4]);
++ aic32x4->setup->gpio_func[4]);
+ snd_soc_add_component_controls(component, aic32x4_mfp5,
+ ARRAY_SIZE(aic32x4_mfp5));
+ }
+@@ -1007,8 +1002,8 @@ static int aic32x4_component_probe(struc
+
+ /* Power platform configuration */
+ if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
+- snd_soc_component_write(component, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN |
+- AIC32X4_MICBIAS_2075V);
++ snd_soc_component_write(component, AIC32X4_MICBIAS,
++ AIC32X4_MICBIAS_LDOIN | AIC32X4_MICBIAS_2075V);
+ }
+ if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE)
+ snd_soc_component_write(component, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
+@@ -1071,12 +1066,18 @@ static int aic32x4_parse_dt(struct aic32
+ struct device_node *np)
+ {
+ struct aic32x4_setup_data *aic32x4_setup;
++ int ret;
+
+ aic32x4_setup = devm_kzalloc(aic32x4->dev, sizeof(*aic32x4_setup),
+ GFP_KERNEL);
+ if (!aic32x4_setup)
+ return -ENOMEM;
+
++ ret = of_property_match_string(np, "clock-names", "mclk");
++ if (ret < 0)
++ return -EINVAL;
++ aic32x4->mclk_name = of_clk_get_parent_name(np, ret);
++
+ aic32x4->swapdacs = false;
+ aic32x4->micpga_routing = 0;
+ aic32x4->rstn_gpio = of_get_named_gpio(np, "reset-gpios", 0);
+@@ -1198,7 +1199,7 @@ int aic32x4_probe(struct device *dev, st
+ return PTR_ERR(regmap);
+
+ aic32x4 = devm_kzalloc(dev, sizeof(struct aic32x4_priv),
+- GFP_KERNEL);
++ GFP_KERNEL);
+ if (aic32x4 == NULL)
+ return -ENOMEM;
+
+@@ -1210,6 +1211,7 @@ int aic32x4_probe(struct device *dev, st
+ aic32x4->swapdacs = pdata->swapdacs;
+ aic32x4->micpga_routing = pdata->micpga_routing;
+ aic32x4->rstn_gpio = pdata->rstn_gpio;
++ aic32x4->mclk_name = "mclk";
+ } else if (np) {
+ ret = aic32x4_parse_dt(aic32x4, np);
+ if (ret) {
+@@ -1221,6 +1223,7 @@ int aic32x4_probe(struct device *dev, st
+ aic32x4->swapdacs = false;
+ aic32x4->micpga_routing = 0;
+ aic32x4->rstn_gpio = -1;
++ aic32x4->mclk_name = "mclk";
+ }
+
+ aic32x4->mclk = devm_clk_get(dev, "mclk");
+@@ -1229,6 +1232,10 @@ int aic32x4_probe(struct device *dev, st
+ return PTR_ERR(aic32x4->mclk);
+ }
+
++ ret = aic32x4_register_clocks(dev, aic32x4->mclk_name);
++ if (ret)
++ return ret;
++
+ if (gpio_is_valid(aic32x4->rstn_gpio)) {
+ ret = devm_gpio_request_one(dev, aic32x4->rstn_gpio,
+ GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
+--- a/sound/soc/codecs/tlv320aic32x4.h
++++ b/sound/soc/codecs/tlv320aic32x4.h
+@@ -16,6 +16,7 @@ struct regmap_config;
+ extern const struct regmap_config aic32x4_regmap_config;
+ int aic32x4_probe(struct device *dev, struct regmap *regmap);
+ int aic32x4_remove(struct device *dev);
++int aic32x4_register_clocks(struct device *dev, const char *mclk_name);
+
+ /* tlv320aic32x4 register space (in decimal to match datasheet) */
+
+@@ -205,4 +206,8 @@ int aic32x4_remove(struct device *dev);
+ #define AIC32X4_RMICPGANIN_IN1L_10K 0x10
+ #define AIC32X4_RMICPGANIN_CM1R_10K 0x40
+
++/* Clock Limits */
++#define AIC32X4_MAX_PLL_CLKIN 20000000
++
++
+ #endif /* _TLV320AIC32X4_H */
+++ /dev/null
-From e4e16b18401abf412c5d1d6435176e609a33c1ed Mon Sep 17 00:00:00 2001
-From: b-ak <anur.bhargav@gmail.com>
-Date: Wed, 9 Jan 2019 22:41:21 +0530
-Subject: [PATCH 402/703] ASoC: tlv320aic32x4: SND_SOC_DAPM_MICBIAS is
- deprecated
-
-commit 04d979d7a7bac2f645cd827ea37e5ffa5b4e1f97 upstream.
-
-SND_SOC_DAPM_MICBIAS is deprecated, replace it with SND_SOC_DAPM_SUPPLY.
-
-MICBIAS voltage wasn't supplied to the microphone with the older
-SND_SOC_DAPM_MICBIAS widget, hence the microphone wouldn't work.
-
-This patch fixes the problem.
-
-Signed-off-by: b-ak <anur.bhargav@gmail.com>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 30 +++++++++++++++++++++++++++++-
- sound/soc/codecs/tlv320aic32x4.h | 1 +
- 2 files changed, 30 insertions(+), 1 deletion(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -79,6 +79,32 @@ struct aic32x4_priv {
- struct device *dev;
- };
-
-+static int mic_bias_event(struct snd_soc_dapm_widget *w,
-+ struct snd_kcontrol *kcontrol, int event)
-+{
-+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
-+
-+ switch (event) {
-+ case SND_SOC_DAPM_POST_PMU:
-+ /* Change Mic Bias Registor */
-+ snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
-+ AIC32x4_MICBIAS_MASK,
-+ AIC32X4_MICBIAS_LDOIN |
-+ AIC32X4_MICBIAS_2075V);
-+ printk(KERN_DEBUG "%s: Mic Bias will be turned ON\n", __func__);
-+ break;
-+ case SND_SOC_DAPM_PRE_PMD:
-+ snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
-+ AIC32x4_MICBIAS_MASK, 0);
-+ printk(KERN_DEBUG "%s: Mic Bias will be turned OFF\n",
-+ __func__);
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+
- static int aic32x4_get_mfp1_gpio(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
- {
-@@ -450,7 +476,9 @@ static const struct snd_soc_dapm_widget
- SND_SOC_DAPM_MUX("IN3_R to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
- in3r_to_lmixer_controls),
-
-- SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0),
-+ SND_SOC_DAPM_SUPPLY("Mic Bias", AIC32X4_MICBIAS, 6, 0, mic_bias_event,
-+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-+
-
- SND_SOC_DAPM_OUTPUT("HPL"),
- SND_SOC_DAPM_OUTPUT("HPR"),
---- a/sound/soc/codecs/tlv320aic32x4.h
-+++ b/sound/soc/codecs/tlv320aic32x4.h
-@@ -195,6 +195,7 @@ int aic32x4_remove(struct device *dev);
- /* AIC32X4_MICBIAS */
- #define AIC32X4_MICBIAS_LDOIN BIT(3)
- #define AIC32X4_MICBIAS_2075V 0x60
-+#define AIC32x4_MICBIAS_MASK GENMASK(6, 3)
-
- /* AIC32X4_LMICPGANIN */
- #define AIC32X4_LMICPGANIN_IN2R_10K 0x10
+++ /dev/null
-From 8ce90120ea5e084d5d9f2b5b1a449edef6099b0b Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Mon, 18 Mar 2019 20:37:44 -0700
-Subject: [PATCH 403/703] ASoC: tlv320aic32x4: Break out clock setting into
- separate function
-
-commit bf31cbfbe25001036e1e096b1c260bf871766ea5 upstream.
-
-Break the clock setting logic out from the main hw_params. It's
-rather large and unweildy and makes for a large function. This
-also better enables some of the following changes to the clock
-tree access in the driver.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 26 ++++++++++++++++++--------
- 1 file changed, 18 insertions(+), 8 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -698,17 +698,13 @@ static int aic32x4_set_dai_fmt(struct sn
- return 0;
- }
-
--static int aic32x4_hw_params(struct snd_pcm_substream *substream,
-- struct snd_pcm_hw_params *params,
-- struct snd_soc_dai *dai)
-+static int aic32x4_setup_clocks(struct snd_soc_component *component,
-+ unsigned int sample_rate,
-+ unsigned int parent_rate)
- {
-- struct snd_soc_component *component = dai->component;
-- struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
-- u8 iface1_reg = 0;
-- u8 dacsetup_reg = 0;
- int i;
-
-- i = aic32x4_get_divs(aic32x4->sysclk, params_rate(params));
-+ i = aic32x4_get_divs(parent_rate, sample_rate);
- if (i < 0) {
- printk(KERN_ERR "aic32x4: sampling rate not supported\n");
- return i;
-@@ -765,6 +761,20 @@ static int aic32x4_hw_params(struct snd_
- snd_soc_component_update_bits(component, AIC32X4_BCLKN,
- AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
-
-+ return 0;
-+}
-+
-+static int aic32x4_hw_params(struct snd_pcm_substream *substream,
-+ struct snd_pcm_hw_params *params,
-+ struct snd_soc_dai *dai)
-+{
-+ struct snd_soc_component *component = dai->component;
-+ struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
-+ u8 iface1_reg = 0;
-+ u8 dacsetup_reg = 0;
-+
-+ aic32x4_setup_clocks(component, params_rate(params), aic32x4->sysclk);
-+
- switch (params_width(params)) {
- case 16:
- iface1_reg |= (AIC32X4_WORD_LEN_16BITS <<
--- /dev/null
+From 7ba72b1d9a6bc4d3db7d38a24c5c23bc3e8184da Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:46 -0700
+Subject: [PATCH 403/725] ASoC: tlv320aic32x4: Model CODEC_CLKIN in CCF
+
+commit fd2df3aeafa4b4cc468d58e147e0822967034b71 upstream.
+
+Model and manage codec clock input as a component in the Core
+Clock Framework. This should allow us to do some more complex
+clock management and power control. Also, some of the
+on-board chip clocks can be exposed to the outside, and this
+change will make those clocks easier to consume by other
+parts of the kernel.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4-clk.c | 34 ++++++++++++++++++++++++++++
+ sound/soc/codecs/tlv320aic32x4.c | 18 +++++++++++----
+ 2 files changed, 47 insertions(+), 5 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4-clk.c
++++ b/sound/soc/codecs/tlv320aic32x4-clk.c
+@@ -265,6 +265,30 @@ static const struct clk_ops aic32x4_pll_
+ .get_parent = clk_aic32x4_pll_get_parent,
+ };
+
++static int clk_aic32x4_codec_clkin_set_parent(struct clk_hw *hw, u8 index)
++{
++ struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
++
++ return regmap_update_bits(mux->regmap,
++ AIC32X4_CLKMUX,
++ AIC32X4_CODEC_CLKIN_MASK, index << AIC32X4_CODEC_CLKIN_SHIFT);
++}
++
++static u8 clk_aic32x4_codec_clkin_get_parent(struct clk_hw *hw)
++{
++ struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
++ unsigned int val;
++
++ regmap_read(mux->regmap, AIC32X4_CLKMUX, &val);
++
++ return (val & AIC32X4_CODEC_CLKIN_MASK) >> AIC32X4_CODEC_CLKIN_SHIFT;
++}
++
++static const struct clk_ops aic32x4_codec_clkin_ops = {
++ .set_parent = clk_aic32x4_codec_clkin_set_parent,
++ .get_parent = clk_aic32x4_codec_clkin_get_parent,
++};
++
+ static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
+ {
+ .name = "pll",
+@@ -274,6 +298,14 @@ static struct aic32x4_clkdesc aic32x4_cl
+ .ops = &aic32x4_pll_ops,
+ .reg = 0,
+ },
++ {
++ .name = "codec_clkin",
++ .parent_names =
++ (const char *[]) { "mclk", "bclk", "gpio", "pll" },
++ .num_parents = 4,
++ .ops = &aic32x4_codec_clkin_ops,
++ .reg = 0,
++ },
+ };
+
+ static struct clk *aic32x4_register_clk(struct device *dev,
+@@ -314,6 +346,8 @@ int aic32x4_register_clocks(struct devic
+ */
+ aic32x4_clkdesc_array[0].parent_names =
+ (const char* []) { mclk_name, "bclk", "gpio", "din" };
++ aic32x4_clkdesc_array[1].parent_names =
++ (const char *[]) { mclk_name, "bclk", "gpio", "pll" };
+
+ for (i = 0; i < ARRAY_SIZE(aic32x4_clkdesc_array); ++i)
+ aic32x4_register_clk(dev, &aic32x4_clkdesc_array[i]);
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -737,12 +737,9 @@ static int aic32x4_setup_clocks(struct s
+
+ aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
+
+- /* PLL as CODEC_CLKIN */
+- snd_soc_component_update_bits(component, AIC32X4_CLKMUX,
+- AIC32X4_CODEC_CLKIN_MASK,
+- AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT);
+ /* DAC_MOD_CLK as BDIV_CLKIN */
+- snd_soc_component_update_bits(component, AIC32X4_IFACE3, AIC32X4_BDIVCLK_MASK,
++ snd_soc_component_update_bits(component, AIC32X4_IFACE3,
++ AIC32X4_BDIVCLK_MASK,
+ AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
+
+ /* NDAC divider value */
+@@ -989,6 +986,15 @@ static int aic32x4_component_probe(struc
+ {
+ struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
+ u32 tmp_reg;
++ int ret;
++
++ struct clk_bulk_data clocks[] = {
++ { .id = "codec_clkin" },
++ };
++
++ ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
++ if (ret)
++ return ret;
+
+ if (gpio_is_valid(aic32x4->rstn_gpio)) {
+ ndelay(10);
+@@ -1000,6 +1006,8 @@ static int aic32x4_component_probe(struc
+ if (aic32x4->setup)
+ aic32x4_setup_gpios(component);
+
++ clk_set_parent(clocks[0].clk, clocks[1].clk);
++
+ /* Power platform configuration */
+ if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
+ snd_soc_component_write(component, AIC32X4_MICBIAS,
--- /dev/null
+From c4c080628e85c7860986c64a7a0b7f56a521fef6 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:47 -0700
+Subject: [PATCH 404/725] ASoC: tlv320aic32x4: Model DAC/ADC dividers in CCF
+
+commit a51b50062091619915c5155085bbe13a7aca6903 upstream.
+
+Model and manage DAC/ADC dividers as components in the Core
+Clock Framework. This should allow us to do some more complex
+clock management and power control. Also, some of the
+on-board chip clocks can be exposed to the outside, and this
+change will make those clocks easier to consume by other
+parts of the kernel.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4-clk.c | 90 ++++++++++++++++++++++++
+ sound/soc/codecs/tlv320aic32x4.c | 101 +++++++++++++++------------
+ sound/soc/codecs/tlv320aic32x4.h | 4 ++
+ 3 files changed, 151 insertions(+), 44 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4-clk.c
++++ b/sound/soc/codecs/tlv320aic32x4-clk.c
+@@ -289,6 +289,68 @@ static const struct clk_ops aic32x4_code
+ .get_parent = clk_aic32x4_codec_clkin_get_parent,
+ };
+
++static int clk_aic32x4_div_prepare(struct clk_hw *hw)
++{
++ struct clk_aic32x4 *div = to_clk_aic32x4(hw);
++
++ return regmap_update_bits(div->regmap, div->reg,
++ AIC32X4_DIVEN, AIC32X4_DIVEN);
++}
++
++static void clk_aic32x4_div_unprepare(struct clk_hw *hw)
++{
++ struct clk_aic32x4 *div = to_clk_aic32x4(hw);
++
++ regmap_update_bits(div->regmap, div->reg,
++ AIC32X4_DIVEN, 0);
++}
++
++static int clk_aic32x4_div_set_rate(struct clk_hw *hw, unsigned long rate,
++ unsigned long parent_rate)
++{
++ struct clk_aic32x4 *div = to_clk_aic32x4(hw);
++ u8 divisor;
++
++ divisor = DIV_ROUND_UP(parent_rate, rate);
++ if (divisor > 128)
++ return -EINVAL;
++
++ return regmap_update_bits(div->regmap, div->reg,
++ AIC32X4_DIV_MASK, divisor);
++}
++
++static long clk_aic32x4_div_round_rate(struct clk_hw *hw, unsigned long rate,
++ unsigned long *parent_rate)
++{
++ unsigned long divisor;
++
++ divisor = DIV_ROUND_UP(*parent_rate, rate);
++ if (divisor > 128)
++ return -EINVAL;
++
++ return DIV_ROUND_UP(*parent_rate, divisor);
++}
++
++static unsigned long clk_aic32x4_div_recalc_rate(struct clk_hw *hw,
++ unsigned long parent_rate)
++{
++ struct clk_aic32x4 *div = to_clk_aic32x4(hw);
++
++ unsigned int val;
++
++ regmap_read(div->regmap, div->reg, &val);
++
++ return DIV_ROUND_UP(parent_rate, val & AIC32X4_DIV_MASK);
++}
++
++static const struct clk_ops aic32x4_div_ops = {
++ .prepare = clk_aic32x4_div_prepare,
++ .unprepare = clk_aic32x4_div_unprepare,
++ .set_rate = clk_aic32x4_div_set_rate,
++ .round_rate = clk_aic32x4_div_round_rate,
++ .recalc_rate = clk_aic32x4_div_recalc_rate,
++};
++
+ static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
+ {
+ .name = "pll",
+@@ -306,6 +368,34 @@ static struct aic32x4_clkdesc aic32x4_cl
+ .ops = &aic32x4_codec_clkin_ops,
+ .reg = 0,
+ },
++ {
++ .name = "ndac",
++ .parent_names = (const char * []) { "codec_clkin" },
++ .num_parents = 1,
++ .ops = &aic32x4_div_ops,
++ .reg = AIC32X4_NDAC,
++ },
++ {
++ .name = "mdac",
++ .parent_names = (const char * []) { "ndac" },
++ .num_parents = 1,
++ .ops = &aic32x4_div_ops,
++ .reg = AIC32X4_MDAC,
++ },
++ {
++ .name = "nadc",
++ .parent_names = (const char * []) { "codec_clkin" },
++ .num_parents = 1,
++ .ops = &aic32x4_div_ops,
++ .reg = AIC32X4_NADC,
++ },
++ {
++ .name = "madc",
++ .parent_names = (const char * []) { "nadc" },
++ .num_parents = 1,
++ .ops = &aic32x4_div_ops,
++ .reg = AIC32X4_MADC,
++ },
+ };
+
+ static struct clk *aic32x4_register_clk(struct device *dev,
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -52,11 +52,11 @@ struct aic32x4_rate_divs {
+ u32 rate;
+ unsigned long pll_rate;
+ u16 dosr;
+- u8 ndac;
+- u8 mdac;
++ unsigned long ndac_rate;
++ unsigned long mdac_rate;
+ u8 aosr;
+- u8 nadc;
+- u8 madc;
++ unsigned long nadc_rate;
++ unsigned long madc_rate;
+ u8 blck_N;
+ u8 r_block;
+ u8 p_block;
+@@ -309,34 +309,54 @@ static const struct snd_kcontrol_new aic
+
+ static const struct aic32x4_rate_divs aic32x4_divs[] = {
+ /* 8k rate */
+- { 12000000, 8000, 57120000, 768, 5, 3, 128, 5, 18, 24, 1, 1 },
+- { 24000000, 8000, 57120000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
+- { 25000000, 8000, 32620000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
++ { 12000000, 8000, 57120000, 768, 18432000, 6144000, 128, 18432000,
++ 1024000, 24, 1, 1 },
++ { 24000000, 8000, 57120000, 768, 6144000, 6144000, 64, 2048000,
++ 512000, 24, 1, 1 },
++ { 25000000, 8000, 32620000, 768, 6144000, 6144000, 64, 2048000,
++ 512000, 24, 1, 1 },
+ /* 11.025k rate */
+- { 12000000, 11025, 44217600, 512, 8, 2, 128, 8, 8, 16, 1, 1 },
+- { 24000000, 11025, 44217600, 512, 16, 1, 64, 32, 4, 16, 1, 1 },
++ { 12000000, 11025, 44217600, 512, 11289600, 5644800, 128, 11289600,
++ 1411200, 16, 1, 1 },
++ { 24000000, 11025, 44217600, 512, 5644800, 5644800, 64, 2822400,
++ 705600, 16, 1, 1 },
+ /* 16k rate */
+- { 12000000, 16000, 57120000, 384, 5, 3, 128, 5, 9, 12, 1, 1 },
+- { 24000000, 16000, 57120000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
+- { 25000000, 16000, 32620000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
++ { 12000000, 16000, 57120000, 384, 18432000, 6144000, 128, 18432000,
++ 2048000, 12, 1, 1 },
++ { 24000000, 16000, 57120000, 384, 6144000, 6144000, 64, 5120000,
++ 1024000, 12, 1, 1 },
++ { 25000000, 16000, 32620000, 384, 6144000, 6144000, 64, 5120000,
++ 1024000, 12, 1, 1 },
+ /* 22.05k rate */
+- { 12000000, 22050, 44217600, 256, 4, 4, 128, 4, 8, 8, 1, 1 },
+- { 24000000, 22050, 44217600, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
+- { 25000000, 22050, 19713750, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
++ { 12000000, 22050, 44217600, 256, 22579200, 5644800, 128, 22579200,
++ 2822400, 8, 1, 1 },
++ { 24000000, 22050, 44217600, 256, 5644800, 5644800, 64, 5644800,
++ 1411200, 8, 1, 1 },
++ { 25000000, 22050, 19713750, 256, 5644800, 5644800, 64, 5644800,
++ 1411200, 8, 1, 1 },
+ /* 32k rate */
+- { 12000000, 32000, 14112000, 192, 2, 7, 64, 2, 21, 6, 1, 1 },
+- { 24000000, 32000, 14112000, 192, 7, 2, 64, 7, 6, 6, 1, 1 },
++ { 12000000, 32000, 14112000, 192, 43008000, 6144000, 64, 43008000,
++ 2048000, 6, 1, 1 },
++ { 24000000, 32000, 14112000, 192, 12288000, 6144000, 64, 12288000,
++ 2048000, 6, 1, 1 },
+ /* 44.1k rate */
+- { 12000000, 44100, 44217600, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
+- { 24000000, 44100, 44217600, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
+- { 25000000, 44100, 19713750, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
++ { 12000000, 44100, 44217600, 128, 45158400, 5644800, 128, 45158400,
++ 5644800, 4, 1, 1 },
++ { 24000000, 44100, 44217600, 128, 11289600, 5644800, 64, 11289600,
++ 2822400, 4, 1, 1 },
++ { 25000000, 44100, 19713750, 128, 11289600, 5644800, 64, 11289600,
++ 2822400, 4, 1, 1 },
+ /* 48k rate */
+- { 12000000, 48000, 18432000, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
+- { 24000000, 48000, 18432000, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
+- { 25000000, 48000, 75626250, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
++ { 12000000, 48000, 18432000, 128, 49152000, 6144000, 128, 49152000,
++ 6144000, 4, 1, 1 },
++ { 24000000, 48000, 18432000, 128, 12288000, 6144000, 64, 12288000,
++ 3072000, 4, 1, 1 },
++ { 25000000, 48000, 75626250, 128, 12288000, 6144000, 64, 12288000,
++ 3072000, 4, 1, 1 },
+
+ /* 96k rate */
+- { 25000000, 96000, 75626250, 64, 4, 4, 64, 4, 4, 1, 1, 9 },
++ { 25000000, 96000, 75626250, 64, 24576000, 6144000, 64, 24576000,
++ 6144000, 1, 1, 9 },
+ };
+
+ static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
+@@ -721,6 +741,10 @@ static int aic32x4_setup_clocks(struct s
+
+ struct clk_bulk_data clocks[] = {
+ { .id = "pll" },
++ { .id = "nadc" },
++ { .id = "madc" },
++ { .id = "ndac" },
++ { .id = "mdac" },
+ };
+
+ i = aic32x4_get_divs(parent_rate, sample_rate);
+@@ -733,7 +757,11 @@ static int aic32x4_setup_clocks(struct s
+ if (ret)
+ return ret;
+
+- clk_set_rate(clocks[0].clk, sample_rate);
++ clk_set_rate(clocks[0].clk, aic32x4_divs[i].pll_rate);
++ clk_set_rate(clocks[1].clk, aic32x4_divs[i].nadc_rate);
++ clk_set_rate(clocks[2].clk, aic32x4_divs[i].madc_rate);
++ clk_set_rate(clocks[3].clk, aic32x4_divs[i].ndac_rate);
++ clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
+
+ aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
+
+@@ -742,26 +770,10 @@ static int aic32x4_setup_clocks(struct s
+ AIC32X4_BDIVCLK_MASK,
+ AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
+
+- /* NDAC divider value */
+- snd_soc_component_update_bits(component, AIC32X4_NDAC,
+- AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac);
+-
+- /* MDAC divider value */
+- snd_soc_component_update_bits(component, AIC32X4_MDAC,
+- AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac);
+-
+ /* DOSR MSB & LSB values */
+ snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
+ snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff));
+
+- /* NADC divider value */
+- snd_soc_component_update_bits(component, AIC32X4_NADC,
+- AIC32X4_NADC_MASK, aic32x4_divs[i].nadc);
+-
+- /* MADC divider value */
+- snd_soc_component_update_bits(component, AIC32X4_MADC,
+- AIC32X4_MADC_MASK, aic32x4_divs[i].madc);
+-
+ /* AOSR value */
+ snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
+
+@@ -773,8 +785,8 @@ static int aic32x4_setup_clocks(struct s
+ }
+
+ static int aic32x4_hw_params(struct snd_pcm_substream *substream,
+- struct snd_pcm_hw_params *params,
+- struct snd_soc_dai *dai)
++ struct snd_pcm_hw_params *params,
++ struct snd_soc_dai *dai)
+ {
+ struct snd_soc_component *component = dai->component;
+ struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
+@@ -989,7 +1001,8 @@ static int aic32x4_component_probe(struc
+ int ret;
+
+ struct clk_bulk_data clocks[] = {
+- { .id = "codec_clkin" },
++ { .id = "codec_clkin" },
++ { .id = "pll" },
+ };
+
+ ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
+--- a/sound/soc/codecs/tlv320aic32x4.h
++++ b/sound/soc/codecs/tlv320aic32x4.h
+@@ -206,6 +206,10 @@ int aic32x4_register_clocks(struct devic
+ #define AIC32X4_RMICPGANIN_IN1L_10K 0x10
+ #define AIC32X4_RMICPGANIN_CM1R_10K 0x40
+
++/* Common mask and enable for all of the dividers */
++#define AIC32X4_DIVEN BIT(7)
++#define AIC32X4_DIV_MASK GENMASK(6, 0)
++
+ /* Clock Limits */
+ #define AIC32X4_MAX_PLL_CLKIN 20000000
+
+++ /dev/null
-From d41102524cf14a1098a735add06aa4d67c631130 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Wed, 20 Mar 2019 19:38:44 -0700
-Subject: [PATCH 404/703] ASoC: tlv320aic32x4: Properly Set Processing Blocks
-
-commit c95e3a4b96293403a427b5185e60fad28af51fdd upstream.
-
-Different processing blocks are required for different sampling
-rates and power parameters. Set the processing blocks based
-on this information.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 56 ++++++++++++++++++++------------
- 1 file changed, 36 insertions(+), 20 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -59,6 +59,8 @@ struct aic32x4_rate_divs {
- u8 nadc;
- u8 madc;
- u8 blck_N;
-+ u8 r_block;
-+ u8 p_block;
- };
-
- struct aic32x4_priv {
-@@ -307,34 +309,34 @@ static const struct snd_kcontrol_new aic
-
- static const struct aic32x4_rate_divs aic32x4_divs[] = {
- /* 8k rate */
-- {12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24},
-- {24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24},
-- {25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24},
-+ {12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24, 1, 1},
-+ {24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24, 1, 1},
-+ {25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24, 1, 1},
- /* 11.025k rate */
-- {12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16},
-- {24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16},
-+ {12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16, 1, 1},
-+ {24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16, 1, 1},
- /* 16k rate */
-- {12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12},
-- {24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12},
-- {25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12},
-+ {12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12, 1, 1},
-+ {24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12, 1, 1},
-+ {25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12, 1, 1},
- /* 22.05k rate */
-- {12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8},
-- {24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8},
-- {25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8},
-+ {12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8, 1, 1},
-+ {24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8, 1, 1},
-+ {25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8, 1, 1},
- /* 32k rate */
-- {12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6},
-- {24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6},
-+ {12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6, 1, 1},
-+ {24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6, 1, 1},
- /* 44.1k rate */
-- {12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4},
-- {24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4},
-- {25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4},
-+ {12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4, 1, 1},
-+ {24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4, 1, 1},
-+ {25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4, 1, 1},
- /* 48k rate */
-- {12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4},
-- {24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4},
-- {25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4},
-+ {12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4, 1, 1},
-+ {24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4, 1, 1},
-+ {25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4, 1, 1},
-
- /* 96k rate */
-- {25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1},
-+ {25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1, 1, 9},
- };
-
- static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
-@@ -698,6 +700,18 @@ static int aic32x4_set_dai_fmt(struct sn
- return 0;
- }
-
-+static int aic32x4_set_processing_blocks(struct snd_soc_component *component,
-+ u8 r_block, u8 p_block)
-+{
-+ if (r_block > 18 || p_block > 25)
-+ return -EINVAL;
-+
-+ snd_soc_component_write(component, AIC32X4_ADCSPB, r_block);
-+ snd_soc_component_write(component, AIC32X4_DACSPB, p_block);
-+
-+ return 0;
-+}
-+
- static int aic32x4_setup_clocks(struct snd_soc_component *component,
- unsigned int sample_rate,
- unsigned int parent_rate)
-@@ -710,6 +724,8 @@ static int aic32x4_setup_clocks(struct s
- return i;
- }
-
-+ aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
-+
- /* MCLK as PLL_CLKIN */
- snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_PLL_CLKIN_MASK,
- AIC32X4_PLL_CLKIN_MCLK << AIC32X4_PLL_CLKIN_SHIFT);
--- /dev/null
+From 0ce031ad1a56ab6201bf6fbe7e14bc1e0979e8c3 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:48 -0700
+Subject: [PATCH 405/725] ASoC: tlv320aic32x4: Model BDIV divider in CCF
+
+commit 9b484124ebd906c4d6bc826cc0d417e80cc1105c upstream.
+
+Model and manage BDIV divider as components in the Core
+Clock Framework. This should allow us to do some more complex
+clock management and power control. Also, some of the
+on-board chip clocks can be exposed to the outside, and this
+change will make those clocks easier to consume by other
+parts of the kernel.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4-clk.c | 36 ++++++++++++++++++
+ sound/soc/codecs/tlv320aic32x4.c | 56 +++++++++++++---------------
+ 2 files changed, 62 insertions(+), 30 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4-clk.c
++++ b/sound/soc/codecs/tlv320aic32x4-clk.c
+@@ -351,6 +351,34 @@ static const struct clk_ops aic32x4_div_
+ .recalc_rate = clk_aic32x4_div_recalc_rate,
+ };
+
++static int clk_aic32x4_bdiv_set_parent(struct clk_hw *hw, u8 index)
++{
++ struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
++
++ return regmap_update_bits(mux->regmap, AIC32X4_IFACE3,
++ AIC32X4_BDIVCLK_MASK, index);
++}
++
++static u8 clk_aic32x4_bdiv_get_parent(struct clk_hw *hw)
++{
++ struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
++ unsigned int val;
++
++ regmap_read(mux->regmap, AIC32X4_IFACE3, &val);
++
++ return val & AIC32X4_BDIVCLK_MASK;
++}
++
++static const struct clk_ops aic32x4_bdiv_ops = {
++ .prepare = clk_aic32x4_div_prepare,
++ .unprepare = clk_aic32x4_div_unprepare,
++ .set_parent = clk_aic32x4_bdiv_set_parent,
++ .get_parent = clk_aic32x4_bdiv_get_parent,
++ .set_rate = clk_aic32x4_div_set_rate,
++ .round_rate = clk_aic32x4_div_round_rate,
++ .recalc_rate = clk_aic32x4_div_recalc_rate,
++};
++
+ static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
+ {
+ .name = "pll",
+@@ -396,6 +424,14 @@ static struct aic32x4_clkdesc aic32x4_cl
+ .ops = &aic32x4_div_ops,
+ .reg = AIC32X4_MADC,
+ },
++ {
++ .name = "bdiv",
++ .parent_names =
++ (const char *[]) { "ndac", "mdac", "nadc", "madc" },
++ .num_parents = 4,
++ .ops = &aic32x4_bdiv_ops,
++ .reg = AIC32X4_BCLKN,
++ },
+ };
+
+ static struct clk *aic32x4_register_clk(struct device *dev,
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -57,7 +57,7 @@ struct aic32x4_rate_divs {
+ u8 aosr;
+ unsigned long nadc_rate;
+ unsigned long madc_rate;
+- u8 blck_N;
++ unsigned long bdiv_rate;
+ u8 r_block;
+ u8 p_block;
+ };
+@@ -310,53 +310,53 @@ static const struct snd_kcontrol_new aic
+ static const struct aic32x4_rate_divs aic32x4_divs[] = {
+ /* 8k rate */
+ { 12000000, 8000, 57120000, 768, 18432000, 6144000, 128, 18432000,
+- 1024000, 24, 1, 1 },
++ 1024000, 256000, 1, 1 },
+ { 24000000, 8000, 57120000, 768, 6144000, 6144000, 64, 2048000,
+- 512000, 24, 1, 1 },
++ 512000, 256000, 1, 1 },
+ { 25000000, 8000, 32620000, 768, 6144000, 6144000, 64, 2048000,
+- 512000, 24, 1, 1 },
++ 512000, 256000, 1, 1 },
+ /* 11.025k rate */
+ { 12000000, 11025, 44217600, 512, 11289600, 5644800, 128, 11289600,
+- 1411200, 16, 1, 1 },
++ 1411200, 352800, 1, 1 },
+ { 24000000, 11025, 44217600, 512, 5644800, 5644800, 64, 2822400,
+- 705600, 16, 1, 1 },
++ 705600, 352800, 1, 1 },
+ /* 16k rate */
+ { 12000000, 16000, 57120000, 384, 18432000, 6144000, 128, 18432000,
+- 2048000, 12, 1, 1 },
++ 2048000, 512000, 1, 1 },
+ { 24000000, 16000, 57120000, 384, 6144000, 6144000, 64, 5120000,
+- 1024000, 12, 1, 1 },
++ 1024000, 512000, 1, 1 },
+ { 25000000, 16000, 32620000, 384, 6144000, 6144000, 64, 5120000,
+- 1024000, 12, 1, 1 },
++ 1024000, 512000, 1, 1 },
+ /* 22.05k rate */
+ { 12000000, 22050, 44217600, 256, 22579200, 5644800, 128, 22579200,
+- 2822400, 8, 1, 1 },
++ 2822400, 705600, 1, 1 },
+ { 24000000, 22050, 44217600, 256, 5644800, 5644800, 64, 5644800,
+- 1411200, 8, 1, 1 },
++ 1411200, 705600, 1, 1 },
+ { 25000000, 22050, 19713750, 256, 5644800, 5644800, 64, 5644800,
+- 1411200, 8, 1, 1 },
++ 1411200, 705600, 1, 1 },
+ /* 32k rate */
+ { 12000000, 32000, 14112000, 192, 43008000, 6144000, 64, 43008000,
+- 2048000, 6, 1, 1 },
++ 2048000, 1024000, 1, 1 },
+ { 24000000, 32000, 14112000, 192, 12288000, 6144000, 64, 12288000,
+- 2048000, 6, 1, 1 },
++ 2048000, 1024000, 1, 1 },
+ /* 44.1k rate */
+ { 12000000, 44100, 44217600, 128, 45158400, 5644800, 128, 45158400,
+- 5644800, 4, 1, 1 },
++ 5644800, 1411200, 1, 1 },
+ { 24000000, 44100, 44217600, 128, 11289600, 5644800, 64, 11289600,
+- 2822400, 4, 1, 1 },
++ 2822400, 1411200, 1, 1 },
+ { 25000000, 44100, 19713750, 128, 11289600, 5644800, 64, 11289600,
+- 2822400, 4, 1, 1 },
++ 2822400, 1411200, 1, 1 },
+ /* 48k rate */
+ { 12000000, 48000, 18432000, 128, 49152000, 6144000, 128, 49152000,
+- 6144000, 4, 1, 1 },
++ 6144000, 1536000, 1, 1 },
+ { 24000000, 48000, 18432000, 128, 12288000, 6144000, 64, 12288000,
+- 3072000, 4, 1, 1 },
++ 3072000, 1536000, 1, 1 },
+ { 25000000, 48000, 75626250, 128, 12288000, 6144000, 64, 12288000,
+- 3072000, 4, 1, 1 },
++ 3072000, 1536000, 1, 1 },
+
+ /* 96k rate */
+ { 25000000, 96000, 75626250, 64, 24576000, 6144000, 64, 24576000,
+- 6144000, 1, 1, 9 },
++ 6144000, 3072000, 1, 9 },
+ };
+
+ static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
+@@ -745,6 +745,7 @@ static int aic32x4_setup_clocks(struct s
+ { .id = "madc" },
+ { .id = "ndac" },
+ { .id = "mdac" },
++ { .id = "bdiv" },
+ };
+
+ i = aic32x4_get_divs(parent_rate, sample_rate);
+@@ -762,14 +763,10 @@ static int aic32x4_setup_clocks(struct s
+ clk_set_rate(clocks[2].clk, aic32x4_divs[i].madc_rate);
+ clk_set_rate(clocks[3].clk, aic32x4_divs[i].ndac_rate);
+ clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
++ clk_set_rate(clocks[5].clk, aic32x4_divs[i].bdiv_rate);
+
+ aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
+
+- /* DAC_MOD_CLK as BDIV_CLKIN */
+- snd_soc_component_update_bits(component, AIC32X4_IFACE3,
+- AIC32X4_BDIVCLK_MASK,
+- AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
+-
+ /* DOSR MSB & LSB values */
+ snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
+ snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff));
+@@ -777,10 +774,6 @@ static int aic32x4_setup_clocks(struct s
+ /* AOSR value */
+ snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
+
+- /* BCLK N divider */
+- snd_soc_component_update_bits(component, AIC32X4_BCLKN,
+- AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
+-
+ return 0;
+ }
+
+@@ -1003,6 +996,8 @@ static int aic32x4_component_probe(struc
+ struct clk_bulk_data clocks[] = {
+ { .id = "codec_clkin" },
+ { .id = "pll" },
++ { .id = "bdiv" },
++ { .id = "mdac" },
+ };
+
+ ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
+@@ -1020,6 +1015,7 @@ static int aic32x4_component_probe(struc
+ aic32x4_setup_gpios(component);
+
+ clk_set_parent(clocks[0].clk, clocks[1].clk);
++ clk_set_parent(clocks[2].clk, clocks[3].clk);
+
+ /* Power platform configuration */
+ if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
+++ /dev/null
-From 12e71e0f6b9009a5de89b2073a53c55c9ae28a40 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:45 -0700
-Subject: [PATCH 405/703] ASoC: tlv320aic32x4: Model PLL in CCF
-
-commit 514b044cba667e4b7c383ec79b42b997e624b91d upstream.
-
-Model and manage the on-board PLL as a component in the Core
-Clock Framework. This should allow us to do some more complex
-clock management and power control. Also, some of the
-on-board chip clocks can be exposed to the outside, and this
-change will make those clocks easier to consume by other
-parts of the kernel.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/Kconfig | 1 +
- sound/soc/codecs/Makefile | 2 +-
- sound/soc/codecs/tlv320aic32x4-clk.c | 323 +++++++++++++++++++++++++++
- sound/soc/codecs/tlv320aic32x4.c | 195 ++++++++--------
- sound/soc/codecs/tlv320aic32x4.h | 5 +
- 5 files changed, 431 insertions(+), 95 deletions(-)
- create mode 100644 sound/soc/codecs/tlv320aic32x4-clk.c
-
---- a/sound/soc/codecs/Kconfig
-+++ b/sound/soc/codecs/Kconfig
-@@ -1025,6 +1025,7 @@ config SND_SOC_TLV320AIC31XX
-
- config SND_SOC_TLV320AIC32X4
- tristate
-+ depends on COMMON_CLK
-
- config SND_SOC_TLV320AIC32X4_I2C
- tristate "Texas Instruments TLV320AIC32x4 audio CODECs - I2C"
---- a/sound/soc/codecs/Makefile
-+++ b/sound/soc/codecs/Makefile
-@@ -182,7 +182,7 @@ snd-soc-tlv320aic23-i2c-objs := tlv320ai
- snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o
- snd-soc-tlv320aic26-objs := tlv320aic26.o
- snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o
--snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
-+snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o tlv320aic32x4-clk.o
- snd-soc-tlv320aic32x4-i2c-objs := tlv320aic32x4-i2c.o
- snd-soc-tlv320aic32x4-spi-objs := tlv320aic32x4-spi.o
- snd-soc-tlv320aic3x-objs := tlv320aic3x.o
---- /dev/null
-+++ b/sound/soc/codecs/tlv320aic32x4-clk.c
-@@ -0,0 +1,323 @@
-+/* SPDX-License-Identifier: GPL-2.0
-+ *
-+ * Clock Tree for the Texas Instruments TLV320AIC32x4
-+ *
-+ * Copyright 2019 Annaliese McDermond
-+ *
-+ * Author: Annaliese McDermond <nh6z@nh6z.net>
-+ */
-+
-+#include <linux/clk-provider.h>
-+#include <linux/clkdev.h>
-+#include <linux/regmap.h>
-+#include <linux/device.h>
-+
-+#include "tlv320aic32x4.h"
-+
-+#define to_clk_aic32x4(_hw) container_of(_hw, struct clk_aic32x4, hw)
-+struct clk_aic32x4 {
-+ struct clk_hw hw;
-+ struct device *dev;
-+ struct regmap *regmap;
-+ unsigned int reg;
-+};
-+
-+/*
-+ * struct clk_aic32x4_pll_muldiv - Multiplier/divider settings
-+ * @p: Divider
-+ * @r: first multiplier
-+ * @j: integer part of second multiplier
-+ * @d: decimal part of second multiplier
-+ */
-+struct clk_aic32x4_pll_muldiv {
-+ u8 p;
-+ u16 r;
-+ u8 j;
-+ u16 d;
-+};
-+
-+struct aic32x4_clkdesc {
-+ const char *name;
-+ const char * const *parent_names;
-+ unsigned int num_parents;
-+ const struct clk_ops *ops;
-+ unsigned int reg;
-+};
-+
-+static int clk_aic32x4_pll_prepare(struct clk_hw *hw)
-+{
-+ struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
-+
-+ return regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
-+ AIC32X4_PLLEN, AIC32X4_PLLEN);
-+}
-+
-+static void clk_aic32x4_pll_unprepare(struct clk_hw *hw)
-+{
-+ struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
-+
-+ regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
-+ AIC32X4_PLLEN, 0);
-+}
-+
-+static int clk_aic32x4_pll_is_prepared(struct clk_hw *hw)
-+{
-+ struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
-+
-+ unsigned int val;
-+ int ret;
-+
-+ ret = regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
-+ if (ret < 0)
-+ return ret;
-+
-+ return !!(val & AIC32X4_PLLEN);
-+}
-+
-+static int clk_aic32x4_pll_get_muldiv(struct clk_aic32x4 *pll,
-+ struct clk_aic32x4_pll_muldiv *settings)
-+{
-+ /* Change to use regmap_bulk_read? */
-+ unsigned int val;
-+ int ret;
-+
-+ ret = regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
-+ if (ret)
-+ return ret;
-+ settings->r = val & AIC32X4_PLL_R_MASK;
-+ settings->p = (val & AIC32X4_PLL_P_MASK) >> AIC32X4_PLL_P_SHIFT;
-+
-+ ret = regmap_read(pll->regmap, AIC32X4_PLLJ, &val);
-+ if (ret < 0)
-+ return ret;
-+ settings->j = val;
-+
-+ ret = regmap_read(pll->regmap, AIC32X4_PLLDMSB, &val);
-+ if (ret < 0)
-+ return ret;
-+ settings->d = val << 8;
-+
-+ ret = regmap_read(pll->regmap, AIC32X4_PLLDLSB, &val);
-+ if (ret < 0)
-+ return ret;
-+ settings->d |= val;
-+
-+ return 0;
-+}
-+
-+static int clk_aic32x4_pll_set_muldiv(struct clk_aic32x4 *pll,
-+ struct clk_aic32x4_pll_muldiv *settings)
-+{
-+ int ret;
-+ /* Change to use regmap_bulk_write for some if not all? */
-+
-+ ret = regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
-+ AIC32X4_PLL_R_MASK, settings->r);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
-+ AIC32X4_PLL_P_MASK,
-+ settings->p << AIC32X4_PLL_P_SHIFT);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = regmap_write(pll->regmap, AIC32X4_PLLJ, settings->j);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = regmap_write(pll->regmap, AIC32X4_PLLDMSB, (settings->d >> 8));
-+ if (ret < 0)
-+ return ret;
-+ ret = regmap_write(pll->regmap, AIC32X4_PLLDLSB, (settings->d & 0xff));
-+ if (ret < 0)
-+ return ret;
-+
-+ return 0;
-+}
-+
-+static unsigned long clk_aic32x4_pll_calc_rate(
-+ struct clk_aic32x4_pll_muldiv *settings,
-+ unsigned long parent_rate)
-+{
-+ u64 rate;
-+ /*
-+ * We scale j by 10000 to account for the decimal part of P and divide
-+ * it back out later.
-+ */
-+ rate = (u64) parent_rate * settings->r *
-+ ((settings->j * 10000) + settings->d);
-+
-+ return (unsigned long) DIV_ROUND_UP_ULL(rate, settings->p * 10000);
-+}
-+
-+static int clk_aic32x4_pll_calc_muldiv(struct clk_aic32x4_pll_muldiv *settings,
-+ unsigned long rate, unsigned long parent_rate)
-+{
-+ u64 multiplier;
-+
-+ settings->p = parent_rate / AIC32X4_MAX_PLL_CLKIN + 1;
-+ if (settings->p > 8)
-+ return -1;
-+
-+ /*
-+ * We scale this figure by 10000 so that we can get the decimal part
-+ * of the multiplier. This is because we can't do floating point
-+ * math in the kernel.
-+ */
-+ multiplier = (u64) rate * settings->p * 10000;
-+ do_div(multiplier, parent_rate);
-+
-+ /*
-+ * J can't be over 64, so R can scale this.
-+ * R can't be greater than 4.
-+ */
-+ settings->r = ((u32) multiplier / 640000) + 1;
-+ if (settings->r > 4)
-+ return -1;
-+ do_div(multiplier, settings->r);
-+
-+ /*
-+ * J can't be < 1.
-+ */
-+ if (multiplier < 10000)
-+ return -1;
-+
-+ /* Figure out the integer part, J, and the fractional part, D. */
-+ settings->j = (u32) multiplier / 10000;
-+ settings->d = (u32) multiplier % 10000;
-+
-+ return 0;
-+}
-+
-+static unsigned long clk_aic32x4_pll_recalc_rate(struct clk_hw *hw,
-+ unsigned long parent_rate)
-+{
-+ struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
-+ struct clk_aic32x4_pll_muldiv settings;
-+ int ret;
-+
-+ ret = clk_aic32x4_pll_get_muldiv(pll, &settings);
-+ if (ret < 0)
-+ return 0;
-+
-+ return clk_aic32x4_pll_calc_rate(&settings, parent_rate);
-+}
-+
-+static long clk_aic32x4_pll_round_rate(struct clk_hw *hw,
-+ unsigned long rate,
-+ unsigned long *parent_rate)
-+{
-+ struct clk_aic32x4_pll_muldiv settings;
-+ int ret;
-+
-+ ret = clk_aic32x4_pll_calc_muldiv(&settings, rate, *parent_rate);
-+ if (ret < 0)
-+ return 0;
-+
-+ return clk_aic32x4_pll_calc_rate(&settings, *parent_rate);
-+}
-+
-+static int clk_aic32x4_pll_set_rate(struct clk_hw *hw,
-+ unsigned long rate,
-+ unsigned long parent_rate)
-+{
-+ struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
-+ struct clk_aic32x4_pll_muldiv settings;
-+ int ret;
-+
-+ ret = clk_aic32x4_pll_calc_muldiv(&settings, rate, parent_rate);
-+ if (ret < 0)
-+ return -EINVAL;
-+
-+ return clk_aic32x4_pll_set_muldiv(pll, &settings);
-+}
-+
-+static int clk_aic32x4_pll_set_parent(struct clk_hw *hw, u8 index)
-+{
-+ struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
-+
-+ return regmap_update_bits(pll->regmap,
-+ AIC32X4_CLKMUX,
-+ AIC32X4_PLL_CLKIN_MASK,
-+ index << AIC32X4_PLL_CLKIN_SHIFT);
-+}
-+
-+static u8 clk_aic32x4_pll_get_parent(struct clk_hw *hw)
-+{
-+ struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
-+ unsigned int val;
-+
-+ regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
-+
-+ return (val & AIC32X4_PLL_CLKIN_MASK) >> AIC32X4_PLL_CLKIN_SHIFT;
-+}
-+
-+
-+static const struct clk_ops aic32x4_pll_ops = {
-+ .prepare = clk_aic32x4_pll_prepare,
-+ .unprepare = clk_aic32x4_pll_unprepare,
-+ .is_prepared = clk_aic32x4_pll_is_prepared,
-+ .recalc_rate = clk_aic32x4_pll_recalc_rate,
-+ .round_rate = clk_aic32x4_pll_round_rate,
-+ .set_rate = clk_aic32x4_pll_set_rate,
-+ .set_parent = clk_aic32x4_pll_set_parent,
-+ .get_parent = clk_aic32x4_pll_get_parent,
-+};
-+
-+static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
-+ {
-+ .name = "pll",
-+ .parent_names =
-+ (const char* []) { "mclk", "bclk", "gpio", "din" },
-+ .num_parents = 4,
-+ .ops = &aic32x4_pll_ops,
-+ .reg = 0,
-+ },
-+};
-+
-+static struct clk *aic32x4_register_clk(struct device *dev,
-+ struct aic32x4_clkdesc *desc)
-+{
-+ struct clk_init_data init;
-+ struct clk_aic32x4 *priv;
-+ const char *devname = dev_name(dev);
-+
-+ init.ops = desc->ops;
-+ init.name = desc->name;
-+ init.parent_names = desc->parent_names;
-+ init.num_parents = desc->num_parents;
-+ init.flags = 0;
-+
-+ priv = devm_kzalloc(dev, sizeof(struct clk_aic32x4), GFP_KERNEL);
-+ if (priv == NULL)
-+ return (struct clk *) -ENOMEM;
-+
-+ priv->dev = dev;
-+ priv->hw.init = &init;
-+ priv->regmap = dev_get_regmap(dev, NULL);
-+ priv->reg = desc->reg;
-+
-+ clk_hw_register_clkdev(&priv->hw, desc->name, devname);
-+ return devm_clk_register(dev, &priv->hw);
-+}
-+
-+int aic32x4_register_clocks(struct device *dev, const char *mclk_name)
-+{
-+ int i;
-+
-+ /*
-+ * These lines are here to preserve the current functionality of
-+ * the driver with regard to the DT. These should eventually be set
-+ * by DT nodes so that the connections can be set up in configuration
-+ * rather than code.
-+ */
-+ aic32x4_clkdesc_array[0].parent_names =
-+ (const char* []) { mclk_name, "bclk", "gpio", "din" };
-+
-+ for (i = 0; i < ARRAY_SIZE(aic32x4_clkdesc_array); ++i)
-+ aic32x4_register_clk(dev, &aic32x4_clkdesc_array[i]);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(aic32x4_register_clocks);
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -14,7 +14,7 @@
- *
- * 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
-+ * 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
-@@ -33,6 +33,7 @@
- #include <linux/cdev.h>
- #include <linux/slab.h>
- #include <linux/clk.h>
-+#include <linux/of_clk.h>
- #include <linux/regulator/consumer.h>
-
- #include <sound/tlv320aic32x4.h>
-@@ -49,9 +50,7 @@
- struct aic32x4_rate_divs {
- u32 mclk;
- u32 rate;
-- u8 p_val;
-- u8 pll_j;
-- u16 pll_d;
-+ unsigned long pll_rate;
- u16 dosr;
- u8 ndac;
- u8 mdac;
-@@ -71,6 +70,7 @@ struct aic32x4_priv {
- bool swapdacs;
- int rstn_gpio;
- struct clk *mclk;
-+ const char *mclk_name;
-
- struct regulator *supply_ldo;
- struct regulator *supply_iov;
-@@ -309,34 +309,34 @@ static const struct snd_kcontrol_new aic
-
- static const struct aic32x4_rate_divs aic32x4_divs[] = {
- /* 8k rate */
-- {12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24, 1, 1},
-- {24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24, 1, 1},
-- {25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24, 1, 1},
-+ { 12000000, 8000, 57120000, 768, 5, 3, 128, 5, 18, 24, 1, 1 },
-+ { 24000000, 8000, 57120000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
-+ { 25000000, 8000, 32620000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
- /* 11.025k rate */
-- {12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16, 1, 1},
-- {24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16, 1, 1},
-+ { 12000000, 11025, 44217600, 512, 8, 2, 128, 8, 8, 16, 1, 1 },
-+ { 24000000, 11025, 44217600, 512, 16, 1, 64, 32, 4, 16, 1, 1 },
- /* 16k rate */
-- {12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12, 1, 1},
-- {24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12, 1, 1},
-- {25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12, 1, 1},
-+ { 12000000, 16000, 57120000, 384, 5, 3, 128, 5, 9, 12, 1, 1 },
-+ { 24000000, 16000, 57120000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
-+ { 25000000, 16000, 32620000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
- /* 22.05k rate */
-- {12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8, 1, 1},
-- {24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8, 1, 1},
-- {25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8, 1, 1},
-+ { 12000000, 22050, 44217600, 256, 4, 4, 128, 4, 8, 8, 1, 1 },
-+ { 24000000, 22050, 44217600, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
-+ { 25000000, 22050, 19713750, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
- /* 32k rate */
-- {12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6, 1, 1},
-- {24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6, 1, 1},
-+ { 12000000, 32000, 14112000, 192, 2, 7, 64, 2, 21, 6, 1, 1 },
-+ { 24000000, 32000, 14112000, 192, 7, 2, 64, 7, 6, 6, 1, 1 },
- /* 44.1k rate */
-- {12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4, 1, 1},
-- {24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4, 1, 1},
-- {25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4, 1, 1},
-+ { 12000000, 44100, 44217600, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
-+ { 24000000, 44100, 44217600, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
-+ { 25000000, 44100, 19713750, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
- /* 48k rate */
-- {12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4, 1, 1},
-- {24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4, 1, 1},
-- {25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4, 1, 1},
-+ { 12000000, 48000, 18432000, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
-+ { 24000000, 48000, 18432000, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
-+ { 25000000, 48000, 75626250, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
-
- /* 96k rate */
-- {25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1, 1, 9},
-+ { 25000000, 96000, 75626250, 64, 4, 4, 64, 4, 4, 1, 1, 9 },
- };
-
- static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
-@@ -393,7 +393,7 @@ static const struct snd_kcontrol_new in3
- SOC_DAPM_ENUM("IN3_R L- Switch", in3r_lpga_n_enum),
- };
-
--/* Right mixer pins */
-+/* Right mixer pins */
- static SOC_ENUM_SINGLE_DECL(in1r_rpga_p_enum, AIC32X4_RMICPGAPIN, 6, resistor_text);
- static SOC_ENUM_SINGLE_DECL(in2r_rpga_p_enum, AIC32X4_RMICPGAPIN, 4, resistor_text);
- static SOC_ENUM_SINGLE_DECL(in3r_rpga_p_enum, AIC32X4_RMICPGAPIN, 2, resistor_text);
-@@ -597,7 +597,7 @@ static const struct snd_soc_dapm_route a
- static const struct regmap_range_cfg aic32x4_regmap_pages[] = {
- {
- .selector_reg = 0,
-- .selector_mask = 0xff,
-+ .selector_mask = 0xff,
- .window_start = 0,
- .window_len = 128,
- .range_min = 0,
-@@ -618,7 +618,7 @@ static inline int aic32x4_get_divs(int m
-
- for (i = 0; i < ARRAY_SIZE(aic32x4_divs); i++) {
- if ((aic32x4_divs[i].rate == rate)
-- && (aic32x4_divs[i].mclk == mclk)) {
-+ && (aic32x4_divs[i].mclk == mclk)) {
- return i;
- }
- }
-@@ -690,12 +690,12 @@ static int aic32x4_set_dai_fmt(struct sn
- }
-
- snd_soc_component_update_bits(component, AIC32X4_IFACE1,
-- AIC32X4_IFACE1_DATATYPE_MASK |
-- AIC32X4_IFACE1_MASTER_MASK, iface_reg_1);
-+ AIC32X4_IFACE1_DATATYPE_MASK |
-+ AIC32X4_IFACE1_MASTER_MASK, iface_reg_1);
- snd_soc_component_update_bits(component, AIC32X4_IFACE2,
-- AIC32X4_DATA_OFFSET_MASK, iface_reg_2);
-+ AIC32X4_DATA_OFFSET_MASK, iface_reg_2);
- snd_soc_component_update_bits(component, AIC32X4_IFACE3,
-- AIC32X4_BCLKINV_MASK, iface_reg_3);
-+ AIC32X4_BCLKINV_MASK, iface_reg_3);
-
- return 0;
- }
-@@ -717,6 +717,11 @@ static int aic32x4_setup_clocks(struct s
- unsigned int parent_rate)
- {
- int i;
-+ int ret;
-+
-+ struct clk_bulk_data clocks[] = {
-+ { .id = "pll" },
-+ };
-
- i = aic32x4_get_divs(parent_rate, sample_rate);
- if (i < 0) {
-@@ -724,39 +729,29 @@ static int aic32x4_setup_clocks(struct s
- return i;
- }
-
-+ ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
-+ if (ret)
-+ return ret;
-+
-+ clk_set_rate(clocks[0].clk, sample_rate);
-+
- aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
-
-- /* MCLK as PLL_CLKIN */
-- snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_PLL_CLKIN_MASK,
-- AIC32X4_PLL_CLKIN_MCLK << AIC32X4_PLL_CLKIN_SHIFT);
- /* PLL as CODEC_CLKIN */
-- snd_soc_component_update_bits(component, AIC32X4_CLKMUX, AIC32X4_CODEC_CLKIN_MASK,
-- AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT);
-+ snd_soc_component_update_bits(component, AIC32X4_CLKMUX,
-+ AIC32X4_CODEC_CLKIN_MASK,
-+ AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT);
- /* DAC_MOD_CLK as BDIV_CLKIN */
- snd_soc_component_update_bits(component, AIC32X4_IFACE3, AIC32X4_BDIVCLK_MASK,
-- AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
--
-- /* We will fix R value to 1 and will make P & J=K.D as variable */
-- snd_soc_component_update_bits(component, AIC32X4_PLLPR, AIC32X4_PLL_R_MASK, 0x01);
--
-- /* PLL P value */
-- snd_soc_component_update_bits(component, AIC32X4_PLLPR, AIC32X4_PLL_P_MASK,
-- aic32x4_divs[i].p_val << AIC32X4_PLL_P_SHIFT);
--
-- /* PLL J value */
-- snd_soc_component_write(component, AIC32X4_PLLJ, aic32x4_divs[i].pll_j);
--
-- /* PLL D value */
-- snd_soc_component_write(component, AIC32X4_PLLDMSB, (aic32x4_divs[i].pll_d >> 8));
-- snd_soc_component_write(component, AIC32X4_PLLDLSB, (aic32x4_divs[i].pll_d & 0xff));
-+ AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
-
- /* NDAC divider value */
- snd_soc_component_update_bits(component, AIC32X4_NDAC,
-- AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac);
-+ AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac);
-
- /* MDAC divider value */
- snd_soc_component_update_bits(component, AIC32X4_MDAC,
-- AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac);
-+ AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac);
-
- /* DOSR MSB & LSB values */
- snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
-@@ -764,18 +759,18 @@ static int aic32x4_setup_clocks(struct s
-
- /* NADC divider value */
- snd_soc_component_update_bits(component, AIC32X4_NADC,
-- AIC32X4_NADC_MASK, aic32x4_divs[i].nadc);
-+ AIC32X4_NADC_MASK, aic32x4_divs[i].nadc);
-
- /* MADC divider value */
- snd_soc_component_update_bits(component, AIC32X4_MADC,
-- AIC32X4_MADC_MASK, aic32x4_divs[i].madc);
-+ AIC32X4_MADC_MASK, aic32x4_divs[i].madc);
-
- /* AOSR value */
- snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
-
- /* BCLK N divider */
- snd_soc_component_update_bits(component, AIC32X4_BCLKN,
-- AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
-+ AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
-
- return 0;
- }
-@@ -794,23 +789,23 @@ static int aic32x4_hw_params(struct snd_
- switch (params_width(params)) {
- case 16:
- iface1_reg |= (AIC32X4_WORD_LEN_16BITS <<
-- AIC32X4_IFACE1_DATALEN_SHIFT);
-+ AIC32X4_IFACE1_DATALEN_SHIFT);
- break;
- case 20:
- iface1_reg |= (AIC32X4_WORD_LEN_20BITS <<
-- AIC32X4_IFACE1_DATALEN_SHIFT);
-+ AIC32X4_IFACE1_DATALEN_SHIFT);
- break;
- case 24:
- iface1_reg |= (AIC32X4_WORD_LEN_24BITS <<
-- AIC32X4_IFACE1_DATALEN_SHIFT);
-+ AIC32X4_IFACE1_DATALEN_SHIFT);
- break;
- case 32:
- iface1_reg |= (AIC32X4_WORD_LEN_32BITS <<
-- AIC32X4_IFACE1_DATALEN_SHIFT);
-+ AIC32X4_IFACE1_DATALEN_SHIFT);
- break;
- }
- snd_soc_component_update_bits(component, AIC32X4_IFACE1,
-- AIC32X4_IFACE1_DATALEN_MASK, iface1_reg);
-+ AIC32X4_IFACE1_DATALEN_MASK, iface1_reg);
-
- if (params_channels(params) == 1) {
- dacsetup_reg = AIC32X4_RDAC2LCHN | AIC32X4_LDAC2LCHN;
-@@ -821,7 +816,7 @@ static int aic32x4_hw_params(struct snd_
- dacsetup_reg = AIC32X4_LDAC2LCHN | AIC32X4_RDAC2RCHN;
- }
- snd_soc_component_update_bits(component, AIC32X4_DACSETUP,
-- AIC32X4_DAC_CHAN_MASK, dacsetup_reg);
-+ AIC32X4_DAC_CHAN_MASK, dacsetup_reg);
-
- return 0;
- }
-@@ -831,7 +826,7 @@ static int aic32x4_mute(struct snd_soc_d
- struct snd_soc_component *component = dai->component;
-
- snd_soc_component_update_bits(component, AIC32X4_DACMUTE,
-- AIC32X4_MUTEON, mute ? AIC32X4_MUTEON : 0);
-+ AIC32X4_MUTEON, mute ? AIC32X4_MUTEON : 0);
-
- return 0;
- }
-@@ -853,27 +848,27 @@ static int aic32x4_set_bias_level(struct
-
- /* Switch on PLL */
- snd_soc_component_update_bits(component, AIC32X4_PLLPR,
-- AIC32X4_PLLEN, AIC32X4_PLLEN);
-+ AIC32X4_PLLEN, AIC32X4_PLLEN);
-
- /* Switch on NDAC Divider */
- snd_soc_component_update_bits(component, AIC32X4_NDAC,
-- AIC32X4_NDACEN, AIC32X4_NDACEN);
-+ AIC32X4_NDACEN, AIC32X4_NDACEN);
-
- /* Switch on MDAC Divider */
- snd_soc_component_update_bits(component, AIC32X4_MDAC,
-- AIC32X4_MDACEN, AIC32X4_MDACEN);
-+ AIC32X4_MDACEN, AIC32X4_MDACEN);
-
- /* Switch on NADC Divider */
- snd_soc_component_update_bits(component, AIC32X4_NADC,
-- AIC32X4_NADCEN, AIC32X4_NADCEN);
-+ AIC32X4_NADCEN, AIC32X4_NADCEN);
-
- /* Switch on MADC Divider */
- snd_soc_component_update_bits(component, AIC32X4_MADC,
-- AIC32X4_MADCEN, AIC32X4_MADCEN);
-+ AIC32X4_MADCEN, AIC32X4_MADCEN);
-
- /* Switch on BCLK_N Divider */
- snd_soc_component_update_bits(component, AIC32X4_BCLKN,
-- AIC32X4_BCLKEN, AIC32X4_BCLKEN);
-+ AIC32X4_BCLKEN, AIC32X4_BCLKEN);
- break;
- case SND_SOC_BIAS_PREPARE:
- break;
-@@ -884,27 +879,27 @@ static int aic32x4_set_bias_level(struct
-
- /* Switch off BCLK_N Divider */
- snd_soc_component_update_bits(component, AIC32X4_BCLKN,
-- AIC32X4_BCLKEN, 0);
-+ AIC32X4_BCLKEN, 0);
-
- /* Switch off MADC Divider */
- snd_soc_component_update_bits(component, AIC32X4_MADC,
-- AIC32X4_MADCEN, 0);
-+ AIC32X4_MADCEN, 0);
-
- /* Switch off NADC Divider */
- snd_soc_component_update_bits(component, AIC32X4_NADC,
-- AIC32X4_NADCEN, 0);
-+ AIC32X4_NADCEN, 0);
-
- /* Switch off MDAC Divider */
- snd_soc_component_update_bits(component, AIC32X4_MDAC,
-- AIC32X4_MDACEN, 0);
-+ AIC32X4_MDACEN, 0);
-
- /* Switch off NDAC Divider */
- snd_soc_component_update_bits(component, AIC32X4_NDAC,
-- AIC32X4_NDACEN, 0);
-+ AIC32X4_NDACEN, 0);
-
- /* Switch off PLL */
- snd_soc_component_update_bits(component, AIC32X4_PLLPR,
-- AIC32X4_PLLEN, 0);
-+ AIC32X4_PLLEN, 0);
-
- /* Switch off master clock */
- clk_disable_unprepare(aic32x4->mclk);
-@@ -916,7 +911,7 @@ static int aic32x4_set_bias_level(struct
- }
-
- #define AIC32X4_RATES SNDRV_PCM_RATE_8000_96000
--#define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
-+#define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
- | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
-
- static const struct snd_soc_dai_ops aic32x4_ops = {
-@@ -929,17 +924,17 @@ static const struct snd_soc_dai_ops aic3
- static struct snd_soc_dai_driver aic32x4_dai = {
- .name = "tlv320aic32x4-hifi",
- .playback = {
-- .stream_name = "Playback",
-- .channels_min = 1,
-- .channels_max = 2,
-- .rates = AIC32X4_RATES,
-- .formats = AIC32X4_FORMATS,},
-+ .stream_name = "Playback",
-+ .channels_min = 1,
-+ .channels_max = 2,
-+ .rates = AIC32X4_RATES,
-+ .formats = AIC32X4_FORMATS,},
- .capture = {
-- .stream_name = "Capture",
-- .channels_min = 1,
-- .channels_max = 2,
-- .rates = AIC32X4_RATES,
-- .formats = AIC32X4_FORMATS,},
-+ .stream_name = "Capture",
-+ .channels_min = 1,
-+ .channels_max = 2,
-+ .rates = AIC32X4_RATES,
-+ .formats = AIC32X4_FORMATS,},
- .ops = &aic32x4_ops,
- .symmetric_rates = 1,
- };
-@@ -952,7 +947,7 @@ static void aic32x4_setup_gpios(struct s
- /* MFP1 */
- if (aic32x4->setup->gpio_func[0] != AIC32X4_MFPX_DEFAULT_VALUE) {
- snd_soc_component_write(component, AIC32X4_DINCTL,
-- aic32x4->setup->gpio_func[0]);
-+ aic32x4->setup->gpio_func[0]);
- snd_soc_add_component_controls(component, aic32x4_mfp1,
- ARRAY_SIZE(aic32x4_mfp1));
- }
-@@ -960,7 +955,7 @@ static void aic32x4_setup_gpios(struct s
- /* MFP2 */
- if (aic32x4->setup->gpio_func[1] != AIC32X4_MFPX_DEFAULT_VALUE) {
- snd_soc_component_write(component, AIC32X4_DOUTCTL,
-- aic32x4->setup->gpio_func[1]);
-+ aic32x4->setup->gpio_func[1]);
- snd_soc_add_component_controls(component, aic32x4_mfp2,
- ARRAY_SIZE(aic32x4_mfp2));
- }
-@@ -968,7 +963,7 @@ static void aic32x4_setup_gpios(struct s
- /* MFP3 */
- if (aic32x4->setup->gpio_func[2] != AIC32X4_MFPX_DEFAULT_VALUE) {
- snd_soc_component_write(component, AIC32X4_SCLKCTL,
-- aic32x4->setup->gpio_func[2]);
-+ aic32x4->setup->gpio_func[2]);
- snd_soc_add_component_controls(component, aic32x4_mfp3,
- ARRAY_SIZE(aic32x4_mfp3));
- }
-@@ -976,7 +971,7 @@ static void aic32x4_setup_gpios(struct s
- /* MFP4 */
- if (aic32x4->setup->gpio_func[3] != AIC32X4_MFPX_DEFAULT_VALUE) {
- snd_soc_component_write(component, AIC32X4_MISOCTL,
-- aic32x4->setup->gpio_func[3]);
-+ aic32x4->setup->gpio_func[3]);
- snd_soc_add_component_controls(component, aic32x4_mfp4,
- ARRAY_SIZE(aic32x4_mfp4));
- }
-@@ -984,7 +979,7 @@ static void aic32x4_setup_gpios(struct s
- /* MFP5 */
- if (aic32x4->setup->gpio_func[4] != AIC32X4_MFPX_DEFAULT_VALUE) {
- snd_soc_component_write(component, AIC32X4_GPIOCTL,
-- aic32x4->setup->gpio_func[4]);
-+ aic32x4->setup->gpio_func[4]);
- snd_soc_add_component_controls(component, aic32x4_mfp5,
- ARRAY_SIZE(aic32x4_mfp5));
- }
-@@ -1007,8 +1002,8 @@ static int aic32x4_component_probe(struc
-
- /* Power platform configuration */
- if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
-- snd_soc_component_write(component, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN |
-- AIC32X4_MICBIAS_2075V);
-+ snd_soc_component_write(component, AIC32X4_MICBIAS,
-+ AIC32X4_MICBIAS_LDOIN | AIC32X4_MICBIAS_2075V);
- }
- if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE)
- snd_soc_component_write(component, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
-@@ -1071,12 +1066,18 @@ static int aic32x4_parse_dt(struct aic32
- struct device_node *np)
- {
- struct aic32x4_setup_data *aic32x4_setup;
-+ int ret;
-
- aic32x4_setup = devm_kzalloc(aic32x4->dev, sizeof(*aic32x4_setup),
- GFP_KERNEL);
- if (!aic32x4_setup)
- return -ENOMEM;
-
-+ ret = of_property_match_string(np, "clock-names", "mclk");
-+ if (ret < 0)
-+ return -EINVAL;
-+ aic32x4->mclk_name = of_clk_get_parent_name(np, ret);
-+
- aic32x4->swapdacs = false;
- aic32x4->micpga_routing = 0;
- aic32x4->rstn_gpio = of_get_named_gpio(np, "reset-gpios", 0);
-@@ -1198,7 +1199,7 @@ int aic32x4_probe(struct device *dev, st
- return PTR_ERR(regmap);
-
- aic32x4 = devm_kzalloc(dev, sizeof(struct aic32x4_priv),
-- GFP_KERNEL);
-+ GFP_KERNEL);
- if (aic32x4 == NULL)
- return -ENOMEM;
-
-@@ -1210,6 +1211,7 @@ int aic32x4_probe(struct device *dev, st
- aic32x4->swapdacs = pdata->swapdacs;
- aic32x4->micpga_routing = pdata->micpga_routing;
- aic32x4->rstn_gpio = pdata->rstn_gpio;
-+ aic32x4->mclk_name = "mclk";
- } else if (np) {
- ret = aic32x4_parse_dt(aic32x4, np);
- if (ret) {
-@@ -1221,6 +1223,7 @@ int aic32x4_probe(struct device *dev, st
- aic32x4->swapdacs = false;
- aic32x4->micpga_routing = 0;
- aic32x4->rstn_gpio = -1;
-+ aic32x4->mclk_name = "mclk";
- }
-
- aic32x4->mclk = devm_clk_get(dev, "mclk");
-@@ -1229,6 +1232,10 @@ int aic32x4_probe(struct device *dev, st
- return PTR_ERR(aic32x4->mclk);
- }
-
-+ ret = aic32x4_register_clocks(dev, aic32x4->mclk_name);
-+ if (ret)
-+ return ret;
-+
- if (gpio_is_valid(aic32x4->rstn_gpio)) {
- ret = devm_gpio_request_one(dev, aic32x4->rstn_gpio,
- GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
---- a/sound/soc/codecs/tlv320aic32x4.h
-+++ b/sound/soc/codecs/tlv320aic32x4.h
-@@ -16,6 +16,7 @@ struct regmap_config;
- extern const struct regmap_config aic32x4_regmap_config;
- int aic32x4_probe(struct device *dev, struct regmap *regmap);
- int aic32x4_remove(struct device *dev);
-+int aic32x4_register_clocks(struct device *dev, const char *mclk_name);
-
- /* tlv320aic32x4 register space (in decimal to match datasheet) */
-
-@@ -205,4 +206,8 @@ int aic32x4_remove(struct device *dev);
- #define AIC32X4_RMICPGANIN_IN1L_10K 0x10
- #define AIC32X4_RMICPGANIN_CM1R_10K 0x40
-
-+/* Clock Limits */
-+#define AIC32X4_MAX_PLL_CLKIN 20000000
-+
-+
- #endif /* _TLV320AIC32X4_H */
--- /dev/null
+From 95c6e21b0ab366f5433d5c89aa5ae961ad40d2e6 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:49 -0700
+Subject: [PATCH 406/725] ASoC: tlv320aic32x4: Control clock gating with CCF
+
+commit d25970b5fd51e9fcf0afbe190908ea4049454da4 upstream.
+
+Control the clock gating to the various clock components to use
+the CCF. This allows us to prepare_enalbe only 3 clocks and the
+relationships assigned to them will cause upstream clockss to
+enable automatically. Additionally we can do this in a single
+call to the CCF.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 67 +++++++-------------------------
+ 1 file changed, 13 insertions(+), 54 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -836,41 +836,25 @@ static int aic32x4_mute(struct snd_soc_d
+ static int aic32x4_set_bias_level(struct snd_soc_component *component,
+ enum snd_soc_bias_level level)
+ {
+- struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
+ int ret;
+
++ struct clk_bulk_data clocks[] = {
++ { .id = "madc" },
++ { .id = "mdac" },
++ { .id = "bdiv" },
++ };
++
++ ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
++ if (ret)
++ return ret;
++
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+- /* Switch on master clock */
+- ret = clk_prepare_enable(aic32x4->mclk);
++ ret = clk_bulk_prepare_enable(ARRAY_SIZE(clocks), clocks);
+ if (ret) {
+- dev_err(component->dev, "Failed to enable master clock\n");
++ dev_err(component->dev, "Failed to enable clocks\n");
+ return ret;
+ }
+-
+- /* Switch on PLL */
+- snd_soc_component_update_bits(component, AIC32X4_PLLPR,
+- AIC32X4_PLLEN, AIC32X4_PLLEN);
+-
+- /* Switch on NDAC Divider */
+- snd_soc_component_update_bits(component, AIC32X4_NDAC,
+- AIC32X4_NDACEN, AIC32X4_NDACEN);
+-
+- /* Switch on MDAC Divider */
+- snd_soc_component_update_bits(component, AIC32X4_MDAC,
+- AIC32X4_MDACEN, AIC32X4_MDACEN);
+-
+- /* Switch on NADC Divider */
+- snd_soc_component_update_bits(component, AIC32X4_NADC,
+- AIC32X4_NADCEN, AIC32X4_NADCEN);
+-
+- /* Switch on MADC Divider */
+- snd_soc_component_update_bits(component, AIC32X4_MADC,
+- AIC32X4_MADCEN, AIC32X4_MADCEN);
+-
+- /* Switch on BCLK_N Divider */
+- snd_soc_component_update_bits(component, AIC32X4_BCLKN,
+- AIC32X4_BCLKEN, AIC32X4_BCLKEN);
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ break;
+@@ -879,32 +863,7 @@ static int aic32x4_set_bias_level(struct
+ if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
+ break;
+
+- /* Switch off BCLK_N Divider */
+- snd_soc_component_update_bits(component, AIC32X4_BCLKN,
+- AIC32X4_BCLKEN, 0);
+-
+- /* Switch off MADC Divider */
+- snd_soc_component_update_bits(component, AIC32X4_MADC,
+- AIC32X4_MADCEN, 0);
+-
+- /* Switch off NADC Divider */
+- snd_soc_component_update_bits(component, AIC32X4_NADC,
+- AIC32X4_NADCEN, 0);
+-
+- /* Switch off MDAC Divider */
+- snd_soc_component_update_bits(component, AIC32X4_MDAC,
+- AIC32X4_MDACEN, 0);
+-
+- /* Switch off NDAC Divider */
+- snd_soc_component_update_bits(component, AIC32X4_NDAC,
+- AIC32X4_NDACEN, 0);
+-
+- /* Switch off PLL */
+- snd_soc_component_update_bits(component, AIC32X4_PLLPR,
+- AIC32X4_PLLEN, 0);
+-
+- /* Switch off master clock */
+- clk_disable_unprepare(aic32x4->mclk);
++ clk_bulk_disable_unprepare(ARRAY_SIZE(clocks), clocks);
+ break;
+ case SND_SOC_BIAS_OFF:
+ break;
+++ /dev/null
-From f0192af931c8aea25440c014b9a995a3bf1a5363 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:46 -0700
-Subject: [PATCH 406/703] ASoC: tlv320aic32x4: Model CODEC_CLKIN in CCF
-
-commit fd2df3aeafa4b4cc468d58e147e0822967034b71 upstream.
-
-Model and manage codec clock input as a component in the Core
-Clock Framework. This should allow us to do some more complex
-clock management and power control. Also, some of the
-on-board chip clocks can be exposed to the outside, and this
-change will make those clocks easier to consume by other
-parts of the kernel.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4-clk.c | 34 ++++++++++++++++++++++++++++
- sound/soc/codecs/tlv320aic32x4.c | 18 +++++++++++----
- 2 files changed, 47 insertions(+), 5 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4-clk.c
-+++ b/sound/soc/codecs/tlv320aic32x4-clk.c
-@@ -265,6 +265,30 @@ static const struct clk_ops aic32x4_pll_
- .get_parent = clk_aic32x4_pll_get_parent,
- };
-
-+static int clk_aic32x4_codec_clkin_set_parent(struct clk_hw *hw, u8 index)
-+{
-+ struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
-+
-+ return regmap_update_bits(mux->regmap,
-+ AIC32X4_CLKMUX,
-+ AIC32X4_CODEC_CLKIN_MASK, index << AIC32X4_CODEC_CLKIN_SHIFT);
-+}
-+
-+static u8 clk_aic32x4_codec_clkin_get_parent(struct clk_hw *hw)
-+{
-+ struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
-+ unsigned int val;
-+
-+ regmap_read(mux->regmap, AIC32X4_CLKMUX, &val);
-+
-+ return (val & AIC32X4_CODEC_CLKIN_MASK) >> AIC32X4_CODEC_CLKIN_SHIFT;
-+}
-+
-+static const struct clk_ops aic32x4_codec_clkin_ops = {
-+ .set_parent = clk_aic32x4_codec_clkin_set_parent,
-+ .get_parent = clk_aic32x4_codec_clkin_get_parent,
-+};
-+
- static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
- {
- .name = "pll",
-@@ -274,6 +298,14 @@ static struct aic32x4_clkdesc aic32x4_cl
- .ops = &aic32x4_pll_ops,
- .reg = 0,
- },
-+ {
-+ .name = "codec_clkin",
-+ .parent_names =
-+ (const char *[]) { "mclk", "bclk", "gpio", "pll" },
-+ .num_parents = 4,
-+ .ops = &aic32x4_codec_clkin_ops,
-+ .reg = 0,
-+ },
- };
-
- static struct clk *aic32x4_register_clk(struct device *dev,
-@@ -314,6 +346,8 @@ int aic32x4_register_clocks(struct devic
- */
- aic32x4_clkdesc_array[0].parent_names =
- (const char* []) { mclk_name, "bclk", "gpio", "din" };
-+ aic32x4_clkdesc_array[1].parent_names =
-+ (const char *[]) { mclk_name, "bclk", "gpio", "pll" };
-
- for (i = 0; i < ARRAY_SIZE(aic32x4_clkdesc_array); ++i)
- aic32x4_register_clk(dev, &aic32x4_clkdesc_array[i]);
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -737,12 +737,9 @@ static int aic32x4_setup_clocks(struct s
-
- aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
-
-- /* PLL as CODEC_CLKIN */
-- snd_soc_component_update_bits(component, AIC32X4_CLKMUX,
-- AIC32X4_CODEC_CLKIN_MASK,
-- AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT);
- /* DAC_MOD_CLK as BDIV_CLKIN */
-- snd_soc_component_update_bits(component, AIC32X4_IFACE3, AIC32X4_BDIVCLK_MASK,
-+ snd_soc_component_update_bits(component, AIC32X4_IFACE3,
-+ AIC32X4_BDIVCLK_MASK,
- AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
-
- /* NDAC divider value */
-@@ -989,6 +986,15 @@ static int aic32x4_component_probe(struc
- {
- struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
- u32 tmp_reg;
-+ int ret;
-+
-+ struct clk_bulk_data clocks[] = {
-+ { .id = "codec_clkin" },
-+ };
-+
-+ ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
-+ if (ret)
-+ return ret;
-
- if (gpio_is_valid(aic32x4->rstn_gpio)) {
- ndelay(10);
-@@ -1000,6 +1006,8 @@ static int aic32x4_component_probe(struc
- if (aic32x4->setup)
- aic32x4_setup_gpios(component);
-
-+ clk_set_parent(clocks[0].clk, clocks[1].clk);
-+
- /* Power platform configuration */
- if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
- snd_soc_component_write(component, AIC32X4_MICBIAS,
+++ /dev/null
-From 532403e3a16502340711131fd075cd7dd4dd20b1 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:47 -0700
-Subject: [PATCH 407/703] ASoC: tlv320aic32x4: Model DAC/ADC dividers in CCF
-
-commit a51b50062091619915c5155085bbe13a7aca6903 upstream.
-
-Model and manage DAC/ADC dividers as components in the Core
-Clock Framework. This should allow us to do some more complex
-clock management and power control. Also, some of the
-on-board chip clocks can be exposed to the outside, and this
-change will make those clocks easier to consume by other
-parts of the kernel.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4-clk.c | 90 ++++++++++++++++++++++++
- sound/soc/codecs/tlv320aic32x4.c | 101 +++++++++++++++------------
- sound/soc/codecs/tlv320aic32x4.h | 4 ++
- 3 files changed, 151 insertions(+), 44 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4-clk.c
-+++ b/sound/soc/codecs/tlv320aic32x4-clk.c
-@@ -289,6 +289,68 @@ static const struct clk_ops aic32x4_code
- .get_parent = clk_aic32x4_codec_clkin_get_parent,
- };
-
-+static int clk_aic32x4_div_prepare(struct clk_hw *hw)
-+{
-+ struct clk_aic32x4 *div = to_clk_aic32x4(hw);
-+
-+ return regmap_update_bits(div->regmap, div->reg,
-+ AIC32X4_DIVEN, AIC32X4_DIVEN);
-+}
-+
-+static void clk_aic32x4_div_unprepare(struct clk_hw *hw)
-+{
-+ struct clk_aic32x4 *div = to_clk_aic32x4(hw);
-+
-+ regmap_update_bits(div->regmap, div->reg,
-+ AIC32X4_DIVEN, 0);
-+}
-+
-+static int clk_aic32x4_div_set_rate(struct clk_hw *hw, unsigned long rate,
-+ unsigned long parent_rate)
-+{
-+ struct clk_aic32x4 *div = to_clk_aic32x4(hw);
-+ u8 divisor;
-+
-+ divisor = DIV_ROUND_UP(parent_rate, rate);
-+ if (divisor > 128)
-+ return -EINVAL;
-+
-+ return regmap_update_bits(div->regmap, div->reg,
-+ AIC32X4_DIV_MASK, divisor);
-+}
-+
-+static long clk_aic32x4_div_round_rate(struct clk_hw *hw, unsigned long rate,
-+ unsigned long *parent_rate)
-+{
-+ unsigned long divisor;
-+
-+ divisor = DIV_ROUND_UP(*parent_rate, rate);
-+ if (divisor > 128)
-+ return -EINVAL;
-+
-+ return DIV_ROUND_UP(*parent_rate, divisor);
-+}
-+
-+static unsigned long clk_aic32x4_div_recalc_rate(struct clk_hw *hw,
-+ unsigned long parent_rate)
-+{
-+ struct clk_aic32x4 *div = to_clk_aic32x4(hw);
-+
-+ unsigned int val;
-+
-+ regmap_read(div->regmap, div->reg, &val);
-+
-+ return DIV_ROUND_UP(parent_rate, val & AIC32X4_DIV_MASK);
-+}
-+
-+static const struct clk_ops aic32x4_div_ops = {
-+ .prepare = clk_aic32x4_div_prepare,
-+ .unprepare = clk_aic32x4_div_unprepare,
-+ .set_rate = clk_aic32x4_div_set_rate,
-+ .round_rate = clk_aic32x4_div_round_rate,
-+ .recalc_rate = clk_aic32x4_div_recalc_rate,
-+};
-+
- static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
- {
- .name = "pll",
-@@ -306,6 +368,34 @@ static struct aic32x4_clkdesc aic32x4_cl
- .ops = &aic32x4_codec_clkin_ops,
- .reg = 0,
- },
-+ {
-+ .name = "ndac",
-+ .parent_names = (const char * []) { "codec_clkin" },
-+ .num_parents = 1,
-+ .ops = &aic32x4_div_ops,
-+ .reg = AIC32X4_NDAC,
-+ },
-+ {
-+ .name = "mdac",
-+ .parent_names = (const char * []) { "ndac" },
-+ .num_parents = 1,
-+ .ops = &aic32x4_div_ops,
-+ .reg = AIC32X4_MDAC,
-+ },
-+ {
-+ .name = "nadc",
-+ .parent_names = (const char * []) { "codec_clkin" },
-+ .num_parents = 1,
-+ .ops = &aic32x4_div_ops,
-+ .reg = AIC32X4_NADC,
-+ },
-+ {
-+ .name = "madc",
-+ .parent_names = (const char * []) { "nadc" },
-+ .num_parents = 1,
-+ .ops = &aic32x4_div_ops,
-+ .reg = AIC32X4_MADC,
-+ },
- };
-
- static struct clk *aic32x4_register_clk(struct device *dev,
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -52,11 +52,11 @@ struct aic32x4_rate_divs {
- u32 rate;
- unsigned long pll_rate;
- u16 dosr;
-- u8 ndac;
-- u8 mdac;
-+ unsigned long ndac_rate;
-+ unsigned long mdac_rate;
- u8 aosr;
-- u8 nadc;
-- u8 madc;
-+ unsigned long nadc_rate;
-+ unsigned long madc_rate;
- u8 blck_N;
- u8 r_block;
- u8 p_block;
-@@ -309,34 +309,54 @@ static const struct snd_kcontrol_new aic
-
- static const struct aic32x4_rate_divs aic32x4_divs[] = {
- /* 8k rate */
-- { 12000000, 8000, 57120000, 768, 5, 3, 128, 5, 18, 24, 1, 1 },
-- { 24000000, 8000, 57120000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
-- { 25000000, 8000, 32620000, 768, 15, 1, 64, 45, 4, 24, 1, 1 },
-+ { 12000000, 8000, 57120000, 768, 18432000, 6144000, 128, 18432000,
-+ 1024000, 24, 1, 1 },
-+ { 24000000, 8000, 57120000, 768, 6144000, 6144000, 64, 2048000,
-+ 512000, 24, 1, 1 },
-+ { 25000000, 8000, 32620000, 768, 6144000, 6144000, 64, 2048000,
-+ 512000, 24, 1, 1 },
- /* 11.025k rate */
-- { 12000000, 11025, 44217600, 512, 8, 2, 128, 8, 8, 16, 1, 1 },
-- { 24000000, 11025, 44217600, 512, 16, 1, 64, 32, 4, 16, 1, 1 },
-+ { 12000000, 11025, 44217600, 512, 11289600, 5644800, 128, 11289600,
-+ 1411200, 16, 1, 1 },
-+ { 24000000, 11025, 44217600, 512, 5644800, 5644800, 64, 2822400,
-+ 705600, 16, 1, 1 },
- /* 16k rate */
-- { 12000000, 16000, 57120000, 384, 5, 3, 128, 5, 9, 12, 1, 1 },
-- { 24000000, 16000, 57120000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
-- { 25000000, 16000, 32620000, 384, 15, 1, 64, 18, 5, 12, 1, 1 },
-+ { 12000000, 16000, 57120000, 384, 18432000, 6144000, 128, 18432000,
-+ 2048000, 12, 1, 1 },
-+ { 24000000, 16000, 57120000, 384, 6144000, 6144000, 64, 5120000,
-+ 1024000, 12, 1, 1 },
-+ { 25000000, 16000, 32620000, 384, 6144000, 6144000, 64, 5120000,
-+ 1024000, 12, 1, 1 },
- /* 22.05k rate */
-- { 12000000, 22050, 44217600, 256, 4, 4, 128, 4, 8, 8, 1, 1 },
-- { 24000000, 22050, 44217600, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
-- { 25000000, 22050, 19713750, 256, 16, 1, 64, 16, 4, 8, 1, 1 },
-+ { 12000000, 22050, 44217600, 256, 22579200, 5644800, 128, 22579200,
-+ 2822400, 8, 1, 1 },
-+ { 24000000, 22050, 44217600, 256, 5644800, 5644800, 64, 5644800,
-+ 1411200, 8, 1, 1 },
-+ { 25000000, 22050, 19713750, 256, 5644800, 5644800, 64, 5644800,
-+ 1411200, 8, 1, 1 },
- /* 32k rate */
-- { 12000000, 32000, 14112000, 192, 2, 7, 64, 2, 21, 6, 1, 1 },
-- { 24000000, 32000, 14112000, 192, 7, 2, 64, 7, 6, 6, 1, 1 },
-+ { 12000000, 32000, 14112000, 192, 43008000, 6144000, 64, 43008000,
-+ 2048000, 6, 1, 1 },
-+ { 24000000, 32000, 14112000, 192, 12288000, 6144000, 64, 12288000,
-+ 2048000, 6, 1, 1 },
- /* 44.1k rate */
-- { 12000000, 44100, 44217600, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
-- { 24000000, 44100, 44217600, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
-- { 25000000, 44100, 19713750, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
-+ { 12000000, 44100, 44217600, 128, 45158400, 5644800, 128, 45158400,
-+ 5644800, 4, 1, 1 },
-+ { 24000000, 44100, 44217600, 128, 11289600, 5644800, 64, 11289600,
-+ 2822400, 4, 1, 1 },
-+ { 25000000, 44100, 19713750, 128, 11289600, 5644800, 64, 11289600,
-+ 2822400, 4, 1, 1 },
- /* 48k rate */
-- { 12000000, 48000, 18432000, 128, 2, 8, 128, 2, 8, 4, 1, 1 },
-- { 24000000, 48000, 18432000, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
-- { 25000000, 48000, 75626250, 128, 8, 2, 64, 8, 4, 4, 1, 1 },
-+ { 12000000, 48000, 18432000, 128, 49152000, 6144000, 128, 49152000,
-+ 6144000, 4, 1, 1 },
-+ { 24000000, 48000, 18432000, 128, 12288000, 6144000, 64, 12288000,
-+ 3072000, 4, 1, 1 },
-+ { 25000000, 48000, 75626250, 128, 12288000, 6144000, 64, 12288000,
-+ 3072000, 4, 1, 1 },
-
- /* 96k rate */
-- { 25000000, 96000, 75626250, 64, 4, 4, 64, 4, 4, 1, 1, 9 },
-+ { 25000000, 96000, 75626250, 64, 24576000, 6144000, 64, 24576000,
-+ 6144000, 1, 1, 9 },
- };
-
- static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
-@@ -721,6 +741,10 @@ static int aic32x4_setup_clocks(struct s
-
- struct clk_bulk_data clocks[] = {
- { .id = "pll" },
-+ { .id = "nadc" },
-+ { .id = "madc" },
-+ { .id = "ndac" },
-+ { .id = "mdac" },
- };
-
- i = aic32x4_get_divs(parent_rate, sample_rate);
-@@ -733,7 +757,11 @@ static int aic32x4_setup_clocks(struct s
- if (ret)
- return ret;
-
-- clk_set_rate(clocks[0].clk, sample_rate);
-+ clk_set_rate(clocks[0].clk, aic32x4_divs[i].pll_rate);
-+ clk_set_rate(clocks[1].clk, aic32x4_divs[i].nadc_rate);
-+ clk_set_rate(clocks[2].clk, aic32x4_divs[i].madc_rate);
-+ clk_set_rate(clocks[3].clk, aic32x4_divs[i].ndac_rate);
-+ clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
-
- aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
-
-@@ -742,26 +770,10 @@ static int aic32x4_setup_clocks(struct s
- AIC32X4_BDIVCLK_MASK,
- AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
-
-- /* NDAC divider value */
-- snd_soc_component_update_bits(component, AIC32X4_NDAC,
-- AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac);
--
-- /* MDAC divider value */
-- snd_soc_component_update_bits(component, AIC32X4_MDAC,
-- AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac);
--
- /* DOSR MSB & LSB values */
- snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
- snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff));
-
-- /* NADC divider value */
-- snd_soc_component_update_bits(component, AIC32X4_NADC,
-- AIC32X4_NADC_MASK, aic32x4_divs[i].nadc);
--
-- /* MADC divider value */
-- snd_soc_component_update_bits(component, AIC32X4_MADC,
-- AIC32X4_MADC_MASK, aic32x4_divs[i].madc);
--
- /* AOSR value */
- snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
-
-@@ -773,8 +785,8 @@ static int aic32x4_setup_clocks(struct s
- }
-
- static int aic32x4_hw_params(struct snd_pcm_substream *substream,
-- struct snd_pcm_hw_params *params,
-- struct snd_soc_dai *dai)
-+ struct snd_pcm_hw_params *params,
-+ struct snd_soc_dai *dai)
- {
- struct snd_soc_component *component = dai->component;
- struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
-@@ -989,7 +1001,8 @@ static int aic32x4_component_probe(struc
- int ret;
-
- struct clk_bulk_data clocks[] = {
-- { .id = "codec_clkin" },
-+ { .id = "codec_clkin" },
-+ { .id = "pll" },
- };
-
- ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
---- a/sound/soc/codecs/tlv320aic32x4.h
-+++ b/sound/soc/codecs/tlv320aic32x4.h
-@@ -206,6 +206,10 @@ int aic32x4_register_clocks(struct devic
- #define AIC32X4_RMICPGANIN_IN1L_10K 0x10
- #define AIC32X4_RMICPGANIN_CM1R_10K 0x40
-
-+/* Common mask and enable for all of the dividers */
-+#define AIC32X4_DIVEN BIT(7)
-+#define AIC32X4_DIV_MASK GENMASK(6, 0)
-+
- /* Clock Limits */
- #define AIC32X4_MAX_PLL_CLKIN 20000000
-
--- /dev/null
+From 8c49a3384501933c9919a44504b4f3148a16320a Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:50 -0700
+Subject: [PATCH 407/725] ASoC: tlv320aic32x4: Move aosr and dosr setting to
+ separate functions
+
+commit fbafbf6517274a797e6e6508c18dd8dba5920c89 upstream.
+
+Move these to separate helper functions. This looks cleaner and fits
+better with the new clock setting in CCF.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 24 +++++++++++++++++-------
+ 1 file changed, 17 insertions(+), 7 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -720,6 +720,20 @@ static int aic32x4_set_dai_fmt(struct sn
+ return 0;
+ }
+
++static int aic32x4_set_aosr(struct snd_soc_component *component, u8 aosr)
++{
++ return snd_soc_component_write(component, AIC32X4_AOSR, aosr);
++}
++
++static int aic32x4_set_dosr(struct snd_soc_component *component, u16 dosr)
++{
++ snd_soc_component_write(component, AIC32X4_DOSRMSB, dosr >> 8);
++ snd_soc_component_write(component, AIC32X4_DOSRLSB,
++ (dosr & 0xff));
++
++ return 0;
++}
++
+ static int aic32x4_set_processing_blocks(struct snd_soc_component *component,
+ u8 r_block, u8 p_block)
+ {
+@@ -765,14 +779,10 @@ static int aic32x4_setup_clocks(struct s
+ clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
+ clk_set_rate(clocks[5].clk, aic32x4_divs[i].bdiv_rate);
+
+- aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
++ aic32x4_set_aosr(component, aic32x4_divs[i].aosr);
++ aic32x4_set_dosr(component, aic32x4_divs[i].dosr);
+
+- /* DOSR MSB & LSB values */
+- snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
+- snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff));
+-
+- /* AOSR value */
+- snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
++ aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
+
+ return 0;
+ }
--- /dev/null
+From d246d5e5edb858db81b72b58c1f2ef0f0b15fb97 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:51 -0700
+Subject: [PATCH 408/725] ASoC: tlv320aic32x4: Dynamically Determine Clocking
+
+commit 96c3bb00239de4fb5f4ddca42c1f90d6d9b3c697 upstream.
+
+The existing code uses a static lookup table to determine the
+settings of the various clock devices on board the chip. This is
+limiting in a couple of ways. First, this doesn't allow for any
+master clock rates other than the three that have been
+precalculated. Additionally, new sample rates are difficult to
+add to the table. Witness that the chip is capable of 192000 Hz
+sampling, but it is not provided by this driver. Last, if the
+driver is clocked by something that isn't a crystal, the
+upstream clock may not be able to achieve exactly the rate
+requested in the driver. This will mean that clocking will be
+slightly off for the sampling clock or that it won't work at all.
+
+This patch determines the settings for all of the clocks at
+runtime considering the real conditions of the clocks in the
+system. The rules for the clocks are in TI's SLAA557 application
+guide on pages 37, 51 and 77.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 190 ++++++++++++++-----------------
+ sound/soc/codecs/tlv320aic32x4.h | 4 +-
+ 2 files changed, 90 insertions(+), 104 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -47,21 +47,6 @@
+
+ #include "tlv320aic32x4.h"
+
+-struct aic32x4_rate_divs {
+- u32 mclk;
+- u32 rate;
+- unsigned long pll_rate;
+- u16 dosr;
+- unsigned long ndac_rate;
+- unsigned long mdac_rate;
+- u8 aosr;
+- unsigned long nadc_rate;
+- unsigned long madc_rate;
+- unsigned long bdiv_rate;
+- u8 r_block;
+- u8 p_block;
+-};
+-
+ struct aic32x4_priv {
+ struct regmap *regmap;
+ u32 sysclk;
+@@ -307,58 +292,6 @@ static const struct snd_kcontrol_new aic
+ 0, 0x0F, 0),
+ };
+
+-static const struct aic32x4_rate_divs aic32x4_divs[] = {
+- /* 8k rate */
+- { 12000000, 8000, 57120000, 768, 18432000, 6144000, 128, 18432000,
+- 1024000, 256000, 1, 1 },
+- { 24000000, 8000, 57120000, 768, 6144000, 6144000, 64, 2048000,
+- 512000, 256000, 1, 1 },
+- { 25000000, 8000, 32620000, 768, 6144000, 6144000, 64, 2048000,
+- 512000, 256000, 1, 1 },
+- /* 11.025k rate */
+- { 12000000, 11025, 44217600, 512, 11289600, 5644800, 128, 11289600,
+- 1411200, 352800, 1, 1 },
+- { 24000000, 11025, 44217600, 512, 5644800, 5644800, 64, 2822400,
+- 705600, 352800, 1, 1 },
+- /* 16k rate */
+- { 12000000, 16000, 57120000, 384, 18432000, 6144000, 128, 18432000,
+- 2048000, 512000, 1, 1 },
+- { 24000000, 16000, 57120000, 384, 6144000, 6144000, 64, 5120000,
+- 1024000, 512000, 1, 1 },
+- { 25000000, 16000, 32620000, 384, 6144000, 6144000, 64, 5120000,
+- 1024000, 512000, 1, 1 },
+- /* 22.05k rate */
+- { 12000000, 22050, 44217600, 256, 22579200, 5644800, 128, 22579200,
+- 2822400, 705600, 1, 1 },
+- { 24000000, 22050, 44217600, 256, 5644800, 5644800, 64, 5644800,
+- 1411200, 705600, 1, 1 },
+- { 25000000, 22050, 19713750, 256, 5644800, 5644800, 64, 5644800,
+- 1411200, 705600, 1, 1 },
+- /* 32k rate */
+- { 12000000, 32000, 14112000, 192, 43008000, 6144000, 64, 43008000,
+- 2048000, 1024000, 1, 1 },
+- { 24000000, 32000, 14112000, 192, 12288000, 6144000, 64, 12288000,
+- 2048000, 1024000, 1, 1 },
+- /* 44.1k rate */
+- { 12000000, 44100, 44217600, 128, 45158400, 5644800, 128, 45158400,
+- 5644800, 1411200, 1, 1 },
+- { 24000000, 44100, 44217600, 128, 11289600, 5644800, 64, 11289600,
+- 2822400, 1411200, 1, 1 },
+- { 25000000, 44100, 19713750, 128, 11289600, 5644800, 64, 11289600,
+- 2822400, 1411200, 1, 1 },
+- /* 48k rate */
+- { 12000000, 48000, 18432000, 128, 49152000, 6144000, 128, 49152000,
+- 6144000, 1536000, 1, 1 },
+- { 24000000, 48000, 18432000, 128, 12288000, 6144000, 64, 12288000,
+- 3072000, 1536000, 1, 1 },
+- { 25000000, 48000, 75626250, 128, 12288000, 6144000, 64, 12288000,
+- 3072000, 1536000, 1, 1 },
+-
+- /* 96k rate */
+- { 25000000, 96000, 75626250, 64, 24576000, 6144000, 64, 24576000,
+- 6144000, 3072000, 1, 9 },
+-};
+-
+ static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
+ SOC_DAPM_SINGLE("L_DAC Switch", AIC32X4_HPLROUTE, 3, 1, 0),
+ SOC_DAPM_SINGLE("IN1_L Switch", AIC32X4_HPLROUTE, 2, 1, 0),
+@@ -632,20 +565,6 @@ const struct regmap_config aic32x4_regma
+ };
+ EXPORT_SYMBOL(aic32x4_regmap_config);
+
+-static inline int aic32x4_get_divs(int mclk, int rate)
+-{
+- int i;
+-
+- for (i = 0; i < ARRAY_SIZE(aic32x4_divs); i++) {
+- if ((aic32x4_divs[i].rate == rate)
+- && (aic32x4_divs[i].mclk == mclk)) {
+- return i;
+- }
+- }
+- printk(KERN_ERR "aic32x4: master clock and sample rate is not supported\n");
+- return -EINVAL;
+-}
+-
+ static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+ {
+@@ -747,11 +666,17 @@ static int aic32x4_set_processing_blocks
+ }
+
+ static int aic32x4_setup_clocks(struct snd_soc_component *component,
+- unsigned int sample_rate,
+- unsigned int parent_rate)
++ unsigned int sample_rate)
+ {
+- int i;
++ u8 aosr;
++ u16 dosr;
++ u8 adc_resource_class, dac_resource_class;
++ u8 madc, nadc, mdac, ndac, max_nadc, min_mdac, max_ndac;
++ u8 dosr_increment;
++ u16 max_dosr, min_dosr;
++ unsigned long mclk_rate, adc_clock_rate, dac_clock_rate;
+ int ret;
++ struct clk *mclk;
+
+ struct clk_bulk_data clocks[] = {
+ { .id = "pll" },
+@@ -761,30 +686,89 @@ static int aic32x4_setup_clocks(struct s
+ { .id = "mdac" },
+ { .id = "bdiv" },
+ };
+-
+- i = aic32x4_get_divs(parent_rate, sample_rate);
+- if (i < 0) {
+- printk(KERN_ERR "aic32x4: sampling rate not supported\n");
+- return i;
+- }
+-
+ ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
+ if (ret)
+ return ret;
+
+- clk_set_rate(clocks[0].clk, aic32x4_divs[i].pll_rate);
+- clk_set_rate(clocks[1].clk, aic32x4_divs[i].nadc_rate);
+- clk_set_rate(clocks[2].clk, aic32x4_divs[i].madc_rate);
+- clk_set_rate(clocks[3].clk, aic32x4_divs[i].ndac_rate);
+- clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
+- clk_set_rate(clocks[5].clk, aic32x4_divs[i].bdiv_rate);
++ mclk = clk_get_parent(clocks[1].clk);
++ mclk_rate = clk_get_rate(mclk);
+
+- aic32x4_set_aosr(component, aic32x4_divs[i].aosr);
+- aic32x4_set_dosr(component, aic32x4_divs[i].dosr);
++ if (sample_rate <= 48000) {
++ aosr = 128;
++ adc_resource_class = 6;
++ dac_resource_class = 8;
++ dosr_increment = 8;
++ aic32x4_set_processing_blocks(component, 1, 1);
++ } else if (sample_rate <= 96000) {
++ aosr = 64;
++ adc_resource_class = 6;
++ dac_resource_class = 8;
++ dosr_increment = 4;
++ aic32x4_set_processing_blocks(component, 1, 9);
++ } else if (sample_rate == 192000) {
++ aosr = 32;
++ adc_resource_class = 3;
++ dac_resource_class = 4;
++ dosr_increment = 2;
++ aic32x4_set_processing_blocks(component, 13, 19);
++ } else {
++ dev_err(component->dev, "Sampling rate not supported\n");
++ return -EINVAL;
++ }
+
+- aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
++ madc = DIV_ROUND_UP((32 * adc_resource_class), aosr);
++ max_dosr = (AIC32X4_MAX_DOSR_FREQ / sample_rate / dosr_increment) *
++ dosr_increment;
++ min_dosr = (AIC32X4_MIN_DOSR_FREQ / sample_rate / dosr_increment) *
++ dosr_increment;
++ max_nadc = AIC32X4_MAX_CODEC_CLKIN_FREQ / (madc * aosr * sample_rate);
++
++ for (nadc = max_nadc; nadc > 0; --nadc) {
++ adc_clock_rate = nadc * madc * aosr * sample_rate;
++ for (dosr = max_dosr; dosr >= min_dosr;
++ dosr -= dosr_increment) {
++ min_mdac = DIV_ROUND_UP((32 * dac_resource_class), dosr);
++ max_ndac = AIC32X4_MAX_CODEC_CLKIN_FREQ /
++ (min_mdac * dosr * sample_rate);
++ for (mdac = min_mdac; mdac <= 128; ++mdac) {
++ for (ndac = max_ndac; ndac > 0; --ndac) {
++ dac_clock_rate = ndac * mdac * dosr *
++ sample_rate;
++ if (dac_clock_rate == adc_clock_rate) {
++ if (clk_round_rate(clocks[0].clk, dac_clock_rate) == 0)
++ continue;
++
++ clk_set_rate(clocks[0].clk,
++ dac_clock_rate);
++
++ clk_set_rate(clocks[1].clk,
++ sample_rate * aosr *
++ madc);
++ clk_set_rate(clocks[2].clk,
++ sample_rate * aosr);
++ aic32x4_set_aosr(component,
++ aosr);
++
++ clk_set_rate(clocks[3].clk,
++ sample_rate * dosr *
++ mdac);
++ clk_set_rate(clocks[4].clk,
++ sample_rate * dosr);
++ aic32x4_set_dosr(component,
++ dosr);
++
++ clk_set_rate(clocks[5].clk,
++ sample_rate * 32);
++ return 0;
++ }
++ }
++ }
++ }
++ }
+
+- return 0;
++ dev_err(component->dev,
++ "Could not set clocks to support sample rate.\n");
++ return -EINVAL;
+ }
+
+ static int aic32x4_hw_params(struct snd_pcm_substream *substream,
+@@ -796,7 +780,7 @@ static int aic32x4_hw_params(struct snd_
+ u8 iface1_reg = 0;
+ u8 dacsetup_reg = 0;
+
+- aic32x4_setup_clocks(component, params_rate(params), aic32x4->sysclk);
++ aic32x4_setup_clocks(component, params_rate(params));
+
+ switch (params_width(params)) {
+ case 16:
+--- a/sound/soc/codecs/tlv320aic32x4.h
++++ b/sound/soc/codecs/tlv320aic32x4.h
+@@ -211,7 +211,9 @@ int aic32x4_register_clocks(struct devic
+ #define AIC32X4_DIV_MASK GENMASK(6, 0)
+
+ /* Clock Limits */
++#define AIC32X4_MAX_DOSR_FREQ 6200000
++#define AIC32X4_MIN_DOSR_FREQ 2800000
++#define AIC32X4_MAX_CODEC_CLKIN_FREQ 110000000
+ #define AIC32X4_MAX_PLL_CLKIN 20000000
+
+-
+ #endif /* _TLV320AIC32X4_H */
+++ /dev/null
-From f057c2ccc9c5fddca55fb42032395cf355f918e8 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:48 -0700
-Subject: [PATCH 408/703] ASoC: tlv320aic32x4: Model BDIV divider in CCF
-
-commit 9b484124ebd906c4d6bc826cc0d417e80cc1105c upstream.
-
-Model and manage BDIV divider as components in the Core
-Clock Framework. This should allow us to do some more complex
-clock management and power control. Also, some of the
-on-board chip clocks can be exposed to the outside, and this
-change will make those clocks easier to consume by other
-parts of the kernel.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4-clk.c | 36 ++++++++++++++++++
- sound/soc/codecs/tlv320aic32x4.c | 56 +++++++++++++---------------
- 2 files changed, 62 insertions(+), 30 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4-clk.c
-+++ b/sound/soc/codecs/tlv320aic32x4-clk.c
-@@ -351,6 +351,34 @@ static const struct clk_ops aic32x4_div_
- .recalc_rate = clk_aic32x4_div_recalc_rate,
- };
-
-+static int clk_aic32x4_bdiv_set_parent(struct clk_hw *hw, u8 index)
-+{
-+ struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
-+
-+ return regmap_update_bits(mux->regmap, AIC32X4_IFACE3,
-+ AIC32X4_BDIVCLK_MASK, index);
-+}
-+
-+static u8 clk_aic32x4_bdiv_get_parent(struct clk_hw *hw)
-+{
-+ struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
-+ unsigned int val;
-+
-+ regmap_read(mux->regmap, AIC32X4_IFACE3, &val);
-+
-+ return val & AIC32X4_BDIVCLK_MASK;
-+}
-+
-+static const struct clk_ops aic32x4_bdiv_ops = {
-+ .prepare = clk_aic32x4_div_prepare,
-+ .unprepare = clk_aic32x4_div_unprepare,
-+ .set_parent = clk_aic32x4_bdiv_set_parent,
-+ .get_parent = clk_aic32x4_bdiv_get_parent,
-+ .set_rate = clk_aic32x4_div_set_rate,
-+ .round_rate = clk_aic32x4_div_round_rate,
-+ .recalc_rate = clk_aic32x4_div_recalc_rate,
-+};
-+
- static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
- {
- .name = "pll",
-@@ -396,6 +424,14 @@ static struct aic32x4_clkdesc aic32x4_cl
- .ops = &aic32x4_div_ops,
- .reg = AIC32X4_MADC,
- },
-+ {
-+ .name = "bdiv",
-+ .parent_names =
-+ (const char *[]) { "ndac", "mdac", "nadc", "madc" },
-+ .num_parents = 4,
-+ .ops = &aic32x4_bdiv_ops,
-+ .reg = AIC32X4_BCLKN,
-+ },
- };
-
- static struct clk *aic32x4_register_clk(struct device *dev,
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -57,7 +57,7 @@ struct aic32x4_rate_divs {
- u8 aosr;
- unsigned long nadc_rate;
- unsigned long madc_rate;
-- u8 blck_N;
-+ unsigned long bdiv_rate;
- u8 r_block;
- u8 p_block;
- };
-@@ -310,53 +310,53 @@ static const struct snd_kcontrol_new aic
- static const struct aic32x4_rate_divs aic32x4_divs[] = {
- /* 8k rate */
- { 12000000, 8000, 57120000, 768, 18432000, 6144000, 128, 18432000,
-- 1024000, 24, 1, 1 },
-+ 1024000, 256000, 1, 1 },
- { 24000000, 8000, 57120000, 768, 6144000, 6144000, 64, 2048000,
-- 512000, 24, 1, 1 },
-+ 512000, 256000, 1, 1 },
- { 25000000, 8000, 32620000, 768, 6144000, 6144000, 64, 2048000,
-- 512000, 24, 1, 1 },
-+ 512000, 256000, 1, 1 },
- /* 11.025k rate */
- { 12000000, 11025, 44217600, 512, 11289600, 5644800, 128, 11289600,
-- 1411200, 16, 1, 1 },
-+ 1411200, 352800, 1, 1 },
- { 24000000, 11025, 44217600, 512, 5644800, 5644800, 64, 2822400,
-- 705600, 16, 1, 1 },
-+ 705600, 352800, 1, 1 },
- /* 16k rate */
- { 12000000, 16000, 57120000, 384, 18432000, 6144000, 128, 18432000,
-- 2048000, 12, 1, 1 },
-+ 2048000, 512000, 1, 1 },
- { 24000000, 16000, 57120000, 384, 6144000, 6144000, 64, 5120000,
-- 1024000, 12, 1, 1 },
-+ 1024000, 512000, 1, 1 },
- { 25000000, 16000, 32620000, 384, 6144000, 6144000, 64, 5120000,
-- 1024000, 12, 1, 1 },
-+ 1024000, 512000, 1, 1 },
- /* 22.05k rate */
- { 12000000, 22050, 44217600, 256, 22579200, 5644800, 128, 22579200,
-- 2822400, 8, 1, 1 },
-+ 2822400, 705600, 1, 1 },
- { 24000000, 22050, 44217600, 256, 5644800, 5644800, 64, 5644800,
-- 1411200, 8, 1, 1 },
-+ 1411200, 705600, 1, 1 },
- { 25000000, 22050, 19713750, 256, 5644800, 5644800, 64, 5644800,
-- 1411200, 8, 1, 1 },
-+ 1411200, 705600, 1, 1 },
- /* 32k rate */
- { 12000000, 32000, 14112000, 192, 43008000, 6144000, 64, 43008000,
-- 2048000, 6, 1, 1 },
-+ 2048000, 1024000, 1, 1 },
- { 24000000, 32000, 14112000, 192, 12288000, 6144000, 64, 12288000,
-- 2048000, 6, 1, 1 },
-+ 2048000, 1024000, 1, 1 },
- /* 44.1k rate */
- { 12000000, 44100, 44217600, 128, 45158400, 5644800, 128, 45158400,
-- 5644800, 4, 1, 1 },
-+ 5644800, 1411200, 1, 1 },
- { 24000000, 44100, 44217600, 128, 11289600, 5644800, 64, 11289600,
-- 2822400, 4, 1, 1 },
-+ 2822400, 1411200, 1, 1 },
- { 25000000, 44100, 19713750, 128, 11289600, 5644800, 64, 11289600,
-- 2822400, 4, 1, 1 },
-+ 2822400, 1411200, 1, 1 },
- /* 48k rate */
- { 12000000, 48000, 18432000, 128, 49152000, 6144000, 128, 49152000,
-- 6144000, 4, 1, 1 },
-+ 6144000, 1536000, 1, 1 },
- { 24000000, 48000, 18432000, 128, 12288000, 6144000, 64, 12288000,
-- 3072000, 4, 1, 1 },
-+ 3072000, 1536000, 1, 1 },
- { 25000000, 48000, 75626250, 128, 12288000, 6144000, 64, 12288000,
-- 3072000, 4, 1, 1 },
-+ 3072000, 1536000, 1, 1 },
-
- /* 96k rate */
- { 25000000, 96000, 75626250, 64, 24576000, 6144000, 64, 24576000,
-- 6144000, 1, 1, 9 },
-+ 6144000, 3072000, 1, 9 },
- };
-
- static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
-@@ -745,6 +745,7 @@ static int aic32x4_setup_clocks(struct s
- { .id = "madc" },
- { .id = "ndac" },
- { .id = "mdac" },
-+ { .id = "bdiv" },
- };
-
- i = aic32x4_get_divs(parent_rate, sample_rate);
-@@ -762,14 +763,10 @@ static int aic32x4_setup_clocks(struct s
- clk_set_rate(clocks[2].clk, aic32x4_divs[i].madc_rate);
- clk_set_rate(clocks[3].clk, aic32x4_divs[i].ndac_rate);
- clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
-+ clk_set_rate(clocks[5].clk, aic32x4_divs[i].bdiv_rate);
-
- aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
-
-- /* DAC_MOD_CLK as BDIV_CLKIN */
-- snd_soc_component_update_bits(component, AIC32X4_IFACE3,
-- AIC32X4_BDIVCLK_MASK,
-- AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
--
- /* DOSR MSB & LSB values */
- snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
- snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff));
-@@ -777,10 +774,6 @@ static int aic32x4_setup_clocks(struct s
- /* AOSR value */
- snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
-
-- /* BCLK N divider */
-- snd_soc_component_update_bits(component, AIC32X4_BCLKN,
-- AIC32X4_BCLK_MASK, aic32x4_divs[i].blck_N);
--
- return 0;
- }
-
-@@ -1003,6 +996,8 @@ static int aic32x4_component_probe(struc
- struct clk_bulk_data clocks[] = {
- { .id = "codec_clkin" },
- { .id = "pll" },
-+ { .id = "bdiv" },
-+ { .id = "mdac" },
- };
-
- ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
-@@ -1020,6 +1015,7 @@ static int aic32x4_component_probe(struc
- aic32x4_setup_gpios(component);
-
- clk_set_parent(clocks[0].clk, clocks[1].clk);
-+ clk_set_parent(clocks[2].clk, clocks[3].clk);
-
- /* Power platform configuration */
- if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
+++ /dev/null
-From eea2c82299034bb146f3ad10e8ed4c2d574777df Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:49 -0700
-Subject: [PATCH 409/703] ASoC: tlv320aic32x4: Control clock gating with CCF
-
-commit d25970b5fd51e9fcf0afbe190908ea4049454da4 upstream.
-
-Control the clock gating to the various clock components to use
-the CCF. This allows us to prepare_enalbe only 3 clocks and the
-relationships assigned to them will cause upstream clockss to
-enable automatically. Additionally we can do this in a single
-call to the CCF.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 67 +++++++-------------------------
- 1 file changed, 13 insertions(+), 54 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -836,41 +836,25 @@ static int aic32x4_mute(struct snd_soc_d
- static int aic32x4_set_bias_level(struct snd_soc_component *component,
- enum snd_soc_bias_level level)
- {
-- struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
- int ret;
-
-+ struct clk_bulk_data clocks[] = {
-+ { .id = "madc" },
-+ { .id = "mdac" },
-+ { .id = "bdiv" },
-+ };
-+
-+ ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
-+ if (ret)
-+ return ret;
-+
- switch (level) {
- case SND_SOC_BIAS_ON:
-- /* Switch on master clock */
-- ret = clk_prepare_enable(aic32x4->mclk);
-+ ret = clk_bulk_prepare_enable(ARRAY_SIZE(clocks), clocks);
- if (ret) {
-- dev_err(component->dev, "Failed to enable master clock\n");
-+ dev_err(component->dev, "Failed to enable clocks\n");
- return ret;
- }
--
-- /* Switch on PLL */
-- snd_soc_component_update_bits(component, AIC32X4_PLLPR,
-- AIC32X4_PLLEN, AIC32X4_PLLEN);
--
-- /* Switch on NDAC Divider */
-- snd_soc_component_update_bits(component, AIC32X4_NDAC,
-- AIC32X4_NDACEN, AIC32X4_NDACEN);
--
-- /* Switch on MDAC Divider */
-- snd_soc_component_update_bits(component, AIC32X4_MDAC,
-- AIC32X4_MDACEN, AIC32X4_MDACEN);
--
-- /* Switch on NADC Divider */
-- snd_soc_component_update_bits(component, AIC32X4_NADC,
-- AIC32X4_NADCEN, AIC32X4_NADCEN);
--
-- /* Switch on MADC Divider */
-- snd_soc_component_update_bits(component, AIC32X4_MADC,
-- AIC32X4_MADCEN, AIC32X4_MADCEN);
--
-- /* Switch on BCLK_N Divider */
-- snd_soc_component_update_bits(component, AIC32X4_BCLKN,
-- AIC32X4_BCLKEN, AIC32X4_BCLKEN);
- break;
- case SND_SOC_BIAS_PREPARE:
- break;
-@@ -879,32 +863,7 @@ static int aic32x4_set_bias_level(struct
- if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
- break;
-
-- /* Switch off BCLK_N Divider */
-- snd_soc_component_update_bits(component, AIC32X4_BCLKN,
-- AIC32X4_BCLKEN, 0);
--
-- /* Switch off MADC Divider */
-- snd_soc_component_update_bits(component, AIC32X4_MADC,
-- AIC32X4_MADCEN, 0);
--
-- /* Switch off NADC Divider */
-- snd_soc_component_update_bits(component, AIC32X4_NADC,
-- AIC32X4_NADCEN, 0);
--
-- /* Switch off MDAC Divider */
-- snd_soc_component_update_bits(component, AIC32X4_MDAC,
-- AIC32X4_MDACEN, 0);
--
-- /* Switch off NDAC Divider */
-- snd_soc_component_update_bits(component, AIC32X4_NDAC,
-- AIC32X4_NDACEN, 0);
--
-- /* Switch off PLL */
-- snd_soc_component_update_bits(component, AIC32X4_PLLPR,
-- AIC32X4_PLLEN, 0);
--
-- /* Switch off master clock */
-- clk_disable_unprepare(aic32x4->mclk);
-+ clk_bulk_disable_unprepare(ARRAY_SIZE(clocks), clocks);
- break;
- case SND_SOC_BIAS_OFF:
- break;
--- /dev/null
+From 58dc9e3363b946adc015c9b6d9f8b4c9c85f08a6 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:52 -0700
+Subject: [PATCH 409/725] ASoC: tlv320aic32x4: Restructure set_dai_sysclk
+
+commit aa6a60f7be925210d5156f0e8025f3afe1f4f54d upstream.
+
+The sysclk is now managed by the CCF. Change this function
+to merely find the system clock and set it using
+clk_set_rate.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 17 ++++++-----------
+ 1 file changed, 6 insertions(+), 11 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -49,7 +49,6 @@
+
+ struct aic32x4_priv {
+ struct regmap *regmap;
+- u32 sysclk;
+ u32 power_cfg;
+ u32 micpga_routing;
+ bool swapdacs;
+@@ -569,17 +568,13 @@ static int aic32x4_set_dai_sysclk(struct
+ int clk_id, unsigned int freq, int dir)
+ {
+ struct snd_soc_component *component = codec_dai->component;
+- struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
++ struct clk *mclk;
++ struct clk *pll;
+
+- switch (freq) {
+- case 12000000:
+- case 24000000:
+- case 25000000:
+- aic32x4->sysclk = freq;
+- return 0;
+- }
+- printk(KERN_ERR "aic32x4: invalid frequency to set DAI system clock\n");
+- return -EINVAL;
++ pll = devm_clk_get(component->dev, "pll");
++ mclk = clk_get_parent(pll);
++
++ return clk_set_rate(mclk, freq);
+ }
+
+ static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+++ /dev/null
-From d69dddf58047b95c5ade57c246e7d4994d439f23 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:50 -0700
-Subject: [PATCH 410/703] ASoC: tlv320aic32x4: Move aosr and dosr setting to
- separate functions
-
-commit fbafbf6517274a797e6e6508c18dd8dba5920c89 upstream.
-
-Move these to separate helper functions. This looks cleaner and fits
-better with the new clock setting in CCF.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 24 +++++++++++++++++-------
- 1 file changed, 17 insertions(+), 7 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -720,6 +720,20 @@ static int aic32x4_set_dai_fmt(struct sn
- return 0;
- }
-
-+static int aic32x4_set_aosr(struct snd_soc_component *component, u8 aosr)
-+{
-+ return snd_soc_component_write(component, AIC32X4_AOSR, aosr);
-+}
-+
-+static int aic32x4_set_dosr(struct snd_soc_component *component, u16 dosr)
-+{
-+ snd_soc_component_write(component, AIC32X4_DOSRMSB, dosr >> 8);
-+ snd_soc_component_write(component, AIC32X4_DOSRLSB,
-+ (dosr & 0xff));
-+
-+ return 0;
-+}
-+
- static int aic32x4_set_processing_blocks(struct snd_soc_component *component,
- u8 r_block, u8 p_block)
- {
-@@ -765,14 +779,10 @@ static int aic32x4_setup_clocks(struct s
- clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
- clk_set_rate(clocks[5].clk, aic32x4_divs[i].bdiv_rate);
-
-- aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
-+ aic32x4_set_aosr(component, aic32x4_divs[i].aosr);
-+ aic32x4_set_dosr(component, aic32x4_divs[i].dosr);
-
-- /* DOSR MSB & LSB values */
-- snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
-- snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff));
--
-- /* AOSR value */
-- snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr);
-+ aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
-
- return 0;
- }
--- /dev/null
+From a815db43f1cd8dc8ac18d06c20526883d285c527 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:53 -0700
+Subject: [PATCH 410/725] ASoC: tlv320aic32x4: Remove mclk references
+
+commit 78f2d58a289302e56a7def96a783a7686ebf27e2 upstream.
+
+mclk is not used by anything anymore. Remove support for it.
+All that information now comes from the clock tree.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 7 -------
+ 1 file changed, 7 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -53,7 +53,6 @@ struct aic32x4_priv {
+ u32 micpga_routing;
+ bool swapdacs;
+ int rstn_gpio;
+- struct clk *mclk;
+ const char *mclk_name;
+
+ struct regulator *supply_ldo;
+@@ -1191,12 +1190,6 @@ int aic32x4_probe(struct device *dev, st
+ aic32x4->mclk_name = "mclk";
+ }
+
+- aic32x4->mclk = devm_clk_get(dev, "mclk");
+- if (IS_ERR(aic32x4->mclk)) {
+- dev_err(dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n");
+- return PTR_ERR(aic32x4->mclk);
+- }
+-
+ ret = aic32x4_register_clocks(dev, aic32x4->mclk_name);
+ if (ret)
+ return ret;
--- /dev/null
+From 7ce5af6517eee229b6ef65126a672a0d5c42d315 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:54 -0700
+Subject: [PATCH 411/725] ASoC: tlv320aic32x4: Allow 192000 Sample Rate
+
+commit 6d56ee1550b8a81bc63c80051ff78d8d704b09ba upstream.
+
+The clocking and processing blocks are now properly set up to
+support 192000 sample rates. Allow drivers to ask for that.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -859,7 +859,7 @@ static int aic32x4_set_bias_level(struct
+ return 0;
+ }
+
+-#define AIC32X4_RATES SNDRV_PCM_RATE_8000_96000
++#define AIC32X4_RATES SNDRV_PCM_RATE_8000_192000
+ #define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
+ | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+++ /dev/null
-From 60aee9d4b5857dbefc658ff7b3317cacf568a5d5 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:51 -0700
-Subject: [PATCH 411/703] ASoC: tlv320aic32x4: Dynamically Determine Clocking
-
-commit 96c3bb00239de4fb5f4ddca42c1f90d6d9b3c697 upstream.
-
-The existing code uses a static lookup table to determine the
-settings of the various clock devices on board the chip. This is
-limiting in a couple of ways. First, this doesn't allow for any
-master clock rates other than the three that have been
-precalculated. Additionally, new sample rates are difficult to
-add to the table. Witness that the chip is capable of 192000 Hz
-sampling, but it is not provided by this driver. Last, if the
-driver is clocked by something that isn't a crystal, the
-upstream clock may not be able to achieve exactly the rate
-requested in the driver. This will mean that clocking will be
-slightly off for the sampling clock or that it won't work at all.
-
-This patch determines the settings for all of the clocks at
-runtime considering the real conditions of the clocks in the
-system. The rules for the clocks are in TI's SLAA557 application
-guide on pages 37, 51 and 77.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 190 ++++++++++++++-----------------
- sound/soc/codecs/tlv320aic32x4.h | 4 +-
- 2 files changed, 90 insertions(+), 104 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -47,21 +47,6 @@
-
- #include "tlv320aic32x4.h"
-
--struct aic32x4_rate_divs {
-- u32 mclk;
-- u32 rate;
-- unsigned long pll_rate;
-- u16 dosr;
-- unsigned long ndac_rate;
-- unsigned long mdac_rate;
-- u8 aosr;
-- unsigned long nadc_rate;
-- unsigned long madc_rate;
-- unsigned long bdiv_rate;
-- u8 r_block;
-- u8 p_block;
--};
--
- struct aic32x4_priv {
- struct regmap *regmap;
- u32 sysclk;
-@@ -307,58 +292,6 @@ static const struct snd_kcontrol_new aic
- 0, 0x0F, 0),
- };
-
--static const struct aic32x4_rate_divs aic32x4_divs[] = {
-- /* 8k rate */
-- { 12000000, 8000, 57120000, 768, 18432000, 6144000, 128, 18432000,
-- 1024000, 256000, 1, 1 },
-- { 24000000, 8000, 57120000, 768, 6144000, 6144000, 64, 2048000,
-- 512000, 256000, 1, 1 },
-- { 25000000, 8000, 32620000, 768, 6144000, 6144000, 64, 2048000,
-- 512000, 256000, 1, 1 },
-- /* 11.025k rate */
-- { 12000000, 11025, 44217600, 512, 11289600, 5644800, 128, 11289600,
-- 1411200, 352800, 1, 1 },
-- { 24000000, 11025, 44217600, 512, 5644800, 5644800, 64, 2822400,
-- 705600, 352800, 1, 1 },
-- /* 16k rate */
-- { 12000000, 16000, 57120000, 384, 18432000, 6144000, 128, 18432000,
-- 2048000, 512000, 1, 1 },
-- { 24000000, 16000, 57120000, 384, 6144000, 6144000, 64, 5120000,
-- 1024000, 512000, 1, 1 },
-- { 25000000, 16000, 32620000, 384, 6144000, 6144000, 64, 5120000,
-- 1024000, 512000, 1, 1 },
-- /* 22.05k rate */
-- { 12000000, 22050, 44217600, 256, 22579200, 5644800, 128, 22579200,
-- 2822400, 705600, 1, 1 },
-- { 24000000, 22050, 44217600, 256, 5644800, 5644800, 64, 5644800,
-- 1411200, 705600, 1, 1 },
-- { 25000000, 22050, 19713750, 256, 5644800, 5644800, 64, 5644800,
-- 1411200, 705600, 1, 1 },
-- /* 32k rate */
-- { 12000000, 32000, 14112000, 192, 43008000, 6144000, 64, 43008000,
-- 2048000, 1024000, 1, 1 },
-- { 24000000, 32000, 14112000, 192, 12288000, 6144000, 64, 12288000,
-- 2048000, 1024000, 1, 1 },
-- /* 44.1k rate */
-- { 12000000, 44100, 44217600, 128, 45158400, 5644800, 128, 45158400,
-- 5644800, 1411200, 1, 1 },
-- { 24000000, 44100, 44217600, 128, 11289600, 5644800, 64, 11289600,
-- 2822400, 1411200, 1, 1 },
-- { 25000000, 44100, 19713750, 128, 11289600, 5644800, 64, 11289600,
-- 2822400, 1411200, 1, 1 },
-- /* 48k rate */
-- { 12000000, 48000, 18432000, 128, 49152000, 6144000, 128, 49152000,
-- 6144000, 1536000, 1, 1 },
-- { 24000000, 48000, 18432000, 128, 12288000, 6144000, 64, 12288000,
-- 3072000, 1536000, 1, 1 },
-- { 25000000, 48000, 75626250, 128, 12288000, 6144000, 64, 12288000,
-- 3072000, 1536000, 1, 1 },
--
-- /* 96k rate */
-- { 25000000, 96000, 75626250, 64, 24576000, 6144000, 64, 24576000,
-- 6144000, 3072000, 1, 9 },
--};
--
- static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
- SOC_DAPM_SINGLE("L_DAC Switch", AIC32X4_HPLROUTE, 3, 1, 0),
- SOC_DAPM_SINGLE("IN1_L Switch", AIC32X4_HPLROUTE, 2, 1, 0),
-@@ -632,20 +565,6 @@ const struct regmap_config aic32x4_regma
- };
- EXPORT_SYMBOL(aic32x4_regmap_config);
-
--static inline int aic32x4_get_divs(int mclk, int rate)
--{
-- int i;
--
-- for (i = 0; i < ARRAY_SIZE(aic32x4_divs); i++) {
-- if ((aic32x4_divs[i].rate == rate)
-- && (aic32x4_divs[i].mclk == mclk)) {
-- return i;
-- }
-- }
-- printk(KERN_ERR "aic32x4: master clock and sample rate is not supported\n");
-- return -EINVAL;
--}
--
- static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai,
- int clk_id, unsigned int freq, int dir)
- {
-@@ -747,11 +666,17 @@ static int aic32x4_set_processing_blocks
- }
-
- static int aic32x4_setup_clocks(struct snd_soc_component *component,
-- unsigned int sample_rate,
-- unsigned int parent_rate)
-+ unsigned int sample_rate)
- {
-- int i;
-+ u8 aosr;
-+ u16 dosr;
-+ u8 adc_resource_class, dac_resource_class;
-+ u8 madc, nadc, mdac, ndac, max_nadc, min_mdac, max_ndac;
-+ u8 dosr_increment;
-+ u16 max_dosr, min_dosr;
-+ unsigned long mclk_rate, adc_clock_rate, dac_clock_rate;
- int ret;
-+ struct clk *mclk;
-
- struct clk_bulk_data clocks[] = {
- { .id = "pll" },
-@@ -761,30 +686,89 @@ static int aic32x4_setup_clocks(struct s
- { .id = "mdac" },
- { .id = "bdiv" },
- };
--
-- i = aic32x4_get_divs(parent_rate, sample_rate);
-- if (i < 0) {
-- printk(KERN_ERR "aic32x4: sampling rate not supported\n");
-- return i;
-- }
--
- ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
- if (ret)
- return ret;
-
-- clk_set_rate(clocks[0].clk, aic32x4_divs[i].pll_rate);
-- clk_set_rate(clocks[1].clk, aic32x4_divs[i].nadc_rate);
-- clk_set_rate(clocks[2].clk, aic32x4_divs[i].madc_rate);
-- clk_set_rate(clocks[3].clk, aic32x4_divs[i].ndac_rate);
-- clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate);
-- clk_set_rate(clocks[5].clk, aic32x4_divs[i].bdiv_rate);
-+ mclk = clk_get_parent(clocks[1].clk);
-+ mclk_rate = clk_get_rate(mclk);
-
-- aic32x4_set_aosr(component, aic32x4_divs[i].aosr);
-- aic32x4_set_dosr(component, aic32x4_divs[i].dosr);
-+ if (sample_rate <= 48000) {
-+ aosr = 128;
-+ adc_resource_class = 6;
-+ dac_resource_class = 8;
-+ dosr_increment = 8;
-+ aic32x4_set_processing_blocks(component, 1, 1);
-+ } else if (sample_rate <= 96000) {
-+ aosr = 64;
-+ adc_resource_class = 6;
-+ dac_resource_class = 8;
-+ dosr_increment = 4;
-+ aic32x4_set_processing_blocks(component, 1, 9);
-+ } else if (sample_rate == 192000) {
-+ aosr = 32;
-+ adc_resource_class = 3;
-+ dac_resource_class = 4;
-+ dosr_increment = 2;
-+ aic32x4_set_processing_blocks(component, 13, 19);
-+ } else {
-+ dev_err(component->dev, "Sampling rate not supported\n");
-+ return -EINVAL;
-+ }
-
-- aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
-+ madc = DIV_ROUND_UP((32 * adc_resource_class), aosr);
-+ max_dosr = (AIC32X4_MAX_DOSR_FREQ / sample_rate / dosr_increment) *
-+ dosr_increment;
-+ min_dosr = (AIC32X4_MIN_DOSR_FREQ / sample_rate / dosr_increment) *
-+ dosr_increment;
-+ max_nadc = AIC32X4_MAX_CODEC_CLKIN_FREQ / (madc * aosr * sample_rate);
-+
-+ for (nadc = max_nadc; nadc > 0; --nadc) {
-+ adc_clock_rate = nadc * madc * aosr * sample_rate;
-+ for (dosr = max_dosr; dosr >= min_dosr;
-+ dosr -= dosr_increment) {
-+ min_mdac = DIV_ROUND_UP((32 * dac_resource_class), dosr);
-+ max_ndac = AIC32X4_MAX_CODEC_CLKIN_FREQ /
-+ (min_mdac * dosr * sample_rate);
-+ for (mdac = min_mdac; mdac <= 128; ++mdac) {
-+ for (ndac = max_ndac; ndac > 0; --ndac) {
-+ dac_clock_rate = ndac * mdac * dosr *
-+ sample_rate;
-+ if (dac_clock_rate == adc_clock_rate) {
-+ if (clk_round_rate(clocks[0].clk, dac_clock_rate) == 0)
-+ continue;
-+
-+ clk_set_rate(clocks[0].clk,
-+ dac_clock_rate);
-+
-+ clk_set_rate(clocks[1].clk,
-+ sample_rate * aosr *
-+ madc);
-+ clk_set_rate(clocks[2].clk,
-+ sample_rate * aosr);
-+ aic32x4_set_aosr(component,
-+ aosr);
-+
-+ clk_set_rate(clocks[3].clk,
-+ sample_rate * dosr *
-+ mdac);
-+ clk_set_rate(clocks[4].clk,
-+ sample_rate * dosr);
-+ aic32x4_set_dosr(component,
-+ dosr);
-+
-+ clk_set_rate(clocks[5].clk,
-+ sample_rate * 32);
-+ return 0;
-+ }
-+ }
-+ }
-+ }
-+ }
-
-- return 0;
-+ dev_err(component->dev,
-+ "Could not set clocks to support sample rate.\n");
-+ return -EINVAL;
- }
-
- static int aic32x4_hw_params(struct snd_pcm_substream *substream,
-@@ -796,7 +780,7 @@ static int aic32x4_hw_params(struct snd_
- u8 iface1_reg = 0;
- u8 dacsetup_reg = 0;
-
-- aic32x4_setup_clocks(component, params_rate(params), aic32x4->sysclk);
-+ aic32x4_setup_clocks(component, params_rate(params));
-
- switch (params_width(params)) {
- case 16:
---- a/sound/soc/codecs/tlv320aic32x4.h
-+++ b/sound/soc/codecs/tlv320aic32x4.h
-@@ -211,7 +211,9 @@ int aic32x4_register_clocks(struct devic
- #define AIC32X4_DIV_MASK GENMASK(6, 0)
-
- /* Clock Limits */
-+#define AIC32X4_MAX_DOSR_FREQ 6200000
-+#define AIC32X4_MIN_DOSR_FREQ 2800000
-+#define AIC32X4_MAX_CODEC_CLKIN_FREQ 110000000
- #define AIC32X4_MAX_PLL_CLKIN 20000000
-
--
- #endif /* _TLV320AIC32X4_H */
--- /dev/null
+From 618baa8ddc305c5bbe1cd4682c9df252e6fc386c Mon Sep 17 00:00:00 2001
+From: Mark Brown <broonie@kernel.org>
+Date: Tue, 26 Mar 2019 13:10:13 +0000
+Subject: [PATCH 412/725] ASoC: tlv320aic32x4: Only enable with common clock
+
+commit 64f01d2b5ccc621c3aa66b82daf9154f5581f36a upstream.
+
+Some architectures do not yet support the common clock API at all but
+the tlv320aic32x4 driver now requires it.
+
+Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/Kconfig | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -170,8 +170,8 @@ config SND_SOC_ALL_CODECS
+ select SND_SOC_TAS5713 if I2C
+ select SND_SOC_TLV320AIC26 if SPI_MASTER
+ select SND_SOC_TLV320AIC31XX if I2C
+- select SND_SOC_TLV320AIC32X4_I2C if I2C
+- select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER
++ select SND_SOC_TLV320AIC32X4_I2C if I2C && COMMON_CLK
++ select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER && COMMON_CLK
+ select SND_SOC_TLV320AIC3X if I2C
+ select SND_SOC_TPA6130A2 if I2C
+ select SND_SOC_TLV320DAC33 if I2C
+@@ -1030,11 +1030,13 @@ config SND_SOC_TLV320AIC32X4
+ config SND_SOC_TLV320AIC32X4_I2C
+ tristate "Texas Instruments TLV320AIC32x4 audio CODECs - I2C"
+ depends on I2C
++ depends on COMMON_CLK
+ select SND_SOC_TLV320AIC32X4
+
+ config SND_SOC_TLV320AIC32X4_SPI
+ tristate "Texas Instruments TLV320AIC32x4 audio CODECs - SPI"
+ depends on SPI_MASTER
++ depends on COMMON_CLK
+ select SND_SOC_TLV320AIC32X4
+
+ config SND_SOC_TLV320AIC3X
+++ /dev/null
-From dc848cfb79aa1a4cea301c388e920e4205ac791a Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:52 -0700
-Subject: [PATCH 412/703] ASoC: tlv320aic32x4: Restructure set_dai_sysclk
-
-commit aa6a60f7be925210d5156f0e8025f3afe1f4f54d upstream.
-
-The sysclk is now managed by the CCF. Change this function
-to merely find the system clock and set it using
-clk_set_rate.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 17 ++++++-----------
- 1 file changed, 6 insertions(+), 11 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -49,7 +49,6 @@
-
- struct aic32x4_priv {
- struct regmap *regmap;
-- u32 sysclk;
- u32 power_cfg;
- u32 micpga_routing;
- bool swapdacs;
-@@ -569,17 +568,13 @@ static int aic32x4_set_dai_sysclk(struct
- int clk_id, unsigned int freq, int dir)
- {
- struct snd_soc_component *component = codec_dai->component;
-- struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
-+ struct clk *mclk;
-+ struct clk *pll;
-
-- switch (freq) {
-- case 12000000:
-- case 24000000:
-- case 25000000:
-- aic32x4->sysclk = freq;
-- return 0;
-- }
-- printk(KERN_ERR "aic32x4: invalid frequency to set DAI system clock\n");
-- return -EINVAL;
-+ pll = devm_clk_get(component->dev, "pll");
-+ mclk = clk_get_parent(pll);
-+
-+ return clk_set_rate(mclk, freq);
- }
-
- static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+++ /dev/null
-From 76203a21b47e2dcbb3619a9655cc4918e4d496a5 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:53 -0700
-Subject: [PATCH 413/703] ASoC: tlv320aic32x4: Remove mclk references
-
-commit 78f2d58a289302e56a7def96a783a7686ebf27e2 upstream.
-
-mclk is not used by anything anymore. Remove support for it.
-All that information now comes from the clock tree.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 7 -------
- 1 file changed, 7 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -53,7 +53,6 @@ struct aic32x4_priv {
- u32 micpga_routing;
- bool swapdacs;
- int rstn_gpio;
-- struct clk *mclk;
- const char *mclk_name;
-
- struct regulator *supply_ldo;
-@@ -1191,12 +1190,6 @@ int aic32x4_probe(struct device *dev, st
- aic32x4->mclk_name = "mclk";
- }
-
-- aic32x4->mclk = devm_clk_get(dev, "mclk");
-- if (IS_ERR(aic32x4->mclk)) {
-- dev_err(dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n");
-- return PTR_ERR(aic32x4->mclk);
-- }
--
- ret = aic32x4_register_clocks(dev, aic32x4->mclk_name);
- if (ret)
- return ret;
--- /dev/null
+From 739091e806876265d78915310e4037d0061648f8 Mon Sep 17 00:00:00 2001
+From: FERHAT Nicolas <contact@audiophonics.fr>
+Date: Fri, 5 Apr 2019 13:06:42 +0100
+Subject: [PATCH 413/725] Audiophonics I-Sabre 9038Q2M DAC driver
+
+Signed-off-by: Audiophonics <contact@audiophonics.fr>
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 6 +
+ .../boot/dts/overlays/i-sabre-q2m-overlay.dts | 39 ++
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ sound/soc/bcm/Kconfig | 7 +
+ sound/soc/bcm/Makefile | 2 +
+ sound/soc/bcm/i-sabre-q2m.c | 157 +++++++
+ sound/soc/codecs/Kconfig | 5 +
+ sound/soc/codecs/Makefile | 2 +
+ sound/soc/codecs/i-sabre-codec.c | 392 ++++++++++++++++++
+ sound/soc/codecs/i-sabre-codec.h | 42 ++
+ 13 files changed, 656 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
+ create mode 100644 sound/soc/bcm/i-sabre-q2m.c
+ create mode 100644 sound/soc/codecs/i-sabre-codec.c
+ create mode 100644 sound/soc/codecs/i-sabre-codec.h
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -55,6 +55,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ hy28a.dtbo \
+ hy28b.dtbo \
+ hy28b-2017.dtbo \
++ i-sabre-q2m.dtbo \
+ i2c-bcm2708.dtbo \
+ i2c-gpio.dtbo \
+ i2c-mux.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -869,6 +869,12 @@ Params: speed Display
+ ledgpio GPIO used to control backlight
+
+
++Name: i-sabre-q2m
++Info: Configures the Audiophonics I-SABRE Q2M DAC
++Load: dtoverlay=i-sabre-q2m
++Params: <None>
++
++
+ Name: i2c-bcm2708
+ Info: Fall back to the i2c_bcm2708 driver for the i2c_arm bus.
+ Load: dtoverlay=i2c-bcm2708
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
+@@ -0,0 +1,39 @@
++// Definitions for I-Sabre Q2M
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "brcm,bcm2708";
++
++ fragment@0 {
++ target = <&sound>;
++ frag0: __overlay__ {
++ compatible = "audiophonics,i-sabre-q2m";
++ 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";
++
++ i-sabre-codec@48 {
++ #sound-dai-cells = <0>;
++ compatible = "audiophonics,i-sabre-codec";
++ reg = <0x48>;
++ status = "okay";
++ };
++ };
++ };
++};
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -916,6 +916,7 @@ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m
+ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
++CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M=m
+ CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
+ CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m
+ CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -909,6 +909,7 @@ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m
+ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
++CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M=m
+ CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
+ CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m
+ CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -804,6 +804,7 @@ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m
+ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
++CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M=m
+ CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
+ CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m
+ CONFIG_SND_AUDIOSENSE_PI=m
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -123,6 +123,13 @@ config SND_BCM2708_SOC_IQAUDIO_DIGI
+ help
+ Say Y or M if you want to add support for IQAudIO Digital IO board.
+
++config SND_BCM2708_SOC_I_SABRE_Q2M
++ tristate "Support for Audiophonics I-Sabre Q2M DAC"
++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++ select SND_SOC_I_SABRE_CODEC
++ help
++ Say Y or M if you want to add support for Audiophonics I-SABRE Q2M DAC
++
+ config SND_BCM2708_SOC_ADAU1977_ADC
+ tristate "Support for ADAU1977 ADC"
+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -19,6 +19,7 @@ snd-soc-justboom-dac-objs := justboom-da
+ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
+ snd-soc-rpi-proto-objs := rpi-proto.o
+ snd-soc-iqaudio-dac-objs := iqaudio-dac.o
++ snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
+ snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
+ snd-soc-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o
+ snd-soc-audiosense-pi-objs := audiosense-pi.o
+@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DA
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.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_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.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_AUDIOSENSE_PI) += snd-soc-audiosense-pi.o
+--- /dev/null
++++ b/sound/soc/bcm/i-sabre-q2m.c
+@@ -0,0 +1,157 @@
++/*
++ * ASoC Driver for I-Sabre Q2M
++ *
++ * Author: Satoru Kawase
++ * Modified by: Xiao Qingyong
++ * Update kernel v4.18+ by : Audiophonics
++ * Copyright 2018 Audiophonics
++ *
++ * 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 <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <sound/core.h>
++#include <sound/soc.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++
++#include "../codecs/i-sabre-codec.h"
++
++
++static int snd_rpi_i_sabre_q2m_init(struct snd_soc_pcm_runtime *rtd)
++{
++ struct snd_soc_component *component = rtd->codec_dai->component;
++ unsigned int value;
++
++ /* Device ID */
++ value = snd_soc_component_read32(component, ISABRECODEC_REG_01);
++ dev_info(component->card->dev, "Audiophonics Device ID : %02X\n", value);
++
++ /* API revision */
++ value = snd_soc_component_read32(component, ISABRECODEC_REG_02);
++ dev_info(component->card->dev, "Audiophonics API revision : %02X\n", value);
++
++ return 0;
++}
++
++static int snd_rpi_i_sabre_q2m_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;
++ int bclk_ratio;
++
++ bclk_ratio = snd_pcm_format_physical_width(
++ params_format(params)) * params_channels(params);
++ return snd_soc_dai_set_bclk_ratio(cpu_dai, bclk_ratio);
++}
++
++/* machine stream operations */
++static struct snd_soc_ops snd_rpi_i_sabre_q2m_ops = {
++ .hw_params = snd_rpi_i_sabre_q2m_hw_params,
++};
++
++
++static struct snd_soc_dai_link snd_rpi_i_sabre_q2m_dai[] = {
++ {
++ .name = "I-Sabre Q2M",
++ .stream_name = "I-Sabre Q2M DAC",
++ .cpu_dai_name = "bcm2708-i2s.0",
++ .codec_dai_name = "i-sabre-codec-dai",
++ .platform_name = "bcm2708-i2s.0",
++ .codec_name = "i-sabre-codec-i2c.1-0048",
++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
++ | SND_SOC_DAIFMT_CBS_CFS,
++ .init = snd_rpi_i_sabre_q2m_init,
++ .ops = &snd_rpi_i_sabre_q2m_ops,
++ }
++};
++
++/* audio machine driver */
++static struct snd_soc_card snd_rpi_i_sabre_q2m = {
++ .name = "I-Sabre Q2M DAC",
++ .owner = THIS_MODULE,
++ .dai_link = snd_rpi_i_sabre_q2m_dai,
++ .num_links = ARRAY_SIZE(snd_rpi_i_sabre_q2m_dai)
++};
++
++
++static int snd_rpi_i_sabre_q2m_probe(struct platform_device *pdev)
++{
++ int ret = 0;
++
++ snd_rpi_i_sabre_q2m.dev = &pdev->dev;
++ if (pdev->dev.of_node) {
++ struct device_node *i2s_node;
++ struct snd_soc_dai_link *dai;
++
++ dai = &snd_rpi_i_sabre_q2m_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;
++ } else {
++ dev_err(&pdev->dev,
++ "Property 'i2s-controller' missing or invalid\n");
++ return (-EINVAL);
++ }
++
++ dai->name = "I-Sabre Q2M";
++ dai->stream_name = "I-Sabre Q2M DAC";
++ dai->dai_fmt = SND_SOC_DAIFMT_I2S
++ | SND_SOC_DAIFMT_NB_NF
++ | SND_SOC_DAIFMT_CBS_CFS;
++ }
++
++ /* Wait for registering codec driver */
++ mdelay(50);
++
++ ret = snd_soc_register_card(&snd_rpi_i_sabre_q2m);
++ if (ret) {
++ dev_err(&pdev->dev,
++ "snd_soc_register_card() failed: %d\n", ret);
++ }
++
++ return ret;
++}
++
++static int snd_rpi_i_sabre_q2m_remove(struct platform_device *pdev)
++{
++ return snd_soc_unregister_card(&snd_rpi_i_sabre_q2m);
++}
++
++static const struct of_device_id snd_rpi_i_sabre_q2m_of_match[] = {
++ { .compatible = "audiophonics,i-sabre-q2m", },
++ {}
++};
++MODULE_DEVICE_TABLE(of, snd_rpi_i_sabre_q2m_of_match);
++
++static struct platform_driver snd_rpi_i_sabre_q2m_driver = {
++ .driver = {
++ .name = "snd-rpi-i-sabre-q2m",
++ .owner = THIS_MODULE,
++ .of_match_table = snd_rpi_i_sabre_q2m_of_match,
++ },
++ .probe = snd_rpi_i_sabre_q2m_probe,
++ .remove = snd_rpi_i_sabre_q2m_remove,
++};
++module_platform_driver(snd_rpi_i_sabre_q2m_driver);
++
++MODULE_DESCRIPTION("ASoC Driver for I-Sabre Q2M");
++MODULE_AUTHOR("Audiophonics <http://www.audiophonics.fr>");
++MODULE_LICENSE("GPL");
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -85,6 +85,7 @@ config SND_SOC_ALL_CODECS
+ select SND_SOC_ICS43432
+ select SND_SOC_INNO_RK3036
+ select SND_SOC_ISABELLE if I2C
++ select SND_SOC_I_SABRE_CODEC if I2C
+ select SND_SOC_JZ4740_CODEC
+ select SND_SOC_LM4857 if I2C
+ select SND_SOC_LM49453 if I2C
+@@ -1322,4 +1323,8 @@ config SND_SOC_TPA6130A2
+ tristate "Texas Instruments TPA6130A2 headphone amplifier"
+ depends on I2C
+
++config SND_SOC_I_SABRE_CODEC
++ tristate "Audiophonics I-SABRE Codec"
++ depends on I2C
++
+ endmenu
+--- a/sound/soc/codecs/Makefile
++++ b/sound/soc/codecs/Makefile
+@@ -81,6 +81,7 @@ snd-soc-hdac-hdmi-objs := hdac_hdmi.o
+ snd-soc-ics43432-objs := ics43432.o
+ snd-soc-inno-rk3036-objs := inno_rk3036.o
+ snd-soc-isabelle-objs := isabelle.o
++snd-soc-i-sabre-codec-objs := i-sabre-codec.o
+ snd-soc-jz4740-codec-objs := jz4740.o
+ snd-soc-l3-objs := l3.o
+ snd-soc-lm4857-objs := lm4857.o
+@@ -343,6 +344,7 @@ obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-s
+ obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o
+ obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o
+ obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
++obj-$(CONFIG_SND_SOC_I_SABRE_CODEC) += snd-soc-i-sabre-codec.o
+ obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
+ obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
+ obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
+--- /dev/null
++++ b/sound/soc/codecs/i-sabre-codec.c
+@@ -0,0 +1,392 @@
++/*
++ * Driver for I-Sabre Q2M
++ *
++ * Author: Satoru Kawase
++ * Modified by: Xiao Qingyong
++ * Modified by: JC BARBAUD (Mute)
++ * Update kernel v4.18+ by : Audiophonics
++ * Copyright 2018 Audiophonics
++ *
++ * 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 <linux/init.h>
++#include <linux/module.h>
++#include <linux/regmap.h>
++#include <linux/i2c.h>
++#include <sound/soc.h>
++#include <sound/pcm_params.h>
++#include <sound/tlv.h>
++
++#include "i-sabre-codec.h"
++
++
++/* I-Sabre Q2M Codec Private Data */
++struct i_sabre_codec_priv {
++ struct regmap *regmap;
++ unsigned int fmt;
++};
++
++
++/* I-Sabre Q2M Codec Default Register Value */
++static const struct reg_default i_sabre_codec_reg_defaults[] = {
++ { ISABRECODEC_REG_10, 0x00 },
++ { ISABRECODEC_REG_20, 0x00 },
++ { ISABRECODEC_REG_21, 0x00 },
++ { ISABRECODEC_REG_22, 0x00 },
++ { ISABRECODEC_REG_24, 0x00 },
++};
++
++
++static bool i_sabre_codec_writeable(struct device *dev, unsigned int reg)
++{
++ switch (reg) {
++ case ISABRECODEC_REG_10:
++ case ISABRECODEC_REG_20:
++ case ISABRECODEC_REG_21:
++ case ISABRECODEC_REG_22:
++ case ISABRECODEC_REG_24:
++ return true;
++
++ default:
++ return false;
++ }
++}
++
++static bool i_sabre_codec_readable(struct device *dev, unsigned int reg)
++{
++ switch (reg) {
++ case ISABRECODEC_REG_01:
++ case ISABRECODEC_REG_02:
++ case ISABRECODEC_REG_10:
++ case ISABRECODEC_REG_20:
++ case ISABRECODEC_REG_21:
++ case ISABRECODEC_REG_22:
++ case ISABRECODEC_REG_24:
++ return true;
++
++ default:
++ return false;
++ }
++}
++
++static bool i_sabre_codec_volatile(struct device *dev, unsigned int reg)
++{
++ switch (reg) {
++ case ISABRECODEC_REG_01:
++ case ISABRECODEC_REG_02:
++ return true;
++
++ default:
++ return false;
++ }
++}
++
++
++/* Volume Scale */
++static const DECLARE_TLV_DB_SCALE(volume_tlv, -10000, 100, 0);
++
++
++/* Filter Type */
++static const char * const fir_filter_type_texts[] = {
++ "brick wall",
++ "corrected minimum phase fast",
++ "minimum phase slow",
++ "minimum phase fast",
++ "linear phase slow",
++ "linear phase fast",
++ "apodizing fast",
++};
++
++static SOC_ENUM_SINGLE_DECL(i_sabre_fir_filter_type_enum,
++ ISABRECODEC_REG_22, 0, fir_filter_type_texts);
++
++
++/* I2S / SPDIF Select */
++static const char * const iis_spdif_sel_texts[] = {
++ "I2S",
++ "SPDIF",
++};
++
++static SOC_ENUM_SINGLE_DECL(i_sabre_iis_spdif_sel_enum,
++ ISABRECODEC_REG_24, 0, iis_spdif_sel_texts);
++
++
++/* Control */
++static const struct snd_kcontrol_new i_sabre_codec_controls[] = {
++SOC_SINGLE_RANGE_TLV("Digital Playback Volume", ISABRECODEC_REG_20, 0, 0, 100, 1, volume_tlv),
++SOC_SINGLE("Digital Playback Switch", ISABRECODEC_REG_21, 0, 1, 1),
++SOC_ENUM("FIR Filter Type", i_sabre_fir_filter_type_enum),
++SOC_ENUM("I2S/SPDIF Select", i_sabre_iis_spdif_sel_enum),
++};
++
++
++static const u32 i_sabre_codec_dai_rates_slave[] = {
++ 8000, 11025, 16000, 22050, 32000,
++ 44100, 48000, 64000, 88200, 96000,
++ 176400, 192000, 352800, 384000,
++ 705600, 768000, 1411200, 1536000
++};
++
++static const struct snd_pcm_hw_constraint_list constraints_slave = {
++ .list = i_sabre_codec_dai_rates_slave,
++ .count = ARRAY_SIZE(i_sabre_codec_dai_rates_slave),
++};
++
++static int i_sabre_codec_dai_startup_slave(
++ struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
++{
++ struct snd_soc_component *component = dai->component;
++ int ret;
++
++ ret = snd_pcm_hw_constraint_list(substream->runtime,
++ 0, SNDRV_PCM_HW_PARAM_RATE, &constraints_slave);
++ if (ret != 0) {
++ dev_err(component->card->dev, "Failed to setup rates constraints: %d\n", ret);
++ }
++
++ return ret;
++}
++
++static int i_sabre_codec_dai_startup(
++ struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
++{
++ struct snd_soc_component *component = dai->component;
++ struct i_sabre_codec_priv *i_sabre_codec
++ = snd_soc_component_get_drvdata(component);
++
++ switch (i_sabre_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
++ case SND_SOC_DAIFMT_CBS_CFS:
++ return i_sabre_codec_dai_startup_slave(substream, dai);
++
++ default:
++ return (-EINVAL);
++ }
++}
++
++static int i_sabre_codec_hw_params(
++ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
++ struct snd_soc_dai *dai)
++{
++ struct snd_soc_component *component = dai->component;
++ struct i_sabre_codec_priv *i_sabre_codec
++ = snd_soc_component_get_drvdata(component);
++ unsigned int daifmt;
++ int format_width;
++
++ dev_dbg(component->card->dev, "hw_params %u Hz, %u channels\n",
++ params_rate(params), params_channels(params));
++
++ /* Check I2S Format (Bit Size) */
++ format_width = snd_pcm_format_width(params_format(params));
++ if ((format_width != 32) && (format_width != 16)) {
++ dev_err(component->card->dev, "Bad frame size: %d\n",
++ snd_pcm_format_width(params_format(params)));
++ return (-EINVAL);
++ }
++
++ /* Check Slave Mode */
++ daifmt = i_sabre_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK;
++ if (daifmt != SND_SOC_DAIFMT_CBS_CFS) {
++ return (-EINVAL);
++ }
++
++ /* Notify Sampling Frequency */
++ switch (params_rate(params))
++ {
++ case 44100:
++ case 48000:
++ case 88200:
++ case 96000:
++ case 176400:
++ case 192000:
++ snd_soc_component_update_bits(component, ISABRECODEC_REG_10, 0x01, 0x00);
++ break;
++
++ case 352800:
++ case 384000:
++ case 705600:
++ case 768000:
++ case 1411200:
++ case 1536000:
++ snd_soc_component_update_bits(component, ISABRECODEC_REG_10, 0x01, 0x01);
++ break;
++ }
++
++ return 0;
++}
++
++static int i_sabre_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
++{
++ struct snd_soc_component *component = dai->component;
++ struct i_sabre_codec_priv *i_sabre_codec
++ = snd_soc_component_get_drvdata(component);
++
++ /* interface format */
++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++ case SND_SOC_DAIFMT_I2S:
++ break;
++
++ case SND_SOC_DAIFMT_RIGHT_J:
++ case SND_SOC_DAIFMT_LEFT_J:
++ default:
++ return (-EINVAL);
++ }
++
++ /* clock inversion */
++ if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
++ return (-EINVAL);
++ }
++
++ /* Set Audio Data Format */
++ i_sabre_codec->fmt = fmt;
++
++ return 0;
++}
++
++static int i_sabre_codec_dac_mute(struct snd_soc_dai *dai, int mute)
++{
++ struct snd_soc_component *component = dai->component;
++
++ if (mute) {
++ snd_soc_component_update_bits(component, ISABRECODEC_REG_21, 0x01, 0x01);
++ } else {
++ snd_soc_component_update_bits(component, ISABRECODEC_REG_21, 0x01, 0x00);
++ }
++
++ return 0;
++}
++
++
++static const struct snd_soc_dai_ops i_sabre_codec_dai_ops = {
++ .startup = i_sabre_codec_dai_startup,
++ .hw_params = i_sabre_codec_hw_params,
++ .set_fmt = i_sabre_codec_set_fmt,
++ .digital_mute = i_sabre_codec_dac_mute,
++};
++
++static struct snd_soc_dai_driver i_sabre_codec_dai = {
++ .name = "i-sabre-codec-dai",
++ .playback = {
++ .stream_name = "Playback",
++ .channels_min = 2,
++ .channels_max = 2,
++ .rates = SNDRV_PCM_RATE_CONTINUOUS,
++ .rate_min = 8000,
++ .rate_max = 1536000,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE
++ | SNDRV_PCM_FMTBIT_S32_LE,
++ },
++ .ops = &i_sabre_codec_dai_ops,
++};
++
++static struct snd_soc_component_driver i_sabre_codec_codec_driver = {
++ .controls = i_sabre_codec_controls,
++ .num_controls = ARRAY_SIZE(i_sabre_codec_controls),
++};
++
++
++static const struct regmap_config i_sabre_codec_regmap = {
++ .reg_bits = 8,
++ .val_bits = 8,
++ .max_register = ISABRECODEC_MAX_REG,
++
++ .reg_defaults = i_sabre_codec_reg_defaults,
++ .num_reg_defaults = ARRAY_SIZE(i_sabre_codec_reg_defaults),
++
++ .writeable_reg = i_sabre_codec_writeable,
++ .readable_reg = i_sabre_codec_readable,
++ .volatile_reg = i_sabre_codec_volatile,
++
++ .cache_type = REGCACHE_RBTREE,
++};
++
++
++static int i_sabre_codec_probe(struct device *dev, struct regmap *regmap)
++{
++ struct i_sabre_codec_priv *i_sabre_codec;
++ int ret;
++
++ i_sabre_codec = devm_kzalloc(dev, sizeof(*i_sabre_codec), GFP_KERNEL);
++ if (!i_sabre_codec) {
++ dev_err(dev, "devm_kzalloc");
++ return (-ENOMEM);
++ }
++
++ i_sabre_codec->regmap = regmap;
++
++ dev_set_drvdata(dev, i_sabre_codec);
++
++ ret = snd_soc_register_component(dev,
++ &i_sabre_codec_codec_driver, &i_sabre_codec_dai, 1);
++ if (ret != 0) {
++ dev_err(dev, "Failed to register CODEC: %d\n", ret);
++ return ret;
++ }
++
++ return 0;
++}
++
++static void i_sabre_codec_remove(struct device *dev)
++{
++ snd_soc_unregister_component(dev);
++}
++
++
++static int i_sabre_codec_i2c_probe(
++ struct i2c_client *i2c, const struct i2c_device_id *id)
++{
++ struct regmap *regmap;
++
++ regmap = devm_regmap_init_i2c(i2c, &i_sabre_codec_regmap);
++ if (IS_ERR(regmap)) {
++ return PTR_ERR(regmap);
++ }
++
++ return i_sabre_codec_probe(&i2c->dev, regmap);
++}
++
++static int i_sabre_codec_i2c_remove(struct i2c_client *i2c)
++{
++ i_sabre_codec_remove(&i2c->dev);
++
++ return 0;
++}
++
++
++static const struct i2c_device_id i_sabre_codec_i2c_id[] = {
++ { "i-sabre-codec", },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, i_sabre_codec_i2c_id);
++
++static const struct of_device_id i_sabre_codec_of_match[] = {
++ { .compatible = "audiophonics,i-sabre-codec", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, i_sabre_codec_of_match);
++
++static struct i2c_driver i_sabre_codec_i2c_driver = {
++ .driver = {
++ .name = "i-sabre-codec-i2c",
++ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(i_sabre_codec_of_match),
++ },
++ .probe = i_sabre_codec_i2c_probe,
++ .remove = i_sabre_codec_i2c_remove,
++ .id_table = i_sabre_codec_i2c_id,
++};
++module_i2c_driver(i_sabre_codec_i2c_driver);
++
++
++MODULE_DESCRIPTION("ASoC I-Sabre Q2M codec driver");
++MODULE_AUTHOR("Audiophonics <http://www.audiophonics.fr>");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/sound/soc/codecs/i-sabre-codec.h
+@@ -0,0 +1,42 @@
++/*
++ * Driver for I-Sabre Q2M
++ *
++ * Author: Satoru Kawase
++ * Modified by: Xiao Qingyong
++ * Copyright 2018 Audiophonics
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ */
++
++#ifndef _SND_SOC_ISABRECODEC
++#define _SND_SOC_ISABRECODEC
++
++
++/* ISABRECODEC Register Address */
++#define ISABRECODEC_REG_01 0x01 /* Virtual Device ID : 0x01 = es9038q2m */
++#define ISABRECODEC_REG_02 0x02 /* API revision : 0x01 = Revision 01 */
++#define ISABRECODEC_REG_10 0x10 /* 0x01 = above 192kHz, 0x00 = otherwise */
++#define ISABRECODEC_REG_20 0x20 /* 0 - 100 (decimal value, 0 = min., 100 = max.) */
++#define ISABRECODEC_REG_21 0x21 /* 0x00 = Mute OFF, 0x01 = Mute ON */
++#define ISABRECODEC_REG_22 0x22
++/*
++ 0x00 = brick wall,
++ 0x01 = corrected minimum phase fast,
++ 0x02 = minimum phase slow,
++ 0x03 = minimum phase fast,
++ 0x04 = linear phase slow,
++ 0x05 = linear phase fast,
++ 0x06 = apodizing fast,
++*/
++//#define ISABRECODEC_REG_23 0x23 /* reserved */
++#define ISABRECODEC_REG_24 0x24 /* 0x00 = I2S, 0x01 = SPDIF */
++#define ISABRECODEC_MAX_REG 0x24 /* Maximum Register Number */
++
++#endif /* _SND_SOC_ISABRECODEC */
+++ /dev/null
-From c72904446aa20ab6136502697641545cc5e7dc7e Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Thu, 21 Mar 2019 17:58:54 -0700
-Subject: [PATCH 414/703] ASoC: tlv320aic32x4: Allow 192000 Sample Rate
-
-commit 6d56ee1550b8a81bc63c80051ff78d8d704b09ba upstream.
-
-The clocking and processing blocks are now properly set up to
-support 192000 sample rates. Allow drivers to ask for that.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -859,7 +859,7 @@ static int aic32x4_set_bias_level(struct
- return 0;
- }
-
--#define AIC32X4_RATES SNDRV_PCM_RATE_8000_96000
-+#define AIC32X4_RATES SNDRV_PCM_RATE_8000_192000
- #define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
- | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
-
--- /dev/null
+From 05c2d56f6c014aea65288abbb10a28feb2c284fb Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 3 Apr 2019 21:17:15 -0700
+Subject: [PATCH 414/725] ASoC: tlv320aic32x4: Change author's name
+
+commit 7297ba6c74c5b9e78d8e936af82eecfcf7d32dfb upstream.
+
+The author of these files has changed her name. Update
+instances in the code of her dead name to current legal
+name.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4-i2c.c | 4 ++--
+ sound/soc/codecs/tlv320aic32x4-spi.c | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4-i2c.c
++++ b/sound/soc/codecs/tlv320aic32x4-i2c.c
+@@ -3,7 +3,7 @@
+ *
+ * Copyright 2011 NW Digital Radio
+ *
+- * Author: Jeremy McDermond <nh6z@nh6z.net>
++ * Author: Annaliese McDermond <nh6z@nh6z.net>
+ *
+ * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
+ *
+@@ -72,5 +72,5 @@ static struct i2c_driver aic32x4_i2c_dri
+ module_i2c_driver(aic32x4_i2c_driver);
+
+ MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver I2C");
+-MODULE_AUTHOR("Jeremy McDermond <nh6z@nh6z.net>");
++MODULE_AUTHOR("Annaliese McDermond <nh6z@nh6z.net>");
+ MODULE_LICENSE("GPL");
+--- a/sound/soc/codecs/tlv320aic32x4-spi.c
++++ b/sound/soc/codecs/tlv320aic32x4-spi.c
+@@ -3,7 +3,7 @@
+ *
+ * Copyright 2011 NW Digital Radio
+ *
+- * Author: Jeremy McDermond <nh6z@nh6z.net>
++ * Author: Annaliese McDermond <nh6z@nh6z.net>
+ *
+ * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
+ *
+@@ -74,5 +74,5 @@ static struct spi_driver aic32x4_spi_dri
+ module_spi_driver(aic32x4_spi_driver);
+
+ MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver SPI");
+-MODULE_AUTHOR("Jeremy McDermond <nh6z@nh6z.net>");
++MODULE_AUTHOR("Annaliese McDermond <nh6z@nh6z.net>");
+ MODULE_LICENSE("GPL");
+++ /dev/null
-From 499d000a3d56edf6c5d2bf81de6d7af5348eb258 Mon Sep 17 00:00:00 2001
-From: Mark Brown <broonie@kernel.org>
-Date: Tue, 26 Mar 2019 13:10:13 +0000
-Subject: [PATCH 415/703] ASoC: tlv320aic32x4: Only enable with common clock
-
-commit 64f01d2b5ccc621c3aa66b82daf9154f5581f36a upstream.
-
-Some architectures do not yet support the common clock API at all but
-the tlv320aic32x4 driver now requires it.
-
-Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/Kconfig | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
---- a/sound/soc/codecs/Kconfig
-+++ b/sound/soc/codecs/Kconfig
-@@ -170,8 +170,8 @@ config SND_SOC_ALL_CODECS
- select SND_SOC_TAS5713 if I2C
- select SND_SOC_TLV320AIC26 if SPI_MASTER
- select SND_SOC_TLV320AIC31XX if I2C
-- select SND_SOC_TLV320AIC32X4_I2C if I2C
-- select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER
-+ select SND_SOC_TLV320AIC32X4_I2C if I2C && COMMON_CLK
-+ select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER && COMMON_CLK
- select SND_SOC_TLV320AIC3X if I2C
- select SND_SOC_TPA6130A2 if I2C
- select SND_SOC_TLV320DAC33 if I2C
-@@ -1030,11 +1030,13 @@ config SND_SOC_TLV320AIC32X4
- config SND_SOC_TLV320AIC32X4_I2C
- tristate "Texas Instruments TLV320AIC32x4 audio CODECs - I2C"
- depends on I2C
-+ depends on COMMON_CLK
- select SND_SOC_TLV320AIC32X4
-
- config SND_SOC_TLV320AIC32X4_SPI
- tristate "Texas Instruments TLV320AIC32x4 audio CODECs - SPI"
- depends on SPI_MASTER
-+ depends on COMMON_CLK
- select SND_SOC_TLV320AIC32X4
-
- config SND_SOC_TLV320AIC3X
--- /dev/null
+From 019b18d8dd0b7c6e8123ae6fb91235b21d80833b Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 3 Apr 2019 21:17:16 -0700
+Subject: [PATCH 415/725] ASoC: tlv320aic32x4: Update copyright and use SPDX
+ identifier
+
+commit 8a1d95c393d971e624fc28f11516b0bc3a7fa706 upstream.
+
+Update the copyright dates and use the SPDX identifier instead
+of reciting the license.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4-i2c.c | 14 ++------------
+ sound/soc/codecs/tlv320aic32x4-spi.c | 14 ++------------
+ 2 files changed, 4 insertions(+), 24 deletions(-)
+
+--- a/sound/soc/codecs/tlv320aic32x4-i2c.c
++++ b/sound/soc/codecs/tlv320aic32x4-i2c.c
+@@ -1,21 +1,11 @@
+-/*
+- * linux/sound/soc/codecs/tlv320aic32x4-i2c.c
++/* SPDX-License-Identifier: GPL-2.0
+ *
+- * Copyright 2011 NW Digital Radio
++ * Copyright 2011-2019 NW Digital Radio
+ *
+ * Author: Annaliese McDermond <nh6z@nh6z.net>
+ *
+ * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
+ *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+ */
+
+ #include <linux/i2c.h>
+--- a/sound/soc/codecs/tlv320aic32x4-spi.c
++++ b/sound/soc/codecs/tlv320aic32x4-spi.c
+@@ -1,21 +1,11 @@
+-/*
+- * linux/sound/soc/codecs/tlv320aic32x4-spi.c
++/* SPDX-License-Identifier: GPL-2.0
+ *
+- * Copyright 2011 NW Digital Radio
++ * Copyright 2011-2019 NW Digital Radio
+ *
+ * Author: Annaliese McDermond <nh6z@nh6z.net>
+ *
+ * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
+ *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+ */
+
+ #include <linux/spi/spi.h>
--- /dev/null
+From 283878c9a11df280fe7621f79409a1228de68843 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 3 Apr 2019 21:01:54 -0700
+Subject: [PATCH 416/725] ASoC: tlv320aic32x4: Add Switch for Setting Common
+ Mode Voltage
+
+commit 44ceee847e27c828f2f1ef4e400e6bc0c8d04de3 upstream.
+
+Add a switch for setting common mode voltage. This can allow
+for higher drive levels on the amplifier outputs.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -242,6 +242,12 @@ static DECLARE_TLV_DB_SCALE(tlv_driver_g
+ /* -12dB min, 0.5dB steps */
+ static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0);
+
++static const char * const lo_cm_text[] = {
++ "Full Chip", "1.65V",
++};
++
++static SOC_ENUM_SINGLE_DECL(lo_cm_enum, AIC32X4_CMMODE, 3, lo_cm_text);
++
+ static const struct snd_kcontrol_new aic32x4_snd_controls[] = {
+ SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL,
+ AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm),
+@@ -255,6 +261,7 @@ static const struct snd_kcontrol_new aic
+ AIC32X4_HPRGAIN, 6, 0x01, 1),
+ SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN,
+ AIC32X4_LORGAIN, 6, 0x01, 1),
++ SOC_ENUM("LO Playback Common Mode Switch", lo_cm_enum),
+ SOC_DOUBLE_R("Mic PGA Switch", AIC32X4_LMICPGAVOL,
+ AIC32X4_RMICPGAVOL, 7, 0x01, 1),
+
+++ /dev/null
-From b40f72a9aeee6ce7d7df3a3b3ff602234215fe79 Mon Sep 17 00:00:00 2001
-From: FERHAT Nicolas <contact@audiophonics.fr>
-Date: Fri, 5 Apr 2019 13:06:42 +0100
-Subject: [PATCH 416/703] Audiophonics I-Sabre 9038Q2M DAC driver
-
-Signed-off-by: Audiophonics <contact@audiophonics.fr>
----
- arch/arm/boot/dts/overlays/Makefile | 1 +
- arch/arm/boot/dts/overlays/README | 6 +
- .../boot/dts/overlays/i-sabre-q2m-overlay.dts | 39 ++
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- sound/soc/bcm/Kconfig | 7 +
- sound/soc/bcm/Makefile | 2 +
- sound/soc/bcm/i-sabre-q2m.c | 157 +++++++
- sound/soc/codecs/Kconfig | 5 +
- sound/soc/codecs/Makefile | 2 +
- sound/soc/codecs/i-sabre-codec.c | 392 ++++++++++++++++++
- sound/soc/codecs/i-sabre-codec.h | 42 ++
- 13 files changed, 656 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
- create mode 100644 sound/soc/bcm/i-sabre-q2m.c
- create mode 100644 sound/soc/codecs/i-sabre-codec.c
- create mode 100644 sound/soc/codecs/i-sabre-codec.h
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -55,6 +55,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- hy28a.dtbo \
- hy28b.dtbo \
- hy28b-2017.dtbo \
-+ i-sabre-q2m.dtbo \
- i2c-bcm2708.dtbo \
- i2c-gpio.dtbo \
- i2c-mux.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -869,6 +869,12 @@ Params: speed Display
- ledgpio GPIO used to control backlight
-
-
-+Name: i-sabre-q2m
-+Info: Configures the Audiophonics I-SABRE Q2M DAC
-+Load: dtoverlay=i-sabre-q2m
-+Params: <None>
-+
-+
- Name: i2c-bcm2708
- Info: Fall back to the i2c_bcm2708 driver for the i2c_arm bus.
- Load: dtoverlay=i2c-bcm2708
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
-@@ -0,0 +1,39 @@
-+// Definitions for I-Sabre Q2M
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+ compatible = "brcm,bcm2708";
-+
-+ fragment@0 {
-+ target = <&sound>;
-+ frag0: __overlay__ {
-+ compatible = "audiophonics,i-sabre-q2m";
-+ 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";
-+
-+ i-sabre-codec@48 {
-+ #sound-dai-cells = <0>;
-+ compatible = "audiophonics,i-sabre-codec";
-+ reg = <0x48>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+};
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -916,6 +916,7 @@ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m
- CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
-+CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M=m
- CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
- CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m
- CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -909,6 +909,7 @@ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m
- CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
-+CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M=m
- CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
- CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m
- CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -804,6 +804,7 @@ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m
- CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
-+CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M=m
- CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
- CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m
- CONFIG_SND_AUDIOSENSE_PI=m
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -123,6 +123,13 @@ config SND_BCM2708_SOC_IQAUDIO_DIGI
- help
- Say Y or M if you want to add support for IQAudIO Digital IO board.
-
-+config SND_BCM2708_SOC_I_SABRE_Q2M
-+ tristate "Support for Audiophonics I-Sabre Q2M DAC"
-+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+ select SND_SOC_I_SABRE_CODEC
-+ help
-+ Say Y or M if you want to add support for Audiophonics I-SABRE Q2M DAC
-+
- config SND_BCM2708_SOC_ADAU1977_ADC
- tristate "Support for ADAU1977 ADC"
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -19,6 +19,7 @@ snd-soc-justboom-dac-objs := justboom-da
- snd-soc-rpi-cirrus-objs := rpi-cirrus.o
- snd-soc-rpi-proto-objs := rpi-proto.o
- snd-soc-iqaudio-dac-objs := iqaudio-dac.o
-+ snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
- snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
- snd-soc-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o
- snd-soc-audiosense-pi-objs := audiosense-pi.o
-@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DA
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.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_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.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_AUDIOSENSE_PI) += snd-soc-audiosense-pi.o
---- /dev/null
-+++ b/sound/soc/bcm/i-sabre-q2m.c
-@@ -0,0 +1,157 @@
-+/*
-+ * ASoC Driver for I-Sabre Q2M
-+ *
-+ * Author: Satoru Kawase
-+ * Modified by: Xiao Qingyong
-+ * Update kernel v4.18+ by : Audiophonics
-+ * Copyright 2018 Audiophonics
-+ *
-+ * 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 <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/delay.h>
-+#include <linux/fs.h>
-+#include <asm/uaccess.h>
-+#include <sound/core.h>
-+#include <sound/soc.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+
-+#include "../codecs/i-sabre-codec.h"
-+
-+
-+static int snd_rpi_i_sabre_q2m_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+ struct snd_soc_component *component = rtd->codec_dai->component;
-+ unsigned int value;
-+
-+ /* Device ID */
-+ value = snd_soc_component_read32(component, ISABRECODEC_REG_01);
-+ dev_info(component->card->dev, "Audiophonics Device ID : %02X\n", value);
-+
-+ /* API revision */
-+ value = snd_soc_component_read32(component, ISABRECODEC_REG_02);
-+ dev_info(component->card->dev, "Audiophonics API revision : %02X\n", value);
-+
-+ return 0;
-+}
-+
-+static int snd_rpi_i_sabre_q2m_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;
-+ int bclk_ratio;
-+
-+ bclk_ratio = snd_pcm_format_physical_width(
-+ params_format(params)) * params_channels(params);
-+ return snd_soc_dai_set_bclk_ratio(cpu_dai, bclk_ratio);
-+}
-+
-+/* machine stream operations */
-+static struct snd_soc_ops snd_rpi_i_sabre_q2m_ops = {
-+ .hw_params = snd_rpi_i_sabre_q2m_hw_params,
-+};
-+
-+
-+static struct snd_soc_dai_link snd_rpi_i_sabre_q2m_dai[] = {
-+ {
-+ .name = "I-Sabre Q2M",
-+ .stream_name = "I-Sabre Q2M DAC",
-+ .cpu_dai_name = "bcm2708-i2s.0",
-+ .codec_dai_name = "i-sabre-codec-dai",
-+ .platform_name = "bcm2708-i2s.0",
-+ .codec_name = "i-sabre-codec-i2c.1-0048",
-+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
-+ | SND_SOC_DAIFMT_CBS_CFS,
-+ .init = snd_rpi_i_sabre_q2m_init,
-+ .ops = &snd_rpi_i_sabre_q2m_ops,
-+ }
-+};
-+
-+/* audio machine driver */
-+static struct snd_soc_card snd_rpi_i_sabre_q2m = {
-+ .name = "I-Sabre Q2M DAC",
-+ .owner = THIS_MODULE,
-+ .dai_link = snd_rpi_i_sabre_q2m_dai,
-+ .num_links = ARRAY_SIZE(snd_rpi_i_sabre_q2m_dai)
-+};
-+
-+
-+static int snd_rpi_i_sabre_q2m_probe(struct platform_device *pdev)
-+{
-+ int ret = 0;
-+
-+ snd_rpi_i_sabre_q2m.dev = &pdev->dev;
-+ if (pdev->dev.of_node) {
-+ struct device_node *i2s_node;
-+ struct snd_soc_dai_link *dai;
-+
-+ dai = &snd_rpi_i_sabre_q2m_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;
-+ } else {
-+ dev_err(&pdev->dev,
-+ "Property 'i2s-controller' missing or invalid\n");
-+ return (-EINVAL);
-+ }
-+
-+ dai->name = "I-Sabre Q2M";
-+ dai->stream_name = "I-Sabre Q2M DAC";
-+ dai->dai_fmt = SND_SOC_DAIFMT_I2S
-+ | SND_SOC_DAIFMT_NB_NF
-+ | SND_SOC_DAIFMT_CBS_CFS;
-+ }
-+
-+ /* Wait for registering codec driver */
-+ mdelay(50);
-+
-+ ret = snd_soc_register_card(&snd_rpi_i_sabre_q2m);
-+ if (ret) {
-+ dev_err(&pdev->dev,
-+ "snd_soc_register_card() failed: %d\n", ret);
-+ }
-+
-+ return ret;
-+}
-+
-+static int snd_rpi_i_sabre_q2m_remove(struct platform_device *pdev)
-+{
-+ return snd_soc_unregister_card(&snd_rpi_i_sabre_q2m);
-+}
-+
-+static const struct of_device_id snd_rpi_i_sabre_q2m_of_match[] = {
-+ { .compatible = "audiophonics,i-sabre-q2m", },
-+ {}
-+};
-+MODULE_DEVICE_TABLE(of, snd_rpi_i_sabre_q2m_of_match);
-+
-+static struct platform_driver snd_rpi_i_sabre_q2m_driver = {
-+ .driver = {
-+ .name = "snd-rpi-i-sabre-q2m",
-+ .owner = THIS_MODULE,
-+ .of_match_table = snd_rpi_i_sabre_q2m_of_match,
-+ },
-+ .probe = snd_rpi_i_sabre_q2m_probe,
-+ .remove = snd_rpi_i_sabre_q2m_remove,
-+};
-+module_platform_driver(snd_rpi_i_sabre_q2m_driver);
-+
-+MODULE_DESCRIPTION("ASoC Driver for I-Sabre Q2M");
-+MODULE_AUTHOR("Audiophonics <http://www.audiophonics.fr>");
-+MODULE_LICENSE("GPL");
---- a/sound/soc/codecs/Kconfig
-+++ b/sound/soc/codecs/Kconfig
-@@ -85,6 +85,7 @@ config SND_SOC_ALL_CODECS
- select SND_SOC_ICS43432
- select SND_SOC_INNO_RK3036
- select SND_SOC_ISABELLE if I2C
-+ select SND_SOC_I_SABRE_CODEC if I2C
- select SND_SOC_JZ4740_CODEC
- select SND_SOC_LM4857 if I2C
- select SND_SOC_LM49453 if I2C
-@@ -1322,4 +1323,8 @@ config SND_SOC_TPA6130A2
- tristate "Texas Instruments TPA6130A2 headphone amplifier"
- depends on I2C
-
-+config SND_SOC_I_SABRE_CODEC
-+ tristate "Audiophonics I-SABRE Codec"
-+ depends on I2C
-+
- endmenu
---- a/sound/soc/codecs/Makefile
-+++ b/sound/soc/codecs/Makefile
-@@ -81,6 +81,7 @@ snd-soc-hdac-hdmi-objs := hdac_hdmi.o
- snd-soc-ics43432-objs := ics43432.o
- snd-soc-inno-rk3036-objs := inno_rk3036.o
- snd-soc-isabelle-objs := isabelle.o
-+snd-soc-i-sabre-codec-objs := i-sabre-codec.o
- snd-soc-jz4740-codec-objs := jz4740.o
- snd-soc-l3-objs := l3.o
- snd-soc-lm4857-objs := lm4857.o
-@@ -343,6 +344,7 @@ obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-s
- obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o
- obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o
- obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
-+obj-$(CONFIG_SND_SOC_I_SABRE_CODEC) += snd-soc-i-sabre-codec.o
- obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
- obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
- obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
---- /dev/null
-+++ b/sound/soc/codecs/i-sabre-codec.c
-@@ -0,0 +1,392 @@
-+/*
-+ * Driver for I-Sabre Q2M
-+ *
-+ * Author: Satoru Kawase
-+ * Modified by: Xiao Qingyong
-+ * Modified by: JC BARBAUD (Mute)
-+ * Update kernel v4.18+ by : Audiophonics
-+ * Copyright 2018 Audiophonics
-+ *
-+ * 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 <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/regmap.h>
-+#include <linux/i2c.h>
-+#include <sound/soc.h>
-+#include <sound/pcm_params.h>
-+#include <sound/tlv.h>
-+
-+#include "i-sabre-codec.h"
-+
-+
-+/* I-Sabre Q2M Codec Private Data */
-+struct i_sabre_codec_priv {
-+ struct regmap *regmap;
-+ unsigned int fmt;
-+};
-+
-+
-+/* I-Sabre Q2M Codec Default Register Value */
-+static const struct reg_default i_sabre_codec_reg_defaults[] = {
-+ { ISABRECODEC_REG_10, 0x00 },
-+ { ISABRECODEC_REG_20, 0x00 },
-+ { ISABRECODEC_REG_21, 0x00 },
-+ { ISABRECODEC_REG_22, 0x00 },
-+ { ISABRECODEC_REG_24, 0x00 },
-+};
-+
-+
-+static bool i_sabre_codec_writeable(struct device *dev, unsigned int reg)
-+{
-+ switch (reg) {
-+ case ISABRECODEC_REG_10:
-+ case ISABRECODEC_REG_20:
-+ case ISABRECODEC_REG_21:
-+ case ISABRECODEC_REG_22:
-+ case ISABRECODEC_REG_24:
-+ return true;
-+
-+ default:
-+ return false;
-+ }
-+}
-+
-+static bool i_sabre_codec_readable(struct device *dev, unsigned int reg)
-+{
-+ switch (reg) {
-+ case ISABRECODEC_REG_01:
-+ case ISABRECODEC_REG_02:
-+ case ISABRECODEC_REG_10:
-+ case ISABRECODEC_REG_20:
-+ case ISABRECODEC_REG_21:
-+ case ISABRECODEC_REG_22:
-+ case ISABRECODEC_REG_24:
-+ return true;
-+
-+ default:
-+ return false;
-+ }
-+}
-+
-+static bool i_sabre_codec_volatile(struct device *dev, unsigned int reg)
-+{
-+ switch (reg) {
-+ case ISABRECODEC_REG_01:
-+ case ISABRECODEC_REG_02:
-+ return true;
-+
-+ default:
-+ return false;
-+ }
-+}
-+
-+
-+/* Volume Scale */
-+static const DECLARE_TLV_DB_SCALE(volume_tlv, -10000, 100, 0);
-+
-+
-+/* Filter Type */
-+static const char * const fir_filter_type_texts[] = {
-+ "brick wall",
-+ "corrected minimum phase fast",
-+ "minimum phase slow",
-+ "minimum phase fast",
-+ "linear phase slow",
-+ "linear phase fast",
-+ "apodizing fast",
-+};
-+
-+static SOC_ENUM_SINGLE_DECL(i_sabre_fir_filter_type_enum,
-+ ISABRECODEC_REG_22, 0, fir_filter_type_texts);
-+
-+
-+/* I2S / SPDIF Select */
-+static const char * const iis_spdif_sel_texts[] = {
-+ "I2S",
-+ "SPDIF",
-+};
-+
-+static SOC_ENUM_SINGLE_DECL(i_sabre_iis_spdif_sel_enum,
-+ ISABRECODEC_REG_24, 0, iis_spdif_sel_texts);
-+
-+
-+/* Control */
-+static const struct snd_kcontrol_new i_sabre_codec_controls[] = {
-+SOC_SINGLE_RANGE_TLV("Digital Playback Volume", ISABRECODEC_REG_20, 0, 0, 100, 1, volume_tlv),
-+SOC_SINGLE("Digital Playback Switch", ISABRECODEC_REG_21, 0, 1, 1),
-+SOC_ENUM("FIR Filter Type", i_sabre_fir_filter_type_enum),
-+SOC_ENUM("I2S/SPDIF Select", i_sabre_iis_spdif_sel_enum),
-+};
-+
-+
-+static const u32 i_sabre_codec_dai_rates_slave[] = {
-+ 8000, 11025, 16000, 22050, 32000,
-+ 44100, 48000, 64000, 88200, 96000,
-+ 176400, 192000, 352800, 384000,
-+ 705600, 768000, 1411200, 1536000
-+};
-+
-+static const struct snd_pcm_hw_constraint_list constraints_slave = {
-+ .list = i_sabre_codec_dai_rates_slave,
-+ .count = ARRAY_SIZE(i_sabre_codec_dai_rates_slave),
-+};
-+
-+static int i_sabre_codec_dai_startup_slave(
-+ struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
-+{
-+ struct snd_soc_component *component = dai->component;
-+ int ret;
-+
-+ ret = snd_pcm_hw_constraint_list(substream->runtime,
-+ 0, SNDRV_PCM_HW_PARAM_RATE, &constraints_slave);
-+ if (ret != 0) {
-+ dev_err(component->card->dev, "Failed to setup rates constraints: %d\n", ret);
-+ }
-+
-+ return ret;
-+}
-+
-+static int i_sabre_codec_dai_startup(
-+ struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
-+{
-+ struct snd_soc_component *component = dai->component;
-+ struct i_sabre_codec_priv *i_sabre_codec
-+ = snd_soc_component_get_drvdata(component);
-+
-+ switch (i_sabre_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-+ case SND_SOC_DAIFMT_CBS_CFS:
-+ return i_sabre_codec_dai_startup_slave(substream, dai);
-+
-+ default:
-+ return (-EINVAL);
-+ }
-+}
-+
-+static int i_sabre_codec_hw_params(
-+ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
-+ struct snd_soc_dai *dai)
-+{
-+ struct snd_soc_component *component = dai->component;
-+ struct i_sabre_codec_priv *i_sabre_codec
-+ = snd_soc_component_get_drvdata(component);
-+ unsigned int daifmt;
-+ int format_width;
-+
-+ dev_dbg(component->card->dev, "hw_params %u Hz, %u channels\n",
-+ params_rate(params), params_channels(params));
-+
-+ /* Check I2S Format (Bit Size) */
-+ format_width = snd_pcm_format_width(params_format(params));
-+ if ((format_width != 32) && (format_width != 16)) {
-+ dev_err(component->card->dev, "Bad frame size: %d\n",
-+ snd_pcm_format_width(params_format(params)));
-+ return (-EINVAL);
-+ }
-+
-+ /* Check Slave Mode */
-+ daifmt = i_sabre_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK;
-+ if (daifmt != SND_SOC_DAIFMT_CBS_CFS) {
-+ return (-EINVAL);
-+ }
-+
-+ /* Notify Sampling Frequency */
-+ switch (params_rate(params))
-+ {
-+ case 44100:
-+ case 48000:
-+ case 88200:
-+ case 96000:
-+ case 176400:
-+ case 192000:
-+ snd_soc_component_update_bits(component, ISABRECODEC_REG_10, 0x01, 0x00);
-+ break;
-+
-+ case 352800:
-+ case 384000:
-+ case 705600:
-+ case 768000:
-+ case 1411200:
-+ case 1536000:
-+ snd_soc_component_update_bits(component, ISABRECODEC_REG_10, 0x01, 0x01);
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+static int i_sabre_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-+{
-+ struct snd_soc_component *component = dai->component;
-+ struct i_sabre_codec_priv *i_sabre_codec
-+ = snd_soc_component_get_drvdata(component);
-+
-+ /* interface format */
-+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-+ case SND_SOC_DAIFMT_I2S:
-+ break;
-+
-+ case SND_SOC_DAIFMT_RIGHT_J:
-+ case SND_SOC_DAIFMT_LEFT_J:
-+ default:
-+ return (-EINVAL);
-+ }
-+
-+ /* clock inversion */
-+ if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
-+ return (-EINVAL);
-+ }
-+
-+ /* Set Audio Data Format */
-+ i_sabre_codec->fmt = fmt;
-+
-+ return 0;
-+}
-+
-+static int i_sabre_codec_dac_mute(struct snd_soc_dai *dai, int mute)
-+{
-+ struct snd_soc_component *component = dai->component;
-+
-+ if (mute) {
-+ snd_soc_component_update_bits(component, ISABRECODEC_REG_21, 0x01, 0x01);
-+ } else {
-+ snd_soc_component_update_bits(component, ISABRECODEC_REG_21, 0x01, 0x00);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static const struct snd_soc_dai_ops i_sabre_codec_dai_ops = {
-+ .startup = i_sabre_codec_dai_startup,
-+ .hw_params = i_sabre_codec_hw_params,
-+ .set_fmt = i_sabre_codec_set_fmt,
-+ .digital_mute = i_sabre_codec_dac_mute,
-+};
-+
-+static struct snd_soc_dai_driver i_sabre_codec_dai = {
-+ .name = "i-sabre-codec-dai",
-+ .playback = {
-+ .stream_name = "Playback",
-+ .channels_min = 2,
-+ .channels_max = 2,
-+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
-+ .rate_min = 8000,
-+ .rate_max = 1536000,
-+ .formats = SNDRV_PCM_FMTBIT_S16_LE
-+ | SNDRV_PCM_FMTBIT_S32_LE,
-+ },
-+ .ops = &i_sabre_codec_dai_ops,
-+};
-+
-+static struct snd_soc_component_driver i_sabre_codec_codec_driver = {
-+ .controls = i_sabre_codec_controls,
-+ .num_controls = ARRAY_SIZE(i_sabre_codec_controls),
-+};
-+
-+
-+static const struct regmap_config i_sabre_codec_regmap = {
-+ .reg_bits = 8,
-+ .val_bits = 8,
-+ .max_register = ISABRECODEC_MAX_REG,
-+
-+ .reg_defaults = i_sabre_codec_reg_defaults,
-+ .num_reg_defaults = ARRAY_SIZE(i_sabre_codec_reg_defaults),
-+
-+ .writeable_reg = i_sabre_codec_writeable,
-+ .readable_reg = i_sabre_codec_readable,
-+ .volatile_reg = i_sabre_codec_volatile,
-+
-+ .cache_type = REGCACHE_RBTREE,
-+};
-+
-+
-+static int i_sabre_codec_probe(struct device *dev, struct regmap *regmap)
-+{
-+ struct i_sabre_codec_priv *i_sabre_codec;
-+ int ret;
-+
-+ i_sabre_codec = devm_kzalloc(dev, sizeof(*i_sabre_codec), GFP_KERNEL);
-+ if (!i_sabre_codec) {
-+ dev_err(dev, "devm_kzalloc");
-+ return (-ENOMEM);
-+ }
-+
-+ i_sabre_codec->regmap = regmap;
-+
-+ dev_set_drvdata(dev, i_sabre_codec);
-+
-+ ret = snd_soc_register_component(dev,
-+ &i_sabre_codec_codec_driver, &i_sabre_codec_dai, 1);
-+ if (ret != 0) {
-+ dev_err(dev, "Failed to register CODEC: %d\n", ret);
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static void i_sabre_codec_remove(struct device *dev)
-+{
-+ snd_soc_unregister_component(dev);
-+}
-+
-+
-+static int i_sabre_codec_i2c_probe(
-+ struct i2c_client *i2c, const struct i2c_device_id *id)
-+{
-+ struct regmap *regmap;
-+
-+ regmap = devm_regmap_init_i2c(i2c, &i_sabre_codec_regmap);
-+ if (IS_ERR(regmap)) {
-+ return PTR_ERR(regmap);
-+ }
-+
-+ return i_sabre_codec_probe(&i2c->dev, regmap);
-+}
-+
-+static int i_sabre_codec_i2c_remove(struct i2c_client *i2c)
-+{
-+ i_sabre_codec_remove(&i2c->dev);
-+
-+ return 0;
-+}
-+
-+
-+static const struct i2c_device_id i_sabre_codec_i2c_id[] = {
-+ { "i-sabre-codec", },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(i2c, i_sabre_codec_i2c_id);
-+
-+static const struct of_device_id i_sabre_codec_of_match[] = {
-+ { .compatible = "audiophonics,i-sabre-codec", },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, i_sabre_codec_of_match);
-+
-+static struct i2c_driver i_sabre_codec_i2c_driver = {
-+ .driver = {
-+ .name = "i-sabre-codec-i2c",
-+ .owner = THIS_MODULE,
-+ .of_match_table = of_match_ptr(i_sabre_codec_of_match),
-+ },
-+ .probe = i_sabre_codec_i2c_probe,
-+ .remove = i_sabre_codec_i2c_remove,
-+ .id_table = i_sabre_codec_i2c_id,
-+};
-+module_i2c_driver(i_sabre_codec_i2c_driver);
-+
-+
-+MODULE_DESCRIPTION("ASoC I-Sabre Q2M codec driver");
-+MODULE_AUTHOR("Audiophonics <http://www.audiophonics.fr>");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/sound/soc/codecs/i-sabre-codec.h
-@@ -0,0 +1,42 @@
-+/*
-+ * Driver for I-Sabre Q2M
-+ *
-+ * Author: Satoru Kawase
-+ * Modified by: Xiao Qingyong
-+ * Copyright 2018 Audiophonics
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * version 2 as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ */
-+
-+#ifndef _SND_SOC_ISABRECODEC
-+#define _SND_SOC_ISABRECODEC
-+
-+
-+/* ISABRECODEC Register Address */
-+#define ISABRECODEC_REG_01 0x01 /* Virtual Device ID : 0x01 = es9038q2m */
-+#define ISABRECODEC_REG_02 0x02 /* API revision : 0x01 = Revision 01 */
-+#define ISABRECODEC_REG_10 0x10 /* 0x01 = above 192kHz, 0x00 = otherwise */
-+#define ISABRECODEC_REG_20 0x20 /* 0 - 100 (decimal value, 0 = min., 100 = max.) */
-+#define ISABRECODEC_REG_21 0x21 /* 0x00 = Mute OFF, 0x01 = Mute ON */
-+#define ISABRECODEC_REG_22 0x22
-+/*
-+ 0x00 = brick wall,
-+ 0x01 = corrected minimum phase fast,
-+ 0x02 = minimum phase slow,
-+ 0x03 = minimum phase fast,
-+ 0x04 = linear phase slow,
-+ 0x05 = linear phase fast,
-+ 0x06 = apodizing fast,
-+*/
-+//#define ISABRECODEC_REG_23 0x23 /* reserved */
-+#define ISABRECODEC_REG_24 0x24 /* 0x00 = I2S, 0x01 = SPDIF */
-+#define ISABRECODEC_MAX_REG 0x24 /* Maximum Register Number */
-+
-+#endif /* _SND_SOC_ISABRECODEC */
--- /dev/null
+From 731092f2b29ef4e1c0081698d683d9542426e500 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 3 Apr 2019 21:01:55 -0700
+Subject: [PATCH 417/725] ASoC: tlv320aic32x4: Add Playback PowerTune Controls
+
+commit d3e6e374566e1154820a9a3dc82f7eef646fcf95 upstream.
+
+PowerTune controls the power level of the chip. On playback this
+indirectly controls things like the gain of the various output
+amplifiers. This can allow for the decrease of output levels
+from the codec. This adds controls for those power levels to
+the driver.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/codecs/tlv320aic32x4.c | 9 +++++++++
+ sound/soc/codecs/tlv320aic32x4.h | 2 ++
+ 2 files changed, 11 insertions(+)
+
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -248,9 +248,18 @@ static const char * const lo_cm_text[] =
+
+ static SOC_ENUM_SINGLE_DECL(lo_cm_enum, AIC32X4_CMMODE, 3, lo_cm_text);
+
++static const char * const ptm_text[] = {
++ "P3", "P2", "P1",
++};
++
++static SOC_ENUM_SINGLE_DECL(l_ptm_enum, AIC32X4_LPLAYBACK, 2, ptm_text);
++static SOC_ENUM_SINGLE_DECL(r_ptm_enum, AIC32X4_RPLAYBACK, 2, ptm_text);
++
+ static const struct snd_kcontrol_new aic32x4_snd_controls[] = {
+ SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL,
+ AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm),
++ SOC_ENUM("DAC Left Playback PowerTune Switch", l_ptm_enum),
++ SOC_ENUM("DAC Right Playback PowerTune Switch", r_ptm_enum),
+ SOC_DOUBLE_R_S_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN,
+ AIC32X4_HPRGAIN, 0, -0x6, 0x1d, 5, 0,
+ tlv_driver_gain),
+--- a/sound/soc/codecs/tlv320aic32x4.h
++++ b/sound/soc/codecs/tlv320aic32x4.h
+@@ -78,6 +78,8 @@ int aic32x4_register_clocks(struct devic
+
+ #define AIC32X4_PWRCFG AIC32X4_REG(1, 1)
+ #define AIC32X4_LDOCTL AIC32X4_REG(1, 2)
++#define AIC32X4_LPLAYBACK AIC32X4_REG(1, 3)
++#define AIC32X4_RPLAYBACK AIC32X4_REG(1, 4)
+ #define AIC32X4_OUTPWRCTL AIC32X4_REG(1, 9)
+ #define AIC32X4_CMMODE AIC32X4_REG(1, 10)
+ #define AIC32X4_HPLROUTE AIC32X4_REG(1, 12)
+++ /dev/null
-From fcde4e55513ec62d7a0fdc18c9db9445de741f4f Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Wed, 3 Apr 2019 21:17:15 -0700
-Subject: [PATCH 417/703] ASoC: tlv320aic32x4: Change author's name
-
-commit 7297ba6c74c5b9e78d8e936af82eecfcf7d32dfb upstream.
-
-The author of these files has changed her name. Update
-instances in the code of her dead name to current legal
-name.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4-i2c.c | 4 ++--
- sound/soc/codecs/tlv320aic32x4-spi.c | 4 ++--
- 2 files changed, 4 insertions(+), 4 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4-i2c.c
-+++ b/sound/soc/codecs/tlv320aic32x4-i2c.c
-@@ -3,7 +3,7 @@
- *
- * Copyright 2011 NW Digital Radio
- *
-- * Author: Jeremy McDermond <nh6z@nh6z.net>
-+ * Author: Annaliese McDermond <nh6z@nh6z.net>
- *
- * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
- *
-@@ -72,5 +72,5 @@ static struct i2c_driver aic32x4_i2c_dri
- module_i2c_driver(aic32x4_i2c_driver);
-
- MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver I2C");
--MODULE_AUTHOR("Jeremy McDermond <nh6z@nh6z.net>");
-+MODULE_AUTHOR("Annaliese McDermond <nh6z@nh6z.net>");
- MODULE_LICENSE("GPL");
---- a/sound/soc/codecs/tlv320aic32x4-spi.c
-+++ b/sound/soc/codecs/tlv320aic32x4-spi.c
-@@ -3,7 +3,7 @@
- *
- * Copyright 2011 NW Digital Radio
- *
-- * Author: Jeremy McDermond <nh6z@nh6z.net>
-+ * Author: Annaliese McDermond <nh6z@nh6z.net>
- *
- * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
- *
-@@ -74,5 +74,5 @@ static struct spi_driver aic32x4_spi_dri
- module_spi_driver(aic32x4_spi_driver);
-
- MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver SPI");
--MODULE_AUTHOR("Jeremy McDermond <nh6z@nh6z.net>");
-+MODULE_AUTHOR("Annaliese McDermond <nh6z@nh6z.net>");
- MODULE_LICENSE("GPL");
+++ /dev/null
-From c287dc67e33f04d09f8bc0d2cdf900d6b720fc78 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Wed, 3 Apr 2019 21:17:16 -0700
-Subject: [PATCH 418/703] ASoC: tlv320aic32x4: Update copyright and use SPDX
- identifier
-
-commit 8a1d95c393d971e624fc28f11516b0bc3a7fa706 upstream.
-
-Update the copyright dates and use the SPDX identifier instead
-of reciting the license.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4-i2c.c | 14 ++------------
- sound/soc/codecs/tlv320aic32x4-spi.c | 14 ++------------
- 2 files changed, 4 insertions(+), 24 deletions(-)
-
---- a/sound/soc/codecs/tlv320aic32x4-i2c.c
-+++ b/sound/soc/codecs/tlv320aic32x4-i2c.c
-@@ -1,21 +1,11 @@
--/*
-- * linux/sound/soc/codecs/tlv320aic32x4-i2c.c
-+/* SPDX-License-Identifier: GPL-2.0
- *
-- * Copyright 2011 NW Digital Radio
-+ * Copyright 2011-2019 NW Digital Radio
- *
- * Author: Annaliese McDermond <nh6z@nh6z.net>
- *
- * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
- */
-
- #include <linux/i2c.h>
---- a/sound/soc/codecs/tlv320aic32x4-spi.c
-+++ b/sound/soc/codecs/tlv320aic32x4-spi.c
-@@ -1,21 +1,11 @@
--/*
-- * linux/sound/soc/codecs/tlv320aic32x4-spi.c
-+/* SPDX-License-Identifier: GPL-2.0
- *
-- * Copyright 2011 NW Digital Radio
-+ * Copyright 2011-2019 NW Digital Radio
- *
- * Author: Annaliese McDermond <nh6z@nh6z.net>
- *
- * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
- */
-
- #include <linux/spi/spi.h>
--- /dev/null
+From 3fbe7d511602b2888eec568b8870484a06e165e7 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Sun, 17 Mar 2019 16:48:36 -0700
+Subject: [PATCH 418/725] dtoverlays: Add Support for the UDRC/DRAWS
+
+Adds a new overlay to support the Northwest Digital Radio
+DRAWS and UDRC HATs. See http://nwdigitalradio.com.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+---
+ arch/arm/boot/dts/overlays/Makefile | 2 +
+ arch/arm/boot/dts/overlays/README | 59 ++++++
+ arch/arm/boot/dts/overlays/draws-overlay.dts | 200 +++++++++++++++++++
+ arch/arm/boot/dts/overlays/udrc-overlay.dts | 128 ++++++++++++
+ 4 files changed, 389 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/draws-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/udrc-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -29,6 +29,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ dionaudio-loco-v2.dtbo \
+ dpi18.dtbo \
+ dpi24.dtbo \
++ draws.dtbo \
+ dwc-otg.dtbo \
+ dwc2.dtbo \
+ enc28j60.dtbo \
+@@ -146,6 +147,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ tpm-slb9670.dtbo \
+ uart0.dtbo \
+ uart1.dtbo \
++ udrc.dtbo \
+ upstream.dtbo \
+ upstream-aux-interrupt.dtbo \
+ vc4-fkms-v3d.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -531,6 +531,59 @@ Load: dtoverlay=dpi24
+ Params: <None>
+
+
++Name: draws
++Info: Configures the NW Digital Radio DRAWS Hat
++
++ The board includes an ADC to measure various board values and also
++ provides two analog user inputs on the expansion header. The ADC
++ can be configured for various sample rates and gain values to adjust
++ the input range. Tables describing the two parameters follow.
++
++ ADC Gain Values:
++ 0 = +/- 6.144V
++ 1 = +/- 4.096V
++ 2 = +/- 2.048V
++ 3 = +/- 1.024V
++ 4 = +/- 0.512V
++ 5 = +/- 0.256V
++ 6 = +/- 0.256V
++ 7 = +/- 0.256V
++
++ ADC Datarate Values:
++ 0 = 128sps
++ 1 = 250sps
++ 2 = 490sps
++ 3 = 920sps
++ 4 = 1600sps (default)
++ 5 = 2400sps
++ 6 = 3300sps
++ 7 = 3300sps
++Load: dtoverlay=draws,<param>=<val>
++Params: draws_adc_ch4_gain Sets the full scale resolution of the ADCs
++ input voltage sensor (default 1)
++
++ draws_adc_ch4_datarate Sets the datarate of the ADCs input voltage
++ sensor
++
++ draws_adc_ch5_gain Sets the full scale resolution of the ADCs
++ 5V rail voltage sensor (default 1)
++
++ draws_adc_ch5_datarate Sets the datarate of the ADCs 4V rail voltage
++ sensor
++
++ draws_adc_ch6_gain Sets the full scale resolution of the ADCs
++ AIN2 input (default 2)
++
++ draws_adc_ch6_datarate Sets the datarate of the ADCs AIN2 input
++
++ draws_adc_ch7_gain Sets the full scale resolution of the ADCs
++ AIN3 input (default 2)
++
++ draws_adc_ch7_datarate Sets the datarate of the ADCs AIN3 input
++
++ alsaname Name of the ALSA audio device (default "draws")
++
++
+ Name: dwc-otg
+ Info: Selects the dwc_otg USB controller driver which has fiq support. This
+ is the default on all except the Pi Zero which defaults to dwc2.
+@@ -2117,6 +2170,12 @@ Params: txd1_pin GPIO pin
+ rxd1_pin GPIO pin for RXD1 (15, 33 or 41 - default 15)
+
+
++Name: udrc
++Info: Configures the NW Digital Radio UDRC Hat
++Load: dtoverlay=udrc,<param>=<val>
++Params: alsaname Name of the ALSA audio device (default "udrc")
++
++
+ Name: upstream
+ Info: Allow usage of downstream .dtb with upstream kernel. Comprises
+ vc4-kms-v3d, dwc2 and upstream-aux-interrupt overlays.
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/draws-overlay.dts
+@@ -0,0 +1,200 @@
++#include <dt-bindings/clock/bcm2835.h>
++/*
++ * Device tree overlay for the DRAWS Hardware
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++ fragment@0 {
++ target = <&i2s>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@1 {
++ target-path = "/";
++ __overlay__ {
++ regulators {
++ compatible = "simple-bus";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ udrc0_ldoin: udrc0_ldoin {
++ compatible = "regulator-fixed";
++ regulator-name = "ldoin";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-always-on;
++ };
++ };
++
++ pps: pps {
++ compatible = "pps-gpio";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pps_pins>;
++ gpios = <&gpio 7 0>;
++ status = "okay";
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&i2c_arm>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ tlv320aic32x4: tlv320aic32x4@18 {
++ compatible = "ti,tlv320aic32x4";
++ reg = <0x18>;
++ #sound-dai-cells = <0>;
++ status = "okay";
++
++ clocks = <&clocks BCM2835_CLOCK_GP0>;
++ clock-names = "mclk";
++ assigned-clocks = <&clocks BCM2835_CLOCK_GP0>;
++ assigned-clock-rates = <25000000>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&gpclk0_pin &aic3204_reset>;
++
++ reset-gpios = <&gpio 13 0>;
++
++ iov-supply = <&udrc0_ldoin>;
++ ldoin-supply = <&udrc0_ldoin>;
++ };
++
++ sc16is752: sc16is752@50 {
++ compatible = "nxp,sc16is752";
++ reg = <0x50>;
++ clocks = <&sc16is752_clk>;
++ interrupt-parent = <&gpio>;
++ interrupts = <17 2>; /* IRQ_TYPE_EDGE_FALLING */
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&sc16is752_irq>;
++
++ sc16is752_clk: sc16is752_clk {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <1843200>;
++ };
++ };
++
++ tla2024: tla2024@48 {
++ compatible = "ti,ads1015";
++ reg = <0x48>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ adc_ch4: channel@4 {
++ reg = <4>;
++ ti,gain = <1>;
++ ti,datarate = <4>;
++ };
++
++ adc_ch5: channel@5 {
++ reg = <5>;
++ ti,gain = <1>;
++ ti,datarate = <4>;
++ };
++
++ adc_ch6: channel@6 {
++ reg = <6>;
++ ti,gain = <2>;
++ ti,datarate = <4>;
++ };
++
++ adc_ch7: channel@7 {
++ reg = <7>;
++ ti,gain = <2>;
++ ti,datarate = <4>;
++ };
++ };
++ };
++ };
++
++ fragment@3 {
++ target = <&sound>;
++ snd: __overlay__ {
++ compatible = "simple-audio-card";
++ i2s-controller = <&i2s>;
++ status = "okay";
++
++ simple-audio-card,name = "draws";
++ simple-audio-card,format = "i2s";
++
++ simple-audio-card,bitclock-master = <&dailink0_master>;
++ simple-audio-card,frame-master = <&dailink0_master>;
++
++ simple-audio-card,widgets =
++ "Line", "Line In",
++ "Line", "Line Out";
++
++ simple-audio-card,routing =
++ "IN1_R", "Line In",
++ "IN1_L", "Line In",
++ "CM_L", "Line In",
++ "CM_R", "Line In",
++ "Line Out", "LOR",
++ "Line Out", "LOL";
++
++ dailink0_master: simple-audio-card,cpu {
++ sound-dai = <&i2s>;
++ };
++
++ simple-audio-card,codec {
++ sound-dai = <&tlv320aic32x4>;
++ };
++ };
++ };
++
++ fragment@4 {
++ target = <&gpio>;
++ __overlay__ {
++ gpclk0_pin: gpclk0_pin {
++ brcm,pins = <4>;
++ brcm,function = <4>;
++ };
++
++ aic3204_reset: aic3204_reset {
++ brcm,pins = <13>;
++ brcm,function = <1>;
++ brcm,pull = <1>;
++ };
++
++ aic3204_gpio: aic3204_gpio {
++ brcm,pins = <26>;
++ };
++
++ sc16is752_irq: sc16is752_irq {
++ brcm,pins = <17>;
++ brcm,function = <0>;
++ brcm,pull = <2>;
++ };
++
++ pps_pins: pps_pins {
++ brcm,pins = <7>;
++ brcm,function = <0>;
++ brcm,pull = <0>;
++ };
++ };
++ };
++
++ __overrides__ {
++ draws_adc_ch4_gain = <&adc_ch4>,"ti,gain:0";
++ draws_adc_ch4_datarate = <&adc_ch4>,"ti,datarate:0";
++ draws_adc_ch5_gain = <&adc_ch5>,"ti,gain:0";
++ draws_adc_ch5_datarate = <&adc_ch5>,"ti,datarate:0";
++ draws_adc_ch6_gain = <&adc_ch6>,"ti,gain:0";
++ draws_adc_ch6_datarate = <&adc_ch6>,"ti,datarate:0";
++ draws_adc_ch7_gain = <&adc_ch7>,"ti,gain:0";
++ draws_adc_ch7_datarate = <&adc_ch7>,"ti,datarate:0";
++ alsaname = <&snd>, "simple-audio-card,name";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/udrc-overlay.dts
+@@ -0,0 +1,128 @@
++#include <dt-bindings/clock/bcm2835.h>
++/*
++ * Device tree overlay for the Universal Digital Radio Controller
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++ fragment@0 {
++ target = <&i2s>;
++ __overlay__ {
++ clocks = <&clocks BCM2835_CLOCK_PCM>;
++ clock-names = "pcm";
++ status = "okay";
++ };
++ };
++
++ fragment@1 {
++ target-path = "/";
++ __overlay__ {
++ regulators {
++ compatible = "simple-bus";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ udrc0_ldoin: udrc0_ldoin {
++ compatible = "regulator-fixed";
++ regulator-name = "ldoin";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-always-on;
++ };
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&i2c1>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++ clocks = <&clocks BCM2835_CLOCK_VPU>;
++ clock-frequency = <400000>;
++
++ tlv320aic32x4: tlv320aic32x4@18 {
++ compatible = "ti,tlv320aic32x4";
++ #sound-dai-cells = <0>;
++ reg = <0x18>;
++ status = "okay";
++
++ clocks = <&clocks BCM2835_CLOCK_GP0>;
++ clock-names = "mclk";
++ assigned-clocks = <&clocks BCM2835_CLOCK_GP0>;
++ assigned-clock-rates = <25000000>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&gpclk0_pin &aic3204_reset>;
++
++ reset-gpios = <&gpio 13 0>;
++
++ iov-supply = <&udrc0_ldoin>;
++ ldoin-supply = <&udrc0_ldoin>;
++ };
++ };
++ };
++
++ fragment@3 {
++ target = <&sound>;
++ snd: __overlay__ {
++ compatible = "simple-audio-card";
++ i2s-controller = <&i2s>;
++ status = "okay";
++
++ simple-audio-card,name = "udrc";
++ simple-audio-card,format = "i2s";
++
++ simple-audio-card,bitclock-master = <&dailink0_master>;
++ simple-audio-card,frame-master = <&dailink0_master>;
++
++ simple-audio-card,widgets =
++ "Line", "Line In",
++ "Line", "Line Out";
++
++ simple-audio-card,routing =
++ "IN1_R", "Line In",
++ "IN1_L", "Line In",
++ "CM_L", "Line In",
++ "CM_R", "Line In",
++ "Line Out", "LOR",
++ "Line Out", "LOL";
++
++ dailink0_master: simple-audio-card,cpu {
++ sound-dai = <&i2s>;
++ };
++
++ simple-audio-card,codec {
++ sound-dai = <&tlv320aic32x4>;
++ };
++ };
++ };
++
++ fragment@4 {
++ target = <&gpio>;
++ __overlay__ {
++ gpclk0_pin: gpclk0_pin {
++ brcm,pins = <4>;
++ brcm,function = <4>;
++ };
++
++ aic3204_reset: aic3204_reset {
++ brcm,pins = <13>;
++ brcm,function = <1>;
++ brcm,pull = <1>;
++ };
++
++ aic3204_gpio: aic3204_gpio {
++ brcm,pins = <26>;
++ };
++ };
++ };
++
++ __overrides__ {
++ alsaname = <&snd>, "simple-audio-card,name";
++ };
++};
+++ /dev/null
-From 8821b9227b5e19f7a745c5836b6ef4b9a478904f Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Wed, 3 Apr 2019 21:01:54 -0700
-Subject: [PATCH 419/703] ASoC: tlv320aic32x4: Add Switch for Setting Common
- Mode Voltage
-
-commit 44ceee847e27c828f2f1ef4e400e6bc0c8d04de3 upstream.
-
-Add a switch for setting common mode voltage. This can allow
-for higher drive levels on the amplifier outputs.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -242,6 +242,12 @@ static DECLARE_TLV_DB_SCALE(tlv_driver_g
- /* -12dB min, 0.5dB steps */
- static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0);
-
-+static const char * const lo_cm_text[] = {
-+ "Full Chip", "1.65V",
-+};
-+
-+static SOC_ENUM_SINGLE_DECL(lo_cm_enum, AIC32X4_CMMODE, 3, lo_cm_text);
-+
- static const struct snd_kcontrol_new aic32x4_snd_controls[] = {
- SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL,
- AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm),
-@@ -255,6 +261,7 @@ static const struct snd_kcontrol_new aic
- AIC32X4_HPRGAIN, 6, 0x01, 1),
- SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN,
- AIC32X4_LORGAIN, 6, 0x01, 1),
-+ SOC_ENUM("LO Playback Common Mode Switch", lo_cm_enum),
- SOC_DOUBLE_R("Mic PGA Switch", AIC32X4_LMICPGAVOL,
- AIC32X4_RMICPGAVOL, 7, 0x01, 1),
-
--- /dev/null
+From d3245a8de2208d8147707fb35cd3a6da99107cc6 Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Mon, 8 Apr 2019 12:45:23 +0100
+Subject: [PATCH 419/725] dwc_otg: only do_split when we actually need to do a
+ split
+
+The previous test would fail if the root port was in fullspeed mode
+and there was a hub between the FS device and the root port. While
+the transfer worked, the schedule mangling performed for high-speed
+split transfers would break leading to an 8ms polling interval.
+---
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
+@@ -167,8 +167,10 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
+ char *speed, *type;
+ int dev_speed;
+ uint32_t hub_addr, hub_port;
++ hprt0_data_t hprt;
+
+ dwc_memset(qh, 0, sizeof(dwc_otg_qh_t));
++ hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
+
+ /* Initialize QH */
+ qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
+@@ -191,9 +193,8 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
+
+ qh->nak_frame = 0xffff;
+
+- if (((dev_speed == USB_SPEED_LOW) ||
+- (dev_speed == USB_SPEED_FULL)) &&
+- (hub_addr != 0 && hub_addr != 1)) {
++ if (hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED &&
++ dev_speed != USB_SPEED_HIGH) {
+ DWC_DEBUGPL(DBG_HCD,
+ "QH init: EP %d: TT found at hub addr %d, for port %d\n",
+ dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
+@@ -204,7 +205,6 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
+
+ if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
+ /* Compute scheduling parameters once and save them. */
+- hprt0_data_t hprt;
+
+ /** @todo Account for split transfers in the bus time. */
+ int bytecount =
+@@ -219,7 +219,6 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
+ SCHEDULE_SLOP);
+ qh->interval = urb->interval;
+
+- hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
+ if (hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) {
+ if (dev_speed == USB_SPEED_LOW ||
+ dev_speed == USB_SPEED_FULL) {
+++ /dev/null
-From cbea77ecf69bf49def7f8222e38037a9349adbaa Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Wed, 3 Apr 2019 21:01:55 -0700
-Subject: [PATCH 420/703] ASoC: tlv320aic32x4: Add Playback PowerTune Controls
-
-commit d3e6e374566e1154820a9a3dc82f7eef646fcf95 upstream.
-
-PowerTune controls the power level of the chip. On playback this
-indirectly controls things like the gain of the various output
-amplifiers. This can allow for the decrease of output levels
-from the codec. This adds controls for those power levels to
-the driver.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/codecs/tlv320aic32x4.c | 9 +++++++++
- sound/soc/codecs/tlv320aic32x4.h | 2 ++
- 2 files changed, 11 insertions(+)
-
---- a/sound/soc/codecs/tlv320aic32x4.c
-+++ b/sound/soc/codecs/tlv320aic32x4.c
-@@ -248,9 +248,18 @@ static const char * const lo_cm_text[] =
-
- static SOC_ENUM_SINGLE_DECL(lo_cm_enum, AIC32X4_CMMODE, 3, lo_cm_text);
-
-+static const char * const ptm_text[] = {
-+ "P3", "P2", "P1",
-+};
-+
-+static SOC_ENUM_SINGLE_DECL(l_ptm_enum, AIC32X4_LPLAYBACK, 2, ptm_text);
-+static SOC_ENUM_SINGLE_DECL(r_ptm_enum, AIC32X4_RPLAYBACK, 2, ptm_text);
-+
- static const struct snd_kcontrol_new aic32x4_snd_controls[] = {
- SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL,
- AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm),
-+ SOC_ENUM("DAC Left Playback PowerTune Switch", l_ptm_enum),
-+ SOC_ENUM("DAC Right Playback PowerTune Switch", r_ptm_enum),
- SOC_DOUBLE_R_S_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN,
- AIC32X4_HPRGAIN, 0, -0x6, 0x1d, 5, 0,
- tlv_driver_gain),
---- a/sound/soc/codecs/tlv320aic32x4.h
-+++ b/sound/soc/codecs/tlv320aic32x4.h
-@@ -78,6 +78,8 @@ int aic32x4_register_clocks(struct devic
-
- #define AIC32X4_PWRCFG AIC32X4_REG(1, 1)
- #define AIC32X4_LDOCTL AIC32X4_REG(1, 2)
-+#define AIC32X4_LPLAYBACK AIC32X4_REG(1, 3)
-+#define AIC32X4_RPLAYBACK AIC32X4_REG(1, 4)
- #define AIC32X4_OUTPWRCTL AIC32X4_REG(1, 9)
- #define AIC32X4_CMMODE AIC32X4_REG(1, 10)
- #define AIC32X4_HPLROUTE AIC32X4_REG(1, 12)
--- /dev/null
+From 15ad41e728284da6191d9bd6ac77f797660bb54f Mon Sep 17 00:00:00 2001
+From: Samuel Hsu <hsu@distec.de>
+Date: Mon, 8 Apr 2019 16:42:17 +0200
+Subject: [PATCH 420/725] Input: ili210x - fetch touchscreen geometry from DT
+
+commit f67cc3e927d8414ad3872e046764534ea1f5db0d upstream
+
+Fetching the geometry from the ILI251x registers seems unreliable and
+sometimes returns all zeroes. Add support for fetching the geometry and
+axis inversion from DT instead.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+---
+ drivers/input/touchscreen/ili210x.c | 321 +++++++++++++++++-----------
+ 1 file changed, 194 insertions(+), 127 deletions(-)
+
+--- a/drivers/input/touchscreen/ili210x.c
++++ b/drivers/input/touchscreen/ili210x.c
+@@ -4,11 +4,15 @@
+ #include <linux/slab.h>
+ #include <linux/input.h>
+ #include <linux/input/mt.h>
++#include <linux/input/touchscreen.h>
+ #include <linux/delay.h>
+ #include <linux/workqueue.h>
+-#include <linux/input/ili210x.h>
++#include <linux/gpio/consumer.h>
++#include <linux/of_device.h>
++#include <asm/unaligned.h>
+
+-#define MAX_TOUCHES 2
++#define ILI210X_TOUCHES 2
++#define ILI251X_TOUCHES 10
+ #define DEFAULT_POLL_PERIOD 20
+
+ /* Touchscreen commands */
+@@ -17,41 +21,32 @@
+ #define REG_FIRMWARE_VERSION 0x40
+ #define REG_CALIBRATE 0xcc
+
+-struct finger {
+- u8 x_low;
+- u8 x_high;
+- u8 y_low;
+- u8 y_high;
+-} __packed;
+-
+-struct touchdata {
+- u8 status;
+- struct finger finger[MAX_TOUCHES];
+-} __packed;
+-
+-struct panel_info {
+- struct finger finger_max;
+- u8 xchannel_num;
+- u8 ychannel_num;
+-} __packed;
+-
+ struct firmware_version {
+ u8 id;
+ u8 major;
+ u8 minor;
+ } __packed;
+
++enum ili2xxx_model {
++ MODEL_ILI210X,
++ MODEL_ILI251X,
++};
++
+ struct ili210x {
+ struct i2c_client *client;
+ struct input_dev *input;
+- bool (*get_pendown_state)(void);
+ unsigned int poll_period;
+ struct delayed_work dwork;
++ struct gpio_desc *reset_gpio;
++ struct touchscreen_properties prop;
++ enum ili2xxx_model model;
++ unsigned int max_touches;
+ };
+
+ static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf,
+ size_t len)
+ {
++ struct ili210x *priv = i2c_get_clientdata(client);
+ struct i2c_msg msg[2] = {
+ {
+ .addr = client->addr,
+@@ -67,7 +62,38 @@ static int ili210x_read_reg(struct i2c_c
+ }
+ };
+
+- if (i2c_transfer(client->adapter, msg, 2) != 2) {
++ if (priv->model == MODEL_ILI251X) {
++ if (i2c_transfer(client->adapter, msg, 1) != 1) {
++ dev_err(&client->dev, "i2c transfer failed\n");
++ return -EIO;
++ }
++
++ usleep_range(5000, 5500);
++
++ if (i2c_transfer(client->adapter, msg + 1, 1) != 1) {
++ dev_err(&client->dev, "i2c transfer failed\n");
++ return -EIO;
++ }
++ } else {
++ if (i2c_transfer(client->adapter, msg, 2) != 2) {
++ dev_err(&client->dev, "i2c transfer failed\n");
++ return -EIO;
++ }
++ }
++
++ return 0;
++}
++
++static int ili210x_read(struct i2c_client *client, void *buf, size_t len)
++{
++ struct i2c_msg msg = {
++ .addr = client->addr,
++ .flags = I2C_M_RD,
++ .len = len,
++ .buf = buf,
++ };
++
++ if (i2c_transfer(client->adapter, &msg, 1) != 1) {
+ dev_err(&client->dev, "i2c transfer failed\n");
+ return -EIO;
+ }
+@@ -75,42 +101,72 @@ static int ili210x_read_reg(struct i2c_c
+ return 0;
+ }
+
+-static void ili210x_report_events(struct input_dev *input,
+- const struct touchdata *touchdata)
++static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
++ unsigned int finger,
++ unsigned int *x, unsigned int *y)
+ {
+- int i;
+- bool touch;
+- unsigned int x, y;
+- const struct finger *finger;
++ if (finger >= ILI210X_TOUCHES)
++ return false;
+
+- for (i = 0; i < MAX_TOUCHES; i++) {
+- input_mt_slot(input, i);
++ if (touchdata[0] & BIT(finger))
++ return false;
+
+- finger = &touchdata->finger[i];
++ *x = get_unaligned_be16(touchdata + 1 + (finger * 4) + 0);
++ *y = get_unaligned_be16(touchdata + 1 + (finger * 4) + 2);
+
+- touch = touchdata->status & (1 << i);
+- input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+- if (touch) {
+- x = finger->x_low | (finger->x_high << 8);
+- y = finger->y_low | (finger->y_high << 8);
++ return true;
++}
++
++static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
++ unsigned int finger,
++ unsigned int *x, unsigned int *y)
++{
++ if (finger >= ILI251X_TOUCHES)
++ return false;
++
++ *x = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0);
++ if (!(*x & BIT(15))) /* Touch indication */
++ return false;
++
++ *x &= 0x3fff;
++ *y = get_unaligned_be16(touchdata + 1 + (finger * 5) + 2);
++
++ return true;
++}
++
++static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
++{
++ struct input_dev *input = priv->input;
++ int i;
++ bool contact = false, touch = false;
++ unsigned int x = 0, y = 0;
+
+- input_report_abs(input, ABS_MT_POSITION_X, x);
+- input_report_abs(input, ABS_MT_POSITION_Y, y);
++ for (i = 0; i < priv->max_touches; i++) {
++ if (priv->model == MODEL_ILI210X) {
++ touch = ili210x_touchdata_to_coords(priv, touchdata,
++ i, &x, &y);
++ } else if (priv->model == MODEL_ILI251X) {
++ touch = ili251x_touchdata_to_coords(priv, touchdata,
++ i, &x, &y);
++ if (touch)
++ contact = true;
+ }
++
++ input_mt_slot(input, i);
++ input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
++ if (!touch)
++ continue;
++ touchscreen_report_pos(input, &priv->prop, x, y,
++ true);
+ }
+
+ input_mt_report_pointer_emulation(input, false);
+ input_sync(input);
+-}
+
+-static bool get_pendown_state(const struct ili210x *priv)
+-{
+- bool state = false;
+-
+- if (priv->get_pendown_state)
+- state = priv->get_pendown_state();
++ if (priv->model == MODEL_ILI210X)
++ contact = touchdata[0] & 0xf3;
+
+- return state;
++ return contact;
+ }
+
+ static void ili210x_work(struct work_struct *work)
+@@ -118,20 +174,29 @@ static void ili210x_work(struct work_str
+ struct ili210x *priv = container_of(work, struct ili210x,
+ dwork.work);
+ struct i2c_client *client = priv->client;
+- struct touchdata touchdata;
+- int error;
++ u8 touchdata[64] = { 0 };
++ bool touch;
++ int error = -EINVAL;
++
++ if (priv->model == MODEL_ILI210X) {
++ error = ili210x_read_reg(client, REG_TOUCHDATA,
++ touchdata, sizeof(touchdata));
++ } else if (priv->model == MODEL_ILI251X) {
++ error = ili210x_read_reg(client, REG_TOUCHDATA,
++ touchdata, 31);
++ if (!error && touchdata[0] == 2)
++ error = ili210x_read(client, &touchdata[31], 20);
++ }
+
+- error = ili210x_read_reg(client, REG_TOUCHDATA,
+- &touchdata, sizeof(touchdata));
+ if (error) {
+ dev_err(&client->dev,
+ "Unable to get touchdata, err = %d\n", error);
+ return;
+ }
+
+- ili210x_report_events(priv->input, &touchdata);
++ touch = ili210x_report_events(priv, touchdata);
+
+- if ((touchdata.status & 0xf3) || get_pendown_state(priv))
++ if (touch)
+ schedule_delayed_work(&priv->dwork,
+ msecs_to_jiffies(priv->poll_period));
+ }
+@@ -180,30 +245,76 @@ static const struct attribute_group ili2
+ .attrs = ili210x_attributes,
+ };
+
++static void ili210x_power_down(void *data)
++{
++ struct gpio_desc *reset_gpio = data;
++
++ gpiod_set_value_cansleep(reset_gpio, 1);
++}
++
++static void ili210x_cancel_work(void *data)
++{
++ struct ili210x *priv = data;
++
++ cancel_delayed_work_sync(&priv->dwork);
++}
++
+ static int ili210x_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+ {
+ struct device *dev = &client->dev;
+- const struct ili210x_platform_data *pdata = dev_get_platdata(dev);
+ struct ili210x *priv;
++ struct gpio_desc *reset_gpio;
+ struct input_dev *input;
+- struct panel_info panel;
+ struct firmware_version firmware;
+- int xmax, ymax;
++ enum ili2xxx_model model;
+ int error;
+
+- dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
++ model = (enum ili2xxx_model)id->driver_data;
+
+- if (!pdata) {
+- dev_err(dev, "No platform data!\n");
+- return -EINVAL;
+- }
++ dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
+
+ if (client->irq <= 0) {
+ dev_err(dev, "No IRQ!\n");
+ return -EINVAL;
+ }
+
++ reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
++ if (IS_ERR(reset_gpio))
++ return PTR_ERR(reset_gpio);
++
++ if (reset_gpio) {
++ error = devm_add_action_or_reset(dev, ili210x_power_down,
++ reset_gpio);
++ if (error)
++ return error;
++
++ usleep_range(50, 100);
++ gpiod_set_value_cansleep(reset_gpio, 0);
++ msleep(100);
++ }
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ input = devm_input_allocate_device(dev);
++ if (!input)
++ return -ENOMEM;
++
++ priv->client = client;
++ priv->input = input;
++ priv->poll_period = DEFAULT_POLL_PERIOD;
++ INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
++ priv->reset_gpio = reset_gpio;
++ priv->model = model;
++ if (model == MODEL_ILI210X)
++ priv->max_touches = ILI210X_TOUCHES;
++ if (model == MODEL_ILI251X)
++ priv->max_touches = ILI251X_TOUCHES;
++
++ i2c_set_clientdata(client, priv);
++
+ /* Get firmware version */
+ error = ili210x_read_reg(client, REG_FIRMWARE_VERSION,
+ &firmware, sizeof(firmware));
+@@ -213,70 +324,40 @@ static int ili210x_i2c_probe(struct i2c_
+ return error;
+ }
+
+- /* get panel info */
+- error = ili210x_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel));
+- if (error) {
+- dev_err(dev, "Failed to get panel information, err: %d\n",
+- error);
+- return error;
+- }
+-
+- xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8);
+- ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8);
+-
+- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+- input = input_allocate_device();
+- if (!priv || !input) {
+- error = -ENOMEM;
+- goto err_free_mem;
+- }
+-
+- priv->client = client;
+- priv->input = input;
+- priv->get_pendown_state = pdata->get_pendown_state;
+- priv->poll_period = pdata->poll_period ? : DEFAULT_POLL_PERIOD;
+- INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
+-
+ /* Setup input device */
+ input->name = "ILI210x Touchscreen";
+ input->id.bustype = BUS_I2C;
+ input->dev.parent = dev;
+
+- __set_bit(EV_SYN, input->evbit);
+- __set_bit(EV_KEY, input->evbit);
+- __set_bit(EV_ABS, input->evbit);
+- __set_bit(BTN_TOUCH, input->keybit);
+-
+- /* Single touch */
+- input_set_abs_params(input, ABS_X, 0, xmax, 0, 0);
+- input_set_abs_params(input, ABS_Y, 0, ymax, 0, 0);
+-
+ /* Multi touch */
+- input_mt_init_slots(input, MAX_TOUCHES, 0);
+- input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0);
+- input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0);
++ input_set_abs_params(input, ABS_MT_POSITION_X, 0, 0xffff, 0, 0);
++ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0);
++ touchscreen_parse_properties(input, true, &priv->prop);
++ input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT);
+
+- i2c_set_clientdata(client, priv);
++ error = devm_add_action(dev, ili210x_cancel_work, priv);
++ if (error)
++ return error;
+
+- error = request_irq(client->irq, ili210x_irq, pdata->irq_flags,
+- client->name, priv);
++ error = devm_request_irq(dev, client->irq, ili210x_irq, 0,
++ client->name, priv);
+ if (error) {
+ dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
+ error);
+- goto err_free_mem;
++ return error;
+ }
+
+- error = sysfs_create_group(&dev->kobj, &ili210x_attr_group);
++ error = devm_device_add_group(dev, &ili210x_attr_group);
+ if (error) {
+ dev_err(dev, "Unable to create sysfs attributes, err: %d\n",
+ error);
+- goto err_free_irq;
++ return error;
+ }
+
+ error = input_register_device(priv->input);
+ if (error) {
+ dev_err(dev, "Cannot register input device, err: %d\n", error);
+- goto err_remove_sysfs;
++ return error;
+ }
+
+ device_init_wakeup(dev, 1);
+@@ -286,28 +367,6 @@ static int ili210x_i2c_probe(struct i2c_
+ client->irq, firmware.id, firmware.major, firmware.minor);
+
+ return 0;
+-
+-err_remove_sysfs:
+- sysfs_remove_group(&dev->kobj, &ili210x_attr_group);
+-err_free_irq:
+- free_irq(client->irq, priv);
+-err_free_mem:
+- input_free_device(input);
+- kfree(priv);
+- return error;
+-}
+-
+-static int ili210x_i2c_remove(struct i2c_client *client)
+-{
+- struct ili210x *priv = i2c_get_clientdata(client);
+-
+- sysfs_remove_group(&client->dev.kobj, &ili210x_attr_group);
+- free_irq(priv->client->irq, priv);
+- cancel_delayed_work_sync(&priv->dwork);
+- input_unregister_device(priv->input);
+- kfree(priv);
+-
+- return 0;
+ }
+
+ static int __maybe_unused ili210x_i2c_suspend(struct device *dev)
+@@ -334,19 +393,27 @@ static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm,
+ ili210x_i2c_suspend, ili210x_i2c_resume);
+
+ static const struct i2c_device_id ili210x_i2c_id[] = {
+- { "ili210x", 0 },
++ { "ili210x", MODEL_ILI210X },
++ { "ili251x", MODEL_ILI251X },
+ { }
+ };
+ MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
+
++static const struct of_device_id ili210x_dt_ids[] = {
++ { .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X },
++ { .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X },
++ { },
++};
++MODULE_DEVICE_TABLE(of, ili210x_dt_ids);
++
+ static struct i2c_driver ili210x_ts_driver = {
+ .driver = {
+ .name = "ili210x_i2c",
+ .pm = &ili210x_i2c_pm,
++ .of_match_table = ili210x_dt_ids,
+ },
+ .id_table = ili210x_i2c_id,
+ .probe = ili210x_i2c_probe,
+- .remove = ili210x_i2c_remove,
+ };
+
+ module_i2c_driver(ili210x_ts_driver);
--- /dev/null
+From 5157a5c0fa2f7489e3ebf20dcbd9a7078ced6afd Mon Sep 17 00:00:00 2001
+From: Samuel Hsu <hsu@distec.de>
+Date: Mon, 8 Apr 2019 16:49:51 +0200
+Subject: [PATCH 421/725] Input: ili210x - add DT binding document
+
+commit 41a852e002e65ab7a1e6841b485d72d022e95df2 upstream
+
+Add DT binding document for the Ilitek ILI210x and ILI251x
+touchscreen controllers.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+---
+ .../bindings/input/ilitek,ili2xxx.txt | 26 +++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt
+@@ -0,0 +1,26 @@
++Ilitek ILI210x/ILI251x touchscreen controller
++
++Required properties:
++- compatible:
++ ilitek,ili210x for ILI210x
++ ilitek,ili251x for ILI251x
++
++- reg: The I2C address of the device
++
++- interrupts: The sink for the touchscreen's IRQ output
++ See ../interrupt-controller/interrupts.txt
++
++Optional properties for main touchpad device:
++
++- reset-gpios: GPIO specifier for the touchscreen's reset pin (active low)
++
++Example:
++
++ touchscreen@41 {
++ compatible = "ilitek,ili251x";
++ reg = <0x41>;
++ interrupt-parent = <&gpio4>;
++ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
++ reset-gpios = <&gpio5 21 GPIO_ACTIVE_LOW>;
++ };
++
+++ /dev/null
-From f1e74b2152a21e848075ea40ba8e8665f8313739 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Sun, 17 Mar 2019 16:48:36 -0700
-Subject: [PATCH 421/703] dtoverlays: Add Support for the UDRC/DRAWS
-
-Adds a new overlay to support the Northwest Digital Radio
-DRAWS and UDRC HATs. See http://nwdigitalradio.com.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
----
- arch/arm/boot/dts/overlays/Makefile | 2 +
- arch/arm/boot/dts/overlays/README | 59 ++++++
- arch/arm/boot/dts/overlays/draws-overlay.dts | 200 +++++++++++++++++++
- arch/arm/boot/dts/overlays/udrc-overlay.dts | 128 ++++++++++++
- 4 files changed, 389 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/draws-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/udrc-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -29,6 +29,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- dionaudio-loco-v2.dtbo \
- dpi18.dtbo \
- dpi24.dtbo \
-+ draws.dtbo \
- dwc-otg.dtbo \
- dwc2.dtbo \
- enc28j60.dtbo \
-@@ -146,6 +147,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- tpm-slb9670.dtbo \
- uart0.dtbo \
- uart1.dtbo \
-+ udrc.dtbo \
- upstream.dtbo \
- upstream-aux-interrupt.dtbo \
- vc4-fkms-v3d.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -531,6 +531,59 @@ Load: dtoverlay=dpi24
- Params: <None>
-
-
-+Name: draws
-+Info: Configures the NW Digital Radio DRAWS Hat
-+
-+ The board includes an ADC to measure various board values and also
-+ provides two analog user inputs on the expansion header. The ADC
-+ can be configured for various sample rates and gain values to adjust
-+ the input range. Tables describing the two parameters follow.
-+
-+ ADC Gain Values:
-+ 0 = +/- 6.144V
-+ 1 = +/- 4.096V
-+ 2 = +/- 2.048V
-+ 3 = +/- 1.024V
-+ 4 = +/- 0.512V
-+ 5 = +/- 0.256V
-+ 6 = +/- 0.256V
-+ 7 = +/- 0.256V
-+
-+ ADC Datarate Values:
-+ 0 = 128sps
-+ 1 = 250sps
-+ 2 = 490sps
-+ 3 = 920sps
-+ 4 = 1600sps (default)
-+ 5 = 2400sps
-+ 6 = 3300sps
-+ 7 = 3300sps
-+Load: dtoverlay=draws,<param>=<val>
-+Params: draws_adc_ch4_gain Sets the full scale resolution of the ADCs
-+ input voltage sensor (default 1)
-+
-+ draws_adc_ch4_datarate Sets the datarate of the ADCs input voltage
-+ sensor
-+
-+ draws_adc_ch5_gain Sets the full scale resolution of the ADCs
-+ 5V rail voltage sensor (default 1)
-+
-+ draws_adc_ch5_datarate Sets the datarate of the ADCs 4V rail voltage
-+ sensor
-+
-+ draws_adc_ch6_gain Sets the full scale resolution of the ADCs
-+ AIN2 input (default 2)
-+
-+ draws_adc_ch6_datarate Sets the datarate of the ADCs AIN2 input
-+
-+ draws_adc_ch7_gain Sets the full scale resolution of the ADCs
-+ AIN3 input (default 2)
-+
-+ draws_adc_ch7_datarate Sets the datarate of the ADCs AIN3 input
-+
-+ alsaname Name of the ALSA audio device (default "draws")
-+
-+
- Name: dwc-otg
- Info: Selects the dwc_otg USB controller driver which has fiq support. This
- is the default on all except the Pi Zero which defaults to dwc2.
-@@ -2117,6 +2170,12 @@ Params: txd1_pin GPIO pin
- rxd1_pin GPIO pin for RXD1 (15, 33 or 41 - default 15)
-
-
-+Name: udrc
-+Info: Configures the NW Digital Radio UDRC Hat
-+Load: dtoverlay=udrc,<param>=<val>
-+Params: alsaname Name of the ALSA audio device (default "udrc")
-+
-+
- Name: upstream
- Info: Allow usage of downstream .dtb with upstream kernel. Comprises
- vc4-kms-v3d, dwc2 and upstream-aux-interrupt overlays.
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/draws-overlay.dts
-@@ -0,0 +1,200 @@
-+#include <dt-bindings/clock/bcm2835.h>
-+/*
-+ * Device tree overlay for the DRAWS Hardware
-+ */
-+
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+ fragment@0 {
-+ target = <&i2s>;
-+ __overlay__ {
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@1 {
-+ target-path = "/";
-+ __overlay__ {
-+ regulators {
-+ compatible = "simple-bus";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ udrc0_ldoin: udrc0_ldoin {
-+ compatible = "regulator-fixed";
-+ regulator-name = "ldoin";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ regulator-always-on;
-+ };
-+ };
-+
-+ pps: pps {
-+ compatible = "pps-gpio";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pps_pins>;
-+ gpios = <&gpio 7 0>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ fragment@2 {
-+ target = <&i2c_arm>;
-+ __overlay__ {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "okay";
-+
-+ tlv320aic32x4: tlv320aic32x4@18 {
-+ compatible = "ti,tlv320aic32x4";
-+ reg = <0x18>;
-+ #sound-dai-cells = <0>;
-+ status = "okay";
-+
-+ clocks = <&clocks BCM2835_CLOCK_GP0>;
-+ clock-names = "mclk";
-+ assigned-clocks = <&clocks BCM2835_CLOCK_GP0>;
-+ assigned-clock-rates = <25000000>;
-+
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&gpclk0_pin &aic3204_reset>;
-+
-+ reset-gpios = <&gpio 13 0>;
-+
-+ iov-supply = <&udrc0_ldoin>;
-+ ldoin-supply = <&udrc0_ldoin>;
-+ };
-+
-+ sc16is752: sc16is752@50 {
-+ compatible = "nxp,sc16is752";
-+ reg = <0x50>;
-+ clocks = <&sc16is752_clk>;
-+ interrupt-parent = <&gpio>;
-+ interrupts = <17 2>; /* IRQ_TYPE_EDGE_FALLING */
-+
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&sc16is752_irq>;
-+
-+ sc16is752_clk: sc16is752_clk {
-+ compatible = "fixed-clock";
-+ #clock-cells = <0>;
-+ clock-frequency = <1843200>;
-+ };
-+ };
-+
-+ tla2024: tla2024@48 {
-+ compatible = "ti,ads1015";
-+ reg = <0x48>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ adc_ch4: channel@4 {
-+ reg = <4>;
-+ ti,gain = <1>;
-+ ti,datarate = <4>;
-+ };
-+
-+ adc_ch5: channel@5 {
-+ reg = <5>;
-+ ti,gain = <1>;
-+ ti,datarate = <4>;
-+ };
-+
-+ adc_ch6: channel@6 {
-+ reg = <6>;
-+ ti,gain = <2>;
-+ ti,datarate = <4>;
-+ };
-+
-+ adc_ch7: channel@7 {
-+ reg = <7>;
-+ ti,gain = <2>;
-+ ti,datarate = <4>;
-+ };
-+ };
-+ };
-+ };
-+
-+ fragment@3 {
-+ target = <&sound>;
-+ snd: __overlay__ {
-+ compatible = "simple-audio-card";
-+ i2s-controller = <&i2s>;
-+ status = "okay";
-+
-+ simple-audio-card,name = "draws";
-+ simple-audio-card,format = "i2s";
-+
-+ simple-audio-card,bitclock-master = <&dailink0_master>;
-+ simple-audio-card,frame-master = <&dailink0_master>;
-+
-+ simple-audio-card,widgets =
-+ "Line", "Line In",
-+ "Line", "Line Out";
-+
-+ simple-audio-card,routing =
-+ "IN1_R", "Line In",
-+ "IN1_L", "Line In",
-+ "CM_L", "Line In",
-+ "CM_R", "Line In",
-+ "Line Out", "LOR",
-+ "Line Out", "LOL";
-+
-+ dailink0_master: simple-audio-card,cpu {
-+ sound-dai = <&i2s>;
-+ };
-+
-+ simple-audio-card,codec {
-+ sound-dai = <&tlv320aic32x4>;
-+ };
-+ };
-+ };
-+
-+ fragment@4 {
-+ target = <&gpio>;
-+ __overlay__ {
-+ gpclk0_pin: gpclk0_pin {
-+ brcm,pins = <4>;
-+ brcm,function = <4>;
-+ };
-+
-+ aic3204_reset: aic3204_reset {
-+ brcm,pins = <13>;
-+ brcm,function = <1>;
-+ brcm,pull = <1>;
-+ };
-+
-+ aic3204_gpio: aic3204_gpio {
-+ brcm,pins = <26>;
-+ };
-+
-+ sc16is752_irq: sc16is752_irq {
-+ brcm,pins = <17>;
-+ brcm,function = <0>;
-+ brcm,pull = <2>;
-+ };
-+
-+ pps_pins: pps_pins {
-+ brcm,pins = <7>;
-+ brcm,function = <0>;
-+ brcm,pull = <0>;
-+ };
-+ };
-+ };
-+
-+ __overrides__ {
-+ draws_adc_ch4_gain = <&adc_ch4>,"ti,gain:0";
-+ draws_adc_ch4_datarate = <&adc_ch4>,"ti,datarate:0";
-+ draws_adc_ch5_gain = <&adc_ch5>,"ti,gain:0";
-+ draws_adc_ch5_datarate = <&adc_ch5>,"ti,datarate:0";
-+ draws_adc_ch6_gain = <&adc_ch6>,"ti,gain:0";
-+ draws_adc_ch6_datarate = <&adc_ch6>,"ti,datarate:0";
-+ draws_adc_ch7_gain = <&adc_ch7>,"ti,gain:0";
-+ draws_adc_ch7_datarate = <&adc_ch7>,"ti,datarate:0";
-+ alsaname = <&snd>, "simple-audio-card,name";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/udrc-overlay.dts
-@@ -0,0 +1,128 @@
-+#include <dt-bindings/clock/bcm2835.h>
-+/*
-+ * Device tree overlay for the Universal Digital Radio Controller
-+ */
-+
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+ fragment@0 {
-+ target = <&i2s>;
-+ __overlay__ {
-+ clocks = <&clocks BCM2835_CLOCK_PCM>;
-+ clock-names = "pcm";
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@1 {
-+ target-path = "/";
-+ __overlay__ {
-+ regulators {
-+ compatible = "simple-bus";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ udrc0_ldoin: udrc0_ldoin {
-+ compatible = "regulator-fixed";
-+ regulator-name = "ldoin";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ regulator-always-on;
-+ };
-+ };
-+ };
-+ };
-+
-+ fragment@2 {
-+ target = <&i2c1>;
-+ __overlay__ {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "okay";
-+ clocks = <&clocks BCM2835_CLOCK_VPU>;
-+ clock-frequency = <400000>;
-+
-+ tlv320aic32x4: tlv320aic32x4@18 {
-+ compatible = "ti,tlv320aic32x4";
-+ #sound-dai-cells = <0>;
-+ reg = <0x18>;
-+ status = "okay";
-+
-+ clocks = <&clocks BCM2835_CLOCK_GP0>;
-+ clock-names = "mclk";
-+ assigned-clocks = <&clocks BCM2835_CLOCK_GP0>;
-+ assigned-clock-rates = <25000000>;
-+
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&gpclk0_pin &aic3204_reset>;
-+
-+ reset-gpios = <&gpio 13 0>;
-+
-+ iov-supply = <&udrc0_ldoin>;
-+ ldoin-supply = <&udrc0_ldoin>;
-+ };
-+ };
-+ };
-+
-+ fragment@3 {
-+ target = <&sound>;
-+ snd: __overlay__ {
-+ compatible = "simple-audio-card";
-+ i2s-controller = <&i2s>;
-+ status = "okay";
-+
-+ simple-audio-card,name = "udrc";
-+ simple-audio-card,format = "i2s";
-+
-+ simple-audio-card,bitclock-master = <&dailink0_master>;
-+ simple-audio-card,frame-master = <&dailink0_master>;
-+
-+ simple-audio-card,widgets =
-+ "Line", "Line In",
-+ "Line", "Line Out";
-+
-+ simple-audio-card,routing =
-+ "IN1_R", "Line In",
-+ "IN1_L", "Line In",
-+ "CM_L", "Line In",
-+ "CM_R", "Line In",
-+ "Line Out", "LOR",
-+ "Line Out", "LOL";
-+
-+ dailink0_master: simple-audio-card,cpu {
-+ sound-dai = <&i2s>;
-+ };
-+
-+ simple-audio-card,codec {
-+ sound-dai = <&tlv320aic32x4>;
-+ };
-+ };
-+ };
-+
-+ fragment@4 {
-+ target = <&gpio>;
-+ __overlay__ {
-+ gpclk0_pin: gpclk0_pin {
-+ brcm,pins = <4>;
-+ brcm,function = <4>;
-+ };
-+
-+ aic3204_reset: aic3204_reset {
-+ brcm,pins = <13>;
-+ brcm,function = <1>;
-+ brcm,pull = <1>;
-+ };
-+
-+ aic3204_gpio: aic3204_gpio {
-+ brcm,pins = <26>;
-+ };
-+ };
-+ };
-+
-+ __overrides__ {
-+ alsaname = <&snd>, "simple-audio-card,name";
-+ };
-+};
--- /dev/null
+From f3d6c9f20cf6c0f0f970b4ded850b23c0554e779 Mon Sep 17 00:00:00 2001
+From: Samuel Hsu <hsu@distec.de>
+Date: Mon, 8 Apr 2019 16:54:34 +0200
+Subject: [PATCH 422/725] configs: Add TOUCHSCREEN_ILI210X=m
+
+Signed-off-by: Samuel Hsu <hsu@distec.de>
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ 3 files changed, 3 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -565,6 +565,7 @@ CONFIG_TOUCHSCREEN_ADS7846=m
+ CONFIG_TOUCHSCREEN_EGALAX=m
+ CONFIG_TOUCHSCREEN_EXC3000=m
+ CONFIG_TOUCHSCREEN_GOODIX=m
++CONFIG_TOUCHSCREEN_ILI210X=m
+ CONFIG_TOUCHSCREEN_EDT_FT5X06=m
+ CONFIG_TOUCHSCREEN_RPI_FT5406=m
+ CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -559,6 +559,7 @@ CONFIG_TOUCHSCREEN_ADS7846=m
+ CONFIG_TOUCHSCREEN_EGALAX=m
+ CONFIG_TOUCHSCREEN_EXC3000=m
+ CONFIG_TOUCHSCREEN_GOODIX=m
++CONFIG_TOUCHSCREEN_ILI210X=m
+ CONFIG_TOUCHSCREEN_EDT_FT5X06=m
+ CONFIG_TOUCHSCREEN_RPI_FT5406=m
+ CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -547,6 +547,7 @@ CONFIG_INPUT_TOUCHSCREEN=y
+ CONFIG_TOUCHSCREEN_ADS7846=m
+ CONFIG_TOUCHSCREEN_EGALAX=m
+ CONFIG_TOUCHSCREEN_EKTF2127=m
++CONFIG_TOUCHSCREEN_ILI210X=m
+ CONFIG_TOUCHSCREEN_RPI_FT5406=m
+ CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+ CONFIG_TOUCHSCREEN_STMPE=m
+++ /dev/null
-From e30b8c6f64fe1cd5ea4e522186847be170efe88b Mon Sep 17 00:00:00 2001
-From: P33M <p33m@github.com>
-Date: Mon, 8 Apr 2019 12:45:23 +0100
-Subject: [PATCH 422/703] dwc_otg: only do_split when we actually need to do a
- split
-
-The previous test would fail if the root port was in fullspeed mode
-and there was a hub between the FS device and the root port. While
-the transfer worked, the schedule mangling performed for high-speed
-split transfers would break leading to an 8ms polling interval.
----
- drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 9 ++++-----
- 1 file changed, 4 insertions(+), 5 deletions(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
-@@ -167,8 +167,10 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
- char *speed, *type;
- int dev_speed;
- uint32_t hub_addr, hub_port;
-+ hprt0_data_t hprt;
-
- dwc_memset(qh, 0, sizeof(dwc_otg_qh_t));
-+ hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
-
- /* Initialize QH */
- qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
-@@ -191,9 +193,8 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
-
- qh->nak_frame = 0xffff;
-
-- if (((dev_speed == USB_SPEED_LOW) ||
-- (dev_speed == USB_SPEED_FULL)) &&
-- (hub_addr != 0 && hub_addr != 1)) {
-+ if (hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED &&
-+ dev_speed != USB_SPEED_HIGH) {
- DWC_DEBUGPL(DBG_HCD,
- "QH init: EP %d: TT found at hub addr %d, for port %d\n",
- dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
-@@ -204,7 +205,6 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
-
- if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
- /* Compute scheduling parameters once and save them. */
-- hprt0_data_t hprt;
-
- /** @todo Account for split transfers in the bus time. */
- int bytecount =
-@@ -219,7 +219,6 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
- SCHEDULE_SLOP);
- qh->interval = urb->interval;
-
-- hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
- if (hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) {
- if (dev_speed == USB_SPEED_LOW ||
- dev_speed == USB_SPEED_FULL) {
--- /dev/null
+From 3c0bead8692a211c548d046790dc4129128fbff1 Mon Sep 17 00:00:00 2001
+From: Samuel Hsu <hsu@distec.de>
+Date: Mon, 8 Apr 2019 17:06:44 +0200
+Subject: [PATCH 423/725] BCM2708: Add core Device Tree support, ilitek251x
+
+Signed-off-by: Samuel Hsu <hsu@distec.de>
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 11 +++++
+ .../boot/dts/overlays/ilitek251x-overlay.dts | 45 +++++++++++++++++++
+ 3 files changed, 57 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -67,6 +67,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ i2c0-bcm2708.dtbo \
+ i2c1-bcm2708.dtbo \
+ i2s-gpio28-31.dtbo \
++ ilitek251x.dtbo \
+ iqaudio-dac.dtbo \
+ iqaudio-dacplus.dtbo \
+ iqaudio-digi-wm8804-audio.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1146,6 +1146,17 @@ Load: dtoverlay=i2s-gpio28-31
+ Params: <None>
+
+
++Name: ilitek251x
++Info: Enables I2C connected Ilitek 251x multiple touch controller using
++ GPIO 4 (pin 7 on GPIO header) for interrupt.
++Load: dtoverlay=ilitek251x,<param>=<val>
++Params: interrupt GPIO used for interrupt (default 4)
++ sizex Touchscreen size x, horizontal resolution of
++ touchscreen (in pixels)
++ sizey Touchscreen size y, vertical resolution of
++ touchscreen (in pixels)
++
++
+ Name: iqaudio-dac
+ Info: Configures the IQaudio DAC audio card
+ Load: dtoverlay=iqaudio-dac,<param>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
+@@ -0,0 +1,45 @@
++// Device tree overlay for I2C connected Ilitek multiple touch controller
++/dts-v1/;
++/plugin/;
++
++ / {
++ compatible = "brcm,bcm2708";
++
++ fragment@0 {
++ target = <&gpio>;
++ __overlay__ {
++ ili251x_pins: ili251x_pins {
++ brcm,pins = <4>; // interrupt
++ brcm,function = <0>; // in
++ brcm,pull = <2>; // pull-up //
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&i2c1>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ ili251x: ili251x@41 {
++ compatible = "ilitek,ili251x";
++ reg = <0x41>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&ili251x_pins>;
++ interrupt-parent = <&gpio>;
++ interrupts = <4 8>; // high-to-low edge triggered
++ touchscreen-size-x = <16384>;
++ touchscreen-size-y = <9600>;
++ };
++ };
++ };
++
++ __overrides__ {
++ interrupt = <&ili251x_pins>,"brcm,pins:0",
++ <&ili251x>,"interrupts:0";
++ sizex = <&ili251x>,"touchscreen-size-x:0";
++ sizey = <&ili251x>,"touchscreen-size-y:0";
++ };
++};
+++ /dev/null
-From 7424847b3053bb995d52b13b6b7a387d682cde31 Mon Sep 17 00:00:00 2001
-From: Samuel Hsu <hsu@distec.de>
-Date: Mon, 8 Apr 2019 16:42:17 +0200
-Subject: [PATCH 423/703] Input: ili210x - fetch touchscreen geometry from DT
-
-commit f67cc3e927d8414ad3872e046764534ea1f5db0d upstream
-
-Fetching the geometry from the ILI251x registers seems unreliable and
-sometimes returns all zeroes. Add support for fetching the geometry and
-axis inversion from DT instead.
-
-Signed-off-by: Marek Vasut <marex@denx.de>
-Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
----
- drivers/input/touchscreen/ili210x.c | 321 +++++++++++++++++-----------
- 1 file changed, 194 insertions(+), 127 deletions(-)
-
---- a/drivers/input/touchscreen/ili210x.c
-+++ b/drivers/input/touchscreen/ili210x.c
-@@ -4,11 +4,15 @@
- #include <linux/slab.h>
- #include <linux/input.h>
- #include <linux/input/mt.h>
-+#include <linux/input/touchscreen.h>
- #include <linux/delay.h>
- #include <linux/workqueue.h>
--#include <linux/input/ili210x.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/of_device.h>
-+#include <asm/unaligned.h>
-
--#define MAX_TOUCHES 2
-+#define ILI210X_TOUCHES 2
-+#define ILI251X_TOUCHES 10
- #define DEFAULT_POLL_PERIOD 20
-
- /* Touchscreen commands */
-@@ -17,41 +21,32 @@
- #define REG_FIRMWARE_VERSION 0x40
- #define REG_CALIBRATE 0xcc
-
--struct finger {
-- u8 x_low;
-- u8 x_high;
-- u8 y_low;
-- u8 y_high;
--} __packed;
--
--struct touchdata {
-- u8 status;
-- struct finger finger[MAX_TOUCHES];
--} __packed;
--
--struct panel_info {
-- struct finger finger_max;
-- u8 xchannel_num;
-- u8 ychannel_num;
--} __packed;
--
- struct firmware_version {
- u8 id;
- u8 major;
- u8 minor;
- } __packed;
-
-+enum ili2xxx_model {
-+ MODEL_ILI210X,
-+ MODEL_ILI251X,
-+};
-+
- struct ili210x {
- struct i2c_client *client;
- struct input_dev *input;
-- bool (*get_pendown_state)(void);
- unsigned int poll_period;
- struct delayed_work dwork;
-+ struct gpio_desc *reset_gpio;
-+ struct touchscreen_properties prop;
-+ enum ili2xxx_model model;
-+ unsigned int max_touches;
- };
-
- static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf,
- size_t len)
- {
-+ struct ili210x *priv = i2c_get_clientdata(client);
- struct i2c_msg msg[2] = {
- {
- .addr = client->addr,
-@@ -67,7 +62,38 @@ static int ili210x_read_reg(struct i2c_c
- }
- };
-
-- if (i2c_transfer(client->adapter, msg, 2) != 2) {
-+ if (priv->model == MODEL_ILI251X) {
-+ if (i2c_transfer(client->adapter, msg, 1) != 1) {
-+ dev_err(&client->dev, "i2c transfer failed\n");
-+ return -EIO;
-+ }
-+
-+ usleep_range(5000, 5500);
-+
-+ if (i2c_transfer(client->adapter, msg + 1, 1) != 1) {
-+ dev_err(&client->dev, "i2c transfer failed\n");
-+ return -EIO;
-+ }
-+ } else {
-+ if (i2c_transfer(client->adapter, msg, 2) != 2) {
-+ dev_err(&client->dev, "i2c transfer failed\n");
-+ return -EIO;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static int ili210x_read(struct i2c_client *client, void *buf, size_t len)
-+{
-+ struct i2c_msg msg = {
-+ .addr = client->addr,
-+ .flags = I2C_M_RD,
-+ .len = len,
-+ .buf = buf,
-+ };
-+
-+ if (i2c_transfer(client->adapter, &msg, 1) != 1) {
- dev_err(&client->dev, "i2c transfer failed\n");
- return -EIO;
- }
-@@ -75,42 +101,72 @@ static int ili210x_read_reg(struct i2c_c
- return 0;
- }
-
--static void ili210x_report_events(struct input_dev *input,
-- const struct touchdata *touchdata)
-+static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
-+ unsigned int finger,
-+ unsigned int *x, unsigned int *y)
- {
-- int i;
-- bool touch;
-- unsigned int x, y;
-- const struct finger *finger;
-+ if (finger >= ILI210X_TOUCHES)
-+ return false;
-
-- for (i = 0; i < MAX_TOUCHES; i++) {
-- input_mt_slot(input, i);
-+ if (touchdata[0] & BIT(finger))
-+ return false;
-
-- finger = &touchdata->finger[i];
-+ *x = get_unaligned_be16(touchdata + 1 + (finger * 4) + 0);
-+ *y = get_unaligned_be16(touchdata + 1 + (finger * 4) + 2);
-
-- touch = touchdata->status & (1 << i);
-- input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
-- if (touch) {
-- x = finger->x_low | (finger->x_high << 8);
-- y = finger->y_low | (finger->y_high << 8);
-+ return true;
-+}
-+
-+static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
-+ unsigned int finger,
-+ unsigned int *x, unsigned int *y)
-+{
-+ if (finger >= ILI251X_TOUCHES)
-+ return false;
-+
-+ *x = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0);
-+ if (!(*x & BIT(15))) /* Touch indication */
-+ return false;
-+
-+ *x &= 0x3fff;
-+ *y = get_unaligned_be16(touchdata + 1 + (finger * 5) + 2);
-+
-+ return true;
-+}
-+
-+static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
-+{
-+ struct input_dev *input = priv->input;
-+ int i;
-+ bool contact = false, touch = false;
-+ unsigned int x = 0, y = 0;
-
-- input_report_abs(input, ABS_MT_POSITION_X, x);
-- input_report_abs(input, ABS_MT_POSITION_Y, y);
-+ for (i = 0; i < priv->max_touches; i++) {
-+ if (priv->model == MODEL_ILI210X) {
-+ touch = ili210x_touchdata_to_coords(priv, touchdata,
-+ i, &x, &y);
-+ } else if (priv->model == MODEL_ILI251X) {
-+ touch = ili251x_touchdata_to_coords(priv, touchdata,
-+ i, &x, &y);
-+ if (touch)
-+ contact = true;
- }
-+
-+ input_mt_slot(input, i);
-+ input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
-+ if (!touch)
-+ continue;
-+ touchscreen_report_pos(input, &priv->prop, x, y,
-+ true);
- }
-
- input_mt_report_pointer_emulation(input, false);
- input_sync(input);
--}
-
--static bool get_pendown_state(const struct ili210x *priv)
--{
-- bool state = false;
--
-- if (priv->get_pendown_state)
-- state = priv->get_pendown_state();
-+ if (priv->model == MODEL_ILI210X)
-+ contact = touchdata[0] & 0xf3;
-
-- return state;
-+ return contact;
- }
-
- static void ili210x_work(struct work_struct *work)
-@@ -118,20 +174,29 @@ static void ili210x_work(struct work_str
- struct ili210x *priv = container_of(work, struct ili210x,
- dwork.work);
- struct i2c_client *client = priv->client;
-- struct touchdata touchdata;
-- int error;
-+ u8 touchdata[64] = { 0 };
-+ bool touch;
-+ int error = -EINVAL;
-+
-+ if (priv->model == MODEL_ILI210X) {
-+ error = ili210x_read_reg(client, REG_TOUCHDATA,
-+ touchdata, sizeof(touchdata));
-+ } else if (priv->model == MODEL_ILI251X) {
-+ error = ili210x_read_reg(client, REG_TOUCHDATA,
-+ touchdata, 31);
-+ if (!error && touchdata[0] == 2)
-+ error = ili210x_read(client, &touchdata[31], 20);
-+ }
-
-- error = ili210x_read_reg(client, REG_TOUCHDATA,
-- &touchdata, sizeof(touchdata));
- if (error) {
- dev_err(&client->dev,
- "Unable to get touchdata, err = %d\n", error);
- return;
- }
-
-- ili210x_report_events(priv->input, &touchdata);
-+ touch = ili210x_report_events(priv, touchdata);
-
-- if ((touchdata.status & 0xf3) || get_pendown_state(priv))
-+ if (touch)
- schedule_delayed_work(&priv->dwork,
- msecs_to_jiffies(priv->poll_period));
- }
-@@ -180,30 +245,76 @@ static const struct attribute_group ili2
- .attrs = ili210x_attributes,
- };
-
-+static void ili210x_power_down(void *data)
-+{
-+ struct gpio_desc *reset_gpio = data;
-+
-+ gpiod_set_value_cansleep(reset_gpio, 1);
-+}
-+
-+static void ili210x_cancel_work(void *data)
-+{
-+ struct ili210x *priv = data;
-+
-+ cancel_delayed_work_sync(&priv->dwork);
-+}
-+
- static int ili210x_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
- {
- struct device *dev = &client->dev;
-- const struct ili210x_platform_data *pdata = dev_get_platdata(dev);
- struct ili210x *priv;
-+ struct gpio_desc *reset_gpio;
- struct input_dev *input;
-- struct panel_info panel;
- struct firmware_version firmware;
-- int xmax, ymax;
-+ enum ili2xxx_model model;
- int error;
-
-- dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
-+ model = (enum ili2xxx_model)id->driver_data;
-
-- if (!pdata) {
-- dev_err(dev, "No platform data!\n");
-- return -EINVAL;
-- }
-+ dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
-
- if (client->irq <= 0) {
- dev_err(dev, "No IRQ!\n");
- return -EINVAL;
- }
-
-+ reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
-+ if (IS_ERR(reset_gpio))
-+ return PTR_ERR(reset_gpio);
-+
-+ if (reset_gpio) {
-+ error = devm_add_action_or_reset(dev, ili210x_power_down,
-+ reset_gpio);
-+ if (error)
-+ return error;
-+
-+ usleep_range(50, 100);
-+ gpiod_set_value_cansleep(reset_gpio, 0);
-+ msleep(100);
-+ }
-+
-+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+ if (!priv)
-+ return -ENOMEM;
-+
-+ input = devm_input_allocate_device(dev);
-+ if (!input)
-+ return -ENOMEM;
-+
-+ priv->client = client;
-+ priv->input = input;
-+ priv->poll_period = DEFAULT_POLL_PERIOD;
-+ INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
-+ priv->reset_gpio = reset_gpio;
-+ priv->model = model;
-+ if (model == MODEL_ILI210X)
-+ priv->max_touches = ILI210X_TOUCHES;
-+ if (model == MODEL_ILI251X)
-+ priv->max_touches = ILI251X_TOUCHES;
-+
-+ i2c_set_clientdata(client, priv);
-+
- /* Get firmware version */
- error = ili210x_read_reg(client, REG_FIRMWARE_VERSION,
- &firmware, sizeof(firmware));
-@@ -213,70 +324,40 @@ static int ili210x_i2c_probe(struct i2c_
- return error;
- }
-
-- /* get panel info */
-- error = ili210x_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel));
-- if (error) {
-- dev_err(dev, "Failed to get panel information, err: %d\n",
-- error);
-- return error;
-- }
--
-- xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8);
-- ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8);
--
-- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-- input = input_allocate_device();
-- if (!priv || !input) {
-- error = -ENOMEM;
-- goto err_free_mem;
-- }
--
-- priv->client = client;
-- priv->input = input;
-- priv->get_pendown_state = pdata->get_pendown_state;
-- priv->poll_period = pdata->poll_period ? : DEFAULT_POLL_PERIOD;
-- INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
--
- /* Setup input device */
- input->name = "ILI210x Touchscreen";
- input->id.bustype = BUS_I2C;
- input->dev.parent = dev;
-
-- __set_bit(EV_SYN, input->evbit);
-- __set_bit(EV_KEY, input->evbit);
-- __set_bit(EV_ABS, input->evbit);
-- __set_bit(BTN_TOUCH, input->keybit);
--
-- /* Single touch */
-- input_set_abs_params(input, ABS_X, 0, xmax, 0, 0);
-- input_set_abs_params(input, ABS_Y, 0, ymax, 0, 0);
--
- /* Multi touch */
-- input_mt_init_slots(input, MAX_TOUCHES, 0);
-- input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0);
-- input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0);
-+ input_set_abs_params(input, ABS_MT_POSITION_X, 0, 0xffff, 0, 0);
-+ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0);
-+ touchscreen_parse_properties(input, true, &priv->prop);
-+ input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT);
-
-- i2c_set_clientdata(client, priv);
-+ error = devm_add_action(dev, ili210x_cancel_work, priv);
-+ if (error)
-+ return error;
-
-- error = request_irq(client->irq, ili210x_irq, pdata->irq_flags,
-- client->name, priv);
-+ error = devm_request_irq(dev, client->irq, ili210x_irq, 0,
-+ client->name, priv);
- if (error) {
- dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
- error);
-- goto err_free_mem;
-+ return error;
- }
-
-- error = sysfs_create_group(&dev->kobj, &ili210x_attr_group);
-+ error = devm_device_add_group(dev, &ili210x_attr_group);
- if (error) {
- dev_err(dev, "Unable to create sysfs attributes, err: %d\n",
- error);
-- goto err_free_irq;
-+ return error;
- }
-
- error = input_register_device(priv->input);
- if (error) {
- dev_err(dev, "Cannot register input device, err: %d\n", error);
-- goto err_remove_sysfs;
-+ return error;
- }
-
- device_init_wakeup(dev, 1);
-@@ -286,28 +367,6 @@ static int ili210x_i2c_probe(struct i2c_
- client->irq, firmware.id, firmware.major, firmware.minor);
-
- return 0;
--
--err_remove_sysfs:
-- sysfs_remove_group(&dev->kobj, &ili210x_attr_group);
--err_free_irq:
-- free_irq(client->irq, priv);
--err_free_mem:
-- input_free_device(input);
-- kfree(priv);
-- return error;
--}
--
--static int ili210x_i2c_remove(struct i2c_client *client)
--{
-- struct ili210x *priv = i2c_get_clientdata(client);
--
-- sysfs_remove_group(&client->dev.kobj, &ili210x_attr_group);
-- free_irq(priv->client->irq, priv);
-- cancel_delayed_work_sync(&priv->dwork);
-- input_unregister_device(priv->input);
-- kfree(priv);
--
-- return 0;
- }
-
- static int __maybe_unused ili210x_i2c_suspend(struct device *dev)
-@@ -334,19 +393,27 @@ static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm,
- ili210x_i2c_suspend, ili210x_i2c_resume);
-
- static const struct i2c_device_id ili210x_i2c_id[] = {
-- { "ili210x", 0 },
-+ { "ili210x", MODEL_ILI210X },
-+ { "ili251x", MODEL_ILI251X },
- { }
- };
- MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
-
-+static const struct of_device_id ili210x_dt_ids[] = {
-+ { .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X },
-+ { .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X },
-+ { },
-+};
-+MODULE_DEVICE_TABLE(of, ili210x_dt_ids);
-+
- static struct i2c_driver ili210x_ts_driver = {
- .driver = {
- .name = "ili210x_i2c",
- .pm = &ili210x_i2c_pm,
-+ .of_match_table = ili210x_dt_ids,
- },
- .id_table = ili210x_i2c_id,
- .probe = ili210x_i2c_probe,
-- .remove = ili210x_i2c_remove,
- };
-
- module_i2c_driver(ili210x_ts_driver);
+++ /dev/null
-From 5cea7939c6062752322697e33f8a90e33fca461f Mon Sep 17 00:00:00 2001
-From: Samuel Hsu <hsu@distec.de>
-Date: Mon, 8 Apr 2019 16:49:51 +0200
-Subject: [PATCH 424/703] Input: ili210x - add DT binding document
-
-commit 41a852e002e65ab7a1e6841b485d72d022e95df2 upstream
-
-Add DT binding document for the Ilitek ILI210x and ILI251x
-touchscreen controllers.
-
-Signed-off-by: Marek Vasut <marex@denx.de>
-Reviewed-by: Rob Herring <robh@kernel.org>
-Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
----
- .../bindings/input/ilitek,ili2xxx.txt | 26 +++++++++++++++++++
- 1 file changed, 26 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt
-@@ -0,0 +1,26 @@
-+Ilitek ILI210x/ILI251x touchscreen controller
-+
-+Required properties:
-+- compatible:
-+ ilitek,ili210x for ILI210x
-+ ilitek,ili251x for ILI251x
-+
-+- reg: The I2C address of the device
-+
-+- interrupts: The sink for the touchscreen's IRQ output
-+ See ../interrupt-controller/interrupts.txt
-+
-+Optional properties for main touchpad device:
-+
-+- reset-gpios: GPIO specifier for the touchscreen's reset pin (active low)
-+
-+Example:
-+
-+ touchscreen@41 {
-+ compatible = "ilitek,ili251x";
-+ reg = <0x41>;
-+ interrupt-parent = <&gpio4>;
-+ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
-+ reset-gpios = <&gpio5 21 GPIO_ACTIVE_LOW>;
-+ };
-+
--- /dev/null
+From 9b55ce7579702f6a0bde5cd3e97b745f7b3f0239 Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Tue, 9 Apr 2019 16:40:48 +0100
+Subject: [PATCH 424/725] dwc_otg: fix locking around dequeueing and killing
+ URBs
+
+kill_urbs_in_qh_list() is practically only ever called with the fiq lock
+already held, so don't spinlock twice in the case where we need to cancel
+an isochronous transfer.
+
+Also fix up a case where the global interrupt register could be read with
+the fiq lock not held.
+
+Fixes the deadlock seen in https://github.com/raspberrypi/linux/issues/2907
+---
+ drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 9 +++++++--
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 4 ----
+ 2 files changed, 7 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
+@@ -1344,16 +1344,21 @@ static inline uint32_t dwc_otg_read_comm
+ */
+ gintmsk_common.b.portintr = 1;
+ }
+- gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
+- gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
+ if(fiq_enable) {
+ local_fiq_disable();
++ fiq_fsm_spin_lock(&hcd->fiq_state->lock);
++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
++ gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
+ /* Pull in the interrupts that the FIQ has masked */
+ gintmsk.d32 |= ~(hcd->fiq_state->gintmsk_saved.d32);
+ gintmsk.d32 |= gintmsk_common.d32;
+ /* for the upstairs function to reenable - have to read it here in case FIQ triggers again */
+ reenable_gintmsk->d32 = gintmsk.d32;
++ fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
+ local_fiq_enable();
++ } else {
++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
++ gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
+ }
+
+ gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+@@ -195,15 +195,11 @@ static void kill_urbs_in_qh_list(dwc_otg
+ * but not yet been through the IRQ handler.
+ */
+ if (fiq_fsm_enable && (hcd->fiq_state->channel[qh->channel->hc_num].fsm != FIQ_PASSTHROUGH)) {
+- local_fiq_disable();
+- fiq_fsm_spin_lock(&hcd->fiq_state->lock);
+ qh->channel->halt_status = DWC_OTG_HC_XFER_URB_DEQUEUE;
+ qh->channel->halt_pending = 1;
+ if (hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_TURBO ||
+ hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_SLEEPING)
+ hcd->fiq_state->channel[n].fsm = FIQ_HS_ISOC_ABORTED;
+- fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
+- local_fiq_enable();
+ } else {
+ dwc_otg_hc_halt(hcd->core_if, qh->channel,
+ DWC_OTG_HC_XFER_URB_DEQUEUE);
+++ /dev/null
-From e01ec5fd94e01b665f4deb1567f5b1da0537cce8 Mon Sep 17 00:00:00 2001
-From: Samuel Hsu <hsu@distec.de>
-Date: Mon, 8 Apr 2019 16:54:34 +0200
-Subject: [PATCH 425/703] configs: Add TOUCHSCREEN_ILI210X=m
-
-Signed-off-by: Samuel Hsu <hsu@distec.de>
----
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- 3 files changed, 3 insertions(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -565,6 +565,7 @@ CONFIG_TOUCHSCREEN_ADS7846=m
- CONFIG_TOUCHSCREEN_EGALAX=m
- CONFIG_TOUCHSCREEN_EXC3000=m
- CONFIG_TOUCHSCREEN_GOODIX=m
-+CONFIG_TOUCHSCREEN_ILI210X=m
- CONFIG_TOUCHSCREEN_EDT_FT5X06=m
- CONFIG_TOUCHSCREEN_RPI_FT5406=m
- CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -559,6 +559,7 @@ CONFIG_TOUCHSCREEN_ADS7846=m
- CONFIG_TOUCHSCREEN_EGALAX=m
- CONFIG_TOUCHSCREEN_EXC3000=m
- CONFIG_TOUCHSCREEN_GOODIX=m
-+CONFIG_TOUCHSCREEN_ILI210X=m
- CONFIG_TOUCHSCREEN_EDT_FT5X06=m
- CONFIG_TOUCHSCREEN_RPI_FT5406=m
- CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -547,6 +547,7 @@ CONFIG_INPUT_TOUCHSCREEN=y
- CONFIG_TOUCHSCREEN_ADS7846=m
- CONFIG_TOUCHSCREEN_EGALAX=m
- CONFIG_TOUCHSCREEN_EKTF2127=m
-+CONFIG_TOUCHSCREEN_ILI210X=m
- CONFIG_TOUCHSCREEN_RPI_FT5406=m
- CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
- CONFIG_TOUCHSCREEN_STMPE=m
--- /dev/null
+From 94ff67715e55c545dccbc00c8930a7566ba05a6c Mon Sep 17 00:00:00 2001
+From: Phil Howard <phil@gadgetoid.com>
+Date: Fri, 29 Mar 2019 10:53:14 +0000
+Subject: [PATCH 425/725] rtc: rv3028: Add backup switchover mode support
+
+Signed-off-by: Phil Howard <phil@pimoroni.com>
+---
+ drivers/rtc/rtc-rv3028.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+--- a/drivers/rtc/rtc-rv3028.c
++++ b/drivers/rtc/rtc-rv3028.c
+@@ -74,6 +74,7 @@
+
+ #define RV3028_BACKUP_TCE BIT(5)
+ #define RV3028_BACKUP_TCR_MASK GENMASK(1,0)
++#define RV3028_BACKUP_BSM_MASK 0x0C
+
+ #define OFFSET_STEP_PPT 953674
+
+@@ -601,6 +602,7 @@ static int rv3028_probe(struct i2c_clien
+ struct rv3028_data *rv3028;
+ int ret, status;
+ u32 ohms;
++ u8 bsm;
+ struct nvmem_config nvmem_cfg = {
+ .name = "rv3028_nvram",
+ .word_size = 1,
+@@ -671,6 +673,21 @@ static int rv3028_probe(struct i2c_clien
+ if (ret)
+ return ret;
+
++ /* setup backup switchover mode */
++ if (!device_property_read_u8(&client->dev, "backup-switchover-mode",
++ &bsm)) {
++ if (bsm <= 3) {
++ ret = regmap_update_bits(rv3028->regmap, RV3028_BACKUP,
++ RV3028_BACKUP_BSM_MASK,
++ (bsm & 0x03) << 2);
++
++ if (ret)
++ return ret;
++ } else {
++ dev_warn(&client->dev, "invalid backup switchover mode value\n");
++ }
++ }
++
+ /* setup trickle charger */
+ if (!device_property_read_u32(&client->dev, "trickle-resistor-ohms",
+ &ohms)) {
+++ /dev/null
-From 7b15bdfee1c922d6c3e92329cd23a45e77e036ae Mon Sep 17 00:00:00 2001
-From: Samuel Hsu <hsu@distec.de>
-Date: Mon, 8 Apr 2019 17:06:44 +0200
-Subject: [PATCH 426/703] BCM2708: Add core Device Tree support, ilitek251x
-
-Signed-off-by: Samuel Hsu <hsu@distec.de>
----
- arch/arm/boot/dts/overlays/Makefile | 1 +
- arch/arm/boot/dts/overlays/README | 11 +++++
- .../boot/dts/overlays/ilitek251x-overlay.dts | 45 +++++++++++++++++++
- 3 files changed, 57 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -67,6 +67,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- i2c0-bcm2708.dtbo \
- i2c1-bcm2708.dtbo \
- i2s-gpio28-31.dtbo \
-+ ilitek251x.dtbo \
- iqaudio-dac.dtbo \
- iqaudio-dacplus.dtbo \
- iqaudio-digi-wm8804-audio.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1146,6 +1146,17 @@ Load: dtoverlay=i2s-gpio28-31
- Params: <None>
-
-
-+Name: ilitek251x
-+Info: Enables I2C connected Ilitek 251x multiple touch controller using
-+ GPIO 4 (pin 7 on GPIO header) for interrupt.
-+Load: dtoverlay=ilitek251x,<param>=<val>
-+Params: interrupt GPIO used for interrupt (default 4)
-+ sizex Touchscreen size x, horizontal resolution of
-+ touchscreen (in pixels)
-+ sizey Touchscreen size y, vertical resolution of
-+ touchscreen (in pixels)
-+
-+
- Name: iqaudio-dac
- Info: Configures the IQaudio DAC audio card
- Load: dtoverlay=iqaudio-dac,<param>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
-@@ -0,0 +1,45 @@
-+// Device tree overlay for I2C connected Ilitek multiple touch controller
-+/dts-v1/;
-+/plugin/;
-+
-+ / {
-+ compatible = "brcm,bcm2708";
-+
-+ fragment@0 {
-+ target = <&gpio>;
-+ __overlay__ {
-+ ili251x_pins: ili251x_pins {
-+ brcm,pins = <4>; // interrupt
-+ brcm,function = <0>; // in
-+ brcm,pull = <2>; // pull-up //
-+ };
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&i2c1>;
-+ __overlay__ {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "okay";
-+
-+ ili251x: ili251x@41 {
-+ compatible = "ilitek,ili251x";
-+ reg = <0x41>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&ili251x_pins>;
-+ interrupt-parent = <&gpio>;
-+ interrupts = <4 8>; // high-to-low edge triggered
-+ touchscreen-size-x = <16384>;
-+ touchscreen-size-y = <9600>;
-+ };
-+ };
-+ };
-+
-+ __overrides__ {
-+ interrupt = <&ili251x_pins>,"brcm,pins:0",
-+ <&ili251x>,"interrupts:0";
-+ sizex = <&ili251x>,"touchscreen-size-x:0";
-+ sizey = <&ili251x>,"touchscreen-size-y:0";
-+ };
-+};
--- /dev/null
+From 35cd2dda8463e8a1d20789487505809723953464 Mon Sep 17 00:00:00 2001
+From: Phil Howard <phil@gadgetoid.com>
+Date: Fri, 29 Mar 2019 10:57:07 +0000
+Subject: [PATCH 426/725] dt-bindings: rv3028 backup switchover support
+
+Signed-off-by: Phil Howard <phil@pimoroni.com>
+---
+ Documentation/devicetree/bindings/rtc/rtc.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/Documentation/devicetree/bindings/rtc/rtc.txt
++++ b/Documentation/devicetree/bindings/rtc/rtc.txt
+@@ -26,6 +26,7 @@ below.
+ - trickle-diode-disable : Do not use internal trickle charger diode Should be
+ given if internal trickle charger diode should be
+ disabled
++- backup-switchover-mode : Configure RTC backup power supply switch behaviour
+ - wakeup-source : Enables wake up of host system on alarm
+ - quartz-load-femtofarads : The capacitive load of the quartz(x-tal),
+ expressed in femto Farad (fF).
+++ /dev/null
-From ddd696d15f75315f1a20d5da57d94ed65d8c1404 Mon Sep 17 00:00:00 2001
-From: P33M <p33m@github.com>
-Date: Tue, 9 Apr 2019 16:40:48 +0100
-Subject: [PATCH 427/703] dwc_otg: fix locking around dequeueing and killing
- URBs
-
-kill_urbs_in_qh_list() is practically only ever called with the fiq lock
-already held, so don't spinlock twice in the case where we need to cancel
-an isochronous transfer.
-
-Also fix up a case where the global interrupt register could be read with
-the fiq lock not held.
-
-Fixes the deadlock seen in https://github.com/raspberrypi/linux/issues/2907
----
- drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 9 +++++++--
- drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 4 ----
- 2 files changed, 7 insertions(+), 6 deletions(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
-@@ -1344,16 +1344,21 @@ static inline uint32_t dwc_otg_read_comm
- */
- gintmsk_common.b.portintr = 1;
- }
-- gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
-- gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
- if(fiq_enable) {
- local_fiq_disable();
-+ fiq_fsm_spin_lock(&hcd->fiq_state->lock);
-+ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
-+ gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
- /* Pull in the interrupts that the FIQ has masked */
- gintmsk.d32 |= ~(hcd->fiq_state->gintmsk_saved.d32);
- gintmsk.d32 |= gintmsk_common.d32;
- /* for the upstairs function to reenable - have to read it here in case FIQ triggers again */
- reenable_gintmsk->d32 = gintmsk.d32;
-+ fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
- local_fiq_enable();
-+ } else {
-+ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
-+ gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
- }
-
- gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-@@ -195,15 +195,11 @@ static void kill_urbs_in_qh_list(dwc_otg
- * but not yet been through the IRQ handler.
- */
- if (fiq_fsm_enable && (hcd->fiq_state->channel[qh->channel->hc_num].fsm != FIQ_PASSTHROUGH)) {
-- local_fiq_disable();
-- fiq_fsm_spin_lock(&hcd->fiq_state->lock);
- qh->channel->halt_status = DWC_OTG_HC_XFER_URB_DEQUEUE;
- qh->channel->halt_pending = 1;
- if (hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_TURBO ||
- hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_SLEEPING)
- hcd->fiq_state->channel[n].fsm = FIQ_HS_ISOC_ABORTED;
-- fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
-- local_fiq_enable();
- } else {
- dwc_otg_hc_halt(hcd->core_if, qh->channel,
- DWC_OTG_HC_XFER_URB_DEQUEUE);
--- /dev/null
+From 3ef74a4e32c2d5d7893b6743e2379fbfcac6fd91 Mon Sep 17 00:00:00 2001
+From: Phil Howard <phil@gadgetoid.com>
+Date: Fri, 29 Mar 2019 10:59:55 +0000
+Subject: [PATCH 427/725] overlays: Add rv3028 backup switchover support to
+ i2c-rtc
+
+Signed-off-by: Phil Howard <phil@pimoroni.com>
+---
+ arch/arm/boot/dts/overlays/README | 3 +++
+ arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 1 +
+ 2 files changed, 4 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1013,6 +1013,9 @@ Params: abx80x Select o
+ wakeup-source Specify that the RTC can be used as a wakeup
+ source
+
++ backup-switchover-mode Backup power supply switch mode. Must be 0 for
++ off or 1 for Vdd < VBackup (RV3028 only)
++
+
+ Name: i2c-rtc-gpio
+ Info: Adds support for a number of I2C Real Time Clock devices
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -200,6 +200,7 @@
+ trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0",
+ <&abx80x>,"abracon,tc-resistor",
+ <&rv3028>,"trickle-resistor-ohms:0";
++ backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0";
+ wakeup-source = <&ds1339>,"wakeup-source?",
+ <&ds3231>,"wakeup-source?",
+ <&mcp7940x>,"wakeup-source?",
--- /dev/null
+From 8a063d9d7c86075dbae91ef353540ab7724cce35 Mon Sep 17 00:00:00 2001
+From: wavelet2 <20504977+wavelet2@users.noreply.github.com>
+Date: Mon, 15 Apr 2019 10:00:20 +0100
+Subject: [PATCH 428/725] Maxim MAX98357A I2S DAC overlay (#2935)
+
+Add overlay for Maxim MAX98357A I2S DAC.
+
+Signed-off-by: Richard Steedman <richard.steedman@gmail.com>
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 9 ++
+ .../boot/dts/overlays/max98357a-overlay.dts | 84 +++++++++++++++++++
+ 3 files changed, 94 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/max98357a-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -75,6 +75,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ justboom-dac.dtbo \
+ justboom-digi.dtbo \
+ ltc294x.dtbo \
++ max98357a.dtbo \
+ mbed-dac.dtbo \
+ mcp23017.dtbo \
+ mcp23s17.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1276,6 +1276,15 @@ Params: ltc2941 Select t
+ See the datasheet for more information.
+
+
++Name: max98357a
++Info: Configures the Maxim MAX98357A I2S DAC
++Load: dtoverlay=max98357a,<param>=<val>
++Params: no-sdmode Driver does not manage the state of the DAC's
++ SD_MODE pin (i.e. chip is always on).
++ sdmode-pin integer, GPIO pin connected to the SD_MODE input
++ of the DAC (default GPIO4 if parameter omitted).
++
++
+ Name: mbed-dac
+ Info: Configures the mbed AudioCODEC (TLV320AIC23B)
+ Load: dtoverlay=mbed-dac
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/max98357a-overlay.dts
+@@ -0,0 +1,84 @@
++// Overlay for Maxim MAX98357A audio DAC
++
++// dtparams:
++// no-sdmode - SD_MODE pin not managed by driver.
++// sdmode-pin - Specify GPIO pin to which SD_MODE is connected (default 4).
++
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++
++ /* Enable I2S */
++ fragment@0 {
++ target = <&i2s>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ /* DAC whose SD_MODE pin is managed by driver (via GPIO pin) */
++ fragment@1 {
++ target-path = "/";
++ __overlay__ {
++ max98357a_dac: max98357a {
++ compatible = "maxim,max98357a";
++ #sound-dai-cells = <0>;
++ sdmode-gpios = <&gpio 4 0>; /* 2nd word overwritten by sdmode-pin parameter */
++ status = "okay";
++ };
++ };
++ };
++
++ /* DAC whose SD_MODE pin is not managed by driver */
++ fragment@2 {
++ target-path = "/";
++ __dormant__ {
++ max98357a_nsd: max98357a {
++ compatible = "maxim,max98357a";
++ #sound-dai-cells = <0>;
++ status = "okay";
++ };
++ };
++ };
++
++ /* Soundcard connecting I2S to DAC with SD_MODE */
++ fragment@3 {
++ target = <&sound>;
++ __overlay__ {
++ compatible = "simple-audio-card";
++ simple-audio-card,format = "i2s";
++ simple-audio-card,name = "MAX98357A";
++ status = "okay";
++ simple-audio-card,cpu {
++ sound-dai = <&i2s>;
++ };
++ simple-audio-card,codec {
++ sound-dai = <&max98357a_dac>;
++ };
++ };
++ };
++
++ /* Soundcard connecting I2S to DAC without SD_MODE */
++ fragment@4 {
++ target = <&sound>;
++ __dormant__ {
++ compatible = "simple-audio-card";
++ simple-audio-card,format = "i2s";
++ simple-audio-card,name = "MAX98357A";
++ status = "okay";
++ simple-audio-card,cpu {
++ sound-dai = <&i2s>;
++ };
++ simple-audio-card,codec {
++ sound-dai = <&max98357a_nsd>;
++ };
++ };
++ };
++
++ __overrides__ {
++ no-sdmode = <0>,"-1+2-3+4";
++ sdmode-pin = <&max98357a_dac>,"sdmode-gpios:4";
++ };
++};
+++ /dev/null
-From 5159281b7a2fe2f4dc1cc2f1cd97d45972f02d99 Mon Sep 17 00:00:00 2001
-From: Phil Howard <phil@gadgetoid.com>
-Date: Fri, 29 Mar 2019 10:53:14 +0000
-Subject: [PATCH 428/703] rtc: rv3028: Add backup switchover mode support
-
-Signed-off-by: Phil Howard <phil@pimoroni.com>
----
- drivers/rtc/rtc-rv3028.c | 17 +++++++++++++++++
- 1 file changed, 17 insertions(+)
-
---- a/drivers/rtc/rtc-rv3028.c
-+++ b/drivers/rtc/rtc-rv3028.c
-@@ -74,6 +74,7 @@
-
- #define RV3028_BACKUP_TCE BIT(5)
- #define RV3028_BACKUP_TCR_MASK GENMASK(1,0)
-+#define RV3028_BACKUP_BSM_MASK 0x0C
-
- #define OFFSET_STEP_PPT 953674
-
-@@ -601,6 +602,7 @@ static int rv3028_probe(struct i2c_clien
- struct rv3028_data *rv3028;
- int ret, status;
- u32 ohms;
-+ u8 bsm;
- struct nvmem_config nvmem_cfg = {
- .name = "rv3028_nvram",
- .word_size = 1,
-@@ -671,6 +673,21 @@ static int rv3028_probe(struct i2c_clien
- if (ret)
- return ret;
-
-+ /* setup backup switchover mode */
-+ if (!device_property_read_u8(&client->dev, "backup-switchover-mode",
-+ &bsm)) {
-+ if (bsm <= 3) {
-+ ret = regmap_update_bits(rv3028->regmap, RV3028_BACKUP,
-+ RV3028_BACKUP_BSM_MASK,
-+ (bsm & 0x03) << 2);
-+
-+ if (ret)
-+ return ret;
-+ } else {
-+ dev_warn(&client->dev, "invalid backup switchover mode value\n");
-+ }
-+ }
-+
- /* setup trickle charger */
- if (!device_property_read_u32(&client->dev, "trickle-resistor-ohms",
- &ohms)) {
+++ /dev/null
-From ea30c9b919bbd7695f99e0467f3546ac945d4e54 Mon Sep 17 00:00:00 2001
-From: Phil Howard <phil@gadgetoid.com>
-Date: Fri, 29 Mar 2019 10:57:07 +0000
-Subject: [PATCH 429/703] dt-bindings: rv3028 backup switchover support
-
-Signed-off-by: Phil Howard <phil@pimoroni.com>
----
- Documentation/devicetree/bindings/rtc/rtc.txt | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/Documentation/devicetree/bindings/rtc/rtc.txt
-+++ b/Documentation/devicetree/bindings/rtc/rtc.txt
-@@ -26,6 +26,7 @@ below.
- - trickle-diode-disable : Do not use internal trickle charger diode Should be
- given if internal trickle charger diode should be
- disabled
-+- backup-switchover-mode : Configure RTC backup power supply switch behaviour
- - wakeup-source : Enables wake up of host system on alarm
- - quartz-load-femtofarads : The capacitive load of the quartz(x-tal),
- expressed in femto Farad (fF).
--- /dev/null
+From c349bcade000820be4f53dd2d189887ec11794d4 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 21 Mar 2019 11:19:46 +0000
+Subject: [PATCH 429/725] sound: Fixes for audioinjector-octo under 4.19
+
+1. Move the DT alias declaration to the I2C shim in the cases
+where the shim is enabled. This works around a problem caused by a
+4.19 commit [1] that generates DT/OF uevents for I2C drivers.
+
+2. Fix the diagnostics in an error path of the soundcard driver to
+correctly identify the reason for the failure to load.
+
+3. Move the declaration of the clock node in the overlay outside
+the I2C node to avoid warnings.
+
+4. Sort the overlay nodes so that dependencies are only to earlier
+fragments, in an attempt to get runtime dtoverlay application to
+work (it still doesn't...)
+
+See: https://github.com/Audio-Injector/Octo/issues/14
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+
+[1] af503716ac14 ("i2c: core: report OF style module alias for devices registered via OF")
+---
+ .../overlays/audioinjector-addons-overlay.dts | 19 ++++++++++++-------
+ sound/soc/bcm/audioinjector-octo-soundcard.c | 2 +-
+ sound/soc/codecs/cs42xx8-i2c.c | 7 +++++++
+ sound/soc/codecs/cs42xx8.c | 2 ++
+ 4 files changed, 22 insertions(+), 8 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
+@@ -13,6 +13,17 @@
+ };
+
+ fragment@1 {
++ target-path = "/";
++ __overlay__ {
++ cs42448_mclk: codec-mclk {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <49152000>;
++ };
++ };
++ };
++
++ fragment@2 {
+ target = <&i2c1>;
+ __overlay__ {
+ #address-cells = <1>;
+@@ -27,16 +38,10 @@
+ clock-names = "mclk";
+ status = "okay";
+ };
+-
+- cs42448_mclk: codec-mclk {
+- compatible = "fixed-clock";
+- #clock-cells = <0>;
+- clock-frequency = <49152000>;
+- };
+ };
+ };
+
+- fragment@2 {
++ fragment@3 {
+ target = <&sound>;
+ snd: __overlay__ {
+ compatible = "ai,audioinjector-octo-soundcard";
+--- a/sound/soc/bcm/audioinjector-octo-soundcard.c
++++ b/sound/soc/bcm/audioinjector-octo-soundcard.c
+@@ -297,7 +297,7 @@ static int audioinjector_octo_probe(stru
+ dai->codec_name = NULL;
+ dai->codec_of_node = codec_node;
+ } else
+- if (!dai->cpu_of_node) {
++ if (!i2s_node) {
+ dev_err(&pdev->dev,
+ "i2s-controller missing or invalid in DT\n");
+ return -EINVAL;
+--- a/sound/soc/codecs/cs42xx8-i2c.c
++++ b/sound/soc/codecs/cs42xx8-i2c.c
+@@ -45,6 +45,13 @@ static struct i2c_device_id cs42xx8_i2c_
+ };
+ MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id);
+
++const struct of_device_id cs42xx8_of_match[] = {
++ { .compatible = "cirrus,cs42448", .data = &cs42448_data, },
++ { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
++ { /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
++
+ static struct i2c_driver cs42xx8_i2c_driver = {
+ .driver = {
+ .name = "cs42xx8",
+--- a/sound/soc/codecs/cs42xx8.c
++++ b/sound/soc/codecs/cs42xx8.c
+@@ -436,8 +436,10 @@ const struct of_device_id cs42xx8_of_mat
+ { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
+ { /* sentinel */ }
+ };
++#if !IS_ENABLED(CONFIG_SND_SOC_CS42XX8_I2C)
+ MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
+ EXPORT_SYMBOL_GPL(cs42xx8_of_match);
++#endif
+
+ int cs42xx8_probe(struct device *dev, struct regmap *regmap)
+ {
--- /dev/null
+From 95eef94518f050146820340787b2472db13c38ae Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Wed, 24 Apr 2019 14:25:09 +0100
+Subject: [PATCH 430/725] Revert "cgroup: Disable cgroup "memory" by default"
+
+This reverts commit cd6ce4d0ded13c94ff5208c679ed5e030263149b.
+---
+ kernel/cgroup/cgroup.c | 30 ------------------------------
+ 1 file changed, 30 deletions(-)
+
+--- a/kernel/cgroup/cgroup.c
++++ b/kernel/cgroup/cgroup.c
+@@ -5296,8 +5296,6 @@ int __init cgroup_init_early(void)
+ }
+
+ static u16 cgroup_disable_mask __initdata;
+-static u16 cgroup_enable_mask __initdata;
+-static int __init cgroup_disable(char *str);
+
+ /**
+ * cgroup_init - cgroup initialization
+@@ -5338,12 +5336,6 @@ int __init cgroup_init(void)
+
+ mutex_unlock(&cgroup_mutex);
+
+- /* Apply an implicit disable... */
+- cgroup_disable("memory");
+-
+- /* ...knowing that an explicit enable will override it. */
+- cgroup_disable_mask &= ~cgroup_enable_mask;
+-
+ for_each_subsys(ss, ssid) {
+ if (ss->early_init) {
+ struct cgroup_subsys_state *css =
+@@ -5727,28 +5719,6 @@ static int __init cgroup_disable(char *s
+ }
+ __setup("cgroup_disable=", cgroup_disable);
+
+-static int __init cgroup_enable(char *str)
+-{
+- struct cgroup_subsys *ss;
+- char *token;
+- int i;
+-
+- while ((token = strsep(&str, ",")) != NULL) {
+- if (!*token)
+- continue;
+-
+- for_each_subsys(ss, i) {
+- if (strcmp(token, ss->name) &&
+- strcmp(token, ss->legacy_name))
+- continue;
+-
+- cgroup_enable_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
+++ /dev/null
-From a73793c4cea3ef39d203c6a0e7e3456629e25f5e Mon Sep 17 00:00:00 2001
-From: Phil Howard <phil@gadgetoid.com>
-Date: Fri, 29 Mar 2019 10:59:55 +0000
-Subject: [PATCH 430/703] overlays: Add rv3028 backup switchover support to
- i2c-rtc
-
-Signed-off-by: Phil Howard <phil@pimoroni.com>
----
- arch/arm/boot/dts/overlays/README | 3 +++
- arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 1 +
- 2 files changed, 4 insertions(+)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1013,6 +1013,9 @@ Params: abx80x Select o
- wakeup-source Specify that the RTC can be used as a wakeup
- source
-
-+ backup-switchover-mode Backup power supply switch mode. Must be 0 for
-+ off or 1 for Vdd < VBackup (RV3028 only)
-+
-
- Name: i2c-rtc-gpio
- Info: Adds support for a number of I2C Real Time Clock devices
---- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-@@ -200,6 +200,7 @@
- trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0",
- <&abx80x>,"abracon,tc-resistor",
- <&rv3028>,"trickle-resistor-ohms:0";
-+ backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0";
- wakeup-source = <&ds1339>,"wakeup-source?",
- <&ds3231>,"wakeup-source?",
- <&mcp7940x>,"wakeup-source?",
+++ /dev/null
-From 43371fb1fb2a2eaefe54288bcd61d015237c25fe Mon Sep 17 00:00:00 2001
-From: wavelet2 <20504977+wavelet2@users.noreply.github.com>
-Date: Mon, 15 Apr 2019 10:00:20 +0100
-Subject: [PATCH 431/703] Maxim MAX98357A I2S DAC overlay (#2935)
-
-Add overlay for Maxim MAX98357A I2S DAC.
-
-Signed-off-by: Richard Steedman <richard.steedman@gmail.com>
----
- arch/arm/boot/dts/overlays/Makefile | 1 +
- arch/arm/boot/dts/overlays/README | 9 ++
- .../boot/dts/overlays/max98357a-overlay.dts | 84 +++++++++++++++++++
- 3 files changed, 94 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/max98357a-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -75,6 +75,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- justboom-dac.dtbo \
- justboom-digi.dtbo \
- ltc294x.dtbo \
-+ max98357a.dtbo \
- mbed-dac.dtbo \
- mcp23017.dtbo \
- mcp23s17.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1276,6 +1276,15 @@ Params: ltc2941 Select t
- See the datasheet for more information.
-
-
-+Name: max98357a
-+Info: Configures the Maxim MAX98357A I2S DAC
-+Load: dtoverlay=max98357a,<param>=<val>
-+Params: no-sdmode Driver does not manage the state of the DAC's
-+ SD_MODE pin (i.e. chip is always on).
-+ sdmode-pin integer, GPIO pin connected to the SD_MODE input
-+ of the DAC (default GPIO4 if parameter omitted).
-+
-+
- Name: mbed-dac
- Info: Configures the mbed AudioCODEC (TLV320AIC23B)
- Load: dtoverlay=mbed-dac
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/max98357a-overlay.dts
-@@ -0,0 +1,84 @@
-+// Overlay for Maxim MAX98357A audio DAC
-+
-+// dtparams:
-+// no-sdmode - SD_MODE pin not managed by driver.
-+// sdmode-pin - Specify GPIO pin to which SD_MODE is connected (default 4).
-+
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+
-+ /* Enable I2S */
-+ fragment@0 {
-+ target = <&i2s>;
-+ __overlay__ {
-+ status = "okay";
-+ };
-+ };
-+
-+ /* DAC whose SD_MODE pin is managed by driver (via GPIO pin) */
-+ fragment@1 {
-+ target-path = "/";
-+ __overlay__ {
-+ max98357a_dac: max98357a {
-+ compatible = "maxim,max98357a";
-+ #sound-dai-cells = <0>;
-+ sdmode-gpios = <&gpio 4 0>; /* 2nd word overwritten by sdmode-pin parameter */
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ /* DAC whose SD_MODE pin is not managed by driver */
-+ fragment@2 {
-+ target-path = "/";
-+ __dormant__ {
-+ max98357a_nsd: max98357a {
-+ compatible = "maxim,max98357a";
-+ #sound-dai-cells = <0>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ /* Soundcard connecting I2S to DAC with SD_MODE */
-+ fragment@3 {
-+ target = <&sound>;
-+ __overlay__ {
-+ compatible = "simple-audio-card";
-+ simple-audio-card,format = "i2s";
-+ simple-audio-card,name = "MAX98357A";
-+ status = "okay";
-+ simple-audio-card,cpu {
-+ sound-dai = <&i2s>;
-+ };
-+ simple-audio-card,codec {
-+ sound-dai = <&max98357a_dac>;
-+ };
-+ };
-+ };
-+
-+ /* Soundcard connecting I2S to DAC without SD_MODE */
-+ fragment@4 {
-+ target = <&sound>;
-+ __dormant__ {
-+ compatible = "simple-audio-card";
-+ simple-audio-card,format = "i2s";
-+ simple-audio-card,name = "MAX98357A";
-+ status = "okay";
-+ simple-audio-card,cpu {
-+ sound-dai = <&i2s>;
-+ };
-+ simple-audio-card,codec {
-+ sound-dai = <&max98357a_nsd>;
-+ };
-+ };
-+ };
-+
-+ __overrides__ {
-+ no-sdmode = <0>,"-1+2-3+4";
-+ sdmode-pin = <&max98357a_dac>,"sdmode-gpios:4";
-+ };
-+};
--- /dev/null
+From 6e1f012d8072528275a751fa9b12496bfcc07088 Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Wed, 24 Apr 2019 14:25:41 +0100
+Subject: [PATCH 431/725] Revert "defconfigs: disable memory and IO cgroups
+ (#2908)"
+
+This reverts commit 9881cdbf446081f71c62f39f4c56a21001baea73.
+---
+ arch/arm/configs/bcm2709_defconfig | 4 ++++
+ arch/arm/configs/bcmrpi_defconfig | 4 ++++
+ arch/arm64/configs/bcmrpi3_defconfig | 4 ++++
+ 3 files changed, 12 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -14,6 +14,8 @@ CONFIG_TASK_XACCT=y
+ CONFIG_TASK_IO_ACCOUNTING=y
+ CONFIG_IKCONFIG=m
+ CONFIG_IKCONFIG_PROC=y
++CONFIG_MEMCG=y
++CONFIG_BLK_CGROUP=y
+ CONFIG_CGROUP_FREEZER=y
+ CONFIG_CPUSETS=y
+ CONFIG_CGROUP_DEVICE=y
+@@ -62,8 +64,10 @@ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_MODULE_SRCVERSION_ALL=y
++CONFIG_BLK_DEV_THROTTLING=y
+ CONFIG_PARTITION_ADVANCED=y
+ CONFIG_MAC_PARTITION=y
++CONFIG_CFQ_GROUP_IOSCHED=y
+ CONFIG_BINFMT_MISC=m
+ CONFIG_CLEANCACHE=y
+ CONFIG_FRONTSWAP=y
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -13,6 +13,8 @@ CONFIG_TASK_XACCT=y
+ CONFIG_TASK_IO_ACCOUNTING=y
+ CONFIG_IKCONFIG=m
+ CONFIG_IKCONFIG_PROC=y
++CONFIG_MEMCG=y
++CONFIG_BLK_CGROUP=y
+ CONFIG_CGROUP_FREEZER=y
+ CONFIG_CGROUP_DEVICE=y
+ CONFIG_CGROUP_CPUACCT=y
+@@ -56,8 +58,10 @@ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_MODULE_SRCVERSION_ALL=y
++CONFIG_BLK_DEV_THROTTLING=y
+ CONFIG_PARTITION_ADVANCED=y
+ CONFIG_MAC_PARTITION=y
++CONFIG_CFQ_GROUP_IOSCHED=y
+ CONFIG_BINFMT_MISC=m
+ CONFIG_CLEANCACHE=y
+ CONFIG_FRONTSWAP=y
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -13,6 +13,8 @@ CONFIG_TASK_XACCT=y
+ CONFIG_TASK_IO_ACCOUNTING=y
+ CONFIG_IKCONFIG=m
+ CONFIG_IKCONFIG_PROC=y
++CONFIG_MEMCG=y
++CONFIG_BLK_CGROUP=y
+ CONFIG_CGROUP_FREEZER=y
+ CONFIG_CPUSETS=y
+ CONFIG_CGROUP_DEVICE=y
+@@ -60,8 +62,10 @@ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_MODULE_SRCVERSION_ALL=y
++CONFIG_BLK_DEV_THROTTLING=y
+ CONFIG_PARTITION_ADVANCED=y
+ CONFIG_MAC_PARTITION=y
++CONFIG_CFQ_GROUP_IOSCHED=y
+ CONFIG_BINFMT_MISC=y
+ CONFIG_CLEANCACHE=y
+ CONFIG_FRONTSWAP=y
--- /dev/null
+From 54882fd6678b052c68040caa38c70b2c3af0c958 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Mon, 29 Apr 2019 19:35:33 +0200
+Subject: [PATCH 432/725] overlays: Add PiGlow overlay
+
+The PiGlow is a small add-on board for the Raspberry Pi that provides
+18 individually controllable LEDs (SN3218) and uses the following pins:
+
+P1 & P17 (3V3)
+P2 (5V)
+P3 (SDA)
+P5 (SCL)
+P14 (GND)
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 6 ++
+ arch/arm/boot/dts/overlays/piglow-overlay.dts | 97 +++++++++++++++++++
+ 3 files changed, 104 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/piglow-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -97,6 +97,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ pi3-disable-wifi.dtbo \
+ pi3-miniuart-bt.dtbo \
+ pibell.dtbo \
++ piglow.dtbo \
+ piscreen.dtbo \
+ piscreen2r.dtbo \
+ pisound.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1532,6 +1532,12 @@ Params: alsaname Set the
+ "PiBell")
+
+
++Name: piglow
++Info: Configures the PiGlow by pimoroni.com
++Load: dtoverlay=piglow
++Params: <None>
++
++
+ Name: piscreen
+ Info: PiScreen display by OzzMaker.com
+ Load: dtoverlay=piscreen,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/piglow-overlay.dts
+@@ -0,0 +1,97 @@
++// Definitions for SN3218 LED driver from Si-En Technology on PiGlow
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "brcm,bcm2708";
++
++ fragment@0 {
++ target = <&i2c_arm>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ sn3218@54 {
++ compatible = "si-en,sn3218";
++ reg = <0x54>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ led@1 {
++ reg = <1>;
++ label = "piglow:red:led1";
++ };
++ led@2 {
++ reg = <2>;
++ label = "piglow:orange:led2";
++ };
++ led@3 {
++ reg = <3>;
++ label = "piglow:yellow:led3";
++ };
++ led@4 {
++ reg = <4>;
++ label = "piglow:green:led4";
++ };
++ led@5 {
++ reg = <5>;
++ label = "piglow:blue:led5";
++ };
++ led@6 {
++ reg = <6>;
++ label = "piglow:green:led6";
++ };
++ led@7 {
++ reg = <7>;
++ label = "piglow:red:led7";
++ };
++ led@8 {
++ reg = <8>;
++ label = "piglow:orange:led8";
++ };
++ led@9 {
++ reg = <9>;
++ label = "piglow:yellow:led9";
++ };
++ led@10 {
++ reg = <10>;
++ label = "piglow:white:led10";
++ };
++ led@11 {
++ reg = <11>;
++ label = "piglow:white:led11";
++ };
++ led@12 {
++ reg = <12>;
++ label = "piglow:blue:led12";
++ };
++ led@13 {
++ reg = <13>;
++ label = "piglow:white:led13";
++ };
++ led@14 {
++ reg = <14>;
++ label = "piglow:green:led14";
++ };
++ led@15 {
++ reg = <15>;
++ label = "piglow:blue:led15";
++ };
++ led@16 {
++ reg = <16>;
++ label = "piglow:yellow:led16";
++ };
++ led@17 {
++ reg = <17>;
++ label = "piglow:orange:led17";
++ };
++ led@18 {
++ reg = <18>;
++ label = "piglow:red:led18";
++ };
++ };
++ };
++ };
++};
+++ /dev/null
-From 7ed120d6a2733f70a5c8ee15844e1f02aec3f421 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 21 Mar 2019 11:19:46 +0000
-Subject: [PATCH 432/703] sound: Fixes for audioinjector-octo under 4.19
-
-1. Move the DT alias declaration to the I2C shim in the cases
-where the shim is enabled. This works around a problem caused by a
-4.19 commit [1] that generates DT/OF uevents for I2C drivers.
-
-2. Fix the diagnostics in an error path of the soundcard driver to
-correctly identify the reason for the failure to load.
-
-3. Move the declaration of the clock node in the overlay outside
-the I2C node to avoid warnings.
-
-4. Sort the overlay nodes so that dependencies are only to earlier
-fragments, in an attempt to get runtime dtoverlay application to
-work (it still doesn't...)
-
-See: https://github.com/Audio-Injector/Octo/issues/14
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
-
-[1] af503716ac14 ("i2c: core: report OF style module alias for devices registered via OF")
----
- .../overlays/audioinjector-addons-overlay.dts | 19 ++++++++++++-------
- sound/soc/bcm/audioinjector-octo-soundcard.c | 2 +-
- sound/soc/codecs/cs42xx8-i2c.c | 7 +++++++
- sound/soc/codecs/cs42xx8.c | 2 ++
- 4 files changed, 22 insertions(+), 8 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
-@@ -13,6 +13,17 @@
- };
-
- fragment@1 {
-+ target-path = "/";
-+ __overlay__ {
-+ cs42448_mclk: codec-mclk {
-+ compatible = "fixed-clock";
-+ #clock-cells = <0>;
-+ clock-frequency = <49152000>;
-+ };
-+ };
-+ };
-+
-+ fragment@2 {
- target = <&i2c1>;
- __overlay__ {
- #address-cells = <1>;
-@@ -27,16 +38,10 @@
- clock-names = "mclk";
- status = "okay";
- };
--
-- cs42448_mclk: codec-mclk {
-- compatible = "fixed-clock";
-- #clock-cells = <0>;
-- clock-frequency = <49152000>;
-- };
- };
- };
-
-- fragment@2 {
-+ fragment@3 {
- target = <&sound>;
- snd: __overlay__ {
- compatible = "ai,audioinjector-octo-soundcard";
---- a/sound/soc/bcm/audioinjector-octo-soundcard.c
-+++ b/sound/soc/bcm/audioinjector-octo-soundcard.c
-@@ -297,7 +297,7 @@ static int audioinjector_octo_probe(stru
- dai->codec_name = NULL;
- dai->codec_of_node = codec_node;
- } else
-- if (!dai->cpu_of_node) {
-+ if (!i2s_node) {
- dev_err(&pdev->dev,
- "i2s-controller missing or invalid in DT\n");
- return -EINVAL;
---- a/sound/soc/codecs/cs42xx8-i2c.c
-+++ b/sound/soc/codecs/cs42xx8-i2c.c
-@@ -45,6 +45,13 @@ static struct i2c_device_id cs42xx8_i2c_
- };
- MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id);
-
-+const struct of_device_id cs42xx8_of_match[] = {
-+ { .compatible = "cirrus,cs42448", .data = &cs42448_data, },
-+ { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
-+ { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
-+
- static struct i2c_driver cs42xx8_i2c_driver = {
- .driver = {
- .name = "cs42xx8",
---- a/sound/soc/codecs/cs42xx8.c
-+++ b/sound/soc/codecs/cs42xx8.c
-@@ -436,8 +436,10 @@ const struct of_device_id cs42xx8_of_mat
- { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
- { /* sentinel */ }
- };
-+#if !IS_ENABLED(CONFIG_SND_SOC_CS42XX8_I2C)
- MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
- EXPORT_SYMBOL_GPL(cs42xx8_of_match);
-+#endif
-
- int cs42xx8_probe(struct device *dev, struct regmap *regmap)
- {
+++ /dev/null
-From 18c18a16cbf0007907319d5472351f6bc3e7135d Mon Sep 17 00:00:00 2001
-From: P33M <p33m@github.com>
-Date: Wed, 24 Apr 2019 14:25:09 +0100
-Subject: [PATCH 433/703] Revert "cgroup: Disable cgroup "memory" by default"
-
-This reverts commit cd6ce4d0ded13c94ff5208c679ed5e030263149b.
----
- kernel/cgroup/cgroup.c | 30 ------------------------------
- 1 file changed, 30 deletions(-)
-
---- a/kernel/cgroup/cgroup.c
-+++ b/kernel/cgroup/cgroup.c
-@@ -5296,8 +5296,6 @@ int __init cgroup_init_early(void)
- }
-
- static u16 cgroup_disable_mask __initdata;
--static u16 cgroup_enable_mask __initdata;
--static int __init cgroup_disable(char *str);
-
- /**
- * cgroup_init - cgroup initialization
-@@ -5338,12 +5336,6 @@ int __init cgroup_init(void)
-
- mutex_unlock(&cgroup_mutex);
-
-- /* Apply an implicit disable... */
-- cgroup_disable("memory");
--
-- /* ...knowing that an explicit enable will override it. */
-- cgroup_disable_mask &= ~cgroup_enable_mask;
--
- for_each_subsys(ss, ssid) {
- if (ss->early_init) {
- struct cgroup_subsys_state *css =
-@@ -5727,28 +5719,6 @@ static int __init cgroup_disable(char *s
- }
- __setup("cgroup_disable=", cgroup_disable);
-
--static int __init cgroup_enable(char *str)
--{
-- struct cgroup_subsys *ss;
-- char *token;
-- int i;
--
-- while ((token = strsep(&str, ",")) != NULL) {
-- if (!*token)
-- continue;
--
-- for_each_subsys(ss, i) {
-- if (strcmp(token, ss->name) &&
-- strcmp(token, ss->legacy_name))
-- continue;
--
-- cgroup_enable_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
--- /dev/null
+From d100cd5246ac51acdcfc4bec574e127ee61dcf99 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Mon, 29 Apr 2019 19:28:51 +0200
+Subject: [PATCH 433/725] configs: enable LED driver for PiGlow
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ arch/arm64/configs/bcmrpi3_defconfig | 3 ++-
+ 3 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -1131,6 +1131,7 @@ CONFIG_MMC_SPI=m
+ CONFIG_LEDS_CLASS=y
+ CONFIG_LEDS_GPIO=y
+ CONFIG_LEDS_PCA963X=m
++CONFIG_LEDS_IS31FL32XX=m
+ CONFIG_LEDS_TRIGGER_TIMER=y
+ CONFIG_LEDS_TRIGGER_ONESHOT=y
+ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -1124,6 +1124,7 @@ CONFIG_MMC_SPI=m
+ CONFIG_LEDS_CLASS=y
+ CONFIG_LEDS_GPIO=y
+ CONFIG_LEDS_PCA963X=m
++CONFIG_LEDS_IS31FL32XX=m
+ CONFIG_LEDS_TRIGGER_TIMER=y
+ CONFIG_LEDS_TRIGGER_ONESHOT=y
+ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -550,8 +550,8 @@ CONFIG_JOYSTICK_RPISENSE=m
+ CONFIG_INPUT_TOUCHSCREEN=y
+ CONFIG_TOUCHSCREEN_ADS7846=m
+ CONFIG_TOUCHSCREEN_EGALAX=m
+-CONFIG_TOUCHSCREEN_EKTF2127=m
+ CONFIG_TOUCHSCREEN_ILI210X=m
++CONFIG_TOUCHSCREEN_EKTF2127=m
+ CONFIG_TOUCHSCREEN_RPI_FT5406=m
+ CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+ CONFIG_TOUCHSCREEN_STMPE=m
+@@ -991,6 +991,7 @@ CONFIG_MMC_SPI=m
+ CONFIG_LEDS_CLASS=y
+ CONFIG_LEDS_GPIO=y
+ CONFIG_LEDS_PCA963X=m
++CONFIG_LEDS_IS31FL32XX=m
+ CONFIG_LEDS_TRIGGER_TIMER=y
+ CONFIG_LEDS_TRIGGER_ONESHOT=y
+ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
--- /dev/null
+From 48f4f82875a8bc8fe399714114daee135592d963 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 29 Apr 2019 19:16:14 +0100
+Subject: [PATCH 434/725] Revert "bcm2835: interpolate audio delay"
+
+commit fb4b9f02986fcb5ae751106ef9b027806b5dd750 upstream.
+
+This reverts commit fb8cc99f05687ca5565dc53a7ee0dd86aefad952.
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 12 +-----------
+ .../staging/vc04_services/bcm2835-audio/bcm2835.h | 1 -
+ 2 files changed, 1 insertion(+), 12 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -11,7 +11,7 @@
+ /* hardware definition */
+ static const 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 | SNDRV_PCM_INFO_BATCH),
++ 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,
+@@ -81,8 +81,6 @@ void bcm2835_playback_fifo(struct bcm283
+ alsa_stream->pos %= alsa_stream->buffer_size;
+ }
+
+- alsa_stream->interpolate_start = ktime_get_ns();
+-
+ if (alsa_stream->substream) {
+ if (new_period)
+ snd_pcm_period_elapsed(alsa_stream->substream);
+@@ -308,7 +306,6 @@ static int snd_bcm2835_pcm_prepare(struc
+ alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
+ alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
+ alsa_stream->pos = 0;
+- alsa_stream->interpolate_start = ktime_get_ns();
+
+ audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n",
+ alsa_stream->buffer_size, alsa_stream->period_size,
+@@ -400,19 +397,12 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
+- u64 now = ktime_get_ns();
+
+ 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);
+
+- /* Give userspace better delay reporting by interpolating between GPU
+- * notifications, assuming audio speed is close enough to the clock
+- * used for ktime */
+- if (alsa_stream->interpolate_start && alsa_stream->interpolate_start < now)
+- runtime->delay = -(int)div_u64((now - alsa_stream->interpolate_start) * runtime->rate, 1000000000);
+-
+ return snd_pcm_indirect_playback_pointer(substream,
+ &alsa_stream->pcm_indirect,
+ alsa_stream->pos);
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -133,7 +133,6 @@ struct bcm2835_alsa_stream {
+ unsigned int pos;
+ unsigned int buffer_size;
+ unsigned int period_size;
+- u64 interpolate_start;
+
+ atomic_t retrieved;
+ struct bcm2835_audio_instance *instance;
+++ /dev/null
-From 76088decdde58c18a100c2fc7f15f9abbead6eef Mon Sep 17 00:00:00 2001
-From: P33M <p33m@github.com>
-Date: Wed, 24 Apr 2019 14:25:41 +0100
-Subject: [PATCH 434/703] Revert "defconfigs: disable memory and IO cgroups
- (#2908)"
-
-This reverts commit 9881cdbf446081f71c62f39f4c56a21001baea73.
----
- arch/arm/configs/bcm2709_defconfig | 4 ++++
- arch/arm/configs/bcmrpi_defconfig | 4 ++++
- arch/arm64/configs/bcmrpi3_defconfig | 4 ++++
- 3 files changed, 12 insertions(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -14,6 +14,8 @@ CONFIG_TASK_XACCT=y
- CONFIG_TASK_IO_ACCOUNTING=y
- CONFIG_IKCONFIG=m
- CONFIG_IKCONFIG_PROC=y
-+CONFIG_MEMCG=y
-+CONFIG_BLK_CGROUP=y
- CONFIG_CGROUP_FREEZER=y
- CONFIG_CPUSETS=y
- CONFIG_CGROUP_DEVICE=y
-@@ -62,8 +64,10 @@ CONFIG_MODULES=y
- CONFIG_MODULE_UNLOAD=y
- CONFIG_MODVERSIONS=y
- CONFIG_MODULE_SRCVERSION_ALL=y
-+CONFIG_BLK_DEV_THROTTLING=y
- CONFIG_PARTITION_ADVANCED=y
- CONFIG_MAC_PARTITION=y
-+CONFIG_CFQ_GROUP_IOSCHED=y
- CONFIG_BINFMT_MISC=m
- CONFIG_CLEANCACHE=y
- CONFIG_FRONTSWAP=y
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -13,6 +13,8 @@ CONFIG_TASK_XACCT=y
- CONFIG_TASK_IO_ACCOUNTING=y
- CONFIG_IKCONFIG=m
- CONFIG_IKCONFIG_PROC=y
-+CONFIG_MEMCG=y
-+CONFIG_BLK_CGROUP=y
- CONFIG_CGROUP_FREEZER=y
- CONFIG_CGROUP_DEVICE=y
- CONFIG_CGROUP_CPUACCT=y
-@@ -56,8 +58,10 @@ CONFIG_MODULES=y
- CONFIG_MODULE_UNLOAD=y
- CONFIG_MODVERSIONS=y
- CONFIG_MODULE_SRCVERSION_ALL=y
-+CONFIG_BLK_DEV_THROTTLING=y
- CONFIG_PARTITION_ADVANCED=y
- CONFIG_MAC_PARTITION=y
-+CONFIG_CFQ_GROUP_IOSCHED=y
- CONFIG_BINFMT_MISC=m
- CONFIG_CLEANCACHE=y
- CONFIG_FRONTSWAP=y
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -13,6 +13,8 @@ CONFIG_TASK_XACCT=y
- CONFIG_TASK_IO_ACCOUNTING=y
- CONFIG_IKCONFIG=m
- CONFIG_IKCONFIG_PROC=y
-+CONFIG_MEMCG=y
-+CONFIG_BLK_CGROUP=y
- CONFIG_CGROUP_FREEZER=y
- CONFIG_CPUSETS=y
- CONFIG_CGROUP_DEVICE=y
-@@ -60,8 +62,10 @@ CONFIG_MODULES=y
- CONFIG_MODULE_UNLOAD=y
- CONFIG_MODVERSIONS=y
- CONFIG_MODULE_SRCVERSION_ALL=y
-+CONFIG_BLK_DEV_THROTTLING=y
- CONFIG_PARTITION_ADVANCED=y
- CONFIG_MAC_PARTITION=y
-+CONFIG_CFQ_GROUP_IOSCHED=y
- CONFIG_BINFMT_MISC=y
- CONFIG_CLEANCACHE=y
- CONFIG_FRONTSWAP=y
--- /dev/null
+From 12c14e45b31f60c1fd591d4aebbfcd7c2b730e67 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 29 Apr 2019 19:16:15 +0100
+Subject: [PATCH 435/725] Revert "staging: bcm2835-audio: Enable compile test"
+
+commit 4eae66777a262ac9707980ea0cfe902afadfb577 upstream.
+
+This reverts commit 02d205a57c4c943fc2a5b1ac7c912ce01944f700.
+---
+ drivers/staging/vc04_services/bcm2835-audio/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/Kconfig
++++ b/drivers/staging/vc04_services/bcm2835-audio/Kconfig
+@@ -1,6 +1,6 @@
+ config SND_BCM2835
+ tristate "BCM2835 Audio"
+- depends on (ARCH_BCM2835 || COMPILE_TEST) && SND
++ depends on ARCH_BCM2835 && SND
+ select SND_PCM
+ select BCM2835_VCHIQ
+ help
+++ /dev/null
-From 1c61854d266759522f33e59fb58de1cb9470d886 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Mon, 29 Apr 2019 19:35:33 +0200
-Subject: [PATCH 435/703] overlays: Add PiGlow overlay
-
-The PiGlow is a small add-on board for the Raspberry Pi that provides
-18 individually controllable LEDs (SN3218) and uses the following pins:
-
-P1 & P17 (3V3)
-P2 (5V)
-P3 (SDA)
-P5 (SCL)
-P14 (GND)
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- arch/arm/boot/dts/overlays/Makefile | 1 +
- arch/arm/boot/dts/overlays/README | 6 ++
- arch/arm/boot/dts/overlays/piglow-overlay.dts | 97 +++++++++++++++++++
- 3 files changed, 104 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/piglow-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -97,6 +97,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- pi3-disable-wifi.dtbo \
- pi3-miniuart-bt.dtbo \
- pibell.dtbo \
-+ piglow.dtbo \
- piscreen.dtbo \
- piscreen2r.dtbo \
- pisound.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1532,6 +1532,12 @@ Params: alsaname Set the
- "PiBell")
-
-
-+Name: piglow
-+Info: Configures the PiGlow by pimoroni.com
-+Load: dtoverlay=piglow
-+Params: <None>
-+
-+
- Name: piscreen
- Info: PiScreen display by OzzMaker.com
- Load: dtoverlay=piscreen,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/piglow-overlay.dts
-@@ -0,0 +1,97 @@
-+// Definitions for SN3218 LED driver from Si-En Technology on PiGlow
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+ compatible = "brcm,bcm2708";
-+
-+ fragment@0 {
-+ target = <&i2c_arm>;
-+ __overlay__ {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "okay";
-+
-+ sn3218@54 {
-+ compatible = "si-en,sn3218";
-+ reg = <0x54>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "okay";
-+
-+ led@1 {
-+ reg = <1>;
-+ label = "piglow:red:led1";
-+ };
-+ led@2 {
-+ reg = <2>;
-+ label = "piglow:orange:led2";
-+ };
-+ led@3 {
-+ reg = <3>;
-+ label = "piglow:yellow:led3";
-+ };
-+ led@4 {
-+ reg = <4>;
-+ label = "piglow:green:led4";
-+ };
-+ led@5 {
-+ reg = <5>;
-+ label = "piglow:blue:led5";
-+ };
-+ led@6 {
-+ reg = <6>;
-+ label = "piglow:green:led6";
-+ };
-+ led@7 {
-+ reg = <7>;
-+ label = "piglow:red:led7";
-+ };
-+ led@8 {
-+ reg = <8>;
-+ label = "piglow:orange:led8";
-+ };
-+ led@9 {
-+ reg = <9>;
-+ label = "piglow:yellow:led9";
-+ };
-+ led@10 {
-+ reg = <10>;
-+ label = "piglow:white:led10";
-+ };
-+ led@11 {
-+ reg = <11>;
-+ label = "piglow:white:led11";
-+ };
-+ led@12 {
-+ reg = <12>;
-+ label = "piglow:blue:led12";
-+ };
-+ led@13 {
-+ reg = <13>;
-+ label = "piglow:white:led13";
-+ };
-+ led@14 {
-+ reg = <14>;
-+ label = "piglow:green:led14";
-+ };
-+ led@15 {
-+ reg = <15>;
-+ label = "piglow:blue:led15";
-+ };
-+ led@16 {
-+ reg = <16>;
-+ label = "piglow:yellow:led16";
-+ };
-+ led@17 {
-+ reg = <17>;
-+ label = "piglow:orange:led17";
-+ };
-+ led@18 {
-+ reg = <18>;
-+ label = "piglow:red:led18";
-+ };
-+ };
-+ };
-+ };
-+};
--- /dev/null
+From fc06fbe84cdcd35d8be8775576f07c52ccdf8cd2 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 29 Apr 2019 19:16:16 +0100
+Subject: [PATCH 436/725] Revert "staging: bcm2835-audio: use
+ module_platform_driver() macro"
+
+commit ed4c2e5dc4216d5dded502bfcf594d3984e6bccd upstream.
+
+This reverts commit 786ced30fec053b27248ed5b24dcde61ed3f47f6.
+---
+ .../vc04_services/bcm2835-audio/bcm2835.c | 20 ++++++++++++++++++-
+ 1 file changed, 19 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -470,7 +470,25 @@ static struct platform_driver bcm2835_al
+ .of_match_table = snd_bcm2835_of_match_table,
+ },
+ };
+-module_platform_driver(bcm2835_alsa0_driver);
++
++static int bcm2835_alsa_device_init(void)
++{
++ int retval;
++
++ retval = platform_driver_register(&bcm2835_alsa0_driver);
++ if (retval)
++ pr_err("Error registering bcm2835_audio driver %d .\n", retval);
++
++ return retval;
++}
++
++static void bcm2835_alsa_device_exit(void)
++{
++ platform_driver_unregister(&bcm2835_alsa0_driver);
++}
++
++late_initcall(bcm2835_alsa_device_init);
++module_exit(bcm2835_alsa_device_exit);
+
+ MODULE_AUTHOR("Dom Cobley");
+ MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
+++ /dev/null
-From bf7d2a13c0617dd23e0a394bccd9b41b2295ead0 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Mon, 29 Apr 2019 19:28:51 +0200
-Subject: [PATCH 436/703] configs: enable LED driver for PiGlow
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- arch/arm64/configs/bcmrpi3_defconfig | 3 ++-
- 3 files changed, 4 insertions(+), 1 deletion(-)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -1131,6 +1131,7 @@ CONFIG_MMC_SPI=m
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
- CONFIG_LEDS_PCA963X=m
-+CONFIG_LEDS_IS31FL32XX=m
- CONFIG_LEDS_TRIGGER_TIMER=y
- CONFIG_LEDS_TRIGGER_ONESHOT=y
- CONFIG_LEDS_TRIGGER_HEARTBEAT=y
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -1124,6 +1124,7 @@ CONFIG_MMC_SPI=m
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
- CONFIG_LEDS_PCA963X=m
-+CONFIG_LEDS_IS31FL32XX=m
- CONFIG_LEDS_TRIGGER_TIMER=y
- CONFIG_LEDS_TRIGGER_ONESHOT=y
- CONFIG_LEDS_TRIGGER_HEARTBEAT=y
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -550,8 +550,8 @@ CONFIG_JOYSTICK_RPISENSE=m
- CONFIG_INPUT_TOUCHSCREEN=y
- CONFIG_TOUCHSCREEN_ADS7846=m
- CONFIG_TOUCHSCREEN_EGALAX=m
--CONFIG_TOUCHSCREEN_EKTF2127=m
- CONFIG_TOUCHSCREEN_ILI210X=m
-+CONFIG_TOUCHSCREEN_EKTF2127=m
- CONFIG_TOUCHSCREEN_RPI_FT5406=m
- CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
- CONFIG_TOUCHSCREEN_STMPE=m
-@@ -991,6 +991,7 @@ CONFIG_MMC_SPI=m
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
- CONFIG_LEDS_PCA963X=m
-+CONFIG_LEDS_IS31FL32XX=m
- CONFIG_LEDS_TRIGGER_TIMER=y
- CONFIG_LEDS_TRIGGER_ONESHOT=y
- CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+++ /dev/null
-From fe6afd9a110a042d2f00934b3a95ae57471f18cf Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Mon, 29 Apr 2019 19:16:14 +0100
-Subject: [PATCH 437/703] Revert "bcm2835: interpolate audio delay"
-
-commit fb4b9f02986fcb5ae751106ef9b027806b5dd750 upstream.
-
-This reverts commit fb8cc99f05687ca5565dc53a7ee0dd86aefad952.
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 12 +-----------
- .../staging/vc04_services/bcm2835-audio/bcm2835.h | 1 -
- 2 files changed, 1 insertion(+), 12 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -11,7 +11,7 @@
- /* hardware definition */
- static const 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 | SNDRV_PCM_INFO_BATCH),
-+ 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,
-@@ -81,8 +81,6 @@ void bcm2835_playback_fifo(struct bcm283
- alsa_stream->pos %= alsa_stream->buffer_size;
- }
-
-- alsa_stream->interpolate_start = ktime_get_ns();
--
- if (alsa_stream->substream) {
- if (new_period)
- snd_pcm_period_elapsed(alsa_stream->substream);
-@@ -308,7 +306,6 @@ static int snd_bcm2835_pcm_prepare(struc
- alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
- alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
- alsa_stream->pos = 0;
-- alsa_stream->interpolate_start = ktime_get_ns();
-
- audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n",
- alsa_stream->buffer_size, alsa_stream->period_size,
-@@ -400,19 +397,12 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
- {
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
-- u64 now = ktime_get_ns();
-
- 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);
-
-- /* Give userspace better delay reporting by interpolating between GPU
-- * notifications, assuming audio speed is close enough to the clock
-- * used for ktime */
-- if (alsa_stream->interpolate_start && alsa_stream->interpolate_start < now)
-- runtime->delay = -(int)div_u64((now - alsa_stream->interpolate_start) * runtime->rate, 1000000000);
--
- return snd_pcm_indirect_playback_pointer(substream,
- &alsa_stream->pcm_indirect,
- alsa_stream->pos);
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -133,7 +133,6 @@ struct bcm2835_alsa_stream {
- unsigned int pos;
- unsigned int buffer_size;
- unsigned int period_size;
-- u64 interpolate_start;
-
- atomic_t retrieved;
- struct bcm2835_audio_instance *instance;
--- /dev/null
+From 2dc2366eddba3b7a59d1f19b7ce13f7a52574d63 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:30 +0200
+Subject: [PATCH 437/725] staging: bcm2835-audio: Clean up mutex locks
+
+commit ce4bb1aa271a97047b80ac917a5d91b54925913b upstream.
+
+snd-bcm2835 driver takes the lock with mutex_lock_interruptible() in
+all places, which don't make sense. Replace them with the simple
+mutex_lock().
+
+Also taking a mutex lock right after creating it for each PCM object
+is nonsense, too. It cannot be racy at that point. We can get rid of
+it.
+
+Last but not least, initializing chip->audio_mutex at each place is
+error-prone. Initialize properly at creating the chip object in
+snd_bcm2835_create() instead.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 18 +++----
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 33 ++-----------
+ .../bcm2835-audio/bcm2835-vchiq.c | 47 ++++---------------
+ .../vc04_services/bcm2835-audio/bcm2835.c | 1 +
+ 4 files changed, 20 insertions(+), 79 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
+@@ -77,8 +77,7 @@ static int snd_bcm2835_ctl_get(struct sn
+ {
+ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
+
+- if (mutex_lock_interruptible(&chip->audio_mutex))
+- return -EINTR;
++ mutex_lock(&chip->audio_mutex);
+
+ BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));
+
+@@ -99,8 +98,7 @@ static int snd_bcm2835_ctl_put(struct sn
+ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
+ int changed = 0;
+
+- if (mutex_lock_interruptible(&chip->audio_mutex))
+- return -EINTR;
++ mutex_lock(&chip->audio_mutex);
+
+ 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]);
+@@ -187,8 +185,7 @@ static int snd_bcm2835_spdif_default_get
+ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
+ int i;
+
+- if (mutex_lock_interruptible(&chip->audio_mutex))
+- return -EINTR;
++ mutex_lock(&chip->audio_mutex);
+
+ for (i = 0; i < 4; i++)
+ ucontrol->value.iec958.status[i] =
+@@ -205,8 +202,7 @@ static int snd_bcm2835_spdif_default_put
+ unsigned int val = 0;
+ int i, change;
+
+- if (mutex_lock_interruptible(&chip->audio_mutex))
+- return -EINTR;
++ mutex_lock(&chip->audio_mutex);
+
+ for (i = 0; i < 4; i++)
+ val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
+@@ -251,8 +247,7 @@ static int snd_bcm2835_spdif_stream_get(
+ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
+ int i;
+
+- if (mutex_lock_interruptible(&chip->audio_mutex))
+- return -EINTR;
++ mutex_lock(&chip->audio_mutex);
+
+ for (i = 0; i < 4; i++)
+ ucontrol->value.iec958.status[i] =
+@@ -269,8 +264,7 @@ static int snd_bcm2835_spdif_stream_put(
+ unsigned int val = 0;
+ int i, change;
+
+- if (mutex_lock_interruptible(&chip->audio_mutex))
+- return -EINTR;
++ mutex_lock(&chip->audio_mutex);
+
+ for (i = 0; i < 4; i++)
+ val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -99,10 +99,7 @@ static int snd_bcm2835_playback_open_gen
+ int idx;
+ int err;
+
+- if (mutex_lock_interruptible(&chip->audio_mutex)) {
+- audio_error("Interrupted whilst waiting for lock\n");
+- return -EINTR;
+- }
++ mutex_lock(&chip->audio_mutex);
+ audio_info("Alsa open (%d)\n", substream->number);
+ idx = substream->number;
+
+@@ -194,10 +191,7 @@ static int snd_bcm2835_playback_close(st
+ struct bcm2835_alsa_stream *alsa_stream;
+
+ chip = snd_pcm_substream_chip(substream);
+- if (mutex_lock_interruptible(&chip->audio_mutex)) {
+- audio_error("Interrupted whilst waiting for lock\n");
+- return -EINTR;
+- }
++ mutex_lock(&chip->audio_mutex);
+ runtime = substream->runtime;
+ alsa_stream = runtime->private_data;
+
+@@ -274,8 +268,7 @@ static int snd_bcm2835_pcm_prepare(struc
+ int channels;
+ int err;
+
+- if (mutex_lock_interruptible(&chip->audio_mutex))
+- return -EINTR;
++ mutex_lock(&chip->audio_mutex);
+
+ /* notify the vchiq that it should enter spdif passthrough mode by
+ * setting channels=0 (see
+@@ -449,14 +442,9 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
+ struct snd_pcm *pcm;
+ int err;
+
+- 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, numchannels, 0, &pcm);
+ if (err < 0)
+- goto out;
++ return err;
+ pcm->private_data = chip;
+ strcpy(pcm->name, "bcm2835 ALSA");
+ chip->pcm = pcm;
+@@ -474,9 +462,6 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
+ snd_bcm2835_playback_hw.buffer_bytes_max,
+ snd_bcm2835_playback_hw.buffer_bytes_max);
+
+-out:
+- mutex_unlock(&chip->audio_mutex);
+-
+ return 0;
+ }
+
+@@ -485,13 +470,9 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
+ struct snd_pcm *pcm;
+ int err;
+
+- 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;
++ return err;
+
+ pcm->private_data = chip;
+ strcpy(pcm->name, "bcm2835 IEC958/HDMI");
+@@ -504,8 +485,6 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
+ 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);
+
+ return 0;
+ }
+@@ -518,8 +497,6 @@ int snd_bcm2835_new_simple_pcm(struct bc
+ struct snd_pcm *pcm;
+ int err;
+
+- mutex_init(&chip->audio_mutex);
+-
+ err = snd_pcm_new(chip->card, name, 0, numchannels,
+ 0, &pcm);
+ if (err)
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -319,11 +319,7 @@ static int vc_vchi_audio_deinit(struct b
+ }
+
+ 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;
+- }
++ mutex_lock(&instance->vchi_mutex);
+
+ /* Close all VCHI service connections */
+ for (i = 0; i < instance->num_connections; i++) {
+@@ -434,11 +430,7 @@ int bcm2835_audio_open(struct bcm2835_al
+ 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);
+- ret = -EINTR;
+- goto free_wq;
+- }
++ mutex_lock(&instance->vchi_mutex);
+ vchi_service_use(instance->vchi_handle[0]);
+
+ m.type = VC_AUDIO_MSG_TYPE_OPEN;
+@@ -479,11 +471,7 @@ static int bcm2835_audio_set_ctls_chan(s
+ 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;
+- }
++ mutex_lock(&instance->vchi_mutex);
+ vchi_service_use(instance->vchi_handle[0]);
+
+ instance->result = -1;
+@@ -569,10 +557,7 @@ int bcm2835_audio_set_params(struct bcm2
+ return -EINVAL;
+ }
+
+- if (mutex_lock_interruptible(&instance->vchi_mutex)) {
+- LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance->num_connections);
+- return -EINTR;
+- }
++ mutex_lock(&instance->vchi_mutex);
+ vchi_service_use(instance->vchi_handle[0]);
+
+ instance->result = -1;
+@@ -629,11 +614,7 @@ static int bcm2835_audio_start_worker(st
+ int status;
+ int ret;
+
+- if (mutex_lock_interruptible(&instance->vchi_mutex)) {
+- LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
+- instance->num_connections);
+- return -EINTR;
+- }
++ mutex_lock(&instance->vchi_mutex);
+ vchi_service_use(instance->vchi_handle[0]);
+
+ m.type = VC_AUDIO_MSG_TYPE_START;
+@@ -665,11 +646,7 @@ static int bcm2835_audio_stop_worker(str
+ int status;
+ int ret;
+
+- if (mutex_lock_interruptible(&instance->vchi_mutex)) {
+- LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
+- instance->num_connections);
+- return -EINTR;
+- }
++ mutex_lock(&instance->vchi_mutex);
+ vchi_service_use(instance->vchi_handle[0]);
+
+ m.type = VC_AUDIO_MSG_TYPE_STOP;
+@@ -704,11 +681,7 @@ int bcm2835_audio_close(struct bcm2835_a
+
+ 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;
+- }
++ mutex_lock(&instance->vchi_mutex);
+ vchi_service_use(instance->vchi_handle[0]);
+
+ m.type = VC_AUDIO_MSG_TYPE_CLOSE;
+@@ -761,11 +734,7 @@ static int bcm2835_audio_write_worker(st
+
+ 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;
+- }
++ mutex_lock(&instance->vchi_mutex);
+ vchi_service_use(instance->vchi_handle[0]);
+
+ if (instance->peer_version == 0 &&
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -149,6 +149,7 @@ static int snd_bcm2835_create(struct snd
+ return -ENOMEM;
+
+ chip->card = card;
++ mutex_init(&chip->audio_mutex);
+
+ chip->vchi_ctx = devres_find(card->dev->parent,
+ bcm2835_devm_free_vchi_ctx, NULL, NULL);
+++ /dev/null
-From 5776c86dca6b3bc3c96d28514b1c5b398c7c6b8f Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Mon, 29 Apr 2019 19:16:15 +0100
-Subject: [PATCH 438/703] Revert "staging: bcm2835-audio: Enable compile test"
-
-commit 4eae66777a262ac9707980ea0cfe902afadfb577 upstream.
-
-This reverts commit 02d205a57c4c943fc2a5b1ac7c912ce01944f700.
----
- drivers/staging/vc04_services/bcm2835-audio/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/Kconfig
-+++ b/drivers/staging/vc04_services/bcm2835-audio/Kconfig
-@@ -1,6 +1,6 @@
- config SND_BCM2835
- tristate "BCM2835 Audio"
-- depends on (ARCH_BCM2835 || COMPILE_TEST) && SND
-+ depends on ARCH_BCM2835 && SND
- select SND_PCM
- select BCM2835_VCHIQ
- help
--- /dev/null
+From b44bb742007c7ef0b6507a3573dfca716192c200 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:31 +0200
+Subject: [PATCH 438/725] staging: bcm2835-audio: Remove redundant spdif stream
+ ctls
+
+commit ab91e26229eaca2832df51e13c1285aea3be33ab upstream.
+
+The "IEC958 Playback Stream" control does basically the very same
+thing as "IEC958 Playback Default" redundantly. The former should
+have been stream-specific and restored after closing the stream, but
+we don't do in that way.
+
+Since it's nothing but confusion, remove this fake.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 51 -------------------
+ 1 file changed, 51 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
+@@ -233,48 +233,6 @@ static int snd_bcm2835_spdif_mask_get(st
+ 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;
+-
+- mutex_lock(&chip->audio_mutex);
+-
+- 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;
+-
+- mutex_lock(&chip->audio_mutex);
+-
+- 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,
+@@ -290,15 +248,6 @@ static struct snd_kcontrol_new snd_bcm28
+ .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(struct bcm2835_chip *chip)
+++ /dev/null
-From f1137241f30689ffe38dd414c73f0b17bf08ecc8 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Mon, 29 Apr 2019 19:16:16 +0100
-Subject: [PATCH 439/703] Revert "staging: bcm2835-audio: use
- module_platform_driver() macro"
-
-commit ed4c2e5dc4216d5dded502bfcf594d3984e6bccd upstream.
-
-This reverts commit 786ced30fec053b27248ed5b24dcde61ed3f47f6.
----
- .../vc04_services/bcm2835-audio/bcm2835.c | 20 ++++++++++++++++++-
- 1 file changed, 19 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -470,7 +470,25 @@ static struct platform_driver bcm2835_al
- .of_match_table = snd_bcm2835_of_match_table,
- },
- };
--module_platform_driver(bcm2835_alsa0_driver);
-+
-+static int bcm2835_alsa_device_init(void)
-+{
-+ int retval;
-+
-+ retval = platform_driver_register(&bcm2835_alsa0_driver);
-+ if (retval)
-+ pr_err("Error registering bcm2835_audio driver %d .\n", retval);
-+
-+ return retval;
-+}
-+
-+static void bcm2835_alsa_device_exit(void)
-+{
-+ platform_driver_unregister(&bcm2835_alsa0_driver);
-+}
-+
-+late_initcall(bcm2835_alsa_device_init);
-+module_exit(bcm2835_alsa_device_exit);
-
- MODULE_AUTHOR("Dom Cobley");
- MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
--- /dev/null
+From 62a36a18cad14a7a262c8e5f4bbce3db01aa35e1 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:32 +0200
+Subject: [PATCH 439/725] staging: bcm2835-audio: Clean up include files in
+ bcm2835-ctl.c
+
+commit 821950d3da4bf97bcfedcb812176a0f26b833db0 upstream.
+
+Only a few of them are really needed.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 15 ---------------
+ 1 file changed, 15 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
+@@ -1,23 +1,8 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /* Copyright 2011 Broadcom Corporation. All rights reserved. */
+
+-#include <linux/platform_device.h>
+-#include <linux/init.h>
+-#include <linux/io.h>
+-#include <linux/jiffies.h>
+-#include <linux/slab.h>
+-#include <linux/time.h>
+-#include <linux/wait.h>
+-#include <linux/delay.h>
+-#include <linux/moduleparam.h>
+-#include <linux/sched.h>
+-
+ #include <sound/core.h>
+ #include <sound/control.h>
+-#include <sound/pcm.h>
+-#include <sound/pcm_params.h>
+-#include <sound/rawmidi.h>
+-#include <sound/initval.h>
+ #include <sound/tlv.h>
+ #include <sound/asoundef.h>
+
+++ /dev/null
-From 8fa93d6fee921789b90a1b3be272366df36e026e Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:30 +0200
-Subject: [PATCH 440/703] staging: bcm2835-audio: Clean up mutex locks
-
-commit ce4bb1aa271a97047b80ac917a5d91b54925913b upstream.
-
-snd-bcm2835 driver takes the lock with mutex_lock_interruptible() in
-all places, which don't make sense. Replace them with the simple
-mutex_lock().
-
-Also taking a mutex lock right after creating it for each PCM object
-is nonsense, too. It cannot be racy at that point. We can get rid of
-it.
-
-Last but not least, initializing chip->audio_mutex at each place is
-error-prone. Initialize properly at creating the chip object in
-snd_bcm2835_create() instead.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 18 +++----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 33 ++-----------
- .../bcm2835-audio/bcm2835-vchiq.c | 47 ++++---------------
- .../vc04_services/bcm2835-audio/bcm2835.c | 1 +
- 4 files changed, 20 insertions(+), 79 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-@@ -77,8 +77,7 @@ static int snd_bcm2835_ctl_get(struct sn
- {
- struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
-
-- if (mutex_lock_interruptible(&chip->audio_mutex))
-- return -EINTR;
-+ mutex_lock(&chip->audio_mutex);
-
- BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));
-
-@@ -99,8 +98,7 @@ static int snd_bcm2835_ctl_put(struct sn
- struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
- int changed = 0;
-
-- if (mutex_lock_interruptible(&chip->audio_mutex))
-- return -EINTR;
-+ mutex_lock(&chip->audio_mutex);
-
- 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]);
-@@ -187,8 +185,7 @@ static int snd_bcm2835_spdif_default_get
- struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
- int i;
-
-- if (mutex_lock_interruptible(&chip->audio_mutex))
-- return -EINTR;
-+ mutex_lock(&chip->audio_mutex);
-
- for (i = 0; i < 4; i++)
- ucontrol->value.iec958.status[i] =
-@@ -205,8 +202,7 @@ static int snd_bcm2835_spdif_default_put
- unsigned int val = 0;
- int i, change;
-
-- if (mutex_lock_interruptible(&chip->audio_mutex))
-- return -EINTR;
-+ mutex_lock(&chip->audio_mutex);
-
- for (i = 0; i < 4; i++)
- val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
-@@ -251,8 +247,7 @@ static int snd_bcm2835_spdif_stream_get(
- struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
- int i;
-
-- if (mutex_lock_interruptible(&chip->audio_mutex))
-- return -EINTR;
-+ mutex_lock(&chip->audio_mutex);
-
- for (i = 0; i < 4; i++)
- ucontrol->value.iec958.status[i] =
-@@ -269,8 +264,7 @@ static int snd_bcm2835_spdif_stream_put(
- unsigned int val = 0;
- int i, change;
-
-- if (mutex_lock_interruptible(&chip->audio_mutex))
-- return -EINTR;
-+ mutex_lock(&chip->audio_mutex);
-
- for (i = 0; i < 4; i++)
- val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -99,10 +99,7 @@ static int snd_bcm2835_playback_open_gen
- int idx;
- int err;
-
-- if (mutex_lock_interruptible(&chip->audio_mutex)) {
-- audio_error("Interrupted whilst waiting for lock\n");
-- return -EINTR;
-- }
-+ mutex_lock(&chip->audio_mutex);
- audio_info("Alsa open (%d)\n", substream->number);
- idx = substream->number;
-
-@@ -194,10 +191,7 @@ static int snd_bcm2835_playback_close(st
- struct bcm2835_alsa_stream *alsa_stream;
-
- chip = snd_pcm_substream_chip(substream);
-- if (mutex_lock_interruptible(&chip->audio_mutex)) {
-- audio_error("Interrupted whilst waiting for lock\n");
-- return -EINTR;
-- }
-+ mutex_lock(&chip->audio_mutex);
- runtime = substream->runtime;
- alsa_stream = runtime->private_data;
-
-@@ -274,8 +268,7 @@ static int snd_bcm2835_pcm_prepare(struc
- int channels;
- int err;
-
-- if (mutex_lock_interruptible(&chip->audio_mutex))
-- return -EINTR;
-+ mutex_lock(&chip->audio_mutex);
-
- /* notify the vchiq that it should enter spdif passthrough mode by
- * setting channels=0 (see
-@@ -449,14 +442,9 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
- struct snd_pcm *pcm;
- int err;
-
-- 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, numchannels, 0, &pcm);
- if (err < 0)
-- goto out;
-+ return err;
- pcm->private_data = chip;
- strcpy(pcm->name, "bcm2835 ALSA");
- chip->pcm = pcm;
-@@ -474,9 +462,6 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
- snd_bcm2835_playback_hw.buffer_bytes_max,
- snd_bcm2835_playback_hw.buffer_bytes_max);
-
--out:
-- mutex_unlock(&chip->audio_mutex);
--
- return 0;
- }
-
-@@ -485,13 +470,9 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
- struct snd_pcm *pcm;
- int err;
-
-- 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;
-+ return err;
-
- pcm->private_data = chip;
- strcpy(pcm->name, "bcm2835 IEC958/HDMI");
-@@ -504,8 +485,6 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
- 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);
-
- return 0;
- }
-@@ -518,8 +497,6 @@ int snd_bcm2835_new_simple_pcm(struct bc
- struct snd_pcm *pcm;
- int err;
-
-- mutex_init(&chip->audio_mutex);
--
- err = snd_pcm_new(chip->card, name, 0, numchannels,
- 0, &pcm);
- if (err)
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -319,11 +319,7 @@ static int vc_vchi_audio_deinit(struct b
- }
-
- 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;
-- }
-+ mutex_lock(&instance->vchi_mutex);
-
- /* Close all VCHI service connections */
- for (i = 0; i < instance->num_connections; i++) {
-@@ -434,11 +430,7 @@ int bcm2835_audio_open(struct bcm2835_al
- 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);
-- ret = -EINTR;
-- goto free_wq;
-- }
-+ mutex_lock(&instance->vchi_mutex);
- vchi_service_use(instance->vchi_handle[0]);
-
- m.type = VC_AUDIO_MSG_TYPE_OPEN;
-@@ -479,11 +471,7 @@ static int bcm2835_audio_set_ctls_chan(s
- 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;
-- }
-+ mutex_lock(&instance->vchi_mutex);
- vchi_service_use(instance->vchi_handle[0]);
-
- instance->result = -1;
-@@ -569,10 +557,7 @@ int bcm2835_audio_set_params(struct bcm2
- return -EINVAL;
- }
-
-- if (mutex_lock_interruptible(&instance->vchi_mutex)) {
-- LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance->num_connections);
-- return -EINTR;
-- }
-+ mutex_lock(&instance->vchi_mutex);
- vchi_service_use(instance->vchi_handle[0]);
-
- instance->result = -1;
-@@ -629,11 +614,7 @@ static int bcm2835_audio_start_worker(st
- int status;
- int ret;
-
-- if (mutex_lock_interruptible(&instance->vchi_mutex)) {
-- LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
-- instance->num_connections);
-- return -EINTR;
-- }
-+ mutex_lock(&instance->vchi_mutex);
- vchi_service_use(instance->vchi_handle[0]);
-
- m.type = VC_AUDIO_MSG_TYPE_START;
-@@ -665,11 +646,7 @@ static int bcm2835_audio_stop_worker(str
- int status;
- int ret;
-
-- if (mutex_lock_interruptible(&instance->vchi_mutex)) {
-- LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",
-- instance->num_connections);
-- return -EINTR;
-- }
-+ mutex_lock(&instance->vchi_mutex);
- vchi_service_use(instance->vchi_handle[0]);
-
- m.type = VC_AUDIO_MSG_TYPE_STOP;
-@@ -704,11 +681,7 @@ int bcm2835_audio_close(struct bcm2835_a
-
- 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;
-- }
-+ mutex_lock(&instance->vchi_mutex);
- vchi_service_use(instance->vchi_handle[0]);
-
- m.type = VC_AUDIO_MSG_TYPE_CLOSE;
-@@ -761,11 +734,7 @@ static int bcm2835_audio_write_worker(st
-
- 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;
-- }
-+ mutex_lock(&instance->vchi_mutex);
- vchi_service_use(instance->vchi_handle[0]);
-
- if (instance->peer_version == 0 &&
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -149,6 +149,7 @@ static int snd_bcm2835_create(struct snd
- return -ENOMEM;
-
- chip->card = card;
-+ mutex_init(&chip->audio_mutex);
-
- chip->vchi_ctx = devres_find(card->dev->parent,
- bcm2835_devm_free_vchi_ctx, NULL, NULL);
--- /dev/null
+From 176ca4daf9b956adbdb6846a457053db375d3954 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:33 +0200
+Subject: [PATCH 440/725] staging: bcm2835-audio: Remove redundant substream
+ mask checks
+
+commit 14b1f4cba853a11c7b381ad919622f38eb194bd7 upstream.
+
+The avail_substreams bit mask is checked for the possible racy
+accesses, but this cannot happen in practice; i.e. the assignment and
+the check are superfluous.
+
+Let's rip them off.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 2 --
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 8 --------
+ .../vc04_services/bcm2835-audio/bcm2835-vchiq.c | 17 +++++++----------
+ .../vc04_services/bcm2835-audio/bcm2835.c | 5 +----
+ .../vc04_services/bcm2835-audio/bcm2835.h | 2 --
+ 5 files changed, 8 insertions(+), 26 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
+@@ -64,8 +64,6 @@ static int snd_bcm2835_ctl_get(struct sn
+
+ mutex_lock(&chip->audio_mutex);
+
+- 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)
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -118,14 +118,6 @@ static int snd_bcm2835_playback_open_gen
+ 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(*alsa_stream), GFP_KERNEL);
+ if (!alsa_stream) {
+ err = -ENOMEM;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -523,16 +523,13 @@ int bcm2835_audio_set_ctls(struct bcm283
+
+ /* 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(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);
+- }
++ if (!chip->alsa_stream[i])
++ continue;
++ if (bcm2835_audio_set_ctls_chan(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);
+ }
+ }
+ return ret;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -280,7 +280,7 @@ static int snd_add_child_device(struct d
+ struct snd_card *card;
+ struct device *child;
+ struct bcm2835_chip *chip;
+- int err, i;
++ int err;
+
+ child = snd_create_device(device, &audio_driver->driver,
+ audio_driver->driver.name);
+@@ -325,9 +325,6 @@ static int snd_add_child_device(struct d
+ return err;
+ }
+
+- for (i = 0; i < numchans; i++)
+- chip->avail_substreams |= (1 << i);
+-
+ err = snd_card_register(card);
+ if (err) {
+ dev_err(child, "Failed to register card, error %d\n", err);
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -98,8 +98,6 @@ struct bcm2835_chip {
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm *pcm_spdif;
+- /* Bitmat for valid reg_base and irq numbers */
+- unsigned int avail_substreams;
+ struct device *dev;
+ struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS];
+
--- /dev/null
+From a51b0db4416ffc832c98adbe815337c8f1c1d47e Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:34 +0200
+Subject: [PATCH 441/725] staging: bcm2835-audio: Fix mute controls, volume
+ handling cleanup
+
+commit 495e5a0d83d3902c741771f267a702ae19da8ab6 upstream.
+
+In the current code, the mute control is dealt in a special manner,
+modifying the current volume and saving the old volume, etc. This is
+inconsistent (e.g. change the volume while muted, then unmute), and
+way too complex.
+
+Also, the whole volume handling code has conversion between ALSA
+volume and raw volume values, which can lead to another
+inconsistency and complexity.
+
+This patch simplifies these points:
+- The ALSA volume value is saved in chip->volume
+- volume->mute saves the mute state
+- The mute state is evaluated only when the actual volume is passed to
+ the hardware, bcm2835_audio_set_ctls()
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 84 +++++++------------
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 6 +-
+ .../bcm2835-audio/bcm2835-vchiq.c | 32 ++-----
+ .../vc04_services/bcm2835-audio/bcm2835.h | 5 +-
+ 4 files changed, 45 insertions(+), 82 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
+@@ -12,6 +12,21 @@
+ #define CTRL_VOL_MAX 400
+ #define CTRL_VOL_MIN -10239 /* originally -10240 */
+
++static int bcm2835_audio_set_chip_ctls(struct bcm2835_chip *chip)
++{
++ int i, err = 0;
++
++ /* change ctls for all substreams */
++ for (i = 0; i < MAX_SUBSTREAMS; i++) {
++ if (chip->alsa_stream[i]) {
++ err = bcm2835_audio_set_ctls(chip->alsa_stream[i]);
++ if (err < 0)
++ break;
++ }
++ }
++ return err;
++}
++
+ static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+ {
+@@ -34,29 +49,6 @@ static int snd_bcm2835_ctl_info(struct s
+ 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)
+ {
+@@ -65,7 +57,7 @@ static int snd_bcm2835_ctl_get(struct sn
+ mutex_lock(&chip->audio_mutex);
+
+ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
+- ucontrol->value.integer.value[0] = chip2alsa(chip->volume);
++ ucontrol->value.integer.value[0] = chip->volume;
+ else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
+ ucontrol->value.integer.value[0] = chip->mute;
+ else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
+@@ -79,38 +71,26 @@ static int snd_bcm2835_ctl_put(struct sn
+ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
++ int val, *valp;
+ int changed = 0;
+
+- mutex_lock(&chip->audio_mutex);
+-
+- 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]);
++ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
++ valp = &chip->volume;
++ else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
++ valp = &chip->mute;
++ else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
++ valp = &chip->dest;
++ else
++ return -EINVAL;
+
+- } 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;
+- }
++ val = ucontrol->value.integer.value[0];
++ mutex_lock(&chip->audio_mutex);
++ if (val != *valp) {
++ *valp = val;
++ changed = 1;
++ if (bcm2835_audio_set_chip_ctls(chip))
++ dev_err(chip->card->dev, "Failed to set ALSA controls..\n");
+ }
+-
+- if (changed && bcm2835_audio_set_ctls(chip))
+- dev_err(chip->card->dev, "Failed to set ALSA controls..\n");
+-
+-unlock:
+ mutex_unlock(&chip->audio_mutex);
+ return changed;
+ }
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -280,7 +280,7 @@ static int snd_bcm2835_pcm_prepare(struc
+ 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);
++ bcm2835_audio_set_ctls(alsa_stream);
+
+ memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
+
+@@ -441,7 +441,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
+ strcpy(pcm->name, "bcm2835 ALSA");
+ chip->pcm = pcm;
+ chip->dest = AUDIO_DEST_AUTO;
+- chip->volume = alsa2chip(0);
++ chip->volume = 0;
+ chip->mute = CTRL_VOL_UNMUTE; /*disable mute on startup */
+ /* set operators */
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+@@ -498,7 +498,7 @@ int snd_bcm2835_new_simple_pcm(struct bc
+ strcpy(pcm->name, name);
+ chip->pcm = pcm;
+ chip->dest = route;
+- chip->volume = alsa2chip(0);
++ chip->volume = 0;
+ chip->mute = CTRL_VOL_UNMUTE;
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -460,11 +460,11 @@ free_wq:
+ return ret;
+ }
+
+-static int bcm2835_audio_set_ctls_chan(struct bcm2835_alsa_stream *alsa_stream,
+- struct bcm2835_chip *chip)
++int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream)
+ {
+ struct vc_audio_msg m;
+ struct bcm2835_audio_instance *instance = alsa_stream->instance;
++ struct bcm2835_chip *chip = alsa_stream->chip;
+ int status;
+ int ret;
+
+@@ -478,7 +478,10 @@ static int bcm2835_audio_set_ctls_chan(s
+
+ m.type = VC_AUDIO_MSG_TYPE_CONTROL;
+ m.u.control.dest = chip->dest;
+- m.u.control.volume = chip->volume;
++ if (!chip->mute)
++ m.u.control.volume = CHIP_MIN_VOLUME;
++ else
++ m.u.control.volume = alsa2chip(chip->volume);
+
+ /* Create the message available completion */
+ init_completion(&instance->msg_avail_comp);
+@@ -514,27 +517,6 @@ unlock:
+ return ret;
+ }
+
+-int bcm2835_audio_set_ctls(struct bcm2835_chip *chip)
+-{
+- int i;
+- int ret = 0;
+-
+- 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->alsa_stream[i])
+- continue;
+- if (bcm2835_audio_set_ctls_chan(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);
+- }
+- }
+- return ret;
+-}
+-
+ int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
+ unsigned int channels, unsigned int samplerate,
+ unsigned int bps)
+@@ -548,7 +530,7 @@ int bcm2835_audio_set_params(struct bcm2
+ 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);
++ ret = bcm2835_audio_set_ctls(alsa_stream);
+ if (ret) {
+ LOG_ERR(" Alsa controls not supported\n");
+ return -EINVAL;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -74,6 +74,8 @@ enum {
+ // convert chip to alsa volume
+ #define chip2alsa(vol) -(((vol) * 100) >> 8)
+
++#define CHIP_MIN_VOLUME 26214 /* minimum level aka mute */
++
+ /* Some constants for values .. */
+ enum snd_bcm2835_route {
+ AUDIO_DEST_AUTO = 0,
+@@ -102,7 +104,6 @@ struct bcm2835_chip {
+ struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS];
+
+ int volume;
+- int old_volume; /* stores the volume value whist muted */
+ int dest;
+ int mute;
+
+@@ -160,7 +161,7 @@ int bcm2835_audio_set_params(struct bcm2
+ int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream);
+-int bcm2835_audio_set_ctls(struct bcm2835_chip *chip);
++int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
+ unsigned int count,
+ void *src);
+++ /dev/null
-From 5171b87bdf5a98d8d24f9fd7a5f3b6304e8ce5ad Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:31 +0200
-Subject: [PATCH 441/703] staging: bcm2835-audio: Remove redundant spdif stream
- ctls
-
-commit ab91e26229eaca2832df51e13c1285aea3be33ab upstream.
-
-The "IEC958 Playback Stream" control does basically the very same
-thing as "IEC958 Playback Default" redundantly. The former should
-have been stream-specific and restored after closing the stream, but
-we don't do in that way.
-
-Since it's nothing but confusion, remove this fake.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 51 -------------------
- 1 file changed, 51 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-@@ -233,48 +233,6 @@ static int snd_bcm2835_spdif_mask_get(st
- 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;
--
-- mutex_lock(&chip->audio_mutex);
--
-- 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;
--
-- mutex_lock(&chip->audio_mutex);
--
-- 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,
-@@ -290,15 +248,6 @@ static struct snd_kcontrol_new snd_bcm28
- .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(struct bcm2835_chip *chip)
+++ /dev/null
-From eaa6771ead56c4388b41740e502b652912423d65 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:32 +0200
-Subject: [PATCH 442/703] staging: bcm2835-audio: Clean up include files in
- bcm2835-ctl.c
-
-commit 821950d3da4bf97bcfedcb812176a0f26b833db0 upstream.
-
-Only a few of them are really needed.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 15 ---------------
- 1 file changed, 15 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-@@ -1,23 +1,8 @@
- // SPDX-License-Identifier: GPL-2.0
- /* Copyright 2011 Broadcom Corporation. All rights reserved. */
-
--#include <linux/platform_device.h>
--#include <linux/init.h>
--#include <linux/io.h>
--#include <linux/jiffies.h>
--#include <linux/slab.h>
--#include <linux/time.h>
--#include <linux/wait.h>
--#include <linux/delay.h>
--#include <linux/moduleparam.h>
--#include <linux/sched.h>
--
- #include <sound/core.h>
- #include <sound/control.h>
--#include <sound/pcm.h>
--#include <sound/pcm_params.h>
--#include <sound/rawmidi.h>
--#include <sound/initval.h>
- #include <sound/tlv.h>
- #include <sound/asoundef.h>
-
--- /dev/null
+From 641b5ca89295f0cdb0990a2d7b866200643c6a8d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:35 +0200
+Subject: [PATCH 442/725] staging: bcm2835-audio: Remove redundant function
+ calls
+
+commit 124950ebe9fa8547c59e8d4acc8d6c59e6278ed6 upstream.
+
+bcm2835_audio_setup(), bcm2835_audio_flush_buffers() and
+bcm2835_audio_flush_playback_buffers() functions do implement
+nothing.
+
+Also, bcm2835_audio_set_ctls() is already called inside
+bcm2835_audio_set_params(), so the later call is superfluous.
+
+This patch removes these superfluous implementations.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 5 -----
+ .../bcm2835-audio/bcm2835-vchiq.c | 21 -------------------
+ .../vc04_services/bcm2835-audio/bcm2835.h | 3 ---
+ 3 files changed, 29 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -277,11 +277,6 @@ static int snd_bcm2835_pcm_prepare(struc
+ 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);
+-
+ memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
+
+ alsa_stream->pcm_indirect.hw_buffer_size =
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -580,12 +580,6 @@ unlock:
+ return ret;
+ }
+
+-int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream)
+-{
+-
+- return 0;
+-}
+-
+ static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream)
+ {
+ struct vc_audio_msg m;
+@@ -774,21 +768,6 @@ unlock:
+ return ret;
+ }
+
+-/**
+- * Returns all buffers from arm->vc
+- */
+-void bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream *alsa_stream)
+-{
+-}
+-
+-/**
+- * Forces VC to flush(drop) its filled playback buffers and
+- * return them the us. (VC->ARM)
+- */
+-void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream *alsa_stream)
+-{
+-}
+-
+ unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream)
+ {
+ unsigned int count = atomic_read(&alsa_stream->retrieved);
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -158,7 +158,6 @@ int bcm2835_audio_close(struct bcm2835_a
+ int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
+ unsigned int channels, unsigned int samplerate,
+ unsigned int bps);
+-int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream);
+@@ -167,7 +166,5 @@ int bcm2835_audio_write(struct bcm2835_a
+ void *src);
+ void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream);
+ unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream);
+-void bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream *alsa_stream);
+-void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream *alsa_stream);
+
+ #endif /* __SOUND_ARM_BCM2835_H */
+++ /dev/null
-From 48113d6d98bd0f810b439741bb0da982b1abe4c1 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:33 +0200
-Subject: [PATCH 443/703] staging: bcm2835-audio: Remove redundant substream
- mask checks
-
-commit 14b1f4cba853a11c7b381ad919622f38eb194bd7 upstream.
-
-The avail_substreams bit mask is checked for the possible racy
-accesses, but this cannot happen in practice; i.e. the assignment and
-the check are superfluous.
-
-Let's rip them off.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 2 --
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 8 --------
- .../vc04_services/bcm2835-audio/bcm2835-vchiq.c | 17 +++++++----------
- .../vc04_services/bcm2835-audio/bcm2835.c | 5 +----
- .../vc04_services/bcm2835-audio/bcm2835.h | 2 --
- 5 files changed, 8 insertions(+), 26 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-@@ -64,8 +64,6 @@ static int snd_bcm2835_ctl_get(struct sn
-
- mutex_lock(&chip->audio_mutex);
-
-- 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)
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -118,14 +118,6 @@ static int snd_bcm2835_playback_open_gen
- 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(*alsa_stream), GFP_KERNEL);
- if (!alsa_stream) {
- err = -ENOMEM;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -523,16 +523,13 @@ int bcm2835_audio_set_ctls(struct bcm283
-
- /* 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(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);
-- }
-+ if (!chip->alsa_stream[i])
-+ continue;
-+ if (bcm2835_audio_set_ctls_chan(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);
- }
- }
- return ret;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -280,7 +280,7 @@ static int snd_add_child_device(struct d
- struct snd_card *card;
- struct device *child;
- struct bcm2835_chip *chip;
-- int err, i;
-+ int err;
-
- child = snd_create_device(device, &audio_driver->driver,
- audio_driver->driver.name);
-@@ -325,9 +325,6 @@ static int snd_add_child_device(struct d
- return err;
- }
-
-- for (i = 0; i < numchans; i++)
-- chip->avail_substreams |= (1 << i);
--
- err = snd_card_register(card);
- if (err) {
- dev_err(child, "Failed to register card, error %d\n", err);
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -98,8 +98,6 @@ struct bcm2835_chip {
- struct snd_card *card;
- struct snd_pcm *pcm;
- struct snd_pcm *pcm_spdif;
-- /* Bitmat for valid reg_base and irq numbers */
-- unsigned int avail_substreams;
- struct device *dev;
- struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS];
-
--- /dev/null
+From e935363e043245369cb6b566348e86b0be6c0840 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:36 +0200
+Subject: [PATCH 443/725] staging: bcm2835-audio: Remove superfluous open flag
+
+commit ad13924de6b07cb52714ea1809c57b2e72a24504 upstream.
+
+All the alsa_stream->open flag checks in the current code are
+redundant, and they cannot be racy. For the code simplification,
+let's remove the flag and its check.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 9 ++-------
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835.h | 1 -
+ 2 files changed, 2 insertions(+), 8 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -57,8 +57,7 @@ void bcm2835_playback_fifo(struct bcm283
+ 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);
++ 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
+@@ -154,7 +153,6 @@ static int snd_bcm2835_playback_open_gen
+ chip->alsa_stream[idx] = alsa_stream;
+
+ chip->opened |= (1 << idx);
+- alsa_stream->open = 1;
+ alsa_stream->draining = 1;
+
+ out:
+@@ -205,10 +203,7 @@ static int snd_bcm2835_playback_close(st
+ alsa_stream->period_size = 0;
+ alsa_stream->buffer_size = 0;
+
+- if (alsa_stream->open) {
+- alsa_stream->open = 0;
+- bcm2835_audio_close(alsa_stream);
+- }
++ bcm2835_audio_close(alsa_stream);
+ if (alsa_stream->chip)
+ alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL;
+ /*
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -121,7 +121,6 @@ struct bcm2835_alsa_stream {
+
+ spinlock_t lock;
+
+- int open;
+ int running;
+ int draining;
+
--- /dev/null
+From 70e1a30534d17ecf4fb6a5e04241b1d1704a909d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:37 +0200
+Subject: [PATCH 444/725] staging: bcm2835-audio: Drop useless running flag and
+ check
+
+commit 02f2376321d75e78117f39ff81f215254ee6b4ef upstream.
+
+The running flag of alsa_stream is basically useless. The running
+state is strictly controlled in ALSA PCM core side, hence the check in
+PCM trigger and close callbacks are superfluous.
+
+Also, the prefill ack at trigger start became superfluous nowadays
+with the ALSA PCM core update.
+
+Let's rip them off.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 46 ++++---------------
+ .../vc04_services/bcm2835-audio/bcm2835.h | 1 -
+ 2 files changed, 8 insertions(+), 39 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -187,19 +187,6 @@ static int snd_bcm2835_playback_close(st
+
+ 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)
+- audio_error(" Failed to STOP alsa device\n");
+- }
+-
+ alsa_stream->period_size = 0;
+ alsa_stream->buffer_size = 0;
+
+@@ -324,27 +311,13 @@ static int snd_bcm2835_pcm_trigger(struc
+
+ 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) {
+- 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);
+- }
+- }
++ err = bcm2835_audio_start(alsa_stream);
++ if (!err)
++ 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;
+@@ -352,12 +325,9 @@ static int snd_bcm2835_pcm_trigger(struc
+ 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;
+- }
++ err = bcm2835_audio_stop(alsa_stream);
++ if (err != 0)
++ audio_error(" Failed to STOP alsa device (%d)\n", err);
+ break;
+ default:
+ err = -EINVAL;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -121,7 +121,6 @@ struct bcm2835_alsa_stream {
+
+ spinlock_t lock;
+
+- int running;
+ int draining;
+
+ int channels;
+++ /dev/null
-From 8e1cbe403cccb0269ad6563cf223a220f2173964 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:34 +0200
-Subject: [PATCH 444/703] staging: bcm2835-audio: Fix mute controls, volume
- handling cleanup
-
-commit 495e5a0d83d3902c741771f267a702ae19da8ab6 upstream.
-
-In the current code, the mute control is dealt in a special manner,
-modifying the current volume and saving the old volume, etc. This is
-inconsistent (e.g. change the volume while muted, then unmute), and
-way too complex.
-
-Also, the whole volume handling code has conversion between ALSA
-volume and raw volume values, which can lead to another
-inconsistency and complexity.
-
-This patch simplifies these points:
-- The ALSA volume value is saved in chip->volume
-- volume->mute saves the mute state
-- The mute state is evaluated only when the actual volume is passed to
- the hardware, bcm2835_audio_set_ctls()
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 84 +++++++------------
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 6 +-
- .../bcm2835-audio/bcm2835-vchiq.c | 32 ++-----
- .../vc04_services/bcm2835-audio/bcm2835.h | 5 +-
- 4 files changed, 45 insertions(+), 82 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-@@ -12,6 +12,21 @@
- #define CTRL_VOL_MAX 400
- #define CTRL_VOL_MIN -10239 /* originally -10240 */
-
-+static int bcm2835_audio_set_chip_ctls(struct bcm2835_chip *chip)
-+{
-+ int i, err = 0;
-+
-+ /* change ctls for all substreams */
-+ for (i = 0; i < MAX_SUBSTREAMS; i++) {
-+ if (chip->alsa_stream[i]) {
-+ err = bcm2835_audio_set_ctls(chip->alsa_stream[i]);
-+ if (err < 0)
-+ break;
-+ }
-+ }
-+ return err;
-+}
-+
- static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
- {
-@@ -34,29 +49,6 @@ static int snd_bcm2835_ctl_info(struct s
- 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)
- {
-@@ -65,7 +57,7 @@ static int snd_bcm2835_ctl_get(struct sn
- mutex_lock(&chip->audio_mutex);
-
- if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
-- ucontrol->value.integer.value[0] = chip2alsa(chip->volume);
-+ ucontrol->value.integer.value[0] = chip->volume;
- else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
- ucontrol->value.integer.value[0] = chip->mute;
- else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
-@@ -79,38 +71,26 @@ static int snd_bcm2835_ctl_put(struct sn
- struct snd_ctl_elem_value *ucontrol)
- {
- struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
-+ int val, *valp;
- int changed = 0;
-
-- mutex_lock(&chip->audio_mutex);
--
-- 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]);
-+ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
-+ valp = &chip->volume;
-+ else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
-+ valp = &chip->mute;
-+ else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
-+ valp = &chip->dest;
-+ else
-+ return -EINVAL;
-
-- } 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;
-- }
-+ val = ucontrol->value.integer.value[0];
-+ mutex_lock(&chip->audio_mutex);
-+ if (val != *valp) {
-+ *valp = val;
-+ changed = 1;
-+ if (bcm2835_audio_set_chip_ctls(chip))
-+ dev_err(chip->card->dev, "Failed to set ALSA controls..\n");
- }
--
-- if (changed && bcm2835_audio_set_ctls(chip))
-- dev_err(chip->card->dev, "Failed to set ALSA controls..\n");
--
--unlock:
- mutex_unlock(&chip->audio_mutex);
- return changed;
- }
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -280,7 +280,7 @@ static int snd_bcm2835_pcm_prepare(struc
- 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);
-+ bcm2835_audio_set_ctls(alsa_stream);
-
- memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
-
-@@ -441,7 +441,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
- strcpy(pcm->name, "bcm2835 ALSA");
- chip->pcm = pcm;
- chip->dest = AUDIO_DEST_AUTO;
-- chip->volume = alsa2chip(0);
-+ chip->volume = 0;
- chip->mute = CTRL_VOL_UNMUTE; /*disable mute on startup */
- /* set operators */
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-@@ -498,7 +498,7 @@ int snd_bcm2835_new_simple_pcm(struct bc
- strcpy(pcm->name, name);
- chip->pcm = pcm;
- chip->dest = route;
-- chip->volume = alsa2chip(0);
-+ chip->volume = 0;
- chip->mute = CTRL_VOL_UNMUTE;
-
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -460,11 +460,11 @@ free_wq:
- return ret;
- }
-
--static int bcm2835_audio_set_ctls_chan(struct bcm2835_alsa_stream *alsa_stream,
-- struct bcm2835_chip *chip)
-+int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream)
- {
- struct vc_audio_msg m;
- struct bcm2835_audio_instance *instance = alsa_stream->instance;
-+ struct bcm2835_chip *chip = alsa_stream->chip;
- int status;
- int ret;
-
-@@ -478,7 +478,10 @@ static int bcm2835_audio_set_ctls_chan(s
-
- m.type = VC_AUDIO_MSG_TYPE_CONTROL;
- m.u.control.dest = chip->dest;
-- m.u.control.volume = chip->volume;
-+ if (!chip->mute)
-+ m.u.control.volume = CHIP_MIN_VOLUME;
-+ else
-+ m.u.control.volume = alsa2chip(chip->volume);
-
- /* Create the message available completion */
- init_completion(&instance->msg_avail_comp);
-@@ -514,27 +517,6 @@ unlock:
- return ret;
- }
-
--int bcm2835_audio_set_ctls(struct bcm2835_chip *chip)
--{
-- int i;
-- int ret = 0;
--
-- 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->alsa_stream[i])
-- continue;
-- if (bcm2835_audio_set_ctls_chan(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);
-- }
-- }
-- return ret;
--}
--
- int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
- unsigned int channels, unsigned int samplerate,
- unsigned int bps)
-@@ -548,7 +530,7 @@ int bcm2835_audio_set_params(struct bcm2
- 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);
-+ ret = bcm2835_audio_set_ctls(alsa_stream);
- if (ret) {
- LOG_ERR(" Alsa controls not supported\n");
- return -EINVAL;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -74,6 +74,8 @@ enum {
- // convert chip to alsa volume
- #define chip2alsa(vol) -(((vol) * 100) >> 8)
-
-+#define CHIP_MIN_VOLUME 26214 /* minimum level aka mute */
-+
- /* Some constants for values .. */
- enum snd_bcm2835_route {
- AUDIO_DEST_AUTO = 0,
-@@ -102,7 +104,6 @@ struct bcm2835_chip {
- struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS];
-
- int volume;
-- int old_volume; /* stores the volume value whist muted */
- int dest;
- int mute;
-
-@@ -160,7 +161,7 @@ int bcm2835_audio_set_params(struct bcm2
- int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream);
--int bcm2835_audio_set_ctls(struct bcm2835_chip *chip);
-+int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
- unsigned int count,
- void *src);
--- /dev/null
+From 52a5b0e8e24f31fdef175e76405fd4ee08936f26 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:38 +0200
+Subject: [PATCH 445/725] staging: bcm2835-audio: Fix incorrect draining
+ handling
+
+commit 7d2a91f5f1bcf08ca257bcf1ed9721fcd341f834 upstream.
+
+The handling of SNDRV_PCM_TRIGGER_STOP at the trigger callback is
+incorrect: when the STOP is issued, the driver is supposed to drop the
+stream immediately. Meanwhile bcm2835 driver checks the DRAINING
+state and tries to issue some different command.
+
+This patch straightens things a bit, dropping the incorrect state
+checks. The draining behavior would be still not perfect at this
+point, but will be improved in a later patch.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 18 ++++++------------
+ 1 file changed, 6 insertions(+), 12 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -153,7 +153,6 @@ static int snd_bcm2835_playback_open_gen
+ chip->alsa_stream[idx] = alsa_stream;
+
+ chip->opened |= (1 << idx);
+- alsa_stream->draining = 1;
+
+ out:
+ mutex_unlock(&chip->audio_mutex);
+@@ -268,6 +267,7 @@ static int snd_bcm2835_pcm_prepare(struc
+ alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
+ alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
+ alsa_stream->pos = 0;
++ alsa_stream->draining = false;
+
+ audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n",
+ alsa_stream->buffer_size, alsa_stream->period_size,
+@@ -312,21 +312,15 @@ static int snd_bcm2835_pcm_trigger(struc
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ err = bcm2835_audio_start(alsa_stream);
+- if (!err)
+- alsa_stream->draining = 1;
+- else
++ if (err)
+ audio_error(" Failed to START alsa device (%d)\n", err);
+ break;
++ case SNDRV_PCM_TRIGGER_DRAIN:
++ alsa_stream->draining = true;
++ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+- 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;
+- }
+ err = bcm2835_audio_stop(alsa_stream);
+- if (err != 0)
++ if (err)
+ audio_error(" Failed to STOP alsa device (%d)\n", err);
+ break;
+ default:
+++ /dev/null
-From c778d5d0208598e0595e59b2795b92580483971d Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:35 +0200
-Subject: [PATCH 445/703] staging: bcm2835-audio: Remove redundant function
- calls
-
-commit 124950ebe9fa8547c59e8d4acc8d6c59e6278ed6 upstream.
-
-bcm2835_audio_setup(), bcm2835_audio_flush_buffers() and
-bcm2835_audio_flush_playback_buffers() functions do implement
-nothing.
-
-Also, bcm2835_audio_set_ctls() is already called inside
-bcm2835_audio_set_params(), so the later call is superfluous.
-
-This patch removes these superfluous implementations.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 5 -----
- .../bcm2835-audio/bcm2835-vchiq.c | 21 -------------------
- .../vc04_services/bcm2835-audio/bcm2835.h | 3 ---
- 3 files changed, 29 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -277,11 +277,6 @@ static int snd_bcm2835_pcm_prepare(struc
- 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);
--
- memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
-
- alsa_stream->pcm_indirect.hw_buffer_size =
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -580,12 +580,6 @@ unlock:
- return ret;
- }
-
--int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream)
--{
--
-- return 0;
--}
--
- static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream)
- {
- struct vc_audio_msg m;
-@@ -774,21 +768,6 @@ unlock:
- return ret;
- }
-
--/**
-- * Returns all buffers from arm->vc
-- */
--void bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream *alsa_stream)
--{
--}
--
--/**
-- * Forces VC to flush(drop) its filled playback buffers and
-- * return them the us. (VC->ARM)
-- */
--void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream *alsa_stream)
--{
--}
--
- unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream)
- {
- unsigned int count = atomic_read(&alsa_stream->retrieved);
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -158,7 +158,6 @@ int bcm2835_audio_close(struct bcm2835_a
- int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
- unsigned int channels, unsigned int samplerate,
- unsigned int bps);
--int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream);
-@@ -167,7 +166,5 @@ int bcm2835_audio_write(struct bcm2835_a
- void *src);
- void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream);
- unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream);
--void bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream *alsa_stream);
--void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream *alsa_stream);
-
- #endif /* __SOUND_ARM_BCM2835_H */
--- /dev/null
+From 0f4ac0deca99ce7936a43d1e1f7b712a30dc554d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:39 +0200
+Subject: [PATCH 446/725] staging: bcm2835-audio: Kill unused spinlock
+
+commit 5332f6f012c0bf3a45c77dbc0f79814443a884d4 upstream.
+
+The alsa_stream->lock is never used. Kill it.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 2 --
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835.h | 2 --
+ 2 files changed, 4 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -128,8 +128,6 @@ static int snd_bcm2835_playback_open_gen
+ alsa_stream->substream = substream;
+ alsa_stream->idx = idx;
+
+- spin_lock_init(&alsa_stream->lock);
+-
+ err = bcm2835_audio_open(alsa_stream);
+ if (err) {
+ kfree(alsa_stream);
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -119,8 +119,6 @@ struct bcm2835_alsa_stream {
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_indirect pcm_indirect;
+
+- spinlock_t lock;
+-
+ int draining;
+
+ int channels;
+++ /dev/null
-From 5894f3d0de921dd5134004906643a1d1219b13cf Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:36 +0200
-Subject: [PATCH 446/703] staging: bcm2835-audio: Remove superfluous open flag
-
-commit ad13924de6b07cb52714ea1809c57b2e72a24504 upstream.
-
-All the alsa_stream->open flag checks in the current code are
-redundant, and they cannot be racy. For the code simplification,
-let's remove the flag and its check.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 9 ++-------
- drivers/staging/vc04_services/bcm2835-audio/bcm2835.h | 1 -
- 2 files changed, 2 insertions(+), 8 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -57,8 +57,7 @@ void bcm2835_playback_fifo(struct bcm283
- 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);
-+ 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
-@@ -154,7 +153,6 @@ static int snd_bcm2835_playback_open_gen
- chip->alsa_stream[idx] = alsa_stream;
-
- chip->opened |= (1 << idx);
-- alsa_stream->open = 1;
- alsa_stream->draining = 1;
-
- out:
-@@ -205,10 +203,7 @@ static int snd_bcm2835_playback_close(st
- alsa_stream->period_size = 0;
- alsa_stream->buffer_size = 0;
-
-- if (alsa_stream->open) {
-- alsa_stream->open = 0;
-- bcm2835_audio_close(alsa_stream);
-- }
-+ bcm2835_audio_close(alsa_stream);
- if (alsa_stream->chip)
- alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL;
- /*
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -121,7 +121,6 @@ struct bcm2835_alsa_stream {
-
- spinlock_t lock;
-
-- int open;
- int running;
- int draining;
-
+++ /dev/null
-From 2dd8625b99a3244bf632278cd7fdd74dffaeb3a3 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:37 +0200
-Subject: [PATCH 447/703] staging: bcm2835-audio: Drop useless running flag and
- check
-
-commit 02f2376321d75e78117f39ff81f215254ee6b4ef upstream.
-
-The running flag of alsa_stream is basically useless. The running
-state is strictly controlled in ALSA PCM core side, hence the check in
-PCM trigger and close callbacks are superfluous.
-
-Also, the prefill ack at trigger start became superfluous nowadays
-with the ALSA PCM core update.
-
-Let's rip them off.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 46 ++++---------------
- .../vc04_services/bcm2835-audio/bcm2835.h | 1 -
- 2 files changed, 8 insertions(+), 39 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -187,19 +187,6 @@ static int snd_bcm2835_playback_close(st
-
- 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)
-- audio_error(" Failed to STOP alsa device\n");
-- }
--
- alsa_stream->period_size = 0;
- alsa_stream->buffer_size = 0;
-
-@@ -324,27 +311,13 @@ static int snd_bcm2835_pcm_trigger(struc
-
- 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) {
-- 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);
-- }
-- }
-+ err = bcm2835_audio_start(alsa_stream);
-+ if (!err)
-+ 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;
-@@ -352,12 +325,9 @@ static int snd_bcm2835_pcm_trigger(struc
- 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;
-- }
-+ err = bcm2835_audio_stop(alsa_stream);
-+ if (err != 0)
-+ audio_error(" Failed to STOP alsa device (%d)\n", err);
- break;
- default:
- err = -EINVAL;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -121,7 +121,6 @@ struct bcm2835_alsa_stream {
-
- spinlock_t lock;
-
-- int running;
- int draining;
-
- int channels;
--- /dev/null
+From aaf04413a17530437872ec909f2af1fb012e9954 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:40 +0200
+Subject: [PATCH 447/725] staging: bcm2835-audio: Use PCM runtime values
+ instead
+
+commit b8f7fdd50890b848e085c0519469aed4ff4d9b54 upstream.
+
+Some fields in alsa_stream are the values we keep already in PCM
+runtime object, hence they are redundant. Use the standard PCM
+runtime values instead of the private copies.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 23 ++++---------------
+ .../vc04_services/bcm2835-audio/bcm2835.h | 4 ----
+ 2 files changed, 4 insertions(+), 23 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -206,22 +206,7 @@ static int snd_bcm2835_playback_close(st
+ 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;
+- struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
+- int err;
+-
+- 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));
+-
+- return err;
++ return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+ }
+
+ /* hw_free callback */
+@@ -248,11 +233,11 @@ static int snd_bcm2835_pcm_prepare(struc
+ if (chip->spdif_status & IEC958_AES0_NONAUDIO)
+ channels = 0;
+ else
+- channels = alsa_stream->channels;
++ channels = runtime->channels;
+
+ err = bcm2835_audio_set_params(alsa_stream, channels,
+- alsa_stream->params_rate,
+- alsa_stream->pcm_format_width);
++ runtime->rate,
++ snd_pcm_format_width(runtime->format));
+ if (err < 0)
+ audio_error(" error setting hw params\n");
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -121,10 +121,6 @@ struct bcm2835_alsa_stream {
+
+ int draining;
+
+- int channels;
+- int params_rate;
+- int pcm_format_width;
+-
+ unsigned int pos;
+ unsigned int buffer_size;
+ unsigned int period_size;
--- /dev/null
+From 1e69d6aed91e759114adec689fe954890dbac0d0 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:41 +0200
+Subject: [PATCH 448/725] staging: bcm2835-audio: Drop unnecessary pcm indirect
+ setup
+
+commit 7318ec896f4856fae2bb013858e422fa078201e1 upstream.
+
+The hw_queue_size of PCM indirect helper doesn't need to be set up if
+you use the whole given buffer size. Drop the useless
+initialization, which just confuses readers.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -280,7 +280,6 @@ static int snd_bcm2835_pcm_ack(struct sn
+ struct bcm2835_alsa_stream *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;
+ return snd_pcm_indirect_playback_transfer(substream, pcm_indirect,
+ snd_bcm2835_pcm_transfer);
+ }
+++ /dev/null
-From 0938ad598509c19a256d5fc63b9002ad9cf59a14 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:38 +0200
-Subject: [PATCH 448/703] staging: bcm2835-audio: Fix incorrect draining
- handling
-
-commit 7d2a91f5f1bcf08ca257bcf1ed9721fcd341f834 upstream.
-
-The handling of SNDRV_PCM_TRIGGER_STOP at the trigger callback is
-incorrect: when the STOP is issued, the driver is supposed to drop the
-stream immediately. Meanwhile bcm2835 driver checks the DRAINING
-state and tries to issue some different command.
-
-This patch straightens things a bit, dropping the incorrect state
-checks. The draining behavior would be still not perfect at this
-point, but will be improved in a later patch.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 18 ++++++------------
- 1 file changed, 6 insertions(+), 12 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -153,7 +153,6 @@ static int snd_bcm2835_playback_open_gen
- chip->alsa_stream[idx] = alsa_stream;
-
- chip->opened |= (1 << idx);
-- alsa_stream->draining = 1;
-
- out:
- mutex_unlock(&chip->audio_mutex);
-@@ -268,6 +267,7 @@ static int snd_bcm2835_pcm_prepare(struc
- alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
- alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
- alsa_stream->pos = 0;
-+ alsa_stream->draining = false;
-
- audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n",
- alsa_stream->buffer_size, alsa_stream->period_size,
-@@ -312,21 +312,15 @@ static int snd_bcm2835_pcm_trigger(struc
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- err = bcm2835_audio_start(alsa_stream);
-- if (!err)
-- alsa_stream->draining = 1;
-- else
-+ if (err)
- audio_error(" Failed to START alsa device (%d)\n", err);
- break;
-+ case SNDRV_PCM_TRIGGER_DRAIN:
-+ alsa_stream->draining = true;
-+ break;
- case SNDRV_PCM_TRIGGER_STOP:
-- 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;
-- }
- err = bcm2835_audio_stop(alsa_stream);
-- if (err != 0)
-+ if (err)
- audio_error(" Failed to STOP alsa device (%d)\n", err);
- break;
- default:
--- /dev/null
+From 8756f60e33dfa2c92d8d3c2abd162c084a9d92c6 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:42 +0200
+Subject: [PATCH 449/725] staging: bcm2835-audio: Drop useless NULL check
+
+commit 8bcf9f252c29c2d5bcce3db605c0ebf1ef230f9c upstream.
+
+alsa_stream->chip can be never NULL.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -188,8 +188,7 @@ static int snd_bcm2835_playback_close(st
+ alsa_stream->buffer_size = 0;
+
+ bcm2835_audio_close(alsa_stream);
+- if (alsa_stream->chip)
+- alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL;
++ 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
+++ /dev/null
-From 7634e4d73bc54cd1382ccffd72ab07db522f2667 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:39 +0200
-Subject: [PATCH 449/703] staging: bcm2835-audio: Kill unused spinlock
-
-commit 5332f6f012c0bf3a45c77dbc0f79814443a884d4 upstream.
-
-The alsa_stream->lock is never used. Kill it.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 2 --
- drivers/staging/vc04_services/bcm2835-audio/bcm2835.h | 2 --
- 2 files changed, 4 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -128,8 +128,6 @@ static int snd_bcm2835_playback_open_gen
- alsa_stream->substream = substream;
- alsa_stream->idx = idx;
-
-- spin_lock_init(&alsa_stream->lock);
--
- err = bcm2835_audio_open(alsa_stream);
- if (err) {
- kfree(alsa_stream);
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -119,8 +119,6 @@ struct bcm2835_alsa_stream {
- struct snd_pcm_substream *substream;
- struct snd_pcm_indirect pcm_indirect;
-
-- spinlock_t lock;
--
- int draining;
-
- int channels;
--- /dev/null
+From da7c23faa34cb7ace6c22dbdfba3eb3ee047454f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:43 +0200
+Subject: [PATCH 450/725] staging: bcm2835-audio: Propagate parameter setup
+ error
+
+commit fee5638fe552ff8222c3a5bdcc4a34255e248d8c upstream.
+
+When the parameter setup fails, the driver should propagate the error
+code instead of silently ignoring it.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -238,7 +238,7 @@ static int snd_bcm2835_pcm_prepare(struc
+ runtime->rate,
+ snd_pcm_format_width(runtime->format));
+ if (err < 0)
+- audio_error(" error setting hw params\n");
++ goto out;
+
+ memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
+
+@@ -255,8 +255,9 @@ static int snd_bcm2835_pcm_prepare(struc
+ alsa_stream->buffer_size, alsa_stream->period_size,
+ alsa_stream->pos, runtime->frame_bits);
+
++ out:
+ mutex_unlock(&chip->audio_mutex);
+- return 0;
++ return err;
+ }
+
+ static void snd_bcm2835_pcm_transfer(struct snd_pcm_substream *substream,
+++ /dev/null
-From 5e97bf3a60f5ebcb1e4135fe1d92f649c920ff81 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:40 +0200
-Subject: [PATCH 450/703] staging: bcm2835-audio: Use PCM runtime values
- instead
-
-commit b8f7fdd50890b848e085c0519469aed4ff4d9b54 upstream.
-
-Some fields in alsa_stream are the values we keep already in PCM
-runtime object, hence they are redundant. Use the standard PCM
-runtime values instead of the private copies.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 23 ++++---------------
- .../vc04_services/bcm2835-audio/bcm2835.h | 4 ----
- 2 files changed, 4 insertions(+), 23 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -206,22 +206,7 @@ static int snd_bcm2835_playback_close(st
- 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;
-- struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
-- int err;
--
-- 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));
--
-- return err;
-+ return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
- }
-
- /* hw_free callback */
-@@ -248,11 +233,11 @@ static int snd_bcm2835_pcm_prepare(struc
- if (chip->spdif_status & IEC958_AES0_NONAUDIO)
- channels = 0;
- else
-- channels = alsa_stream->channels;
-+ channels = runtime->channels;
-
- err = bcm2835_audio_set_params(alsa_stream, channels,
-- alsa_stream->params_rate,
-- alsa_stream->pcm_format_width);
-+ runtime->rate,
-+ snd_pcm_format_width(runtime->format));
- if (err < 0)
- audio_error(" error setting hw params\n");
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -121,10 +121,6 @@ struct bcm2835_alsa_stream {
-
- int draining;
-
-- int channels;
-- int params_rate;
-- int pcm_format_width;
--
- unsigned int pos;
- unsigned int buffer_size;
- unsigned int period_size;
--- /dev/null
+From 3341080850b4ad6e51017afa9ca83020487f1c3d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:44 +0200
+Subject: [PATCH 451/725] staging: bcm2835-audio: Drop debug messages in
+ bcm2835-pcm.c
+
+commit 055e1c330d04df87d4730a5db837161c11ddaafc upstream.
+
+These debug messages worsen the code readability a lot while they give
+little debuggability (which we already have via tracing, in anyway).
+
+Let's clean them up. This allows us to reduce the
+snd_bcm2835_pcm_lib_ioctl() function to be a direct call of the
+snd_pcm_lib_ioctl callback (like most other drivers do), too.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 51 +++----------------
+ 1 file changed, 7 insertions(+), 44 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -44,9 +44,7 @@ static const struct snd_pcm_hardware snd
+
+ static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime)
+ {
+- audio_info("Freeing up alsa stream here ..\n");
+ kfree(runtime->private_data);
+- runtime->private_data = NULL;
+ }
+
+ void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream)
+@@ -99,7 +97,6 @@ static int snd_bcm2835_playback_open_gen
+ int err;
+
+ mutex_lock(&chip->audio_mutex);
+- audio_info("Alsa open (%d)\n", substream->number);
+ idx = substream->number;
+
+ if (spdif && chip->opened) {
+@@ -182,8 +179,6 @@ static int snd_bcm2835_playback_close(st
+ runtime = substream->runtime;
+ alsa_stream = runtime->private_data;
+
+- audio_info("Alsa close\n");
+-
+ alsa_stream->period_size = 0;
+ alsa_stream->buffer_size = 0;
+
+@@ -251,10 +246,6 @@ static int snd_bcm2835_pcm_prepare(struc
+ alsa_stream->pos = 0;
+ alsa_stream->draining = false;
+
+- 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);
+-
+ out:
+ mutex_unlock(&chip->audio_mutex);
+ return err;
+@@ -266,12 +257,8 @@ static void snd_bcm2835_pcm_transfer(str
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct bcm2835_alsa_stream *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);
+
++ bcm2835_audio_write(alsa_stream, bytes, src);
+ }
+
+ static int snd_bcm2835_pcm_ack(struct snd_pcm_substream *substream)
+@@ -289,27 +276,18 @@ static int snd_bcm2835_pcm_trigger(struc
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
+- int err = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+- err = bcm2835_audio_start(alsa_stream);
+- if (err)
+- audio_error(" Failed to START alsa device (%d)\n", err);
+- break;
++ return bcm2835_audio_start(alsa_stream);
+ case SNDRV_PCM_TRIGGER_DRAIN:
+ alsa_stream->draining = true;
+- break;
++ return 0;
+ case SNDRV_PCM_TRIGGER_STOP:
+- err = bcm2835_audio_stop(alsa_stream);
+- if (err)
+- audio_error(" Failed to STOP alsa device (%d)\n", err);
+- break;
++ return bcm2835_audio_stop(alsa_stream);
+ default:
+- err = -EINVAL;
++ return -EINVAL;
+ }
+-
+- return err;
+ }
+
+ /* pointer callback */
+@@ -319,31 +297,16 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
+
+- 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);
+-
+ 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 int *)arg : 0, ret);
+- return ret;
+-}
+-
+ /* operators */
+ static const struct snd_pcm_ops snd_bcm2835_playback_ops = {
+ .open = snd_bcm2835_playback_open,
+ .close = snd_bcm2835_playback_close,
+- .ioctl = snd_bcm2835_pcm_lib_ioctl,
++ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_bcm2835_pcm_hw_params,
+ .hw_free = snd_bcm2835_pcm_hw_free,
+ .prepare = snd_bcm2835_pcm_prepare,
+@@ -355,7 +318,7 @@ static const struct snd_pcm_ops snd_bcm2
+ static const 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,
++ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_bcm2835_pcm_hw_params,
+ .hw_free = snd_bcm2835_pcm_hw_free,
+ .prepare = snd_bcm2835_pcm_prepare,
+++ /dev/null
-From 82365fbb4b8d2b7602c765b49524da2895efba61 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:41 +0200
-Subject: [PATCH 451/703] staging: bcm2835-audio: Drop unnecessary pcm indirect
- setup
-
-commit 7318ec896f4856fae2bb013858e422fa078201e1 upstream.
-
-The hw_queue_size of PCM indirect helper doesn't need to be set up if
-you use the whole given buffer size. Drop the useless
-initialization, which just confuses readers.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -280,7 +280,6 @@ static int snd_bcm2835_pcm_ack(struct sn
- struct bcm2835_alsa_stream *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;
- return snd_pcm_indirect_playback_transfer(substream, pcm_indirect,
- snd_bcm2835_pcm_transfer);
- }
--- /dev/null
+From e890c7d7d4476ed6276f0d902a83b6d34ad513f2 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:45 +0200
+Subject: [PATCH 452/725] staging: bcm2835-audio: Drop superfluous mutex lock
+ during prepare
+
+commit f0eb15d055380ff127e5f12c8fad2b36bdb3c006 upstream.
+
+The chip->audio_mutex is used basically for protecting the opened
+stream assignment, and the prepare callback is irrelevant with it.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -218,8 +218,6 @@ static int snd_bcm2835_pcm_prepare(struc
+ int channels;
+ int err;
+
+- mutex_lock(&chip->audio_mutex);
+-
+ /* notify the vchiq that it should enter spdif passthrough mode by
+ * setting channels=0 (see
+ * https://github.com/raspberrypi/linux/issues/528)
+@@ -233,7 +231,7 @@ static int snd_bcm2835_pcm_prepare(struc
+ runtime->rate,
+ snd_pcm_format_width(runtime->format));
+ if (err < 0)
+- goto out;
++ return err;
+
+ memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
+
+@@ -246,9 +244,7 @@ static int snd_bcm2835_pcm_prepare(struc
+ alsa_stream->pos = 0;
+ alsa_stream->draining = false;
+
+- out:
+- mutex_unlock(&chip->audio_mutex);
+- return err;
++ return 0;
+ }
+
+ static void snd_bcm2835_pcm_transfer(struct snd_pcm_substream *substream,
+++ /dev/null
-From fa0533b8020b056d559cfdcb86da8ee332ae8a02 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:42 +0200
-Subject: [PATCH 452/703] staging: bcm2835-audio: Drop useless NULL check
-
-commit 8bcf9f252c29c2d5bcce3db605c0ebf1ef230f9c upstream.
-
-alsa_stream->chip can be never NULL.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -188,8 +188,7 @@ static int snd_bcm2835_playback_close(st
- alsa_stream->buffer_size = 0;
-
- bcm2835_audio_close(alsa_stream);
-- if (alsa_stream->chip)
-- alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL;
-+ 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
--- /dev/null
+From 9634bb7bf8aa4fe86d00ff572c3290dfa042a8d6 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:46 +0200
+Subject: [PATCH 453/725] staging: bcm2835-audio: Add 10ms period constraint
+
+commit 93c66acaf68b5247c3121a46a71ff6a70fc1d492 upstream.
+
+It seems that the resolution of vc04 callback is in 10 msec; i.e. the
+minimal period size is also 10 msec.
+
+This patch adds the corresponding hw constraint.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -145,6 +145,11 @@ static int snd_bcm2835_playback_open_gen
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+ 16);
+
++ /* position update is in 10ms order */
++ snd_pcm_hw_constraint_minmax(runtime,
++ SNDRV_PCM_HW_PARAM_PERIOD_TIME,
++ 10 * 1000, UINT_MAX);
++
+ chip->alsa_stream[idx] = alsa_stream;
+
+ chip->opened |= (1 << idx);
+++ /dev/null
-From 10310b6f36d3573f55e3ab318204aebe9f1a60f8 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:43 +0200
-Subject: [PATCH 453/703] staging: bcm2835-audio: Propagate parameter setup
- error
-
-commit fee5638fe552ff8222c3a5bdcc4a34255e248d8c upstream.
-
-When the parameter setup fails, the driver should propagate the error
-code instead of silently ignoring it.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -238,7 +238,7 @@ static int snd_bcm2835_pcm_prepare(struc
- runtime->rate,
- snd_pcm_format_width(runtime->format));
- if (err < 0)
-- audio_error(" error setting hw params\n");
-+ goto out;
-
- memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
-
-@@ -255,8 +255,9 @@ static int snd_bcm2835_pcm_prepare(struc
- alsa_stream->buffer_size, alsa_stream->period_size,
- alsa_stream->pos, runtime->frame_bits);
-
-+ out:
- mutex_unlock(&chip->audio_mutex);
-- return 0;
-+ return err;
- }
-
- static void snd_bcm2835_pcm_transfer(struct snd_pcm_substream *substream,
+++ /dev/null
-From 50292f7a57de792cb23b3883594b0e102e74e9e2 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:44 +0200
-Subject: [PATCH 454/703] staging: bcm2835-audio: Drop debug messages in
- bcm2835-pcm.c
-
-commit 055e1c330d04df87d4730a5db837161c11ddaafc upstream.
-
-These debug messages worsen the code readability a lot while they give
-little debuggability (which we already have via tracing, in anyway).
-
-Let's clean them up. This allows us to reduce the
-snd_bcm2835_pcm_lib_ioctl() function to be a direct call of the
-snd_pcm_lib_ioctl callback (like most other drivers do), too.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 51 +++----------------
- 1 file changed, 7 insertions(+), 44 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -44,9 +44,7 @@ static const struct snd_pcm_hardware snd
-
- static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime)
- {
-- audio_info("Freeing up alsa stream here ..\n");
- kfree(runtime->private_data);
-- runtime->private_data = NULL;
- }
-
- void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream)
-@@ -99,7 +97,6 @@ static int snd_bcm2835_playback_open_gen
- int err;
-
- mutex_lock(&chip->audio_mutex);
-- audio_info("Alsa open (%d)\n", substream->number);
- idx = substream->number;
-
- if (spdif && chip->opened) {
-@@ -182,8 +179,6 @@ static int snd_bcm2835_playback_close(st
- runtime = substream->runtime;
- alsa_stream = runtime->private_data;
-
-- audio_info("Alsa close\n");
--
- alsa_stream->period_size = 0;
- alsa_stream->buffer_size = 0;
-
-@@ -251,10 +246,6 @@ static int snd_bcm2835_pcm_prepare(struc
- alsa_stream->pos = 0;
- alsa_stream->draining = false;
-
-- 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);
--
- out:
- mutex_unlock(&chip->audio_mutex);
- return err;
-@@ -266,12 +257,8 @@ static void snd_bcm2835_pcm_transfer(str
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct bcm2835_alsa_stream *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);
-
-+ bcm2835_audio_write(alsa_stream, bytes, src);
- }
-
- static int snd_bcm2835_pcm_ack(struct snd_pcm_substream *substream)
-@@ -289,27 +276,18 @@ static int snd_bcm2835_pcm_trigger(struc
- {
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
-- int err = 0;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
-- err = bcm2835_audio_start(alsa_stream);
-- if (err)
-- audio_error(" Failed to START alsa device (%d)\n", err);
-- break;
-+ return bcm2835_audio_start(alsa_stream);
- case SNDRV_PCM_TRIGGER_DRAIN:
- alsa_stream->draining = true;
-- break;
-+ return 0;
- case SNDRV_PCM_TRIGGER_STOP:
-- err = bcm2835_audio_stop(alsa_stream);
-- if (err)
-- audio_error(" Failed to STOP alsa device (%d)\n", err);
-- break;
-+ return bcm2835_audio_stop(alsa_stream);
- default:
-- err = -EINVAL;
-+ return -EINVAL;
- }
--
-- return err;
- }
-
- /* pointer callback */
-@@ -319,31 +297,16 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
-
-- 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);
--
- 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 int *)arg : 0, ret);
-- return ret;
--}
--
- /* operators */
- static const struct snd_pcm_ops snd_bcm2835_playback_ops = {
- .open = snd_bcm2835_playback_open,
- .close = snd_bcm2835_playback_close,
-- .ioctl = snd_bcm2835_pcm_lib_ioctl,
-+ .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_bcm2835_pcm_hw_params,
- .hw_free = snd_bcm2835_pcm_hw_free,
- .prepare = snd_bcm2835_pcm_prepare,
-@@ -355,7 +318,7 @@ static const struct snd_pcm_ops snd_bcm2
- static const 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,
-+ .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_bcm2835_pcm_hw_params,
- .hw_free = snd_bcm2835_pcm_hw_free,
- .prepare = snd_bcm2835_pcm_prepare,
--- /dev/null
+From 2aa144a5c55a27072f21c0dcb8efa180a46c4cd1 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:47 +0200
+Subject: [PATCH 454/725] staging: bcm2835-audio: Make single vchi handle
+
+commit 326a6edcb2ada56375bd7d3fc24c83f58e8da7f3 upstream.
+
+The bcm2835_audio_instance object contains the array of
+VCHI_SERVICE_HANDLE_T, while the code assumes and uses only the first
+element explicitly. Let's reduce to a single vchi handle for
+simplifying the code.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../bcm2835-audio/bcm2835-vchiq.c | 170 ++++++------------
+ 1 file changed, 58 insertions(+), 112 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -44,8 +44,7 @@
+ #endif
+
+ struct bcm2835_audio_instance {
+- unsigned int num_connections;
+- VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS];
++ VCHI_SERVICE_HANDLE_T vchi_handle;
+ struct completion msg_avail_comp;
+ struct mutex vchi_mutex;
+ struct bcm2835_alsa_stream *alsa_stream;
+@@ -202,12 +201,12 @@ static void audio_vchi_callback(void *pa
+ BUG();
+ return;
+ }
+- if (!instance->vchi_handle[0]) {
+- LOG_ERR(" .. instance->vchi_handle[0] is null\n");
++ if (!instance->vchi_handle) {
++ LOG_ERR(" .. instance->vchi_handle is null\n");
+ BUG();
+ return;
+ }
+- status = vchi_msg_dequeue(instance->vchi_handle[0],
++ status = vchi_msg_dequeue(instance->vchi_handle,
+ &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",
+@@ -237,102 +236,61 @@ static void audio_vchi_callback(void *pa
+
+ static struct bcm2835_audio_instance *
+ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance,
+- VCHI_CONNECTION_T **vchi_connections,
+- unsigned int num_connections)
++ VCHI_CONNECTION_T *vchi_connection)
+ {
+- unsigned int i;
++ SERVICE_CREATION_T params = {
++ .version = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
++ .service_id = VC_AUDIO_SERVER_NAME,
++ .connection = vchi_connection,
++ .rx_fifo_size = 0,
++ .tx_fifo_size = 0,
++ .callback = audio_vchi_callback,
++ .want_unaligned_bulk_rx = 1, //TODO: remove VCOS_FALSE
++ .want_unaligned_bulk_tx = 1, //TODO: remove VCOS_FALSE
++ .want_crc = 0
++ };
+ struct bcm2835_audio_instance *instance;
+ int status;
+- int ret;
+-
+- 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 ERR_PTR(-EINVAL);
+- }
+ /* Allocate memory for this instance */
+ instance = kzalloc(sizeof(*instance), GFP_KERNEL);
+ if (!instance)
+ return ERR_PTR(-ENOMEM);
+
+- 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 = {
+- .version = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
+- .service_id = VC_AUDIO_SERVER_NAME,
+- .connection = vchi_connections[i],
+- .rx_fifo_size = 0,
+- .tx_fifo_size = 0,
+- .callback = audio_vchi_callback,
+- .callback_param = instance,
+- .want_unaligned_bulk_rx = 1, //TODO: remove VCOS_FALSE
+- .want_unaligned_bulk_tx = 1, //TODO: remove VCOS_FALSE
+- .want_crc = 0
+- };
+-
+- LOG_DBG("%s: about to open %i\n", __func__, i);
+- status = vchi_service_open(vchi_instance, ¶ms,
+- &instance->vchi_handle[i]);
++ params.callback_param = instance,
+
+- 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);
+- ret = -EPERM;
+- 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;
++ status = vchi_service_open(vchi_instance, ¶ms,
++ &instance->vchi_handle);
+
+-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]);
++ if (status) {
++ LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
++ __func__, status);
++ kfree(instance);
++ return ERR_PTR(-EPERM);
+ }
+
+- kfree(instance);
+- LOG_ERR("%s: error\n", __func__);
++ /* Finished with the service for now */
++ vchi_service_release(instance->vchi_handle);
+
+- return ERR_PTR(ret);
++ return instance;
+ }
+
+ static int vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
+ {
+- unsigned int i;
+-
+- if (!instance) {
+- LOG_ERR("%s: invalid handle %p\n", __func__, instance);
+-
+- return -1;
+- }
++ int status;
+
+- LOG_DBG(" .. about to lock (%d)\n", instance->num_connections);
+ mutex_lock(&instance->vchi_mutex);
+
+ /* Close all VCHI service connections */
+- for (i = 0; i < instance->num_connections; i++) {
+- int status;
+-
+- LOG_DBG(" .. %i:closing %p\n", i, instance->vchi_handle[i]);
+- vchi_service_use(instance->vchi_handle[i]);
++ vchi_service_use(instance->vchi_handle);
+
+- status = vchi_service_close(instance->vchi_handle[i]);
+- if (status) {
+- LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
+- __func__, status);
+- }
++ status = vchi_service_close(instance->vchi_handle);
++ if (status) {
++ LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
++ __func__, status);
+ }
+
+ mutex_unlock(&instance->vchi_mutex);
+@@ -383,19 +341,9 @@ static int bcm2835_audio_open_connection
+ (struct bcm2835_audio_instance *)alsa_stream->instance;
+ struct bcm2835_vchi_ctx *vhci_ctx = alsa_stream->chip->vchi_ctx;
+
+- 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;
+- return 0;
+- }
+-
+ /* Initialize an instance of the audio service */
+ instance = vc_vchi_audio_init(vhci_ctx->vchi_instance,
+- &vhci_ctx->vchi_connection, 1);
++ vhci_ctx->vchi_connection);
+
+ if (IS_ERR(instance)) {
+ LOG_ERR("%s: failed to initialize audio service\n", __func__);
+@@ -407,8 +355,6 @@ static int bcm2835_audio_open_connection
+ instance->alsa_stream = alsa_stream;
+ alsa_stream->instance = instance;
+
+- LOG_DBG(" success !\n");
+-
+ return 0;
+ }
+
+@@ -431,12 +377,12 @@ int bcm2835_audio_open(struct bcm2835_al
+ LOG_DBG(" instance (%p)\n", instance);
+
+ mutex_lock(&instance->vchi_mutex);
+- vchi_service_use(instance->vchi_handle[0]);
++ vchi_service_use(instance->vchi_handle);
+
+ m.type = VC_AUDIO_MSG_TYPE_OPEN;
+
+ /* Send the message to the videocore */
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+ &m, sizeof(m));
+
+ if (status) {
+@@ -450,7 +396,7 @@ int bcm2835_audio_open(struct bcm2835_al
+ ret = 0;
+
+ unlock:
+- vchi_service_release(instance->vchi_handle[0]);
++ vchi_service_release(instance->vchi_handle);
+ mutex_unlock(&instance->vchi_mutex);
+
+ free_wq:
+@@ -472,7 +418,7 @@ int bcm2835_audio_set_ctls(struct bcm283
+ chip->dest, chip->volume);
+
+ mutex_lock(&instance->vchi_mutex);
+- vchi_service_use(instance->vchi_handle[0]);
++ vchi_service_use(instance->vchi_handle);
+
+ instance->result = -1;
+
+@@ -487,7 +433,7 @@ int bcm2835_audio_set_ctls(struct bcm283
+ init_completion(&instance->msg_avail_comp);
+
+ /* Send the message to the videocore */
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+ &m, sizeof(m));
+
+ if (status) {
+@@ -511,7 +457,7 @@ int bcm2835_audio_set_ctls(struct bcm283
+ ret = 0;
+
+ unlock:
+- vchi_service_release(instance->vchi_handle[0]);
++ vchi_service_release(instance->vchi_handle);
+ mutex_unlock(&instance->vchi_mutex);
+
+ return ret;
+@@ -537,7 +483,7 @@ int bcm2835_audio_set_params(struct bcm2
+ }
+
+ mutex_lock(&instance->vchi_mutex);
+- vchi_service_use(instance->vchi_handle[0]);
++ vchi_service_use(instance->vchi_handle);
+
+ instance->result = -1;
+
+@@ -550,7 +496,7 @@ int bcm2835_audio_set_params(struct bcm2
+ init_completion(&instance->msg_avail_comp);
+
+ /* Send the message to the videocore */
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+ &m, sizeof(m));
+
+ if (status) {
+@@ -574,7 +520,7 @@ int bcm2835_audio_set_params(struct bcm2
+ ret = 0;
+
+ unlock:
+- vchi_service_release(instance->vchi_handle[0]);
++ vchi_service_release(instance->vchi_handle);
+ mutex_unlock(&instance->vchi_mutex);
+
+ return ret;
+@@ -588,12 +534,12 @@ static int bcm2835_audio_start_worker(st
+ int ret;
+
+ mutex_lock(&instance->vchi_mutex);
+- vchi_service_use(instance->vchi_handle[0]);
++ vchi_service_use(instance->vchi_handle);
+
+ m.type = VC_AUDIO_MSG_TYPE_START;
+
+ /* Send the message to the videocore */
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+ &m, sizeof(m));
+
+ if (status) {
+@@ -607,7 +553,7 @@ static int bcm2835_audio_start_worker(st
+ ret = 0;
+
+ unlock:
+- vchi_service_release(instance->vchi_handle[0]);
++ vchi_service_release(instance->vchi_handle);
+ mutex_unlock(&instance->vchi_mutex);
+ return ret;
+ }
+@@ -620,13 +566,13 @@ static int bcm2835_audio_stop_worker(str
+ int ret;
+
+ mutex_lock(&instance->vchi_mutex);
+- vchi_service_use(instance->vchi_handle[0]);
++ vchi_service_use(instance->vchi_handle);
+
+ m.type = VC_AUDIO_MSG_TYPE_STOP;
+ m.u.stop.draining = alsa_stream->draining;
+
+ /* Send the message to the videocore */
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+ &m, sizeof(m));
+
+ if (status) {
+@@ -640,7 +586,7 @@ static int bcm2835_audio_stop_worker(str
+ ret = 0;
+
+ unlock:
+- vchi_service_release(instance->vchi_handle[0]);
++ vchi_service_release(instance->vchi_handle);
+ mutex_unlock(&instance->vchi_mutex);
+ return ret;
+ }
+@@ -655,7 +601,7 @@ int bcm2835_audio_close(struct bcm2835_a
+ my_workqueue_quit(alsa_stream);
+
+ mutex_lock(&instance->vchi_mutex);
+- vchi_service_use(instance->vchi_handle[0]);
++ vchi_service_use(instance->vchi_handle);
+
+ m.type = VC_AUDIO_MSG_TYPE_CLOSE;
+
+@@ -663,7 +609,7 @@ int bcm2835_audio_close(struct bcm2835_a
+ init_completion(&instance->msg_avail_comp);
+
+ /* Send the message to the videocore */
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+ &m, sizeof(m));
+
+ if (status) {
+@@ -687,7 +633,7 @@ int bcm2835_audio_close(struct bcm2835_a
+ ret = 0;
+
+ unlock:
+- vchi_service_release(instance->vchi_handle[0]);
++ vchi_service_release(instance->vchi_handle);
+ mutex_unlock(&instance->vchi_mutex);
+
+ /* Stop the audio service */
+@@ -708,10 +654,10 @@ static int bcm2835_audio_write_worker(st
+ LOG_INFO(" Writing %d bytes from %p\n", count, src);
+
+ mutex_lock(&instance->vchi_mutex);
+- vchi_service_use(instance->vchi_handle[0]);
++ vchi_service_use(instance->vchi_handle);
+
+ if (instance->peer_version == 0 &&
+- vchi_get_peer_version(instance->vchi_handle[0], &instance->peer_version) == 0)
++ vchi_get_peer_version(instance->vchi_handle, &instance->peer_version) == 0)
+ LOG_DBG("%s: client version %d connected\n", __func__, instance->peer_version);
+
+ m.type = VC_AUDIO_MSG_TYPE_WRITE;
+@@ -723,7 +669,7 @@ static int bcm2835_audio_write_worker(st
+ m.u.write.silence = src == NULL;
+
+ /* Send the message to the videocore */
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+ &m, sizeof(m));
+
+ if (status) {
+@@ -736,7 +682,7 @@ static int bcm2835_audio_write_worker(st
+ if (!m.u.write.silence) {
+ if (!m.u.write.max_packet) {
+ /* Send the message to the videocore */
+- status = vchi_bulk_queue_transmit(instance->vchi_handle[0],
++ status = vchi_bulk_queue_transmit(instance->vchi_handle,
+ src, count,
+ 0 * VCHI_FLAGS_BLOCK_UNTIL_QUEUED
+ +
+@@ -746,7 +692,7 @@ static int bcm2835_audio_write_worker(st
+ while (count > 0) {
+ int bytes = min_t(int, m.u.write.max_packet, count);
+
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+ src, bytes);
+ src = (char *)src + bytes;
+ count -= bytes;
+@@ -763,7 +709,7 @@ static int bcm2835_audio_write_worker(st
+ ret = 0;
+
+ unlock:
+- vchi_service_release(instance->vchi_handle[0]);
++ vchi_service_release(instance->vchi_handle);
+ mutex_unlock(&instance->vchi_mutex);
+ return ret;
+ }
--- /dev/null
+From 4cb3893de2db276e3db35ad61092c9f9cf2f705d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:48 +0200
+Subject: [PATCH 455/725] staging: bcm2835-audio: Code refactoring of vchiq
+ accessor codes
+
+commit 769a8e9bf5cf39813f52962fdafdf7e4d52ad585 upstream.
+
+This is a cleanup and code refactoring in bcm2835-vchiq.c.
+
+The major code changes are to provide local helpers for easier use of
+lock / unlock, and message passing with/without response wait. This
+allows us to reduce lots of open codes.
+
+Also, the max packet is set at opening the stream, not at each time
+when the write gets called.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../bcm2835-audio/bcm2835-vchiq.c | 440 ++++++------------
+ 1 file changed, 142 insertions(+), 298 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -49,6 +49,7 @@ struct bcm2835_audio_instance {
+ struct mutex vchi_mutex;
+ struct bcm2835_alsa_stream *alsa_stream;
+ int result;
++ unsigned int max_packet;
+ short peer_version;
+ };
+
+@@ -65,16 +66,68 @@ static int bcm2835_audio_start_worker(st
+ static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
+ unsigned int count, void *src);
+
+-// Routine to send a message across a service
++static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
++{
++ mutex_lock(&instance->vchi_mutex);
++ vchi_service_use(instance->vchi_handle);
++}
++
++static void bcm2835_audio_unlock(struct bcm2835_audio_instance *instance)
++{
++ vchi_service_release(instance->vchi_handle);
++ mutex_unlock(&instance->vchi_mutex);
++}
++
++static int bcm2835_audio_send_msg_locked(struct bcm2835_audio_instance *instance,
++ struct vc_audio_msg *m, bool wait)
++{
++ int status;
++
++ if (wait) {
++ instance->result = -1;
++ init_completion(&instance->msg_avail_comp);
++ }
++
++ status = vchi_queue_kernel_message(instance->vchi_handle,
++ m, sizeof(*m));
++ if (status) {
++ LOG_ERR("vchi message queue failed: %d, msg=%d\n",
++ status, m->type);
++ return -EIO;
++ }
++
++ if (wait) {
++ if (!wait_for_completion_timeout(&instance->msg_avail_comp,
++ msecs_to_jiffies(10 * 1000))) {
++ LOG_ERR("vchi message timeout, msg=%d\n", m->type);
++ return -ETIMEDOUT;
++ } else if (instance->result) {
++ LOG_ERR("vchi message response error:%d, msg=%d\n",
++ instance->result, m->type);
++ return -EIO;
++ }
++ }
++
++ return 0;
++}
+
+-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 int bcm2835_audio_send_msg(struct bcm2835_audio_instance *instance,
++ struct vc_audio_msg *m, bool wait)
++{
++ int err;
++
++ bcm2835_audio_lock(instance);
++ err = bcm2835_audio_send_msg_locked(instance, m, wait);
++ bcm2835_audio_unlock(instance);
++ return err;
++}
++
++static int bcm2835_audio_send_simple(struct bcm2835_audio_instance *instance,
++ int type, bool wait)
++{
++ struct vc_audio_msg m = { .type = type };
++
++ return bcm2835_audio_send_msg(instance, &m, wait);
+ }
+
+ static const u32 BCM2835_AUDIO_WRITE_COOKIE1 = ('B' << 24 | 'C' << 16 |
+@@ -283,10 +336,9 @@ static int vc_vchi_audio_deinit(struct b
+ int status;
+
+ mutex_lock(&instance->vchi_mutex);
+-
+- /* Close all VCHI service connections */
+ vchi_service_use(instance->vchi_handle);
+
++ /* Close all VCHI service connections */
+ status = vchi_service_close(instance->vchi_handle);
+ if (status) {
+ LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
+@@ -345,12 +397,8 @@ static int bcm2835_audio_open_connection
+ instance = vc_vchi_audio_init(vhci_ctx->vchi_instance,
+ vhci_ctx->vchi_connection);
+
+- if (IS_ERR(instance)) {
+- LOG_ERR("%s: failed to initialize audio service\n", __func__);
+-
+- /* vchi_instance is retained for use the next time. */
++ if (IS_ERR(instance))
+ return PTR_ERR(instance);
+- }
+
+ instance->alsa_stream = alsa_stream;
+ alsa_stream->instance = instance;
+@@ -361,66 +409,44 @@ static int bcm2835_audio_open_connection
+ int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream)
+ {
+ struct bcm2835_audio_instance *instance;
+- struct vc_audio_msg m;
+- int status;
+- int ret;
++ int err;
+
+ alsa_stream->my_wq = alloc_workqueue("my_queue", WQ_HIGHPRI, 1);
+ if (!alsa_stream->my_wq)
+ return -ENOMEM;
+
+- ret = bcm2835_audio_open_connection(alsa_stream);
+- if (ret)
++ err = bcm2835_audio_open_connection(alsa_stream);
++ if (err < 0)
+ goto free_wq;
+
+ instance = alsa_stream->instance;
+- LOG_DBG(" instance (%p)\n", instance);
+-
+- mutex_lock(&instance->vchi_mutex);
+- vchi_service_use(instance->vchi_handle);
+-
+- m.type = VC_AUDIO_MSG_TYPE_OPEN;
+-
+- /* Send the message to the videocore */
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+- &m, sizeof(m));
+-
+- if (status) {
+- LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+- __func__, status);
+-
+- ret = -1;
+- goto unlock;
+- }
+-
+- ret = 0;
+
+-unlock:
+- vchi_service_release(instance->vchi_handle);
+- mutex_unlock(&instance->vchi_mutex);
++ err = bcm2835_audio_send_simple(instance, VC_AUDIO_MSG_TYPE_OPEN,
++ false);
++ if (err < 0)
++ goto deinit;
++
++ bcm2835_audio_lock(instance);
++ vchi_get_peer_version(instance->vchi_handle, &instance->peer_version);
++ bcm2835_audio_unlock(instance);
++ if (instance->peer_version < 2 || force_bulk)
++ instance->max_packet = 0; /* bulk transfer */
++ else
++ instance->max_packet = 4000;
+
+-free_wq:
+- if (ret)
+- destroy_workqueue(alsa_stream->my_wq);
++ return 0;
+
+- return ret;
++ deinit:
++ vc_vchi_audio_deinit(instance);
++ free_wq:
++ destroy_workqueue(alsa_stream->my_wq);
++ return err;
+ }
+
+ int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream)
+ {
+- struct vc_audio_msg m;
+- struct bcm2835_audio_instance *instance = alsa_stream->instance;
+ struct bcm2835_chip *chip = alsa_stream->chip;
+- int status;
+- int ret;
+-
+- LOG_INFO(" Setting ALSA dest(%d), volume(%d)\n",
+- chip->dest, chip->volume);
+-
+- mutex_lock(&instance->vchi_mutex);
+- vchi_service_use(instance->vchi_handle);
+-
+- instance->result = -1;
++ struct vc_audio_msg m = {};
+
+ m.type = VC_AUDIO_MSG_TYPE_CONTROL;
+ m.u.control.dest = chip->dest;
+@@ -429,289 +455,107 @@ int bcm2835_audio_set_ctls(struct bcm283
+ else
+ m.u.control.volume = alsa2chip(chip->volume);
+
+- /* Create the message available completion */
+- init_completion(&instance->msg_avail_comp);
+-
+- /* Send the message to the videocore */
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+- &m, sizeof(m));
+-
+- if (status) {
+- LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+- __func__, status);
+-
+- ret = -1;
+- goto unlock;
+- }
+-
+- /* We are expecting a reply from the videocore */
+- wait_for_completion(&instance->msg_avail_comp);
+-
+- if (instance->result) {
+- LOG_ERR("%s: result=%d\n", __func__, instance->result);
+-
+- ret = -1;
+- goto unlock;
+- }
+-
+- ret = 0;
+-
+-unlock:
+- vchi_service_release(instance->vchi_handle);
+- mutex_unlock(&instance->vchi_mutex);
+-
+- return ret;
++ return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
+ }
+
+ int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
+ unsigned int channels, unsigned int samplerate,
+ unsigned int bps)
+ {
+- struct vc_audio_msg m;
+- struct bcm2835_audio_instance *instance = alsa_stream->instance;
+- int status;
+- int ret;
+-
+- LOG_INFO(" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n",
+- channels, samplerate, bps);
++ struct vc_audio_msg m = {
++ .type = VC_AUDIO_MSG_TYPE_CONFIG,
++ .u.config.channels = channels,
++ .u.config.samplerate = samplerate,
++ .u.config.bps = bps,
++ };
++ int err;
+
+ /* resend ctls - alsa_stream may not have been open when first send */
+- ret = bcm2835_audio_set_ctls(alsa_stream);
+- if (ret) {
+- LOG_ERR(" Alsa controls not supported\n");
+- return -EINVAL;
+- }
++ err = bcm2835_audio_set_ctls(alsa_stream);
++ if (err)
++ return err;
+
+- mutex_lock(&instance->vchi_mutex);
+- vchi_service_use(instance->vchi_handle);
+-
+- 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 */
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+- &m, sizeof(m));
+-
+- if (status) {
+- LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+- __func__, status);
+-
+- ret = -1;
+- goto unlock;
+- }
+-
+- /* We are expecting a reply from the videocore */
+- wait_for_completion(&instance->msg_avail_comp);
+-
+- if (instance->result) {
+- LOG_ERR("%s: result=%d", __func__, instance->result);
+-
+- ret = -1;
+- goto unlock;
+- }
+-
+- ret = 0;
+-
+-unlock:
+- vchi_service_release(instance->vchi_handle);
+- mutex_unlock(&instance->vchi_mutex);
+-
+- return ret;
++ return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
+ }
+
+ static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream)
+ {
+- struct vc_audio_msg m;
+- struct bcm2835_audio_instance *instance = alsa_stream->instance;
+- int status;
+- int ret;
+-
+- mutex_lock(&instance->vchi_mutex);
+- vchi_service_use(instance->vchi_handle);
+-
+- m.type = VC_AUDIO_MSG_TYPE_START;
+-
+- /* Send the message to the videocore */
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+- &m, sizeof(m));
+-
+- if (status) {
+- LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+- __func__, status);
+-
+- ret = -1;
+- goto unlock;
+- }
+-
+- ret = 0;
+-
+-unlock:
+- vchi_service_release(instance->vchi_handle);
+- mutex_unlock(&instance->vchi_mutex);
+- return ret;
++ return bcm2835_audio_send_simple(alsa_stream->instance,
++ VC_AUDIO_MSG_TYPE_START, false);
+ }
+
+ static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream)
+ {
+- struct vc_audio_msg m;
+- struct bcm2835_audio_instance *instance = alsa_stream->instance;
+- int status;
+- int ret;
+-
+- mutex_lock(&instance->vchi_mutex);
+- vchi_service_use(instance->vchi_handle);
+-
+- m.type = VC_AUDIO_MSG_TYPE_STOP;
+- m.u.stop.draining = alsa_stream->draining;
+-
+- /* Send the message to the videocore */
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+- &m, sizeof(m));
+-
+- if (status) {
+- LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+- __func__, status);
+-
+- ret = -1;
+- goto unlock;
+- }
+-
+- ret = 0;
+-
+-unlock:
+- vchi_service_release(instance->vchi_handle);
+- mutex_unlock(&instance->vchi_mutex);
+- return ret;
++ return bcm2835_audio_send_simple(alsa_stream->instance,
++ VC_AUDIO_MSG_TYPE_STOP, false);
+ }
+
+ int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream)
+ {
+- struct vc_audio_msg m;
+ struct bcm2835_audio_instance *instance = alsa_stream->instance;
+- int status;
+- int ret;
++ int err;
+
+ my_workqueue_quit(alsa_stream);
+
+- mutex_lock(&instance->vchi_mutex);
+- vchi_service_use(instance->vchi_handle);
+-
+- m.type = VC_AUDIO_MSG_TYPE_CLOSE;
+-
+- /* Create the message available completion */
+- init_completion(&instance->msg_avail_comp);
+-
+- /* Send the message to the videocore */
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+- &m, sizeof(m));
+-
+- if (status) {
+- LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+- __func__, status);
+- ret = -1;
+- goto unlock;
+- }
+-
+- /* We are expecting a reply from the videocore */
+- wait_for_completion(&instance->msg_avail_comp);
+-
+- if (instance->result) {
+- LOG_ERR("%s: failed result (result=%d)\n",
+- __func__, instance->result);
+-
+- ret = -1;
+- goto unlock;
+- }
+-
+- ret = 0;
+-
+-unlock:
+- vchi_service_release(instance->vchi_handle);
+- mutex_unlock(&instance->vchi_mutex);
++ err = bcm2835_audio_send_simple(alsa_stream->instance,
++ VC_AUDIO_MSG_TYPE_CLOSE, true);
+
+ /* Stop the audio service */
+ vc_vchi_audio_deinit(instance);
+ alsa_stream->instance = NULL;
+
+- return ret;
++ return err;
+ }
+
+ static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
+- unsigned int count, void *src)
++ unsigned int size, void *src)
+ {
+- struct vc_audio_msg m;
+ struct bcm2835_audio_instance *instance = alsa_stream->instance;
+- int status;
+- int ret;
+-
+- LOG_INFO(" Writing %d bytes from %p\n", count, src);
+-
+- mutex_lock(&instance->vchi_mutex);
+- vchi_service_use(instance->vchi_handle);
++ struct vc_audio_msg m = {
++ .type = VC_AUDIO_MSG_TYPE_WRITE,
++ .u.write.count = size,
++ .u.write.max_packet = instance->max_packet,
++ .u.write.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1,
++ .u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2,
++ };
++ unsigned int count;
++ int err, status;
+
+- if (instance->peer_version == 0 &&
+- vchi_get_peer_version(instance->vchi_handle, &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.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1;
+- m.u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2;
+- m.u.write.silence = src == NULL;
+-
+- /* Send the message to the videocore */
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+- &m, sizeof(m));
++ if (!size)
++ return 0;
+
+- if (status) {
+- LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
+- __func__, status);
+-
+- ret = -1;
++ bcm2835_audio_lock(instance);
++ err = bcm2835_audio_send_msg_locked(instance, &m, false);
++ if (err < 0)
+ goto unlock;
+- }
+- if (!m.u.write.silence) {
+- if (!m.u.write.max_packet) {
+- /* Send the message to the videocore */
+- status = vchi_bulk_queue_transmit(instance->vchi_handle,
+- src, count,
+- 0 * VCHI_FLAGS_BLOCK_UNTIL_QUEUED
+- +
+- 1 * VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
+- NULL);
+- } else {
+- while (count > 0) {
+- int bytes = min_t(int, m.u.write.max_packet, count);
+
+- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
+- src, bytes);
+- src = (char *)src + bytes;
+- count -= bytes;
+- }
+- }
+- if (status) {
+- LOG_ERR("%s: failed on vchi_bulk_queue_transmit (status=%d)\n",
+- __func__, status);
++ count = size;
++ if (!instance->max_packet) {
++ /* Send the message to the videocore */
++ status = vchi_bulk_queue_transmit(instance->vchi_handle,
++ src, count,
++ VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
++ NULL);
++ } else {
++ while (count > 0) {
++ int bytes = min(instance->max_packet, count);
+
+- ret = -1;
+- goto unlock;
++ status = vchi_queue_kernel_message(instance->vchi_handle,
++ src, bytes);
++ src += bytes;
++ count -= bytes;
+ }
+ }
+- ret = 0;
+
+-unlock:
+- vchi_service_release(instance->vchi_handle);
+- mutex_unlock(&instance->vchi_mutex);
+- return ret;
++ if (status) {
++ LOG_ERR("failed on %d bytes transfer (status=%d)\n",
++ size, status);
++ err = -EIO;
++ }
++
++ unlock:
++ bcm2835_audio_unlock(instance);
++ return err;
+ }
+
+ unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream)
+++ /dev/null
-From 1eb403fb6c5f6b8bea96e9bd0d6b87949aab172f Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:45 +0200
-Subject: [PATCH 455/703] staging: bcm2835-audio: Drop superfluous mutex lock
- during prepare
-
-commit f0eb15d055380ff127e5f12c8fad2b36bdb3c006 upstream.
-
-The chip->audio_mutex is used basically for protecting the opened
-stream assignment, and the prepare callback is irrelevant with it.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 8 ++------
- 1 file changed, 2 insertions(+), 6 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -218,8 +218,6 @@ static int snd_bcm2835_pcm_prepare(struc
- int channels;
- int err;
-
-- mutex_lock(&chip->audio_mutex);
--
- /* notify the vchiq that it should enter spdif passthrough mode by
- * setting channels=0 (see
- * https://github.com/raspberrypi/linux/issues/528)
-@@ -233,7 +231,7 @@ static int snd_bcm2835_pcm_prepare(struc
- runtime->rate,
- snd_pcm_format_width(runtime->format));
- if (err < 0)
-- goto out;
-+ return err;
-
- memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
-
-@@ -246,9 +244,7 @@ static int snd_bcm2835_pcm_prepare(struc
- alsa_stream->pos = 0;
- alsa_stream->draining = false;
-
-- out:
-- mutex_unlock(&chip->audio_mutex);
-- return err;
-+ return 0;
- }
-
- static void snd_bcm2835_pcm_transfer(struct snd_pcm_substream *substream,
+++ /dev/null
-From c0c56af886a1f7078dcd78ab46d7480009b080a2 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:46 +0200
-Subject: [PATCH 456/703] staging: bcm2835-audio: Add 10ms period constraint
-
-commit 93c66acaf68b5247c3121a46a71ff6a70fc1d492 upstream.
-
-It seems that the resolution of vc04 callback is in 10 msec; i.e. the
-minimal period size is also 10 msec.
-
-This patch adds the corresponding hw constraint.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -145,6 +145,11 @@ static int snd_bcm2835_playback_open_gen
- SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
- 16);
-
-+ /* position update is in 10ms order */
-+ snd_pcm_hw_constraint_minmax(runtime,
-+ SNDRV_PCM_HW_PARAM_PERIOD_TIME,
-+ 10 * 1000, UINT_MAX);
-+
- chip->alsa_stream[idx] = alsa_stream;
-
- chip->opened |= (1 << idx);
--- /dev/null
+From 43fad60114297457914dae77debd68ed185f66e9 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:49 +0200
+Subject: [PATCH 456/725] staging: bcm2835-audio: Operate non-atomic PCM ops
+
+commit 5c7883e5f27e829f3f3a2ba174d4a724bfd5f026 upstream.
+
+This is the most significant part in the patch series.
+
+The bcm2835-audio driver used to queue the commands to vc04 core via
+workqueue, but basically the whole accesses to vc04 core are done in
+the sleepable context, including the callback calls. In such a case,
+rewriting the code using non-atomic PCM ops will simplify the logic a
+lot.
+
+This patch does it: all workqueue are gone and each former-work
+implementation is now directly called from PCM ops like trigger and
+write transfer.
+
+Along with it, the DMA position updater, bcm2835_playback_fifo(), was
+also rewritten to use a simpler logic. Now it handles the XRUN and
+draining properly by calling snd_pcm_stop() conditionally.
+
+The current position is kept in atomic_t value so that it can be read
+concurrently from the pointer callback.
+
+Also, the bcm2835_audio_instance object is allocated at the beginning
+of bcm2835_audio_open(). This makes the resource management clearer.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 74 +++---
+ .../bcm2835-audio/bcm2835-vchiq.c | 244 +++---------------
+ .../vc04_services/bcm2835-audio/bcm2835.h | 9 +-
+ 3 files changed, 82 insertions(+), 245 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -11,7 +11,8 @@
+ /* hardware definition */
+ static const 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),
++ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
++ SNDRV_PCM_INFO_DRAIN_TRIGGER),
+ .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+@@ -27,7 +28,8 @@ static const struct snd_pcm_hardware snd
+
+ static const 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),
++ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
++ SNDRV_PCM_INFO_DRAIN_TRIGGER),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000,
+@@ -47,42 +49,34 @@ static void snd_bcm2835_playback_free(st
+ kfree(runtime->private_data);
+ }
+
+-void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream)
++void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream,
++ unsigned int bytes)
+ {
+- unsigned int consumed = 0;
+- int new_period = 0;
++ struct snd_pcm_substream *substream = alsa_stream->substream;
++ unsigned int pos;
+
+- audio_info("alsa_stream=%p substream=%p\n", alsa_stream,
+- alsa_stream ? alsa_stream->substream : 0);
++ if (!alsa_stream->period_size)
++ return;
+
+- 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 (bytes >= alsa_stream->buffer_size) {
++ snd_pcm_stream_lock(substream);
++ snd_pcm_stop(substream,
++ alsa_stream->draining ?
++ SNDRV_PCM_STATE_SETUP :
++ SNDRV_PCM_STATE_XRUN);
++ snd_pcm_stream_unlock(substream);
++ return;
+ }
+
+- if (alsa_stream->substream) {
+- if (new_period)
+- snd_pcm_period_elapsed(alsa_stream->substream);
+- } else {
+- audio_warning(" unexpected NULL substream\n");
++ pos = atomic_read(&alsa_stream->pos);
++ pos += bytes;
++ pos %= alsa_stream->buffer_size;
++ atomic_set(&alsa_stream->pos, pos);
++
++ alsa_stream->period_offset += bytes;
++ if (alsa_stream->period_offset >= alsa_stream->period_size) {
++ alsa_stream->period_offset %= alsa_stream->period_size;
++ snd_pcm_period_elapsed(substream);
+ }
+ }
+
+@@ -246,7 +240,8 @@ static int snd_bcm2835_pcm_prepare(struc
+
+ alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
+ alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
+- alsa_stream->pos = 0;
++ atomic_set(&alsa_stream->pos, 0);
++ alsa_stream->period_offset = 0;
+ alsa_stream->draining = false;
+
+ return 0;
+@@ -283,7 +278,7 @@ static int snd_bcm2835_pcm_trigger(struc
+ return bcm2835_audio_start(alsa_stream);
+ case SNDRV_PCM_TRIGGER_DRAIN:
+ alsa_stream->draining = true;
+- return 0;
++ return bcm2835_audio_drain(alsa_stream);
+ case SNDRV_PCM_TRIGGER_STOP:
+ return bcm2835_audio_stop(alsa_stream);
+ default:
+@@ -300,7 +295,7 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
+
+ return snd_pcm_indirect_playback_pointer(substream,
+ &alsa_stream->pcm_indirect,
+- alsa_stream->pos);
++ atomic_read(&alsa_stream->pos));
+ }
+
+ /* operators */
+@@ -338,6 +333,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
+ if (err < 0)
+ return err;
+ pcm->private_data = chip;
++ pcm->nonatomic = true;
+ strcpy(pcm->name, "bcm2835 ALSA");
+ chip->pcm = pcm;
+ chip->dest = AUDIO_DEST_AUTO;
+@@ -367,6 +363,7 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
+ return err;
+
+ pcm->private_data = chip;
++ pcm->nonatomic = true;
+ strcpy(pcm->name, "bcm2835 IEC958/HDMI");
+ chip->pcm_spdif = pcm;
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+@@ -395,6 +392,7 @@ int snd_bcm2835_new_simple_pcm(struct bc
+ return err;
+
+ pcm->private_data = chip;
++ pcm->nonatomic = true;
+ strcpy(pcm->name, name);
+ chip->pcm = pcm;
+ chip->dest = route;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -26,10 +26,6 @@
+
+ /* ---- 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)
+@@ -55,17 +51,6 @@ struct bcm2835_audio_instance {
+
+ static bool force_bulk;
+
+-/* ---- Private Variables ---------------------------------------------------- */
+-
+-/* ---- Private Function Prototypes ------------------------------------------ */
+-
+-/* ---- Private Functions ---------------------------------------------------- */
+-
+-static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream);
+-static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream);
+-static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
+- unsigned int count, void *src);
+-
+ static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
+ {
+ mutex_lock(&instance->vchi_mutex);
+@@ -135,108 +120,6 @@ static const u32 BCM2835_AUDIO_WRITE_COO
+ static const u32 BCM2835_AUDIO_WRITE_COOKIE2 = ('D' << 24 | 'A' << 16 |
+ 'T' << 8 | 'A');
+
+-struct bcm2835_audio_work {
+- struct work_struct my_work;
+- struct bcm2835_alsa_stream *alsa_stream;
+- int cmd;
+- void *src;
+- unsigned int count;
+-};
+-
+-static void my_wq_function(struct work_struct *work)
+-{
+- struct bcm2835_audio_work *w =
+- container_of(work, struct bcm2835_audio_work, my_work);
+- int ret = -9;
+-
+- 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);
+-}
+-
+-int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream)
+-{
+- struct bcm2835_audio_work *work;
+-
+- work = kmalloc(sizeof(*work), GFP_ATOMIC);
+- /*--- Queue some work (item 1) ---*/
+- if (!work) {
+- LOG_ERR(" .. Error: NULL work kmalloc\n");
+- return -ENOMEM;
+- }
+- INIT_WORK(&work->my_work, my_wq_function);
+- work->alsa_stream = alsa_stream;
+- work->cmd = BCM2835_AUDIO_START;
+- if (!queue_work(alsa_stream->my_wq, &work->my_work)) {
+- kfree(work);
+- return -EBUSY;
+- }
+- return 0;
+-}
+-
+-int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream)
+-{
+- struct bcm2835_audio_work *work;
+-
+- work = kmalloc(sizeof(*work), GFP_ATOMIC);
+- /*--- Queue some work (item 1) ---*/
+- if (!work) {
+- LOG_ERR(" .. Error: NULL work kmalloc\n");
+- return -ENOMEM;
+- }
+- INIT_WORK(&work->my_work, my_wq_function);
+- work->alsa_stream = alsa_stream;
+- work->cmd = BCM2835_AUDIO_STOP;
+- if (!queue_work(alsa_stream->my_wq, &work->my_work)) {
+- kfree(work);
+- return -EBUSY;
+- }
+- return 0;
+-}
+-
+-int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
+- unsigned int count, void *src)
+-{
+- struct bcm2835_audio_work *work;
+-
+- work = kmalloc(sizeof(*work), GFP_ATOMIC);
+- /*--- Queue some work (item 1) ---*/
+- if (!work) {
+- LOG_ERR(" .. Error: NULL work kmalloc\n");
+- return -ENOMEM;
+- }
+- INIT_WORK(&work->my_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, &work->my_work)) {
+- kfree(work);
+- return -EBUSY;
+- }
+- return 0;
+-}
+-
+-static void my_workqueue_quit(struct bcm2835_alsa_stream *alsa_stream)
+-{
+- flush_workqueue(alsa_stream->my_wq);
+- destroy_workqueue(alsa_stream->my_wq);
+- alsa_stream->my_wq = NULL;
+-}
+-
+ static void audio_vchi_callback(void *param,
+ const VCHI_CALLBACK_REASON_T reason,
+ void *msg_handle)
+@@ -249,47 +132,27 @@ static void audio_vchi_callback(void *pa
+ if (reason != VCHI_CALLBACK_MSG_AVAILABLE)
+ return;
+
+- if (!instance) {
+- LOG_ERR(" .. instance is null\n");
+- BUG();
+- return;
+- }
+- if (!instance->vchi_handle) {
+- LOG_ERR(" .. instance->vchi_handle is null\n");
+- BUG();
+- return;
+- }
+ status = vchi_msg_dequeue(instance->vchi_handle,
+ &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) {
+- struct bcm2835_alsa_stream *alsa_stream = instance->alsa_stream;
+-
+- LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n",
+- instance, m.u.complete.count);
+ if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 ||
+ m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2)
+- LOG_ERR(" .. response is corrupt\n");
+- else if (alsa_stream) {
+- atomic_add(m.u.complete.count,
+- &alsa_stream->retrieved);
+- bcm2835_playback_fifo(alsa_stream);
+- } else {
+- LOG_ERR(" .. unexpected alsa_stream=%p\n",
+- alsa_stream);
+- }
++ LOG_ERR("invalid cookie\n");
++ else
++ bcm2835_playback_fifo(instance->alsa_stream,
++ m.u.complete.count);
+ } else {
+- LOG_ERR(" .. unexpected m.type=%d\n", m.type);
++ LOG_ERR("unexpected callback type=%d\n", m.type);
+ }
+ }
+
+-static struct bcm2835_audio_instance *
++static int
+ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance,
+- VCHI_CONNECTION_T *vchi_connection)
++ VCHI_CONNECTION_T *vchi_connection,
++ struct bcm2835_audio_instance *instance)
+ {
+ SERVICE_CREATION_T params = {
+ .version = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
+@@ -298,23 +161,14 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
+ .rx_fifo_size = 0,
+ .tx_fifo_size = 0,
+ .callback = audio_vchi_callback,
++ .callback_param = instance,
+ .want_unaligned_bulk_rx = 1, //TODO: remove VCOS_FALSE
+ .want_unaligned_bulk_tx = 1, //TODO: remove VCOS_FALSE
+ .want_crc = 0
+ };
+- struct bcm2835_audio_instance *instance;
+ int status;
+
+- /* Allocate memory for this instance */
+- instance = kzalloc(sizeof(*instance), GFP_KERNEL);
+- if (!instance)
+- return ERR_PTR(-ENOMEM);
+-
+- /* Create a lock for exclusive, serialized VCHI connection access */
+- mutex_init(&instance->vchi_mutex);
+ /* Open the VCHI service connections */
+- params.callback_param = instance,
+-
+ status = vchi_service_open(vchi_instance, ¶ms,
+ &instance->vchi_handle);
+
+@@ -322,16 +176,16 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
+ LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
+ __func__, status);
+ kfree(instance);
+- return ERR_PTR(-EPERM);
++ return -EPERM;
+ }
+
+ /* Finished with the service for now */
+ vchi_service_release(instance->vchi_handle);
+
+- return instance;
++ return 0;
+ }
+
+-static int vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
++static void vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
+ {
+ int status;
+
+@@ -346,10 +200,6 @@ static int vc_vchi_audio_deinit(struct b
+ }
+
+ mutex_unlock(&instance->vchi_mutex);
+-
+- kfree(instance);
+-
+- return 0;
+ }
+
+ int bcm2835_new_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx)
+@@ -387,39 +237,25 @@ void bcm2835_free_vchi_ctx(struct bcm283
+ vchi_ctx->vchi_instance = NULL;
+ }
+
+-static int bcm2835_audio_open_connection(struct bcm2835_alsa_stream *alsa_stream)
+-{
+- struct bcm2835_audio_instance *instance =
+- (struct bcm2835_audio_instance *)alsa_stream->instance;
+- struct bcm2835_vchi_ctx *vhci_ctx = alsa_stream->chip->vchi_ctx;
+-
+- /* Initialize an instance of the audio service */
+- instance = vc_vchi_audio_init(vhci_ctx->vchi_instance,
+- vhci_ctx->vchi_connection);
+-
+- if (IS_ERR(instance))
+- return PTR_ERR(instance);
+-
+- instance->alsa_stream = alsa_stream;
+- alsa_stream->instance = instance;
+-
+- return 0;
+-}
+-
+ int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream)
+ {
++ struct bcm2835_vchi_ctx *vchi_ctx = alsa_stream->chip->vchi_ctx;
+ struct bcm2835_audio_instance *instance;
+ int err;
+
+- alsa_stream->my_wq = alloc_workqueue("my_queue", WQ_HIGHPRI, 1);
+- if (!alsa_stream->my_wq)
++ /* Allocate memory for this instance */
++ instance = kzalloc(sizeof(*instance), GFP_KERNEL);
++ if (!instance)
+ return -ENOMEM;
++ mutex_init(&instance->vchi_mutex);
++ instance->alsa_stream = alsa_stream;
++ alsa_stream->instance = instance;
+
+- err = bcm2835_audio_open_connection(alsa_stream);
++ err = vc_vchi_audio_init(vchi_ctx->vchi_instance,
++ vchi_ctx->vchi_connection,
++ instance);
+ if (err < 0)
+- goto free_wq;
+-
+- instance = alsa_stream->instance;
++ goto free_instance;
+
+ err = bcm2835_audio_send_simple(instance, VC_AUDIO_MSG_TYPE_OPEN,
+ false);
+@@ -438,8 +274,9 @@ int bcm2835_audio_open(struct bcm2835_al
+
+ deinit:
+ vc_vchi_audio_deinit(instance);
+- free_wq:
+- destroy_workqueue(alsa_stream->my_wq);
++ free_instance:
++ alsa_stream->instance = NULL;
++ kfree(instance);
+ return err;
+ }
+
+@@ -478,37 +315,46 @@ int bcm2835_audio_set_params(struct bcm2
+ return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
+ }
+
+-static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream)
++int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream)
+ {
+ return bcm2835_audio_send_simple(alsa_stream->instance,
+ VC_AUDIO_MSG_TYPE_START, false);
+ }
+
+-static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream)
++int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream)
+ {
+ return bcm2835_audio_send_simple(alsa_stream->instance,
+ VC_AUDIO_MSG_TYPE_STOP, false);
+ }
+
++int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream)
++{
++ struct vc_audio_msg m = {
++ .type = VC_AUDIO_MSG_TYPE_STOP,
++ .u.stop.draining = 1,
++ };
++
++ return bcm2835_audio_send_msg(alsa_stream->instance, &m, false);
++}
++
+ int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream)
+ {
+ struct bcm2835_audio_instance *instance = alsa_stream->instance;
+ int err;
+
+- my_workqueue_quit(alsa_stream);
+-
+ err = bcm2835_audio_send_simple(alsa_stream->instance,
+ VC_AUDIO_MSG_TYPE_CLOSE, true);
+
+ /* Stop the audio service */
+ vc_vchi_audio_deinit(instance);
+ alsa_stream->instance = NULL;
++ kfree(instance);
+
+ return err;
+ }
+
+-static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
+- unsigned int size, void *src)
++int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
++ unsigned int size, void *src)
+ {
+ struct bcm2835_audio_instance *instance = alsa_stream->instance;
+ struct vc_audio_msg m = {
+@@ -558,13 +404,5 @@ static int bcm2835_audio_write_worker(st
+ return err;
+ }
+
+-unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream)
+-{
+- unsigned int 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");
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -121,13 +121,12 @@ struct bcm2835_alsa_stream {
+
+ int draining;
+
+- unsigned int pos;
++ atomic_t pos;
++ unsigned int period_offset;
+ unsigned int buffer_size;
+ unsigned int period_size;
+
+- atomic_t retrieved;
+ struct bcm2835_audio_instance *instance;
+- struct workqueue_struct *my_wq;
+ int idx;
+ };
+
+@@ -152,11 +151,13 @@ int bcm2835_audio_set_params(struct bcm2
+ unsigned int bps);
+ int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream);
++int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream);
+ int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
+ unsigned int count,
+ void *src);
+-void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream);
++void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream,
++ unsigned int size);
+ unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream);
+
+ #endif /* __SOUND_ARM_BCM2835_H */
+++ /dev/null
-From 8456d764799cf7bc661892900cb08b3943e3bda2 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:47 +0200
-Subject: [PATCH 457/703] staging: bcm2835-audio: Make single vchi handle
-
-commit 326a6edcb2ada56375bd7d3fc24c83f58e8da7f3 upstream.
-
-The bcm2835_audio_instance object contains the array of
-VCHI_SERVICE_HANDLE_T, while the code assumes and uses only the first
-element explicitly. Let's reduce to a single vchi handle for
-simplifying the code.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../bcm2835-audio/bcm2835-vchiq.c | 170 ++++++------------
- 1 file changed, 58 insertions(+), 112 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -44,8 +44,7 @@
- #endif
-
- struct bcm2835_audio_instance {
-- unsigned int num_connections;
-- VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS];
-+ VCHI_SERVICE_HANDLE_T vchi_handle;
- struct completion msg_avail_comp;
- struct mutex vchi_mutex;
- struct bcm2835_alsa_stream *alsa_stream;
-@@ -202,12 +201,12 @@ static void audio_vchi_callback(void *pa
- BUG();
- return;
- }
-- if (!instance->vchi_handle[0]) {
-- LOG_ERR(" .. instance->vchi_handle[0] is null\n");
-+ if (!instance->vchi_handle) {
-+ LOG_ERR(" .. instance->vchi_handle is null\n");
- BUG();
- return;
- }
-- status = vchi_msg_dequeue(instance->vchi_handle[0],
-+ status = vchi_msg_dequeue(instance->vchi_handle,
- &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",
-@@ -237,102 +236,61 @@ static void audio_vchi_callback(void *pa
-
- static struct bcm2835_audio_instance *
- vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance,
-- VCHI_CONNECTION_T **vchi_connections,
-- unsigned int num_connections)
-+ VCHI_CONNECTION_T *vchi_connection)
- {
-- unsigned int i;
-+ SERVICE_CREATION_T params = {
-+ .version = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
-+ .service_id = VC_AUDIO_SERVER_NAME,
-+ .connection = vchi_connection,
-+ .rx_fifo_size = 0,
-+ .tx_fifo_size = 0,
-+ .callback = audio_vchi_callback,
-+ .want_unaligned_bulk_rx = 1, //TODO: remove VCOS_FALSE
-+ .want_unaligned_bulk_tx = 1, //TODO: remove VCOS_FALSE
-+ .want_crc = 0
-+ };
- struct bcm2835_audio_instance *instance;
- int status;
-- int ret;
--
-- 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 ERR_PTR(-EINVAL);
-- }
- /* Allocate memory for this instance */
- instance = kzalloc(sizeof(*instance), GFP_KERNEL);
- if (!instance)
- return ERR_PTR(-ENOMEM);
-
-- 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 = {
-- .version = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
-- .service_id = VC_AUDIO_SERVER_NAME,
-- .connection = vchi_connections[i],
-- .rx_fifo_size = 0,
-- .tx_fifo_size = 0,
-- .callback = audio_vchi_callback,
-- .callback_param = instance,
-- .want_unaligned_bulk_rx = 1, //TODO: remove VCOS_FALSE
-- .want_unaligned_bulk_tx = 1, //TODO: remove VCOS_FALSE
-- .want_crc = 0
-- };
--
-- LOG_DBG("%s: about to open %i\n", __func__, i);
-- status = vchi_service_open(vchi_instance, ¶ms,
-- &instance->vchi_handle[i]);
-+ params.callback_param = instance,
-
-- 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);
-- ret = -EPERM;
-- 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;
-+ status = vchi_service_open(vchi_instance, ¶ms,
-+ &instance->vchi_handle);
-
--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]);
-+ if (status) {
-+ LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
-+ __func__, status);
-+ kfree(instance);
-+ return ERR_PTR(-EPERM);
- }
-
-- kfree(instance);
-- LOG_ERR("%s: error\n", __func__);
-+ /* Finished with the service for now */
-+ vchi_service_release(instance->vchi_handle);
-
-- return ERR_PTR(ret);
-+ return instance;
- }
-
- static int vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
- {
-- unsigned int i;
--
-- if (!instance) {
-- LOG_ERR("%s: invalid handle %p\n", __func__, instance);
--
-- return -1;
-- }
-+ int status;
-
-- LOG_DBG(" .. about to lock (%d)\n", instance->num_connections);
- mutex_lock(&instance->vchi_mutex);
-
- /* Close all VCHI service connections */
-- for (i = 0; i < instance->num_connections; i++) {
-- int status;
--
-- LOG_DBG(" .. %i:closing %p\n", i, instance->vchi_handle[i]);
-- vchi_service_use(instance->vchi_handle[i]);
-+ vchi_service_use(instance->vchi_handle);
-
-- status = vchi_service_close(instance->vchi_handle[i]);
-- if (status) {
-- LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
-- __func__, status);
-- }
-+ status = vchi_service_close(instance->vchi_handle);
-+ if (status) {
-+ LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
-+ __func__, status);
- }
-
- mutex_unlock(&instance->vchi_mutex);
-@@ -383,19 +341,9 @@ static int bcm2835_audio_open_connection
- (struct bcm2835_audio_instance *)alsa_stream->instance;
- struct bcm2835_vchi_ctx *vhci_ctx = alsa_stream->chip->vchi_ctx;
-
-- 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;
-- return 0;
-- }
--
- /* Initialize an instance of the audio service */
- instance = vc_vchi_audio_init(vhci_ctx->vchi_instance,
-- &vhci_ctx->vchi_connection, 1);
-+ vhci_ctx->vchi_connection);
-
- if (IS_ERR(instance)) {
- LOG_ERR("%s: failed to initialize audio service\n", __func__);
-@@ -407,8 +355,6 @@ static int bcm2835_audio_open_connection
- instance->alsa_stream = alsa_stream;
- alsa_stream->instance = instance;
-
-- LOG_DBG(" success !\n");
--
- return 0;
- }
-
-@@ -431,12 +377,12 @@ int bcm2835_audio_open(struct bcm2835_al
- LOG_DBG(" instance (%p)\n", instance);
-
- mutex_lock(&instance->vchi_mutex);
-- vchi_service_use(instance->vchi_handle[0]);
-+ vchi_service_use(instance->vchi_handle);
-
- m.type = VC_AUDIO_MSG_TYPE_OPEN;
-
- /* Send the message to the videocore */
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
- &m, sizeof(m));
-
- if (status) {
-@@ -450,7 +396,7 @@ int bcm2835_audio_open(struct bcm2835_al
- ret = 0;
-
- unlock:
-- vchi_service_release(instance->vchi_handle[0]);
-+ vchi_service_release(instance->vchi_handle);
- mutex_unlock(&instance->vchi_mutex);
-
- free_wq:
-@@ -472,7 +418,7 @@ int bcm2835_audio_set_ctls(struct bcm283
- chip->dest, chip->volume);
-
- mutex_lock(&instance->vchi_mutex);
-- vchi_service_use(instance->vchi_handle[0]);
-+ vchi_service_use(instance->vchi_handle);
-
- instance->result = -1;
-
-@@ -487,7 +433,7 @@ int bcm2835_audio_set_ctls(struct bcm283
- init_completion(&instance->msg_avail_comp);
-
- /* Send the message to the videocore */
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
- &m, sizeof(m));
-
- if (status) {
-@@ -511,7 +457,7 @@ int bcm2835_audio_set_ctls(struct bcm283
- ret = 0;
-
- unlock:
-- vchi_service_release(instance->vchi_handle[0]);
-+ vchi_service_release(instance->vchi_handle);
- mutex_unlock(&instance->vchi_mutex);
-
- return ret;
-@@ -537,7 +483,7 @@ int bcm2835_audio_set_params(struct bcm2
- }
-
- mutex_lock(&instance->vchi_mutex);
-- vchi_service_use(instance->vchi_handle[0]);
-+ vchi_service_use(instance->vchi_handle);
-
- instance->result = -1;
-
-@@ -550,7 +496,7 @@ int bcm2835_audio_set_params(struct bcm2
- init_completion(&instance->msg_avail_comp);
-
- /* Send the message to the videocore */
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
- &m, sizeof(m));
-
- if (status) {
-@@ -574,7 +520,7 @@ int bcm2835_audio_set_params(struct bcm2
- ret = 0;
-
- unlock:
-- vchi_service_release(instance->vchi_handle[0]);
-+ vchi_service_release(instance->vchi_handle);
- mutex_unlock(&instance->vchi_mutex);
-
- return ret;
-@@ -588,12 +534,12 @@ static int bcm2835_audio_start_worker(st
- int ret;
-
- mutex_lock(&instance->vchi_mutex);
-- vchi_service_use(instance->vchi_handle[0]);
-+ vchi_service_use(instance->vchi_handle);
-
- m.type = VC_AUDIO_MSG_TYPE_START;
-
- /* Send the message to the videocore */
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
- &m, sizeof(m));
-
- if (status) {
-@@ -607,7 +553,7 @@ static int bcm2835_audio_start_worker(st
- ret = 0;
-
- unlock:
-- vchi_service_release(instance->vchi_handle[0]);
-+ vchi_service_release(instance->vchi_handle);
- mutex_unlock(&instance->vchi_mutex);
- return ret;
- }
-@@ -620,13 +566,13 @@ static int bcm2835_audio_stop_worker(str
- int ret;
-
- mutex_lock(&instance->vchi_mutex);
-- vchi_service_use(instance->vchi_handle[0]);
-+ vchi_service_use(instance->vchi_handle);
-
- m.type = VC_AUDIO_MSG_TYPE_STOP;
- m.u.stop.draining = alsa_stream->draining;
-
- /* Send the message to the videocore */
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
- &m, sizeof(m));
-
- if (status) {
-@@ -640,7 +586,7 @@ static int bcm2835_audio_stop_worker(str
- ret = 0;
-
- unlock:
-- vchi_service_release(instance->vchi_handle[0]);
-+ vchi_service_release(instance->vchi_handle);
- mutex_unlock(&instance->vchi_mutex);
- return ret;
- }
-@@ -655,7 +601,7 @@ int bcm2835_audio_close(struct bcm2835_a
- my_workqueue_quit(alsa_stream);
-
- mutex_lock(&instance->vchi_mutex);
-- vchi_service_use(instance->vchi_handle[0]);
-+ vchi_service_use(instance->vchi_handle);
-
- m.type = VC_AUDIO_MSG_TYPE_CLOSE;
-
-@@ -663,7 +609,7 @@ int bcm2835_audio_close(struct bcm2835_a
- init_completion(&instance->msg_avail_comp);
-
- /* Send the message to the videocore */
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
- &m, sizeof(m));
-
- if (status) {
-@@ -687,7 +633,7 @@ int bcm2835_audio_close(struct bcm2835_a
- ret = 0;
-
- unlock:
-- vchi_service_release(instance->vchi_handle[0]);
-+ vchi_service_release(instance->vchi_handle);
- mutex_unlock(&instance->vchi_mutex);
-
- /* Stop the audio service */
-@@ -708,10 +654,10 @@ static int bcm2835_audio_write_worker(st
- LOG_INFO(" Writing %d bytes from %p\n", count, src);
-
- mutex_lock(&instance->vchi_mutex);
-- vchi_service_use(instance->vchi_handle[0]);
-+ vchi_service_use(instance->vchi_handle);
-
- if (instance->peer_version == 0 &&
-- vchi_get_peer_version(instance->vchi_handle[0], &instance->peer_version) == 0)
-+ vchi_get_peer_version(instance->vchi_handle, &instance->peer_version) == 0)
- LOG_DBG("%s: client version %d connected\n", __func__, instance->peer_version);
-
- m.type = VC_AUDIO_MSG_TYPE_WRITE;
-@@ -723,7 +669,7 @@ static int bcm2835_audio_write_worker(st
- m.u.write.silence = src == NULL;
-
- /* Send the message to the videocore */
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
- &m, sizeof(m));
-
- if (status) {
-@@ -736,7 +682,7 @@ static int bcm2835_audio_write_worker(st
- if (!m.u.write.silence) {
- if (!m.u.write.max_packet) {
- /* Send the message to the videocore */
-- status = vchi_bulk_queue_transmit(instance->vchi_handle[0],
-+ status = vchi_bulk_queue_transmit(instance->vchi_handle,
- src, count,
- 0 * VCHI_FLAGS_BLOCK_UNTIL_QUEUED
- +
-@@ -746,7 +692,7 @@ static int bcm2835_audio_write_worker(st
- while (count > 0) {
- int bytes = min_t(int, m.u.write.max_packet, count);
-
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+ status = bcm2835_vchi_msg_queue(instance->vchi_handle,
- src, bytes);
- src = (char *)src + bytes;
- count -= bytes;
-@@ -763,7 +709,7 @@ static int bcm2835_audio_write_worker(st
- ret = 0;
-
- unlock:
-- vchi_service_release(instance->vchi_handle[0]);
-+ vchi_service_release(instance->vchi_handle);
- mutex_unlock(&instance->vchi_mutex);
- return ret;
- }
--- /dev/null
+From 45a6f73971c5e20f256ad2faa1c17d3525affa15 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:50 +0200
+Subject: [PATCH 457/725] staging: bcm2835-audio: Use card->private_data
+
+commit 898001a0c845cefe5d47d133485712412853f0a8 upstream.
+
+Instead of allocating a separate snd_device object, let snd_card_new()
+allocate the private resource. This simplifies the code.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835.c | 91 +++----------------
+ 1 file changed, 13 insertions(+), 78 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -86,9 +86,6 @@ static int bcm2835_devm_add_vchi_ctx(str
+
+ static void snd_bcm2835_release(struct device *dev)
+ {
+- struct bcm2835_chip *chip = dev_get_drvdata(dev);
+-
+- kfree(chip);
+ }
+
+ static struct device *
+@@ -117,69 +114,6 @@ snd_create_device(struct device *parent,
+ return device;
+ }
+
+-/* component-destructor
+- * (see "Management of Cards and Components")
+- */
+-static int snd_bcm2835_dev_free(struct snd_device *device)
+-{
+- struct bcm2835_chip *chip = device->device_data;
+- struct snd_card *card = chip->card;
+-
+- snd_device_free(card, chip);
+-
+- return 0;
+-}
+-
+-/* chip-specific constructor
+- * (see "Management of Cards and Components")
+- */
+-static int snd_bcm2835_create(struct snd_card *card,
+- struct bcm2835_chip **rchip)
+-{
+- struct bcm2835_chip *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)
+- return -ENOMEM;
+-
+- chip->card = card;
+- mutex_init(&chip->audio_mutex);
+-
+- chip->vchi_ctx = devres_find(card->dev->parent,
+- bcm2835_devm_free_vchi_ctx, NULL, NULL);
+- if (!chip->vchi_ctx) {
+- kfree(chip);
+- return -ENODEV;
+- }
+-
+- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+- if (err) {
+- kfree(chip);
+- return err;
+- }
+-
+- *rchip = chip;
+- return 0;
+-}
+-
+-static struct snd_card *snd_bcm2835_card_new(struct device *dev)
+-{
+- struct snd_card *card;
+- int ret;
+-
+- ret = snd_card_new(dev, -1, NULL, THIS_MODULE, 0, &card);
+- if (ret)
+- return ERR_PTR(ret);
+-
+- return card;
+-}
+-
+ typedef int (*bcm2835_audio_newpcm_func)(struct bcm2835_chip *chip,
+ const char *name,
+ enum snd_bcm2835_route route,
+@@ -292,25 +226,26 @@ static int snd_add_child_device(struct d
+ return PTR_ERR(child);
+ }
+
+- card = snd_bcm2835_card_new(child);
+- if (IS_ERR(card)) {
++ err = snd_card_new(child, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
++ if (err < 0) {
+ dev_err(child, "Failed to create card");
+- return PTR_ERR(card);
++ return err;
+ }
+
+- snd_card_set_dev(card, child);
++ chip = card->private_data;
++ chip->card = card;
++ chip->dev = child;
++ mutex_init(&chip->audio_mutex);
++
++ chip->vchi_ctx = devres_find(device,
++ bcm2835_devm_free_vchi_ctx, NULL, NULL);
++ if (!chip->vchi_ctx)
++ return -ENODEV;
++
+ strcpy(card->driver, audio_driver->driver.name);
+ strcpy(card->shortname, audio_driver->shortname);
+ strcpy(card->longname, audio_driver->longname);
+
+- err = snd_bcm2835_create(card, &chip);
+- if (err) {
+- dev_err(child, "Failed to create chip, error %d\n", err);
+- return err;
+- }
+-
+- chip->dev = child;
+-
+ err = audio_driver->newpcm(chip, audio_driver->shortname,
+ audio_driver->route,
+ numchans);
+++ /dev/null
-From 8ef08ec7a6a8f3bb42b8000e84cc444c88e60f8d Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:48 +0200
-Subject: [PATCH 458/703] staging: bcm2835-audio: Code refactoring of vchiq
- accessor codes
-
-commit 769a8e9bf5cf39813f52962fdafdf7e4d52ad585 upstream.
-
-This is a cleanup and code refactoring in bcm2835-vchiq.c.
-
-The major code changes are to provide local helpers for easier use of
-lock / unlock, and message passing with/without response wait. This
-allows us to reduce lots of open codes.
-
-Also, the max packet is set at opening the stream, not at each time
-when the write gets called.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../bcm2835-audio/bcm2835-vchiq.c | 440 ++++++------------
- 1 file changed, 142 insertions(+), 298 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -49,6 +49,7 @@ struct bcm2835_audio_instance {
- struct mutex vchi_mutex;
- struct bcm2835_alsa_stream *alsa_stream;
- int result;
-+ unsigned int max_packet;
- short peer_version;
- };
-
-@@ -65,16 +66,68 @@ static int bcm2835_audio_start_worker(st
- static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
- unsigned int count, void *src);
-
--// Routine to send a message across a service
-+static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
-+{
-+ mutex_lock(&instance->vchi_mutex);
-+ vchi_service_use(instance->vchi_handle);
-+}
-+
-+static void bcm2835_audio_unlock(struct bcm2835_audio_instance *instance)
-+{
-+ vchi_service_release(instance->vchi_handle);
-+ mutex_unlock(&instance->vchi_mutex);
-+}
-+
-+static int bcm2835_audio_send_msg_locked(struct bcm2835_audio_instance *instance,
-+ struct vc_audio_msg *m, bool wait)
-+{
-+ int status;
-+
-+ if (wait) {
-+ instance->result = -1;
-+ init_completion(&instance->msg_avail_comp);
-+ }
-+
-+ status = vchi_queue_kernel_message(instance->vchi_handle,
-+ m, sizeof(*m));
-+ if (status) {
-+ LOG_ERR("vchi message queue failed: %d, msg=%d\n",
-+ status, m->type);
-+ return -EIO;
-+ }
-+
-+ if (wait) {
-+ if (!wait_for_completion_timeout(&instance->msg_avail_comp,
-+ msecs_to_jiffies(10 * 1000))) {
-+ LOG_ERR("vchi message timeout, msg=%d\n", m->type);
-+ return -ETIMEDOUT;
-+ } else if (instance->result) {
-+ LOG_ERR("vchi message response error:%d, msg=%d\n",
-+ instance->result, m->type);
-+ return -EIO;
-+ }
-+ }
-+
-+ return 0;
-+}
-
--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 int bcm2835_audio_send_msg(struct bcm2835_audio_instance *instance,
-+ struct vc_audio_msg *m, bool wait)
-+{
-+ int err;
-+
-+ bcm2835_audio_lock(instance);
-+ err = bcm2835_audio_send_msg_locked(instance, m, wait);
-+ bcm2835_audio_unlock(instance);
-+ return err;
-+}
-+
-+static int bcm2835_audio_send_simple(struct bcm2835_audio_instance *instance,
-+ int type, bool wait)
-+{
-+ struct vc_audio_msg m = { .type = type };
-+
-+ return bcm2835_audio_send_msg(instance, &m, wait);
- }
-
- static const u32 BCM2835_AUDIO_WRITE_COOKIE1 = ('B' << 24 | 'C' << 16 |
-@@ -283,10 +336,9 @@ static int vc_vchi_audio_deinit(struct b
- int status;
-
- mutex_lock(&instance->vchi_mutex);
--
-- /* Close all VCHI service connections */
- vchi_service_use(instance->vchi_handle);
-
-+ /* Close all VCHI service connections */
- status = vchi_service_close(instance->vchi_handle);
- if (status) {
- LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
-@@ -345,12 +397,8 @@ static int bcm2835_audio_open_connection
- instance = vc_vchi_audio_init(vhci_ctx->vchi_instance,
- vhci_ctx->vchi_connection);
-
-- if (IS_ERR(instance)) {
-- LOG_ERR("%s: failed to initialize audio service\n", __func__);
--
-- /* vchi_instance is retained for use the next time. */
-+ if (IS_ERR(instance))
- return PTR_ERR(instance);
-- }
-
- instance->alsa_stream = alsa_stream;
- alsa_stream->instance = instance;
-@@ -361,66 +409,44 @@ static int bcm2835_audio_open_connection
- int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream)
- {
- struct bcm2835_audio_instance *instance;
-- struct vc_audio_msg m;
-- int status;
-- int ret;
-+ int err;
-
- alsa_stream->my_wq = alloc_workqueue("my_queue", WQ_HIGHPRI, 1);
- if (!alsa_stream->my_wq)
- return -ENOMEM;
-
-- ret = bcm2835_audio_open_connection(alsa_stream);
-- if (ret)
-+ err = bcm2835_audio_open_connection(alsa_stream);
-+ if (err < 0)
- goto free_wq;
-
- instance = alsa_stream->instance;
-- LOG_DBG(" instance (%p)\n", instance);
--
-- mutex_lock(&instance->vchi_mutex);
-- vchi_service_use(instance->vchi_handle);
--
-- m.type = VC_AUDIO_MSG_TYPE_OPEN;
--
-- /* Send the message to the videocore */
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-- &m, sizeof(m));
--
-- if (status) {
-- LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
-- __func__, status);
--
-- ret = -1;
-- goto unlock;
-- }
--
-- ret = 0;
-
--unlock:
-- vchi_service_release(instance->vchi_handle);
-- mutex_unlock(&instance->vchi_mutex);
-+ err = bcm2835_audio_send_simple(instance, VC_AUDIO_MSG_TYPE_OPEN,
-+ false);
-+ if (err < 0)
-+ goto deinit;
-+
-+ bcm2835_audio_lock(instance);
-+ vchi_get_peer_version(instance->vchi_handle, &instance->peer_version);
-+ bcm2835_audio_unlock(instance);
-+ if (instance->peer_version < 2 || force_bulk)
-+ instance->max_packet = 0; /* bulk transfer */
-+ else
-+ instance->max_packet = 4000;
-
--free_wq:
-- if (ret)
-- destroy_workqueue(alsa_stream->my_wq);
-+ return 0;
-
-- return ret;
-+ deinit:
-+ vc_vchi_audio_deinit(instance);
-+ free_wq:
-+ destroy_workqueue(alsa_stream->my_wq);
-+ return err;
- }
-
- int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream)
- {
-- struct vc_audio_msg m;
-- struct bcm2835_audio_instance *instance = alsa_stream->instance;
- struct bcm2835_chip *chip = alsa_stream->chip;
-- int status;
-- int ret;
--
-- LOG_INFO(" Setting ALSA dest(%d), volume(%d)\n",
-- chip->dest, chip->volume);
--
-- mutex_lock(&instance->vchi_mutex);
-- vchi_service_use(instance->vchi_handle);
--
-- instance->result = -1;
-+ struct vc_audio_msg m = {};
-
- m.type = VC_AUDIO_MSG_TYPE_CONTROL;
- m.u.control.dest = chip->dest;
-@@ -429,289 +455,107 @@ int bcm2835_audio_set_ctls(struct bcm283
- else
- m.u.control.volume = alsa2chip(chip->volume);
-
-- /* Create the message available completion */
-- init_completion(&instance->msg_avail_comp);
--
-- /* Send the message to the videocore */
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-- &m, sizeof(m));
--
-- if (status) {
-- LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
-- __func__, status);
--
-- ret = -1;
-- goto unlock;
-- }
--
-- /* We are expecting a reply from the videocore */
-- wait_for_completion(&instance->msg_avail_comp);
--
-- if (instance->result) {
-- LOG_ERR("%s: result=%d\n", __func__, instance->result);
--
-- ret = -1;
-- goto unlock;
-- }
--
-- ret = 0;
--
--unlock:
-- vchi_service_release(instance->vchi_handle);
-- mutex_unlock(&instance->vchi_mutex);
--
-- return ret;
-+ return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
- }
-
- int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
- unsigned int channels, unsigned int samplerate,
- unsigned int bps)
- {
-- struct vc_audio_msg m;
-- struct bcm2835_audio_instance *instance = alsa_stream->instance;
-- int status;
-- int ret;
--
-- LOG_INFO(" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n",
-- channels, samplerate, bps);
-+ struct vc_audio_msg m = {
-+ .type = VC_AUDIO_MSG_TYPE_CONFIG,
-+ .u.config.channels = channels,
-+ .u.config.samplerate = samplerate,
-+ .u.config.bps = bps,
-+ };
-+ int err;
-
- /* resend ctls - alsa_stream may not have been open when first send */
-- ret = bcm2835_audio_set_ctls(alsa_stream);
-- if (ret) {
-- LOG_ERR(" Alsa controls not supported\n");
-- return -EINVAL;
-- }
-+ err = bcm2835_audio_set_ctls(alsa_stream);
-+ if (err)
-+ return err;
-
-- mutex_lock(&instance->vchi_mutex);
-- vchi_service_use(instance->vchi_handle);
--
-- 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 */
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-- &m, sizeof(m));
--
-- if (status) {
-- LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
-- __func__, status);
--
-- ret = -1;
-- goto unlock;
-- }
--
-- /* We are expecting a reply from the videocore */
-- wait_for_completion(&instance->msg_avail_comp);
--
-- if (instance->result) {
-- LOG_ERR("%s: result=%d", __func__, instance->result);
--
-- ret = -1;
-- goto unlock;
-- }
--
-- ret = 0;
--
--unlock:
-- vchi_service_release(instance->vchi_handle);
-- mutex_unlock(&instance->vchi_mutex);
--
-- return ret;
-+ return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
- }
-
- static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream)
- {
-- struct vc_audio_msg m;
-- struct bcm2835_audio_instance *instance = alsa_stream->instance;
-- int status;
-- int ret;
--
-- mutex_lock(&instance->vchi_mutex);
-- vchi_service_use(instance->vchi_handle);
--
-- m.type = VC_AUDIO_MSG_TYPE_START;
--
-- /* Send the message to the videocore */
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-- &m, sizeof(m));
--
-- if (status) {
-- LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
-- __func__, status);
--
-- ret = -1;
-- goto unlock;
-- }
--
-- ret = 0;
--
--unlock:
-- vchi_service_release(instance->vchi_handle);
-- mutex_unlock(&instance->vchi_mutex);
-- return ret;
-+ return bcm2835_audio_send_simple(alsa_stream->instance,
-+ VC_AUDIO_MSG_TYPE_START, false);
- }
-
- static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream)
- {
-- struct vc_audio_msg m;
-- struct bcm2835_audio_instance *instance = alsa_stream->instance;
-- int status;
-- int ret;
--
-- mutex_lock(&instance->vchi_mutex);
-- vchi_service_use(instance->vchi_handle);
--
-- m.type = VC_AUDIO_MSG_TYPE_STOP;
-- m.u.stop.draining = alsa_stream->draining;
--
-- /* Send the message to the videocore */
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-- &m, sizeof(m));
--
-- if (status) {
-- LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
-- __func__, status);
--
-- ret = -1;
-- goto unlock;
-- }
--
-- ret = 0;
--
--unlock:
-- vchi_service_release(instance->vchi_handle);
-- mutex_unlock(&instance->vchi_mutex);
-- return ret;
-+ return bcm2835_audio_send_simple(alsa_stream->instance,
-+ VC_AUDIO_MSG_TYPE_STOP, false);
- }
-
- int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream)
- {
-- struct vc_audio_msg m;
- struct bcm2835_audio_instance *instance = alsa_stream->instance;
-- int status;
-- int ret;
-+ int err;
-
- my_workqueue_quit(alsa_stream);
-
-- mutex_lock(&instance->vchi_mutex);
-- vchi_service_use(instance->vchi_handle);
--
-- m.type = VC_AUDIO_MSG_TYPE_CLOSE;
--
-- /* Create the message available completion */
-- init_completion(&instance->msg_avail_comp);
--
-- /* Send the message to the videocore */
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-- &m, sizeof(m));
--
-- if (status) {
-- LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
-- __func__, status);
-- ret = -1;
-- goto unlock;
-- }
--
-- /* We are expecting a reply from the videocore */
-- wait_for_completion(&instance->msg_avail_comp);
--
-- if (instance->result) {
-- LOG_ERR("%s: failed result (result=%d)\n",
-- __func__, instance->result);
--
-- ret = -1;
-- goto unlock;
-- }
--
-- ret = 0;
--
--unlock:
-- vchi_service_release(instance->vchi_handle);
-- mutex_unlock(&instance->vchi_mutex);
-+ err = bcm2835_audio_send_simple(alsa_stream->instance,
-+ VC_AUDIO_MSG_TYPE_CLOSE, true);
-
- /* Stop the audio service */
- vc_vchi_audio_deinit(instance);
- alsa_stream->instance = NULL;
-
-- return ret;
-+ return err;
- }
-
- static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
-- unsigned int count, void *src)
-+ unsigned int size, void *src)
- {
-- struct vc_audio_msg m;
- struct bcm2835_audio_instance *instance = alsa_stream->instance;
-- int status;
-- int ret;
--
-- LOG_INFO(" Writing %d bytes from %p\n", count, src);
--
-- mutex_lock(&instance->vchi_mutex);
-- vchi_service_use(instance->vchi_handle);
-+ struct vc_audio_msg m = {
-+ .type = VC_AUDIO_MSG_TYPE_WRITE,
-+ .u.write.count = size,
-+ .u.write.max_packet = instance->max_packet,
-+ .u.write.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1,
-+ .u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2,
-+ };
-+ unsigned int count;
-+ int err, status;
-
-- if (instance->peer_version == 0 &&
-- vchi_get_peer_version(instance->vchi_handle, &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.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1;
-- m.u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2;
-- m.u.write.silence = src == NULL;
--
-- /* Send the message to the videocore */
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-- &m, sizeof(m));
-+ if (!size)
-+ return 0;
-
-- if (status) {
-- LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
-- __func__, status);
--
-- ret = -1;
-+ bcm2835_audio_lock(instance);
-+ err = bcm2835_audio_send_msg_locked(instance, &m, false);
-+ if (err < 0)
- goto unlock;
-- }
-- if (!m.u.write.silence) {
-- if (!m.u.write.max_packet) {
-- /* Send the message to the videocore */
-- status = vchi_bulk_queue_transmit(instance->vchi_handle,
-- src, count,
-- 0 * VCHI_FLAGS_BLOCK_UNTIL_QUEUED
-- +
-- 1 * VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
-- NULL);
-- } else {
-- while (count > 0) {
-- int bytes = min_t(int, m.u.write.max_packet, count);
-
-- status = bcm2835_vchi_msg_queue(instance->vchi_handle,
-- src, bytes);
-- src = (char *)src + bytes;
-- count -= bytes;
-- }
-- }
-- if (status) {
-- LOG_ERR("%s: failed on vchi_bulk_queue_transmit (status=%d)\n",
-- __func__, status);
-+ count = size;
-+ if (!instance->max_packet) {
-+ /* Send the message to the videocore */
-+ status = vchi_bulk_queue_transmit(instance->vchi_handle,
-+ src, count,
-+ VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
-+ NULL);
-+ } else {
-+ while (count > 0) {
-+ int bytes = min(instance->max_packet, count);
-
-- ret = -1;
-- goto unlock;
-+ status = vchi_queue_kernel_message(instance->vchi_handle,
-+ src, bytes);
-+ src += bytes;
-+ count -= bytes;
- }
- }
-- ret = 0;
-
--unlock:
-- vchi_service_release(instance->vchi_handle);
-- mutex_unlock(&instance->vchi_mutex);
-- return ret;
-+ if (status) {
-+ LOG_ERR("failed on %d bytes transfer (status=%d)\n",
-+ size, status);
-+ err = -EIO;
-+ }
-+
-+ unlock:
-+ bcm2835_audio_unlock(instance);
-+ return err;
- }
-
- unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream)
--- /dev/null
+From 2648530ca51dc98d65f1c747de4f7ddd20af6d62 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:51 +0200
+Subject: [PATCH 458/725] staging: bcm2835-audio: Use standard error print
+ helpers
+
+commit b7584b64168208ebc14160770c0966b8b12fc16b upstream.
+
+For making the whole code more consistent, replace the home-made debug
+print macros with the standard dev_err() & co.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 4 +-
+ .../bcm2835-audio/bcm2835-vchiq.c | 52 ++++++++-----------
+ .../vc04_services/bcm2835-audio/bcm2835.c | 2 +-
+ .../vc04_services/bcm2835-audio/bcm2835.h | 43 +--------------
+ 4 files changed, 27 insertions(+), 74 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -101,8 +101,8 @@ static int snd_bcm2835_playback_open_gen
+ goto out;
+ }
+ if (idx >= MAX_SUBSTREAMS) {
+- audio_error
+- ("substream(%d) device doesn't exist max(%d) substreams allowed\n",
++ dev_err(chip->dev,
++ "substream(%d) device doesn't exist max(%d) substreams allowed\n",
+ idx, MAX_SUBSTREAMS);
+ err = -ENODEV;
+ goto out;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -26,20 +26,8 @@
+
+ /* ---- Private Constants and Types ------------------------------------------ */
+
+-/* 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...) no_printk(fmt, ##arg)
+-#define LOG_INFO(fmt, arg...) no_printk(fmt, ##arg)
+-#define LOG_DBG(fmt, arg...) no_printk(fmt, ##arg)
+-#endif
+-
+ struct bcm2835_audio_instance {
++ struct device *dev;
+ VCHI_SERVICE_HANDLE_T vchi_handle;
+ struct completion msg_avail_comp;
+ struct mutex vchi_mutex;
+@@ -76,7 +64,8 @@ static int bcm2835_audio_send_msg_locked
+ status = vchi_queue_kernel_message(instance->vchi_handle,
+ m, sizeof(*m));
+ if (status) {
+- LOG_ERR("vchi message queue failed: %d, msg=%d\n",
++ dev_err(instance->dev,
++ "vchi message queue failed: %d, msg=%d\n",
+ status, m->type);
+ return -EIO;
+ }
+@@ -84,10 +73,12 @@ static int bcm2835_audio_send_msg_locked
+ if (wait) {
+ if (!wait_for_completion_timeout(&instance->msg_avail_comp,
+ msecs_to_jiffies(10 * 1000))) {
+- LOG_ERR("vchi message timeout, msg=%d\n", m->type);
++ dev_err(instance->dev,
++ "vchi message timeout, msg=%d\n", m->type);
+ return -ETIMEDOUT;
+ } else if (instance->result) {
+- LOG_ERR("vchi message response error:%d, msg=%d\n",
++ dev_err(instance->dev,
++ "vchi message response error:%d, msg=%d\n",
+ instance->result, m->type);
+ return -EIO;
+ }
+@@ -140,12 +131,12 @@ static void audio_vchi_callback(void *pa
+ } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
+ if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 ||
+ m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2)
+- LOG_ERR("invalid cookie\n");
++ dev_err(instance->dev, "invalid cookie\n");
+ else
+ bcm2835_playback_fifo(instance->alsa_stream,
+ m.u.complete.count);
+ } else {
+- LOG_ERR("unexpected callback type=%d\n", m.type);
++ dev_err(instance->dev, "unexpected callback type=%d\n", m.type);
+ }
+ }
+
+@@ -173,8 +164,9 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
+ &instance->vchi_handle);
+
+ if (status) {
+- LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
+- __func__, status);
++ dev_err(instance->dev,
++ "failed to open VCHI service connection (status=%d)\n",
++ status);
+ kfree(instance);
+ return -EPERM;
+ }
+@@ -195,30 +187,30 @@ static void vc_vchi_audio_deinit(struct
+ /* Close all VCHI service connections */
+ status = vchi_service_close(instance->vchi_handle);
+ if (status) {
+- LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
+- __func__, status);
++ dev_err(instance->dev,
++ "failed to close VCHI service connection (status=%d)\n",
++ status);
+ }
+
+ mutex_unlock(&instance->vchi_mutex);
+ }
+
+-int bcm2835_new_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx)
++int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx)
+ {
+ int ret;
+
+ /* Initialize and create a VCHI connection */
+ ret = vchi_initialise(&vchi_ctx->vchi_instance);
+ if (ret) {
+- LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)\n",
+- __func__, ret);
+-
++ dev_err(dev, "failed to initialise VCHI instance (ret=%d)\n",
++ ret);
+ return -EIO;
+ }
+
+ ret = vchi_connect(NULL, 0, vchi_ctx->vchi_instance);
+ if (ret) {
+- LOG_ERR("%s: failed to connect VCHI instance (ret=%d)\n",
+- __func__, ret);
++ dev_dbg(dev, "failed to connect VCHI instance (ret=%d)\n",
++ ret);
+
+ kfree(vchi_ctx->vchi_instance);
+ vchi_ctx->vchi_instance = NULL;
+@@ -248,6 +240,7 @@ int bcm2835_audio_open(struct bcm2835_al
+ if (!instance)
+ return -ENOMEM;
+ mutex_init(&instance->vchi_mutex);
++ instance->dev = alsa_stream->chip->dev;
+ instance->alsa_stream = alsa_stream;
+ alsa_stream->instance = instance;
+
+@@ -394,7 +387,8 @@ int bcm2835_audio_write(struct bcm2835_a
+ }
+
+ if (status) {
+- LOG_ERR("failed on %d bytes transfer (status=%d)\n",
++ dev_err(instance->dev,
++ "failed on %d bytes transfer (status=%d)\n",
+ size, status);
+ err = -EIO;
+ }
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -73,7 +73,7 @@ static int bcm2835_devm_add_vchi_ctx(str
+
+ memset(vchi_ctx, 0, sizeof(*vchi_ctx));
+
+- ret = bcm2835_new_vchi_ctx(vchi_ctx);
++ ret = bcm2835_new_vchi_ctx(dev, vchi_ctx);
+ if (ret) {
+ devres_free(vchi_ctx);
+ return ret;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -17,47 +17,6 @@
+
+ #include "interface/vchi/vchi.h"
+
+-/*
+- * #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...) \
+- pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
+-
+-#define audio_info(fmt, arg...) \
+- pr_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...) \
+- pr_err("%s:%d " fmt, __func__, __LINE__, ##arg)
+-
+-#define audio_warning(fmt, arg...) \
+- pr_warn("%s:%d " fmt, __func__, __LINE__, ##arg)
+-
+-#define audio_alert(fmt, arg...) \
+- pr_alert("%s:%d " fmt, __func__, __LINE__, ##arg)
+-
+ #define MAX_SUBSTREAMS (8)
+ #define AVAIL_SUBSTREAMS_MASK (0xff)
+
+@@ -141,7 +100,7 @@ int snd_bcm2835_new_simple_pcm(struct bc
+ int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip);
+ int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip);
+
+-int bcm2835_new_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx);
++int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx);
+ void bcm2835_free_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx);
+
+ int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream);
+++ /dev/null
-From 8f5871c73ba767c9443eb02c4ca0cb7df56982e8 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:49 +0200
-Subject: [PATCH 459/703] staging: bcm2835-audio: Operate non-atomic PCM ops
-
-commit 5c7883e5f27e829f3f3a2ba174d4a724bfd5f026 upstream.
-
-This is the most significant part in the patch series.
-
-The bcm2835-audio driver used to queue the commands to vc04 core via
-workqueue, but basically the whole accesses to vc04 core are done in
-the sleepable context, including the callback calls. In such a case,
-rewriting the code using non-atomic PCM ops will simplify the logic a
-lot.
-
-This patch does it: all workqueue are gone and each former-work
-implementation is now directly called from PCM ops like trigger and
-write transfer.
-
-Along with it, the DMA position updater, bcm2835_playback_fifo(), was
-also rewritten to use a simpler logic. Now it handles the XRUN and
-draining properly by calling snd_pcm_stop() conditionally.
-
-The current position is kept in atomic_t value so that it can be read
-concurrently from the pointer callback.
-
-Also, the bcm2835_audio_instance object is allocated at the beginning
-of bcm2835_audio_open(). This makes the resource management clearer.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 74 +++---
- .../bcm2835-audio/bcm2835-vchiq.c | 244 +++---------------
- .../vc04_services/bcm2835-audio/bcm2835.h | 9 +-
- 3 files changed, 82 insertions(+), 245 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -11,7 +11,8 @@
- /* hardware definition */
- static const 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),
-+ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
-+ SNDRV_PCM_INFO_DRAIN_TRIGGER),
- .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
- .rate_min = 8000,
-@@ -27,7 +28,8 @@ static const struct snd_pcm_hardware snd
-
- static const 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),
-+ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
-+ SNDRV_PCM_INFO_DRAIN_TRIGGER),
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000,
-@@ -47,42 +49,34 @@ static void snd_bcm2835_playback_free(st
- kfree(runtime->private_data);
- }
-
--void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream)
-+void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream,
-+ unsigned int bytes)
- {
-- unsigned int consumed = 0;
-- int new_period = 0;
-+ struct snd_pcm_substream *substream = alsa_stream->substream;
-+ unsigned int pos;
-
-- audio_info("alsa_stream=%p substream=%p\n", alsa_stream,
-- alsa_stream ? alsa_stream->substream : 0);
-+ if (!alsa_stream->period_size)
-+ return;
-
-- 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 (bytes >= alsa_stream->buffer_size) {
-+ snd_pcm_stream_lock(substream);
-+ snd_pcm_stop(substream,
-+ alsa_stream->draining ?
-+ SNDRV_PCM_STATE_SETUP :
-+ SNDRV_PCM_STATE_XRUN);
-+ snd_pcm_stream_unlock(substream);
-+ return;
- }
-
-- if (alsa_stream->substream) {
-- if (new_period)
-- snd_pcm_period_elapsed(alsa_stream->substream);
-- } else {
-- audio_warning(" unexpected NULL substream\n");
-+ pos = atomic_read(&alsa_stream->pos);
-+ pos += bytes;
-+ pos %= alsa_stream->buffer_size;
-+ atomic_set(&alsa_stream->pos, pos);
-+
-+ alsa_stream->period_offset += bytes;
-+ if (alsa_stream->period_offset >= alsa_stream->period_size) {
-+ alsa_stream->period_offset %= alsa_stream->period_size;
-+ snd_pcm_period_elapsed(substream);
- }
- }
-
-@@ -246,7 +240,8 @@ static int snd_bcm2835_pcm_prepare(struc
-
- alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
- alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
-- alsa_stream->pos = 0;
-+ atomic_set(&alsa_stream->pos, 0);
-+ alsa_stream->period_offset = 0;
- alsa_stream->draining = false;
-
- return 0;
-@@ -283,7 +278,7 @@ static int snd_bcm2835_pcm_trigger(struc
- return bcm2835_audio_start(alsa_stream);
- case SNDRV_PCM_TRIGGER_DRAIN:
- alsa_stream->draining = true;
-- return 0;
-+ return bcm2835_audio_drain(alsa_stream);
- case SNDRV_PCM_TRIGGER_STOP:
- return bcm2835_audio_stop(alsa_stream);
- default:
-@@ -300,7 +295,7 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
-
- return snd_pcm_indirect_playback_pointer(substream,
- &alsa_stream->pcm_indirect,
-- alsa_stream->pos);
-+ atomic_read(&alsa_stream->pos));
- }
-
- /* operators */
-@@ -338,6 +333,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
- if (err < 0)
- return err;
- pcm->private_data = chip;
-+ pcm->nonatomic = true;
- strcpy(pcm->name, "bcm2835 ALSA");
- chip->pcm = pcm;
- chip->dest = AUDIO_DEST_AUTO;
-@@ -367,6 +363,7 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
- return err;
-
- pcm->private_data = chip;
-+ pcm->nonatomic = true;
- strcpy(pcm->name, "bcm2835 IEC958/HDMI");
- chip->pcm_spdif = pcm;
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-@@ -395,6 +392,7 @@ int snd_bcm2835_new_simple_pcm(struct bc
- return err;
-
- pcm->private_data = chip;
-+ pcm->nonatomic = true;
- strcpy(pcm->name, name);
- chip->pcm = pcm;
- chip->dest = route;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -26,10 +26,6 @@
-
- /* ---- 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)
-@@ -55,17 +51,6 @@ struct bcm2835_audio_instance {
-
- static bool force_bulk;
-
--/* ---- Private Variables ---------------------------------------------------- */
--
--/* ---- Private Function Prototypes ------------------------------------------ */
--
--/* ---- Private Functions ---------------------------------------------------- */
--
--static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream);
--static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream);
--static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
-- unsigned int count, void *src);
--
- static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
- {
- mutex_lock(&instance->vchi_mutex);
-@@ -135,108 +120,6 @@ static const u32 BCM2835_AUDIO_WRITE_COO
- static const u32 BCM2835_AUDIO_WRITE_COOKIE2 = ('D' << 24 | 'A' << 16 |
- 'T' << 8 | 'A');
-
--struct bcm2835_audio_work {
-- struct work_struct my_work;
-- struct bcm2835_alsa_stream *alsa_stream;
-- int cmd;
-- void *src;
-- unsigned int count;
--};
--
--static void my_wq_function(struct work_struct *work)
--{
-- struct bcm2835_audio_work *w =
-- container_of(work, struct bcm2835_audio_work, my_work);
-- int ret = -9;
--
-- 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);
--}
--
--int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream)
--{
-- struct bcm2835_audio_work *work;
--
-- work = kmalloc(sizeof(*work), GFP_ATOMIC);
-- /*--- Queue some work (item 1) ---*/
-- if (!work) {
-- LOG_ERR(" .. Error: NULL work kmalloc\n");
-- return -ENOMEM;
-- }
-- INIT_WORK(&work->my_work, my_wq_function);
-- work->alsa_stream = alsa_stream;
-- work->cmd = BCM2835_AUDIO_START;
-- if (!queue_work(alsa_stream->my_wq, &work->my_work)) {
-- kfree(work);
-- return -EBUSY;
-- }
-- return 0;
--}
--
--int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream)
--{
-- struct bcm2835_audio_work *work;
--
-- work = kmalloc(sizeof(*work), GFP_ATOMIC);
-- /*--- Queue some work (item 1) ---*/
-- if (!work) {
-- LOG_ERR(" .. Error: NULL work kmalloc\n");
-- return -ENOMEM;
-- }
-- INIT_WORK(&work->my_work, my_wq_function);
-- work->alsa_stream = alsa_stream;
-- work->cmd = BCM2835_AUDIO_STOP;
-- if (!queue_work(alsa_stream->my_wq, &work->my_work)) {
-- kfree(work);
-- return -EBUSY;
-- }
-- return 0;
--}
--
--int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
-- unsigned int count, void *src)
--{
-- struct bcm2835_audio_work *work;
--
-- work = kmalloc(sizeof(*work), GFP_ATOMIC);
-- /*--- Queue some work (item 1) ---*/
-- if (!work) {
-- LOG_ERR(" .. Error: NULL work kmalloc\n");
-- return -ENOMEM;
-- }
-- INIT_WORK(&work->my_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, &work->my_work)) {
-- kfree(work);
-- return -EBUSY;
-- }
-- return 0;
--}
--
--static void my_workqueue_quit(struct bcm2835_alsa_stream *alsa_stream)
--{
-- flush_workqueue(alsa_stream->my_wq);
-- destroy_workqueue(alsa_stream->my_wq);
-- alsa_stream->my_wq = NULL;
--}
--
- static void audio_vchi_callback(void *param,
- const VCHI_CALLBACK_REASON_T reason,
- void *msg_handle)
-@@ -249,47 +132,27 @@ static void audio_vchi_callback(void *pa
- if (reason != VCHI_CALLBACK_MSG_AVAILABLE)
- return;
-
-- if (!instance) {
-- LOG_ERR(" .. instance is null\n");
-- BUG();
-- return;
-- }
-- if (!instance->vchi_handle) {
-- LOG_ERR(" .. instance->vchi_handle is null\n");
-- BUG();
-- return;
-- }
- status = vchi_msg_dequeue(instance->vchi_handle,
- &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) {
-- struct bcm2835_alsa_stream *alsa_stream = instance->alsa_stream;
--
-- LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n",
-- instance, m.u.complete.count);
- if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 ||
- m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2)
-- LOG_ERR(" .. response is corrupt\n");
-- else if (alsa_stream) {
-- atomic_add(m.u.complete.count,
-- &alsa_stream->retrieved);
-- bcm2835_playback_fifo(alsa_stream);
-- } else {
-- LOG_ERR(" .. unexpected alsa_stream=%p\n",
-- alsa_stream);
-- }
-+ LOG_ERR("invalid cookie\n");
-+ else
-+ bcm2835_playback_fifo(instance->alsa_stream,
-+ m.u.complete.count);
- } else {
-- LOG_ERR(" .. unexpected m.type=%d\n", m.type);
-+ LOG_ERR("unexpected callback type=%d\n", m.type);
- }
- }
-
--static struct bcm2835_audio_instance *
-+static int
- vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance,
-- VCHI_CONNECTION_T *vchi_connection)
-+ VCHI_CONNECTION_T *vchi_connection,
-+ struct bcm2835_audio_instance *instance)
- {
- SERVICE_CREATION_T params = {
- .version = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),
-@@ -298,23 +161,14 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
- .rx_fifo_size = 0,
- .tx_fifo_size = 0,
- .callback = audio_vchi_callback,
-+ .callback_param = instance,
- .want_unaligned_bulk_rx = 1, //TODO: remove VCOS_FALSE
- .want_unaligned_bulk_tx = 1, //TODO: remove VCOS_FALSE
- .want_crc = 0
- };
-- struct bcm2835_audio_instance *instance;
- int status;
-
-- /* Allocate memory for this instance */
-- instance = kzalloc(sizeof(*instance), GFP_KERNEL);
-- if (!instance)
-- return ERR_PTR(-ENOMEM);
--
-- /* Create a lock for exclusive, serialized VCHI connection access */
-- mutex_init(&instance->vchi_mutex);
- /* Open the VCHI service connections */
-- params.callback_param = instance,
--
- status = vchi_service_open(vchi_instance, ¶ms,
- &instance->vchi_handle);
-
-@@ -322,16 +176,16 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
- LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
- __func__, status);
- kfree(instance);
-- return ERR_PTR(-EPERM);
-+ return -EPERM;
- }
-
- /* Finished with the service for now */
- vchi_service_release(instance->vchi_handle);
-
-- return instance;
-+ return 0;
- }
-
--static int vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
-+static void vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance)
- {
- int status;
-
-@@ -346,10 +200,6 @@ static int vc_vchi_audio_deinit(struct b
- }
-
- mutex_unlock(&instance->vchi_mutex);
--
-- kfree(instance);
--
-- return 0;
- }
-
- int bcm2835_new_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx)
-@@ -387,39 +237,25 @@ void bcm2835_free_vchi_ctx(struct bcm283
- vchi_ctx->vchi_instance = NULL;
- }
-
--static int bcm2835_audio_open_connection(struct bcm2835_alsa_stream *alsa_stream)
--{
-- struct bcm2835_audio_instance *instance =
-- (struct bcm2835_audio_instance *)alsa_stream->instance;
-- struct bcm2835_vchi_ctx *vhci_ctx = alsa_stream->chip->vchi_ctx;
--
-- /* Initialize an instance of the audio service */
-- instance = vc_vchi_audio_init(vhci_ctx->vchi_instance,
-- vhci_ctx->vchi_connection);
--
-- if (IS_ERR(instance))
-- return PTR_ERR(instance);
--
-- instance->alsa_stream = alsa_stream;
-- alsa_stream->instance = instance;
--
-- return 0;
--}
--
- int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream)
- {
-+ struct bcm2835_vchi_ctx *vchi_ctx = alsa_stream->chip->vchi_ctx;
- struct bcm2835_audio_instance *instance;
- int err;
-
-- alsa_stream->my_wq = alloc_workqueue("my_queue", WQ_HIGHPRI, 1);
-- if (!alsa_stream->my_wq)
-+ /* Allocate memory for this instance */
-+ instance = kzalloc(sizeof(*instance), GFP_KERNEL);
-+ if (!instance)
- return -ENOMEM;
-+ mutex_init(&instance->vchi_mutex);
-+ instance->alsa_stream = alsa_stream;
-+ alsa_stream->instance = instance;
-
-- err = bcm2835_audio_open_connection(alsa_stream);
-+ err = vc_vchi_audio_init(vchi_ctx->vchi_instance,
-+ vchi_ctx->vchi_connection,
-+ instance);
- if (err < 0)
-- goto free_wq;
--
-- instance = alsa_stream->instance;
-+ goto free_instance;
-
- err = bcm2835_audio_send_simple(instance, VC_AUDIO_MSG_TYPE_OPEN,
- false);
-@@ -438,8 +274,9 @@ int bcm2835_audio_open(struct bcm2835_al
-
- deinit:
- vc_vchi_audio_deinit(instance);
-- free_wq:
-- destroy_workqueue(alsa_stream->my_wq);
-+ free_instance:
-+ alsa_stream->instance = NULL;
-+ kfree(instance);
- return err;
- }
-
-@@ -478,37 +315,46 @@ int bcm2835_audio_set_params(struct bcm2
- return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
- }
-
--static int bcm2835_audio_start_worker(struct bcm2835_alsa_stream *alsa_stream)
-+int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream)
- {
- return bcm2835_audio_send_simple(alsa_stream->instance,
- VC_AUDIO_MSG_TYPE_START, false);
- }
-
--static int bcm2835_audio_stop_worker(struct bcm2835_alsa_stream *alsa_stream)
-+int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream)
- {
- return bcm2835_audio_send_simple(alsa_stream->instance,
- VC_AUDIO_MSG_TYPE_STOP, false);
- }
-
-+int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream)
-+{
-+ struct vc_audio_msg m = {
-+ .type = VC_AUDIO_MSG_TYPE_STOP,
-+ .u.stop.draining = 1,
-+ };
-+
-+ return bcm2835_audio_send_msg(alsa_stream->instance, &m, false);
-+}
-+
- int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream)
- {
- struct bcm2835_audio_instance *instance = alsa_stream->instance;
- int err;
-
-- my_workqueue_quit(alsa_stream);
--
- err = bcm2835_audio_send_simple(alsa_stream->instance,
- VC_AUDIO_MSG_TYPE_CLOSE, true);
-
- /* Stop the audio service */
- vc_vchi_audio_deinit(instance);
- alsa_stream->instance = NULL;
-+ kfree(instance);
-
- return err;
- }
-
--static int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream,
-- unsigned int size, void *src)
-+int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
-+ unsigned int size, void *src)
- {
- struct bcm2835_audio_instance *instance = alsa_stream->instance;
- struct vc_audio_msg m = {
-@@ -558,13 +404,5 @@ static int bcm2835_audio_write_worker(st
- return err;
- }
-
--unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream)
--{
-- unsigned int 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");
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -121,13 +121,12 @@ struct bcm2835_alsa_stream {
-
- int draining;
-
-- unsigned int pos;
-+ atomic_t pos;
-+ unsigned int period_offset;
- unsigned int buffer_size;
- unsigned int period_size;
-
-- atomic_t retrieved;
- struct bcm2835_audio_instance *instance;
-- struct workqueue_struct *my_wq;
- int idx;
- };
-
-@@ -152,11 +151,13 @@ int bcm2835_audio_set_params(struct bcm2
- unsigned int bps);
- int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream);
-+int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream);
- int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
- unsigned int count,
- void *src);
--void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream);
-+void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream,
-+ unsigned int size);
- unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream);
-
- #endif /* __SOUND_ARM_BCM2835_H */
--- /dev/null
+From abed6180470d4004c4578a7a28b846b3517149f9 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:52 +0200
+Subject: [PATCH 459/725] staging: bcm2835-audio: Remove unnecessary header
+ file includes
+
+commit 7e46fff5f19ce2b8a9891e4c08631c64d06e9e17 upstream.
+
+Yet a few header files are included unnecessarily. Drop them.
+
+Also remove trivial comments.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../bcm2835-audio/bcm2835-vchiq.c | 19 -------------------
+ .../vc04_services/bcm2835-audio/bcm2835.h | 6 ------
+ 2 files changed, 25 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -1,31 +1,12 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /* Copyright 2011 Broadcom Corporation. All rights reserved. */
+
+-#include <linux/device.h>
+-#include <sound/core.h>
+-#include <sound/initval.h>
+-#include <sound/pcm.h>
+-#include <linux/io.h>
+-#include <linux/interrupt.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/mm.h>
+-#include <linux/syscalls.h>
+-#include <linux/uaccess.h>
+ #include <linux/slab.h>
+-#include <linux/delay.h>
+-#include <linux/atomic.h>
+ #include <linux/module.h>
+ #include <linux/completion.h>
+-
+ #include "bcm2835.h"
+-
+-/* ---- Include Files -------------------------------------------------------- */
+-
+ #include "vc_vchi_audioserv_defs.h"
+
+-/* ---- Private Constants and Types ------------------------------------------ */
+-
+ struct bcm2835_audio_instance {
+ struct device *dev;
+ VCHI_SERVICE_HANDLE_T vchi_handle;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -5,16 +5,10 @@
+ #define __SOUND_ARM_BCM2835_H
+
+ #include <linux/device.h>
+-#include <linux/list.h>
+-#include <linux/interrupt.h>
+ #include <linux/wait.h>
+ #include <sound/core.h>
+-#include <sound/initval.h>
+ #include <sound/pcm.h>
+-#include <sound/pcm_params.h>
+ #include <sound/pcm-indirect.h>
+-#include <linux/workqueue.h>
+-
+ #include "interface/vchi/vchi.h"
+
+ #define MAX_SUBSTREAMS (8)
--- /dev/null
+From 7f64018d201f24f5922a61a14363d87560b5b0fd Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:53 +0200
+Subject: [PATCH 460/725] staging: bcm2835-audio: Move module parameter
+ description
+
+commit b876f2075808e95e244053caa53fa7e86e929a99 upstream.
+
+For more consistency, move the module parameter description right
+after its variable definition.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -19,6 +19,8 @@ struct bcm2835_audio_instance {
+ };
+
+ static bool force_bulk;
++module_param(force_bulk, bool, 0444);
++MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");
+
+ static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
+ {
+@@ -378,6 +380,3 @@ int bcm2835_audio_write(struct bcm2835_a
+ bcm2835_audio_unlock(instance);
+ return err;
+ }
+-
+-module_param(force_bulk, bool, 0444);
+-MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");
+++ /dev/null
-From 18bd0bcc6b0455640038084fa6ab3b06462319c5 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:50 +0200
-Subject: [PATCH 460/703] staging: bcm2835-audio: Use card->private_data
-
-commit 898001a0c845cefe5d47d133485712412853f0a8 upstream.
-
-Instead of allocating a separate snd_device object, let snd_card_new()
-allocate the private resource. This simplifies the code.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835.c | 91 +++----------------
- 1 file changed, 13 insertions(+), 78 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -86,9 +86,6 @@ static int bcm2835_devm_add_vchi_ctx(str
-
- static void snd_bcm2835_release(struct device *dev)
- {
-- struct bcm2835_chip *chip = dev_get_drvdata(dev);
--
-- kfree(chip);
- }
-
- static struct device *
-@@ -117,69 +114,6 @@ snd_create_device(struct device *parent,
- return device;
- }
-
--/* component-destructor
-- * (see "Management of Cards and Components")
-- */
--static int snd_bcm2835_dev_free(struct snd_device *device)
--{
-- struct bcm2835_chip *chip = device->device_data;
-- struct snd_card *card = chip->card;
--
-- snd_device_free(card, chip);
--
-- return 0;
--}
--
--/* chip-specific constructor
-- * (see "Management of Cards and Components")
-- */
--static int snd_bcm2835_create(struct snd_card *card,
-- struct bcm2835_chip **rchip)
--{
-- struct bcm2835_chip *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)
-- return -ENOMEM;
--
-- chip->card = card;
-- mutex_init(&chip->audio_mutex);
--
-- chip->vchi_ctx = devres_find(card->dev->parent,
-- bcm2835_devm_free_vchi_ctx, NULL, NULL);
-- if (!chip->vchi_ctx) {
-- kfree(chip);
-- return -ENODEV;
-- }
--
-- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-- if (err) {
-- kfree(chip);
-- return err;
-- }
--
-- *rchip = chip;
-- return 0;
--}
--
--static struct snd_card *snd_bcm2835_card_new(struct device *dev)
--{
-- struct snd_card *card;
-- int ret;
--
-- ret = snd_card_new(dev, -1, NULL, THIS_MODULE, 0, &card);
-- if (ret)
-- return ERR_PTR(ret);
--
-- return card;
--}
--
- typedef int (*bcm2835_audio_newpcm_func)(struct bcm2835_chip *chip,
- const char *name,
- enum snd_bcm2835_route route,
-@@ -292,25 +226,26 @@ static int snd_add_child_device(struct d
- return PTR_ERR(child);
- }
-
-- card = snd_bcm2835_card_new(child);
-- if (IS_ERR(card)) {
-+ err = snd_card_new(child, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
-+ if (err < 0) {
- dev_err(child, "Failed to create card");
-- return PTR_ERR(card);
-+ return err;
- }
-
-- snd_card_set_dev(card, child);
-+ chip = card->private_data;
-+ chip->card = card;
-+ chip->dev = child;
-+ mutex_init(&chip->audio_mutex);
-+
-+ chip->vchi_ctx = devres_find(device,
-+ bcm2835_devm_free_vchi_ctx, NULL, NULL);
-+ if (!chip->vchi_ctx)
-+ return -ENODEV;
-+
- strcpy(card->driver, audio_driver->driver.name);
- strcpy(card->shortname, audio_driver->shortname);
- strcpy(card->longname, audio_driver->longname);
-
-- err = snd_bcm2835_create(card, &chip);
-- if (err) {
-- dev_err(child, "Failed to create chip, error %d\n", err);
-- return err;
-- }
--
-- chip->dev = child;
--
- err = audio_driver->newpcm(chip, audio_driver->shortname,
- audio_driver->route,
- numchans);
--- /dev/null
+From eeb863318a36c32dd4bb6a5767980485050cd85c Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:54 +0200
+Subject: [PATCH 461/725] staging: bcm2835-audio: Use coherent device buffers
+
+commit ad29c6e6cbf6f2af7362b043adad51a3be3d39c7 upstream.
+
+The memory access to the pages allocated with
+SNDRV_DMA_TYPE_CONTINUOUS are basically non-coherent, and it becomes a
+problem when a process accesses via mmap.
+
+For the more consistent access, use the device coherent memory, just
+by replacing the call pattern in the allocator helpers.
+
+The only point we need to be careful for is the device object passed
+there; since bcm2835-audio driver creates fake devices and each card
+is created on top of that, we need to pass its parent device as the
+real device object.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -345,8 +345,8 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
+
+ /* 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_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
++ chip->card->dev->parent,
+ snd_bcm2835_playback_hw.buffer_bytes_max,
+ snd_bcm2835_playback_hw.buffer_bytes_max);
+
+@@ -371,8 +371,8 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
+
+ /* 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_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
++ chip->card->dev->parent,
+ snd_bcm2835_playback_spdif_hw.buffer_bytes_max, snd_bcm2835_playback_spdif_hw.buffer_bytes_max);
+
+ return 0;
+@@ -404,8 +404,8 @@ int snd_bcm2835_new_simple_pcm(struct bc
+
+ snd_pcm_lib_preallocate_pages_for_all(
+ pcm,
+- SNDRV_DMA_TYPE_CONTINUOUS,
+- snd_dma_continuous_data(GFP_KERNEL),
++ SNDRV_DMA_TYPE_DEV,
++ chip->card->dev->parent,
+ snd_bcm2835_playback_hw.buffer_bytes_max,
+ snd_bcm2835_playback_hw.buffer_bytes_max);
+
+++ /dev/null
-From 1dff63cdd20b6dfc763d01d35dff231b8abe8175 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:51 +0200
-Subject: [PATCH 461/703] staging: bcm2835-audio: Use standard error print
- helpers
-
-commit b7584b64168208ebc14160770c0966b8b12fc16b upstream.
-
-For making the whole code more consistent, replace the home-made debug
-print macros with the standard dev_err() & co.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 4 +-
- .../bcm2835-audio/bcm2835-vchiq.c | 52 ++++++++-----------
- .../vc04_services/bcm2835-audio/bcm2835.c | 2 +-
- .../vc04_services/bcm2835-audio/bcm2835.h | 43 +--------------
- 4 files changed, 27 insertions(+), 74 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -101,8 +101,8 @@ static int snd_bcm2835_playback_open_gen
- goto out;
- }
- if (idx >= MAX_SUBSTREAMS) {
-- audio_error
-- ("substream(%d) device doesn't exist max(%d) substreams allowed\n",
-+ dev_err(chip->dev,
-+ "substream(%d) device doesn't exist max(%d) substreams allowed\n",
- idx, MAX_SUBSTREAMS);
- err = -ENODEV;
- goto out;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -26,20 +26,8 @@
-
- /* ---- Private Constants and Types ------------------------------------------ */
-
--/* 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...) no_printk(fmt, ##arg)
--#define LOG_INFO(fmt, arg...) no_printk(fmt, ##arg)
--#define LOG_DBG(fmt, arg...) no_printk(fmt, ##arg)
--#endif
--
- struct bcm2835_audio_instance {
-+ struct device *dev;
- VCHI_SERVICE_HANDLE_T vchi_handle;
- struct completion msg_avail_comp;
- struct mutex vchi_mutex;
-@@ -76,7 +64,8 @@ static int bcm2835_audio_send_msg_locked
- status = vchi_queue_kernel_message(instance->vchi_handle,
- m, sizeof(*m));
- if (status) {
-- LOG_ERR("vchi message queue failed: %d, msg=%d\n",
-+ dev_err(instance->dev,
-+ "vchi message queue failed: %d, msg=%d\n",
- status, m->type);
- return -EIO;
- }
-@@ -84,10 +73,12 @@ static int bcm2835_audio_send_msg_locked
- if (wait) {
- if (!wait_for_completion_timeout(&instance->msg_avail_comp,
- msecs_to_jiffies(10 * 1000))) {
-- LOG_ERR("vchi message timeout, msg=%d\n", m->type);
-+ dev_err(instance->dev,
-+ "vchi message timeout, msg=%d\n", m->type);
- return -ETIMEDOUT;
- } else if (instance->result) {
-- LOG_ERR("vchi message response error:%d, msg=%d\n",
-+ dev_err(instance->dev,
-+ "vchi message response error:%d, msg=%d\n",
- instance->result, m->type);
- return -EIO;
- }
-@@ -140,12 +131,12 @@ static void audio_vchi_callback(void *pa
- } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
- if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 ||
- m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2)
-- LOG_ERR("invalid cookie\n");
-+ dev_err(instance->dev, "invalid cookie\n");
- else
- bcm2835_playback_fifo(instance->alsa_stream,
- m.u.complete.count);
- } else {
-- LOG_ERR("unexpected callback type=%d\n", m.type);
-+ dev_err(instance->dev, "unexpected callback type=%d\n", m.type);
- }
- }
-
-@@ -173,8 +164,9 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
- &instance->vchi_handle);
-
- if (status) {
-- LOG_ERR("%s: failed to open VCHI service connection (status=%d)\n",
-- __func__, status);
-+ dev_err(instance->dev,
-+ "failed to open VCHI service connection (status=%d)\n",
-+ status);
- kfree(instance);
- return -EPERM;
- }
-@@ -195,30 +187,30 @@ static void vc_vchi_audio_deinit(struct
- /* Close all VCHI service connections */
- status = vchi_service_close(instance->vchi_handle);
- if (status) {
-- LOG_DBG("%s: failed to close VCHI service connection (status=%d)\n",
-- __func__, status);
-+ dev_err(instance->dev,
-+ "failed to close VCHI service connection (status=%d)\n",
-+ status);
- }
-
- mutex_unlock(&instance->vchi_mutex);
- }
-
--int bcm2835_new_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx)
-+int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx)
- {
- int ret;
-
- /* Initialize and create a VCHI connection */
- ret = vchi_initialise(&vchi_ctx->vchi_instance);
- if (ret) {
-- LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)\n",
-- __func__, ret);
--
-+ dev_err(dev, "failed to initialise VCHI instance (ret=%d)\n",
-+ ret);
- return -EIO;
- }
-
- ret = vchi_connect(NULL, 0, vchi_ctx->vchi_instance);
- if (ret) {
-- LOG_ERR("%s: failed to connect VCHI instance (ret=%d)\n",
-- __func__, ret);
-+ dev_dbg(dev, "failed to connect VCHI instance (ret=%d)\n",
-+ ret);
-
- kfree(vchi_ctx->vchi_instance);
- vchi_ctx->vchi_instance = NULL;
-@@ -248,6 +240,7 @@ int bcm2835_audio_open(struct bcm2835_al
- if (!instance)
- return -ENOMEM;
- mutex_init(&instance->vchi_mutex);
-+ instance->dev = alsa_stream->chip->dev;
- instance->alsa_stream = alsa_stream;
- alsa_stream->instance = instance;
-
-@@ -394,7 +387,8 @@ int bcm2835_audio_write(struct bcm2835_a
- }
-
- if (status) {
-- LOG_ERR("failed on %d bytes transfer (status=%d)\n",
-+ dev_err(instance->dev,
-+ "failed on %d bytes transfer (status=%d)\n",
- size, status);
- err = -EIO;
- }
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -73,7 +73,7 @@ static int bcm2835_devm_add_vchi_ctx(str
-
- memset(vchi_ctx, 0, sizeof(*vchi_ctx));
-
-- ret = bcm2835_new_vchi_ctx(vchi_ctx);
-+ ret = bcm2835_new_vchi_ctx(dev, vchi_ctx);
- if (ret) {
- devres_free(vchi_ctx);
- return ret;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -17,47 +17,6 @@
-
- #include "interface/vchi/vchi.h"
-
--/*
-- * #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...) \
-- pr_info("%s:%d " fmt, __func__, __LINE__, ##arg)
--
--#define audio_info(fmt, arg...) \
-- pr_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...) \
-- pr_err("%s:%d " fmt, __func__, __LINE__, ##arg)
--
--#define audio_warning(fmt, arg...) \
-- pr_warn("%s:%d " fmt, __func__, __LINE__, ##arg)
--
--#define audio_alert(fmt, arg...) \
-- pr_alert("%s:%d " fmt, __func__, __LINE__, ##arg)
--
- #define MAX_SUBSTREAMS (8)
- #define AVAIL_SUBSTREAMS_MASK (0xff)
-
-@@ -141,7 +100,7 @@ int snd_bcm2835_new_simple_pcm(struct bc
- int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip);
- int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip);
-
--int bcm2835_new_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx);
-+int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx);
- void bcm2835_free_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx);
-
- int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream);
+++ /dev/null
-From d202703ef99f5d370997c2372e8b0e0873834868 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:52 +0200
-Subject: [PATCH 462/703] staging: bcm2835-audio: Remove unnecessary header
- file includes
-
-commit 7e46fff5f19ce2b8a9891e4c08631c64d06e9e17 upstream.
-
-Yet a few header files are included unnecessarily. Drop them.
-
-Also remove trivial comments.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../bcm2835-audio/bcm2835-vchiq.c | 19 -------------------
- .../vc04_services/bcm2835-audio/bcm2835.h | 6 ------
- 2 files changed, 25 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -1,31 +1,12 @@
- // SPDX-License-Identifier: GPL-2.0
- /* Copyright 2011 Broadcom Corporation. All rights reserved. */
-
--#include <linux/device.h>
--#include <sound/core.h>
--#include <sound/initval.h>
--#include <sound/pcm.h>
--#include <linux/io.h>
--#include <linux/interrupt.h>
--#include <linux/fs.h>
--#include <linux/file.h>
--#include <linux/mm.h>
--#include <linux/syscalls.h>
--#include <linux/uaccess.h>
- #include <linux/slab.h>
--#include <linux/delay.h>
--#include <linux/atomic.h>
- #include <linux/module.h>
- #include <linux/completion.h>
--
- #include "bcm2835.h"
--
--/* ---- Include Files -------------------------------------------------------- */
--
- #include "vc_vchi_audioserv_defs.h"
-
--/* ---- Private Constants and Types ------------------------------------------ */
--
- struct bcm2835_audio_instance {
- struct device *dev;
- VCHI_SERVICE_HANDLE_T vchi_handle;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -5,16 +5,10 @@
- #define __SOUND_ARM_BCM2835_H
-
- #include <linux/device.h>
--#include <linux/list.h>
--#include <linux/interrupt.h>
- #include <linux/wait.h>
- #include <sound/core.h>
--#include <sound/initval.h>
- #include <sound/pcm.h>
--#include <sound/pcm_params.h>
- #include <sound/pcm-indirect.h>
--#include <linux/workqueue.h>
--
- #include "interface/vchi/vchi.h"
-
- #define MAX_SUBSTREAMS (8)
--- /dev/null
+From e700838ddf8bdae4ecf25d031e46d8624eba00e1 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:55 +0200
+Subject: [PATCH 462/725] staging: bcm2835-audio: Set
+ SNDRV_PCM_INFO_SYNC_APPLPTR
+
+commit b59d6a5f73501f74848d6700101e7736afe3d54a upstream.
+
+The recent ALSA PCM core supports the SNDRV_PCM_INFO_SYNC_APPLPTR flag
+indicating that the driver needs the ack call at each appl_ptr
+update. This is requirement for the indirect PCM implementations like
+bcm2835-audio driver, too.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -12,7 +12,7 @@
+ static const 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 |
+- SNDRV_PCM_INFO_DRAIN_TRIGGER),
++ SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
+ .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+@@ -29,7 +29,7 @@ static const struct snd_pcm_hardware snd
+ static const 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 |
+- SNDRV_PCM_INFO_DRAIN_TRIGGER),
++ SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000,
+++ /dev/null
-From 4337174647cfd9a5bde517543ec1093d43c81522 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:53 +0200
-Subject: [PATCH 463/703] staging: bcm2835-audio: Move module parameter
- description
-
-commit b876f2075808e95e244053caa53fa7e86e929a99 upstream.
-
-For more consistency, move the module parameter description right
-after its variable definition.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c | 5 ++---
- 1 file changed, 2 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -19,6 +19,8 @@ struct bcm2835_audio_instance {
- };
-
- static bool force_bulk;
-+module_param(force_bulk, bool, 0444);
-+MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");
-
- static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
- {
-@@ -378,6 +380,3 @@ int bcm2835_audio_write(struct bcm2835_a
- bcm2835_audio_unlock(instance);
- return err;
- }
--
--module_param(force_bulk, bool, 0444);
--MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");
--- /dev/null
+From dc765e2328fdd22b055101bbe848fb50b0a592b9 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:56 +0200
+Subject: [PATCH 463/725] staging: bcm2835-audio: Simplify PCM creation helpers
+
+commit 74470ffeb9aed5548654cfca881bf1d7469fe9c4 upstream.
+
+All three functions to create PCM objects are fairly resemble, and can
+be unified to a single common helper.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 87 ++++---------------
+ .../vc04_services/bcm2835-audio/bcm2835.c | 17 +++-
+ .../vc04_services/bcm2835-audio/bcm2835.h | 9 +-
+ 3 files changed, 32 insertions(+), 81 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -324,91 +324,36 @@ static const struct snd_pcm_ops snd_bcm2
+ };
+
+ /* create a pcm device */
+-int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, u32 numchannels)
++int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, const char *name,
++ int idx, enum snd_bcm2835_route route,
++ u32 numchannels, bool spdif)
+ {
+ struct snd_pcm *pcm;
+ int err;
+
+- err = snd_pcm_new(chip->card, "bcm2835 ALSA", 0, numchannels, 0, &pcm);
+- if (err < 0)
+- return err;
+- pcm->private_data = chip;
+- pcm->nonatomic = true;
+- strcpy(pcm->name, "bcm2835 ALSA");
+- chip->pcm = pcm;
+- chip->dest = AUDIO_DEST_AUTO;
+- chip->volume = 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_DEV,
+- chip->card->dev->parent,
+- snd_bcm2835_playback_hw.buffer_bytes_max,
+- snd_bcm2835_playback_hw.buffer_bytes_max);
+-
+- return 0;
+-}
+-
+-int snd_bcm2835_new_spdif_pcm(struct bcm2835_chip *chip)
+-{
+- struct snd_pcm *pcm;
+- int err;
+-
+- err = snd_pcm_new(chip->card, "bcm2835 ALSA", 1, 1, 0, &pcm);
+- if (err < 0)
+- return err;
+-
+- pcm->private_data = chip;
+- pcm->nonatomic = true;
+- 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_DEV,
+- chip->card->dev->parent,
+- snd_bcm2835_playback_spdif_hw.buffer_bytes_max, snd_bcm2835_playback_spdif_hw.buffer_bytes_max);
+-
+- return 0;
+-}
+-
+-int snd_bcm2835_new_simple_pcm(struct bcm2835_chip *chip,
+- const char *name,
+- enum snd_bcm2835_route route,
+- u32 numchannels)
+-{
+- struct snd_pcm *pcm;
+- int err;
+-
+- err = snd_pcm_new(chip->card, name, 0, numchannels,
+- 0, &pcm);
++ err = snd_pcm_new(chip->card, name, idx, numchannels, 0, &pcm);
+ if (err)
+ return err;
+
+ pcm->private_data = chip;
+ pcm->nonatomic = true;
+ strcpy(pcm->name, name);
+- chip->pcm = pcm;
+- chip->dest = route;
+- chip->volume = 0;
+- chip->mute = CTRL_VOL_UNMUTE;
++ if (!spdif) {
++ chip->dest = route;
++ chip->volume = 0;
++ chip->mute = CTRL_VOL_UNMUTE;
++ }
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
++ spdif ? &snd_bcm2835_playback_spdif_ops :
+ &snd_bcm2835_playback_ops);
+
+- snd_pcm_lib_preallocate_pages_for_all(
+- pcm,
+- SNDRV_DMA_TYPE_DEV,
+- chip->card->dev->parent,
+- snd_bcm2835_playback_hw.buffer_bytes_max,
+- snd_bcm2835_playback_hw.buffer_bytes_max);
++ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
++ chip->card->dev->parent, 128 * 1024, 128 * 1024);
+
++ if (spdif)
++ chip->pcm_spdif = pcm;
++ else
++ chip->pcm = pcm;
+ return 0;
+ }
+-
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -138,17 +138,26 @@ static int bcm2835_audio_alsa_newpcm(str
+ {
+ int err;
+
+- err = snd_bcm2835_new_pcm(chip, numchannels - 1);
++ err = snd_bcm2835_new_pcm(chip, "bcm2835 ALSA", 0, AUDIO_DEST_AUTO,
++ numchannels - 1, false);
+ if (err)
+ return err;
+
+- err = snd_bcm2835_new_spdif_pcm(chip);
++ err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI", 1, 0, 1, true);
+ if (err)
+ return err;
+
+ return 0;
+ }
+
++static int bcm2835_audio_simple_newpcm(struct bcm2835_chip *chip,
++ const char *name,
++ enum snd_bcm2835_route route,
++ u32 numchannels)
++{
++ return snd_bcm2835_new_pcm(chip, name, 0, route, numchannels, false);
++}
++
+ static struct bcm2835_audio_driver bcm2835_audio_alsa = {
+ .driver = {
+ .name = "bcm2835_alsa",
+@@ -169,7 +178,7 @@ static struct bcm2835_audio_driver bcm28
+ .shortname = "bcm2835 HDMI",
+ .longname = "bcm2835 HDMI",
+ .minchannels = 1,
+- .newpcm = snd_bcm2835_new_simple_pcm,
++ .newpcm = bcm2835_audio_simple_newpcm,
+ .newctl = snd_bcm2835_new_hdmi_ctl,
+ .route = AUDIO_DEST_HDMI
+ };
+@@ -182,7 +191,7 @@ static struct bcm2835_audio_driver bcm28
+ .shortname = "bcm2835 Headphones",
+ .longname = "bcm2835 Headphones",
+ .minchannels = 1,
+- .newpcm = snd_bcm2835_new_simple_pcm,
++ .newpcm = bcm2835_audio_simple_newpcm,
+ .newctl = snd_bcm2835_new_headphones_ctl,
+ .route = AUDIO_DEST_HEADPHONES
+ };
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -84,12 +84,9 @@ struct bcm2835_alsa_stream {
+ };
+
+ int snd_bcm2835_new_ctl(struct bcm2835_chip *chip);
+-int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, u32 numchannels);
+-int snd_bcm2835_new_spdif_pcm(struct bcm2835_chip *chip);
+-int snd_bcm2835_new_simple_pcm(struct bcm2835_chip *chip,
+- const char *name,
+- enum snd_bcm2835_route route,
+- u32 numchannels);
++int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, const char *name,
++ int idx, enum snd_bcm2835_route route,
++ u32 numchannels, bool spdif);
+
+ int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip);
+ int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip);
--- /dev/null
+From 9b2cae69685c0cb362aba7341acec397b783e49b Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:57 +0200
+Subject: [PATCH 464/725] staging: bcm2835-audio: Simplify kctl creation
+ helpers
+
+commit dc5c0eb1e8601206dffbfc302cbd190f89dcd040 upstream.
+
+Just a minor code refactoring and adding some const prefix.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 69 +++++++------------
+ 1 file changed, 25 insertions(+), 44 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
+@@ -97,40 +97,34 @@ static int snd_bcm2835_ctl_put(struct sn
+
+ static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, CTRL_VOL_MIN, 1, 1);
+
+-static struct snd_kcontrol_new snd_bcm2835_ctl[] = {
++static const 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,
+ },
+ };
+
+@@ -196,7 +190,7 @@ static int snd_bcm2835_spdif_mask_get(st
+ return 0;
+ }
+
+-static struct snd_kcontrol_new snd_bcm2835_spdif[] = {
++static const struct snd_kcontrol_new snd_bcm2835_spdif[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
+@@ -213,28 +207,32 @@ static struct snd_kcontrol_new snd_bcm28
+ },
+ };
+
+-int snd_bcm2835_new_ctl(struct bcm2835_chip *chip)
++static int create_ctls(struct bcm2835_chip *chip, size_t size,
++ const struct snd_kcontrol_new *kctls)
+ {
+- int err;
+- unsigned int idx;
++ int i, err;
+
+- 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));
++ for (i = 0; i < size; i++) {
++ err = snd_ctl_add(chip->card, snd_ctl_new1(&kctls[i], chip));
+ if (err < 0)
+ return err;
+ }
+ return 0;
+ }
+
+-static struct snd_kcontrol_new snd_bcm2835_headphones_ctl[] = {
++int snd_bcm2835_new_ctl(struct bcm2835_chip *chip)
++{
++ int err;
++
++ strcpy(chip->card->mixername, "Broadcom Mixer");
++ err = create_ctls(chip, ARRAY_SIZE(snd_bcm2835_ctl), snd_bcm2835_ctl);
++ if (err < 0)
++ return err;
++ return create_ctls(chip, ARRAY_SIZE(snd_bcm2835_spdif),
++ snd_bcm2835_spdif);
++}
++
++static const struct snd_kcontrol_new snd_bcm2835_headphones_ctl[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Headphone Playback Volume",
+@@ -263,21 +261,12 @@ static struct snd_kcontrol_new snd_bcm28
+
+ int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip)
+ {
+- int err;
+- unsigned int idx;
+-
+ strcpy(chip->card->mixername, "Broadcom Mixer");
+- for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_headphones_ctl); idx++) {
+- err = snd_ctl_add(chip->card,
+- snd_ctl_new1(&snd_bcm2835_headphones_ctl[idx],
+- chip));
+- if (err)
+- return err;
+- }
+- return 0;
++ return create_ctls(chip, ARRAY_SIZE(snd_bcm2835_headphones_ctl),
++ snd_bcm2835_headphones_ctl);
+ }
+
+-static struct snd_kcontrol_new snd_bcm2835_hdmi[] = {
++static const struct snd_kcontrol_new snd_bcm2835_hdmi[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HDMI Playback Volume",
+@@ -306,16 +295,8 @@ static struct snd_kcontrol_new snd_bcm28
+
+ int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip)
+ {
+- int err;
+- unsigned int idx;
+-
+ strcpy(chip->card->mixername, "Broadcom Mixer");
+- for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_hdmi); idx++) {
+- err = snd_ctl_add(chip->card,
+- snd_ctl_new1(&snd_bcm2835_hdmi[idx], chip));
+- if (err)
+- return err;
+- }
+- return 0;
++ return create_ctls(chip, ARRAY_SIZE(snd_bcm2835_hdmi),
++ snd_bcm2835_hdmi);
+ }
+
+++ /dev/null
-From 4ff1a81a824daafb1c0fd56d299852ada0dd0b05 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:54 +0200
-Subject: [PATCH 464/703] staging: bcm2835-audio: Use coherent device buffers
-
-commit ad29c6e6cbf6f2af7362b043adad51a3be3d39c7 upstream.
-
-The memory access to the pages allocated with
-SNDRV_DMA_TYPE_CONTINUOUS are basically non-coherent, and it becomes a
-problem when a process accesses via mmap.
-
-For the more consistent access, use the device coherent memory, just
-by replacing the call pattern in the allocator helpers.
-
-The only point we need to be careful for is the device object passed
-there; since bcm2835-audio driver creates fake devices and each card
-is created on top of that, we need to pass its parent device as the
-real device object.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -345,8 +345,8 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
-
- /* 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_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-+ chip->card->dev->parent,
- snd_bcm2835_playback_hw.buffer_bytes_max,
- snd_bcm2835_playback_hw.buffer_bytes_max);
-
-@@ -371,8 +371,8 @@ int snd_bcm2835_new_spdif_pcm(struct bcm
-
- /* 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_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-+ chip->card->dev->parent,
- snd_bcm2835_playback_spdif_hw.buffer_bytes_max, snd_bcm2835_playback_spdif_hw.buffer_bytes_max);
-
- return 0;
-@@ -404,8 +404,8 @@ int snd_bcm2835_new_simple_pcm(struct bc
-
- snd_pcm_lib_preallocate_pages_for_all(
- pcm,
-- SNDRV_DMA_TYPE_CONTINUOUS,
-- snd_dma_continuous_data(GFP_KERNEL),
-+ SNDRV_DMA_TYPE_DEV,
-+ chip->card->dev->parent,
- snd_bcm2835_playback_hw.buffer_bytes_max,
- snd_bcm2835_playback_hw.buffer_bytes_max);
-
+++ /dev/null
-From b30057f82f95a75c641ff5ffe6bdb4d4507ecd8e Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:55 +0200
-Subject: [PATCH 465/703] staging: bcm2835-audio: Set
- SNDRV_PCM_INFO_SYNC_APPLPTR
-
-commit b59d6a5f73501f74848d6700101e7736afe3d54a upstream.
-
-The recent ALSA PCM core supports the SNDRV_PCM_INFO_SYNC_APPLPTR flag
-indicating that the driver needs the ack call at each appl_ptr
-update. This is requirement for the indirect PCM implementations like
-bcm2835-audio driver, too.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -12,7 +12,7 @@
- static const 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 |
-- SNDRV_PCM_INFO_DRAIN_TRIGGER),
-+ SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
- .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
- .rate_min = 8000,
-@@ -29,7 +29,7 @@ static const struct snd_pcm_hardware snd
- static const 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 |
-- SNDRV_PCM_INFO_DRAIN_TRIGGER),
-+ SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000,
--- /dev/null
+From 61a4c0f40810dde6cd4d562d452defcefdddd27a Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:58 +0200
+Subject: [PATCH 465/725] staging: bcm2835-audio: Simplify card object
+ management
+
+commit 872ae2d63d516a2a3b9c833d8685afcfa7814542 upstream.
+
+Instead of creating a dummy child device to manage the card object,
+just use devm stuff directly for releasing with snd_card_free().
+This results in a lot of code reduction.
+
+Since the dummy child devices are gone, the device object to be passed
+to the memory allocator needs to be adjusted as well.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 2 +-
+ .../vc04_services/bcm2835-audio/bcm2835.c | 120 +++++-------------
+ 2 files changed, 33 insertions(+), 89 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -349,7 +349,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
+ &snd_bcm2835_playback_ops);
+
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+- chip->card->dev->parent, 128 * 1024, 128 * 1024);
++ chip->card->dev, 128 * 1024, 128 * 1024);
+
+ if (spdif)
+ chip->pcm_spdif = pcm;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -22,38 +22,6 @@ module_param(enable_compat_alsa, bool, 0
+ MODULE_PARM_DESC(enable_compat_alsa,
+ "Enables ALSA compatibility virtual audio device");
+
+-static void snd_devm_unregister_child(struct device *dev, void *res)
+-{
+- struct device *childdev = *(struct device **)res;
+- struct bcm2835_chip *chip = dev_get_drvdata(childdev);
+- struct snd_card *card = chip->card;
+-
+- snd_card_free(card);
+-
+- device_unregister(childdev);
+-}
+-
+-static int snd_devm_add_child(struct device *dev, struct device *child)
+-{
+- struct device **dr;
+- int ret;
+-
+- dr = devres_alloc(snd_devm_unregister_child, sizeof(*dr), GFP_KERNEL);
+- if (!dr)
+- return -ENOMEM;
+-
+- ret = device_add(child);
+- if (ret) {
+- devres_free(dr);
+- return ret;
+- }
+-
+- *dr = child;
+- devres_add(dev, dr);
+-
+- return 0;
+-}
+-
+ static void bcm2835_devm_free_vchi_ctx(struct device *dev, void *res)
+ {
+ struct bcm2835_vchi_ctx *vchi_ctx = res;
+@@ -84,36 +52,6 @@ static int bcm2835_devm_add_vchi_ctx(str
+ return 0;
+ }
+
+-static void snd_bcm2835_release(struct device *dev)
+-{
+-}
+-
+-static struct device *
+-snd_create_device(struct device *parent,
+- struct device_driver *driver,
+- const char *name)
+-{
+- struct device *device;
+- int ret;
+-
+- device = devm_kzalloc(parent, sizeof(*device), GFP_KERNEL);
+- if (!device)
+- return ERR_PTR(-ENOMEM);
+-
+- device_initialize(device);
+- device->parent = parent;
+- device->driver = driver;
+- device->release = snd_bcm2835_release;
+-
+- dev_set_name(device, "%s", name);
+-
+- ret = snd_devm_add_child(parent, device);
+- if (ret)
+- return ERR_PTR(ret);
+-
+- return device;
+-}
+-
+ typedef int (*bcm2835_audio_newpcm_func)(struct bcm2835_chip *chip,
+ const char *name,
+ enum snd_bcm2835_route route,
+@@ -216,40 +154,36 @@ static struct bcm2835_audio_drivers chil
+ },
+ };
+
+-static int snd_add_child_device(struct device *device,
++static void bcm2835_card_free(void *data)
++{
++ snd_card_free(data);
++}
++
++static int snd_add_child_device(struct device *dev,
+ struct bcm2835_audio_driver *audio_driver,
+ u32 numchans)
+ {
+ struct snd_card *card;
+- struct device *child;
+ struct bcm2835_chip *chip;
+ int err;
+
+- child = snd_create_device(device, &audio_driver->driver,
+- audio_driver->driver.name);
+- if (IS_ERR(child)) {
+- dev_err(device,
+- "Unable to create child device %p, error %ld",
+- audio_driver->driver.name,
+- PTR_ERR(child));
+- return PTR_ERR(child);
+- }
+-
+- err = snd_card_new(child, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
++ err = snd_card_new(dev, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
+ if (err < 0) {
+- dev_err(child, "Failed to create card");
++ dev_err(dev, "Failed to create card");
+ return err;
+ }
+
+ chip = card->private_data;
+ chip->card = card;
+- chip->dev = child;
++ chip->dev = dev;
+ mutex_init(&chip->audio_mutex);
+
+- chip->vchi_ctx = devres_find(device,
++ chip->vchi_ctx = devres_find(dev,
+ bcm2835_devm_free_vchi_ctx, NULL, NULL);
+- if (!chip->vchi_ctx)
+- return -ENODEV;
++ if (!chip->vchi_ctx) {
++ err = -ENODEV;
++ goto error;
++ }
+
+ strcpy(card->driver, audio_driver->driver.name);
+ strcpy(card->shortname, audio_driver->shortname);
+@@ -259,26 +193,36 @@ static int snd_add_child_device(struct d
+ audio_driver->route,
+ numchans);
+ if (err) {
+- dev_err(child, "Failed to create pcm, error %d\n", err);
+- return err;
++ dev_err(dev, "Failed to create pcm, error %d\n", err);
++ goto error;
+ }
+
+ err = audio_driver->newctl(chip);
+ if (err) {
+- dev_err(child, "Failed to create controls, error %d\n", err);
+- return err;
++ dev_err(dev, "Failed to create controls, error %d\n", err);
++ goto error;
+ }
+
+ err = snd_card_register(card);
+ if (err) {
+- dev_err(child, "Failed to register card, error %d\n", err);
+- return err;
++ dev_err(dev, "Failed to register card, error %d\n", err);
++ goto error;
+ }
+
+- dev_set_drvdata(child, chip);
+- dev_info(child, "card created with %d channels\n", numchans);
++ dev_set_drvdata(dev, chip);
+
++ err = devm_add_action(dev, bcm2835_card_free, card);
++ if (err < 0) {
++ dev_err(dev, "Failed to add devm action, err %d\n", err);
++ goto error;
++ }
++
++ dev_info(dev, "card created with %d channels\n", numchans);
+ return 0;
++
++ error:
++ snd_card_free(card);
++ return err;
+ }
+
+ static int snd_add_child_devices(struct device *device, u32 numchans)
+++ /dev/null
-From 1d7ccadf57b043d8721a5110ac9203e9883fceb2 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:56 +0200
-Subject: [PATCH 466/703] staging: bcm2835-audio: Simplify PCM creation helpers
-
-commit 74470ffeb9aed5548654cfca881bf1d7469fe9c4 upstream.
-
-All three functions to create PCM objects are fairly resemble, and can
-be unified to a single common helper.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 87 ++++---------------
- .../vc04_services/bcm2835-audio/bcm2835.c | 17 +++-
- .../vc04_services/bcm2835-audio/bcm2835.h | 9 +-
- 3 files changed, 32 insertions(+), 81 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -324,91 +324,36 @@ static const struct snd_pcm_ops snd_bcm2
- };
-
- /* create a pcm device */
--int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, u32 numchannels)
-+int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, const char *name,
-+ int idx, enum snd_bcm2835_route route,
-+ u32 numchannels, bool spdif)
- {
- struct snd_pcm *pcm;
- int err;
-
-- err = snd_pcm_new(chip->card, "bcm2835 ALSA", 0, numchannels, 0, &pcm);
-- if (err < 0)
-- return err;
-- pcm->private_data = chip;
-- pcm->nonatomic = true;
-- strcpy(pcm->name, "bcm2835 ALSA");
-- chip->pcm = pcm;
-- chip->dest = AUDIO_DEST_AUTO;
-- chip->volume = 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_DEV,
-- chip->card->dev->parent,
-- snd_bcm2835_playback_hw.buffer_bytes_max,
-- snd_bcm2835_playback_hw.buffer_bytes_max);
--
-- return 0;
--}
--
--int snd_bcm2835_new_spdif_pcm(struct bcm2835_chip *chip)
--{
-- struct snd_pcm *pcm;
-- int err;
--
-- err = snd_pcm_new(chip->card, "bcm2835 ALSA", 1, 1, 0, &pcm);
-- if (err < 0)
-- return err;
--
-- pcm->private_data = chip;
-- pcm->nonatomic = true;
-- 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_DEV,
-- chip->card->dev->parent,
-- snd_bcm2835_playback_spdif_hw.buffer_bytes_max, snd_bcm2835_playback_spdif_hw.buffer_bytes_max);
--
-- return 0;
--}
--
--int snd_bcm2835_new_simple_pcm(struct bcm2835_chip *chip,
-- const char *name,
-- enum snd_bcm2835_route route,
-- u32 numchannels)
--{
-- struct snd_pcm *pcm;
-- int err;
--
-- err = snd_pcm_new(chip->card, name, 0, numchannels,
-- 0, &pcm);
-+ err = snd_pcm_new(chip->card, name, idx, numchannels, 0, &pcm);
- if (err)
- return err;
-
- pcm->private_data = chip;
- pcm->nonatomic = true;
- strcpy(pcm->name, name);
-- chip->pcm = pcm;
-- chip->dest = route;
-- chip->volume = 0;
-- chip->mute = CTRL_VOL_UNMUTE;
-+ if (!spdif) {
-+ chip->dest = route;
-+ chip->volume = 0;
-+ chip->mute = CTRL_VOL_UNMUTE;
-+ }
-
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-+ spdif ? &snd_bcm2835_playback_spdif_ops :
- &snd_bcm2835_playback_ops);
-
-- snd_pcm_lib_preallocate_pages_for_all(
-- pcm,
-- SNDRV_DMA_TYPE_DEV,
-- chip->card->dev->parent,
-- snd_bcm2835_playback_hw.buffer_bytes_max,
-- snd_bcm2835_playback_hw.buffer_bytes_max);
-+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-+ chip->card->dev->parent, 128 * 1024, 128 * 1024);
-
-+ if (spdif)
-+ chip->pcm_spdif = pcm;
-+ else
-+ chip->pcm = pcm;
- return 0;
- }
--
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -138,17 +138,26 @@ static int bcm2835_audio_alsa_newpcm(str
- {
- int err;
-
-- err = snd_bcm2835_new_pcm(chip, numchannels - 1);
-+ err = snd_bcm2835_new_pcm(chip, "bcm2835 ALSA", 0, AUDIO_DEST_AUTO,
-+ numchannels - 1, false);
- if (err)
- return err;
-
-- err = snd_bcm2835_new_spdif_pcm(chip);
-+ err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI", 1, 0, 1, true);
- if (err)
- return err;
-
- return 0;
- }
-
-+static int bcm2835_audio_simple_newpcm(struct bcm2835_chip *chip,
-+ const char *name,
-+ enum snd_bcm2835_route route,
-+ u32 numchannels)
-+{
-+ return snd_bcm2835_new_pcm(chip, name, 0, route, numchannels, false);
-+}
-+
- static struct bcm2835_audio_driver bcm2835_audio_alsa = {
- .driver = {
- .name = "bcm2835_alsa",
-@@ -169,7 +178,7 @@ static struct bcm2835_audio_driver bcm28
- .shortname = "bcm2835 HDMI",
- .longname = "bcm2835 HDMI",
- .minchannels = 1,
-- .newpcm = snd_bcm2835_new_simple_pcm,
-+ .newpcm = bcm2835_audio_simple_newpcm,
- .newctl = snd_bcm2835_new_hdmi_ctl,
- .route = AUDIO_DEST_HDMI
- };
-@@ -182,7 +191,7 @@ static struct bcm2835_audio_driver bcm28
- .shortname = "bcm2835 Headphones",
- .longname = "bcm2835 Headphones",
- .minchannels = 1,
-- .newpcm = snd_bcm2835_new_simple_pcm,
-+ .newpcm = bcm2835_audio_simple_newpcm,
- .newctl = snd_bcm2835_new_headphones_ctl,
- .route = AUDIO_DEST_HEADPHONES
- };
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -84,12 +84,9 @@ struct bcm2835_alsa_stream {
- };
-
- int snd_bcm2835_new_ctl(struct bcm2835_chip *chip);
--int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, u32 numchannels);
--int snd_bcm2835_new_spdif_pcm(struct bcm2835_chip *chip);
--int snd_bcm2835_new_simple_pcm(struct bcm2835_chip *chip,
-- const char *name,
-- enum snd_bcm2835_route route,
-- u32 numchannels);
-+int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, const char *name,
-+ int idx, enum snd_bcm2835_route route,
-+ u32 numchannels, bool spdif);
-
- int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip);
- int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip);
--- /dev/null
+From 324af1fceb517d7250b13a31e5185c06f4366d5c Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 17 Oct 2018 21:01:50 +0200
+Subject: [PATCH 466/725] staging: bcm2835-audio: unify FOURCC command
+ definitions
+
+commit a90d8f49cc7fd7220aa24b85fc74ef3cfd62b96f upstream.
+
+The device communicates with the audio core using FOURCC codes. The
+driver was generating them using different macros/expressions. We now
+use the same macro to create them and centralize all the definitions.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-vchiq.c | 13 ++++---------
+ .../bcm2835-audio/vc_vchi_audioserv_defs.h | 4 +++-
+ 2 files changed, 7 insertions(+), 10 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -89,11 +89,6 @@ static int bcm2835_audio_send_simple(str
+ return bcm2835_audio_send_msg(instance, &m, wait);
+ }
+
+-static const u32 BCM2835_AUDIO_WRITE_COOKIE1 = ('B' << 24 | 'C' << 16 |
+- 'M' << 8 | 'A');
+-static const u32 BCM2835_AUDIO_WRITE_COOKIE2 = ('D' << 24 | 'A' << 16 |
+- 'T' << 8 | 'A');
+-
+ static void audio_vchi_callback(void *param,
+ const VCHI_CALLBACK_REASON_T reason,
+ void *msg_handle)
+@@ -112,8 +107,8 @@ static void audio_vchi_callback(void *pa
+ instance->result = m.u.result.success;
+ complete(&instance->msg_avail_comp);
+ } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
+- if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 ||
+- m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2)
++ if (m.u.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 ||
++ m.u.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2)
+ dev_err(instance->dev, "invalid cookie\n");
+ else
+ bcm2835_playback_fifo(instance->alsa_stream,
+@@ -337,8 +332,8 @@ int bcm2835_audio_write(struct bcm2835_a
+ .type = VC_AUDIO_MSG_TYPE_WRITE,
+ .u.write.count = size,
+ .u.write.max_packet = instance->max_packet,
+- .u.write.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1,
+- .u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2,
++ .u.write.cookie1 = VC_AUDIO_WRITE_COOKIE1,
++ .u.write.cookie2 = VC_AUDIO_WRITE_COOKIE2,
+ };
+ unsigned int count;
+ int err, status;
+--- a/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
+@@ -7,8 +7,10 @@
+ #define VC_AUDIOSERV_MIN_VER 1
+ #define VC_AUDIOSERV_VER 2
+
+-/* FourCC code used for VCHI connection */
++/* FourCC codes used for VCHI communication */
+ #define VC_AUDIO_SERVER_NAME MAKE_FOURCC("AUDS")
++#define VC_AUDIO_WRITE_COOKIE1 MAKE_FOURCC("BCMA")
++#define VC_AUDIO_WRITE_COOKIE2 MAKE_FOURCC("DATA")
+
+ /*
+ * List of screens that are currently supported
+++ /dev/null
-From af83d44b51e549b26c1f0db6cfc3207cf9e44d50 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:57 +0200
-Subject: [PATCH 467/703] staging: bcm2835-audio: Simplify kctl creation
- helpers
-
-commit dc5c0eb1e8601206dffbfc302cbd190f89dcd040 upstream.
-
-Just a minor code refactoring and adding some const prefix.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 69 +++++++------------
- 1 file changed, 25 insertions(+), 44 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
-@@ -97,40 +97,34 @@ static int snd_bcm2835_ctl_put(struct sn
-
- static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, CTRL_VOL_MIN, 1, 1);
-
--static struct snd_kcontrol_new snd_bcm2835_ctl[] = {
-+static const 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,
- },
- };
-
-@@ -196,7 +190,7 @@ static int snd_bcm2835_spdif_mask_get(st
- return 0;
- }
-
--static struct snd_kcontrol_new snd_bcm2835_spdif[] = {
-+static const struct snd_kcontrol_new snd_bcm2835_spdif[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
-@@ -213,28 +207,32 @@ static struct snd_kcontrol_new snd_bcm28
- },
- };
-
--int snd_bcm2835_new_ctl(struct bcm2835_chip *chip)
-+static int create_ctls(struct bcm2835_chip *chip, size_t size,
-+ const struct snd_kcontrol_new *kctls)
- {
-- int err;
-- unsigned int idx;
-+ int i, err;
-
-- 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));
-+ for (i = 0; i < size; i++) {
-+ err = snd_ctl_add(chip->card, snd_ctl_new1(&kctls[i], chip));
- if (err < 0)
- return err;
- }
- return 0;
- }
-
--static struct snd_kcontrol_new snd_bcm2835_headphones_ctl[] = {
-+int snd_bcm2835_new_ctl(struct bcm2835_chip *chip)
-+{
-+ int err;
-+
-+ strcpy(chip->card->mixername, "Broadcom Mixer");
-+ err = create_ctls(chip, ARRAY_SIZE(snd_bcm2835_ctl), snd_bcm2835_ctl);
-+ if (err < 0)
-+ return err;
-+ return create_ctls(chip, ARRAY_SIZE(snd_bcm2835_spdif),
-+ snd_bcm2835_spdif);
-+}
-+
-+static const struct snd_kcontrol_new snd_bcm2835_headphones_ctl[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Headphone Playback Volume",
-@@ -263,21 +261,12 @@ static struct snd_kcontrol_new snd_bcm28
-
- int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip)
- {
-- int err;
-- unsigned int idx;
--
- strcpy(chip->card->mixername, "Broadcom Mixer");
-- for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_headphones_ctl); idx++) {
-- err = snd_ctl_add(chip->card,
-- snd_ctl_new1(&snd_bcm2835_headphones_ctl[idx],
-- chip));
-- if (err)
-- return err;
-- }
-- return 0;
-+ return create_ctls(chip, ARRAY_SIZE(snd_bcm2835_headphones_ctl),
-+ snd_bcm2835_headphones_ctl);
- }
-
--static struct snd_kcontrol_new snd_bcm2835_hdmi[] = {
-+static const struct snd_kcontrol_new snd_bcm2835_hdmi[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "HDMI Playback Volume",
-@@ -306,16 +295,8 @@ static struct snd_kcontrol_new snd_bcm28
-
- int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip)
- {
-- int err;
-- unsigned int idx;
--
- strcpy(chip->card->mixername, "Broadcom Mixer");
-- for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_hdmi); idx++) {
-- err = snd_ctl_add(chip->card,
-- snd_ctl_new1(&snd_bcm2835_hdmi[idx], chip));
-- if (err)
-- return err;
-- }
-- return 0;
-+ return create_ctls(chip, ARRAY_SIZE(snd_bcm2835_hdmi),
-+ snd_bcm2835_hdmi);
- }
-
--- /dev/null
+From e2389771445d4c01aa8c2cfdc5f854451ba1d29d Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 17 Oct 2018 21:01:51 +0200
+Subject: [PATCH 467/725] staging: bcm2835-audio: don't initialize memory twice
+
+commit 2e5f59fb77397cab3bc3d156e8be4164a67d32ef upstream.
+
+The memory is being allocated with devres_alloc(), wich ultimately uses
+__GFP_ZERO to call kmalloc. We don't need to zero the memory area again
+in bcm2835-audio.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -39,8 +39,6 @@ static int bcm2835_devm_add_vchi_ctx(str
+ if (!vchi_ctx)
+ return -ENOMEM;
+
+- memset(vchi_ctx, 0, sizeof(*vchi_ctx));
+-
+ ret = bcm2835_new_vchi_ctx(dev, vchi_ctx);
+ if (ret) {
+ devres_free(vchi_ctx);
+++ /dev/null
-From 18c2353cd57e25ececa0551b2ec22fd1f76f6484 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Tue, 4 Sep 2018 17:58:58 +0200
-Subject: [PATCH 468/703] staging: bcm2835-audio: Simplify card object
- management
-
-commit 872ae2d63d516a2a3b9c833d8685afcfa7814542 upstream.
-
-Instead of creating a dummy child device to manage the card object,
-just use devm stuff directly for releasing with snd_card_free().
-This results in a lot of code reduction.
-
-Since the dummy child devices are gone, the device object to be passed
-to the memory allocator needs to be adjusted as well.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 2 +-
- .../vc04_services/bcm2835-audio/bcm2835.c | 120 +++++-------------
- 2 files changed, 33 insertions(+), 89 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -349,7 +349,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
- &snd_bcm2835_playback_ops);
-
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-- chip->card->dev->parent, 128 * 1024, 128 * 1024);
-+ chip->card->dev, 128 * 1024, 128 * 1024);
-
- if (spdif)
- chip->pcm_spdif = pcm;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -22,38 +22,6 @@ module_param(enable_compat_alsa, bool, 0
- MODULE_PARM_DESC(enable_compat_alsa,
- "Enables ALSA compatibility virtual audio device");
-
--static void snd_devm_unregister_child(struct device *dev, void *res)
--{
-- struct device *childdev = *(struct device **)res;
-- struct bcm2835_chip *chip = dev_get_drvdata(childdev);
-- struct snd_card *card = chip->card;
--
-- snd_card_free(card);
--
-- device_unregister(childdev);
--}
--
--static int snd_devm_add_child(struct device *dev, struct device *child)
--{
-- struct device **dr;
-- int ret;
--
-- dr = devres_alloc(snd_devm_unregister_child, sizeof(*dr), GFP_KERNEL);
-- if (!dr)
-- return -ENOMEM;
--
-- ret = device_add(child);
-- if (ret) {
-- devres_free(dr);
-- return ret;
-- }
--
-- *dr = child;
-- devres_add(dev, dr);
--
-- return 0;
--}
--
- static void bcm2835_devm_free_vchi_ctx(struct device *dev, void *res)
- {
- struct bcm2835_vchi_ctx *vchi_ctx = res;
-@@ -84,36 +52,6 @@ static int bcm2835_devm_add_vchi_ctx(str
- return 0;
- }
-
--static void snd_bcm2835_release(struct device *dev)
--{
--}
--
--static struct device *
--snd_create_device(struct device *parent,
-- struct device_driver *driver,
-- const char *name)
--{
-- struct device *device;
-- int ret;
--
-- device = devm_kzalloc(parent, sizeof(*device), GFP_KERNEL);
-- if (!device)
-- return ERR_PTR(-ENOMEM);
--
-- device_initialize(device);
-- device->parent = parent;
-- device->driver = driver;
-- device->release = snd_bcm2835_release;
--
-- dev_set_name(device, "%s", name);
--
-- ret = snd_devm_add_child(parent, device);
-- if (ret)
-- return ERR_PTR(ret);
--
-- return device;
--}
--
- typedef int (*bcm2835_audio_newpcm_func)(struct bcm2835_chip *chip,
- const char *name,
- enum snd_bcm2835_route route,
-@@ -216,40 +154,36 @@ static struct bcm2835_audio_drivers chil
- },
- };
-
--static int snd_add_child_device(struct device *device,
-+static void bcm2835_card_free(void *data)
-+{
-+ snd_card_free(data);
-+}
-+
-+static int snd_add_child_device(struct device *dev,
- struct bcm2835_audio_driver *audio_driver,
- u32 numchans)
- {
- struct snd_card *card;
-- struct device *child;
- struct bcm2835_chip *chip;
- int err;
-
-- child = snd_create_device(device, &audio_driver->driver,
-- audio_driver->driver.name);
-- if (IS_ERR(child)) {
-- dev_err(device,
-- "Unable to create child device %p, error %ld",
-- audio_driver->driver.name,
-- PTR_ERR(child));
-- return PTR_ERR(child);
-- }
--
-- err = snd_card_new(child, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
-+ err = snd_card_new(dev, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
- if (err < 0) {
-- dev_err(child, "Failed to create card");
-+ dev_err(dev, "Failed to create card");
- return err;
- }
-
- chip = card->private_data;
- chip->card = card;
-- chip->dev = child;
-+ chip->dev = dev;
- mutex_init(&chip->audio_mutex);
-
-- chip->vchi_ctx = devres_find(device,
-+ chip->vchi_ctx = devres_find(dev,
- bcm2835_devm_free_vchi_ctx, NULL, NULL);
-- if (!chip->vchi_ctx)
-- return -ENODEV;
-+ if (!chip->vchi_ctx) {
-+ err = -ENODEV;
-+ goto error;
-+ }
-
- strcpy(card->driver, audio_driver->driver.name);
- strcpy(card->shortname, audio_driver->shortname);
-@@ -259,26 +193,36 @@ static int snd_add_child_device(struct d
- audio_driver->route,
- numchans);
- if (err) {
-- dev_err(child, "Failed to create pcm, error %d\n", err);
-- return err;
-+ dev_err(dev, "Failed to create pcm, error %d\n", err);
-+ goto error;
- }
-
- err = audio_driver->newctl(chip);
- if (err) {
-- dev_err(child, "Failed to create controls, error %d\n", err);
-- return err;
-+ dev_err(dev, "Failed to create controls, error %d\n", err);
-+ goto error;
- }
-
- err = snd_card_register(card);
- if (err) {
-- dev_err(child, "Failed to register card, error %d\n", err);
-- return err;
-+ dev_err(dev, "Failed to register card, error %d\n", err);
-+ goto error;
- }
-
-- dev_set_drvdata(child, chip);
-- dev_info(child, "card created with %d channels\n", numchans);
-+ dev_set_drvdata(dev, chip);
-
-+ err = devm_add_action(dev, bcm2835_card_free, card);
-+ if (err < 0) {
-+ dev_err(dev, "Failed to add devm action, err %d\n", err);
-+ goto error;
-+ }
-+
-+ dev_info(dev, "card created with %d channels\n", numchans);
- return 0;
-+
-+ error:
-+ snd_card_free(card);
-+ return err;
- }
-
- static int snd_add_child_devices(struct device *device, u32 numchans)
--- /dev/null
+From 28436930910a42f2127e0b91dcdf20ec99d1da41 Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 17 Oct 2018 21:01:52 +0200
+Subject: [PATCH 468/725] staging: bcm2835-audio: reorder variable declarations
+ & remove trivial comments
+
+commit d048385a070552ae819f99f05bd03ec41072783d upstream.
+
+When it comes to declaring variables it's preferred, when possible, to
+use an inverted tree organization scheme.
+
+Also, removes some comments that were useless.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 10 ++--------
+ .../vc04_services/bcm2835-audio/bcm2835-vchiq.c | 4 ++--
+ .../staging/vc04_services/bcm2835-audio/bcm2835.c | 14 +++++++-------
+ 3 files changed, 11 insertions(+), 17 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -164,14 +164,11 @@ static int snd_bcm2835_playback_spdif_op
+ 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 */
+-
+- struct bcm2835_chip *chip;
+- struct snd_pcm_runtime *runtime;
+ struct bcm2835_alsa_stream *alsa_stream;
++ struct snd_pcm_runtime *runtime;
++ struct bcm2835_chip *chip;
+
+ chip = snd_pcm_substream_chip(substream);
+ mutex_lock(&chip->audio_mutex);
+@@ -195,20 +192,17 @@ static int snd_bcm2835_playback_close(st
+ return 0;
+ }
+
+-/* hw_params callback */
+ static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+ {
+ return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+ }
+
+-/* hw_free callback */
+ static int snd_bcm2835_pcm_hw_free(struct snd_pcm_substream *substream)
+ {
+ return snd_pcm_lib_free_pages(substream);
+ }
+
+-/* prepare callback */
+ static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream)
+ {
+ struct bcm2835_chip *chip = snd_pcm_substream_chip(substream);
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -94,9 +94,9 @@ static void audio_vchi_callback(void *pa
+ void *msg_handle)
+ {
+ struct bcm2835_audio_instance *instance = param;
+- int status;
+- int msg_len;
+ struct vc_audio_msg m;
++ int msg_len;
++ int status;
+
+ if (reason != VCHI_CALLBACK_MSG_AVAILABLE)
+ return;
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -161,8 +161,8 @@ static int snd_add_child_device(struct d
+ struct bcm2835_audio_driver *audio_driver,
+ u32 numchans)
+ {
+- struct snd_card *card;
+ struct bcm2835_chip *chip;
++ struct snd_card *card;
+ int err;
+
+ err = snd_card_new(dev, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
+@@ -225,12 +225,12 @@ static int snd_add_child_device(struct d
+
+ static int snd_add_child_devices(struct device *device, u32 numchans)
+ {
+- int i;
+- int count_devices = 0;
+- int minchannels = 0;
+- int extrachannels = 0;
+ int extrachannels_per_driver = 0;
+ int extrachannels_remainder = 0;
++ int count_devices = 0;
++ int extrachannels = 0;
++ int minchannels = 0;
++ int i;
+
+ for (i = 0; i < ARRAY_SIZE(children_devices); i++)
+ if (*children_devices[i].is_enabled)
+@@ -258,9 +258,9 @@ static int snd_add_child_devices(struct
+ extrachannels_remainder);
+
+ for (i = 0; i < ARRAY_SIZE(children_devices); i++) {
+- int err;
+- int numchannels_this_device;
+ struct bcm2835_audio_driver *audio_driver;
++ int numchannels_this_device;
++ int err;
+
+ if (!*children_devices[i].is_enabled)
+ continue;
+++ /dev/null
-From 6bfd152edc4d9a19836dc2a12c9545a5ccc1a87f Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 17 Oct 2018 21:01:50 +0200
-Subject: [PATCH 469/703] staging: bcm2835-audio: unify FOURCC command
- definitions
-
-commit a90d8f49cc7fd7220aa24b85fc74ef3cfd62b96f upstream.
-
-The device communicates with the audio core using FOURCC codes. The
-driver was generating them using different macros/expressions. We now
-use the same macro to create them and centralize all the definitions.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Takashi Iwai <tiwai@suse.de>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-vchiq.c | 13 ++++---------
- .../bcm2835-audio/vc_vchi_audioserv_defs.h | 4 +++-
- 2 files changed, 7 insertions(+), 10 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -89,11 +89,6 @@ static int bcm2835_audio_send_simple(str
- return bcm2835_audio_send_msg(instance, &m, wait);
- }
-
--static const u32 BCM2835_AUDIO_WRITE_COOKIE1 = ('B' << 24 | 'C' << 16 |
-- 'M' << 8 | 'A');
--static const u32 BCM2835_AUDIO_WRITE_COOKIE2 = ('D' << 24 | 'A' << 16 |
-- 'T' << 8 | 'A');
--
- static void audio_vchi_callback(void *param,
- const VCHI_CALLBACK_REASON_T reason,
- void *msg_handle)
-@@ -112,8 +107,8 @@ static void audio_vchi_callback(void *pa
- instance->result = m.u.result.success;
- complete(&instance->msg_avail_comp);
- } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
-- if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 ||
-- m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2)
-+ if (m.u.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 ||
-+ m.u.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2)
- dev_err(instance->dev, "invalid cookie\n");
- else
- bcm2835_playback_fifo(instance->alsa_stream,
-@@ -337,8 +332,8 @@ int bcm2835_audio_write(struct bcm2835_a
- .type = VC_AUDIO_MSG_TYPE_WRITE,
- .u.write.count = size,
- .u.write.max_packet = instance->max_packet,
-- .u.write.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1,
-- .u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2,
-+ .u.write.cookie1 = VC_AUDIO_WRITE_COOKIE1,
-+ .u.write.cookie2 = VC_AUDIO_WRITE_COOKIE2,
- };
- unsigned int count;
- int err, status;
---- a/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
-@@ -7,8 +7,10 @@
- #define VC_AUDIOSERV_MIN_VER 1
- #define VC_AUDIOSERV_VER 2
-
--/* FourCC code used for VCHI connection */
-+/* FourCC codes used for VCHI communication */
- #define VC_AUDIO_SERVER_NAME MAKE_FOURCC("AUDS")
-+#define VC_AUDIO_WRITE_COOKIE1 MAKE_FOURCC("BCMA")
-+#define VC_AUDIO_WRITE_COOKIE2 MAKE_FOURCC("DATA")
-
- /*
- * List of screens that are currently supported
--- /dev/null
+From 5f7ebc0e341a4bf93db4c8e031b0e260be567e00 Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 17 Oct 2018 21:01:53 +0200
+Subject: [PATCH 469/725] staging: bcm2835-audio: use anonymous union in struct
+ vc_audio_msg
+
+commit 9c2eaf7da855d314a369d48b9cbf8ac80717a1d0 upstream.
+
+In this case explicitly naming the union doesn't help overall code
+comprehension and clutters it.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../bcm2835-audio/bcm2835-vchiq.c | 30 +++++++++----------
+ .../bcm2835-audio/vc_vchi_audioserv_defs.h | 2 +-
+ 2 files changed, 16 insertions(+), 16 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -104,15 +104,15 @@ static void audio_vchi_callback(void *pa
+ status = vchi_msg_dequeue(instance->vchi_handle,
+ &m, sizeof(m), &msg_len, VCHI_FLAGS_NONE);
+ if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
+- instance->result = m.u.result.success;
++ instance->result = m.result.success;
+ complete(&instance->msg_avail_comp);
+ } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
+- if (m.u.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 ||
+- m.u.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2)
++ if (m.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 ||
++ m.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2)
+ dev_err(instance->dev, "invalid cookie\n");
+ else
+ bcm2835_playback_fifo(instance->alsa_stream,
+- m.u.complete.count);
++ m.complete.count);
+ } else {
+ dev_err(instance->dev, "unexpected callback type=%d\n", m.type);
+ }
+@@ -257,11 +257,11 @@ int bcm2835_audio_set_ctls(struct bcm283
+ struct vc_audio_msg m = {};
+
+ m.type = VC_AUDIO_MSG_TYPE_CONTROL;
+- m.u.control.dest = chip->dest;
++ m.control.dest = chip->dest;
+ if (!chip->mute)
+- m.u.control.volume = CHIP_MIN_VOLUME;
++ m.control.volume = CHIP_MIN_VOLUME;
+ else
+- m.u.control.volume = alsa2chip(chip->volume);
++ m.control.volume = alsa2chip(chip->volume);
+
+ return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
+ }
+@@ -272,9 +272,9 @@ int bcm2835_audio_set_params(struct bcm2
+ {
+ struct vc_audio_msg m = {
+ .type = VC_AUDIO_MSG_TYPE_CONFIG,
+- .u.config.channels = channels,
+- .u.config.samplerate = samplerate,
+- .u.config.bps = bps,
++ .config.channels = channels,
++ .config.samplerate = samplerate,
++ .config.bps = bps,
+ };
+ int err;
+
+@@ -302,7 +302,7 @@ int bcm2835_audio_drain(struct bcm2835_a
+ {
+ struct vc_audio_msg m = {
+ .type = VC_AUDIO_MSG_TYPE_STOP,
+- .u.stop.draining = 1,
++ .stop.draining = 1,
+ };
+
+ return bcm2835_audio_send_msg(alsa_stream->instance, &m, false);
+@@ -330,10 +330,10 @@ int bcm2835_audio_write(struct bcm2835_a
+ struct bcm2835_audio_instance *instance = alsa_stream->instance;
+ struct vc_audio_msg m = {
+ .type = VC_AUDIO_MSG_TYPE_WRITE,
+- .u.write.count = size,
+- .u.write.max_packet = instance->max_packet,
+- .u.write.cookie1 = VC_AUDIO_WRITE_COOKIE1,
+- .u.write.cookie2 = VC_AUDIO_WRITE_COOKIE2,
++ .write.count = size,
++ .write.max_packet = instance->max_packet,
++ .write.cookie1 = VC_AUDIO_WRITE_COOKIE1,
++ .write.cookie2 = VC_AUDIO_WRITE_COOKIE2,
+ };
+ unsigned int count;
+ int err, status;
+--- a/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
+@@ -93,7 +93,7 @@ struct vc_audio_msg {
+ struct vc_audio_write write;
+ struct vc_audio_result result;
+ struct vc_audio_complete complete;
+- } u;
++ };
+ };
+
+ #endif /* _VC_AUDIO_DEFS_H_ */
+++ /dev/null
-From 2477bc42397c7be4c74429b6fb8c1325765b9a46 Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 17 Oct 2018 21:01:51 +0200
-Subject: [PATCH 470/703] staging: bcm2835-audio: don't initialize memory twice
-
-commit 2e5f59fb77397cab3bc3d156e8be4164a67d32ef upstream.
-
-The memory is being allocated with devres_alloc(), wich ultimately uses
-__GFP_ZERO to call kmalloc. We don't need to zero the memory area again
-in bcm2835-audio.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Takashi Iwai <tiwai@suse.de>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 2 --
- 1 file changed, 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -39,8 +39,6 @@ static int bcm2835_devm_add_vchi_ctx(str
- if (!vchi_ctx)
- return -ENOMEM;
-
-- memset(vchi_ctx, 0, sizeof(*vchi_ctx));
--
- ret = bcm2835_new_vchi_ctx(dev, vchi_ctx);
- if (ret) {
- devres_free(vchi_ctx);
--- /dev/null
+From 769a356761d6848a6ba1d396d97c76d6ff81451f Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 17 Oct 2018 21:01:54 +0200
+Subject: [PATCH 470/725] staging: bcm2835-audio: more generic probe function
+ name
+
+commit 96f3bd8ae6516898c7b411ecb87064bb0dd25415 upstream.
+
+There will only be one probe function, there is no use for appendig
+"_dt" the end of the name.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -291,7 +291,7 @@ static int snd_add_child_devices(struct
+ return 0;
+ }
+
+-static int snd_bcm2835_alsa_probe_dt(struct platform_device *pdev)
++static int snd_bcm2835_alsa_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ u32 numchans;
+@@ -344,7 +344,7 @@ static const struct of_device_id snd_bcm
+ MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table);
+
+ static struct platform_driver bcm2835_alsa0_driver = {
+- .probe = snd_bcm2835_alsa_probe_dt,
++ .probe = snd_bcm2835_alsa_probe,
+ #ifdef CONFIG_PM
+ .suspend = snd_bcm2835_alsa_suspend,
+ .resume = snd_bcm2835_alsa_resume,
--- /dev/null
+From e46a97daa661f61453787ef90c95fe02e36ba48d Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 17 Oct 2018 21:01:55 +0200
+Subject: [PATCH 471/725] staging: bcm2835-audio: rename platform_driver
+ structure
+
+commit 82cdc0c6b6faf877e2aecb957cffa9cb578cc572 upstream.
+
+It was called bcm2835_alsa0_driver, that "0" didn't mean much.
+
+Suggested-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -343,7 +343,7 @@ static const struct of_device_id snd_bcm
+ };
+ MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table);
+
+-static struct platform_driver bcm2835_alsa0_driver = {
++static struct platform_driver bcm2835_alsa_driver = {
+ .probe = snd_bcm2835_alsa_probe,
+ #ifdef CONFIG_PM
+ .suspend = snd_bcm2835_alsa_suspend,
+@@ -359,7 +359,7 @@ static int bcm2835_alsa_device_init(void
+ {
+ int retval;
+
+- retval = platform_driver_register(&bcm2835_alsa0_driver);
++ retval = platform_driver_register(&bcm2835_alsa_driver);
+ if (retval)
+ pr_err("Error registering bcm2835_audio driver %d .\n", retval);
+
+@@ -368,7 +368,7 @@ static int bcm2835_alsa_device_init(void
+
+ static void bcm2835_alsa_device_exit(void)
+ {
+- platform_driver_unregister(&bcm2835_alsa0_driver);
++ platform_driver_unregister(&bcm2835_alsa_driver);
+ }
+
+ late_initcall(bcm2835_alsa_device_init);
+++ /dev/null
-From 42b0651189ceea6c9684931d68566091a37914a3 Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 17 Oct 2018 21:01:52 +0200
-Subject: [PATCH 471/703] staging: bcm2835-audio: reorder variable declarations
- & remove trivial comments
-
-commit d048385a070552ae819f99f05bd03ec41072783d upstream.
-
-When it comes to declaring variables it's preferred, when possible, to
-use an inverted tree organization scheme.
-
-Also, removes some comments that were useless.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Takashi Iwai <tiwai@suse.de>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 10 ++--------
- .../vc04_services/bcm2835-audio/bcm2835-vchiq.c | 4 ++--
- .../staging/vc04_services/bcm2835-audio/bcm2835.c | 14 +++++++-------
- 3 files changed, 11 insertions(+), 17 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -164,14 +164,11 @@ static int snd_bcm2835_playback_spdif_op
- 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 */
--
-- struct bcm2835_chip *chip;
-- struct snd_pcm_runtime *runtime;
- struct bcm2835_alsa_stream *alsa_stream;
-+ struct snd_pcm_runtime *runtime;
-+ struct bcm2835_chip *chip;
-
- chip = snd_pcm_substream_chip(substream);
- mutex_lock(&chip->audio_mutex);
-@@ -195,20 +192,17 @@ static int snd_bcm2835_playback_close(st
- return 0;
- }
-
--/* hw_params callback */
- static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
- {
- return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
- }
-
--/* hw_free callback */
- static int snd_bcm2835_pcm_hw_free(struct snd_pcm_substream *substream)
- {
- return snd_pcm_lib_free_pages(substream);
- }
-
--/* prepare callback */
- static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream)
- {
- struct bcm2835_chip *chip = snd_pcm_substream_chip(substream);
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -94,9 +94,9 @@ static void audio_vchi_callback(void *pa
- void *msg_handle)
- {
- struct bcm2835_audio_instance *instance = param;
-- int status;
-- int msg_len;
- struct vc_audio_msg m;
-+ int msg_len;
-+ int status;
-
- if (reason != VCHI_CALLBACK_MSG_AVAILABLE)
- return;
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -161,8 +161,8 @@ static int snd_add_child_device(struct d
- struct bcm2835_audio_driver *audio_driver,
- u32 numchans)
- {
-- struct snd_card *card;
- struct bcm2835_chip *chip;
-+ struct snd_card *card;
- int err;
-
- err = snd_card_new(dev, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
-@@ -225,12 +225,12 @@ static int snd_add_child_device(struct d
-
- static int snd_add_child_devices(struct device *device, u32 numchans)
- {
-- int i;
-- int count_devices = 0;
-- int minchannels = 0;
-- int extrachannels = 0;
- int extrachannels_per_driver = 0;
- int extrachannels_remainder = 0;
-+ int count_devices = 0;
-+ int extrachannels = 0;
-+ int minchannels = 0;
-+ int i;
-
- for (i = 0; i < ARRAY_SIZE(children_devices); i++)
- if (*children_devices[i].is_enabled)
-@@ -258,9 +258,9 @@ static int snd_add_child_devices(struct
- extrachannels_remainder);
-
- for (i = 0; i < ARRAY_SIZE(children_devices); i++) {
-- int err;
-- int numchannels_this_device;
- struct bcm2835_audio_driver *audio_driver;
-+ int numchannels_this_device;
-+ int err;
-
- if (!*children_devices[i].is_enabled)
- continue;
--- /dev/null
+From c13b55d072cfd79e0dc17a80ee7536b272e5bcca Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Wed, 17 Oct 2018 21:01:56 +0200
+Subject: [PATCH 472/725] staging: bcm2835-audio: update TODO
+
+commit 01ec7398c56e8f1b903ecb3c5c75400e263eef43 upstream.
+
+The following tasks were completed or not the right solution:
+
+1/2- Not the proper solution, we should register a platform device in
+vchiq the same way it's done with bcm2835-camera as commented here:
+https://lkml.org/lkml/2018/10/16/1131
+
+2/3- Fixed by Takashi Iwai here: https://lkml.org/lkml/2018/9/4/587
+
+Also, adds a new task as per mailing list conversation.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../staging/vc04_services/bcm2835-audio/TODO | 25 +++----------------
+ 1 file changed, 3 insertions(+), 22 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/TODO
++++ b/drivers/staging/vc04_services/bcm2835-audio/TODO
+@@ -4,26 +4,7 @@
+ * *
+ *****************************************************************************
+
++1) Revisit multi-cards options and PCM route mixer control (as per comment
++https://lkml.org/lkml/2018/9/8/200)
+
+-1) Document the device tree node
+-
+-The downstream tree(the tree that the driver was imported from) at
+-http://www.github.com/raspberrypi/linux uses this node:
+-
+-audio: audio {
+- compatible = "brcm,bcm2835-audio";
+- brcm,pwm-channels = <8>;
+-};
+-
+-Since the driver requires the use of VCHIQ, it may be useful to have a link
+-in the device tree to the VCHIQ driver.
+-
+-2) Gracefully handle the case where VCHIQ is missing from the device tree or
+-it has not been initialized yet.
+-
+-3) Review error handling and remove duplicate code.
+-
+-4) Cleanup the logging mechanism. The driver should probably be using the
+-standard kernel logging mechanisms such as dev_info, dev_dbg, and friends.
+-
+-5) Fix the remaining checkpatch.pl errors and warnings.
++2) Fix the remaining checkpatch.pl errors and warnings.
+++ /dev/null
-From ba6476674aaab4ed91db3792eb860c65ff6c588f Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 17 Oct 2018 21:01:53 +0200
-Subject: [PATCH 472/703] staging: bcm2835-audio: use anonymous union in struct
- vc_audio_msg
-
-commit 9c2eaf7da855d314a369d48b9cbf8ac80717a1d0 upstream.
-
-In this case explicitly naming the union doesn't help overall code
-comprehension and clutters it.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Takashi Iwai <tiwai@suse.de>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../bcm2835-audio/bcm2835-vchiq.c | 30 +++++++++----------
- .../bcm2835-audio/vc_vchi_audioserv_defs.h | 2 +-
- 2 files changed, 16 insertions(+), 16 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -104,15 +104,15 @@ static void audio_vchi_callback(void *pa
- status = vchi_msg_dequeue(instance->vchi_handle,
- &m, sizeof(m), &msg_len, VCHI_FLAGS_NONE);
- if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
-- instance->result = m.u.result.success;
-+ instance->result = m.result.success;
- complete(&instance->msg_avail_comp);
- } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
-- if (m.u.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 ||
-- m.u.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2)
-+ if (m.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 ||
-+ m.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2)
- dev_err(instance->dev, "invalid cookie\n");
- else
- bcm2835_playback_fifo(instance->alsa_stream,
-- m.u.complete.count);
-+ m.complete.count);
- } else {
- dev_err(instance->dev, "unexpected callback type=%d\n", m.type);
- }
-@@ -257,11 +257,11 @@ int bcm2835_audio_set_ctls(struct bcm283
- struct vc_audio_msg m = {};
-
- m.type = VC_AUDIO_MSG_TYPE_CONTROL;
-- m.u.control.dest = chip->dest;
-+ m.control.dest = chip->dest;
- if (!chip->mute)
-- m.u.control.volume = CHIP_MIN_VOLUME;
-+ m.control.volume = CHIP_MIN_VOLUME;
- else
-- m.u.control.volume = alsa2chip(chip->volume);
-+ m.control.volume = alsa2chip(chip->volume);
-
- return bcm2835_audio_send_msg(alsa_stream->instance, &m, true);
- }
-@@ -272,9 +272,9 @@ int bcm2835_audio_set_params(struct bcm2
- {
- struct vc_audio_msg m = {
- .type = VC_AUDIO_MSG_TYPE_CONFIG,
-- .u.config.channels = channels,
-- .u.config.samplerate = samplerate,
-- .u.config.bps = bps,
-+ .config.channels = channels,
-+ .config.samplerate = samplerate,
-+ .config.bps = bps,
- };
- int err;
-
-@@ -302,7 +302,7 @@ int bcm2835_audio_drain(struct bcm2835_a
- {
- struct vc_audio_msg m = {
- .type = VC_AUDIO_MSG_TYPE_STOP,
-- .u.stop.draining = 1,
-+ .stop.draining = 1,
- };
-
- return bcm2835_audio_send_msg(alsa_stream->instance, &m, false);
-@@ -330,10 +330,10 @@ int bcm2835_audio_write(struct bcm2835_a
- struct bcm2835_audio_instance *instance = alsa_stream->instance;
- struct vc_audio_msg m = {
- .type = VC_AUDIO_MSG_TYPE_WRITE,
-- .u.write.count = size,
-- .u.write.max_packet = instance->max_packet,
-- .u.write.cookie1 = VC_AUDIO_WRITE_COOKIE1,
-- .u.write.cookie2 = VC_AUDIO_WRITE_COOKIE2,
-+ .write.count = size,
-+ .write.max_packet = instance->max_packet,
-+ .write.cookie1 = VC_AUDIO_WRITE_COOKIE1,
-+ .write.cookie2 = VC_AUDIO_WRITE_COOKIE2,
- };
- unsigned int count;
- int err, status;
---- a/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
-@@ -93,7 +93,7 @@ struct vc_audio_msg {
- struct vc_audio_write write;
- struct vc_audio_result result;
- struct vc_audio_complete complete;
-- } u;
-+ };
- };
-
- #endif /* _VC_AUDIO_DEFS_H_ */
--- /dev/null
+From 3cd2b5a8d643c8e1d8ae0a63fc517ec7f47c6fb0 Mon Sep 17 00:00:00 2001
+From: Mike Brady <mikebrady@eircom.net>
+Date: Mon, 22 Oct 2018 20:17:08 +0100
+Subject: [PATCH 473/725] staging: bcm2835-audio: interpolate audio delay
+
+commit a105a3a72824e0ac685a0711a67e4dbe29de62d0 upstream.
+
+When the BCM2835 audio output is used, userspace sees a jitter up to 10ms
+in the audio position, aka "delay" -- the number of frames that must
+be output before a new frame would be played.
+Make this a bit nicer for userspace by interpolating the position
+using the CPU clock.
+The overhead is small -- an extra ktime_get() every time a GPU message
+is sent -- and another call and a few calculations whenever the delay
+is sought from userland.
+At 48,000 frames per second, i.e. approximately 20 microseconds per
+frame, it would take a clock inaccuracy of
+20 microseconds in 10 milliseconds -- 2,000 parts per million --
+to result in an inaccurate estimate, whereas
+crystal- or resonator-based clocks typically have an
+inaccuracy of 10s to 100s of parts per million.
+
+Signed-off-by: Mike Brady <mikebrady@eircom.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 20 +++++++++++++++++++
+ .../vc04_services/bcm2835-audio/bcm2835.h | 1 +
+ 2 files changed, 21 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -74,6 +74,7 @@ void bcm2835_playback_fifo(struct bcm283
+ atomic_set(&alsa_stream->pos, pos);
+
+ alsa_stream->period_offset += bytes;
++ alsa_stream->interpolate_start = ktime_get();
+ if (alsa_stream->period_offset >= alsa_stream->period_size) {
+ alsa_stream->period_offset %= alsa_stream->period_size;
+ snd_pcm_period_elapsed(substream);
+@@ -237,6 +238,7 @@ static int snd_bcm2835_pcm_prepare(struc
+ atomic_set(&alsa_stream->pos, 0);
+ alsa_stream->period_offset = 0;
+ alsa_stream->draining = false;
++ alsa_stream->interpolate_start = ktime_get();
+
+ return 0;
+ }
+@@ -286,6 +288,24 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
++ ktime_t now = ktime_get();
++
++ /* Give userspace better delay reporting by interpolating between GPU
++ * notifications, assuming audio speed is close enough to the clock
++ * used for ktime
++ */
++
++ if ((ktime_to_ns(alsa_stream->interpolate_start)) &&
++ (ktime_compare(alsa_stream->interpolate_start, now) < 0)) {
++ u64 interval =
++ (ktime_to_ns(ktime_sub(now,
++ alsa_stream->interpolate_start)));
++ u64 frames_output_in_interval =
++ div_u64((interval * runtime->rate), 1000000000);
++ snd_pcm_sframes_t frames_output_in_interval_sized =
++ -frames_output_in_interval;
++ runtime->delay = frames_output_in_interval_sized;
++ }
+
+ return snd_pcm_indirect_playback_pointer(substream,
+ &alsa_stream->pcm_indirect,
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -78,6 +78,7 @@ struct bcm2835_alsa_stream {
+ unsigned int period_offset;
+ unsigned int buffer_size;
+ unsigned int period_size;
++ ktime_t interpolate_start;
+
+ struct bcm2835_audio_instance *instance;
+ int idx;
+++ /dev/null
-From 7c0e6cbc1257861e011256fd78a713b8d308541d Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 17 Oct 2018 21:01:54 +0200
-Subject: [PATCH 473/703] staging: bcm2835-audio: more generic probe function
- name
-
-commit 96f3bd8ae6516898c7b411ecb87064bb0dd25415 upstream.
-
-There will only be one probe function, there is no use for appendig
-"_dt" the end of the name.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Takashi Iwai <tiwai@suse.de>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -291,7 +291,7 @@ static int snd_add_child_devices(struct
- return 0;
- }
-
--static int snd_bcm2835_alsa_probe_dt(struct platform_device *pdev)
-+static int snd_bcm2835_alsa_probe(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
- u32 numchans;
-@@ -344,7 +344,7 @@ static const struct of_device_id snd_bcm
- MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table);
-
- static struct platform_driver bcm2835_alsa0_driver = {
-- .probe = snd_bcm2835_alsa_probe_dt,
-+ .probe = snd_bcm2835_alsa_probe,
- #ifdef CONFIG_PM
- .suspend = snd_bcm2835_alsa_suspend,
- .resume = snd_bcm2835_alsa_resume,
--- /dev/null
+From 68093eedc7ce6e023944cc1099810351ad3a21dd Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Thu, 6 Dec 2018 19:28:56 +0100
+Subject: [PATCH 474/725] staging: bcm2835-audio: Enable compile test
+
+commit 458d4866a34d0c129ffc3bd56345b2166ba46d77 upstream.
+
+Enable the compilation test for bcm2835-audio to gain more build coverage.
+
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/Kconfig
++++ b/drivers/staging/vc04_services/bcm2835-audio/Kconfig
+@@ -1,6 +1,6 @@
+ config SND_BCM2835
+ tristate "BCM2835 Audio"
+- depends on ARCH_BCM2835 && SND
++ depends on (ARCH_BCM2835 || COMPILE_TEST) && SND
+ select SND_PCM
+ select BCM2835_VCHIQ
+ help
+++ /dev/null
-From 8766790884bfc46d8036a9da0dcf8d0cf291e42b Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 17 Oct 2018 21:01:55 +0200
-Subject: [PATCH 474/703] staging: bcm2835-audio: rename platform_driver
- structure
-
-commit 82cdc0c6b6faf877e2aecb957cffa9cb578cc572 upstream.
-
-It was called bcm2835_alsa0_driver, that "0" didn't mean much.
-
-Suggested-by: Takashi Iwai <tiwai@suse.de>
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -343,7 +343,7 @@ static const struct of_device_id snd_bcm
- };
- MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table);
-
--static struct platform_driver bcm2835_alsa0_driver = {
-+static struct platform_driver bcm2835_alsa_driver = {
- .probe = snd_bcm2835_alsa_probe,
- #ifdef CONFIG_PM
- .suspend = snd_bcm2835_alsa_suspend,
-@@ -359,7 +359,7 @@ static int bcm2835_alsa_device_init(void
- {
- int retval;
-
-- retval = platform_driver_register(&bcm2835_alsa0_driver);
-+ retval = platform_driver_register(&bcm2835_alsa_driver);
- if (retval)
- pr_err("Error registering bcm2835_audio driver %d .\n", retval);
-
-@@ -368,7 +368,7 @@ static int bcm2835_alsa_device_init(void
-
- static void bcm2835_alsa_device_exit(void)
- {
-- platform_driver_unregister(&bcm2835_alsa0_driver);
-+ platform_driver_unregister(&bcm2835_alsa_driver);
- }
-
- late_initcall(bcm2835_alsa_device_init);
+++ /dev/null
-From ab9ae6bfcca7033f0d6767e21076d82f4554ba99 Mon Sep 17 00:00:00 2001
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Date: Wed, 17 Oct 2018 21:01:56 +0200
-Subject: [PATCH 475/703] staging: bcm2835-audio: update TODO
-
-commit 01ec7398c56e8f1b903ecb3c5c75400e263eef43 upstream.
-
-The following tasks were completed or not the right solution:
-
-1/2- Not the proper solution, we should register a platform device in
-vchiq the same way it's done with bcm2835-camera as commented here:
-https://lkml.org/lkml/2018/10/16/1131
-
-2/3- Fixed by Takashi Iwai here: https://lkml.org/lkml/2018/9/4/587
-
-Also, adds a new task as per mailing list conversation.
-
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../staging/vc04_services/bcm2835-audio/TODO | 25 +++----------------
- 1 file changed, 3 insertions(+), 22 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/TODO
-+++ b/drivers/staging/vc04_services/bcm2835-audio/TODO
-@@ -4,26 +4,7 @@
- * *
- *****************************************************************************
-
-+1) Revisit multi-cards options and PCM route mixer control (as per comment
-+https://lkml.org/lkml/2018/9/8/200)
-
--1) Document the device tree node
--
--The downstream tree(the tree that the driver was imported from) at
--http://www.github.com/raspberrypi/linux uses this node:
--
--audio: audio {
-- compatible = "brcm,bcm2835-audio";
-- brcm,pwm-channels = <8>;
--};
--
--Since the driver requires the use of VCHIQ, it may be useful to have a link
--in the device tree to the VCHIQ driver.
--
--2) Gracefully handle the case where VCHIQ is missing from the device tree or
--it has not been initialized yet.
--
--3) Review error handling and remove duplicate code.
--
--4) Cleanup the logging mechanism. The driver should probably be using the
--standard kernel logging mechanisms such as dev_info, dev_dbg, and friends.
--
--5) Fix the remaining checkpatch.pl errors and warnings.
-+2) Fix the remaining checkpatch.pl errors and warnings.
--- /dev/null
+From d84c50e6ccd6138d902da87d293ee6ae5855b611 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Thu, 6 Dec 2018 19:28:57 +0100
+Subject: [PATCH 475/725] staging: bcm2835-audio: use module_platform_driver()
+ macro
+
+commit 1e55d56344b0777d6cee9b9e4a813d53728ee798 upstream.
+
+There is not much value behind this boilerplate, so use
+module_platform_driver() instead.
+
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835.c | 20 +------------------
+ 1 file changed, 1 insertion(+), 19 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -354,25 +354,7 @@ static struct platform_driver bcm2835_al
+ .of_match_table = snd_bcm2835_of_match_table,
+ },
+ };
+-
+-static int bcm2835_alsa_device_init(void)
+-{
+- int retval;
+-
+- retval = platform_driver_register(&bcm2835_alsa_driver);
+- if (retval)
+- pr_err("Error registering bcm2835_audio driver %d .\n", retval);
+-
+- return retval;
+-}
+-
+-static void bcm2835_alsa_device_exit(void)
+-{
+- platform_driver_unregister(&bcm2835_alsa_driver);
+-}
+-
+-late_initcall(bcm2835_alsa_device_init);
+-module_exit(bcm2835_alsa_device_exit);
++module_platform_driver(bcm2835_alsa_driver);
+
+ MODULE_AUTHOR("Dom Cobley");
+ MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
--- /dev/null
+From e035b14b6608084e3276253cf477ecfc0f68fd18 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <stefan.wahren@i2se.com>
+Date: Thu, 6 Dec 2018 19:28:58 +0100
+Subject: [PATCH 476/725] staging: bcm2835-audio: Drop DT dependency
+
+commit 438fc48260a0afc4cee733e5bc20234ff2bbef56 upstream.
+
+Just like the bcm2835-video make this a platform driver which is probed
+by vchiq. In order to change the number of channels use a module
+parameter instead, but use the maximum as default.
+
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../vc04_services/bcm2835-audio/bcm2835.c | 31 ++++++-------------
+ 1 file changed, 9 insertions(+), 22 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -6,13 +6,13 @@
+ #include <linux/init.h>
+ #include <linux/slab.h>
+ #include <linux/module.h>
+-#include <linux/of.h>
+
+ #include "bcm2835.h"
+
+ static bool enable_hdmi;
+ static bool enable_headphones;
+ static bool enable_compat_alsa = true;
++static int num_channels = MAX_SUBSTREAMS;
+
+ module_param(enable_hdmi, bool, 0444);
+ MODULE_PARM_DESC(enable_hdmi, "Enables HDMI virtual audio device");
+@@ -21,6 +21,8 @@ MODULE_PARM_DESC(enable_headphones, "Ena
+ module_param(enable_compat_alsa, bool, 0444);
+ MODULE_PARM_DESC(enable_compat_alsa,
+ "Enables ALSA compatibility virtual audio device");
++module_param(num_channels, int, 0644);
++MODULE_PARM_DESC(num_channels, "Number of audio channels (default: 8)");
+
+ static void bcm2835_devm_free_vchi_ctx(struct device *dev, void *res)
+ {
+@@ -294,28 +296,19 @@ static int snd_add_child_devices(struct
+ static int snd_bcm2835_alsa_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+- u32 numchans;
+ int err;
+
+- 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);
++ if (num_channels <= 0 || num_channels > MAX_SUBSTREAMS) {
++ num_channels = MAX_SUBSTREAMS;
++ dev_warn(dev, "Illegal num_channels value, will use %u\n",
++ num_channels);
+ }
+
+ err = bcm2835_devm_add_vchi_ctx(dev);
+ if (err)
+ return err;
+
+- err = snd_add_child_devices(dev, numchans);
++ err = snd_add_child_devices(dev, num_channels);
+ if (err)
+ return err;
+
+@@ -337,12 +330,6 @@ static int snd_bcm2835_alsa_resume(struc
+
+ #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_alsa_driver = {
+ .probe = snd_bcm2835_alsa_probe,
+ #ifdef CONFIG_PM
+@@ -351,7 +338,6 @@ static struct platform_driver bcm2835_al
+ #endif
+ .driver = {
+ .name = "bcm2835_audio",
+- .of_match_table = snd_bcm2835_of_match_table,
+ },
+ };
+ module_platform_driver(bcm2835_alsa_driver);
+@@ -359,3 +345,4 @@ module_platform_driver(bcm2835_alsa_driv
+ MODULE_AUTHOR("Dom Cobley");
+ MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:bcm2835_audio");
+++ /dev/null
-From 798edea528f75fd95c0edc6967efce509969e8e9 Mon Sep 17 00:00:00 2001
-From: Mike Brady <mikebrady@eircom.net>
-Date: Mon, 22 Oct 2018 20:17:08 +0100
-Subject: [PATCH 476/703] staging: bcm2835-audio: interpolate audio delay
-
-commit a105a3a72824e0ac685a0711a67e4dbe29de62d0 upstream.
-
-When the BCM2835 audio output is used, userspace sees a jitter up to 10ms
-in the audio position, aka "delay" -- the number of frames that must
-be output before a new frame would be played.
-Make this a bit nicer for userspace by interpolating the position
-using the CPU clock.
-The overhead is small -- an extra ktime_get() every time a GPU message
-is sent -- and another call and a few calculations whenever the delay
-is sought from userland.
-At 48,000 frames per second, i.e. approximately 20 microseconds per
-frame, it would take a clock inaccuracy of
-20 microseconds in 10 milliseconds -- 2,000 parts per million --
-to result in an inaccurate estimate, whereas
-crystal- or resonator-based clocks typically have an
-inaccuracy of 10s to 100s of parts per million.
-
-Signed-off-by: Mike Brady <mikebrady@eircom.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 20 +++++++++++++++++++
- .../vc04_services/bcm2835-audio/bcm2835.h | 1 +
- 2 files changed, 21 insertions(+)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -74,6 +74,7 @@ void bcm2835_playback_fifo(struct bcm283
- atomic_set(&alsa_stream->pos, pos);
-
- alsa_stream->period_offset += bytes;
-+ alsa_stream->interpolate_start = ktime_get();
- if (alsa_stream->period_offset >= alsa_stream->period_size) {
- alsa_stream->period_offset %= alsa_stream->period_size;
- snd_pcm_period_elapsed(substream);
-@@ -237,6 +238,7 @@ static int snd_bcm2835_pcm_prepare(struc
- atomic_set(&alsa_stream->pos, 0);
- alsa_stream->period_offset = 0;
- alsa_stream->draining = false;
-+ alsa_stream->interpolate_start = ktime_get();
-
- return 0;
- }
-@@ -286,6 +288,24 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
- {
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
-+ ktime_t now = ktime_get();
-+
-+ /* Give userspace better delay reporting by interpolating between GPU
-+ * notifications, assuming audio speed is close enough to the clock
-+ * used for ktime
-+ */
-+
-+ if ((ktime_to_ns(alsa_stream->interpolate_start)) &&
-+ (ktime_compare(alsa_stream->interpolate_start, now) < 0)) {
-+ u64 interval =
-+ (ktime_to_ns(ktime_sub(now,
-+ alsa_stream->interpolate_start)));
-+ u64 frames_output_in_interval =
-+ div_u64((interval * runtime->rate), 1000000000);
-+ snd_pcm_sframes_t frames_output_in_interval_sized =
-+ -frames_output_in_interval;
-+ runtime->delay = frames_output_in_interval_sized;
-+ }
-
- return snd_pcm_indirect_playback_pointer(substream,
- &alsa_stream->pcm_indirect,
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
-@@ -78,6 +78,7 @@ struct bcm2835_alsa_stream {
- unsigned int period_offset;
- unsigned int buffer_size;
- unsigned int period_size;
-+ ktime_t interpolate_start;
-
- struct bcm2835_audio_instance *instance;
- int idx;
+++ /dev/null
-From 54b8fc1b2213a73f56a5ca9e098f420014f3c073 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Thu, 6 Dec 2018 19:28:56 +0100
-Subject: [PATCH 477/703] staging: bcm2835-audio: Enable compile test
-
-commit 458d4866a34d0c129ffc3bd56345b2166ba46d77 upstream.
-
-Enable the compilation test for bcm2835-audio to gain more build coverage.
-
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/Kconfig
-+++ b/drivers/staging/vc04_services/bcm2835-audio/Kconfig
-@@ -1,6 +1,6 @@
- config SND_BCM2835
- tristate "BCM2835 Audio"
-- depends on ARCH_BCM2835 && SND
-+ depends on (ARCH_BCM2835 || COMPILE_TEST) && SND
- select SND_PCM
- select BCM2835_VCHIQ
- help
--- /dev/null
+From abba794012b78bca2bb90277ef088edf8f3b84ff Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Mon, 17 Dec 2018 10:08:54 +0300
+Subject: [PATCH 477/725] staging: bcm2835-audio: double free in init error
+ path
+
+commit 136ff5e49271c4c8fceeca5491c48e66b961564b upstream.
+
+We free instance here and in the caller. It should be only the caller
+which handles it.
+
+Fixes: d7ca3a71545b ("staging: bcm2835-audio: Operate non-atomic PCM ops")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+@@ -145,7 +145,6 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
+ dev_err(instance->dev,
+ "failed to open VCHI service connection (status=%d)\n",
+ status);
+- kfree(instance);
+ return -EPERM;
+ }
+
--- /dev/null
+From 89102cfe2b789118442d9a0e9a0e42fcf29f8f58 Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Wed, 1 May 2019 15:00:05 +0100
+Subject: [PATCH 478/725] dts: Increase default coherent pool size
+
+dwc_otg allocates DMA-coherent buffers in atomic context for misaligned
+transfer buffers. The pool that these allocations come from is set up
+at boot-time but can be overridden by a commandline parameter -
+increase this for now to prevent failures seen on 4.19 with multiple
+USB Ethernet devices.
+
+see: https://github.com/raspberrypi/linux/issues/2924
+---
+ arch/arm/boot/dts/bcm270x.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -3,7 +3,7 @@
+
+ / {
+ chosen {
+- bootargs = "";
++ bootargs = "coherent_pool=1M";
+ /delete-property/ stdout-path;
+ };
+
+++ /dev/null
-From 8981dcb58013f5e48b8657377018cb09896bab98 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Thu, 6 Dec 2018 19:28:57 +0100
-Subject: [PATCH 478/703] staging: bcm2835-audio: use module_platform_driver()
- macro
-
-commit 1e55d56344b0777d6cee9b9e4a813d53728ee798 upstream.
-
-There is not much value behind this boilerplate, so use
-module_platform_driver() instead.
-
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835.c | 20 +------------------
- 1 file changed, 1 insertion(+), 19 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -354,25 +354,7 @@ static struct platform_driver bcm2835_al
- .of_match_table = snd_bcm2835_of_match_table,
- },
- };
--
--static int bcm2835_alsa_device_init(void)
--{
-- int retval;
--
-- retval = platform_driver_register(&bcm2835_alsa_driver);
-- if (retval)
-- pr_err("Error registering bcm2835_audio driver %d .\n", retval);
--
-- return retval;
--}
--
--static void bcm2835_alsa_device_exit(void)
--{
-- platform_driver_unregister(&bcm2835_alsa_driver);
--}
--
--late_initcall(bcm2835_alsa_device_init);
--module_exit(bcm2835_alsa_device_exit);
-+module_platform_driver(bcm2835_alsa_driver);
-
- MODULE_AUTHOR("Dom Cobley");
- MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
--- /dev/null
+From d9e9bfb28a22d9f1ed95e2dbe71bec9662717724 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Wed, 1 May 2019 14:23:39 +0100
+Subject: [PATCH 479/725] Revert "staging: bcm2835-audio: Drop DT dependency"
+
+This reverts commit 60a2e557a4f81480216066f22b84c3dda31b3470.
+---
+ .../vc04_services/bcm2835-audio/bcm2835.c | 31 +++++++++++++------
+ 1 file changed, 22 insertions(+), 9 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -6,13 +6,13 @@
+ #include <linux/init.h>
+ #include <linux/slab.h>
+ #include <linux/module.h>
++#include <linux/of.h>
+
+ #include "bcm2835.h"
+
+ static bool enable_hdmi;
+ static bool enable_headphones;
+ static bool enable_compat_alsa = true;
+-static int num_channels = MAX_SUBSTREAMS;
+
+ module_param(enable_hdmi, bool, 0444);
+ MODULE_PARM_DESC(enable_hdmi, "Enables HDMI virtual audio device");
+@@ -21,8 +21,6 @@ MODULE_PARM_DESC(enable_headphones, "Ena
+ module_param(enable_compat_alsa, bool, 0444);
+ MODULE_PARM_DESC(enable_compat_alsa,
+ "Enables ALSA compatibility virtual audio device");
+-module_param(num_channels, int, 0644);
+-MODULE_PARM_DESC(num_channels, "Number of audio channels (default: 8)");
+
+ static void bcm2835_devm_free_vchi_ctx(struct device *dev, void *res)
+ {
+@@ -296,19 +294,28 @@ static int snd_add_child_devices(struct
+ static int snd_bcm2835_alsa_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
++ u32 numchans;
+ int err;
+
+- if (num_channels <= 0 || num_channels > MAX_SUBSTREAMS) {
+- num_channels = MAX_SUBSTREAMS;
+- dev_warn(dev, "Illegal num_channels value, will use %u\n",
+- num_channels);
++ 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 = bcm2835_devm_add_vchi_ctx(dev);
+ if (err)
+ return err;
+
+- err = snd_add_child_devices(dev, num_channels);
++ err = snd_add_child_devices(dev, numchans);
+ if (err)
+ return err;
+
+@@ -330,6 +337,12 @@ static int snd_bcm2835_alsa_resume(struc
+
+ #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_alsa_driver = {
+ .probe = snd_bcm2835_alsa_probe,
+ #ifdef CONFIG_PM
+@@ -338,6 +351,7 @@ static struct platform_driver bcm2835_al
+ #endif
+ .driver = {
+ .name = "bcm2835_audio",
++ .of_match_table = snd_bcm2835_of_match_table,
+ },
+ };
+ module_platform_driver(bcm2835_alsa_driver);
+@@ -345,4 +359,3 @@ module_platform_driver(bcm2835_alsa_driv
+ MODULE_AUTHOR("Dom Cobley");
+ MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform:bcm2835_audio");
+++ /dev/null
-From 2fa5b1611732fd522cbceaded4dad36e81b3d990 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Thu, 6 Dec 2018 19:28:58 +0100
-Subject: [PATCH 479/703] staging: bcm2835-audio: Drop DT dependency
-
-commit 438fc48260a0afc4cee733e5bc20234ff2bbef56 upstream.
-
-Just like the bcm2835-video make this a platform driver which is probed
-by vchiq. In order to change the number of channels use a module
-parameter instead, but use the maximum as default.
-
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../vc04_services/bcm2835-audio/bcm2835.c | 31 ++++++-------------
- 1 file changed, 9 insertions(+), 22 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -6,13 +6,13 @@
- #include <linux/init.h>
- #include <linux/slab.h>
- #include <linux/module.h>
--#include <linux/of.h>
-
- #include "bcm2835.h"
-
- static bool enable_hdmi;
- static bool enable_headphones;
- static bool enable_compat_alsa = true;
-+static int num_channels = MAX_SUBSTREAMS;
-
- module_param(enable_hdmi, bool, 0444);
- MODULE_PARM_DESC(enable_hdmi, "Enables HDMI virtual audio device");
-@@ -21,6 +21,8 @@ MODULE_PARM_DESC(enable_headphones, "Ena
- module_param(enable_compat_alsa, bool, 0444);
- MODULE_PARM_DESC(enable_compat_alsa,
- "Enables ALSA compatibility virtual audio device");
-+module_param(num_channels, int, 0644);
-+MODULE_PARM_DESC(num_channels, "Number of audio channels (default: 8)");
-
- static void bcm2835_devm_free_vchi_ctx(struct device *dev, void *res)
- {
-@@ -294,28 +296,19 @@ static int snd_add_child_devices(struct
- static int snd_bcm2835_alsa_probe(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
-- u32 numchans;
- int err;
-
-- 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);
-+ if (num_channels <= 0 || num_channels > MAX_SUBSTREAMS) {
-+ num_channels = MAX_SUBSTREAMS;
-+ dev_warn(dev, "Illegal num_channels value, will use %u\n",
-+ num_channels);
- }
-
- err = bcm2835_devm_add_vchi_ctx(dev);
- if (err)
- return err;
-
-- err = snd_add_child_devices(dev, numchans);
-+ err = snd_add_child_devices(dev, num_channels);
- if (err)
- return err;
-
-@@ -337,12 +330,6 @@ static int snd_bcm2835_alsa_resume(struc
-
- #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_alsa_driver = {
- .probe = snd_bcm2835_alsa_probe,
- #ifdef CONFIG_PM
-@@ -351,7 +338,6 @@ static struct platform_driver bcm2835_al
- #endif
- .driver = {
- .name = "bcm2835_audio",
-- .of_match_table = snd_bcm2835_of_match_table,
- },
- };
- module_platform_driver(bcm2835_alsa_driver);
-@@ -359,3 +345,4 @@ module_platform_driver(bcm2835_alsa_driv
- MODULE_AUTHOR("Dom Cobley");
- MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:bcm2835_audio");
--- /dev/null
+From 964ee89545061f55bee90bae39b852db74607468 Mon Sep 17 00:00:00 2001
+From: Russell Joyce <russell.joyce@york.ac.uk>
+Date: Wed, 1 May 2019 16:43:27 +0100
+Subject: [PATCH 480/725] configs: Enable netdev LED trigger
+
+Signed-off-by: Russell Joyce <russell.joyce@york.ac.uk>
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ 3 files changed, 3 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -1143,6 +1143,7 @@ CONFIG_LEDS_TRIGGER_TRANSIENT=m
+ CONFIG_LEDS_TRIGGER_CAMERA=m
+ CONFIG_LEDS_TRIGGER_INPUT=y
+ CONFIG_LEDS_TRIGGER_PANIC=y
++CONFIG_LEDS_TRIGGER_NETDEV=m
+ CONFIG_RTC_CLASS=y
+ # CONFIG_RTC_HCTOSYS is not set
+ CONFIG_RTC_DRV_ABX80X=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -1136,6 +1136,7 @@ CONFIG_LEDS_TRIGGER_TRANSIENT=m
+ CONFIG_LEDS_TRIGGER_CAMERA=m
+ CONFIG_LEDS_TRIGGER_INPUT=y
+ CONFIG_LEDS_TRIGGER_PANIC=y
++CONFIG_LEDS_TRIGGER_NETDEV=m
+ CONFIG_RTC_CLASS=y
+ # CONFIG_RTC_HCTOSYS is not set
+ CONFIG_RTC_DRV_ABX80X=m
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -1003,6 +1003,7 @@ CONFIG_LEDS_TRIGGER_TRANSIENT=m
+ CONFIG_LEDS_TRIGGER_CAMERA=m
+ CONFIG_LEDS_TRIGGER_INPUT=y
+ CONFIG_LEDS_TRIGGER_PANIC=y
++CONFIG_LEDS_TRIGGER_NETDEV=m
+ CONFIG_RTC_CLASS=y
+ # CONFIG_RTC_HCTOSYS is not set
+ CONFIG_RTC_DRV_ABX80X=m
+++ /dev/null
-From 9886534de7551e0a59e90677bd1bab0539102772 Mon Sep 17 00:00:00 2001
-From: Dan Carpenter <dan.carpenter@oracle.com>
-Date: Mon, 17 Dec 2018 10:08:54 +0300
-Subject: [PATCH 480/703] staging: bcm2835-audio: double free in init error
- path
-
-commit 136ff5e49271c4c8fceeca5491c48e66b961564b upstream.
-
-We free instance here and in the caller. It should be only the caller
-which handles it.
-
-Fixes: d7ca3a71545b ("staging: bcm2835-audio: Operate non-atomic PCM ops")
-Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
-Reviewed-by: Takashi Iwai <tiwai@suse.de>
-Cc: stable <stable@vger.kernel.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
-@@ -145,7 +145,6 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_
- dev_err(instance->dev,
- "failed to open VCHI service connection (status=%d)\n",
- status);
-- kfree(instance);
- return -EPERM;
- }
-
+++ /dev/null
-From 451f65d34555dad7837da5f9502968f31284615b Mon Sep 17 00:00:00 2001
-From: P33M <p33m@github.com>
-Date: Wed, 1 May 2019 15:00:05 +0100
-Subject: [PATCH 481/703] dts: Increase default coherent pool size
-
-dwc_otg allocates DMA-coherent buffers in atomic context for misaligned
-transfer buffers. The pool that these allocations come from is set up
-at boot-time but can be overridden by a commandline parameter -
-increase this for now to prevent failures seen on 4.19 with multiple
-USB Ethernet devices.
-
-see: https://github.com/raspberrypi/linux/issues/2924
----
- arch/arm/boot/dts/bcm270x.dtsi | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/bcm270x.dtsi
-+++ b/arch/arm/boot/dts/bcm270x.dtsi
-@@ -3,7 +3,7 @@
-
- / {
- chosen {
-- bootargs = "";
-+ bootargs = "coherent_pool=1M";
- /delete-property/ stdout-path;
- };
-
--- /dev/null
+From 706a1636883d35b9399be0003d9e36d0f46fd6c5 Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Wed, 1 May 2019 17:04:32 +0100
+Subject: [PATCH 481/725] smsc95xx: dynamically fix up TX buffer alignment with
+ padding bytes
+
+dwc_otg requires a 32-bit aligned buffer start address, otherwise
+expensive bounce buffers are used. The LAN951x hardware can skip up to
+3 bytes between the TX header and the start of frame data, which can
+be used to force alignment of the URB passed to dwc_otg.
+
+As found in https://github.com/raspberrypi/linux/issues/2924
+---
+ drivers/net/usb/smsc95xx.c | 12 +++++++-----
+ drivers/net/usb/smsc95xx.h | 2 +-
+ 2 files changed, 8 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/usb/smsc95xx.c
++++ b/drivers/net/usb/smsc95xx.c
+@@ -2082,7 +2082,9 @@ static struct sk_buff *smsc95xx_tx_fixup
+ struct sk_buff *skb, gfp_t flags)
+ {
+ bool csum = skb->ip_summed == CHECKSUM_PARTIAL;
+- int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD;
++ unsigned int align_bytes = -((uintptr_t)skb->data) & 0x3;
++ int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM + align_bytes
++ : SMSC95XX_TX_OVERHEAD + align_bytes;
+ u32 tx_cmd_a, tx_cmd_b;
+
+ /* We do not advertise SG, so skbs should be already linearized */
+@@ -2116,16 +2118,16 @@ static struct sk_buff *smsc95xx_tx_fixup
+ }
+ }
+
+- skb_push(skb, 4);
+- tx_cmd_b = (u32)(skb->len - 4);
++ skb_push(skb, 4 + align_bytes);
++ tx_cmd_b = (u32)(skb->len - 4 - align_bytes);
+ if (csum)
+ tx_cmd_b |= TX_CMD_B_CSUM_ENABLE;
+ cpu_to_le32s(&tx_cmd_b);
+ memcpy(skb->data, &tx_cmd_b, 4);
+
+ skb_push(skb, 4);
+- tx_cmd_a = (u32)(skb->len - 8) | TX_CMD_A_FIRST_SEG_ |
+- TX_CMD_A_LAST_SEG_;
++ tx_cmd_a = (u32)(skb->len - 8 - align_bytes) | TX_CMD_A_FIRST_SEG_ |
++ (align_bytes << 16) | TX_CMD_A_LAST_SEG_;
+ cpu_to_le32s(&tx_cmd_a);
+ memcpy(skb->data, &tx_cmd_a, 4);
+
+--- a/drivers/net/usb/smsc95xx.h
++++ b/drivers/net/usb/smsc95xx.h
+@@ -21,7 +21,7 @@
+ #define _SMSC95XX_H
+
+ /* Tx command words */
+-#define TX_CMD_A_DATA_OFFSET_ (0x001F0000) /* Data Start Offset */
++#define TX_CMD_A_DATA_OFFSET_ (0x00030000) /* Data Start Offset */
+ #define TX_CMD_A_FIRST_SEG_ (0x00002000) /* First Segment */
+ #define TX_CMD_A_LAST_SEG_ (0x00001000) /* Last Segment */
+ #define TX_CMD_A_BUF_SIZE_ (0x000007FF) /* Buffer Size */
+++ /dev/null
-From 5a957250fdb0f0b45bd41569c754a676fa556225 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Wed, 1 May 2019 14:23:39 +0100
-Subject: [PATCH 482/703] Revert "staging: bcm2835-audio: Drop DT dependency"
-
-This reverts commit 60a2e557a4f81480216066f22b84c3dda31b3470.
----
- .../vc04_services/bcm2835-audio/bcm2835.c | 31 +++++++++++++------
- 1 file changed, 22 insertions(+), 9 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
-@@ -6,13 +6,13 @@
- #include <linux/init.h>
- #include <linux/slab.h>
- #include <linux/module.h>
-+#include <linux/of.h>
-
- #include "bcm2835.h"
-
- static bool enable_hdmi;
- static bool enable_headphones;
- static bool enable_compat_alsa = true;
--static int num_channels = MAX_SUBSTREAMS;
-
- module_param(enable_hdmi, bool, 0444);
- MODULE_PARM_DESC(enable_hdmi, "Enables HDMI virtual audio device");
-@@ -21,8 +21,6 @@ MODULE_PARM_DESC(enable_headphones, "Ena
- module_param(enable_compat_alsa, bool, 0444);
- MODULE_PARM_DESC(enable_compat_alsa,
- "Enables ALSA compatibility virtual audio device");
--module_param(num_channels, int, 0644);
--MODULE_PARM_DESC(num_channels, "Number of audio channels (default: 8)");
-
- static void bcm2835_devm_free_vchi_ctx(struct device *dev, void *res)
- {
-@@ -296,19 +294,28 @@ static int snd_add_child_devices(struct
- static int snd_bcm2835_alsa_probe(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
-+ u32 numchans;
- int err;
-
-- if (num_channels <= 0 || num_channels > MAX_SUBSTREAMS) {
-- num_channels = MAX_SUBSTREAMS;
-- dev_warn(dev, "Illegal num_channels value, will use %u\n",
-- num_channels);
-+ 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 = bcm2835_devm_add_vchi_ctx(dev);
- if (err)
- return err;
-
-- err = snd_add_child_devices(dev, num_channels);
-+ err = snd_add_child_devices(dev, numchans);
- if (err)
- return err;
-
-@@ -330,6 +337,12 @@ static int snd_bcm2835_alsa_resume(struc
-
- #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_alsa_driver = {
- .probe = snd_bcm2835_alsa_probe,
- #ifdef CONFIG_PM
-@@ -338,6 +351,7 @@ static struct platform_driver bcm2835_al
- #endif
- .driver = {
- .name = "bcm2835_audio",
-+ .of_match_table = snd_bcm2835_of_match_table,
- },
- };
- module_platform_driver(bcm2835_alsa_driver);
-@@ -345,4 +359,3 @@ module_platform_driver(bcm2835_alsa_driv
- MODULE_AUTHOR("Dom Cobley");
- MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
- MODULE_LICENSE("GPL");
--MODULE_ALIAS("platform:bcm2835_audio");
--- /dev/null
+From d57123651a91cf3896faf299614475225dcc88f0 Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Thu, 2 May 2019 11:53:45 +0100
+Subject: [PATCH 482/725] lan78xx: use default alignment for rx buffers
+
+The lan78xx uses a 12-byte hardware rx header, so there is no need
+to allocate SKBs with NET_IP_ALIGN set. Removes alignment faults
+in both dwc_otg and in ipv6 processing.
+---
+ drivers/net/usb/lan78xx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -3250,7 +3250,7 @@ static int rx_submit(struct lan78xx_net
+ size_t size = dev->rx_urb_size;
+ int ret = 0;
+
+- skb = netdev_alloc_skb_ip_align(dev->net, size);
++ skb = netdev_alloc_skb(dev->net, size);
+ if (!skb) {
+ usb_free_urb(urb);
+ return -ENOMEM;
+++ /dev/null
-From dcf73f16faa51b4ff0fc25106e1b45f861ddd5b8 Mon Sep 17 00:00:00 2001
-From: Russell Joyce <russell.joyce@york.ac.uk>
-Date: Wed, 1 May 2019 16:43:27 +0100
-Subject: [PATCH 483/703] configs: Enable netdev LED trigger
-
-Signed-off-by: Russell Joyce <russell.joyce@york.ac.uk>
----
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- 3 files changed, 3 insertions(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -1143,6 +1143,7 @@ CONFIG_LEDS_TRIGGER_TRANSIENT=m
- CONFIG_LEDS_TRIGGER_CAMERA=m
- CONFIG_LEDS_TRIGGER_INPUT=y
- CONFIG_LEDS_TRIGGER_PANIC=y
-+CONFIG_LEDS_TRIGGER_NETDEV=m
- CONFIG_RTC_CLASS=y
- # CONFIG_RTC_HCTOSYS is not set
- CONFIG_RTC_DRV_ABX80X=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -1136,6 +1136,7 @@ CONFIG_LEDS_TRIGGER_TRANSIENT=m
- CONFIG_LEDS_TRIGGER_CAMERA=m
- CONFIG_LEDS_TRIGGER_INPUT=y
- CONFIG_LEDS_TRIGGER_PANIC=y
-+CONFIG_LEDS_TRIGGER_NETDEV=m
- CONFIG_RTC_CLASS=y
- # CONFIG_RTC_HCTOSYS is not set
- CONFIG_RTC_DRV_ABX80X=m
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -1003,6 +1003,7 @@ CONFIG_LEDS_TRIGGER_TRANSIENT=m
- CONFIG_LEDS_TRIGGER_CAMERA=m
- CONFIG_LEDS_TRIGGER_INPUT=y
- CONFIG_LEDS_TRIGGER_PANIC=y
-+CONFIG_LEDS_TRIGGER_NETDEV=m
- CONFIG_RTC_CLASS=y
- # CONFIG_RTC_HCTOSYS is not set
- CONFIG_RTC_DRV_ABX80X=m
--- /dev/null
+From 42b1168b921a0183da6754f43192f7090145feed Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 2 May 2019 14:30:24 +0100
+Subject: [PATCH 483/725] staging: bcm2835-codec: Correct port width calc for
+ truncation
+
+The calculation converting from V4L2 bytesperline to MMAL
+width had an operator ordering issue that lead to Bayer raw 10
+(and 12 and 14) setting an incorrect stride for the buffer.
+Correct this operation ordering issue.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -605,8 +605,8 @@ static void setup_mmal_port_format(struc
+
+ if (!(q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED)) {
+ /* Raw image format - set width/height */
+- port->es.video.width = q_data->bytesperline /
+- (q_data->fmt->depth >> 3);
++ port->es.video.width = (q_data->bytesperline << 3) /
++ q_data->fmt->depth;
+ port->es.video.height = q_data->height;
+ port->es.video.crop.width = q_data->crop_width;
+ port->es.video.crop.height = q_data->crop_height;
+++ /dev/null
-From e303bfb934b2a5adb549b43bbd51b1a0e33c33b3 Mon Sep 17 00:00:00 2001
-From: P33M <p33m@github.com>
-Date: Wed, 1 May 2019 17:04:32 +0100
-Subject: [PATCH 484/703] smsc95xx: dynamically fix up TX buffer alignment with
- padding bytes
-
-dwc_otg requires a 32-bit aligned buffer start address, otherwise
-expensive bounce buffers are used. The LAN951x hardware can skip up to
-3 bytes between the TX header and the start of frame data, which can
-be used to force alignment of the URB passed to dwc_otg.
-
-As found in https://github.com/raspberrypi/linux/issues/2924
----
- drivers/net/usb/smsc95xx.c | 12 +++++++-----
- drivers/net/usb/smsc95xx.h | 2 +-
- 2 files changed, 8 insertions(+), 6 deletions(-)
-
---- a/drivers/net/usb/smsc95xx.c
-+++ b/drivers/net/usb/smsc95xx.c
-@@ -2082,7 +2082,9 @@ static struct sk_buff *smsc95xx_tx_fixup
- struct sk_buff *skb, gfp_t flags)
- {
- bool csum = skb->ip_summed == CHECKSUM_PARTIAL;
-- int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD;
-+ unsigned int align_bytes = -((uintptr_t)skb->data) & 0x3;
-+ int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM + align_bytes
-+ : SMSC95XX_TX_OVERHEAD + align_bytes;
- u32 tx_cmd_a, tx_cmd_b;
-
- /* We do not advertise SG, so skbs should be already linearized */
-@@ -2116,16 +2118,16 @@ static struct sk_buff *smsc95xx_tx_fixup
- }
- }
-
-- skb_push(skb, 4);
-- tx_cmd_b = (u32)(skb->len - 4);
-+ skb_push(skb, 4 + align_bytes);
-+ tx_cmd_b = (u32)(skb->len - 4 - align_bytes);
- if (csum)
- tx_cmd_b |= TX_CMD_B_CSUM_ENABLE;
- cpu_to_le32s(&tx_cmd_b);
- memcpy(skb->data, &tx_cmd_b, 4);
-
- skb_push(skb, 4);
-- tx_cmd_a = (u32)(skb->len - 8) | TX_CMD_A_FIRST_SEG_ |
-- TX_CMD_A_LAST_SEG_;
-+ tx_cmd_a = (u32)(skb->len - 8 - align_bytes) | TX_CMD_A_FIRST_SEG_ |
-+ (align_bytes << 16) | TX_CMD_A_LAST_SEG_;
- cpu_to_le32s(&tx_cmd_a);
- memcpy(skb->data, &tx_cmd_a, 4);
-
---- a/drivers/net/usb/smsc95xx.h
-+++ b/drivers/net/usb/smsc95xx.h
-@@ -21,7 +21,7 @@
- #define _SMSC95XX_H
-
- /* Tx command words */
--#define TX_CMD_A_DATA_OFFSET_ (0x001F0000) /* Data Start Offset */
-+#define TX_CMD_A_DATA_OFFSET_ (0x00030000) /* Data Start Offset */
- #define TX_CMD_A_FIRST_SEG_ (0x00002000) /* First Segment */
- #define TX_CMD_A_LAST_SEG_ (0x00001000) /* Last Segment */
- #define TX_CMD_A_BUF_SIZE_ (0x000007FF) /* Buffer Size */
--- /dev/null
+From 54f10f595339ee996e0ec0ac755b13a891f7ab92 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 2 May 2019 14:32:21 +0100
+Subject: [PATCH 484/725] staging: bcm2835-codec: Remove height padding for ISP
+ role
+
+The ISP has no need for heights to be a multiple of macroblock
+sizes, therefore doesn't require the align on the height.
+Remove it for the ISP role. (It is required for the codecs).
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -1015,7 +1015,8 @@ static int vidioc_g_fmt_vid_cap(struct f
+ return vidioc_g_fmt(file2ctx(file), f);
+ }
+
+-static int vidioc_try_fmt(struct v4l2_format *f, struct bcm2835_codec_fmt *fmt)
++static int vidioc_try_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
++ struct bcm2835_codec_fmt *fmt)
+ {
+ /*
+ * The V4L2 specification requires the driver to correct the format
+@@ -1034,11 +1035,13 @@ static int vidioc_try_fmt(struct v4l2_fo
+ f->fmt.pix.height = MIN_H;
+
+ /*
+- * Buffer must have a vertical alignment of 16 lines.
++ * For codecs the buffer must have a vertical alignment of 16
++ * lines.
+ * The selection will reflect any cropping rectangle when only
+ * some of the pixels are active.
+ */
+- f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
++ if (ctx->dev->role != ISP)
++ f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
+ }
+ f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
+ fmt);
+@@ -1065,7 +1068,7 @@ static int vidioc_try_fmt_vid_cap(struct
+ fmt = find_format(f, ctx->dev, true);
+ }
+
+- return vidioc_try_fmt(f, fmt);
++ return vidioc_try_fmt(ctx, f, fmt);
+ }
+
+ static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
+@@ -1084,7 +1087,7 @@ static int vidioc_try_fmt_vid_out(struct
+ if (!f->fmt.pix.colorspace)
+ f->fmt.pix.colorspace = ctx->colorspace;
+
+- return vidioc_try_fmt(f, fmt);
++ return vidioc_try_fmt(ctx, f, fmt);
+ }
+
+ static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
+++ /dev/null
-From 877ede0851381694597771e1497ca7fc24cd23a6 Mon Sep 17 00:00:00 2001
-From: P33M <p33m@github.com>
-Date: Thu, 2 May 2019 11:53:45 +0100
-Subject: [PATCH 485/703] lan78xx: use default alignment for rx buffers
-
-The lan78xx uses a 12-byte hardware rx header, so there is no need
-to allocate SKBs with NET_IP_ALIGN set. Removes alignment faults
-in both dwc_otg and in ipv6 processing.
----
- drivers/net/usb/lan78xx.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/usb/lan78xx.c
-+++ b/drivers/net/usb/lan78xx.c
-@@ -3250,7 +3250,7 @@ static int rx_submit(struct lan78xx_net
- size_t size = dev->rx_urb_size;
- int ret = 0;
-
-- skb = netdev_alloc_skb_ip_align(dev->net, size);
-+ skb = netdev_alloc_skb(dev->net, size);
- if (!skb) {
- usb_free_urb(urb);
- return -ENOMEM;
--- /dev/null
+From 7b8bb1cd4c48b917888f80d22f789ad3896da20e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 1 May 2019 13:27:23 +0100
+Subject: [PATCH 485/725] staging: mmal-vchiq: Free the event context for
+ control ports
+
+vchiq_mmal_component_init calls init_event_context for the
+control port, but vchiq_mmal_component_finalise didn't free
+it, causing a memory leak..
+
+Add the free call.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -1982,6 +1982,8 @@ int vchiq_mmal_component_finalise(struct
+ for (idx = 0; idx < component->clocks; idx++)
+ free_event_context(&component->clock[idx]);
+
++ free_event_context(&component->control);
++
+ mutex_unlock(&instance->vchiq_mutex);
+
+ return ret;
--- /dev/null
+From 4c6084642e3682684dc10c6487c9aa4ae4a2651f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 2 May 2019 22:14:34 +0100
+Subject: [PATCH 486/725] BCM270X_DT: Also set coherent_pool=1M for BT Pis
+
+See: https://github.com/raspberrypi/linux/issues/2924
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2708-rpi-0-w.dts | 2 +-
+ arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 2 +-
+ arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
+@@ -8,7 +8,7 @@
+ model = "Raspberry Pi Zero W";
+
+ chosen {
+- bootargs = "8250.nr_uarts=1";
++ bootargs = "coherent_pool=1M 8250.nr_uarts=1";
+ };
+
+ aliases {
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
+@@ -9,7 +9,7 @@
+ model = "Raspberry Pi 3 Model B+";
+
+ chosen {
+- bootargs = "8250.nr_uarts=1";
++ bootargs = "coherent_pool=1M 8250.nr_uarts=1";
+ };
+
+ aliases {
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
+@@ -9,7 +9,7 @@
+ model = "Raspberry Pi 3 Model B";
+
+ chosen {
+- bootargs = "8250.nr_uarts=1";
++ bootargs = "coherent_pool=1M 8250.nr_uarts=1";
+ };
+
+ aliases {
+++ /dev/null
-From f6e11e230a385a290e1a5890241f0ec4907f794c Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 2 May 2019 14:30:24 +0100
-Subject: [PATCH 486/703] staging: bcm2835-codec: Correct port width calc for
- truncation
-
-The calculation converting from V4L2 bytesperline to MMAL
-width had an operator ordering issue that lead to Bayer raw 10
-(and 12 and 14) setting an incorrect stride for the buffer.
-Correct this operation ordering issue.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -605,8 +605,8 @@ static void setup_mmal_port_format(struc
-
- if (!(q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED)) {
- /* Raw image format - set width/height */
-- port->es.video.width = q_data->bytesperline /
-- (q_data->fmt->depth >> 3);
-+ port->es.video.width = (q_data->bytesperline << 3) /
-+ q_data->fmt->depth;
- port->es.video.height = q_data->height;
- port->es.video.crop.width = q_data->crop_width;
- port->es.video.crop.height = q_data->crop_height;
--- /dev/null
+From b8ed46bf8324dc44bf2e623e3ad78498fd7ae447 Mon Sep 17 00:00:00 2001
+From: Russell Joyce <russell.joyce@york.ac.uk>
+Date: Thu, 2 May 2019 15:18:36 +0100
+Subject: [PATCH 487/725] configs: Enable ICS-43432 I2S microphone module
+
+Signed-off-by: Russell Joyce <russell.joyce@york.ac.uk>
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ 3 files changed, 3 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -943,6 +943,7 @@ CONFIG_SND_SOC_ADAU7002=m
+ CONFIG_SND_SOC_AK4554=m
+ CONFIG_SND_SOC_CS4265=m
+ CONFIG_SND_SOC_CS4271_I2C=m
++CONFIG_SND_SOC_ICS43432=m
+ CONFIG_SND_SOC_SPDIF=m
+ CONFIG_SND_SOC_WM8804_I2C=m
+ CONFIG_SND_SIMPLE_CARD=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -936,6 +936,7 @@ CONFIG_SND_SOC_ADAU7002=m
+ CONFIG_SND_SOC_AK4554=m
+ CONFIG_SND_SOC_CS4265=m
+ CONFIG_SND_SOC_CS4271_I2C=m
++CONFIG_SND_SOC_ICS43432=m
+ CONFIG_SND_SOC_SPDIF=m
+ CONFIG_SND_SOC_WM8804_I2C=m
+ CONFIG_SND_SIMPLE_CARD=m
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -822,6 +822,7 @@ CONFIG_SND_SOC_AD193X_I2C=m
+ CONFIG_SND_SOC_ADAU1701=m
+ CONFIG_SND_SOC_AK4554=m
+ CONFIG_SND_SOC_CS4271_I2C=m
++CONFIG_SND_SOC_ICS43432=m
+ CONFIG_SND_SOC_WM8804_I2C=m
+ CONFIG_SND_SIMPLE_CARD=m
+ CONFIG_HIDRAW=y
+++ /dev/null
-From 9b2ae5ee715a6dfc1d82b8ed0602a7221df6b641 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 2 May 2019 14:32:21 +0100
-Subject: [PATCH 487/703] staging: bcm2835-codec: Remove height padding for ISP
- role
-
-The ISP has no need for heights to be a multiple of macroblock
-sizes, therefore doesn't require the align on the height.
-Remove it for the ISP role. (It is required for the codecs).
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c | 13 ++++++++-----
- 1 file changed, 8 insertions(+), 5 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -1015,7 +1015,8 @@ static int vidioc_g_fmt_vid_cap(struct f
- return vidioc_g_fmt(file2ctx(file), f);
- }
-
--static int vidioc_try_fmt(struct v4l2_format *f, struct bcm2835_codec_fmt *fmt)
-+static int vidioc_try_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
-+ struct bcm2835_codec_fmt *fmt)
- {
- /*
- * The V4L2 specification requires the driver to correct the format
-@@ -1034,11 +1035,13 @@ static int vidioc_try_fmt(struct v4l2_fo
- f->fmt.pix.height = MIN_H;
-
- /*
-- * Buffer must have a vertical alignment of 16 lines.
-+ * For codecs the buffer must have a vertical alignment of 16
-+ * lines.
- * The selection will reflect any cropping rectangle when only
- * some of the pixels are active.
- */
-- f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
-+ if (ctx->dev->role != ISP)
-+ f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
- }
- f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
- fmt);
-@@ -1065,7 +1068,7 @@ static int vidioc_try_fmt_vid_cap(struct
- fmt = find_format(f, ctx->dev, true);
- }
-
-- return vidioc_try_fmt(f, fmt);
-+ return vidioc_try_fmt(ctx, f, fmt);
- }
-
- static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
-@@ -1084,7 +1087,7 @@ static int vidioc_try_fmt_vid_out(struct
- if (!f->fmt.pix.colorspace)
- f->fmt.pix.colorspace = ctx->colorspace;
-
-- return vidioc_try_fmt(f, fmt);
-+ return vidioc_try_fmt(ctx, f, fmt);
- }
-
- static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
--- /dev/null
+From 209b4058e447c11ce8db6b13123696db0cdd9c63 Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Sun, 5 May 2019 21:07:12 +0100
+Subject: [PATCH 488/725] arm: dts: overlays: rpi-sense: add upstream humidity
+ compatible
+
+The upstream humidiity driver uses "st,hts221" for the compatible
+string so add that in as well so it will work with an unmodified
+upstream kernel driver. We leave the downstream as the priority.
+
+Signed-off-by: Peter Robinson <pbrobinson@gmail.com>
+---
+ arch/arm/boot/dts/overlays/rpi-sense-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
+@@ -38,7 +38,7 @@
+ };
+
+ hts221-humid@5f {
+- compatible = "st,hts221-humid";
++ compatible = "st,hts221-humid", "st,hts221";
+ reg = <0x5f>;
+ status = "okay";
+ };
+++ /dev/null
-From 26f04aa97ca1c498f13e6c4dfea2e8ea436a9f83 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 1 May 2019 13:27:23 +0100
-Subject: [PATCH 488/703] staging: mmal-vchiq: Free the event context for
- control ports
-
-vchiq_mmal_component_init calls init_event_context for the
-control port, but vchiq_mmal_component_finalise didn't free
-it, causing a memory leak..
-
-Add the free call.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -1982,6 +1982,8 @@ int vchiq_mmal_component_finalise(struct
- for (idx = 0; idx < component->clocks; idx++)
- free_event_context(&component->clock[idx]);
-
-+ free_event_context(&component->control);
-+
- mutex_unlock(&instance->vchiq_mutex);
-
- return ret;
--- /dev/null
+From f538653f1307d7b3b2ebfbdef90dc18f23cc4863 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 2 May 2019 15:50:01 +0100
+Subject: [PATCH 489/725] staging: mmal-vchiq: Fix memory leak in error path
+
+On error, vchiq_mmal_component_init could leave the
+event context allocated for ports.
+Clean them up in the error path.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/vchiq-mmal/mmal-vchiq.c | 27 +++++++++++++------
+ 1 file changed, 19 insertions(+), 8 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -1848,9 +1848,26 @@ static void free_event_context(struct vc
+ {
+ struct mmal_msg_context *ctx = port->event_context;
+
++ if (!ctx)
++ return;
++
+ kfree(ctx->u.bulk.buffer->buffer);
+ kfree(ctx->u.bulk.buffer);
+ release_msg_context(ctx);
++ port->event_context = NULL;
++}
++
++static void release_all_event_contexts(struct vchiq_mmal_component *component)
++{
++ int idx;
++
++ for (idx = 0; idx < component->inputs; idx++)
++ free_event_context(&component->input[idx]);
++ for (idx = 0; idx < component->outputs; idx++)
++ free_event_context(&component->output[idx]);
++ for (idx = 0; idx < component->clocks; idx++)
++ free_event_context(&component->clock[idx]);
++ free_event_context(&component->control);
+ }
+
+ /* Initialise a mmal component and its ports
+@@ -1948,6 +1965,7 @@ int vchiq_mmal_component_init(struct vch
+
+ release_component:
+ destroy_component(instance, component);
++ release_all_event_contexts(component);
+ unlock:
+ if (component)
+ component->in_use = 0;
+@@ -1975,14 +1993,7 @@ int vchiq_mmal_component_finalise(struct
+
+ component->in_use = 0;
+
+- for (idx = 0; idx < component->inputs; idx++)
+- free_event_context(&component->input[idx]);
+- for (idx = 0; idx < component->outputs; idx++)
+- free_event_context(&component->output[idx]);
+- for (idx = 0; idx < component->clocks; idx++)
+- free_event_context(&component->clock[idx]);
+-
+- free_event_context(&component->control);
++ release_all_event_contexts(component);
+
+ mutex_unlock(&instance->vchiq_mutex);
+
+++ /dev/null
-From 0e6d5495da81b0f441a8e59156213907b170b085 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 2 May 2019 22:14:34 +0100
-Subject: [PATCH 490/703] BCM270X_DT: Also set coherent_pool=1M for BT Pis
-
-See: https://github.com/raspberrypi/linux/issues/2924
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2708-rpi-0-w.dts | 2 +-
- arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 2 +-
- arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 2 +-
- 3 files changed, 3 insertions(+), 3 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
-+++ b/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
-@@ -8,7 +8,7 @@
- model = "Raspberry Pi Zero W";
-
- chosen {
-- bootargs = "8250.nr_uarts=1";
-+ bootargs = "coherent_pool=1M 8250.nr_uarts=1";
- };
-
- aliases {
---- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
-@@ -9,7 +9,7 @@
- model = "Raspberry Pi 3 Model B+";
-
- chosen {
-- bootargs = "8250.nr_uarts=1";
-+ bootargs = "coherent_pool=1M 8250.nr_uarts=1";
- };
-
- aliases {
---- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
-@@ -9,7 +9,7 @@
- model = "Raspberry Pi 3 Model B";
-
- chosen {
-- bootargs = "8250.nr_uarts=1";
-+ bootargs = "coherent_pool=1M 8250.nr_uarts=1";
- };
-
- aliases {
--- /dev/null
+From d9725f9881c55fdb8727301e45ce6b200c1d7633 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 3 May 2019 13:27:51 +0100
+Subject: [PATCH 490/725] staging: vchiq-mmal: Fix memory leak of vchiq
+ instance
+
+The vchiq instance was allocated from vchiq_mmal_init via
+vchi_initialise, but was never released with vchi_disconnect.
+
+Retain the handle and release it from vchiq_mmal_finalise.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -176,6 +176,7 @@ struct mmal_msg_context {
+ };
+
+ struct vchiq_mmal_instance {
++ VCHI_INSTANCE_T vchi_instance;
+ VCHI_SERVICE_HANDLE_T handle;
+
+ /* ensure serialised access to service */
+@@ -1981,7 +1982,7 @@ EXPORT_SYMBOL_GPL(vchiq_mmal_component_i
+ int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
+ struct vchiq_mmal_component *component)
+ {
+- int ret, idx;
++ int ret;
+
+ if (mutex_lock_interruptible(&instance->vchiq_mutex))
+ return -EINTR;
+@@ -2094,6 +2095,8 @@ int vchiq_mmal_finalise(struct vchiq_mma
+
+ idr_destroy(&instance->context_map);
+
++ vchi_disconnect(instance->vchi_instance);
++
+ kfree(instance);
+
+ return status;
+@@ -2105,7 +2108,7 @@ int vchiq_mmal_init(struct vchiq_mmal_in
+ int status;
+ struct vchiq_mmal_instance *instance;
+ static VCHI_CONNECTION_T *vchi_connection;
+- static VCHI_INSTANCE_T vchi_instance;
++ VCHI_INSTANCE_T vchi_instance;
+ SERVICE_CREATION_T params = {
+ .version = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
+ .service_id = VC_MMAL_SERVER_NAME,
+@@ -2151,6 +2154,8 @@ int vchiq_mmal_init(struct vchiq_mmal_in
+ if (!instance)
+ return -ENOMEM;
+
++ instance->vchi_instance = vchi_instance;
++
+ mutex_init(&instance->vchiq_mutex);
+
+ instance->bulk_scratch = vmalloc(PAGE_SIZE);
--- /dev/null
+From 0c9e8983c1ab986a833e8b5fbe180f06957529ad Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 13 May 2019 17:34:29 +0100
+Subject: [PATCH 491/725] Revert "video: bcm2708_fb: Try allocating on the ARM
+ and passing to VPU"
+
+This reverts commit ca36c709fce57e8023d2b8b354376bf161601a49.
+
+The driver tries a cma_alloc to avoid using gpu_mem, but should
+that fail the core code is logging an error with no easy way to
+test whether it will succeed or fail first.
+
+Revert until we either totally give up on gpu_mem and increase
+CMA always, or find a way to try an allocation.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/video/fbdev/bcm2708_fb.c | 102 +++------------------
+ include/soc/bcm2835/raspberrypi-firmware.h | 1 -
+ 2 files changed, 12 insertions(+), 91 deletions(-)
+
+--- a/drivers/video/fbdev/bcm2708_fb.c
++++ b/drivers/video/fbdev/bcm2708_fb.c
+@@ -98,11 +98,6 @@ struct bcm2708_fb {
+ struct bcm2708_fb_stats stats;
+ unsigned long fb_bus_address;
+ struct { u32 base, length; } gpu;
+-
+- bool disable_arm_alloc;
+- unsigned int image_size;
+- dma_addr_t dma_addr;
+- void *cpuaddr;
+ };
+
+ #define to_bcm2708(info) container_of(info, struct bcm2708_fb, fb)
+@@ -288,88 +283,23 @@ static int bcm2708_fb_set_par(struct fb_
+ .xoffset = info->var.xoffset,
+ .yoffset = info->var.yoffset,
+ .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
+- /* base and screen_size will be initialised later */
+- .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
+- /* pitch will be initialised later */
++ .base = 0,
++ .screen_size = 0,
++ .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
++ .pitch = 0,
+ };
+- int ret, image_size;
+-
++ int ret;
+
+ print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
+ info->var.xres, info->var.yres, info->var.xres_virtual,
+ info->var.yres_virtual, (int)info->screen_size,
+ info->var.bits_per_pixel);
+
+- /* Try allocating our own buffer. We can specify all the parameters */
+- image_size = ((info->var.xres * info->var.yres) *
+- info->var.bits_per_pixel) >> 3;
+-
+- if (!fb->disable_arm_alloc &&
+- (image_size != fb->image_size || !fb->dma_addr)) {
+- if (fb->dma_addr) {
+- dma_free_coherent(info->device, fb->image_size,
+- fb->cpuaddr, fb->dma_addr);
+- fb->image_size = 0;
+- fb->cpuaddr = NULL;
+- fb->dma_addr = 0;
+- }
+-
+- fb->cpuaddr = dma_alloc_coherent(info->device, image_size,
+- &fb->dma_addr, GFP_KERNEL);
+-
+- if (!fb->cpuaddr) {
+- fb->dma_addr = 0;
+- fb->disable_arm_alloc = true;
+- } else {
+- fb->image_size = image_size;
+- }
+- }
+-
+- if (fb->cpuaddr) {
+- fbinfo.base = fb->dma_addr;
+- fbinfo.screen_size = image_size;
+- fbinfo.pitch = (info->var.xres * info->var.bits_per_pixel) >> 3;
+-
+- ret = rpi_firmware_property_list(fb->fw, &fbinfo,
+- sizeof(fbinfo));
+- if (ret || fbinfo.base != fb->dma_addr) {
+- /* Firmware either failed, or assigned a different base
+- * address (ie it doesn't support being passed an FB
+- * allocation).
+- * Destroy the allocation, and don't try again.
+- */
+- dma_free_coherent(info->device, fb->image_size,
+- fb->cpuaddr, fb->dma_addr);
+- fb->image_size = 0;
+- fb->cpuaddr = NULL;
+- fb->dma_addr = 0;
+- fb->disable_arm_alloc = true;
+- }
+- } else {
+- /* Our allocation failed - drop into the old scheme of
+- * allocation by the VPU.
+- */
+- ret = -ENOMEM;
+- }
+-
++ ret = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo));
+ if (ret) {
+- /* Old scheme:
+- * - FRAMEBUFFER_ALLOCATE passes 0 for base and screen_size.
+- * - GET_PITCH instead of SET_PITCH.
+- */
+- fbinfo.base = 0;
+- fbinfo.screen_size = 0;
+- fbinfo.tag6.tag = RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH;
+- fbinfo.pitch = 0;
+-
+- ret = rpi_firmware_property_list(fb->fw, &fbinfo,
+- sizeof(fbinfo));
+- if (ret) {
+- dev_err(info->device,
+- "Failed to allocate GPU framebuffer (%d)\n",
+- ret);
+- return ret;
+- }
++ dev_err(info->device,
++ "Failed to allocate GPU framebuffer (%d)\n", ret);
++ return ret;
+ }
+
+ if (info->var.bits_per_pixel <= 8)
+@@ -384,17 +314,9 @@ static int bcm2708_fb_set_par(struct fb_
+ fb->fb.fix.smem_start = fbinfo.base;
+ fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual;
+ fb->fb.screen_size = fbinfo.screen_size;
+-
+- if (!fb->dma_addr) {
+- if (fb->fb.screen_base)
+- iounmap(fb->fb.screen_base);
+-
+- fb->fb.screen_base = ioremap_wc(fbinfo.base,
+- fb->fb.screen_size);
+- } else {
+- fb->fb.screen_base = fb->cpuaddr;
+- }
+-
++ if (fb->fb.screen_base)
++ iounmap(fb->fb.screen_base);
++ fb->fb.screen_base = ioremap_wc(fbinfo.base, fb->fb.screen_size);
+ if (!fb->fb.screen_base) {
+ /* the console may currently be locked */
+ console_trylock();
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -128,7 +128,6 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
+- RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH = 0x00048008,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
+++ /dev/null
-From 9618e38d927290bf174936756face014a37a93e6 Mon Sep 17 00:00:00 2001
-From: Russell Joyce <russell.joyce@york.ac.uk>
-Date: Thu, 2 May 2019 15:18:36 +0100
-Subject: [PATCH 491/703] configs: Enable ICS-43432 I2S microphone module
-
-Signed-off-by: Russell Joyce <russell.joyce@york.ac.uk>
----
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- 3 files changed, 3 insertions(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -943,6 +943,7 @@ CONFIG_SND_SOC_ADAU7002=m
- CONFIG_SND_SOC_AK4554=m
- CONFIG_SND_SOC_CS4265=m
- CONFIG_SND_SOC_CS4271_I2C=m
-+CONFIG_SND_SOC_ICS43432=m
- CONFIG_SND_SOC_SPDIF=m
- CONFIG_SND_SOC_WM8804_I2C=m
- CONFIG_SND_SIMPLE_CARD=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -936,6 +936,7 @@ CONFIG_SND_SOC_ADAU7002=m
- CONFIG_SND_SOC_AK4554=m
- CONFIG_SND_SOC_CS4265=m
- CONFIG_SND_SOC_CS4271_I2C=m
-+CONFIG_SND_SOC_ICS43432=m
- CONFIG_SND_SOC_SPDIF=m
- CONFIG_SND_SOC_WM8804_I2C=m
- CONFIG_SND_SIMPLE_CARD=m
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -822,6 +822,7 @@ CONFIG_SND_SOC_AD193X_I2C=m
- CONFIG_SND_SOC_ADAU1701=m
- CONFIG_SND_SOC_AK4554=m
- CONFIG_SND_SOC_CS4271_I2C=m
-+CONFIG_SND_SOC_ICS43432=m
- CONFIG_SND_SOC_WM8804_I2C=m
- CONFIG_SND_SIMPLE_CARD=m
- CONFIG_HIDRAW=y
--- /dev/null
+From f1735eca66ab19d14c3f77c0869d7378897aa13c Mon Sep 17 00:00:00 2001
+From: IQaudIO <gordon@iqaudio.com>
+Date: Mon, 13 May 2019 21:53:05 +0100
+Subject: [PATCH 492/725] Added IQaudIO Pi-Codec board support (#2969)
+
+Add support for the IQaudIO Pi-Codec board.
+
+Signed-off-by: Gordon <gordon@iqaudio.com>
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 6 +
+ .../dts/overlays/iqaudio-codec-overlay.dts | 42 +++
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ sound/soc/bcm/Kconfig | 7 +
+ sound/soc/bcm/Makefile | 2 +
+ sound/soc/bcm/iqaudio-codec.c | 250 ++++++++++++++++++
+ 9 files changed, 311 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts
+ create mode 100644 sound/soc/bcm/iqaudio-codec.c
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -68,6 +68,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ i2c1-bcm2708.dtbo \
+ i2s-gpio28-31.dtbo \
+ ilitek251x.dtbo \
++ iqaudio-codec.dtbo \
+ iqaudio-dac.dtbo \
+ iqaudio-dacplus.dtbo \
+ iqaudio-digi-wm8804-audio.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1160,6 +1160,12 @@ Params: interrupt GPIO use
+ touchscreen (in pixels)
+
+
++Name: iqaudio-codec
++Info: Configures the IQaudio Codec audio card
++Load: dtoverlay=iqaudio-codec
++Params: <None>
++
++
+ Name: iqaudio-dac
+ Info: Configures the IQaudio DAC audio card
+ Load: dtoverlay=iqaudio-dac,<param>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts
+@@ -0,0 +1,42 @@
++// Definitions for IQaudIO CODEC
++/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";
++
++ da2713@1a {
++ #sound-dai-cells = <0>;
++ compatible = "dlg,da7213";
++ reg = <0x1a>;
++ status = "okay";
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&sound>;
++ iqaudio_dac: __overlay__ {
++ compatible = "iqaudio,iqaudio-codec";
++ i2s-controller = <&i2s>;
++ status = "okay";
++ };
++ };
++
++ __overrides__ {
++ };
++};
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -919,6 +919,7 @@ CONFIG_SND_BCM2708_SOC_RPI_DAC=m
+ CONFIG_SND_BCM2708_SOC_RPI_PROTO=m
+ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m
+ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
++CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
+ CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -912,6 +912,7 @@ CONFIG_SND_BCM2708_SOC_RPI_DAC=m
+ CONFIG_SND_BCM2708_SOC_RPI_PROTO=m
+ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m
+ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
++CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
+ CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M=m
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -807,6 +807,7 @@ CONFIG_SND_BCM2708_SOC_RPI_DAC=m
+ CONFIG_SND_BCM2708_SOC_RPI_PROTO=m
+ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m
+ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
++CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
+ CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M=m
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -108,6 +108,13 @@ config SND_BCM2708_SOC_JUSTBOOM_DIGI
+ help
+ Say Y or M if you want to add support for JustBoom Digi.
+
++config SND_BCM2708_SOC_IQAUDIO_CODEC
++ tristate "Support for IQaudIO-CODEC"
++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++ select SND_SOC_DA7213
++ help
++ Say Y or M if you want to add support for IQaudIO-CODEC.
++
+ config SND_BCM2708_SOC_IQAUDIO_DAC
+ tristate "Support for IQaudIO-DAC"
+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -18,6 +18,7 @@ snd-soc-hifiberry-dacplusadc-objs := hif
+ snd-soc-justboom-dac-objs := justboom-dac.o
+ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
+ snd-soc-rpi-proto-objs := rpi-proto.o
++snd-soc-iqaudio-codec-objs := iqaudio-codec.o
+ snd-soc-iqaudio-dac-objs := iqaudio-dac.o
+ snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
+ snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
+@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D
+ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
++obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC) += snd-soc-iqaudio-codec.o
+ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
+ obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.o
+ obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o
+--- /dev/null
++++ b/sound/soc/bcm/iqaudio-codec.c
+@@ -0,0 +1,250 @@
++/*
++ * ASoC Driver for IQaudIO Raspberry Pi Codec board
++ *
++ * Author: Gordon Garrity <gordon@iqaudio.com>
++ * (C) Copyright IQaudio Limited, 2017-2019
++ *
++ * 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 <linux/module.h>
++#include <linux/gpio/consumer.h>
++#include <linux/platform_device.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/jack.h>
++
++#include <linux/acpi.h>
++#include <linux/slab.h>
++#include "../codecs/da7213.h"
++
++static int pll_out = DA7213_PLL_FREQ_OUT_90316800;
++
++static int snd_rpi_iqaudio_pll_control(struct snd_soc_dapm_widget *w,
++ struct snd_kcontrol *k, int event)
++{
++ int ret = 0;
++ struct snd_soc_dapm_context *dapm = w->dapm;
++ struct snd_soc_card *card = dapm->card;
++ struct snd_soc_pcm_runtime *rtd =
++ snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
++ struct snd_soc_dai *codec_dai = rtd->codec_dai;
++
++ if (SND_SOC_DAPM_EVENT_OFF(event)) {
++ ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_MCLK, 0,
++ 0);
++ if (ret)
++ dev_err(card->dev, "Failed to bypass PLL: %d\n", ret);
++ } else if (SND_SOC_DAPM_EVENT_ON(event)) {
++ ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_PLL, 0,
++ pll_out);
++ if (ret)
++ dev_err(card->dev, "Failed to enable PLL: %d\n", ret);
++ }
++
++ return ret;
++}
++
++static int snd_rpi_iqaudio_post_dapm_event(struct snd_soc_dapm_widget *w,
++ struct snd_kcontrol *kcontrol,
++ int event)
++{
++ switch (event) {
++ case SND_SOC_DAPM_POST_PMU:
++ /* Delay for mic bias ramp */
++ msleep(1000);
++ break;
++ default:
++ break;
++ }
++
++ return 0;
++}
++
++static const struct snd_soc_dapm_widget dapm_widgets[] = {
++ SND_SOC_DAPM_HP("HP Jack", NULL),
++ SND_SOC_DAPM_MIC("MIC Jack", NULL),
++ SND_SOC_DAPM_MIC("Onboard MIC", NULL),
++ SND_SOC_DAPM_LINE("AUX Jack", NULL),
++ SND_SOC_DAPM_SUPPLY("PLL Control", SND_SOC_NOPM, 0, 0,
++ snd_rpi_iqaudio_pll_control,
++ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
++ SND_SOC_DAPM_POST("Post Power Up Event", snd_rpi_iqaudio_post_dapm_event),
++};
++
++static const struct snd_soc_dapm_route audio_map[] = {
++ {"HP Jack", NULL, "HPL"},
++ {"HP Jack", NULL, "HPR"},
++ {"HP Jack", NULL, "PLL Control"},
++
++ {"AUX Jack", NULL, "AUXR"},
++ {"AUX Jack", NULL, "AUXL"},
++ {"AUX Jack", NULL, "PLL Control"},
++
++ /* Assume Mic1 is linked to Headset and Mic2 to on-board mic */
++ {"MIC Jack", NULL, "MIC1"},
++ {"MIC Jack", NULL, "PLL Control"},
++ {"Onboard MIC", NULL, "MIC2"},
++ {"Onboard MIC", NULL, "PLL Control"},
++};
++
++/* machine stream operations */
++
++static int snd_rpi_iqaudio_codec_init(struct snd_soc_pcm_runtime *rtd)
++{
++ struct snd_soc_dai *codec_dai = rtd->codec_dai;
++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
++ int ret;
++
++ /* Set bclk ratio to align with codec's BCLK rate */
++ ret = snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
++ if (ret) {
++ dev_err(rtd->dev, "Failed to set CPU BLCK ratio\n");
++ return ret;
++ }
++
++ /* Set MCLK frequency to codec, onboard 11.2896MHz clock */
++ return snd_soc_dai_set_sysclk(codec_dai, DA7213_CLKSRC_MCLK, 11289600,
++ SND_SOC_CLOCK_OUT);
++}
++
++static int snd_rpi_iqaudio_codec_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ unsigned int samplerate = params_rate(params);
++
++ switch (samplerate) {
++ case 8000:
++ case 16000:
++ case 32000:
++ case 48000:
++ case 96000:
++ pll_out = DA7213_PLL_FREQ_OUT_98304000;
++ return 0;
++ case 44100:
++ case 88200:
++ pll_out = DA7213_PLL_FREQ_OUT_90316800;
++ return 0;
++ default:
++ dev_err(rtd->dev,"Unsupported samplerate %d\n", samplerate);
++ return -EINVAL;
++ }
++}
++
++static const struct snd_soc_ops snd_rpi_iqaudio_codec_ops = {
++ .hw_params = snd_rpi_iqaudio_codec_hw_params,
++};
++
++
++static struct snd_soc_dai_link snd_rpi_iqaudio_codec_dai[] = {
++{
++ .cpu_dai_name = "bcm2708-i2s.0",
++ .codec_dai_name = "da7213-hifi",
++ .platform_name = "bmc2708-i2s.0",
++ .codec_name = "da7213.1-001a",
++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBM_CFM,
++ .init = snd_rpi_iqaudio_codec_init,
++ .ops = &snd_rpi_iqaudio_codec_ops,
++ .symmetric_rates = 1,
++ .symmetric_channels = 1,
++ .symmetric_samplebits = 1,
++},
++};
++
++/* audio machine driver */
++static struct snd_soc_card snd_rpi_iqaudio_codec = {
++ .owner = THIS_MODULE,
++ .dai_link = snd_rpi_iqaudio_codec_dai,
++ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_codec_dai),
++ .dapm_widgets = dapm_widgets,
++ .num_dapm_widgets = ARRAY_SIZE(dapm_widgets),
++ .dapm_routes = audio_map,
++ .num_dapm_routes = ARRAY_SIZE(audio_map),
++};
++
++static int snd_rpi_iqaudio_codec_probe(struct platform_device *pdev)
++{
++ int ret = 0;
++
++ snd_rpi_iqaudio_codec.dev = &pdev->dev;
++
++ if (pdev->dev.of_node) {
++ struct device_node *i2s_node;
++ struct snd_soc_card *card = &snd_rpi_iqaudio_codec;
++ struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_codec_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;
++ }
++
++ if (of_property_read_string(pdev->dev.of_node, "card_name",
++ &card->name))
++ card->name = "IQaudIOCODEC";
++
++ if (of_property_read_string(pdev->dev.of_node, "dai_name",
++ &dai->name))
++ dai->name = "IQaudIO CODEC";
++
++ if (of_property_read_string(pdev->dev.of_node,
++ "dai_stream_name", &dai->stream_name))
++ dai->stream_name = "IQaudIO CODEC HiFi v1.1";
++
++ }
++
++ ret = snd_soc_register_card(&snd_rpi_iqaudio_codec);
++ if (ret) {
++ if (ret != -EPROBE_DEFER)
++ dev_err(&pdev->dev,
++ "snd_soc_register_card() failed: %d\n", ret);
++ return ret;
++ }
++
++ return 0;
++}
++
++static int snd_rpi_iqaudio_codec_remove(struct platform_device *pdev)
++{
++ return snd_soc_unregister_card(&snd_rpi_iqaudio_codec);
++}
++
++static const struct of_device_id iqaudio_of_match[] = {
++ { .compatible = "iqaudio,iqaudio-codec", },
++ {},
++};
++
++MODULE_DEVICE_TABLE(of, iqaudio_of_match);
++
++static struct platform_driver snd_rpi_iqaudio_codec_driver = {
++ .driver = {
++ .name = "snd-rpi-iqaudio-codec",
++ .owner = THIS_MODULE,
++ .of_match_table = iqaudio_of_match,
++ },
++ .probe = snd_rpi_iqaudio_codec_probe,
++ .remove = snd_rpi_iqaudio_codec_remove,
++};
++
++
++
++module_platform_driver(snd_rpi_iqaudio_codec_driver);
++
++MODULE_AUTHOR("Gordon Garrity <gordon@iqaudio.com>");
++MODULE_DESCRIPTION("ASoC Driver for IQaudIO CODEC");
++MODULE_LICENSE("GPL v2");
+++ /dev/null
-From cecb1267b1b51025c6e54bb4ba05c84ff6e7e3c7 Mon Sep 17 00:00:00 2001
-From: Peter Robinson <pbrobinson@gmail.com>
-Date: Sun, 5 May 2019 21:07:12 +0100
-Subject: [PATCH 492/703] arm: dts: overlays: rpi-sense: add upstream humidity
- compatible
-
-The upstream humidiity driver uses "st,hts221" for the compatible
-string so add that in as well so it will work with an unmodified
-upstream kernel driver. We leave the downstream as the priority.
-
-Signed-off-by: Peter Robinson <pbrobinson@gmail.com>
----
- arch/arm/boot/dts/overlays/rpi-sense-overlay.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
-@@ -38,7 +38,7 @@
- };
-
- hts221-humid@5f {
-- compatible = "st,hts221-humid";
-+ compatible = "st,hts221-humid", "st,hts221";
- reg = <0x5f>;
- status = "okay";
- };
--- /dev/null
+From ac011573006f07da4a140f05e1ee8be0c441f3dc Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Tue, 14 May 2019 14:55:19 +0100
+Subject: [PATCH 493/725] Revert "smsc95xx: dynamically fix up TX buffer
+ alignment with padding bytes"
+
+As reported in https://github.com/raspberrypi/linux/issues/2964 this
+commit causes a regression corrupting non-option TCP ack packets.
+
+This reverts commit 96b972dc736d943f371a16ccca452a053d83c65b.
+---
+ drivers/net/usb/smsc95xx.c | 12 +++++-------
+ drivers/net/usb/smsc95xx.h | 2 +-
+ 2 files changed, 6 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/usb/smsc95xx.c
++++ b/drivers/net/usb/smsc95xx.c
+@@ -2082,9 +2082,7 @@ static struct sk_buff *smsc95xx_tx_fixup
+ struct sk_buff *skb, gfp_t flags)
+ {
+ bool csum = skb->ip_summed == CHECKSUM_PARTIAL;
+- unsigned int align_bytes = -((uintptr_t)skb->data) & 0x3;
+- int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM + align_bytes
+- : SMSC95XX_TX_OVERHEAD + align_bytes;
++ int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD;
+ u32 tx_cmd_a, tx_cmd_b;
+
+ /* We do not advertise SG, so skbs should be already linearized */
+@@ -2118,16 +2116,16 @@ static struct sk_buff *smsc95xx_tx_fixup
+ }
+ }
+
+- skb_push(skb, 4 + align_bytes);
+- tx_cmd_b = (u32)(skb->len - 4 - align_bytes);
++ skb_push(skb, 4);
++ tx_cmd_b = (u32)(skb->len - 4);
+ if (csum)
+ tx_cmd_b |= TX_CMD_B_CSUM_ENABLE;
+ cpu_to_le32s(&tx_cmd_b);
+ memcpy(skb->data, &tx_cmd_b, 4);
+
+ skb_push(skb, 4);
+- tx_cmd_a = (u32)(skb->len - 8 - align_bytes) | TX_CMD_A_FIRST_SEG_ |
+- (align_bytes << 16) | TX_CMD_A_LAST_SEG_;
++ tx_cmd_a = (u32)(skb->len - 8) | TX_CMD_A_FIRST_SEG_ |
++ TX_CMD_A_LAST_SEG_;
+ cpu_to_le32s(&tx_cmd_a);
+ memcpy(skb->data, &tx_cmd_a, 4);
+
+--- a/drivers/net/usb/smsc95xx.h
++++ b/drivers/net/usb/smsc95xx.h
+@@ -21,7 +21,7 @@
+ #define _SMSC95XX_H
+
+ /* Tx command words */
+-#define TX_CMD_A_DATA_OFFSET_ (0x00030000) /* Data Start Offset */
++#define TX_CMD_A_DATA_OFFSET_ (0x001F0000) /* Data Start Offset */
+ #define TX_CMD_A_FIRST_SEG_ (0x00002000) /* First Segment */
+ #define TX_CMD_A_LAST_SEG_ (0x00001000) /* Last Segment */
+ #define TX_CMD_A_BUF_SIZE_ (0x000007FF) /* Buffer Size */
+++ /dev/null
-From af1d0b04a35776cf36049b1549fcb33260a4e145 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 2 May 2019 15:50:01 +0100
-Subject: [PATCH 493/703] staging: mmal-vchiq: Fix memory leak in error path
-
-On error, vchiq_mmal_component_init could leave the
-event context allocated for ports.
-Clean them up in the error path.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/vchiq-mmal/mmal-vchiq.c | 27 +++++++++++++------
- 1 file changed, 19 insertions(+), 8 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -1848,9 +1848,26 @@ static void free_event_context(struct vc
- {
- struct mmal_msg_context *ctx = port->event_context;
-
-+ if (!ctx)
-+ return;
-+
- kfree(ctx->u.bulk.buffer->buffer);
- kfree(ctx->u.bulk.buffer);
- release_msg_context(ctx);
-+ port->event_context = NULL;
-+}
-+
-+static void release_all_event_contexts(struct vchiq_mmal_component *component)
-+{
-+ int idx;
-+
-+ for (idx = 0; idx < component->inputs; idx++)
-+ free_event_context(&component->input[idx]);
-+ for (idx = 0; idx < component->outputs; idx++)
-+ free_event_context(&component->output[idx]);
-+ for (idx = 0; idx < component->clocks; idx++)
-+ free_event_context(&component->clock[idx]);
-+ free_event_context(&component->control);
- }
-
- /* Initialise a mmal component and its ports
-@@ -1948,6 +1965,7 @@ int vchiq_mmal_component_init(struct vch
-
- release_component:
- destroy_component(instance, component);
-+ release_all_event_contexts(component);
- unlock:
- if (component)
- component->in_use = 0;
-@@ -1975,14 +1993,7 @@ int vchiq_mmal_component_finalise(struct
-
- component->in_use = 0;
-
-- for (idx = 0; idx < component->inputs; idx++)
-- free_event_context(&component->input[idx]);
-- for (idx = 0; idx < component->outputs; idx++)
-- free_event_context(&component->output[idx]);
-- for (idx = 0; idx < component->clocks; idx++)
-- free_event_context(&component->clock[idx]);
--
-- free_event_context(&component->control);
-+ release_all_event_contexts(component);
-
- mutex_unlock(&instance->vchiq_mutex);
-
--- /dev/null
+From 4398e1d8787c792a4451beb890d00fba313b6fa7 Mon Sep 17 00:00:00 2001
+From: Henrique Gontijo <hgontijo@guidewire.com>
+Date: Sun, 12 May 2019 17:11:02 -0700
+Subject: [PATCH 494/725] configs: Enable PIDs cgroup
+
+My use case to is to allow Kubernetes master to run on Raspberry Pi 3.
+Kubernetes introduced [Pid limiting](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/20190129-pid-limiting.md),
+on v.1.14.0 which includes [Pod Pids Limit](https://github.com/kubernetes/kubernetes/commit/bce9d5f2043bd86964c9fec80d466e47776071bc)
+and [Node Pids Limit](https://github.com/kubernetes/kubernetes/commit/2597a1d97ef4d8f54b1ca661453e32794b756909#diff-fa76bb6ae2d9b4bb3d023737fe5e6029R333)
+that requires pids cgroup.
+
+See: https://github.com/raspberrypi/linux/pull/2968
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -20,6 +20,7 @@ CONFIG_CGROUP_FREEZER=y
+ CONFIG_CPUSETS=y
+ CONFIG_CGROUP_DEVICE=y
+ CONFIG_CGROUP_CPUACCT=y
++CONFIG_CGROUP_PIDS=y
+ CONFIG_NAMESPACES=y
+ CONFIG_USER_NS=y
+ CONFIG_SCHED_AUTOGROUP=y
+++ /dev/null
-From 123507714c5b2fd44d78f2eac3dc8ade39bb3018 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 3 May 2019 13:27:51 +0100
-Subject: [PATCH 494/703] staging: vchiq-mmal: Fix memory leak of vchiq
- instance
-
-The vchiq instance was allocated from vchiq_mmal_init via
-vchi_initialise, but was never released with vchi_disconnect.
-
-Retain the handle and release it from vchiq_mmal_finalise.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
-@@ -176,6 +176,7 @@ struct mmal_msg_context {
- };
-
- struct vchiq_mmal_instance {
-+ VCHI_INSTANCE_T vchi_instance;
- VCHI_SERVICE_HANDLE_T handle;
-
- /* ensure serialised access to service */
-@@ -1981,7 +1982,7 @@ EXPORT_SYMBOL_GPL(vchiq_mmal_component_i
- int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
- struct vchiq_mmal_component *component)
- {
-- int ret, idx;
-+ int ret;
-
- if (mutex_lock_interruptible(&instance->vchiq_mutex))
- return -EINTR;
-@@ -2094,6 +2095,8 @@ int vchiq_mmal_finalise(struct vchiq_mma
-
- idr_destroy(&instance->context_map);
-
-+ vchi_disconnect(instance->vchi_instance);
-+
- kfree(instance);
-
- return status;
-@@ -2105,7 +2108,7 @@ int vchiq_mmal_init(struct vchiq_mmal_in
- int status;
- struct vchiq_mmal_instance *instance;
- static VCHI_CONNECTION_T *vchi_connection;
-- static VCHI_INSTANCE_T vchi_instance;
-+ VCHI_INSTANCE_T vchi_instance;
- SERVICE_CREATION_T params = {
- .version = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
- .service_id = VC_MMAL_SERVER_NAME,
-@@ -2151,6 +2154,8 @@ int vchiq_mmal_init(struct vchiq_mmal_in
- if (!instance)
- return -ENOMEM;
-
-+ instance->vchi_instance = vchi_instance;
-+
- mutex_init(&instance->vchiq_mutex);
-
- instance->bulk_scratch = vmalloc(PAGE_SIZE);
+++ /dev/null
-From dfe9e42ef9bce3edba84cab22269995f8edd02a5 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 13 May 2019 17:34:29 +0100
-Subject: [PATCH 495/703] Revert "video: bcm2708_fb: Try allocating on the ARM
- and passing to VPU"
-
-This reverts commit ca36c709fce57e8023d2b8b354376bf161601a49.
-
-The driver tries a cma_alloc to avoid using gpu_mem, but should
-that fail the core code is logging an error with no easy way to
-test whether it will succeed or fail first.
-
-Revert until we either totally give up on gpu_mem and increase
-CMA always, or find a way to try an allocation.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/video/fbdev/bcm2708_fb.c | 102 +++------------------
- include/soc/bcm2835/raspberrypi-firmware.h | 1 -
- 2 files changed, 12 insertions(+), 91 deletions(-)
-
---- a/drivers/video/fbdev/bcm2708_fb.c
-+++ b/drivers/video/fbdev/bcm2708_fb.c
-@@ -98,11 +98,6 @@ struct bcm2708_fb {
- struct bcm2708_fb_stats stats;
- unsigned long fb_bus_address;
- struct { u32 base, length; } gpu;
--
-- bool disable_arm_alloc;
-- unsigned int image_size;
-- dma_addr_t dma_addr;
-- void *cpuaddr;
- };
-
- #define to_bcm2708(info) container_of(info, struct bcm2708_fb, fb)
-@@ -288,88 +283,23 @@ static int bcm2708_fb_set_par(struct fb_
- .xoffset = info->var.xoffset,
- .yoffset = info->var.yoffset,
- .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
-- /* base and screen_size will be initialised later */
-- .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
-- /* pitch will be initialised later */
-+ .base = 0,
-+ .screen_size = 0,
-+ .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
-+ .pitch = 0,
- };
-- int ret, image_size;
--
-+ int ret;
-
- print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
- info->var.xres, info->var.yres, info->var.xres_virtual,
- info->var.yres_virtual, (int)info->screen_size,
- info->var.bits_per_pixel);
-
-- /* Try allocating our own buffer. We can specify all the parameters */
-- image_size = ((info->var.xres * info->var.yres) *
-- info->var.bits_per_pixel) >> 3;
--
-- if (!fb->disable_arm_alloc &&
-- (image_size != fb->image_size || !fb->dma_addr)) {
-- if (fb->dma_addr) {
-- dma_free_coherent(info->device, fb->image_size,
-- fb->cpuaddr, fb->dma_addr);
-- fb->image_size = 0;
-- fb->cpuaddr = NULL;
-- fb->dma_addr = 0;
-- }
--
-- fb->cpuaddr = dma_alloc_coherent(info->device, image_size,
-- &fb->dma_addr, GFP_KERNEL);
--
-- if (!fb->cpuaddr) {
-- fb->dma_addr = 0;
-- fb->disable_arm_alloc = true;
-- } else {
-- fb->image_size = image_size;
-- }
-- }
--
-- if (fb->cpuaddr) {
-- fbinfo.base = fb->dma_addr;
-- fbinfo.screen_size = image_size;
-- fbinfo.pitch = (info->var.xres * info->var.bits_per_pixel) >> 3;
--
-- ret = rpi_firmware_property_list(fb->fw, &fbinfo,
-- sizeof(fbinfo));
-- if (ret || fbinfo.base != fb->dma_addr) {
-- /* Firmware either failed, or assigned a different base
-- * address (ie it doesn't support being passed an FB
-- * allocation).
-- * Destroy the allocation, and don't try again.
-- */
-- dma_free_coherent(info->device, fb->image_size,
-- fb->cpuaddr, fb->dma_addr);
-- fb->image_size = 0;
-- fb->cpuaddr = NULL;
-- fb->dma_addr = 0;
-- fb->disable_arm_alloc = true;
-- }
-- } else {
-- /* Our allocation failed - drop into the old scheme of
-- * allocation by the VPU.
-- */
-- ret = -ENOMEM;
-- }
--
-+ ret = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo));
- if (ret) {
-- /* Old scheme:
-- * - FRAMEBUFFER_ALLOCATE passes 0 for base and screen_size.
-- * - GET_PITCH instead of SET_PITCH.
-- */
-- fbinfo.base = 0;
-- fbinfo.screen_size = 0;
-- fbinfo.tag6.tag = RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH;
-- fbinfo.pitch = 0;
--
-- ret = rpi_firmware_property_list(fb->fw, &fbinfo,
-- sizeof(fbinfo));
-- if (ret) {
-- dev_err(info->device,
-- "Failed to allocate GPU framebuffer (%d)\n",
-- ret);
-- return ret;
-- }
-+ dev_err(info->device,
-+ "Failed to allocate GPU framebuffer (%d)\n", ret);
-+ return ret;
- }
-
- if (info->var.bits_per_pixel <= 8)
-@@ -384,17 +314,9 @@ static int bcm2708_fb_set_par(struct fb_
- fb->fb.fix.smem_start = fbinfo.base;
- fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual;
- fb->fb.screen_size = fbinfo.screen_size;
--
-- if (!fb->dma_addr) {
-- if (fb->fb.screen_base)
-- iounmap(fb->fb.screen_base);
--
-- fb->fb.screen_base = ioremap_wc(fbinfo.base,
-- fb->fb.screen_size);
-- } else {
-- fb->fb.screen_base = fb->cpuaddr;
-- }
--
-+ if (fb->fb.screen_base)
-+ iounmap(fb->fb.screen_base);
-+ fb->fb.screen_base = ioremap_wc(fbinfo.base, fb->fb.screen_size);
- if (!fb->fb.screen_base) {
- /* the console may currently be locked */
- console_trylock();
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -128,7 +128,6 @@ enum rpi_firmware_property_tag {
- RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
- RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
- RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
-- RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH = 0x00048008,
- RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
- RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
- RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
--- /dev/null
+From a059cb29f76396d640199026bd94ed654b31e70d Mon Sep 17 00:00:00 2001
+From: Jean-Francois Dagenais <jeff.dagenais@gmail.com>
+Date: Thu, 28 Mar 2019 12:41:11 -0400
+Subject: [PATCH 495/725] w1: ds2408: reset on output_write retry with readback
+
+commit 49695ac46861180baf2b2b92c62da8619b6bf28f upstream.
+
+When we have success in 'Channel Access Write' but reading back latch
+states fails, a write is retried without doing a proper slave reset.
+This leads to protocol errors as the slave treats the next 'Channel
+Access Write' as the continuation of previous command.
+
+This commit is fixing this by making sure if the retry loop re-runs, a
+reset is performed, whatever the failure (CONFIRM_BYTE or the read
+back).
+
+The loop was quite due for a cleanup and this change mandated it. By
+isolating the CONFIG_W1_SLAVE_DS2408_READBACK case into it's own
+function, we vastly reduce the visual and branching(runtime and
+compile-time) noise.
+
+Reported-by: Mariusz Bialonczyk <manio@skyboo.net>
+Tested-by: Mariusz Bialonczyk <manio@skyboo.net>
+Signed-off-by: Jean-Francois Dagenais <jeff.dagenais@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_ds2408.c | 76 ++++++++++++++++++-----------------
+ 1 file changed, 39 insertions(+), 37 deletions(-)
+
+--- a/drivers/w1/slaves/w1_ds2408.c
++++ b/drivers/w1/slaves/w1_ds2408.c
+@@ -138,14 +138,37 @@ static ssize_t status_control_read(struc
+ W1_F29_REG_CONTROL_AND_STATUS, buf);
+ }
+
++#ifdef fCONFIG_W1_SLAVE_DS2408_READBACK
++static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
++{
++ u8 w1_buf[3];
++
++ if (w1_reset_resume_command(sl->master))
++ return false;
++
++ w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
++ w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
++ w1_buf[2] = 0;
++
++ w1_write_block(sl->master, w1_buf, 3);
++
++ return (w1_read_8(sl->master) == expected);
++}
++#else
++static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
++{
++ return true;
++}
++#endif
++
+ static ssize_t output_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *buf,
+ loff_t off, size_t count)
+ {
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+ u8 w1_buf[3];
+- u8 readBack;
+ unsigned int retries = W1_F29_RETRIES;
++ ssize_t bytes_written = -EIO;
+
+ if (count != 1 || off != 0)
+ return -EFAULT;
+@@ -155,54 +178,33 @@ static ssize_t output_write(struct file
+ dev_dbg(&sl->dev, "mutex locked");
+
+ if (w1_reset_select_slave(sl))
+- goto error;
++ goto out;
+
+- while (retries--) {
++ do {
+ w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE;
+ w1_buf[1] = *buf;
+ w1_buf[2] = ~(*buf);
+- w1_write_block(sl->master, w1_buf, 3);
+
+- readBack = w1_read_8(sl->master);
++ w1_write_block(sl->master, w1_buf, 3);
+
+- if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) {
+- if (w1_reset_resume_command(sl->master))
+- goto error;
+- /* try again, the slave is ready for a command */
+- continue;
++ if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE &&
++ optional_read_back_valid(sl, *buf)) {
++ bytes_written = 1;
++ goto out;
+ }
+
+-#ifdef CONFIG_W1_SLAVE_DS2408_READBACK
+- /* here the master could read another byte which
+- would be the PIO reg (the actual pin logic state)
+- since in this driver we don't know which pins are
+- in and outs, there's no value to read the state and
+- compare. with (*buf) so end this command abruptly: */
+ if (w1_reset_resume_command(sl->master))
+- goto error;
++ goto out; /* unrecoverable error */
++ /* try again, the slave is ready for a command */
++ } while (--retries);
+
+- /* go read back the output latches */
+- /* (the direct effect of the write above) */
+- w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
+- w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
+- w1_buf[2] = 0;
+- w1_write_block(sl->master, w1_buf, 3);
+- /* read the result of the READ_PIO_REGS command */
+- if (w1_read_8(sl->master) == *buf)
+-#endif
+- {
+- /* success! */
+- mutex_unlock(&sl->master->bus_mutex);
+- dev_dbg(&sl->dev,
+- "mutex unlocked, retries:%d", retries);
+- return 1;
+- }
+- }
+-error:
++out:
+ mutex_unlock(&sl->master->bus_mutex);
+- dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
+
+- return -EIO;
++ dev_dbg(&sl->dev, "%s, mutex unlocked retries:%d\n",
++ (bytes_written > 0) ? "succeeded" : "error", retries);
++
++ return bytes_written;
+ }
+
+
+++ /dev/null
-From 7208ccb2165feb06eda3f04858d09388cd279c7d Mon Sep 17 00:00:00 2001
-From: IQaudIO <gordon@iqaudio.com>
-Date: Mon, 13 May 2019 21:53:05 +0100
-Subject: [PATCH 496/703] Added IQaudIO Pi-Codec board support (#2969)
-
-Add support for the IQaudIO Pi-Codec board.
-
-Signed-off-by: Gordon <gordon@iqaudio.com>
----
- arch/arm/boot/dts/overlays/Makefile | 1 +
- arch/arm/boot/dts/overlays/README | 6 +
- .../dts/overlays/iqaudio-codec-overlay.dts | 42 +++
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- arch/arm64/configs/bcmrpi3_defconfig | 1 +
- sound/soc/bcm/Kconfig | 7 +
- sound/soc/bcm/Makefile | 2 +
- sound/soc/bcm/iqaudio-codec.c | 250 ++++++++++++++++++
- 9 files changed, 311 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts
- create mode 100644 sound/soc/bcm/iqaudio-codec.c
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -68,6 +68,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- i2c1-bcm2708.dtbo \
- i2s-gpio28-31.dtbo \
- ilitek251x.dtbo \
-+ iqaudio-codec.dtbo \
- iqaudio-dac.dtbo \
- iqaudio-dacplus.dtbo \
- iqaudio-digi-wm8804-audio.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1160,6 +1160,12 @@ Params: interrupt GPIO use
- touchscreen (in pixels)
-
-
-+Name: iqaudio-codec
-+Info: Configures the IQaudio Codec audio card
-+Load: dtoverlay=iqaudio-codec
-+Params: <None>
-+
-+
- Name: iqaudio-dac
- Info: Configures the IQaudio DAC audio card
- Load: dtoverlay=iqaudio-dac,<param>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts
-@@ -0,0 +1,42 @@
-+// Definitions for IQaudIO CODEC
-+/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";
-+
-+ da2713@1a {
-+ #sound-dai-cells = <0>;
-+ compatible = "dlg,da7213";
-+ reg = <0x1a>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ fragment@2 {
-+ target = <&sound>;
-+ iqaudio_dac: __overlay__ {
-+ compatible = "iqaudio,iqaudio-codec";
-+ i2s-controller = <&i2s>;
-+ status = "okay";
-+ };
-+ };
-+
-+ __overrides__ {
-+ };
-+};
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -919,6 +919,7 @@ CONFIG_SND_BCM2708_SOC_RPI_DAC=m
- CONFIG_SND_BCM2708_SOC_RPI_PROTO=m
- CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m
- CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
-+CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
- CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -912,6 +912,7 @@ CONFIG_SND_BCM2708_SOC_RPI_DAC=m
- CONFIG_SND_BCM2708_SOC_RPI_PROTO=m
- CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m
- CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
-+CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
- CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M=m
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -807,6 +807,7 @@ CONFIG_SND_BCM2708_SOC_RPI_DAC=m
- CONFIG_SND_BCM2708_SOC_RPI_PROTO=m
- CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m
- CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
-+CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
- CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M=m
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -108,6 +108,13 @@ config SND_BCM2708_SOC_JUSTBOOM_DIGI
- help
- Say Y or M if you want to add support for JustBoom Digi.
-
-+config SND_BCM2708_SOC_IQAUDIO_CODEC
-+ tristate "Support for IQaudIO-CODEC"
-+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+ select SND_SOC_DA7213
-+ help
-+ Say Y or M if you want to add support for IQaudIO-CODEC.
-+
- config SND_BCM2708_SOC_IQAUDIO_DAC
- tristate "Support for IQaudIO-DAC"
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -18,6 +18,7 @@ snd-soc-hifiberry-dacplusadc-objs := hif
- snd-soc-justboom-dac-objs := justboom-dac.o
- snd-soc-rpi-cirrus-objs := rpi-cirrus.o
- snd-soc-rpi-proto-objs := rpi-proto.o
-+snd-soc-iqaudio-codec-objs := iqaudio-codec.o
- snd-soc-iqaudio-dac-objs := iqaudio-dac.o
- snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
- snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
-@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D
- obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
-+obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC) += snd-soc-iqaudio-codec.o
- obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
- obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.o
- obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o
---- /dev/null
-+++ b/sound/soc/bcm/iqaudio-codec.c
-@@ -0,0 +1,250 @@
-+/*
-+ * ASoC Driver for IQaudIO Raspberry Pi Codec board
-+ *
-+ * Author: Gordon Garrity <gordon@iqaudio.com>
-+ * (C) Copyright IQaudio Limited, 2017-2019
-+ *
-+ * 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 <linux/module.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/platform_device.h>
-+
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/jack.h>
-+
-+#include <linux/acpi.h>
-+#include <linux/slab.h>
-+#include "../codecs/da7213.h"
-+
-+static int pll_out = DA7213_PLL_FREQ_OUT_90316800;
-+
-+static int snd_rpi_iqaudio_pll_control(struct snd_soc_dapm_widget *w,
-+ struct snd_kcontrol *k, int event)
-+{
-+ int ret = 0;
-+ struct snd_soc_dapm_context *dapm = w->dapm;
-+ struct snd_soc_card *card = dapm->card;
-+ struct snd_soc_pcm_runtime *rtd =
-+ snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
-+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
-+
-+ if (SND_SOC_DAPM_EVENT_OFF(event)) {
-+ ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_MCLK, 0,
-+ 0);
-+ if (ret)
-+ dev_err(card->dev, "Failed to bypass PLL: %d\n", ret);
-+ } else if (SND_SOC_DAPM_EVENT_ON(event)) {
-+ ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_PLL, 0,
-+ pll_out);
-+ if (ret)
-+ dev_err(card->dev, "Failed to enable PLL: %d\n", ret);
-+ }
-+
-+ return ret;
-+}
-+
-+static int snd_rpi_iqaudio_post_dapm_event(struct snd_soc_dapm_widget *w,
-+ struct snd_kcontrol *kcontrol,
-+ int event)
-+{
-+ switch (event) {
-+ case SND_SOC_DAPM_POST_PMU:
-+ /* Delay for mic bias ramp */
-+ msleep(1000);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+static const struct snd_soc_dapm_widget dapm_widgets[] = {
-+ SND_SOC_DAPM_HP("HP Jack", NULL),
-+ SND_SOC_DAPM_MIC("MIC Jack", NULL),
-+ SND_SOC_DAPM_MIC("Onboard MIC", NULL),
-+ SND_SOC_DAPM_LINE("AUX Jack", NULL),
-+ SND_SOC_DAPM_SUPPLY("PLL Control", SND_SOC_NOPM, 0, 0,
-+ snd_rpi_iqaudio_pll_control,
-+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-+ SND_SOC_DAPM_POST("Post Power Up Event", snd_rpi_iqaudio_post_dapm_event),
-+};
-+
-+static const struct snd_soc_dapm_route audio_map[] = {
-+ {"HP Jack", NULL, "HPL"},
-+ {"HP Jack", NULL, "HPR"},
-+ {"HP Jack", NULL, "PLL Control"},
-+
-+ {"AUX Jack", NULL, "AUXR"},
-+ {"AUX Jack", NULL, "AUXL"},
-+ {"AUX Jack", NULL, "PLL Control"},
-+
-+ /* Assume Mic1 is linked to Headset and Mic2 to on-board mic */
-+ {"MIC Jack", NULL, "MIC1"},
-+ {"MIC Jack", NULL, "PLL Control"},
-+ {"Onboard MIC", NULL, "MIC2"},
-+ {"Onboard MIC", NULL, "PLL Control"},
-+};
-+
-+/* machine stream operations */
-+
-+static int snd_rpi_iqaudio_codec_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
-+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-+ int ret;
-+
-+ /* Set bclk ratio to align with codec's BCLK rate */
-+ ret = snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
-+ if (ret) {
-+ dev_err(rtd->dev, "Failed to set CPU BLCK ratio\n");
-+ return ret;
-+ }
-+
-+ /* Set MCLK frequency to codec, onboard 11.2896MHz clock */
-+ return snd_soc_dai_set_sysclk(codec_dai, DA7213_CLKSRC_MCLK, 11289600,
-+ SND_SOC_CLOCK_OUT);
-+}
-+
-+static int snd_rpi_iqaudio_codec_hw_params(struct snd_pcm_substream *substream,
-+ struct snd_pcm_hw_params *params)
-+{
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ unsigned int samplerate = params_rate(params);
-+
-+ switch (samplerate) {
-+ case 8000:
-+ case 16000:
-+ case 32000:
-+ case 48000:
-+ case 96000:
-+ pll_out = DA7213_PLL_FREQ_OUT_98304000;
-+ return 0;
-+ case 44100:
-+ case 88200:
-+ pll_out = DA7213_PLL_FREQ_OUT_90316800;
-+ return 0;
-+ default:
-+ dev_err(rtd->dev,"Unsupported samplerate %d\n", samplerate);
-+ return -EINVAL;
-+ }
-+}
-+
-+static const struct snd_soc_ops snd_rpi_iqaudio_codec_ops = {
-+ .hw_params = snd_rpi_iqaudio_codec_hw_params,
-+};
-+
-+
-+static struct snd_soc_dai_link snd_rpi_iqaudio_codec_dai[] = {
-+{
-+ .cpu_dai_name = "bcm2708-i2s.0",
-+ .codec_dai_name = "da7213-hifi",
-+ .platform_name = "bmc2708-i2s.0",
-+ .codec_name = "da7213.1-001a",
-+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-+ SND_SOC_DAIFMT_CBM_CFM,
-+ .init = snd_rpi_iqaudio_codec_init,
-+ .ops = &snd_rpi_iqaudio_codec_ops,
-+ .symmetric_rates = 1,
-+ .symmetric_channels = 1,
-+ .symmetric_samplebits = 1,
-+},
-+};
-+
-+/* audio machine driver */
-+static struct snd_soc_card snd_rpi_iqaudio_codec = {
-+ .owner = THIS_MODULE,
-+ .dai_link = snd_rpi_iqaudio_codec_dai,
-+ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_codec_dai),
-+ .dapm_widgets = dapm_widgets,
-+ .num_dapm_widgets = ARRAY_SIZE(dapm_widgets),
-+ .dapm_routes = audio_map,
-+ .num_dapm_routes = ARRAY_SIZE(audio_map),
-+};
-+
-+static int snd_rpi_iqaudio_codec_probe(struct platform_device *pdev)
-+{
-+ int ret = 0;
-+
-+ snd_rpi_iqaudio_codec.dev = &pdev->dev;
-+
-+ if (pdev->dev.of_node) {
-+ struct device_node *i2s_node;
-+ struct snd_soc_card *card = &snd_rpi_iqaudio_codec;
-+ struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_codec_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;
-+ }
-+
-+ if (of_property_read_string(pdev->dev.of_node, "card_name",
-+ &card->name))
-+ card->name = "IQaudIOCODEC";
-+
-+ if (of_property_read_string(pdev->dev.of_node, "dai_name",
-+ &dai->name))
-+ dai->name = "IQaudIO CODEC";
-+
-+ if (of_property_read_string(pdev->dev.of_node,
-+ "dai_stream_name", &dai->stream_name))
-+ dai->stream_name = "IQaudIO CODEC HiFi v1.1";
-+
-+ }
-+
-+ ret = snd_soc_register_card(&snd_rpi_iqaudio_codec);
-+ if (ret) {
-+ if (ret != -EPROBE_DEFER)
-+ dev_err(&pdev->dev,
-+ "snd_soc_register_card() failed: %d\n", ret);
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static int snd_rpi_iqaudio_codec_remove(struct platform_device *pdev)
-+{
-+ return snd_soc_unregister_card(&snd_rpi_iqaudio_codec);
-+}
-+
-+static const struct of_device_id iqaudio_of_match[] = {
-+ { .compatible = "iqaudio,iqaudio-codec", },
-+ {},
-+};
-+
-+MODULE_DEVICE_TABLE(of, iqaudio_of_match);
-+
-+static struct platform_driver snd_rpi_iqaudio_codec_driver = {
-+ .driver = {
-+ .name = "snd-rpi-iqaudio-codec",
-+ .owner = THIS_MODULE,
-+ .of_match_table = iqaudio_of_match,
-+ },
-+ .probe = snd_rpi_iqaudio_codec_probe,
-+ .remove = snd_rpi_iqaudio_codec_remove,
-+};
-+
-+
-+
-+module_platform_driver(snd_rpi_iqaudio_codec_driver);
-+
-+MODULE_AUTHOR("Gordon Garrity <gordon@iqaudio.com>");
-+MODULE_DESCRIPTION("ASoC Driver for IQaudIO CODEC");
-+MODULE_LICENSE("GPL v2");
--- /dev/null
+From 5afe695ddcc560424d2b98984902a578ae8e416c Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Mon, 4 Mar 2019 12:23:36 +0100
+Subject: [PATCH 496/725] w1: ds2482: cosmetic fixes after 54865314f5a1
+
+commit 5cb27d30fc3a281e830a2099d520b469e2b82008 upstream.
+
+We have a helper function ds2482_calculate_config() which is calculating
+the config value, so just use it instead of passing the same variable
+in all calls to this function.
+
+Also fixes the placement of module parameters to match with:
+50fa2951bd74 (w1: Organize driver source to natural/common order)
+by Andrew F. Davis
+
+Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
+Cc: Andrew Worsley <amworsley@gmail.com>
+Cc: Andrew F. Davis <afd@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/masters/ds2482.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+--- a/drivers/w1/masters/ds2482.c
++++ b/drivers/w1/masters/ds2482.c
+@@ -37,6 +37,11 @@ module_param_named(active_pullup, ds2482
+ MODULE_PARM_DESC(active_pullup, "Active pullup (apply to all buses): " \
+ "0-disable, 1-enable (default)");
+
++/* extra configurations - e.g. 1WS */
++static int extra_config;
++module_param(extra_config, int, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8=1WS");
++
+ /**
+ * The DS2482 registers - there are 3 registers that are addressed by a read
+ * pointer. The read pointer is set by the last command executed.
+@@ -70,8 +75,6 @@ MODULE_PARM_DESC(active_pullup, "Active
+ #define DS2482_REG_CFG_PPM 0x02 /* presence pulse masking */
+ #define DS2482_REG_CFG_APU 0x01 /* active pull-up */
+
+-/* extra configurations - e.g. 1WS */
+-static int extra_config;
+
+ /**
+ * Write and verify codes for the CHANNEL_SELECT command (DS2482-800 only).
+@@ -130,6 +133,8 @@ struct ds2482_data {
+ */
+ static inline u8 ds2482_calculate_config(u8 conf)
+ {
++ conf |= extra_config;
++
+ if (ds2482_active_pullup)
+ conf |= DS2482_REG_CFG_APU;
+
+@@ -405,7 +410,7 @@ static u8 ds2482_w1_reset_bus(void *data
+ /* If the chip did reset since detect, re-config it */
+ if (err & DS2482_REG_STS_RST)
+ ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG,
+- ds2482_calculate_config(extra_config));
++ ds2482_calculate_config(0x00));
+ }
+
+ mutex_unlock(&pdev->access_lock);
+@@ -431,7 +436,8 @@ static u8 ds2482_w1_set_pullup(void *dat
+ ds2482_wait_1wire_idle(pdev);
+ /* note: it seems like both SPU and APU have to be set! */
+ retval = ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG,
+- ds2482_calculate_config(extra_config|DS2482_REG_CFG_SPU|DS2482_REG_CFG_APU));
++ ds2482_calculate_config(DS2482_REG_CFG_SPU |
++ DS2482_REG_CFG_APU));
+ ds2482_wait_1wire_idle(pdev);
+ }
+
+@@ -484,7 +490,7 @@ static int ds2482_probe(struct i2c_clien
+
+ /* Set all config items to 0 (off) */
+ ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG,
+- ds2482_calculate_config(extra_config));
++ ds2482_calculate_config(0x00));
+
+ mutex_init(&data->access_lock);
+
+@@ -559,7 +565,5 @@ module_i2c_driver(ds2482_driver);
+
+ MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+ MODULE_DESCRIPTION("DS2482 driver");
+-module_param(extra_config, int, S_IRUGO | S_IWUSR);
+-MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8=1WS");
+
+ MODULE_LICENSE("GPL");
+++ /dev/null
-From fb13c1342c81bb0c06afdcfe1e8561e8a6e149d7 Mon Sep 17 00:00:00 2001
-From: P33M <p33m@github.com>
-Date: Tue, 14 May 2019 14:55:19 +0100
-Subject: [PATCH 497/703] Revert "smsc95xx: dynamically fix up TX buffer
- alignment with padding bytes"
-
-As reported in https://github.com/raspberrypi/linux/issues/2964 this
-commit causes a regression corrupting non-option TCP ack packets.
-
-This reverts commit 96b972dc736d943f371a16ccca452a053d83c65b.
----
- drivers/net/usb/smsc95xx.c | 12 +++++-------
- drivers/net/usb/smsc95xx.h | 2 +-
- 2 files changed, 6 insertions(+), 8 deletions(-)
-
---- a/drivers/net/usb/smsc95xx.c
-+++ b/drivers/net/usb/smsc95xx.c
-@@ -2082,9 +2082,7 @@ static struct sk_buff *smsc95xx_tx_fixup
- struct sk_buff *skb, gfp_t flags)
- {
- bool csum = skb->ip_summed == CHECKSUM_PARTIAL;
-- unsigned int align_bytes = -((uintptr_t)skb->data) & 0x3;
-- int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM + align_bytes
-- : SMSC95XX_TX_OVERHEAD + align_bytes;
-+ int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD;
- u32 tx_cmd_a, tx_cmd_b;
-
- /* We do not advertise SG, so skbs should be already linearized */
-@@ -2118,16 +2116,16 @@ static struct sk_buff *smsc95xx_tx_fixup
- }
- }
-
-- skb_push(skb, 4 + align_bytes);
-- tx_cmd_b = (u32)(skb->len - 4 - align_bytes);
-+ skb_push(skb, 4);
-+ tx_cmd_b = (u32)(skb->len - 4);
- if (csum)
- tx_cmd_b |= TX_CMD_B_CSUM_ENABLE;
- cpu_to_le32s(&tx_cmd_b);
- memcpy(skb->data, &tx_cmd_b, 4);
-
- skb_push(skb, 4);
-- tx_cmd_a = (u32)(skb->len - 8 - align_bytes) | TX_CMD_A_FIRST_SEG_ |
-- (align_bytes << 16) | TX_CMD_A_LAST_SEG_;
-+ tx_cmd_a = (u32)(skb->len - 8) | TX_CMD_A_FIRST_SEG_ |
-+ TX_CMD_A_LAST_SEG_;
- cpu_to_le32s(&tx_cmd_a);
- memcpy(skb->data, &tx_cmd_a, 4);
-
---- a/drivers/net/usb/smsc95xx.h
-+++ b/drivers/net/usb/smsc95xx.h
-@@ -21,7 +21,7 @@
- #define _SMSC95XX_H
-
- /* Tx command words */
--#define TX_CMD_A_DATA_OFFSET_ (0x00030000) /* Data Start Offset */
-+#define TX_CMD_A_DATA_OFFSET_ (0x001F0000) /* Data Start Offset */
- #define TX_CMD_A_FIRST_SEG_ (0x00002000) /* First Segment */
- #define TX_CMD_A_LAST_SEG_ (0x00001000) /* Last Segment */
- #define TX_CMD_A_BUF_SIZE_ (0x000007FF) /* Buffer Size */
--- /dev/null
+From 5989c694277724691de437691ea314fc8fad93b8 Mon Sep 17 00:00:00 2001
+From: Klaus Schulz <klsschlz@gmail.com>
+Date: Thu, 16 May 2019 13:35:32 +0200
+Subject: [PATCH 497/725] sound: pcm512x-codec: Adding 352.8kHz samplerate
+ support
+
+---
+ sound/soc/codecs/pcm512x.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/soc/codecs/pcm512x.c
++++ b/sound/soc/codecs/pcm512x.c
+@@ -542,7 +542,7 @@ static unsigned long pcm512x_ncp_target(
+
+ static const u32 pcm512x_dai_rates[] = {
+ 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
+- 88200, 96000, 176400, 192000, 384000,
++ 88200, 96000, 176400, 192000, 352800, 384000,
+ };
+
+ static const struct snd_pcm_hw_constraint_list constraints_slave = {
--- /dev/null
+From 0a066a3f2e77c2d4d49a8d1f148b30a10a89de74 Mon Sep 17 00:00:00 2001
+From: GT <dev@3d-lab-av.com>
+Date: Sat, 6 Apr 2019 21:16:39 +0100
+Subject: [PATCH 498/725] ASoC: decommissioning driver for 3Dlab Nano soundcard
+
+---
+ .../overlays/3dlab-nano-player-overlay.dts | 32 --
+ arch/arm/boot/dts/overlays/Makefile | 1 -
+ arch/arm/boot/dts/overlays/README | 6 -
+ arch/arm/configs/bcm2709_defconfig | 1 -
+ arch/arm/configs/bcmrpi_defconfig | 1 -
+ sound/soc/bcm/3dlab-nano-player.c | 370 ------------------
+ sound/soc/bcm/Kconfig | 6 -
+ sound/soc/bcm/Makefile | 6 +-
+ 8 files changed, 2 insertions(+), 421 deletions(-)
+ delete mode 100644 arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
+ delete mode 100644 sound/soc/bcm/3dlab-nano-player.c
+
+--- a/arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
++++ /dev/null
+@@ -1,32 +0,0 @@
+-// Definitions for 3Dlab Nano Player
+-/dts-v1/;
+-/plugin/;
+-
+-/ {
+- compatible = "brcm,bcm2708";
+-
+- fragment@0 {
+- target = <&i2s>;
+- __overlay__ {
+- status = "okay";
+- };
+- };
+-
+- fragment@1 {
+- target = <&i2c>;
+- __overlay__ {
+- #address-cells = <1>;
+- #size-cells = <0>;
+- status = "okay";
+-
+- nano-player@41 {
+- compatible = "3dlab,nano-player";
+- reg = <0x41>;
+- i2s-controller = <&i2s>;
+- status = "okay";
+- };
+- };
+- };
+-};
+-
+-// EOF
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -1,7 +1,6 @@
+ # Overlays for the Raspberry Pi platform
+
+ dtbo-$(CONFIG_ARCH_BCM2835) += \
+- 3dlab-nano-player.dtbo \
+ adau1977-adc.dtbo \
+ adau7002-simple.dtbo \
+ ads1015.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -205,12 +205,6 @@ Params:
+ and the other i2c baudrate parameters.
+
+
+-Name: 3dlab-nano-player
+-Info: Configures the 3Dlab Nano Player
+-Load: dtoverlay=3dlab-nano-player
+-Params: <None>
+-
+-
+ Name: adau1977-adc
+ Info: Overlay for activation of ADAU1977 ADC codec over I2C for control
+ and I2S for data.
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -908,7 +908,6 @@ CONFIG_SND_USB_6FIRE=m
+ CONFIG_SND_USB_HIFACE=m
+ CONFIG_SND_SOC=m
+ CONFIG_SND_BCM2835_SOC_I2S=m
+-CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
+ CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -900,7 +900,6 @@ CONFIG_SND_USB_6FIRE=m
+ CONFIG_SND_USB_HIFACE=m
+ CONFIG_SND_SOC=m
+ CONFIG_SND_BCM2835_SOC_I2S=m
+-CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
+ CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
+--- a/sound/soc/bcm/3dlab-nano-player.c
++++ /dev/null
+@@ -1,370 +0,0 @@
+-/*
+- * 3Dlab Nano Player ALSA SoC Audio driver.
+- *
+- * Copyright (C) 2018 3Dlab.
+- *
+- * Author: GT <dev@3d-lab-av.com>
+- *
+- * 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 <linux/module.h>
+-#include <linux/i2c.h>
+-#include <sound/soc.h>
+-#include <sound/pcm.h>
+-#include <sound/pcm_params.h>
+-#include <sound/control.h>
+-
+-#define NANO_ID 0x00
+-#define NANO_VER 0x01
+-#define NANO_CFG 0x02
+-#define NANO_STATUS 0x03
+-#define NANO_SPI_ADDR 0x04
+-#define NANO_SPI_DATA 0x05
+-
+-#define NANO_ID_VAL 0x3D
+-#define NANO_CFG_OFF 0x00
+-#define NANO_CFG_MULT1 0
+-#define NANO_CFG_MULT2 1
+-#define NANO_CFG_MULT4 2
+-#define NANO_CFG_MULT8 3
+-#define NANO_CFG_MULT16 4
+-#define NANO_CFG_CLK22 0
+-#define NANO_CFG_CLK24 BIT(3)
+-#define NANO_CFG_DSD BIT(4)
+-#define NANO_CFG_ENA BIT(5)
+-#define NANO_CFG_BLINK BIT(6)
+-#define NANO_STATUS_P1 BIT(0)
+-#define NANO_STATUS_P2 BIT(1)
+-#define NANO_STATUS_FLG BIT(2)
+-#define NANO_STATUS_CLK BIT(3)
+-#define NANO_SPI_READ 0
+-#define NANO_SPI_WRITE BIT(5)
+-
+-#define NANO_DAC_CTRL1 0x00
+-#define NANO_DAC_CTRL2 0x01
+-#define NANO_DAC_CTRL3 0x02
+-#define NANO_DAC_LATT 0x03
+-#define NANO_DAC_RATT 0x04
+-
+-#define NANO_CTRL2_VAL 0x22
+-
+-static int nano_player_spi_write(struct regmap *map,
+- unsigned int reg, unsigned int val)
+-{
+- /* indirect register access */
+- regmap_write(map, NANO_SPI_DATA, val);
+- regmap_write(map, NANO_SPI_ADDR, reg | NANO_SPI_WRITE);
+- return 0;
+-}
+-
+-static int nano_player_ctrl_info(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_info *uinfo)
+-{
+- /* describe control element */
+- if (strstr(kcontrol->id.name, "Volume")) {
+- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+- uinfo->count = 1;
+- uinfo->value.integer.min = 0;
+- uinfo->value.integer.max = 100;
+- } else {
+- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+- uinfo->count = 1;
+- uinfo->value.integer.min = 0;
+- uinfo->value.integer.max = 1;
+- }
+-
+- return 0;
+-}
+-
+-static int nano_player_ctrl_put(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- /* program control value to hardware */
+- struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+- struct regmap *regmap = snd_soc_card_get_drvdata(card);
+-
+- if (strstr(kcontrol->id.name, "Volume")) {
+- unsigned int vol = ucontrol->value.integer.value[0];
+- unsigned int att = 255 - (2 * (100 - vol));
+-
+- nano_player_spi_write(regmap, NANO_DAC_LATT, att);
+- nano_player_spi_write(regmap, NANO_DAC_RATT, att);
+- kcontrol->private_value = vol;
+- } else {
+- unsigned int mute = ucontrol->value.integer.value[0];
+- unsigned int reg = NANO_CTRL2_VAL | mute;
+-
+- nano_player_spi_write(regmap, NANO_DAC_CTRL2, reg);
+- kcontrol->private_value = mute;
+- }
+- return 0;
+-}
+-
+-static int nano_player_ctrl_get(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- /* return last programmed value */
+- ucontrol->value.integer.value[0] = kcontrol->private_value;
+- return 0;
+-}
+-
+-#define SOC_NANO_PLAYER_CTRL(xname) \
+-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+- .info = nano_player_ctrl_info, \
+- .put = nano_player_ctrl_put, \
+- .get = nano_player_ctrl_get }
+-
+-static const struct snd_kcontrol_new nano_player_controls[] = {
+- SOC_NANO_PLAYER_CTRL("Master Playback Volume"),
+- SOC_NANO_PLAYER_CTRL("Master Playback Switch"),
+-};
+-
+-static const unsigned int nano_player_rates[] = {
+- 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000,
+- 705600, 768000 /* only possible with fast clocks */
+-};
+-
+-static struct snd_pcm_hw_constraint_list nano_player_constraint_rates = {
+- .list = nano_player_rates,
+- .count = ARRAY_SIZE(nano_player_rates),
+-};
+-
+-static int nano_player_init(struct snd_soc_pcm_runtime *rtd)
+-{
+- struct snd_soc_card *card = rtd->card;
+- struct regmap *regmap = snd_soc_card_get_drvdata(card);
+- struct snd_soc_pcm_stream *cpu = &rtd->cpu_dai->driver->playback;
+- struct snd_soc_pcm_stream *codec = &rtd->codec_dai->driver->playback;
+- unsigned int sample_bits = 32;
+- unsigned int val;
+-
+- /* configure cpu dai */
+- cpu->formats |= SNDRV_PCM_FMTBIT_DSD_U32_LE;
+- cpu->rate_max = 768000;
+-
+- /* configure dummy codec dai */
+- codec->rate_min = 44100;
+- codec->rates = SNDRV_PCM_RATE_KNOT;
+- codec->formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_DSD_U32_LE;
+-
+- /* configure max supported rate */
+- regmap_read(regmap, NANO_STATUS, &val);
+- if (val & NANO_STATUS_CLK) {
+- dev_notice(card->dev, "Board with fast clocks installed\n");
+- codec->rate_max = 768000;
+- } else {
+- dev_notice(card->dev, "Board with normal clocks installed\n");
+- codec->rate_max = 384000;
+- }
+-
+- /* frame length enforced by hardware */
+- return snd_soc_dai_set_bclk_ratio(rtd->cpu_dai, sample_bits * 2);
+-}
+-
+-static int nano_player_startup(struct snd_pcm_substream *substream)
+-{
+- return snd_pcm_hw_constraint_list(substream->runtime, 0,
+- SNDRV_PCM_HW_PARAM_RATE,
+- &nano_player_constraint_rates);
+-}
+-
+-static int nano_player_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 regmap *regmap = snd_soc_card_get_drvdata(card);
+- unsigned int config = NANO_CFG_ENA;
+- struct snd_mask *fmt;
+-
+- /* configure PCM or DSD */
+- fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+- if (snd_mask_test(fmt, SNDRV_PCM_FORMAT_DSD_U32_LE)) {
+- /* embed DSD in PCM data */
+- snd_mask_none(fmt);
+- snd_mask_set(fmt, SNDRV_PCM_FORMAT_S32_LE);
+- /* enable DSD mode */
+- config |= NANO_CFG_DSD;
+- }
+-
+- /* configure clocks */
+- switch (params_rate(params)) {
+- case 44100:
+- config |= NANO_CFG_MULT1 | NANO_CFG_CLK22;
+- break;
+- case 88200:
+- config |= NANO_CFG_MULT2 | NANO_CFG_CLK22;
+- break;
+- case 176400:
+- config |= NANO_CFG_MULT4 | NANO_CFG_CLK22;
+- break;
+- case 352800:
+- config |= NANO_CFG_MULT8 | NANO_CFG_CLK22;
+- break;
+- case 705600:
+- config |= NANO_CFG_MULT16 | NANO_CFG_CLK22;
+- break;
+- case 48000:
+- config |= NANO_CFG_MULT1 | NANO_CFG_CLK24;
+- break;
+- case 96000:
+- config |= NANO_CFG_MULT2 | NANO_CFG_CLK24;
+- break;
+- case 192000:
+- config |= NANO_CFG_MULT4 | NANO_CFG_CLK24;
+- break;
+- case 384000:
+- config |= NANO_CFG_MULT8 | NANO_CFG_CLK24;
+- break;
+- case 768000:
+- config |= NANO_CFG_MULT16 | NANO_CFG_CLK24;
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+- dev_dbg(card->dev, "Send CFG register 0x%02X\n", config);
+- return regmap_write(regmap, NANO_CFG, config);
+-}
+-
+-static struct snd_soc_ops nano_player_ops = {
+- .startup = nano_player_startup,
+- .hw_params = nano_player_hw_params,
+-};
+-
+-static struct snd_soc_dai_link nano_player_link = {
+- .name = "3Dlab Nano Player",
+- .stream_name = "3Dlab Nano Player HiFi",
+- .platform_name = "bcm2708-i2s.0",
+- .cpu_dai_name = "bcm2708-i2s.0",
+- .codec_name = "snd-soc-dummy",
+- .codec_dai_name = "snd-soc-dummy-dai",
+- .dai_fmt = SND_SOC_DAIFMT_I2S |
+- SND_SOC_DAIFMT_CONT |
+- SND_SOC_DAIFMT_NB_NF |
+- SND_SOC_DAIFMT_CBM_CFM,
+- .init = nano_player_init,
+- .ops = &nano_player_ops,
+-};
+-
+-static const struct regmap_config nano_player_regmap = {
+- .reg_bits = 8,
+- .val_bits = 8,
+- .max_register = 128,
+- .cache_type = REGCACHE_RBTREE,
+-};
+-
+-static int nano_player_card_probe(struct snd_soc_card *card)
+-{
+- struct regmap *regmap = snd_soc_card_get_drvdata(card);
+- unsigned int val;
+-
+- /* check hardware integrity */
+- regmap_read(regmap, NANO_ID, &val);
+- if (val != NANO_ID_VAL) {
+- dev_err(card->dev, "Invalid ID register 0x%02X\n", val);
+- return -ENODEV;
+- }
+-
+- /* report version to the user */
+- regmap_read(regmap, NANO_VER, &val);
+- dev_notice(card->dev, "Started 3Dlab Nano Player driver (v%d)\n", val);
+-
+- /* enable internal audio bus and blink status LED */
+- return regmap_write(regmap, NANO_CFG, NANO_CFG_ENA | NANO_CFG_BLINK);
+-}
+-
+-static int nano_player_card_remove(struct snd_soc_card *card)
+-{
+- /* disable internal audio bus */
+- struct regmap *regmap = snd_soc_card_get_drvdata(card);
+-
+- return regmap_write(regmap, NANO_CFG, NANO_CFG_OFF);
+-}
+-
+-static struct snd_soc_card nano_player_card = {
+- .name = "3Dlab_Nano_Player",
+- .owner = THIS_MODULE,
+- .dai_link = &nano_player_link,
+- .num_links = 1,
+- .controls = nano_player_controls,
+- .num_controls = ARRAY_SIZE(nano_player_controls),
+- .probe = nano_player_card_probe,
+- .remove = nano_player_card_remove,
+-};
+-
+-static int nano_player_i2c_probe(struct i2c_client *i2c,
+- const struct i2c_device_id *id)
+-{
+- struct regmap *regmap;
+- int ret;
+-
+- regmap = devm_regmap_init_i2c(i2c, &nano_player_regmap);
+- if (IS_ERR(regmap)) {
+- ret = PTR_ERR(regmap);
+- dev_err(&i2c->dev, "Failed to init regmap %d\n", ret);
+- return ret;
+- }
+-
+- if (i2c->dev.of_node) {
+- struct snd_soc_dai_link *dai = &nano_player_link;
+- struct device_node *node;
+-
+- /* cpu handle configured by device tree */
+- node = of_parse_phandle(i2c->dev.of_node, "i2s-controller", 0);
+- if (node) {
+- dai->platform_name = NULL;
+- dai->platform_of_node = node;
+- dai->cpu_dai_name = NULL;
+- dai->cpu_of_node = node;
+- }
+- }
+-
+- nano_player_card.dev = &i2c->dev;
+- snd_soc_card_set_drvdata(&nano_player_card, regmap);
+- ret = devm_snd_soc_register_card(&i2c->dev, &nano_player_card);
+-
+- if (ret && ret != -EPROBE_DEFER)
+- dev_err(&i2c->dev, "Failed to register card %d\n", ret);
+-
+- return ret;
+-}
+-
+-static const struct of_device_id nano_player_of_match[] = {
+- { .compatible = "3dlab,nano-player", },
+- { }
+-};
+-MODULE_DEVICE_TABLE(of, nano_player_of_match);
+-
+-static const struct i2c_device_id nano_player_i2c_id[] = {
+- { "nano-player", 0 },
+- { }
+-};
+-MODULE_DEVICE_TABLE(i2c, nano_player_i2c_id);
+-
+-static struct i2c_driver nano_player_i2c_driver = {
+- .probe = nano_player_i2c_probe,
+- .id_table = nano_player_i2c_id,
+- .driver = {
+- .name = "nano-player",
+- .owner = THIS_MODULE,
+- .of_match_table = nano_player_of_match,
+- },
+-};
+-
+-module_i2c_driver(nano_player_i2c_driver);
+-
+-MODULE_DESCRIPTION("ASoC 3Dlab Nano Player driver");
+-MODULE_AUTHOR("GT <dev@3d-lab-av.com>");
+-MODULE_LICENSE("GPL v2");
+-
+-/* EOF */
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -17,12 +17,6 @@ config SND_SOC_CYGNUS
+
+ If you don't know what to do here, say N.
+
+-config SND_BCM2708_SOC_3DLAB_NANO_PLAYER
+- tristate "Support for 3Dlab Nano Player"
+- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+- help
+- Say Y or M if you want to add support for 3Dlab Nano Player.
+-
+ config SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD
+ tristate "Support for Google voiceHAT soundcard"
+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -12,7 +12,6 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-
+ snd-soc-googlevoicehat-codec-objs := googlevoicehat-codec.o
+
+ # BCM2708 Machine Support
+-snd-soc-3dlab-nano-player-objs := 3dlab-nano-player.o
+ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
+ snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
+ snd-soc-justboom-dac-objs := justboom-dac.o
+@@ -20,7 +19,7 @@ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
+ snd-soc-rpi-proto-objs := rpi-proto.o
+ snd-soc-iqaudio-codec-objs := iqaudio-codec.o
+ snd-soc-iqaudio-dac-objs := iqaudio-dac.o
+- snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
++snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
+ snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
+ snd-soc-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o
+ snd-soc-audiosense-pi-objs := audiosense-pi.o
+@@ -36,7 +35,6 @@ snd-soc-fe-pi-audio-objs := fe-pi-audio.
+ snd-soc-rpi-simple-soundcard-objs := rpi-simple-soundcard.o
+ snd-soc-rpi-wm8804-soundcard-objs := rpi-wm8804-soundcard.o
+
+-obj-$(CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER) += snd-soc-3dlab-nano-player.o
+ obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD) += snd-soc-googlevoicehat-codec.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
+@@ -45,7 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS)
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
+ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC) += snd-soc-iqaudio-codec.o
+ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
+- obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.o
++obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.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_AUDIOSENSE_PI) += snd-soc-audiosense-pi.o
+++ /dev/null
-From 8bf83aaaa40f140bc14521ac2f1dd08a8463cc87 Mon Sep 17 00:00:00 2001
-From: Henrique Gontijo <hgontijo@guidewire.com>
-Date: Sun, 12 May 2019 17:11:02 -0700
-Subject: [PATCH 498/703] configs: Enable PIDs cgroup
-
-My use case to is to allow Kubernetes master to run on Raspberry Pi 3.
-Kubernetes introduced [Pid limiting](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/20190129-pid-limiting.md),
-on v.1.14.0 which includes [Pod Pids Limit](https://github.com/kubernetes/kubernetes/commit/bce9d5f2043bd86964c9fec80d466e47776071bc)
-and [Node Pids Limit](https://github.com/kubernetes/kubernetes/commit/2597a1d97ef4d8f54b1ca661453e32794b756909#diff-fa76bb6ae2d9b4bb3d023737fe5e6029R333)
-that requires pids cgroup.
-
-See: https://github.com/raspberrypi/linux/pull/2968
----
- arch/arm/configs/bcm2709_defconfig | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -20,6 +20,7 @@ CONFIG_CGROUP_FREEZER=y
- CONFIG_CPUSETS=y
- CONFIG_CGROUP_DEVICE=y
- CONFIG_CGROUP_CPUACCT=y
-+CONFIG_CGROUP_PIDS=y
- CONFIG_NAMESPACES=y
- CONFIG_USER_NS=y
- CONFIG_SCHED_AUTOGROUP=y
--- /dev/null
+From 08452889f1bd46f4b4f34b915a3095523de1758a Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Tue, 21 May 2019 15:17:33 +0100
+Subject: [PATCH 499/725] .gitignore: Add *.dtbo explicitly
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ .gitignore | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/.gitignore
++++ b/.gitignore
+@@ -15,7 +15,8 @@
+ *.bin
+ *.bz2
+ *.c.[012]*.*
+-*.dtb*
++*.dtb
++*.dtbo
+ *.dtb.S
+ *.dwo
+ *.elf
+++ /dev/null
-From cc87b27a07e5da8d072b3c4e80a3f92cda44e106 Mon Sep 17 00:00:00 2001
-From: Jean-Francois Dagenais <jeff.dagenais@gmail.com>
-Date: Thu, 28 Mar 2019 12:41:11 -0400
-Subject: [PATCH 499/703] w1: ds2408: reset on output_write retry with readback
-
-commit 49695ac46861180baf2b2b92c62da8619b6bf28f upstream.
-
-When we have success in 'Channel Access Write' but reading back latch
-states fails, a write is retried without doing a proper slave reset.
-This leads to protocol errors as the slave treats the next 'Channel
-Access Write' as the continuation of previous command.
-
-This commit is fixing this by making sure if the retry loop re-runs, a
-reset is performed, whatever the failure (CONFIRM_BYTE or the read
-back).
-
-The loop was quite due for a cleanup and this change mandated it. By
-isolating the CONFIG_W1_SLAVE_DS2408_READBACK case into it's own
-function, we vastly reduce the visual and branching(runtime and
-compile-time) noise.
-
-Reported-by: Mariusz Bialonczyk <manio@skyboo.net>
-Tested-by: Mariusz Bialonczyk <manio@skyboo.net>
-Signed-off-by: Jean-Francois Dagenais <jeff.dagenais@gmail.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/slaves/w1_ds2408.c | 76 ++++++++++++++++++-----------------
- 1 file changed, 39 insertions(+), 37 deletions(-)
-
---- a/drivers/w1/slaves/w1_ds2408.c
-+++ b/drivers/w1/slaves/w1_ds2408.c
-@@ -138,14 +138,37 @@ static ssize_t status_control_read(struc
- W1_F29_REG_CONTROL_AND_STATUS, buf);
- }
-
-+#ifdef fCONFIG_W1_SLAVE_DS2408_READBACK
-+static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
-+{
-+ u8 w1_buf[3];
-+
-+ if (w1_reset_resume_command(sl->master))
-+ return false;
-+
-+ w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
-+ w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
-+ w1_buf[2] = 0;
-+
-+ w1_write_block(sl->master, w1_buf, 3);
-+
-+ return (w1_read_8(sl->master) == expected);
-+}
-+#else
-+static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
-+{
-+ return true;
-+}
-+#endif
-+
- static ssize_t output_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
- loff_t off, size_t count)
- {
- struct w1_slave *sl = kobj_to_w1_slave(kobj);
- u8 w1_buf[3];
-- u8 readBack;
- unsigned int retries = W1_F29_RETRIES;
-+ ssize_t bytes_written = -EIO;
-
- if (count != 1 || off != 0)
- return -EFAULT;
-@@ -155,54 +178,33 @@ static ssize_t output_write(struct file
- dev_dbg(&sl->dev, "mutex locked");
-
- if (w1_reset_select_slave(sl))
-- goto error;
-+ goto out;
-
-- while (retries--) {
-+ do {
- w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE;
- w1_buf[1] = *buf;
- w1_buf[2] = ~(*buf);
-- w1_write_block(sl->master, w1_buf, 3);
-
-- readBack = w1_read_8(sl->master);
-+ w1_write_block(sl->master, w1_buf, 3);
-
-- if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) {
-- if (w1_reset_resume_command(sl->master))
-- goto error;
-- /* try again, the slave is ready for a command */
-- continue;
-+ if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE &&
-+ optional_read_back_valid(sl, *buf)) {
-+ bytes_written = 1;
-+ goto out;
- }
-
--#ifdef CONFIG_W1_SLAVE_DS2408_READBACK
-- /* here the master could read another byte which
-- would be the PIO reg (the actual pin logic state)
-- since in this driver we don't know which pins are
-- in and outs, there's no value to read the state and
-- compare. with (*buf) so end this command abruptly: */
- if (w1_reset_resume_command(sl->master))
-- goto error;
-+ goto out; /* unrecoverable error */
-+ /* try again, the slave is ready for a command */
-+ } while (--retries);
-
-- /* go read back the output latches */
-- /* (the direct effect of the write above) */
-- w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
-- w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
-- w1_buf[2] = 0;
-- w1_write_block(sl->master, w1_buf, 3);
-- /* read the result of the READ_PIO_REGS command */
-- if (w1_read_8(sl->master) == *buf)
--#endif
-- {
-- /* success! */
-- mutex_unlock(&sl->master->bus_mutex);
-- dev_dbg(&sl->dev,
-- "mutex unlocked, retries:%d", retries);
-- return 1;
-- }
-- }
--error:
-+out:
- mutex_unlock(&sl->master->bus_mutex);
-- dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
-
-- return -EIO;
-+ dev_dbg(&sl->dev, "%s, mutex unlocked retries:%d\n",
-+ (bytes_written > 0) ? "succeeded" : "error", retries);
-+
-+ return bytes_written;
- }
-
-
--- /dev/null
+From 6dec9b770df1f986091eb4e61e829f2d8b2031b1 Mon Sep 17 00:00:00 2001
+From: Marcel Holtmann <marcel@holtmann.org>
+Date: Wed, 22 May 2019 09:05:40 +0200
+Subject: [PATCH 500/725] Bluetooth: Check key sizes only when Secure Simple
+ Pairing is enabled
+
+The encryption is only mandatory to be enforced when both sides are using
+Secure Simple Pairing and this means the key size check makes only sense
+in that case.
+
+On legacy Bluetooth 2.0 and earlier devices like mice the encryption was
+optional and thus causing an issue if the key size check is not bound to
+using Secure Simple Pairing.
+
+Fixes: d5bb334a8e17 ("Bluetooth: Align minimum encryption key size for LE and BR/EDR connections")
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Cc: stable@vger.kernel.org
+---
+ net/bluetooth/hci_conn.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -1272,8 +1272,13 @@ int hci_conn_check_link_mode(struct hci_
+ return 0;
+ }
+
+- if (hci_conn_ssp_enabled(conn) &&
+- !test_bit(HCI_CONN_ENCRYPT, &conn->flags))
++ /* If Secure Simple Pairing is not enabled, then legacy connection
++ * setup is used and no encryption or key sizes can be enforced.
++ */
++ if (!hci_conn_ssp_enabled(conn))
++ return 1;
++
++ if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
+ return 0;
+
+ return 1;
+++ /dev/null
-From cf423c8b0d5d1fa5cc0c9427b5282aa888b5eaef Mon Sep 17 00:00:00 2001
-From: Mariusz Bialonczyk <manio@skyboo.net>
-Date: Mon, 4 Mar 2019 12:23:36 +0100
-Subject: [PATCH 500/703] w1: ds2482: cosmetic fixes after 54865314f5a1
-
-commit 5cb27d30fc3a281e830a2099d520b469e2b82008 upstream.
-
-We have a helper function ds2482_calculate_config() which is calculating
-the config value, so just use it instead of passing the same variable
-in all calls to this function.
-
-Also fixes the placement of module parameters to match with:
-50fa2951bd74 (w1: Organize driver source to natural/common order)
-by Andrew F. Davis
-
-Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
-Cc: Andrew Worsley <amworsley@gmail.com>
-Cc: Andrew F. Davis <afd@ti.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/masters/ds2482.c | 18 +++++++++++-------
- 1 file changed, 11 insertions(+), 7 deletions(-)
-
---- a/drivers/w1/masters/ds2482.c
-+++ b/drivers/w1/masters/ds2482.c
-@@ -37,6 +37,11 @@ module_param_named(active_pullup, ds2482
- MODULE_PARM_DESC(active_pullup, "Active pullup (apply to all buses): " \
- "0-disable, 1-enable (default)");
-
-+/* extra configurations - e.g. 1WS */
-+static int extra_config;
-+module_param(extra_config, int, S_IRUGO | S_IWUSR);
-+MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8=1WS");
-+
- /**
- * The DS2482 registers - there are 3 registers that are addressed by a read
- * pointer. The read pointer is set by the last command executed.
-@@ -70,8 +75,6 @@ MODULE_PARM_DESC(active_pullup, "Active
- #define DS2482_REG_CFG_PPM 0x02 /* presence pulse masking */
- #define DS2482_REG_CFG_APU 0x01 /* active pull-up */
-
--/* extra configurations - e.g. 1WS */
--static int extra_config;
-
- /**
- * Write and verify codes for the CHANNEL_SELECT command (DS2482-800 only).
-@@ -130,6 +133,8 @@ struct ds2482_data {
- */
- static inline u8 ds2482_calculate_config(u8 conf)
- {
-+ conf |= extra_config;
-+
- if (ds2482_active_pullup)
- conf |= DS2482_REG_CFG_APU;
-
-@@ -405,7 +410,7 @@ static u8 ds2482_w1_reset_bus(void *data
- /* If the chip did reset since detect, re-config it */
- if (err & DS2482_REG_STS_RST)
- ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG,
-- ds2482_calculate_config(extra_config));
-+ ds2482_calculate_config(0x00));
- }
-
- mutex_unlock(&pdev->access_lock);
-@@ -431,7 +436,8 @@ static u8 ds2482_w1_set_pullup(void *dat
- ds2482_wait_1wire_idle(pdev);
- /* note: it seems like both SPU and APU have to be set! */
- retval = ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG,
-- ds2482_calculate_config(extra_config|DS2482_REG_CFG_SPU|DS2482_REG_CFG_APU));
-+ ds2482_calculate_config(DS2482_REG_CFG_SPU |
-+ DS2482_REG_CFG_APU));
- ds2482_wait_1wire_idle(pdev);
- }
-
-@@ -484,7 +490,7 @@ static int ds2482_probe(struct i2c_clien
-
- /* Set all config items to 0 (off) */
- ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG,
-- ds2482_calculate_config(extra_config));
-+ ds2482_calculate_config(0x00));
-
- mutex_init(&data->access_lock);
-
-@@ -559,7 +565,5 @@ module_i2c_driver(ds2482_driver);
-
- MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
- MODULE_DESCRIPTION("DS2482 driver");
--module_param(extra_config, int, S_IRUGO | S_IWUSR);
--MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8=1WS");
-
- MODULE_LICENSE("GPL");
+++ /dev/null
-From d188a0a3472f80003d2558639ebeb41e190a4b9b Mon Sep 17 00:00:00 2001
-From: Klaus Schulz <klsschlz@gmail.com>
-Date: Thu, 16 May 2019 13:35:32 +0200
-Subject: [PATCH 501/703] sound: pcm512x-codec: Adding 352.8kHz samplerate
- support
-
----
- sound/soc/codecs/pcm512x.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/sound/soc/codecs/pcm512x.c
-+++ b/sound/soc/codecs/pcm512x.c
-@@ -542,7 +542,7 @@ static unsigned long pcm512x_ncp_target(
-
- static const u32 pcm512x_dai_rates[] = {
- 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
-- 88200, 96000, 176400, 192000, 384000,
-+ 88200, 96000, 176400, 192000, 352800, 384000,
- };
-
- static const struct snd_pcm_hw_constraint_list constraints_slave = {
--- /dev/null
+From f37b215f0ea4180c8befba9fe48626ec8d5bfc41 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 7 May 2019 17:23:41 +0100
+Subject: [PATCH 501/725] usb: dwc_otg: Clean up interrupt claiming code
+
+The FIQ/IRQ interrupt number identification code is scattered through
+the dwc_otg driver. Rationalise it, simplifying the code and solving
+an existing issue.
+
+See: https://github.com/raspberrypi/linux/issues/2612
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_driver.c | 18 +++++++++-----
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 10 +++-----
+ drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 6 +++++
+ drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 26 +++-----------------
+ 4 files changed, 25 insertions(+), 35 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
+@@ -624,11 +624,7 @@ static int dwc_otg_driver_remove(
+ * Free the IRQ
+ */
+ if (otg_dev->common_irq_installed) {
+-#ifdef PLATFORM_INTERFACE
+- free_irq(platform_get_irq(_dev, 0), otg_dev);
+-#else
+- free_irq(_dev->irq, otg_dev);
+-#endif
++ free_irq(otg_dev->os_dep.irq_num, otg_dev);
+ } else {
+ DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__);
+ return REM_RETVAL(-ENXIO);
+@@ -905,7 +901,9 @@ static int dwc_otg_driver_probe(
+ */
+
+ #if defined(PLATFORM_INTERFACE)
+- devirq = platform_get_irq(_dev, fiq_enable ? 0 : 1);
++ devirq = platform_get_irq_byname(_dev, fiq_enable ? "soft" : "usb");
++ if (devirq < 0)
++ devirq = platform_get_irq(_dev, fiq_enable ? 0 : 1);
+ #else
+ devirq = _dev->irq;
+ #endif
+@@ -922,6 +920,14 @@ static int dwc_otg_driver_probe(
+ } else {
+ dwc_otg_device->common_irq_installed = 1;
+ }
++ dwc_otg_device->os_dep.irq_num = devirq;
++ dwc_otg_device->os_dep.fiq_num = -EINVAL;
++ if (fiq_enable) {
++ int devfiq = platform_get_irq_byname(_dev, "usb");
++ if (devfiq < 0)
++ devfiq = platform_get_irq(_dev, 1);
++ dwc_otg_device->os_dep.fiq_num = devfiq;
++ }
+
+ #ifndef IRQF_TRIGGER_LOW
+ #if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+@@ -492,7 +492,7 @@ static void hcd_init_fiq(void *cookie)
+ #endif
+ // Enable FIQ interrupt from USB peripheral
+ #ifdef CONFIG_ARM64
+- irq = platform_get_irq(otg_dev->os_dep.platformdev, 1);
++ irq = otg_dev->os_dep.fiq_num;
+
+ if (irq < 0) {
+ DWC_ERROR("Can't get SIM-FIQ irq");
+@@ -509,7 +509,7 @@ static void hcd_init_fiq(void *cookie)
+ simfiq_irq = irq;
+ #else
+ #ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
+- irq = platform_get_irq(otg_dev->os_dep.platformdev, 1);
++ irq = otg_dev->os_dep.fiq_num;
+ #else
+ irq = INTERRUPT_VC_USB;
+ #endif
+@@ -626,11 +626,7 @@ int hcd_init(dwc_bus_dev_t *_dev)
+ * allocates the DMA buffer pool, registers the USB bus, requests the
+ * IRQ line, and calls hcd_start method.
+ */
+-#ifdef PLATFORM_INTERFACE
+- retval = usb_add_hcd(hcd, platform_get_irq(_dev, fiq_enable ? 0 : 1), IRQF_SHARED);
+-#else
+- retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED);
+-#endif
++ retval = usb_add_hcd(hcd, otg_dev->os_dep.irq_num, IRQF_SHARED);
+ if (retval < 0) {
+ goto error2;
+ }
+--- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
++++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
+@@ -102,6 +102,12 @@ typedef struct os_dependent {
+ /** Base address for MPHI peripheral */
+ void *mphi_base;
+
++ /** IRQ number (<0 if not valid) */
++ int irq_num;
++
++ /** FIQ number (<0 if not valid) */
++ int fiq_num;
++
+ #ifdef LM_INTERFACE
+ struct lm_device *lmdev;
+ #elif defined(PCI_INTERFACE)
+--- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
+@@ -1224,30 +1224,16 @@ int pcd_init(dwc_bus_dev_t *_dev)
+ /*
+ * Setup interupt handler
+ */
+-#ifdef PLATFORM_INTERFACE
+ DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
+- platform_get_irq(_dev, fiq_enable ? 0 : 1));
+- retval = request_irq(platform_get_irq(_dev, fiq_enable ? 0 : 1), dwc_otg_pcd_irq,
++ otg_dev->os_dep.irq_num);
++ retval = request_irq(otg_dev->os_dep.irq_num, dwc_otg_pcd_irq,
+ IRQF_SHARED, gadget_wrapper->gadget.name,
+ otg_dev->pcd);
+ if (retval != 0) {
+- DWC_ERROR("request of irq%d failed\n",
+- platform_get_irq(_dev, fiq_enable ? 0 : 1));
++ DWC_ERROR("request of irq%d failed\n", otg_dev->os_dep.irq_num);
+ free_wrapper(gadget_wrapper);
+ return -EBUSY;
+ }
+-#else
+- DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
+- _dev->irq);
+- retval = request_irq(_dev->irq, dwc_otg_pcd_irq,
+- IRQF_SHARED | IRQF_DISABLED,
+- gadget_wrapper->gadget.name, otg_dev->pcd);
+- if (retval != 0) {
+- DWC_ERROR("request of irq%d failed\n", _dev->irq);
+- free_wrapper(gadget_wrapper);
+- return -EBUSY;
+- }
+-#endif
+
+ dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);
+
+@@ -1267,11 +1253,7 @@ void pcd_remove(dwc_bus_dev_t *_dev)
+ /*
+ * Free the IRQ
+ */
+-#ifdef PLATFORM_INTERFACE
+- free_irq(platform_get_irq(_dev, 0), pcd);
+-#else
+- free_irq(_dev->irq, pcd);
+-#endif
++ free_irq(otg_dev->os_dep.irq_num, pcd);
+ dwc_otg_pcd_remove(otg_dev->pcd);
+ free_wrapper(gadget_wrapper);
+ otg_dev->pcd = 0;
+++ /dev/null
-From 4f8dc6c030b1d24c4bf270637eba452ad9b9dd9b Mon Sep 17 00:00:00 2001
-From: GT <dev@3d-lab-av.com>
-Date: Sat, 6 Apr 2019 21:16:39 +0100
-Subject: [PATCH 502/703] ASoC: decommissioning driver for 3Dlab Nano soundcard
-
----
- .../overlays/3dlab-nano-player-overlay.dts | 32 --
- arch/arm/boot/dts/overlays/Makefile | 1 -
- arch/arm/boot/dts/overlays/README | 6 -
- arch/arm/configs/bcm2709_defconfig | 1 -
- arch/arm/configs/bcmrpi_defconfig | 1 -
- sound/soc/bcm/3dlab-nano-player.c | 370 ------------------
- sound/soc/bcm/Kconfig | 6 -
- sound/soc/bcm/Makefile | 6 +-
- 8 files changed, 2 insertions(+), 421 deletions(-)
- delete mode 100644 arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
- delete mode 100644 sound/soc/bcm/3dlab-nano-player.c
-
---- a/arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts
-+++ /dev/null
-@@ -1,32 +0,0 @@
--// Definitions for 3Dlab Nano Player
--/dts-v1/;
--/plugin/;
--
--/ {
-- compatible = "brcm,bcm2708";
--
-- fragment@0 {
-- target = <&i2s>;
-- __overlay__ {
-- status = "okay";
-- };
-- };
--
-- fragment@1 {
-- target = <&i2c>;
-- __overlay__ {
-- #address-cells = <1>;
-- #size-cells = <0>;
-- status = "okay";
--
-- nano-player@41 {
-- compatible = "3dlab,nano-player";
-- reg = <0x41>;
-- i2s-controller = <&i2s>;
-- status = "okay";
-- };
-- };
-- };
--};
--
--// EOF
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -1,7 +1,6 @@
- # Overlays for the Raspberry Pi platform
-
- dtbo-$(CONFIG_ARCH_BCM2835) += \
-- 3dlab-nano-player.dtbo \
- adau1977-adc.dtbo \
- adau7002-simple.dtbo \
- ads1015.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -205,12 +205,6 @@ Params:
- and the other i2c baudrate parameters.
-
-
--Name: 3dlab-nano-player
--Info: Configures the 3Dlab Nano Player
--Load: dtoverlay=3dlab-nano-player
--Params: <None>
--
--
- Name: adau1977-adc
- Info: Overlay for activation of ADAU1977 ADC codec over I2C for control
- and I2S for data.
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -908,7 +908,6 @@ CONFIG_SND_USB_6FIRE=m
- CONFIG_SND_USB_HIFACE=m
- CONFIG_SND_SOC=m
- CONFIG_SND_BCM2835_SOC_I2S=m
--CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
- CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -900,7 +900,6 @@ CONFIG_SND_USB_6FIRE=m
- CONFIG_SND_USB_HIFACE=m
- CONFIG_SND_SOC=m
- CONFIG_SND_BCM2835_SOC_I2S=m
--CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER=m
- CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
- CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
---- a/sound/soc/bcm/3dlab-nano-player.c
-+++ /dev/null
-@@ -1,370 +0,0 @@
--/*
-- * 3Dlab Nano Player ALSA SoC Audio driver.
-- *
-- * Copyright (C) 2018 3Dlab.
-- *
-- * Author: GT <dev@3d-lab-av.com>
-- *
-- * 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 <linux/module.h>
--#include <linux/i2c.h>
--#include <sound/soc.h>
--#include <sound/pcm.h>
--#include <sound/pcm_params.h>
--#include <sound/control.h>
--
--#define NANO_ID 0x00
--#define NANO_VER 0x01
--#define NANO_CFG 0x02
--#define NANO_STATUS 0x03
--#define NANO_SPI_ADDR 0x04
--#define NANO_SPI_DATA 0x05
--
--#define NANO_ID_VAL 0x3D
--#define NANO_CFG_OFF 0x00
--#define NANO_CFG_MULT1 0
--#define NANO_CFG_MULT2 1
--#define NANO_CFG_MULT4 2
--#define NANO_CFG_MULT8 3
--#define NANO_CFG_MULT16 4
--#define NANO_CFG_CLK22 0
--#define NANO_CFG_CLK24 BIT(3)
--#define NANO_CFG_DSD BIT(4)
--#define NANO_CFG_ENA BIT(5)
--#define NANO_CFG_BLINK BIT(6)
--#define NANO_STATUS_P1 BIT(0)
--#define NANO_STATUS_P2 BIT(1)
--#define NANO_STATUS_FLG BIT(2)
--#define NANO_STATUS_CLK BIT(3)
--#define NANO_SPI_READ 0
--#define NANO_SPI_WRITE BIT(5)
--
--#define NANO_DAC_CTRL1 0x00
--#define NANO_DAC_CTRL2 0x01
--#define NANO_DAC_CTRL3 0x02
--#define NANO_DAC_LATT 0x03
--#define NANO_DAC_RATT 0x04
--
--#define NANO_CTRL2_VAL 0x22
--
--static int nano_player_spi_write(struct regmap *map,
-- unsigned int reg, unsigned int val)
--{
-- /* indirect register access */
-- regmap_write(map, NANO_SPI_DATA, val);
-- regmap_write(map, NANO_SPI_ADDR, reg | NANO_SPI_WRITE);
-- return 0;
--}
--
--static int nano_player_ctrl_info(struct snd_kcontrol *kcontrol,
-- struct snd_ctl_elem_info *uinfo)
--{
-- /* describe control element */
-- if (strstr(kcontrol->id.name, "Volume")) {
-- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-- uinfo->count = 1;
-- uinfo->value.integer.min = 0;
-- uinfo->value.integer.max = 100;
-- } else {
-- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-- uinfo->count = 1;
-- uinfo->value.integer.min = 0;
-- uinfo->value.integer.max = 1;
-- }
--
-- return 0;
--}
--
--static int nano_player_ctrl_put(struct snd_kcontrol *kcontrol,
-- struct snd_ctl_elem_value *ucontrol)
--{
-- /* program control value to hardware */
-- struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
-- struct regmap *regmap = snd_soc_card_get_drvdata(card);
--
-- if (strstr(kcontrol->id.name, "Volume")) {
-- unsigned int vol = ucontrol->value.integer.value[0];
-- unsigned int att = 255 - (2 * (100 - vol));
--
-- nano_player_spi_write(regmap, NANO_DAC_LATT, att);
-- nano_player_spi_write(regmap, NANO_DAC_RATT, att);
-- kcontrol->private_value = vol;
-- } else {
-- unsigned int mute = ucontrol->value.integer.value[0];
-- unsigned int reg = NANO_CTRL2_VAL | mute;
--
-- nano_player_spi_write(regmap, NANO_DAC_CTRL2, reg);
-- kcontrol->private_value = mute;
-- }
-- return 0;
--}
--
--static int nano_player_ctrl_get(struct snd_kcontrol *kcontrol,
-- struct snd_ctl_elem_value *ucontrol)
--{
-- /* return last programmed value */
-- ucontrol->value.integer.value[0] = kcontrol->private_value;
-- return 0;
--}
--
--#define SOC_NANO_PLAYER_CTRL(xname) \
--{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
-- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
-- .info = nano_player_ctrl_info, \
-- .put = nano_player_ctrl_put, \
-- .get = nano_player_ctrl_get }
--
--static const struct snd_kcontrol_new nano_player_controls[] = {
-- SOC_NANO_PLAYER_CTRL("Master Playback Volume"),
-- SOC_NANO_PLAYER_CTRL("Master Playback Switch"),
--};
--
--static const unsigned int nano_player_rates[] = {
-- 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000,
-- 705600, 768000 /* only possible with fast clocks */
--};
--
--static struct snd_pcm_hw_constraint_list nano_player_constraint_rates = {
-- .list = nano_player_rates,
-- .count = ARRAY_SIZE(nano_player_rates),
--};
--
--static int nano_player_init(struct snd_soc_pcm_runtime *rtd)
--{
-- struct snd_soc_card *card = rtd->card;
-- struct regmap *regmap = snd_soc_card_get_drvdata(card);
-- struct snd_soc_pcm_stream *cpu = &rtd->cpu_dai->driver->playback;
-- struct snd_soc_pcm_stream *codec = &rtd->codec_dai->driver->playback;
-- unsigned int sample_bits = 32;
-- unsigned int val;
--
-- /* configure cpu dai */
-- cpu->formats |= SNDRV_PCM_FMTBIT_DSD_U32_LE;
-- cpu->rate_max = 768000;
--
-- /* configure dummy codec dai */
-- codec->rate_min = 44100;
-- codec->rates = SNDRV_PCM_RATE_KNOT;
-- codec->formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_DSD_U32_LE;
--
-- /* configure max supported rate */
-- regmap_read(regmap, NANO_STATUS, &val);
-- if (val & NANO_STATUS_CLK) {
-- dev_notice(card->dev, "Board with fast clocks installed\n");
-- codec->rate_max = 768000;
-- } else {
-- dev_notice(card->dev, "Board with normal clocks installed\n");
-- codec->rate_max = 384000;
-- }
--
-- /* frame length enforced by hardware */
-- return snd_soc_dai_set_bclk_ratio(rtd->cpu_dai, sample_bits * 2);
--}
--
--static int nano_player_startup(struct snd_pcm_substream *substream)
--{
-- return snd_pcm_hw_constraint_list(substream->runtime, 0,
-- SNDRV_PCM_HW_PARAM_RATE,
-- &nano_player_constraint_rates);
--}
--
--static int nano_player_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 regmap *regmap = snd_soc_card_get_drvdata(card);
-- unsigned int config = NANO_CFG_ENA;
-- struct snd_mask *fmt;
--
-- /* configure PCM or DSD */
-- fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
-- if (snd_mask_test(fmt, SNDRV_PCM_FORMAT_DSD_U32_LE)) {
-- /* embed DSD in PCM data */
-- snd_mask_none(fmt);
-- snd_mask_set(fmt, SNDRV_PCM_FORMAT_S32_LE);
-- /* enable DSD mode */
-- config |= NANO_CFG_DSD;
-- }
--
-- /* configure clocks */
-- switch (params_rate(params)) {
-- case 44100:
-- config |= NANO_CFG_MULT1 | NANO_CFG_CLK22;
-- break;
-- case 88200:
-- config |= NANO_CFG_MULT2 | NANO_CFG_CLK22;
-- break;
-- case 176400:
-- config |= NANO_CFG_MULT4 | NANO_CFG_CLK22;
-- break;
-- case 352800:
-- config |= NANO_CFG_MULT8 | NANO_CFG_CLK22;
-- break;
-- case 705600:
-- config |= NANO_CFG_MULT16 | NANO_CFG_CLK22;
-- break;
-- case 48000:
-- config |= NANO_CFG_MULT1 | NANO_CFG_CLK24;
-- break;
-- case 96000:
-- config |= NANO_CFG_MULT2 | NANO_CFG_CLK24;
-- break;
-- case 192000:
-- config |= NANO_CFG_MULT4 | NANO_CFG_CLK24;
-- break;
-- case 384000:
-- config |= NANO_CFG_MULT8 | NANO_CFG_CLK24;
-- break;
-- case 768000:
-- config |= NANO_CFG_MULT16 | NANO_CFG_CLK24;
-- break;
-- default:
-- return -EINVAL;
-- }
--
-- dev_dbg(card->dev, "Send CFG register 0x%02X\n", config);
-- return regmap_write(regmap, NANO_CFG, config);
--}
--
--static struct snd_soc_ops nano_player_ops = {
-- .startup = nano_player_startup,
-- .hw_params = nano_player_hw_params,
--};
--
--static struct snd_soc_dai_link nano_player_link = {
-- .name = "3Dlab Nano Player",
-- .stream_name = "3Dlab Nano Player HiFi",
-- .platform_name = "bcm2708-i2s.0",
-- .cpu_dai_name = "bcm2708-i2s.0",
-- .codec_name = "snd-soc-dummy",
-- .codec_dai_name = "snd-soc-dummy-dai",
-- .dai_fmt = SND_SOC_DAIFMT_I2S |
-- SND_SOC_DAIFMT_CONT |
-- SND_SOC_DAIFMT_NB_NF |
-- SND_SOC_DAIFMT_CBM_CFM,
-- .init = nano_player_init,
-- .ops = &nano_player_ops,
--};
--
--static const struct regmap_config nano_player_regmap = {
-- .reg_bits = 8,
-- .val_bits = 8,
-- .max_register = 128,
-- .cache_type = REGCACHE_RBTREE,
--};
--
--static int nano_player_card_probe(struct snd_soc_card *card)
--{
-- struct regmap *regmap = snd_soc_card_get_drvdata(card);
-- unsigned int val;
--
-- /* check hardware integrity */
-- regmap_read(regmap, NANO_ID, &val);
-- if (val != NANO_ID_VAL) {
-- dev_err(card->dev, "Invalid ID register 0x%02X\n", val);
-- return -ENODEV;
-- }
--
-- /* report version to the user */
-- regmap_read(regmap, NANO_VER, &val);
-- dev_notice(card->dev, "Started 3Dlab Nano Player driver (v%d)\n", val);
--
-- /* enable internal audio bus and blink status LED */
-- return regmap_write(regmap, NANO_CFG, NANO_CFG_ENA | NANO_CFG_BLINK);
--}
--
--static int nano_player_card_remove(struct snd_soc_card *card)
--{
-- /* disable internal audio bus */
-- struct regmap *regmap = snd_soc_card_get_drvdata(card);
--
-- return regmap_write(regmap, NANO_CFG, NANO_CFG_OFF);
--}
--
--static struct snd_soc_card nano_player_card = {
-- .name = "3Dlab_Nano_Player",
-- .owner = THIS_MODULE,
-- .dai_link = &nano_player_link,
-- .num_links = 1,
-- .controls = nano_player_controls,
-- .num_controls = ARRAY_SIZE(nano_player_controls),
-- .probe = nano_player_card_probe,
-- .remove = nano_player_card_remove,
--};
--
--static int nano_player_i2c_probe(struct i2c_client *i2c,
-- const struct i2c_device_id *id)
--{
-- struct regmap *regmap;
-- int ret;
--
-- regmap = devm_regmap_init_i2c(i2c, &nano_player_regmap);
-- if (IS_ERR(regmap)) {
-- ret = PTR_ERR(regmap);
-- dev_err(&i2c->dev, "Failed to init regmap %d\n", ret);
-- return ret;
-- }
--
-- if (i2c->dev.of_node) {
-- struct snd_soc_dai_link *dai = &nano_player_link;
-- struct device_node *node;
--
-- /* cpu handle configured by device tree */
-- node = of_parse_phandle(i2c->dev.of_node, "i2s-controller", 0);
-- if (node) {
-- dai->platform_name = NULL;
-- dai->platform_of_node = node;
-- dai->cpu_dai_name = NULL;
-- dai->cpu_of_node = node;
-- }
-- }
--
-- nano_player_card.dev = &i2c->dev;
-- snd_soc_card_set_drvdata(&nano_player_card, regmap);
-- ret = devm_snd_soc_register_card(&i2c->dev, &nano_player_card);
--
-- if (ret && ret != -EPROBE_DEFER)
-- dev_err(&i2c->dev, "Failed to register card %d\n", ret);
--
-- return ret;
--}
--
--static const struct of_device_id nano_player_of_match[] = {
-- { .compatible = "3dlab,nano-player", },
-- { }
--};
--MODULE_DEVICE_TABLE(of, nano_player_of_match);
--
--static const struct i2c_device_id nano_player_i2c_id[] = {
-- { "nano-player", 0 },
-- { }
--};
--MODULE_DEVICE_TABLE(i2c, nano_player_i2c_id);
--
--static struct i2c_driver nano_player_i2c_driver = {
-- .probe = nano_player_i2c_probe,
-- .id_table = nano_player_i2c_id,
-- .driver = {
-- .name = "nano-player",
-- .owner = THIS_MODULE,
-- .of_match_table = nano_player_of_match,
-- },
--};
--
--module_i2c_driver(nano_player_i2c_driver);
--
--MODULE_DESCRIPTION("ASoC 3Dlab Nano Player driver");
--MODULE_AUTHOR("GT <dev@3d-lab-av.com>");
--MODULE_LICENSE("GPL v2");
--
--/* EOF */
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -17,12 +17,6 @@ config SND_SOC_CYGNUS
-
- If you don't know what to do here, say N.
-
--config SND_BCM2708_SOC_3DLAB_NANO_PLAYER
-- tristate "Support for 3Dlab Nano Player"
-- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-- help
-- Say Y or M if you want to add support for 3Dlab Nano Player.
--
- config SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD
- tristate "Support for Google voiceHAT soundcard"
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -12,7 +12,6 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-
- snd-soc-googlevoicehat-codec-objs := googlevoicehat-codec.o
-
- # BCM2708 Machine Support
--snd-soc-3dlab-nano-player-objs := 3dlab-nano-player.o
- snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
- snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
- snd-soc-justboom-dac-objs := justboom-dac.o
-@@ -20,7 +19,7 @@ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
- snd-soc-rpi-proto-objs := rpi-proto.o
- snd-soc-iqaudio-codec-objs := iqaudio-codec.o
- snd-soc-iqaudio-dac-objs := iqaudio-dac.o
-- snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
-+snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
- snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
- snd-soc-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o
- snd-soc-audiosense-pi-objs := audiosense-pi.o
-@@ -36,7 +35,6 @@ snd-soc-fe-pi-audio-objs := fe-pi-audio.
- snd-soc-rpi-simple-soundcard-objs := rpi-simple-soundcard.o
- snd-soc-rpi-wm8804-soundcard-objs := rpi-wm8804-soundcard.o
-
--obj-$(CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER) += snd-soc-3dlab-nano-player.o
- obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD) += snd-soc-googlevoicehat-codec.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
-@@ -45,7 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS)
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
- obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC) += snd-soc-iqaudio-codec.o
- obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
-- obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.o
-+obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.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_AUDIOSENSE_PI) += snd-soc-audiosense-pi.o
--- /dev/null
+From c8bf649a93e00e411c9d52d8ba7902b0984a7c3e Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 7 May 2019 14:27:35 +0100
+Subject: [PATCH 502/725] overlays: Delete the deprecated sdio-1bit overlay
+
+Use dtoverlay=sdio,bus_width=1,gpios_22_25 instead.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 -
+ .../boot/dts/overlays/sdio-1bit-overlay.dts | 63 -------------------
+ 2 files changed, 64 deletions(-)
+ delete mode 100644 arch/arm/boot/dts/overlays/sdio-1bit-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -126,7 +126,6 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ sc16is752-spi1.dtbo \
+ sdhost.dtbo \
+ sdio.dtbo \
+- sdio-1bit.dtbo \
+ sdtweak.dtbo \
+ smi.dtbo \
+ smi-dev.dtbo \
+--- a/arch/arm/boot/dts/overlays/sdio-1bit-overlay.dts
++++ /dev/null
+@@ -1,63 +0,0 @@
+-/dts-v1/;
+-/plugin/;
+-
+-/* Enable 1-bit SDIO from MMC interface via GPIOs 22-25. Includes sdhost overlay. */
+-
+-/{
+- compatible = "brcm,bcm2708";
+-
+- fragment@0 {
+- target = <&mmc>;
+- __overlay__ {
+- status = "disabled";
+- };
+- };
+-
+- fragment@1 {
+- target = <&soc>;
+- __overlay__ {
+- #address-cells = <1>;
+- #size-cells = <1>;
+-
+- sdio_1bit: sdio@7e300000 {
+- compatible = "brcm,bcm2835-mmc",
+- "brcm,bcm2835-sdhci";
+- reg = <0x7e300000 0x100>;
+- interrupts = <2 30>;
+- clocks = <&clocks 28/*BCM2835_CLOCK_EMMC*/>;
+- dmas = <&dma 11>;
+- dma-names = "rx-tx";
+- brcm,overclock-50 = <0>;
+- status = "okay";
+- pinctrl-names = "default";
+- pinctrl-0 = <&sdio_1bit_pins>;
+- non-removable;
+- bus-width = <1>;
+- };
+- };
+- };
+-
+- fragment@2 {
+- target = <&gpio>;
+- __overlay__ {
+- sdio_1bit_pins: sdio_1bit_pins {
+- brcm,pins = <22 23 24 25>;
+- brcm,function = <7>; /* ALT3 = SD1 */
+- brcm,pull = <0 2 2 2>;
+- };
+- };
+- };
+-
+- fragment@3 {
+- target-path = "/aliases";
+- __overlay__ {
+- mmc1 = "/soc/sdio@7e300000";
+- };
+- };
+-
+-
+- __overrides__ {
+- poll_once = <&sdio_1bit>,"non-removable?";
+- sdio_overclock = <&sdio_1bit>,"brcm,overclock-50:0";
+- };
+-};
+++ /dev/null
-From 44cadbedb79dbbae0cea7dd008bcf2583570e883 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Tue, 21 May 2019 15:17:33 +0100
-Subject: [PATCH 503/703] .gitignore: Add *.dtbo explicitly
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- .gitignore | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/.gitignore
-+++ b/.gitignore
-@@ -15,7 +15,8 @@
- *.bin
- *.bz2
- *.c.[012]*.*
--*.dtb*
-+*.dtb
-+*.dtbo
- *.dtb.S
- *.dwo
- *.elf
--- /dev/null
+From 23a2fa493ee4e0734e7cf7402527889a5752548b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 7 May 2019 10:06:04 +0100
+Subject: [PATCH 503/725] overlays: Remove upstream-aux-interrupt overlay
+
+We no longer have a downstream-specific auxilliary interrupt
+driver, so the overlay to disable it is no longer needed.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 -
+ arch/arm/boot/dts/overlays/README | 12 +++----
+ .../upstream-aux-interrupt-overlay.dts | 33 -------------------
+ .../boot/dts/overlays/upstream-overlay.dts | 2 +-
+ 4 files changed, 6 insertions(+), 42 deletions(-)
+ delete mode 100644 arch/arm/boot/dts/overlays/upstream-aux-interrupt-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -151,7 +151,6 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ uart1.dtbo \
+ udrc.dtbo \
+ upstream.dtbo \
+- upstream-aux-interrupt.dtbo \
+ vc4-fkms-v3d.dtbo \
+ vc4-kms-kippah-7inch.dtbo \
+ vc4-kms-v3d.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2206,18 +2206,16 @@ Params: alsaname Name of
+
+
+ Name: upstream
+-Info: Allow usage of downstream .dtb with upstream kernel. Comprises
+- vc4-kms-v3d, dwc2 and upstream-aux-interrupt overlays.
++Info: Allow usage of downstream .dtb with upstream kernel. Comprises the
++ vc4-kms-v3d and dwc2 overlays.
+ Load: dtoverlay=upstream
+ Params: <None>
+
+
+ Name: upstream-aux-interrupt
+-Info: Allow usage of downstream .dtb with upstream kernel by binding AUX
+- devices directly to the shared AUX interrupt line. One of the parts
+- of the 'upstream' overlay
+-Load: dtoverlay=upstream-aux-interrupt
+-Params: <None>
++Info: This overlay has been deprecated and removed because it is no longer
++ necessary.
++Load: <Deprecated>
+
+
+ Name: vc4-fkms-v3d
+--- a/arch/arm/boot/dts/overlays/upstream-aux-interrupt-overlay.dts
++++ /dev/null
+@@ -1,33 +0,0 @@
+-// Overlay for missing AUX interrupt controller
+-// Instead we bind all AUX devices to the generic AUX interrupt line
+-/dts-v1/;
+-/plugin/;
+-
+-/ {
+- compatible = "brcm,bcm2708";
+-
+- fragment@0 {
+- target = <&uart1>;
+- __overlay__ {
+- interrupt-parent = <&intc>;
+- interrupts = <0x1 0x1d>;
+- };
+- };
+-
+- fragment@1 {
+- target = <&spi1>;
+- __overlay__ {
+- interrupt-parent = <&intc>;
+- interrupts = <0x1 0x1d>;
+- };
+- };
+-
+- fragment@2 {
+- target = <&spi2>;
+- __overlay__ {
+- interrupt-parent = <&intc>;
+- interrupts = <0x1 0x1d>;
+- };
+- };
+-};
+-
+--- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
+@@ -1,4 +1,4 @@
+-// redo: ovmerge -c vc4-kms-v3d-overlay.dts,cma-96 dwc2-overlay.dts,dr_mode=otg upstream-aux-interrupt-overlay.dts,
++// redo: ovmerge -c vc4-kms-v3d-overlay.dts,cma-96 dwc2-overlay.dts,dr_mode=otg
+
+ /dts-v1/;
+ /plugin/;
+++ /dev/null
-From 0b83f023796a12b822191c29b4313b161d68fbe7 Mon Sep 17 00:00:00 2001
-From: Marcel Holtmann <marcel@holtmann.org>
-Date: Wed, 22 May 2019 09:05:40 +0200
-Subject: [PATCH 504/703] Bluetooth: Check key sizes only when Secure Simple
- Pairing is enabled
-
-The encryption is only mandatory to be enforced when both sides are using
-Secure Simple Pairing and this means the key size check makes only sense
-in that case.
-
-On legacy Bluetooth 2.0 and earlier devices like mice the encryption was
-optional and thus causing an issue if the key size check is not bound to
-using Secure Simple Pairing.
-
-Fixes: d5bb334a8e17 ("Bluetooth: Align minimum encryption key size for LE and BR/EDR connections")
-Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-Cc: stable@vger.kernel.org
----
- net/bluetooth/hci_conn.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
---- a/net/bluetooth/hci_conn.c
-+++ b/net/bluetooth/hci_conn.c
-@@ -1272,8 +1272,13 @@ int hci_conn_check_link_mode(struct hci_
- return 0;
- }
-
-- if (hci_conn_ssp_enabled(conn) &&
-- !test_bit(HCI_CONN_ENCRYPT, &conn->flags))
-+ /* If Secure Simple Pairing is not enabled, then legacy connection
-+ * setup is used and no encryption or key sizes can be enforced.
-+ */
-+ if (!hci_conn_ssp_enabled(conn))
-+ return 1;
-+
-+ if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
- return 0;
-
- return 1;
--- /dev/null
+From d5c9e73f36c946e403d408b08d7360f227c75837 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 14 May 2019 13:33:05 +0100
+Subject: [PATCH 504/725] overlays: Standardise on compatible="brcm,bcm2835"
+
+Curb the proliferation of compatible string combinations by
+standardising on "brcm,bcm2835" to denote BCM2835 and its descendants.
+
+As nothing in the firmware or kernel is checking overlay compatible
+strings, this should be a purely cosmetic change.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/ads1015-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/ads1115-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/ads7846-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/adv7282m-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/adv728x-m-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts | 2 +-
+ .../boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/allo-digione-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts | 2 +-
+ .../boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts | 2 +-
+ .../dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/applepi-dac-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/at86rf233-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts | 2 +-
+ .../boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/audremap-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/balena-fin-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/dht11-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/dpi18-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/dpi24-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/draws-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/dwc-otg-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/dwc2-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/enc28j60-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/exc3000-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/goodix-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/gpio-fan-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/gpio-ir-tx-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/gpio-key-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/hy28a-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/hy28b-2017-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/hy28b-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/i2c-mux-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/i2s-gpio28-31-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/ilitek251x-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts | 2 +-
+ .../arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/justboom-dac-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/justboom-digi-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/max98357a-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/mbed-dac-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/mcp23017-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/mcp23s17-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/mcp3008-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/mcp3202-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/mcp342x-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/media-center-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/mmc-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/mpu6050-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/mz61581-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/ov5647-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/papirus-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/pibell-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/piglow-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/piscreen-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/piscreen2r-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/pisound-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/pitft22-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/pps-gpio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/pwm-ir-tx-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/qca7000-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/rotary-encoder-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/rpi-dac-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/rpi-display-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/rpi-poe-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/rpi-proto-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/rpi-sense-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/rpi-tv-overlay.dts | 2 +-
+ .../arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/sdhost-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/sdio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/sdtweak-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/smi-nand-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/smi-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi-rtc-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi0-cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/ssd1306-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/superaudioboard-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/sx150x-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/tc358743-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/tinylcd35-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/uart0-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/uart1-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/udrc-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/upstream-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/vga666-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/w1-gpio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/wittypi-overlay.dts | 2 +-
+ 146 files changed, 146 insertions(+), 146 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c>;
+--- a/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts
++++ b/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/ads1015-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ads1015-overlay.dts
+@@ -5,7 +5,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+ /* ----------- ADS1015 ------------ */
+ fragment@0 {
+ target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/ads1115-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ads1115-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/ads7846-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ads7846-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/adv7282m-overlay.dts
++++ b/arch/arm/boot/dts/overlays/adv7282m-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c_vc>;
+--- a/arch/arm/boot/dts/overlays/adv728x-m-overlay.dts
++++ b/arch/arm/boot/dts/overlays/adv728x-m-overlay.dts
+@@ -5,7 +5,7 @@
+ #include "adv7282m-overlay.dts"
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ // Fragment numbers deliberately high to avoid conflicts with the
+ // included adv7282m overlay file.
+--- a/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts
++++ b/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/clocks";
+--- a/arch/arm/boot/dts/overlays/allo-digione-overlay.dts
++++ b/arch/arm/boot/dts/overlays/allo-digione-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts
+@@ -13,7 +13,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/applepi-dac-overlay.dts
++++ b/arch/arm/boot/dts/overlays/applepi-dac-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&sound>;
+--- a/arch/arm/boot/dts/overlays/at86rf233-overlay.dts
++++ b/arch/arm/boot/dts/overlays/at86rf233-overlay.dts
+@@ -4,7 +4,7 @@
+ /* Overlay for Atmel AT86RF233 IEEE 802.15.4 WPAN transceiver on spi0.0 */
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
+@@ -5,7 +5,7 @@
+ #include <dt-bindings/gpio/gpio.h>
+
+ / {
+- compatible = "brcm,bcm2837", "brcm,bcm2836", "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/audremap-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audremap-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&audio_pins>;
+--- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
++++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&mmc>;
+--- a/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts
++++ b/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/dht11-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dht11-overlay.dts
+@@ -5,7 +5,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/";
+--- a/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts
+@@ -8,7 +8,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts
+@@ -9,7 +9,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&sound>;
+--- a/arch/arm/boot/dts/overlays/dpi18-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dpi18-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ // There is no DPI driver module, but we need a platform device
+ // node (that doesn't already use pinctrl) to hang the pinctrl
+--- a/arch/arm/boot/dts/overlays/dpi24-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dpi24-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ // There is no DPI driver module, but we need a platform device
+ // node (that doesn't already use pinctrl) to hang the pinctrl
+--- a/arch/arm/boot/dts/overlays/draws-overlay.dts
++++ b/arch/arm/boot/dts/overlays/draws-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+ fragment@0 {
+ target = <&i2s>;
+ __overlay__ {
+--- a/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&usb>;
+--- a/arch/arm/boot/dts/overlays/dwc2-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dwc2-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&usb>;
+--- a/arch/arm/boot/dts/overlays/enc28j60-overlay.dts
++++ b/arch/arm/boot/dts/overlays/enc28j60-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts
++++ b/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi2>;
+--- a/arch/arm/boot/dts/overlays/exc3000-overlay.dts
++++ b/arch/arm/boot/dts/overlays/exc3000-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&clocks>;
+--- a/arch/arm/boot/dts/overlays/goodix-overlay.dts
++++ b/arch/arm/boot/dts/overlays/goodix-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts
++++ b/arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts
+@@ -38,7 +38,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/";
+--- a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/";
+--- a/arch/arm/boot/dts/overlays/gpio-ir-tx-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-ir-tx-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/gpio-key-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-key-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ // Configure the gpio pin controller
+--- a/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/";
+--- a/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
+@@ -10,7 +10,7 @@
+ // note that GPIO3 has an external pullup on at least some boards).
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ // Configure the gpio pin controller
+--- a/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/clocks";
+--- a/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/clocks";
+--- a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/hy28a-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hy28a-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/hy28b-2017-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hy28b-2017-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/hy28b-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hy28b-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&sound>;
+--- a/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/";
+--- a/arch/arm/boot/dts/overlays/i2c-mux-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-mux-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/";
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts
+@@ -9,7 +9,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c0>;
+--- a/arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts
+@@ -9,7 +9,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c1>;
+--- a/arch/arm/boot/dts/overlays/i2s-gpio28-31-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2s-gpio28-31-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s_pins>;
+--- a/arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts
++++ b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts
++++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts
++++ b/arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts
+@@ -13,7 +13,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ // disable spi-dev on spi0.0
+ fragment@0 {
+--- a/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts
++++ b/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/max98357a-overlay.dts
++++ b/arch/arm/boot/dts/overlays/max98357a-overlay.dts
+@@ -8,7 +8,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ /* Enable I2S */
+ fragment@0 {
+--- a/arch/arm/boot/dts/overlays/mbed-dac-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mbed-dac-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c1>;
+--- a/arch/arm/boot/dts/overlays/mcp23s17-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp23s17-overlay.dts
+@@ -20,7 +20,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ // disable spi-dev on spi0.0
+ fragment@0 {
+--- a/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+ /* disable spi-dev for spi0.0 */
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+ /* disable spi-dev for spi0.1 */
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/mcp3008-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp3008-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spidev0>;
+--- a/arch/arm/boot/dts/overlays/mcp3202-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp3202-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spidev0>;
+--- a/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c1>;
+--- a/arch/arm/boot/dts/overlays/media-center-overlay.dts
++++ b/arch/arm/boot/dts/overlays/media-center-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/mmc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mmc-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&mmc>;
+--- a/arch/arm/boot/dts/overlays/mpu6050-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mpu6050-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c1>;
+--- a/arch/arm/boot/dts/overlays/mz61581-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mz61581-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c_vc>;
+--- a/arch/arm/boot/dts/overlays/papirus-overlay.dts
++++ b/arch/arm/boot/dts/overlays/papirus-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
+@@ -11,7 +11,7 @@
+ */
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&act_led>;
+--- a/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
+@@ -9,7 +9,7 @@
+ */
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&uart1>;
+--- a/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&mmc>;
+--- a/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
+@@ -16,7 +16,7 @@
+ */
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&uart0>;
+--- a/arch/arm/boot/dts/overlays/pibell-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pibell-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/";
+--- a/arch/arm/boot/dts/overlays/piglow-overlay.dts
++++ b/arch/arm/boot/dts/overlays/piglow-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/piscreen-overlay.dts
++++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/piscreen2r-overlay.dts
++++ b/arch/arm/boot/dts/overlays/piscreen2r-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/pisound-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts
+@@ -23,7 +23,7 @@
+ #include <dt-bindings/gpio/gpio.h>
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/pitft22-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pitft22-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+ fragment@0 {
+ target-path = "/";
+ __overlay__ {
+--- a/arch/arm/boot/dts/overlays/pwm-ir-tx-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pwm-ir-tx-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/qca7000-overlay.dts
++++ b/arch/arm/boot/dts/overlays/qca7000-overlay.dts
+@@ -5,7 +5,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spidev0>;
+--- a/arch/arm/boot/dts/overlays/rotary-encoder-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rotary-encoder-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/";
+--- a/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
+@@ -6,7 +6,7 @@
+ #include <dt-bindings/mfd/arizona.h>
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/rpi-display-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/";
+--- a/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
+@@ -5,7 +5,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/";
+--- a/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c1>;
+--- a/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spidev0>;
+--- a/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c_arm>;
+--- a/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/sdhost-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts
+@@ -4,7 +4,7 @@
+ /* Provide backwards compatible aliases for the old sdhost dtparams. */
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&sdhost>;
+--- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
+@@ -4,7 +4,7 @@
+ /* Enable SDIO from MMC interface via GPIOs 22-27. Includes sdhost overlay. */
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&mmc>;
+--- a/arch/arm/boot/dts/overlays/sdtweak-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sdtweak-overlay.dts
+@@ -4,7 +4,7 @@
+ /* Provide backwards compatible aliases for the old sdhost dtparams. */
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&sdhost>;
+--- a/arch/arm/boot/dts/overlays/smi-nand-overlay.dts
++++ b/arch/arm/boot/dts/overlays/smi-nand-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&smi>;
+--- a/arch/arm/boot/dts/overlays/smi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/smi-overlay.dts
+@@ -5,7 +5,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&smi>;
+--- a/arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spidev0>;
+--- a/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts
+@@ -3,7 +3,7 @@
+
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0_cs_pins>;
+--- a/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts
+@@ -3,7 +3,7 @@
+
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts
+@@ -3,7 +3,7 @@
+
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts
+@@ -3,7 +3,7 @@
+
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts
+@@ -3,7 +3,7 @@
+
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts
+@@ -3,7 +3,7 @@
+
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts
++++ b/arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts
+@@ -3,7 +3,7 @@
+
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&gpio>;
+--- a/arch/arm/boot/dts/overlays/ssd1306-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ssd1306-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2718";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c1>;
+--- a/arch/arm/boot/dts/overlays/superaudioboard-overlay.dts
++++ b/arch/arm/boot/dts/overlays/superaudioboard-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&sound>;
+--- a/arch/arm/boot/dts/overlays/sx150x-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sx150x-overlay.dts
+@@ -22,7 +22,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ // Enable I2C#0 interface
+ fragment@0 {
+--- a/arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts
+@@ -5,7 +5,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2s>;
+--- a/arch/arm/boot/dts/overlays/tc358743-overlay.dts
++++ b/arch/arm/boot/dts/overlays/tc358743-overlay.dts
+@@ -4,7 +4,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&i2c_vc>;
+--- a/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
++++ b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
+@@ -24,7 +24,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
++++ b/arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
+@@ -8,7 +8,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&spi0>;
+--- a/arch/arm/boot/dts/overlays/uart0-overlay.dts
++++ b/arch/arm/boot/dts/overlays/uart0-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&uart0>;
+--- a/arch/arm/boot/dts/overlays/uart1-overlay.dts
++++ b/arch/arm/boot/dts/overlays/uart1-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&uart1>;
+--- a/arch/arm/boot/dts/overlays/udrc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/udrc-overlay.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+ fragment@0 {
+ target = <&i2s>;
+ __overlay__ {
+--- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
+@@ -6,7 +6,7 @@
+ #include <dt-bindings/clock/bcm2835.h>
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+ fragment@0 {
+ target-path = "/chosen";
+ __dormant__ {
+--- a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
+@@ -6,7 +6,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/chosen";
+--- a/arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts
+@@ -8,7 +8,7 @@
+ #include <dt-bindings/pinctrl/bcm2835.h>
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/";
+--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
+@@ -8,7 +8,7 @@
+ #include <dt-bindings/clock/bcm2835.h>
+
+ / {
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/chosen";
+--- a/arch/arm/boot/dts/overlays/vga666-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vga666-overlay.dts
+@@ -2,7 +2,7 @@
+ /plugin/;
+
+ /{
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ // There is no VGA driver module, but we need a platform device
+ // node (that doesn't already use pinctrl) to hang the pinctrl
+--- a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/";
+--- a/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
++++ b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
+@@ -3,7 +3,7 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2708";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target-path = "/";
+--- a/arch/arm/boot/dts/overlays/wittypi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/wittypi-overlay.dts
+@@ -8,7 +8,7 @@
+
+ / {
+
+- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
++ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+ target = <&leds>;
+++ /dev/null
-From 6ed82a6ca0e146b20e1d09dc7ec9d31706fc85c5 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 7 May 2019 17:23:41 +0100
-Subject: [PATCH 505/703] usb: dwc_otg: Clean up interrupt claiming code
-
-The FIQ/IRQ interrupt number identification code is scattered through
-the dwc_otg driver. Rationalise it, simplifying the code and solving
-an existing issue.
-
-See: https://github.com/raspberrypi/linux/issues/2612
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/usb/host/dwc_otg/dwc_otg_driver.c | 18 +++++++++-----
- drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 10 +++-----
- drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 6 +++++
- drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 26 +++-----------------
- 4 files changed, 25 insertions(+), 35 deletions(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
-@@ -624,11 +624,7 @@ static int dwc_otg_driver_remove(
- * Free the IRQ
- */
- if (otg_dev->common_irq_installed) {
--#ifdef PLATFORM_INTERFACE
-- free_irq(platform_get_irq(_dev, 0), otg_dev);
--#else
-- free_irq(_dev->irq, otg_dev);
--#endif
-+ free_irq(otg_dev->os_dep.irq_num, otg_dev);
- } else {
- DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__);
- return REM_RETVAL(-ENXIO);
-@@ -905,7 +901,9 @@ static int dwc_otg_driver_probe(
- */
-
- #if defined(PLATFORM_INTERFACE)
-- devirq = platform_get_irq(_dev, fiq_enable ? 0 : 1);
-+ devirq = platform_get_irq_byname(_dev, fiq_enable ? "soft" : "usb");
-+ if (devirq < 0)
-+ devirq = platform_get_irq(_dev, fiq_enable ? 0 : 1);
- #else
- devirq = _dev->irq;
- #endif
-@@ -922,6 +920,14 @@ static int dwc_otg_driver_probe(
- } else {
- dwc_otg_device->common_irq_installed = 1;
- }
-+ dwc_otg_device->os_dep.irq_num = devirq;
-+ dwc_otg_device->os_dep.fiq_num = -EINVAL;
-+ if (fiq_enable) {
-+ int devfiq = platform_get_irq_byname(_dev, "usb");
-+ if (devfiq < 0)
-+ devfiq = platform_get_irq(_dev, 1);
-+ dwc_otg_device->os_dep.fiq_num = devfiq;
-+ }
-
- #ifndef IRQF_TRIGGER_LOW
- #if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-@@ -492,7 +492,7 @@ static void hcd_init_fiq(void *cookie)
- #endif
- // Enable FIQ interrupt from USB peripheral
- #ifdef CONFIG_ARM64
-- irq = platform_get_irq(otg_dev->os_dep.platformdev, 1);
-+ irq = otg_dev->os_dep.fiq_num;
-
- if (irq < 0) {
- DWC_ERROR("Can't get SIM-FIQ irq");
-@@ -509,7 +509,7 @@ static void hcd_init_fiq(void *cookie)
- simfiq_irq = irq;
- #else
- #ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
-- irq = platform_get_irq(otg_dev->os_dep.platformdev, 1);
-+ irq = otg_dev->os_dep.fiq_num;
- #else
- irq = INTERRUPT_VC_USB;
- #endif
-@@ -626,11 +626,7 @@ int hcd_init(dwc_bus_dev_t *_dev)
- * allocates the DMA buffer pool, registers the USB bus, requests the
- * IRQ line, and calls hcd_start method.
- */
--#ifdef PLATFORM_INTERFACE
-- retval = usb_add_hcd(hcd, platform_get_irq(_dev, fiq_enable ? 0 : 1), IRQF_SHARED);
--#else
-- retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED);
--#endif
-+ retval = usb_add_hcd(hcd, otg_dev->os_dep.irq_num, IRQF_SHARED);
- if (retval < 0) {
- goto error2;
- }
---- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
-@@ -102,6 +102,12 @@ typedef struct os_dependent {
- /** Base address for MPHI peripheral */
- void *mphi_base;
-
-+ /** IRQ number (<0 if not valid) */
-+ int irq_num;
-+
-+ /** FIQ number (<0 if not valid) */
-+ int fiq_num;
-+
- #ifdef LM_INTERFACE
- struct lm_device *lmdev;
- #elif defined(PCI_INTERFACE)
---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
-@@ -1224,30 +1224,16 @@ int pcd_init(dwc_bus_dev_t *_dev)
- /*
- * Setup interupt handler
- */
--#ifdef PLATFORM_INTERFACE
- DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
-- platform_get_irq(_dev, fiq_enable ? 0 : 1));
-- retval = request_irq(platform_get_irq(_dev, fiq_enable ? 0 : 1), dwc_otg_pcd_irq,
-+ otg_dev->os_dep.irq_num);
-+ retval = request_irq(otg_dev->os_dep.irq_num, dwc_otg_pcd_irq,
- IRQF_SHARED, gadget_wrapper->gadget.name,
- otg_dev->pcd);
- if (retval != 0) {
-- DWC_ERROR("request of irq%d failed\n",
-- platform_get_irq(_dev, fiq_enable ? 0 : 1));
-+ DWC_ERROR("request of irq%d failed\n", otg_dev->os_dep.irq_num);
- free_wrapper(gadget_wrapper);
- return -EBUSY;
- }
--#else
-- DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
-- _dev->irq);
-- retval = request_irq(_dev->irq, dwc_otg_pcd_irq,
-- IRQF_SHARED | IRQF_DISABLED,
-- gadget_wrapper->gadget.name, otg_dev->pcd);
-- if (retval != 0) {
-- DWC_ERROR("request of irq%d failed\n", _dev->irq);
-- free_wrapper(gadget_wrapper);
-- return -EBUSY;
-- }
--#endif
-
- dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);
-
-@@ -1267,11 +1253,7 @@ void pcd_remove(dwc_bus_dev_t *_dev)
- /*
- * Free the IRQ
- */
--#ifdef PLATFORM_INTERFACE
-- free_irq(platform_get_irq(_dev, 0), pcd);
--#else
-- free_irq(_dev->irq, pcd);
--#endif
-+ free_irq(otg_dev->os_dep.irq_num, pcd);
- dwc_otg_pcd_remove(otg_dev->pcd);
- free_wrapper(gadget_wrapper);
- otg_dev->pcd = 0;
--- /dev/null
+From 4014add8e56b0169d767f6feb99ab9387bdd1c2b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 22 May 2019 12:58:47 +0100
+Subject: [PATCH 505/725] vc4: Remove interrupt and DMA trampling
+
+As part of the effort to clean up the overlays, remove the interrupt
+and DMA mask declarations from the vc4 overlays which just duplicate
+that which is in the base DTBs.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ .../boot/dts/overlays/vc4-fkms-v3d-overlay.dts | 8 --------
+ .../boot/dts/overlays/vc4-kms-v3d-overlay.dts | 18 ++----------------
+ 2 files changed, 2 insertions(+), 24 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
+@@ -60,7 +60,6 @@
+ fragment@7 {
+ target = <&v3d>;
+ __overlay__ {
+- interrupts = <1 10>;
+ status = "okay";
+ };
+ };
+@@ -72,13 +71,6 @@
+ };
+ };
+
+- fragment@9 {
+- target-path = "/soc/dma";
+- __overlay__ {
+- brcm,dma-channel-mask = <0x7f35>;
+- };
+- };
+-
+ __overrides__ {
+ cma-256 = <0>,"+0-1-2-3-4";
+ cma-192 = <0>,"-0+1-2-3-4";
+--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
+@@ -62,7 +62,6 @@
+ fragment@7 {
+ target = <&pixelvalve0>;
+ __overlay__ {
+- interrupts = <2 13>; /* pwa0 */
+ status = "okay";
+ };
+ };
+@@ -70,7 +69,6 @@
+ fragment@8 {
+ target = <&pixelvalve1>;
+ __overlay__ {
+- interrupts = <2 14>; /* pwa1 */
+ status = "okay";
+ };
+ };
+@@ -78,7 +76,6 @@
+ fragment@9 {
+ target = <&pixelvalve2>;
+ __overlay__ {
+- interrupts = <2 10>; /* pixelvalve */
+ status = "okay";
+ };
+ };
+@@ -86,7 +83,6 @@
+ fragment@10 {
+ target = <&hvs>;
+ __overlay__ {
+- interrupts = <2 1>;
+ status = "okay";
+ };
+ };
+@@ -94,7 +90,6 @@
+ fragment@11 {
+ target = <&hdmi>;
+ __overlay__ {
+- interrupts = <2 8>, <2 9>;
+ status = "okay";
+ };
+ };
+@@ -102,7 +97,6 @@
+ fragment@12 {
+ target = <&v3d>;
+ __overlay__ {
+- interrupts = <1 10>;
+ status = "okay";
+ };
+ };
+@@ -115,14 +109,6 @@
+ };
+
+ fragment@14 {
+- target-path = "/soc/dma";
+- __overlay__ {
+- brcm,dma-channel-mask = <0x7f35>;
+- };
+- };
+-
+-
+- fragment@15 {
+ target = <&clocks>;
+ __overlay__ {
+ claim-clocks = <
+@@ -134,14 +120,14 @@
+ };
+ };
+
+- fragment@16 {
++ fragment@15 {
+ target = <&vec>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+- fragment@17 {
++ fragment@16 {
+ target = <&txp>;
+ __overlay__ {
+ status = "okay";
--- /dev/null
+From 7530f75c6f8207751821a72a5da3ee8d275921f3 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 7 May 2019 14:29:38 +0100
+Subject: [PATCH 506/725] BCM270X_DT: Add non-removable clone of mmc node
+
+non-removable is a boolean property, and as such can't be unset by an
+overlay if it is set in a base DTB. Until now the workaround for this
+problem has been for overlays to clone non-removable nodes without
+the offending property, but this involves a lot of unnecessary
+replication. Instead, add a clone of the mmc node with non-removable
+already set to the base DTB, selecting the required version using
+the status properties.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2708-rpi-0-w.dts | 4 +--
+ arch/arm/boot/dts/bcm2708-rpi.dtsi | 3 +-
+ arch/arm/boot/dts/bcm270x.dtsi | 13 ++++++++
+ arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 5 ++--
+ arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 5 ++--
+ arch/arm/boot/dts/overlays/mmc-overlay.dts | 7 +++++
+ arch/arm/boot/dts/overlays/sdio-overlay.dts | 33 +++++++--------------
+ 7 files changed, 38 insertions(+), 32 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
+@@ -14,6 +14,7 @@
+ aliases {
+ serial0 = &uart1;
+ serial1 = &uart0;
++ mmc1 = &mmcnr;
+ };
+ };
+
+@@ -73,10 +74,9 @@
+ };
+ };
+
+-&mmc {
++&mmcnr {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio_pins>;
+- non-removable;
+ bus-width = <4>;
+ status = "okay";
+ };
+--- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
+@@ -118,7 +118,8 @@
+ sd_force_pio = <&sdhost>,"brcm,force-pio?";
+ sd_pio_limit = <&sdhost>,"brcm,pio-limit:0";
+ sd_debug = <&sdhost>,"brcm,debug";
+- sdio_overclock = <&mmc>,"brcm,overclock-50:0";
++ sdio_overclock = <&mmc>,"brcm,overclock-50:0",
++ <&mmcnr>,"brcm,overclock-50:0";
+ axiperf = <&axiperf>,"status";
+ };
+ };
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -79,6 +79,19 @@
+ status = "disabled";
+ };
+
++ /* A clone of mmc but with non-removable set */
++ mmcnr: mmcnr@7e300000 {
++ compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci";
++ reg = <0x7e300000 0x100>;
++ interrupts = <2 30>;
++ clocks = <&clocks BCM2835_CLOCK_EMMC>;
++ dmas = <&dma 11>;
++ dma-names = "rx-tx";
++ brcm,overclock-50 = <0>;
++ non-removable;
++ status = "disabled";
++ };
++
+ hvs: hvs@7e400000 {
+ /* Add alias */
+ status = "disabled";
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
+@@ -15,6 +15,7 @@
+ aliases {
+ serial0 = &uart1;
+ serial1 = &uart0;
++ mmc1 = &mmcnr;
+ };
+ };
+
+@@ -74,13 +75,11 @@
+ };
+ };
+
+-&mmc {
++&mmcnr {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio_pins>;
+- non-removable;
+ bus-width = <4>;
+ status = "okay";
+- brcm,overclock-50 = <0>;
+ };
+
+ &firmware {
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
+@@ -15,6 +15,7 @@
+ aliases {
+ serial0 = &uart1;
+ serial1 = &uart0;
++ mmc1 = &mmcnr;
+ };
+ };
+
+@@ -74,13 +75,11 @@
+ };
+ };
+
+-&mmc {
++&mmcnr {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio_pins>;
+- non-removable;
+ bus-width = <4>;
+ status = "okay";
+- brcm,overclock-50 = <0>;
+ };
+
+ &soc {
+--- a/arch/arm/boot/dts/overlays/mmc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mmc-overlay.dts
+@@ -33,6 +33,13 @@
+ };
+ };
+
++ fragment@3 {
++ target = <&mmcnr>;
++ __overlay__ {
++ status = "disabled";
++ };
++ };
++
+ __overrides__ {
+ overclock_50 = <&frag0>,"brcm,overclock-50:0";
+ };
+--- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
+@@ -1,39 +1,26 @@
+ /dts-v1/;
+ /plugin/;
+
+-/* Enable SDIO from MMC interface via GPIOs 22-27. Includes sdhost overlay. */
++/* Enable SDIO from MMC interface via various GPIO groups */
+
+ /{
+ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+- target = <&mmc>;
++ target = <&mmcnr>;
+ __overlay__ {
+ status = "disabled";
+ };
+ };
+
+ fragment@1 {
+- target = <&soc>;
+- __overlay__ {
+- #address-cells = <1>;
+- #size-cells = <1>;
+-
+- sdio_ovl: sdio@7e300000 {
+- compatible = "brcm,bcm2835-mmc",
+- "brcm,bcm2835-sdhci";
+- reg = <0x7e300000 0x100>;
+- interrupts = <2 30>;
+- clocks = <&clocks 28/*BCM2835_CLOCK_EMMC*/>;
+- dmas = <&dma 11>;
+- dma-names = "rx-tx";
+- brcm,overclock-50 = <0>;
+- status = "okay";
+- pinctrl-names = "default";
+- pinctrl-0 = <&sdio_ovl_pins>;
+- non-removable;
+- bus-width = <4>;
+- };
++ target = <&mmc>;
++ sdio_ovl: __overlay__ {
++ pinctrl-0 = <&sdio_ovl_pins>;
++ pinctrl-names = "default";
++ non-removable;
++ bus-width = <4>;
++ status = "okay";
+ };
+ };
+
+@@ -75,7 +62,7 @@
+ fragment@6 {
+ target-path = "/aliases";
+ __overlay__ {
+- mmc1 = "/soc/sdio@7e300000";
++ mmc1 = "/soc/mmc@7e300000";
+ };
+ };
+
+++ /dev/null
-From 039ab199d862424e77a9f5a8b431453a36d6af7c Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 7 May 2019 14:27:35 +0100
-Subject: [PATCH 506/703] overlays: Delete the deprecated sdio-1bit overlay
-
-Use dtoverlay=sdio,bus_width=1,gpios_22_25 instead.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/Makefile | 1 -
- .../boot/dts/overlays/sdio-1bit-overlay.dts | 63 -------------------
- 2 files changed, 64 deletions(-)
- delete mode 100644 arch/arm/boot/dts/overlays/sdio-1bit-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -126,7 +126,6 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- sc16is752-spi1.dtbo \
- sdhost.dtbo \
- sdio.dtbo \
-- sdio-1bit.dtbo \
- sdtweak.dtbo \
- smi.dtbo \
- smi-dev.dtbo \
---- a/arch/arm/boot/dts/overlays/sdio-1bit-overlay.dts
-+++ /dev/null
-@@ -1,63 +0,0 @@
--/dts-v1/;
--/plugin/;
--
--/* Enable 1-bit SDIO from MMC interface via GPIOs 22-25. Includes sdhost overlay. */
--
--/{
-- compatible = "brcm,bcm2708";
--
-- fragment@0 {
-- target = <&mmc>;
-- __overlay__ {
-- status = "disabled";
-- };
-- };
--
-- fragment@1 {
-- target = <&soc>;
-- __overlay__ {
-- #address-cells = <1>;
-- #size-cells = <1>;
--
-- sdio_1bit: sdio@7e300000 {
-- compatible = "brcm,bcm2835-mmc",
-- "brcm,bcm2835-sdhci";
-- reg = <0x7e300000 0x100>;
-- interrupts = <2 30>;
-- clocks = <&clocks 28/*BCM2835_CLOCK_EMMC*/>;
-- dmas = <&dma 11>;
-- dma-names = "rx-tx";
-- brcm,overclock-50 = <0>;
-- status = "okay";
-- pinctrl-names = "default";
-- pinctrl-0 = <&sdio_1bit_pins>;
-- non-removable;
-- bus-width = <1>;
-- };
-- };
-- };
--
-- fragment@2 {
-- target = <&gpio>;
-- __overlay__ {
-- sdio_1bit_pins: sdio_1bit_pins {
-- brcm,pins = <22 23 24 25>;
-- brcm,function = <7>; /* ALT3 = SD1 */
-- brcm,pull = <0 2 2 2>;
-- };
-- };
-- };
--
-- fragment@3 {
-- target-path = "/aliases";
-- __overlay__ {
-- mmc1 = "/soc/sdio@7e300000";
-- };
-- };
--
--
-- __overrides__ {
-- poll_once = <&sdio_1bit>,"non-removable?";
-- sdio_overclock = <&sdio_1bit>,"brcm,overclock-50:0";
-- };
--};
--- /dev/null
+From 7a56bb870785b5cb85a5902c32b23f956f1a1287 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 8 May 2019 10:08:31 +0100
+Subject: [PATCH 507/725] BCM270X_DT: usb: Refactor DTS and overlays
+
+Move the IRQ interrupt declaration in the usb node before the FIQ
+declaration, so that the dwc2 driver will find it. Name the
+interrupts appropriately so that the dwc_otg driver can still find
+them. Then remove the interrupt rewriting from the overlays.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm270x.dtsi | 6 ++++--
+ arch/arm/boot/dts/overlays/dwc-otg-overlay.dts | 6 ------
+ arch/arm/boot/dts/overlays/dwc2-overlay.dts | 2 --
+ 3 files changed, 4 insertions(+), 10 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -131,8 +131,10 @@
+ compatible = "brcm,bcm2708-usb";
+ reg = <0x7e980000 0x10000>,
+ <0x7e006000 0x1000>;
+- interrupts = <2 0>,
+- <1 9>;
++ interrupt-names = "usb",
++ "soft";
++ interrupts = <1 9>,
++ <2 0>;
+ };
+
+ v3d@7ec00000 { /* vd3 */
+--- a/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
+@@ -6,14 +6,8 @@
+
+ fragment@0 {
+ target = <&usb>;
+- #address-cells = <1>;
+- #size-cells = <1>;
+ __overlay__ {
+ compatible = "brcm,bcm2708-usb";
+- reg = <0x7e980000 0x10000>,
+- <0x7e006000 0x1000>;
+- interrupts = <2 0>,
+- <1 9>;
+ status = "okay";
+ };
+ };
+--- a/arch/arm/boot/dts/overlays/dwc2-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dwc2-overlay.dts
+@@ -10,8 +10,6 @@
+ #size-cells = <1>;
+ dwc2_usb: __overlay__ {
+ compatible = "brcm,bcm2835-usb";
+- reg = <0x7e980000 0x10000>;
+- interrupts = <1 9>;
+ dr_mode = "otg";
+ g-np-tx-fifo-size = <32>;
+ g-rx-fifo-size = <256>;
+++ /dev/null
-From 1bb35a0debe9afff8113fe7727020e22a6160fd2 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 7 May 2019 10:06:04 +0100
-Subject: [PATCH 507/703] overlays: Remove upstream-aux-interrupt overlay
-
-We no longer have a downstream-specific auxilliary interrupt
-driver, so the overlay to disable it is no longer needed.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/Makefile | 1 -
- arch/arm/boot/dts/overlays/README | 12 +++----
- .../upstream-aux-interrupt-overlay.dts | 33 -------------------
- .../boot/dts/overlays/upstream-overlay.dts | 2 +-
- 4 files changed, 6 insertions(+), 42 deletions(-)
- delete mode 100644 arch/arm/boot/dts/overlays/upstream-aux-interrupt-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -151,7 +151,6 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- uart1.dtbo \
- udrc.dtbo \
- upstream.dtbo \
-- upstream-aux-interrupt.dtbo \
- vc4-fkms-v3d.dtbo \
- vc4-kms-kippah-7inch.dtbo \
- vc4-kms-v3d.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -2206,18 +2206,16 @@ Params: alsaname Name of
-
-
- Name: upstream
--Info: Allow usage of downstream .dtb with upstream kernel. Comprises
-- vc4-kms-v3d, dwc2 and upstream-aux-interrupt overlays.
-+Info: Allow usage of downstream .dtb with upstream kernel. Comprises the
-+ vc4-kms-v3d and dwc2 overlays.
- Load: dtoverlay=upstream
- Params: <None>
-
-
- Name: upstream-aux-interrupt
--Info: Allow usage of downstream .dtb with upstream kernel by binding AUX
-- devices directly to the shared AUX interrupt line. One of the parts
-- of the 'upstream' overlay
--Load: dtoverlay=upstream-aux-interrupt
--Params: <None>
-+Info: This overlay has been deprecated and removed because it is no longer
-+ necessary.
-+Load: <Deprecated>
-
-
- Name: vc4-fkms-v3d
---- a/arch/arm/boot/dts/overlays/upstream-aux-interrupt-overlay.dts
-+++ /dev/null
-@@ -1,33 +0,0 @@
--// Overlay for missing AUX interrupt controller
--// Instead we bind all AUX devices to the generic AUX interrupt line
--/dts-v1/;
--/plugin/;
--
--/ {
-- compatible = "brcm,bcm2708";
--
-- fragment@0 {
-- target = <&uart1>;
-- __overlay__ {
-- interrupt-parent = <&intc>;
-- interrupts = <0x1 0x1d>;
-- };
-- };
--
-- fragment@1 {
-- target = <&spi1>;
-- __overlay__ {
-- interrupt-parent = <&intc>;
-- interrupts = <0x1 0x1d>;
-- };
-- };
--
-- fragment@2 {
-- target = <&spi2>;
-- __overlay__ {
-- interrupt-parent = <&intc>;
-- interrupts = <0x1 0x1d>;
-- };
-- };
--};
--
---- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
-@@ -1,4 +1,4 @@
--// redo: ovmerge -c vc4-kms-v3d-overlay.dts,cma-96 dwc2-overlay.dts,dr_mode=otg upstream-aux-interrupt-overlay.dts,
-+// redo: ovmerge -c vc4-kms-v3d-overlay.dts,cma-96 dwc2-overlay.dts,dr_mode=otg
-
- /dts-v1/;
- /plugin/;
+++ /dev/null
-From 72ce89af10e9f0d504f9c31a137928464b269cfb Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 14 May 2019 13:33:05 +0100
-Subject: [PATCH 508/703] overlays: Standardise on compatible="brcm,bcm2835"
-
-Curb the proliferation of compatible string combinations by
-standardising on "brcm,bcm2835" to denote BCM2835 and its descendants.
-
-As nothing in the firmware or kernel is checking overlay compatible
-strings, this should be a purely cosmetic change.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/ads1015-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/ads1115-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/ads7846-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/adv7282m-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/adv728x-m-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts | 2 +-
- .../boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/allo-digione-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts | 2 +-
- .../boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts | 2 +-
- .../dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/applepi-dac-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/at86rf233-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts | 2 +-
- .../boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/audremap-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/balena-fin-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/dht11-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/dpi18-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/dpi24-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/draws-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/dwc-otg-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/dwc2-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/enc28j60-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/exc3000-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/goodix-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/gpio-fan-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/gpio-ir-tx-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/gpio-key-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/hy28a-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/hy28b-2017-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/hy28b-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/i2c-mux-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/i2s-gpio28-31-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/ilitek251x-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts | 2 +-
- .../arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/justboom-dac-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/justboom-digi-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/max98357a-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/mbed-dac-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/mcp23017-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/mcp23s17-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/mcp3008-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/mcp3202-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/mcp342x-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/media-center-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/mmc-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/mpu6050-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/mz61581-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/ov5647-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/papirus-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/pibell-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/piglow-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/piscreen-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/piscreen2r-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/pisound-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/pitft22-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/pps-gpio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/pwm-ir-tx-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/qca7000-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/rotary-encoder-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/rpi-dac-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/rpi-display-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/rpi-poe-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/rpi-proto-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/rpi-sense-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/rpi-tv-overlay.dts | 2 +-
- .../arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/sdhost-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/sdio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/sdtweak-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/smi-nand-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/smi-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi-rtc-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi0-cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/ssd1306-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/superaudioboard-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/sx150x-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/tc358743-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/tinylcd35-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/uart0-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/uart1-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/udrc-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/upstream-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/vga666-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/w1-gpio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/wittypi-overlay.dts | 2 +-
- 146 files changed, 146 insertions(+), 146 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c>;
---- a/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/ads1015-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/ads1015-overlay.dts
-@@ -5,7 +5,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
- /* ----------- ADS1015 ------------ */
- fragment@0 {
- target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/ads1115-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/ads1115-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/ads7846-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/ads7846-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/adv7282m-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/adv7282m-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c_vc>;
---- a/arch/arm/boot/dts/overlays/adv728x-m-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/adv728x-m-overlay.dts
-@@ -5,7 +5,7 @@
- #include "adv7282m-overlay.dts"
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- // Fragment numbers deliberately high to avoid conflicts with the
- // included adv7282m overlay file.
---- a/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/clocks";
---- a/arch/arm/boot/dts/overlays/allo-digione-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/allo-digione-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts
-@@ -13,7 +13,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/applepi-dac-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/applepi-dac-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&sound>;
---- a/arch/arm/boot/dts/overlays/at86rf233-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/at86rf233-overlay.dts
-@@ -4,7 +4,7 @@
- /* Overlay for Atmel AT86RF233 IEEE 802.15.4 WPAN transceiver on spi0.0 */
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts
-@@ -5,7 +5,7 @@
- #include <dt-bindings/gpio/gpio.h>
-
- / {
-- compatible = "brcm,bcm2837", "brcm,bcm2836", "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/audremap-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/audremap-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&audio_pins>;
---- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&mmc>;
---- a/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/dht11-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dht11-overlay.dts
-@@ -5,7 +5,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/";
---- a/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts
-@@ -8,7 +8,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts
-@@ -9,7 +9,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&sound>;
---- a/arch/arm/boot/dts/overlays/dpi18-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dpi18-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- // There is no DPI driver module, but we need a platform device
- // node (that doesn't already use pinctrl) to hang the pinctrl
---- a/arch/arm/boot/dts/overlays/dpi24-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dpi24-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- // There is no DPI driver module, but we need a platform device
- // node (that doesn't already use pinctrl) to hang the pinctrl
---- a/arch/arm/boot/dts/overlays/draws-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/draws-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
- fragment@0 {
- target = <&i2s>;
- __overlay__ {
---- a/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&usb>;
---- a/arch/arm/boot/dts/overlays/dwc2-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dwc2-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&usb>;
---- a/arch/arm/boot/dts/overlays/enc28j60-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/enc28j60-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi2>;
---- a/arch/arm/boot/dts/overlays/exc3000-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/exc3000-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&clocks>;
---- a/arch/arm/boot/dts/overlays/goodix-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/goodix-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts
-@@ -38,7 +38,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/";
---- a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/";
---- a/arch/arm/boot/dts/overlays/gpio-ir-tx-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-ir-tx-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/gpio-key-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-key-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- // Configure the gpio pin controller
---- a/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/";
---- a/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
-@@ -10,7 +10,7 @@
- // note that GPIO3 has an external pullup on at least some boards).
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- // Configure the gpio pin controller
---- a/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/clocks";
---- a/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/clocks";
---- a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/hy28a-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hy28a-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/hy28b-2017-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hy28b-2017-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/hy28b-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/hy28b-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&sound>;
---- a/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/";
---- a/arch/arm/boot/dts/overlays/i2c-mux-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-mux-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/";
---- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts
-@@ -9,7 +9,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c0>;
---- a/arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts
-@@ -9,7 +9,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c1>;
---- a/arch/arm/boot/dts/overlays/i2s-gpio28-31-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2s-gpio28-31-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s_pins>;
---- a/arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/ilitek251x-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts
-@@ -13,7 +13,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- // disable spi-dev on spi0.0
- fragment@0 {
---- a/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/max98357a-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/max98357a-overlay.dts
-@@ -8,7 +8,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- /* Enable I2S */
- fragment@0 {
---- a/arch/arm/boot/dts/overlays/mbed-dac-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mbed-dac-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c1>;
---- a/arch/arm/boot/dts/overlays/mcp23s17-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp23s17-overlay.dts
-@@ -20,7 +20,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- // disable spi-dev on spi0.0
- fragment@0 {
---- a/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
- /* disable spi-dev for spi0.0 */
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
- /* disable spi-dev for spi0.1 */
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/mcp3008-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp3008-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spidev0>;
---- a/arch/arm/boot/dts/overlays/mcp3202-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp3202-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spidev0>;
---- a/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c1>;
---- a/arch/arm/boot/dts/overlays/media-center-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/media-center-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/mmc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mmc-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&mmc>;
---- a/arch/arm/boot/dts/overlays/mpu6050-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mpu6050-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c1>;
---- a/arch/arm/boot/dts/overlays/mz61581-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mz61581-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c_vc>;
---- a/arch/arm/boot/dts/overlays/papirus-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/papirus-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
-@@ -11,7 +11,7 @@
- */
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&act_led>;
---- a/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
-@@ -9,7 +9,7 @@
- */
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&uart1>;
---- a/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&mmc>;
---- a/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
-@@ -16,7 +16,7 @@
- */
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&uart0>;
---- a/arch/arm/boot/dts/overlays/pibell-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pibell-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/";
---- a/arch/arm/boot/dts/overlays/piglow-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/piglow-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/piscreen-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/piscreen2r-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/piscreen2r-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/pisound-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts
-@@ -23,7 +23,7 @@
- #include <dt-bindings/gpio/gpio.h>
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/pitft22-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pitft22-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
- fragment@0 {
- target-path = "/";
- __overlay__ {
---- a/arch/arm/boot/dts/overlays/pwm-ir-tx-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pwm-ir-tx-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/qca7000-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/qca7000-overlay.dts
-@@ -5,7 +5,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spidev0>;
---- a/arch/arm/boot/dts/overlays/rotary-encoder-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rotary-encoder-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/";
---- a/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
-@@ -6,7 +6,7 @@
- #include <dt-bindings/mfd/arizona.h>
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/rpi-display-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/";
---- a/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
-@@ -5,7 +5,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/";
---- a/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c1>;
---- a/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spidev0>;
---- a/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c_arm>;
---- a/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/sdhost-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts
-@@ -4,7 +4,7 @@
- /* Provide backwards compatible aliases for the old sdhost dtparams. */
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&sdhost>;
---- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
-@@ -4,7 +4,7 @@
- /* Enable SDIO from MMC interface via GPIOs 22-27. Includes sdhost overlay. */
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&mmc>;
---- a/arch/arm/boot/dts/overlays/sdtweak-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sdtweak-overlay.dts
-@@ -4,7 +4,7 @@
- /* Provide backwards compatible aliases for the old sdhost dtparams. */
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&sdhost>;
---- a/arch/arm/boot/dts/overlays/smi-nand-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/smi-nand-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&smi>;
---- a/arch/arm/boot/dts/overlays/smi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/smi-overlay.dts
-@@ -5,7 +5,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&smi>;
---- a/arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spidev0>;
---- a/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts
-@@ -3,7 +3,7 @@
-
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0_cs_pins>;
---- a/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts
-@@ -3,7 +3,7 @@
-
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts
-@@ -3,7 +3,7 @@
-
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts
-@@ -3,7 +3,7 @@
-
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts
-@@ -3,7 +3,7 @@
-
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts
-@@ -3,7 +3,7 @@
-
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts
-@@ -3,7 +3,7 @@
-
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&gpio>;
---- a/arch/arm/boot/dts/overlays/ssd1306-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/ssd1306-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2718";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c1>;
---- a/arch/arm/boot/dts/overlays/superaudioboard-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/superaudioboard-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&sound>;
---- a/arch/arm/boot/dts/overlays/sx150x-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sx150x-overlay.dts
-@@ -22,7 +22,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- // Enable I2C#0 interface
- fragment@0 {
---- a/arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts
-@@ -5,7 +5,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2s>;
---- a/arch/arm/boot/dts/overlays/tc358743-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/tc358743-overlay.dts
-@@ -4,7 +4,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&i2c_vc>;
---- a/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
-@@ -24,7 +24,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/tpm-slb9670-overlay.dts
-@@ -8,7 +8,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&spi0>;
---- a/arch/arm/boot/dts/overlays/uart0-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/uart0-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&uart0>;
---- a/arch/arm/boot/dts/overlays/uart1-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/uart1-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&uart1>;
---- a/arch/arm/boot/dts/overlays/udrc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/udrc-overlay.dts
-@@ -7,7 +7,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
- fragment@0 {
- target = <&i2s>;
- __overlay__ {
---- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
-@@ -6,7 +6,7 @@
- #include <dt-bindings/clock/bcm2835.h>
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
- fragment@0 {
- target-path = "/chosen";
- __dormant__ {
---- a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
-@@ -6,7 +6,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/chosen";
---- a/arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts
-@@ -8,7 +8,7 @@
- #include <dt-bindings/pinctrl/bcm2835.h>
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/";
---- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
-@@ -8,7 +8,7 @@
- #include <dt-bindings/clock/bcm2835.h>
-
- / {
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/chosen";
---- a/arch/arm/boot/dts/overlays/vga666-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/vga666-overlay.dts
-@@ -2,7 +2,7 @@
- /plugin/;
-
- /{
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- // There is no VGA driver module, but we need a platform device
- // node (that doesn't already use pinctrl) to hang the pinctrl
---- a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/";
---- a/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
-@@ -3,7 +3,7 @@
- /plugin/;
-
- / {
-- compatible = "brcm,bcm2708";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target-path = "/";
---- a/arch/arm/boot/dts/overlays/wittypi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/wittypi-overlay.dts
-@@ -8,7 +8,7 @@
-
- / {
-
-- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-+ compatible = "brcm,bcm2835";
-
- fragment@0 {
- target = <&leds>;
--- /dev/null
+From 9e3b138e750cddfd19e8463661e592fd14621c9c Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 22 May 2019 13:29:56 +0100
+Subject: [PATCH 508/725] overlays: Update upstream overlay
+
+The recent DT/overlay changes have had a corresponding effect on the
+upstream overlay, which is a composite of the vc4-kms-v3d and dwc2
+overlays.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ .../boot/dts/overlays/upstream-overlay.dts | 41 ++-----------------
+ 1 file changed, 3 insertions(+), 38 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
+@@ -52,42 +52,36 @@
+ fragment@7 {
+ target = <&pixelvalve0>;
+ __overlay__ {
+- interrupts = <2 13>;
+ status = "okay";
+ };
+ };
+ fragment@8 {
+ target = <&pixelvalve1>;
+ __overlay__ {
+- interrupts = <2 14>;
+ status = "okay";
+ };
+ };
+ fragment@9 {
+ target = <&pixelvalve2>;
+ __overlay__ {
+- interrupts = <2 10>;
+ status = "okay";
+ };
+ };
+ fragment@10 {
+ target = <&hvs>;
+ __overlay__ {
+- interrupts = <2 1>;
+ status = "okay";
+ };
+ };
+ fragment@11 {
+ target = <&hdmi>;
+ __overlay__ {
+- interrupts = <2 8>, <2 9>;
+ status = "okay";
+ };
+ };
+ fragment@12 {
+ target = <&v3d>;
+ __overlay__ {
+- interrupts = <1 10>;
+ status = "okay";
+ };
+ };
+@@ -98,37 +92,29 @@
+ };
+ };
+ fragment@14 {
+- target-path = "/soc/dma";
+- __overlay__ {
+- brcm,dma-channel-mask = <0x7f35>;
+- };
+- };
+- fragment@15 {
+ target = <&clocks>;
+ __overlay__ {
+ claim-clocks = <BCM2835_PLLD_DSI0 BCM2835_PLLD_DSI1 BCM2835_PLLH_AUX BCM2835_PLLH_PIX>;
+ };
+ };
+- fragment@16 {
++ fragment@15 {
+ target = <&vec>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+- fragment@17 {
++ fragment@16 {
+ target = <&txp>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+- fragment@18 {
++ fragment@17 {
+ target = <&usb>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ dwc2_usb: __overlay__ {
+ compatible = "brcm,bcm2835-usb";
+- reg = <0x7e980000 0x10000>;
+- interrupts = <1 9>;
+ dr_mode = "otg";
+ g-np-tx-fifo-size = <32>;
+ g-rx-fifo-size = <256>;
+@@ -136,25 +122,4 @@
+ status = "okay";
+ };
+ };
+- fragment@19 {
+- target = <&uart1>;
+- __overlay__ {
+- interrupt-parent = <&intc>;
+- interrupts = <0x1 0x1d>;
+- };
+- };
+- fragment@20 {
+- target = <&spi1>;
+- __overlay__ {
+- interrupt-parent = <&intc>;
+- interrupts = <0x1 0x1d>;
+- };
+- };
+- fragment@21 {
+- target = <&spi2>;
+- __overlay__ {
+- interrupt-parent = <&intc>;
+- interrupts = <0x1 0x1d>;
+- };
+- };
+ };
+++ /dev/null
-From 66ba94b1099ebc09bf82516499257165495c7c46 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 22 May 2019 12:58:47 +0100
-Subject: [PATCH 509/703] vc4: Remove interrupt and DMA trampling
-
-As part of the effort to clean up the overlays, remove the interrupt
-and DMA mask declarations from the vc4 overlays which just duplicate
-that which is in the base DTBs.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- .../boot/dts/overlays/vc4-fkms-v3d-overlay.dts | 8 --------
- .../boot/dts/overlays/vc4-kms-v3d-overlay.dts | 18 ++----------------
- 2 files changed, 2 insertions(+), 24 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts
-@@ -60,7 +60,6 @@
- fragment@7 {
- target = <&v3d>;
- __overlay__ {
-- interrupts = <1 10>;
- status = "okay";
- };
- };
-@@ -72,13 +71,6 @@
- };
- };
-
-- fragment@9 {
-- target-path = "/soc/dma";
-- __overlay__ {
-- brcm,dma-channel-mask = <0x7f35>;
-- };
-- };
--
- __overrides__ {
- cma-256 = <0>,"+0-1-2-3-4";
- cma-192 = <0>,"-0+1-2-3-4";
---- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
-@@ -62,7 +62,6 @@
- fragment@7 {
- target = <&pixelvalve0>;
- __overlay__ {
-- interrupts = <2 13>; /* pwa0 */
- status = "okay";
- };
- };
-@@ -70,7 +69,6 @@
- fragment@8 {
- target = <&pixelvalve1>;
- __overlay__ {
-- interrupts = <2 14>; /* pwa1 */
- status = "okay";
- };
- };
-@@ -78,7 +76,6 @@
- fragment@9 {
- target = <&pixelvalve2>;
- __overlay__ {
-- interrupts = <2 10>; /* pixelvalve */
- status = "okay";
- };
- };
-@@ -86,7 +83,6 @@
- fragment@10 {
- target = <&hvs>;
- __overlay__ {
-- interrupts = <2 1>;
- status = "okay";
- };
- };
-@@ -94,7 +90,6 @@
- fragment@11 {
- target = <&hdmi>;
- __overlay__ {
-- interrupts = <2 8>, <2 9>;
- status = "okay";
- };
- };
-@@ -102,7 +97,6 @@
- fragment@12 {
- target = <&v3d>;
- __overlay__ {
-- interrupts = <1 10>;
- status = "okay";
- };
- };
-@@ -115,14 +109,6 @@
- };
-
- fragment@14 {
-- target-path = "/soc/dma";
-- __overlay__ {
-- brcm,dma-channel-mask = <0x7f35>;
-- };
-- };
--
--
-- fragment@15 {
- target = <&clocks>;
- __overlay__ {
- claim-clocks = <
-@@ -134,14 +120,14 @@
- };
- };
-
-- fragment@16 {
-+ fragment@15 {
- target = <&vec>;
- __overlay__ {
- status = "okay";
- };
- };
-
-- fragment@17 {
-+ fragment@16 {
- target = <&txp>;
- __overlay__ {
- status = "okay";
--- /dev/null
+From 04d76f91610d34088593cc128de8184d86240db4 Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Thu, 16 May 2019 14:39:21 +0200
+Subject: [PATCH 509/725] w1: ds2408: Fix typo after 49695ac46861 (reset on
+ output_write retry with readback)
+
+commit 6660a04feb7ef648e50c792e19084d675fa6f3a2 upstream.
+
+Fix a typo in commit:
+49695ac46861 w1: ds2408: reset on output_write retry with readback
+
+Fixes: 49695ac46861 ("w1: ds2408: reset on output_write retry with readback")
+Reported-by: Phil Elwell <phil@raspberrypi.org>
+Cc: Jean-Francois Dagenais <jeff.dagenais@gmail.com>
+Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_ds2408.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/w1/slaves/w1_ds2408.c
++++ b/drivers/w1/slaves/w1_ds2408.c
+@@ -138,7 +138,7 @@ static ssize_t status_control_read(struc
+ W1_F29_REG_CONTROL_AND_STATUS, buf);
+ }
+
+-#ifdef fCONFIG_W1_SLAVE_DS2408_READBACK
++#ifdef CONFIG_W1_SLAVE_DS2408_READBACK
+ static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
+ {
+ u8 w1_buf[3];
+++ /dev/null
-From 5c9796882b256d149d9c9d9da6b374e4c4e7cbaa Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 7 May 2019 14:29:38 +0100
-Subject: [PATCH 510/703] BCM270X_DT: Add non-removable clone of mmc node
-
-non-removable is a boolean property, and as such can't be unset by an
-overlay if it is set in a base DTB. Until now the workaround for this
-problem has been for overlays to clone non-removable nodes without
-the offending property, but this involves a lot of unnecessary
-replication. Instead, add a clone of the mmc node with non-removable
-already set to the base DTB, selecting the required version using
-the status properties.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2708-rpi-0-w.dts | 4 +--
- arch/arm/boot/dts/bcm2708-rpi.dtsi | 3 +-
- arch/arm/boot/dts/bcm270x.dtsi | 13 ++++++++
- arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 5 ++--
- arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 5 ++--
- arch/arm/boot/dts/overlays/mmc-overlay.dts | 7 +++++
- arch/arm/boot/dts/overlays/sdio-overlay.dts | 33 +++++++--------------
- 7 files changed, 38 insertions(+), 32 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
-+++ b/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
-@@ -14,6 +14,7 @@
- aliases {
- serial0 = &uart1;
- serial1 = &uart0;
-+ mmc1 = &mmcnr;
- };
- };
-
-@@ -73,10 +74,9 @@
- };
- };
-
--&mmc {
-+&mmcnr {
- pinctrl-names = "default";
- pinctrl-0 = <&sdio_pins>;
-- non-removable;
- bus-width = <4>;
- status = "okay";
- };
---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
-@@ -118,7 +118,8 @@
- sd_force_pio = <&sdhost>,"brcm,force-pio?";
- sd_pio_limit = <&sdhost>,"brcm,pio-limit:0";
- sd_debug = <&sdhost>,"brcm,debug";
-- sdio_overclock = <&mmc>,"brcm,overclock-50:0";
-+ sdio_overclock = <&mmc>,"brcm,overclock-50:0",
-+ <&mmcnr>,"brcm,overclock-50:0";
- axiperf = <&axiperf>,"status";
- };
- };
---- a/arch/arm/boot/dts/bcm270x.dtsi
-+++ b/arch/arm/boot/dts/bcm270x.dtsi
-@@ -79,6 +79,19 @@
- status = "disabled";
- };
-
-+ /* A clone of mmc but with non-removable set */
-+ mmcnr: mmcnr@7e300000 {
-+ compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci";
-+ reg = <0x7e300000 0x100>;
-+ interrupts = <2 30>;
-+ clocks = <&clocks BCM2835_CLOCK_EMMC>;
-+ dmas = <&dma 11>;
-+ dma-names = "rx-tx";
-+ brcm,overclock-50 = <0>;
-+ non-removable;
-+ status = "disabled";
-+ };
-+
- hvs: hvs@7e400000 {
- /* Add alias */
- status = "disabled";
---- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
-@@ -15,6 +15,7 @@
- aliases {
- serial0 = &uart1;
- serial1 = &uart0;
-+ mmc1 = &mmcnr;
- };
- };
-
-@@ -74,13 +75,11 @@
- };
- };
-
--&mmc {
-+&mmcnr {
- pinctrl-names = "default";
- pinctrl-0 = <&sdio_pins>;
-- non-removable;
- bus-width = <4>;
- status = "okay";
-- brcm,overclock-50 = <0>;
- };
-
- &firmware {
---- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
-@@ -15,6 +15,7 @@
- aliases {
- serial0 = &uart1;
- serial1 = &uart0;
-+ mmc1 = &mmcnr;
- };
- };
-
-@@ -74,13 +75,11 @@
- };
- };
-
--&mmc {
-+&mmcnr {
- pinctrl-names = "default";
- pinctrl-0 = <&sdio_pins>;
-- non-removable;
- bus-width = <4>;
- status = "okay";
-- brcm,overclock-50 = <0>;
- };
-
- &soc {
---- a/arch/arm/boot/dts/overlays/mmc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mmc-overlay.dts
-@@ -33,6 +33,13 @@
- };
- };
-
-+ fragment@3 {
-+ target = <&mmcnr>;
-+ __overlay__ {
-+ status = "disabled";
-+ };
-+ };
-+
- __overrides__ {
- overclock_50 = <&frag0>,"brcm,overclock-50:0";
- };
---- a/arch/arm/boot/dts/overlays/sdio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sdio-overlay.dts
-@@ -1,39 +1,26 @@
- /dts-v1/;
- /plugin/;
-
--/* Enable SDIO from MMC interface via GPIOs 22-27. Includes sdhost overlay. */
-+/* Enable SDIO from MMC interface via various GPIO groups */
-
- /{
- compatible = "brcm,bcm2835";
-
- fragment@0 {
-- target = <&mmc>;
-+ target = <&mmcnr>;
- __overlay__ {
- status = "disabled";
- };
- };
-
- fragment@1 {
-- target = <&soc>;
-- __overlay__ {
-- #address-cells = <1>;
-- #size-cells = <1>;
--
-- sdio_ovl: sdio@7e300000 {
-- compatible = "brcm,bcm2835-mmc",
-- "brcm,bcm2835-sdhci";
-- reg = <0x7e300000 0x100>;
-- interrupts = <2 30>;
-- clocks = <&clocks 28/*BCM2835_CLOCK_EMMC*/>;
-- dmas = <&dma 11>;
-- dma-names = "rx-tx";
-- brcm,overclock-50 = <0>;
-- status = "okay";
-- pinctrl-names = "default";
-- pinctrl-0 = <&sdio_ovl_pins>;
-- non-removable;
-- bus-width = <4>;
-- };
-+ target = <&mmc>;
-+ sdio_ovl: __overlay__ {
-+ pinctrl-0 = <&sdio_ovl_pins>;
-+ pinctrl-names = "default";
-+ non-removable;
-+ bus-width = <4>;
-+ status = "okay";
- };
- };
-
-@@ -75,7 +62,7 @@
- fragment@6 {
- target-path = "/aliases";
- __overlay__ {
-- mmc1 = "/soc/sdio@7e300000";
-+ mmc1 = "/soc/mmc@7e300000";
- };
- };
-
--- /dev/null
+From c9858300591b9406b9b65e41da8d383d7cbd6826 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 28 May 2019 16:36:04 +0100
+Subject: [PATCH 510/725] BCM270X_DT: Rename Pi Zero W DT files
+
+The downtream Pi Zero W dts file uses the digit 0, whereas upstream
+chose to spell it out - "zero-w". The firmware has, for a long time,
+looked for bcm2708-rpi-zero-w.dtb first before falling back to the
+numerical version. Therefore it is better to follow upstream and
+make the switch to "bcm2708-rpi-zero-w".
+
+At the same time, remove some overrides that duplicate values
+inherited from the shared .dtsi files.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/Makefile | 2 +-
+ .../boot/dts/{bcm2708-rpi-0-w.dts => bcm2708-rpi-zero-w.dts} | 5 -----
+ 2 files changed, 1 insertion(+), 6 deletions(-)
+ rename arch/arm/boot/dts/{bcm2708-rpi-0-w.dts => bcm2708-rpi-zero-w.dts} (97%)
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -4,7 +4,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+ bcm2708-rpi-b.dtb \
+ bcm2708-rpi-b-plus.dtb \
+ bcm2708-rpi-cm.dtb \
+- bcm2708-rpi-0-w.dtb \
++ bcm2708-rpi-zero-w.dtb \
+ bcm2709-rpi-2-b.dtb \
+ bcm2710-rpi-3-b.dtb \
+ bcm2710-rpi-3-b-plus.dtb \
+--- a/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
++++ /dev/null
+@@ -1,167 +0,0 @@
+-/dts-v1/;
+-
+-#include "bcm2708.dtsi"
+-#include "bcm283x-rpi-csi1-2lane.dtsi"
+-
+-/ {
+- compatible = "raspberrypi,model-zero-w", "brcm,bcm2835";
+- model = "Raspberry Pi Zero W";
+-
+- chosen {
+- bootargs = "coherent_pool=1M 8250.nr_uarts=1";
+- };
+-
+- aliases {
+- serial0 = &uart1;
+- serial1 = &uart0;
+- mmc1 = &mmcnr;
+- };
+-};
+-
+-&gpio {
+- 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 = <>;
+- };
+-};
+-
+-&mmcnr {
+- pinctrl-names = "default";
+- pinctrl-0 = <&sdio_pins>;
+- bus-width = <4>;
+- 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 = <125000000>;
+- };
+-
+- spidev1: spidev@1{
+- compatible = "spidev";
+- reg = <1>; /* CE1 */
+- #address-cells = <1>;
+- #size-cells = <0>;
+- spi-max-frequency = <125000000>;
+- };
+-};
+-
+-&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>;
+-};
+-
+-/ {
+- __overrides__ {
+- act_led_gpio = <&act_led>,"gpios:4";
+- act_led_activelow = <&act_led>,"gpios:8";
+- act_led_trigger = <&act_led>,"linux,default-trigger";
+- };
+-};
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
+@@ -0,0 +1,162 @@
++/dts-v1/;
++
++#include "bcm2708.dtsi"
++#include "bcm283x-rpi-csi1-2lane.dtsi"
++
++/ {
++ compatible = "raspberrypi,model-zero-w", "brcm,bcm2835";
++ model = "Raspberry Pi Zero W";
++
++ chosen {
++ bootargs = "coherent_pool=1M 8250.nr_uarts=1";
++ };
++
++ aliases {
++ serial0 = &uart1;
++ serial1 = &uart0;
++ mmc1 = &mmcnr;
++ };
++};
++
++&gpio {
++ 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 = <>;
++ };
++};
++
++&mmcnr {
++ pinctrl-names = "default";
++ pinctrl-0 = <&sdio_pins>;
++ bus-width = <4>;
++ 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 = <125000000>;
++ };
++
++ spidev1: spidev@1{
++ compatible = "spidev";
++ reg = <1>; /* CE1 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ };
++};
++
++&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 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2s_pins>;
++};
++
++&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>;
++};
++
++/ {
++ __overrides__ {
++ act_led_gpio = <&act_led>,"gpios:4";
++ act_led_activelow = <&act_led>,"gpios:8";
++ act_led_trigger = <&act_led>,"linux,default-trigger";
++ };
++};
--- /dev/null
+From b9a96a4b09c30803092ed4a9f730cb3573037cd6 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 28 May 2019 16:23:51 +0100
+Subject: [PATCH 511/725] BCM270X_DT: Create bcm2708-rpi-zero.dts
+
+The Pi Zero deserves a dedicated .dtb file - sharing the b-plus .dtb
+has been observed to cause an issue with the MAC address of some
+Ethernet dongles.
+
+See: https://github.com/raspberrypi/linux/issues/2990
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/Makefile | 1 +
+ arch/arm/boot/dts/bcm2708-rpi-zero.dts | 117 +++++++++++++++++++++++++
+ 2 files changed, 118 insertions(+)
+ create mode 100644 arch/arm/boot/dts/bcm2708-rpi-zero.dts
+
+--- 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-zero.dtb \
+ bcm2708-rpi-zero-w.dtb \
+ bcm2709-rpi-2-b.dtb \
+ bcm2710-rpi-3-b.dtb \
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts
+@@ -0,0 +1,117 @@
++/dts-v1/;
++
++#include "bcm2708.dtsi"
++#include "bcm283x-rpi-csi1-2lane.dtsi"
++
++/ {
++ compatible = "raspberrypi,model-zero", "brcm,bcm2835";
++ model = "Raspberry Pi Zero";
++
++ chosen {
++ bootargs = "coherent_pool=1M";
++ };
++};
++
++&gpio {
++ 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 */
++ };
++
++ audio_pins: audio_pins {
++ brcm,pins = <>;
++ brcm,function = <>;
++ };
++};
++
++&uart0 {
++ 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 = <125000000>;
++ };
++
++ spidev1: spidev@1{
++ compatible = "spidev";
++ reg = <1>; /* CE1 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ };
++};
++
++&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 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2s_pins>;
++};
++
++&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>;
++};
++
++/ {
++ __overrides__ {
++ act_led_gpio = <&act_led>,"gpios:4";
++ act_led_activelow = <&act_led>,"gpios:8";
++ act_led_trigger = <&act_led>,"linux,default-trigger";
++ };
++};
+++ /dev/null
-From fdec17c9cd5cb9c52872e9669aca53d58c7f1eaf Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 8 May 2019 10:08:31 +0100
-Subject: [PATCH 511/703] BCM270X_DT: usb: Refactor DTS and overlays
-
-Move the IRQ interrupt declaration in the usb node before the FIQ
-declaration, so that the dwc2 driver will find it. Name the
-interrupts appropriately so that the dwc_otg driver can still find
-them. Then remove the interrupt rewriting from the overlays.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm270x.dtsi | 6 ++++--
- arch/arm/boot/dts/overlays/dwc-otg-overlay.dts | 6 ------
- arch/arm/boot/dts/overlays/dwc2-overlay.dts | 2 --
- 3 files changed, 4 insertions(+), 10 deletions(-)
-
---- a/arch/arm/boot/dts/bcm270x.dtsi
-+++ b/arch/arm/boot/dts/bcm270x.dtsi
-@@ -131,8 +131,10 @@
- compatible = "brcm,bcm2708-usb";
- reg = <0x7e980000 0x10000>,
- <0x7e006000 0x1000>;
-- interrupts = <2 0>,
-- <1 9>;
-+ interrupt-names = "usb",
-+ "soft";
-+ interrupts = <1 9>,
-+ <2 0>;
- };
-
- v3d@7ec00000 { /* vd3 */
---- a/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dwc-otg-overlay.dts
-@@ -6,14 +6,8 @@
-
- fragment@0 {
- target = <&usb>;
-- #address-cells = <1>;
-- #size-cells = <1>;
- __overlay__ {
- compatible = "brcm,bcm2708-usb";
-- reg = <0x7e980000 0x10000>,
-- <0x7e006000 0x1000>;
-- interrupts = <2 0>,
-- <1 9>;
- status = "okay";
- };
- };
---- a/arch/arm/boot/dts/overlays/dwc2-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dwc2-overlay.dts
-@@ -10,8 +10,6 @@
- #size-cells = <1>;
- dwc2_usb: __overlay__ {
- compatible = "brcm,bcm2835-usb";
-- reg = <0x7e980000 0x10000>;
-- interrupts = <1 9>;
- dr_mode = "otg";
- g-np-tx-fifo-size = <32>;
- g-rx-fifo-size = <256>;
--- /dev/null
+From 4adf2465fe10714a159a2e9a885989d0ad46db13 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 30 May 2019 12:25:29 +0100
+Subject: [PATCH 512/725] overlays: Fix mmc-related overlays after refactor
+
+The addition of the mmcnr node to the base dtbs caused some overlays to
+not work as they should. Patch up pi3-disable-wifi, balena-fin and
+sdhost.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/balena-fin-overlay.dts | 7 ++++---
+ arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts | 7 +++++++
+ arch/arm/boot/dts/overlays/sdhost-overlay.dts | 7 +++++++
+ 3 files changed, 18 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
++++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
+@@ -5,13 +5,12 @@
+ compatible = "brcm,bcm2835";
+
+ fragment@0 {
+- target = <&mmc>;
+- sdio_wifi: __overlay__ {
++ target = <&mmcnr>;
++ __overlay__ {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio_pins>;
+ bus-width = <4>;
+ brcm,overclock-50 = <35>;
+- non-removable;
+ status = "okay";
+ };
+ };
+@@ -43,6 +42,8 @@
+ compatible = "gpio-poweroff";
+ gpios = <&gpio 40 1>;
+ force;
++ pinctrl-names = "default";
++ pinctrl-0 = <&power_ctrl_pins>;
+ };
+
+ i2c_soft: i2c@0 {
+--- a/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
+@@ -10,4 +10,11 @@
+ status = "disabled";
+ };
+ };
++
++ fragment@1 {
++ target = <&mmcnr>;
++ __overlay__ {
++ status = "disabled";
++ };
++ };
+ };
+--- a/arch/arm/boot/dts/overlays/sdhost-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts
+@@ -22,6 +22,13 @@
+ };
+ };
+
++ fragment@2 {
++ target = <&mmcnr>;
++ __overlay__ {
++ status = "disabled";
++ };
++ };
++
+ __overrides__ {
+ overclock_50 = <&frag0>,"brcm,overclock-50:0";
+ force_pio = <&frag0>,"brcm,force-pio?";
+++ /dev/null
-From a81bfae69a80e92852509118ff81f3485836b81e Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 22 May 2019 13:29:56 +0100
-Subject: [PATCH 512/703] overlays: Update upstream overlay
-
-The recent DT/overlay changes have had a corresponding effect on the
-upstream overlay, which is a composite of the vc4-kms-v3d and dwc2
-overlays.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- .../boot/dts/overlays/upstream-overlay.dts | 41 ++-----------------
- 1 file changed, 3 insertions(+), 38 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
-@@ -52,42 +52,36 @@
- fragment@7 {
- target = <&pixelvalve0>;
- __overlay__ {
-- interrupts = <2 13>;
- status = "okay";
- };
- };
- fragment@8 {
- target = <&pixelvalve1>;
- __overlay__ {
-- interrupts = <2 14>;
- status = "okay";
- };
- };
- fragment@9 {
- target = <&pixelvalve2>;
- __overlay__ {
-- interrupts = <2 10>;
- status = "okay";
- };
- };
- fragment@10 {
- target = <&hvs>;
- __overlay__ {
-- interrupts = <2 1>;
- status = "okay";
- };
- };
- fragment@11 {
- target = <&hdmi>;
- __overlay__ {
-- interrupts = <2 8>, <2 9>;
- status = "okay";
- };
- };
- fragment@12 {
- target = <&v3d>;
- __overlay__ {
-- interrupts = <1 10>;
- status = "okay";
- };
- };
-@@ -98,37 +92,29 @@
- };
- };
- fragment@14 {
-- target-path = "/soc/dma";
-- __overlay__ {
-- brcm,dma-channel-mask = <0x7f35>;
-- };
-- };
-- fragment@15 {
- target = <&clocks>;
- __overlay__ {
- claim-clocks = <BCM2835_PLLD_DSI0 BCM2835_PLLD_DSI1 BCM2835_PLLH_AUX BCM2835_PLLH_PIX>;
- };
- };
-- fragment@16 {
-+ fragment@15 {
- target = <&vec>;
- __overlay__ {
- status = "okay";
- };
- };
-- fragment@17 {
-+ fragment@16 {
- target = <&txp>;
- __overlay__ {
- status = "okay";
- };
- };
-- fragment@18 {
-+ fragment@17 {
- target = <&usb>;
- #address-cells = <1>;
- #size-cells = <1>;
- dwc2_usb: __overlay__ {
- compatible = "brcm,bcm2835-usb";
-- reg = <0x7e980000 0x10000>;
-- interrupts = <1 9>;
- dr_mode = "otg";
- g-np-tx-fifo-size = <32>;
- g-rx-fifo-size = <256>;
-@@ -136,25 +122,4 @@
- status = "okay";
- };
- };
-- fragment@19 {
-- target = <&uart1>;
-- __overlay__ {
-- interrupt-parent = <&intc>;
-- interrupts = <0x1 0x1d>;
-- };
-- };
-- fragment@20 {
-- target = <&spi1>;
-- __overlay__ {
-- interrupt-parent = <&intc>;
-- interrupts = <0x1 0x1d>;
-- };
-- };
-- fragment@21 {
-- target = <&spi2>;
-- __overlay__ {
-- interrupt-parent = <&intc>;
-- interrupts = <0x1 0x1d>;
-- };
-- };
- };
--- /dev/null
+From cc26d5547fc63f2cead8d51379cfd782b70832ba Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 3 Jun 2019 14:57:56 +0100
+Subject: [PATCH 513/725] config: Add NF_TABLES support
+
+---
+ arch/arm/configs/bcm2709_defconfig | 48 ++++++++++++++++++++++++++++++
+ arch/arm/configs/bcmrpi_defconfig | 48 ++++++++++++++++++++++++++++++
+ 2 files changed, 96 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -136,6 +136,36 @@ CONFIG_NF_CONNTRACK_SANE=m
+ CONFIG_NF_CONNTRACK_SIP=m
+ CONFIG_NF_CONNTRACK_TFTP=m
+ CONFIG_NF_CT_NETLINK=m
++CONFIG_NF_TABLES=m
++CONFIG_NF_TABLES_SET=m
++CONFIG_NF_TABLES_INET=y
++CONFIG_NF_TABLES_NETDEV=y
++CONFIG_NFT_NUMGEN=m
++CONFIG_NFT_CT=m
++CONFIG_NFT_FLOW_OFFLOAD=m
++CONFIG_NFT_COUNTER=m
++CONFIG_NFT_CONNLIMIT=m
++CONFIG_NFT_LOG=m
++CONFIG_NFT_LIMIT=m
++CONFIG_NFT_MASQ=m
++CONFIG_NFT_REDIR=m
++CONFIG_NFT_NAT=m
++CONFIG_NFT_TUNNEL=m
++CONFIG_NFT_OBJREF=m
++CONFIG_NFT_QUEUE=m
++CONFIG_NFT_QUOTA=m
++CONFIG_NFT_REJECT=m
++CONFIG_NFT_COMPAT=m
++CONFIG_NFT_HASH=m
++CONFIG_NFT_FIB_INET=m
++CONFIG_NFT_SOCKET=m
++CONFIG_NFT_OSF=m
++CONFIG_NFT_TPROXY=m
++CONFIG_NFT_DUP_NETDEV=m
++CONFIG_NFT_FWD_NETDEV=m
++CONFIG_NFT_FIB_NETDEV=m
++CONFIG_NF_FLOW_TABLE_INET=m
++CONFIG_NF_FLOW_TABLE=m
+ CONFIG_NETFILTER_XT_SET=m
+ CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+ CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+@@ -224,6 +254,14 @@ CONFIG_IP_VS_SED=m
+ CONFIG_IP_VS_NQ=m
+ CONFIG_IP_VS_FTP=m
+ CONFIG_IP_VS_PE_SIP=m
++CONFIG_NFT_CHAIN_ROUTE_IPV4=m
++CONFIG_NFT_DUP_IPV4=m
++CONFIG_NFT_FIB_IPV4=m
++CONFIG_NF_TABLES_ARP=y
++CONFIG_NF_FLOW_TABLE_IPV4=m
++CONFIG_NFT_CHAIN_NAT_IPV4=m
++CONFIG_NFT_MASQ_IPV4=m
++CONFIG_NFT_REDIR_IPV4=m
+ CONFIG_IP_NF_IPTABLES=m
+ CONFIG_IP_NF_MATCH_AH=m
+ CONFIG_IP_NF_MATCH_ECN=m
+@@ -243,6 +281,13 @@ CONFIG_IP_NF_RAW=m
+ CONFIG_IP_NF_ARPTABLES=m
+ CONFIG_IP_NF_ARPFILTER=m
+ CONFIG_IP_NF_ARP_MANGLE=m
++CONFIG_NFT_CHAIN_ROUTE_IPV6=m
++CONFIG_NFT_CHAIN_NAT_IPV6=m
++CONFIG_NFT_MASQ_IPV6=m
++CONFIG_NFT_REDIR_IPV6=m
++CONFIG_NFT_DUP_IPV6=m
++CONFIG_NFT_FIB_IPV6=m
++CONFIG_NF_FLOW_TABLE_IPV6=m
+ CONFIG_IP6_NF_IPTABLES=m
+ CONFIG_IP6_NF_MATCH_AH=m
+ CONFIG_IP6_NF_MATCH_EUI64=m
+@@ -261,6 +306,9 @@ CONFIG_IP6_NF_RAW=m
+ CONFIG_IP6_NF_NAT=m
+ CONFIG_IP6_NF_TARGET_MASQUERADE=m
+ CONFIG_IP6_NF_TARGET_NPT=m
++CONFIG_NF_TABLES_BRIDGE=y
++CONFIG_NFT_BRIDGE_REJECT=m
++CONFIG_NF_LOG_BRIDGE=m
+ CONFIG_BRIDGE_NF_EBTABLES=m
+ CONFIG_BRIDGE_EBT_BROUTE=m
+ CONFIG_BRIDGE_EBT_T_FILTER=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -129,6 +129,36 @@ CONFIG_NF_CONNTRACK_SANE=m
+ CONFIG_NF_CONNTRACK_SIP=m
+ CONFIG_NF_CONNTRACK_TFTP=m
+ CONFIG_NF_CT_NETLINK=m
++CONFIG_NF_TABLES=m
++CONFIG_NF_TABLES_SET=m
++CONFIG_NF_TABLES_INET=y
++CONFIG_NF_TABLES_NETDEV=y
++CONFIG_NFT_NUMGEN=m
++CONFIG_NFT_CT=m
++CONFIG_NFT_FLOW_OFFLOAD=m
++CONFIG_NFT_COUNTER=m
++CONFIG_NFT_CONNLIMIT=m
++CONFIG_NFT_LOG=m
++CONFIG_NFT_LIMIT=m
++CONFIG_NFT_MASQ=m
++CONFIG_NFT_REDIR=m
++CONFIG_NFT_NAT=m
++CONFIG_NFT_TUNNEL=m
++CONFIG_NFT_OBJREF=m
++CONFIG_NFT_QUEUE=m
++CONFIG_NFT_QUOTA=m
++CONFIG_NFT_REJECT=m
++CONFIG_NFT_COMPAT=m
++CONFIG_NFT_HASH=m
++CONFIG_NFT_FIB_INET=m
++CONFIG_NFT_SOCKET=m
++CONFIG_NFT_OSF=m
++CONFIG_NFT_TPROXY=m
++CONFIG_NFT_DUP_NETDEV=m
++CONFIG_NFT_FWD_NETDEV=m
++CONFIG_NFT_FIB_NETDEV=m
++CONFIG_NF_FLOW_TABLE_INET=m
++CONFIG_NF_FLOW_TABLE=m
+ CONFIG_NETFILTER_XT_SET=m
+ CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+ CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+@@ -217,6 +247,14 @@ CONFIG_IP_VS_SED=m
+ CONFIG_IP_VS_NQ=m
+ CONFIG_IP_VS_FTP=m
+ CONFIG_IP_VS_PE_SIP=m
++CONFIG_NFT_CHAIN_ROUTE_IPV4=m
++CONFIG_NFT_DUP_IPV4=m
++CONFIG_NFT_FIB_IPV4=m
++CONFIG_NF_TABLES_ARP=y
++CONFIG_NF_FLOW_TABLE_IPV4=m
++CONFIG_NFT_CHAIN_NAT_IPV4=m
++CONFIG_NFT_MASQ_IPV4=m
++CONFIG_NFT_REDIR_IPV4=m
+ CONFIG_IP_NF_IPTABLES=m
+ CONFIG_IP_NF_MATCH_AH=m
+ CONFIG_IP_NF_MATCH_ECN=m
+@@ -236,6 +274,13 @@ CONFIG_IP_NF_RAW=m
+ CONFIG_IP_NF_ARPTABLES=m
+ CONFIG_IP_NF_ARPFILTER=m
+ CONFIG_IP_NF_ARP_MANGLE=m
++CONFIG_NFT_CHAIN_ROUTE_IPV6=m
++CONFIG_NFT_CHAIN_NAT_IPV6=m
++CONFIG_NFT_MASQ_IPV6=m
++CONFIG_NFT_REDIR_IPV6=m
++CONFIG_NFT_DUP_IPV6=m
++CONFIG_NFT_FIB_IPV6=m
++CONFIG_NF_FLOW_TABLE_IPV6=m
+ CONFIG_IP6_NF_IPTABLES=m
+ CONFIG_IP6_NF_MATCH_AH=m
+ CONFIG_IP6_NF_MATCH_EUI64=m
+@@ -254,6 +299,9 @@ CONFIG_IP6_NF_RAW=m
+ CONFIG_IP6_NF_NAT=m
+ CONFIG_IP6_NF_TARGET_MASQUERADE=m
+ CONFIG_IP6_NF_TARGET_NPT=m
++CONFIG_NF_TABLES_BRIDGE=y
++CONFIG_NFT_BRIDGE_REJECT=m
++CONFIG_NF_LOG_BRIDGE=m
+ CONFIG_BRIDGE_NF_EBTABLES=m
+ CONFIG_BRIDGE_EBT_BROUTE=m
+ CONFIG_BRIDGE_EBT_T_FILTER=m
+++ /dev/null
-From b7e76f445cec9a72c1f8f22cba1b2afe0e77f849 Mon Sep 17 00:00:00 2001
-From: Mariusz Bialonczyk <manio@skyboo.net>
-Date: Thu, 16 May 2019 14:39:21 +0200
-Subject: [PATCH 513/703] w1: ds2408: Fix typo after 49695ac46861 (reset on
- output_write retry with readback)
-
-commit 6660a04feb7ef648e50c792e19084d675fa6f3a2 upstream.
-
-Fix a typo in commit:
-49695ac46861 w1: ds2408: reset on output_write retry with readback
-
-Fixes: 49695ac46861 ("w1: ds2408: reset on output_write retry with readback")
-Reported-by: Phil Elwell <phil@raspberrypi.org>
-Cc: Jean-Francois Dagenais <jeff.dagenais@gmail.com>
-Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/slaves/w1_ds2408.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/w1/slaves/w1_ds2408.c
-+++ b/drivers/w1/slaves/w1_ds2408.c
-@@ -138,7 +138,7 @@ static ssize_t status_control_read(struc
- W1_F29_REG_CONTROL_AND_STATUS, buf);
- }
-
--#ifdef fCONFIG_W1_SLAVE_DS2408_READBACK
-+#ifdef CONFIG_W1_SLAVE_DS2408_READBACK
- static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
- {
- u8 w1_buf[3];
+++ /dev/null
-From 8daca09e4eea788e6fc2fdf3d8ab4c0976128d3d Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 28 May 2019 16:36:04 +0100
-Subject: [PATCH 514/703] BCM270X_DT: Rename Pi Zero W DT files
-
-The downtream Pi Zero W dts file uses the digit 0, whereas upstream
-chose to spell it out - "zero-w". The firmware has, for a long time,
-looked for bcm2708-rpi-zero-w.dtb first before falling back to the
-numerical version. Therefore it is better to follow upstream and
-make the switch to "bcm2708-rpi-zero-w".
-
-At the same time, remove some overrides that duplicate values
-inherited from the shared .dtsi files.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/Makefile | 2 +-
- .../boot/dts/{bcm2708-rpi-0-w.dts => bcm2708-rpi-zero-w.dts} | 5 -----
- 2 files changed, 1 insertion(+), 6 deletions(-)
- rename arch/arm/boot/dts/{bcm2708-rpi-0-w.dts => bcm2708-rpi-zero-w.dts} (97%)
-
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -4,7 +4,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
- bcm2708-rpi-b.dtb \
- bcm2708-rpi-b-plus.dtb \
- bcm2708-rpi-cm.dtb \
-- bcm2708-rpi-0-w.dtb \
-+ bcm2708-rpi-zero-w.dtb \
- bcm2709-rpi-2-b.dtb \
- bcm2710-rpi-3-b.dtb \
- bcm2710-rpi-3-b-plus.dtb \
---- a/arch/arm/boot/dts/bcm2708-rpi-0-w.dts
-+++ /dev/null
-@@ -1,167 +0,0 @@
--/dts-v1/;
--
--#include "bcm2708.dtsi"
--#include "bcm283x-rpi-csi1-2lane.dtsi"
--
--/ {
-- compatible = "raspberrypi,model-zero-w", "brcm,bcm2835";
-- model = "Raspberry Pi Zero W";
--
-- chosen {
-- bootargs = "coherent_pool=1M 8250.nr_uarts=1";
-- };
--
-- aliases {
-- serial0 = &uart1;
-- serial1 = &uart0;
-- mmc1 = &mmcnr;
-- };
--};
--
--&gpio {
-- 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 = <>;
-- };
--};
--
--&mmcnr {
-- pinctrl-names = "default";
-- pinctrl-0 = <&sdio_pins>;
-- bus-width = <4>;
-- 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 = <125000000>;
-- };
--
-- spidev1: spidev@1{
-- compatible = "spidev";
-- reg = <1>; /* CE1 */
-- #address-cells = <1>;
-- #size-cells = <0>;
-- spi-max-frequency = <125000000>;
-- };
--};
--
--&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>;
--};
--
--/ {
-- __overrides__ {
-- act_led_gpio = <&act_led>,"gpios:4";
-- act_led_activelow = <&act_led>,"gpios:8";
-- act_led_trigger = <&act_led>,"linux,default-trigger";
-- };
--};
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
-@@ -0,0 +1,162 @@
-+/dts-v1/;
-+
-+#include "bcm2708.dtsi"
-+#include "bcm283x-rpi-csi1-2lane.dtsi"
-+
-+/ {
-+ compatible = "raspberrypi,model-zero-w", "brcm,bcm2835";
-+ model = "Raspberry Pi Zero W";
-+
-+ chosen {
-+ bootargs = "coherent_pool=1M 8250.nr_uarts=1";
-+ };
-+
-+ aliases {
-+ serial0 = &uart1;
-+ serial1 = &uart0;
-+ mmc1 = &mmcnr;
-+ };
-+};
-+
-+&gpio {
-+ 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 = <>;
-+ };
-+};
-+
-+&mmcnr {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&sdio_pins>;
-+ bus-width = <4>;
-+ 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 = <125000000>;
-+ };
-+
-+ spidev1: spidev@1{
-+ compatible = "spidev";
-+ reg = <1>; /* CE1 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ };
-+};
-+
-+&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 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2s_pins>;
-+};
-+
-+&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>;
-+};
-+
-+/ {
-+ __overrides__ {
-+ act_led_gpio = <&act_led>,"gpios:4";
-+ act_led_activelow = <&act_led>,"gpios:8";
-+ act_led_trigger = <&act_led>,"linux,default-trigger";
-+ };
-+};
--- /dev/null
+From 534eaba07cc9ffcf9ee74aeeeb9b2ab96b18ece5 Mon Sep 17 00:00:00 2001
+From: IQaudIO <gordon@iqaudio.com>
+Date: Thu, 6 Jun 2019 10:20:55 +0100
+Subject: [PATCH 514/725] Fixed 48k timing issue
+
+---
+ sound/soc/bcm/iqaudio-codec.c | 33 ++++++++++++++++++++++++++++-----
+ 1 file changed, 28 insertions(+), 5 deletions(-)
+
+--- a/sound/soc/bcm/iqaudio-codec.c
++++ b/sound/soc/bcm/iqaudio-codec.c
+@@ -45,11 +45,15 @@ static int snd_rpi_iqaudio_pll_control(s
+ 0);
+ if (ret)
+ dev_err(card->dev, "Failed to bypass PLL: %d\n", ret);
++ /* Allow PLL time to bypass */
++ msleep(100);
+ } else if (SND_SOC_DAPM_EVENT_ON(event)) {
+ ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_PLL, 0,
+ pll_out);
+ if (ret)
+ dev_err(card->dev, "Failed to enable PLL: %d\n", ret);
++ /* Allow PLL time to lock */
++ msleep(100);
+ }
+
+ return ret;
+@@ -71,6 +75,13 @@ static int snd_rpi_iqaudio_post_dapm_eve
+ return 0;
+ }
+
++static const struct snd_kcontrol_new dapm_controls[] = {
++ SOC_DAPM_PIN_SWITCH("HP Jack"),
++ SOC_DAPM_PIN_SWITCH("MIC Jack"),
++ SOC_DAPM_PIN_SWITCH("Onboard MIC"),
++ SOC_DAPM_PIN_SWITCH("AUX Jack"),
++};
++
+ static const struct snd_soc_dapm_widget dapm_widgets[] = {
+ SND_SOC_DAPM_HP("HP Jack", NULL),
+ SND_SOC_DAPM_MIC("MIC Jack", NULL),
+@@ -87,14 +98,14 @@ static const struct snd_soc_dapm_route a
+ {"HP Jack", NULL, "HPR"},
+ {"HP Jack", NULL, "PLL Control"},
+
+- {"AUX Jack", NULL, "AUXR"},
+- {"AUX Jack", NULL, "AUXL"},
++ {"AUXR", NULL, "AUX Jack"},
++ {"AUXL", NULL, "AUX Jack"},
+ {"AUX Jack", NULL, "PLL Control"},
+
+ /* Assume Mic1 is linked to Headset and Mic2 to on-board mic */
+- {"MIC Jack", NULL, "MIC1"},
++ {"MIC1", NULL, "MIC Jack"},
+ {"MIC Jack", NULL, "PLL Control"},
+- {"Onboard MIC", NULL, "MIC2"},
++ {"MIC2", NULL, "Onboard MIC"},
+ {"Onboard MIC", NULL, "PLL Control"},
+ };
+
+@@ -106,6 +117,16 @@ static int snd_rpi_iqaudio_codec_init(st
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret;
+
++ /*
++ * Disable AUX Jack Pin by default to prevent PLL being enabled at
++ * startup. This avoids holding the PLL to a fixed SR config for
++ * subsequent streams.
++ *
++ * This pin can still be enabled later, as required by user-space.
++ */
++ snd_soc_dapm_disable_pin(&rtd->card->dapm, "AUX Jack");
++ snd_soc_dapm_sync(&rtd->card->dapm);
++
+ /* Set bclk ratio to align with codec's BCLK rate */
+ ret = snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
+ if (ret) {
+@@ -168,6 +189,8 @@ static struct snd_soc_card snd_rpi_iqaud
+ .owner = THIS_MODULE,
+ .dai_link = snd_rpi_iqaudio_codec_dai,
+ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_codec_dai),
++ .controls = dapm_controls,
++ .num_controls = ARRAY_SIZE(dapm_controls),
+ .dapm_widgets = dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(dapm_widgets),
+ .dapm_routes = audio_map,
+@@ -204,7 +227,7 @@ static int snd_rpi_iqaudio_codec_probe(s
+
+ if (of_property_read_string(pdev->dev.of_node,
+ "dai_stream_name", &dai->stream_name))
+- dai->stream_name = "IQaudIO CODEC HiFi v1.1";
++ dai->stream_name = "IQaudIO CODEC HiFi v1.2";
+
+ }
+
+++ /dev/null
-From 926eb05f48f4c805075aa535a444127de6de0dbb Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 28 May 2019 16:23:51 +0100
-Subject: [PATCH 515/703] BCM270X_DT: Create bcm2708-rpi-zero.dts
-
-The Pi Zero deserves a dedicated .dtb file - sharing the b-plus .dtb
-has been observed to cause an issue with the MAC address of some
-Ethernet dongles.
-
-See: https://github.com/raspberrypi/linux/issues/2990
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/Makefile | 1 +
- arch/arm/boot/dts/bcm2708-rpi-zero.dts | 117 +++++++++++++++++++++++++
- 2 files changed, 118 insertions(+)
- create mode 100644 arch/arm/boot/dts/bcm2708-rpi-zero.dts
-
---- 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-zero.dtb \
- bcm2708-rpi-zero-w.dtb \
- bcm2709-rpi-2-b.dtb \
- bcm2710-rpi-3-b.dtb \
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts
-@@ -0,0 +1,117 @@
-+/dts-v1/;
-+
-+#include "bcm2708.dtsi"
-+#include "bcm283x-rpi-csi1-2lane.dtsi"
-+
-+/ {
-+ compatible = "raspberrypi,model-zero", "brcm,bcm2835";
-+ model = "Raspberry Pi Zero";
-+
-+ chosen {
-+ bootargs = "coherent_pool=1M";
-+ };
-+};
-+
-+&gpio {
-+ 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 */
-+ };
-+
-+ audio_pins: audio_pins {
-+ brcm,pins = <>;
-+ brcm,function = <>;
-+ };
-+};
-+
-+&uart0 {
-+ 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 = <125000000>;
-+ };
-+
-+ spidev1: spidev@1{
-+ compatible = "spidev";
-+ reg = <1>; /* CE1 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ };
-+};
-+
-+&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 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2s_pins>;
-+};
-+
-+&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>;
-+};
-+
-+/ {
-+ __overrides__ {
-+ act_led_gpio = <&act_led>,"gpios:4";
-+ act_led_activelow = <&act_led>,"gpios:8";
-+ act_led_trigger = <&act_led>,"linux,default-trigger";
-+ };
-+};
--- /dev/null
+From 7b288978c69b614afbc4de50a2e68c8e26c988ef Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 10 May 2019 14:11:58 +0100
+Subject: [PATCH 515/725] staging: bcm2835-codec: Convert V4L2 nsec timestamps
+ to MMAL usec
+
+V4L2 uses nsecs, whilst MMAL uses usecs, but the code wasn't converting
+between them. This upsets video encode rate control.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -823,7 +823,8 @@ static void op_buffer_cb(struct vchiq_mm
+ vb2->flags |= V4L2_BUF_FLAG_LAST;
+ }
+
+- vb2->vb2_buf.timestamp = mmal_buf->pts;
++ /* vb2 timestamps in nsecs, mmal in usecs */
++ vb2->vb2_buf.timestamp = mmal_buf->pts * 1000;
+
+ vb2_set_plane_payload(&vb2->vb2_buf, 0, mmal_buf->length);
+ if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
+@@ -847,6 +848,7 @@ static void op_buffer_cb(struct vchiq_mm
+ static void vb2_to_mmal_buffer(struct m2m_mmal_buffer *buf,
+ struct vb2_v4l2_buffer *vb2)
+ {
++ u64 pts;
+ buf->mmal.mmal_flags = 0;
+ if (vb2->flags & V4L2_BUF_FLAG_KEYFRAME)
+ buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_KEYFRAME;
+@@ -869,7 +871,10 @@ static void vb2_to_mmal_buffer(struct m2
+ if (!buf->mmal.length || vb2->flags & V4L2_BUF_FLAG_LAST)
+ buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
+
+- buf->mmal.pts = vb2->vb2_buf.timestamp;
++ /* vb2 timestamps in nsecs, mmal in usecs */
++ pts = vb2->vb2_buf.timestamp;
++ do_div(pts, 1000);
++ buf->mmal.pts = pts;
+ buf->mmal.dts = MMAL_TIME_UNKNOWN;
+ }
+
+++ /dev/null
-From 59ffffa03628f1df3dc63d8f2f1b61bce4b322c2 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 30 May 2019 12:25:29 +0100
-Subject: [PATCH 516/703] overlays: Fix mmc-related overlays after refactor
-
-The addition of the mmcnr node to the base dtbs caused some overlays to
-not work as they should. Patch up pi3-disable-wifi, balena-fin and
-sdhost.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/balena-fin-overlay.dts | 7 ++++---
- arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts | 7 +++++++
- arch/arm/boot/dts/overlays/sdhost-overlay.dts | 7 +++++++
- 3 files changed, 18 insertions(+), 3 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-@@ -5,13 +5,12 @@
- compatible = "brcm,bcm2835";
-
- fragment@0 {
-- target = <&mmc>;
-- sdio_wifi: __overlay__ {
-+ target = <&mmcnr>;
-+ __overlay__ {
- pinctrl-names = "default";
- pinctrl-0 = <&sdio_pins>;
- bus-width = <4>;
- brcm,overclock-50 = <35>;
-- non-removable;
- status = "okay";
- };
- };
-@@ -43,6 +42,8 @@
- compatible = "gpio-poweroff";
- gpios = <&gpio 40 1>;
- force;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&power_ctrl_pins>;
- };
-
- i2c_soft: i2c@0 {
---- a/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
-@@ -10,4 +10,11 @@
- status = "disabled";
- };
- };
-+
-+ fragment@1 {
-+ target = <&mmcnr>;
-+ __overlay__ {
-+ status = "disabled";
-+ };
-+ };
- };
---- a/arch/arm/boot/dts/overlays/sdhost-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts
-@@ -22,6 +22,13 @@
- };
- };
-
-+ fragment@2 {
-+ target = <&mmcnr>;
-+ __overlay__ {
-+ status = "disabled";
-+ };
-+ };
-+
- __overrides__ {
- overclock_50 = <&frag0>,"brcm,overclock-50:0";
- force_pio = <&frag0>,"brcm,force-pio?";
--- /dev/null
+From 36a826c4ef3da5d893b44816692f9b77a4842536 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 10 May 2019 14:13:11 +0100
+Subject: [PATCH 516/725] staging: bcm2835-codec: Add support for setting
+ S_PARM and G_PARM
+
+Video encode can use the frame rate for rate control calculations,
+therefore plumb it through from V4L2's [S|G]_PARM ioctl.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c | 52 +++++++++++++++++--
+ 1 file changed, 48 insertions(+), 4 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -447,6 +447,8 @@ struct bcm2835_codec_ctx {
+ /* Source and destination queue data */
+ struct bcm2835_codec_q_data q_data[2];
+ s32 bitrate;
++ unsigned int framerate_num;
++ unsigned int framerate_denom;
+
+ bool aborting;
+ int num_ip_buffers;
+@@ -610,8 +612,8 @@ static void setup_mmal_port_format(struc
+ port->es.video.height = q_data->height;
+ port->es.video.crop.width = q_data->crop_width;
+ port->es.video.crop.height = q_data->crop_height;
+- port->es.video.frame_rate.num = 0;
+- port->es.video.frame_rate.den = 1;
++ port->es.video.frame_rate.num = ctx->framerate_num;
++ port->es.video.frame_rate.den = ctx->framerate_denom;
+ } else {
+ /* Compressed format - leave resolution as 0 for decode */
+ if (ctx->dev->role == DECODE) {
+@@ -625,9 +627,9 @@ static void setup_mmal_port_format(struc
+ port->es.video.crop.width = q_data->crop_width;
+ port->es.video.crop.height = q_data->crop_height;
+ port->format.bitrate = ctx->bitrate;
++ port->es.video.frame_rate.num = ctx->framerate_num;
++ port->es.video.frame_rate.den = ctx->framerate_denom;
+ }
+- port->es.video.frame_rate.num = 0;
+- port->es.video.frame_rate.den = 1;
+ }
+ port->es.video.crop.x = 0;
+ port->es.video.crop.y = 0;
+@@ -1361,6 +1363,41 @@ static int vidioc_s_selection(struct fil
+ return 0;
+ }
+
++static int vidioc_s_parm(struct file *file, void *priv,
++ struct v4l2_streamparm *parm)
++{
++ struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++ if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
++ return -EINVAL;
++
++ ctx->framerate_num =
++ parm->parm.output.timeperframe.denominator;
++ ctx->framerate_denom =
++ parm->parm.output.timeperframe.numerator;
++
++ parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
++
++ return 0;
++}
++
++static int vidioc_g_parm(struct file *file, void *priv,
++ struct v4l2_streamparm *parm)
++{
++ struct bcm2835_codec_ctx *ctx = file2ctx(file);
++
++ if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
++ return -EINVAL;
++
++ parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
++ parm->parm.output.timeperframe.denominator =
++ ctx->framerate_num;
++ parm->parm.output.timeperframe.numerator =
++ ctx->framerate_denom;
++
++ return 0;
++}
++
+ static int vidioc_subscribe_evt(struct v4l2_fh *fh,
+ const struct v4l2_event_subscription *sub)
+ {
+@@ -1725,6 +1762,9 @@ static const struct v4l2_ioctl_ops bcm28
+ .vidioc_g_selection = vidioc_g_selection,
+ .vidioc_s_selection = vidioc_s_selection,
+
++ .vidioc_g_parm = vidioc_g_parm,
++ .vidioc_s_parm = vidioc_s_parm,
++
+ .vidioc_subscribe_event = vidioc_subscribe_evt,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+
+@@ -2546,6 +2586,8 @@ static int bcm2835_codec_create(struct p
+ case DECODE:
+ v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
+ v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
++ v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
++ v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
+ video_nr = decode_video_nr;
+ break;
+ case ENCODE:
+@@ -2558,6 +2600,8 @@ static int bcm2835_codec_create(struct p
+ v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
+ v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
+ v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
++ v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
++ v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
+ video_nr = isp_video_nr;
+ break;
+ default:
+++ /dev/null
-From f022f74f85fa0871e650c1a2fe385d7a24d07d92 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Mon, 3 Jun 2019 14:57:56 +0100
-Subject: [PATCH 517/703] config: Add NF_TABLES support
-
----
- arch/arm/configs/bcm2709_defconfig | 48 ++++++++++++++++++++++++++++++
- arch/arm/configs/bcmrpi_defconfig | 48 ++++++++++++++++++++++++++++++
- 2 files changed, 96 insertions(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -136,6 +136,36 @@ CONFIG_NF_CONNTRACK_SANE=m
- CONFIG_NF_CONNTRACK_SIP=m
- CONFIG_NF_CONNTRACK_TFTP=m
- CONFIG_NF_CT_NETLINK=m
-+CONFIG_NF_TABLES=m
-+CONFIG_NF_TABLES_SET=m
-+CONFIG_NF_TABLES_INET=y
-+CONFIG_NF_TABLES_NETDEV=y
-+CONFIG_NFT_NUMGEN=m
-+CONFIG_NFT_CT=m
-+CONFIG_NFT_FLOW_OFFLOAD=m
-+CONFIG_NFT_COUNTER=m
-+CONFIG_NFT_CONNLIMIT=m
-+CONFIG_NFT_LOG=m
-+CONFIG_NFT_LIMIT=m
-+CONFIG_NFT_MASQ=m
-+CONFIG_NFT_REDIR=m
-+CONFIG_NFT_NAT=m
-+CONFIG_NFT_TUNNEL=m
-+CONFIG_NFT_OBJREF=m
-+CONFIG_NFT_QUEUE=m
-+CONFIG_NFT_QUOTA=m
-+CONFIG_NFT_REJECT=m
-+CONFIG_NFT_COMPAT=m
-+CONFIG_NFT_HASH=m
-+CONFIG_NFT_FIB_INET=m
-+CONFIG_NFT_SOCKET=m
-+CONFIG_NFT_OSF=m
-+CONFIG_NFT_TPROXY=m
-+CONFIG_NFT_DUP_NETDEV=m
-+CONFIG_NFT_FWD_NETDEV=m
-+CONFIG_NFT_FIB_NETDEV=m
-+CONFIG_NF_FLOW_TABLE_INET=m
-+CONFIG_NF_FLOW_TABLE=m
- CONFIG_NETFILTER_XT_SET=m
- CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
- CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-@@ -224,6 +254,14 @@ CONFIG_IP_VS_SED=m
- CONFIG_IP_VS_NQ=m
- CONFIG_IP_VS_FTP=m
- CONFIG_IP_VS_PE_SIP=m
-+CONFIG_NFT_CHAIN_ROUTE_IPV4=m
-+CONFIG_NFT_DUP_IPV4=m
-+CONFIG_NFT_FIB_IPV4=m
-+CONFIG_NF_TABLES_ARP=y
-+CONFIG_NF_FLOW_TABLE_IPV4=m
-+CONFIG_NFT_CHAIN_NAT_IPV4=m
-+CONFIG_NFT_MASQ_IPV4=m
-+CONFIG_NFT_REDIR_IPV4=m
- CONFIG_IP_NF_IPTABLES=m
- CONFIG_IP_NF_MATCH_AH=m
- CONFIG_IP_NF_MATCH_ECN=m
-@@ -243,6 +281,13 @@ CONFIG_IP_NF_RAW=m
- CONFIG_IP_NF_ARPTABLES=m
- CONFIG_IP_NF_ARPFILTER=m
- CONFIG_IP_NF_ARP_MANGLE=m
-+CONFIG_NFT_CHAIN_ROUTE_IPV6=m
-+CONFIG_NFT_CHAIN_NAT_IPV6=m
-+CONFIG_NFT_MASQ_IPV6=m
-+CONFIG_NFT_REDIR_IPV6=m
-+CONFIG_NFT_DUP_IPV6=m
-+CONFIG_NFT_FIB_IPV6=m
-+CONFIG_NF_FLOW_TABLE_IPV6=m
- CONFIG_IP6_NF_IPTABLES=m
- CONFIG_IP6_NF_MATCH_AH=m
- CONFIG_IP6_NF_MATCH_EUI64=m
-@@ -261,6 +306,9 @@ CONFIG_IP6_NF_RAW=m
- CONFIG_IP6_NF_NAT=m
- CONFIG_IP6_NF_TARGET_MASQUERADE=m
- CONFIG_IP6_NF_TARGET_NPT=m
-+CONFIG_NF_TABLES_BRIDGE=y
-+CONFIG_NFT_BRIDGE_REJECT=m
-+CONFIG_NF_LOG_BRIDGE=m
- CONFIG_BRIDGE_NF_EBTABLES=m
- CONFIG_BRIDGE_EBT_BROUTE=m
- CONFIG_BRIDGE_EBT_T_FILTER=m
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -129,6 +129,36 @@ CONFIG_NF_CONNTRACK_SANE=m
- CONFIG_NF_CONNTRACK_SIP=m
- CONFIG_NF_CONNTRACK_TFTP=m
- CONFIG_NF_CT_NETLINK=m
-+CONFIG_NF_TABLES=m
-+CONFIG_NF_TABLES_SET=m
-+CONFIG_NF_TABLES_INET=y
-+CONFIG_NF_TABLES_NETDEV=y
-+CONFIG_NFT_NUMGEN=m
-+CONFIG_NFT_CT=m
-+CONFIG_NFT_FLOW_OFFLOAD=m
-+CONFIG_NFT_COUNTER=m
-+CONFIG_NFT_CONNLIMIT=m
-+CONFIG_NFT_LOG=m
-+CONFIG_NFT_LIMIT=m
-+CONFIG_NFT_MASQ=m
-+CONFIG_NFT_REDIR=m
-+CONFIG_NFT_NAT=m
-+CONFIG_NFT_TUNNEL=m
-+CONFIG_NFT_OBJREF=m
-+CONFIG_NFT_QUEUE=m
-+CONFIG_NFT_QUOTA=m
-+CONFIG_NFT_REJECT=m
-+CONFIG_NFT_COMPAT=m
-+CONFIG_NFT_HASH=m
-+CONFIG_NFT_FIB_INET=m
-+CONFIG_NFT_SOCKET=m
-+CONFIG_NFT_OSF=m
-+CONFIG_NFT_TPROXY=m
-+CONFIG_NFT_DUP_NETDEV=m
-+CONFIG_NFT_FWD_NETDEV=m
-+CONFIG_NFT_FIB_NETDEV=m
-+CONFIG_NF_FLOW_TABLE_INET=m
-+CONFIG_NF_FLOW_TABLE=m
- CONFIG_NETFILTER_XT_SET=m
- CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
- CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-@@ -217,6 +247,14 @@ CONFIG_IP_VS_SED=m
- CONFIG_IP_VS_NQ=m
- CONFIG_IP_VS_FTP=m
- CONFIG_IP_VS_PE_SIP=m
-+CONFIG_NFT_CHAIN_ROUTE_IPV4=m
-+CONFIG_NFT_DUP_IPV4=m
-+CONFIG_NFT_FIB_IPV4=m
-+CONFIG_NF_TABLES_ARP=y
-+CONFIG_NF_FLOW_TABLE_IPV4=m
-+CONFIG_NFT_CHAIN_NAT_IPV4=m
-+CONFIG_NFT_MASQ_IPV4=m
-+CONFIG_NFT_REDIR_IPV4=m
- CONFIG_IP_NF_IPTABLES=m
- CONFIG_IP_NF_MATCH_AH=m
- CONFIG_IP_NF_MATCH_ECN=m
-@@ -236,6 +274,13 @@ CONFIG_IP_NF_RAW=m
- CONFIG_IP_NF_ARPTABLES=m
- CONFIG_IP_NF_ARPFILTER=m
- CONFIG_IP_NF_ARP_MANGLE=m
-+CONFIG_NFT_CHAIN_ROUTE_IPV6=m
-+CONFIG_NFT_CHAIN_NAT_IPV6=m
-+CONFIG_NFT_MASQ_IPV6=m
-+CONFIG_NFT_REDIR_IPV6=m
-+CONFIG_NFT_DUP_IPV6=m
-+CONFIG_NFT_FIB_IPV6=m
-+CONFIG_NF_FLOW_TABLE_IPV6=m
- CONFIG_IP6_NF_IPTABLES=m
- CONFIG_IP6_NF_MATCH_AH=m
- CONFIG_IP6_NF_MATCH_EUI64=m
-@@ -254,6 +299,9 @@ CONFIG_IP6_NF_RAW=m
- CONFIG_IP6_NF_NAT=m
- CONFIG_IP6_NF_TARGET_MASQUERADE=m
- CONFIG_IP6_NF_TARGET_NPT=m
-+CONFIG_NF_TABLES_BRIDGE=y
-+CONFIG_NFT_BRIDGE_REJECT=m
-+CONFIG_NF_LOG_BRIDGE=m
- CONFIG_BRIDGE_NF_EBTABLES=m
- CONFIG_BRIDGE_EBT_BROUTE=m
- CONFIG_BRIDGE_EBT_T_FILTER=m
--- /dev/null
+From bc6a43d8d2aabc061c407d6644f04b9c51b65280 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 12 Jun 2019 17:15:05 +0100
+Subject: [PATCH 517/725] w1: w1-gpio: Make GPIO an output for strong pullup
+
+The logic to drive the data line high to implement a strong pullup
+assumed that the pin was already an output - setting a value does
+not change an input.
+
+See: https://github.com/raspberrypi/firmware/issues/1143
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/w1/masters/w1-gpio.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/w1/masters/w1-gpio.c
++++ b/drivers/w1/masters/w1-gpio.c
+@@ -33,7 +33,7 @@ static u8 w1_gpio_set_pullup(void *data,
+ * This will OVERRIDE open drain emulation and force-pull
+ * the line high for some time.
+ */
+- gpiod_set_raw_value(pdata->gpiod, 1);
++ gpiod_direction_output_raw(pdata->gpiod, 1);
+ msleep(pdata->pullup_duration);
+ /*
+ * This will simply set the line as input since we are doing
+++ /dev/null
-From a06ffe5daac9ef401c406a8aa28b5d20279e0cdb Mon Sep 17 00:00:00 2001
-From: IQaudIO <gordon@iqaudio.com>
-Date: Thu, 6 Jun 2019 10:20:55 +0100
-Subject: [PATCH 518/703] Fixed 48k timing issue
-
----
- sound/soc/bcm/iqaudio-codec.c | 33 ++++++++++++++++++++++++++++-----
- 1 file changed, 28 insertions(+), 5 deletions(-)
-
---- a/sound/soc/bcm/iqaudio-codec.c
-+++ b/sound/soc/bcm/iqaudio-codec.c
-@@ -45,11 +45,15 @@ static int snd_rpi_iqaudio_pll_control(s
- 0);
- if (ret)
- dev_err(card->dev, "Failed to bypass PLL: %d\n", ret);
-+ /* Allow PLL time to bypass */
-+ msleep(100);
- } else if (SND_SOC_DAPM_EVENT_ON(event)) {
- ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_PLL, 0,
- pll_out);
- if (ret)
- dev_err(card->dev, "Failed to enable PLL: %d\n", ret);
-+ /* Allow PLL time to lock */
-+ msleep(100);
- }
-
- return ret;
-@@ -71,6 +75,13 @@ static int snd_rpi_iqaudio_post_dapm_eve
- return 0;
- }
-
-+static const struct snd_kcontrol_new dapm_controls[] = {
-+ SOC_DAPM_PIN_SWITCH("HP Jack"),
-+ SOC_DAPM_PIN_SWITCH("MIC Jack"),
-+ SOC_DAPM_PIN_SWITCH("Onboard MIC"),
-+ SOC_DAPM_PIN_SWITCH("AUX Jack"),
-+};
-+
- static const struct snd_soc_dapm_widget dapm_widgets[] = {
- SND_SOC_DAPM_HP("HP Jack", NULL),
- SND_SOC_DAPM_MIC("MIC Jack", NULL),
-@@ -87,14 +98,14 @@ static const struct snd_soc_dapm_route a
- {"HP Jack", NULL, "HPR"},
- {"HP Jack", NULL, "PLL Control"},
-
-- {"AUX Jack", NULL, "AUXR"},
-- {"AUX Jack", NULL, "AUXL"},
-+ {"AUXR", NULL, "AUX Jack"},
-+ {"AUXL", NULL, "AUX Jack"},
- {"AUX Jack", NULL, "PLL Control"},
-
- /* Assume Mic1 is linked to Headset and Mic2 to on-board mic */
-- {"MIC Jack", NULL, "MIC1"},
-+ {"MIC1", NULL, "MIC Jack"},
- {"MIC Jack", NULL, "PLL Control"},
-- {"Onboard MIC", NULL, "MIC2"},
-+ {"MIC2", NULL, "Onboard MIC"},
- {"Onboard MIC", NULL, "PLL Control"},
- };
-
-@@ -106,6 +117,16 @@ static int snd_rpi_iqaudio_codec_init(st
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int ret;
-
-+ /*
-+ * Disable AUX Jack Pin by default to prevent PLL being enabled at
-+ * startup. This avoids holding the PLL to a fixed SR config for
-+ * subsequent streams.
-+ *
-+ * This pin can still be enabled later, as required by user-space.
-+ */
-+ snd_soc_dapm_disable_pin(&rtd->card->dapm, "AUX Jack");
-+ snd_soc_dapm_sync(&rtd->card->dapm);
-+
- /* Set bclk ratio to align with codec's BCLK rate */
- ret = snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
- if (ret) {
-@@ -168,6 +189,8 @@ static struct snd_soc_card snd_rpi_iqaud
- .owner = THIS_MODULE,
- .dai_link = snd_rpi_iqaudio_codec_dai,
- .num_links = ARRAY_SIZE(snd_rpi_iqaudio_codec_dai),
-+ .controls = dapm_controls,
-+ .num_controls = ARRAY_SIZE(dapm_controls),
- .dapm_widgets = dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(dapm_widgets),
- .dapm_routes = audio_map,
-@@ -204,7 +227,7 @@ static int snd_rpi_iqaudio_codec_probe(s
-
- if (of_property_read_string(pdev->dev.of_node,
- "dai_stream_name", &dai->stream_name))
-- dai->stream_name = "IQaudIO CODEC HiFi v1.1";
-+ dai->stream_name = "IQaudIO CODEC HiFi v1.2";
-
- }
-
--- /dev/null
+From 62e3712d23602b04dd28340ea05643708d603241 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 12 Jun 2019 17:32:11 +0100
+Subject: [PATCH 518/725] overlays: Update w1-gpio and w1-gpio-pullup
+
+The parasitic power (power on data) feature is now enabled by
+default in the w1-gpio driver, so update the README and make the
+"pullup" parameter a no-op.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README | 9 ++-------
+ arch/arm/boot/dts/overlays/w1-gpio-overlay.dts | 3 +--
+ arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts | 3 +--
+ 3 files changed, 4 insertions(+), 11 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2261,9 +2261,7 @@ Info: Configures the w1-gpio Onewire i
+ Use this overlay if you *don't* need a GPIO to drive an external pullup.
+ Load: dtoverlay=w1-gpio,<param>=<val>
+ Params: gpiopin GPIO for I/O (default "4")
+-
+- pullup Non-zero, "on", or "y" to enable the parasitic
+- power (2-wire, power-on-data) feature
++ pullup Now enabled by default (ignored)
+
+
+ Name: w1-gpio-pullup
+@@ -2271,11 +2269,8 @@ Info: Configures the w1-gpio Onewire i
+ Use this overlay if you *do* need a GPIO to drive an external pullup.
+ Load: dtoverlay=w1-gpio-pullup,<param>=<val>
+ Params: gpiopin GPIO for I/O (default "4")
+-
+- pullup Non-zero, "on", or "y" to enable the parasitic
+- power (2-wire, power-on-data) feature
+-
+ extpullup GPIO for external pullup (default "5")
++ pullup Now enabled by default (ignored)
+
+
+ Name: wittypi
+--- a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
+@@ -14,7 +14,6 @@
+ pinctrl-names = "default";
+ pinctrl-0 = <&w1_pins>;
+ gpios = <&gpio 4 0>;
+- rpi,parasitic-power = <0>;
+ status = "okay";
+ };
+ };
+@@ -36,6 +35,6 @@
+ <&w1>,"reg:0",
+ <&w1_pins>,"brcm,pins:0",
+ <&w1_pins>,"reg:0";
+- pullup = <&w1>,"rpi,parasitic-power:0";
++ pullup; // Silently ignore unneeded parameter
+ };
+ };
+--- a/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
++++ b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
+@@ -14,7 +14,6 @@
+ pinctrl-names = "default";
+ pinctrl-0 = <&w1_pins>;
+ gpios = <&gpio 4 0>, <&gpio 5 1>;
+- rpi,parasitic-power = <0>;
+ status = "okay";
+ };
+ };
+@@ -38,6 +37,6 @@
+ <&w1_pins>,"reg:0";
+ extpullup = <&w1>,"gpios:16",
+ <&w1_pins>,"brcm,pins:4";
+- pullup = <&w1>,"rpi,parasitic-power:0";
++ pullup; // Silently ignore unneeded parameter
+ };
+ };
--- /dev/null
+From f6ed43e4cef98ce5d000f809af5f03d57a5b2e34 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 12 Jun 2019 20:45:17 +0100
+Subject: [PATCH 519/725] bcm2835-sdhost: Fix DMA channel leak on error/remove
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/mmc/host/bcm2835-sdhost.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/mmc/host/bcm2835-sdhost.c
++++ b/drivers/mmc/host/bcm2835-sdhost.c
+@@ -2154,6 +2154,8 @@ static int bcm2835_sdhost_probe(struct p
+
+ err:
+ pr_debug("bcm2835_sdhost_probe -> err %d\n", ret);
++ if (host->dma_chan_rxtx)
++ dma_release_channel(host->dma_chan_rxtx);
+ mmc_free_host(mmc);
+
+ return ret;
+@@ -2174,7 +2176,8 @@ static int bcm2835_sdhost_remove(struct
+ del_timer_sync(&host->timer);
+
+ tasklet_kill(&host->finish_tasklet);
+-
++ if (host->dma_chan_rxtx)
++ dma_release_channel(host->dma_chan_rxtx);
+ mmc_free_host(host->mmc);
+ platform_set_drvdata(pdev, NULL);
+
+++ /dev/null
-From 58b048261814bb8763573cac6146079ed8813f65 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 10 May 2019 14:11:58 +0100
-Subject: [PATCH 519/703] staging: bcm2835-codec: Convert V4L2 nsec timestamps
- to MMAL usec
-
-V4L2 uses nsecs, whilst MMAL uses usecs, but the code wasn't converting
-between them. This upsets video encode rate control.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -823,7 +823,8 @@ static void op_buffer_cb(struct vchiq_mm
- vb2->flags |= V4L2_BUF_FLAG_LAST;
- }
-
-- vb2->vb2_buf.timestamp = mmal_buf->pts;
-+ /* vb2 timestamps in nsecs, mmal in usecs */
-+ vb2->vb2_buf.timestamp = mmal_buf->pts * 1000;
-
- vb2_set_plane_payload(&vb2->vb2_buf, 0, mmal_buf->length);
- if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
-@@ -847,6 +848,7 @@ static void op_buffer_cb(struct vchiq_mm
- static void vb2_to_mmal_buffer(struct m2m_mmal_buffer *buf,
- struct vb2_v4l2_buffer *vb2)
- {
-+ u64 pts;
- buf->mmal.mmal_flags = 0;
- if (vb2->flags & V4L2_BUF_FLAG_KEYFRAME)
- buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_KEYFRAME;
-@@ -869,7 +871,10 @@ static void vb2_to_mmal_buffer(struct m2
- if (!buf->mmal.length || vb2->flags & V4L2_BUF_FLAG_LAST)
- buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
-
-- buf->mmal.pts = vb2->vb2_buf.timestamp;
-+ /* vb2 timestamps in nsecs, mmal in usecs */
-+ pts = vb2->vb2_buf.timestamp;
-+ do_div(pts, 1000);
-+ buf->mmal.pts = pts;
- buf->mmal.dts = MMAL_TIME_UNKNOWN;
- }
-
--- /dev/null
+From 77a612fb674f924495a3a9a36ea60fb30d86644a Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Sat, 8 Jun 2019 10:14:43 -0700
+Subject: [PATCH 520/725] i2c: bcm2835: Model Divider in CCF
+
+Commit bebff81fb8b9216eb4fba22cf910553621ae3477 upstream.
+
+Model the I2C bus clock divider as a part of the Core Clock Framework.
+Primarily this removes the clk_get_rate() call from each transfer.
+This call causes problems for slave drivers that themselves have
+internal clock components that are controlled by an I2C interface.
+When the slave's internal clock component is prepared, the prepare
+lock is obtained, and it makes calls to the I2C subsystem to
+command the hardware to activate the clock. In order to perform
+the I2C transfer, this driver sets the divider, which requires
+it to get the parent clock rate, which it does with clk_get_rate().
+Unfortunately, this function will try to take the clock prepare
+lock, which is already held by the slave's internal clock calls
+creating a deadlock.
+
+Modeling the divider in the CCF natively removes this dependency
+and the divider value is only set upon changing the bus clock
+frequency or changes in the parent clock that cascade down to this
+divisor. This obviates the need to set the divider with every
+transfer and avoids the deadlock described above. It also should
+provide better clock debugging and save a few cycles on each
+transfer due to not having to recalcuate the divider value.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 145 ++++++++++++++++++++++++-------
+ 1 file changed, 114 insertions(+), 31 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -12,6 +12,8 @@
+ */
+
+ #include <linux/clk.h>
++#include <linux/clkdev.h>
++#include <linux/clk-provider.h>
+ #include <linux/completion.h>
+ #include <linux/err.h>
+ #include <linux/i2c.h>
+@@ -71,9 +73,7 @@ struct bcm2835_debug {
+ struct bcm2835_i2c_dev {
+ struct device *dev;
+ void __iomem *regs;
+- struct clk *clk;
+ int irq;
+- u32 bus_clk_rate;
+ struct i2c_adapter adapter;
+ struct completion completion;
+ struct i2c_msg *curr_msg;
+@@ -164,12 +164,17 @@ static inline u32 bcm2835_i2c_readl(stru
+ return readl(i2c_dev->regs + reg);
+ }
+
+-static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev)
++#define to_clk_bcm2835_i2c(_hw) container_of(_hw, struct clk_bcm2835_i2c, hw)
++struct clk_bcm2835_i2c {
++ struct clk_hw hw;
++ struct bcm2835_i2c_dev *i2c_dev;
++};
++
++static int clk_bcm2835_i2c_calc_divider(unsigned long rate,
++ unsigned long parent_rate)
+ {
+- u32 divider, redl, fedl;
++ u32 divider = DIV_ROUND_UP(parent_rate, rate);
+
+- divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk),
+- i2c_dev->bus_clk_rate);
+ /*
+ * Per the datasheet, the register is always interpreted as an even
+ * number, by rounding down. In other words, the LSB is ignored. So,
+@@ -178,12 +183,23 @@ static int bcm2835_i2c_set_divider(struc
+ if (divider & 1)
+ divider++;
+ if ((divider < BCM2835_I2C_CDIV_MIN) ||
+- (divider > BCM2835_I2C_CDIV_MAX)) {
+- dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n");
++ (divider > BCM2835_I2C_CDIV_MAX))
+ return -EINVAL;
+- }
+
+- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider);
++ return divider;
++}
++
++static int clk_bcm2835_i2c_set_rate(struct clk_hw *hw, unsigned long rate,
++ unsigned long parent_rate)
++{
++ struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
++ u32 redl, fedl;
++ u32 divider = clk_bcm2835_i2c_calc_divider(rate, parent_rate);
++
++ if (divider == -EINVAL)
++ return -EINVAL;
++
++ bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DIV, divider);
+
+ /*
+ * Number of core clocks to wait after falling edge before
+@@ -198,12 +214,62 @@ static int bcm2835_i2c_set_divider(struc
+ */
+ redl = max(divider / 4, 1u);
+
+- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DEL,
++ bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DEL,
+ (fedl << BCM2835_I2C_FEDL_SHIFT) |
+ (redl << BCM2835_I2C_REDL_SHIFT));
+ return 0;
+ }
+
++static long clk_bcm2835_i2c_round_rate(struct clk_hw *hw, unsigned long rate,
++ unsigned long *parent_rate)
++{
++ u32 divider = clk_bcm2835_i2c_calc_divider(rate, *parent_rate);
++
++ return DIV_ROUND_UP(*parent_rate, divider);
++}
++
++static unsigned long clk_bcm2835_i2c_recalc_rate(struct clk_hw *hw,
++ unsigned long parent_rate)
++{
++ struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
++ u32 divider = bcm2835_i2c_readl(div->i2c_dev, BCM2835_I2C_DIV);
++
++ return DIV_ROUND_UP(parent_rate, divider);
++}
++
++static const struct clk_ops clk_bcm2835_i2c_ops = {
++ .set_rate = clk_bcm2835_i2c_set_rate,
++ .round_rate = clk_bcm2835_i2c_round_rate,
++ .recalc_rate = clk_bcm2835_i2c_recalc_rate,
++};
++
++static struct clk *bcm2835_i2c_register_div(struct device *dev,
++ const char *mclk_name,
++ struct bcm2835_i2c_dev *i2c_dev)
++{
++ struct clk_init_data init;
++ struct clk_bcm2835_i2c *priv;
++ char name[32];
++
++ snprintf(name, sizeof(name), "%s_div", dev_name(dev));
++
++ init.ops = &clk_bcm2835_i2c_ops;
++ init.name = name;
++ init.parent_names = (const char* []) { mclk_name };
++ init.num_parents = 1;
++ init.flags = 0;
++
++ priv = devm_kzalloc(dev, sizeof(struct clk_bcm2835_i2c), GFP_KERNEL);
++ if (priv == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ priv->hw.init = &init;
++ priv->i2c_dev = i2c_dev;
++
++ clk_hw_register_clkdev(&priv->hw, "div", dev_name(dev));
++ return devm_clk_register(dev, &priv->hw);
++}
++
+ static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev)
+ {
+ u32 val;
+@@ -363,7 +429,7 @@ static int bcm2835_i2c_xfer(struct i2c_a
+ {
+ struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+ unsigned long time_left;
+- int i, ret;
++ int i;
+
+ if (debug)
+ i2c_dev->debug_num_msgs = num;
+@@ -379,10 +445,6 @@ static int bcm2835_i2c_xfer(struct i2c_a
+ return -EOPNOTSUPP;
+ }
+
+- ret = bcm2835_i2c_set_divider(i2c_dev);
+- if (ret)
+- return ret;
+-
+ i2c_dev->curr_msg = msgs;
+ i2c_dev->num_msgs = num;
+ reinit_completion(&i2c_dev->completion);
+@@ -443,6 +505,9 @@ static int bcm2835_i2c_probe(struct plat
+ struct resource *mem, *irq;
+ int ret;
+ struct i2c_adapter *adap;
++ const char *mclk_name;
++ struct clk *bus_clk;
++ u32 bus_clk_rate;
+
+ i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
+ if (!i2c_dev)
+@@ -456,21 +521,6 @@ static int bcm2835_i2c_probe(struct plat
+ if (IS_ERR(i2c_dev->regs))
+ return PTR_ERR(i2c_dev->regs);
+
+- i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
+- if (IS_ERR(i2c_dev->clk)) {
+- if (PTR_ERR(i2c_dev->clk) != -EPROBE_DEFER)
+- dev_err(&pdev->dev, "Could not get clock\n");
+- return PTR_ERR(i2c_dev->clk);
+- }
+-
+- ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+- &i2c_dev->bus_clk_rate);
+- if (ret < 0) {
+- dev_warn(&pdev->dev,
+- "Could not read clock-frequency property\n");
+- i2c_dev->bus_clk_rate = 100000;
+- }
+-
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq) {
+ dev_err(&pdev->dev, "No IRQ resource\n");
+@@ -485,6 +535,35 @@ static int bcm2835_i2c_probe(struct plat
+ return -ENODEV;
+ }
+
++ mclk_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
++
++ bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk_name, i2c_dev);
++
++ if (IS_ERR(bus_clk)) {
++ dev_err(&pdev->dev, "Could not register clock\n");
++ return PTR_ERR(bus_clk);
++ }
++
++ ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
++ &bus_clk_rate);
++ if (ret < 0) {
++ dev_warn(&pdev->dev,
++ "Could not read clock-frequency property\n");
++ bus_clk_rate = 100000;
++ }
++
++ ret = clk_set_rate_exclusive(bus_clk, bus_clk_rate);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "Could not set clock frequency\n");
++ return ret;
++ }
++
++ ret = clk_prepare_enable(bus_clk);
++ if (ret) {
++ dev_err(&pdev->dev, "Couldn't prepare clock");
++ return ret;
++ }
++
+ adap = &i2c_dev->adapter;
+ i2c_set_adapdata(adap, i2c_dev);
+ adap->owner = THIS_MODULE;
+@@ -507,6 +586,10 @@ static int bcm2835_i2c_probe(struct plat
+ static int bcm2835_i2c_remove(struct platform_device *pdev)
+ {
+ struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
++ struct clk *bus_clk = devm_clk_get(i2c_dev->dev, "div");
++
++ clk_rate_exclusive_put(bus_clk);
++ clk_disable_unprepare(bus_clk);
+
+ free_irq(i2c_dev->irq, i2c_dev);
+ i2c_del_adapter(&i2c_dev->adapter);
+++ /dev/null
-From 17100548de7995412237633c58c4e04a11a6d5ed Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 10 May 2019 14:13:11 +0100
-Subject: [PATCH 520/703] staging: bcm2835-codec: Add support for setting
- S_PARM and G_PARM
-
-Video encode can use the frame rate for rate control calculations,
-therefore plumb it through from V4L2's [S|G]_PARM ioctl.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../bcm2835-codec/bcm2835-v4l2-codec.c | 52 +++++++++++++++++--
- 1 file changed, 48 insertions(+), 4 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
-@@ -447,6 +447,8 @@ struct bcm2835_codec_ctx {
- /* Source and destination queue data */
- struct bcm2835_codec_q_data q_data[2];
- s32 bitrate;
-+ unsigned int framerate_num;
-+ unsigned int framerate_denom;
-
- bool aborting;
- int num_ip_buffers;
-@@ -610,8 +612,8 @@ static void setup_mmal_port_format(struc
- port->es.video.height = q_data->height;
- port->es.video.crop.width = q_data->crop_width;
- port->es.video.crop.height = q_data->crop_height;
-- port->es.video.frame_rate.num = 0;
-- port->es.video.frame_rate.den = 1;
-+ port->es.video.frame_rate.num = ctx->framerate_num;
-+ port->es.video.frame_rate.den = ctx->framerate_denom;
- } else {
- /* Compressed format - leave resolution as 0 for decode */
- if (ctx->dev->role == DECODE) {
-@@ -625,9 +627,9 @@ static void setup_mmal_port_format(struc
- port->es.video.crop.width = q_data->crop_width;
- port->es.video.crop.height = q_data->crop_height;
- port->format.bitrate = ctx->bitrate;
-+ port->es.video.frame_rate.num = ctx->framerate_num;
-+ port->es.video.frame_rate.den = ctx->framerate_denom;
- }
-- port->es.video.frame_rate.num = 0;
-- port->es.video.frame_rate.den = 1;
- }
- port->es.video.crop.x = 0;
- port->es.video.crop.y = 0;
-@@ -1361,6 +1363,41 @@ static int vidioc_s_selection(struct fil
- return 0;
- }
-
-+static int vidioc_s_parm(struct file *file, void *priv,
-+ struct v4l2_streamparm *parm)
-+{
-+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+ if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-+ return -EINVAL;
-+
-+ ctx->framerate_num =
-+ parm->parm.output.timeperframe.denominator;
-+ ctx->framerate_denom =
-+ parm->parm.output.timeperframe.numerator;
-+
-+ parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
-+
-+ return 0;
-+}
-+
-+static int vidioc_g_parm(struct file *file, void *priv,
-+ struct v4l2_streamparm *parm)
-+{
-+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
-+
-+ if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-+ return -EINVAL;
-+
-+ parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
-+ parm->parm.output.timeperframe.denominator =
-+ ctx->framerate_num;
-+ parm->parm.output.timeperframe.numerator =
-+ ctx->framerate_denom;
-+
-+ return 0;
-+}
-+
- static int vidioc_subscribe_evt(struct v4l2_fh *fh,
- const struct v4l2_event_subscription *sub)
- {
-@@ -1725,6 +1762,9 @@ static const struct v4l2_ioctl_ops bcm28
- .vidioc_g_selection = vidioc_g_selection,
- .vidioc_s_selection = vidioc_s_selection,
-
-+ .vidioc_g_parm = vidioc_g_parm,
-+ .vidioc_s_parm = vidioc_s_parm,
-+
- .vidioc_subscribe_event = vidioc_subscribe_evt,
- .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-
-@@ -2546,6 +2586,8 @@ static int bcm2835_codec_create(struct p
- case DECODE:
- v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
- v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
-+ v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
-+ v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
- video_nr = decode_video_nr;
- break;
- case ENCODE:
-@@ -2558,6 +2600,8 @@ static int bcm2835_codec_create(struct p
- v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
- v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
- v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
-+ v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
-+ v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
- video_nr = isp_video_nr;
- break;
- default:
--- /dev/null
+From 29fb40874924e09b1a1063ef8155fdf77df4b9fd Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 17 Sep 2018 09:22:21 +0100
+Subject: [PATCH 521/725] staging/vc04_services: Use correct cache line size
+
+Use the compatible string in the DTB to select the correct cache line
+size for the SoC - 32 for BCM2835, and 64 for BCM2836 and BCM2837.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../interface/vchiq_arm/vchiq_2835_arm.c | 15 ++------
+ .../interface/vchiq_arm/vchiq_arm.c | 35 +++++++++++++------
+ .../interface/vchiq_arm/vchiq_arm.h | 5 +++
+ 3 files changed, 33 insertions(+), 22 deletions(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
+@@ -117,7 +117,8 @@ free_pagelist(struct vchiq_pagelist_info
+ int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state)
+ {
+ struct device *dev = &pdev->dev;
+- struct rpi_firmware *fw = platform_get_drvdata(pdev);
++ struct vchiq_drvdata *drvdata = platform_get_drvdata(pdev);
++ struct rpi_firmware *fw = drvdata->fw;
+ VCHIQ_SLOT_ZERO_T *vchiq_slot_zero;
+ struct resource *res;
+ void *slot_mem;
+@@ -135,17 +136,7 @@ int vchiq_platform_init(struct platform_
+ if (err < 0)
+ return err;
+
+- /*
+- * The tempting L1_CACHE_BYTES macro doesn't work in the case of
+- * a kernel built with bcm2835_defconfig running on a BCM2836/7
+- * processor, hence the need for a runtime check. The dcache line size
+- * is encoded in one of the coprocessor registers, but there is no
+- * convenient way to access it short of embedded assembler, hence
+- * the use of read_cpuid_id(). The following test evaluates to true
+- * on a BCM2835 showing that it is ARMv6-ish, whereas
+- * cpu_architecture() will indicate that it is an ARMv7.
+- */
+- g_cache_line_size = ((read_cpuid_id() & 0x7f000) == 0x7b000) ? 32 : 64;
++ g_cache_line_size = drvdata->cache_line_size;
+ g_fragments_size = 2 * g_cache_line_size;
+
+ /* Allocate space for the channels in coherent memory */
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -173,6 +173,14 @@ static struct platform_device *bcm2835_c
+ static struct platform_device *bcm2835_codec;
+ static struct platform_device *vcsm_cma;
+
++static struct vchiq_drvdata bcm2835_drvdata = {
++ .cache_line_size = 32,
++};
++
++static struct vchiq_drvdata bcm2836_drvdata = {
++ .cache_line_size = 64,
++};
++
+ static const char *const ioctl_names[] = {
+ "CONNECT",
+ "SHUTDOWN",
+@@ -3607,12 +3615,25 @@ vchiq_register_child(struct platform_dev
+ return new_dev;
+ }
+
++static const struct of_device_id vchiq_of_match[] = {
++ { .compatible = "brcm,bcm2835-vchiq", .data = &bcm2835_drvdata },
++ { .compatible = "brcm,bcm2836-vchiq", .data = &bcm2836_drvdata },
++ {},
++};
++MODULE_DEVICE_TABLE(of, vchiq_of_match);
++
+ static int vchiq_probe(struct platform_device *pdev)
+ {
+ struct device_node *fw_node;
+- struct rpi_firmware *fw;
++ const struct of_device_id *of_id;
++ struct vchiq_drvdata *drvdata;
+ int err;
+
++ of_id = of_match_node(vchiq_of_match, pdev->dev.of_node);
++ drvdata = (struct vchiq_drvdata *)of_id->data;
++ if (!drvdata)
++ return -EINVAL;
++
+ fw_node = of_find_compatible_node(NULL, NULL,
+ "raspberrypi,bcm2835-firmware");
+ if (!fw_node) {
+@@ -3620,12 +3641,12 @@ static int vchiq_probe(struct platform_d
+ return -ENOENT;
+ }
+
+- fw = rpi_firmware_get(fw_node);
++ drvdata->fw = rpi_firmware_get(fw_node);
+ of_node_put(fw_node);
+- if (!fw)
++ if (!drvdata->fw)
+ return -EPROBE_DEFER;
+
+- platform_set_drvdata(pdev, fw);
++ platform_set_drvdata(pdev, drvdata);
+
+ err = vchiq_platform_init(pdev, &g_state);
+ if (err != 0)
+@@ -3703,12 +3724,6 @@ static int vchiq_remove(struct platform_
+ return 0;
+ }
+
+-static const struct of_device_id vchiq_of_match[] = {
+- { .compatible = "brcm,bcm2835-vchiq", },
+- {},
+-};
+-MODULE_DEVICE_TABLE(of, vchiq_of_match);
+-
+ static struct platform_driver vchiq_driver = {
+ .driver = {
+ .name = "bcm2835_vchiq",
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
+@@ -123,6 +123,11 @@ typedef struct vchiq_arm_state_struct {
+
+ } VCHIQ_ARM_STATE_T;
+
++struct vchiq_drvdata {
++ const unsigned int cache_line_size;
++ struct rpi_firmware *fw;
++};
++
+ extern int vchiq_arm_log_level;
+ extern int vchiq_susp_log_level;
+
+++ /dev/null
-From d4b6aeeb564bcc56316ba15eaa62d25400dde175 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 12 Jun 2019 17:15:05 +0100
-Subject: [PATCH 521/703] w1: w1-gpio: Make GPIO an output for strong pullup
-
-The logic to drive the data line high to implement a strong pullup
-assumed that the pin was already an output - setting a value does
-not change an input.
-
-See: https://github.com/raspberrypi/firmware/issues/1143
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/w1/masters/w1-gpio.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/w1/masters/w1-gpio.c
-+++ b/drivers/w1/masters/w1-gpio.c
-@@ -33,7 +33,7 @@ static u8 w1_gpio_set_pullup(void *data,
- * This will OVERRIDE open drain emulation and force-pull
- * the line high for some time.
- */
-- gpiod_set_raw_value(pdata->gpiod, 1);
-+ gpiod_direction_output_raw(pdata->gpiod, 1);
- msleep(pdata->pullup_duration);
- /*
- * This will simply set the line as input since we are doing
+++ /dev/null
-From f182f8725cc6a5cccd7f513268e311e5037eca03 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 12 Jun 2019 17:32:11 +0100
-Subject: [PATCH 522/703] overlays: Update w1-gpio and w1-gpio-pullup
-
-The parasitic power (power on data) feature is now enabled by
-default in the w1-gpio driver, so update the README and make the
-"pullup" parameter a no-op.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README | 9 ++-------
- arch/arm/boot/dts/overlays/w1-gpio-overlay.dts | 3 +--
- arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts | 3 +--
- 3 files changed, 4 insertions(+), 11 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -2261,9 +2261,7 @@ Info: Configures the w1-gpio Onewire i
- Use this overlay if you *don't* need a GPIO to drive an external pullup.
- Load: dtoverlay=w1-gpio,<param>=<val>
- Params: gpiopin GPIO for I/O (default "4")
--
-- pullup Non-zero, "on", or "y" to enable the parasitic
-- power (2-wire, power-on-data) feature
-+ pullup Now enabled by default (ignored)
-
-
- Name: w1-gpio-pullup
-@@ -2271,11 +2269,8 @@ Info: Configures the w1-gpio Onewire i
- Use this overlay if you *do* need a GPIO to drive an external pullup.
- Load: dtoverlay=w1-gpio-pullup,<param>=<val>
- Params: gpiopin GPIO for I/O (default "4")
--
-- pullup Non-zero, "on", or "y" to enable the parasitic
-- power (2-wire, power-on-data) feature
--
- extpullup GPIO for external pullup (default "5")
-+ pullup Now enabled by default (ignored)
-
-
- Name: wittypi
---- a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts
-@@ -14,7 +14,6 @@
- pinctrl-names = "default";
- pinctrl-0 = <&w1_pins>;
- gpios = <&gpio 4 0>;
-- rpi,parasitic-power = <0>;
- status = "okay";
- };
- };
-@@ -36,6 +35,6 @@
- <&w1>,"reg:0",
- <&w1_pins>,"brcm,pins:0",
- <&w1_pins>,"reg:0";
-- pullup = <&w1>,"rpi,parasitic-power:0";
-+ pullup; // Silently ignore unneeded parameter
- };
- };
---- a/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts
-@@ -14,7 +14,6 @@
- pinctrl-names = "default";
- pinctrl-0 = <&w1_pins>;
- gpios = <&gpio 4 0>, <&gpio 5 1>;
-- rpi,parasitic-power = <0>;
- status = "okay";
- };
- };
-@@ -38,6 +37,6 @@
- <&w1_pins>,"reg:0";
- extpullup = <&w1>,"gpios:16",
- <&w1_pins>,"brcm,pins:4";
-- pullup = <&w1>,"rpi,parasitic-power:0";
-+ pullup; // Silently ignore unneeded parameter
- };
- };
--- /dev/null
+From e30c029a882170cfc57612129b4eebff56f7cd6b Mon Sep 17 00:00:00 2001
+From: Doug Berger <opendmb@gmail.com>
+Date: Mon, 13 May 2019 20:59:45 +0200
+Subject: [PATCH 522/725] tty: amba-pl011: allow shared interrupt
+
+The PL011 register space includes all necessary status bits to
+determine whether a device instance requires handling in response
+to an interrupt. Therefore, multiple instances of the device could
+be serviced by a single shared interrupt, which is the case on BCM7211.
+
+Signed-off-by: Doug Berger <opendmb@gmail.com>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ drivers/tty/serial/amba-pl011.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/tty/serial/amba-pl011.c
++++ b/drivers/tty/serial/amba-pl011.c
+@@ -1735,7 +1735,8 @@ static int pl011_allocate_irq(struct uar
+ {
+ pl011_write(uap->im, uap, REG_IMSC);
+
+- return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
++ return request_irq(uap->port.irq, pl011_int, IRQF_SHARED, "uart-pl011",
++ uap);
+ }
+
+ /*
--- /dev/null
+From 7739b8497c229fdac29640985e0dba9c8d6f04f1 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sun, 19 May 2019 12:20:00 +0200
+Subject: [PATCH 523/725] ARM: bcm283x: Reduce register ranges for UART, SPI
+ and I2C
+
+The assigned register ranges for UART, SPI and I2C were too wasteful.
+In order to avoid overlapping with the new functions on BCM2838
+reduce the ranges.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ arch/arm/boot/dts/bcm283x.dtsi | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -387,7 +387,7 @@
+
+ uart0: serial@7e201000 {
+ compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
+- reg = <0x7e201000 0x1000>;
++ reg = <0x7e201000 0x200>;
+ interrupts = <2 25>;
+ clocks = <&clocks BCM2835_CLOCK_UART>,
+ <&clocks BCM2835_CLOCK_VPU>;
+@@ -418,7 +418,7 @@
+
+ spi: spi@7e204000 {
+ compatible = "brcm,bcm2835-spi";
+- reg = <0x7e204000 0x1000>;
++ reg = <0x7e204000 0x200>;
+ interrupts = <2 22>;
+ clocks = <&clocks BCM2835_CLOCK_VPU>;
+ #address-cells = <1>;
+@@ -428,7 +428,7 @@
+
+ i2c0: i2c@7e205000 {
+ compatible = "brcm,bcm2835-i2c";
+- reg = <0x7e205000 0x1000>;
++ reg = <0x7e205000 0x200>;
+ interrupts = <2 21>;
+ clocks = <&clocks BCM2835_CLOCK_VPU>;
+ #address-cells = <1>;
+++ /dev/null
-From 578084fa26af562bc35db7175ea7784a01f87f87 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 12 Jun 2019 20:45:17 +0100
-Subject: [PATCH 523/703] bcm2835-sdhost: Fix DMA channel leak on error/remove
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/mmc/host/bcm2835-sdhost.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
---- a/drivers/mmc/host/bcm2835-sdhost.c
-+++ b/drivers/mmc/host/bcm2835-sdhost.c
-@@ -2154,6 +2154,8 @@ static int bcm2835_sdhost_probe(struct p
-
- err:
- pr_debug("bcm2835_sdhost_probe -> err %d\n", ret);
-+ if (host->dma_chan_rxtx)
-+ dma_release_channel(host->dma_chan_rxtx);
- mmc_free_host(mmc);
-
- return ret;
-@@ -2174,7 +2176,8 @@ static int bcm2835_sdhost_remove(struct
- del_timer_sync(&host->timer);
-
- tasklet_kill(&host->finish_tasklet);
--
-+ if (host->dma_chan_rxtx)
-+ dma_release_channel(host->dma_chan_rxtx);
- mmc_free_host(host->mmc);
- platform_set_drvdata(pdev, NULL);
-
--- /dev/null
+From bd7335b5e204cf0dc88550497fbd12002a0f35d5 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 12 Dec 2018 15:51:49 -0800
+Subject: [PATCH 524/725] ARM: bcm283x: Extend the WDT DT node out to cover the
+ whole PM block. (v4)
+
+It was covering part of the PM block's range, up to the WDT regs. To
+support the rest of the PM block's functionality, we need the full
+register range plus the AXI Async Bridge regs for PM sequencing.
+
+This doesn't convert any of the consumers over to the new binding yet,
+since we will need to be careful in coordinating our usage of firmware
+services that might power domains on and off versus the bcm2835-pm
+driver's access of those same domains.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+(cherry picked from commit 29abc92c1d93e28a8f4d55e6343eec4faf44025a)
+---
+ arch/arm/boot/dts/bcm283x.dtsi | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -121,8 +121,17 @@
+ };
+
+ watchdog@7e100000 {
+- compatible = "brcm,bcm2835-pm-wdt";
+- reg = <0x7e100000 0x28>;
++ compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
++ #power-domain-cells = <1>;
++ #reset-cells = <1>;
++ reg = <0x7e100000 0x114>,
++ <0x7e00a000 0x24>;
++ clocks = <&clocks BCM2835_CLOCK_V3D>,
++ <&clocks BCM2835_CLOCK_PERI_IMAGE>,
++ <&clocks BCM2835_CLOCK_H264>,
++ <&clocks BCM2835_CLOCK_ISP>;
++ clock-names = "v3d", "peri_image", "h264", "isp";
++ system-power-controller;
+ };
+
+ clocks: cprman@7e101000 {
+++ /dev/null
-From c86d0f6bfecc53a44e753f14238921ababae29d4 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Sat, 8 Jun 2019 10:14:43 -0700
-Subject: [PATCH 524/703] i2c: bcm2835: Model Divider in CCF
-
-Commit bebff81fb8b9216eb4fba22cf910553621ae3477 upstream.
-
-Model the I2C bus clock divider as a part of the Core Clock Framework.
-Primarily this removes the clk_get_rate() call from each transfer.
-This call causes problems for slave drivers that themselves have
-internal clock components that are controlled by an I2C interface.
-When the slave's internal clock component is prepared, the prepare
-lock is obtained, and it makes calls to the I2C subsystem to
-command the hardware to activate the clock. In order to perform
-the I2C transfer, this driver sets the divider, which requires
-it to get the parent clock rate, which it does with clk_get_rate().
-Unfortunately, this function will try to take the clock prepare
-lock, which is already held by the slave's internal clock calls
-creating a deadlock.
-
-Modeling the divider in the CCF natively removes this dependency
-and the divider value is only set upon changing the bus clock
-frequency or changes in the parent clock that cascade down to this
-divisor. This obviates the need to set the divider with every
-transfer and avoids the deadlock described above. It also should
-provide better clock debugging and save a few cycles on each
-transfer due to not having to recalcuate the divider value.
-
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Reviewed-by: Eric Anholt <eric@anholt.net>
-Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
----
- drivers/i2c/busses/i2c-bcm2835.c | 145 ++++++++++++++++++++++++-------
- 1 file changed, 114 insertions(+), 31 deletions(-)
-
---- a/drivers/i2c/busses/i2c-bcm2835.c
-+++ b/drivers/i2c/busses/i2c-bcm2835.c
-@@ -12,6 +12,8 @@
- */
-
- #include <linux/clk.h>
-+#include <linux/clkdev.h>
-+#include <linux/clk-provider.h>
- #include <linux/completion.h>
- #include <linux/err.h>
- #include <linux/i2c.h>
-@@ -71,9 +73,7 @@ struct bcm2835_debug {
- struct bcm2835_i2c_dev {
- struct device *dev;
- void __iomem *regs;
-- struct clk *clk;
- int irq;
-- u32 bus_clk_rate;
- struct i2c_adapter adapter;
- struct completion completion;
- struct i2c_msg *curr_msg;
-@@ -164,12 +164,17 @@ static inline u32 bcm2835_i2c_readl(stru
- return readl(i2c_dev->regs + reg);
- }
-
--static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev)
-+#define to_clk_bcm2835_i2c(_hw) container_of(_hw, struct clk_bcm2835_i2c, hw)
-+struct clk_bcm2835_i2c {
-+ struct clk_hw hw;
-+ struct bcm2835_i2c_dev *i2c_dev;
-+};
-+
-+static int clk_bcm2835_i2c_calc_divider(unsigned long rate,
-+ unsigned long parent_rate)
- {
-- u32 divider, redl, fedl;
-+ u32 divider = DIV_ROUND_UP(parent_rate, rate);
-
-- divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk),
-- i2c_dev->bus_clk_rate);
- /*
- * Per the datasheet, the register is always interpreted as an even
- * number, by rounding down. In other words, the LSB is ignored. So,
-@@ -178,12 +183,23 @@ static int bcm2835_i2c_set_divider(struc
- if (divider & 1)
- divider++;
- if ((divider < BCM2835_I2C_CDIV_MIN) ||
-- (divider > BCM2835_I2C_CDIV_MAX)) {
-- dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n");
-+ (divider > BCM2835_I2C_CDIV_MAX))
- return -EINVAL;
-- }
-
-- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider);
-+ return divider;
-+}
-+
-+static int clk_bcm2835_i2c_set_rate(struct clk_hw *hw, unsigned long rate,
-+ unsigned long parent_rate)
-+{
-+ struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
-+ u32 redl, fedl;
-+ u32 divider = clk_bcm2835_i2c_calc_divider(rate, parent_rate);
-+
-+ if (divider == -EINVAL)
-+ return -EINVAL;
-+
-+ bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DIV, divider);
-
- /*
- * Number of core clocks to wait after falling edge before
-@@ -198,12 +214,62 @@ static int bcm2835_i2c_set_divider(struc
- */
- redl = max(divider / 4, 1u);
-
-- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DEL,
-+ bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DEL,
- (fedl << BCM2835_I2C_FEDL_SHIFT) |
- (redl << BCM2835_I2C_REDL_SHIFT));
- return 0;
- }
-
-+static long clk_bcm2835_i2c_round_rate(struct clk_hw *hw, unsigned long rate,
-+ unsigned long *parent_rate)
-+{
-+ u32 divider = clk_bcm2835_i2c_calc_divider(rate, *parent_rate);
-+
-+ return DIV_ROUND_UP(*parent_rate, divider);
-+}
-+
-+static unsigned long clk_bcm2835_i2c_recalc_rate(struct clk_hw *hw,
-+ unsigned long parent_rate)
-+{
-+ struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
-+ u32 divider = bcm2835_i2c_readl(div->i2c_dev, BCM2835_I2C_DIV);
-+
-+ return DIV_ROUND_UP(parent_rate, divider);
-+}
-+
-+static const struct clk_ops clk_bcm2835_i2c_ops = {
-+ .set_rate = clk_bcm2835_i2c_set_rate,
-+ .round_rate = clk_bcm2835_i2c_round_rate,
-+ .recalc_rate = clk_bcm2835_i2c_recalc_rate,
-+};
-+
-+static struct clk *bcm2835_i2c_register_div(struct device *dev,
-+ const char *mclk_name,
-+ struct bcm2835_i2c_dev *i2c_dev)
-+{
-+ struct clk_init_data init;
-+ struct clk_bcm2835_i2c *priv;
-+ char name[32];
-+
-+ snprintf(name, sizeof(name), "%s_div", dev_name(dev));
-+
-+ init.ops = &clk_bcm2835_i2c_ops;
-+ init.name = name;
-+ init.parent_names = (const char* []) { mclk_name };
-+ init.num_parents = 1;
-+ init.flags = 0;
-+
-+ priv = devm_kzalloc(dev, sizeof(struct clk_bcm2835_i2c), GFP_KERNEL);
-+ if (priv == NULL)
-+ return ERR_PTR(-ENOMEM);
-+
-+ priv->hw.init = &init;
-+ priv->i2c_dev = i2c_dev;
-+
-+ clk_hw_register_clkdev(&priv->hw, "div", dev_name(dev));
-+ return devm_clk_register(dev, &priv->hw);
-+}
-+
- static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev)
- {
- u32 val;
-@@ -363,7 +429,7 @@ static int bcm2835_i2c_xfer(struct i2c_a
- {
- struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
- unsigned long time_left;
-- int i, ret;
-+ int i;
-
- if (debug)
- i2c_dev->debug_num_msgs = num;
-@@ -379,10 +445,6 @@ static int bcm2835_i2c_xfer(struct i2c_a
- return -EOPNOTSUPP;
- }
-
-- ret = bcm2835_i2c_set_divider(i2c_dev);
-- if (ret)
-- return ret;
--
- i2c_dev->curr_msg = msgs;
- i2c_dev->num_msgs = num;
- reinit_completion(&i2c_dev->completion);
-@@ -443,6 +505,9 @@ static int bcm2835_i2c_probe(struct plat
- struct resource *mem, *irq;
- int ret;
- struct i2c_adapter *adap;
-+ const char *mclk_name;
-+ struct clk *bus_clk;
-+ u32 bus_clk_rate;
-
- i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
- if (!i2c_dev)
-@@ -456,21 +521,6 @@ static int bcm2835_i2c_probe(struct plat
- if (IS_ERR(i2c_dev->regs))
- return PTR_ERR(i2c_dev->regs);
-
-- i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
-- if (IS_ERR(i2c_dev->clk)) {
-- if (PTR_ERR(i2c_dev->clk) != -EPROBE_DEFER)
-- dev_err(&pdev->dev, "Could not get clock\n");
-- return PTR_ERR(i2c_dev->clk);
-- }
--
-- ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
-- &i2c_dev->bus_clk_rate);
-- if (ret < 0) {
-- dev_warn(&pdev->dev,
-- "Could not read clock-frequency property\n");
-- i2c_dev->bus_clk_rate = 100000;
-- }
--
- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!irq) {
- dev_err(&pdev->dev, "No IRQ resource\n");
-@@ -485,6 +535,35 @@ static int bcm2835_i2c_probe(struct plat
- return -ENODEV;
- }
-
-+ mclk_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
-+
-+ bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk_name, i2c_dev);
-+
-+ if (IS_ERR(bus_clk)) {
-+ dev_err(&pdev->dev, "Could not register clock\n");
-+ return PTR_ERR(bus_clk);
-+ }
-+
-+ ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
-+ &bus_clk_rate);
-+ if (ret < 0) {
-+ dev_warn(&pdev->dev,
-+ "Could not read clock-frequency property\n");
-+ bus_clk_rate = 100000;
-+ }
-+
-+ ret = clk_set_rate_exclusive(bus_clk, bus_clk_rate);
-+ if (ret < 0) {
-+ dev_err(&pdev->dev, "Could not set clock frequency\n");
-+ return ret;
-+ }
-+
-+ ret = clk_prepare_enable(bus_clk);
-+ if (ret) {
-+ dev_err(&pdev->dev, "Couldn't prepare clock");
-+ return ret;
-+ }
-+
- adap = &i2c_dev->adapter;
- i2c_set_adapdata(adap, i2c_dev);
- adap->owner = THIS_MODULE;
-@@ -507,6 +586,10 @@ static int bcm2835_i2c_probe(struct plat
- static int bcm2835_i2c_remove(struct platform_device *pdev)
- {
- struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
-+ struct clk *bus_clk = devm_clk_get(i2c_dev->dev, "div");
-+
-+ clk_rate_exclusive_put(bus_clk);
-+ clk_disable_unprepare(bus_clk);
-
- free_irq(i2c_dev->irq, i2c_dev);
- i2c_del_adapter(&i2c_dev->adapter);
--- /dev/null
+From 430a2bead0b7cf0100008189cad88213fcb6afb6 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sat, 4 May 2019 17:06:54 +0200
+Subject: [PATCH 525/725] ARM: dts: Add label to bcm2835 RNG
+
+---
+ arch/arm/boot/dts/bcm283x.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -148,7 +148,7 @@
+ <&dsi1 0>, <&dsi1 1>, <&dsi1 2>;
+ };
+
+- rng@7e104000 {
++ rng: rng@7e104000 {
+ compatible = "brcm,bcm2835-rng";
+ reg = <0x7e104000 0x10>;
+ interrupts = <2 29>;
+++ /dev/null
-From 75d0074312c7cb74c7a7c17f9cef7a071e209d79 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 17 Sep 2018 09:22:21 +0100
-Subject: [PATCH 525/703] staging/vc04_services: Use correct cache line size
-
-Use the compatible string in the DTB to select the correct cache line
-size for the SoC - 32 for BCM2835, and 64 for BCM2836 and BCM2837.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
-Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- .../interface/vchiq_arm/vchiq_2835_arm.c | 15 ++------
- .../interface/vchiq_arm/vchiq_arm.c | 35 +++++++++++++------
- .../interface/vchiq_arm/vchiq_arm.h | 5 +++
- 3 files changed, 33 insertions(+), 22 deletions(-)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
-@@ -117,7 +117,8 @@ free_pagelist(struct vchiq_pagelist_info
- int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state)
- {
- struct device *dev = &pdev->dev;
-- struct rpi_firmware *fw = platform_get_drvdata(pdev);
-+ struct vchiq_drvdata *drvdata = platform_get_drvdata(pdev);
-+ struct rpi_firmware *fw = drvdata->fw;
- VCHIQ_SLOT_ZERO_T *vchiq_slot_zero;
- struct resource *res;
- void *slot_mem;
-@@ -135,17 +136,7 @@ int vchiq_platform_init(struct platform_
- if (err < 0)
- return err;
-
-- /*
-- * The tempting L1_CACHE_BYTES macro doesn't work in the case of
-- * a kernel built with bcm2835_defconfig running on a BCM2836/7
-- * processor, hence the need for a runtime check. The dcache line size
-- * is encoded in one of the coprocessor registers, but there is no
-- * convenient way to access it short of embedded assembler, hence
-- * the use of read_cpuid_id(). The following test evaluates to true
-- * on a BCM2835 showing that it is ARMv6-ish, whereas
-- * cpu_architecture() will indicate that it is an ARMv7.
-- */
-- g_cache_line_size = ((read_cpuid_id() & 0x7f000) == 0x7b000) ? 32 : 64;
-+ g_cache_line_size = drvdata->cache_line_size;
- g_fragments_size = 2 * g_cache_line_size;
-
- /* Allocate space for the channels in coherent memory */
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -173,6 +173,14 @@ static struct platform_device *bcm2835_c
- static struct platform_device *bcm2835_codec;
- static struct platform_device *vcsm_cma;
-
-+static struct vchiq_drvdata bcm2835_drvdata = {
-+ .cache_line_size = 32,
-+};
-+
-+static struct vchiq_drvdata bcm2836_drvdata = {
-+ .cache_line_size = 64,
-+};
-+
- static const char *const ioctl_names[] = {
- "CONNECT",
- "SHUTDOWN",
-@@ -3607,12 +3615,25 @@ vchiq_register_child(struct platform_dev
- return new_dev;
- }
-
-+static const struct of_device_id vchiq_of_match[] = {
-+ { .compatible = "brcm,bcm2835-vchiq", .data = &bcm2835_drvdata },
-+ { .compatible = "brcm,bcm2836-vchiq", .data = &bcm2836_drvdata },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, vchiq_of_match);
-+
- static int vchiq_probe(struct platform_device *pdev)
- {
- struct device_node *fw_node;
-- struct rpi_firmware *fw;
-+ const struct of_device_id *of_id;
-+ struct vchiq_drvdata *drvdata;
- int err;
-
-+ of_id = of_match_node(vchiq_of_match, pdev->dev.of_node);
-+ drvdata = (struct vchiq_drvdata *)of_id->data;
-+ if (!drvdata)
-+ return -EINVAL;
-+
- fw_node = of_find_compatible_node(NULL, NULL,
- "raspberrypi,bcm2835-firmware");
- if (!fw_node) {
-@@ -3620,12 +3641,12 @@ static int vchiq_probe(struct platform_d
- return -ENOENT;
- }
-
-- fw = rpi_firmware_get(fw_node);
-+ drvdata->fw = rpi_firmware_get(fw_node);
- of_node_put(fw_node);
-- if (!fw)
-+ if (!drvdata->fw)
- return -EPROBE_DEFER;
-
-- platform_set_drvdata(pdev, fw);
-+ platform_set_drvdata(pdev, drvdata);
-
- err = vchiq_platform_init(pdev, &g_state);
- if (err != 0)
-@@ -3703,12 +3724,6 @@ static int vchiq_remove(struct platform_
- return 0;
- }
-
--static const struct of_device_id vchiq_of_match[] = {
-- { .compatible = "brcm,bcm2835-vchiq", },
-- {},
--};
--MODULE_DEVICE_TABLE(of, vchiq_of_match);
--
- static struct platform_driver vchiq_driver = {
- .driver = {
- .name = "bcm2835_vchiq",
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
-@@ -123,6 +123,11 @@ typedef struct vchiq_arm_state_struct {
-
- } VCHIQ_ARM_STATE_T;
-
-+struct vchiq_drvdata {
-+ const unsigned int cache_line_size;
-+ struct rpi_firmware *fw;
-+};
-+
- extern int vchiq_arm_log_level;
- extern int vchiq_susp_log_level;
-
--- /dev/null
+From d907bff594e59457b42df94c8da1b34f1964b2ae Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Thu, 12 Oct 2017 18:11:32 +0100
+Subject: [PATCH 526/725] dts: Use fb rather than leds for dpi overlay
+
+---
+ arch/arm/boot/dts/overlays/dpi18-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/dpi24-overlay.dts | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/dpi18-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dpi18-overlay.dts
+@@ -9,7 +9,7 @@
+ // reference on - leds will do
+
+ fragment@0 {
+- target = <&leds>;
++ target = <&fb>;
+ __overlay__ {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dpi18_pins>;
+--- a/arch/arm/boot/dts/overlays/dpi24-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dpi24-overlay.dts
+@@ -9,7 +9,7 @@
+ // reference on - leds will do
+
+ fragment@0 {
+- target = <&leds>;
++ target = <&fb>;
+ __overlay__ {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dpi24_pins>;
+++ /dev/null
-From 135b1563027fb8f30be1a9daae3db209166028af Mon Sep 17 00:00:00 2001
-From: Doug Berger <opendmb@gmail.com>
-Date: Mon, 13 May 2019 20:59:45 +0200
-Subject: [PATCH 526/703] tty: amba-pl011: allow shared interrupt
-
-The PL011 register space includes all necessary status bits to
-determine whether a device instance requires handling in response
-to an interrupt. Therefore, multiple instances of the device could
-be serviced by a single shared interrupt, which is the case on BCM7211.
-
-Signed-off-by: Doug Berger <opendmb@gmail.com>
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
----
- drivers/tty/serial/amba-pl011.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/tty/serial/amba-pl011.c
-+++ b/drivers/tty/serial/amba-pl011.c
-@@ -1735,7 +1735,8 @@ static int pl011_allocate_irq(struct uar
- {
- pl011_write(uap->im, uap, REG_IMSC);
-
-- return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
-+ return request_irq(uap->port.irq, pl011_int, IRQF_SHARED, "uart-pl011",
-+ uap);
- }
-
- /*
+++ /dev/null
-From 272132a1b67448ec6e72e431abe0ca00cc4e0554 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sun, 19 May 2019 12:20:00 +0200
-Subject: [PATCH 527/703] ARM: bcm283x: Reduce register ranges for UART, SPI
- and I2C
-
-The assigned register ranges for UART, SPI and I2C were too wasteful.
-In order to avoid overlapping with the new functions on BCM2838
-reduce the ranges.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- arch/arm/boot/dts/bcm283x.dtsi | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/arch/arm/boot/dts/bcm283x.dtsi
-+++ b/arch/arm/boot/dts/bcm283x.dtsi
-@@ -387,7 +387,7 @@
-
- uart0: serial@7e201000 {
- compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
-- reg = <0x7e201000 0x1000>;
-+ reg = <0x7e201000 0x200>;
- interrupts = <2 25>;
- clocks = <&clocks BCM2835_CLOCK_UART>,
- <&clocks BCM2835_CLOCK_VPU>;
-@@ -418,7 +418,7 @@
-
- spi: spi@7e204000 {
- compatible = "brcm,bcm2835-spi";
-- reg = <0x7e204000 0x1000>;
-+ reg = <0x7e204000 0x200>;
- interrupts = <2 22>;
- clocks = <&clocks BCM2835_CLOCK_VPU>;
- #address-cells = <1>;
-@@ -428,7 +428,7 @@
-
- i2c0: i2c@7e205000 {
- compatible = "brcm,bcm2835-i2c";
-- reg = <0x7e205000 0x1000>;
-+ reg = <0x7e205000 0x200>;
- interrupts = <2 21>;
- clocks = <&clocks BCM2835_CLOCK_VPU>;
- #address-cells = <1>;
--- /dev/null
+From fb2ff9ebd588db603dc9df848203e2f764a3ae90 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 May 2019 15:19:21 +0100
+Subject: [PATCH 527/725] BCM270X_DT: Minor tidy up
+
+Move arm_pmu out of soc on bcm2710, and labels aren't aliases.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm270x.dtsi | 14 +++++++-------
+ arch/arm/boot/dts/bcm2710.dtsi | 13 +++++--------
+ 2 files changed, 12 insertions(+), 15 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -10,11 +10,11 @@
+ soc: soc {
+
+ watchdog: watchdog@7e100000 {
+- /* Add alias */
++ /* Add label */
+ };
+
+ random: rng@7e104000 {
+- /* Add alias */
++ /* Add label */
+ };
+
+ gpio@7e200000 { /* gpio */
+@@ -40,18 +40,18 @@
+ };
+
+ spi0: spi@7e204000 {
+- /* Add alias */
++ /* Add label */
+ dmas = <&dma 6>, <&dma 7>;
+ dma-names = "tx", "rx";
+ };
+
+ pixelvalve0: pixelvalve@7e206000 {
+- /* Add alias */
++ /* Add label */
+ status = "disabled";
+ };
+
+ pixelvalve1: pixelvalve@7e207000 {
+- /* Add alias */
++ /* Add label */
+ status = "disabled";
+ };
+
+@@ -93,7 +93,7 @@
+ };
+
+ hvs: hvs@7e400000 {
+- /* Add alias */
++ /* Add label */
+ status = "disabled";
+ };
+
+@@ -119,7 +119,7 @@
+ };
+
+ pixelvalve2: pixelvalve@7e807000 {
+- /* Add alias */
++ /* Add label */
+ status = "disabled";
+ };
+
+--- a/arch/arm/boot/dts/bcm2710.dtsi
++++ b/arch/arm/boot/dts/bcm2710.dtsi
+@@ -5,18 +5,15 @@
+ / {
+ compatible = "brcm,bcm2837", "brcm,bcm2836";
+
+- soc {
+-
+- arm-pmu {
++ arm-pmu {
+ #ifdef RPI364
+- compatible = "arm,armv8-pmuv3", "arm,cortex-a7-pmu";
++ compatible = "arm,armv8-pmuv3", "arm,cortex-a7-pmu";
+ #else
+- compatible = "arm,cortex-a7-pmu";
++ compatible = "arm,cortex-a7-pmu";
+ #endif
+- interrupt-parent = <&local_intc>;
+- interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
+- };
++ };
+
++ soc {
+ /delete-node/ timer@7e003000;
+ };
+
+++ /dev/null
-From 35c9dd5eb19625b5eba5373ca780eef9e4029e87 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 12 Dec 2018 15:51:49 -0800
-Subject: [PATCH 528/703] ARM: bcm283x: Extend the WDT DT node out to cover the
- whole PM block. (v4)
-
-It was covering part of the PM block's range, up to the WDT regs. To
-support the rest of the PM block's functionality, we need the full
-register range plus the AXI Async Bridge regs for PM sequencing.
-
-This doesn't convert any of the consumers over to the new binding yet,
-since we will need to be careful in coordinating our usage of firmware
-services that might power domains on and off versus the bcm2835-pm
-driver's access of those same domains.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-(cherry picked from commit 29abc92c1d93e28a8f4d55e6343eec4faf44025a)
----
- arch/arm/boot/dts/bcm283x.dtsi | 13 +++++++++++--
- 1 file changed, 11 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/bcm283x.dtsi
-+++ b/arch/arm/boot/dts/bcm283x.dtsi
-@@ -121,8 +121,17 @@
- };
-
- watchdog@7e100000 {
-- compatible = "brcm,bcm2835-pm-wdt";
-- reg = <0x7e100000 0x28>;
-+ compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
-+ #power-domain-cells = <1>;
-+ #reset-cells = <1>;
-+ reg = <0x7e100000 0x114>,
-+ <0x7e00a000 0x24>;
-+ clocks = <&clocks BCM2835_CLOCK_V3D>,
-+ <&clocks BCM2835_CLOCK_PERI_IMAGE>,
-+ <&clocks BCM2835_CLOCK_H264>,
-+ <&clocks BCM2835_CLOCK_ISP>;
-+ clock-names = "v3d", "peri_image", "h264", "isp";
-+ system-power-controller;
- };
-
- clocks: cprman@7e101000 {
--- /dev/null
+From 35a736173fb6404fe35467a8c4802f7cd060388a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 20 Feb 2019 08:49:39 +0000
+Subject: [PATCH 528/725] arm: bcm2835: Fix FIQ early ioremap
+
+The ioremapping creates mappings within the vmalloc area. The
+equivalent early function, create_mapping, now checks that the
+requested explicit virtual address is between VMALLOC_START and
+VMALLOC_END. As there is no reason to have any correlation between
+the physical and virtual addresses, put the required mappings at
+VMALLOC_START and above.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/mach-bcm/board_bcm2835.c | 21 +++++++++++++++------
+ 1 file changed, 15 insertions(+), 6 deletions(-)
+
+--- a/arch/arm/mach-bcm/board_bcm2835.c
++++ b/arch/arm/mach-bcm/board_bcm2835.c
+@@ -14,17 +14,20 @@
+
+ #include <linux/init.h>
+ #include <linux/irqchip.h>
++#include <linux/mm.h>
+ #include <linux/of_address.h>
+ #include <linux/of_fdt.h>
+ #include <asm/system_info.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
++#include <asm/memory.h>
++#include <asm/pgtable.h>
+
+ #include "platsmp.h"
+
+-#define BCM2835_USB_VIRT_BASE 0xf0980000
+-#define BCM2835_USB_VIRT_MPHI 0xf0006000
++#define BCM2835_USB_VIRT_BASE (VMALLOC_START)
++#define BCM2835_USB_VIRT_MPHI (VMALLOC_START + 0x10000)
+
+ static void __init bcm2835_init(void)
+ {
+@@ -83,20 +86,26 @@ static int __init bcm2835_map_usb(unsign
+
+ static void __init bcm2835_map_io(void)
+ {
+- const __be32 *ranges;
++ const __be32 *ranges, *address_cells;
++ unsigned long root, addr_cells;
+ int soc, len;
+ unsigned long p2b_offset;
+
+ debug_ll_io_init();
+
++ root = of_get_flat_dt_root();
+ /* Find out how to map bus to physical address first from soc/ranges */
+- soc = of_get_flat_dt_subnode_by_name(of_get_flat_dt_root(), "soc");
++ soc = of_get_flat_dt_subnode_by_name(root, "soc");
+ if (soc < 0)
+ return;
++ address_cells = of_get_flat_dt_prop(root, "#address-cells", &len);
++ if (!address_cells || len < (sizeof(unsigned long)))
++ return;
++ addr_cells = be32_to_cpu(address_cells[0]);
+ ranges = of_get_flat_dt_prop(soc, "ranges", &len);
+- if (!ranges || len < (sizeof(unsigned long) * 3))
++ if (!ranges || len < (sizeof(unsigned long) * (2 + addr_cells)))
+ return;
+- p2b_offset = be32_to_cpu(ranges[0]) - be32_to_cpu(ranges[1]);
++ p2b_offset = be32_to_cpu(ranges[0]) - be32_to_cpu(ranges[addr_cells]);
+
+ /* Now search for bcm2708-usb node in device tree */
+ of_scan_flat_dt(bcm2835_map_usb, &p2b_offset);
+++ /dev/null
-From 381ffaf15617d63c898f3b70105dc42d17e4ed3b Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sat, 4 May 2019 17:06:54 +0200
-Subject: [PATCH 529/703] ARM: dts: Add label to bcm2835 RNG
-
----
- arch/arm/boot/dts/bcm283x.dtsi | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/bcm283x.dtsi
-+++ b/arch/arm/boot/dts/bcm283x.dtsi
-@@ -148,7 +148,7 @@
- <&dsi1 0>, <&dsi1 1>, <&dsi1 2>;
- };
-
-- rng@7e104000 {
-+ rng: rng@7e104000 {
- compatible = "brcm,bcm2835-rng";
- reg = <0x7e104000 0x10>;
- interrupts = <2 29>;
--- /dev/null
+From 4006c9ee386c4b3f33e816130bad8dc44030a316 Mon Sep 17 00:00:00 2001
+From: Tim Gover <tim.gover@raspberrypi.org>
+Date: Thu, 14 Mar 2019 10:16:02 +0000
+Subject: [PATCH 529/725] Fix copy_from_user if BCM2835_FAST_MEMCPY=n
+
+The change which introduced CONFIG_BCM2835_FAST_MEMCPY unconditionally
+changed the behaviour of arm_copy_from_user. The page pinning code
+is not safe on ARMv7 if LPAE & high memory is enabled and causes
+crashes which look like PTE corruption.
+
+Make __copy_from_user_memcpy conditional on CONFIG_2835_FAST_MEMCPY=y
+which is really an ARMv6 / Pi1 optimization and not necessary on newer
+ARM processors.
+---
+ arch/arm/lib/uaccess_with_memcpy.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/arch/arm/lib/uaccess_with_memcpy.c
++++ b/arch/arm/lib/uaccess_with_memcpy.c
+@@ -257,6 +257,7 @@ arm_copy_to_user(void __user *to, const
+ unsigned long __must_check
+ arm_copy_from_user(void *to, const void __user *from, unsigned long n)
+ {
++#ifdef CONFIG_BCM2835_FAST_MEMCPY
+ /*
+ * This test is stubbed out of the main function above to keep
+ * the overhead for small copies low by avoiding a large
+@@ -271,6 +272,11 @@ arm_copy_from_user(void *to, const void
+ } else {
+ n = __copy_from_user_memcpy(to, from, n);
+ }
++#else
++ unsigned long ua_flags = uaccess_save_and_enable();
++ n = __copy_from_user_std(to, from, n);
++ uaccess_restore(ua_flags);
++#endif
+ return n;
+ }
+
--- /dev/null
+From 0677ac68d2063ba12ea08e847d08b7b25089a283 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 19 Feb 2019 22:06:59 +0000
+Subject: [PATCH 530/725] PCI: brcmstb: Add Broadcom STB PCIe host controller
+ driver
+
+This commit adds the basic Broadcom STB PCIe controller. Missing is
+the ability to process MSI and also handle dma-ranges for inbound
+memory accesses. These two functionalities are added in subsequent
+commits.
+
+The PCIe block contains an MDIO interface. This is a local interface
+only accessible by the PCIe controller. It cannot be used or shared
+by any other HW. As such, the small amount of code for this
+controller is included in this driver as there is little upside to put
+it elsewhere.
+
+Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
+---
+ drivers/pci/controller/Kconfig | 9 +
+ drivers/pci/controller/Makefile | 2 +-
+ drivers/pci/controller/pcie-brcmstb.c | 1097 +++++++++++++++++++++++++
+ include/soc/brcmstb/memory_api.h | 25 +
+ 4 files changed, 1132 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/pci/controller/pcie-brcmstb.c
+ create mode 100644 include/soc/brcmstb/memory_api.h
+
+--- a/drivers/pci/controller/Kconfig
++++ b/drivers/pci/controller/Kconfig
+@@ -278,5 +278,14 @@ config VMD
+ To compile this driver as a module, choose M here: the
+ module will be called vmd.
+
++config PCIE_BRCMSTB
++ tristate "Broadcom Brcmstb PCIe platform host driver"
++ depends on ARCH_BRCMSTB || BMIPS_GENERIC
++ depends on OF
++ depends on SOC_BRCMSTB
++ default ARCH_BRCMSTB || BMIPS_GENERIC
++ help
++ Adds support for Broadcom Settop Box PCIe host controller.
++
+ source "drivers/pci/controller/dwc/Kconfig"
+ endmenu
+--- a/drivers/pci/controller/Makefile
++++ b/drivers/pci/controller/Makefile
+@@ -28,11 +28,11 @@ obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie
+ obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
+ obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
+ obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
++obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
+ obj-$(CONFIG_VMD) += vmd.o
+ # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
+ obj-y += dwc/
+
+-
+ # The following drivers are for devices that use the generic ACPI
+ # pci_root.c driver but don't support standard ECAM config access.
+ # They contain MCFG quirks to replace the generic ECAM accessors with
+--- /dev/null
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -0,0 +1,1097 @@
++// SPDX-License-Identifier: GPL-2.0
++/* Copyright (C) 2009 - 2017 Broadcom */
++
++#include <linux/clk.h>
++#include <linux/compiler.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/ioport.h>
++#include <linux/irqdomain.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/log2.h>
++#include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/of_irq.h>
++#include <linux/of_pci.h>
++#include <linux/of_platform.h>
++#include <linux/pci.h>
++#include <linux/printk.h>
++#include <linux/sizes.h>
++#include <linux/slab.h>
++#include <soc/brcmstb/memory_api.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include "../pci.h"
++
++/* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
++#define BRCM_PCIE_CAP_REGS 0x00ac
++
++/*
++ * Broadcom Settop Box PCIe Register Offsets. The names are from
++ * the chip's RDB and we use them here so that a script can correlate
++ * this code and the RDB to prevent discrepancies.
++ */
++#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1 0x0188
++#define PCIE_RC_CFG_PRIV1_ID_VAL3 0x043c
++#define PCIE_RC_DL_MDIO_ADDR 0x1100
++#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
++#define PCIE_RC_DL_MDIO_RD_DATA 0x1108
++#define PCIE_MISC_MISC_CTRL 0x4008
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO 0x400c
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI 0x4010
++#define PCIE_MISC_RC_BAR1_CONFIG_LO 0x402c
++#define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034
++#define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038
++#define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
++#define PCIE_MISC_PCIE_CTRL 0x4064
++#define PCIE_MISC_PCIE_STATUS 0x4068
++#define PCIE_MISC_REVISION 0x406c
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT 0x4070
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI 0x4080
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI 0x4084
++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204
++#define PCIE_INTR2_CPU_BASE 0x4300
++
++/*
++ * Broadcom Settop Box PCIe Register Field shift and mask info. The
++ * names are from the chip's RDB and we use them here so that a script
++ * can correlate this code and the RDB to prevent discrepancies.
++ */
++#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK 0xc
++#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_SHIFT 0x2
++#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff
++#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_SHIFT 0x0
++#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK 0x1000
++#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_SHIFT 0xc
++#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000
++#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_SHIFT 0xd
++#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000
++#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_SHIFT 0x14
++#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK 0xf8000000
++#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_SHIFT 0x1b
++#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_MASK 0x7c00000
++#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_SHIFT 0x16
++#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_MASK 0x1f
++#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_SHIFT 0x0
++#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK 0x1f
++#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_SHIFT 0x0
++#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK 0x1f
++#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_SHIFT 0x0
++#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f
++#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_SHIFT 0x0
++#define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK 0x4
++#define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_SHIFT 0x2
++#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK 0x1
++#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_SHIFT 0x0
++#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK 0x80
++#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_SHIFT 0x7
++#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_MASK 0x20
++#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_SHIFT 0x5
++#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK 0x10
++#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_SHIFT 0x4
++#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK 0x40
++#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_SHIFT 0x6
++#define PCIE_MISC_REVISION_MAJMIN_MASK 0xffff
++#define PCIE_MISC_REVISION_MAJMIN_SHIFT 0
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK 0xfff00000
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_SHIFT 0x14
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK 0xfff0
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_SHIFT 0x4
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS 0xc
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_MASK 0xff
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_SHIFT 0x0
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK 0xff
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_SHIFT 0x0
++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2
++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_SHIFT 0x1
++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_SHIFT 0x1b
++#define PCIE_RGR1_SW_INIT_1_PERST_MASK 0x1
++#define PCIE_RGR1_SW_INIT_1_PERST_SHIFT 0x0
++
++#define BRCM_NUM_PCIE_OUT_WINS 0x4
++#define BRCM_MAX_SCB 0x4
++
++#define BRCM_MSI_TARGET_ADDR_LT_4GB 0x0fffffffcULL
++#define BRCM_MSI_TARGET_ADDR_GT_4GB 0xffffffffcULL
++
++#define BURST_SIZE_128 0
++#define BURST_SIZE_256 1
++#define BURST_SIZE_512 2
++
++/* Offsets from PCIE_INTR2_CPU_BASE */
++#define STATUS 0x0
++#define SET 0x4
++#define CLR 0x8
++#define MASK_STATUS 0xc
++#define MASK_SET 0x10
++#define MASK_CLR 0x14
++
++#define PCIE_BUSNUM_SHIFT 20
++#define PCIE_SLOT_SHIFT 15
++#define PCIE_FUNC_SHIFT 12
++
++#if defined(__BIG_ENDIAN)
++#define DATA_ENDIAN 2 /* PCIe->DDR inbound traffic */
++#define MMIO_ENDIAN 2 /* CPU->PCIe outbound traffic */
++#else
++#define DATA_ENDIAN 0
++#define MMIO_ENDIAN 0
++#endif
++
++#define MDIO_PORT0 0x0
++#define MDIO_DATA_MASK 0x7fffffff
++#define MDIO_DATA_SHIFT 0x0
++#define MDIO_PORT_MASK 0xf0000
++#define MDIO_PORT_SHIFT 0x16
++#define MDIO_REGAD_MASK 0xffff
++#define MDIO_REGAD_SHIFT 0x0
++#define MDIO_CMD_MASK 0xfff00000
++#define MDIO_CMD_SHIFT 0x14
++#define MDIO_CMD_READ 0x1
++#define MDIO_CMD_WRITE 0x0
++#define MDIO_DATA_DONE_MASK 0x80000000
++#define MDIO_RD_DONE(x) (((x) & MDIO_DATA_DONE_MASK) ? 1 : 0)
++#define MDIO_WT_DONE(x) (((x) & MDIO_DATA_DONE_MASK) ? 0 : 1)
++#define SSC_REGS_ADDR 0x1100
++#define SET_ADDR_OFFSET 0x1f
++#define SSC_CNTL_OFFSET 0x2
++#define SSC_CNTL_OVRD_EN_MASK 0x8000
++#define SSC_CNTL_OVRD_EN_SHIFT 0xf
++#define SSC_CNTL_OVRD_VAL_MASK 0x4000
++#define SSC_CNTL_OVRD_VAL_SHIFT 0xe
++#define SSC_STATUS_OFFSET 0x1
++#define SSC_STATUS_SSC_MASK 0x400
++#define SSC_STATUS_SSC_SHIFT 0xa
++#define SSC_STATUS_PLL_LOCK_MASK 0x800
++#define SSC_STATUS_PLL_LOCK_SHIFT 0xb
++
++#define IDX_ADDR(pcie) \
++ ((pcie)->reg_offsets[EXT_CFG_INDEX])
++#define DATA_ADDR(pcie) \
++ ((pcie)->reg_offsets[EXT_CFG_DATA])
++#define PCIE_RGR1_SW_INIT_1(pcie) \
++ ((pcie)->reg_offsets[RGR1_SW_INIT_1])
++
++enum {
++ RGR1_SW_INIT_1,
++ EXT_CFG_INDEX,
++ EXT_CFG_DATA,
++};
++
++enum {
++ RGR1_SW_INIT_1_INIT_MASK,
++ RGR1_SW_INIT_1_INIT_SHIFT,
++ RGR1_SW_INIT_1_PERST_MASK,
++ RGR1_SW_INIT_1_PERST_SHIFT,
++};
++
++enum pcie_type {
++ BCM7425,
++ BCM7435,
++ GENERIC,
++ BCM7278,
++};
++
++struct brcm_window {
++ dma_addr_t pcie_addr;
++ phys_addr_t cpu_addr;
++ dma_addr_t size;
++};
++
++/* Internal PCIe Host Controller Information.*/
++struct brcm_pcie {
++ struct device *dev;
++ void __iomem *base;
++ struct list_head resources;
++ int irq;
++ struct clk *clk;
++ struct pci_bus *root_bus;
++ struct device_node *dn;
++ int id;
++ bool suspended;
++ int num_out_wins;
++ bool ssc;
++ int gen;
++ struct brcm_window out_wins[BRCM_NUM_PCIE_OUT_WINS];
++ unsigned int rev;
++ const int *reg_offsets;
++ const int *reg_field_info;
++ enum pcie_type type;
++};
++
++struct pcie_cfg_data {
++ const int *reg_field_info;
++ const int *offsets;
++ const enum pcie_type type;
++};
++
++static const int pcie_reg_field_info[] = {
++ [RGR1_SW_INIT_1_INIT_MASK] = 0x2,
++ [RGR1_SW_INIT_1_INIT_SHIFT] = 0x1,
++};
++
++static const int pcie_reg_field_info_bcm7278[] = {
++ [RGR1_SW_INIT_1_INIT_MASK] = 0x1,
++ [RGR1_SW_INIT_1_INIT_SHIFT] = 0x0,
++};
++
++static const int pcie_offset_bcm7425[] = {
++ [RGR1_SW_INIT_1] = 0x8010,
++ [EXT_CFG_INDEX] = 0x8300,
++ [EXT_CFG_DATA] = 0x8304,
++};
++
++static const struct pcie_cfg_data bcm7425_cfg = {
++ .reg_field_info = pcie_reg_field_info,
++ .offsets = pcie_offset_bcm7425,
++ .type = BCM7425,
++};
++
++static const int pcie_offsets[] = {
++ [RGR1_SW_INIT_1] = 0x9210,
++ [EXT_CFG_INDEX] = 0x9000,
++ [EXT_CFG_DATA] = 0x9004,
++};
++
++static const struct pcie_cfg_data bcm7435_cfg = {
++ .reg_field_info = pcie_reg_field_info,
++ .offsets = pcie_offsets,
++ .type = BCM7435,
++};
++
++static const struct pcie_cfg_data generic_cfg = {
++ .reg_field_info = pcie_reg_field_info,
++ .offsets = pcie_offsets,
++ .type = GENERIC,
++};
++
++static const int pcie_offset_bcm7278[] = {
++ [RGR1_SW_INIT_1] = 0xc010,
++ [EXT_CFG_INDEX] = 0x9000,
++ [EXT_CFG_DATA] = 0x9004,
++};
++
++static const struct pcie_cfg_data bcm7278_cfg = {
++ .reg_field_info = pcie_reg_field_info_bcm7278,
++ .offsets = pcie_offset_bcm7278,
++ .type = BCM7278,
++};
++
++static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned int devfn,
++ int where);
++
++static struct pci_ops brcm_pcie_ops = {
++ .map_bus = brcm_pcie_map_conf,
++ .read = pci_generic_config_read,
++ .write = pci_generic_config_write,
++};
++
++#if defined(CONFIG_MIPS)
++/* Broadcom MIPs HW implicitly does the swapping if necessary */
++#define bcm_readl(a) __raw_readl(a)
++#define bcm_writel(d, a) __raw_writel(d, a)
++#define bcm_readw(a) __raw_readw(a)
++#define bcm_writew(d, a) __raw_writew(d, a)
++#else
++#define bcm_readl(a) readl(a)
++#define bcm_writel(d, a) writel(d, a)
++#define bcm_readw(a) readw(a)
++#define bcm_writew(d, a) writew(d, a)
++#endif
++
++/* These macros extract/insert fields to host controller's register set. */
++#define RD_FLD(base, reg, field) \
++ rd_fld(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT)
++#define WR_FLD(base, reg, field, val) \
++ wr_fld(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT, val)
++#define WR_FLD_RB(base, reg, field, val) \
++ wr_fld_rb(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT, val)
++#define WR_FLD_WITH_OFFSET(base, off, reg, field, val) \
++ wr_fld(base + reg + off, reg##_##field##_MASK, \
++ reg##_##field##_SHIFT, val)
++#define EXTRACT_FIELD(val, reg, field) \
++ ((val & reg##_##field##_MASK) >> reg##_##field##_SHIFT)
++#define INSERT_FIELD(val, reg, field, field_val) \
++ ((val & ~reg##_##field##_MASK) | \
++ (reg##_##field##_MASK & (field_val << reg##_##field##_SHIFT)))
++
++static phys_addr_t scb_size[BRCM_MAX_SCB];
++static int num_memc;
++static int num_pcie;
++static DEFINE_MUTEX(brcm_pcie_lock);
++
++static u32 rd_fld(void __iomem *p, u32 mask, int shift)
++{
++ return (bcm_readl(p) & mask) >> shift;
++}
++
++static void wr_fld(void __iomem *p, u32 mask, int shift, u32 val)
++{
++ u32 reg = bcm_readl(p);
++
++ reg = (reg & ~mask) | ((val << shift) & mask);
++ bcm_writel(reg, p);
++}
++
++static void wr_fld_rb(void __iomem *p, u32 mask, int shift, u32 val)
++{
++ wr_fld(p, mask, shift, val);
++ (void)bcm_readl(p);
++}
++
++static const char *link_speed_to_str(int s)
++{
++ switch (s) {
++ case 1:
++ return "2.5";
++ case 2:
++ return "5.0";
++ case 3:
++ return "8.0";
++ default:
++ break;
++ }
++ return "???";
++}
++
++/*
++ * The roundup_pow_of_two() from log2.h invokes
++ * __roundup_pow_of_two(unsigned long), but we really need a
++ * such a function to take a native u64 since unsigned long
++ * is 32 bits on some configurations. So we provide this helper
++ * function below.
++ */
++static u64 roundup_pow_of_two_64(u64 n)
++{
++ return 1ULL << fls64(n - 1);
++}
++
++/*
++ * This is to convert the size of the inbound "BAR" region to the
++ * non-linear values of PCIE_X_MISC_RC_BAR[123]_CONFIG_LO.SIZE
++ */
++int encode_ibar_size(u64 size)
++{
++ int log2_in = ilog2(size);
++
++ if (log2_in >= 12 && log2_in <= 15)
++ /* Covers 4KB to 32KB (inclusive) */
++ return (log2_in - 12) + 0x1c;
++ else if (log2_in >= 16 && log2_in <= 37)
++ /* Covers 64KB to 32GB, (inclusive) */
++ return log2_in - 15;
++ /* Something is awry so disable */
++ return 0;
++}
++
++static u32 mdio_form_pkt(int port, int regad, int cmd)
++{
++ u32 pkt = 0;
++
++ pkt |= (port << MDIO_PORT_SHIFT) & MDIO_PORT_MASK;
++ pkt |= (regad << MDIO_REGAD_SHIFT) & MDIO_REGAD_MASK;
++ pkt |= (cmd << MDIO_CMD_SHIFT) & MDIO_CMD_MASK;
++
++ return pkt;
++}
++
++/* negative return value indicates error */
++static int mdio_read(void __iomem *base, u8 port, u8 regad)
++{
++ int tries;
++ u32 data;
++
++ bcm_writel(mdio_form_pkt(port, regad, MDIO_CMD_READ),
++ base + PCIE_RC_DL_MDIO_ADDR);
++ bcm_readl(base + PCIE_RC_DL_MDIO_ADDR);
++
++ data = bcm_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
++ for (tries = 0; !MDIO_RD_DONE(data) && tries < 10; tries++) {
++ udelay(10);
++ data = bcm_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
++ }
++
++ return MDIO_RD_DONE(data)
++ ? (data & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT
++ : -EIO;
++}
++
++/* negative return value indicates error */
++static int mdio_write(void __iomem *base, u8 port, u8 regad, u16 wrdata)
++{
++ int tries;
++ u32 data;
++
++ bcm_writel(mdio_form_pkt(port, regad, MDIO_CMD_WRITE),
++ base + PCIE_RC_DL_MDIO_ADDR);
++ bcm_readl(base + PCIE_RC_DL_MDIO_ADDR);
++ bcm_writel(MDIO_DATA_DONE_MASK | wrdata,
++ base + PCIE_RC_DL_MDIO_WR_DATA);
++
++ data = bcm_readl(base + PCIE_RC_DL_MDIO_WR_DATA);
++ for (tries = 0; !MDIO_WT_DONE(data) && tries < 10; tries++) {
++ udelay(10);
++ data = bcm_readl(base + PCIE_RC_DL_MDIO_WR_DATA);
++ }
++
++ return MDIO_WT_DONE(data) ? 0 : -EIO;
++}
++
++/*
++ * Configures device for Spread Spectrum Clocking (SSC) mode; a negative
++ * return value indicates error.
++ */
++static int set_ssc(void __iomem *base)
++{
++ int tmp;
++ u16 wrdata;
++ int pll, ssc;
++
++ tmp = mdio_write(base, MDIO_PORT0, SET_ADDR_OFFSET, SSC_REGS_ADDR);
++ if (tmp < 0)
++ return tmp;
++
++ tmp = mdio_read(base, MDIO_PORT0, SSC_CNTL_OFFSET);
++ if (tmp < 0)
++ return tmp;
++
++ wrdata = INSERT_FIELD(tmp, SSC_CNTL_OVRD, EN, 1);
++ wrdata = INSERT_FIELD(wrdata, SSC_CNTL_OVRD, VAL, 1);
++ tmp = mdio_write(base, MDIO_PORT0, SSC_CNTL_OFFSET, wrdata);
++ if (tmp < 0)
++ return tmp;
++
++ usleep_range(1000, 2000);
++ tmp = mdio_read(base, MDIO_PORT0, SSC_STATUS_OFFSET);
++ if (tmp < 0)
++ return tmp;
++
++ ssc = EXTRACT_FIELD(tmp, SSC_STATUS, SSC);
++ pll = EXTRACT_FIELD(tmp, SSC_STATUS, PLL_LOCK);
++
++ return (ssc && pll) ? 0 : -EIO;
++}
++
++/* Limits operation to a specific generation (1, 2, or 3) */
++static void set_gen(void __iomem *base, int gen)
++{
++ u32 lnkcap = bcm_readl(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
++ u16 lnkctl2 = bcm_readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
++
++ lnkcap = (lnkcap & ~PCI_EXP_LNKCAP_SLS) | gen;
++ bcm_writel(lnkcap, base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
++
++ lnkctl2 = (lnkctl2 & ~0xf) | gen;
++ bcm_writew(lnkctl2, base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
++}
++
++static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie,
++ unsigned int win, phys_addr_t cpu_addr,
++ dma_addr_t pcie_addr, dma_addr_t size)
++{
++ void __iomem *base = pcie->base;
++ phys_addr_t cpu_addr_mb, limit_addr_mb;
++ u32 tmp;
++
++ /* Set the base of the pcie_addr window */
++ bcm_writel(lower_32_bits(pcie_addr) + MMIO_ENDIAN,
++ base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + (win * 8));
++ bcm_writel(upper_32_bits(pcie_addr),
++ base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + (win * 8));
++
++ cpu_addr_mb = cpu_addr >> 20;
++ limit_addr_mb = (cpu_addr + size - 1) >> 20;
++
++ /* Write the addr base low register */
++ WR_FLD_WITH_OFFSET(base, (win * 4),
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT,
++ BASE, cpu_addr_mb);
++ /* Write the addr limit low register */
++ WR_FLD_WITH_OFFSET(base, (win * 4),
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT,
++ LIMIT, limit_addr_mb);
++
++ if (pcie->type != BCM7435 && pcie->type != BCM7425) {
++ /* Write the cpu addr high register */
++ tmp = (u32)(cpu_addr_mb >>
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS);
++ WR_FLD_WITH_OFFSET(base, (win * 8),
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI,
++ BASE, tmp);
++ /* Write the cpu limit high register */
++ tmp = (u32)(limit_addr_mb >>
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS);
++ WR_FLD_WITH_OFFSET(base, (win * 8),
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI,
++ LIMIT, tmp);
++ }
++}
++
++/* Configuration space read/write support */
++static int cfg_index(int busnr, int devfn, int reg)
++{
++ return ((PCI_SLOT(devfn) & 0x1f) << PCIE_SLOT_SHIFT)
++ | ((PCI_FUNC(devfn) & 0x07) << PCIE_FUNC_SHIFT)
++ | (busnr << PCIE_BUSNUM_SHIFT)
++ | (reg & ~3);
++}
++
++/* The controller is capable of serving in both RC and EP roles */
++static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie)
++{
++ void __iomem *base = pcie->base;
++ u32 val = bcm_readl(base + PCIE_MISC_PCIE_STATUS);
++
++ return !!EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, PCIE_PORT);
++}
++
++static bool brcm_pcie_link_up(struct brcm_pcie *pcie)
++{
++ void __iomem *base = pcie->base;
++ u32 val = bcm_readl(base + PCIE_MISC_PCIE_STATUS);
++ u32 dla = EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, PCIE_DL_ACTIVE);
++ u32 plu = EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, PCIE_PHYLINKUP);
++
++ return (dla && plu) ? true : false;
++}
++
++static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned int devfn,
++ int where)
++{
++ struct brcm_pcie *pcie = bus->sysdata;
++ void __iomem *base = pcie->base;
++ int idx;
++
++ /* Accesses to the RC go right to the RC registers if slot==0 */
++ if (pci_is_root_bus(bus))
++ return PCI_SLOT(devfn) ? NULL : base + where;
++
++ /* For devices, write to the config space index register */
++ idx = cfg_index(bus->number, devfn, where);
++ bcm_writel(idx, pcie->base + IDX_ADDR(pcie));
++ return base + DATA_ADDR(pcie) + (where & 0x3);
++}
++
++static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie,
++ unsigned int val)
++{
++ unsigned int shift = pcie->reg_field_info[RGR1_SW_INIT_1_INIT_SHIFT];
++ u32 mask = pcie->reg_field_info[RGR1_SW_INIT_1_INIT_MASK];
++
++ wr_fld_rb(pcie->base + PCIE_RGR1_SW_INIT_1(pcie), mask, shift, val);
++}
++
++static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie,
++ unsigned int val)
++{
++ if (pcie->type != BCM7278)
++ wr_fld_rb(pcie->base + PCIE_RGR1_SW_INIT_1(pcie),
++ PCIE_RGR1_SW_INIT_1_PERST_MASK,
++ PCIE_RGR1_SW_INIT_1_PERST_SHIFT, val);
++ else
++ /* Assert = 0, de-assert = 1 on 7278 */
++ WR_FLD_RB(pcie->base, PCIE_MISC_PCIE_CTRL, PCIE_PERSTB, !val);
++}
++
++static int brcm_pcie_add_controller(struct brcm_pcie *pcie)
++{
++ int i, ret = 0;
++
++ mutex_lock(&brcm_pcie_lock);
++ if (num_pcie > 0) {
++ num_pcie++;
++ goto done;
++ }
++
++ /* Determine num_memc and their sizes */
++ for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
++ u64 size = brcmstb_memory_memc_size(i);
++
++ if (size == (u64)-1) {
++ dev_err(pcie->dev, "cannot get memc%d size\n", i);
++ ret = -EINVAL;
++ goto done;
++ } else if (size) {
++ scb_size[i] = roundup_pow_of_two_64(size);
++ num_memc++;
++ } else {
++ break;
++ }
++ }
++ if (!ret && num_memc == 0) {
++ ret = -EINVAL;
++ goto done;
++ }
++
++ num_pcie++;
++done:
++ mutex_unlock(&brcm_pcie_lock);
++ return ret;
++}
++
++static void brcm_pcie_remove_controller(struct brcm_pcie *pcie)
++{
++ mutex_lock(&brcm_pcie_lock);
++ if (--num_pcie == 0)
++ num_memc = 0;
++ mutex_unlock(&brcm_pcie_lock);
++}
++
++static int brcm_pcie_parse_request_of_pci_ranges(struct brcm_pcie *pcie)
++{
++ struct resource_entry *win;
++ int ret;
++
++ ret = devm_of_pci_get_host_bridge_resources(pcie->dev, 0, 0xff,
++ &pcie->resources, NULL);
++ if (ret) {
++ dev_err(pcie->dev, "failed to get host resources\n");
++ return ret;
++ }
++
++ resource_list_for_each_entry(win, &pcie->resources) {
++ struct resource *parent, *res = win->res;
++ dma_addr_t offset = (dma_addr_t)win->offset;
++
++ if (resource_type(res) == IORESOURCE_IO) {
++ parent = &ioport_resource;
++ } else if (resource_type(res) == IORESOURCE_MEM) {
++ if (pcie->num_out_wins >= BRCM_NUM_PCIE_OUT_WINS) {
++ dev_err(pcie->dev, "too many outbound wins\n");
++ return -EINVAL;
++ }
++ pcie->out_wins[pcie->num_out_wins].cpu_addr
++ = (phys_addr_t)res->start;
++ pcie->out_wins[pcie->num_out_wins].pcie_addr
++ = (dma_addr_t)(res->start
++ - (phys_addr_t)offset);
++ pcie->out_wins[pcie->num_out_wins].size
++ = (dma_addr_t)(res->end - res->start + 1);
++ pcie->num_out_wins++;
++ parent = &iomem_resource;
++ } else {
++ continue;
++ }
++
++ ret = devm_request_resource(pcie->dev, parent, res);
++ if (ret) {
++ dev_err(pcie->dev, "failed to get res %pR\n", res);
++ return ret;
++ }
++ }
++ return 0;
++}
++
++static int brcm_pcie_setup(struct brcm_pcie *pcie)
++{
++ void __iomem *base = pcie->base;
++ unsigned int scb_size_val;
++ u64 rc_bar2_offset, rc_bar2_size, total_mem_size = 0;
++ u32 tmp, burst;
++ int i, j, ret, limit;
++ u16 nlw, cls, lnksta;
++ bool ssc_good = false;
++ struct device *dev = pcie->dev;
++
++ /* Reset the bridge */
++ brcm_pcie_bridge_sw_init_set(pcie, 1);
++
++ /*
++ * Ensure that the fundamental reset is asserted, except for 7278,
++ * which fails if we do this.
++ */
++ if (pcie->type != BCM7278)
++ brcm_pcie_perst_set(pcie, 1);
++
++ usleep_range(100, 200);
++
++ /* Take the bridge out of reset */
++ brcm_pcie_bridge_sw_init_set(pcie, 0);
++
++ WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 0);
++ /* Wait for SerDes to be stable */
++ usleep_range(100, 200);
++
++ /* Grab the PCIe hw revision number */
++ tmp = bcm_readl(base + PCIE_MISC_REVISION);
++ pcie->rev = EXTRACT_FIELD(tmp, PCIE_MISC_REVISION, MAJMIN);
++
++ /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
++ tmp = INSERT_FIELD(0, PCIE_MISC_MISC_CTRL, SCB_ACCESS_EN, 1);
++ tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, CFG_READ_UR_MODE, 1);
++ burst = (pcie->type == GENERIC || pcie->type == BCM7278)
++ ? BURST_SIZE_512 : BURST_SIZE_256;
++ tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE, burst);
++ bcm_writel(tmp, base + PCIE_MISC_MISC_CTRL);
++
++ /*
++ * Set up inbound memory view for the EP (called RC_BAR2,
++ * not to be confused with the BARs that are advertised by
++ * the EP).
++ */
++ for (i = 0; i < num_memc; i++)
++ total_mem_size += scb_size[i];
++
++ /*
++ * The PCIe host controller by design must set the inbound
++ * viewport to be a contiguous arrangement of all of the
++ * system's memory. In addition, its size mut be a power of
++ * two. To further complicate matters, the viewport must
++ * start on a pcie-address that is aligned on a multiple of its
++ * size. If a portion of the viewport does not represent
++ * system memory -- e.g. 3GB of memory requires a 4GB viewport
++ * -- we can map the outbound memory in or after 3GB and even
++ * though the viewport will overlap the outbound memory the
++ * controller will know to send outbound memory downstream and
++ * everything else upstream.
++ */
++ rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
++
++ /*
++ * Set simple configuration based on memory sizes
++ * only. We always start the viewport at address 0.
++ */
++ rc_bar2_offset = 0;
++
++ tmp = lower_32_bits(rc_bar2_offset);
++ tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
++ encode_ibar_size(rc_bar2_size));
++ bcm_writel(tmp, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
++ bcm_writel(upper_32_bits(rc_bar2_offset),
++ base + PCIE_MISC_RC_BAR2_CONFIG_HI);
++
++ scb_size_val = scb_size[0]
++ ? ilog2(scb_size[0]) - 15 : 0xf; /* 0xf is 1GB */
++ WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB0_SIZE, scb_size_val);
++
++ if (num_memc > 1) {
++ scb_size_val = scb_size[1]
++ ? ilog2(scb_size[1]) - 15 : 0xf; /* 0xf is 1GB */
++ WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB1_SIZE, scb_size_val);
++ }
++
++ if (num_memc > 2) {
++ scb_size_val = scb_size[2]
++ ? ilog2(scb_size[2]) - 15 : 0xf; /* 0xf is 1GB */
++ WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB2_SIZE, scb_size_val);
++ }
++
++ /* disable the PCIe->GISB memory window (RC_BAR1) */
++ WR_FLD(base, PCIE_MISC_RC_BAR1_CONFIG_LO, SIZE, 0);
++
++ /* disable the PCIe->SCB memory window (RC_BAR3) */
++ WR_FLD(base, PCIE_MISC_RC_BAR3_CONFIG_LO, SIZE, 0);
++
++ if (!pcie->suspended) {
++ /* clear any interrupts we find on boot */
++ bcm_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + CLR);
++ (void)bcm_readl(base + PCIE_INTR2_CPU_BASE + CLR);
++ }
++
++ /* Mask all interrupts since we are not handling any yet */
++ bcm_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + MASK_SET);
++ (void)bcm_readl(base + PCIE_INTR2_CPU_BASE + MASK_SET);
++
++ if (pcie->gen)
++ set_gen(base, pcie->gen);
++
++ /* Unassert the fundamental reset */
++ brcm_pcie_perst_set(pcie, 0);
++
++ /*
++ * Give the RC/EP time to wake up, before trying to configure RC.
++ * Intermittently check status for link-up, up to a total of 100ms
++ * when we don't know if the device is there, and up to 1000ms if
++ * we do know the device is there.
++ */
++ limit = pcie->suspended ? 1000 : 100;
++ for (i = 1, j = 0; j < limit && !brcm_pcie_link_up(pcie);
++ j += i, i = i * 2)
++ msleep(i + j > limit ? limit - j : i);
++
++ if (!brcm_pcie_link_up(pcie)) {
++ dev_info(dev, "link down\n");
++ return -ENODEV;
++ }
++
++ if (!brcm_pcie_rc_mode(pcie)) {
++ dev_err(dev, "PCIe misconfigured; is in EP mode\n");
++ return -EINVAL;
++ }
++
++ for (i = 0; i < pcie->num_out_wins; i++)
++ brcm_pcie_set_outbound_win(pcie, i, pcie->out_wins[i].cpu_addr,
++ pcie->out_wins[i].pcie_addr,
++ pcie->out_wins[i].size);
++
++ /*
++ * For config space accesses on the RC, show the right class for
++ * a PCIe-PCIe bridge (the default setting is to be EP mode).
++ */
++ WR_FLD_RB(base, PCIE_RC_CFG_PRIV1_ID_VAL3, CLASS_CODE, 0x060400);
++
++ if (pcie->ssc) {
++ ret = set_ssc(base);
++ if (ret == 0)
++ ssc_good = true;
++ else
++ dev_err(dev, "failed attempt to enter ssc mode\n");
++ }
++
++ lnksta = bcm_readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKSTA);
++ cls = lnksta & PCI_EXP_LNKSTA_CLS;
++ nlw = (lnksta & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
++ dev_info(dev, "link up, %s Gbps x%u %s\n", link_speed_to_str(cls),
++ nlw, ssc_good ? "(SSC)" : "(!SSC)");
++
++ /* PCIe->SCB endian mode for BAR */
++ /* field ENDIAN_MODE_BAR2 = DATA_ENDIAN */
++ WR_FLD_RB(base, PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1,
++ ENDIAN_MODE_BAR2, DATA_ENDIAN);
++
++ /*
++ * Refclk from RC should be gated with CLKREQ# input when ASPM L0s,L1
++ * is enabled => setting the CLKREQ_DEBUG_ENABLE field to 1.
++ */
++ WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, CLKREQ_DEBUG_ENABLE, 1);
++
++ return 0;
++}
++
++/* L23 is a low-power PCIe link state */
++static void enter_l23(struct brcm_pcie *pcie)
++{
++ void __iomem *base = pcie->base;
++ int tries, l23;
++
++ /* assert request for L23 */
++ WR_FLD_RB(base, PCIE_MISC_PCIE_CTRL, PCIE_L23_REQUEST, 1);
++ /* poll L23 status */
++ for (tries = 0, l23 = 0; tries < 1000 && !l23; tries++)
++ l23 = RD_FLD(base, PCIE_MISC_PCIE_STATUS, PCIE_LINK_IN_L23);
++ if (!l23)
++ dev_err(pcie->dev, "failed to enter L23\n");
++}
++
++static void turn_off(struct brcm_pcie *pcie)
++{
++ void __iomem *base = pcie->base;
++
++ if (brcm_pcie_link_up(pcie))
++ enter_l23(pcie);
++ /* Assert fundamental reset */
++ brcm_pcie_perst_set(pcie, 1);
++ /* Deassert request for L23 in case it was asserted */
++ WR_FLD_RB(base, PCIE_MISC_PCIE_CTRL, PCIE_L23_REQUEST, 0);
++ /* Turn off SerDes */
++ WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 1);
++ /* Shutdown PCIe bridge */
++ brcm_pcie_bridge_sw_init_set(pcie, 1);
++}
++
++static int brcm_pcie_suspend(struct device *dev)
++{
++ struct brcm_pcie *pcie = dev_get_drvdata(dev);
++
++ turn_off(pcie);
++ clk_disable_unprepare(pcie->clk);
++ pcie->suspended = true;
++
++ return 0;
++}
++
++static int brcm_pcie_resume(struct device *dev)
++{
++ struct brcm_pcie *pcie = dev_get_drvdata(dev);
++ void __iomem *base;
++ int ret;
++
++ base = pcie->base;
++ clk_prepare_enable(pcie->clk);
++
++ /* Take bridge out of reset so we can access the SerDes reg */
++ brcm_pcie_bridge_sw_init_set(pcie, 0);
++
++ /* Turn on SerDes */
++ WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 0);
++ /* Wait for SerDes to be stable */
++ usleep_range(100, 200);
++
++ ret = brcm_pcie_setup(pcie);
++ if (ret)
++ return ret;
++
++ pcie->suspended = false;
++
++ return 0;
++}
++
++static void _brcm_pcie_remove(struct brcm_pcie *pcie)
++{
++ turn_off(pcie);
++ clk_disable_unprepare(pcie->clk);
++ clk_put(pcie->clk);
++ brcm_pcie_remove_controller(pcie);
++}
++
++static int brcm_pcie_remove(struct platform_device *pdev)
++{
++ struct brcm_pcie *pcie = platform_get_drvdata(pdev);
++
++ pci_stop_root_bus(pcie->root_bus);
++ pci_remove_root_bus(pcie->root_bus);
++ _brcm_pcie_remove(pcie);
++
++ return 0;
++}
++
++static const struct of_device_id brcm_pcie_match[] = {
++ { .compatible = "brcm,bcm7425-pcie", .data = &bcm7425_cfg },
++ { .compatible = "brcm,bcm7435-pcie", .data = &bcm7435_cfg },
++ { .compatible = "brcm,bcm7278-pcie", .data = &bcm7278_cfg },
++ { .compatible = "brcm,bcm7445-pcie", .data = &generic_cfg },
++ {},
++};
++MODULE_DEVICE_TABLE(of, brcm_pcie_match);
++
++static int brcm_pcie_probe(struct platform_device *pdev)
++{
++ struct device_node *dn = pdev->dev.of_node;
++ const struct of_device_id *of_id;
++ const struct pcie_cfg_data *data;
++ int ret;
++ struct brcm_pcie *pcie;
++ struct resource *res;
++ void __iomem *base;
++ u32 tmp;
++ struct pci_host_bridge *bridge;
++ struct pci_bus *child;
++
++ bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie));
++ if (!bridge)
++ return -ENOMEM;
++
++ pcie = pci_host_bridge_priv(bridge);
++ INIT_LIST_HEAD(&pcie->resources);
++
++ of_id = of_match_node(brcm_pcie_match, dn);
++ if (!of_id) {
++ dev_err(&pdev->dev, "failed to look up compatible string\n");
++ return -EINVAL;
++ }
++
++ if (of_property_read_u32(dn, "dma-ranges", &tmp) == 0) {
++ dev_err(&pdev->dev, "cannot yet handle dma-ranges\n");
++ return -EINVAL;
++ }
++
++ data = of_id->data;
++ pcie->reg_offsets = data->offsets;
++ pcie->reg_field_info = data->reg_field_info;
++ pcie->type = data->type;
++ pcie->dn = dn;
++ pcie->dev = &pdev->dev;
++
++ /* We use the domain number as our controller number */
++ pcie->id = of_get_pci_domain_nr(dn);
++ if (pcie->id < 0)
++ return pcie->id;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res)
++ return -EINVAL;
++
++ base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(base))
++ return PTR_ERR(base);
++
++ pcie->clk = of_clk_get_by_name(dn, "sw_pcie");
++ if (IS_ERR(pcie->clk)) {
++ dev_err(&pdev->dev, "could not get clock\n");
++ pcie->clk = NULL;
++ }
++ pcie->base = base;
++
++ ret = of_pci_get_max_link_speed(dn);
++ pcie->gen = (ret < 0) ? 0 : ret;
++
++ pcie->ssc = of_property_read_bool(dn, "brcm,enable-ssc");
++
++ ret = irq_of_parse_and_map(pdev->dev.of_node, 0);
++ if (ret == 0)
++ /* keep going, as we don't use this intr yet */
++ dev_warn(pcie->dev, "cannot get PCIe interrupt\n");
++ else
++ pcie->irq = ret;
++
++ ret = brcm_pcie_parse_request_of_pci_ranges(pcie);
++ if (ret)
++ return ret;
++
++ ret = clk_prepare_enable(pcie->clk);
++ if (ret) {
++ dev_err(&pdev->dev, "could not enable clock\n");
++ return ret;
++ }
++
++ ret = brcm_pcie_add_controller(pcie);
++ if (ret)
++ return ret;
++
++ ret = brcm_pcie_setup(pcie);
++ if (ret)
++ goto fail;
++
++ list_splice_init(&pcie->resources, &bridge->windows);
++ bridge->dev.parent = &pdev->dev;
++ bridge->busnr = 0;
++ bridge->ops = &brcm_pcie_ops;
++ bridge->sysdata = pcie;
++ bridge->map_irq = of_irq_parse_and_map_pci;
++ bridge->swizzle_irq = pci_common_swizzle;
++
++ ret = pci_scan_root_bus_bridge(bridge);
++ if (ret < 0) {
++ dev_err(pcie->dev, "Scanning root bridge failed\n");
++ goto fail;
++ }
++
++ pci_assign_unassigned_bus_resources(bridge->bus);
++ list_for_each_entry(child, &bridge->bus->children, node)
++ pcie_bus_configure_settings(child);
++ pci_bus_add_devices(bridge->bus);
++ platform_set_drvdata(pdev, pcie);
++ pcie->root_bus = bridge->bus;
++
++ return 0;
++
++fail:
++ _brcm_pcie_remove(pcie);
++ return ret;
++}
++
++static const struct dev_pm_ops brcm_pcie_pm_ops = {
++ .suspend_noirq = brcm_pcie_suspend,
++ .resume_noirq = brcm_pcie_resume,
++};
++
++static struct platform_driver brcm_pcie_driver = {
++ .probe = brcm_pcie_probe,
++ .remove = brcm_pcie_remove,
++ .driver = {
++ .name = "brcm-pcie",
++ .owner = THIS_MODULE,
++ .of_match_table = brcm_pcie_match,
++ .pm = &brcm_pcie_pm_ops,
++ },
++};
++
++module_platform_driver(brcm_pcie_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("Broadcom STB PCIe RC driver");
++MODULE_AUTHOR("Broadcom");
+--- /dev/null
++++ b/include/soc/brcmstb/memory_api.h
+@@ -0,0 +1,25 @@
++#ifndef __MEMORY_API_H
++#define __MEMORY_API_H
++
++/*
++ * Bus Interface Unit control register setup, must happen early during boot,
++ * before SMP is brought up, called by machine entry point.
++ */
++void brcmstb_biuctrl_init(void);
++
++#ifdef CONFIG_SOC_BRCMSTB
++int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa);
++u64 brcmstb_memory_memc_size(int memc);
++#else
++static inline int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa)
++{
++ return -EINVAL;
++}
++
++static inline u64 brcmstb_memory_memc_size(int memc)
++{
++ return -1;
++}
++#endif
++
++#endif /* __MEMORY_API_H */
+++ /dev/null
-From ef4e6bd54e6b5d352eb62d245bf4354259812d05 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Thu, 12 Oct 2017 18:11:32 +0100
-Subject: [PATCH 530/703] dts: Use fb rather than leds for dpi overlay
-
----
- arch/arm/boot/dts/overlays/dpi18-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/dpi24-overlay.dts | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/dpi18-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dpi18-overlay.dts
-@@ -9,7 +9,7 @@
- // reference on - leds will do
-
- fragment@0 {
-- target = <&leds>;
-+ target = <&fb>;
- __overlay__ {
- pinctrl-names = "default";
- pinctrl-0 = <&dpi18_pins>;
---- a/arch/arm/boot/dts/overlays/dpi24-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dpi24-overlay.dts
-@@ -9,7 +9,7 @@
- // reference on - leds will do
-
- fragment@0 {
-- target = <&leds>;
-+ target = <&fb>;
- __overlay__ {
- pinctrl-names = "default";
- pinctrl-0 = <&dpi24_pins>;
+++ /dev/null
-From 8b2b33292610a414d8cc3a7a78104fd375bf0cce Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 29 May 2019 15:19:21 +0100
-Subject: [PATCH 531/703] BCM270X_DT: Minor tidy up
-
-Move arm_pmu out of soc on bcm2710, and labels aren't aliases.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm270x.dtsi | 14 +++++++-------
- arch/arm/boot/dts/bcm2710.dtsi | 13 +++++--------
- 2 files changed, 12 insertions(+), 15 deletions(-)
-
---- a/arch/arm/boot/dts/bcm270x.dtsi
-+++ b/arch/arm/boot/dts/bcm270x.dtsi
-@@ -10,11 +10,11 @@
- soc: soc {
-
- watchdog: watchdog@7e100000 {
-- /* Add alias */
-+ /* Add label */
- };
-
- random: rng@7e104000 {
-- /* Add alias */
-+ /* Add label */
- };
-
- gpio@7e200000 { /* gpio */
-@@ -40,18 +40,18 @@
- };
-
- spi0: spi@7e204000 {
-- /* Add alias */
-+ /* Add label */
- dmas = <&dma 6>, <&dma 7>;
- dma-names = "tx", "rx";
- };
-
- pixelvalve0: pixelvalve@7e206000 {
-- /* Add alias */
-+ /* Add label */
- status = "disabled";
- };
-
- pixelvalve1: pixelvalve@7e207000 {
-- /* Add alias */
-+ /* Add label */
- status = "disabled";
- };
-
-@@ -93,7 +93,7 @@
- };
-
- hvs: hvs@7e400000 {
-- /* Add alias */
-+ /* Add label */
- status = "disabled";
- };
-
-@@ -119,7 +119,7 @@
- };
-
- pixelvalve2: pixelvalve@7e807000 {
-- /* Add alias */
-+ /* Add label */
- status = "disabled";
- };
-
---- a/arch/arm/boot/dts/bcm2710.dtsi
-+++ b/arch/arm/boot/dts/bcm2710.dtsi
-@@ -5,18 +5,15 @@
- / {
- compatible = "brcm,bcm2837", "brcm,bcm2836";
-
-- soc {
--
-- arm-pmu {
-+ arm-pmu {
- #ifdef RPI364
-- compatible = "arm,armv8-pmuv3", "arm,cortex-a7-pmu";
-+ compatible = "arm,armv8-pmuv3", "arm,cortex-a7-pmu";
- #else
-- compatible = "arm,cortex-a7-pmu";
-+ compatible = "arm,cortex-a7-pmu";
- #endif
-- interrupt-parent = <&local_intc>;
-- interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
-- };
-+ };
-
-+ soc {
- /delete-node/ timer@7e003000;
- };
-
--- /dev/null
+From 155b86245f5c14317f41a0677ed78601fbe1f28b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 19 Feb 2019 22:06:59 +0000
+Subject: [PATCH 531/725] PCI: brcmstb: Add dma-range mapping for inbound
+ traffic
+
+The Broadcom STB PCIe host controller is intimately related to the
+memory subsystem. This close relationship adds complexity to how cpu
+system memory is mapped to PCIe memory. Ideally, this mapping is an
+identity mapping, or an identity mapping off by a constant. Not so in
+this case.
+
+Consider the Broadcom reference board BCM97445LCC_4X8 which has 6 GB
+of system memory. Here is how the PCIe controller maps the
+system memory to PCIe memory:
+
+ memc0-a@[ 0....3fffffff] <=> pci@[ 0....3fffffff]
+ memc0-b@[100000000...13fffffff] <=> pci@[ 40000000....7fffffff]
+ memc1-a@[ 40000000....7fffffff] <=> pci@[ 80000000....bfffffff]
+ memc1-b@[300000000...33fffffff] <=> pci@[ c0000000....ffffffff]
+ memc2-a@[ 80000000....bfffffff] <=> pci@[100000000...13fffffff]
+ memc2-b@[c00000000...c3fffffff] <=> pci@[140000000...17fffffff]
+
+Although there are some "gaps" that can be added between the
+individual mappings by software, the permutation of memory regions for
+the most part is fixed by HW. The solution of having something close
+to an identity mapping is not possible.
+
+The idea behind this HW design is that the same PCIe module can
+act as an RC or EP, and if it acts as an EP it concatenates all
+of system memory into a BAR so anything can be accessed. Unfortunately,
+when the PCIe block is in the role of an RC it also presents this
+"BAR" to downstream PCIe devices, rather than offering an identity map
+between its system memory and PCIe space.
+
+Suppose that an endpoint driver allocs some DMA memory. Suppose this
+memory is located at 0x6000_0000, which is in the middle of memc1-a.
+The driver wants a dma_addr_t value that it can pass on to the EP to
+use. Without doing any custom mapping, the EP will use this value for
+DMA: the driver will get a dma_addr_t equal to 0x6000_0000. But this
+won't work; the device needs a dma_addr_t that reflects the PCIe space
+address, namely 0xa000_0000.
+
+So, essentially the solution to this problem must modify the
+dma_addr_t returned by the DMA routines routines. There are two
+ways (I know of) of doing this:
+
+(a) overriding/redefining the dma_to_phys() and phys_to_dma() calls
+that are used by the dma_ops routines. This is the approach of
+
+ arch/mips/cavium-octeon/dma-octeon.c
+
+In ARM and ARM64 these two routines are defiend in asm/dma-mapping.h
+as static inline functions.
+
+(b) Subscribe to a notifier that notifies when a device is added to a
+bus. When this happens, set_dma_ops() can be called for the device.
+This method is mentioned in:
+
+ http://lxr.free-electrons.com/source/drivers/of/platform.c?v=3.16#L152
+
+where it says as a comment
+
+ "In case if platform code need to use own special DMA
+ configuration, it can use Platform bus notifier and
+ handle BUS_NOTIFY_ADD_DEVICE event to fix up DMA
+ configuration."
+
+Solution (b) is what this commit does. It uses its own set of
+dma_ops which are wrappers around the arch_dma_ops. The
+wrappers translate the dma addresses before/after invoking
+the arch_dma_ops, as appropriate.
+
+Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
+---
+ drivers/pci/controller/pcie-brcmstb.c | 420 +++++++++++++++++++++++++-
+ 1 file changed, 411 insertions(+), 9 deletions(-)
+
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -4,6 +4,7 @@
+ #include <linux/clk.h>
+ #include <linux/compiler.h>
+ #include <linux/delay.h>
++#include <linux/dma-mapping.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/io.h>
+@@ -319,11 +320,307 @@ static struct pci_ops brcm_pcie_ops = {
+ ((val & ~reg##_##field##_MASK) | \
+ (reg##_##field##_MASK & (field_val << reg##_##field##_SHIFT)))
+
++static const struct dma_map_ops *arch_dma_ops;
++static const struct dma_map_ops *brcm_dma_ops_ptr;
++static struct of_pci_range *dma_ranges;
++static int num_dma_ranges;
++
+ static phys_addr_t scb_size[BRCM_MAX_SCB];
+ static int num_memc;
+ static int num_pcie;
+ static DEFINE_MUTEX(brcm_pcie_lock);
+
++static dma_addr_t brcm_to_pci(dma_addr_t addr)
++{
++ struct of_pci_range *p;
++
++ if (!num_dma_ranges)
++ return addr;
++
++ for (p = dma_ranges; p < &dma_ranges[num_dma_ranges]; p++)
++ if (addr >= p->cpu_addr && addr < (p->cpu_addr + p->size))
++ return addr - p->cpu_addr + p->pci_addr;
++
++ return addr;
++}
++
++static dma_addr_t brcm_to_cpu(dma_addr_t addr)
++{
++ struct of_pci_range *p;
++
++ if (!num_dma_ranges)
++ return addr;
++
++ for (p = dma_ranges; p < &dma_ranges[num_dma_ranges]; p++)
++ if (addr >= p->pci_addr && addr < (p->pci_addr + p->size))
++ return addr - p->pci_addr + p->cpu_addr;
++
++ return addr;
++}
++
++static void *brcm_alloc(struct device *dev, size_t size, dma_addr_t *handle,
++ gfp_t gfp, unsigned long attrs)
++{
++ void *ret;
++
++ ret = arch_dma_ops->alloc(dev, size, handle, gfp, attrs);
++ if (ret)
++ *handle = brcm_to_pci(*handle);
++ return ret;
++}
++
++static void brcm_free(struct device *dev, size_t size, void *cpu_addr,
++ dma_addr_t handle, unsigned long attrs)
++{
++ handle = brcm_to_cpu(handle);
++ arch_dma_ops->free(dev, size, cpu_addr, handle, attrs);
++}
++
++static int brcm_mmap(struct device *dev, struct vm_area_struct *vma,
++ void *cpu_addr, dma_addr_t dma_addr, size_t size,
++ unsigned long attrs)
++{
++ dma_addr = brcm_to_cpu(dma_addr);
++ return arch_dma_ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
++}
++
++static int brcm_get_sgtable(struct device *dev, struct sg_table *sgt,
++ void *cpu_addr, dma_addr_t handle, size_t size,
++ unsigned long attrs)
++{
++ handle = brcm_to_cpu(handle);
++ return arch_dma_ops->get_sgtable(dev, sgt, cpu_addr, handle, size,
++ attrs);
++}
++
++static dma_addr_t brcm_map_page(struct device *dev, struct page *page,
++ unsigned long offset, size_t size,
++ enum dma_data_direction dir,
++ unsigned long attrs)
++{
++ return brcm_to_pci(arch_dma_ops->map_page(dev, page, offset, size,
++ dir, attrs));
++}
++
++static void brcm_unmap_page(struct device *dev, dma_addr_t handle,
++ size_t size, enum dma_data_direction dir,
++ unsigned long attrs)
++{
++ handle = brcm_to_cpu(handle);
++ arch_dma_ops->unmap_page(dev, handle, size, dir, attrs);
++}
++
++static int brcm_map_sg(struct device *dev, struct scatterlist *sgl,
++ int nents, enum dma_data_direction dir,
++ unsigned long attrs)
++{
++ int i, j;
++ struct scatterlist *sg;
++
++ for_each_sg(sgl, sg, nents, i) {
++#ifdef CONFIG_NEED_SG_DMA_LENGTH
++ sg->dma_length = sg->length;
++#endif
++ sg->dma_address =
++ brcm_dma_ops_ptr->map_page(dev, sg_page(sg), sg->offset,
++ sg->length, dir, attrs);
++ if (dma_mapping_error(dev, sg->dma_address))
++ goto bad_mapping;
++ }
++ return nents;
++
++bad_mapping:
++ for_each_sg(sgl, sg, i, j)
++ brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
++ sg_dma_len(sg), dir, attrs);
++ return 0;
++}
++
++static void brcm_unmap_sg(struct device *dev,
++ struct scatterlist *sgl, int nents,
++ enum dma_data_direction dir,
++ unsigned long attrs)
++{
++ int i;
++ struct scatterlist *sg;
++
++ for_each_sg(sgl, sg, nents, i)
++ brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
++ sg_dma_len(sg), dir, attrs);
++}
++
++static void brcm_sync_single_for_cpu(struct device *dev,
++ dma_addr_t handle, size_t size,
++ enum dma_data_direction dir)
++{
++ handle = brcm_to_cpu(handle);
++ arch_dma_ops->sync_single_for_cpu(dev, handle, size, dir);
++}
++
++static void brcm_sync_single_for_device(struct device *dev,
++ dma_addr_t handle, size_t size,
++ enum dma_data_direction dir)
++{
++ handle = brcm_to_cpu(handle);
++ arch_dma_ops->sync_single_for_device(dev, handle, size, dir);
++}
++
++static dma_addr_t brcm_map_resource(struct device *dev, phys_addr_t phys,
++ size_t size,
++ enum dma_data_direction dir,
++ unsigned long attrs)
++{
++ if (arch_dma_ops->map_resource)
++ return brcm_to_pci(arch_dma_ops->map_resource
++ (dev, phys, size, dir, attrs));
++ return brcm_to_pci((dma_addr_t)phys);
++}
++
++static void brcm_unmap_resource(struct device *dev, dma_addr_t handle,
++ size_t size, enum dma_data_direction dir,
++ unsigned long attrs)
++{
++ if (arch_dma_ops->unmap_resource)
++ arch_dma_ops->unmap_resource(dev, brcm_to_cpu(handle), size,
++ dir, attrs);
++}
++
++void brcm_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl,
++ int nents, enum dma_data_direction dir)
++{
++ struct scatterlist *sg;
++ int i;
++
++ for_each_sg(sgl, sg, nents, i)
++ brcm_dma_ops_ptr->sync_single_for_cpu(dev, sg_dma_address(sg),
++ sg->length, dir);
++}
++
++void brcm_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
++ int nents, enum dma_data_direction dir)
++{
++ struct scatterlist *sg;
++ int i;
++
++ for_each_sg(sgl, sg, nents, i)
++ brcm_dma_ops_ptr->sync_single_for_device(dev,
++ sg_dma_address(sg),
++ sg->length, dir);
++}
++
++static int brcm_mapping_error(struct device *dev, dma_addr_t dma_addr)
++{
++ return arch_dma_ops->mapping_error(dev, dma_addr);
++}
++
++static int brcm_dma_supported(struct device *dev, u64 mask)
++{
++ if (num_dma_ranges) {
++ /*
++ * It is our translated addresses that the EP will "see", so
++ * we check all of the ranges for the largest possible value.
++ */
++ int i;
++
++ for (i = 0; i < num_dma_ranges; i++)
++ if (dma_ranges[i].pci_addr + dma_ranges[i].size - 1
++ > mask)
++ return 0;
++ return 1;
++ }
++
++ return arch_dma_ops->dma_supported(dev, mask);
++}
++
++#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
++u64 brcm_get_required_mask)(struct device *dev)
++{
++ return arch_dma_ops->get_required_mask(dev);
++}
++#endif
++
++static const struct dma_map_ops brcm_dma_ops = {
++ .alloc = brcm_alloc,
++ .free = brcm_free,
++ .mmap = brcm_mmap,
++ .get_sgtable = brcm_get_sgtable,
++ .map_page = brcm_map_page,
++ .unmap_page = brcm_unmap_page,
++ .map_sg = brcm_map_sg,
++ .unmap_sg = brcm_unmap_sg,
++ .map_resource = brcm_map_resource,
++ .unmap_resource = brcm_unmap_resource,
++ .sync_single_for_cpu = brcm_sync_single_for_cpu,
++ .sync_single_for_device = brcm_sync_single_for_device,
++ .sync_sg_for_cpu = brcm_sync_sg_for_cpu,
++ .sync_sg_for_device = brcm_sync_sg_for_device,
++ .mapping_error = brcm_mapping_error,
++ .dma_supported = brcm_dma_supported,
++#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
++ .get_required_mask = brcm_get_required_mask,
++#endif
++};
++
++static void brcm_set_dma_ops(struct device *dev)
++{
++ int ret;
++
++ if (IS_ENABLED(CONFIG_ARM64)) {
++ /*
++ * We are going to invoke get_dma_ops(). That
++ * function, at this point in time, invokes
++ * get_arch_dma_ops(), and for ARM64 that function
++ * returns a pointer to dummy_dma_ops. So then we'd
++ * like to call arch_setup_dma_ops(), but that isn't
++ * exported. Instead, we call of_dma_configure(),
++ * which is exported, and this calls
++ * arch_setup_dma_ops(). Once we do this the call to
++ * get_dma_ops() will work properly because
++ * dev->dma_ops will be set.
++ */
++ ret = of_dma_configure(dev, dev->of_node, true);
++ if (ret) {
++ dev_err(dev, "of_dma_configure() failed: %d\n", ret);
++ return;
++ }
++ }
++
++ arch_dma_ops = get_dma_ops(dev);
++ if (!arch_dma_ops) {
++ dev_err(dev, "failed to get arch_dma_ops\n");
++ return;
++ }
++
++ set_dma_ops(dev, &brcm_dma_ops);
++}
++
++static int brcmstb_platform_notifier(struct notifier_block *nb,
++ unsigned long event, void *__dev)
++{
++ struct device *dev = __dev;
++
++ brcm_dma_ops_ptr = &brcm_dma_ops;
++ if (event != BUS_NOTIFY_ADD_DEVICE)
++ return NOTIFY_DONE;
++
++ brcm_set_dma_ops(dev);
++ return NOTIFY_OK;
++}
++
++static struct notifier_block brcmstb_platform_nb = {
++ .notifier_call = brcmstb_platform_notifier,
++};
++
++static int brcm_register_notifier(void)
++{
++ return bus_register_notifier(&pci_bus_type, &brcmstb_platform_nb);
++}
++
++static int brcm_unregister_notifier(void)
++{
++ return bus_unregister_notifier(&pci_bus_type, &brcmstb_platform_nb);
++}
++
+ static u32 rd_fld(void __iomem *p, u32 mask, int shift)
+ {
+ return (bcm_readl(p) & mask) >> shift;
+@@ -597,9 +894,71 @@ static inline void brcm_pcie_perst_set(s
+ WR_FLD_RB(pcie->base, PCIE_MISC_PCIE_CTRL, PCIE_PERSTB, !val);
+ }
+
++static int pci_dma_range_parser_init(struct of_pci_range_parser *parser,
++ struct device_node *node)
++{
++ const int na = 3, ns = 2;
++ int rlen;
++
++ parser->node = node;
++ parser->pna = of_n_addr_cells(node);
++ parser->np = parser->pna + na + ns;
++
++ parser->range = of_get_property(node, "dma-ranges", &rlen);
++ if (!parser->range)
++ return -ENOENT;
++
++ parser->end = parser->range + rlen / sizeof(__be32);
++
++ return 0;
++}
++
++static int brcm_pcie_parse_map_dma_ranges(struct brcm_pcie *pcie)
++{
++ int i;
++ struct of_pci_range_parser parser;
++ struct device_node *dn = pcie->dn;
++
++ /*
++ * Parse dma-ranges property if present. If there are multiple
++ * PCIe controllers, we only have to parse from one of them since
++ * the others will have an identical mapping.
++ */
++ if (!pci_dma_range_parser_init(&parser, dn)) {
++ unsigned int max_ranges
++ = (parser.end - parser.range) / parser.np;
++
++ dma_ranges = kcalloc(max_ranges, sizeof(struct of_pci_range),
++ GFP_KERNEL);
++ if (!dma_ranges)
++ return -ENOMEM;
++
++ for (i = 0; of_pci_range_parser_one(&parser, dma_ranges + i);
++ i++)
++ num_dma_ranges++;
++ }
++
++ for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
++ u64 size = brcmstb_memory_memc_size(i);
++
++ if (size == (u64)-1) {
++ dev_err(pcie->dev, "cannot get memc%d size", i);
++ return -EINVAL;
++ } else if (size) {
++ scb_size[i] = roundup_pow_of_two_64(size);
++ num_memc++;
++ } else {
++ break;
++ }
++ }
++
++ return 0;
++}
++
+ static int brcm_pcie_add_controller(struct brcm_pcie *pcie)
+ {
+ int i, ret = 0;
++ struct device *dev = pcie->dev;
+
+ mutex_lock(&brcm_pcie_lock);
+ if (num_pcie > 0) {
+@@ -607,12 +966,21 @@ static int brcm_pcie_add_controller(stru
+ goto done;
+ }
+
++ ret = brcm_register_notifier();
++ if (ret) {
++ dev_err(dev, "failed to register pci bus notifier\n");
++ goto done;
++ }
++ ret = brcm_pcie_parse_map_dma_ranges(pcie);
++ if (ret)
++ goto done;
++
+ /* Determine num_memc and their sizes */
+ for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
+ u64 size = brcmstb_memory_memc_size(i);
+
+ if (size == (u64)-1) {
+- dev_err(pcie->dev, "cannot get memc%d size\n", i);
++ dev_err(dev, "cannot get memc%d size\n", i);
+ ret = -EINVAL;
+ goto done;
+ } else if (size) {
+@@ -636,8 +1004,16 @@ done:
+ static void brcm_pcie_remove_controller(struct brcm_pcie *pcie)
+ {
+ mutex_lock(&brcm_pcie_lock);
+- if (--num_pcie == 0)
+- num_memc = 0;
++ if (--num_pcie > 0)
++ goto out;
++
++ if (brcm_unregister_notifier())
++ dev_err(pcie->dev, "failed to unregister pci bus notifier\n");
++ kfree(dma_ranges);
++ dma_ranges = NULL;
++ num_dma_ranges = 0;
++ num_memc = 0;
++out:
+ mutex_unlock(&brcm_pcie_lock);
+ }
+
+@@ -757,6 +1133,38 @@ static int brcm_pcie_setup(struct brcm_p
+ */
+ rc_bar2_offset = 0;
+
++ if (dma_ranges) {
++ /*
++ * The best-case scenario is to place the inbound
++ * region in the first 4GB of pci-space, as some
++ * legacy devices can only address 32bits.
++ * We would also like to put the MSI under 4GB
++ * as well, since some devices require a 32bit
++ * MSI target address.
++ */
++ if (total_mem_size <= 0xc0000000ULL &&
++ rc_bar2_size <= 0x100000000ULL) {
++ rc_bar2_offset = 0;
++ } else {
++ /*
++ * The system memory is 4GB or larger so we
++ * cannot start the inbound region at location
++ * 0 (since we have to allow some space for
++ * outbound memory @ 3GB). So instead we
++ * start it at the 1x multiple of its size
++ */
++ rc_bar2_offset = rc_bar2_size;
++ }
++
++ } else {
++ /*
++ * Set simple configuration based on memory sizes
++ * only. We always start the viewport at address 0,
++ * and set the MSI target address accordingly.
++ */
++ rc_bar2_offset = 0;
++ }
++
+ tmp = lower_32_bits(rc_bar2_offset);
+ tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
+ encode_ibar_size(rc_bar2_size));
+@@ -967,7 +1375,6 @@ static int brcm_pcie_probe(struct platfo
+ struct brcm_pcie *pcie;
+ struct resource *res;
+ void __iomem *base;
+- u32 tmp;
+ struct pci_host_bridge *bridge;
+ struct pci_bus *child;
+
+@@ -984,11 +1391,6 @@ static int brcm_pcie_probe(struct platfo
+ return -EINVAL;
+ }
+
+- if (of_property_read_u32(dn, "dma-ranges", &tmp) == 0) {
+- dev_err(&pdev->dev, "cannot yet handle dma-ranges\n");
+- return -EINVAL;
+- }
+-
+ data = of_id->data;
+ pcie->reg_offsets = data->offsets;
+ pcie->reg_field_info = data->reg_field_info;
--- /dev/null
+From 2f802e11ea7ca4f7c688ecc64019bec25a5e62a1 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 19 Feb 2019 22:06:59 +0000
+Subject: [PATCH 532/725] PCI: brcmstb: Add MSI capability
+
+This commit adds MSI to the Broadcom STB PCIe host controller. It does
+not add MSIX since that functionality is not in the HW. The MSI
+controller is physically located within the PCIe block, however, there
+is no reason why the MSI controller could not be moved elsewhere in
+the future.
+
+Since the internal Brcmstb MSI controller is intertwined with the PCIe
+controller, it is not its own platform device but rather part of the
+PCIe platform device.
+
+Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
+---
+ drivers/pci/controller/pcie-brcmstb.c | 374 ++++++++++++++++++++++++--
+ 1 file changed, 353 insertions(+), 21 deletions(-)
+
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -1,6 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /* Copyright (C) 2009 - 2017 Broadcom */
+
++#include <linux/bitops.h>
+ #include <linux/clk.h>
+ #include <linux/compiler.h>
+ #include <linux/delay.h>
+@@ -9,11 +10,13 @@
+ #include <linux/interrupt.h>
+ #include <linux/io.h>
+ #include <linux/ioport.h>
++#include <linux/irqchip/chained_irq.h>
+ #include <linux/irqdomain.h>
+ #include <linux/kernel.h>
+ #include <linux/list.h>
+ #include <linux/log2.h>
+ #include <linux/module.h>
++#include <linux/msi.h>
+ #include <linux/of_address.h>
+ #include <linux/of_irq.h>
+ #include <linux/of_pci.h>
+@@ -47,6 +50,9 @@
+ #define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034
+ #define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038
+ #define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
++#define PCIE_MISC_MSI_BAR_CONFIG_LO 0x4044
++#define PCIE_MISC_MSI_BAR_CONFIG_HI 0x4048
++#define PCIE_MISC_MSI_DATA_CONFIG 0x404c
+ #define PCIE_MISC_PCIE_CTRL 0x4064
+ #define PCIE_MISC_PCIE_STATUS 0x4068
+ #define PCIE_MISC_REVISION 0x406c
+@@ -55,6 +61,7 @@
+ #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI 0x4084
+ #define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204
+ #define PCIE_INTR2_CPU_BASE 0x4300
++#define PCIE_MSI_INTR2_BASE 0x4500
+
+ /*
+ * Broadcom Settop Box PCIe Register Field shift and mask info. The
+@@ -115,6 +122,8 @@
+
+ #define BRCM_NUM_PCIE_OUT_WINS 0x4
+ #define BRCM_MAX_SCB 0x4
++#define BRCM_INT_PCI_MSI_NR 32
++#define BRCM_PCIE_HW_REV_33 0x0303
+
+ #define BRCM_MSI_TARGET_ADDR_LT_4GB 0x0fffffffcULL
+ #define BRCM_MSI_TARGET_ADDR_GT_4GB 0xffffffffcULL
+@@ -203,6 +212,33 @@ struct brcm_window {
+ dma_addr_t size;
+ };
+
++struct brcm_msi {
++ struct device *dev;
++ void __iomem *base;
++ struct device_node *dn;
++ struct irq_domain *msi_domain;
++ struct irq_domain *inner_domain;
++ struct mutex lock; /* guards the alloc/free operations */
++ u64 target_addr;
++ int irq;
++
++ /* intr_base is the base pointer for interrupt status/set/clr regs */
++ void __iomem *intr_base;
++
++ /* intr_legacy_mask indicates how many bits are MSI interrupts */
++ u32 intr_legacy_mask;
++
++ /*
++ * intr_legacy_offset indicates bit position of MSI_01. It is
++ * to map the register bit position to a hwirq that starts at 0.
++ */
++ u32 intr_legacy_offset;
++
++ /* used indicates which MSI interrupts have been alloc'd */
++ unsigned long used;
++ unsigned int rev;
++};
++
+ /* Internal PCIe Host Controller Information.*/
+ struct brcm_pcie {
+ struct device *dev;
+@@ -217,7 +253,10 @@ struct brcm_pcie {
+ int num_out_wins;
+ bool ssc;
+ int gen;
++ u64 msi_target_addr;
+ struct brcm_window out_wins[BRCM_NUM_PCIE_OUT_WINS];
++ struct brcm_msi *msi;
++ bool msi_internal;
+ unsigned int rev;
+ const int *reg_offsets;
+ const int *reg_field_info;
+@@ -225,9 +264,9 @@ struct brcm_pcie {
+ };
+
+ struct pcie_cfg_data {
+- const int *reg_field_info;
+- const int *offsets;
+- const enum pcie_type type;
++ const int *reg_field_info;
++ const int *offsets;
++ const enum pcie_type type;
+ };
+
+ static const int pcie_reg_field_info[] = {
+@@ -828,6 +867,267 @@ static void brcm_pcie_set_outbound_win(s
+ }
+ }
+
++static struct irq_chip brcm_msi_irq_chip = {
++ .name = "Brcm_MSI",
++ .irq_mask = pci_msi_mask_irq,
++ .irq_unmask = pci_msi_unmask_irq,
++};
++
++static struct msi_domain_info brcm_msi_domain_info = {
++ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
++ MSI_FLAG_PCI_MSIX),
++ .chip = &brcm_msi_irq_chip,
++};
++
++static void brcm_pcie_msi_isr(struct irq_desc *desc)
++{
++ struct irq_chip *chip = irq_desc_get_chip(desc);
++ struct brcm_msi *msi;
++ unsigned long status, virq;
++ u32 mask, bit, hwirq;
++ struct device *dev;
++
++ chained_irq_enter(chip, desc);
++ msi = irq_desc_get_handler_data(desc);
++ mask = msi->intr_legacy_mask;
++ dev = msi->dev;
++
++ while ((status = bcm_readl(msi->intr_base + STATUS) & mask)) {
++ for_each_set_bit(bit, &status, BRCM_INT_PCI_MSI_NR) {
++ /* clear the interrupt */
++ bcm_writel(1 << bit, msi->intr_base + CLR);
++
++ /* Account for legacy interrupt offset */
++ hwirq = bit - msi->intr_legacy_offset;
++
++ virq = irq_find_mapping(msi->inner_domain, hwirq);
++ if (virq) {
++ if (msi->used & (1 << hwirq))
++ generic_handle_irq(virq);
++ else
++ dev_info(dev, "unhandled MSI %d\n",
++ hwirq);
++ } else {
++ /* Unknown MSI, just clear it */
++ dev_dbg(dev, "unexpected MSI\n");
++ }
++ }
++ }
++ chained_irq_exit(chip, desc);
++}
++
++static void brcm_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
++{
++ struct brcm_msi *msi = irq_data_get_irq_chip_data(data);
++ u32 temp;
++
++ msg->address_lo = lower_32_bits(msi->target_addr);
++ msg->address_hi = upper_32_bits(msi->target_addr);
++ temp = bcm_readl(msi->base + PCIE_MISC_MSI_DATA_CONFIG);
++ msg->data = ((temp >> 16) & (temp & 0xffff)) | data->hwirq;
++}
++
++static int brcm_msi_set_affinity(struct irq_data *irq_data,
++ const struct cpumask *mask, bool force)
++{
++ return -EINVAL;
++}
++
++static struct irq_chip brcm_msi_bottom_irq_chip = {
++ .name = "Brcm_MSI",
++ .irq_compose_msi_msg = brcm_compose_msi_msg,
++ .irq_set_affinity = brcm_msi_set_affinity,
++};
++
++static int brcm_msi_alloc(struct brcm_msi *msi)
++{
++ int bit, hwirq;
++
++ mutex_lock(&msi->lock);
++ bit = ~msi->used ? ffz(msi->used) : -1;
++
++ if (bit >= 0 && bit < BRCM_INT_PCI_MSI_NR) {
++ msi->used |= (1 << bit);
++ hwirq = bit - msi->intr_legacy_offset;
++ } else {
++ hwirq = -ENOSPC;
++ }
++
++ mutex_unlock(&msi->lock);
++ return hwirq;
++}
++
++static void brcm_msi_free(struct brcm_msi *msi, unsigned long hwirq)
++{
++ mutex_lock(&msi->lock);
++ msi->used &= ~(1 << (hwirq + msi->intr_legacy_offset));
++ mutex_unlock(&msi->lock);
++}
++
++static int brcm_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
++ unsigned int nr_irqs, void *args)
++{
++ struct brcm_msi *msi = domain->host_data;
++ int hwirq;
++
++ hwirq = brcm_msi_alloc(msi);
++
++ if (hwirq < 0)
++ return hwirq;
++
++ irq_domain_set_info(domain, virq, (irq_hw_number_t)hwirq,
++ &brcm_msi_bottom_irq_chip, domain->host_data,
++ handle_simple_irq, NULL, NULL);
++ return 0;
++}
++
++static void brcm_irq_domain_free(struct irq_domain *domain,
++ unsigned int virq, unsigned int nr_irqs)
++{
++ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
++ struct brcm_msi *msi = irq_data_get_irq_chip_data(d);
++
++ brcm_msi_free(msi, d->hwirq);
++}
++
++static void brcm_msi_set_regs(struct brcm_msi *msi)
++{
++ u32 data_val, msi_lo, msi_hi;
++
++ if (msi->rev >= BRCM_PCIE_HW_REV_33) {
++ /*
++ * ffe0 -- least sig 5 bits are 0 indicating 32 msgs
++ * 6540 -- this is our arbitrary unique data value
++ */
++ data_val = 0xffe06540;
++ } else {
++ /*
++ * fff8 -- least sig 3 bits are 0 indicating 8 msgs
++ * 6540 -- this is our arbitrary unique data value
++ */
++ data_val = 0xfff86540;
++ }
++
++ /*
++ * Make sure we are not masking MSIs. Note that MSIs can be masked,
++ * but that occurs on the PCIe EP device
++ */
++ bcm_writel(0xffffffff & msi->intr_legacy_mask,
++ msi->intr_base + MASK_CLR);
++
++ msi_lo = lower_32_bits(msi->target_addr);
++ msi_hi = upper_32_bits(msi->target_addr);
++ /*
++ * The 0 bit of PCIE_MISC_MSI_BAR_CONFIG_LO is repurposed to MSI
++ * enable, which we set to 1.
++ */
++ bcm_writel(msi_lo | 1, msi->base + PCIE_MISC_MSI_BAR_CONFIG_LO);
++ bcm_writel(msi_hi, msi->base + PCIE_MISC_MSI_BAR_CONFIG_HI);
++ bcm_writel(data_val, msi->base + PCIE_MISC_MSI_DATA_CONFIG);
++}
++
++static const struct irq_domain_ops msi_domain_ops = {
++ .alloc = brcm_irq_domain_alloc,
++ .free = brcm_irq_domain_free,
++};
++
++static int brcm_allocate_domains(struct brcm_msi *msi)
++{
++ struct fwnode_handle *fwnode = of_node_to_fwnode(msi->dn);
++ struct device *dev = msi->dev;
++
++ msi->inner_domain = irq_domain_add_linear(NULL, BRCM_INT_PCI_MSI_NR,
++ &msi_domain_ops, msi);
++ if (!msi->inner_domain) {
++ dev_err(dev, "failed to create IRQ domain\n");
++ return -ENOMEM;
++ }
++
++ msi->msi_domain = pci_msi_create_irq_domain(fwnode,
++ &brcm_msi_domain_info,
++ msi->inner_domain);
++ if (!msi->msi_domain) {
++ dev_err(dev, "failed to create MSI domain\n");
++ irq_domain_remove(msi->inner_domain);
++ return -ENOMEM;
++ }
++
++ return 0;
++}
++
++static void brcm_free_domains(struct brcm_msi *msi)
++{
++ irq_domain_remove(msi->msi_domain);
++ irq_domain_remove(msi->inner_domain);
++}
++
++static void brcm_msi_remove(struct brcm_pcie *pcie)
++{
++ struct brcm_msi *msi = pcie->msi;
++
++ if (!msi)
++ return;
++ irq_set_chained_handler(msi->irq, NULL);
++ irq_set_handler_data(msi->irq, NULL);
++ brcm_free_domains(msi);
++}
++
++static int brcm_pcie_enable_msi(struct brcm_pcie *pcie)
++{
++ struct brcm_msi *msi;
++ int irq, ret;
++ struct device *dev = pcie->dev;
++
++ irq = irq_of_parse_and_map(dev->of_node, 1);
++ if (irq <= 0) {
++ dev_err(dev, "cannot map msi intr\n");
++ return -ENODEV;
++ }
++
++ msi = devm_kzalloc(dev, sizeof(struct brcm_msi), GFP_KERNEL);
++ if (!msi)
++ return -ENOMEM;
++
++ msi->dev = dev;
++ msi->base = pcie->base;
++ msi->rev = pcie->rev;
++ msi->dn = pcie->dn;
++ msi->target_addr = pcie->msi_target_addr;
++ msi->irq = irq;
++
++ ret = brcm_allocate_domains(msi);
++ if (ret)
++ return ret;
++
++ irq_set_chained_handler_and_data(msi->irq, brcm_pcie_msi_isr, msi);
++
++ if (msi->rev >= BRCM_PCIE_HW_REV_33) {
++ msi->intr_base = msi->base + PCIE_MSI_INTR2_BASE;
++ /*
++ * This version of PCIe hw has only 32 intr bits
++ * starting at bit position 0.
++ */
++ msi->intr_legacy_mask = 0xffffffff;
++ msi->intr_legacy_offset = 0x0;
++ msi->used = 0x0;
++
++ } else {
++ msi->intr_base = msi->base + PCIE_INTR2_CPU_BASE;
++ /*
++ * This version of PCIe hw has only 8 intr bits starting
++ * at bit position 24.
++ */
++ msi->intr_legacy_mask = 0xff000000;
++ msi->intr_legacy_offset = 24;
++ msi->used = 0x00ffffff;
++ }
++
++ brcm_msi_set_regs(msi);
++ pcie->msi = msi;
++
++ return 0;
++}
++
+ /* Configuration space read/write support */
+ static int cfg_index(int busnr, int devfn, int reg)
+ {
+@@ -1072,6 +1372,7 @@ static int brcm_pcie_setup(struct brcm_p
+ u16 nlw, cls, lnksta;
+ bool ssc_good = false;
+ struct device *dev = pcie->dev;
++ u64 msi_target_addr;
+
+ /* Reset the bridge */
+ brcm_pcie_bridge_sw_init_set(pcie, 1);
+@@ -1116,27 +1417,24 @@ static int brcm_pcie_setup(struct brcm_p
+ * The PCIe host controller by design must set the inbound
+ * viewport to be a contiguous arrangement of all of the
+ * system's memory. In addition, its size mut be a power of
+- * two. To further complicate matters, the viewport must
+- * start on a pcie-address that is aligned on a multiple of its
+- * size. If a portion of the viewport does not represent
+- * system memory -- e.g. 3GB of memory requires a 4GB viewport
+- * -- we can map the outbound memory in or after 3GB and even
+- * though the viewport will overlap the outbound memory the
+- * controller will know to send outbound memory downstream and
+- * everything else upstream.
++ * two. Further, the MSI target address must NOT be placed
++ * inside this region, as the decoding logic will consider its
++ * address to be inbound memory traffic. To further
++ * complicate matters, the viewport must start on a
++ * pcie-address that is aligned on a multiple of its size.
++ * If a portion of the viewport does not represent system
++ * memory -- e.g. 3GB of memory requires a 4GB viewport --
++ * we can map the outbound memory in or after 3GB and even
++ * though the viewport will overlap the outbound memory
++ * the controller will know to send outbound memory downstream
++ * and everything else upstream.
+ */
+ rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
+
+- /*
+- * Set simple configuration based on memory sizes
+- * only. We always start the viewport at address 0.
+- */
+- rc_bar2_offset = 0;
+-
+ if (dma_ranges) {
+ /*
+ * The best-case scenario is to place the inbound
+- * region in the first 4GB of pci-space, as some
++ * region in the first 4GB of pcie-space, as some
+ * legacy devices can only address 32bits.
+ * We would also like to put the MSI under 4GB
+ * as well, since some devices require a 32bit
+@@ -1145,6 +1443,14 @@ static int brcm_pcie_setup(struct brcm_p
+ if (total_mem_size <= 0xc0000000ULL &&
+ rc_bar2_size <= 0x100000000ULL) {
+ rc_bar2_offset = 0;
++ /* If the viewport is less then 4GB we can fit
++ * the MSI target address under 4GB. Otherwise
++ * put it right below 64GB.
++ */
++ msi_target_addr =
++ (rc_bar2_size == 0x100000000ULL)
++ ? BRCM_MSI_TARGET_ADDR_GT_4GB
++ : BRCM_MSI_TARGET_ADDR_LT_4GB;
+ } else {
+ /*
+ * The system memory is 4GB or larger so we
+@@ -1154,8 +1460,12 @@ static int brcm_pcie_setup(struct brcm_p
+ * start it at the 1x multiple of its size
+ */
+ rc_bar2_offset = rc_bar2_size;
+- }
+
++ /* Since we are starting the viewport at 4GB or
++ * higher, put the MSI target address below 4GB
++ */
++ msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
++ }
+ } else {
+ /*
+ * Set simple configuration based on memory sizes
+@@ -1163,7 +1473,12 @@ static int brcm_pcie_setup(struct brcm_p
+ * and set the MSI target address accordingly.
+ */
+ rc_bar2_offset = 0;
++
++ msi_target_addr = (rc_bar2_size >= 0x100000000ULL)
++ ? BRCM_MSI_TARGET_ADDR_GT_4GB
++ : BRCM_MSI_TARGET_ADDR_LT_4GB;
+ }
++ pcie->msi_target_addr = msi_target_addr;
+
+ tmp = lower_32_bits(rc_bar2_offset);
+ tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
+@@ -1333,6 +1648,9 @@ static int brcm_pcie_resume(struct devic
+ if (ret)
+ return ret;
+
++ if (pcie->msi && pcie->msi_internal)
++ brcm_msi_set_regs(pcie->msi);
++
+ pcie->suspended = false;
+
+ return 0;
+@@ -1340,6 +1658,7 @@ static int brcm_pcie_resume(struct devic
+
+ static void _brcm_pcie_remove(struct brcm_pcie *pcie)
+ {
++ brcm_msi_remove(pcie);
+ turn_off(pcie);
+ clk_disable_unprepare(pcie->clk);
+ clk_put(pcie->clk);
+@@ -1368,7 +1687,7 @@ MODULE_DEVICE_TABLE(of, brcm_pcie_match)
+
+ static int brcm_pcie_probe(struct platform_device *pdev)
+ {
+- struct device_node *dn = pdev->dev.of_node;
++ struct device_node *dn = pdev->dev.of_node, *msi_dn;
+ const struct of_device_id *of_id;
+ const struct pcie_cfg_data *data;
+ int ret;
+@@ -1448,6 +1767,20 @@ static int brcm_pcie_probe(struct platfo
+ if (ret)
+ goto fail;
+
++ msi_dn = of_parse_phandle(pcie->dn, "msi-parent", 0);
++ /* Use the internal MSI if no msi-parent property */
++ if (!msi_dn)
++ msi_dn = pcie->dn;
++
++ if (pci_msi_enabled() && msi_dn == pcie->dn) {
++ ret = brcm_pcie_enable_msi(pcie);
++ if (ret)
++ dev_err(pcie->dev,
++ "probe of internal MSI failed: %d)", ret);
++ else
++ pcie->msi_internal = true;
++ }
++
+ list_splice_init(&pcie->resources, &bridge->windows);
+ bridge->dev.parent = &pdev->dev;
+ bridge->busnr = 0;
+@@ -1470,7 +1803,6 @@ static int brcm_pcie_probe(struct platfo
+ pcie->root_bus = bridge->bus;
+
+ return 0;
+-
+ fail:
+ _brcm_pcie_remove(pcie);
+ return ret;
+++ /dev/null
-From bd1c6d07ec4b1ddf087ad139c0164ab195244a55 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 20 Feb 2019 08:49:39 +0000
-Subject: [PATCH 532/703] arm: bcm2835: Fix FIQ early ioremap
-
-The ioremapping creates mappings within the vmalloc area. The
-equivalent early function, create_mapping, now checks that the
-requested explicit virtual address is between VMALLOC_START and
-VMALLOC_END. As there is no reason to have any correlation between
-the physical and virtual addresses, put the required mappings at
-VMALLOC_START and above.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/mach-bcm/board_bcm2835.c | 21 +++++++++++++++------
- 1 file changed, 15 insertions(+), 6 deletions(-)
-
---- a/arch/arm/mach-bcm/board_bcm2835.c
-+++ b/arch/arm/mach-bcm/board_bcm2835.c
-@@ -14,17 +14,20 @@
-
- #include <linux/init.h>
- #include <linux/irqchip.h>
-+#include <linux/mm.h>
- #include <linux/of_address.h>
- #include <linux/of_fdt.h>
- #include <asm/system_info.h>
-
- #include <asm/mach/arch.h>
- #include <asm/mach/map.h>
-+#include <asm/memory.h>
-+#include <asm/pgtable.h>
-
- #include "platsmp.h"
-
--#define BCM2835_USB_VIRT_BASE 0xf0980000
--#define BCM2835_USB_VIRT_MPHI 0xf0006000
-+#define BCM2835_USB_VIRT_BASE (VMALLOC_START)
-+#define BCM2835_USB_VIRT_MPHI (VMALLOC_START + 0x10000)
-
- static void __init bcm2835_init(void)
- {
-@@ -83,20 +86,26 @@ static int __init bcm2835_map_usb(unsign
-
- static void __init bcm2835_map_io(void)
- {
-- const __be32 *ranges;
-+ const __be32 *ranges, *address_cells;
-+ unsigned long root, addr_cells;
- int soc, len;
- unsigned long p2b_offset;
-
- debug_ll_io_init();
-
-+ root = of_get_flat_dt_root();
- /* Find out how to map bus to physical address first from soc/ranges */
-- soc = of_get_flat_dt_subnode_by_name(of_get_flat_dt_root(), "soc");
-+ soc = of_get_flat_dt_subnode_by_name(root, "soc");
- if (soc < 0)
- return;
-+ address_cells = of_get_flat_dt_prop(root, "#address-cells", &len);
-+ if (!address_cells || len < (sizeof(unsigned long)))
-+ return;
-+ addr_cells = be32_to_cpu(address_cells[0]);
- ranges = of_get_flat_dt_prop(soc, "ranges", &len);
-- if (!ranges || len < (sizeof(unsigned long) * 3))
-+ if (!ranges || len < (sizeof(unsigned long) * (2 + addr_cells)))
- return;
-- p2b_offset = be32_to_cpu(ranges[0]) - be32_to_cpu(ranges[1]);
-+ p2b_offset = be32_to_cpu(ranges[0]) - be32_to_cpu(ranges[addr_cells]);
-
- /* Now search for bcm2708-usb node in device tree */
- of_scan_flat_dt(bcm2835_map_usb, &p2b_offset);
+++ /dev/null
-From 1f1c37d795048414202d1b097854ebb78df4b1fe Mon Sep 17 00:00:00 2001
-From: Tim Gover <tim.gover@raspberrypi.org>
-Date: Thu, 14 Mar 2019 10:16:02 +0000
-Subject: [PATCH 533/703] Fix copy_from_user if BCM2835_FAST_MEMCPY=n
-
-The change which introduced CONFIG_BCM2835_FAST_MEMCPY unconditionally
-changed the behaviour of arm_copy_from_user. The page pinning code
-is not safe on ARMv7 if LPAE & high memory is enabled and causes
-crashes which look like PTE corruption.
-
-Make __copy_from_user_memcpy conditional on CONFIG_2835_FAST_MEMCPY=y
-which is really an ARMv6 / Pi1 optimization and not necessary on newer
-ARM processors.
----
- arch/arm/lib/uaccess_with_memcpy.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/arch/arm/lib/uaccess_with_memcpy.c
-+++ b/arch/arm/lib/uaccess_with_memcpy.c
-@@ -257,6 +257,7 @@ arm_copy_to_user(void __user *to, const
- unsigned long __must_check
- arm_copy_from_user(void *to, const void __user *from, unsigned long n)
- {
-+#ifdef CONFIG_BCM2835_FAST_MEMCPY
- /*
- * This test is stubbed out of the main function above to keep
- * the overhead for small copies low by avoiding a large
-@@ -271,6 +272,11 @@ arm_copy_from_user(void *to, const void
- } else {
- n = __copy_from_user_memcpy(to, from, n);
- }
-+#else
-+ unsigned long ua_flags = uaccess_save_and_enable();
-+ n = __copy_from_user_std(to, from, n);
-+ uaccess_restore(ua_flags);
-+#endif
- return n;
- }
-
--- /dev/null
+From 830343693fac9c7aa58e6a14f636e75d2fb3b2e5 Mon Sep 17 00:00:00 2001
+From: Jim Quinlan <jim2101024@gmail.com>
+Date: Mon, 15 Jan 2018 18:28:39 -0500
+Subject: [PATCH 533/725] dt-bindings: pci: Add DT docs for Brcmstb PCIe device
+
+The DT bindings description of the Brcmstb PCIe device is described. This
+node can be used by almost all Broadcom settop box chips, using
+ARM, ARM64, or MIPS CPU architectures.
+
+Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
+---
+ .../devicetree/bindings/pci/brcmstb-pcie.txt | 59 +++++++++++++++++++
+ 1 file changed, 59 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pci/brcmstb-pcie.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pci/brcmstb-pcie.txt
+@@ -0,0 +1,59 @@
++Brcmstb PCIe Host Controller Device Tree Bindings
++
++Required Properties:
++- compatible
++ "brcm,bcm7425-pcie" -- for 7425 family MIPS-based SOCs.
++ "brcm,bcm7435-pcie" -- for 7435 family MIPS-based SOCs.
++ "brcm,bcm7445-pcie" -- for 7445 and later ARM based SOCs (not including
++ the 7278).
++ "brcm,bcm7278-pcie" -- for 7278 family ARM-based SOCs.
++
++- reg -- the register start address and length for the PCIe reg block.
++- interrupts -- two interrupts are specified; the first interrupt is for
++ the PCI host controller and the second is for MSI if the built-in
++ MSI controller is to be used.
++- interrupt-names -- names of the interrupts (above): "pcie" and "msi".
++- #address-cells -- set to <3>.
++- #size-cells -- set to <2>.
++- #interrupt-cells: set to <1>.
++- interrupt-map-mask and interrupt-map, standard PCI properties to define the
++ mapping of the PCIe interface to interrupt numbers.
++- ranges: ranges for the PCI memory and I/O regions.
++- linux,pci-domain -- should be unique per host controller.
++
++Optional Properties:
++- clocks -- phandle of pcie clock.
++- clock-names -- set to "sw_pcie" if clocks is used.
++- dma-ranges -- Specifies the inbound memory mapping regions when
++ an "identity map" is not possible.
++- msi-controller -- this property is typically specified to have the
++ PCIe controller use its internal MSI controller.
++- msi-parent -- set to use an external MSI interrupt controller.
++- brcm,enable-ssc -- (boolean) indicates usage of spread-spectrum clocking.
++- max-link-speed -- (integer) indicates desired generation of link:
++ 1 => 2.5 Gbps (gen1), 2 => 5.0 Gbps (gen2), 3 => 8.0 Gbps (gen3).
++
++Example Node:
++
++pcie0: pcie@f0460000 {
++ reg = <0x0 0xf0460000 0x0 0x9310>;
++ interrupts = <0x0 0x0 0x4>;
++ compatible = "brcm,bcm7445-pcie";
++ #address-cells = <3>;
++ #size-cells = <2>;
++ ranges = <0x02000000 0x00000000 0x00000000 0x00000000 0xc0000000 0x00000000 0x08000000
++ 0x02000000 0x00000000 0x08000000 0x00000000 0xc8000000 0x00000000 0x08000000>;
++ #interrupt-cells = <1>;
++ interrupt-map-mask = <0 0 0 7>;
++ interrupt-map = <0 0 0 1 &intc 0 47 3
++ 0 0 0 2 &intc 0 48 3
++ 0 0 0 3 &intc 0 49 3
++ 0 0 0 4 &intc 0 50 3>;
++ clocks = <&sw_pcie0>;
++ clock-names = "sw_pcie";
++ msi-parent = <&pcie0>; /* use PCIe's internal MSI controller */
++ msi-controller; /* use PCIe's internal MSI controller */
++ brcm,ssc;
++ max-link-speed = <1>;
++ linux,pci-domain = <0>;
++ };
+++ /dev/null
-From f44f216d79d668049e28f696840c7761017e3406 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 19 Feb 2019 22:06:59 +0000
-Subject: [PATCH 534/703] PCI: brcmstb: Add Broadcom STB PCIe host controller
- driver
-
-This commit adds the basic Broadcom STB PCIe controller. Missing is
-the ability to process MSI and also handle dma-ranges for inbound
-memory accesses. These two functionalities are added in subsequent
-commits.
-
-The PCIe block contains an MDIO interface. This is a local interface
-only accessible by the PCIe controller. It cannot be used or shared
-by any other HW. As such, the small amount of code for this
-controller is included in this driver as there is little upside to put
-it elsewhere.
-
-Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
----
- drivers/pci/controller/Kconfig | 9 +
- drivers/pci/controller/Makefile | 2 +-
- drivers/pci/controller/pcie-brcmstb.c | 1097 +++++++++++++++++++++++++
- include/soc/brcmstb/memory_api.h | 25 +
- 4 files changed, 1132 insertions(+), 1 deletion(-)
- create mode 100644 drivers/pci/controller/pcie-brcmstb.c
- create mode 100644 include/soc/brcmstb/memory_api.h
-
---- a/drivers/pci/controller/Kconfig
-+++ b/drivers/pci/controller/Kconfig
-@@ -278,5 +278,14 @@ config VMD
- To compile this driver as a module, choose M here: the
- module will be called vmd.
-
-+config PCIE_BRCMSTB
-+ tristate "Broadcom Brcmstb PCIe platform host driver"
-+ depends on ARCH_BRCMSTB || BMIPS_GENERIC
-+ depends on OF
-+ depends on SOC_BRCMSTB
-+ default ARCH_BRCMSTB || BMIPS_GENERIC
-+ help
-+ Adds support for Broadcom Settop Box PCIe host controller.
-+
- source "drivers/pci/controller/dwc/Kconfig"
- endmenu
---- a/drivers/pci/controller/Makefile
-+++ b/drivers/pci/controller/Makefile
-@@ -28,11 +28,11 @@ obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie
- obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
- obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
- obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
-+obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
- obj-$(CONFIG_VMD) += vmd.o
- # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
- obj-y += dwc/
-
--
- # The following drivers are for devices that use the generic ACPI
- # pci_root.c driver but don't support standard ECAM config access.
- # They contain MCFG quirks to replace the generic ECAM accessors with
---- /dev/null
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -0,0 +1,1097 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/* Copyright (C) 2009 - 2017 Broadcom */
-+
-+#include <linux/clk.h>
-+#include <linux/compiler.h>
-+#include <linux/delay.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/ioport.h>
-+#include <linux/irqdomain.h>
-+#include <linux/kernel.h>
-+#include <linux/list.h>
-+#include <linux/log2.h>
-+#include <linux/module.h>
-+#include <linux/of_address.h>
-+#include <linux/of_irq.h>
-+#include <linux/of_pci.h>
-+#include <linux/of_platform.h>
-+#include <linux/pci.h>
-+#include <linux/printk.h>
-+#include <linux/sizes.h>
-+#include <linux/slab.h>
-+#include <soc/brcmstb/memory_api.h>
-+#include <linux/string.h>
-+#include <linux/types.h>
-+#include "../pci.h"
-+
-+/* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
-+#define BRCM_PCIE_CAP_REGS 0x00ac
-+
-+/*
-+ * Broadcom Settop Box PCIe Register Offsets. The names are from
-+ * the chip's RDB and we use them here so that a script can correlate
-+ * this code and the RDB to prevent discrepancies.
-+ */
-+#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1 0x0188
-+#define PCIE_RC_CFG_PRIV1_ID_VAL3 0x043c
-+#define PCIE_RC_DL_MDIO_ADDR 0x1100
-+#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
-+#define PCIE_RC_DL_MDIO_RD_DATA 0x1108
-+#define PCIE_MISC_MISC_CTRL 0x4008
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO 0x400c
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI 0x4010
-+#define PCIE_MISC_RC_BAR1_CONFIG_LO 0x402c
-+#define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034
-+#define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038
-+#define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
-+#define PCIE_MISC_PCIE_CTRL 0x4064
-+#define PCIE_MISC_PCIE_STATUS 0x4068
-+#define PCIE_MISC_REVISION 0x406c
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT 0x4070
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI 0x4080
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI 0x4084
-+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204
-+#define PCIE_INTR2_CPU_BASE 0x4300
-+
-+/*
-+ * Broadcom Settop Box PCIe Register Field shift and mask info. The
-+ * names are from the chip's RDB and we use them here so that a script
-+ * can correlate this code and the RDB to prevent discrepancies.
-+ */
-+#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK 0xc
-+#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_SHIFT 0x2
-+#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff
-+#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_SHIFT 0x0
-+#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK 0x1000
-+#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_SHIFT 0xc
-+#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000
-+#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_SHIFT 0xd
-+#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000
-+#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_SHIFT 0x14
-+#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK 0xf8000000
-+#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_SHIFT 0x1b
-+#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_MASK 0x7c00000
-+#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_SHIFT 0x16
-+#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_MASK 0x1f
-+#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_SHIFT 0x0
-+#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK 0x1f
-+#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_SHIFT 0x0
-+#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK 0x1f
-+#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_SHIFT 0x0
-+#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f
-+#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_SHIFT 0x0
-+#define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK 0x4
-+#define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_SHIFT 0x2
-+#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK 0x1
-+#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_SHIFT 0x0
-+#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK 0x80
-+#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_SHIFT 0x7
-+#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_MASK 0x20
-+#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_SHIFT 0x5
-+#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK 0x10
-+#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_SHIFT 0x4
-+#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK 0x40
-+#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_SHIFT 0x6
-+#define PCIE_MISC_REVISION_MAJMIN_MASK 0xffff
-+#define PCIE_MISC_REVISION_MAJMIN_SHIFT 0
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK 0xfff00000
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_SHIFT 0x14
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK 0xfff0
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_SHIFT 0x4
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS 0xc
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_MASK 0xff
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_SHIFT 0x0
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK 0xff
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_SHIFT 0x0
-+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2
-+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_SHIFT 0x1
-+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
-+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_SHIFT 0x1b
-+#define PCIE_RGR1_SW_INIT_1_PERST_MASK 0x1
-+#define PCIE_RGR1_SW_INIT_1_PERST_SHIFT 0x0
-+
-+#define BRCM_NUM_PCIE_OUT_WINS 0x4
-+#define BRCM_MAX_SCB 0x4
-+
-+#define BRCM_MSI_TARGET_ADDR_LT_4GB 0x0fffffffcULL
-+#define BRCM_MSI_TARGET_ADDR_GT_4GB 0xffffffffcULL
-+
-+#define BURST_SIZE_128 0
-+#define BURST_SIZE_256 1
-+#define BURST_SIZE_512 2
-+
-+/* Offsets from PCIE_INTR2_CPU_BASE */
-+#define STATUS 0x0
-+#define SET 0x4
-+#define CLR 0x8
-+#define MASK_STATUS 0xc
-+#define MASK_SET 0x10
-+#define MASK_CLR 0x14
-+
-+#define PCIE_BUSNUM_SHIFT 20
-+#define PCIE_SLOT_SHIFT 15
-+#define PCIE_FUNC_SHIFT 12
-+
-+#if defined(__BIG_ENDIAN)
-+#define DATA_ENDIAN 2 /* PCIe->DDR inbound traffic */
-+#define MMIO_ENDIAN 2 /* CPU->PCIe outbound traffic */
-+#else
-+#define DATA_ENDIAN 0
-+#define MMIO_ENDIAN 0
-+#endif
-+
-+#define MDIO_PORT0 0x0
-+#define MDIO_DATA_MASK 0x7fffffff
-+#define MDIO_DATA_SHIFT 0x0
-+#define MDIO_PORT_MASK 0xf0000
-+#define MDIO_PORT_SHIFT 0x16
-+#define MDIO_REGAD_MASK 0xffff
-+#define MDIO_REGAD_SHIFT 0x0
-+#define MDIO_CMD_MASK 0xfff00000
-+#define MDIO_CMD_SHIFT 0x14
-+#define MDIO_CMD_READ 0x1
-+#define MDIO_CMD_WRITE 0x0
-+#define MDIO_DATA_DONE_MASK 0x80000000
-+#define MDIO_RD_DONE(x) (((x) & MDIO_DATA_DONE_MASK) ? 1 : 0)
-+#define MDIO_WT_DONE(x) (((x) & MDIO_DATA_DONE_MASK) ? 0 : 1)
-+#define SSC_REGS_ADDR 0x1100
-+#define SET_ADDR_OFFSET 0x1f
-+#define SSC_CNTL_OFFSET 0x2
-+#define SSC_CNTL_OVRD_EN_MASK 0x8000
-+#define SSC_CNTL_OVRD_EN_SHIFT 0xf
-+#define SSC_CNTL_OVRD_VAL_MASK 0x4000
-+#define SSC_CNTL_OVRD_VAL_SHIFT 0xe
-+#define SSC_STATUS_OFFSET 0x1
-+#define SSC_STATUS_SSC_MASK 0x400
-+#define SSC_STATUS_SSC_SHIFT 0xa
-+#define SSC_STATUS_PLL_LOCK_MASK 0x800
-+#define SSC_STATUS_PLL_LOCK_SHIFT 0xb
-+
-+#define IDX_ADDR(pcie) \
-+ ((pcie)->reg_offsets[EXT_CFG_INDEX])
-+#define DATA_ADDR(pcie) \
-+ ((pcie)->reg_offsets[EXT_CFG_DATA])
-+#define PCIE_RGR1_SW_INIT_1(pcie) \
-+ ((pcie)->reg_offsets[RGR1_SW_INIT_1])
-+
-+enum {
-+ RGR1_SW_INIT_1,
-+ EXT_CFG_INDEX,
-+ EXT_CFG_DATA,
-+};
-+
-+enum {
-+ RGR1_SW_INIT_1_INIT_MASK,
-+ RGR1_SW_INIT_1_INIT_SHIFT,
-+ RGR1_SW_INIT_1_PERST_MASK,
-+ RGR1_SW_INIT_1_PERST_SHIFT,
-+};
-+
-+enum pcie_type {
-+ BCM7425,
-+ BCM7435,
-+ GENERIC,
-+ BCM7278,
-+};
-+
-+struct brcm_window {
-+ dma_addr_t pcie_addr;
-+ phys_addr_t cpu_addr;
-+ dma_addr_t size;
-+};
-+
-+/* Internal PCIe Host Controller Information.*/
-+struct brcm_pcie {
-+ struct device *dev;
-+ void __iomem *base;
-+ struct list_head resources;
-+ int irq;
-+ struct clk *clk;
-+ struct pci_bus *root_bus;
-+ struct device_node *dn;
-+ int id;
-+ bool suspended;
-+ int num_out_wins;
-+ bool ssc;
-+ int gen;
-+ struct brcm_window out_wins[BRCM_NUM_PCIE_OUT_WINS];
-+ unsigned int rev;
-+ const int *reg_offsets;
-+ const int *reg_field_info;
-+ enum pcie_type type;
-+};
-+
-+struct pcie_cfg_data {
-+ const int *reg_field_info;
-+ const int *offsets;
-+ const enum pcie_type type;
-+};
-+
-+static const int pcie_reg_field_info[] = {
-+ [RGR1_SW_INIT_1_INIT_MASK] = 0x2,
-+ [RGR1_SW_INIT_1_INIT_SHIFT] = 0x1,
-+};
-+
-+static const int pcie_reg_field_info_bcm7278[] = {
-+ [RGR1_SW_INIT_1_INIT_MASK] = 0x1,
-+ [RGR1_SW_INIT_1_INIT_SHIFT] = 0x0,
-+};
-+
-+static const int pcie_offset_bcm7425[] = {
-+ [RGR1_SW_INIT_1] = 0x8010,
-+ [EXT_CFG_INDEX] = 0x8300,
-+ [EXT_CFG_DATA] = 0x8304,
-+};
-+
-+static const struct pcie_cfg_data bcm7425_cfg = {
-+ .reg_field_info = pcie_reg_field_info,
-+ .offsets = pcie_offset_bcm7425,
-+ .type = BCM7425,
-+};
-+
-+static const int pcie_offsets[] = {
-+ [RGR1_SW_INIT_1] = 0x9210,
-+ [EXT_CFG_INDEX] = 0x9000,
-+ [EXT_CFG_DATA] = 0x9004,
-+};
-+
-+static const struct pcie_cfg_data bcm7435_cfg = {
-+ .reg_field_info = pcie_reg_field_info,
-+ .offsets = pcie_offsets,
-+ .type = BCM7435,
-+};
-+
-+static const struct pcie_cfg_data generic_cfg = {
-+ .reg_field_info = pcie_reg_field_info,
-+ .offsets = pcie_offsets,
-+ .type = GENERIC,
-+};
-+
-+static const int pcie_offset_bcm7278[] = {
-+ [RGR1_SW_INIT_1] = 0xc010,
-+ [EXT_CFG_INDEX] = 0x9000,
-+ [EXT_CFG_DATA] = 0x9004,
-+};
-+
-+static const struct pcie_cfg_data bcm7278_cfg = {
-+ .reg_field_info = pcie_reg_field_info_bcm7278,
-+ .offsets = pcie_offset_bcm7278,
-+ .type = BCM7278,
-+};
-+
-+static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned int devfn,
-+ int where);
-+
-+static struct pci_ops brcm_pcie_ops = {
-+ .map_bus = brcm_pcie_map_conf,
-+ .read = pci_generic_config_read,
-+ .write = pci_generic_config_write,
-+};
-+
-+#if defined(CONFIG_MIPS)
-+/* Broadcom MIPs HW implicitly does the swapping if necessary */
-+#define bcm_readl(a) __raw_readl(a)
-+#define bcm_writel(d, a) __raw_writel(d, a)
-+#define bcm_readw(a) __raw_readw(a)
-+#define bcm_writew(d, a) __raw_writew(d, a)
-+#else
-+#define bcm_readl(a) readl(a)
-+#define bcm_writel(d, a) writel(d, a)
-+#define bcm_readw(a) readw(a)
-+#define bcm_writew(d, a) writew(d, a)
-+#endif
-+
-+/* These macros extract/insert fields to host controller's register set. */
-+#define RD_FLD(base, reg, field) \
-+ rd_fld(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT)
-+#define WR_FLD(base, reg, field, val) \
-+ wr_fld(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT, val)
-+#define WR_FLD_RB(base, reg, field, val) \
-+ wr_fld_rb(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT, val)
-+#define WR_FLD_WITH_OFFSET(base, off, reg, field, val) \
-+ wr_fld(base + reg + off, reg##_##field##_MASK, \
-+ reg##_##field##_SHIFT, val)
-+#define EXTRACT_FIELD(val, reg, field) \
-+ ((val & reg##_##field##_MASK) >> reg##_##field##_SHIFT)
-+#define INSERT_FIELD(val, reg, field, field_val) \
-+ ((val & ~reg##_##field##_MASK) | \
-+ (reg##_##field##_MASK & (field_val << reg##_##field##_SHIFT)))
-+
-+static phys_addr_t scb_size[BRCM_MAX_SCB];
-+static int num_memc;
-+static int num_pcie;
-+static DEFINE_MUTEX(brcm_pcie_lock);
-+
-+static u32 rd_fld(void __iomem *p, u32 mask, int shift)
-+{
-+ return (bcm_readl(p) & mask) >> shift;
-+}
-+
-+static void wr_fld(void __iomem *p, u32 mask, int shift, u32 val)
-+{
-+ u32 reg = bcm_readl(p);
-+
-+ reg = (reg & ~mask) | ((val << shift) & mask);
-+ bcm_writel(reg, p);
-+}
-+
-+static void wr_fld_rb(void __iomem *p, u32 mask, int shift, u32 val)
-+{
-+ wr_fld(p, mask, shift, val);
-+ (void)bcm_readl(p);
-+}
-+
-+static const char *link_speed_to_str(int s)
-+{
-+ switch (s) {
-+ case 1:
-+ return "2.5";
-+ case 2:
-+ return "5.0";
-+ case 3:
-+ return "8.0";
-+ default:
-+ break;
-+ }
-+ return "???";
-+}
-+
-+/*
-+ * The roundup_pow_of_two() from log2.h invokes
-+ * __roundup_pow_of_two(unsigned long), but we really need a
-+ * such a function to take a native u64 since unsigned long
-+ * is 32 bits on some configurations. So we provide this helper
-+ * function below.
-+ */
-+static u64 roundup_pow_of_two_64(u64 n)
-+{
-+ return 1ULL << fls64(n - 1);
-+}
-+
-+/*
-+ * This is to convert the size of the inbound "BAR" region to the
-+ * non-linear values of PCIE_X_MISC_RC_BAR[123]_CONFIG_LO.SIZE
-+ */
-+int encode_ibar_size(u64 size)
-+{
-+ int log2_in = ilog2(size);
-+
-+ if (log2_in >= 12 && log2_in <= 15)
-+ /* Covers 4KB to 32KB (inclusive) */
-+ return (log2_in - 12) + 0x1c;
-+ else if (log2_in >= 16 && log2_in <= 37)
-+ /* Covers 64KB to 32GB, (inclusive) */
-+ return log2_in - 15;
-+ /* Something is awry so disable */
-+ return 0;
-+}
-+
-+static u32 mdio_form_pkt(int port, int regad, int cmd)
-+{
-+ u32 pkt = 0;
-+
-+ pkt |= (port << MDIO_PORT_SHIFT) & MDIO_PORT_MASK;
-+ pkt |= (regad << MDIO_REGAD_SHIFT) & MDIO_REGAD_MASK;
-+ pkt |= (cmd << MDIO_CMD_SHIFT) & MDIO_CMD_MASK;
-+
-+ return pkt;
-+}
-+
-+/* negative return value indicates error */
-+static int mdio_read(void __iomem *base, u8 port, u8 regad)
-+{
-+ int tries;
-+ u32 data;
-+
-+ bcm_writel(mdio_form_pkt(port, regad, MDIO_CMD_READ),
-+ base + PCIE_RC_DL_MDIO_ADDR);
-+ bcm_readl(base + PCIE_RC_DL_MDIO_ADDR);
-+
-+ data = bcm_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
-+ for (tries = 0; !MDIO_RD_DONE(data) && tries < 10; tries++) {
-+ udelay(10);
-+ data = bcm_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
-+ }
-+
-+ return MDIO_RD_DONE(data)
-+ ? (data & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT
-+ : -EIO;
-+}
-+
-+/* negative return value indicates error */
-+static int mdio_write(void __iomem *base, u8 port, u8 regad, u16 wrdata)
-+{
-+ int tries;
-+ u32 data;
-+
-+ bcm_writel(mdio_form_pkt(port, regad, MDIO_CMD_WRITE),
-+ base + PCIE_RC_DL_MDIO_ADDR);
-+ bcm_readl(base + PCIE_RC_DL_MDIO_ADDR);
-+ bcm_writel(MDIO_DATA_DONE_MASK | wrdata,
-+ base + PCIE_RC_DL_MDIO_WR_DATA);
-+
-+ data = bcm_readl(base + PCIE_RC_DL_MDIO_WR_DATA);
-+ for (tries = 0; !MDIO_WT_DONE(data) && tries < 10; tries++) {
-+ udelay(10);
-+ data = bcm_readl(base + PCIE_RC_DL_MDIO_WR_DATA);
-+ }
-+
-+ return MDIO_WT_DONE(data) ? 0 : -EIO;
-+}
-+
-+/*
-+ * Configures device for Spread Spectrum Clocking (SSC) mode; a negative
-+ * return value indicates error.
-+ */
-+static int set_ssc(void __iomem *base)
-+{
-+ int tmp;
-+ u16 wrdata;
-+ int pll, ssc;
-+
-+ tmp = mdio_write(base, MDIO_PORT0, SET_ADDR_OFFSET, SSC_REGS_ADDR);
-+ if (tmp < 0)
-+ return tmp;
-+
-+ tmp = mdio_read(base, MDIO_PORT0, SSC_CNTL_OFFSET);
-+ if (tmp < 0)
-+ return tmp;
-+
-+ wrdata = INSERT_FIELD(tmp, SSC_CNTL_OVRD, EN, 1);
-+ wrdata = INSERT_FIELD(wrdata, SSC_CNTL_OVRD, VAL, 1);
-+ tmp = mdio_write(base, MDIO_PORT0, SSC_CNTL_OFFSET, wrdata);
-+ if (tmp < 0)
-+ return tmp;
-+
-+ usleep_range(1000, 2000);
-+ tmp = mdio_read(base, MDIO_PORT0, SSC_STATUS_OFFSET);
-+ if (tmp < 0)
-+ return tmp;
-+
-+ ssc = EXTRACT_FIELD(tmp, SSC_STATUS, SSC);
-+ pll = EXTRACT_FIELD(tmp, SSC_STATUS, PLL_LOCK);
-+
-+ return (ssc && pll) ? 0 : -EIO;
-+}
-+
-+/* Limits operation to a specific generation (1, 2, or 3) */
-+static void set_gen(void __iomem *base, int gen)
-+{
-+ u32 lnkcap = bcm_readl(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
-+ u16 lnkctl2 = bcm_readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
-+
-+ lnkcap = (lnkcap & ~PCI_EXP_LNKCAP_SLS) | gen;
-+ bcm_writel(lnkcap, base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
-+
-+ lnkctl2 = (lnkctl2 & ~0xf) | gen;
-+ bcm_writew(lnkctl2, base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
-+}
-+
-+static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie,
-+ unsigned int win, phys_addr_t cpu_addr,
-+ dma_addr_t pcie_addr, dma_addr_t size)
-+{
-+ void __iomem *base = pcie->base;
-+ phys_addr_t cpu_addr_mb, limit_addr_mb;
-+ u32 tmp;
-+
-+ /* Set the base of the pcie_addr window */
-+ bcm_writel(lower_32_bits(pcie_addr) + MMIO_ENDIAN,
-+ base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + (win * 8));
-+ bcm_writel(upper_32_bits(pcie_addr),
-+ base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + (win * 8));
-+
-+ cpu_addr_mb = cpu_addr >> 20;
-+ limit_addr_mb = (cpu_addr + size - 1) >> 20;
-+
-+ /* Write the addr base low register */
-+ WR_FLD_WITH_OFFSET(base, (win * 4),
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT,
-+ BASE, cpu_addr_mb);
-+ /* Write the addr limit low register */
-+ WR_FLD_WITH_OFFSET(base, (win * 4),
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT,
-+ LIMIT, limit_addr_mb);
-+
-+ if (pcie->type != BCM7435 && pcie->type != BCM7425) {
-+ /* Write the cpu addr high register */
-+ tmp = (u32)(cpu_addr_mb >>
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS);
-+ WR_FLD_WITH_OFFSET(base, (win * 8),
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI,
-+ BASE, tmp);
-+ /* Write the cpu limit high register */
-+ tmp = (u32)(limit_addr_mb >>
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS);
-+ WR_FLD_WITH_OFFSET(base, (win * 8),
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI,
-+ LIMIT, tmp);
-+ }
-+}
-+
-+/* Configuration space read/write support */
-+static int cfg_index(int busnr, int devfn, int reg)
-+{
-+ return ((PCI_SLOT(devfn) & 0x1f) << PCIE_SLOT_SHIFT)
-+ | ((PCI_FUNC(devfn) & 0x07) << PCIE_FUNC_SHIFT)
-+ | (busnr << PCIE_BUSNUM_SHIFT)
-+ | (reg & ~3);
-+}
-+
-+/* The controller is capable of serving in both RC and EP roles */
-+static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie)
-+{
-+ void __iomem *base = pcie->base;
-+ u32 val = bcm_readl(base + PCIE_MISC_PCIE_STATUS);
-+
-+ return !!EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, PCIE_PORT);
-+}
-+
-+static bool brcm_pcie_link_up(struct brcm_pcie *pcie)
-+{
-+ void __iomem *base = pcie->base;
-+ u32 val = bcm_readl(base + PCIE_MISC_PCIE_STATUS);
-+ u32 dla = EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, PCIE_DL_ACTIVE);
-+ u32 plu = EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, PCIE_PHYLINKUP);
-+
-+ return (dla && plu) ? true : false;
-+}
-+
-+static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned int devfn,
-+ int where)
-+{
-+ struct brcm_pcie *pcie = bus->sysdata;
-+ void __iomem *base = pcie->base;
-+ int idx;
-+
-+ /* Accesses to the RC go right to the RC registers if slot==0 */
-+ if (pci_is_root_bus(bus))
-+ return PCI_SLOT(devfn) ? NULL : base + where;
-+
-+ /* For devices, write to the config space index register */
-+ idx = cfg_index(bus->number, devfn, where);
-+ bcm_writel(idx, pcie->base + IDX_ADDR(pcie));
-+ return base + DATA_ADDR(pcie) + (where & 0x3);
-+}
-+
-+static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie,
-+ unsigned int val)
-+{
-+ unsigned int shift = pcie->reg_field_info[RGR1_SW_INIT_1_INIT_SHIFT];
-+ u32 mask = pcie->reg_field_info[RGR1_SW_INIT_1_INIT_MASK];
-+
-+ wr_fld_rb(pcie->base + PCIE_RGR1_SW_INIT_1(pcie), mask, shift, val);
-+}
-+
-+static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie,
-+ unsigned int val)
-+{
-+ if (pcie->type != BCM7278)
-+ wr_fld_rb(pcie->base + PCIE_RGR1_SW_INIT_1(pcie),
-+ PCIE_RGR1_SW_INIT_1_PERST_MASK,
-+ PCIE_RGR1_SW_INIT_1_PERST_SHIFT, val);
-+ else
-+ /* Assert = 0, de-assert = 1 on 7278 */
-+ WR_FLD_RB(pcie->base, PCIE_MISC_PCIE_CTRL, PCIE_PERSTB, !val);
-+}
-+
-+static int brcm_pcie_add_controller(struct brcm_pcie *pcie)
-+{
-+ int i, ret = 0;
-+
-+ mutex_lock(&brcm_pcie_lock);
-+ if (num_pcie > 0) {
-+ num_pcie++;
-+ goto done;
-+ }
-+
-+ /* Determine num_memc and their sizes */
-+ for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
-+ u64 size = brcmstb_memory_memc_size(i);
-+
-+ if (size == (u64)-1) {
-+ dev_err(pcie->dev, "cannot get memc%d size\n", i);
-+ ret = -EINVAL;
-+ goto done;
-+ } else if (size) {
-+ scb_size[i] = roundup_pow_of_two_64(size);
-+ num_memc++;
-+ } else {
-+ break;
-+ }
-+ }
-+ if (!ret && num_memc == 0) {
-+ ret = -EINVAL;
-+ goto done;
-+ }
-+
-+ num_pcie++;
-+done:
-+ mutex_unlock(&brcm_pcie_lock);
-+ return ret;
-+}
-+
-+static void brcm_pcie_remove_controller(struct brcm_pcie *pcie)
-+{
-+ mutex_lock(&brcm_pcie_lock);
-+ if (--num_pcie == 0)
-+ num_memc = 0;
-+ mutex_unlock(&brcm_pcie_lock);
-+}
-+
-+static int brcm_pcie_parse_request_of_pci_ranges(struct brcm_pcie *pcie)
-+{
-+ struct resource_entry *win;
-+ int ret;
-+
-+ ret = devm_of_pci_get_host_bridge_resources(pcie->dev, 0, 0xff,
-+ &pcie->resources, NULL);
-+ if (ret) {
-+ dev_err(pcie->dev, "failed to get host resources\n");
-+ return ret;
-+ }
-+
-+ resource_list_for_each_entry(win, &pcie->resources) {
-+ struct resource *parent, *res = win->res;
-+ dma_addr_t offset = (dma_addr_t)win->offset;
-+
-+ if (resource_type(res) == IORESOURCE_IO) {
-+ parent = &ioport_resource;
-+ } else if (resource_type(res) == IORESOURCE_MEM) {
-+ if (pcie->num_out_wins >= BRCM_NUM_PCIE_OUT_WINS) {
-+ dev_err(pcie->dev, "too many outbound wins\n");
-+ return -EINVAL;
-+ }
-+ pcie->out_wins[pcie->num_out_wins].cpu_addr
-+ = (phys_addr_t)res->start;
-+ pcie->out_wins[pcie->num_out_wins].pcie_addr
-+ = (dma_addr_t)(res->start
-+ - (phys_addr_t)offset);
-+ pcie->out_wins[pcie->num_out_wins].size
-+ = (dma_addr_t)(res->end - res->start + 1);
-+ pcie->num_out_wins++;
-+ parent = &iomem_resource;
-+ } else {
-+ continue;
-+ }
-+
-+ ret = devm_request_resource(pcie->dev, parent, res);
-+ if (ret) {
-+ dev_err(pcie->dev, "failed to get res %pR\n", res);
-+ return ret;
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int brcm_pcie_setup(struct brcm_pcie *pcie)
-+{
-+ void __iomem *base = pcie->base;
-+ unsigned int scb_size_val;
-+ u64 rc_bar2_offset, rc_bar2_size, total_mem_size = 0;
-+ u32 tmp, burst;
-+ int i, j, ret, limit;
-+ u16 nlw, cls, lnksta;
-+ bool ssc_good = false;
-+ struct device *dev = pcie->dev;
-+
-+ /* Reset the bridge */
-+ brcm_pcie_bridge_sw_init_set(pcie, 1);
-+
-+ /*
-+ * Ensure that the fundamental reset is asserted, except for 7278,
-+ * which fails if we do this.
-+ */
-+ if (pcie->type != BCM7278)
-+ brcm_pcie_perst_set(pcie, 1);
-+
-+ usleep_range(100, 200);
-+
-+ /* Take the bridge out of reset */
-+ brcm_pcie_bridge_sw_init_set(pcie, 0);
-+
-+ WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 0);
-+ /* Wait for SerDes to be stable */
-+ usleep_range(100, 200);
-+
-+ /* Grab the PCIe hw revision number */
-+ tmp = bcm_readl(base + PCIE_MISC_REVISION);
-+ pcie->rev = EXTRACT_FIELD(tmp, PCIE_MISC_REVISION, MAJMIN);
-+
-+ /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
-+ tmp = INSERT_FIELD(0, PCIE_MISC_MISC_CTRL, SCB_ACCESS_EN, 1);
-+ tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, CFG_READ_UR_MODE, 1);
-+ burst = (pcie->type == GENERIC || pcie->type == BCM7278)
-+ ? BURST_SIZE_512 : BURST_SIZE_256;
-+ tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE, burst);
-+ bcm_writel(tmp, base + PCIE_MISC_MISC_CTRL);
-+
-+ /*
-+ * Set up inbound memory view for the EP (called RC_BAR2,
-+ * not to be confused with the BARs that are advertised by
-+ * the EP).
-+ */
-+ for (i = 0; i < num_memc; i++)
-+ total_mem_size += scb_size[i];
-+
-+ /*
-+ * The PCIe host controller by design must set the inbound
-+ * viewport to be a contiguous arrangement of all of the
-+ * system's memory. In addition, its size mut be a power of
-+ * two. To further complicate matters, the viewport must
-+ * start on a pcie-address that is aligned on a multiple of its
-+ * size. If a portion of the viewport does not represent
-+ * system memory -- e.g. 3GB of memory requires a 4GB viewport
-+ * -- we can map the outbound memory in or after 3GB and even
-+ * though the viewport will overlap the outbound memory the
-+ * controller will know to send outbound memory downstream and
-+ * everything else upstream.
-+ */
-+ rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
-+
-+ /*
-+ * Set simple configuration based on memory sizes
-+ * only. We always start the viewport at address 0.
-+ */
-+ rc_bar2_offset = 0;
-+
-+ tmp = lower_32_bits(rc_bar2_offset);
-+ tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
-+ encode_ibar_size(rc_bar2_size));
-+ bcm_writel(tmp, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
-+ bcm_writel(upper_32_bits(rc_bar2_offset),
-+ base + PCIE_MISC_RC_BAR2_CONFIG_HI);
-+
-+ scb_size_val = scb_size[0]
-+ ? ilog2(scb_size[0]) - 15 : 0xf; /* 0xf is 1GB */
-+ WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB0_SIZE, scb_size_val);
-+
-+ if (num_memc > 1) {
-+ scb_size_val = scb_size[1]
-+ ? ilog2(scb_size[1]) - 15 : 0xf; /* 0xf is 1GB */
-+ WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB1_SIZE, scb_size_val);
-+ }
-+
-+ if (num_memc > 2) {
-+ scb_size_val = scb_size[2]
-+ ? ilog2(scb_size[2]) - 15 : 0xf; /* 0xf is 1GB */
-+ WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB2_SIZE, scb_size_val);
-+ }
-+
-+ /* disable the PCIe->GISB memory window (RC_BAR1) */
-+ WR_FLD(base, PCIE_MISC_RC_BAR1_CONFIG_LO, SIZE, 0);
-+
-+ /* disable the PCIe->SCB memory window (RC_BAR3) */
-+ WR_FLD(base, PCIE_MISC_RC_BAR3_CONFIG_LO, SIZE, 0);
-+
-+ if (!pcie->suspended) {
-+ /* clear any interrupts we find on boot */
-+ bcm_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + CLR);
-+ (void)bcm_readl(base + PCIE_INTR2_CPU_BASE + CLR);
-+ }
-+
-+ /* Mask all interrupts since we are not handling any yet */
-+ bcm_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + MASK_SET);
-+ (void)bcm_readl(base + PCIE_INTR2_CPU_BASE + MASK_SET);
-+
-+ if (pcie->gen)
-+ set_gen(base, pcie->gen);
-+
-+ /* Unassert the fundamental reset */
-+ brcm_pcie_perst_set(pcie, 0);
-+
-+ /*
-+ * Give the RC/EP time to wake up, before trying to configure RC.
-+ * Intermittently check status for link-up, up to a total of 100ms
-+ * when we don't know if the device is there, and up to 1000ms if
-+ * we do know the device is there.
-+ */
-+ limit = pcie->suspended ? 1000 : 100;
-+ for (i = 1, j = 0; j < limit && !brcm_pcie_link_up(pcie);
-+ j += i, i = i * 2)
-+ msleep(i + j > limit ? limit - j : i);
-+
-+ if (!brcm_pcie_link_up(pcie)) {
-+ dev_info(dev, "link down\n");
-+ return -ENODEV;
-+ }
-+
-+ if (!brcm_pcie_rc_mode(pcie)) {
-+ dev_err(dev, "PCIe misconfigured; is in EP mode\n");
-+ return -EINVAL;
-+ }
-+
-+ for (i = 0; i < pcie->num_out_wins; i++)
-+ brcm_pcie_set_outbound_win(pcie, i, pcie->out_wins[i].cpu_addr,
-+ pcie->out_wins[i].pcie_addr,
-+ pcie->out_wins[i].size);
-+
-+ /*
-+ * For config space accesses on the RC, show the right class for
-+ * a PCIe-PCIe bridge (the default setting is to be EP mode).
-+ */
-+ WR_FLD_RB(base, PCIE_RC_CFG_PRIV1_ID_VAL3, CLASS_CODE, 0x060400);
-+
-+ if (pcie->ssc) {
-+ ret = set_ssc(base);
-+ if (ret == 0)
-+ ssc_good = true;
-+ else
-+ dev_err(dev, "failed attempt to enter ssc mode\n");
-+ }
-+
-+ lnksta = bcm_readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKSTA);
-+ cls = lnksta & PCI_EXP_LNKSTA_CLS;
-+ nlw = (lnksta & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
-+ dev_info(dev, "link up, %s Gbps x%u %s\n", link_speed_to_str(cls),
-+ nlw, ssc_good ? "(SSC)" : "(!SSC)");
-+
-+ /* PCIe->SCB endian mode for BAR */
-+ /* field ENDIAN_MODE_BAR2 = DATA_ENDIAN */
-+ WR_FLD_RB(base, PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1,
-+ ENDIAN_MODE_BAR2, DATA_ENDIAN);
-+
-+ /*
-+ * Refclk from RC should be gated with CLKREQ# input when ASPM L0s,L1
-+ * is enabled => setting the CLKREQ_DEBUG_ENABLE field to 1.
-+ */
-+ WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, CLKREQ_DEBUG_ENABLE, 1);
-+
-+ return 0;
-+}
-+
-+/* L23 is a low-power PCIe link state */
-+static void enter_l23(struct brcm_pcie *pcie)
-+{
-+ void __iomem *base = pcie->base;
-+ int tries, l23;
-+
-+ /* assert request for L23 */
-+ WR_FLD_RB(base, PCIE_MISC_PCIE_CTRL, PCIE_L23_REQUEST, 1);
-+ /* poll L23 status */
-+ for (tries = 0, l23 = 0; tries < 1000 && !l23; tries++)
-+ l23 = RD_FLD(base, PCIE_MISC_PCIE_STATUS, PCIE_LINK_IN_L23);
-+ if (!l23)
-+ dev_err(pcie->dev, "failed to enter L23\n");
-+}
-+
-+static void turn_off(struct brcm_pcie *pcie)
-+{
-+ void __iomem *base = pcie->base;
-+
-+ if (brcm_pcie_link_up(pcie))
-+ enter_l23(pcie);
-+ /* Assert fundamental reset */
-+ brcm_pcie_perst_set(pcie, 1);
-+ /* Deassert request for L23 in case it was asserted */
-+ WR_FLD_RB(base, PCIE_MISC_PCIE_CTRL, PCIE_L23_REQUEST, 0);
-+ /* Turn off SerDes */
-+ WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 1);
-+ /* Shutdown PCIe bridge */
-+ brcm_pcie_bridge_sw_init_set(pcie, 1);
-+}
-+
-+static int brcm_pcie_suspend(struct device *dev)
-+{
-+ struct brcm_pcie *pcie = dev_get_drvdata(dev);
-+
-+ turn_off(pcie);
-+ clk_disable_unprepare(pcie->clk);
-+ pcie->suspended = true;
-+
-+ return 0;
-+}
-+
-+static int brcm_pcie_resume(struct device *dev)
-+{
-+ struct brcm_pcie *pcie = dev_get_drvdata(dev);
-+ void __iomem *base;
-+ int ret;
-+
-+ base = pcie->base;
-+ clk_prepare_enable(pcie->clk);
-+
-+ /* Take bridge out of reset so we can access the SerDes reg */
-+ brcm_pcie_bridge_sw_init_set(pcie, 0);
-+
-+ /* Turn on SerDes */
-+ WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 0);
-+ /* Wait for SerDes to be stable */
-+ usleep_range(100, 200);
-+
-+ ret = brcm_pcie_setup(pcie);
-+ if (ret)
-+ return ret;
-+
-+ pcie->suspended = false;
-+
-+ return 0;
-+}
-+
-+static void _brcm_pcie_remove(struct brcm_pcie *pcie)
-+{
-+ turn_off(pcie);
-+ clk_disable_unprepare(pcie->clk);
-+ clk_put(pcie->clk);
-+ brcm_pcie_remove_controller(pcie);
-+}
-+
-+static int brcm_pcie_remove(struct platform_device *pdev)
-+{
-+ struct brcm_pcie *pcie = platform_get_drvdata(pdev);
-+
-+ pci_stop_root_bus(pcie->root_bus);
-+ pci_remove_root_bus(pcie->root_bus);
-+ _brcm_pcie_remove(pcie);
-+
-+ return 0;
-+}
-+
-+static const struct of_device_id brcm_pcie_match[] = {
-+ { .compatible = "brcm,bcm7425-pcie", .data = &bcm7425_cfg },
-+ { .compatible = "brcm,bcm7435-pcie", .data = &bcm7435_cfg },
-+ { .compatible = "brcm,bcm7278-pcie", .data = &bcm7278_cfg },
-+ { .compatible = "brcm,bcm7445-pcie", .data = &generic_cfg },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, brcm_pcie_match);
-+
-+static int brcm_pcie_probe(struct platform_device *pdev)
-+{
-+ struct device_node *dn = pdev->dev.of_node;
-+ const struct of_device_id *of_id;
-+ const struct pcie_cfg_data *data;
-+ int ret;
-+ struct brcm_pcie *pcie;
-+ struct resource *res;
-+ void __iomem *base;
-+ u32 tmp;
-+ struct pci_host_bridge *bridge;
-+ struct pci_bus *child;
-+
-+ bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie));
-+ if (!bridge)
-+ return -ENOMEM;
-+
-+ pcie = pci_host_bridge_priv(bridge);
-+ INIT_LIST_HEAD(&pcie->resources);
-+
-+ of_id = of_match_node(brcm_pcie_match, dn);
-+ if (!of_id) {
-+ dev_err(&pdev->dev, "failed to look up compatible string\n");
-+ return -EINVAL;
-+ }
-+
-+ if (of_property_read_u32(dn, "dma-ranges", &tmp) == 0) {
-+ dev_err(&pdev->dev, "cannot yet handle dma-ranges\n");
-+ return -EINVAL;
-+ }
-+
-+ data = of_id->data;
-+ pcie->reg_offsets = data->offsets;
-+ pcie->reg_field_info = data->reg_field_info;
-+ pcie->type = data->type;
-+ pcie->dn = dn;
-+ pcie->dev = &pdev->dev;
-+
-+ /* We use the domain number as our controller number */
-+ pcie->id = of_get_pci_domain_nr(dn);
-+ if (pcie->id < 0)
-+ return pcie->id;
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!res)
-+ return -EINVAL;
-+
-+ base = devm_ioremap_resource(&pdev->dev, res);
-+ if (IS_ERR(base))
-+ return PTR_ERR(base);
-+
-+ pcie->clk = of_clk_get_by_name(dn, "sw_pcie");
-+ if (IS_ERR(pcie->clk)) {
-+ dev_err(&pdev->dev, "could not get clock\n");
-+ pcie->clk = NULL;
-+ }
-+ pcie->base = base;
-+
-+ ret = of_pci_get_max_link_speed(dn);
-+ pcie->gen = (ret < 0) ? 0 : ret;
-+
-+ pcie->ssc = of_property_read_bool(dn, "brcm,enable-ssc");
-+
-+ ret = irq_of_parse_and_map(pdev->dev.of_node, 0);
-+ if (ret == 0)
-+ /* keep going, as we don't use this intr yet */
-+ dev_warn(pcie->dev, "cannot get PCIe interrupt\n");
-+ else
-+ pcie->irq = ret;
-+
-+ ret = brcm_pcie_parse_request_of_pci_ranges(pcie);
-+ if (ret)
-+ return ret;
-+
-+ ret = clk_prepare_enable(pcie->clk);
-+ if (ret) {
-+ dev_err(&pdev->dev, "could not enable clock\n");
-+ return ret;
-+ }
-+
-+ ret = brcm_pcie_add_controller(pcie);
-+ if (ret)
-+ return ret;
-+
-+ ret = brcm_pcie_setup(pcie);
-+ if (ret)
-+ goto fail;
-+
-+ list_splice_init(&pcie->resources, &bridge->windows);
-+ bridge->dev.parent = &pdev->dev;
-+ bridge->busnr = 0;
-+ bridge->ops = &brcm_pcie_ops;
-+ bridge->sysdata = pcie;
-+ bridge->map_irq = of_irq_parse_and_map_pci;
-+ bridge->swizzle_irq = pci_common_swizzle;
-+
-+ ret = pci_scan_root_bus_bridge(bridge);
-+ if (ret < 0) {
-+ dev_err(pcie->dev, "Scanning root bridge failed\n");
-+ goto fail;
-+ }
-+
-+ pci_assign_unassigned_bus_resources(bridge->bus);
-+ list_for_each_entry(child, &bridge->bus->children, node)
-+ pcie_bus_configure_settings(child);
-+ pci_bus_add_devices(bridge->bus);
-+ platform_set_drvdata(pdev, pcie);
-+ pcie->root_bus = bridge->bus;
-+
-+ return 0;
-+
-+fail:
-+ _brcm_pcie_remove(pcie);
-+ return ret;
-+}
-+
-+static const struct dev_pm_ops brcm_pcie_pm_ops = {
-+ .suspend_noirq = brcm_pcie_suspend,
-+ .resume_noirq = brcm_pcie_resume,
-+};
-+
-+static struct platform_driver brcm_pcie_driver = {
-+ .probe = brcm_pcie_probe,
-+ .remove = brcm_pcie_remove,
-+ .driver = {
-+ .name = "brcm-pcie",
-+ .owner = THIS_MODULE,
-+ .of_match_table = brcm_pcie_match,
-+ .pm = &brcm_pcie_pm_ops,
-+ },
-+};
-+
-+module_platform_driver(brcm_pcie_driver);
-+
-+MODULE_LICENSE("GPL v2");
-+MODULE_DESCRIPTION("Broadcom STB PCIe RC driver");
-+MODULE_AUTHOR("Broadcom");
---- /dev/null
-+++ b/include/soc/brcmstb/memory_api.h
-@@ -0,0 +1,25 @@
-+#ifndef __MEMORY_API_H
-+#define __MEMORY_API_H
-+
-+/*
-+ * Bus Interface Unit control register setup, must happen early during boot,
-+ * before SMP is brought up, called by machine entry point.
-+ */
-+void brcmstb_biuctrl_init(void);
-+
-+#ifdef CONFIG_SOC_BRCMSTB
-+int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa);
-+u64 brcmstb_memory_memc_size(int memc);
-+#else
-+static inline int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa)
-+{
-+ return -EINVAL;
-+}
-+
-+static inline u64 brcmstb_memory_memc_size(int memc)
-+{
-+ return -1;
-+}
-+#endif
-+
-+#endif /* __MEMORY_API_H */
--- /dev/null
+From cbe53bb0428c1ae30fb7395fc8d8f507a6afbded Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 19 Feb 2019 22:06:59 +0000
+Subject: [PATCH 534/725] pcie-brcmstb: Changes for BCM2711
+
+The initial brcmstb PCIe driver - originally taken from the V3(?)
+patch set - has been modified significantly for the BCM2711.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/dma/bcm2835-dma.c | 107 ++++
+ drivers/pci/controller/Makefile | 4 +
+ drivers/pci/controller/pcie-brcmstb-bounce.c | 564 +++++++++++++++++++
+ drivers/pci/controller/pcie-brcmstb-bounce.h | 32 ++
+ drivers/pci/controller/pcie-brcmstb.c | 237 ++++----
+ drivers/soc/bcm/brcmstb/Makefile | 2 +-
+ drivers/soc/bcm/brcmstb/memory.c | 158 ++++++
+ 7 files changed, 996 insertions(+), 108 deletions(-)
+ create mode 100644 drivers/pci/controller/pcie-brcmstb-bounce.c
+ create mode 100644 drivers/pci/controller/pcie-brcmstb-bounce.h
+ create mode 100644 drivers/soc/bcm/brcmstb/memory.c
+
+--- a/drivers/dma/bcm2835-dma.c
++++ b/drivers/dma/bcm2835-dma.c
+@@ -68,6 +68,17 @@ struct bcm2835_dma_cb {
+ uint32_t pad[2];
+ };
+
++struct bcm2838_dma40_scb {
++ uint32_t ti;
++ uint32_t src;
++ uint32_t srci;
++ uint32_t dst;
++ uint32_t dsti;
++ uint32_t len;
++ uint32_t next_cb;
++ uint32_t rsvd;
++};
++
+ struct bcm2835_cb_entry {
+ struct bcm2835_dma_cb *cb;
+ dma_addr_t paddr;
+@@ -185,6 +196,45 @@ struct bcm2835_desc {
+ #define MAX_DMA_LEN SZ_1G
+ #define MAX_LITE_DMA_LEN (SZ_64K - 4)
+
++/* 40-bit DMA support */
++#define BCM2838_DMA40_CS 0x00
++#define BCM2838_DMA40_CB 0x04
++#define BCM2838_DMA40_DEBUG 0x0c
++#define BCM2858_DMA40_TI 0x10
++#define BCM2838_DMA40_SRC 0x14
++#define BCM2838_DMA40_SRCI 0x18
++#define BCM2838_DMA40_DEST 0x1c
++#define BCM2838_DMA40_DESTI 0x20
++#define BCM2838_DMA40_LEN 0x24
++#define BCM2838_DMA40_NEXT_CB 0x28
++#define BCM2838_DMA40_DEBUG2 0x2c
++
++#define BCM2838_DMA40_CS_ACTIVE BIT(0)
++#define BCM2838_DMA40_CS_END BIT(1)
++
++#define BCM2838_DMA40_CS_QOS(x) (((x) & 0x1f) << 16)
++#define BCM2838_DMA40_CS_PANIC_QOS(x) (((x) & 0x1f) << 20)
++#define BCM2838_DMA40_CS_WRITE_WAIT BIT(28)
++
++#define BCM2838_DMA40_BURST_LEN(x) ((((x) - 1) & 0xf) << 8)
++#define BCM2838_DMA40_INC BIT(12)
++#define BCM2838_DMA40_SIZE_128 (2 << 13)
++
++#define BCM2838_DMA40_MEMCPY_QOS \
++ (BCM2838_DMA40_CS_QOS(0x0) | \
++ BCM2838_DMA40_CS_PANIC_QOS(0x0) | \
++ BCM2838_DMA40_CS_WRITE_WAIT)
++
++#define BCM2838_DMA40_MEMCPY_XFER_INFO \
++ (BCM2838_DMA40_SIZE_128 | \
++ BCM2838_DMA40_INC | \
++ BCM2838_DMA40_BURST_LEN(16))
++
++static void __iomem *memcpy_chan;
++static struct bcm2838_dma40_scb *memcpy_scb;
++static dma_addr_t memcpy_scb_dma;
++DEFINE_SPINLOCK(memcpy_lock);
++
+ static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c)
+ {
+ /* lite and normal channels have different max frame length */
+@@ -868,6 +918,56 @@ static void bcm2835_dma_free(struct bcm2
+ }
+ }
+
++int bcm2838_dma40_memcpy_init(struct device *dev)
++{
++ if (memcpy_scb)
++ return 0;
++
++ memcpy_scb = dma_alloc_coherent(dev, sizeof(*memcpy_scb),
++ &memcpy_scb_dma, GFP_KERNEL);
++
++ if (!memcpy_scb) {
++ pr_err("bcm2838_dma40_memcpy_init failed!\n");
++ return -ENOMEM;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(bcm2838_dma40_memcpy_init);
++
++void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size)
++{
++ struct bcm2838_dma40_scb *scb = memcpy_scb;
++ unsigned long flags;
++
++ if (!scb) {
++ pr_err("bcm2838_dma40_memcpy not initialised!\n");
++ return;
++ }
++
++ spin_lock_irqsave(&memcpy_lock, flags);
++
++ scb->ti = 0;
++ scb->src = lower_32_bits(src);
++ scb->srci = upper_32_bits(src) | BCM2838_DMA40_MEMCPY_XFER_INFO;
++ scb->dst = lower_32_bits(dst);
++ scb->dsti = upper_32_bits(dst) | BCM2838_DMA40_MEMCPY_XFER_INFO;
++ scb->len = size;
++ scb->next_cb = 0;
++
++ writel((u32)(memcpy_scb_dma >> 5), memcpy_chan + BCM2838_DMA40_CB);
++ writel(BCM2838_DMA40_MEMCPY_QOS + BCM2838_DMA40_CS_ACTIVE,
++ memcpy_chan + BCM2838_DMA40_CS);
++ /* Poll for completion */
++ while (!(readl(memcpy_chan + BCM2838_DMA40_CS) & BCM2838_DMA40_CS_END))
++ cpu_relax();
++
++ writel(BCM2838_DMA40_CS_END, memcpy_chan + BCM2838_DMA40_CS);
++
++ spin_unlock_irqrestore(&memcpy_lock, flags);
++}
++EXPORT_SYMBOL(bcm2838_dma40_memcpy);
++
+ static const struct of_device_id bcm2835_dma_of_match[] = {
+ { .compatible = "brcm,bcm2835-dma", },
+ {},
+@@ -964,6 +1064,13 @@ static int bcm2835_dma_probe(struct plat
+ /* Channel 0 is used by the legacy API */
+ chans_available &= ~BCM2835_DMA_BULK_MASK;
+
++ /* We can't use channels 11-13 yet */
++ chans_available &= ~(BIT(11) | BIT(12) | BIT(13));
++
++ /* Grab channel 14 for the 40-bit DMA memcpy */
++ chans_available &= ~BIT(14);
++ memcpy_chan = BCM2835_DMA_CHANIO(base, 14);
++
+ /* get irqs for each channel that we support */
+ for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
+ /* skip masked out channels */
+--- a/drivers/pci/controller/Makefile
++++ b/drivers/pci/controller/Makefile
+@@ -29,6 +29,10 @@ obj-$(CONFIG_PCIE_MEDIATEK) += pcie-medi
+ obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
+ obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
+ obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
++ifdef CONFIG_ARM
++obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb-bounce.o
++endif
++
+ obj-$(CONFIG_VMD) += vmd.o
+ # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
+ obj-y += dwc/
+--- /dev/null
++++ b/drivers/pci/controller/pcie-brcmstb-bounce.c
+@@ -0,0 +1,564 @@
++/*
++ * This code started out as a version of arch/arm/common/dmabounce.c,
++ * modified to cope with highmem pages. Now it has been changed heavily -
++ * it now preallocates a large block (currently 4MB) and carves it up
++ * sequentially in ring fashion, and DMA is used to copy the data - to the
++ * point where very little of the original remains.
++ *
++ * Copyright (C) 2019 Raspberry Pi (Trading) Ltd.
++ *
++ * Original version by Brad Parker (brad@heeltoe.com)
++ * Re-written by Christopher Hoover <ch@murgatroid.com>
++ * Made generic by Deepak Saxena <dsaxena@plexity.net>
++ *
++ * Copyright (C) 2002 Hewlett Packard Company.
++ * Copyright (C) 2004 MontaVista Software, 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 <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/page-flags.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/dmapool.h>
++#include <linux/list.h>
++#include <linux/scatterlist.h>
++#include <linux/bitmap.h>
++
++#include <asm/cacheflush.h>
++#include <asm/dma-iommu.h>
++
++#define STATS
++
++#ifdef STATS
++#define DO_STATS(X) do { X ; } while (0)
++#else
++#define DO_STATS(X) do { } while (0)
++#endif
++
++/* ************************************************** */
++
++struct safe_buffer {
++ struct list_head node;
++
++ /* original request */
++ size_t size;
++ int direction;
++
++ struct dmabounce_pool *pool;
++ void *safe;
++ dma_addr_t unsafe_dma_addr;
++ dma_addr_t safe_dma_addr;
++};
++
++struct dmabounce_pool {
++ unsigned long pages;
++ void *virt_addr;
++ dma_addr_t dma_addr;
++ unsigned long *alloc_map;
++ unsigned long alloc_pos;
++ spinlock_t lock;
++ struct device *dev;
++ unsigned long num_pages;
++#ifdef STATS
++ size_t max_size;
++ unsigned long num_bufs;
++ unsigned long max_bufs;
++ unsigned long max_pages;
++#endif
++};
++
++struct dmabounce_device_info {
++ struct device *dev;
++ dma_addr_t threshold;
++ struct list_head safe_buffers;
++ struct dmabounce_pool pool;
++ rwlock_t lock;
++#ifdef STATS
++ unsigned long map_count;
++ unsigned long unmap_count;
++ unsigned long sync_dev_count;
++ unsigned long sync_cpu_count;
++ unsigned long fail_count;
++ int attr_res;
++#endif
++};
++
++static struct dmabounce_device_info *g_dmabounce_device_info;
++
++extern int bcm2838_dma40_memcpy_init(struct device *dev);
++extern void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size);
++
++#ifdef STATS
++static ssize_t
++bounce_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct dmabounce_device_info *device_info = g_dmabounce_device_info;
++ return sprintf(buf, "m:%lu/%lu s:%lu/%lu f:%lu s:%zu b:%lu/%lu a:%lu/%lu\n",
++ device_info->map_count,
++ device_info->unmap_count,
++ device_info->sync_dev_count,
++ device_info->sync_cpu_count,
++ device_info->fail_count,
++ device_info->pool.max_size,
++ device_info->pool.num_bufs,
++ device_info->pool.max_bufs,
++ device_info->pool.num_pages * PAGE_SIZE,
++ device_info->pool.max_pages * PAGE_SIZE);
++}
++
++static DEVICE_ATTR(dmabounce_stats, 0444, bounce_show, NULL);
++#endif
++
++static int bounce_create(struct dmabounce_pool *pool, struct device *dev,
++ unsigned long buffer_size)
++{
++ int ret = -ENOMEM;
++ pool->pages = (buffer_size + PAGE_SIZE - 1)/PAGE_SIZE;
++ pool->alloc_map = bitmap_zalloc(pool->pages, GFP_KERNEL);
++ if (!pool->alloc_map)
++ goto err_bitmap;
++ pool->virt_addr = dma_alloc_coherent(dev, pool->pages * PAGE_SIZE,
++ &pool->dma_addr, GFP_KERNEL);
++ if (!pool->virt_addr)
++ goto err_dmabuf;
++
++ pool->alloc_pos = 0;
++ spin_lock_init(&pool->lock);
++ pool->dev = dev;
++ pool->num_pages = 0;
++
++ DO_STATS(pool->max_size = 0);
++ DO_STATS(pool->num_bufs = 0);
++ DO_STATS(pool->max_bufs = 0);
++ DO_STATS(pool->max_pages = 0);
++
++ return 0;
++
++err_dmabuf:
++ bitmap_free(pool->alloc_map);
++err_bitmap:
++ return ret;
++}
++
++static void bounce_destroy(struct dmabounce_pool *pool)
++{
++ dma_free_coherent(pool->dev, pool->pages * PAGE_SIZE, pool->virt_addr,
++ pool->dma_addr);
++
++ bitmap_free(pool->alloc_map);
++}
++
++static void *bounce_alloc(struct dmabounce_pool *pool, size_t size,
++ dma_addr_t *dmaaddrp)
++{
++ unsigned long pages;
++ unsigned long flags;
++ unsigned long pos;
++
++ pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
++
++ DO_STATS(pool->max_size = max(size, pool->max_size));
++
++ spin_lock_irqsave(&pool->lock, flags);
++ pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
++ pool->alloc_pos, pages, 0);
++ /* If not found, try from the start */
++ if (pos >= pool->pages && pool->alloc_pos)
++ pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
++ 0, pages, 0);
++
++ if (pos >= pool->pages) {
++ spin_unlock_irqrestore(&pool->lock, flags);
++ return NULL;
++ }
++
++ bitmap_set(pool->alloc_map, pos, pages);
++ pool->alloc_pos = (pos + pages) % pool->pages;
++ pool->num_pages += pages;
++
++ DO_STATS(pool->num_bufs++);
++ DO_STATS(pool->max_bufs = max(pool->num_bufs, pool->max_bufs));
++ DO_STATS(pool->max_pages = max(pool->num_pages, pool->max_pages));
++
++ spin_unlock_irqrestore(&pool->lock, flags);
++
++ *dmaaddrp = pool->dma_addr + pos * PAGE_SIZE;
++
++ return pool->virt_addr + pos * PAGE_SIZE;
++}
++
++static void
++bounce_free(struct dmabounce_pool *pool, void *buf, size_t size)
++{
++ unsigned long pages;
++ unsigned long flags;
++ unsigned long pos;
++
++ pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
++ pos = (buf - pool->virt_addr)/PAGE_SIZE;
++
++ BUG_ON((buf - pool->virt_addr) & (PAGE_SIZE - 1));
++
++ spin_lock_irqsave(&pool->lock, flags);
++ bitmap_clear(pool->alloc_map, pos, pages);
++ pool->num_pages -= pages;
++ if (pool->num_pages == 0)
++ pool->alloc_pos = 0;
++ DO_STATS(pool->num_bufs--);
++ spin_unlock_irqrestore(&pool->lock, flags);
++}
++
++/* allocate a 'safe' buffer and keep track of it */
++static struct safe_buffer *
++alloc_safe_buffer(struct dmabounce_device_info *device_info,
++ dma_addr_t dma_addr, size_t size, enum dma_data_direction dir)
++{
++ struct safe_buffer *buf;
++ struct dmabounce_pool *pool = &device_info->pool;
++ struct device *dev = device_info->dev;
++ unsigned long flags;
++
++ /*
++ * Although one might expect this to be called in thread context,
++ * using GFP_KERNEL here leads to hard-to-debug lockups. in_atomic()
++ * was previously used to select the appropriate allocation mode,
++ * but this is unsafe.
++ */
++ buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
++ if (!buf) {
++ dev_warn(dev, "%s: kmalloc failed\n", __func__);
++ return NULL;
++ }
++
++ buf->unsafe_dma_addr = dma_addr;
++ buf->size = size;
++ buf->direction = dir;
++ buf->pool = pool;
++
++ buf->safe = bounce_alloc(pool, size, &buf->safe_dma_addr);
++
++ if (!buf->safe) {
++ dev_warn(dev,
++ "%s: could not alloc dma memory (size=%d)\n",
++ __func__, size);
++ kfree(buf);
++ return NULL;
++ }
++
++ write_lock_irqsave(&device_info->lock, flags);
++ list_add(&buf->node, &device_info->safe_buffers);
++ write_unlock_irqrestore(&device_info->lock, flags);
++
++ return buf;
++}
++
++/* determine if a buffer is from our "safe" pool */
++static struct safe_buffer *
++find_safe_buffer(struct dmabounce_device_info *device_info,
++ dma_addr_t safe_dma_addr)
++{
++ struct safe_buffer *b, *rb = NULL;
++ unsigned long flags;
++
++ read_lock_irqsave(&device_info->lock, flags);
++
++ list_for_each_entry(b, &device_info->safe_buffers, node)
++ if (b->safe_dma_addr <= safe_dma_addr &&
++ b->safe_dma_addr + b->size > safe_dma_addr) {
++ rb = b;
++ break;
++ }
++
++ read_unlock_irqrestore(&device_info->lock, flags);
++ return rb;
++}
++
++static void
++free_safe_buffer(struct dmabounce_device_info *device_info,
++ struct safe_buffer *buf)
++{
++ unsigned long flags;
++
++ write_lock_irqsave(&device_info->lock, flags);
++ list_del(&buf->node);
++ write_unlock_irqrestore(&device_info->lock, flags);
++
++ bounce_free(buf->pool, buf->safe, buf->size);
++
++ kfree(buf);
++}
++
++/* ************************************************** */
++
++static struct safe_buffer *
++find_safe_buffer_dev(struct device *dev, dma_addr_t dma_addr, const char *where)
++{
++ if (!dev || !g_dmabounce_device_info)
++ return NULL;
++ if (dma_mapping_error(dev, dma_addr)) {
++ dev_err(dev, "Trying to %s invalid mapping\n", where);
++ return NULL;
++ }
++ return find_safe_buffer(g_dmabounce_device_info, dma_addr);
++}
++
++static dma_addr_t
++map_single(struct device *dev, struct safe_buffer *buf, size_t size,
++ enum dma_data_direction dir, unsigned long attrs)
++{
++ BUG_ON(buf->size != size);
++ BUG_ON(buf->direction != dir);
++
++ dev_dbg(dev, "map: %llx->%llx\n", (u64)buf->unsafe_dma_addr,
++ (u64)buf->safe_dma_addr);
++
++ if ((dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) &&
++ !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
++ bcm2838_dma40_memcpy(buf->safe_dma_addr, buf->unsafe_dma_addr,
++ size);
++
++ return buf->safe_dma_addr;
++}
++
++static dma_addr_t
++unmap_single(struct device *dev, struct safe_buffer *buf, size_t size,
++ enum dma_data_direction dir, unsigned long attrs)
++{
++ BUG_ON(buf->size != size);
++ BUG_ON(buf->direction != dir);
++
++ if ((dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) &&
++ !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
++ dev_dbg(dev, "unmap: %llx->%llx\n", (u64)buf->safe_dma_addr,
++ (u64)buf->unsafe_dma_addr);
++
++ bcm2838_dma40_memcpy(buf->unsafe_dma_addr, buf->safe_dma_addr,
++ size);
++ }
++ return buf->unsafe_dma_addr;
++}
++
++/* ************************************************** */
++
++/*
++ * see if a buffer address is in an 'unsafe' range. if it is
++ * allocate a 'safe' buffer and copy the unsafe buffer into it.
++ * substitute the safe buffer for the unsafe one.
++ * (basically move the buffer from an unsafe area to a safe one)
++ */
++static dma_addr_t
++dmabounce_map_page(struct device *dev, struct page *page, unsigned long offset,
++ size_t size, enum dma_data_direction dir,
++ unsigned long attrs)
++{
++ struct dmabounce_device_info *device_info = g_dmabounce_device_info;
++ dma_addr_t dma_addr;
++
++ dma_addr = pfn_to_dma(dev, page_to_pfn(page)) + offset;
++
++ arm_dma_ops.sync_single_for_device(dev, dma_addr, size, dir);
++
++ if (device_info && (dma_addr + size) > device_info->threshold) {
++ struct safe_buffer *buf;
++
++ buf = alloc_safe_buffer(device_info, dma_addr, size, dir);
++ if (!buf) {
++ DO_STATS(device_info->fail_count++);
++ return ARM_MAPPING_ERROR;
++ }
++
++ DO_STATS(device_info->map_count++);
++
++ dma_addr = map_single(dev, buf, size, dir, attrs);
++ }
++
++ return dma_addr;
++}
++
++/*
++ * see if a mapped address was really a "safe" buffer and if so, copy
++ * the data from the safe buffer back to the unsafe buffer and free up
++ * the safe buffer. (basically return things back to the way they
++ * should be)
++ */
++static void
++dmabounce_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
++ enum dma_data_direction dir, unsigned long attrs)
++{
++ struct safe_buffer *buf;
++
++ buf = find_safe_buffer_dev(dev, dma_addr, __func__);
++ if (buf) {
++ DO_STATS(g_dmabounce_device_info->unmap_count++);
++ dma_addr = unmap_single(dev, buf, size, dir, attrs);
++ free_safe_buffer(g_dmabounce_device_info, buf);
++ }
++
++ arm_dma_ops.sync_single_for_cpu(dev, dma_addr, size, dir);
++}
++
++/*
++ * A version of dmabounce_map_page that assumes the mapping has already
++ * been created - intended for streaming operation.
++ */
++static void
++dmabounce_sync_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
++ enum dma_data_direction dir)
++{
++ struct safe_buffer *buf;
++
++ arm_dma_ops.sync_single_for_device(dev, dma_addr, size, dir);
++
++ buf = find_safe_buffer_dev(dev, dma_addr, __func__);
++ if (buf) {
++ DO_STATS(g_dmabounce_device_info->sync_dev_count++);
++ map_single(dev, buf, size, dir, 0);
++ }
++}
++
++/*
++ * A version of dmabounce_unmap_page that doesn't destroy the mapping -
++ * intended for streaming operation.
++ */
++static void
++dmabounce_sync_for_cpu(struct device *dev, dma_addr_t dma_addr,
++ size_t size, enum dma_data_direction dir)
++{
++ struct safe_buffer *buf;
++
++ buf = find_safe_buffer_dev(dev, dma_addr, __func__);
++ if (buf) {
++ DO_STATS(g_dmabounce_device_info->sync_cpu_count++);
++ dma_addr = unmap_single(dev, buf, size, dir, 0);
++ }
++
++ arm_dma_ops.sync_single_for_cpu(dev, dma_addr, size, dir);
++}
++
++static int dmabounce_dma_supported(struct device *dev, u64 dma_mask)
++{
++ if (g_dmabounce_device_info)
++ return 0;
++
++ return arm_dma_ops.dma_supported(dev, dma_mask);
++}
++
++static int dmabounce_mapping_error(struct device *dev, dma_addr_t dma_addr)
++{
++ return arm_dma_ops.mapping_error(dev, dma_addr);
++}
++
++static const struct dma_map_ops dmabounce_ops = {
++ .alloc = arm_dma_alloc,
++ .free = arm_dma_free,
++ .mmap = arm_dma_mmap,
++ .get_sgtable = arm_dma_get_sgtable,
++ .map_page = dmabounce_map_page,
++ .unmap_page = dmabounce_unmap_page,
++ .sync_single_for_cpu = dmabounce_sync_for_cpu,
++ .sync_single_for_device = dmabounce_sync_for_device,
++ .map_sg = arm_dma_map_sg,
++ .unmap_sg = arm_dma_unmap_sg,
++ .sync_sg_for_cpu = arm_dma_sync_sg_for_cpu,
++ .sync_sg_for_device = arm_dma_sync_sg_for_device,
++ .dma_supported = dmabounce_dma_supported,
++ .mapping_error = dmabounce_mapping_error,
++};
++
++int brcm_pcie_bounce_register_dev(struct device *dev,
++ unsigned long buffer_size,
++ dma_addr_t threshold)
++{
++ struct dmabounce_device_info *device_info;
++ int ret;
++
++ /* Only support a single client */
++ if (g_dmabounce_device_info)
++ return -EBUSY;
++
++ ret = bcm2838_dma40_memcpy_init(dev);
++ if (ret)
++ return ret;
++
++ device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
++ if (!device_info) {
++ dev_err(dev,
++ "Could not allocated dmabounce_device_info\n");
++ return -ENOMEM;
++ }
++
++ ret = bounce_create(&device_info->pool, dev, buffer_size);
++ if (ret) {
++ dev_err(dev,
++ "dmabounce: could not allocate %ld byte DMA pool\n",
++ buffer_size);
++ goto err_bounce;
++ }
++
++ device_info->dev = dev;
++ device_info->threshold = threshold;
++ INIT_LIST_HEAD(&device_info->safe_buffers);
++ rwlock_init(&device_info->lock);
++
++ DO_STATS(device_info->map_count = 0);
++ DO_STATS(device_info->unmap_count = 0);
++ DO_STATS(device_info->sync_dev_count = 0);
++ DO_STATS(device_info->sync_cpu_count = 0);
++ DO_STATS(device_info->fail_count = 0);
++ DO_STATS(device_info->attr_res =
++ device_create_file(dev, &dev_attr_dmabounce_stats));
++
++ g_dmabounce_device_info = device_info;
++ set_dma_ops(dev, &dmabounce_ops);
++
++ dev_info(dev, "dmabounce: registered device - %ld kB, threshold %pad\n",
++ buffer_size / 1024, &threshold);
++
++ return 0;
++
++ err_bounce:
++ kfree(device_info);
++ return ret;
++}
++EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
++
++void brcm_pcie_bounce_unregister_dev(struct device *dev)
++{
++ struct dmabounce_device_info *device_info = g_dmabounce_device_info;
++
++ g_dmabounce_device_info = NULL;
++ set_dma_ops(dev, NULL);
++
++ if (!device_info) {
++ dev_warn(dev,
++ "Never registered with dmabounce but attempting"
++ "to unregister!\n");
++ return;
++ }
++
++ if (!list_empty(&device_info->safe_buffers)) {
++ dev_err(dev,
++ "Removing from dmabounce with pending buffers!\n");
++ BUG();
++ }
++
++ bounce_destroy(&device_info->pool);
++
++ DO_STATS(if (device_info->attr_res == 0)
++ device_remove_file(dev, &dev_attr_dmabounce_stats));
++
++ kfree(device_info);
++
++ dev_info(dev, "dmabounce: device unregistered\n");
++}
++EXPORT_SYMBOL(brcm_pcie_bounce_unregister_dev);
++
++MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.org>");
++MODULE_DESCRIPTION("Dedicate DMA bounce support for pcie-brcmstb");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/drivers/pci/controller/pcie-brcmstb-bounce.h
+@@ -0,0 +1,32 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (C) 2019 Raspberry Pi (Trading) Ltd.
++ */
++
++#ifndef _PCIE_BRCMSTB_BOUNCE_H
++#define _PCIE_BRCMSTB_BOUNCE_H
++
++#ifdef CONFIG_ARM
++
++int brcm_pcie_bounce_register_dev(struct device *dev, unsigned long buffer_size,
++ dma_addr_t threshold);
++
++int brcm_pcie_bounce_unregister_dev(struct device *dev);
++
++#else
++
++static inline int brcm_pcie_bounce_register_dev(struct device *dev,
++ unsigned long buffer_size,
++ dma_addr_t threshold)
++{
++ return 0;
++}
++
++static inline int brcm_pcie_bounce_unregister_dev(struct device *dev)
++{
++ return 0;
++}
++
++#endif
++
++#endif /* _PCIE_BRCMSTB_BOUNCE_H */
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -29,6 +29,7 @@
+ #include <linux/string.h>
+ #include <linux/types.h>
+ #include "../pci.h"
++#include "pcie-brcmstb-bounce.h"
+
+ /* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
+ #define BRCM_PCIE_CAP_REGS 0x00ac
+@@ -53,6 +54,7 @@
+ #define PCIE_MISC_MSI_BAR_CONFIG_LO 0x4044
+ #define PCIE_MISC_MSI_BAR_CONFIG_HI 0x4048
+ #define PCIE_MISC_MSI_DATA_CONFIG 0x404c
++#define PCIE_MISC_EOI_CTRL 0x4060
+ #define PCIE_MISC_PCIE_CTRL 0x4064
+ #define PCIE_MISC_PCIE_STATUS 0x4068
+ #define PCIE_MISC_REVISION 0x406c
+@@ -260,12 +262,14 @@ struct brcm_pcie {
+ unsigned int rev;
+ const int *reg_offsets;
+ const int *reg_field_info;
++ u32 max_burst_size;
+ enum pcie_type type;
+ };
+
+ struct pcie_cfg_data {
+ const int *reg_field_info;
+ const int *offsets;
++ const u32 max_burst_size;
+ const enum pcie_type type;
+ };
+
+@@ -288,24 +292,27 @@ static const int pcie_offset_bcm7425[] =
+ static const struct pcie_cfg_data bcm7425_cfg = {
+ .reg_field_info = pcie_reg_field_info,
+ .offsets = pcie_offset_bcm7425,
++ .max_burst_size = BURST_SIZE_256,
+ .type = BCM7425,
+ };
+
+ static const int pcie_offsets[] = {
+ [RGR1_SW_INIT_1] = 0x9210,
+ [EXT_CFG_INDEX] = 0x9000,
+- [EXT_CFG_DATA] = 0x9004,
++ [EXT_CFG_DATA] = 0x8000,
+ };
+
+ static const struct pcie_cfg_data bcm7435_cfg = {
+ .reg_field_info = pcie_reg_field_info,
+ .offsets = pcie_offsets,
++ .max_burst_size = BURST_SIZE_256,
+ .type = BCM7435,
+ };
+
+ static const struct pcie_cfg_data generic_cfg = {
+ .reg_field_info = pcie_reg_field_info,
+ .offsets = pcie_offsets,
++ .max_burst_size = BURST_SIZE_128, // before BURST_SIZE_512
+ .type = GENERIC,
+ };
+
+@@ -318,6 +325,7 @@ static const int pcie_offset_bcm7278[] =
+ static const struct pcie_cfg_data bcm7278_cfg = {
+ .reg_field_info = pcie_reg_field_info_bcm7278,
+ .offsets = pcie_offset_bcm7278,
++ .max_burst_size = BURST_SIZE_512,
+ .type = BCM7278,
+ };
+
+@@ -360,7 +368,6 @@ static struct pci_ops brcm_pcie_ops = {
+ (reg##_##field##_MASK & (field_val << reg##_##field##_SHIFT)))
+
+ static const struct dma_map_ops *arch_dma_ops;
+-static const struct dma_map_ops *brcm_dma_ops_ptr;
+ static struct of_pci_range *dma_ranges;
+ static int num_dma_ranges;
+
+@@ -369,6 +376,16 @@ static int num_memc;
+ static int num_pcie;
+ static DEFINE_MUTEX(brcm_pcie_lock);
+
++static unsigned int bounce_buffer = 32*1024*1024;
++module_param(bounce_buffer, uint, 0644);
++MODULE_PARM_DESC(bounce_buffer, "Size of bounce buffer");
++
++static unsigned int bounce_threshold = 0xc0000000;
++module_param(bounce_threshold, uint, 0644);
++MODULE_PARM_DESC(bounce_threshold, "Bounce threshold");
++
++static struct brcm_pcie *g_pcie;
++
+ static dma_addr_t brcm_to_pci(dma_addr_t addr)
+ {
+ struct of_pci_range *p;
+@@ -457,12 +474,10 @@ static int brcm_map_sg(struct device *de
+ struct scatterlist *sg;
+
+ for_each_sg(sgl, sg, nents, i) {
+-#ifdef CONFIG_NEED_SG_DMA_LENGTH
+- sg->dma_length = sg->length;
+-#endif
++ sg_dma_len(sg) = sg->length;
+ sg->dma_address =
+- brcm_dma_ops_ptr->map_page(dev, sg_page(sg), sg->offset,
+- sg->length, dir, attrs);
++ brcm_map_page(dev, sg_page(sg), sg->offset,
++ sg->length, dir, attrs);
+ if (dma_mapping_error(dev, sg->dma_address))
+ goto bad_mapping;
+ }
+@@ -470,8 +485,8 @@ static int brcm_map_sg(struct device *de
+
+ bad_mapping:
+ for_each_sg(sgl, sg, i, j)
+- brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
+- sg_dma_len(sg), dir, attrs);
++ brcm_unmap_page(dev, sg_dma_address(sg),
++ sg_dma_len(sg), dir, attrs);
+ return 0;
+ }
+
+@@ -484,8 +499,8 @@ static void brcm_unmap_sg(struct device
+ struct scatterlist *sg;
+
+ for_each_sg(sgl, sg, nents, i)
+- brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
+- sg_dma_len(sg), dir, attrs);
++ brcm_unmap_page(dev, sg_dma_address(sg),
++ sg_dma_len(sg), dir, attrs);
+ }
+
+ static void brcm_sync_single_for_cpu(struct device *dev,
+@@ -531,8 +546,8 @@ void brcm_sync_sg_for_cpu(struct device
+ int i;
+
+ for_each_sg(sgl, sg, nents, i)
+- brcm_dma_ops_ptr->sync_single_for_cpu(dev, sg_dma_address(sg),
+- sg->length, dir);
++ brcm_sync_single_for_cpu(dev, sg_dma_address(sg),
++ sg->length, dir);
+ }
+
+ void brcm_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
+@@ -542,9 +557,9 @@ void brcm_sync_sg_for_device(struct devi
+ int i;
+
+ for_each_sg(sgl, sg, nents, i)
+- brcm_dma_ops_ptr->sync_single_for_device(dev,
+- sg_dma_address(sg),
+- sg->length, dir);
++ brcm_sync_single_for_device(dev,
++ sg_dma_address(sg),
++ sg->length, dir);
+ }
+
+ static int brcm_mapping_error(struct device *dev, dma_addr_t dma_addr)
+@@ -633,17 +648,47 @@ static void brcm_set_dma_ops(struct devi
+ set_dma_ops(dev, &brcm_dma_ops);
+ }
+
++static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie,
++ unsigned int val);
+ static int brcmstb_platform_notifier(struct notifier_block *nb,
+ unsigned long event, void *__dev)
+ {
++ extern unsigned long max_pfn;
+ struct device *dev = __dev;
++ const char *rc_name = "0000:00:00.0";
+
+- brcm_dma_ops_ptr = &brcm_dma_ops;
+- if (event != BUS_NOTIFY_ADD_DEVICE)
+- return NOTIFY_DONE;
++ switch (event) {
++ case BUS_NOTIFY_ADD_DEVICE:
++ if (max_pfn > (bounce_threshold/PAGE_SIZE) &&
++ strcmp(dev->kobj.name, rc_name)) {
++ int ret;
++
++ ret = brcm_pcie_bounce_register_dev(dev, bounce_buffer,
++ (dma_addr_t)bounce_threshold);
++ if (ret) {
++ dev_err(dev,
++ "brcm_pcie_bounce_register_dev() failed: %d\n",
++ ret);
++ return ret;
++ }
++ }
++ brcm_set_dma_ops(dev);
++ return NOTIFY_OK;
++
++ case BUS_NOTIFY_DEL_DEVICE:
++ if (!strcmp(dev->kobj.name, rc_name) && g_pcie) {
++ /* Force a bus reset */
++ brcm_pcie_perst_set(g_pcie, 1);
++ msleep(100);
++ brcm_pcie_perst_set(g_pcie, 0);
++ } else if (max_pfn > (bounce_threshold/PAGE_SIZE)) {
++ brcm_pcie_bounce_unregister_dev(dev);
++ }
++ return NOTIFY_OK;
+
+- brcm_set_dma_ops(dev);
+- return NOTIFY_OK;
++ default:
++ return NOTIFY_DONE;
++ }
+ }
+
+ static struct notifier_block brcmstb_platform_nb = {
+@@ -914,6 +959,7 @@ static void brcm_pcie_msi_isr(struct irq
+ }
+ }
+ chained_irq_exit(chip, desc);
++ bcm_writel(1, msi->base + PCIE_MISC_EOI_CTRL);
+ }
+
+ static void brcm_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+@@ -930,7 +976,8 @@ static void brcm_compose_msi_msg(struct
+ static int brcm_msi_set_affinity(struct irq_data *irq_data,
+ const struct cpumask *mask, bool force)
+ {
+- return -EINVAL;
++ struct brcm_msi *msi = irq_data_get_irq_chip_data(irq_data);
++ return __irq_set_affinity(msi->irq, mask, force);
+ }
+
+ static struct irq_chip brcm_msi_bottom_irq_chip = {
+@@ -1168,9 +1215,9 @@ static void __iomem *brcm_pcie_map_conf(
+ return PCI_SLOT(devfn) ? NULL : base + where;
+
+ /* For devices, write to the config space index register */
+- idx = cfg_index(bus->number, devfn, where);
++ idx = cfg_index(bus->number, devfn, 0);
+ bcm_writel(idx, pcie->base + IDX_ADDR(pcie));
+- return base + DATA_ADDR(pcie) + (where & 0x3);
++ return base + DATA_ADDR(pcie) + where;
+ }
+
+ static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie,
+@@ -1238,20 +1285,6 @@ static int brcm_pcie_parse_map_dma_range
+ num_dma_ranges++;
+ }
+
+- for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
+- u64 size = brcmstb_memory_memc_size(i);
+-
+- if (size == (u64)-1) {
+- dev_err(pcie->dev, "cannot get memc%d size", i);
+- return -EINVAL;
+- } else if (size) {
+- scb_size[i] = roundup_pow_of_two_64(size);
+- num_memc++;
+- } else {
+- break;
+- }
+- }
+-
+ return 0;
+ }
+
+@@ -1275,26 +1308,25 @@ static int brcm_pcie_add_controller(stru
+ if (ret)
+ goto done;
+
+- /* Determine num_memc and their sizes */
+- for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
+- u64 size = brcmstb_memory_memc_size(i);
+-
+- if (size == (u64)-1) {
+- dev_err(dev, "cannot get memc%d size\n", i);
+- ret = -EINVAL;
+- goto done;
+- } else if (size) {
+- scb_size[i] = roundup_pow_of_two_64(size);
+- num_memc++;
+- } else {
+- break;
++ if (!num_dma_ranges) {
++ /* Determine num_memc and their sizes by other means */
++ for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
++ u64 size = brcmstb_memory_memc_size(i);
++
++ if (size == (u64)-1) {
++ dev_err(dev, "cannot get memc%d size\n", i);
++ ret = -EINVAL;
++ goto done;
++ } else if (size) {
++ scb_size[i] = roundup_pow_of_two_64(size);
++ } else {
++ break;
++ }
+ }
+- }
+- if (!ret && num_memc == 0) {
+- ret = -EINVAL;
+- goto done;
++ num_memc = i;
+ }
+
++ g_pcie = pcie;
+ num_pcie++;
+ done:
+ mutex_unlock(&brcm_pcie_lock);
+@@ -1307,6 +1339,7 @@ static void brcm_pcie_remove_controller(
+ if (--num_pcie > 0)
+ goto out;
+
++ g_pcie = NULL;
+ if (brcm_unregister_notifier())
+ dev_err(pcie->dev, "failed to unregister pci bus notifier\n");
+ kfree(dma_ranges);
+@@ -1367,7 +1400,7 @@ static int brcm_pcie_setup(struct brcm_p
+ void __iomem *base = pcie->base;
+ unsigned int scb_size_val;
+ u64 rc_bar2_offset, rc_bar2_size, total_mem_size = 0;
+- u32 tmp, burst;
++ u32 tmp;
+ int i, j, ret, limit;
+ u16 nlw, cls, lnksta;
+ bool ssc_good = false;
+@@ -1400,20 +1433,15 @@ static int brcm_pcie_setup(struct brcm_p
+ /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
+ tmp = INSERT_FIELD(0, PCIE_MISC_MISC_CTRL, SCB_ACCESS_EN, 1);
+ tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, CFG_READ_UR_MODE, 1);
+- burst = (pcie->type == GENERIC || pcie->type == BCM7278)
+- ? BURST_SIZE_512 : BURST_SIZE_256;
+- tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE, burst);
++ tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE,
++ pcie->max_burst_size);
+ bcm_writel(tmp, base + PCIE_MISC_MISC_CTRL);
+
+ /*
+ * Set up inbound memory view for the EP (called RC_BAR2,
+ * not to be confused with the BARs that are advertised by
+ * the EP).
+- */
+- for (i = 0; i < num_memc; i++)
+- total_mem_size += scb_size[i];
+-
+- /*
++ *
+ * The PCIe host controller by design must set the inbound
+ * viewport to be a contiguous arrangement of all of the
+ * system's memory. In addition, its size mut be a power of
+@@ -1429,55 +1457,49 @@ static int brcm_pcie_setup(struct brcm_p
+ * the controller will know to send outbound memory downstream
+ * and everything else upstream.
+ */
+- rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
+
+- if (dma_ranges) {
++ if (num_dma_ranges) {
+ /*
+- * The best-case scenario is to place the inbound
+- * region in the first 4GB of pcie-space, as some
+- * legacy devices can only address 32bits.
+- * We would also like to put the MSI under 4GB
+- * as well, since some devices require a 32bit
+- * MSI target address.
++ * Use the base address and size(s) provided in the dma-ranges
++ * property.
+ */
+- if (total_mem_size <= 0xc0000000ULL &&
+- rc_bar2_size <= 0x100000000ULL) {
+- rc_bar2_offset = 0;
+- /* If the viewport is less then 4GB we can fit
+- * the MSI target address under 4GB. Otherwise
+- * put it right below 64GB.
+- */
+- msi_target_addr =
+- (rc_bar2_size == 0x100000000ULL)
+- ? BRCM_MSI_TARGET_ADDR_GT_4GB
+- : BRCM_MSI_TARGET_ADDR_LT_4GB;
+- } else {
+- /*
+- * The system memory is 4GB or larger so we
+- * cannot start the inbound region at location
+- * 0 (since we have to allow some space for
+- * outbound memory @ 3GB). So instead we
+- * start it at the 1x multiple of its size
+- */
+- rc_bar2_offset = rc_bar2_size;
+-
+- /* Since we are starting the viewport at 4GB or
+- * higher, put the MSI target address below 4GB
+- */
+- msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
+- }
+- } else {
++ for (i = 0; i < num_dma_ranges; i++)
++ scb_size[i] = roundup_pow_of_two_64(dma_ranges[i].size);
++
++ num_memc = num_dma_ranges;
++ rc_bar2_offset = dma_ranges[0].pci_addr;
++ } else if (num_memc) {
+ /*
+ * Set simple configuration based on memory sizes
+- * only. We always start the viewport at address 0,
+- * and set the MSI target address accordingly.
++ * only. We always start the viewport at address 0.
+ */
+ rc_bar2_offset = 0;
++ } else {
++ return -EINVAL;
++ }
++
++ for (i = 0; i < num_memc; i++)
++ total_mem_size += scb_size[i];
++
++ rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
+
+- msi_target_addr = (rc_bar2_size >= 0x100000000ULL)
+- ? BRCM_MSI_TARGET_ADDR_GT_4GB
+- : BRCM_MSI_TARGET_ADDR_LT_4GB;
++ /* Verify the alignment is correct */
++ if (rc_bar2_offset & (rc_bar2_size - 1)) {
++ dev_err(dev, "inbound window is misaligned\n");
++ return -EINVAL;
+ }
++
++ /*
++ * Position the MSI target low if possible.
++ *
++ * TO DO: Consider outbound window when choosing MSI target and
++ * verifying configuration.
++ */
++ msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
++ if (rc_bar2_offset <= msi_target_addr &&
++ rc_bar2_offset + rc_bar2_size > msi_target_addr)
++ msi_target_addr = BRCM_MSI_TARGET_ADDR_GT_4GB;
++
+ pcie->msi_target_addr = msi_target_addr;
+
+ tmp = lower_32_bits(rc_bar2_offset);
+@@ -1713,6 +1735,7 @@ static int brcm_pcie_probe(struct platfo
+ data = of_id->data;
+ pcie->reg_offsets = data->offsets;
+ pcie->reg_field_info = data->reg_field_info;
++ pcie->max_burst_size = data->max_burst_size;
+ pcie->type = data->type;
+ pcie->dn = dn;
+ pcie->dev = &pdev->dev;
+@@ -1732,7 +1755,7 @@ static int brcm_pcie_probe(struct platfo
+
+ pcie->clk = of_clk_get_by_name(dn, "sw_pcie");
+ if (IS_ERR(pcie->clk)) {
+- dev_err(&pdev->dev, "could not get clock\n");
++ dev_warn(&pdev->dev, "could not get clock\n");
+ pcie->clk = NULL;
+ }
+ pcie->base = base;
+@@ -1755,7 +1778,8 @@ static int brcm_pcie_probe(struct platfo
+
+ ret = clk_prepare_enable(pcie->clk);
+ if (ret) {
+- dev_err(&pdev->dev, "could not enable clock\n");
++ if (ret != -EPROBE_DEFER)
++ dev_err(&pdev->dev, "could not enable clock\n");
+ return ret;
+ }
+
+@@ -1818,7 +1842,6 @@ static struct platform_driver brcm_pcie_
+ .remove = brcm_pcie_remove,
+ .driver = {
+ .name = "brcm-pcie",
+- .owner = THIS_MODULE,
+ .of_match_table = brcm_pcie_match,
+ .pm = &brcm_pcie_pm_ops,
+ },
+--- a/drivers/soc/bcm/brcmstb/Makefile
++++ b/drivers/soc/bcm/brcmstb/Makefile
+@@ -1,2 +1,2 @@
+-obj-y += common.o biuctrl.o
++obj-y += common.o biuctrl.o memory.o
+ obj-$(CONFIG_BRCMSTB_PM) += pm/
+--- /dev/null
++++ b/drivers/soc/bcm/brcmstb/memory.c
+@@ -0,0 +1,158 @@
++// SPDX-License-Identifier: GPL-2.0
++/* Copyright © 2015-2017 Broadcom */
++
++#include <linux/device.h>
++#include <linux/io.h>
++#include <linux/libfdt.h>
++#include <linux/of_address.h>
++#include <linux/of_fdt.h>
++#include <linux/sizes.h>
++#include <soc/brcmstb/memory_api.h>
++
++/* Macro to help extract property data */
++#define DT_PROP_DATA_TO_U32(b, offs) (fdt32_to_cpu(*(u32 *)(b + offs)))
++
++/* Constants used when retrieving memc info */
++#define NUM_BUS_RANGES 10
++#define BUS_RANGE_ULIMIT_SHIFT 4
++#define BUS_RANGE_LLIMIT_SHIFT 4
++#define BUS_RANGE_PA_SHIFT 12
++
++enum {
++ BUSNUM_MCP0 = 0x4,
++ BUSNUM_MCP1 = 0x5,
++ BUSNUM_MCP2 = 0x6,
++};
++
++/*
++ * If the DT nodes are handy, determine which MEMC holds the specified
++ * physical address.
++ */
++#ifdef CONFIG_ARCH_BRCMSTB
++int __brcmstb_memory_phys_addr_to_memc(phys_addr_t pa, void __iomem *base)
++{
++ int memc = -1;
++ int i;
++
++ for (i = 0; i < NUM_BUS_RANGES; i++, base += 8) {
++ const u64 ulimit_raw = readl(base);
++ const u64 llimit_raw = readl(base + 4);
++ const u64 ulimit =
++ ((ulimit_raw >> BUS_RANGE_ULIMIT_SHIFT)
++ << BUS_RANGE_PA_SHIFT) | 0xfff;
++ const u64 llimit = (llimit_raw >> BUS_RANGE_LLIMIT_SHIFT)
++ << BUS_RANGE_PA_SHIFT;
++ const u32 busnum = (u32)(ulimit_raw & 0xf);
++
++ if (pa >= llimit && pa <= ulimit) {
++ if (busnum >= BUSNUM_MCP0 && busnum <= BUSNUM_MCP2) {
++ memc = busnum - BUSNUM_MCP0;
++ break;
++ }
++ }
++ }
++
++ return memc;
++}
++
++int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa)
++{
++ int memc = -1;
++ struct device_node *np;
++ void __iomem *cpubiuctrl;
++
++ np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
++ if (!np)
++ return memc;
++
++ cpubiuctrl = of_iomap(np, 0);
++ if (!cpubiuctrl)
++ goto cleanup;
++
++ memc = __brcmstb_memory_phys_addr_to_memc(pa, cpubiuctrl);
++ iounmap(cpubiuctrl);
++
++cleanup:
++ of_node_put(np);
++
++ return memc;
++}
++
++#elif defined(CONFIG_MIPS)
++int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa)
++{
++ /* The logic here is fairly simple and hardcoded: if pa <= 0x5000_0000,
++ * then this is MEMC0, else MEMC1.
++ *
++ * For systems with 2GB on MEMC0, MEMC1 starts at 9000_0000, with 1GB
++ * on MEMC0, MEMC1 starts at 6000_0000.
++ */
++ if (pa >= 0x50000000ULL)
++ return 1;
++ else
++ return 0;
++}
++#endif
++
++u64 brcmstb_memory_memc_size(int memc)
++{
++ const void *fdt = initial_boot_params;
++ const int mem_offset = fdt_path_offset(fdt, "/memory");
++ int addr_cells = 1, size_cells = 1;
++ const struct fdt_property *prop;
++ int proplen, cellslen;
++ u64 memc_size = 0;
++ int i;
++
++ /* Get root size and address cells if specified */
++ prop = fdt_get_property(fdt, 0, "#size-cells", &proplen);
++ if (prop)
++ size_cells = DT_PROP_DATA_TO_U32(prop->data, 0);
++
++ prop = fdt_get_property(fdt, 0, "#address-cells", &proplen);
++ if (prop)
++ addr_cells = DT_PROP_DATA_TO_U32(prop->data, 0);
++
++ if (mem_offset < 0)
++ return -1;
++
++ prop = fdt_get_property(fdt, mem_offset, "reg", &proplen);
++ cellslen = (int)sizeof(u32) * (addr_cells + size_cells);
++ if ((proplen % cellslen) != 0)
++ return -1;
++
++ for (i = 0; i < proplen / cellslen; ++i) {
++ u64 addr = 0;
++ u64 size = 0;
++ int memc_idx;
++ int j;
++
++ for (j = 0; j < addr_cells; ++j) {
++ int offset = (cellslen * i) + (sizeof(u32) * j);
++
++ addr |= (u64)DT_PROP_DATA_TO_U32(prop->data, offset) <<
++ ((addr_cells - j - 1) * 32);
++ }
++ for (j = 0; j < size_cells; ++j) {
++ int offset = (cellslen * i) +
++ (sizeof(u32) * (j + addr_cells));
++
++ size |= (u64)DT_PROP_DATA_TO_U32(prop->data, offset) <<
++ ((size_cells - j - 1) * 32);
++ }
++
++ if ((phys_addr_t)addr != addr) {
++ pr_err("phys_addr_t is smaller than provided address 0x%llx!\n",
++ addr);
++ return -1;
++ }
++
++ memc_idx = brcmstb_memory_phys_addr_to_memc((phys_addr_t)addr);
++ if (memc_idx == memc)
++ memc_size += size;
++ }
++
++ return memc_size;
++}
++EXPORT_SYMBOL_GPL(brcmstb_memory_memc_size);
++
+++ /dev/null
-From 00dbba2f38e18a68e5dce8327ec91bdcb94d2bd1 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 19 Feb 2019 22:06:59 +0000
-Subject: [PATCH 535/703] PCI: brcmstb: Add dma-range mapping for inbound
- traffic
-
-The Broadcom STB PCIe host controller is intimately related to the
-memory subsystem. This close relationship adds complexity to how cpu
-system memory is mapped to PCIe memory. Ideally, this mapping is an
-identity mapping, or an identity mapping off by a constant. Not so in
-this case.
-
-Consider the Broadcom reference board BCM97445LCC_4X8 which has 6 GB
-of system memory. Here is how the PCIe controller maps the
-system memory to PCIe memory:
-
- memc0-a@[ 0....3fffffff] <=> pci@[ 0....3fffffff]
- memc0-b@[100000000...13fffffff] <=> pci@[ 40000000....7fffffff]
- memc1-a@[ 40000000....7fffffff] <=> pci@[ 80000000....bfffffff]
- memc1-b@[300000000...33fffffff] <=> pci@[ c0000000....ffffffff]
- memc2-a@[ 80000000....bfffffff] <=> pci@[100000000...13fffffff]
- memc2-b@[c00000000...c3fffffff] <=> pci@[140000000...17fffffff]
-
-Although there are some "gaps" that can be added between the
-individual mappings by software, the permutation of memory regions for
-the most part is fixed by HW. The solution of having something close
-to an identity mapping is not possible.
-
-The idea behind this HW design is that the same PCIe module can
-act as an RC or EP, and if it acts as an EP it concatenates all
-of system memory into a BAR so anything can be accessed. Unfortunately,
-when the PCIe block is in the role of an RC it also presents this
-"BAR" to downstream PCIe devices, rather than offering an identity map
-between its system memory and PCIe space.
-
-Suppose that an endpoint driver allocs some DMA memory. Suppose this
-memory is located at 0x6000_0000, which is in the middle of memc1-a.
-The driver wants a dma_addr_t value that it can pass on to the EP to
-use. Without doing any custom mapping, the EP will use this value for
-DMA: the driver will get a dma_addr_t equal to 0x6000_0000. But this
-won't work; the device needs a dma_addr_t that reflects the PCIe space
-address, namely 0xa000_0000.
-
-So, essentially the solution to this problem must modify the
-dma_addr_t returned by the DMA routines routines. There are two
-ways (I know of) of doing this:
-
-(a) overriding/redefining the dma_to_phys() and phys_to_dma() calls
-that are used by the dma_ops routines. This is the approach of
-
- arch/mips/cavium-octeon/dma-octeon.c
-
-In ARM and ARM64 these two routines are defiend in asm/dma-mapping.h
-as static inline functions.
-
-(b) Subscribe to a notifier that notifies when a device is added to a
-bus. When this happens, set_dma_ops() can be called for the device.
-This method is mentioned in:
-
- http://lxr.free-electrons.com/source/drivers/of/platform.c?v=3.16#L152
-
-where it says as a comment
-
- "In case if platform code need to use own special DMA
- configuration, it can use Platform bus notifier and
- handle BUS_NOTIFY_ADD_DEVICE event to fix up DMA
- configuration."
-
-Solution (b) is what this commit does. It uses its own set of
-dma_ops which are wrappers around the arch_dma_ops. The
-wrappers translate the dma addresses before/after invoking
-the arch_dma_ops, as appropriate.
-
-Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
----
- drivers/pci/controller/pcie-brcmstb.c | 420 +++++++++++++++++++++++++-
- 1 file changed, 411 insertions(+), 9 deletions(-)
-
---- a/drivers/pci/controller/pcie-brcmstb.c
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -4,6 +4,7 @@
- #include <linux/clk.h>
- #include <linux/compiler.h>
- #include <linux/delay.h>
-+#include <linux/dma-mapping.h>
- #include <linux/init.h>
- #include <linux/interrupt.h>
- #include <linux/io.h>
-@@ -319,11 +320,307 @@ static struct pci_ops brcm_pcie_ops = {
- ((val & ~reg##_##field##_MASK) | \
- (reg##_##field##_MASK & (field_val << reg##_##field##_SHIFT)))
-
-+static const struct dma_map_ops *arch_dma_ops;
-+static const struct dma_map_ops *brcm_dma_ops_ptr;
-+static struct of_pci_range *dma_ranges;
-+static int num_dma_ranges;
-+
- static phys_addr_t scb_size[BRCM_MAX_SCB];
- static int num_memc;
- static int num_pcie;
- static DEFINE_MUTEX(brcm_pcie_lock);
-
-+static dma_addr_t brcm_to_pci(dma_addr_t addr)
-+{
-+ struct of_pci_range *p;
-+
-+ if (!num_dma_ranges)
-+ return addr;
-+
-+ for (p = dma_ranges; p < &dma_ranges[num_dma_ranges]; p++)
-+ if (addr >= p->cpu_addr && addr < (p->cpu_addr + p->size))
-+ return addr - p->cpu_addr + p->pci_addr;
-+
-+ return addr;
-+}
-+
-+static dma_addr_t brcm_to_cpu(dma_addr_t addr)
-+{
-+ struct of_pci_range *p;
-+
-+ if (!num_dma_ranges)
-+ return addr;
-+
-+ for (p = dma_ranges; p < &dma_ranges[num_dma_ranges]; p++)
-+ if (addr >= p->pci_addr && addr < (p->pci_addr + p->size))
-+ return addr - p->pci_addr + p->cpu_addr;
-+
-+ return addr;
-+}
-+
-+static void *brcm_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-+ gfp_t gfp, unsigned long attrs)
-+{
-+ void *ret;
-+
-+ ret = arch_dma_ops->alloc(dev, size, handle, gfp, attrs);
-+ if (ret)
-+ *handle = brcm_to_pci(*handle);
-+ return ret;
-+}
-+
-+static void brcm_free(struct device *dev, size_t size, void *cpu_addr,
-+ dma_addr_t handle, unsigned long attrs)
-+{
-+ handle = brcm_to_cpu(handle);
-+ arch_dma_ops->free(dev, size, cpu_addr, handle, attrs);
-+}
-+
-+static int brcm_mmap(struct device *dev, struct vm_area_struct *vma,
-+ void *cpu_addr, dma_addr_t dma_addr, size_t size,
-+ unsigned long attrs)
-+{
-+ dma_addr = brcm_to_cpu(dma_addr);
-+ return arch_dma_ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
-+}
-+
-+static int brcm_get_sgtable(struct device *dev, struct sg_table *sgt,
-+ void *cpu_addr, dma_addr_t handle, size_t size,
-+ unsigned long attrs)
-+{
-+ handle = brcm_to_cpu(handle);
-+ return arch_dma_ops->get_sgtable(dev, sgt, cpu_addr, handle, size,
-+ attrs);
-+}
-+
-+static dma_addr_t brcm_map_page(struct device *dev, struct page *page,
-+ unsigned long offset, size_t size,
-+ enum dma_data_direction dir,
-+ unsigned long attrs)
-+{
-+ return brcm_to_pci(arch_dma_ops->map_page(dev, page, offset, size,
-+ dir, attrs));
-+}
-+
-+static void brcm_unmap_page(struct device *dev, dma_addr_t handle,
-+ size_t size, enum dma_data_direction dir,
-+ unsigned long attrs)
-+{
-+ handle = brcm_to_cpu(handle);
-+ arch_dma_ops->unmap_page(dev, handle, size, dir, attrs);
-+}
-+
-+static int brcm_map_sg(struct device *dev, struct scatterlist *sgl,
-+ int nents, enum dma_data_direction dir,
-+ unsigned long attrs)
-+{
-+ int i, j;
-+ struct scatterlist *sg;
-+
-+ for_each_sg(sgl, sg, nents, i) {
-+#ifdef CONFIG_NEED_SG_DMA_LENGTH
-+ sg->dma_length = sg->length;
-+#endif
-+ sg->dma_address =
-+ brcm_dma_ops_ptr->map_page(dev, sg_page(sg), sg->offset,
-+ sg->length, dir, attrs);
-+ if (dma_mapping_error(dev, sg->dma_address))
-+ goto bad_mapping;
-+ }
-+ return nents;
-+
-+bad_mapping:
-+ for_each_sg(sgl, sg, i, j)
-+ brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
-+ sg_dma_len(sg), dir, attrs);
-+ return 0;
-+}
-+
-+static void brcm_unmap_sg(struct device *dev,
-+ struct scatterlist *sgl, int nents,
-+ enum dma_data_direction dir,
-+ unsigned long attrs)
-+{
-+ int i;
-+ struct scatterlist *sg;
-+
-+ for_each_sg(sgl, sg, nents, i)
-+ brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
-+ sg_dma_len(sg), dir, attrs);
-+}
-+
-+static void brcm_sync_single_for_cpu(struct device *dev,
-+ dma_addr_t handle, size_t size,
-+ enum dma_data_direction dir)
-+{
-+ handle = brcm_to_cpu(handle);
-+ arch_dma_ops->sync_single_for_cpu(dev, handle, size, dir);
-+}
-+
-+static void brcm_sync_single_for_device(struct device *dev,
-+ dma_addr_t handle, size_t size,
-+ enum dma_data_direction dir)
-+{
-+ handle = brcm_to_cpu(handle);
-+ arch_dma_ops->sync_single_for_device(dev, handle, size, dir);
-+}
-+
-+static dma_addr_t brcm_map_resource(struct device *dev, phys_addr_t phys,
-+ size_t size,
-+ enum dma_data_direction dir,
-+ unsigned long attrs)
-+{
-+ if (arch_dma_ops->map_resource)
-+ return brcm_to_pci(arch_dma_ops->map_resource
-+ (dev, phys, size, dir, attrs));
-+ return brcm_to_pci((dma_addr_t)phys);
-+}
-+
-+static void brcm_unmap_resource(struct device *dev, dma_addr_t handle,
-+ size_t size, enum dma_data_direction dir,
-+ unsigned long attrs)
-+{
-+ if (arch_dma_ops->unmap_resource)
-+ arch_dma_ops->unmap_resource(dev, brcm_to_cpu(handle), size,
-+ dir, attrs);
-+}
-+
-+void brcm_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl,
-+ int nents, enum dma_data_direction dir)
-+{
-+ struct scatterlist *sg;
-+ int i;
-+
-+ for_each_sg(sgl, sg, nents, i)
-+ brcm_dma_ops_ptr->sync_single_for_cpu(dev, sg_dma_address(sg),
-+ sg->length, dir);
-+}
-+
-+void brcm_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
-+ int nents, enum dma_data_direction dir)
-+{
-+ struct scatterlist *sg;
-+ int i;
-+
-+ for_each_sg(sgl, sg, nents, i)
-+ brcm_dma_ops_ptr->sync_single_for_device(dev,
-+ sg_dma_address(sg),
-+ sg->length, dir);
-+}
-+
-+static int brcm_mapping_error(struct device *dev, dma_addr_t dma_addr)
-+{
-+ return arch_dma_ops->mapping_error(dev, dma_addr);
-+}
-+
-+static int brcm_dma_supported(struct device *dev, u64 mask)
-+{
-+ if (num_dma_ranges) {
-+ /*
-+ * It is our translated addresses that the EP will "see", so
-+ * we check all of the ranges for the largest possible value.
-+ */
-+ int i;
-+
-+ for (i = 0; i < num_dma_ranges; i++)
-+ if (dma_ranges[i].pci_addr + dma_ranges[i].size - 1
-+ > mask)
-+ return 0;
-+ return 1;
-+ }
-+
-+ return arch_dma_ops->dma_supported(dev, mask);
-+}
-+
-+#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
-+u64 brcm_get_required_mask)(struct device *dev)
-+{
-+ return arch_dma_ops->get_required_mask(dev);
-+}
-+#endif
-+
-+static const struct dma_map_ops brcm_dma_ops = {
-+ .alloc = brcm_alloc,
-+ .free = brcm_free,
-+ .mmap = brcm_mmap,
-+ .get_sgtable = brcm_get_sgtable,
-+ .map_page = brcm_map_page,
-+ .unmap_page = brcm_unmap_page,
-+ .map_sg = brcm_map_sg,
-+ .unmap_sg = brcm_unmap_sg,
-+ .map_resource = brcm_map_resource,
-+ .unmap_resource = brcm_unmap_resource,
-+ .sync_single_for_cpu = brcm_sync_single_for_cpu,
-+ .sync_single_for_device = brcm_sync_single_for_device,
-+ .sync_sg_for_cpu = brcm_sync_sg_for_cpu,
-+ .sync_sg_for_device = brcm_sync_sg_for_device,
-+ .mapping_error = brcm_mapping_error,
-+ .dma_supported = brcm_dma_supported,
-+#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
-+ .get_required_mask = brcm_get_required_mask,
-+#endif
-+};
-+
-+static void brcm_set_dma_ops(struct device *dev)
-+{
-+ int ret;
-+
-+ if (IS_ENABLED(CONFIG_ARM64)) {
-+ /*
-+ * We are going to invoke get_dma_ops(). That
-+ * function, at this point in time, invokes
-+ * get_arch_dma_ops(), and for ARM64 that function
-+ * returns a pointer to dummy_dma_ops. So then we'd
-+ * like to call arch_setup_dma_ops(), but that isn't
-+ * exported. Instead, we call of_dma_configure(),
-+ * which is exported, and this calls
-+ * arch_setup_dma_ops(). Once we do this the call to
-+ * get_dma_ops() will work properly because
-+ * dev->dma_ops will be set.
-+ */
-+ ret = of_dma_configure(dev, dev->of_node, true);
-+ if (ret) {
-+ dev_err(dev, "of_dma_configure() failed: %d\n", ret);
-+ return;
-+ }
-+ }
-+
-+ arch_dma_ops = get_dma_ops(dev);
-+ if (!arch_dma_ops) {
-+ dev_err(dev, "failed to get arch_dma_ops\n");
-+ return;
-+ }
-+
-+ set_dma_ops(dev, &brcm_dma_ops);
-+}
-+
-+static int brcmstb_platform_notifier(struct notifier_block *nb,
-+ unsigned long event, void *__dev)
-+{
-+ struct device *dev = __dev;
-+
-+ brcm_dma_ops_ptr = &brcm_dma_ops;
-+ if (event != BUS_NOTIFY_ADD_DEVICE)
-+ return NOTIFY_DONE;
-+
-+ brcm_set_dma_ops(dev);
-+ return NOTIFY_OK;
-+}
-+
-+static struct notifier_block brcmstb_platform_nb = {
-+ .notifier_call = brcmstb_platform_notifier,
-+};
-+
-+static int brcm_register_notifier(void)
-+{
-+ return bus_register_notifier(&pci_bus_type, &brcmstb_platform_nb);
-+}
-+
-+static int brcm_unregister_notifier(void)
-+{
-+ return bus_unregister_notifier(&pci_bus_type, &brcmstb_platform_nb);
-+}
-+
- static u32 rd_fld(void __iomem *p, u32 mask, int shift)
- {
- return (bcm_readl(p) & mask) >> shift;
-@@ -597,9 +894,71 @@ static inline void brcm_pcie_perst_set(s
- WR_FLD_RB(pcie->base, PCIE_MISC_PCIE_CTRL, PCIE_PERSTB, !val);
- }
-
-+static int pci_dma_range_parser_init(struct of_pci_range_parser *parser,
-+ struct device_node *node)
-+{
-+ const int na = 3, ns = 2;
-+ int rlen;
-+
-+ parser->node = node;
-+ parser->pna = of_n_addr_cells(node);
-+ parser->np = parser->pna + na + ns;
-+
-+ parser->range = of_get_property(node, "dma-ranges", &rlen);
-+ if (!parser->range)
-+ return -ENOENT;
-+
-+ parser->end = parser->range + rlen / sizeof(__be32);
-+
-+ return 0;
-+}
-+
-+static int brcm_pcie_parse_map_dma_ranges(struct brcm_pcie *pcie)
-+{
-+ int i;
-+ struct of_pci_range_parser parser;
-+ struct device_node *dn = pcie->dn;
-+
-+ /*
-+ * Parse dma-ranges property if present. If there are multiple
-+ * PCIe controllers, we only have to parse from one of them since
-+ * the others will have an identical mapping.
-+ */
-+ if (!pci_dma_range_parser_init(&parser, dn)) {
-+ unsigned int max_ranges
-+ = (parser.end - parser.range) / parser.np;
-+
-+ dma_ranges = kcalloc(max_ranges, sizeof(struct of_pci_range),
-+ GFP_KERNEL);
-+ if (!dma_ranges)
-+ return -ENOMEM;
-+
-+ for (i = 0; of_pci_range_parser_one(&parser, dma_ranges + i);
-+ i++)
-+ num_dma_ranges++;
-+ }
-+
-+ for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
-+ u64 size = brcmstb_memory_memc_size(i);
-+
-+ if (size == (u64)-1) {
-+ dev_err(pcie->dev, "cannot get memc%d size", i);
-+ return -EINVAL;
-+ } else if (size) {
-+ scb_size[i] = roundup_pow_of_two_64(size);
-+ num_memc++;
-+ } else {
-+ break;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
- static int brcm_pcie_add_controller(struct brcm_pcie *pcie)
- {
- int i, ret = 0;
-+ struct device *dev = pcie->dev;
-
- mutex_lock(&brcm_pcie_lock);
- if (num_pcie > 0) {
-@@ -607,12 +966,21 @@ static int brcm_pcie_add_controller(stru
- goto done;
- }
-
-+ ret = brcm_register_notifier();
-+ if (ret) {
-+ dev_err(dev, "failed to register pci bus notifier\n");
-+ goto done;
-+ }
-+ ret = brcm_pcie_parse_map_dma_ranges(pcie);
-+ if (ret)
-+ goto done;
-+
- /* Determine num_memc and their sizes */
- for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
- u64 size = brcmstb_memory_memc_size(i);
-
- if (size == (u64)-1) {
-- dev_err(pcie->dev, "cannot get memc%d size\n", i);
-+ dev_err(dev, "cannot get memc%d size\n", i);
- ret = -EINVAL;
- goto done;
- } else if (size) {
-@@ -636,8 +1004,16 @@ done:
- static void brcm_pcie_remove_controller(struct brcm_pcie *pcie)
- {
- mutex_lock(&brcm_pcie_lock);
-- if (--num_pcie == 0)
-- num_memc = 0;
-+ if (--num_pcie > 0)
-+ goto out;
-+
-+ if (brcm_unregister_notifier())
-+ dev_err(pcie->dev, "failed to unregister pci bus notifier\n");
-+ kfree(dma_ranges);
-+ dma_ranges = NULL;
-+ num_dma_ranges = 0;
-+ num_memc = 0;
-+out:
- mutex_unlock(&brcm_pcie_lock);
- }
-
-@@ -757,6 +1133,38 @@ static int brcm_pcie_setup(struct brcm_p
- */
- rc_bar2_offset = 0;
-
-+ if (dma_ranges) {
-+ /*
-+ * The best-case scenario is to place the inbound
-+ * region in the first 4GB of pci-space, as some
-+ * legacy devices can only address 32bits.
-+ * We would also like to put the MSI under 4GB
-+ * as well, since some devices require a 32bit
-+ * MSI target address.
-+ */
-+ if (total_mem_size <= 0xc0000000ULL &&
-+ rc_bar2_size <= 0x100000000ULL) {
-+ rc_bar2_offset = 0;
-+ } else {
-+ /*
-+ * The system memory is 4GB or larger so we
-+ * cannot start the inbound region at location
-+ * 0 (since we have to allow some space for
-+ * outbound memory @ 3GB). So instead we
-+ * start it at the 1x multiple of its size
-+ */
-+ rc_bar2_offset = rc_bar2_size;
-+ }
-+
-+ } else {
-+ /*
-+ * Set simple configuration based on memory sizes
-+ * only. We always start the viewport at address 0,
-+ * and set the MSI target address accordingly.
-+ */
-+ rc_bar2_offset = 0;
-+ }
-+
- tmp = lower_32_bits(rc_bar2_offset);
- tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
- encode_ibar_size(rc_bar2_size));
-@@ -967,7 +1375,6 @@ static int brcm_pcie_probe(struct platfo
- struct brcm_pcie *pcie;
- struct resource *res;
- void __iomem *base;
-- u32 tmp;
- struct pci_host_bridge *bridge;
- struct pci_bus *child;
-
-@@ -984,11 +1391,6 @@ static int brcm_pcie_probe(struct platfo
- return -EINVAL;
- }
-
-- if (of_property_read_u32(dn, "dma-ranges", &tmp) == 0) {
-- dev_err(&pdev->dev, "cannot yet handle dma-ranges\n");
-- return -EINVAL;
-- }
--
- data = of_id->data;
- pcie->reg_offsets = data->offsets;
- pcie->reg_field_info = data->reg_field_info;
--- /dev/null
+From 873462f7e2a67c2683c916612716b447b2f8f7d7 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 May 2019 15:47:42 +0100
+Subject: [PATCH 535/725] arm: bcm2835: DMA can only address 1GB
+
+The legacy peripherals can only address the first gigabyte of RAM, so
+ensure that DMA allocations are restricted to that region.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/mach-bcm/board_bcm2835.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/arch/arm/mach-bcm/board_bcm2835.c
++++ b/arch/arm/mach-bcm/board_bcm2835.c
+@@ -123,6 +123,9 @@ static const char * const bcm2835_compat
+ };
+
+ DT_MACHINE_START(BCM2835, "BCM2835")
++#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
++ .dma_zone_size = SZ_1G,
++#endif
+ .map_io = bcm2835_map_io,
+ .init_machine = bcm2835_init,
+ .dt_compat = bcm2835_compat,
+++ /dev/null
-From 17f152efa5b5c156df0ff918b38855a1b4efd1e9 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 19 Feb 2019 22:06:59 +0000
-Subject: [PATCH 536/703] PCI: brcmstb: Add MSI capability
-
-This commit adds MSI to the Broadcom STB PCIe host controller. It does
-not add MSIX since that functionality is not in the HW. The MSI
-controller is physically located within the PCIe block, however, there
-is no reason why the MSI controller could not be moved elsewhere in
-the future.
-
-Since the internal Brcmstb MSI controller is intertwined with the PCIe
-controller, it is not its own platform device but rather part of the
-PCIe platform device.
-
-Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
----
- drivers/pci/controller/pcie-brcmstb.c | 374 ++++++++++++++++++++++++--
- 1 file changed, 353 insertions(+), 21 deletions(-)
-
---- a/drivers/pci/controller/pcie-brcmstb.c
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -1,6 +1,7 @@
- // SPDX-License-Identifier: GPL-2.0
- /* Copyright (C) 2009 - 2017 Broadcom */
-
-+#include <linux/bitops.h>
- #include <linux/clk.h>
- #include <linux/compiler.h>
- #include <linux/delay.h>
-@@ -9,11 +10,13 @@
- #include <linux/interrupt.h>
- #include <linux/io.h>
- #include <linux/ioport.h>
-+#include <linux/irqchip/chained_irq.h>
- #include <linux/irqdomain.h>
- #include <linux/kernel.h>
- #include <linux/list.h>
- #include <linux/log2.h>
- #include <linux/module.h>
-+#include <linux/msi.h>
- #include <linux/of_address.h>
- #include <linux/of_irq.h>
- #include <linux/of_pci.h>
-@@ -47,6 +50,9 @@
- #define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034
- #define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038
- #define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
-+#define PCIE_MISC_MSI_BAR_CONFIG_LO 0x4044
-+#define PCIE_MISC_MSI_BAR_CONFIG_HI 0x4048
-+#define PCIE_MISC_MSI_DATA_CONFIG 0x404c
- #define PCIE_MISC_PCIE_CTRL 0x4064
- #define PCIE_MISC_PCIE_STATUS 0x4068
- #define PCIE_MISC_REVISION 0x406c
-@@ -55,6 +61,7 @@
- #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI 0x4084
- #define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204
- #define PCIE_INTR2_CPU_BASE 0x4300
-+#define PCIE_MSI_INTR2_BASE 0x4500
-
- /*
- * Broadcom Settop Box PCIe Register Field shift and mask info. The
-@@ -115,6 +122,8 @@
-
- #define BRCM_NUM_PCIE_OUT_WINS 0x4
- #define BRCM_MAX_SCB 0x4
-+#define BRCM_INT_PCI_MSI_NR 32
-+#define BRCM_PCIE_HW_REV_33 0x0303
-
- #define BRCM_MSI_TARGET_ADDR_LT_4GB 0x0fffffffcULL
- #define BRCM_MSI_TARGET_ADDR_GT_4GB 0xffffffffcULL
-@@ -203,6 +212,33 @@ struct brcm_window {
- dma_addr_t size;
- };
-
-+struct brcm_msi {
-+ struct device *dev;
-+ void __iomem *base;
-+ struct device_node *dn;
-+ struct irq_domain *msi_domain;
-+ struct irq_domain *inner_domain;
-+ struct mutex lock; /* guards the alloc/free operations */
-+ u64 target_addr;
-+ int irq;
-+
-+ /* intr_base is the base pointer for interrupt status/set/clr regs */
-+ void __iomem *intr_base;
-+
-+ /* intr_legacy_mask indicates how many bits are MSI interrupts */
-+ u32 intr_legacy_mask;
-+
-+ /*
-+ * intr_legacy_offset indicates bit position of MSI_01. It is
-+ * to map the register bit position to a hwirq that starts at 0.
-+ */
-+ u32 intr_legacy_offset;
-+
-+ /* used indicates which MSI interrupts have been alloc'd */
-+ unsigned long used;
-+ unsigned int rev;
-+};
-+
- /* Internal PCIe Host Controller Information.*/
- struct brcm_pcie {
- struct device *dev;
-@@ -217,7 +253,10 @@ struct brcm_pcie {
- int num_out_wins;
- bool ssc;
- int gen;
-+ u64 msi_target_addr;
- struct brcm_window out_wins[BRCM_NUM_PCIE_OUT_WINS];
-+ struct brcm_msi *msi;
-+ bool msi_internal;
- unsigned int rev;
- const int *reg_offsets;
- const int *reg_field_info;
-@@ -225,9 +264,9 @@ struct brcm_pcie {
- };
-
- struct pcie_cfg_data {
-- const int *reg_field_info;
-- const int *offsets;
-- const enum pcie_type type;
-+ const int *reg_field_info;
-+ const int *offsets;
-+ const enum pcie_type type;
- };
-
- static const int pcie_reg_field_info[] = {
-@@ -828,6 +867,267 @@ static void brcm_pcie_set_outbound_win(s
- }
- }
-
-+static struct irq_chip brcm_msi_irq_chip = {
-+ .name = "Brcm_MSI",
-+ .irq_mask = pci_msi_mask_irq,
-+ .irq_unmask = pci_msi_unmask_irq,
-+};
-+
-+static struct msi_domain_info brcm_msi_domain_info = {
-+ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
-+ MSI_FLAG_PCI_MSIX),
-+ .chip = &brcm_msi_irq_chip,
-+};
-+
-+static void brcm_pcie_msi_isr(struct irq_desc *desc)
-+{
-+ struct irq_chip *chip = irq_desc_get_chip(desc);
-+ struct brcm_msi *msi;
-+ unsigned long status, virq;
-+ u32 mask, bit, hwirq;
-+ struct device *dev;
-+
-+ chained_irq_enter(chip, desc);
-+ msi = irq_desc_get_handler_data(desc);
-+ mask = msi->intr_legacy_mask;
-+ dev = msi->dev;
-+
-+ while ((status = bcm_readl(msi->intr_base + STATUS) & mask)) {
-+ for_each_set_bit(bit, &status, BRCM_INT_PCI_MSI_NR) {
-+ /* clear the interrupt */
-+ bcm_writel(1 << bit, msi->intr_base + CLR);
-+
-+ /* Account for legacy interrupt offset */
-+ hwirq = bit - msi->intr_legacy_offset;
-+
-+ virq = irq_find_mapping(msi->inner_domain, hwirq);
-+ if (virq) {
-+ if (msi->used & (1 << hwirq))
-+ generic_handle_irq(virq);
-+ else
-+ dev_info(dev, "unhandled MSI %d\n",
-+ hwirq);
-+ } else {
-+ /* Unknown MSI, just clear it */
-+ dev_dbg(dev, "unexpected MSI\n");
-+ }
-+ }
-+ }
-+ chained_irq_exit(chip, desc);
-+}
-+
-+static void brcm_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
-+{
-+ struct brcm_msi *msi = irq_data_get_irq_chip_data(data);
-+ u32 temp;
-+
-+ msg->address_lo = lower_32_bits(msi->target_addr);
-+ msg->address_hi = upper_32_bits(msi->target_addr);
-+ temp = bcm_readl(msi->base + PCIE_MISC_MSI_DATA_CONFIG);
-+ msg->data = ((temp >> 16) & (temp & 0xffff)) | data->hwirq;
-+}
-+
-+static int brcm_msi_set_affinity(struct irq_data *irq_data,
-+ const struct cpumask *mask, bool force)
-+{
-+ return -EINVAL;
-+}
-+
-+static struct irq_chip brcm_msi_bottom_irq_chip = {
-+ .name = "Brcm_MSI",
-+ .irq_compose_msi_msg = brcm_compose_msi_msg,
-+ .irq_set_affinity = brcm_msi_set_affinity,
-+};
-+
-+static int brcm_msi_alloc(struct brcm_msi *msi)
-+{
-+ int bit, hwirq;
-+
-+ mutex_lock(&msi->lock);
-+ bit = ~msi->used ? ffz(msi->used) : -1;
-+
-+ if (bit >= 0 && bit < BRCM_INT_PCI_MSI_NR) {
-+ msi->used |= (1 << bit);
-+ hwirq = bit - msi->intr_legacy_offset;
-+ } else {
-+ hwirq = -ENOSPC;
-+ }
-+
-+ mutex_unlock(&msi->lock);
-+ return hwirq;
-+}
-+
-+static void brcm_msi_free(struct brcm_msi *msi, unsigned long hwirq)
-+{
-+ mutex_lock(&msi->lock);
-+ msi->used &= ~(1 << (hwirq + msi->intr_legacy_offset));
-+ mutex_unlock(&msi->lock);
-+}
-+
-+static int brcm_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
-+ unsigned int nr_irqs, void *args)
-+{
-+ struct brcm_msi *msi = domain->host_data;
-+ int hwirq;
-+
-+ hwirq = brcm_msi_alloc(msi);
-+
-+ if (hwirq < 0)
-+ return hwirq;
-+
-+ irq_domain_set_info(domain, virq, (irq_hw_number_t)hwirq,
-+ &brcm_msi_bottom_irq_chip, domain->host_data,
-+ handle_simple_irq, NULL, NULL);
-+ return 0;
-+}
-+
-+static void brcm_irq_domain_free(struct irq_domain *domain,
-+ unsigned int virq, unsigned int nr_irqs)
-+{
-+ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
-+ struct brcm_msi *msi = irq_data_get_irq_chip_data(d);
-+
-+ brcm_msi_free(msi, d->hwirq);
-+}
-+
-+static void brcm_msi_set_regs(struct brcm_msi *msi)
-+{
-+ u32 data_val, msi_lo, msi_hi;
-+
-+ if (msi->rev >= BRCM_PCIE_HW_REV_33) {
-+ /*
-+ * ffe0 -- least sig 5 bits are 0 indicating 32 msgs
-+ * 6540 -- this is our arbitrary unique data value
-+ */
-+ data_val = 0xffe06540;
-+ } else {
-+ /*
-+ * fff8 -- least sig 3 bits are 0 indicating 8 msgs
-+ * 6540 -- this is our arbitrary unique data value
-+ */
-+ data_val = 0xfff86540;
-+ }
-+
-+ /*
-+ * Make sure we are not masking MSIs. Note that MSIs can be masked,
-+ * but that occurs on the PCIe EP device
-+ */
-+ bcm_writel(0xffffffff & msi->intr_legacy_mask,
-+ msi->intr_base + MASK_CLR);
-+
-+ msi_lo = lower_32_bits(msi->target_addr);
-+ msi_hi = upper_32_bits(msi->target_addr);
-+ /*
-+ * The 0 bit of PCIE_MISC_MSI_BAR_CONFIG_LO is repurposed to MSI
-+ * enable, which we set to 1.
-+ */
-+ bcm_writel(msi_lo | 1, msi->base + PCIE_MISC_MSI_BAR_CONFIG_LO);
-+ bcm_writel(msi_hi, msi->base + PCIE_MISC_MSI_BAR_CONFIG_HI);
-+ bcm_writel(data_val, msi->base + PCIE_MISC_MSI_DATA_CONFIG);
-+}
-+
-+static const struct irq_domain_ops msi_domain_ops = {
-+ .alloc = brcm_irq_domain_alloc,
-+ .free = brcm_irq_domain_free,
-+};
-+
-+static int brcm_allocate_domains(struct brcm_msi *msi)
-+{
-+ struct fwnode_handle *fwnode = of_node_to_fwnode(msi->dn);
-+ struct device *dev = msi->dev;
-+
-+ msi->inner_domain = irq_domain_add_linear(NULL, BRCM_INT_PCI_MSI_NR,
-+ &msi_domain_ops, msi);
-+ if (!msi->inner_domain) {
-+ dev_err(dev, "failed to create IRQ domain\n");
-+ return -ENOMEM;
-+ }
-+
-+ msi->msi_domain = pci_msi_create_irq_domain(fwnode,
-+ &brcm_msi_domain_info,
-+ msi->inner_domain);
-+ if (!msi->msi_domain) {
-+ dev_err(dev, "failed to create MSI domain\n");
-+ irq_domain_remove(msi->inner_domain);
-+ return -ENOMEM;
-+ }
-+
-+ return 0;
-+}
-+
-+static void brcm_free_domains(struct brcm_msi *msi)
-+{
-+ irq_domain_remove(msi->msi_domain);
-+ irq_domain_remove(msi->inner_domain);
-+}
-+
-+static void brcm_msi_remove(struct brcm_pcie *pcie)
-+{
-+ struct brcm_msi *msi = pcie->msi;
-+
-+ if (!msi)
-+ return;
-+ irq_set_chained_handler(msi->irq, NULL);
-+ irq_set_handler_data(msi->irq, NULL);
-+ brcm_free_domains(msi);
-+}
-+
-+static int brcm_pcie_enable_msi(struct brcm_pcie *pcie)
-+{
-+ struct brcm_msi *msi;
-+ int irq, ret;
-+ struct device *dev = pcie->dev;
-+
-+ irq = irq_of_parse_and_map(dev->of_node, 1);
-+ if (irq <= 0) {
-+ dev_err(dev, "cannot map msi intr\n");
-+ return -ENODEV;
-+ }
-+
-+ msi = devm_kzalloc(dev, sizeof(struct brcm_msi), GFP_KERNEL);
-+ if (!msi)
-+ return -ENOMEM;
-+
-+ msi->dev = dev;
-+ msi->base = pcie->base;
-+ msi->rev = pcie->rev;
-+ msi->dn = pcie->dn;
-+ msi->target_addr = pcie->msi_target_addr;
-+ msi->irq = irq;
-+
-+ ret = brcm_allocate_domains(msi);
-+ if (ret)
-+ return ret;
-+
-+ irq_set_chained_handler_and_data(msi->irq, brcm_pcie_msi_isr, msi);
-+
-+ if (msi->rev >= BRCM_PCIE_HW_REV_33) {
-+ msi->intr_base = msi->base + PCIE_MSI_INTR2_BASE;
-+ /*
-+ * This version of PCIe hw has only 32 intr bits
-+ * starting at bit position 0.
-+ */
-+ msi->intr_legacy_mask = 0xffffffff;
-+ msi->intr_legacy_offset = 0x0;
-+ msi->used = 0x0;
-+
-+ } else {
-+ msi->intr_base = msi->base + PCIE_INTR2_CPU_BASE;
-+ /*
-+ * This version of PCIe hw has only 8 intr bits starting
-+ * at bit position 24.
-+ */
-+ msi->intr_legacy_mask = 0xff000000;
-+ msi->intr_legacy_offset = 24;
-+ msi->used = 0x00ffffff;
-+ }
-+
-+ brcm_msi_set_regs(msi);
-+ pcie->msi = msi;
-+
-+ return 0;
-+}
-+
- /* Configuration space read/write support */
- static int cfg_index(int busnr, int devfn, int reg)
- {
-@@ -1072,6 +1372,7 @@ static int brcm_pcie_setup(struct brcm_p
- u16 nlw, cls, lnksta;
- bool ssc_good = false;
- struct device *dev = pcie->dev;
-+ u64 msi_target_addr;
-
- /* Reset the bridge */
- brcm_pcie_bridge_sw_init_set(pcie, 1);
-@@ -1116,27 +1417,24 @@ static int brcm_pcie_setup(struct brcm_p
- * The PCIe host controller by design must set the inbound
- * viewport to be a contiguous arrangement of all of the
- * system's memory. In addition, its size mut be a power of
-- * two. To further complicate matters, the viewport must
-- * start on a pcie-address that is aligned on a multiple of its
-- * size. If a portion of the viewport does not represent
-- * system memory -- e.g. 3GB of memory requires a 4GB viewport
-- * -- we can map the outbound memory in or after 3GB and even
-- * though the viewport will overlap the outbound memory the
-- * controller will know to send outbound memory downstream and
-- * everything else upstream.
-+ * two. Further, the MSI target address must NOT be placed
-+ * inside this region, as the decoding logic will consider its
-+ * address to be inbound memory traffic. To further
-+ * complicate matters, the viewport must start on a
-+ * pcie-address that is aligned on a multiple of its size.
-+ * If a portion of the viewport does not represent system
-+ * memory -- e.g. 3GB of memory requires a 4GB viewport --
-+ * we can map the outbound memory in or after 3GB and even
-+ * though the viewport will overlap the outbound memory
-+ * the controller will know to send outbound memory downstream
-+ * and everything else upstream.
- */
- rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
-
-- /*
-- * Set simple configuration based on memory sizes
-- * only. We always start the viewport at address 0.
-- */
-- rc_bar2_offset = 0;
--
- if (dma_ranges) {
- /*
- * The best-case scenario is to place the inbound
-- * region in the first 4GB of pci-space, as some
-+ * region in the first 4GB of pcie-space, as some
- * legacy devices can only address 32bits.
- * We would also like to put the MSI under 4GB
- * as well, since some devices require a 32bit
-@@ -1145,6 +1443,14 @@ static int brcm_pcie_setup(struct brcm_p
- if (total_mem_size <= 0xc0000000ULL &&
- rc_bar2_size <= 0x100000000ULL) {
- rc_bar2_offset = 0;
-+ /* If the viewport is less then 4GB we can fit
-+ * the MSI target address under 4GB. Otherwise
-+ * put it right below 64GB.
-+ */
-+ msi_target_addr =
-+ (rc_bar2_size == 0x100000000ULL)
-+ ? BRCM_MSI_TARGET_ADDR_GT_4GB
-+ : BRCM_MSI_TARGET_ADDR_LT_4GB;
- } else {
- /*
- * The system memory is 4GB or larger so we
-@@ -1154,8 +1460,12 @@ static int brcm_pcie_setup(struct brcm_p
- * start it at the 1x multiple of its size
- */
- rc_bar2_offset = rc_bar2_size;
-- }
-
-+ /* Since we are starting the viewport at 4GB or
-+ * higher, put the MSI target address below 4GB
-+ */
-+ msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
-+ }
- } else {
- /*
- * Set simple configuration based on memory sizes
-@@ -1163,7 +1473,12 @@ static int brcm_pcie_setup(struct brcm_p
- * and set the MSI target address accordingly.
- */
- rc_bar2_offset = 0;
-+
-+ msi_target_addr = (rc_bar2_size >= 0x100000000ULL)
-+ ? BRCM_MSI_TARGET_ADDR_GT_4GB
-+ : BRCM_MSI_TARGET_ADDR_LT_4GB;
- }
-+ pcie->msi_target_addr = msi_target_addr;
-
- tmp = lower_32_bits(rc_bar2_offset);
- tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
-@@ -1333,6 +1648,9 @@ static int brcm_pcie_resume(struct devic
- if (ret)
- return ret;
-
-+ if (pcie->msi && pcie->msi_internal)
-+ brcm_msi_set_regs(pcie->msi);
-+
- pcie->suspended = false;
-
- return 0;
-@@ -1340,6 +1658,7 @@ static int brcm_pcie_resume(struct devic
-
- static void _brcm_pcie_remove(struct brcm_pcie *pcie)
- {
-+ brcm_msi_remove(pcie);
- turn_off(pcie);
- clk_disable_unprepare(pcie->clk);
- clk_put(pcie->clk);
-@@ -1368,7 +1687,7 @@ MODULE_DEVICE_TABLE(of, brcm_pcie_match)
-
- static int brcm_pcie_probe(struct platform_device *pdev)
- {
-- struct device_node *dn = pdev->dev.of_node;
-+ struct device_node *dn = pdev->dev.of_node, *msi_dn;
- const struct of_device_id *of_id;
- const struct pcie_cfg_data *data;
- int ret;
-@@ -1448,6 +1767,20 @@ static int brcm_pcie_probe(struct platfo
- if (ret)
- goto fail;
-
-+ msi_dn = of_parse_phandle(pcie->dn, "msi-parent", 0);
-+ /* Use the internal MSI if no msi-parent property */
-+ if (!msi_dn)
-+ msi_dn = pcie->dn;
-+
-+ if (pci_msi_enabled() && msi_dn == pcie->dn) {
-+ ret = brcm_pcie_enable_msi(pcie);
-+ if (ret)
-+ dev_err(pcie->dev,
-+ "probe of internal MSI failed: %d)", ret);
-+ else
-+ pcie->msi_internal = true;
-+ }
-+
- list_splice_init(&pcie->resources, &bridge->windows);
- bridge->dev.parent = &pdev->dev;
- bridge->busnr = 0;
-@@ -1470,7 +1803,6 @@ static int brcm_pcie_probe(struct platfo
- pcie->root_bus = bridge->bus;
-
- return 0;
--
- fail:
- _brcm_pcie_remove(pcie);
- return ret;
--- /dev/null
+From beea04563e4d7df06d5cec9bae2171e7eca643b1 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 Aug 2018 09:05:15 +0100
+Subject: [PATCH 536/725] mmc: bcm2835-sdhost: Support 64-bit physical
+ addresses
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/mmc/host/bcm2835-sdhost.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/mmc/host/bcm2835-sdhost.c
++++ b/drivers/mmc/host/bcm2835-sdhost.c
+@@ -148,7 +148,7 @@ struct bcm2835_host {
+ spinlock_t lock;
+
+ void __iomem *ioaddr;
+- u32 bus_addr;
++ phys_addr_t bus_addr;
+
+ struct mmc_host *mmc;
+
+@@ -246,8 +246,8 @@ static void log_init(struct device *dev,
+ sdhost_log_buf = dma_zalloc_coherent(dev, LOG_SIZE, &sdhost_log_addr,
+ GFP_KERNEL);
+ if (sdhost_log_buf) {
+- pr_info("sdhost: log_buf @ %p (%x)\n",
+- sdhost_log_buf, (u32)sdhost_log_addr);
++ pr_info("sdhost: log_buf @ %p (%llx)\n",
++ sdhost_log_buf, (u64)sdhost_log_addr);
+ timer_base = ioremap_nocache(bus_to_phys + 0x7e003000, SZ_4K);
+ if (!timer_base)
+ pr_err("sdhost: failed to remap timer\n");
+@@ -2024,6 +2024,7 @@ static int bcm2835_sdhost_probe(struct p
+ struct mmc_host *mmc;
+ const __be32 *addr;
+ u32 msg[3];
++ int na;
+ int ret;
+
+ pr_debug("bcm2835_sdhost_probe\n");
+@@ -2047,12 +2048,13 @@ static int bcm2835_sdhost_probe(struct p
+ goto err;
+ }
+
++ na = of_n_addr_cells(node);
+ addr = of_get_address(node, 0, NULL, NULL);
+ if (!addr) {
+ dev_err(dev, "could not get DMA-register address\n");
+ return -ENODEV;
+ }
+- host->bus_addr = be32_to_cpup(addr);
++ host->bus_addr = (phys_addr_t)of_read_number(addr, na);
+ pr_debug(" - ioaddr %lx, iomem->start %lx, bus_addr %lx\n",
+ (unsigned long)host->ioaddr,
+ (unsigned long)iomem->start,
+++ /dev/null
-From ed5b4725bde9d0067ac2a1098756ff5abfa13798 Mon Sep 17 00:00:00 2001
-From: Jim Quinlan <jim2101024@gmail.com>
-Date: Mon, 15 Jan 2018 18:28:39 -0500
-Subject: [PATCH 537/703] dt-bindings: pci: Add DT docs for Brcmstb PCIe device
-
-The DT bindings description of the Brcmstb PCIe device is described. This
-node can be used by almost all Broadcom settop box chips, using
-ARM, ARM64, or MIPS CPU architectures.
-
-Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
----
- .../devicetree/bindings/pci/brcmstb-pcie.txt | 59 +++++++++++++++++++
- 1 file changed, 59 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/pci/brcmstb-pcie.txt
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/pci/brcmstb-pcie.txt
-@@ -0,0 +1,59 @@
-+Brcmstb PCIe Host Controller Device Tree Bindings
-+
-+Required Properties:
-+- compatible
-+ "brcm,bcm7425-pcie" -- for 7425 family MIPS-based SOCs.
-+ "brcm,bcm7435-pcie" -- for 7435 family MIPS-based SOCs.
-+ "brcm,bcm7445-pcie" -- for 7445 and later ARM based SOCs (not including
-+ the 7278).
-+ "brcm,bcm7278-pcie" -- for 7278 family ARM-based SOCs.
-+
-+- reg -- the register start address and length for the PCIe reg block.
-+- interrupts -- two interrupts are specified; the first interrupt is for
-+ the PCI host controller and the second is for MSI if the built-in
-+ MSI controller is to be used.
-+- interrupt-names -- names of the interrupts (above): "pcie" and "msi".
-+- #address-cells -- set to <3>.
-+- #size-cells -- set to <2>.
-+- #interrupt-cells: set to <1>.
-+- interrupt-map-mask and interrupt-map, standard PCI properties to define the
-+ mapping of the PCIe interface to interrupt numbers.
-+- ranges: ranges for the PCI memory and I/O regions.
-+- linux,pci-domain -- should be unique per host controller.
-+
-+Optional Properties:
-+- clocks -- phandle of pcie clock.
-+- clock-names -- set to "sw_pcie" if clocks is used.
-+- dma-ranges -- Specifies the inbound memory mapping regions when
-+ an "identity map" is not possible.
-+- msi-controller -- this property is typically specified to have the
-+ PCIe controller use its internal MSI controller.
-+- msi-parent -- set to use an external MSI interrupt controller.
-+- brcm,enable-ssc -- (boolean) indicates usage of spread-spectrum clocking.
-+- max-link-speed -- (integer) indicates desired generation of link:
-+ 1 => 2.5 Gbps (gen1), 2 => 5.0 Gbps (gen2), 3 => 8.0 Gbps (gen3).
-+
-+Example Node:
-+
-+pcie0: pcie@f0460000 {
-+ reg = <0x0 0xf0460000 0x0 0x9310>;
-+ interrupts = <0x0 0x0 0x4>;
-+ compatible = "brcm,bcm7445-pcie";
-+ #address-cells = <3>;
-+ #size-cells = <2>;
-+ ranges = <0x02000000 0x00000000 0x00000000 0x00000000 0xc0000000 0x00000000 0x08000000
-+ 0x02000000 0x00000000 0x08000000 0x00000000 0xc8000000 0x00000000 0x08000000>;
-+ #interrupt-cells = <1>;
-+ interrupt-map-mask = <0 0 0 7>;
-+ interrupt-map = <0 0 0 1 &intc 0 47 3
-+ 0 0 0 2 &intc 0 48 3
-+ 0 0 0 3 &intc 0 49 3
-+ 0 0 0 4 &intc 0 50 3>;
-+ clocks = <&sw_pcie0>;
-+ clock-names = "sw_pcie";
-+ msi-parent = <&pcie0>; /* use PCIe's internal MSI controller */
-+ msi-controller; /* use PCIe's internal MSI controller */
-+ brcm,ssc;
-+ max-link-speed = <1>;
-+ linux,pci-domain = <0>;
-+ };
--- /dev/null
+From b0aa16d75f422fb369696520189c9fa7b0b12e60 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 28 Sep 2018 16:24:05 +0100
+Subject: [PATCH 537/725] mmc: sdhci: Mask "spurious" interrupts
+
+Add a filter for "spurious" Transfer Complete interrupts, attempting
+to make it as specific as possible:
+* INT_DATA_END (transfer complete) is set
+* There is a stop command in progress
+* There is no data transfer in progress
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/mmc/host/sdhci.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -2930,6 +2930,10 @@ static irqreturn_t sdhci_irq(int irq, vo
+ result = IRQ_WAKE_THREAD;
+ }
+
++ if ((intmask & SDHCI_INT_DATA_END) && !host->data &&
++ host->cmd && (host->cmd == host->cmd->mrq->stop))
++ intmask &= ~SDHCI_INT_DATA_END;
++
+ if (intmask & SDHCI_INT_CMD_MASK)
+ sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, &intmask);
+
--- /dev/null
+From 1224508f6ea00a9f730d394cf5f482acccbb9e88 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sat, 27 Apr 2019 12:33:57 +0200
+Subject: [PATCH 538/725] mmc: sdhci-iproc: Add support for emmc2 of the
+ BCM2838
+
+The emmc2 interface of the BCM2838 should be integrated in sdhci-iproc
+to avoid code redundancy. Except 32 bit only access no other quirks are
+known yet. Add an additional compatible string for upstream proposal.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ drivers/mmc/host/sdhci-iproc.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/mmc/host/sdhci-iproc.c
++++ b/drivers/mmc/host/sdhci-iproc.c
+@@ -250,8 +250,18 @@ static const struct sdhci_iproc_data bcm
+ .mmc_caps = 0x00000000,
+ };
+
++static const struct sdhci_pltfm_data sdhci_bcm2838_pltfm_data = {
++ .ops = &sdhci_iproc_32only_ops,
++};
++
++static const struct sdhci_iproc_data bcm2838_data = {
++ .pdata = &sdhci_bcm2838_pltfm_data,
++};
++
+ static const struct of_device_id sdhci_iproc_of_match[] = {
+ { .compatible = "brcm,bcm2835-sdhci", .data = &bcm2835_data },
++ { .compatible = "brcm,bcm2838-sdhci", .data = &bcm2838_data },
++ { .compatible = "brcm,bcm2711-emmc2", .data = &bcm2838_data },
+ { .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_cygnus_data},
+ { .compatible = "brcm,sdhci-iproc", .data = &iproc_data },
+ { }
+++ /dev/null
-From 20675667235d3f454db422f8fbc296605195647e Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 19 Feb 2019 22:06:59 +0000
-Subject: [PATCH 538/703] pcie-brcmstb: Changes for BCM2711
-
-The initial brcmstb PCIe driver - originally taken from the V3(?)
-patch set - has been modified significantly for the BCM2711.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/dma/bcm2835-dma.c | 107 ++++
- drivers/pci/controller/Makefile | 4 +
- drivers/pci/controller/pcie-brcmstb-bounce.c | 564 +++++++++++++++++++
- drivers/pci/controller/pcie-brcmstb-bounce.h | 32 ++
- drivers/pci/controller/pcie-brcmstb.c | 237 ++++----
- drivers/soc/bcm/brcmstb/Makefile | 2 +-
- drivers/soc/bcm/brcmstb/memory.c | 158 ++++++
- 7 files changed, 996 insertions(+), 108 deletions(-)
- create mode 100644 drivers/pci/controller/pcie-brcmstb-bounce.c
- create mode 100644 drivers/pci/controller/pcie-brcmstb-bounce.h
- create mode 100644 drivers/soc/bcm/brcmstb/memory.c
-
---- a/drivers/dma/bcm2835-dma.c
-+++ b/drivers/dma/bcm2835-dma.c
-@@ -68,6 +68,17 @@ struct bcm2835_dma_cb {
- uint32_t pad[2];
- };
-
-+struct bcm2838_dma40_scb {
-+ uint32_t ti;
-+ uint32_t src;
-+ uint32_t srci;
-+ uint32_t dst;
-+ uint32_t dsti;
-+ uint32_t len;
-+ uint32_t next_cb;
-+ uint32_t rsvd;
-+};
-+
- struct bcm2835_cb_entry {
- struct bcm2835_dma_cb *cb;
- dma_addr_t paddr;
-@@ -185,6 +196,45 @@ struct bcm2835_desc {
- #define MAX_DMA_LEN SZ_1G
- #define MAX_LITE_DMA_LEN (SZ_64K - 4)
-
-+/* 40-bit DMA support */
-+#define BCM2838_DMA40_CS 0x00
-+#define BCM2838_DMA40_CB 0x04
-+#define BCM2838_DMA40_DEBUG 0x0c
-+#define BCM2858_DMA40_TI 0x10
-+#define BCM2838_DMA40_SRC 0x14
-+#define BCM2838_DMA40_SRCI 0x18
-+#define BCM2838_DMA40_DEST 0x1c
-+#define BCM2838_DMA40_DESTI 0x20
-+#define BCM2838_DMA40_LEN 0x24
-+#define BCM2838_DMA40_NEXT_CB 0x28
-+#define BCM2838_DMA40_DEBUG2 0x2c
-+
-+#define BCM2838_DMA40_CS_ACTIVE BIT(0)
-+#define BCM2838_DMA40_CS_END BIT(1)
-+
-+#define BCM2838_DMA40_CS_QOS(x) (((x) & 0x1f) << 16)
-+#define BCM2838_DMA40_CS_PANIC_QOS(x) (((x) & 0x1f) << 20)
-+#define BCM2838_DMA40_CS_WRITE_WAIT BIT(28)
-+
-+#define BCM2838_DMA40_BURST_LEN(x) ((((x) - 1) & 0xf) << 8)
-+#define BCM2838_DMA40_INC BIT(12)
-+#define BCM2838_DMA40_SIZE_128 (2 << 13)
-+
-+#define BCM2838_DMA40_MEMCPY_QOS \
-+ (BCM2838_DMA40_CS_QOS(0x0) | \
-+ BCM2838_DMA40_CS_PANIC_QOS(0x0) | \
-+ BCM2838_DMA40_CS_WRITE_WAIT)
-+
-+#define BCM2838_DMA40_MEMCPY_XFER_INFO \
-+ (BCM2838_DMA40_SIZE_128 | \
-+ BCM2838_DMA40_INC | \
-+ BCM2838_DMA40_BURST_LEN(16))
-+
-+static void __iomem *memcpy_chan;
-+static struct bcm2838_dma40_scb *memcpy_scb;
-+static dma_addr_t memcpy_scb_dma;
-+DEFINE_SPINLOCK(memcpy_lock);
-+
- static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c)
- {
- /* lite and normal channels have different max frame length */
-@@ -868,6 +918,56 @@ static void bcm2835_dma_free(struct bcm2
- }
- }
-
-+int bcm2838_dma40_memcpy_init(struct device *dev)
-+{
-+ if (memcpy_scb)
-+ return 0;
-+
-+ memcpy_scb = dma_alloc_coherent(dev, sizeof(*memcpy_scb),
-+ &memcpy_scb_dma, GFP_KERNEL);
-+
-+ if (!memcpy_scb) {
-+ pr_err("bcm2838_dma40_memcpy_init failed!\n");
-+ return -ENOMEM;
-+ }
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(bcm2838_dma40_memcpy_init);
-+
-+void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size)
-+{
-+ struct bcm2838_dma40_scb *scb = memcpy_scb;
-+ unsigned long flags;
-+
-+ if (!scb) {
-+ pr_err("bcm2838_dma40_memcpy not initialised!\n");
-+ return;
-+ }
-+
-+ spin_lock_irqsave(&memcpy_lock, flags);
-+
-+ scb->ti = 0;
-+ scb->src = lower_32_bits(src);
-+ scb->srci = upper_32_bits(src) | BCM2838_DMA40_MEMCPY_XFER_INFO;
-+ scb->dst = lower_32_bits(dst);
-+ scb->dsti = upper_32_bits(dst) | BCM2838_DMA40_MEMCPY_XFER_INFO;
-+ scb->len = size;
-+ scb->next_cb = 0;
-+
-+ writel((u32)(memcpy_scb_dma >> 5), memcpy_chan + BCM2838_DMA40_CB);
-+ writel(BCM2838_DMA40_MEMCPY_QOS + BCM2838_DMA40_CS_ACTIVE,
-+ memcpy_chan + BCM2838_DMA40_CS);
-+ /* Poll for completion */
-+ while (!(readl(memcpy_chan + BCM2838_DMA40_CS) & BCM2838_DMA40_CS_END))
-+ cpu_relax();
-+
-+ writel(BCM2838_DMA40_CS_END, memcpy_chan + BCM2838_DMA40_CS);
-+
-+ spin_unlock_irqrestore(&memcpy_lock, flags);
-+}
-+EXPORT_SYMBOL(bcm2838_dma40_memcpy);
-+
- static const struct of_device_id bcm2835_dma_of_match[] = {
- { .compatible = "brcm,bcm2835-dma", },
- {},
-@@ -964,6 +1064,13 @@ static int bcm2835_dma_probe(struct plat
- /* Channel 0 is used by the legacy API */
- chans_available &= ~BCM2835_DMA_BULK_MASK;
-
-+ /* We can't use channels 11-13 yet */
-+ chans_available &= ~(BIT(11) | BIT(12) | BIT(13));
-+
-+ /* Grab channel 14 for the 40-bit DMA memcpy */
-+ chans_available &= ~BIT(14);
-+ memcpy_chan = BCM2835_DMA_CHANIO(base, 14);
-+
- /* get irqs for each channel that we support */
- for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
- /* skip masked out channels */
---- a/drivers/pci/controller/Makefile
-+++ b/drivers/pci/controller/Makefile
-@@ -29,6 +29,10 @@ obj-$(CONFIG_PCIE_MEDIATEK) += pcie-medi
- obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
- obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
- obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
-+ifdef CONFIG_ARM
-+obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb-bounce.o
-+endif
-+
- obj-$(CONFIG_VMD) += vmd.o
- # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
- obj-y += dwc/
---- /dev/null
-+++ b/drivers/pci/controller/pcie-brcmstb-bounce.c
-@@ -0,0 +1,564 @@
-+/*
-+ * This code started out as a version of arch/arm/common/dmabounce.c,
-+ * modified to cope with highmem pages. Now it has been changed heavily -
-+ * it now preallocates a large block (currently 4MB) and carves it up
-+ * sequentially in ring fashion, and DMA is used to copy the data - to the
-+ * point where very little of the original remains.
-+ *
-+ * Copyright (C) 2019 Raspberry Pi (Trading) Ltd.
-+ *
-+ * Original version by Brad Parker (brad@heeltoe.com)
-+ * Re-written by Christopher Hoover <ch@murgatroid.com>
-+ * Made generic by Deepak Saxena <dsaxena@plexity.net>
-+ *
-+ * Copyright (C) 2002 Hewlett Packard Company.
-+ * Copyright (C) 2004 MontaVista Software, 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 <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/page-flags.h>
-+#include <linux/device.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/dmapool.h>
-+#include <linux/list.h>
-+#include <linux/scatterlist.h>
-+#include <linux/bitmap.h>
-+
-+#include <asm/cacheflush.h>
-+#include <asm/dma-iommu.h>
-+
-+#define STATS
-+
-+#ifdef STATS
-+#define DO_STATS(X) do { X ; } while (0)
-+#else
-+#define DO_STATS(X) do { } while (0)
-+#endif
-+
-+/* ************************************************** */
-+
-+struct safe_buffer {
-+ struct list_head node;
-+
-+ /* original request */
-+ size_t size;
-+ int direction;
-+
-+ struct dmabounce_pool *pool;
-+ void *safe;
-+ dma_addr_t unsafe_dma_addr;
-+ dma_addr_t safe_dma_addr;
-+};
-+
-+struct dmabounce_pool {
-+ unsigned long pages;
-+ void *virt_addr;
-+ dma_addr_t dma_addr;
-+ unsigned long *alloc_map;
-+ unsigned long alloc_pos;
-+ spinlock_t lock;
-+ struct device *dev;
-+ unsigned long num_pages;
-+#ifdef STATS
-+ size_t max_size;
-+ unsigned long num_bufs;
-+ unsigned long max_bufs;
-+ unsigned long max_pages;
-+#endif
-+};
-+
-+struct dmabounce_device_info {
-+ struct device *dev;
-+ dma_addr_t threshold;
-+ struct list_head safe_buffers;
-+ struct dmabounce_pool pool;
-+ rwlock_t lock;
-+#ifdef STATS
-+ unsigned long map_count;
-+ unsigned long unmap_count;
-+ unsigned long sync_dev_count;
-+ unsigned long sync_cpu_count;
-+ unsigned long fail_count;
-+ int attr_res;
-+#endif
-+};
-+
-+static struct dmabounce_device_info *g_dmabounce_device_info;
-+
-+extern int bcm2838_dma40_memcpy_init(struct device *dev);
-+extern void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size);
-+
-+#ifdef STATS
-+static ssize_t
-+bounce_show(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+ struct dmabounce_device_info *device_info = g_dmabounce_device_info;
-+ return sprintf(buf, "m:%lu/%lu s:%lu/%lu f:%lu s:%zu b:%lu/%lu a:%lu/%lu\n",
-+ device_info->map_count,
-+ device_info->unmap_count,
-+ device_info->sync_dev_count,
-+ device_info->sync_cpu_count,
-+ device_info->fail_count,
-+ device_info->pool.max_size,
-+ device_info->pool.num_bufs,
-+ device_info->pool.max_bufs,
-+ device_info->pool.num_pages * PAGE_SIZE,
-+ device_info->pool.max_pages * PAGE_SIZE);
-+}
-+
-+static DEVICE_ATTR(dmabounce_stats, 0444, bounce_show, NULL);
-+#endif
-+
-+static int bounce_create(struct dmabounce_pool *pool, struct device *dev,
-+ unsigned long buffer_size)
-+{
-+ int ret = -ENOMEM;
-+ pool->pages = (buffer_size + PAGE_SIZE - 1)/PAGE_SIZE;
-+ pool->alloc_map = bitmap_zalloc(pool->pages, GFP_KERNEL);
-+ if (!pool->alloc_map)
-+ goto err_bitmap;
-+ pool->virt_addr = dma_alloc_coherent(dev, pool->pages * PAGE_SIZE,
-+ &pool->dma_addr, GFP_KERNEL);
-+ if (!pool->virt_addr)
-+ goto err_dmabuf;
-+
-+ pool->alloc_pos = 0;
-+ spin_lock_init(&pool->lock);
-+ pool->dev = dev;
-+ pool->num_pages = 0;
-+
-+ DO_STATS(pool->max_size = 0);
-+ DO_STATS(pool->num_bufs = 0);
-+ DO_STATS(pool->max_bufs = 0);
-+ DO_STATS(pool->max_pages = 0);
-+
-+ return 0;
-+
-+err_dmabuf:
-+ bitmap_free(pool->alloc_map);
-+err_bitmap:
-+ return ret;
-+}
-+
-+static void bounce_destroy(struct dmabounce_pool *pool)
-+{
-+ dma_free_coherent(pool->dev, pool->pages * PAGE_SIZE, pool->virt_addr,
-+ pool->dma_addr);
-+
-+ bitmap_free(pool->alloc_map);
-+}
-+
-+static void *bounce_alloc(struct dmabounce_pool *pool, size_t size,
-+ dma_addr_t *dmaaddrp)
-+{
-+ unsigned long pages;
-+ unsigned long flags;
-+ unsigned long pos;
-+
-+ pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
-+
-+ DO_STATS(pool->max_size = max(size, pool->max_size));
-+
-+ spin_lock_irqsave(&pool->lock, flags);
-+ pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
-+ pool->alloc_pos, pages, 0);
-+ /* If not found, try from the start */
-+ if (pos >= pool->pages && pool->alloc_pos)
-+ pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
-+ 0, pages, 0);
-+
-+ if (pos >= pool->pages) {
-+ spin_unlock_irqrestore(&pool->lock, flags);
-+ return NULL;
-+ }
-+
-+ bitmap_set(pool->alloc_map, pos, pages);
-+ pool->alloc_pos = (pos + pages) % pool->pages;
-+ pool->num_pages += pages;
-+
-+ DO_STATS(pool->num_bufs++);
-+ DO_STATS(pool->max_bufs = max(pool->num_bufs, pool->max_bufs));
-+ DO_STATS(pool->max_pages = max(pool->num_pages, pool->max_pages));
-+
-+ spin_unlock_irqrestore(&pool->lock, flags);
-+
-+ *dmaaddrp = pool->dma_addr + pos * PAGE_SIZE;
-+
-+ return pool->virt_addr + pos * PAGE_SIZE;
-+}
-+
-+static void
-+bounce_free(struct dmabounce_pool *pool, void *buf, size_t size)
-+{
-+ unsigned long pages;
-+ unsigned long flags;
-+ unsigned long pos;
-+
-+ pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
-+ pos = (buf - pool->virt_addr)/PAGE_SIZE;
-+
-+ BUG_ON((buf - pool->virt_addr) & (PAGE_SIZE - 1));
-+
-+ spin_lock_irqsave(&pool->lock, flags);
-+ bitmap_clear(pool->alloc_map, pos, pages);
-+ pool->num_pages -= pages;
-+ if (pool->num_pages == 0)
-+ pool->alloc_pos = 0;
-+ DO_STATS(pool->num_bufs--);
-+ spin_unlock_irqrestore(&pool->lock, flags);
-+}
-+
-+/* allocate a 'safe' buffer and keep track of it */
-+static struct safe_buffer *
-+alloc_safe_buffer(struct dmabounce_device_info *device_info,
-+ dma_addr_t dma_addr, size_t size, enum dma_data_direction dir)
-+{
-+ struct safe_buffer *buf;
-+ struct dmabounce_pool *pool = &device_info->pool;
-+ struct device *dev = device_info->dev;
-+ unsigned long flags;
-+
-+ /*
-+ * Although one might expect this to be called in thread context,
-+ * using GFP_KERNEL here leads to hard-to-debug lockups. in_atomic()
-+ * was previously used to select the appropriate allocation mode,
-+ * but this is unsafe.
-+ */
-+ buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
-+ if (!buf) {
-+ dev_warn(dev, "%s: kmalloc failed\n", __func__);
-+ return NULL;
-+ }
-+
-+ buf->unsafe_dma_addr = dma_addr;
-+ buf->size = size;
-+ buf->direction = dir;
-+ buf->pool = pool;
-+
-+ buf->safe = bounce_alloc(pool, size, &buf->safe_dma_addr);
-+
-+ if (!buf->safe) {
-+ dev_warn(dev,
-+ "%s: could not alloc dma memory (size=%d)\n",
-+ __func__, size);
-+ kfree(buf);
-+ return NULL;
-+ }
-+
-+ write_lock_irqsave(&device_info->lock, flags);
-+ list_add(&buf->node, &device_info->safe_buffers);
-+ write_unlock_irqrestore(&device_info->lock, flags);
-+
-+ return buf;
-+}
-+
-+/* determine if a buffer is from our "safe" pool */
-+static struct safe_buffer *
-+find_safe_buffer(struct dmabounce_device_info *device_info,
-+ dma_addr_t safe_dma_addr)
-+{
-+ struct safe_buffer *b, *rb = NULL;
-+ unsigned long flags;
-+
-+ read_lock_irqsave(&device_info->lock, flags);
-+
-+ list_for_each_entry(b, &device_info->safe_buffers, node)
-+ if (b->safe_dma_addr <= safe_dma_addr &&
-+ b->safe_dma_addr + b->size > safe_dma_addr) {
-+ rb = b;
-+ break;
-+ }
-+
-+ read_unlock_irqrestore(&device_info->lock, flags);
-+ return rb;
-+}
-+
-+static void
-+free_safe_buffer(struct dmabounce_device_info *device_info,
-+ struct safe_buffer *buf)
-+{
-+ unsigned long flags;
-+
-+ write_lock_irqsave(&device_info->lock, flags);
-+ list_del(&buf->node);
-+ write_unlock_irqrestore(&device_info->lock, flags);
-+
-+ bounce_free(buf->pool, buf->safe, buf->size);
-+
-+ kfree(buf);
-+}
-+
-+/* ************************************************** */
-+
-+static struct safe_buffer *
-+find_safe_buffer_dev(struct device *dev, dma_addr_t dma_addr, const char *where)
-+{
-+ if (!dev || !g_dmabounce_device_info)
-+ return NULL;
-+ if (dma_mapping_error(dev, dma_addr)) {
-+ dev_err(dev, "Trying to %s invalid mapping\n", where);
-+ return NULL;
-+ }
-+ return find_safe_buffer(g_dmabounce_device_info, dma_addr);
-+}
-+
-+static dma_addr_t
-+map_single(struct device *dev, struct safe_buffer *buf, size_t size,
-+ enum dma_data_direction dir, unsigned long attrs)
-+{
-+ BUG_ON(buf->size != size);
-+ BUG_ON(buf->direction != dir);
-+
-+ dev_dbg(dev, "map: %llx->%llx\n", (u64)buf->unsafe_dma_addr,
-+ (u64)buf->safe_dma_addr);
-+
-+ if ((dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) &&
-+ !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-+ bcm2838_dma40_memcpy(buf->safe_dma_addr, buf->unsafe_dma_addr,
-+ size);
-+
-+ return buf->safe_dma_addr;
-+}
-+
-+static dma_addr_t
-+unmap_single(struct device *dev, struct safe_buffer *buf, size_t size,
-+ enum dma_data_direction dir, unsigned long attrs)
-+{
-+ BUG_ON(buf->size != size);
-+ BUG_ON(buf->direction != dir);
-+
-+ if ((dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) &&
-+ !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
-+ dev_dbg(dev, "unmap: %llx->%llx\n", (u64)buf->safe_dma_addr,
-+ (u64)buf->unsafe_dma_addr);
-+
-+ bcm2838_dma40_memcpy(buf->unsafe_dma_addr, buf->safe_dma_addr,
-+ size);
-+ }
-+ return buf->unsafe_dma_addr;
-+}
-+
-+/* ************************************************** */
-+
-+/*
-+ * see if a buffer address is in an 'unsafe' range. if it is
-+ * allocate a 'safe' buffer and copy the unsafe buffer into it.
-+ * substitute the safe buffer for the unsafe one.
-+ * (basically move the buffer from an unsafe area to a safe one)
-+ */
-+static dma_addr_t
-+dmabounce_map_page(struct device *dev, struct page *page, unsigned long offset,
-+ size_t size, enum dma_data_direction dir,
-+ unsigned long attrs)
-+{
-+ struct dmabounce_device_info *device_info = g_dmabounce_device_info;
-+ dma_addr_t dma_addr;
-+
-+ dma_addr = pfn_to_dma(dev, page_to_pfn(page)) + offset;
-+
-+ arm_dma_ops.sync_single_for_device(dev, dma_addr, size, dir);
-+
-+ if (device_info && (dma_addr + size) > device_info->threshold) {
-+ struct safe_buffer *buf;
-+
-+ buf = alloc_safe_buffer(device_info, dma_addr, size, dir);
-+ if (!buf) {
-+ DO_STATS(device_info->fail_count++);
-+ return ARM_MAPPING_ERROR;
-+ }
-+
-+ DO_STATS(device_info->map_count++);
-+
-+ dma_addr = map_single(dev, buf, size, dir, attrs);
-+ }
-+
-+ return dma_addr;
-+}
-+
-+/*
-+ * see if a mapped address was really a "safe" buffer and if so, copy
-+ * the data from the safe buffer back to the unsafe buffer and free up
-+ * the safe buffer. (basically return things back to the way they
-+ * should be)
-+ */
-+static void
-+dmabounce_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
-+ enum dma_data_direction dir, unsigned long attrs)
-+{
-+ struct safe_buffer *buf;
-+
-+ buf = find_safe_buffer_dev(dev, dma_addr, __func__);
-+ if (buf) {
-+ DO_STATS(g_dmabounce_device_info->unmap_count++);
-+ dma_addr = unmap_single(dev, buf, size, dir, attrs);
-+ free_safe_buffer(g_dmabounce_device_info, buf);
-+ }
-+
-+ arm_dma_ops.sync_single_for_cpu(dev, dma_addr, size, dir);
-+}
-+
-+/*
-+ * A version of dmabounce_map_page that assumes the mapping has already
-+ * been created - intended for streaming operation.
-+ */
-+static void
-+dmabounce_sync_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
-+ enum dma_data_direction dir)
-+{
-+ struct safe_buffer *buf;
-+
-+ arm_dma_ops.sync_single_for_device(dev, dma_addr, size, dir);
-+
-+ buf = find_safe_buffer_dev(dev, dma_addr, __func__);
-+ if (buf) {
-+ DO_STATS(g_dmabounce_device_info->sync_dev_count++);
-+ map_single(dev, buf, size, dir, 0);
-+ }
-+}
-+
-+/*
-+ * A version of dmabounce_unmap_page that doesn't destroy the mapping -
-+ * intended for streaming operation.
-+ */
-+static void
-+dmabounce_sync_for_cpu(struct device *dev, dma_addr_t dma_addr,
-+ size_t size, enum dma_data_direction dir)
-+{
-+ struct safe_buffer *buf;
-+
-+ buf = find_safe_buffer_dev(dev, dma_addr, __func__);
-+ if (buf) {
-+ DO_STATS(g_dmabounce_device_info->sync_cpu_count++);
-+ dma_addr = unmap_single(dev, buf, size, dir, 0);
-+ }
-+
-+ arm_dma_ops.sync_single_for_cpu(dev, dma_addr, size, dir);
-+}
-+
-+static int dmabounce_dma_supported(struct device *dev, u64 dma_mask)
-+{
-+ if (g_dmabounce_device_info)
-+ return 0;
-+
-+ return arm_dma_ops.dma_supported(dev, dma_mask);
-+}
-+
-+static int dmabounce_mapping_error(struct device *dev, dma_addr_t dma_addr)
-+{
-+ return arm_dma_ops.mapping_error(dev, dma_addr);
-+}
-+
-+static const struct dma_map_ops dmabounce_ops = {
-+ .alloc = arm_dma_alloc,
-+ .free = arm_dma_free,
-+ .mmap = arm_dma_mmap,
-+ .get_sgtable = arm_dma_get_sgtable,
-+ .map_page = dmabounce_map_page,
-+ .unmap_page = dmabounce_unmap_page,
-+ .sync_single_for_cpu = dmabounce_sync_for_cpu,
-+ .sync_single_for_device = dmabounce_sync_for_device,
-+ .map_sg = arm_dma_map_sg,
-+ .unmap_sg = arm_dma_unmap_sg,
-+ .sync_sg_for_cpu = arm_dma_sync_sg_for_cpu,
-+ .sync_sg_for_device = arm_dma_sync_sg_for_device,
-+ .dma_supported = dmabounce_dma_supported,
-+ .mapping_error = dmabounce_mapping_error,
-+};
-+
-+int brcm_pcie_bounce_register_dev(struct device *dev,
-+ unsigned long buffer_size,
-+ dma_addr_t threshold)
-+{
-+ struct dmabounce_device_info *device_info;
-+ int ret;
-+
-+ /* Only support a single client */
-+ if (g_dmabounce_device_info)
-+ return -EBUSY;
-+
-+ ret = bcm2838_dma40_memcpy_init(dev);
-+ if (ret)
-+ return ret;
-+
-+ device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
-+ if (!device_info) {
-+ dev_err(dev,
-+ "Could not allocated dmabounce_device_info\n");
-+ return -ENOMEM;
-+ }
-+
-+ ret = bounce_create(&device_info->pool, dev, buffer_size);
-+ if (ret) {
-+ dev_err(dev,
-+ "dmabounce: could not allocate %ld byte DMA pool\n",
-+ buffer_size);
-+ goto err_bounce;
-+ }
-+
-+ device_info->dev = dev;
-+ device_info->threshold = threshold;
-+ INIT_LIST_HEAD(&device_info->safe_buffers);
-+ rwlock_init(&device_info->lock);
-+
-+ DO_STATS(device_info->map_count = 0);
-+ DO_STATS(device_info->unmap_count = 0);
-+ DO_STATS(device_info->sync_dev_count = 0);
-+ DO_STATS(device_info->sync_cpu_count = 0);
-+ DO_STATS(device_info->fail_count = 0);
-+ DO_STATS(device_info->attr_res =
-+ device_create_file(dev, &dev_attr_dmabounce_stats));
-+
-+ g_dmabounce_device_info = device_info;
-+ set_dma_ops(dev, &dmabounce_ops);
-+
-+ dev_info(dev, "dmabounce: registered device - %ld kB, threshold %pad\n",
-+ buffer_size / 1024, &threshold);
-+
-+ return 0;
-+
-+ err_bounce:
-+ kfree(device_info);
-+ return ret;
-+}
-+EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
-+
-+void brcm_pcie_bounce_unregister_dev(struct device *dev)
-+{
-+ struct dmabounce_device_info *device_info = g_dmabounce_device_info;
-+
-+ g_dmabounce_device_info = NULL;
-+ set_dma_ops(dev, NULL);
-+
-+ if (!device_info) {
-+ dev_warn(dev,
-+ "Never registered with dmabounce but attempting"
-+ "to unregister!\n");
-+ return;
-+ }
-+
-+ if (!list_empty(&device_info->safe_buffers)) {
-+ dev_err(dev,
-+ "Removing from dmabounce with pending buffers!\n");
-+ BUG();
-+ }
-+
-+ bounce_destroy(&device_info->pool);
-+
-+ DO_STATS(if (device_info->attr_res == 0)
-+ device_remove_file(dev, &dev_attr_dmabounce_stats));
-+
-+ kfree(device_info);
-+
-+ dev_info(dev, "dmabounce: device unregistered\n");
-+}
-+EXPORT_SYMBOL(brcm_pcie_bounce_unregister_dev);
-+
-+MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.org>");
-+MODULE_DESCRIPTION("Dedicate DMA bounce support for pcie-brcmstb");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/pci/controller/pcie-brcmstb-bounce.h
-@@ -0,0 +1,32 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (C) 2019 Raspberry Pi (Trading) Ltd.
-+ */
-+
-+#ifndef _PCIE_BRCMSTB_BOUNCE_H
-+#define _PCIE_BRCMSTB_BOUNCE_H
-+
-+#ifdef CONFIG_ARM
-+
-+int brcm_pcie_bounce_register_dev(struct device *dev, unsigned long buffer_size,
-+ dma_addr_t threshold);
-+
-+int brcm_pcie_bounce_unregister_dev(struct device *dev);
-+
-+#else
-+
-+static inline int brcm_pcie_bounce_register_dev(struct device *dev,
-+ unsigned long buffer_size,
-+ dma_addr_t threshold)
-+{
-+ return 0;
-+}
-+
-+static inline int brcm_pcie_bounce_unregister_dev(struct device *dev)
-+{
-+ return 0;
-+}
-+
-+#endif
-+
-+#endif /* _PCIE_BRCMSTB_BOUNCE_H */
---- a/drivers/pci/controller/pcie-brcmstb.c
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -29,6 +29,7 @@
- #include <linux/string.h>
- #include <linux/types.h>
- #include "../pci.h"
-+#include "pcie-brcmstb-bounce.h"
-
- /* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
- #define BRCM_PCIE_CAP_REGS 0x00ac
-@@ -53,6 +54,7 @@
- #define PCIE_MISC_MSI_BAR_CONFIG_LO 0x4044
- #define PCIE_MISC_MSI_BAR_CONFIG_HI 0x4048
- #define PCIE_MISC_MSI_DATA_CONFIG 0x404c
-+#define PCIE_MISC_EOI_CTRL 0x4060
- #define PCIE_MISC_PCIE_CTRL 0x4064
- #define PCIE_MISC_PCIE_STATUS 0x4068
- #define PCIE_MISC_REVISION 0x406c
-@@ -260,12 +262,14 @@ struct brcm_pcie {
- unsigned int rev;
- const int *reg_offsets;
- const int *reg_field_info;
-+ u32 max_burst_size;
- enum pcie_type type;
- };
-
- struct pcie_cfg_data {
- const int *reg_field_info;
- const int *offsets;
-+ const u32 max_burst_size;
- const enum pcie_type type;
- };
-
-@@ -288,24 +292,27 @@ static const int pcie_offset_bcm7425[] =
- static const struct pcie_cfg_data bcm7425_cfg = {
- .reg_field_info = pcie_reg_field_info,
- .offsets = pcie_offset_bcm7425,
-+ .max_burst_size = BURST_SIZE_256,
- .type = BCM7425,
- };
-
- static const int pcie_offsets[] = {
- [RGR1_SW_INIT_1] = 0x9210,
- [EXT_CFG_INDEX] = 0x9000,
-- [EXT_CFG_DATA] = 0x9004,
-+ [EXT_CFG_DATA] = 0x8000,
- };
-
- static const struct pcie_cfg_data bcm7435_cfg = {
- .reg_field_info = pcie_reg_field_info,
- .offsets = pcie_offsets,
-+ .max_burst_size = BURST_SIZE_256,
- .type = BCM7435,
- };
-
- static const struct pcie_cfg_data generic_cfg = {
- .reg_field_info = pcie_reg_field_info,
- .offsets = pcie_offsets,
-+ .max_burst_size = BURST_SIZE_128, // before BURST_SIZE_512
- .type = GENERIC,
- };
-
-@@ -318,6 +325,7 @@ static const int pcie_offset_bcm7278[] =
- static const struct pcie_cfg_data bcm7278_cfg = {
- .reg_field_info = pcie_reg_field_info_bcm7278,
- .offsets = pcie_offset_bcm7278,
-+ .max_burst_size = BURST_SIZE_512,
- .type = BCM7278,
- };
-
-@@ -360,7 +368,6 @@ static struct pci_ops brcm_pcie_ops = {
- (reg##_##field##_MASK & (field_val << reg##_##field##_SHIFT)))
-
- static const struct dma_map_ops *arch_dma_ops;
--static const struct dma_map_ops *brcm_dma_ops_ptr;
- static struct of_pci_range *dma_ranges;
- static int num_dma_ranges;
-
-@@ -369,6 +376,16 @@ static int num_memc;
- static int num_pcie;
- static DEFINE_MUTEX(brcm_pcie_lock);
-
-+static unsigned int bounce_buffer = 32*1024*1024;
-+module_param(bounce_buffer, uint, 0644);
-+MODULE_PARM_DESC(bounce_buffer, "Size of bounce buffer");
-+
-+static unsigned int bounce_threshold = 0xc0000000;
-+module_param(bounce_threshold, uint, 0644);
-+MODULE_PARM_DESC(bounce_threshold, "Bounce threshold");
-+
-+static struct brcm_pcie *g_pcie;
-+
- static dma_addr_t brcm_to_pci(dma_addr_t addr)
- {
- struct of_pci_range *p;
-@@ -457,12 +474,10 @@ static int brcm_map_sg(struct device *de
- struct scatterlist *sg;
-
- for_each_sg(sgl, sg, nents, i) {
--#ifdef CONFIG_NEED_SG_DMA_LENGTH
-- sg->dma_length = sg->length;
--#endif
-+ sg_dma_len(sg) = sg->length;
- sg->dma_address =
-- brcm_dma_ops_ptr->map_page(dev, sg_page(sg), sg->offset,
-- sg->length, dir, attrs);
-+ brcm_map_page(dev, sg_page(sg), sg->offset,
-+ sg->length, dir, attrs);
- if (dma_mapping_error(dev, sg->dma_address))
- goto bad_mapping;
- }
-@@ -470,8 +485,8 @@ static int brcm_map_sg(struct device *de
-
- bad_mapping:
- for_each_sg(sgl, sg, i, j)
-- brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
-- sg_dma_len(sg), dir, attrs);
-+ brcm_unmap_page(dev, sg_dma_address(sg),
-+ sg_dma_len(sg), dir, attrs);
- return 0;
- }
-
-@@ -484,8 +499,8 @@ static void brcm_unmap_sg(struct device
- struct scatterlist *sg;
-
- for_each_sg(sgl, sg, nents, i)
-- brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
-- sg_dma_len(sg), dir, attrs);
-+ brcm_unmap_page(dev, sg_dma_address(sg),
-+ sg_dma_len(sg), dir, attrs);
- }
-
- static void brcm_sync_single_for_cpu(struct device *dev,
-@@ -531,8 +546,8 @@ void brcm_sync_sg_for_cpu(struct device
- int i;
-
- for_each_sg(sgl, sg, nents, i)
-- brcm_dma_ops_ptr->sync_single_for_cpu(dev, sg_dma_address(sg),
-- sg->length, dir);
-+ brcm_sync_single_for_cpu(dev, sg_dma_address(sg),
-+ sg->length, dir);
- }
-
- void brcm_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
-@@ -542,9 +557,9 @@ void brcm_sync_sg_for_device(struct devi
- int i;
-
- for_each_sg(sgl, sg, nents, i)
-- brcm_dma_ops_ptr->sync_single_for_device(dev,
-- sg_dma_address(sg),
-- sg->length, dir);
-+ brcm_sync_single_for_device(dev,
-+ sg_dma_address(sg),
-+ sg->length, dir);
- }
-
- static int brcm_mapping_error(struct device *dev, dma_addr_t dma_addr)
-@@ -633,17 +648,47 @@ static void brcm_set_dma_ops(struct devi
- set_dma_ops(dev, &brcm_dma_ops);
- }
-
-+static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie,
-+ unsigned int val);
- static int brcmstb_platform_notifier(struct notifier_block *nb,
- unsigned long event, void *__dev)
- {
-+ extern unsigned long max_pfn;
- struct device *dev = __dev;
-+ const char *rc_name = "0000:00:00.0";
-
-- brcm_dma_ops_ptr = &brcm_dma_ops;
-- if (event != BUS_NOTIFY_ADD_DEVICE)
-- return NOTIFY_DONE;
-+ switch (event) {
-+ case BUS_NOTIFY_ADD_DEVICE:
-+ if (max_pfn > (bounce_threshold/PAGE_SIZE) &&
-+ strcmp(dev->kobj.name, rc_name)) {
-+ int ret;
-+
-+ ret = brcm_pcie_bounce_register_dev(dev, bounce_buffer,
-+ (dma_addr_t)bounce_threshold);
-+ if (ret) {
-+ dev_err(dev,
-+ "brcm_pcie_bounce_register_dev() failed: %d\n",
-+ ret);
-+ return ret;
-+ }
-+ }
-+ brcm_set_dma_ops(dev);
-+ return NOTIFY_OK;
-+
-+ case BUS_NOTIFY_DEL_DEVICE:
-+ if (!strcmp(dev->kobj.name, rc_name) && g_pcie) {
-+ /* Force a bus reset */
-+ brcm_pcie_perst_set(g_pcie, 1);
-+ msleep(100);
-+ brcm_pcie_perst_set(g_pcie, 0);
-+ } else if (max_pfn > (bounce_threshold/PAGE_SIZE)) {
-+ brcm_pcie_bounce_unregister_dev(dev);
-+ }
-+ return NOTIFY_OK;
-
-- brcm_set_dma_ops(dev);
-- return NOTIFY_OK;
-+ default:
-+ return NOTIFY_DONE;
-+ }
- }
-
- static struct notifier_block brcmstb_platform_nb = {
-@@ -914,6 +959,7 @@ static void brcm_pcie_msi_isr(struct irq
- }
- }
- chained_irq_exit(chip, desc);
-+ bcm_writel(1, msi->base + PCIE_MISC_EOI_CTRL);
- }
-
- static void brcm_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
-@@ -930,7 +976,8 @@ static void brcm_compose_msi_msg(struct
- static int brcm_msi_set_affinity(struct irq_data *irq_data,
- const struct cpumask *mask, bool force)
- {
-- return -EINVAL;
-+ struct brcm_msi *msi = irq_data_get_irq_chip_data(irq_data);
-+ return __irq_set_affinity(msi->irq, mask, force);
- }
-
- static struct irq_chip brcm_msi_bottom_irq_chip = {
-@@ -1168,9 +1215,9 @@ static void __iomem *brcm_pcie_map_conf(
- return PCI_SLOT(devfn) ? NULL : base + where;
-
- /* For devices, write to the config space index register */
-- idx = cfg_index(bus->number, devfn, where);
-+ idx = cfg_index(bus->number, devfn, 0);
- bcm_writel(idx, pcie->base + IDX_ADDR(pcie));
-- return base + DATA_ADDR(pcie) + (where & 0x3);
-+ return base + DATA_ADDR(pcie) + where;
- }
-
- static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie,
-@@ -1238,20 +1285,6 @@ static int brcm_pcie_parse_map_dma_range
- num_dma_ranges++;
- }
-
-- for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
-- u64 size = brcmstb_memory_memc_size(i);
--
-- if (size == (u64)-1) {
-- dev_err(pcie->dev, "cannot get memc%d size", i);
-- return -EINVAL;
-- } else if (size) {
-- scb_size[i] = roundup_pow_of_two_64(size);
-- num_memc++;
-- } else {
-- break;
-- }
-- }
--
- return 0;
- }
-
-@@ -1275,26 +1308,25 @@ static int brcm_pcie_add_controller(stru
- if (ret)
- goto done;
-
-- /* Determine num_memc and their sizes */
-- for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
-- u64 size = brcmstb_memory_memc_size(i);
--
-- if (size == (u64)-1) {
-- dev_err(dev, "cannot get memc%d size\n", i);
-- ret = -EINVAL;
-- goto done;
-- } else if (size) {
-- scb_size[i] = roundup_pow_of_two_64(size);
-- num_memc++;
-- } else {
-- break;
-+ if (!num_dma_ranges) {
-+ /* Determine num_memc and their sizes by other means */
-+ for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
-+ u64 size = brcmstb_memory_memc_size(i);
-+
-+ if (size == (u64)-1) {
-+ dev_err(dev, "cannot get memc%d size\n", i);
-+ ret = -EINVAL;
-+ goto done;
-+ } else if (size) {
-+ scb_size[i] = roundup_pow_of_two_64(size);
-+ } else {
-+ break;
-+ }
- }
-- }
-- if (!ret && num_memc == 0) {
-- ret = -EINVAL;
-- goto done;
-+ num_memc = i;
- }
-
-+ g_pcie = pcie;
- num_pcie++;
- done:
- mutex_unlock(&brcm_pcie_lock);
-@@ -1307,6 +1339,7 @@ static void brcm_pcie_remove_controller(
- if (--num_pcie > 0)
- goto out;
-
-+ g_pcie = NULL;
- if (brcm_unregister_notifier())
- dev_err(pcie->dev, "failed to unregister pci bus notifier\n");
- kfree(dma_ranges);
-@@ -1367,7 +1400,7 @@ static int brcm_pcie_setup(struct brcm_p
- void __iomem *base = pcie->base;
- unsigned int scb_size_val;
- u64 rc_bar2_offset, rc_bar2_size, total_mem_size = 0;
-- u32 tmp, burst;
-+ u32 tmp;
- int i, j, ret, limit;
- u16 nlw, cls, lnksta;
- bool ssc_good = false;
-@@ -1400,20 +1433,15 @@ static int brcm_pcie_setup(struct brcm_p
- /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
- tmp = INSERT_FIELD(0, PCIE_MISC_MISC_CTRL, SCB_ACCESS_EN, 1);
- tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, CFG_READ_UR_MODE, 1);
-- burst = (pcie->type == GENERIC || pcie->type == BCM7278)
-- ? BURST_SIZE_512 : BURST_SIZE_256;
-- tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE, burst);
-+ tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE,
-+ pcie->max_burst_size);
- bcm_writel(tmp, base + PCIE_MISC_MISC_CTRL);
-
- /*
- * Set up inbound memory view for the EP (called RC_BAR2,
- * not to be confused with the BARs that are advertised by
- * the EP).
-- */
-- for (i = 0; i < num_memc; i++)
-- total_mem_size += scb_size[i];
--
-- /*
-+ *
- * The PCIe host controller by design must set the inbound
- * viewport to be a contiguous arrangement of all of the
- * system's memory. In addition, its size mut be a power of
-@@ -1429,55 +1457,49 @@ static int brcm_pcie_setup(struct brcm_p
- * the controller will know to send outbound memory downstream
- * and everything else upstream.
- */
-- rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
-
-- if (dma_ranges) {
-+ if (num_dma_ranges) {
- /*
-- * The best-case scenario is to place the inbound
-- * region in the first 4GB of pcie-space, as some
-- * legacy devices can only address 32bits.
-- * We would also like to put the MSI under 4GB
-- * as well, since some devices require a 32bit
-- * MSI target address.
-+ * Use the base address and size(s) provided in the dma-ranges
-+ * property.
- */
-- if (total_mem_size <= 0xc0000000ULL &&
-- rc_bar2_size <= 0x100000000ULL) {
-- rc_bar2_offset = 0;
-- /* If the viewport is less then 4GB we can fit
-- * the MSI target address under 4GB. Otherwise
-- * put it right below 64GB.
-- */
-- msi_target_addr =
-- (rc_bar2_size == 0x100000000ULL)
-- ? BRCM_MSI_TARGET_ADDR_GT_4GB
-- : BRCM_MSI_TARGET_ADDR_LT_4GB;
-- } else {
-- /*
-- * The system memory is 4GB or larger so we
-- * cannot start the inbound region at location
-- * 0 (since we have to allow some space for
-- * outbound memory @ 3GB). So instead we
-- * start it at the 1x multiple of its size
-- */
-- rc_bar2_offset = rc_bar2_size;
--
-- /* Since we are starting the viewport at 4GB or
-- * higher, put the MSI target address below 4GB
-- */
-- msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
-- }
-- } else {
-+ for (i = 0; i < num_dma_ranges; i++)
-+ scb_size[i] = roundup_pow_of_two_64(dma_ranges[i].size);
-+
-+ num_memc = num_dma_ranges;
-+ rc_bar2_offset = dma_ranges[0].pci_addr;
-+ } else if (num_memc) {
- /*
- * Set simple configuration based on memory sizes
-- * only. We always start the viewport at address 0,
-- * and set the MSI target address accordingly.
-+ * only. We always start the viewport at address 0.
- */
- rc_bar2_offset = 0;
-+ } else {
-+ return -EINVAL;
-+ }
-+
-+ for (i = 0; i < num_memc; i++)
-+ total_mem_size += scb_size[i];
-+
-+ rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
-
-- msi_target_addr = (rc_bar2_size >= 0x100000000ULL)
-- ? BRCM_MSI_TARGET_ADDR_GT_4GB
-- : BRCM_MSI_TARGET_ADDR_LT_4GB;
-+ /* Verify the alignment is correct */
-+ if (rc_bar2_offset & (rc_bar2_size - 1)) {
-+ dev_err(dev, "inbound window is misaligned\n");
-+ return -EINVAL;
- }
-+
-+ /*
-+ * Position the MSI target low if possible.
-+ *
-+ * TO DO: Consider outbound window when choosing MSI target and
-+ * verifying configuration.
-+ */
-+ msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
-+ if (rc_bar2_offset <= msi_target_addr &&
-+ rc_bar2_offset + rc_bar2_size > msi_target_addr)
-+ msi_target_addr = BRCM_MSI_TARGET_ADDR_GT_4GB;
-+
- pcie->msi_target_addr = msi_target_addr;
-
- tmp = lower_32_bits(rc_bar2_offset);
-@@ -1713,6 +1735,7 @@ static int brcm_pcie_probe(struct platfo
- data = of_id->data;
- pcie->reg_offsets = data->offsets;
- pcie->reg_field_info = data->reg_field_info;
-+ pcie->max_burst_size = data->max_burst_size;
- pcie->type = data->type;
- pcie->dn = dn;
- pcie->dev = &pdev->dev;
-@@ -1732,7 +1755,7 @@ static int brcm_pcie_probe(struct platfo
-
- pcie->clk = of_clk_get_by_name(dn, "sw_pcie");
- if (IS_ERR(pcie->clk)) {
-- dev_err(&pdev->dev, "could not get clock\n");
-+ dev_warn(&pdev->dev, "could not get clock\n");
- pcie->clk = NULL;
- }
- pcie->base = base;
-@@ -1755,7 +1778,8 @@ static int brcm_pcie_probe(struct platfo
-
- ret = clk_prepare_enable(pcie->clk);
- if (ret) {
-- dev_err(&pdev->dev, "could not enable clock\n");
-+ if (ret != -EPROBE_DEFER)
-+ dev_err(&pdev->dev, "could not enable clock\n");
- return ret;
- }
-
-@@ -1818,7 +1842,6 @@ static struct platform_driver brcm_pcie_
- .remove = brcm_pcie_remove,
- .driver = {
- .name = "brcm-pcie",
-- .owner = THIS_MODULE,
- .of_match_table = brcm_pcie_match,
- .pm = &brcm_pcie_pm_ops,
- },
---- a/drivers/soc/bcm/brcmstb/Makefile
-+++ b/drivers/soc/bcm/brcmstb/Makefile
-@@ -1,2 +1,2 @@
--obj-y += common.o biuctrl.o
-+obj-y += common.o biuctrl.o memory.o
- obj-$(CONFIG_BRCMSTB_PM) += pm/
---- /dev/null
-+++ b/drivers/soc/bcm/brcmstb/memory.c
-@@ -0,0 +1,158 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/* Copyright © 2015-2017 Broadcom */
-+
-+#include <linux/device.h>
-+#include <linux/io.h>
-+#include <linux/libfdt.h>
-+#include <linux/of_address.h>
-+#include <linux/of_fdt.h>
-+#include <linux/sizes.h>
-+#include <soc/brcmstb/memory_api.h>
-+
-+/* Macro to help extract property data */
-+#define DT_PROP_DATA_TO_U32(b, offs) (fdt32_to_cpu(*(u32 *)(b + offs)))
-+
-+/* Constants used when retrieving memc info */
-+#define NUM_BUS_RANGES 10
-+#define BUS_RANGE_ULIMIT_SHIFT 4
-+#define BUS_RANGE_LLIMIT_SHIFT 4
-+#define BUS_RANGE_PA_SHIFT 12
-+
-+enum {
-+ BUSNUM_MCP0 = 0x4,
-+ BUSNUM_MCP1 = 0x5,
-+ BUSNUM_MCP2 = 0x6,
-+};
-+
-+/*
-+ * If the DT nodes are handy, determine which MEMC holds the specified
-+ * physical address.
-+ */
-+#ifdef CONFIG_ARCH_BRCMSTB
-+int __brcmstb_memory_phys_addr_to_memc(phys_addr_t pa, void __iomem *base)
-+{
-+ int memc = -1;
-+ int i;
-+
-+ for (i = 0; i < NUM_BUS_RANGES; i++, base += 8) {
-+ const u64 ulimit_raw = readl(base);
-+ const u64 llimit_raw = readl(base + 4);
-+ const u64 ulimit =
-+ ((ulimit_raw >> BUS_RANGE_ULIMIT_SHIFT)
-+ << BUS_RANGE_PA_SHIFT) | 0xfff;
-+ const u64 llimit = (llimit_raw >> BUS_RANGE_LLIMIT_SHIFT)
-+ << BUS_RANGE_PA_SHIFT;
-+ const u32 busnum = (u32)(ulimit_raw & 0xf);
-+
-+ if (pa >= llimit && pa <= ulimit) {
-+ if (busnum >= BUSNUM_MCP0 && busnum <= BUSNUM_MCP2) {
-+ memc = busnum - BUSNUM_MCP0;
-+ break;
-+ }
-+ }
-+ }
-+
-+ return memc;
-+}
-+
-+int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa)
-+{
-+ int memc = -1;
-+ struct device_node *np;
-+ void __iomem *cpubiuctrl;
-+
-+ np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
-+ if (!np)
-+ return memc;
-+
-+ cpubiuctrl = of_iomap(np, 0);
-+ if (!cpubiuctrl)
-+ goto cleanup;
-+
-+ memc = __brcmstb_memory_phys_addr_to_memc(pa, cpubiuctrl);
-+ iounmap(cpubiuctrl);
-+
-+cleanup:
-+ of_node_put(np);
-+
-+ return memc;
-+}
-+
-+#elif defined(CONFIG_MIPS)
-+int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa)
-+{
-+ /* The logic here is fairly simple and hardcoded: if pa <= 0x5000_0000,
-+ * then this is MEMC0, else MEMC1.
-+ *
-+ * For systems with 2GB on MEMC0, MEMC1 starts at 9000_0000, with 1GB
-+ * on MEMC0, MEMC1 starts at 6000_0000.
-+ */
-+ if (pa >= 0x50000000ULL)
-+ return 1;
-+ else
-+ return 0;
-+}
-+#endif
-+
-+u64 brcmstb_memory_memc_size(int memc)
-+{
-+ const void *fdt = initial_boot_params;
-+ const int mem_offset = fdt_path_offset(fdt, "/memory");
-+ int addr_cells = 1, size_cells = 1;
-+ const struct fdt_property *prop;
-+ int proplen, cellslen;
-+ u64 memc_size = 0;
-+ int i;
-+
-+ /* Get root size and address cells if specified */
-+ prop = fdt_get_property(fdt, 0, "#size-cells", &proplen);
-+ if (prop)
-+ size_cells = DT_PROP_DATA_TO_U32(prop->data, 0);
-+
-+ prop = fdt_get_property(fdt, 0, "#address-cells", &proplen);
-+ if (prop)
-+ addr_cells = DT_PROP_DATA_TO_U32(prop->data, 0);
-+
-+ if (mem_offset < 0)
-+ return -1;
-+
-+ prop = fdt_get_property(fdt, mem_offset, "reg", &proplen);
-+ cellslen = (int)sizeof(u32) * (addr_cells + size_cells);
-+ if ((proplen % cellslen) != 0)
-+ return -1;
-+
-+ for (i = 0; i < proplen / cellslen; ++i) {
-+ u64 addr = 0;
-+ u64 size = 0;
-+ int memc_idx;
-+ int j;
-+
-+ for (j = 0; j < addr_cells; ++j) {
-+ int offset = (cellslen * i) + (sizeof(u32) * j);
-+
-+ addr |= (u64)DT_PROP_DATA_TO_U32(prop->data, offset) <<
-+ ((addr_cells - j - 1) * 32);
-+ }
-+ for (j = 0; j < size_cells; ++j) {
-+ int offset = (cellslen * i) +
-+ (sizeof(u32) * (j + addr_cells));
-+
-+ size |= (u64)DT_PROP_DATA_TO_U32(prop->data, offset) <<
-+ ((size_cells - j - 1) * 32);
-+ }
-+
-+ if ((phys_addr_t)addr != addr) {
-+ pr_err("phys_addr_t is smaller than provided address 0x%llx!\n",
-+ addr);
-+ return -1;
-+ }
-+
-+ memc_idx = brcmstb_memory_phys_addr_to_memc((phys_addr_t)addr);
-+ if (memc_idx == memc)
-+ memc_size += size;
-+ }
-+
-+ return memc_size;
-+}
-+EXPORT_SYMBOL_GPL(brcmstb_memory_memc_size);
-+
+++ /dev/null
-From 4f8fa14b05198c3d145d72d47ad9adfc25601842 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 29 May 2019 15:47:42 +0100
-Subject: [PATCH 539/703] arm: bcm2835: DMA can only address 1GB
-
-The legacy peripherals can only address the first gigabyte of RAM, so
-ensure that DMA allocations are restricted to that region.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/mach-bcm/board_bcm2835.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/arch/arm/mach-bcm/board_bcm2835.c
-+++ b/arch/arm/mach-bcm/board_bcm2835.c
-@@ -123,6 +123,9 @@ static const char * const bcm2835_compat
- };
-
- DT_MACHINE_START(BCM2835, "BCM2835")
-+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
-+ .dma_zone_size = SZ_1G,
-+#endif
- .map_io = bcm2835_map_io,
- .init_machine = bcm2835_init,
- .dt_compat = bcm2835_compat,
--- /dev/null
+From c1a3581a5637d096c40456e22edf7f846ca24ad4 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sat, 4 May 2019 17:06:15 +0200
+Subject: [PATCH 539/725] hwrng: iproc-rng200: Add BCM2838 support
+
+The HWRNG on the BCM2838 is compatible to iproc-rng200, so add the
+support to this driver instead of bcm2835-rng.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ drivers/char/hw_random/Kconfig | 4 +-
+ drivers/char/hw_random/iproc-rng200.c | 81 +++++++++++++++++++++++++--
+ 2 files changed, 79 insertions(+), 6 deletions(-)
+
+--- a/drivers/char/hw_random/Kconfig
++++ b/drivers/char/hw_random/Kconfig
+@@ -89,11 +89,11 @@ config HW_RANDOM_BCM2835
+
+ config HW_RANDOM_IPROC_RNG200
+ tristate "Broadcom iProc/STB RNG200 support"
+- depends on ARCH_BCM_IPROC || ARCH_BRCMSTB
++ depends on ARCH_BCM_IPROC || ARCH_BCM2835 || ARCH_BRCMSTB
+ default HW_RANDOM
+ ---help---
+ This driver provides kernel-side support for the RNG200
+- hardware found on the Broadcom iProc and STB SoCs.
++ hardware found on the Broadcom iProc, BCM2838 and STB SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called iproc-rng200
+--- a/drivers/char/hw_random/iproc-rng200.c
++++ b/drivers/char/hw_random/iproc-rng200.c
+@@ -29,6 +29,7 @@
+ #define RNG_CTRL_RNG_RBGEN_MASK 0x00001FFF
+ #define RNG_CTRL_RNG_RBGEN_ENABLE 0x00000001
+ #define RNG_CTRL_RNG_RBGEN_DISABLE 0x00000000
++#define RNG_CTRL_RNG_DIV_CTRL_SHIFT 13
+
+ #define RNG_SOFT_RESET_OFFSET 0x04
+ #define RNG_SOFT_RESET 0x00000001
+@@ -36,16 +37,23 @@
+ #define RBG_SOFT_RESET_OFFSET 0x08
+ #define RBG_SOFT_RESET 0x00000001
+
++#define RNG_TOTAL_BIT_COUNT_OFFSET 0x0C
++
++#define RNG_TOTAL_BIT_COUNT_THRESHOLD_OFFSET 0x10
++
+ #define RNG_INT_STATUS_OFFSET 0x18
+ #define RNG_INT_STATUS_MASTER_FAIL_LOCKOUT_IRQ_MASK 0x80000000
+ #define RNG_INT_STATUS_STARTUP_TRANSITIONS_MET_IRQ_MASK 0x00020000
+ #define RNG_INT_STATUS_NIST_FAIL_IRQ_MASK 0x00000020
+ #define RNG_INT_STATUS_TOTAL_BITS_COUNT_IRQ_MASK 0x00000001
+
++#define RNG_INT_ENABLE_OFFSET 0x1C
++
+ #define RNG_FIFO_DATA_OFFSET 0x20
+
+ #define RNG_FIFO_COUNT_OFFSET 0x24
+ #define RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK 0x000000FF
++#define RNG_FIFO_COUNT_RNG_FIFO_THRESHOLD_SHIFT 8
+
+ struct iproc_rng200_dev {
+ struct hwrng rng;
+@@ -166,6 +174,64 @@ static int iproc_rng200_init(struct hwrn
+ return 0;
+ }
+
++static int bcm2838_rng200_read(struct hwrng *rng, void *buf, size_t max,
++ bool wait)
++{
++ struct iproc_rng200_dev *priv = to_rng_priv(rng);
++ u32 max_words = max / sizeof(u32);
++ u32 num_words, count, val;
++
++ /* ensure warm up period has elapsed */
++ while (1) {
++ val = ioread32(priv->base + RNG_TOTAL_BIT_COUNT_OFFSET);
++ if (val > 16)
++ break;
++ cpu_relax();
++ }
++
++ /* ensure fifo is not empty */
++ while (1) {
++ num_words = ioread32(priv->base + RNG_FIFO_COUNT_OFFSET) &
++ RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK;
++ if (num_words)
++ break;
++ if (!wait)
++ return 0;
++ cpu_relax();
++ }
++
++ if (num_words > max_words)
++ num_words = max_words;
++
++ for (count = 0; count < num_words; count++) {
++ ((u32 *)buf)[count] = ioread32(priv->base +
++ RNG_FIFO_DATA_OFFSET);
++ }
++
++ return num_words * sizeof(u32);
++}
++
++static int bcm2838_rng200_init(struct hwrng *rng)
++{
++ struct iproc_rng200_dev *priv = to_rng_priv(rng);
++ uint32_t val;
++
++ if (ioread32(priv->base + RNG_CTRL_OFFSET) & RNG_CTRL_RNG_RBGEN_MASK)
++ return 0;
++
++ /* initial numbers generated are "less random" so will be discarded */
++ val = 0x40000;
++ iowrite32(val, priv->base + RNG_TOTAL_BIT_COUNT_THRESHOLD_OFFSET);
++ /* min fifo count to generate full interrupt */
++ val = 2 << RNG_FIFO_COUNT_RNG_FIFO_THRESHOLD_SHIFT;
++ iowrite32(val, priv->base + RNG_FIFO_COUNT_OFFSET);
++ /* enable the rng - 1Mhz sample rate */
++ val = (0x3 << RNG_CTRL_RNG_DIV_CTRL_SHIFT) | RNG_CTRL_RNG_RBGEN_MASK;
++ iowrite32(val, priv->base + RNG_CTRL_OFFSET);
++
++ return 0;
++}
++
+ static void iproc_rng200_cleanup(struct hwrng *rng)
+ {
+ struct iproc_rng200_dev *priv = to_rng_priv(rng);
+@@ -202,10 +268,16 @@ static int iproc_rng200_probe(struct pla
+ return PTR_ERR(priv->base);
+ }
+
+- priv->rng.name = "iproc-rng200",
+- priv->rng.read = iproc_rng200_read,
+- priv->rng.init = iproc_rng200_init,
+- priv->rng.cleanup = iproc_rng200_cleanup,
++ priv->rng.name = pdev->name;
++ priv->rng.cleanup = iproc_rng200_cleanup;
++
++ if (of_device_is_compatible(dev->of_node, "brcm,bcm2838-rng200")) {
++ priv->rng.init = bcm2838_rng200_init;
++ priv->rng.read = bcm2838_rng200_read;
++ } else {
++ priv->rng.init = iproc_rng200_init;
++ priv->rng.read = iproc_rng200_read;
++ }
+
+ /* Register driver */
+ ret = devm_hwrng_register(dev, &priv->rng);
+@@ -222,6 +294,7 @@ static int iproc_rng200_probe(struct pla
+ static const struct of_device_id iproc_rng200_of_match[] = {
+ { .compatible = "brcm,bcm7278-rng200", },
+ { .compatible = "brcm,iproc-rng200", },
++ { .compatible = "brcm,bcm2838-rng200"},
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, iproc_rng200_of_match);
+++ /dev/null
-From 6178ee953f25002e50b63af4b77b1f2a58ce17d6 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 29 Aug 2018 09:05:15 +0100
-Subject: [PATCH 540/703] mmc: bcm2835-sdhost: Support 64-bit physical
- addresses
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/mmc/host/bcm2835-sdhost.c | 10 ++++++----
- 1 file changed, 6 insertions(+), 4 deletions(-)
-
---- a/drivers/mmc/host/bcm2835-sdhost.c
-+++ b/drivers/mmc/host/bcm2835-sdhost.c
-@@ -148,7 +148,7 @@ struct bcm2835_host {
- spinlock_t lock;
-
- void __iomem *ioaddr;
-- u32 bus_addr;
-+ phys_addr_t bus_addr;
-
- struct mmc_host *mmc;
-
-@@ -246,8 +246,8 @@ static void log_init(struct device *dev,
- sdhost_log_buf = dma_zalloc_coherent(dev, LOG_SIZE, &sdhost_log_addr,
- GFP_KERNEL);
- if (sdhost_log_buf) {
-- pr_info("sdhost: log_buf @ %p (%x)\n",
-- sdhost_log_buf, (u32)sdhost_log_addr);
-+ pr_info("sdhost: log_buf @ %p (%llx)\n",
-+ sdhost_log_buf, (u64)sdhost_log_addr);
- timer_base = ioremap_nocache(bus_to_phys + 0x7e003000, SZ_4K);
- if (!timer_base)
- pr_err("sdhost: failed to remap timer\n");
-@@ -2024,6 +2024,7 @@ static int bcm2835_sdhost_probe(struct p
- struct mmc_host *mmc;
- const __be32 *addr;
- u32 msg[3];
-+ int na;
- int ret;
-
- pr_debug("bcm2835_sdhost_probe\n");
-@@ -2047,12 +2048,13 @@ static int bcm2835_sdhost_probe(struct p
- goto err;
- }
-
-+ na = of_n_addr_cells(node);
- addr = of_get_address(node, 0, NULL, NULL);
- if (!addr) {
- dev_err(dev, "could not get DMA-register address\n");
- return -ENODEV;
- }
-- host->bus_addr = be32_to_cpup(addr);
-+ host->bus_addr = (phys_addr_t)of_read_number(addr, na);
- pr_debug(" - ioaddr %lx, iomem->start %lx, bus_addr %lx\n",
- (unsigned long)host->ioaddr,
- (unsigned long)iomem->start,
--- /dev/null
+From fa0113f19ec808428cad9d92a17d13f17bfbd07e Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sat, 18 May 2019 12:26:11 +0200
+Subject: [PATCH 540/725] thermal: brcmstb_thermal: Add BCM2838 support
+
+The BCM2838 has an AVS TMON hardware block. This adds the necessary
+support to the brcmstb_thermal driver ( no trip handling ).
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ drivers/thermal/broadcom/Kconfig | 2 +-
+ drivers/thermal/broadcom/brcmstb_thermal.c | 65 +++++++++++++++++++---
+ 2 files changed, 58 insertions(+), 9 deletions(-)
+
+--- a/drivers/thermal/broadcom/Kconfig
++++ b/drivers/thermal/broadcom/Kconfig
+@@ -8,7 +8,7 @@ config BCM2835_THERMAL
+
+ config BRCMSTB_THERMAL
+ tristate "Broadcom STB AVS TMON thermal driver"
+- depends on ARCH_BRCMSTB || COMPILE_TEST
++ depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
+ help
+ Enable this driver if you have a Broadcom STB SoC and would like
+ thermal framework support.
+--- a/drivers/thermal/broadcom/brcmstb_thermal.c
++++ b/drivers/thermal/broadcom/brcmstb_thermal.c
+@@ -19,6 +19,7 @@
+ #define pr_fmt(fmt) DRV_NAME ": " fmt
+
+ #include <linux/bitops.h>
++#include <linux/clk.h>
+ #include <linux/device.h>
+ #include <linux/err.h>
+ #include <linux/io.h>
+@@ -31,9 +32,6 @@
+ #include <linux/thermal.h>
+
+ #define AVS_TMON_STATUS 0x00
+- #define AVS_TMON_STATUS_valid_msk BIT(11)
+- #define AVS_TMON_STATUS_data_msk GENMASK(10, 1)
+- #define AVS_TMON_STATUS_data_shift 1
+
+ #define AVS_TMON_EN_OVERTEMP_RESET 0x04
+ #define AVS_TMON_EN_OVERTEMP_RESET_msk BIT(0)
+@@ -111,10 +109,19 @@ static struct avs_tmon_trip avs_tmon_tri
+ },
+ };
+
++struct brcmstb_thermal_of_data {
++ const struct thermal_zone_of_device_ops *of_ops;
++ u32 status_valid_mask;
++ u32 status_data_mask;
++ u32 status_data_shift;
++};
++
+ struct brcmstb_thermal_priv {
+ void __iomem *tmon_base;
+ struct device *dev;
+ struct thermal_zone_device *thermal;
++ struct clk *clk;
++ const struct brcmstb_thermal_of_data *socdata;
+ };
+
+ static void avs_tmon_get_coeffs(struct thermal_zone_device *tz, int *slope,
+@@ -164,17 +171,18 @@ static inline u32 avs_tmon_temp_to_code(
+ static int brcmstb_get_temp(void *data, int *temp)
+ {
+ struct brcmstb_thermal_priv *priv = data;
++ const struct brcmstb_thermal_of_data *socdata = priv->socdata;
+ u32 val;
+ long t;
+
+ val = __raw_readl(priv->tmon_base + AVS_TMON_STATUS);
+
+- if (!(val & AVS_TMON_STATUS_valid_msk)) {
++ if (!(val & socdata->status_valid_mask)) {
+ dev_err(priv->dev, "reading not valid\n");
+ return -EIO;
+ }
+
+- val = (val & AVS_TMON_STATUS_data_msk) >> AVS_TMON_STATUS_data_shift;
++ val = (val & socdata->status_data_mask) >> socdata->status_data_shift;
+
+ t = avs_tmon_code_to_temp(priv->thermal, val);
+ if (t < 0)
+@@ -299,13 +307,34 @@ static int brcmstb_set_trips(void *data,
+ return 0;
+ }
+
+-static struct thermal_zone_of_device_ops of_ops = {
++static const struct thermal_zone_of_device_ops bcm7445_thermal_of_ops = {
+ .get_temp = brcmstb_get_temp,
+ .set_trips = brcmstb_set_trips,
+ };
+
++static const struct thermal_zone_of_device_ops bcm2838_thermal_of_ops = {
++ .get_temp = brcmstb_get_temp,
++};
++
++static const struct brcmstb_thermal_of_data bcm7445_thermal_of_data = {
++ .of_ops = &bcm7445_thermal_of_ops,
++ .status_valid_mask = BIT(11),
++ .status_data_mask = GENMASK(10, 1),
++ .status_data_shift = 1,
++};
++
++static const struct brcmstb_thermal_of_data bcm2838_thermal_of_data = {
++ .of_ops = &bcm2838_thermal_of_ops,
++ .status_valid_mask = BIT(10),
++ .status_data_mask = GENMASK(9, 0),
++ .status_data_shift = 0,
++};
++
+ static const struct of_device_id brcmstb_thermal_id_table[] = {
+- { .compatible = "brcm,avs-tmon" },
++ { .compatible = "brcm,avs-tmon",
++ .data = &bcm7445_thermal_of_data },
++ { .compatible = "brcm,avs-tmon-bcm2838",
++ .data = &bcm2838_thermal_of_data },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, brcmstb_thermal_id_table);
+@@ -326,10 +355,27 @@ static int brcmstb_thermal_probe(struct
+ if (IS_ERR(priv->tmon_base))
+ return PTR_ERR(priv->tmon_base);
+
++ priv->socdata = of_device_get_match_data(&pdev->dev);
++ if (!priv->socdata) {
++ dev_err(&pdev->dev, "no device match found\n");
++ return -ENODEV;
++ }
++
++ priv->clk = devm_clk_get(&pdev->dev, NULL);
++ if (IS_ERR(priv->clk) && PTR_ERR(priv->clk) == -EPROBE_DEFER)
++ return -EPROBE_DEFER;
++
++ if (!IS_ERR(priv->clk)) {
++ ret = clk_prepare_enable(priv->clk);
++ if (ret)
++ return ret;
++ }
++
+ priv->dev = &pdev->dev;
+ platform_set_drvdata(pdev, priv);
+
+- thermal = thermal_zone_of_sensor_register(&pdev->dev, 0, priv, &of_ops);
++ thermal = thermal_zone_of_sensor_register(&pdev->dev, 0, priv,
++ priv->socdata->of_ops);
+ if (IS_ERR(thermal)) {
+ ret = PTR_ERR(thermal);
+ dev_err(&pdev->dev, "could not register sensor: %d\n", ret);
+@@ -369,6 +415,9 @@ static int brcmstb_thermal_exit(struct p
+ if (thermal)
+ thermal_zone_of_sensor_unregister(&pdev->dev, priv->thermal);
+
++ if (!IS_ERR(priv->clk))
++ clk_disable_unprepare(priv->clk);
++
+ return 0;
+ }
+
+++ /dev/null
-From 80e4525509000d3f7faebbc9ea403c9776aab2c5 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 28 Sep 2018 16:24:05 +0100
-Subject: [PATCH 541/703] mmc: sdhci: Mask "spurious" interrupts
-
-Add a filter for "spurious" Transfer Complete interrupts, attempting
-to make it as specific as possible:
-* INT_DATA_END (transfer complete) is set
-* There is a stop command in progress
-* There is no data transfer in progress
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/mmc/host/sdhci.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/mmc/host/sdhci.c
-+++ b/drivers/mmc/host/sdhci.c
-@@ -2930,6 +2930,10 @@ static irqreturn_t sdhci_irq(int irq, vo
- result = IRQ_WAKE_THREAD;
- }
-
-+ if ((intmask & SDHCI_INT_DATA_END) && !host->data &&
-+ host->cmd && (host->cmd == host->cmd->mrq->stop))
-+ intmask &= ~SDHCI_INT_DATA_END;
-+
- if (intmask & SDHCI_INT_CMD_MASK)
- sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, &intmask);
-
--- /dev/null
+From 2d12aba4b1475c04f247b96075ad1a7f65152a23 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 1 Nov 2018 17:31:37 +0000
+Subject: [PATCH 541/725] vchiq: Add 36-bit address support
+
+Conditional on a new compatible string, change the pagelist encoding
+such that the top 24 bits are the pfn, leaving 8 bits for run length
+(-1).
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ .../interface/vchiq_arm/vchiq_2835_arm.c | 90 ++++++++++++++-----
+ .../interface/vchiq_arm/vchiq_arm.c | 6 ++
+ .../interface/vchiq_arm/vchiq_arm.h | 1 +
+ 3 files changed, 75 insertions(+), 22 deletions(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
+@@ -47,6 +47,8 @@
+ #include <soc/bcm2835/raspberrypi-firmware.h>
+
+ #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32)
++#define VC_SAFE(x) (g_use_36bit_addrs ? ((u32)(x) | 0xc0000000) : (u32)(x))
++#define IS_VC_SAFE(x) (g_use_36bit_addrs ? !((x) & ~0x3fffffffull) : 1)
+
+ #include "vchiq_arm.h"
+ #include "vchiq_connected.h"
+@@ -96,6 +98,7 @@ static void __iomem *g_regs;
+ */
+ static unsigned int g_cache_line_size;
+ static struct dma_pool *g_dma_pool;
++static unsigned int g_use_36bit_addrs = 0;
+ static unsigned int g_fragments_size;
+ static char *g_fragments_base;
+ static char *g_free_fragments;
+@@ -139,6 +142,8 @@ int vchiq_platform_init(struct platform_
+ g_cache_line_size = drvdata->cache_line_size;
+ g_fragments_size = 2 * g_cache_line_size;
+
++ g_use_36bit_addrs = (dev->dma_pfn_offset == 0);
++
+ /* Allocate space for the channels in coherent memory */
+ slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE);
+ frag_mem_size = PAGE_ALIGN(g_fragments_size * MAX_FRAGMENTS);
+@@ -150,14 +155,21 @@ int vchiq_platform_init(struct platform_
+ return -ENOMEM;
+ }
+
++ if (!IS_VC_SAFE(slot_phys)) {
++ dev_err(dev, "allocated DMA memory %pad is not VC-safe\n",
++ &slot_phys);
++ return -ENOMEM;
++ }
++
+ WARN_ON(((unsigned long)slot_mem & (PAGE_SIZE - 1)) != 0);
++ channelbase = VC_SAFE(slot_phys);
+
+ vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size);
+ if (!vchiq_slot_zero)
+ return -EINVAL;
+
+ vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] =
+- (int)slot_phys + slot_mem_size;
++ channelbase + slot_mem_size;
+ vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] =
+ MAX_FRAGMENTS;
+
+@@ -193,7 +205,6 @@ int vchiq_platform_init(struct platform_
+ }
+
+ /* Send the base address of the slots to VideoCore */
+- channelbase = slot_phys;
+ err = rpi_firmware_property(fw, RPI_FIRMWARE_VCHIQ_INIT,
+ &channelbase, sizeof(channelbase));
+ if (err || channelbase) {
+@@ -282,7 +293,7 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bu
+ return VCHIQ_ERROR;
+
+ bulk->handle = memhandle;
+- bulk->data = (void *)(unsigned long)pagelistinfo->dma_addr;
++ bulk->data = (void *)VC_SAFE(pagelistinfo->dma_addr);
+
+ /*
+ * Store the pagelistinfo address in remote_data,
+@@ -570,25 +581,60 @@ create_pagelist(char __user *buf, size_t
+
+ /* Combine adjacent blocks for performance */
+ k = 0;
+- for_each_sg(scatterlist, sg, dma_buffers, i) {
+- u32 len = sg_dma_len(sg);
+- u32 addr = sg_dma_address(sg);
+-
+- /* Note: addrs is the address + page_count - 1
+- * The firmware expects blocks after the first to be page-
+- * aligned and a multiple of the page size
+- */
+- WARN_ON(len == 0);
+- 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))
+- == (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);
++ if (g_use_36bit_addrs) {
++ for_each_sg(scatterlist, sg, dma_buffers, i) {
++ u32 len = sg_dma_len(sg);
++ u64 addr = sg_dma_address(sg);
++ u32 page_id = (u32)((addr >> 4) & ~0xff);
++ u32 sg_pages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
++
++ /* Note: addrs is the address + page_count - 1
++ * The firmware expects blocks after the first to be page-
++ * aligned and a multiple of the page size
++ */
++ WARN_ON(len == 0);
++ WARN_ON(i &&
++ (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
++ WARN_ON(i && (addr & ~PAGE_MASK));
++ WARN_ON(upper_32_bits(addr) > 0xf);
++ if (k > 0 &&
++ ((addrs[k - 1] & ~0xff) +
++ (((addrs[k - 1] & 0xff) + 1) << 8)
++ == page_id)) {
++ u32 inc_pages = min(sg_pages,
++ 0xff - (addrs[k - 1] & 0xff));
++ addrs[k - 1] += inc_pages;
++ page_id += inc_pages << 8;
++ sg_pages -= inc_pages;
++ }
++ while (sg_pages) {
++ u32 inc_pages = min(sg_pages, 0x100u);
++ addrs[k++] = page_id | (inc_pages - 1);
++ page_id += inc_pages << 8;
++ sg_pages -= inc_pages;
++ }
++ }
++ } else {
++ for_each_sg(scatterlist, sg, dma_buffers, i) {
++ u32 len = sg_dma_len(sg);
++ u32 addr = VC_SAFE(sg_dma_address(sg));
++ u32 new_pages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
++
++ /* Note: addrs is the address + page_count - 1
++ * The firmware expects blocks after the first to be page-
++ * aligned and a multiple of the page size
++ */
++ WARN_ON(len == 0);
++ 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))
++ == (addr & PAGE_MASK))
++ addrs[k - 1] += new_pages;
++ else
++ addrs[k++] = (addr & PAGE_MASK) | (new_pages - 1);
++ }
+ }
+
+ /* Partial cache lines (fragments) require special measures */
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -181,6 +181,11 @@ static struct vchiq_drvdata bcm2836_drvd
+ .cache_line_size = 64,
+ };
+
++static struct vchiq_drvdata bcm2838_drvdata = {
++ .cache_line_size = 64,
++ .use_36bit_addrs = true,
++};
++
+ static const char *const ioctl_names[] = {
+ "CONNECT",
+ "SHUTDOWN",
+@@ -3618,6 +3623,7 @@ vchiq_register_child(struct platform_dev
+ static const struct of_device_id vchiq_of_match[] = {
+ { .compatible = "brcm,bcm2835-vchiq", .data = &bcm2835_drvdata },
+ { .compatible = "brcm,bcm2836-vchiq", .data = &bcm2836_drvdata },
++ { .compatible = "brcm,bcm2838-vchiq", .data = &bcm2838_drvdata },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, vchiq_of_match);
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
+@@ -125,6 +125,7 @@ typedef struct vchiq_arm_state_struct {
+
+ struct vchiq_drvdata {
+ const unsigned int cache_line_size;
++ const bool use_36bit_addrs;
+ struct rpi_firmware *fw;
+ };
+
--- /dev/null
+From 23793b5dcab413aaf7f7551aaa9473670b111832 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Tue, 30 Apr 2019 19:15:30 +0100
+Subject: [PATCH 542/725] bcm2835-pcm.c: Support multichannel audio
+
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -14,9 +14,9 @@ static const struct snd_pcm_hardware snd
+ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
+ .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
+- .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
++ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000,
+ .rate_min = 8000,
+- .rate_max = 48000,
++ .rate_max = 192000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = 128 * 1024,
+@@ -31,15 +31,16 @@ static const struct snd_pcm_hardware snd
+ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+- .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
+- SNDRV_PCM_RATE_48000,
++ .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
++ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
++ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
+ .rate_min = 44100,
+- .rate_max = 48000,
++ .rate_max = 192000,
+ .channels_min = 2,
+- .channels_max = 2,
+- .buffer_bytes_max = 128 * 1024,
++ .channels_max = 8,
++ .buffer_bytes_max = 512 * 1024,
+ .period_bytes_min = 1 * 1024,
+- .period_bytes_max = 128 * 1024,
++ .period_bytes_max = 512 * 1024,
+ .periods_min = 1,
+ .periods_max = 128,
+ };
+++ /dev/null
-From 8433b9112a42c8f7b0fefeac50e2f3ebb3ab956c Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sat, 27 Apr 2019 12:33:57 +0200
-Subject: [PATCH 542/703] mmc: sdhci-iproc: Add support for emmc2 of the
- BCM2838
-
-The emmc2 interface of the BCM2838 should be integrated in sdhci-iproc
-to avoid code redundancy. Except 32 bit only access no other quirks are
-known yet. Add an additional compatible string for upstream proposal.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- drivers/mmc/host/sdhci-iproc.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/drivers/mmc/host/sdhci-iproc.c
-+++ b/drivers/mmc/host/sdhci-iproc.c
-@@ -250,8 +250,18 @@ static const struct sdhci_iproc_data bcm
- .mmc_caps = 0x00000000,
- };
-
-+static const struct sdhci_pltfm_data sdhci_bcm2838_pltfm_data = {
-+ .ops = &sdhci_iproc_32only_ops,
-+};
-+
-+static const struct sdhci_iproc_data bcm2838_data = {
-+ .pdata = &sdhci_bcm2838_pltfm_data,
-+};
-+
- static const struct of_device_id sdhci_iproc_of_match[] = {
- { .compatible = "brcm,bcm2835-sdhci", .data = &bcm2835_data },
-+ { .compatible = "brcm,bcm2838-sdhci", .data = &bcm2838_data },
-+ { .compatible = "brcm,bcm2711-emmc2", .data = &bcm2838_data },
- { .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_cygnus_data},
- { .compatible = "brcm,sdhci-iproc", .data = &iproc_data },
- { }
--- /dev/null
+From 99f79579e704a5fa56238e8c650289fda6a67071 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Wed, 12 Sep 2018 14:44:53 +0100
+Subject: [PATCH 543/725] bcmgenet: constrain max DMA burst length
+
+---
+ drivers/net/ethernet/broadcom/genet/bcmgenet.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+@@ -31,7 +31,7 @@
+ #define ENET_PAD 8
+ #define ENET_MAX_MTU_SIZE (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + \
+ ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD)
+-#define DMA_MAX_BURST_LENGTH 0x10
++#define DMA_MAX_BURST_LENGTH 0x08
+
+ /* misc. configuration */
+ #define CLEAR_ALL_HFB 0xFF
+++ /dev/null
-From 60dfcaef2e9fb7fd79b7a87c25cd520b82c6dd02 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sat, 4 May 2019 17:06:15 +0200
-Subject: [PATCH 543/703] hwrng: iproc-rng200: Add BCM2838 support
-
-The HWRNG on the BCM2838 is compatible to iproc-rng200, so add the
-support to this driver instead of bcm2835-rng.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- drivers/char/hw_random/Kconfig | 4 +-
- drivers/char/hw_random/iproc-rng200.c | 81 +++++++++++++++++++++++++--
- 2 files changed, 79 insertions(+), 6 deletions(-)
-
---- a/drivers/char/hw_random/Kconfig
-+++ b/drivers/char/hw_random/Kconfig
-@@ -89,11 +89,11 @@ config HW_RANDOM_BCM2835
-
- config HW_RANDOM_IPROC_RNG200
- tristate "Broadcom iProc/STB RNG200 support"
-- depends on ARCH_BCM_IPROC || ARCH_BRCMSTB
-+ depends on ARCH_BCM_IPROC || ARCH_BCM2835 || ARCH_BRCMSTB
- default HW_RANDOM
- ---help---
- This driver provides kernel-side support for the RNG200
-- hardware found on the Broadcom iProc and STB SoCs.
-+ hardware found on the Broadcom iProc, BCM2838 and STB SoCs.
-
- To compile this driver as a module, choose M here: the
- module will be called iproc-rng200
---- a/drivers/char/hw_random/iproc-rng200.c
-+++ b/drivers/char/hw_random/iproc-rng200.c
-@@ -29,6 +29,7 @@
- #define RNG_CTRL_RNG_RBGEN_MASK 0x00001FFF
- #define RNG_CTRL_RNG_RBGEN_ENABLE 0x00000001
- #define RNG_CTRL_RNG_RBGEN_DISABLE 0x00000000
-+#define RNG_CTRL_RNG_DIV_CTRL_SHIFT 13
-
- #define RNG_SOFT_RESET_OFFSET 0x04
- #define RNG_SOFT_RESET 0x00000001
-@@ -36,16 +37,23 @@
- #define RBG_SOFT_RESET_OFFSET 0x08
- #define RBG_SOFT_RESET 0x00000001
-
-+#define RNG_TOTAL_BIT_COUNT_OFFSET 0x0C
-+
-+#define RNG_TOTAL_BIT_COUNT_THRESHOLD_OFFSET 0x10
-+
- #define RNG_INT_STATUS_OFFSET 0x18
- #define RNG_INT_STATUS_MASTER_FAIL_LOCKOUT_IRQ_MASK 0x80000000
- #define RNG_INT_STATUS_STARTUP_TRANSITIONS_MET_IRQ_MASK 0x00020000
- #define RNG_INT_STATUS_NIST_FAIL_IRQ_MASK 0x00000020
- #define RNG_INT_STATUS_TOTAL_BITS_COUNT_IRQ_MASK 0x00000001
-
-+#define RNG_INT_ENABLE_OFFSET 0x1C
-+
- #define RNG_FIFO_DATA_OFFSET 0x20
-
- #define RNG_FIFO_COUNT_OFFSET 0x24
- #define RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK 0x000000FF
-+#define RNG_FIFO_COUNT_RNG_FIFO_THRESHOLD_SHIFT 8
-
- struct iproc_rng200_dev {
- struct hwrng rng;
-@@ -166,6 +174,64 @@ static int iproc_rng200_init(struct hwrn
- return 0;
- }
-
-+static int bcm2838_rng200_read(struct hwrng *rng, void *buf, size_t max,
-+ bool wait)
-+{
-+ struct iproc_rng200_dev *priv = to_rng_priv(rng);
-+ u32 max_words = max / sizeof(u32);
-+ u32 num_words, count, val;
-+
-+ /* ensure warm up period has elapsed */
-+ while (1) {
-+ val = ioread32(priv->base + RNG_TOTAL_BIT_COUNT_OFFSET);
-+ if (val > 16)
-+ break;
-+ cpu_relax();
-+ }
-+
-+ /* ensure fifo is not empty */
-+ while (1) {
-+ num_words = ioread32(priv->base + RNG_FIFO_COUNT_OFFSET) &
-+ RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK;
-+ if (num_words)
-+ break;
-+ if (!wait)
-+ return 0;
-+ cpu_relax();
-+ }
-+
-+ if (num_words > max_words)
-+ num_words = max_words;
-+
-+ for (count = 0; count < num_words; count++) {
-+ ((u32 *)buf)[count] = ioread32(priv->base +
-+ RNG_FIFO_DATA_OFFSET);
-+ }
-+
-+ return num_words * sizeof(u32);
-+}
-+
-+static int bcm2838_rng200_init(struct hwrng *rng)
-+{
-+ struct iproc_rng200_dev *priv = to_rng_priv(rng);
-+ uint32_t val;
-+
-+ if (ioread32(priv->base + RNG_CTRL_OFFSET) & RNG_CTRL_RNG_RBGEN_MASK)
-+ return 0;
-+
-+ /* initial numbers generated are "less random" so will be discarded */
-+ val = 0x40000;
-+ iowrite32(val, priv->base + RNG_TOTAL_BIT_COUNT_THRESHOLD_OFFSET);
-+ /* min fifo count to generate full interrupt */
-+ val = 2 << RNG_FIFO_COUNT_RNG_FIFO_THRESHOLD_SHIFT;
-+ iowrite32(val, priv->base + RNG_FIFO_COUNT_OFFSET);
-+ /* enable the rng - 1Mhz sample rate */
-+ val = (0x3 << RNG_CTRL_RNG_DIV_CTRL_SHIFT) | RNG_CTRL_RNG_RBGEN_MASK;
-+ iowrite32(val, priv->base + RNG_CTRL_OFFSET);
-+
-+ return 0;
-+}
-+
- static void iproc_rng200_cleanup(struct hwrng *rng)
- {
- struct iproc_rng200_dev *priv = to_rng_priv(rng);
-@@ -202,10 +268,16 @@ static int iproc_rng200_probe(struct pla
- return PTR_ERR(priv->base);
- }
-
-- priv->rng.name = "iproc-rng200",
-- priv->rng.read = iproc_rng200_read,
-- priv->rng.init = iproc_rng200_init,
-- priv->rng.cleanup = iproc_rng200_cleanup,
-+ priv->rng.name = pdev->name;
-+ priv->rng.cleanup = iproc_rng200_cleanup;
-+
-+ if (of_device_is_compatible(dev->of_node, "brcm,bcm2838-rng200")) {
-+ priv->rng.init = bcm2838_rng200_init;
-+ priv->rng.read = bcm2838_rng200_read;
-+ } else {
-+ priv->rng.init = iproc_rng200_init;
-+ priv->rng.read = iproc_rng200_read;
-+ }
-
- /* Register driver */
- ret = devm_hwrng_register(dev, &priv->rng);
-@@ -222,6 +294,7 @@ static int iproc_rng200_probe(struct pla
- static const struct of_device_id iproc_rng200_of_match[] = {
- { .compatible = "brcm,bcm7278-rng200", },
- { .compatible = "brcm,iproc-rng200", },
-+ { .compatible = "brcm,bcm2838-rng200"},
- {},
- };
- MODULE_DEVICE_TABLE(of, iproc_rng200_of_match);
--- /dev/null
+From 9e374c8058f9fc6dc4069f2cf878ca941f5836d3 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 27 Mar 2019 13:45:46 +0000
+Subject: [PATCH 544/725] bcmgenet: Better coalescing parameter defaults
+
+Set defaults for TX and RX packet coalescing to be equivalent to:
+
+ # ethtool -C eth0 tx-frames 10
+ # ethtool -C eth0 rx-usecs 50
+
+This may be something we want to set via DT parameters in the
+future.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/net/ethernet/broadcom/genet/bcmgenet.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+@@ -2147,7 +2147,7 @@ static void bcmgenet_init_tx_ring(struct
+
+ bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_PROD_INDEX);
+ bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_CONS_INDEX);
+- bcmgenet_tdma_ring_writel(priv, index, 1, DMA_MBUF_DONE_THRESH);
++ bcmgenet_tdma_ring_writel(priv, index, 10, DMA_MBUF_DONE_THRESH);
+ /* Disable rate control for now */
+ bcmgenet_tdma_ring_writel(priv, index, flow_period_val,
+ TDMA_FLOW_PERIOD);
+@@ -3571,9 +3571,12 @@ static int bcmgenet_probe(struct platfor
+ netif_set_real_num_rx_queues(priv->dev, priv->hw_params->rx_queues + 1);
+
+ /* Set default coalescing parameters */
+- for (i = 0; i < priv->hw_params->rx_queues; i++)
++ for (i = 0; i < priv->hw_params->rx_queues; i++) {
+ priv->rx_rings[i].rx_max_coalesced_frames = 1;
++ priv->rx_rings[i].rx_coalesce_usecs = 50;
++ }
+ priv->rx_rings[DESC_INDEX].rx_max_coalesced_frames = 1;
++ priv->rx_rings[DESC_INDEX].rx_coalesce_usecs = 50;
+
+ /* libphy will determine the link state */
+ netif_carrier_off(dev);
+++ /dev/null
-From bbb17da9724f068cc4cd7620c6d75b09a3d76a96 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sat, 18 May 2019 12:26:11 +0200
-Subject: [PATCH 544/703] thermal: brcmstb_thermal: Add BCM2838 support
-
-The BCM2838 has an AVS TMON hardware block. This adds the necessary
-support to the brcmstb_thermal driver ( no trip handling ).
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- drivers/thermal/broadcom/Kconfig | 2 +-
- drivers/thermal/broadcom/brcmstb_thermal.c | 65 +++++++++++++++++++---
- 2 files changed, 58 insertions(+), 9 deletions(-)
-
---- a/drivers/thermal/broadcom/Kconfig
-+++ b/drivers/thermal/broadcom/Kconfig
-@@ -8,7 +8,7 @@ config BCM2835_THERMAL
-
- config BRCMSTB_THERMAL
- tristate "Broadcom STB AVS TMON thermal driver"
-- depends on ARCH_BRCMSTB || COMPILE_TEST
-+ depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
- help
- Enable this driver if you have a Broadcom STB SoC and would like
- thermal framework support.
---- a/drivers/thermal/broadcom/brcmstb_thermal.c
-+++ b/drivers/thermal/broadcom/brcmstb_thermal.c
-@@ -19,6 +19,7 @@
- #define pr_fmt(fmt) DRV_NAME ": " fmt
-
- #include <linux/bitops.h>
-+#include <linux/clk.h>
- #include <linux/device.h>
- #include <linux/err.h>
- #include <linux/io.h>
-@@ -31,9 +32,6 @@
- #include <linux/thermal.h>
-
- #define AVS_TMON_STATUS 0x00
-- #define AVS_TMON_STATUS_valid_msk BIT(11)
-- #define AVS_TMON_STATUS_data_msk GENMASK(10, 1)
-- #define AVS_TMON_STATUS_data_shift 1
-
- #define AVS_TMON_EN_OVERTEMP_RESET 0x04
- #define AVS_TMON_EN_OVERTEMP_RESET_msk BIT(0)
-@@ -111,10 +109,19 @@ static struct avs_tmon_trip avs_tmon_tri
- },
- };
-
-+struct brcmstb_thermal_of_data {
-+ const struct thermal_zone_of_device_ops *of_ops;
-+ u32 status_valid_mask;
-+ u32 status_data_mask;
-+ u32 status_data_shift;
-+};
-+
- struct brcmstb_thermal_priv {
- void __iomem *tmon_base;
- struct device *dev;
- struct thermal_zone_device *thermal;
-+ struct clk *clk;
-+ const struct brcmstb_thermal_of_data *socdata;
- };
-
- static void avs_tmon_get_coeffs(struct thermal_zone_device *tz, int *slope,
-@@ -164,17 +171,18 @@ static inline u32 avs_tmon_temp_to_code(
- static int brcmstb_get_temp(void *data, int *temp)
- {
- struct brcmstb_thermal_priv *priv = data;
-+ const struct brcmstb_thermal_of_data *socdata = priv->socdata;
- u32 val;
- long t;
-
- val = __raw_readl(priv->tmon_base + AVS_TMON_STATUS);
-
-- if (!(val & AVS_TMON_STATUS_valid_msk)) {
-+ if (!(val & socdata->status_valid_mask)) {
- dev_err(priv->dev, "reading not valid\n");
- return -EIO;
- }
-
-- val = (val & AVS_TMON_STATUS_data_msk) >> AVS_TMON_STATUS_data_shift;
-+ val = (val & socdata->status_data_mask) >> socdata->status_data_shift;
-
- t = avs_tmon_code_to_temp(priv->thermal, val);
- if (t < 0)
-@@ -299,13 +307,34 @@ static int brcmstb_set_trips(void *data,
- return 0;
- }
-
--static struct thermal_zone_of_device_ops of_ops = {
-+static const struct thermal_zone_of_device_ops bcm7445_thermal_of_ops = {
- .get_temp = brcmstb_get_temp,
- .set_trips = brcmstb_set_trips,
- };
-
-+static const struct thermal_zone_of_device_ops bcm2838_thermal_of_ops = {
-+ .get_temp = brcmstb_get_temp,
-+};
-+
-+static const struct brcmstb_thermal_of_data bcm7445_thermal_of_data = {
-+ .of_ops = &bcm7445_thermal_of_ops,
-+ .status_valid_mask = BIT(11),
-+ .status_data_mask = GENMASK(10, 1),
-+ .status_data_shift = 1,
-+};
-+
-+static const struct brcmstb_thermal_of_data bcm2838_thermal_of_data = {
-+ .of_ops = &bcm2838_thermal_of_ops,
-+ .status_valid_mask = BIT(10),
-+ .status_data_mask = GENMASK(9, 0),
-+ .status_data_shift = 0,
-+};
-+
- static const struct of_device_id brcmstb_thermal_id_table[] = {
-- { .compatible = "brcm,avs-tmon" },
-+ { .compatible = "brcm,avs-tmon",
-+ .data = &bcm7445_thermal_of_data },
-+ { .compatible = "brcm,avs-tmon-bcm2838",
-+ .data = &bcm2838_thermal_of_data },
- {},
- };
- MODULE_DEVICE_TABLE(of, brcmstb_thermal_id_table);
-@@ -326,10 +355,27 @@ static int brcmstb_thermal_probe(struct
- if (IS_ERR(priv->tmon_base))
- return PTR_ERR(priv->tmon_base);
-
-+ priv->socdata = of_device_get_match_data(&pdev->dev);
-+ if (!priv->socdata) {
-+ dev_err(&pdev->dev, "no device match found\n");
-+ return -ENODEV;
-+ }
-+
-+ priv->clk = devm_clk_get(&pdev->dev, NULL);
-+ if (IS_ERR(priv->clk) && PTR_ERR(priv->clk) == -EPROBE_DEFER)
-+ return -EPROBE_DEFER;
-+
-+ if (!IS_ERR(priv->clk)) {
-+ ret = clk_prepare_enable(priv->clk);
-+ if (ret)
-+ return ret;
-+ }
-+
- priv->dev = &pdev->dev;
- platform_set_drvdata(pdev, priv);
-
-- thermal = thermal_zone_of_sensor_register(&pdev->dev, 0, priv, &of_ops);
-+ thermal = thermal_zone_of_sensor_register(&pdev->dev, 0, priv,
-+ priv->socdata->of_ops);
- if (IS_ERR(thermal)) {
- ret = PTR_ERR(thermal);
- dev_err(&pdev->dev, "could not register sensor: %d\n", ret);
-@@ -369,6 +415,9 @@ static int brcmstb_thermal_exit(struct p
- if (thermal)
- thermal_zone_of_sensor_unregister(&pdev->dev, priv->thermal);
-
-+ if (!IS_ERR(priv->clk))
-+ clk_disable_unprepare(priv->clk);
-+
- return 0;
- }
-
--- /dev/null
+From fd72c4f7da285c5dee66f01cdec075a5d863a3a3 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 14 May 2019 17:17:59 +0100
+Subject: [PATCH 545/725] net: genet: enable link energy detect powerdown for
+ external PHYs
+
+There are several warts surrounding bcmgenet_mii_probe() as this
+function is called from ndo_open, but it's calling registration-type
+functions. The probe should be called at probe time and refactored
+such that the PHY device data can be extracted to limit the scope
+of this flag to Broadcom PHYs.
+
+For now, pass this flag in as it puts our attached PHY into a low-power
+state when disconnected.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/net/ethernet/broadcom/genet/bcmmii.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
+@@ -280,7 +280,10 @@ int bcmgenet_mii_probe(struct net_device
+ int ret;
+
+ /* Communicate the integrated PHY revision */
+- phy_flags = priv->gphy_rev;
++ if (priv->internal_phy)
++ phy_flags = priv->gphy_rev;
++ else
++ phy_flags = PHY_BRCM_AUTO_PWRDWN_ENABLE;
+
+ /* Initialize link state variables that bcmgenet_mii_setup() uses */
+ priv->old_link = -1;
+++ /dev/null
-From f9625d8ee77e57593af378a1d60708fc8d43db46 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 1 Nov 2018 17:31:37 +0000
-Subject: [PATCH 545/703] vchiq: Add 36-bit address support
-
-Conditional on a new compatible string, change the pagelist encoding
-such that the top 24 bits are the pfn, leaving 8 bits for run length
-(-1).
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- .../interface/vchiq_arm/vchiq_2835_arm.c | 90 ++++++++++++++-----
- .../interface/vchiq_arm/vchiq_arm.c | 6 ++
- .../interface/vchiq_arm/vchiq_arm.h | 1 +
- 3 files changed, 75 insertions(+), 22 deletions(-)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
-@@ -47,6 +47,8 @@
- #include <soc/bcm2835/raspberrypi-firmware.h>
-
- #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32)
-+#define VC_SAFE(x) (g_use_36bit_addrs ? ((u32)(x) | 0xc0000000) : (u32)(x))
-+#define IS_VC_SAFE(x) (g_use_36bit_addrs ? !((x) & ~0x3fffffffull) : 1)
-
- #include "vchiq_arm.h"
- #include "vchiq_connected.h"
-@@ -96,6 +98,7 @@ static void __iomem *g_regs;
- */
- static unsigned int g_cache_line_size;
- static struct dma_pool *g_dma_pool;
-+static unsigned int g_use_36bit_addrs = 0;
- static unsigned int g_fragments_size;
- static char *g_fragments_base;
- static char *g_free_fragments;
-@@ -139,6 +142,8 @@ int vchiq_platform_init(struct platform_
- g_cache_line_size = drvdata->cache_line_size;
- g_fragments_size = 2 * g_cache_line_size;
-
-+ g_use_36bit_addrs = (dev->dma_pfn_offset == 0);
-+
- /* Allocate space for the channels in coherent memory */
- slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE);
- frag_mem_size = PAGE_ALIGN(g_fragments_size * MAX_FRAGMENTS);
-@@ -150,14 +155,21 @@ int vchiq_platform_init(struct platform_
- return -ENOMEM;
- }
-
-+ if (!IS_VC_SAFE(slot_phys)) {
-+ dev_err(dev, "allocated DMA memory %pad is not VC-safe\n",
-+ &slot_phys);
-+ return -ENOMEM;
-+ }
-+
- WARN_ON(((unsigned long)slot_mem & (PAGE_SIZE - 1)) != 0);
-+ channelbase = VC_SAFE(slot_phys);
-
- vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size);
- if (!vchiq_slot_zero)
- return -EINVAL;
-
- vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] =
-- (int)slot_phys + slot_mem_size;
-+ channelbase + slot_mem_size;
- vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] =
- MAX_FRAGMENTS;
-
-@@ -193,7 +205,6 @@ int vchiq_platform_init(struct platform_
- }
-
- /* Send the base address of the slots to VideoCore */
-- channelbase = slot_phys;
- err = rpi_firmware_property(fw, RPI_FIRMWARE_VCHIQ_INIT,
- &channelbase, sizeof(channelbase));
- if (err || channelbase) {
-@@ -282,7 +293,7 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bu
- return VCHIQ_ERROR;
-
- bulk->handle = memhandle;
-- bulk->data = (void *)(unsigned long)pagelistinfo->dma_addr;
-+ bulk->data = (void *)VC_SAFE(pagelistinfo->dma_addr);
-
- /*
- * Store the pagelistinfo address in remote_data,
-@@ -570,25 +581,60 @@ create_pagelist(char __user *buf, size_t
-
- /* Combine adjacent blocks for performance */
- k = 0;
-- for_each_sg(scatterlist, sg, dma_buffers, i) {
-- u32 len = sg_dma_len(sg);
-- u32 addr = sg_dma_address(sg);
--
-- /* Note: addrs is the address + page_count - 1
-- * The firmware expects blocks after the first to be page-
-- * aligned and a multiple of the page size
-- */
-- WARN_ON(len == 0);
-- 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))
-- == (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);
-+ if (g_use_36bit_addrs) {
-+ for_each_sg(scatterlist, sg, dma_buffers, i) {
-+ u32 len = sg_dma_len(sg);
-+ u64 addr = sg_dma_address(sg);
-+ u32 page_id = (u32)((addr >> 4) & ~0xff);
-+ u32 sg_pages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
-+
-+ /* Note: addrs is the address + page_count - 1
-+ * The firmware expects blocks after the first to be page-
-+ * aligned and a multiple of the page size
-+ */
-+ WARN_ON(len == 0);
-+ WARN_ON(i &&
-+ (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
-+ WARN_ON(i && (addr & ~PAGE_MASK));
-+ WARN_ON(upper_32_bits(addr) > 0xf);
-+ if (k > 0 &&
-+ ((addrs[k - 1] & ~0xff) +
-+ (((addrs[k - 1] & 0xff) + 1) << 8)
-+ == page_id)) {
-+ u32 inc_pages = min(sg_pages,
-+ 0xff - (addrs[k - 1] & 0xff));
-+ addrs[k - 1] += inc_pages;
-+ page_id += inc_pages << 8;
-+ sg_pages -= inc_pages;
-+ }
-+ while (sg_pages) {
-+ u32 inc_pages = min(sg_pages, 0x100u);
-+ addrs[k++] = page_id | (inc_pages - 1);
-+ page_id += inc_pages << 8;
-+ sg_pages -= inc_pages;
-+ }
-+ }
-+ } else {
-+ for_each_sg(scatterlist, sg, dma_buffers, i) {
-+ u32 len = sg_dma_len(sg);
-+ u32 addr = VC_SAFE(sg_dma_address(sg));
-+ u32 new_pages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
-+
-+ /* Note: addrs is the address + page_count - 1
-+ * The firmware expects blocks after the first to be page-
-+ * aligned and a multiple of the page size
-+ */
-+ WARN_ON(len == 0);
-+ 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))
-+ == (addr & PAGE_MASK))
-+ addrs[k - 1] += new_pages;
-+ else
-+ addrs[k++] = (addr & PAGE_MASK) | (new_pages - 1);
-+ }
- }
-
- /* Partial cache lines (fragments) require special measures */
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -181,6 +181,11 @@ static struct vchiq_drvdata bcm2836_drvd
- .cache_line_size = 64,
- };
-
-+static struct vchiq_drvdata bcm2838_drvdata = {
-+ .cache_line_size = 64,
-+ .use_36bit_addrs = true,
-+};
-+
- static const char *const ioctl_names[] = {
- "CONNECT",
- "SHUTDOWN",
-@@ -3618,6 +3623,7 @@ vchiq_register_child(struct platform_dev
- static const struct of_device_id vchiq_of_match[] = {
- { .compatible = "brcm,bcm2835-vchiq", .data = &bcm2835_drvdata },
- { .compatible = "brcm,bcm2836-vchiq", .data = &bcm2836_drvdata },
-+ { .compatible = "brcm,bcm2838-vchiq", .data = &bcm2838_drvdata },
- {},
- };
- MODULE_DEVICE_TABLE(of, vchiq_of_match);
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
-@@ -125,6 +125,7 @@ typedef struct vchiq_arm_state_struct {
-
- struct vchiq_drvdata {
- const unsigned int cache_line_size;
-+ const bool use_36bit_addrs;
- struct rpi_firmware *fw;
- };
-
+++ /dev/null
-From d1712d177a85f00eaf359d9b479841bb21239adb Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Tue, 30 Apr 2019 19:15:30 +0100
-Subject: [PATCH 546/703] bcm2835-pcm.c: Support multichannel audio
-
----
- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 17 +++++++++--------
- 1 file changed, 9 insertions(+), 8 deletions(-)
-
---- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
-@@ -14,9 +14,9 @@ static const struct snd_pcm_hardware snd
- SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
- .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
-- .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
-+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000,
- .rate_min = 8000,
-- .rate_max = 48000,
-+ .rate_max = 192000,
- .channels_min = 1,
- .channels_max = 2,
- .buffer_bytes_max = 128 * 1024,
-@@ -31,15 +31,16 @@ static const struct snd_pcm_hardware snd
- SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
-- .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
-- SNDRV_PCM_RATE_48000,
-+ .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-+ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-+ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
- .rate_min = 44100,
-- .rate_max = 48000,
-+ .rate_max = 192000,
- .channels_min = 2,
-- .channels_max = 2,
-- .buffer_bytes_max = 128 * 1024,
-+ .channels_max = 8,
-+ .buffer_bytes_max = 512 * 1024,
- .period_bytes_min = 1 * 1024,
-- .period_bytes_max = 128 * 1024,
-+ .period_bytes_max = 512 * 1024,
- .periods_min = 1,
- .periods_max = 128,
- };
--- /dev/null
+From 21e3d91c32f71881ca5d8fba428a2ebe55398760 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 14 May 2019 17:00:41 +0100
+Subject: [PATCH 546/725] phy: broadcom: split out the BCM54213PE from the
+ BCM54210E IDs
+
+The last nibble is a revision ID, and the 54213pe is a later rev
+than the 54210e. Running the 54210e setup code on a 54213pe results
+in a broken RGMII interface.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/net/phy/broadcom.c | 17 ++++++++++++++---
+ include/linux/brcmphy.h | 1 +
+ 2 files changed, 15 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -222,7 +222,8 @@ static void bcm54xx_adjust_rxrefclk(stru
+ /* Abort if we are using an untested phy. */
+ if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 &&
+ BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 &&
+- BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
++ BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M &&
++ BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54213PE)
+ return;
+
+ val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
+@@ -604,7 +605,7 @@ static struct phy_driver broadcom_driver
+ .config_intr = bcm_phy_config_intr,
+ }, {
+ .phy_id = PHY_ID_BCM54210E,
+- .phy_id_mask = 0xfffffff0,
++ .phy_id_mask = 0xffffffff,
+ .name = "Broadcom BCM54210E",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+@@ -612,6 +613,15 @@ static struct phy_driver broadcom_driver
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
+ }, {
++ .phy_id = PHY_ID_BCM54213PE,
++ .phy_id_mask = 0xffffffff,
++ .name = "Broadcom BCM54213PE",
++ .features = PHY_GBIT_FEATURES,
++ .flags = PHY_HAS_INTERRUPT,
++ .config_init = bcm54xx_config_init,
++ .ack_interrupt = bcm_phy_ack_intr,
++ .config_intr = bcm_phy_config_intr,
++}, {
+ .phy_id = PHY_ID_BCM5461,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Broadcom BCM5461",
+@@ -748,7 +758,8 @@ module_phy_driver(broadcom_drivers);
+ static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
+ { PHY_ID_BCM5411, 0xfffffff0 },
+ { PHY_ID_BCM5421, 0xfffffff0 },
+- { PHY_ID_BCM54210E, 0xfffffff0 },
++ { PHY_ID_BCM54210E, 0xffffffff },
++ { PHY_ID_BCM54213PE, 0xffffffff },
+ { PHY_ID_BCM5461, 0xfffffff0 },
+ { PHY_ID_BCM54612E, 0xfffffff0 },
+ { PHY_ID_BCM54616S, 0xfffffff0 },
+--- a/include/linux/brcmphy.h
++++ b/include/linux/brcmphy.h
+@@ -20,6 +20,7 @@
+ #define PHY_ID_BCM5411 0x00206070
+ #define PHY_ID_BCM5421 0x002060e0
+ #define PHY_ID_BCM54210E 0x600d84a0
++#define PHY_ID_BCM54213PE 0x600d84a2
+ #define PHY_ID_BCM5464 0x002060b0
+ #define PHY_ID_BCM5461 0x002060c0
+ #define PHY_ID_BCM54612E 0x03625e60
+++ /dev/null
-From 9c341c10cd2ad2a61f084dc222fd380ed1687f50 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Wed, 12 Sep 2018 14:44:53 +0100
-Subject: [PATCH 547/703] bcmgenet: constrain max DMA burst length
-
----
- drivers/net/ethernet/broadcom/genet/bcmgenet.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
-+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
-@@ -31,7 +31,7 @@
- #define ENET_PAD 8
- #define ENET_MAX_MTU_SIZE (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + \
- ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD)
--#define DMA_MAX_BURST_LENGTH 0x10
-+#define DMA_MAX_BURST_LENGTH 0x08
-
- /* misc. configuration */
- #define CLEAR_ALL_HFB 0xFF
--- /dev/null
+From 6873c605ba15e36bbc5efffd3b86caab09c9ce5a Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Fri, 17 May 2019 13:31:21 +0100
+Subject: [PATCH 547/725] phy: bcm54213pe: configure the LED outputs to be more
+ user-friendly
+
+The default state was both LEDs indicating link speed.
+
+Change the default configuration to
+- Amber: 1000/100 link speed indication
+- Green: link present + activity indication
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/net/phy/broadcom.c | 17 +++++++++++++++++
+ include/linux/brcmphy.h | 4 ++++
+ 2 files changed, 21 insertions(+)
+
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -52,6 +52,21 @@ static int bcm54210e_config_init(struct
+ return 0;
+ }
+
++static void bcm54213pe_config_init(struct phy_device *phydev)
++{
++ u16 val;
++
++ /* Enable ACT+LINK indication on ACTIVITY trigger */
++ val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_LEDCTL);
++ val |= BCM54XX_SHD_LEDCTL_ACTLINK_EN;
++ bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDCTL, val);
++
++ /* Set ACTIVITY on LED "1" output, LINKSPD[1] on LED "3" output */
++ val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
++ BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD1);
++ bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val);
++}
++
+ static int bcm54612e_config_init(struct phy_device *phydev)
+ {
+ int reg;
+@@ -310,6 +325,8 @@ static int bcm54xx_config_init(struct ph
+ err = bcm54210e_config_init(phydev);
+ if (err)
+ return err;
++ } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54213PE) {
++ bcm54213pe_config_init(phydev);
+ } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54612E) {
+ err = bcm54612e_config_init(phydev);
+ if (err)
+--- a/include/linux/brcmphy.h
++++ b/include/linux/brcmphy.h
+@@ -168,6 +168,10 @@
+ #define BCM54XX_SHD_SCR3_DLLAPD_DIS 0x0002
+ #define BCM54XX_SHD_SCR3_TRDDAPD 0x0004
+
++/* 01001: Additional LED trigger options */
++#define BCM54XX_SHD_LEDCTL 0x09
++#define BCM54XX_SHD_LEDCTL_ACTLINK_EN 0x0010
++
+ /* 01010: Auto Power-Down */
+ #define BCM54XX_SHD_APD 0x0a
+ #define BCM_APD_CLR_MASK 0xFE9F /* clear bits 5, 6 & 8 */
+++ /dev/null
-From 8d30a996253c537f4978910aabf1e098bac8fa1a Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 27 Mar 2019 13:45:46 +0000
-Subject: [PATCH 548/703] bcmgenet: Better coalescing parameter defaults
-
-Set defaults for TX and RX packet coalescing to be equivalent to:
-
- # ethtool -C eth0 tx-frames 10
- # ethtool -C eth0 rx-usecs 50
-
-This may be something we want to set via DT parameters in the
-future.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
---- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
-+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
-@@ -2147,7 +2147,7 @@ static void bcmgenet_init_tx_ring(struct
-
- bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_PROD_INDEX);
- bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_CONS_INDEX);
-- bcmgenet_tdma_ring_writel(priv, index, 1, DMA_MBUF_DONE_THRESH);
-+ bcmgenet_tdma_ring_writel(priv, index, 10, DMA_MBUF_DONE_THRESH);
- /* Disable rate control for now */
- bcmgenet_tdma_ring_writel(priv, index, flow_period_val,
- TDMA_FLOW_PERIOD);
-@@ -3571,9 +3571,12 @@ static int bcmgenet_probe(struct platfor
- netif_set_real_num_rx_queues(priv->dev, priv->hw_params->rx_queues + 1);
-
- /* Set default coalescing parameters */
-- for (i = 0; i < priv->hw_params->rx_queues; i++)
-+ for (i = 0; i < priv->hw_params->rx_queues; i++) {
- priv->rx_rings[i].rx_max_coalesced_frames = 1;
-+ priv->rx_rings[i].rx_coalesce_usecs = 50;
-+ }
- priv->rx_rings[DESC_INDEX].rx_max_coalesced_frames = 1;
-+ priv->rx_rings[DESC_INDEX].rx_coalesce_usecs = 50;
-
- /* libphy will determine the link state */
- netif_carrier_off(dev);
--- /dev/null
+From 1fa7016f17e440f19a7895b795384f105772dbfe Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 21 May 2019 13:36:52 +0100
+Subject: [PATCH 548/725] dwc_otg: Choose appropriate IRQ handover strategy
+
+2711 has no MPHI peripheral, but the ARM Control block can fake
+interrupts. Use the size of the DTB "mphi" reg block to determine
+which is required.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_driver.c | 9 +++--
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 21 ++++++----
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 2 +
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 12 ++++--
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 41 +++++++++++++-------
+ drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 3 ++
+ 6 files changed, 60 insertions(+), 28 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
+@@ -806,14 +806,15 @@ static int dwc_otg_driver_probe(
+ if (!request_mem_region(_dev->resource[1].start,
+ _dev->resource[1].end - _dev->resource[1].start + 1,
+ "dwc_otg")) {
+- dev_dbg(&_dev->dev, "error reserving mapped memory\n");
+- retval = -EFAULT;
+- goto fail;
+- }
++ dev_dbg(&_dev->dev, "error reserving mapped memory\n");
++ retval = -EFAULT;
++ goto fail;
++ }
+
+ dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start,
+ _dev->resource[1].end -
+ _dev->resource[1].start + 1);
++ dwc_otg_device->os_dep.use_swirq = (_dev->resource[1].end - _dev->resource[1].start) == 0x200;
+ }
+
+ #else
+--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
+@@ -1347,8 +1347,12 @@ void notrace dwc_otg_fiq_fsm(struct fiq_
+ /* We got an interrupt, didn't handle it. */
+ if (kick_irq) {
+ state->mphi_int_count++;
+- FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
+- FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
++ if (state->mphi_regs.swirq_set) {
++ FIQ_WRITE(state->mphi_regs.swirq_set, 1);
++ } else {
++ FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
++ FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
++ }
+
+ }
+ state->fiq_done++;
+@@ -1406,11 +1410,14 @@ void notrace dwc_otg_fiq_nop(struct fiq_
+ state->mphi_int_count++;
+ gintmsk.d32 &= state->gintmsk_saved.d32;
+ FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32);
+- /* Force a clear before another dummy send */
+- FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
+- FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
+- FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
+-
++ if (state->mphi_regs.swirq_set) {
++ FIQ_WRITE(state->mphi_regs.swirq_set, 1);
++ } else {
++ /* Force a clear before another dummy send */
++ FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
++ FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
++ FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
++ }
+ }
+ state->fiq_done++;
+ mb();
+--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
+@@ -118,6 +118,8 @@ typedef struct {
+ volatile void* outdda;
+ volatile void* outddb;
+ volatile void* intstat;
++ volatile void* swirq_set;
++ volatile void* swirq_clr;
+ } mphi_regs_t;
+
+ enum fiq_debug_level {
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
+@@ -220,16 +220,20 @@ exit_handler_routine:
+
+ /* The FIQ could have sneaked another interrupt in. If so, don't clear MPHI */
+ if ((gintmsk_new.d32 == ~0) && (haintmsk_new.d32 == 0x0000FFFF)) {
++ if (dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr) {
++ DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr, 1);
++ } else {
+ DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.intstat, (1<<16));
+- if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) {
+- fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR");
++ }
++ if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) {
++ fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR");
+ DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, ((1<<31) + (1<<16)));
+ while (!(DWC_READ_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & (1 << 17)))
+ ;
+ DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, (1<<31));
+ dwc_otg_hcd->fiq_state->mphi_int_count = 0;
+- }
+- int_done++;
++ }
++ int_done++;
+ }
+ haintmsk.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
+ /* Re-enable interrupts that the FIQ masked (first time round) */
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+@@ -474,22 +474,37 @@ static void hcd_init_fiq(void *cookie)
+ set_fiq_regs(®s);
+ #endif
+
+- //Set the mphi periph to the required registers
+- dwc_otg_hcd->fiq_state->mphi_regs.base = otg_dev->os_dep.mphi_base;
+- dwc_otg_hcd->fiq_state->mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c;
+- dwc_otg_hcd->fiq_state->mphi_regs.outdda = otg_dev->os_dep.mphi_base + 0x28;
+- dwc_otg_hcd->fiq_state->mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c;
+- dwc_otg_hcd->fiq_state->mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
+ dwc_otg_hcd->fiq_state->dwc_regs_base = otg_dev->os_dep.base;
+- DWC_WARN("MPHI regs_base at %px", dwc_otg_hcd->fiq_state->mphi_regs.base);
+- //Enable mphi peripheral
+- writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
++ //Set the mphi periph to the required registers
++ dwc_otg_hcd->fiq_state->mphi_regs.base = otg_dev->os_dep.mphi_base;
++ if (otg_dev->os_dep.use_swirq) {
++ dwc_otg_hcd->fiq_state->mphi_regs.swirq_set =
++ otg_dev->os_dep.mphi_base + 0x1f0;
++ dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr =
++ otg_dev->os_dep.mphi_base + 0x1f4;
++ DWC_WARN("Fake MPHI regs_base at 0x%08x",
++ (int)dwc_otg_hcd->fiq_state->mphi_regs.base);
++ } else {
++ dwc_otg_hcd->fiq_state->mphi_regs.ctrl =
++ otg_dev->os_dep.mphi_base + 0x4c;
++ dwc_otg_hcd->fiq_state->mphi_regs.outdda
++ = otg_dev->os_dep.mphi_base + 0x28;
++ dwc_otg_hcd->fiq_state->mphi_regs.outddb
++ = otg_dev->os_dep.mphi_base + 0x2c;
++ dwc_otg_hcd->fiq_state->mphi_regs.intstat
++ = otg_dev->os_dep.mphi_base + 0x50;
++ DWC_WARN("MPHI regs_base at %px",
++ dwc_otg_hcd->fiq_state->mphi_regs.base);
++
++ //Enable mphi peripheral
++ writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
+ #ifdef DEBUG
+- if (readl(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & 0x80000000)
+- DWC_WARN("MPHI periph has been enabled");
+- else
+- DWC_WARN("MPHI periph has NOT been enabled");
++ if (readl(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & 0x80000000)
++ DWC_WARN("MPHI periph has been enabled");
++ else
++ DWC_WARN("MPHI periph has NOT been enabled");
+ #endif
++ }
+ // Enable FIQ interrupt from USB peripheral
+ #ifdef CONFIG_ARM64
+ irq = otg_dev->os_dep.fiq_num;
+--- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
++++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
+@@ -102,6 +102,9 @@ typedef struct os_dependent {
+ /** Base address for MPHI peripheral */
+ void *mphi_base;
+
++ /** mphi_base actually points to the SWIRQ block */
++ bool use_swirq;
++
+ /** IRQ number (<0 if not valid) */
+ int irq_num;
+
+++ /dev/null
-From 03bd32474bf378c1537775970b35c7081779aec4 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Tue, 14 May 2019 17:17:59 +0100
-Subject: [PATCH 549/703] net: genet: enable link energy detect powerdown for
- external PHYs
-
-There are several warts surrounding bcmgenet_mii_probe() as this
-function is called from ndo_open, but it's calling registration-type
-functions. The probe should be called at probe time and refactored
-such that the PHY device data can be extracted to limit the scope
-of this flag to Broadcom PHYs.
-
-For now, pass this flag in as it puts our attached PHY into a low-power
-state when disconnected.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/net/ethernet/broadcom/genet/bcmmii.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
---- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
-+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
-@@ -280,7 +280,10 @@ int bcmgenet_mii_probe(struct net_device
- int ret;
-
- /* Communicate the integrated PHY revision */
-- phy_flags = priv->gphy_rev;
-+ if (priv->internal_phy)
-+ phy_flags = priv->gphy_rev;
-+ else
-+ phy_flags = PHY_BRCM_AUTO_PWRDWN_ENABLE;
-
- /* Initialize link state variables that bcmgenet_mii_setup() uses */
- priv->old_link = -1;
--- /dev/null
+From 4f8e73f79d01049ab47e4984f8df63cd92a4da5c Mon Sep 17 00:00:00 2001
+From: Tim Gover <tim.gover@raspberrypi.org>
+Date: Fri, 22 Mar 2019 09:47:14 +0000
+Subject: [PATCH 549/725] usb: xhci: Disable the XHCI 5 second timeout
+
+If the VL805 EEPROM has not been programmed then boot will hang for five
+seconds. The timeout seems to be arbitrary and is an unecessary
+delay on the first boot. Remove the timeout.
+
+This is common code and probably can't be upstreamed unless the timeout
+can be configurable somehow or perhaps the XHCI driver can be skipped
+on the first boot.
+---
+ drivers/usb/host/xhci.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -196,8 +196,9 @@ int xhci_reset(struct xhci_hcd *xhci)
+ if (xhci->quirks & XHCI_INTEL_HOST)
+ udelay(1000);
+
++ // Hack: reduce handshake timeout from 10s 0.5s due to unprogrammed vl805
+ ret = xhci_handshake(&xhci->op_regs->command,
+- CMD_RESET, 0, 10 * 1000 * 1000);
++ CMD_RESET, 0, 500 * 1000);
+ if (ret)
+ return ret;
+
+++ /dev/null
-From 845295c21d9123f24a33bcb683f02fa7f3c7648e Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Tue, 14 May 2019 17:00:41 +0100
-Subject: [PATCH 550/703] phy: broadcom: split out the BCM54213PE from the
- BCM54210E IDs
-
-The last nibble is a revision ID, and the 54213pe is a later rev
-than the 54210e. Running the 54210e setup code on a 54213pe results
-in a broken RGMII interface.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/net/phy/broadcom.c | 17 ++++++++++++++---
- include/linux/brcmphy.h | 1 +
- 2 files changed, 15 insertions(+), 3 deletions(-)
-
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -222,7 +222,8 @@ static void bcm54xx_adjust_rxrefclk(stru
- /* Abort if we are using an untested phy. */
- if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 &&
- BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 &&
-- BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
-+ BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M &&
-+ BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54213PE)
- return;
-
- val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
-@@ -604,7 +605,7 @@ static struct phy_driver broadcom_driver
- .config_intr = bcm_phy_config_intr,
- }, {
- .phy_id = PHY_ID_BCM54210E,
-- .phy_id_mask = 0xfffffff0,
-+ .phy_id_mask = 0xffffffff,
- .name = "Broadcom BCM54210E",
- .features = PHY_GBIT_FEATURES,
- .flags = PHY_HAS_INTERRUPT,
-@@ -612,6 +613,15 @@ static struct phy_driver broadcom_driver
- .ack_interrupt = bcm_phy_ack_intr,
- .config_intr = bcm_phy_config_intr,
- }, {
-+ .phy_id = PHY_ID_BCM54213PE,
-+ .phy_id_mask = 0xffffffff,
-+ .name = "Broadcom BCM54213PE",
-+ .features = PHY_GBIT_FEATURES,
-+ .flags = PHY_HAS_INTERRUPT,
-+ .config_init = bcm54xx_config_init,
-+ .ack_interrupt = bcm_phy_ack_intr,
-+ .config_intr = bcm_phy_config_intr,
-+}, {
- .phy_id = PHY_ID_BCM5461,
- .phy_id_mask = 0xfffffff0,
- .name = "Broadcom BCM5461",
-@@ -748,7 +758,8 @@ module_phy_driver(broadcom_drivers);
- static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
- { PHY_ID_BCM5411, 0xfffffff0 },
- { PHY_ID_BCM5421, 0xfffffff0 },
-- { PHY_ID_BCM54210E, 0xfffffff0 },
-+ { PHY_ID_BCM54210E, 0xffffffff },
-+ { PHY_ID_BCM54213PE, 0xffffffff },
- { PHY_ID_BCM5461, 0xfffffff0 },
- { PHY_ID_BCM54612E, 0xfffffff0 },
- { PHY_ID_BCM54616S, 0xfffffff0 },
---- a/include/linux/brcmphy.h
-+++ b/include/linux/brcmphy.h
-@@ -20,6 +20,7 @@
- #define PHY_ID_BCM5411 0x00206070
- #define PHY_ID_BCM5421 0x002060e0
- #define PHY_ID_BCM54210E 0x600d84a0
-+#define PHY_ID_BCM54213PE 0x600d84a2
- #define PHY_ID_BCM5464 0x002060b0
- #define PHY_ID_BCM5461 0x002060c0
- #define PHY_ID_BCM54612E 0x03625e60
--- /dev/null
+From 66cba59420caaf4fd1123e7aa4ef87de34cca440 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 23 May 2019 15:08:30 +0100
+Subject: [PATCH 550/725] usb: xhci: Show that the VIA VL805 supports LPM
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/usb/host/xhci-pci.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -222,6 +222,10 @@ static void xhci_pci_quirks(struct devic
+ pdev->device == 0x3432)
+ xhci->quirks |= XHCI_BROKEN_STREAMS;
+
++ if (pdev->vendor == PCI_VENDOR_ID_VIA &&
++ pdev->device == 0x3483)
++ xhci->quirks |= XHCI_LPM_SUPPORT;
++
+ if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+ pdev->device == 0x1042)
+ xhci->quirks |= XHCI_BROKEN_STREAMS;
+++ /dev/null
-From 5353102f2d7e2f61cca4014aacfa3ac9a71aaeea Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Fri, 17 May 2019 13:31:21 +0100
-Subject: [PATCH 551/703] phy: bcm54213pe: configure the LED outputs to be more
- user-friendly
-
-The default state was both LEDs indicating link speed.
-
-Change the default configuration to
-- Amber: 1000/100 link speed indication
-- Green: link present + activity indication
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/net/phy/broadcom.c | 17 +++++++++++++++++
- include/linux/brcmphy.h | 4 ++++
- 2 files changed, 21 insertions(+)
-
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -52,6 +52,21 @@ static int bcm54210e_config_init(struct
- return 0;
- }
-
-+static void bcm54213pe_config_init(struct phy_device *phydev)
-+{
-+ u16 val;
-+
-+ /* Enable ACT+LINK indication on ACTIVITY trigger */
-+ val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_LEDCTL);
-+ val |= BCM54XX_SHD_LEDCTL_ACTLINK_EN;
-+ bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDCTL, val);
-+
-+ /* Set ACTIVITY on LED "1" output, LINKSPD[1] on LED "3" output */
-+ val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
-+ BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD1);
-+ bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val);
-+}
-+
- static int bcm54612e_config_init(struct phy_device *phydev)
- {
- int reg;
-@@ -310,6 +325,8 @@ static int bcm54xx_config_init(struct ph
- err = bcm54210e_config_init(phydev);
- if (err)
- return err;
-+ } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54213PE) {
-+ bcm54213pe_config_init(phydev);
- } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54612E) {
- err = bcm54612e_config_init(phydev);
- if (err)
---- a/include/linux/brcmphy.h
-+++ b/include/linux/brcmphy.h
-@@ -168,6 +168,10 @@
- #define BCM54XX_SHD_SCR3_DLLAPD_DIS 0x0002
- #define BCM54XX_SHD_SCR3_TRDDAPD 0x0004
-
-+/* 01001: Additional LED trigger options */
-+#define BCM54XX_SHD_LEDCTL 0x09
-+#define BCM54XX_SHD_LEDCTL_ACTLINK_EN 0x0010
-+
- /* 01010: Auto Power-Down */
- #define BCM54XX_SHD_APD 0x0a
- #define BCM_APD_CLR_MASK 0xFE9F /* clear bits 5, 6 & 8 */
--- /dev/null
+From ebd33389465183268879eb8c3eefe9e7e5363cf3 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Thu, 30 May 2019 10:38:40 +0100
+Subject: [PATCH 551/725] usb: xhci: hack xhci_urb_enqueue to support
+ hid.mousepoll behaviour
+
+xHCI creates endpoint contexts directly from the device's endpoint
+data, so submitting URBs with urb->interval different from the hardware
+interval has no effect.
+
+Add an explicit reconfiguration of the endpoint context when requested,
+which will happen only when the interval is different from the cached
+value. In practice, the reconfiguration only happens on the first URB
+submitted for the endpoint.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/host/xhci.c | 86 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 86 insertions(+)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -1416,6 +1416,87 @@ command_cleanup:
+ }
+
+ /*
++ * RPI: Fixup endpoint intervals when requested
++ * - Check interval versus the (cached) endpoint context
++ * - set the endpoint interval to the new value
++ * - force an endpoint configure command
++ */
++static void xhci_fixup_interval(struct xhci_hcd *xhci, struct urb *urb,
++ unsigned int slot_id, unsigned int ep_index)
++{
++ struct xhci_ep_ctx *ep_ctx_out, *ep_ctx_in;
++ struct xhci_command *command;
++ struct xhci_input_control_ctx *ctrl_ctx;
++ struct xhci_virt_device *vdev;
++ int xhci_interval, ep_interval;
++ int ret;
++ unsigned long flags;
++ u32 ep_info_tmp;
++
++ spin_lock_irqsave(&xhci->lock, flags);
++
++ vdev = xhci->devs[slot_id];
++ /* Get context-derived endpoint interval */
++ ep_ctx_out = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
++ ep_ctx_in = xhci_get_ep_ctx(xhci, vdev->in_ctx, ep_index);
++ xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx_out->ep_info));
++ ep_interval = urb->interval * 8;
++
++ if (ep_interval == xhci_interval) {
++ spin_unlock_irqrestore(&xhci->lock, flags);
++ return;
++ }
++
++ xhci_dbg(xhci, "Fixup interval ep_interval=%d xhci_interval=%d\n",
++ ep_interval, xhci_interval);
++ command = xhci_alloc_command_with_ctx(xhci, true, GFP_ATOMIC);
++ if (!command) {
++ /* Failure here is benign, poll at the original rate */
++ spin_unlock_irqrestore(&xhci->lock, flags);
++ return;
++ }
++
++ /* xHCI uses exponents for intervals... */
++ xhci_interval = fls(ep_interval) - 1;
++ xhci_interval = clamp_val(xhci_interval, 3, 10);
++ ep_info_tmp = le32_to_cpu(ep_ctx_out->ep_info);
++ ep_info_tmp &= ~EP_INTERVAL(255);
++ ep_info_tmp |= EP_INTERVAL(xhci_interval);
++
++ /* Keep the endpoint context up-to-date while issuing the command. */
++ xhci_endpoint_copy(xhci, vdev->in_ctx,
++ vdev->out_ctx, ep_index);
++ ep_ctx_in->ep_info = cpu_to_le32(ep_info_tmp);
++
++ /*
++ * We need to drop the lock, so take an explicit copy
++ * of the ep context.
++ */
++ xhci_endpoint_copy(xhci, command->in_ctx, vdev->in_ctx, ep_index);
++
++ ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx);
++ if (!ctrl_ctx) {
++ xhci_warn(xhci,
++ "%s: Could not get input context, bad type.\n",
++ __func__);
++ spin_unlock_irqrestore(&xhci->lock, flags);
++ xhci_free_command(xhci, command);
++ return;
++ }
++ ctrl_ctx->add_flags = xhci_get_endpoint_flag_from_index(ep_index);
++ ctrl_ctx->drop_flags = 0;
++
++ spin_unlock_irqrestore(&xhci->lock, flags);
++
++ ret = xhci_configure_endpoint(xhci, urb->dev, command,
++ false, false);
++ if (ret)
++ xhci_warn(xhci, "%s: Configure endpoint failed: %d\n",
++ __func__, ret);
++ xhci_free_command(xhci, command);
++}
++
++/*
+ * non-error returns are a promise to giveback() the urb later
+ * we drop ownership so next owner (or urb unlink) can get it
+ */
+@@ -1483,6 +1564,11 @@ static int xhci_urb_enqueue(struct usb_h
+ }
+ }
+
++ if (usb_endpoint_xfer_int(&urb->ep->desc) &&
++ (urb->dev->speed == USB_SPEED_FULL ||
++ urb->dev->speed == USB_SPEED_LOW))
++ xhci_fixup_interval(xhci, urb, slot_id, ep_index);
++
+ spin_lock_irqsave(&xhci->lock, flags);
+
+ if (xhci->xhc_state & XHCI_STATE_DYING) {
+++ /dev/null
-From 9a7fd87f8f2a28cee05a847266a5a168a3d8c0dd Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 21 May 2019 13:36:52 +0100
-Subject: [PATCH 552/703] dwc_otg: Choose appropriate IRQ handover strategy
-
-2711 has no MPHI peripheral, but the ARM Control block can fake
-interrupts. Use the size of the DTB "mphi" reg block to determine
-which is required.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/usb/host/dwc_otg/dwc_otg_driver.c | 9 +++--
- drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 21 ++++++----
- drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 2 +
- drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 12 ++++--
- drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 41 +++++++++++++-------
- drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 3 ++
- 6 files changed, 60 insertions(+), 28 deletions(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
-@@ -806,14 +806,15 @@ static int dwc_otg_driver_probe(
- if (!request_mem_region(_dev->resource[1].start,
- _dev->resource[1].end - _dev->resource[1].start + 1,
- "dwc_otg")) {
-- dev_dbg(&_dev->dev, "error reserving mapped memory\n");
-- retval = -EFAULT;
-- goto fail;
-- }
-+ dev_dbg(&_dev->dev, "error reserving mapped memory\n");
-+ retval = -EFAULT;
-+ goto fail;
-+ }
-
- dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start,
- _dev->resource[1].end -
- _dev->resource[1].start + 1);
-+ dwc_otg_device->os_dep.use_swirq = (_dev->resource[1].end - _dev->resource[1].start) == 0x200;
- }
-
- #else
---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
-@@ -1347,8 +1347,12 @@ void notrace dwc_otg_fiq_fsm(struct fiq_
- /* We got an interrupt, didn't handle it. */
- if (kick_irq) {
- state->mphi_int_count++;
-- FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
-- FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
-+ if (state->mphi_regs.swirq_set) {
-+ FIQ_WRITE(state->mphi_regs.swirq_set, 1);
-+ } else {
-+ FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
-+ FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
-+ }
-
- }
- state->fiq_done++;
-@@ -1406,11 +1410,14 @@ void notrace dwc_otg_fiq_nop(struct fiq_
- state->mphi_int_count++;
- gintmsk.d32 &= state->gintmsk_saved.d32;
- FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32);
-- /* Force a clear before another dummy send */
-- FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
-- FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
-- FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
--
-+ if (state->mphi_regs.swirq_set) {
-+ FIQ_WRITE(state->mphi_regs.swirq_set, 1);
-+ } else {
-+ /* Force a clear before another dummy send */
-+ FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
-+ FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
-+ FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
-+ }
- }
- state->fiq_done++;
- mb();
---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
-@@ -118,6 +118,8 @@ typedef struct {
- volatile void* outdda;
- volatile void* outddb;
- volatile void* intstat;
-+ volatile void* swirq_set;
-+ volatile void* swirq_clr;
- } mphi_regs_t;
-
- enum fiq_debug_level {
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
-@@ -220,16 +220,20 @@ exit_handler_routine:
-
- /* The FIQ could have sneaked another interrupt in. If so, don't clear MPHI */
- if ((gintmsk_new.d32 == ~0) && (haintmsk_new.d32 == 0x0000FFFF)) {
-+ if (dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr) {
-+ DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr, 1);
-+ } else {
- DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.intstat, (1<<16));
-- if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) {
-- fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR");
-+ }
-+ if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) {
-+ fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR");
- DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, ((1<<31) + (1<<16)));
- while (!(DWC_READ_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & (1 << 17)))
- ;
- DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, (1<<31));
- dwc_otg_hcd->fiq_state->mphi_int_count = 0;
-- }
-- int_done++;
-+ }
-+ int_done++;
- }
- haintmsk.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
- /* Re-enable interrupts that the FIQ masked (first time round) */
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-@@ -474,22 +474,37 @@ static void hcd_init_fiq(void *cookie)
- set_fiq_regs(®s);
- #endif
-
-- //Set the mphi periph to the required registers
-- dwc_otg_hcd->fiq_state->mphi_regs.base = otg_dev->os_dep.mphi_base;
-- dwc_otg_hcd->fiq_state->mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c;
-- dwc_otg_hcd->fiq_state->mphi_regs.outdda = otg_dev->os_dep.mphi_base + 0x28;
-- dwc_otg_hcd->fiq_state->mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c;
-- dwc_otg_hcd->fiq_state->mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
- dwc_otg_hcd->fiq_state->dwc_regs_base = otg_dev->os_dep.base;
-- DWC_WARN("MPHI regs_base at %px", dwc_otg_hcd->fiq_state->mphi_regs.base);
-- //Enable mphi peripheral
-- writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
-+ //Set the mphi periph to the required registers
-+ dwc_otg_hcd->fiq_state->mphi_regs.base = otg_dev->os_dep.mphi_base;
-+ if (otg_dev->os_dep.use_swirq) {
-+ dwc_otg_hcd->fiq_state->mphi_regs.swirq_set =
-+ otg_dev->os_dep.mphi_base + 0x1f0;
-+ dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr =
-+ otg_dev->os_dep.mphi_base + 0x1f4;
-+ DWC_WARN("Fake MPHI regs_base at 0x%08x",
-+ (int)dwc_otg_hcd->fiq_state->mphi_regs.base);
-+ } else {
-+ dwc_otg_hcd->fiq_state->mphi_regs.ctrl =
-+ otg_dev->os_dep.mphi_base + 0x4c;
-+ dwc_otg_hcd->fiq_state->mphi_regs.outdda
-+ = otg_dev->os_dep.mphi_base + 0x28;
-+ dwc_otg_hcd->fiq_state->mphi_regs.outddb
-+ = otg_dev->os_dep.mphi_base + 0x2c;
-+ dwc_otg_hcd->fiq_state->mphi_regs.intstat
-+ = otg_dev->os_dep.mphi_base + 0x50;
-+ DWC_WARN("MPHI regs_base at %px",
-+ dwc_otg_hcd->fiq_state->mphi_regs.base);
-+
-+ //Enable mphi peripheral
-+ writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
- #ifdef DEBUG
-- if (readl(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & 0x80000000)
-- DWC_WARN("MPHI periph has been enabled");
-- else
-- DWC_WARN("MPHI periph has NOT been enabled");
-+ if (readl(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & 0x80000000)
-+ DWC_WARN("MPHI periph has been enabled");
-+ else
-+ DWC_WARN("MPHI periph has NOT been enabled");
- #endif
-+ }
- // Enable FIQ interrupt from USB peripheral
- #ifdef CONFIG_ARM64
- irq = otg_dev->os_dep.fiq_num;
---- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
-@@ -102,6 +102,9 @@ typedef struct os_dependent {
- /** Base address for MPHI peripheral */
- void *mphi_base;
-
-+ /** mphi_base actually points to the SWIRQ block */
-+ bool use_swirq;
-+
- /** IRQ number (<0 if not valid) */
- int irq_num;
-
--- /dev/null
+From 40c0d670970e7896a0be03ab0f884bdcd718660d Mon Sep 17 00:00:00 2001
+From: Tim Gover <tim.gover@raspberrypi.org>
+Date: Wed, 9 Jan 2019 14:43:36 +0000
+Subject: [PATCH 552/725] pinctrl-bcm2835: Add support for BCM2838
+
+GPIO configuration on BCM2838 is largely the same as BCM2835 except for
+the pull up/down configuration. The old mechanism has been replaced
+by new registers which don't require the fixed delay.
+
+Detect BCN2838 at run-time and use the new mechanism. Backwards
+compatibility for the device-tree configuration has been retained.
+---
+ drivers/pinctrl/bcm/pinctrl-bcm2835.c | 58 ++++++++++++++++++++-------
+ 1 file changed, 44 insertions(+), 14 deletions(-)
+
+--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+@@ -67,6 +67,12 @@
+ #define GPPUD 0x94 /* Pin Pull-up/down Enable */
+ #define GPPUDCLK0 0x98 /* Pin Pull-up/down Enable Clock */
+
++/* 2711 has a different mechanism for pin pull-up/down/enable */
++#define GPPUPPDN0 0xe4 /* Pin pull-up/down for pins 15:0 */
++#define GPPUPPDN1 0xe8 /* Pin pull-up/down for pins 31:16 */
++#define GPPUPPDN2 0xec /* Pin pull-up/down for pins 47:32 */
++#define GPPUPPDN3 0xf0 /* Pin pull-up/down for pins 57:48 */
++
+ #define FSEL_REG(p) (GPFSEL0 + (((p) / 10) * 4))
+ #define FSEL_SHIFT(p) (((p) % 10) * 3)
+ #define GPIO_REG_OFFSET(p) ((p) / 32)
+@@ -917,21 +923,45 @@ static void bcm2835_pull_config_set(stru
+ unsigned int pin, unsigned int arg)
+ {
+ u32 off, bit;
++ /* BCM2835, BCM2836 & BCM2837 return 'gpio' for this unused register */
++ int is_2835 = bcm2835_gpio_rd(pc, GPPUPPDN3) == 0x6770696f;
+
+- off = GPIO_REG_OFFSET(pin);
+- bit = GPIO_REG_SHIFT(pin);
+-
+- bcm2835_gpio_wr(pc, GPPUD, arg & 3);
+- /*
+- * BCM2835 datasheet say to wait 150 cycles, but not of what.
+- * But the VideoCore firmware delay for this operation
+- * based nearly on the same amount of VPU cycles and this clock
+- * runs at 250 MHz.
+- */
+- udelay(1);
+- bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
+- udelay(1);
+- bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
++ if (is_2835) {
++ off = GPIO_REG_OFFSET(pin);
++ bit = GPIO_REG_SHIFT(pin);
++ /*
++ * BCM2835 datasheet say to wait 150 cycles, but not of what.
++ * But the VideoCore firmware delay for this operation
++ * based nearly on the same amount of VPU cycles and this clock
++ * runs at 250 MHz.
++ */
++ bcm2835_gpio_wr(pc, GPPUD, arg & 3);
++ udelay(1);
++ bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
++ udelay(1);
++ bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
++ } else {
++ u32 reg;
++ int lsb;
++
++ off = (pin >> 4);
++ if (off > 3)
++ return;
++ lsb = (pin & 0xf) << 1;
++
++ /* The up/down semantics are reversed compared to BCM2835.
++ * Instead of updating all the device tree files, translate the
++ * values here.
++ */
++ if (arg == 2)
++ arg = 1;
++ else if (arg == 1)
++ arg = 2;
++ reg = bcm2835_gpio_rd(pc, GPPUPPDN0 + (off *4));
++ reg &= ~(0x3 << lsb);
++ reg |= (arg & 3) << lsb;
++ bcm2835_gpio_wr(pc, GPPUPPDN0 + (off * 4), reg);
++ }
+ }
+
+ static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
--- /dev/null
+From bca62369ca063a66ab3bfb3d129d76da88a3b99b Mon Sep 17 00:00:00 2001
+From: Martin Sperl <kernel@martin.sperl.org>
+Date: Mon, 13 May 2019 11:05:27 +0000
+Subject: [PATCH 553/725] spi: bcm2835: enable shared interrupt support
+
+Add shared interrupt support for this driver.
+
+Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
+---
+ drivers/spi/spi-bcm2835.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/spi/spi-bcm2835.c
++++ b/drivers/spi/spi-bcm2835.c
+@@ -150,6 +150,10 @@ static irqreturn_t bcm2835_spi_interrupt
+ struct spi_master *master = dev_id;
+ struct bcm2835_spi *bs = spi_master_get_devdata(master);
+
++ /* check if we got interrupt enabled */
++ if (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_INTR))
++ return IRQ_NONE;
++
+ /* Read as many bytes as possible from FIFO */
+ bcm2835_rd_fifo(bs);
+ /* Write as many bytes as possible to FIFO */
+@@ -755,7 +759,8 @@ static int bcm2835_spi_probe(struct plat
+ bcm2835_wr(bs, BCM2835_SPI_CS,
+ BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
+
+- err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0,
++ err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt,
++ IRQF_SHARED,
+ dev_name(&pdev->dev), master);
+ if (err) {
+ dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
+++ /dev/null
-From 2957990a8291f860ca5bbbc58d2b28aaf6acd28e Mon Sep 17 00:00:00 2001
-From: Tim Gover <tim.gover@raspberrypi.org>
-Date: Fri, 22 Mar 2019 09:47:14 +0000
-Subject: [PATCH 553/703] usb: xhci: Disable the XHCI 5 second timeout
-
-If the VL805 EEPROM has not been programmed then boot will hang for five
-seconds. The timeout seems to be arbitrary and is an unecessary
-delay on the first boot. Remove the timeout.
-
-This is common code and probably can't be upstreamed unless the timeout
-can be configurable somehow or perhaps the XHCI driver can be skipped
-on the first boot.
----
- drivers/usb/host/xhci.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/usb/host/xhci.c
-+++ b/drivers/usb/host/xhci.c
-@@ -196,8 +196,9 @@ int xhci_reset(struct xhci_hcd *xhci)
- if (xhci->quirks & XHCI_INTEL_HOST)
- udelay(1000);
-
-+ // Hack: reduce handshake timeout from 10s 0.5s due to unprogrammed vl805
- ret = xhci_handshake(&xhci->op_regs->command,
-- CMD_RESET, 0, 10 * 1000 * 1000);
-+ CMD_RESET, 0, 500 * 1000);
- if (ret)
- return ret;
-
--- /dev/null
+From b64f3dadd338591992edcadfa064920de997d058 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Thu, 9 May 2019 14:30:37 +0100
+Subject: [PATCH 554/725] drivers: char: add chardev for mmap'ing Argon control
+ registers
+
+Based on the gpiomem driver, allow mapping of the decoder register
+spaces such that userspace can access control/status registers.
+This driver is intended for use with a custom ffmpeg backend accelerator
+prior to a v4l2 driver being written.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/char/broadcom/Kconfig | 8 +
+ drivers/char/broadcom/Makefile | 1 +
+ drivers/char/broadcom/argon-mem.c | 277 ++++++++++++++++++++++++++++++
+ 3 files changed, 286 insertions(+)
+ create mode 100644 drivers/char/broadcom/argon-mem.c
+
+--- a/drivers/char/broadcom/Kconfig
++++ b/drivers/char/broadcom/Kconfig
+@@ -49,3 +49,11 @@ config BCM2835_SMI_DEV
+ This driver provides a character device interface (ioctl + read/write) to
+ Broadcom's Secondary Memory interface. The low-level functionality is provided
+ by the SMI driver itself.
++
++config ARGON_MEM
++ tristate "Character device driver for the Argon decoder hardware"
++ default n
++ help
++ This driver provides a character device interface for memory-map operations
++ so userspace tools can access the control and status registers of the Argon
++ video decoder hardware.
+--- a/drivers/char/broadcom/Makefile
++++ b/drivers/char/broadcom/Makefile
+@@ -4,3 +4,4 @@ obj-$(CONFIG_BCM_VC_SM) += vc_sm
+
+ obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o
+ obj-$(CONFIG_BCM2835_SMI_DEV) += bcm2835_smi_dev.o
++obj-$(CONFIG_ARGON_MEM) += argon-mem.o
+--- /dev/null
++++ b/drivers/char/broadcom/argon-mem.c
+@@ -0,0 +1,277 @@
++/**
++ * argon-mem.c - character device access to the Argon decoder registers
++ *
++ * Based on bcm2835-gpiomem.c. Provides IO memory access to the decoder
++ * register blocks such that ffmpeg plugins can access the hardware.
++ *
++ * Jonathan Bell <jonathan@raspberrypi.org>
++ * Copyright (c) 2019, Raspberry Pi (Trading) Ltd.
++ *
++ * 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 <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/cdev.h>
++#include <linux/pagemap.h>
++#include <linux/io.h>
++
++#define DRIVER_NAME "argon-mem"
++#define DEVICE_MINOR 0
++
++struct argon_mem_priv {
++ dev_t devid;
++ struct class *class;
++ struct cdev argon_mem_cdev;
++ unsigned long regs_phys;
++ unsigned long mem_window_len;
++ struct device *dev;
++ const char *name;
++};
++
++static int argon_mem_open(struct inode *inode, struct file *file)
++{
++ int dev = iminor(inode);
++ int ret = 0;
++ struct argon_mem_priv *priv;
++ if (dev != DEVICE_MINOR)
++ ret = -ENXIO;
++
++ priv = container_of(inode->i_cdev, struct argon_mem_priv,
++ argon_mem_cdev);
++ if (!priv)
++ return -EINVAL;
++ file->private_data = priv;
++ return ret;
++}
++
++static int argon_mem_release(struct inode *inode, struct file *file)
++{
++ int dev = iminor(inode);
++ int ret = 0;
++
++ if (dev != DEVICE_MINOR)
++ ret = -ENXIO;
++
++ return ret;
++}
++
++static const struct vm_operations_struct argon_mem_vm_ops = {
++#ifdef CONFIG_HAVE_IOREMAP_PROT
++ .access = generic_access_phys
++#endif
++};
++
++static int argon_mem_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ struct argon_mem_priv *priv;
++ unsigned long pages;
++
++ priv = file->private_data;
++ pages = priv->regs_phys >> PAGE_SHIFT;
++ /*
++ * The address decode is far larger than the actual number of registers.
++ * Just map the whole lot in.
++ */
++ vma->vm_page_prot = phys_mem_access_prot(file, pages,
++ priv->mem_window_len,
++ vma->vm_page_prot);
++ vma->vm_ops = &argon_mem_vm_ops;
++ if (remap_pfn_range(vma, vma->vm_start,
++ pages,
++ priv->mem_window_len,
++ vma->vm_page_prot)) {
++ return -EAGAIN;
++ }
++ return 0;
++}
++
++static const struct file_operations
++argon_mem_fops = {
++ .owner = THIS_MODULE,
++ .open = argon_mem_open,
++ .release = argon_mem_release,
++ .mmap = argon_mem_mmap,
++};
++
++static const struct of_device_id argon_mem_of_match[];
++static int argon_mem_probe(struct platform_device *pdev)
++{
++ int err;
++ void *ptr_err;
++ const struct of_device_id *id;
++ struct device *dev = &pdev->dev;
++ struct device *argon_mem_dev;
++ struct resource *ioresource;
++ struct argon_mem_priv *priv;
++
++
++ /* Allocate buffers and instance data */
++
++ priv = kzalloc(sizeof(struct argon_mem_priv), GFP_KERNEL);
++
++ if (!priv) {
++ err = -ENOMEM;
++ goto failed_inst_alloc;
++ }
++ platform_set_drvdata(pdev, priv);
++
++ priv->dev = dev;
++ id = of_match_device(argon_mem_of_match, dev);
++ if (!id)
++ return -EINVAL;
++ priv->name = id->data;
++
++ ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (ioresource) {
++ priv->regs_phys = ioresource->start;
++ priv->mem_window_len = ioresource->end - ioresource->start;
++ } else {
++ dev_err(priv->dev, "failed to get IO resource");
++ err = -ENOENT;
++ goto failed_get_resource;
++ }
++
++ /* Create character device entries */
++
++ err = alloc_chrdev_region(&priv->devid,
++ DEVICE_MINOR, 1, priv->name);
++ if (err != 0) {
++ dev_err(priv->dev, "unable to allocate device number");
++ goto failed_alloc_chrdev;
++ }
++ cdev_init(&priv->argon_mem_cdev, &argon_mem_fops);
++ priv->argon_mem_cdev.owner = THIS_MODULE;
++ err = cdev_add(&priv->argon_mem_cdev, priv->devid, 1);
++ if (err != 0) {
++ dev_err(priv->dev, "unable to register device");
++ goto failed_cdev_add;
++ }
++
++ /* Create sysfs entries */
++
++ priv->class = class_create(THIS_MODULE, priv->name);
++ ptr_err = priv->class;
++ if (IS_ERR(ptr_err))
++ goto failed_class_create;
++
++ argon_mem_dev = device_create(priv->class, NULL,
++ priv->devid, NULL,
++ priv->name);
++ ptr_err = argon_mem_dev;
++ if (IS_ERR(ptr_err))
++ goto failed_device_create;
++
++ dev_info(priv->dev, "%s initialised: Registers at 0x%08lx length 0x%08lx",
++ priv->name, priv->regs_phys, priv->mem_window_len);
++
++ return 0;
++
++failed_device_create:
++ class_destroy(priv->class);
++failed_class_create:
++ cdev_del(&priv->argon_mem_cdev);
++ err = PTR_ERR(ptr_err);
++failed_cdev_add:
++ unregister_chrdev_region(priv->devid, 1);
++failed_alloc_chrdev:
++failed_get_resource:
++ kfree(priv);
++failed_inst_alloc:
++ dev_err(priv->dev, "could not load argon_mem");
++ return err;
++}
++
++static int argon_mem_remove(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct argon_mem_priv *priv = platform_get_drvdata(pdev);
++
++ device_destroy(priv->class, priv->devid);
++ class_destroy(priv->class);
++ cdev_del(&priv->argon_mem_cdev);
++ unregister_chrdev_region(priv->devid, 1);
++ kfree(priv);
++
++ dev_info(dev, "%s driver removed - OK", priv->name);
++ return 0;
++}
++
++static const char argon_hevc_name[] = "argon-hevcmem";
++static const char argon_h264_name[] = "argon-h264mem";
++static const char argon_vp9_name[] = "argon-vp9mem";
++static const char argon_intc_name[] = "argon-intcmem";
++
++static const struct of_device_id argon_mem_of_match[] = {
++ {
++ .compatible = "raspberrypi,argon-hevc-decoder",
++ .data = &argon_hevc_name,
++ },
++ {
++ .compatible = "raspberrypi,argon-h264-decoder",
++ .data = &argon_h264_name,
++ },
++ {
++ .compatible = "raspberrypi,argon-vp9-decoder",
++ .data = &argon_vp9_name,
++ },
++ /* The "intc" is included as this block of hardware contains the
++ * "frame done" status flags.
++ */
++ {
++ .compatible = "raspberrypi,argon-local-intc",
++ .data = &argon_intc_name,
++ },
++ { /* sentinel */ },
++};
++
++MODULE_DEVICE_TABLE(of, argon_mem_of_match);
++
++static struct platform_driver argon_mem_driver = {
++ .probe = argon_mem_probe,
++ .remove = argon_mem_remove,
++ .driver = {
++ .name = DRIVER_NAME,
++ .owner = THIS_MODULE,
++ .of_match_table = argon_mem_of_match,
++ },
++};
++
++module_platform_driver(argon_mem_driver);
++
++MODULE_ALIAS("platform:argon-mem");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Driver for accessing Argon decoder registers from userspace");
++MODULE_AUTHOR("Jonathan Bell <jonathan@raspberrypi.org>");
+++ /dev/null
-From 42738c082b40c372dcaebfae4dcbd3b3251cb37f Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 23 May 2019 15:08:30 +0100
-Subject: [PATCH 554/703] usb: xhci: Show that the VIA VL805 supports LPM
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/usb/host/xhci-pci.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/usb/host/xhci-pci.c
-+++ b/drivers/usb/host/xhci-pci.c
-@@ -222,6 +222,10 @@ static void xhci_pci_quirks(struct devic
- pdev->device == 0x3432)
- xhci->quirks |= XHCI_BROKEN_STREAMS;
-
-+ if (pdev->vendor == PCI_VENDOR_ID_VIA &&
-+ pdev->device == 0x3483)
-+ xhci->quirks |= XHCI_LPM_SUPPORT;
-+
- if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
- pdev->device == 0x1042)
- xhci->quirks |= XHCI_BROKEN_STREAMS;
--- /dev/null
+From 3ac14a916d67071cd0311de9cf420e5a649c7517 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 23 Jan 2019 16:11:50 +0000
+Subject: [PATCH 555/725] clk-bcm2835: Don't wait for pllh lock
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -627,15 +627,17 @@ static int bcm2835_pll_on(struct clk_hw
+ spin_unlock(&cprman->regs_lock);
+
+ /* Wait for the PLL to lock. */
+- timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
+- while (!(cprman_read(cprman, CM_LOCK) & data->lock_mask)) {
+- if (ktime_after(ktime_get(), timeout)) {
+- dev_err(cprman->dev, "%s: couldn't lock PLL\n",
+- clk_hw_get_name(hw));
+- return -ETIMEDOUT;
+- }
++ if (strcmp(data->name, "pllh")) {
++ timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
++ while (!(cprman_read(cprman, CM_LOCK) & data->lock_mask)) {
++ if (ktime_after(ktime_get(), timeout)) {
++ dev_err(cprman->dev, "%s: couldn't lock PLL\n",
++ clk_hw_get_name(hw));
++ return -ETIMEDOUT;
++ }
+
+- cpu_relax();
++ cpu_relax();
++ }
+ }
+
+ cprman_write(cprman, data->a2w_ctrl_reg,
+++ /dev/null
-From dd2f4acbdd9731757fe9aedd11164d67a785e25c Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Thu, 30 May 2019 10:38:40 +0100
-Subject: [PATCH 555/703] usb: xhci: hack xhci_urb_enqueue to support
- hid.mousepoll behaviour
-
-xHCI creates endpoint contexts directly from the device's endpoint
-data, so submitting URBs with urb->interval different from the hardware
-interval has no effect.
-
-Add an explicit reconfiguration of the endpoint context when requested,
-which will happen only when the interval is different from the cached
-value. In practice, the reconfiguration only happens on the first URB
-submitted for the endpoint.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/usb/host/xhci.c | 86 +++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 86 insertions(+)
-
---- a/drivers/usb/host/xhci.c
-+++ b/drivers/usb/host/xhci.c
-@@ -1416,6 +1416,87 @@ command_cleanup:
- }
-
- /*
-+ * RPI: Fixup endpoint intervals when requested
-+ * - Check interval versus the (cached) endpoint context
-+ * - set the endpoint interval to the new value
-+ * - force an endpoint configure command
-+ */
-+static void xhci_fixup_interval(struct xhci_hcd *xhci, struct urb *urb,
-+ unsigned int slot_id, unsigned int ep_index)
-+{
-+ struct xhci_ep_ctx *ep_ctx_out, *ep_ctx_in;
-+ struct xhci_command *command;
-+ struct xhci_input_control_ctx *ctrl_ctx;
-+ struct xhci_virt_device *vdev;
-+ int xhci_interval, ep_interval;
-+ int ret;
-+ unsigned long flags;
-+ u32 ep_info_tmp;
-+
-+ spin_lock_irqsave(&xhci->lock, flags);
-+
-+ vdev = xhci->devs[slot_id];
-+ /* Get context-derived endpoint interval */
-+ ep_ctx_out = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
-+ ep_ctx_in = xhci_get_ep_ctx(xhci, vdev->in_ctx, ep_index);
-+ xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx_out->ep_info));
-+ ep_interval = urb->interval * 8;
-+
-+ if (ep_interval == xhci_interval) {
-+ spin_unlock_irqrestore(&xhci->lock, flags);
-+ return;
-+ }
-+
-+ xhci_dbg(xhci, "Fixup interval ep_interval=%d xhci_interval=%d\n",
-+ ep_interval, xhci_interval);
-+ command = xhci_alloc_command_with_ctx(xhci, true, GFP_ATOMIC);
-+ if (!command) {
-+ /* Failure here is benign, poll at the original rate */
-+ spin_unlock_irqrestore(&xhci->lock, flags);
-+ return;
-+ }
-+
-+ /* xHCI uses exponents for intervals... */
-+ xhci_interval = fls(ep_interval) - 1;
-+ xhci_interval = clamp_val(xhci_interval, 3, 10);
-+ ep_info_tmp = le32_to_cpu(ep_ctx_out->ep_info);
-+ ep_info_tmp &= ~EP_INTERVAL(255);
-+ ep_info_tmp |= EP_INTERVAL(xhci_interval);
-+
-+ /* Keep the endpoint context up-to-date while issuing the command. */
-+ xhci_endpoint_copy(xhci, vdev->in_ctx,
-+ vdev->out_ctx, ep_index);
-+ ep_ctx_in->ep_info = cpu_to_le32(ep_info_tmp);
-+
-+ /*
-+ * We need to drop the lock, so take an explicit copy
-+ * of the ep context.
-+ */
-+ xhci_endpoint_copy(xhci, command->in_ctx, vdev->in_ctx, ep_index);
-+
-+ ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx);
-+ if (!ctrl_ctx) {
-+ xhci_warn(xhci,
-+ "%s: Could not get input context, bad type.\n",
-+ __func__);
-+ spin_unlock_irqrestore(&xhci->lock, flags);
-+ xhci_free_command(xhci, command);
-+ return;
-+ }
-+ ctrl_ctx->add_flags = xhci_get_endpoint_flag_from_index(ep_index);
-+ ctrl_ctx->drop_flags = 0;
-+
-+ spin_unlock_irqrestore(&xhci->lock, flags);
-+
-+ ret = xhci_configure_endpoint(xhci, urb->dev, command,
-+ false, false);
-+ if (ret)
-+ xhci_warn(xhci, "%s: Configure endpoint failed: %d\n",
-+ __func__, ret);
-+ xhci_free_command(xhci, command);
-+}
-+
-+/*
- * non-error returns are a promise to giveback() the urb later
- * we drop ownership so next owner (or urb unlink) can get it
- */
-@@ -1483,6 +1564,11 @@ static int xhci_urb_enqueue(struct usb_h
- }
- }
-
-+ if (usb_endpoint_xfer_int(&urb->ep->desc) &&
-+ (urb->dev->speed == USB_SPEED_FULL ||
-+ urb->dev->speed == USB_SPEED_LOW))
-+ xhci_fixup_interval(xhci, urb, slot_id, ep_index);
-+
- spin_lock_irqsave(&xhci->lock, flags);
-
- if (xhci->xhc_state & XHCI_STATE_DYING) {
--- /dev/null
+From 6b41815e23a72453b859e245cad9fcd6a5f0ef31 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 12 Dec 2018 15:51:47 -0800
+Subject: [PATCH 556/725] bcm2835-pm: Move bcm2835-watchdog's DT probe to an
+ MFD.
+
+The PM block that the wdt driver was binding to actually has multiple
+features we want to expose (power domains, reset, watchdog). Move the
+DT attachment to a MFD driver and make WDT probe against MFD.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+(cherry picked from commit 5e6acc3e678ed3db746ab4fb53a980861cd711b6)
+---
+ drivers/mfd/Makefile | 1 +
+ drivers/mfd/bcm2835-pm.c | 64 ++++++++++++++++++++++++++++++++++
+ drivers/watchdog/bcm2835_wdt.c | 26 +++++---------
+ include/linux/mfd/bcm2835-pm.h | 13 +++++++
+ 4 files changed, 87 insertions(+), 17 deletions(-)
+ create mode 100644 drivers/mfd/bcm2835-pm.c
+ create mode 100644 include/linux/mfd/bcm2835-pm.h
+
+--- a/drivers/mfd/Makefile
++++ b/drivers/mfd/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_MFD_88PM805) += 88pm805.o 8
+ obj-$(CONFIG_MFD_ACT8945A) += act8945a.o
+ obj-$(CONFIG_MFD_SM501) += sm501.o
+ obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
++obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o
+ obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
+ obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
+ cros_ec_core-objs := cros_ec.o
+--- /dev/null
++++ b/drivers/mfd/bcm2835-pm.c
+@@ -0,0 +1,64 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * PM MFD driver for Broadcom BCM2835
++ *
++ * This driver binds to the PM block and creates the MFD device for
++ * the WDT driver.
++ */
++
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/mfd/bcm2835-pm.h>
++#include <linux/mfd/core.h>
++#include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/of_platform.h>
++#include <linux/platform_device.h>
++#include <linux/types.h>
++#include <linux/watchdog.h>
++
++static const struct mfd_cell bcm2835_pm_devs[] = {
++ { .name = "bcm2835-wdt" },
++};
++
++static int bcm2835_pm_probe(struct platform_device *pdev)
++{
++ struct resource *res;
++ struct device *dev = &pdev->dev;
++ struct bcm2835_pm *pm;
++
++ pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL);
++ if (!pm)
++ return -ENOMEM;
++ platform_set_drvdata(pdev, pm);
++
++ pm->dev = dev;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ pm->base = devm_ioremap_resource(dev, res);
++ if (IS_ERR(pm->base))
++ return PTR_ERR(pm->base);
++
++ return devm_mfd_add_devices(dev, -1,
++ bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
++ NULL, 0, NULL);
++}
++
++static const struct of_device_id bcm2835_pm_of_match[] = {
++ { .compatible = "brcm,bcm2835-pm-wdt", },
++ {},
++};
++MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
++
++static struct platform_driver bcm2835_pm_driver = {
++ .probe = bcm2835_pm_probe,
++ .driver = {
++ .name = "bcm2835-pm",
++ .of_match_table = bcm2835_pm_of_match,
++ },
++};
++module_platform_driver(bcm2835_pm_driver);
++
++MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
++MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM MFD");
++MODULE_LICENSE("GPL");
+--- a/drivers/watchdog/bcm2835_wdt.c
++++ b/drivers/watchdog/bcm2835_wdt.c
+@@ -12,6 +12,7 @@
+
+ #include <linux/delay.h>
+ #include <linux/types.h>
++#include <linux/mfd/bcm2835-pm.h>
+ #include <linux/module.h>
+ #include <linux/io.h>
+ #include <linux/watchdog.h>
+@@ -41,6 +42,8 @@ struct bcm2835_wdt {
+ spinlock_t lock;
+ };
+
++static struct bcm2835_wdt *bcm2835_power_off_wdt;
++
+ static unsigned int heartbeat;
+ static bool nowayout = WATCHDOG_NOWAYOUT;
+
+@@ -163,10 +166,7 @@ static struct watchdog_device bcm2835_wd
+ */
+ static void bcm2835_power_off(void)
+ {
+- struct device_node *np =
+- 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);
++ struct bcm2835_wdt *wdt = bcm2835_power_off_wdt;
+
+ /* Partition 63 tells the firmware that this is a halt */
+ __bcm2835_restart(wdt, 63);
+@@ -174,7 +174,7 @@ static void bcm2835_power_off(void)
+
+ static int bcm2835_wdt_probe(struct platform_device *pdev)
+ {
+- struct resource *res;
++ struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
+ struct device *dev = &pdev->dev;
+ struct bcm2835_wdt *wdt;
+ int err;
+@@ -186,10 +186,7 @@ static int bcm2835_wdt_probe(struct plat
+
+ spin_lock_init(&wdt->lock);
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- wdt->base = devm_ioremap_resource(dev, res);
+- if (IS_ERR(wdt->base))
+- return PTR_ERR(wdt->base);
++ wdt->base = pm->base;
+
+ watchdog_set_drvdata(&bcm2835_wdt_wdd, wdt);
+ watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev);
+@@ -216,8 +213,10 @@ static int bcm2835_wdt_probe(struct plat
+ return err;
+ }
+
+- if (pm_power_off == NULL)
++ if (pm_power_off == NULL) {
+ pm_power_off = bcm2835_power_off;
++ bcm2835_power_off_wdt = wdt;
++ }
+
+ dev_info(dev, "Broadcom BCM2835 watchdog timer");
+ return 0;
+@@ -231,18 +230,11 @@ static int bcm2835_wdt_remove(struct pla
+ return 0;
+ }
+
+-static const struct of_device_id bcm2835_wdt_of_match[] = {
+- { .compatible = "brcm,bcm2835-pm-wdt", },
+- {},
+-};
+-MODULE_DEVICE_TABLE(of, bcm2835_wdt_of_match);
+-
+ static struct platform_driver bcm2835_wdt_driver = {
+ .probe = bcm2835_wdt_probe,
+ .remove = bcm2835_wdt_remove,
+ .driver = {
+ .name = "bcm2835-wdt",
+- .of_match_table = bcm2835_wdt_of_match,
+ },
+ };
+ module_platform_driver(bcm2835_wdt_driver);
+--- /dev/null
++++ b/include/linux/mfd/bcm2835-pm.h
+@@ -0,0 +1,13 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++
++#ifndef BCM2835_MFD_PM_H
++#define BCM2835_MFD_PM_H
++
++#include <linux/regmap.h>
++
++struct bcm2835_pm {
++ struct device *dev;
++ void __iomem *base;
++};
++
++#endif /* BCM2835_MFD_PM_H */
+++ /dev/null
-From 9d0c6b7b815e9c8d578299446a28c3ed54700464 Mon Sep 17 00:00:00 2001
-From: Tim Gover <tim.gover@raspberrypi.org>
-Date: Wed, 9 Jan 2019 14:43:36 +0000
-Subject: [PATCH 556/703] pinctrl-bcm2835: Add support for BCM2838
-
-GPIO configuration on BCM2838 is largely the same as BCM2835 except for
-the pull up/down configuration. The old mechanism has been replaced
-by new registers which don't require the fixed delay.
-
-Detect BCN2838 at run-time and use the new mechanism. Backwards
-compatibility for the device-tree configuration has been retained.
----
- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 58 ++++++++++++++++++++-------
- 1 file changed, 44 insertions(+), 14 deletions(-)
-
---- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-@@ -67,6 +67,12 @@
- #define GPPUD 0x94 /* Pin Pull-up/down Enable */
- #define GPPUDCLK0 0x98 /* Pin Pull-up/down Enable Clock */
-
-+/* 2711 has a different mechanism for pin pull-up/down/enable */
-+#define GPPUPPDN0 0xe4 /* Pin pull-up/down for pins 15:0 */
-+#define GPPUPPDN1 0xe8 /* Pin pull-up/down for pins 31:16 */
-+#define GPPUPPDN2 0xec /* Pin pull-up/down for pins 47:32 */
-+#define GPPUPPDN3 0xf0 /* Pin pull-up/down for pins 57:48 */
-+
- #define FSEL_REG(p) (GPFSEL0 + (((p) / 10) * 4))
- #define FSEL_SHIFT(p) (((p) % 10) * 3)
- #define GPIO_REG_OFFSET(p) ((p) / 32)
-@@ -917,21 +923,45 @@ static void bcm2835_pull_config_set(stru
- unsigned int pin, unsigned int arg)
- {
- u32 off, bit;
-+ /* BCM2835, BCM2836 & BCM2837 return 'gpio' for this unused register */
-+ int is_2835 = bcm2835_gpio_rd(pc, GPPUPPDN3) == 0x6770696f;
-
-- off = GPIO_REG_OFFSET(pin);
-- bit = GPIO_REG_SHIFT(pin);
--
-- bcm2835_gpio_wr(pc, GPPUD, arg & 3);
-- /*
-- * BCM2835 datasheet say to wait 150 cycles, but not of what.
-- * But the VideoCore firmware delay for this operation
-- * based nearly on the same amount of VPU cycles and this clock
-- * runs at 250 MHz.
-- */
-- udelay(1);
-- bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
-- udelay(1);
-- bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
-+ if (is_2835) {
-+ off = GPIO_REG_OFFSET(pin);
-+ bit = GPIO_REG_SHIFT(pin);
-+ /*
-+ * BCM2835 datasheet say to wait 150 cycles, but not of what.
-+ * But the VideoCore firmware delay for this operation
-+ * based nearly on the same amount of VPU cycles and this clock
-+ * runs at 250 MHz.
-+ */
-+ bcm2835_gpio_wr(pc, GPPUD, arg & 3);
-+ udelay(1);
-+ bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
-+ udelay(1);
-+ bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
-+ } else {
-+ u32 reg;
-+ int lsb;
-+
-+ off = (pin >> 4);
-+ if (off > 3)
-+ return;
-+ lsb = (pin & 0xf) << 1;
-+
-+ /* The up/down semantics are reversed compared to BCM2835.
-+ * Instead of updating all the device tree files, translate the
-+ * values here.
-+ */
-+ if (arg == 2)
-+ arg = 1;
-+ else if (arg == 1)
-+ arg = 2;
-+ reg = bcm2835_gpio_rd(pc, GPPUPPDN0 + (off *4));
-+ reg &= ~(0x3 << lsb);
-+ reg |= (arg & 3) << lsb;
-+ bcm2835_gpio_wr(pc, GPPUPPDN0 + (off * 4), reg);
-+ }
- }
-
- static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
--- /dev/null
+From 25b7b6863a8dd292fa88309f70c980265b076c4e Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 12 Dec 2018 15:51:48 -0800
+Subject: [PATCH 557/725] soc: bcm: bcm2835-pm: Add support for power domains
+ under a new binding.
+
+This provides a free software alternative to raspberrypi-power.c's
+firmware calls to manage power domains. It also exposes a reset line,
+where previously the vc4 driver had to try to force power off the
+domain in order to trigger a reset.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Acked-by: Rob Herring <robh@kernel.org>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+(cherry picked from commit 670c672608a1ffcbc7ac0f872734843593bb8b15)
+---
+ drivers/mfd/bcm2835-pm.c | 36 +-
+ drivers/soc/bcm/Kconfig | 11 +
+ drivers/soc/bcm/Makefile | 1 +
+ drivers/soc/bcm/bcm2835-power.c | 661 +++++++++++++++++++++++++++
+ include/dt-bindings/soc/bcm2835-pm.h | 28 ++
+ include/linux/mfd/bcm2835-pm.h | 1 +
+ 6 files changed, 734 insertions(+), 4 deletions(-)
+ create mode 100644 drivers/soc/bcm/bcm2835-power.c
+ create mode 100644 include/dt-bindings/soc/bcm2835-pm.h
+
+--- a/drivers/mfd/bcm2835-pm.c
++++ b/drivers/mfd/bcm2835-pm.c
+@@ -3,7 +3,7 @@
+ * PM MFD driver for Broadcom BCM2835
+ *
+ * This driver binds to the PM block and creates the MFD device for
+- * the WDT driver.
++ * the WDT and power drivers.
+ */
+
+ #include <linux/delay.h>
+@@ -21,11 +21,16 @@ static const struct mfd_cell bcm2835_pm_
+ { .name = "bcm2835-wdt" },
+ };
+
++static const struct mfd_cell bcm2835_power_devs[] = {
++ { .name = "bcm2835-power" },
++};
++
+ static int bcm2835_pm_probe(struct platform_device *pdev)
+ {
+ struct resource *res;
+ struct device *dev = &pdev->dev;
+ struct bcm2835_pm *pm;
++ int ret;
+
+ pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL);
+ if (!pm)
+@@ -39,13 +44,36 @@ static int bcm2835_pm_probe(struct platf
+ if (IS_ERR(pm->base))
+ return PTR_ERR(pm->base);
+
+- return devm_mfd_add_devices(dev, -1,
+- bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
+- NULL, 0, NULL);
++ ret = devm_mfd_add_devices(dev, -1,
++ bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
++ NULL, 0, NULL);
++ if (ret)
++ return ret;
++
++ /* We'll use the presence of the AXI ASB regs in the
++ * bcm2835-pm binding as the key for whether we can reference
++ * the full PM register range and support power domains.
++ */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ if (res) {
++ pm->asb = devm_ioremap_resource(dev, res);
++ if (IS_ERR(pm->asb))
++ return PTR_ERR(pm->asb);
++
++ ret = devm_mfd_add_devices(dev, -1,
++ bcm2835_power_devs,
++ ARRAY_SIZE(bcm2835_power_devs),
++ NULL, 0, NULL);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
+ }
+
+ static const struct of_device_id bcm2835_pm_of_match[] = {
+ { .compatible = "brcm,bcm2835-pm-wdt", },
++ { .compatible = "brcm,bcm2835-pm", },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
+--- a/drivers/soc/bcm/Kconfig
++++ b/drivers/soc/bcm/Kconfig
+@@ -1,5 +1,16 @@
+ menu "Broadcom SoC drivers"
+
++config BCM2835_POWER
++ bool "BCM2835 power domain driver"
++ depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
++ select PM_GENERIC_DOMAINS if PM
++ select RESET_CONTROLLER
++ help
++ This enables support for the BCM2835 power domains and reset
++ controller. Any usage of power domains by the Raspberry Pi
++ firmware means that Linux usage of the same power domain
++ must be accessed using the RASPBERRYPI_POWER driver
++
+ config RASPBERRYPI_POWER
+ bool "Raspberry Pi power domain driver"
+ depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
+--- a/drivers/soc/bcm/Makefile
++++ b/drivers/soc/bcm/Makefile
+@@ -1,2 +1,3 @@
++obj-$(CONFIG_BCM2835_POWER) += bcm2835-power.o
+ obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o
+ obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
+--- /dev/null
++++ b/drivers/soc/bcm/bcm2835-power.c
+@@ -0,0 +1,661 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Power domain driver for Broadcom BCM2835
++ *
++ * Copyright (C) 2018 Broadcom
++ */
++
++#include <dt-bindings/soc/bcm2835-pm.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/mfd/bcm2835-pm.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/pm_domain.h>
++#include <linux/reset-controller.h>
++#include <linux/types.h>
++
++#define PM_GNRIC 0x00
++#define PM_AUDIO 0x04
++#define PM_STATUS 0x18
++#define PM_RSTC 0x1c
++#define PM_RSTS 0x20
++#define PM_WDOG 0x24
++#define PM_PADS0 0x28
++#define PM_PADS2 0x2c
++#define PM_PADS3 0x30
++#define PM_PADS4 0x34
++#define PM_PADS5 0x38
++#define PM_PADS6 0x3c
++#define PM_CAM0 0x44
++#define PM_CAM0_LDOHPEN BIT(2)
++#define PM_CAM0_LDOLPEN BIT(1)
++#define PM_CAM0_CTRLEN BIT(0)
++
++#define PM_CAM1 0x48
++#define PM_CAM1_LDOHPEN BIT(2)
++#define PM_CAM1_LDOLPEN BIT(1)
++#define PM_CAM1_CTRLEN BIT(0)
++
++#define PM_CCP2TX 0x4c
++#define PM_CCP2TX_LDOEN BIT(1)
++#define PM_CCP2TX_CTRLEN BIT(0)
++
++#define PM_DSI0 0x50
++#define PM_DSI0_LDOHPEN BIT(2)
++#define PM_DSI0_LDOLPEN BIT(1)
++#define PM_DSI0_CTRLEN BIT(0)
++
++#define PM_DSI1 0x54
++#define PM_DSI1_LDOHPEN BIT(2)
++#define PM_DSI1_LDOLPEN BIT(1)
++#define PM_DSI1_CTRLEN BIT(0)
++
++#define PM_HDMI 0x58
++#define PM_HDMI_RSTDR BIT(19)
++#define PM_HDMI_LDOPD BIT(1)
++#define PM_HDMI_CTRLEN BIT(0)
++
++#define PM_USB 0x5c
++/* The power gates must be enabled with this bit before enabling the LDO in the
++ * USB block.
++ */
++#define PM_USB_CTRLEN BIT(0)
++
++#define PM_PXLDO 0x60
++#define PM_PXBG 0x64
++#define PM_DFT 0x68
++#define PM_SMPS 0x6c
++#define PM_XOSC 0x70
++#define PM_SPAREW 0x74
++#define PM_SPARER 0x78
++#define PM_AVS_RSTDR 0x7c
++#define PM_AVS_STAT 0x80
++#define PM_AVS_EVENT 0x84
++#define PM_AVS_INTEN 0x88
++#define PM_DUMMY 0xfc
++
++#define PM_IMAGE 0x108
++#define PM_GRAFX 0x10c
++#define PM_PROC 0x110
++#define PM_ENAB BIT(12)
++#define PM_ISPRSTN BIT(8)
++#define PM_H264RSTN BIT(7)
++#define PM_PERIRSTN BIT(6)
++#define PM_V3DRSTN BIT(6)
++#define PM_ISFUNC BIT(5)
++#define PM_MRDONE BIT(4)
++#define PM_MEMREP BIT(3)
++#define PM_ISPOW BIT(2)
++#define PM_POWOK BIT(1)
++#define PM_POWUP BIT(0)
++#define PM_INRUSH_SHIFT 13
++#define PM_INRUSH_3_5_MA 0
++#define PM_INRUSH_5_MA 1
++#define PM_INRUSH_10_MA 2
++#define PM_INRUSH_20_MA 3
++#define PM_INRUSH_MASK (3 << PM_INRUSH_SHIFT)
++
++#define PM_PASSWORD 0x5a000000
++
++#define PM_WDOG_TIME_SET 0x000fffff
++#define PM_RSTC_WRCFG_CLR 0xffffffcf
++#define PM_RSTS_HADWRH_SET 0x00000040
++#define PM_RSTC_WRCFG_SET 0x00000030
++#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
++#define PM_RSTC_RESET 0x00000102
++
++#define PM_READ(reg) readl(power->base + (reg))
++#define PM_WRITE(reg, val) writel(PM_PASSWORD | (val), power->base + (reg))
++
++#define ASB_BRDG_VERSION 0x00
++#define ASB_CPR_CTRL 0x04
++
++#define ASB_V3D_S_CTRL 0x08
++#define ASB_V3D_M_CTRL 0x0c
++#define ASB_ISP_S_CTRL 0x10
++#define ASB_ISP_M_CTRL 0x14
++#define ASB_H264_S_CTRL 0x18
++#define ASB_H264_M_CTRL 0x1c
++
++#define ASB_REQ_STOP BIT(0)
++#define ASB_ACK BIT(1)
++#define ASB_EMPTY BIT(2)
++#define ASB_FULL BIT(3)
++
++#define ASB_AXI_BRDG_ID 0x20
++
++#define ASB_READ(reg) readl(power->asb + (reg))
++#define ASB_WRITE(reg, val) writel(PM_PASSWORD | (val), power->asb + (reg))
++
++struct bcm2835_power_domain {
++ struct generic_pm_domain base;
++ struct bcm2835_power *power;
++ u32 domain;
++ struct clk *clk;
++};
++
++struct bcm2835_power {
++ struct device *dev;
++ /* PM registers. */
++ void __iomem *base;
++ /* AXI Async bridge registers. */
++ void __iomem *asb;
++
++ struct genpd_onecell_data pd_xlate;
++ struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
++ struct reset_controller_dev reset;
++};
++
++static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
++{
++ u64 start = ktime_get_ns();
++
++ /* Enable the module's async AXI bridges. */
++ ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP);
++ while (ASB_READ(reg) & ASB_ACK) {
++ cpu_relax();
++ if (ktime_get_ns() - start >= 1000)
++ return -ETIMEDOUT;
++ }
++
++ return 0;
++}
++
++static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
++{
++ u64 start = ktime_get_ns();
++
++ /* Enable the module's async AXI bridges. */
++ ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP);
++ while (!(ASB_READ(reg) & ASB_ACK)) {
++ cpu_relax();
++ if (ktime_get_ns() - start >= 1000)
++ return -ETIMEDOUT;
++ }
++
++ return 0;
++}
++
++static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg)
++{
++ struct bcm2835_power *power = pd->power;
++
++ /* Enable functional isolation */
++ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
++
++ /* Enable electrical isolation */
++ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
++
++ /* Open the power switches. */
++ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP);
++
++ return 0;
++}
++
++static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg)
++{
++ struct bcm2835_power *power = pd->power;
++ struct device *dev = power->dev;
++ u64 start;
++ int ret;
++ int inrush;
++ bool powok;
++
++ /* If it was already powered on by the fw, leave it that way. */
++ if (PM_READ(pm_reg) & PM_POWUP)
++ return 0;
++
++ /* Enable power. Allowing too much current at once may result
++ * in POWOK never getting set, so start low and ramp it up as
++ * necessary to succeed.
++ */
++ powok = false;
++ for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; inrush++) {
++ PM_WRITE(pm_reg,
++ (PM_READ(pm_reg) & ~PM_INRUSH_MASK) |
++ (inrush << PM_INRUSH_SHIFT) |
++ PM_POWUP);
++
++ start = ktime_get_ns();
++ while (!(powok = !!(PM_READ(pm_reg) & PM_POWOK))) {
++ cpu_relax();
++ if (ktime_get_ns() - start >= 3000)
++ break;
++ }
++ }
++ if (!powok) {
++ dev_err(dev, "Timeout waiting for %s power OK\n",
++ pd->base.name);
++ ret = -ETIMEDOUT;
++ goto err_disable_powup;
++ }
++
++ /* Disable electrical isolation */
++ PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW);
++
++ /* Repair memory */
++ PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP);
++ start = ktime_get_ns();
++ while (!(PM_READ(pm_reg) & PM_MRDONE)) {
++ cpu_relax();
++ if (ktime_get_ns() - start >= 1000) {
++ dev_err(dev, "Timeout waiting for %s memory repair\n",
++ pd->base.name);
++ ret = -ETIMEDOUT;
++ goto err_disable_ispow;
++ }
++ }
++
++ /* Disable functional isolation */
++ PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC);
++
++ return 0;
++
++err_disable_ispow:
++ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
++err_disable_powup:
++ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK));
++ return ret;
++}
++
++static int bcm2835_asb_power_on(struct bcm2835_power_domain *pd,
++ u32 pm_reg,
++ u32 asb_m_reg,
++ u32 asb_s_reg,
++ u32 reset_flags)
++{
++ struct bcm2835_power *power = pd->power;
++ int ret;
++
++ ret = clk_prepare_enable(pd->clk);
++ if (ret) {
++ dev_err(power->dev, "Failed to enable clock for %s\n",
++ pd->base.name);
++ return ret;
++ }
++
++ /* Wait 32 clocks for reset to propagate, 1 us will be enough */
++ udelay(1);
++
++ clk_disable_unprepare(pd->clk);
++
++ /* Deassert the resets. */
++ PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags);
++
++ ret = clk_prepare_enable(pd->clk);
++ if (ret) {
++ dev_err(power->dev, "Failed to enable clock for %s\n",
++ pd->base.name);
++ goto err_enable_resets;
++ }
++
++ ret = bcm2835_asb_enable(power, asb_m_reg);
++ if (ret) {
++ dev_err(power->dev, "Failed to enable ASB master for %s\n",
++ pd->base.name);
++ goto err_disable_clk;
++ }
++ ret = bcm2835_asb_enable(power, asb_s_reg);
++ if (ret) {
++ dev_err(power->dev, "Failed to enable ASB slave for %s\n",
++ pd->base.name);
++ goto err_disable_asb_master;
++ }
++
++ return 0;
++
++err_disable_asb_master:
++ bcm2835_asb_disable(power, asb_m_reg);
++err_disable_clk:
++ clk_disable_unprepare(pd->clk);
++err_enable_resets:
++ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
++ return ret;
++}
++
++static int bcm2835_asb_power_off(struct bcm2835_power_domain *pd,
++ u32 pm_reg,
++ u32 asb_m_reg,
++ u32 asb_s_reg,
++ u32 reset_flags)
++{
++ struct bcm2835_power *power = pd->power;
++ int ret;
++
++ ret = bcm2835_asb_disable(power, asb_s_reg);
++ if (ret) {
++ dev_warn(power->dev, "Failed to disable ASB slave for %s\n",
++ pd->base.name);
++ return ret;
++ }
++ ret = bcm2835_asb_disable(power, asb_m_reg);
++ if (ret) {
++ dev_warn(power->dev, "Failed to disable ASB master for %s\n",
++ pd->base.name);
++ bcm2835_asb_enable(power, asb_s_reg);
++ return ret;
++ }
++
++ clk_disable_unprepare(pd->clk);
++
++ /* Assert the resets. */
++ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
++
++ return 0;
++}
++
++static int bcm2835_power_pd_power_on(struct generic_pm_domain *domain)
++{
++ struct bcm2835_power_domain *pd =
++ container_of(domain, struct bcm2835_power_domain, base);
++ struct bcm2835_power *power = pd->power;
++
++ switch (pd->domain) {
++ case BCM2835_POWER_DOMAIN_GRAFX:
++ return bcm2835_power_power_on(pd, PM_GRAFX);
++
++ case BCM2835_POWER_DOMAIN_GRAFX_V3D:
++ return bcm2835_asb_power_on(pd, PM_GRAFX,
++ ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
++ PM_V3DRSTN);
++
++ case BCM2835_POWER_DOMAIN_IMAGE:
++ return bcm2835_power_power_on(pd, PM_IMAGE);
++
++ case BCM2835_POWER_DOMAIN_IMAGE_PERI:
++ return bcm2835_asb_power_on(pd, PM_IMAGE,
++ 0, 0,
++ PM_PERIRSTN);
++
++ case BCM2835_POWER_DOMAIN_IMAGE_ISP:
++ return bcm2835_asb_power_on(pd, PM_IMAGE,
++ ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
++ PM_ISPRSTN);
++
++ case BCM2835_POWER_DOMAIN_IMAGE_H264:
++ return bcm2835_asb_power_on(pd, PM_IMAGE,
++ ASB_H264_M_CTRL, ASB_H264_S_CTRL,
++ PM_H264RSTN);
++
++ case BCM2835_POWER_DOMAIN_USB:
++ PM_WRITE(PM_USB, PM_USB_CTRLEN);
++ return 0;
++
++ case BCM2835_POWER_DOMAIN_DSI0:
++ PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
++ PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN);
++ return 0;
++
++ case BCM2835_POWER_DOMAIN_DSI1:
++ PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
++ PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN);
++ return 0;
++
++ case BCM2835_POWER_DOMAIN_CCP2TX:
++ PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
++ PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN);
++ return 0;
++
++ case BCM2835_POWER_DOMAIN_HDMI:
++ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR);
++ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN);
++ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD);
++ usleep_range(100, 200);
++ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR);
++ return 0;
++
++ default:
++ dev_err(power->dev, "Invalid domain %d\n", pd->domain);
++ return -EINVAL;
++ }
++}
++
++static int bcm2835_power_pd_power_off(struct generic_pm_domain *domain)
++{
++ struct bcm2835_power_domain *pd =
++ container_of(domain, struct bcm2835_power_domain, base);
++ struct bcm2835_power *power = pd->power;
++
++ switch (pd->domain) {
++ case BCM2835_POWER_DOMAIN_GRAFX:
++ return bcm2835_power_power_off(pd, PM_GRAFX);
++
++ case BCM2835_POWER_DOMAIN_GRAFX_V3D:
++ return bcm2835_asb_power_off(pd, PM_GRAFX,
++ ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
++ PM_V3DRSTN);
++
++ case BCM2835_POWER_DOMAIN_IMAGE:
++ return bcm2835_power_power_off(pd, PM_IMAGE);
++
++ case BCM2835_POWER_DOMAIN_IMAGE_PERI:
++ return bcm2835_asb_power_off(pd, PM_IMAGE,
++ 0, 0,
++ PM_PERIRSTN);
++
++ case BCM2835_POWER_DOMAIN_IMAGE_ISP:
++ return bcm2835_asb_power_off(pd, PM_IMAGE,
++ ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
++ PM_ISPRSTN);
++
++ case BCM2835_POWER_DOMAIN_IMAGE_H264:
++ return bcm2835_asb_power_off(pd, PM_IMAGE,
++ ASB_H264_M_CTRL, ASB_H264_S_CTRL,
++ PM_H264RSTN);
++
++ case BCM2835_POWER_DOMAIN_USB:
++ PM_WRITE(PM_USB, 0);
++ return 0;
++
++ case BCM2835_POWER_DOMAIN_DSI0:
++ PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
++ PM_WRITE(PM_DSI0, 0);
++ return 0;
++
++ case BCM2835_POWER_DOMAIN_DSI1:
++ PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
++ PM_WRITE(PM_DSI1, 0);
++ return 0;
++
++ case BCM2835_POWER_DOMAIN_CCP2TX:
++ PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
++ PM_WRITE(PM_CCP2TX, 0);
++ return 0;
++
++ case BCM2835_POWER_DOMAIN_HDMI:
++ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD);
++ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN);
++ return 0;
++
++ default:
++ dev_err(power->dev, "Invalid domain %d\n", pd->domain);
++ return -EINVAL;
++ }
++}
++
++static void
++bcm2835_init_power_domain(struct bcm2835_power *power,
++ int pd_xlate_index, const char *name)
++{
++ struct device *dev = power->dev;
++ struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
++
++ dom->clk = devm_clk_get(dev->parent, name);
++
++ dom->base.name = name;
++ dom->base.power_on = bcm2835_power_pd_power_on;
++ dom->base.power_off = bcm2835_power_pd_power_off;
++
++ dom->domain = pd_xlate_index;
++ dom->power = power;
++
++ /* XXX: on/off at boot? */
++ pm_genpd_init(&dom->base, NULL, true);
++
++ power->pd_xlate.domains[pd_xlate_index] = &dom->base;
++}
++
++/** bcm2835_reset_reset - Resets a block that has a reset line in the
++ * PM block.
++ *
++ * The consumer of the reset controller must have the power domain up
++ * -- there's no reset ability with the power domain down. To reset
++ * the sub-block, we just disable its access to memory through the
++ * ASB, reset, and re-enable.
++ */
++static int bcm2835_reset_reset(struct reset_controller_dev *rcdev,
++ unsigned long id)
++{
++ struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
++ reset);
++ struct bcm2835_power_domain *pd;
++ int ret;
++
++ switch (id) {
++ case BCM2835_RESET_V3D:
++ pd = &power->domains[BCM2835_POWER_DOMAIN_GRAFX_V3D];
++ break;
++ case BCM2835_RESET_H264:
++ pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_H264];
++ break;
++ case BCM2835_RESET_ISP:
++ pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_ISP];
++ break;
++ default:
++ dev_err(power->dev, "Bad reset id %ld\n", id);
++ return -EINVAL;
++ }
++
++ ret = bcm2835_power_pd_power_off(&pd->base);
++ if (ret)
++ return ret;
++
++ return bcm2835_power_pd_power_on(&pd->base);
++}
++
++static int bcm2835_reset_status(struct reset_controller_dev *rcdev,
++ unsigned long id)
++{
++ struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
++ reset);
++
++ switch (id) {
++ case BCM2835_RESET_V3D:
++ return !PM_READ(PM_GRAFX & PM_V3DRSTN);
++ case BCM2835_RESET_H264:
++ return !PM_READ(PM_IMAGE & PM_H264RSTN);
++ case BCM2835_RESET_ISP:
++ return !PM_READ(PM_IMAGE & PM_ISPRSTN);
++ default:
++ return -EINVAL;
++ }
++}
++
++const struct reset_control_ops bcm2835_reset_ops = {
++ .reset = bcm2835_reset_reset,
++ .status = bcm2835_reset_status,
++};
++
++static const char *const power_domain_names[] = {
++ [BCM2835_POWER_DOMAIN_GRAFX] = "grafx",
++ [BCM2835_POWER_DOMAIN_GRAFX_V3D] = "v3d",
++
++ [BCM2835_POWER_DOMAIN_IMAGE] = "image",
++ [BCM2835_POWER_DOMAIN_IMAGE_PERI] = "peri_image",
++ [BCM2835_POWER_DOMAIN_IMAGE_H264] = "h264",
++ [BCM2835_POWER_DOMAIN_IMAGE_ISP] = "isp",
++
++ [BCM2835_POWER_DOMAIN_USB] = "usb",
++ [BCM2835_POWER_DOMAIN_DSI0] = "dsi0",
++ [BCM2835_POWER_DOMAIN_DSI1] = "dsi1",
++ [BCM2835_POWER_DOMAIN_CAM0] = "cam0",
++ [BCM2835_POWER_DOMAIN_CAM1] = "cam1",
++ [BCM2835_POWER_DOMAIN_CCP2TX] = "ccp2tx",
++ [BCM2835_POWER_DOMAIN_HDMI] = "hdmi",
++};
++
++static int bcm2835_power_probe(struct platform_device *pdev)
++{
++ struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
++ struct device *dev = &pdev->dev;
++ struct bcm2835_power *power;
++ static const struct {
++ int parent, child;
++ } domain_deps[] = {
++ { BCM2835_POWER_DOMAIN_GRAFX, BCM2835_POWER_DOMAIN_GRAFX_V3D },
++ { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_PERI },
++ { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_H264 },
++ { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_ISP },
++ { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_USB },
++ { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
++ { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
++ };
++ int ret, i;
++ u32 id;
++
++ power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
++ if (!power)
++ return -ENOMEM;
++ platform_set_drvdata(pdev, power);
++
++ power->dev = dev;
++ power->base = pm->base;
++ power->asb = pm->asb;
++
++ id = ASB_READ(ASB_AXI_BRDG_ID);
++ if (id != 0x62726467 /* "BRDG" */) {
++ dev_err(dev, "ASB register ID returned 0x%08x\n", id);
++ return -ENODEV;
++ }
++
++ power->pd_xlate.domains = devm_kcalloc(dev,
++ ARRAY_SIZE(power_domain_names),
++ sizeof(*power->pd_xlate.domains),
++ GFP_KERNEL);
++ if (!power->pd_xlate.domains)
++ return -ENOMEM;
++
++ power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
++
++ for (i = 0; i < ARRAY_SIZE(power_domain_names); i++)
++ bcm2835_init_power_domain(power, i, power_domain_names[i]);
++
++ for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
++ pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
++ &power->domains[domain_deps[i].child].base);
++ }
++
++ power->reset.owner = THIS_MODULE;
++ power->reset.nr_resets = BCM2835_RESET_COUNT;
++ power->reset.ops = &bcm2835_reset_ops;
++ power->reset.of_node = dev->parent->of_node;
++
++ ret = devm_reset_controller_register(dev, &power->reset);
++ if (ret)
++ return ret;
++
++ of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
++
++ dev_info(dev, "Broadcom BCM2835 power domains driver");
++ return 0;
++}
++
++static int bcm2835_power_remove(struct platform_device *pdev)
++{
++ return 0;
++}
++
++static struct platform_driver bcm2835_power_driver = {
++ .probe = bcm2835_power_probe,
++ .remove = bcm2835_power_remove,
++ .driver = {
++ .name = "bcm2835-power",
++ },
++};
++module_platform_driver(bcm2835_power_driver);
++
++MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
++MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/include/dt-bindings/soc/bcm2835-pm.h
+@@ -0,0 +1,28 @@
++/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
++
++#ifndef _DT_BINDINGS_ARM_BCM2835_PM_H
++#define _DT_BINDINGS_ARM_BCM2835_PM_H
++
++#define BCM2835_POWER_DOMAIN_GRAFX 0
++#define BCM2835_POWER_DOMAIN_GRAFX_V3D 1
++#define BCM2835_POWER_DOMAIN_IMAGE 2
++#define BCM2835_POWER_DOMAIN_IMAGE_PERI 3
++#define BCM2835_POWER_DOMAIN_IMAGE_ISP 4
++#define BCM2835_POWER_DOMAIN_IMAGE_H264 5
++#define BCM2835_POWER_DOMAIN_USB 6
++#define BCM2835_POWER_DOMAIN_DSI0 7
++#define BCM2835_POWER_DOMAIN_DSI1 8
++#define BCM2835_POWER_DOMAIN_CAM0 9
++#define BCM2835_POWER_DOMAIN_CAM1 10
++#define BCM2835_POWER_DOMAIN_CCP2TX 11
++#define BCM2835_POWER_DOMAIN_HDMI 12
++
++#define BCM2835_POWER_DOMAIN_COUNT 13
++
++#define BCM2835_RESET_V3D 0
++#define BCM2835_RESET_ISP 1
++#define BCM2835_RESET_H264 2
++
++#define BCM2835_RESET_COUNT 3
++
++#endif /* _DT_BINDINGS_ARM_BCM2835_PM_H */
+--- a/include/linux/mfd/bcm2835-pm.h
++++ b/include/linux/mfd/bcm2835-pm.h
+@@ -8,6 +8,7 @@
+ struct bcm2835_pm {
+ struct device *dev;
+ void __iomem *base;
++ void __iomem *asb;
+ };
+
+ #endif /* BCM2835_MFD_PM_H */
+++ /dev/null
-From 6dc0f30ee18404547a2ca94fd11914ea0d75841f Mon Sep 17 00:00:00 2001
-From: Martin Sperl <kernel@martin.sperl.org>
-Date: Mon, 13 May 2019 11:05:27 +0000
-Subject: [PATCH 557/703] spi: bcm2835: enable shared interrupt support
-
-Add shared interrupt support for this driver.
-
-Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
----
- drivers/spi/spi-bcm2835.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
---- a/drivers/spi/spi-bcm2835.c
-+++ b/drivers/spi/spi-bcm2835.c
-@@ -150,6 +150,10 @@ static irqreturn_t bcm2835_spi_interrupt
- struct spi_master *master = dev_id;
- struct bcm2835_spi *bs = spi_master_get_devdata(master);
-
-+ /* check if we got interrupt enabled */
-+ if (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_INTR))
-+ return IRQ_NONE;
-+
- /* Read as many bytes as possible from FIFO */
- bcm2835_rd_fifo(bs);
- /* Write as many bytes as possible to FIFO */
-@@ -755,7 +759,8 @@ static int bcm2835_spi_probe(struct plat
- bcm2835_wr(bs, BCM2835_SPI_CS,
- BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
-
-- err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0,
-+ err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt,
-+ IRQF_SHARED,
- dev_name(&pdev->dev), master);
- if (err) {
- dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
+++ /dev/null
-From 0a0ebc37b25830162918aa31278b2f7857b8032b Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Thu, 9 May 2019 14:30:37 +0100
-Subject: [PATCH 558/703] drivers: char: add chardev for mmap'ing Argon control
- registers
-
-Based on the gpiomem driver, allow mapping of the decoder register
-spaces such that userspace can access control/status registers.
-This driver is intended for use with a custom ffmpeg backend accelerator
-prior to a v4l2 driver being written.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/char/broadcom/Kconfig | 8 +
- drivers/char/broadcom/Makefile | 1 +
- drivers/char/broadcom/argon-mem.c | 277 ++++++++++++++++++++++++++++++
- 3 files changed, 286 insertions(+)
- create mode 100644 drivers/char/broadcom/argon-mem.c
-
---- a/drivers/char/broadcom/Kconfig
-+++ b/drivers/char/broadcom/Kconfig
-@@ -49,3 +49,11 @@ config BCM2835_SMI_DEV
- This driver provides a character device interface (ioctl + read/write) to
- Broadcom's Secondary Memory interface. The low-level functionality is provided
- by the SMI driver itself.
-+
-+config ARGON_MEM
-+ tristate "Character device driver for the Argon decoder hardware"
-+ default n
-+ help
-+ This driver provides a character device interface for memory-map operations
-+ so userspace tools can access the control and status registers of the Argon
-+ video decoder hardware.
---- a/drivers/char/broadcom/Makefile
-+++ b/drivers/char/broadcom/Makefile
-@@ -4,3 +4,4 @@ obj-$(CONFIG_BCM_VC_SM) += vc_sm
-
- obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o
- obj-$(CONFIG_BCM2835_SMI_DEV) += bcm2835_smi_dev.o
-+obj-$(CONFIG_ARGON_MEM) += argon-mem.o
---- /dev/null
-+++ b/drivers/char/broadcom/argon-mem.c
-@@ -0,0 +1,277 @@
-+/**
-+ * argon-mem.c - character device access to the Argon decoder registers
-+ *
-+ * Based on bcm2835-gpiomem.c. Provides IO memory access to the decoder
-+ * register blocks such that ffmpeg plugins can access the hardware.
-+ *
-+ * Jonathan Bell <jonathan@raspberrypi.org>
-+ * Copyright (c) 2019, Raspberry Pi (Trading) Ltd.
-+ *
-+ * 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 <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_device.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/cdev.h>
-+#include <linux/pagemap.h>
-+#include <linux/io.h>
-+
-+#define DRIVER_NAME "argon-mem"
-+#define DEVICE_MINOR 0
-+
-+struct argon_mem_priv {
-+ dev_t devid;
-+ struct class *class;
-+ struct cdev argon_mem_cdev;
-+ unsigned long regs_phys;
-+ unsigned long mem_window_len;
-+ struct device *dev;
-+ const char *name;
-+};
-+
-+static int argon_mem_open(struct inode *inode, struct file *file)
-+{
-+ int dev = iminor(inode);
-+ int ret = 0;
-+ struct argon_mem_priv *priv;
-+ if (dev != DEVICE_MINOR)
-+ ret = -ENXIO;
-+
-+ priv = container_of(inode->i_cdev, struct argon_mem_priv,
-+ argon_mem_cdev);
-+ if (!priv)
-+ return -EINVAL;
-+ file->private_data = priv;
-+ return ret;
-+}
-+
-+static int argon_mem_release(struct inode *inode, struct file *file)
-+{
-+ int dev = iminor(inode);
-+ int ret = 0;
-+
-+ if (dev != DEVICE_MINOR)
-+ ret = -ENXIO;
-+
-+ return ret;
-+}
-+
-+static const struct vm_operations_struct argon_mem_vm_ops = {
-+#ifdef CONFIG_HAVE_IOREMAP_PROT
-+ .access = generic_access_phys
-+#endif
-+};
-+
-+static int argon_mem_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ struct argon_mem_priv *priv;
-+ unsigned long pages;
-+
-+ priv = file->private_data;
-+ pages = priv->regs_phys >> PAGE_SHIFT;
-+ /*
-+ * The address decode is far larger than the actual number of registers.
-+ * Just map the whole lot in.
-+ */
-+ vma->vm_page_prot = phys_mem_access_prot(file, pages,
-+ priv->mem_window_len,
-+ vma->vm_page_prot);
-+ vma->vm_ops = &argon_mem_vm_ops;
-+ if (remap_pfn_range(vma, vma->vm_start,
-+ pages,
-+ priv->mem_window_len,
-+ vma->vm_page_prot)) {
-+ return -EAGAIN;
-+ }
-+ return 0;
-+}
-+
-+static const struct file_operations
-+argon_mem_fops = {
-+ .owner = THIS_MODULE,
-+ .open = argon_mem_open,
-+ .release = argon_mem_release,
-+ .mmap = argon_mem_mmap,
-+};
-+
-+static const struct of_device_id argon_mem_of_match[];
-+static int argon_mem_probe(struct platform_device *pdev)
-+{
-+ int err;
-+ void *ptr_err;
-+ const struct of_device_id *id;
-+ struct device *dev = &pdev->dev;
-+ struct device *argon_mem_dev;
-+ struct resource *ioresource;
-+ struct argon_mem_priv *priv;
-+
-+
-+ /* Allocate buffers and instance data */
-+
-+ priv = kzalloc(sizeof(struct argon_mem_priv), GFP_KERNEL);
-+
-+ if (!priv) {
-+ err = -ENOMEM;
-+ goto failed_inst_alloc;
-+ }
-+ platform_set_drvdata(pdev, priv);
-+
-+ priv->dev = dev;
-+ id = of_match_device(argon_mem_of_match, dev);
-+ if (!id)
-+ return -EINVAL;
-+ priv->name = id->data;
-+
-+ ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (ioresource) {
-+ priv->regs_phys = ioresource->start;
-+ priv->mem_window_len = ioresource->end - ioresource->start;
-+ } else {
-+ dev_err(priv->dev, "failed to get IO resource");
-+ err = -ENOENT;
-+ goto failed_get_resource;
-+ }
-+
-+ /* Create character device entries */
-+
-+ err = alloc_chrdev_region(&priv->devid,
-+ DEVICE_MINOR, 1, priv->name);
-+ if (err != 0) {
-+ dev_err(priv->dev, "unable to allocate device number");
-+ goto failed_alloc_chrdev;
-+ }
-+ cdev_init(&priv->argon_mem_cdev, &argon_mem_fops);
-+ priv->argon_mem_cdev.owner = THIS_MODULE;
-+ err = cdev_add(&priv->argon_mem_cdev, priv->devid, 1);
-+ if (err != 0) {
-+ dev_err(priv->dev, "unable to register device");
-+ goto failed_cdev_add;
-+ }
-+
-+ /* Create sysfs entries */
-+
-+ priv->class = class_create(THIS_MODULE, priv->name);
-+ ptr_err = priv->class;
-+ if (IS_ERR(ptr_err))
-+ goto failed_class_create;
-+
-+ argon_mem_dev = device_create(priv->class, NULL,
-+ priv->devid, NULL,
-+ priv->name);
-+ ptr_err = argon_mem_dev;
-+ if (IS_ERR(ptr_err))
-+ goto failed_device_create;
-+
-+ dev_info(priv->dev, "%s initialised: Registers at 0x%08lx length 0x%08lx",
-+ priv->name, priv->regs_phys, priv->mem_window_len);
-+
-+ return 0;
-+
-+failed_device_create:
-+ class_destroy(priv->class);
-+failed_class_create:
-+ cdev_del(&priv->argon_mem_cdev);
-+ err = PTR_ERR(ptr_err);
-+failed_cdev_add:
-+ unregister_chrdev_region(priv->devid, 1);
-+failed_alloc_chrdev:
-+failed_get_resource:
-+ kfree(priv);
-+failed_inst_alloc:
-+ dev_err(priv->dev, "could not load argon_mem");
-+ return err;
-+}
-+
-+static int argon_mem_remove(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct argon_mem_priv *priv = platform_get_drvdata(pdev);
-+
-+ device_destroy(priv->class, priv->devid);
-+ class_destroy(priv->class);
-+ cdev_del(&priv->argon_mem_cdev);
-+ unregister_chrdev_region(priv->devid, 1);
-+ kfree(priv);
-+
-+ dev_info(dev, "%s driver removed - OK", priv->name);
-+ return 0;
-+}
-+
-+static const char argon_hevc_name[] = "argon-hevcmem";
-+static const char argon_h264_name[] = "argon-h264mem";
-+static const char argon_vp9_name[] = "argon-vp9mem";
-+static const char argon_intc_name[] = "argon-intcmem";
-+
-+static const struct of_device_id argon_mem_of_match[] = {
-+ {
-+ .compatible = "raspberrypi,argon-hevc-decoder",
-+ .data = &argon_hevc_name,
-+ },
-+ {
-+ .compatible = "raspberrypi,argon-h264-decoder",
-+ .data = &argon_h264_name,
-+ },
-+ {
-+ .compatible = "raspberrypi,argon-vp9-decoder",
-+ .data = &argon_vp9_name,
-+ },
-+ /* The "intc" is included as this block of hardware contains the
-+ * "frame done" status flags.
-+ */
-+ {
-+ .compatible = "raspberrypi,argon-local-intc",
-+ .data = &argon_intc_name,
-+ },
-+ { /* sentinel */ },
-+};
-+
-+MODULE_DEVICE_TABLE(of, argon_mem_of_match);
-+
-+static struct platform_driver argon_mem_driver = {
-+ .probe = argon_mem_probe,
-+ .remove = argon_mem_remove,
-+ .driver = {
-+ .name = DRIVER_NAME,
-+ .owner = THIS_MODULE,
-+ .of_match_table = argon_mem_of_match,
-+ },
-+};
-+
-+module_platform_driver(argon_mem_driver);
-+
-+MODULE_ALIAS("platform:argon-mem");
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Driver for accessing Argon decoder registers from userspace");
-+MODULE_AUTHOR("Jonathan Bell <jonathan@raspberrypi.org>");
--- /dev/null
+From 3cd53598cdb1749d6d5ed03e378276be22fc6e8d Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 11 Jan 2019 17:29:10 -0800
+Subject: [PATCH 558/725] soc: bcm: bcm2835-pm: Fix PM_IMAGE_PERI power domain
+ support.
+
+We don't have ASB master/slave regs for this domain, so just skip that
+step.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Fixes: 670c672608a1 ("soc: bcm: bcm2835-pm: Add support for power domains under a new binding.")
+---
+ drivers/soc/bcm/bcm2835-power.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/soc/bcm/bcm2835-power.c
++++ b/drivers/soc/bcm/bcm2835-power.c
+@@ -150,7 +150,12 @@ struct bcm2835_power {
+
+ static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
+ {
+- u64 start = ktime_get_ns();
++ u64 start;
++
++ if (!reg)
++ return 0;
++
++ start = ktime_get_ns();
+
+ /* Enable the module's async AXI bridges. */
+ ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP);
+@@ -165,7 +170,12 @@ static int bcm2835_asb_enable(struct bcm
+
+ static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
+ {
+- u64 start = ktime_get_ns();
++ u64 start;
++
++ if (!reg)
++ return 0;
++
++ start = ktime_get_ns();
+
+ /* Enable the module's async AXI bridges. */
+ ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP);
+++ /dev/null
-From 258c43d5303a3afe7c416b4fa9875bdbd3470131 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 23 Jan 2019 16:11:50 +0000
-Subject: [PATCH 559/703] clk-bcm2835: Don't wait for pllh lock
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/clk/bcm/clk-bcm2835.c | 18 ++++++++++--------
- 1 file changed, 10 insertions(+), 8 deletions(-)
-
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -627,15 +627,17 @@ static int bcm2835_pll_on(struct clk_hw
- spin_unlock(&cprman->regs_lock);
-
- /* Wait for the PLL to lock. */
-- timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
-- while (!(cprman_read(cprman, CM_LOCK) & data->lock_mask)) {
-- if (ktime_after(ktime_get(), timeout)) {
-- dev_err(cprman->dev, "%s: couldn't lock PLL\n",
-- clk_hw_get_name(hw));
-- return -ETIMEDOUT;
-- }
-+ if (strcmp(data->name, "pllh")) {
-+ timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
-+ while (!(cprman_read(cprman, CM_LOCK) & data->lock_mask)) {
-+ if (ktime_after(ktime_get(), timeout)) {
-+ dev_err(cprman->dev, "%s: couldn't lock PLL\n",
-+ clk_hw_get_name(hw));
-+ return -ETIMEDOUT;
-+ }
-
-- cpu_relax();
-+ cpu_relax();
-+ }
- }
-
- cprman_write(cprman, data->a2w_ctrl_reg,
--- /dev/null
+From b1b13630de7806f63b4e10cd90f91ad4bc3d1247 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Sat, 12 Jan 2019 08:07:43 -0800
+Subject: [PATCH 559/725] soc: bcm: bcm2835-pm: Fix error paths of
+ initialization.
+
+The clock driver may probe after ours and so we need to pass the
+-EPROBE_DEFER out. Fix the other error path while we're here.
+
+v2: Use dom->name instead of dom->gov as the flag for initialized
+ domains, since we aren't setting up a governor. Make sure to
+ clear ->clk when no clk is present in the DT.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Fixes: 670c672608a1 ("soc: bcm: bcm2835-pm: Add support for power domains under a new binding.")
+---
+ drivers/soc/bcm/bcm2835-power.c | 35 ++++++++++++++++++++++++++++-----
+ 1 file changed, 30 insertions(+), 5 deletions(-)
+
+--- a/drivers/soc/bcm/bcm2835-power.c
++++ b/drivers/soc/bcm/bcm2835-power.c
+@@ -485,7 +485,7 @@ static int bcm2835_power_pd_power_off(st
+ }
+ }
+
+-static void
++static int
+ bcm2835_init_power_domain(struct bcm2835_power *power,
+ int pd_xlate_index, const char *name)
+ {
+@@ -493,6 +493,17 @@ bcm2835_init_power_domain(struct bcm2835
+ struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
+
+ dom->clk = devm_clk_get(dev->parent, name);
++ if (IS_ERR(dom->clk)) {
++ int ret = PTR_ERR(dom->clk);
++
++ if (ret == -EPROBE_DEFER)
++ return ret;
++
++ /* Some domains don't have a clk, so make sure that we
++ * don't deref an error pointer later.
++ */
++ dom->clk = NULL;
++ }
+
+ dom->base.name = name;
+ dom->base.power_on = bcm2835_power_pd_power_on;
+@@ -505,6 +516,8 @@ bcm2835_init_power_domain(struct bcm2835
+ pm_genpd_init(&dom->base, NULL, true);
+
+ power->pd_xlate.domains[pd_xlate_index] = &dom->base;
++
++ return 0;
+ }
+
+ /** bcm2835_reset_reset - Resets a block that has a reset line in the
+@@ -602,7 +615,7 @@ static int bcm2835_power_probe(struct pl
+ { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
+ { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
+ };
+- int ret, i;
++ int ret = 0, i;
+ u32 id;
+
+ power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
+@@ -629,8 +642,11 @@ static int bcm2835_power_probe(struct pl
+
+ power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
+
+- for (i = 0; i < ARRAY_SIZE(power_domain_names); i++)
+- bcm2835_init_power_domain(power, i, power_domain_names[i]);
++ for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
++ ret = bcm2835_init_power_domain(power, i, power_domain_names[i]);
++ if (ret)
++ goto fail;
++ }
+
+ for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
+ pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
+@@ -644,12 +660,21 @@ static int bcm2835_power_probe(struct pl
+
+ ret = devm_reset_controller_register(dev, &power->reset);
+ if (ret)
+- return ret;
++ goto fail;
+
+ of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
+
+ dev_info(dev, "Broadcom BCM2835 power domains driver");
+ return 0;
++
++fail:
++ for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
++ struct generic_pm_domain *dom = &power->domains[i].base;
++
++ if (dom->name)
++ pm_genpd_remove(dom);
++ }
++ return ret;
+ }
+
+ static int bcm2835_power_remove(struct platform_device *pdev)
+++ /dev/null
-From 2dbc6987e9ef3130c9a72422f3f06b8edd06d88a Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 12 Dec 2018 15:51:47 -0800
-Subject: [PATCH 560/703] bcm2835-pm: Move bcm2835-watchdog's DT probe to an
- MFD.
-
-The PM block that the wdt driver was binding to actually has multiple
-features we want to expose (power domains, reset, watchdog). Move the
-DT attachment to a MFD driver and make WDT probe against MFD.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Guenter Roeck <linux@roeck-us.net>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-(cherry picked from commit 5e6acc3e678ed3db746ab4fb53a980861cd711b6)
----
- drivers/mfd/Makefile | 1 +
- drivers/mfd/bcm2835-pm.c | 64 ++++++++++++++++++++++++++++++++++
- drivers/watchdog/bcm2835_wdt.c | 26 +++++---------
- include/linux/mfd/bcm2835-pm.h | 13 +++++++
- 4 files changed, 87 insertions(+), 17 deletions(-)
- create mode 100644 drivers/mfd/bcm2835-pm.c
- create mode 100644 include/linux/mfd/bcm2835-pm.h
-
---- a/drivers/mfd/Makefile
-+++ b/drivers/mfd/Makefile
-@@ -10,6 +10,7 @@ obj-$(CONFIG_MFD_88PM805) += 88pm805.o 8
- obj-$(CONFIG_MFD_ACT8945A) += act8945a.o
- obj-$(CONFIG_MFD_SM501) += sm501.o
- obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
-+obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o
- obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
- obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
- cros_ec_core-objs := cros_ec.o
---- /dev/null
-+++ b/drivers/mfd/bcm2835-pm.c
-@@ -0,0 +1,64 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * PM MFD driver for Broadcom BCM2835
-+ *
-+ * This driver binds to the PM block and creates the MFD device for
-+ * the WDT driver.
-+ */
-+
-+#include <linux/delay.h>
-+#include <linux/io.h>
-+#include <linux/mfd/bcm2835-pm.h>
-+#include <linux/mfd/core.h>
-+#include <linux/module.h>
-+#include <linux/of_address.h>
-+#include <linux/of_platform.h>
-+#include <linux/platform_device.h>
-+#include <linux/types.h>
-+#include <linux/watchdog.h>
-+
-+static const struct mfd_cell bcm2835_pm_devs[] = {
-+ { .name = "bcm2835-wdt" },
-+};
-+
-+static int bcm2835_pm_probe(struct platform_device *pdev)
-+{
-+ struct resource *res;
-+ struct device *dev = &pdev->dev;
-+ struct bcm2835_pm *pm;
-+
-+ pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL);
-+ if (!pm)
-+ return -ENOMEM;
-+ platform_set_drvdata(pdev, pm);
-+
-+ pm->dev = dev;
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ pm->base = devm_ioremap_resource(dev, res);
-+ if (IS_ERR(pm->base))
-+ return PTR_ERR(pm->base);
-+
-+ return devm_mfd_add_devices(dev, -1,
-+ bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
-+ NULL, 0, NULL);
-+}
-+
-+static const struct of_device_id bcm2835_pm_of_match[] = {
-+ { .compatible = "brcm,bcm2835-pm-wdt", },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
-+
-+static struct platform_driver bcm2835_pm_driver = {
-+ .probe = bcm2835_pm_probe,
-+ .driver = {
-+ .name = "bcm2835-pm",
-+ .of_match_table = bcm2835_pm_of_match,
-+ },
-+};
-+module_platform_driver(bcm2835_pm_driver);
-+
-+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
-+MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM MFD");
-+MODULE_LICENSE("GPL");
---- a/drivers/watchdog/bcm2835_wdt.c
-+++ b/drivers/watchdog/bcm2835_wdt.c
-@@ -12,6 +12,7 @@
-
- #include <linux/delay.h>
- #include <linux/types.h>
-+#include <linux/mfd/bcm2835-pm.h>
- #include <linux/module.h>
- #include <linux/io.h>
- #include <linux/watchdog.h>
-@@ -41,6 +42,8 @@ struct bcm2835_wdt {
- spinlock_t lock;
- };
-
-+static struct bcm2835_wdt *bcm2835_power_off_wdt;
-+
- static unsigned int heartbeat;
- static bool nowayout = WATCHDOG_NOWAYOUT;
-
-@@ -163,10 +166,7 @@ static struct watchdog_device bcm2835_wd
- */
- static void bcm2835_power_off(void)
- {
-- struct device_node *np =
-- 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);
-+ struct bcm2835_wdt *wdt = bcm2835_power_off_wdt;
-
- /* Partition 63 tells the firmware that this is a halt */
- __bcm2835_restart(wdt, 63);
-@@ -174,7 +174,7 @@ static void bcm2835_power_off(void)
-
- static int bcm2835_wdt_probe(struct platform_device *pdev)
- {
-- struct resource *res;
-+ struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
- struct device *dev = &pdev->dev;
- struct bcm2835_wdt *wdt;
- int err;
-@@ -186,10 +186,7 @@ static int bcm2835_wdt_probe(struct plat
-
- spin_lock_init(&wdt->lock);
-
-- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- wdt->base = devm_ioremap_resource(dev, res);
-- if (IS_ERR(wdt->base))
-- return PTR_ERR(wdt->base);
-+ wdt->base = pm->base;
-
- watchdog_set_drvdata(&bcm2835_wdt_wdd, wdt);
- watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev);
-@@ -216,8 +213,10 @@ static int bcm2835_wdt_probe(struct plat
- return err;
- }
-
-- if (pm_power_off == NULL)
-+ if (pm_power_off == NULL) {
- pm_power_off = bcm2835_power_off;
-+ bcm2835_power_off_wdt = wdt;
-+ }
-
- dev_info(dev, "Broadcom BCM2835 watchdog timer");
- return 0;
-@@ -231,18 +230,11 @@ static int bcm2835_wdt_remove(struct pla
- return 0;
- }
-
--static const struct of_device_id bcm2835_wdt_of_match[] = {
-- { .compatible = "brcm,bcm2835-pm-wdt", },
-- {},
--};
--MODULE_DEVICE_TABLE(of, bcm2835_wdt_of_match);
--
- static struct platform_driver bcm2835_wdt_driver = {
- .probe = bcm2835_wdt_probe,
- .remove = bcm2835_wdt_remove,
- .driver = {
- .name = "bcm2835-wdt",
-- .of_match_table = bcm2835_wdt_of_match,
- },
- };
- module_platform_driver(bcm2835_wdt_driver);
---- /dev/null
-+++ b/include/linux/mfd/bcm2835-pm.h
-@@ -0,0 +1,13 @@
-+/* SPDX-License-Identifier: GPL-2.0+ */
-+
-+#ifndef BCM2835_MFD_PM_H
-+#define BCM2835_MFD_PM_H
-+
-+#include <linux/regmap.h>
-+
-+struct bcm2835_pm {
-+ struct device *dev;
-+ void __iomem *base;
-+};
-+
-+#endif /* BCM2835_MFD_PM_H */
--- /dev/null
+From d3c6eea95890c539b24ae16bd508f3b631985516 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 11 Jan 2019 17:31:07 -0800
+Subject: [PATCH 560/725] soc: bcm: bcm2835-pm: Add support for 2711.
+
+Without the actual power management part any more, there's a lot less
+to set up for V3D. We just need to clear the RSTN field for the power
+domain, and expose the reset controller for toggling it again.
+
+This is definitely incomplete -- the old ISP and H264 is in the old
+bridge, but since we have no consumers of it I've just done the
+minimum to get V3D working.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/mfd/bcm2835-pm.c | 11 +++++++++++
+ drivers/soc/bcm/bcm2835-power.c | 22 ++++++++++++++++++++++
+ include/linux/mfd/bcm2835-pm.h | 1 +
+ 3 files changed, 34 insertions(+)
+
+--- a/drivers/mfd/bcm2835-pm.c
++++ b/drivers/mfd/bcm2835-pm.c
+@@ -50,6 +50,17 @@ static int bcm2835_pm_probe(struct platf
+ if (ret)
+ return ret;
+
++ /* Map the ARGON ASB regs if present. */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
++ if (res) {
++ pm->arg_asb = devm_ioremap_resource(dev, res);
++ if (IS_ERR(pm->arg_asb)) {
++ dev_err(dev, "Failed to map ARGON ASB: %ld\n",
++ PTR_ERR(pm->arg_asb));
++ return PTR_ERR(pm->arg_asb);
++ }
++ }
++
+ /* We'll use the presence of the AXI ASB regs in the
+ * bcm2835-pm binding as the key for whether we can reference
+ * the full PM register range and support power domains.
+--- a/drivers/soc/bcm/bcm2835-power.c
++++ b/drivers/soc/bcm/bcm2835-power.c
+@@ -143,6 +143,8 @@ struct bcm2835_power {
+ /* AXI Async bridge registers. */
+ void __iomem *asb;
+
++ bool is_2711;
++
+ struct genpd_onecell_data pd_xlate;
+ struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
+ struct reset_controller_dev reset;
+@@ -192,6 +194,10 @@ static int bcm2835_power_power_off(struc
+ {
+ struct bcm2835_power *power = pd->power;
+
++ /* 2711 has no power domains above the reset controller. */
++ if (power->is_2711)
++ return 0;
++
+ /* Enable functional isolation */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
+
+@@ -213,6 +219,10 @@ static int bcm2835_power_power_on(struct
+ int inrush;
+ bool powok;
+
++ /* 2711 has no power domains above the reset controller. */
++ if (power->is_2711)
++ return 0;
++
+ /* If it was already powered on by the fw, leave it that way. */
+ if (PM_READ(pm_reg) & PM_POWUP)
+ return 0;
+@@ -627,6 +637,18 @@ static int bcm2835_power_probe(struct pl
+ power->base = pm->base;
+ power->asb = pm->asb;
+
++ /* 2711 hack: the new ARGON ASB took over V3D, which is our
++ * only consumer of this driver so far. The old ASB seems to
++ * still be present with ISP and H264 bits but no V3D, but I
++ * don't know if that's real or not. The V3D is in the same
++ * place in the new ASB as the old one, so just poke the new
++ * one for now.
++ */
++ if (pm->arg_asb) {
++ power->asb = pm->arg_asb;
++ power->is_2711 = true;
++ }
++
+ id = ASB_READ(ASB_AXI_BRDG_ID);
+ if (id != 0x62726467 /* "BRDG" */) {
+ dev_err(dev, "ASB register ID returned 0x%08x\n", id);
+--- a/include/linux/mfd/bcm2835-pm.h
++++ b/include/linux/mfd/bcm2835-pm.h
+@@ -9,6 +9,7 @@ struct bcm2835_pm {
+ struct device *dev;
+ void __iomem *base;
+ void __iomem *asb;
++ void __iomem *arg_asb;
+ };
+
+ #endif /* BCM2835_MFD_PM_H */
--- /dev/null
+From f4645265e2dffcbc729a510aed85637b5519d8af Mon Sep 17 00:00:00 2001
+From: Chunming Zhou <david1.zhou@amd.com>
+Date: Thu, 30 Aug 2018 14:48:29 +0800
+Subject: [PATCH 561/725] drm: expand drm_syncobj_find_fence to support
+ timeline point v2
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+we can fetch timeline point fence after expanded.
+v2: The parameter fence is the result of the function and should come last.
+
+Signed-off-by: Chunming Zhou <david1.zhou@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Link: https://patchwork.freedesktop.org/patch/246541/
+(cherry picked from commit 0a6730ea27b68c7ac4171c29a816c29d26a9637a)
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +-
+ drivers/gpu/drm/drm_syncobj.c | 5 +++--
+ drivers/gpu/drm/v3d/v3d_gem.c | 4 ++--
+ drivers/gpu/drm/vc4/vc4_gem.c | 2 +-
+ include/drm/drm_syncobj.h | 2 +-
+ 5 files changed, 8 insertions(+), 7 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+@@ -1105,7 +1105,7 @@ static int amdgpu_syncobj_lookup_and_add
+ {
+ int r;
+ struct dma_fence *fence;
+- r = drm_syncobj_find_fence(p->filp, handle, &fence);
++ r = drm_syncobj_find_fence(p->filp, handle, 0, &fence);
+ if (r)
+ return r;
+
+--- a/drivers/gpu/drm/drm_syncobj.c
++++ b/drivers/gpu/drm/drm_syncobj.c
+@@ -235,6 +235,7 @@ static int drm_syncobj_assign_null_handl
+ * drm_syncobj_find_fence - lookup and reference the fence in a sync object
+ * @file_private: drm file private pointer
+ * @handle: sync object handle to lookup.
++ * @point: timeline point
+ * @fence: out parameter for the fence
+ *
+ * This is just a convenience function that combines drm_syncobj_find() and
+@@ -245,7 +246,7 @@ static int drm_syncobj_assign_null_handl
+ * dma_fence_put().
+ */
+ int drm_syncobj_find_fence(struct drm_file *file_private,
+- u32 handle,
++ u32 handle, u64 point,
+ struct dma_fence **fence)
+ {
+ struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle);
+@@ -516,7 +517,7 @@ static int drm_syncobj_export_sync_file(
+ if (fd < 0)
+ return fd;
+
+- ret = drm_syncobj_find_fence(file_private, handle, &fence);
++ ret = drm_syncobj_find_fence(file_private, handle, 0, &fence);
+ if (ret)
+ goto err_put_fd;
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -521,12 +521,12 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ kref_init(&exec->refcount);
+
+ ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,
+- &exec->bin.in_fence);
++ 0, &exec->bin.in_fence);
+ if (ret == -EINVAL)
+ goto fail;
+
+ ret = drm_syncobj_find_fence(file_priv, args->in_sync_rcl,
+- &exec->render.in_fence);
++ 0, &exec->render.in_fence);
+ if (ret == -EINVAL)
+ goto fail;
+
+--- a/drivers/gpu/drm/vc4/vc4_gem.c
++++ b/drivers/gpu/drm/vc4/vc4_gem.c
+@@ -1173,7 +1173,7 @@ vc4_submit_cl_ioctl(struct drm_device *d
+
+ if (args->in_sync) {
+ ret = drm_syncobj_find_fence(file_priv, args->in_sync,
+- &in_fence);
++ 0, &in_fence);
+ if (ret)
+ goto fail;
+
+--- a/include/drm/drm_syncobj.h
++++ b/include/drm/drm_syncobj.h
+@@ -139,7 +139,7 @@ void drm_syncobj_remove_callback(struct
+ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
+ struct dma_fence *fence);
+ int drm_syncobj_find_fence(struct drm_file *file_private,
+- u32 handle,
++ u32 handle, u64 point,
+ struct dma_fence **fence);
+ void drm_syncobj_free(struct kref *kref);
+ int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags,
+++ /dev/null
-From c3005e0dbe1f7f6d93833d5a43b12866873a312f Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 12 Dec 2018 15:51:48 -0800
-Subject: [PATCH 561/703] soc: bcm: bcm2835-pm: Add support for power domains
- under a new binding.
-
-This provides a free software alternative to raspberrypi-power.c's
-firmware calls to manage power domains. It also exposes a reset line,
-where previously the vc4 driver had to try to force power off the
-domain in order to trigger a reset.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Acked-by: Rob Herring <robh@kernel.org>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-(cherry picked from commit 670c672608a1ffcbc7ac0f872734843593bb8b15)
----
- drivers/mfd/bcm2835-pm.c | 36 +-
- drivers/soc/bcm/Kconfig | 11 +
- drivers/soc/bcm/Makefile | 1 +
- drivers/soc/bcm/bcm2835-power.c | 661 +++++++++++++++++++++++++++
- include/dt-bindings/soc/bcm2835-pm.h | 28 ++
- include/linux/mfd/bcm2835-pm.h | 1 +
- 6 files changed, 734 insertions(+), 4 deletions(-)
- create mode 100644 drivers/soc/bcm/bcm2835-power.c
- create mode 100644 include/dt-bindings/soc/bcm2835-pm.h
-
---- a/drivers/mfd/bcm2835-pm.c
-+++ b/drivers/mfd/bcm2835-pm.c
-@@ -3,7 +3,7 @@
- * PM MFD driver for Broadcom BCM2835
- *
- * This driver binds to the PM block and creates the MFD device for
-- * the WDT driver.
-+ * the WDT and power drivers.
- */
-
- #include <linux/delay.h>
-@@ -21,11 +21,16 @@ static const struct mfd_cell bcm2835_pm_
- { .name = "bcm2835-wdt" },
- };
-
-+static const struct mfd_cell bcm2835_power_devs[] = {
-+ { .name = "bcm2835-power" },
-+};
-+
- static int bcm2835_pm_probe(struct platform_device *pdev)
- {
- struct resource *res;
- struct device *dev = &pdev->dev;
- struct bcm2835_pm *pm;
-+ int ret;
-
- pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL);
- if (!pm)
-@@ -39,13 +44,36 @@ static int bcm2835_pm_probe(struct platf
- if (IS_ERR(pm->base))
- return PTR_ERR(pm->base);
-
-- return devm_mfd_add_devices(dev, -1,
-- bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
-- NULL, 0, NULL);
-+ ret = devm_mfd_add_devices(dev, -1,
-+ bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
-+ NULL, 0, NULL);
-+ if (ret)
-+ return ret;
-+
-+ /* We'll use the presence of the AXI ASB regs in the
-+ * bcm2835-pm binding as the key for whether we can reference
-+ * the full PM register range and support power domains.
-+ */
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+ if (res) {
-+ pm->asb = devm_ioremap_resource(dev, res);
-+ if (IS_ERR(pm->asb))
-+ return PTR_ERR(pm->asb);
-+
-+ ret = devm_mfd_add_devices(dev, -1,
-+ bcm2835_power_devs,
-+ ARRAY_SIZE(bcm2835_power_devs),
-+ NULL, 0, NULL);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ return 0;
- }
-
- static const struct of_device_id bcm2835_pm_of_match[] = {
- { .compatible = "brcm,bcm2835-pm-wdt", },
-+ { .compatible = "brcm,bcm2835-pm", },
- {},
- };
- MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
---- a/drivers/soc/bcm/Kconfig
-+++ b/drivers/soc/bcm/Kconfig
-@@ -1,5 +1,16 @@
- menu "Broadcom SoC drivers"
-
-+config BCM2835_POWER
-+ bool "BCM2835 power domain driver"
-+ depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
-+ select PM_GENERIC_DOMAINS if PM
-+ select RESET_CONTROLLER
-+ help
-+ This enables support for the BCM2835 power domains and reset
-+ controller. Any usage of power domains by the Raspberry Pi
-+ firmware means that Linux usage of the same power domain
-+ must be accessed using the RASPBERRYPI_POWER driver
-+
- config RASPBERRYPI_POWER
- bool "Raspberry Pi power domain driver"
- depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
---- a/drivers/soc/bcm/Makefile
-+++ b/drivers/soc/bcm/Makefile
-@@ -1,2 +1,3 @@
-+obj-$(CONFIG_BCM2835_POWER) += bcm2835-power.o
- obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o
- obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
---- /dev/null
-+++ b/drivers/soc/bcm/bcm2835-power.c
-@@ -0,0 +1,661 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * Power domain driver for Broadcom BCM2835
-+ *
-+ * Copyright (C) 2018 Broadcom
-+ */
-+
-+#include <dt-bindings/soc/bcm2835-pm.h>
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/io.h>
-+#include <linux/mfd/bcm2835-pm.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm_domain.h>
-+#include <linux/reset-controller.h>
-+#include <linux/types.h>
-+
-+#define PM_GNRIC 0x00
-+#define PM_AUDIO 0x04
-+#define PM_STATUS 0x18
-+#define PM_RSTC 0x1c
-+#define PM_RSTS 0x20
-+#define PM_WDOG 0x24
-+#define PM_PADS0 0x28
-+#define PM_PADS2 0x2c
-+#define PM_PADS3 0x30
-+#define PM_PADS4 0x34
-+#define PM_PADS5 0x38
-+#define PM_PADS6 0x3c
-+#define PM_CAM0 0x44
-+#define PM_CAM0_LDOHPEN BIT(2)
-+#define PM_CAM0_LDOLPEN BIT(1)
-+#define PM_CAM0_CTRLEN BIT(0)
-+
-+#define PM_CAM1 0x48
-+#define PM_CAM1_LDOHPEN BIT(2)
-+#define PM_CAM1_LDOLPEN BIT(1)
-+#define PM_CAM1_CTRLEN BIT(0)
-+
-+#define PM_CCP2TX 0x4c
-+#define PM_CCP2TX_LDOEN BIT(1)
-+#define PM_CCP2TX_CTRLEN BIT(0)
-+
-+#define PM_DSI0 0x50
-+#define PM_DSI0_LDOHPEN BIT(2)
-+#define PM_DSI0_LDOLPEN BIT(1)
-+#define PM_DSI0_CTRLEN BIT(0)
-+
-+#define PM_DSI1 0x54
-+#define PM_DSI1_LDOHPEN BIT(2)
-+#define PM_DSI1_LDOLPEN BIT(1)
-+#define PM_DSI1_CTRLEN BIT(0)
-+
-+#define PM_HDMI 0x58
-+#define PM_HDMI_RSTDR BIT(19)
-+#define PM_HDMI_LDOPD BIT(1)
-+#define PM_HDMI_CTRLEN BIT(0)
-+
-+#define PM_USB 0x5c
-+/* The power gates must be enabled with this bit before enabling the LDO in the
-+ * USB block.
-+ */
-+#define PM_USB_CTRLEN BIT(0)
-+
-+#define PM_PXLDO 0x60
-+#define PM_PXBG 0x64
-+#define PM_DFT 0x68
-+#define PM_SMPS 0x6c
-+#define PM_XOSC 0x70
-+#define PM_SPAREW 0x74
-+#define PM_SPARER 0x78
-+#define PM_AVS_RSTDR 0x7c
-+#define PM_AVS_STAT 0x80
-+#define PM_AVS_EVENT 0x84
-+#define PM_AVS_INTEN 0x88
-+#define PM_DUMMY 0xfc
-+
-+#define PM_IMAGE 0x108
-+#define PM_GRAFX 0x10c
-+#define PM_PROC 0x110
-+#define PM_ENAB BIT(12)
-+#define PM_ISPRSTN BIT(8)
-+#define PM_H264RSTN BIT(7)
-+#define PM_PERIRSTN BIT(6)
-+#define PM_V3DRSTN BIT(6)
-+#define PM_ISFUNC BIT(5)
-+#define PM_MRDONE BIT(4)
-+#define PM_MEMREP BIT(3)
-+#define PM_ISPOW BIT(2)
-+#define PM_POWOK BIT(1)
-+#define PM_POWUP BIT(0)
-+#define PM_INRUSH_SHIFT 13
-+#define PM_INRUSH_3_5_MA 0
-+#define PM_INRUSH_5_MA 1
-+#define PM_INRUSH_10_MA 2
-+#define PM_INRUSH_20_MA 3
-+#define PM_INRUSH_MASK (3 << PM_INRUSH_SHIFT)
-+
-+#define PM_PASSWORD 0x5a000000
-+
-+#define PM_WDOG_TIME_SET 0x000fffff
-+#define PM_RSTC_WRCFG_CLR 0xffffffcf
-+#define PM_RSTS_HADWRH_SET 0x00000040
-+#define PM_RSTC_WRCFG_SET 0x00000030
-+#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
-+#define PM_RSTC_RESET 0x00000102
-+
-+#define PM_READ(reg) readl(power->base + (reg))
-+#define PM_WRITE(reg, val) writel(PM_PASSWORD | (val), power->base + (reg))
-+
-+#define ASB_BRDG_VERSION 0x00
-+#define ASB_CPR_CTRL 0x04
-+
-+#define ASB_V3D_S_CTRL 0x08
-+#define ASB_V3D_M_CTRL 0x0c
-+#define ASB_ISP_S_CTRL 0x10
-+#define ASB_ISP_M_CTRL 0x14
-+#define ASB_H264_S_CTRL 0x18
-+#define ASB_H264_M_CTRL 0x1c
-+
-+#define ASB_REQ_STOP BIT(0)
-+#define ASB_ACK BIT(1)
-+#define ASB_EMPTY BIT(2)
-+#define ASB_FULL BIT(3)
-+
-+#define ASB_AXI_BRDG_ID 0x20
-+
-+#define ASB_READ(reg) readl(power->asb + (reg))
-+#define ASB_WRITE(reg, val) writel(PM_PASSWORD | (val), power->asb + (reg))
-+
-+struct bcm2835_power_domain {
-+ struct generic_pm_domain base;
-+ struct bcm2835_power *power;
-+ u32 domain;
-+ struct clk *clk;
-+};
-+
-+struct bcm2835_power {
-+ struct device *dev;
-+ /* PM registers. */
-+ void __iomem *base;
-+ /* AXI Async bridge registers. */
-+ void __iomem *asb;
-+
-+ struct genpd_onecell_data pd_xlate;
-+ struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
-+ struct reset_controller_dev reset;
-+};
-+
-+static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
-+{
-+ u64 start = ktime_get_ns();
-+
-+ /* Enable the module's async AXI bridges. */
-+ ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP);
-+ while (ASB_READ(reg) & ASB_ACK) {
-+ cpu_relax();
-+ if (ktime_get_ns() - start >= 1000)
-+ return -ETIMEDOUT;
-+ }
-+
-+ return 0;
-+}
-+
-+static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
-+{
-+ u64 start = ktime_get_ns();
-+
-+ /* Enable the module's async AXI bridges. */
-+ ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP);
-+ while (!(ASB_READ(reg) & ASB_ACK)) {
-+ cpu_relax();
-+ if (ktime_get_ns() - start >= 1000)
-+ return -ETIMEDOUT;
-+ }
-+
-+ return 0;
-+}
-+
-+static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg)
-+{
-+ struct bcm2835_power *power = pd->power;
-+
-+ /* Enable functional isolation */
-+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
-+
-+ /* Enable electrical isolation */
-+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
-+
-+ /* Open the power switches. */
-+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP);
-+
-+ return 0;
-+}
-+
-+static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg)
-+{
-+ struct bcm2835_power *power = pd->power;
-+ struct device *dev = power->dev;
-+ u64 start;
-+ int ret;
-+ int inrush;
-+ bool powok;
-+
-+ /* If it was already powered on by the fw, leave it that way. */
-+ if (PM_READ(pm_reg) & PM_POWUP)
-+ return 0;
-+
-+ /* Enable power. Allowing too much current at once may result
-+ * in POWOK never getting set, so start low and ramp it up as
-+ * necessary to succeed.
-+ */
-+ powok = false;
-+ for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; inrush++) {
-+ PM_WRITE(pm_reg,
-+ (PM_READ(pm_reg) & ~PM_INRUSH_MASK) |
-+ (inrush << PM_INRUSH_SHIFT) |
-+ PM_POWUP);
-+
-+ start = ktime_get_ns();
-+ while (!(powok = !!(PM_READ(pm_reg) & PM_POWOK))) {
-+ cpu_relax();
-+ if (ktime_get_ns() - start >= 3000)
-+ break;
-+ }
-+ }
-+ if (!powok) {
-+ dev_err(dev, "Timeout waiting for %s power OK\n",
-+ pd->base.name);
-+ ret = -ETIMEDOUT;
-+ goto err_disable_powup;
-+ }
-+
-+ /* Disable electrical isolation */
-+ PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW);
-+
-+ /* Repair memory */
-+ PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP);
-+ start = ktime_get_ns();
-+ while (!(PM_READ(pm_reg) & PM_MRDONE)) {
-+ cpu_relax();
-+ if (ktime_get_ns() - start >= 1000) {
-+ dev_err(dev, "Timeout waiting for %s memory repair\n",
-+ pd->base.name);
-+ ret = -ETIMEDOUT;
-+ goto err_disable_ispow;
-+ }
-+ }
-+
-+ /* Disable functional isolation */
-+ PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC);
-+
-+ return 0;
-+
-+err_disable_ispow:
-+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
-+err_disable_powup:
-+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK));
-+ return ret;
-+}
-+
-+static int bcm2835_asb_power_on(struct bcm2835_power_domain *pd,
-+ u32 pm_reg,
-+ u32 asb_m_reg,
-+ u32 asb_s_reg,
-+ u32 reset_flags)
-+{
-+ struct bcm2835_power *power = pd->power;
-+ int ret;
-+
-+ ret = clk_prepare_enable(pd->clk);
-+ if (ret) {
-+ dev_err(power->dev, "Failed to enable clock for %s\n",
-+ pd->base.name);
-+ return ret;
-+ }
-+
-+ /* Wait 32 clocks for reset to propagate, 1 us will be enough */
-+ udelay(1);
-+
-+ clk_disable_unprepare(pd->clk);
-+
-+ /* Deassert the resets. */
-+ PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags);
-+
-+ ret = clk_prepare_enable(pd->clk);
-+ if (ret) {
-+ dev_err(power->dev, "Failed to enable clock for %s\n",
-+ pd->base.name);
-+ goto err_enable_resets;
-+ }
-+
-+ ret = bcm2835_asb_enable(power, asb_m_reg);
-+ if (ret) {
-+ dev_err(power->dev, "Failed to enable ASB master for %s\n",
-+ pd->base.name);
-+ goto err_disable_clk;
-+ }
-+ ret = bcm2835_asb_enable(power, asb_s_reg);
-+ if (ret) {
-+ dev_err(power->dev, "Failed to enable ASB slave for %s\n",
-+ pd->base.name);
-+ goto err_disable_asb_master;
-+ }
-+
-+ return 0;
-+
-+err_disable_asb_master:
-+ bcm2835_asb_disable(power, asb_m_reg);
-+err_disable_clk:
-+ clk_disable_unprepare(pd->clk);
-+err_enable_resets:
-+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
-+ return ret;
-+}
-+
-+static int bcm2835_asb_power_off(struct bcm2835_power_domain *pd,
-+ u32 pm_reg,
-+ u32 asb_m_reg,
-+ u32 asb_s_reg,
-+ u32 reset_flags)
-+{
-+ struct bcm2835_power *power = pd->power;
-+ int ret;
-+
-+ ret = bcm2835_asb_disable(power, asb_s_reg);
-+ if (ret) {
-+ dev_warn(power->dev, "Failed to disable ASB slave for %s\n",
-+ pd->base.name);
-+ return ret;
-+ }
-+ ret = bcm2835_asb_disable(power, asb_m_reg);
-+ if (ret) {
-+ dev_warn(power->dev, "Failed to disable ASB master for %s\n",
-+ pd->base.name);
-+ bcm2835_asb_enable(power, asb_s_reg);
-+ return ret;
-+ }
-+
-+ clk_disable_unprepare(pd->clk);
-+
-+ /* Assert the resets. */
-+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
-+
-+ return 0;
-+}
-+
-+static int bcm2835_power_pd_power_on(struct generic_pm_domain *domain)
-+{
-+ struct bcm2835_power_domain *pd =
-+ container_of(domain, struct bcm2835_power_domain, base);
-+ struct bcm2835_power *power = pd->power;
-+
-+ switch (pd->domain) {
-+ case BCM2835_POWER_DOMAIN_GRAFX:
-+ return bcm2835_power_power_on(pd, PM_GRAFX);
-+
-+ case BCM2835_POWER_DOMAIN_GRAFX_V3D:
-+ return bcm2835_asb_power_on(pd, PM_GRAFX,
-+ ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
-+ PM_V3DRSTN);
-+
-+ case BCM2835_POWER_DOMAIN_IMAGE:
-+ return bcm2835_power_power_on(pd, PM_IMAGE);
-+
-+ case BCM2835_POWER_DOMAIN_IMAGE_PERI:
-+ return bcm2835_asb_power_on(pd, PM_IMAGE,
-+ 0, 0,
-+ PM_PERIRSTN);
-+
-+ case BCM2835_POWER_DOMAIN_IMAGE_ISP:
-+ return bcm2835_asb_power_on(pd, PM_IMAGE,
-+ ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
-+ PM_ISPRSTN);
-+
-+ case BCM2835_POWER_DOMAIN_IMAGE_H264:
-+ return bcm2835_asb_power_on(pd, PM_IMAGE,
-+ ASB_H264_M_CTRL, ASB_H264_S_CTRL,
-+ PM_H264RSTN);
-+
-+ case BCM2835_POWER_DOMAIN_USB:
-+ PM_WRITE(PM_USB, PM_USB_CTRLEN);
-+ return 0;
-+
-+ case BCM2835_POWER_DOMAIN_DSI0:
-+ PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
-+ PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN);
-+ return 0;
-+
-+ case BCM2835_POWER_DOMAIN_DSI1:
-+ PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
-+ PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN);
-+ return 0;
-+
-+ case BCM2835_POWER_DOMAIN_CCP2TX:
-+ PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
-+ PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN);
-+ return 0;
-+
-+ case BCM2835_POWER_DOMAIN_HDMI:
-+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR);
-+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN);
-+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD);
-+ usleep_range(100, 200);
-+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR);
-+ return 0;
-+
-+ default:
-+ dev_err(power->dev, "Invalid domain %d\n", pd->domain);
-+ return -EINVAL;
-+ }
-+}
-+
-+static int bcm2835_power_pd_power_off(struct generic_pm_domain *domain)
-+{
-+ struct bcm2835_power_domain *pd =
-+ container_of(domain, struct bcm2835_power_domain, base);
-+ struct bcm2835_power *power = pd->power;
-+
-+ switch (pd->domain) {
-+ case BCM2835_POWER_DOMAIN_GRAFX:
-+ return bcm2835_power_power_off(pd, PM_GRAFX);
-+
-+ case BCM2835_POWER_DOMAIN_GRAFX_V3D:
-+ return bcm2835_asb_power_off(pd, PM_GRAFX,
-+ ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
-+ PM_V3DRSTN);
-+
-+ case BCM2835_POWER_DOMAIN_IMAGE:
-+ return bcm2835_power_power_off(pd, PM_IMAGE);
-+
-+ case BCM2835_POWER_DOMAIN_IMAGE_PERI:
-+ return bcm2835_asb_power_off(pd, PM_IMAGE,
-+ 0, 0,
-+ PM_PERIRSTN);
-+
-+ case BCM2835_POWER_DOMAIN_IMAGE_ISP:
-+ return bcm2835_asb_power_off(pd, PM_IMAGE,
-+ ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
-+ PM_ISPRSTN);
-+
-+ case BCM2835_POWER_DOMAIN_IMAGE_H264:
-+ return bcm2835_asb_power_off(pd, PM_IMAGE,
-+ ASB_H264_M_CTRL, ASB_H264_S_CTRL,
-+ PM_H264RSTN);
-+
-+ case BCM2835_POWER_DOMAIN_USB:
-+ PM_WRITE(PM_USB, 0);
-+ return 0;
-+
-+ case BCM2835_POWER_DOMAIN_DSI0:
-+ PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
-+ PM_WRITE(PM_DSI0, 0);
-+ return 0;
-+
-+ case BCM2835_POWER_DOMAIN_DSI1:
-+ PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
-+ PM_WRITE(PM_DSI1, 0);
-+ return 0;
-+
-+ case BCM2835_POWER_DOMAIN_CCP2TX:
-+ PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
-+ PM_WRITE(PM_CCP2TX, 0);
-+ return 0;
-+
-+ case BCM2835_POWER_DOMAIN_HDMI:
-+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD);
-+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN);
-+ return 0;
-+
-+ default:
-+ dev_err(power->dev, "Invalid domain %d\n", pd->domain);
-+ return -EINVAL;
-+ }
-+}
-+
-+static void
-+bcm2835_init_power_domain(struct bcm2835_power *power,
-+ int pd_xlate_index, const char *name)
-+{
-+ struct device *dev = power->dev;
-+ struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
-+
-+ dom->clk = devm_clk_get(dev->parent, name);
-+
-+ dom->base.name = name;
-+ dom->base.power_on = bcm2835_power_pd_power_on;
-+ dom->base.power_off = bcm2835_power_pd_power_off;
-+
-+ dom->domain = pd_xlate_index;
-+ dom->power = power;
-+
-+ /* XXX: on/off at boot? */
-+ pm_genpd_init(&dom->base, NULL, true);
-+
-+ power->pd_xlate.domains[pd_xlate_index] = &dom->base;
-+}
-+
-+/** bcm2835_reset_reset - Resets a block that has a reset line in the
-+ * PM block.
-+ *
-+ * The consumer of the reset controller must have the power domain up
-+ * -- there's no reset ability with the power domain down. To reset
-+ * the sub-block, we just disable its access to memory through the
-+ * ASB, reset, and re-enable.
-+ */
-+static int bcm2835_reset_reset(struct reset_controller_dev *rcdev,
-+ unsigned long id)
-+{
-+ struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
-+ reset);
-+ struct bcm2835_power_domain *pd;
-+ int ret;
-+
-+ switch (id) {
-+ case BCM2835_RESET_V3D:
-+ pd = &power->domains[BCM2835_POWER_DOMAIN_GRAFX_V3D];
-+ break;
-+ case BCM2835_RESET_H264:
-+ pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_H264];
-+ break;
-+ case BCM2835_RESET_ISP:
-+ pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_ISP];
-+ break;
-+ default:
-+ dev_err(power->dev, "Bad reset id %ld\n", id);
-+ return -EINVAL;
-+ }
-+
-+ ret = bcm2835_power_pd_power_off(&pd->base);
-+ if (ret)
-+ return ret;
-+
-+ return bcm2835_power_pd_power_on(&pd->base);
-+}
-+
-+static int bcm2835_reset_status(struct reset_controller_dev *rcdev,
-+ unsigned long id)
-+{
-+ struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
-+ reset);
-+
-+ switch (id) {
-+ case BCM2835_RESET_V3D:
-+ return !PM_READ(PM_GRAFX & PM_V3DRSTN);
-+ case BCM2835_RESET_H264:
-+ return !PM_READ(PM_IMAGE & PM_H264RSTN);
-+ case BCM2835_RESET_ISP:
-+ return !PM_READ(PM_IMAGE & PM_ISPRSTN);
-+ default:
-+ return -EINVAL;
-+ }
-+}
-+
-+const struct reset_control_ops bcm2835_reset_ops = {
-+ .reset = bcm2835_reset_reset,
-+ .status = bcm2835_reset_status,
-+};
-+
-+static const char *const power_domain_names[] = {
-+ [BCM2835_POWER_DOMAIN_GRAFX] = "grafx",
-+ [BCM2835_POWER_DOMAIN_GRAFX_V3D] = "v3d",
-+
-+ [BCM2835_POWER_DOMAIN_IMAGE] = "image",
-+ [BCM2835_POWER_DOMAIN_IMAGE_PERI] = "peri_image",
-+ [BCM2835_POWER_DOMAIN_IMAGE_H264] = "h264",
-+ [BCM2835_POWER_DOMAIN_IMAGE_ISP] = "isp",
-+
-+ [BCM2835_POWER_DOMAIN_USB] = "usb",
-+ [BCM2835_POWER_DOMAIN_DSI0] = "dsi0",
-+ [BCM2835_POWER_DOMAIN_DSI1] = "dsi1",
-+ [BCM2835_POWER_DOMAIN_CAM0] = "cam0",
-+ [BCM2835_POWER_DOMAIN_CAM1] = "cam1",
-+ [BCM2835_POWER_DOMAIN_CCP2TX] = "ccp2tx",
-+ [BCM2835_POWER_DOMAIN_HDMI] = "hdmi",
-+};
-+
-+static int bcm2835_power_probe(struct platform_device *pdev)
-+{
-+ struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
-+ struct device *dev = &pdev->dev;
-+ struct bcm2835_power *power;
-+ static const struct {
-+ int parent, child;
-+ } domain_deps[] = {
-+ { BCM2835_POWER_DOMAIN_GRAFX, BCM2835_POWER_DOMAIN_GRAFX_V3D },
-+ { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_PERI },
-+ { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_H264 },
-+ { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_ISP },
-+ { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_USB },
-+ { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
-+ { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
-+ };
-+ int ret, i;
-+ u32 id;
-+
-+ power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
-+ if (!power)
-+ return -ENOMEM;
-+ platform_set_drvdata(pdev, power);
-+
-+ power->dev = dev;
-+ power->base = pm->base;
-+ power->asb = pm->asb;
-+
-+ id = ASB_READ(ASB_AXI_BRDG_ID);
-+ if (id != 0x62726467 /* "BRDG" */) {
-+ dev_err(dev, "ASB register ID returned 0x%08x\n", id);
-+ return -ENODEV;
-+ }
-+
-+ power->pd_xlate.domains = devm_kcalloc(dev,
-+ ARRAY_SIZE(power_domain_names),
-+ sizeof(*power->pd_xlate.domains),
-+ GFP_KERNEL);
-+ if (!power->pd_xlate.domains)
-+ return -ENOMEM;
-+
-+ power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
-+
-+ for (i = 0; i < ARRAY_SIZE(power_domain_names); i++)
-+ bcm2835_init_power_domain(power, i, power_domain_names[i]);
-+
-+ for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
-+ pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
-+ &power->domains[domain_deps[i].child].base);
-+ }
-+
-+ power->reset.owner = THIS_MODULE;
-+ power->reset.nr_resets = BCM2835_RESET_COUNT;
-+ power->reset.ops = &bcm2835_reset_ops;
-+ power->reset.of_node = dev->parent->of_node;
-+
-+ ret = devm_reset_controller_register(dev, &power->reset);
-+ if (ret)
-+ return ret;
-+
-+ of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
-+
-+ dev_info(dev, "Broadcom BCM2835 power domains driver");
-+ return 0;
-+}
-+
-+static int bcm2835_power_remove(struct platform_device *pdev)
-+{
-+ return 0;
-+}
-+
-+static struct platform_driver bcm2835_power_driver = {
-+ .probe = bcm2835_power_probe,
-+ .remove = bcm2835_power_remove,
-+ .driver = {
-+ .name = "bcm2835-power",
-+ },
-+};
-+module_platform_driver(bcm2835_power_driver);
-+
-+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
-+MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/include/dt-bindings/soc/bcm2835-pm.h
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
-+
-+#ifndef _DT_BINDINGS_ARM_BCM2835_PM_H
-+#define _DT_BINDINGS_ARM_BCM2835_PM_H
-+
-+#define BCM2835_POWER_DOMAIN_GRAFX 0
-+#define BCM2835_POWER_DOMAIN_GRAFX_V3D 1
-+#define BCM2835_POWER_DOMAIN_IMAGE 2
-+#define BCM2835_POWER_DOMAIN_IMAGE_PERI 3
-+#define BCM2835_POWER_DOMAIN_IMAGE_ISP 4
-+#define BCM2835_POWER_DOMAIN_IMAGE_H264 5
-+#define BCM2835_POWER_DOMAIN_USB 6
-+#define BCM2835_POWER_DOMAIN_DSI0 7
-+#define BCM2835_POWER_DOMAIN_DSI1 8
-+#define BCM2835_POWER_DOMAIN_CAM0 9
-+#define BCM2835_POWER_DOMAIN_CAM1 10
-+#define BCM2835_POWER_DOMAIN_CCP2TX 11
-+#define BCM2835_POWER_DOMAIN_HDMI 12
-+
-+#define BCM2835_POWER_DOMAIN_COUNT 13
-+
-+#define BCM2835_RESET_V3D 0
-+#define BCM2835_RESET_ISP 1
-+#define BCM2835_RESET_H264 2
-+
-+#define BCM2835_RESET_COUNT 3
-+
-+#endif /* _DT_BINDINGS_ARM_BCM2835_PM_H */
---- a/include/linux/mfd/bcm2835-pm.h
-+++ b/include/linux/mfd/bcm2835-pm.h
-@@ -8,6 +8,7 @@
- struct bcm2835_pm {
- struct device *dev;
- void __iomem *base;
-+ void __iomem *asb;
- };
-
- #endif /* BCM2835_MFD_PM_H */
--- /dev/null
+From 29fd99cb6bccda2b084b7a78824294075aafcc27 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 28 Sep 2018 16:21:23 -0700
+Subject: [PATCH 562/725] drm/v3d: Fix a use-after-free race accessing the
+ scheduler's fences.
+
+Once we push the job, the scheduler could run it and free it. So, if
+we want to reference their fences, we need to grab them before then.
+I haven't seen this happen in many days of conformance test runtime,
+but let's still close the race.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
+Link: https://patchwork.freedesktop.org/patch/254119/
+Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
+(cherry picked from commit 34c2c4f632f232ed2fdb66d4e42cc72d322273fe)
+---
+ drivers/gpu/drm/v3d/v3d_drv.h | 5 +++++
+ drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++++--
+ 2 files changed, 11 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -198,6 +198,11 @@ struct v3d_exec_info {
+ */
+ struct dma_fence *bin_done_fence;
+
++ /* Fence for when the scheduler considers the render to be
++ * done, for when the BOs reservations should be complete.
++ */
++ struct dma_fence *render_done_fence;
++
+ struct kref refcount;
+
+ /* This is the array of BOs that were looked up at the start of exec. */
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -209,7 +209,7 @@ v3d_flush_caches(struct v3d_dev *v3d)
+ static void
+ v3d_attach_object_fences(struct v3d_exec_info *exec)
+ {
+- struct dma_fence *out_fence = &exec->render.base.s_fence->finished;
++ struct dma_fence *out_fence = exec->render_done_fence;
+ struct v3d_bo *bo;
+ int i;
+
+@@ -409,6 +409,7 @@ v3d_exec_cleanup(struct kref *ref)
+ dma_fence_put(exec->render.done_fence);
+
+ dma_fence_put(exec->bin_done_fence);
++ dma_fence_put(exec->render_done_fence);
+
+ for (i = 0; i < exec->bo_count; i++)
+ drm_gem_object_put_unlocked(&exec->bo[i]->base);
+@@ -572,6 +573,9 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ if (ret)
+ goto fail_unreserve;
+
++ exec->render_done_fence =
++ dma_fence_get(&exec->render.base.s_fence->finished);
++
+ kref_get(&exec->refcount); /* put by scheduler job completion */
+ drm_sched_entity_push_job(&exec->render.base,
+ &v3d_priv->sched_entity[V3D_RENDER]);
+@@ -585,7 +589,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ sync_out = drm_syncobj_find(file_priv, args->out_sync);
+ if (sync_out) {
+ drm_syncobj_replace_fence(sync_out,
+- &exec->render.base.s_fence->finished);
++ exec->render_done_fence);
+ drm_syncobj_put(sync_out);
+ }
+
+++ /dev/null
-From 81f47bb7d51490b62ba2fad6c0be42bf0e4e13a2 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 11 Jan 2019 17:29:10 -0800
-Subject: [PATCH 562/703] soc: bcm: bcm2835-pm: Fix PM_IMAGE_PERI power domain
- support.
-
-We don't have ASB master/slave regs for this domain, so just skip that
-step.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Fixes: 670c672608a1 ("soc: bcm: bcm2835-pm: Add support for power domains under a new binding.")
----
- drivers/soc/bcm/bcm2835-power.c | 14 ++++++++++++--
- 1 file changed, 12 insertions(+), 2 deletions(-)
-
---- a/drivers/soc/bcm/bcm2835-power.c
-+++ b/drivers/soc/bcm/bcm2835-power.c
-@@ -150,7 +150,12 @@ struct bcm2835_power {
-
- static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
- {
-- u64 start = ktime_get_ns();
-+ u64 start;
-+
-+ if (!reg)
-+ return 0;
-+
-+ start = ktime_get_ns();
-
- /* Enable the module's async AXI bridges. */
- ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP);
-@@ -165,7 +170,12 @@ static int bcm2835_asb_enable(struct bcm
-
- static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
- {
-- u64 start = ktime_get_ns();
-+ u64 start;
-+
-+ if (!reg)
-+ return 0;
-+
-+ start = ktime_get_ns();
-
- /* Enable the module's async AXI bridges. */
- ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP);
--- /dev/null
+From d38e39d32a5df364c46416e25a5ee07756f8991e Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 28 Sep 2018 16:21:24 -0700
+Subject: [PATCH 563/725] drm/v3d: Add a little debugfs entry for measuring the
+ core clock.
+
+This adds just enough performance counter support to measure the
+clock. We don't have linux kernel drivers for the clock driving the
+HW, and this was useful for determining that the V3D HW is running on
+a slow clock, not that the driver was slow.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20180928232126.4332-2-eric@anholt.net
+Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
+(cherry picked from commit 6915c9a525e575732429c22b28eb11871a29374b)
+---
+ drivers/gpu/drm/v3d/v3d_debugfs.c | 35 +++++++++++++++++++++++++++++++
+ drivers/gpu/drm/v3d/v3d_regs.h | 30 ++++++++++++++++++++++++++
+ 2 files changed, 65 insertions(+)
+
+--- a/drivers/gpu/drm/v3d/v3d_debugfs.c
++++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
+@@ -179,9 +179,44 @@ static int v3d_debugfs_bo_stats(struct s
+ return 0;
+ }
+
++static int v3d_measure_clock(struct seq_file *m, void *unused)
++{
++ struct drm_info_node *node = (struct drm_info_node *)m->private;
++ struct drm_device *dev = node->minor->dev;
++ struct v3d_dev *v3d = to_v3d_dev(dev);
++ uint32_t cycles;
++ int core = 0;
++ int measure_ms = 1000;
++
++ if (v3d->ver >= 40) {
++ V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3,
++ V3D_SET_FIELD(V3D_PCTR_CYCLE_COUNT,
++ V3D_PCTR_S0));
++ V3D_CORE_WRITE(core, V3D_V4_PCTR_0_CLR, 1);
++ V3D_CORE_WRITE(core, V3D_V4_PCTR_0_EN, 1);
++ } else {
++ V3D_CORE_WRITE(core, V3D_V3_PCTR_0_PCTRS0,
++ V3D_PCTR_CYCLE_COUNT);
++ V3D_CORE_WRITE(core, V3D_V3_PCTR_0_CLR, 1);
++ V3D_CORE_WRITE(core, V3D_V3_PCTR_0_EN,
++ V3D_V3_PCTR_0_EN_ENABLE |
++ 1);
++ }
++ msleep(measure_ms);
++ cycles = V3D_CORE_READ(core, V3D_PCTR_0_PCTR0);
++
++ seq_printf(m, "cycles: %d (%d.%d Mhz)\n",
++ cycles,
++ cycles / (measure_ms * 1000),
++ (cycles / (measure_ms * 100)) % 10);
++
++ return 0;
++}
++
+ static const struct drm_info_list v3d_debugfs_list[] = {
+ {"v3d_ident", v3d_v3d_debugfs_ident, 0},
+ {"v3d_regs", v3d_v3d_debugfs_regs, 0},
++ {"measure_clock", v3d_measure_clock, 0},
+ {"bo_stats", v3d_debugfs_bo_stats, 0},
+ };
+
+--- a/drivers/gpu/drm/v3d/v3d_regs.h
++++ b/drivers/gpu/drm/v3d/v3d_regs.h
+@@ -267,6 +267,36 @@
+ # define V3D_PTB_BXCF_RWORDERDISA BIT(1)
+ # define V3D_PTB_BXCF_CLIPDISA BIT(0)
+
++#define V3D_V3_PCTR_0_EN 0x00674
++#define V3D_V3_PCTR_0_EN_ENABLE BIT(31)
++#define V3D_V4_PCTR_0_EN 0x00650
++/* When a bit is set, resets the counter to 0. */
++#define V3D_V3_PCTR_0_CLR 0x00670
++#define V3D_V4_PCTR_0_CLR 0x00654
++#define V3D_PCTR_0_OVERFLOW 0x00658
++
++#define V3D_V3_PCTR_0_PCTRS0 0x00684
++#define V3D_V3_PCTR_0_PCTRS15 0x00660
++#define V3D_V3_PCTR_0_PCTRSX(x) (V3D_V3_PCTR_0_PCTRS0 + \
++ 4 * (x))
++/* Each src reg muxes four counters each. */
++#define V3D_V4_PCTR_0_SRC_0_3 0x00660
++#define V3D_V4_PCTR_0_SRC_28_31 0x0067c
++# define V3D_PCTR_S0_MASK V3D_MASK(6, 0)
++# define V3D_PCTR_S0_SHIFT 0
++# define V3D_PCTR_S1_MASK V3D_MASK(14, 8)
++# define V3D_PCTR_S1_SHIFT 8
++# define V3D_PCTR_S2_MASK V3D_MASK(22, 16)
++# define V3D_PCTR_S2_SHIFT 16
++# define V3D_PCTR_S3_MASK V3D_MASK(30, 24)
++# define V3D_PCTR_S3_SHIFT 24
++# define V3D_PCTR_CYCLE_COUNT 32
++
++/* Output values of the counters. */
++#define V3D_PCTR_0_PCTR0 0x00680
++#define V3D_PCTR_0_PCTR31 0x006fc
++#define V3D_PCTR_0_PCTRX(x) (V3D_PCTR_0_PCTR0 + \
++ 4 * (x))
+ #define V3D_GMP_STATUS 0x00800
+ # define V3D_GMP_STATUS_GMPRST BIT(31)
+ # define V3D_GMP_STATUS_WR_COUNT_MASK V3D_MASK(30, 24)
+++ /dev/null
-From 03ca911deca660a85ff285b53b1431350c77b246 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Sat, 12 Jan 2019 08:07:43 -0800
-Subject: [PATCH 563/703] soc: bcm: bcm2835-pm: Fix error paths of
- initialization.
-
-The clock driver may probe after ours and so we need to pass the
--EPROBE_DEFER out. Fix the other error path while we're here.
-
-v2: Use dom->name instead of dom->gov as the flag for initialized
- domains, since we aren't setting up a governor. Make sure to
- clear ->clk when no clk is present in the DT.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Fixes: 670c672608a1 ("soc: bcm: bcm2835-pm: Add support for power domains under a new binding.")
----
- drivers/soc/bcm/bcm2835-power.c | 35 ++++++++++++++++++++++++++++-----
- 1 file changed, 30 insertions(+), 5 deletions(-)
-
---- a/drivers/soc/bcm/bcm2835-power.c
-+++ b/drivers/soc/bcm/bcm2835-power.c
-@@ -485,7 +485,7 @@ static int bcm2835_power_pd_power_off(st
- }
- }
-
--static void
-+static int
- bcm2835_init_power_domain(struct bcm2835_power *power,
- int pd_xlate_index, const char *name)
- {
-@@ -493,6 +493,17 @@ bcm2835_init_power_domain(struct bcm2835
- struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
-
- dom->clk = devm_clk_get(dev->parent, name);
-+ if (IS_ERR(dom->clk)) {
-+ int ret = PTR_ERR(dom->clk);
-+
-+ if (ret == -EPROBE_DEFER)
-+ return ret;
-+
-+ /* Some domains don't have a clk, so make sure that we
-+ * don't deref an error pointer later.
-+ */
-+ dom->clk = NULL;
-+ }
-
- dom->base.name = name;
- dom->base.power_on = bcm2835_power_pd_power_on;
-@@ -505,6 +516,8 @@ bcm2835_init_power_domain(struct bcm2835
- pm_genpd_init(&dom->base, NULL, true);
-
- power->pd_xlate.domains[pd_xlate_index] = &dom->base;
-+
-+ return 0;
- }
-
- /** bcm2835_reset_reset - Resets a block that has a reset line in the
-@@ -602,7 +615,7 @@ static int bcm2835_power_probe(struct pl
- { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
- { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
- };
-- int ret, i;
-+ int ret = 0, i;
- u32 id;
-
- power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
-@@ -629,8 +642,11 @@ static int bcm2835_power_probe(struct pl
-
- power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
-
-- for (i = 0; i < ARRAY_SIZE(power_domain_names); i++)
-- bcm2835_init_power_domain(power, i, power_domain_names[i]);
-+ for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
-+ ret = bcm2835_init_power_domain(power, i, power_domain_names[i]);
-+ if (ret)
-+ goto fail;
-+ }
-
- for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
- pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
-@@ -644,12 +660,21 @@ static int bcm2835_power_probe(struct pl
-
- ret = devm_reset_controller_register(dev, &power->reset);
- if (ret)
-- return ret;
-+ goto fail;
-
- of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
-
- dev_info(dev, "Broadcom BCM2835 power domains driver");
- return 0;
-+
-+fail:
-+ for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
-+ struct generic_pm_domain *dom = &power->domains[i].base;
-+
-+ if (dom->name)
-+ pm_genpd_remove(dom);
-+ }
-+ return ret;
- }
-
- static int bcm2835_power_remove(struct platform_device *pdev)
--- /dev/null
+From fe38ab422b824e2e1f4b010a7b48c820ff302c8d Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 8 Nov 2018 08:16:52 -0800
+Subject: [PATCH 564/725] drm/v3d: Update a comment about what uses
+ v3d_job_dependency().
+
+I merged bin and render's paths in a late refactoring.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181108161654.19888-3-eric@anholt.net
+Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
+(cherry picked from commit e90e45f6bd45cc494a6f4cd1853c5e7cd4be7f68)
+---
+ drivers/gpu/drm/v3d/v3d_sched.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -39,7 +39,7 @@ v3d_job_free(struct drm_sched_job *sched
+ }
+
+ /**
+- * Returns the fences that the bin job depends on, one by one.
++ * Returns the fences that the bin or render job depends on, one by one.
+ * v3d_job_run() won't be called until all of them have been signaled.
+ */
+ static struct dma_fence *
+++ /dev/null
-From 4c3762f3ef917c00708650cdd532dd857ca75f04 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 11 Jan 2019 17:31:07 -0800
-Subject: [PATCH 564/703] soc: bcm: bcm2835-pm: Add support for 2711.
-
-Without the actual power management part any more, there's a lot less
-to set up for V3D. We just need to clear the RSTN field for the power
-domain, and expose the reset controller for toggling it again.
-
-This is definitely incomplete -- the old ISP and H264 is in the old
-bridge, but since we have no consumers of it I've just done the
-minimum to get V3D working.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/mfd/bcm2835-pm.c | 11 +++++++++++
- drivers/soc/bcm/bcm2835-power.c | 22 ++++++++++++++++++++++
- include/linux/mfd/bcm2835-pm.h | 1 +
- 3 files changed, 34 insertions(+)
-
---- a/drivers/mfd/bcm2835-pm.c
-+++ b/drivers/mfd/bcm2835-pm.c
-@@ -50,6 +50,17 @@ static int bcm2835_pm_probe(struct platf
- if (ret)
- return ret;
-
-+ /* Map the ARGON ASB regs if present. */
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-+ if (res) {
-+ pm->arg_asb = devm_ioremap_resource(dev, res);
-+ if (IS_ERR(pm->arg_asb)) {
-+ dev_err(dev, "Failed to map ARGON ASB: %ld\n",
-+ PTR_ERR(pm->arg_asb));
-+ return PTR_ERR(pm->arg_asb);
-+ }
-+ }
-+
- /* We'll use the presence of the AXI ASB regs in the
- * bcm2835-pm binding as the key for whether we can reference
- * the full PM register range and support power domains.
---- a/drivers/soc/bcm/bcm2835-power.c
-+++ b/drivers/soc/bcm/bcm2835-power.c
-@@ -143,6 +143,8 @@ struct bcm2835_power {
- /* AXI Async bridge registers. */
- void __iomem *asb;
-
-+ bool is_2711;
-+
- struct genpd_onecell_data pd_xlate;
- struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
- struct reset_controller_dev reset;
-@@ -192,6 +194,10 @@ static int bcm2835_power_power_off(struc
- {
- struct bcm2835_power *power = pd->power;
-
-+ /* 2711 has no power domains above the reset controller. */
-+ if (power->is_2711)
-+ return 0;
-+
- /* Enable functional isolation */
- PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
-
-@@ -213,6 +219,10 @@ static int bcm2835_power_power_on(struct
- int inrush;
- bool powok;
-
-+ /* 2711 has no power domains above the reset controller. */
-+ if (power->is_2711)
-+ return 0;
-+
- /* If it was already powered on by the fw, leave it that way. */
- if (PM_READ(pm_reg) & PM_POWUP)
- return 0;
-@@ -627,6 +637,18 @@ static int bcm2835_power_probe(struct pl
- power->base = pm->base;
- power->asb = pm->asb;
-
-+ /* 2711 hack: the new ARGON ASB took over V3D, which is our
-+ * only consumer of this driver so far. The old ASB seems to
-+ * still be present with ISP and H264 bits but no V3D, but I
-+ * don't know if that's real or not. The V3D is in the same
-+ * place in the new ASB as the old one, so just poke the new
-+ * one for now.
-+ */
-+ if (pm->arg_asb) {
-+ power->asb = pm->arg_asb;
-+ power->is_2711 = true;
-+ }
-+
- id = ASB_READ(ASB_AXI_BRDG_ID);
- if (id != 0x62726467 /* "BRDG" */) {
- dev_err(dev, "ASB register ID returned 0x%08x\n", id);
---- a/include/linux/mfd/bcm2835-pm.h
-+++ b/include/linux/mfd/bcm2835-pm.h
-@@ -9,6 +9,7 @@ struct bcm2835_pm {
- struct device *dev;
- void __iomem *base;
- void __iomem *asb;
-+ void __iomem *arg_asb;
- };
-
- #endif /* BCM2835_MFD_PM_H */
+++ /dev/null
-From 2593714309aa6f7fb3b06ffac7ca195a50543252 Mon Sep 17 00:00:00 2001
-From: Chunming Zhou <david1.zhou@amd.com>
-Date: Thu, 30 Aug 2018 14:48:29 +0800
-Subject: [PATCH 565/703] drm: expand drm_syncobj_find_fence to support
- timeline point v2
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-we can fetch timeline point fence after expanded.
-v2: The parameter fence is the result of the function and should come last.
-
-Signed-off-by: Chunming Zhou <david1.zhou@amd.com>
-Reviewed-by: Christian König <christian.koenig@amd.com>
-Signed-off-by: Christian König <christian.koenig@amd.com>
-Link: https://patchwork.freedesktop.org/patch/246541/
-(cherry picked from commit 0a6730ea27b68c7ac4171c29a816c29d26a9637a)
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +-
- drivers/gpu/drm/drm_syncobj.c | 5 +++--
- drivers/gpu/drm/v3d/v3d_gem.c | 4 ++--
- drivers/gpu/drm/vc4/vc4_gem.c | 2 +-
- include/drm/drm_syncobj.h | 2 +-
- 5 files changed, 8 insertions(+), 7 deletions(-)
-
---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
-+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
-@@ -1105,7 +1105,7 @@ static int amdgpu_syncobj_lookup_and_add
- {
- int r;
- struct dma_fence *fence;
-- r = drm_syncobj_find_fence(p->filp, handle, &fence);
-+ r = drm_syncobj_find_fence(p->filp, handle, 0, &fence);
- if (r)
- return r;
-
---- a/drivers/gpu/drm/drm_syncobj.c
-+++ b/drivers/gpu/drm/drm_syncobj.c
-@@ -235,6 +235,7 @@ static int drm_syncobj_assign_null_handl
- * drm_syncobj_find_fence - lookup and reference the fence in a sync object
- * @file_private: drm file private pointer
- * @handle: sync object handle to lookup.
-+ * @point: timeline point
- * @fence: out parameter for the fence
- *
- * This is just a convenience function that combines drm_syncobj_find() and
-@@ -245,7 +246,7 @@ static int drm_syncobj_assign_null_handl
- * dma_fence_put().
- */
- int drm_syncobj_find_fence(struct drm_file *file_private,
-- u32 handle,
-+ u32 handle, u64 point,
- struct dma_fence **fence)
- {
- struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle);
-@@ -516,7 +517,7 @@ static int drm_syncobj_export_sync_file(
- if (fd < 0)
- return fd;
-
-- ret = drm_syncobj_find_fence(file_private, handle, &fence);
-+ ret = drm_syncobj_find_fence(file_private, handle, 0, &fence);
- if (ret)
- goto err_put_fd;
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -521,12 +521,12 @@ v3d_submit_cl_ioctl(struct drm_device *d
- kref_init(&exec->refcount);
-
- ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,
-- &exec->bin.in_fence);
-+ 0, &exec->bin.in_fence);
- if (ret == -EINVAL)
- goto fail;
-
- ret = drm_syncobj_find_fence(file_priv, args->in_sync_rcl,
-- &exec->render.in_fence);
-+ 0, &exec->render.in_fence);
- if (ret == -EINVAL)
- goto fail;
-
---- a/drivers/gpu/drm/vc4/vc4_gem.c
-+++ b/drivers/gpu/drm/vc4/vc4_gem.c
-@@ -1173,7 +1173,7 @@ vc4_submit_cl_ioctl(struct drm_device *d
-
- if (args->in_sync) {
- ret = drm_syncobj_find_fence(file_priv, args->in_sync,
-- &in_fence);
-+ 0, &in_fence);
- if (ret)
- goto fail;
-
---- a/include/drm/drm_syncobj.h
-+++ b/include/drm/drm_syncobj.h
-@@ -139,7 +139,7 @@ void drm_syncobj_remove_callback(struct
- void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
- struct dma_fence *fence);
- int drm_syncobj_find_fence(struct drm_file *file_private,
-- u32 handle,
-+ u32 handle, u64 point,
- struct dma_fence **fence);
- void drm_syncobj_free(struct kref *kref);
- int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags,
--- /dev/null
+From bf9bb521ac3c5d18ed4a8e8e5004f015c2b2a818 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 8 Nov 2018 08:16:53 -0800
+Subject: [PATCH 565/725] drm/v3d: Clean up the reservation object setup.
+
+The extra to_v3d_bo() calls came from copying this from the vc4
+driver, which stored the cma gem object in the structs.
+
+v2: Fix an unused var warning
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181108161654.19888-4-eric@anholt.net
+Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com> (v1)
+(cherry picked from commit 8f1cd826641d677d0f7494253ecfc3335f0bcd4e)
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 33 +++++++++++----------------------
+ 1 file changed, 11 insertions(+), 22 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -210,14 +210,11 @@ static void
+ v3d_attach_object_fences(struct v3d_exec_info *exec)
+ {
+ struct dma_fence *out_fence = exec->render_done_fence;
+- struct v3d_bo *bo;
+ int i;
+
+ for (i = 0; i < exec->bo_count; i++) {
+- bo = to_v3d_bo(&exec->bo[i]->base);
+-
+ /* XXX: Use shared fences for read-only objects. */
+- reservation_object_add_excl_fence(bo->resv, out_fence);
++ reservation_object_add_excl_fence(exec->bo[i]->resv, out_fence);
+ }
+ }
+
+@@ -228,11 +225,8 @@ v3d_unlock_bo_reservations(struct drm_de
+ {
+ int i;
+
+- for (i = 0; i < exec->bo_count; i++) {
+- struct v3d_bo *bo = to_v3d_bo(&exec->bo[i]->base);
+-
+- ww_mutex_unlock(&bo->resv->lock);
+- }
++ for (i = 0; i < exec->bo_count; i++)
++ ww_mutex_unlock(&exec->bo[i]->resv->lock);
+
+ ww_acquire_fini(acquire_ctx);
+ }
+@@ -251,13 +245,13 @@ v3d_lock_bo_reservations(struct drm_devi
+ {
+ int contended_lock = -1;
+ int i, ret;
+- struct v3d_bo *bo;
+
+ ww_acquire_init(acquire_ctx, &reservation_ww_class);
+
+ retry:
+ if (contended_lock != -1) {
+- bo = to_v3d_bo(&exec->bo[contended_lock]->base);
++ struct v3d_bo *bo = exec->bo[contended_lock];
++
+ ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
+ acquire_ctx);
+ if (ret) {
+@@ -270,19 +264,16 @@ retry:
+ if (i == contended_lock)
+ continue;
+
+- bo = to_v3d_bo(&exec->bo[i]->base);
+-
+- ret = ww_mutex_lock_interruptible(&bo->resv->lock, acquire_ctx);
++ ret = ww_mutex_lock_interruptible(&exec->bo[i]->resv->lock,
++ acquire_ctx);
+ if (ret) {
+ int j;
+
+- for (j = 0; j < i; j++) {
+- bo = to_v3d_bo(&exec->bo[j]->base);
+- ww_mutex_unlock(&bo->resv->lock);
+- }
++ for (j = 0; j < i; j++)
++ ww_mutex_unlock(&exec->bo[j]->resv->lock);
+
+ if (contended_lock != -1 && contended_lock >= i) {
+- bo = to_v3d_bo(&exec->bo[contended_lock]->base);
++ struct v3d_bo *bo = exec->bo[contended_lock];
+
+ ww_mutex_unlock(&bo->resv->lock);
+ }
+@@ -303,9 +294,7 @@ retry:
+ * before we commit the CL to the hardware.
+ */
+ for (i = 0; i < exec->bo_count; i++) {
+- bo = to_v3d_bo(&exec->bo[i]->base);
+-
+- ret = reservation_object_reserve_shared(bo->resv);
++ ret = reservation_object_reserve_shared(exec->bo[i]->resv);
+ if (ret) {
+ v3d_unlock_bo_reservations(dev, exec, acquire_ctx);
+ return ret;
--- /dev/null
+From 5d80273397b13617211ac6dd1e0e9759fff0470d Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 28 Nov 2018 15:09:25 -0800
+Subject: [PATCH 566/725] drm/v3d: Add support for submitting jobs to the TFU.
+
+The TFU can copy from raster, UIF, and SAND input images to UIF output
+images, with optional mipmap generation. This will certainly be
+useful for media EGL image input, but is also useful immediately for
+mipmap generation without bogging the V3D core down.
+
+For now we only run the queue 1 job deep, and don't have any hang
+recovery (though I don't think we should need it, with TFU). Queuing
+multiple jobs in the HW will require synchronizing the YUV coefficient
+regs updates since they don't get FIFOed with the job.
+
+v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
+ why TFU is AUTH, clarify the syncing docs, drop the unused TFU
+ interrupt regs (you're expected to use the hub's), don't take
+ &bo->base for NULL bos.
+v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
+ on drm_sched_job_cleanup() changes.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
+Link: https://patchwork.freedesktop.org/patch/264607/
+(cherry picked from commit 1584f16ca96ef124aad79efa3303cff5f3530e2c)
+---
+ drivers/gpu/drm/v3d/v3d_drv.c | 15 ++-
+ drivers/gpu/drm/v3d/v3d_drv.h | 32 +++++-
+ drivers/gpu/drm/v3d/v3d_gem.c | 178 ++++++++++++++++++++++++++++----
+ drivers/gpu/drm/v3d/v3d_irq.c | 12 ++-
+ drivers/gpu/drm/v3d/v3d_regs.h | 49 +++++++++
+ drivers/gpu/drm/v3d/v3d_sched.c | 148 ++++++++++++++++++++++----
+ drivers/gpu/drm/v3d/v3d_trace.h | 20 ++++
+ include/uapi/drm/v3d_drm.h | 25 +++++
+ 8 files changed, 426 insertions(+), 53 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -112,10 +112,15 @@ static int v3d_get_param_ioctl(struct dr
+ return 0;
+ }
+
+- /* Any params that aren't just register reads would go here. */
+
+- DRM_DEBUG("Unknown parameter %d\n", args->param);
+- return -EINVAL;
++ switch (args->param) {
++ case DRM_V3D_PARAM_SUPPORTS_TFU:
++ args->value = 1;
++ return 0;
++ default:
++ DRM_DEBUG("Unknown parameter %d\n", args->param);
++ return -EINVAL;
++ }
+ }
+
+ static int
+@@ -170,7 +175,8 @@ static const struct file_operations v3d_
+ /* DRM_AUTH is required on SUBMIT_CL for now, while we don't have GMP
+ * protection between clients. Note that render nodes would be be
+ * able to submit CLs that could access BOs from clients authenticated
+- * with the master node.
++ * with the master node. The TFU doesn't use the GMP, so it would
++ * need to stay DRM_AUTH until we do buffer size/offset validation.
+ */
+ static const struct drm_ioctl_desc v3d_drm_ioctls[] = {
+ DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CL, v3d_submit_cl_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
+@@ -179,6 +185,7 @@ static const struct drm_ioctl_desc v3d_d
+ DRM_IOCTL_DEF_DRV(V3D_MMAP_BO, v3d_mmap_bo_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(V3D_GET_PARAM, v3d_get_param_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(V3D_GET_BO_OFFSET, v3d_get_bo_offset_ioctl, DRM_RENDER_ALLOW),
++ DRM_IOCTL_DEF_DRV(V3D_SUBMIT_TFU, v3d_submit_tfu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
+ };
+
+ static const struct vm_operations_struct v3d_vm_ops = {
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -7,19 +7,18 @@
+ #include <drm/drm_encoder.h>
+ #include <drm/drm_gem.h>
+ #include <drm/gpu_scheduler.h>
++#include "uapi/drm/v3d_drm.h"
+
+ #define GMP_GRANULARITY (128 * 1024)
+
+-/* Enum for each of the V3D queues. We maintain various queue
+- * tracking as an array because at some point we'll want to support
+- * the TFU (texture formatting unit) as another queue.
+- */
++/* Enum for each of the V3D queues. */
+ enum v3d_queue {
+ V3D_BIN,
+ V3D_RENDER,
++ V3D_TFU,
+ };
+
+-#define V3D_MAX_QUEUES (V3D_RENDER + 1)
++#define V3D_MAX_QUEUES (V3D_TFU + 1)
+
+ struct v3d_queue_state {
+ struct drm_gpu_scheduler sched;
+@@ -68,6 +67,7 @@ struct v3d_dev {
+
+ struct v3d_exec_info *bin_job;
+ struct v3d_exec_info *render_job;
++ struct v3d_tfu_job *tfu_job;
+
+ struct v3d_queue_state queue[V3D_MAX_QUEUES];
+
+@@ -218,6 +218,25 @@ struct v3d_exec_info {
+ u32 qma, qms, qts;
+ };
+
++struct v3d_tfu_job {
++ struct drm_sched_job base;
++
++ struct drm_v3d_submit_tfu args;
++
++ /* An optional fence userspace can pass in for the job to depend on. */
++ struct dma_fence *in_fence;
++
++ /* v3d fence to be signaled by IRQ handler when the job is complete. */
++ struct dma_fence *done_fence;
++
++ struct v3d_dev *v3d;
++
++ struct kref refcount;
++
++ /* This is the array of BOs that were looked up at the start of exec. */
++ struct v3d_bo *bo[4];
++};
++
+ /**
+ * _wait_for - magic (register) wait macro
+ *
+@@ -281,9 +300,12 @@ int v3d_gem_init(struct drm_device *dev)
+ void v3d_gem_destroy(struct drm_device *dev);
+ int v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
++int v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
++ struct drm_file *file_priv);
+ int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+ void v3d_exec_put(struct v3d_exec_info *exec);
++void v3d_tfu_job_put(struct v3d_tfu_job *exec);
+ void v3d_reset(struct v3d_dev *v3d);
+ void v3d_invalidate_caches(struct v3d_dev *v3d);
+ void v3d_flush_caches(struct v3d_dev *v3d);
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -207,26 +207,27 @@ v3d_flush_caches(struct v3d_dev *v3d)
+ }
+
+ static void
+-v3d_attach_object_fences(struct v3d_exec_info *exec)
++v3d_attach_object_fences(struct v3d_bo **bos, int bo_count,
++ struct dma_fence *fence)
+ {
+- struct dma_fence *out_fence = exec->render_done_fence;
+ int i;
+
+- for (i = 0; i < exec->bo_count; i++) {
++ for (i = 0; i < bo_count; i++) {
+ /* XXX: Use shared fences for read-only objects. */
+- reservation_object_add_excl_fence(exec->bo[i]->resv, out_fence);
++ reservation_object_add_excl_fence(bos[i]->resv, fence);
+ }
+ }
+
+ static void
+ v3d_unlock_bo_reservations(struct drm_device *dev,
+- struct v3d_exec_info *exec,
++ struct v3d_bo **bos,
++ int bo_count,
+ struct ww_acquire_ctx *acquire_ctx)
+ {
+ int i;
+
+- for (i = 0; i < exec->bo_count; i++)
+- ww_mutex_unlock(&exec->bo[i]->resv->lock);
++ for (i = 0; i < bo_count; i++)
++ ww_mutex_unlock(&bos[i]->resv->lock);
+
+ ww_acquire_fini(acquire_ctx);
+ }
+@@ -240,7 +241,8 @@ v3d_unlock_bo_reservations(struct drm_de
+ */
+ static int
+ v3d_lock_bo_reservations(struct drm_device *dev,
+- struct v3d_exec_info *exec,
++ struct v3d_bo **bos,
++ int bo_count,
+ struct ww_acquire_ctx *acquire_ctx)
+ {
+ int contended_lock = -1;
+@@ -250,7 +252,7 @@ v3d_lock_bo_reservations(struct drm_devi
+
+ retry:
+ if (contended_lock != -1) {
+- struct v3d_bo *bo = exec->bo[contended_lock];
++ struct v3d_bo *bo = bos[contended_lock];
+
+ ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
+ acquire_ctx);
+@@ -260,20 +262,20 @@ retry:
+ }
+ }
+
+- for (i = 0; i < exec->bo_count; i++) {
++ for (i = 0; i < bo_count; i++) {
+ if (i == contended_lock)
+ continue;
+
+- ret = ww_mutex_lock_interruptible(&exec->bo[i]->resv->lock,
++ ret = ww_mutex_lock_interruptible(&bos[i]->resv->lock,
+ acquire_ctx);
+ if (ret) {
+ int j;
+
+ for (j = 0; j < i; j++)
+- ww_mutex_unlock(&exec->bo[j]->resv->lock);
++ ww_mutex_unlock(&bos[j]->resv->lock);
+
+ if (contended_lock != -1 && contended_lock >= i) {
+- struct v3d_bo *bo = exec->bo[contended_lock];
++ struct v3d_bo *bo = bos[contended_lock];
+
+ ww_mutex_unlock(&bo->resv->lock);
+ }
+@@ -293,10 +295,11 @@ retry:
+ /* Reserve space for our shared (read-only) fence references,
+ * before we commit the CL to the hardware.
+ */
+- for (i = 0; i < exec->bo_count; i++) {
+- ret = reservation_object_reserve_shared(exec->bo[i]->resv);
++ for (i = 0; i < bo_count; i++) {
++ ret = reservation_object_reserve_shared(bos[i]->resv);
+ if (ret) {
+- v3d_unlock_bo_reservations(dev, exec, acquire_ctx);
++ v3d_unlock_bo_reservations(dev, bos, bo_count,
++ acquire_ctx);
+ return ret;
+ }
+ }
+@@ -419,6 +422,33 @@ void v3d_exec_put(struct v3d_exec_info *
+ kref_put(&exec->refcount, v3d_exec_cleanup);
+ }
+
++static void
++v3d_tfu_job_cleanup(struct kref *ref)
++{
++ struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,
++ refcount);
++ struct v3d_dev *v3d = job->v3d;
++ unsigned int i;
++
++ dma_fence_put(job->in_fence);
++ dma_fence_put(job->done_fence);
++
++ for (i = 0; i < ARRAY_SIZE(job->bo); i++) {
++ if (job->bo[i])
++ drm_gem_object_put_unlocked(&job->bo[i]->base);
++ }
++
++ pm_runtime_mark_last_busy(v3d->dev);
++ pm_runtime_put_autosuspend(v3d->dev);
++
++ kfree(job);
++}
++
++void v3d_tfu_job_put(struct v3d_tfu_job *job)
++{
++ kref_put(&job->refcount, v3d_tfu_job_cleanup);
++}
++
+ int
+ v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+@@ -536,7 +566,8 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ if (ret)
+ goto fail;
+
+- ret = v3d_lock_bo_reservations(dev, exec, &acquire_ctx);
++ ret = v3d_lock_bo_reservations(dev, exec->bo, exec->bo_count,
++ &acquire_ctx);
+ if (ret)
+ goto fail;
+
+@@ -570,9 +601,10 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ &v3d_priv->sched_entity[V3D_RENDER]);
+ mutex_unlock(&v3d->sched_lock);
+
+- v3d_attach_object_fences(exec);
++ v3d_attach_object_fences(exec->bo, exec->bo_count,
++ exec->render_done_fence);
+
+- v3d_unlock_bo_reservations(dev, exec, &acquire_ctx);
++ v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
+
+ /* Update the return sync object for the */
+ sync_out = drm_syncobj_find(file_priv, args->out_sync);
+@@ -588,12 +620,118 @@ v3d_submit_cl_ioctl(struct drm_device *d
+
+ fail_unreserve:
+ mutex_unlock(&v3d->sched_lock);
+- v3d_unlock_bo_reservations(dev, exec, &acquire_ctx);
++ v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
+ fail:
+ v3d_exec_put(exec);
+
+ return ret;
+ }
++
++/**
++ * v3d_submit_tfu_ioctl() - Submits a TFU (texture formatting) job to the V3D.
++ * @dev: DRM device
++ * @data: ioctl argument
++ * @file_priv: DRM file for this fd
++ *
++ * Userspace provides the register setup for the TFU, which we don't
++ * need to validate since the TFU is behind the MMU.
++ */
++int
++v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
++ struct drm_file *file_priv)
++{
++ struct v3d_dev *v3d = to_v3d_dev(dev);
++ struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
++ struct drm_v3d_submit_tfu *args = data;
++ struct v3d_tfu_job *job;
++ struct ww_acquire_ctx acquire_ctx;
++ struct drm_syncobj *sync_out;
++ struct dma_fence *sched_done_fence;
++ int ret = 0;
++ int bo_count;
++
++ job = kcalloc(1, sizeof(*job), GFP_KERNEL);
++ if (!job)
++ return -ENOMEM;
++
++ ret = pm_runtime_get_sync(v3d->dev);
++ if (ret < 0) {
++ kfree(job);
++ return ret;
++ }
++
++ kref_init(&job->refcount);
++
++ ret = drm_syncobj_find_fence(file_priv, args->in_sync,
++ 0, &job->in_fence);
++ if (ret == -EINVAL)
++ goto fail;
++
++ job->args = *args;
++ job->v3d = v3d;
++
++ spin_lock(&file_priv->table_lock);
++ for (bo_count = 0; bo_count < ARRAY_SIZE(job->bo); bo_count++) {
++ struct drm_gem_object *bo;
++
++ if (!args->bo_handles[bo_count])
++ break;
++
++ bo = idr_find(&file_priv->object_idr,
++ args->bo_handles[bo_count]);
++ if (!bo) {
++ DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
++ bo_count, args->bo_handles[bo_count]);
++ ret = -ENOENT;
++ spin_unlock(&file_priv->table_lock);
++ goto fail;
++ }
++ drm_gem_object_get(bo);
++ job->bo[bo_count] = to_v3d_bo(bo);
++ }
++ spin_unlock(&file_priv->table_lock);
++
++ ret = v3d_lock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
++ if (ret)
++ goto fail;
++
++ mutex_lock(&v3d->sched_lock);
++ ret = drm_sched_job_init(&job->base,
++ &v3d_priv->sched_entity[V3D_TFU],
++ v3d_priv);
++ if (ret)
++ goto fail_unreserve;
++
++ sched_done_fence = dma_fence_get(&job->base.s_fence->finished);
++
++ kref_get(&job->refcount); /* put by scheduler job completion */
++ drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[V3D_TFU]);
++ mutex_unlock(&v3d->sched_lock);
++
++ v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);
++
++ v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
++
++ /* Update the return sync object */
++ sync_out = drm_syncobj_find(file_priv, args->out_sync);
++ if (sync_out) {
++ drm_syncobj_replace_fence(sync_out, sched_done_fence);
++ drm_syncobj_put(sync_out);
++ }
++ dma_fence_put(sched_done_fence);
++
++ v3d_tfu_job_put(job);
++
++ return 0;
++
++fail_unreserve:
++ mutex_unlock(&v3d->sched_lock);
++ v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
++fail:
++ v3d_tfu_job_put(job);
++
++ return ret;
++}
+
+ int
+ v3d_gem_init(struct drm_device *dev)
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -4,8 +4,8 @@
+ /**
+ * DOC: Interrupt management for the V3D engine
+ *
+- * When we take a binning or rendering flush done interrupt, we need
+- * to signal the fence for that job so that the scheduler can queue up
++ * When we take a bin, render, or TFU done interrupt, we need to
++ * signal the fence for that job so that the scheduler can queue up
+ * the next one and unblock any waiters.
+ *
+ * When we take the binner out of memory interrupt, we need to
+@@ -23,7 +23,8 @@
+
+ #define V3D_HUB_IRQS ((u32)(V3D_HUB_INT_MMU_WRV | \
+ V3D_HUB_INT_MMU_PTI | \
+- V3D_HUB_INT_MMU_CAP))
++ V3D_HUB_INT_MMU_CAP | \
++ V3D_HUB_INT_TFUC))
+
+ static void
+ v3d_overflow_mem_work(struct work_struct *work)
+@@ -117,6 +118,11 @@ v3d_hub_irq(int irq, void *arg)
+ /* Acknowledge the interrupts we're handling here. */
+ V3D_WRITE(V3D_HUB_INT_CLR, intsts);
+
++ if (intsts & V3D_HUB_INT_TFUC) {
++ dma_fence_signal(v3d->tfu_job->done_fence);
++ status = IRQ_HANDLED;
++ }
++
+ if (intsts & (V3D_HUB_INT_MMU_WRV |
+ V3D_HUB_INT_MMU_PTI |
+ V3D_HUB_INT_MMU_CAP)) {
+--- a/drivers/gpu/drm/v3d/v3d_regs.h
++++ b/drivers/gpu/drm/v3d/v3d_regs.h
+@@ -86,6 +86,55 @@
+ # define V3D_TOP_GR_BRIDGE_SW_INIT_1 0x0000c
+ # define V3D_TOP_GR_BRIDGE_SW_INIT_1_V3D_CLK_108_SW_INIT BIT(0)
+
++#define V3D_TFU_CS 0x00400
++/* Stops current job, empties input fifo. */
++# define V3D_TFU_CS_TFURST BIT(31)
++# define V3D_TFU_CS_CVTCT_MASK V3D_MASK(23, 16)
++# define V3D_TFU_CS_CVTCT_SHIFT 16
++# define V3D_TFU_CS_NFREE_MASK V3D_MASK(13, 8)
++# define V3D_TFU_CS_NFREE_SHIFT 8
++# define V3D_TFU_CS_BUSY BIT(0)
++
++#define V3D_TFU_SU 0x00404
++/* Interrupt when FINTTHR input slots are free (0 = disabled) */
++# define V3D_TFU_SU_FINTTHR_MASK V3D_MASK(13, 8)
++# define V3D_TFU_SU_FINTTHR_SHIFT 8
++/* Skips resetting the CRC at the start of CRC generation. */
++# define V3D_TFU_SU_CRCCHAIN BIT(4)
++/* skips writes, computes CRC of the image. miplevels must be 0. */
++# define V3D_TFU_SU_CRC BIT(3)
++# define V3D_TFU_SU_THROTTLE_MASK V3D_MASK(1, 0)
++# define V3D_TFU_SU_THROTTLE_SHIFT 0
++
++#define V3D_TFU_ICFG 0x00408
++/* Interrupt when the conversion is complete. */
++# define V3D_TFU_ICFG_IOC BIT(0)
++
++/* Input Image Address */
++#define V3D_TFU_IIA 0x0040c
++/* Input Chroma Address */
++#define V3D_TFU_ICA 0x00410
++/* Input Image Stride */
++#define V3D_TFU_IIS 0x00414
++/* Input Image U-Plane Address */
++#define V3D_TFU_IUA 0x00418
++/* Output Image Address */
++#define V3D_TFU_IOA 0x0041c
++/* Image Output Size */
++#define V3D_TFU_IOS 0x00420
++/* TFU YUV Coefficient 0 */
++#define V3D_TFU_COEF0 0x00424
++/* Use these regs instead of the defaults. */
++# define V3D_TFU_COEF0_USECOEF BIT(31)
++/* TFU YUV Coefficient 1 */
++#define V3D_TFU_COEF1 0x00428
++/* TFU YUV Coefficient 2 */
++#define V3D_TFU_COEF2 0x0042c
++/* TFU YUV Coefficient 3 */
++#define V3D_TFU_COEF3 0x00430
++
++#define V3D_TFU_CRC 0x00434
++
+ /* Per-MMU registers. */
+
+ #define V3D_MMUC_CONTROL 0x01000
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -30,6 +30,12 @@ to_v3d_job(struct drm_sched_job *sched_j
+ return container_of(sched_job, struct v3d_job, base);
+ }
+
++static struct v3d_tfu_job *
++to_tfu_job(struct drm_sched_job *sched_job)
++{
++ return container_of(sched_job, struct v3d_tfu_job, base);
++}
++
+ static void
+ v3d_job_free(struct drm_sched_job *sched_job)
+ {
+@@ -38,6 +44,14 @@ v3d_job_free(struct drm_sched_job *sched
+ v3d_exec_put(job->exec);
+ }
+
++static void
++v3d_tfu_job_free(struct drm_sched_job *sched_job)
++{
++ struct v3d_tfu_job *job = to_tfu_job(sched_job);
++
++ v3d_tfu_job_put(job);
++}
++
+ /**
+ * Returns the fences that the bin or render job depends on, one by one.
+ * v3d_job_run() won't be called until all of them have been signaled.
+@@ -76,6 +90,27 @@ v3d_job_dependency(struct drm_sched_job
+ return fence;
+ }
+
++/**
++ * Returns the fences that the TFU job depends on, one by one.
++ * v3d_tfu_job_run() won't be called until all of them have been
++ * signaled.
++ */
++static struct dma_fence *
++v3d_tfu_job_dependency(struct drm_sched_job *sched_job,
++ struct drm_sched_entity *s_entity)
++{
++ struct v3d_tfu_job *job = to_tfu_job(sched_job);
++ struct dma_fence *fence;
++
++ fence = job->in_fence;
++ if (fence) {
++ job->in_fence = NULL;
++ return fence;
++ }
++
++ return NULL;
++}
++
+ static struct dma_fence *v3d_job_run(struct drm_sched_job *sched_job)
+ {
+ struct v3d_job *job = to_v3d_job(sched_job);
+@@ -147,31 +182,47 @@ static struct dma_fence *v3d_job_run(str
+ return fence;
+ }
+
+-static void
+-v3d_job_timedout(struct drm_sched_job *sched_job)
++static struct dma_fence *
++v3d_tfu_job_run(struct drm_sched_job *sched_job)
+ {
+- struct v3d_job *job = to_v3d_job(sched_job);
+- struct v3d_exec_info *exec = job->exec;
+- struct v3d_dev *v3d = exec->v3d;
+- enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
+- enum v3d_queue q;
+- u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));
+- u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));
++ struct v3d_tfu_job *job = to_tfu_job(sched_job);
++ struct v3d_dev *v3d = job->v3d;
++ struct drm_device *dev = &v3d->drm;
++ struct dma_fence *fence;
+
+- /* If the current address or return address have changed, then
+- * the GPU has probably made progress and we should delay the
+- * reset. This could fail if the GPU got in an infinite loop
+- * in the CL, but that is pretty unlikely outside of an i-g-t
+- * testcase.
+- */
+- if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) {
+- job->timedout_ctca = ctca;
+- job->timedout_ctra = ctra;
++ fence = v3d_fence_create(v3d, V3D_TFU);
++ if (IS_ERR(fence))
++ return NULL;
+
+- schedule_delayed_work(&job->base.work_tdr,
+- job->base.sched->timeout);
+- return;
++ v3d->tfu_job = job;
++ if (job->done_fence)
++ dma_fence_put(job->done_fence);
++ job->done_fence = dma_fence_get(fence);
++
++ trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
++
++ V3D_WRITE(V3D_TFU_IIA, job->args.iia);
++ V3D_WRITE(V3D_TFU_IIS, job->args.iis);
++ V3D_WRITE(V3D_TFU_ICA, job->args.ica);
++ V3D_WRITE(V3D_TFU_IUA, job->args.iua);
++ V3D_WRITE(V3D_TFU_IOA, job->args.ioa);
++ V3D_WRITE(V3D_TFU_IOS, job->args.ios);
++ V3D_WRITE(V3D_TFU_COEF0, job->args.coef[0]);
++ if (job->args.coef[0] & V3D_TFU_COEF0_USECOEF) {
++ V3D_WRITE(V3D_TFU_COEF1, job->args.coef[1]);
++ V3D_WRITE(V3D_TFU_COEF2, job->args.coef[2]);
++ V3D_WRITE(V3D_TFU_COEF3, job->args.coef[3]);
+ }
++ /* ICFG kicks off the job. */
++ V3D_WRITE(V3D_TFU_ICFG, job->args.icfg | V3D_TFU_ICFG_IOC);
++
++ return fence;
++}
++
++static void
++v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job)
++{
++ enum v3d_queue q;
+
+ mutex_lock(&v3d->reset_lock);
+
+@@ -196,6 +247,41 @@ v3d_job_timedout(struct drm_sched_job *s
+ mutex_unlock(&v3d->reset_lock);
+ }
+
++static void
++v3d_job_timedout(struct drm_sched_job *sched_job)
++{
++ struct v3d_job *job = to_v3d_job(sched_job);
++ struct v3d_exec_info *exec = job->exec;
++ struct v3d_dev *v3d = exec->v3d;
++ enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
++ u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));
++ u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));
++
++ /* If the current address or return address have changed, then
++ * the GPU has probably made progress and we should delay the
++ * reset. This could fail if the GPU got in an infinite loop
++ * in the CL, but that is pretty unlikely outside of an i-g-t
++ * testcase.
++ */
++ if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) {
++ job->timedout_ctca = ctca;
++ job->timedout_ctra = ctra;
++ schedule_delayed_work(&job->base.work_tdr,
++ job->base.sched->timeout);
++ return;
++ }
++
++ v3d_gpu_reset_for_timeout(v3d, sched_job);
++}
++
++static void
++v3d_tfu_job_timedout(struct drm_sched_job *sched_job)
++{
++ struct v3d_tfu_job *job = to_tfu_job(sched_job);
++
++ v3d_gpu_reset_for_timeout(job->v3d, sched_job);
++}
++
+ static const struct drm_sched_backend_ops v3d_sched_ops = {
+ .dependency = v3d_job_dependency,
+ .run_job = v3d_job_run,
+@@ -203,6 +289,13 @@ static const struct drm_sched_backend_op
+ .free_job = v3d_job_free
+ };
+
++static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
++ .dependency = v3d_tfu_job_dependency,
++ .run_job = v3d_tfu_job_run,
++ .timedout_job = v3d_tfu_job_timedout,
++ .free_job = v3d_tfu_job_free
++};
++
+ int
+ v3d_sched_init(struct v3d_dev *v3d)
+ {
+@@ -232,6 +325,19 @@ v3d_sched_init(struct v3d_dev *v3d)
+ drm_sched_fini(&v3d->queue[V3D_BIN].sched);
+ return ret;
+ }
++
++ ret = drm_sched_init(&v3d->queue[V3D_TFU].sched,
++ &v3d_tfu_sched_ops,
++ hw_jobs_limit, job_hang_limit,
++ msecs_to_jiffies(hang_limit_ms),
++ "v3d_tfu");
++ if (ret) {
++ dev_err(v3d->dev, "Failed to create TFU scheduler: %d.",
++ ret);
++ drm_sched_fini(&v3d->queue[V3D_RENDER].sched);
++ drm_sched_fini(&v3d->queue[V3D_BIN].sched);
++ return ret;
++ }
+
+ return 0;
+ }
+--- a/drivers/gpu/drm/v3d/v3d_trace.h
++++ b/drivers/gpu/drm/v3d/v3d_trace.h
+@@ -42,6 +42,26 @@ TRACE_EVENT(v3d_submit_cl,
+ __entry->ctnqea)
+ );
+
++TRACE_EVENT(v3d_submit_tfu,
++ TP_PROTO(struct drm_device *dev,
++ uint64_t seqno),
++ TP_ARGS(dev, seqno),
++
++ TP_STRUCT__entry(
++ __field(u32, dev)
++ __field(u64, seqno)
++ ),
++
++ TP_fast_assign(
++ __entry->dev = dev->primary->index;
++ __entry->seqno = seqno;
++ ),
++
++ TP_printk("dev=%u, seqno=%llu",
++ __entry->dev,
++ __entry->seqno)
++);
++
+ TRACE_EVENT(v3d_reset_begin,
+ TP_PROTO(struct drm_device *dev),
+ TP_ARGS(dev),
+--- a/include/uapi/drm/v3d_drm.h
++++ b/include/uapi/drm/v3d_drm.h
+@@ -36,6 +36,7 @@ extern "C" {
+ #define DRM_V3D_MMAP_BO 0x03
+ #define DRM_V3D_GET_PARAM 0x04
+ #define DRM_V3D_GET_BO_OFFSET 0x05
++#define DRM_V3D_SUBMIT_TFU 0x06
+
+ #define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
+ #define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
+@@ -43,6 +44,7 @@ extern "C" {
+ #define DRM_IOCTL_V3D_MMAP_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_MMAP_BO, struct drm_v3d_mmap_bo)
+ #define DRM_IOCTL_V3D_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)
+ #define DRM_IOCTL_V3D_GET_BO_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
++#define DRM_IOCTL_V3D_SUBMIT_TFU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
+
+ /**
+ * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
+@@ -169,6 +171,7 @@ enum drm_v3d_param {
+ DRM_V3D_PARAM_V3D_CORE0_IDENT0,
+ DRM_V3D_PARAM_V3D_CORE0_IDENT1,
+ DRM_V3D_PARAM_V3D_CORE0_IDENT2,
++ DRM_V3D_PARAM_SUPPORTS_TFU,
+ };
+
+ struct drm_v3d_get_param {
+@@ -187,6 +190,28 @@ struct drm_v3d_get_bo_offset {
+ __u32 offset;
+ };
+
++struct drm_v3d_submit_tfu {
++ __u32 icfg;
++ __u32 iia;
++ __u32 iis;
++ __u32 ica;
++ __u32 iua;
++ __u32 ioa;
++ __u32 ios;
++ __u32 coef[4];
++ /* First handle is the output BO, following are other inputs.
++ * 0 for unused.
++ */
++ __u32 bo_handles[4];
++ /* sync object to block on before running the TFU job. Each TFU
++ * job will execute in the order submitted to its FD. Synchronization
++ * against rendering jobs requires using sync objects.
++ */
++ __u32 in_sync;
++ /* Sync object to signal when the TFU job is done. */
++ __u32 out_sync;
++};
++
+ #if defined(__cplusplus)
+ }
+ #endif
+++ /dev/null
-From d66b36c8443b24eab7512467095f7395d01f77de Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 28 Sep 2018 16:21:23 -0700
-Subject: [PATCH 566/703] drm/v3d: Fix a use-after-free race accessing the
- scheduler's fences.
-
-Once we push the job, the scheduler could run it and free it. So, if
-we want to reference their fences, we need to grab them before then.
-I haven't seen this happen in many days of conformance test runtime,
-but let's still close the race.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
-Link: https://patchwork.freedesktop.org/patch/254119/
-Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
-(cherry picked from commit 34c2c4f632f232ed2fdb66d4e42cc72d322273fe)
----
- drivers/gpu/drm/v3d/v3d_drv.h | 5 +++++
- drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++++--
- 2 files changed, 11 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -198,6 +198,11 @@ struct v3d_exec_info {
- */
- struct dma_fence *bin_done_fence;
-
-+ /* Fence for when the scheduler considers the render to be
-+ * done, for when the BOs reservations should be complete.
-+ */
-+ struct dma_fence *render_done_fence;
-+
- struct kref refcount;
-
- /* This is the array of BOs that were looked up at the start of exec. */
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -209,7 +209,7 @@ v3d_flush_caches(struct v3d_dev *v3d)
- static void
- v3d_attach_object_fences(struct v3d_exec_info *exec)
- {
-- struct dma_fence *out_fence = &exec->render.base.s_fence->finished;
-+ struct dma_fence *out_fence = exec->render_done_fence;
- struct v3d_bo *bo;
- int i;
-
-@@ -409,6 +409,7 @@ v3d_exec_cleanup(struct kref *ref)
- dma_fence_put(exec->render.done_fence);
-
- dma_fence_put(exec->bin_done_fence);
-+ dma_fence_put(exec->render_done_fence);
-
- for (i = 0; i < exec->bo_count; i++)
- drm_gem_object_put_unlocked(&exec->bo[i]->base);
-@@ -572,6 +573,9 @@ v3d_submit_cl_ioctl(struct drm_device *d
- if (ret)
- goto fail_unreserve;
-
-+ exec->render_done_fence =
-+ dma_fence_get(&exec->render.base.s_fence->finished);
-+
- kref_get(&exec->refcount); /* put by scheduler job completion */
- drm_sched_entity_push_job(&exec->render.base,
- &v3d_priv->sched_entity[V3D_RENDER]);
-@@ -585,7 +589,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
- sync_out = drm_syncobj_find(file_priv, args->out_sync);
- if (sync_out) {
- drm_syncobj_replace_fence(sync_out,
-- &exec->render.base.s_fence->finished);
-+ exec->render_done_fence);
- drm_syncobj_put(sync_out);
- }
-
+++ /dev/null
-From 50ecde652603895b0b0e22de62be36be47b83ab2 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 28 Sep 2018 16:21:24 -0700
-Subject: [PATCH 567/703] drm/v3d: Add a little debugfs entry for measuring the
- core clock.
-
-This adds just enough performance counter support to measure the
-clock. We don't have linux kernel drivers for the clock driving the
-HW, and this was useful for determining that the V3D HW is running on
-a slow clock, not that the driver was slow.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20180928232126.4332-2-eric@anholt.net
-Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
-(cherry picked from commit 6915c9a525e575732429c22b28eb11871a29374b)
----
- drivers/gpu/drm/v3d/v3d_debugfs.c | 35 +++++++++++++++++++++++++++++++
- drivers/gpu/drm/v3d/v3d_regs.h | 30 ++++++++++++++++++++++++++
- 2 files changed, 65 insertions(+)
-
---- a/drivers/gpu/drm/v3d/v3d_debugfs.c
-+++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
-@@ -179,9 +179,44 @@ static int v3d_debugfs_bo_stats(struct s
- return 0;
- }
-
-+static int v3d_measure_clock(struct seq_file *m, void *unused)
-+{
-+ struct drm_info_node *node = (struct drm_info_node *)m->private;
-+ struct drm_device *dev = node->minor->dev;
-+ struct v3d_dev *v3d = to_v3d_dev(dev);
-+ uint32_t cycles;
-+ int core = 0;
-+ int measure_ms = 1000;
-+
-+ if (v3d->ver >= 40) {
-+ V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3,
-+ V3D_SET_FIELD(V3D_PCTR_CYCLE_COUNT,
-+ V3D_PCTR_S0));
-+ V3D_CORE_WRITE(core, V3D_V4_PCTR_0_CLR, 1);
-+ V3D_CORE_WRITE(core, V3D_V4_PCTR_0_EN, 1);
-+ } else {
-+ V3D_CORE_WRITE(core, V3D_V3_PCTR_0_PCTRS0,
-+ V3D_PCTR_CYCLE_COUNT);
-+ V3D_CORE_WRITE(core, V3D_V3_PCTR_0_CLR, 1);
-+ V3D_CORE_WRITE(core, V3D_V3_PCTR_0_EN,
-+ V3D_V3_PCTR_0_EN_ENABLE |
-+ 1);
-+ }
-+ msleep(measure_ms);
-+ cycles = V3D_CORE_READ(core, V3D_PCTR_0_PCTR0);
-+
-+ seq_printf(m, "cycles: %d (%d.%d Mhz)\n",
-+ cycles,
-+ cycles / (measure_ms * 1000),
-+ (cycles / (measure_ms * 100)) % 10);
-+
-+ return 0;
-+}
-+
- static const struct drm_info_list v3d_debugfs_list[] = {
- {"v3d_ident", v3d_v3d_debugfs_ident, 0},
- {"v3d_regs", v3d_v3d_debugfs_regs, 0},
-+ {"measure_clock", v3d_measure_clock, 0},
- {"bo_stats", v3d_debugfs_bo_stats, 0},
- };
-
---- a/drivers/gpu/drm/v3d/v3d_regs.h
-+++ b/drivers/gpu/drm/v3d/v3d_regs.h
-@@ -267,6 +267,36 @@
- # define V3D_PTB_BXCF_RWORDERDISA BIT(1)
- # define V3D_PTB_BXCF_CLIPDISA BIT(0)
-
-+#define V3D_V3_PCTR_0_EN 0x00674
-+#define V3D_V3_PCTR_0_EN_ENABLE BIT(31)
-+#define V3D_V4_PCTR_0_EN 0x00650
-+/* When a bit is set, resets the counter to 0. */
-+#define V3D_V3_PCTR_0_CLR 0x00670
-+#define V3D_V4_PCTR_0_CLR 0x00654
-+#define V3D_PCTR_0_OVERFLOW 0x00658
-+
-+#define V3D_V3_PCTR_0_PCTRS0 0x00684
-+#define V3D_V3_PCTR_0_PCTRS15 0x00660
-+#define V3D_V3_PCTR_0_PCTRSX(x) (V3D_V3_PCTR_0_PCTRS0 + \
-+ 4 * (x))
-+/* Each src reg muxes four counters each. */
-+#define V3D_V4_PCTR_0_SRC_0_3 0x00660
-+#define V3D_V4_PCTR_0_SRC_28_31 0x0067c
-+# define V3D_PCTR_S0_MASK V3D_MASK(6, 0)
-+# define V3D_PCTR_S0_SHIFT 0
-+# define V3D_PCTR_S1_MASK V3D_MASK(14, 8)
-+# define V3D_PCTR_S1_SHIFT 8
-+# define V3D_PCTR_S2_MASK V3D_MASK(22, 16)
-+# define V3D_PCTR_S2_SHIFT 16
-+# define V3D_PCTR_S3_MASK V3D_MASK(30, 24)
-+# define V3D_PCTR_S3_SHIFT 24
-+# define V3D_PCTR_CYCLE_COUNT 32
-+
-+/* Output values of the counters. */
-+#define V3D_PCTR_0_PCTR0 0x00680
-+#define V3D_PCTR_0_PCTR31 0x006fc
-+#define V3D_PCTR_0_PCTRX(x) (V3D_PCTR_0_PCTR0 + \
-+ 4 * (x))
- #define V3D_GMP_STATUS 0x00800
- # define V3D_GMP_STATUS_GMPRST BIT(31)
- # define V3D_GMP_STATUS_WR_COUNT_MASK V3D_MASK(30, 24)
--- /dev/null
+From bf4cf0eca83106426162a548d788b1e2102e72bd Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 28 Nov 2018 15:09:26 -0800
+Subject: [PATCH 567/725] drm/v3d: Drop the "dev" argument to lock/unlock of BO
+ reservations.
+
+They were unused, as Dave Emett noticed in TFU review.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Cc: Dave Emett <david.emett@broadcom.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181128230927.10951-2-eric@anholt.net
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+(cherry picked from commit e14a07fc4b961a75f6c275d6bd670ba54fbdae14)
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -219,8 +219,7 @@ v3d_attach_object_fences(struct v3d_bo *
+ }
+
+ static void
+-v3d_unlock_bo_reservations(struct drm_device *dev,
+- struct v3d_bo **bos,
++v3d_unlock_bo_reservations(struct v3d_bo **bos,
+ int bo_count,
+ struct ww_acquire_ctx *acquire_ctx)
+ {
+@@ -240,8 +239,7 @@ v3d_unlock_bo_reservations(struct drm_de
+ * to v3d, so we don't attach dma-buf fences to them.
+ */
+ static int
+-v3d_lock_bo_reservations(struct drm_device *dev,
+- struct v3d_bo **bos,
++v3d_lock_bo_reservations(struct v3d_bo **bos,
+ int bo_count,
+ struct ww_acquire_ctx *acquire_ctx)
+ {
+@@ -298,7 +296,7 @@ retry:
+ for (i = 0; i < bo_count; i++) {
+ ret = reservation_object_reserve_shared(bos[i]->resv);
+ if (ret) {
+- v3d_unlock_bo_reservations(dev, bos, bo_count,
++ v3d_unlock_bo_reservations(bos, bo_count,
+ acquire_ctx);
+ return ret;
+ }
+@@ -566,7 +564,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ if (ret)
+ goto fail;
+
+- ret = v3d_lock_bo_reservations(dev, exec->bo, exec->bo_count,
++ ret = v3d_lock_bo_reservations(exec->bo, exec->bo_count,
+ &acquire_ctx);
+ if (ret)
+ goto fail;
+@@ -604,7 +602,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ v3d_attach_object_fences(exec->bo, exec->bo_count,
+ exec->render_done_fence);
+
+- v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
++ v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
+
+ /* Update the return sync object for the */
+ sync_out = drm_syncobj_find(file_priv, args->out_sync);
+@@ -620,7 +618,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
+
+ fail_unreserve:
+ mutex_unlock(&v3d->sched_lock);
+- v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
++ v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
+ fail:
+ v3d_exec_put(exec);
+
+@@ -691,7 +689,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
+ }
+ spin_unlock(&file_priv->table_lock);
+
+- ret = v3d_lock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
++ ret = v3d_lock_bo_reservations(job->bo, bo_count, &acquire_ctx);
+ if (ret)
+ goto fail;
+
+@@ -710,7 +708,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
+
+ v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);
+
+- v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
++ v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
+
+ /* Update the return sync object */
+ sync_out = drm_syncobj_find(file_priv, args->out_sync);
+@@ -726,7 +724,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
+
+ fail_unreserve:
+ mutex_unlock(&v3d->sched_lock);
+- v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
++ v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
+ fail:
+ v3d_tfu_job_put(job);
+
--- /dev/null
+From 14952ee8c73b05a062d1b7682a5919c5f0833a54 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 30 Nov 2018 16:57:59 -0800
+Subject: [PATCH 568/725] drm/v3d: Add missing fence timeline name for TFU.
+
+We shouldn't be returning v3d-render for our new queue.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Fixes: 83d5139982db ("drm/v3d: Add support for submitting jobs to the TFU.")
+Link: https://patchwork.freedesktop.org/patch/msgid/20181201005759.28093-6-eric@anholt.net
+Reviewed-by: Dave Emett <david.emett@broadcom.com>
+(cherry picked from commit db176f6ba1da39ad0016c77b9775a6bb3d0ce88a)
+---
+ drivers/gpu/drm/v3d/v3d_fence.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_fence.c
++++ b/drivers/gpu/drm/v3d/v3d_fence.c
+@@ -29,10 +29,16 @@ static const char *v3d_fence_get_timelin
+ {
+ struct v3d_fence *f = to_v3d_fence(fence);
+
+- if (f->queue == V3D_BIN)
++ switch (f->queue) {
++ case V3D_BIN:
+ return "v3d-bin";
+- else
++ case V3D_RENDER:
+ return "v3d-render";
++ case V3D_TFU:
++ return "v3d-tfu";
++ default:
++ return NULL;
++ }
+ }
+
+ const struct dma_fence_ops v3d_fence_ops = {
+++ /dev/null
-From 1ab9b7689ae0ba9d1f31c5da609004aa8c61a9ed Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 8 Nov 2018 08:16:52 -0800
-Subject: [PATCH 568/703] drm/v3d: Update a comment about what uses
- v3d_job_dependency().
-
-I merged bin and render's paths in a late refactoring.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181108161654.19888-3-eric@anholt.net
-Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
-(cherry picked from commit e90e45f6bd45cc494a6f4cd1853c5e7cd4be7f68)
----
- drivers/gpu/drm/v3d/v3d_sched.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/v3d/v3d_sched.c
-+++ b/drivers/gpu/drm/v3d/v3d_sched.c
-@@ -39,7 +39,7 @@ v3d_job_free(struct drm_sched_job *sched
- }
-
- /**
-- * Returns the fences that the bin job depends on, one by one.
-+ * Returns the fences that the bin or render job depends on, one by one.
- * v3d_job_run() won't be called until all of them have been signaled.
- */
- static struct dma_fence *
--- /dev/null
+From 5a2fcd01c138ce8bca696ca5c785290121cd4f93 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 30 Nov 2018 16:57:58 -0800
+Subject: [PATCH 569/725] drm/v3d: Add more tracepoints for V3D GPU rendering.
+
+The core scheduler tells us when the job is pushed to the scheduler's
+queue, and I had the job_run functions saying when they actually queue
+the job to the hardware. By adding tracepoints for the very top of
+the ioctls and the IRQs signaling job completion, "perf record -a -e
+v3d:.\* -e gpu_scheduler:.\* <job>; perf script" gets you a pretty
+decent timeline.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181201005759.28093-5-eric@anholt.net
+Reviewed-by: Dave Emett <david.emett@broadcom.com>
+(cherry picked from commit 55a9b74846ed5e6219c7d81a8e1bf96f25d8ad5e)
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 4 ++
+ drivers/gpu/drm/v3d/v3d_irq.c | 19 +++++-
+ drivers/gpu/drm/v3d/v3d_trace.h | 101 ++++++++++++++++++++++++++++++++
+ 3 files changed, 121 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -521,6 +521,8 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ struct drm_syncobj *sync_out;
+ int ret = 0;
+
++ trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
++
+ if (args->pad != 0) {
+ DRM_INFO("pad must be zero: %d\n", args->pad);
+ return -EINVAL;
+@@ -648,6 +650,8 @@ v3d_submit_tfu_ioctl(struct drm_device *
+ int ret = 0;
+ int bo_count;
+
++ trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia);
++
+ job = kcalloc(1, sizeof(*job), GFP_KERNEL);
+ if (!job)
+ return -ENOMEM;
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -15,6 +15,7 @@
+
+ #include "v3d_drv.h"
+ #include "v3d_regs.h"
++#include "v3d_trace.h"
+
+ #define V3D_CORE_IRQS ((u32)(V3D_INT_OUTOMEM | \
+ V3D_INT_FLDONE | \
+@@ -88,12 +89,20 @@ v3d_irq(int irq, void *arg)
+ }
+
+ if (intsts & V3D_INT_FLDONE) {
+- dma_fence_signal(v3d->bin_job->bin.done_fence);
++ struct v3d_fence *fence =
++ to_v3d_fence(v3d->bin_job->bin.done_fence);
++
++ trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
++ dma_fence_signal(&fence->base);
+ status = IRQ_HANDLED;
+ }
+
+ if (intsts & V3D_INT_FRDONE) {
+- dma_fence_signal(v3d->render_job->render.done_fence);
++ struct v3d_fence *fence =
++ to_v3d_fence(v3d->render_job->render.done_fence);
++
++ trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
++ dma_fence_signal(&fence->base);
+ status = IRQ_HANDLED;
+ }
+
+@@ -119,7 +128,11 @@ v3d_hub_irq(int irq, void *arg)
+ V3D_WRITE(V3D_HUB_INT_CLR, intsts);
+
+ if (intsts & V3D_HUB_INT_TFUC) {
+- dma_fence_signal(v3d->tfu_job->done_fence);
++ struct v3d_fence *fence =
++ to_v3d_fence(v3d->tfu_job->done_fence);
++
++ trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
++ dma_fence_signal(&fence->base);
+ status = IRQ_HANDLED;
+ }
+
+--- a/drivers/gpu/drm/v3d/v3d_trace.h
++++ b/drivers/gpu/drm/v3d/v3d_trace.h
+@@ -12,6 +12,28 @@
+ #define TRACE_SYSTEM v3d
+ #define TRACE_INCLUDE_FILE v3d_trace
+
++TRACE_EVENT(v3d_submit_cl_ioctl,
++ TP_PROTO(struct drm_device *dev, u32 ct1qba, u32 ct1qea),
++ TP_ARGS(dev, ct1qba, ct1qea),
++
++ TP_STRUCT__entry(
++ __field(u32, dev)
++ __field(u32, ct1qba)
++ __field(u32, ct1qea)
++ ),
++
++ TP_fast_assign(
++ __entry->dev = dev->primary->index;
++ __entry->ct1qba = ct1qba;
++ __entry->ct1qea = ct1qea;
++ ),
++
++ TP_printk("dev=%u, RCL 0x%08x..0x%08x",
++ __entry->dev,
++ __entry->ct1qba,
++ __entry->ct1qea)
++);
++
+ TRACE_EVENT(v3d_submit_cl,
+ TP_PROTO(struct drm_device *dev, bool is_render,
+ uint64_t seqno,
+@@ -42,6 +64,85 @@ TRACE_EVENT(v3d_submit_cl,
+ __entry->ctnqea)
+ );
+
++TRACE_EVENT(v3d_bcl_irq,
++ TP_PROTO(struct drm_device *dev,
++ uint64_t seqno),
++ TP_ARGS(dev, seqno),
++
++ TP_STRUCT__entry(
++ __field(u32, dev)
++ __field(u64, seqno)
++ ),
++
++ TP_fast_assign(
++ __entry->dev = dev->primary->index;
++ __entry->seqno = seqno;
++ ),
++
++ TP_printk("dev=%u, seqno=%llu",
++ __entry->dev,
++ __entry->seqno)
++);
++
++TRACE_EVENT(v3d_rcl_irq,
++ TP_PROTO(struct drm_device *dev,
++ uint64_t seqno),
++ TP_ARGS(dev, seqno),
++
++ TP_STRUCT__entry(
++ __field(u32, dev)
++ __field(u64, seqno)
++ ),
++
++ TP_fast_assign(
++ __entry->dev = dev->primary->index;
++ __entry->seqno = seqno;
++ ),
++
++ TP_printk("dev=%u, seqno=%llu",
++ __entry->dev,
++ __entry->seqno)
++);
++
++TRACE_EVENT(v3d_tfu_irq,
++ TP_PROTO(struct drm_device *dev,
++ uint64_t seqno),
++ TP_ARGS(dev, seqno),
++
++ TP_STRUCT__entry(
++ __field(u32, dev)
++ __field(u64, seqno)
++ ),
++
++ TP_fast_assign(
++ __entry->dev = dev->primary->index;
++ __entry->seqno = seqno;
++ ),
++
++ TP_printk("dev=%u, seqno=%llu",
++ __entry->dev,
++ __entry->seqno)
++);
++
++TRACE_EVENT(v3d_submit_tfu_ioctl,
++ TP_PROTO(struct drm_device *dev, u32 iia),
++ TP_ARGS(dev, iia),
++
++ TP_STRUCT__entry(
++ __field(u32, dev)
++ __field(u32, iia)
++ ),
++
++ TP_fast_assign(
++ __entry->dev = dev->primary->index;
++ __entry->iia = iia;
++ ),
++
++ TP_printk("dev=%u, IIA 0x%08x",
++ __entry->dev,
++ __entry->iia)
++);
++
+ TRACE_EVENT(v3d_submit_tfu,
+ TP_PROTO(struct drm_device *dev,
+ uint64_t seqno),
+++ /dev/null
-From cdc1e8a4116661a965c1021cd153a8a4fa8eee82 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 8 Nov 2018 08:16:53 -0800
-Subject: [PATCH 569/703] drm/v3d: Clean up the reservation object setup.
-
-The extra to_v3d_bo() calls came from copying this from the vc4
-driver, which stored the cma gem object in the structs.
-
-v2: Fix an unused var warning
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181108161654.19888-4-eric@anholt.net
-Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com> (v1)
-(cherry picked from commit 8f1cd826641d677d0f7494253ecfc3335f0bcd4e)
----
- drivers/gpu/drm/v3d/v3d_gem.c | 33 +++++++++++----------------------
- 1 file changed, 11 insertions(+), 22 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -210,14 +210,11 @@ static void
- v3d_attach_object_fences(struct v3d_exec_info *exec)
- {
- struct dma_fence *out_fence = exec->render_done_fence;
-- struct v3d_bo *bo;
- int i;
-
- for (i = 0; i < exec->bo_count; i++) {
-- bo = to_v3d_bo(&exec->bo[i]->base);
--
- /* XXX: Use shared fences for read-only objects. */
-- reservation_object_add_excl_fence(bo->resv, out_fence);
-+ reservation_object_add_excl_fence(exec->bo[i]->resv, out_fence);
- }
- }
-
-@@ -228,11 +225,8 @@ v3d_unlock_bo_reservations(struct drm_de
- {
- int i;
-
-- for (i = 0; i < exec->bo_count; i++) {
-- struct v3d_bo *bo = to_v3d_bo(&exec->bo[i]->base);
--
-- ww_mutex_unlock(&bo->resv->lock);
-- }
-+ for (i = 0; i < exec->bo_count; i++)
-+ ww_mutex_unlock(&exec->bo[i]->resv->lock);
-
- ww_acquire_fini(acquire_ctx);
- }
-@@ -251,13 +245,13 @@ v3d_lock_bo_reservations(struct drm_devi
- {
- int contended_lock = -1;
- int i, ret;
-- struct v3d_bo *bo;
-
- ww_acquire_init(acquire_ctx, &reservation_ww_class);
-
- retry:
- if (contended_lock != -1) {
-- bo = to_v3d_bo(&exec->bo[contended_lock]->base);
-+ struct v3d_bo *bo = exec->bo[contended_lock];
-+
- ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
- acquire_ctx);
- if (ret) {
-@@ -270,19 +264,16 @@ retry:
- if (i == contended_lock)
- continue;
-
-- bo = to_v3d_bo(&exec->bo[i]->base);
--
-- ret = ww_mutex_lock_interruptible(&bo->resv->lock, acquire_ctx);
-+ ret = ww_mutex_lock_interruptible(&exec->bo[i]->resv->lock,
-+ acquire_ctx);
- if (ret) {
- int j;
-
-- for (j = 0; j < i; j++) {
-- bo = to_v3d_bo(&exec->bo[j]->base);
-- ww_mutex_unlock(&bo->resv->lock);
-- }
-+ for (j = 0; j < i; j++)
-+ ww_mutex_unlock(&exec->bo[j]->resv->lock);
-
- if (contended_lock != -1 && contended_lock >= i) {
-- bo = to_v3d_bo(&exec->bo[contended_lock]->base);
-+ struct v3d_bo *bo = exec->bo[contended_lock];
-
- ww_mutex_unlock(&bo->resv->lock);
- }
-@@ -303,9 +294,7 @@ retry:
- * before we commit the CL to the hardware.
- */
- for (i = 0; i < exec->bo_count; i++) {
-- bo = to_v3d_bo(&exec->bo[i]->base);
--
-- ret = reservation_object_reserve_shared(bo->resv);
-+ ret = reservation_object_reserve_shared(exec->bo[i]->resv);
- if (ret) {
- v3d_unlock_bo_reservations(dev, exec, acquire_ctx);
- return ret;
+++ /dev/null
-From 60c65dc612663be7136a19a117cee5d194530600 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 28 Nov 2018 15:09:25 -0800
-Subject: [PATCH 570/703] drm/v3d: Add support for submitting jobs to the TFU.
-
-The TFU can copy from raster, UIF, and SAND input images to UIF output
-images, with optional mipmap generation. This will certainly be
-useful for media EGL image input, but is also useful immediately for
-mipmap generation without bogging the V3D core down.
-
-For now we only run the queue 1 job deep, and don't have any hang
-recovery (though I don't think we should need it, with TFU). Queuing
-multiple jobs in the HW will require synchronizing the YUV coefficient
-regs updates since they don't get FIFOed with the job.
-
-v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
- why TFU is AUTH, clarify the syncing docs, drop the unused TFU
- interrupt regs (you're expected to use the hub's), don't take
- &bo->base for NULL bos.
-v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
- on drm_sched_job_cleanup() changes.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
-Link: https://patchwork.freedesktop.org/patch/264607/
-(cherry picked from commit 1584f16ca96ef124aad79efa3303cff5f3530e2c)
----
- drivers/gpu/drm/v3d/v3d_drv.c | 15 ++-
- drivers/gpu/drm/v3d/v3d_drv.h | 32 +++++-
- drivers/gpu/drm/v3d/v3d_gem.c | 178 ++++++++++++++++++++++++++++----
- drivers/gpu/drm/v3d/v3d_irq.c | 12 ++-
- drivers/gpu/drm/v3d/v3d_regs.h | 49 +++++++++
- drivers/gpu/drm/v3d/v3d_sched.c | 148 ++++++++++++++++++++++----
- drivers/gpu/drm/v3d/v3d_trace.h | 20 ++++
- include/uapi/drm/v3d_drm.h | 25 +++++
- 8 files changed, 426 insertions(+), 53 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -112,10 +112,15 @@ static int v3d_get_param_ioctl(struct dr
- return 0;
- }
-
-- /* Any params that aren't just register reads would go here. */
-
-- DRM_DEBUG("Unknown parameter %d\n", args->param);
-- return -EINVAL;
-+ switch (args->param) {
-+ case DRM_V3D_PARAM_SUPPORTS_TFU:
-+ args->value = 1;
-+ return 0;
-+ default:
-+ DRM_DEBUG("Unknown parameter %d\n", args->param);
-+ return -EINVAL;
-+ }
- }
-
- static int
-@@ -170,7 +175,8 @@ static const struct file_operations v3d_
- /* DRM_AUTH is required on SUBMIT_CL for now, while we don't have GMP
- * protection between clients. Note that render nodes would be be
- * able to submit CLs that could access BOs from clients authenticated
-- * with the master node.
-+ * with the master node. The TFU doesn't use the GMP, so it would
-+ * need to stay DRM_AUTH until we do buffer size/offset validation.
- */
- static const struct drm_ioctl_desc v3d_drm_ioctls[] = {
- DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CL, v3d_submit_cl_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
-@@ -179,6 +185,7 @@ static const struct drm_ioctl_desc v3d_d
- DRM_IOCTL_DEF_DRV(V3D_MMAP_BO, v3d_mmap_bo_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(V3D_GET_PARAM, v3d_get_param_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(V3D_GET_BO_OFFSET, v3d_get_bo_offset_ioctl, DRM_RENDER_ALLOW),
-+ DRM_IOCTL_DEF_DRV(V3D_SUBMIT_TFU, v3d_submit_tfu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
- };
-
- static const struct vm_operations_struct v3d_vm_ops = {
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -7,19 +7,18 @@
- #include <drm/drm_encoder.h>
- #include <drm/drm_gem.h>
- #include <drm/gpu_scheduler.h>
-+#include "uapi/drm/v3d_drm.h"
-
- #define GMP_GRANULARITY (128 * 1024)
-
--/* Enum for each of the V3D queues. We maintain various queue
-- * tracking as an array because at some point we'll want to support
-- * the TFU (texture formatting unit) as another queue.
-- */
-+/* Enum for each of the V3D queues. */
- enum v3d_queue {
- V3D_BIN,
- V3D_RENDER,
-+ V3D_TFU,
- };
-
--#define V3D_MAX_QUEUES (V3D_RENDER + 1)
-+#define V3D_MAX_QUEUES (V3D_TFU + 1)
-
- struct v3d_queue_state {
- struct drm_gpu_scheduler sched;
-@@ -68,6 +67,7 @@ struct v3d_dev {
-
- struct v3d_exec_info *bin_job;
- struct v3d_exec_info *render_job;
-+ struct v3d_tfu_job *tfu_job;
-
- struct v3d_queue_state queue[V3D_MAX_QUEUES];
-
-@@ -218,6 +218,25 @@ struct v3d_exec_info {
- u32 qma, qms, qts;
- };
-
-+struct v3d_tfu_job {
-+ struct drm_sched_job base;
-+
-+ struct drm_v3d_submit_tfu args;
-+
-+ /* An optional fence userspace can pass in for the job to depend on. */
-+ struct dma_fence *in_fence;
-+
-+ /* v3d fence to be signaled by IRQ handler when the job is complete. */
-+ struct dma_fence *done_fence;
-+
-+ struct v3d_dev *v3d;
-+
-+ struct kref refcount;
-+
-+ /* This is the array of BOs that were looked up at the start of exec. */
-+ struct v3d_bo *bo[4];
-+};
-+
- /**
- * _wait_for - magic (register) wait macro
- *
-@@ -281,9 +300,12 @@ int v3d_gem_init(struct drm_device *dev)
- void v3d_gem_destroy(struct drm_device *dev);
- int v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-+int v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
-+ struct drm_file *file_priv);
- int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
- void v3d_exec_put(struct v3d_exec_info *exec);
-+void v3d_tfu_job_put(struct v3d_tfu_job *exec);
- void v3d_reset(struct v3d_dev *v3d);
- void v3d_invalidate_caches(struct v3d_dev *v3d);
- void v3d_flush_caches(struct v3d_dev *v3d);
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -207,26 +207,27 @@ v3d_flush_caches(struct v3d_dev *v3d)
- }
-
- static void
--v3d_attach_object_fences(struct v3d_exec_info *exec)
-+v3d_attach_object_fences(struct v3d_bo **bos, int bo_count,
-+ struct dma_fence *fence)
- {
-- struct dma_fence *out_fence = exec->render_done_fence;
- int i;
-
-- for (i = 0; i < exec->bo_count; i++) {
-+ for (i = 0; i < bo_count; i++) {
- /* XXX: Use shared fences for read-only objects. */
-- reservation_object_add_excl_fence(exec->bo[i]->resv, out_fence);
-+ reservation_object_add_excl_fence(bos[i]->resv, fence);
- }
- }
-
- static void
- v3d_unlock_bo_reservations(struct drm_device *dev,
-- struct v3d_exec_info *exec,
-+ struct v3d_bo **bos,
-+ int bo_count,
- struct ww_acquire_ctx *acquire_ctx)
- {
- int i;
-
-- for (i = 0; i < exec->bo_count; i++)
-- ww_mutex_unlock(&exec->bo[i]->resv->lock);
-+ for (i = 0; i < bo_count; i++)
-+ ww_mutex_unlock(&bos[i]->resv->lock);
-
- ww_acquire_fini(acquire_ctx);
- }
-@@ -240,7 +241,8 @@ v3d_unlock_bo_reservations(struct drm_de
- */
- static int
- v3d_lock_bo_reservations(struct drm_device *dev,
-- struct v3d_exec_info *exec,
-+ struct v3d_bo **bos,
-+ int bo_count,
- struct ww_acquire_ctx *acquire_ctx)
- {
- int contended_lock = -1;
-@@ -250,7 +252,7 @@ v3d_lock_bo_reservations(struct drm_devi
-
- retry:
- if (contended_lock != -1) {
-- struct v3d_bo *bo = exec->bo[contended_lock];
-+ struct v3d_bo *bo = bos[contended_lock];
-
- ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
- acquire_ctx);
-@@ -260,20 +262,20 @@ retry:
- }
- }
-
-- for (i = 0; i < exec->bo_count; i++) {
-+ for (i = 0; i < bo_count; i++) {
- if (i == contended_lock)
- continue;
-
-- ret = ww_mutex_lock_interruptible(&exec->bo[i]->resv->lock,
-+ ret = ww_mutex_lock_interruptible(&bos[i]->resv->lock,
- acquire_ctx);
- if (ret) {
- int j;
-
- for (j = 0; j < i; j++)
-- ww_mutex_unlock(&exec->bo[j]->resv->lock);
-+ ww_mutex_unlock(&bos[j]->resv->lock);
-
- if (contended_lock != -1 && contended_lock >= i) {
-- struct v3d_bo *bo = exec->bo[contended_lock];
-+ struct v3d_bo *bo = bos[contended_lock];
-
- ww_mutex_unlock(&bo->resv->lock);
- }
-@@ -293,10 +295,11 @@ retry:
- /* Reserve space for our shared (read-only) fence references,
- * before we commit the CL to the hardware.
- */
-- for (i = 0; i < exec->bo_count; i++) {
-- ret = reservation_object_reserve_shared(exec->bo[i]->resv);
-+ for (i = 0; i < bo_count; i++) {
-+ ret = reservation_object_reserve_shared(bos[i]->resv);
- if (ret) {
-- v3d_unlock_bo_reservations(dev, exec, acquire_ctx);
-+ v3d_unlock_bo_reservations(dev, bos, bo_count,
-+ acquire_ctx);
- return ret;
- }
- }
-@@ -419,6 +422,33 @@ void v3d_exec_put(struct v3d_exec_info *
- kref_put(&exec->refcount, v3d_exec_cleanup);
- }
-
-+static void
-+v3d_tfu_job_cleanup(struct kref *ref)
-+{
-+ struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,
-+ refcount);
-+ struct v3d_dev *v3d = job->v3d;
-+ unsigned int i;
-+
-+ dma_fence_put(job->in_fence);
-+ dma_fence_put(job->done_fence);
-+
-+ for (i = 0; i < ARRAY_SIZE(job->bo); i++) {
-+ if (job->bo[i])
-+ drm_gem_object_put_unlocked(&job->bo[i]->base);
-+ }
-+
-+ pm_runtime_mark_last_busy(v3d->dev);
-+ pm_runtime_put_autosuspend(v3d->dev);
-+
-+ kfree(job);
-+}
-+
-+void v3d_tfu_job_put(struct v3d_tfu_job *job)
-+{
-+ kref_put(&job->refcount, v3d_tfu_job_cleanup);
-+}
-+
- int
- v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-@@ -536,7 +566,8 @@ v3d_submit_cl_ioctl(struct drm_device *d
- if (ret)
- goto fail;
-
-- ret = v3d_lock_bo_reservations(dev, exec, &acquire_ctx);
-+ ret = v3d_lock_bo_reservations(dev, exec->bo, exec->bo_count,
-+ &acquire_ctx);
- if (ret)
- goto fail;
-
-@@ -570,9 +601,10 @@ v3d_submit_cl_ioctl(struct drm_device *d
- &v3d_priv->sched_entity[V3D_RENDER]);
- mutex_unlock(&v3d->sched_lock);
-
-- v3d_attach_object_fences(exec);
-+ v3d_attach_object_fences(exec->bo, exec->bo_count,
-+ exec->render_done_fence);
-
-- v3d_unlock_bo_reservations(dev, exec, &acquire_ctx);
-+ v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
-
- /* Update the return sync object for the */
- sync_out = drm_syncobj_find(file_priv, args->out_sync);
-@@ -588,12 +620,118 @@ v3d_submit_cl_ioctl(struct drm_device *d
-
- fail_unreserve:
- mutex_unlock(&v3d->sched_lock);
-- v3d_unlock_bo_reservations(dev, exec, &acquire_ctx);
-+ v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
- fail:
- v3d_exec_put(exec);
-
- return ret;
- }
-+
-+/**
-+ * v3d_submit_tfu_ioctl() - Submits a TFU (texture formatting) job to the V3D.
-+ * @dev: DRM device
-+ * @data: ioctl argument
-+ * @file_priv: DRM file for this fd
-+ *
-+ * Userspace provides the register setup for the TFU, which we don't
-+ * need to validate since the TFU is behind the MMU.
-+ */
-+int
-+v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
-+ struct drm_file *file_priv)
-+{
-+ struct v3d_dev *v3d = to_v3d_dev(dev);
-+ struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
-+ struct drm_v3d_submit_tfu *args = data;
-+ struct v3d_tfu_job *job;
-+ struct ww_acquire_ctx acquire_ctx;
-+ struct drm_syncobj *sync_out;
-+ struct dma_fence *sched_done_fence;
-+ int ret = 0;
-+ int bo_count;
-+
-+ job = kcalloc(1, sizeof(*job), GFP_KERNEL);
-+ if (!job)
-+ return -ENOMEM;
-+
-+ ret = pm_runtime_get_sync(v3d->dev);
-+ if (ret < 0) {
-+ kfree(job);
-+ return ret;
-+ }
-+
-+ kref_init(&job->refcount);
-+
-+ ret = drm_syncobj_find_fence(file_priv, args->in_sync,
-+ 0, &job->in_fence);
-+ if (ret == -EINVAL)
-+ goto fail;
-+
-+ job->args = *args;
-+ job->v3d = v3d;
-+
-+ spin_lock(&file_priv->table_lock);
-+ for (bo_count = 0; bo_count < ARRAY_SIZE(job->bo); bo_count++) {
-+ struct drm_gem_object *bo;
-+
-+ if (!args->bo_handles[bo_count])
-+ break;
-+
-+ bo = idr_find(&file_priv->object_idr,
-+ args->bo_handles[bo_count]);
-+ if (!bo) {
-+ DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
-+ bo_count, args->bo_handles[bo_count]);
-+ ret = -ENOENT;
-+ spin_unlock(&file_priv->table_lock);
-+ goto fail;
-+ }
-+ drm_gem_object_get(bo);
-+ job->bo[bo_count] = to_v3d_bo(bo);
-+ }
-+ spin_unlock(&file_priv->table_lock);
-+
-+ ret = v3d_lock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
-+ if (ret)
-+ goto fail;
-+
-+ mutex_lock(&v3d->sched_lock);
-+ ret = drm_sched_job_init(&job->base,
-+ &v3d_priv->sched_entity[V3D_TFU],
-+ v3d_priv);
-+ if (ret)
-+ goto fail_unreserve;
-+
-+ sched_done_fence = dma_fence_get(&job->base.s_fence->finished);
-+
-+ kref_get(&job->refcount); /* put by scheduler job completion */
-+ drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[V3D_TFU]);
-+ mutex_unlock(&v3d->sched_lock);
-+
-+ v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);
-+
-+ v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
-+
-+ /* Update the return sync object */
-+ sync_out = drm_syncobj_find(file_priv, args->out_sync);
-+ if (sync_out) {
-+ drm_syncobj_replace_fence(sync_out, sched_done_fence);
-+ drm_syncobj_put(sync_out);
-+ }
-+ dma_fence_put(sched_done_fence);
-+
-+ v3d_tfu_job_put(job);
-+
-+ return 0;
-+
-+fail_unreserve:
-+ mutex_unlock(&v3d->sched_lock);
-+ v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
-+fail:
-+ v3d_tfu_job_put(job);
-+
-+ return ret;
-+}
-
- int
- v3d_gem_init(struct drm_device *dev)
---- a/drivers/gpu/drm/v3d/v3d_irq.c
-+++ b/drivers/gpu/drm/v3d/v3d_irq.c
-@@ -4,8 +4,8 @@
- /**
- * DOC: Interrupt management for the V3D engine
- *
-- * When we take a binning or rendering flush done interrupt, we need
-- * to signal the fence for that job so that the scheduler can queue up
-+ * When we take a bin, render, or TFU done interrupt, we need to
-+ * signal the fence for that job so that the scheduler can queue up
- * the next one and unblock any waiters.
- *
- * When we take the binner out of memory interrupt, we need to
-@@ -23,7 +23,8 @@
-
- #define V3D_HUB_IRQS ((u32)(V3D_HUB_INT_MMU_WRV | \
- V3D_HUB_INT_MMU_PTI | \
-- V3D_HUB_INT_MMU_CAP))
-+ V3D_HUB_INT_MMU_CAP | \
-+ V3D_HUB_INT_TFUC))
-
- static void
- v3d_overflow_mem_work(struct work_struct *work)
-@@ -117,6 +118,11 @@ v3d_hub_irq(int irq, void *arg)
- /* Acknowledge the interrupts we're handling here. */
- V3D_WRITE(V3D_HUB_INT_CLR, intsts);
-
-+ if (intsts & V3D_HUB_INT_TFUC) {
-+ dma_fence_signal(v3d->tfu_job->done_fence);
-+ status = IRQ_HANDLED;
-+ }
-+
- if (intsts & (V3D_HUB_INT_MMU_WRV |
- V3D_HUB_INT_MMU_PTI |
- V3D_HUB_INT_MMU_CAP)) {
---- a/drivers/gpu/drm/v3d/v3d_regs.h
-+++ b/drivers/gpu/drm/v3d/v3d_regs.h
-@@ -86,6 +86,55 @@
- # define V3D_TOP_GR_BRIDGE_SW_INIT_1 0x0000c
- # define V3D_TOP_GR_BRIDGE_SW_INIT_1_V3D_CLK_108_SW_INIT BIT(0)
-
-+#define V3D_TFU_CS 0x00400
-+/* Stops current job, empties input fifo. */
-+# define V3D_TFU_CS_TFURST BIT(31)
-+# define V3D_TFU_CS_CVTCT_MASK V3D_MASK(23, 16)
-+# define V3D_TFU_CS_CVTCT_SHIFT 16
-+# define V3D_TFU_CS_NFREE_MASK V3D_MASK(13, 8)
-+# define V3D_TFU_CS_NFREE_SHIFT 8
-+# define V3D_TFU_CS_BUSY BIT(0)
-+
-+#define V3D_TFU_SU 0x00404
-+/* Interrupt when FINTTHR input slots are free (0 = disabled) */
-+# define V3D_TFU_SU_FINTTHR_MASK V3D_MASK(13, 8)
-+# define V3D_TFU_SU_FINTTHR_SHIFT 8
-+/* Skips resetting the CRC at the start of CRC generation. */
-+# define V3D_TFU_SU_CRCCHAIN BIT(4)
-+/* skips writes, computes CRC of the image. miplevels must be 0. */
-+# define V3D_TFU_SU_CRC BIT(3)
-+# define V3D_TFU_SU_THROTTLE_MASK V3D_MASK(1, 0)
-+# define V3D_TFU_SU_THROTTLE_SHIFT 0
-+
-+#define V3D_TFU_ICFG 0x00408
-+/* Interrupt when the conversion is complete. */
-+# define V3D_TFU_ICFG_IOC BIT(0)
-+
-+/* Input Image Address */
-+#define V3D_TFU_IIA 0x0040c
-+/* Input Chroma Address */
-+#define V3D_TFU_ICA 0x00410
-+/* Input Image Stride */
-+#define V3D_TFU_IIS 0x00414
-+/* Input Image U-Plane Address */
-+#define V3D_TFU_IUA 0x00418
-+/* Output Image Address */
-+#define V3D_TFU_IOA 0x0041c
-+/* Image Output Size */
-+#define V3D_TFU_IOS 0x00420
-+/* TFU YUV Coefficient 0 */
-+#define V3D_TFU_COEF0 0x00424
-+/* Use these regs instead of the defaults. */
-+# define V3D_TFU_COEF0_USECOEF BIT(31)
-+/* TFU YUV Coefficient 1 */
-+#define V3D_TFU_COEF1 0x00428
-+/* TFU YUV Coefficient 2 */
-+#define V3D_TFU_COEF2 0x0042c
-+/* TFU YUV Coefficient 3 */
-+#define V3D_TFU_COEF3 0x00430
-+
-+#define V3D_TFU_CRC 0x00434
-+
- /* Per-MMU registers. */
-
- #define V3D_MMUC_CONTROL 0x01000
---- a/drivers/gpu/drm/v3d/v3d_sched.c
-+++ b/drivers/gpu/drm/v3d/v3d_sched.c
-@@ -30,6 +30,12 @@ to_v3d_job(struct drm_sched_job *sched_j
- return container_of(sched_job, struct v3d_job, base);
- }
-
-+static struct v3d_tfu_job *
-+to_tfu_job(struct drm_sched_job *sched_job)
-+{
-+ return container_of(sched_job, struct v3d_tfu_job, base);
-+}
-+
- static void
- v3d_job_free(struct drm_sched_job *sched_job)
- {
-@@ -38,6 +44,14 @@ v3d_job_free(struct drm_sched_job *sched
- v3d_exec_put(job->exec);
- }
-
-+static void
-+v3d_tfu_job_free(struct drm_sched_job *sched_job)
-+{
-+ struct v3d_tfu_job *job = to_tfu_job(sched_job);
-+
-+ v3d_tfu_job_put(job);
-+}
-+
- /**
- * Returns the fences that the bin or render job depends on, one by one.
- * v3d_job_run() won't be called until all of them have been signaled.
-@@ -76,6 +90,27 @@ v3d_job_dependency(struct drm_sched_job
- return fence;
- }
-
-+/**
-+ * Returns the fences that the TFU job depends on, one by one.
-+ * v3d_tfu_job_run() won't be called until all of them have been
-+ * signaled.
-+ */
-+static struct dma_fence *
-+v3d_tfu_job_dependency(struct drm_sched_job *sched_job,
-+ struct drm_sched_entity *s_entity)
-+{
-+ struct v3d_tfu_job *job = to_tfu_job(sched_job);
-+ struct dma_fence *fence;
-+
-+ fence = job->in_fence;
-+ if (fence) {
-+ job->in_fence = NULL;
-+ return fence;
-+ }
-+
-+ return NULL;
-+}
-+
- static struct dma_fence *v3d_job_run(struct drm_sched_job *sched_job)
- {
- struct v3d_job *job = to_v3d_job(sched_job);
-@@ -147,31 +182,47 @@ static struct dma_fence *v3d_job_run(str
- return fence;
- }
-
--static void
--v3d_job_timedout(struct drm_sched_job *sched_job)
-+static struct dma_fence *
-+v3d_tfu_job_run(struct drm_sched_job *sched_job)
- {
-- struct v3d_job *job = to_v3d_job(sched_job);
-- struct v3d_exec_info *exec = job->exec;
-- struct v3d_dev *v3d = exec->v3d;
-- enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
-- enum v3d_queue q;
-- u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));
-- u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));
-+ struct v3d_tfu_job *job = to_tfu_job(sched_job);
-+ struct v3d_dev *v3d = job->v3d;
-+ struct drm_device *dev = &v3d->drm;
-+ struct dma_fence *fence;
-
-- /* If the current address or return address have changed, then
-- * the GPU has probably made progress and we should delay the
-- * reset. This could fail if the GPU got in an infinite loop
-- * in the CL, but that is pretty unlikely outside of an i-g-t
-- * testcase.
-- */
-- if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) {
-- job->timedout_ctca = ctca;
-- job->timedout_ctra = ctra;
-+ fence = v3d_fence_create(v3d, V3D_TFU);
-+ if (IS_ERR(fence))
-+ return NULL;
-
-- schedule_delayed_work(&job->base.work_tdr,
-- job->base.sched->timeout);
-- return;
-+ v3d->tfu_job = job;
-+ if (job->done_fence)
-+ dma_fence_put(job->done_fence);
-+ job->done_fence = dma_fence_get(fence);
-+
-+ trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
-+
-+ V3D_WRITE(V3D_TFU_IIA, job->args.iia);
-+ V3D_WRITE(V3D_TFU_IIS, job->args.iis);
-+ V3D_WRITE(V3D_TFU_ICA, job->args.ica);
-+ V3D_WRITE(V3D_TFU_IUA, job->args.iua);
-+ V3D_WRITE(V3D_TFU_IOA, job->args.ioa);
-+ V3D_WRITE(V3D_TFU_IOS, job->args.ios);
-+ V3D_WRITE(V3D_TFU_COEF0, job->args.coef[0]);
-+ if (job->args.coef[0] & V3D_TFU_COEF0_USECOEF) {
-+ V3D_WRITE(V3D_TFU_COEF1, job->args.coef[1]);
-+ V3D_WRITE(V3D_TFU_COEF2, job->args.coef[2]);
-+ V3D_WRITE(V3D_TFU_COEF3, job->args.coef[3]);
- }
-+ /* ICFG kicks off the job. */
-+ V3D_WRITE(V3D_TFU_ICFG, job->args.icfg | V3D_TFU_ICFG_IOC);
-+
-+ return fence;
-+}
-+
-+static void
-+v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job)
-+{
-+ enum v3d_queue q;
-
- mutex_lock(&v3d->reset_lock);
-
-@@ -196,6 +247,41 @@ v3d_job_timedout(struct drm_sched_job *s
- mutex_unlock(&v3d->reset_lock);
- }
-
-+static void
-+v3d_job_timedout(struct drm_sched_job *sched_job)
-+{
-+ struct v3d_job *job = to_v3d_job(sched_job);
-+ struct v3d_exec_info *exec = job->exec;
-+ struct v3d_dev *v3d = exec->v3d;
-+ enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
-+ u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));
-+ u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));
-+
-+ /* If the current address or return address have changed, then
-+ * the GPU has probably made progress and we should delay the
-+ * reset. This could fail if the GPU got in an infinite loop
-+ * in the CL, but that is pretty unlikely outside of an i-g-t
-+ * testcase.
-+ */
-+ if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) {
-+ job->timedout_ctca = ctca;
-+ job->timedout_ctra = ctra;
-+ schedule_delayed_work(&job->base.work_tdr,
-+ job->base.sched->timeout);
-+ return;
-+ }
-+
-+ v3d_gpu_reset_for_timeout(v3d, sched_job);
-+}
-+
-+static void
-+v3d_tfu_job_timedout(struct drm_sched_job *sched_job)
-+{
-+ struct v3d_tfu_job *job = to_tfu_job(sched_job);
-+
-+ v3d_gpu_reset_for_timeout(job->v3d, sched_job);
-+}
-+
- static const struct drm_sched_backend_ops v3d_sched_ops = {
- .dependency = v3d_job_dependency,
- .run_job = v3d_job_run,
-@@ -203,6 +289,13 @@ static const struct drm_sched_backend_op
- .free_job = v3d_job_free
- };
-
-+static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
-+ .dependency = v3d_tfu_job_dependency,
-+ .run_job = v3d_tfu_job_run,
-+ .timedout_job = v3d_tfu_job_timedout,
-+ .free_job = v3d_tfu_job_free
-+};
-+
- int
- v3d_sched_init(struct v3d_dev *v3d)
- {
-@@ -232,6 +325,19 @@ v3d_sched_init(struct v3d_dev *v3d)
- drm_sched_fini(&v3d->queue[V3D_BIN].sched);
- return ret;
- }
-+
-+ ret = drm_sched_init(&v3d->queue[V3D_TFU].sched,
-+ &v3d_tfu_sched_ops,
-+ hw_jobs_limit, job_hang_limit,
-+ msecs_to_jiffies(hang_limit_ms),
-+ "v3d_tfu");
-+ if (ret) {
-+ dev_err(v3d->dev, "Failed to create TFU scheduler: %d.",
-+ ret);
-+ drm_sched_fini(&v3d->queue[V3D_RENDER].sched);
-+ drm_sched_fini(&v3d->queue[V3D_BIN].sched);
-+ return ret;
-+ }
-
- return 0;
- }
---- a/drivers/gpu/drm/v3d/v3d_trace.h
-+++ b/drivers/gpu/drm/v3d/v3d_trace.h
-@@ -42,6 +42,26 @@ TRACE_EVENT(v3d_submit_cl,
- __entry->ctnqea)
- );
-
-+TRACE_EVENT(v3d_submit_tfu,
-+ TP_PROTO(struct drm_device *dev,
-+ uint64_t seqno),
-+ TP_ARGS(dev, seqno),
-+
-+ TP_STRUCT__entry(
-+ __field(u32, dev)
-+ __field(u64, seqno)
-+ ),
-+
-+ TP_fast_assign(
-+ __entry->dev = dev->primary->index;
-+ __entry->seqno = seqno;
-+ ),
-+
-+ TP_printk("dev=%u, seqno=%llu",
-+ __entry->dev,
-+ __entry->seqno)
-+);
-+
- TRACE_EVENT(v3d_reset_begin,
- TP_PROTO(struct drm_device *dev),
- TP_ARGS(dev),
---- a/include/uapi/drm/v3d_drm.h
-+++ b/include/uapi/drm/v3d_drm.h
-@@ -36,6 +36,7 @@ extern "C" {
- #define DRM_V3D_MMAP_BO 0x03
- #define DRM_V3D_GET_PARAM 0x04
- #define DRM_V3D_GET_BO_OFFSET 0x05
-+#define DRM_V3D_SUBMIT_TFU 0x06
-
- #define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
- #define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
-@@ -43,6 +44,7 @@ extern "C" {
- #define DRM_IOCTL_V3D_MMAP_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_MMAP_BO, struct drm_v3d_mmap_bo)
- #define DRM_IOCTL_V3D_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)
- #define DRM_IOCTL_V3D_GET_BO_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
-+#define DRM_IOCTL_V3D_SUBMIT_TFU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
-
- /**
- * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
-@@ -169,6 +171,7 @@ enum drm_v3d_param {
- DRM_V3D_PARAM_V3D_CORE0_IDENT0,
- DRM_V3D_PARAM_V3D_CORE0_IDENT1,
- DRM_V3D_PARAM_V3D_CORE0_IDENT2,
-+ DRM_V3D_PARAM_SUPPORTS_TFU,
- };
-
- struct drm_v3d_get_param {
-@@ -187,6 +190,28 @@ struct drm_v3d_get_bo_offset {
- __u32 offset;
- };
-
-+struct drm_v3d_submit_tfu {
-+ __u32 icfg;
-+ __u32 iia;
-+ __u32 iis;
-+ __u32 ica;
-+ __u32 iua;
-+ __u32 ioa;
-+ __u32 ios;
-+ __u32 coef[4];
-+ /* First handle is the output BO, following are other inputs.
-+ * 0 for unused.
-+ */
-+ __u32 bo_handles[4];
-+ /* sync object to block on before running the TFU job. Each TFU
-+ * job will execute in the order submitted to its FD. Synchronization
-+ * against rendering jobs requires using sync objects.
-+ */
-+ __u32 in_sync;
-+ /* Sync object to signal when the TFU job is done. */
-+ __u32 out_sync;
-+};
-+
- #if defined(__cplusplus)
- }
- #endif
--- /dev/null
+From e8fb9a84012e6c866d1143acf04ca855b05f4241 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:34 -0800
+Subject: [PATCH 570/725] drm/v3d: Drop unused v3d_flush_caches().
+
+Now that I've specified how the end-of-pipeline flushing should work,
+we're never going to use this function.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Reviewed-by: Dave Emett <david.emett@broadcom.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-2-eric@anholt.net
+(cherry picked from commit 2aa34fd5c7754824cf5488b61ac644f30d3c5c85)
+---
+ drivers/gpu/drm/v3d/v3d_drv.h | 1 -
+ drivers/gpu/drm/v3d/v3d_gem.c | 21 ---------------------
+ 2 files changed, 22 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -308,7 +308,6 @@ void v3d_exec_put(struct v3d_exec_info *
+ void v3d_tfu_job_put(struct v3d_tfu_job *exec);
+ void v3d_reset(struct v3d_dev *v3d);
+ void v3d_invalidate_caches(struct v3d_dev *v3d);
+-void v3d_flush_caches(struct v3d_dev *v3d);
+
+ /* v3d_irq.c */
+ int v3d_irq_init(struct v3d_dev *v3d);
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -175,20 +175,6 @@ v3d_invalidate_slices(struct v3d_dev *v3
+ V3D_SET_FIELD(0xf, V3D_SLCACTL_ICC));
+ }
+
+-/* Invalidates texture L2 cachelines */
+-static void
+-v3d_invalidate_l2t(struct v3d_dev *v3d, int core)
+-{
+- V3D_CORE_WRITE(core,
+- V3D_CTL_L2TCACTL,
+- V3D_L2TCACTL_L2TFLS |
+- V3D_SET_FIELD(V3D_L2TCACTL_FLM_CLEAR, V3D_L2TCACTL_FLM));
+- if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
+- V3D_L2TCACTL_L2TFLS), 100)) {
+- DRM_ERROR("Timeout waiting for L2T invalidate\n");
+- }
+-}
+-
+ void
+ v3d_invalidate_caches(struct v3d_dev *v3d)
+ {
+@@ -199,13 +185,6 @@ v3d_invalidate_caches(struct v3d_dev *v3
+ v3d_flush_l2t(v3d, 0);
+ }
+
+-void
+-v3d_flush_caches(struct v3d_dev *v3d)
+-{
+- v3d_invalidate_l1td(v3d, 0);
+- v3d_invalidate_l2t(v3d, 0);
+-}
+-
+ static void
+ v3d_attach_object_fences(struct v3d_bo **bos, int bo_count,
+ struct dma_fence *fence)
--- /dev/null
+From d11e738a810d653444f24b81f681cd336e4c9f70 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:35 -0800
+Subject: [PATCH 571/725] drm/v3d: Don't bother flushing L1TD at job start.
+
+This is the write combiner for TMU writes. You're supposed to flush
+that at job end if you had dirtied any cachelines. Flushing it at job
+start then doesn't make any sense.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
+Reviewed-by: Dave Emett <david.emett@broadcom.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-3-eric@anholt.net
+(cherry picked from commit 2e6dc3bd80478212e84addf1cafd6ec60674b884)
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 12 ------------
+ 1 file changed, 12 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -139,22 +139,10 @@ v3d_invalidate_l2(struct v3d_dev *v3d, i
+ V3D_L2CACTL_L2CENA);
+ }
+
+-static void
+-v3d_invalidate_l1td(struct v3d_dev *v3d, int core)
+-{
+- V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);
+- if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
+- V3D_L2TCACTL_L2TFLS), 100)) {
+- DRM_ERROR("Timeout waiting for L1T write combiner flush\n");
+- }
+-}
+-
+ /* Invalidates texture L2 cachelines */
+ static void
+ v3d_flush_l2t(struct v3d_dev *v3d, int core)
+ {
+- v3d_invalidate_l1td(v3d, core);
+-
+ V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
+ V3D_L2TCACTL_L2TFLS |
+ V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
+++ /dev/null
-From ee1ef747ef5c088504b541e461d94feadac03bfa Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 28 Nov 2018 15:09:26 -0800
-Subject: [PATCH 571/703] drm/v3d: Drop the "dev" argument to lock/unlock of BO
- reservations.
-
-They were unused, as Dave Emett noticed in TFU review.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Cc: Dave Emett <david.emett@broadcom.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181128230927.10951-2-eric@anholt.net
-Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-(cherry picked from commit e14a07fc4b961a75f6c275d6bd670ba54fbdae14)
----
- drivers/gpu/drm/v3d/v3d_gem.c | 20 +++++++++-----------
- 1 file changed, 9 insertions(+), 11 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -219,8 +219,7 @@ v3d_attach_object_fences(struct v3d_bo *
- }
-
- static void
--v3d_unlock_bo_reservations(struct drm_device *dev,
-- struct v3d_bo **bos,
-+v3d_unlock_bo_reservations(struct v3d_bo **bos,
- int bo_count,
- struct ww_acquire_ctx *acquire_ctx)
- {
-@@ -240,8 +239,7 @@ v3d_unlock_bo_reservations(struct drm_de
- * to v3d, so we don't attach dma-buf fences to them.
- */
- static int
--v3d_lock_bo_reservations(struct drm_device *dev,
-- struct v3d_bo **bos,
-+v3d_lock_bo_reservations(struct v3d_bo **bos,
- int bo_count,
- struct ww_acquire_ctx *acquire_ctx)
- {
-@@ -298,7 +296,7 @@ retry:
- for (i = 0; i < bo_count; i++) {
- ret = reservation_object_reserve_shared(bos[i]->resv);
- if (ret) {
-- v3d_unlock_bo_reservations(dev, bos, bo_count,
-+ v3d_unlock_bo_reservations(bos, bo_count,
- acquire_ctx);
- return ret;
- }
-@@ -566,7 +564,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
- if (ret)
- goto fail;
-
-- ret = v3d_lock_bo_reservations(dev, exec->bo, exec->bo_count,
-+ ret = v3d_lock_bo_reservations(exec->bo, exec->bo_count,
- &acquire_ctx);
- if (ret)
- goto fail;
-@@ -604,7 +602,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
- v3d_attach_object_fences(exec->bo, exec->bo_count,
- exec->render_done_fence);
-
-- v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
-+ v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
-
- /* Update the return sync object for the */
- sync_out = drm_syncobj_find(file_priv, args->out_sync);
-@@ -620,7 +618,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
-
- fail_unreserve:
- mutex_unlock(&v3d->sched_lock);
-- v3d_unlock_bo_reservations(dev, exec->bo, exec->bo_count, &acquire_ctx);
-+ v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
- fail:
- v3d_exec_put(exec);
-
-@@ -691,7 +689,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
- }
- spin_unlock(&file_priv->table_lock);
-
-- ret = v3d_lock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
-+ ret = v3d_lock_bo_reservations(job->bo, bo_count, &acquire_ctx);
- if (ret)
- goto fail;
-
-@@ -710,7 +708,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
-
- v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);
-
-- v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
-+ v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
-
- /* Update the return sync object */
- sync_out = drm_syncobj_find(file_priv, args->out_sync);
-@@ -726,7 +724,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
-
- fail_unreserve:
- mutex_unlock(&v3d->sched_lock);
-- v3d_unlock_bo_reservations(dev, job->bo, bo_count, &acquire_ctx);
-+ v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
- fail:
- v3d_tfu_job_put(job);
-
+++ /dev/null
-From ffc2056239de0353374d8eb9d3022542e4ec5208 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 30 Nov 2018 16:57:59 -0800
-Subject: [PATCH 572/703] drm/v3d: Add missing fence timeline name for TFU.
-
-We shouldn't be returning v3d-render for our new queue.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Fixes: 83d5139982db ("drm/v3d: Add support for submitting jobs to the TFU.")
-Link: https://patchwork.freedesktop.org/patch/msgid/20181201005759.28093-6-eric@anholt.net
-Reviewed-by: Dave Emett <david.emett@broadcom.com>
-(cherry picked from commit db176f6ba1da39ad0016c77b9775a6bb3d0ce88a)
----
- drivers/gpu/drm/v3d/v3d_fence.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_fence.c
-+++ b/drivers/gpu/drm/v3d/v3d_fence.c
-@@ -29,10 +29,16 @@ static const char *v3d_fence_get_timelin
- {
- struct v3d_fence *f = to_v3d_fence(fence);
-
-- if (f->queue == V3D_BIN)
-+ switch (f->queue) {
-+ case V3D_BIN:
- return "v3d-bin";
-- else
-+ case V3D_RENDER:
- return "v3d-render";
-+ case V3D_TFU:
-+ return "v3d-tfu";
-+ default:
-+ return NULL;
-+ }
- }
-
- const struct dma_fence_ops v3d_fence_ops = {
--- /dev/null
+From be7e9e3b29166df5f2e5a06fc94c2aa07c414c4e Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:36 -0800
+Subject: [PATCH 572/725] drm/v3d: Drop the wait for L2T flush to complete.
+
+According to Dave, once you've started an L2T flush, all L2T accesses
+will be blocked until the flush completes. This fixes a consistent
+3-4ms stall between the ioctl and running the job, and 3DMMES Taiji
+goes from 27fps to 110fps.
+
+v2: Leave a note about why we don't need to wait for completion.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
+Reviewed-by: Dave Emett <david.emett@broadcom.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-4-eric@anholt.net
+(cherry picked from commit 51c1b6f9eb3dbdec91b0e3c89f623e634c996bbb)
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -143,13 +143,13 @@ v3d_invalidate_l2(struct v3d_dev *v3d, i
+ static void
+ v3d_flush_l2t(struct v3d_dev *v3d, int core)
+ {
++ /* While there is a busy bit (V3D_L2TCACTL_L2TFLS), we don't
++ * need to wait for completion before dispatching the job --
++ * L2T accesses will be stalled until the flush has completed.
++ */
+ V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
+ V3D_L2TCACTL_L2TFLS |
+ V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
+- if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
+- V3D_L2TCACTL_L2TFLS), 100)) {
+- DRM_ERROR("Timeout waiting for L2T flush\n");
+- }
+ }
+
+ /* Invalidates the slice caches. These are read-only caches. */
+++ /dev/null
-From 5d505c19fc3fce8c17711a53287081e61418a776 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 30 Nov 2018 16:57:58 -0800
-Subject: [PATCH 573/703] drm/v3d: Add more tracepoints for V3D GPU rendering.
-
-The core scheduler tells us when the job is pushed to the scheduler's
-queue, and I had the job_run functions saying when they actually queue
-the job to the hardware. By adding tracepoints for the very top of
-the ioctls and the IRQs signaling job completion, "perf record -a -e
-v3d:.\* -e gpu_scheduler:.\* <job>; perf script" gets you a pretty
-decent timeline.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181201005759.28093-5-eric@anholt.net
-Reviewed-by: Dave Emett <david.emett@broadcom.com>
-(cherry picked from commit 55a9b74846ed5e6219c7d81a8e1bf96f25d8ad5e)
----
- drivers/gpu/drm/v3d/v3d_gem.c | 4 ++
- drivers/gpu/drm/v3d/v3d_irq.c | 19 +++++-
- drivers/gpu/drm/v3d/v3d_trace.h | 101 ++++++++++++++++++++++++++++++++
- 3 files changed, 121 insertions(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -521,6 +521,8 @@ v3d_submit_cl_ioctl(struct drm_device *d
- struct drm_syncobj *sync_out;
- int ret = 0;
-
-+ trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
-+
- if (args->pad != 0) {
- DRM_INFO("pad must be zero: %d\n", args->pad);
- return -EINVAL;
-@@ -648,6 +650,8 @@ v3d_submit_tfu_ioctl(struct drm_device *
- int ret = 0;
- int bo_count;
-
-+ trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia);
-+
- job = kcalloc(1, sizeof(*job), GFP_KERNEL);
- if (!job)
- return -ENOMEM;
---- a/drivers/gpu/drm/v3d/v3d_irq.c
-+++ b/drivers/gpu/drm/v3d/v3d_irq.c
-@@ -15,6 +15,7 @@
-
- #include "v3d_drv.h"
- #include "v3d_regs.h"
-+#include "v3d_trace.h"
-
- #define V3D_CORE_IRQS ((u32)(V3D_INT_OUTOMEM | \
- V3D_INT_FLDONE | \
-@@ -88,12 +89,20 @@ v3d_irq(int irq, void *arg)
- }
-
- if (intsts & V3D_INT_FLDONE) {
-- dma_fence_signal(v3d->bin_job->bin.done_fence);
-+ struct v3d_fence *fence =
-+ to_v3d_fence(v3d->bin_job->bin.done_fence);
-+
-+ trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
-+ dma_fence_signal(&fence->base);
- status = IRQ_HANDLED;
- }
-
- if (intsts & V3D_INT_FRDONE) {
-- dma_fence_signal(v3d->render_job->render.done_fence);
-+ struct v3d_fence *fence =
-+ to_v3d_fence(v3d->render_job->render.done_fence);
-+
-+ trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
-+ dma_fence_signal(&fence->base);
- status = IRQ_HANDLED;
- }
-
-@@ -119,7 +128,11 @@ v3d_hub_irq(int irq, void *arg)
- V3D_WRITE(V3D_HUB_INT_CLR, intsts);
-
- if (intsts & V3D_HUB_INT_TFUC) {
-- dma_fence_signal(v3d->tfu_job->done_fence);
-+ struct v3d_fence *fence =
-+ to_v3d_fence(v3d->tfu_job->done_fence);
-+
-+ trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
-+ dma_fence_signal(&fence->base);
- status = IRQ_HANDLED;
- }
-
---- a/drivers/gpu/drm/v3d/v3d_trace.h
-+++ b/drivers/gpu/drm/v3d/v3d_trace.h
-@@ -12,6 +12,28 @@
- #define TRACE_SYSTEM v3d
- #define TRACE_INCLUDE_FILE v3d_trace
-
-+TRACE_EVENT(v3d_submit_cl_ioctl,
-+ TP_PROTO(struct drm_device *dev, u32 ct1qba, u32 ct1qea),
-+ TP_ARGS(dev, ct1qba, ct1qea),
-+
-+ TP_STRUCT__entry(
-+ __field(u32, dev)
-+ __field(u32, ct1qba)
-+ __field(u32, ct1qea)
-+ ),
-+
-+ TP_fast_assign(
-+ __entry->dev = dev->primary->index;
-+ __entry->ct1qba = ct1qba;
-+ __entry->ct1qea = ct1qea;
-+ ),
-+
-+ TP_printk("dev=%u, RCL 0x%08x..0x%08x",
-+ __entry->dev,
-+ __entry->ct1qba,
-+ __entry->ct1qea)
-+);
-+
- TRACE_EVENT(v3d_submit_cl,
- TP_PROTO(struct drm_device *dev, bool is_render,
- uint64_t seqno,
-@@ -42,6 +64,85 @@ TRACE_EVENT(v3d_submit_cl,
- __entry->ctnqea)
- );
-
-+TRACE_EVENT(v3d_bcl_irq,
-+ TP_PROTO(struct drm_device *dev,
-+ uint64_t seqno),
-+ TP_ARGS(dev, seqno),
-+
-+ TP_STRUCT__entry(
-+ __field(u32, dev)
-+ __field(u64, seqno)
-+ ),
-+
-+ TP_fast_assign(
-+ __entry->dev = dev->primary->index;
-+ __entry->seqno = seqno;
-+ ),
-+
-+ TP_printk("dev=%u, seqno=%llu",
-+ __entry->dev,
-+ __entry->seqno)
-+);
-+
-+TRACE_EVENT(v3d_rcl_irq,
-+ TP_PROTO(struct drm_device *dev,
-+ uint64_t seqno),
-+ TP_ARGS(dev, seqno),
-+
-+ TP_STRUCT__entry(
-+ __field(u32, dev)
-+ __field(u64, seqno)
-+ ),
-+
-+ TP_fast_assign(
-+ __entry->dev = dev->primary->index;
-+ __entry->seqno = seqno;
-+ ),
-+
-+ TP_printk("dev=%u, seqno=%llu",
-+ __entry->dev,
-+ __entry->seqno)
-+);
-+
-+TRACE_EVENT(v3d_tfu_irq,
-+ TP_PROTO(struct drm_device *dev,
-+ uint64_t seqno),
-+ TP_ARGS(dev, seqno),
-+
-+ TP_STRUCT__entry(
-+ __field(u32, dev)
-+ __field(u64, seqno)
-+ ),
-+
-+ TP_fast_assign(
-+ __entry->dev = dev->primary->index;
-+ __entry->seqno = seqno;
-+ ),
-+
-+ TP_printk("dev=%u, seqno=%llu",
-+ __entry->dev,
-+ __entry->seqno)
-+);
-+
-+TRACE_EVENT(v3d_submit_tfu_ioctl,
-+ TP_PROTO(struct drm_device *dev, u32 iia),
-+ TP_ARGS(dev, iia),
-+
-+ TP_STRUCT__entry(
-+ __field(u32, dev)
-+ __field(u32, iia)
-+ ),
-+
-+ TP_fast_assign(
-+ __entry->dev = dev->primary->index;
-+ __entry->iia = iia;
-+ ),
-+
-+ TP_printk("dev=%u, IIA 0x%08x",
-+ __entry->dev,
-+ __entry->iia)
-+);
-+
- TRACE_EVENT(v3d_submit_tfu,
- TP_PROTO(struct drm_device *dev,
- uint64_t seqno),
--- /dev/null
+From af6319dd15fd5ec3dac4345136ccfb07eb151c63 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:37 -0800
+Subject: [PATCH 573/725] drm/v3d: Stop trying to flush L2C on V3D 3.3+
+
+This cache was replaced with the slice accessing the L2T in the newer
+generations. Noted by Dave during review.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-5-eric@anholt.net
+Reviewed-by: Dave Emett <david.emett@broadcom.com>
+(cherry picked from commit 7b9d2fe4350a9c12f66ad8cc78c1098226f6c3c2)
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -130,10 +130,15 @@ v3d_flush_l3(struct v3d_dev *v3d)
+ }
+ }
+
+-/* Invalidates the (read-only) L2 cache. */
++/* Invalidates the (read-only) L2C cache. This was the L2 cache for
++ * uniforms and instructions on V3D 3.2.
++ */
+ static void
+-v3d_invalidate_l2(struct v3d_dev *v3d, int core)
++v3d_invalidate_l2c(struct v3d_dev *v3d, int core)
+ {
++ if (v3d->ver > 32)
++ return;
++
+ V3D_CORE_WRITE(core, V3D_CTL_L2CACTL,
+ V3D_L2CACTL_L2CCLR |
+ V3D_L2CACTL_L2CENA);
+@@ -168,7 +173,7 @@ v3d_invalidate_caches(struct v3d_dev *v3
+ {
+ v3d_flush_l3(v3d);
+
+- v3d_invalidate_l2(v3d, 0);
++ v3d_invalidate_l2c(v3d, 0);
+ v3d_invalidate_slices(v3d, 0);
+ v3d_flush_l2t(v3d, 0);
+ }
+++ /dev/null
-From b9b60a044a52d5de6e9bc6c6703e2ac8cb7cc9c5 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 3 Dec 2018 14:24:34 -0800
-Subject: [PATCH 574/703] drm/v3d: Drop unused v3d_flush_caches().
-
-Now that I've specified how the end-of-pipeline flushing should work,
-we're never going to use this function.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Dave Emett <david.emett@broadcom.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-2-eric@anholt.net
-(cherry picked from commit 2aa34fd5c7754824cf5488b61ac644f30d3c5c85)
----
- drivers/gpu/drm/v3d/v3d_drv.h | 1 -
- drivers/gpu/drm/v3d/v3d_gem.c | 21 ---------------------
- 2 files changed, 22 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -308,7 +308,6 @@ void v3d_exec_put(struct v3d_exec_info *
- void v3d_tfu_job_put(struct v3d_tfu_job *exec);
- void v3d_reset(struct v3d_dev *v3d);
- void v3d_invalidate_caches(struct v3d_dev *v3d);
--void v3d_flush_caches(struct v3d_dev *v3d);
-
- /* v3d_irq.c */
- int v3d_irq_init(struct v3d_dev *v3d);
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -175,20 +175,6 @@ v3d_invalidate_slices(struct v3d_dev *v3
- V3D_SET_FIELD(0xf, V3D_SLCACTL_ICC));
- }
-
--/* Invalidates texture L2 cachelines */
--static void
--v3d_invalidate_l2t(struct v3d_dev *v3d, int core)
--{
-- V3D_CORE_WRITE(core,
-- V3D_CTL_L2TCACTL,
-- V3D_L2TCACTL_L2TFLS |
-- V3D_SET_FIELD(V3D_L2TCACTL_FLM_CLEAR, V3D_L2TCACTL_FLM));
-- if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
-- V3D_L2TCACTL_L2TFLS), 100)) {
-- DRM_ERROR("Timeout waiting for L2T invalidate\n");
-- }
--}
--
- void
- v3d_invalidate_caches(struct v3d_dev *v3d)
- {
-@@ -199,13 +185,6 @@ v3d_invalidate_caches(struct v3d_dev *v3
- v3d_flush_l2t(v3d, 0);
- }
-
--void
--v3d_flush_caches(struct v3d_dev *v3d)
--{
-- v3d_invalidate_l1td(v3d, 0);
-- v3d_invalidate_l2t(v3d, 0);
--}
--
- static void
- v3d_attach_object_fences(struct v3d_bo **bos, int bo_count,
- struct dma_fence *fence)
--- /dev/null
+From 1b56cdcccd969ef80f4bf87ca0ef637ca5afc6cc Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:38 -0800
+Subject: [PATCH 574/725] drm/v3d: Invalidate the caches from the outside in.
+
+This would be a fairly obscure race, but let's make sure we don't ever
+lose it.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-6-eric@anholt.net
+Reviewed-by: Dave Emett <david.emett@broadcom.com>
+(cherry picked from commit aa5beec32e8b78bfcf621e3c3daebfb1644b6365)
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -171,11 +171,15 @@ v3d_invalidate_slices(struct v3d_dev *v3
+ void
+ v3d_invalidate_caches(struct v3d_dev *v3d)
+ {
++ /* Invalidate the caches from the outside in. That way if
++ * another CL's concurrent use of nearby memory were to pull
++ * an invalidated cacheline back in, we wouldn't leave stale
++ * data in the inner cache.
++ */
+ v3d_flush_l3(v3d);
+-
+ v3d_invalidate_l2c(v3d, 0);
+- v3d_invalidate_slices(v3d, 0);
+ v3d_flush_l2t(v3d, 0);
++ v3d_invalidate_slices(v3d, 0);
+ }
+
+ static void
+++ /dev/null
-From 7b8186de594a27954c909cd8a9ad1ac2cc27a526 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 3 Dec 2018 14:24:35 -0800
-Subject: [PATCH 575/703] drm/v3d: Don't bother flushing L1TD at job start.
-
-This is the write combiner for TMU writes. You're supposed to flush
-that at job end if you had dirtied any cachelines. Flushing it at job
-start then doesn't make any sense.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
-Reviewed-by: Dave Emett <david.emett@broadcom.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-3-eric@anholt.net
-(cherry picked from commit 2e6dc3bd80478212e84addf1cafd6ec60674b884)
----
- drivers/gpu/drm/v3d/v3d_gem.c | 12 ------------
- 1 file changed, 12 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -139,22 +139,10 @@ v3d_invalidate_l2(struct v3d_dev *v3d, i
- V3D_L2CACTL_L2CENA);
- }
-
--static void
--v3d_invalidate_l1td(struct v3d_dev *v3d, int core)
--{
-- V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);
-- if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
-- V3D_L2TCACTL_L2TFLS), 100)) {
-- DRM_ERROR("Timeout waiting for L1T write combiner flush\n");
-- }
--}
--
- /* Invalidates texture L2 cachelines */
- static void
- v3d_flush_l2t(struct v3d_dev *v3d, int core)
- {
-- v3d_invalidate_l1td(v3d, core);
--
- V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
- V3D_L2TCACTL_L2TFLS |
- V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
--- /dev/null
+From 8a757f0cafacc0549aa333882060999b4465ac0c Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 7 Feb 2019 15:26:13 -0800
+Subject: [PATCH 575/725] drm/v3d: Fix BO stats accounting for dma-buf-imported
+ buffers.
+
+We always decrement at GEM free, so make sure we increment at GEM
+creation for dma-bufs.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20190207232613.24981-1-eric@anholt.net
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+(cherry picked from commit cc3f60cfd4f2752f1bad7eaa3839855c15347abc)
+---
+ drivers/gpu/drm/v3d/v3d_bo.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/gpu/drm/v3d/v3d_bo.c
++++ b/drivers/gpu/drm/v3d/v3d_bo.c
+@@ -282,6 +282,7 @@ v3d_prime_import_sg_table(struct drm_dev
+ struct dma_buf_attachment *attach,
+ struct sg_table *sgt)
+ {
++ struct v3d_dev *v3d = to_v3d_dev(dev);
+ struct drm_gem_object *obj;
+ struct v3d_bo *bo;
+
+@@ -296,6 +297,11 @@ v3d_prime_import_sg_table(struct drm_dev
+ obj->import_attach = attach;
+ v3d_bo_get_pages(bo);
+
++ mutex_lock(&v3d->bo_lock);
++ v3d->bo_stats.num_allocated++;
++ v3d->bo_stats.pages_allocated += obj->size >> PAGE_SHIFT;
++ mutex_unlock(&v3d->bo_lock);
++
+ v3d_mmu_insert_ptes(bo);
+
+ return obj;
+++ /dev/null
-From 6820b2b01d69ac316786570a592cc32efc559a0e Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 3 Dec 2018 14:24:36 -0800
-Subject: [PATCH 576/703] drm/v3d: Drop the wait for L2T flush to complete.
-
-According to Dave, once you've started an L2T flush, all L2T accesses
-will be blocked until the flush completes. This fixes a consistent
-3-4ms stall between the ioctl and running the job, and 3DMMES Taiji
-goes from 27fps to 110fps.
-
-v2: Leave a note about why we don't need to wait for completion.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
-Reviewed-by: Dave Emett <david.emett@broadcom.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-4-eric@anholt.net
-(cherry picked from commit 51c1b6f9eb3dbdec91b0e3c89f623e634c996bbb)
----
- drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -143,13 +143,13 @@ v3d_invalidate_l2(struct v3d_dev *v3d, i
- static void
- v3d_flush_l2t(struct v3d_dev *v3d, int core)
- {
-+ /* While there is a busy bit (V3D_L2TCACTL_L2TFLS), we don't
-+ * need to wait for completion before dispatching the job --
-+ * L2T accesses will be stalled until the flush has completed.
-+ */
- V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
- V3D_L2TCACTL_L2TFLS |
- V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
-- if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
-- V3D_L2TCACTL_L2TFLS), 100)) {
-- DRM_ERROR("Timeout waiting for L2T flush\n");
-- }
- }
-
- /* Invalidates the slice caches. These are read-only caches. */
--- /dev/null
+From e984884708d1777866cd8aba8de60eb9927f1628 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 7 Feb 2019 12:09:58 -0800
+Subject: [PATCH 576/725] drm/v3d: Update top-level kerneldoc for the addition
+ of TFU.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20190207201001.5730-1-eric@anholt.net
+Reviewed-by: Thomas Spurden <thomas.spurden@broadcom.com>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+(cherry picked from commit fd347df16d4ed2eef565344b8f16a1134bddf185)
+---
+ drivers/gpu/drm/v3d/v3d_drv.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -7,9 +7,9 @@
+ * This driver supports the Broadcom V3D 3.3 and 4.1 OpenGL ES GPUs.
+ * For V3D 2.x support, see the VC4 driver.
+ *
+- * Currently only single-core rendering using the binner and renderer
+- * is supported. The TFU (texture formatting unit) and V3D 4.x's CSD
+- * (compute shader dispatch) are not yet supported.
++ * Currently only single-core rendering using the binner and renderer,
++ * along with TFU (texture formatting unit) rendering is supported.
++ * V3D 4.x's CSD (compute shader dispatch) is not yet supported.
+ */
+
+ #include <linux/clk.h>
+++ /dev/null
-From 861449c481eaa203998a4298d81b2fba6b34f543 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 3 Dec 2018 14:24:37 -0800
-Subject: [PATCH 577/703] drm/v3d: Stop trying to flush L2C on V3D 3.3+
-
-This cache was replaced with the slice accessing the L2T in the newer
-generations. Noted by Dave during review.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-5-eric@anholt.net
-Reviewed-by: Dave Emett <david.emett@broadcom.com>
-(cherry picked from commit 7b9d2fe4350a9c12f66ad8cc78c1098226f6c3c2)
----
- drivers/gpu/drm/v3d/v3d_gem.c | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -130,10 +130,15 @@ v3d_flush_l3(struct v3d_dev *v3d)
- }
- }
-
--/* Invalidates the (read-only) L2 cache. */
-+/* Invalidates the (read-only) L2C cache. This was the L2 cache for
-+ * uniforms and instructions on V3D 3.2.
-+ */
- static void
--v3d_invalidate_l2(struct v3d_dev *v3d, int core)
-+v3d_invalidate_l2c(struct v3d_dev *v3d, int core)
- {
-+ if (v3d->ver > 32)
-+ return;
-+
- V3D_CORE_WRITE(core, V3D_CTL_L2CACTL,
- V3D_L2CACTL_L2CCLR |
- V3D_L2CACTL_L2CENA);
-@@ -168,7 +173,7 @@ v3d_invalidate_caches(struct v3d_dev *v3
- {
- v3d_flush_l3(v3d);
-
-- v3d_invalidate_l2(v3d, 0);
-+ v3d_invalidate_l2c(v3d, 0);
- v3d_invalidate_slices(v3d, 0);
- v3d_flush_l2t(v3d, 0);
- }
--- /dev/null
+From 7551fad9f71e9228df091897d61b2d3df7c96ab1 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 4 Mar 2019 11:59:34 -0800
+Subject: [PATCH 577/725] drm/vc4: Fix oops at boot with firmwarekms on 4.19.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_kms.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -107,6 +107,9 @@ vc4_ctm_commit(struct vc4_dev *vc4, stru
+ struct vc4_ctm_state *ctm_state = to_vc4_ctm_state(vc4->ctm_manager.state);
+ struct drm_color_ctm *ctm = ctm_state->ctm;
+
++ if (vc4->firmware_kms)
++ return;
++
+ if (ctm_state->fifo) {
+ HVS_WRITE(SCALER_OLEDCOEF2,
+ VC4_SET_FIELD(vc4_ctm_s31_32_to_s0_9(ctm->matrix[0]),
+++ /dev/null
-From 022131a879deb883f4fbbbd7b5887ae6b2738172 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 3 Dec 2018 14:24:38 -0800
-Subject: [PATCH 578/703] drm/v3d: Invalidate the caches from the outside in.
-
-This would be a fairly obscure race, but let's make sure we don't ever
-lose it.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-6-eric@anholt.net
-Reviewed-by: Dave Emett <david.emett@broadcom.com>
-(cherry picked from commit aa5beec32e8b78bfcf621e3c3daebfb1644b6365)
----
- drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++++--
- 1 file changed, 6 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -171,11 +171,15 @@ v3d_invalidate_slices(struct v3d_dev *v3
- void
- v3d_invalidate_caches(struct v3d_dev *v3d)
- {
-+ /* Invalidate the caches from the outside in. That way if
-+ * another CL's concurrent use of nearby memory were to pull
-+ * an invalidated cacheline back in, we wouldn't leave stale
-+ * data in the inner cache.
-+ */
- v3d_flush_l3(v3d);
--
- v3d_invalidate_l2c(v3d, 0);
-- v3d_invalidate_slices(v3d, 0);
- v3d_flush_l2t(v3d, 0);
-+ v3d_invalidate_slices(v3d, 0);
- }
-
- static void
--- /dev/null
+From ef816cd2c04e82d3b923cbb407025609fecd1205 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 20 Feb 2019 13:03:41 -0800
+Subject: [PATCH 578/725] drm/vc4: Disable V3D interactions if the v3d
+ component didn't probe.
+
+One might want to use the VC4 display stack without using Mesa.
+Similar to the debugfs fixes for not having all of the possible
+display bits enabled, make sure you can't oops in vc4 if v3d isn't
+enabled.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_drv.c | 11 +++++++++++
+ drivers/gpu/drm/vc4/vc4_gem.c | 10 ++++++++++
+ drivers/gpu/drm/vc4/vc4_irq.c | 9 +++++++++
+ drivers/gpu/drm/vc4/vc4_perfmon.c | 18 ++++++++++++++++++
+ 4 files changed, 48 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_drv.c
++++ b/drivers/gpu/drm/vc4/vc4_drv.c
+@@ -71,6 +71,9 @@ static int vc4_get_param_ioctl(struct dr
+ if (args->pad != 0)
+ return -EINVAL;
+
++ if (!vc4->v3d)
++ return -EINVAL;
++
+ switch (args->param) {
+ case DRM_VC4_PARAM_V3D_IDENT0:
+ ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
+@@ -271,6 +274,7 @@ static int vc4_drm_bind(struct device *d
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm;
+ struct vc4_dev *vc4;
++ struct device_node *node;
+ int ret = 0;
+
+ dev->coherent_dma_mask = DMA_BIT_MASK(32);
+@@ -279,6 +283,13 @@ static int vc4_drm_bind(struct device *d
+ if (!vc4)
+ return -ENOMEM;
+
++ /* If VC4 V3D is missing, don't advertise render nodes. */
++ node = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-v3d");
++ if (node)
++ of_node_put(node);
++ else
++ vc4_drm_driver.driver_features &= ~DRIVER_RENDER;
++
+ drm = drm_dev_alloc(&vc4_drm_driver, dev);
+ if (IS_ERR(drm))
+ return PTR_ERR(drm);
+--- a/drivers/gpu/drm/vc4/vc4_gem.c
++++ b/drivers/gpu/drm/vc4/vc4_gem.c
+@@ -74,6 +74,11 @@ vc4_get_hang_state_ioctl(struct drm_devi
+ u32 i;
+ int ret = 0;
+
++ if (!vc4->v3d) {
++ DRM_DEBUG("VC4_GET_HANG_STATE with no VC4 V3D probed\n");
++ return -EINVAL;
++ }
++
+ spin_lock_irqsave(&vc4->job_lock, irqflags);
+ kernel_state = vc4->hang_state;
+ if (!kernel_state) {
+@@ -1124,6 +1129,11 @@ vc4_submit_cl_ioctl(struct drm_device *d
+ struct dma_fence *in_fence;
+ int ret = 0;
+
++ if (!vc4->v3d) {
++ DRM_DEBUG("VC4_SUBMIT_CL with no VC4 V3D probed\n");
++ return -EINVAL;
++ }
++
+ if ((args->flags & ~(VC4_SUBMIT_CL_USE_CLEAR_COLOR |
+ VC4_SUBMIT_CL_FIXED_RCL_ORDER |
+ VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X |
+--- a/drivers/gpu/drm/vc4/vc4_irq.c
++++ b/drivers/gpu/drm/vc4/vc4_irq.c
+@@ -229,6 +229,9 @@ vc4_irq_preinstall(struct drm_device *de
+ {
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
++ if (!vc4->v3d)
++ return;
++
+ init_waitqueue_head(&vc4->job_wait_queue);
+ INIT_WORK(&vc4->overflow_mem_work, vc4_overflow_mem_work);
+
+@@ -243,6 +246,9 @@ vc4_irq_postinstall(struct drm_device *d
+ {
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
++ if (!vc4->v3d)
++ return 0;
++
+ /* Enable both the render done and out of memory interrupts. */
+ V3D_WRITE(V3D_INTENA, V3D_DRIVER_IRQS);
+
+@@ -254,6 +260,9 @@ vc4_irq_uninstall(struct drm_device *dev
+ {
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
++ if (!vc4->v3d)
++ return;
++
+ /* Disable sending interrupts for our driver's IRQs. */
+ V3D_WRITE(V3D_INTDIS, V3D_DRIVER_IRQS);
+
+--- a/drivers/gpu/drm/vc4/vc4_perfmon.c
++++ b/drivers/gpu/drm/vc4/vc4_perfmon.c
+@@ -100,12 +100,18 @@ void vc4_perfmon_close_file(struct vc4_f
+ int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+ {
++ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct vc4_file *vc4file = file_priv->driver_priv;
+ struct drm_vc4_perfmon_create *req = data;
+ struct vc4_perfmon *perfmon;
+ unsigned int i;
+ int ret;
+
++ if (!vc4->v3d) {
++ DRM_DEBUG("Creating perfmon no VC4 V3D probed\n");
++ return -EINVAL;
++ }
++
+ /* Number of monitored counters cannot exceed HW limits. */
+ if (req->ncounters > DRM_VC4_MAX_PERF_COUNTERS ||
+ !req->ncounters)
+@@ -146,10 +152,16 @@ int vc4_perfmon_create_ioctl(struct drm_
+ int vc4_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+ {
++ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct vc4_file *vc4file = file_priv->driver_priv;
+ struct drm_vc4_perfmon_destroy *req = data;
+ struct vc4_perfmon *perfmon;
+
++ if (!vc4->v3d) {
++ DRM_DEBUG("Destroying perfmon no VC4 V3D probed\n");
++ return -EINVAL;
++ }
++
+ mutex_lock(&vc4file->perfmon.lock);
+ perfmon = idr_remove(&vc4file->perfmon.idr, req->id);
+ mutex_unlock(&vc4file->perfmon.lock);
+@@ -164,11 +176,17 @@ int vc4_perfmon_destroy_ioctl(struct drm
+ int vc4_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+ {
++ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct vc4_file *vc4file = file_priv->driver_priv;
+ struct drm_vc4_perfmon_get_values *req = data;
+ struct vc4_perfmon *perfmon;
+ int ret;
+
++ if (!vc4->v3d) {
++ DRM_DEBUG("Getting perfmon no VC4 V3D probed\n");
++ return -EINVAL;
++ }
++
+ mutex_lock(&vc4file->perfmon.lock);
+ perfmon = idr_find(&vc4file->perfmon.idr, req->id);
+ vc4_perfmon_get(perfmon);
--- /dev/null
+From 6c378699bbc94d0f4e13fa5df43c8e2c7b9c1480 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 4 Oct 2018 17:22:43 -0700
+Subject: [PATCH 579/725] drm/v3d: Add support for V3D v4.2.
+
+No compatible string for it yet, just the version-dependent changes.
+They've now tied the hub and the core interrupt lines into a single
+interrupt line coming out of the block. It also turns out I made a
+mistake in modeling the V3D v3.3 and v4.1 bridge as a part of V3D
+itself -- the bridge is going away in favor of an external reset
+controller in a larger HW module.
+
+v2: Use consistent checks for whether we're on 4.2, and fix a leak in
+ an error path.
+v3: Use more general means of determining if the current 4.2 changes
+ are in place, as apparently other platforms may switch back (noted
+ by Dave). Update the binding doc.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ .../devicetree/bindings/gpu/brcm,bcm-v3d.txt | 11 ++++--
+ drivers/gpu/drm/v3d/v3d_drv.c | 21 +++++++++---
+ drivers/gpu/drm/v3d/v3d_drv.h | 2 ++
+ drivers/gpu/drm/v3d/v3d_gem.c | 12 ++++++-
+ drivers/gpu/drm/v3d/v3d_irq.c | 34 ++++++++++++++-----
+ 5 files changed, 63 insertions(+), 17 deletions(-)
+
+--- a/Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.txt
++++ b/Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.txt
+@@ -6,15 +6,20 @@ For V3D 2.x, see brcm,bcm-vc4.txt.
+ Required properties:
+ - compatible: Should be "brcm,7268-v3d" or "brcm,7278-v3d"
+ - reg: Physical base addresses and lengths of the register areas
+-- reg-names: Names for the register areas. The "hub", "bridge", and "core0"
++- reg-names: Names for the register areas. The "hub" and "core0"
+ register areas are always required. The "gca" register area
+- is required if the GCA cache controller is present.
++ is required if the GCA cache controller is present. The
++ "bridge" register area is required if an external reset
++ controller is not present.
+ - interrupts: The interrupt numbers. The first interrupt is for the hub,
+- while the following interrupts are for the cores.
++ while the following interrupts are separate interrupt lines
++ for the cores (if they don't share the hub's interrupt).
+ See bindings/interrupt-controller/interrupts.txt
+
+ Optional properties:
+ - clocks: The core clock the unit runs on
++- resets: The reset line for v3d, if not using a mapping of the bridge
++ See bindings/reset/reset.txt
+
+ v3d {
+ compatible = "brcm,7268-v3d";
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -19,6 +19,7 @@
+ #include <linux/of_platform.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_runtime.h>
++#include <linux/reset.h>
+ #include <drm/drm_fb_cma_helper.h>
+ #include <drm/drm_fb_helper.h>
+
+@@ -265,10 +266,6 @@ static int v3d_platform_drm_probe(struct
+ v3d->pdev = pdev;
+ drm = &v3d->drm;
+
+- ret = map_regs(v3d, &v3d->bridge_regs, "bridge");
+- if (ret)
+- goto dev_free;
+-
+ ret = map_regs(v3d, &v3d->hub_regs, "hub");
+ if (ret)
+ goto dev_free;
+@@ -283,6 +280,22 @@ static int v3d_platform_drm_probe(struct
+ v3d->cores = V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_NCORES);
+ WARN_ON(v3d->cores > 1); /* multicore not yet implemented */
+
++ v3d->reset = devm_reset_control_get_exclusive(dev, NULL);
++ if (IS_ERR(v3d->reset)) {
++ ret = PTR_ERR(v3d->reset);
++
++ if (ret == -EPROBE_DEFER)
++ goto dev_free;
++
++ v3d->reset = NULL;
++ ret = map_regs(v3d, &v3d->bridge_regs, "bridge");
++ if (ret) {
++ dev_err(dev,
++ "Failed to get reset control or bridge regs\n");
++ goto dev_free;
++ }
++ }
++
+ if (v3d->ver < 41) {
+ ret = map_regs(v3d, &v3d->gca_regs, "gca");
+ if (ret)
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -34,6 +34,7 @@ struct v3d_dev {
+ * and revision.
+ */
+ int ver;
++ bool single_irq_line;
+
+ struct device *dev;
+ struct platform_device *pdev;
+@@ -42,6 +43,7 @@ struct v3d_dev {
+ void __iomem *bridge_regs;
+ void __iomem *gca_regs;
+ struct clk *clk;
++ struct reset_control *reset;
+
+ /* Virtual and DMA addresses of the single shared page table. */
+ volatile u32 *pt;
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -6,6 +6,7 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_runtime.h>
++#include <linux/reset.h>
+ #include <linux/device.h>
+ #include <linux/io.h>
+ #include <linux/sched/signal.h>
+@@ -69,7 +70,7 @@ v3d_idle_gca(struct v3d_dev *v3d)
+ }
+
+ static void
+-v3d_reset_v3d(struct v3d_dev *v3d)
++v3d_reset_by_bridge(struct v3d_dev *v3d)
+ {
+ int version = V3D_BRIDGE_READ(V3D_TOP_GR_BRIDGE_REVISION);
+
+@@ -89,6 +90,15 @@ v3d_reset_v3d(struct v3d_dev *v3d)
+ V3D_TOP_GR_BRIDGE_SW_INIT_1_V3D_CLK_108_SW_INIT);
+ V3D_BRIDGE_WRITE(V3D_TOP_GR_BRIDGE_SW_INIT_1, 0);
+ }
++}
++
++static void
++v3d_reset_v3d(struct v3d_dev *v3d)
++{
++ if (v3d->reset)
++ reset_control_reset(v3d->reset);
++ else
++ v3d_reset_by_bridge(v3d);
+
+ v3d_init_hw_state(v3d);
+ }
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -27,6 +27,9 @@
+ V3D_HUB_INT_MMU_CAP | \
+ V3D_HUB_INT_TFUC))
+
++static irqreturn_t
++v3d_hub_irq(int irq, void *arg);
++
+ static void
+ v3d_overflow_mem_work(struct work_struct *work)
+ {
+@@ -112,6 +115,12 @@ v3d_irq(int irq, void *arg)
+ if (intsts & V3D_INT_GMPV)
+ dev_err(v3d->dev, "GMP violation\n");
+
++ /* V3D 4.2 wires the hub and core IRQs together, so if we &
++ * didn't see the common one then check hub for MMU IRQs.
++ */
++ if (v3d->single_irq_line && status == IRQ_NONE)
++ return v3d_hub_irq(irq, arg);
++
+ return status;
+ }
+
+@@ -170,15 +179,22 @@ v3d_irq_init(struct v3d_dev *v3d)
+ V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS);
+ V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS);
+
+- ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
+- v3d_hub_irq, IRQF_SHARED,
+- "v3d_hub", v3d);
+- if (ret)
+- goto fail;
+-
+- ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 1),
+- v3d_irq, IRQF_SHARED,
+- "v3d_core0", v3d);
++ if (platform_get_irq(v3d->pdev, 1) < 0) {
++ ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
++ v3d_irq, IRQF_SHARED,
++ "v3d", v3d);
++ v3d->single_irq_line = true;
++ } else {
++ ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
++ v3d_hub_irq, IRQF_SHARED,
++ "v3d_hub", v3d);
++ if (ret)
++ goto fail;
++
++ ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 1),
++ v3d_irq, IRQF_SHARED,
++ "v3d_core0", v3d);
++ }
+ if (ret)
+ goto fail;
+
+++ /dev/null
-From cc4f39930d6d1cf396c3a1f6fa45696582247ee6 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 7 Feb 2019 15:26:13 -0800
-Subject: [PATCH 579/703] drm/v3d: Fix BO stats accounting for dma-buf-imported
- buffers.
-
-We always decrement at GEM free, so make sure we increment at GEM
-creation for dma-bufs.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20190207232613.24981-1-eric@anholt.net
-Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
-(cherry picked from commit cc3f60cfd4f2752f1bad7eaa3839855c15347abc)
----
- drivers/gpu/drm/v3d/v3d_bo.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/gpu/drm/v3d/v3d_bo.c
-+++ b/drivers/gpu/drm/v3d/v3d_bo.c
-@@ -282,6 +282,7 @@ v3d_prime_import_sg_table(struct drm_dev
- struct dma_buf_attachment *attach,
- struct sg_table *sgt)
- {
-+ struct v3d_dev *v3d = to_v3d_dev(dev);
- struct drm_gem_object *obj;
- struct v3d_bo *bo;
-
-@@ -296,6 +297,11 @@ v3d_prime_import_sg_table(struct drm_dev
- obj->import_attach = attach;
- v3d_bo_get_pages(bo);
-
-+ mutex_lock(&v3d->bo_lock);
-+ v3d->bo_stats.num_allocated++;
-+ v3d->bo_stats.pages_allocated += obj->size >> PAGE_SHIFT;
-+ mutex_unlock(&v3d->bo_lock);
-+
- v3d_mmu_insert_ptes(bo);
-
- return obj;
--- /dev/null
+From 10a571a91a1d34cd89bb45a562aafc625dd6e738 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 16 Oct 2018 10:13:41 -0700
+Subject: [PATCH 580/725] drm/v3d: Don't try to set OVRTMUOUT on V3D 4.x.
+
+The old field is gone and the register now has a different field,
+QRMAXCNT for how many TMU requests get serviced before thread switch.
+We were accidentally reducing it from its default of 0x3 (4 requests)
+to 0x0 (1).
+
+v2: Skip setting the reg at all on 4.x, instead of trying to update
+ only the old field.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 3 ++-
+ drivers/gpu/drm/v3d/v3d_regs.h | 2 ++
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -25,7 +25,8 @@ v3d_init_core(struct v3d_dev *v3d, int c
+ * type. If you want the default behavior, you can still put
+ * "2" in the indirect texture state's output_type field.
+ */
+- V3D_CORE_WRITE(core, V3D_CTL_MISCCFG, V3D_MISCCFG_OVRTMUOUT);
++ if (v3d->ver < 40)
++ V3D_CORE_WRITE(core, V3D_CTL_MISCCFG, V3D_MISCCFG_OVRTMUOUT);
+
+ /* Whenever we flush the L2T cache, we always want to flush
+ * the whole thing.
+--- a/drivers/gpu/drm/v3d/v3d_regs.h
++++ b/drivers/gpu/drm/v3d/v3d_regs.h
+@@ -216,6 +216,8 @@
+ # define V3D_IDENT2_BCG_INT BIT(28)
+
+ #define V3D_CTL_MISCCFG 0x00018
++# define V3D_CTL_MISCCFG_QRMAXCNT_MASK V3D_MASK(3, 1)
++# define V3D_CTL_MISCCFG_QRMAXCNT_SHIFT 1
+ # define V3D_MISCCFG_OVRTMUOUT BIT(0)
+
+ #define V3D_CTL_L2CACTL 0x00020
+++ /dev/null
-From e4759dbb9968baee8a35bf2f165f6096be6aac00 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 7 Feb 2019 12:09:58 -0800
-Subject: [PATCH 580/703] drm/v3d: Update top-level kerneldoc for the addition
- of TFU.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20190207201001.5730-1-eric@anholt.net
-Reviewed-by: Thomas Spurden <thomas.spurden@broadcom.com>
-Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
-(cherry picked from commit fd347df16d4ed2eef565344b8f16a1134bddf185)
----
- drivers/gpu/drm/v3d/v3d_drv.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -7,9 +7,9 @@
- * This driver supports the Broadcom V3D 3.3 and 4.1 OpenGL ES GPUs.
- * For V3D 2.x support, see the VC4 driver.
- *
-- * Currently only single-core rendering using the binner and renderer
-- * is supported. The TFU (texture formatting unit) and V3D 4.x's CSD
-- * (compute shader dispatch) are not yet supported.
-+ * Currently only single-core rendering using the binner and renderer,
-+ * along with TFU (texture formatting unit) rendering is supported.
-+ * V3D 4.x's CSD (compute shader dispatch) is not yet supported.
- */
-
- #include <linux/clk.h>
--- /dev/null
+From cf9082f5c2ae9b9a85329cbb5a0651bcc36205a3 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 14 Jan 2019 17:26:04 -0800
+Subject: [PATCH 581/725] drm/v3d: Make sure the GPU is on when measuring
+ clocks.
+
+You'll get garbage measurements if the registers always read back
+0xdeadbeef
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_debugfs.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/gpu/drm/v3d/v3d_debugfs.c
++++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
+@@ -187,6 +187,11 @@ static int v3d_measure_clock(struct seq_
+ uint32_t cycles;
+ int core = 0;
+ int measure_ms = 1000;
++ int ret;
++
++ ret = pm_runtime_get_sync(v3d->dev);
++ if (ret < 0)
++ return ret;
+
+ if (v3d->ver >= 40) {
+ V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3,
+@@ -210,6 +215,9 @@ static int v3d_measure_clock(struct seq_
+ cycles / (measure_ms * 1000),
+ (cycles / (measure_ms * 100)) % 10);
+
++ pm_runtime_mark_last_busy(v3d->dev);
++ pm_runtime_put_autosuspend(v3d->dev);
++
+ return 0;
+ }
+
+++ /dev/null
-From 88066d8b4bd16fb094b74447684f474dd84092a9 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 4 Mar 2019 11:59:34 -0800
-Subject: [PATCH 581/703] drm/vc4: Fix oops at boot with firmwarekms on 4.19.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_kms.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -107,6 +107,9 @@ vc4_ctm_commit(struct vc4_dev *vc4, stru
- struct vc4_ctm_state *ctm_state = to_vc4_ctm_state(vc4->ctm_manager.state);
- struct drm_color_ctm *ctm = ctm_state->ctm;
-
-+ if (vc4->firmware_kms)
-+ return;
-+
- if (ctm_state->fifo) {
- HVS_WRITE(SCALER_OLEDCOEF2,
- VC4_SET_FIELD(vc4_ctm_s31_32_to_s0_9(ctm->matrix[0]),
--- /dev/null
+From c0584debae6e08806a3136b96e4378fe6ed8c908 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 4 Oct 2018 17:22:43 -0700
+Subject: [PATCH 582/725] drm/v3d: Add support for 2711.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_drv.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -235,6 +235,7 @@ static struct drm_driver v3d_drm_driver
+ static const struct of_device_id v3d_of_match[] = {
+ { .compatible = "brcm,7268-v3d" },
+ { .compatible = "brcm,7278-v3d" },
++ { .compatible = "brcm,2711-v3d" },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, v3d_of_match);
+++ /dev/null
-From 00f06424b180f1f6a3f52df718eae07c36fc72e5 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 20 Feb 2019 13:03:41 -0800
-Subject: [PATCH 582/703] drm/vc4: Disable V3D interactions if the v3d
- component didn't probe.
-
-One might want to use the VC4 display stack without using Mesa.
-Similar to the debugfs fixes for not having all of the possible
-display bits enabled, make sure you can't oops in vc4 if v3d isn't
-enabled.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_drv.c | 11 +++++++++++
- drivers/gpu/drm/vc4/vc4_gem.c | 10 ++++++++++
- drivers/gpu/drm/vc4/vc4_irq.c | 9 +++++++++
- drivers/gpu/drm/vc4/vc4_perfmon.c | 18 ++++++++++++++++++
- 4 files changed, 48 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_drv.c
-+++ b/drivers/gpu/drm/vc4/vc4_drv.c
-@@ -71,6 +71,9 @@ static int vc4_get_param_ioctl(struct dr
- if (args->pad != 0)
- return -EINVAL;
-
-+ if (!vc4->v3d)
-+ return -EINVAL;
-+
- switch (args->param) {
- case DRM_VC4_PARAM_V3D_IDENT0:
- ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
-@@ -271,6 +274,7 @@ static int vc4_drm_bind(struct device *d
- struct platform_device *pdev = to_platform_device(dev);
- struct drm_device *drm;
- struct vc4_dev *vc4;
-+ struct device_node *node;
- int ret = 0;
-
- dev->coherent_dma_mask = DMA_BIT_MASK(32);
-@@ -279,6 +283,13 @@ static int vc4_drm_bind(struct device *d
- if (!vc4)
- return -ENOMEM;
-
-+ /* If VC4 V3D is missing, don't advertise render nodes. */
-+ node = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-v3d");
-+ if (node)
-+ of_node_put(node);
-+ else
-+ vc4_drm_driver.driver_features &= ~DRIVER_RENDER;
-+
- drm = drm_dev_alloc(&vc4_drm_driver, dev);
- if (IS_ERR(drm))
- return PTR_ERR(drm);
---- a/drivers/gpu/drm/vc4/vc4_gem.c
-+++ b/drivers/gpu/drm/vc4/vc4_gem.c
-@@ -74,6 +74,11 @@ vc4_get_hang_state_ioctl(struct drm_devi
- u32 i;
- int ret = 0;
-
-+ if (!vc4->v3d) {
-+ DRM_DEBUG("VC4_GET_HANG_STATE with no VC4 V3D probed\n");
-+ return -EINVAL;
-+ }
-+
- spin_lock_irqsave(&vc4->job_lock, irqflags);
- kernel_state = vc4->hang_state;
- if (!kernel_state) {
-@@ -1124,6 +1129,11 @@ vc4_submit_cl_ioctl(struct drm_device *d
- struct dma_fence *in_fence;
- int ret = 0;
-
-+ if (!vc4->v3d) {
-+ DRM_DEBUG("VC4_SUBMIT_CL with no VC4 V3D probed\n");
-+ return -EINVAL;
-+ }
-+
- if ((args->flags & ~(VC4_SUBMIT_CL_USE_CLEAR_COLOR |
- VC4_SUBMIT_CL_FIXED_RCL_ORDER |
- VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X |
---- a/drivers/gpu/drm/vc4/vc4_irq.c
-+++ b/drivers/gpu/drm/vc4/vc4_irq.c
-@@ -229,6 +229,9 @@ vc4_irq_preinstall(struct drm_device *de
- {
- struct vc4_dev *vc4 = to_vc4_dev(dev);
-
-+ if (!vc4->v3d)
-+ return;
-+
- init_waitqueue_head(&vc4->job_wait_queue);
- INIT_WORK(&vc4->overflow_mem_work, vc4_overflow_mem_work);
-
-@@ -243,6 +246,9 @@ vc4_irq_postinstall(struct drm_device *d
- {
- struct vc4_dev *vc4 = to_vc4_dev(dev);
-
-+ if (!vc4->v3d)
-+ return 0;
-+
- /* Enable both the render done and out of memory interrupts. */
- V3D_WRITE(V3D_INTENA, V3D_DRIVER_IRQS);
-
-@@ -254,6 +260,9 @@ vc4_irq_uninstall(struct drm_device *dev
- {
- struct vc4_dev *vc4 = to_vc4_dev(dev);
-
-+ if (!vc4->v3d)
-+ return;
-+
- /* Disable sending interrupts for our driver's IRQs. */
- V3D_WRITE(V3D_INTDIS, V3D_DRIVER_IRQS);
-
---- a/drivers/gpu/drm/vc4/vc4_perfmon.c
-+++ b/drivers/gpu/drm/vc4/vc4_perfmon.c
-@@ -100,12 +100,18 @@ void vc4_perfmon_close_file(struct vc4_f
- int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
- {
-+ struct vc4_dev *vc4 = to_vc4_dev(dev);
- struct vc4_file *vc4file = file_priv->driver_priv;
- struct drm_vc4_perfmon_create *req = data;
- struct vc4_perfmon *perfmon;
- unsigned int i;
- int ret;
-
-+ if (!vc4->v3d) {
-+ DRM_DEBUG("Creating perfmon no VC4 V3D probed\n");
-+ return -EINVAL;
-+ }
-+
- /* Number of monitored counters cannot exceed HW limits. */
- if (req->ncounters > DRM_VC4_MAX_PERF_COUNTERS ||
- !req->ncounters)
-@@ -146,10 +152,16 @@ int vc4_perfmon_create_ioctl(struct drm_
- int vc4_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
- {
-+ struct vc4_dev *vc4 = to_vc4_dev(dev);
- struct vc4_file *vc4file = file_priv->driver_priv;
- struct drm_vc4_perfmon_destroy *req = data;
- struct vc4_perfmon *perfmon;
-
-+ if (!vc4->v3d) {
-+ DRM_DEBUG("Destroying perfmon no VC4 V3D probed\n");
-+ return -EINVAL;
-+ }
-+
- mutex_lock(&vc4file->perfmon.lock);
- perfmon = idr_remove(&vc4file->perfmon.idr, req->id);
- mutex_unlock(&vc4file->perfmon.lock);
-@@ -164,11 +176,17 @@ int vc4_perfmon_destroy_ioctl(struct drm
- int vc4_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
- {
-+ struct vc4_dev *vc4 = to_vc4_dev(dev);
- struct vc4_file *vc4file = file_priv->driver_priv;
- struct drm_vc4_perfmon_get_values *req = data;
- struct vc4_perfmon *perfmon;
- int ret;
-
-+ if (!vc4->v3d) {
-+ DRM_DEBUG("Getting perfmon no VC4 V3D probed\n");
-+ return -EINVAL;
-+ }
-+
- mutex_lock(&vc4file->perfmon.lock);
- perfmon = idr_find(&vc4file->perfmon.idr, req->id);
- vc4_perfmon_get(perfmon);
+++ /dev/null
-From 8169ec547bf6719c89c3ed88f9884bb9dd84479d Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 4 Oct 2018 17:22:43 -0700
-Subject: [PATCH 583/703] drm/v3d: Add support for V3D v4.2.
-
-No compatible string for it yet, just the version-dependent changes.
-They've now tied the hub and the core interrupt lines into a single
-interrupt line coming out of the block. It also turns out I made a
-mistake in modeling the V3D v3.3 and v4.1 bridge as a part of V3D
-itself -- the bridge is going away in favor of an external reset
-controller in a larger HW module.
-
-v2: Use consistent checks for whether we're on 4.2, and fix a leak in
- an error path.
-v3: Use more general means of determining if the current 4.2 changes
- are in place, as apparently other platforms may switch back (noted
- by Dave). Update the binding doc.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- .../devicetree/bindings/gpu/brcm,bcm-v3d.txt | 11 ++++--
- drivers/gpu/drm/v3d/v3d_drv.c | 21 +++++++++---
- drivers/gpu/drm/v3d/v3d_drv.h | 2 ++
- drivers/gpu/drm/v3d/v3d_gem.c | 12 ++++++-
- drivers/gpu/drm/v3d/v3d_irq.c | 34 ++++++++++++++-----
- 5 files changed, 63 insertions(+), 17 deletions(-)
-
---- a/Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.txt
-+++ b/Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.txt
-@@ -6,15 +6,20 @@ For V3D 2.x, see brcm,bcm-vc4.txt.
- Required properties:
- - compatible: Should be "brcm,7268-v3d" or "brcm,7278-v3d"
- - reg: Physical base addresses and lengths of the register areas
--- reg-names: Names for the register areas. The "hub", "bridge", and "core0"
-+- reg-names: Names for the register areas. The "hub" and "core0"
- register areas are always required. The "gca" register area
-- is required if the GCA cache controller is present.
-+ is required if the GCA cache controller is present. The
-+ "bridge" register area is required if an external reset
-+ controller is not present.
- - interrupts: The interrupt numbers. The first interrupt is for the hub,
-- while the following interrupts are for the cores.
-+ while the following interrupts are separate interrupt lines
-+ for the cores (if they don't share the hub's interrupt).
- See bindings/interrupt-controller/interrupts.txt
-
- Optional properties:
- - clocks: The core clock the unit runs on
-+- resets: The reset line for v3d, if not using a mapping of the bridge
-+ See bindings/reset/reset.txt
-
- v3d {
- compatible = "brcm,7268-v3d";
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -19,6 +19,7 @@
- #include <linux/of_platform.h>
- #include <linux/platform_device.h>
- #include <linux/pm_runtime.h>
-+#include <linux/reset.h>
- #include <drm/drm_fb_cma_helper.h>
- #include <drm/drm_fb_helper.h>
-
-@@ -265,10 +266,6 @@ static int v3d_platform_drm_probe(struct
- v3d->pdev = pdev;
- drm = &v3d->drm;
-
-- ret = map_regs(v3d, &v3d->bridge_regs, "bridge");
-- if (ret)
-- goto dev_free;
--
- ret = map_regs(v3d, &v3d->hub_regs, "hub");
- if (ret)
- goto dev_free;
-@@ -283,6 +280,22 @@ static int v3d_platform_drm_probe(struct
- v3d->cores = V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_NCORES);
- WARN_ON(v3d->cores > 1); /* multicore not yet implemented */
-
-+ v3d->reset = devm_reset_control_get_exclusive(dev, NULL);
-+ if (IS_ERR(v3d->reset)) {
-+ ret = PTR_ERR(v3d->reset);
-+
-+ if (ret == -EPROBE_DEFER)
-+ goto dev_free;
-+
-+ v3d->reset = NULL;
-+ ret = map_regs(v3d, &v3d->bridge_regs, "bridge");
-+ if (ret) {
-+ dev_err(dev,
-+ "Failed to get reset control or bridge regs\n");
-+ goto dev_free;
-+ }
-+ }
-+
- if (v3d->ver < 41) {
- ret = map_regs(v3d, &v3d->gca_regs, "gca");
- if (ret)
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -34,6 +34,7 @@ struct v3d_dev {
- * and revision.
- */
- int ver;
-+ bool single_irq_line;
-
- struct device *dev;
- struct platform_device *pdev;
-@@ -42,6 +43,7 @@ struct v3d_dev {
- void __iomem *bridge_regs;
- void __iomem *gca_regs;
- struct clk *clk;
-+ struct reset_control *reset;
-
- /* Virtual and DMA addresses of the single shared page table. */
- volatile u32 *pt;
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -6,6 +6,7 @@
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/pm_runtime.h>
-+#include <linux/reset.h>
- #include <linux/device.h>
- #include <linux/io.h>
- #include <linux/sched/signal.h>
-@@ -69,7 +70,7 @@ v3d_idle_gca(struct v3d_dev *v3d)
- }
-
- static void
--v3d_reset_v3d(struct v3d_dev *v3d)
-+v3d_reset_by_bridge(struct v3d_dev *v3d)
- {
- int version = V3D_BRIDGE_READ(V3D_TOP_GR_BRIDGE_REVISION);
-
-@@ -89,6 +90,15 @@ v3d_reset_v3d(struct v3d_dev *v3d)
- V3D_TOP_GR_BRIDGE_SW_INIT_1_V3D_CLK_108_SW_INIT);
- V3D_BRIDGE_WRITE(V3D_TOP_GR_BRIDGE_SW_INIT_1, 0);
- }
-+}
-+
-+static void
-+v3d_reset_v3d(struct v3d_dev *v3d)
-+{
-+ if (v3d->reset)
-+ reset_control_reset(v3d->reset);
-+ else
-+ v3d_reset_by_bridge(v3d);
-
- v3d_init_hw_state(v3d);
- }
---- a/drivers/gpu/drm/v3d/v3d_irq.c
-+++ b/drivers/gpu/drm/v3d/v3d_irq.c
-@@ -27,6 +27,9 @@
- V3D_HUB_INT_MMU_CAP | \
- V3D_HUB_INT_TFUC))
-
-+static irqreturn_t
-+v3d_hub_irq(int irq, void *arg);
-+
- static void
- v3d_overflow_mem_work(struct work_struct *work)
- {
-@@ -112,6 +115,12 @@ v3d_irq(int irq, void *arg)
- if (intsts & V3D_INT_GMPV)
- dev_err(v3d->dev, "GMP violation\n");
-
-+ /* V3D 4.2 wires the hub and core IRQs together, so if we &
-+ * didn't see the common one then check hub for MMU IRQs.
-+ */
-+ if (v3d->single_irq_line && status == IRQ_NONE)
-+ return v3d_hub_irq(irq, arg);
-+
- return status;
- }
-
-@@ -170,15 +179,22 @@ v3d_irq_init(struct v3d_dev *v3d)
- V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS);
- V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS);
-
-- ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
-- v3d_hub_irq, IRQF_SHARED,
-- "v3d_hub", v3d);
-- if (ret)
-- goto fail;
--
-- ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 1),
-- v3d_irq, IRQF_SHARED,
-- "v3d_core0", v3d);
-+ if (platform_get_irq(v3d->pdev, 1) < 0) {
-+ ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
-+ v3d_irq, IRQF_SHARED,
-+ "v3d", v3d);
-+ v3d->single_irq_line = true;
-+ } else {
-+ ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
-+ v3d_hub_irq, IRQF_SHARED,
-+ "v3d_hub", v3d);
-+ if (ret)
-+ goto fail;
-+
-+ ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 1),
-+ v3d_irq, IRQF_SHARED,
-+ "v3d_core0", v3d);
-+ }
- if (ret)
- goto fail;
-
--- /dev/null
+From 7cfea1be1c757c983e632f56dc8f9dde42c9170d Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 14 Jan 2019 12:35:43 -0800
+Subject: [PATCH 583/725] drm/v3d: Skip MMU flush if the device is currently
+ off.
+
+If it's off, we know it will be reset on poweron, so the MMU won't
+have any TLB cached from before this point. Avoids failed waits for
+MMU flush to reply.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+(cherry picked from commit 3ee4e2e0a9e9587eacbb69b067bbc72ab2cdc47b)
+---
+ drivers/gpu/drm/v3d/v3d_mmu.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/drivers/gpu/drm/v3d/v3d_mmu.c
++++ b/drivers/gpu/drm/v3d/v3d_mmu.c
+@@ -18,6 +18,8 @@
+ * each client. This is not yet implemented.
+ */
+
++#include <linux/pm_runtime.h>
++
+ #include "v3d_drv.h"
+ #include "v3d_regs.h"
+
+@@ -34,6 +36,14 @@ static int v3d_mmu_flush_all(struct v3d_
+ {
+ int ret;
+
++ /* Keep power on the device on until we're done with this
++ * call, but skip the flush if the device is off and will be
++ * reset when powered back on.
++ */
++ ret = pm_runtime_get_if_in_use(v3d->dev);
++ if (ret == 0)
++ return 0;
++
+ /* Make sure that another flush isn't already running when we
+ * start this one.
+ */
+@@ -61,6 +71,9 @@ static int v3d_mmu_flush_all(struct v3d_
+ if (ret)
+ dev_err(v3d->dev, "MMUC flush wait idle failed\n");
+
++ pm_runtime_mark_last_busy(v3d->dev);
++ pm_runtime_put_autosuspend(v3d->dev);
++
+ return ret;
+ }
+
+++ /dev/null
-From d4b98e9e78d87fe34b89077b9776a66f19d23856 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Tue, 16 Oct 2018 10:13:41 -0700
-Subject: [PATCH 584/703] drm/v3d: Don't try to set OVRTMUOUT on V3D 4.x.
-
-The old field is gone and the register now has a different field,
-QRMAXCNT for how many TMU requests get serviced before thread switch.
-We were accidentally reducing it from its default of 0x3 (4 requests)
-to 0x0 (1).
-
-v2: Skip setting the reg at all on 4.x, instead of trying to update
- only the old field.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_gem.c | 3 ++-
- drivers/gpu/drm/v3d/v3d_regs.h | 2 ++
- 2 files changed, 4 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -25,7 +25,8 @@ v3d_init_core(struct v3d_dev *v3d, int c
- * type. If you want the default behavior, you can still put
- * "2" in the indirect texture state's output_type field.
- */
-- V3D_CORE_WRITE(core, V3D_CTL_MISCCFG, V3D_MISCCFG_OVRTMUOUT);
-+ if (v3d->ver < 40)
-+ V3D_CORE_WRITE(core, V3D_CTL_MISCCFG, V3D_MISCCFG_OVRTMUOUT);
-
- /* Whenever we flush the L2T cache, we always want to flush
- * the whole thing.
---- a/drivers/gpu/drm/v3d/v3d_regs.h
-+++ b/drivers/gpu/drm/v3d/v3d_regs.h
-@@ -216,6 +216,8 @@
- # define V3D_IDENT2_BCG_INT BIT(28)
-
- #define V3D_CTL_MISCCFG 0x00018
-+# define V3D_CTL_MISCCFG_QRMAXCNT_MASK V3D_MASK(3, 1)
-+# define V3D_CTL_MISCCFG_QRMAXCNT_SHIFT 1
- # define V3D_MISCCFG_OVRTMUOUT BIT(0)
-
- #define V3D_CTL_L2CACTL 0x00020
--- /dev/null
+From f436620c2c61e76adcd2d4d694ad9f4d87f301e3 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 14 Jan 2019 14:47:57 -0800
+Subject: [PATCH 584/725] drm/v3d: Hook up the runtime PM ops.
+
+In translating the runtime PM code from vc4, I missed the ".pm"
+assignment to actually connect them up. Fixes missing MMU setup if
+runtime PM resets V3D.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+(cherry picked from commit ca197699af29baa8236c74c53d4904ca8957ee06)
+---
+ drivers/gpu/drm/v3d/v3d_drv.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -66,7 +66,7 @@ static int v3d_runtime_resume(struct dev
+ }
+ #endif
+
+-static const struct dev_pm_ops v3d_v3d_pm_ops = {
++static const struct dev_pm_ops v3d_pm_ops = {
+ SET_RUNTIME_PM_OPS(v3d_runtime_suspend, v3d_runtime_resume, NULL)
+ };
+
+@@ -371,6 +371,7 @@ static struct platform_driver v3d_platfo
+ .driver = {
+ .name = "v3d",
+ .of_match_table = v3d_of_match,
++ .pm = &v3d_pm_ops,
+ },
+ };
+
--- /dev/null
+From f9ed79254b9bc0063bd65ebc1ef0b5b789e81e17 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 14 Jan 2019 15:13:17 -0800
+Subject: [PATCH 585/725] drm/v3d: HACK: gut runtime pm for now.
+
+Something is still unstable -- on starting a new glxgears from an idle
+X11, I get an MMU violation in high addresses. The CTS also failed
+quite quickly. With this, CTS progresses for an hour before OOMing
+(allocating some big buffers when my board only has 600MB available to
+Linux)
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_debugfs.c | 16 +---------------
+ drivers/gpu/drm/v3d/v3d_drv.c | 7 -------
+ drivers/gpu/drm/v3d/v3d_gem.c | 20 --------------------
+ 3 files changed, 1 insertion(+), 42 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_debugfs.c
++++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
+@@ -4,7 +4,6 @@
+ #include <linux/circ_buf.h>
+ #include <linux/ctype.h>
+ #include <linux/debugfs.h>
+-#include <linux/pm_runtime.h>
+ #include <linux/seq_file.h>
+ #include <drm/drmP.h>
+
+@@ -100,11 +99,8 @@ static int v3d_v3d_debugfs_ident(struct
+ struct drm_device *dev = node->minor->dev;
+ struct v3d_dev *v3d = to_v3d_dev(dev);
+ u32 ident0, ident1, ident2, ident3, cores;
+- int ret, core;
++ int core;
+
+- ret = pm_runtime_get_sync(v3d->dev);
+- if (ret < 0)
+- return ret;
+
+ ident0 = V3D_READ(V3D_HUB_IDENT0);
+ ident1 = V3D_READ(V3D_HUB_IDENT1);
+@@ -157,9 +153,6 @@ static int v3d_v3d_debugfs_ident(struct
+ (misccfg & V3D_MISCCFG_OVRTMUOUT) != 0);
+ }
+
+- pm_runtime_mark_last_busy(v3d->dev);
+- pm_runtime_put_autosuspend(v3d->dev);
+-
+ return 0;
+ }
+
+@@ -187,11 +180,6 @@ static int v3d_measure_clock(struct seq_
+ uint32_t cycles;
+ int core = 0;
+ int measure_ms = 1000;
+- int ret;
+-
+- ret = pm_runtime_get_sync(v3d->dev);
+- if (ret < 0)
+- return ret;
+
+ if (v3d->ver >= 40) {
+ V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3,
+@@ -215,8 +203,6 @@ static int v3d_measure_clock(struct seq_
+ cycles / (measure_ms * 1000),
+ (cycles / (measure_ms * 100)) % 10);
+
+- pm_runtime_mark_last_busy(v3d->dev);
+- pm_runtime_put_autosuspend(v3d->dev);
+
+ return 0;
+ }
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -75,7 +75,6 @@ static int v3d_get_param_ioctl(struct dr
+ {
+ struct v3d_dev *v3d = to_v3d_dev(dev);
+ struct drm_v3d_get_param *args = data;
+- int ret;
+ static const u32 reg_map[] = {
+ [DRM_V3D_PARAM_V3D_UIFCFG] = V3D_HUB_UIFCFG,
+ [DRM_V3D_PARAM_V3D_HUB_IDENT1] = V3D_HUB_IDENT1,
+@@ -101,15 +100,12 @@ static int v3d_get_param_ioctl(struct dr
+ if (args->value != 0)
+ return -EINVAL;
+
+- ret = pm_runtime_get_sync(v3d->dev);
+ if (args->param >= DRM_V3D_PARAM_V3D_CORE0_IDENT0 &&
+ args->param <= DRM_V3D_PARAM_V3D_CORE0_IDENT2) {
+ args->value = V3D_CORE_READ(0, offset);
+ } else {
+ args->value = V3D_READ(offset);
+ }
+- pm_runtime_mark_last_busy(v3d->dev);
+- pm_runtime_put_autosuspend(v3d->dev);
+ return 0;
+ }
+
+@@ -311,9 +307,6 @@ static int v3d_platform_drm_probe(struct
+ goto dev_free;
+ }
+
+- pm_runtime_use_autosuspend(dev);
+- pm_runtime_set_autosuspend_delay(dev, 50);
+- pm_runtime_enable(dev);
+
+ ret = drm_dev_init(&v3d->drm, &v3d_drm_driver, dev);
+ if (ret)
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -375,7 +375,6 @@ v3d_exec_cleanup(struct kref *ref)
+ {
+ struct v3d_exec_info *exec = container_of(ref, struct v3d_exec_info,
+ refcount);
+- struct v3d_dev *v3d = exec->v3d;
+ unsigned int i;
+ struct v3d_bo *bo, *save;
+
+@@ -396,9 +395,6 @@ v3d_exec_cleanup(struct kref *ref)
+ drm_gem_object_put_unlocked(&bo->base);
+ }
+
+- pm_runtime_mark_last_busy(v3d->dev);
+- pm_runtime_put_autosuspend(v3d->dev);
+-
+ kfree(exec);
+ }
+
+@@ -412,7 +408,6 @@ v3d_tfu_job_cleanup(struct kref *ref)
+ {
+ struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,
+ refcount);
+- struct v3d_dev *v3d = job->v3d;
+ unsigned int i;
+
+ dma_fence_put(job->in_fence);
+@@ -423,9 +418,6 @@ v3d_tfu_job_cleanup(struct kref *ref)
+ drm_gem_object_put_unlocked(&job->bo[i]->base);
+ }
+
+- pm_runtime_mark_last_busy(v3d->dev);
+- pm_runtime_put_autosuspend(v3d->dev);
+-
+ kfree(job);
+ }
+
+@@ -519,12 +511,6 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ if (!exec)
+ return -ENOMEM;
+
+- ret = pm_runtime_get_sync(v3d->dev);
+- if (ret < 0) {
+- kfree(exec);
+- return ret;
+- }
+-
+ kref_init(&exec->refcount);
+
+ ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,
+@@ -643,12 +629,6 @@ v3d_submit_tfu_ioctl(struct drm_device *
+ if (!job)
+ return -ENOMEM;
+
+- ret = pm_runtime_get_sync(v3d->dev);
+- if (ret < 0) {
+- kfree(job);
+- return ret;
+- }
+-
+ kref_init(&job->refcount);
+
+ ret = drm_syncobj_find_fence(file_priv, args->in_sync,
+++ /dev/null
-From 51a1e9604fdd215581d7974a185809b1ac93adac Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 14 Jan 2019 17:26:04 -0800
-Subject: [PATCH 585/703] drm/v3d: Make sure the GPU is on when measuring
- clocks.
-
-You'll get garbage measurements if the registers always read back
-0xdeadbeef
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_debugfs.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/drivers/gpu/drm/v3d/v3d_debugfs.c
-+++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
-@@ -187,6 +187,11 @@ static int v3d_measure_clock(struct seq_
- uint32_t cycles;
- int core = 0;
- int measure_ms = 1000;
-+ int ret;
-+
-+ ret = pm_runtime_get_sync(v3d->dev);
-+ if (ret < 0)
-+ return ret;
-
- if (v3d->ver >= 40) {
- V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3,
-@@ -210,6 +215,9 @@ static int v3d_measure_clock(struct seq_
- cycles / (measure_ms * 1000),
- (cycles / (measure_ms * 100)) % 10);
-
-+ pm_runtime_mark_last_busy(v3d->dev);
-+ pm_runtime_put_autosuspend(v3d->dev);
-+
- return 0;
- }
-
+++ /dev/null
-From 2990828736d42f8308e9ef4e5ca0e8165c952eea Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 4 Oct 2018 17:22:43 -0700
-Subject: [PATCH 586/703] drm/v3d: Add support for 2711.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_drv.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -235,6 +235,7 @@ static struct drm_driver v3d_drm_driver
- static const struct of_device_id v3d_of_match[] = {
- { .compatible = "brcm,7268-v3d" },
- { .compatible = "brcm,7278-v3d" },
-+ { .compatible = "brcm,2711-v3d" },
- {},
- };
- MODULE_DEVICE_TABLE(of, v3d_of_match);
--- /dev/null
+From 1e3a40ffdfe1bafc7e0a0dcbeeff92a1f2a6655b Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 12 Mar 2019 09:08:10 -0700
+Subject: [PATCH 586/725] drm/v3d: Update to upstream IRQ code.
+
+---
+ drivers/gpu/drm/v3d/v3d_irq.c | 25 +++++++++++++++----------
+ 1 file changed, 15 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -168,7 +168,7 @@ v3d_hub_irq(int irq, void *arg)
+ int
+ v3d_irq_init(struct v3d_dev *v3d)
+ {
+- int ret, core;
++ int irq1, ret, core;
+
+ INIT_WORK(&v3d->overflow_mem_work, v3d_overflow_mem_work);
+
+@@ -179,24 +179,29 @@ v3d_irq_init(struct v3d_dev *v3d)
+ V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS);
+ V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS);
+
+- if (platform_get_irq(v3d->pdev, 1) < 0) {
+- ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
++ irq1 = platform_get_irq(v3d->pdev, 1);
++ if (irq1 == -EPROBE_DEFER)
++ return irq1;
++ if (irq1 > 0) {
++ ret = devm_request_irq(v3d->dev, irq1,
+ v3d_irq, IRQF_SHARED,
+- "v3d", v3d);
+- v3d->single_irq_line = true;
+- } else {
++ "v3d_core0", v3d);
++ if (ret)
++ goto fail;
+ ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
+ v3d_hub_irq, IRQF_SHARED,
+ "v3d_hub", v3d);
+ if (ret)
+ goto fail;
++ } else {
++ v3d->single_irq_line = true;
+
+- ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 1),
++ ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
+ v3d_irq, IRQF_SHARED,
+- "v3d_core0", v3d);
++ "v3d", v3d);
++ if (ret)
++ goto fail;
+ }
+- if (ret)
+- goto fail;
+
+ v3d_irq_enable(v3d);
+ return 0;
--- /dev/null
+From 17b0b9ba33df31ade992e46501f1b03296b758c7 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 27 Dec 2018 14:04:44 -0800
+Subject: [PATCH 587/725] drm/v3d: Rename the fence signaled from IRQs to
+ "irq_fence".
+
+We have another thing called the "done fence" that tracks when the
+scheduler considers the job done, and having the shared name was
+confusing.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_drv.h | 4 ++--
+ drivers/gpu/drm/v3d/v3d_gem.c | 6 +++---
+ drivers/gpu/drm/v3d/v3d_irq.c | 6 +++---
+ drivers/gpu/drm/v3d/v3d_sched.c | 12 ++++++------
+ 4 files changed, 14 insertions(+), 14 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -182,7 +182,7 @@ struct v3d_job {
+ struct dma_fence *in_fence;
+
+ /* v3d fence to be signaled by IRQ handler when the job is complete. */
+- struct dma_fence *done_fence;
++ struct dma_fence *irq_fence;
+
+ /* GPU virtual addresses of the start/end of the CL job. */
+ u32 start, end;
+@@ -229,7 +229,7 @@ struct v3d_tfu_job {
+ struct dma_fence *in_fence;
+
+ /* v3d fence to be signaled by IRQ handler when the job is complete. */
+- struct dma_fence *done_fence;
++ struct dma_fence *irq_fence;
+
+ struct v3d_dev *v3d;
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -381,8 +381,8 @@ v3d_exec_cleanup(struct kref *ref)
+ dma_fence_put(exec->bin.in_fence);
+ dma_fence_put(exec->render.in_fence);
+
+- dma_fence_put(exec->bin.done_fence);
+- dma_fence_put(exec->render.done_fence);
++ dma_fence_put(exec->bin.irq_fence);
++ dma_fence_put(exec->render.irq_fence);
+
+ dma_fence_put(exec->bin_done_fence);
+ dma_fence_put(exec->render_done_fence);
+@@ -411,7 +411,7 @@ v3d_tfu_job_cleanup(struct kref *ref)
+ unsigned int i;
+
+ dma_fence_put(job->in_fence);
+- dma_fence_put(job->done_fence);
++ dma_fence_put(job->irq_fence);
+
+ for (i = 0; i < ARRAY_SIZE(job->bo); i++) {
+ if (job->bo[i])
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -93,7 +93,7 @@ v3d_irq(int irq, void *arg)
+
+ if (intsts & V3D_INT_FLDONE) {
+ struct v3d_fence *fence =
+- to_v3d_fence(v3d->bin_job->bin.done_fence);
++ to_v3d_fence(v3d->bin_job->bin.irq_fence);
+
+ trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
+ dma_fence_signal(&fence->base);
+@@ -102,7 +102,7 @@ v3d_irq(int irq, void *arg)
+
+ if (intsts & V3D_INT_FRDONE) {
+ struct v3d_fence *fence =
+- to_v3d_fence(v3d->render_job->render.done_fence);
++ to_v3d_fence(v3d->render_job->render.irq_fence);
+
+ trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
+ dma_fence_signal(&fence->base);
+@@ -138,7 +138,7 @@ v3d_hub_irq(int irq, void *arg)
+
+ if (intsts & V3D_HUB_INT_TFUC) {
+ struct v3d_fence *fence =
+- to_v3d_fence(v3d->tfu_job->done_fence);
++ to_v3d_fence(v3d->tfu_job->irq_fence);
+
+ trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
+ dma_fence_signal(&fence->base);
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -152,9 +152,9 @@ static struct dma_fence *v3d_job_run(str
+ if (IS_ERR(fence))
+ return NULL;
+
+- if (job->done_fence)
+- dma_fence_put(job->done_fence);
+- job->done_fence = dma_fence_get(fence);
++ if (job->irq_fence)
++ dma_fence_put(job->irq_fence);
++ job->irq_fence = dma_fence_get(fence);
+
+ trace_v3d_submit_cl(dev, q == V3D_RENDER, to_v3d_fence(fence)->seqno,
+ job->start, job->end);
+@@ -195,9 +195,9 @@ v3d_tfu_job_run(struct drm_sched_job *sc
+ return NULL;
+
+ v3d->tfu_job = job;
+- if (job->done_fence)
+- dma_fence_put(job->done_fence);
+- job->done_fence = dma_fence_get(fence);
++ if (job->irq_fence)
++ dma_fence_put(job->irq_fence);
++ job->irq_fence = dma_fence_get(fence);
+
+ trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
+
+++ /dev/null
-From 2e3f1f0991163004ea441307ab52ce4ea3e068d7 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 14 Jan 2019 12:35:43 -0800
-Subject: [PATCH 587/703] drm/v3d: Skip MMU flush if the device is currently
- off.
-
-If it's off, we know it will be reset on poweron, so the MMU won't
-have any TLB cached from before this point. Avoids failed waits for
-MMU flush to reply.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-(cherry picked from commit 3ee4e2e0a9e9587eacbb69b067bbc72ab2cdc47b)
----
- drivers/gpu/drm/v3d/v3d_mmu.c | 13 +++++++++++++
- 1 file changed, 13 insertions(+)
-
---- a/drivers/gpu/drm/v3d/v3d_mmu.c
-+++ b/drivers/gpu/drm/v3d/v3d_mmu.c
-@@ -18,6 +18,8 @@
- * each client. This is not yet implemented.
- */
-
-+#include <linux/pm_runtime.h>
-+
- #include "v3d_drv.h"
- #include "v3d_regs.h"
-
-@@ -34,6 +36,14 @@ static int v3d_mmu_flush_all(struct v3d_
- {
- int ret;
-
-+ /* Keep power on the device on until we're done with this
-+ * call, but skip the flush if the device is off and will be
-+ * reset when powered back on.
-+ */
-+ ret = pm_runtime_get_if_in_use(v3d->dev);
-+ if (ret == 0)
-+ return 0;
-+
- /* Make sure that another flush isn't already running when we
- * start this one.
- */
-@@ -61,6 +71,9 @@ static int v3d_mmu_flush_all(struct v3d_
- if (ret)
- dev_err(v3d->dev, "MMUC flush wait idle failed\n");
-
-+ pm_runtime_mark_last_busy(v3d->dev);
-+ pm_runtime_put_autosuspend(v3d->dev);
-+
- return ret;
- }
-
+++ /dev/null
-From ee17d7708bdf44fb3e04045c661b317245d90c1a Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 14 Jan 2019 14:47:57 -0800
-Subject: [PATCH 588/703] drm/v3d: Hook up the runtime PM ops.
-
-In translating the runtime PM code from vc4, I missed the ".pm"
-assignment to actually connect them up. Fixes missing MMU setup if
-runtime PM resets V3D.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-(cherry picked from commit ca197699af29baa8236c74c53d4904ca8957ee06)
----
- drivers/gpu/drm/v3d/v3d_drv.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -66,7 +66,7 @@ static int v3d_runtime_resume(struct dev
- }
- #endif
-
--static const struct dev_pm_ops v3d_v3d_pm_ops = {
-+static const struct dev_pm_ops v3d_pm_ops = {
- SET_RUNTIME_PM_OPS(v3d_runtime_suspend, v3d_runtime_resume, NULL)
- };
-
-@@ -371,6 +371,7 @@ static struct platform_driver v3d_platfo
- .driver = {
- .name = "v3d",
- .of_match_table = v3d_of_match,
-+ .pm = &v3d_pm_ops,
- },
- };
-
--- /dev/null
+From 83e671a4dbca6b0a1d2fad326f6cb8316d25e9e0 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 27 Dec 2018 12:11:52 -0800
+Subject: [PATCH 588/725] drm/v3d: Refactor job management.
+
+The CL submission had two jobs embedded in an exec struct. When I
+added TFU support, I had to replicate some of the exec stuff and some
+of the job stuff. As I went to add CSD, it became clear that actually
+what was in exec should just be in the two CL jobs, and it would let
+us share a lot more code between the 4 queues.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_drv.h | 77 ++++----
+ drivers/gpu/drm/v3d/v3d_gem.c | 331 +++++++++++++++++---------------
+ drivers/gpu/drm/v3d/v3d_irq.c | 8 +-
+ drivers/gpu/drm/v3d/v3d_sched.c | 264 ++++++++++++++-----------
+ 4 files changed, 373 insertions(+), 307 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -67,8 +67,8 @@ struct v3d_dev {
+
+ struct work_struct overflow_mem_work;
+
+- struct v3d_exec_info *bin_job;
+- struct v3d_exec_info *render_job;
++ struct v3d_bin_job *bin_job;
++ struct v3d_render_job *render_job;
+ struct v3d_tfu_job *tfu_job;
+
+ struct v3d_queue_state queue[V3D_MAX_QUEUES];
+@@ -132,7 +132,7 @@ struct v3d_bo {
+ struct list_head vmas; /* list of v3d_vma */
+
+ /* List entry for the BO's position in
+- * v3d_exec_info->unref_list
++ * v3d_render_job->unref_list
+ */
+ struct list_head unref_head;
+
+@@ -176,7 +176,15 @@ to_v3d_fence(struct dma_fence *fence)
+ struct v3d_job {
+ struct drm_sched_job base;
+
+- struct v3d_exec_info *exec;
++ struct kref refcount;
++
++ struct v3d_dev *v3d;
++
++ /* This is the array of BOs that were looked up at the start
++ * of submission.
++ */
++ struct v3d_bo **bo;
++ u32 bo_count;
+
+ /* An optional fence userspace can pass in for the job to depend on. */
+ struct dma_fence *in_fence;
+@@ -184,59 +192,53 @@ struct v3d_job {
+ /* v3d fence to be signaled by IRQ handler when the job is complete. */
+ struct dma_fence *irq_fence;
+
++ /* scheduler fence for when the job is considered complete and
++ * the BO reservations can be released.
++ */
++ struct dma_fence *done_fence;
++
++ /* Callback for the freeing of the job on refcount going to 0. */
++ void (*free)(struct kref *ref);
++};
++
++struct v3d_bin_job {
++ struct v3d_job base;
++
+ /* GPU virtual addresses of the start/end of the CL job. */
+ u32 start, end;
+
+ u32 timedout_ctca, timedout_ctra;
+-};
+
+-struct v3d_exec_info {
+- struct v3d_dev *v3d;
++ /* Corresponding render job, for attaching our overflow memory. */
++ struct v3d_render_job *render;
++
++ /* Submitted tile memory allocation start/size, tile state. */
++ u32 qma, qms, qts;
++};
+
+- struct v3d_job bin, render;
++struct v3d_render_job {
++ struct v3d_job base;
+
+- /* Fence for when the scheduler considers the binner to be
+- * done, for render to depend on.
++ /* Optional fence for the binner, to depend on before starting
++ * our job.
+ */
+ struct dma_fence *bin_done_fence;
+
+- /* Fence for when the scheduler considers the render to be
+- * done, for when the BOs reservations should be complete.
+- */
+- struct dma_fence *render_done_fence;
+-
+- struct kref refcount;
++ /* GPU virtual addresses of the start/end of the CL job. */
++ u32 start, end;
+
+- /* This is the array of BOs that were looked up at the start of exec. */
+- struct v3d_bo **bo;
+- u32 bo_count;
++ u32 timedout_ctca, timedout_ctra;
+
+ /* List of overflow BOs used in the job that need to be
+ * released once the job is complete.
+ */
+ struct list_head unref_list;
+-
+- /* Submitted tile memory allocation start/size, tile state. */
+- u32 qma, qms, qts;
+ };
+
+ struct v3d_tfu_job {
+- struct drm_sched_job base;
++ struct v3d_job base;
+
+ struct drm_v3d_submit_tfu args;
+-
+- /* An optional fence userspace can pass in for the job to depend on. */
+- struct dma_fence *in_fence;
+-
+- /* v3d fence to be signaled by IRQ handler when the job is complete. */
+- struct dma_fence *irq_fence;
+-
+- struct v3d_dev *v3d;
+-
+- struct kref refcount;
+-
+- /* This is the array of BOs that were looked up at the start of exec. */
+- struct v3d_bo *bo[4];
+ };
+
+ /**
+@@ -306,8 +308,7 @@ int v3d_submit_tfu_ioctl(struct drm_devi
+ struct drm_file *file_priv);
+ int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+-void v3d_exec_put(struct v3d_exec_info *exec);
+-void v3d_tfu_job_put(struct v3d_tfu_job *exec);
++void v3d_job_put(struct v3d_job *job);
+ void v3d_reset(struct v3d_dev *v3d);
+ void v3d_invalidate_caches(struct v3d_dev *v3d);
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -293,11 +293,11 @@ retry:
+ }
+
+ /**
+- * v3d_cl_lookup_bos() - Sets up exec->bo[] with the GEM objects
++ * v3d_lookup_bos() - Sets up job->bo[] with the GEM objects
+ * referenced by the job.
+ * @dev: DRM device
+ * @file_priv: DRM file for this fd
+- * @exec: V3D job being set up
++ * @job: V3D job being set up
+ *
+ * The command validator needs to reference BOs by their index within
+ * the submitted job's BO list. This does the validation of the job's
+@@ -307,18 +307,19 @@ retry:
+ * failure, because that will happen at v3d_exec_cleanup() time.
+ */
+ static int
+-v3d_cl_lookup_bos(struct drm_device *dev,
+- struct drm_file *file_priv,
+- struct drm_v3d_submit_cl *args,
+- struct v3d_exec_info *exec)
++v3d_lookup_bos(struct drm_device *dev,
++ struct drm_file *file_priv,
++ struct v3d_job *job,
++ u64 bo_handles,
++ u32 bo_count)
+ {
+ u32 *handles;
+ int ret = 0;
+ int i;
+
+- exec->bo_count = args->bo_handle_count;
++ job->bo_count = bo_count;
+
+- if (!exec->bo_count) {
++ if (!job->bo_count) {
+ /* See comment on bo_index for why we have to check
+ * this.
+ */
+@@ -326,15 +327,15 @@ v3d_cl_lookup_bos(struct drm_device *dev
+ return -EINVAL;
+ }
+
+- exec->bo = kvmalloc_array(exec->bo_count,
+- sizeof(struct drm_gem_cma_object *),
+- GFP_KERNEL | __GFP_ZERO);
+- if (!exec->bo) {
++ job->bo = kvmalloc_array(job->bo_count,
++ sizeof(struct drm_gem_cma_object *),
++ GFP_KERNEL | __GFP_ZERO);
++ if (!job->bo) {
+ DRM_DEBUG("Failed to allocate validated BO pointers\n");
+ return -ENOMEM;
+ }
+
+- handles = kvmalloc_array(exec->bo_count, sizeof(u32), GFP_KERNEL);
++ handles = kvmalloc_array(job->bo_count, sizeof(u32), GFP_KERNEL);
+ if (!handles) {
+ ret = -ENOMEM;
+ DRM_DEBUG("Failed to allocate incoming GEM handles\n");
+@@ -342,15 +343,15 @@ v3d_cl_lookup_bos(struct drm_device *dev
+ }
+
+ if (copy_from_user(handles,
+- (void __user *)(uintptr_t)args->bo_handles,
+- exec->bo_count * sizeof(u32))) {
++ (void __user *)(uintptr_t)bo_handles,
++ job->bo_count * sizeof(u32))) {
+ ret = -EFAULT;
+ DRM_DEBUG("Failed to copy in GEM handles\n");
+ goto fail;
+ }
+
+ spin_lock(&file_priv->table_lock);
+- for (i = 0; i < exec->bo_count; i++) {
++ for (i = 0; i < job->bo_count; i++) {
+ struct drm_gem_object *bo = idr_find(&file_priv->object_idr,
+ handles[i]);
+ if (!bo) {
+@@ -361,7 +362,7 @@ v3d_cl_lookup_bos(struct drm_device *dev
+ goto fail;
+ }
+ drm_gem_object_get(bo);
+- exec->bo[i] = to_v3d_bo(bo);
++ job->bo[i] = to_v3d_bo(bo);
+ }
+ spin_unlock(&file_priv->table_lock);
+
+@@ -371,59 +372,41 @@ fail:
+ }
+
+ static void
+-v3d_exec_cleanup(struct kref *ref)
++v3d_job_free(struct kref *ref)
+ {
+- struct v3d_exec_info *exec = container_of(ref, struct v3d_exec_info,
+- refcount);
+- unsigned int i;
+- struct v3d_bo *bo, *save;
+-
+- dma_fence_put(exec->bin.in_fence);
+- dma_fence_put(exec->render.in_fence);
+-
+- dma_fence_put(exec->bin.irq_fence);
+- dma_fence_put(exec->render.irq_fence);
+-
+- dma_fence_put(exec->bin_done_fence);
+- dma_fence_put(exec->render_done_fence);
+-
+- for (i = 0; i < exec->bo_count; i++)
+- drm_gem_object_put_unlocked(&exec->bo[i]->base);
+- kvfree(exec->bo);
++ struct v3d_job *job = container_of(ref, struct v3d_job, refcount);
++ int i;
+
+- list_for_each_entry_safe(bo, save, &exec->unref_list, unref_head) {
+- drm_gem_object_put_unlocked(&bo->base);
++ for (i = 0; i < job->bo_count; i++) {
++ if (job->bo[i])
++ drm_gem_object_put_unlocked(&job->bo[i]->base);
+ }
++ kvfree(job->bo);
+
+- kfree(exec);
+-}
++ dma_fence_put(job->in_fence);
++ dma_fence_put(job->irq_fence);
++ dma_fence_put(job->done_fence);
+
+-void v3d_exec_put(struct v3d_exec_info *exec)
+-{
+- kref_put(&exec->refcount, v3d_exec_cleanup);
++ kfree(job);
+ }
+
+ static void
+-v3d_tfu_job_cleanup(struct kref *ref)
++v3d_render_job_free(struct kref *ref)
+ {
+- struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,
+- refcount);
+- unsigned int i;
+-
+- dma_fence_put(job->in_fence);
+- dma_fence_put(job->irq_fence);
++ struct v3d_render_job *job = container_of(ref, struct v3d_render_job,
++ base.refcount);
++ struct v3d_bo *bo, *save;
+
+- for (i = 0; i < ARRAY_SIZE(job->bo); i++) {
+- if (job->bo[i])
+- drm_gem_object_put_unlocked(&job->bo[i]->base);
++ list_for_each_entry_safe(bo, save, &job->unref_list, unref_head) {
++ drm_gem_object_put_unlocked(&bo->base);
+ }
+
+- kfree(job);
++ v3d_job_free(ref);
+ }
+
+-void v3d_tfu_job_put(struct v3d_tfu_job *job)
++void v3d_job_put(struct v3d_job *job)
+ {
+- kref_put(&job->refcount, v3d_tfu_job_cleanup);
++ kref_put(&job->refcount, job->free);
+ }
+
+ int
+@@ -476,6 +459,65 @@ v3d_wait_bo_ioctl(struct drm_device *dev
+ return ret;
+ }
+
++static int
++v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,
++ struct v3d_job *job, void (*free)(struct kref *ref),
++ u32 in_sync)
++{
++ int ret;
++
++ job->v3d = v3d;
++ job->free = free;
++
++ ret = drm_syncobj_find_fence(file_priv, in_sync, 0, &job->in_fence);
++ if (ret == -EINVAL)
++ return ret;
++
++ kref_init(&job->refcount);
++
++ return 0;
++}
++
++static int
++v3d_push_job(struct v3d_file_priv *v3d_priv,
++ struct v3d_job *job, enum v3d_queue queue)
++{
++ int ret;
++
++ ret = drm_sched_job_init(&job->base, &v3d_priv->sched_entity[queue],
++ v3d_priv);
++ if (ret)
++ return ret;
++
++ job->done_fence = dma_fence_get(&job->base.s_fence->finished);
++
++ /* put by scheduler job completion */
++ kref_get(&job->refcount);
++
++ drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[queue]);
++
++ return 0;
++}
++
++static void
++v3d_attach_fences_and_unlock_reservation(struct drm_file *file_priv,
++ struct v3d_job *job,
++ struct ww_acquire_ctx *acquire_ctx,
++ u32 out_sync)
++{
++ struct drm_syncobj *sync_out;
++
++ v3d_attach_object_fences(job->bo, job->bo_count, job->done_fence);
++ v3d_unlock_bo_reservations(job->bo, job->bo_count, acquire_ctx);
++
++ /* Update the return sync object for the job */
++ sync_out = drm_syncobj_find(file_priv, out_sync);
++ if (sync_out) {
++ drm_syncobj_replace_fence(sync_out, job->done_fence);
++ drm_syncobj_put(sync_out);
++ }
++}
++
+ /**
+ * v3d_submit_cl_ioctl() - Submits a job (frame) to the V3D.
+ * @dev: DRM device
+@@ -495,9 +537,9 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ struct v3d_dev *v3d = to_v3d_dev(dev);
+ struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
+ struct drm_v3d_submit_cl *args = data;
+- struct v3d_exec_info *exec;
++ struct v3d_bin_job *bin = NULL;
++ struct v3d_render_job *render;
+ struct ww_acquire_ctx acquire_ctx;
+- struct drm_syncobj *sync_out;
+ int ret = 0;
+
+ trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
+@@ -507,95 +549,84 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ return -EINVAL;
+ }
+
+- exec = kcalloc(1, sizeof(*exec), GFP_KERNEL);
+- if (!exec)
++ render = kcalloc(1, sizeof(*render), GFP_KERNEL);
++ if (!render)
+ return -ENOMEM;
+
+- kref_init(&exec->refcount);
++ render->start = args->rcl_start;
++ render->end = args->rcl_end;
++ INIT_LIST_HEAD(&render->unref_list);
+
+- ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,
+- 0, &exec->bin.in_fence);
+- if (ret == -EINVAL)
+- goto fail;
++ ret = v3d_job_init(v3d, file_priv, &render->base,
++ v3d_render_job_free, args->in_sync_rcl);
++ if (ret) {
++ kfree(bin);
++ kfree(render);
++ return ret;
++ }
+
+- ret = drm_syncobj_find_fence(file_priv, args->in_sync_rcl,
+- 0, &exec->render.in_fence);
+- if (ret == -EINVAL)
+- goto fail;
++ if (args->bcl_start != args->bcl_end) {
++ bin = kcalloc(1, sizeof(*bin), GFP_KERNEL);
++ if (!bin)
++ return -ENOMEM;
++
++ ret = v3d_job_init(v3d, file_priv, &bin->base,
++ v3d_job_free, args->in_sync_bcl);
++ if (ret) {
++ v3d_job_put(&render->base);
++ return ret;
++ }
+
+- exec->qma = args->qma;
+- exec->qms = args->qms;
+- exec->qts = args->qts;
+- exec->bin.exec = exec;
+- exec->bin.start = args->bcl_start;
+- exec->bin.end = args->bcl_end;
+- exec->render.exec = exec;
+- exec->render.start = args->rcl_start;
+- exec->render.end = args->rcl_end;
+- exec->v3d = v3d;
+- INIT_LIST_HEAD(&exec->unref_list);
++ bin->start = args->bcl_start;
++ bin->end = args->bcl_end;
++ bin->qma = args->qma;
++ bin->qms = args->qms;
++ bin->qts = args->qts;
++ bin->render = render;
++ }
+
+- ret = v3d_cl_lookup_bos(dev, file_priv, args, exec);
++ ret = v3d_lookup_bos(dev, file_priv, &render->base,
++ args->bo_handles, args->bo_handle_count);
+ if (ret)
+ goto fail;
+
+- ret = v3d_lock_bo_reservations(exec->bo, exec->bo_count,
++ ret = v3d_lock_bo_reservations(render->base.bo, render->base.bo_count,
+ &acquire_ctx);
+ if (ret)
+ goto fail;
+
+ mutex_lock(&v3d->sched_lock);
+- if (exec->bin.start != exec->bin.end) {
+- ret = drm_sched_job_init(&exec->bin.base,
+- &v3d_priv->sched_entity[V3D_BIN],
+- v3d_priv);
++ if (bin) {
++ ret = v3d_push_job(v3d_priv, &bin->base, V3D_BIN);
+ if (ret)
+ goto fail_unreserve;
+
+- exec->bin_done_fence =
+- dma_fence_get(&exec->bin.base.s_fence->finished);
+-
+- kref_get(&exec->refcount); /* put by scheduler job completion */
+- drm_sched_entity_push_job(&exec->bin.base,
+- &v3d_priv->sched_entity[V3D_BIN]);
++ render->bin_done_fence = dma_fence_get(bin->base.done_fence);
+ }
+
+- ret = drm_sched_job_init(&exec->render.base,
+- &v3d_priv->sched_entity[V3D_RENDER],
+- v3d_priv);
++ ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);
+ if (ret)
+ goto fail_unreserve;
+-
+- exec->render_done_fence =
+- dma_fence_get(&exec->render.base.s_fence->finished);
+-
+- kref_get(&exec->refcount); /* put by scheduler job completion */
+- drm_sched_entity_push_job(&exec->render.base,
+- &v3d_priv->sched_entity[V3D_RENDER]);
+ mutex_unlock(&v3d->sched_lock);
+
+- v3d_attach_object_fences(exec->bo, exec->bo_count,
+- exec->render_done_fence);
+-
+- v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
+-
+- /* Update the return sync object for the */
+- sync_out = drm_syncobj_find(file_priv, args->out_sync);
+- if (sync_out) {
+- drm_syncobj_replace_fence(sync_out,
+- exec->render_done_fence);
+- drm_syncobj_put(sync_out);
+- }
+-
+- v3d_exec_put(exec);
++ v3d_attach_fences_and_unlock_reservation(file_priv,
++ &render->base, &acquire_ctx,
++ args->out_sync);
++
++ if (bin)
++ v3d_job_put(&bin->base);
++ v3d_job_put(&render->base);
+
+ return 0;
+
+ fail_unreserve:
+ mutex_unlock(&v3d->sched_lock);
+- v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
++ v3d_unlock_bo_reservations(render->base.bo,
++ render->base.bo_count, &acquire_ctx);
+ fail:
+- v3d_exec_put(exec);
++ if (bin)
++ v3d_job_put(&bin->base);
++ v3d_job_put(&render->base);
+
+ return ret;
+ }
+@@ -618,10 +649,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
+ struct drm_v3d_submit_tfu *args = data;
+ struct v3d_tfu_job *job;
+ struct ww_acquire_ctx acquire_ctx;
+- struct drm_syncobj *sync_out;
+- struct dma_fence *sched_done_fence;
+ int ret = 0;
+- int bo_count;
+
+ trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia);
+
+@@ -629,75 +657,66 @@ v3d_submit_tfu_ioctl(struct drm_device *
+ if (!job)
+ return -ENOMEM;
+
+- kref_init(&job->refcount);
+-
+- ret = drm_syncobj_find_fence(file_priv, args->in_sync,
+- 0, &job->in_fence);
+- if (ret == -EINVAL)
+- goto fail;
++ ret = v3d_job_init(v3d, file_priv, &job->base,
++ v3d_job_free, args->in_sync);
++ if (ret) {
++ kfree(job);
++ return ret;
++ }
+
++ job->base.bo = kcalloc(ARRAY_SIZE(args->bo_handles),
++ sizeof(*job->base.bo), GFP_KERNEL);
+ job->args = *args;
+- job->v3d = v3d;
+
+ spin_lock(&file_priv->table_lock);
+- for (bo_count = 0; bo_count < ARRAY_SIZE(job->bo); bo_count++) {
++ for (job->base.bo_count = 0;
++ job->base.bo_count < ARRAY_SIZE(args->bo_handles);
++ job->base.bo_count++) {
+ struct drm_gem_object *bo;
+
+- if (!args->bo_handles[bo_count])
++ if (!args->bo_handles[job->base.bo_count])
+ break;
+
+ bo = idr_find(&file_priv->object_idr,
+- args->bo_handles[bo_count]);
++ args->bo_handles[job->base.bo_count]);
+ if (!bo) {
+ DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
+- bo_count, args->bo_handles[bo_count]);
++ job->base.bo_count,
++ args->bo_handles[job->base.bo_count]);
+ ret = -ENOENT;
+ spin_unlock(&file_priv->table_lock);
+ goto fail;
+ }
+ drm_gem_object_get(bo);
+- job->bo[bo_count] = to_v3d_bo(bo);
++ job->base.bo[job->base.bo_count] = to_v3d_bo(bo);
+ }
+ spin_unlock(&file_priv->table_lock);
+
+- ret = v3d_lock_bo_reservations(job->bo, bo_count, &acquire_ctx);
++ ret = v3d_lock_bo_reservations(job->base.bo, job->base.bo_count,
++ &acquire_ctx);
+ if (ret)
+ goto fail;
+
+ mutex_lock(&v3d->sched_lock);
+- ret = drm_sched_job_init(&job->base,
+- &v3d_priv->sched_entity[V3D_TFU],
+- v3d_priv);
++ ret = v3d_push_job(v3d_priv, &job->base, V3D_TFU);
+ if (ret)
+ goto fail_unreserve;
+-
+- sched_done_fence = dma_fence_get(&job->base.s_fence->finished);
+-
+- kref_get(&job->refcount); /* put by scheduler job completion */
+- drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[V3D_TFU]);
+ mutex_unlock(&v3d->sched_lock);
+
+- v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);
+-
+- v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
+-
+- /* Update the return sync object */
+- sync_out = drm_syncobj_find(file_priv, args->out_sync);
+- if (sync_out) {
+- drm_syncobj_replace_fence(sync_out, sched_done_fence);
+- drm_syncobj_put(sync_out);
+- }
+- dma_fence_put(sched_done_fence);
++ v3d_attach_fences_and_unlock_reservation(file_priv,
++ &job->base, &acquire_ctx,
++ args->out_sync);
+
+- v3d_tfu_job_put(job);
++ v3d_job_put(&job->base);
+
+ return 0;
+
+ fail_unreserve:
+ mutex_unlock(&v3d->sched_lock);
+- v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
++ v3d_unlock_bo_reservations(job->base.bo, job->base.bo_count,
++ &acquire_ctx);
+ fail:
+- v3d_tfu_job_put(job);
++ v3d_job_put(&job->base);
+
+ return ret;
+ }
+@@ -755,7 +774,7 @@ v3d_gem_destroy(struct drm_device *dev)
+
+ v3d_sched_fini(v3d);
+
+- /* Waiting for exec to finish would need to be done before
++ /* Waiting for jobs to finish would need to be done before
+ * unregistering V3D.
+ */
+ WARN_ON(v3d->bin_job);
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -60,7 +60,7 @@ v3d_overflow_mem_work(struct work_struct
+ }
+
+ drm_gem_object_get(&bo->base);
+- list_add_tail(&bo->unref_head, &v3d->bin_job->unref_list);
++ list_add_tail(&bo->unref_head, &v3d->bin_job->render->unref_list);
+ spin_unlock_irqrestore(&v3d->job_lock, irqflags);
+
+ V3D_CORE_WRITE(0, V3D_PTB_BPOA, bo->node.start << PAGE_SHIFT);
+@@ -93,7 +93,7 @@ v3d_irq(int irq, void *arg)
+
+ if (intsts & V3D_INT_FLDONE) {
+ struct v3d_fence *fence =
+- to_v3d_fence(v3d->bin_job->bin.irq_fence);
++ to_v3d_fence(v3d->bin_job->base.irq_fence);
+
+ trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
+ dma_fence_signal(&fence->base);
+@@ -102,7 +102,7 @@ v3d_irq(int irq, void *arg)
+
+ if (intsts & V3D_INT_FRDONE) {
+ struct v3d_fence *fence =
+- to_v3d_fence(v3d->render_job->render.irq_fence);
++ to_v3d_fence(v3d->render_job->base.irq_fence);
+
+ trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
+ dma_fence_signal(&fence->base);
+@@ -138,7 +138,7 @@ v3d_hub_irq(int irq, void *arg)
+
+ if (intsts & V3D_HUB_INT_TFUC) {
+ struct v3d_fence *fence =
+- to_v3d_fence(v3d->tfu_job->irq_fence);
++ to_v3d_fence(v3d->tfu_job->base.irq_fence);
+
+ trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
+ dma_fence_signal(&fence->base);
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -30,39 +30,43 @@ to_v3d_job(struct drm_sched_job *sched_j
+ return container_of(sched_job, struct v3d_job, base);
+ }
+
+-static struct v3d_tfu_job *
+-to_tfu_job(struct drm_sched_job *sched_job)
++static struct v3d_bin_job *
++to_bin_job(struct drm_sched_job *sched_job)
+ {
+- return container_of(sched_job, struct v3d_tfu_job, base);
++ return container_of(sched_job, struct v3d_bin_job, base.base);
+ }
+
+-static void
+-v3d_job_free(struct drm_sched_job *sched_job)
++static struct v3d_render_job *
++to_render_job(struct drm_sched_job *sched_job)
+ {
+- struct v3d_job *job = to_v3d_job(sched_job);
++ return container_of(sched_job, struct v3d_render_job, base.base);
++}
+
+- v3d_exec_put(job->exec);
++static struct v3d_tfu_job *
++to_tfu_job(struct drm_sched_job *sched_job)
++{
++ return container_of(sched_job, struct v3d_tfu_job, base.base);
+ }
+
+ static void
+-v3d_tfu_job_free(struct drm_sched_job *sched_job)
++v3d_job_free(struct drm_sched_job *sched_job)
+ {
+- struct v3d_tfu_job *job = to_tfu_job(sched_job);
++ struct v3d_job *job = to_v3d_job(sched_job);
+
+- v3d_tfu_job_put(job);
++ v3d_job_put(job);
+ }
+
+ /**
+- * Returns the fences that the bin or render job depends on, one by one.
+- * v3d_job_run() won't be called until all of them have been signaled.
++ * Returns the fences that the job depends on, one by one.
++ *
++ * If placed in the scheduler's .dependency method, the corresponding
++ * .run_job won't be called until all of them have been signaled.
+ */
+ static struct dma_fence *
+ v3d_job_dependency(struct drm_sched_job *sched_job,
+ struct drm_sched_entity *s_entity)
+ {
+ struct v3d_job *job = to_v3d_job(sched_job);
+- struct v3d_exec_info *exec = job->exec;
+- enum v3d_queue q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
+ struct dma_fence *fence;
+
+ fence = job->in_fence;
+@@ -71,113 +75,132 @@ v3d_job_dependency(struct drm_sched_job
+ return fence;
+ }
+
+- if (q == V3D_RENDER) {
+- /* If we had a bin job, the render job definitely depends on
+- * it. We first have to wait for bin to be scheduled, so that
+- * its done_fence is created.
+- */
+- fence = exec->bin_done_fence;
+- if (fence) {
+- exec->bin_done_fence = NULL;
+- return fence;
+- }
+- }
+-
+- /* XXX: Wait on a fence for switching the GMP if necessary,
+- * and then do so.
+- */
+-
+- return fence;
++ return NULL;
+ }
+
+ /**
+- * Returns the fences that the TFU job depends on, one by one.
+- * v3d_tfu_job_run() won't be called until all of them have been
+- * signaled.
++ * Returns the fences that the render job depends on, one by one.
++ * v3d_job_run() won't be called until all of them have been signaled.
+ */
+ static struct dma_fence *
+-v3d_tfu_job_dependency(struct drm_sched_job *sched_job,
+- struct drm_sched_entity *s_entity)
++v3d_render_job_dependency(struct drm_sched_job *sched_job,
++ struct drm_sched_entity *s_entity)
+ {
+- struct v3d_tfu_job *job = to_tfu_job(sched_job);
++ struct v3d_render_job *job = to_render_job(sched_job);
+ struct dma_fence *fence;
+
+- fence = job->in_fence;
++ fence = v3d_job_dependency(sched_job, s_entity);
++ if (fence)
++ return fence;
++
++ /* If we had a bin job, the render job definitely depends on
++ * it. We first have to wait for bin to be scheduled, so that
++ * its done_fence is created.
++ */
++ fence = job->bin_done_fence;
+ if (fence) {
+- job->in_fence = NULL;
++ job->bin_done_fence = NULL;
+ return fence;
+ }
+
+- return NULL;
++ /* XXX: Wait on a fence for switching the GMP if necessary,
++ * and then do so.
++ */
++
++ return fence;
+ }
+
+-static struct dma_fence *v3d_job_run(struct drm_sched_job *sched_job)
++static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
+ {
+- struct v3d_job *job = to_v3d_job(sched_job);
+- struct v3d_exec_info *exec = job->exec;
+- enum v3d_queue q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
+- struct v3d_dev *v3d = exec->v3d;
++ struct v3d_bin_job *job = to_bin_job(sched_job);
++ struct v3d_dev *v3d = job->base.v3d;
+ struct drm_device *dev = &v3d->drm;
+ struct dma_fence *fence;
+ unsigned long irqflags;
+
+- if (unlikely(job->base.s_fence->finished.error))
++ if (unlikely(job->base.base.s_fence->finished.error))
+ return NULL;
+
+ /* Lock required around bin_job update vs
+ * v3d_overflow_mem_work().
+ */
+ spin_lock_irqsave(&v3d->job_lock, irqflags);
+- if (q == V3D_BIN) {
+- v3d->bin_job = job->exec;
++ v3d->bin_job = job;
++ /* Clear out the overflow allocation, so we don't
++ * reuse the overflow attached to a previous job.
++ */
++ V3D_CORE_WRITE(0, V3D_PTB_BPOS, 0);
++ spin_unlock_irqrestore(&v3d->job_lock, irqflags);
++
++ v3d_invalidate_caches(v3d);
+
+- /* Clear out the overflow allocation, so we don't
+- * reuse the overflow attached to a previous job.
+- */
+- V3D_CORE_WRITE(0, V3D_PTB_BPOS, 0);
+- } else {
+- v3d->render_job = job->exec;
++ fence = v3d_fence_create(v3d, V3D_BIN);
++ if (IS_ERR(fence))
++ return NULL;
++
++ if (job->base.irq_fence)
++ dma_fence_put(job->base.irq_fence);
++ job->base.irq_fence = dma_fence_get(fence);
++
++ trace_v3d_submit_cl(dev, false, to_v3d_fence(fence)->seqno,
++ job->start, job->end);
++
++ /* Set the current and end address of the control list.
++ * Writing the end register is what starts the job.
++ */
++ if (job->qma) {
++ V3D_CORE_WRITE(0, V3D_CLE_CT0QMA, job->qma);
++ V3D_CORE_WRITE(0, V3D_CLE_CT0QMS, job->qms);
+ }
+- spin_unlock_irqrestore(&v3d->job_lock, irqflags);
++ if (job->qts) {
++ V3D_CORE_WRITE(0, V3D_CLE_CT0QTS,
++ V3D_CLE_CT0QTS_ENABLE |
++ job->qts);
++ }
++ V3D_CORE_WRITE(0, V3D_CLE_CT0QBA, job->start);
++ V3D_CORE_WRITE(0, V3D_CLE_CT0QEA, job->end);
++
++ return fence;
++}
++
++static struct dma_fence *v3d_render_job_run(struct drm_sched_job *sched_job)
++{
++ struct v3d_render_job *job = to_render_job(sched_job);
++ struct v3d_dev *v3d = job->base.v3d;
++ struct drm_device *dev = &v3d->drm;
++ struct dma_fence *fence;
++
++ if (unlikely(job->base.base.s_fence->finished.error))
++ return NULL;
+
+- /* Can we avoid this flush when q==RENDER? We need to be
+- * careful of scheduling, though -- imagine job0 rendering to
+- * texture and job1 reading, and them being executed as bin0,
+- * bin1, render0, render1, so that render1's flush at bin time
++ v3d->render_job = job;
++
++ /* Can we avoid this flush? We need to be careful of
++ * scheduling, though -- imagine job0 rendering to texture and
++ * job1 reading, and them being executed as bin0, bin1,
++ * render0, render1, so that render1's flush at bin time
+ * wasn't enough.
+ */
+ v3d_invalidate_caches(v3d);
+
+- fence = v3d_fence_create(v3d, q);
++ fence = v3d_fence_create(v3d, V3D_RENDER);
+ if (IS_ERR(fence))
+ return NULL;
+
+- if (job->irq_fence)
+- dma_fence_put(job->irq_fence);
+- job->irq_fence = dma_fence_get(fence);
++ if (job->base.irq_fence)
++ dma_fence_put(job->base.irq_fence);
++ job->base.irq_fence = dma_fence_get(fence);
+
+- trace_v3d_submit_cl(dev, q == V3D_RENDER, to_v3d_fence(fence)->seqno,
++ trace_v3d_submit_cl(dev, true, to_v3d_fence(fence)->seqno,
+ job->start, job->end);
+
+- if (q == V3D_BIN) {
+- if (exec->qma) {
+- V3D_CORE_WRITE(0, V3D_CLE_CT0QMA, exec->qma);
+- V3D_CORE_WRITE(0, V3D_CLE_CT0QMS, exec->qms);
+- }
+- if (exec->qts) {
+- V3D_CORE_WRITE(0, V3D_CLE_CT0QTS,
+- V3D_CLE_CT0QTS_ENABLE |
+- exec->qts);
+- }
+- } else {
+- /* XXX: Set the QCFG */
+- }
++ /* XXX: Set the QCFG */
+
+ /* Set the current and end address of the control list.
+ * Writing the end register is what starts the job.
+ */
+- V3D_CORE_WRITE(0, V3D_CLE_CTNQBA(q), job->start);
+- V3D_CORE_WRITE(0, V3D_CLE_CTNQEA(q), job->end);
++ V3D_CORE_WRITE(0, V3D_CLE_CT1QBA, job->start);
++ V3D_CORE_WRITE(0, V3D_CLE_CT1QEA, job->end);
+
+ return fence;
+ }
+@@ -186,7 +209,7 @@ static struct dma_fence *
+ v3d_tfu_job_run(struct drm_sched_job *sched_job)
+ {
+ struct v3d_tfu_job *job = to_tfu_job(sched_job);
+- struct v3d_dev *v3d = job->v3d;
++ struct v3d_dev *v3d = job->base.v3d;
+ struct drm_device *dev = &v3d->drm;
+ struct dma_fence *fence;
+
+@@ -195,9 +218,9 @@ v3d_tfu_job_run(struct drm_sched_job *sc
+ return NULL;
+
+ v3d->tfu_job = job;
+- if (job->irq_fence)
+- dma_fence_put(job->irq_fence);
+- job->irq_fence = dma_fence_get(fence);
++ if (job->base.irq_fence)
++ dma_fence_put(job->base.irq_fence);
++ job->base.irq_fence = dma_fence_get(fence);
+
+ trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
+
+@@ -247,25 +270,23 @@ v3d_gpu_reset_for_timeout(struct v3d_dev
+ mutex_unlock(&v3d->reset_lock);
+ }
+
++/* If the current address or return address have changed, then the GPU
++ * has probably made progress and we should delay the reset. This
++ * could fail if the GPU got in an infinite loop in the CL, but that
++ * is pretty unlikely outside of an i-g-t testcase.
++ */
+ static void
+-v3d_job_timedout(struct drm_sched_job *sched_job)
++v3d_cl_job_timedout(struct drm_sched_job *sched_job, enum v3d_queue q,
++ u32 *timedout_ctca, u32 *timedout_ctra)
+ {
+ struct v3d_job *job = to_v3d_job(sched_job);
+- struct v3d_exec_info *exec = job->exec;
+- struct v3d_dev *v3d = exec->v3d;
+- enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
+- u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));
+- u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));
+-
+- /* If the current address or return address have changed, then
+- * the GPU has probably made progress and we should delay the
+- * reset. This could fail if the GPU got in an infinite loop
+- * in the CL, but that is pretty unlikely outside of an i-g-t
+- * testcase.
+- */
+- if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) {
+- job->timedout_ctca = ctca;
+- job->timedout_ctra = ctra;
++ struct v3d_dev *v3d = job->v3d;
++ u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(q));
++ u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(q));
++
++ if (*timedout_ctca != ctca || *timedout_ctra != ctra) {
++ *timedout_ctca = ctca;
++ *timedout_ctra = ctra;
+ schedule_delayed_work(&job->base.work_tdr,
+ job->base.sched->timeout);
+ return;
+@@ -275,25 +296,50 @@ v3d_job_timedout(struct drm_sched_job *s
+ }
+
+ static void
++v3d_bin_job_timedout(struct drm_sched_job *sched_job)
++{
++ struct v3d_bin_job *job = to_bin_job(sched_job);
++
++ v3d_cl_job_timedout(sched_job, V3D_BIN,
++ &job->timedout_ctca, &job->timedout_ctra);
++}
++
++static void
++v3d_render_job_timedout(struct drm_sched_job *sched_job)
++{
++ struct v3d_render_job *job = to_render_job(sched_job);
++
++ v3d_cl_job_timedout(sched_job, V3D_RENDER,
++ &job->timedout_ctca, &job->timedout_ctra);
++}
++
++static void
+ v3d_tfu_job_timedout(struct drm_sched_job *sched_job)
+ {
+- struct v3d_tfu_job *job = to_tfu_job(sched_job);
++ struct v3d_job *job = to_v3d_job(sched_job);
+
+ v3d_gpu_reset_for_timeout(job->v3d, sched_job);
+ }
+
+-static const struct drm_sched_backend_ops v3d_sched_ops = {
++static const struct drm_sched_backend_ops v3d_bin_sched_ops = {
+ .dependency = v3d_job_dependency,
+- .run_job = v3d_job_run,
+- .timedout_job = v3d_job_timedout,
+- .free_job = v3d_job_free
++ .run_job = v3d_bin_job_run,
++ .timedout_job = v3d_bin_job_timedout,
++ .free_job = v3d_job_free,
++};
++
++static const struct drm_sched_backend_ops v3d_render_sched_ops = {
++ .dependency = v3d_render_job_dependency,
++ .run_job = v3d_render_job_run,
++ .timedout_job = v3d_render_job_timedout,
++ .free_job = v3d_job_free,
+ };
+
+ static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
+- .dependency = v3d_tfu_job_dependency,
++ .dependency = v3d_job_dependency,
+ .run_job = v3d_tfu_job_run,
+ .timedout_job = v3d_tfu_job_timedout,
+- .free_job = v3d_tfu_job_free
++ .free_job = v3d_job_free,
+ };
+
+ int
+@@ -305,7 +351,7 @@ v3d_sched_init(struct v3d_dev *v3d)
+ int ret;
+
+ ret = drm_sched_init(&v3d->queue[V3D_BIN].sched,
+- &v3d_sched_ops,
++ &v3d_bin_sched_ops,
+ hw_jobs_limit, job_hang_limit,
+ msecs_to_jiffies(hang_limit_ms),
+ "v3d_bin");
+@@ -315,7 +361,7 @@ v3d_sched_init(struct v3d_dev *v3d)
+ }
+
+ ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched,
+- &v3d_sched_ops,
++ &v3d_render_sched_ops,
+ hw_jobs_limit, job_hang_limit,
+ msecs_to_jiffies(hang_limit_ms),
+ "v3d_render");
--- /dev/null
+From 55757fd208de69d0701ac9d6e368d9647549d74f Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 27 Mar 2019 17:44:40 -0700
+Subject: [PATCH 589/725] drm/v3d: Add missing implicit synchronization.
+
+It is the expectation of existing userspace (X11 + Mesa, in
+particular) that jobs submitted to the kernel against a shared BO will
+get implicitly synchronized by their submission order. If we want to
+allow clever userspace to disable implicit synchronization, we should
+do that under its own submit flag (as amdgpu and lima do).
+
+Note that we currently only implicitly sync for the rendering pass,
+not binning -- if you texture-from-pixmap in the binning vertex shader
+(vertex coordinate generation), you'll miss out on synchronization.
+
+Fixes flickering when multiple clients are running in parallel,
+particularly GL apps and compositors.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_drv.h | 10 +---
+ drivers/gpu/drm/v3d/v3d_gem.c | 98 ++++++++++++++++++++++++++++++---
+ drivers/gpu/drm/v3d/v3d_sched.c | 45 ++-------------
+ 3 files changed, 96 insertions(+), 57 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -186,8 +186,9 @@ struct v3d_job {
+ struct v3d_bo **bo;
+ u32 bo_count;
+
+- /* An optional fence userspace can pass in for the job to depend on. */
+- struct dma_fence *in_fence;
++ struct dma_fence **deps;
++ int deps_count;
++ int deps_size;
+
+ /* v3d fence to be signaled by IRQ handler when the job is complete. */
+ struct dma_fence *irq_fence;
+@@ -219,11 +220,6 @@ struct v3d_bin_job {
+ struct v3d_render_job {
+ struct v3d_job base;
+
+- /* Optional fence for the binner, to depend on before starting
+- * our job.
+- */
+- struct dma_fence *bin_done_fence;
+-
+ /* GPU virtual addresses of the start/end of the CL job. */
+ u32 start, end;
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -218,6 +218,71 @@ v3d_unlock_bo_reservations(struct v3d_bo
+ ww_acquire_fini(acquire_ctx);
+ }
+
++static int
++v3d_add_dep(struct v3d_job *job, struct dma_fence *fence)
++{
++ if (!fence)
++ return 0;
++
++ if (job->deps_size == job->deps_count) {
++ int new_deps_size = max(job->deps_size * 2, 4);
++ struct dma_fence **new_deps =
++ krealloc(job->deps, new_deps_size * sizeof(*new_deps),
++ GFP_KERNEL);
++ if (!new_deps) {
++ dma_fence_put(fence);
++ return -ENOMEM;
++ }
++
++ job->deps = new_deps;
++ job->deps_size = new_deps_size;
++ }
++
++ job->deps[job->deps_count++] = fence;
++
++ return 0;
++}
++
++/**
++ * Adds the required implicit fences before executing the job
++ *
++ * Userspace (X11 + Mesa) requires that a job submitted against a shared BO
++ * from one fd will implicitly synchronize against previous jobs submitted
++ * against that BO from other fds.
++ *
++ * Currently we don't bother trying to track the shared BOs, and instead just
++ * sync everything. However, our synchronization is only for the render pass
++ * -- the binning stage (VS coordinate calculations) ignores implicit sync,
++ * since using shared buffers for texture coordinates seems unlikely, and
++ * implicitly syncing them would break bin/render parallelism. If we want to
++ * fix that, we should introduce a flag when VS texturing has been used in the
++ * binning stage, or a set of flags for which BOs are sampled during binning.
++ */
++static int
++v3d_add_implicit_fences(struct v3d_job *job, struct v3d_bo *bo)
++{
++ int i, ret, nr_fences;
++ struct dma_fence **fences;
++
++ ret = reservation_object_get_fences_rcu(bo->resv, NULL,
++ &nr_fences, &fences);
++ if (ret || !nr_fences)
++ return ret;
++
++ for (i = 0; i < nr_fences; i++) {
++ ret = v3d_add_dep(job, fences[i]);
++ if (ret)
++ break;
++ }
++
++ /* Free any remaining fences after error. */
++ for (; i < nr_fences; i++)
++ dma_fence_put(fences[i]);
++ kfree(fences);
++
++ return ret;
++}
++
+ /* Takes the reservation lock on all the BOs being referenced, so that
+ * at queue submit time we can update the reservations.
+ *
+@@ -226,10 +291,11 @@ v3d_unlock_bo_reservations(struct v3d_bo
+ * to v3d, so we don't attach dma-buf fences to them.
+ */
+ static int
+-v3d_lock_bo_reservations(struct v3d_bo **bos,
+- int bo_count,
++v3d_lock_bo_reservations(struct v3d_job *job,
+ struct ww_acquire_ctx *acquire_ctx)
+ {
++ struct v3d_bo **bos = job->bo;
++ int bo_count = job->bo_count;
+ int contended_lock = -1;
+ int i, ret;
+
+@@ -281,6 +347,13 @@ retry:
+ * before we commit the CL to the hardware.
+ */
+ for (i = 0; i < bo_count; i++) {
++ ret = v3d_add_implicit_fences(job, bos[i]);
++ if (ret) {
++ v3d_unlock_bo_reservations(bos, bo_count,
++ acquire_ctx);
++ return ret;
++ }
++
+ ret = reservation_object_reserve_shared(bos[i]->resv);
+ if (ret) {
+ v3d_unlock_bo_reservations(bos, bo_count,
+@@ -383,7 +456,10 @@ v3d_job_free(struct kref *ref)
+ }
+ kvfree(job->bo);
+
+- dma_fence_put(job->in_fence);
++ for (i = 0; i < job->deps_count; i++)
++ dma_fence_put(job->deps[i]);
++ kfree(job->deps);
++
+ dma_fence_put(job->irq_fence);
+ dma_fence_put(job->done_fence);
+
+@@ -464,15 +540,20 @@ v3d_job_init(struct v3d_dev *v3d, struct
+ struct v3d_job *job, void (*free)(struct kref *ref),
+ u32 in_sync)
+ {
++ struct dma_fence *in_fence = NULL;
+ int ret;
+
+ job->v3d = v3d;
+ job->free = free;
+
+- ret = drm_syncobj_find_fence(file_priv, in_sync, 0, &job->in_fence);
++ ret = drm_syncobj_find_fence(file_priv, in_sync, 0, &in_fence);
+ if (ret == -EINVAL)
+ return ret;
+
++ ret = v3d_add_dep(job, in_fence);
++ if (ret)
++ return ret;
++
+ kref_init(&job->refcount);
+
+ return 0;
+@@ -590,8 +671,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ if (ret)
+ goto fail;
+
+- ret = v3d_lock_bo_reservations(render->base.bo, render->base.bo_count,
+- &acquire_ctx);
++ ret = v3d_lock_bo_reservations(&render->base, &acquire_ctx);
+ if (ret)
+ goto fail;
+
+@@ -601,7 +681,8 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ if (ret)
+ goto fail_unreserve;
+
+- render->bin_done_fence = dma_fence_get(bin->base.done_fence);
++ ret = v3d_add_dep(&render->base,
++ dma_fence_get(bin->base.done_fence));
+ }
+
+ ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);
+@@ -692,8 +773,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
+ }
+ spin_unlock(&file_priv->table_lock);
+
+- ret = v3d_lock_bo_reservations(job->base.bo, job->base.bo_count,
+- &acquire_ctx);
++ ret = v3d_lock_bo_reservations(&job->base, &acquire_ctx);
+ if (ret)
+ goto fail;
+
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -67,47 +67,10 @@ v3d_job_dependency(struct drm_sched_job
+ struct drm_sched_entity *s_entity)
+ {
+ struct v3d_job *job = to_v3d_job(sched_job);
+- struct dma_fence *fence;
+-
+- fence = job->in_fence;
+- if (fence) {
+- job->in_fence = NULL;
+- return fence;
+- }
+-
+- return NULL;
+-}
+
+-/**
+- * Returns the fences that the render job depends on, one by one.
+- * v3d_job_run() won't be called until all of them have been signaled.
+- */
+-static struct dma_fence *
+-v3d_render_job_dependency(struct drm_sched_job *sched_job,
+- struct drm_sched_entity *s_entity)
+-{
+- struct v3d_render_job *job = to_render_job(sched_job);
+- struct dma_fence *fence;
+-
+- fence = v3d_job_dependency(sched_job, s_entity);
+- if (fence)
+- return fence;
+-
+- /* If we had a bin job, the render job definitely depends on
+- * it. We first have to wait for bin to be scheduled, so that
+- * its done_fence is created.
+- */
+- fence = job->bin_done_fence;
+- if (fence) {
+- job->bin_done_fence = NULL;
+- return fence;
+- }
+-
+- /* XXX: Wait on a fence for switching the GMP if necessary,
+- * and then do so.
+- */
+-
+- return fence;
++ if (!job->deps_count)
++ return NULL;
++ return job->deps[--job->deps_count];
+ }
+
+ static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
+@@ -329,7 +292,7 @@ static const struct drm_sched_backend_op
+ };
+
+ static const struct drm_sched_backend_ops v3d_render_sched_ops = {
+- .dependency = v3d_render_job_dependency,
++ .dependency = v3d_job_dependency,
+ .run_job = v3d_render_job_run,
+ .timedout_job = v3d_render_job_timedout,
+ .free_job = v3d_job_free,
+++ /dev/null
-From f5ba2c027e3f21bafcbff13ec513d6a10c8dc585 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 14 Jan 2019 15:13:17 -0800
-Subject: [PATCH 589/703] drm/v3d: HACK: gut runtime pm for now.
-
-Something is still unstable -- on starting a new glxgears from an idle
-X11, I get an MMU violation in high addresses. The CTS also failed
-quite quickly. With this, CTS progresses for an hour before OOMing
-(allocating some big buffers when my board only has 600MB available to
-Linux)
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_debugfs.c | 16 +---------------
- drivers/gpu/drm/v3d/v3d_drv.c | 7 -------
- drivers/gpu/drm/v3d/v3d_gem.c | 20 --------------------
- 3 files changed, 1 insertion(+), 42 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_debugfs.c
-+++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
-@@ -4,7 +4,6 @@
- #include <linux/circ_buf.h>
- #include <linux/ctype.h>
- #include <linux/debugfs.h>
--#include <linux/pm_runtime.h>
- #include <linux/seq_file.h>
- #include <drm/drmP.h>
-
-@@ -100,11 +99,8 @@ static int v3d_v3d_debugfs_ident(struct
- struct drm_device *dev = node->minor->dev;
- struct v3d_dev *v3d = to_v3d_dev(dev);
- u32 ident0, ident1, ident2, ident3, cores;
-- int ret, core;
-+ int core;
-
-- ret = pm_runtime_get_sync(v3d->dev);
-- if (ret < 0)
-- return ret;
-
- ident0 = V3D_READ(V3D_HUB_IDENT0);
- ident1 = V3D_READ(V3D_HUB_IDENT1);
-@@ -157,9 +153,6 @@ static int v3d_v3d_debugfs_ident(struct
- (misccfg & V3D_MISCCFG_OVRTMUOUT) != 0);
- }
-
-- pm_runtime_mark_last_busy(v3d->dev);
-- pm_runtime_put_autosuspend(v3d->dev);
--
- return 0;
- }
-
-@@ -187,11 +180,6 @@ static int v3d_measure_clock(struct seq_
- uint32_t cycles;
- int core = 0;
- int measure_ms = 1000;
-- int ret;
--
-- ret = pm_runtime_get_sync(v3d->dev);
-- if (ret < 0)
-- return ret;
-
- if (v3d->ver >= 40) {
- V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3,
-@@ -215,8 +203,6 @@ static int v3d_measure_clock(struct seq_
- cycles / (measure_ms * 1000),
- (cycles / (measure_ms * 100)) % 10);
-
-- pm_runtime_mark_last_busy(v3d->dev);
-- pm_runtime_put_autosuspend(v3d->dev);
-
- return 0;
- }
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -75,7 +75,6 @@ static int v3d_get_param_ioctl(struct dr
- {
- struct v3d_dev *v3d = to_v3d_dev(dev);
- struct drm_v3d_get_param *args = data;
-- int ret;
- static const u32 reg_map[] = {
- [DRM_V3D_PARAM_V3D_UIFCFG] = V3D_HUB_UIFCFG,
- [DRM_V3D_PARAM_V3D_HUB_IDENT1] = V3D_HUB_IDENT1,
-@@ -101,15 +100,12 @@ static int v3d_get_param_ioctl(struct dr
- if (args->value != 0)
- return -EINVAL;
-
-- ret = pm_runtime_get_sync(v3d->dev);
- if (args->param >= DRM_V3D_PARAM_V3D_CORE0_IDENT0 &&
- args->param <= DRM_V3D_PARAM_V3D_CORE0_IDENT2) {
- args->value = V3D_CORE_READ(0, offset);
- } else {
- args->value = V3D_READ(offset);
- }
-- pm_runtime_mark_last_busy(v3d->dev);
-- pm_runtime_put_autosuspend(v3d->dev);
- return 0;
- }
-
-@@ -311,9 +307,6 @@ static int v3d_platform_drm_probe(struct
- goto dev_free;
- }
-
-- pm_runtime_use_autosuspend(dev);
-- pm_runtime_set_autosuspend_delay(dev, 50);
-- pm_runtime_enable(dev);
-
- ret = drm_dev_init(&v3d->drm, &v3d_drm_driver, dev);
- if (ret)
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -375,7 +375,6 @@ v3d_exec_cleanup(struct kref *ref)
- {
- struct v3d_exec_info *exec = container_of(ref, struct v3d_exec_info,
- refcount);
-- struct v3d_dev *v3d = exec->v3d;
- unsigned int i;
- struct v3d_bo *bo, *save;
-
-@@ -396,9 +395,6 @@ v3d_exec_cleanup(struct kref *ref)
- drm_gem_object_put_unlocked(&bo->base);
- }
-
-- pm_runtime_mark_last_busy(v3d->dev);
-- pm_runtime_put_autosuspend(v3d->dev);
--
- kfree(exec);
- }
-
-@@ -412,7 +408,6 @@ v3d_tfu_job_cleanup(struct kref *ref)
- {
- struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,
- refcount);
-- struct v3d_dev *v3d = job->v3d;
- unsigned int i;
-
- dma_fence_put(job->in_fence);
-@@ -423,9 +418,6 @@ v3d_tfu_job_cleanup(struct kref *ref)
- drm_gem_object_put_unlocked(&job->bo[i]->base);
- }
-
-- pm_runtime_mark_last_busy(v3d->dev);
-- pm_runtime_put_autosuspend(v3d->dev);
--
- kfree(job);
- }
-
-@@ -519,12 +511,6 @@ v3d_submit_cl_ioctl(struct drm_device *d
- if (!exec)
- return -ENOMEM;
-
-- ret = pm_runtime_get_sync(v3d->dev);
-- if (ret < 0) {
-- kfree(exec);
-- return ret;
-- }
--
- kref_init(&exec->refcount);
-
- ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,
-@@ -643,12 +629,6 @@ v3d_submit_tfu_ioctl(struct drm_device *
- if (!job)
- return -ENOMEM;
-
-- ret = pm_runtime_get_sync(v3d->dev);
-- if (ret < 0) {
-- kfree(job);
-- return ret;
-- }
--
- kref_init(&job->refcount);
-
- ret = drm_syncobj_find_fence(file_priv, args->in_sync,
+++ /dev/null
-From 97f75af520bb5c124641b0704ebbd171f80d0bfb Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Tue, 12 Mar 2019 09:08:10 -0700
-Subject: [PATCH 590/703] drm/v3d: Update to upstream IRQ code.
-
----
- drivers/gpu/drm/v3d/v3d_irq.c | 25 +++++++++++++++----------
- 1 file changed, 15 insertions(+), 10 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_irq.c
-+++ b/drivers/gpu/drm/v3d/v3d_irq.c
-@@ -168,7 +168,7 @@ v3d_hub_irq(int irq, void *arg)
- int
- v3d_irq_init(struct v3d_dev *v3d)
- {
-- int ret, core;
-+ int irq1, ret, core;
-
- INIT_WORK(&v3d->overflow_mem_work, v3d_overflow_mem_work);
-
-@@ -179,24 +179,29 @@ v3d_irq_init(struct v3d_dev *v3d)
- V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS);
- V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS);
-
-- if (platform_get_irq(v3d->pdev, 1) < 0) {
-- ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
-+ irq1 = platform_get_irq(v3d->pdev, 1);
-+ if (irq1 == -EPROBE_DEFER)
-+ return irq1;
-+ if (irq1 > 0) {
-+ ret = devm_request_irq(v3d->dev, irq1,
- v3d_irq, IRQF_SHARED,
-- "v3d", v3d);
-- v3d->single_irq_line = true;
-- } else {
-+ "v3d_core0", v3d);
-+ if (ret)
-+ goto fail;
- ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
- v3d_hub_irq, IRQF_SHARED,
- "v3d_hub", v3d);
- if (ret)
- goto fail;
-+ } else {
-+ v3d->single_irq_line = true;
-
-- ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 1),
-+ ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0),
- v3d_irq, IRQF_SHARED,
-- "v3d_core0", v3d);
-+ "v3d", v3d);
-+ if (ret)
-+ goto fail;
- }
-- if (ret)
-- goto fail;
-
- v3d_irq_enable(v3d);
- return 0;
--- /dev/null
+From 4d3b9226dfa79720e200af46474b2e6f3158d40c Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 28 Mar 2019 11:58:51 -0700
+Subject: [PATCH 590/725] drm/vc4: Fix synchronization firmwarekms against GL
+ rendering.
+
+We would present the framebuffer immediately without waiting for
+rendering to finish first, resulting in stuttering and flickering as a
+window was dragged around when the GPU was busy enough to not just win
+the race.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -15,6 +15,7 @@
+ */
+
+ #include "drm/drm_atomic_helper.h"
++#include "drm/drm_gem_framebuffer_helper.h"
+ #include "drm/drm_plane_helper.h"
+ #include "drm/drm_crtc_helper.h"
+ #include "drm/drm_fourcc.h"
+@@ -291,7 +292,7 @@ static const struct drm_plane_funcs vc4_
+ };
+
+ static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = {
+- .prepare_fb = NULL,
++ .prepare_fb = drm_gem_fb_prepare_fb,
+ .cleanup_fb = NULL,
+ .atomic_check = vc4_plane_atomic_check,
+ .atomic_update = vc4_primary_plane_atomic_update,
+@@ -299,7 +300,7 @@ static const struct drm_plane_helper_fun
+ };
+
+ static const struct drm_plane_helper_funcs vc4_cursor_plane_helper_funcs = {
+- .prepare_fb = NULL,
++ .prepare_fb = drm_gem_fb_prepare_fb,
+ .cleanup_fb = NULL,
+ .atomic_check = vc4_plane_atomic_check,
+ .atomic_update = vc4_cursor_plane_atomic_update,
+++ /dev/null
-From ee870243ebbf7a8a7c5a8c24259a8c37be16b507 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 27 Dec 2018 14:04:44 -0800
-Subject: [PATCH 591/703] drm/v3d: Rename the fence signaled from IRQs to
- "irq_fence".
-
-We have another thing called the "done fence" that tracks when the
-scheduler considers the job done, and having the shared name was
-confusing.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_drv.h | 4 ++--
- drivers/gpu/drm/v3d/v3d_gem.c | 6 +++---
- drivers/gpu/drm/v3d/v3d_irq.c | 6 +++---
- drivers/gpu/drm/v3d/v3d_sched.c | 12 ++++++------
- 4 files changed, 14 insertions(+), 14 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -182,7 +182,7 @@ struct v3d_job {
- struct dma_fence *in_fence;
-
- /* v3d fence to be signaled by IRQ handler when the job is complete. */
-- struct dma_fence *done_fence;
-+ struct dma_fence *irq_fence;
-
- /* GPU virtual addresses of the start/end of the CL job. */
- u32 start, end;
-@@ -229,7 +229,7 @@ struct v3d_tfu_job {
- struct dma_fence *in_fence;
-
- /* v3d fence to be signaled by IRQ handler when the job is complete. */
-- struct dma_fence *done_fence;
-+ struct dma_fence *irq_fence;
-
- struct v3d_dev *v3d;
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -381,8 +381,8 @@ v3d_exec_cleanup(struct kref *ref)
- dma_fence_put(exec->bin.in_fence);
- dma_fence_put(exec->render.in_fence);
-
-- dma_fence_put(exec->bin.done_fence);
-- dma_fence_put(exec->render.done_fence);
-+ dma_fence_put(exec->bin.irq_fence);
-+ dma_fence_put(exec->render.irq_fence);
-
- dma_fence_put(exec->bin_done_fence);
- dma_fence_put(exec->render_done_fence);
-@@ -411,7 +411,7 @@ v3d_tfu_job_cleanup(struct kref *ref)
- unsigned int i;
-
- dma_fence_put(job->in_fence);
-- dma_fence_put(job->done_fence);
-+ dma_fence_put(job->irq_fence);
-
- for (i = 0; i < ARRAY_SIZE(job->bo); i++) {
- if (job->bo[i])
---- a/drivers/gpu/drm/v3d/v3d_irq.c
-+++ b/drivers/gpu/drm/v3d/v3d_irq.c
-@@ -93,7 +93,7 @@ v3d_irq(int irq, void *arg)
-
- if (intsts & V3D_INT_FLDONE) {
- struct v3d_fence *fence =
-- to_v3d_fence(v3d->bin_job->bin.done_fence);
-+ to_v3d_fence(v3d->bin_job->bin.irq_fence);
-
- trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
- dma_fence_signal(&fence->base);
-@@ -102,7 +102,7 @@ v3d_irq(int irq, void *arg)
-
- if (intsts & V3D_INT_FRDONE) {
- struct v3d_fence *fence =
-- to_v3d_fence(v3d->render_job->render.done_fence);
-+ to_v3d_fence(v3d->render_job->render.irq_fence);
-
- trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
- dma_fence_signal(&fence->base);
-@@ -138,7 +138,7 @@ v3d_hub_irq(int irq, void *arg)
-
- if (intsts & V3D_HUB_INT_TFUC) {
- struct v3d_fence *fence =
-- to_v3d_fence(v3d->tfu_job->done_fence);
-+ to_v3d_fence(v3d->tfu_job->irq_fence);
-
- trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
- dma_fence_signal(&fence->base);
---- a/drivers/gpu/drm/v3d/v3d_sched.c
-+++ b/drivers/gpu/drm/v3d/v3d_sched.c
-@@ -152,9 +152,9 @@ static struct dma_fence *v3d_job_run(str
- if (IS_ERR(fence))
- return NULL;
-
-- if (job->done_fence)
-- dma_fence_put(job->done_fence);
-- job->done_fence = dma_fence_get(fence);
-+ if (job->irq_fence)
-+ dma_fence_put(job->irq_fence);
-+ job->irq_fence = dma_fence_get(fence);
-
- trace_v3d_submit_cl(dev, q == V3D_RENDER, to_v3d_fence(fence)->seqno,
- job->start, job->end);
-@@ -195,9 +195,9 @@ v3d_tfu_job_run(struct drm_sched_job *sc
- return NULL;
-
- v3d->tfu_job = job;
-- if (job->done_fence)
-- dma_fence_put(job->done_fence);
-- job->done_fence = dma_fence_get(fence);
-+ if (job->irq_fence)
-+ dma_fence_put(job->irq_fence);
-+ job->irq_fence = dma_fence_get(fence);
-
- trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
-
--- /dev/null
+From 0ce577f34c986e0d3e42aecd3a7a3407d5d52f1b Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 29 Mar 2019 12:04:36 -0700
+Subject: [PATCH 591/725] drm/vc4: Make sure that vblank waits work without v3d
+ loaded.
+
+This flag exists to protect legacy drivers, but when vc4's v3d doesn't
+probe, it doesn't get set up by vc4_v3d.c's call of drm_irq_install.
+This resulted in applications running as fast as possible, and laggy
+performance from compton as it had to wait for the latest rendering by
+the application for its presentation.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_kms.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -422,6 +422,7 @@ int vc4_kms_load(struct drm_device *dev)
+ /* Set support for vblank irq fast disable, before drm_vblank_init() */
+ dev->vblank_disable_immediate = true;
+
++ dev->irq_enabled = true;
+ ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+ if (ret < 0) {
+ dev_err(dev->dev, "failed to initialize vblank\n");
+++ /dev/null
-From fe5b0a576fd25f7929e553cd11d98959af808525 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 27 Dec 2018 12:11:52 -0800
-Subject: [PATCH 592/703] drm/v3d: Refactor job management.
-
-The CL submission had two jobs embedded in an exec struct. When I
-added TFU support, I had to replicate some of the exec stuff and some
-of the job stuff. As I went to add CSD, it became clear that actually
-what was in exec should just be in the two CL jobs, and it would let
-us share a lot more code between the 4 queues.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_drv.h | 77 ++++----
- drivers/gpu/drm/v3d/v3d_gem.c | 331 +++++++++++++++++---------------
- drivers/gpu/drm/v3d/v3d_irq.c | 8 +-
- drivers/gpu/drm/v3d/v3d_sched.c | 264 ++++++++++++++-----------
- 4 files changed, 373 insertions(+), 307 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -67,8 +67,8 @@ struct v3d_dev {
-
- struct work_struct overflow_mem_work;
-
-- struct v3d_exec_info *bin_job;
-- struct v3d_exec_info *render_job;
-+ struct v3d_bin_job *bin_job;
-+ struct v3d_render_job *render_job;
- struct v3d_tfu_job *tfu_job;
-
- struct v3d_queue_state queue[V3D_MAX_QUEUES];
-@@ -132,7 +132,7 @@ struct v3d_bo {
- struct list_head vmas; /* list of v3d_vma */
-
- /* List entry for the BO's position in
-- * v3d_exec_info->unref_list
-+ * v3d_render_job->unref_list
- */
- struct list_head unref_head;
-
-@@ -176,7 +176,15 @@ to_v3d_fence(struct dma_fence *fence)
- struct v3d_job {
- struct drm_sched_job base;
-
-- struct v3d_exec_info *exec;
-+ struct kref refcount;
-+
-+ struct v3d_dev *v3d;
-+
-+ /* This is the array of BOs that were looked up at the start
-+ * of submission.
-+ */
-+ struct v3d_bo **bo;
-+ u32 bo_count;
-
- /* An optional fence userspace can pass in for the job to depend on. */
- struct dma_fence *in_fence;
-@@ -184,59 +192,53 @@ struct v3d_job {
- /* v3d fence to be signaled by IRQ handler when the job is complete. */
- struct dma_fence *irq_fence;
-
-+ /* scheduler fence for when the job is considered complete and
-+ * the BO reservations can be released.
-+ */
-+ struct dma_fence *done_fence;
-+
-+ /* Callback for the freeing of the job on refcount going to 0. */
-+ void (*free)(struct kref *ref);
-+};
-+
-+struct v3d_bin_job {
-+ struct v3d_job base;
-+
- /* GPU virtual addresses of the start/end of the CL job. */
- u32 start, end;
-
- u32 timedout_ctca, timedout_ctra;
--};
-
--struct v3d_exec_info {
-- struct v3d_dev *v3d;
-+ /* Corresponding render job, for attaching our overflow memory. */
-+ struct v3d_render_job *render;
-+
-+ /* Submitted tile memory allocation start/size, tile state. */
-+ u32 qma, qms, qts;
-+};
-
-- struct v3d_job bin, render;
-+struct v3d_render_job {
-+ struct v3d_job base;
-
-- /* Fence for when the scheduler considers the binner to be
-- * done, for render to depend on.
-+ /* Optional fence for the binner, to depend on before starting
-+ * our job.
- */
- struct dma_fence *bin_done_fence;
-
-- /* Fence for when the scheduler considers the render to be
-- * done, for when the BOs reservations should be complete.
-- */
-- struct dma_fence *render_done_fence;
--
-- struct kref refcount;
-+ /* GPU virtual addresses of the start/end of the CL job. */
-+ u32 start, end;
-
-- /* This is the array of BOs that were looked up at the start of exec. */
-- struct v3d_bo **bo;
-- u32 bo_count;
-+ u32 timedout_ctca, timedout_ctra;
-
- /* List of overflow BOs used in the job that need to be
- * released once the job is complete.
- */
- struct list_head unref_list;
--
-- /* Submitted tile memory allocation start/size, tile state. */
-- u32 qma, qms, qts;
- };
-
- struct v3d_tfu_job {
-- struct drm_sched_job base;
-+ struct v3d_job base;
-
- struct drm_v3d_submit_tfu args;
--
-- /* An optional fence userspace can pass in for the job to depend on. */
-- struct dma_fence *in_fence;
--
-- /* v3d fence to be signaled by IRQ handler when the job is complete. */
-- struct dma_fence *irq_fence;
--
-- struct v3d_dev *v3d;
--
-- struct kref refcount;
--
-- /* This is the array of BOs that were looked up at the start of exec. */
-- struct v3d_bo *bo[4];
- };
-
- /**
-@@ -306,8 +308,7 @@ int v3d_submit_tfu_ioctl(struct drm_devi
- struct drm_file *file_priv);
- int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
--void v3d_exec_put(struct v3d_exec_info *exec);
--void v3d_tfu_job_put(struct v3d_tfu_job *exec);
-+void v3d_job_put(struct v3d_job *job);
- void v3d_reset(struct v3d_dev *v3d);
- void v3d_invalidate_caches(struct v3d_dev *v3d);
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -293,11 +293,11 @@ retry:
- }
-
- /**
-- * v3d_cl_lookup_bos() - Sets up exec->bo[] with the GEM objects
-+ * v3d_lookup_bos() - Sets up job->bo[] with the GEM objects
- * referenced by the job.
- * @dev: DRM device
- * @file_priv: DRM file for this fd
-- * @exec: V3D job being set up
-+ * @job: V3D job being set up
- *
- * The command validator needs to reference BOs by their index within
- * the submitted job's BO list. This does the validation of the job's
-@@ -307,18 +307,19 @@ retry:
- * failure, because that will happen at v3d_exec_cleanup() time.
- */
- static int
--v3d_cl_lookup_bos(struct drm_device *dev,
-- struct drm_file *file_priv,
-- struct drm_v3d_submit_cl *args,
-- struct v3d_exec_info *exec)
-+v3d_lookup_bos(struct drm_device *dev,
-+ struct drm_file *file_priv,
-+ struct v3d_job *job,
-+ u64 bo_handles,
-+ u32 bo_count)
- {
- u32 *handles;
- int ret = 0;
- int i;
-
-- exec->bo_count = args->bo_handle_count;
-+ job->bo_count = bo_count;
-
-- if (!exec->bo_count) {
-+ if (!job->bo_count) {
- /* See comment on bo_index for why we have to check
- * this.
- */
-@@ -326,15 +327,15 @@ v3d_cl_lookup_bos(struct drm_device *dev
- return -EINVAL;
- }
-
-- exec->bo = kvmalloc_array(exec->bo_count,
-- sizeof(struct drm_gem_cma_object *),
-- GFP_KERNEL | __GFP_ZERO);
-- if (!exec->bo) {
-+ job->bo = kvmalloc_array(job->bo_count,
-+ sizeof(struct drm_gem_cma_object *),
-+ GFP_KERNEL | __GFP_ZERO);
-+ if (!job->bo) {
- DRM_DEBUG("Failed to allocate validated BO pointers\n");
- return -ENOMEM;
- }
-
-- handles = kvmalloc_array(exec->bo_count, sizeof(u32), GFP_KERNEL);
-+ handles = kvmalloc_array(job->bo_count, sizeof(u32), GFP_KERNEL);
- if (!handles) {
- ret = -ENOMEM;
- DRM_DEBUG("Failed to allocate incoming GEM handles\n");
-@@ -342,15 +343,15 @@ v3d_cl_lookup_bos(struct drm_device *dev
- }
-
- if (copy_from_user(handles,
-- (void __user *)(uintptr_t)args->bo_handles,
-- exec->bo_count * sizeof(u32))) {
-+ (void __user *)(uintptr_t)bo_handles,
-+ job->bo_count * sizeof(u32))) {
- ret = -EFAULT;
- DRM_DEBUG("Failed to copy in GEM handles\n");
- goto fail;
- }
-
- spin_lock(&file_priv->table_lock);
-- for (i = 0; i < exec->bo_count; i++) {
-+ for (i = 0; i < job->bo_count; i++) {
- struct drm_gem_object *bo = idr_find(&file_priv->object_idr,
- handles[i]);
- if (!bo) {
-@@ -361,7 +362,7 @@ v3d_cl_lookup_bos(struct drm_device *dev
- goto fail;
- }
- drm_gem_object_get(bo);
-- exec->bo[i] = to_v3d_bo(bo);
-+ job->bo[i] = to_v3d_bo(bo);
- }
- spin_unlock(&file_priv->table_lock);
-
-@@ -371,59 +372,41 @@ fail:
- }
-
- static void
--v3d_exec_cleanup(struct kref *ref)
-+v3d_job_free(struct kref *ref)
- {
-- struct v3d_exec_info *exec = container_of(ref, struct v3d_exec_info,
-- refcount);
-- unsigned int i;
-- struct v3d_bo *bo, *save;
--
-- dma_fence_put(exec->bin.in_fence);
-- dma_fence_put(exec->render.in_fence);
--
-- dma_fence_put(exec->bin.irq_fence);
-- dma_fence_put(exec->render.irq_fence);
--
-- dma_fence_put(exec->bin_done_fence);
-- dma_fence_put(exec->render_done_fence);
--
-- for (i = 0; i < exec->bo_count; i++)
-- drm_gem_object_put_unlocked(&exec->bo[i]->base);
-- kvfree(exec->bo);
-+ struct v3d_job *job = container_of(ref, struct v3d_job, refcount);
-+ int i;
-
-- list_for_each_entry_safe(bo, save, &exec->unref_list, unref_head) {
-- drm_gem_object_put_unlocked(&bo->base);
-+ for (i = 0; i < job->bo_count; i++) {
-+ if (job->bo[i])
-+ drm_gem_object_put_unlocked(&job->bo[i]->base);
- }
-+ kvfree(job->bo);
-
-- kfree(exec);
--}
-+ dma_fence_put(job->in_fence);
-+ dma_fence_put(job->irq_fence);
-+ dma_fence_put(job->done_fence);
-
--void v3d_exec_put(struct v3d_exec_info *exec)
--{
-- kref_put(&exec->refcount, v3d_exec_cleanup);
-+ kfree(job);
- }
-
- static void
--v3d_tfu_job_cleanup(struct kref *ref)
-+v3d_render_job_free(struct kref *ref)
- {
-- struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,
-- refcount);
-- unsigned int i;
--
-- dma_fence_put(job->in_fence);
-- dma_fence_put(job->irq_fence);
-+ struct v3d_render_job *job = container_of(ref, struct v3d_render_job,
-+ base.refcount);
-+ struct v3d_bo *bo, *save;
-
-- for (i = 0; i < ARRAY_SIZE(job->bo); i++) {
-- if (job->bo[i])
-- drm_gem_object_put_unlocked(&job->bo[i]->base);
-+ list_for_each_entry_safe(bo, save, &job->unref_list, unref_head) {
-+ drm_gem_object_put_unlocked(&bo->base);
- }
-
-- kfree(job);
-+ v3d_job_free(ref);
- }
-
--void v3d_tfu_job_put(struct v3d_tfu_job *job)
-+void v3d_job_put(struct v3d_job *job)
- {
-- kref_put(&job->refcount, v3d_tfu_job_cleanup);
-+ kref_put(&job->refcount, job->free);
- }
-
- int
-@@ -476,6 +459,65 @@ v3d_wait_bo_ioctl(struct drm_device *dev
- return ret;
- }
-
-+static int
-+v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,
-+ struct v3d_job *job, void (*free)(struct kref *ref),
-+ u32 in_sync)
-+{
-+ int ret;
-+
-+ job->v3d = v3d;
-+ job->free = free;
-+
-+ ret = drm_syncobj_find_fence(file_priv, in_sync, 0, &job->in_fence);
-+ if (ret == -EINVAL)
-+ return ret;
-+
-+ kref_init(&job->refcount);
-+
-+ return 0;
-+}
-+
-+static int
-+v3d_push_job(struct v3d_file_priv *v3d_priv,
-+ struct v3d_job *job, enum v3d_queue queue)
-+{
-+ int ret;
-+
-+ ret = drm_sched_job_init(&job->base, &v3d_priv->sched_entity[queue],
-+ v3d_priv);
-+ if (ret)
-+ return ret;
-+
-+ job->done_fence = dma_fence_get(&job->base.s_fence->finished);
-+
-+ /* put by scheduler job completion */
-+ kref_get(&job->refcount);
-+
-+ drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[queue]);
-+
-+ return 0;
-+}
-+
-+static void
-+v3d_attach_fences_and_unlock_reservation(struct drm_file *file_priv,
-+ struct v3d_job *job,
-+ struct ww_acquire_ctx *acquire_ctx,
-+ u32 out_sync)
-+{
-+ struct drm_syncobj *sync_out;
-+
-+ v3d_attach_object_fences(job->bo, job->bo_count, job->done_fence);
-+ v3d_unlock_bo_reservations(job->bo, job->bo_count, acquire_ctx);
-+
-+ /* Update the return sync object for the job */
-+ sync_out = drm_syncobj_find(file_priv, out_sync);
-+ if (sync_out) {
-+ drm_syncobj_replace_fence(sync_out, job->done_fence);
-+ drm_syncobj_put(sync_out);
-+ }
-+}
-+
- /**
- * v3d_submit_cl_ioctl() - Submits a job (frame) to the V3D.
- * @dev: DRM device
-@@ -495,9 +537,9 @@ v3d_submit_cl_ioctl(struct drm_device *d
- struct v3d_dev *v3d = to_v3d_dev(dev);
- struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
- struct drm_v3d_submit_cl *args = data;
-- struct v3d_exec_info *exec;
-+ struct v3d_bin_job *bin = NULL;
-+ struct v3d_render_job *render;
- struct ww_acquire_ctx acquire_ctx;
-- struct drm_syncobj *sync_out;
- int ret = 0;
-
- trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
-@@ -507,95 +549,84 @@ v3d_submit_cl_ioctl(struct drm_device *d
- return -EINVAL;
- }
-
-- exec = kcalloc(1, sizeof(*exec), GFP_KERNEL);
-- if (!exec)
-+ render = kcalloc(1, sizeof(*render), GFP_KERNEL);
-+ if (!render)
- return -ENOMEM;
-
-- kref_init(&exec->refcount);
-+ render->start = args->rcl_start;
-+ render->end = args->rcl_end;
-+ INIT_LIST_HEAD(&render->unref_list);
-
-- ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,
-- 0, &exec->bin.in_fence);
-- if (ret == -EINVAL)
-- goto fail;
-+ ret = v3d_job_init(v3d, file_priv, &render->base,
-+ v3d_render_job_free, args->in_sync_rcl);
-+ if (ret) {
-+ kfree(bin);
-+ kfree(render);
-+ return ret;
-+ }
-
-- ret = drm_syncobj_find_fence(file_priv, args->in_sync_rcl,
-- 0, &exec->render.in_fence);
-- if (ret == -EINVAL)
-- goto fail;
-+ if (args->bcl_start != args->bcl_end) {
-+ bin = kcalloc(1, sizeof(*bin), GFP_KERNEL);
-+ if (!bin)
-+ return -ENOMEM;
-+
-+ ret = v3d_job_init(v3d, file_priv, &bin->base,
-+ v3d_job_free, args->in_sync_bcl);
-+ if (ret) {
-+ v3d_job_put(&render->base);
-+ return ret;
-+ }
-
-- exec->qma = args->qma;
-- exec->qms = args->qms;
-- exec->qts = args->qts;
-- exec->bin.exec = exec;
-- exec->bin.start = args->bcl_start;
-- exec->bin.end = args->bcl_end;
-- exec->render.exec = exec;
-- exec->render.start = args->rcl_start;
-- exec->render.end = args->rcl_end;
-- exec->v3d = v3d;
-- INIT_LIST_HEAD(&exec->unref_list);
-+ bin->start = args->bcl_start;
-+ bin->end = args->bcl_end;
-+ bin->qma = args->qma;
-+ bin->qms = args->qms;
-+ bin->qts = args->qts;
-+ bin->render = render;
-+ }
-
-- ret = v3d_cl_lookup_bos(dev, file_priv, args, exec);
-+ ret = v3d_lookup_bos(dev, file_priv, &render->base,
-+ args->bo_handles, args->bo_handle_count);
- if (ret)
- goto fail;
-
-- ret = v3d_lock_bo_reservations(exec->bo, exec->bo_count,
-+ ret = v3d_lock_bo_reservations(render->base.bo, render->base.bo_count,
- &acquire_ctx);
- if (ret)
- goto fail;
-
- mutex_lock(&v3d->sched_lock);
-- if (exec->bin.start != exec->bin.end) {
-- ret = drm_sched_job_init(&exec->bin.base,
-- &v3d_priv->sched_entity[V3D_BIN],
-- v3d_priv);
-+ if (bin) {
-+ ret = v3d_push_job(v3d_priv, &bin->base, V3D_BIN);
- if (ret)
- goto fail_unreserve;
-
-- exec->bin_done_fence =
-- dma_fence_get(&exec->bin.base.s_fence->finished);
--
-- kref_get(&exec->refcount); /* put by scheduler job completion */
-- drm_sched_entity_push_job(&exec->bin.base,
-- &v3d_priv->sched_entity[V3D_BIN]);
-+ render->bin_done_fence = dma_fence_get(bin->base.done_fence);
- }
-
-- ret = drm_sched_job_init(&exec->render.base,
-- &v3d_priv->sched_entity[V3D_RENDER],
-- v3d_priv);
-+ ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);
- if (ret)
- goto fail_unreserve;
--
-- exec->render_done_fence =
-- dma_fence_get(&exec->render.base.s_fence->finished);
--
-- kref_get(&exec->refcount); /* put by scheduler job completion */
-- drm_sched_entity_push_job(&exec->render.base,
-- &v3d_priv->sched_entity[V3D_RENDER]);
- mutex_unlock(&v3d->sched_lock);
-
-- v3d_attach_object_fences(exec->bo, exec->bo_count,
-- exec->render_done_fence);
--
-- v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
--
-- /* Update the return sync object for the */
-- sync_out = drm_syncobj_find(file_priv, args->out_sync);
-- if (sync_out) {
-- drm_syncobj_replace_fence(sync_out,
-- exec->render_done_fence);
-- drm_syncobj_put(sync_out);
-- }
--
-- v3d_exec_put(exec);
-+ v3d_attach_fences_and_unlock_reservation(file_priv,
-+ &render->base, &acquire_ctx,
-+ args->out_sync);
-+
-+ if (bin)
-+ v3d_job_put(&bin->base);
-+ v3d_job_put(&render->base);
-
- return 0;
-
- fail_unreserve:
- mutex_unlock(&v3d->sched_lock);
-- v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
-+ v3d_unlock_bo_reservations(render->base.bo,
-+ render->base.bo_count, &acquire_ctx);
- fail:
-- v3d_exec_put(exec);
-+ if (bin)
-+ v3d_job_put(&bin->base);
-+ v3d_job_put(&render->base);
-
- return ret;
- }
-@@ -618,10 +649,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
- struct drm_v3d_submit_tfu *args = data;
- struct v3d_tfu_job *job;
- struct ww_acquire_ctx acquire_ctx;
-- struct drm_syncobj *sync_out;
-- struct dma_fence *sched_done_fence;
- int ret = 0;
-- int bo_count;
-
- trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia);
-
-@@ -629,75 +657,66 @@ v3d_submit_tfu_ioctl(struct drm_device *
- if (!job)
- return -ENOMEM;
-
-- kref_init(&job->refcount);
--
-- ret = drm_syncobj_find_fence(file_priv, args->in_sync,
-- 0, &job->in_fence);
-- if (ret == -EINVAL)
-- goto fail;
-+ ret = v3d_job_init(v3d, file_priv, &job->base,
-+ v3d_job_free, args->in_sync);
-+ if (ret) {
-+ kfree(job);
-+ return ret;
-+ }
-
-+ job->base.bo = kcalloc(ARRAY_SIZE(args->bo_handles),
-+ sizeof(*job->base.bo), GFP_KERNEL);
- job->args = *args;
-- job->v3d = v3d;
-
- spin_lock(&file_priv->table_lock);
-- for (bo_count = 0; bo_count < ARRAY_SIZE(job->bo); bo_count++) {
-+ for (job->base.bo_count = 0;
-+ job->base.bo_count < ARRAY_SIZE(args->bo_handles);
-+ job->base.bo_count++) {
- struct drm_gem_object *bo;
-
-- if (!args->bo_handles[bo_count])
-+ if (!args->bo_handles[job->base.bo_count])
- break;
-
- bo = idr_find(&file_priv->object_idr,
-- args->bo_handles[bo_count]);
-+ args->bo_handles[job->base.bo_count]);
- if (!bo) {
- DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
-- bo_count, args->bo_handles[bo_count]);
-+ job->base.bo_count,
-+ args->bo_handles[job->base.bo_count]);
- ret = -ENOENT;
- spin_unlock(&file_priv->table_lock);
- goto fail;
- }
- drm_gem_object_get(bo);
-- job->bo[bo_count] = to_v3d_bo(bo);
-+ job->base.bo[job->base.bo_count] = to_v3d_bo(bo);
- }
- spin_unlock(&file_priv->table_lock);
-
-- ret = v3d_lock_bo_reservations(job->bo, bo_count, &acquire_ctx);
-+ ret = v3d_lock_bo_reservations(job->base.bo, job->base.bo_count,
-+ &acquire_ctx);
- if (ret)
- goto fail;
-
- mutex_lock(&v3d->sched_lock);
-- ret = drm_sched_job_init(&job->base,
-- &v3d_priv->sched_entity[V3D_TFU],
-- v3d_priv);
-+ ret = v3d_push_job(v3d_priv, &job->base, V3D_TFU);
- if (ret)
- goto fail_unreserve;
--
-- sched_done_fence = dma_fence_get(&job->base.s_fence->finished);
--
-- kref_get(&job->refcount); /* put by scheduler job completion */
-- drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[V3D_TFU]);
- mutex_unlock(&v3d->sched_lock);
-
-- v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);
--
-- v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
--
-- /* Update the return sync object */
-- sync_out = drm_syncobj_find(file_priv, args->out_sync);
-- if (sync_out) {
-- drm_syncobj_replace_fence(sync_out, sched_done_fence);
-- drm_syncobj_put(sync_out);
-- }
-- dma_fence_put(sched_done_fence);
-+ v3d_attach_fences_and_unlock_reservation(file_priv,
-+ &job->base, &acquire_ctx,
-+ args->out_sync);
-
-- v3d_tfu_job_put(job);
-+ v3d_job_put(&job->base);
-
- return 0;
-
- fail_unreserve:
- mutex_unlock(&v3d->sched_lock);
-- v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
-+ v3d_unlock_bo_reservations(job->base.bo, job->base.bo_count,
-+ &acquire_ctx);
- fail:
-- v3d_tfu_job_put(job);
-+ v3d_job_put(&job->base);
-
- return ret;
- }
-@@ -755,7 +774,7 @@ v3d_gem_destroy(struct drm_device *dev)
-
- v3d_sched_fini(v3d);
-
-- /* Waiting for exec to finish would need to be done before
-+ /* Waiting for jobs to finish would need to be done before
- * unregistering V3D.
- */
- WARN_ON(v3d->bin_job);
---- a/drivers/gpu/drm/v3d/v3d_irq.c
-+++ b/drivers/gpu/drm/v3d/v3d_irq.c
-@@ -60,7 +60,7 @@ v3d_overflow_mem_work(struct work_struct
- }
-
- drm_gem_object_get(&bo->base);
-- list_add_tail(&bo->unref_head, &v3d->bin_job->unref_list);
-+ list_add_tail(&bo->unref_head, &v3d->bin_job->render->unref_list);
- spin_unlock_irqrestore(&v3d->job_lock, irqflags);
-
- V3D_CORE_WRITE(0, V3D_PTB_BPOA, bo->node.start << PAGE_SHIFT);
-@@ -93,7 +93,7 @@ v3d_irq(int irq, void *arg)
-
- if (intsts & V3D_INT_FLDONE) {
- struct v3d_fence *fence =
-- to_v3d_fence(v3d->bin_job->bin.irq_fence);
-+ to_v3d_fence(v3d->bin_job->base.irq_fence);
-
- trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
- dma_fence_signal(&fence->base);
-@@ -102,7 +102,7 @@ v3d_irq(int irq, void *arg)
-
- if (intsts & V3D_INT_FRDONE) {
- struct v3d_fence *fence =
-- to_v3d_fence(v3d->render_job->render.irq_fence);
-+ to_v3d_fence(v3d->render_job->base.irq_fence);
-
- trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
- dma_fence_signal(&fence->base);
-@@ -138,7 +138,7 @@ v3d_hub_irq(int irq, void *arg)
-
- if (intsts & V3D_HUB_INT_TFUC) {
- struct v3d_fence *fence =
-- to_v3d_fence(v3d->tfu_job->irq_fence);
-+ to_v3d_fence(v3d->tfu_job->base.irq_fence);
-
- trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
- dma_fence_signal(&fence->base);
---- a/drivers/gpu/drm/v3d/v3d_sched.c
-+++ b/drivers/gpu/drm/v3d/v3d_sched.c
-@@ -30,39 +30,43 @@ to_v3d_job(struct drm_sched_job *sched_j
- return container_of(sched_job, struct v3d_job, base);
- }
-
--static struct v3d_tfu_job *
--to_tfu_job(struct drm_sched_job *sched_job)
-+static struct v3d_bin_job *
-+to_bin_job(struct drm_sched_job *sched_job)
- {
-- return container_of(sched_job, struct v3d_tfu_job, base);
-+ return container_of(sched_job, struct v3d_bin_job, base.base);
- }
-
--static void
--v3d_job_free(struct drm_sched_job *sched_job)
-+static struct v3d_render_job *
-+to_render_job(struct drm_sched_job *sched_job)
- {
-- struct v3d_job *job = to_v3d_job(sched_job);
-+ return container_of(sched_job, struct v3d_render_job, base.base);
-+}
-
-- v3d_exec_put(job->exec);
-+static struct v3d_tfu_job *
-+to_tfu_job(struct drm_sched_job *sched_job)
-+{
-+ return container_of(sched_job, struct v3d_tfu_job, base.base);
- }
-
- static void
--v3d_tfu_job_free(struct drm_sched_job *sched_job)
-+v3d_job_free(struct drm_sched_job *sched_job)
- {
-- struct v3d_tfu_job *job = to_tfu_job(sched_job);
-+ struct v3d_job *job = to_v3d_job(sched_job);
-
-- v3d_tfu_job_put(job);
-+ v3d_job_put(job);
- }
-
- /**
-- * Returns the fences that the bin or render job depends on, one by one.
-- * v3d_job_run() won't be called until all of them have been signaled.
-+ * Returns the fences that the job depends on, one by one.
-+ *
-+ * If placed in the scheduler's .dependency method, the corresponding
-+ * .run_job won't be called until all of them have been signaled.
- */
- static struct dma_fence *
- v3d_job_dependency(struct drm_sched_job *sched_job,
- struct drm_sched_entity *s_entity)
- {
- struct v3d_job *job = to_v3d_job(sched_job);
-- struct v3d_exec_info *exec = job->exec;
-- enum v3d_queue q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
- struct dma_fence *fence;
-
- fence = job->in_fence;
-@@ -71,113 +75,132 @@ v3d_job_dependency(struct drm_sched_job
- return fence;
- }
-
-- if (q == V3D_RENDER) {
-- /* If we had a bin job, the render job definitely depends on
-- * it. We first have to wait for bin to be scheduled, so that
-- * its done_fence is created.
-- */
-- fence = exec->bin_done_fence;
-- if (fence) {
-- exec->bin_done_fence = NULL;
-- return fence;
-- }
-- }
--
-- /* XXX: Wait on a fence for switching the GMP if necessary,
-- * and then do so.
-- */
--
-- return fence;
-+ return NULL;
- }
-
- /**
-- * Returns the fences that the TFU job depends on, one by one.
-- * v3d_tfu_job_run() won't be called until all of them have been
-- * signaled.
-+ * Returns the fences that the render job depends on, one by one.
-+ * v3d_job_run() won't be called until all of them have been signaled.
- */
- static struct dma_fence *
--v3d_tfu_job_dependency(struct drm_sched_job *sched_job,
-- struct drm_sched_entity *s_entity)
-+v3d_render_job_dependency(struct drm_sched_job *sched_job,
-+ struct drm_sched_entity *s_entity)
- {
-- struct v3d_tfu_job *job = to_tfu_job(sched_job);
-+ struct v3d_render_job *job = to_render_job(sched_job);
- struct dma_fence *fence;
-
-- fence = job->in_fence;
-+ fence = v3d_job_dependency(sched_job, s_entity);
-+ if (fence)
-+ return fence;
-+
-+ /* If we had a bin job, the render job definitely depends on
-+ * it. We first have to wait for bin to be scheduled, so that
-+ * its done_fence is created.
-+ */
-+ fence = job->bin_done_fence;
- if (fence) {
-- job->in_fence = NULL;
-+ job->bin_done_fence = NULL;
- return fence;
- }
-
-- return NULL;
-+ /* XXX: Wait on a fence for switching the GMP if necessary,
-+ * and then do so.
-+ */
-+
-+ return fence;
- }
-
--static struct dma_fence *v3d_job_run(struct drm_sched_job *sched_job)
-+static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
- {
-- struct v3d_job *job = to_v3d_job(sched_job);
-- struct v3d_exec_info *exec = job->exec;
-- enum v3d_queue q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
-- struct v3d_dev *v3d = exec->v3d;
-+ struct v3d_bin_job *job = to_bin_job(sched_job);
-+ struct v3d_dev *v3d = job->base.v3d;
- struct drm_device *dev = &v3d->drm;
- struct dma_fence *fence;
- unsigned long irqflags;
-
-- if (unlikely(job->base.s_fence->finished.error))
-+ if (unlikely(job->base.base.s_fence->finished.error))
- return NULL;
-
- /* Lock required around bin_job update vs
- * v3d_overflow_mem_work().
- */
- spin_lock_irqsave(&v3d->job_lock, irqflags);
-- if (q == V3D_BIN) {
-- v3d->bin_job = job->exec;
-+ v3d->bin_job = job;
-+ /* Clear out the overflow allocation, so we don't
-+ * reuse the overflow attached to a previous job.
-+ */
-+ V3D_CORE_WRITE(0, V3D_PTB_BPOS, 0);
-+ spin_unlock_irqrestore(&v3d->job_lock, irqflags);
-+
-+ v3d_invalidate_caches(v3d);
-
-- /* Clear out the overflow allocation, so we don't
-- * reuse the overflow attached to a previous job.
-- */
-- V3D_CORE_WRITE(0, V3D_PTB_BPOS, 0);
-- } else {
-- v3d->render_job = job->exec;
-+ fence = v3d_fence_create(v3d, V3D_BIN);
-+ if (IS_ERR(fence))
-+ return NULL;
-+
-+ if (job->base.irq_fence)
-+ dma_fence_put(job->base.irq_fence);
-+ job->base.irq_fence = dma_fence_get(fence);
-+
-+ trace_v3d_submit_cl(dev, false, to_v3d_fence(fence)->seqno,
-+ job->start, job->end);
-+
-+ /* Set the current and end address of the control list.
-+ * Writing the end register is what starts the job.
-+ */
-+ if (job->qma) {
-+ V3D_CORE_WRITE(0, V3D_CLE_CT0QMA, job->qma);
-+ V3D_CORE_WRITE(0, V3D_CLE_CT0QMS, job->qms);
- }
-- spin_unlock_irqrestore(&v3d->job_lock, irqflags);
-+ if (job->qts) {
-+ V3D_CORE_WRITE(0, V3D_CLE_CT0QTS,
-+ V3D_CLE_CT0QTS_ENABLE |
-+ job->qts);
-+ }
-+ V3D_CORE_WRITE(0, V3D_CLE_CT0QBA, job->start);
-+ V3D_CORE_WRITE(0, V3D_CLE_CT0QEA, job->end);
-+
-+ return fence;
-+}
-+
-+static struct dma_fence *v3d_render_job_run(struct drm_sched_job *sched_job)
-+{
-+ struct v3d_render_job *job = to_render_job(sched_job);
-+ struct v3d_dev *v3d = job->base.v3d;
-+ struct drm_device *dev = &v3d->drm;
-+ struct dma_fence *fence;
-+
-+ if (unlikely(job->base.base.s_fence->finished.error))
-+ return NULL;
-
-- /* Can we avoid this flush when q==RENDER? We need to be
-- * careful of scheduling, though -- imagine job0 rendering to
-- * texture and job1 reading, and them being executed as bin0,
-- * bin1, render0, render1, so that render1's flush at bin time
-+ v3d->render_job = job;
-+
-+ /* Can we avoid this flush? We need to be careful of
-+ * scheduling, though -- imagine job0 rendering to texture and
-+ * job1 reading, and them being executed as bin0, bin1,
-+ * render0, render1, so that render1's flush at bin time
- * wasn't enough.
- */
- v3d_invalidate_caches(v3d);
-
-- fence = v3d_fence_create(v3d, q);
-+ fence = v3d_fence_create(v3d, V3D_RENDER);
- if (IS_ERR(fence))
- return NULL;
-
-- if (job->irq_fence)
-- dma_fence_put(job->irq_fence);
-- job->irq_fence = dma_fence_get(fence);
-+ if (job->base.irq_fence)
-+ dma_fence_put(job->base.irq_fence);
-+ job->base.irq_fence = dma_fence_get(fence);
-
-- trace_v3d_submit_cl(dev, q == V3D_RENDER, to_v3d_fence(fence)->seqno,
-+ trace_v3d_submit_cl(dev, true, to_v3d_fence(fence)->seqno,
- job->start, job->end);
-
-- if (q == V3D_BIN) {
-- if (exec->qma) {
-- V3D_CORE_WRITE(0, V3D_CLE_CT0QMA, exec->qma);
-- V3D_CORE_WRITE(0, V3D_CLE_CT0QMS, exec->qms);
-- }
-- if (exec->qts) {
-- V3D_CORE_WRITE(0, V3D_CLE_CT0QTS,
-- V3D_CLE_CT0QTS_ENABLE |
-- exec->qts);
-- }
-- } else {
-- /* XXX: Set the QCFG */
-- }
-+ /* XXX: Set the QCFG */
-
- /* Set the current and end address of the control list.
- * Writing the end register is what starts the job.
- */
-- V3D_CORE_WRITE(0, V3D_CLE_CTNQBA(q), job->start);
-- V3D_CORE_WRITE(0, V3D_CLE_CTNQEA(q), job->end);
-+ V3D_CORE_WRITE(0, V3D_CLE_CT1QBA, job->start);
-+ V3D_CORE_WRITE(0, V3D_CLE_CT1QEA, job->end);
-
- return fence;
- }
-@@ -186,7 +209,7 @@ static struct dma_fence *
- v3d_tfu_job_run(struct drm_sched_job *sched_job)
- {
- struct v3d_tfu_job *job = to_tfu_job(sched_job);
-- struct v3d_dev *v3d = job->v3d;
-+ struct v3d_dev *v3d = job->base.v3d;
- struct drm_device *dev = &v3d->drm;
- struct dma_fence *fence;
-
-@@ -195,9 +218,9 @@ v3d_tfu_job_run(struct drm_sched_job *sc
- return NULL;
-
- v3d->tfu_job = job;
-- if (job->irq_fence)
-- dma_fence_put(job->irq_fence);
-- job->irq_fence = dma_fence_get(fence);
-+ if (job->base.irq_fence)
-+ dma_fence_put(job->base.irq_fence);
-+ job->base.irq_fence = dma_fence_get(fence);
-
- trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
-
-@@ -247,25 +270,23 @@ v3d_gpu_reset_for_timeout(struct v3d_dev
- mutex_unlock(&v3d->reset_lock);
- }
-
-+/* If the current address or return address have changed, then the GPU
-+ * has probably made progress and we should delay the reset. This
-+ * could fail if the GPU got in an infinite loop in the CL, but that
-+ * is pretty unlikely outside of an i-g-t testcase.
-+ */
- static void
--v3d_job_timedout(struct drm_sched_job *sched_job)
-+v3d_cl_job_timedout(struct drm_sched_job *sched_job, enum v3d_queue q,
-+ u32 *timedout_ctca, u32 *timedout_ctra)
- {
- struct v3d_job *job = to_v3d_job(sched_job);
-- struct v3d_exec_info *exec = job->exec;
-- struct v3d_dev *v3d = exec->v3d;
-- enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
-- u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));
-- u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));
--
-- /* If the current address or return address have changed, then
-- * the GPU has probably made progress and we should delay the
-- * reset. This could fail if the GPU got in an infinite loop
-- * in the CL, but that is pretty unlikely outside of an i-g-t
-- * testcase.
-- */
-- if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) {
-- job->timedout_ctca = ctca;
-- job->timedout_ctra = ctra;
-+ struct v3d_dev *v3d = job->v3d;
-+ u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(q));
-+ u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(q));
-+
-+ if (*timedout_ctca != ctca || *timedout_ctra != ctra) {
-+ *timedout_ctca = ctca;
-+ *timedout_ctra = ctra;
- schedule_delayed_work(&job->base.work_tdr,
- job->base.sched->timeout);
- return;
-@@ -275,25 +296,50 @@ v3d_job_timedout(struct drm_sched_job *s
- }
-
- static void
-+v3d_bin_job_timedout(struct drm_sched_job *sched_job)
-+{
-+ struct v3d_bin_job *job = to_bin_job(sched_job);
-+
-+ v3d_cl_job_timedout(sched_job, V3D_BIN,
-+ &job->timedout_ctca, &job->timedout_ctra);
-+}
-+
-+static void
-+v3d_render_job_timedout(struct drm_sched_job *sched_job)
-+{
-+ struct v3d_render_job *job = to_render_job(sched_job);
-+
-+ v3d_cl_job_timedout(sched_job, V3D_RENDER,
-+ &job->timedout_ctca, &job->timedout_ctra);
-+}
-+
-+static void
- v3d_tfu_job_timedout(struct drm_sched_job *sched_job)
- {
-- struct v3d_tfu_job *job = to_tfu_job(sched_job);
-+ struct v3d_job *job = to_v3d_job(sched_job);
-
- v3d_gpu_reset_for_timeout(job->v3d, sched_job);
- }
-
--static const struct drm_sched_backend_ops v3d_sched_ops = {
-+static const struct drm_sched_backend_ops v3d_bin_sched_ops = {
- .dependency = v3d_job_dependency,
-- .run_job = v3d_job_run,
-- .timedout_job = v3d_job_timedout,
-- .free_job = v3d_job_free
-+ .run_job = v3d_bin_job_run,
-+ .timedout_job = v3d_bin_job_timedout,
-+ .free_job = v3d_job_free,
-+};
-+
-+static const struct drm_sched_backend_ops v3d_render_sched_ops = {
-+ .dependency = v3d_render_job_dependency,
-+ .run_job = v3d_render_job_run,
-+ .timedout_job = v3d_render_job_timedout,
-+ .free_job = v3d_job_free,
- };
-
- static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
-- .dependency = v3d_tfu_job_dependency,
-+ .dependency = v3d_job_dependency,
- .run_job = v3d_tfu_job_run,
- .timedout_job = v3d_tfu_job_timedout,
-- .free_job = v3d_tfu_job_free
-+ .free_job = v3d_job_free,
- };
-
- int
-@@ -305,7 +351,7 @@ v3d_sched_init(struct v3d_dev *v3d)
- int ret;
-
- ret = drm_sched_init(&v3d->queue[V3D_BIN].sched,
-- &v3d_sched_ops,
-+ &v3d_bin_sched_ops,
- hw_jobs_limit, job_hang_limit,
- msecs_to_jiffies(hang_limit_ms),
- "v3d_bin");
-@@ -315,7 +361,7 @@ v3d_sched_init(struct v3d_dev *v3d)
- }
-
- ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched,
-- &v3d_sched_ops,
-+ &v3d_render_sched_ops,
- hw_jobs_limit, job_hang_limit,
- msecs_to_jiffies(hang_limit_ms),
- "v3d_render");
--- /dev/null
+From 32964196c5dd171ac78f692faba460ae1229b995 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 18 Mar 2019 16:38:32 -0700
+Subject: [PATCH 592/725] drm/vc4: Expose the format modifiers for firmware
+ kms.
+
+This should technically not expose VC4_T_TILED on pi4. However, if we
+don't expose anything, then userspace will assume that display can
+handle whatever modifiers 3d can do (UIF on 2711). By exposing a
+list, that will get intersected with what 3D can do so that we get T
+tiling for display on 2710 and linear on 2711.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 33 +++++++++++++++++++++++++-
+ 1 file changed, 32 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -281,6 +281,27 @@ static void vc4_plane_destroy(struct drm
+ drm_plane_cleanup(plane);
+ }
+
++static bool vc4_fkms_format_mod_supported(struct drm_plane *plane,
++ uint32_t format,
++ uint64_t modifier)
++{
++ /* Support T_TILING for RGB formats only. */
++ switch (format) {
++ case DRM_FORMAT_XRGB8888:
++ case DRM_FORMAT_ARGB8888:
++ switch (modifier) {
++ case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
++ case DRM_FORMAT_MOD_LINEAR:
++ case DRM_FORMAT_MOD_BROADCOM_UIF:
++ return true;
++ default:
++ return false;
++ }
++ default:
++ return false;
++ }
++}
++
+ static const struct drm_plane_funcs vc4_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+@@ -289,6 +310,7 @@ static const struct drm_plane_funcs vc4_
+ .reset = drm_atomic_helper_plane_reset,
+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
++ .format_mod_supported = vc4_fkms_format_mod_supported,
+ };
+
+ static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = {
+@@ -316,6 +338,14 @@ static struct drm_plane *vc4_fkms_plane_
+ u32 argb8888 = DRM_FORMAT_ARGB8888;
+ int ret = 0;
+ bool primary = (type == DRM_PLANE_TYPE_PRIMARY);
++ static const uint64_t modifiers[] = {
++ DRM_FORMAT_MOD_LINEAR,
++ /* VC4_T_TILED should come after linear, because we
++ * would prefer to scan out linear (less bus traffic).
++ */
++ DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
++ DRM_FORMAT_MOD_INVALID,
++ };
+
+ vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
+ GFP_KERNEL);
+@@ -327,7 +357,8 @@ static struct drm_plane *vc4_fkms_plane_
+ plane = &vc4_plane->base;
+ ret = drm_universal_plane_init(dev, plane, 0xff,
+ &vc4_plane_funcs,
+- primary ? &xrgb8888 : &argb8888, 1, NULL,
++ primary ? &xrgb8888 : &argb8888, 1,
++ modifiers,
+ type, primary ? "primary" : "cursor");
+
+ if (type == DRM_PLANE_TYPE_PRIMARY) {
+++ /dev/null
-From 50482167989066e0fb9597fe37146a0ee5bc4067 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 27 Mar 2019 17:44:40 -0700
-Subject: [PATCH 593/703] drm/v3d: Add missing implicit synchronization.
-
-It is the expectation of existing userspace (X11 + Mesa, in
-particular) that jobs submitted to the kernel against a shared BO will
-get implicitly synchronized by their submission order. If we want to
-allow clever userspace to disable implicit synchronization, we should
-do that under its own submit flag (as amdgpu and lima do).
-
-Note that we currently only implicitly sync for the rendering pass,
-not binning -- if you texture-from-pixmap in the binning vertex shader
-(vertex coordinate generation), you'll miss out on synchronization.
-
-Fixes flickering when multiple clients are running in parallel,
-particularly GL apps and compositors.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_drv.h | 10 +---
- drivers/gpu/drm/v3d/v3d_gem.c | 98 ++++++++++++++++++++++++++++++---
- drivers/gpu/drm/v3d/v3d_sched.c | 45 ++-------------
- 3 files changed, 96 insertions(+), 57 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -186,8 +186,9 @@ struct v3d_job {
- struct v3d_bo **bo;
- u32 bo_count;
-
-- /* An optional fence userspace can pass in for the job to depend on. */
-- struct dma_fence *in_fence;
-+ struct dma_fence **deps;
-+ int deps_count;
-+ int deps_size;
-
- /* v3d fence to be signaled by IRQ handler when the job is complete. */
- struct dma_fence *irq_fence;
-@@ -219,11 +220,6 @@ struct v3d_bin_job {
- struct v3d_render_job {
- struct v3d_job base;
-
-- /* Optional fence for the binner, to depend on before starting
-- * our job.
-- */
-- struct dma_fence *bin_done_fence;
--
- /* GPU virtual addresses of the start/end of the CL job. */
- u32 start, end;
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -218,6 +218,71 @@ v3d_unlock_bo_reservations(struct v3d_bo
- ww_acquire_fini(acquire_ctx);
- }
-
-+static int
-+v3d_add_dep(struct v3d_job *job, struct dma_fence *fence)
-+{
-+ if (!fence)
-+ return 0;
-+
-+ if (job->deps_size == job->deps_count) {
-+ int new_deps_size = max(job->deps_size * 2, 4);
-+ struct dma_fence **new_deps =
-+ krealloc(job->deps, new_deps_size * sizeof(*new_deps),
-+ GFP_KERNEL);
-+ if (!new_deps) {
-+ dma_fence_put(fence);
-+ return -ENOMEM;
-+ }
-+
-+ job->deps = new_deps;
-+ job->deps_size = new_deps_size;
-+ }
-+
-+ job->deps[job->deps_count++] = fence;
-+
-+ return 0;
-+}
-+
-+/**
-+ * Adds the required implicit fences before executing the job
-+ *
-+ * Userspace (X11 + Mesa) requires that a job submitted against a shared BO
-+ * from one fd will implicitly synchronize against previous jobs submitted
-+ * against that BO from other fds.
-+ *
-+ * Currently we don't bother trying to track the shared BOs, and instead just
-+ * sync everything. However, our synchronization is only for the render pass
-+ * -- the binning stage (VS coordinate calculations) ignores implicit sync,
-+ * since using shared buffers for texture coordinates seems unlikely, and
-+ * implicitly syncing them would break bin/render parallelism. If we want to
-+ * fix that, we should introduce a flag when VS texturing has been used in the
-+ * binning stage, or a set of flags for which BOs are sampled during binning.
-+ */
-+static int
-+v3d_add_implicit_fences(struct v3d_job *job, struct v3d_bo *bo)
-+{
-+ int i, ret, nr_fences;
-+ struct dma_fence **fences;
-+
-+ ret = reservation_object_get_fences_rcu(bo->resv, NULL,
-+ &nr_fences, &fences);
-+ if (ret || !nr_fences)
-+ return ret;
-+
-+ for (i = 0; i < nr_fences; i++) {
-+ ret = v3d_add_dep(job, fences[i]);
-+ if (ret)
-+ break;
-+ }
-+
-+ /* Free any remaining fences after error. */
-+ for (; i < nr_fences; i++)
-+ dma_fence_put(fences[i]);
-+ kfree(fences);
-+
-+ return ret;
-+}
-+
- /* Takes the reservation lock on all the BOs being referenced, so that
- * at queue submit time we can update the reservations.
- *
-@@ -226,10 +291,11 @@ v3d_unlock_bo_reservations(struct v3d_bo
- * to v3d, so we don't attach dma-buf fences to them.
- */
- static int
--v3d_lock_bo_reservations(struct v3d_bo **bos,
-- int bo_count,
-+v3d_lock_bo_reservations(struct v3d_job *job,
- struct ww_acquire_ctx *acquire_ctx)
- {
-+ struct v3d_bo **bos = job->bo;
-+ int bo_count = job->bo_count;
- int contended_lock = -1;
- int i, ret;
-
-@@ -281,6 +347,13 @@ retry:
- * before we commit the CL to the hardware.
- */
- for (i = 0; i < bo_count; i++) {
-+ ret = v3d_add_implicit_fences(job, bos[i]);
-+ if (ret) {
-+ v3d_unlock_bo_reservations(bos, bo_count,
-+ acquire_ctx);
-+ return ret;
-+ }
-+
- ret = reservation_object_reserve_shared(bos[i]->resv);
- if (ret) {
- v3d_unlock_bo_reservations(bos, bo_count,
-@@ -383,7 +456,10 @@ v3d_job_free(struct kref *ref)
- }
- kvfree(job->bo);
-
-- dma_fence_put(job->in_fence);
-+ for (i = 0; i < job->deps_count; i++)
-+ dma_fence_put(job->deps[i]);
-+ kfree(job->deps);
-+
- dma_fence_put(job->irq_fence);
- dma_fence_put(job->done_fence);
-
-@@ -464,15 +540,20 @@ v3d_job_init(struct v3d_dev *v3d, struct
- struct v3d_job *job, void (*free)(struct kref *ref),
- u32 in_sync)
- {
-+ struct dma_fence *in_fence = NULL;
- int ret;
-
- job->v3d = v3d;
- job->free = free;
-
-- ret = drm_syncobj_find_fence(file_priv, in_sync, 0, &job->in_fence);
-+ ret = drm_syncobj_find_fence(file_priv, in_sync, 0, &in_fence);
- if (ret == -EINVAL)
- return ret;
-
-+ ret = v3d_add_dep(job, in_fence);
-+ if (ret)
-+ return ret;
-+
- kref_init(&job->refcount);
-
- return 0;
-@@ -590,8 +671,7 @@ v3d_submit_cl_ioctl(struct drm_device *d
- if (ret)
- goto fail;
-
-- ret = v3d_lock_bo_reservations(render->base.bo, render->base.bo_count,
-- &acquire_ctx);
-+ ret = v3d_lock_bo_reservations(&render->base, &acquire_ctx);
- if (ret)
- goto fail;
-
-@@ -601,7 +681,8 @@ v3d_submit_cl_ioctl(struct drm_device *d
- if (ret)
- goto fail_unreserve;
-
-- render->bin_done_fence = dma_fence_get(bin->base.done_fence);
-+ ret = v3d_add_dep(&render->base,
-+ dma_fence_get(bin->base.done_fence));
- }
-
- ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);
-@@ -692,8 +773,7 @@ v3d_submit_tfu_ioctl(struct drm_device *
- }
- spin_unlock(&file_priv->table_lock);
-
-- ret = v3d_lock_bo_reservations(job->base.bo, job->base.bo_count,
-- &acquire_ctx);
-+ ret = v3d_lock_bo_reservations(&job->base, &acquire_ctx);
- if (ret)
- goto fail;
-
---- a/drivers/gpu/drm/v3d/v3d_sched.c
-+++ b/drivers/gpu/drm/v3d/v3d_sched.c
-@@ -67,47 +67,10 @@ v3d_job_dependency(struct drm_sched_job
- struct drm_sched_entity *s_entity)
- {
- struct v3d_job *job = to_v3d_job(sched_job);
-- struct dma_fence *fence;
--
-- fence = job->in_fence;
-- if (fence) {
-- job->in_fence = NULL;
-- return fence;
-- }
--
-- return NULL;
--}
-
--/**
-- * Returns the fences that the render job depends on, one by one.
-- * v3d_job_run() won't be called until all of them have been signaled.
-- */
--static struct dma_fence *
--v3d_render_job_dependency(struct drm_sched_job *sched_job,
-- struct drm_sched_entity *s_entity)
--{
-- struct v3d_render_job *job = to_render_job(sched_job);
-- struct dma_fence *fence;
--
-- fence = v3d_job_dependency(sched_job, s_entity);
-- if (fence)
-- return fence;
--
-- /* If we had a bin job, the render job definitely depends on
-- * it. We first have to wait for bin to be scheduled, so that
-- * its done_fence is created.
-- */
-- fence = job->bin_done_fence;
-- if (fence) {
-- job->bin_done_fence = NULL;
-- return fence;
-- }
--
-- /* XXX: Wait on a fence for switching the GMP if necessary,
-- * and then do so.
-- */
--
-- return fence;
-+ if (!job->deps_count)
-+ return NULL;
-+ return job->deps[--job->deps_count];
- }
-
- static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
-@@ -329,7 +292,7 @@ static const struct drm_sched_backend_op
- };
-
- static const struct drm_sched_backend_ops v3d_render_sched_ops = {
-- .dependency = v3d_render_job_dependency,
-+ .dependency = v3d_job_dependency,
- .run_job = v3d_render_job_run,
- .timedout_job = v3d_render_job_timedout,
- .free_job = v3d_job_free,
--- /dev/null
+From 347a871c771ab3682febed0cc5011618234c2b9e Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 2 Apr 2019 13:29:00 -0700
+Subject: [PATCH 593/725] drm/vc4: Fix vblank timestamping for firmwarekms.
+
+The core doesn't expect a false return from the scanoutpos function in
+normal usage, so we were doing the precise vblank timestamping path
+and thus "immediate" vblank disables (even though firmwarekms can't
+actually disable vblanks interrupts, sigh), and the kernel would get
+confused when getting timestamp info when also turning vblanks back
+on.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/vc4/vc4_crtc.c | 3 ---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 ++++++
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_crtc.c
++++ b/drivers/gpu/drm/vc4/vc4_crtc.c
+@@ -133,9 +133,6 @@ bool vc4_crtc_get_scanoutpos(struct drm_
+ int vblank_lines;
+ bool ret = false;
+
+- if (vc4->firmware_kms)
+- return 0;
+-
+ /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */
+
+ /* Get optional system timestamp before query. */
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -673,6 +673,12 @@ static int vc4_fkms_bind(struct device *
+
+ vc4->firmware_kms = true;
+
++ /* firmware kms doesn't have precise a scanoutpos implementation, so
++ * we can't do the precise vblank timestamp mode.
++ */
++ drm->driver->get_scanout_position = NULL;
++ drm->driver->get_vblank_timestamp = NULL;
++
+ vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
+ if (!vc4_crtc)
+ return -ENOMEM;
+++ /dev/null
-From a7b923e660e71a2d2b13a7aac36f11b9dcec9295 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 28 Mar 2019 11:58:51 -0700
-Subject: [PATCH 594/703] drm/vc4: Fix synchronization firmwarekms against GL
- rendering.
-
-We would present the framebuffer immediately without waiting for
-rendering to finish first, resulting in stuttering and flickering as a
-window was dragged around when the GPU was busy enough to not just win
-the race.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -15,6 +15,7 @@
- */
-
- #include "drm/drm_atomic_helper.h"
-+#include "drm/drm_gem_framebuffer_helper.h"
- #include "drm/drm_plane_helper.h"
- #include "drm/drm_crtc_helper.h"
- #include "drm/drm_fourcc.h"
-@@ -291,7 +292,7 @@ static const struct drm_plane_funcs vc4_
- };
-
- static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = {
-- .prepare_fb = NULL,
-+ .prepare_fb = drm_gem_fb_prepare_fb,
- .cleanup_fb = NULL,
- .atomic_check = vc4_plane_atomic_check,
- .atomic_update = vc4_primary_plane_atomic_update,
-@@ -299,7 +300,7 @@ static const struct drm_plane_helper_fun
- };
-
- static const struct drm_plane_helper_funcs vc4_cursor_plane_helper_funcs = {
-- .prepare_fb = NULL,
-+ .prepare_fb = drm_gem_fb_prepare_fb,
- .cleanup_fb = NULL,
- .atomic_check = vc4_plane_atomic_check,
- .atomic_update = vc4_cursor_plane_atomic_update,
--- /dev/null
+From 55e1b4a94b6ea98ad4c170b79b30e2ed39855535 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 26 Mar 2019 14:43:06 +0000
+Subject: [PATCH 594/725] gpu: vc4-fkms: Switch to the newer mailbox frame
+ buffer API.
+
+The old mailbox FB API was ideally deprecated but still used by
+the FKMS driver.
+Update to the newer API.
+
+NB This needs current firmware that accepts ARM allocated buffers
+through the newer API.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 109 +++++++++++----------
+ include/soc/bcm2835/raspberrypi-firmware.h | 10 ++
+ 2 files changed, 67 insertions(+), 52 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -28,6 +28,25 @@
+ #include "vc4_regs.h"
+ #include <soc/bcm2835/raspberrypi-firmware.h>
+
++struct fb_alloc_tags {
++ struct rpi_firmware_property_tag_header tag1;
++ u32 xres, yres;
++ struct rpi_firmware_property_tag_header tag2;
++ u32 xres_virtual, yres_virtual;
++ struct rpi_firmware_property_tag_header tag3;
++ u32 bpp;
++ struct rpi_firmware_property_tag_header tag4;
++ u32 xoffset, yoffset;
++ struct rpi_firmware_property_tag_header tag5;
++ u32 base, screen_size;
++ struct rpi_firmware_property_tag_header tag6;
++ u32 pitch;
++ struct rpi_firmware_property_tag_header tag7;
++ u32 alpha_mode;
++ struct rpi_firmware_property_tag_header tag8;
++ u32 layer;
++};
++
+ /* The firmware delivers a vblank interrupt to us through the SMI
+ * hardware, which has only this one register.
+ */
+@@ -121,45 +140,39 @@ static void vc4_primary_plane_atomic_upd
+ 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 format = fb->format->format;
++ struct fb_alloc_tags fbinfo = {
++ .tag1 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT,
++ 8, 0, },
++ .xres = state->crtc_w,
++ .yres = state->crtc_h,
++ .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT,
++ 8, 0, },
++ .xres_virtual = state->crtc_w,
++ .yres_virtual = state->crtc_h,
++ .tag3 = { RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, 4, 0 },
++ .bpp = 32,
++ .tag4 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, 8, 0 },
++ .xoffset = 0,
++ .yoffset = 0,
++ .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
++ .base = bo->paddr + fb->offsets[0],
++ .screen_size = state->crtc_w * state->crtc_h * 4,
++ .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
++ .pitch = fb->pitches[0],
++ .tag7 = { RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE, 4, 0 },
++ .alpha_mode = format == DRM_FORMAT_ARGB8888 ? 0 : 2,
++ .tag8 = { RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER, 4, 0 },
++ .layer = -127,
++ };
+ u32 bpp = 32;
+ int ret;
+
+- 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];
+-
+ if (fb->modifier == DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED)
+- fbinfo->bpp |= BIT(31);
+-
+- /* 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]);
+- }
++ fbinfo.bpp |= BIT(31);
+
+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%d\n",
+ plane->base.id, plane->name,
+@@ -168,14 +181,13 @@ static void vc4_primary_plane_atomic_upd
+ bpp,
+ state->crtc_x,
+ state->crtc_y,
+- &fbinfo->base,
++ &fbinfo.base,
+ 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]);
++ ret = rpi_firmware_property_list(vc4->firmware, &fbinfo,
++ sizeof(fbinfo));
++ WARN_ON_ONCE(fbinfo.pitch != fb->pitches[0]);
++ WARN_ON_ONCE(fbinfo.base != bo->paddr + fb->offsets[0]);
+
+ /* If the CRTC is on (or going to be on) and we're enabled,
+ * then unblank. Otherwise, stay blank until CRTC enable.
+@@ -332,10 +344,10 @@ static const struct drm_plane_helper_fun
+ static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
+ enum drm_plane_type type)
+ {
++ /* Primary and cursor planes only */
+ struct drm_plane *plane = NULL;
+ struct vc4_fkms_plane *vc4_plane;
+- u32 xrgb8888 = DRM_FORMAT_XRGB8888;
+- u32 argb8888 = DRM_FORMAT_ARGB8888;
++ u32 formats[] = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888};
+ int ret = 0;
+ bool primary = (type == DRM_PLANE_TYPE_PRIMARY);
+ static const uint64_t modifiers[] = {
+@@ -357,22 +369,15 @@ static struct drm_plane *vc4_fkms_plane_
+ plane = &vc4_plane->base;
+ ret = drm_universal_plane_init(dev, plane, 0xff,
+ &vc4_plane_funcs,
+- primary ? &xrgb8888 : &argb8888, 1,
+- modifiers,
++ formats, primary ? 2 : 1, modifiers,
+ type, primary ? "primary" : "cursor");
+
+- 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));
+-
++ if (type == DRM_PLANE_TYPE_PRIMARY)
+ drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs);
+- } else {
++ else
+ drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs);
+- }
++
++ drm_plane_create_alpha_property(plane);
+
+ return plane;
+ fail:
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -111,9 +111,15 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b,
++ RPI_FIRMWARE_FRAMEBUFFER_GET_LAYER = 0x0004000c,
++ RPI_FIRMWARE_FRAMEBUFFER_GET_TRANSFORM = 0x0004000d,
++ RPI_FIRMWARE_FRAMEBUFFER_GET_VSYNC = 0x0004000e,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
+ RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001,
++ RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM = 0x00048013,
++ RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS = 0x00040013,
++ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS = 0x00040014,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_DEPTH = 0x00044005,
+@@ -122,6 +128,8 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE = 0x0004400b,
++ RPI_FIRMWARE_FRAMEBUFFER_TEST_LAYER = 0x0004400c,
++ RPI_FIRMWARE_FRAMEBUFFER_TEST_TRANSFORM = 0x0004400d,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_VSYNC = 0x0004400e,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004,
+@@ -134,6 +142,8 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
++ RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER = 0x0004800c,
++ RPI_FIRMWARE_FRAMEBUFFER_SET_TRANSFORM = 0x0004800d,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f,
+
+ RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
--- /dev/null
+From 58da9f30e54c4fe6b3ca17afad492d3c156a1503 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 27 Mar 2019 17:45:01 +0000
+Subject: [PATCH 595/725] drm: vc4: Add an overlay plane to vc4-firmware-kms
+
+This uses a new API that is exposed via the mailbox service
+to stick an element straight on the screen using DispmanX.
+
+The primary and cursor planes have also been switched to using
+the new plane API, and it supports layering based on the DRM
+zpos parameter.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 518 ++++++++++++++-------
+ drivers/gpu/drm/vc4/vc4_kms.c | 1 +
+ drivers/gpu/drm/vc4/vc_image_types.h | 143 ++++++
+ include/soc/bcm2835/raspberrypi-firmware.h | 2 +
+ 4 files changed, 495 insertions(+), 169 deletions(-)
+ create mode 100644 drivers/gpu/drm/vc4/vc_image_types.h
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -26,8 +26,46 @@
+ #include "linux/of_device.h"
+ #include "vc4_drv.h"
+ #include "vc4_regs.h"
++#include "vc_image_types.h"
+ #include <soc/bcm2835/raspberrypi-firmware.h>
+
++struct set_plane {
++ u8 display;
++ u8 plane_id;
++ u8 vc_image_type;
++ s8 layer;
++
++ u16 width;
++ u16 height;
++
++ u16 pitch;
++ u16 vpitch;
++
++ u32 src_x; /* 16p16 */
++ u32 src_y; /* 16p16 */
++
++ u32 src_w; /* 16p16 */
++ u32 src_h; /* 16p16 */
++
++ s16 dst_x;
++ s16 dst_y;
++
++ u16 dst_w;
++ u16 dst_h;
++
++ u8 alpha;
++ u8 num_planes;
++ u8 is_vu;
++ u8 padding;
++
++ u32 planes[4]; /* DMA address of each plane */
++};
++
++struct mailbox_set_plane {
++ struct rpi_firmware_property_tag_header tag;
++ struct set_plane plane;
++};
++
+ struct fb_alloc_tags {
+ struct rpi_firmware_property_tag_header tag1;
+ u32 xres, yres;
+@@ -47,6 +85,79 @@ struct fb_alloc_tags {
+ u32 layer;
+ };
+
++static const struct vc_image_format {
++ u32 drm; /* DRM_FORMAT_* */
++ u32 vc_image; /* VC_IMAGE_* */
++ u32 is_vu;
++} vc_image_formats[] = {
++ {
++ .drm = DRM_FORMAT_XRGB8888,
++ .vc_image = VC_IMAGE_XRGB8888,
++ },
++ {
++ .drm = DRM_FORMAT_ARGB8888,
++ .vc_image = VC_IMAGE_ARGB8888,
++ },
++/*
++ * FIXME: Need to resolve which DRM format goes to which vc_image format
++ * for the remaining RGBA and RGBX formats.
++ * {
++ * .drm = DRM_FORMAT_ABGR8888,
++ * .vc_image = VC_IMAGE_RGBA8888,
++ * },
++ * {
++ * .drm = DRM_FORMAT_XBGR8888,
++ * .vc_image = VC_IMAGE_RGBA8888,
++ * },
++ */
++ {
++ .drm = DRM_FORMAT_RGB565,
++ .vc_image = VC_IMAGE_RGB565,
++ },
++ {
++ .drm = DRM_FORMAT_RGB888,
++ .vc_image = VC_IMAGE_BGR888,
++ },
++ {
++ .drm = DRM_FORMAT_BGR888,
++ .vc_image = VC_IMAGE_RGB888,
++ },
++ {
++ .drm = DRM_FORMAT_YUV422,
++ .vc_image = VC_IMAGE_YUV422PLANAR,
++ },
++ {
++ .drm = DRM_FORMAT_YUV420,
++ .vc_image = VC_IMAGE_YUV420,
++ },
++ {
++ .drm = DRM_FORMAT_YVU420,
++ .vc_image = VC_IMAGE_YUV420,
++ .is_vu = 1,
++ },
++ {
++ .drm = DRM_FORMAT_NV12,
++ .vc_image = VC_IMAGE_YUV420SP,
++ },
++ {
++ .drm = DRM_FORMAT_NV21,
++ .vc_image = VC_IMAGE_YUV420SP,
++ .is_vu = 1,
++ },
++};
++
++static const struct vc_image_format *vc4_get_vc_image_fmt(u32 drm_format)
++{
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++) {
++ if (vc_image_formats[i].drm == drm_format)
++ return &vc_image_formats[i];
++ }
++
++ return NULL;
++}
++
+ /* The firmware delivers a vblank interrupt to us through the SMI
+ * hardware, which has only this one register.
+ */
+@@ -113,6 +224,7 @@ struct vc4_fkms_plane {
+ struct fbinfo_s *fbinfo;
+ dma_addr_t fbinfo_bus_addr;
+ u32 pitch;
++ struct mailbox_set_plane mb;
+ };
+
+ static inline struct vc4_fkms_plane *to_vc4_fkms_plane(struct drm_plane *plane)
+@@ -120,165 +232,183 @@ static inline struct vc4_fkms_plane *to_
+ return (struct vc4_fkms_plane *)plane;
+ }
+
+-/* Turns the display on/off. */
+-static int vc4_plane_set_primary_blank(struct drm_plane *plane, bool blank)
++static int vc4_plane_set_blank(struct drm_plane *plane, bool blank)
+ {
+ struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
++ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
++ struct mailbox_set_plane blank_mb = {
++ .tag = { RPI_FIRMWARE_SET_PLANE, sizeof(struct set_plane), 0 },
++ .plane = {
++ .display = vc4_plane->mb.plane.display,
++ .plane_id = vc4_plane->mb.plane.plane_id,
++ }
++ };
++ int ret;
+
+- u32 packet = blank;
+-
+- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary plane %s",
++ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] overlay plane %s",
+ plane->base.id, plane->name,
+ blank ? "blank" : "unblank");
+
+- return rpi_firmware_property(vc4->firmware,
+- RPI_FIRMWARE_FRAMEBUFFER_BLANK,
+- &packet, sizeof(packet));
++ if (blank)
++ ret = rpi_firmware_property_list(vc4->firmware, &blank_mb,
++ sizeof(blank_mb));
++ else
++ ret = rpi_firmware_property_list(vc4->firmware, &vc4_plane->mb,
++ sizeof(vc4_plane->mb));
++
++ WARN_ONCE(ret, "%s: firmware call failed. Please update your firmware",
++ __func__);
++ return ret;
+ }
+
+-static void vc4_primary_plane_atomic_update(struct drm_plane *plane,
+- struct drm_plane_state *old_state)
++static void vc4_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);
+- u32 format = fb->format->format;
+- struct fb_alloc_tags fbinfo = {
+- .tag1 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT,
+- 8, 0, },
+- .xres = state->crtc_w,
+- .yres = state->crtc_h,
+- .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT,
+- 8, 0, },
+- .xres_virtual = state->crtc_w,
+- .yres_virtual = state->crtc_h,
+- .tag3 = { RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, 4, 0 },
+- .bpp = 32,
+- .tag4 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, 8, 0 },
+- .xoffset = 0,
+- .yoffset = 0,
+- .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
+- .base = bo->paddr + fb->offsets[0],
+- .screen_size = state->crtc_w * state->crtc_h * 4,
+- .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
+- .pitch = fb->pitches[0],
+- .tag7 = { RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE, 4, 0 },
+- .alpha_mode = format == DRM_FORMAT_ARGB8888 ? 0 : 2,
+- .tag8 = { RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER, 4, 0 },
+- .layer = -127,
+- };
+- u32 bpp = 32;
+- int ret;
++ const struct drm_format_info *drm_fmt = fb->format;
++ const struct vc_image_format *vc_fmt =
++ vc4_get_vc_image_fmt(drm_fmt->format);
++ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
++ struct mailbox_set_plane *mb = &vc4_plane->mb;
++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
++ int num_planes = fb->format->num_planes;
++ struct drm_display_mode *mode = &state->crtc->mode;
+
+- if (fb->modifier == DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED)
+- fbinfo.bpp |= BIT(31);
++ mb->plane.vc_image_type = vc_fmt->vc_image;
++ mb->plane.width = fb->width;
++ mb->plane.height = fb->height;
++ mb->plane.pitch = fb->pitches[0];
++ mb->plane.src_w = state->src_w;
++ mb->plane.src_h = state->src_h;
++ mb->plane.src_x = state->src_x;
++ mb->plane.src_y = state->src_y;
++ mb->plane.dst_w = state->crtc_w;
++ mb->plane.dst_h = state->crtc_h;
++ mb->plane.dst_x = state->crtc_x;
++ mb->plane.dst_y = state->crtc_y;
++ mb->plane.alpha = state->alpha >> 8;
++ mb->plane.layer = state->normalized_zpos ?
++ state->normalized_zpos : -127;
++ mb->plane.num_planes = num_planes;
++ mb->plane.is_vu = vc_fmt->is_vu;
++ mb->plane.planes[0] = bo->paddr + fb->offsets[0];
+
+- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%d\n",
++ /* FIXME: If the dest rect goes off screen then clip the src rect so we
++ * don't have off-screen pixels.
++ */
++ if (plane->type == DRM_PLANE_TYPE_CURSOR) {
++ /* There is no scaling on the cursor plane, therefore the calcs
++ * to alter the source crop as the cursor goes off the screen
++ * are simple.
++ */
++ if (mb->plane.dst_x + mb->plane.dst_w > mode->hdisplay) {
++ mb->plane.dst_w = mode->hdisplay - mb->plane.dst_x;
++ mb->plane.src_w = (mode->hdisplay - mb->plane.dst_x)
++ << 16;
++ }
++ if (mb->plane.dst_y + mb->plane.dst_h > mode->vdisplay) {
++ mb->plane.dst_h = mode->vdisplay - mb->plane.dst_y;
++ mb->plane.src_h = (mode->vdisplay - mb->plane.dst_y)
++ << 16;
++ }
++ }
++
++ if (num_planes > 1) {
++ /* Assume this must be YUV */
++ /* Makes assumptions on the stride for the chroma planes as we
++ * can't easily plumb in non-standard pitches.
++ */
++ mb->plane.planes[1] = bo->paddr + fb->offsets[1];
++ if (num_planes > 2)
++ mb->plane.planes[2] = bo->paddr + fb->offsets[2];
++ else
++ mb->plane.planes[2] = 0;
++
++ /* Special case the YUV420 with U and V as line interleaved
++ * planes as we have special handling for that case.
++ */
++ if (num_planes == 3 &&
++ (fb->offsets[2] - fb->offsets[1]) == fb->pitches[1])
++ mb->plane.vc_image_type = VC_IMAGE_YUV420_S;
++ } else {
++ mb->plane.planes[1] = 0;
++ mb->plane.planes[2] = 0;
++ }
++ mb->plane.planes[3] = 0;
++
++ switch (fb->modifier) {
++ case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
++ switch (mb->plane.vc_image_type) {
++ case VC_IMAGE_RGBX32:
++ mb->plane.vc_image_type = VC_IMAGE_TF_RGBX32;
++ break;
++ case VC_IMAGE_RGBA32:
++ mb->plane.vc_image_type = VC_IMAGE_TF_RGBA32;
++ break;
++ case VC_IMAGE_RGB565:
++ mb->plane.vc_image_type = VC_IMAGE_TF_RGB565;
++ break;
++ }
++ break;
++ case DRM_FORMAT_MOD_BROADCOM_SAND128:
++ mb->plane.vc_image_type = VC_IMAGE_YUV_UV;
++ mb->plane.pitch = fourcc_mod_broadcom_param(fb->modifier);
++ break;
++ }
++
++ if (vc4_crtc) {
++ mb->plane.dst_x += vc4_crtc->overscan[0];
++ mb->plane.dst_y += vc4_crtc->overscan[1];
++ }
++
++ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane update %dx%d@%d +dst(%d,%d, %d,%d) +src(%d,%d, %d,%d) 0x%08x/%08x/%08x/%d, alpha %u zpos %u\n",
+ plane->base.id, plane->name,
+- state->crtc_w,
+- state->crtc_h,
+- bpp,
++ mb->plane.width,
++ mb->plane.height,
++ mb->plane.vc_image_type,
+ state->crtc_x,
+ state->crtc_y,
+- &fbinfo.base,
+- fb->pitches[0]);
+-
+- ret = rpi_firmware_property_list(vc4->firmware, &fbinfo,
+- sizeof(fbinfo));
+- WARN_ON_ONCE(fbinfo.pitch != fb->pitches[0]);
+- WARN_ON_ONCE(fbinfo.base != bo->paddr + fb->offsets[0]);
+-
+- /* If the CRTC is on (or going to be on) and we're enabled,
++ state->crtc_w,
++ state->crtc_h,
++ mb->plane.src_x,
++ mb->plane.src_y,
++ mb->plane.src_w,
++ mb->plane.src_h,
++ mb->plane.planes[0],
++ mb->plane.planes[1],
++ mb->plane.planes[2],
++ fb->pitches[0],
++ state->alpha,
++ state->normalized_zpos);
++
++ /*
++ * Do NOT set now, as we haven't checked if the crtc is active or not.
++ * Set from vc4_plane_set_blank instead.
++ *
++ * If the CRTC is on (or going to be on) and we're enabled,
+ * then unblank. Otherwise, stay blank until CRTC enable.
+- */
++ */
+ if (state->crtc->state->active)
+- vc4_plane_set_primary_blank(plane, false);
++ vc4_plane_set_blank(plane, false);
+ }
+
+-static void vc4_primary_plane_atomic_disable(struct drm_plane *plane,
+- struct drm_plane_state *old_state)
++static void vc4_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 vc4_dev *vc4 = to_vc4_dev(plane->dev);
+ struct drm_plane_state *state = plane->state;
+- struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
+- struct drm_framebuffer *fb = state->fb;
+- struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
+- dma_addr_t addr = bo->paddr + fb->offsets[0];
+- int ret;
+- u32 packet_state[] = {
+- state->crtc->state->active,
+- state->crtc_x,
+- state->crtc_y,
+- 0
+- };
+- WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4);
++ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
+
+- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%pad/%d)",
++ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane disable %dx%d@%d +%d,%d\n",
+ plane->base.id, plane->name,
+ state->crtc_w,
+ state->crtc_h,
++ vc4_plane->mb.plane.vc_image_type,
+ state->crtc_x,
+- state->crtc_y,
+- &addr,
+- fb->pitches[0]);
+-
+- /* add on the top/left offsets when overscan is active */
+- if (vc4_crtc) {
+- packet_state[1] += vc4_crtc->overscan[0];
+- packet_state[2] += vc4_crtc->overscan[1];
+- }
+-
+- 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]);
+-
+- /* Note: When the cursor contents change, the modesetting
+- * driver calls drm_mode_cursor_univeral() with
+- * DRM_MODE_CURSOR_BO, which means a new fb will be allocated.
+- */
+- if (!old_state ||
+- state->crtc_w != old_state->crtc_w ||
+- state->crtc_h != old_state->crtc_h ||
+- fb != old_state->fb) {
+- u32 packet_info[] = { state->crtc_w, state->crtc_h,
+- 0, /* unused */
+- addr,
+- 0, 0, /* hotx, hoty */};
+-
+- 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;
+-
+- 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,
+- sizeof(packet_state));
+- if (ret || packet_state[0] != 0)
+- DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]);
++ state->crtc_y);
++ vc4_plane_set_blank(plane, true);
+ }
+
+ static int vc4_plane_atomic_check(struct drm_plane *plane,
+@@ -301,6 +431,7 @@ static bool vc4_fkms_format_mod_supporte
+ switch (format) {
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_ARGB8888:
++ case DRM_FORMAT_RGB565:
+ switch (modifier) {
+ case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
+ case DRM_FORMAT_MOD_LINEAR:
+@@ -309,8 +440,22 @@ static bool vc4_fkms_format_mod_supporte
+ default:
+ return false;
+ }
++ case DRM_FORMAT_NV12:
++ case DRM_FORMAT_NV21:
++ switch (fourcc_mod_broadcom_mod(modifier)) {
++ case DRM_FORMAT_MOD_LINEAR:
++ case DRM_FORMAT_MOD_BROADCOM_SAND128:
++ return true;
++ default:
++ return false;
++ }
++ case DRM_FORMAT_RGB888:
++ case DRM_FORMAT_BGR888:
++ case DRM_FORMAT_YUV422:
++ case DRM_FORMAT_YUV420:
++ case DRM_FORMAT_YVU420:
+ default:
+- return false;
++ return (modifier == DRM_FORMAT_MOD_LINEAR);
+ }
+ }
+
+@@ -325,31 +470,24 @@ static const struct drm_plane_funcs vc4_
+ .format_mod_supported = vc4_fkms_format_mod_supported,
+ };
+
+-static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = {
+- .prepare_fb = drm_gem_fb_prepare_fb,
+- .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 = {
++static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = {
+ .prepare_fb = drm_gem_fb_prepare_fb,
+ .cleanup_fb = NULL,
+ .atomic_check = vc4_plane_atomic_check,
+- .atomic_update = vc4_cursor_plane_atomic_update,
+- .atomic_disable = vc4_cursor_plane_atomic_disable,
++ .atomic_update = vc4_plane_atomic_update,
++ .atomic_disable = vc4_plane_atomic_disable,
+ };
+
+ static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
+- enum drm_plane_type type)
++ enum drm_plane_type type,
++ u8 plane_id)
+ {
+- /* Primary and cursor planes only */
+ struct drm_plane *plane = NULL;
+ struct vc4_fkms_plane *vc4_plane;
+- u32 formats[] = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888};
++ u32 formats[ARRAY_SIZE(vc_image_formats)];
++ unsigned int default_zpos;
++ u32 num_formats = 0;
+ int ret = 0;
+- bool primary = (type == DRM_PLANE_TYPE_PRIMARY);
+ static const uint64_t modifiers[] = {
+ DRM_FORMAT_MOD_LINEAR,
+ /* VC4_T_TILED should come after linear, because we
+@@ -358,6 +496,7 @@ static struct drm_plane *vc4_fkms_plane_
+ DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
+ DRM_FORMAT_MOD_INVALID,
+ };
++ int i;
+
+ vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
+ GFP_KERNEL);
+@@ -366,19 +505,48 @@ static struct drm_plane *vc4_fkms_plane_
+ goto fail;
+ }
+
++ for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++)
++ formats[num_formats++] = vc_image_formats[i].drm;
++
+ plane = &vc4_plane->base;
+ ret = drm_universal_plane_init(dev, plane, 0xff,
+ &vc4_plane_funcs,
+- formats, primary ? 2 : 1, modifiers,
+- type, primary ? "primary" : "cursor");
++ formats, num_formats, modifiers,
++ type, NULL);
+
+- if (type == DRM_PLANE_TYPE_PRIMARY)
+- drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs);
+- else
+- drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs);
++ drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
+
+ drm_plane_create_alpha_property(plane);
+
++ /*
++ * Default frame buffer setup is with FB on -127, and raspistill etc
++ * tend to drop overlays on layer 2. Cursor plane was on layer +127.
++ *
++ * For F-KMS the mailbox call allows for a s8.
++ * Remap zpos 0 to -127 for the background layer, but leave all the
++ * other layers as requested by KMS.
++ */
++ switch (type) {
++ case DRM_PLANE_TYPE_PRIMARY:
++ default_zpos = 0;
++ break;
++ case DRM_PLANE_TYPE_OVERLAY:
++ default_zpos = 1;
++ break;
++ case DRM_PLANE_TYPE_CURSOR:
++ default_zpos = 2;
++ break;
++ }
++ drm_plane_create_zpos_property(plane, default_zpos, 0, 127);
++
++ /* Prepare the static elements of the mailbox structure */
++ vc4_plane->mb.tag.tag = RPI_FIRMWARE_SET_PLANE;
++ vc4_plane->mb.tag.buf_size = sizeof(struct set_plane);
++ vc4_plane->mb.tag.req_resp_size = 0;
++ vc4_plane->mb.plane.display = 0;
++ vc4_plane->mb.plane.plane_id = plane_id;
++ vc4_plane->mb.plane.layer = default_zpos ? default_zpos : -127;
++
+ return plane;
+ fail:
+ if (plane)
+@@ -400,19 +568,23 @@ static void vc4_crtc_disable(struct drm_
+ * whether anything scans out at all, but the firmware doesn't
+ * give us a CRTC-level control for that.
+ */
+- vc4_cursor_plane_atomic_disable(crtc->cursor, crtc->cursor->state);
+- vc4_plane_set_primary_blank(crtc->primary, true);
++
++ vc4_plane_atomic_disable(crtc->cursor, crtc->cursor->state);
++ vc4_plane_atomic_disable(crtc->primary, crtc->primary->state);
++
++ /* FIXME: Disable overlay planes */
+ }
+
+ static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+ {
+ /* Unblank the planes (if they're supposed to be displayed). */
++
+ if (crtc->primary->state->fb)
+- vc4_plane_set_primary_blank(crtc->primary, false);
+- if (crtc->cursor->state->fb) {
+- vc4_cursor_plane_atomic_update(crtc->cursor,
+- crtc->cursor->state);
+- }
++ vc4_plane_set_blank(crtc->primary, false);
++ if (crtc->cursor->state->fb)
++ vc4_plane_set_blank(crtc->cursor, crtc->cursor->state);
++
++ /* FIXME: Enable overlay planes */
+ }
+
+ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
+@@ -672,8 +844,10 @@ static int vc4_fkms_bind(struct device *
+ 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 drm_plane *primary_plane, *overlay_plane, *cursor_plane;
++ struct drm_plane *destroy_plane, *temp;
+ struct device_node *firmware_node;
++ u32 blank = 1;
+ int ret;
+
+ vc4->firmware_kms = true;
+@@ -702,20 +876,26 @@ static int vc4_fkms_bind(struct device *
+ 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);
++ /* Blank the firmware provided framebuffer */
++ rpi_firmware_property(vc4->firmware,
++ RPI_FIRMWARE_FRAMEBUFFER_BLANK,
++ &blank, sizeof(blank));
++
++ primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY, 0);
+ 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);
++ overlay_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_OVERLAY, 1);
++ if (IS_ERR(overlay_plane)) {
++ dev_err(dev, "failed to construct overlay plane\n");
++ ret = PTR_ERR(overlay_plane);
++ goto err;
++ }
++
++ cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR, 2);
+ if (IS_ERR(cursor_plane)) {
+ dev_err(dev, "failed to construct cursor plane\n");
+ ret = PTR_ERR(cursor_plane);
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -435,6 +435,7 @@ int vc4_kms_load(struct drm_device *dev)
+ dev->mode_config.preferred_depth = 24;
+ dev->mode_config.async_page_flip = true;
+ dev->mode_config.allow_fb_modifiers = true;
++ dev->mode_config.normalize_zpos = true;
+
+ drm_modeset_lock_init(&vc4->ctm_state_lock);
+
+--- /dev/null
++++ b/drivers/gpu/drm/vc4/vc_image_types.h
+@@ -0,0 +1,143 @@
++
++/*
++ * Copyright (c) 2012, Broadcom Europe Ltd
++ *
++ * Values taken from vc_image_types.h released by Broadcom at
++ * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h
++ *
++ * 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.
++ */
++
++enum {
++ VC_IMAGE_MIN = 0, //bounds for error checking
++
++ VC_IMAGE_RGB565 = 1,
++ VC_IMAGE_1BPP,
++ VC_IMAGE_YUV420,
++ VC_IMAGE_48BPP,
++ VC_IMAGE_RGB888,
++ VC_IMAGE_8BPP,
++ /* 4bpp palettised image */
++ VC_IMAGE_4BPP,
++ /* A separated format of 16 colour/light shorts followed by 16 z
++ * values
++ */
++ VC_IMAGE_3D32,
++ /* 16 colours followed by 16 z values */
++ VC_IMAGE_3D32B,
++ /* A separated format of 16 material/colour/light shorts followed by
++ * 16 z values
++ */
++ VC_IMAGE_3D32MAT,
++ /* 32 bit format containing 18 bits of 6.6.6 RGB, 9 bits per short */
++ VC_IMAGE_RGB2X9,
++ /* 32-bit format holding 18 bits of 6.6.6 RGB */
++ VC_IMAGE_RGB666,
++ /* 4bpp palettised image with embedded palette */
++ VC_IMAGE_PAL4_OBSOLETE,
++ /* 8bpp palettised image with embedded palette */
++ VC_IMAGE_PAL8_OBSOLETE,
++ /* RGB888 with an alpha byte after each pixel */
++ VC_IMAGE_RGBA32,
++ /* a line of Y (32-byte padded), a line of U (16-byte padded), and a
++ * line of V (16-byte padded)
++ */
++ VC_IMAGE_YUV422,
++ /* RGB565 with a transparent patch */
++ VC_IMAGE_RGBA565,
++ /* Compressed (4444) version of RGBA32 */
++ VC_IMAGE_RGBA16,
++ /* VCIII codec format */
++ VC_IMAGE_YUV_UV,
++ /* VCIII T-format RGBA8888 */
++ VC_IMAGE_TF_RGBA32,
++ /* VCIII T-format RGBx8888 */
++ VC_IMAGE_TF_RGBX32,
++ /* VCIII T-format float */
++ VC_IMAGE_TF_FLOAT,
++ /* VCIII T-format RGBA4444 */
++ VC_IMAGE_TF_RGBA16,
++ /* VCIII T-format RGB5551 */
++ VC_IMAGE_TF_RGBA5551,
++ /* VCIII T-format RGB565 */
++ VC_IMAGE_TF_RGB565,
++ /* VCIII T-format 8-bit luma and 8-bit alpha */
++ VC_IMAGE_TF_YA88,
++ /* VCIII T-format 8 bit generic sample */
++ VC_IMAGE_TF_BYTE,
++ /* VCIII T-format 8-bit palette */
++ VC_IMAGE_TF_PAL8,
++ /* VCIII T-format 4-bit palette */
++ VC_IMAGE_TF_PAL4,
++ /* VCIII T-format Ericsson Texture Compressed */
++ VC_IMAGE_TF_ETC1,
++ /* RGB888 with R & B swapped */
++ VC_IMAGE_BGR888,
++ /* RGB888 with R & B swapped, but with no pitch, i.e. no padding after
++ * each row of pixels
++ */
++ VC_IMAGE_BGR888_NP,
++ /* Bayer image, extra defines which variant is being used */
++ VC_IMAGE_BAYER,
++ /* General wrapper for codec images e.g. JPEG from camera */
++ VC_IMAGE_CODEC,
++ /* VCIII codec format */
++ VC_IMAGE_YUV_UV32,
++ /* VCIII T-format 8-bit luma */
++ VC_IMAGE_TF_Y8,
++ /* VCIII T-format 8-bit alpha */
++ VC_IMAGE_TF_A8,
++ /* VCIII T-format 16-bit generic sample */
++ VC_IMAGE_TF_SHORT,
++ /* VCIII T-format 1bpp black/white */
++ VC_IMAGE_TF_1BPP,
++ VC_IMAGE_OPENGL,
++ /* VCIII-B0 HVS YUV 4:4:4 interleaved samples */
++ VC_IMAGE_YUV444I,
++ /* Y, U, & V planes separately (VC_IMAGE_YUV422 has them interleaved on
++ * a per line basis)
++ */
++ VC_IMAGE_YUV422PLANAR,
++ /* 32bpp with 8bit alpha at MS byte, with R, G, B (LS byte) */
++ VC_IMAGE_ARGB8888,
++ /* 32bpp with 8bit unused at MS byte, with R, G, B (LS byte) */
++ VC_IMAGE_XRGB8888,
++
++ /* interleaved 8 bit samples of Y, U, Y, V (4 flavours) */
++ VC_IMAGE_YUV422YUYV,
++ VC_IMAGE_YUV422YVYU,
++ VC_IMAGE_YUV422UYVY,
++ VC_IMAGE_YUV422VYUY,
++
++ /* 32bpp like RGBA32 but with unused alpha */
++ VC_IMAGE_RGBX32,
++ /* 32bpp, corresponding to RGBA with unused alpha */
++ VC_IMAGE_RGBX8888,
++ /* 32bpp, corresponding to BGRA with unused alpha */
++ VC_IMAGE_BGRX8888,
++
++ /* Y as a plane, then UV byte interleaved in plane with with same pitch,
++ * half height
++ */
++ VC_IMAGE_YUV420SP,
++
++ /* Y, U, & V planes separately 4:4:4 */
++ VC_IMAGE_YUV444PLANAR,
++
++ /* T-format 8-bit U - same as TF_Y8 buf from U plane */
++ VC_IMAGE_TF_U8,
++ /* T-format 8-bit U - same as TF_Y8 buf from V plane */
++ VC_IMAGE_TF_V8,
++
++ /* YUV4:2:0 planar, 16bit values */
++ VC_IMAGE_YUV420_16,
++ /* YUV4:2:0 codec format, 16bit values */
++ VC_IMAGE_YUV_UV_16,
++ /* YUV4:2:0 with U,V in side-by-side format */
++ VC_IMAGE_YUV420_S,
++
++ VC_IMAGE_MAX, /* bounds for error checking */
++ VC_IMAGE_FORCE_ENUM_16BIT = 0xffff,
++};
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -148,6 +148,8 @@ enum rpi_firmware_property_tag {
+
+ RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
+
++ RPI_FIRMWARE_SET_PLANE = 0x00048015,
++
+ RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
+ RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,
+ };
+++ /dev/null
-From 53fb5e2a9834ead04a432c266831e5fd77f96983 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Fri, 29 Mar 2019 12:04:36 -0700
-Subject: [PATCH 595/703] drm/vc4: Make sure that vblank waits work without v3d
- loaded.
-
-This flag exists to protect legacy drivers, but when vc4's v3d doesn't
-probe, it doesn't get set up by vc4_v3d.c's call of drm_irq_install.
-This resulted in applications running as fast as possible, and laggy
-performance from compton as it had to wait for the latest rendering by
-the application for its presentation.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_kms.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -422,6 +422,7 @@ int vc4_kms_load(struct drm_device *dev)
- /* Set support for vblank irq fast disable, before drm_vblank_init() */
- dev->vblank_disable_immediate = true;
-
-+ dev->irq_enabled = true;
- ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
- if (ret < 0) {
- dev_err(dev->dev, "failed to initialize vblank\n");
+++ /dev/null
-From 3d8b2b7adbec2ea7bf9012300c5e381cb60c270e Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 18 Mar 2019 16:38:32 -0700
-Subject: [PATCH 596/703] drm/vc4: Expose the format modifiers for firmware
- kms.
-
-This should technically not expose VC4_T_TILED on pi4. However, if we
-don't expose anything, then userspace will assume that display can
-handle whatever modifiers 3d can do (UIF on 2711). By exposing a
-list, that will get intersected with what 3D can do so that we get T
-tiling for display on 2710 and linear on 2711.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 33 +++++++++++++++++++++++++-
- 1 file changed, 32 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -281,6 +281,27 @@ static void vc4_plane_destroy(struct drm
- drm_plane_cleanup(plane);
- }
-
-+static bool vc4_fkms_format_mod_supported(struct drm_plane *plane,
-+ uint32_t format,
-+ uint64_t modifier)
-+{
-+ /* Support T_TILING for RGB formats only. */
-+ switch (format) {
-+ case DRM_FORMAT_XRGB8888:
-+ case DRM_FORMAT_ARGB8888:
-+ switch (modifier) {
-+ case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
-+ case DRM_FORMAT_MOD_LINEAR:
-+ case DRM_FORMAT_MOD_BROADCOM_UIF:
-+ return true;
-+ default:
-+ return false;
-+ }
-+ default:
-+ return false;
-+ }
-+}
-+
- static const struct drm_plane_funcs vc4_plane_funcs = {
- .update_plane = drm_atomic_helper_update_plane,
- .disable_plane = drm_atomic_helper_disable_plane,
-@@ -289,6 +310,7 @@ static const struct drm_plane_funcs vc4_
- .reset = drm_atomic_helper_plane_reset,
- .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
-+ .format_mod_supported = vc4_fkms_format_mod_supported,
- };
-
- static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = {
-@@ -316,6 +338,14 @@ static struct drm_plane *vc4_fkms_plane_
- u32 argb8888 = DRM_FORMAT_ARGB8888;
- int ret = 0;
- bool primary = (type == DRM_PLANE_TYPE_PRIMARY);
-+ static const uint64_t modifiers[] = {
-+ DRM_FORMAT_MOD_LINEAR,
-+ /* VC4_T_TILED should come after linear, because we
-+ * would prefer to scan out linear (less bus traffic).
-+ */
-+ DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
-+ DRM_FORMAT_MOD_INVALID,
-+ };
-
- vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
- GFP_KERNEL);
-@@ -327,7 +357,8 @@ static struct drm_plane *vc4_fkms_plane_
- plane = &vc4_plane->base;
- ret = drm_universal_plane_init(dev, plane, 0xff,
- &vc4_plane_funcs,
-- primary ? &xrgb8888 : &argb8888, 1, NULL,
-+ primary ? &xrgb8888 : &argb8888, 1,
-+ modifiers,
- type, primary ? "primary" : "cursor");
-
- if (type == DRM_PLANE_TYPE_PRIMARY) {
--- /dev/null
+From fe4fbbfe9e5cba10f41c116441fea1dc30c28291 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 3 Apr 2019 15:20:05 +0100
+Subject: [PATCH 596/725] drm: vc4: Increase max screen size to 4096x4096.
+
+We now should support 4k screens, therefore this limit needs to
+be increased.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_kms.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -429,8 +429,8 @@ int vc4_kms_load(struct drm_device *dev)
+ return ret;
+ }
+
+- dev->mode_config.max_width = 2048;
+- dev->mode_config.max_height = 2048;
++ dev->mode_config.max_width = 4096;
++ dev->mode_config.max_height = 4096;
+ dev->mode_config.funcs = &vc4_mode_funcs;
+ dev->mode_config.preferred_depth = 24;
+ dev->mode_config.async_page_flip = true;
--- /dev/null
+From c933118b00cb40f4c9fa8f6470ef9a33ea046c4d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 3 Apr 2019 17:15:45 +0100
+Subject: [PATCH 597/725] drm: vc4: Add support for multiple displays to fkms
+
+There is a slightly nasty hack in that all crtcs share the
+same SMI interrupt from the firmware. This seems to currently
+work well enough, but ought to be fixed at a later date.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 160 +++++++++++++++++--------
+ 1 file changed, 113 insertions(+), 47 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -29,6 +29,8 @@
+ #include "vc_image_types.h"
+ #include <soc/bcm2835/raspberrypi-firmware.h>
+
++#define PLANES_PER_CRTC 3
++
+ struct set_plane {
+ u8 display;
+ u8 plane_id;
+@@ -175,6 +177,7 @@ struct vc4_crtc {
+ struct drm_pending_vblank_event *event;
+ u32 overscan[4];
+ bool vblank_enabled;
++ u32 display_number;
+ };
+
+ static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc)
+@@ -480,6 +483,7 @@ static const struct drm_plane_helper_fun
+
+ static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
+ enum drm_plane_type type,
++ u8 display_num,
+ u8 plane_id)
+ {
+ struct drm_plane *plane = NULL;
+@@ -543,7 +547,7 @@ static struct drm_plane *vc4_fkms_plane_
+ vc4_plane->mb.tag.tag = RPI_FIRMWARE_SET_PLANE;
+ vc4_plane->mb.tag.buf_size = sizeof(struct set_plane);
+ vc4_plane->mb.tag.req_resp_size = 0;
+- vc4_plane->mb.plane.display = 0;
++ vc4_plane->mb.plane.display = display_num;
+ vc4_plane->mb.plane.plane_id = plane_id;
+ vc4_plane->mb.plane.layer = default_zpos ? default_zpos : -127;
+
+@@ -630,16 +634,20 @@ static void vc4_crtc_handle_page_flip(st
+
+ static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
+ {
+- struct vc4_crtc *vc4_crtc = data;
+- u32 stat = readl(vc4_crtc->regs + SMICS);
++ struct vc4_crtc **crtc_list = data;
++ int i;
++ u32 stat = readl(crtc_list[0]->regs + SMICS);
+ irqreturn_t ret = IRQ_NONE;
+
+ if (stat & SMICS_INTERRUPTS) {
+- writel(0, vc4_crtc->regs + SMICS);
+- if (vc4_crtc->vblank_enabled)
+- drm_crtc_handle_vblank(&vc4_crtc->base);
+- vc4_crtc_handle_page_flip(vc4_crtc);
+- ret = IRQ_HANDLED;
++ writel(0, crtc_list[0]->regs + SMICS);
++
++ for (i = 0; crtc_list[i]; i++) {
++ if (crtc_list[i]->vblank_enabled)
++ drm_crtc_handle_vblank(&crtc_list[i]->base);
++ vc4_crtc_handle_page_flip(crtc_list[i]);
++ ret = IRQ_HANDLED;
++ }
+ }
+
+ return ret;
+@@ -836,66 +844,55 @@ static const struct drm_encoder_helper_f
+ .disable = vc4_fkms_encoder_disable,
+ };
+
+-static int vc4_fkms_bind(struct device *dev, struct device *master, void *data)
++static int vc4_fkms_create_screen(struct device *dev, struct drm_device *drm,
++ int display_idx, int display_ref,
++ struct vc4_crtc **ret_crtc)
+ {
+- 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, *overlay_plane, *cursor_plane;
+ struct drm_plane *destroy_plane, *temp;
+- struct device_node *firmware_node;
+ u32 blank = 1;
+ int ret;
+
+- vc4->firmware_kms = true;
+-
+- /* firmware kms doesn't have precise a scanoutpos implementation, so
+- * we can't do the precise vblank timestamp mode.
+- */
+- drm->driver->get_scanout_position = NULL;
+- drm->driver->get_vblank_timestamp = NULL;
+-
+ 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);
++ vc4_crtc->display_number = display_ref;
+
+ /* Blank the firmware provided framebuffer */
+ rpi_firmware_property(vc4->firmware,
+ RPI_FIRMWARE_FRAMEBUFFER_BLANK,
+ &blank, sizeof(blank));
+
+- primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY, 0);
++ primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY,
++ display_ref,
++ 0 + (display_idx * PLANES_PER_CRTC)
++ );
+ if (IS_ERR(primary_plane)) {
+ dev_err(dev, "failed to construct primary plane\n");
+ ret = PTR_ERR(primary_plane);
+ goto err;
+ }
+
+- overlay_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_OVERLAY, 1);
++ overlay_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_OVERLAY,
++ display_ref,
++ 1 + (display_idx * PLANES_PER_CRTC)
++ );
+ if (IS_ERR(overlay_plane)) {
+ dev_err(dev, "failed to construct overlay plane\n");
+ ret = PTR_ERR(overlay_plane);
+ goto err;
+ }
+
+- cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR, 2);
++ cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR,
++ display_ref,
++ 2 + (display_idx * PLANES_PER_CRTC)
++ );
+ if (IS_ERR(cursor_plane)) {
+ dev_err(dev, "failed to construct cursor plane\n");
+ ret = PTR_ERR(cursor_plane);
+@@ -922,13 +919,6 @@ static int vc4_fkms_bind(struct device *
+ 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;
+-
+ ret = rpi_firmware_property(vc4->firmware,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN,
+ &vc4_crtc->overscan,
+@@ -938,7 +928,7 @@ static int vc4_fkms_bind(struct device *
+ memset(&vc4_crtc->overscan, 0, sizeof(vc4_crtc->overscan));
+ }
+
+- platform_set_drvdata(pdev, vc4_crtc);
++ *ret_crtc = vc4_crtc;
+
+ return 0;
+
+@@ -955,15 +945,91 @@ err:
+ return ret;
+ }
+
++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 device_node *firmware_node;
++ struct vc4_crtc **crtc_list;
++ u32 num_displays, display_num;
++ int ret;
++ const u32 display_num_lookup[] = {2, 7, 1};
++
++ vc4->firmware_kms = true;
++
++ /* firmware kms doesn't have precise a scanoutpos implementation, so
++ * we can't do the precise vblank timestamp mode.
++ */
++ drm->driver->get_scanout_position = NULL;
++ drm->driver->get_vblank_timestamp = NULL;
++
++ 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);
++
++ ret = rpi_firmware_property(vc4->firmware,
++ RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
++ &num_displays, sizeof(u32));
++
++ /* If we fail to get the number of displays, or it returns 0, then
++ * assume old firmware that doesn't have the mailbox call, so just
++ * set one display
++ */
++ if (ret || num_displays == 0) {
++ num_displays = 1;
++ DRM_WARN("Unable to determine number of displays's. Assuming 1\n");
++ ret = 0;
++ }
++
++ /* Allocate a list, with space for a NULL on the end */
++ crtc_list = devm_kzalloc(dev, sizeof(crtc_list) * (num_displays + 1),
++ GFP_KERNEL);
++ if (!crtc_list)
++ return -ENOMEM;
++
++ for (display_num = 0; display_num < num_displays; display_num++) {
++ ret = vc4_fkms_create_screen(dev, drm, display_num,
++ display_num_lookup[display_num],
++ &crtc_list[display_num]);
++ if (ret)
++ DRM_ERROR("Oh dear, failed to create display %u\n",
++ display_num);
++ }
++
++ /* Map the SMI interrupt reg */
++ crtc_list[0]->regs = vc4_ioremap_regs(pdev, 0);
++ if (IS_ERR(crtc_list[0]->regs))
++ DRM_ERROR("Oh dear, failed to map registers\n");
++
++ writel(0, crtc_list[0]->regs + SMICS);
++ ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
++ vc4_crtc_irq_handler, 0, "vc4 firmware kms",
++ crtc_list);
++ if (ret)
++ DRM_ERROR("Oh dear, failed to register IRQ\n");
++
++ platform_set_drvdata(pdev, crtc_list);
++
++ return 0;
++}
++
+ 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);
++ struct vc4_crtc **crtc_list = dev_get_drvdata(dev);
++ int i;
+
+- vc4_fkms_connector_destroy(vc4_crtc->connector);
+- vc4_fkms_encoder_destroy(vc4_crtc->encoder);
+- drm_crtc_cleanup(&vc4_crtc->base);
++ for (i = 0; crtc_list[i]; i++) {
++ vc4_fkms_connector_destroy(crtc_list[i]->connector);
++ vc4_fkms_encoder_destroy(crtc_list[i]->encoder);
++ drm_crtc_cleanup(&crtc_list[i]->base);
++ }
+
+ platform_set_drvdata(pdev, NULL);
+ }
+++ /dev/null
-From 3b341544a3dae555d48ece948c44b3b434543077 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Tue, 2 Apr 2019 13:29:00 -0700
-Subject: [PATCH 597/703] drm/vc4: Fix vblank timestamping for firmwarekms.
-
-The core doesn't expect a false return from the scanoutpos function in
-normal usage, so we were doing the precise vblank timestamping path
-and thus "immediate" vblank disables (even though firmwarekms can't
-actually disable vblanks interrupts, sigh), and the kernel would get
-confused when getting timestamp info when also turning vblanks back
-on.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/vc4/vc4_crtc.c | 3 ---
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 ++++++
- 2 files changed, 6 insertions(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_crtc.c
-+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
-@@ -133,9 +133,6 @@ bool vc4_crtc_get_scanoutpos(struct drm_
- int vblank_lines;
- bool ret = false;
-
-- if (vc4->firmware_kms)
-- return 0;
--
- /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */
-
- /* Get optional system timestamp before query. */
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -673,6 +673,12 @@ static int vc4_fkms_bind(struct device *
-
- vc4->firmware_kms = true;
-
-+ /* firmware kms doesn't have precise a scanoutpos implementation, so
-+ * we can't do the precise vblank timestamp mode.
-+ */
-+ drm->driver->get_scanout_position = NULL;
-+ drm->driver->get_vblank_timestamp = NULL;
-+
- vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
- if (!vc4_crtc)
- return -ENOMEM;
--- /dev/null
+From 407f6a2ad0168c3385d9d015aac2af70532ecd4a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 5 Apr 2019 17:21:56 +0100
+Subject: [PATCH 598/725] drm: vc4: Fix build warning
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -932,8 +932,6 @@ static int vc4_fkms_create_screen(struct
+
+ 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,
+++ /dev/null
-From e4aadf5daae0b3f544e5ade7ee27a5e0f83af1b0 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 26 Mar 2019 14:43:06 +0000
-Subject: [PATCH 598/703] gpu: vc4-fkms: Switch to the newer mailbox frame
- buffer API.
-
-The old mailbox FB API was ideally deprecated but still used by
-the FKMS driver.
-Update to the newer API.
-
-NB This needs current firmware that accepts ARM allocated buffers
-through the newer API.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 109 +++++++++++----------
- include/soc/bcm2835/raspberrypi-firmware.h | 10 ++
- 2 files changed, 67 insertions(+), 52 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -28,6 +28,25 @@
- #include "vc4_regs.h"
- #include <soc/bcm2835/raspberrypi-firmware.h>
-
-+struct fb_alloc_tags {
-+ struct rpi_firmware_property_tag_header tag1;
-+ u32 xres, yres;
-+ struct rpi_firmware_property_tag_header tag2;
-+ u32 xres_virtual, yres_virtual;
-+ struct rpi_firmware_property_tag_header tag3;
-+ u32 bpp;
-+ struct rpi_firmware_property_tag_header tag4;
-+ u32 xoffset, yoffset;
-+ struct rpi_firmware_property_tag_header tag5;
-+ u32 base, screen_size;
-+ struct rpi_firmware_property_tag_header tag6;
-+ u32 pitch;
-+ struct rpi_firmware_property_tag_header tag7;
-+ u32 alpha_mode;
-+ struct rpi_firmware_property_tag_header tag8;
-+ u32 layer;
-+};
-+
- /* The firmware delivers a vblank interrupt to us through the SMI
- * hardware, which has only this one register.
- */
-@@ -121,45 +140,39 @@ static void vc4_primary_plane_atomic_upd
- 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 format = fb->format->format;
-+ struct fb_alloc_tags fbinfo = {
-+ .tag1 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT,
-+ 8, 0, },
-+ .xres = state->crtc_w,
-+ .yres = state->crtc_h,
-+ .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT,
-+ 8, 0, },
-+ .xres_virtual = state->crtc_w,
-+ .yres_virtual = state->crtc_h,
-+ .tag3 = { RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, 4, 0 },
-+ .bpp = 32,
-+ .tag4 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, 8, 0 },
-+ .xoffset = 0,
-+ .yoffset = 0,
-+ .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
-+ .base = bo->paddr + fb->offsets[0],
-+ .screen_size = state->crtc_w * state->crtc_h * 4,
-+ .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
-+ .pitch = fb->pitches[0],
-+ .tag7 = { RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE, 4, 0 },
-+ .alpha_mode = format == DRM_FORMAT_ARGB8888 ? 0 : 2,
-+ .tag8 = { RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER, 4, 0 },
-+ .layer = -127,
-+ };
- u32 bpp = 32;
- int ret;
-
-- 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];
--
- if (fb->modifier == DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED)
-- fbinfo->bpp |= BIT(31);
--
-- /* 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]);
-- }
-+ fbinfo.bpp |= BIT(31);
-
- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%d\n",
- plane->base.id, plane->name,
-@@ -168,14 +181,13 @@ static void vc4_primary_plane_atomic_upd
- bpp,
- state->crtc_x,
- state->crtc_y,
-- &fbinfo->base,
-+ &fbinfo.base,
- 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]);
-+ ret = rpi_firmware_property_list(vc4->firmware, &fbinfo,
-+ sizeof(fbinfo));
-+ WARN_ON_ONCE(fbinfo.pitch != fb->pitches[0]);
-+ WARN_ON_ONCE(fbinfo.base != bo->paddr + fb->offsets[0]);
-
- /* If the CRTC is on (or going to be on) and we're enabled,
- * then unblank. Otherwise, stay blank until CRTC enable.
-@@ -332,10 +344,10 @@ static const struct drm_plane_helper_fun
- static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
- enum drm_plane_type type)
- {
-+ /* Primary and cursor planes only */
- struct drm_plane *plane = NULL;
- struct vc4_fkms_plane *vc4_plane;
-- u32 xrgb8888 = DRM_FORMAT_XRGB8888;
-- u32 argb8888 = DRM_FORMAT_ARGB8888;
-+ u32 formats[] = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888};
- int ret = 0;
- bool primary = (type == DRM_PLANE_TYPE_PRIMARY);
- static const uint64_t modifiers[] = {
-@@ -357,22 +369,15 @@ static struct drm_plane *vc4_fkms_plane_
- plane = &vc4_plane->base;
- ret = drm_universal_plane_init(dev, plane, 0xff,
- &vc4_plane_funcs,
-- primary ? &xrgb8888 : &argb8888, 1,
-- modifiers,
-+ formats, primary ? 2 : 1, modifiers,
- type, primary ? "primary" : "cursor");
-
-- 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));
--
-+ if (type == DRM_PLANE_TYPE_PRIMARY)
- drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs);
-- } else {
-+ else
- drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs);
-- }
-+
-+ drm_plane_create_alpha_property(plane);
-
- return plane;
- fail:
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -111,9 +111,15 @@ enum rpi_firmware_property_tag {
- RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009,
- RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a,
- RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b,
-+ RPI_FIRMWARE_FRAMEBUFFER_GET_LAYER = 0x0004000c,
-+ RPI_FIRMWARE_FRAMEBUFFER_GET_TRANSFORM = 0x0004000d,
-+ RPI_FIRMWARE_FRAMEBUFFER_GET_VSYNC = 0x0004000e,
- RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f,
- RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
- RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001,
-+ RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM = 0x00048013,
-+ RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS = 0x00040013,
-+ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS = 0x00040014,
- RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
- RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
- RPI_FIRMWARE_FRAMEBUFFER_TEST_DEPTH = 0x00044005,
-@@ -122,6 +128,8 @@ enum rpi_firmware_property_tag {
- RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009,
- RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a,
- RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE = 0x0004400b,
-+ RPI_FIRMWARE_FRAMEBUFFER_TEST_LAYER = 0x0004400c,
-+ RPI_FIRMWARE_FRAMEBUFFER_TEST_TRANSFORM = 0x0004400d,
- RPI_FIRMWARE_FRAMEBUFFER_TEST_VSYNC = 0x0004400e,
- RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003,
- RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004,
-@@ -134,6 +142,8 @@ enum rpi_firmware_property_tag {
- RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
- RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020,
- RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
-+ RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER = 0x0004800c,
-+ RPI_FIRMWARE_FRAMEBUFFER_SET_TRANSFORM = 0x0004800d,
- RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f,
-
- RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
+++ /dev/null
-From 36b8b81762806952c524da6539b76771266d79c5 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 27 Mar 2019 17:45:01 +0000
-Subject: [PATCH 599/703] drm: vc4: Add an overlay plane to vc4-firmware-kms
-
-This uses a new API that is exposed via the mailbox service
-to stick an element straight on the screen using DispmanX.
-
-The primary and cursor planes have also been switched to using
-the new plane API, and it supports layering based on the DRM
-zpos parameter.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 518 ++++++++++++++-------
- drivers/gpu/drm/vc4/vc4_kms.c | 1 +
- drivers/gpu/drm/vc4/vc_image_types.h | 143 ++++++
- include/soc/bcm2835/raspberrypi-firmware.h | 2 +
- 4 files changed, 495 insertions(+), 169 deletions(-)
- create mode 100644 drivers/gpu/drm/vc4/vc_image_types.h
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -26,8 +26,46 @@
- #include "linux/of_device.h"
- #include "vc4_drv.h"
- #include "vc4_regs.h"
-+#include "vc_image_types.h"
- #include <soc/bcm2835/raspberrypi-firmware.h>
-
-+struct set_plane {
-+ u8 display;
-+ u8 plane_id;
-+ u8 vc_image_type;
-+ s8 layer;
-+
-+ u16 width;
-+ u16 height;
-+
-+ u16 pitch;
-+ u16 vpitch;
-+
-+ u32 src_x; /* 16p16 */
-+ u32 src_y; /* 16p16 */
-+
-+ u32 src_w; /* 16p16 */
-+ u32 src_h; /* 16p16 */
-+
-+ s16 dst_x;
-+ s16 dst_y;
-+
-+ u16 dst_w;
-+ u16 dst_h;
-+
-+ u8 alpha;
-+ u8 num_planes;
-+ u8 is_vu;
-+ u8 padding;
-+
-+ u32 planes[4]; /* DMA address of each plane */
-+};
-+
-+struct mailbox_set_plane {
-+ struct rpi_firmware_property_tag_header tag;
-+ struct set_plane plane;
-+};
-+
- struct fb_alloc_tags {
- struct rpi_firmware_property_tag_header tag1;
- u32 xres, yres;
-@@ -47,6 +85,79 @@ struct fb_alloc_tags {
- u32 layer;
- };
-
-+static const struct vc_image_format {
-+ u32 drm; /* DRM_FORMAT_* */
-+ u32 vc_image; /* VC_IMAGE_* */
-+ u32 is_vu;
-+} vc_image_formats[] = {
-+ {
-+ .drm = DRM_FORMAT_XRGB8888,
-+ .vc_image = VC_IMAGE_XRGB8888,
-+ },
-+ {
-+ .drm = DRM_FORMAT_ARGB8888,
-+ .vc_image = VC_IMAGE_ARGB8888,
-+ },
-+/*
-+ * FIXME: Need to resolve which DRM format goes to which vc_image format
-+ * for the remaining RGBA and RGBX formats.
-+ * {
-+ * .drm = DRM_FORMAT_ABGR8888,
-+ * .vc_image = VC_IMAGE_RGBA8888,
-+ * },
-+ * {
-+ * .drm = DRM_FORMAT_XBGR8888,
-+ * .vc_image = VC_IMAGE_RGBA8888,
-+ * },
-+ */
-+ {
-+ .drm = DRM_FORMAT_RGB565,
-+ .vc_image = VC_IMAGE_RGB565,
-+ },
-+ {
-+ .drm = DRM_FORMAT_RGB888,
-+ .vc_image = VC_IMAGE_BGR888,
-+ },
-+ {
-+ .drm = DRM_FORMAT_BGR888,
-+ .vc_image = VC_IMAGE_RGB888,
-+ },
-+ {
-+ .drm = DRM_FORMAT_YUV422,
-+ .vc_image = VC_IMAGE_YUV422PLANAR,
-+ },
-+ {
-+ .drm = DRM_FORMAT_YUV420,
-+ .vc_image = VC_IMAGE_YUV420,
-+ },
-+ {
-+ .drm = DRM_FORMAT_YVU420,
-+ .vc_image = VC_IMAGE_YUV420,
-+ .is_vu = 1,
-+ },
-+ {
-+ .drm = DRM_FORMAT_NV12,
-+ .vc_image = VC_IMAGE_YUV420SP,
-+ },
-+ {
-+ .drm = DRM_FORMAT_NV21,
-+ .vc_image = VC_IMAGE_YUV420SP,
-+ .is_vu = 1,
-+ },
-+};
-+
-+static const struct vc_image_format *vc4_get_vc_image_fmt(u32 drm_format)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++) {
-+ if (vc_image_formats[i].drm == drm_format)
-+ return &vc_image_formats[i];
-+ }
-+
-+ return NULL;
-+}
-+
- /* The firmware delivers a vblank interrupt to us through the SMI
- * hardware, which has only this one register.
- */
-@@ -113,6 +224,7 @@ struct vc4_fkms_plane {
- struct fbinfo_s *fbinfo;
- dma_addr_t fbinfo_bus_addr;
- u32 pitch;
-+ struct mailbox_set_plane mb;
- };
-
- static inline struct vc4_fkms_plane *to_vc4_fkms_plane(struct drm_plane *plane)
-@@ -120,165 +232,183 @@ static inline struct vc4_fkms_plane *to_
- return (struct vc4_fkms_plane *)plane;
- }
-
--/* Turns the display on/off. */
--static int vc4_plane_set_primary_blank(struct drm_plane *plane, bool blank)
-+static int vc4_plane_set_blank(struct drm_plane *plane, bool blank)
- {
- struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
-+ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
-+ struct mailbox_set_plane blank_mb = {
-+ .tag = { RPI_FIRMWARE_SET_PLANE, sizeof(struct set_plane), 0 },
-+ .plane = {
-+ .display = vc4_plane->mb.plane.display,
-+ .plane_id = vc4_plane->mb.plane.plane_id,
-+ }
-+ };
-+ int ret;
-
-- u32 packet = blank;
--
-- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary plane %s",
-+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] overlay plane %s",
- plane->base.id, plane->name,
- blank ? "blank" : "unblank");
-
-- return rpi_firmware_property(vc4->firmware,
-- RPI_FIRMWARE_FRAMEBUFFER_BLANK,
-- &packet, sizeof(packet));
-+ if (blank)
-+ ret = rpi_firmware_property_list(vc4->firmware, &blank_mb,
-+ sizeof(blank_mb));
-+ else
-+ ret = rpi_firmware_property_list(vc4->firmware, &vc4_plane->mb,
-+ sizeof(vc4_plane->mb));
-+
-+ WARN_ONCE(ret, "%s: firmware call failed. Please update your firmware",
-+ __func__);
-+ return ret;
- }
-
--static void vc4_primary_plane_atomic_update(struct drm_plane *plane,
-- struct drm_plane_state *old_state)
-+static void vc4_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);
-- u32 format = fb->format->format;
-- struct fb_alloc_tags fbinfo = {
-- .tag1 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT,
-- 8, 0, },
-- .xres = state->crtc_w,
-- .yres = state->crtc_h,
-- .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT,
-- 8, 0, },
-- .xres_virtual = state->crtc_w,
-- .yres_virtual = state->crtc_h,
-- .tag3 = { RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, 4, 0 },
-- .bpp = 32,
-- .tag4 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, 8, 0 },
-- .xoffset = 0,
-- .yoffset = 0,
-- .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
-- .base = bo->paddr + fb->offsets[0],
-- .screen_size = state->crtc_w * state->crtc_h * 4,
-- .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
-- .pitch = fb->pitches[0],
-- .tag7 = { RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE, 4, 0 },
-- .alpha_mode = format == DRM_FORMAT_ARGB8888 ? 0 : 2,
-- .tag8 = { RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER, 4, 0 },
-- .layer = -127,
-- };
-- u32 bpp = 32;
-- int ret;
-+ const struct drm_format_info *drm_fmt = fb->format;
-+ const struct vc_image_format *vc_fmt =
-+ vc4_get_vc_image_fmt(drm_fmt->format);
-+ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
-+ struct mailbox_set_plane *mb = &vc4_plane->mb;
-+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
-+ int num_planes = fb->format->num_planes;
-+ struct drm_display_mode *mode = &state->crtc->mode;
-
-- if (fb->modifier == DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED)
-- fbinfo.bpp |= BIT(31);
-+ mb->plane.vc_image_type = vc_fmt->vc_image;
-+ mb->plane.width = fb->width;
-+ mb->plane.height = fb->height;
-+ mb->plane.pitch = fb->pitches[0];
-+ mb->plane.src_w = state->src_w;
-+ mb->plane.src_h = state->src_h;
-+ mb->plane.src_x = state->src_x;
-+ mb->plane.src_y = state->src_y;
-+ mb->plane.dst_w = state->crtc_w;
-+ mb->plane.dst_h = state->crtc_h;
-+ mb->plane.dst_x = state->crtc_x;
-+ mb->plane.dst_y = state->crtc_y;
-+ mb->plane.alpha = state->alpha >> 8;
-+ mb->plane.layer = state->normalized_zpos ?
-+ state->normalized_zpos : -127;
-+ mb->plane.num_planes = num_planes;
-+ mb->plane.is_vu = vc_fmt->is_vu;
-+ mb->plane.planes[0] = bo->paddr + fb->offsets[0];
-
-- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%d\n",
-+ /* FIXME: If the dest rect goes off screen then clip the src rect so we
-+ * don't have off-screen pixels.
-+ */
-+ if (plane->type == DRM_PLANE_TYPE_CURSOR) {
-+ /* There is no scaling on the cursor plane, therefore the calcs
-+ * to alter the source crop as the cursor goes off the screen
-+ * are simple.
-+ */
-+ if (mb->plane.dst_x + mb->plane.dst_w > mode->hdisplay) {
-+ mb->plane.dst_w = mode->hdisplay - mb->plane.dst_x;
-+ mb->plane.src_w = (mode->hdisplay - mb->plane.dst_x)
-+ << 16;
-+ }
-+ if (mb->plane.dst_y + mb->plane.dst_h > mode->vdisplay) {
-+ mb->plane.dst_h = mode->vdisplay - mb->plane.dst_y;
-+ mb->plane.src_h = (mode->vdisplay - mb->plane.dst_y)
-+ << 16;
-+ }
-+ }
-+
-+ if (num_planes > 1) {
-+ /* Assume this must be YUV */
-+ /* Makes assumptions on the stride for the chroma planes as we
-+ * can't easily plumb in non-standard pitches.
-+ */
-+ mb->plane.planes[1] = bo->paddr + fb->offsets[1];
-+ if (num_planes > 2)
-+ mb->plane.planes[2] = bo->paddr + fb->offsets[2];
-+ else
-+ mb->plane.planes[2] = 0;
-+
-+ /* Special case the YUV420 with U and V as line interleaved
-+ * planes as we have special handling for that case.
-+ */
-+ if (num_planes == 3 &&
-+ (fb->offsets[2] - fb->offsets[1]) == fb->pitches[1])
-+ mb->plane.vc_image_type = VC_IMAGE_YUV420_S;
-+ } else {
-+ mb->plane.planes[1] = 0;
-+ mb->plane.planes[2] = 0;
-+ }
-+ mb->plane.planes[3] = 0;
-+
-+ switch (fb->modifier) {
-+ case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
-+ switch (mb->plane.vc_image_type) {
-+ case VC_IMAGE_RGBX32:
-+ mb->plane.vc_image_type = VC_IMAGE_TF_RGBX32;
-+ break;
-+ case VC_IMAGE_RGBA32:
-+ mb->plane.vc_image_type = VC_IMAGE_TF_RGBA32;
-+ break;
-+ case VC_IMAGE_RGB565:
-+ mb->plane.vc_image_type = VC_IMAGE_TF_RGB565;
-+ break;
-+ }
-+ break;
-+ case DRM_FORMAT_MOD_BROADCOM_SAND128:
-+ mb->plane.vc_image_type = VC_IMAGE_YUV_UV;
-+ mb->plane.pitch = fourcc_mod_broadcom_param(fb->modifier);
-+ break;
-+ }
-+
-+ if (vc4_crtc) {
-+ mb->plane.dst_x += vc4_crtc->overscan[0];
-+ mb->plane.dst_y += vc4_crtc->overscan[1];
-+ }
-+
-+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane update %dx%d@%d +dst(%d,%d, %d,%d) +src(%d,%d, %d,%d) 0x%08x/%08x/%08x/%d, alpha %u zpos %u\n",
- plane->base.id, plane->name,
-- state->crtc_w,
-- state->crtc_h,
-- bpp,
-+ mb->plane.width,
-+ mb->plane.height,
-+ mb->plane.vc_image_type,
- state->crtc_x,
- state->crtc_y,
-- &fbinfo.base,
-- fb->pitches[0]);
--
-- ret = rpi_firmware_property_list(vc4->firmware, &fbinfo,
-- sizeof(fbinfo));
-- WARN_ON_ONCE(fbinfo.pitch != fb->pitches[0]);
-- WARN_ON_ONCE(fbinfo.base != bo->paddr + fb->offsets[0]);
--
-- /* If the CRTC is on (or going to be on) and we're enabled,
-+ state->crtc_w,
-+ state->crtc_h,
-+ mb->plane.src_x,
-+ mb->plane.src_y,
-+ mb->plane.src_w,
-+ mb->plane.src_h,
-+ mb->plane.planes[0],
-+ mb->plane.planes[1],
-+ mb->plane.planes[2],
-+ fb->pitches[0],
-+ state->alpha,
-+ state->normalized_zpos);
-+
-+ /*
-+ * Do NOT set now, as we haven't checked if the crtc is active or not.
-+ * Set from vc4_plane_set_blank instead.
-+ *
-+ * If the CRTC is on (or going to be on) and we're enabled,
- * then unblank. Otherwise, stay blank until CRTC enable.
-- */
-+ */
- if (state->crtc->state->active)
-- vc4_plane_set_primary_blank(plane, false);
-+ vc4_plane_set_blank(plane, false);
- }
-
--static void vc4_primary_plane_atomic_disable(struct drm_plane *plane,
-- struct drm_plane_state *old_state)
-+static void vc4_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 vc4_dev *vc4 = to_vc4_dev(plane->dev);
- struct drm_plane_state *state = plane->state;
-- struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
-- struct drm_framebuffer *fb = state->fb;
-- struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
-- dma_addr_t addr = bo->paddr + fb->offsets[0];
-- int ret;
-- u32 packet_state[] = {
-- state->crtc->state->active,
-- state->crtc_x,
-- state->crtc_y,
-- 0
-- };
-- WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4);
-+ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
-
-- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%pad/%d)",
-+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane disable %dx%d@%d +%d,%d\n",
- plane->base.id, plane->name,
- state->crtc_w,
- state->crtc_h,
-+ vc4_plane->mb.plane.vc_image_type,
- state->crtc_x,
-- state->crtc_y,
-- &addr,
-- fb->pitches[0]);
--
-- /* add on the top/left offsets when overscan is active */
-- if (vc4_crtc) {
-- packet_state[1] += vc4_crtc->overscan[0];
-- packet_state[2] += vc4_crtc->overscan[1];
-- }
--
-- 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]);
--
-- /* Note: When the cursor contents change, the modesetting
-- * driver calls drm_mode_cursor_univeral() with
-- * DRM_MODE_CURSOR_BO, which means a new fb will be allocated.
-- */
-- if (!old_state ||
-- state->crtc_w != old_state->crtc_w ||
-- state->crtc_h != old_state->crtc_h ||
-- fb != old_state->fb) {
-- u32 packet_info[] = { state->crtc_w, state->crtc_h,
-- 0, /* unused */
-- addr,
-- 0, 0, /* hotx, hoty */};
--
-- 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;
--
-- 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,
-- sizeof(packet_state));
-- if (ret || packet_state[0] != 0)
-- DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]);
-+ state->crtc_y);
-+ vc4_plane_set_blank(plane, true);
- }
-
- static int vc4_plane_atomic_check(struct drm_plane *plane,
-@@ -301,6 +431,7 @@ static bool vc4_fkms_format_mod_supporte
- switch (format) {
- case DRM_FORMAT_XRGB8888:
- case DRM_FORMAT_ARGB8888:
-+ case DRM_FORMAT_RGB565:
- switch (modifier) {
- case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
- case DRM_FORMAT_MOD_LINEAR:
-@@ -309,8 +440,22 @@ static bool vc4_fkms_format_mod_supporte
- default:
- return false;
- }
-+ case DRM_FORMAT_NV12:
-+ case DRM_FORMAT_NV21:
-+ switch (fourcc_mod_broadcom_mod(modifier)) {
-+ case DRM_FORMAT_MOD_LINEAR:
-+ case DRM_FORMAT_MOD_BROADCOM_SAND128:
-+ return true;
-+ default:
-+ return false;
-+ }
-+ case DRM_FORMAT_RGB888:
-+ case DRM_FORMAT_BGR888:
-+ case DRM_FORMAT_YUV422:
-+ case DRM_FORMAT_YUV420:
-+ case DRM_FORMAT_YVU420:
- default:
-- return false;
-+ return (modifier == DRM_FORMAT_MOD_LINEAR);
- }
- }
-
-@@ -325,31 +470,24 @@ static const struct drm_plane_funcs vc4_
- .format_mod_supported = vc4_fkms_format_mod_supported,
- };
-
--static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = {
-- .prepare_fb = drm_gem_fb_prepare_fb,
-- .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 = {
-+static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = {
- .prepare_fb = drm_gem_fb_prepare_fb,
- .cleanup_fb = NULL,
- .atomic_check = vc4_plane_atomic_check,
-- .atomic_update = vc4_cursor_plane_atomic_update,
-- .atomic_disable = vc4_cursor_plane_atomic_disable,
-+ .atomic_update = vc4_plane_atomic_update,
-+ .atomic_disable = vc4_plane_atomic_disable,
- };
-
- static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
-- enum drm_plane_type type)
-+ enum drm_plane_type type,
-+ u8 plane_id)
- {
-- /* Primary and cursor planes only */
- struct drm_plane *plane = NULL;
- struct vc4_fkms_plane *vc4_plane;
-- u32 formats[] = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888};
-+ u32 formats[ARRAY_SIZE(vc_image_formats)];
-+ unsigned int default_zpos;
-+ u32 num_formats = 0;
- int ret = 0;
-- bool primary = (type == DRM_PLANE_TYPE_PRIMARY);
- static const uint64_t modifiers[] = {
- DRM_FORMAT_MOD_LINEAR,
- /* VC4_T_TILED should come after linear, because we
-@@ -358,6 +496,7 @@ static struct drm_plane *vc4_fkms_plane_
- DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
- DRM_FORMAT_MOD_INVALID,
- };
-+ int i;
-
- vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
- GFP_KERNEL);
-@@ -366,19 +505,48 @@ static struct drm_plane *vc4_fkms_plane_
- goto fail;
- }
-
-+ for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++)
-+ formats[num_formats++] = vc_image_formats[i].drm;
-+
- plane = &vc4_plane->base;
- ret = drm_universal_plane_init(dev, plane, 0xff,
- &vc4_plane_funcs,
-- formats, primary ? 2 : 1, modifiers,
-- type, primary ? "primary" : "cursor");
-+ formats, num_formats, modifiers,
-+ type, NULL);
-
-- if (type == DRM_PLANE_TYPE_PRIMARY)
-- drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs);
-- else
-- drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs);
-+ drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
-
- drm_plane_create_alpha_property(plane);
-
-+ /*
-+ * Default frame buffer setup is with FB on -127, and raspistill etc
-+ * tend to drop overlays on layer 2. Cursor plane was on layer +127.
-+ *
-+ * For F-KMS the mailbox call allows for a s8.
-+ * Remap zpos 0 to -127 for the background layer, but leave all the
-+ * other layers as requested by KMS.
-+ */
-+ switch (type) {
-+ case DRM_PLANE_TYPE_PRIMARY:
-+ default_zpos = 0;
-+ break;
-+ case DRM_PLANE_TYPE_OVERLAY:
-+ default_zpos = 1;
-+ break;
-+ case DRM_PLANE_TYPE_CURSOR:
-+ default_zpos = 2;
-+ break;
-+ }
-+ drm_plane_create_zpos_property(plane, default_zpos, 0, 127);
-+
-+ /* Prepare the static elements of the mailbox structure */
-+ vc4_plane->mb.tag.tag = RPI_FIRMWARE_SET_PLANE;
-+ vc4_plane->mb.tag.buf_size = sizeof(struct set_plane);
-+ vc4_plane->mb.tag.req_resp_size = 0;
-+ vc4_plane->mb.plane.display = 0;
-+ vc4_plane->mb.plane.plane_id = plane_id;
-+ vc4_plane->mb.plane.layer = default_zpos ? default_zpos : -127;
-+
- return plane;
- fail:
- if (plane)
-@@ -400,19 +568,23 @@ static void vc4_crtc_disable(struct drm_
- * whether anything scans out at all, but the firmware doesn't
- * give us a CRTC-level control for that.
- */
-- vc4_cursor_plane_atomic_disable(crtc->cursor, crtc->cursor->state);
-- vc4_plane_set_primary_blank(crtc->primary, true);
-+
-+ vc4_plane_atomic_disable(crtc->cursor, crtc->cursor->state);
-+ vc4_plane_atomic_disable(crtc->primary, crtc->primary->state);
-+
-+ /* FIXME: Disable overlay planes */
- }
-
- static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
- {
- /* Unblank the planes (if they're supposed to be displayed). */
-+
- if (crtc->primary->state->fb)
-- vc4_plane_set_primary_blank(crtc->primary, false);
-- if (crtc->cursor->state->fb) {
-- vc4_cursor_plane_atomic_update(crtc->cursor,
-- crtc->cursor->state);
-- }
-+ vc4_plane_set_blank(crtc->primary, false);
-+ if (crtc->cursor->state->fb)
-+ vc4_plane_set_blank(crtc->cursor, crtc->cursor->state);
-+
-+ /* FIXME: Enable overlay planes */
- }
-
- static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
-@@ -672,8 +844,10 @@ static int vc4_fkms_bind(struct device *
- 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 drm_plane *primary_plane, *overlay_plane, *cursor_plane;
-+ struct drm_plane *destroy_plane, *temp;
- struct device_node *firmware_node;
-+ u32 blank = 1;
- int ret;
-
- vc4->firmware_kms = true;
-@@ -702,20 +876,26 @@ static int vc4_fkms_bind(struct device *
- 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);
-+ /* Blank the firmware provided framebuffer */
-+ rpi_firmware_property(vc4->firmware,
-+ RPI_FIRMWARE_FRAMEBUFFER_BLANK,
-+ &blank, sizeof(blank));
-+
-+ primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY, 0);
- 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);
-+ overlay_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_OVERLAY, 1);
-+ if (IS_ERR(overlay_plane)) {
-+ dev_err(dev, "failed to construct overlay plane\n");
-+ ret = PTR_ERR(overlay_plane);
-+ goto err;
-+ }
-+
-+ cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR, 2);
- if (IS_ERR(cursor_plane)) {
- dev_err(dev, "failed to construct cursor plane\n");
- ret = PTR_ERR(cursor_plane);
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -435,6 +435,7 @@ int vc4_kms_load(struct drm_device *dev)
- dev->mode_config.preferred_depth = 24;
- dev->mode_config.async_page_flip = true;
- dev->mode_config.allow_fb_modifiers = true;
-+ dev->mode_config.normalize_zpos = true;
-
- drm_modeset_lock_init(&vc4->ctm_state_lock);
-
---- /dev/null
-+++ b/drivers/gpu/drm/vc4/vc_image_types.h
-@@ -0,0 +1,143 @@
-+
-+/*
-+ * Copyright (c) 2012, Broadcom Europe Ltd
-+ *
-+ * Values taken from vc_image_types.h released by Broadcom at
-+ * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h
-+ *
-+ * 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.
-+ */
-+
-+enum {
-+ VC_IMAGE_MIN = 0, //bounds for error checking
-+
-+ VC_IMAGE_RGB565 = 1,
-+ VC_IMAGE_1BPP,
-+ VC_IMAGE_YUV420,
-+ VC_IMAGE_48BPP,
-+ VC_IMAGE_RGB888,
-+ VC_IMAGE_8BPP,
-+ /* 4bpp palettised image */
-+ VC_IMAGE_4BPP,
-+ /* A separated format of 16 colour/light shorts followed by 16 z
-+ * values
-+ */
-+ VC_IMAGE_3D32,
-+ /* 16 colours followed by 16 z values */
-+ VC_IMAGE_3D32B,
-+ /* A separated format of 16 material/colour/light shorts followed by
-+ * 16 z values
-+ */
-+ VC_IMAGE_3D32MAT,
-+ /* 32 bit format containing 18 bits of 6.6.6 RGB, 9 bits per short */
-+ VC_IMAGE_RGB2X9,
-+ /* 32-bit format holding 18 bits of 6.6.6 RGB */
-+ VC_IMAGE_RGB666,
-+ /* 4bpp palettised image with embedded palette */
-+ VC_IMAGE_PAL4_OBSOLETE,
-+ /* 8bpp palettised image with embedded palette */
-+ VC_IMAGE_PAL8_OBSOLETE,
-+ /* RGB888 with an alpha byte after each pixel */
-+ VC_IMAGE_RGBA32,
-+ /* a line of Y (32-byte padded), a line of U (16-byte padded), and a
-+ * line of V (16-byte padded)
-+ */
-+ VC_IMAGE_YUV422,
-+ /* RGB565 with a transparent patch */
-+ VC_IMAGE_RGBA565,
-+ /* Compressed (4444) version of RGBA32 */
-+ VC_IMAGE_RGBA16,
-+ /* VCIII codec format */
-+ VC_IMAGE_YUV_UV,
-+ /* VCIII T-format RGBA8888 */
-+ VC_IMAGE_TF_RGBA32,
-+ /* VCIII T-format RGBx8888 */
-+ VC_IMAGE_TF_RGBX32,
-+ /* VCIII T-format float */
-+ VC_IMAGE_TF_FLOAT,
-+ /* VCIII T-format RGBA4444 */
-+ VC_IMAGE_TF_RGBA16,
-+ /* VCIII T-format RGB5551 */
-+ VC_IMAGE_TF_RGBA5551,
-+ /* VCIII T-format RGB565 */
-+ VC_IMAGE_TF_RGB565,
-+ /* VCIII T-format 8-bit luma and 8-bit alpha */
-+ VC_IMAGE_TF_YA88,
-+ /* VCIII T-format 8 bit generic sample */
-+ VC_IMAGE_TF_BYTE,
-+ /* VCIII T-format 8-bit palette */
-+ VC_IMAGE_TF_PAL8,
-+ /* VCIII T-format 4-bit palette */
-+ VC_IMAGE_TF_PAL4,
-+ /* VCIII T-format Ericsson Texture Compressed */
-+ VC_IMAGE_TF_ETC1,
-+ /* RGB888 with R & B swapped */
-+ VC_IMAGE_BGR888,
-+ /* RGB888 with R & B swapped, but with no pitch, i.e. no padding after
-+ * each row of pixels
-+ */
-+ VC_IMAGE_BGR888_NP,
-+ /* Bayer image, extra defines which variant is being used */
-+ VC_IMAGE_BAYER,
-+ /* General wrapper for codec images e.g. JPEG from camera */
-+ VC_IMAGE_CODEC,
-+ /* VCIII codec format */
-+ VC_IMAGE_YUV_UV32,
-+ /* VCIII T-format 8-bit luma */
-+ VC_IMAGE_TF_Y8,
-+ /* VCIII T-format 8-bit alpha */
-+ VC_IMAGE_TF_A8,
-+ /* VCIII T-format 16-bit generic sample */
-+ VC_IMAGE_TF_SHORT,
-+ /* VCIII T-format 1bpp black/white */
-+ VC_IMAGE_TF_1BPP,
-+ VC_IMAGE_OPENGL,
-+ /* VCIII-B0 HVS YUV 4:4:4 interleaved samples */
-+ VC_IMAGE_YUV444I,
-+ /* Y, U, & V planes separately (VC_IMAGE_YUV422 has them interleaved on
-+ * a per line basis)
-+ */
-+ VC_IMAGE_YUV422PLANAR,
-+ /* 32bpp with 8bit alpha at MS byte, with R, G, B (LS byte) */
-+ VC_IMAGE_ARGB8888,
-+ /* 32bpp with 8bit unused at MS byte, with R, G, B (LS byte) */
-+ VC_IMAGE_XRGB8888,
-+
-+ /* interleaved 8 bit samples of Y, U, Y, V (4 flavours) */
-+ VC_IMAGE_YUV422YUYV,
-+ VC_IMAGE_YUV422YVYU,
-+ VC_IMAGE_YUV422UYVY,
-+ VC_IMAGE_YUV422VYUY,
-+
-+ /* 32bpp like RGBA32 but with unused alpha */
-+ VC_IMAGE_RGBX32,
-+ /* 32bpp, corresponding to RGBA with unused alpha */
-+ VC_IMAGE_RGBX8888,
-+ /* 32bpp, corresponding to BGRA with unused alpha */
-+ VC_IMAGE_BGRX8888,
-+
-+ /* Y as a plane, then UV byte interleaved in plane with with same pitch,
-+ * half height
-+ */
-+ VC_IMAGE_YUV420SP,
-+
-+ /* Y, U, & V planes separately 4:4:4 */
-+ VC_IMAGE_YUV444PLANAR,
-+
-+ /* T-format 8-bit U - same as TF_Y8 buf from U plane */
-+ VC_IMAGE_TF_U8,
-+ /* T-format 8-bit U - same as TF_Y8 buf from V plane */
-+ VC_IMAGE_TF_V8,
-+
-+ /* YUV4:2:0 planar, 16bit values */
-+ VC_IMAGE_YUV420_16,
-+ /* YUV4:2:0 codec format, 16bit values */
-+ VC_IMAGE_YUV_UV_16,
-+ /* YUV4:2:0 with U,V in side-by-side format */
-+ VC_IMAGE_YUV420_S,
-+
-+ VC_IMAGE_MAX, /* bounds for error checking */
-+ VC_IMAGE_FORCE_ENUM_16BIT = 0xffff,
-+};
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -148,6 +148,8 @@ enum rpi_firmware_property_tag {
-
- RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
-
-+ RPI_FIRMWARE_SET_PLANE = 0x00048015,
-+
- RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
- RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,
- };
--- /dev/null
+From afb2fb1c99cefdd0dc95a944bd3506658b31768b Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 5 Apr 2019 17:23:15 +0100
+Subject: [PATCH 599/725] drm: vc4: Select display to blank during
+ initialisation
+
+Otherwise the rainbow splash screen remained in the display list
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 18 ++++++++++++++----
+ 1 file changed, 14 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -87,6 +87,13 @@ struct fb_alloc_tags {
+ u32 layer;
+ };
+
++struct mailbox_blank_display {
++ struct rpi_firmware_property_tag_header tag1;
++ u32 display;
++ struct rpi_firmware_property_tag_header tag2;
++ u32 blank;
++};
++
+ static const struct vc_image_format {
+ u32 drm; /* DRM_FORMAT_* */
+ u32 vc_image; /* VC_IMAGE_* */
+@@ -854,7 +861,12 @@ static int vc4_fkms_create_screen(struct
+ struct drm_crtc *crtc;
+ struct drm_plane *primary_plane, *overlay_plane, *cursor_plane;
+ struct drm_plane *destroy_plane, *temp;
+- u32 blank = 1;
++ struct mailbox_blank_display blank = {
++ .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
++ .display = display_idx,
++ .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_BLANK, 4, 0, },
++ .blank = 1,
++ };
+ int ret;
+
+ vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
+@@ -865,9 +877,7 @@ static int vc4_fkms_create_screen(struct
+ vc4_crtc->display_number = display_ref;
+
+ /* Blank the firmware provided framebuffer */
+- rpi_firmware_property(vc4->firmware,
+- RPI_FIRMWARE_FRAMEBUFFER_BLANK,
+- &blank, sizeof(blank));
++ rpi_firmware_property_list(vc4->firmware, &blank, sizeof(blank));
+
+ primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY,
+ display_ref,
+++ /dev/null
-From 519f7cae9e7120bb3abc13d33ace4f7438d140bc Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 3 Apr 2019 15:20:05 +0100
-Subject: [PATCH 600/703] drm: vc4: Increase max screen size to 4096x4096.
-
-We now should support 4k screens, therefore this limit needs to
-be increased.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_kms.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -429,8 +429,8 @@ int vc4_kms_load(struct drm_device *dev)
- return ret;
- }
-
-- dev->mode_config.max_width = 2048;
-- dev->mode_config.max_height = 2048;
-+ dev->mode_config.max_width = 4096;
-+ dev->mode_config.max_height = 4096;
- dev->mode_config.funcs = &vc4_mode_funcs;
- dev->mode_config.preferred_depth = 24;
- dev->mode_config.async_page_flip = true;
--- /dev/null
+From d4ab5b715c6d52e7135849924d2de08eccd28106 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 5 Apr 2019 17:24:20 +0100
+Subject: [PATCH 600/725] drm: vc4: Remove now unused structure.
+
+Cleaning up structure that was unused after
+fbb59a2 drm: vc4: Add an overlay plane to vc4-firmware-kms
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 19 -------------------
+ 1 file changed, 19 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -68,25 +68,6 @@ struct mailbox_set_plane {
+ struct set_plane plane;
+ };
+
+-struct fb_alloc_tags {
+- struct rpi_firmware_property_tag_header tag1;
+- u32 xres, yres;
+- struct rpi_firmware_property_tag_header tag2;
+- u32 xres_virtual, yres_virtual;
+- struct rpi_firmware_property_tag_header tag3;
+- u32 bpp;
+- struct rpi_firmware_property_tag_header tag4;
+- u32 xoffset, yoffset;
+- struct rpi_firmware_property_tag_header tag5;
+- u32 base, screen_size;
+- struct rpi_firmware_property_tag_header tag6;
+- u32 pitch;
+- struct rpi_firmware_property_tag_header tag7;
+- u32 alpha_mode;
+- struct rpi_firmware_property_tag_header tag8;
+- u32 layer;
+-};
+-
+ struct mailbox_blank_display {
+ struct rpi_firmware_property_tag_header tag1;
+ u32 display;
+++ /dev/null
-From f4dee6e8ddab28130160a4dba535dca167e69f13 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 3 Apr 2019 17:15:45 +0100
-Subject: [PATCH 601/703] drm: vc4: Add support for multiple displays to fkms
-
-There is a slightly nasty hack in that all crtcs share the
-same SMI interrupt from the firmware. This seems to currently
-work well enough, but ought to be fixed at a later date.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 160 +++++++++++++++++--------
- 1 file changed, 113 insertions(+), 47 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -29,6 +29,8 @@
- #include "vc_image_types.h"
- #include <soc/bcm2835/raspberrypi-firmware.h>
-
-+#define PLANES_PER_CRTC 3
-+
- struct set_plane {
- u8 display;
- u8 plane_id;
-@@ -175,6 +177,7 @@ struct vc4_crtc {
- struct drm_pending_vblank_event *event;
- u32 overscan[4];
- bool vblank_enabled;
-+ u32 display_number;
- };
-
- static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc)
-@@ -480,6 +483,7 @@ static const struct drm_plane_helper_fun
-
- static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
- enum drm_plane_type type,
-+ u8 display_num,
- u8 plane_id)
- {
- struct drm_plane *plane = NULL;
-@@ -543,7 +547,7 @@ static struct drm_plane *vc4_fkms_plane_
- vc4_plane->mb.tag.tag = RPI_FIRMWARE_SET_PLANE;
- vc4_plane->mb.tag.buf_size = sizeof(struct set_plane);
- vc4_plane->mb.tag.req_resp_size = 0;
-- vc4_plane->mb.plane.display = 0;
-+ vc4_plane->mb.plane.display = display_num;
- vc4_plane->mb.plane.plane_id = plane_id;
- vc4_plane->mb.plane.layer = default_zpos ? default_zpos : -127;
-
-@@ -630,16 +634,20 @@ static void vc4_crtc_handle_page_flip(st
-
- static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
- {
-- struct vc4_crtc *vc4_crtc = data;
-- u32 stat = readl(vc4_crtc->regs + SMICS);
-+ struct vc4_crtc **crtc_list = data;
-+ int i;
-+ u32 stat = readl(crtc_list[0]->regs + SMICS);
- irqreturn_t ret = IRQ_NONE;
-
- if (stat & SMICS_INTERRUPTS) {
-- writel(0, vc4_crtc->regs + SMICS);
-- if (vc4_crtc->vblank_enabled)
-- drm_crtc_handle_vblank(&vc4_crtc->base);
-- vc4_crtc_handle_page_flip(vc4_crtc);
-- ret = IRQ_HANDLED;
-+ writel(0, crtc_list[0]->regs + SMICS);
-+
-+ for (i = 0; crtc_list[i]; i++) {
-+ if (crtc_list[i]->vblank_enabled)
-+ drm_crtc_handle_vblank(&crtc_list[i]->base);
-+ vc4_crtc_handle_page_flip(crtc_list[i]);
-+ ret = IRQ_HANDLED;
-+ }
- }
-
- return ret;
-@@ -836,66 +844,55 @@ static const struct drm_encoder_helper_f
- .disable = vc4_fkms_encoder_disable,
- };
-
--static int vc4_fkms_bind(struct device *dev, struct device *master, void *data)
-+static int vc4_fkms_create_screen(struct device *dev, struct drm_device *drm,
-+ int display_idx, int display_ref,
-+ struct vc4_crtc **ret_crtc)
- {
-- 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, *overlay_plane, *cursor_plane;
- struct drm_plane *destroy_plane, *temp;
-- struct device_node *firmware_node;
- u32 blank = 1;
- int ret;
-
-- vc4->firmware_kms = true;
--
-- /* firmware kms doesn't have precise a scanoutpos implementation, so
-- * we can't do the precise vblank timestamp mode.
-- */
-- drm->driver->get_scanout_position = NULL;
-- drm->driver->get_vblank_timestamp = NULL;
--
- 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);
-+ vc4_crtc->display_number = display_ref;
-
- /* Blank the firmware provided framebuffer */
- rpi_firmware_property(vc4->firmware,
- RPI_FIRMWARE_FRAMEBUFFER_BLANK,
- &blank, sizeof(blank));
-
-- primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY, 0);
-+ primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY,
-+ display_ref,
-+ 0 + (display_idx * PLANES_PER_CRTC)
-+ );
- if (IS_ERR(primary_plane)) {
- dev_err(dev, "failed to construct primary plane\n");
- ret = PTR_ERR(primary_plane);
- goto err;
- }
-
-- overlay_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_OVERLAY, 1);
-+ overlay_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_OVERLAY,
-+ display_ref,
-+ 1 + (display_idx * PLANES_PER_CRTC)
-+ );
- if (IS_ERR(overlay_plane)) {
- dev_err(dev, "failed to construct overlay plane\n");
- ret = PTR_ERR(overlay_plane);
- goto err;
- }
-
-- cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR, 2);
-+ cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR,
-+ display_ref,
-+ 2 + (display_idx * PLANES_PER_CRTC)
-+ );
- if (IS_ERR(cursor_plane)) {
- dev_err(dev, "failed to construct cursor plane\n");
- ret = PTR_ERR(cursor_plane);
-@@ -922,13 +919,6 @@ static int vc4_fkms_bind(struct device *
- 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;
--
- ret = rpi_firmware_property(vc4->firmware,
- RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN,
- &vc4_crtc->overscan,
-@@ -938,7 +928,7 @@ static int vc4_fkms_bind(struct device *
- memset(&vc4_crtc->overscan, 0, sizeof(vc4_crtc->overscan));
- }
-
-- platform_set_drvdata(pdev, vc4_crtc);
-+ *ret_crtc = vc4_crtc;
-
- return 0;
-
-@@ -955,15 +945,91 @@ err:
- return ret;
- }
-
-+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 device_node *firmware_node;
-+ struct vc4_crtc **crtc_list;
-+ u32 num_displays, display_num;
-+ int ret;
-+ const u32 display_num_lookup[] = {2, 7, 1};
-+
-+ vc4->firmware_kms = true;
-+
-+ /* firmware kms doesn't have precise a scanoutpos implementation, so
-+ * we can't do the precise vblank timestamp mode.
-+ */
-+ drm->driver->get_scanout_position = NULL;
-+ drm->driver->get_vblank_timestamp = NULL;
-+
-+ 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);
-+
-+ ret = rpi_firmware_property(vc4->firmware,
-+ RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
-+ &num_displays, sizeof(u32));
-+
-+ /* If we fail to get the number of displays, or it returns 0, then
-+ * assume old firmware that doesn't have the mailbox call, so just
-+ * set one display
-+ */
-+ if (ret || num_displays == 0) {
-+ num_displays = 1;
-+ DRM_WARN("Unable to determine number of displays's. Assuming 1\n");
-+ ret = 0;
-+ }
-+
-+ /* Allocate a list, with space for a NULL on the end */
-+ crtc_list = devm_kzalloc(dev, sizeof(crtc_list) * (num_displays + 1),
-+ GFP_KERNEL);
-+ if (!crtc_list)
-+ return -ENOMEM;
-+
-+ for (display_num = 0; display_num < num_displays; display_num++) {
-+ ret = vc4_fkms_create_screen(dev, drm, display_num,
-+ display_num_lookup[display_num],
-+ &crtc_list[display_num]);
-+ if (ret)
-+ DRM_ERROR("Oh dear, failed to create display %u\n",
-+ display_num);
-+ }
-+
-+ /* Map the SMI interrupt reg */
-+ crtc_list[0]->regs = vc4_ioremap_regs(pdev, 0);
-+ if (IS_ERR(crtc_list[0]->regs))
-+ DRM_ERROR("Oh dear, failed to map registers\n");
-+
-+ writel(0, crtc_list[0]->regs + SMICS);
-+ ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
-+ vc4_crtc_irq_handler, 0, "vc4 firmware kms",
-+ crtc_list);
-+ if (ret)
-+ DRM_ERROR("Oh dear, failed to register IRQ\n");
-+
-+ platform_set_drvdata(pdev, crtc_list);
-+
-+ return 0;
-+}
-+
- 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);
-+ struct vc4_crtc **crtc_list = dev_get_drvdata(dev);
-+ int i;
-
-- vc4_fkms_connector_destroy(vc4_crtc->connector);
-- vc4_fkms_encoder_destroy(vc4_crtc->encoder);
-- drm_crtc_cleanup(&vc4_crtc->base);
-+ for (i = 0; crtc_list[i]; i++) {
-+ vc4_fkms_connector_destroy(crtc_list[i]->connector);
-+ vc4_fkms_encoder_destroy(crtc_list[i]->encoder);
-+ drm_crtc_cleanup(&crtc_list[i]->base);
-+ }
-
- platform_set_drvdata(pdev, NULL);
- }
--- /dev/null
+From 65367a8d30161871007aa14e62644f62fc5d102b Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 9 Apr 2019 12:37:28 +0100
+Subject: [PATCH 601/725] drm: vc4: Query the display ID for each display in
+ FKMS
+
+Replace the hard coded list of display IDs for a mailbox call
+that returns the display ID for each display that has been
+detected.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 16 +++++++++++++---
+ include/soc/bcm2835/raspberrypi-firmware.h | 1 +
+ 2 files changed, 14 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -943,7 +943,7 @@ static int vc4_fkms_bind(struct device *
+ struct vc4_crtc **crtc_list;
+ u32 num_displays, display_num;
+ int ret;
+- const u32 display_num_lookup[] = {2, 7, 1};
++ u32 display_id;
+
+ vc4->firmware_kms = true;
+
+@@ -982,8 +982,18 @@ static int vc4_fkms_bind(struct device *
+ return -ENOMEM;
+
+ for (display_num = 0; display_num < num_displays; display_num++) {
+- ret = vc4_fkms_create_screen(dev, drm, display_num,
+- display_num_lookup[display_num],
++ display_id = display_num;
++ ret = rpi_firmware_property(vc4->firmware,
++ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID,
++ &display_id, sizeof(display_id));
++ /* FIXME: Determine the correct error handling here.
++ * Should we fail to create the one "screen" but keep the
++ * others, or fail the whole thing?
++ */
++ if (ret)
++ DRM_ERROR("Failed to get display id %u\n", display_num);
++
++ ret = vc4_fkms_create_screen(dev, drm, display_num, display_id,
+ &crtc_list[display_num]);
+ if (ret)
+ DRM_ERROR("Oh dear, failed to create display %u\n",
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -117,6 +117,7 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
+ RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001,
++ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID = 0x00040016,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM = 0x00048013,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS = 0x00040013,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS = 0x00040014,
+++ /dev/null
-From 56ac34a516982f51f7a0678f185bcb80f5070a0e Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 5 Apr 2019 17:21:56 +0100
-Subject: [PATCH 602/703] drm: vc4: Fix build warning
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 2 --
- 1 file changed, 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -932,8 +932,6 @@ static int vc4_fkms_create_screen(struct
-
- 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,
--- /dev/null
+From 753eb8bb53189b0e9c81454739e02fffdc5ec319 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 9 Apr 2019 14:00:07 +0100
+Subject: [PATCH 602/725] drm/vc4: Set the display number when querying the
+ display resolution
+
+Without this the two displays got set to the same resolution.
+(Requires a firmware bug fix to work).
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 37 +++++++++++++++++++-------
+ 1 file changed, 27 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -75,6 +75,13 @@ struct mailbox_blank_display {
+ u32 blank;
+ };
+
++struct mailbox_get_width_height {
++ struct rpi_firmware_property_tag_header tag1;
++ u32 display;
++ struct rpi_firmware_property_tag_header tag2;
++ u32 wh[2];
++};
++
+ static const struct vc_image_format {
+ u32 drm; /* DRM_FORMAT_* */
+ u32 vc_image; /* VC_IMAGE_* */
+@@ -192,6 +199,7 @@ struct vc4_fkms_connector {
+ * hook.
+ */
+ struct drm_encoder *encoder;
++ u32 display_idx;
+ };
+
+ static inline struct vc4_fkms_connector *
+@@ -723,21 +731,27 @@ vc4_fkms_connector_detect(struct drm_con
+ static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
+ {
+ struct drm_device *dev = connector->dev;
++ struct vc4_fkms_connector *fkms_connector =
++ to_vc4_fkms_connector(connector);
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+- u32 wh[2] = {0, 0};
+- int ret;
+ struct drm_display_mode *mode;
++ struct mailbox_get_width_height wh = {
++ .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
++ .display = fkms_connector->display_idx,
++ .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT,
++ 8, 0, },
++ };
++ int ret;
++
++ ret = rpi_firmware_property_list(vc4->firmware, &wh, sizeof(wh));
+
+- 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]);
++ ret, wh.wh[0], wh.wh[1]);
+ return 0;
+ }
+
+- mode = drm_cvt_mode(dev, wh[0], wh[1], 60 /* vrefresh */,
++ mode = drm_cvt_mode(dev, wh.wh[0], wh.wh[1], 60 /* vrefresh */,
+ 0, 0, false);
+ drm_mode_probed_add(connector, mode);
+
+@@ -772,8 +786,9 @@ static const struct drm_connector_helper
+ .best_encoder = vc4_fkms_connector_best_encoder,
+ };
+
+-static struct drm_connector *vc4_fkms_connector_init(struct drm_device *dev,
+- struct drm_encoder *encoder)
++static struct drm_connector *
++vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
++ u32 display_idx)
+ {
+ struct drm_connector *connector = NULL;
+ struct vc4_fkms_connector *fkms_connector;
+@@ -788,6 +803,7 @@ static struct drm_connector *vc4_fkms_co
+ connector = &fkms_connector->base;
+
+ fkms_connector->encoder = encoder;
++ fkms_connector->display_idx = display_idx;
+
+ drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA);
+@@ -904,7 +920,8 @@ static int vc4_fkms_create_screen(struct
+ drm_encoder_helper_add(&vc4_encoder->base,
+ &vc4_fkms_encoder_helper_funcs);
+
+- vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base);
++ vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base,
++ display_idx);
+ if (IS_ERR(vc4_crtc->connector)) {
+ ret = PTR_ERR(vc4_crtc->connector);
+ goto err_destroy_encoder;
--- /dev/null
+From ed17deed1d56073de5733383e7897837e6f1e975 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 9 Apr 2019 18:14:44 +0100
+Subject: [PATCH 603/725] drm: vc4: Need to call drm_crtc_vblank_[on|off] from
+ vc4_crtc_[en|dis]able
+
+vblank needs to be enabled and disabled by the driver to avoid the
+DRM framework complaining in the kernel log.
+
+vc4_fkms_disable_vblank needs to signal that we don't want vblank
+callbacks too.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -562,6 +562,8 @@ static void vc4_crtc_mode_set_nofb(struc
+
+ static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+ {
++ drm_crtc_vblank_off(crtc);
++
+ /* Always turn the planes off on CRTC disable. In DRM, planes
+ * are enabled/disabled through the update/disable hooks
+ * above, and the CRTC enable/disable independently controls
+@@ -577,6 +579,7 @@ static void vc4_crtc_disable(struct drm_
+
+ static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+ {
++ drm_crtc_vblank_on(crtc);
+ /* Unblank the planes (if they're supposed to be displayed). */
+
+ if (crtc->primary->state->fb)
+@@ -673,6 +676,9 @@ static int vc4_fkms_enable_vblank(struct
+
+ static void vc4_fkms_disable_vblank(struct drm_crtc *crtc)
+ {
++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
++
++ vc4_crtc->vblank_enabled = false;
+ }
+
+ static const struct drm_crtc_funcs vc4_crtc_funcs = {
+++ /dev/null
-From 2ec4f853916551a57f574b988162b589e3331359 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 5 Apr 2019 17:23:15 +0100
-Subject: [PATCH 603/703] drm: vc4: Select display to blank during
- initialisation
-
-Otherwise the rainbow splash screen remained in the display list
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 18 ++++++++++++++----
- 1 file changed, 14 insertions(+), 4 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -87,6 +87,13 @@ struct fb_alloc_tags {
- u32 layer;
- };
-
-+struct mailbox_blank_display {
-+ struct rpi_firmware_property_tag_header tag1;
-+ u32 display;
-+ struct rpi_firmware_property_tag_header tag2;
-+ u32 blank;
-+};
-+
- static const struct vc_image_format {
- u32 drm; /* DRM_FORMAT_* */
- u32 vc_image; /* VC_IMAGE_* */
-@@ -854,7 +861,12 @@ static int vc4_fkms_create_screen(struct
- struct drm_crtc *crtc;
- struct drm_plane *primary_plane, *overlay_plane, *cursor_plane;
- struct drm_plane *destroy_plane, *temp;
-- u32 blank = 1;
-+ struct mailbox_blank_display blank = {
-+ .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
-+ .display = display_idx,
-+ .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_BLANK, 4, 0, },
-+ .blank = 1,
-+ };
- int ret;
-
- vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
-@@ -865,9 +877,7 @@ static int vc4_fkms_create_screen(struct
- vc4_crtc->display_number = display_ref;
-
- /* Blank the firmware provided framebuffer */
-- rpi_firmware_property(vc4->firmware,
-- RPI_FIRMWARE_FRAMEBUFFER_BLANK,
-- &blank, sizeof(blank));
-+ rpi_firmware_property_list(vc4->firmware, &blank, sizeof(blank));
-
- primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY,
- display_ref,
--- /dev/null
+From 566c87d4ab55a10a4a4c929e1ad00ddca2294af2 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 9 Apr 2019 17:19:51 +0100
+Subject: [PATCH 604/725] drm: vc4: Add support for H & V flips on each plane
+ for FKMS
+
+They are near zero cost options for the HVS, therefore they
+may as well be implemented, and it allows us to invert the
+DSI display.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 36 ++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -61,8 +61,21 @@ struct set_plane {
+ u8 padding;
+
+ u32 planes[4]; /* DMA address of each plane */
++
++ u32 transform;
+ };
+
++/* Values for the transform field */
++#define TRANSFORM_NO_ROTATE 0
++#define TRANSFORM_ROTATE_180 BIT(1)
++#define TRANSFORM_FLIP_HRIZ BIT(16)
++#define TRANSFORM_FLIP_VERT BIT(17)
++
++#define SUPPORTED_ROTATIONS (DRM_MODE_ROTATE_0 | \
++ DRM_MODE_ROTATE_180 | \
++ DRM_MODE_REFLECT_X | \
++ DRM_MODE_REFLECT_Y)
++
+ struct mailbox_set_plane {
+ struct rpi_firmware_property_tag_header tag;
+ struct set_plane plane;
+@@ -274,6 +287,7 @@ static void vc4_plane_atomic_update(stru
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
+ int num_planes = fb->format->num_planes;
+ struct drm_display_mode *mode = &state->crtc->mode;
++ unsigned int rotation = SUPPORTED_ROTATIONS;
+
+ mb->plane.vc_image_type = vc_fmt->vc_image;
+ mb->plane.width = fb->width;
+@@ -294,6 +308,24 @@ static void vc4_plane_atomic_update(stru
+ mb->plane.is_vu = vc_fmt->is_vu;
+ mb->plane.planes[0] = bo->paddr + fb->offsets[0];
+
++ rotation = drm_rotation_simplify(state->rotation, rotation);
++
++ switch (rotation) {
++ default:
++ case DRM_MODE_ROTATE_0:
++ mb->plane.transform = TRANSFORM_NO_ROTATE;
++ break;
++ case DRM_MODE_ROTATE_180:
++ mb->plane.transform = TRANSFORM_ROTATE_180;
++ break;
++ case DRM_MODE_REFLECT_X:
++ mb->plane.transform = TRANSFORM_FLIP_HRIZ;
++ break;
++ case DRM_MODE_REFLECT_Y:
++ mb->plane.transform = TRANSFORM_FLIP_VERT;
++ break;
++ }
++
+ /* FIXME: If the dest rect goes off screen then clip the src rect so we
+ * don't have off-screen pixels.
+ */
+@@ -514,9 +546,13 @@ static struct drm_plane *vc4_fkms_plane_
+ formats, num_formats, modifiers,
+ type, NULL);
+
++ /* FIXME: Do we need to be checking return values from all these calls?
++ */
+ drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
+
+ drm_plane_create_alpha_property(plane);
++ drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
++ SUPPORTED_ROTATIONS);
+
+ /*
+ * Default frame buffer setup is with FB on -127, and raspistill etc
+++ /dev/null
-From 8b4aa15c2c83d84b3f8e94412af3a03061c8878d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 5 Apr 2019 17:24:20 +0100
-Subject: [PATCH 604/703] drm: vc4: Remove now unused structure.
-
-Cleaning up structure that was unused after
-fbb59a2 drm: vc4: Add an overlay plane to vc4-firmware-kms
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 19 -------------------
- 1 file changed, 19 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -68,25 +68,6 @@ struct mailbox_set_plane {
- struct set_plane plane;
- };
-
--struct fb_alloc_tags {
-- struct rpi_firmware_property_tag_header tag1;
-- u32 xres, yres;
-- struct rpi_firmware_property_tag_header tag2;
-- u32 xres_virtual, yres_virtual;
-- struct rpi_firmware_property_tag_header tag3;
-- u32 bpp;
-- struct rpi_firmware_property_tag_header tag4;
-- u32 xoffset, yoffset;
-- struct rpi_firmware_property_tag_header tag5;
-- u32 base, screen_size;
-- struct rpi_firmware_property_tag_header tag6;
-- u32 pitch;
-- struct rpi_firmware_property_tag_header tag7;
-- u32 alpha_mode;
-- struct rpi_firmware_property_tag_header tag8;
-- u32 layer;
--};
--
- struct mailbox_blank_display {
- struct rpi_firmware_property_tag_header tag1;
- u32 display;
+++ /dev/null
-From 9b3747e9bdce9beb84bec50e7ad06af365e50173 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 9 Apr 2019 12:37:28 +0100
-Subject: [PATCH 605/703] drm: vc4: Query the display ID for each display in
- FKMS
-
-Replace the hard coded list of display IDs for a mailbox call
-that returns the display ID for each display that has been
-detected.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 16 +++++++++++++---
- include/soc/bcm2835/raspberrypi-firmware.h | 1 +
- 2 files changed, 14 insertions(+), 3 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -943,7 +943,7 @@ static int vc4_fkms_bind(struct device *
- struct vc4_crtc **crtc_list;
- u32 num_displays, display_num;
- int ret;
-- const u32 display_num_lookup[] = {2, 7, 1};
-+ u32 display_id;
-
- vc4->firmware_kms = true;
-
-@@ -982,8 +982,18 @@ static int vc4_fkms_bind(struct device *
- return -ENOMEM;
-
- for (display_num = 0; display_num < num_displays; display_num++) {
-- ret = vc4_fkms_create_screen(dev, drm, display_num,
-- display_num_lookup[display_num],
-+ display_id = display_num;
-+ ret = rpi_firmware_property(vc4->firmware,
-+ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID,
-+ &display_id, sizeof(display_id));
-+ /* FIXME: Determine the correct error handling here.
-+ * Should we fail to create the one "screen" but keep the
-+ * others, or fail the whole thing?
-+ */
-+ if (ret)
-+ DRM_ERROR("Failed to get display id %u\n", display_num);
-+
-+ ret = vc4_fkms_create_screen(dev, drm, display_num, display_id,
- &crtc_list[display_num]);
- if (ret)
- DRM_ERROR("Oh dear, failed to create display %u\n",
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -117,6 +117,7 @@ enum rpi_firmware_property_tag {
- RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f,
- RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
- RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001,
-+ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID = 0x00040016,
- RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM = 0x00048013,
- RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS = 0x00040013,
- RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS = 0x00040014,
--- /dev/null
+From e413b9a87e5b559fd66ff867333d64dedf95fe4c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 10 Apr 2019 17:35:05 +0100
+Subject: [PATCH 605/725] drm: vc4: Remove unused vc4_fkms_cancel_page_flip
+ function
+
+"32a3dbe drm/vc4: Nuke preclose hook" removed vc4_cancel_page_flip,
+but vc4_fkms_cancel_page_flip was still be added to with the
+fkms driver, even though it was never called.
+Nuke it too.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_drv.h | 1 -
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 20 --------------------
+ 2 files changed, 21 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_drv.h
++++ b/drivers/gpu/drm/vc4/vc4_drv.h
+@@ -724,7 +724,6 @@ extern const struct dma_fence_ops vc4_fe
+
+ /* 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);
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -739,26 +739,6 @@ static const struct drm_crtc_helper_func
+ .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" },
+ {}
--- /dev/null
+From 6196e905883945a65a8316d9d08725c6b64ec211 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 10 Apr 2019 17:42:37 +0100
+Subject: [PATCH 606/725] drm: vc4: Iterate over all planes in
+ vc4_crtc_[dis|en]able
+
+Fixes a FIXME where the overlay plane wouldn't be restored.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -598,6 +598,8 @@ static void vc4_crtc_mode_set_nofb(struc
+
+ static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+ {
++ struct drm_plane *plane;
++
+ drm_crtc_vblank_off(crtc);
+
+ /* Always turn the planes off on CRTC disable. In DRM, planes
+@@ -607,23 +609,23 @@ static void vc4_crtc_disable(struct drm_
+ * give us a CRTC-level control for that.
+ */
+
+- vc4_plane_atomic_disable(crtc->cursor, crtc->cursor->state);
+- vc4_plane_atomic_disable(crtc->primary, crtc->primary->state);
+-
+- /* FIXME: Disable overlay planes */
++ drm_atomic_crtc_for_each_plane(plane, crtc)
++ vc4_plane_atomic_disable(plane, plane->state);
+ }
+
+ static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+ {
++ struct drm_plane *plane;
++
+ drm_crtc_vblank_on(crtc);
++
+ /* Unblank the planes (if they're supposed to be displayed). */
++ drm_atomic_crtc_for_each_plane(plane, crtc)
++ if (plane->state->fb)
++ vc4_plane_set_blank(plane, plane->state->visible);
++}
+
+- if (crtc->primary->state->fb)
+- vc4_plane_set_blank(crtc->primary, false);
+- if (crtc->cursor->state->fb)
+- vc4_plane_set_blank(crtc->cursor, crtc->cursor->state);
+
+- /* FIXME: Enable overlay planes */
+ }
+
+ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
+++ /dev/null
-From d00d0711df4da66465ba5086e99c5936ea3b9577 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 9 Apr 2019 14:00:07 +0100
-Subject: [PATCH 606/703] drm/vc4: Set the display number when querying the
- display resolution
-
-Without this the two displays got set to the same resolution.
-(Requires a firmware bug fix to work).
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 37 +++++++++++++++++++-------
- 1 file changed, 27 insertions(+), 10 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -75,6 +75,13 @@ struct mailbox_blank_display {
- u32 blank;
- };
-
-+struct mailbox_get_width_height {
-+ struct rpi_firmware_property_tag_header tag1;
-+ u32 display;
-+ struct rpi_firmware_property_tag_header tag2;
-+ u32 wh[2];
-+};
-+
- static const struct vc_image_format {
- u32 drm; /* DRM_FORMAT_* */
- u32 vc_image; /* VC_IMAGE_* */
-@@ -192,6 +199,7 @@ struct vc4_fkms_connector {
- * hook.
- */
- struct drm_encoder *encoder;
-+ u32 display_idx;
- };
-
- static inline struct vc4_fkms_connector *
-@@ -723,21 +731,27 @@ vc4_fkms_connector_detect(struct drm_con
- static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
- {
- struct drm_device *dev = connector->dev;
-+ struct vc4_fkms_connector *fkms_connector =
-+ to_vc4_fkms_connector(connector);
- struct vc4_dev *vc4 = to_vc4_dev(dev);
-- u32 wh[2] = {0, 0};
-- int ret;
- struct drm_display_mode *mode;
-+ struct mailbox_get_width_height wh = {
-+ .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
-+ .display = fkms_connector->display_idx,
-+ .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT,
-+ 8, 0, },
-+ };
-+ int ret;
-+
-+ ret = rpi_firmware_property_list(vc4->firmware, &wh, sizeof(wh));
-
-- 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]);
-+ ret, wh.wh[0], wh.wh[1]);
- return 0;
- }
-
-- mode = drm_cvt_mode(dev, wh[0], wh[1], 60 /* vrefresh */,
-+ mode = drm_cvt_mode(dev, wh.wh[0], wh.wh[1], 60 /* vrefresh */,
- 0, 0, false);
- drm_mode_probed_add(connector, mode);
-
-@@ -772,8 +786,9 @@ static const struct drm_connector_helper
- .best_encoder = vc4_fkms_connector_best_encoder,
- };
-
--static struct drm_connector *vc4_fkms_connector_init(struct drm_device *dev,
-- struct drm_encoder *encoder)
-+static struct drm_connector *
-+vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
-+ u32 display_idx)
- {
- struct drm_connector *connector = NULL;
- struct vc4_fkms_connector *fkms_connector;
-@@ -788,6 +803,7 @@ static struct drm_connector *vc4_fkms_co
- connector = &fkms_connector->base;
-
- fkms_connector->encoder = encoder;
-+ fkms_connector->display_idx = display_idx;
-
- drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
- DRM_MODE_CONNECTOR_HDMIA);
-@@ -904,7 +920,8 @@ static int vc4_fkms_create_screen(struct
- drm_encoder_helper_add(&vc4_encoder->base,
- &vc4_fkms_encoder_helper_funcs);
-
-- vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base);
-+ vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base,
-+ display_idx);
- if (IS_ERR(vc4_crtc->connector)) {
- ret = PTR_ERR(vc4_crtc->connector);
- goto err_destroy_encoder;
--- /dev/null
+From fc819de185dd2a0c7ff1846ee3ec64668f9163cc Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 10 Apr 2019 17:43:57 +0100
+Subject: [PATCH 607/725] drm: vc4: Bring fkms into line with kms in blocking
+ doublescan modes
+
+Implement vc4_crtc_mode_valid so that it blocks doublescan modes
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -625,7 +625,17 @@ static void vc4_crtc_enable(struct drm_c
+ vc4_plane_set_blank(plane, plane->state->visible);
+ }
+
++static enum drm_mode_status
++vc4_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
++{
++ /* Do not allow doublescan modes from user space */
++ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
++ DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n",
++ crtc->base.id);
++ return MODE_NO_DBLESCAN;
++ }
+
++ return MODE_OK;
+ }
+
+ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
+@@ -735,10 +745,11 @@ static const struct drm_crtc_funcs vc4_c
+
+ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
+ .mode_set_nofb = vc4_crtc_mode_set_nofb,
+- .atomic_disable = vc4_crtc_disable,
+- .atomic_enable = vc4_crtc_enable,
++ .mode_valid = vc4_crtc_mode_valid,
+ .atomic_check = vc4_crtc_atomic_check,
+ .atomic_flush = vc4_crtc_atomic_flush,
++ .atomic_enable = vc4_crtc_enable,
++ .atomic_disable = vc4_crtc_disable,
+ };
+
+ static const struct of_device_id vc4_firmware_kms_dt_match[] = {
+++ /dev/null
-From 7129a308f4716a416f3e0fdd5f565457ed3bde03 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 9 Apr 2019 18:14:44 +0100
-Subject: [PATCH 607/703] drm: vc4: Need to call drm_crtc_vblank_[on|off] from
- vc4_crtc_[en|dis]able
-
-vblank needs to be enabled and disabled by the driver to avoid the
-DRM framework complaining in the kernel log.
-
-vc4_fkms_disable_vblank needs to signal that we don't want vblank
-callbacks too.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -562,6 +562,8 @@ static void vc4_crtc_mode_set_nofb(struc
-
- static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
- {
-+ drm_crtc_vblank_off(crtc);
-+
- /* Always turn the planes off on CRTC disable. In DRM, planes
- * are enabled/disabled through the update/disable hooks
- * above, and the CRTC enable/disable independently controls
-@@ -577,6 +579,7 @@ static void vc4_crtc_disable(struct drm_
-
- static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
- {
-+ drm_crtc_vblank_on(crtc);
- /* Unblank the planes (if they're supposed to be displayed). */
-
- if (crtc->primary->state->fb)
-@@ -673,6 +676,9 @@ static int vc4_fkms_enable_vblank(struct
-
- static void vc4_fkms_disable_vblank(struct drm_crtc *crtc)
- {
-+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-+
-+ vc4_crtc->vblank_enabled = false;
- }
-
- static const struct drm_crtc_funcs vc4_crtc_funcs = {
+++ /dev/null
-From 9887c3c6ada2620592687b520e778980bc32c256 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 9 Apr 2019 17:19:51 +0100
-Subject: [PATCH 608/703] drm: vc4: Add support for H & V flips on each plane
- for FKMS
-
-They are near zero cost options for the HVS, therefore they
-may as well be implemented, and it allows us to invert the
-DSI display.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 36 ++++++++++++++++++++++++++
- 1 file changed, 36 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -61,8 +61,21 @@ struct set_plane {
- u8 padding;
-
- u32 planes[4]; /* DMA address of each plane */
-+
-+ u32 transform;
- };
-
-+/* Values for the transform field */
-+#define TRANSFORM_NO_ROTATE 0
-+#define TRANSFORM_ROTATE_180 BIT(1)
-+#define TRANSFORM_FLIP_HRIZ BIT(16)
-+#define TRANSFORM_FLIP_VERT BIT(17)
-+
-+#define SUPPORTED_ROTATIONS (DRM_MODE_ROTATE_0 | \
-+ DRM_MODE_ROTATE_180 | \
-+ DRM_MODE_REFLECT_X | \
-+ DRM_MODE_REFLECT_Y)
-+
- struct mailbox_set_plane {
- struct rpi_firmware_property_tag_header tag;
- struct set_plane plane;
-@@ -274,6 +287,7 @@ static void vc4_plane_atomic_update(stru
- struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
- int num_planes = fb->format->num_planes;
- struct drm_display_mode *mode = &state->crtc->mode;
-+ unsigned int rotation = SUPPORTED_ROTATIONS;
-
- mb->plane.vc_image_type = vc_fmt->vc_image;
- mb->plane.width = fb->width;
-@@ -294,6 +308,24 @@ static void vc4_plane_atomic_update(stru
- mb->plane.is_vu = vc_fmt->is_vu;
- mb->plane.planes[0] = bo->paddr + fb->offsets[0];
-
-+ rotation = drm_rotation_simplify(state->rotation, rotation);
-+
-+ switch (rotation) {
-+ default:
-+ case DRM_MODE_ROTATE_0:
-+ mb->plane.transform = TRANSFORM_NO_ROTATE;
-+ break;
-+ case DRM_MODE_ROTATE_180:
-+ mb->plane.transform = TRANSFORM_ROTATE_180;
-+ break;
-+ case DRM_MODE_REFLECT_X:
-+ mb->plane.transform = TRANSFORM_FLIP_HRIZ;
-+ break;
-+ case DRM_MODE_REFLECT_Y:
-+ mb->plane.transform = TRANSFORM_FLIP_VERT;
-+ break;
-+ }
-+
- /* FIXME: If the dest rect goes off screen then clip the src rect so we
- * don't have off-screen pixels.
- */
-@@ -514,9 +546,13 @@ static struct drm_plane *vc4_fkms_plane_
- formats, num_formats, modifiers,
- type, NULL);
-
-+ /* FIXME: Do we need to be checking return values from all these calls?
-+ */
- drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
-
- drm_plane_create_alpha_property(plane);
-+ drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
-+ SUPPORTED_ROTATIONS);
-
- /*
- * Default frame buffer setup is with FB on -127, and raspistill etc
--- /dev/null
+From f47b844c77068b837566f74e8872972ef880f834 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 29 Apr 2019 18:45:00 +0100
+Subject: [PATCH 608/725] drm: vc4: Increase max_width/height to 7680.
+
+There are some limits still being investigated that stop
+us going up to 8192, but 7680 is sufficient for dual 4k
+displays.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_kms.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -429,8 +429,8 @@ int vc4_kms_load(struct drm_device *dev)
+ return ret;
+ }
+
+- dev->mode_config.max_width = 4096;
+- dev->mode_config.max_height = 4096;
++ dev->mode_config.max_width = 7680;
++ dev->mode_config.max_height = 7680;
+ dev->mode_config.funcs = &vc4_mode_funcs;
+ dev->mode_config.preferred_depth = 24;
+ dev->mode_config.async_page_flip = true;
--- /dev/null
+From bd09766537994059c1d4a20762a6552dc0a62dae Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 9 Apr 2019 18:23:41 +0100
+Subject: [PATCH 609/725] drm: vc4: FKMS reads the EDID from fw, and supports
+ mode setting
+
+This extends FKMS to read the EDID from the display, and support
+requesting a particular mode via KMS.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 334 ++++++++++++++++++---
+ include/soc/bcm2835/raspberrypi-firmware.h | 2 +
+ 2 files changed, 302 insertions(+), 34 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -88,11 +88,60 @@ struct mailbox_blank_display {
+ u32 blank;
+ };
+
+-struct mailbox_get_width_height {
++struct mailbox_get_edid {
+ struct rpi_firmware_property_tag_header tag1;
+- u32 display;
+- struct rpi_firmware_property_tag_header tag2;
+- u32 wh[2];
++ u32 block;
++ u32 display_number;
++ u8 edid[128];
++};
++
++struct set_timings {
++ u8 display;
++ u8 padding;
++ u16 video_id_code;
++
++ u32 clock; /* in kHz */
++
++ u16 hdisplay;
++ u16 hsync_start;
++
++ u16 hsync_end;
++ u16 htotal;
++
++ u16 hskew;
++ u16 vdisplay;
++
++ u16 vsync_start;
++ u16 vsync_end;
++
++ u16 vtotal;
++ u16 vscan;
++
++ u16 vrefresh;
++ u16 padding2;
++
++ u32 flags;
++#define TIMINGS_FLAGS_H_SYNC_POS BIT(0)
++#define TIMINGS_FLAGS_H_SYNC_NEG 0
++#define TIMINGS_FLAGS_V_SYNC_POS BIT(1)
++#define TIMINGS_FLAGS_V_SYNC_NEG 0
++
++#define TIMINGS_FLAGS_ASPECT_MASK GENMASK(7, 4)
++#define TIMINGS_FLAGS_ASPECT_NONE (0 << 4)
++#define TIMINGS_FLAGS_ASPECT_4_3 (1 << 4)
++#define TIMINGS_FLAGS_ASPECT_16_9 (2 << 4)
++#define TIMINGS_FLAGS_ASPECT_64_27 (3 << 4)
++#define TIMINGS_FLAGS_ASPECT_256_135 (4 << 4)
++
++/* Limited range RGB flag. Not set corresponds to full range. */
++#define TIMINGS_FLAGS_RGB_LIMITED BIT(8)
++/* DVI monitor, therefore disable infoframes. Not set corresponds to HDMI. */
++#define TIMINGS_FLAGS_DVI BIT(9)
++};
++
++struct mailbox_set_mode {
++ struct rpi_firmware_property_tag_header tag1;
++ struct set_timings timings;
+ };
+
+ static const struct vc_image_format {
+@@ -186,6 +235,7 @@ struct vc4_crtc {
+ u32 overscan[4];
+ bool vblank_enabled;
+ u32 display_number;
++ u32 display_type;
+ };
+
+ static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc)
+@@ -195,6 +245,8 @@ static inline struct vc4_crtc *to_vc4_cr
+
+ struct vc4_fkms_encoder {
+ struct drm_encoder base;
++ bool hdmi_monitor;
++ bool rgb_range_selectable;
+ };
+
+ static inline struct vc4_fkms_encoder *
+@@ -212,7 +264,9 @@ struct vc4_fkms_connector {
+ * hook.
+ */
+ struct drm_encoder *encoder;
+- u32 display_idx;
++ struct vc4_dev *vc4_dev;
++ u32 display_number;
++ u32 display_type;
+ };
+
+ static inline struct vc4_fkms_connector *
+@@ -221,6 +275,26 @@ to_vc4_fkms_connector(struct drm_connect
+ return container_of(connector, struct vc4_fkms_connector, base);
+ }
+
++static u32 vc4_get_display_type(u32 display_number)
++{
++ const u32 display_types[] = {
++ /* The firmware display (DispmanX) IDs map to specific types in
++ * a fixed manner.
++ */
++ DRM_MODE_ENCODER_DSI, /* MAIN_LCD */
++ DRM_MODE_ENCODER_DSI, /* AUX_LCD */
++ DRM_MODE_ENCODER_TMDS, /* HDMI0 */
++ DRM_MODE_ENCODER_TVDAC, /* VEC */
++ DRM_MODE_ENCODER_NONE, /* FORCE_LCD */
++ DRM_MODE_ENCODER_NONE, /* FORCE_TV */
++ DRM_MODE_ENCODER_NONE, /* FORCE_OTHER */
++ DRM_MODE_ENCODER_TMDS, /* HDMI1 */
++ DRM_MODE_ENCODER_NONE, /* FORCE_TV2 */
++ };
++ return display_number > ARRAY_SIZE(display_types) - 1 ?
++ DRM_MODE_ENCODER_NONE : display_types[display_number];
++}
++
+ /* Firmware's structure for making an FB mbox call. */
+ struct fbinfo_s {
+ u32 xres, yres, xres_virtual, yres_virtual;
+@@ -255,10 +329,15 @@ static int vc4_plane_set_blank(struct dr
+ .plane_id = vc4_plane->mb.plane.plane_id,
+ }
+ };
++ static const char * const plane_types[] = {
++ "overlay",
++ "primary",
++ "cursor"
++ };
+ int ret;
+
+- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] overlay plane %s",
+- plane->base.id, plane->name,
++ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] %s plane %s",
++ plane->base.id, plane->name, plane_types[plane->type],
+ blank ? "blank" : "unblank");
+
+ if (blank)
+@@ -593,13 +672,102 @@ fail:
+
+ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
+ {
+- /* Everyting is handled in the planes. */
++ struct drm_device *dev = crtc->dev;
++ struct vc4_dev *vc4 = to_vc4_dev(dev);
++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
++ struct drm_display_mode *mode = &crtc->state->adjusted_mode;
++ struct vc4_fkms_encoder *vc4_encoder =
++ to_vc4_fkms_encoder(vc4_crtc->encoder);
++ struct mailbox_set_mode mb = {
++ .tag1 = { RPI_FIRMWARE_SET_TIMING,
++ sizeof(struct set_timings), 0},
++ };
++ union hdmi_infoframe frame;
++ int ret;
++
++ ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
++ if (ret < 0) {
++ DRM_ERROR("couldn't fill AVI infoframe\n");
++ return;
++ }
++
++ DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u\n",
++ vc4_crtc->display_number, mode->name, mode->clock,
++ mode->hdisplay, mode->hsync_start, mode->hsync_end,
++ mode->htotal, mode->hskew, mode->vdisplay,
++ mode->vsync_start, mode->vsync_end, mode->vtotal,
++ mode->vscan, mode->vrefresh, mode->picture_aspect_ratio);
++ mb.timings.display = vc4_crtc->display_number;
++
++ mb.timings.video_id_code = frame.avi.video_code;
++
++ mb.timings.clock = mode->clock;
++ mb.timings.hdisplay = mode->hdisplay;
++ mb.timings.hsync_start = mode->hsync_start;
++ mb.timings.hsync_end = mode->hsync_end;
++ mb.timings.htotal = mode->htotal;
++ mb.timings.hskew = mode->hskew;
++ mb.timings.vdisplay = mode->vdisplay;
++ mb.timings.vsync_start = mode->vsync_start;
++ mb.timings.vsync_end = mode->vsync_end;
++ mb.timings.vtotal = mode->vtotal;
++ mb.timings.vscan = mode->vscan;
++ mb.timings.vrefresh = 0;
++ mb.timings.flags = 0;
++ if (mode->flags & DRM_MODE_FLAG_PHSYNC)
++ mb.timings.flags |= TIMINGS_FLAGS_H_SYNC_POS;
++ if (mode->flags & DRM_MODE_FLAG_PVSYNC)
++ mb.timings.flags |= TIMINGS_FLAGS_V_SYNC_POS;
++
++ switch (frame.avi.picture_aspect) {
++ default:
++ case HDMI_PICTURE_ASPECT_NONE:
++ mode->flags |= TIMINGS_FLAGS_ASPECT_NONE;
++ break;
++ case HDMI_PICTURE_ASPECT_4_3:
++ mode->flags |= TIMINGS_FLAGS_ASPECT_4_3;
++ break;
++ case HDMI_PICTURE_ASPECT_16_9:
++ mode->flags |= TIMINGS_FLAGS_ASPECT_16_9;
++ break;
++ case HDMI_PICTURE_ASPECT_64_27:
++ mode->flags |= TIMINGS_FLAGS_ASPECT_64_27;
++ break;
++ case HDMI_PICTURE_ASPECT_256_135:
++ mode->flags |= TIMINGS_FLAGS_ASPECT_256_135;
++ break;
++ }
++
++ if (!vc4_encoder->hdmi_monitor)
++ mb.timings.flags |= TIMINGS_FLAGS_DVI;
++ else if (drm_default_rgb_quant_range(mode) ==
++ HDMI_QUANTIZATION_RANGE_LIMITED)
++ mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
++
++ /*
++ FIXME: To implement
++ switch(mode->flag & DRM_MODE_FLAG_3D_MASK) {
++ case DRM_MODE_FLAG_3D_NONE:
++ case DRM_MODE_FLAG_3D_FRAME_PACKING:
++ case DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE:
++ case DRM_MODE_FLAG_3D_LINE_ALTERNATIVE:
++ case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL:
++ case DRM_MODE_FLAG_3D_L_DEPTH:
++ case DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH:
++ case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM:
++ case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF:
++ }
++ */
++
++ ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
+ }
+
+ static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+ {
+ struct drm_plane *plane;
+
++ DRM_DEBUG_KMS("[CRTC:%d] vblanks off.\n",
++ crtc->base.id);
+ drm_crtc_vblank_off(crtc);
+
+ /* Always turn the planes off on CRTC disable. In DRM, planes
+@@ -617,6 +785,8 @@ static void vc4_crtc_enable(struct drm_c
+ {
+ struct drm_plane *plane;
+
++ DRM_DEBUG_KMS("[CRTC:%d] vblanks on.\n",
++ crtc->base.id);
+ drm_crtc_vblank_on(crtc);
+
+ /* Unblank the planes (if they're supposed to be displayed). */
+@@ -635,12 +805,20 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
+ return MODE_NO_DBLESCAN;
+ }
+
++ /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
++ * working.
++ */
++ if (mode->clock > 340000)
++ return MODE_CLOCK_HIGH;
++
+ return MODE_OK;
+ }
+
+ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+ {
++ DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_check.\n",
++ crtc->base.id);
+ return 0;
+ }
+
+@@ -650,6 +828,8 @@ static void vc4_crtc_atomic_flush(struct
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+
++ DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_flush.\n",
++ crtc->base.id);
+ if (crtc->state->event) {
+ unsigned long flags;
+
+@@ -717,6 +897,8 @@ static int vc4_fkms_enable_vblank(struct
+ {
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
++ DRM_DEBUG_KMS("[CRTC:%d] enable_vblank.\n",
++ crtc->base.id);
+ vc4_crtc->vblank_enabled = true;
+
+ return 0;
+@@ -726,6 +908,8 @@ static void vc4_fkms_disable_vblank(stru
+ {
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
++ DRM_DEBUG_KMS("[CRTC:%d] disable_vblank.\n",
++ crtc->base.id);
+ vc4_crtc->vblank_enabled = false;
+ }
+
+@@ -760,36 +944,92 @@ static const struct of_device_id vc4_fir
+ static enum drm_connector_status
+ vc4_fkms_connector_detect(struct drm_connector *connector, bool force)
+ {
++ DRM_DEBUG_KMS("connector detect.\n");
+ return connector_status_connected;
+ }
+
+-static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
++static int vc4_fkms_get_edid_block(void *data, u8 *buf, unsigned int block,
++ size_t len)
+ {
+- struct drm_device *dev = connector->dev;
+ struct vc4_fkms_connector *fkms_connector =
+- to_vc4_fkms_connector(connector);
+- struct vc4_dev *vc4 = to_vc4_dev(dev);
+- struct drm_display_mode *mode;
+- struct mailbox_get_width_height wh = {
+- .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
+- .display = fkms_connector->display_idx,
+- .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT,
+- 8, 0, },
++ (struct vc4_fkms_connector *)data;
++ struct vc4_dev *vc4 = fkms_connector->vc4_dev;
++ struct mailbox_get_edid mb = {
++ .tag1 = { RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY,
++ 128 + 8, 0 },
++ .block = block,
++ .display_number = fkms_connector->display_number,
+ };
+- int ret;
++ int ret = 0;
++
++ ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
++
++ if (!ret)
++ memcpy(buf, mb.edid, len);
++
++ return ret;
++}
++
++static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
++{
++ struct vc4_fkms_connector *fkms_connector =
++ to_vc4_fkms_connector(connector);
++ struct drm_encoder *encoder = fkms_connector->encoder;
++ struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
++ int ret = 0;
++ struct edid *edid;
++
++ edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block,
++ fkms_connector);
++
++ /* FIXME: Can we do CEC?
++ * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
++ * if (!edid)
++ * return -ENODEV;
++ */
++
++ vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
+
+- ret = rpi_firmware_property_list(vc4->firmware, &wh, sizeof(wh));
++ if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
++ vc4_encoder->rgb_range_selectable =
++ drm_rgb_quant_range_selectable(edid);
++ }
++
++ drm_connector_update_edid_property(connector, edid);
++ ret = drm_add_edid_modes(connector, edid);
++ kfree(edid);
++
++ return ret;
++}
++
++/* FIXME: Read LCD mode from the firmware. This is the DSI panel resolution. */
++static const struct drm_display_mode lcd_mode = {
++ DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
++ 25979400 / 1000,
++ 800, 800 + 1, 800 + 1 + 2, 800 + 1 + 2 + 46, 0,
++ 480, 480 + 7, 480 + 7 + 2, 480 + 7 + 2 + 21, 0,
++ DRM_MODE_FLAG_INTERLACE)
++};
++
++static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
++{
++ //struct vc4_fkms_connector *fkms_connector =
++ // to_vc4_fkms_connector(connector);
++ //struct drm_encoder *encoder = fkms_connector->encoder;
++ //struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
++ struct drm_display_mode *mode;
++ //int ret = 0;
+
+- if (ret) {
+- DRM_ERROR("Failed to get screen size: %d (0x%08x 0x%08x)\n",
+- ret, wh.wh[0], wh.wh[1]);
+- return 0;
++ mode = drm_mode_duplicate(connector->dev,
++ &lcd_mode);
++ if (!mode) {
++ DRM_ERROR("Failed to create a new display mode\n");
++ return -ENOMEM;
+ }
+
+- mode = drm_cvt_mode(dev, wh.wh[0], wh.wh[1], 60 /* vrefresh */,
+- 0, 0, false);
+ drm_mode_probed_add(connector, mode);
+
++ /* We have one mode */
+ return 1;
+ }
+
+@@ -798,11 +1038,14 @@ vc4_fkms_connector_best_encoder(struct d
+ {
+ struct vc4_fkms_connector *fkms_connector =
+ to_vc4_fkms_connector(connector);
++ DRM_DEBUG_KMS("best_connector.\n");
+ return fkms_connector->encoder;
+ }
+
+ static void vc4_fkms_connector_destroy(struct drm_connector *connector)
+ {
++ DRM_DEBUG_KMS("[CONNECTOR:%d] destroy.\n",
++ connector->base.id);
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+ }
+@@ -821,14 +1064,22 @@ static const struct drm_connector_helper
+ .best_encoder = vc4_fkms_connector_best_encoder,
+ };
+
++static const struct drm_connector_helper_funcs vc4_fkms_lcd_conn_helper_funcs = {
++ .get_modes = vc4_fkms_lcd_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,
+- u32 display_idx)
++ u32 display_num)
+ {
+ struct drm_connector *connector = NULL;
+ struct vc4_fkms_connector *fkms_connector;
++ struct vc4_dev *vc4_dev = to_vc4_dev(dev);
+ int ret = 0;
+
++ DRM_DEBUG_KMS("connector_init, display_num %u\n", display_num);
++
+ fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector),
+ GFP_KERNEL);
+ if (!fkms_connector) {
+@@ -838,11 +1089,21 @@ vc4_fkms_connector_init(struct drm_devic
+ connector = &fkms_connector->base;
+
+ fkms_connector->encoder = encoder;
+- fkms_connector->display_idx = display_idx;
+-
+- drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
+- DRM_MODE_CONNECTOR_HDMIA);
+- drm_connector_helper_add(connector, &vc4_fkms_connector_helper_funcs);
++ fkms_connector->display_number = display_num;
++ fkms_connector->display_type = vc4_get_display_type(display_num);
++ fkms_connector->vc4_dev = vc4_dev;
++
++ if (fkms_connector->display_type == DRM_MODE_ENCODER_DSI) {
++ drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
++ DRM_MODE_CONNECTOR_DSI);
++ drm_connector_helper_add(connector,
++ &vc4_fkms_lcd_conn_helper_funcs);
++ } else {
++ 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);
+@@ -863,6 +1124,7 @@ vc4_fkms_connector_init(struct drm_devic
+
+ static void vc4_fkms_encoder_destroy(struct drm_encoder *encoder)
+ {
++ DRM_DEBUG_KMS("Encoder_destroy\n");
+ drm_encoder_cleanup(encoder);
+ }
+
+@@ -872,10 +1134,12 @@ static const struct drm_encoder_funcs vc
+
+ static void vc4_fkms_encoder_enable(struct drm_encoder *encoder)
+ {
++ DRM_DEBUG_KMS("Encoder_enable\n");
+ }
+
+ static void vc4_fkms_encoder_disable(struct drm_encoder *encoder)
+ {
++ DRM_DEBUG_KMS("Encoder_disable\n");
+ }
+
+ static const struct drm_encoder_helper_funcs vc4_fkms_encoder_helper_funcs = {
+@@ -907,6 +1171,7 @@ static int vc4_fkms_create_screen(struct
+ crtc = &vc4_crtc->base;
+
+ vc4_crtc->display_number = display_ref;
++ vc4_crtc->display_type = vc4_get_display_type(display_ref);
+
+ /* Blank the firmware provided framebuffer */
+ rpi_firmware_property_list(vc4->firmware, &blank, sizeof(blank));
+@@ -950,13 +1215,14 @@ static int vc4_fkms_create_screen(struct
+ 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);
++ vc4_crtc->display_type, NULL);
+ drm_encoder_helper_add(&vc4_encoder->base,
+ &vc4_fkms_encoder_helper_funcs);
+
+ vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base,
+- display_idx);
++ display_ref);
+ if (IS_ERR(vc4_crtc->connector)) {
+ ret = PTR_ERR(vc4_crtc->connector);
+ goto err_destroy_encoder;
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -78,6 +78,7 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014,
+ RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020,
+ RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021,
++ RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY = 0x00030023,
+ RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030,
+ RPI_FIRMWARE_GET_THROTTLED = 0x00030046,
+ RPI_FIRMWARE_GET_CLOCK_MEASURED = 0x00030047,
+@@ -150,6 +151,7 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
+
+ RPI_FIRMWARE_SET_PLANE = 0x00048015,
++ RPI_FIRMWARE_SET_TIMING = 0x00048017,
+
+ RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
+ RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,
+++ /dev/null
-From 335909eb24aba8b42738895ae2fe7d24c67ec466 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 10 Apr 2019 17:35:05 +0100
-Subject: [PATCH 609/703] drm: vc4: Remove unused vc4_fkms_cancel_page_flip
- function
-
-"32a3dbe drm/vc4: Nuke preclose hook" removed vc4_cancel_page_flip,
-but vc4_fkms_cancel_page_flip was still be added to with the
-fkms driver, even though it was never called.
-Nuke it too.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_drv.h | 1 -
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 20 --------------------
- 2 files changed, 21 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_drv.h
-+++ b/drivers/gpu/drm/vc4/vc4_drv.h
-@@ -724,7 +724,6 @@ extern const struct dma_fence_ops vc4_fe
-
- /* 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);
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -739,26 +739,6 @@ static const struct drm_crtc_helper_func
- .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" },
- {}
--- /dev/null
+From acf164cd389fb272e51d90a381927e9bca67a113 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 2 May 2019 15:11:05 -0700
+Subject: [PATCH 610/725] clk: bcm2835: Add support for setting leaf clock
+ rates while running.
+
+As long as you wait for !BUSY, you can do glitch-free updates of clock
+rate while the clock is running.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 22 +++++++++++++---------
+ 1 file changed, 13 insertions(+), 9 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1097,15 +1097,19 @@ static int bcm2835_clock_set_rate(struct
+
+ spin_lock(&cprman->regs_lock);
+
+- /*
+- * Setting up frac support
+- *
+- * In principle it is recommended to stop/start the clock first,
+- * but as we set CLK_SET_RATE_GATE during registration of the
+- * clock this requirement should be take care of by the
+- * clk-framework.
++ ctl = cprman_read(cprman, data->ctl_reg);
++
++ /* If the clock is running, we have to pause clock generation while
++ * updating the control and div regs. This is glitchless (no clock
++ * signals generated faster than the rate) but each reg access is two
++ * OSC cycles so the clock will slow down for a moment.
+ */
+- ctl = cprman_read(cprman, data->ctl_reg) & ~CM_FRAC;
++ if (ctl & CM_ENABLE) {
++ cprman_write(cprman, data->ctl_reg, ctl & ~CM_ENABLE);
++ bcm2835_clock_wait_busy(clock);
++ }
++
++ ctl &= ~CM_FRAC;
+ ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
+ cprman_write(cprman, data->ctl_reg, ctl);
+
+@@ -1475,7 +1479,7 @@ static struct clk_hw *bcm2835_register_c
+ init.ops = &bcm2835_vpu_clock_clk_ops;
+ } else {
+ init.ops = &bcm2835_clock_clk_ops;
+- init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
++ init.flags |= CLK_SET_PARENT_GATE;
+
+ /* If the clock wasn't actually enabled at boot, it's not
+ * critical.
+++ /dev/null
-From 1aadf149d0be5b0cab5425845a21cbfd35618119 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 10 Apr 2019 17:42:37 +0100
-Subject: [PATCH 610/703] drm: vc4: Iterate over all planes in
- vc4_crtc_[dis|en]able
-
-Fixes a FIXME where the overlay plane wouldn't be restored.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 20 +++++++++++---------
- 1 file changed, 11 insertions(+), 9 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -598,6 +598,8 @@ static void vc4_crtc_mode_set_nofb(struc
-
- static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
- {
-+ struct drm_plane *plane;
-+
- drm_crtc_vblank_off(crtc);
-
- /* Always turn the planes off on CRTC disable. In DRM, planes
-@@ -607,23 +609,23 @@ static void vc4_crtc_disable(struct drm_
- * give us a CRTC-level control for that.
- */
-
-- vc4_plane_atomic_disable(crtc->cursor, crtc->cursor->state);
-- vc4_plane_atomic_disable(crtc->primary, crtc->primary->state);
--
-- /* FIXME: Disable overlay planes */
-+ drm_atomic_crtc_for_each_plane(plane, crtc)
-+ vc4_plane_atomic_disable(plane, plane->state);
- }
-
- static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
- {
-+ struct drm_plane *plane;
-+
- drm_crtc_vblank_on(crtc);
-+
- /* Unblank the planes (if they're supposed to be displayed). */
-+ drm_atomic_crtc_for_each_plane(plane, crtc)
-+ if (plane->state->fb)
-+ vc4_plane_set_blank(plane, plane->state->visible);
-+}
-
-- if (crtc->primary->state->fb)
-- vc4_plane_set_blank(crtc->primary, false);
-- if (crtc->cursor->state->fb)
-- vc4_plane_set_blank(crtc->cursor, crtc->cursor->state);
-
-- /* FIXME: Enable overlay planes */
- }
-
- static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
--- /dev/null
+From 356d46e6eb84700f12fa2d0a56c5c60dddbed67a Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 2 May 2019 15:24:04 -0700
+Subject: [PATCH 611/725] clk: bcm2835: Allow reparenting leaf clocks while
+ they're running.
+
+This falls under the same "we can reprogram glitch-free as long as we
+pause generation" rule as updating the div/frac fields. This can be
+used for runtime reclocking of V3D to manage power leakage.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1086,8 +1086,10 @@ static int bcm2835_clock_on(struct clk_h
+ return 0;
+ }
+
+-static int bcm2835_clock_set_rate(struct clk_hw *hw,
+- unsigned long rate, unsigned long parent_rate)
++static int bcm2835_clock_set_rate_and_parent(struct clk_hw *hw,
++ unsigned long rate,
++ unsigned long parent_rate,
++ u8 parent)
+ {
+ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+ struct bcm2835_cprman *cprman = clock->cprman;
+@@ -1109,6 +1111,11 @@ static int bcm2835_clock_set_rate(struct
+ bcm2835_clock_wait_busy(clock);
+ }
+
++ if (parent != 0xff) {
++ ctl &= ~(CM_SRC_MASK << CM_SRC_SHIFT);
++ ctl |= parent << CM_SRC_SHIFT;
++ }
++
+ ctl &= ~CM_FRAC;
+ ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
+ cprman_write(cprman, data->ctl_reg, ctl);
+@@ -1120,6 +1127,12 @@ static int bcm2835_clock_set_rate(struct
+ return 0;
+ }
+
++static int bcm2835_clock_set_rate(struct clk_hw *hw,
++ unsigned long rate, unsigned long parent_rate)
++{
++ return bcm2835_clock_set_rate_and_parent(hw, rate, parent_rate, 0xff);
++}
++
+ static bool
+ bcm2835_clk_is_pllc(struct clk_hw *hw)
+ {
+@@ -1303,6 +1316,7 @@ static const struct clk_ops bcm2835_cloc
+ .unprepare = bcm2835_clock_off,
+ .recalc_rate = bcm2835_clock_get_rate,
+ .set_rate = bcm2835_clock_set_rate,
++ .set_rate_and_parent = bcm2835_clock_set_rate_and_parent,
+ .determine_rate = bcm2835_clock_determine_rate,
+ .set_parent = bcm2835_clock_set_parent,
+ .get_parent = bcm2835_clock_get_parent,
+@@ -1479,7 +1493,6 @@ static struct clk_hw *bcm2835_register_c
+ init.ops = &bcm2835_vpu_clock_clk_ops;
+ } else {
+ init.ops = &bcm2835_clock_clk_ops;
+- init.flags |= CLK_SET_PARENT_GATE;
+
+ /* If the clock wasn't actually enabled at boot, it's not
+ * critical.
+++ /dev/null
-From 6b36249bd9c3399d4b8552c7557406586dc31521 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 10 Apr 2019 17:43:57 +0100
-Subject: [PATCH 611/703] drm: vc4: Bring fkms into line with kms in blocking
- doublescan modes
-
-Implement vc4_crtc_mode_valid so that it blocks doublescan modes
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 15 +++++++++++++--
- 1 file changed, 13 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -625,7 +625,17 @@ static void vc4_crtc_enable(struct drm_c
- vc4_plane_set_blank(plane, plane->state->visible);
- }
-
-+static enum drm_mode_status
-+vc4_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
-+{
-+ /* Do not allow doublescan modes from user space */
-+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
-+ DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n",
-+ crtc->base.id);
-+ return MODE_NO_DBLESCAN;
-+ }
-
-+ return MODE_OK;
- }
-
- static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
-@@ -735,10 +745,11 @@ static const struct drm_crtc_funcs vc4_c
-
- static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
- .mode_set_nofb = vc4_crtc_mode_set_nofb,
-- .atomic_disable = vc4_crtc_disable,
-- .atomic_enable = vc4_crtc_enable,
-+ .mode_valid = vc4_crtc_mode_valid,
- .atomic_check = vc4_crtc_atomic_check,
- .atomic_flush = vc4_crtc_atomic_flush,
-+ .atomic_enable = vc4_crtc_enable,
-+ .atomic_disable = vc4_crtc_disable,
- };
-
- static const struct of_device_id vc4_firmware_kms_dt_match[] = {
--- /dev/null
+From c1d46fee0b1f4711ffa9b6517a460cf5411aa0fc Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 16 Apr 2019 15:58:54 -0700
+Subject: [PATCH 612/725] drm/v3d: Add support for compute shader dispatch.
+
+The compute shader dispatch interface is pretty simple -- just pass in
+the regs that userspace has passed us, with no CLs to run. However,
+with no CL to run it means that we need to do manual cache flushing of
+the L2 after the HW execution completes (for SSBO, atomic, and
+image_load_store writes that are the output of compute shaders).
+
+This doesn't yet expose the L2 cache's ability to have a region of the
+address space not write back to memory (which could be used for
+shared_var storage).
+
+So far, the Mesa side has been tested on V3D v4.2 simpenrose (passing
+the ES31 tests), and on the kernel side on 7278 (failing atomic
+compswap tests in a way that doesn't reproduce on simpenrose).
+
+v2: Fix excessive allocation for the clean_job (reported by Dan
+ Carpenter). Keep refs on jobs until clean_job is finished, to
+ avoid spurious MMU errors if the output BOs are freed by userspace
+ before L2 cleaning is finished.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20190416225856.20264-4-eric@anholt.net
+Acked-by: Rob Clark <robdclark@gmail.com>
+---
+ drivers/gpu/drm/v3d/v3d_debugfs.c | 22 +++++
+ drivers/gpu/drm/v3d/v3d_drv.c | 10 +-
+ drivers/gpu/drm/v3d/v3d_drv.h | 28 +++++-
+ drivers/gpu/drm/v3d/v3d_fence.c | 2 +
+ drivers/gpu/drm/v3d/v3d_gem.c | 156 +++++++++++++++++++++++++++++-
+ drivers/gpu/drm/v3d/v3d_irq.c | 16 ++-
+ drivers/gpu/drm/v3d/v3d_regs.h | 73 ++++++++++++++
+ drivers/gpu/drm/v3d/v3d_sched.c | 121 +++++++++++++++++++++--
+ drivers/gpu/drm/v3d/v3d_trace.h | 94 ++++++++++++++++++
+ include/uapi/drm/v3d_drm.h | 28 ++++++
+ 10 files changed, 531 insertions(+), 19 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_debugfs.c
++++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
+@@ -57,6 +57,17 @@ static const struct v3d_reg_def v3d_core
+ REGDEF(V3D_GMP_VIO_ADDR),
+ };
+
++static const struct v3d_reg_def v3d_csd_reg_defs[] = {
++ REGDEF(V3D_CSD_STATUS),
++ REGDEF(V3D_CSD_CURRENT_CFG0),
++ REGDEF(V3D_CSD_CURRENT_CFG1),
++ REGDEF(V3D_CSD_CURRENT_CFG2),
++ REGDEF(V3D_CSD_CURRENT_CFG3),
++ REGDEF(V3D_CSD_CURRENT_CFG4),
++ REGDEF(V3D_CSD_CURRENT_CFG5),
++ REGDEF(V3D_CSD_CURRENT_CFG6),
++};
++
+ static int v3d_v3d_debugfs_regs(struct seq_file *m, void *unused)
+ {
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
+@@ -88,6 +99,17 @@ static int v3d_v3d_debugfs_regs(struct s
+ V3D_CORE_READ(core,
+ v3d_core_reg_defs[i].reg));
+ }
++
++ if (v3d_has_csd(v3d)) {
++ for (i = 0; i < ARRAY_SIZE(v3d_csd_reg_defs); i++) {
++ seq_printf(m, "core %d %s (0x%04x): 0x%08x\n",
++ core,
++ v3d_csd_reg_defs[i].name,
++ v3d_csd_reg_defs[i].reg,
++ V3D_CORE_READ(core,
++ v3d_csd_reg_defs[i].reg));
++ }
++ }
+ }
+
+ return 0;
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -7,9 +7,9 @@
+ * This driver supports the Broadcom V3D 3.3 and 4.1 OpenGL ES GPUs.
+ * For V3D 2.x support, see the VC4 driver.
+ *
+- * Currently only single-core rendering using the binner and renderer,
+- * along with TFU (texture formatting unit) rendering is supported.
+- * V3D 4.x's CSD (compute shader dispatch) is not yet supported.
++ * The V3D GPU includes a tiled render (composed of a bin and render
++ * pipelines), the TFU (texture formatting unit), and the CSD (compute
++ * shader dispatch).
+ */
+
+ #include <linux/clk.h>
+@@ -114,6 +114,9 @@ static int v3d_get_param_ioctl(struct dr
+ case DRM_V3D_PARAM_SUPPORTS_TFU:
+ args->value = 1;
+ return 0;
++ case DRM_V3D_PARAM_SUPPORTS_CSD:
++ args->value = v3d_has_csd(v3d);
++ return 0;
+ default:
+ DRM_DEBUG("Unknown parameter %d\n", args->param);
+ return -EINVAL;
+@@ -183,6 +186,7 @@ static const struct drm_ioctl_desc v3d_d
+ DRM_IOCTL_DEF_DRV(V3D_GET_PARAM, v3d_get_param_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(V3D_GET_BO_OFFSET, v3d_get_bo_offset_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(V3D_SUBMIT_TFU, v3d_submit_tfu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
++ DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CSD, v3d_submit_csd_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
+ };
+
+ static const struct vm_operations_struct v3d_vm_ops = {
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -16,9 +16,11 @@ enum v3d_queue {
+ V3D_BIN,
+ V3D_RENDER,
+ V3D_TFU,
++ V3D_CSD,
++ V3D_CACHE_CLEAN,
+ };
+
+-#define V3D_MAX_QUEUES (V3D_TFU + 1)
++#define V3D_MAX_QUEUES (V3D_CACHE_CLEAN + 1)
+
+ struct v3d_queue_state {
+ struct drm_gpu_scheduler sched;
+@@ -70,6 +72,7 @@ struct v3d_dev {
+ struct v3d_bin_job *bin_job;
+ struct v3d_render_job *render_job;
+ struct v3d_tfu_job *tfu_job;
++ struct v3d_csd_job *csd_job;
+
+ struct v3d_queue_state queue[V3D_MAX_QUEUES];
+
+@@ -92,6 +95,12 @@ struct v3d_dev {
+ */
+ struct mutex sched_lock;
+
++ /* Lock taken during a cache clean and when initiating an L2
++ * flush, to keep L2 flushes from interfering with the
++ * synchronous L2 cleans.
++ */
++ struct mutex cache_clean_lock;
++
+ struct {
+ u32 num_allocated;
+ u32 pages_allocated;
+@@ -104,6 +113,12 @@ to_v3d_dev(struct drm_device *dev)
+ return (struct v3d_dev *)dev->dev_private;
+ }
+
++static inline bool
++v3d_has_csd(struct v3d_dev *v3d)
++{
++ return v3d->ver >= 41;
++}
++
+ /* The per-fd struct, which tracks the MMU mappings. */
+ struct v3d_file_priv {
+ struct v3d_dev *v3d;
+@@ -237,6 +252,14 @@ struct v3d_tfu_job {
+ struct drm_v3d_submit_tfu args;
+ };
+
++struct v3d_csd_job {
++ struct v3d_job base;
++
++ u32 timedout_batches;
++
++ struct drm_v3d_submit_csd args;
++};
++
+ /**
+ * _wait_for - magic (register) wait macro
+ *
+@@ -302,11 +325,14 @@ int v3d_submit_cl_ioctl(struct drm_devic
+ struct drm_file *file_priv);
+ int v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
++int v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
++ struct drm_file *file_priv);
+ int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+ void v3d_job_put(struct v3d_job *job);
+ void v3d_reset(struct v3d_dev *v3d);
+ void v3d_invalidate_caches(struct v3d_dev *v3d);
++void v3d_clean_caches(struct v3d_dev *v3d);
+
+ /* v3d_irq.c */
+ int v3d_irq_init(struct v3d_dev *v3d);
+--- a/drivers/gpu/drm/v3d/v3d_fence.c
++++ b/drivers/gpu/drm/v3d/v3d_fence.c
+@@ -36,6 +36,8 @@ static const char *v3d_fence_get_timelin
+ return "v3d-render";
+ case V3D_TFU:
+ return "v3d-tfu";
++ case V3D_CSD:
++ return "v3d-csd";
+ default:
+ return NULL;
+ }
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -162,10 +162,52 @@ v3d_flush_l2t(struct v3d_dev *v3d, int c
+ /* While there is a busy bit (V3D_L2TCACTL_L2TFLS), we don't
+ * need to wait for completion before dispatching the job --
+ * L2T accesses will be stalled until the flush has completed.
++ * However, we do need to make sure we don't try to trigger a
++ * new flush while the L2_CLEAN queue is trying to
++ * synchronously clean after a job.
+ */
++ mutex_lock(&v3d->cache_clean_lock);
+ V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
+ V3D_L2TCACTL_L2TFLS |
+ V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
++ mutex_unlock(&v3d->cache_clean_lock);
++}
++
++/* Cleans texture L1 and L2 cachelines (writing back dirty data).
++ *
++ * For cleaning, which happens from the CACHE_CLEAN queue after CSD has
++ * executed, we need to make sure that the clean is done before
++ * signaling job completion. So, we synchronously wait before
++ * returning, and we make sure that L2 invalidates don't happen in the
++ * meantime to confuse our are-we-done checks.
++ */
++void
++v3d_clean_caches(struct v3d_dev *v3d)
++{
++ struct drm_device *dev = &v3d->drm;
++ int core = 0;
++
++ trace_v3d_cache_clean_begin(dev);
++
++ V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);
++ if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
++ V3D_L2TCACTL_L2TFLS), 100)) {
++ DRM_ERROR("Timeout waiting for L1T write combiner flush\n");
++ }
++
++ mutex_lock(&v3d->cache_clean_lock);
++ V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
++ V3D_L2TCACTL_L2TFLS |
++ V3D_SET_FIELD(V3D_L2TCACTL_FLM_CLEAN, V3D_L2TCACTL_FLM));
++
++ if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
++ V3D_L2TCACTL_L2TFLS), 100)) {
++ DRM_ERROR("Timeout waiting for L2T clean\n");
++ }
++
++ mutex_unlock(&v3d->cache_clean_lock);
++
++ trace_v3d_cache_clean_end(dev);
+ }
+
+ /* Invalidates the slice caches. These are read-only caches. */
+@@ -584,7 +626,8 @@ static void
+ v3d_attach_fences_and_unlock_reservation(struct drm_file *file_priv,
+ struct v3d_job *job,
+ struct ww_acquire_ctx *acquire_ctx,
+- u32 out_sync)
++ u32 out_sync,
++ struct dma_fence *done_fence)
+ {
+ struct drm_syncobj *sync_out;
+
+@@ -594,7 +637,7 @@ v3d_attach_fences_and_unlock_reservation
+ /* Update the return sync object for the job */
+ sync_out = drm_syncobj_find(file_priv, out_sync);
+ if (sync_out) {
+- drm_syncobj_replace_fence(sync_out, job->done_fence);
++ drm_syncobj_replace_fence(sync_out, done_fence);
+ drm_syncobj_put(sync_out);
+ }
+ }
+@@ -691,8 +734,10 @@ v3d_submit_cl_ioctl(struct drm_device *d
+ mutex_unlock(&v3d->sched_lock);
+
+ v3d_attach_fences_and_unlock_reservation(file_priv,
+- &render->base, &acquire_ctx,
+- args->out_sync);
++ &render->base,
++ &acquire_ctx,
++ args->out_sync,
++ render->base.done_fence);
+
+ if (bin)
+ v3d_job_put(&bin->base);
+@@ -785,7 +830,8 @@ v3d_submit_tfu_ioctl(struct drm_device *
+
+ v3d_attach_fences_and_unlock_reservation(file_priv,
+ &job->base, &acquire_ctx,
+- args->out_sync);
++ args->out_sync,
++ job->base.done_fence);
+
+ v3d_job_put(&job->base);
+
+@@ -801,6 +847,105 @@ fail:
+ return ret;
+ }
+
++/**
++ * v3d_submit_csd_ioctl() - Submits a CSD (texture formatting) job to the V3D.
++ * @dev: DRM device
++ * @data: ioctl argument
++ * @file_priv: DRM file for this fd
++ *
++ * Userspace provides the register setup for the CSD, which we don't
++ * need to validate since the CSD is behind the MMU.
++ */
++int
++v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
++ struct drm_file *file_priv)
++{
++ struct v3d_dev *v3d = to_v3d_dev(dev);
++ struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
++ struct drm_v3d_submit_csd *args = data;
++ struct v3d_csd_job *job;
++ struct v3d_job *clean_job;
++ struct ww_acquire_ctx acquire_ctx;
++ int ret;
++
++ trace_v3d_submit_csd_ioctl(&v3d->drm, args->cfg[5], args->cfg[6]);
++
++ if (!v3d_has_csd(v3d)) {
++ DRM_DEBUG("Attempting CSD submit on non-CSD hardware\n");
++ return -EINVAL;
++ }
++
++ job = kcalloc(1, sizeof(*job), GFP_KERNEL);
++ if (!job)
++ return -ENOMEM;
++
++ ret = v3d_job_init(v3d, file_priv, &job->base,
++ v3d_job_free, args->in_sync);
++ if (ret) {
++ kfree(job);
++ return ret;
++ }
++
++ clean_job = kcalloc(1, sizeof(*clean_job), GFP_KERNEL);
++ if (!clean_job) {
++ v3d_job_put(&job->base);
++ kfree(job);
++ return -ENOMEM;
++ }
++
++ ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0);
++ if (ret) {
++ v3d_job_put(&job->base);
++ kfree(clean_job);
++ return ret;
++ }
++
++ job->args = *args;
++
++ ret = v3d_lookup_bos(dev, file_priv, clean_job,
++ args->bo_handles, args->bo_handle_count);
++ if (ret)
++ goto fail;
++
++ ret = v3d_lock_bo_reservations(clean_job, &acquire_ctx);
++ if (ret)
++ goto fail;
++
++ mutex_lock(&v3d->sched_lock);
++ ret = v3d_push_job(v3d_priv, &job->base, V3D_CSD);
++ if (ret)
++ goto fail_unreserve;
++
++ ret = v3d_add_dep(clean_job, dma_fence_get(job->base.done_fence));
++ if (ret)
++ goto fail_unreserve;
++ ret = v3d_push_job(v3d_priv, clean_job, V3D_CACHE_CLEAN);
++ if (ret)
++ goto fail_unreserve;
++ mutex_unlock(&v3d->sched_lock);
++
++ v3d_attach_fences_and_unlock_reservation(file_priv,
++ clean_job,
++ &acquire_ctx,
++ args->out_sync,
++ clean_job->done_fence);
++
++ v3d_job_put(&job->base);
++ v3d_job_put(clean_job);
++
++ return 0;
++
++fail_unreserve:
++ mutex_unlock(&v3d->sched_lock);
++ v3d_unlock_bo_reservations(clean_job->bo, clean_job->bo_count,
++ &acquire_ctx);
++fail:
++ v3d_job_put(&job->base);
++ v3d_job_put(clean_job);
++
++ return ret;
++}
++
+ int
+ v3d_gem_init(struct drm_device *dev)
+ {
+@@ -816,6 +961,7 @@ v3d_gem_init(struct drm_device *dev)
+ mutex_init(&v3d->bo_lock);
+ mutex_init(&v3d->reset_lock);
+ mutex_init(&v3d->sched_lock);
++ mutex_init(&v3d->cache_clean_lock);
+
+ /* Note: We don't allocate address 0. Various bits of HW
+ * treat 0 as special, such as the occlusion query counters
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -4,9 +4,9 @@
+ /**
+ * DOC: Interrupt management for the V3D engine
+ *
+- * When we take a bin, render, or TFU done interrupt, we need to
+- * signal the fence for that job so that the scheduler can queue up
+- * the next one and unblock any waiters.
++ * When we take a bin, render, TFU done, or CSD done interrupt, we
++ * need to signal the fence for that job so that the scheduler can
++ * queue up the next one and unblock any waiters.
+ *
+ * When we take the binner out of memory interrupt, we need to
+ * allocate some new memory and pass it to the binner so that the
+@@ -20,6 +20,7 @@
+ #define V3D_CORE_IRQS ((u32)(V3D_INT_OUTOMEM | \
+ V3D_INT_FLDONE | \
+ V3D_INT_FRDONE | \
++ V3D_INT_CSDDONE | \
+ V3D_INT_GMPV))
+
+ #define V3D_HUB_IRQS ((u32)(V3D_HUB_INT_MMU_WRV | \
+@@ -108,6 +109,15 @@ v3d_irq(int irq, void *arg)
+ dma_fence_signal(&fence->base);
+ status = IRQ_HANDLED;
+ }
++
++ if (intsts & V3D_INT_CSDDONE) {
++ struct v3d_fence *fence =
++ to_v3d_fence(v3d->csd_job->base.irq_fence);
++
++ trace_v3d_csd_irq(&v3d->drm, fence->seqno);
++ dma_fence_signal(&fence->base);
++ status = IRQ_HANDLED;
++ }
+
+ /* We shouldn't be triggering these if we have GMP in
+ * always-allowed mode.
+--- a/drivers/gpu/drm/v3d/v3d_regs.h
++++ b/drivers/gpu/drm/v3d/v3d_regs.h
+@@ -238,8 +238,11 @@
+ #define V3D_CTL_L2TCACTL 0x00030
+ # define V3D_L2TCACTL_TMUWCF BIT(8)
+ # define V3D_L2TCACTL_L2T_NO_WM BIT(4)
++/* Invalidates cache lines. */
+ # define V3D_L2TCACTL_FLM_FLUSH 0
++/* Removes cachelines without writing dirty lines back. */
+ # define V3D_L2TCACTL_FLM_CLEAR 1
++/* Writes out dirty cachelines and marks them clean, but doesn't invalidate. */
+ # define V3D_L2TCACTL_FLM_CLEAN 2
+ # define V3D_L2TCACTL_FLM_MASK V3D_MASK(2, 1)
+ # define V3D_L2TCACTL_FLM_SHIFT 1
+@@ -255,6 +258,8 @@
+ #define V3D_CTL_INT_MSK_CLR 0x00064
+ # define V3D_INT_QPU_MASK V3D_MASK(27, 16)
+ # define V3D_INT_QPU_SHIFT 16
++# define V3D_INT_CSDDONE BIT(7)
++# define V3D_INT_PCTR BIT(6)
+ # define V3D_INT_GMPV BIT(5)
+ # define V3D_INT_TRFB BIT(4)
+ # define V3D_INT_SPILLUSE BIT(3)
+@@ -374,4 +379,72 @@
+ #define V3D_GMP_PRESERVE_LOAD 0x00818
+ #define V3D_GMP_VALID_LINES 0x00820
+
++#define V3D_CSD_STATUS 0x00900
++# define V3D_CSD_STATUS_NUM_COMPLETED_MASK V3D_MASK(11, 4)
++# define V3D_CSD_STATUS_NUM_COMPLETED_SHIFT 4
++# define V3D_CSD_STATUS_NUM_ACTIVE_MASK V3D_MASK(3, 2)
++# define V3D_CSD_STATUS_NUM_ACTIVE_SHIFT 2
++# define V3D_CSD_STATUS_HAVE_CURRENT_DISPATCH BIT(1)
++# define V3D_CSD_STATUS_HAVE_QUEUED_DISPATCH BIT(0)
++
++#define V3D_CSD_QUEUED_CFG0 0x00904
++# define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_MASK V3D_MASK(31, 16)
++# define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_SHIFT 16
++# define V3D_CSD_QUEUED_CFG0_WG_X_OFFSET_MASK V3D_MASK(15, 0)
++# define V3D_CSD_QUEUED_CFG0_WG_X_OFFSET_SHIFT 0
++
++#define V3D_CSD_QUEUED_CFG1 0x00908
++# define V3D_CSD_QUEUED_CFG1_NUM_WGS_Y_MASK V3D_MASK(31, 16)
++# define V3D_CSD_QUEUED_CFG1_NUM_WGS_Y_SHIFT 16
++# define V3D_CSD_QUEUED_CFG1_WG_Y_OFFSET_MASK V3D_MASK(15, 0)
++# define V3D_CSD_QUEUED_CFG1_WG_Y_OFFSET_SHIFT 0
++
++#define V3D_CSD_QUEUED_CFG2 0x0090c
++# define V3D_CSD_QUEUED_CFG2_NUM_WGS_Z_MASK V3D_MASK(31, 16)
++# define V3D_CSD_QUEUED_CFG2_NUM_WGS_Z_SHIFT 16
++# define V3D_CSD_QUEUED_CFG2_WG_Z_OFFSET_MASK V3D_MASK(15, 0)
++# define V3D_CSD_QUEUED_CFG2_WG_Z_OFFSET_SHIFT 0
++
++#define V3D_CSD_QUEUED_CFG3 0x00910
++# define V3D_CSD_QUEUED_CFG3_OVERLAP_WITH_PREV BIT(26)
++# define V3D_CSD_QUEUED_CFG3_MAX_SG_ID_MASK V3D_MASK(25, 20)
++# define V3D_CSD_QUEUED_CFG3_MAX_SG_ID_SHIFT 20
++# define V3D_CSD_QUEUED_CFG3_BATCHES_PER_SG_M1_MASK V3D_MASK(19, 12)
++# define V3D_CSD_QUEUED_CFG3_BATCHES_PER_SG_M1_SHIFT 12
++# define V3D_CSD_QUEUED_CFG3_WGS_PER_SG_MASK V3D_MASK(11, 8)
++# define V3D_CSD_QUEUED_CFG3_WGS_PER_SG_SHIFT 8
++# define V3D_CSD_QUEUED_CFG3_WG_SIZE_MASK V3D_MASK(7, 0)
++# define V3D_CSD_QUEUED_CFG3_WG_SIZE_SHIFT 0
++
++/* Number of batches, minus 1 */
++#define V3D_CSD_QUEUED_CFG4 0x00914
++
++/* Shader address, pnan, singleseg, threading, like a shader record. */
++#define V3D_CSD_QUEUED_CFG5 0x00918
++
++/* Uniforms address (4 byte aligned) */
++#define V3D_CSD_QUEUED_CFG6 0x0091c
++
++#define V3D_CSD_CURRENT_CFG0 0x00920
++#define V3D_CSD_CURRENT_CFG1 0x00924
++#define V3D_CSD_CURRENT_CFG2 0x00928
++#define V3D_CSD_CURRENT_CFG3 0x0092c
++#define V3D_CSD_CURRENT_CFG4 0x00930
++#define V3D_CSD_CURRENT_CFG5 0x00934
++#define V3D_CSD_CURRENT_CFG6 0x00938
++
++#define V3D_CSD_CURRENT_ID0 0x0093c
++# define V3D_CSD_CURRENT_ID0_WG_X_MASK V3D_MASK(31, 16)
++# define V3D_CSD_CURRENT_ID0_WG_X_SHIFT 16
++# define V3D_CSD_CURRENT_ID0_WG_IN_SG_MASK V3D_MASK(11, 8)
++# define V3D_CSD_CURRENT_ID0_WG_IN_SG_SHIFT 8
++# define V3D_CSD_CURRENT_ID0_L_IDX_MASK V3D_MASK(7, 0)
++# define V3D_CSD_CURRENT_ID0_L_IDX_SHIFT 0
++
++#define V3D_CSD_CURRENT_ID1 0x00940
++# define V3D_CSD_CURRENT_ID0_WG_Z_MASK V3D_MASK(31, 16)
++# define V3D_CSD_CURRENT_ID0_WG_Z_SHIFT 16
++# define V3D_CSD_CURRENT_ID0_WG_Y_MASK V3D_MASK(15, 0)
++# define V3D_CSD_CURRENT_ID0_WG_Y_SHIFT 0
++
+ #endif /* V3D_REGS_H */
+--- a/drivers/gpu/drm/v3d/v3d_sched.c
++++ b/drivers/gpu/drm/v3d/v3d_sched.c
+@@ -48,6 +48,12 @@ to_tfu_job(struct drm_sched_job *sched_j
+ return container_of(sched_job, struct v3d_tfu_job, base.base);
+ }
+
++static struct v3d_csd_job *
++to_csd_job(struct drm_sched_job *sched_job)
++{
++ return container_of(sched_job, struct v3d_csd_job, base.base);
++}
++
+ static void
+ v3d_job_free(struct drm_sched_job *sched_job)
+ {
+@@ -205,6 +211,48 @@ v3d_tfu_job_run(struct drm_sched_job *sc
+ return fence;
+ }
+
++static struct dma_fence *
++v3d_csd_job_run(struct drm_sched_job *sched_job)
++{
++ struct v3d_csd_job *job = to_csd_job(sched_job);
++ struct v3d_dev *v3d = job->base.v3d;
++ struct drm_device *dev = &v3d->drm;
++ struct dma_fence *fence;
++ int i;
++
++ v3d->csd_job = job;
++
++ v3d_invalidate_caches(v3d);
++
++ fence = v3d_fence_create(v3d, V3D_CSD);
++ if (IS_ERR(fence))
++ return NULL;
++
++ if (job->base.irq_fence)
++ dma_fence_put(job->base.irq_fence);
++ job->base.irq_fence = dma_fence_get(fence);
++
++ trace_v3d_submit_csd(dev, to_v3d_fence(fence)->seqno);
++
++ for (i = 1; i <= 6; i++)
++ V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0 + 4 * i, job->args.cfg[i]);
++ /* CFG0 write kicks off the job. */
++ V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0, job->args.cfg[0]);
++
++ return fence;
++}
++
++static struct dma_fence *
++v3d_cache_clean_job_run(struct drm_sched_job *sched_job)
++{
++ struct v3d_job *job = to_v3d_job(sched_job);
++ struct v3d_dev *v3d = job->v3d;
++
++ v3d_clean_caches(v3d);
++
++ return NULL;
++}
++
+ static void
+ v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job)
+ {
+@@ -277,13 +325,31 @@ v3d_render_job_timedout(struct drm_sched
+ }
+
+ static void
+-v3d_tfu_job_timedout(struct drm_sched_job *sched_job)
++v3d_generic_job_timedout(struct drm_sched_job *sched_job)
+ {
+ struct v3d_job *job = to_v3d_job(sched_job);
+
+ v3d_gpu_reset_for_timeout(job->v3d, sched_job);
+ }
+
++static void
++v3d_csd_job_timedout(struct drm_sched_job *sched_job)
++{
++ struct v3d_csd_job *job = to_csd_job(sched_job);
++ struct v3d_dev *v3d = job->base.v3d;
++ u32 batches = V3D_CORE_READ(0, V3D_CSD_CURRENT_CFG4);
++
++ /* If we've made progress, skip reset and let the timer get
++ * rearmed.
++ */
++ if (job->timedout_batches != batches) {
++ job->timedout_batches = batches;
++ return;
++ }
++
++ v3d_gpu_reset_for_timeout(v3d, sched_job);
++}
++
+ static const struct drm_sched_backend_ops v3d_bin_sched_ops = {
+ .dependency = v3d_job_dependency,
+ .run_job = v3d_bin_job_run,
+@@ -301,10 +367,24 @@ static const struct drm_sched_backend_op
+ static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
+ .dependency = v3d_job_dependency,
+ .run_job = v3d_tfu_job_run,
+- .timedout_job = v3d_tfu_job_timedout,
++ .timedout_job = v3d_generic_job_timedout,
+ .free_job = v3d_job_free,
+ };
+
++static const struct drm_sched_backend_ops v3d_csd_sched_ops = {
++ .dependency = v3d_job_dependency,
++ .run_job = v3d_csd_job_run,
++ .timedout_job = v3d_csd_job_timedout,
++ .free_job = v3d_job_free
++};
++
++static const struct drm_sched_backend_ops v3d_cache_clean_sched_ops = {
++ .dependency = v3d_job_dependency,
++ .run_job = v3d_cache_clean_job_run,
++ .timedout_job = v3d_generic_job_timedout,
++ .free_job = v3d_job_free
++};
++
+ int
+ v3d_sched_init(struct v3d_dev *v3d)
+ {
+@@ -331,7 +411,7 @@ v3d_sched_init(struct v3d_dev *v3d)
+ if (ret) {
+ dev_err(v3d->dev, "Failed to create render scheduler: %d.",
+ ret);
+- drm_sched_fini(&v3d->queue[V3D_BIN].sched);
++ v3d_sched_fini(v3d);
+ return ret;
+ }
+
+@@ -343,11 +423,36 @@ v3d_sched_init(struct v3d_dev *v3d)
+ if (ret) {
+ dev_err(v3d->dev, "Failed to create TFU scheduler: %d.",
+ ret);
+- drm_sched_fini(&v3d->queue[V3D_RENDER].sched);
+- drm_sched_fini(&v3d->queue[V3D_BIN].sched);
++ v3d_sched_fini(v3d);
+ return ret;
+ }
+
++ if (v3d_has_csd(v3d)) {
++ ret = drm_sched_init(&v3d->queue[V3D_CSD].sched,
++ &v3d_csd_sched_ops,
++ hw_jobs_limit, job_hang_limit,
++ msecs_to_jiffies(hang_limit_ms),
++ "v3d_csd");
++ if (ret) {
++ dev_err(v3d->dev, "Failed to create CSD scheduler: %d.",
++ ret);
++ v3d_sched_fini(v3d);
++ return ret;
++ }
++
++ ret = drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched,
++ &v3d_cache_clean_sched_ops,
++ hw_jobs_limit, job_hang_limit,
++ msecs_to_jiffies(hang_limit_ms),
++ "v3d_cache_clean");
++ if (ret) {
++ dev_err(v3d->dev, "Failed to create CACHE_CLEAN scheduler: %d.",
++ ret);
++ v3d_sched_fini(v3d);
++ return ret;
++ }
++ }
++
+ return 0;
+ }
+
+@@ -356,6 +461,8 @@ v3d_sched_fini(struct v3d_dev *v3d)
+ {
+ enum v3d_queue q;
+
+- for (q = 0; q < V3D_MAX_QUEUES; q++)
+- drm_sched_fini(&v3d->queue[q].sched);
++ for (q = 0; q < V3D_MAX_QUEUES; q++) {
++ if (v3d->queue[q].sched.ops)
++ drm_sched_fini(&v3d->queue[q].sched);
++ }
+ }
+--- a/drivers/gpu/drm/v3d/v3d_trace.h
++++ b/drivers/gpu/drm/v3d/v3d_trace.h
+@@ -124,6 +124,26 @@ TRACE_EVENT(v3d_tfu_irq,
+ __entry->seqno)
+ );
+
++TRACE_EVENT(v3d_csd_irq,
++ TP_PROTO(struct drm_device *dev,
++ uint64_t seqno),
++ TP_ARGS(dev, seqno),
++
++ TP_STRUCT__entry(
++ __field(u32, dev)
++ __field(u64, seqno)
++ ),
++
++ TP_fast_assign(
++ __entry->dev = dev->primary->index;
++ __entry->seqno = seqno;
++ ),
++
++ TP_printk("dev=%u, seqno=%llu",
++ __entry->dev,
++ __entry->seqno)
++);
++
+ TRACE_EVENT(v3d_submit_tfu_ioctl,
+ TP_PROTO(struct drm_device *dev, u32 iia),
+ TP_ARGS(dev, iia),
+@@ -163,6 +183,80 @@ TRACE_EVENT(v3d_submit_tfu,
+ __entry->seqno)
+ );
+
++TRACE_EVENT(v3d_submit_csd_ioctl,
++ TP_PROTO(struct drm_device *dev, u32 cfg5, u32 cfg6),
++ TP_ARGS(dev, cfg5, cfg6),
++
++ TP_STRUCT__entry(
++ __field(u32, dev)
++ __field(u32, cfg5)
++ __field(u32, cfg6)
++ ),
++
++ TP_fast_assign(
++ __entry->dev = dev->primary->index;
++ __entry->cfg5 = cfg5;
++ __entry->cfg6 = cfg6;
++ ),
++
++ TP_printk("dev=%u, CFG5 0x%08x, CFG6 0x%08x",
++ __entry->dev,
++ __entry->cfg5,
++ __entry->cfg6)
++);
++
++TRACE_EVENT(v3d_submit_csd,
++ TP_PROTO(struct drm_device *dev,
++ uint64_t seqno),
++ TP_ARGS(dev, seqno),
++
++ TP_STRUCT__entry(
++ __field(u32, dev)
++ __field(u64, seqno)
++ ),
++
++ TP_fast_assign(
++ __entry->dev = dev->primary->index;
++ __entry->seqno = seqno;
++ ),
++
++ TP_printk("dev=%u, seqno=%llu",
++ __entry->dev,
++ __entry->seqno)
++);
++
++TRACE_EVENT(v3d_cache_clean_begin,
++ TP_PROTO(struct drm_device *dev),
++ TP_ARGS(dev),
++
++ TP_STRUCT__entry(
++ __field(u32, dev)
++ ),
++
++ TP_fast_assign(
++ __entry->dev = dev->primary->index;
++ ),
++
++ TP_printk("dev=%u",
++ __entry->dev)
++);
++
++TRACE_EVENT(v3d_cache_clean_end,
++ TP_PROTO(struct drm_device *dev),
++ TP_ARGS(dev),
++
++ TP_STRUCT__entry(
++ __field(u32, dev)
++ ),
++
++ TP_fast_assign(
++ __entry->dev = dev->primary->index;
++ ),
++
++ TP_printk("dev=%u",
++ __entry->dev)
++);
++
+ TRACE_EVENT(v3d_reset_begin,
+ TP_PROTO(struct drm_device *dev),
+ TP_ARGS(dev),
+--- a/include/uapi/drm/v3d_drm.h
++++ b/include/uapi/drm/v3d_drm.h
+@@ -37,6 +37,7 @@ extern "C" {
+ #define DRM_V3D_GET_PARAM 0x04
+ #define DRM_V3D_GET_BO_OFFSET 0x05
+ #define DRM_V3D_SUBMIT_TFU 0x06
++#define DRM_V3D_SUBMIT_CSD 0x07
+
+ #define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
+ #define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
+@@ -45,6 +46,7 @@ extern "C" {
+ #define DRM_IOCTL_V3D_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)
+ #define DRM_IOCTL_V3D_GET_BO_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
+ #define DRM_IOCTL_V3D_SUBMIT_TFU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
++#define DRM_IOCTL_V3D_SUBMIT_CSD DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CSD, struct drm_v3d_submit_csd)
+
+ /**
+ * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
+@@ -172,6 +174,7 @@ enum drm_v3d_param {
+ DRM_V3D_PARAM_V3D_CORE0_IDENT1,
+ DRM_V3D_PARAM_V3D_CORE0_IDENT2,
+ DRM_V3D_PARAM_SUPPORTS_TFU,
++ DRM_V3D_PARAM_SUPPORTS_CSD,
+ };
+
+ struct drm_v3d_get_param {
+@@ -212,6 +215,31 @@ struct drm_v3d_submit_tfu {
+ __u32 out_sync;
+ };
+
++/* Submits a compute shader for dispatch. This job will block on any
++ * previous compute shaders submitted on this fd, and any other
++ * synchronization must be performed with in_sync/out_sync.
++ */
++struct drm_v3d_submit_csd {
++ __u32 cfg[7];
++ __u32 coef[4];
++
++ /* Pointer to a u32 array of the BOs that are referenced by the job.
++ */
++ __u64 bo_handles;
++
++ /* Number of BO handles passed in (size is that times 4). */
++ __u32 bo_handle_count;
++
++ /* sync object to block on before running the CSD job. Each
++ * CSD job will execute in the order submitted to its FD.
++ * Synchronization against rendering/TFU jobs or CSD from
++ * other fds requires using sync objects.
++ */
++ __u32 in_sync;
++ /* Sync object to signal when the CSD job is done. */
++ __u32 out_sync;
++};
++
+ #if defined(__cplusplus)
+ }
+ #endif
+++ /dev/null
-From 64a1a6d813cea64ee9dafca163e62542dce04399 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 29 Apr 2019 18:45:00 +0100
-Subject: [PATCH 612/703] drm: vc4: Increase max_width/height to 7680.
-
-There are some limits still being investigated that stop
-us going up to 8192, but 7680 is sufficient for dual 4k
-displays.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_kms.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -429,8 +429,8 @@ int vc4_kms_load(struct drm_device *dev)
- return ret;
- }
-
-- dev->mode_config.max_width = 4096;
-- dev->mode_config.max_height = 4096;
-+ dev->mode_config.max_width = 7680;
-+ dev->mode_config.max_height = 7680;
- dev->mode_config.funcs = &vc4_mode_funcs;
- dev->mode_config.preferred_depth = 24;
- dev->mode_config.async_page_flip = true;
--- /dev/null
+From 78981e59b011aa5d21ccedf124c0af9b445d279f Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 2 May 2019 13:22:53 -0700
+Subject: [PATCH 613/725] drm/v3d: Clock V3D down when not in use.
+
+My various attempts at re-enabling runtime PM have failed, so just
+crank the clock down when V3D is idle to reduce power consumption.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/gpu/drm/v3d/v3d_drv.c | 18 +++++++++++++
+ drivers/gpu/drm/v3d/v3d_drv.h | 6 +++++
+ drivers/gpu/drm/v3d/v3d_gem.c | 49 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 73 insertions(+)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -297,6 +297,21 @@ static int v3d_platform_drm_probe(struct
+ }
+ }
+
++ v3d->clk = devm_clk_get(dev, NULL);
++ if (IS_ERR(v3d->clk)) {
++ if (ret != -EPROBE_DEFER)
++ dev_err(dev, "Failed to get clock\n");
++ goto dev_free;
++ }
++ v3d->clk_up_rate = clk_get_rate(v3d->clk);
++ /* For downclocking, drop it to the minimum frequency we can get from
++ * the CPRMAN clock generator dividing off our parent. The divider is
++ * 4 bits, but ask for just higher than that so that rounding doesn't
++ * make cprman reject our rate.
++ */
++ v3d->clk_down_rate =
++ (clk_get_rate(clk_get_parent(v3d->clk)) / (1 << 4)) + 10000;
++
+ if (v3d->ver < 41) {
+ ret = map_regs(v3d, &v3d->gca_regs, "gca");
+ if (ret)
+@@ -331,6 +346,9 @@ static int v3d_platform_drm_probe(struct
+ if (ret)
+ goto irq_disable;
+
++ ret = clk_set_rate(v3d->clk, v3d->clk_down_rate);
++ WARN_ON_ONCE(ret != 0);
++
+ return 0;
+
+ irq_disable:
+--- a/drivers/gpu/drm/v3d/v3d_drv.h
++++ b/drivers/gpu/drm/v3d/v3d_drv.h
+@@ -45,6 +45,12 @@ struct v3d_dev {
+ void __iomem *bridge_regs;
+ void __iomem *gca_regs;
+ struct clk *clk;
++ struct delayed_work clk_down_work;
++ unsigned long clk_up_rate, clk_down_rate;
++ struct mutex clk_lock;
++ u32 clk_refcount;
++ bool clk_up;
++
+ struct reset_control *reset;
+
+ /* Virtual and DMA addresses of the single shared page table. */
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -3,6 +3,7 @@
+
+ #include <drm/drmP.h>
+ #include <drm/drm_syncobj.h>
++#include <linux/clk.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_runtime.h>
+@@ -17,6 +18,47 @@
+ #include "v3d_trace.h"
+
+ static void
++v3d_clock_down_work(struct work_struct *work)
++{
++ struct v3d_dev *v3d =
++ container_of(work, struct v3d_dev, clk_down_work.work);
++ int ret;
++
++ ret = clk_set_rate(v3d->clk, v3d->clk_down_rate);
++ v3d->clk_up = false;
++ WARN_ON_ONCE(ret != 0);
++}
++
++static void
++v3d_clock_up_get(struct v3d_dev *v3d)
++{
++ mutex_lock(&v3d->clk_lock);
++ if (v3d->clk_refcount++ == 0) {
++ cancel_delayed_work_sync(&v3d->clk_down_work);
++ if (!v3d->clk_up) {
++ int ret;
++
++ ret = clk_set_rate(v3d->clk, v3d->clk_up_rate);
++ WARN_ON_ONCE(ret != 0);
++ v3d->clk_up = true;
++ }
++ }
++ mutex_unlock(&v3d->clk_lock);
++}
++
++static void
++v3d_clock_up_put(struct v3d_dev *v3d)
++{
++ mutex_lock(&v3d->clk_lock);
++ if (--v3d->clk_refcount == 0) {
++ schedule_delayed_work(&v3d->clk_down_work,
++ msecs_to_jiffies(100));
++ }
++ mutex_unlock(&v3d->clk_lock);
++}
++
++
++static void
+ v3d_init_core(struct v3d_dev *v3d, int core)
+ {
+ /* Set OVRTMUOUT, which means that the texture sampler uniform
+@@ -490,6 +532,7 @@ static void
+ v3d_job_free(struct kref *ref)
+ {
+ struct v3d_job *job = container_of(ref, struct v3d_job, refcount);
++ struct v3d_dev *v3d = job->v3d;
+ int i;
+
+ for (i = 0; i < job->bo_count; i++) {
+@@ -505,6 +548,8 @@ v3d_job_free(struct kref *ref)
+ dma_fence_put(job->irq_fence);
+ dma_fence_put(job->done_fence);
+
++ v3d_clock_up_put(v3d);
++
+ kfree(job);
+ }
+
+@@ -596,6 +641,7 @@ v3d_job_init(struct v3d_dev *v3d, struct
+ if (ret)
+ return ret;
+
++ v3d_clock_up_get(v3d);
+ kref_init(&job->refcount);
+
+ return 0;
+@@ -963,6 +1009,9 @@ v3d_gem_init(struct drm_device *dev)
+ mutex_init(&v3d->sched_lock);
+ mutex_init(&v3d->cache_clean_lock);
+
++ mutex_init(&v3d->clk_lock);
++ INIT_DELAYED_WORK(&v3d->clk_down_work, v3d_clock_down_work);
++
+ /* Note: We don't allocate address 0. Various bits of HW
+ * treat 0 as special, such as the occlusion query counters
+ * where 0 means "disabled".
+++ /dev/null
-From 9dccdfcd48e7adb46af440cec26df2d8146afefb Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 9 Apr 2019 18:23:41 +0100
-Subject: [PATCH 613/703] drm: vc4: FKMS reads the EDID from fw, and supports
- mode setting
-
-This extends FKMS to read the EDID from the display, and support
-requesting a particular mode via KMS.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 334 ++++++++++++++++++---
- include/soc/bcm2835/raspberrypi-firmware.h | 2 +
- 2 files changed, 302 insertions(+), 34 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -88,11 +88,60 @@ struct mailbox_blank_display {
- u32 blank;
- };
-
--struct mailbox_get_width_height {
-+struct mailbox_get_edid {
- struct rpi_firmware_property_tag_header tag1;
-- u32 display;
-- struct rpi_firmware_property_tag_header tag2;
-- u32 wh[2];
-+ u32 block;
-+ u32 display_number;
-+ u8 edid[128];
-+};
-+
-+struct set_timings {
-+ u8 display;
-+ u8 padding;
-+ u16 video_id_code;
-+
-+ u32 clock; /* in kHz */
-+
-+ u16 hdisplay;
-+ u16 hsync_start;
-+
-+ u16 hsync_end;
-+ u16 htotal;
-+
-+ u16 hskew;
-+ u16 vdisplay;
-+
-+ u16 vsync_start;
-+ u16 vsync_end;
-+
-+ u16 vtotal;
-+ u16 vscan;
-+
-+ u16 vrefresh;
-+ u16 padding2;
-+
-+ u32 flags;
-+#define TIMINGS_FLAGS_H_SYNC_POS BIT(0)
-+#define TIMINGS_FLAGS_H_SYNC_NEG 0
-+#define TIMINGS_FLAGS_V_SYNC_POS BIT(1)
-+#define TIMINGS_FLAGS_V_SYNC_NEG 0
-+
-+#define TIMINGS_FLAGS_ASPECT_MASK GENMASK(7, 4)
-+#define TIMINGS_FLAGS_ASPECT_NONE (0 << 4)
-+#define TIMINGS_FLAGS_ASPECT_4_3 (1 << 4)
-+#define TIMINGS_FLAGS_ASPECT_16_9 (2 << 4)
-+#define TIMINGS_FLAGS_ASPECT_64_27 (3 << 4)
-+#define TIMINGS_FLAGS_ASPECT_256_135 (4 << 4)
-+
-+/* Limited range RGB flag. Not set corresponds to full range. */
-+#define TIMINGS_FLAGS_RGB_LIMITED BIT(8)
-+/* DVI monitor, therefore disable infoframes. Not set corresponds to HDMI. */
-+#define TIMINGS_FLAGS_DVI BIT(9)
-+};
-+
-+struct mailbox_set_mode {
-+ struct rpi_firmware_property_tag_header tag1;
-+ struct set_timings timings;
- };
-
- static const struct vc_image_format {
-@@ -186,6 +235,7 @@ struct vc4_crtc {
- u32 overscan[4];
- bool vblank_enabled;
- u32 display_number;
-+ u32 display_type;
- };
-
- static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc)
-@@ -195,6 +245,8 @@ static inline struct vc4_crtc *to_vc4_cr
-
- struct vc4_fkms_encoder {
- struct drm_encoder base;
-+ bool hdmi_monitor;
-+ bool rgb_range_selectable;
- };
-
- static inline struct vc4_fkms_encoder *
-@@ -212,7 +264,9 @@ struct vc4_fkms_connector {
- * hook.
- */
- struct drm_encoder *encoder;
-- u32 display_idx;
-+ struct vc4_dev *vc4_dev;
-+ u32 display_number;
-+ u32 display_type;
- };
-
- static inline struct vc4_fkms_connector *
-@@ -221,6 +275,26 @@ to_vc4_fkms_connector(struct drm_connect
- return container_of(connector, struct vc4_fkms_connector, base);
- }
-
-+static u32 vc4_get_display_type(u32 display_number)
-+{
-+ const u32 display_types[] = {
-+ /* The firmware display (DispmanX) IDs map to specific types in
-+ * a fixed manner.
-+ */
-+ DRM_MODE_ENCODER_DSI, /* MAIN_LCD */
-+ DRM_MODE_ENCODER_DSI, /* AUX_LCD */
-+ DRM_MODE_ENCODER_TMDS, /* HDMI0 */
-+ DRM_MODE_ENCODER_TVDAC, /* VEC */
-+ DRM_MODE_ENCODER_NONE, /* FORCE_LCD */
-+ DRM_MODE_ENCODER_NONE, /* FORCE_TV */
-+ DRM_MODE_ENCODER_NONE, /* FORCE_OTHER */
-+ DRM_MODE_ENCODER_TMDS, /* HDMI1 */
-+ DRM_MODE_ENCODER_NONE, /* FORCE_TV2 */
-+ };
-+ return display_number > ARRAY_SIZE(display_types) - 1 ?
-+ DRM_MODE_ENCODER_NONE : display_types[display_number];
-+}
-+
- /* Firmware's structure for making an FB mbox call. */
- struct fbinfo_s {
- u32 xres, yres, xres_virtual, yres_virtual;
-@@ -255,10 +329,15 @@ static int vc4_plane_set_blank(struct dr
- .plane_id = vc4_plane->mb.plane.plane_id,
- }
- };
-+ static const char * const plane_types[] = {
-+ "overlay",
-+ "primary",
-+ "cursor"
-+ };
- int ret;
-
-- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] overlay plane %s",
-- plane->base.id, plane->name,
-+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] %s plane %s",
-+ plane->base.id, plane->name, plane_types[plane->type],
- blank ? "blank" : "unblank");
-
- if (blank)
-@@ -593,13 +672,102 @@ fail:
-
- static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
- {
-- /* Everyting is handled in the planes. */
-+ struct drm_device *dev = crtc->dev;
-+ struct vc4_dev *vc4 = to_vc4_dev(dev);
-+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-+ struct drm_display_mode *mode = &crtc->state->adjusted_mode;
-+ struct vc4_fkms_encoder *vc4_encoder =
-+ to_vc4_fkms_encoder(vc4_crtc->encoder);
-+ struct mailbox_set_mode mb = {
-+ .tag1 = { RPI_FIRMWARE_SET_TIMING,
-+ sizeof(struct set_timings), 0},
-+ };
-+ union hdmi_infoframe frame;
-+ int ret;
-+
-+ ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
-+ if (ret < 0) {
-+ DRM_ERROR("couldn't fill AVI infoframe\n");
-+ return;
-+ }
-+
-+ DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u\n",
-+ vc4_crtc->display_number, mode->name, mode->clock,
-+ mode->hdisplay, mode->hsync_start, mode->hsync_end,
-+ mode->htotal, mode->hskew, mode->vdisplay,
-+ mode->vsync_start, mode->vsync_end, mode->vtotal,
-+ mode->vscan, mode->vrefresh, mode->picture_aspect_ratio);
-+ mb.timings.display = vc4_crtc->display_number;
-+
-+ mb.timings.video_id_code = frame.avi.video_code;
-+
-+ mb.timings.clock = mode->clock;
-+ mb.timings.hdisplay = mode->hdisplay;
-+ mb.timings.hsync_start = mode->hsync_start;
-+ mb.timings.hsync_end = mode->hsync_end;
-+ mb.timings.htotal = mode->htotal;
-+ mb.timings.hskew = mode->hskew;
-+ mb.timings.vdisplay = mode->vdisplay;
-+ mb.timings.vsync_start = mode->vsync_start;
-+ mb.timings.vsync_end = mode->vsync_end;
-+ mb.timings.vtotal = mode->vtotal;
-+ mb.timings.vscan = mode->vscan;
-+ mb.timings.vrefresh = 0;
-+ mb.timings.flags = 0;
-+ if (mode->flags & DRM_MODE_FLAG_PHSYNC)
-+ mb.timings.flags |= TIMINGS_FLAGS_H_SYNC_POS;
-+ if (mode->flags & DRM_MODE_FLAG_PVSYNC)
-+ mb.timings.flags |= TIMINGS_FLAGS_V_SYNC_POS;
-+
-+ switch (frame.avi.picture_aspect) {
-+ default:
-+ case HDMI_PICTURE_ASPECT_NONE:
-+ mode->flags |= TIMINGS_FLAGS_ASPECT_NONE;
-+ break;
-+ case HDMI_PICTURE_ASPECT_4_3:
-+ mode->flags |= TIMINGS_FLAGS_ASPECT_4_3;
-+ break;
-+ case HDMI_PICTURE_ASPECT_16_9:
-+ mode->flags |= TIMINGS_FLAGS_ASPECT_16_9;
-+ break;
-+ case HDMI_PICTURE_ASPECT_64_27:
-+ mode->flags |= TIMINGS_FLAGS_ASPECT_64_27;
-+ break;
-+ case HDMI_PICTURE_ASPECT_256_135:
-+ mode->flags |= TIMINGS_FLAGS_ASPECT_256_135;
-+ break;
-+ }
-+
-+ if (!vc4_encoder->hdmi_monitor)
-+ mb.timings.flags |= TIMINGS_FLAGS_DVI;
-+ else if (drm_default_rgb_quant_range(mode) ==
-+ HDMI_QUANTIZATION_RANGE_LIMITED)
-+ mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
-+
-+ /*
-+ FIXME: To implement
-+ switch(mode->flag & DRM_MODE_FLAG_3D_MASK) {
-+ case DRM_MODE_FLAG_3D_NONE:
-+ case DRM_MODE_FLAG_3D_FRAME_PACKING:
-+ case DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE:
-+ case DRM_MODE_FLAG_3D_LINE_ALTERNATIVE:
-+ case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL:
-+ case DRM_MODE_FLAG_3D_L_DEPTH:
-+ case DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH:
-+ case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM:
-+ case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF:
-+ }
-+ */
-+
-+ ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
- }
-
- static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
- {
- struct drm_plane *plane;
-
-+ DRM_DEBUG_KMS("[CRTC:%d] vblanks off.\n",
-+ crtc->base.id);
- drm_crtc_vblank_off(crtc);
-
- /* Always turn the planes off on CRTC disable. In DRM, planes
-@@ -617,6 +785,8 @@ static void vc4_crtc_enable(struct drm_c
- {
- struct drm_plane *plane;
-
-+ DRM_DEBUG_KMS("[CRTC:%d] vblanks on.\n",
-+ crtc->base.id);
- drm_crtc_vblank_on(crtc);
-
- /* Unblank the planes (if they're supposed to be displayed). */
-@@ -635,12 +805,20 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
- return MODE_NO_DBLESCAN;
- }
-
-+ /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
-+ * working.
-+ */
-+ if (mode->clock > 340000)
-+ return MODE_CLOCK_HIGH;
-+
- return MODE_OK;
- }
-
- static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
- struct drm_crtc_state *state)
- {
-+ DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_check.\n",
-+ crtc->base.id);
- return 0;
- }
-
-@@ -650,6 +828,8 @@ static void vc4_crtc_atomic_flush(struct
- struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
- struct drm_device *dev = crtc->dev;
-
-+ DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_flush.\n",
-+ crtc->base.id);
- if (crtc->state->event) {
- unsigned long flags;
-
-@@ -717,6 +897,8 @@ static int vc4_fkms_enable_vblank(struct
- {
- struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-
-+ DRM_DEBUG_KMS("[CRTC:%d] enable_vblank.\n",
-+ crtc->base.id);
- vc4_crtc->vblank_enabled = true;
-
- return 0;
-@@ -726,6 +908,8 @@ static void vc4_fkms_disable_vblank(stru
- {
- struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-
-+ DRM_DEBUG_KMS("[CRTC:%d] disable_vblank.\n",
-+ crtc->base.id);
- vc4_crtc->vblank_enabled = false;
- }
-
-@@ -760,36 +944,92 @@ static const struct of_device_id vc4_fir
- static enum drm_connector_status
- vc4_fkms_connector_detect(struct drm_connector *connector, bool force)
- {
-+ DRM_DEBUG_KMS("connector detect.\n");
- return connector_status_connected;
- }
-
--static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
-+static int vc4_fkms_get_edid_block(void *data, u8 *buf, unsigned int block,
-+ size_t len)
- {
-- struct drm_device *dev = connector->dev;
- struct vc4_fkms_connector *fkms_connector =
-- to_vc4_fkms_connector(connector);
-- struct vc4_dev *vc4 = to_vc4_dev(dev);
-- struct drm_display_mode *mode;
-- struct mailbox_get_width_height wh = {
-- .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
-- .display = fkms_connector->display_idx,
-- .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT,
-- 8, 0, },
-+ (struct vc4_fkms_connector *)data;
-+ struct vc4_dev *vc4 = fkms_connector->vc4_dev;
-+ struct mailbox_get_edid mb = {
-+ .tag1 = { RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY,
-+ 128 + 8, 0 },
-+ .block = block,
-+ .display_number = fkms_connector->display_number,
- };
-- int ret;
-+ int ret = 0;
-+
-+ ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
-+
-+ if (!ret)
-+ memcpy(buf, mb.edid, len);
-+
-+ return ret;
-+}
-+
-+static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
-+{
-+ struct vc4_fkms_connector *fkms_connector =
-+ to_vc4_fkms_connector(connector);
-+ struct drm_encoder *encoder = fkms_connector->encoder;
-+ struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
-+ int ret = 0;
-+ struct edid *edid;
-+
-+ edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block,
-+ fkms_connector);
-+
-+ /* FIXME: Can we do CEC?
-+ * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
-+ * if (!edid)
-+ * return -ENODEV;
-+ */
-+
-+ vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
-
-- ret = rpi_firmware_property_list(vc4->firmware, &wh, sizeof(wh));
-+ if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
-+ vc4_encoder->rgb_range_selectable =
-+ drm_rgb_quant_range_selectable(edid);
-+ }
-+
-+ drm_connector_update_edid_property(connector, edid);
-+ ret = drm_add_edid_modes(connector, edid);
-+ kfree(edid);
-+
-+ return ret;
-+}
-+
-+/* FIXME: Read LCD mode from the firmware. This is the DSI panel resolution. */
-+static const struct drm_display_mode lcd_mode = {
-+ DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
-+ 25979400 / 1000,
-+ 800, 800 + 1, 800 + 1 + 2, 800 + 1 + 2 + 46, 0,
-+ 480, 480 + 7, 480 + 7 + 2, 480 + 7 + 2 + 21, 0,
-+ DRM_MODE_FLAG_INTERLACE)
-+};
-+
-+static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
-+{
-+ //struct vc4_fkms_connector *fkms_connector =
-+ // to_vc4_fkms_connector(connector);
-+ //struct drm_encoder *encoder = fkms_connector->encoder;
-+ //struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
-+ struct drm_display_mode *mode;
-+ //int ret = 0;
-
-- if (ret) {
-- DRM_ERROR("Failed to get screen size: %d (0x%08x 0x%08x)\n",
-- ret, wh.wh[0], wh.wh[1]);
-- return 0;
-+ mode = drm_mode_duplicate(connector->dev,
-+ &lcd_mode);
-+ if (!mode) {
-+ DRM_ERROR("Failed to create a new display mode\n");
-+ return -ENOMEM;
- }
-
-- mode = drm_cvt_mode(dev, wh.wh[0], wh.wh[1], 60 /* vrefresh */,
-- 0, 0, false);
- drm_mode_probed_add(connector, mode);
-
-+ /* We have one mode */
- return 1;
- }
-
-@@ -798,11 +1038,14 @@ vc4_fkms_connector_best_encoder(struct d
- {
- struct vc4_fkms_connector *fkms_connector =
- to_vc4_fkms_connector(connector);
-+ DRM_DEBUG_KMS("best_connector.\n");
- return fkms_connector->encoder;
- }
-
- static void vc4_fkms_connector_destroy(struct drm_connector *connector)
- {
-+ DRM_DEBUG_KMS("[CONNECTOR:%d] destroy.\n",
-+ connector->base.id);
- drm_connector_unregister(connector);
- drm_connector_cleanup(connector);
- }
-@@ -821,14 +1064,22 @@ static const struct drm_connector_helper
- .best_encoder = vc4_fkms_connector_best_encoder,
- };
-
-+static const struct drm_connector_helper_funcs vc4_fkms_lcd_conn_helper_funcs = {
-+ .get_modes = vc4_fkms_lcd_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,
-- u32 display_idx)
-+ u32 display_num)
- {
- struct drm_connector *connector = NULL;
- struct vc4_fkms_connector *fkms_connector;
-+ struct vc4_dev *vc4_dev = to_vc4_dev(dev);
- int ret = 0;
-
-+ DRM_DEBUG_KMS("connector_init, display_num %u\n", display_num);
-+
- fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector),
- GFP_KERNEL);
- if (!fkms_connector) {
-@@ -838,11 +1089,21 @@ vc4_fkms_connector_init(struct drm_devic
- connector = &fkms_connector->base;
-
- fkms_connector->encoder = encoder;
-- fkms_connector->display_idx = display_idx;
--
-- drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
-- DRM_MODE_CONNECTOR_HDMIA);
-- drm_connector_helper_add(connector, &vc4_fkms_connector_helper_funcs);
-+ fkms_connector->display_number = display_num;
-+ fkms_connector->display_type = vc4_get_display_type(display_num);
-+ fkms_connector->vc4_dev = vc4_dev;
-+
-+ if (fkms_connector->display_type == DRM_MODE_ENCODER_DSI) {
-+ drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
-+ DRM_MODE_CONNECTOR_DSI);
-+ drm_connector_helper_add(connector,
-+ &vc4_fkms_lcd_conn_helper_funcs);
-+ } else {
-+ 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);
-@@ -863,6 +1124,7 @@ vc4_fkms_connector_init(struct drm_devic
-
- static void vc4_fkms_encoder_destroy(struct drm_encoder *encoder)
- {
-+ DRM_DEBUG_KMS("Encoder_destroy\n");
- drm_encoder_cleanup(encoder);
- }
-
-@@ -872,10 +1134,12 @@ static const struct drm_encoder_funcs vc
-
- static void vc4_fkms_encoder_enable(struct drm_encoder *encoder)
- {
-+ DRM_DEBUG_KMS("Encoder_enable\n");
- }
-
- static void vc4_fkms_encoder_disable(struct drm_encoder *encoder)
- {
-+ DRM_DEBUG_KMS("Encoder_disable\n");
- }
-
- static const struct drm_encoder_helper_funcs vc4_fkms_encoder_helper_funcs = {
-@@ -907,6 +1171,7 @@ static int vc4_fkms_create_screen(struct
- crtc = &vc4_crtc->base;
-
- vc4_crtc->display_number = display_ref;
-+ vc4_crtc->display_type = vc4_get_display_type(display_ref);
-
- /* Blank the firmware provided framebuffer */
- rpi_firmware_property_list(vc4->firmware, &blank, sizeof(blank));
-@@ -950,13 +1215,14 @@ static int vc4_fkms_create_screen(struct
- 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);
-+ vc4_crtc->display_type, NULL);
- drm_encoder_helper_add(&vc4_encoder->base,
- &vc4_fkms_encoder_helper_funcs);
-
- vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base,
-- display_idx);
-+ display_ref);
- if (IS_ERR(vc4_crtc->connector)) {
- ret = PTR_ERR(vc4_crtc->connector);
- goto err_destroy_encoder;
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -78,6 +78,7 @@ enum rpi_firmware_property_tag {
- RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014,
- RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020,
- RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021,
-+ RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY = 0x00030023,
- RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030,
- RPI_FIRMWARE_GET_THROTTLED = 0x00030046,
- RPI_FIRMWARE_GET_CLOCK_MEASURED = 0x00030047,
-@@ -150,6 +151,7 @@ enum rpi_firmware_property_tag {
- RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
-
- RPI_FIRMWARE_SET_PLANE = 0x00048015,
-+ RPI_FIRMWARE_SET_TIMING = 0x00048017,
-
- RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
- RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,
--- /dev/null
+From ea2e0086511bc2e61c58b7f298bcb558f1fc48b4 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Thu, 2 May 2019 23:42:29 +0200
+Subject: [PATCH 614/725] HACK: clk-bcm2835: Add BCM2838_CLOCK_EMMC2 support
+
+The new BCM2838 supports an additional emmc2 clock. So add a new
+compatible to register this clock only for BCM2838.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 20 ++++++++++++++++++--
+ include/dt-bindings/clock/bcm2835.h | 2 ++
+ 2 files changed, 20 insertions(+), 2 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -124,6 +124,8 @@
+ #define CM_AVEODIV 0x1bc
+ #define CM_EMMCCTL 0x1c0
+ #define CM_EMMCDIV 0x1c4
++#define CM_EMMC2CTL 0x1d0
++#define CM_EMMC2DIV 0x1d4
+
+ /* General bits for the CM_*CTL regs */
+ # define CM_ENABLE BIT(4)
+@@ -2047,6 +2049,15 @@ static const struct bcm2835_clk_desc clk
+ .frac_bits = 8,
+ .tcnt_mux = 39),
+
++ /* EMMC2 clock (only available for BCM2838) */
++ [BCM2838_CLOCK_EMMC2] = REGISTER_PER_CLK(
++ .name = "emmc2",
++ .ctl_reg = CM_EMMC2CTL,
++ .div_reg = CM_EMMC2DIV,
++ .int_bits = 4,
++ .frac_bits = 8,
++ .tcnt_mux = 42),
++
+ /* General purpose (GPIO) clocks */
+ [BCM2835_CLOCK_GP0] = REGISTER_PER_CLK(
+ .name = "gp0",
+@@ -2276,8 +2287,12 @@ static int bcm2835_clk_probe(struct plat
+
+ for (i = 0; i < asize; i++) {
+ desc = &clk_desc_array[i];
+- if (desc->clk_register && desc->data)
+- hws[i] = desc->clk_register(cprman, desc->data);
++ if (desc->clk_register && desc->data) {
++ if ((i != BCM2838_CLOCK_EMMC2) ||
++ of_device_is_compatible(fw_node, "brcm,bcm2838-cprman")) {
++ hws[i] = desc->clk_register(cprman, desc->data);
++ }
++ }
+ }
+
+ ret = bcm2835_mark_sdc_parent_critical(hws[BCM2835_CLOCK_SDRAM]->clk);
+@@ -2297,6 +2312,7 @@ static int bcm2835_clk_probe(struct plat
+
+ static const struct of_device_id bcm2835_clk_of_match[] = {
+ { .compatible = "brcm,bcm2835-cprman", },
++ { .compatible = "brcm,bcm2838-cprman", },
+ {}
+ };
+ MODULE_DEVICE_TABLE(of, bcm2835_clk_of_match);
+--- a/include/dt-bindings/clock/bcm2835.h
++++ b/include/dt-bindings/clock/bcm2835.h
+@@ -66,3 +66,5 @@
+ #define BCM2835_CLOCK_DSI1E 48
+ #define BCM2835_CLOCK_DSI0P 49
+ #define BCM2835_CLOCK_DSI1P 50
++
++#define BCM2838_CLOCK_EMMC2 51
+++ /dev/null
-From ace78bef08082eb8971b87b28525926cd86b68c1 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 2 May 2019 15:11:05 -0700
-Subject: [PATCH 614/703] clk: bcm2835: Add support for setting leaf clock
- rates while running.
-
-As long as you wait for !BUSY, you can do glitch-free updates of clock
-rate while the clock is running.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/clk/bcm/clk-bcm2835.c | 22 +++++++++++++---------
- 1 file changed, 13 insertions(+), 9 deletions(-)
-
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -1097,15 +1097,19 @@ static int bcm2835_clock_set_rate(struct
-
- spin_lock(&cprman->regs_lock);
-
-- /*
-- * Setting up frac support
-- *
-- * In principle it is recommended to stop/start the clock first,
-- * but as we set CLK_SET_RATE_GATE during registration of the
-- * clock this requirement should be take care of by the
-- * clk-framework.
-+ ctl = cprman_read(cprman, data->ctl_reg);
-+
-+ /* If the clock is running, we have to pause clock generation while
-+ * updating the control and div regs. This is glitchless (no clock
-+ * signals generated faster than the rate) but each reg access is two
-+ * OSC cycles so the clock will slow down for a moment.
- */
-- ctl = cprman_read(cprman, data->ctl_reg) & ~CM_FRAC;
-+ if (ctl & CM_ENABLE) {
-+ cprman_write(cprman, data->ctl_reg, ctl & ~CM_ENABLE);
-+ bcm2835_clock_wait_busy(clock);
-+ }
-+
-+ ctl &= ~CM_FRAC;
- ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
- cprman_write(cprman, data->ctl_reg, ctl);
-
-@@ -1475,7 +1479,7 @@ static struct clk_hw *bcm2835_register_c
- init.ops = &bcm2835_vpu_clock_clk_ops;
- } else {
- init.ops = &bcm2835_clock_clk_ops;
-- init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
-+ init.flags |= CLK_SET_PARENT_GATE;
-
- /* If the clock wasn't actually enabled at boot, it's not
- * critical.
+++ /dev/null
-From bfdd7752d7503203300ce8359103b11b961611cf Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 2 May 2019 15:24:04 -0700
-Subject: [PATCH 615/703] clk: bcm2835: Allow reparenting leaf clocks while
- they're running.
-
-This falls under the same "we can reprogram glitch-free as long as we
-pause generation" rule as updating the div/frac fields. This can be
-used for runtime reclocking of V3D to manage power leakage.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/clk/bcm/clk-bcm2835.c | 19 ++++++++++++++++---
- 1 file changed, 16 insertions(+), 3 deletions(-)
-
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -1086,8 +1086,10 @@ static int bcm2835_clock_on(struct clk_h
- return 0;
- }
-
--static int bcm2835_clock_set_rate(struct clk_hw *hw,
-- unsigned long rate, unsigned long parent_rate)
-+static int bcm2835_clock_set_rate_and_parent(struct clk_hw *hw,
-+ unsigned long rate,
-+ unsigned long parent_rate,
-+ u8 parent)
- {
- struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
- struct bcm2835_cprman *cprman = clock->cprman;
-@@ -1109,6 +1111,11 @@ static int bcm2835_clock_set_rate(struct
- bcm2835_clock_wait_busy(clock);
- }
-
-+ if (parent != 0xff) {
-+ ctl &= ~(CM_SRC_MASK << CM_SRC_SHIFT);
-+ ctl |= parent << CM_SRC_SHIFT;
-+ }
-+
- ctl &= ~CM_FRAC;
- ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
- cprman_write(cprman, data->ctl_reg, ctl);
-@@ -1120,6 +1127,12 @@ static int bcm2835_clock_set_rate(struct
- return 0;
- }
-
-+static int bcm2835_clock_set_rate(struct clk_hw *hw,
-+ unsigned long rate, unsigned long parent_rate)
-+{
-+ return bcm2835_clock_set_rate_and_parent(hw, rate, parent_rate, 0xff);
-+}
-+
- static bool
- bcm2835_clk_is_pllc(struct clk_hw *hw)
- {
-@@ -1303,6 +1316,7 @@ static const struct clk_ops bcm2835_cloc
- .unprepare = bcm2835_clock_off,
- .recalc_rate = bcm2835_clock_get_rate,
- .set_rate = bcm2835_clock_set_rate,
-+ .set_rate_and_parent = bcm2835_clock_set_rate_and_parent,
- .determine_rate = bcm2835_clock_determine_rate,
- .set_parent = bcm2835_clock_set_parent,
- .get_parent = bcm2835_clock_get_parent,
-@@ -1479,7 +1493,6 @@ static struct clk_hw *bcm2835_register_c
- init.ops = &bcm2835_vpu_clock_clk_ops;
- } else {
- init.ops = &bcm2835_clock_clk_ops;
-- init.flags |= CLK_SET_PARENT_GATE;
-
- /* If the clock wasn't actually enabled at boot, it's not
- * critical.
--- /dev/null
+From 670f61146f51a0fcfc75c9c5920922f94c662f59 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 3 May 2019 13:58:03 +0100
+Subject: [PATCH 615/725] drm: vc4-firmware-kms: Remove incorrect overscan
+ support.
+
+The overscan support was required for the old mailbox API
+in order to match up the cursor and frame buffer planes.
+With the newer API directly talking to dispmanx there is no
+difference, therefore FKMS does not need to make any
+adjustments.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 15 ---------------
+ 1 file changed, 15 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -232,7 +232,6 @@ struct vc4_crtc {
+ void __iomem *regs;
+
+ struct drm_pending_vblank_event *event;
+- u32 overscan[4];
+ bool vblank_enabled;
+ u32 display_number;
+ u32 display_type;
+@@ -468,11 +467,6 @@ static void vc4_plane_atomic_update(stru
+ break;
+ }
+
+- if (vc4_crtc) {
+- mb->plane.dst_x += vc4_crtc->overscan[0];
+- mb->plane.dst_y += vc4_crtc->overscan[1];
+- }
+-
+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane update %dx%d@%d +dst(%d,%d, %d,%d) +src(%d,%d, %d,%d) 0x%08x/%08x/%08x/%d, alpha %u zpos %u\n",
+ plane->base.id, plane->name,
+ mb->plane.width,
+@@ -1228,15 +1222,6 @@ static int vc4_fkms_create_screen(struct
+ goto err_destroy_encoder;
+ }
+
+- ret = rpi_firmware_property(vc4->firmware,
+- RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN,
+- &vc4_crtc->overscan,
+- sizeof(vc4_crtc->overscan));
+- if (ret) {
+- DRM_ERROR("Failed to get overscan state: 0x%08x\n", vc4_crtc->overscan[0]);
+- memset(&vc4_crtc->overscan, 0, sizeof(vc4_crtc->overscan));
+- }
+-
+ *ret_crtc = vc4_crtc;
+
+ return 0;
+++ /dev/null
-From d607c1cfefb38ae7a75ac057afff275e89cff691 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Tue, 16 Apr 2019 15:58:54 -0700
-Subject: [PATCH 616/703] drm/v3d: Add support for compute shader dispatch.
-
-The compute shader dispatch interface is pretty simple -- just pass in
-the regs that userspace has passed us, with no CLs to run. However,
-with no CL to run it means that we need to do manual cache flushing of
-the L2 after the HW execution completes (for SSBO, atomic, and
-image_load_store writes that are the output of compute shaders).
-
-This doesn't yet expose the L2 cache's ability to have a region of the
-address space not write back to memory (which could be used for
-shared_var storage).
-
-So far, the Mesa side has been tested on V3D v4.2 simpenrose (passing
-the ES31 tests), and on the kernel side on 7278 (failing atomic
-compswap tests in a way that doesn't reproduce on simpenrose).
-
-v2: Fix excessive allocation for the clean_job (reported by Dan
- Carpenter). Keep refs on jobs until clean_job is finished, to
- avoid spurious MMU errors if the output BOs are freed by userspace
- before L2 cleaning is finished.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Link: https://patchwork.freedesktop.org/patch/msgid/20190416225856.20264-4-eric@anholt.net
-Acked-by: Rob Clark <robdclark@gmail.com>
----
- drivers/gpu/drm/v3d/v3d_debugfs.c | 22 +++++
- drivers/gpu/drm/v3d/v3d_drv.c | 10 +-
- drivers/gpu/drm/v3d/v3d_drv.h | 28 +++++-
- drivers/gpu/drm/v3d/v3d_fence.c | 2 +
- drivers/gpu/drm/v3d/v3d_gem.c | 156 +++++++++++++++++++++++++++++-
- drivers/gpu/drm/v3d/v3d_irq.c | 16 ++-
- drivers/gpu/drm/v3d/v3d_regs.h | 73 ++++++++++++++
- drivers/gpu/drm/v3d/v3d_sched.c | 121 +++++++++++++++++++++--
- drivers/gpu/drm/v3d/v3d_trace.h | 94 ++++++++++++++++++
- include/uapi/drm/v3d_drm.h | 28 ++++++
- 10 files changed, 531 insertions(+), 19 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_debugfs.c
-+++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
-@@ -57,6 +57,17 @@ static const struct v3d_reg_def v3d_core
- REGDEF(V3D_GMP_VIO_ADDR),
- };
-
-+static const struct v3d_reg_def v3d_csd_reg_defs[] = {
-+ REGDEF(V3D_CSD_STATUS),
-+ REGDEF(V3D_CSD_CURRENT_CFG0),
-+ REGDEF(V3D_CSD_CURRENT_CFG1),
-+ REGDEF(V3D_CSD_CURRENT_CFG2),
-+ REGDEF(V3D_CSD_CURRENT_CFG3),
-+ REGDEF(V3D_CSD_CURRENT_CFG4),
-+ REGDEF(V3D_CSD_CURRENT_CFG5),
-+ REGDEF(V3D_CSD_CURRENT_CFG6),
-+};
-+
- static int v3d_v3d_debugfs_regs(struct seq_file *m, void *unused)
- {
- struct drm_info_node *node = (struct drm_info_node *)m->private;
-@@ -88,6 +99,17 @@ static int v3d_v3d_debugfs_regs(struct s
- V3D_CORE_READ(core,
- v3d_core_reg_defs[i].reg));
- }
-+
-+ if (v3d_has_csd(v3d)) {
-+ for (i = 0; i < ARRAY_SIZE(v3d_csd_reg_defs); i++) {
-+ seq_printf(m, "core %d %s (0x%04x): 0x%08x\n",
-+ core,
-+ v3d_csd_reg_defs[i].name,
-+ v3d_csd_reg_defs[i].reg,
-+ V3D_CORE_READ(core,
-+ v3d_csd_reg_defs[i].reg));
-+ }
-+ }
- }
-
- return 0;
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -7,9 +7,9 @@
- * This driver supports the Broadcom V3D 3.3 and 4.1 OpenGL ES GPUs.
- * For V3D 2.x support, see the VC4 driver.
- *
-- * Currently only single-core rendering using the binner and renderer,
-- * along with TFU (texture formatting unit) rendering is supported.
-- * V3D 4.x's CSD (compute shader dispatch) is not yet supported.
-+ * The V3D GPU includes a tiled render (composed of a bin and render
-+ * pipelines), the TFU (texture formatting unit), and the CSD (compute
-+ * shader dispatch).
- */
-
- #include <linux/clk.h>
-@@ -114,6 +114,9 @@ static int v3d_get_param_ioctl(struct dr
- case DRM_V3D_PARAM_SUPPORTS_TFU:
- args->value = 1;
- return 0;
-+ case DRM_V3D_PARAM_SUPPORTS_CSD:
-+ args->value = v3d_has_csd(v3d);
-+ return 0;
- default:
- DRM_DEBUG("Unknown parameter %d\n", args->param);
- return -EINVAL;
-@@ -183,6 +186,7 @@ static const struct drm_ioctl_desc v3d_d
- DRM_IOCTL_DEF_DRV(V3D_GET_PARAM, v3d_get_param_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(V3D_GET_BO_OFFSET, v3d_get_bo_offset_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(V3D_SUBMIT_TFU, v3d_submit_tfu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
-+ DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CSD, v3d_submit_csd_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
- };
-
- static const struct vm_operations_struct v3d_vm_ops = {
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -16,9 +16,11 @@ enum v3d_queue {
- V3D_BIN,
- V3D_RENDER,
- V3D_TFU,
-+ V3D_CSD,
-+ V3D_CACHE_CLEAN,
- };
-
--#define V3D_MAX_QUEUES (V3D_TFU + 1)
-+#define V3D_MAX_QUEUES (V3D_CACHE_CLEAN + 1)
-
- struct v3d_queue_state {
- struct drm_gpu_scheduler sched;
-@@ -70,6 +72,7 @@ struct v3d_dev {
- struct v3d_bin_job *bin_job;
- struct v3d_render_job *render_job;
- struct v3d_tfu_job *tfu_job;
-+ struct v3d_csd_job *csd_job;
-
- struct v3d_queue_state queue[V3D_MAX_QUEUES];
-
-@@ -92,6 +95,12 @@ struct v3d_dev {
- */
- struct mutex sched_lock;
-
-+ /* Lock taken during a cache clean and when initiating an L2
-+ * flush, to keep L2 flushes from interfering with the
-+ * synchronous L2 cleans.
-+ */
-+ struct mutex cache_clean_lock;
-+
- struct {
- u32 num_allocated;
- u32 pages_allocated;
-@@ -104,6 +113,12 @@ to_v3d_dev(struct drm_device *dev)
- return (struct v3d_dev *)dev->dev_private;
- }
-
-+static inline bool
-+v3d_has_csd(struct v3d_dev *v3d)
-+{
-+ return v3d->ver >= 41;
-+}
-+
- /* The per-fd struct, which tracks the MMU mappings. */
- struct v3d_file_priv {
- struct v3d_dev *v3d;
-@@ -237,6 +252,14 @@ struct v3d_tfu_job {
- struct drm_v3d_submit_tfu args;
- };
-
-+struct v3d_csd_job {
-+ struct v3d_job base;
-+
-+ u32 timedout_batches;
-+
-+ struct drm_v3d_submit_csd args;
-+};
-+
- /**
- * _wait_for - magic (register) wait macro
- *
-@@ -302,11 +325,14 @@ int v3d_submit_cl_ioctl(struct drm_devic
- struct drm_file *file_priv);
- int v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-+int v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
-+ struct drm_file *file_priv);
- int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
- void v3d_job_put(struct v3d_job *job);
- void v3d_reset(struct v3d_dev *v3d);
- void v3d_invalidate_caches(struct v3d_dev *v3d);
-+void v3d_clean_caches(struct v3d_dev *v3d);
-
- /* v3d_irq.c */
- int v3d_irq_init(struct v3d_dev *v3d);
---- a/drivers/gpu/drm/v3d/v3d_fence.c
-+++ b/drivers/gpu/drm/v3d/v3d_fence.c
-@@ -36,6 +36,8 @@ static const char *v3d_fence_get_timelin
- return "v3d-render";
- case V3D_TFU:
- return "v3d-tfu";
-+ case V3D_CSD:
-+ return "v3d-csd";
- default:
- return NULL;
- }
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -162,10 +162,52 @@ v3d_flush_l2t(struct v3d_dev *v3d, int c
- /* While there is a busy bit (V3D_L2TCACTL_L2TFLS), we don't
- * need to wait for completion before dispatching the job --
- * L2T accesses will be stalled until the flush has completed.
-+ * However, we do need to make sure we don't try to trigger a
-+ * new flush while the L2_CLEAN queue is trying to
-+ * synchronously clean after a job.
- */
-+ mutex_lock(&v3d->cache_clean_lock);
- V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
- V3D_L2TCACTL_L2TFLS |
- V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
-+ mutex_unlock(&v3d->cache_clean_lock);
-+}
-+
-+/* Cleans texture L1 and L2 cachelines (writing back dirty data).
-+ *
-+ * For cleaning, which happens from the CACHE_CLEAN queue after CSD has
-+ * executed, we need to make sure that the clean is done before
-+ * signaling job completion. So, we synchronously wait before
-+ * returning, and we make sure that L2 invalidates don't happen in the
-+ * meantime to confuse our are-we-done checks.
-+ */
-+void
-+v3d_clean_caches(struct v3d_dev *v3d)
-+{
-+ struct drm_device *dev = &v3d->drm;
-+ int core = 0;
-+
-+ trace_v3d_cache_clean_begin(dev);
-+
-+ V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);
-+ if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
-+ V3D_L2TCACTL_L2TFLS), 100)) {
-+ DRM_ERROR("Timeout waiting for L1T write combiner flush\n");
-+ }
-+
-+ mutex_lock(&v3d->cache_clean_lock);
-+ V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
-+ V3D_L2TCACTL_L2TFLS |
-+ V3D_SET_FIELD(V3D_L2TCACTL_FLM_CLEAN, V3D_L2TCACTL_FLM));
-+
-+ if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
-+ V3D_L2TCACTL_L2TFLS), 100)) {
-+ DRM_ERROR("Timeout waiting for L2T clean\n");
-+ }
-+
-+ mutex_unlock(&v3d->cache_clean_lock);
-+
-+ trace_v3d_cache_clean_end(dev);
- }
-
- /* Invalidates the slice caches. These are read-only caches. */
-@@ -584,7 +626,8 @@ static void
- v3d_attach_fences_and_unlock_reservation(struct drm_file *file_priv,
- struct v3d_job *job,
- struct ww_acquire_ctx *acquire_ctx,
-- u32 out_sync)
-+ u32 out_sync,
-+ struct dma_fence *done_fence)
- {
- struct drm_syncobj *sync_out;
-
-@@ -594,7 +637,7 @@ v3d_attach_fences_and_unlock_reservation
- /* Update the return sync object for the job */
- sync_out = drm_syncobj_find(file_priv, out_sync);
- if (sync_out) {
-- drm_syncobj_replace_fence(sync_out, job->done_fence);
-+ drm_syncobj_replace_fence(sync_out, done_fence);
- drm_syncobj_put(sync_out);
- }
- }
-@@ -691,8 +734,10 @@ v3d_submit_cl_ioctl(struct drm_device *d
- mutex_unlock(&v3d->sched_lock);
-
- v3d_attach_fences_and_unlock_reservation(file_priv,
-- &render->base, &acquire_ctx,
-- args->out_sync);
-+ &render->base,
-+ &acquire_ctx,
-+ args->out_sync,
-+ render->base.done_fence);
-
- if (bin)
- v3d_job_put(&bin->base);
-@@ -785,7 +830,8 @@ v3d_submit_tfu_ioctl(struct drm_device *
-
- v3d_attach_fences_and_unlock_reservation(file_priv,
- &job->base, &acquire_ctx,
-- args->out_sync);
-+ args->out_sync,
-+ job->base.done_fence);
-
- v3d_job_put(&job->base);
-
-@@ -801,6 +847,105 @@ fail:
- return ret;
- }
-
-+/**
-+ * v3d_submit_csd_ioctl() - Submits a CSD (texture formatting) job to the V3D.
-+ * @dev: DRM device
-+ * @data: ioctl argument
-+ * @file_priv: DRM file for this fd
-+ *
-+ * Userspace provides the register setup for the CSD, which we don't
-+ * need to validate since the CSD is behind the MMU.
-+ */
-+int
-+v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
-+ struct drm_file *file_priv)
-+{
-+ struct v3d_dev *v3d = to_v3d_dev(dev);
-+ struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
-+ struct drm_v3d_submit_csd *args = data;
-+ struct v3d_csd_job *job;
-+ struct v3d_job *clean_job;
-+ struct ww_acquire_ctx acquire_ctx;
-+ int ret;
-+
-+ trace_v3d_submit_csd_ioctl(&v3d->drm, args->cfg[5], args->cfg[6]);
-+
-+ if (!v3d_has_csd(v3d)) {
-+ DRM_DEBUG("Attempting CSD submit on non-CSD hardware\n");
-+ return -EINVAL;
-+ }
-+
-+ job = kcalloc(1, sizeof(*job), GFP_KERNEL);
-+ if (!job)
-+ return -ENOMEM;
-+
-+ ret = v3d_job_init(v3d, file_priv, &job->base,
-+ v3d_job_free, args->in_sync);
-+ if (ret) {
-+ kfree(job);
-+ return ret;
-+ }
-+
-+ clean_job = kcalloc(1, sizeof(*clean_job), GFP_KERNEL);
-+ if (!clean_job) {
-+ v3d_job_put(&job->base);
-+ kfree(job);
-+ return -ENOMEM;
-+ }
-+
-+ ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0);
-+ if (ret) {
-+ v3d_job_put(&job->base);
-+ kfree(clean_job);
-+ return ret;
-+ }
-+
-+ job->args = *args;
-+
-+ ret = v3d_lookup_bos(dev, file_priv, clean_job,
-+ args->bo_handles, args->bo_handle_count);
-+ if (ret)
-+ goto fail;
-+
-+ ret = v3d_lock_bo_reservations(clean_job, &acquire_ctx);
-+ if (ret)
-+ goto fail;
-+
-+ mutex_lock(&v3d->sched_lock);
-+ ret = v3d_push_job(v3d_priv, &job->base, V3D_CSD);
-+ if (ret)
-+ goto fail_unreserve;
-+
-+ ret = v3d_add_dep(clean_job, dma_fence_get(job->base.done_fence));
-+ if (ret)
-+ goto fail_unreserve;
-+ ret = v3d_push_job(v3d_priv, clean_job, V3D_CACHE_CLEAN);
-+ if (ret)
-+ goto fail_unreserve;
-+ mutex_unlock(&v3d->sched_lock);
-+
-+ v3d_attach_fences_and_unlock_reservation(file_priv,
-+ clean_job,
-+ &acquire_ctx,
-+ args->out_sync,
-+ clean_job->done_fence);
-+
-+ v3d_job_put(&job->base);
-+ v3d_job_put(clean_job);
-+
-+ return 0;
-+
-+fail_unreserve:
-+ mutex_unlock(&v3d->sched_lock);
-+ v3d_unlock_bo_reservations(clean_job->bo, clean_job->bo_count,
-+ &acquire_ctx);
-+fail:
-+ v3d_job_put(&job->base);
-+ v3d_job_put(clean_job);
-+
-+ return ret;
-+}
-+
- int
- v3d_gem_init(struct drm_device *dev)
- {
-@@ -816,6 +961,7 @@ v3d_gem_init(struct drm_device *dev)
- mutex_init(&v3d->bo_lock);
- mutex_init(&v3d->reset_lock);
- mutex_init(&v3d->sched_lock);
-+ mutex_init(&v3d->cache_clean_lock);
-
- /* Note: We don't allocate address 0. Various bits of HW
- * treat 0 as special, such as the occlusion query counters
---- a/drivers/gpu/drm/v3d/v3d_irq.c
-+++ b/drivers/gpu/drm/v3d/v3d_irq.c
-@@ -4,9 +4,9 @@
- /**
- * DOC: Interrupt management for the V3D engine
- *
-- * When we take a bin, render, or TFU done interrupt, we need to
-- * signal the fence for that job so that the scheduler can queue up
-- * the next one and unblock any waiters.
-+ * When we take a bin, render, TFU done, or CSD done interrupt, we
-+ * need to signal the fence for that job so that the scheduler can
-+ * queue up the next one and unblock any waiters.
- *
- * When we take the binner out of memory interrupt, we need to
- * allocate some new memory and pass it to the binner so that the
-@@ -20,6 +20,7 @@
- #define V3D_CORE_IRQS ((u32)(V3D_INT_OUTOMEM | \
- V3D_INT_FLDONE | \
- V3D_INT_FRDONE | \
-+ V3D_INT_CSDDONE | \
- V3D_INT_GMPV))
-
- #define V3D_HUB_IRQS ((u32)(V3D_HUB_INT_MMU_WRV | \
-@@ -108,6 +109,15 @@ v3d_irq(int irq, void *arg)
- dma_fence_signal(&fence->base);
- status = IRQ_HANDLED;
- }
-+
-+ if (intsts & V3D_INT_CSDDONE) {
-+ struct v3d_fence *fence =
-+ to_v3d_fence(v3d->csd_job->base.irq_fence);
-+
-+ trace_v3d_csd_irq(&v3d->drm, fence->seqno);
-+ dma_fence_signal(&fence->base);
-+ status = IRQ_HANDLED;
-+ }
-
- /* We shouldn't be triggering these if we have GMP in
- * always-allowed mode.
---- a/drivers/gpu/drm/v3d/v3d_regs.h
-+++ b/drivers/gpu/drm/v3d/v3d_regs.h
-@@ -238,8 +238,11 @@
- #define V3D_CTL_L2TCACTL 0x00030
- # define V3D_L2TCACTL_TMUWCF BIT(8)
- # define V3D_L2TCACTL_L2T_NO_WM BIT(4)
-+/* Invalidates cache lines. */
- # define V3D_L2TCACTL_FLM_FLUSH 0
-+/* Removes cachelines without writing dirty lines back. */
- # define V3D_L2TCACTL_FLM_CLEAR 1
-+/* Writes out dirty cachelines and marks them clean, but doesn't invalidate. */
- # define V3D_L2TCACTL_FLM_CLEAN 2
- # define V3D_L2TCACTL_FLM_MASK V3D_MASK(2, 1)
- # define V3D_L2TCACTL_FLM_SHIFT 1
-@@ -255,6 +258,8 @@
- #define V3D_CTL_INT_MSK_CLR 0x00064
- # define V3D_INT_QPU_MASK V3D_MASK(27, 16)
- # define V3D_INT_QPU_SHIFT 16
-+# define V3D_INT_CSDDONE BIT(7)
-+# define V3D_INT_PCTR BIT(6)
- # define V3D_INT_GMPV BIT(5)
- # define V3D_INT_TRFB BIT(4)
- # define V3D_INT_SPILLUSE BIT(3)
-@@ -374,4 +379,72 @@
- #define V3D_GMP_PRESERVE_LOAD 0x00818
- #define V3D_GMP_VALID_LINES 0x00820
-
-+#define V3D_CSD_STATUS 0x00900
-+# define V3D_CSD_STATUS_NUM_COMPLETED_MASK V3D_MASK(11, 4)
-+# define V3D_CSD_STATUS_NUM_COMPLETED_SHIFT 4
-+# define V3D_CSD_STATUS_NUM_ACTIVE_MASK V3D_MASK(3, 2)
-+# define V3D_CSD_STATUS_NUM_ACTIVE_SHIFT 2
-+# define V3D_CSD_STATUS_HAVE_CURRENT_DISPATCH BIT(1)
-+# define V3D_CSD_STATUS_HAVE_QUEUED_DISPATCH BIT(0)
-+
-+#define V3D_CSD_QUEUED_CFG0 0x00904
-+# define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_MASK V3D_MASK(31, 16)
-+# define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_SHIFT 16
-+# define V3D_CSD_QUEUED_CFG0_WG_X_OFFSET_MASK V3D_MASK(15, 0)
-+# define V3D_CSD_QUEUED_CFG0_WG_X_OFFSET_SHIFT 0
-+
-+#define V3D_CSD_QUEUED_CFG1 0x00908
-+# define V3D_CSD_QUEUED_CFG1_NUM_WGS_Y_MASK V3D_MASK(31, 16)
-+# define V3D_CSD_QUEUED_CFG1_NUM_WGS_Y_SHIFT 16
-+# define V3D_CSD_QUEUED_CFG1_WG_Y_OFFSET_MASK V3D_MASK(15, 0)
-+# define V3D_CSD_QUEUED_CFG1_WG_Y_OFFSET_SHIFT 0
-+
-+#define V3D_CSD_QUEUED_CFG2 0x0090c
-+# define V3D_CSD_QUEUED_CFG2_NUM_WGS_Z_MASK V3D_MASK(31, 16)
-+# define V3D_CSD_QUEUED_CFG2_NUM_WGS_Z_SHIFT 16
-+# define V3D_CSD_QUEUED_CFG2_WG_Z_OFFSET_MASK V3D_MASK(15, 0)
-+# define V3D_CSD_QUEUED_CFG2_WG_Z_OFFSET_SHIFT 0
-+
-+#define V3D_CSD_QUEUED_CFG3 0x00910
-+# define V3D_CSD_QUEUED_CFG3_OVERLAP_WITH_PREV BIT(26)
-+# define V3D_CSD_QUEUED_CFG3_MAX_SG_ID_MASK V3D_MASK(25, 20)
-+# define V3D_CSD_QUEUED_CFG3_MAX_SG_ID_SHIFT 20
-+# define V3D_CSD_QUEUED_CFG3_BATCHES_PER_SG_M1_MASK V3D_MASK(19, 12)
-+# define V3D_CSD_QUEUED_CFG3_BATCHES_PER_SG_M1_SHIFT 12
-+# define V3D_CSD_QUEUED_CFG3_WGS_PER_SG_MASK V3D_MASK(11, 8)
-+# define V3D_CSD_QUEUED_CFG3_WGS_PER_SG_SHIFT 8
-+# define V3D_CSD_QUEUED_CFG3_WG_SIZE_MASK V3D_MASK(7, 0)
-+# define V3D_CSD_QUEUED_CFG3_WG_SIZE_SHIFT 0
-+
-+/* Number of batches, minus 1 */
-+#define V3D_CSD_QUEUED_CFG4 0x00914
-+
-+/* Shader address, pnan, singleseg, threading, like a shader record. */
-+#define V3D_CSD_QUEUED_CFG5 0x00918
-+
-+/* Uniforms address (4 byte aligned) */
-+#define V3D_CSD_QUEUED_CFG6 0x0091c
-+
-+#define V3D_CSD_CURRENT_CFG0 0x00920
-+#define V3D_CSD_CURRENT_CFG1 0x00924
-+#define V3D_CSD_CURRENT_CFG2 0x00928
-+#define V3D_CSD_CURRENT_CFG3 0x0092c
-+#define V3D_CSD_CURRENT_CFG4 0x00930
-+#define V3D_CSD_CURRENT_CFG5 0x00934
-+#define V3D_CSD_CURRENT_CFG6 0x00938
-+
-+#define V3D_CSD_CURRENT_ID0 0x0093c
-+# define V3D_CSD_CURRENT_ID0_WG_X_MASK V3D_MASK(31, 16)
-+# define V3D_CSD_CURRENT_ID0_WG_X_SHIFT 16
-+# define V3D_CSD_CURRENT_ID0_WG_IN_SG_MASK V3D_MASK(11, 8)
-+# define V3D_CSD_CURRENT_ID0_WG_IN_SG_SHIFT 8
-+# define V3D_CSD_CURRENT_ID0_L_IDX_MASK V3D_MASK(7, 0)
-+# define V3D_CSD_CURRENT_ID0_L_IDX_SHIFT 0
-+
-+#define V3D_CSD_CURRENT_ID1 0x00940
-+# define V3D_CSD_CURRENT_ID0_WG_Z_MASK V3D_MASK(31, 16)
-+# define V3D_CSD_CURRENT_ID0_WG_Z_SHIFT 16
-+# define V3D_CSD_CURRENT_ID0_WG_Y_MASK V3D_MASK(15, 0)
-+# define V3D_CSD_CURRENT_ID0_WG_Y_SHIFT 0
-+
- #endif /* V3D_REGS_H */
---- a/drivers/gpu/drm/v3d/v3d_sched.c
-+++ b/drivers/gpu/drm/v3d/v3d_sched.c
-@@ -48,6 +48,12 @@ to_tfu_job(struct drm_sched_job *sched_j
- return container_of(sched_job, struct v3d_tfu_job, base.base);
- }
-
-+static struct v3d_csd_job *
-+to_csd_job(struct drm_sched_job *sched_job)
-+{
-+ return container_of(sched_job, struct v3d_csd_job, base.base);
-+}
-+
- static void
- v3d_job_free(struct drm_sched_job *sched_job)
- {
-@@ -205,6 +211,48 @@ v3d_tfu_job_run(struct drm_sched_job *sc
- return fence;
- }
-
-+static struct dma_fence *
-+v3d_csd_job_run(struct drm_sched_job *sched_job)
-+{
-+ struct v3d_csd_job *job = to_csd_job(sched_job);
-+ struct v3d_dev *v3d = job->base.v3d;
-+ struct drm_device *dev = &v3d->drm;
-+ struct dma_fence *fence;
-+ int i;
-+
-+ v3d->csd_job = job;
-+
-+ v3d_invalidate_caches(v3d);
-+
-+ fence = v3d_fence_create(v3d, V3D_CSD);
-+ if (IS_ERR(fence))
-+ return NULL;
-+
-+ if (job->base.irq_fence)
-+ dma_fence_put(job->base.irq_fence);
-+ job->base.irq_fence = dma_fence_get(fence);
-+
-+ trace_v3d_submit_csd(dev, to_v3d_fence(fence)->seqno);
-+
-+ for (i = 1; i <= 6; i++)
-+ V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0 + 4 * i, job->args.cfg[i]);
-+ /* CFG0 write kicks off the job. */
-+ V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0, job->args.cfg[0]);
-+
-+ return fence;
-+}
-+
-+static struct dma_fence *
-+v3d_cache_clean_job_run(struct drm_sched_job *sched_job)
-+{
-+ struct v3d_job *job = to_v3d_job(sched_job);
-+ struct v3d_dev *v3d = job->v3d;
-+
-+ v3d_clean_caches(v3d);
-+
-+ return NULL;
-+}
-+
- static void
- v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job)
- {
-@@ -277,13 +325,31 @@ v3d_render_job_timedout(struct drm_sched
- }
-
- static void
--v3d_tfu_job_timedout(struct drm_sched_job *sched_job)
-+v3d_generic_job_timedout(struct drm_sched_job *sched_job)
- {
- struct v3d_job *job = to_v3d_job(sched_job);
-
- v3d_gpu_reset_for_timeout(job->v3d, sched_job);
- }
-
-+static void
-+v3d_csd_job_timedout(struct drm_sched_job *sched_job)
-+{
-+ struct v3d_csd_job *job = to_csd_job(sched_job);
-+ struct v3d_dev *v3d = job->base.v3d;
-+ u32 batches = V3D_CORE_READ(0, V3D_CSD_CURRENT_CFG4);
-+
-+ /* If we've made progress, skip reset and let the timer get
-+ * rearmed.
-+ */
-+ if (job->timedout_batches != batches) {
-+ job->timedout_batches = batches;
-+ return;
-+ }
-+
-+ v3d_gpu_reset_for_timeout(v3d, sched_job);
-+}
-+
- static const struct drm_sched_backend_ops v3d_bin_sched_ops = {
- .dependency = v3d_job_dependency,
- .run_job = v3d_bin_job_run,
-@@ -301,10 +367,24 @@ static const struct drm_sched_backend_op
- static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
- .dependency = v3d_job_dependency,
- .run_job = v3d_tfu_job_run,
-- .timedout_job = v3d_tfu_job_timedout,
-+ .timedout_job = v3d_generic_job_timedout,
- .free_job = v3d_job_free,
- };
-
-+static const struct drm_sched_backend_ops v3d_csd_sched_ops = {
-+ .dependency = v3d_job_dependency,
-+ .run_job = v3d_csd_job_run,
-+ .timedout_job = v3d_csd_job_timedout,
-+ .free_job = v3d_job_free
-+};
-+
-+static const struct drm_sched_backend_ops v3d_cache_clean_sched_ops = {
-+ .dependency = v3d_job_dependency,
-+ .run_job = v3d_cache_clean_job_run,
-+ .timedout_job = v3d_generic_job_timedout,
-+ .free_job = v3d_job_free
-+};
-+
- int
- v3d_sched_init(struct v3d_dev *v3d)
- {
-@@ -331,7 +411,7 @@ v3d_sched_init(struct v3d_dev *v3d)
- if (ret) {
- dev_err(v3d->dev, "Failed to create render scheduler: %d.",
- ret);
-- drm_sched_fini(&v3d->queue[V3D_BIN].sched);
-+ v3d_sched_fini(v3d);
- return ret;
- }
-
-@@ -343,11 +423,36 @@ v3d_sched_init(struct v3d_dev *v3d)
- if (ret) {
- dev_err(v3d->dev, "Failed to create TFU scheduler: %d.",
- ret);
-- drm_sched_fini(&v3d->queue[V3D_RENDER].sched);
-- drm_sched_fini(&v3d->queue[V3D_BIN].sched);
-+ v3d_sched_fini(v3d);
- return ret;
- }
-
-+ if (v3d_has_csd(v3d)) {
-+ ret = drm_sched_init(&v3d->queue[V3D_CSD].sched,
-+ &v3d_csd_sched_ops,
-+ hw_jobs_limit, job_hang_limit,
-+ msecs_to_jiffies(hang_limit_ms),
-+ "v3d_csd");
-+ if (ret) {
-+ dev_err(v3d->dev, "Failed to create CSD scheduler: %d.",
-+ ret);
-+ v3d_sched_fini(v3d);
-+ return ret;
-+ }
-+
-+ ret = drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched,
-+ &v3d_cache_clean_sched_ops,
-+ hw_jobs_limit, job_hang_limit,
-+ msecs_to_jiffies(hang_limit_ms),
-+ "v3d_cache_clean");
-+ if (ret) {
-+ dev_err(v3d->dev, "Failed to create CACHE_CLEAN scheduler: %d.",
-+ ret);
-+ v3d_sched_fini(v3d);
-+ return ret;
-+ }
-+ }
-+
- return 0;
- }
-
-@@ -356,6 +461,8 @@ v3d_sched_fini(struct v3d_dev *v3d)
- {
- enum v3d_queue q;
-
-- for (q = 0; q < V3D_MAX_QUEUES; q++)
-- drm_sched_fini(&v3d->queue[q].sched);
-+ for (q = 0; q < V3D_MAX_QUEUES; q++) {
-+ if (v3d->queue[q].sched.ops)
-+ drm_sched_fini(&v3d->queue[q].sched);
-+ }
- }
---- a/drivers/gpu/drm/v3d/v3d_trace.h
-+++ b/drivers/gpu/drm/v3d/v3d_trace.h
-@@ -124,6 +124,26 @@ TRACE_EVENT(v3d_tfu_irq,
- __entry->seqno)
- );
-
-+TRACE_EVENT(v3d_csd_irq,
-+ TP_PROTO(struct drm_device *dev,
-+ uint64_t seqno),
-+ TP_ARGS(dev, seqno),
-+
-+ TP_STRUCT__entry(
-+ __field(u32, dev)
-+ __field(u64, seqno)
-+ ),
-+
-+ TP_fast_assign(
-+ __entry->dev = dev->primary->index;
-+ __entry->seqno = seqno;
-+ ),
-+
-+ TP_printk("dev=%u, seqno=%llu",
-+ __entry->dev,
-+ __entry->seqno)
-+);
-+
- TRACE_EVENT(v3d_submit_tfu_ioctl,
- TP_PROTO(struct drm_device *dev, u32 iia),
- TP_ARGS(dev, iia),
-@@ -163,6 +183,80 @@ TRACE_EVENT(v3d_submit_tfu,
- __entry->seqno)
- );
-
-+TRACE_EVENT(v3d_submit_csd_ioctl,
-+ TP_PROTO(struct drm_device *dev, u32 cfg5, u32 cfg6),
-+ TP_ARGS(dev, cfg5, cfg6),
-+
-+ TP_STRUCT__entry(
-+ __field(u32, dev)
-+ __field(u32, cfg5)
-+ __field(u32, cfg6)
-+ ),
-+
-+ TP_fast_assign(
-+ __entry->dev = dev->primary->index;
-+ __entry->cfg5 = cfg5;
-+ __entry->cfg6 = cfg6;
-+ ),
-+
-+ TP_printk("dev=%u, CFG5 0x%08x, CFG6 0x%08x",
-+ __entry->dev,
-+ __entry->cfg5,
-+ __entry->cfg6)
-+);
-+
-+TRACE_EVENT(v3d_submit_csd,
-+ TP_PROTO(struct drm_device *dev,
-+ uint64_t seqno),
-+ TP_ARGS(dev, seqno),
-+
-+ TP_STRUCT__entry(
-+ __field(u32, dev)
-+ __field(u64, seqno)
-+ ),
-+
-+ TP_fast_assign(
-+ __entry->dev = dev->primary->index;
-+ __entry->seqno = seqno;
-+ ),
-+
-+ TP_printk("dev=%u, seqno=%llu",
-+ __entry->dev,
-+ __entry->seqno)
-+);
-+
-+TRACE_EVENT(v3d_cache_clean_begin,
-+ TP_PROTO(struct drm_device *dev),
-+ TP_ARGS(dev),
-+
-+ TP_STRUCT__entry(
-+ __field(u32, dev)
-+ ),
-+
-+ TP_fast_assign(
-+ __entry->dev = dev->primary->index;
-+ ),
-+
-+ TP_printk("dev=%u",
-+ __entry->dev)
-+);
-+
-+TRACE_EVENT(v3d_cache_clean_end,
-+ TP_PROTO(struct drm_device *dev),
-+ TP_ARGS(dev),
-+
-+ TP_STRUCT__entry(
-+ __field(u32, dev)
-+ ),
-+
-+ TP_fast_assign(
-+ __entry->dev = dev->primary->index;
-+ ),
-+
-+ TP_printk("dev=%u",
-+ __entry->dev)
-+);
-+
- TRACE_EVENT(v3d_reset_begin,
- TP_PROTO(struct drm_device *dev),
- TP_ARGS(dev),
---- a/include/uapi/drm/v3d_drm.h
-+++ b/include/uapi/drm/v3d_drm.h
-@@ -37,6 +37,7 @@ extern "C" {
- #define DRM_V3D_GET_PARAM 0x04
- #define DRM_V3D_GET_BO_OFFSET 0x05
- #define DRM_V3D_SUBMIT_TFU 0x06
-+#define DRM_V3D_SUBMIT_CSD 0x07
-
- #define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
- #define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
-@@ -45,6 +46,7 @@ extern "C" {
- #define DRM_IOCTL_V3D_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)
- #define DRM_IOCTL_V3D_GET_BO_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
- #define DRM_IOCTL_V3D_SUBMIT_TFU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
-+#define DRM_IOCTL_V3D_SUBMIT_CSD DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CSD, struct drm_v3d_submit_csd)
-
- /**
- * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
-@@ -172,6 +174,7 @@ enum drm_v3d_param {
- DRM_V3D_PARAM_V3D_CORE0_IDENT1,
- DRM_V3D_PARAM_V3D_CORE0_IDENT2,
- DRM_V3D_PARAM_SUPPORTS_TFU,
-+ DRM_V3D_PARAM_SUPPORTS_CSD,
- };
-
- struct drm_v3d_get_param {
-@@ -212,6 +215,31 @@ struct drm_v3d_submit_tfu {
- __u32 out_sync;
- };
-
-+/* Submits a compute shader for dispatch. This job will block on any
-+ * previous compute shaders submitted on this fd, and any other
-+ * synchronization must be performed with in_sync/out_sync.
-+ */
-+struct drm_v3d_submit_csd {
-+ __u32 cfg[7];
-+ __u32 coef[4];
-+
-+ /* Pointer to a u32 array of the BOs that are referenced by the job.
-+ */
-+ __u64 bo_handles;
-+
-+ /* Number of BO handles passed in (size is that times 4). */
-+ __u32 bo_handle_count;
-+
-+ /* sync object to block on before running the CSD job. Each
-+ * CSD job will execute in the order submitted to its FD.
-+ * Synchronization against rendering/TFU jobs or CSD from
-+ * other fds requires using sync objects.
-+ */
-+ __u32 in_sync;
-+ /* Sync object to signal when the CSD job is done. */
-+ __u32 out_sync;
-+};
-+
- #if defined(__cplusplus)
- }
- #endif
--- /dev/null
+From 8a35a7bb6b1a0182adf1e92d138b7d88f93abbb6 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 7 May 2019 12:13:34 +0100
+Subject: [PATCH 616/725] drm: vc4: Log flags in fkms mode set
+
+The flags contain info such as limited/full range RGB, aspect
+ratio, and a fwe other useful things.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -685,12 +685,13 @@ static void vc4_crtc_mode_set_nofb(struc
+ return;
+ }
+
+- DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u\n",
++ DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u, flags 0x%04x\n",
+ vc4_crtc->display_number, mode->name, mode->clock,
+ mode->hdisplay, mode->hsync_start, mode->hsync_end,
+ mode->htotal, mode->hskew, mode->vdisplay,
+ mode->vsync_start, mode->vsync_end, mode->vtotal,
+- mode->vscan, mode->vrefresh, mode->picture_aspect_ratio);
++ mode->vscan, mode->vrefresh, mode->picture_aspect_ratio,
++ mode->flags);
+ mb.timings.display = vc4_crtc->display_number;
+
+ mb.timings.video_id_code = frame.avi.video_code;
+++ /dev/null
-From 167429373da6ab4f3f498013277eb5545d6f0c64 Mon Sep 17 00:00:00 2001
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 2 May 2019 13:22:53 -0700
-Subject: [PATCH 617/703] drm/v3d: Clock V3D down when not in use.
-
-My various attempts at re-enabling runtime PM have failed, so just
-crank the clock down when V3D is idle to reduce power consumption.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
- drivers/gpu/drm/v3d/v3d_drv.c | 18 +++++++++++++
- drivers/gpu/drm/v3d/v3d_drv.h | 6 +++++
- drivers/gpu/drm/v3d/v3d_gem.c | 49 +++++++++++++++++++++++++++++++++++
- 3 files changed, 73 insertions(+)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -297,6 +297,21 @@ static int v3d_platform_drm_probe(struct
- }
- }
-
-+ v3d->clk = devm_clk_get(dev, NULL);
-+ if (IS_ERR(v3d->clk)) {
-+ if (ret != -EPROBE_DEFER)
-+ dev_err(dev, "Failed to get clock\n");
-+ goto dev_free;
-+ }
-+ v3d->clk_up_rate = clk_get_rate(v3d->clk);
-+ /* For downclocking, drop it to the minimum frequency we can get from
-+ * the CPRMAN clock generator dividing off our parent. The divider is
-+ * 4 bits, but ask for just higher than that so that rounding doesn't
-+ * make cprman reject our rate.
-+ */
-+ v3d->clk_down_rate =
-+ (clk_get_rate(clk_get_parent(v3d->clk)) / (1 << 4)) + 10000;
-+
- if (v3d->ver < 41) {
- ret = map_regs(v3d, &v3d->gca_regs, "gca");
- if (ret)
-@@ -331,6 +346,9 @@ static int v3d_platform_drm_probe(struct
- if (ret)
- goto irq_disable;
-
-+ ret = clk_set_rate(v3d->clk, v3d->clk_down_rate);
-+ WARN_ON_ONCE(ret != 0);
-+
- return 0;
-
- irq_disable:
---- a/drivers/gpu/drm/v3d/v3d_drv.h
-+++ b/drivers/gpu/drm/v3d/v3d_drv.h
-@@ -45,6 +45,12 @@ struct v3d_dev {
- void __iomem *bridge_regs;
- void __iomem *gca_regs;
- struct clk *clk;
-+ struct delayed_work clk_down_work;
-+ unsigned long clk_up_rate, clk_down_rate;
-+ struct mutex clk_lock;
-+ u32 clk_refcount;
-+ bool clk_up;
-+
- struct reset_control *reset;
-
- /* Virtual and DMA addresses of the single shared page table. */
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -3,6 +3,7 @@
-
- #include <drm/drmP.h>
- #include <drm/drm_syncobj.h>
-+#include <linux/clk.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/pm_runtime.h>
-@@ -17,6 +18,47 @@
- #include "v3d_trace.h"
-
- static void
-+v3d_clock_down_work(struct work_struct *work)
-+{
-+ struct v3d_dev *v3d =
-+ container_of(work, struct v3d_dev, clk_down_work.work);
-+ int ret;
-+
-+ ret = clk_set_rate(v3d->clk, v3d->clk_down_rate);
-+ v3d->clk_up = false;
-+ WARN_ON_ONCE(ret != 0);
-+}
-+
-+static void
-+v3d_clock_up_get(struct v3d_dev *v3d)
-+{
-+ mutex_lock(&v3d->clk_lock);
-+ if (v3d->clk_refcount++ == 0) {
-+ cancel_delayed_work_sync(&v3d->clk_down_work);
-+ if (!v3d->clk_up) {
-+ int ret;
-+
-+ ret = clk_set_rate(v3d->clk, v3d->clk_up_rate);
-+ WARN_ON_ONCE(ret != 0);
-+ v3d->clk_up = true;
-+ }
-+ }
-+ mutex_unlock(&v3d->clk_lock);
-+}
-+
-+static void
-+v3d_clock_up_put(struct v3d_dev *v3d)
-+{
-+ mutex_lock(&v3d->clk_lock);
-+ if (--v3d->clk_refcount == 0) {
-+ schedule_delayed_work(&v3d->clk_down_work,
-+ msecs_to_jiffies(100));
-+ }
-+ mutex_unlock(&v3d->clk_lock);
-+}
-+
-+
-+static void
- v3d_init_core(struct v3d_dev *v3d, int core)
- {
- /* Set OVRTMUOUT, which means that the texture sampler uniform
-@@ -490,6 +532,7 @@ static void
- v3d_job_free(struct kref *ref)
- {
- struct v3d_job *job = container_of(ref, struct v3d_job, refcount);
-+ struct v3d_dev *v3d = job->v3d;
- int i;
-
- for (i = 0; i < job->bo_count; i++) {
-@@ -505,6 +548,8 @@ v3d_job_free(struct kref *ref)
- dma_fence_put(job->irq_fence);
- dma_fence_put(job->done_fence);
-
-+ v3d_clock_up_put(v3d);
-+
- kfree(job);
- }
-
-@@ -596,6 +641,7 @@ v3d_job_init(struct v3d_dev *v3d, struct
- if (ret)
- return ret;
-
-+ v3d_clock_up_get(v3d);
- kref_init(&job->refcount);
-
- return 0;
-@@ -963,6 +1009,9 @@ v3d_gem_init(struct drm_device *dev)
- mutex_init(&v3d->sched_lock);
- mutex_init(&v3d->cache_clean_lock);
-
-+ mutex_init(&v3d->clk_lock);
-+ INIT_DELAYED_WORK(&v3d->clk_down_work, v3d_clock_down_work);
-+
- /* Note: We don't allocate address 0. Various bits of HW
- * treat 0 as special, such as the occlusion query counters
- * where 0 means "disabled".
--- /dev/null
+From aee8bec6a1a39eb97dd5af86b4126d5e1ced2ac6 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 16 May 2019 17:49:42 +0100
+Subject: [PATCH 617/725] drm: vc4-firmware-kms: Fix DSI display support
+
+The mode was incorrectly listed as interlaced, which was then
+rejected.
+Correct this and FKMS works with the DSI display.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -1003,7 +1003,7 @@ static const struct drm_display_mode lcd
+ 25979400 / 1000,
+ 800, 800 + 1, 800 + 1 + 2, 800 + 1 + 2 + 46, 0,
+ 480, 480 + 7, 480 + 7 + 2, 480 + 7 + 2 + 21, 0,
+- DRM_MODE_FLAG_INTERLACE)
++ 0)
+ };
+
+ static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
+++ /dev/null
-From 00f31bede51da02552b235fc93d35f357f13378a Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Thu, 2 May 2019 23:42:29 +0200
-Subject: [PATCH 618/703] HACK: clk-bcm2835: Add BCM2838_CLOCK_EMMC2 support
-
-The new BCM2838 supports an additional emmc2 clock. So add a new
-compatible to register this clock only for BCM2838.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- drivers/clk/bcm/clk-bcm2835.c | 20 ++++++++++++++++++--
- include/dt-bindings/clock/bcm2835.h | 2 ++
- 2 files changed, 20 insertions(+), 2 deletions(-)
-
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -124,6 +124,8 @@
- #define CM_AVEODIV 0x1bc
- #define CM_EMMCCTL 0x1c0
- #define CM_EMMCDIV 0x1c4
-+#define CM_EMMC2CTL 0x1d0
-+#define CM_EMMC2DIV 0x1d4
-
- /* General bits for the CM_*CTL regs */
- # define CM_ENABLE BIT(4)
-@@ -2047,6 +2049,15 @@ static const struct bcm2835_clk_desc clk
- .frac_bits = 8,
- .tcnt_mux = 39),
-
-+ /* EMMC2 clock (only available for BCM2838) */
-+ [BCM2838_CLOCK_EMMC2] = REGISTER_PER_CLK(
-+ .name = "emmc2",
-+ .ctl_reg = CM_EMMC2CTL,
-+ .div_reg = CM_EMMC2DIV,
-+ .int_bits = 4,
-+ .frac_bits = 8,
-+ .tcnt_mux = 42),
-+
- /* General purpose (GPIO) clocks */
- [BCM2835_CLOCK_GP0] = REGISTER_PER_CLK(
- .name = "gp0",
-@@ -2276,8 +2287,12 @@ static int bcm2835_clk_probe(struct plat
-
- for (i = 0; i < asize; i++) {
- desc = &clk_desc_array[i];
-- if (desc->clk_register && desc->data)
-- hws[i] = desc->clk_register(cprman, desc->data);
-+ if (desc->clk_register && desc->data) {
-+ if ((i != BCM2838_CLOCK_EMMC2) ||
-+ of_device_is_compatible(fw_node, "brcm,bcm2838-cprman")) {
-+ hws[i] = desc->clk_register(cprman, desc->data);
-+ }
-+ }
- }
-
- ret = bcm2835_mark_sdc_parent_critical(hws[BCM2835_CLOCK_SDRAM]->clk);
-@@ -2297,6 +2312,7 @@ static int bcm2835_clk_probe(struct plat
-
- static const struct of_device_id bcm2835_clk_of_match[] = {
- { .compatible = "brcm,bcm2835-cprman", },
-+ { .compatible = "brcm,bcm2838-cprman", },
- {}
- };
- MODULE_DEVICE_TABLE(of, bcm2835_clk_of_match);
---- a/include/dt-bindings/clock/bcm2835.h
-+++ b/include/dt-bindings/clock/bcm2835.h
-@@ -66,3 +66,5 @@
- #define BCM2835_CLOCK_DSI1E 48
- #define BCM2835_CLOCK_DSI0P 49
- #define BCM2835_CLOCK_DSI1P 50
-+
-+#define BCM2838_CLOCK_EMMC2 51
--- /dev/null
+From f77057c81999f0cf6da1c4eab08ce57189279a14 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 21 May 2019 11:50:00 +0100
+Subject: [PATCH 618/725] drm: vc4: Probe DPI/DSI timings from the firmware
+
+For DPI and DSI displays query the firmware as to the configuration
+and add it as the only mode for DRM.
+
+In theory we can add plumbing for setting the DPI/DSI mode from
+KMS, but this is not being added at present as the support frameworks
+aren't present in the firmware.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 60 ++++++++++++++++++----
+ include/soc/bcm2835/raspberrypi-firmware.h | 1 +
+ 2 files changed, 51 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -280,7 +280,7 @@ static u32 vc4_get_display_type(u32 disp
+ /* The firmware display (DispmanX) IDs map to specific types in
+ * a fixed manner.
+ */
+- DRM_MODE_ENCODER_DSI, /* MAIN_LCD */
++ DRM_MODE_ENCODER_DSI, /* MAIN_LCD - DSI or DPI */
+ DRM_MODE_ENCODER_DSI, /* AUX_LCD */
+ DRM_MODE_ENCODER_TMDS, /* HDMI0 */
+ DRM_MODE_ENCODER_TVDAC, /* VEC */
+@@ -362,7 +362,6 @@ static void vc4_plane_atomic_update(stru
+ vc4_get_vc_image_fmt(drm_fmt->format);
+ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
+ struct mailbox_set_plane *mb = &vc4_plane->mb;
+- struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
+ int num_planes = fb->format->num_planes;
+ struct drm_display_mode *mode = &state->crtc->mode;
+ unsigned int rotation = SUPPORTED_ROTATIONS;
+@@ -997,7 +996,9 @@ static int vc4_fkms_connector_get_modes(
+ return ret;
+ }
+
+-/* FIXME: Read LCD mode from the firmware. This is the DSI panel resolution. */
++/* This is the DSI panel resolution. Use this as a default should the firmware
++ * not respond to our request for the timings.
++ */
+ static const struct drm_display_mode lcd_mode = {
+ DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+ 25979400 / 1000,
+@@ -1008,15 +1009,54 @@ static const struct drm_display_mode lcd
+
+ static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
+ {
+- //struct vc4_fkms_connector *fkms_connector =
+- // to_vc4_fkms_connector(connector);
+- //struct drm_encoder *encoder = fkms_connector->encoder;
+- //struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
++ struct vc4_fkms_connector *fkms_connector =
++ to_vc4_fkms_connector(connector);
++ struct vc4_dev *vc4 = fkms_connector->vc4_dev;
+ struct drm_display_mode *mode;
+- //int ret = 0;
++ struct mailbox_set_mode mb = {
++ .tag1 = { RPI_FIRMWARE_GET_DISPLAY_TIMING,
++ sizeof(struct set_timings), 0},
++ .timings = { .display = fkms_connector->display_number },
++ };
++ struct drm_display_mode fw_mode;
++ int ret = 0;
++
++ ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
++ if (!ret) {
++ /* Equivalent to DRM_MODE macro. */
++ memset(&fw_mode, 0, sizeof(fw_mode));
++ strncpy(fw_mode.name, "LCD_MODE", sizeof(fw_mode.name));
++ fw_mode.status = 0;
++ fw_mode.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
++ fw_mode.clock = mb.timings.clock;
++ fw_mode.hdisplay = mb.timings.hdisplay;
++ fw_mode.hsync_start = mb.timings.hsync_start;
++ fw_mode.hsync_end = mb.timings.hsync_end;
++ fw_mode.htotal = mb.timings.htotal;
++ fw_mode.hskew = 0;
++ fw_mode.vdisplay = mb.timings.vdisplay;
++ fw_mode.vsync_start = mb.timings.vsync_start;
++ fw_mode.vsync_end = mb.timings.vsync_end;
++ fw_mode.vtotal = mb.timings.vtotal;
++ fw_mode.vscan = mb.timings.vscan;
++ if (mb.timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
++ fw_mode.flags |= DRM_MODE_FLAG_PHSYNC;
++ else
++ fw_mode.flags |= DRM_MODE_FLAG_NHSYNC;
++ if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
++ fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
++ else
++ fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
++
++ fw_mode.base.type = DRM_MODE_OBJECT_MODE;
++
++ mode = drm_mode_duplicate(connector->dev,
++ &fw_mode);
++ } else {
++ mode = drm_mode_duplicate(connector->dev,
++ &lcd_mode);
++ }
+
+- mode = drm_mode_duplicate(connector->dev,
+- &lcd_mode);
+ if (!mode) {
+ DRM_ERROR("Failed to create a new display mode\n");
+ return -ENOMEM;
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -151,6 +151,7 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
+
+ RPI_FIRMWARE_SET_PLANE = 0x00048015,
++ RPI_FIRMWARE_GET_DISPLAY_TIMING = 0x00040017,
+ RPI_FIRMWARE_SET_TIMING = 0x00048017,
+
+ RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
+++ /dev/null
-From 7e50ab877c14dff56f0836d6b79d9f6964b5e8b1 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 3 May 2019 13:58:03 +0100
-Subject: [PATCH 619/703] drm: vc4-firmware-kms: Remove incorrect overscan
- support.
-
-The overscan support was required for the old mailbox API
-in order to match up the cursor and frame buffer planes.
-With the newer API directly talking to dispmanx there is no
-difference, therefore FKMS does not need to make any
-adjustments.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 15 ---------------
- 1 file changed, 15 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -232,7 +232,6 @@ struct vc4_crtc {
- void __iomem *regs;
-
- struct drm_pending_vblank_event *event;
-- u32 overscan[4];
- bool vblank_enabled;
- u32 display_number;
- u32 display_type;
-@@ -468,11 +467,6 @@ static void vc4_plane_atomic_update(stru
- break;
- }
-
-- if (vc4_crtc) {
-- mb->plane.dst_x += vc4_crtc->overscan[0];
-- mb->plane.dst_y += vc4_crtc->overscan[1];
-- }
--
- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane update %dx%d@%d +dst(%d,%d, %d,%d) +src(%d,%d, %d,%d) 0x%08x/%08x/%08x/%d, alpha %u zpos %u\n",
- plane->base.id, plane->name,
- mb->plane.width,
-@@ -1228,15 +1222,6 @@ static int vc4_fkms_create_screen(struct
- goto err_destroy_encoder;
- }
-
-- ret = rpi_firmware_property(vc4->firmware,
-- RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN,
-- &vc4_crtc->overscan,
-- sizeof(vc4_crtc->overscan));
-- if (ret) {
-- DRM_ERROR("Failed to get overscan state: 0x%08x\n", vc4_crtc->overscan[0]);
-- memset(&vc4_crtc->overscan, 0, sizeof(vc4_crtc->overscan));
-- }
--
- *ret_crtc = vc4_crtc;
-
- return 0;
--- /dev/null
+From 234c55d9e6bb7fa68466a599bd1665bcd89a99d2 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 28 May 2019 13:56:06 +0100
+Subject: [PATCH 619/725] drm: vc4: handle the case where there are no
+ available displays
+
+It's reasonable for the firmware to return zero as the number of
+attached displays. Handle this case as otherwise drm thinks that
+the DSI panel is attached, which is nonsense.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 32 +++++++++++++++-----------
+ 1 file changed, 18 insertions(+), 14 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -1309,13 +1309,13 @@ static int vc4_fkms_bind(struct device *
+ RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
+ &num_displays, sizeof(u32));
+
+- /* If we fail to get the number of displays, or it returns 0, then
++ /* If we fail to get the number of displays, then
+ * assume old firmware that doesn't have the mailbox call, so just
+ * set one display
+ */
+- if (ret || num_displays == 0) {
++ if (ret) {
+ num_displays = 1;
+- DRM_WARN("Unable to determine number of displays's. Assuming 1\n");
++ DRM_WARN("Unable to determine number of displays - assuming 1\n");
+ ret = 0;
+ }
+
+@@ -1344,17 +1344,21 @@ static int vc4_fkms_bind(struct device *
+ display_num);
+ }
+
+- /* Map the SMI interrupt reg */
+- crtc_list[0]->regs = vc4_ioremap_regs(pdev, 0);
+- if (IS_ERR(crtc_list[0]->regs))
+- DRM_ERROR("Oh dear, failed to map registers\n");
+-
+- writel(0, crtc_list[0]->regs + SMICS);
+- ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
+- vc4_crtc_irq_handler, 0, "vc4 firmware kms",
+- crtc_list);
+- if (ret)
+- DRM_ERROR("Oh dear, failed to register IRQ\n");
++ if (num_displays > 0) {
++ /* Map the SMI interrupt reg */
++ crtc_list[0]->regs = vc4_ioremap_regs(pdev, 0);
++ if (IS_ERR(crtc_list[0]->regs))
++ DRM_ERROR("Oh dear, failed to map registers\n");
++
++ writel(0, crtc_list[0]->regs + SMICS);
++ ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
++ vc4_crtc_irq_handler, 0,
++ "vc4 firmware kms", crtc_list);
++ if (ret)
++ DRM_ERROR("Oh dear, failed to register IRQ\n");
++ } else {
++ DRM_WARN("No displays found. Consider forcing hotplug if HDMI is attached\n");
++ }
+
+ platform_set_drvdata(pdev, crtc_list);
+
+++ /dev/null
-From 5ab2c06953f0ef6da029ced94ca7468057e7ecb3 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 7 May 2019 12:13:34 +0100
-Subject: [PATCH 620/703] drm: vc4: Log flags in fkms mode set
-
-The flags contain info such as limited/full range RGB, aspect
-ratio, and a fwe other useful things.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -685,12 +685,13 @@ static void vc4_crtc_mode_set_nofb(struc
- return;
- }
-
-- DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u\n",
-+ DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u, flags 0x%04x\n",
- vc4_crtc->display_number, mode->name, mode->clock,
- mode->hdisplay, mode->hsync_start, mode->hsync_end,
- mode->htotal, mode->hskew, mode->vdisplay,
- mode->vsync_start, mode->vsync_end, mode->vtotal,
-- mode->vscan, mode->vrefresh, mode->picture_aspect_ratio);
-+ mode->vscan, mode->vrefresh, mode->picture_aspect_ratio,
-+ mode->flags);
- mb.timings.display = vc4_crtc->display_number;
-
- mb.timings.video_id_code = frame.avi.video_code;
--- /dev/null
+From e2e439eb235a75c4719d52b5c7c60ed782727010 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 24 May 2019 17:59:01 +0100
+Subject: [PATCH 620/725] drm/vc4: Support the VEC in FKMS
+
+Extends the DPI/DSI support to also report the VEC output
+which supports interlacing too.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -125,6 +125,7 @@ struct set_timings {
+ #define TIMINGS_FLAGS_H_SYNC_NEG 0
+ #define TIMINGS_FLAGS_V_SYNC_POS BIT(1)
+ #define TIMINGS_FLAGS_V_SYNC_NEG 0
++#define TIMINGS_FLAGS_INTERLACE BIT(2)
+
+ #define TIMINGS_FLAGS_ASPECT_MASK GENMASK(7, 4)
+ #define TIMINGS_FLAGS_ASPECT_NONE (0 << 4)
+@@ -1047,6 +1048,12 @@ static int vc4_fkms_lcd_connector_get_mo
+ fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
+ else
+ fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
++ if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
++ fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
++ else
++ fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
++ if (mb.timings.flags & TIMINGS_FLAGS_INTERLACE)
++ fw_mode.flags |= DRM_MODE_FLAG_INTERLACE;
+
+ fw_mode.base.type = DRM_MODE_OBJECT_MODE;
+
+@@ -1133,17 +1140,24 @@ vc4_fkms_connector_init(struct drm_devic
+ DRM_MODE_CONNECTOR_DSI);
+ drm_connector_helper_add(connector,
+ &vc4_fkms_lcd_conn_helper_funcs);
++ connector->interlace_allowed = 0;
++ } else if (fkms_connector->display_type == DRM_MODE_ENCODER_TVDAC) {
++ drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
++ DRM_MODE_CONNECTOR_Composite);
++ drm_connector_helper_add(connector,
++ &vc4_fkms_lcd_conn_helper_funcs);
++ connector->interlace_allowed = 1;
+ } else {
+ drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA);
+ drm_connector_helper_add(connector,
+ &vc4_fkms_connector_helper_funcs);
++ connector->interlace_allowed = 0;
+ }
+
+ connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT);
+
+- connector->interlace_allowed = 0;
+ connector->doublescan_allowed = 0;
+
+ drm_connector_attach_encoder(connector, encoder);
--- /dev/null
+From 6019920db110cd6c181d7843794a71b8736c2697 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 7 May 2019 15:00:02 +0100
+Subject: [PATCH 621/725] drm: vc4: Fixup typo when setting HDMI aspect ratio
+
+Assignment was to the wrong structure.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -717,19 +717,19 @@ static void vc4_crtc_mode_set_nofb(struc
+ switch (frame.avi.picture_aspect) {
+ default:
+ case HDMI_PICTURE_ASPECT_NONE:
+- mode->flags |= TIMINGS_FLAGS_ASPECT_NONE;
++ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_NONE;
+ break;
+ case HDMI_PICTURE_ASPECT_4_3:
+- mode->flags |= TIMINGS_FLAGS_ASPECT_4_3;
++ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_4_3;
+ break;
+ case HDMI_PICTURE_ASPECT_16_9:
+- mode->flags |= TIMINGS_FLAGS_ASPECT_16_9;
++ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_16_9;
+ break;
+ case HDMI_PICTURE_ASPECT_64_27:
+- mode->flags |= TIMINGS_FLAGS_ASPECT_64_27;
++ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_64_27;
+ break;
+ case HDMI_PICTURE_ASPECT_256_135:
+- mode->flags |= TIMINGS_FLAGS_ASPECT_256_135;
++ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_256_135;
+ break;
+ }
+
+++ /dev/null
-From 5812f56a56140b70c110c22824d196c6abb866be Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 16 May 2019 17:49:42 +0100
-Subject: [PATCH 621/703] drm: vc4-firmware-kms: Fix DSI display support
-
-The mode was incorrectly listed as interlaced, which was then
-rejected.
-Correct this and FKMS works with the DSI display.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -1003,7 +1003,7 @@ static const struct drm_display_mode lcd
- 25979400 / 1000,
- 800, 800 + 1, 800 + 1 + 2, 800 + 1 + 2 + 46, 0,
- 480, 480 + 7, 480 + 7 + 2, 480 + 7 + 2 + 21, 0,
-- DRM_MODE_FLAG_INTERLACE)
-+ 0)
- };
-
- static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
--- /dev/null
+From a8ff82f4ae5871be6632d231692d5149976c0eeb Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 29 May 2019 15:44:11 +0100
+Subject: [PATCH 622/725] drm/vc4: Correct SAND support for FKMS.
+
+It was accepting NV21 which doesn't map through, but
+also wasn't advertising the modifier so nothing would know
+to request it.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -545,7 +545,6 @@ static bool vc4_fkms_format_mod_supporte
+ return false;
+ }
+ case DRM_FORMAT_NV12:
+- case DRM_FORMAT_NV21:
+ switch (fourcc_mod_broadcom_mod(modifier)) {
+ case DRM_FORMAT_MOD_LINEAR:
+ case DRM_FORMAT_MOD_BROADCOM_SAND128:
+@@ -553,6 +552,7 @@ static bool vc4_fkms_format_mod_supporte
+ default:
+ return false;
+ }
++ case DRM_FORMAT_NV21:
+ case DRM_FORMAT_RGB888:
+ case DRM_FORMAT_BGR888:
+ case DRM_FORMAT_YUV422:
+@@ -599,6 +599,7 @@ static struct drm_plane *vc4_fkms_plane_
+ * would prefer to scan out linear (less bus traffic).
+ */
+ DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
++ DRM_FORMAT_MOD_BROADCOM_SAND128,
+ DRM_FORMAT_MOD_INVALID,
+ };
+ int i;
+++ /dev/null
-From d5db7a4a6af4b3281ac2ef1023de68e4f6250516 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 21 May 2019 11:50:00 +0100
-Subject: [PATCH 622/703] drm: vc4: Probe DPI/DSI timings from the firmware
-
-For DPI and DSI displays query the firmware as to the configuration
-and add it as the only mode for DRM.
-
-In theory we can add plumbing for setting the DPI/DSI mode from
-KMS, but this is not being added at present as the support frameworks
-aren't present in the firmware.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 60 ++++++++++++++++++----
- include/soc/bcm2835/raspberrypi-firmware.h | 1 +
- 2 files changed, 51 insertions(+), 10 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -280,7 +280,7 @@ static u32 vc4_get_display_type(u32 disp
- /* The firmware display (DispmanX) IDs map to specific types in
- * a fixed manner.
- */
-- DRM_MODE_ENCODER_DSI, /* MAIN_LCD */
-+ DRM_MODE_ENCODER_DSI, /* MAIN_LCD - DSI or DPI */
- DRM_MODE_ENCODER_DSI, /* AUX_LCD */
- DRM_MODE_ENCODER_TMDS, /* HDMI0 */
- DRM_MODE_ENCODER_TVDAC, /* VEC */
-@@ -362,7 +362,6 @@ static void vc4_plane_atomic_update(stru
- vc4_get_vc_image_fmt(drm_fmt->format);
- struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
- struct mailbox_set_plane *mb = &vc4_plane->mb;
-- struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
- int num_planes = fb->format->num_planes;
- struct drm_display_mode *mode = &state->crtc->mode;
- unsigned int rotation = SUPPORTED_ROTATIONS;
-@@ -997,7 +996,9 @@ static int vc4_fkms_connector_get_modes(
- return ret;
- }
-
--/* FIXME: Read LCD mode from the firmware. This is the DSI panel resolution. */
-+/* This is the DSI panel resolution. Use this as a default should the firmware
-+ * not respond to our request for the timings.
-+ */
- static const struct drm_display_mode lcd_mode = {
- DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
- 25979400 / 1000,
-@@ -1008,15 +1009,54 @@ static const struct drm_display_mode lcd
-
- static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
- {
-- //struct vc4_fkms_connector *fkms_connector =
-- // to_vc4_fkms_connector(connector);
-- //struct drm_encoder *encoder = fkms_connector->encoder;
-- //struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
-+ struct vc4_fkms_connector *fkms_connector =
-+ to_vc4_fkms_connector(connector);
-+ struct vc4_dev *vc4 = fkms_connector->vc4_dev;
- struct drm_display_mode *mode;
-- //int ret = 0;
-+ struct mailbox_set_mode mb = {
-+ .tag1 = { RPI_FIRMWARE_GET_DISPLAY_TIMING,
-+ sizeof(struct set_timings), 0},
-+ .timings = { .display = fkms_connector->display_number },
-+ };
-+ struct drm_display_mode fw_mode;
-+ int ret = 0;
-+
-+ ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
-+ if (!ret) {
-+ /* Equivalent to DRM_MODE macro. */
-+ memset(&fw_mode, 0, sizeof(fw_mode));
-+ strncpy(fw_mode.name, "LCD_MODE", sizeof(fw_mode.name));
-+ fw_mode.status = 0;
-+ fw_mode.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-+ fw_mode.clock = mb.timings.clock;
-+ fw_mode.hdisplay = mb.timings.hdisplay;
-+ fw_mode.hsync_start = mb.timings.hsync_start;
-+ fw_mode.hsync_end = mb.timings.hsync_end;
-+ fw_mode.htotal = mb.timings.htotal;
-+ fw_mode.hskew = 0;
-+ fw_mode.vdisplay = mb.timings.vdisplay;
-+ fw_mode.vsync_start = mb.timings.vsync_start;
-+ fw_mode.vsync_end = mb.timings.vsync_end;
-+ fw_mode.vtotal = mb.timings.vtotal;
-+ fw_mode.vscan = mb.timings.vscan;
-+ if (mb.timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
-+ fw_mode.flags |= DRM_MODE_FLAG_PHSYNC;
-+ else
-+ fw_mode.flags |= DRM_MODE_FLAG_NHSYNC;
-+ if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
-+ fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
-+ else
-+ fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
-+
-+ fw_mode.base.type = DRM_MODE_OBJECT_MODE;
-+
-+ mode = drm_mode_duplicate(connector->dev,
-+ &fw_mode);
-+ } else {
-+ mode = drm_mode_duplicate(connector->dev,
-+ &lcd_mode);
-+ }
-
-- mode = drm_mode_duplicate(connector->dev,
-- &lcd_mode);
- if (!mode) {
- DRM_ERROR("Failed to create a new display mode\n");
- return -ENOMEM;
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -151,6 +151,7 @@ enum rpi_firmware_property_tag {
- RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
-
- RPI_FIRMWARE_SET_PLANE = 0x00048015,
-+ RPI_FIRMWARE_GET_DISPLAY_TIMING = 0x00040017,
- RPI_FIRMWARE_SET_TIMING = 0x00048017,
-
- RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
--- /dev/null
+From a1a297d0fd4b5ec427be523ed73afc5762f83595 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 30 May 2019 13:56:15 +0100
+Subject: [PATCH 623/725] drm/vc4: fkms to query the VPU for HDMI clock limits
+
+The VPU has configured clocks for 4k (or not) via config.txt,
+and will limit the choice of video modes based on that.
+Make fkms query it for these limits too to avoid selecting modes
+that can not be handled by the current clock setup.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_drv.h | 1 +
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 48 ++++++++++++++++++++++
+ include/soc/bcm2835/raspberrypi-firmware.h | 1 +
+ 3 files changed, 50 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_drv.h
++++ b/drivers/gpu/drm/vc4/vc4_drv.h
+@@ -77,6 +77,7 @@ struct vc4_dev {
+ struct vc4_dsi *dsi1;
+ struct vc4_vec *vec;
+ struct vc4_txp *txp;
++ struct vc4_fkms *fkms;
+
+ struct vc4_hang_state *hang_state;
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -29,6 +29,14 @@
+ #include "vc_image_types.h"
+ #include <soc/bcm2835/raspberrypi-firmware.h>
+
++struct get_display_cfg {
++ u32 max_pixel_clock[2]; //Max pixel clock for each display
++};
++
++struct vc4_fkms {
++ struct get_display_cfg cfg;
++};
++
+ #define PLANES_PER_CRTC 3
+
+ struct set_plane {
+@@ -794,6 +802,11 @@ static void vc4_crtc_enable(struct drm_c
+ static enum drm_mode_status
+ vc4_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
+ {
++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
++ struct drm_device *dev = crtc->dev;
++ struct vc4_dev *vc4 = to_vc4_dev(dev);
++ struct vc4_fkms *fkms = vc4->fkms;
++
+ /* Do not allow doublescan modes from user space */
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
+ DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n",
+@@ -801,6 +814,22 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
+ return MODE_NO_DBLESCAN;
+ }
+
++ /* Limit the pixel clock based on the HDMI clock limits from the
++ * firmware
++ */
++ switch (vc4_crtc->display_number) {
++ case 2: /* HDMI0 */
++ if (fkms->cfg.max_pixel_clock[0] &&
++ mode->clock > fkms->cfg.max_pixel_clock[0])
++ return MODE_CLOCK_HIGH;
++ break;
++ case 7: /* HDMI1 */
++ if (fkms->cfg.max_pixel_clock[1] &&
++ mode->clock > fkms->cfg.max_pixel_clock[1])
++ return MODE_CLOCK_HIGH;
++ break;
++ }
++
+ /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
+ * working.
+ */
+@@ -1301,11 +1330,16 @@ static int vc4_fkms_bind(struct device *
+ struct device_node *firmware_node;
+ struct vc4_crtc **crtc_list;
+ u32 num_displays, display_num;
++ struct vc4_fkms *fkms;
+ int ret;
+ u32 display_id;
+
+ vc4->firmware_kms = true;
+
++ fkms = devm_kzalloc(dev, sizeof(*fkms), GFP_KERNEL);
++ if (!fkms)
++ return -ENOMEM;
++
+ /* firmware kms doesn't have precise a scanoutpos implementation, so
+ * we can't do the precise vblank timestamp mode.
+ */
+@@ -1334,6 +1368,18 @@ static int vc4_fkms_bind(struct device *
+ ret = 0;
+ }
+
++ ret = rpi_firmware_property(vc4->firmware,
++ RPI_FIRMWARE_GET_DISPLAY_CFG,
++ &fkms->cfg, sizeof(fkms->cfg));
++
++ if (ret)
++ return -EINVAL;
++ /* The firmware works in Hz. This will be compared against kHz, so div
++ * 1000 now rather than multiple times later.
++ */
++ fkms->cfg.max_pixel_clock[0] /= 1000;
++ fkms->cfg.max_pixel_clock[1] /= 1000;
++
+ /* Allocate a list, with space for a NULL on the end */
+ crtc_list = devm_kzalloc(dev, sizeof(crtc_list) * (num_displays + 1),
+ GFP_KERNEL);
+@@ -1375,6 +1421,8 @@ static int vc4_fkms_bind(struct device *
+ DRM_WARN("No displays found. Consider forcing hotplug if HDMI is attached\n");
+ }
+
++ vc4->fkms = fkms;
++
+ platform_set_drvdata(pdev, crtc_list);
+
+ return 0;
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -153,6 +153,7 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_SET_PLANE = 0x00048015,
+ RPI_FIRMWARE_GET_DISPLAY_TIMING = 0x00040017,
+ RPI_FIRMWARE_SET_TIMING = 0x00048017,
++ RPI_FIRMWARE_GET_DISPLAY_CFG = 0x00040018,
+
+ RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
+ RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,
+++ /dev/null
-From 124d768ec6f79f42bdcde24801e2315c4d2d7632 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Tue, 28 May 2019 13:56:06 +0100
-Subject: [PATCH 623/703] drm: vc4: handle the case where there are no
- available displays
-
-It's reasonable for the firmware to return zero as the number of
-attached displays. Handle this case as otherwise drm thinks that
-the DSI panel is attached, which is nonsense.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 32 +++++++++++++++-----------
- 1 file changed, 18 insertions(+), 14 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -1309,13 +1309,13 @@ static int vc4_fkms_bind(struct device *
- RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
- &num_displays, sizeof(u32));
-
-- /* If we fail to get the number of displays, or it returns 0, then
-+ /* If we fail to get the number of displays, then
- * assume old firmware that doesn't have the mailbox call, so just
- * set one display
- */
-- if (ret || num_displays == 0) {
-+ if (ret) {
- num_displays = 1;
-- DRM_WARN("Unable to determine number of displays's. Assuming 1\n");
-+ DRM_WARN("Unable to determine number of displays - assuming 1\n");
- ret = 0;
- }
-
-@@ -1344,17 +1344,21 @@ static int vc4_fkms_bind(struct device *
- display_num);
- }
-
-- /* Map the SMI interrupt reg */
-- crtc_list[0]->regs = vc4_ioremap_regs(pdev, 0);
-- if (IS_ERR(crtc_list[0]->regs))
-- DRM_ERROR("Oh dear, failed to map registers\n");
--
-- writel(0, crtc_list[0]->regs + SMICS);
-- ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
-- vc4_crtc_irq_handler, 0, "vc4 firmware kms",
-- crtc_list);
-- if (ret)
-- DRM_ERROR("Oh dear, failed to register IRQ\n");
-+ if (num_displays > 0) {
-+ /* Map the SMI interrupt reg */
-+ crtc_list[0]->regs = vc4_ioremap_regs(pdev, 0);
-+ if (IS_ERR(crtc_list[0]->regs))
-+ DRM_ERROR("Oh dear, failed to map registers\n");
-+
-+ writel(0, crtc_list[0]->regs + SMICS);
-+ ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
-+ vc4_crtc_irq_handler, 0,
-+ "vc4 firmware kms", crtc_list);
-+ if (ret)
-+ DRM_ERROR("Oh dear, failed to register IRQ\n");
-+ } else {
-+ DRM_WARN("No displays found. Consider forcing hotplug if HDMI is attached\n");
-+ }
-
- platform_set_drvdata(pdev, crtc_list);
-
--- /dev/null
+From aad4f4253c65b20796a1b472d1599149062f169c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 30 May 2019 15:55:15 +0100
+Subject: [PATCH 624/725] drm/vc4: Max resolution of 7680 is conditional on
+ being Pi4
+
+The max resolution had been increased from 2048 to 7680 for all
+platforms. This code is common with Pi0-3 which have a max render
+target for GL of 2048, therefore the increased resolution has to
+be conditional on the platform.
+Switch based on whether the bcm2835-v3d node is found, as that is
+not present on Pi4. (There is a potential configuration on Pi0-3
+with no v3d, but this is very unlikely).
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_kms.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -429,8 +429,14 @@ int vc4_kms_load(struct drm_device *dev)
+ return ret;
+ }
+
+- dev->mode_config.max_width = 7680;
+- dev->mode_config.max_height = 7680;
++ if (!drm_core_check_feature(dev, DRIVER_RENDER)) {
++ /* No V3D as part of vc4. Assume this is Pi4. */
++ dev->mode_config.max_width = 7680;
++ dev->mode_config.max_height = 7680;
++ } else {
++ dev->mode_config.max_width = 2048;
++ dev->mode_config.max_height = 2048;
++ }
+ dev->mode_config.funcs = &vc4_mode_funcs;
+ dev->mode_config.preferred_depth = 24;
+ dev->mode_config.async_page_flip = true;
+++ /dev/null
-From 1627c1be944a27b3b2f06d8d2b9dacf917c0ff67 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 24 May 2019 17:59:01 +0100
-Subject: [PATCH 624/703] drm/vc4: Support the VEC in FKMS
-
-Extends the DPI/DSI support to also report the VEC output
-which supports interlacing too.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 16 +++++++++++++++-
- 1 file changed, 15 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -125,6 +125,7 @@ struct set_timings {
- #define TIMINGS_FLAGS_H_SYNC_NEG 0
- #define TIMINGS_FLAGS_V_SYNC_POS BIT(1)
- #define TIMINGS_FLAGS_V_SYNC_NEG 0
-+#define TIMINGS_FLAGS_INTERLACE BIT(2)
-
- #define TIMINGS_FLAGS_ASPECT_MASK GENMASK(7, 4)
- #define TIMINGS_FLAGS_ASPECT_NONE (0 << 4)
-@@ -1047,6 +1048,12 @@ static int vc4_fkms_lcd_connector_get_mo
- fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
- else
- fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
-+ if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
-+ fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
-+ else
-+ fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
-+ if (mb.timings.flags & TIMINGS_FLAGS_INTERLACE)
-+ fw_mode.flags |= DRM_MODE_FLAG_INTERLACE;
-
- fw_mode.base.type = DRM_MODE_OBJECT_MODE;
-
-@@ -1133,17 +1140,24 @@ vc4_fkms_connector_init(struct drm_devic
- DRM_MODE_CONNECTOR_DSI);
- drm_connector_helper_add(connector,
- &vc4_fkms_lcd_conn_helper_funcs);
-+ connector->interlace_allowed = 0;
-+ } else if (fkms_connector->display_type == DRM_MODE_ENCODER_TVDAC) {
-+ drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
-+ DRM_MODE_CONNECTOR_Composite);
-+ drm_connector_helper_add(connector,
-+ &vc4_fkms_lcd_conn_helper_funcs);
-+ connector->interlace_allowed = 1;
- } else {
- drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
- DRM_MODE_CONNECTOR_HDMIA);
- drm_connector_helper_add(connector,
- &vc4_fkms_connector_helper_funcs);
-+ connector->interlace_allowed = 0;
- }
-
- connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
- DRM_CONNECTOR_POLL_DISCONNECT);
-
-- connector->interlace_allowed = 0;
- connector->doublescan_allowed = 0;
-
- drm_connector_attach_encoder(connector, encoder);
+++ /dev/null
-From 8fa80c9aeab3fac843be81d1dda0e87042367d34 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 7 May 2019 15:00:02 +0100
-Subject: [PATCH 625/703] drm: vc4: Fixup typo when setting HDMI aspect ratio
-
-Assignment was to the wrong structure.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -717,19 +717,19 @@ static void vc4_crtc_mode_set_nofb(struc
- switch (frame.avi.picture_aspect) {
- default:
- case HDMI_PICTURE_ASPECT_NONE:
-- mode->flags |= TIMINGS_FLAGS_ASPECT_NONE;
-+ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_NONE;
- break;
- case HDMI_PICTURE_ASPECT_4_3:
-- mode->flags |= TIMINGS_FLAGS_ASPECT_4_3;
-+ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_4_3;
- break;
- case HDMI_PICTURE_ASPECT_16_9:
-- mode->flags |= TIMINGS_FLAGS_ASPECT_16_9;
-+ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_16_9;
- break;
- case HDMI_PICTURE_ASPECT_64_27:
-- mode->flags |= TIMINGS_FLAGS_ASPECT_64_27;
-+ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_64_27;
- break;
- case HDMI_PICTURE_ASPECT_256_135:
-- mode->flags |= TIMINGS_FLAGS_ASPECT_256_135;
-+ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_256_135;
- break;
- }
-
--- /dev/null
+From aca9059632595f34dcd03b17f2396bbd47b1406b Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 10 Dec 2018 17:35:58 +0000
+Subject: [PATCH 625/725] staging: vc-sm-cma: Remove obsolete comment and make
+ function static
+
+Removes obsolete comment about wanting to pass a function
+pointer into mmal-vchiq as we now do.
+As the function is passed as a function pointer, the function itself
+can be static.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -594,8 +594,7 @@ error:
+ return ret;
+ }
+
+-/* FIXME: Pass a function pointer to this into vc_vchi_sm.c */
+-void
++static void
+ vc_sm_vpu_event(struct sm_instance *instance, struct vc_sm_result_t *reply,
+ int reply_len)
+ {
+++ /dev/null
-From b974397afb8ba0a0e11146886686163dfd4a3664 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 29 May 2019 15:44:11 +0100
-Subject: [PATCH 626/703] drm/vc4: Correct SAND support for FKMS.
-
-It was accepting NV21 which doesn't map through, but
-also wasn't advertising the modifier so nothing would know
-to request it.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -545,7 +545,6 @@ static bool vc4_fkms_format_mod_supporte
- return false;
- }
- case DRM_FORMAT_NV12:
-- case DRM_FORMAT_NV21:
- switch (fourcc_mod_broadcom_mod(modifier)) {
- case DRM_FORMAT_MOD_LINEAR:
- case DRM_FORMAT_MOD_BROADCOM_SAND128:
-@@ -553,6 +552,7 @@ static bool vc4_fkms_format_mod_supporte
- default:
- return false;
- }
-+ case DRM_FORMAT_NV21:
- case DRM_FORMAT_RGB888:
- case DRM_FORMAT_BGR888:
- case DRM_FORMAT_YUV422:
-@@ -599,6 +599,7 @@ static struct drm_plane *vc4_fkms_plane_
- * would prefer to scan out linear (less bus traffic).
- */
- DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
-+ DRM_FORMAT_MOD_BROADCOM_SAND128,
- DRM_FORMAT_MOD_INVALID,
- };
- int i;
--- /dev/null
+From ff6f3a7725d91cc9a793923e569b6ea08675d037 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 21 Dec 2018 16:50:53 +0000
+Subject: [PATCH 626/725] staging: vc-sm-cma: Add in allocation for VPU
+ requests.
+
+Module has to change from tristate to bool as all CMA functions
+are boolean.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vc-sm-cma/Kconfig | 4 +-
+ .../staging/vc04_services/vc-sm-cma/Makefile | 2 +-
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c | 642 +++++++++++++++---
+ .../staging/vc04_services/vc-sm-cma/vc_sm.h | 30 +-
+ .../vc04_services/vc-sm-cma/vc_sm_cma.c | 99 +++
+ .../vc04_services/vc-sm-cma/vc_sm_cma.h | 39 ++
+ .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c | 10 +
+ .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.h | 4 +
+ .../vc04_services/vc-sm-cma/vc_sm_defs.h | 2 +
+ 9 files changed, 723 insertions(+), 109 deletions(-)
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
+ create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/Kconfig
++++ b/drivers/staging/vc04_services/vc-sm-cma/Kconfig
+@@ -1,6 +1,6 @@
+ config BCM_VC_SM_CMA
+- tristate "VideoCore Shared Memory (CMA) driver"
+- depends on BCM2835_VCHIQ
++ bool "VideoCore Shared Memory (CMA) driver"
++ depends on BCM2835_VCHIQ && DMA_CMA
+ select RBTREE
+ select DMA_SHARED_BUFFER
+ help
+--- a/drivers/staging/vc04_services/vc-sm-cma/Makefile
++++ b/drivers/staging/vc04_services/vc-sm-cma/Makefile
+@@ -3,6 +3,6 @@ ccflags-y += -Idrivers/staging/vc04_serv
+ ccflags-y += -D__VCCOREVER__=0
+
+ vc-sm-cma-$(CONFIG_BCM_VC_SM_CMA) := \
+- vc_sm.o vc_sm_cma_vchi.o
++ vc_sm.o vc_sm_cma_vchi.o vc_sm_cma.o
+
+ obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma.o
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -9,10 +9,21 @@
+ * and taking some code for CMA/dmabuf handling from the Android Ion
+ * driver (Google/Linaro).
+ *
+- * This is cut down version to only support import of dma_bufs from
+- * other kernel drivers. A more complete implementation of the old
+- * vmcs_sm functionality can follow later.
+ *
++ * This driver has 3 main uses:
++ * 1) Allocating buffers for the kernel or userspace that can be shared with the
++ * VPU.
++ * 2) Importing dmabufs from elsewhere for sharing with the VPU.
++ * 3) Allocating buffers for use by the VPU.
++ *
++ * In the first and second cases the native handle is a dmabuf. Releasing the
++ * resource inherently comes from releasing the dmabuf, and this will trigger
++ * unmapping on the VPU. The underlying allocation and our buffer structure are
++ * retained until the VPU has confirmed that it has finished with it.
++ *
++ * For the VPU allocations the VPU is responsible for triggering the release,
++ * and therefore the released message decrements the dma_buf refcount (with the
++ * VPU mapping having already been marked as released).
+ */
+
+ /* ---- Include Files ----------------------------------------------------- */
+@@ -39,6 +50,7 @@
+ #include "vc_sm_cma_vchi.h"
+
+ #include "vc_sm.h"
++#include "vc_sm_cma.h"
+ #include "vc_sm_knl.h"
+
+ /* ---- Private Constants and Types --------------------------------------- */
+@@ -72,6 +84,7 @@ struct sm_state_t {
+ struct platform_device *pdev;
+
+ struct sm_instance *sm_handle; /* Handle for videocore service. */
++ struct cma *cma_heap;
+
+ spinlock_t kernelid_map_lock; /* Spinlock protecting kernelid_map */
+ struct idr kernelid_map;
+@@ -80,6 +93,7 @@ struct sm_state_t {
+ struct list_head buffer_list; /* List of buffer. */
+
+ struct vc_sm_privdata_t *data_knl; /* Kernel internal data tracking. */
++ struct vc_sm_privdata_t *vpu_allocs; /* All allocations from the VPU */
+ struct dentry *dir_root; /* Debug fs entries root. */
+ struct sm_pde_t dir_state; /* Debug fs entries state sub-tree. */
+
+@@ -89,6 +103,12 @@ struct sm_state_t {
+ u32 int_trans_id; /* Interrupted transaction. */
+ };
+
++struct vc_sm_dma_buf_attachment {
++ struct device *dev;
++ struct sg_table *table;
++ struct list_head list;
++};
++
+ /* ---- Private Variables ----------------------------------------------- */
+
+ static struct sm_state_t *sm_state;
+@@ -172,12 +192,14 @@ static int vc_sm_cma_global_state_show(s
+ resource->size);
+ seq_printf(s, " DMABUF %p\n",
+ resource->dma_buf);
+- seq_printf(s, " ATTACH %p\n",
+- resource->attach);
++ if (resource->imported) {
++ seq_printf(s, " ATTACH %p\n",
++ resource->import.attach);
++ seq_printf(s, " SGT %p\n",
++ resource->import.sgt);
++ }
+ seq_printf(s, " SG_TABLE %p\n",
+ resource->sg_table);
+- seq_printf(s, " SGT %p\n",
+- resource->sgt);
+ seq_printf(s, " DMA_ADDR %pad\n",
+ &resource->dma_addr);
+ seq_printf(s, " VC_HANDLE %08x\n",
+@@ -209,17 +231,33 @@ static void vc_sm_add_resource(struct vc
+ }
+
+ /*
+- * Release an allocation.
+- * All refcounting is done via the dma buf object.
++ * Cleans up imported dmabuf.
+ */
+-static void vc_sm_release_resource(struct vc_sm_buffer *buffer, int force)
++static void vc_sm_clean_up_dmabuf(struct vc_sm_buffer *buffer)
+ {
+- mutex_lock(&sm_state->map_lock);
+- mutex_lock(&buffer->lock);
++ if (!buffer->imported)
++ return;
+
+- pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
+- __func__, buffer, buffer->name, buffer->size);
++ /* Handle cleaning up imported dmabufs */
++ mutex_lock(&buffer->lock);
++ if (buffer->import.sgt) {
++ dma_buf_unmap_attachment(buffer->import.attach,
++ buffer->import.sgt,
++ DMA_BIDIRECTIONAL);
++ buffer->import.sgt = NULL;
++ }
++ if (buffer->import.attach) {
++ dma_buf_detach(buffer->dma_buf, buffer->import.attach);
++ buffer->import.attach = NULL;
++ }
++ mutex_unlock(&buffer->lock);
++}
+
++/*
++ * Instructs VPU to decrement the refcount on a buffer.
++ */
++static void vc_sm_vpu_free(struct vc_sm_buffer *buffer)
++{
+ if (buffer->vc_handle && buffer->vpu_state == VPU_MAPPED) {
+ struct vc_sm_free_t free = { buffer->vc_handle, 0 };
+ int status = vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
+@@ -230,17 +268,32 @@ static void vc_sm_release_resource(struc
+ }
+
+ if (sm_state->require_released_callback) {
+- /* Need to wait for the VPU to confirm the free */
++ /* Need to wait for the VPU to confirm the free. */
+
+ /* Retain a reference on this until the VPU has
+ * released it
+ */
+ buffer->vpu_state = VPU_UNMAPPING;
+- goto defer;
++ } else {
++ buffer->vpu_state = VPU_NOT_MAPPED;
++ buffer->vc_handle = 0;
+ }
+- buffer->vpu_state = VPU_NOT_MAPPED;
+- buffer->vc_handle = 0;
+ }
++}
++
++/*
++ * Release an allocation.
++ * All refcounting is done via the dma buf object.
++ *
++ * Must be called with the mutex held. The function will either release the
++ * mutex (if defering the release) or destroy it. The caller must therefore not
++ * reuse the buffer on return.
++ */
++static void vc_sm_release_resource(struct vc_sm_buffer *buffer)
++{
++ pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
++ __func__, buffer, buffer->name, buffer->size);
++
+ if (buffer->vc_handle) {
+ /* We've sent the unmap request but not had the response. */
+ pr_err("[%s]: Waiting for VPU unmap response on %p\n",
+@@ -248,45 +301,43 @@ static void vc_sm_release_resource(struc
+ goto defer;
+ }
+ if (buffer->in_use) {
+- /* Don't release dmabuf here - we await the release */
++ /* dmabuf still in use - we await the release */
+ pr_err("[%s]: buffer %p is still in use\n",
+ __func__, buffer);
+ goto defer;
+ }
+
+- /* Handle cleaning up imported dmabufs */
+- if (buffer->sgt) {
+- dma_buf_unmap_attachment(buffer->attach, buffer->sgt,
+- DMA_BIDIRECTIONAL);
+- buffer->sgt = NULL;
+- }
+- if (buffer->attach) {
+- dma_buf_detach(buffer->dma_buf, buffer->attach);
+- buffer->attach = NULL;
+- }
+-
+- /* Release the dma_buf (whether ours or imported) */
+- if (buffer->import_dma_buf) {
+- dma_buf_put(buffer->import_dma_buf);
+- buffer->import_dma_buf = NULL;
+- buffer->dma_buf = NULL;
+- } else if (buffer->dma_buf) {
+- dma_buf_put(buffer->dma_buf);
+- buffer->dma_buf = NULL;
++ /* Release the allocation (whether imported dmabuf or CMA allocation) */
++ if (buffer->imported) {
++ pr_debug("%s: Release imported dmabuf %p\n", __func__,
++ buffer->import.dma_buf);
++ if (buffer->import.dma_buf)
++ dma_buf_put(buffer->import.dma_buf);
++ else
++ pr_err("%s: Imported dmabuf already been put for buf %p\n",
++ __func__, buffer);
++ buffer->import.dma_buf = NULL;
++ } else {
++ if (buffer->sg_table) {
++ /* Our own allocation that we need to dma_unmap_sg */
++ dma_unmap_sg(&sm_state->pdev->dev,
++ buffer->sg_table->sgl,
++ buffer->sg_table->nents,
++ DMA_BIDIRECTIONAL);
++ }
++ pr_debug("%s: Release our allocation\n", __func__);
++ vc_sm_cma_buffer_free(&buffer->alloc);
++ pr_debug("%s: Release our allocation - done\n", __func__);
+ }
+
+- if (buffer->sg_table && !buffer->import_dma_buf) {
+- /* Our own allocation that we need to dma_unmap_sg */
+- dma_unmap_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
+- buffer->sg_table->nents, DMA_BIDIRECTIONAL);
+- }
+
+- /* Free the local resource. Start by removing it from the list */
+- buffer->private = NULL;
++ /* Free our buffer. Start by removing it from the list */
++ mutex_lock(&sm_state->map_lock);
+ list_del(&buffer->global_buffer_list);
++ mutex_unlock(&sm_state->map_lock);
+
++ pr_debug("%s: Release our allocation - done\n", __func__);
+ mutex_unlock(&buffer->lock);
+- mutex_unlock(&sm_state->map_lock);
+
+ mutex_destroy(&buffer->lock);
+
+@@ -295,7 +346,7 @@ static void vc_sm_release_resource(struc
+
+ defer:
+ mutex_unlock(&buffer->lock);
+- mutex_unlock(&sm_state->map_lock);
++ return;
+ }
+
+ /* Create support for private data tracking. */
+@@ -317,16 +368,267 @@ static struct vc_sm_privdata_t *vc_sm_cm
+ return file_data;
+ }
+
++static struct sg_table *dup_sg_table(struct sg_table *table)
++{
++ struct sg_table *new_table;
++ int ret, i;
++ struct scatterlist *sg, *new_sg;
++
++ new_table = kzalloc(sizeof(*new_table), GFP_KERNEL);
++ if (!new_table)
++ return ERR_PTR(-ENOMEM);
++
++ ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL);
++ if (ret) {
++ kfree(new_table);
++ return ERR_PTR(-ENOMEM);
++ }
++
++ new_sg = new_table->sgl;
++ for_each_sg(table->sgl, sg, table->nents, i) {
++ memcpy(new_sg, sg, sizeof(*sg));
++ sg->dma_address = 0;
++ new_sg = sg_next(new_sg);
++ }
++
++ return new_table;
++}
++
++static void free_duped_table(struct sg_table *table)
++{
++ sg_free_table(table);
++ kfree(table);
++}
++
++/* Dma buf operations for use with our own allocations */
++
++static int vc_sm_dma_buf_attach(struct dma_buf *dmabuf,
++ struct dma_buf_attachment *attachment)
++
++{
++ struct vc_sm_dma_buf_attachment *a;
++ struct sg_table *table;
++ struct vc_sm_buffer *buf = dmabuf->priv;
++
++ a = kzalloc(sizeof(*a), GFP_KERNEL);
++ if (!a)
++ return -ENOMEM;
++
++ table = dup_sg_table(buf->sg_table);
++ if (IS_ERR(table)) {
++ kfree(a);
++ return -ENOMEM;
++ }
++
++ a->table = table;
++ INIT_LIST_HEAD(&a->list);
++
++ attachment->priv = a;
++
++ mutex_lock(&buf->lock);
++ list_add(&a->list, &buf->attachments);
++ mutex_unlock(&buf->lock);
++ pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
++
++ return 0;
++}
++
++static void vc_sm_dma_buf_detatch(struct dma_buf *dmabuf,
++ struct dma_buf_attachment *attachment)
++{
++ struct vc_sm_dma_buf_attachment *a = attachment->priv;
++ struct vc_sm_buffer *buf = dmabuf->priv;
++
++ pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
++ free_duped_table(a->table);
++ mutex_lock(&buf->lock);
++ list_del(&a->list);
++ mutex_unlock(&buf->lock);
++
++ kfree(a);
++}
++
++static struct sg_table *vc_sm_map_dma_buf(struct dma_buf_attachment *attachment,
++ enum dma_data_direction direction)
++{
++ struct vc_sm_dma_buf_attachment *a = attachment->priv;
++ struct sg_table *table;
++
++ table = a->table;
++
++ if (!dma_map_sg(attachment->dev, table->sgl, table->nents,
++ direction))
++ return ERR_PTR(-ENOMEM);
++
++ pr_debug("%s attachment %p\n", __func__, attachment);
++ return table;
++}
++
++static void vc_sm_unmap_dma_buf(struct dma_buf_attachment *attachment,
++ struct sg_table *table,
++ enum dma_data_direction direction)
++{
++ pr_debug("%s attachment %p\n", __func__, attachment);
++ dma_unmap_sg(attachment->dev, table->sgl, table->nents, direction);
++}
++
++static int vc_sm_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
++{
++ struct vc_sm_buffer *buf = dmabuf->priv;
++ struct sg_table *table = buf->sg_table;
++ unsigned long addr = vma->vm_start;
++ unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
++ struct scatterlist *sg;
++ int i;
++ int ret = 0;
++
++ pr_debug("%s dmabuf %p, buf %p, vm_start %08lX\n", __func__, dmabuf,
++ buf, addr);
++
++ mutex_lock(&buf->lock);
++
++ /* now map it to userspace */
++ for_each_sg(table->sgl, sg, table->nents, i) {
++ struct page *page = sg_page(sg);
++ unsigned long remainder = vma->vm_end - addr;
++ unsigned long len = sg->length;
++
++ if (offset >= sg->length) {
++ offset -= sg->length;
++ continue;
++ } else if (offset) {
++ page += offset / PAGE_SIZE;
++ len = sg->length - offset;
++ offset = 0;
++ }
++ len = min(len, remainder);
++ ret = remap_pfn_range(vma, addr, page_to_pfn(page), len,
++ vma->vm_page_prot);
++ if (ret)
++ break;
++ addr += len;
++ if (addr >= vma->vm_end)
++ break;
++ }
++ mutex_unlock(&buf->lock);
++
++ if (ret)
++ pr_err("%s: failure mapping buffer to userspace\n",
++ __func__);
++
++ return ret;
++}
++
++static void vc_sm_dma_buf_release(struct dma_buf *dmabuf)
++{
++ struct vc_sm_buffer *buffer;
++
++ if (!dmabuf)
++ return;
++
++ buffer = (struct vc_sm_buffer *)dmabuf->priv;
++
++ mutex_lock(&buffer->lock);
++
++ pr_debug("%s dmabuf %p, buffer %p\n", __func__, dmabuf, buffer);
++
++ buffer->in_use = 0;
++
++ /* Unmap on the VPU */
++ vc_sm_vpu_free(buffer);
++ pr_debug("%s vpu_free done\n", __func__);
++
++ /* Unmap our dma_buf object (the vc_sm_buffer remains until released
++ * on the VPU).
++ */
++ vc_sm_clean_up_dmabuf(buffer);
++ pr_debug("%s clean_up dmabuf done\n", __func__);
++
++ vc_sm_release_resource(buffer);
++ pr_debug("%s done\n", __func__);
++}
++
++static int vc_sm_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
++ enum dma_data_direction direction)
++{
++ struct vc_sm_buffer *buf;
++ struct vc_sm_dma_buf_attachment *a;
++
++ if (!dmabuf)
++ return -EFAULT;
++
++ buf = dmabuf->priv;
++ if (!buf)
++ return -EFAULT;
++
++ mutex_lock(&buf->lock);
++
++ list_for_each_entry(a, &buf->attachments, list) {
++ dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents,
++ direction);
++ }
++ mutex_unlock(&buf->lock);
++
++ return 0;
++}
++
++static int vc_sm_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
++ enum dma_data_direction direction)
++{
++ struct vc_sm_buffer *buf;
++ struct vc_sm_dma_buf_attachment *a;
++
++ if (!dmabuf)
++ return -EFAULT;
++ buf = dmabuf->priv;
++ if (!buf)
++ return -EFAULT;
++
++ mutex_lock(&buf->lock);
++
++ list_for_each_entry(a, &buf->attachments, list) {
++ dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents,
++ direction);
++ }
++ mutex_unlock(&buf->lock);
++
++ return 0;
++}
++
++static void *vc_sm_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset)
++{
++ /* FIXME */
++ return NULL;
++}
++
++static void vc_sm_dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long offset,
++ void *ptr)
++{
++ /* FIXME */
++}
++
++static const struct dma_buf_ops dma_buf_ops = {
++ .map_dma_buf = vc_sm_map_dma_buf,
++ .unmap_dma_buf = vc_sm_unmap_dma_buf,
++ .mmap = vc_sm_dmabuf_mmap,
++ .release = vc_sm_dma_buf_release,
++ .attach = vc_sm_dma_buf_attach,
++ .detach = vc_sm_dma_buf_detatch,
++ .begin_cpu_access = vc_sm_dma_buf_begin_cpu_access,
++ .end_cpu_access = vc_sm_dma_buf_end_cpu_access,
++ .map = vc_sm_dma_buf_kmap,
++ .unmap = vc_sm_dma_buf_kunmap,
++};
+ /* Dma_buf operations for chaining through to an imported dma_buf */
+ static
+ int vc_sm_import_dma_buf_attach(struct dma_buf *dmabuf,
+ struct dma_buf_attachment *attachment)
+ {
+- struct vc_sm_buffer *res = dmabuf->priv;
++ struct vc_sm_buffer *buf = dmabuf->priv;
+
+- if (!res->import_dma_buf)
++ if (!buf->imported)
+ return -EINVAL;
+- return res->import_dma_buf->ops->attach(res->import_dma_buf,
++ return buf->import.dma_buf->ops->attach(buf->import.dma_buf,
+ attachment);
+ }
+
+@@ -334,22 +636,23 @@ static
+ void vc_sm_import_dma_buf_detatch(struct dma_buf *dmabuf,
+ struct dma_buf_attachment *attachment)
+ {
+- struct vc_sm_buffer *res = dmabuf->priv;
++ struct vc_sm_buffer *buf = dmabuf->priv;
+
+- if (!res->import_dma_buf)
++ if (!buf->imported)
+ return;
+- res->import_dma_buf->ops->detach(res->import_dma_buf, attachment);
++ buf->import.dma_buf->ops->detach(buf->import.dma_buf, attachment);
+ }
+
+ static
+ struct sg_table *vc_sm_import_map_dma_buf(struct dma_buf_attachment *attachment,
+ enum dma_data_direction direction)
+ {
+- struct vc_sm_buffer *res = attachment->dmabuf->priv;
++ struct vc_sm_buffer *buf = attachment->dmabuf->priv;
+
+- if (!res->import_dma_buf)
++ if (!buf->imported)
+ return NULL;
+- return res->import_dma_buf->ops->map_dma_buf(attachment, direction);
++ return buf->import.dma_buf->ops->map_dma_buf(attachment,
++ direction);
+ }
+
+ static
+@@ -357,87 +660,88 @@ void vc_sm_import_unmap_dma_buf(struct d
+ struct sg_table *table,
+ enum dma_data_direction direction)
+ {
+- struct vc_sm_buffer *res = attachment->dmabuf->priv;
++ struct vc_sm_buffer *buf = attachment->dmabuf->priv;
+
+- if (!res->import_dma_buf)
++ if (!buf->imported)
+ return;
+- res->import_dma_buf->ops->unmap_dma_buf(attachment, table, direction);
++ buf->import.dma_buf->ops->unmap_dma_buf(attachment, table, direction);
+ }
+
+ static
+ int vc_sm_import_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
+ {
+- struct vc_sm_buffer *res = dmabuf->priv;
++ struct vc_sm_buffer *buf = dmabuf->priv;
+
+- pr_debug("%s: mmap dma_buf %p, res %p, imported db %p\n", __func__,
+- dmabuf, res, res->import_dma_buf);
+- if (!res->import_dma_buf) {
++ pr_debug("%s: mmap dma_buf %p, buf %p, imported db %p\n", __func__,
++ dmabuf, buf, buf->import.dma_buf);
++ if (!buf->imported) {
+ pr_err("%s: mmap dma_buf %p- not an imported buffer\n",
+ __func__, dmabuf);
+ return -EINVAL;
+ }
+- return res->import_dma_buf->ops->mmap(res->import_dma_buf, vma);
++ return buf->import.dma_buf->ops->mmap(buf->import.dma_buf, vma);
+ }
+
+ static
+ void vc_sm_import_dma_buf_release(struct dma_buf *dmabuf)
+ {
+- struct vc_sm_buffer *res = dmabuf->priv;
++ struct vc_sm_buffer *buf = dmabuf->priv;
+
+ pr_debug("%s: Relasing dma_buf %p\n", __func__, dmabuf);
+- if (!res->import_dma_buf)
++ mutex_lock(&buf->lock);
++ if (!buf->imported)
+ return;
+
+- res->in_use = 0;
++ buf->in_use = 0;
+
+- vc_sm_release_resource(res, 0);
++ vc_sm_vpu_free(buf);
++
++ vc_sm_release_resource(buf);
+ }
+
+ static
+ void *vc_sm_import_dma_buf_kmap(struct dma_buf *dmabuf,
+ unsigned long offset)
+ {
+- struct vc_sm_buffer *res = dmabuf->priv;
++ struct vc_sm_buffer *buf = dmabuf->priv;
+
+- if (!res->import_dma_buf)
++ if (!buf->imported)
+ return NULL;
+- return res->import_dma_buf->ops->map(res->import_dma_buf,
+- offset);
++ return buf->import.dma_buf->ops->map(buf->import.dma_buf, offset);
+ }
+
+ static
+ void vc_sm_import_dma_buf_kunmap(struct dma_buf *dmabuf,
+ unsigned long offset, void *ptr)
+ {
+- struct vc_sm_buffer *res = dmabuf->priv;
++ struct vc_sm_buffer *buf = dmabuf->priv;
+
+- if (!res->import_dma_buf)
++ if (!buf->imported)
+ return;
+- res->import_dma_buf->ops->unmap(res->import_dma_buf,
+- offset, ptr);
++ buf->import.dma_buf->ops->unmap(buf->import.dma_buf, offset, ptr);
+ }
+
+ static
+ int vc_sm_import_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
+ enum dma_data_direction direction)
+ {
+- struct vc_sm_buffer *res = dmabuf->priv;
++ struct vc_sm_buffer *buf = dmabuf->priv;
+
+- if (!res->import_dma_buf)
++ if (!buf->imported)
+ return -EINVAL;
+- return res->import_dma_buf->ops->begin_cpu_access(res->import_dma_buf,
+- direction);
++ return buf->import.dma_buf->ops->begin_cpu_access(buf->import.dma_buf,
++ direction);
+ }
+
+ static
+ int vc_sm_import_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
+ enum dma_data_direction direction)
+ {
+- struct vc_sm_buffer *res = dmabuf->priv;
++ struct vc_sm_buffer *buf = dmabuf->priv;
+
+- if (!res->import_dma_buf)
++ if (!buf->imported)
+ return -EINVAL;
+- return res->import_dma_buf->ops->end_cpu_access(res->import_dma_buf,
++ return buf->import.dma_buf->ops->end_cpu_access(buf->import.dma_buf,
+ direction);
+ }
+
+@@ -516,9 +820,8 @@ vc_sm_cma_import_dmabuf_internal(struct
+ memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
+ sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
+
+- pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %pad, size %u\n",
+- __func__, import.name, import.type, &dma_addr,
+- import.size);
++ pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %pad, size %u.\n",
++ __func__, import.name, import.type, &dma_addr, import.size);
+
+ /* Allocate the videocore buffer. */
+ status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
+@@ -548,12 +851,14 @@ vc_sm_cma_import_dmabuf_internal(struct
+ buffer->size = import.size;
+ buffer->vpu_state = VPU_MAPPED;
+
+- buffer->import_dma_buf = dma_buf;
++ buffer->imported = 1;
++ buffer->import.dma_buf = dma_buf;
+
+- buffer->attach = attach;
+- buffer->sgt = sgt;
++ buffer->import.attach = attach;
++ buffer->import.sgt = sgt;
+ buffer->dma_addr = dma_addr;
+ buffer->in_use = 1;
++ buffer->kernel_id = import.kernel_id;
+
+ /*
+ * We're done - we need to export a new dmabuf chaining through most
+@@ -594,6 +899,91 @@ error:
+ return ret;
+ }
+
++static int vc_sm_cma_vpu_alloc(u32 size, uint32_t align, const char *name,
++ u32 mem_handle, struct vc_sm_buffer **ret_buffer)
++{
++ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
++ struct vc_sm_buffer *buffer = NULL;
++ int aligned_size;
++ int ret = 0;
++
++ /* Align to the user requested align */
++ aligned_size = ALIGN(size, align);
++ /* and then to a page boundary */
++ aligned_size = PAGE_ALIGN(aligned_size);
++
++ if (!aligned_size)
++ return -EINVAL;
++
++ /* Allocate local buffer to track this allocation. */
++ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
++ if (!buffer)
++ return -ENOMEM;
++
++ mutex_init(&buffer->lock);
++
++ if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
++ aligned_size)) {
++ pr_err("[%s]: cma alloc of %d bytes failed\n",
++ __func__, aligned_size);
++ ret = -ENOMEM;
++ goto error;
++ }
++ buffer->sg_table = buffer->alloc.sg_table;
++
++ pr_debug("[%s]: cma alloc of %d bytes success\n",
++ __func__, aligned_size);
++
++ if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
++ buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
++ pr_err("[%s]: dma_map_sg failed\n", __func__);
++ goto error;
++ }
++
++ INIT_LIST_HEAD(&buffer->attachments);
++
++ memcpy(buffer->name, name,
++ min(sizeof(buffer->name), strlen(name)));
++
++ exp_info.ops = &dma_buf_ops;
++ exp_info.size = aligned_size;
++ exp_info.flags = O_RDWR;
++ exp_info.priv = buffer;
++
++ buffer->dma_buf = dma_buf_export(&exp_info);
++ if (IS_ERR(buffer->dma_buf)) {
++ ret = PTR_ERR(buffer->dma_buf);
++ goto error;
++ }
++ buffer->dma_addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
++ if ((buffer->dma_addr & 0xC0000000) != 0xC0000000) {
++ pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
++ __func__, &buffer->dma_addr);
++ buffer->dma_addr |= 0xC0000000;
++ }
++ buffer->private = sm_state->vpu_allocs;
++
++ buffer->vc_handle = mem_handle;
++ buffer->vpu_state = VPU_MAPPED;
++ buffer->vpu_allocated = 1;
++ buffer->size = size;
++ /*
++ * Create an ID that will be passed along with our message so
++ * that when we service the release reply, we can look up which
++ * resource is being released.
++ */
++ buffer->kernel_id = get_kernel_id(buffer);
++
++ vc_sm_add_resource(sm_state->vpu_allocs, buffer);
++
++ *ret_buffer = buffer;
++ return 0;
++error:
++ if (buffer)
++ vc_sm_release_resource(buffer);
++ return ret;
++}
++
+ static void
+ vc_sm_vpu_event(struct sm_instance *instance, struct vc_sm_result_t *reply,
+ int reply_len)
+@@ -612,21 +1002,61 @@ vc_sm_vpu_event(struct sm_instance *inst
+ struct vc_sm_released *release = (struct vc_sm_released *)reply;
+ struct vc_sm_buffer *buffer =
+ lookup_kernel_id(release->kernel_id);
++ if (!buffer) {
++ pr_err("%s: VC released a buffer that is already released, kernel_id %d\n",
++ __func__, release->kernel_id);
++ break;
++ }
++ mutex_lock(&buffer->lock);
+
+- /*
+- * FIXME: Need to check buffer is still valid and allocated
+- * before continuing
+- */
+ pr_debug("%s: Released addr %08x, size %u, id %08x, mem_handle %08x\n",
+ __func__, release->addr, release->size,
+ release->kernel_id, release->vc_handle);
+- mutex_lock(&buffer->lock);
++
+ buffer->vc_handle = 0;
+ buffer->vpu_state = VPU_NOT_MAPPED;
+- mutex_unlock(&buffer->lock);
+ free_kernel_id(release->kernel_id);
+
+- vc_sm_release_resource(buffer, 0);
++ if (buffer->vpu_allocated) {
++ /* VPU allocation, so release the dmabuf which will
++ * trigger the clean up.
++ */
++ mutex_unlock(&buffer->lock);
++ dma_buf_put(buffer->dma_buf);
++ } else {
++ vc_sm_release_resource(buffer);
++ }
++ }
++ break;
++ case VC_SM_MSG_TYPE_VC_MEM_REQUEST:
++ {
++ struct vc_sm_buffer *buffer = NULL;
++ struct vc_sm_vc_mem_request *req =
++ (struct vc_sm_vc_mem_request *)reply;
++ struct vc_sm_vc_mem_request_result reply;
++ int ret;
++
++ pr_debug("%s: Request %u bytes of memory, align %d name %s, trans_id %08x\n",
++ __func__, req->size, req->align, req->name,
++ req->trans_id);
++ ret = vc_sm_cma_vpu_alloc(req->size, req->align, req->name,
++ req->vc_handle, &buffer);
++
++ reply.trans_id = req->trans_id;
++ if (!ret) {
++ reply.addr = buffer->dma_addr;
++ reply.kernel_id = buffer->kernel_id;
++ pr_debug("%s: Allocated resource buffer %p, addr %pad\n",
++ __func__, buffer, &buffer->dma_addr);
++ } else {
++ pr_err("%s: Allocation failed size %u, name %s, vc_handle %u\n",
++ __func__, req->size, req->name, req->vc_handle);
++ reply.addr = 0;
++ reply.kernel_id = 0;
++ }
++ vc_sm_vchi_client_vc_mem_req_reply(sm_state->sm_handle, &reply,
++ &sm_state->int_trans_id);
++ break;
+ }
+ break;
+ default:
+@@ -645,6 +1075,14 @@ static void vc_sm_connected_init(void)
+
+ pr_info("[%s]: start\n", __func__);
+
++ if (vc_sm_cma_add_heaps(&sm_state->cma_heap) ||
++ !sm_state->cma_heap) {
++ pr_err("[%s]: failed to initialise CMA heaps\n",
++ __func__);
++ ret = -EIO;
++ goto err_free_mem;
++ }
++
+ /*
+ * Initialize and create a VCHI connection for the shared memory service
+ * running on videocore.
+@@ -696,7 +1134,7 @@ static void vc_sm_connected_init(void)
+ goto err_remove_shared_memory;
+ }
+
+- version.version = 1;
++ version.version = 2;
+ ret = vc_sm_cma_vchi_client_version(sm_state->sm_handle, &version,
+ &version_result,
+ &sm_state->int_trans_id);
+@@ -768,7 +1206,7 @@ static int bcm2835_vc_sm_cma_remove(stru
+ int vc_sm_cma_int_handle(void *handle)
+ {
+ struct dma_buf *dma_buf = (struct dma_buf *)handle;
+- struct vc_sm_buffer *res;
++ struct vc_sm_buffer *buf;
+
+ /* Validate we can work with this device. */
+ if (!sm_state || !handle) {
+@@ -776,8 +1214,8 @@ int vc_sm_cma_int_handle(void *handle)
+ return 0;
+ }
+
+- res = (struct vc_sm_buffer *)dma_buf->priv;
+- return res->vc_handle;
++ buf = (struct vc_sm_buffer *)dma_buf->priv;
++ return buf->vc_handle;
+ }
+ EXPORT_SYMBOL_GPL(vc_sm_cma_int_handle);
+
+@@ -804,7 +1242,7 @@ EXPORT_SYMBOL_GPL(vc_sm_cma_free);
+ int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, void **handle)
+ {
+ struct dma_buf *new_dma_buf;
+- struct vc_sm_buffer *res;
++ struct vc_sm_buffer *buf;
+ int ret;
+
+ /* Validate we can work with this device. */
+@@ -818,7 +1256,7 @@ int vc_sm_cma_import_dmabuf(struct dma_b
+
+ if (!ret) {
+ pr_debug("%s: imported to ptr %p\n", __func__, new_dma_buf);
+- res = (struct vc_sm_buffer *)new_dma_buf->priv;
++ buf = (struct vc_sm_buffer *)new_dma_buf->priv;
+
+ /* Assign valid handle at this time.*/
+ *handle = new_dma_buf;
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
+@@ -21,6 +21,8 @@
+ #include <linux/types.h>
+ #include <linux/miscdevice.h>
+
++#include "vc_sm_cma.h"
++
+ #define VC_SM_MAX_NAME_LEN 32
+
+ enum vc_sm_vpu_mapping_state {
+@@ -29,31 +31,51 @@ enum vc_sm_vpu_mapping_state {
+ VPU_UNMAPPING
+ };
+
++struct vc_sm_imported {
++ struct dma_buf *dma_buf;
++ struct dma_buf_attachment *attach;
++ struct sg_table *sgt;
++};
++
+ struct vc_sm_buffer {
+ struct list_head global_buffer_list; /* Global list of buffers. */
+
++ /* Index in the kernel_id idr so that we can find the
++ * mmal_msg_context again when servicing the VCHI reply.
++ */
++ int kernel_id;
++
+ size_t size;
+
+ /* Lock over all the following state for this buffer */
+ struct mutex lock;
+- struct sg_table *sg_table;
+ struct list_head attachments;
+
+ char name[VC_SM_MAX_NAME_LEN];
+
+ int in_use:1; /* Kernel is still using this resource */
++ int imported:1; /* Imported dmabuf */
++
++ struct sg_table *sg_table;
+
+ enum vc_sm_vpu_mapping_state vpu_state;
+ u32 vc_handle; /* VideoCore handle for this buffer */
++ int vpu_allocated; /*
++ * The VPU made this allocation. Release the
++ * local dma_buf when the VPU releases the
++ * resource.
++ */
+
+ /* DMABUF related fields */
+- struct dma_buf *import_dma_buf;
+ struct dma_buf *dma_buf;
+- struct dma_buf_attachment *attach;
+- struct sg_table *sgt;
+ dma_addr_t dma_addr;
+
+ struct vc_sm_privdata_t *private;
++
++ union {
++ struct vc_sm_cma_alloc_data alloc;
++ struct vc_sm_imported import;
++ };
+ };
+
+ #endif
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
+@@ -0,0 +1,99 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * VideoCore Shared Memory CMA allocator
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ *
++ * Based on the Android ION allocator
++ * Copyright (C) Linaro 2012
++ * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
++ *
++ */
++
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/err.h>
++#include <linux/cma.h>
++#include <linux/scatterlist.h>
++
++#include "vc_sm_cma.h"
++
++/* CMA heap operations functions */
++int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
++ struct vc_sm_cma_alloc_data *buffer,
++ unsigned long len)
++{
++ /* len should already be page aligned */
++ unsigned long num_pages = len / PAGE_SIZE;
++ struct sg_table *table;
++ struct page *pages;
++ int ret;
++
++ pages = cma_alloc(cma_heap, num_pages, 0, GFP_KERNEL);
++ if (!pages)
++ return -ENOMEM;
++
++ table = kmalloc(sizeof(*table), GFP_KERNEL);
++ if (!table)
++ goto err;
++
++ ret = sg_alloc_table(table, 1, GFP_KERNEL);
++ if (ret)
++ goto free_mem;
++
++ sg_set_page(table->sgl, pages, len, 0);
++
++ buffer->priv_virt = pages;
++ buffer->sg_table = table;
++ buffer->cma_heap = cma_heap;
++ buffer->num_pages = num_pages;
++ return 0;
++
++free_mem:
++ kfree(table);
++err:
++ cma_release(cma_heap, pages, num_pages);
++ return -ENOMEM;
++}
++
++void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer)
++{
++ struct cma *cma_heap = buffer->cma_heap;
++ struct page *pages = buffer->priv_virt;
++
++ /* release memory */
++ if (cma_heap)
++ cma_release(cma_heap, pages, buffer->num_pages);
++
++ /* release sg table */
++ if (buffer->sg_table) {
++ sg_free_table(buffer->sg_table);
++ kfree(buffer->sg_table);
++ buffer->sg_table = NULL;
++ }
++}
++
++int __vc_sm_cma_add_heaps(struct cma *cma, void *priv)
++{
++ struct cma **heap = (struct cma **)priv;
++ const char *name = cma_get_name(cma);
++
++ if (!(*heap)) {
++ phys_addr_t phys_addr = cma_get_base(cma);
++
++ pr_debug("%s: Adding cma heap %s (start %pap, size %lu) for use by vcsm\n",
++ __func__, name, &phys_addr, cma_get_size(cma));
++ *heap = cma;
++ } else {
++ pr_err("%s: Ignoring heap %s as already set\n",
++ __func__, name);
++ }
++
++ return 0;
++}
++
++int vc_sm_cma_add_heaps(struct cma **cma_heap)
++{
++ cma_for_each_area(__vc_sm_cma_add_heaps, cma_heap);
++ return 0;
++}
+--- /dev/null
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
+@@ -0,0 +1,39 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++/*
++ * VideoCore Shared Memory CMA allocator
++ *
++ * Copyright: 2018, Raspberry Pi (Trading) Ltd
++ *
++ * Based on the Android ION allocator
++ * Copyright (C) Linaro 2012
++ * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ */
++#ifndef VC_SM_CMA_H
++#define VC_SM_CMA_H
++
++struct vc_sm_cma_alloc_data {
++ struct cma *cma_heap;
++ unsigned long num_pages;
++ void *priv_virt;
++ struct sg_table *sg_table;
++};
++
++int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
++ struct vc_sm_cma_alloc_data *buffer,
++ unsigned long len);
++void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer);
++
++int vc_sm_cma_add_heaps(struct cma **cma_heap);
++
++#endif
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
+@@ -500,3 +500,13 @@ int vc_sm_cma_vchi_client_version(struct
+ msg, sizeof(*msg), NULL, 0,
+ cur_trans_id, 0);
+ }
++
++int vc_sm_vchi_client_vc_mem_req_reply(struct sm_instance *handle,
++ struct vc_sm_vc_mem_request_result *msg,
++ uint32_t *cur_trans_id)
++{
++ return vc_sm_cma_vchi_send_msg(handle,
++ VC_SM_MSG_TYPE_VC_MEM_REQUEST_REPLY,
++ msg, sizeof(*msg), 0, 0, cur_trans_id,
++ 0);
++}
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
+@@ -56,4 +56,8 @@ int vc_sm_cma_vchi_client_version(struct
+ struct vc_sm_result_t *result,
+ u32 *cur_trans_id);
+
++int vc_sm_vchi_client_vc_mem_req_reply(struct sm_instance *handle,
++ struct vc_sm_vc_mem_request_result *msg,
++ uint32_t *cur_trans_id);
++
+ #endif /* __VC_SM_CMA_VCHI_H__INCLUDED__ */
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
+@@ -264,6 +264,8 @@ struct vc_sm_vc_mem_request {
+ u32 align;
+ /* resource name (for easier tracking) */
+ char name[VC_SM_RESOURCE_NAME];
++ /* VPU handle for the resource */
++ u32 vc_handle;
+ };
+
+ /* Response from the kernel to provide the VPU with some memory */
+++ /dev/null
-From 4a720b86a1ef014dcaa6e55deec883312ca3afce Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 30 May 2019 13:56:15 +0100
-Subject: [PATCH 627/703] drm/vc4: fkms to query the VPU for HDMI clock limits
-
-The VPU has configured clocks for 4k (or not) via config.txt,
-and will limit the choice of video modes based on that.
-Make fkms query it for these limits too to avoid selecting modes
-that can not be handled by the current clock setup.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_drv.h | 1 +
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 48 ++++++++++++++++++++++
- include/soc/bcm2835/raspberrypi-firmware.h | 1 +
- 3 files changed, 50 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_drv.h
-+++ b/drivers/gpu/drm/vc4/vc4_drv.h
-@@ -77,6 +77,7 @@ struct vc4_dev {
- struct vc4_dsi *dsi1;
- struct vc4_vec *vec;
- struct vc4_txp *txp;
-+ struct vc4_fkms *fkms;
-
- struct vc4_hang_state *hang_state;
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -29,6 +29,14 @@
- #include "vc_image_types.h"
- #include <soc/bcm2835/raspberrypi-firmware.h>
-
-+struct get_display_cfg {
-+ u32 max_pixel_clock[2]; //Max pixel clock for each display
-+};
-+
-+struct vc4_fkms {
-+ struct get_display_cfg cfg;
-+};
-+
- #define PLANES_PER_CRTC 3
-
- struct set_plane {
-@@ -794,6 +802,11 @@ static void vc4_crtc_enable(struct drm_c
- static enum drm_mode_status
- vc4_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
- {
-+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-+ struct drm_device *dev = crtc->dev;
-+ struct vc4_dev *vc4 = to_vc4_dev(dev);
-+ struct vc4_fkms *fkms = vc4->fkms;
-+
- /* Do not allow doublescan modes from user space */
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
- DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n",
-@@ -801,6 +814,22 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
- return MODE_NO_DBLESCAN;
- }
-
-+ /* Limit the pixel clock based on the HDMI clock limits from the
-+ * firmware
-+ */
-+ switch (vc4_crtc->display_number) {
-+ case 2: /* HDMI0 */
-+ if (fkms->cfg.max_pixel_clock[0] &&
-+ mode->clock > fkms->cfg.max_pixel_clock[0])
-+ return MODE_CLOCK_HIGH;
-+ break;
-+ case 7: /* HDMI1 */
-+ if (fkms->cfg.max_pixel_clock[1] &&
-+ mode->clock > fkms->cfg.max_pixel_clock[1])
-+ return MODE_CLOCK_HIGH;
-+ break;
-+ }
-+
- /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
- * working.
- */
-@@ -1301,11 +1330,16 @@ static int vc4_fkms_bind(struct device *
- struct device_node *firmware_node;
- struct vc4_crtc **crtc_list;
- u32 num_displays, display_num;
-+ struct vc4_fkms *fkms;
- int ret;
- u32 display_id;
-
- vc4->firmware_kms = true;
-
-+ fkms = devm_kzalloc(dev, sizeof(*fkms), GFP_KERNEL);
-+ if (!fkms)
-+ return -ENOMEM;
-+
- /* firmware kms doesn't have precise a scanoutpos implementation, so
- * we can't do the precise vblank timestamp mode.
- */
-@@ -1334,6 +1368,18 @@ static int vc4_fkms_bind(struct device *
- ret = 0;
- }
-
-+ ret = rpi_firmware_property(vc4->firmware,
-+ RPI_FIRMWARE_GET_DISPLAY_CFG,
-+ &fkms->cfg, sizeof(fkms->cfg));
-+
-+ if (ret)
-+ return -EINVAL;
-+ /* The firmware works in Hz. This will be compared against kHz, so div
-+ * 1000 now rather than multiple times later.
-+ */
-+ fkms->cfg.max_pixel_clock[0] /= 1000;
-+ fkms->cfg.max_pixel_clock[1] /= 1000;
-+
- /* Allocate a list, with space for a NULL on the end */
- crtc_list = devm_kzalloc(dev, sizeof(crtc_list) * (num_displays + 1),
- GFP_KERNEL);
-@@ -1375,6 +1421,8 @@ static int vc4_fkms_bind(struct device *
- DRM_WARN("No displays found. Consider forcing hotplug if HDMI is attached\n");
- }
-
-+ vc4->fkms = fkms;
-+
- platform_set_drvdata(pdev, crtc_list);
-
- return 0;
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -153,6 +153,7 @@ enum rpi_firmware_property_tag {
- RPI_FIRMWARE_SET_PLANE = 0x00048015,
- RPI_FIRMWARE_GET_DISPLAY_TIMING = 0x00040017,
- RPI_FIRMWARE_SET_TIMING = 0x00048017,
-+ RPI_FIRMWARE_GET_DISPLAY_CFG = 0x00040018,
-
- RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
- RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,
--- /dev/null
+From 010e6c5fe89059edff82fdbc05726e26e6a0b2b0 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 11 Mar 2019 16:38:32 +0000
+Subject: [PATCH 627/725] staging: vc-sm-cma: Update TODO.
+
+The driver is already a platform driver, so that can be
+deleted from the TODO.
+There are no known issues that need to be resolved.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/TODO | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/TODO
++++ b/drivers/staging/vc04_services/vc-sm-cma/TODO
+@@ -1,2 +1 @@
+-1) Convert to a platform driver.
+-
++No currently outstanding tasks except some clean-up.
+++ /dev/null
-From 78bd1c0169850a388fd7a45af6dd566613403a8e Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 30 May 2019 15:55:15 +0100
-Subject: [PATCH 628/703] drm/vc4: Max resolution of 7680 is conditional on
- being Pi4
-
-The max resolution had been increased from 2048 to 7680 for all
-platforms. This code is common with Pi0-3 which have a max render
-target for GL of 2048, therefore the increased resolution has to
-be conditional on the platform.
-Switch based on whether the bcm2835-v3d node is found, as that is
-not present on Pi4. (There is a potential configuration on Pi0-3
-with no v3d, but this is very unlikely).
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_kms.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_kms.c
-@@ -429,8 +429,14 @@ int vc4_kms_load(struct drm_device *dev)
- return ret;
- }
-
-- dev->mode_config.max_width = 7680;
-- dev->mode_config.max_height = 7680;
-+ if (!drm_core_check_feature(dev, DRIVER_RENDER)) {
-+ /* No V3D as part of vc4. Assume this is Pi4. */
-+ dev->mode_config.max_width = 7680;
-+ dev->mode_config.max_height = 7680;
-+ } else {
-+ dev->mode_config.max_width = 2048;
-+ dev->mode_config.max_height = 2048;
-+ }
- dev->mode_config.funcs = &vc4_mode_funcs;
- dev->mode_config.preferred_depth = 24;
- dev->mode_config.async_page_flip = true;
--- /dev/null
+From 0f56a2c03c3255d27bd8ee1c5cb32cc132b8c523 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 11 Mar 2019 16:35:23 +0000
+Subject: [PATCH 628/725] staging: vc-sm-cma: Add in userspace allocation API
+
+Replacing the functionality from the older vc-sm driver,
+add in a userspace API that allows allocation of buffers,
+and importing of dma-bufs.
+The driver hands out dma-buf fds, therefore much of the
+handling around lifespan and odd mmaps from the old driver
+goes away.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c | 371 ++++++++++++++++--
+ .../vc04_services/vc-sm-cma/vc_sm_cma.c | 3 +-
+ .../vc04_services/vc-sm-cma/vc_sm_cma.h | 2 +-
+ include/linux/broadcom/vc_sm_cma_ioctl.h | 87 ++++
+ 4 files changed, 435 insertions(+), 28 deletions(-)
+ create mode 100644 include/linux/broadcom/vc_sm_cma_ioctl.h
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -36,6 +36,7 @@
+ #include <linux/fs.h>
+ #include <linux/kernel.h>
+ #include <linux/list.h>
++#include <linux/miscdevice.h>
+ #include <linux/module.h>
+ #include <linux/mm.h>
+ #include <linux/of_device.h>
+@@ -52,6 +53,7 @@
+ #include "vc_sm.h"
+ #include "vc_sm_cma.h"
+ #include "vc_sm_knl.h"
++#include <linux/broadcom/vc_sm_cma_ioctl.h>
+
+ /* ---- Private Constants and Types --------------------------------------- */
+
+@@ -83,6 +85,8 @@ struct sm_pde_t {
+ struct sm_state_t {
+ struct platform_device *pdev;
+
++ struct miscdevice misc_dev;
++
+ struct sm_instance *sm_handle; /* Handle for videocore service. */
+ struct cma *cma_heap;
+
+@@ -346,7 +350,6 @@ static void vc_sm_release_resource(struc
+
+ defer:
+ mutex_unlock(&buffer->lock);
+- return;
+ }
+
+ /* Create support for private data tracking. */
+@@ -381,7 +384,7 @@ static struct sg_table *dup_sg_table(str
+ ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL);
+ if (ret) {
+ kfree(new_table);
+- return ERR_PTR(-ENOMEM);
++ return ERR_PTR(ret);
+ }
+
+ new_sg = new_table->sgl;
+@@ -417,7 +420,7 @@ static int vc_sm_dma_buf_attach(struct d
+ table = dup_sg_table(buf->sg_table);
+ if (IS_ERR(table)) {
+ kfree(a);
+- return -ENOMEM;
++ return PTR_ERR(table);
+ }
+
+ a->table = table;
+@@ -433,8 +436,8 @@ static int vc_sm_dma_buf_attach(struct d
+ return 0;
+ }
+
+-static void vc_sm_dma_buf_detatch(struct dma_buf *dmabuf,
+- struct dma_buf_attachment *attachment)
++static void vc_sm_dma_buf_detach(struct dma_buf *dmabuf,
++ struct dma_buf_attachment *attachment)
+ {
+ struct vc_sm_dma_buf_attachment *a = attachment->priv;
+ struct vc_sm_buffer *buf = dmabuf->priv;
+@@ -544,6 +547,9 @@ static void vc_sm_dma_buf_release(struct
+ vc_sm_clean_up_dmabuf(buffer);
+ pr_debug("%s clean_up dmabuf done\n", __func__);
+
++ /* buffer->lock will be destroyed by vc_sm_release_resource if finished
++ * with, otherwise unlocked. Do NOT unlock here.
++ */
+ vc_sm_release_resource(buffer);
+ pr_debug("%s done\n", __func__);
+ }
+@@ -613,7 +619,7 @@ static const struct dma_buf_ops dma_buf_
+ .mmap = vc_sm_dmabuf_mmap,
+ .release = vc_sm_dma_buf_release,
+ .attach = vc_sm_dma_buf_attach,
+- .detach = vc_sm_dma_buf_detatch,
++ .detach = vc_sm_dma_buf_detach,
+ .begin_cpu_access = vc_sm_dma_buf_begin_cpu_access,
+ .end_cpu_access = vc_sm_dma_buf_end_cpu_access,
+ .map = vc_sm_dma_buf_kmap,
+@@ -762,6 +768,7 @@ static const struct dma_buf_ops dma_buf_
+ int
+ vc_sm_cma_import_dmabuf_internal(struct vc_sm_privdata_t *private,
+ struct dma_buf *dma_buf,
++ int fd,
+ struct dma_buf **imported_buf)
+ {
+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+@@ -775,10 +782,15 @@ vc_sm_cma_import_dmabuf_internal(struct
+ int status;
+
+ /* Setup our allocation parameters */
+- pr_debug("%s: importing dma_buf %p\n", __func__, dma_buf);
++ pr_debug("%s: importing dma_buf %p/fd %d\n", __func__, dma_buf, fd);
+
+- get_dma_buf(dma_buf);
+- dma_buf = dma_buf;
++ if (fd < 0)
++ get_dma_buf(dma_buf);
++ else
++ dma_buf = dma_buf_get(fd);
++
++ if (!dma_buf)
++ return -EINVAL;
+
+ attach = dma_buf_attach(dma_buf, &sm_state->pdev->dev);
+ if (IS_ERR(attach)) {
+@@ -921,6 +933,10 @@ static int vc_sm_cma_vpu_alloc(u32 size,
+ return -ENOMEM;
+
+ mutex_init(&buffer->lock);
++ /* Acquire the mutex as vc_sm_release_resource will release it in the
++ * error path.
++ */
++ mutex_lock(&buffer->lock);
+
+ if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
+ aligned_size)) {
+@@ -976,6 +992,8 @@ static int vc_sm_cma_vpu_alloc(u32 size,
+
+ vc_sm_add_resource(sm_state->vpu_allocs, buffer);
+
++ mutex_unlock(&buffer->lock);
++
+ *ret_buffer = buffer;
+ return 0;
+ error:
+@@ -1065,6 +1083,297 @@ vc_sm_vpu_event(struct sm_instance *inst
+ }
+ }
+
++/* Userspace handling */
++/*
++ * Open the device. Creates a private state to help track all allocation
++ * associated with this device.
++ */
++static int vc_sm_cma_open(struct inode *inode, struct file *file)
++{
++ /* Make sure the device was started properly. */
++ if (!sm_state) {
++ pr_err("[%s]: invalid device\n", __func__);
++ return -EPERM;
++ }
++
++ file->private_data = vc_sm_cma_create_priv_data(current->tgid);
++ if (!file->private_data) {
++ pr_err("[%s]: failed to create data tracker\n", __func__);
++
++ return -ENOMEM;
++ }
++
++ return 0;
++}
++
++/*
++ * Close the vcsm-cma device.
++ * All allocations are file descriptors to the dmabuf objects, so we will get
++ * the clean up request on those as those are cleaned up.
++ */
++static int vc_sm_cma_release(struct inode *inode, struct file *file)
++{
++ struct vc_sm_privdata_t *file_data =
++ (struct vc_sm_privdata_t *)file->private_data;
++ int ret = 0;
++
++ /* Make sure the device was started properly. */
++ if (!sm_state || !file_data) {
++ pr_err("[%s]: invalid device\n", __func__);
++ ret = -EPERM;
++ goto out;
++ }
++
++ pr_debug("[%s]: using private data %p\n", __func__, file_data);
++
++ /* Terminate the private data. */
++ kfree(file_data);
++
++out:
++ return ret;
++}
++
++/*
++ * Allocate a shared memory handle and block.
++ * Allocation is from CMA, and then imported into the VPU mappings.
++ */
++int vc_sm_cma_ioctl_alloc(struct vc_sm_privdata_t *private,
++ struct vc_sm_cma_ioctl_alloc *ioparam)
++{
++ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
++ struct vc_sm_buffer *buffer = NULL;
++ struct vc_sm_import import = { 0 };
++ struct vc_sm_import_result result = { 0 };
++ struct dma_buf *dmabuf = NULL;
++ int aligned_size;
++ int ret = 0;
++ int status;
++ int fd = -1;
++
++ aligned_size = PAGE_ALIGN(ioparam->size);
++
++ if (!aligned_size)
++ return -EINVAL;
++
++ /* Allocate local buffer to track this allocation. */
++ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
++ if (!buffer) {
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
++ aligned_size)) {
++ pr_err("[%s]: cma alloc of %d bytes failed\n",
++ __func__, aligned_size);
++ kfree(buffer);
++ return -ENOMEM;
++ }
++ buffer->sg_table = buffer->alloc.sg_table;
++
++ if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
++ buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
++ pr_err("[%s]: dma_map_sg failed\n", __func__);
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ import.type = VC_SM_ALLOC_NON_CACHED;
++ import.allocator = current->tgid;
++
++ if (*ioparam->name)
++ memcpy(import.name, ioparam->name, sizeof(import.name) - 1);
++ else
++ memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
++ sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
++
++ mutex_init(&buffer->lock);
++ INIT_LIST_HEAD(&buffer->attachments);
++ memcpy(buffer->name, import.name,
++ min(sizeof(buffer->name), sizeof(import.name) - 1));
++
++ exp_info.ops = &dma_buf_ops;
++ exp_info.size = aligned_size;
++ exp_info.flags = O_RDWR;
++ exp_info.priv = buffer;
++
++ dmabuf = dma_buf_export(&exp_info);
++ if (IS_ERR(dmabuf)) {
++ ret = PTR_ERR(dmabuf);
++ goto error;
++ }
++ buffer->dma_buf = dmabuf;
++
++ import.addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
++ import.size = aligned_size;
++ import.kernel_id = (uint32_t)buffer;
++
++ /* Wrap it into a videocore buffer. */
++ status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
++ &sm_state->int_trans_id);
++ if (status == -EINTR) {
++ pr_debug("[%s]: requesting import memory action restart (trans_id: %u)\n",
++ __func__, sm_state->int_trans_id);
++ ret = -ERESTARTSYS;
++ private->restart_sys = -EINTR;
++ private->int_action = VC_SM_MSG_TYPE_IMPORT;
++ goto error;
++ } else if (status || !result.res_handle) {
++ pr_err("[%s]: failed to import memory on videocore (status: %u, trans_id: %u)\n",
++ __func__, status, sm_state->int_trans_id);
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ /* Keep track of the buffer we created. */
++ buffer->private = private;
++ buffer->vc_handle = result.res_handle;
++ buffer->size = import.size;
++ buffer->dma_addr = import.addr;
++ buffer->vpu_state = VPU_MAPPED;
++ //buffer->res_cached = ioparam->cached;
++
++ fd = dma_buf_fd(dmabuf, O_CLOEXEC);
++ if (fd < 0)
++ goto error;
++
++ vc_sm_add_resource(private, buffer);
++
++ pr_debug("[%s]: Added resource as fd %d, buffer %p, private %p, dma_addr %pad\n",
++ __func__, fd, buffer, private, &buffer->dma_addr);
++
++ /* We're done */
++ ioparam->handle = fd;
++ ioparam->vc_handle = buffer->vc_handle;
++ ioparam->dma_addr = buffer->dma_addr;
++ return 0;
++
++error:
++ if (buffer) {
++ pr_err("[%s]: something failed - cleanup. ret %d\n", __func__,
++ ret);
++
++ dma_buf_put(dmabuf);
++ }
++ return ret;
++}
++
++static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ int ret = 0;
++ unsigned int cmdnr = _IOC_NR(cmd);
++ struct vc_sm_privdata_t *file_data =
++ (struct vc_sm_privdata_t *)file->private_data;
++
++ /* Validate we can work with this device. */
++ if (!sm_state || !file_data) {
++ pr_err("[%s]: invalid device\n", __func__);
++ return -EPERM;
++ }
++
++ pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
++ current->tgid, file_data->pid);
++
++ /* Action is a re-post of a previously interrupted action? */
++ if (file_data->restart_sys == -EINTR) {
++ struct vc_sm_action_clean_t action_clean;
++
++ pr_debug("[%s]: clean up of action %u (trans_id: %u) following EINTR\n",
++ __func__, file_data->int_action,
++ file_data->int_trans_id);
++
++ action_clean.res_action = file_data->int_action;
++ action_clean.action_trans_id = file_data->int_trans_id;
++
++ file_data->restart_sys = 0;
++ }
++
++ /* Now process the command. */
++ switch (cmdnr) {
++ /* New memory allocation.
++ */
++ case VC_SM_CMA_CMD_ALLOC:
++ {
++ struct vc_sm_cma_ioctl_alloc ioparam;
++
++ /* Get the parameter data. */
++ if (copy_from_user
++ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ break;
++ }
++
++ ret = vc_sm_cma_ioctl_alloc(file_data, &ioparam);
++ if (!ret &&
++ (copy_to_user((void *)arg, &ioparam,
++ sizeof(ioparam)) != 0)) {
++ /* FIXME: Release allocation */
++ pr_err("[%s]: failed to copy-to-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ }
++ break;
++ }
++
++ case VC_SM_CMA_CMD_IMPORT_DMABUF:
++ {
++ struct vc_sm_cma_ioctl_import_dmabuf ioparam;
++ struct dma_buf *new_dmabuf;
++
++ /* Get the parameter data. */
++ if (copy_from_user
++ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ break;
++ }
++
++ ret = vc_sm_cma_import_dmabuf_internal(file_data,
++ NULL,
++ ioparam.dmabuf_fd,
++ &new_dmabuf);
++
++ if (!ret) {
++ struct vc_sm_buffer *buf = new_dmabuf->priv;
++
++ ioparam.size = buf->size;
++ ioparam.handle = dma_buf_fd(new_dmabuf,
++ O_CLOEXEC);
++ ioparam.vc_handle = buf->vc_handle;
++ ioparam.dma_addr = buf->dma_addr;
++
++ if (ioparam.handle < 0 ||
++ (copy_to_user((void *)arg, &ioparam,
++ sizeof(ioparam)) != 0)) {
++ dma_buf_put(new_dmabuf);
++ /* FIXME: Release allocation */
++ ret = -EFAULT;
++ }
++ }
++ break;
++ }
++
++ default:
++ ret = -EINVAL;
++ break;
++ }
++
++ return ret;
++}
++
++/* Device operations that we managed in this driver. */
++static const struct file_operations vc_sm_ops = {
++ .owner = THIS_MODULE,
++ .unlocked_ioctl = vc_sm_cma_ioctl,
++ .open = vc_sm_cma_open,
++ .release = vc_sm_cma_release,
++};
++
++/* Driver load/unload functions */
+ /* Videocore connected. */
+ static void vc_sm_connected_init(void)
+ {
+@@ -1075,12 +1384,11 @@ static void vc_sm_connected_init(void)
+
+ pr_info("[%s]: start\n", __func__);
+
+- if (vc_sm_cma_add_heaps(&sm_state->cma_heap) ||
+- !sm_state->cma_heap) {
+- pr_err("[%s]: failed to initialise CMA heaps\n",
++ vc_sm_cma_add_heaps(&sm_state->cma_heap);
++ if (!sm_state->cma_heap) {
++ pr_err("[%s]: failed to initialise CMA heap\n",
+ __func__);
+- ret = -EIO;
+- goto err_free_mem;
++ return;
+ }
+
+ /*
+@@ -1092,8 +1400,7 @@ static void vc_sm_connected_init(void)
+ pr_err("[%s]: failed to initialise VCHI instance (ret=%d)\n",
+ __func__, ret);
+
+- ret = -EIO;
+- goto err_failed;
++ return;
+ }
+
+ ret = vchi_connect(NULL, 0, vchi_instance);
+@@ -1101,8 +1408,7 @@ static void vc_sm_connected_init(void)
+ pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n",
+ __func__, ret);
+
+- ret = -EIO;
+- goto err_failed;
++ return;
+ }
+
+ /* Initialize an instance of the shared memory service. */
+@@ -1112,8 +1418,7 @@ static void vc_sm_connected_init(void)
+ pr_err("[%s]: failed to initialize shared memory service\n",
+ __func__);
+
+- ret = -EPERM;
+- goto err_failed;
++ return;
+ }
+
+ /* Create a debug fs directory entry (root). */
+@@ -1127,11 +1432,22 @@ static void vc_sm_connected_init(void)
+
+ INIT_LIST_HEAD(&sm_state->buffer_list);
+
++ /* Create a shared memory device. */
++ sm_state->misc_dev.minor = MISC_DYNAMIC_MINOR;
++ sm_state->misc_dev.name = DEVICE_NAME;
++ sm_state->misc_dev.fops = &vc_sm_ops;
++ sm_state->misc_dev.parent = NULL;
++ ret = misc_register(&sm_state->misc_dev);
++ if (ret) {
++ pr_err("vcsm-cma: failed to register misc device.\n");
++ goto err_remove_debugfs;
++ }
++
+ sm_state->data_knl = vc_sm_cma_create_priv_data(0);
+ if (!sm_state->data_knl) {
+ pr_err("[%s]: failed to create kernel private data tracker\n",
+ __func__);
+- goto err_remove_shared_memory;
++ goto err_remove_misc_dev;
+ }
+
+ version.version = 2;
+@@ -1148,11 +1464,13 @@ static void vc_sm_connected_init(void)
+ pr_info("[%s]: installed successfully\n", __func__);
+ return;
+
+-err_remove_shared_memory:
++err_remove_misc_dev:
++ misc_deregister(&sm_state->misc_dev);
++err_remove_debugfs:
+ debugfs_remove_recursive(sm_state->dir_root);
+ vc_sm_cma_vchi_stop(&sm_state->sm_handle);
+-err_failed:
+- pr_info("[%s]: failed, ret %d\n", __func__, ret);
++
++ return;
+ }
+
+ /* Driver loading. */
+@@ -1184,6 +1502,8 @@ static int bcm2835_vc_sm_cma_remove(stru
+ {
+ pr_debug("[%s]: start\n", __func__);
+ if (sm_inited) {
++ misc_deregister(&sm_state->misc_dev);
++
+ /* Remove all proc entries. */
+ debugfs_remove_recursive(sm_state->dir_root);
+
+@@ -1202,6 +1522,7 @@ static int bcm2835_vc_sm_cma_remove(stru
+ return 0;
+ }
+
++/* Kernel API calls */
+ /* Get an internal resource handle mapped from the external one. */
+ int vc_sm_cma_int_handle(void *handle)
+ {
+@@ -1252,7 +1573,7 @@ int vc_sm_cma_import_dmabuf(struct dma_b
+ }
+
+ ret = vc_sm_cma_import_dmabuf_internal(sm_state->data_knl, src_dmabuf,
+- &new_dma_buf);
++ -1, &new_dma_buf);
+
+ if (!ret) {
+ pr_debug("%s: imported to ptr %p\n", __func__, new_dma_buf);
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
+@@ -92,8 +92,7 @@ int __vc_sm_cma_add_heaps(struct cma *cm
+ return 0;
+ }
+
+-int vc_sm_cma_add_heaps(struct cma **cma_heap)
++void vc_sm_cma_add_heaps(struct cma **cma_heap)
+ {
+ cma_for_each_area(__vc_sm_cma_add_heaps, cma_heap);
+- return 0;
+ }
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
+@@ -34,6 +34,6 @@ int vc_sm_cma_buffer_allocate(struct cma
+ unsigned long len);
+ void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer);
+
+-int vc_sm_cma_add_heaps(struct cma **cma_heap);
++void vc_sm_cma_add_heaps(struct cma **cma_heap);
+
+ #endif
+--- /dev/null
++++ b/include/linux/broadcom/vc_sm_cma_ioctl.h
+@@ -0,0 +1,87 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++/*
++ * Copyright 2019 Raspberry Pi (Trading) Ltd. All rights reserved.
++ *
++ * Based on vmcs_sm_ioctl.h Copyright Broadcom Corporation.
++ */
++
++#ifndef __VC_SM_CMA_IOCTL_H
++#define __VC_SM_CMA_IOCTL_H
++
++/* ---- Include Files ---------------------------------------------------- */
++
++#if defined(__KERNEL__)
++#include <linux/types.h> /* Needed for standard types */
++#else
++#include <stdint.h>
++#endif
++
++#include <linux/ioctl.h>
++
++/* ---- Constants and Types ---------------------------------------------- */
++
++#define VC_SM_CMA_RESOURCE_NAME 32
++#define VC_SM_CMA_RESOURCE_NAME_DEFAULT "sm-host-resource"
++
++/* Type define used to create unique IOCTL number */
++#define VC_SM_CMA_MAGIC_TYPE 'J'
++
++/* IOCTL commands on /dev/vc-sm-cma */
++enum vc_sm_cma_cmd_e {
++ VC_SM_CMA_CMD_ALLOC = 0x5A, /* Start at 0x5A arbitrarily */
++
++ VC_SM_CMA_CMD_IMPORT_DMABUF,
++
++ VC_SM_CMA_CMD_LAST /* Do not delete */
++};
++
++/* Cache type supported, conveniently matches the user space definition in
++ * user-vcsm.h.
++ */
++enum vc_sm_cma_cache_e {
++ VC_SM_CMA_CACHE_NONE,
++ VC_SM_CMA_CACHE_HOST,
++ VC_SM_CMA_CACHE_VC,
++ VC_SM_CMA_CACHE_BOTH,
++};
++
++/* IOCTL Data structures */
++struct vc_sm_cma_ioctl_alloc {
++ /* user -> kernel */
++ __u32 size;
++ __u32 num;
++ __u32 cached; /* enum vc_sm_cma_cache_e */
++ __u32 pad;
++ __u8 name[VC_SM_CMA_RESOURCE_NAME];
++
++ /* kernel -> user */
++ __s32 handle;
++ __u32 vc_handle;
++ __u64 dma_addr;
++};
++
++struct vc_sm_cma_ioctl_import_dmabuf {
++ /* user -> kernel */
++ __s32 dmabuf_fd;
++ __u32 cached; /* enum vc_sm_cma_cache_e */
++ __u8 name[VC_SM_CMA_RESOURCE_NAME];
++
++ /* kernel -> user */
++ __s32 handle;
++ __u32 vc_handle;
++ __u32 size;
++ __u32 pad;
++ __u64 dma_addr;
++};
++
++/* IOCTL numbers */
++#define VC_SM_CMA_IOCTL_MEM_ALLOC\
++ _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_ALLOC,\
++ struct vc_sm_cma_ioctl_alloc)
++
++#define VC_SM_CMA_IOCTL_MEM_IMPORT_DMABUF\
++ _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_IMPORT_DMABUF,\
++ struct vc_sm_cma_ioctl_import_dmabuf)
++
++#endif /* __VC_SM_CMA_IOCTL_H */
+++ /dev/null
-From a493861ab01161aedb611793c87456dc1394bec6 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 10 Dec 2018 17:35:58 +0000
-Subject: [PATCH 629/703] staging: vc-sm-cma: Remove obsolete comment and make
- function static
-
-Removes obsolete comment about wanting to pass a function
-pointer into mmal-vchiq as we now do.
-As the function is passed as a function pointer, the function itself
-can be static.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -594,8 +594,7 @@ error:
- return ret;
- }
-
--/* FIXME: Pass a function pointer to this into vc_vchi_sm.c */
--void
-+static void
- vc_sm_vpu_event(struct sm_instance *instance, struct vc_sm_result_t *reply,
- int reply_len)
- {
--- /dev/null
+From 495a11dc216b24bfde79e61b2335be6da6c86945 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 20 Mar 2019 10:40:00 +0000
+Subject: [PATCH 629/725] staging: vcsm-cma: Add cache control ioctls
+
+The old driver allowed for direct cache manipulation and that
+was used by various clients. Replicate here.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c | 141 +++++++++++++++++-
+ include/linux/broadcom/vc_sm_cma_ioctl.h | 27 ++++
+ 2 files changed, 165 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -46,6 +46,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/syscalls.h>
+ #include <linux/types.h>
++#include <asm/cacheflush.h>
+
+ #include "vchiq_connected.h"
+ #include "vc_sm_cma_vchi.h"
+@@ -1258,6 +1259,99 @@ error:
+ return ret;
+ }
+
++/* Converts VCSM_CACHE_OP_* to an operating function. */
++static void (*cache_op_to_func(const unsigned int cache_op))
++ (const void*, const void*)
++{
++ switch (cache_op) {
++ case VC_SM_CACHE_OP_NOP:
++ return NULL;
++
++ case VC_SM_CACHE_OP_INV:
++ return dmac_inv_range;
++
++ case VC_SM_CACHE_OP_CLEAN:
++ return dmac_clean_range;
++
++ case VC_SM_CACHE_OP_FLUSH:
++ return dmac_flush_range;
++
++ default:
++ pr_err("[%s]: Invalid cache_op: 0x%08x\n", __func__, cache_op);
++ return NULL;
++ }
++}
++
++/*
++ * Clean/invalid/flush cache of which buffer is already pinned (i.e. accessed).
++ */
++static int clean_invalid_contig_2d(const void __user *addr,
++ const size_t block_count,
++ const size_t block_size,
++ const size_t stride,
++ const unsigned int cache_op)
++{
++ size_t i;
++ void (*op_fn)(const void *start, const void *end);
++
++ if (!block_size) {
++ pr_err("[%s]: size cannot be 0\n", __func__);
++ return -EINVAL;
++ }
++
++ op_fn = cache_op_to_func(cache_op);
++ if (!op_fn)
++ return -EINVAL;
++
++ for (i = 0; i < block_count; i ++, addr += stride)
++ op_fn(addr, addr + block_size);
++
++ return 0;
++}
++
++static int vc_sm_cma_clean_invalid2(unsigned int cmdnr, unsigned long arg)
++{
++ struct vc_sm_cma_ioctl_clean_invalid2 ioparam;
++ struct vc_sm_cma_ioctl_clean_invalid_block *block = NULL;
++ int i, ret = 0;
++
++ /* Get parameter data. */
++ if (copy_from_user(&ioparam, (void *)arg, sizeof(ioparam))) {
++ pr_err("[%s]: failed to copy-from-user header for cmd %x\n",
++ __func__, cmdnr);
++ return -EFAULT;
++ }
++ block = kmalloc(ioparam.op_count * sizeof(*block), GFP_KERNEL);
++ if (!block)
++ return -EFAULT;
++
++ if (copy_from_user(block, (void *)(arg + sizeof(ioparam)),
++ ioparam.op_count * sizeof(*block)) != 0) {
++ pr_err("[%s]: failed to copy-from-user payload for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ for (i = 0; i < ioparam.op_count; i++) {
++ const struct vc_sm_cma_ioctl_clean_invalid_block * const op = block + i;
++
++ if (op->invalidate_mode == VC_SM_CACHE_OP_NOP)
++ continue;
++
++ ret = clean_invalid_contig_2d((void __user *)op->start_address,
++ op->block_count, op->block_size,
++ op->inter_block_stride,
++ op->invalidate_mode);
++ if (ret)
++ break;
++ }
++out:
++ kfree(block);
++
++ return ret;
++}
++
+ static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+ {
+@@ -1272,9 +1366,6 @@ static long vc_sm_cma_ioctl(struct file
+ return -EPERM;
+ }
+
+- pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
+- current->tgid, file_data->pid);
+-
+ /* Action is a re-post of a previously interrupted action? */
+ if (file_data->restart_sys == -EINTR) {
+ struct vc_sm_action_clean_t action_clean;
+@@ -1357,7 +1448,18 @@ static long vc_sm_cma_ioctl(struct file
+ break;
+ }
+
++ /*
++ * Flush/Invalidate the cache for a given mapping.
++ * Blocks must be pinned (i.e. accessed) before this call.
++ */
++ case VC_SM_CMA_CMD_CLEAN_INVALID2:
++ ret = vc_sm_cma_clean_invalid2(cmdnr, arg);
++ break;
++
+ default:
++ pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
++ current->tgid, file_data->pid);
++
+ ret = -EINVAL;
+ break;
+ }
+@@ -1365,10 +1467,43 @@ static long vc_sm_cma_ioctl(struct file
+ return ret;
+ }
+
++#ifdef CONFIG_COMPAT
++struct vc_sm_cma_ioctl_clean_invalid2_32 {
++ u32 op_count;
++ struct vc_sm_cma_ioctl_clean_invalid_block {
++ u16 invalidate_mode;
++ u16 block_count;
++ compat_uptr_t start_address;
++ u32 block_size;
++ u32 inter_block_stride;
++ } s[0];
++};
++
++#define VC_SM_CMA_CMD_CLEAN_INVALID2_32\
++ _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
++ struct vc_sm_cma_ioctl_clean_invalid2)
++
++static long vc_sm_cma_compat_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ switch (cmd) {
++ case VC_SM_CMA_CMD_CLEAN_INVALID2_32:
++ /* FIXME */
++ break;
++
++ default:
++ return vc_sm_cma_compat_ioctl(file, cmd, arg);
++ }
++}
++#endif
++
+ /* Device operations that we managed in this driver. */
+ static const struct file_operations vc_sm_ops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = vc_sm_cma_ioctl,
++#ifdef CONFIG_COMPAT
++ .compat_ioctl = vc_sm_cma_compat_ioctl,
++#endif
+ .open = vc_sm_cma_open,
+ .release = vc_sm_cma_release,
+ };
+--- a/include/linux/broadcom/vc_sm_cma_ioctl.h
++++ b/include/linux/broadcom/vc_sm_cma_ioctl.h
+@@ -33,6 +33,8 @@ enum vc_sm_cma_cmd_e {
+
+ VC_SM_CMA_CMD_IMPORT_DMABUF,
+
++ VC_SM_CMA_CMD_CLEAN_INVALID2,
++
+ VC_SM_CMA_CMD_LAST /* Do not delete */
+ };
+
+@@ -75,6 +77,27 @@ struct vc_sm_cma_ioctl_import_dmabuf {
+ __u64 dma_addr;
+ };
+
++/*
++ * Cache functions to be set to struct vc_sm_cma_ioctl_clean_invalid2
++ * invalidate_mode.
++ */
++#define VC_SM_CACHE_OP_NOP 0x00
++#define VC_SM_CACHE_OP_INV 0x01
++#define VC_SM_CACHE_OP_CLEAN 0x02
++#define VC_SM_CACHE_OP_FLUSH 0x03
++
++struct vc_sm_cma_ioctl_clean_invalid2 {
++ __u32 op_count;
++ __u32 pad;
++ struct vc_sm_cma_ioctl_clean_invalid_block {
++ __u32 invalidate_mode;
++ __u32 block_count;
++ void * __user start_address;
++ __u32 block_size;
++ __u32 inter_block_stride;
++ } s[0];
++};
++
+ /* IOCTL numbers */
+ #define VC_SM_CMA_IOCTL_MEM_ALLOC\
+ _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_ALLOC,\
+@@ -84,4 +107,8 @@ struct vc_sm_cma_ioctl_import_dmabuf {
+ _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_IMPORT_DMABUF,\
+ struct vc_sm_cma_ioctl_import_dmabuf)
+
++#define VC_SM_CMA_IOCTL_MEM_CLEAN_INVALID2\
++ _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
++ struct vc_sm_cma_ioctl_clean_invalid2)
++
+ #endif /* __VC_SM_CMA_IOCTL_H */
+++ /dev/null
-From 904c0d6a47b181b134a3626bfd93b456ec6b411d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 21 Dec 2018 16:50:53 +0000
-Subject: [PATCH 630/703] staging: vc-sm-cma: Add in allocation for VPU
- requests.
-
-Module has to change from tristate to bool as all CMA functions
-are boolean.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vc-sm-cma/Kconfig | 4 +-
- .../staging/vc04_services/vc-sm-cma/Makefile | 2 +-
- .../staging/vc04_services/vc-sm-cma/vc_sm.c | 642 +++++++++++++++---
- .../staging/vc04_services/vc-sm-cma/vc_sm.h | 30 +-
- .../vc04_services/vc-sm-cma/vc_sm_cma.c | 99 +++
- .../vc04_services/vc-sm-cma/vc_sm_cma.h | 39 ++
- .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c | 10 +
- .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.h | 4 +
- .../vc04_services/vc-sm-cma/vc_sm_defs.h | 2 +
- 9 files changed, 723 insertions(+), 109 deletions(-)
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
- create mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
-
---- a/drivers/staging/vc04_services/vc-sm-cma/Kconfig
-+++ b/drivers/staging/vc04_services/vc-sm-cma/Kconfig
-@@ -1,6 +1,6 @@
- config BCM_VC_SM_CMA
-- tristate "VideoCore Shared Memory (CMA) driver"
-- depends on BCM2835_VCHIQ
-+ bool "VideoCore Shared Memory (CMA) driver"
-+ depends on BCM2835_VCHIQ && DMA_CMA
- select RBTREE
- select DMA_SHARED_BUFFER
- help
---- a/drivers/staging/vc04_services/vc-sm-cma/Makefile
-+++ b/drivers/staging/vc04_services/vc-sm-cma/Makefile
-@@ -3,6 +3,6 @@ ccflags-y += -Idrivers/staging/vc04_serv
- ccflags-y += -D__VCCOREVER__=0
-
- vc-sm-cma-$(CONFIG_BCM_VC_SM_CMA) := \
-- vc_sm.o vc_sm_cma_vchi.o
-+ vc_sm.o vc_sm_cma_vchi.o vc_sm_cma.o
-
- obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma.o
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -9,10 +9,21 @@
- * and taking some code for CMA/dmabuf handling from the Android Ion
- * driver (Google/Linaro).
- *
-- * This is cut down version to only support import of dma_bufs from
-- * other kernel drivers. A more complete implementation of the old
-- * vmcs_sm functionality can follow later.
- *
-+ * This driver has 3 main uses:
-+ * 1) Allocating buffers for the kernel or userspace that can be shared with the
-+ * VPU.
-+ * 2) Importing dmabufs from elsewhere for sharing with the VPU.
-+ * 3) Allocating buffers for use by the VPU.
-+ *
-+ * In the first and second cases the native handle is a dmabuf. Releasing the
-+ * resource inherently comes from releasing the dmabuf, and this will trigger
-+ * unmapping on the VPU. The underlying allocation and our buffer structure are
-+ * retained until the VPU has confirmed that it has finished with it.
-+ *
-+ * For the VPU allocations the VPU is responsible for triggering the release,
-+ * and therefore the released message decrements the dma_buf refcount (with the
-+ * VPU mapping having already been marked as released).
- */
-
- /* ---- Include Files ----------------------------------------------------- */
-@@ -39,6 +50,7 @@
- #include "vc_sm_cma_vchi.h"
-
- #include "vc_sm.h"
-+#include "vc_sm_cma.h"
- #include "vc_sm_knl.h"
-
- /* ---- Private Constants and Types --------------------------------------- */
-@@ -72,6 +84,7 @@ struct sm_state_t {
- struct platform_device *pdev;
-
- struct sm_instance *sm_handle; /* Handle for videocore service. */
-+ struct cma *cma_heap;
-
- spinlock_t kernelid_map_lock; /* Spinlock protecting kernelid_map */
- struct idr kernelid_map;
-@@ -80,6 +93,7 @@ struct sm_state_t {
- struct list_head buffer_list; /* List of buffer. */
-
- struct vc_sm_privdata_t *data_knl; /* Kernel internal data tracking. */
-+ struct vc_sm_privdata_t *vpu_allocs; /* All allocations from the VPU */
- struct dentry *dir_root; /* Debug fs entries root. */
- struct sm_pde_t dir_state; /* Debug fs entries state sub-tree. */
-
-@@ -89,6 +103,12 @@ struct sm_state_t {
- u32 int_trans_id; /* Interrupted transaction. */
- };
-
-+struct vc_sm_dma_buf_attachment {
-+ struct device *dev;
-+ struct sg_table *table;
-+ struct list_head list;
-+};
-+
- /* ---- Private Variables ----------------------------------------------- */
-
- static struct sm_state_t *sm_state;
-@@ -172,12 +192,14 @@ static int vc_sm_cma_global_state_show(s
- resource->size);
- seq_printf(s, " DMABUF %p\n",
- resource->dma_buf);
-- seq_printf(s, " ATTACH %p\n",
-- resource->attach);
-+ if (resource->imported) {
-+ seq_printf(s, " ATTACH %p\n",
-+ resource->import.attach);
-+ seq_printf(s, " SGT %p\n",
-+ resource->import.sgt);
-+ }
- seq_printf(s, " SG_TABLE %p\n",
- resource->sg_table);
-- seq_printf(s, " SGT %p\n",
-- resource->sgt);
- seq_printf(s, " DMA_ADDR %pad\n",
- &resource->dma_addr);
- seq_printf(s, " VC_HANDLE %08x\n",
-@@ -209,17 +231,33 @@ static void vc_sm_add_resource(struct vc
- }
-
- /*
-- * Release an allocation.
-- * All refcounting is done via the dma buf object.
-+ * Cleans up imported dmabuf.
- */
--static void vc_sm_release_resource(struct vc_sm_buffer *buffer, int force)
-+static void vc_sm_clean_up_dmabuf(struct vc_sm_buffer *buffer)
- {
-- mutex_lock(&sm_state->map_lock);
-- mutex_lock(&buffer->lock);
-+ if (!buffer->imported)
-+ return;
-
-- pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
-- __func__, buffer, buffer->name, buffer->size);
-+ /* Handle cleaning up imported dmabufs */
-+ mutex_lock(&buffer->lock);
-+ if (buffer->import.sgt) {
-+ dma_buf_unmap_attachment(buffer->import.attach,
-+ buffer->import.sgt,
-+ DMA_BIDIRECTIONAL);
-+ buffer->import.sgt = NULL;
-+ }
-+ if (buffer->import.attach) {
-+ dma_buf_detach(buffer->dma_buf, buffer->import.attach);
-+ buffer->import.attach = NULL;
-+ }
-+ mutex_unlock(&buffer->lock);
-+}
-
-+/*
-+ * Instructs VPU to decrement the refcount on a buffer.
-+ */
-+static void vc_sm_vpu_free(struct vc_sm_buffer *buffer)
-+{
- if (buffer->vc_handle && buffer->vpu_state == VPU_MAPPED) {
- struct vc_sm_free_t free = { buffer->vc_handle, 0 };
- int status = vc_sm_cma_vchi_free(sm_state->sm_handle, &free,
-@@ -230,17 +268,32 @@ static void vc_sm_release_resource(struc
- }
-
- if (sm_state->require_released_callback) {
-- /* Need to wait for the VPU to confirm the free */
-+ /* Need to wait for the VPU to confirm the free. */
-
- /* Retain a reference on this until the VPU has
- * released it
- */
- buffer->vpu_state = VPU_UNMAPPING;
-- goto defer;
-+ } else {
-+ buffer->vpu_state = VPU_NOT_MAPPED;
-+ buffer->vc_handle = 0;
- }
-- buffer->vpu_state = VPU_NOT_MAPPED;
-- buffer->vc_handle = 0;
- }
-+}
-+
-+/*
-+ * Release an allocation.
-+ * All refcounting is done via the dma buf object.
-+ *
-+ * Must be called with the mutex held. The function will either release the
-+ * mutex (if defering the release) or destroy it. The caller must therefore not
-+ * reuse the buffer on return.
-+ */
-+static void vc_sm_release_resource(struct vc_sm_buffer *buffer)
-+{
-+ pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
-+ __func__, buffer, buffer->name, buffer->size);
-+
- if (buffer->vc_handle) {
- /* We've sent the unmap request but not had the response. */
- pr_err("[%s]: Waiting for VPU unmap response on %p\n",
-@@ -248,45 +301,43 @@ static void vc_sm_release_resource(struc
- goto defer;
- }
- if (buffer->in_use) {
-- /* Don't release dmabuf here - we await the release */
-+ /* dmabuf still in use - we await the release */
- pr_err("[%s]: buffer %p is still in use\n",
- __func__, buffer);
- goto defer;
- }
-
-- /* Handle cleaning up imported dmabufs */
-- if (buffer->sgt) {
-- dma_buf_unmap_attachment(buffer->attach, buffer->sgt,
-- DMA_BIDIRECTIONAL);
-- buffer->sgt = NULL;
-- }
-- if (buffer->attach) {
-- dma_buf_detach(buffer->dma_buf, buffer->attach);
-- buffer->attach = NULL;
-- }
--
-- /* Release the dma_buf (whether ours or imported) */
-- if (buffer->import_dma_buf) {
-- dma_buf_put(buffer->import_dma_buf);
-- buffer->import_dma_buf = NULL;
-- buffer->dma_buf = NULL;
-- } else if (buffer->dma_buf) {
-- dma_buf_put(buffer->dma_buf);
-- buffer->dma_buf = NULL;
-+ /* Release the allocation (whether imported dmabuf or CMA allocation) */
-+ if (buffer->imported) {
-+ pr_debug("%s: Release imported dmabuf %p\n", __func__,
-+ buffer->import.dma_buf);
-+ if (buffer->import.dma_buf)
-+ dma_buf_put(buffer->import.dma_buf);
-+ else
-+ pr_err("%s: Imported dmabuf already been put for buf %p\n",
-+ __func__, buffer);
-+ buffer->import.dma_buf = NULL;
-+ } else {
-+ if (buffer->sg_table) {
-+ /* Our own allocation that we need to dma_unmap_sg */
-+ dma_unmap_sg(&sm_state->pdev->dev,
-+ buffer->sg_table->sgl,
-+ buffer->sg_table->nents,
-+ DMA_BIDIRECTIONAL);
-+ }
-+ pr_debug("%s: Release our allocation\n", __func__);
-+ vc_sm_cma_buffer_free(&buffer->alloc);
-+ pr_debug("%s: Release our allocation - done\n", __func__);
- }
-
-- if (buffer->sg_table && !buffer->import_dma_buf) {
-- /* Our own allocation that we need to dma_unmap_sg */
-- dma_unmap_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
-- buffer->sg_table->nents, DMA_BIDIRECTIONAL);
-- }
-
-- /* Free the local resource. Start by removing it from the list */
-- buffer->private = NULL;
-+ /* Free our buffer. Start by removing it from the list */
-+ mutex_lock(&sm_state->map_lock);
- list_del(&buffer->global_buffer_list);
-+ mutex_unlock(&sm_state->map_lock);
-
-+ pr_debug("%s: Release our allocation - done\n", __func__);
- mutex_unlock(&buffer->lock);
-- mutex_unlock(&sm_state->map_lock);
-
- mutex_destroy(&buffer->lock);
-
-@@ -295,7 +346,7 @@ static void vc_sm_release_resource(struc
-
- defer:
- mutex_unlock(&buffer->lock);
-- mutex_unlock(&sm_state->map_lock);
-+ return;
- }
-
- /* Create support for private data tracking. */
-@@ -317,16 +368,267 @@ static struct vc_sm_privdata_t *vc_sm_cm
- return file_data;
- }
-
-+static struct sg_table *dup_sg_table(struct sg_table *table)
-+{
-+ struct sg_table *new_table;
-+ int ret, i;
-+ struct scatterlist *sg, *new_sg;
-+
-+ new_table = kzalloc(sizeof(*new_table), GFP_KERNEL);
-+ if (!new_table)
-+ return ERR_PTR(-ENOMEM);
-+
-+ ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL);
-+ if (ret) {
-+ kfree(new_table);
-+ return ERR_PTR(-ENOMEM);
-+ }
-+
-+ new_sg = new_table->sgl;
-+ for_each_sg(table->sgl, sg, table->nents, i) {
-+ memcpy(new_sg, sg, sizeof(*sg));
-+ sg->dma_address = 0;
-+ new_sg = sg_next(new_sg);
-+ }
-+
-+ return new_table;
-+}
-+
-+static void free_duped_table(struct sg_table *table)
-+{
-+ sg_free_table(table);
-+ kfree(table);
-+}
-+
-+/* Dma buf operations for use with our own allocations */
-+
-+static int vc_sm_dma_buf_attach(struct dma_buf *dmabuf,
-+ struct dma_buf_attachment *attachment)
-+
-+{
-+ struct vc_sm_dma_buf_attachment *a;
-+ struct sg_table *table;
-+ struct vc_sm_buffer *buf = dmabuf->priv;
-+
-+ a = kzalloc(sizeof(*a), GFP_KERNEL);
-+ if (!a)
-+ return -ENOMEM;
-+
-+ table = dup_sg_table(buf->sg_table);
-+ if (IS_ERR(table)) {
-+ kfree(a);
-+ return -ENOMEM;
-+ }
-+
-+ a->table = table;
-+ INIT_LIST_HEAD(&a->list);
-+
-+ attachment->priv = a;
-+
-+ mutex_lock(&buf->lock);
-+ list_add(&a->list, &buf->attachments);
-+ mutex_unlock(&buf->lock);
-+ pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
-+
-+ return 0;
-+}
-+
-+static void vc_sm_dma_buf_detatch(struct dma_buf *dmabuf,
-+ struct dma_buf_attachment *attachment)
-+{
-+ struct vc_sm_dma_buf_attachment *a = attachment->priv;
-+ struct vc_sm_buffer *buf = dmabuf->priv;
-+
-+ pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
-+ free_duped_table(a->table);
-+ mutex_lock(&buf->lock);
-+ list_del(&a->list);
-+ mutex_unlock(&buf->lock);
-+
-+ kfree(a);
-+}
-+
-+static struct sg_table *vc_sm_map_dma_buf(struct dma_buf_attachment *attachment,
-+ enum dma_data_direction direction)
-+{
-+ struct vc_sm_dma_buf_attachment *a = attachment->priv;
-+ struct sg_table *table;
-+
-+ table = a->table;
-+
-+ if (!dma_map_sg(attachment->dev, table->sgl, table->nents,
-+ direction))
-+ return ERR_PTR(-ENOMEM);
-+
-+ pr_debug("%s attachment %p\n", __func__, attachment);
-+ return table;
-+}
-+
-+static void vc_sm_unmap_dma_buf(struct dma_buf_attachment *attachment,
-+ struct sg_table *table,
-+ enum dma_data_direction direction)
-+{
-+ pr_debug("%s attachment %p\n", __func__, attachment);
-+ dma_unmap_sg(attachment->dev, table->sgl, table->nents, direction);
-+}
-+
-+static int vc_sm_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
-+{
-+ struct vc_sm_buffer *buf = dmabuf->priv;
-+ struct sg_table *table = buf->sg_table;
-+ unsigned long addr = vma->vm_start;
-+ unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
-+ struct scatterlist *sg;
-+ int i;
-+ int ret = 0;
-+
-+ pr_debug("%s dmabuf %p, buf %p, vm_start %08lX\n", __func__, dmabuf,
-+ buf, addr);
-+
-+ mutex_lock(&buf->lock);
-+
-+ /* now map it to userspace */
-+ for_each_sg(table->sgl, sg, table->nents, i) {
-+ struct page *page = sg_page(sg);
-+ unsigned long remainder = vma->vm_end - addr;
-+ unsigned long len = sg->length;
-+
-+ if (offset >= sg->length) {
-+ offset -= sg->length;
-+ continue;
-+ } else if (offset) {
-+ page += offset / PAGE_SIZE;
-+ len = sg->length - offset;
-+ offset = 0;
-+ }
-+ len = min(len, remainder);
-+ ret = remap_pfn_range(vma, addr, page_to_pfn(page), len,
-+ vma->vm_page_prot);
-+ if (ret)
-+ break;
-+ addr += len;
-+ if (addr >= vma->vm_end)
-+ break;
-+ }
-+ mutex_unlock(&buf->lock);
-+
-+ if (ret)
-+ pr_err("%s: failure mapping buffer to userspace\n",
-+ __func__);
-+
-+ return ret;
-+}
-+
-+static void vc_sm_dma_buf_release(struct dma_buf *dmabuf)
-+{
-+ struct vc_sm_buffer *buffer;
-+
-+ if (!dmabuf)
-+ return;
-+
-+ buffer = (struct vc_sm_buffer *)dmabuf->priv;
-+
-+ mutex_lock(&buffer->lock);
-+
-+ pr_debug("%s dmabuf %p, buffer %p\n", __func__, dmabuf, buffer);
-+
-+ buffer->in_use = 0;
-+
-+ /* Unmap on the VPU */
-+ vc_sm_vpu_free(buffer);
-+ pr_debug("%s vpu_free done\n", __func__);
-+
-+ /* Unmap our dma_buf object (the vc_sm_buffer remains until released
-+ * on the VPU).
-+ */
-+ vc_sm_clean_up_dmabuf(buffer);
-+ pr_debug("%s clean_up dmabuf done\n", __func__);
-+
-+ vc_sm_release_resource(buffer);
-+ pr_debug("%s done\n", __func__);
-+}
-+
-+static int vc_sm_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
-+ enum dma_data_direction direction)
-+{
-+ struct vc_sm_buffer *buf;
-+ struct vc_sm_dma_buf_attachment *a;
-+
-+ if (!dmabuf)
-+ return -EFAULT;
-+
-+ buf = dmabuf->priv;
-+ if (!buf)
-+ return -EFAULT;
-+
-+ mutex_lock(&buf->lock);
-+
-+ list_for_each_entry(a, &buf->attachments, list) {
-+ dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents,
-+ direction);
-+ }
-+ mutex_unlock(&buf->lock);
-+
-+ return 0;
-+}
-+
-+static int vc_sm_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
-+ enum dma_data_direction direction)
-+{
-+ struct vc_sm_buffer *buf;
-+ struct vc_sm_dma_buf_attachment *a;
-+
-+ if (!dmabuf)
-+ return -EFAULT;
-+ buf = dmabuf->priv;
-+ if (!buf)
-+ return -EFAULT;
-+
-+ mutex_lock(&buf->lock);
-+
-+ list_for_each_entry(a, &buf->attachments, list) {
-+ dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents,
-+ direction);
-+ }
-+ mutex_unlock(&buf->lock);
-+
-+ return 0;
-+}
-+
-+static void *vc_sm_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset)
-+{
-+ /* FIXME */
-+ return NULL;
-+}
-+
-+static void vc_sm_dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long offset,
-+ void *ptr)
-+{
-+ /* FIXME */
-+}
-+
-+static const struct dma_buf_ops dma_buf_ops = {
-+ .map_dma_buf = vc_sm_map_dma_buf,
-+ .unmap_dma_buf = vc_sm_unmap_dma_buf,
-+ .mmap = vc_sm_dmabuf_mmap,
-+ .release = vc_sm_dma_buf_release,
-+ .attach = vc_sm_dma_buf_attach,
-+ .detach = vc_sm_dma_buf_detatch,
-+ .begin_cpu_access = vc_sm_dma_buf_begin_cpu_access,
-+ .end_cpu_access = vc_sm_dma_buf_end_cpu_access,
-+ .map = vc_sm_dma_buf_kmap,
-+ .unmap = vc_sm_dma_buf_kunmap,
-+};
- /* Dma_buf operations for chaining through to an imported dma_buf */
- static
- int vc_sm_import_dma_buf_attach(struct dma_buf *dmabuf,
- struct dma_buf_attachment *attachment)
- {
-- struct vc_sm_buffer *res = dmabuf->priv;
-+ struct vc_sm_buffer *buf = dmabuf->priv;
-
-- if (!res->import_dma_buf)
-+ if (!buf->imported)
- return -EINVAL;
-- return res->import_dma_buf->ops->attach(res->import_dma_buf,
-+ return buf->import.dma_buf->ops->attach(buf->import.dma_buf,
- attachment);
- }
-
-@@ -334,22 +636,23 @@ static
- void vc_sm_import_dma_buf_detatch(struct dma_buf *dmabuf,
- struct dma_buf_attachment *attachment)
- {
-- struct vc_sm_buffer *res = dmabuf->priv;
-+ struct vc_sm_buffer *buf = dmabuf->priv;
-
-- if (!res->import_dma_buf)
-+ if (!buf->imported)
- return;
-- res->import_dma_buf->ops->detach(res->import_dma_buf, attachment);
-+ buf->import.dma_buf->ops->detach(buf->import.dma_buf, attachment);
- }
-
- static
- struct sg_table *vc_sm_import_map_dma_buf(struct dma_buf_attachment *attachment,
- enum dma_data_direction direction)
- {
-- struct vc_sm_buffer *res = attachment->dmabuf->priv;
-+ struct vc_sm_buffer *buf = attachment->dmabuf->priv;
-
-- if (!res->import_dma_buf)
-+ if (!buf->imported)
- return NULL;
-- return res->import_dma_buf->ops->map_dma_buf(attachment, direction);
-+ return buf->import.dma_buf->ops->map_dma_buf(attachment,
-+ direction);
- }
-
- static
-@@ -357,87 +660,88 @@ void vc_sm_import_unmap_dma_buf(struct d
- struct sg_table *table,
- enum dma_data_direction direction)
- {
-- struct vc_sm_buffer *res = attachment->dmabuf->priv;
-+ struct vc_sm_buffer *buf = attachment->dmabuf->priv;
-
-- if (!res->import_dma_buf)
-+ if (!buf->imported)
- return;
-- res->import_dma_buf->ops->unmap_dma_buf(attachment, table, direction);
-+ buf->import.dma_buf->ops->unmap_dma_buf(attachment, table, direction);
- }
-
- static
- int vc_sm_import_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
- {
-- struct vc_sm_buffer *res = dmabuf->priv;
-+ struct vc_sm_buffer *buf = dmabuf->priv;
-
-- pr_debug("%s: mmap dma_buf %p, res %p, imported db %p\n", __func__,
-- dmabuf, res, res->import_dma_buf);
-- if (!res->import_dma_buf) {
-+ pr_debug("%s: mmap dma_buf %p, buf %p, imported db %p\n", __func__,
-+ dmabuf, buf, buf->import.dma_buf);
-+ if (!buf->imported) {
- pr_err("%s: mmap dma_buf %p- not an imported buffer\n",
- __func__, dmabuf);
- return -EINVAL;
- }
-- return res->import_dma_buf->ops->mmap(res->import_dma_buf, vma);
-+ return buf->import.dma_buf->ops->mmap(buf->import.dma_buf, vma);
- }
-
- static
- void vc_sm_import_dma_buf_release(struct dma_buf *dmabuf)
- {
-- struct vc_sm_buffer *res = dmabuf->priv;
-+ struct vc_sm_buffer *buf = dmabuf->priv;
-
- pr_debug("%s: Relasing dma_buf %p\n", __func__, dmabuf);
-- if (!res->import_dma_buf)
-+ mutex_lock(&buf->lock);
-+ if (!buf->imported)
- return;
-
-- res->in_use = 0;
-+ buf->in_use = 0;
-
-- vc_sm_release_resource(res, 0);
-+ vc_sm_vpu_free(buf);
-+
-+ vc_sm_release_resource(buf);
- }
-
- static
- void *vc_sm_import_dma_buf_kmap(struct dma_buf *dmabuf,
- unsigned long offset)
- {
-- struct vc_sm_buffer *res = dmabuf->priv;
-+ struct vc_sm_buffer *buf = dmabuf->priv;
-
-- if (!res->import_dma_buf)
-+ if (!buf->imported)
- return NULL;
-- return res->import_dma_buf->ops->map(res->import_dma_buf,
-- offset);
-+ return buf->import.dma_buf->ops->map(buf->import.dma_buf, offset);
- }
-
- static
- void vc_sm_import_dma_buf_kunmap(struct dma_buf *dmabuf,
- unsigned long offset, void *ptr)
- {
-- struct vc_sm_buffer *res = dmabuf->priv;
-+ struct vc_sm_buffer *buf = dmabuf->priv;
-
-- if (!res->import_dma_buf)
-+ if (!buf->imported)
- return;
-- res->import_dma_buf->ops->unmap(res->import_dma_buf,
-- offset, ptr);
-+ buf->import.dma_buf->ops->unmap(buf->import.dma_buf, offset, ptr);
- }
-
- static
- int vc_sm_import_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
- enum dma_data_direction direction)
- {
-- struct vc_sm_buffer *res = dmabuf->priv;
-+ struct vc_sm_buffer *buf = dmabuf->priv;
-
-- if (!res->import_dma_buf)
-+ if (!buf->imported)
- return -EINVAL;
-- return res->import_dma_buf->ops->begin_cpu_access(res->import_dma_buf,
-- direction);
-+ return buf->import.dma_buf->ops->begin_cpu_access(buf->import.dma_buf,
-+ direction);
- }
-
- static
- int vc_sm_import_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
- enum dma_data_direction direction)
- {
-- struct vc_sm_buffer *res = dmabuf->priv;
-+ struct vc_sm_buffer *buf = dmabuf->priv;
-
-- if (!res->import_dma_buf)
-+ if (!buf->imported)
- return -EINVAL;
-- return res->import_dma_buf->ops->end_cpu_access(res->import_dma_buf,
-+ return buf->import.dma_buf->ops->end_cpu_access(buf->import.dma_buf,
- direction);
- }
-
-@@ -516,9 +820,8 @@ vc_sm_cma_import_dmabuf_internal(struct
- memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
- sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
-
-- pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %pad, size %u\n",
-- __func__, import.name, import.type, &dma_addr,
-- import.size);
-+ pr_debug("[%s]: attempt to import \"%s\" data - type %u, addr %pad, size %u.\n",
-+ __func__, import.name, import.type, &dma_addr, import.size);
-
- /* Allocate the videocore buffer. */
- status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
-@@ -548,12 +851,14 @@ vc_sm_cma_import_dmabuf_internal(struct
- buffer->size = import.size;
- buffer->vpu_state = VPU_MAPPED;
-
-- buffer->import_dma_buf = dma_buf;
-+ buffer->imported = 1;
-+ buffer->import.dma_buf = dma_buf;
-
-- buffer->attach = attach;
-- buffer->sgt = sgt;
-+ buffer->import.attach = attach;
-+ buffer->import.sgt = sgt;
- buffer->dma_addr = dma_addr;
- buffer->in_use = 1;
-+ buffer->kernel_id = import.kernel_id;
-
- /*
- * We're done - we need to export a new dmabuf chaining through most
-@@ -594,6 +899,91 @@ error:
- return ret;
- }
-
-+static int vc_sm_cma_vpu_alloc(u32 size, uint32_t align, const char *name,
-+ u32 mem_handle, struct vc_sm_buffer **ret_buffer)
-+{
-+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-+ struct vc_sm_buffer *buffer = NULL;
-+ int aligned_size;
-+ int ret = 0;
-+
-+ /* Align to the user requested align */
-+ aligned_size = ALIGN(size, align);
-+ /* and then to a page boundary */
-+ aligned_size = PAGE_ALIGN(aligned_size);
-+
-+ if (!aligned_size)
-+ return -EINVAL;
-+
-+ /* Allocate local buffer to track this allocation. */
-+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
-+ if (!buffer)
-+ return -ENOMEM;
-+
-+ mutex_init(&buffer->lock);
-+
-+ if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
-+ aligned_size)) {
-+ pr_err("[%s]: cma alloc of %d bytes failed\n",
-+ __func__, aligned_size);
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+ buffer->sg_table = buffer->alloc.sg_table;
-+
-+ pr_debug("[%s]: cma alloc of %d bytes success\n",
-+ __func__, aligned_size);
-+
-+ if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
-+ buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
-+ pr_err("[%s]: dma_map_sg failed\n", __func__);
-+ goto error;
-+ }
-+
-+ INIT_LIST_HEAD(&buffer->attachments);
-+
-+ memcpy(buffer->name, name,
-+ min(sizeof(buffer->name), strlen(name)));
-+
-+ exp_info.ops = &dma_buf_ops;
-+ exp_info.size = aligned_size;
-+ exp_info.flags = O_RDWR;
-+ exp_info.priv = buffer;
-+
-+ buffer->dma_buf = dma_buf_export(&exp_info);
-+ if (IS_ERR(buffer->dma_buf)) {
-+ ret = PTR_ERR(buffer->dma_buf);
-+ goto error;
-+ }
-+ buffer->dma_addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
-+ if ((buffer->dma_addr & 0xC0000000) != 0xC0000000) {
-+ pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
-+ __func__, &buffer->dma_addr);
-+ buffer->dma_addr |= 0xC0000000;
-+ }
-+ buffer->private = sm_state->vpu_allocs;
-+
-+ buffer->vc_handle = mem_handle;
-+ buffer->vpu_state = VPU_MAPPED;
-+ buffer->vpu_allocated = 1;
-+ buffer->size = size;
-+ /*
-+ * Create an ID that will be passed along with our message so
-+ * that when we service the release reply, we can look up which
-+ * resource is being released.
-+ */
-+ buffer->kernel_id = get_kernel_id(buffer);
-+
-+ vc_sm_add_resource(sm_state->vpu_allocs, buffer);
-+
-+ *ret_buffer = buffer;
-+ return 0;
-+error:
-+ if (buffer)
-+ vc_sm_release_resource(buffer);
-+ return ret;
-+}
-+
- static void
- vc_sm_vpu_event(struct sm_instance *instance, struct vc_sm_result_t *reply,
- int reply_len)
-@@ -612,21 +1002,61 @@ vc_sm_vpu_event(struct sm_instance *inst
- struct vc_sm_released *release = (struct vc_sm_released *)reply;
- struct vc_sm_buffer *buffer =
- lookup_kernel_id(release->kernel_id);
-+ if (!buffer) {
-+ pr_err("%s: VC released a buffer that is already released, kernel_id %d\n",
-+ __func__, release->kernel_id);
-+ break;
-+ }
-+ mutex_lock(&buffer->lock);
-
-- /*
-- * FIXME: Need to check buffer is still valid and allocated
-- * before continuing
-- */
- pr_debug("%s: Released addr %08x, size %u, id %08x, mem_handle %08x\n",
- __func__, release->addr, release->size,
- release->kernel_id, release->vc_handle);
-- mutex_lock(&buffer->lock);
-+
- buffer->vc_handle = 0;
- buffer->vpu_state = VPU_NOT_MAPPED;
-- mutex_unlock(&buffer->lock);
- free_kernel_id(release->kernel_id);
-
-- vc_sm_release_resource(buffer, 0);
-+ if (buffer->vpu_allocated) {
-+ /* VPU allocation, so release the dmabuf which will
-+ * trigger the clean up.
-+ */
-+ mutex_unlock(&buffer->lock);
-+ dma_buf_put(buffer->dma_buf);
-+ } else {
-+ vc_sm_release_resource(buffer);
-+ }
-+ }
-+ break;
-+ case VC_SM_MSG_TYPE_VC_MEM_REQUEST:
-+ {
-+ struct vc_sm_buffer *buffer = NULL;
-+ struct vc_sm_vc_mem_request *req =
-+ (struct vc_sm_vc_mem_request *)reply;
-+ struct vc_sm_vc_mem_request_result reply;
-+ int ret;
-+
-+ pr_debug("%s: Request %u bytes of memory, align %d name %s, trans_id %08x\n",
-+ __func__, req->size, req->align, req->name,
-+ req->trans_id);
-+ ret = vc_sm_cma_vpu_alloc(req->size, req->align, req->name,
-+ req->vc_handle, &buffer);
-+
-+ reply.trans_id = req->trans_id;
-+ if (!ret) {
-+ reply.addr = buffer->dma_addr;
-+ reply.kernel_id = buffer->kernel_id;
-+ pr_debug("%s: Allocated resource buffer %p, addr %pad\n",
-+ __func__, buffer, &buffer->dma_addr);
-+ } else {
-+ pr_err("%s: Allocation failed size %u, name %s, vc_handle %u\n",
-+ __func__, req->size, req->name, req->vc_handle);
-+ reply.addr = 0;
-+ reply.kernel_id = 0;
-+ }
-+ vc_sm_vchi_client_vc_mem_req_reply(sm_state->sm_handle, &reply,
-+ &sm_state->int_trans_id);
-+ break;
- }
- break;
- default:
-@@ -645,6 +1075,14 @@ static void vc_sm_connected_init(void)
-
- pr_info("[%s]: start\n", __func__);
-
-+ if (vc_sm_cma_add_heaps(&sm_state->cma_heap) ||
-+ !sm_state->cma_heap) {
-+ pr_err("[%s]: failed to initialise CMA heaps\n",
-+ __func__);
-+ ret = -EIO;
-+ goto err_free_mem;
-+ }
-+
- /*
- * Initialize and create a VCHI connection for the shared memory service
- * running on videocore.
-@@ -696,7 +1134,7 @@ static void vc_sm_connected_init(void)
- goto err_remove_shared_memory;
- }
-
-- version.version = 1;
-+ version.version = 2;
- ret = vc_sm_cma_vchi_client_version(sm_state->sm_handle, &version,
- &version_result,
- &sm_state->int_trans_id);
-@@ -768,7 +1206,7 @@ static int bcm2835_vc_sm_cma_remove(stru
- int vc_sm_cma_int_handle(void *handle)
- {
- struct dma_buf *dma_buf = (struct dma_buf *)handle;
-- struct vc_sm_buffer *res;
-+ struct vc_sm_buffer *buf;
-
- /* Validate we can work with this device. */
- if (!sm_state || !handle) {
-@@ -776,8 +1214,8 @@ int vc_sm_cma_int_handle(void *handle)
- return 0;
- }
-
-- res = (struct vc_sm_buffer *)dma_buf->priv;
-- return res->vc_handle;
-+ buf = (struct vc_sm_buffer *)dma_buf->priv;
-+ return buf->vc_handle;
- }
- EXPORT_SYMBOL_GPL(vc_sm_cma_int_handle);
-
-@@ -804,7 +1242,7 @@ EXPORT_SYMBOL_GPL(vc_sm_cma_free);
- int vc_sm_cma_import_dmabuf(struct dma_buf *src_dmabuf, void **handle)
- {
- struct dma_buf *new_dma_buf;
-- struct vc_sm_buffer *res;
-+ struct vc_sm_buffer *buf;
- int ret;
-
- /* Validate we can work with this device. */
-@@ -818,7 +1256,7 @@ int vc_sm_cma_import_dmabuf(struct dma_b
-
- if (!ret) {
- pr_debug("%s: imported to ptr %p\n", __func__, new_dma_buf);
-- res = (struct vc_sm_buffer *)new_dma_buf->priv;
-+ buf = (struct vc_sm_buffer *)new_dma_buf->priv;
-
- /* Assign valid handle at this time.*/
- *handle = new_dma_buf;
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
-@@ -21,6 +21,8 @@
- #include <linux/types.h>
- #include <linux/miscdevice.h>
-
-+#include "vc_sm_cma.h"
-+
- #define VC_SM_MAX_NAME_LEN 32
-
- enum vc_sm_vpu_mapping_state {
-@@ -29,31 +31,51 @@ enum vc_sm_vpu_mapping_state {
- VPU_UNMAPPING
- };
-
-+struct vc_sm_imported {
-+ struct dma_buf *dma_buf;
-+ struct dma_buf_attachment *attach;
-+ struct sg_table *sgt;
-+};
-+
- struct vc_sm_buffer {
- struct list_head global_buffer_list; /* Global list of buffers. */
-
-+ /* Index in the kernel_id idr so that we can find the
-+ * mmal_msg_context again when servicing the VCHI reply.
-+ */
-+ int kernel_id;
-+
- size_t size;
-
- /* Lock over all the following state for this buffer */
- struct mutex lock;
-- struct sg_table *sg_table;
- struct list_head attachments;
-
- char name[VC_SM_MAX_NAME_LEN];
-
- int in_use:1; /* Kernel is still using this resource */
-+ int imported:1; /* Imported dmabuf */
-+
-+ struct sg_table *sg_table;
-
- enum vc_sm_vpu_mapping_state vpu_state;
- u32 vc_handle; /* VideoCore handle for this buffer */
-+ int vpu_allocated; /*
-+ * The VPU made this allocation. Release the
-+ * local dma_buf when the VPU releases the
-+ * resource.
-+ */
-
- /* DMABUF related fields */
-- struct dma_buf *import_dma_buf;
- struct dma_buf *dma_buf;
-- struct dma_buf_attachment *attach;
-- struct sg_table *sgt;
- dma_addr_t dma_addr;
-
- struct vc_sm_privdata_t *private;
-+
-+ union {
-+ struct vc_sm_cma_alloc_data alloc;
-+ struct vc_sm_imported import;
-+ };
- };
-
- #endif
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
-@@ -0,0 +1,99 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * VideoCore Shared Memory CMA allocator
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ *
-+ * Based on the Android ION allocator
-+ * Copyright (C) Linaro 2012
-+ * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
-+ *
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/errno.h>
-+#include <linux/err.h>
-+#include <linux/cma.h>
-+#include <linux/scatterlist.h>
-+
-+#include "vc_sm_cma.h"
-+
-+/* CMA heap operations functions */
-+int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
-+ struct vc_sm_cma_alloc_data *buffer,
-+ unsigned long len)
-+{
-+ /* len should already be page aligned */
-+ unsigned long num_pages = len / PAGE_SIZE;
-+ struct sg_table *table;
-+ struct page *pages;
-+ int ret;
-+
-+ pages = cma_alloc(cma_heap, num_pages, 0, GFP_KERNEL);
-+ if (!pages)
-+ return -ENOMEM;
-+
-+ table = kmalloc(sizeof(*table), GFP_KERNEL);
-+ if (!table)
-+ goto err;
-+
-+ ret = sg_alloc_table(table, 1, GFP_KERNEL);
-+ if (ret)
-+ goto free_mem;
-+
-+ sg_set_page(table->sgl, pages, len, 0);
-+
-+ buffer->priv_virt = pages;
-+ buffer->sg_table = table;
-+ buffer->cma_heap = cma_heap;
-+ buffer->num_pages = num_pages;
-+ return 0;
-+
-+free_mem:
-+ kfree(table);
-+err:
-+ cma_release(cma_heap, pages, num_pages);
-+ return -ENOMEM;
-+}
-+
-+void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer)
-+{
-+ struct cma *cma_heap = buffer->cma_heap;
-+ struct page *pages = buffer->priv_virt;
-+
-+ /* release memory */
-+ if (cma_heap)
-+ cma_release(cma_heap, pages, buffer->num_pages);
-+
-+ /* release sg table */
-+ if (buffer->sg_table) {
-+ sg_free_table(buffer->sg_table);
-+ kfree(buffer->sg_table);
-+ buffer->sg_table = NULL;
-+ }
-+}
-+
-+int __vc_sm_cma_add_heaps(struct cma *cma, void *priv)
-+{
-+ struct cma **heap = (struct cma **)priv;
-+ const char *name = cma_get_name(cma);
-+
-+ if (!(*heap)) {
-+ phys_addr_t phys_addr = cma_get_base(cma);
-+
-+ pr_debug("%s: Adding cma heap %s (start %pap, size %lu) for use by vcsm\n",
-+ __func__, name, &phys_addr, cma_get_size(cma));
-+ *heap = cma;
-+ } else {
-+ pr_err("%s: Ignoring heap %s as already set\n",
-+ __func__, name);
-+ }
-+
-+ return 0;
-+}
-+
-+int vc_sm_cma_add_heaps(struct cma **cma_heap)
-+{
-+ cma_for_each_area(__vc_sm_cma_add_heaps, cma_heap);
-+ return 0;
-+}
---- /dev/null
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
-@@ -0,0 +1,39 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/*
-+ * VideoCore Shared Memory CMA allocator
-+ *
-+ * Copyright: 2018, Raspberry Pi (Trading) Ltd
-+ *
-+ * Based on the Android ION allocator
-+ * Copyright (C) Linaro 2012
-+ * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
-+ *
-+ * This software is licensed under the terms of the GNU General Public
-+ * License version 2, as published by the Free Software Foundation, and
-+ * may be copied, distributed, and modified under those terms.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ */
-+#ifndef VC_SM_CMA_H
-+#define VC_SM_CMA_H
-+
-+struct vc_sm_cma_alloc_data {
-+ struct cma *cma_heap;
-+ unsigned long num_pages;
-+ void *priv_virt;
-+ struct sg_table *sg_table;
-+};
-+
-+int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
-+ struct vc_sm_cma_alloc_data *buffer,
-+ unsigned long len);
-+void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer);
-+
-+int vc_sm_cma_add_heaps(struct cma **cma_heap);
-+
-+#endif
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-@@ -500,3 +500,13 @@ int vc_sm_cma_vchi_client_version(struct
- msg, sizeof(*msg), NULL, 0,
- cur_trans_id, 0);
- }
-+
-+int vc_sm_vchi_client_vc_mem_req_reply(struct sm_instance *handle,
-+ struct vc_sm_vc_mem_request_result *msg,
-+ uint32_t *cur_trans_id)
-+{
-+ return vc_sm_cma_vchi_send_msg(handle,
-+ VC_SM_MSG_TYPE_VC_MEM_REQUEST_REPLY,
-+ msg, sizeof(*msg), 0, 0, cur_trans_id,
-+ 0);
-+}
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.h
-@@ -56,4 +56,8 @@ int vc_sm_cma_vchi_client_version(struct
- struct vc_sm_result_t *result,
- u32 *cur_trans_id);
-
-+int vc_sm_vchi_client_vc_mem_req_reply(struct sm_instance *handle,
-+ struct vc_sm_vc_mem_request_result *msg,
-+ uint32_t *cur_trans_id);
-+
- #endif /* __VC_SM_CMA_VCHI_H__INCLUDED__ */
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_defs.h
-@@ -264,6 +264,8 @@ struct vc_sm_vc_mem_request {
- u32 align;
- /* resource name (for easier tracking) */
- char name[VC_SM_RESOURCE_NAME];
-+ /* VPU handle for the resource */
-+ u32 vc_handle;
- };
-
- /* Response from the kernel to provide the VPU with some memory */
--- /dev/null
+From d21247010c8e885916908e641481d1d915d8a690 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 13 May 2019 16:47:54 +0100
+Subject: [PATCH 630/725] staging: vcsm-cma: Alter dev node permissions to 0666
+
+Until the udev rules are updated, open up access to this node by
+default.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -1572,6 +1572,8 @@ static void vc_sm_connected_init(void)
+ sm_state->misc_dev.name = DEVICE_NAME;
+ sm_state->misc_dev.fops = &vc_sm_ops;
+ sm_state->misc_dev.parent = NULL;
++ /* Temporarily set as 666 until udev rules have been sorted */
++ sm_state->misc_dev.mode = 0666;
+ ret = misc_register(&sm_state->misc_dev);
+ if (ret) {
+ pr_err("vcsm-cma: failed to register misc device.\n");
+++ /dev/null
-From 2de0580b775aa8ff923d70ca84e8688b28dd2ced Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 11 Mar 2019 16:38:32 +0000
-Subject: [PATCH 631/703] staging: vc-sm-cma: Update TODO.
-
-The driver is already a platform driver, so that can be
-deleted from the TODO.
-There are no known issues that need to be resolved.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/TODO | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/TODO
-+++ b/drivers/staging/vc04_services/vc-sm-cma/TODO
-@@ -1,2 +1 @@
--1) Convert to a platform driver.
--
-+No currently outstanding tasks except some clean-up.
--- /dev/null
+From e31bdb189cc74c8bcba855bd617f9a663d794fe4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 16 May 2019 15:17:19 +0100
+Subject: [PATCH 631/725] staging: vcsm-cma: Drop logging level on messages in
+ vc_sm_release_resource
+
+They weren't errors but were logged as such.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -301,14 +301,13 @@ static void vc_sm_release_resource(struc
+
+ if (buffer->vc_handle) {
+ /* We've sent the unmap request but not had the response. */
+- pr_err("[%s]: Waiting for VPU unmap response on %p\n",
+- __func__, buffer);
++ pr_debug("[%s]: Waiting for VPU unmap response on %p\n",
++ __func__, buffer);
+ goto defer;
+ }
+ if (buffer->in_use) {
+ /* dmabuf still in use - we await the release */
+- pr_err("[%s]: buffer %p is still in use\n",
+- __func__, buffer);
++ pr_debug("[%s]: buffer %p is still in use\n", __func__, buffer);
+ goto defer;
+ }
+
+++ /dev/null
-From 2cd18cda345cadbc702520602cbf41dee0774cc0 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 11 Mar 2019 16:35:23 +0000
-Subject: [PATCH 632/703] staging: vc-sm-cma: Add in userspace allocation API
-
-Replacing the functionality from the older vc-sm driver,
-add in a userspace API that allows allocation of buffers,
-and importing of dma-bufs.
-The driver hands out dma-buf fds, therefore much of the
-handling around lifespan and odd mmaps from the old driver
-goes away.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vc-sm-cma/vc_sm.c | 371 ++++++++++++++++--
- .../vc04_services/vc-sm-cma/vc_sm_cma.c | 3 +-
- .../vc04_services/vc-sm-cma/vc_sm_cma.h | 2 +-
- include/linux/broadcom/vc_sm_cma_ioctl.h | 87 ++++
- 4 files changed, 435 insertions(+), 28 deletions(-)
- create mode 100644 include/linux/broadcom/vc_sm_cma_ioctl.h
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -36,6 +36,7 @@
- #include <linux/fs.h>
- #include <linux/kernel.h>
- #include <linux/list.h>
-+#include <linux/miscdevice.h>
- #include <linux/module.h>
- #include <linux/mm.h>
- #include <linux/of_device.h>
-@@ -52,6 +53,7 @@
- #include "vc_sm.h"
- #include "vc_sm_cma.h"
- #include "vc_sm_knl.h"
-+#include <linux/broadcom/vc_sm_cma_ioctl.h>
-
- /* ---- Private Constants and Types --------------------------------------- */
-
-@@ -83,6 +85,8 @@ struct sm_pde_t {
- struct sm_state_t {
- struct platform_device *pdev;
-
-+ struct miscdevice misc_dev;
-+
- struct sm_instance *sm_handle; /* Handle for videocore service. */
- struct cma *cma_heap;
-
-@@ -346,7 +350,6 @@ static void vc_sm_release_resource(struc
-
- defer:
- mutex_unlock(&buffer->lock);
-- return;
- }
-
- /* Create support for private data tracking. */
-@@ -381,7 +384,7 @@ static struct sg_table *dup_sg_table(str
- ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL);
- if (ret) {
- kfree(new_table);
-- return ERR_PTR(-ENOMEM);
-+ return ERR_PTR(ret);
- }
-
- new_sg = new_table->sgl;
-@@ -417,7 +420,7 @@ static int vc_sm_dma_buf_attach(struct d
- table = dup_sg_table(buf->sg_table);
- if (IS_ERR(table)) {
- kfree(a);
-- return -ENOMEM;
-+ return PTR_ERR(table);
- }
-
- a->table = table;
-@@ -433,8 +436,8 @@ static int vc_sm_dma_buf_attach(struct d
- return 0;
- }
-
--static void vc_sm_dma_buf_detatch(struct dma_buf *dmabuf,
-- struct dma_buf_attachment *attachment)
-+static void vc_sm_dma_buf_detach(struct dma_buf *dmabuf,
-+ struct dma_buf_attachment *attachment)
- {
- struct vc_sm_dma_buf_attachment *a = attachment->priv;
- struct vc_sm_buffer *buf = dmabuf->priv;
-@@ -544,6 +547,9 @@ static void vc_sm_dma_buf_release(struct
- vc_sm_clean_up_dmabuf(buffer);
- pr_debug("%s clean_up dmabuf done\n", __func__);
-
-+ /* buffer->lock will be destroyed by vc_sm_release_resource if finished
-+ * with, otherwise unlocked. Do NOT unlock here.
-+ */
- vc_sm_release_resource(buffer);
- pr_debug("%s done\n", __func__);
- }
-@@ -613,7 +619,7 @@ static const struct dma_buf_ops dma_buf_
- .mmap = vc_sm_dmabuf_mmap,
- .release = vc_sm_dma_buf_release,
- .attach = vc_sm_dma_buf_attach,
-- .detach = vc_sm_dma_buf_detatch,
-+ .detach = vc_sm_dma_buf_detach,
- .begin_cpu_access = vc_sm_dma_buf_begin_cpu_access,
- .end_cpu_access = vc_sm_dma_buf_end_cpu_access,
- .map = vc_sm_dma_buf_kmap,
-@@ -762,6 +768,7 @@ static const struct dma_buf_ops dma_buf_
- int
- vc_sm_cma_import_dmabuf_internal(struct vc_sm_privdata_t *private,
- struct dma_buf *dma_buf,
-+ int fd,
- struct dma_buf **imported_buf)
- {
- DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-@@ -775,10 +782,15 @@ vc_sm_cma_import_dmabuf_internal(struct
- int status;
-
- /* Setup our allocation parameters */
-- pr_debug("%s: importing dma_buf %p\n", __func__, dma_buf);
-+ pr_debug("%s: importing dma_buf %p/fd %d\n", __func__, dma_buf, fd);
-
-- get_dma_buf(dma_buf);
-- dma_buf = dma_buf;
-+ if (fd < 0)
-+ get_dma_buf(dma_buf);
-+ else
-+ dma_buf = dma_buf_get(fd);
-+
-+ if (!dma_buf)
-+ return -EINVAL;
-
- attach = dma_buf_attach(dma_buf, &sm_state->pdev->dev);
- if (IS_ERR(attach)) {
-@@ -921,6 +933,10 @@ static int vc_sm_cma_vpu_alloc(u32 size,
- return -ENOMEM;
-
- mutex_init(&buffer->lock);
-+ /* Acquire the mutex as vc_sm_release_resource will release it in the
-+ * error path.
-+ */
-+ mutex_lock(&buffer->lock);
-
- if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
- aligned_size)) {
-@@ -976,6 +992,8 @@ static int vc_sm_cma_vpu_alloc(u32 size,
-
- vc_sm_add_resource(sm_state->vpu_allocs, buffer);
-
-+ mutex_unlock(&buffer->lock);
-+
- *ret_buffer = buffer;
- return 0;
- error:
-@@ -1065,6 +1083,297 @@ vc_sm_vpu_event(struct sm_instance *inst
- }
- }
-
-+/* Userspace handling */
-+/*
-+ * Open the device. Creates a private state to help track all allocation
-+ * associated with this device.
-+ */
-+static int vc_sm_cma_open(struct inode *inode, struct file *file)
-+{
-+ /* Make sure the device was started properly. */
-+ if (!sm_state) {
-+ pr_err("[%s]: invalid device\n", __func__);
-+ return -EPERM;
-+ }
-+
-+ file->private_data = vc_sm_cma_create_priv_data(current->tgid);
-+ if (!file->private_data) {
-+ pr_err("[%s]: failed to create data tracker\n", __func__);
-+
-+ return -ENOMEM;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Close the vcsm-cma device.
-+ * All allocations are file descriptors to the dmabuf objects, so we will get
-+ * the clean up request on those as those are cleaned up.
-+ */
-+static int vc_sm_cma_release(struct inode *inode, struct file *file)
-+{
-+ struct vc_sm_privdata_t *file_data =
-+ (struct vc_sm_privdata_t *)file->private_data;
-+ int ret = 0;
-+
-+ /* Make sure the device was started properly. */
-+ if (!sm_state || !file_data) {
-+ pr_err("[%s]: invalid device\n", __func__);
-+ ret = -EPERM;
-+ goto out;
-+ }
-+
-+ pr_debug("[%s]: using private data %p\n", __func__, file_data);
-+
-+ /* Terminate the private data. */
-+ kfree(file_data);
-+
-+out:
-+ return ret;
-+}
-+
-+/*
-+ * Allocate a shared memory handle and block.
-+ * Allocation is from CMA, and then imported into the VPU mappings.
-+ */
-+int vc_sm_cma_ioctl_alloc(struct vc_sm_privdata_t *private,
-+ struct vc_sm_cma_ioctl_alloc *ioparam)
-+{
-+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-+ struct vc_sm_buffer *buffer = NULL;
-+ struct vc_sm_import import = { 0 };
-+ struct vc_sm_import_result result = { 0 };
-+ struct dma_buf *dmabuf = NULL;
-+ int aligned_size;
-+ int ret = 0;
-+ int status;
-+ int fd = -1;
-+
-+ aligned_size = PAGE_ALIGN(ioparam->size);
-+
-+ if (!aligned_size)
-+ return -EINVAL;
-+
-+ /* Allocate local buffer to track this allocation. */
-+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
-+ if (!buffer) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
-+ aligned_size)) {
-+ pr_err("[%s]: cma alloc of %d bytes failed\n",
-+ __func__, aligned_size);
-+ kfree(buffer);
-+ return -ENOMEM;
-+ }
-+ buffer->sg_table = buffer->alloc.sg_table;
-+
-+ if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
-+ buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
-+ pr_err("[%s]: dma_map_sg failed\n", __func__);
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ import.type = VC_SM_ALLOC_NON_CACHED;
-+ import.allocator = current->tgid;
-+
-+ if (*ioparam->name)
-+ memcpy(import.name, ioparam->name, sizeof(import.name) - 1);
-+ else
-+ memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
-+ sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
-+
-+ mutex_init(&buffer->lock);
-+ INIT_LIST_HEAD(&buffer->attachments);
-+ memcpy(buffer->name, import.name,
-+ min(sizeof(buffer->name), sizeof(import.name) - 1));
-+
-+ exp_info.ops = &dma_buf_ops;
-+ exp_info.size = aligned_size;
-+ exp_info.flags = O_RDWR;
-+ exp_info.priv = buffer;
-+
-+ dmabuf = dma_buf_export(&exp_info);
-+ if (IS_ERR(dmabuf)) {
-+ ret = PTR_ERR(dmabuf);
-+ goto error;
-+ }
-+ buffer->dma_buf = dmabuf;
-+
-+ import.addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
-+ import.size = aligned_size;
-+ import.kernel_id = (uint32_t)buffer;
-+
-+ /* Wrap it into a videocore buffer. */
-+ status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
-+ &sm_state->int_trans_id);
-+ if (status == -EINTR) {
-+ pr_debug("[%s]: requesting import memory action restart (trans_id: %u)\n",
-+ __func__, sm_state->int_trans_id);
-+ ret = -ERESTARTSYS;
-+ private->restart_sys = -EINTR;
-+ private->int_action = VC_SM_MSG_TYPE_IMPORT;
-+ goto error;
-+ } else if (status || !result.res_handle) {
-+ pr_err("[%s]: failed to import memory on videocore (status: %u, trans_id: %u)\n",
-+ __func__, status, sm_state->int_trans_id);
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ /* Keep track of the buffer we created. */
-+ buffer->private = private;
-+ buffer->vc_handle = result.res_handle;
-+ buffer->size = import.size;
-+ buffer->dma_addr = import.addr;
-+ buffer->vpu_state = VPU_MAPPED;
-+ //buffer->res_cached = ioparam->cached;
-+
-+ fd = dma_buf_fd(dmabuf, O_CLOEXEC);
-+ if (fd < 0)
-+ goto error;
-+
-+ vc_sm_add_resource(private, buffer);
-+
-+ pr_debug("[%s]: Added resource as fd %d, buffer %p, private %p, dma_addr %pad\n",
-+ __func__, fd, buffer, private, &buffer->dma_addr);
-+
-+ /* We're done */
-+ ioparam->handle = fd;
-+ ioparam->vc_handle = buffer->vc_handle;
-+ ioparam->dma_addr = buffer->dma_addr;
-+ return 0;
-+
-+error:
-+ if (buffer) {
-+ pr_err("[%s]: something failed - cleanup. ret %d\n", __func__,
-+ ret);
-+
-+ dma_buf_put(dmabuf);
-+ }
-+ return ret;
-+}
-+
-+static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ int ret = 0;
-+ unsigned int cmdnr = _IOC_NR(cmd);
-+ struct vc_sm_privdata_t *file_data =
-+ (struct vc_sm_privdata_t *)file->private_data;
-+
-+ /* Validate we can work with this device. */
-+ if (!sm_state || !file_data) {
-+ pr_err("[%s]: invalid device\n", __func__);
-+ return -EPERM;
-+ }
-+
-+ pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
-+ current->tgid, file_data->pid);
-+
-+ /* Action is a re-post of a previously interrupted action? */
-+ if (file_data->restart_sys == -EINTR) {
-+ struct vc_sm_action_clean_t action_clean;
-+
-+ pr_debug("[%s]: clean up of action %u (trans_id: %u) following EINTR\n",
-+ __func__, file_data->int_action,
-+ file_data->int_trans_id);
-+
-+ action_clean.res_action = file_data->int_action;
-+ action_clean.action_trans_id = file_data->int_trans_id;
-+
-+ file_data->restart_sys = 0;
-+ }
-+
-+ /* Now process the command. */
-+ switch (cmdnr) {
-+ /* New memory allocation.
-+ */
-+ case VC_SM_CMA_CMD_ALLOC:
-+ {
-+ struct vc_sm_cma_ioctl_alloc ioparam;
-+
-+ /* Get the parameter data. */
-+ if (copy_from_user
-+ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
-+ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
-+ __func__, cmdnr);
-+ ret = -EFAULT;
-+ break;
-+ }
-+
-+ ret = vc_sm_cma_ioctl_alloc(file_data, &ioparam);
-+ if (!ret &&
-+ (copy_to_user((void *)arg, &ioparam,
-+ sizeof(ioparam)) != 0)) {
-+ /* FIXME: Release allocation */
-+ pr_err("[%s]: failed to copy-to-user for cmd %x\n",
-+ __func__, cmdnr);
-+ ret = -EFAULT;
-+ }
-+ break;
-+ }
-+
-+ case VC_SM_CMA_CMD_IMPORT_DMABUF:
-+ {
-+ struct vc_sm_cma_ioctl_import_dmabuf ioparam;
-+ struct dma_buf *new_dmabuf;
-+
-+ /* Get the parameter data. */
-+ if (copy_from_user
-+ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
-+ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
-+ __func__, cmdnr);
-+ ret = -EFAULT;
-+ break;
-+ }
-+
-+ ret = vc_sm_cma_import_dmabuf_internal(file_data,
-+ NULL,
-+ ioparam.dmabuf_fd,
-+ &new_dmabuf);
-+
-+ if (!ret) {
-+ struct vc_sm_buffer *buf = new_dmabuf->priv;
-+
-+ ioparam.size = buf->size;
-+ ioparam.handle = dma_buf_fd(new_dmabuf,
-+ O_CLOEXEC);
-+ ioparam.vc_handle = buf->vc_handle;
-+ ioparam.dma_addr = buf->dma_addr;
-+
-+ if (ioparam.handle < 0 ||
-+ (copy_to_user((void *)arg, &ioparam,
-+ sizeof(ioparam)) != 0)) {
-+ dma_buf_put(new_dmabuf);
-+ /* FIXME: Release allocation */
-+ ret = -EFAULT;
-+ }
-+ }
-+ break;
-+ }
-+
-+ default:
-+ ret = -EINVAL;
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+/* Device operations that we managed in this driver. */
-+static const struct file_operations vc_sm_ops = {
-+ .owner = THIS_MODULE,
-+ .unlocked_ioctl = vc_sm_cma_ioctl,
-+ .open = vc_sm_cma_open,
-+ .release = vc_sm_cma_release,
-+};
-+
-+/* Driver load/unload functions */
- /* Videocore connected. */
- static void vc_sm_connected_init(void)
- {
-@@ -1075,12 +1384,11 @@ static void vc_sm_connected_init(void)
-
- pr_info("[%s]: start\n", __func__);
-
-- if (vc_sm_cma_add_heaps(&sm_state->cma_heap) ||
-- !sm_state->cma_heap) {
-- pr_err("[%s]: failed to initialise CMA heaps\n",
-+ vc_sm_cma_add_heaps(&sm_state->cma_heap);
-+ if (!sm_state->cma_heap) {
-+ pr_err("[%s]: failed to initialise CMA heap\n",
- __func__);
-- ret = -EIO;
-- goto err_free_mem;
-+ return;
- }
-
- /*
-@@ -1092,8 +1400,7 @@ static void vc_sm_connected_init(void)
- pr_err("[%s]: failed to initialise VCHI instance (ret=%d)\n",
- __func__, ret);
-
-- ret = -EIO;
-- goto err_failed;
-+ return;
- }
-
- ret = vchi_connect(NULL, 0, vchi_instance);
-@@ -1101,8 +1408,7 @@ static void vc_sm_connected_init(void)
- pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n",
- __func__, ret);
-
-- ret = -EIO;
-- goto err_failed;
-+ return;
- }
-
- /* Initialize an instance of the shared memory service. */
-@@ -1112,8 +1418,7 @@ static void vc_sm_connected_init(void)
- pr_err("[%s]: failed to initialize shared memory service\n",
- __func__);
-
-- ret = -EPERM;
-- goto err_failed;
-+ return;
- }
-
- /* Create a debug fs directory entry (root). */
-@@ -1127,11 +1432,22 @@ static void vc_sm_connected_init(void)
-
- INIT_LIST_HEAD(&sm_state->buffer_list);
-
-+ /* Create a shared memory device. */
-+ sm_state->misc_dev.minor = MISC_DYNAMIC_MINOR;
-+ sm_state->misc_dev.name = DEVICE_NAME;
-+ sm_state->misc_dev.fops = &vc_sm_ops;
-+ sm_state->misc_dev.parent = NULL;
-+ ret = misc_register(&sm_state->misc_dev);
-+ if (ret) {
-+ pr_err("vcsm-cma: failed to register misc device.\n");
-+ goto err_remove_debugfs;
-+ }
-+
- sm_state->data_knl = vc_sm_cma_create_priv_data(0);
- if (!sm_state->data_knl) {
- pr_err("[%s]: failed to create kernel private data tracker\n",
- __func__);
-- goto err_remove_shared_memory;
-+ goto err_remove_misc_dev;
- }
-
- version.version = 2;
-@@ -1148,11 +1464,13 @@ static void vc_sm_connected_init(void)
- pr_info("[%s]: installed successfully\n", __func__);
- return;
-
--err_remove_shared_memory:
-+err_remove_misc_dev:
-+ misc_deregister(&sm_state->misc_dev);
-+err_remove_debugfs:
- debugfs_remove_recursive(sm_state->dir_root);
- vc_sm_cma_vchi_stop(&sm_state->sm_handle);
--err_failed:
-- pr_info("[%s]: failed, ret %d\n", __func__, ret);
-+
-+ return;
- }
-
- /* Driver loading. */
-@@ -1184,6 +1502,8 @@ static int bcm2835_vc_sm_cma_remove(stru
- {
- pr_debug("[%s]: start\n", __func__);
- if (sm_inited) {
-+ misc_deregister(&sm_state->misc_dev);
-+
- /* Remove all proc entries. */
- debugfs_remove_recursive(sm_state->dir_root);
-
-@@ -1202,6 +1522,7 @@ static int bcm2835_vc_sm_cma_remove(stru
- return 0;
- }
-
-+/* Kernel API calls */
- /* Get an internal resource handle mapped from the external one. */
- int vc_sm_cma_int_handle(void *handle)
- {
-@@ -1252,7 +1573,7 @@ int vc_sm_cma_import_dmabuf(struct dma_b
- }
-
- ret = vc_sm_cma_import_dmabuf_internal(sm_state->data_knl, src_dmabuf,
-- &new_dma_buf);
-+ -1, &new_dma_buf);
-
- if (!ret) {
- pr_debug("%s: imported to ptr %p\n", __func__, new_dma_buf);
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
-@@ -92,8 +92,7 @@ int __vc_sm_cma_add_heaps(struct cma *cm
- return 0;
- }
-
--int vc_sm_cma_add_heaps(struct cma **cma_heap)
-+void vc_sm_cma_add_heaps(struct cma **cma_heap)
- {
- cma_for_each_area(__vc_sm_cma_add_heaps, cma_heap);
-- return 0;
- }
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
-@@ -34,6 +34,6 @@ int vc_sm_cma_buffer_allocate(struct cma
- unsigned long len);
- void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer);
-
--int vc_sm_cma_add_heaps(struct cma **cma_heap);
-+void vc_sm_cma_add_heaps(struct cma **cma_heap);
-
- #endif
---- /dev/null
-+++ b/include/linux/broadcom/vc_sm_cma_ioctl.h
-@@ -0,0 +1,87 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/*
-+ * Copyright 2019 Raspberry Pi (Trading) Ltd. All rights reserved.
-+ *
-+ * Based on vmcs_sm_ioctl.h Copyright Broadcom Corporation.
-+ */
-+
-+#ifndef __VC_SM_CMA_IOCTL_H
-+#define __VC_SM_CMA_IOCTL_H
-+
-+/* ---- Include Files ---------------------------------------------------- */
-+
-+#if defined(__KERNEL__)
-+#include <linux/types.h> /* Needed for standard types */
-+#else
-+#include <stdint.h>
-+#endif
-+
-+#include <linux/ioctl.h>
-+
-+/* ---- Constants and Types ---------------------------------------------- */
-+
-+#define VC_SM_CMA_RESOURCE_NAME 32
-+#define VC_SM_CMA_RESOURCE_NAME_DEFAULT "sm-host-resource"
-+
-+/* Type define used to create unique IOCTL number */
-+#define VC_SM_CMA_MAGIC_TYPE 'J'
-+
-+/* IOCTL commands on /dev/vc-sm-cma */
-+enum vc_sm_cma_cmd_e {
-+ VC_SM_CMA_CMD_ALLOC = 0x5A, /* Start at 0x5A arbitrarily */
-+
-+ VC_SM_CMA_CMD_IMPORT_DMABUF,
-+
-+ VC_SM_CMA_CMD_LAST /* Do not delete */
-+};
-+
-+/* Cache type supported, conveniently matches the user space definition in
-+ * user-vcsm.h.
-+ */
-+enum vc_sm_cma_cache_e {
-+ VC_SM_CMA_CACHE_NONE,
-+ VC_SM_CMA_CACHE_HOST,
-+ VC_SM_CMA_CACHE_VC,
-+ VC_SM_CMA_CACHE_BOTH,
-+};
-+
-+/* IOCTL Data structures */
-+struct vc_sm_cma_ioctl_alloc {
-+ /* user -> kernel */
-+ __u32 size;
-+ __u32 num;
-+ __u32 cached; /* enum vc_sm_cma_cache_e */
-+ __u32 pad;
-+ __u8 name[VC_SM_CMA_RESOURCE_NAME];
-+
-+ /* kernel -> user */
-+ __s32 handle;
-+ __u32 vc_handle;
-+ __u64 dma_addr;
-+};
-+
-+struct vc_sm_cma_ioctl_import_dmabuf {
-+ /* user -> kernel */
-+ __s32 dmabuf_fd;
-+ __u32 cached; /* enum vc_sm_cma_cache_e */
-+ __u8 name[VC_SM_CMA_RESOURCE_NAME];
-+
-+ /* kernel -> user */
-+ __s32 handle;
-+ __u32 vc_handle;
-+ __u32 size;
-+ __u32 pad;
-+ __u64 dma_addr;
-+};
-+
-+/* IOCTL numbers */
-+#define VC_SM_CMA_IOCTL_MEM_ALLOC\
-+ _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_ALLOC,\
-+ struct vc_sm_cma_ioctl_alloc)
-+
-+#define VC_SM_CMA_IOCTL_MEM_IMPORT_DMABUF\
-+ _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_IMPORT_DMABUF,\
-+ struct vc_sm_cma_ioctl_import_dmabuf)
-+
-+#endif /* __VC_SM_CMA_IOCTL_H */
--- /dev/null
+From 69e50a6fc060432f4d7802d116a4086e3a0df600 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 22 May 2019 15:40:37 +0100
+Subject: [PATCH 632/725] staging: vcsm-cma: Fixup the alloc code handling of
+ kernel_id
+
+The allocation code had been copied in from an old branch prior
+to having added the IDR for 64bit support. It was therefore pushing
+a pointer into the kernel_id field instead of an IDR handle, the
+lookup therefore failed, and we never released the buffer.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -1206,7 +1206,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+
+ import.addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
+ import.size = aligned_size;
+- import.kernel_id = (uint32_t)buffer;
++ import.kernel_id = get_kernel_id(buffer);
+
+ /* Wrap it into a videocore buffer. */
+ status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
+@@ -1231,6 +1231,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+ buffer->size = import.size;
+ buffer->dma_addr = import.addr;
+ buffer->vpu_state = VPU_MAPPED;
++ buffer->kernel_id = import.kernel_id;
+ //buffer->res_cached = ioparam->cached;
+
+ fd = dma_buf_fd(dmabuf, O_CLOEXEC);
--- /dev/null
+From bc982ce2b2d37e03cb023a66b932301bcb6b3e78 Mon Sep 17 00:00:00 2001
+From: James Hughes <james.hughes@raspberrypi.org>
+Date: Thu, 14 Mar 2019 13:27:54 +0000
+Subject: [PATCH 633/725] Pulled in the multi frame buffer support from the Pi3
+ repo
+
+---
+ drivers/video/fbdev/bcm2708_fb.c | 580 +++++++++++++++------
+ include/soc/bcm2835/raspberrypi-firmware.h | 4 +
+ 2 files changed, 432 insertions(+), 152 deletions(-)
+
+--- a/drivers/video/fbdev/bcm2708_fb.c
++++ b/drivers/video/fbdev/bcm2708_fb.c
+@@ -2,6 +2,7 @@
+ * linux/drivers/video/bcm2708_fb.c
+ *
+ * Copyright (C) 2010 Broadcom
++ * Copyright (C) 2018 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
+@@ -13,6 +14,7 @@
+ * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
+ *
+ */
++
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+@@ -36,6 +38,7 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/cred.h>
+ #include <soc/bcm2835/raspberrypi-firmware.h>
++#include <linux/mutex.h>
+
+ //#define BCM2708_FB_DEBUG
+ #define MODULE_NAME "bcm2708_fb"
+@@ -82,62 +85,139 @@ struct bcm2708_fb_stats {
+ u32 dma_irqs;
+ };
+
++struct vc4_display_settings_t {
++ u32 display_num;
++ u32 width;
++ u32 height;
++ u32 pitch;
++ u32 depth;
++ u32 virtual_width;
++ u32 virtual_height;
++ u32 virtual_width_offset;
++ u32 virtual_height_offset;
++ unsigned long fb_bus_address;
++};
++
++struct bcm2708_fb_dev;
++
+ struct bcm2708_fb {
+ struct fb_info fb;
+ struct platform_device *dev;
+- struct rpi_firmware *fw;
+ u32 cmap[16];
+ u32 gpu_cmap[256];
++ struct dentry *debugfs_dir;
++ struct dentry *debugfs_subdir;
++ unsigned long fb_bus_address;
++ struct { u32 base, length; } gpu;
++ struct vc4_display_settings_t display_settings;
++ struct debugfs_regset32 screeninfo_regset;
++ struct bcm2708_fb_dev *fbdev;
++ unsigned int image_size;
++ dma_addr_t dma_addr;
++ void *cpuaddr;
++};
++
++#define MAX_FRAMEBUFFERS 3
++
++struct bcm2708_fb_dev {
++ int firmware_supports_multifb;
++ /* Protects the DMA system from multiple FB access */
++ struct mutex dma_mutex;
+ int dma_chan;
+ int dma_irq;
+ void __iomem *dma_chan_base;
+- void *cb_base; /* DMA control blocks */
+- dma_addr_t cb_handle;
+- struct dentry *debugfs_dir;
+ wait_queue_head_t dma_waitq;
+- struct bcm2708_fb_stats stats;
+- unsigned long fb_bus_address;
+- struct { u32 base, length; } gpu;
++ bool disable_arm_alloc;
++ struct bcm2708_fb_stats dma_stats;
++ void *cb_base; /* DMA control blocks */
++ dma_addr_t cb_handle;
++ int instance_count;
++ int num_displays;
++ struct rpi_firmware *fw;
++ struct bcm2708_fb displays[MAX_FRAMEBUFFERS];
+ };
+
+ #define to_bcm2708(info) container_of(info, struct bcm2708_fb, fb)
+
+ static void bcm2708_fb_debugfs_deinit(struct bcm2708_fb *fb)
+ {
+- debugfs_remove_recursive(fb->debugfs_dir);
+- fb->debugfs_dir = NULL;
++ debugfs_remove_recursive(fb->debugfs_subdir);
++ fb->debugfs_subdir = NULL;
++
++ fb->fbdev->instance_count--;
++
++ if (!fb->fbdev->instance_count) {
++ debugfs_remove_recursive(fb->debugfs_dir);
++ fb->debugfs_dir = NULL;
++ }
+ }
+
+ static int bcm2708_fb_debugfs_init(struct bcm2708_fb *fb)
+ {
++ char buf[3];
++ struct bcm2708_fb_dev *fbdev = fb->fbdev;
++
+ static struct debugfs_reg32 stats_registers[] = {
+- {
+- "dma_copies",
+- offsetof(struct bcm2708_fb_stats, dma_copies)
+- },
+- {
+- "dma_irqs",
+- offsetof(struct bcm2708_fb_stats, dma_irqs)
+- },
++ {"dma_copies", offsetof(struct bcm2708_fb_stats, dma_copies)},
++ {"dma_irqs", offsetof(struct bcm2708_fb_stats, dma_irqs)},
+ };
+
+- fb->debugfs_dir = debugfs_create_dir(DRIVER_NAME, NULL);
++ static struct debugfs_reg32 screeninfo[] = {
++ {"width", offsetof(struct fb_var_screeninfo, xres)},
++ {"height", offsetof(struct fb_var_screeninfo, yres)},
++ {"bpp", offsetof(struct fb_var_screeninfo, bits_per_pixel)},
++ {"xres_virtual", offsetof(struct fb_var_screeninfo, xres_virtual)},
++ {"yres_virtual", offsetof(struct fb_var_screeninfo, yres_virtual)},
++ {"xoffset", offsetof(struct fb_var_screeninfo, xoffset)},
++ {"yoffset", offsetof(struct fb_var_screeninfo, yoffset)},
++ };
++
++ fb->debugfs_dir = debugfs_lookup(DRIVER_NAME, NULL);
++
++ if (!fb->debugfs_dir)
++ fb->debugfs_dir = debugfs_create_dir(DRIVER_NAME, NULL);
++
+ if (!fb->debugfs_dir) {
+- pr_warn("%s: could not create debugfs entry\n",
+- __func__);
++ dev_warn(fb->fb.dev, "%s: could not create debugfs folder\n",
++ __func__);
++ return -EFAULT;
++ }
++
++ snprintf(buf, sizeof(buf), "%u", fb->display_settings.display_num);
++
++ fb->debugfs_subdir = debugfs_create_dir(buf, fb->debugfs_dir);
++
++ if (!fb->debugfs_subdir) {
++ dev_warn(fb->fb.dev, "%s: could not create debugfs entry %u\n",
++ __func__, fb->display_settings.display_num);
+ return -EFAULT;
+ }
+
+- fb->stats.regset.regs = stats_registers;
+- fb->stats.regset.nregs = ARRAY_SIZE(stats_registers);
+- fb->stats.regset.base = &fb->stats;
+-
+- if (!debugfs_create_regset32("stats", 0444, fb->debugfs_dir,
+- &fb->stats.regset)) {
+- pr_warn("%s: could not create statistics registers\n",
+- __func__);
++ fbdev->dma_stats.regset.regs = stats_registers;
++ fbdev->dma_stats.regset.nregs = ARRAY_SIZE(stats_registers);
++ fbdev->dma_stats.regset.base = &fbdev->dma_stats;
++
++ if (!debugfs_create_regset32("dma_stats", 0444, fb->debugfs_subdir,
++ &fbdev->dma_stats.regset)) {
++ dev_warn(fb->fb.dev, "%s: could not create statistics registers\n",
++ __func__);
++ goto fail;
++ }
++
++ fb->screeninfo_regset.regs = screeninfo;
++ fb->screeninfo_regset.nregs = ARRAY_SIZE(screeninfo);
++ fb->screeninfo_regset.base = &fb->fb.var;
++
++ if (!debugfs_create_regset32("screeninfo", 0444, fb->debugfs_subdir,
++ &fb->screeninfo_regset)) {
++ dev_warn(fb->fb.dev,
++ "%s: could not create dimensions registers\n",
++ __func__);
+ goto fail;
+ }
++
++ fbdev->instance_count++;
++
+ return 0;
+
+ fail:
+@@ -145,6 +225,20 @@ fail:
+ return -EFAULT;
+ }
+
++static void set_display_num(struct bcm2708_fb *fb)
++{
++ if (fb && fb->fbdev && fb->fbdev->firmware_supports_multifb) {
++ u32 tmp = fb->display_settings.display_num;
++
++ if (rpi_firmware_property(fb->fbdev->fw,
++ RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM,
++ &tmp,
++ sizeof(tmp)))
++ dev_warn_once(fb->fb.dev,
++ "Set display number call failed. Old GPU firmware?");
++ }
++}
++
+ static int bcm2708_fb_set_bitfields(struct fb_var_screeninfo *var)
+ {
+ int ret = 0;
+@@ -222,11 +316,11 @@ static int bcm2708_fb_check_var(struct f
+ struct fb_info *info)
+ {
+ /* info input, var output */
+- print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n",
++ print_debug("%s(%p) %ux%u (%ux%u), %ul, %u\n",
+ __func__, info, info->var.xres, info->var.yres,
+ info->var.xres_virtual, info->var.yres_virtual,
+- (int)info->screen_size, info->var.bits_per_pixel);
+- print_debug("%s(%p) %dx%d (%dx%d), %d\n", __func__, var, var->xres,
++ info->screen_size, info->var.bits_per_pixel);
++ print_debug("%s(%p) %ux%u (%ux%u), %u\n", __func__, var, var->xres,
+ var->yres, var->xres_virtual, var->yres_virtual,
+ var->bits_per_pixel);
+
+@@ -283,23 +377,96 @@ static int bcm2708_fb_set_par(struct fb_
+ .xoffset = info->var.xoffset,
+ .yoffset = info->var.yoffset,
+ .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
+- .base = 0,
+- .screen_size = 0,
+- .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
+- .pitch = 0,
++ /* base and screen_size will be initialised later */
++ .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
++ /* pitch will be initialised later */
+ };
+- int ret;
++ int ret, image_size;
++
+
+- print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
++ print_debug("%s(%p) %dx%d (%dx%d), %d, %d (display %d)\n", __func__,
++ info,
+ info->var.xres, info->var.yres, info->var.xres_virtual,
+ info->var.yres_virtual, (int)info->screen_size,
+- info->var.bits_per_pixel);
++ info->var.bits_per_pixel, value);
++
++ /* Need to set the display number to act on first
++ * Cannot do it in the tag list because on older firmware the call
++ * will fail and stop the rest of the list being executed.
++ * We can ignore this call failing as the default at other end is 0
++ */
++ set_display_num(fb);
++
++ /* Try allocating our own buffer. We can specify all the parameters */
++ image_size = ((info->var.xres * info->var.yres) *
++ info->var.bits_per_pixel) >> 3;
++
++ if (!fb->fbdev->disable_arm_alloc &&
++ (image_size != fb->image_size || !fb->dma_addr)) {
++ if (fb->dma_addr) {
++ dma_free_coherent(info->device, fb->image_size,
++ fb->cpuaddr, fb->dma_addr);
++ fb->image_size = 0;
++ fb->cpuaddr = NULL;
++ fb->dma_addr = 0;
++ }
++
++ fb->cpuaddr = dma_alloc_coherent(info->device, image_size,
++ &fb->dma_addr, GFP_KERNEL);
++
++ if (!fb->cpuaddr) {
++ fb->dma_addr = 0;
++ fb->fbdev->disable_arm_alloc = true;
++ } else {
++ fb->image_size = image_size;
++ }
++ }
++
++ if (fb->cpuaddr) {
++ fbinfo.base = fb->dma_addr;
++ fbinfo.screen_size = image_size;
++ fbinfo.pitch = (info->var.xres * info->var.bits_per_pixel) >> 3;
++
++ ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
++ sizeof(fbinfo));
++ if (ret || fbinfo.base != fb->dma_addr) {
++ /* Firmware either failed, or assigned a different base
++ * address (ie it doesn't support being passed an FB
++ * allocation).
++ * Destroy the allocation, and don't try again.
++ */
++ dma_free_coherent(info->device, fb->image_size,
++ fb->cpuaddr, fb->dma_addr);
++ fb->image_size = 0;
++ fb->cpuaddr = NULL;
++ fb->dma_addr = 0;
++ fb->fbdev->disable_arm_alloc = true;
++ }
++ } else {
++ /* Our allocation failed - drop into the old scheme of
++ * allocation by the VPU.
++ */
++ ret = -ENOMEM;
++ }
+
+- ret = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo));
+ if (ret) {
+- dev_err(info->device,
+- "Failed to allocate GPU framebuffer (%d)\n", ret);
+- return ret;
++ /* Old scheme:
++ * - FRAMEBUFFER_ALLOCATE passes 0 for base and screen_size.
++ * - GET_PITCH instead of SET_PITCH.
++ */
++ fbinfo.base = 0;
++ fbinfo.screen_size = 0;
++ fbinfo.tag6.tag = RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH;
++ fbinfo.pitch = 0;
++
++ ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
++ sizeof(fbinfo));
++ if (ret) {
++ dev_err(info->device,
++ "Failed to allocate GPU framebuffer (%d)\n",
++ ret);
++ return ret;
++ }
+ }
+
+ if (info->var.bits_per_pixel <= 8)
+@@ -314,9 +481,17 @@ static int bcm2708_fb_set_par(struct fb_
+ fb->fb.fix.smem_start = fbinfo.base;
+ fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual;
+ fb->fb.screen_size = fbinfo.screen_size;
+- if (fb->fb.screen_base)
+- iounmap(fb->fb.screen_base);
+- fb->fb.screen_base = ioremap_wc(fbinfo.base, fb->fb.screen_size);
++
++ if (!fb->dma_addr) {
++ if (fb->fb.screen_base)
++ iounmap(fb->fb.screen_base);
++
++ fb->fb.screen_base = ioremap_wc(fbinfo.base,
++ fb->fb.screen_size);
++ } else {
++ fb->fb.screen_base = fb->cpuaddr;
++ }
++
+ if (!fb->fb.screen_base) {
+ /* the console may currently be locked */
+ console_trylock();
+@@ -374,7 +549,10 @@ static int bcm2708_fb_setcolreg(unsigned
+ packet->length = regno + 1;
+ memcpy(packet->cmap, fb->gpu_cmap,
+ sizeof(packet->cmap));
+- ret = rpi_firmware_property(fb->fw,
++
++ set_display_num(fb);
++
++ ret = rpi_firmware_property(fb->fbdev->fw,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE,
+ packet,
+ (2 + packet->length) * sizeof(u32));
+@@ -413,8 +591,11 @@ static int bcm2708_fb_blank(int blank_mo
+ return -EINVAL;
+ }
+
+- ret = rpi_firmware_property(fb->fw, RPI_FIRMWARE_FRAMEBUFFER_BLANK,
++ set_display_num(fb);
++
++ ret = rpi_firmware_property(fb->fbdev->fw, RPI_FIRMWARE_FRAMEBUFFER_BLANK,
+ &value, sizeof(value));
++
+ if (ret)
+ dev_err(info->device, "%s(%d) failed: %d\n", __func__,
+ blank_mode, ret);
+@@ -431,7 +612,7 @@ static int bcm2708_fb_pan_display(struct
+ info->var.yoffset = var->yoffset;
+ result = bcm2708_fb_set_par(info);
+ if (result != 0)
+- pr_err("%s(%d,%d) returns=%d\n", __func__, var->xoffset,
++ pr_err("%s(%u,%u) returns=%d\n", __func__, var->xoffset,
+ var->yoffset, result);
+ return result;
+ }
+@@ -439,8 +620,9 @@ static int bcm2708_fb_pan_display(struct
+ static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src,
+ int size)
+ {
+- int burst_size = (fb->dma_chan == 0) ? 8 : 2;
+- struct bcm2708_dma_cb *cb = fb->cb_base;
++ struct bcm2708_fb_dev *fbdev = fb->fbdev;
++ struct bcm2708_dma_cb *cb = fbdev->cb_base;
++ int burst_size = (fbdev->dma_chan == 0) ? 8 : 2;
+
+ cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH |
+ BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH |
+@@ -453,21 +635,27 @@ static void dma_memcpy(struct bcm2708_fb
+ cb->pad[1] = 0;
+ cb->next = 0;
+
++ // Not sure what to do if this gets a signal whilst waiting
++ if (mutex_lock_interruptible(&fbdev->dma_mutex))
++ return;
++
+ if (size < dma_busy_wait_threshold) {
+- bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
+- bcm_dma_wait_idle(fb->dma_chan_base);
++ bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
++ bcm_dma_wait_idle(fbdev->dma_chan_base);
+ } else {
+- void __iomem *dma_chan = fb->dma_chan_base;
++ void __iomem *local_dma_chan = fbdev->dma_chan_base;
+
+ cb->info |= BCM2708_DMA_INT_EN;
+- bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
+- while (bcm_dma_is_busy(dma_chan)) {
+- wait_event_interruptible(fb->dma_waitq,
+- !bcm_dma_is_busy(dma_chan));
++ bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
++ while (bcm_dma_is_busy(local_dma_chan)) {
++ wait_event_interruptible(fbdev->dma_waitq,
++ !bcm_dma_is_busy(local_dma_chan));
+ }
+- fb->stats.dma_irqs++;
++ fbdev->dma_stats.dma_irqs++;
+ }
+- fb->stats.dma_copies++;
++ fbdev->dma_stats.dma_copies++;
++
++ mutex_unlock(&fbdev->dma_mutex);
+ }
+
+ /* address with no aliases */
+@@ -542,10 +730,13 @@ static int bcm2708_ioctl(struct fb_info
+
+ switch (cmd) {
+ case FBIO_WAITFORVSYNC:
+- ret = rpi_firmware_property(fb->fw,
++ set_display_num(fb);
++
++ ret = rpi_firmware_property(fb->fbdev->fw,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC,
+ &dummy, sizeof(dummy));
+ break;
++
+ case FBIODMACOPY:
+ {
+ struct fb_dmacopy ioparam;
+@@ -615,23 +806,22 @@ static int bcm2708_compat_ioctl(struct f
+ static void bcm2708_fb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect)
+ {
+- /* (is called) print_debug("bcm2708_fb_fillrect\n"); */
+ cfb_fillrect(info, rect);
+ }
+
+ /* A helper function for configuring dma control block */
+ static void set_dma_cb(struct bcm2708_dma_cb *cb,
+- int burst_size,
+- dma_addr_t dst,
+- int dst_stride,
+- dma_addr_t src,
+- int src_stride,
+- int w,
+- int h)
++ int burst_size,
++ dma_addr_t dst,
++ int dst_stride,
++ dma_addr_t src,
++ int src_stride,
++ int w,
++ int h)
+ {
+ cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH |
+- BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH |
+- BCM2708_DMA_D_INC | BCM2708_DMA_TDMODE;
++ BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH |
++ BCM2708_DMA_D_INC | BCM2708_DMA_TDMODE;
+ cb->dst = dst;
+ cb->src = src;
+ /*
+@@ -649,15 +839,19 @@ static void bcm2708_fb_copyarea(struct f
+ const struct fb_copyarea *region)
+ {
+ struct bcm2708_fb *fb = to_bcm2708(info);
+- struct bcm2708_dma_cb *cb = fb->cb_base;
++ struct bcm2708_fb_dev *fbdev = fb->fbdev;
++ struct bcm2708_dma_cb *cb = fbdev->cb_base;
+ int bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
+
+ /* Channel 0 supports larger bursts and is a bit faster */
+- int burst_size = (fb->dma_chan == 0) ? 8 : 2;
++ int burst_size = (fbdev->dma_chan == 0) ? 8 : 2;
+ int pixels = region->width * region->height;
+
+- /* Fallback to cfb_copyarea() if we don't like something */
+- if (bytes_per_pixel > 4 ||
++ /* If DMA is currently in use (ie being used on another FB), then
++ * rather than wait for it to finish, just use the cfb_copyarea
++ */
++ if (!mutex_trylock(&fbdev->dma_mutex) ||
++ bytes_per_pixel > 4 ||
+ info->var.xres * info->var.yres > 1920 * 1200 ||
+ region->width <= 0 || region->width > info->var.xres ||
+ region->height <= 0 || region->height > info->var.yres ||
+@@ -684,8 +878,8 @@ static void bcm2708_fb_copyarea(struct f
+ * 1920x1200 resolution at 32bpp pixel depth.
+ */
+ int y;
+- dma_addr_t control_block_pa = fb->cb_handle;
+- dma_addr_t scratchbuf = fb->cb_handle + 16 * 1024;
++ dma_addr_t control_block_pa = fbdev->cb_handle;
++ dma_addr_t scratchbuf = fbdev->cb_handle + 16 * 1024;
+ int scanline_size = bytes_per_pixel * region->width;
+ int scanlines_per_cb = (64 * 1024 - 16 * 1024) / scanline_size;
+
+@@ -735,10 +929,10 @@ static void bcm2708_fb_copyarea(struct f
+ }
+ set_dma_cb(cb, burst_size,
+ fb->fb_bus_address + dy * fb->fb.fix.line_length +
+- bytes_per_pixel * region->dx,
++ bytes_per_pixel * region->dx,
+ stride,
+ fb->fb_bus_address + sy * fb->fb.fix.line_length +
+- bytes_per_pixel * region->sx,
++ bytes_per_pixel * region->sx,
+ stride,
+ region->width * bytes_per_pixel,
+ region->height);
+@@ -748,32 +942,33 @@ static void bcm2708_fb_copyarea(struct f
+ cb->next = 0;
+
+ if (pixels < dma_busy_wait_threshold) {
+- bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
+- bcm_dma_wait_idle(fb->dma_chan_base);
++ bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
++ bcm_dma_wait_idle(fbdev->dma_chan_base);
+ } else {
+- void __iomem *dma_chan = fb->dma_chan_base;
++ void __iomem *local_dma_chan = fbdev->dma_chan_base;
+
+ cb->info |= BCM2708_DMA_INT_EN;
+- bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
+- while (bcm_dma_is_busy(dma_chan)) {
+- wait_event_interruptible(fb->dma_waitq,
+- !bcm_dma_is_busy(dma_chan));
++ bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
++ while (bcm_dma_is_busy(local_dma_chan)) {
++ wait_event_interruptible(fbdev->dma_waitq,
++ !bcm_dma_is_busy(local_dma_chan));
+ }
+- fb->stats.dma_irqs++;
++ fbdev->dma_stats.dma_irqs++;
+ }
+- fb->stats.dma_copies++;
++ fbdev->dma_stats.dma_copies++;
++
++ mutex_unlock(&fbdev->dma_mutex);
+ }
+
+ static void bcm2708_fb_imageblit(struct fb_info *info,
+ const struct fb_image *image)
+ {
+- /* (is called) print_debug("bcm2708_fb_imageblit\n"); */
+ cfb_imageblit(info, image);
+ }
+
+ static irqreturn_t bcm2708_fb_dma_irq(int irq, void *cxt)
+ {
+- struct bcm2708_fb *fb = cxt;
++ struct bcm2708_fb_dev *fbdev = cxt;
+
+ /* FIXME: should read status register to check if this is
+ * actually interrupting us or not, in case this interrupt
+@@ -783,9 +978,9 @@ static irqreturn_t bcm2708_fb_dma_irq(in
+ */
+
+ /* acknowledge the interrupt */
+- writel(BCM2708_DMA_INT, fb->dma_chan_base + BCM2708_DMA_CS);
++ writel(BCM2708_DMA_INT, fbdev->dma_chan_base + BCM2708_DMA_CS);
+
+- wake_up(&fb->dma_waitq);
++ wake_up(&fbdev->dma_waitq);
+ return IRQ_HANDLED;
+ }
+
+@@ -821,11 +1016,23 @@ static int bcm2708_fb_register(struct bc
+ fb->fb.fix.ywrapstep = 0;
+ fb->fb.fix.accel = FB_ACCEL_NONE;
+
+- fb->fb.var.xres = fbwidth;
+- fb->fb.var.yres = fbheight;
+- fb->fb.var.xres_virtual = fbwidth;
+- fb->fb.var.yres_virtual = fbheight;
+- fb->fb.var.bits_per_pixel = fbdepth;
++ /* If we have data from the VC4 on FB's, use that, otherwise use the
++ * module parameters
++ */
++ if (fb->display_settings.width) {
++ fb->fb.var.xres = fb->display_settings.width;
++ fb->fb.var.yres = fb->display_settings.height;
++ fb->fb.var.xres_virtual = fb->fb.var.xres;
++ fb->fb.var.yres_virtual = fb->fb.var.yres;
++ fb->fb.var.bits_per_pixel = fb->display_settings.depth;
++ } else {
++ fb->fb.var.xres = fbwidth;
++ fb->fb.var.yres = fbheight;
++ fb->fb.var.xres_virtual = fbwidth;
++ fb->fb.var.yres_virtual = fbheight;
++ fb->fb.var.bits_per_pixel = fbdepth;
++ }
++
+ fb->fb.var.vmode = FB_VMODE_NONINTERLACED;
+ fb->fb.var.activate = FB_ACTIVATE_NOW;
+ fb->fb.var.nonstd = 0;
+@@ -841,26 +1048,23 @@ static int bcm2708_fb_register(struct bc
+ fb->fb.monspecs.dclkmax = 100000000;
+
+ bcm2708_fb_set_bitfields(&fb->fb.var);
+- init_waitqueue_head(&fb->dma_waitq);
+
+ /*
+ * Allocate colourmap.
+ */
+-
+ fb_set_var(&fb->fb, &fb->fb.var);
++
+ ret = bcm2708_fb_set_par(&fb->fb);
++
+ if (ret)
+ return ret;
+
+- print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n",
+- fbwidth, fbheight, fbdepth, fbswap);
+-
+ ret = register_framebuffer(&fb->fb);
+- print_debug("BCM2708FB: register framebuffer (%d)\n", ret);
++
+ if (ret == 0)
+ goto out;
+
+- print_debug("BCM2708FB: cannot register framebuffer (%d)\n", ret);
++ dev_warn(fb->fb.dev, "Unable to register framebuffer (%d)\n", ret);
+ out:
+ return ret;
+ }
+@@ -869,10 +1073,18 @@ static int bcm2708_fb_probe(struct platf
+ {
+ struct device_node *fw_np;
+ struct rpi_firmware *fw;
+- struct bcm2708_fb *fb;
+- int ret;
++ int ret, i;
++ u32 num_displays;
++ struct bcm2708_fb_dev *fbdev;
++ struct { u32 base, length; } gpu_mem;
++
++ fbdev = devm_kzalloc(&dev->dev, sizeof(*fbdev), GFP_KERNEL);
++
++ if (!fbdev)
++ return -ENOMEM;
+
+ fw_np = of_parse_phandle(dev->dev.of_node, "firmware", 0);
++
+ /* Remove comment when booting without Device Tree is no longer supported
+ * if (!fw_np) {
+ * dev_err(&dev->dev, "Missing firmware node\n");
+@@ -880,90 +1092,154 @@ static int bcm2708_fb_probe(struct platf
+ * }
+ */
+ fw = rpi_firmware_get(fw_np);
++ fbdev->fw = fw;
++
+ if (!fw)
+ return -EPROBE_DEFER;
+
+- fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+- if (!fb) {
+- ret = -ENOMEM;
+- goto free_region;
++ ret = rpi_firmware_property(fw,
++ RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
++ &num_displays, sizeof(u32));
++
++ /* If we fail to get the number of displays, or it returns 0, then
++ * assume old firmware that doesn't have the mailbox call, so just
++ * set one display
++ */
++ if (ret || num_displays == 0) {
++ num_displays = 1;
++ dev_err(&dev->dev,
++ "Unable to determine number of FB's. Assuming 1\n");
++ ret = 0;
++ } else {
++ fbdev->firmware_supports_multifb = 1;
+ }
+
+- fb->fw = fw;
+- bcm2708_fb_debugfs_init(fb);
++ if (num_displays > MAX_FRAMEBUFFERS) {
++ dev_warn(&dev->dev,
++ "More displays reported from firmware than supported in driver (%u vs %u)",
++ num_displays, MAX_FRAMEBUFFERS);
++ num_displays = MAX_FRAMEBUFFERS;
++ }
+
+- fb->cb_base = dma_alloc_writecombine(&dev->dev, SZ_64K,
+- &fb->cb_handle, GFP_KERNEL);
+- if (!fb->cb_base) {
++ dev_info(&dev->dev, "FB found %d display(s)\n", num_displays);
++
++ /* Set up the DMA information. Note we have just one set of DMA
++ * parameters to work with all the FB's so requires synchronising when
++ * being used
++ */
++
++ mutex_init(&fbdev->dma_mutex);
++
++ fbdev->cb_base = dma_alloc_writecombine(&dev->dev, SZ_64K,
++ &fbdev->cb_handle,
++ GFP_KERNEL);
++ if (!fbdev->cb_base) {
+ dev_err(&dev->dev, "cannot allocate DMA CBs\n");
+ ret = -ENOMEM;
+ goto free_fb;
+ }
+
+- pr_info("BCM2708FB: allocated DMA memory %pad\n", &fb->cb_handle);
+-
+ ret = bcm_dma_chan_alloc(BCM_DMA_FEATURE_BULK,
+- &fb->dma_chan_base, &fb->dma_irq);
++ &fbdev->dma_chan_base,
++ &fbdev->dma_irq);
+ if (ret < 0) {
+- dev_err(&dev->dev, "couldn't allocate a DMA channel\n");
++ dev_err(&dev->dev, "Couldn't allocate a DMA channel\n");
+ goto free_cb;
+ }
+- fb->dma_chan = ret;
++ fbdev->dma_chan = ret;
+
+- ret = request_irq(fb->dma_irq, bcm2708_fb_dma_irq,
+- 0, "bcm2708_fb dma", fb);
++ ret = request_irq(fbdev->dma_irq, bcm2708_fb_dma_irq,
++ 0, "bcm2708_fb DMA", fbdev);
+ if (ret) {
+- pr_err("%s: failed to request DMA irq\n", __func__);
++ dev_err(&dev->dev,
++ "Failed to request DMA irq\n");
+ goto free_dma_chan;
+ }
+
+- pr_info("BCM2708FB: allocated DMA channel %d\n", fb->dma_chan);
++ rpi_firmware_property(fbdev->fw,
++ RPI_FIRMWARE_GET_VC_MEMORY,
++ &gpu_mem, sizeof(gpu_mem));
++
++ for (i = 0; i < num_displays; i++) {
++ struct bcm2708_fb *fb = &fbdev->displays[i];
++
++ fb->display_settings.display_num = i;
++ fb->dev = dev;
++ fb->fb.device = &dev->dev;
++ fb->fbdev = fbdev;
++
++ fb->gpu.base = gpu_mem.base;
++ fb->gpu.length = gpu_mem.length;
++
++ if (fbdev->firmware_supports_multifb) {
++ ret = rpi_firmware_property(fw,
++ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS,
++ &fb->display_settings,
++ GET_DISPLAY_SETTINGS_PAYLOAD_SIZE);
++ } else {
++ memset(&fb->display_settings, 0,
++ sizeof(fb->display_settings));
++ }
++
++ ret = bcm2708_fb_register(fb);
+
+- fb->dev = dev;
+- fb->fb.device = &dev->dev;
++ if (ret == 0) {
++ bcm2708_fb_debugfs_init(fb);
+
+- /* failure here isn't fatal, but we'll fail in vc_mem_copy if
+- * fb->gpu is not valid
+- */
+- rpi_firmware_property(fb->fw, RPI_FIRMWARE_GET_VC_MEMORY, &fb->gpu,
+- sizeof(fb->gpu));
++ fbdev->num_displays++;
+
+- ret = bcm2708_fb_register(fb);
+- if (ret == 0) {
+- platform_set_drvdata(dev, fb);
+- goto out;
++ dev_info(&dev->dev,
++ "Registered framebuffer for display %u, size %ux%u\n",
++ fb->display_settings.display_num,
++ fb->fb.var.xres,
++ fb->fb.var.yres);
++ } else {
++ // Use this to flag if this FB entry is in use.
++ fb->fbdev = NULL;
++ }
++ }
++
++ // Did we actually successfully create any FB's?
++ if (fbdev->num_displays) {
++ init_waitqueue_head(&fbdev->dma_waitq);
++ platform_set_drvdata(dev, fbdev);
++ return ret;
+ }
+
+ free_dma_chan:
+- bcm_dma_chan_free(fb->dma_chan);
++ bcm_dma_chan_free(fbdev->dma_chan);
+ free_cb:
+- dma_free_writecombine(&dev->dev, SZ_64K, fb->cb_base, fb->cb_handle);
++ dma_free_writecombine(&dev->dev, SZ_64K, fbdev->cb_base,
++ fbdev->cb_handle);
+ free_fb:
+- kfree(fb);
+-free_region:
+ dev_err(&dev->dev, "probe failed, err %d\n", ret);
+-out:
++
+ return ret;
+ }
+
+ static int bcm2708_fb_remove(struct platform_device *dev)
+ {
+- struct bcm2708_fb *fb = platform_get_drvdata(dev);
++ struct bcm2708_fb_dev *fbdev = platform_get_drvdata(dev);
++ int i;
+
+ platform_set_drvdata(dev, NULL);
+
+- if (fb->fb.screen_base)
+- iounmap(fb->fb.screen_base);
+- unregister_framebuffer(&fb->fb);
+-
+- dma_free_writecombine(&dev->dev, SZ_64K, fb->cb_base, fb->cb_handle);
+- bcm_dma_chan_free(fb->dma_chan);
+-
+- bcm2708_fb_debugfs_deinit(fb);
++ for (i = 0; i < fbdev->num_displays; i++) {
++ if (fbdev->displays[i].fb.screen_base)
++ iounmap(fbdev->displays[i].fb.screen_base);
++
++ if (fbdev->displays[i].fbdev) {
++ unregister_framebuffer(&fbdev->displays[i].fb);
++ bcm2708_fb_debugfs_deinit(&fbdev->displays[i]);
++ }
++ }
+
+- free_irq(fb->dma_irq, fb);
++ dma_free_writecombine(&dev->dev, SZ_64K, fbdev->cb_base,
++ fbdev->cb_handle);
++ bcm_dma_chan_free(fbdev->dma_chan);
++ free_irq(fbdev->dma_irq, fbdev);
+
+- kfree(fb);
++ mutex_destroy(&fbdev->dma_mutex);
+
+ return 0;
+ }
+@@ -978,10 +1254,10 @@ static struct platform_driver bcm2708_fb
+ .probe = bcm2708_fb_probe,
+ .remove = bcm2708_fb_remove,
+ .driver = {
+- .name = DRIVER_NAME,
+- .owner = THIS_MODULE,
+- .of_match_table = bcm2708_fb_of_match_table,
+- },
++ .name = DRIVER_NAME,
++ .owner = THIS_MODULE,
++ .of_match_table = bcm2708_fb_of_match_table,
++ },
+ };
+
+ static int __init bcm2708_fb_init(void)
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -138,9 +138,11 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
++ RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH = 0x00048008,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
++
+ RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
+@@ -159,6 +161,8 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,
+ };
+
++#define GET_DISPLAY_SETTINGS_PAYLOAD_SIZE 64
++
+ #if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE)
+ int rpi_firmware_property(struct rpi_firmware *fw,
+ u32 tag, void *data, size_t len);
+++ /dev/null
-From 8859e85097f9e1bbc86b8818e24abc3c36c45b15 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 20 Mar 2019 10:40:00 +0000
-Subject: [PATCH 633/703] staging: vcsm-cma: Add cache control ioctls
-
-The old driver allowed for direct cache manipulation and that
-was used by various clients. Replicate here.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vc-sm-cma/vc_sm.c | 141 +++++++++++++++++-
- include/linux/broadcom/vc_sm_cma_ioctl.h | 27 ++++
- 2 files changed, 165 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -46,6 +46,7 @@
- #include <linux/seq_file.h>
- #include <linux/syscalls.h>
- #include <linux/types.h>
-+#include <asm/cacheflush.h>
-
- #include "vchiq_connected.h"
- #include "vc_sm_cma_vchi.h"
-@@ -1258,6 +1259,99 @@ error:
- return ret;
- }
-
-+/* Converts VCSM_CACHE_OP_* to an operating function. */
-+static void (*cache_op_to_func(const unsigned int cache_op))
-+ (const void*, const void*)
-+{
-+ switch (cache_op) {
-+ case VC_SM_CACHE_OP_NOP:
-+ return NULL;
-+
-+ case VC_SM_CACHE_OP_INV:
-+ return dmac_inv_range;
-+
-+ case VC_SM_CACHE_OP_CLEAN:
-+ return dmac_clean_range;
-+
-+ case VC_SM_CACHE_OP_FLUSH:
-+ return dmac_flush_range;
-+
-+ default:
-+ pr_err("[%s]: Invalid cache_op: 0x%08x\n", __func__, cache_op);
-+ return NULL;
-+ }
-+}
-+
-+/*
-+ * Clean/invalid/flush cache of which buffer is already pinned (i.e. accessed).
-+ */
-+static int clean_invalid_contig_2d(const void __user *addr,
-+ const size_t block_count,
-+ const size_t block_size,
-+ const size_t stride,
-+ const unsigned int cache_op)
-+{
-+ size_t i;
-+ void (*op_fn)(const void *start, const void *end);
-+
-+ if (!block_size) {
-+ pr_err("[%s]: size cannot be 0\n", __func__);
-+ return -EINVAL;
-+ }
-+
-+ op_fn = cache_op_to_func(cache_op);
-+ if (!op_fn)
-+ return -EINVAL;
-+
-+ for (i = 0; i < block_count; i ++, addr += stride)
-+ op_fn(addr, addr + block_size);
-+
-+ return 0;
-+}
-+
-+static int vc_sm_cma_clean_invalid2(unsigned int cmdnr, unsigned long arg)
-+{
-+ struct vc_sm_cma_ioctl_clean_invalid2 ioparam;
-+ struct vc_sm_cma_ioctl_clean_invalid_block *block = NULL;
-+ int i, ret = 0;
-+
-+ /* Get parameter data. */
-+ if (copy_from_user(&ioparam, (void *)arg, sizeof(ioparam))) {
-+ pr_err("[%s]: failed to copy-from-user header for cmd %x\n",
-+ __func__, cmdnr);
-+ return -EFAULT;
-+ }
-+ block = kmalloc(ioparam.op_count * sizeof(*block), GFP_KERNEL);
-+ if (!block)
-+ return -EFAULT;
-+
-+ if (copy_from_user(block, (void *)(arg + sizeof(ioparam)),
-+ ioparam.op_count * sizeof(*block)) != 0) {
-+ pr_err("[%s]: failed to copy-from-user payload for cmd %x\n",
-+ __func__, cmdnr);
-+ ret = -EFAULT;
-+ goto out;
-+ }
-+
-+ for (i = 0; i < ioparam.op_count; i++) {
-+ const struct vc_sm_cma_ioctl_clean_invalid_block * const op = block + i;
-+
-+ if (op->invalidate_mode == VC_SM_CACHE_OP_NOP)
-+ continue;
-+
-+ ret = clean_invalid_contig_2d((void __user *)op->start_address,
-+ op->block_count, op->block_size,
-+ op->inter_block_stride,
-+ op->invalidate_mode);
-+ if (ret)
-+ break;
-+ }
-+out:
-+ kfree(block);
-+
-+ return ret;
-+}
-+
- static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
- {
-@@ -1272,9 +1366,6 @@ static long vc_sm_cma_ioctl(struct file
- return -EPERM;
- }
-
-- pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
-- current->tgid, file_data->pid);
--
- /* Action is a re-post of a previously interrupted action? */
- if (file_data->restart_sys == -EINTR) {
- struct vc_sm_action_clean_t action_clean;
-@@ -1357,7 +1448,18 @@ static long vc_sm_cma_ioctl(struct file
- break;
- }
-
-+ /*
-+ * Flush/Invalidate the cache for a given mapping.
-+ * Blocks must be pinned (i.e. accessed) before this call.
-+ */
-+ case VC_SM_CMA_CMD_CLEAN_INVALID2:
-+ ret = vc_sm_cma_clean_invalid2(cmdnr, arg);
-+ break;
-+
- default:
-+ pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
-+ current->tgid, file_data->pid);
-+
- ret = -EINVAL;
- break;
- }
-@@ -1365,10 +1467,43 @@ static long vc_sm_cma_ioctl(struct file
- return ret;
- }
-
-+#ifdef CONFIG_COMPAT
-+struct vc_sm_cma_ioctl_clean_invalid2_32 {
-+ u32 op_count;
-+ struct vc_sm_cma_ioctl_clean_invalid_block {
-+ u16 invalidate_mode;
-+ u16 block_count;
-+ compat_uptr_t start_address;
-+ u32 block_size;
-+ u32 inter_block_stride;
-+ } s[0];
-+};
-+
-+#define VC_SM_CMA_CMD_CLEAN_INVALID2_32\
-+ _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
-+ struct vc_sm_cma_ioctl_clean_invalid2)
-+
-+static long vc_sm_cma_compat_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ switch (cmd) {
-+ case VC_SM_CMA_CMD_CLEAN_INVALID2_32:
-+ /* FIXME */
-+ break;
-+
-+ default:
-+ return vc_sm_cma_compat_ioctl(file, cmd, arg);
-+ }
-+}
-+#endif
-+
- /* Device operations that we managed in this driver. */
- static const struct file_operations vc_sm_ops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = vc_sm_cma_ioctl,
-+#ifdef CONFIG_COMPAT
-+ .compat_ioctl = vc_sm_cma_compat_ioctl,
-+#endif
- .open = vc_sm_cma_open,
- .release = vc_sm_cma_release,
- };
---- a/include/linux/broadcom/vc_sm_cma_ioctl.h
-+++ b/include/linux/broadcom/vc_sm_cma_ioctl.h
-@@ -33,6 +33,8 @@ enum vc_sm_cma_cmd_e {
-
- VC_SM_CMA_CMD_IMPORT_DMABUF,
-
-+ VC_SM_CMA_CMD_CLEAN_INVALID2,
-+
- VC_SM_CMA_CMD_LAST /* Do not delete */
- };
-
-@@ -75,6 +77,27 @@ struct vc_sm_cma_ioctl_import_dmabuf {
- __u64 dma_addr;
- };
-
-+/*
-+ * Cache functions to be set to struct vc_sm_cma_ioctl_clean_invalid2
-+ * invalidate_mode.
-+ */
-+#define VC_SM_CACHE_OP_NOP 0x00
-+#define VC_SM_CACHE_OP_INV 0x01
-+#define VC_SM_CACHE_OP_CLEAN 0x02
-+#define VC_SM_CACHE_OP_FLUSH 0x03
-+
-+struct vc_sm_cma_ioctl_clean_invalid2 {
-+ __u32 op_count;
-+ __u32 pad;
-+ struct vc_sm_cma_ioctl_clean_invalid_block {
-+ __u32 invalidate_mode;
-+ __u32 block_count;
-+ void * __user start_address;
-+ __u32 block_size;
-+ __u32 inter_block_stride;
-+ } s[0];
-+};
-+
- /* IOCTL numbers */
- #define VC_SM_CMA_IOCTL_MEM_ALLOC\
- _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_ALLOC,\
-@@ -84,4 +107,8 @@ struct vc_sm_cma_ioctl_import_dmabuf {
- _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_IMPORT_DMABUF,\
- struct vc_sm_cma_ioctl_import_dmabuf)
-
-+#define VC_SM_CMA_IOCTL_MEM_CLEAN_INVALID2\
-+ _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
-+ struct vc_sm_cma_ioctl_clean_invalid2)
-+
- #endif /* __VC_SM_CMA_IOCTL_H */
--- /dev/null
+From 655d142ec4bcf46f10c4e09099f9a9846e078454 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sun, 19 May 2019 12:26:21 +0200
+Subject: [PATCH 634/725] ARM: dts: bcm283x: Move BCM2835/6/7 specific to
+ bcm2835-common.dtsi
+
+We want all common BCM2835/6/7/8 functions in bcm283x.dtsi and all
+BCM2835/6/7 specific in the new bcm2835-common.dtsi.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ arch/arm/boot/dts/bcm2835-common.dtsi | 53 +++++++++++++++++++++++++++
+ arch/arm/boot/dts/bcm2835.dtsi | 1 +
+ arch/arm/boot/dts/bcm2836.dtsi | 1 +
+ arch/arm/boot/dts/bcm2837.dtsi | 1 +
+ arch/arm/boot/dts/bcm283x.dtsi | 43 +---------------------
+ 5 files changed, 57 insertions(+), 42 deletions(-)
+ create mode 100644 arch/arm/boot/dts/bcm2835-common.dtsi
+
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2835-common.dtsi
+@@ -0,0 +1,53 @@
++// SPDX-License-Identifier: GPL-2.0
++
++/* This include file covers the common peripherals and configuration between
++ * bcm2835, bcm2836 and bcm2837 implementations.
++ */
++
++/ {
++ soc {
++ timer@7e003000 {
++ compatible = "brcm,bcm2835-system-timer";
++ reg = <0x7e003000 0x1000>;
++ interrupts = <1 0>, <1 1>, <1 2>, <1 3>;
++ /* This could be a reference to BCM2835_CLOCK_TIMER,
++ * but we don't have the driver using the common clock
++ * support yet.
++ */
++ clock-frequency = <1000000>;
++ };
++
++ intc: interrupt-controller@7e00b200 {
++ compatible = "brcm,bcm2835-armctrl-ic";
++ reg = <0x7e00b200 0x200>;
++ interrupt-controller;
++ #interrupt-cells = <2>;
++ };
++
++ thermal: thermal@7e212000 {
++ compatible = "brcm,bcm2835-thermal";
++ reg = <0x7e212000 0x8>;
++ clocks = <&clocks BCM2835_CLOCK_TSENS>;
++ #thermal-sensor-cells = <0>;
++ status = "disabled";
++ };
++
++ v3d: v3d@7ec00000 {
++ compatible = "brcm,bcm2835-v3d";
++ reg = <0x7ec00000 0x1000>;
++ interrupts = <1 10>;
++ };
++ };
++};
++
++&gpio {
++ i2c_slave_gpio18: i2c_slave_gpio18 {
++ brcm,pins = <18 19 20 21>;
++ brcm,function = <BCM2835_FSEL_ALT3>;
++ };
++
++ jtag_gpio4: jtag_gpio4 {
++ brcm,pins = <4 5 6 12 13>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++};
+--- a/arch/arm/boot/dts/bcm2835.dtsi
++++ b/arch/arm/boot/dts/bcm2835.dtsi
+@@ -1,5 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+ #include "bcm283x.dtsi"
++#include "bcm2835-common.dtsi"
+
+ / {
+ compatible = "brcm,bcm2835";
+--- a/arch/arm/boot/dts/bcm2836.dtsi
++++ b/arch/arm/boot/dts/bcm2836.dtsi
+@@ -1,5 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+ #include "bcm283x.dtsi"
++#include "bcm2835-common.dtsi"
+
+ / {
+ compatible = "brcm,bcm2836";
+--- a/arch/arm/boot/dts/bcm2837.dtsi
++++ b/arch/arm/boot/dts/bcm2837.dtsi
+@@ -1,4 +1,5 @@
+ #include "bcm283x.dtsi"
++#include "bcm2835-common.dtsi"
+
+ / {
+ compatible = "brcm,bcm2837";
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -55,17 +55,6 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+- timer@7e003000 {
+- compatible = "brcm,bcm2835-system-timer";
+- reg = <0x7e003000 0x1000>;
+- interrupts = <1 0>, <1 1>, <1 2>, <1 3>;
+- /* This could be a reference to BCM2835_CLOCK_TIMER,
+- * but we don't have the driver using the common clock
+- * support yet.
+- */
+- clock-frequency = <1000000>;
+- };
+-
+ txp@7e004000 {
+ compatible = "brcm,bcm2835-txp";
+ reg = <0x7e004000 0x20>;
+@@ -113,13 +102,6 @@
+ brcm,dma-channel-mask = <0x7f35>;
+ };
+
+- intc: interrupt-controller@7e00b200 {
+- compatible = "brcm,bcm2835-armctrl-ic";
+- reg = <0x7e00b200 0x200>;
+- interrupt-controller;
+- #interrupt-cells = <2>;
+- };
+-
+ watchdog@7e100000 {
+ compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
+ #power-domain-cells = <1>;
+@@ -183,8 +165,7 @@
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+- /* Defines pin muxing groups according to
+- * BCM2835-ARM-Peripherals.pdf page 102.
++ /* Defines common pin muxing groups
+ *
+ * While each pin can have its mux selected
+ * for various functions individually, some
+@@ -262,15 +243,7 @@
+ brcm,pins = <44 45>;
+ brcm,function = <BCM2835_FSEL_ALT2>;
+ };
+- i2c_slave_gpio18: i2c_slave_gpio18 {
+- brcm,pins = <18 19 20 21>;
+- brcm,function = <BCM2835_FSEL_ALT3>;
+- };
+
+- jtag_gpio4: jtag_gpio4 {
+- brcm,pins = <4 5 6 12 13>;
+- brcm,function = <BCM2835_FSEL_ALT5>;
+- };
+ jtag_gpio22: jtag_gpio22 {
+ brcm,pins = <22 23 24 25 26 27>;
+ brcm,function = <BCM2835_FSEL_ALT4>;
+@@ -487,14 +460,6 @@
+
+ };
+
+- thermal: thermal@7e212000 {
+- compatible = "brcm,bcm2835-thermal";
+- reg = <0x7e212000 0x8>;
+- clocks = <&clocks BCM2835_CLOCK_TSENS>;
+- #thermal-sensor-cells = <0>;
+- status = "disabled";
+- };
+-
+ aux: aux@7e215000 {
+ compatible = "brcm,bcm2835-aux";
+ #clock-cells = <1>;
+@@ -660,12 +625,6 @@
+ phy-names = "usb2-phy";
+ };
+
+- v3d: v3d@7ec00000 {
+- compatible = "brcm,bcm2835-v3d";
+- reg = <0x7ec00000 0x1000>;
+- interrupts = <1 10>;
+- };
+-
+ vc4: gpu {
+ compatible = "brcm,bcm2835-vc4";
+ };
+++ /dev/null
-From efb4b8384a21a1542bc4c26063752180dda79c0b Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 13 May 2019 16:47:54 +0100
-Subject: [PATCH 634/703] staging: vcsm-cma: Alter dev node permissions to 0666
-
-Until the udev rules are updated, open up access to this node by
-default.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -1572,6 +1572,8 @@ static void vc_sm_connected_init(void)
- sm_state->misc_dev.name = DEVICE_NAME;
- sm_state->misc_dev.fops = &vc_sm_ops;
- sm_state->misc_dev.parent = NULL;
-+ /* Temporarily set as 666 until udev rules have been sorted */
-+ sm_state->misc_dev.mode = 0666;
- ret = misc_register(&sm_state->misc_dev);
- if (ret) {
- pr_err("vcsm-cma: failed to register misc device.\n");
--- /dev/null
+From 8e0de1503575a5cb6810089b8fe40ad2309ac717 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 May 2019 13:54:21 +0100
+Subject: [PATCH 635/725] ARM: dts: Add bcm2711-rpi-4-b.dts and components
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/Makefile | 1 +
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 320 ++++++++++++
+ arch/arm/boot/dts/bcm2711.dtsi | 50 ++
+ arch/arm/boot/dts/bcm2838.dtsi | 724 ++++++++++++++++++++++++++
+ 4 files changed, 1095 insertions(+)
+ create mode 100644 arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+ create mode 100644 arch/arm/boot/dts/bcm2711.dtsi
+ create mode 100644 arch/arm/boot/dts/bcm2838.dtsi
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -8,6 +8,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+ bcm2708-rpi-zero-w.dtb \
+ bcm2709-rpi-2-b.dtb \
+ bcm2710-rpi-3-b.dtb \
++ bcm2711-rpi-4-b.dtb \
+ bcm2710-rpi-3-b-plus.dtb \
+ bcm2710-rpi-cm3.dtb
+
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -0,0 +1,320 @@
++/dts-v1/;
++
++#include "bcm2711.dtsi"
++
++/ {
++ compatible = "raspberrypi,4-model-b", "brcm,bcm2838", "brcm,bcm2837";
++ model = "Raspberry Pi 4 Model B";
++ #address-cells = <2>;
++ #size-cells = <1>;
++
++ memory {
++ device_type = "memory";
++ reg = <0x0 0x0 0x0>;
++ };
++
++ chosen {
++ bootargs = "8250.nr_uarts=1 cma=64M";
++ };
++
++ aliases {
++ serial0 = &uart1;
++ serial1 = &uart0;
++ mmc0 = &emmc2;
++ mmc1 = &mmcnr;
++ mmc2 = &sdhost;
++ /delete-property/ ethernet;
++ /delete-property/ intc;
++ ethernet0 = &genet;
++ };
++};
++
++&soc {
++ virtgpio: virtgpio {
++ compatible = "brcm,bcm2835-virtgpio";
++ gpio-controller;
++ #gpio-cells = <2>;
++ firmware = <&firmware>;
++ status = "okay";
++ };
++};
++
++&mmcnr {
++ pinctrl-names = "default";
++ pinctrl-0 = <&sdio_pins>;
++ bus-width = <4>;
++ status = "okay";
++};
++
++&firmware {
++ expgpio: expgpio {
++ compatible = "raspberrypi,firmware-gpio";
++ gpio-controller;
++ #gpio-cells = <2>;
++ 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 = <125000000>;
++ };
++
++ spidev1: spidev@1{
++ compatible = "spidev";
++ reg = <1>; /* CE1 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ };
++};
++
++// =============================================
++// Board specific stuff here
++
++/ {
++
++ sd_io_1v8_reg: sd_io_1v8_reg {
++ status = "okay";
++ compatible = "regulator-gpio";
++ vin-supply = <&vdd_5v0_reg>;
++ regulator-name = "vdd-sd-io";
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-boot-on;
++ regulator-always-on;
++ regulator-settling-time-us = <5000>;
++
++ gpios = <&expgpio 4 GPIO_ACTIVE_HIGH>;
++ states = <1800000 0x1
++ 3300000 0x0>;
++ };
++};
++
++&sdhost {
++ status = "disabled";
++};
++
++&emmc2 {
++ status = "okay";
++ broken-cd;
++ vqmmc-supply = <&sd_io_1v8_reg>;
++};
++
++&leds {
++ act_led: act {
++ label = "led0";
++ linux,default-trigger = "mmc0";
++ gpios = <&gpio 42 0>;
++ };
++
++ pwr_led: pwr {
++ label = "led1";
++ linux,default-trigger = "input";
++ gpios = <&expgpio 2 0>;
++ };
++};
++
++&audio {
++ pinctrl-names = "default";
++ pinctrl-0 = <&audio_pins>;
++};
++
++&sdhost_gpio48 {
++ brcm,pins = <22 23 24 25 26 27>;
++ brcm,function = <BCM2835_FSEL_ALT0>;
++};
++
++&gpio {
++ spi0_pins: spi0_pins {
++ brcm,pins = <9 10 11>;
++ brcm,function = <BCM2835_FSEL_ALT0>;
++ };
++
++ spi0_cs_pins: spi0_cs_pins {
++ brcm,pins = <8 7>;
++ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++ };
++
++ spi3_pins: spi3_pins {
++ brcm,pins = <1 2 3>;
++ brcm,function = <BCM2835_FSEL_ALT3>;
++ };
++
++ spi3_cs_pins: spi3_cs_pins {
++ brcm,pins = <0 24>;
++ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++ };
++
++ spi4_pins: spi4_pins {
++ brcm,pins = <5 6 7>;
++ brcm,function = <BCM2835_FSEL_ALT3>;
++ };
++
++ spi4_cs_pins: spi4_cs_pins {
++ brcm,pins = <4 25>;
++ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++ };
++
++ spi5_pins: spi5_pins {
++ brcm,pins = <13 14 15>;
++ brcm,function = <BCM2835_FSEL_ALT3>;
++ };
++
++ spi5_cs_pins: spi5_cs_pins {
++ brcm,pins = <12 26>;
++ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++ };
++
++ spi6_pins: spi6_pins {
++ brcm,pins = <19 20 21>;
++ brcm,function = <BCM2835_FSEL_ALT3>;
++ };
++
++ spi6_cs_pins: spi6_cs_pins {
++ brcm,pins = <18 27>;
++ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++ };
++
++ i2c0_pins: i2c0 {
++ brcm,pins = <0 1>;
++ brcm,function = <BCM2835_FSEL_ALT0>;
++ };
++
++ i2c1_pins: i2c1 {
++ brcm,pins = <2 3>;
++ brcm,function = <BCM2835_FSEL_ALT0>;
++ };
++
++ i2c3_pins: i2c3 {
++ brcm,pins = <4 5>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++
++ i2c4_pins: i2c4 {
++ brcm,pins = <8 9>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++
++ i2c5_pins: i2c5 {
++ brcm,pins = <12 13>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++
++ i2c6_pins: i2c6 {
++ brcm,pins = <22 23>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++
++ i2s_pins: i2s {
++ brcm,pins = <18 19 20 21>;
++ brcm,function = <BCM2835_FSEL_ALT0>;
++ };
++
++ sdio_pins: sdio_pins {
++ brcm,pins = <34 35 36 37 38 39>;
++ brcm,function = <BCM2835_FSEL_ALT3>; // alt3 = SD1
++ brcm,pull = <0 2 2 2 2 2>;
++ };
++
++ bt_pins: bt_pins {
++ brcm,pins = "-"; // non-empty to keep btuart happy, //4 = 0
++ // to fool pinctrl
++ brcm,function = <0>;
++ brcm,pull = <2>;
++ };
++
++ uart0_pins: uart0_pins {
++ brcm,pins = <32 33>;
++ brcm,function = <BCM2835_FSEL_ALT3>;
++ brcm,pull = <0 2>;
++ };
++
++ uart1_pins: uart1_pins {
++ brcm,pins;
++ brcm,function;
++ brcm,pull;
++ };
++
++ uart2_pins: uart2_pins {
++ brcm,pins = <0 1>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ brcm,pull = <0 2>;
++ };
++
++ uart3_pins: uart3_pins {
++ brcm,pins = <4 5>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ brcm,pull = <0 2>;
++ };
++
++ uart4_pins: uart4_pins {
++ brcm,pins = <8 9>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ brcm,pull = <0 2>;
++ };
++
++ uart5_pins: uart5_pins {
++ brcm,pins = <12 13>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ brcm,pull = <0 2>;
++ };
++
++ audio_pins: audio_pins {
++ brcm,pins = <40 41>;
++ brcm,function = <4>;
++ };
++};
++
++&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 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2s_pins>;
++};
++
++/ {
++ __overrides__ {
++ act_led_gpio = <&act_led>,"gpios:4";
++ 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";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2711.dtsi
+@@ -0,0 +1,50 @@
++#include "bcm2838.dtsi"
++#include "bcm270x.dtsi"
++#include "bcm2708-rpi.dtsi"
++
++/ {
++ soc {
++ /delete-node/ mailbox@7e00b840;
++ /delete-node/ v3d@7ec00000;
++ };
++
++ __overrides__ {
++ arm_freq;
++ };
++};
++
++&dma {
++ brcm,dma-channel-mask = <0x7ef5>;
++};
++
++&txp {
++ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&firmwarekms {
++ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&smi {
++ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&mmc {
++ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&mmcnr {
++ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&usb {
++ reg = <0x7e980000 0x10000>,
++ <0x7e00b200 0x200>;
++ interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&gpio {
++ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -0,0 +1,724 @@
++// SPDX-License-Identifier: GPL-2.0
++#include "bcm283x.dtsi"
++
++#include <dt-bindings/interrupt-controller/arm-gic.h>
++#include <dt-bindings/soc/bcm2835-pm.h>
++
++/ {
++ compatible = "brcm,bcm2838", "brcm,bcm2837";
++
++ interrupt-parent = <&gicv2>;
++
++ soc {
++ ranges = <0x7e000000 0x0 0xfe000000 0x01800000>,
++ <0x7c000000 0x0 0xfc000000 0x02000000>,
++ <0x40000000 0x0 0xff800000 0x00800000>;
++ /* Emulate a contiguous 30-bit address range for DMA */
++ dma-ranges = <0xc0000000 0x0 0x00000000 0x3c000000>;
++
++ /delete-node/ mailbox@7e00b840;
++ /delete-node/ interrupt-controller@7e00f300;
++
++ local_intc: local_intc@40000000 {
++ compatible = "brcm,bcm2836-l1-intc";
++ reg = <0x40000000 0x100>;
++ };
++
++ gicv2: gic400@40041000 {
++ interrupt-controller;
++ #interrupt-cells = <3>;
++ compatible = "arm,gic-400";
++ reg = <0x40041000 0x1000>,
++ <0x40042000 0x2000>,
++ <0x40046000 0x2000>,
++ <0x40048000 0x2000>;
++ };
++
++ thermal: thermal@7d5d2200 {
++ compatible = "brcm,avs-tmon-bcm2838";
++ reg = <0x7d5d2200 0x2c>;
++ interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "tmon";
++ clocks = <&clocks BCM2835_CLOCK_TSENS>;
++ #thermal-sensor-cells = <0>;
++ status = "okay";
++ };
++
++ pm: watchdog@7e100000 {
++ reg = <0x7e100000 0x114>,
++ <0x7e00a000 0x24>,
++ <0x7ec11000 0x20>;
++ };
++
++ rng@7e104000 {
++ interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ uart2: serial@7e201400 {
++ compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
++ reg = <0x7e201400 0x200>;
++ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&clocks BCM2835_CLOCK_UART>,
++ <&clocks BCM2835_CLOCK_VPU>;
++ clock-names = "uartclk", "apb_pclk";
++ arm,primecell-periphid = <0x00241011>;
++ status = "disabled";
++ };
++
++ uart3: serial@7e201600 {
++ compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
++ reg = <0x7e201600 0x200>;
++ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&clocks BCM2835_CLOCK_UART>,
++ <&clocks BCM2835_CLOCK_VPU>;
++ clock-names = "uartclk", "apb_pclk";
++ arm,primecell-periphid = <0x00241011>;
++ status = "disabled";
++ };
++
++ uart4: serial@7e201800 {
++ compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
++ reg = <0x7e201800 0x200>;
++ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&clocks BCM2835_CLOCK_UART>,
++ <&clocks BCM2835_CLOCK_VPU>;
++ clock-names = "uartclk", "apb_pclk";
++ arm,primecell-periphid = <0x00241011>;
++ status = "disabled";
++ };
++
++ uart5: serial@7e201a00 {
++ compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
++ reg = <0x7e201a00 0x200>;
++ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&clocks BCM2835_CLOCK_UART>,
++ <&clocks BCM2835_CLOCK_VPU>;
++ clock-names = "uartclk", "apb_pclk";
++ arm,primecell-periphid = <0x00241011>;
++ status = "disabled";
++ };
++
++ spi@7e204000 {
++ reg = <0x7e204000 0x0200>;
++ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ spi3: spi@7e204600 {
++ compatible = "brcm,bcm2835-spi";
++ reg = <0x7e204600 0x0200>;
++ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&clocks BCM2835_CLOCK_VPU>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "disabled";
++ };
++
++ spi4: spi@7e204800 {
++ compatible = "brcm,bcm2835-spi";
++ reg = <0x7e204800 0x0200>;
++ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&clocks BCM2835_CLOCK_VPU>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "disabled";
++ };
++
++ spi5: spi@7e204a00 {
++ compatible = "brcm,bcm2835-spi";
++ reg = <0x7e204a00 0x0200>;
++ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&clocks BCM2835_CLOCK_VPU>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "disabled";
++ };
++
++ spi6: spi@7e204c00 {
++ compatible = "brcm,bcm2835-spi";
++ reg = <0x7e204c00 0x0200>;
++ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&clocks BCM2835_CLOCK_VPU>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "disabled";
++ };
++
++ i2c3: i2c@7e205600 {
++ compatible = "brcm,bcm2835-i2c";
++ reg = <0x7e205600 0x200>;
++ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&clocks BCM2835_CLOCK_VPU>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "disabled";
++ };
++
++ i2c4: i2c@7e205800 {
++ compatible = "brcm,bcm2835-i2c";
++ reg = <0x7e205800 0x200>;
++ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&clocks BCM2835_CLOCK_VPU>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "disabled";
++ };
++
++ i2c5: i2c@7e205a00 {
++ compatible = "brcm,bcm2835-i2c";
++ reg = <0x7e205a00 0x200>;
++ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&clocks BCM2835_CLOCK_VPU>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "disabled";
++ };
++
++ i2c6: i2c@7e205c00 {
++ compatible = "brcm,bcm2835-i2c";
++ reg = <0x7e205c00 0x200>;
++ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&clocks BCM2835_CLOCK_VPU>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "disabled";
++ };
++
++ pixelvalve@7e206000 {
++ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ pixelvalve@7e207000 {
++ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ emmc2: emmc2@7e340000 {
++ compatible = "brcm,bcm2711-emmc2";
++ status = "okay";
++ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&clocks BCM2838_CLOCK_EMMC2>;
++ reg = <0x7e340000 0x100>;
++ };
++
++ hvs@7e400000 {
++ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ pixelvalve@7e807000 {
++ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
++ };
++ };
++
++ arm-pmu {
++ /*
++ * N.B. the A72 PMU support only exists in arch/arm64, hence
++ * the fallback to the A53 version.
++ */
++ compatible = "arm,cortex-a72-pmu", "arm,cortex-a53-pmu";
++ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ timer {
++ compatible = "arm,armv7-timer";
++ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) |
++ IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) |
++ IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
++ IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
++ IRQ_TYPE_LEVEL_LOW)>;
++ arm,cpu-registers-not-fw-configured;
++ always-on;
++ };
++
++ cpus: cpus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ enable-method = "brcm,bcm2836-smp"; // for ARM 32-bit
++
++ cpu0: cpu@0 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a72";
++ reg = <0>;
++ enable-method = "spin-table";
++ cpu-release-addr = <0x0 0x000000d8>;
++ };
++
++ cpu1: cpu@1 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a72";
++ reg = <1>;
++ enable-method = "spin-table";
++ cpu-release-addr = <0x0 0x000000e0>;
++ };
++
++ cpu2: cpu@2 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a72";
++ reg = <2>;
++ enable-method = "spin-table";
++ cpu-release-addr = <0x0 0x000000e8>;
++ };
++
++ cpu3: cpu@3 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a72";
++ reg = <3>;
++ enable-method = "spin-table";
++ cpu-release-addr = <0x0 0x000000f0>;
++ };
++ };
++
++ v3dbus {
++ compatible = "simple-bus";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges = <0x7c500000 0x0 0xfc500000 0x03300000>,
++ <0x40000000 0x0 0xff800000 0x00800000>;
++ dma-ranges = <0x00000000 0x0 0x00000000 0x3c000000>;
++
++ v3d: v3d@7ec04000 {
++ compatible = "brcm,2711-v3d";
++ reg =
++ <0x7ec00000 0x4000>,
++ <0x7ec04000 0x4000>;
++ reg-names = "hub", "core0";
++
++ power-domains = <&pm BCM2835_POWER_DOMAIN_GRAFX_V3D>;
++ resets = <&pm BCM2835_RESET_V3D>;
++ clocks = <&clocks BCM2835_CLOCK_V3D>;
++ interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
++ status = "okay";
++ };
++ };
++
++ scb: scb {
++ compatible = "simple-bus";
++ #address-cells = <2>;
++ #size-cells = <1>;
++
++ ranges = <0x0 0x7c000000 0x0 0xfc000000 0x03800000>,
++ <0x0 0x40000000 0x0 0xff800000 0x00800000>,
++ <0x6 0x00000000 0x6 0x00000000 0x40000000>,
++ <0x0 0x00000000 0x0 0x00000000 0xfc000000>;
++ dma-ranges = <0x0 0x00000000 0x0 0x00000000 0xfc000000>;
++
++ pcie_0: pcie@7d500000 {
++ reg = <0x0 0x7d500000 0x9310>,
++ <0x0 0x7e00f300 0x20>;
++ msi-controller;
++ msi-parent = <&pcie_0>;
++ #address-cells = <3>;
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ bus-range = <0x0 0x01>;
++ compatible = "brcm,bcm7211-pcie", "brcm,bcm7445-pcie",
++ "brcm,pci-plat-dev";
++ max-link-speed = <2>;
++ tot-num-pcie = <1>;
++ linux,pci-domain = <0>;
++ interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "pcie", "msi";
++ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
++ interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 143
++ IRQ_TYPE_LEVEL_HIGH
++ 0 0 0 2 &gicv2 GIC_SPI 144
++ IRQ_TYPE_LEVEL_HIGH
++ 0 0 0 3 &gicv2 GIC_SPI 145
++ IRQ_TYPE_LEVEL_HIGH
++ 0 0 0 4 &gicv2 GIC_SPI 146
++ IRQ_TYPE_LEVEL_HIGH>;
++
++ /* Map outbound accesses from scb:0x6_00000000-03ffffff
++ * to pci:0x0_f8000000-fbffffff
++ */
++ ranges = <0x02000000 0x0 0xf8000000 0x6 0x00000000
++ 0x0 0x04000000>;
++ /* Map inbound accesses from pci:0x0_00000000..ffffffff
++ * to scb:0x0_00000000-ffffffff
++ */
++ dma-ranges = <0x02000000 0x0 0x00000000 0x0 0x00000000
++ 0x1 0x00000000>;
++ status = "okay";
++ };
++
++ genet: genet@7d580000 {
++ compatible = "brcm,genet-v5";
++ reg = <0x0 0x7d580000 0x10000>;
++ status = "okay";
++ #address-cells = <0x1>;
++ #size-cells = <0x1>;
++ interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
++ phy-handle = <&phy1>;
++ phy-mode = "rgmii";
++ mdio@e14 {
++ #address-cells = <0x0>;
++ #size-cells = <0x1>;
++ compatible = "brcm,genet-mdio-v5";
++ reg = <0xe14 0x8>;
++ reg-names = "mdio";
++ phy1: genet-phy@0 {
++ compatible =
++ "ethernet-phy-ieee802.3-c22";
++ /* No interrupts - use PHY_POLL */
++ max-speed = <1000>;
++ reg = <0x1>;
++ };
++ };
++ };
++
++ xhci: xhci@7e9c0000 {
++ compatible = "generic-xhci";
++ status = "disabled";
++ reg = <0x0 0x7e9c0000 0x100000>;
++ interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ vchiq: mailbox@7e00b840 {
++ compatible = "brcm,bcm2838-vchiq";
++ reg = <0 0x7e00b840 0x3c>;
++ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ hevc-decoder@7eb00000 {
++ compatible = "raspberrypi,argon-hevc-decoder";
++ reg = <0x0 0x7eb00000 0x10000>;
++ status = "okay";
++ };
++
++ argon-local-intc@7eb10000 {
++ compatible = "raspberrypi,argon-local-intc";
++ reg = <0x0 0x7eb10000 0x1000>;
++ status = "okay";
++ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ h264-decoder@7eb20000 {
++ compatible = "raspberrypi,argon-h264-decoder";
++ reg = <0x0 0x7eb20000 0x10000>;
++ status = "okay";
++ };
++
++ vp9-decoder@7eb30000 {
++ compatible = "raspberrypi,argon-vp9-decoder";
++ reg = <0x0 0x7eb30000 0x10000>;
++ status = "okay";
++ };
++ };
++};
++
++&clk_osc {
++ clock-frequency = <54000000>;
++};
++
++&clocks {
++ compatible = "brcm,bcm2838-cprman";
++};
++
++&cpu_thermal {
++ coefficients = <(-487) 410040>;
++};
++
++&dsi0 {
++ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&dsi1 {
++ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&gpio {
++ gpclk0_gpio49: gpclk0_gpio49 {
++ brcm,pins = <49>;
++ brcm,function = <BCM2835_FSEL_ALT1>;
++ brcm,pull = <BCM2835_PUD_OFF>;
++ };
++ gpclk1_gpio50: gpclk1_gpio50 {
++ brcm,pins = <50>;
++ brcm,function = <BCM2835_FSEL_ALT1>;
++ brcm,pull = <BCM2835_PUD_OFF>;
++ };
++ gpclk2_gpio51: gpclk2_gpio51 {
++ brcm,pins = <51>;
++ brcm,function = <BCM2835_FSEL_ALT1>;
++ brcm,pull = <BCM2835_PUD_OFF>;
++ };
++
++ i2c0_gpio46: i2c0_gpio46 {
++ brcm,pins = <46 47>;
++ brcm,function = <BCM2835_FSEL_ALT0>;
++ };
++ i2c1_gpio46: i2c1_gpio46 {
++ brcm,pins = <46 47>;
++ brcm,function = <BCM2835_FSEL_ALT1>;
++ };
++ i2c3_gpio2: i2c3_gpio2 {
++ brcm,pins = <2 3>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++ i2c3_gpio4: i2c3_gpio4 {
++ brcm,pins = <4 5>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++ i2c4_gpio6: i2c4_gpio6 {
++ brcm,pins = <6 7>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++ i2c4_gpio8: i2c4_gpio8 {
++ brcm,pins = <8 9>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++ i2c5_gpio10: i2c5_gpio10 {
++ brcm,pins = <10 11>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++ i2c5_gpio12: i2c5_gpio12 {
++ brcm,pins = <12 13>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++ i2c6_gpio0: i2c6_gpio0 {
++ brcm,pins = <0 1>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++ i2c6_gpio22: i2c6_gpio22 {
++ brcm,pins = <22 23>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++ i2c_slave_gpio8: i2c_slave_gpio8 {
++ brcm,pins = <8 9 10 11>;
++ brcm,function = <BCM2835_FSEL_ALT3>;
++ };
++
++ jtag_gpio48: jtag_gpio48 {
++ brcm,pins = <48 49 50 51 52 53>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ };
++
++ mii_gpio28: mii_gpio28 {
++ brcm,pins = <28 29 30 31>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ };
++ mii_gpio36: mii_gpio36 {
++ brcm,pins = <36 37 38 39>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++
++ pcm_gpio50: pcm_gpio50 {
++ brcm,pins = <50 51 52 53>;
++ brcm,function = <BCM2835_FSEL_ALT2>;
++ };
++
++ pwm0_gpio52: pwm0_gpio52 {
++ brcm,pins = <52>;
++ brcm,function = <BCM2835_FSEL_ALT1>;
++ brcm,pull = <BCM2835_PUD_OFF>;
++ };
++ pwm1_gpio53: pwm1_gpio53 {
++ brcm,pins = <53>;
++ brcm,function = <BCM2835_FSEL_ALT1>;
++ brcm,pull = <BCM2835_PUD_OFF>;
++ };
++
++ /* The following group consists of:
++ * RGMII_START_STOP
++ * RGMII_RX_OK
++ */
++ rgmii_gpio35: rgmii_gpio35 {
++ brcm,pins = <35 36>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ };
++ rgmii_irq_gpio34: rgmii_irq_gpio34 {
++ brcm,pins = <34>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++ rgmii_irq_gpio39: rgmii_irq_gpio39 {
++ brcm,pins = <39>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ };
++ rgmii_mdio_gpio28: rgmii_mdio_gpio28 {
++ brcm,pins = <28 29>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++ rgmii_mdio_gpio37: rgmii_mdio_gpio37 {
++ brcm,pins = <37 38>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ };
++
++ spi0_gpio46: spi0_gpio46 {
++ brcm,pins = <46 47 48 49>;
++ brcm,function = <BCM2835_FSEL_ALT2>;
++ };
++ spi2_gpio46: spi2_gpio46 {
++ brcm,pins = <46 47 48 49 50>;
++ brcm,function = <BCM2835_FSEL_ALT5>;
++ };
++ spi3_gpio0: spi3_gpio0 {
++ brcm,pins = <0 1 2 3>;
++ brcm,function = <BCM2835_FSEL_ALT3>;
++ };
++ spi4_gpio4: spi4_gpio4 {
++ brcm,pins = <4 5 6 7>;
++ brcm,function = <BCM2835_FSEL_ALT3>;
++ };
++ spi5_gpio12: spi5_gpio12 {
++ brcm,pins = <12 13 14 15>;
++ brcm,function = <BCM2835_FSEL_ALT3>;
++ };
++ spi6_gpio18: spi6_gpio18 {
++ brcm,pins = <18 19 20 21>;
++ brcm,function = <BCM2835_FSEL_ALT3>;
++ };
++
++ uart2_gpio0: uart2_gpio0 {
++ brcm,pins = <0 1>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
++ };
++ uart2_ctsrts_gpio2: uart2_ctsrts_gpio2 {
++ brcm,pins = <2 3>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
++ };
++ uart3_gpio4: uart3_gpio4 {
++ brcm,pins = <4 5>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
++ };
++ uart3_ctsrts_gpio6: uart3_ctsrts_gpio6 {
++ brcm,pins = <6 7>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
++ };
++ uart4_gpio8: uart4_gpio8 {
++ brcm,pins = <8 9>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
++ };
++ uart4_ctsrts_gpio10: uart4_ctsrts_gpio10 {
++ brcm,pins = <10 11>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
++ };
++ uart5_gpio12: uart5_gpio12 {
++ brcm,pins = <12 13>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
++ };
++ uart5_ctsrts_gpio14: uart5_ctsrts_gpio14 {
++ brcm,pins = <14 15>;
++ brcm,function = <BCM2835_FSEL_ALT4>;
++ brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
++ };
++};
++
++&vec {
++ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&usb {
++ interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&hdmi {
++ interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&uart1 {
++ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&spi1 {
++ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&spi2 {
++ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&csi0 {
++ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&csi1 {
++ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&sdhci {
++ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&i2c0 {
++ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&i2c1 {
++ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&i2c2 {
++ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&gpio {
++ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&mailbox {
++ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&rng {
++ compatible = "brcm,bcm2838-rng200";
++};
++
++&sdhost {
++ interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&uart0 {
++ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&dma {
++ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 7 */
++ <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 8 */
++ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 9 */
++ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 10 */
++ /* DMA4 - 40 bit DMA engines */
++ <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, /* dma4 11 */
++ <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, /* dma4 12 */
++ <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, /* dma4 13 */
++ <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; /* dma4 14 */
++ interrupt-names = "dma0",
++ "dma1",
++ "dma2",
++ "dma3",
++ "dma4",
++ "dma5",
++ "dma6",
++ "dma7",
++ "dma8",
++ "dma9",
++ "dma10",
++ "dma11",
++ "dma12",
++ "dma13",
++ "dma14";
++ brcm,dma-channel-mask = <0x7ef5>;
++};
+++ /dev/null
-From 800cd6716ba60faf5f1782935c12b12943237de4 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 16 May 2019 15:17:19 +0100
-Subject: [PATCH 635/703] staging: vcsm-cma: Drop logging level on messages in
- vc_sm_release_resource
-
-They weren't errors but were logged as such.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 7 +++----
- 1 file changed, 3 insertions(+), 4 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -301,14 +301,13 @@ static void vc_sm_release_resource(struc
-
- if (buffer->vc_handle) {
- /* We've sent the unmap request but not had the response. */
-- pr_err("[%s]: Waiting for VPU unmap response on %p\n",
-- __func__, buffer);
-+ pr_debug("[%s]: Waiting for VPU unmap response on %p\n",
-+ __func__, buffer);
- goto defer;
- }
- if (buffer->in_use) {
- /* dmabuf still in use - we await the release */
-- pr_err("[%s]: buffer %p is still in use\n",
-- __func__, buffer);
-+ pr_debug("[%s]: buffer %p is still in use\n", __func__, buffer);
- goto defer;
- }
-
--- /dev/null
+From 9bb7aa6a108469e331bc46513c317f088b720880 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 30 May 2019 16:44:24 +0100
+Subject: [PATCH 636/725] overlays: Add i2c3-6 and uart2-5 overlays
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/Makefile | 8 +++
+ arch/arm/boot/dts/overlays/README | 52 ++++++++++++++++++++
+ arch/arm/boot/dts/overlays/i2c3-overlay.dts | 27 ++++++++++
+ arch/arm/boot/dts/overlays/i2c4-overlay.dts | 27 ++++++++++
+ arch/arm/boot/dts/overlays/i2c5-overlay.dts | 27 ++++++++++
+ arch/arm/boot/dts/overlays/i2c6-overlay.dts | 27 ++++++++++
+ arch/arm/boot/dts/overlays/uart2-overlay.dts | 27 ++++++++++
+ arch/arm/boot/dts/overlays/uart3-overlay.dts | 27 ++++++++++
+ arch/arm/boot/dts/overlays/uart4-overlay.dts | 27 ++++++++++
+ arch/arm/boot/dts/overlays/uart5-overlay.dts | 27 ++++++++++
+ 10 files changed, 276 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/i2c3-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/i2c4-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/i2c5-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/i2c6-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/uart2-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/uart3-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/uart4-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/uart5-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -65,6 +65,10 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ i2c-sensor.dtbo \
+ i2c0-bcm2708.dtbo \
+ i2c1-bcm2708.dtbo \
++ i2c3.dtbo \
++ i2c4.dtbo \
++ i2c5.dtbo \
++ i2c6.dtbo \
+ i2s-gpio28-31.dtbo \
+ ilitek251x.dtbo \
+ iqaudio-codec.dtbo \
+@@ -149,6 +153,10 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ tpm-slb9670.dtbo \
+ uart0.dtbo \
+ uart1.dtbo \
++ uart2.dtbo \
++ uart3.dtbo \
++ uart4.dtbo \
++ uart5.dtbo \
+ udrc.dtbo \
+ upstream.dtbo \
+ vc4-fkms-v3d.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1137,6 +1137,34 @@ Params: sda1_pin GPIO pin
+ "yes")
+
+
++Name: i2c3
++Info: Enable the i2c3 bus
++Load: dtoverlay=i2c3,<param>
++Params: pins_2_3 Use GPIOs 2 and 3
++ pins_4_5 Use GPIOs 4 and 5 (default)
++
++
++Name: i2c4
++Info: Enable the i2c4 bus
++Load: dtoverlay=i2c4,<param>
++Params: pins_6_7 Use GPIOs 6 and 7
++ pins_8_9 Use GPIOs 8 and 9 (default)
++
++
++Name: i2c5
++Info: Enable the i2c5 bus
++Load: dtoverlay=i2c5,<param>
++Params: pins_10_11 Use GPIOs 10 and 11
++ pins_12_13 Use GPIOs 12 and 13 (default)
++
++
++Name: i2c6
++Info: Enable the i2c6 bus
++Load: dtoverlay=i2c6,<param>
++Params: pins_0_1 Use GPIOs 0 and 1
++ pins_22_23 Use GPIOs 22 and 23 (default)
++
++
+ Name: i2s-gpio28-31
+ Info: move I2S function block to GPIO 28 to 31
+ Load: dtoverlay=i2s-gpio28-31
+@@ -2199,6 +2227,30 @@ Params: txd1_pin GPIO pin
+ rxd1_pin GPIO pin for RXD1 (15, 33 or 41 - default 15)
+
+
++Name: uart2
++Info: Enable uart 2 on GPIOs 0-3
++Load: dtoverlay=uart2,<param>
++Params: ctsrts Enable CTS/RTS on GPIOs 2-3 (default off)
++
++
++Name: uart3
++Info: Enable uart 3 on GPIOs 4-7
++Load: dtoverlay=uart3,<param>
++Params: ctsrts Enable CTS/RTS on GPIOs 6-7 (default off)
++
++
++Name: uart4
++Info: Enable uart 4 on GPIOs 8-11
++Load: dtoverlay=uart4,<param>
++Params: ctsrts Enable CTS/RTS on GPIOs 10-11 (default off)
++
++
++Name: uart5
++Info: Enable uart 5 on GPIOs 12-15
++Load: dtoverlay=uart5,<param>
++Params: ctsrts Enable CTS/RTS on GPIOs 14-15 (default off)
++
++
+ Name: udrc
+ Info: Configures the NW Digital Radio UDRC Hat
+ Load: dtoverlay=udrc,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/i2c3-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&i2c3>;
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c3_pins>;
++ };
++ };
++
++ fragment@1 {
++ target = <&i2c3_pins>;
++ __dormant__ {
++ brcm,pins = <2 3>;
++ };
++ };
++
++ __overrides__ {
++ pins_2_3 = <0>,"=1";
++ pins_4_5 = <0>,"!1";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/i2c4-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&i2c4>;
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c4_pins>;
++ };
++ };
++
++ fragment@1 {
++ target = <&i2c4_pins>;
++ __dormant__ {
++ brcm,pins = <6 7>;
++ };
++ };
++
++ __overrides__ {
++ pins_6_7 = <0>,"=1";
++ pins_8_9 = <0>,"!1";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/i2c5-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&i2c5>;
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c5_pins>;
++ };
++ };
++
++ fragment@1 {
++ target = <&i2c5_pins>;
++ __dormant__ {
++ brcm,pins = <10 11>;
++ };
++ };
++
++ __overrides__ {
++ pins_10_11 = <0>,"=1";
++ pins_12_13 = <0>,"!1";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/i2c6-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&i2c6>;
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c6_pins>;
++ };
++ };
++
++ fragment@1 {
++ target = <&i2c6_pins>;
++ __dormant__ {
++ brcm,pins = <0 1>;
++ };
++ };
++
++ __overrides__ {
++ pins_0_1 = <0>,"=1";
++ pins_22_23 = <0>,"!1";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/uart2-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&uart2>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart2_pins>;
++ status = "okay";
++ };
++ };
++
++ fragment@1 {
++ target = <&uart2_pins>;
++ __dormant__ {
++ brcm,pins = <0 1 2 3>;
++ brcm,pull = <0 2 2 0>;
++ };
++ };
++
++ __overrides__ {
++ ctsrts = <0>,"=1";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/uart3-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&uart3>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart3_pins>;
++ status = "okay";
++ };
++ };
++
++ fragment@1 {
++ target = <&uart3_pins>;
++ __dormant__ {
++ brcm,pins = <4 5 6 7>;
++ brcm,pull = <0 2 2 0>;
++ };
++ };
++
++ __overrides__ {
++ ctsrts = <0>,"=1";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/uart4-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&uart4>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart4_pins>;
++ status = "okay";
++ };
++ };
++
++ fragment@1 {
++ target = <&uart4_pins>;
++ __dormant__ {
++ brcm,pins = <8 9 10 11>;
++ brcm,pull = <0 2 2 0>;
++ };
++ };
++
++ __overrides__ {
++ ctsrts = <0>,"=1";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/uart5-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/{
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&uart5>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart5_pins>;
++ status = "okay";
++ };
++ };
++
++ fragment@1 {
++ target = <&uart5_pins>;
++ __dormant__ {
++ brcm,pins = <12 13 14 15>;
++ brcm,pull = <0 2 2 0>;
++ };
++ };
++
++ __overrides__ {
++ ctsrts = <0>,"=1";
++ };
++};
+++ /dev/null
-From bc7d2e33c324c77c13ecc7699342a72f52cf0789 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 22 May 2019 15:40:37 +0100
-Subject: [PATCH 636/703] staging: vcsm-cma: Fixup the alloc code handling of
- kernel_id
-
-The allocation code had been copied in from an old branch prior
-to having added the IDR for 64bit support. It was therefore pushing
-a pointer into the kernel_id field instead of an IDR handle, the
-lookup therefore failed, and we never released the buffer.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -1206,7 +1206,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
-
- import.addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
- import.size = aligned_size;
-- import.kernel_id = (uint32_t)buffer;
-+ import.kernel_id = get_kernel_id(buffer);
-
- /* Wrap it into a videocore buffer. */
- status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
-@@ -1231,6 +1231,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
- buffer->size = import.size;
- buffer->dma_addr = import.addr;
- buffer->vpu_state = VPU_MAPPED;
-+ buffer->kernel_id = import.kernel_id;
- //buffer->res_cached = ioparam->cached;
-
- fd = dma_buf_fd(dmabuf, O_CLOEXEC);
+++ /dev/null
-From 03f6bc683489b9652491d981b83448863230068c Mon Sep 17 00:00:00 2001
-From: James Hughes <james.hughes@raspberrypi.org>
-Date: Thu, 14 Mar 2019 13:27:54 +0000
-Subject: [PATCH 637/703] Pulled in the multi frame buffer support from the Pi3
- repo
-
----
- drivers/video/fbdev/bcm2708_fb.c | 580 +++++++++++++++------
- include/soc/bcm2835/raspberrypi-firmware.h | 4 +
- 2 files changed, 432 insertions(+), 152 deletions(-)
-
---- a/drivers/video/fbdev/bcm2708_fb.c
-+++ b/drivers/video/fbdev/bcm2708_fb.c
-@@ -2,6 +2,7 @@
- * linux/drivers/video/bcm2708_fb.c
- *
- * Copyright (C) 2010 Broadcom
-+ * Copyright (C) 2018 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
-@@ -13,6 +14,7 @@
- * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
- *
- */
-+
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/errno.h>
-@@ -36,6 +38,7 @@
- #include <linux/dma-mapping.h>
- #include <linux/cred.h>
- #include <soc/bcm2835/raspberrypi-firmware.h>
-+#include <linux/mutex.h>
-
- //#define BCM2708_FB_DEBUG
- #define MODULE_NAME "bcm2708_fb"
-@@ -82,62 +85,139 @@ struct bcm2708_fb_stats {
- u32 dma_irqs;
- };
-
-+struct vc4_display_settings_t {
-+ u32 display_num;
-+ u32 width;
-+ u32 height;
-+ u32 pitch;
-+ u32 depth;
-+ u32 virtual_width;
-+ u32 virtual_height;
-+ u32 virtual_width_offset;
-+ u32 virtual_height_offset;
-+ unsigned long fb_bus_address;
-+};
-+
-+struct bcm2708_fb_dev;
-+
- struct bcm2708_fb {
- struct fb_info fb;
- struct platform_device *dev;
-- struct rpi_firmware *fw;
- u32 cmap[16];
- u32 gpu_cmap[256];
-+ struct dentry *debugfs_dir;
-+ struct dentry *debugfs_subdir;
-+ unsigned long fb_bus_address;
-+ struct { u32 base, length; } gpu;
-+ struct vc4_display_settings_t display_settings;
-+ struct debugfs_regset32 screeninfo_regset;
-+ struct bcm2708_fb_dev *fbdev;
-+ unsigned int image_size;
-+ dma_addr_t dma_addr;
-+ void *cpuaddr;
-+};
-+
-+#define MAX_FRAMEBUFFERS 3
-+
-+struct bcm2708_fb_dev {
-+ int firmware_supports_multifb;
-+ /* Protects the DMA system from multiple FB access */
-+ struct mutex dma_mutex;
- int dma_chan;
- int dma_irq;
- void __iomem *dma_chan_base;
-- void *cb_base; /* DMA control blocks */
-- dma_addr_t cb_handle;
-- struct dentry *debugfs_dir;
- wait_queue_head_t dma_waitq;
-- struct bcm2708_fb_stats stats;
-- unsigned long fb_bus_address;
-- struct { u32 base, length; } gpu;
-+ bool disable_arm_alloc;
-+ struct bcm2708_fb_stats dma_stats;
-+ void *cb_base; /* DMA control blocks */
-+ dma_addr_t cb_handle;
-+ int instance_count;
-+ int num_displays;
-+ struct rpi_firmware *fw;
-+ struct bcm2708_fb displays[MAX_FRAMEBUFFERS];
- };
-
- #define to_bcm2708(info) container_of(info, struct bcm2708_fb, fb)
-
- static void bcm2708_fb_debugfs_deinit(struct bcm2708_fb *fb)
- {
-- debugfs_remove_recursive(fb->debugfs_dir);
-- fb->debugfs_dir = NULL;
-+ debugfs_remove_recursive(fb->debugfs_subdir);
-+ fb->debugfs_subdir = NULL;
-+
-+ fb->fbdev->instance_count--;
-+
-+ if (!fb->fbdev->instance_count) {
-+ debugfs_remove_recursive(fb->debugfs_dir);
-+ fb->debugfs_dir = NULL;
-+ }
- }
-
- static int bcm2708_fb_debugfs_init(struct bcm2708_fb *fb)
- {
-+ char buf[3];
-+ struct bcm2708_fb_dev *fbdev = fb->fbdev;
-+
- static struct debugfs_reg32 stats_registers[] = {
-- {
-- "dma_copies",
-- offsetof(struct bcm2708_fb_stats, dma_copies)
-- },
-- {
-- "dma_irqs",
-- offsetof(struct bcm2708_fb_stats, dma_irqs)
-- },
-+ {"dma_copies", offsetof(struct bcm2708_fb_stats, dma_copies)},
-+ {"dma_irqs", offsetof(struct bcm2708_fb_stats, dma_irqs)},
- };
-
-- fb->debugfs_dir = debugfs_create_dir(DRIVER_NAME, NULL);
-+ static struct debugfs_reg32 screeninfo[] = {
-+ {"width", offsetof(struct fb_var_screeninfo, xres)},
-+ {"height", offsetof(struct fb_var_screeninfo, yres)},
-+ {"bpp", offsetof(struct fb_var_screeninfo, bits_per_pixel)},
-+ {"xres_virtual", offsetof(struct fb_var_screeninfo, xres_virtual)},
-+ {"yres_virtual", offsetof(struct fb_var_screeninfo, yres_virtual)},
-+ {"xoffset", offsetof(struct fb_var_screeninfo, xoffset)},
-+ {"yoffset", offsetof(struct fb_var_screeninfo, yoffset)},
-+ };
-+
-+ fb->debugfs_dir = debugfs_lookup(DRIVER_NAME, NULL);
-+
-+ if (!fb->debugfs_dir)
-+ fb->debugfs_dir = debugfs_create_dir(DRIVER_NAME, NULL);
-+
- if (!fb->debugfs_dir) {
-- pr_warn("%s: could not create debugfs entry\n",
-- __func__);
-+ dev_warn(fb->fb.dev, "%s: could not create debugfs folder\n",
-+ __func__);
-+ return -EFAULT;
-+ }
-+
-+ snprintf(buf, sizeof(buf), "%u", fb->display_settings.display_num);
-+
-+ fb->debugfs_subdir = debugfs_create_dir(buf, fb->debugfs_dir);
-+
-+ if (!fb->debugfs_subdir) {
-+ dev_warn(fb->fb.dev, "%s: could not create debugfs entry %u\n",
-+ __func__, fb->display_settings.display_num);
- return -EFAULT;
- }
-
-- fb->stats.regset.regs = stats_registers;
-- fb->stats.regset.nregs = ARRAY_SIZE(stats_registers);
-- fb->stats.regset.base = &fb->stats;
--
-- if (!debugfs_create_regset32("stats", 0444, fb->debugfs_dir,
-- &fb->stats.regset)) {
-- pr_warn("%s: could not create statistics registers\n",
-- __func__);
-+ fbdev->dma_stats.regset.regs = stats_registers;
-+ fbdev->dma_stats.regset.nregs = ARRAY_SIZE(stats_registers);
-+ fbdev->dma_stats.regset.base = &fbdev->dma_stats;
-+
-+ if (!debugfs_create_regset32("dma_stats", 0444, fb->debugfs_subdir,
-+ &fbdev->dma_stats.regset)) {
-+ dev_warn(fb->fb.dev, "%s: could not create statistics registers\n",
-+ __func__);
-+ goto fail;
-+ }
-+
-+ fb->screeninfo_regset.regs = screeninfo;
-+ fb->screeninfo_regset.nregs = ARRAY_SIZE(screeninfo);
-+ fb->screeninfo_regset.base = &fb->fb.var;
-+
-+ if (!debugfs_create_regset32("screeninfo", 0444, fb->debugfs_subdir,
-+ &fb->screeninfo_regset)) {
-+ dev_warn(fb->fb.dev,
-+ "%s: could not create dimensions registers\n",
-+ __func__);
- goto fail;
- }
-+
-+ fbdev->instance_count++;
-+
- return 0;
-
- fail:
-@@ -145,6 +225,20 @@ fail:
- return -EFAULT;
- }
-
-+static void set_display_num(struct bcm2708_fb *fb)
-+{
-+ if (fb && fb->fbdev && fb->fbdev->firmware_supports_multifb) {
-+ u32 tmp = fb->display_settings.display_num;
-+
-+ if (rpi_firmware_property(fb->fbdev->fw,
-+ RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM,
-+ &tmp,
-+ sizeof(tmp)))
-+ dev_warn_once(fb->fb.dev,
-+ "Set display number call failed. Old GPU firmware?");
-+ }
-+}
-+
- static int bcm2708_fb_set_bitfields(struct fb_var_screeninfo *var)
- {
- int ret = 0;
-@@ -222,11 +316,11 @@ static int bcm2708_fb_check_var(struct f
- struct fb_info *info)
- {
- /* info input, var output */
-- print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n",
-+ print_debug("%s(%p) %ux%u (%ux%u), %ul, %u\n",
- __func__, info, info->var.xres, info->var.yres,
- info->var.xres_virtual, info->var.yres_virtual,
-- (int)info->screen_size, info->var.bits_per_pixel);
-- print_debug("%s(%p) %dx%d (%dx%d), %d\n", __func__, var, var->xres,
-+ info->screen_size, info->var.bits_per_pixel);
-+ print_debug("%s(%p) %ux%u (%ux%u), %u\n", __func__, var, var->xres,
- var->yres, var->xres_virtual, var->yres_virtual,
- var->bits_per_pixel);
-
-@@ -283,23 +377,96 @@ static int bcm2708_fb_set_par(struct fb_
- .xoffset = info->var.xoffset,
- .yoffset = info->var.yoffset,
- .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
-- .base = 0,
-- .screen_size = 0,
-- .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
-- .pitch = 0,
-+ /* base and screen_size will be initialised later */
-+ .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
-+ /* pitch will be initialised later */
- };
-- int ret;
-+ int ret, image_size;
-+
-
-- print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
-+ print_debug("%s(%p) %dx%d (%dx%d), %d, %d (display %d)\n", __func__,
-+ info,
- info->var.xres, info->var.yres, info->var.xres_virtual,
- info->var.yres_virtual, (int)info->screen_size,
-- info->var.bits_per_pixel);
-+ info->var.bits_per_pixel, value);
-+
-+ /* Need to set the display number to act on first
-+ * Cannot do it in the tag list because on older firmware the call
-+ * will fail and stop the rest of the list being executed.
-+ * We can ignore this call failing as the default at other end is 0
-+ */
-+ set_display_num(fb);
-+
-+ /* Try allocating our own buffer. We can specify all the parameters */
-+ image_size = ((info->var.xres * info->var.yres) *
-+ info->var.bits_per_pixel) >> 3;
-+
-+ if (!fb->fbdev->disable_arm_alloc &&
-+ (image_size != fb->image_size || !fb->dma_addr)) {
-+ if (fb->dma_addr) {
-+ dma_free_coherent(info->device, fb->image_size,
-+ fb->cpuaddr, fb->dma_addr);
-+ fb->image_size = 0;
-+ fb->cpuaddr = NULL;
-+ fb->dma_addr = 0;
-+ }
-+
-+ fb->cpuaddr = dma_alloc_coherent(info->device, image_size,
-+ &fb->dma_addr, GFP_KERNEL);
-+
-+ if (!fb->cpuaddr) {
-+ fb->dma_addr = 0;
-+ fb->fbdev->disable_arm_alloc = true;
-+ } else {
-+ fb->image_size = image_size;
-+ }
-+ }
-+
-+ if (fb->cpuaddr) {
-+ fbinfo.base = fb->dma_addr;
-+ fbinfo.screen_size = image_size;
-+ fbinfo.pitch = (info->var.xres * info->var.bits_per_pixel) >> 3;
-+
-+ ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
-+ sizeof(fbinfo));
-+ if (ret || fbinfo.base != fb->dma_addr) {
-+ /* Firmware either failed, or assigned a different base
-+ * address (ie it doesn't support being passed an FB
-+ * allocation).
-+ * Destroy the allocation, and don't try again.
-+ */
-+ dma_free_coherent(info->device, fb->image_size,
-+ fb->cpuaddr, fb->dma_addr);
-+ fb->image_size = 0;
-+ fb->cpuaddr = NULL;
-+ fb->dma_addr = 0;
-+ fb->fbdev->disable_arm_alloc = true;
-+ }
-+ } else {
-+ /* Our allocation failed - drop into the old scheme of
-+ * allocation by the VPU.
-+ */
-+ ret = -ENOMEM;
-+ }
-
-- ret = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo));
- if (ret) {
-- dev_err(info->device,
-- "Failed to allocate GPU framebuffer (%d)\n", ret);
-- return ret;
-+ /* Old scheme:
-+ * - FRAMEBUFFER_ALLOCATE passes 0 for base and screen_size.
-+ * - GET_PITCH instead of SET_PITCH.
-+ */
-+ fbinfo.base = 0;
-+ fbinfo.screen_size = 0;
-+ fbinfo.tag6.tag = RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH;
-+ fbinfo.pitch = 0;
-+
-+ ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
-+ sizeof(fbinfo));
-+ if (ret) {
-+ dev_err(info->device,
-+ "Failed to allocate GPU framebuffer (%d)\n",
-+ ret);
-+ return ret;
-+ }
- }
-
- if (info->var.bits_per_pixel <= 8)
-@@ -314,9 +481,17 @@ static int bcm2708_fb_set_par(struct fb_
- fb->fb.fix.smem_start = fbinfo.base;
- fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual;
- fb->fb.screen_size = fbinfo.screen_size;
-- if (fb->fb.screen_base)
-- iounmap(fb->fb.screen_base);
-- fb->fb.screen_base = ioremap_wc(fbinfo.base, fb->fb.screen_size);
-+
-+ if (!fb->dma_addr) {
-+ if (fb->fb.screen_base)
-+ iounmap(fb->fb.screen_base);
-+
-+ fb->fb.screen_base = ioremap_wc(fbinfo.base,
-+ fb->fb.screen_size);
-+ } else {
-+ fb->fb.screen_base = fb->cpuaddr;
-+ }
-+
- if (!fb->fb.screen_base) {
- /* the console may currently be locked */
- console_trylock();
-@@ -374,7 +549,10 @@ static int bcm2708_fb_setcolreg(unsigned
- packet->length = regno + 1;
- memcpy(packet->cmap, fb->gpu_cmap,
- sizeof(packet->cmap));
-- ret = rpi_firmware_property(fb->fw,
-+
-+ set_display_num(fb);
-+
-+ ret = rpi_firmware_property(fb->fbdev->fw,
- RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE,
- packet,
- (2 + packet->length) * sizeof(u32));
-@@ -413,8 +591,11 @@ static int bcm2708_fb_blank(int blank_mo
- return -EINVAL;
- }
-
-- ret = rpi_firmware_property(fb->fw, RPI_FIRMWARE_FRAMEBUFFER_BLANK,
-+ set_display_num(fb);
-+
-+ ret = rpi_firmware_property(fb->fbdev->fw, RPI_FIRMWARE_FRAMEBUFFER_BLANK,
- &value, sizeof(value));
-+
- if (ret)
- dev_err(info->device, "%s(%d) failed: %d\n", __func__,
- blank_mode, ret);
-@@ -431,7 +612,7 @@ static int bcm2708_fb_pan_display(struct
- info->var.yoffset = var->yoffset;
- result = bcm2708_fb_set_par(info);
- if (result != 0)
-- pr_err("%s(%d,%d) returns=%d\n", __func__, var->xoffset,
-+ pr_err("%s(%u,%u) returns=%d\n", __func__, var->xoffset,
- var->yoffset, result);
- return result;
- }
-@@ -439,8 +620,9 @@ static int bcm2708_fb_pan_display(struct
- static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src,
- int size)
- {
-- int burst_size = (fb->dma_chan == 0) ? 8 : 2;
-- struct bcm2708_dma_cb *cb = fb->cb_base;
-+ struct bcm2708_fb_dev *fbdev = fb->fbdev;
-+ struct bcm2708_dma_cb *cb = fbdev->cb_base;
-+ int burst_size = (fbdev->dma_chan == 0) ? 8 : 2;
-
- cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH |
- BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH |
-@@ -453,21 +635,27 @@ static void dma_memcpy(struct bcm2708_fb
- cb->pad[1] = 0;
- cb->next = 0;
-
-+ // Not sure what to do if this gets a signal whilst waiting
-+ if (mutex_lock_interruptible(&fbdev->dma_mutex))
-+ return;
-+
- if (size < dma_busy_wait_threshold) {
-- bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
-- bcm_dma_wait_idle(fb->dma_chan_base);
-+ bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
-+ bcm_dma_wait_idle(fbdev->dma_chan_base);
- } else {
-- void __iomem *dma_chan = fb->dma_chan_base;
-+ void __iomem *local_dma_chan = fbdev->dma_chan_base;
-
- cb->info |= BCM2708_DMA_INT_EN;
-- bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
-- while (bcm_dma_is_busy(dma_chan)) {
-- wait_event_interruptible(fb->dma_waitq,
-- !bcm_dma_is_busy(dma_chan));
-+ bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
-+ while (bcm_dma_is_busy(local_dma_chan)) {
-+ wait_event_interruptible(fbdev->dma_waitq,
-+ !bcm_dma_is_busy(local_dma_chan));
- }
-- fb->stats.dma_irqs++;
-+ fbdev->dma_stats.dma_irqs++;
- }
-- fb->stats.dma_copies++;
-+ fbdev->dma_stats.dma_copies++;
-+
-+ mutex_unlock(&fbdev->dma_mutex);
- }
-
- /* address with no aliases */
-@@ -542,10 +730,13 @@ static int bcm2708_ioctl(struct fb_info
-
- switch (cmd) {
- case FBIO_WAITFORVSYNC:
-- ret = rpi_firmware_property(fb->fw,
-+ set_display_num(fb);
-+
-+ ret = rpi_firmware_property(fb->fbdev->fw,
- RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC,
- &dummy, sizeof(dummy));
- break;
-+
- case FBIODMACOPY:
- {
- struct fb_dmacopy ioparam;
-@@ -615,23 +806,22 @@ static int bcm2708_compat_ioctl(struct f
- static void bcm2708_fb_fillrect(struct fb_info *info,
- const struct fb_fillrect *rect)
- {
-- /* (is called) print_debug("bcm2708_fb_fillrect\n"); */
- cfb_fillrect(info, rect);
- }
-
- /* A helper function for configuring dma control block */
- static void set_dma_cb(struct bcm2708_dma_cb *cb,
-- int burst_size,
-- dma_addr_t dst,
-- int dst_stride,
-- dma_addr_t src,
-- int src_stride,
-- int w,
-- int h)
-+ int burst_size,
-+ dma_addr_t dst,
-+ int dst_stride,
-+ dma_addr_t src,
-+ int src_stride,
-+ int w,
-+ int h)
- {
- cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH |
-- BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH |
-- BCM2708_DMA_D_INC | BCM2708_DMA_TDMODE;
-+ BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH |
-+ BCM2708_DMA_D_INC | BCM2708_DMA_TDMODE;
- cb->dst = dst;
- cb->src = src;
- /*
-@@ -649,15 +839,19 @@ static void bcm2708_fb_copyarea(struct f
- const struct fb_copyarea *region)
- {
- struct bcm2708_fb *fb = to_bcm2708(info);
-- struct bcm2708_dma_cb *cb = fb->cb_base;
-+ struct bcm2708_fb_dev *fbdev = fb->fbdev;
-+ struct bcm2708_dma_cb *cb = fbdev->cb_base;
- int bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
-
- /* Channel 0 supports larger bursts and is a bit faster */
-- int burst_size = (fb->dma_chan == 0) ? 8 : 2;
-+ int burst_size = (fbdev->dma_chan == 0) ? 8 : 2;
- int pixels = region->width * region->height;
-
-- /* Fallback to cfb_copyarea() if we don't like something */
-- if (bytes_per_pixel > 4 ||
-+ /* If DMA is currently in use (ie being used on another FB), then
-+ * rather than wait for it to finish, just use the cfb_copyarea
-+ */
-+ if (!mutex_trylock(&fbdev->dma_mutex) ||
-+ bytes_per_pixel > 4 ||
- info->var.xres * info->var.yres > 1920 * 1200 ||
- region->width <= 0 || region->width > info->var.xres ||
- region->height <= 0 || region->height > info->var.yres ||
-@@ -684,8 +878,8 @@ static void bcm2708_fb_copyarea(struct f
- * 1920x1200 resolution at 32bpp pixel depth.
- */
- int y;
-- dma_addr_t control_block_pa = fb->cb_handle;
-- dma_addr_t scratchbuf = fb->cb_handle + 16 * 1024;
-+ dma_addr_t control_block_pa = fbdev->cb_handle;
-+ dma_addr_t scratchbuf = fbdev->cb_handle + 16 * 1024;
- int scanline_size = bytes_per_pixel * region->width;
- int scanlines_per_cb = (64 * 1024 - 16 * 1024) / scanline_size;
-
-@@ -735,10 +929,10 @@ static void bcm2708_fb_copyarea(struct f
- }
- set_dma_cb(cb, burst_size,
- fb->fb_bus_address + dy * fb->fb.fix.line_length +
-- bytes_per_pixel * region->dx,
-+ bytes_per_pixel * region->dx,
- stride,
- fb->fb_bus_address + sy * fb->fb.fix.line_length +
-- bytes_per_pixel * region->sx,
-+ bytes_per_pixel * region->sx,
- stride,
- region->width * bytes_per_pixel,
- region->height);
-@@ -748,32 +942,33 @@ static void bcm2708_fb_copyarea(struct f
- cb->next = 0;
-
- if (pixels < dma_busy_wait_threshold) {
-- bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
-- bcm_dma_wait_idle(fb->dma_chan_base);
-+ bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
-+ bcm_dma_wait_idle(fbdev->dma_chan_base);
- } else {
-- void __iomem *dma_chan = fb->dma_chan_base;
-+ void __iomem *local_dma_chan = fbdev->dma_chan_base;
-
- cb->info |= BCM2708_DMA_INT_EN;
-- bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
-- while (bcm_dma_is_busy(dma_chan)) {
-- wait_event_interruptible(fb->dma_waitq,
-- !bcm_dma_is_busy(dma_chan));
-+ bcm_dma_start(fbdev->dma_chan_base, fbdev->cb_handle);
-+ while (bcm_dma_is_busy(local_dma_chan)) {
-+ wait_event_interruptible(fbdev->dma_waitq,
-+ !bcm_dma_is_busy(local_dma_chan));
- }
-- fb->stats.dma_irqs++;
-+ fbdev->dma_stats.dma_irqs++;
- }
-- fb->stats.dma_copies++;
-+ fbdev->dma_stats.dma_copies++;
-+
-+ mutex_unlock(&fbdev->dma_mutex);
- }
-
- static void bcm2708_fb_imageblit(struct fb_info *info,
- const struct fb_image *image)
- {
-- /* (is called) print_debug("bcm2708_fb_imageblit\n"); */
- cfb_imageblit(info, image);
- }
-
- static irqreturn_t bcm2708_fb_dma_irq(int irq, void *cxt)
- {
-- struct bcm2708_fb *fb = cxt;
-+ struct bcm2708_fb_dev *fbdev = cxt;
-
- /* FIXME: should read status register to check if this is
- * actually interrupting us or not, in case this interrupt
-@@ -783,9 +978,9 @@ static irqreturn_t bcm2708_fb_dma_irq(in
- */
-
- /* acknowledge the interrupt */
-- writel(BCM2708_DMA_INT, fb->dma_chan_base + BCM2708_DMA_CS);
-+ writel(BCM2708_DMA_INT, fbdev->dma_chan_base + BCM2708_DMA_CS);
-
-- wake_up(&fb->dma_waitq);
-+ wake_up(&fbdev->dma_waitq);
- return IRQ_HANDLED;
- }
-
-@@ -821,11 +1016,23 @@ static int bcm2708_fb_register(struct bc
- fb->fb.fix.ywrapstep = 0;
- fb->fb.fix.accel = FB_ACCEL_NONE;
-
-- fb->fb.var.xres = fbwidth;
-- fb->fb.var.yres = fbheight;
-- fb->fb.var.xres_virtual = fbwidth;
-- fb->fb.var.yres_virtual = fbheight;
-- fb->fb.var.bits_per_pixel = fbdepth;
-+ /* If we have data from the VC4 on FB's, use that, otherwise use the
-+ * module parameters
-+ */
-+ if (fb->display_settings.width) {
-+ fb->fb.var.xres = fb->display_settings.width;
-+ fb->fb.var.yres = fb->display_settings.height;
-+ fb->fb.var.xres_virtual = fb->fb.var.xres;
-+ fb->fb.var.yres_virtual = fb->fb.var.yres;
-+ fb->fb.var.bits_per_pixel = fb->display_settings.depth;
-+ } else {
-+ fb->fb.var.xres = fbwidth;
-+ fb->fb.var.yres = fbheight;
-+ fb->fb.var.xres_virtual = fbwidth;
-+ fb->fb.var.yres_virtual = fbheight;
-+ fb->fb.var.bits_per_pixel = fbdepth;
-+ }
-+
- fb->fb.var.vmode = FB_VMODE_NONINTERLACED;
- fb->fb.var.activate = FB_ACTIVATE_NOW;
- fb->fb.var.nonstd = 0;
-@@ -841,26 +1048,23 @@ static int bcm2708_fb_register(struct bc
- fb->fb.monspecs.dclkmax = 100000000;
-
- bcm2708_fb_set_bitfields(&fb->fb.var);
-- init_waitqueue_head(&fb->dma_waitq);
-
- /*
- * Allocate colourmap.
- */
--
- fb_set_var(&fb->fb, &fb->fb.var);
-+
- ret = bcm2708_fb_set_par(&fb->fb);
-+
- if (ret)
- return ret;
-
-- print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n",
-- fbwidth, fbheight, fbdepth, fbswap);
--
- ret = register_framebuffer(&fb->fb);
-- print_debug("BCM2708FB: register framebuffer (%d)\n", ret);
-+
- if (ret == 0)
- goto out;
-
-- print_debug("BCM2708FB: cannot register framebuffer (%d)\n", ret);
-+ dev_warn(fb->fb.dev, "Unable to register framebuffer (%d)\n", ret);
- out:
- return ret;
- }
-@@ -869,10 +1073,18 @@ static int bcm2708_fb_probe(struct platf
- {
- struct device_node *fw_np;
- struct rpi_firmware *fw;
-- struct bcm2708_fb *fb;
-- int ret;
-+ int ret, i;
-+ u32 num_displays;
-+ struct bcm2708_fb_dev *fbdev;
-+ struct { u32 base, length; } gpu_mem;
-+
-+ fbdev = devm_kzalloc(&dev->dev, sizeof(*fbdev), GFP_KERNEL);
-+
-+ if (!fbdev)
-+ return -ENOMEM;
-
- fw_np = of_parse_phandle(dev->dev.of_node, "firmware", 0);
-+
- /* Remove comment when booting without Device Tree is no longer supported
- * if (!fw_np) {
- * dev_err(&dev->dev, "Missing firmware node\n");
-@@ -880,90 +1092,154 @@ static int bcm2708_fb_probe(struct platf
- * }
- */
- fw = rpi_firmware_get(fw_np);
-+ fbdev->fw = fw;
-+
- if (!fw)
- return -EPROBE_DEFER;
-
-- fb = kzalloc(sizeof(*fb), GFP_KERNEL);
-- if (!fb) {
-- ret = -ENOMEM;
-- goto free_region;
-+ ret = rpi_firmware_property(fw,
-+ RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
-+ &num_displays, sizeof(u32));
-+
-+ /* If we fail to get the number of displays, or it returns 0, then
-+ * assume old firmware that doesn't have the mailbox call, so just
-+ * set one display
-+ */
-+ if (ret || num_displays == 0) {
-+ num_displays = 1;
-+ dev_err(&dev->dev,
-+ "Unable to determine number of FB's. Assuming 1\n");
-+ ret = 0;
-+ } else {
-+ fbdev->firmware_supports_multifb = 1;
- }
-
-- fb->fw = fw;
-- bcm2708_fb_debugfs_init(fb);
-+ if (num_displays > MAX_FRAMEBUFFERS) {
-+ dev_warn(&dev->dev,
-+ "More displays reported from firmware than supported in driver (%u vs %u)",
-+ num_displays, MAX_FRAMEBUFFERS);
-+ num_displays = MAX_FRAMEBUFFERS;
-+ }
-
-- fb->cb_base = dma_alloc_writecombine(&dev->dev, SZ_64K,
-- &fb->cb_handle, GFP_KERNEL);
-- if (!fb->cb_base) {
-+ dev_info(&dev->dev, "FB found %d display(s)\n", num_displays);
-+
-+ /* Set up the DMA information. Note we have just one set of DMA
-+ * parameters to work with all the FB's so requires synchronising when
-+ * being used
-+ */
-+
-+ mutex_init(&fbdev->dma_mutex);
-+
-+ fbdev->cb_base = dma_alloc_writecombine(&dev->dev, SZ_64K,
-+ &fbdev->cb_handle,
-+ GFP_KERNEL);
-+ if (!fbdev->cb_base) {
- dev_err(&dev->dev, "cannot allocate DMA CBs\n");
- ret = -ENOMEM;
- goto free_fb;
- }
-
-- pr_info("BCM2708FB: allocated DMA memory %pad\n", &fb->cb_handle);
--
- ret = bcm_dma_chan_alloc(BCM_DMA_FEATURE_BULK,
-- &fb->dma_chan_base, &fb->dma_irq);
-+ &fbdev->dma_chan_base,
-+ &fbdev->dma_irq);
- if (ret < 0) {
-- dev_err(&dev->dev, "couldn't allocate a DMA channel\n");
-+ dev_err(&dev->dev, "Couldn't allocate a DMA channel\n");
- goto free_cb;
- }
-- fb->dma_chan = ret;
-+ fbdev->dma_chan = ret;
-
-- ret = request_irq(fb->dma_irq, bcm2708_fb_dma_irq,
-- 0, "bcm2708_fb dma", fb);
-+ ret = request_irq(fbdev->dma_irq, bcm2708_fb_dma_irq,
-+ 0, "bcm2708_fb DMA", fbdev);
- if (ret) {
-- pr_err("%s: failed to request DMA irq\n", __func__);
-+ dev_err(&dev->dev,
-+ "Failed to request DMA irq\n");
- goto free_dma_chan;
- }
-
-- pr_info("BCM2708FB: allocated DMA channel %d\n", fb->dma_chan);
-+ rpi_firmware_property(fbdev->fw,
-+ RPI_FIRMWARE_GET_VC_MEMORY,
-+ &gpu_mem, sizeof(gpu_mem));
-+
-+ for (i = 0; i < num_displays; i++) {
-+ struct bcm2708_fb *fb = &fbdev->displays[i];
-+
-+ fb->display_settings.display_num = i;
-+ fb->dev = dev;
-+ fb->fb.device = &dev->dev;
-+ fb->fbdev = fbdev;
-+
-+ fb->gpu.base = gpu_mem.base;
-+ fb->gpu.length = gpu_mem.length;
-+
-+ if (fbdev->firmware_supports_multifb) {
-+ ret = rpi_firmware_property(fw,
-+ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS,
-+ &fb->display_settings,
-+ GET_DISPLAY_SETTINGS_PAYLOAD_SIZE);
-+ } else {
-+ memset(&fb->display_settings, 0,
-+ sizeof(fb->display_settings));
-+ }
-+
-+ ret = bcm2708_fb_register(fb);
-
-- fb->dev = dev;
-- fb->fb.device = &dev->dev;
-+ if (ret == 0) {
-+ bcm2708_fb_debugfs_init(fb);
-
-- /* failure here isn't fatal, but we'll fail in vc_mem_copy if
-- * fb->gpu is not valid
-- */
-- rpi_firmware_property(fb->fw, RPI_FIRMWARE_GET_VC_MEMORY, &fb->gpu,
-- sizeof(fb->gpu));
-+ fbdev->num_displays++;
-
-- ret = bcm2708_fb_register(fb);
-- if (ret == 0) {
-- platform_set_drvdata(dev, fb);
-- goto out;
-+ dev_info(&dev->dev,
-+ "Registered framebuffer for display %u, size %ux%u\n",
-+ fb->display_settings.display_num,
-+ fb->fb.var.xres,
-+ fb->fb.var.yres);
-+ } else {
-+ // Use this to flag if this FB entry is in use.
-+ fb->fbdev = NULL;
-+ }
-+ }
-+
-+ // Did we actually successfully create any FB's?
-+ if (fbdev->num_displays) {
-+ init_waitqueue_head(&fbdev->dma_waitq);
-+ platform_set_drvdata(dev, fbdev);
-+ return ret;
- }
-
- free_dma_chan:
-- bcm_dma_chan_free(fb->dma_chan);
-+ bcm_dma_chan_free(fbdev->dma_chan);
- free_cb:
-- dma_free_writecombine(&dev->dev, SZ_64K, fb->cb_base, fb->cb_handle);
-+ dma_free_writecombine(&dev->dev, SZ_64K, fbdev->cb_base,
-+ fbdev->cb_handle);
- free_fb:
-- kfree(fb);
--free_region:
- dev_err(&dev->dev, "probe failed, err %d\n", ret);
--out:
-+
- return ret;
- }
-
- static int bcm2708_fb_remove(struct platform_device *dev)
- {
-- struct bcm2708_fb *fb = platform_get_drvdata(dev);
-+ struct bcm2708_fb_dev *fbdev = platform_get_drvdata(dev);
-+ int i;
-
- platform_set_drvdata(dev, NULL);
-
-- if (fb->fb.screen_base)
-- iounmap(fb->fb.screen_base);
-- unregister_framebuffer(&fb->fb);
--
-- dma_free_writecombine(&dev->dev, SZ_64K, fb->cb_base, fb->cb_handle);
-- bcm_dma_chan_free(fb->dma_chan);
--
-- bcm2708_fb_debugfs_deinit(fb);
-+ for (i = 0; i < fbdev->num_displays; i++) {
-+ if (fbdev->displays[i].fb.screen_base)
-+ iounmap(fbdev->displays[i].fb.screen_base);
-+
-+ if (fbdev->displays[i].fbdev) {
-+ unregister_framebuffer(&fbdev->displays[i].fb);
-+ bcm2708_fb_debugfs_deinit(&fbdev->displays[i]);
-+ }
-+ }
-
-- free_irq(fb->dma_irq, fb);
-+ dma_free_writecombine(&dev->dev, SZ_64K, fbdev->cb_base,
-+ fbdev->cb_handle);
-+ bcm_dma_chan_free(fbdev->dma_chan);
-+ free_irq(fbdev->dma_irq, fbdev);
-
-- kfree(fb);
-+ mutex_destroy(&fbdev->dma_mutex);
-
- return 0;
- }
-@@ -978,10 +1254,10 @@ static struct platform_driver bcm2708_fb
- .probe = bcm2708_fb_probe,
- .remove = bcm2708_fb_remove,
- .driver = {
-- .name = DRIVER_NAME,
-- .owner = THIS_MODULE,
-- .of_match_table = bcm2708_fb_of_match_table,
-- },
-+ .name = DRIVER_NAME,
-+ .owner = THIS_MODULE,
-+ .of_match_table = bcm2708_fb_of_match_table,
-+ },
- };
-
- static int __init bcm2708_fb_init(void)
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -138,9 +138,11 @@ enum rpi_firmware_property_tag {
- RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
- RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
- RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
-+ RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH = 0x00048008,
- RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
- RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
- RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
-+
- RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
- RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020,
- RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
-@@ -159,6 +161,8 @@ enum rpi_firmware_property_tag {
- RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,
- };
-
-+#define GET_DISPLAY_SETTINGS_PAYLOAD_SIZE 64
-+
- #if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE)
- int rpi_firmware_property(struct rpi_firmware *fw,
- u32 tag, void *data, size_t len);
--- /dev/null
+From 2965d0b1d0b91c199d7468aa89874a9b462fd924 Mon Sep 17 00:00:00 2001
+From: Martin Sperl <kernel@martin.sperl.org>
+Date: Sun, 12 May 2019 16:17:08 +0000
+Subject: [PATCH 637/725] spi: devicetree: add overlays for spi 3 to 6
+
+Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
+---
+ arch/arm/boot/dts/overlays/Makefile | 8 ++
+ arch/arm/boot/dts/overlays/README | 104 ++++++++++++++++++
+ .../boot/dts/overlays/spi3-1cs-overlay.dts | 44 ++++++++
+ .../boot/dts/overlays/spi3-2cs-overlay.dts | 56 ++++++++++
+ .../boot/dts/overlays/spi4-1cs-overlay.dts | 44 ++++++++
+ .../boot/dts/overlays/spi4-2cs-overlay.dts | 56 ++++++++++
+ .../boot/dts/overlays/spi5-1cs-overlay.dts | 44 ++++++++
+ .../boot/dts/overlays/spi5-2cs-overlay.dts | 56 ++++++++++
+ .../boot/dts/overlays/spi6-1cs-overlay.dts | 44 ++++++++
+ .../boot/dts/overlays/spi6-2cs-overlay.dts | 56 ++++++++++
+ 10 files changed, 512 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/spi3-1cs-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/spi3-2cs-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/spi4-1cs-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/spi4-2cs-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/spi5-1cs-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/spi5-2cs-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/spi6-1cs-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/spi6-2cs-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -144,6 +144,14 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ spi2-1cs.dtbo \
+ spi2-2cs.dtbo \
+ spi2-3cs.dtbo \
++ spi3-1cs.dtbo \
++ spi3-2cs.dtbo \
++ spi4-1cs.dtbo \
++ spi4-2cs.dtbo \
++ spi5-1cs.dtbo \
++ spi5-2cs.dtbo \
++ spi6-1cs.dtbo \
++ spi6-2cs.dtbo \
+ ssd1306.dtbo \
+ superaudioboard.dtbo \
+ sx150x.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2085,6 +2085,110 @@ Params: cs0_pin GPIO pin
+ is 'okay' or enabled).
+
+
++Name: spi3-1cs
++Info: Enables spi3 with a single chip select (CS) line and associated spidev
++ dev node. The gpio pin number for the CS line and spidev device node
++ creation are configurable.
++Load: dtoverlay=spi3-1cs,<param>=<val>
++Params: cs0_pin GPIO pin for CS0 (default 0 - BCM SPI3_CE0).
++ cs0_spidev Set to 'off' to prevent the creation of a
++ userspace device node /dev/spidev3.0 (default
++ is 'on' or enabled).
++
++
++Name: spi3-2cs
++Info: Enables spi3 with two chip select (CS) lines and associated spidev
++ dev nodes. The gpio pin numbers for the CS lines and spidev device node
++ creation are configurable.
++Load: dtoverlay=spi3-2cs,<param>=<val>
++Params: cs0_pin GPIO pin for CS0 (default 0 - BCM SPI3_CE0).
++ cs1_pin GPIO pin for CS1 (default 24 - BCM SPI3_CE1).
++ cs0_spidev Set to 'off' to prevent the creation of a
++ userspace device node /dev/spidev3.0 (default
++ is 'on' or enabled).
++ cs1_spidev Set to 'off' to prevent the creation of a
++ userspace device node /dev/spidev3.1 (default
++ is 'on' or enabled).
++
++
++Name: spi4-1cs
++Info: Enables spi4 with a single chip select (CS) line and associated spidev
++ dev node. The gpio pin number for the CS line and spidev device node
++ creation are configurable.
++Load: dtoverlay=spi4-1cs,<param>=<val>
++Params: cs0_pin GPIO pin for CS0 (default 4 - BCM SPI4_CE0).
++ cs0_spidev Set to 'off' to prevent the creation of a
++ userspace device node /dev/spidev4.0 (default
++ is 'on' or enabled).
++
++
++Name: spi4-2cs
++Info: Enables spi4 with two chip select (CS) lines and associated spidev
++ dev nodes. The gpio pin numbers for the CS lines and spidev device node
++ creation are configurable.
++Load: dtoverlay=spi4-2cs,<param>=<val>
++Params: cs0_pin GPIO pin for CS0 (default 4 - BCM SPI4_CE0).
++ cs1_pin GPIO pin for CS1 (default 25 - BCM SPI4_CE1).
++ cs0_spidev Set to 'off' to prevent the creation of a
++ userspace device node /dev/spidev4.0 (default
++ is 'on' or enabled).
++ cs1_spidev Set to 'off' to prevent the creation of a
++ userspace device node /dev/spidev4.1 (default
++ is 'on' or enabled).
++
++
++Name: spi5-1cs
++Info: Enables spi5 with a single chip select (CS) line and associated spidev
++ dev node. The gpio pin numbers for the CS lines and spidev device node
++ creation are configurable.
++Load: dtoverlay=spi5-1cs,<param>=<val>
++Params: cs0_pin GPIO pin for CS0 (default 12 - BCM SPI5_CE0).
++ cs0_spidev Set to 'off' to prevent the creation of a
++ userspace device node /dev/spidev5.0 (default
++ is 'on' or enabled).
++
++
++Name: spi5-2cs
++Info: Enables spi5 with two chip select (CS) lines and associated spidev
++ dev nodes. The gpio pin numbers for the CS lines and spidev device node
++ creation are configurable.
++Load: dtoverlay=spi5-2cs,<param>=<val>
++Params: cs0_pin GPIO pin for CS0 (default 12 - BCM SPI5_CE0).
++ cs1_pin GPIO pin for CS1 (default 26 - BCM SPI5_CE1).
++ cs0_spidev Set to 'off' to prevent the creation of a
++ userspace device node /dev/spidev5.0 (default
++ is 'on' or enabled).
++ cs1_spidev Set to 'off' to prevent the creation of a
++ userspace device node /dev/spidev5.1 (default
++ is 'on' or enabled).
++
++
++Name: spi6-1cs
++Info: Enables spi6 with a single chip select (CS) line and associated spidev
++ dev node. The gpio pin number for the CS line and spidev device node
++ creation are configurable.
++Load: dtoverlay=spi6-1cs,<param>=<val>
++Params: cs0_pin GPIO pin for CS0 (default 18 - BCM SPI6_CE0).
++ cs0_spidev Set to 'off' to prevent the creation of a
++ userspace device node /dev/spidev6.0 (default
++ is 'on' or enabled).
++
++
++Name: spi6-2cs
++Info: Enables spi6 with two chip select (CS) lines and associated spidev
++ dev nodes. The gpio pin numbers for the CS lines and spidev device node
++ creation are configurable.
++Load: dtoverlay=spi6-2cs,<param>=<val>
++Params: cs0_pin GPIO pin for CS0 (default 18 - BCM SPI6_CE0).
++ cs1_pin GPIO pin for CS1 (default 27 - BCM SPI6_CE1).
++ cs0_spidev Set to 'off' to prevent the creation of a
++ userspace device node /dev/spidev6.0 (default
++ is 'on' or enabled).
++ cs1_spidev Set to 'off' to prevent the creation of a
++ userspace device node /dev/spidev6.1 (default
++ is 'on' or enabled).
++
++
+ Name: ssd1306
+ Info: Overlay for activation of SSD1306 over I2C OLED display framebuffer.
+ Load: dtoverlay=ssd1306,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi3-1cs-overlay.dts
+@@ -0,0 +1,44 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&spi3_cs_pins>;
++ frag0: __overlay__ {
++ brcm,pins = <0>;
++ brcm,function = <1>; /* output */
++ };
++ };
++
++ fragment@1 {
++ target = <&spi3>;
++ frag1: __overlay__ {
++ /* needed to avoid dtc warning */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi3_pins &spi3_cs_pins>;
++ cs-gpios = <&gpio 0 1>;
++ status = "okay";
++
++ spidev3_0: spidev@0 {
++ compatible = "spidev";
++ reg = <0>; /* CE0 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ status = "okay";
++ };
++ };
++ };
++
++ __overrides__ {
++ cs0_pin = <&frag0>,"brcm,pins:0",
++ <&frag1>,"cs-gpios:4";
++ cs0_spidev = <&spidev3_0>,"status";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi3-2cs-overlay.dts
+@@ -0,0 +1,56 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&spi3_cs_pins>;
++ frag0: __overlay__ {
++ brcm,pins = <0 24>;
++ brcm,function = <1>; /* output */
++ };
++ };
++
++ fragment@1 {
++ target = <&spi3>;
++ frag1: __overlay__ {
++ /* needed to avoid dtc warning */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi3_pins &spi3_cs_pins>;
++ cs-gpios = <&gpio 0 1>, <&gpio 24 1>;
++ status = "okay";
++
++ spidev3_0: spidev@0 {
++ compatible = "spidev";
++ reg = <0>; /* CE0 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ status = "okay";
++ };
++
++ spidev3_1: spidev@1 {
++ compatible = "spidev";
++ reg = <1>; /* CE1 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ status = "okay";
++ };
++ };
++ };
++
++ __overrides__ {
++ cs0_pin = <&frag0>,"brcm,pins:0",
++ <&frag1>,"cs-gpios:4";
++ cs1_pin = <&frag0>,"brcm,pins:4",
++ <&frag1>,"cs-gpios:16";
++ cs0_spidev = <&spidev3_0>,"status";
++ cs1_spidev = <&spidev3_1>,"status";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi4-1cs-overlay.dts
+@@ -0,0 +1,44 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&spi4_cs_pins>;
++ frag0: __overlay__ {
++ brcm,pins = <4>;
++ brcm,function = <1>; /* output */
++ };
++ };
++
++ fragment@1 {
++ target = <&spi4>;
++ frag1: __overlay__ {
++ /* needed to avoid dtc warning */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi4_pins &spi4_cs_pins>;
++ cs-gpios = <&gpio 4 1>;
++ status = "okay";
++
++ spidev4_0: spidev@0 {
++ compatible = "spidev";
++ reg = <0>; /* CE0 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ status = "okay";
++ };
++ };
++ };
++
++ __overrides__ {
++ cs0_pin = <&frag0>,"brcm,pins:0",
++ <&frag1>,"cs-gpios:4";
++ cs0_spidev = <&spidev4_0>,"status";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi4-2cs-overlay.dts
+@@ -0,0 +1,56 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&spi4_cs_pins>;
++ frag0: __overlay__ {
++ brcm,pins = <4 25>;
++ brcm,function = <1>; /* output */
++ };
++ };
++
++ fragment@1 {
++ target = <&spi4>;
++ frag1: __overlay__ {
++ /* needed to avoid dtc warning */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi4_pins &spi4_cs_pins>;
++ cs-gpios = <&gpio 4 1>, <&gpio 25 1>;
++ status = "okay";
++
++ spidev4_0: spidev@0 {
++ compatible = "spidev";
++ reg = <0>; /* CE0 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ status = "okay";
++ };
++
++ spidev4_1: spidev@1 {
++ compatible = "spidev";
++ reg = <1>; /* CE1 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ status = "okay";
++ };
++ };
++ };
++
++ __overrides__ {
++ cs0_pin = <&frag0>,"brcm,pins:0",
++ <&frag1>,"cs-gpios:4";
++ cs1_pin = <&frag0>,"brcm,pins:4",
++ <&frag1>,"cs-gpios:16";
++ cs0_spidev = <&spidev4_0>,"status";
++ cs1_spidev = <&spidev4_1>,"status";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi5-1cs-overlay.dts
+@@ -0,0 +1,44 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&spi5_cs_pins>;
++ frag0: __overlay__ {
++ brcm,pins = <12>;
++ brcm,function = <1>; /* output */
++ };
++ };
++
++ fragment@1 {
++ target = <&spi5>;
++ frag1: __overlay__ {
++ /* needed to avoid dtc warning */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi5_pins &spi5_cs_pins>;
++ cs-gpios = <&gpio 12 1>;
++ status = "okay";
++
++ spidev5_0: spidev@0 {
++ compatible = "spidev";
++ reg = <0>; /* CE0 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ status = "okay";
++ };
++ };
++ };
++
++ __overrides__ {
++ cs0_pin = <&frag0>,"brcm,pins:0",
++ <&frag1>,"cs-gpios:4";
++ cs0_spidev = <&spidev5_0>,"status";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi5-2cs-overlay.dts
+@@ -0,0 +1,56 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&spi5_cs_pins>;
++ frag0: __overlay__ {
++ brcm,pins = <12 26>;
++ brcm,function = <1>; /* output */
++ };
++ };
++
++ fragment@1 {
++ target = <&spi5>;
++ frag1: __overlay__ {
++ /* needed to avoid dtc warning */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi5_pins &spi5_cs_pins>;
++ cs-gpios = <&gpio 12 1>, <&gpio 26 1>;
++ status = "okay";
++
++ spidev5_0: spidev@0 {
++ compatible = "spidev";
++ reg = <0>; /* CE0 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ status = "okay";
++ };
++
++ spidev5_1: spidev@1 {
++ compatible = "spidev";
++ reg = <1>; /* CE1 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ status = "okay";
++ };
++ };
++ };
++
++ __overrides__ {
++ cs0_pin = <&frag0>,"brcm,pins:0",
++ <&frag1>,"cs-gpios:4";
++ cs1_pin = <&frag0>,"brcm,pins:4",
++ <&frag1>,"cs-gpios:16";
++ cs0_spidev = <&spidev5_0>,"status";
++ cs1_spidev = <&spidev5_1>,"status";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi6-1cs-overlay.dts
+@@ -0,0 +1,44 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&spi6_cs_pins>;
++ frag0: __overlay__ {
++ brcm,pins = <18>;
++ brcm,function = <1>; /* output */
++ };
++ };
++
++ fragment@1 {
++ target = <&spi6>;
++ frag1: __overlay__ {
++ /* needed to avoid dtc warning */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi6_pins &spi6_cs_pins>;
++ cs-gpios = <&gpio 18 1>;
++ status = "okay";
++
++ spidev6_0: spidev@0 {
++ compatible = "spidev";
++ reg = <0>; /* CE0 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ status = "okay";
++ };
++ };
++ };
++
++ __overrides__ {
++ cs0_pin = <&frag0>,"brcm,pins:0",
++ <&frag1>,"cs-gpios:4";
++ cs0_spidev = <&spidev6_0>,"status";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi6-2cs-overlay.dts
+@@ -0,0 +1,56 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++ compatible = "brcm,bcm2838";
++
++ fragment@0 {
++ target = <&spi6_cs_pins>;
++ frag0: __overlay__ {
++ brcm,pins = <18 27>;
++ brcm,function = <1>; /* output */
++ };
++ };
++
++ fragment@1 {
++ target = <&spi6>;
++ frag1: __overlay__ {
++ /* needed to avoid dtc warning */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi6_pins &spi6_cs_pins>;
++ cs-gpios = <&gpio 18 1>, <&gpio 27 1>;
++ status = "okay";
++
++ spidev6_0: spidev@0 {
++ compatible = "spidev";
++ reg = <0>; /* CE0 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ status = "okay";
++ };
++
++ spidev6_1: spidev@1 {
++ compatible = "spidev";
++ reg = <1>; /* CE1 */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ spi-max-frequency = <125000000>;
++ status = "okay";
++ };
++ };
++ };
++
++ __overrides__ {
++ cs0_pin = <&frag0>,"brcm,pins:0",
++ <&frag1>,"cs-gpios:4";
++ cs1_pin = <&frag0>,"brcm,pins:4",
++ <&frag1>,"cs-gpios:16";
++ cs0_spidev = <&spidev6_0>,"status";
++ cs1_spidev = <&spidev6_1>,"status";
++ };
++};
+++ /dev/null
-From ba24f07c814a4d0527fa5821834cded70ac705be Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <wahrenst@gmx.net>
-Date: Sun, 19 May 2019 12:26:21 +0200
-Subject: [PATCH 638/703] ARM: dts: bcm283x: Move BCM2835/6/7 specific to
- bcm2835-common.dtsi
-
-We want all common BCM2835/6/7/8 functions in bcm283x.dtsi and all
-BCM2835/6/7 specific in the new bcm2835-common.dtsi.
-
-Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
----
- arch/arm/boot/dts/bcm2835-common.dtsi | 53 +++++++++++++++++++++++++++
- arch/arm/boot/dts/bcm2835.dtsi | 1 +
- arch/arm/boot/dts/bcm2836.dtsi | 1 +
- arch/arm/boot/dts/bcm2837.dtsi | 1 +
- arch/arm/boot/dts/bcm283x.dtsi | 43 +---------------------
- 5 files changed, 57 insertions(+), 42 deletions(-)
- create mode 100644 arch/arm/boot/dts/bcm2835-common.dtsi
-
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2835-common.dtsi
-@@ -0,0 +1,53 @@
-+// SPDX-License-Identifier: GPL-2.0
-+
-+/* This include file covers the common peripherals and configuration between
-+ * bcm2835, bcm2836 and bcm2837 implementations.
-+ */
-+
-+/ {
-+ soc {
-+ timer@7e003000 {
-+ compatible = "brcm,bcm2835-system-timer";
-+ reg = <0x7e003000 0x1000>;
-+ interrupts = <1 0>, <1 1>, <1 2>, <1 3>;
-+ /* This could be a reference to BCM2835_CLOCK_TIMER,
-+ * but we don't have the driver using the common clock
-+ * support yet.
-+ */
-+ clock-frequency = <1000000>;
-+ };
-+
-+ intc: interrupt-controller@7e00b200 {
-+ compatible = "brcm,bcm2835-armctrl-ic";
-+ reg = <0x7e00b200 0x200>;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-+
-+ thermal: thermal@7e212000 {
-+ compatible = "brcm,bcm2835-thermal";
-+ reg = <0x7e212000 0x8>;
-+ clocks = <&clocks BCM2835_CLOCK_TSENS>;
-+ #thermal-sensor-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ v3d: v3d@7ec00000 {
-+ compatible = "brcm,bcm2835-v3d";
-+ reg = <0x7ec00000 0x1000>;
-+ interrupts = <1 10>;
-+ };
-+ };
-+};
-+
-+&gpio {
-+ i2c_slave_gpio18: i2c_slave_gpio18 {
-+ brcm,pins = <18 19 20 21>;
-+ brcm,function = <BCM2835_FSEL_ALT3>;
-+ };
-+
-+ jtag_gpio4: jtag_gpio4 {
-+ brcm,pins = <4 5 6 12 13>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+};
---- a/arch/arm/boot/dts/bcm2835.dtsi
-+++ b/arch/arm/boot/dts/bcm2835.dtsi
-@@ -1,5 +1,6 @@
- // SPDX-License-Identifier: GPL-2.0
- #include "bcm283x.dtsi"
-+#include "bcm2835-common.dtsi"
-
- / {
- compatible = "brcm,bcm2835";
---- a/arch/arm/boot/dts/bcm2836.dtsi
-+++ b/arch/arm/boot/dts/bcm2836.dtsi
-@@ -1,5 +1,6 @@
- // SPDX-License-Identifier: GPL-2.0
- #include "bcm283x.dtsi"
-+#include "bcm2835-common.dtsi"
-
- / {
- compatible = "brcm,bcm2836";
---- a/arch/arm/boot/dts/bcm2837.dtsi
-+++ b/arch/arm/boot/dts/bcm2837.dtsi
-@@ -1,4 +1,5 @@
- #include "bcm283x.dtsi"
-+#include "bcm2835-common.dtsi"
-
- / {
- compatible = "brcm,bcm2837";
---- a/arch/arm/boot/dts/bcm283x.dtsi
-+++ b/arch/arm/boot/dts/bcm283x.dtsi
-@@ -55,17 +55,6 @@
- #address-cells = <1>;
- #size-cells = <1>;
-
-- timer@7e003000 {
-- compatible = "brcm,bcm2835-system-timer";
-- reg = <0x7e003000 0x1000>;
-- interrupts = <1 0>, <1 1>, <1 2>, <1 3>;
-- /* This could be a reference to BCM2835_CLOCK_TIMER,
-- * but we don't have the driver using the common clock
-- * support yet.
-- */
-- clock-frequency = <1000000>;
-- };
--
- txp@7e004000 {
- compatible = "brcm,bcm2835-txp";
- reg = <0x7e004000 0x20>;
-@@ -113,13 +102,6 @@
- brcm,dma-channel-mask = <0x7f35>;
- };
-
-- intc: interrupt-controller@7e00b200 {
-- compatible = "brcm,bcm2835-armctrl-ic";
-- reg = <0x7e00b200 0x200>;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
--
- watchdog@7e100000 {
- compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
- #power-domain-cells = <1>;
-@@ -183,8 +165,7 @@
- interrupt-controller;
- #interrupt-cells = <2>;
-
-- /* Defines pin muxing groups according to
-- * BCM2835-ARM-Peripherals.pdf page 102.
-+ /* Defines common pin muxing groups
- *
- * While each pin can have its mux selected
- * for various functions individually, some
-@@ -262,15 +243,7 @@
- brcm,pins = <44 45>;
- brcm,function = <BCM2835_FSEL_ALT2>;
- };
-- i2c_slave_gpio18: i2c_slave_gpio18 {
-- brcm,pins = <18 19 20 21>;
-- brcm,function = <BCM2835_FSEL_ALT3>;
-- };
-
-- jtag_gpio4: jtag_gpio4 {
-- brcm,pins = <4 5 6 12 13>;
-- brcm,function = <BCM2835_FSEL_ALT5>;
-- };
- jtag_gpio22: jtag_gpio22 {
- brcm,pins = <22 23 24 25 26 27>;
- brcm,function = <BCM2835_FSEL_ALT4>;
-@@ -487,14 +460,6 @@
-
- };
-
-- thermal: thermal@7e212000 {
-- compatible = "brcm,bcm2835-thermal";
-- reg = <0x7e212000 0x8>;
-- clocks = <&clocks BCM2835_CLOCK_TSENS>;
-- #thermal-sensor-cells = <0>;
-- status = "disabled";
-- };
--
- aux: aux@7e215000 {
- compatible = "brcm,bcm2835-aux";
- #clock-cells = <1>;
-@@ -660,12 +625,6 @@
- phy-names = "usb2-phy";
- };
-
-- v3d: v3d@7ec00000 {
-- compatible = "brcm,bcm2835-v3d";
-- reg = <0x7ec00000 0x1000>;
-- interrupts = <1 10>;
-- };
--
- vc4: gpu {
- compatible = "brcm,bcm2835-vc4";
- };
--- /dev/null
+From 8ebd5065611e9ffc833d7da8018c787a533b1231 Mon Sep 17 00:00:00 2001
+From: Tim Gover <tim.gover@raspberrypi.org>
+Date: Tue, 22 Jan 2019 10:49:41 +0000
+Subject: [PATCH 638/725] overlays: Add the spi-gpio40-45 overlay
+
+The 2711 B0 boot EEPROM is programmed via SPI0 on GPIO
+pins 40-43 CS0. Add a device tree overlay to optionally
+change the SPI0 pinmux from the external GPIO pins to
+the boot EEPROM pins.
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 6 ++++
+ .../dts/overlays/spi-gpio40-45-overlay.dts | 36 +++++++++++++++++++
+ 3 files changed, 43 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/spi-gpio40-45-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -135,6 +135,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ smi-dev.dtbo \
+ smi-nand.dtbo \
+ spi-gpio35-39.dtbo \
++ spi-gpio40-45.dtbo \
+ spi-rtc.dtbo \
+ spi0-cs.dtbo \
+ spi0-hw-cs.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1967,6 +1967,12 @@ Load: dtoverlay=spi-gpio35-39
+ Params: <None>
+
+
++Name: spi-gpio40-45
++Info: Move SPI function block to GPIOs 40 to 45
++Load: dtoverlay=spi-gpio40-45
++Params: <None>
++
++
+ Name: spi-rtc
+ Info: Adds support for a number of SPI Real Time Clock devices
+ Load: dtoverlay=spi-rtc,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi-gpio40-45-overlay.dts
+@@ -0,0 +1,36 @@
++/*
++ * Boot EEPROM overlay
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "brcm,bcm2835";
++
++ fragment@0 {
++ target = <&spi0>;
++ __overlay__ {
++ cs-gpios = <&gpio 43 1>, <&gpio 44 1>, <&gpio 45 1>;
++ status = "okay";
++ };
++ };
++
++ fragment@1 {
++ target = <&spi0_cs_pins>;
++ __overlay__ {
++ brcm,pins = <45 44 43>;
++ brcm,function = <1>; /* output */
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&spi0_pins>;
++ __overlay__ {
++ brcm,pins = <40 41 42>;
++ brcm,function = <3>; /* alt4 */
++ status = "okay";
++ };
++ };
++};
+++ /dev/null
-From 4671029bae38c2057890e60ac26263f982775152 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 29 May 2019 13:54:21 +0100
-Subject: [PATCH 639/703] ARM: dts: Add bcm2711-rpi-4-b.dts and components
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/Makefile | 1 +
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 320 ++++++++++++
- arch/arm/boot/dts/bcm2711.dtsi | 50 ++
- arch/arm/boot/dts/bcm2838.dtsi | 724 ++++++++++++++++++++++++++
- 4 files changed, 1095 insertions(+)
- create mode 100644 arch/arm/boot/dts/bcm2711-rpi-4-b.dts
- create mode 100644 arch/arm/boot/dts/bcm2711.dtsi
- create mode 100644 arch/arm/boot/dts/bcm2838.dtsi
-
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -8,6 +8,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
- bcm2708-rpi-zero-w.dtb \
- bcm2709-rpi-2-b.dtb \
- bcm2710-rpi-3-b.dtb \
-+ bcm2711-rpi-4-b.dtb \
- bcm2710-rpi-3-b-plus.dtb \
- bcm2710-rpi-cm3.dtb
-
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -0,0 +1,320 @@
-+/dts-v1/;
-+
-+#include "bcm2711.dtsi"
-+
-+/ {
-+ compatible = "raspberrypi,4-model-b", "brcm,bcm2838", "brcm,bcm2837";
-+ model = "Raspberry Pi 4 Model B";
-+ #address-cells = <2>;
-+ #size-cells = <1>;
-+
-+ memory {
-+ device_type = "memory";
-+ reg = <0x0 0x0 0x0>;
-+ };
-+
-+ chosen {
-+ bootargs = "8250.nr_uarts=1 cma=64M";
-+ };
-+
-+ aliases {
-+ serial0 = &uart1;
-+ serial1 = &uart0;
-+ mmc0 = &emmc2;
-+ mmc1 = &mmcnr;
-+ mmc2 = &sdhost;
-+ /delete-property/ ethernet;
-+ /delete-property/ intc;
-+ ethernet0 = &genet;
-+ };
-+};
-+
-+&soc {
-+ virtgpio: virtgpio {
-+ compatible = "brcm,bcm2835-virtgpio";
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+ firmware = <&firmware>;
-+ status = "okay";
-+ };
-+};
-+
-+&mmcnr {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&sdio_pins>;
-+ bus-width = <4>;
-+ status = "okay";
-+};
-+
-+&firmware {
-+ expgpio: expgpio {
-+ compatible = "raspberrypi,firmware-gpio";
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+ 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 = <125000000>;
-+ };
-+
-+ spidev1: spidev@1{
-+ compatible = "spidev";
-+ reg = <1>; /* CE1 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ };
-+};
-+
-+// =============================================
-+// Board specific stuff here
-+
-+/ {
-+
-+ sd_io_1v8_reg: sd_io_1v8_reg {
-+ status = "okay";
-+ compatible = "regulator-gpio";
-+ vin-supply = <&vdd_5v0_reg>;
-+ regulator-name = "vdd-sd-io";
-+ regulator-min-microvolt = <1800000>;
-+ regulator-max-microvolt = <3300000>;
-+ regulator-boot-on;
-+ regulator-always-on;
-+ regulator-settling-time-us = <5000>;
-+
-+ gpios = <&expgpio 4 GPIO_ACTIVE_HIGH>;
-+ states = <1800000 0x1
-+ 3300000 0x0>;
-+ };
-+};
-+
-+&sdhost {
-+ status = "disabled";
-+};
-+
-+&emmc2 {
-+ status = "okay";
-+ broken-cd;
-+ vqmmc-supply = <&sd_io_1v8_reg>;
-+};
-+
-+&leds {
-+ act_led: act {
-+ label = "led0";
-+ linux,default-trigger = "mmc0";
-+ gpios = <&gpio 42 0>;
-+ };
-+
-+ pwr_led: pwr {
-+ label = "led1";
-+ linux,default-trigger = "input";
-+ gpios = <&expgpio 2 0>;
-+ };
-+};
-+
-+&audio {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&audio_pins>;
-+};
-+
-+&sdhost_gpio48 {
-+ brcm,pins = <22 23 24 25 26 27>;
-+ brcm,function = <BCM2835_FSEL_ALT0>;
-+};
-+
-+&gpio {
-+ spi0_pins: spi0_pins {
-+ brcm,pins = <9 10 11>;
-+ brcm,function = <BCM2835_FSEL_ALT0>;
-+ };
-+
-+ spi0_cs_pins: spi0_cs_pins {
-+ brcm,pins = <8 7>;
-+ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
-+ };
-+
-+ spi3_pins: spi3_pins {
-+ brcm,pins = <1 2 3>;
-+ brcm,function = <BCM2835_FSEL_ALT3>;
-+ };
-+
-+ spi3_cs_pins: spi3_cs_pins {
-+ brcm,pins = <0 24>;
-+ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
-+ };
-+
-+ spi4_pins: spi4_pins {
-+ brcm,pins = <5 6 7>;
-+ brcm,function = <BCM2835_FSEL_ALT3>;
-+ };
-+
-+ spi4_cs_pins: spi4_cs_pins {
-+ brcm,pins = <4 25>;
-+ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
-+ };
-+
-+ spi5_pins: spi5_pins {
-+ brcm,pins = <13 14 15>;
-+ brcm,function = <BCM2835_FSEL_ALT3>;
-+ };
-+
-+ spi5_cs_pins: spi5_cs_pins {
-+ brcm,pins = <12 26>;
-+ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
-+ };
-+
-+ spi6_pins: spi6_pins {
-+ brcm,pins = <19 20 21>;
-+ brcm,function = <BCM2835_FSEL_ALT3>;
-+ };
-+
-+ spi6_cs_pins: spi6_cs_pins {
-+ brcm,pins = <18 27>;
-+ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
-+ };
-+
-+ i2c0_pins: i2c0 {
-+ brcm,pins = <0 1>;
-+ brcm,function = <BCM2835_FSEL_ALT0>;
-+ };
-+
-+ i2c1_pins: i2c1 {
-+ brcm,pins = <2 3>;
-+ brcm,function = <BCM2835_FSEL_ALT0>;
-+ };
-+
-+ i2c3_pins: i2c3 {
-+ brcm,pins = <4 5>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+
-+ i2c4_pins: i2c4 {
-+ brcm,pins = <8 9>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+
-+ i2c5_pins: i2c5 {
-+ brcm,pins = <12 13>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+
-+ i2c6_pins: i2c6 {
-+ brcm,pins = <22 23>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+
-+ i2s_pins: i2s {
-+ brcm,pins = <18 19 20 21>;
-+ brcm,function = <BCM2835_FSEL_ALT0>;
-+ };
-+
-+ sdio_pins: sdio_pins {
-+ brcm,pins = <34 35 36 37 38 39>;
-+ brcm,function = <BCM2835_FSEL_ALT3>; // alt3 = SD1
-+ brcm,pull = <0 2 2 2 2 2>;
-+ };
-+
-+ bt_pins: bt_pins {
-+ brcm,pins = "-"; // non-empty to keep btuart happy, //4 = 0
-+ // to fool pinctrl
-+ brcm,function = <0>;
-+ brcm,pull = <2>;
-+ };
-+
-+ uart0_pins: uart0_pins {
-+ brcm,pins = <32 33>;
-+ brcm,function = <BCM2835_FSEL_ALT3>;
-+ brcm,pull = <0 2>;
-+ };
-+
-+ uart1_pins: uart1_pins {
-+ brcm,pins;
-+ brcm,function;
-+ brcm,pull;
-+ };
-+
-+ uart2_pins: uart2_pins {
-+ brcm,pins = <0 1>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ brcm,pull = <0 2>;
-+ };
-+
-+ uart3_pins: uart3_pins {
-+ brcm,pins = <4 5>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ brcm,pull = <0 2>;
-+ };
-+
-+ uart4_pins: uart4_pins {
-+ brcm,pins = <8 9>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ brcm,pull = <0 2>;
-+ };
-+
-+ uart5_pins: uart5_pins {
-+ brcm,pins = <12 13>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ brcm,pull = <0 2>;
-+ };
-+
-+ audio_pins: audio_pins {
-+ brcm,pins = <40 41>;
-+ brcm,function = <4>;
-+ };
-+};
-+
-+&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 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2s_pins>;
-+};
-+
-+/ {
-+ __overrides__ {
-+ act_led_gpio = <&act_led>,"gpios:4";
-+ 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";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2711.dtsi
-@@ -0,0 +1,50 @@
-+#include "bcm2838.dtsi"
-+#include "bcm270x.dtsi"
-+#include "bcm2708-rpi.dtsi"
-+
-+/ {
-+ soc {
-+ /delete-node/ mailbox@7e00b840;
-+ /delete-node/ v3d@7ec00000;
-+ };
-+
-+ __overrides__ {
-+ arm_freq;
-+ };
-+};
-+
-+&dma {
-+ brcm,dma-channel-mask = <0x7ef5>;
-+};
-+
-+&txp {
-+ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&firmwarekms {
-+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&smi {
-+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&mmc {
-+ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&mmcnr {
-+ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&usb {
-+ reg = <0x7e980000 0x10000>,
-+ <0x7e00b200 0x200>;
-+ interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&gpio {
-+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -0,0 +1,724 @@
-+// SPDX-License-Identifier: GPL-2.0
-+#include "bcm283x.dtsi"
-+
-+#include <dt-bindings/interrupt-controller/arm-gic.h>
-+#include <dt-bindings/soc/bcm2835-pm.h>
-+
-+/ {
-+ compatible = "brcm,bcm2838", "brcm,bcm2837";
-+
-+ interrupt-parent = <&gicv2>;
-+
-+ soc {
-+ ranges = <0x7e000000 0x0 0xfe000000 0x01800000>,
-+ <0x7c000000 0x0 0xfc000000 0x02000000>,
-+ <0x40000000 0x0 0xff800000 0x00800000>;
-+ /* Emulate a contiguous 30-bit address range for DMA */
-+ dma-ranges = <0xc0000000 0x0 0x00000000 0x3c000000>;
-+
-+ /delete-node/ mailbox@7e00b840;
-+ /delete-node/ interrupt-controller@7e00f300;
-+
-+ local_intc: local_intc@40000000 {
-+ compatible = "brcm,bcm2836-l1-intc";
-+ reg = <0x40000000 0x100>;
-+ };
-+
-+ gicv2: gic400@40041000 {
-+ interrupt-controller;
-+ #interrupt-cells = <3>;
-+ compatible = "arm,gic-400";
-+ reg = <0x40041000 0x1000>,
-+ <0x40042000 0x2000>,
-+ <0x40046000 0x2000>,
-+ <0x40048000 0x2000>;
-+ };
-+
-+ thermal: thermal@7d5d2200 {
-+ compatible = "brcm,avs-tmon-bcm2838";
-+ reg = <0x7d5d2200 0x2c>;
-+ interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
-+ interrupt-names = "tmon";
-+ clocks = <&clocks BCM2835_CLOCK_TSENS>;
-+ #thermal-sensor-cells = <0>;
-+ status = "okay";
-+ };
-+
-+ pm: watchdog@7e100000 {
-+ reg = <0x7e100000 0x114>,
-+ <0x7e00a000 0x24>,
-+ <0x7ec11000 0x20>;
-+ };
-+
-+ rng@7e104000 {
-+ interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
-+ };
-+
-+ uart2: serial@7e201400 {
-+ compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
-+ reg = <0x7e201400 0x200>;
-+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&clocks BCM2835_CLOCK_UART>,
-+ <&clocks BCM2835_CLOCK_VPU>;
-+ clock-names = "uartclk", "apb_pclk";
-+ arm,primecell-periphid = <0x00241011>;
-+ status = "disabled";
-+ };
-+
-+ uart3: serial@7e201600 {
-+ compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
-+ reg = <0x7e201600 0x200>;
-+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&clocks BCM2835_CLOCK_UART>,
-+ <&clocks BCM2835_CLOCK_VPU>;
-+ clock-names = "uartclk", "apb_pclk";
-+ arm,primecell-periphid = <0x00241011>;
-+ status = "disabled";
-+ };
-+
-+ uart4: serial@7e201800 {
-+ compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
-+ reg = <0x7e201800 0x200>;
-+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&clocks BCM2835_CLOCK_UART>,
-+ <&clocks BCM2835_CLOCK_VPU>;
-+ clock-names = "uartclk", "apb_pclk";
-+ arm,primecell-periphid = <0x00241011>;
-+ status = "disabled";
-+ };
-+
-+ uart5: serial@7e201a00 {
-+ compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
-+ reg = <0x7e201a00 0x200>;
-+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&clocks BCM2835_CLOCK_UART>,
-+ <&clocks BCM2835_CLOCK_VPU>;
-+ clock-names = "uartclk", "apb_pclk";
-+ arm,primecell-periphid = <0x00241011>;
-+ status = "disabled";
-+ };
-+
-+ spi@7e204000 {
-+ reg = <0x7e204000 0x0200>;
-+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
-+ };
-+
-+ spi3: spi@7e204600 {
-+ compatible = "brcm,bcm2835-spi";
-+ reg = <0x7e204600 0x0200>;
-+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&clocks BCM2835_CLOCK_VPU>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ spi4: spi@7e204800 {
-+ compatible = "brcm,bcm2835-spi";
-+ reg = <0x7e204800 0x0200>;
-+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&clocks BCM2835_CLOCK_VPU>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ spi5: spi@7e204a00 {
-+ compatible = "brcm,bcm2835-spi";
-+ reg = <0x7e204a00 0x0200>;
-+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&clocks BCM2835_CLOCK_VPU>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ spi6: spi@7e204c00 {
-+ compatible = "brcm,bcm2835-spi";
-+ reg = <0x7e204c00 0x0200>;
-+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&clocks BCM2835_CLOCK_VPU>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ i2c3: i2c@7e205600 {
-+ compatible = "brcm,bcm2835-i2c";
-+ reg = <0x7e205600 0x200>;
-+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&clocks BCM2835_CLOCK_VPU>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ i2c4: i2c@7e205800 {
-+ compatible = "brcm,bcm2835-i2c";
-+ reg = <0x7e205800 0x200>;
-+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&clocks BCM2835_CLOCK_VPU>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ i2c5: i2c@7e205a00 {
-+ compatible = "brcm,bcm2835-i2c";
-+ reg = <0x7e205a00 0x200>;
-+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&clocks BCM2835_CLOCK_VPU>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ i2c6: i2c@7e205c00 {
-+ compatible = "brcm,bcm2835-i2c";
-+ reg = <0x7e205c00 0x200>;
-+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&clocks BCM2835_CLOCK_VPU>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ pixelvalve@7e206000 {
-+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
-+ };
-+
-+ pixelvalve@7e207000 {
-+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
-+ };
-+
-+ emmc2: emmc2@7e340000 {
-+ compatible = "brcm,bcm2711-emmc2";
-+ status = "okay";
-+ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&clocks BCM2838_CLOCK_EMMC2>;
-+ reg = <0x7e340000 0x100>;
-+ };
-+
-+ hvs@7e400000 {
-+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
-+ };
-+
-+ pixelvalve@7e807000 {
-+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
-+ };
-+ };
-+
-+ arm-pmu {
-+ /*
-+ * N.B. the A72 PMU support only exists in arch/arm64, hence
-+ * the fallback to the A53 version.
-+ */
-+ compatible = "arm,cortex-a72-pmu", "arm,cortex-a53-pmu";
-+ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
-+ };
-+
-+ timer {
-+ compatible = "arm,armv7-timer";
-+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) |
-+ IRQ_TYPE_LEVEL_LOW)>,
-+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) |
-+ IRQ_TYPE_LEVEL_LOW)>,
-+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
-+ IRQ_TYPE_LEVEL_LOW)>,
-+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
-+ IRQ_TYPE_LEVEL_LOW)>;
-+ arm,cpu-registers-not-fw-configured;
-+ always-on;
-+ };
-+
-+ cpus: cpus {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ enable-method = "brcm,bcm2836-smp"; // for ARM 32-bit
-+
-+ cpu0: cpu@0 {
-+ device_type = "cpu";
-+ compatible = "arm,cortex-a72";
-+ reg = <0>;
-+ enable-method = "spin-table";
-+ cpu-release-addr = <0x0 0x000000d8>;
-+ };
-+
-+ cpu1: cpu@1 {
-+ device_type = "cpu";
-+ compatible = "arm,cortex-a72";
-+ reg = <1>;
-+ enable-method = "spin-table";
-+ cpu-release-addr = <0x0 0x000000e0>;
-+ };
-+
-+ cpu2: cpu@2 {
-+ device_type = "cpu";
-+ compatible = "arm,cortex-a72";
-+ reg = <2>;
-+ enable-method = "spin-table";
-+ cpu-release-addr = <0x0 0x000000e8>;
-+ };
-+
-+ cpu3: cpu@3 {
-+ device_type = "cpu";
-+ compatible = "arm,cortex-a72";
-+ reg = <3>;
-+ enable-method = "spin-table";
-+ cpu-release-addr = <0x0 0x000000f0>;
-+ };
-+ };
-+
-+ v3dbus {
-+ compatible = "simple-bus";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges = <0x7c500000 0x0 0xfc500000 0x03300000>,
-+ <0x40000000 0x0 0xff800000 0x00800000>;
-+ dma-ranges = <0x00000000 0x0 0x00000000 0x3c000000>;
-+
-+ v3d: v3d@7ec04000 {
-+ compatible = "brcm,2711-v3d";
-+ reg =
-+ <0x7ec00000 0x4000>,
-+ <0x7ec04000 0x4000>;
-+ reg-names = "hub", "core0";
-+
-+ power-domains = <&pm BCM2835_POWER_DOMAIN_GRAFX_V3D>;
-+ resets = <&pm BCM2835_RESET_V3D>;
-+ clocks = <&clocks BCM2835_CLOCK_V3D>;
-+ interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
-+ status = "okay";
-+ };
-+ };
-+
-+ scb: scb {
-+ compatible = "simple-bus";
-+ #address-cells = <2>;
-+ #size-cells = <1>;
-+
-+ ranges = <0x0 0x7c000000 0x0 0xfc000000 0x03800000>,
-+ <0x0 0x40000000 0x0 0xff800000 0x00800000>,
-+ <0x6 0x00000000 0x6 0x00000000 0x40000000>,
-+ <0x0 0x00000000 0x0 0x00000000 0xfc000000>;
-+ dma-ranges = <0x0 0x00000000 0x0 0x00000000 0xfc000000>;
-+
-+ pcie_0: pcie@7d500000 {
-+ reg = <0x0 0x7d500000 0x9310>,
-+ <0x0 0x7e00f300 0x20>;
-+ msi-controller;
-+ msi-parent = <&pcie_0>;
-+ #address-cells = <3>;
-+ #interrupt-cells = <1>;
-+ #size-cells = <2>;
-+ bus-range = <0x0 0x01>;
-+ compatible = "brcm,bcm7211-pcie", "brcm,bcm7445-pcie",
-+ "brcm,pci-plat-dev";
-+ max-link-speed = <2>;
-+ tot-num-pcie = <1>;
-+ linux,pci-domain = <0>;
-+ interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
-+ interrupt-names = "pcie", "msi";
-+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
-+ interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 143
-+ IRQ_TYPE_LEVEL_HIGH
-+ 0 0 0 2 &gicv2 GIC_SPI 144
-+ IRQ_TYPE_LEVEL_HIGH
-+ 0 0 0 3 &gicv2 GIC_SPI 145
-+ IRQ_TYPE_LEVEL_HIGH
-+ 0 0 0 4 &gicv2 GIC_SPI 146
-+ IRQ_TYPE_LEVEL_HIGH>;
-+
-+ /* Map outbound accesses from scb:0x6_00000000-03ffffff
-+ * to pci:0x0_f8000000-fbffffff
-+ */
-+ ranges = <0x02000000 0x0 0xf8000000 0x6 0x00000000
-+ 0x0 0x04000000>;
-+ /* Map inbound accesses from pci:0x0_00000000..ffffffff
-+ * to scb:0x0_00000000-ffffffff
-+ */
-+ dma-ranges = <0x02000000 0x0 0x00000000 0x0 0x00000000
-+ 0x1 0x00000000>;
-+ status = "okay";
-+ };
-+
-+ genet: genet@7d580000 {
-+ compatible = "brcm,genet-v5";
-+ reg = <0x0 0x7d580000 0x10000>;
-+ status = "okay";
-+ #address-cells = <0x1>;
-+ #size-cells = <0x1>;
-+ interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
-+ phy-handle = <&phy1>;
-+ phy-mode = "rgmii";
-+ mdio@e14 {
-+ #address-cells = <0x0>;
-+ #size-cells = <0x1>;
-+ compatible = "brcm,genet-mdio-v5";
-+ reg = <0xe14 0x8>;
-+ reg-names = "mdio";
-+ phy1: genet-phy@0 {
-+ compatible =
-+ "ethernet-phy-ieee802.3-c22";
-+ /* No interrupts - use PHY_POLL */
-+ max-speed = <1000>;
-+ reg = <0x1>;
-+ };
-+ };
-+ };
-+
-+ xhci: xhci@7e9c0000 {
-+ compatible = "generic-xhci";
-+ status = "disabled";
-+ reg = <0x0 0x7e9c0000 0x100000>;
-+ interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
-+ };
-+
-+ vchiq: mailbox@7e00b840 {
-+ compatible = "brcm,bcm2838-vchiq";
-+ reg = <0 0x7e00b840 0x3c>;
-+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
-+ };
-+
-+ hevc-decoder@7eb00000 {
-+ compatible = "raspberrypi,argon-hevc-decoder";
-+ reg = <0x0 0x7eb00000 0x10000>;
-+ status = "okay";
-+ };
-+
-+ argon-local-intc@7eb10000 {
-+ compatible = "raspberrypi,argon-local-intc";
-+ reg = <0x0 0x7eb10000 0x1000>;
-+ status = "okay";
-+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
-+ };
-+
-+ h264-decoder@7eb20000 {
-+ compatible = "raspberrypi,argon-h264-decoder";
-+ reg = <0x0 0x7eb20000 0x10000>;
-+ status = "okay";
-+ };
-+
-+ vp9-decoder@7eb30000 {
-+ compatible = "raspberrypi,argon-vp9-decoder";
-+ reg = <0x0 0x7eb30000 0x10000>;
-+ status = "okay";
-+ };
-+ };
-+};
-+
-+&clk_osc {
-+ clock-frequency = <54000000>;
-+};
-+
-+&clocks {
-+ compatible = "brcm,bcm2838-cprman";
-+};
-+
-+&cpu_thermal {
-+ coefficients = <(-487) 410040>;
-+};
-+
-+&dsi0 {
-+ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&dsi1 {
-+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&gpio {
-+ gpclk0_gpio49: gpclk0_gpio49 {
-+ brcm,pins = <49>;
-+ brcm,function = <BCM2835_FSEL_ALT1>;
-+ brcm,pull = <BCM2835_PUD_OFF>;
-+ };
-+ gpclk1_gpio50: gpclk1_gpio50 {
-+ brcm,pins = <50>;
-+ brcm,function = <BCM2835_FSEL_ALT1>;
-+ brcm,pull = <BCM2835_PUD_OFF>;
-+ };
-+ gpclk2_gpio51: gpclk2_gpio51 {
-+ brcm,pins = <51>;
-+ brcm,function = <BCM2835_FSEL_ALT1>;
-+ brcm,pull = <BCM2835_PUD_OFF>;
-+ };
-+
-+ i2c0_gpio46: i2c0_gpio46 {
-+ brcm,pins = <46 47>;
-+ brcm,function = <BCM2835_FSEL_ALT0>;
-+ };
-+ i2c1_gpio46: i2c1_gpio46 {
-+ brcm,pins = <46 47>;
-+ brcm,function = <BCM2835_FSEL_ALT1>;
-+ };
-+ i2c3_gpio2: i2c3_gpio2 {
-+ brcm,pins = <2 3>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+ i2c3_gpio4: i2c3_gpio4 {
-+ brcm,pins = <4 5>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+ i2c4_gpio6: i2c4_gpio6 {
-+ brcm,pins = <6 7>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+ i2c4_gpio8: i2c4_gpio8 {
-+ brcm,pins = <8 9>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+ i2c5_gpio10: i2c5_gpio10 {
-+ brcm,pins = <10 11>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+ i2c5_gpio12: i2c5_gpio12 {
-+ brcm,pins = <12 13>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+ i2c6_gpio0: i2c6_gpio0 {
-+ brcm,pins = <0 1>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+ i2c6_gpio22: i2c6_gpio22 {
-+ brcm,pins = <22 23>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+ i2c_slave_gpio8: i2c_slave_gpio8 {
-+ brcm,pins = <8 9 10 11>;
-+ brcm,function = <BCM2835_FSEL_ALT3>;
-+ };
-+
-+ jtag_gpio48: jtag_gpio48 {
-+ brcm,pins = <48 49 50 51 52 53>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ };
-+
-+ mii_gpio28: mii_gpio28 {
-+ brcm,pins = <28 29 30 31>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ };
-+ mii_gpio36: mii_gpio36 {
-+ brcm,pins = <36 37 38 39>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+
-+ pcm_gpio50: pcm_gpio50 {
-+ brcm,pins = <50 51 52 53>;
-+ brcm,function = <BCM2835_FSEL_ALT2>;
-+ };
-+
-+ pwm0_gpio52: pwm0_gpio52 {
-+ brcm,pins = <52>;
-+ brcm,function = <BCM2835_FSEL_ALT1>;
-+ brcm,pull = <BCM2835_PUD_OFF>;
-+ };
-+ pwm1_gpio53: pwm1_gpio53 {
-+ brcm,pins = <53>;
-+ brcm,function = <BCM2835_FSEL_ALT1>;
-+ brcm,pull = <BCM2835_PUD_OFF>;
-+ };
-+
-+ /* The following group consists of:
-+ * RGMII_START_STOP
-+ * RGMII_RX_OK
-+ */
-+ rgmii_gpio35: rgmii_gpio35 {
-+ brcm,pins = <35 36>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ };
-+ rgmii_irq_gpio34: rgmii_irq_gpio34 {
-+ brcm,pins = <34>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+ rgmii_irq_gpio39: rgmii_irq_gpio39 {
-+ brcm,pins = <39>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ };
-+ rgmii_mdio_gpio28: rgmii_mdio_gpio28 {
-+ brcm,pins = <28 29>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+ rgmii_mdio_gpio37: rgmii_mdio_gpio37 {
-+ brcm,pins = <37 38>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ };
-+
-+ spi0_gpio46: spi0_gpio46 {
-+ brcm,pins = <46 47 48 49>;
-+ brcm,function = <BCM2835_FSEL_ALT2>;
-+ };
-+ spi2_gpio46: spi2_gpio46 {
-+ brcm,pins = <46 47 48 49 50>;
-+ brcm,function = <BCM2835_FSEL_ALT5>;
-+ };
-+ spi3_gpio0: spi3_gpio0 {
-+ brcm,pins = <0 1 2 3>;
-+ brcm,function = <BCM2835_FSEL_ALT3>;
-+ };
-+ spi4_gpio4: spi4_gpio4 {
-+ brcm,pins = <4 5 6 7>;
-+ brcm,function = <BCM2835_FSEL_ALT3>;
-+ };
-+ spi5_gpio12: spi5_gpio12 {
-+ brcm,pins = <12 13 14 15>;
-+ brcm,function = <BCM2835_FSEL_ALT3>;
-+ };
-+ spi6_gpio18: spi6_gpio18 {
-+ brcm,pins = <18 19 20 21>;
-+ brcm,function = <BCM2835_FSEL_ALT3>;
-+ };
-+
-+ uart2_gpio0: uart2_gpio0 {
-+ brcm,pins = <0 1>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
-+ };
-+ uart2_ctsrts_gpio2: uart2_ctsrts_gpio2 {
-+ brcm,pins = <2 3>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
-+ };
-+ uart3_gpio4: uart3_gpio4 {
-+ brcm,pins = <4 5>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
-+ };
-+ uart3_ctsrts_gpio6: uart3_ctsrts_gpio6 {
-+ brcm,pins = <6 7>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
-+ };
-+ uart4_gpio8: uart4_gpio8 {
-+ brcm,pins = <8 9>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
-+ };
-+ uart4_ctsrts_gpio10: uart4_ctsrts_gpio10 {
-+ brcm,pins = <10 11>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
-+ };
-+ uart5_gpio12: uart5_gpio12 {
-+ brcm,pins = <12 13>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
-+ };
-+ uart5_ctsrts_gpio14: uart5_ctsrts_gpio14 {
-+ brcm,pins = <14 15>;
-+ brcm,function = <BCM2835_FSEL_ALT4>;
-+ brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
-+ };
-+};
-+
-+&vec {
-+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&usb {
-+ interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&hdmi {
-+ interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&uart1 {
-+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&spi1 {
-+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&spi2 {
-+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&csi0 {
-+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&csi1 {
-+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&sdhci {
-+ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&i2c0 {
-+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&i2c1 {
-+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&i2c2 {
-+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&gpio {
-+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&mailbox {
-+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&rng {
-+ compatible = "brcm,bcm2838-rng200";
-+};
-+
-+&sdhost {
-+ interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&uart0 {
-+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
-+};
-+
-+&dma {
-+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 7 */
-+ <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 8 */
-+ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 9 */
-+ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 10 */
-+ /* DMA4 - 40 bit DMA engines */
-+ <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, /* dma4 11 */
-+ <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, /* dma4 12 */
-+ <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, /* dma4 13 */
-+ <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; /* dma4 14 */
-+ interrupt-names = "dma0",
-+ "dma1",
-+ "dma2",
-+ "dma3",
-+ "dma4",
-+ "dma5",
-+ "dma6",
-+ "dma7",
-+ "dma8",
-+ "dma9",
-+ "dma10",
-+ "dma11",
-+ "dma12",
-+ "dma13",
-+ "dma14";
-+ brcm,dma-channel-mask = <0x7ef5>;
-+};
--- /dev/null
+From 313e17bef58a02b4cb37f8be66b4f66267d46205 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 4 Sep 2018 11:50:25 +0100
+Subject: [PATCH 639/725] config: Permit LPAE and PCIE_BRCMSTB on BCM2835
+
+---
+ arch/arm/mach-bcm/Kconfig | 4 ++++
+ drivers/pci/controller/Kconfig | 4 ++--
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/mach-bcm/Kconfig
++++ b/arch/arm/mach-bcm/Kconfig
+@@ -161,6 +161,7 @@ config ARCH_BCM2835
+ select GPIOLIB
+ select ARM_AMBA
+ select ARM_ERRATA_411920 if ARCH_MULTI_V6
++ select ARM_GIC
+ select ARM_TIMER_SP804
+ select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7
+ select TIMER_OF
+@@ -169,6 +170,9 @@ config ARCH_BCM2835
+ select PINCTRL
+ select PINCTRL_BCM2835
+ select MFD_SYSCON if ARCH_MULTI_V7
++ select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
++ select ZONE_DMA if ARM_LPAE
++ select MFD_CORE
+ help
+ This enables support for the Broadcom BCM2835 and BCM2836 SoCs.
+ This SoC is used in the Raspberry Pi and Roku 2 devices.
+--- a/drivers/pci/controller/Kconfig
++++ b/drivers/pci/controller/Kconfig
+@@ -280,9 +280,9 @@ config VMD
+
+ config PCIE_BRCMSTB
+ tristate "Broadcom Brcmstb PCIe platform host driver"
+- depends on ARCH_BRCMSTB || BMIPS_GENERIC
++ depends on ARCH_BRCMSTB || BMIPS_GENERIC || ARCH_BCM2835
+ depends on OF
+- depends on SOC_BRCMSTB
++ depends on SOC_BRCMSTB || ARCH_BCM2835
+ default ARCH_BRCMSTB || BMIPS_GENERIC
+ help
+ Adds support for Broadcom Settop Box PCIe host controller.
--- /dev/null
+From 2caac63444825448e0b588af6adae8d80365bbed Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 May 2019 15:40:21 +0100
+Subject: [PATCH 640/725] configs: Add bcm2711_defconfig
+
+---
+ arch/arm/configs/bcm2711_defconfig | 1330 ++++++++++++++++++++++++++++
+ 1 file changed, 1330 insertions(+)
+ create mode 100644 arch/arm/configs/bcm2711_defconfig
+
+--- /dev/null
++++ b/arch/arm/configs/bcm2711_defconfig
+@@ -0,0 +1,1330 @@
++CONFIG_LOCALVERSION="-v7l"
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SYSVIPC=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_GENERIC_IRQ_DEBUGFS=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_PREEMPT_VOLUNTARY=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++CONFIG_TASKSTATS=y
++CONFIG_TASK_DELAY_ACCT=y
++CONFIG_TASK_XACCT=y
++CONFIG_TASK_IO_ACCOUNTING=y
++CONFIG_IKCONFIG=m
++CONFIG_IKCONFIG_PROC=y
++CONFIG_CGROUP_FREEZER=y
++CONFIG_CPUSETS=y
++CONFIG_CGROUP_DEVICE=y
++CONFIG_CGROUP_CPUACCT=y
++CONFIG_NAMESPACES=y
++CONFIG_USER_NS=y
++CONFIG_SCHED_AUTOGROUP=y
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_EMBEDDED=y
++# CONFIG_COMPAT_BRK is not set
++CONFIG_PROFILING=y
++CONFIG_ARCH_BCM=y
++CONFIG_ARCH_BCM2835=y
++CONFIG_ARM_LPAE=y
++# CONFIG_CACHE_L2X0 is not set
++CONFIG_PCI=y
++CONFIG_PCI_MSI=y
++CONFIG_PCIE_BRCMSTB=y
++CONFIG_SMP=y
++CONFIG_HIGHMEM=y
++CONFIG_UACCESS_WITH_MEMCPY=y
++CONFIG_SECCOMP=y
++# CONFIG_ATAGS is not set
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait"
++CONFIG_CPU_FREQ=y
++CONFIG_CPU_FREQ_STAT=y
++CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y
++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
++CONFIG_CPU_FREQ_GOV_USERSPACE=y
++CONFIG_CPU_FREQ_GOV_ONDEMAND=y
++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
++CONFIG_VFP=y
++CONFIG_NEON=y
++CONFIG_KERNEL_MODE_NEON=y
++# CONFIG_SUSPEND is not set
++CONFIG_PM=y
++CONFIG_RASPBERRYPI_FIRMWARE=y
++CONFIG_ARM_CRYPTO=y
++CONFIG_CRYPTO_SHA1_ARM_NEON=m
++CONFIG_CRYPTO_AES_ARM=m
++CONFIG_CRYPTO_AES_ARM_BS=m
++CONFIG_OPROFILE=m
++CONFIG_KPROBES=y
++CONFIG_JUMP_LABEL=y
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODVERSIONS=y
++CONFIG_MODULE_SRCVERSION_ALL=y
++CONFIG_PARTITION_ADVANCED=y
++CONFIG_MAC_PARTITION=y
++CONFIG_BINFMT_MISC=m
++CONFIG_CLEANCACHE=y
++CONFIG_FRONTSWAP=y
++CONFIG_CMA=y
++CONFIG_ZSMALLOC=m
++CONFIG_PGTABLE_MAPPING=y
++CONFIG_NET=y
++CONFIG_PACKET=y
++CONFIG_UNIX=y
++CONFIG_XFRM_USER=y
++CONFIG_NET_KEY=m
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_IP_ROUTE_MULTIPATH=y
++CONFIG_IP_ROUTE_VERBOSE=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_RARP=y
++CONFIG_NET_IPIP=m
++CONFIG_NET_IPGRE_DEMUX=m
++CONFIG_NET_IPGRE=m
++CONFIG_IP_MROUTE=y
++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
++CONFIG_IP_PIMSM_V1=y
++CONFIG_IP_PIMSM_V2=y
++CONFIG_SYN_COOKIES=y
++CONFIG_INET_AH=m
++CONFIG_INET_ESP=m
++CONFIG_INET_IPCOMP=m
++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_IPV6_ROUTE_INFO=y
++CONFIG_INET6_AH=m
++CONFIG_INET6_ESP=m
++CONFIG_INET6_IPCOMP=m
++CONFIG_IPV6_SIT_6RD=y
++CONFIG_IPV6_TUNNEL=m
++CONFIG_IPV6_MULTIPLE_TABLES=y
++CONFIG_IPV6_SUBTREES=y
++CONFIG_IPV6_MROUTE=y
++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
++CONFIG_IPV6_PIMSM_V2=y
++CONFIG_NETFILTER=y
++CONFIG_NF_CONNTRACK=m
++CONFIG_NF_CONNTRACK_ZONES=y
++CONFIG_NF_CONNTRACK_EVENTS=y
++CONFIG_NF_CONNTRACK_TIMESTAMP=y
++CONFIG_NF_CONNTRACK_AMANDA=m
++CONFIG_NF_CONNTRACK_FTP=m
++CONFIG_NF_CONNTRACK_H323=m
++CONFIG_NF_CONNTRACK_IRC=m
++CONFIG_NF_CONNTRACK_NETBIOS_NS=m
++CONFIG_NF_CONNTRACK_SNMP=m
++CONFIG_NF_CONNTRACK_PPTP=m
++CONFIG_NF_CONNTRACK_SANE=m
++CONFIG_NF_CONNTRACK_SIP=m
++CONFIG_NF_CONNTRACK_TFTP=m
++CONFIG_NF_CT_NETLINK=m
++CONFIG_NETFILTER_XT_SET=m
++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
++CONFIG_NETFILTER_XT_TARGET_DSCP=m
++CONFIG_NETFILTER_XT_TARGET_HMARK=m
++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
++CONFIG_NETFILTER_XT_TARGET_LED=m
++CONFIG_NETFILTER_XT_TARGET_LOG=m
++CONFIG_NETFILTER_XT_TARGET_MARK=m
++CONFIG_NETFILTER_XT_TARGET_NFLOG=m
++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
++CONFIG_NETFILTER_XT_TARGET_TEE=m
++CONFIG_NETFILTER_XT_TARGET_TPROXY=m
++CONFIG_NETFILTER_XT_TARGET_TRACE=m
++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
++CONFIG_NETFILTER_XT_MATCH_BPF=m
++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
++CONFIG_NETFILTER_XT_MATCH_COMMENT=m
++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
++CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
++CONFIG_NETFILTER_XT_MATCH_CPU=m
++CONFIG_NETFILTER_XT_MATCH_DCCP=m
++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
++CONFIG_NETFILTER_XT_MATCH_DSCP=m
++CONFIG_NETFILTER_XT_MATCH_ESP=m
++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
++CONFIG_NETFILTER_XT_MATCH_HELPER=m
++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
++CONFIG_NETFILTER_XT_MATCH_IPVS=m
++CONFIG_NETFILTER_XT_MATCH_LENGTH=m
++CONFIG_NETFILTER_XT_MATCH_LIMIT=m
++CONFIG_NETFILTER_XT_MATCH_MAC=m
++CONFIG_NETFILTER_XT_MATCH_MARK=m
++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
++CONFIG_NETFILTER_XT_MATCH_NFACCT=m
++CONFIG_NETFILTER_XT_MATCH_OSF=m
++CONFIG_NETFILTER_XT_MATCH_OWNER=m
++CONFIG_NETFILTER_XT_MATCH_POLICY=m
++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
++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_STATE=m
++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
++CONFIG_NETFILTER_XT_MATCH_STRING=m
++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
++CONFIG_NETFILTER_XT_MATCH_TIME=m
++CONFIG_NETFILTER_XT_MATCH_U32=m
++CONFIG_IP_SET=m
++CONFIG_IP_SET_BITMAP_IP=m
++CONFIG_IP_SET_BITMAP_IPMAC=m
++CONFIG_IP_SET_BITMAP_PORT=m
++CONFIG_IP_SET_HASH_IP=m
++CONFIG_IP_SET_HASH_IPPORT=m
++CONFIG_IP_SET_HASH_IPPORTIP=m
++CONFIG_IP_SET_HASH_IPPORTNET=m
++CONFIG_IP_SET_HASH_NET=m
++CONFIG_IP_SET_HASH_NETPORT=m
++CONFIG_IP_SET_HASH_NETIFACE=m
++CONFIG_IP_SET_LIST_SET=m
++CONFIG_IP_VS=m
++CONFIG_IP_VS_PROTO_TCP=y
++CONFIG_IP_VS_PROTO_UDP=y
++CONFIG_IP_VS_PROTO_ESP=y
++CONFIG_IP_VS_PROTO_AH=y
++CONFIG_IP_VS_PROTO_SCTP=y
++CONFIG_IP_VS_RR=m
++CONFIG_IP_VS_WRR=m
++CONFIG_IP_VS_LC=m
++CONFIG_IP_VS_WLC=m
++CONFIG_IP_VS_LBLC=m
++CONFIG_IP_VS_LBLCR=m
++CONFIG_IP_VS_DH=m
++CONFIG_IP_VS_SH=m
++CONFIG_IP_VS_SED=m
++CONFIG_IP_VS_NQ=m
++CONFIG_IP_VS_FTP=m
++CONFIG_IP_VS_PE_SIP=m
++CONFIG_IP_NF_IPTABLES=m
++CONFIG_IP_NF_MATCH_AH=m
++CONFIG_IP_NF_MATCH_ECN=m
++CONFIG_IP_NF_MATCH_RPFILTER=m
++CONFIG_IP_NF_MATCH_TTL=m
++CONFIG_IP_NF_FILTER=m
++CONFIG_IP_NF_TARGET_REJECT=m
++CONFIG_IP_NF_NAT=m
++CONFIG_IP_NF_TARGET_MASQUERADE=m
++CONFIG_IP_NF_TARGET_NETMAP=m
++CONFIG_IP_NF_TARGET_REDIRECT=m
++CONFIG_IP_NF_MANGLE=m
++CONFIG_IP_NF_TARGET_CLUSTERIP=m
++CONFIG_IP_NF_TARGET_ECN=m
++CONFIG_IP_NF_TARGET_TTL=m
++CONFIG_IP_NF_RAW=m
++CONFIG_IP_NF_ARPTABLES=m
++CONFIG_IP_NF_ARPFILTER=m
++CONFIG_IP_NF_ARP_MANGLE=m
++CONFIG_IP6_NF_IPTABLES=m
++CONFIG_IP6_NF_MATCH_AH=m
++CONFIG_IP6_NF_MATCH_EUI64=m
++CONFIG_IP6_NF_MATCH_FRAG=m
++CONFIG_IP6_NF_MATCH_OPTS=m
++CONFIG_IP6_NF_MATCH_HL=m
++CONFIG_IP6_NF_MATCH_IPV6HEADER=m
++CONFIG_IP6_NF_MATCH_MH=m
++CONFIG_IP6_NF_MATCH_RPFILTER=m
++CONFIG_IP6_NF_MATCH_RT=m
++CONFIG_IP6_NF_TARGET_HL=m
++CONFIG_IP6_NF_FILTER=m
++CONFIG_IP6_NF_TARGET_REJECT=m
++CONFIG_IP6_NF_MANGLE=m
++CONFIG_IP6_NF_RAW=m
++CONFIG_IP6_NF_NAT=m
++CONFIG_IP6_NF_TARGET_MASQUERADE=m
++CONFIG_IP6_NF_TARGET_NPT=m
++CONFIG_BRIDGE_NF_EBTABLES=m
++CONFIG_BRIDGE_EBT_BROUTE=m
++CONFIG_BRIDGE_EBT_T_FILTER=m
++CONFIG_BRIDGE_EBT_T_NAT=m
++CONFIG_BRIDGE_EBT_802_3=m
++CONFIG_BRIDGE_EBT_AMONG=m
++CONFIG_BRIDGE_EBT_ARP=m
++CONFIG_BRIDGE_EBT_IP=m
++CONFIG_BRIDGE_EBT_IP6=m
++CONFIG_BRIDGE_EBT_LIMIT=m
++CONFIG_BRIDGE_EBT_MARK=m
++CONFIG_BRIDGE_EBT_PKTTYPE=m
++CONFIG_BRIDGE_EBT_STP=m
++CONFIG_BRIDGE_EBT_VLAN=m
++CONFIG_BRIDGE_EBT_ARPREPLY=m
++CONFIG_BRIDGE_EBT_DNAT=m
++CONFIG_BRIDGE_EBT_MARK_T=m
++CONFIG_BRIDGE_EBT_REDIRECT=m
++CONFIG_BRIDGE_EBT_SNAT=m
++CONFIG_BRIDGE_EBT_LOG=m
++CONFIG_BRIDGE_EBT_NFLOG=m
++CONFIG_SCTP_COOKIE_HMAC_SHA1=y
++CONFIG_ATM=m
++CONFIG_L2TP=m
++CONFIG_L2TP_V3=y
++CONFIG_L2TP_IP=m
++CONFIG_L2TP_ETH=m
++CONFIG_BRIDGE=m
++CONFIG_VLAN_8021Q=m
++CONFIG_VLAN_8021Q_GVRP=y
++CONFIG_ATALK=m
++CONFIG_6LOWPAN=m
++CONFIG_IEEE802154=m
++CONFIG_IEEE802154_6LOWPAN=m
++CONFIG_MAC802154=m
++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
++CONFIG_NET_SCH_SFB=m
++CONFIG_NET_SCH_SFQ=m
++CONFIG_NET_SCH_TEQL=m
++CONFIG_NET_SCH_TBF=m
++CONFIG_NET_SCH_GRED=m
++CONFIG_NET_SCH_DSMARK=m
++CONFIG_NET_SCH_NETEM=m
++CONFIG_NET_SCH_DRR=m
++CONFIG_NET_SCH_MQPRIO=m
++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
++CONFIG_NET_CLS_TCINDEX=m
++CONFIG_NET_CLS_ROUTE4=m
++CONFIG_NET_CLS_FW=m
++CONFIG_NET_CLS_U32=m
++CONFIG_CLS_U32_MARK=y
++CONFIG_NET_CLS_RSVP=m
++CONFIG_NET_CLS_RSVP6=m
++CONFIG_NET_CLS_FLOW=m
++CONFIG_NET_CLS_CGROUP=m
++CONFIG_NET_EMATCH=y
++CONFIG_NET_EMATCH_CMP=m
++CONFIG_NET_EMATCH_NBYTE=m
++CONFIG_NET_EMATCH_U32=m
++CONFIG_NET_EMATCH_META=m
++CONFIG_NET_EMATCH_TEXT=m
++CONFIG_NET_EMATCH_IPSET=m
++CONFIG_NET_CLS_ACT=y
++CONFIG_NET_ACT_POLICE=m
++CONFIG_NET_ACT_GACT=m
++CONFIG_GACT_PROB=y
++CONFIG_NET_ACT_MIRRED=m
++CONFIG_NET_ACT_IPT=m
++CONFIG_NET_ACT_NAT=m
++CONFIG_NET_ACT_PEDIT=m
++CONFIG_NET_ACT_SIMP=m
++CONFIG_NET_ACT_SKBEDIT=m
++CONFIG_NET_ACT_CSUM=m
++CONFIG_BATMAN_ADV=m
++CONFIG_OPENVSWITCH=m
++CONFIG_NET_PKTGEN=m
++CONFIG_HAMRADIO=y
++CONFIG_AX25=m
++CONFIG_NETROM=m
++CONFIG_ROSE=m
++CONFIG_MKISS=m
++CONFIG_6PACK=m
++CONFIG_BPQETHER=m
++CONFIG_BAYCOM_SER_FDX=m
++CONFIG_BAYCOM_SER_HDX=m
++CONFIG_YAM=m
++CONFIG_CAN=m
++CONFIG_CAN_VCAN=m
++CONFIG_CAN_SLCAN=m
++CONFIG_CAN_MCP251X=m
++CONFIG_CAN_GS_USB=m
++CONFIG_BT=m
++CONFIG_BT_RFCOMM=m
++CONFIG_BT_RFCOMM_TTY=y
++CONFIG_BT_BNEP=m
++CONFIG_BT_BNEP_MC_FILTER=y
++CONFIG_BT_BNEP_PROTO_FILTER=y
++CONFIG_BT_HIDP=m
++CONFIG_BT_6LOWPAN=m
++CONFIG_BT_HCIBTUSB=m
++CONFIG_BT_HCIUART=m
++CONFIG_BT_HCIUART_3WIRE=y
++CONFIG_BT_HCIUART_BCM=y
++CONFIG_BT_HCIBCM203X=m
++CONFIG_BT_HCIBPA10X=m
++CONFIG_BT_HCIBFUSB=m
++CONFIG_BT_HCIVHCI=m
++CONFIG_BT_MRVL=m
++CONFIG_BT_MRVL_SDIO=m
++CONFIG_BT_ATH3K=m
++CONFIG_BT_WILINK=m
++CONFIG_CFG80211=m
++CONFIG_MAC80211=m
++CONFIG_MAC80211_MESH=y
++CONFIG_WIMAX=m
++CONFIG_RFKILL=m
++CONFIG_RFKILL_INPUT=y
++CONFIG_NET_9P=m
++CONFIG_NFC=m
++CONFIG_DEVTMPFS=y
++CONFIG_DEVTMPFS_MOUNT=y
++CONFIG_DMA_CMA=y
++CONFIG_CMA_SIZE_MBYTES=5
++CONFIG_MTD=m
++CONFIG_MTD_BLOCK=m
++CONFIG_MTD_M25P80=m
++CONFIG_MTD_BLOCK2MTD=m
++CONFIG_MTD_NAND=m
++CONFIG_MTD_SPI_NOR=m
++CONFIG_MTD_UBI=m
++CONFIG_OF_CONFIGFS=y
++CONFIG_ZRAM=m
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_BLK_DEV_CRYPTOLOOP=m
++CONFIG_BLK_DEV_DRBD=m
++CONFIG_BLK_DEV_NBD=m
++CONFIG_BLK_DEV_RAM=y
++CONFIG_CDROM_PKTCDVD=m
++CONFIG_ATA_OVER_ETH=m
++CONFIG_EEPROM_AT24=m
++CONFIG_TI_ST=m
++CONFIG_SCSI=y
++# CONFIG_SCSI_PROC_FS is not set
++CONFIG_BLK_DEV_SD=y
++CONFIG_CHR_DEV_ST=m
++CONFIG_CHR_DEV_OSST=m
++CONFIG_BLK_DEV_SR=m
++CONFIG_CHR_DEV_SG=m
++CONFIG_SCSI_ISCSI_ATTRS=y
++CONFIG_ISCSI_TCP=m
++CONFIG_ISCSI_BOOT_SYSFS=m
++CONFIG_MD=y
++CONFIG_MD_LINEAR=m
++CONFIG_BLK_DEV_DM=m
++CONFIG_DM_CRYPT=m
++CONFIG_DM_SNAPSHOT=m
++CONFIG_DM_THIN_PROVISIONING=m
++CONFIG_DM_CACHE=m
++CONFIG_DM_MIRROR=m
++CONFIG_DM_LOG_USERSPACE=m
++CONFIG_DM_RAID=m
++CONFIG_DM_ZERO=m
++CONFIG_DM_DELAY=m
++CONFIG_NETDEVICES=y
++CONFIG_BONDING=m
++CONFIG_DUMMY=m
++CONFIG_IFB=m
++CONFIG_MACVLAN=m
++CONFIG_IPVLAN=m
++CONFIG_VXLAN=m
++CONFIG_NETCONSOLE=m
++CONFIG_TUN=m
++CONFIG_VETH=m
++CONFIG_BCMGENET=y
++CONFIG_ENC28J60=m
++CONFIG_QCA7000_SPI=m
++CONFIG_MDIO_BITBANG=m
++CONFIG_BROADCOM_PHY=y
++CONFIG_PPP=m
++CONFIG_PPP_BSDCOMP=m
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_FILTER=y
++CONFIG_PPP_MPPE=m
++CONFIG_PPP_MULTILINK=y
++CONFIG_PPPOATM=m
++CONFIG_PPPOE=m
++CONFIG_PPPOL2TP=m
++CONFIG_PPP_ASYNC=m
++CONFIG_PPP_SYNC_TTY=m
++CONFIG_SLIP=m
++CONFIG_SLIP_COMPRESSED=y
++CONFIG_SLIP_SMART=y
++CONFIG_USB_CATC=m
++CONFIG_USB_KAWETH=m
++CONFIG_USB_PEGASUS=m
++CONFIG_USB_RTL8150=m
++CONFIG_USB_RTL8152=y
++CONFIG_USB_LAN78XX=y
++CONFIG_USB_USBNET=y
++CONFIG_USB_NET_AX88179_178A=m
++CONFIG_USB_NET_CDCETHER=m
++CONFIG_USB_NET_CDC_EEM=m
++CONFIG_USB_NET_CDC_NCM=m
++CONFIG_USB_NET_HUAWEI_CDC_NCM=m
++CONFIG_USB_NET_CDC_MBIM=m
++CONFIG_USB_NET_DM9601=m
++CONFIG_USB_NET_SR9700=m
++CONFIG_USB_NET_SR9800=m
++CONFIG_USB_NET_SMSC75XX=m
++CONFIG_USB_NET_SMSC95XX=y
++CONFIG_USB_NET_GL620A=m
++CONFIG_USB_NET_NET1080=m
++CONFIG_USB_NET_PLUSB=m
++CONFIG_USB_NET_MCS7830=m
++CONFIG_USB_NET_CDC_SUBSET=m
++CONFIG_USB_ALI_M5632=y
++CONFIG_USB_AN2720=y
++CONFIG_USB_EPSON2888=y
++CONFIG_USB_KC2190=y
++CONFIG_USB_NET_ZAURUS=m
++CONFIG_USB_NET_CX82310_ETH=m
++CONFIG_USB_NET_KALMIA=m
++CONFIG_USB_NET_QMI_WWAN=m
++CONFIG_USB_HSO=m
++CONFIG_USB_NET_INT51X1=m
++CONFIG_USB_IPHETH=m
++CONFIG_USB_SIERRA_NET=m
++CONFIG_USB_VL600=m
++CONFIG_ATH9K=m
++CONFIG_ATH9K_HTC=m
++CONFIG_CARL9170=m
++CONFIG_ATH6KL=m
++CONFIG_ATH6KL_USB=m
++CONFIG_AR5523=m
++CONFIG_AT76C50X_USB=m
++CONFIG_B43=m
++# CONFIG_B43_PHY_N is not set
++CONFIG_B43LEGACY=m
++CONFIG_BRCMFMAC=m
++CONFIG_BRCMFMAC_USB=y
++CONFIG_BRCMDBG=y
++CONFIG_HOSTAP=m
++CONFIG_P54_COMMON=m
++CONFIG_P54_USB=m
++CONFIG_LIBERTAS=m
++CONFIG_LIBERTAS_USB=m
++CONFIG_LIBERTAS_SDIO=m
++CONFIG_LIBERTAS_THINFIRM=m
++CONFIG_LIBERTAS_THINFIRM_USB=m
++CONFIG_MWIFIEX=m
++CONFIG_MWIFIEX_SDIO=m
++CONFIG_MT7601U=m
++CONFIG_RT2X00=m
++CONFIG_RT2500USB=m
++CONFIG_RT73USB=m
++CONFIG_RT2800USB=m
++CONFIG_RT2800USB_RT3573=y
++CONFIG_RT2800USB_RT53XX=y
++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
++CONFIG_USB_NET_RNDIS_WLAN=m
++CONFIG_WIMAX_I2400M_USB=m
++CONFIG_IEEE802154_AT86RF230=m
++CONFIG_IEEE802154_MRF24J40=m
++CONFIG_IEEE802154_CC2520=m
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_JOYDEV=m
++CONFIG_INPUT_EVDEV=m
++# CONFIG_KEYBOARD_ATKBD is not set
++CONFIG_KEYBOARD_GPIO=m
++CONFIG_KEYBOARD_MATRIX=m
++# CONFIG_INPUT_MOUSE is not set
++CONFIG_INPUT_JOYSTICK=y
++CONFIG_JOYSTICK_IFORCE=m
++CONFIG_JOYSTICK_IFORCE_USB=y
++CONFIG_JOYSTICK_XPAD=m
++CONFIG_JOYSTICK_XPAD_FF=y
++CONFIG_JOYSTICK_XPAD_LEDS=y
++CONFIG_JOYSTICK_PSXPAD_SPI=m
++CONFIG_JOYSTICK_PSXPAD_SPI_FF=y
++CONFIG_JOYSTICK_RPISENSE=m
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_TOUCHSCREEN_ADS7846=m
++CONFIG_TOUCHSCREEN_EGALAX=m
++CONFIG_TOUCHSCREEN_EXC3000=m
++CONFIG_TOUCHSCREEN_GOODIX=m
++CONFIG_TOUCHSCREEN_EDT_FT5X06=m
++CONFIG_TOUCHSCREEN_RPI_FT5406=m
++CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
++CONFIG_TOUCHSCREEN_STMPE=m
++CONFIG_INPUT_MISC=y
++CONFIG_INPUT_AD714X=m
++CONFIG_INPUT_ATI_REMOTE2=m
++CONFIG_INPUT_KEYSPAN_REMOTE=m
++CONFIG_INPUT_POWERMATE=m
++CONFIG_INPUT_YEALINK=m
++CONFIG_INPUT_CM109=m
++CONFIG_INPUT_UINPUT=m
++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
++CONFIG_INPUT_ADXL34X=m
++CONFIG_INPUT_CMA3000=m
++CONFIG_SERIO=m
++CONFIG_SERIO_RAW=m
++CONFIG_GAMEPORT=m
++CONFIG_GAMEPORT_NS558=m
++CONFIG_GAMEPORT_L4=m
++CONFIG_BRCM_CHAR_DRIVERS=y
++CONFIG_BCM_VCIO=y
++CONFIG_BCM_VC_SM=y
++CONFIG_BCM2835_DEVGPIOMEM=y
++CONFIG_ARGON_MEM=m
++# CONFIG_LEGACY_PTYS is not set
++CONFIG_SERIAL_8250=y
++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_DMA is not set
++CONFIG_SERIAL_8250_NR_UARTS=1
++CONFIG_SERIAL_8250_RUNTIME_UARTS=0
++CONFIG_SERIAL_8250_EXTENDED=y
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++CONFIG_SERIAL_8250_BCM2835AUX=y
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_SERIAL_AMBA_PL011=y
++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
++CONFIG_SERIAL_SC16IS7XX=m
++CONFIG_SERIAL_SC16IS7XX_SPI=y
++CONFIG_SERIAL_DEV_BUS=m
++CONFIG_TTY_PRINTK=y
++CONFIG_HW_RANDOM=y
++CONFIG_RAW_DRIVER=y
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=m
++CONFIG_I2C_BCM2708=m
++CONFIG_I2C_BCM2835=m
++CONFIG_I2C_GPIO=m
++CONFIG_I2C_ROBOTFUZZ_OSIF=m
++CONFIG_I2C_TINY_USB=m
++CONFIG_SPI=y
++CONFIG_SPI_BCM2835=m
++CONFIG_SPI_BCM2835AUX=m
++CONFIG_SPI_SPIDEV=m
++CONFIG_SPI_SLAVE=y
++CONFIG_PPS=m
++CONFIG_PPS_CLIENT_LDISC=m
++CONFIG_PPS_CLIENT_GPIO=m
++CONFIG_PINCTRL_MCP23S08=m
++CONFIG_GPIO_BCM_VIRT=y
++CONFIG_GPIO_MOCKUP=m
++CONFIG_GPIO_PCF857X=m
++CONFIG_GPIO_ARIZONA=m
++CONFIG_GPIO_STMPE=y
++CONFIG_W1=m
++CONFIG_W1_MASTER_DS2490=m
++CONFIG_W1_MASTER_DS2482=m
++CONFIG_W1_MASTER_DS1WM=m
++CONFIG_W1_MASTER_GPIO=m
++CONFIG_W1_SLAVE_THERM=m
++CONFIG_W1_SLAVE_SMEM=m
++CONFIG_W1_SLAVE_DS2408=m
++CONFIG_W1_SLAVE_DS2413=m
++CONFIG_W1_SLAVE_DS2406=m
++CONFIG_W1_SLAVE_DS2423=m
++CONFIG_W1_SLAVE_DS2431=m
++CONFIG_W1_SLAVE_DS2433=m
++CONFIG_W1_SLAVE_DS2438=m
++CONFIG_W1_SLAVE_DS2780=m
++CONFIG_W1_SLAVE_DS2781=m
++CONFIG_W1_SLAVE_DS28E04=m
++CONFIG_POWER_RESET=y
++CONFIG_POWER_RESET_GPIO=y
++CONFIG_BATTERY_DS2760=m
++CONFIG_BATTERY_GAUGE_LTC2941=m
++CONFIG_HWMON=m
++CONFIG_SENSORS_DS1621=m
++CONFIG_SENSORS_JC42=m
++CONFIG_SENSORS_LM75=m
++CONFIG_SENSORS_RPI_POE_FAN=m
++CONFIG_SENSORS_SHT21=m
++CONFIG_SENSORS_SHT3x=m
++CONFIG_SENSORS_SHTC1=m
++CONFIG_SENSORS_ADS1015=m
++CONFIG_SENSORS_INA2XX=m
++CONFIG_SENSORS_TMP102=m
++CONFIG_THERMAL=y
++CONFIG_BCM2835_THERMAL=y
++CONFIG_BRCMSTB_THERMAL=y
++CONFIG_WATCHDOG=y
++CONFIG_GPIO_WATCHDOG=m
++CONFIG_BCM2835_WDT=y
++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_LDO1=m
++CONFIG_REGULATOR_ARIZONA_MICSUPP=m
++CONFIG_REGULATOR_GPIO=y
++CONFIG_MEDIA_SUPPORT=m
++CONFIG_MEDIA_CAMERA_SUPPORT=y
++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
++CONFIG_MEDIA_RADIO_SUPPORT=y
++CONFIG_MEDIA_CONTROLLER=y
++CONFIG_VIDEO_V4L2_SUBDEV_API=y
++CONFIG_MEDIA_USB_SUPPORT=y
++CONFIG_USB_VIDEO_CLASS=m
++CONFIG_USB_M5602=m
++CONFIG_USB_STV06XX=m
++CONFIG_USB_GL860=m
++CONFIG_USB_GSPCA_BENQ=m
++CONFIG_USB_GSPCA_CONEX=m
++CONFIG_USB_GSPCA_CPIA1=m
++CONFIG_USB_GSPCA_DTCS033=m
++CONFIG_USB_GSPCA_ETOMS=m
++CONFIG_USB_GSPCA_FINEPIX=m
++CONFIG_USB_GSPCA_JEILINJ=m
++CONFIG_USB_GSPCA_JL2005BCD=m
++CONFIG_USB_GSPCA_KINECT=m
++CONFIG_USB_GSPCA_KONICA=m
++CONFIG_USB_GSPCA_MARS=m
++CONFIG_USB_GSPCA_MR97310A=m
++CONFIG_USB_GSPCA_NW80X=m
++CONFIG_USB_GSPCA_OV519=m
++CONFIG_USB_GSPCA_OV534=m
++CONFIG_USB_GSPCA_OV534_9=m
++CONFIG_USB_GSPCA_PAC207=m
++CONFIG_USB_GSPCA_PAC7302=m
++CONFIG_USB_GSPCA_PAC7311=m
++CONFIG_USB_GSPCA_SE401=m
++CONFIG_USB_GSPCA_SN9C2028=m
++CONFIG_USB_GSPCA_SN9C20X=m
++CONFIG_USB_GSPCA_SONIXB=m
++CONFIG_USB_GSPCA_SONIXJ=m
++CONFIG_USB_GSPCA_SPCA500=m
++CONFIG_USB_GSPCA_SPCA501=m
++CONFIG_USB_GSPCA_SPCA505=m
++CONFIG_USB_GSPCA_SPCA506=m
++CONFIG_USB_GSPCA_SPCA508=m
++CONFIG_USB_GSPCA_SPCA561=m
++CONFIG_USB_GSPCA_SPCA1528=m
++CONFIG_USB_GSPCA_SQ905=m
++CONFIG_USB_GSPCA_SQ905C=m
++CONFIG_USB_GSPCA_SQ930X=m
++CONFIG_USB_GSPCA_STK014=m
++CONFIG_USB_GSPCA_STK1135=m
++CONFIG_USB_GSPCA_STV0680=m
++CONFIG_USB_GSPCA_SUNPLUS=m
++CONFIG_USB_GSPCA_T613=m
++CONFIG_USB_GSPCA_TOPRO=m
++CONFIG_USB_GSPCA_TV8532=m
++CONFIG_USB_GSPCA_VC032X=m
++CONFIG_USB_GSPCA_VICAM=m
++CONFIG_USB_GSPCA_XIRLINK_CIT=m
++CONFIG_USB_GSPCA_ZC3XX=m
++CONFIG_USB_PWC=m
++CONFIG_VIDEO_CPIA2=m
++CONFIG_USB_ZR364XX=m
++CONFIG_USB_STKWEBCAM=m
++CONFIG_USB_S2255=m
++CONFIG_VIDEO_USBTV=m
++CONFIG_VIDEO_PVRUSB2=m
++CONFIG_VIDEO_HDPVR=m
++CONFIG_VIDEO_USBVISION=m
++CONFIG_VIDEO_STK1160_COMMON=m
++CONFIG_VIDEO_GO7007=m
++CONFIG_VIDEO_GO7007_USB=m
++CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m
++CONFIG_VIDEO_AU0828=m
++CONFIG_DVB_USB_V2=m
++CONFIG_DVB_USB_AF9035=m
++CONFIG_DVB_USB_ANYSEE=m
++CONFIG_DVB_USB_AU6610=m
++CONFIG_DVB_USB_AZ6007=m
++CONFIG_DVB_USB_CE6230=m
++CONFIG_DVB_USB_EC168=m
++CONFIG_DVB_USB_GL861=m
++CONFIG_DVB_USB_MXL111SF=m
++CONFIG_DVB_USB_DVBSKY=m
++CONFIG_SMS_USB_DRV=m
++CONFIG_DVB_B2C2_FLEXCOP_USB=m
++CONFIG_DVB_AS102=m
++CONFIG_VIDEO_EM28XX=m
++CONFIG_VIDEO_EM28XX_V4L2=m
++CONFIG_VIDEO_EM28XX_ALSA=m
++CONFIG_VIDEO_EM28XX_DVB=m
++CONFIG_V4L_PLATFORM_DRIVERS=y
++CONFIG_VIDEO_BCM2835_UNICAM=m
++CONFIG_RADIO_SI470X=m
++CONFIG_USB_SI470X=m
++CONFIG_I2C_SI470X=m
++CONFIG_RADIO_SI4713=m
++CONFIG_I2C_SI4713=m
++CONFIG_USB_MR800=m
++CONFIG_USB_DSBR=m
++CONFIG_RADIO_SHARK=m
++CONFIG_RADIO_SHARK2=m
++CONFIG_USB_KEENE=m
++CONFIG_USB_MA901=m
++CONFIG_RADIO_TEA5764=m
++CONFIG_RADIO_SAA7706H=m
++CONFIG_RADIO_TEF6862=m
++CONFIG_RADIO_WL1273=m
++CONFIG_RADIO_WL128X=m
++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
++CONFIG_VIDEO_UDA1342=m
++CONFIG_VIDEO_SONY_BTF_MPX=m
++CONFIG_VIDEO_ADV7180=m
++CONFIG_VIDEO_TC358743=m
++CONFIG_VIDEO_TVP5150=m
++CONFIG_VIDEO_TW2804=m
++CONFIG_VIDEO_TW9903=m
++CONFIG_VIDEO_TW9906=m
++CONFIG_VIDEO_OV5647=m
++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_V3D=m
++CONFIG_DRM_VC4=m
++CONFIG_DRM_TINYDRM=m
++CONFIG_TINYDRM_MI0283QT=m
++CONFIG_TINYDRM_REPAPER=m
++CONFIG_FB=y
++CONFIG_FB_BCM2708=y
++CONFIG_FB_UDL=m
++CONFIG_FB_SIMPLE=y
++CONFIG_FB_SSD1307=m
++CONFIG_FB_RPISENSE=m
++# CONFIG_BACKLIGHT_GENERIC is not set
++CONFIG_BACKLIGHT_RPI=m
++CONFIG_BACKLIGHT_GPIO=m
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_LOGO=y
++# CONFIG_LOGO_LINUX_MONO is not set
++# CONFIG_LOGO_LINUX_VGA16 is not set
++CONFIG_SOUND=y
++CONFIG_SND=m
++CONFIG_SND_HRTIMER=m
++CONFIG_SND_SEQUENCER=m
++CONFIG_SND_SEQ_DUMMY=m
++CONFIG_SND_DUMMY=m
++CONFIG_SND_ALOOP=m
++CONFIG_SND_VIRMIDI=m
++CONFIG_SND_MTPAV=m
++CONFIG_SND_SERIAL_U16550=m
++CONFIG_SND_MPU401=m
++CONFIG_SND_USB_AUDIO=m
++CONFIG_SND_USB_UA101=m
++CONFIG_SND_USB_CAIAQ=m
++CONFIG_SND_USB_CAIAQ_INPUT=y
++CONFIG_SND_USB_6FIRE=m
++CONFIG_SND_USB_HIFACE=m
++CONFIG_SND_SOC=m
++CONFIG_SND_BCM2835_SOC_I2S=m
++CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=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
++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
++CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC=m
++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=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_ALLO_PIANO_DAC_PLUS=m
++CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC=m
++CONFIG_SND_BCM2708_SOC_ALLO_DIGIONE=m
++CONFIG_SND_BCM2708_SOC_ALLO_KATANA_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_CS4271_I2C=m
++CONFIG_SND_SOC_SPDIF=m
++CONFIG_SND_SOC_WM8804_I2C=m
++CONFIG_SND_SIMPLE_CARD=m
++CONFIG_HID_BATTERY_STRENGTH=y
++CONFIG_HIDRAW=y
++CONFIG_UHID=m
++CONFIG_HID_A4TECH=m
++CONFIG_HID_ACRUX=m
++CONFIG_HID_APPLE=m
++CONFIG_HID_ASUS=m
++CONFIG_HID_BELKIN=m
++CONFIG_HID_BETOP_FF=m
++CONFIG_HID_CHERRY=m
++CONFIG_HID_CHICONY=m
++CONFIG_HID_CYPRESS=m
++CONFIG_HID_DRAGONRISE=m
++CONFIG_HID_EMS_FF=m
++CONFIG_HID_ELECOM=m
++CONFIG_HID_ELO=m
++CONFIG_HID_EZKEY=m
++CONFIG_HID_GEMBIRD=m
++CONFIG_HID_HOLTEK=m
++CONFIG_HID_KEYTOUCH=m
++CONFIG_HID_KYE=m
++CONFIG_HID_UCLOGIC=m
++CONFIG_HID_WALTOP=m
++CONFIG_HID_GYRATION=m
++CONFIG_HID_TWINHAN=m
++CONFIG_HID_KENSINGTON=m
++CONFIG_HID_LCPOWER=m
++CONFIG_HID_LOGITECH=m
++CONFIG_HID_LOGITECH_DJ=m
++CONFIG_LOGITECH_FF=y
++CONFIG_LOGIRUMBLEPAD2_FF=y
++CONFIG_LOGIG940_FF=y
++CONFIG_HID_MAGICMOUSE=m
++CONFIG_HID_MICROSOFT=m
++CONFIG_HID_MONTEREY=m
++CONFIG_HID_MULTITOUCH=m
++CONFIG_HID_NTRIG=m
++CONFIG_HID_ORTEK=m
++CONFIG_HID_PANTHERLORD=m
++CONFIG_HID_PETALYNX=m
++CONFIG_HID_PICOLCD=m
++CONFIG_HID_ROCCAT=m
++CONFIG_HID_SAMSUNG=m
++CONFIG_HID_SONY=m
++CONFIG_SONY_FF=y
++CONFIG_HID_SPEEDLINK=m
++CONFIG_HID_SUNPLUS=m
++CONFIG_HID_GREENASIA=m
++CONFIG_HID_SMARTJOYPLUS=m
++CONFIG_HID_TOPSEED=m
++CONFIG_HID_THINGM=m
++CONFIG_HID_THRUSTMASTER=m
++CONFIG_HID_WACOM=m
++CONFIG_HID_WIIMOTE=m
++CONFIG_HID_XINMO=m
++CONFIG_HID_ZEROPLUS=m
++CONFIG_HID_ZYDACRON=m
++CONFIG_HID_PID=y
++CONFIG_USB_HIDDEV=y
++CONFIG_USB=y
++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
++CONFIG_USB_MON=m
++CONFIG_USB_XHCI_HCD=y
++CONFIG_USB_DWCOTG=y
++CONFIG_USB_PRINTER=m
++CONFIG_USB_STORAGE=y
++CONFIG_USB_STORAGE_REALTEK=m
++CONFIG_USB_STORAGE_DATAFAB=m
++CONFIG_USB_STORAGE_FREECOM=m
++CONFIG_USB_STORAGE_ISD200=m
++CONFIG_USB_STORAGE_USBAT=m
++CONFIG_USB_STORAGE_SDDR09=m
++CONFIG_USB_STORAGE_SDDR55=m
++CONFIG_USB_STORAGE_JUMPSHOT=m
++CONFIG_USB_STORAGE_ALAUDA=m
++CONFIG_USB_STORAGE_ONETOUCH=m
++CONFIG_USB_STORAGE_KARMA=m
++CONFIG_USB_STORAGE_CYPRESS_ATACB=m
++CONFIG_USB_STORAGE_ENE_UB6250=m
++CONFIG_USB_UAS=y
++CONFIG_USB_MDC800=m
++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
++CONFIG_USB_SERIAL_ARK3116=m
++CONFIG_USB_SERIAL_BELKIN=m
++CONFIG_USB_SERIAL_CH341=m
++CONFIG_USB_SERIAL_WHITEHEAT=m
++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
++CONFIG_USB_SERIAL_CP210X=m
++CONFIG_USB_SERIAL_CYPRESS_M8=m
++CONFIG_USB_SERIAL_EMPEG=m
++CONFIG_USB_SERIAL_FTDI_SIO=m
++CONFIG_USB_SERIAL_VISOR=m
++CONFIG_USB_SERIAL_IPAQ=m
++CONFIG_USB_SERIAL_IR=m
++CONFIG_USB_SERIAL_EDGEPORT=m
++CONFIG_USB_SERIAL_EDGEPORT_TI=m
++CONFIG_USB_SERIAL_F81232=m
++CONFIG_USB_SERIAL_GARMIN=m
++CONFIG_USB_SERIAL_IPW=m
++CONFIG_USB_SERIAL_IUU=m
++CONFIG_USB_SERIAL_KEYSPAN_PDA=m
++CONFIG_USB_SERIAL_KEYSPAN=m
++CONFIG_USB_SERIAL_KLSI=m
++CONFIG_USB_SERIAL_KOBIL_SCT=m
++CONFIG_USB_SERIAL_MCT_U232=m
++CONFIG_USB_SERIAL_METRO=m
++CONFIG_USB_SERIAL_MOS7720=m
++CONFIG_USB_SERIAL_MOS7840=m
++CONFIG_USB_SERIAL_NAVMAN=m
++CONFIG_USB_SERIAL_PL2303=m
++CONFIG_USB_SERIAL_OTI6858=m
++CONFIG_USB_SERIAL_QCAUX=m
++CONFIG_USB_SERIAL_QUALCOMM=m
++CONFIG_USB_SERIAL_SPCP8X5=m
++CONFIG_USB_SERIAL_SAFE=m
++CONFIG_USB_SERIAL_SIERRAWIRELESS=m
++CONFIG_USB_SERIAL_SYMBOL=m
++CONFIG_USB_SERIAL_TI=m
++CONFIG_USB_SERIAL_CYBERJACK=m
++CONFIG_USB_SERIAL_XIRCOM=m
++CONFIG_USB_SERIAL_OPTION=m
++CONFIG_USB_SERIAL_OMNINET=m
++CONFIG_USB_SERIAL_OPTICON=m
++CONFIG_USB_SERIAL_XSENS_MT=m
++CONFIG_USB_SERIAL_WISHBONE=m
++CONFIG_USB_SERIAL_SSU100=m
++CONFIG_USB_SERIAL_QT2=m
++CONFIG_USB_SERIAL_DEBUG=m
++CONFIG_USB_EMI62=m
++CONFIG_USB_EMI26=m
++CONFIG_USB_ADUTUX=m
++CONFIG_USB_SEVSEG=m
++CONFIG_USB_RIO500=m
++CONFIG_USB_LEGOTOWER=m
++CONFIG_USB_LCD=m
++CONFIG_USB_CYPRESS_CY7C63=m
++CONFIG_USB_CYTHERM=m
++CONFIG_USB_IDMOUSE=m
++CONFIG_USB_FTDI_ELAN=m
++CONFIG_USB_APPLEDISPLAY=m
++CONFIG_USB_LD=m
++CONFIG_USB_TRANCEVIBRATOR=m
++CONFIG_USB_IOWARRIOR=m
++CONFIG_USB_TEST=m
++CONFIG_USB_ISIGHTFW=m
++CONFIG_USB_YUREX=m
++CONFIG_USB_ATM=m
++CONFIG_USB_SPEEDTOUCH=m
++CONFIG_USB_CXACRU=m
++CONFIG_USB_UEAGLEATM=m
++CONFIG_USB_XUSBATM=m
++CONFIG_USB_GADGET=m
++CONFIG_USB_CONFIGFS=m
++CONFIG_USB_CONFIGFS_SERIAL=y
++CONFIG_USB_CONFIGFS_ACM=y
++CONFIG_USB_CONFIGFS_OBEX=y
++CONFIG_USB_CONFIGFS_NCM=y
++CONFIG_USB_CONFIGFS_ECM=y
++CONFIG_USB_CONFIGFS_ECM_SUBSET=y
++CONFIG_USB_CONFIGFS_RNDIS=y
++CONFIG_USB_CONFIGFS_EEM=y
++CONFIG_USB_CONFIGFS_MASS_STORAGE=y
++CONFIG_USB_CONFIGFS_F_LB_SS=y
++CONFIG_USB_CONFIGFS_F_FS=y
++CONFIG_USB_CONFIGFS_F_UAC1=y
++CONFIG_USB_CONFIGFS_F_UAC2=y
++CONFIG_USB_CONFIGFS_F_MIDI=y
++CONFIG_USB_CONFIGFS_F_HID=y
++CONFIG_USB_CONFIGFS_F_UVC=y
++CONFIG_USB_CONFIGFS_F_PRINTER=y
++CONFIG_USB_ZERO=m
++CONFIG_USB_AUDIO=m
++CONFIG_USB_ETH=m
++CONFIG_USB_GADGETFS=m
++CONFIG_USB_MASS_STORAGE=m
++CONFIG_USB_G_SERIAL=m
++CONFIG_USB_MIDI_GADGET=m
++CONFIG_USB_G_PRINTER=m
++CONFIG_USB_CDC_COMPOSITE=m
++CONFIG_USB_G_ACM_MS=m
++CONFIG_USB_G_MULTI=m
++CONFIG_USB_G_HID=m
++CONFIG_USB_G_WEBCAM=m
++CONFIG_MMC=y
++CONFIG_MMC_BLOCK_MINORS=32
++CONFIG_MMC_BCM2835_MMC=y
++CONFIG_MMC_BCM2835_DMA=y
++CONFIG_MMC_BCM2835_SDHOST=y
++CONFIG_MMC_SDHCI=y
++CONFIG_MMC_SDHCI_PLTFM=y
++CONFIG_MMC_SDHCI_IPROC=y
++CONFIG_MMC_SPI=m
++CONFIG_LEDS_CLASS=y
++CONFIG_LEDS_GPIO=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_ONESHOT=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++CONFIG_LEDS_TRIGGER_BACKLIGHT=y
++CONFIG_LEDS_TRIGGER_CPU=y
++CONFIG_LEDS_TRIGGER_GPIO=y
++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
++CONFIG_LEDS_TRIGGER_TRANSIENT=m
++CONFIG_LEDS_TRIGGER_CAMERA=m
++CONFIG_LEDS_TRIGGER_INPUT=y
++CONFIG_LEDS_TRIGGER_PANIC=y
++CONFIG_RTC_CLASS=y
++# CONFIG_RTC_HCTOSYS is not set
++CONFIG_RTC_DRV_ABX80X=m
++CONFIG_RTC_DRV_DS1307=m
++CONFIG_RTC_DRV_DS1374=m
++CONFIG_RTC_DRV_DS1672=m
++CONFIG_RTC_DRV_MAX6900=m
++CONFIG_RTC_DRV_RS5C372=m
++CONFIG_RTC_DRV_ISL1208=m
++CONFIG_RTC_DRV_ISL12022=m
++CONFIG_RTC_DRV_X1205=m
++CONFIG_RTC_DRV_PCF8523=m
++CONFIG_RTC_DRV_PCF8563=m
++CONFIG_RTC_DRV_PCF8583=m
++CONFIG_RTC_DRV_M41T80=m
++CONFIG_RTC_DRV_BQ32K=m
++CONFIG_RTC_DRV_S35390A=m
++CONFIG_RTC_DRV_FM3130=m
++CONFIG_RTC_DRV_RX8581=m
++CONFIG_RTC_DRV_RX8025=m
++CONFIG_RTC_DRV_EM3027=m
++CONFIG_RTC_DRV_M41T93=m
++CONFIG_RTC_DRV_M41T94=m
++CONFIG_RTC_DRV_DS1302=m
++CONFIG_RTC_DRV_DS1305=m
++CONFIG_RTC_DRV_DS1390=m
++CONFIG_RTC_DRV_R9701=m
++CONFIG_RTC_DRV_RX4581=m
++CONFIG_RTC_DRV_RS5C348=m
++CONFIG_RTC_DRV_MAX6902=m
++CONFIG_RTC_DRV_PCF2123=m
++CONFIG_RTC_DRV_DS3232=m
++CONFIG_RTC_DRV_PCF2127=m
++CONFIG_RTC_DRV_RV3029C2=m
++CONFIG_DMADEVICES=y
++CONFIG_DMA_BCM2835=y
++CONFIG_DMA_BCM2708=y
++CONFIG_UIO=m
++CONFIG_UIO_PDRV_GENIRQ=m
++CONFIG_STAGING=y
++CONFIG_PRISM2_USB=m
++CONFIG_R8712U=m
++CONFIG_R8188EU=m
++CONFIG_VT6656=m
++CONFIG_SPEAKUP=m
++CONFIG_SPEAKUP_SYNTH_SOFT=m
++CONFIG_STAGING_MEDIA=y
++CONFIG_FB_TFT=m
++CONFIG_FB_TFT_AGM1264K_FL=m
++CONFIG_FB_TFT_BD663474=m
++CONFIG_FB_TFT_HX8340BN=m
++CONFIG_FB_TFT_HX8347D=m
++CONFIG_FB_TFT_HX8353D=m
++CONFIG_FB_TFT_HX8357D=m
++CONFIG_FB_TFT_ILI9163=m
++CONFIG_FB_TFT_ILI9320=m
++CONFIG_FB_TFT_ILI9325=m
++CONFIG_FB_TFT_ILI9340=m
++CONFIG_FB_TFT_ILI9341=m
++CONFIG_FB_TFT_ILI9481=m
++CONFIG_FB_TFT_ILI9486=m
++CONFIG_FB_TFT_PCD8544=m
++CONFIG_FB_TFT_RA8875=m
++CONFIG_FB_TFT_S6D02A1=m
++CONFIG_FB_TFT_S6D1121=m
++CONFIG_FB_TFT_SSD1289=m
++CONFIG_FB_TFT_SSD1306=m
++CONFIG_FB_TFT_SSD1331=m
++CONFIG_FB_TFT_SSD1351=m
++CONFIG_FB_TFT_ST7735R=m
++CONFIG_FB_TFT_ST7789V=m
++CONFIG_FB_TFT_TINYLCD=m
++CONFIG_FB_TFT_TLS8204=m
++CONFIG_FB_TFT_UC1701=m
++CONFIG_FB_TFT_UPD161704=m
++CONFIG_FB_TFT_WATTEROTT=m
++CONFIG_FB_FLEX=m
++CONFIG_FB_TFT_FBTFT_DEVICE=m
++CONFIG_BCM2835_VCHIQ=y
++CONFIG_SND_BCM2835=m
++CONFIG_VIDEO_BCM2835=m
++CONFIG_VIDEO_CODEC_BCM2835=m
++CONFIG_MAILBOX=y
++CONFIG_BCM2835_MBOX=y
++# CONFIG_IOMMU_SUPPORT is not set
++CONFIG_BCM2835_POWER=y
++CONFIG_RASPBERRYPI_POWER=y
++CONFIG_EXTCON=m
++CONFIG_EXTCON_ARIZONA=m
++CONFIG_IIO=m
++CONFIG_IIO_BUFFER_CB=m
++CONFIG_MCP320X=m
++CONFIG_MCP3422=m
++CONFIG_DHT11=m
++CONFIG_HDC100X=m
++CONFIG_HTU21=m
++CONFIG_TSL4531=m
++CONFIG_VEML6070=m
++CONFIG_BMP280=m
++CONFIG_PWM_BCM2835=m
++CONFIG_PWM_PCA9685=m
++CONFIG_GENERIC_PHY=y
++CONFIG_RPI_AXIPERF=m
++CONFIG_EXT4_FS=y
++CONFIG_EXT4_FS_POSIX_ACL=y
++CONFIG_EXT4_FS_SECURITY=y
++CONFIG_REISERFS_FS=m
++CONFIG_REISERFS_FS_XATTR=y
++CONFIG_REISERFS_FS_POSIX_ACL=y
++CONFIG_REISERFS_FS_SECURITY=y
++CONFIG_JFS_FS=m
++CONFIG_JFS_POSIX_ACL=y
++CONFIG_JFS_SECURITY=y
++CONFIG_JFS_STATISTICS=y
++CONFIG_XFS_FS=m
++CONFIG_XFS_QUOTA=y
++CONFIG_XFS_POSIX_ACL=y
++CONFIG_XFS_RT=y
++CONFIG_GFS2_FS=m
++CONFIG_OCFS2_FS=m
++CONFIG_BTRFS_FS=m
++CONFIG_BTRFS_FS_POSIX_ACL=y
++CONFIG_NILFS2_FS=m
++CONFIG_F2FS_FS=y
++CONFIG_FANOTIFY=y
++CONFIG_QFMT_V1=m
++CONFIG_QFMT_V2=m
++CONFIG_AUTOFS4_FS=y
++CONFIG_FUSE_FS=m
++CONFIG_CUSE=m
++CONFIG_OVERLAY_FS=m
++CONFIG_FSCACHE=y
++CONFIG_FSCACHE_STATS=y
++CONFIG_FSCACHE_HISTOGRAM=y
++CONFIG_CACHEFILES=y
++CONFIG_ISO9660_FS=m
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_UDF_FS=m
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
++CONFIG_NTFS_FS=m
++CONFIG_NTFS_RW=y
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++CONFIG_ECRYPT_FS=m
++CONFIG_HFS_FS=m
++CONFIG_HFSPLUS_FS=m
++CONFIG_JFFS2_FS=m
++CONFIG_JFFS2_SUMMARY=y
++CONFIG_UBIFS_FS=m
++CONFIG_SQUASHFS=m
++CONFIG_SQUASHFS_XATTR=y
++CONFIG_SQUASHFS_LZO=y
++CONFIG_SQUASHFS_XZ=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3_ACL=y
++CONFIG_NFS_V4=y
++CONFIG_NFS_SWAP=y
++CONFIG_NFS_V4_1=y
++CONFIG_ROOT_NFS=y
++CONFIG_NFS_FSCACHE=y
++CONFIG_NFSD=m
++CONFIG_NFSD_V3_ACL=y
++CONFIG_NFSD_V4=y
++CONFIG_CIFS=m
++CONFIG_CIFS_WEAK_PW_HASH=y
++CONFIG_CIFS_UPCALL=y
++CONFIG_CIFS_XATTR=y
++CONFIG_CIFS_POSIX=y
++CONFIG_CIFS_ACL=y
++CONFIG_CIFS_DFS_UPCALL=y
++CONFIG_CIFS_FSCACHE=y
++CONFIG_9P_FS=m
++CONFIG_9P_FS_POSIX_ACL=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++CONFIG_NLS_CODEPAGE_737=m
++CONFIG_NLS_CODEPAGE_775=m
++CONFIG_NLS_CODEPAGE_850=m
++CONFIG_NLS_CODEPAGE_852=m
++CONFIG_NLS_CODEPAGE_855=m
++CONFIG_NLS_CODEPAGE_857=m
++CONFIG_NLS_CODEPAGE_860=m
++CONFIG_NLS_CODEPAGE_861=m
++CONFIG_NLS_CODEPAGE_862=m
++CONFIG_NLS_CODEPAGE_863=m
++CONFIG_NLS_CODEPAGE_864=m
++CONFIG_NLS_CODEPAGE_865=m
++CONFIG_NLS_CODEPAGE_866=m
++CONFIG_NLS_CODEPAGE_869=m
++CONFIG_NLS_CODEPAGE_936=m
++CONFIG_NLS_CODEPAGE_950=m
++CONFIG_NLS_CODEPAGE_932=m
++CONFIG_NLS_CODEPAGE_949=m
++CONFIG_NLS_CODEPAGE_874=m
++CONFIG_NLS_ISO8859_8=m
++CONFIG_NLS_CODEPAGE_1250=m
++CONFIG_NLS_CODEPAGE_1251=m
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=m
++CONFIG_NLS_ISO8859_2=m
++CONFIG_NLS_ISO8859_3=m
++CONFIG_NLS_ISO8859_4=m
++CONFIG_NLS_ISO8859_5=m
++CONFIG_NLS_ISO8859_6=m
++CONFIG_NLS_ISO8859_7=m
++CONFIG_NLS_ISO8859_9=m
++CONFIG_NLS_ISO8859_13=m
++CONFIG_NLS_ISO8859_14=m
++CONFIG_NLS_ISO8859_15=m
++CONFIG_NLS_KOI8_R=m
++CONFIG_NLS_KOI8_U=m
++CONFIG_DLM=m
++CONFIG_CRYPTO_USER=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_CTS=m
++CONFIG_CRYPTO_XTS=m
++CONFIG_CRYPTO_XCBC=m
++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_CRC_ITU_T=y
++CONFIG_LIBCRC32C=y
++CONFIG_PRINTK_TIME=y
++CONFIG_BOOT_PRINTK_DELAY=y
++CONFIG_DEBUG_MEMORY_INIT=y
++CONFIG_DETECT_HUNG_TASK=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_UPROBE_EVENTS is not set
++CONFIG_FUNCTION_PROFILER=y
++CONFIG_KGDB=y
++CONFIG_KGDB_KDB=y
++CONFIG_KDB_KEYBOARD=y
+++ /dev/null
-From 3f7bbc703820266e75c079e5553289d969fe0ed7 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 30 May 2019 16:44:24 +0100
-Subject: [PATCH 640/703] overlays: Add i2c3-6 and uart2-5 overlays
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/Makefile | 8 +++
- arch/arm/boot/dts/overlays/README | 52 ++++++++++++++++++++
- arch/arm/boot/dts/overlays/i2c3-overlay.dts | 27 ++++++++++
- arch/arm/boot/dts/overlays/i2c4-overlay.dts | 27 ++++++++++
- arch/arm/boot/dts/overlays/i2c5-overlay.dts | 27 ++++++++++
- arch/arm/boot/dts/overlays/i2c6-overlay.dts | 27 ++++++++++
- arch/arm/boot/dts/overlays/uart2-overlay.dts | 27 ++++++++++
- arch/arm/boot/dts/overlays/uart3-overlay.dts | 27 ++++++++++
- arch/arm/boot/dts/overlays/uart4-overlay.dts | 27 ++++++++++
- arch/arm/boot/dts/overlays/uart5-overlay.dts | 27 ++++++++++
- 10 files changed, 276 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/i2c3-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/i2c4-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/i2c5-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/i2c6-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/uart2-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/uart3-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/uart4-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/uart5-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -65,6 +65,10 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- i2c-sensor.dtbo \
- i2c0-bcm2708.dtbo \
- i2c1-bcm2708.dtbo \
-+ i2c3.dtbo \
-+ i2c4.dtbo \
-+ i2c5.dtbo \
-+ i2c6.dtbo \
- i2s-gpio28-31.dtbo \
- ilitek251x.dtbo \
- iqaudio-codec.dtbo \
-@@ -149,6 +153,10 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- tpm-slb9670.dtbo \
- uart0.dtbo \
- uart1.dtbo \
-+ uart2.dtbo \
-+ uart3.dtbo \
-+ uart4.dtbo \
-+ uart5.dtbo \
- udrc.dtbo \
- upstream.dtbo \
- vc4-fkms-v3d.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1137,6 +1137,34 @@ Params: sda1_pin GPIO pin
- "yes")
-
-
-+Name: i2c3
-+Info: Enable the i2c3 bus
-+Load: dtoverlay=i2c3,<param>
-+Params: pins_2_3 Use GPIOs 2 and 3
-+ pins_4_5 Use GPIOs 4 and 5 (default)
-+
-+
-+Name: i2c4
-+Info: Enable the i2c4 bus
-+Load: dtoverlay=i2c4,<param>
-+Params: pins_6_7 Use GPIOs 6 and 7
-+ pins_8_9 Use GPIOs 8 and 9 (default)
-+
-+
-+Name: i2c5
-+Info: Enable the i2c5 bus
-+Load: dtoverlay=i2c5,<param>
-+Params: pins_10_11 Use GPIOs 10 and 11
-+ pins_12_13 Use GPIOs 12 and 13 (default)
-+
-+
-+Name: i2c6
-+Info: Enable the i2c6 bus
-+Load: dtoverlay=i2c6,<param>
-+Params: pins_0_1 Use GPIOs 0 and 1
-+ pins_22_23 Use GPIOs 22 and 23 (default)
-+
-+
- Name: i2s-gpio28-31
- Info: move I2S function block to GPIO 28 to 31
- Load: dtoverlay=i2s-gpio28-31
-@@ -2199,6 +2227,30 @@ Params: txd1_pin GPIO pin
- rxd1_pin GPIO pin for RXD1 (15, 33 or 41 - default 15)
-
-
-+Name: uart2
-+Info: Enable uart 2 on GPIOs 0-3
-+Load: dtoverlay=uart2,<param>
-+Params: ctsrts Enable CTS/RTS on GPIOs 2-3 (default off)
-+
-+
-+Name: uart3
-+Info: Enable uart 3 on GPIOs 4-7
-+Load: dtoverlay=uart3,<param>
-+Params: ctsrts Enable CTS/RTS on GPIOs 6-7 (default off)
-+
-+
-+Name: uart4
-+Info: Enable uart 4 on GPIOs 8-11
-+Load: dtoverlay=uart4,<param>
-+Params: ctsrts Enable CTS/RTS on GPIOs 10-11 (default off)
-+
-+
-+Name: uart5
-+Info: Enable uart 5 on GPIOs 12-15
-+Load: dtoverlay=uart5,<param>
-+Params: ctsrts Enable CTS/RTS on GPIOs 14-15 (default off)
-+
-+
- Name: udrc
- Info: Configures the NW Digital Radio UDRC Hat
- Load: dtoverlay=udrc,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/i2c3-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&i2c3>;
-+ __overlay__ {
-+ status = "okay";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2c3_pins>;
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&i2c3_pins>;
-+ __dormant__ {
-+ brcm,pins = <2 3>;
-+ };
-+ };
-+
-+ __overrides__ {
-+ pins_2_3 = <0>,"=1";
-+ pins_4_5 = <0>,"!1";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/i2c4-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&i2c4>;
-+ __overlay__ {
-+ status = "okay";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2c4_pins>;
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&i2c4_pins>;
-+ __dormant__ {
-+ brcm,pins = <6 7>;
-+ };
-+ };
-+
-+ __overrides__ {
-+ pins_6_7 = <0>,"=1";
-+ pins_8_9 = <0>,"!1";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/i2c5-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&i2c5>;
-+ __overlay__ {
-+ status = "okay";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2c5_pins>;
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&i2c5_pins>;
-+ __dormant__ {
-+ brcm,pins = <10 11>;
-+ };
-+ };
-+
-+ __overrides__ {
-+ pins_10_11 = <0>,"=1";
-+ pins_12_13 = <0>,"!1";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/i2c6-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&i2c6>;
-+ __overlay__ {
-+ status = "okay";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2c6_pins>;
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&i2c6_pins>;
-+ __dormant__ {
-+ brcm,pins = <0 1>;
-+ };
-+ };
-+
-+ __overrides__ {
-+ pins_0_1 = <0>,"=1";
-+ pins_22_23 = <0>,"!1";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/uart2-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&uart2>;
-+ __overlay__ {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart2_pins>;
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&uart2_pins>;
-+ __dormant__ {
-+ brcm,pins = <0 1 2 3>;
-+ brcm,pull = <0 2 2 0>;
-+ };
-+ };
-+
-+ __overrides__ {
-+ ctsrts = <0>,"=1";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/uart3-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&uart3>;
-+ __overlay__ {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart3_pins>;
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&uart3_pins>;
-+ __dormant__ {
-+ brcm,pins = <4 5 6 7>;
-+ brcm,pull = <0 2 2 0>;
-+ };
-+ };
-+
-+ __overrides__ {
-+ ctsrts = <0>,"=1";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/uart4-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&uart4>;
-+ __overlay__ {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart4_pins>;
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&uart4_pins>;
-+ __dormant__ {
-+ brcm,pins = <8 9 10 11>;
-+ brcm,pull = <0 2 2 0>;
-+ };
-+ };
-+
-+ __overrides__ {
-+ ctsrts = <0>,"=1";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/uart5-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&uart5>;
-+ __overlay__ {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart5_pins>;
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&uart5_pins>;
-+ __dormant__ {
-+ brcm,pins = <12 13 14 15>;
-+ brcm,pull = <0 2 2 0>;
-+ };
-+ };
-+
-+ __overrides__ {
-+ ctsrts = <0>,"=1";
-+ };
-+};
--- /dev/null
+From 3b0307fedd80a85daae89d0346c165d3b3ce6687 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 8 Mar 2019 21:12:39 +0000
+Subject: [PATCH 641/725] 2711: Add basic 64-bit support
+
+This commit adds initial support for 64-bit 2711 builds. However,
+it will only work as much as it does if the Pi4 RAM is limited to
+1GB - more than that and several things break (SD card, coherent
+allocations, etc.)
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm64/boot/dts/broadcom/Makefile | 1 +
+ .../boot/dts/broadcom/bcm2711-rpi-4-b.dts | 3 +
+ arch/arm64/configs/bcm2711_defconfig | 1291 +++++++++++++++++
+ 3 files changed, 1295 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts
+ create mode 100644 arch/arm64/configs/bcm2711_defconfig
+
+--- a/arch/arm64/boot/dts/broadcom/Makefile
++++ b/arch/arm64/boot/dts/broadcom/Makefile
+@@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rp
+ bcm2837-rpi-3-b-plus.dtb
+ dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b.dtb
++dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-4-b.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b-plus.dtb
+ dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-cm3.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-cm3.dtb
+--- /dev/null
++++ b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts
+@@ -0,0 +1,3 @@
++#define RPI364
++
++#include "../../../../arm/boot/dts/bcm2711-rpi-4-b.dts"
+--- /dev/null
++++ b/arch/arm64/configs/bcm2711_defconfig
+@@ -0,0 +1,1291 @@
++CONFIG_LOCALVERSION="-v8"
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SYSVIPC=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_GENERIC_IRQ_DEBUGFS=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_PREEMPT=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++CONFIG_TASKSTATS=y
++CONFIG_TASK_DELAY_ACCT=y
++CONFIG_TASK_XACCT=y
++CONFIG_TASK_IO_ACCOUNTING=y
++CONFIG_IKCONFIG=m
++CONFIG_IKCONFIG_PROC=y
++CONFIG_MEMCG=y
++CONFIG_BLK_CGROUP=y
++CONFIG_CGROUP_FREEZER=y
++CONFIG_CPUSETS=y
++CONFIG_CGROUP_DEVICE=y
++CONFIG_CGROUP_CPUACCT=y
++CONFIG_NAMESPACES=y
++CONFIG_USER_NS=y
++CONFIG_SCHED_AUTOGROUP=y
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_EMBEDDED=y
++# CONFIG_COMPAT_BRK is not set
++CONFIG_PROFILING=y
++CONFIG_ARCH_BCM2835=y
++CONFIG_PCI=y
++CONFIG_PCIE_BRCMSTB=y
++# CONFIG_CAVIUM_ERRATUM_22375 is not set
++# CONFIG_CAVIUM_ERRATUM_23154 is not set
++# CONFIG_CAVIUM_ERRATUM_27456 is not set
++CONFIG_SECCOMP=y
++CONFIG_ARMV8_DEPRECATED=y
++CONFIG_SWP_EMULATION=y
++CONFIG_CP15_BARRIER_EMULATION=y
++CONFIG_SETEND_EMULATION=y
++CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait"
++CONFIG_COMPAT=y
++# CONFIG_SUSPEND is not set
++CONFIG_PM=y
++CONFIG_CPU_IDLE=y
++CONFIG_ARM_CPUIDLE=y
++CONFIG_CPU_FREQ=y
++CONFIG_CPU_FREQ_STAT=y
++CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y
++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
++CONFIG_CPU_FREQ_GOV_USERSPACE=y
++CONFIG_CPU_FREQ_GOV_ONDEMAND=y
++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
++CONFIG_RASPBERRYPI_FIRMWARE=y
++CONFIG_ARM64_CRYPTO=y
++CONFIG_CRYPTO_AES_ARM64_BS=m
++CONFIG_KPROBES=y
++CONFIG_JUMP_LABEL=y
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODVERSIONS=y
++CONFIG_MODULE_SRCVERSION_ALL=y
++CONFIG_BLK_DEV_THROTTLING=y
++CONFIG_PARTITION_ADVANCED=y
++CONFIG_MAC_PARTITION=y
++CONFIG_CFQ_GROUP_IOSCHED=y
++CONFIG_BINFMT_MISC=m
++CONFIG_CLEANCACHE=y
++CONFIG_FRONTSWAP=y
++CONFIG_CMA=y
++CONFIG_ZSMALLOC=m
++CONFIG_PGTABLE_MAPPING=y
++CONFIG_NET=y
++CONFIG_PACKET=y
++CONFIG_UNIX=y
++CONFIG_XFRM_USER=y
++CONFIG_NET_KEY=m
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_IP_ROUTE_MULTIPATH=y
++CONFIG_IP_ROUTE_VERBOSE=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_RARP=y
++CONFIG_NET_IPIP=m
++CONFIG_NET_IPGRE_DEMUX=m
++CONFIG_NET_IPGRE=m
++CONFIG_IP_MROUTE=y
++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
++CONFIG_IP_PIMSM_V1=y
++CONFIG_IP_PIMSM_V2=y
++CONFIG_SYN_COOKIES=y
++CONFIG_INET_AH=m
++CONFIG_INET_ESP=m
++CONFIG_INET_IPCOMP=m
++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_IPV6_ROUTE_INFO=y
++CONFIG_INET6_AH=m
++CONFIG_INET6_ESP=m
++CONFIG_INET6_IPCOMP=m
++CONFIG_IPV6_SIT_6RD=y
++CONFIG_IPV6_TUNNEL=m
++CONFIG_IPV6_MULTIPLE_TABLES=y
++CONFIG_IPV6_SUBTREES=y
++CONFIG_IPV6_MROUTE=y
++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
++CONFIG_IPV6_PIMSM_V2=y
++CONFIG_NETFILTER=y
++CONFIG_NF_CONNTRACK=m
++CONFIG_NF_CONNTRACK_ZONES=y
++CONFIG_NF_CONNTRACK_EVENTS=y
++CONFIG_NF_CONNTRACK_TIMESTAMP=y
++CONFIG_NF_CONNTRACK_AMANDA=m
++CONFIG_NF_CONNTRACK_FTP=m
++CONFIG_NF_CONNTRACK_H323=m
++CONFIG_NF_CONNTRACK_IRC=m
++CONFIG_NF_CONNTRACK_NETBIOS_NS=m
++CONFIG_NF_CONNTRACK_SNMP=m
++CONFIG_NF_CONNTRACK_PPTP=m
++CONFIG_NF_CONNTRACK_SANE=m
++CONFIG_NF_CONNTRACK_SIP=m
++CONFIG_NF_CONNTRACK_TFTP=m
++CONFIG_NF_CT_NETLINK=m
++CONFIG_NETFILTER_XT_SET=m
++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
++CONFIG_NETFILTER_XT_TARGET_DSCP=m
++CONFIG_NETFILTER_XT_TARGET_HMARK=m
++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
++CONFIG_NETFILTER_XT_TARGET_LED=m
++CONFIG_NETFILTER_XT_TARGET_LOG=m
++CONFIG_NETFILTER_XT_TARGET_MARK=m
++CONFIG_NETFILTER_XT_TARGET_NFLOG=m
++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
++CONFIG_NETFILTER_XT_TARGET_TEE=m
++CONFIG_NETFILTER_XT_TARGET_TPROXY=m
++CONFIG_NETFILTER_XT_TARGET_TRACE=m
++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
++CONFIG_NETFILTER_XT_MATCH_BPF=m
++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
++CONFIG_NETFILTER_XT_MATCH_COMMENT=m
++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
++CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
++CONFIG_NETFILTER_XT_MATCH_CPU=m
++CONFIG_NETFILTER_XT_MATCH_DCCP=m
++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
++CONFIG_NETFILTER_XT_MATCH_DSCP=m
++CONFIG_NETFILTER_XT_MATCH_ESP=m
++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
++CONFIG_NETFILTER_XT_MATCH_HELPER=m
++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
++CONFIG_NETFILTER_XT_MATCH_IPVS=m
++CONFIG_NETFILTER_XT_MATCH_LENGTH=m
++CONFIG_NETFILTER_XT_MATCH_LIMIT=m
++CONFIG_NETFILTER_XT_MATCH_MAC=m
++CONFIG_NETFILTER_XT_MATCH_MARK=m
++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
++CONFIG_NETFILTER_XT_MATCH_NFACCT=m
++CONFIG_NETFILTER_XT_MATCH_OSF=m
++CONFIG_NETFILTER_XT_MATCH_OWNER=m
++CONFIG_NETFILTER_XT_MATCH_POLICY=m
++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
++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_STATE=m
++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
++CONFIG_NETFILTER_XT_MATCH_STRING=m
++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
++CONFIG_NETFILTER_XT_MATCH_TIME=m
++CONFIG_NETFILTER_XT_MATCH_U32=m
++CONFIG_IP_SET=m
++CONFIG_IP_SET_BITMAP_IP=m
++CONFIG_IP_SET_BITMAP_IPMAC=m
++CONFIG_IP_SET_BITMAP_PORT=m
++CONFIG_IP_SET_HASH_IP=m
++CONFIG_IP_SET_HASH_IPPORT=m
++CONFIG_IP_SET_HASH_IPPORTIP=m
++CONFIG_IP_SET_HASH_IPPORTNET=m
++CONFIG_IP_SET_HASH_NET=m
++CONFIG_IP_SET_HASH_NETPORT=m
++CONFIG_IP_SET_HASH_NETIFACE=m
++CONFIG_IP_SET_LIST_SET=m
++CONFIG_IP_VS=m
++CONFIG_IP_VS_PROTO_TCP=y
++CONFIG_IP_VS_PROTO_UDP=y
++CONFIG_IP_VS_PROTO_ESP=y
++CONFIG_IP_VS_PROTO_AH=y
++CONFIG_IP_VS_PROTO_SCTP=y
++CONFIG_IP_VS_RR=m
++CONFIG_IP_VS_WRR=m
++CONFIG_IP_VS_LC=m
++CONFIG_IP_VS_WLC=m
++CONFIG_IP_VS_LBLC=m
++CONFIG_IP_VS_LBLCR=m
++CONFIG_IP_VS_DH=m
++CONFIG_IP_VS_SH=m
++CONFIG_IP_VS_SED=m
++CONFIG_IP_VS_NQ=m
++CONFIG_IP_VS_FTP=m
++CONFIG_IP_VS_PE_SIP=m
++CONFIG_IP_NF_IPTABLES=m
++CONFIG_IP_NF_MATCH_AH=m
++CONFIG_IP_NF_MATCH_ECN=m
++CONFIG_IP_NF_MATCH_RPFILTER=m
++CONFIG_IP_NF_MATCH_TTL=m
++CONFIG_IP_NF_FILTER=m
++CONFIG_IP_NF_TARGET_REJECT=m
++CONFIG_IP_NF_NAT=m
++CONFIG_IP_NF_TARGET_MASQUERADE=m
++CONFIG_IP_NF_TARGET_NETMAP=m
++CONFIG_IP_NF_TARGET_REDIRECT=m
++CONFIG_IP_NF_MANGLE=m
++CONFIG_IP_NF_TARGET_CLUSTERIP=m
++CONFIG_IP_NF_TARGET_ECN=m
++CONFIG_IP_NF_TARGET_TTL=m
++CONFIG_IP_NF_RAW=m
++CONFIG_IP_NF_ARPTABLES=m
++CONFIG_IP_NF_ARPFILTER=m
++CONFIG_IP_NF_ARP_MANGLE=m
++CONFIG_IP6_NF_IPTABLES=m
++CONFIG_IP6_NF_MATCH_AH=m
++CONFIG_IP6_NF_MATCH_EUI64=m
++CONFIG_IP6_NF_MATCH_FRAG=m
++CONFIG_IP6_NF_MATCH_OPTS=m
++CONFIG_IP6_NF_MATCH_HL=m
++CONFIG_IP6_NF_MATCH_IPV6HEADER=m
++CONFIG_IP6_NF_MATCH_MH=m
++CONFIG_IP6_NF_MATCH_RPFILTER=m
++CONFIG_IP6_NF_MATCH_RT=m
++CONFIG_IP6_NF_TARGET_HL=m
++CONFIG_IP6_NF_FILTER=m
++CONFIG_IP6_NF_TARGET_REJECT=m
++CONFIG_IP6_NF_MANGLE=m
++CONFIG_IP6_NF_RAW=m
++CONFIG_IP6_NF_NAT=m
++CONFIG_IP6_NF_TARGET_MASQUERADE=m
++CONFIG_IP6_NF_TARGET_NPT=m
++CONFIG_BRIDGE_NF_EBTABLES=m
++CONFIG_BRIDGE_EBT_BROUTE=m
++CONFIG_BRIDGE_EBT_T_FILTER=m
++CONFIG_BRIDGE_EBT_T_NAT=m
++CONFIG_BRIDGE_EBT_802_3=m
++CONFIG_BRIDGE_EBT_AMONG=m
++CONFIG_BRIDGE_EBT_ARP=m
++CONFIG_BRIDGE_EBT_IP=m
++CONFIG_BRIDGE_EBT_IP6=m
++CONFIG_BRIDGE_EBT_LIMIT=m
++CONFIG_BRIDGE_EBT_MARK=m
++CONFIG_BRIDGE_EBT_PKTTYPE=m
++CONFIG_BRIDGE_EBT_STP=m
++CONFIG_BRIDGE_EBT_VLAN=m
++CONFIG_BRIDGE_EBT_ARPREPLY=m
++CONFIG_BRIDGE_EBT_DNAT=m
++CONFIG_BRIDGE_EBT_MARK_T=m
++CONFIG_BRIDGE_EBT_REDIRECT=m
++CONFIG_BRIDGE_EBT_SNAT=m
++CONFIG_BRIDGE_EBT_LOG=m
++CONFIG_BRIDGE_EBT_NFLOG=m
++CONFIG_SCTP_COOKIE_HMAC_SHA1=y
++CONFIG_ATM=m
++CONFIG_L2TP=m
++CONFIG_L2TP_V3=y
++CONFIG_L2TP_IP=m
++CONFIG_L2TP_ETH=m
++CONFIG_BRIDGE=m
++CONFIG_VLAN_8021Q=m
++CONFIG_VLAN_8021Q_GVRP=y
++CONFIG_ATALK=m
++CONFIG_6LOWPAN=m
++CONFIG_IEEE802154=m
++CONFIG_IEEE802154_6LOWPAN=m
++CONFIG_MAC802154=m
++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
++CONFIG_NET_SCH_SFB=m
++CONFIG_NET_SCH_SFQ=m
++CONFIG_NET_SCH_TEQL=m
++CONFIG_NET_SCH_TBF=m
++CONFIG_NET_SCH_GRED=m
++CONFIG_NET_SCH_DSMARK=m
++CONFIG_NET_SCH_NETEM=m
++CONFIG_NET_SCH_DRR=m
++CONFIG_NET_SCH_MQPRIO=m
++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
++CONFIG_NET_CLS_TCINDEX=m
++CONFIG_NET_CLS_ROUTE4=m
++CONFIG_NET_CLS_FW=m
++CONFIG_NET_CLS_U32=m
++CONFIG_CLS_U32_MARK=y
++CONFIG_NET_CLS_RSVP=m
++CONFIG_NET_CLS_RSVP6=m
++CONFIG_NET_CLS_FLOW=m
++CONFIG_NET_CLS_CGROUP=m
++CONFIG_NET_EMATCH=y
++CONFIG_NET_EMATCH_CMP=m
++CONFIG_NET_EMATCH_NBYTE=m
++CONFIG_NET_EMATCH_U32=m
++CONFIG_NET_EMATCH_META=m
++CONFIG_NET_EMATCH_TEXT=m
++CONFIG_NET_EMATCH_IPSET=m
++CONFIG_NET_CLS_ACT=y
++CONFIG_NET_ACT_POLICE=m
++CONFIG_NET_ACT_GACT=m
++CONFIG_GACT_PROB=y
++CONFIG_NET_ACT_MIRRED=m
++CONFIG_NET_ACT_IPT=m
++CONFIG_NET_ACT_NAT=m
++CONFIG_NET_ACT_PEDIT=m
++CONFIG_NET_ACT_SIMP=m
++CONFIG_NET_ACT_SKBEDIT=m
++CONFIG_NET_ACT_CSUM=m
++CONFIG_BATMAN_ADV=m
++CONFIG_OPENVSWITCH=m
++CONFIG_NET_PKTGEN=m
++CONFIG_HAMRADIO=y
++CONFIG_AX25=m
++CONFIG_NETROM=m
++CONFIG_ROSE=m
++CONFIG_MKISS=m
++CONFIG_6PACK=m
++CONFIG_BPQETHER=m
++CONFIG_BAYCOM_SER_FDX=m
++CONFIG_BAYCOM_SER_HDX=m
++CONFIG_YAM=m
++CONFIG_CAN=m
++CONFIG_CAN_VCAN=m
++CONFIG_CAN_SLCAN=m
++CONFIG_CAN_MCP251X=m
++CONFIG_CAN_GS_USB=m
++CONFIG_BT=m
++CONFIG_BT_RFCOMM=m
++CONFIG_BT_RFCOMM_TTY=y
++CONFIG_BT_BNEP=m
++CONFIG_BT_BNEP_MC_FILTER=y
++CONFIG_BT_BNEP_PROTO_FILTER=y
++CONFIG_BT_HIDP=m
++CONFIG_BT_6LOWPAN=m
++CONFIG_BT_HCIBTUSB=m
++CONFIG_BT_HCIUART=m
++CONFIG_BT_HCIUART_3WIRE=y
++CONFIG_BT_HCIUART_BCM=y
++CONFIG_BT_HCIBCM203X=m
++CONFIG_BT_HCIBPA10X=m
++CONFIG_BT_HCIBFUSB=m
++CONFIG_BT_HCIVHCI=m
++CONFIG_BT_MRVL=m
++CONFIG_BT_MRVL_SDIO=m
++CONFIG_BT_ATH3K=m
++CONFIG_BT_WILINK=m
++CONFIG_CFG80211=m
++CONFIG_MAC80211=m
++CONFIG_MAC80211_MESH=y
++CONFIG_WIMAX=m
++CONFIG_RFKILL=m
++CONFIG_RFKILL_INPUT=y
++CONFIG_NET_9P=m
++CONFIG_NFC=m
++CONFIG_DEVTMPFS=y
++CONFIG_DEVTMPFS_MOUNT=y
++CONFIG_DMA_CMA=y
++CONFIG_CMA_SIZE_MBYTES=5
++CONFIG_MTD=m
++CONFIG_MTD_BLOCK=m
++CONFIG_MTD_M25P80=m
++CONFIG_MTD_BLOCK2MTD=m
++CONFIG_MTD_NAND=m
++CONFIG_MTD_SPI_NOR=m
++CONFIG_MTD_UBI=m
++CONFIG_OF_CONFIGFS=y
++CONFIG_ZRAM=m
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_BLK_DEV_CRYPTOLOOP=m
++CONFIG_BLK_DEV_DRBD=m
++CONFIG_BLK_DEV_NBD=m
++CONFIG_BLK_DEV_RAM=y
++CONFIG_CDROM_PKTCDVD=m
++CONFIG_ATA_OVER_ETH=m
++CONFIG_EEPROM_AT24=m
++CONFIG_TI_ST=m
++CONFIG_SCSI=y
++# CONFIG_SCSI_PROC_FS is not set
++CONFIG_BLK_DEV_SD=y
++CONFIG_CHR_DEV_ST=m
++CONFIG_CHR_DEV_OSST=m
++CONFIG_BLK_DEV_SR=m
++CONFIG_CHR_DEV_SG=m
++CONFIG_SCSI_ISCSI_ATTRS=y
++CONFIG_ISCSI_TCP=m
++CONFIG_ISCSI_BOOT_SYSFS=m
++CONFIG_MD=y
++CONFIG_MD_LINEAR=m
++CONFIG_BLK_DEV_DM=m
++CONFIG_DM_CRYPT=m
++CONFIG_DM_SNAPSHOT=m
++CONFIG_DM_THIN_PROVISIONING=m
++CONFIG_DM_CACHE=m
++CONFIG_DM_MIRROR=m
++CONFIG_DM_LOG_USERSPACE=m
++CONFIG_DM_RAID=m
++CONFIG_DM_ZERO=m
++CONFIG_DM_DELAY=m
++CONFIG_NETDEVICES=y
++CONFIG_BONDING=m
++CONFIG_DUMMY=m
++CONFIG_IFB=m
++CONFIG_MACVLAN=m
++CONFIG_IPVLAN=m
++CONFIG_VXLAN=m
++CONFIG_NETCONSOLE=m
++CONFIG_TUN=m
++CONFIG_VETH=m
++CONFIG_BCMGENET=y
++CONFIG_ENC28J60=m
++CONFIG_QCA7000_SPI=m
++CONFIG_MDIO_BITBANG=m
++CONFIG_BROADCOM_PHY=y
++CONFIG_PPP=m
++CONFIG_PPP_BSDCOMP=m
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_FILTER=y
++CONFIG_PPP_MPPE=m
++CONFIG_PPP_MULTILINK=y
++CONFIG_PPPOATM=m
++CONFIG_PPPOE=m
++CONFIG_PPPOL2TP=m
++CONFIG_PPP_ASYNC=m
++CONFIG_PPP_SYNC_TTY=m
++CONFIG_SLIP=m
++CONFIG_SLIP_COMPRESSED=y
++CONFIG_SLIP_SMART=y
++CONFIG_USB_CATC=m
++CONFIG_USB_KAWETH=m
++CONFIG_USB_PEGASUS=m
++CONFIG_USB_RTL8150=m
++CONFIG_USB_RTL8152=y
++CONFIG_USB_LAN78XX=y
++CONFIG_USB_USBNET=y
++CONFIG_USB_NET_AX88179_178A=m
++CONFIG_USB_NET_CDCETHER=m
++CONFIG_USB_NET_CDC_EEM=m
++CONFIG_USB_NET_CDC_NCM=m
++CONFIG_USB_NET_HUAWEI_CDC_NCM=m
++CONFIG_USB_NET_CDC_MBIM=m
++CONFIG_USB_NET_DM9601=m
++CONFIG_USB_NET_SR9700=m
++CONFIG_USB_NET_SR9800=m
++CONFIG_USB_NET_SMSC75XX=m
++CONFIG_USB_NET_SMSC95XX=y
++CONFIG_USB_NET_GL620A=m
++CONFIG_USB_NET_NET1080=m
++CONFIG_USB_NET_PLUSB=m
++CONFIG_USB_NET_MCS7830=m
++CONFIG_USB_NET_CDC_SUBSET=m
++CONFIG_USB_ALI_M5632=y
++CONFIG_USB_AN2720=y
++CONFIG_USB_EPSON2888=y
++CONFIG_USB_KC2190=y
++CONFIG_USB_NET_ZAURUS=m
++CONFIG_USB_NET_CX82310_ETH=m
++CONFIG_USB_NET_KALMIA=m
++CONFIG_USB_NET_QMI_WWAN=m
++CONFIG_USB_HSO=m
++CONFIG_USB_NET_INT51X1=m
++CONFIG_USB_IPHETH=m
++CONFIG_USB_SIERRA_NET=m
++CONFIG_USB_VL600=m
++CONFIG_ATH9K=m
++CONFIG_ATH9K_HTC=m
++CONFIG_CARL9170=m
++CONFIG_ATH6KL=m
++CONFIG_ATH6KL_USB=m
++CONFIG_AR5523=m
++CONFIG_AT76C50X_USB=m
++CONFIG_B43=m
++# CONFIG_B43_PHY_N is not set
++CONFIG_B43LEGACY=m
++CONFIG_BRCMFMAC=m
++CONFIG_BRCMFMAC_USB=y
++CONFIG_BRCMDBG=y
++CONFIG_HOSTAP=m
++CONFIG_P54_COMMON=m
++CONFIG_P54_USB=m
++CONFIG_LIBERTAS=m
++CONFIG_LIBERTAS_USB=m
++CONFIG_LIBERTAS_SDIO=m
++CONFIG_LIBERTAS_THINFIRM=m
++CONFIG_LIBERTAS_THINFIRM_USB=m
++CONFIG_MWIFIEX=m
++CONFIG_MWIFIEX_SDIO=m
++CONFIG_MT7601U=m
++CONFIG_RT2X00=m
++CONFIG_RT2500USB=m
++CONFIG_RT73USB=m
++CONFIG_RT2800USB=m
++CONFIG_RT2800USB_RT3573=y
++CONFIG_RT2800USB_RT53XX=y
++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
++CONFIG_USB_NET_RNDIS_WLAN=m
++CONFIG_WIMAX_I2400M_USB=m
++CONFIG_IEEE802154_AT86RF230=m
++CONFIG_IEEE802154_MRF24J40=m
++CONFIG_IEEE802154_CC2520=m
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_JOYDEV=m
++CONFIG_INPUT_EVDEV=m
++# CONFIG_KEYBOARD_ATKBD is not set
++CONFIG_KEYBOARD_GPIO=m
++CONFIG_KEYBOARD_MATRIX=m
++# CONFIG_INPUT_MOUSE is not set
++CONFIG_INPUT_JOYSTICK=y
++CONFIG_JOYSTICK_IFORCE=m
++CONFIG_JOYSTICK_IFORCE_USB=y
++CONFIG_JOYSTICK_XPAD=m
++CONFIG_JOYSTICK_XPAD_FF=y
++CONFIG_JOYSTICK_XPAD_LEDS=y
++CONFIG_JOYSTICK_PSXPAD_SPI=m
++CONFIG_JOYSTICK_PSXPAD_SPI_FF=y
++CONFIG_JOYSTICK_RPISENSE=m
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_TOUCHSCREEN_ADS7846=m
++CONFIG_TOUCHSCREEN_EGALAX=m
++CONFIG_TOUCHSCREEN_EXC3000=m
++CONFIG_TOUCHSCREEN_GOODIX=m
++CONFIG_TOUCHSCREEN_EDT_FT5X06=m
++CONFIG_TOUCHSCREEN_RPI_FT5406=m
++CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
++CONFIG_TOUCHSCREEN_STMPE=m
++CONFIG_INPUT_MISC=y
++CONFIG_INPUT_AD714X=m
++CONFIG_INPUT_ATI_REMOTE2=m
++CONFIG_INPUT_KEYSPAN_REMOTE=m
++CONFIG_INPUT_POWERMATE=m
++CONFIG_INPUT_YEALINK=m
++CONFIG_INPUT_CM109=m
++CONFIG_INPUT_UINPUT=m
++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
++CONFIG_INPUT_ADXL34X=m
++CONFIG_INPUT_CMA3000=m
++CONFIG_SERIO=m
++CONFIG_SERIO_RAW=m
++CONFIG_GAMEPORT=m
++CONFIG_GAMEPORT_NS558=m
++CONFIG_GAMEPORT_L4=m
++CONFIG_BRCM_CHAR_DRIVERS=y
++CONFIG_BCM_VCIO=y
++CONFIG_BCM2835_DEVGPIOMEM=y
++# CONFIG_BCM2835_SMI_DEV is not set
++# CONFIG_LEGACY_PTYS is not set
++CONFIG_SERIAL_8250=y
++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_DMA is not set
++CONFIG_SERIAL_8250_NR_UARTS=1
++CONFIG_SERIAL_8250_RUNTIME_UARTS=0
++CONFIG_SERIAL_8250_EXTENDED=y
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++CONFIG_SERIAL_8250_BCM2835AUX=y
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_SERIAL_AMBA_PL011=y
++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
++CONFIG_SERIAL_SC16IS7XX=m
++CONFIG_SERIAL_SC16IS7XX_SPI=y
++CONFIG_SERIAL_DEV_BUS=m
++CONFIG_TTY_PRINTK=y
++CONFIG_HW_RANDOM=y
++# CONFIG_HW_RANDOM_BCM2835 is not set
++CONFIG_RAW_DRIVER=y
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=m
++CONFIG_I2C_BCM2708=m
++CONFIG_I2C_BCM2835=m
++CONFIG_I2C_GPIO=m
++CONFIG_I2C_ROBOTFUZZ_OSIF=m
++CONFIG_I2C_TINY_USB=m
++CONFIG_SPI=y
++CONFIG_SPI_BCM2835=m
++CONFIG_SPI_BCM2835AUX=m
++CONFIG_SPI_SPIDEV=m
++CONFIG_SPI_SLAVE=y
++CONFIG_PPS_CLIENT_LDISC=m
++CONFIG_PPS_CLIENT_GPIO=m
++CONFIG_PINCTRL_MCP23S08=m
++CONFIG_GPIO_BCM_VIRT=y
++CONFIG_GPIO_MOCKUP=m
++CONFIG_GPIO_PCF857X=m
++CONFIG_GPIO_ARIZONA=m
++CONFIG_GPIO_STMPE=y
++CONFIG_W1=m
++CONFIG_W1_MASTER_DS2490=m
++CONFIG_W1_MASTER_DS2482=m
++CONFIG_W1_MASTER_DS1WM=m
++CONFIG_W1_MASTER_GPIO=m
++CONFIG_W1_SLAVE_THERM=m
++CONFIG_W1_SLAVE_SMEM=m
++CONFIG_W1_SLAVE_DS2408=m
++CONFIG_W1_SLAVE_DS2413=m
++CONFIG_W1_SLAVE_DS2406=m
++CONFIG_W1_SLAVE_DS2423=m
++CONFIG_W1_SLAVE_DS2431=m
++CONFIG_W1_SLAVE_DS2433=m
++CONFIG_W1_SLAVE_DS2438=m
++CONFIG_W1_SLAVE_DS2780=m
++CONFIG_W1_SLAVE_DS2781=m
++CONFIG_W1_SLAVE_DS28E04=m
++CONFIG_POWER_RESET_GPIO=y
++CONFIG_BATTERY_DS2760=m
++CONFIG_BATTERY_GAUGE_LTC2941=m
++CONFIG_HWMON=m
++CONFIG_SENSORS_DS1621=m
++CONFIG_SENSORS_JC42=m
++CONFIG_SENSORS_LM75=m
++CONFIG_SENSORS_SHT21=m
++CONFIG_SENSORS_SHT3x=m
++CONFIG_SENSORS_SHTC1=m
++CONFIG_SENSORS_ADS1015=m
++CONFIG_SENSORS_INA2XX=m
++CONFIG_SENSORS_TMP102=m
++CONFIG_THERMAL=y
++CONFIG_BCM2835_THERMAL=y
++CONFIG_WATCHDOG=y
++CONFIG_GPIO_WATCHDOG=m
++CONFIG_BCM2835_WDT=y
++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_LDO1=m
++CONFIG_REGULATOR_ARIZONA_MICSUPP=m
++CONFIG_REGULATOR_GPIO=y
++CONFIG_MEDIA_SUPPORT=m
++CONFIG_MEDIA_CAMERA_SUPPORT=y
++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
++CONFIG_MEDIA_RADIO_SUPPORT=y
++CONFIG_MEDIA_CONTROLLER=y
++CONFIG_MEDIA_USB_SUPPORT=y
++CONFIG_USB_VIDEO_CLASS=m
++CONFIG_USB_M5602=m
++CONFIG_USB_STV06XX=m
++CONFIG_USB_GL860=m
++CONFIG_USB_GSPCA_BENQ=m
++CONFIG_USB_GSPCA_CONEX=m
++CONFIG_USB_GSPCA_CPIA1=m
++CONFIG_USB_GSPCA_DTCS033=m
++CONFIG_USB_GSPCA_ETOMS=m
++CONFIG_USB_GSPCA_FINEPIX=m
++CONFIG_USB_GSPCA_JEILINJ=m
++CONFIG_USB_GSPCA_JL2005BCD=m
++CONFIG_USB_GSPCA_KINECT=m
++CONFIG_USB_GSPCA_KONICA=m
++CONFIG_USB_GSPCA_MARS=m
++CONFIG_USB_GSPCA_MR97310A=m
++CONFIG_USB_GSPCA_NW80X=m
++CONFIG_USB_GSPCA_OV519=m
++CONFIG_USB_GSPCA_OV534=m
++CONFIG_USB_GSPCA_OV534_9=m
++CONFIG_USB_GSPCA_PAC207=m
++CONFIG_USB_GSPCA_PAC7302=m
++CONFIG_USB_GSPCA_PAC7311=m
++CONFIG_USB_GSPCA_SE401=m
++CONFIG_USB_GSPCA_SN9C2028=m
++CONFIG_USB_GSPCA_SN9C20X=m
++CONFIG_USB_GSPCA_SONIXB=m
++CONFIG_USB_GSPCA_SONIXJ=m
++CONFIG_USB_GSPCA_SPCA500=m
++CONFIG_USB_GSPCA_SPCA501=m
++CONFIG_USB_GSPCA_SPCA505=m
++CONFIG_USB_GSPCA_SPCA506=m
++CONFIG_USB_GSPCA_SPCA508=m
++CONFIG_USB_GSPCA_SPCA561=m
++CONFIG_USB_GSPCA_SPCA1528=m
++CONFIG_USB_GSPCA_SQ905=m
++CONFIG_USB_GSPCA_SQ905C=m
++CONFIG_USB_GSPCA_SQ930X=m
++CONFIG_USB_GSPCA_STK014=m
++CONFIG_USB_GSPCA_STK1135=m
++CONFIG_USB_GSPCA_STV0680=m
++CONFIG_USB_GSPCA_SUNPLUS=m
++CONFIG_USB_GSPCA_T613=m
++CONFIG_USB_GSPCA_TOPRO=m
++CONFIG_USB_GSPCA_TV8532=m
++CONFIG_USB_GSPCA_VC032X=m
++CONFIG_USB_GSPCA_VICAM=m
++CONFIG_USB_GSPCA_XIRLINK_CIT=m
++CONFIG_USB_GSPCA_ZC3XX=m
++CONFIG_USB_PWC=m
++CONFIG_VIDEO_CPIA2=m
++CONFIG_USB_ZR364XX=m
++CONFIG_USB_STKWEBCAM=m
++CONFIG_USB_S2255=m
++CONFIG_VIDEO_USBTV=m
++CONFIG_VIDEO_PVRUSB2=m
++CONFIG_VIDEO_HDPVR=m
++CONFIG_VIDEO_USBVISION=m
++CONFIG_VIDEO_STK1160_COMMON=m
++CONFIG_VIDEO_GO7007=m
++CONFIG_VIDEO_GO7007_USB=m
++CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m
++CONFIG_VIDEO_AU0828=m
++CONFIG_DVB_USB_V2=m
++CONFIG_DVB_USB_AF9035=m
++CONFIG_DVB_USB_ANYSEE=m
++CONFIG_DVB_USB_AU6610=m
++CONFIG_DVB_USB_AZ6007=m
++CONFIG_DVB_USB_CE6230=m
++CONFIG_DVB_USB_EC168=m
++CONFIG_DVB_USB_GL861=m
++CONFIG_DVB_USB_MXL111SF=m
++CONFIG_DVB_USB_DVBSKY=m
++CONFIG_SMS_USB_DRV=m
++CONFIG_DVB_B2C2_FLEXCOP_USB=m
++CONFIG_DVB_AS102=m
++CONFIG_VIDEO_EM28XX=m
++CONFIG_VIDEO_EM28XX_V4L2=m
++CONFIG_VIDEO_EM28XX_ALSA=m
++CONFIG_VIDEO_EM28XX_DVB=m
++CONFIG_V4L_PLATFORM_DRIVERS=y
++CONFIG_RADIO_SI470X=m
++CONFIG_USB_SI470X=m
++CONFIG_I2C_SI470X=m
++CONFIG_RADIO_SI4713=m
++CONFIG_I2C_SI4713=m
++CONFIG_USB_MR800=m
++CONFIG_USB_DSBR=m
++CONFIG_RADIO_SHARK=m
++CONFIG_RADIO_SHARK2=m
++CONFIG_USB_KEENE=m
++CONFIG_USB_MA901=m
++CONFIG_RADIO_TEA5764=m
++CONFIG_RADIO_SAA7706H=m
++CONFIG_RADIO_TEF6862=m
++CONFIG_RADIO_WL1273=m
++CONFIG_RADIO_WL128X=m
++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
++CONFIG_VIDEO_UDA1342=m
++CONFIG_VIDEO_SONY_BTF_MPX=m
++CONFIG_VIDEO_TVP5150=m
++CONFIG_VIDEO_TW2804=m
++CONFIG_VIDEO_TW9903=m
++CONFIG_VIDEO_TW9906=m
++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_VC4=m
++CONFIG_DRM_TINYDRM=m
++CONFIG_TINYDRM_MI0283QT=m
++CONFIG_TINYDRM_REPAPER=m
++CONFIG_FB=y
++CONFIG_FB_BCM2708=y
++CONFIG_FB_UDL=m
++CONFIG_FB_SSD1307=m
++CONFIG_FB_RPISENSE=m
++# CONFIG_BACKLIGHT_GENERIC is not set
++CONFIG_BACKLIGHT_RPI=m
++CONFIG_BACKLIGHT_GPIO=m
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_LOGO=y
++# CONFIG_LOGO_LINUX_MONO is not set
++# CONFIG_LOGO_LINUX_VGA16 is not set
++CONFIG_SOUND=y
++CONFIG_SND=m
++CONFIG_SND_HRTIMER=m
++CONFIG_SND_SEQUENCER=m
++CONFIG_SND_SEQ_DUMMY=m
++CONFIG_SND_DUMMY=m
++CONFIG_SND_ALOOP=m
++CONFIG_SND_VIRMIDI=m
++CONFIG_SND_MTPAV=m
++CONFIG_SND_SERIAL_U16550=m
++CONFIG_SND_MPU401=m
++CONFIG_SND_USB_AUDIO=m
++CONFIG_SND_USB_UA101=m
++CONFIG_SND_USB_CAIAQ=m
++CONFIG_SND_USB_CAIAQ_INPUT=y
++CONFIG_SND_USB_6FIRE=m
++CONFIG_SND_USB_HIFACE=m
++CONFIG_SND_SOC=m
++CONFIG_SND_BCM2835_SOC_I2S=m
++CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=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
++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
++CONFIG_SND_BCM2708_SOC_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_ALLO_PIANO_DAC_PLUS=m
++CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC=m
++CONFIG_SND_BCM2708_SOC_ALLO_DIGIONE=m
++CONFIG_SND_BCM2708_SOC_ALLO_KATANA_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_CS4271_I2C=m
++CONFIG_SND_SOC_SPDIF=m
++CONFIG_SND_SOC_WM8804_I2C=m
++CONFIG_SND_SIMPLE_CARD=m
++CONFIG_HID_BATTERY_STRENGTH=y
++CONFIG_HIDRAW=y
++CONFIG_UHID=m
++CONFIG_HID_A4TECH=m
++CONFIG_HID_ACRUX=m
++CONFIG_HID_APPLE=m
++CONFIG_HID_ASUS=m
++CONFIG_HID_BELKIN=m
++CONFIG_HID_BETOP_FF=m
++CONFIG_HID_CHERRY=m
++CONFIG_HID_CHICONY=m
++CONFIG_HID_CYPRESS=m
++CONFIG_HID_DRAGONRISE=m
++CONFIG_HID_EMS_FF=m
++CONFIG_HID_ELECOM=m
++CONFIG_HID_ELO=m
++CONFIG_HID_EZKEY=m
++CONFIG_HID_GEMBIRD=m
++CONFIG_HID_HOLTEK=m
++CONFIG_HID_KEYTOUCH=m
++CONFIG_HID_KYE=m
++CONFIG_HID_UCLOGIC=m
++CONFIG_HID_WALTOP=m
++CONFIG_HID_GYRATION=m
++CONFIG_HID_TWINHAN=m
++CONFIG_HID_KENSINGTON=m
++CONFIG_HID_LCPOWER=m
++CONFIG_HID_LOGITECH=m
++CONFIG_HID_LOGITECH_DJ=m
++CONFIG_LOGITECH_FF=y
++CONFIG_LOGIRUMBLEPAD2_FF=y
++CONFIG_LOGIG940_FF=y
++CONFIG_HID_MAGICMOUSE=m
++CONFIG_HID_MICROSOFT=m
++CONFIG_HID_MONTEREY=m
++CONFIG_HID_MULTITOUCH=m
++CONFIG_HID_NTRIG=m
++CONFIG_HID_ORTEK=m
++CONFIG_HID_PANTHERLORD=m
++CONFIG_HID_PETALYNX=m
++CONFIG_HID_PICOLCD=m
++CONFIG_HID_ROCCAT=m
++CONFIG_HID_SAMSUNG=m
++CONFIG_HID_SONY=m
++CONFIG_SONY_FF=y
++CONFIG_HID_SPEEDLINK=m
++CONFIG_HID_SUNPLUS=m
++CONFIG_HID_GREENASIA=m
++CONFIG_HID_SMARTJOYPLUS=m
++CONFIG_HID_TOPSEED=m
++CONFIG_HID_THINGM=m
++CONFIG_HID_THRUSTMASTER=m
++CONFIG_HID_WACOM=m
++CONFIG_HID_WIIMOTE=m
++CONFIG_HID_XINMO=m
++CONFIG_HID_ZEROPLUS=m
++CONFIG_HID_ZYDACRON=m
++CONFIG_HID_PID=y
++CONFIG_USB_HIDDEV=y
++CONFIG_USB=y
++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
++CONFIG_USB_MON=m
++CONFIG_USB_XHCI_HCD=y
++CONFIG_USB_DWCOTG=y
++CONFIG_USB_PRINTER=m
++CONFIG_USB_STORAGE=y
++CONFIG_USB_STORAGE_REALTEK=m
++CONFIG_USB_STORAGE_DATAFAB=m
++CONFIG_USB_STORAGE_FREECOM=m
++CONFIG_USB_STORAGE_ISD200=m
++CONFIG_USB_STORAGE_USBAT=m
++CONFIG_USB_STORAGE_SDDR09=m
++CONFIG_USB_STORAGE_SDDR55=m
++CONFIG_USB_STORAGE_JUMPSHOT=m
++CONFIG_USB_STORAGE_ALAUDA=m
++CONFIG_USB_STORAGE_ONETOUCH=m
++CONFIG_USB_STORAGE_KARMA=m
++CONFIG_USB_STORAGE_CYPRESS_ATACB=m
++CONFIG_USB_STORAGE_ENE_UB6250=m
++CONFIG_USB_MDC800=m
++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
++CONFIG_USB_SERIAL_ARK3116=m
++CONFIG_USB_SERIAL_BELKIN=m
++CONFIG_USB_SERIAL_CH341=m
++CONFIG_USB_SERIAL_WHITEHEAT=m
++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
++CONFIG_USB_SERIAL_CP210X=m
++CONFIG_USB_SERIAL_CYPRESS_M8=m
++CONFIG_USB_SERIAL_EMPEG=m
++CONFIG_USB_SERIAL_FTDI_SIO=m
++CONFIG_USB_SERIAL_VISOR=m
++CONFIG_USB_SERIAL_IPAQ=m
++CONFIG_USB_SERIAL_IR=m
++CONFIG_USB_SERIAL_EDGEPORT=m
++CONFIG_USB_SERIAL_EDGEPORT_TI=m
++CONFIG_USB_SERIAL_F81232=m
++CONFIG_USB_SERIAL_GARMIN=m
++CONFIG_USB_SERIAL_IPW=m
++CONFIG_USB_SERIAL_IUU=m
++CONFIG_USB_SERIAL_KEYSPAN_PDA=m
++CONFIG_USB_SERIAL_KEYSPAN=m
++CONFIG_USB_SERIAL_KLSI=m
++CONFIG_USB_SERIAL_KOBIL_SCT=m
++CONFIG_USB_SERIAL_MCT_U232=m
++CONFIG_USB_SERIAL_METRO=m
++CONFIG_USB_SERIAL_MOS7720=m
++CONFIG_USB_SERIAL_MOS7840=m
++CONFIG_USB_SERIAL_NAVMAN=m
++CONFIG_USB_SERIAL_PL2303=m
++CONFIG_USB_SERIAL_OTI6858=m
++CONFIG_USB_SERIAL_QCAUX=m
++CONFIG_USB_SERIAL_QUALCOMM=m
++CONFIG_USB_SERIAL_SPCP8X5=m
++CONFIG_USB_SERIAL_SAFE=m
++CONFIG_USB_SERIAL_SIERRAWIRELESS=m
++CONFIG_USB_SERIAL_SYMBOL=m
++CONFIG_USB_SERIAL_TI=m
++CONFIG_USB_SERIAL_CYBERJACK=m
++CONFIG_USB_SERIAL_XIRCOM=m
++CONFIG_USB_SERIAL_OPTION=m
++CONFIG_USB_SERIAL_OMNINET=m
++CONFIG_USB_SERIAL_OPTICON=m
++CONFIG_USB_SERIAL_XSENS_MT=m
++CONFIG_USB_SERIAL_WISHBONE=m
++CONFIG_USB_SERIAL_SSU100=m
++CONFIG_USB_SERIAL_QT2=m
++CONFIG_USB_SERIAL_DEBUG=m
++CONFIG_USB_EMI62=m
++CONFIG_USB_EMI26=m
++CONFIG_USB_ADUTUX=m
++CONFIG_USB_SEVSEG=m
++CONFIG_USB_RIO500=m
++CONFIG_USB_LEGOTOWER=m
++CONFIG_USB_LCD=m
++CONFIG_USB_CYPRESS_CY7C63=m
++CONFIG_USB_CYTHERM=m
++CONFIG_USB_IDMOUSE=m
++CONFIG_USB_FTDI_ELAN=m
++CONFIG_USB_APPLEDISPLAY=m
++CONFIG_USB_LD=m
++CONFIG_USB_TRANCEVIBRATOR=m
++CONFIG_USB_IOWARRIOR=m
++CONFIG_USB_TEST=m
++CONFIG_USB_ISIGHTFW=m
++CONFIG_USB_YUREX=m
++CONFIG_USB_ATM=m
++CONFIG_USB_SPEEDTOUCH=m
++CONFIG_USB_CXACRU=m
++CONFIG_USB_UEAGLEATM=m
++CONFIG_USB_XUSBATM=m
++CONFIG_USB_GADGET=m
++CONFIG_USB_ZERO=m
++CONFIG_USB_AUDIO=m
++CONFIG_USB_ETH=m
++CONFIG_USB_GADGETFS=m
++CONFIG_USB_MASS_STORAGE=m
++CONFIG_USB_G_SERIAL=m
++CONFIG_USB_MIDI_GADGET=m
++CONFIG_USB_G_PRINTER=m
++CONFIG_USB_CDC_COMPOSITE=m
++CONFIG_USB_G_ACM_MS=m
++CONFIG_USB_G_MULTI=m
++CONFIG_USB_G_HID=m
++CONFIG_USB_G_WEBCAM=m
++CONFIG_MMC=y
++CONFIG_MMC_BLOCK_MINORS=32
++CONFIG_MMC_SDHCI_BCM2711=y
++CONFIG_MMC_BCM2835_MMC=y
++CONFIG_MMC_BCM2835_DMA=y
++CONFIG_MMC_BCM2835_SDHOST=y
++CONFIG_MMC_SDHCI=y
++CONFIG_MMC_SDHCI_PLTFM=y
++CONFIG_MMC_SPI=m
++CONFIG_LEDS_CLASS=y
++CONFIG_LEDS_GPIO=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_ONESHOT=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++CONFIG_LEDS_TRIGGER_BACKLIGHT=y
++CONFIG_LEDS_TRIGGER_CPU=y
++CONFIG_LEDS_TRIGGER_GPIO=y
++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
++CONFIG_LEDS_TRIGGER_TRANSIENT=m
++CONFIG_LEDS_TRIGGER_CAMERA=m
++CONFIG_LEDS_TRIGGER_INPUT=y
++CONFIG_LEDS_TRIGGER_PANIC=y
++CONFIG_RTC_CLASS=y
++# CONFIG_RTC_HCTOSYS is not set
++CONFIG_RTC_DRV_ABX80X=m
++CONFIG_RTC_DRV_DS1307=m
++CONFIG_RTC_DRV_DS1374=m
++CONFIG_RTC_DRV_DS1672=m
++CONFIG_RTC_DRV_MAX6900=m
++CONFIG_RTC_DRV_RS5C372=m
++CONFIG_RTC_DRV_ISL1208=m
++CONFIG_RTC_DRV_ISL12022=m
++CONFIG_RTC_DRV_X1205=m
++CONFIG_RTC_DRV_PCF8523=m
++CONFIG_RTC_DRV_PCF8563=m
++CONFIG_RTC_DRV_PCF8583=m
++CONFIG_RTC_DRV_M41T80=m
++CONFIG_RTC_DRV_BQ32K=m
++CONFIG_RTC_DRV_S35390A=m
++CONFIG_RTC_DRV_FM3130=m
++CONFIG_RTC_DRV_RX8581=m
++CONFIG_RTC_DRV_RX8025=m
++CONFIG_RTC_DRV_EM3027=m
++CONFIG_RTC_DRV_M41T93=m
++CONFIG_RTC_DRV_M41T94=m
++CONFIG_RTC_DRV_DS1302=m
++CONFIG_RTC_DRV_DS1305=m
++CONFIG_RTC_DRV_DS1390=m
++CONFIG_RTC_DRV_R9701=m
++CONFIG_RTC_DRV_RX4581=m
++CONFIG_RTC_DRV_RS5C348=m
++CONFIG_RTC_DRV_MAX6902=m
++CONFIG_RTC_DRV_PCF2123=m
++CONFIG_RTC_DRV_DS3232=m
++CONFIG_RTC_DRV_PCF2127=m
++CONFIG_RTC_DRV_RV3029C2=m
++CONFIG_DMADEVICES=y
++CONFIG_DMA_BCM2835=y
++CONFIG_DMA_BCM2708=y
++CONFIG_UIO=m
++CONFIG_UIO_PDRV_GENIRQ=m
++CONFIG_STAGING=y
++CONFIG_PRISM2_USB=m
++CONFIG_R8712U=m
++CONFIG_R8188EU=m
++CONFIG_VT6656=m
++CONFIG_SPEAKUP=m
++CONFIG_SPEAKUP_SYNTH_SOFT=m
++CONFIG_STAGING_MEDIA=y
++CONFIG_FB_TFT=m
++CONFIG_FB_TFT_AGM1264K_FL=m
++CONFIG_FB_TFT_BD663474=m
++CONFIG_FB_TFT_HX8340BN=m
++CONFIG_FB_TFT_HX8347D=m
++CONFIG_FB_TFT_HX8353D=m
++CONFIG_FB_TFT_HX8357D=m
++CONFIG_FB_TFT_ILI9163=m
++CONFIG_FB_TFT_ILI9320=m
++CONFIG_FB_TFT_ILI9325=m
++CONFIG_FB_TFT_ILI9340=m
++CONFIG_FB_TFT_ILI9341=m
++CONFIG_FB_TFT_ILI9481=m
++CONFIG_FB_TFT_ILI9486=m
++CONFIG_FB_TFT_PCD8544=m
++CONFIG_FB_TFT_RA8875=m
++CONFIG_FB_TFT_S6D02A1=m
++CONFIG_FB_TFT_S6D1121=m
++CONFIG_FB_TFT_SSD1289=m
++CONFIG_FB_TFT_SSD1306=m
++CONFIG_FB_TFT_SSD1331=m
++CONFIG_FB_TFT_SSD1351=m
++CONFIG_FB_TFT_ST7735R=m
++CONFIG_FB_TFT_ST7789V=m
++CONFIG_FB_TFT_TINYLCD=m
++CONFIG_FB_TFT_TLS8204=m
++CONFIG_FB_TFT_UC1701=m
++CONFIG_FB_TFT_UPD161704=m
++CONFIG_FB_TFT_WATTEROTT=m
++CONFIG_FB_FLEX=m
++CONFIG_FB_TFT_FBTFT_DEVICE=m
++CONFIG_SND_BCM2835=m
++CONFIG_VIDEO_BCM2835=m
++CONFIG_MAILBOX=y
++CONFIG_BCM2835_MBOX=y
++# CONFIG_IOMMU_SUPPORT is not set
++CONFIG_RASPBERRYPI_POWER=y
++CONFIG_EXTCON=m
++CONFIG_EXTCON_ARIZONA=m
++CONFIG_IIO=m
++CONFIG_IIO_BUFFER_CB=m
++CONFIG_MCP320X=m
++CONFIG_MCP3422=m
++CONFIG_DHT11=m
++CONFIG_HDC100X=m
++CONFIG_HTU21=m
++CONFIG_TSL4531=m
++CONFIG_VEML6070=m
++CONFIG_BMP280=m
++CONFIG_PWM_BCM2835=m
++CONFIG_PWM_PCA9685=m
++CONFIG_GENERIC_PHY=y
++CONFIG_RPI_AXIPERF=m
++CONFIG_EXT4_FS=y
++CONFIG_EXT4_FS_POSIX_ACL=y
++CONFIG_EXT4_FS_SECURITY=y
++CONFIG_REISERFS_FS=m
++CONFIG_REISERFS_FS_XATTR=y
++CONFIG_REISERFS_FS_POSIX_ACL=y
++CONFIG_REISERFS_FS_SECURITY=y
++CONFIG_JFS_FS=m
++CONFIG_JFS_POSIX_ACL=y
++CONFIG_JFS_SECURITY=y
++CONFIG_JFS_STATISTICS=y
++CONFIG_XFS_FS=m
++CONFIG_XFS_QUOTA=y
++CONFIG_XFS_POSIX_ACL=y
++CONFIG_XFS_RT=y
++CONFIG_GFS2_FS=m
++CONFIG_OCFS2_FS=m
++CONFIG_BTRFS_FS=m
++CONFIG_BTRFS_FS_POSIX_ACL=y
++CONFIG_NILFS2_FS=m
++CONFIG_F2FS_FS=y
++CONFIG_FANOTIFY=y
++CONFIG_QFMT_V1=m
++CONFIG_QFMT_V2=m
++CONFIG_AUTOFS4_FS=y
++CONFIG_FUSE_FS=m
++CONFIG_CUSE=m
++CONFIG_OVERLAY_FS=m
++CONFIG_FSCACHE=y
++CONFIG_FSCACHE_STATS=y
++CONFIG_FSCACHE_HISTOGRAM=y
++CONFIG_CACHEFILES=y
++CONFIG_ISO9660_FS=m
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_UDF_FS=m
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
++CONFIG_NTFS_FS=m
++CONFIG_NTFS_RW=y
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++CONFIG_ECRYPT_FS=m
++CONFIG_HFS_FS=m
++CONFIG_HFSPLUS_FS=m
++CONFIG_JFFS2_FS=m
++CONFIG_JFFS2_SUMMARY=y
++CONFIG_UBIFS_FS=m
++CONFIG_SQUASHFS=m
++CONFIG_SQUASHFS_XATTR=y
++CONFIG_SQUASHFS_LZO=y
++CONFIG_SQUASHFS_XZ=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3_ACL=y
++CONFIG_NFS_V4=y
++CONFIG_NFS_SWAP=y
++CONFIG_NFS_V4_1=y
++CONFIG_ROOT_NFS=y
++CONFIG_NFS_FSCACHE=y
++CONFIG_NFSD=m
++CONFIG_NFSD_V3_ACL=y
++CONFIG_NFSD_V4=y
++CONFIG_CIFS=m
++CONFIG_CIFS_WEAK_PW_HASH=y
++CONFIG_CIFS_UPCALL=y
++CONFIG_CIFS_XATTR=y
++CONFIG_CIFS_POSIX=y
++CONFIG_CIFS_ACL=y
++CONFIG_CIFS_DFS_UPCALL=y
++CONFIG_CIFS_FSCACHE=y
++CONFIG_9P_FS=m
++CONFIG_9P_FS_POSIX_ACL=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++CONFIG_NLS_CODEPAGE_737=m
++CONFIG_NLS_CODEPAGE_775=m
++CONFIG_NLS_CODEPAGE_850=m
++CONFIG_NLS_CODEPAGE_852=m
++CONFIG_NLS_CODEPAGE_855=m
++CONFIG_NLS_CODEPAGE_857=m
++CONFIG_NLS_CODEPAGE_860=m
++CONFIG_NLS_CODEPAGE_861=m
++CONFIG_NLS_CODEPAGE_862=m
++CONFIG_NLS_CODEPAGE_863=m
++CONFIG_NLS_CODEPAGE_864=m
++CONFIG_NLS_CODEPAGE_865=m
++CONFIG_NLS_CODEPAGE_866=m
++CONFIG_NLS_CODEPAGE_869=m
++CONFIG_NLS_CODEPAGE_936=m
++CONFIG_NLS_CODEPAGE_950=m
++CONFIG_NLS_CODEPAGE_932=m
++CONFIG_NLS_CODEPAGE_949=m
++CONFIG_NLS_CODEPAGE_874=m
++CONFIG_NLS_ISO8859_8=m
++CONFIG_NLS_CODEPAGE_1250=m
++CONFIG_NLS_CODEPAGE_1251=m
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=m
++CONFIG_NLS_ISO8859_2=m
++CONFIG_NLS_ISO8859_3=m
++CONFIG_NLS_ISO8859_4=m
++CONFIG_NLS_ISO8859_5=m
++CONFIG_NLS_ISO8859_6=m
++CONFIG_NLS_ISO8859_7=m
++CONFIG_NLS_ISO8859_9=m
++CONFIG_NLS_ISO8859_13=m
++CONFIG_NLS_ISO8859_14=m
++CONFIG_NLS_ISO8859_15=m
++CONFIG_NLS_KOI8_R=m
++CONFIG_NLS_KOI8_U=m
++CONFIG_DLM=m
++CONFIG_CRYPTO_USER=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_CTS=m
++CONFIG_CRYPTO_XTS=m
++CONFIG_CRYPTO_XCBC=m
++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_CRC_ITU_T=y
++CONFIG_LIBCRC32C=y
++CONFIG_PRINTK_TIME=y
++CONFIG_BOOT_PRINTK_DELAY=y
++CONFIG_DEBUG_MEMORY_INIT=y
++CONFIG_DETECT_HUNG_TASK=y
++CONFIG_LATENCYTOP=y
++CONFIG_IRQSOFF_TRACER=y
++CONFIG_SCHED_TRACER=y
++CONFIG_STACK_TRACER=y
++CONFIG_BLK_DEV_IO_TRACE=y
++CONFIG_FUNCTION_PROFILER=y
++CONFIG_KGDB=y
++CONFIG_KGDB_KDB=y
++CONFIG_KDB_KEYBOARD=y
+++ /dev/null
-From 075cb9a202526c4d4e712fda5db598c28ae74e4a Mon Sep 17 00:00:00 2001
-From: Martin Sperl <kernel@martin.sperl.org>
-Date: Sun, 12 May 2019 16:17:08 +0000
-Subject: [PATCH 641/703] spi: devicetree: add overlays for spi 3 to 6
-
-Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
----
- arch/arm/boot/dts/overlays/Makefile | 8 ++
- arch/arm/boot/dts/overlays/README | 104 ++++++++++++++++++
- .../boot/dts/overlays/spi3-1cs-overlay.dts | 44 ++++++++
- .../boot/dts/overlays/spi3-2cs-overlay.dts | 56 ++++++++++
- .../boot/dts/overlays/spi4-1cs-overlay.dts | 44 ++++++++
- .../boot/dts/overlays/spi4-2cs-overlay.dts | 56 ++++++++++
- .../boot/dts/overlays/spi5-1cs-overlay.dts | 44 ++++++++
- .../boot/dts/overlays/spi5-2cs-overlay.dts | 56 ++++++++++
- .../boot/dts/overlays/spi6-1cs-overlay.dts | 44 ++++++++
- .../boot/dts/overlays/spi6-2cs-overlay.dts | 56 ++++++++++
- 10 files changed, 512 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/spi3-1cs-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/spi3-2cs-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/spi4-1cs-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/spi4-2cs-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/spi5-1cs-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/spi5-2cs-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/spi6-1cs-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/spi6-2cs-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -144,6 +144,14 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- spi2-1cs.dtbo \
- spi2-2cs.dtbo \
- spi2-3cs.dtbo \
-+ spi3-1cs.dtbo \
-+ spi3-2cs.dtbo \
-+ spi4-1cs.dtbo \
-+ spi4-2cs.dtbo \
-+ spi5-1cs.dtbo \
-+ spi5-2cs.dtbo \
-+ spi6-1cs.dtbo \
-+ spi6-2cs.dtbo \
- ssd1306.dtbo \
- superaudioboard.dtbo \
- sx150x.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -2085,6 +2085,110 @@ Params: cs0_pin GPIO pin
- is 'okay' or enabled).
-
-
-+Name: spi3-1cs
-+Info: Enables spi3 with a single chip select (CS) line and associated spidev
-+ dev node. The gpio pin number for the CS line and spidev device node
-+ creation are configurable.
-+Load: dtoverlay=spi3-1cs,<param>=<val>
-+Params: cs0_pin GPIO pin for CS0 (default 0 - BCM SPI3_CE0).
-+ cs0_spidev Set to 'off' to prevent the creation of a
-+ userspace device node /dev/spidev3.0 (default
-+ is 'on' or enabled).
-+
-+
-+Name: spi3-2cs
-+Info: Enables spi3 with two chip select (CS) lines and associated spidev
-+ dev nodes. The gpio pin numbers for the CS lines and spidev device node
-+ creation are configurable.
-+Load: dtoverlay=spi3-2cs,<param>=<val>
-+Params: cs0_pin GPIO pin for CS0 (default 0 - BCM SPI3_CE0).
-+ cs1_pin GPIO pin for CS1 (default 24 - BCM SPI3_CE1).
-+ cs0_spidev Set to 'off' to prevent the creation of a
-+ userspace device node /dev/spidev3.0 (default
-+ is 'on' or enabled).
-+ cs1_spidev Set to 'off' to prevent the creation of a
-+ userspace device node /dev/spidev3.1 (default
-+ is 'on' or enabled).
-+
-+
-+Name: spi4-1cs
-+Info: Enables spi4 with a single chip select (CS) line and associated spidev
-+ dev node. The gpio pin number for the CS line and spidev device node
-+ creation are configurable.
-+Load: dtoverlay=spi4-1cs,<param>=<val>
-+Params: cs0_pin GPIO pin for CS0 (default 4 - BCM SPI4_CE0).
-+ cs0_spidev Set to 'off' to prevent the creation of a
-+ userspace device node /dev/spidev4.0 (default
-+ is 'on' or enabled).
-+
-+
-+Name: spi4-2cs
-+Info: Enables spi4 with two chip select (CS) lines and associated spidev
-+ dev nodes. The gpio pin numbers for the CS lines and spidev device node
-+ creation are configurable.
-+Load: dtoverlay=spi4-2cs,<param>=<val>
-+Params: cs0_pin GPIO pin for CS0 (default 4 - BCM SPI4_CE0).
-+ cs1_pin GPIO pin for CS1 (default 25 - BCM SPI4_CE1).
-+ cs0_spidev Set to 'off' to prevent the creation of a
-+ userspace device node /dev/spidev4.0 (default
-+ is 'on' or enabled).
-+ cs1_spidev Set to 'off' to prevent the creation of a
-+ userspace device node /dev/spidev4.1 (default
-+ is 'on' or enabled).
-+
-+
-+Name: spi5-1cs
-+Info: Enables spi5 with a single chip select (CS) line and associated spidev
-+ dev node. The gpio pin numbers for the CS lines and spidev device node
-+ creation are configurable.
-+Load: dtoverlay=spi5-1cs,<param>=<val>
-+Params: cs0_pin GPIO pin for CS0 (default 12 - BCM SPI5_CE0).
-+ cs0_spidev Set to 'off' to prevent the creation of a
-+ userspace device node /dev/spidev5.0 (default
-+ is 'on' or enabled).
-+
-+
-+Name: spi5-2cs
-+Info: Enables spi5 with two chip select (CS) lines and associated spidev
-+ dev nodes. The gpio pin numbers for the CS lines and spidev device node
-+ creation are configurable.
-+Load: dtoverlay=spi5-2cs,<param>=<val>
-+Params: cs0_pin GPIO pin for CS0 (default 12 - BCM SPI5_CE0).
-+ cs1_pin GPIO pin for CS1 (default 26 - BCM SPI5_CE1).
-+ cs0_spidev Set to 'off' to prevent the creation of a
-+ userspace device node /dev/spidev5.0 (default
-+ is 'on' or enabled).
-+ cs1_spidev Set to 'off' to prevent the creation of a
-+ userspace device node /dev/spidev5.1 (default
-+ is 'on' or enabled).
-+
-+
-+Name: spi6-1cs
-+Info: Enables spi6 with a single chip select (CS) line and associated spidev
-+ dev node. The gpio pin number for the CS line and spidev device node
-+ creation are configurable.
-+Load: dtoverlay=spi6-1cs,<param>=<val>
-+Params: cs0_pin GPIO pin for CS0 (default 18 - BCM SPI6_CE0).
-+ cs0_spidev Set to 'off' to prevent the creation of a
-+ userspace device node /dev/spidev6.0 (default
-+ is 'on' or enabled).
-+
-+
-+Name: spi6-2cs
-+Info: Enables spi6 with two chip select (CS) lines and associated spidev
-+ dev nodes. The gpio pin numbers for the CS lines and spidev device node
-+ creation are configurable.
-+Load: dtoverlay=spi6-2cs,<param>=<val>
-+Params: cs0_pin GPIO pin for CS0 (default 18 - BCM SPI6_CE0).
-+ cs1_pin GPIO pin for CS1 (default 27 - BCM SPI6_CE1).
-+ cs0_spidev Set to 'off' to prevent the creation of a
-+ userspace device node /dev/spidev6.0 (default
-+ is 'on' or enabled).
-+ cs1_spidev Set to 'off' to prevent the creation of a
-+ userspace device node /dev/spidev6.1 (default
-+ is 'on' or enabled).
-+
-+
- Name: ssd1306
- Info: Overlay for activation of SSD1306 over I2C OLED display framebuffer.
- Load: dtoverlay=ssd1306,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi3-1cs-overlay.dts
-@@ -0,0 +1,44 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&spi3_cs_pins>;
-+ frag0: __overlay__ {
-+ brcm,pins = <0>;
-+ brcm,function = <1>; /* output */
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&spi3>;
-+ frag1: __overlay__ {
-+ /* needed to avoid dtc warning */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&spi3_pins &spi3_cs_pins>;
-+ cs-gpios = <&gpio 0 1>;
-+ status = "okay";
-+
-+ spidev3_0: spidev@0 {
-+ compatible = "spidev";
-+ reg = <0>; /* CE0 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ __overrides__ {
-+ cs0_pin = <&frag0>,"brcm,pins:0",
-+ <&frag1>,"cs-gpios:4";
-+ cs0_spidev = <&spidev3_0>,"status";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi3-2cs-overlay.dts
-@@ -0,0 +1,56 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&spi3_cs_pins>;
-+ frag0: __overlay__ {
-+ brcm,pins = <0 24>;
-+ brcm,function = <1>; /* output */
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&spi3>;
-+ frag1: __overlay__ {
-+ /* needed to avoid dtc warning */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&spi3_pins &spi3_cs_pins>;
-+ cs-gpios = <&gpio 0 1>, <&gpio 24 1>;
-+ status = "okay";
-+
-+ spidev3_0: spidev@0 {
-+ compatible = "spidev";
-+ reg = <0>; /* CE0 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ status = "okay";
-+ };
-+
-+ spidev3_1: spidev@1 {
-+ compatible = "spidev";
-+ reg = <1>; /* CE1 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ __overrides__ {
-+ cs0_pin = <&frag0>,"brcm,pins:0",
-+ <&frag1>,"cs-gpios:4";
-+ cs1_pin = <&frag0>,"brcm,pins:4",
-+ <&frag1>,"cs-gpios:16";
-+ cs0_spidev = <&spidev3_0>,"status";
-+ cs1_spidev = <&spidev3_1>,"status";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi4-1cs-overlay.dts
-@@ -0,0 +1,44 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&spi4_cs_pins>;
-+ frag0: __overlay__ {
-+ brcm,pins = <4>;
-+ brcm,function = <1>; /* output */
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&spi4>;
-+ frag1: __overlay__ {
-+ /* needed to avoid dtc warning */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&spi4_pins &spi4_cs_pins>;
-+ cs-gpios = <&gpio 4 1>;
-+ status = "okay";
-+
-+ spidev4_0: spidev@0 {
-+ compatible = "spidev";
-+ reg = <0>; /* CE0 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ __overrides__ {
-+ cs0_pin = <&frag0>,"brcm,pins:0",
-+ <&frag1>,"cs-gpios:4";
-+ cs0_spidev = <&spidev4_0>,"status";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi4-2cs-overlay.dts
-@@ -0,0 +1,56 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&spi4_cs_pins>;
-+ frag0: __overlay__ {
-+ brcm,pins = <4 25>;
-+ brcm,function = <1>; /* output */
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&spi4>;
-+ frag1: __overlay__ {
-+ /* needed to avoid dtc warning */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&spi4_pins &spi4_cs_pins>;
-+ cs-gpios = <&gpio 4 1>, <&gpio 25 1>;
-+ status = "okay";
-+
-+ spidev4_0: spidev@0 {
-+ compatible = "spidev";
-+ reg = <0>; /* CE0 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ status = "okay";
-+ };
-+
-+ spidev4_1: spidev@1 {
-+ compatible = "spidev";
-+ reg = <1>; /* CE1 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ __overrides__ {
-+ cs0_pin = <&frag0>,"brcm,pins:0",
-+ <&frag1>,"cs-gpios:4";
-+ cs1_pin = <&frag0>,"brcm,pins:4",
-+ <&frag1>,"cs-gpios:16";
-+ cs0_spidev = <&spidev4_0>,"status";
-+ cs1_spidev = <&spidev4_1>,"status";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi5-1cs-overlay.dts
-@@ -0,0 +1,44 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&spi5_cs_pins>;
-+ frag0: __overlay__ {
-+ brcm,pins = <12>;
-+ brcm,function = <1>; /* output */
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&spi5>;
-+ frag1: __overlay__ {
-+ /* needed to avoid dtc warning */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&spi5_pins &spi5_cs_pins>;
-+ cs-gpios = <&gpio 12 1>;
-+ status = "okay";
-+
-+ spidev5_0: spidev@0 {
-+ compatible = "spidev";
-+ reg = <0>; /* CE0 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ __overrides__ {
-+ cs0_pin = <&frag0>,"brcm,pins:0",
-+ <&frag1>,"cs-gpios:4";
-+ cs0_spidev = <&spidev5_0>,"status";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi5-2cs-overlay.dts
-@@ -0,0 +1,56 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&spi5_cs_pins>;
-+ frag0: __overlay__ {
-+ brcm,pins = <12 26>;
-+ brcm,function = <1>; /* output */
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&spi5>;
-+ frag1: __overlay__ {
-+ /* needed to avoid dtc warning */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&spi5_pins &spi5_cs_pins>;
-+ cs-gpios = <&gpio 12 1>, <&gpio 26 1>;
-+ status = "okay";
-+
-+ spidev5_0: spidev@0 {
-+ compatible = "spidev";
-+ reg = <0>; /* CE0 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ status = "okay";
-+ };
-+
-+ spidev5_1: spidev@1 {
-+ compatible = "spidev";
-+ reg = <1>; /* CE1 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ __overrides__ {
-+ cs0_pin = <&frag0>,"brcm,pins:0",
-+ <&frag1>,"cs-gpios:4";
-+ cs1_pin = <&frag0>,"brcm,pins:4",
-+ <&frag1>,"cs-gpios:16";
-+ cs0_spidev = <&spidev5_0>,"status";
-+ cs1_spidev = <&spidev5_1>,"status";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi6-1cs-overlay.dts
-@@ -0,0 +1,44 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&spi6_cs_pins>;
-+ frag0: __overlay__ {
-+ brcm,pins = <18>;
-+ brcm,function = <1>; /* output */
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&spi6>;
-+ frag1: __overlay__ {
-+ /* needed to avoid dtc warning */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&spi6_pins &spi6_cs_pins>;
-+ cs-gpios = <&gpio 18 1>;
-+ status = "okay";
-+
-+ spidev6_0: spidev@0 {
-+ compatible = "spidev";
-+ reg = <0>; /* CE0 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ __overrides__ {
-+ cs0_pin = <&frag0>,"brcm,pins:0",
-+ <&frag1>,"cs-gpios:4";
-+ cs0_spidev = <&spidev6_0>,"status";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi6-2cs-overlay.dts
-@@ -0,0 +1,56 @@
-+/dts-v1/;
-+/plugin/;
-+
-+
-+/ {
-+ compatible = "brcm,bcm2838";
-+
-+ fragment@0 {
-+ target = <&spi6_cs_pins>;
-+ frag0: __overlay__ {
-+ brcm,pins = <18 27>;
-+ brcm,function = <1>; /* output */
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&spi6>;
-+ frag1: __overlay__ {
-+ /* needed to avoid dtc warning */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&spi6_pins &spi6_cs_pins>;
-+ cs-gpios = <&gpio 18 1>, <&gpio 27 1>;
-+ status = "okay";
-+
-+ spidev6_0: spidev@0 {
-+ compatible = "spidev";
-+ reg = <0>; /* CE0 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ status = "okay";
-+ };
-+
-+ spidev6_1: spidev@1 {
-+ compatible = "spidev";
-+ reg = <1>; /* CE1 */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <125000000>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ __overrides__ {
-+ cs0_pin = <&frag0>,"brcm,pins:0",
-+ <&frag1>,"cs-gpios:4";
-+ cs1_pin = <&frag0>,"brcm,pins:4",
-+ <&frag1>,"cs-gpios:16";
-+ cs0_spidev = <&spidev6_0>,"status";
-+ cs1_spidev = <&spidev6_1>,"status";
-+ };
-+};
--- /dev/null
+From ab6bac248c5cd5950b5658be31e7484b1eac9333 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 3 Jun 2019 14:57:56 +0100
+Subject: [PATCH 642/725] config: Add NF_TABLES support
+
+---
+ arch/arm/configs/bcm2711_defconfig | 48 ++++++++++++++++++++++++++++++
+ 1 file changed, 48 insertions(+)
+
+--- a/arch/arm/configs/bcm2711_defconfig
++++ b/arch/arm/configs/bcm2711_defconfig
+@@ -133,6 +133,36 @@ CONFIG_NF_CONNTRACK_SANE=m
+ CONFIG_NF_CONNTRACK_SIP=m
+ CONFIG_NF_CONNTRACK_TFTP=m
+ CONFIG_NF_CT_NETLINK=m
++CONFIG_NF_TABLES=m
++CONFIG_NF_TABLES_SET=m
++CONFIG_NF_TABLES_INET=y
++CONFIG_NF_TABLES_NETDEV=y
++CONFIG_NFT_NUMGEN=m
++CONFIG_NFT_CT=m
++CONFIG_NFT_FLOW_OFFLOAD=m
++CONFIG_NFT_COUNTER=m
++CONFIG_NFT_CONNLIMIT=m
++CONFIG_NFT_LOG=m
++CONFIG_NFT_LIMIT=m
++CONFIG_NFT_MASQ=m
++CONFIG_NFT_REDIR=m
++CONFIG_NFT_NAT=m
++CONFIG_NFT_TUNNEL=m
++CONFIG_NFT_OBJREF=m
++CONFIG_NFT_QUEUE=m
++CONFIG_NFT_QUOTA=m
++CONFIG_NFT_REJECT=m
++CONFIG_NFT_COMPAT=m
++CONFIG_NFT_HASH=m
++CONFIG_NFT_FIB_INET=m
++CONFIG_NFT_SOCKET=m
++CONFIG_NFT_OSF=m
++CONFIG_NFT_TPROXY=m
++CONFIG_NFT_DUP_NETDEV=m
++CONFIG_NFT_FWD_NETDEV=m
++CONFIG_NFT_FIB_NETDEV=m
++CONFIG_NF_FLOW_TABLE_INET=m
++CONFIG_NF_FLOW_TABLE=m
+ CONFIG_NETFILTER_XT_SET=m
+ CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+ CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+@@ -220,6 +250,14 @@ CONFIG_IP_VS_SED=m
+ CONFIG_IP_VS_NQ=m
+ CONFIG_IP_VS_FTP=m
+ CONFIG_IP_VS_PE_SIP=m
++CONFIG_NFT_CHAIN_ROUTE_IPV4=m
++CONFIG_NFT_DUP_IPV4=m
++CONFIG_NFT_FIB_IPV4=m
++CONFIG_NF_TABLES_ARP=y
++CONFIG_NF_FLOW_TABLE_IPV4=m
++CONFIG_NFT_CHAIN_NAT_IPV4=m
++CONFIG_NFT_MASQ_IPV4=m
++CONFIG_NFT_REDIR_IPV4=m
+ CONFIG_IP_NF_IPTABLES=m
+ CONFIG_IP_NF_MATCH_AH=m
+ CONFIG_IP_NF_MATCH_ECN=m
+@@ -239,6 +277,13 @@ CONFIG_IP_NF_RAW=m
+ CONFIG_IP_NF_ARPTABLES=m
+ CONFIG_IP_NF_ARPFILTER=m
+ CONFIG_IP_NF_ARP_MANGLE=m
++CONFIG_NFT_CHAIN_ROUTE_IPV6=m
++CONFIG_NFT_CHAIN_NAT_IPV6=m
++CONFIG_NFT_MASQ_IPV6=m
++CONFIG_NFT_REDIR_IPV6=m
++CONFIG_NFT_DUP_IPV6=m
++CONFIG_NFT_FIB_IPV6=m
++CONFIG_NF_FLOW_TABLE_IPV6=m
+ CONFIG_IP6_NF_IPTABLES=m
+ CONFIG_IP6_NF_MATCH_AH=m
+ CONFIG_IP6_NF_MATCH_EUI64=m
+@@ -257,6 +302,9 @@ CONFIG_IP6_NF_RAW=m
+ CONFIG_IP6_NF_NAT=m
+ CONFIG_IP6_NF_TARGET_MASQUERADE=m
+ CONFIG_IP6_NF_TARGET_NPT=m
++CONFIG_NF_TABLES_BRIDGE=y
++CONFIG_NFT_BRIDGE_REJECT=m
++CONFIG_NF_LOG_BRIDGE=m
+ CONFIG_BRIDGE_NF_EBTABLES=m
+ CONFIG_BRIDGE_EBT_BROUTE=m
+ CONFIG_BRIDGE_EBT_T_FILTER=m
+++ /dev/null
-From 14cd6256f49abbf230edc0c7a963f5e780255e98 Mon Sep 17 00:00:00 2001
-From: Tim Gover <tim.gover@raspberrypi.org>
-Date: Tue, 22 Jan 2019 10:49:41 +0000
-Subject: [PATCH 642/703] overlays: Add the spi-gpio40-45 overlay
-
-The 2711 B0 boot EEPROM is programmed via SPI0 on GPIO
-pins 40-43 CS0. Add a device tree overlay to optionally
-change the SPI0 pinmux from the external GPIO pins to
-the boot EEPROM pins.
----
- arch/arm/boot/dts/overlays/Makefile | 1 +
- arch/arm/boot/dts/overlays/README | 6 ++++
- .../dts/overlays/spi-gpio40-45-overlay.dts | 36 +++++++++++++++++++
- 3 files changed, 43 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/spi-gpio40-45-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -135,6 +135,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- smi-dev.dtbo \
- smi-nand.dtbo \
- spi-gpio35-39.dtbo \
-+ spi-gpio40-45.dtbo \
- spi-rtc.dtbo \
- spi0-cs.dtbo \
- spi0-hw-cs.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1967,6 +1967,12 @@ Load: dtoverlay=spi-gpio35-39
- Params: <None>
-
-
-+Name: spi-gpio40-45
-+Info: Move SPI function block to GPIOs 40 to 45
-+Load: dtoverlay=spi-gpio40-45
-+Params: <None>
-+
-+
- Name: spi-rtc
- Info: Adds support for a number of SPI Real Time Clock devices
- Load: dtoverlay=spi-rtc,<param>=<val>
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/spi-gpio40-45-overlay.dts
-@@ -0,0 +1,36 @@
-+/*
-+ * Boot EEPROM overlay
-+ */
-+
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+ compatible = "brcm,bcm2835";
-+
-+ fragment@0 {
-+ target = <&spi0>;
-+ __overlay__ {
-+ cs-gpios = <&gpio 43 1>, <&gpio 44 1>, <&gpio 45 1>;
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&spi0_cs_pins>;
-+ __overlay__ {
-+ brcm,pins = <45 44 43>;
-+ brcm,function = <1>; /* output */
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@2 {
-+ target = <&spi0_pins>;
-+ __overlay__ {
-+ brcm,pins = <40 41 42>;
-+ brcm,function = <3>; /* alt4 */
-+ status = "okay";
-+ };
-+ };
-+};
--- /dev/null
+From 7c68e81f33c801e539baece66f4d4b7e2c129557 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Mon, 3 Jun 2019 15:33:02 +0100
+Subject: [PATCH 643/725] bcm2711_defconfig: add xhci platform support
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ arch/arm/configs/bcm2711_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/configs/bcm2711_defconfig
++++ b/arch/arm/configs/bcm2711_defconfig
+@@ -983,6 +983,7 @@ CONFIG_USB=y
+ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+ CONFIG_USB_MON=m
+ CONFIG_USB_XHCI_HCD=y
++CONFIG_USB_XHCI_PLATFORM=y
+ CONFIG_USB_DWCOTG=y
+ CONFIG_USB_PRINTER=m
+ CONFIG_USB_STORAGE=y
+++ /dev/null
-From fde90a0d1ca0b9a7dc0a7beec2ef60ec71b5cc7d Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 4 Sep 2018 11:50:25 +0100
-Subject: [PATCH 643/703] config: Permit LPAE and PCIE_BRCMSTB on BCM2835
-
----
- arch/arm/mach-bcm/Kconfig | 4 ++++
- drivers/pci/controller/Kconfig | 4 ++--
- 2 files changed, 6 insertions(+), 2 deletions(-)
-
---- a/arch/arm/mach-bcm/Kconfig
-+++ b/arch/arm/mach-bcm/Kconfig
-@@ -161,6 +161,7 @@ config ARCH_BCM2835
- select GPIOLIB
- select ARM_AMBA
- select ARM_ERRATA_411920 if ARCH_MULTI_V6
-+ select ARM_GIC
- select ARM_TIMER_SP804
- select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7
- select TIMER_OF
-@@ -169,6 +170,9 @@ config ARCH_BCM2835
- select PINCTRL
- select PINCTRL_BCM2835
- select MFD_SYSCON if ARCH_MULTI_V7
-+ select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
-+ select ZONE_DMA if ARM_LPAE
-+ select MFD_CORE
- help
- This enables support for the Broadcom BCM2835 and BCM2836 SoCs.
- This SoC is used in the Raspberry Pi and Roku 2 devices.
---- a/drivers/pci/controller/Kconfig
-+++ b/drivers/pci/controller/Kconfig
-@@ -280,9 +280,9 @@ config VMD
-
- config PCIE_BRCMSTB
- tristate "Broadcom Brcmstb PCIe platform host driver"
-- depends on ARCH_BRCMSTB || BMIPS_GENERIC
-+ depends on ARCH_BRCMSTB || BMIPS_GENERIC || ARCH_BCM2835
- depends on OF
-- depends on SOC_BRCMSTB
-+ depends on SOC_BRCMSTB || ARCH_BCM2835
- default ARCH_BRCMSTB || BMIPS_GENERIC
- help
- Adds support for Broadcom Settop Box PCIe host controller.
--- /dev/null
+From 267eeb807da04f60d94b8355858926e8aad65a38 Mon Sep 17 00:00:00 2001
+From: 6by9 <6by9@users.noreply.github.com>
+Date: Wed, 30 Jan 2019 14:22:03 +0000
+Subject: [PATCH 644/725] ARM: dts: bcm283x: Correct vchiq compatible string
+ (#2840)
+
+commit 499770ede3f829e80539f46b59b5f460dc327aa6 upstream.
+
+To allow VCHIQ to determine the correct cache line size, use the new
+"brcm,bcm2836-vchiq" compatible string on BCM2836 and BCM2837.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
+---
+ arch/arm/boot/dts/bcm2835-rpi.dtsi | 2 +-
+ arch/arm/boot/dts/bcm2836-rpi-2-b.dts | 2 +-
+ arch/arm/boot/dts/bcm2836-rpi.dtsi | 6 ++++++
+ arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2 +-
+ arch/arm/boot/dts/bcm2837-rpi-3-b.dts | 2 +-
+ 5 files changed, 10 insertions(+), 4 deletions(-)
+ create mode 100644 arch/arm/boot/dts/bcm2836-rpi.dtsi
+
+--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
+@@ -30,7 +30,7 @@
+ #power-domain-cells = <1>;
+ };
+
+- mailbox@7e00b840 {
++ vchiq: mailbox@7e00b840 {
+ compatible = "brcm,bcm2835-vchiq";
+ reg = <0x7e00b840 0x3c>;
+ interrupts = <0 2>;
+--- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
++++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /dts-v1/;
+ #include "bcm2836.dtsi"
+-#include "bcm2835-rpi.dtsi"
++#include "bcm2836-rpi.dtsi"
+ #include "bcm283x-rpi-smsc9514.dtsi"
+ #include "bcm283x-rpi-usb-host.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2836-rpi.dtsi
+@@ -0,0 +1,6 @@
++// SPDX-License-Identifier: GPL-2.0
++#include "bcm2835-rpi.dtsi"
++
++&vchiq {
++ compatible = "brcm,bcm2836-vchiq", "brcm,bcm2835-vchiq";
++};
+--- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /dts-v1/;
+ #include "bcm2837.dtsi"
+-#include "bcm2835-rpi.dtsi"
++#include "bcm2836-rpi.dtsi"
+ #include "bcm283x-rpi-lan7515.dtsi"
+ #include "bcm283x-rpi-usb-host.dtsi"
+
+--- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /dts-v1/;
+ #include "bcm2837.dtsi"
+-#include "bcm2835-rpi.dtsi"
++#include "bcm2836-rpi.dtsi"
+ #include "bcm283x-rpi-smsc9514.dtsi"
+ #include "bcm283x-rpi-usb-host.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+++ /dev/null
-From 5ae8b0086763f26a25da24133eca8ecd3e5ef5a5 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 29 May 2019 15:40:21 +0100
-Subject: [PATCH 644/703] configs: Add bcm2711_defconfig
-
----
- arch/arm/configs/bcm2711_defconfig | 1330 ++++++++++++++++++++++++++++
- 1 file changed, 1330 insertions(+)
- create mode 100644 arch/arm/configs/bcm2711_defconfig
-
---- /dev/null
-+++ b/arch/arm/configs/bcm2711_defconfig
-@@ -0,0 +1,1330 @@
-+CONFIG_LOCALVERSION="-v7l"
-+# CONFIG_LOCALVERSION_AUTO is not set
-+CONFIG_SYSVIPC=y
-+CONFIG_POSIX_MQUEUE=y
-+CONFIG_GENERIC_IRQ_DEBUGFS=y
-+CONFIG_NO_HZ=y
-+CONFIG_HIGH_RES_TIMERS=y
-+CONFIG_PREEMPT_VOLUNTARY=y
-+CONFIG_BSD_PROCESS_ACCT=y
-+CONFIG_BSD_PROCESS_ACCT_V3=y
-+CONFIG_TASKSTATS=y
-+CONFIG_TASK_DELAY_ACCT=y
-+CONFIG_TASK_XACCT=y
-+CONFIG_TASK_IO_ACCOUNTING=y
-+CONFIG_IKCONFIG=m
-+CONFIG_IKCONFIG_PROC=y
-+CONFIG_CGROUP_FREEZER=y
-+CONFIG_CPUSETS=y
-+CONFIG_CGROUP_DEVICE=y
-+CONFIG_CGROUP_CPUACCT=y
-+CONFIG_NAMESPACES=y
-+CONFIG_USER_NS=y
-+CONFIG_SCHED_AUTOGROUP=y
-+CONFIG_BLK_DEV_INITRD=y
-+CONFIG_EMBEDDED=y
-+# CONFIG_COMPAT_BRK is not set
-+CONFIG_PROFILING=y
-+CONFIG_ARCH_BCM=y
-+CONFIG_ARCH_BCM2835=y
-+CONFIG_ARM_LPAE=y
-+# CONFIG_CACHE_L2X0 is not set
-+CONFIG_PCI=y
-+CONFIG_PCI_MSI=y
-+CONFIG_PCIE_BRCMSTB=y
-+CONFIG_SMP=y
-+CONFIG_HIGHMEM=y
-+CONFIG_UACCESS_WITH_MEMCPY=y
-+CONFIG_SECCOMP=y
-+# CONFIG_ATAGS is not set
-+CONFIG_ZBOOT_ROM_TEXT=0x0
-+CONFIG_ZBOOT_ROM_BSS=0x0
-+CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait"
-+CONFIG_CPU_FREQ=y
-+CONFIG_CPU_FREQ_STAT=y
-+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y
-+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-+CONFIG_CPU_FREQ_GOV_USERSPACE=y
-+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
-+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
-+CONFIG_VFP=y
-+CONFIG_NEON=y
-+CONFIG_KERNEL_MODE_NEON=y
-+# CONFIG_SUSPEND is not set
-+CONFIG_PM=y
-+CONFIG_RASPBERRYPI_FIRMWARE=y
-+CONFIG_ARM_CRYPTO=y
-+CONFIG_CRYPTO_SHA1_ARM_NEON=m
-+CONFIG_CRYPTO_AES_ARM=m
-+CONFIG_CRYPTO_AES_ARM_BS=m
-+CONFIG_OPROFILE=m
-+CONFIG_KPROBES=y
-+CONFIG_JUMP_LABEL=y
-+CONFIG_MODULES=y
-+CONFIG_MODULE_UNLOAD=y
-+CONFIG_MODVERSIONS=y
-+CONFIG_MODULE_SRCVERSION_ALL=y
-+CONFIG_PARTITION_ADVANCED=y
-+CONFIG_MAC_PARTITION=y
-+CONFIG_BINFMT_MISC=m
-+CONFIG_CLEANCACHE=y
-+CONFIG_FRONTSWAP=y
-+CONFIG_CMA=y
-+CONFIG_ZSMALLOC=m
-+CONFIG_PGTABLE_MAPPING=y
-+CONFIG_NET=y
-+CONFIG_PACKET=y
-+CONFIG_UNIX=y
-+CONFIG_XFRM_USER=y
-+CONFIG_NET_KEY=m
-+CONFIG_INET=y
-+CONFIG_IP_MULTICAST=y
-+CONFIG_IP_ADVANCED_ROUTER=y
-+CONFIG_IP_MULTIPLE_TABLES=y
-+CONFIG_IP_ROUTE_MULTIPATH=y
-+CONFIG_IP_ROUTE_VERBOSE=y
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+CONFIG_IP_PNP_RARP=y
-+CONFIG_NET_IPIP=m
-+CONFIG_NET_IPGRE_DEMUX=m
-+CONFIG_NET_IPGRE=m
-+CONFIG_IP_MROUTE=y
-+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
-+CONFIG_IP_PIMSM_V1=y
-+CONFIG_IP_PIMSM_V2=y
-+CONFIG_SYN_COOKIES=y
-+CONFIG_INET_AH=m
-+CONFIG_INET_ESP=m
-+CONFIG_INET_IPCOMP=m
-+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_IPV6_ROUTE_INFO=y
-+CONFIG_INET6_AH=m
-+CONFIG_INET6_ESP=m
-+CONFIG_INET6_IPCOMP=m
-+CONFIG_IPV6_SIT_6RD=y
-+CONFIG_IPV6_TUNNEL=m
-+CONFIG_IPV6_MULTIPLE_TABLES=y
-+CONFIG_IPV6_SUBTREES=y
-+CONFIG_IPV6_MROUTE=y
-+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
-+CONFIG_IPV6_PIMSM_V2=y
-+CONFIG_NETFILTER=y
-+CONFIG_NF_CONNTRACK=m
-+CONFIG_NF_CONNTRACK_ZONES=y
-+CONFIG_NF_CONNTRACK_EVENTS=y
-+CONFIG_NF_CONNTRACK_TIMESTAMP=y
-+CONFIG_NF_CONNTRACK_AMANDA=m
-+CONFIG_NF_CONNTRACK_FTP=m
-+CONFIG_NF_CONNTRACK_H323=m
-+CONFIG_NF_CONNTRACK_IRC=m
-+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
-+CONFIG_NF_CONNTRACK_SNMP=m
-+CONFIG_NF_CONNTRACK_PPTP=m
-+CONFIG_NF_CONNTRACK_SANE=m
-+CONFIG_NF_CONNTRACK_SIP=m
-+CONFIG_NF_CONNTRACK_TFTP=m
-+CONFIG_NF_CT_NETLINK=m
-+CONFIG_NETFILTER_XT_SET=m
-+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
-+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
-+CONFIG_NETFILTER_XT_TARGET_DSCP=m
-+CONFIG_NETFILTER_XT_TARGET_HMARK=m
-+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
-+CONFIG_NETFILTER_XT_TARGET_LED=m
-+CONFIG_NETFILTER_XT_TARGET_LOG=m
-+CONFIG_NETFILTER_XT_TARGET_MARK=m
-+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
-+CONFIG_NETFILTER_XT_TARGET_TEE=m
-+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
-+CONFIG_NETFILTER_XT_TARGET_TRACE=m
-+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
-+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
-+CONFIG_NETFILTER_XT_MATCH_BPF=m
-+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
-+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
-+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
-+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-+CONFIG_NETFILTER_XT_MATCH_CPU=m
-+CONFIG_NETFILTER_XT_MATCH_DCCP=m
-+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
-+CONFIG_NETFILTER_XT_MATCH_DSCP=m
-+CONFIG_NETFILTER_XT_MATCH_ESP=m
-+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
-+CONFIG_NETFILTER_XT_MATCH_HELPER=m
-+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
-+CONFIG_NETFILTER_XT_MATCH_IPVS=m
-+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-+CONFIG_NETFILTER_XT_MATCH_MAC=m
-+CONFIG_NETFILTER_XT_MATCH_MARK=m
-+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
-+CONFIG_NETFILTER_XT_MATCH_OSF=m
-+CONFIG_NETFILTER_XT_MATCH_OWNER=m
-+CONFIG_NETFILTER_XT_MATCH_POLICY=m
-+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
-+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-+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_STATE=m
-+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-+CONFIG_NETFILTER_XT_MATCH_STRING=m
-+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-+CONFIG_NETFILTER_XT_MATCH_TIME=m
-+CONFIG_NETFILTER_XT_MATCH_U32=m
-+CONFIG_IP_SET=m
-+CONFIG_IP_SET_BITMAP_IP=m
-+CONFIG_IP_SET_BITMAP_IPMAC=m
-+CONFIG_IP_SET_BITMAP_PORT=m
-+CONFIG_IP_SET_HASH_IP=m
-+CONFIG_IP_SET_HASH_IPPORT=m
-+CONFIG_IP_SET_HASH_IPPORTIP=m
-+CONFIG_IP_SET_HASH_IPPORTNET=m
-+CONFIG_IP_SET_HASH_NET=m
-+CONFIG_IP_SET_HASH_NETPORT=m
-+CONFIG_IP_SET_HASH_NETIFACE=m
-+CONFIG_IP_SET_LIST_SET=m
-+CONFIG_IP_VS=m
-+CONFIG_IP_VS_PROTO_TCP=y
-+CONFIG_IP_VS_PROTO_UDP=y
-+CONFIG_IP_VS_PROTO_ESP=y
-+CONFIG_IP_VS_PROTO_AH=y
-+CONFIG_IP_VS_PROTO_SCTP=y
-+CONFIG_IP_VS_RR=m
-+CONFIG_IP_VS_WRR=m
-+CONFIG_IP_VS_LC=m
-+CONFIG_IP_VS_WLC=m
-+CONFIG_IP_VS_LBLC=m
-+CONFIG_IP_VS_LBLCR=m
-+CONFIG_IP_VS_DH=m
-+CONFIG_IP_VS_SH=m
-+CONFIG_IP_VS_SED=m
-+CONFIG_IP_VS_NQ=m
-+CONFIG_IP_VS_FTP=m
-+CONFIG_IP_VS_PE_SIP=m
-+CONFIG_IP_NF_IPTABLES=m
-+CONFIG_IP_NF_MATCH_AH=m
-+CONFIG_IP_NF_MATCH_ECN=m
-+CONFIG_IP_NF_MATCH_RPFILTER=m
-+CONFIG_IP_NF_MATCH_TTL=m
-+CONFIG_IP_NF_FILTER=m
-+CONFIG_IP_NF_TARGET_REJECT=m
-+CONFIG_IP_NF_NAT=m
-+CONFIG_IP_NF_TARGET_MASQUERADE=m
-+CONFIG_IP_NF_TARGET_NETMAP=m
-+CONFIG_IP_NF_TARGET_REDIRECT=m
-+CONFIG_IP_NF_MANGLE=m
-+CONFIG_IP_NF_TARGET_CLUSTERIP=m
-+CONFIG_IP_NF_TARGET_ECN=m
-+CONFIG_IP_NF_TARGET_TTL=m
-+CONFIG_IP_NF_RAW=m
-+CONFIG_IP_NF_ARPTABLES=m
-+CONFIG_IP_NF_ARPFILTER=m
-+CONFIG_IP_NF_ARP_MANGLE=m
-+CONFIG_IP6_NF_IPTABLES=m
-+CONFIG_IP6_NF_MATCH_AH=m
-+CONFIG_IP6_NF_MATCH_EUI64=m
-+CONFIG_IP6_NF_MATCH_FRAG=m
-+CONFIG_IP6_NF_MATCH_OPTS=m
-+CONFIG_IP6_NF_MATCH_HL=m
-+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-+CONFIG_IP6_NF_MATCH_MH=m
-+CONFIG_IP6_NF_MATCH_RPFILTER=m
-+CONFIG_IP6_NF_MATCH_RT=m
-+CONFIG_IP6_NF_TARGET_HL=m
-+CONFIG_IP6_NF_FILTER=m
-+CONFIG_IP6_NF_TARGET_REJECT=m
-+CONFIG_IP6_NF_MANGLE=m
-+CONFIG_IP6_NF_RAW=m
-+CONFIG_IP6_NF_NAT=m
-+CONFIG_IP6_NF_TARGET_MASQUERADE=m
-+CONFIG_IP6_NF_TARGET_NPT=m
-+CONFIG_BRIDGE_NF_EBTABLES=m
-+CONFIG_BRIDGE_EBT_BROUTE=m
-+CONFIG_BRIDGE_EBT_T_FILTER=m
-+CONFIG_BRIDGE_EBT_T_NAT=m
-+CONFIG_BRIDGE_EBT_802_3=m
-+CONFIG_BRIDGE_EBT_AMONG=m
-+CONFIG_BRIDGE_EBT_ARP=m
-+CONFIG_BRIDGE_EBT_IP=m
-+CONFIG_BRIDGE_EBT_IP6=m
-+CONFIG_BRIDGE_EBT_LIMIT=m
-+CONFIG_BRIDGE_EBT_MARK=m
-+CONFIG_BRIDGE_EBT_PKTTYPE=m
-+CONFIG_BRIDGE_EBT_STP=m
-+CONFIG_BRIDGE_EBT_VLAN=m
-+CONFIG_BRIDGE_EBT_ARPREPLY=m
-+CONFIG_BRIDGE_EBT_DNAT=m
-+CONFIG_BRIDGE_EBT_MARK_T=m
-+CONFIG_BRIDGE_EBT_REDIRECT=m
-+CONFIG_BRIDGE_EBT_SNAT=m
-+CONFIG_BRIDGE_EBT_LOG=m
-+CONFIG_BRIDGE_EBT_NFLOG=m
-+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
-+CONFIG_ATM=m
-+CONFIG_L2TP=m
-+CONFIG_L2TP_V3=y
-+CONFIG_L2TP_IP=m
-+CONFIG_L2TP_ETH=m
-+CONFIG_BRIDGE=m
-+CONFIG_VLAN_8021Q=m
-+CONFIG_VLAN_8021Q_GVRP=y
-+CONFIG_ATALK=m
-+CONFIG_6LOWPAN=m
-+CONFIG_IEEE802154=m
-+CONFIG_IEEE802154_6LOWPAN=m
-+CONFIG_MAC802154=m
-+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
-+CONFIG_NET_SCH_SFB=m
-+CONFIG_NET_SCH_SFQ=m
-+CONFIG_NET_SCH_TEQL=m
-+CONFIG_NET_SCH_TBF=m
-+CONFIG_NET_SCH_GRED=m
-+CONFIG_NET_SCH_DSMARK=m
-+CONFIG_NET_SCH_NETEM=m
-+CONFIG_NET_SCH_DRR=m
-+CONFIG_NET_SCH_MQPRIO=m
-+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
-+CONFIG_NET_CLS_TCINDEX=m
-+CONFIG_NET_CLS_ROUTE4=m
-+CONFIG_NET_CLS_FW=m
-+CONFIG_NET_CLS_U32=m
-+CONFIG_CLS_U32_MARK=y
-+CONFIG_NET_CLS_RSVP=m
-+CONFIG_NET_CLS_RSVP6=m
-+CONFIG_NET_CLS_FLOW=m
-+CONFIG_NET_CLS_CGROUP=m
-+CONFIG_NET_EMATCH=y
-+CONFIG_NET_EMATCH_CMP=m
-+CONFIG_NET_EMATCH_NBYTE=m
-+CONFIG_NET_EMATCH_U32=m
-+CONFIG_NET_EMATCH_META=m
-+CONFIG_NET_EMATCH_TEXT=m
-+CONFIG_NET_EMATCH_IPSET=m
-+CONFIG_NET_CLS_ACT=y
-+CONFIG_NET_ACT_POLICE=m
-+CONFIG_NET_ACT_GACT=m
-+CONFIG_GACT_PROB=y
-+CONFIG_NET_ACT_MIRRED=m
-+CONFIG_NET_ACT_IPT=m
-+CONFIG_NET_ACT_NAT=m
-+CONFIG_NET_ACT_PEDIT=m
-+CONFIG_NET_ACT_SIMP=m
-+CONFIG_NET_ACT_SKBEDIT=m
-+CONFIG_NET_ACT_CSUM=m
-+CONFIG_BATMAN_ADV=m
-+CONFIG_OPENVSWITCH=m
-+CONFIG_NET_PKTGEN=m
-+CONFIG_HAMRADIO=y
-+CONFIG_AX25=m
-+CONFIG_NETROM=m
-+CONFIG_ROSE=m
-+CONFIG_MKISS=m
-+CONFIG_6PACK=m
-+CONFIG_BPQETHER=m
-+CONFIG_BAYCOM_SER_FDX=m
-+CONFIG_BAYCOM_SER_HDX=m
-+CONFIG_YAM=m
-+CONFIG_CAN=m
-+CONFIG_CAN_VCAN=m
-+CONFIG_CAN_SLCAN=m
-+CONFIG_CAN_MCP251X=m
-+CONFIG_CAN_GS_USB=m
-+CONFIG_BT=m
-+CONFIG_BT_RFCOMM=m
-+CONFIG_BT_RFCOMM_TTY=y
-+CONFIG_BT_BNEP=m
-+CONFIG_BT_BNEP_MC_FILTER=y
-+CONFIG_BT_BNEP_PROTO_FILTER=y
-+CONFIG_BT_HIDP=m
-+CONFIG_BT_6LOWPAN=m
-+CONFIG_BT_HCIBTUSB=m
-+CONFIG_BT_HCIUART=m
-+CONFIG_BT_HCIUART_3WIRE=y
-+CONFIG_BT_HCIUART_BCM=y
-+CONFIG_BT_HCIBCM203X=m
-+CONFIG_BT_HCIBPA10X=m
-+CONFIG_BT_HCIBFUSB=m
-+CONFIG_BT_HCIVHCI=m
-+CONFIG_BT_MRVL=m
-+CONFIG_BT_MRVL_SDIO=m
-+CONFIG_BT_ATH3K=m
-+CONFIG_BT_WILINK=m
-+CONFIG_CFG80211=m
-+CONFIG_MAC80211=m
-+CONFIG_MAC80211_MESH=y
-+CONFIG_WIMAX=m
-+CONFIG_RFKILL=m
-+CONFIG_RFKILL_INPUT=y
-+CONFIG_NET_9P=m
-+CONFIG_NFC=m
-+CONFIG_DEVTMPFS=y
-+CONFIG_DEVTMPFS_MOUNT=y
-+CONFIG_DMA_CMA=y
-+CONFIG_CMA_SIZE_MBYTES=5
-+CONFIG_MTD=m
-+CONFIG_MTD_BLOCK=m
-+CONFIG_MTD_M25P80=m
-+CONFIG_MTD_BLOCK2MTD=m
-+CONFIG_MTD_NAND=m
-+CONFIG_MTD_SPI_NOR=m
-+CONFIG_MTD_UBI=m
-+CONFIG_OF_CONFIGFS=y
-+CONFIG_ZRAM=m
-+CONFIG_BLK_DEV_LOOP=y
-+CONFIG_BLK_DEV_CRYPTOLOOP=m
-+CONFIG_BLK_DEV_DRBD=m
-+CONFIG_BLK_DEV_NBD=m
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_CDROM_PKTCDVD=m
-+CONFIG_ATA_OVER_ETH=m
-+CONFIG_EEPROM_AT24=m
-+CONFIG_TI_ST=m
-+CONFIG_SCSI=y
-+# CONFIG_SCSI_PROC_FS is not set
-+CONFIG_BLK_DEV_SD=y
-+CONFIG_CHR_DEV_ST=m
-+CONFIG_CHR_DEV_OSST=m
-+CONFIG_BLK_DEV_SR=m
-+CONFIG_CHR_DEV_SG=m
-+CONFIG_SCSI_ISCSI_ATTRS=y
-+CONFIG_ISCSI_TCP=m
-+CONFIG_ISCSI_BOOT_SYSFS=m
-+CONFIG_MD=y
-+CONFIG_MD_LINEAR=m
-+CONFIG_BLK_DEV_DM=m
-+CONFIG_DM_CRYPT=m
-+CONFIG_DM_SNAPSHOT=m
-+CONFIG_DM_THIN_PROVISIONING=m
-+CONFIG_DM_CACHE=m
-+CONFIG_DM_MIRROR=m
-+CONFIG_DM_LOG_USERSPACE=m
-+CONFIG_DM_RAID=m
-+CONFIG_DM_ZERO=m
-+CONFIG_DM_DELAY=m
-+CONFIG_NETDEVICES=y
-+CONFIG_BONDING=m
-+CONFIG_DUMMY=m
-+CONFIG_IFB=m
-+CONFIG_MACVLAN=m
-+CONFIG_IPVLAN=m
-+CONFIG_VXLAN=m
-+CONFIG_NETCONSOLE=m
-+CONFIG_TUN=m
-+CONFIG_VETH=m
-+CONFIG_BCMGENET=y
-+CONFIG_ENC28J60=m
-+CONFIG_QCA7000_SPI=m
-+CONFIG_MDIO_BITBANG=m
-+CONFIG_BROADCOM_PHY=y
-+CONFIG_PPP=m
-+CONFIG_PPP_BSDCOMP=m
-+CONFIG_PPP_DEFLATE=m
-+CONFIG_PPP_FILTER=y
-+CONFIG_PPP_MPPE=m
-+CONFIG_PPP_MULTILINK=y
-+CONFIG_PPPOATM=m
-+CONFIG_PPPOE=m
-+CONFIG_PPPOL2TP=m
-+CONFIG_PPP_ASYNC=m
-+CONFIG_PPP_SYNC_TTY=m
-+CONFIG_SLIP=m
-+CONFIG_SLIP_COMPRESSED=y
-+CONFIG_SLIP_SMART=y
-+CONFIG_USB_CATC=m
-+CONFIG_USB_KAWETH=m
-+CONFIG_USB_PEGASUS=m
-+CONFIG_USB_RTL8150=m
-+CONFIG_USB_RTL8152=y
-+CONFIG_USB_LAN78XX=y
-+CONFIG_USB_USBNET=y
-+CONFIG_USB_NET_AX88179_178A=m
-+CONFIG_USB_NET_CDCETHER=m
-+CONFIG_USB_NET_CDC_EEM=m
-+CONFIG_USB_NET_CDC_NCM=m
-+CONFIG_USB_NET_HUAWEI_CDC_NCM=m
-+CONFIG_USB_NET_CDC_MBIM=m
-+CONFIG_USB_NET_DM9601=m
-+CONFIG_USB_NET_SR9700=m
-+CONFIG_USB_NET_SR9800=m
-+CONFIG_USB_NET_SMSC75XX=m
-+CONFIG_USB_NET_SMSC95XX=y
-+CONFIG_USB_NET_GL620A=m
-+CONFIG_USB_NET_NET1080=m
-+CONFIG_USB_NET_PLUSB=m
-+CONFIG_USB_NET_MCS7830=m
-+CONFIG_USB_NET_CDC_SUBSET=m
-+CONFIG_USB_ALI_M5632=y
-+CONFIG_USB_AN2720=y
-+CONFIG_USB_EPSON2888=y
-+CONFIG_USB_KC2190=y
-+CONFIG_USB_NET_ZAURUS=m
-+CONFIG_USB_NET_CX82310_ETH=m
-+CONFIG_USB_NET_KALMIA=m
-+CONFIG_USB_NET_QMI_WWAN=m
-+CONFIG_USB_HSO=m
-+CONFIG_USB_NET_INT51X1=m
-+CONFIG_USB_IPHETH=m
-+CONFIG_USB_SIERRA_NET=m
-+CONFIG_USB_VL600=m
-+CONFIG_ATH9K=m
-+CONFIG_ATH9K_HTC=m
-+CONFIG_CARL9170=m
-+CONFIG_ATH6KL=m
-+CONFIG_ATH6KL_USB=m
-+CONFIG_AR5523=m
-+CONFIG_AT76C50X_USB=m
-+CONFIG_B43=m
-+# CONFIG_B43_PHY_N is not set
-+CONFIG_B43LEGACY=m
-+CONFIG_BRCMFMAC=m
-+CONFIG_BRCMFMAC_USB=y
-+CONFIG_BRCMDBG=y
-+CONFIG_HOSTAP=m
-+CONFIG_P54_COMMON=m
-+CONFIG_P54_USB=m
-+CONFIG_LIBERTAS=m
-+CONFIG_LIBERTAS_USB=m
-+CONFIG_LIBERTAS_SDIO=m
-+CONFIG_LIBERTAS_THINFIRM=m
-+CONFIG_LIBERTAS_THINFIRM_USB=m
-+CONFIG_MWIFIEX=m
-+CONFIG_MWIFIEX_SDIO=m
-+CONFIG_MT7601U=m
-+CONFIG_RT2X00=m
-+CONFIG_RT2500USB=m
-+CONFIG_RT73USB=m
-+CONFIG_RT2800USB=m
-+CONFIG_RT2800USB_RT3573=y
-+CONFIG_RT2800USB_RT53XX=y
-+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
-+CONFIG_USB_NET_RNDIS_WLAN=m
-+CONFIG_WIMAX_I2400M_USB=m
-+CONFIG_IEEE802154_AT86RF230=m
-+CONFIG_IEEE802154_MRF24J40=m
-+CONFIG_IEEE802154_CC2520=m
-+CONFIG_INPUT_MOUSEDEV=y
-+CONFIG_INPUT_JOYDEV=m
-+CONFIG_INPUT_EVDEV=m
-+# CONFIG_KEYBOARD_ATKBD is not set
-+CONFIG_KEYBOARD_GPIO=m
-+CONFIG_KEYBOARD_MATRIX=m
-+# CONFIG_INPUT_MOUSE is not set
-+CONFIG_INPUT_JOYSTICK=y
-+CONFIG_JOYSTICK_IFORCE=m
-+CONFIG_JOYSTICK_IFORCE_USB=y
-+CONFIG_JOYSTICK_XPAD=m
-+CONFIG_JOYSTICK_XPAD_FF=y
-+CONFIG_JOYSTICK_XPAD_LEDS=y
-+CONFIG_JOYSTICK_PSXPAD_SPI=m
-+CONFIG_JOYSTICK_PSXPAD_SPI_FF=y
-+CONFIG_JOYSTICK_RPISENSE=m
-+CONFIG_INPUT_TOUCHSCREEN=y
-+CONFIG_TOUCHSCREEN_ADS7846=m
-+CONFIG_TOUCHSCREEN_EGALAX=m
-+CONFIG_TOUCHSCREEN_EXC3000=m
-+CONFIG_TOUCHSCREEN_GOODIX=m
-+CONFIG_TOUCHSCREEN_EDT_FT5X06=m
-+CONFIG_TOUCHSCREEN_RPI_FT5406=m
-+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
-+CONFIG_TOUCHSCREEN_STMPE=m
-+CONFIG_INPUT_MISC=y
-+CONFIG_INPUT_AD714X=m
-+CONFIG_INPUT_ATI_REMOTE2=m
-+CONFIG_INPUT_KEYSPAN_REMOTE=m
-+CONFIG_INPUT_POWERMATE=m
-+CONFIG_INPUT_YEALINK=m
-+CONFIG_INPUT_CM109=m
-+CONFIG_INPUT_UINPUT=m
-+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
-+CONFIG_INPUT_ADXL34X=m
-+CONFIG_INPUT_CMA3000=m
-+CONFIG_SERIO=m
-+CONFIG_SERIO_RAW=m
-+CONFIG_GAMEPORT=m
-+CONFIG_GAMEPORT_NS558=m
-+CONFIG_GAMEPORT_L4=m
-+CONFIG_BRCM_CHAR_DRIVERS=y
-+CONFIG_BCM_VCIO=y
-+CONFIG_BCM_VC_SM=y
-+CONFIG_BCM2835_DEVGPIOMEM=y
-+CONFIG_ARGON_MEM=m
-+# CONFIG_LEGACY_PTYS is not set
-+CONFIG_SERIAL_8250=y
-+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
-+CONFIG_SERIAL_8250_CONSOLE=y
-+# CONFIG_SERIAL_8250_DMA is not set
-+CONFIG_SERIAL_8250_NR_UARTS=1
-+CONFIG_SERIAL_8250_RUNTIME_UARTS=0
-+CONFIG_SERIAL_8250_EXTENDED=y
-+CONFIG_SERIAL_8250_SHARE_IRQ=y
-+CONFIG_SERIAL_8250_BCM2835AUX=y
-+CONFIG_SERIAL_OF_PLATFORM=y
-+CONFIG_SERIAL_AMBA_PL011=y
-+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-+CONFIG_SERIAL_SC16IS7XX=m
-+CONFIG_SERIAL_SC16IS7XX_SPI=y
-+CONFIG_SERIAL_DEV_BUS=m
-+CONFIG_TTY_PRINTK=y
-+CONFIG_HW_RANDOM=y
-+CONFIG_RAW_DRIVER=y
-+CONFIG_I2C=y
-+CONFIG_I2C_CHARDEV=m
-+CONFIG_I2C_BCM2708=m
-+CONFIG_I2C_BCM2835=m
-+CONFIG_I2C_GPIO=m
-+CONFIG_I2C_ROBOTFUZZ_OSIF=m
-+CONFIG_I2C_TINY_USB=m
-+CONFIG_SPI=y
-+CONFIG_SPI_BCM2835=m
-+CONFIG_SPI_BCM2835AUX=m
-+CONFIG_SPI_SPIDEV=m
-+CONFIG_SPI_SLAVE=y
-+CONFIG_PPS=m
-+CONFIG_PPS_CLIENT_LDISC=m
-+CONFIG_PPS_CLIENT_GPIO=m
-+CONFIG_PINCTRL_MCP23S08=m
-+CONFIG_GPIO_BCM_VIRT=y
-+CONFIG_GPIO_MOCKUP=m
-+CONFIG_GPIO_PCF857X=m
-+CONFIG_GPIO_ARIZONA=m
-+CONFIG_GPIO_STMPE=y
-+CONFIG_W1=m
-+CONFIG_W1_MASTER_DS2490=m
-+CONFIG_W1_MASTER_DS2482=m
-+CONFIG_W1_MASTER_DS1WM=m
-+CONFIG_W1_MASTER_GPIO=m
-+CONFIG_W1_SLAVE_THERM=m
-+CONFIG_W1_SLAVE_SMEM=m
-+CONFIG_W1_SLAVE_DS2408=m
-+CONFIG_W1_SLAVE_DS2413=m
-+CONFIG_W1_SLAVE_DS2406=m
-+CONFIG_W1_SLAVE_DS2423=m
-+CONFIG_W1_SLAVE_DS2431=m
-+CONFIG_W1_SLAVE_DS2433=m
-+CONFIG_W1_SLAVE_DS2438=m
-+CONFIG_W1_SLAVE_DS2780=m
-+CONFIG_W1_SLAVE_DS2781=m
-+CONFIG_W1_SLAVE_DS28E04=m
-+CONFIG_POWER_RESET=y
-+CONFIG_POWER_RESET_GPIO=y
-+CONFIG_BATTERY_DS2760=m
-+CONFIG_BATTERY_GAUGE_LTC2941=m
-+CONFIG_HWMON=m
-+CONFIG_SENSORS_DS1621=m
-+CONFIG_SENSORS_JC42=m
-+CONFIG_SENSORS_LM75=m
-+CONFIG_SENSORS_RPI_POE_FAN=m
-+CONFIG_SENSORS_SHT21=m
-+CONFIG_SENSORS_SHT3x=m
-+CONFIG_SENSORS_SHTC1=m
-+CONFIG_SENSORS_ADS1015=m
-+CONFIG_SENSORS_INA2XX=m
-+CONFIG_SENSORS_TMP102=m
-+CONFIG_THERMAL=y
-+CONFIG_BCM2835_THERMAL=y
-+CONFIG_BRCMSTB_THERMAL=y
-+CONFIG_WATCHDOG=y
-+CONFIG_GPIO_WATCHDOG=m
-+CONFIG_BCM2835_WDT=y
-+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_LDO1=m
-+CONFIG_REGULATOR_ARIZONA_MICSUPP=m
-+CONFIG_REGULATOR_GPIO=y
-+CONFIG_MEDIA_SUPPORT=m
-+CONFIG_MEDIA_CAMERA_SUPPORT=y
-+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
-+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
-+CONFIG_MEDIA_RADIO_SUPPORT=y
-+CONFIG_MEDIA_CONTROLLER=y
-+CONFIG_VIDEO_V4L2_SUBDEV_API=y
-+CONFIG_MEDIA_USB_SUPPORT=y
-+CONFIG_USB_VIDEO_CLASS=m
-+CONFIG_USB_M5602=m
-+CONFIG_USB_STV06XX=m
-+CONFIG_USB_GL860=m
-+CONFIG_USB_GSPCA_BENQ=m
-+CONFIG_USB_GSPCA_CONEX=m
-+CONFIG_USB_GSPCA_CPIA1=m
-+CONFIG_USB_GSPCA_DTCS033=m
-+CONFIG_USB_GSPCA_ETOMS=m
-+CONFIG_USB_GSPCA_FINEPIX=m
-+CONFIG_USB_GSPCA_JEILINJ=m
-+CONFIG_USB_GSPCA_JL2005BCD=m
-+CONFIG_USB_GSPCA_KINECT=m
-+CONFIG_USB_GSPCA_KONICA=m
-+CONFIG_USB_GSPCA_MARS=m
-+CONFIG_USB_GSPCA_MR97310A=m
-+CONFIG_USB_GSPCA_NW80X=m
-+CONFIG_USB_GSPCA_OV519=m
-+CONFIG_USB_GSPCA_OV534=m
-+CONFIG_USB_GSPCA_OV534_9=m
-+CONFIG_USB_GSPCA_PAC207=m
-+CONFIG_USB_GSPCA_PAC7302=m
-+CONFIG_USB_GSPCA_PAC7311=m
-+CONFIG_USB_GSPCA_SE401=m
-+CONFIG_USB_GSPCA_SN9C2028=m
-+CONFIG_USB_GSPCA_SN9C20X=m
-+CONFIG_USB_GSPCA_SONIXB=m
-+CONFIG_USB_GSPCA_SONIXJ=m
-+CONFIG_USB_GSPCA_SPCA500=m
-+CONFIG_USB_GSPCA_SPCA501=m
-+CONFIG_USB_GSPCA_SPCA505=m
-+CONFIG_USB_GSPCA_SPCA506=m
-+CONFIG_USB_GSPCA_SPCA508=m
-+CONFIG_USB_GSPCA_SPCA561=m
-+CONFIG_USB_GSPCA_SPCA1528=m
-+CONFIG_USB_GSPCA_SQ905=m
-+CONFIG_USB_GSPCA_SQ905C=m
-+CONFIG_USB_GSPCA_SQ930X=m
-+CONFIG_USB_GSPCA_STK014=m
-+CONFIG_USB_GSPCA_STK1135=m
-+CONFIG_USB_GSPCA_STV0680=m
-+CONFIG_USB_GSPCA_SUNPLUS=m
-+CONFIG_USB_GSPCA_T613=m
-+CONFIG_USB_GSPCA_TOPRO=m
-+CONFIG_USB_GSPCA_TV8532=m
-+CONFIG_USB_GSPCA_VC032X=m
-+CONFIG_USB_GSPCA_VICAM=m
-+CONFIG_USB_GSPCA_XIRLINK_CIT=m
-+CONFIG_USB_GSPCA_ZC3XX=m
-+CONFIG_USB_PWC=m
-+CONFIG_VIDEO_CPIA2=m
-+CONFIG_USB_ZR364XX=m
-+CONFIG_USB_STKWEBCAM=m
-+CONFIG_USB_S2255=m
-+CONFIG_VIDEO_USBTV=m
-+CONFIG_VIDEO_PVRUSB2=m
-+CONFIG_VIDEO_HDPVR=m
-+CONFIG_VIDEO_USBVISION=m
-+CONFIG_VIDEO_STK1160_COMMON=m
-+CONFIG_VIDEO_GO7007=m
-+CONFIG_VIDEO_GO7007_USB=m
-+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m
-+CONFIG_VIDEO_AU0828=m
-+CONFIG_DVB_USB_V2=m
-+CONFIG_DVB_USB_AF9035=m
-+CONFIG_DVB_USB_ANYSEE=m
-+CONFIG_DVB_USB_AU6610=m
-+CONFIG_DVB_USB_AZ6007=m
-+CONFIG_DVB_USB_CE6230=m
-+CONFIG_DVB_USB_EC168=m
-+CONFIG_DVB_USB_GL861=m
-+CONFIG_DVB_USB_MXL111SF=m
-+CONFIG_DVB_USB_DVBSKY=m
-+CONFIG_SMS_USB_DRV=m
-+CONFIG_DVB_B2C2_FLEXCOP_USB=m
-+CONFIG_DVB_AS102=m
-+CONFIG_VIDEO_EM28XX=m
-+CONFIG_VIDEO_EM28XX_V4L2=m
-+CONFIG_VIDEO_EM28XX_ALSA=m
-+CONFIG_VIDEO_EM28XX_DVB=m
-+CONFIG_V4L_PLATFORM_DRIVERS=y
-+CONFIG_VIDEO_BCM2835_UNICAM=m
-+CONFIG_RADIO_SI470X=m
-+CONFIG_USB_SI470X=m
-+CONFIG_I2C_SI470X=m
-+CONFIG_RADIO_SI4713=m
-+CONFIG_I2C_SI4713=m
-+CONFIG_USB_MR800=m
-+CONFIG_USB_DSBR=m
-+CONFIG_RADIO_SHARK=m
-+CONFIG_RADIO_SHARK2=m
-+CONFIG_USB_KEENE=m
-+CONFIG_USB_MA901=m
-+CONFIG_RADIO_TEA5764=m
-+CONFIG_RADIO_SAA7706H=m
-+CONFIG_RADIO_TEF6862=m
-+CONFIG_RADIO_WL1273=m
-+CONFIG_RADIO_WL128X=m
-+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
-+CONFIG_VIDEO_UDA1342=m
-+CONFIG_VIDEO_SONY_BTF_MPX=m
-+CONFIG_VIDEO_ADV7180=m
-+CONFIG_VIDEO_TC358743=m
-+CONFIG_VIDEO_TVP5150=m
-+CONFIG_VIDEO_TW2804=m
-+CONFIG_VIDEO_TW9903=m
-+CONFIG_VIDEO_TW9906=m
-+CONFIG_VIDEO_OV5647=m
-+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_V3D=m
-+CONFIG_DRM_VC4=m
-+CONFIG_DRM_TINYDRM=m
-+CONFIG_TINYDRM_MI0283QT=m
-+CONFIG_TINYDRM_REPAPER=m
-+CONFIG_FB=y
-+CONFIG_FB_BCM2708=y
-+CONFIG_FB_UDL=m
-+CONFIG_FB_SIMPLE=y
-+CONFIG_FB_SSD1307=m
-+CONFIG_FB_RPISENSE=m
-+# CONFIG_BACKLIGHT_GENERIC is not set
-+CONFIG_BACKLIGHT_RPI=m
-+CONFIG_BACKLIGHT_GPIO=m
-+CONFIG_FRAMEBUFFER_CONSOLE=y
-+CONFIG_LOGO=y
-+# CONFIG_LOGO_LINUX_MONO is not set
-+# CONFIG_LOGO_LINUX_VGA16 is not set
-+CONFIG_SOUND=y
-+CONFIG_SND=m
-+CONFIG_SND_HRTIMER=m
-+CONFIG_SND_SEQUENCER=m
-+CONFIG_SND_SEQ_DUMMY=m
-+CONFIG_SND_DUMMY=m
-+CONFIG_SND_ALOOP=m
-+CONFIG_SND_VIRMIDI=m
-+CONFIG_SND_MTPAV=m
-+CONFIG_SND_SERIAL_U16550=m
-+CONFIG_SND_MPU401=m
-+CONFIG_SND_USB_AUDIO=m
-+CONFIG_SND_USB_UA101=m
-+CONFIG_SND_USB_CAIAQ=m
-+CONFIG_SND_USB_CAIAQ_INPUT=y
-+CONFIG_SND_USB_6FIRE=m
-+CONFIG_SND_USB_HIFACE=m
-+CONFIG_SND_SOC=m
-+CONFIG_SND_BCM2835_SOC_I2S=m
-+CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
-+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
-+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
-+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=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
-+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
-+CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC=m
-+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
-+CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=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_ALLO_PIANO_DAC_PLUS=m
-+CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC=m
-+CONFIG_SND_BCM2708_SOC_ALLO_DIGIONE=m
-+CONFIG_SND_BCM2708_SOC_ALLO_KATANA_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_CS4271_I2C=m
-+CONFIG_SND_SOC_SPDIF=m
-+CONFIG_SND_SOC_WM8804_I2C=m
-+CONFIG_SND_SIMPLE_CARD=m
-+CONFIG_HID_BATTERY_STRENGTH=y
-+CONFIG_HIDRAW=y
-+CONFIG_UHID=m
-+CONFIG_HID_A4TECH=m
-+CONFIG_HID_ACRUX=m
-+CONFIG_HID_APPLE=m
-+CONFIG_HID_ASUS=m
-+CONFIG_HID_BELKIN=m
-+CONFIG_HID_BETOP_FF=m
-+CONFIG_HID_CHERRY=m
-+CONFIG_HID_CHICONY=m
-+CONFIG_HID_CYPRESS=m
-+CONFIG_HID_DRAGONRISE=m
-+CONFIG_HID_EMS_FF=m
-+CONFIG_HID_ELECOM=m
-+CONFIG_HID_ELO=m
-+CONFIG_HID_EZKEY=m
-+CONFIG_HID_GEMBIRD=m
-+CONFIG_HID_HOLTEK=m
-+CONFIG_HID_KEYTOUCH=m
-+CONFIG_HID_KYE=m
-+CONFIG_HID_UCLOGIC=m
-+CONFIG_HID_WALTOP=m
-+CONFIG_HID_GYRATION=m
-+CONFIG_HID_TWINHAN=m
-+CONFIG_HID_KENSINGTON=m
-+CONFIG_HID_LCPOWER=m
-+CONFIG_HID_LOGITECH=m
-+CONFIG_HID_LOGITECH_DJ=m
-+CONFIG_LOGITECH_FF=y
-+CONFIG_LOGIRUMBLEPAD2_FF=y
-+CONFIG_LOGIG940_FF=y
-+CONFIG_HID_MAGICMOUSE=m
-+CONFIG_HID_MICROSOFT=m
-+CONFIG_HID_MONTEREY=m
-+CONFIG_HID_MULTITOUCH=m
-+CONFIG_HID_NTRIG=m
-+CONFIG_HID_ORTEK=m
-+CONFIG_HID_PANTHERLORD=m
-+CONFIG_HID_PETALYNX=m
-+CONFIG_HID_PICOLCD=m
-+CONFIG_HID_ROCCAT=m
-+CONFIG_HID_SAMSUNG=m
-+CONFIG_HID_SONY=m
-+CONFIG_SONY_FF=y
-+CONFIG_HID_SPEEDLINK=m
-+CONFIG_HID_SUNPLUS=m
-+CONFIG_HID_GREENASIA=m
-+CONFIG_HID_SMARTJOYPLUS=m
-+CONFIG_HID_TOPSEED=m
-+CONFIG_HID_THINGM=m
-+CONFIG_HID_THRUSTMASTER=m
-+CONFIG_HID_WACOM=m
-+CONFIG_HID_WIIMOTE=m
-+CONFIG_HID_XINMO=m
-+CONFIG_HID_ZEROPLUS=m
-+CONFIG_HID_ZYDACRON=m
-+CONFIG_HID_PID=y
-+CONFIG_USB_HIDDEV=y
-+CONFIG_USB=y
-+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-+CONFIG_USB_MON=m
-+CONFIG_USB_XHCI_HCD=y
-+CONFIG_USB_DWCOTG=y
-+CONFIG_USB_PRINTER=m
-+CONFIG_USB_STORAGE=y
-+CONFIG_USB_STORAGE_REALTEK=m
-+CONFIG_USB_STORAGE_DATAFAB=m
-+CONFIG_USB_STORAGE_FREECOM=m
-+CONFIG_USB_STORAGE_ISD200=m
-+CONFIG_USB_STORAGE_USBAT=m
-+CONFIG_USB_STORAGE_SDDR09=m
-+CONFIG_USB_STORAGE_SDDR55=m
-+CONFIG_USB_STORAGE_JUMPSHOT=m
-+CONFIG_USB_STORAGE_ALAUDA=m
-+CONFIG_USB_STORAGE_ONETOUCH=m
-+CONFIG_USB_STORAGE_KARMA=m
-+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
-+CONFIG_USB_STORAGE_ENE_UB6250=m
-+CONFIG_USB_UAS=y
-+CONFIG_USB_MDC800=m
-+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
-+CONFIG_USB_SERIAL_ARK3116=m
-+CONFIG_USB_SERIAL_BELKIN=m
-+CONFIG_USB_SERIAL_CH341=m
-+CONFIG_USB_SERIAL_WHITEHEAT=m
-+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
-+CONFIG_USB_SERIAL_CP210X=m
-+CONFIG_USB_SERIAL_CYPRESS_M8=m
-+CONFIG_USB_SERIAL_EMPEG=m
-+CONFIG_USB_SERIAL_FTDI_SIO=m
-+CONFIG_USB_SERIAL_VISOR=m
-+CONFIG_USB_SERIAL_IPAQ=m
-+CONFIG_USB_SERIAL_IR=m
-+CONFIG_USB_SERIAL_EDGEPORT=m
-+CONFIG_USB_SERIAL_EDGEPORT_TI=m
-+CONFIG_USB_SERIAL_F81232=m
-+CONFIG_USB_SERIAL_GARMIN=m
-+CONFIG_USB_SERIAL_IPW=m
-+CONFIG_USB_SERIAL_IUU=m
-+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
-+CONFIG_USB_SERIAL_KEYSPAN=m
-+CONFIG_USB_SERIAL_KLSI=m
-+CONFIG_USB_SERIAL_KOBIL_SCT=m
-+CONFIG_USB_SERIAL_MCT_U232=m
-+CONFIG_USB_SERIAL_METRO=m
-+CONFIG_USB_SERIAL_MOS7720=m
-+CONFIG_USB_SERIAL_MOS7840=m
-+CONFIG_USB_SERIAL_NAVMAN=m
-+CONFIG_USB_SERIAL_PL2303=m
-+CONFIG_USB_SERIAL_OTI6858=m
-+CONFIG_USB_SERIAL_QCAUX=m
-+CONFIG_USB_SERIAL_QUALCOMM=m
-+CONFIG_USB_SERIAL_SPCP8X5=m
-+CONFIG_USB_SERIAL_SAFE=m
-+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
-+CONFIG_USB_SERIAL_SYMBOL=m
-+CONFIG_USB_SERIAL_TI=m
-+CONFIG_USB_SERIAL_CYBERJACK=m
-+CONFIG_USB_SERIAL_XIRCOM=m
-+CONFIG_USB_SERIAL_OPTION=m
-+CONFIG_USB_SERIAL_OMNINET=m
-+CONFIG_USB_SERIAL_OPTICON=m
-+CONFIG_USB_SERIAL_XSENS_MT=m
-+CONFIG_USB_SERIAL_WISHBONE=m
-+CONFIG_USB_SERIAL_SSU100=m
-+CONFIG_USB_SERIAL_QT2=m
-+CONFIG_USB_SERIAL_DEBUG=m
-+CONFIG_USB_EMI62=m
-+CONFIG_USB_EMI26=m
-+CONFIG_USB_ADUTUX=m
-+CONFIG_USB_SEVSEG=m
-+CONFIG_USB_RIO500=m
-+CONFIG_USB_LEGOTOWER=m
-+CONFIG_USB_LCD=m
-+CONFIG_USB_CYPRESS_CY7C63=m
-+CONFIG_USB_CYTHERM=m
-+CONFIG_USB_IDMOUSE=m
-+CONFIG_USB_FTDI_ELAN=m
-+CONFIG_USB_APPLEDISPLAY=m
-+CONFIG_USB_LD=m
-+CONFIG_USB_TRANCEVIBRATOR=m
-+CONFIG_USB_IOWARRIOR=m
-+CONFIG_USB_TEST=m
-+CONFIG_USB_ISIGHTFW=m
-+CONFIG_USB_YUREX=m
-+CONFIG_USB_ATM=m
-+CONFIG_USB_SPEEDTOUCH=m
-+CONFIG_USB_CXACRU=m
-+CONFIG_USB_UEAGLEATM=m
-+CONFIG_USB_XUSBATM=m
-+CONFIG_USB_GADGET=m
-+CONFIG_USB_CONFIGFS=m
-+CONFIG_USB_CONFIGFS_SERIAL=y
-+CONFIG_USB_CONFIGFS_ACM=y
-+CONFIG_USB_CONFIGFS_OBEX=y
-+CONFIG_USB_CONFIGFS_NCM=y
-+CONFIG_USB_CONFIGFS_ECM=y
-+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
-+CONFIG_USB_CONFIGFS_RNDIS=y
-+CONFIG_USB_CONFIGFS_EEM=y
-+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
-+CONFIG_USB_CONFIGFS_F_LB_SS=y
-+CONFIG_USB_CONFIGFS_F_FS=y
-+CONFIG_USB_CONFIGFS_F_UAC1=y
-+CONFIG_USB_CONFIGFS_F_UAC2=y
-+CONFIG_USB_CONFIGFS_F_MIDI=y
-+CONFIG_USB_CONFIGFS_F_HID=y
-+CONFIG_USB_CONFIGFS_F_UVC=y
-+CONFIG_USB_CONFIGFS_F_PRINTER=y
-+CONFIG_USB_ZERO=m
-+CONFIG_USB_AUDIO=m
-+CONFIG_USB_ETH=m
-+CONFIG_USB_GADGETFS=m
-+CONFIG_USB_MASS_STORAGE=m
-+CONFIG_USB_G_SERIAL=m
-+CONFIG_USB_MIDI_GADGET=m
-+CONFIG_USB_G_PRINTER=m
-+CONFIG_USB_CDC_COMPOSITE=m
-+CONFIG_USB_G_ACM_MS=m
-+CONFIG_USB_G_MULTI=m
-+CONFIG_USB_G_HID=m
-+CONFIG_USB_G_WEBCAM=m
-+CONFIG_MMC=y
-+CONFIG_MMC_BLOCK_MINORS=32
-+CONFIG_MMC_BCM2835_MMC=y
-+CONFIG_MMC_BCM2835_DMA=y
-+CONFIG_MMC_BCM2835_SDHOST=y
-+CONFIG_MMC_SDHCI=y
-+CONFIG_MMC_SDHCI_PLTFM=y
-+CONFIG_MMC_SDHCI_IPROC=y
-+CONFIG_MMC_SPI=m
-+CONFIG_LEDS_CLASS=y
-+CONFIG_LEDS_GPIO=y
-+CONFIG_LEDS_TRIGGER_TIMER=y
-+CONFIG_LEDS_TRIGGER_ONESHOT=y
-+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
-+CONFIG_LEDS_TRIGGER_CPU=y
-+CONFIG_LEDS_TRIGGER_GPIO=y
-+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-+CONFIG_LEDS_TRIGGER_TRANSIENT=m
-+CONFIG_LEDS_TRIGGER_CAMERA=m
-+CONFIG_LEDS_TRIGGER_INPUT=y
-+CONFIG_LEDS_TRIGGER_PANIC=y
-+CONFIG_RTC_CLASS=y
-+# CONFIG_RTC_HCTOSYS is not set
-+CONFIG_RTC_DRV_ABX80X=m
-+CONFIG_RTC_DRV_DS1307=m
-+CONFIG_RTC_DRV_DS1374=m
-+CONFIG_RTC_DRV_DS1672=m
-+CONFIG_RTC_DRV_MAX6900=m
-+CONFIG_RTC_DRV_RS5C372=m
-+CONFIG_RTC_DRV_ISL1208=m
-+CONFIG_RTC_DRV_ISL12022=m
-+CONFIG_RTC_DRV_X1205=m
-+CONFIG_RTC_DRV_PCF8523=m
-+CONFIG_RTC_DRV_PCF8563=m
-+CONFIG_RTC_DRV_PCF8583=m
-+CONFIG_RTC_DRV_M41T80=m
-+CONFIG_RTC_DRV_BQ32K=m
-+CONFIG_RTC_DRV_S35390A=m
-+CONFIG_RTC_DRV_FM3130=m
-+CONFIG_RTC_DRV_RX8581=m
-+CONFIG_RTC_DRV_RX8025=m
-+CONFIG_RTC_DRV_EM3027=m
-+CONFIG_RTC_DRV_M41T93=m
-+CONFIG_RTC_DRV_M41T94=m
-+CONFIG_RTC_DRV_DS1302=m
-+CONFIG_RTC_DRV_DS1305=m
-+CONFIG_RTC_DRV_DS1390=m
-+CONFIG_RTC_DRV_R9701=m
-+CONFIG_RTC_DRV_RX4581=m
-+CONFIG_RTC_DRV_RS5C348=m
-+CONFIG_RTC_DRV_MAX6902=m
-+CONFIG_RTC_DRV_PCF2123=m
-+CONFIG_RTC_DRV_DS3232=m
-+CONFIG_RTC_DRV_PCF2127=m
-+CONFIG_RTC_DRV_RV3029C2=m
-+CONFIG_DMADEVICES=y
-+CONFIG_DMA_BCM2835=y
-+CONFIG_DMA_BCM2708=y
-+CONFIG_UIO=m
-+CONFIG_UIO_PDRV_GENIRQ=m
-+CONFIG_STAGING=y
-+CONFIG_PRISM2_USB=m
-+CONFIG_R8712U=m
-+CONFIG_R8188EU=m
-+CONFIG_VT6656=m
-+CONFIG_SPEAKUP=m
-+CONFIG_SPEAKUP_SYNTH_SOFT=m
-+CONFIG_STAGING_MEDIA=y
-+CONFIG_FB_TFT=m
-+CONFIG_FB_TFT_AGM1264K_FL=m
-+CONFIG_FB_TFT_BD663474=m
-+CONFIG_FB_TFT_HX8340BN=m
-+CONFIG_FB_TFT_HX8347D=m
-+CONFIG_FB_TFT_HX8353D=m
-+CONFIG_FB_TFT_HX8357D=m
-+CONFIG_FB_TFT_ILI9163=m
-+CONFIG_FB_TFT_ILI9320=m
-+CONFIG_FB_TFT_ILI9325=m
-+CONFIG_FB_TFT_ILI9340=m
-+CONFIG_FB_TFT_ILI9341=m
-+CONFIG_FB_TFT_ILI9481=m
-+CONFIG_FB_TFT_ILI9486=m
-+CONFIG_FB_TFT_PCD8544=m
-+CONFIG_FB_TFT_RA8875=m
-+CONFIG_FB_TFT_S6D02A1=m
-+CONFIG_FB_TFT_S6D1121=m
-+CONFIG_FB_TFT_SSD1289=m
-+CONFIG_FB_TFT_SSD1306=m
-+CONFIG_FB_TFT_SSD1331=m
-+CONFIG_FB_TFT_SSD1351=m
-+CONFIG_FB_TFT_ST7735R=m
-+CONFIG_FB_TFT_ST7789V=m
-+CONFIG_FB_TFT_TINYLCD=m
-+CONFIG_FB_TFT_TLS8204=m
-+CONFIG_FB_TFT_UC1701=m
-+CONFIG_FB_TFT_UPD161704=m
-+CONFIG_FB_TFT_WATTEROTT=m
-+CONFIG_FB_FLEX=m
-+CONFIG_FB_TFT_FBTFT_DEVICE=m
-+CONFIG_BCM2835_VCHIQ=y
-+CONFIG_SND_BCM2835=m
-+CONFIG_VIDEO_BCM2835=m
-+CONFIG_VIDEO_CODEC_BCM2835=m
-+CONFIG_MAILBOX=y
-+CONFIG_BCM2835_MBOX=y
-+# CONFIG_IOMMU_SUPPORT is not set
-+CONFIG_BCM2835_POWER=y
-+CONFIG_RASPBERRYPI_POWER=y
-+CONFIG_EXTCON=m
-+CONFIG_EXTCON_ARIZONA=m
-+CONFIG_IIO=m
-+CONFIG_IIO_BUFFER_CB=m
-+CONFIG_MCP320X=m
-+CONFIG_MCP3422=m
-+CONFIG_DHT11=m
-+CONFIG_HDC100X=m
-+CONFIG_HTU21=m
-+CONFIG_TSL4531=m
-+CONFIG_VEML6070=m
-+CONFIG_BMP280=m
-+CONFIG_PWM_BCM2835=m
-+CONFIG_PWM_PCA9685=m
-+CONFIG_GENERIC_PHY=y
-+CONFIG_RPI_AXIPERF=m
-+CONFIG_EXT4_FS=y
-+CONFIG_EXT4_FS_POSIX_ACL=y
-+CONFIG_EXT4_FS_SECURITY=y
-+CONFIG_REISERFS_FS=m
-+CONFIG_REISERFS_FS_XATTR=y
-+CONFIG_REISERFS_FS_POSIX_ACL=y
-+CONFIG_REISERFS_FS_SECURITY=y
-+CONFIG_JFS_FS=m
-+CONFIG_JFS_POSIX_ACL=y
-+CONFIG_JFS_SECURITY=y
-+CONFIG_JFS_STATISTICS=y
-+CONFIG_XFS_FS=m
-+CONFIG_XFS_QUOTA=y
-+CONFIG_XFS_POSIX_ACL=y
-+CONFIG_XFS_RT=y
-+CONFIG_GFS2_FS=m
-+CONFIG_OCFS2_FS=m
-+CONFIG_BTRFS_FS=m
-+CONFIG_BTRFS_FS_POSIX_ACL=y
-+CONFIG_NILFS2_FS=m
-+CONFIG_F2FS_FS=y
-+CONFIG_FANOTIFY=y
-+CONFIG_QFMT_V1=m
-+CONFIG_QFMT_V2=m
-+CONFIG_AUTOFS4_FS=y
-+CONFIG_FUSE_FS=m
-+CONFIG_CUSE=m
-+CONFIG_OVERLAY_FS=m
-+CONFIG_FSCACHE=y
-+CONFIG_FSCACHE_STATS=y
-+CONFIG_FSCACHE_HISTOGRAM=y
-+CONFIG_CACHEFILES=y
-+CONFIG_ISO9660_FS=m
-+CONFIG_JOLIET=y
-+CONFIG_ZISOFS=y
-+CONFIG_UDF_FS=m
-+CONFIG_MSDOS_FS=y
-+CONFIG_VFAT_FS=y
-+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
-+CONFIG_NTFS_FS=m
-+CONFIG_NTFS_RW=y
-+CONFIG_TMPFS=y
-+CONFIG_TMPFS_POSIX_ACL=y
-+CONFIG_ECRYPT_FS=m
-+CONFIG_HFS_FS=m
-+CONFIG_HFSPLUS_FS=m
-+CONFIG_JFFS2_FS=m
-+CONFIG_JFFS2_SUMMARY=y
-+CONFIG_UBIFS_FS=m
-+CONFIG_SQUASHFS=m
-+CONFIG_SQUASHFS_XATTR=y
-+CONFIG_SQUASHFS_LZO=y
-+CONFIG_SQUASHFS_XZ=y
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3_ACL=y
-+CONFIG_NFS_V4=y
-+CONFIG_NFS_SWAP=y
-+CONFIG_NFS_V4_1=y
-+CONFIG_ROOT_NFS=y
-+CONFIG_NFS_FSCACHE=y
-+CONFIG_NFSD=m
-+CONFIG_NFSD_V3_ACL=y
-+CONFIG_NFSD_V4=y
-+CONFIG_CIFS=m
-+CONFIG_CIFS_WEAK_PW_HASH=y
-+CONFIG_CIFS_UPCALL=y
-+CONFIG_CIFS_XATTR=y
-+CONFIG_CIFS_POSIX=y
-+CONFIG_CIFS_ACL=y
-+CONFIG_CIFS_DFS_UPCALL=y
-+CONFIG_CIFS_FSCACHE=y
-+CONFIG_9P_FS=m
-+CONFIG_9P_FS_POSIX_ACL=y
-+CONFIG_NLS_DEFAULT="utf8"
-+CONFIG_NLS_CODEPAGE_437=y
-+CONFIG_NLS_CODEPAGE_737=m
-+CONFIG_NLS_CODEPAGE_775=m
-+CONFIG_NLS_CODEPAGE_850=m
-+CONFIG_NLS_CODEPAGE_852=m
-+CONFIG_NLS_CODEPAGE_855=m
-+CONFIG_NLS_CODEPAGE_857=m
-+CONFIG_NLS_CODEPAGE_860=m
-+CONFIG_NLS_CODEPAGE_861=m
-+CONFIG_NLS_CODEPAGE_862=m
-+CONFIG_NLS_CODEPAGE_863=m
-+CONFIG_NLS_CODEPAGE_864=m
-+CONFIG_NLS_CODEPAGE_865=m
-+CONFIG_NLS_CODEPAGE_866=m
-+CONFIG_NLS_CODEPAGE_869=m
-+CONFIG_NLS_CODEPAGE_936=m
-+CONFIG_NLS_CODEPAGE_950=m
-+CONFIG_NLS_CODEPAGE_932=m
-+CONFIG_NLS_CODEPAGE_949=m
-+CONFIG_NLS_CODEPAGE_874=m
-+CONFIG_NLS_ISO8859_8=m
-+CONFIG_NLS_CODEPAGE_1250=m
-+CONFIG_NLS_CODEPAGE_1251=m
-+CONFIG_NLS_ASCII=y
-+CONFIG_NLS_ISO8859_1=m
-+CONFIG_NLS_ISO8859_2=m
-+CONFIG_NLS_ISO8859_3=m
-+CONFIG_NLS_ISO8859_4=m
-+CONFIG_NLS_ISO8859_5=m
-+CONFIG_NLS_ISO8859_6=m
-+CONFIG_NLS_ISO8859_7=m
-+CONFIG_NLS_ISO8859_9=m
-+CONFIG_NLS_ISO8859_13=m
-+CONFIG_NLS_ISO8859_14=m
-+CONFIG_NLS_ISO8859_15=m
-+CONFIG_NLS_KOI8_R=m
-+CONFIG_NLS_KOI8_U=m
-+CONFIG_DLM=m
-+CONFIG_CRYPTO_USER=m
-+CONFIG_CRYPTO_CBC=y
-+CONFIG_CRYPTO_CTS=m
-+CONFIG_CRYPTO_XTS=m
-+CONFIG_CRYPTO_XCBC=m
-+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_CRC_ITU_T=y
-+CONFIG_LIBCRC32C=y
-+CONFIG_PRINTK_TIME=y
-+CONFIG_BOOT_PRINTK_DELAY=y
-+CONFIG_DEBUG_MEMORY_INIT=y
-+CONFIG_DETECT_HUNG_TASK=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_UPROBE_EVENTS is not set
-+CONFIG_FUNCTION_PROFILER=y
-+CONFIG_KGDB=y
-+CONFIG_KGDB_KDB=y
-+CONFIG_KDB_KEYBOARD=y
+++ /dev/null
-From 45c6bd73ebe19c29ccdd6f56b52b0f03c9aed562 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 8 Mar 2019 21:12:39 +0000
-Subject: [PATCH 645/703] 2711: Add basic 64-bit support
-
-This commit adds initial support for 64-bit 2711 builds. However,
-it will only work as much as it does if the Pi4 RAM is limited to
-1GB - more than that and several things break (SD card, coherent
-allocations, etc.)
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm64/boot/dts/broadcom/Makefile | 1 +
- .../boot/dts/broadcom/bcm2711-rpi-4-b.dts | 3 +
- arch/arm64/configs/bcm2711_defconfig | 1291 +++++++++++++++++
- 3 files changed, 1295 insertions(+)
- create mode 100644 arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts
- create mode 100644 arch/arm64/configs/bcm2711_defconfig
-
---- a/arch/arm64/boot/dts/broadcom/Makefile
-+++ b/arch/arm64/boot/dts/broadcom/Makefile
-@@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rp
- bcm2837-rpi-3-b-plus.dtb
- dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb
- dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b.dtb
-+dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-4-b.dtb
- dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b-plus.dtb
- dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-cm3.dtb
- dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-cm3.dtb
---- /dev/null
-+++ b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts
-@@ -0,0 +1,3 @@
-+#define RPI364
-+
-+#include "../../../../arm/boot/dts/bcm2711-rpi-4-b.dts"
---- /dev/null
-+++ b/arch/arm64/configs/bcm2711_defconfig
-@@ -0,0 +1,1291 @@
-+CONFIG_LOCALVERSION="-v8"
-+# CONFIG_LOCALVERSION_AUTO is not set
-+CONFIG_SYSVIPC=y
-+CONFIG_POSIX_MQUEUE=y
-+CONFIG_GENERIC_IRQ_DEBUGFS=y
-+CONFIG_NO_HZ=y
-+CONFIG_HIGH_RES_TIMERS=y
-+CONFIG_PREEMPT=y
-+CONFIG_BSD_PROCESS_ACCT=y
-+CONFIG_BSD_PROCESS_ACCT_V3=y
-+CONFIG_TASKSTATS=y
-+CONFIG_TASK_DELAY_ACCT=y
-+CONFIG_TASK_XACCT=y
-+CONFIG_TASK_IO_ACCOUNTING=y
-+CONFIG_IKCONFIG=m
-+CONFIG_IKCONFIG_PROC=y
-+CONFIG_MEMCG=y
-+CONFIG_BLK_CGROUP=y
-+CONFIG_CGROUP_FREEZER=y
-+CONFIG_CPUSETS=y
-+CONFIG_CGROUP_DEVICE=y
-+CONFIG_CGROUP_CPUACCT=y
-+CONFIG_NAMESPACES=y
-+CONFIG_USER_NS=y
-+CONFIG_SCHED_AUTOGROUP=y
-+CONFIG_BLK_DEV_INITRD=y
-+CONFIG_EMBEDDED=y
-+# CONFIG_COMPAT_BRK is not set
-+CONFIG_PROFILING=y
-+CONFIG_ARCH_BCM2835=y
-+CONFIG_PCI=y
-+CONFIG_PCIE_BRCMSTB=y
-+# CONFIG_CAVIUM_ERRATUM_22375 is not set
-+# CONFIG_CAVIUM_ERRATUM_23154 is not set
-+# CONFIG_CAVIUM_ERRATUM_27456 is not set
-+CONFIG_SECCOMP=y
-+CONFIG_ARMV8_DEPRECATED=y
-+CONFIG_SWP_EMULATION=y
-+CONFIG_CP15_BARRIER_EMULATION=y
-+CONFIG_SETEND_EMULATION=y
-+CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait"
-+CONFIG_COMPAT=y
-+# CONFIG_SUSPEND is not set
-+CONFIG_PM=y
-+CONFIG_CPU_IDLE=y
-+CONFIG_ARM_CPUIDLE=y
-+CONFIG_CPU_FREQ=y
-+CONFIG_CPU_FREQ_STAT=y
-+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y
-+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-+CONFIG_CPU_FREQ_GOV_USERSPACE=y
-+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
-+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
-+CONFIG_RASPBERRYPI_FIRMWARE=y
-+CONFIG_ARM64_CRYPTO=y
-+CONFIG_CRYPTO_AES_ARM64_BS=m
-+CONFIG_KPROBES=y
-+CONFIG_JUMP_LABEL=y
-+CONFIG_MODULES=y
-+CONFIG_MODULE_UNLOAD=y
-+CONFIG_MODVERSIONS=y
-+CONFIG_MODULE_SRCVERSION_ALL=y
-+CONFIG_BLK_DEV_THROTTLING=y
-+CONFIG_PARTITION_ADVANCED=y
-+CONFIG_MAC_PARTITION=y
-+CONFIG_CFQ_GROUP_IOSCHED=y
-+CONFIG_BINFMT_MISC=m
-+CONFIG_CLEANCACHE=y
-+CONFIG_FRONTSWAP=y
-+CONFIG_CMA=y
-+CONFIG_ZSMALLOC=m
-+CONFIG_PGTABLE_MAPPING=y
-+CONFIG_NET=y
-+CONFIG_PACKET=y
-+CONFIG_UNIX=y
-+CONFIG_XFRM_USER=y
-+CONFIG_NET_KEY=m
-+CONFIG_INET=y
-+CONFIG_IP_MULTICAST=y
-+CONFIG_IP_ADVANCED_ROUTER=y
-+CONFIG_IP_MULTIPLE_TABLES=y
-+CONFIG_IP_ROUTE_MULTIPATH=y
-+CONFIG_IP_ROUTE_VERBOSE=y
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+CONFIG_IP_PNP_RARP=y
-+CONFIG_NET_IPIP=m
-+CONFIG_NET_IPGRE_DEMUX=m
-+CONFIG_NET_IPGRE=m
-+CONFIG_IP_MROUTE=y
-+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
-+CONFIG_IP_PIMSM_V1=y
-+CONFIG_IP_PIMSM_V2=y
-+CONFIG_SYN_COOKIES=y
-+CONFIG_INET_AH=m
-+CONFIG_INET_ESP=m
-+CONFIG_INET_IPCOMP=m
-+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_IPV6_ROUTE_INFO=y
-+CONFIG_INET6_AH=m
-+CONFIG_INET6_ESP=m
-+CONFIG_INET6_IPCOMP=m
-+CONFIG_IPV6_SIT_6RD=y
-+CONFIG_IPV6_TUNNEL=m
-+CONFIG_IPV6_MULTIPLE_TABLES=y
-+CONFIG_IPV6_SUBTREES=y
-+CONFIG_IPV6_MROUTE=y
-+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
-+CONFIG_IPV6_PIMSM_V2=y
-+CONFIG_NETFILTER=y
-+CONFIG_NF_CONNTRACK=m
-+CONFIG_NF_CONNTRACK_ZONES=y
-+CONFIG_NF_CONNTRACK_EVENTS=y
-+CONFIG_NF_CONNTRACK_TIMESTAMP=y
-+CONFIG_NF_CONNTRACK_AMANDA=m
-+CONFIG_NF_CONNTRACK_FTP=m
-+CONFIG_NF_CONNTRACK_H323=m
-+CONFIG_NF_CONNTRACK_IRC=m
-+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
-+CONFIG_NF_CONNTRACK_SNMP=m
-+CONFIG_NF_CONNTRACK_PPTP=m
-+CONFIG_NF_CONNTRACK_SANE=m
-+CONFIG_NF_CONNTRACK_SIP=m
-+CONFIG_NF_CONNTRACK_TFTP=m
-+CONFIG_NF_CT_NETLINK=m
-+CONFIG_NETFILTER_XT_SET=m
-+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
-+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
-+CONFIG_NETFILTER_XT_TARGET_DSCP=m
-+CONFIG_NETFILTER_XT_TARGET_HMARK=m
-+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
-+CONFIG_NETFILTER_XT_TARGET_LED=m
-+CONFIG_NETFILTER_XT_TARGET_LOG=m
-+CONFIG_NETFILTER_XT_TARGET_MARK=m
-+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
-+CONFIG_NETFILTER_XT_TARGET_TEE=m
-+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
-+CONFIG_NETFILTER_XT_TARGET_TRACE=m
-+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
-+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
-+CONFIG_NETFILTER_XT_MATCH_BPF=m
-+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
-+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
-+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
-+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-+CONFIG_NETFILTER_XT_MATCH_CPU=m
-+CONFIG_NETFILTER_XT_MATCH_DCCP=m
-+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
-+CONFIG_NETFILTER_XT_MATCH_DSCP=m
-+CONFIG_NETFILTER_XT_MATCH_ESP=m
-+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
-+CONFIG_NETFILTER_XT_MATCH_HELPER=m
-+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
-+CONFIG_NETFILTER_XT_MATCH_IPVS=m
-+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-+CONFIG_NETFILTER_XT_MATCH_MAC=m
-+CONFIG_NETFILTER_XT_MATCH_MARK=m
-+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
-+CONFIG_NETFILTER_XT_MATCH_OSF=m
-+CONFIG_NETFILTER_XT_MATCH_OWNER=m
-+CONFIG_NETFILTER_XT_MATCH_POLICY=m
-+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
-+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-+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_STATE=m
-+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-+CONFIG_NETFILTER_XT_MATCH_STRING=m
-+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-+CONFIG_NETFILTER_XT_MATCH_TIME=m
-+CONFIG_NETFILTER_XT_MATCH_U32=m
-+CONFIG_IP_SET=m
-+CONFIG_IP_SET_BITMAP_IP=m
-+CONFIG_IP_SET_BITMAP_IPMAC=m
-+CONFIG_IP_SET_BITMAP_PORT=m
-+CONFIG_IP_SET_HASH_IP=m
-+CONFIG_IP_SET_HASH_IPPORT=m
-+CONFIG_IP_SET_HASH_IPPORTIP=m
-+CONFIG_IP_SET_HASH_IPPORTNET=m
-+CONFIG_IP_SET_HASH_NET=m
-+CONFIG_IP_SET_HASH_NETPORT=m
-+CONFIG_IP_SET_HASH_NETIFACE=m
-+CONFIG_IP_SET_LIST_SET=m
-+CONFIG_IP_VS=m
-+CONFIG_IP_VS_PROTO_TCP=y
-+CONFIG_IP_VS_PROTO_UDP=y
-+CONFIG_IP_VS_PROTO_ESP=y
-+CONFIG_IP_VS_PROTO_AH=y
-+CONFIG_IP_VS_PROTO_SCTP=y
-+CONFIG_IP_VS_RR=m
-+CONFIG_IP_VS_WRR=m
-+CONFIG_IP_VS_LC=m
-+CONFIG_IP_VS_WLC=m
-+CONFIG_IP_VS_LBLC=m
-+CONFIG_IP_VS_LBLCR=m
-+CONFIG_IP_VS_DH=m
-+CONFIG_IP_VS_SH=m
-+CONFIG_IP_VS_SED=m
-+CONFIG_IP_VS_NQ=m
-+CONFIG_IP_VS_FTP=m
-+CONFIG_IP_VS_PE_SIP=m
-+CONFIG_IP_NF_IPTABLES=m
-+CONFIG_IP_NF_MATCH_AH=m
-+CONFIG_IP_NF_MATCH_ECN=m
-+CONFIG_IP_NF_MATCH_RPFILTER=m
-+CONFIG_IP_NF_MATCH_TTL=m
-+CONFIG_IP_NF_FILTER=m
-+CONFIG_IP_NF_TARGET_REJECT=m
-+CONFIG_IP_NF_NAT=m
-+CONFIG_IP_NF_TARGET_MASQUERADE=m
-+CONFIG_IP_NF_TARGET_NETMAP=m
-+CONFIG_IP_NF_TARGET_REDIRECT=m
-+CONFIG_IP_NF_MANGLE=m
-+CONFIG_IP_NF_TARGET_CLUSTERIP=m
-+CONFIG_IP_NF_TARGET_ECN=m
-+CONFIG_IP_NF_TARGET_TTL=m
-+CONFIG_IP_NF_RAW=m
-+CONFIG_IP_NF_ARPTABLES=m
-+CONFIG_IP_NF_ARPFILTER=m
-+CONFIG_IP_NF_ARP_MANGLE=m
-+CONFIG_IP6_NF_IPTABLES=m
-+CONFIG_IP6_NF_MATCH_AH=m
-+CONFIG_IP6_NF_MATCH_EUI64=m
-+CONFIG_IP6_NF_MATCH_FRAG=m
-+CONFIG_IP6_NF_MATCH_OPTS=m
-+CONFIG_IP6_NF_MATCH_HL=m
-+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-+CONFIG_IP6_NF_MATCH_MH=m
-+CONFIG_IP6_NF_MATCH_RPFILTER=m
-+CONFIG_IP6_NF_MATCH_RT=m
-+CONFIG_IP6_NF_TARGET_HL=m
-+CONFIG_IP6_NF_FILTER=m
-+CONFIG_IP6_NF_TARGET_REJECT=m
-+CONFIG_IP6_NF_MANGLE=m
-+CONFIG_IP6_NF_RAW=m
-+CONFIG_IP6_NF_NAT=m
-+CONFIG_IP6_NF_TARGET_MASQUERADE=m
-+CONFIG_IP6_NF_TARGET_NPT=m
-+CONFIG_BRIDGE_NF_EBTABLES=m
-+CONFIG_BRIDGE_EBT_BROUTE=m
-+CONFIG_BRIDGE_EBT_T_FILTER=m
-+CONFIG_BRIDGE_EBT_T_NAT=m
-+CONFIG_BRIDGE_EBT_802_3=m
-+CONFIG_BRIDGE_EBT_AMONG=m
-+CONFIG_BRIDGE_EBT_ARP=m
-+CONFIG_BRIDGE_EBT_IP=m
-+CONFIG_BRIDGE_EBT_IP6=m
-+CONFIG_BRIDGE_EBT_LIMIT=m
-+CONFIG_BRIDGE_EBT_MARK=m
-+CONFIG_BRIDGE_EBT_PKTTYPE=m
-+CONFIG_BRIDGE_EBT_STP=m
-+CONFIG_BRIDGE_EBT_VLAN=m
-+CONFIG_BRIDGE_EBT_ARPREPLY=m
-+CONFIG_BRIDGE_EBT_DNAT=m
-+CONFIG_BRIDGE_EBT_MARK_T=m
-+CONFIG_BRIDGE_EBT_REDIRECT=m
-+CONFIG_BRIDGE_EBT_SNAT=m
-+CONFIG_BRIDGE_EBT_LOG=m
-+CONFIG_BRIDGE_EBT_NFLOG=m
-+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
-+CONFIG_ATM=m
-+CONFIG_L2TP=m
-+CONFIG_L2TP_V3=y
-+CONFIG_L2TP_IP=m
-+CONFIG_L2TP_ETH=m
-+CONFIG_BRIDGE=m
-+CONFIG_VLAN_8021Q=m
-+CONFIG_VLAN_8021Q_GVRP=y
-+CONFIG_ATALK=m
-+CONFIG_6LOWPAN=m
-+CONFIG_IEEE802154=m
-+CONFIG_IEEE802154_6LOWPAN=m
-+CONFIG_MAC802154=m
-+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
-+CONFIG_NET_SCH_SFB=m
-+CONFIG_NET_SCH_SFQ=m
-+CONFIG_NET_SCH_TEQL=m
-+CONFIG_NET_SCH_TBF=m
-+CONFIG_NET_SCH_GRED=m
-+CONFIG_NET_SCH_DSMARK=m
-+CONFIG_NET_SCH_NETEM=m
-+CONFIG_NET_SCH_DRR=m
-+CONFIG_NET_SCH_MQPRIO=m
-+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
-+CONFIG_NET_CLS_TCINDEX=m
-+CONFIG_NET_CLS_ROUTE4=m
-+CONFIG_NET_CLS_FW=m
-+CONFIG_NET_CLS_U32=m
-+CONFIG_CLS_U32_MARK=y
-+CONFIG_NET_CLS_RSVP=m
-+CONFIG_NET_CLS_RSVP6=m
-+CONFIG_NET_CLS_FLOW=m
-+CONFIG_NET_CLS_CGROUP=m
-+CONFIG_NET_EMATCH=y
-+CONFIG_NET_EMATCH_CMP=m
-+CONFIG_NET_EMATCH_NBYTE=m
-+CONFIG_NET_EMATCH_U32=m
-+CONFIG_NET_EMATCH_META=m
-+CONFIG_NET_EMATCH_TEXT=m
-+CONFIG_NET_EMATCH_IPSET=m
-+CONFIG_NET_CLS_ACT=y
-+CONFIG_NET_ACT_POLICE=m
-+CONFIG_NET_ACT_GACT=m
-+CONFIG_GACT_PROB=y
-+CONFIG_NET_ACT_MIRRED=m
-+CONFIG_NET_ACT_IPT=m
-+CONFIG_NET_ACT_NAT=m
-+CONFIG_NET_ACT_PEDIT=m
-+CONFIG_NET_ACT_SIMP=m
-+CONFIG_NET_ACT_SKBEDIT=m
-+CONFIG_NET_ACT_CSUM=m
-+CONFIG_BATMAN_ADV=m
-+CONFIG_OPENVSWITCH=m
-+CONFIG_NET_PKTGEN=m
-+CONFIG_HAMRADIO=y
-+CONFIG_AX25=m
-+CONFIG_NETROM=m
-+CONFIG_ROSE=m
-+CONFIG_MKISS=m
-+CONFIG_6PACK=m
-+CONFIG_BPQETHER=m
-+CONFIG_BAYCOM_SER_FDX=m
-+CONFIG_BAYCOM_SER_HDX=m
-+CONFIG_YAM=m
-+CONFIG_CAN=m
-+CONFIG_CAN_VCAN=m
-+CONFIG_CAN_SLCAN=m
-+CONFIG_CAN_MCP251X=m
-+CONFIG_CAN_GS_USB=m
-+CONFIG_BT=m
-+CONFIG_BT_RFCOMM=m
-+CONFIG_BT_RFCOMM_TTY=y
-+CONFIG_BT_BNEP=m
-+CONFIG_BT_BNEP_MC_FILTER=y
-+CONFIG_BT_BNEP_PROTO_FILTER=y
-+CONFIG_BT_HIDP=m
-+CONFIG_BT_6LOWPAN=m
-+CONFIG_BT_HCIBTUSB=m
-+CONFIG_BT_HCIUART=m
-+CONFIG_BT_HCIUART_3WIRE=y
-+CONFIG_BT_HCIUART_BCM=y
-+CONFIG_BT_HCIBCM203X=m
-+CONFIG_BT_HCIBPA10X=m
-+CONFIG_BT_HCIBFUSB=m
-+CONFIG_BT_HCIVHCI=m
-+CONFIG_BT_MRVL=m
-+CONFIG_BT_MRVL_SDIO=m
-+CONFIG_BT_ATH3K=m
-+CONFIG_BT_WILINK=m
-+CONFIG_CFG80211=m
-+CONFIG_MAC80211=m
-+CONFIG_MAC80211_MESH=y
-+CONFIG_WIMAX=m
-+CONFIG_RFKILL=m
-+CONFIG_RFKILL_INPUT=y
-+CONFIG_NET_9P=m
-+CONFIG_NFC=m
-+CONFIG_DEVTMPFS=y
-+CONFIG_DEVTMPFS_MOUNT=y
-+CONFIG_DMA_CMA=y
-+CONFIG_CMA_SIZE_MBYTES=5
-+CONFIG_MTD=m
-+CONFIG_MTD_BLOCK=m
-+CONFIG_MTD_M25P80=m
-+CONFIG_MTD_BLOCK2MTD=m
-+CONFIG_MTD_NAND=m
-+CONFIG_MTD_SPI_NOR=m
-+CONFIG_MTD_UBI=m
-+CONFIG_OF_CONFIGFS=y
-+CONFIG_ZRAM=m
-+CONFIG_BLK_DEV_LOOP=y
-+CONFIG_BLK_DEV_CRYPTOLOOP=m
-+CONFIG_BLK_DEV_DRBD=m
-+CONFIG_BLK_DEV_NBD=m
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_CDROM_PKTCDVD=m
-+CONFIG_ATA_OVER_ETH=m
-+CONFIG_EEPROM_AT24=m
-+CONFIG_TI_ST=m
-+CONFIG_SCSI=y
-+# CONFIG_SCSI_PROC_FS is not set
-+CONFIG_BLK_DEV_SD=y
-+CONFIG_CHR_DEV_ST=m
-+CONFIG_CHR_DEV_OSST=m
-+CONFIG_BLK_DEV_SR=m
-+CONFIG_CHR_DEV_SG=m
-+CONFIG_SCSI_ISCSI_ATTRS=y
-+CONFIG_ISCSI_TCP=m
-+CONFIG_ISCSI_BOOT_SYSFS=m
-+CONFIG_MD=y
-+CONFIG_MD_LINEAR=m
-+CONFIG_BLK_DEV_DM=m
-+CONFIG_DM_CRYPT=m
-+CONFIG_DM_SNAPSHOT=m
-+CONFIG_DM_THIN_PROVISIONING=m
-+CONFIG_DM_CACHE=m
-+CONFIG_DM_MIRROR=m
-+CONFIG_DM_LOG_USERSPACE=m
-+CONFIG_DM_RAID=m
-+CONFIG_DM_ZERO=m
-+CONFIG_DM_DELAY=m
-+CONFIG_NETDEVICES=y
-+CONFIG_BONDING=m
-+CONFIG_DUMMY=m
-+CONFIG_IFB=m
-+CONFIG_MACVLAN=m
-+CONFIG_IPVLAN=m
-+CONFIG_VXLAN=m
-+CONFIG_NETCONSOLE=m
-+CONFIG_TUN=m
-+CONFIG_VETH=m
-+CONFIG_BCMGENET=y
-+CONFIG_ENC28J60=m
-+CONFIG_QCA7000_SPI=m
-+CONFIG_MDIO_BITBANG=m
-+CONFIG_BROADCOM_PHY=y
-+CONFIG_PPP=m
-+CONFIG_PPP_BSDCOMP=m
-+CONFIG_PPP_DEFLATE=m
-+CONFIG_PPP_FILTER=y
-+CONFIG_PPP_MPPE=m
-+CONFIG_PPP_MULTILINK=y
-+CONFIG_PPPOATM=m
-+CONFIG_PPPOE=m
-+CONFIG_PPPOL2TP=m
-+CONFIG_PPP_ASYNC=m
-+CONFIG_PPP_SYNC_TTY=m
-+CONFIG_SLIP=m
-+CONFIG_SLIP_COMPRESSED=y
-+CONFIG_SLIP_SMART=y
-+CONFIG_USB_CATC=m
-+CONFIG_USB_KAWETH=m
-+CONFIG_USB_PEGASUS=m
-+CONFIG_USB_RTL8150=m
-+CONFIG_USB_RTL8152=y
-+CONFIG_USB_LAN78XX=y
-+CONFIG_USB_USBNET=y
-+CONFIG_USB_NET_AX88179_178A=m
-+CONFIG_USB_NET_CDCETHER=m
-+CONFIG_USB_NET_CDC_EEM=m
-+CONFIG_USB_NET_CDC_NCM=m
-+CONFIG_USB_NET_HUAWEI_CDC_NCM=m
-+CONFIG_USB_NET_CDC_MBIM=m
-+CONFIG_USB_NET_DM9601=m
-+CONFIG_USB_NET_SR9700=m
-+CONFIG_USB_NET_SR9800=m
-+CONFIG_USB_NET_SMSC75XX=m
-+CONFIG_USB_NET_SMSC95XX=y
-+CONFIG_USB_NET_GL620A=m
-+CONFIG_USB_NET_NET1080=m
-+CONFIG_USB_NET_PLUSB=m
-+CONFIG_USB_NET_MCS7830=m
-+CONFIG_USB_NET_CDC_SUBSET=m
-+CONFIG_USB_ALI_M5632=y
-+CONFIG_USB_AN2720=y
-+CONFIG_USB_EPSON2888=y
-+CONFIG_USB_KC2190=y
-+CONFIG_USB_NET_ZAURUS=m
-+CONFIG_USB_NET_CX82310_ETH=m
-+CONFIG_USB_NET_KALMIA=m
-+CONFIG_USB_NET_QMI_WWAN=m
-+CONFIG_USB_HSO=m
-+CONFIG_USB_NET_INT51X1=m
-+CONFIG_USB_IPHETH=m
-+CONFIG_USB_SIERRA_NET=m
-+CONFIG_USB_VL600=m
-+CONFIG_ATH9K=m
-+CONFIG_ATH9K_HTC=m
-+CONFIG_CARL9170=m
-+CONFIG_ATH6KL=m
-+CONFIG_ATH6KL_USB=m
-+CONFIG_AR5523=m
-+CONFIG_AT76C50X_USB=m
-+CONFIG_B43=m
-+# CONFIG_B43_PHY_N is not set
-+CONFIG_B43LEGACY=m
-+CONFIG_BRCMFMAC=m
-+CONFIG_BRCMFMAC_USB=y
-+CONFIG_BRCMDBG=y
-+CONFIG_HOSTAP=m
-+CONFIG_P54_COMMON=m
-+CONFIG_P54_USB=m
-+CONFIG_LIBERTAS=m
-+CONFIG_LIBERTAS_USB=m
-+CONFIG_LIBERTAS_SDIO=m
-+CONFIG_LIBERTAS_THINFIRM=m
-+CONFIG_LIBERTAS_THINFIRM_USB=m
-+CONFIG_MWIFIEX=m
-+CONFIG_MWIFIEX_SDIO=m
-+CONFIG_MT7601U=m
-+CONFIG_RT2X00=m
-+CONFIG_RT2500USB=m
-+CONFIG_RT73USB=m
-+CONFIG_RT2800USB=m
-+CONFIG_RT2800USB_RT3573=y
-+CONFIG_RT2800USB_RT53XX=y
-+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
-+CONFIG_USB_NET_RNDIS_WLAN=m
-+CONFIG_WIMAX_I2400M_USB=m
-+CONFIG_IEEE802154_AT86RF230=m
-+CONFIG_IEEE802154_MRF24J40=m
-+CONFIG_IEEE802154_CC2520=m
-+CONFIG_INPUT_MOUSEDEV=y
-+CONFIG_INPUT_JOYDEV=m
-+CONFIG_INPUT_EVDEV=m
-+# CONFIG_KEYBOARD_ATKBD is not set
-+CONFIG_KEYBOARD_GPIO=m
-+CONFIG_KEYBOARD_MATRIX=m
-+# CONFIG_INPUT_MOUSE is not set
-+CONFIG_INPUT_JOYSTICK=y
-+CONFIG_JOYSTICK_IFORCE=m
-+CONFIG_JOYSTICK_IFORCE_USB=y
-+CONFIG_JOYSTICK_XPAD=m
-+CONFIG_JOYSTICK_XPAD_FF=y
-+CONFIG_JOYSTICK_XPAD_LEDS=y
-+CONFIG_JOYSTICK_PSXPAD_SPI=m
-+CONFIG_JOYSTICK_PSXPAD_SPI_FF=y
-+CONFIG_JOYSTICK_RPISENSE=m
-+CONFIG_INPUT_TOUCHSCREEN=y
-+CONFIG_TOUCHSCREEN_ADS7846=m
-+CONFIG_TOUCHSCREEN_EGALAX=m
-+CONFIG_TOUCHSCREEN_EXC3000=m
-+CONFIG_TOUCHSCREEN_GOODIX=m
-+CONFIG_TOUCHSCREEN_EDT_FT5X06=m
-+CONFIG_TOUCHSCREEN_RPI_FT5406=m
-+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
-+CONFIG_TOUCHSCREEN_STMPE=m
-+CONFIG_INPUT_MISC=y
-+CONFIG_INPUT_AD714X=m
-+CONFIG_INPUT_ATI_REMOTE2=m
-+CONFIG_INPUT_KEYSPAN_REMOTE=m
-+CONFIG_INPUT_POWERMATE=m
-+CONFIG_INPUT_YEALINK=m
-+CONFIG_INPUT_CM109=m
-+CONFIG_INPUT_UINPUT=m
-+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
-+CONFIG_INPUT_ADXL34X=m
-+CONFIG_INPUT_CMA3000=m
-+CONFIG_SERIO=m
-+CONFIG_SERIO_RAW=m
-+CONFIG_GAMEPORT=m
-+CONFIG_GAMEPORT_NS558=m
-+CONFIG_GAMEPORT_L4=m
-+CONFIG_BRCM_CHAR_DRIVERS=y
-+CONFIG_BCM_VCIO=y
-+CONFIG_BCM2835_DEVGPIOMEM=y
-+# CONFIG_BCM2835_SMI_DEV is not set
-+# CONFIG_LEGACY_PTYS is not set
-+CONFIG_SERIAL_8250=y
-+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
-+CONFIG_SERIAL_8250_CONSOLE=y
-+# CONFIG_SERIAL_8250_DMA is not set
-+CONFIG_SERIAL_8250_NR_UARTS=1
-+CONFIG_SERIAL_8250_RUNTIME_UARTS=0
-+CONFIG_SERIAL_8250_EXTENDED=y
-+CONFIG_SERIAL_8250_SHARE_IRQ=y
-+CONFIG_SERIAL_8250_BCM2835AUX=y
-+CONFIG_SERIAL_OF_PLATFORM=y
-+CONFIG_SERIAL_AMBA_PL011=y
-+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-+CONFIG_SERIAL_SC16IS7XX=m
-+CONFIG_SERIAL_SC16IS7XX_SPI=y
-+CONFIG_SERIAL_DEV_BUS=m
-+CONFIG_TTY_PRINTK=y
-+CONFIG_HW_RANDOM=y
-+# CONFIG_HW_RANDOM_BCM2835 is not set
-+CONFIG_RAW_DRIVER=y
-+CONFIG_I2C=y
-+CONFIG_I2C_CHARDEV=m
-+CONFIG_I2C_BCM2708=m
-+CONFIG_I2C_BCM2835=m
-+CONFIG_I2C_GPIO=m
-+CONFIG_I2C_ROBOTFUZZ_OSIF=m
-+CONFIG_I2C_TINY_USB=m
-+CONFIG_SPI=y
-+CONFIG_SPI_BCM2835=m
-+CONFIG_SPI_BCM2835AUX=m
-+CONFIG_SPI_SPIDEV=m
-+CONFIG_SPI_SLAVE=y
-+CONFIG_PPS_CLIENT_LDISC=m
-+CONFIG_PPS_CLIENT_GPIO=m
-+CONFIG_PINCTRL_MCP23S08=m
-+CONFIG_GPIO_BCM_VIRT=y
-+CONFIG_GPIO_MOCKUP=m
-+CONFIG_GPIO_PCF857X=m
-+CONFIG_GPIO_ARIZONA=m
-+CONFIG_GPIO_STMPE=y
-+CONFIG_W1=m
-+CONFIG_W1_MASTER_DS2490=m
-+CONFIG_W1_MASTER_DS2482=m
-+CONFIG_W1_MASTER_DS1WM=m
-+CONFIG_W1_MASTER_GPIO=m
-+CONFIG_W1_SLAVE_THERM=m
-+CONFIG_W1_SLAVE_SMEM=m
-+CONFIG_W1_SLAVE_DS2408=m
-+CONFIG_W1_SLAVE_DS2413=m
-+CONFIG_W1_SLAVE_DS2406=m
-+CONFIG_W1_SLAVE_DS2423=m
-+CONFIG_W1_SLAVE_DS2431=m
-+CONFIG_W1_SLAVE_DS2433=m
-+CONFIG_W1_SLAVE_DS2438=m
-+CONFIG_W1_SLAVE_DS2780=m
-+CONFIG_W1_SLAVE_DS2781=m
-+CONFIG_W1_SLAVE_DS28E04=m
-+CONFIG_POWER_RESET_GPIO=y
-+CONFIG_BATTERY_DS2760=m
-+CONFIG_BATTERY_GAUGE_LTC2941=m
-+CONFIG_HWMON=m
-+CONFIG_SENSORS_DS1621=m
-+CONFIG_SENSORS_JC42=m
-+CONFIG_SENSORS_LM75=m
-+CONFIG_SENSORS_SHT21=m
-+CONFIG_SENSORS_SHT3x=m
-+CONFIG_SENSORS_SHTC1=m
-+CONFIG_SENSORS_ADS1015=m
-+CONFIG_SENSORS_INA2XX=m
-+CONFIG_SENSORS_TMP102=m
-+CONFIG_THERMAL=y
-+CONFIG_BCM2835_THERMAL=y
-+CONFIG_WATCHDOG=y
-+CONFIG_GPIO_WATCHDOG=m
-+CONFIG_BCM2835_WDT=y
-+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_LDO1=m
-+CONFIG_REGULATOR_ARIZONA_MICSUPP=m
-+CONFIG_REGULATOR_GPIO=y
-+CONFIG_MEDIA_SUPPORT=m
-+CONFIG_MEDIA_CAMERA_SUPPORT=y
-+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
-+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
-+CONFIG_MEDIA_RADIO_SUPPORT=y
-+CONFIG_MEDIA_CONTROLLER=y
-+CONFIG_MEDIA_USB_SUPPORT=y
-+CONFIG_USB_VIDEO_CLASS=m
-+CONFIG_USB_M5602=m
-+CONFIG_USB_STV06XX=m
-+CONFIG_USB_GL860=m
-+CONFIG_USB_GSPCA_BENQ=m
-+CONFIG_USB_GSPCA_CONEX=m
-+CONFIG_USB_GSPCA_CPIA1=m
-+CONFIG_USB_GSPCA_DTCS033=m
-+CONFIG_USB_GSPCA_ETOMS=m
-+CONFIG_USB_GSPCA_FINEPIX=m
-+CONFIG_USB_GSPCA_JEILINJ=m
-+CONFIG_USB_GSPCA_JL2005BCD=m
-+CONFIG_USB_GSPCA_KINECT=m
-+CONFIG_USB_GSPCA_KONICA=m
-+CONFIG_USB_GSPCA_MARS=m
-+CONFIG_USB_GSPCA_MR97310A=m
-+CONFIG_USB_GSPCA_NW80X=m
-+CONFIG_USB_GSPCA_OV519=m
-+CONFIG_USB_GSPCA_OV534=m
-+CONFIG_USB_GSPCA_OV534_9=m
-+CONFIG_USB_GSPCA_PAC207=m
-+CONFIG_USB_GSPCA_PAC7302=m
-+CONFIG_USB_GSPCA_PAC7311=m
-+CONFIG_USB_GSPCA_SE401=m
-+CONFIG_USB_GSPCA_SN9C2028=m
-+CONFIG_USB_GSPCA_SN9C20X=m
-+CONFIG_USB_GSPCA_SONIXB=m
-+CONFIG_USB_GSPCA_SONIXJ=m
-+CONFIG_USB_GSPCA_SPCA500=m
-+CONFIG_USB_GSPCA_SPCA501=m
-+CONFIG_USB_GSPCA_SPCA505=m
-+CONFIG_USB_GSPCA_SPCA506=m
-+CONFIG_USB_GSPCA_SPCA508=m
-+CONFIG_USB_GSPCA_SPCA561=m
-+CONFIG_USB_GSPCA_SPCA1528=m
-+CONFIG_USB_GSPCA_SQ905=m
-+CONFIG_USB_GSPCA_SQ905C=m
-+CONFIG_USB_GSPCA_SQ930X=m
-+CONFIG_USB_GSPCA_STK014=m
-+CONFIG_USB_GSPCA_STK1135=m
-+CONFIG_USB_GSPCA_STV0680=m
-+CONFIG_USB_GSPCA_SUNPLUS=m
-+CONFIG_USB_GSPCA_T613=m
-+CONFIG_USB_GSPCA_TOPRO=m
-+CONFIG_USB_GSPCA_TV8532=m
-+CONFIG_USB_GSPCA_VC032X=m
-+CONFIG_USB_GSPCA_VICAM=m
-+CONFIG_USB_GSPCA_XIRLINK_CIT=m
-+CONFIG_USB_GSPCA_ZC3XX=m
-+CONFIG_USB_PWC=m
-+CONFIG_VIDEO_CPIA2=m
-+CONFIG_USB_ZR364XX=m
-+CONFIG_USB_STKWEBCAM=m
-+CONFIG_USB_S2255=m
-+CONFIG_VIDEO_USBTV=m
-+CONFIG_VIDEO_PVRUSB2=m
-+CONFIG_VIDEO_HDPVR=m
-+CONFIG_VIDEO_USBVISION=m
-+CONFIG_VIDEO_STK1160_COMMON=m
-+CONFIG_VIDEO_GO7007=m
-+CONFIG_VIDEO_GO7007_USB=m
-+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m
-+CONFIG_VIDEO_AU0828=m
-+CONFIG_DVB_USB_V2=m
-+CONFIG_DVB_USB_AF9035=m
-+CONFIG_DVB_USB_ANYSEE=m
-+CONFIG_DVB_USB_AU6610=m
-+CONFIG_DVB_USB_AZ6007=m
-+CONFIG_DVB_USB_CE6230=m
-+CONFIG_DVB_USB_EC168=m
-+CONFIG_DVB_USB_GL861=m
-+CONFIG_DVB_USB_MXL111SF=m
-+CONFIG_DVB_USB_DVBSKY=m
-+CONFIG_SMS_USB_DRV=m
-+CONFIG_DVB_B2C2_FLEXCOP_USB=m
-+CONFIG_DVB_AS102=m
-+CONFIG_VIDEO_EM28XX=m
-+CONFIG_VIDEO_EM28XX_V4L2=m
-+CONFIG_VIDEO_EM28XX_ALSA=m
-+CONFIG_VIDEO_EM28XX_DVB=m
-+CONFIG_V4L_PLATFORM_DRIVERS=y
-+CONFIG_RADIO_SI470X=m
-+CONFIG_USB_SI470X=m
-+CONFIG_I2C_SI470X=m
-+CONFIG_RADIO_SI4713=m
-+CONFIG_I2C_SI4713=m
-+CONFIG_USB_MR800=m
-+CONFIG_USB_DSBR=m
-+CONFIG_RADIO_SHARK=m
-+CONFIG_RADIO_SHARK2=m
-+CONFIG_USB_KEENE=m
-+CONFIG_USB_MA901=m
-+CONFIG_RADIO_TEA5764=m
-+CONFIG_RADIO_SAA7706H=m
-+CONFIG_RADIO_TEF6862=m
-+CONFIG_RADIO_WL1273=m
-+CONFIG_RADIO_WL128X=m
-+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
-+CONFIG_VIDEO_UDA1342=m
-+CONFIG_VIDEO_SONY_BTF_MPX=m
-+CONFIG_VIDEO_TVP5150=m
-+CONFIG_VIDEO_TW2804=m
-+CONFIG_VIDEO_TW9903=m
-+CONFIG_VIDEO_TW9906=m
-+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_VC4=m
-+CONFIG_DRM_TINYDRM=m
-+CONFIG_TINYDRM_MI0283QT=m
-+CONFIG_TINYDRM_REPAPER=m
-+CONFIG_FB=y
-+CONFIG_FB_BCM2708=y
-+CONFIG_FB_UDL=m
-+CONFIG_FB_SSD1307=m
-+CONFIG_FB_RPISENSE=m
-+# CONFIG_BACKLIGHT_GENERIC is not set
-+CONFIG_BACKLIGHT_RPI=m
-+CONFIG_BACKLIGHT_GPIO=m
-+CONFIG_FRAMEBUFFER_CONSOLE=y
-+CONFIG_LOGO=y
-+# CONFIG_LOGO_LINUX_MONO is not set
-+# CONFIG_LOGO_LINUX_VGA16 is not set
-+CONFIG_SOUND=y
-+CONFIG_SND=m
-+CONFIG_SND_HRTIMER=m
-+CONFIG_SND_SEQUENCER=m
-+CONFIG_SND_SEQ_DUMMY=m
-+CONFIG_SND_DUMMY=m
-+CONFIG_SND_ALOOP=m
-+CONFIG_SND_VIRMIDI=m
-+CONFIG_SND_MTPAV=m
-+CONFIG_SND_SERIAL_U16550=m
-+CONFIG_SND_MPU401=m
-+CONFIG_SND_USB_AUDIO=m
-+CONFIG_SND_USB_UA101=m
-+CONFIG_SND_USB_CAIAQ=m
-+CONFIG_SND_USB_CAIAQ_INPUT=y
-+CONFIG_SND_USB_6FIRE=m
-+CONFIG_SND_USB_HIFACE=m
-+CONFIG_SND_SOC=m
-+CONFIG_SND_BCM2835_SOC_I2S=m
-+CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD=m
-+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
-+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
-+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=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
-+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
-+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
-+CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
-+CONFIG_SND_BCM2708_SOC_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_ALLO_PIANO_DAC_PLUS=m
-+CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC=m
-+CONFIG_SND_BCM2708_SOC_ALLO_DIGIONE=m
-+CONFIG_SND_BCM2708_SOC_ALLO_KATANA_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_CS4271_I2C=m
-+CONFIG_SND_SOC_SPDIF=m
-+CONFIG_SND_SOC_WM8804_I2C=m
-+CONFIG_SND_SIMPLE_CARD=m
-+CONFIG_HID_BATTERY_STRENGTH=y
-+CONFIG_HIDRAW=y
-+CONFIG_UHID=m
-+CONFIG_HID_A4TECH=m
-+CONFIG_HID_ACRUX=m
-+CONFIG_HID_APPLE=m
-+CONFIG_HID_ASUS=m
-+CONFIG_HID_BELKIN=m
-+CONFIG_HID_BETOP_FF=m
-+CONFIG_HID_CHERRY=m
-+CONFIG_HID_CHICONY=m
-+CONFIG_HID_CYPRESS=m
-+CONFIG_HID_DRAGONRISE=m
-+CONFIG_HID_EMS_FF=m
-+CONFIG_HID_ELECOM=m
-+CONFIG_HID_ELO=m
-+CONFIG_HID_EZKEY=m
-+CONFIG_HID_GEMBIRD=m
-+CONFIG_HID_HOLTEK=m
-+CONFIG_HID_KEYTOUCH=m
-+CONFIG_HID_KYE=m
-+CONFIG_HID_UCLOGIC=m
-+CONFIG_HID_WALTOP=m
-+CONFIG_HID_GYRATION=m
-+CONFIG_HID_TWINHAN=m
-+CONFIG_HID_KENSINGTON=m
-+CONFIG_HID_LCPOWER=m
-+CONFIG_HID_LOGITECH=m
-+CONFIG_HID_LOGITECH_DJ=m
-+CONFIG_LOGITECH_FF=y
-+CONFIG_LOGIRUMBLEPAD2_FF=y
-+CONFIG_LOGIG940_FF=y
-+CONFIG_HID_MAGICMOUSE=m
-+CONFIG_HID_MICROSOFT=m
-+CONFIG_HID_MONTEREY=m
-+CONFIG_HID_MULTITOUCH=m
-+CONFIG_HID_NTRIG=m
-+CONFIG_HID_ORTEK=m
-+CONFIG_HID_PANTHERLORD=m
-+CONFIG_HID_PETALYNX=m
-+CONFIG_HID_PICOLCD=m
-+CONFIG_HID_ROCCAT=m
-+CONFIG_HID_SAMSUNG=m
-+CONFIG_HID_SONY=m
-+CONFIG_SONY_FF=y
-+CONFIG_HID_SPEEDLINK=m
-+CONFIG_HID_SUNPLUS=m
-+CONFIG_HID_GREENASIA=m
-+CONFIG_HID_SMARTJOYPLUS=m
-+CONFIG_HID_TOPSEED=m
-+CONFIG_HID_THINGM=m
-+CONFIG_HID_THRUSTMASTER=m
-+CONFIG_HID_WACOM=m
-+CONFIG_HID_WIIMOTE=m
-+CONFIG_HID_XINMO=m
-+CONFIG_HID_ZEROPLUS=m
-+CONFIG_HID_ZYDACRON=m
-+CONFIG_HID_PID=y
-+CONFIG_USB_HIDDEV=y
-+CONFIG_USB=y
-+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-+CONFIG_USB_MON=m
-+CONFIG_USB_XHCI_HCD=y
-+CONFIG_USB_DWCOTG=y
-+CONFIG_USB_PRINTER=m
-+CONFIG_USB_STORAGE=y
-+CONFIG_USB_STORAGE_REALTEK=m
-+CONFIG_USB_STORAGE_DATAFAB=m
-+CONFIG_USB_STORAGE_FREECOM=m
-+CONFIG_USB_STORAGE_ISD200=m
-+CONFIG_USB_STORAGE_USBAT=m
-+CONFIG_USB_STORAGE_SDDR09=m
-+CONFIG_USB_STORAGE_SDDR55=m
-+CONFIG_USB_STORAGE_JUMPSHOT=m
-+CONFIG_USB_STORAGE_ALAUDA=m
-+CONFIG_USB_STORAGE_ONETOUCH=m
-+CONFIG_USB_STORAGE_KARMA=m
-+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
-+CONFIG_USB_STORAGE_ENE_UB6250=m
-+CONFIG_USB_MDC800=m
-+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
-+CONFIG_USB_SERIAL_ARK3116=m
-+CONFIG_USB_SERIAL_BELKIN=m
-+CONFIG_USB_SERIAL_CH341=m
-+CONFIG_USB_SERIAL_WHITEHEAT=m
-+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
-+CONFIG_USB_SERIAL_CP210X=m
-+CONFIG_USB_SERIAL_CYPRESS_M8=m
-+CONFIG_USB_SERIAL_EMPEG=m
-+CONFIG_USB_SERIAL_FTDI_SIO=m
-+CONFIG_USB_SERIAL_VISOR=m
-+CONFIG_USB_SERIAL_IPAQ=m
-+CONFIG_USB_SERIAL_IR=m
-+CONFIG_USB_SERIAL_EDGEPORT=m
-+CONFIG_USB_SERIAL_EDGEPORT_TI=m
-+CONFIG_USB_SERIAL_F81232=m
-+CONFIG_USB_SERIAL_GARMIN=m
-+CONFIG_USB_SERIAL_IPW=m
-+CONFIG_USB_SERIAL_IUU=m
-+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
-+CONFIG_USB_SERIAL_KEYSPAN=m
-+CONFIG_USB_SERIAL_KLSI=m
-+CONFIG_USB_SERIAL_KOBIL_SCT=m
-+CONFIG_USB_SERIAL_MCT_U232=m
-+CONFIG_USB_SERIAL_METRO=m
-+CONFIG_USB_SERIAL_MOS7720=m
-+CONFIG_USB_SERIAL_MOS7840=m
-+CONFIG_USB_SERIAL_NAVMAN=m
-+CONFIG_USB_SERIAL_PL2303=m
-+CONFIG_USB_SERIAL_OTI6858=m
-+CONFIG_USB_SERIAL_QCAUX=m
-+CONFIG_USB_SERIAL_QUALCOMM=m
-+CONFIG_USB_SERIAL_SPCP8X5=m
-+CONFIG_USB_SERIAL_SAFE=m
-+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
-+CONFIG_USB_SERIAL_SYMBOL=m
-+CONFIG_USB_SERIAL_TI=m
-+CONFIG_USB_SERIAL_CYBERJACK=m
-+CONFIG_USB_SERIAL_XIRCOM=m
-+CONFIG_USB_SERIAL_OPTION=m
-+CONFIG_USB_SERIAL_OMNINET=m
-+CONFIG_USB_SERIAL_OPTICON=m
-+CONFIG_USB_SERIAL_XSENS_MT=m
-+CONFIG_USB_SERIAL_WISHBONE=m
-+CONFIG_USB_SERIAL_SSU100=m
-+CONFIG_USB_SERIAL_QT2=m
-+CONFIG_USB_SERIAL_DEBUG=m
-+CONFIG_USB_EMI62=m
-+CONFIG_USB_EMI26=m
-+CONFIG_USB_ADUTUX=m
-+CONFIG_USB_SEVSEG=m
-+CONFIG_USB_RIO500=m
-+CONFIG_USB_LEGOTOWER=m
-+CONFIG_USB_LCD=m
-+CONFIG_USB_CYPRESS_CY7C63=m
-+CONFIG_USB_CYTHERM=m
-+CONFIG_USB_IDMOUSE=m
-+CONFIG_USB_FTDI_ELAN=m
-+CONFIG_USB_APPLEDISPLAY=m
-+CONFIG_USB_LD=m
-+CONFIG_USB_TRANCEVIBRATOR=m
-+CONFIG_USB_IOWARRIOR=m
-+CONFIG_USB_TEST=m
-+CONFIG_USB_ISIGHTFW=m
-+CONFIG_USB_YUREX=m
-+CONFIG_USB_ATM=m
-+CONFIG_USB_SPEEDTOUCH=m
-+CONFIG_USB_CXACRU=m
-+CONFIG_USB_UEAGLEATM=m
-+CONFIG_USB_XUSBATM=m
-+CONFIG_USB_GADGET=m
-+CONFIG_USB_ZERO=m
-+CONFIG_USB_AUDIO=m
-+CONFIG_USB_ETH=m
-+CONFIG_USB_GADGETFS=m
-+CONFIG_USB_MASS_STORAGE=m
-+CONFIG_USB_G_SERIAL=m
-+CONFIG_USB_MIDI_GADGET=m
-+CONFIG_USB_G_PRINTER=m
-+CONFIG_USB_CDC_COMPOSITE=m
-+CONFIG_USB_G_ACM_MS=m
-+CONFIG_USB_G_MULTI=m
-+CONFIG_USB_G_HID=m
-+CONFIG_USB_G_WEBCAM=m
-+CONFIG_MMC=y
-+CONFIG_MMC_BLOCK_MINORS=32
-+CONFIG_MMC_SDHCI_BCM2711=y
-+CONFIG_MMC_BCM2835_MMC=y
-+CONFIG_MMC_BCM2835_DMA=y
-+CONFIG_MMC_BCM2835_SDHOST=y
-+CONFIG_MMC_SDHCI=y
-+CONFIG_MMC_SDHCI_PLTFM=y
-+CONFIG_MMC_SPI=m
-+CONFIG_LEDS_CLASS=y
-+CONFIG_LEDS_GPIO=y
-+CONFIG_LEDS_TRIGGER_TIMER=y
-+CONFIG_LEDS_TRIGGER_ONESHOT=y
-+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
-+CONFIG_LEDS_TRIGGER_CPU=y
-+CONFIG_LEDS_TRIGGER_GPIO=y
-+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-+CONFIG_LEDS_TRIGGER_TRANSIENT=m
-+CONFIG_LEDS_TRIGGER_CAMERA=m
-+CONFIG_LEDS_TRIGGER_INPUT=y
-+CONFIG_LEDS_TRIGGER_PANIC=y
-+CONFIG_RTC_CLASS=y
-+# CONFIG_RTC_HCTOSYS is not set
-+CONFIG_RTC_DRV_ABX80X=m
-+CONFIG_RTC_DRV_DS1307=m
-+CONFIG_RTC_DRV_DS1374=m
-+CONFIG_RTC_DRV_DS1672=m
-+CONFIG_RTC_DRV_MAX6900=m
-+CONFIG_RTC_DRV_RS5C372=m
-+CONFIG_RTC_DRV_ISL1208=m
-+CONFIG_RTC_DRV_ISL12022=m
-+CONFIG_RTC_DRV_X1205=m
-+CONFIG_RTC_DRV_PCF8523=m
-+CONFIG_RTC_DRV_PCF8563=m
-+CONFIG_RTC_DRV_PCF8583=m
-+CONFIG_RTC_DRV_M41T80=m
-+CONFIG_RTC_DRV_BQ32K=m
-+CONFIG_RTC_DRV_S35390A=m
-+CONFIG_RTC_DRV_FM3130=m
-+CONFIG_RTC_DRV_RX8581=m
-+CONFIG_RTC_DRV_RX8025=m
-+CONFIG_RTC_DRV_EM3027=m
-+CONFIG_RTC_DRV_M41T93=m
-+CONFIG_RTC_DRV_M41T94=m
-+CONFIG_RTC_DRV_DS1302=m
-+CONFIG_RTC_DRV_DS1305=m
-+CONFIG_RTC_DRV_DS1390=m
-+CONFIG_RTC_DRV_R9701=m
-+CONFIG_RTC_DRV_RX4581=m
-+CONFIG_RTC_DRV_RS5C348=m
-+CONFIG_RTC_DRV_MAX6902=m
-+CONFIG_RTC_DRV_PCF2123=m
-+CONFIG_RTC_DRV_DS3232=m
-+CONFIG_RTC_DRV_PCF2127=m
-+CONFIG_RTC_DRV_RV3029C2=m
-+CONFIG_DMADEVICES=y
-+CONFIG_DMA_BCM2835=y
-+CONFIG_DMA_BCM2708=y
-+CONFIG_UIO=m
-+CONFIG_UIO_PDRV_GENIRQ=m
-+CONFIG_STAGING=y
-+CONFIG_PRISM2_USB=m
-+CONFIG_R8712U=m
-+CONFIG_R8188EU=m
-+CONFIG_VT6656=m
-+CONFIG_SPEAKUP=m
-+CONFIG_SPEAKUP_SYNTH_SOFT=m
-+CONFIG_STAGING_MEDIA=y
-+CONFIG_FB_TFT=m
-+CONFIG_FB_TFT_AGM1264K_FL=m
-+CONFIG_FB_TFT_BD663474=m
-+CONFIG_FB_TFT_HX8340BN=m
-+CONFIG_FB_TFT_HX8347D=m
-+CONFIG_FB_TFT_HX8353D=m
-+CONFIG_FB_TFT_HX8357D=m
-+CONFIG_FB_TFT_ILI9163=m
-+CONFIG_FB_TFT_ILI9320=m
-+CONFIG_FB_TFT_ILI9325=m
-+CONFIG_FB_TFT_ILI9340=m
-+CONFIG_FB_TFT_ILI9341=m
-+CONFIG_FB_TFT_ILI9481=m
-+CONFIG_FB_TFT_ILI9486=m
-+CONFIG_FB_TFT_PCD8544=m
-+CONFIG_FB_TFT_RA8875=m
-+CONFIG_FB_TFT_S6D02A1=m
-+CONFIG_FB_TFT_S6D1121=m
-+CONFIG_FB_TFT_SSD1289=m
-+CONFIG_FB_TFT_SSD1306=m
-+CONFIG_FB_TFT_SSD1331=m
-+CONFIG_FB_TFT_SSD1351=m
-+CONFIG_FB_TFT_ST7735R=m
-+CONFIG_FB_TFT_ST7789V=m
-+CONFIG_FB_TFT_TINYLCD=m
-+CONFIG_FB_TFT_TLS8204=m
-+CONFIG_FB_TFT_UC1701=m
-+CONFIG_FB_TFT_UPD161704=m
-+CONFIG_FB_TFT_WATTEROTT=m
-+CONFIG_FB_FLEX=m
-+CONFIG_FB_TFT_FBTFT_DEVICE=m
-+CONFIG_SND_BCM2835=m
-+CONFIG_VIDEO_BCM2835=m
-+CONFIG_MAILBOX=y
-+CONFIG_BCM2835_MBOX=y
-+# CONFIG_IOMMU_SUPPORT is not set
-+CONFIG_RASPBERRYPI_POWER=y
-+CONFIG_EXTCON=m
-+CONFIG_EXTCON_ARIZONA=m
-+CONFIG_IIO=m
-+CONFIG_IIO_BUFFER_CB=m
-+CONFIG_MCP320X=m
-+CONFIG_MCP3422=m
-+CONFIG_DHT11=m
-+CONFIG_HDC100X=m
-+CONFIG_HTU21=m
-+CONFIG_TSL4531=m
-+CONFIG_VEML6070=m
-+CONFIG_BMP280=m
-+CONFIG_PWM_BCM2835=m
-+CONFIG_PWM_PCA9685=m
-+CONFIG_GENERIC_PHY=y
-+CONFIG_RPI_AXIPERF=m
-+CONFIG_EXT4_FS=y
-+CONFIG_EXT4_FS_POSIX_ACL=y
-+CONFIG_EXT4_FS_SECURITY=y
-+CONFIG_REISERFS_FS=m
-+CONFIG_REISERFS_FS_XATTR=y
-+CONFIG_REISERFS_FS_POSIX_ACL=y
-+CONFIG_REISERFS_FS_SECURITY=y
-+CONFIG_JFS_FS=m
-+CONFIG_JFS_POSIX_ACL=y
-+CONFIG_JFS_SECURITY=y
-+CONFIG_JFS_STATISTICS=y
-+CONFIG_XFS_FS=m
-+CONFIG_XFS_QUOTA=y
-+CONFIG_XFS_POSIX_ACL=y
-+CONFIG_XFS_RT=y
-+CONFIG_GFS2_FS=m
-+CONFIG_OCFS2_FS=m
-+CONFIG_BTRFS_FS=m
-+CONFIG_BTRFS_FS_POSIX_ACL=y
-+CONFIG_NILFS2_FS=m
-+CONFIG_F2FS_FS=y
-+CONFIG_FANOTIFY=y
-+CONFIG_QFMT_V1=m
-+CONFIG_QFMT_V2=m
-+CONFIG_AUTOFS4_FS=y
-+CONFIG_FUSE_FS=m
-+CONFIG_CUSE=m
-+CONFIG_OVERLAY_FS=m
-+CONFIG_FSCACHE=y
-+CONFIG_FSCACHE_STATS=y
-+CONFIG_FSCACHE_HISTOGRAM=y
-+CONFIG_CACHEFILES=y
-+CONFIG_ISO9660_FS=m
-+CONFIG_JOLIET=y
-+CONFIG_ZISOFS=y
-+CONFIG_UDF_FS=m
-+CONFIG_MSDOS_FS=y
-+CONFIG_VFAT_FS=y
-+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
-+CONFIG_NTFS_FS=m
-+CONFIG_NTFS_RW=y
-+CONFIG_TMPFS=y
-+CONFIG_TMPFS_POSIX_ACL=y
-+CONFIG_ECRYPT_FS=m
-+CONFIG_HFS_FS=m
-+CONFIG_HFSPLUS_FS=m
-+CONFIG_JFFS2_FS=m
-+CONFIG_JFFS2_SUMMARY=y
-+CONFIG_UBIFS_FS=m
-+CONFIG_SQUASHFS=m
-+CONFIG_SQUASHFS_XATTR=y
-+CONFIG_SQUASHFS_LZO=y
-+CONFIG_SQUASHFS_XZ=y
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3_ACL=y
-+CONFIG_NFS_V4=y
-+CONFIG_NFS_SWAP=y
-+CONFIG_NFS_V4_1=y
-+CONFIG_ROOT_NFS=y
-+CONFIG_NFS_FSCACHE=y
-+CONFIG_NFSD=m
-+CONFIG_NFSD_V3_ACL=y
-+CONFIG_NFSD_V4=y
-+CONFIG_CIFS=m
-+CONFIG_CIFS_WEAK_PW_HASH=y
-+CONFIG_CIFS_UPCALL=y
-+CONFIG_CIFS_XATTR=y
-+CONFIG_CIFS_POSIX=y
-+CONFIG_CIFS_ACL=y
-+CONFIG_CIFS_DFS_UPCALL=y
-+CONFIG_CIFS_FSCACHE=y
-+CONFIG_9P_FS=m
-+CONFIG_9P_FS_POSIX_ACL=y
-+CONFIG_NLS_DEFAULT="utf8"
-+CONFIG_NLS_CODEPAGE_437=y
-+CONFIG_NLS_CODEPAGE_737=m
-+CONFIG_NLS_CODEPAGE_775=m
-+CONFIG_NLS_CODEPAGE_850=m
-+CONFIG_NLS_CODEPAGE_852=m
-+CONFIG_NLS_CODEPAGE_855=m
-+CONFIG_NLS_CODEPAGE_857=m
-+CONFIG_NLS_CODEPAGE_860=m
-+CONFIG_NLS_CODEPAGE_861=m
-+CONFIG_NLS_CODEPAGE_862=m
-+CONFIG_NLS_CODEPAGE_863=m
-+CONFIG_NLS_CODEPAGE_864=m
-+CONFIG_NLS_CODEPAGE_865=m
-+CONFIG_NLS_CODEPAGE_866=m
-+CONFIG_NLS_CODEPAGE_869=m
-+CONFIG_NLS_CODEPAGE_936=m
-+CONFIG_NLS_CODEPAGE_950=m
-+CONFIG_NLS_CODEPAGE_932=m
-+CONFIG_NLS_CODEPAGE_949=m
-+CONFIG_NLS_CODEPAGE_874=m
-+CONFIG_NLS_ISO8859_8=m
-+CONFIG_NLS_CODEPAGE_1250=m
-+CONFIG_NLS_CODEPAGE_1251=m
-+CONFIG_NLS_ASCII=y
-+CONFIG_NLS_ISO8859_1=m
-+CONFIG_NLS_ISO8859_2=m
-+CONFIG_NLS_ISO8859_3=m
-+CONFIG_NLS_ISO8859_4=m
-+CONFIG_NLS_ISO8859_5=m
-+CONFIG_NLS_ISO8859_6=m
-+CONFIG_NLS_ISO8859_7=m
-+CONFIG_NLS_ISO8859_9=m
-+CONFIG_NLS_ISO8859_13=m
-+CONFIG_NLS_ISO8859_14=m
-+CONFIG_NLS_ISO8859_15=m
-+CONFIG_NLS_KOI8_R=m
-+CONFIG_NLS_KOI8_U=m
-+CONFIG_DLM=m
-+CONFIG_CRYPTO_USER=m
-+CONFIG_CRYPTO_CBC=y
-+CONFIG_CRYPTO_CTS=m
-+CONFIG_CRYPTO_XTS=m
-+CONFIG_CRYPTO_XCBC=m
-+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_CRC_ITU_T=y
-+CONFIG_LIBCRC32C=y
-+CONFIG_PRINTK_TIME=y
-+CONFIG_BOOT_PRINTK_DELAY=y
-+CONFIG_DEBUG_MEMORY_INIT=y
-+CONFIG_DETECT_HUNG_TASK=y
-+CONFIG_LATENCYTOP=y
-+CONFIG_IRQSOFF_TRACER=y
-+CONFIG_SCHED_TRACER=y
-+CONFIG_STACK_TRACER=y
-+CONFIG_BLK_DEV_IO_TRACE=y
-+CONFIG_FUNCTION_PROFILER=y
-+CONFIG_KGDB=y
-+CONFIG_KGDB_KDB=y
-+CONFIG_KDB_KEYBOARD=y
--- /dev/null
+From 9cef5f2288b06b4c3caa157e33345c2938c57a15 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 6 Feb 2019 20:45:16 +0000
+Subject: [PATCH 645/725] arm: dts: Change downstream vchiq compatible string
+
+The new cache line size mechanism requires a different vchiq compatible
+string on BCM2836 and BCM2837, but the downstream dts files didn't
+inherit the upstream changes.
+
+See: https://github.com/raspberrypi/linux/issues/2643
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2708-rpi.dtsi | 2 +-
+ arch/arm/boot/dts/bcm2709-rpi.dtsi | 5 +++++
+ arch/arm/boot/dts/bcm2709.dtsi | 2 +-
+ arch/arm/boot/dts/bcm2710.dtsi | 2 +-
+ 4 files changed, 8 insertions(+), 3 deletions(-)
+ create mode 100644 arch/arm/boot/dts/bcm2709-rpi.dtsi
+
+--- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
+@@ -68,7 +68,7 @@
+ status = "disabled";
+ };
+
+- mailbox@7e00b840 {
++ vchiq: mailbox@7e00b840 {
+ compatible = "brcm,bcm2835-vchiq";
+ reg = <0x7e00b840 0x3c>;
+ interrupts = <0 2>;
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2709-rpi.dtsi
+@@ -0,0 +1,5 @@
++#include "bcm2708-rpi.dtsi"
++
++&vchiq {
++ compatible = "brcm,bcm2836-vchiq", "brcm,bcm2835-vchiq";
++};
+--- a/arch/arm/boot/dts/bcm2709.dtsi
++++ b/arch/arm/boot/dts/bcm2709.dtsi
+@@ -1,6 +1,6 @@
+ #include "bcm2836.dtsi"
+ #include "bcm270x.dtsi"
+-#include "bcm2708-rpi.dtsi"
++#include "bcm2709-rpi.dtsi"
+
+ / {
+ soc {
+--- a/arch/arm/boot/dts/bcm2710.dtsi
++++ b/arch/arm/boot/dts/bcm2710.dtsi
+@@ -1,6 +1,6 @@
+ #include "bcm2837.dtsi"
+ #include "bcm270x.dtsi"
+-#include "bcm2708-rpi.dtsi"
++#include "bcm2709-rpi.dtsi"
+
+ / {
+ compatible = "brcm,bcm2837", "brcm,bcm2836";
--- /dev/null
+From 41cb4ad3f7327869dabc733cceb3a9273eda346d Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 4 Apr 2019 13:33:47 +0100
+Subject: [PATCH 646/725] bcm2835-dma: Add proper 40-bit DMA support
+
+The 40-bit additions are not fully tested, but it should be
+capable of supporting both 40-bit memcpy on BCM2711 and regular
+Lite channels on BCM2835.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2838.dtsi | 33 +-
+ drivers/dma/bcm2835-dma.c | 426 ++++++++++++++-----
+ drivers/pci/controller/pcie-brcmstb-bounce.c | 30 +-
+ drivers/pci/controller/pcie-brcmstb-bounce.h | 21 +-
+ drivers/pci/controller/pcie-brcmstb.c | 23 +-
+ 5 files changed, 395 insertions(+), 138 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -372,6 +372,23 @@
+ };
+ };
+
++ dma40: dma@7e007b00 {
++ compatible = "brcm,bcm2838-dma";
++ reg = <0x0 0x7e007b00 0x400>;
++ interrupts =
++ <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, /* dma4 11 */
++ <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, /* dma4 12 */
++ <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, /* dma4 13 */
++ <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; /* dma4 14 */
++ interrupt-names = "dma11",
++ "dma12",
++ "dma13",
++ "dma14";
++ #dma-cells = <1>;
++ brcm,dma-channel-mask = <0x7000>;
++ };
++ /* DMA4 - 40 bit DMA engines */
++
+ xhci: xhci@7e9c0000 {
+ compatible = "generic-xhci";
+ status = "disabled";
+@@ -689,6 +706,7 @@
+ };
+
+ &dma {
++ reg = <0x7e007000 0xb00>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
+@@ -699,12 +717,7 @@
+ <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 7 */
+ <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 8 */
+ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 9 */
+- <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 10 */
+- /* DMA4 - 40 bit DMA engines */
+- <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, /* dma4 11 */
+- <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, /* dma4 12 */
+- <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, /* dma4 13 */
+- <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; /* dma4 14 */
++ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>; /* dmalite 10 */
+ interrupt-names = "dma0",
+ "dma1",
+ "dma2",
+@@ -715,10 +728,6 @@
+ "dma7",
+ "dma8",
+ "dma9",
+- "dma10",
+- "dma11",
+- "dma12",
+- "dma13",
+- "dma14";
+- brcm,dma-channel-mask = <0x7ef5>;
++ "dma10";
++ brcm,dma-channel-mask = <0x01f5>;
+ };
+--- a/drivers/dma/bcm2835-dma.c
++++ b/drivers/dma/bcm2835-dma.c
+@@ -50,12 +50,18 @@
+ #define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14
+ #define BCM2835_DMA_CHAN_NAME_SIZE 8
+ #define BCM2835_DMA_BULK_MASK BIT(0)
++#define BCM2838_DMA_MEMCPY_CHAN 14
++
++struct bcm2835_dma_cfg_data {
++ u32 chan_40bit_mask;
++};
+
+ struct bcm2835_dmadev {
+ struct dma_device ddev;
+ spinlock_t lock;
+ void __iomem *base;
+ struct device_dma_parameters dma_parms;
++ const struct bcm2835_dma_cfg_data *cfg_data;
+ };
+
+ struct bcm2835_dma_cb {
+@@ -100,6 +106,7 @@ struct bcm2835_chan {
+ unsigned int irq_flags;
+
+ bool is_lite_channel;
++ bool is_40bit_channel;
+ };
+
+ struct bcm2835_desc {
+@@ -189,7 +196,8 @@ struct bcm2835_desc {
+ #define BCM2835_DMA_DATA_TYPE_S128 16
+
+ /* Valid only for channels 0 - 14, 15 has its own base address */
+-#define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */
++#define BCM2835_DMA_CHAN_SIZE 0x100
++#define BCM2835_DMA_CHAN(n) ((n) * BCM2835_DMA_CHAN_SIZE) /* Base address */
+ #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n))
+
+ /* the max dma length for different channels */
+@@ -200,7 +208,7 @@ struct bcm2835_desc {
+ #define BCM2838_DMA40_CS 0x00
+ #define BCM2838_DMA40_CB 0x04
+ #define BCM2838_DMA40_DEBUG 0x0c
+-#define BCM2858_DMA40_TI 0x10
++#define BCM2838_DMA40_TI 0x10
+ #define BCM2838_DMA40_SRC 0x14
+ #define BCM2838_DMA40_SRCI 0x18
+ #define BCM2838_DMA40_DEST 0x1c
+@@ -209,32 +217,97 @@ struct bcm2835_desc {
+ #define BCM2838_DMA40_NEXT_CB 0x28
+ #define BCM2838_DMA40_DEBUG2 0x2c
+
+-#define BCM2838_DMA40_CS_ACTIVE BIT(0)
+-#define BCM2838_DMA40_CS_END BIT(1)
++#define BCM2838_DMA40_ACTIVE BIT(0)
++#define BCM2838_DMA40_END BIT(1)
++#define BCM2838_DMA40_INT BIT(2)
++#define BCM2838_DMA40_DREQ BIT(3) /* DREQ state */
++#define BCM2838_DMA40_RD_PAUSED BIT(4) /* Reading is paused */
++#define BCM2838_DMA40_WR_PAUSED BIT(5) /* Writing is paused */
++#define BCM2838_DMA40_DREQ_PAUSED BIT(6) /* Is paused by DREQ flow control */
++#define BCM2838_DMA40_WAITING_FOR_WRITES BIT(7) /* Waiting for last write */
++#define BCM2838_DMA40_ERR BIT(10)
++#define BCM2838_DMA40_QOS(x) (((x) & 0x1f) << 16)
++#define BCM2838_DMA40_PANIC_QOS(x) (((x) & 0x1f) << 20)
++#define BCM2838_DMA40_WAIT_FOR_WRITES BIT(28)
++#define BCM2838_DMA40_DISDEBUG BIT(29)
++#define BCM2838_DMA40_ABORT BIT(30)
++#define BCM2838_DMA40_HALT BIT(31)
++#define BCM2838_DMA40_CS_FLAGS(x) (x & (BCM2838_DMA40_QOS(15) | \
++ BCM2838_DMA40_PANIC_QOS(15) | \
++ BCM2838_DMA40_WAIT_FOR_WRITES | \
++ BCM2838_DMA40_DISDEBUG))
++
++/* Transfer information bits */
++#define BCM2838_DMA40_INTEN BIT(0)
++#define BCM2838_DMA40_TDMODE BIT(1) /* 2D-Mode */
++#define BCM2838_DMA40_WAIT_RESP BIT(2) /* wait for AXI write to be acked */
++#define BCM2838_DMA40_WAIT_RD_RESP BIT(3) /* wait for AXI read to complete */
++#define BCM2838_DMA40_PER_MAP(x) ((x & 31) << 9) /* REQ source */
++#define BCM2838_DMA40_S_DREQ BIT(14) /* enable SREQ for source */
++#define BCM2838_DMA40_D_DREQ BIT(15) /* enable DREQ for destination */
++#define BCM2838_DMA40_S_WAIT(x) ((x & 0xff) << 16) /* add DMA read-wait cycles */
++#define BCM2838_DMA40_D_WAIT(x) ((x & 0xff) << 24) /* add DMA write-wait cycles */
+
+-#define BCM2838_DMA40_CS_QOS(x) (((x) & 0x1f) << 16)
+-#define BCM2838_DMA40_CS_PANIC_QOS(x) (((x) & 0x1f) << 20)
+-#define BCM2838_DMA40_CS_WRITE_WAIT BIT(28)
++/* debug register bits */
++#define BCM2838_DMA40_DEBUG_WRITE_ERR BIT(0)
++#define BCM2838_DMA40_DEBUG_FIFO_ERR BIT(1)
++#define BCM2838_DMA40_DEBUG_READ_ERR BIT(2)
++#define BCM2838_DMA40_DEBUG_READ_CB_ERR BIT(3)
++#define BCM2838_DMA40_DEBUG_IN_ON_ERR BIT(8)
++#define BCM2838_DMA40_DEBUG_ABORT_ON_ERR BIT(9)
++#define BCM2838_DMA40_DEBUG_HALT_ON_ERR BIT(10)
++#define BCM2838_DMA40_DEBUG_DISABLE_CLK_GATE BIT(11)
++#define BCM2838_DMA40_DEBUG_RSTATE_SHIFT 14
++#define BCM2838_DMA40_DEBUG_RSTATE_BITS 4
++#define BCM2838_DMA40_DEBUG_WSTATE_SHIFT 18
++#define BCM2838_DMA40_DEBUG_WSTATE_BITS 4
++#define BCM2838_DMA40_DEBUG_RESET BIT(23)
++#define BCM2838_DMA40_DEBUG_ID_SHIFT 24
++#define BCM2838_DMA40_DEBUG_ID_BITS 4
++#define BCM2838_DMA40_DEBUG_VERSION_SHIFT 28
++#define BCM2838_DMA40_DEBUG_VERSION_BITS 4
++
++/* Valid only for channels 0 - 3 (11 - 14) */
++#define BCM2838_DMA40_CHAN(n) (((n) + 11) << 8) /* Base address */
++#define BCM2838_DMA40_CHANIO(base, n) ((base) + BCM2838_DMA_CHAN(n))
+
+-#define BCM2838_DMA40_BURST_LEN(x) ((((x) - 1) & 0xf) << 8)
+-#define BCM2838_DMA40_INC BIT(12)
+-#define BCM2838_DMA40_SIZE_128 (2 << 13)
++/* the max dma length for different channels */
++#define MAX_DMA40_LEN SZ_1G
+
+-#define BCM2838_DMA40_MEMCPY_QOS \
+- (BCM2838_DMA40_CS_QOS(0x0) | \
+- BCM2838_DMA40_CS_PANIC_QOS(0x0) | \
+- BCM2838_DMA40_CS_WRITE_WAIT)
++#define BCM2838_DMA40_BURST_LEN(x) ((min(x,16) - 1) << 8)
++#define BCM2838_DMA40_INC BIT(12)
++#define BCM2838_DMA40_SIZE_32 (0 << 13)
++#define BCM2838_DMA40_SIZE_64 (1 << 13)
++#define BCM2838_DMA40_SIZE_128 (2 << 13)
++#define BCM2838_DMA40_SIZE_256 (3 << 13)
++#define BCM2838_DMA40_IGNORE BIT(15)
++#define BCM2838_DMA40_STRIDE(x) ((x) << 16) /* For 2D mode */
++
++#define BCM2838_DMA40_MEMCPY_FLAGS \
++ (BCM2838_DMA40_QOS(0) | \
++ BCM2838_DMA40_PANIC_QOS(0) | \
++ BCM2838_DMA40_WAIT_FOR_WRITES | \
++ BCM2838_DMA40_DISDEBUG)
+
+ #define BCM2838_DMA40_MEMCPY_XFER_INFO \
+ (BCM2838_DMA40_SIZE_128 | \
+ BCM2838_DMA40_INC | \
+ BCM2838_DMA40_BURST_LEN(16))
+
++struct bcm2835_dmadev *memcpy_parent;
+ static void __iomem *memcpy_chan;
+ static struct bcm2838_dma40_scb *memcpy_scb;
+ static dma_addr_t memcpy_scb_dma;
+ DEFINE_SPINLOCK(memcpy_lock);
+
++static const struct bcm2835_dma_cfg_data bcm2835_dma_cfg = {
++ .chan_40bit_mask = 0,
++};
++
++static const struct bcm2835_dma_cfg_data bcm2838_dma_cfg = {
++ .chan_40bit_mask = BIT(11) | BIT(12) | BIT(13) | BIT(14),
++};
++
+ static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c)
+ {
+ /* lite and normal channels have different max frame length */
+@@ -264,6 +337,32 @@ static inline struct bcm2835_desc *to_bc
+ return container_of(t, struct bcm2835_desc, vd.tx);
+ }
+
++static inline uint32_t to_bcm2838_ti(uint32_t info)
++{
++ return ((info & BCM2835_DMA_INT_EN) ? BCM2838_DMA40_INTEN : 0) |
++ ((info & BCM2835_DMA_WAIT_RESP) ? BCM2838_DMA40_WAIT_RESP : 0) |
++ ((info & BCM2835_DMA_S_DREQ) ?
++ (BCM2838_DMA40_S_DREQ | BCM2838_DMA40_WAIT_RD_RESP) : 0) |
++ ((info & BCM2835_DMA_D_DREQ) ? BCM2838_DMA40_D_DREQ : 0) |
++ BCM2838_DMA40_PER_MAP((info >> 16) & 0x1f);
++}
++
++static inline uint32_t to_bcm2838_srci(uint32_t info)
++{
++ return ((info & BCM2835_DMA_S_INC) ? BCM2838_DMA40_INC : 0);
++}
++
++static inline uint32_t to_bcm2838_dsti(uint32_t info)
++{
++ return ((info & BCM2835_DMA_D_INC) ? BCM2838_DMA40_INC : 0);
++}
++
++static inline uint32_t to_bcm2838_cbaddr(dma_addr_t addr)
++{
++ BUG_ON(addr & 0x1f);
++ return (addr >> 5);
++}
++
+ static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc)
+ {
+ size_t i;
+@@ -282,45 +381,53 @@ static void bcm2835_dma_desc_free(struct
+ }
+
+ static void bcm2835_dma_create_cb_set_length(
+- struct bcm2835_chan *chan,
++ struct bcm2835_chan *c,
+ struct bcm2835_dma_cb *control_block,
+ size_t len,
+ size_t period_len,
+ size_t *total_len,
+ u32 finalextrainfo)
+ {
+- size_t max_len = bcm2835_dma_max_frame_length(chan);
++ size_t max_len = bcm2835_dma_max_frame_length(c);
++ uint32_t cb_len;
+
+ /* set the length taking lite-channel limitations into account */
+- control_block->length = min_t(u32, len, max_len);
++ cb_len = min_t(u32, len, max_len);
+
+- /* finished if we have no period_length */
+- if (!period_len)
+- return;
++ if (period_len) {
++ /*
++ * period_len means: that we need to generate
++ * transfers that are terminating at every
++ * multiple of period_len - this is typically
++ * used to set the interrupt flag in info
++ * which is required during cyclic transfers
++ */
+
+- /*
+- * period_len means: that we need to generate
+- * transfers that are terminating at every
+- * multiple of period_len - this is typically
+- * used to set the interrupt flag in info
+- * which is required during cyclic transfers
+- */
++ /* have we filled in period_length yet? */
++ if (*total_len + cb_len < period_len) {
++ /* update number of bytes in this period so far */
++ *total_len += cb_len;
++ } else {
++ /* calculate the length that remains to reach period_len */
++ cb_len = period_len - *total_len;
+
+- /* have we filled in period_length yet? */
+- if (*total_len + control_block->length < period_len) {
+- /* update number of bytes in this period so far */
+- *total_len += control_block->length;
+- return;
++ /* reset total_length for next period */
++ *total_len = 0;
++ }
+ }
+
+- /* calculate the length that remains to reach period_length */
+- control_block->length = period_len - *total_len;
+-
+- /* reset total_length for next period */
+- *total_len = 0;
+-
+- /* add extrainfo bits in info */
+- control_block->info |= finalextrainfo;
++ if (c->is_40bit_channel) {
++ struct bcm2838_dma40_scb *scb =
++ (struct bcm2838_dma40_scb *)control_block;
++
++ scb->len = cb_len;
++ /* add extrainfo bits to ti */
++ scb->ti |= to_bcm2838_ti(finalextrainfo);
++ } else {
++ control_block->length = cb_len;
++ /* add extrainfo bits to info */
++ control_block->info |= finalextrainfo;
++ }
+ }
+
+ static inline size_t bcm2835_dma_count_frames_for_sg(
+@@ -343,7 +450,7 @@ static inline size_t bcm2835_dma_count_f
+ /**
+ * bcm2835_dma_create_cb_chain - create a control block and fills data in
+ *
+- * @chan: the @dma_chan for which we run this
++ * @c: the @bcm2835_chan for which we run this
+ * @direction: the direction in which we transfer
+ * @cyclic: it is a cyclic transfer
+ * @info: the default info bits to apply per controlblock
+@@ -361,12 +468,11 @@ static inline size_t bcm2835_dma_count_f
+ * @gfp: the GFP flag to use for allocation
+ */
+ static struct bcm2835_desc *bcm2835_dma_create_cb_chain(
+- struct dma_chan *chan, enum dma_transfer_direction direction,
++ struct bcm2835_chan *c, enum dma_transfer_direction direction,
+ bool cyclic, u32 info, u32 finalextrainfo, size_t frames,
+ dma_addr_t src, dma_addr_t dst, size_t buf_len,
+ size_t period_len, gfp_t gfp)
+ {
+- struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+ size_t len = buf_len, total_len;
+ size_t frame;
+ struct bcm2835_desc *d;
+@@ -399,11 +505,23 @@ static struct bcm2835_desc *bcm2835_dma_
+
+ /* fill in the control block */
+ control_block = cb_entry->cb;
+- control_block->info = info;
+- control_block->src = src;
+- control_block->dst = dst;
+- control_block->stride = 0;
+- control_block->next = 0;
++ if (c->is_40bit_channel) {
++ struct bcm2838_dma40_scb *scb =
++ (struct bcm2838_dma40_scb *)control_block;
++ scb->ti = to_bcm2838_ti(info);
++ scb->src = lower_32_bits(src);
++ scb->srci= upper_32_bits(src) | to_bcm2838_srci(info);
++ scb->dst = lower_32_bits(dst);
++ scb->dsti = upper_32_bits(dst) | to_bcm2838_dsti(info);
++ scb->next_cb = 0;
++ } else {
++ control_block->info = info;
++ control_block->src = src;
++ control_block->dst = dst;
++ control_block->stride = 0;
++ control_block->next = 0;
++ }
++
+ /* set up length in control_block if requested */
+ if (buf_len) {
+ /* calculate length honoring period_length */
+@@ -417,7 +535,10 @@ static struct bcm2835_desc *bcm2835_dma_
+ }
+
+ /* link this the last controlblock */
+- if (frame)
++ if (frame && c->is_40bit_channel)
++ d->cb_list[frame - 1].cb->next =
++ to_bcm2838_cbaddr(cb_entry->paddr);
++ if (frame && !c->is_40bit_channel)
+ d->cb_list[frame - 1].cb->next = cb_entry->paddr;
+
+ /* update src and dst and length */
+@@ -431,7 +552,14 @@ static struct bcm2835_desc *bcm2835_dma_
+ }
+
+ /* the last frame requires extra flags */
+- d->cb_list[d->frames - 1].cb->info |= finalextrainfo;
++ if (c->is_40bit_channel) {
++ struct bcm2838_dma40_scb *scb =
++ (struct bcm2838_dma40_scb *)d->cb_list[d->frames-1].cb;
++
++ scb->ti |= to_bcm2838_ti(finalextrainfo);
++ } else {
++ d->cb_list[d->frames - 1].cb->info |= finalextrainfo;
++ }
+
+ /* detect a size missmatch */
+ if (buf_len && (d->size != buf_len))
+@@ -445,28 +573,51 @@ error_cb:
+ }
+
+ static void bcm2835_dma_fill_cb_chain_with_sg(
+- struct dma_chan *chan,
++ struct bcm2835_chan *c,
+ enum dma_transfer_direction direction,
+ struct bcm2835_cb_entry *cb,
+ struct scatterlist *sgl,
+ unsigned int sg_len)
+ {
+- struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+ size_t len, max_len;
+ unsigned int i;
+ dma_addr_t addr;
+ struct scatterlist *sgent;
+
++ pr_err("dma_fill_chain_with_sg(ch %d, dir %d):\n", c->ch, direction);
++
+ max_len = bcm2835_dma_max_frame_length(c);
+ for_each_sg(sgl, sgent, sg_len, i) {
+- for (addr = sg_dma_address(sgent), len = sg_dma_len(sgent);
+- len > 0;
+- addr += cb->cb->length, len -= cb->cb->length, cb++) {
+- if (direction == DMA_DEV_TO_MEM)
+- cb->cb->dst = addr;
+- else
+- cb->cb->src = addr;
+- cb->cb->length = min(len, max_len);
++ if (c->is_40bit_channel) {
++ struct bcm2838_dma40_scb *scb =
++ (struct bcm2838_dma40_scb *)cb->cb;
++ for (addr = sg_dma_address(sgent),
++ len = sg_dma_len(sgent);
++ len > 0;
++ addr += scb->len, len -= scb->len, scb++) {
++ if (direction == DMA_DEV_TO_MEM) {
++ scb->dst = lower_32_bits(addr);
++ scb->dsti = upper_32_bits(addr) | BCM2838_DMA40_INC;
++ } else {
++ scb->src = lower_32_bits(addr);
++ scb->srci = upper_32_bits(addr) | BCM2838_DMA40_INC;
++ }
++ scb->len = min(len, max_len);
++ pr_err(" %llx, %x\n", (u64)addr, scb->len);
++ }
++ } else {
++ for (addr = sg_dma_address(sgent),
++ len = sg_dma_len(sgent);
++ len > 0;
++ addr += cb->cb->length, len -= cb->cb->length,
++ cb++) {
++ if (direction == DMA_DEV_TO_MEM)
++ cb->cb->dst = addr;
++ else
++ cb->cb->src = addr;
++ cb->cb->length = min(len, max_len);
++ pr_err(" %llx, %x\n", (u64)addr, cb->cb->length);
++ }
+ }
+ }
+ }
+@@ -475,6 +626,10 @@ static int bcm2835_dma_abort(struct bcm2
+ {
+ void __iomem *chan_base = c->chan_base;
+ long int timeout = 10000;
++ u32 wait_mask = BCM2835_DMA_WAITING_FOR_WRITES;
++
++ if (c->is_40bit_channel)
++ wait_mask = BCM2838_DMA40_WAITING_FOR_WRITES;
+
+ /*
+ * A zero control block address means the channel is idle.
+@@ -487,8 +642,7 @@ static int bcm2835_dma_abort(struct bcm2
+ writel(0, chan_base + BCM2835_DMA_CS);
+
+ /* Wait for any current AXI transfer to complete */
+- while ((readl(chan_base + BCM2835_DMA_CS) &
+- BCM2835_DMA_WAITING_FOR_WRITES) && --timeout)
++ while ((readl(chan_base + BCM2835_DMA_CS) & wait_mask) && --timeout)
+ cpu_relax();
+
+ /* Peripheral might be stuck and fail to signal AXI write responses */
+@@ -505,6 +659,7 @@ static void bcm2835_dma_start_desc(struc
+ struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
+ struct bcm2835_desc *d;
+
++ pr_err("dma_start_desc(%px)\n", vd);
+ if (!vd) {
+ c->desc = NULL;
+ return;
+@@ -514,9 +669,16 @@ static void bcm2835_dma_start_desc(struc
+
+ c->desc = d = to_bcm2835_dma_desc(&vd->tx);
+
+- writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
+- writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq),
+- c->chan_base + BCM2835_DMA_CS);
++ if (c->is_40bit_channel) {
++ writel(to_bcm2838_cbaddr(d->cb_list[0].paddr),
++ c->chan_base + BCM2838_DMA40_CB);
++ writel(BCM2838_DMA40_ACTIVE | BCM2838_DMA40_CS_FLAGS(c->dreq),
++ c->chan_base + BCM2838_DMA40_CS);
++ } else {
++ writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
++ writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq),
++ c->chan_base + BCM2835_DMA_CS);
++ }
+ }
+
+ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
+@@ -544,7 +706,8 @@ static irqreturn_t bcm2835_dma_callback(
+ * will remain idle despite the ACTIVE flag being set.
+ */
+ writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE |
+- BCM2835_DMA_CS_FLAGS(c->dreq),
++ (c->is_40bit_channel ? BCM2838_DMA40_CS_FLAGS(c->dreq) :
++ BCM2835_DMA_CS_FLAGS(c->dreq)),
+ c->chan_base + BCM2835_DMA_CS);
+
+ d = c->desc;
+@@ -643,9 +806,17 @@ static enum dma_status bcm2835_dma_tx_st
+ struct bcm2835_desc *d = c->desc;
+ dma_addr_t pos;
+
+- if (d->dir == DMA_MEM_TO_DEV)
++ if (d->dir == DMA_MEM_TO_DEV && c->is_40bit_channel)
++ pos = readl(c->chan_base + BCM2838_DMA40_SRC) +
++ ((readl(c->chan_base + BCM2838_DMA40_SRCI) &
++ 0xff) << 8);
++ else if (d->dir == DMA_MEM_TO_DEV && !c->is_40bit_channel)
+ pos = readl(c->chan_base + BCM2835_DMA_SOURCE_AD);
+- else if (d->dir == DMA_DEV_TO_MEM)
++ else if (d->dir == DMA_DEV_TO_MEM && c->is_40bit_channel)
++ pos = readl(c->chan_base + BCM2838_DMA40_DEST) +
++ ((readl(c->chan_base + BCM2838_DMA40_DESTI) &
++ 0xff) << 8);
++ else if (d->dir == DMA_DEV_TO_MEM && !c->is_40bit_channel)
+ pos = readl(c->chan_base + BCM2835_DMA_DEST_AD);
+ else
+ pos = 0;
+@@ -691,7 +862,7 @@ static struct dma_async_tx_descriptor *b
+ frames = bcm2835_dma_frames_for_length(len, max_len);
+
+ /* allocate the CB chain - this also fills in the pointers */
+- d = bcm2835_dma_create_cb_chain(chan, DMA_MEM_TO_MEM, false,
++ d = bcm2835_dma_create_cb_chain(c, DMA_MEM_TO_MEM, false,
+ info, extra, frames,
+ src, dst, len, 0, GFP_KERNEL);
+ if (!d)
+@@ -726,11 +897,21 @@ static struct dma_async_tx_descriptor *b
+ if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
+ return NULL;
+ src = c->cfg.src_addr;
++ /*
++ * One would think it ought to be possible to get the physical
++ * to dma address mapping information from the dma-ranges DT
++ * property, but I've not found a way yet that doesn't involve
++ * open-coding the whole thing.
++ */
++ if (c->is_40bit_channel)
++ src |= 0x400000000ull;
+ info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC;
+ } else {
+ if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
+ return NULL;
+ dst = c->cfg.dst_addr;
++ if (c->is_40bit_channel)
++ dst |= 0x400000000ull;
+ info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC;
+ }
+
+@@ -738,7 +919,7 @@ static struct dma_async_tx_descriptor *b
+ frames = bcm2835_dma_count_frames_for_sg(c, sgl, sg_len);
+
+ /* allocate the CB chain */
+- d = bcm2835_dma_create_cb_chain(chan, direction, false,
++ d = bcm2835_dma_create_cb_chain(c, direction, false,
+ info, extra,
+ frames, src, dst, 0, 0,
+ GFP_KERNEL);
+@@ -746,7 +927,7 @@ static struct dma_async_tx_descriptor *b
+ return NULL;
+
+ /* fill in frames with scatterlist pointers */
+- bcm2835_dma_fill_cb_chain_with_sg(chan, direction, d->cb_list,
++ bcm2835_dma_fill_cb_chain_with_sg(c, direction, d->cb_list,
+ sgl, sg_len);
+
+ return vchan_tx_prep(&c->vc, &d->vd, flags);
+@@ -815,7 +996,7 @@ static struct dma_async_tx_descriptor *b
+ * note that we need to use GFP_NOWAIT, as the ALSA i2s dmaengine
+ * implementation calls prep_dma_cyclic with interrupts disabled.
+ */
+- d = bcm2835_dma_create_cb_chain(chan, direction, true,
++ d = bcm2835_dma_create_cb_chain(c, direction, true,
+ info, extra,
+ frames, src, dst, buf_len,
+ period_len, GFP_NOWAIT);
+@@ -823,7 +1004,8 @@ static struct dma_async_tx_descriptor *b
+ return NULL;
+
+ /* wrap around into a loop */
+- d->cb_list[d->frames - 1].cb->next = d->cb_list[0].paddr;
++ d->cb_list[d->frames - 1].cb->next = c->is_40bit_channel ?
++ to_bcm2838_cbaddr(d->cb_list[0].paddr) : d->cb_list[0].paddr;
+
+ return vchan_tx_prep(&c->vc, &d->vd, flags);
+ }
+@@ -899,9 +1081,11 @@ static int bcm2835_dma_chan_init(struct
+ c->irq_number = irq;
+ c->irq_flags = irq_flags;
+
+- /* check in DEBUG register if this is a LITE channel */
+- if (readl(c->chan_base + BCM2835_DMA_DEBUG) &
+- BCM2835_DMA_DEBUG_LITE)
++ /* check for 40bit and lite channels */
++ if (d->cfg_data->chan_40bit_mask & BIT(chan_id))
++ c->is_40bit_channel = true;
++ else if (readl(c->chan_base + BCM2835_DMA_DEBUG) &
++ BCM2835_DMA_DEBUG_LITE)
+ c->is_lite_channel = true;
+
+ return 0;
+@@ -918,18 +1102,16 @@ static void bcm2835_dma_free(struct bcm2
+ }
+ }
+
+-int bcm2838_dma40_memcpy_init(struct device *dev)
++int bcm2838_dma40_memcpy_init(void)
+ {
+- if (memcpy_scb)
+- return 0;
++ if (!memcpy_parent)
++ return -EPROBE_DEFER;
+
+- memcpy_scb = dma_alloc_coherent(dev, sizeof(*memcpy_scb),
+- &memcpy_scb_dma, GFP_KERNEL);
++ if (!memcpy_chan)
++ return -EINVAL;
+
+- if (!memcpy_scb) {
+- pr_err("bcm2838_dma40_memcpy_init failed!\n");
++ if (!memcpy_scb)
+ return -ENOMEM;
+- }
+
+ return 0;
+ }
+@@ -956,20 +1138,22 @@ void bcm2838_dma40_memcpy(dma_addr_t dst
+ scb->next_cb = 0;
+
+ writel((u32)(memcpy_scb_dma >> 5), memcpy_chan + BCM2838_DMA40_CB);
+- writel(BCM2838_DMA40_MEMCPY_QOS + BCM2838_DMA40_CS_ACTIVE,
++ writel(BCM2838_DMA40_MEMCPY_FLAGS + BCM2838_DMA40_ACTIVE,
+ memcpy_chan + BCM2838_DMA40_CS);
++
+ /* Poll for completion */
+- while (!(readl(memcpy_chan + BCM2838_DMA40_CS) & BCM2838_DMA40_CS_END))
++ while (!(readl(memcpy_chan + BCM2838_DMA40_CS) & BCM2838_DMA40_END))
+ cpu_relax();
+
+- writel(BCM2838_DMA40_CS_END, memcpy_chan + BCM2838_DMA40_CS);
++ writel(BCM2838_DMA40_END, memcpy_chan + BCM2838_DMA40_CS);
+
+ spin_unlock_irqrestore(&memcpy_lock, flags);
+ }
+ EXPORT_SYMBOL(bcm2838_dma40_memcpy);
+
+ static const struct of_device_id bcm2835_dma_of_match[] = {
+- { .compatible = "brcm,bcm2835-dma", },
++ { .compatible = "brcm,bcm2835-dma", .data = &bcm2835_dma_cfg },
++ { .compatible = "brcm,bcm2838-dma", .data = &bcm2838_dma_cfg },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match);
+@@ -1001,6 +1185,8 @@ static int bcm2835_dma_probe(struct plat
+ int irq_flags;
+ uint32_t chans_available;
+ char chan_name[BCM2835_DMA_CHAN_NAME_SIZE];
++ const struct of_device_id *of_id;
++ int chan_count, chan_start, chan_end;
+
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+@@ -1020,9 +1206,13 @@ static int bcm2835_dma_probe(struct plat
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+- rc = bcm_dmaman_probe(pdev, base, BCM2835_DMA_BULK_MASK);
+- if (rc)
+- dev_err(&pdev->dev, "Failed to initialize the legacy API\n");
++
++ /* The set of channels can be split across multiple instances. */
++ chan_start = ((u32)base / BCM2835_DMA_CHAN_SIZE) & 0xf;
++ base -= BCM2835_DMA_CHAN(chan_start);
++ chan_count = resource_size(res) / BCM2835_DMA_CHAN_SIZE;
++ chan_end = min(chan_start + chan_count,
++ BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED + 1);
+
+ od->base = base;
+
+@@ -1052,6 +1242,14 @@ static int bcm2835_dma_probe(struct plat
+
+ platform_set_drvdata(pdev, od);
+
++ of_id = of_match_node(bcm2835_dma_of_match, pdev->dev.of_node);
++ if (!of_id) {
++ dev_err(&pdev->dev, "Failed to match compatible string\n");
++ return -EINVAL;
++ }
++
++ od->cfg_data = of_id->data;
++
+ /* Request DMA channel mask from device tree */
+ if (of_property_read_u32(pdev->dev.of_node,
+ "brcm,dma-channel-mask",
+@@ -1061,18 +1259,34 @@ static int bcm2835_dma_probe(struct plat
+ goto err_no_dma;
+ }
+
+- /* Channel 0 is used by the legacy API */
+- chans_available &= ~BCM2835_DMA_BULK_MASK;
++ /* One channel is reserved for the legacy API */
++ if (chans_available & BCM2835_DMA_BULK_MASK) {
++ rc = bcm_dmaman_probe(pdev, base,
++ chans_available & BCM2835_DMA_BULK_MASK);
++ if (rc)
++ dev_err(&pdev->dev,
++ "Failed to initialize the legacy API\n");
++
++ chans_available &= ~BCM2835_DMA_BULK_MASK;
++ }
+
+- /* We can't use channels 11-13 yet */
+- chans_available &= ~(BIT(11) | BIT(12) | BIT(13));
++ /* And possibly one for the 40-bit DMA memcpy API */
++ if (chans_available & od->cfg_data->chan_40bit_mask &
++ BIT(BCM2838_DMA_MEMCPY_CHAN)) {
++ memcpy_parent = od;
++ memcpy_chan = BCM2835_DMA_CHANIO(base, BCM2838_DMA_MEMCPY_CHAN);
++ memcpy_scb = dma_alloc_coherent(memcpy_parent->ddev.dev,
++ sizeof(*memcpy_scb),
++ &memcpy_scb_dma, GFP_KERNEL);
++ if (!memcpy_scb)
++ dev_warn(&pdev->dev,
++ "Failed to allocated memcpy scb\n");
+
+- /* Grab channel 14 for the 40-bit DMA memcpy */
+- chans_available &= ~BIT(14);
+- memcpy_chan = BCM2835_DMA_CHANIO(base, 14);
++ chans_available &= ~BIT(BCM2838_DMA_MEMCPY_CHAN);
++ }
+
+ /* get irqs for each channel that we support */
+- for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
++ for (i = chan_start; i < chan_end; i++) {
+ /* skip masked out channels */
+ if (!(chans_available & (1 << i))) {
+ irq[i] = -1;
+@@ -1095,13 +1309,17 @@ static int bcm2835_dma_probe(struct plat
+ irq[i] = platform_get_irq(pdev, i < 11 ? i : 11);
+ }
+
++ chan_count = 0;
++
+ /* get irqs for each channel */
+- for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
++ for (i = chan_start; i < chan_end; i++) {
+ /* skip channels without irq */
+ if (irq[i] < 0)
+ continue;
+
+ /* check if there are other channels that also use this irq */
++ /* FIXME: This will fail if interrupts are shared across
++ instances */
+ irq_flags = 0;
+ for (j = 0; j <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; j++)
+ if ((i != j) && (irq[j] == irq[i])) {
+@@ -1113,9 +1331,10 @@ static int bcm2835_dma_probe(struct plat
+ rc = bcm2835_dma_chan_init(od, i, irq[i], irq_flags);
+ if (rc)
+ goto err_no_dma;
++ chan_count++;
+ }
+
+- dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", i);
++ dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", chan_count);
+
+ /* Device-tree DMA controller registration */
+ rc = of_dma_controller_register(pdev->dev.of_node,
+@@ -1147,6 +1366,13 @@ static int bcm2835_dma_remove(struct pla
+
+ bcm_dmaman_remove(pdev);
+ dma_async_device_unregister(&od->ddev);
++ if (memcpy_parent == od) {
++ dma_free_coherent(&pdev->dev, sizeof(*memcpy_scb), memcpy_scb,
++ memcpy_scb_dma);
++ memcpy_parent = NULL;
++ memcpy_scb = NULL;
++ memcpy_chan = NULL;
++ }
+ bcm2835_dma_free(od);
+
+ return 0;
+--- a/drivers/pci/controller/pcie-brcmstb-bounce.c
++++ b/drivers/pci/controller/pcie-brcmstb-bounce.c
+@@ -91,7 +91,7 @@ struct dmabounce_device_info {
+
+ static struct dmabounce_device_info *g_dmabounce_device_info;
+
+-extern int bcm2838_dma40_memcpy_init(struct device *dev);
++extern int bcm2838_dma40_memcpy_init(void);
+ extern void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size);
+
+ #ifdef STATS
+@@ -471,9 +471,9 @@ static const struct dma_map_ops dmabounc
+ .mapping_error = dmabounce_mapping_error,
+ };
+
+-int brcm_pcie_bounce_register_dev(struct device *dev,
+- unsigned long buffer_size,
+- dma_addr_t threshold)
++int brcm_pcie_bounce_init(struct device *dev,
++ unsigned long buffer_size,
++ dma_addr_t threshold)
+ {
+ struct dmabounce_device_info *device_info;
+ int ret;
+@@ -482,9 +482,9 @@ int brcm_pcie_bounce_register_dev(struct
+ if (g_dmabounce_device_info)
+ return -EBUSY;
+
+- ret = bcm2838_dma40_memcpy_init(dev);
++ ret = bcm2838_dma40_memcpy_init();
+ if (ret)
+- return ret;
++ return ret;
+
+ device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
+ if (!device_info) {
+@@ -515,9 +515,8 @@ int brcm_pcie_bounce_register_dev(struct
+ device_create_file(dev, &dev_attr_dmabounce_stats));
+
+ g_dmabounce_device_info = device_info;
+- set_dma_ops(dev, &dmabounce_ops);
+
+- dev_info(dev, "dmabounce: registered device - %ld kB, threshold %pad\n",
++ dev_info(dev, "dmabounce: initialised - %ld kB, threshold %pad\n",
+ buffer_size / 1024, &threshold);
+
+ return 0;
+@@ -526,14 +525,13 @@ int brcm_pcie_bounce_register_dev(struct
+ kfree(device_info);
+ return ret;
+ }
+-EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
++EXPORT_SYMBOL(brcm_pcie_bounce_init);
+
+-void brcm_pcie_bounce_unregister_dev(struct device *dev)
++void brcm_pcie_bounce_uninit(struct device *dev)
+ {
+ struct dmabounce_device_info *device_info = g_dmabounce_device_info;
+
+ g_dmabounce_device_info = NULL;
+- set_dma_ops(dev, NULL);
+
+ if (!device_info) {
+ dev_warn(dev,
+@@ -554,10 +552,16 @@ void brcm_pcie_bounce_unregister_dev(str
+ device_remove_file(dev, &dev_attr_dmabounce_stats));
+
+ kfree(device_info);
++}
++EXPORT_SYMBOL(brcm_pcie_bounce_uninit);
++
++int brcm_pcie_bounce_register_dev(struct device *dev)
++{
++ set_dma_ops(dev, &dmabounce_ops);
+
+- dev_info(dev, "dmabounce: device unregistered\n");
++ return 0;
+ }
+-EXPORT_SYMBOL(brcm_pcie_bounce_unregister_dev);
++EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
+
+ MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.org>");
+ MODULE_DESCRIPTION("Dedicate DMA bounce support for pcie-brcmstb");
+--- a/drivers/pci/controller/pcie-brcmstb-bounce.h
++++ b/drivers/pci/controller/pcie-brcmstb-bounce.h
+@@ -8,21 +8,26 @@
+
+ #ifdef CONFIG_ARM
+
+-int brcm_pcie_bounce_register_dev(struct device *dev, unsigned long buffer_size,
+- dma_addr_t threshold);
+-
+-int brcm_pcie_bounce_unregister_dev(struct device *dev);
++int brcm_pcie_bounce_init(struct device *dev, unsigned long buffer_size,
++ dma_addr_t threshold);
++int brcm_pcie_bounce_uninit(struct device *dev);
++int brcm_pcie_bounce_register_dev(struct device *dev);
+
+ #else
+
+-static inline int brcm_pcie_bounce_register_dev(struct device *dev,
+- unsigned long buffer_size,
+- dma_addr_t threshold)
++static inline int brcm_pcie_bounce_init(struct device *dev,
++ unsigned long buffer_size,
++ dma_addr_t threshold)
++{
++ return 0;
++}
++
++static inline int brcm_pcie_bounce_uninit(struct device *dev)
+ {
+ return 0;
+ }
+
+-static inline int brcm_pcie_bounce_unregister_dev(struct device *dev)
++static inline int brcm_pcie_bounce_register_dev(struct device *dev)
+ {
+ return 0;
+ }
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -650,6 +650,7 @@ static void brcm_set_dma_ops(struct devi
+
+ static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie,
+ unsigned int val);
++
+ static int brcmstb_platform_notifier(struct notifier_block *nb,
+ unsigned long event, void *__dev)
+ {
+@@ -663,12 +664,11 @@ static int brcmstb_platform_notifier(str
+ strcmp(dev->kobj.name, rc_name)) {
+ int ret;
+
+- ret = brcm_pcie_bounce_register_dev(dev, bounce_buffer,
+- (dma_addr_t)bounce_threshold);
++ ret = brcm_pcie_bounce_register_dev(dev);
+ if (ret) {
+ dev_err(dev,
+ "brcm_pcie_bounce_register_dev() failed: %d\n",
+- ret);
++ ret);
+ return ret;
+ }
+ }
+@@ -681,8 +681,6 @@ static int brcmstb_platform_notifier(str
+ brcm_pcie_perst_set(g_pcie, 1);
+ msleep(100);
+ brcm_pcie_perst_set(g_pcie, 0);
+- } else if (max_pfn > (bounce_threshold/PAGE_SIZE)) {
+- brcm_pcie_bounce_unregister_dev(dev);
+ }
+ return NOTIFY_OK;
+
+@@ -1718,6 +1716,7 @@ static int brcm_pcie_probe(struct platfo
+ void __iomem *base;
+ struct pci_host_bridge *bridge;
+ struct pci_bus *child;
++ extern unsigned long max_pfn;
+
+ bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie));
+ if (!bridge)
+@@ -1753,6 +1752,20 @@ static int brcm_pcie_probe(struct platfo
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
++ /* To Do: Add hardware check if this ever gets fixed */
++ if (max_pfn > (bounce_threshold/PAGE_SIZE)) {
++ int ret;
++ ret = brcm_pcie_bounce_init(&pdev->dev, bounce_buffer,
++ (dma_addr_t)bounce_threshold);
++ if (ret) {
++ if (ret != -EPROBE_DEFER)
++ dev_err(&pdev->dev,
++ "could not init bounce buffers: %d\n",
++ ret);
++ return ret;
++ }
++ }
++
+ pcie->clk = of_clk_get_by_name(dn, "sw_pcie");
+ if (IS_ERR(pcie->clk)) {
+ dev_warn(&pdev->dev, "could not get clock\n");
+++ /dev/null
-From d5a3a06dce60efe829fd644448bbab8c10368f8a Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Mon, 3 Jun 2019 14:57:56 +0100
-Subject: [PATCH 646/703] config: Add NF_TABLES support
-
----
- arch/arm/configs/bcm2711_defconfig | 48 ++++++++++++++++++++++++++++++
- 1 file changed, 48 insertions(+)
-
---- a/arch/arm/configs/bcm2711_defconfig
-+++ b/arch/arm/configs/bcm2711_defconfig
-@@ -133,6 +133,36 @@ CONFIG_NF_CONNTRACK_SANE=m
- CONFIG_NF_CONNTRACK_SIP=m
- CONFIG_NF_CONNTRACK_TFTP=m
- CONFIG_NF_CT_NETLINK=m
-+CONFIG_NF_TABLES=m
-+CONFIG_NF_TABLES_SET=m
-+CONFIG_NF_TABLES_INET=y
-+CONFIG_NF_TABLES_NETDEV=y
-+CONFIG_NFT_NUMGEN=m
-+CONFIG_NFT_CT=m
-+CONFIG_NFT_FLOW_OFFLOAD=m
-+CONFIG_NFT_COUNTER=m
-+CONFIG_NFT_CONNLIMIT=m
-+CONFIG_NFT_LOG=m
-+CONFIG_NFT_LIMIT=m
-+CONFIG_NFT_MASQ=m
-+CONFIG_NFT_REDIR=m
-+CONFIG_NFT_NAT=m
-+CONFIG_NFT_TUNNEL=m
-+CONFIG_NFT_OBJREF=m
-+CONFIG_NFT_QUEUE=m
-+CONFIG_NFT_QUOTA=m
-+CONFIG_NFT_REJECT=m
-+CONFIG_NFT_COMPAT=m
-+CONFIG_NFT_HASH=m
-+CONFIG_NFT_FIB_INET=m
-+CONFIG_NFT_SOCKET=m
-+CONFIG_NFT_OSF=m
-+CONFIG_NFT_TPROXY=m
-+CONFIG_NFT_DUP_NETDEV=m
-+CONFIG_NFT_FWD_NETDEV=m
-+CONFIG_NFT_FIB_NETDEV=m
-+CONFIG_NF_FLOW_TABLE_INET=m
-+CONFIG_NF_FLOW_TABLE=m
- CONFIG_NETFILTER_XT_SET=m
- CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
- CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-@@ -220,6 +250,14 @@ CONFIG_IP_VS_SED=m
- CONFIG_IP_VS_NQ=m
- CONFIG_IP_VS_FTP=m
- CONFIG_IP_VS_PE_SIP=m
-+CONFIG_NFT_CHAIN_ROUTE_IPV4=m
-+CONFIG_NFT_DUP_IPV4=m
-+CONFIG_NFT_FIB_IPV4=m
-+CONFIG_NF_TABLES_ARP=y
-+CONFIG_NF_FLOW_TABLE_IPV4=m
-+CONFIG_NFT_CHAIN_NAT_IPV4=m
-+CONFIG_NFT_MASQ_IPV4=m
-+CONFIG_NFT_REDIR_IPV4=m
- CONFIG_IP_NF_IPTABLES=m
- CONFIG_IP_NF_MATCH_AH=m
- CONFIG_IP_NF_MATCH_ECN=m
-@@ -239,6 +277,13 @@ CONFIG_IP_NF_RAW=m
- CONFIG_IP_NF_ARPTABLES=m
- CONFIG_IP_NF_ARPFILTER=m
- CONFIG_IP_NF_ARP_MANGLE=m
-+CONFIG_NFT_CHAIN_ROUTE_IPV6=m
-+CONFIG_NFT_CHAIN_NAT_IPV6=m
-+CONFIG_NFT_MASQ_IPV6=m
-+CONFIG_NFT_REDIR_IPV6=m
-+CONFIG_NFT_DUP_IPV6=m
-+CONFIG_NFT_FIB_IPV6=m
-+CONFIG_NF_FLOW_TABLE_IPV6=m
- CONFIG_IP6_NF_IPTABLES=m
- CONFIG_IP6_NF_MATCH_AH=m
- CONFIG_IP6_NF_MATCH_EUI64=m
-@@ -257,6 +302,9 @@ CONFIG_IP6_NF_RAW=m
- CONFIG_IP6_NF_NAT=m
- CONFIG_IP6_NF_TARGET_MASQUERADE=m
- CONFIG_IP6_NF_TARGET_NPT=m
-+CONFIG_NF_TABLES_BRIDGE=y
-+CONFIG_NFT_BRIDGE_REJECT=m
-+CONFIG_NF_LOG_BRIDGE=m
- CONFIG_BRIDGE_NF_EBTABLES=m
- CONFIG_BRIDGE_EBT_BROUTE=m
- CONFIG_BRIDGE_EBT_T_FILTER=m
--- /dev/null
+From 38e3b7d8f4443fd366afc4d20bbd36aa350e68a1 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 5 Jun 2019 21:32:03 +0100
+Subject: [PATCH 647/725] BCM270X_DT: Leave bulk channel in dma channel mask
+
+The updated bcm2835-dma driver does not require the BULK channel
+to be removed from the set of available channels, as provided by
+dma-channel-mask.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2708-rpi.dtsi | 4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
+@@ -124,10 +124,6 @@
+ };
+ };
+
+-&dma {
+- brcm,dma-channel-mask = <0x7f34>;
+-};
+-
+ &hdmi {
+ power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+ };
+++ /dev/null
-From ad2c4e0c73a9de7f06e891faf57ebf868fde6b24 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Mon, 3 Jun 2019 15:33:02 +0100
-Subject: [PATCH 647/703] bcm2711_defconfig: add xhci platform support
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- arch/arm/configs/bcm2711_defconfig | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/configs/bcm2711_defconfig
-+++ b/arch/arm/configs/bcm2711_defconfig
-@@ -983,6 +983,7 @@ CONFIG_USB=y
- CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
- CONFIG_USB_MON=m
- CONFIG_USB_XHCI_HCD=y
-+CONFIG_USB_XHCI_PLATFORM=y
- CONFIG_USB_DWCOTG=y
- CONFIG_USB_PRINTER=m
- CONFIG_USB_STORAGE=y
+++ /dev/null
-From 99c805aa346cf88fba8b26eb1093192bcc822986 Mon Sep 17 00:00:00 2001
-From: 6by9 <6by9@users.noreply.github.com>
-Date: Wed, 30 Jan 2019 14:22:03 +0000
-Subject: [PATCH 648/703] ARM: dts: bcm283x: Correct vchiq compatible string
- (#2840)
-
-commit 499770ede3f829e80539f46b59b5f460dc327aa6 upstream.
-
-To allow VCHIQ to determine the correct cache line size, use the new
-"brcm,bcm2836-vchiq" compatible string on BCM2836 and BCM2837.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
-Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
----
- arch/arm/boot/dts/bcm2835-rpi.dtsi | 2 +-
- arch/arm/boot/dts/bcm2836-rpi-2-b.dts | 2 +-
- arch/arm/boot/dts/bcm2836-rpi.dtsi | 6 ++++++
- arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2 +-
- arch/arm/boot/dts/bcm2837-rpi-3-b.dts | 2 +-
- 5 files changed, 10 insertions(+), 4 deletions(-)
- create mode 100644 arch/arm/boot/dts/bcm2836-rpi.dtsi
-
---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
-@@ -30,7 +30,7 @@
- #power-domain-cells = <1>;
- };
-
-- mailbox@7e00b840 {
-+ vchiq: mailbox@7e00b840 {
- compatible = "brcm,bcm2835-vchiq";
- reg = <0x7e00b840 0x3c>;
- interrupts = <0 2>;
---- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
-+++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
-@@ -1,7 +1,7 @@
- // SPDX-License-Identifier: GPL-2.0
- /dts-v1/;
- #include "bcm2836.dtsi"
--#include "bcm2835-rpi.dtsi"
-+#include "bcm2836-rpi.dtsi"
- #include "bcm283x-rpi-smsc9514.dtsi"
- #include "bcm283x-rpi-usb-host.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2836-rpi.dtsi
-@@ -0,0 +1,6 @@
-+// SPDX-License-Identifier: GPL-2.0
-+#include "bcm2835-rpi.dtsi"
-+
-+&vchiq {
-+ compatible = "brcm,bcm2836-vchiq", "brcm,bcm2835-vchiq";
-+};
---- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
-+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
-@@ -1,7 +1,7 @@
- // SPDX-License-Identifier: GPL-2.0
- /dts-v1/;
- #include "bcm2837.dtsi"
--#include "bcm2835-rpi.dtsi"
-+#include "bcm2836-rpi.dtsi"
- #include "bcm283x-rpi-lan7515.dtsi"
- #include "bcm283x-rpi-usb-host.dtsi"
-
---- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
-+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
-@@ -1,7 +1,7 @@
- // SPDX-License-Identifier: GPL-2.0
- /dts-v1/;
- #include "bcm2837.dtsi"
--#include "bcm2835-rpi.dtsi"
-+#include "bcm2836-rpi.dtsi"
- #include "bcm283x-rpi-smsc9514.dtsi"
- #include "bcm283x-rpi-usb-host.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
--- /dev/null
+From 2abf4cf9870fcd57e614cb39b95e6e2a4462a828 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 6 Jun 2019 09:35:08 +0100
+Subject: [PATCH 648/725] SQUASH: bcm2835-dma: Remove debugging
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/dma/bcm2835-dma.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/drivers/dma/bcm2835-dma.c
++++ b/drivers/dma/bcm2835-dma.c
+@@ -584,8 +584,6 @@ static void bcm2835_dma_fill_cb_chain_wi
+ dma_addr_t addr;
+ struct scatterlist *sgent;
+
+- pr_err("dma_fill_chain_with_sg(ch %d, dir %d):\n", c->ch, direction);
+-
+ max_len = bcm2835_dma_max_frame_length(c);
+ for_each_sg(sgl, sgent, sg_len, i) {
+ if (c->is_40bit_channel) {
+@@ -603,7 +601,6 @@ static void bcm2835_dma_fill_cb_chain_wi
+ scb->srci = upper_32_bits(addr) | BCM2838_DMA40_INC;
+ }
+ scb->len = min(len, max_len);
+- pr_err(" %llx, %x\n", (u64)addr, scb->len);
+ }
+ } else {
+ for (addr = sg_dma_address(sgent),
+@@ -616,7 +613,6 @@ static void bcm2835_dma_fill_cb_chain_wi
+ else
+ cb->cb->src = addr;
+ cb->cb->length = min(len, max_len);
+- pr_err(" %llx, %x\n", (u64)addr, cb->cb->length);
+ }
+ }
+ }
+@@ -659,7 +655,6 @@ static void bcm2835_dma_start_desc(struc
+ struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
+ struct bcm2835_desc *d;
+
+- pr_err("dma_start_desc(%px)\n", vd);
+ if (!vd) {
+ c->desc = NULL;
+ return;
+++ /dev/null
-From 4ef78a596dcde685022fde07c4cb5bc993ce7aa3 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 6 Feb 2019 20:45:16 +0000
-Subject: [PATCH 649/703] arm: dts: Change downstream vchiq compatible string
-
-The new cache line size mechanism requires a different vchiq compatible
-string on BCM2836 and BCM2837, but the downstream dts files didn't
-inherit the upstream changes.
-
-See: https://github.com/raspberrypi/linux/issues/2643
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2708-rpi.dtsi | 2 +-
- arch/arm/boot/dts/bcm2709-rpi.dtsi | 5 +++++
- arch/arm/boot/dts/bcm2709.dtsi | 2 +-
- arch/arm/boot/dts/bcm2710.dtsi | 2 +-
- 4 files changed, 8 insertions(+), 3 deletions(-)
- create mode 100644 arch/arm/boot/dts/bcm2709-rpi.dtsi
-
---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
-@@ -68,7 +68,7 @@
- status = "disabled";
- };
-
-- mailbox@7e00b840 {
-+ vchiq: mailbox@7e00b840 {
- compatible = "brcm,bcm2835-vchiq";
- reg = <0x7e00b840 0x3c>;
- interrupts = <0 2>;
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2709-rpi.dtsi
-@@ -0,0 +1,5 @@
-+#include "bcm2708-rpi.dtsi"
-+
-+&vchiq {
-+ compatible = "brcm,bcm2836-vchiq", "brcm,bcm2835-vchiq";
-+};
---- a/arch/arm/boot/dts/bcm2709.dtsi
-+++ b/arch/arm/boot/dts/bcm2709.dtsi
-@@ -1,6 +1,6 @@
- #include "bcm2836.dtsi"
- #include "bcm270x.dtsi"
--#include "bcm2708-rpi.dtsi"
-+#include "bcm2709-rpi.dtsi"
-
- / {
- soc {
---- a/arch/arm/boot/dts/bcm2710.dtsi
-+++ b/arch/arm/boot/dts/bcm2710.dtsi
-@@ -1,6 +1,6 @@
- #include "bcm2837.dtsi"
- #include "bcm270x.dtsi"
--#include "bcm2708-rpi.dtsi"
-+#include "bcm2709-rpi.dtsi"
-
- / {
- compatible = "brcm,bcm2837", "brcm,bcm2836";
--- /dev/null
+From 1f08e6a6f4210e44d77b40f45ec6cea9e364abe1 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 6 Jun 2019 15:22:29 +0100
+Subject: [PATCH 649/725] defconfig: Update bcm2711 to match bcm2709 on extra
+ modules
+
+Lots of things like USB DVB tuners were missing from the
+defconfig.
+Resync it with bcm2709_defconfig
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm/configs/bcm2711_defconfig | 97 ++++++++++++++++++++++++++++++
+ 1 file changed, 97 insertions(+)
+
+--- a/arch/arm/configs/bcm2711_defconfig
++++ b/arch/arm/configs/bcm2711_defconfig
+@@ -14,6 +14,9 @@ CONFIG_TASK_XACCT=y
+ CONFIG_TASK_IO_ACCOUNTING=y
+ CONFIG_IKCONFIG=m
+ CONFIG_IKCONFIG_PROC=y
++CONFIG_MEMCG=y
++CONFIG_BLK_CGROUP=y
++CONFIG_CGROUP_PIDS=y
+ CONFIG_CGROUP_FREEZER=y
+ CONFIG_CPUSETS=y
+ CONFIG_CGROUP_DEVICE=y
+@@ -65,8 +68,10 @@ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_MODULE_SRCVERSION_ALL=y
++CONFIG_BLK_DEV_THROTTLING=y
+ CONFIG_PARTITION_ADVANCED=y
+ CONFIG_MAC_PARTITION=y
++CONFIG_CFQ_GROUP_IOSCHED=y
+ CONFIG_BINFMT_MISC=m
+ CONFIG_CLEANCACHE=y
+ CONFIG_FRONTSWAP=y
+@@ -95,6 +100,7 @@ CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+ CONFIG_IP_PIMSM_V1=y
+ CONFIG_IP_PIMSM_V2=y
+ CONFIG_SYN_COOKIES=y
++CONFIG_NET_IPVTI=m
+ CONFIG_INET_AH=m
+ CONFIG_INET_ESP=m
+ CONFIG_INET_IPCOMP=m
+@@ -214,6 +220,7 @@ 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
+@@ -520,6 +527,7 @@ CONFIG_USB_RTL8150=m
+ CONFIG_USB_RTL8152=y
+ CONFIG_USB_LAN78XX=y
+ CONFIG_USB_USBNET=y
++CONFIG_USB_NET_AX8817X=m
+ CONFIG_USB_NET_AX88179_178A=m
+ CONFIG_USB_NET_CDCETHER=m
+ CONFIG_USB_NET_CDC_EEM=m
+@@ -573,6 +581,8 @@ CONFIG_LIBERTAS_THINFIRM_USB=m
+ CONFIG_MWIFIEX=m
+ CONFIG_MWIFIEX_SDIO=m
+ CONFIG_MT7601U=m
++CONFIG_MT76x0U=m
++CONFIG_MT76x2U=m
+ CONFIG_RT2X00=m
+ CONFIG_RT2500USB=m
+ CONFIG_RT73USB=m
+@@ -613,6 +623,7 @@ CONFIG_TOUCHSCREEN_ADS7846=m
+ CONFIG_TOUCHSCREEN_EGALAX=m
+ CONFIG_TOUCHSCREEN_EXC3000=m
+ CONFIG_TOUCHSCREEN_GOODIX=m
++CONFIG_TOUCHSCREEN_ILI210X=m
+ CONFIG_TOUCHSCREEN_EDT_FT5X06=m
+ CONFIG_TOUCHSCREEN_RPI_FT5406=m
+ CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+@@ -657,8 +668,13 @@ CONFIG_SERIAL_DEV_BUS=m
+ CONFIG_TTY_PRINTK=y
+ CONFIG_HW_RANDOM=y
+ CONFIG_RAW_DRIVER=y
++CONFIG_TCG_TPM=m
++CONFIG_TCG_TIS_SPI=m
+ CONFIG_I2C=y
+ CONFIG_I2C_CHARDEV=m
++CONFIG_I2C_MUX=m
++CONFIG_I2C_MUX_GPMUX=m
++CONFIG_I2C_MUX_PCA954x=m
+ CONFIG_I2C_BCM2708=m
+ CONFIG_I2C_BCM2835=m
+ CONFIG_I2C_GPIO=m
+@@ -667,6 +683,7 @@ CONFIG_I2C_TINY_USB=m
+ CONFIG_SPI=y
+ CONFIG_SPI_BCM2835=m
+ CONFIG_SPI_BCM2835AUX=m
++CONFIG_SPI_GPIO=m
+ CONFIG_SPI_SPIDEV=m
+ CONFIG_SPI_SLAVE=y
+ CONFIG_PPS=m
+@@ -698,11 +715,14 @@ CONFIG_W1_SLAVE_DS28E04=m
+ CONFIG_POWER_RESET=y
+ CONFIG_POWER_RESET_GPIO=y
+ CONFIG_BATTERY_DS2760=m
++CONFIG_BATTERY_MAX17040=m
+ CONFIG_BATTERY_GAUGE_LTC2941=m
+ CONFIG_HWMON=m
+ CONFIG_SENSORS_DS1621=m
++CONFIG_SENSORS_GPIO_FAN=m
+ CONFIG_SENSORS_JC42=m
+ CONFIG_SENSORS_LM75=m
++CONFIG_SENSORS_RASPBERRYPI_HWMON=m
+ CONFIG_SENSORS_RPI_POE_FAN=m
+ CONFIG_SENSORS_SHT21=m
+ CONFIG_SENSORS_SHT3x=m
+@@ -726,6 +746,31 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=m
+ CONFIG_REGULATOR_ARIZONA_LDO1=m
+ CONFIG_REGULATOR_ARIZONA_MICSUPP=m
+ CONFIG_REGULATOR_GPIO=y
++CONFIG_RC_CORE=y
++CONFIG_LIRC=y
++CONFIG_RC_DECODERS=y
++CONFIG_IR_NEC_DECODER=m
++CONFIG_IR_RC5_DECODER=m
++CONFIG_IR_RC6_DECODER=m
++CONFIG_IR_JVC_DECODER=m
++CONFIG_IR_SONY_DECODER=m
++CONFIG_IR_SANYO_DECODER=m
++CONFIG_IR_SHARP_DECODER=m
++CONFIG_IR_MCE_KBD_DECODER=m
++CONFIG_IR_XMP_DECODER=m
++CONFIG_IR_IMON_DECODER=m
++CONFIG_RC_DEVICES=y
++CONFIG_RC_ATI_REMOTE=m
++CONFIG_IR_IMON=m
++CONFIG_IR_MCEUSB=m
++CONFIG_IR_REDRAT3=m
++CONFIG_IR_STREAMZAP=m
++CONFIG_IR_IGUANA=m
++CONFIG_IR_TTUSBIR=m
++CONFIG_RC_LOOPBACK=m
++CONFIG_IR_GPIO_CIR=m
++CONFIG_IR_GPIO_TX=m
++CONFIG_IR_PWM_TX=m
+ CONFIG_MEDIA_SUPPORT=m
+ CONFIG_MEDIA_CAMERA_SUPPORT=y
+ CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
+@@ -797,7 +842,40 @@ CONFIG_VIDEO_GO7007=m
+ CONFIG_VIDEO_GO7007_USB=m
+ CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m
+ CONFIG_VIDEO_AU0828=m
++CONFIG_VIDEO_AU0828_RC=y
++CONFIG_VIDEO_CX231XX=m
++CONFIG_VIDEO_CX231XX_ALSA=m
++CONFIG_VIDEO_CX231XX_DVB=m
++CONFIG_VIDEO_TM6000=m
++CONFIG_VIDEO_TM6000_ALSA=m
++CONFIG_VIDEO_TM6000_DVB=m
++CONFIG_DVB_USB=m
++CONFIG_DVB_USB_A800=m
++CONFIG_DVB_USB_DIBUSB_MB=m
++CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y
++CONFIG_DVB_USB_DIBUSB_MC=m
++CONFIG_DVB_USB_DIB0700=m
++CONFIG_DVB_USB_UMT_010=m
++CONFIG_DVB_USB_CXUSB=m
++CONFIG_DVB_USB_M920X=m
++CONFIG_DVB_USB_DIGITV=m
++CONFIG_DVB_USB_VP7045=m
++CONFIG_DVB_USB_VP702X=m
++CONFIG_DVB_USB_GP8PSK=m
++CONFIG_DVB_USB_NOVA_T_USB2=m
++CONFIG_DVB_USB_TTUSB2=m
++CONFIG_DVB_USB_DTT200U=m
++CONFIG_DVB_USB_OPERA1=m
++CONFIG_DVB_USB_AF9005=m
++CONFIG_DVB_USB_AF9005_REMOTE=m
++CONFIG_DVB_USB_PCTV452E=m
++CONFIG_DVB_USB_DW2102=m
++CONFIG_DVB_USB_CINERGY_T2=m
++CONFIG_DVB_USB_DTV5100=m
++CONFIG_DVB_USB_AZ6027=m
++CONFIG_DVB_USB_TECHNISAT_USB2=m
+ CONFIG_DVB_USB_V2=m
++CONFIG_DVB_USB_AF9015=m
+ CONFIG_DVB_USB_AF9035=m
+ CONFIG_DVB_USB_ANYSEE=m
+ CONFIG_DVB_USB_AU6610=m
+@@ -805,7 +883,9 @@ CONFIG_DVB_USB_AZ6007=m
+ CONFIG_DVB_USB_CE6230=m
+ CONFIG_DVB_USB_EC168=m
+ CONFIG_DVB_USB_GL861=m
++CONFIG_DVB_USB_LME2510=m
+ CONFIG_DVB_USB_MXL111SF=m
++CONFIG_DVB_USB_RTL28XXU=m
+ CONFIG_DVB_USB_DVBSKY=m
+ CONFIG_SMS_USB_DRV=m
+ CONFIG_DVB_B2C2_FLEXCOP_USB=m
+@@ -900,9 +980,11 @@ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
+ CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
++CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M=m
+ CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
+ CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m
+ CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m
++CONFIG_SND_AUDIOSENSE_PI=m
+ CONFIG_SND_DIGIDAC1_SOUNDCARD=m
+ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m
+ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m
+@@ -913,10 +995,14 @@ CONFIG_SND_BCM2708_SOC_ALLO_DIGIONE=m
+ CONFIG_SND_BCM2708_SOC_ALLO_KATANA_DAC=m
+ CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m
+ CONFIG_SND_PISOUND=m
++CONFIG_SND_SOC_AD193X_SPI=m
++CONFIG_SND_SOC_AD193X_I2C=m
+ CONFIG_SND_SOC_ADAU1701=m
+ CONFIG_SND_SOC_ADAU7002=m
+ CONFIG_SND_SOC_AK4554=m
++CONFIG_SND_SOC_CS4265=m
+ CONFIG_SND_SOC_CS4271_I2C=m
++CONFIG_SND_SOC_ICS43432=m
+ CONFIG_SND_SOC_SPDIF=m
+ CONFIG_SND_SOC_WM8804_I2C=m
+ CONFIG_SND_SIMPLE_CARD=m
+@@ -929,6 +1015,7 @@ CONFIG_HID_APPLE=m
+ CONFIG_HID_ASUS=m
+ CONFIG_HID_BELKIN=m
+ CONFIG_HID_BETOP_FF=m
++CONFIG_HID_BIGBEN_FF=m
+ CONFIG_HID_CHERRY=m
+ CONFIG_HID_CHICONY=m
+ CONFIG_HID_CYPRESS=m
+@@ -986,6 +1073,7 @@ CONFIG_USB_XHCI_HCD=y
+ CONFIG_USB_XHCI_PLATFORM=y
+ CONFIG_USB_DWCOTG=y
+ CONFIG_USB_PRINTER=m
++CONFIG_USB_TMC=m
+ CONFIG_USB_STORAGE=y
+ CONFIG_USB_STORAGE_REALTEK=m
+ CONFIG_USB_STORAGE_DATAFAB=m
+@@ -1006,6 +1094,7 @@ CONFIG_USB_MICROTEK=m
+ CONFIG_USBIP_CORE=m
+ CONFIG_USBIP_VHCI_HCD=m
+ CONFIG_USBIP_HOST=m
++CONFIG_USBIP_VUDC=m
+ CONFIG_USB_DWC2=m
+ CONFIG_USB_SERIAL=m
+ CONFIG_USB_SERIAL_GENERIC=y
+@@ -1122,6 +1211,8 @@ CONFIG_MMC_SDHCI_IPROC=y
+ CONFIG_MMC_SPI=m
+ CONFIG_LEDS_CLASS=y
+ CONFIG_LEDS_GPIO=y
++CONFIG_LEDS_PCA963X=m
++CONFIG_LEDS_IS31FL32XX=m
+ CONFIG_LEDS_TRIGGER_TIMER=y
+ CONFIG_LEDS_TRIGGER_ONESHOT=y
+ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+@@ -1133,6 +1224,7 @@ CONFIG_LEDS_TRIGGER_TRANSIENT=m
+ CONFIG_LEDS_TRIGGER_CAMERA=m
+ CONFIG_LEDS_TRIGGER_INPUT=y
+ CONFIG_LEDS_TRIGGER_PANIC=y
++CONFIG_LEDS_TRIGGER_NETDEV=m
+ CONFIG_RTC_CLASS=y
+ # CONFIG_RTC_HCTOSYS is not set
+ CONFIG_RTC_DRV_ABX80X=m
+@@ -1154,6 +1246,7 @@ CONFIG_RTC_DRV_FM3130=m
+ CONFIG_RTC_DRV_RX8581=m
+ CONFIG_RTC_DRV_RX8025=m
+ CONFIG_RTC_DRV_EM3027=m
++CONFIG_RTC_DRV_RV3028=m
+ CONFIG_RTC_DRV_M41T93=m
+ CONFIG_RTC_DRV_M41T94=m
+ CONFIG_RTC_DRV_DS1302=m
+@@ -1170,6 +1263,8 @@ CONFIG_RTC_DRV_RV3029C2=m
+ CONFIG_DMADEVICES=y
+ CONFIG_DMA_BCM2835=y
+ CONFIG_DMA_BCM2708=y
++CONFIG_AUXDISPLAY=y
++CONFIG_HD44780=m
+ CONFIG_UIO=m
+ CONFIG_UIO_PDRV_GENIRQ=m
+ CONFIG_STAGING=y
+@@ -1198,6 +1293,7 @@ CONFIG_FB_TFT_PCD8544=m
+ CONFIG_FB_TFT_RA8875=m
+ CONFIG_FB_TFT_S6D02A1=m
+ CONFIG_FB_TFT_S6D1121=m
++CONFIG_FB_TFT_SH1106=m
+ CONFIG_FB_TFT_SSD1289=m
+ CONFIG_FB_TFT_SSD1306=m
+ CONFIG_FB_TFT_SSD1331=m
+@@ -1229,6 +1325,7 @@ CONFIG_MCP3422=m
+ CONFIG_DHT11=m
+ CONFIG_HDC100X=m
+ CONFIG_HTU21=m
++CONFIG_INV_MPU6050_I2C=m
+ CONFIG_TSL4531=m
+ CONFIG_VEML6070=m
+ CONFIG_BMP280=m
+++ /dev/null
-From 511ed7aad02f375c8a5cc3c847e6b5fc4bf4a620 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 4 Apr 2019 13:33:47 +0100
-Subject: [PATCH 650/703] bcm2835-dma: Add proper 40-bit DMA support
-
-The 40-bit additions are not fully tested, but it should be
-capable of supporting both 40-bit memcpy on BCM2711 and regular
-Lite channels on BCM2835.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2838.dtsi | 33 +-
- drivers/dma/bcm2835-dma.c | 426 ++++++++++++++-----
- drivers/pci/controller/pcie-brcmstb-bounce.c | 30 +-
- drivers/pci/controller/pcie-brcmstb-bounce.h | 21 +-
- drivers/pci/controller/pcie-brcmstb.c | 23 +-
- 5 files changed, 395 insertions(+), 138 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2838.dtsi
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -372,6 +372,23 @@
- };
- };
-
-+ dma40: dma@7e007b00 {
-+ compatible = "brcm,bcm2838-dma";
-+ reg = <0x0 0x7e007b00 0x400>;
-+ interrupts =
-+ <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, /* dma4 11 */
-+ <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, /* dma4 12 */
-+ <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, /* dma4 13 */
-+ <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; /* dma4 14 */
-+ interrupt-names = "dma11",
-+ "dma12",
-+ "dma13",
-+ "dma14";
-+ #dma-cells = <1>;
-+ brcm,dma-channel-mask = <0x7000>;
-+ };
-+ /* DMA4 - 40 bit DMA engines */
-+
- xhci: xhci@7e9c0000 {
- compatible = "generic-xhci";
- status = "disabled";
-@@ -689,6 +706,7 @@
- };
-
- &dma {
-+ reg = <0x7e007000 0xb00>;
- interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
-@@ -699,12 +717,7 @@
- <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 7 */
- <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 8 */
- <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 9 */
-- <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, /* dmalite 10 */
-- /* DMA4 - 40 bit DMA engines */
-- <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, /* dma4 11 */
-- <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, /* dma4 12 */
-- <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, /* dma4 13 */
-- <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; /* dma4 14 */
-+ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>; /* dmalite 10 */
- interrupt-names = "dma0",
- "dma1",
- "dma2",
-@@ -715,10 +728,6 @@
- "dma7",
- "dma8",
- "dma9",
-- "dma10",
-- "dma11",
-- "dma12",
-- "dma13",
-- "dma14";
-- brcm,dma-channel-mask = <0x7ef5>;
-+ "dma10";
-+ brcm,dma-channel-mask = <0x01f5>;
- };
---- a/drivers/dma/bcm2835-dma.c
-+++ b/drivers/dma/bcm2835-dma.c
-@@ -50,12 +50,18 @@
- #define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14
- #define BCM2835_DMA_CHAN_NAME_SIZE 8
- #define BCM2835_DMA_BULK_MASK BIT(0)
-+#define BCM2838_DMA_MEMCPY_CHAN 14
-+
-+struct bcm2835_dma_cfg_data {
-+ u32 chan_40bit_mask;
-+};
-
- struct bcm2835_dmadev {
- struct dma_device ddev;
- spinlock_t lock;
- void __iomem *base;
- struct device_dma_parameters dma_parms;
-+ const struct bcm2835_dma_cfg_data *cfg_data;
- };
-
- struct bcm2835_dma_cb {
-@@ -100,6 +106,7 @@ struct bcm2835_chan {
- unsigned int irq_flags;
-
- bool is_lite_channel;
-+ bool is_40bit_channel;
- };
-
- struct bcm2835_desc {
-@@ -189,7 +196,8 @@ struct bcm2835_desc {
- #define BCM2835_DMA_DATA_TYPE_S128 16
-
- /* Valid only for channels 0 - 14, 15 has its own base address */
--#define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */
-+#define BCM2835_DMA_CHAN_SIZE 0x100
-+#define BCM2835_DMA_CHAN(n) ((n) * BCM2835_DMA_CHAN_SIZE) /* Base address */
- #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n))
-
- /* the max dma length for different channels */
-@@ -200,7 +208,7 @@ struct bcm2835_desc {
- #define BCM2838_DMA40_CS 0x00
- #define BCM2838_DMA40_CB 0x04
- #define BCM2838_DMA40_DEBUG 0x0c
--#define BCM2858_DMA40_TI 0x10
-+#define BCM2838_DMA40_TI 0x10
- #define BCM2838_DMA40_SRC 0x14
- #define BCM2838_DMA40_SRCI 0x18
- #define BCM2838_DMA40_DEST 0x1c
-@@ -209,32 +217,97 @@ struct bcm2835_desc {
- #define BCM2838_DMA40_NEXT_CB 0x28
- #define BCM2838_DMA40_DEBUG2 0x2c
-
--#define BCM2838_DMA40_CS_ACTIVE BIT(0)
--#define BCM2838_DMA40_CS_END BIT(1)
-+#define BCM2838_DMA40_ACTIVE BIT(0)
-+#define BCM2838_DMA40_END BIT(1)
-+#define BCM2838_DMA40_INT BIT(2)
-+#define BCM2838_DMA40_DREQ BIT(3) /* DREQ state */
-+#define BCM2838_DMA40_RD_PAUSED BIT(4) /* Reading is paused */
-+#define BCM2838_DMA40_WR_PAUSED BIT(5) /* Writing is paused */
-+#define BCM2838_DMA40_DREQ_PAUSED BIT(6) /* Is paused by DREQ flow control */
-+#define BCM2838_DMA40_WAITING_FOR_WRITES BIT(7) /* Waiting for last write */
-+#define BCM2838_DMA40_ERR BIT(10)
-+#define BCM2838_DMA40_QOS(x) (((x) & 0x1f) << 16)
-+#define BCM2838_DMA40_PANIC_QOS(x) (((x) & 0x1f) << 20)
-+#define BCM2838_DMA40_WAIT_FOR_WRITES BIT(28)
-+#define BCM2838_DMA40_DISDEBUG BIT(29)
-+#define BCM2838_DMA40_ABORT BIT(30)
-+#define BCM2838_DMA40_HALT BIT(31)
-+#define BCM2838_DMA40_CS_FLAGS(x) (x & (BCM2838_DMA40_QOS(15) | \
-+ BCM2838_DMA40_PANIC_QOS(15) | \
-+ BCM2838_DMA40_WAIT_FOR_WRITES | \
-+ BCM2838_DMA40_DISDEBUG))
-+
-+/* Transfer information bits */
-+#define BCM2838_DMA40_INTEN BIT(0)
-+#define BCM2838_DMA40_TDMODE BIT(1) /* 2D-Mode */
-+#define BCM2838_DMA40_WAIT_RESP BIT(2) /* wait for AXI write to be acked */
-+#define BCM2838_DMA40_WAIT_RD_RESP BIT(3) /* wait for AXI read to complete */
-+#define BCM2838_DMA40_PER_MAP(x) ((x & 31) << 9) /* REQ source */
-+#define BCM2838_DMA40_S_DREQ BIT(14) /* enable SREQ for source */
-+#define BCM2838_DMA40_D_DREQ BIT(15) /* enable DREQ for destination */
-+#define BCM2838_DMA40_S_WAIT(x) ((x & 0xff) << 16) /* add DMA read-wait cycles */
-+#define BCM2838_DMA40_D_WAIT(x) ((x & 0xff) << 24) /* add DMA write-wait cycles */
-
--#define BCM2838_DMA40_CS_QOS(x) (((x) & 0x1f) << 16)
--#define BCM2838_DMA40_CS_PANIC_QOS(x) (((x) & 0x1f) << 20)
--#define BCM2838_DMA40_CS_WRITE_WAIT BIT(28)
-+/* debug register bits */
-+#define BCM2838_DMA40_DEBUG_WRITE_ERR BIT(0)
-+#define BCM2838_DMA40_DEBUG_FIFO_ERR BIT(1)
-+#define BCM2838_DMA40_DEBUG_READ_ERR BIT(2)
-+#define BCM2838_DMA40_DEBUG_READ_CB_ERR BIT(3)
-+#define BCM2838_DMA40_DEBUG_IN_ON_ERR BIT(8)
-+#define BCM2838_DMA40_DEBUG_ABORT_ON_ERR BIT(9)
-+#define BCM2838_DMA40_DEBUG_HALT_ON_ERR BIT(10)
-+#define BCM2838_DMA40_DEBUG_DISABLE_CLK_GATE BIT(11)
-+#define BCM2838_DMA40_DEBUG_RSTATE_SHIFT 14
-+#define BCM2838_DMA40_DEBUG_RSTATE_BITS 4
-+#define BCM2838_DMA40_DEBUG_WSTATE_SHIFT 18
-+#define BCM2838_DMA40_DEBUG_WSTATE_BITS 4
-+#define BCM2838_DMA40_DEBUG_RESET BIT(23)
-+#define BCM2838_DMA40_DEBUG_ID_SHIFT 24
-+#define BCM2838_DMA40_DEBUG_ID_BITS 4
-+#define BCM2838_DMA40_DEBUG_VERSION_SHIFT 28
-+#define BCM2838_DMA40_DEBUG_VERSION_BITS 4
-+
-+/* Valid only for channels 0 - 3 (11 - 14) */
-+#define BCM2838_DMA40_CHAN(n) (((n) + 11) << 8) /* Base address */
-+#define BCM2838_DMA40_CHANIO(base, n) ((base) + BCM2838_DMA_CHAN(n))
-
--#define BCM2838_DMA40_BURST_LEN(x) ((((x) - 1) & 0xf) << 8)
--#define BCM2838_DMA40_INC BIT(12)
--#define BCM2838_DMA40_SIZE_128 (2 << 13)
-+/* the max dma length for different channels */
-+#define MAX_DMA40_LEN SZ_1G
-
--#define BCM2838_DMA40_MEMCPY_QOS \
-- (BCM2838_DMA40_CS_QOS(0x0) | \
-- BCM2838_DMA40_CS_PANIC_QOS(0x0) | \
-- BCM2838_DMA40_CS_WRITE_WAIT)
-+#define BCM2838_DMA40_BURST_LEN(x) ((min(x,16) - 1) << 8)
-+#define BCM2838_DMA40_INC BIT(12)
-+#define BCM2838_DMA40_SIZE_32 (0 << 13)
-+#define BCM2838_DMA40_SIZE_64 (1 << 13)
-+#define BCM2838_DMA40_SIZE_128 (2 << 13)
-+#define BCM2838_DMA40_SIZE_256 (3 << 13)
-+#define BCM2838_DMA40_IGNORE BIT(15)
-+#define BCM2838_DMA40_STRIDE(x) ((x) << 16) /* For 2D mode */
-+
-+#define BCM2838_DMA40_MEMCPY_FLAGS \
-+ (BCM2838_DMA40_QOS(0) | \
-+ BCM2838_DMA40_PANIC_QOS(0) | \
-+ BCM2838_DMA40_WAIT_FOR_WRITES | \
-+ BCM2838_DMA40_DISDEBUG)
-
- #define BCM2838_DMA40_MEMCPY_XFER_INFO \
- (BCM2838_DMA40_SIZE_128 | \
- BCM2838_DMA40_INC | \
- BCM2838_DMA40_BURST_LEN(16))
-
-+struct bcm2835_dmadev *memcpy_parent;
- static void __iomem *memcpy_chan;
- static struct bcm2838_dma40_scb *memcpy_scb;
- static dma_addr_t memcpy_scb_dma;
- DEFINE_SPINLOCK(memcpy_lock);
-
-+static const struct bcm2835_dma_cfg_data bcm2835_dma_cfg = {
-+ .chan_40bit_mask = 0,
-+};
-+
-+static const struct bcm2835_dma_cfg_data bcm2838_dma_cfg = {
-+ .chan_40bit_mask = BIT(11) | BIT(12) | BIT(13) | BIT(14),
-+};
-+
- static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c)
- {
- /* lite and normal channels have different max frame length */
-@@ -264,6 +337,32 @@ static inline struct bcm2835_desc *to_bc
- return container_of(t, struct bcm2835_desc, vd.tx);
- }
-
-+static inline uint32_t to_bcm2838_ti(uint32_t info)
-+{
-+ return ((info & BCM2835_DMA_INT_EN) ? BCM2838_DMA40_INTEN : 0) |
-+ ((info & BCM2835_DMA_WAIT_RESP) ? BCM2838_DMA40_WAIT_RESP : 0) |
-+ ((info & BCM2835_DMA_S_DREQ) ?
-+ (BCM2838_DMA40_S_DREQ | BCM2838_DMA40_WAIT_RD_RESP) : 0) |
-+ ((info & BCM2835_DMA_D_DREQ) ? BCM2838_DMA40_D_DREQ : 0) |
-+ BCM2838_DMA40_PER_MAP((info >> 16) & 0x1f);
-+}
-+
-+static inline uint32_t to_bcm2838_srci(uint32_t info)
-+{
-+ return ((info & BCM2835_DMA_S_INC) ? BCM2838_DMA40_INC : 0);
-+}
-+
-+static inline uint32_t to_bcm2838_dsti(uint32_t info)
-+{
-+ return ((info & BCM2835_DMA_D_INC) ? BCM2838_DMA40_INC : 0);
-+}
-+
-+static inline uint32_t to_bcm2838_cbaddr(dma_addr_t addr)
-+{
-+ BUG_ON(addr & 0x1f);
-+ return (addr >> 5);
-+}
-+
- static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc)
- {
- size_t i;
-@@ -282,45 +381,53 @@ static void bcm2835_dma_desc_free(struct
- }
-
- static void bcm2835_dma_create_cb_set_length(
-- struct bcm2835_chan *chan,
-+ struct bcm2835_chan *c,
- struct bcm2835_dma_cb *control_block,
- size_t len,
- size_t period_len,
- size_t *total_len,
- u32 finalextrainfo)
- {
-- size_t max_len = bcm2835_dma_max_frame_length(chan);
-+ size_t max_len = bcm2835_dma_max_frame_length(c);
-+ uint32_t cb_len;
-
- /* set the length taking lite-channel limitations into account */
-- control_block->length = min_t(u32, len, max_len);
-+ cb_len = min_t(u32, len, max_len);
-
-- /* finished if we have no period_length */
-- if (!period_len)
-- return;
-+ if (period_len) {
-+ /*
-+ * period_len means: that we need to generate
-+ * transfers that are terminating at every
-+ * multiple of period_len - this is typically
-+ * used to set the interrupt flag in info
-+ * which is required during cyclic transfers
-+ */
-
-- /*
-- * period_len means: that we need to generate
-- * transfers that are terminating at every
-- * multiple of period_len - this is typically
-- * used to set the interrupt flag in info
-- * which is required during cyclic transfers
-- */
-+ /* have we filled in period_length yet? */
-+ if (*total_len + cb_len < period_len) {
-+ /* update number of bytes in this period so far */
-+ *total_len += cb_len;
-+ } else {
-+ /* calculate the length that remains to reach period_len */
-+ cb_len = period_len - *total_len;
-
-- /* have we filled in period_length yet? */
-- if (*total_len + control_block->length < period_len) {
-- /* update number of bytes in this period so far */
-- *total_len += control_block->length;
-- return;
-+ /* reset total_length for next period */
-+ *total_len = 0;
-+ }
- }
-
-- /* calculate the length that remains to reach period_length */
-- control_block->length = period_len - *total_len;
--
-- /* reset total_length for next period */
-- *total_len = 0;
--
-- /* add extrainfo bits in info */
-- control_block->info |= finalextrainfo;
-+ if (c->is_40bit_channel) {
-+ struct bcm2838_dma40_scb *scb =
-+ (struct bcm2838_dma40_scb *)control_block;
-+
-+ scb->len = cb_len;
-+ /* add extrainfo bits to ti */
-+ scb->ti |= to_bcm2838_ti(finalextrainfo);
-+ } else {
-+ control_block->length = cb_len;
-+ /* add extrainfo bits to info */
-+ control_block->info |= finalextrainfo;
-+ }
- }
-
- static inline size_t bcm2835_dma_count_frames_for_sg(
-@@ -343,7 +450,7 @@ static inline size_t bcm2835_dma_count_f
- /**
- * bcm2835_dma_create_cb_chain - create a control block and fills data in
- *
-- * @chan: the @dma_chan for which we run this
-+ * @c: the @bcm2835_chan for which we run this
- * @direction: the direction in which we transfer
- * @cyclic: it is a cyclic transfer
- * @info: the default info bits to apply per controlblock
-@@ -361,12 +468,11 @@ static inline size_t bcm2835_dma_count_f
- * @gfp: the GFP flag to use for allocation
- */
- static struct bcm2835_desc *bcm2835_dma_create_cb_chain(
-- struct dma_chan *chan, enum dma_transfer_direction direction,
-+ struct bcm2835_chan *c, enum dma_transfer_direction direction,
- bool cyclic, u32 info, u32 finalextrainfo, size_t frames,
- dma_addr_t src, dma_addr_t dst, size_t buf_len,
- size_t period_len, gfp_t gfp)
- {
-- struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
- size_t len = buf_len, total_len;
- size_t frame;
- struct bcm2835_desc *d;
-@@ -399,11 +505,23 @@ static struct bcm2835_desc *bcm2835_dma_
-
- /* fill in the control block */
- control_block = cb_entry->cb;
-- control_block->info = info;
-- control_block->src = src;
-- control_block->dst = dst;
-- control_block->stride = 0;
-- control_block->next = 0;
-+ if (c->is_40bit_channel) {
-+ struct bcm2838_dma40_scb *scb =
-+ (struct bcm2838_dma40_scb *)control_block;
-+ scb->ti = to_bcm2838_ti(info);
-+ scb->src = lower_32_bits(src);
-+ scb->srci= upper_32_bits(src) | to_bcm2838_srci(info);
-+ scb->dst = lower_32_bits(dst);
-+ scb->dsti = upper_32_bits(dst) | to_bcm2838_dsti(info);
-+ scb->next_cb = 0;
-+ } else {
-+ control_block->info = info;
-+ control_block->src = src;
-+ control_block->dst = dst;
-+ control_block->stride = 0;
-+ control_block->next = 0;
-+ }
-+
- /* set up length in control_block if requested */
- if (buf_len) {
- /* calculate length honoring period_length */
-@@ -417,7 +535,10 @@ static struct bcm2835_desc *bcm2835_dma_
- }
-
- /* link this the last controlblock */
-- if (frame)
-+ if (frame && c->is_40bit_channel)
-+ d->cb_list[frame - 1].cb->next =
-+ to_bcm2838_cbaddr(cb_entry->paddr);
-+ if (frame && !c->is_40bit_channel)
- d->cb_list[frame - 1].cb->next = cb_entry->paddr;
-
- /* update src and dst and length */
-@@ -431,7 +552,14 @@ static struct bcm2835_desc *bcm2835_dma_
- }
-
- /* the last frame requires extra flags */
-- d->cb_list[d->frames - 1].cb->info |= finalextrainfo;
-+ if (c->is_40bit_channel) {
-+ struct bcm2838_dma40_scb *scb =
-+ (struct bcm2838_dma40_scb *)d->cb_list[d->frames-1].cb;
-+
-+ scb->ti |= to_bcm2838_ti(finalextrainfo);
-+ } else {
-+ d->cb_list[d->frames - 1].cb->info |= finalextrainfo;
-+ }
-
- /* detect a size missmatch */
- if (buf_len && (d->size != buf_len))
-@@ -445,28 +573,51 @@ error_cb:
- }
-
- static void bcm2835_dma_fill_cb_chain_with_sg(
-- struct dma_chan *chan,
-+ struct bcm2835_chan *c,
- enum dma_transfer_direction direction,
- struct bcm2835_cb_entry *cb,
- struct scatterlist *sgl,
- unsigned int sg_len)
- {
-- struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
- size_t len, max_len;
- unsigned int i;
- dma_addr_t addr;
- struct scatterlist *sgent;
-
-+ pr_err("dma_fill_chain_with_sg(ch %d, dir %d):\n", c->ch, direction);
-+
- max_len = bcm2835_dma_max_frame_length(c);
- for_each_sg(sgl, sgent, sg_len, i) {
-- for (addr = sg_dma_address(sgent), len = sg_dma_len(sgent);
-- len > 0;
-- addr += cb->cb->length, len -= cb->cb->length, cb++) {
-- if (direction == DMA_DEV_TO_MEM)
-- cb->cb->dst = addr;
-- else
-- cb->cb->src = addr;
-- cb->cb->length = min(len, max_len);
-+ if (c->is_40bit_channel) {
-+ struct bcm2838_dma40_scb *scb =
-+ (struct bcm2838_dma40_scb *)cb->cb;
-+ for (addr = sg_dma_address(sgent),
-+ len = sg_dma_len(sgent);
-+ len > 0;
-+ addr += scb->len, len -= scb->len, scb++) {
-+ if (direction == DMA_DEV_TO_MEM) {
-+ scb->dst = lower_32_bits(addr);
-+ scb->dsti = upper_32_bits(addr) | BCM2838_DMA40_INC;
-+ } else {
-+ scb->src = lower_32_bits(addr);
-+ scb->srci = upper_32_bits(addr) | BCM2838_DMA40_INC;
-+ }
-+ scb->len = min(len, max_len);
-+ pr_err(" %llx, %x\n", (u64)addr, scb->len);
-+ }
-+ } else {
-+ for (addr = sg_dma_address(sgent),
-+ len = sg_dma_len(sgent);
-+ len > 0;
-+ addr += cb->cb->length, len -= cb->cb->length,
-+ cb++) {
-+ if (direction == DMA_DEV_TO_MEM)
-+ cb->cb->dst = addr;
-+ else
-+ cb->cb->src = addr;
-+ cb->cb->length = min(len, max_len);
-+ pr_err(" %llx, %x\n", (u64)addr, cb->cb->length);
-+ }
- }
- }
- }
-@@ -475,6 +626,10 @@ static int bcm2835_dma_abort(struct bcm2
- {
- void __iomem *chan_base = c->chan_base;
- long int timeout = 10000;
-+ u32 wait_mask = BCM2835_DMA_WAITING_FOR_WRITES;
-+
-+ if (c->is_40bit_channel)
-+ wait_mask = BCM2838_DMA40_WAITING_FOR_WRITES;
-
- /*
- * A zero control block address means the channel is idle.
-@@ -487,8 +642,7 @@ static int bcm2835_dma_abort(struct bcm2
- writel(0, chan_base + BCM2835_DMA_CS);
-
- /* Wait for any current AXI transfer to complete */
-- while ((readl(chan_base + BCM2835_DMA_CS) &
-- BCM2835_DMA_WAITING_FOR_WRITES) && --timeout)
-+ while ((readl(chan_base + BCM2835_DMA_CS) & wait_mask) && --timeout)
- cpu_relax();
-
- /* Peripheral might be stuck and fail to signal AXI write responses */
-@@ -505,6 +659,7 @@ static void bcm2835_dma_start_desc(struc
- struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
- struct bcm2835_desc *d;
-
-+ pr_err("dma_start_desc(%px)\n", vd);
- if (!vd) {
- c->desc = NULL;
- return;
-@@ -514,9 +669,16 @@ static void bcm2835_dma_start_desc(struc
-
- c->desc = d = to_bcm2835_dma_desc(&vd->tx);
-
-- writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
-- writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq),
-- c->chan_base + BCM2835_DMA_CS);
-+ if (c->is_40bit_channel) {
-+ writel(to_bcm2838_cbaddr(d->cb_list[0].paddr),
-+ c->chan_base + BCM2838_DMA40_CB);
-+ writel(BCM2838_DMA40_ACTIVE | BCM2838_DMA40_CS_FLAGS(c->dreq),
-+ c->chan_base + BCM2838_DMA40_CS);
-+ } else {
-+ writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
-+ writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq),
-+ c->chan_base + BCM2835_DMA_CS);
-+ }
- }
-
- static irqreturn_t bcm2835_dma_callback(int irq, void *data)
-@@ -544,7 +706,8 @@ static irqreturn_t bcm2835_dma_callback(
- * will remain idle despite the ACTIVE flag being set.
- */
- writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE |
-- BCM2835_DMA_CS_FLAGS(c->dreq),
-+ (c->is_40bit_channel ? BCM2838_DMA40_CS_FLAGS(c->dreq) :
-+ BCM2835_DMA_CS_FLAGS(c->dreq)),
- c->chan_base + BCM2835_DMA_CS);
-
- d = c->desc;
-@@ -643,9 +806,17 @@ static enum dma_status bcm2835_dma_tx_st
- struct bcm2835_desc *d = c->desc;
- dma_addr_t pos;
-
-- if (d->dir == DMA_MEM_TO_DEV)
-+ if (d->dir == DMA_MEM_TO_DEV && c->is_40bit_channel)
-+ pos = readl(c->chan_base + BCM2838_DMA40_SRC) +
-+ ((readl(c->chan_base + BCM2838_DMA40_SRCI) &
-+ 0xff) << 8);
-+ else if (d->dir == DMA_MEM_TO_DEV && !c->is_40bit_channel)
- pos = readl(c->chan_base + BCM2835_DMA_SOURCE_AD);
-- else if (d->dir == DMA_DEV_TO_MEM)
-+ else if (d->dir == DMA_DEV_TO_MEM && c->is_40bit_channel)
-+ pos = readl(c->chan_base + BCM2838_DMA40_DEST) +
-+ ((readl(c->chan_base + BCM2838_DMA40_DESTI) &
-+ 0xff) << 8);
-+ else if (d->dir == DMA_DEV_TO_MEM && !c->is_40bit_channel)
- pos = readl(c->chan_base + BCM2835_DMA_DEST_AD);
- else
- pos = 0;
-@@ -691,7 +862,7 @@ static struct dma_async_tx_descriptor *b
- frames = bcm2835_dma_frames_for_length(len, max_len);
-
- /* allocate the CB chain - this also fills in the pointers */
-- d = bcm2835_dma_create_cb_chain(chan, DMA_MEM_TO_MEM, false,
-+ d = bcm2835_dma_create_cb_chain(c, DMA_MEM_TO_MEM, false,
- info, extra, frames,
- src, dst, len, 0, GFP_KERNEL);
- if (!d)
-@@ -726,11 +897,21 @@ static struct dma_async_tx_descriptor *b
- if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
- return NULL;
- src = c->cfg.src_addr;
-+ /*
-+ * One would think it ought to be possible to get the physical
-+ * to dma address mapping information from the dma-ranges DT
-+ * property, but I've not found a way yet that doesn't involve
-+ * open-coding the whole thing.
-+ */
-+ if (c->is_40bit_channel)
-+ src |= 0x400000000ull;
- info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC;
- } else {
- if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
- return NULL;
- dst = c->cfg.dst_addr;
-+ if (c->is_40bit_channel)
-+ dst |= 0x400000000ull;
- info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC;
- }
-
-@@ -738,7 +919,7 @@ static struct dma_async_tx_descriptor *b
- frames = bcm2835_dma_count_frames_for_sg(c, sgl, sg_len);
-
- /* allocate the CB chain */
-- d = bcm2835_dma_create_cb_chain(chan, direction, false,
-+ d = bcm2835_dma_create_cb_chain(c, direction, false,
- info, extra,
- frames, src, dst, 0, 0,
- GFP_KERNEL);
-@@ -746,7 +927,7 @@ static struct dma_async_tx_descriptor *b
- return NULL;
-
- /* fill in frames with scatterlist pointers */
-- bcm2835_dma_fill_cb_chain_with_sg(chan, direction, d->cb_list,
-+ bcm2835_dma_fill_cb_chain_with_sg(c, direction, d->cb_list,
- sgl, sg_len);
-
- return vchan_tx_prep(&c->vc, &d->vd, flags);
-@@ -815,7 +996,7 @@ static struct dma_async_tx_descriptor *b
- * note that we need to use GFP_NOWAIT, as the ALSA i2s dmaengine
- * implementation calls prep_dma_cyclic with interrupts disabled.
- */
-- d = bcm2835_dma_create_cb_chain(chan, direction, true,
-+ d = bcm2835_dma_create_cb_chain(c, direction, true,
- info, extra,
- frames, src, dst, buf_len,
- period_len, GFP_NOWAIT);
-@@ -823,7 +1004,8 @@ static struct dma_async_tx_descriptor *b
- return NULL;
-
- /* wrap around into a loop */
-- d->cb_list[d->frames - 1].cb->next = d->cb_list[0].paddr;
-+ d->cb_list[d->frames - 1].cb->next = c->is_40bit_channel ?
-+ to_bcm2838_cbaddr(d->cb_list[0].paddr) : d->cb_list[0].paddr;
-
- return vchan_tx_prep(&c->vc, &d->vd, flags);
- }
-@@ -899,9 +1081,11 @@ static int bcm2835_dma_chan_init(struct
- c->irq_number = irq;
- c->irq_flags = irq_flags;
-
-- /* check in DEBUG register if this is a LITE channel */
-- if (readl(c->chan_base + BCM2835_DMA_DEBUG) &
-- BCM2835_DMA_DEBUG_LITE)
-+ /* check for 40bit and lite channels */
-+ if (d->cfg_data->chan_40bit_mask & BIT(chan_id))
-+ c->is_40bit_channel = true;
-+ else if (readl(c->chan_base + BCM2835_DMA_DEBUG) &
-+ BCM2835_DMA_DEBUG_LITE)
- c->is_lite_channel = true;
-
- return 0;
-@@ -918,18 +1102,16 @@ static void bcm2835_dma_free(struct bcm2
- }
- }
-
--int bcm2838_dma40_memcpy_init(struct device *dev)
-+int bcm2838_dma40_memcpy_init(void)
- {
-- if (memcpy_scb)
-- return 0;
-+ if (!memcpy_parent)
-+ return -EPROBE_DEFER;
-
-- memcpy_scb = dma_alloc_coherent(dev, sizeof(*memcpy_scb),
-- &memcpy_scb_dma, GFP_KERNEL);
-+ if (!memcpy_chan)
-+ return -EINVAL;
-
-- if (!memcpy_scb) {
-- pr_err("bcm2838_dma40_memcpy_init failed!\n");
-+ if (!memcpy_scb)
- return -ENOMEM;
-- }
-
- return 0;
- }
-@@ -956,20 +1138,22 @@ void bcm2838_dma40_memcpy(dma_addr_t dst
- scb->next_cb = 0;
-
- writel((u32)(memcpy_scb_dma >> 5), memcpy_chan + BCM2838_DMA40_CB);
-- writel(BCM2838_DMA40_MEMCPY_QOS + BCM2838_DMA40_CS_ACTIVE,
-+ writel(BCM2838_DMA40_MEMCPY_FLAGS + BCM2838_DMA40_ACTIVE,
- memcpy_chan + BCM2838_DMA40_CS);
-+
- /* Poll for completion */
-- while (!(readl(memcpy_chan + BCM2838_DMA40_CS) & BCM2838_DMA40_CS_END))
-+ while (!(readl(memcpy_chan + BCM2838_DMA40_CS) & BCM2838_DMA40_END))
- cpu_relax();
-
-- writel(BCM2838_DMA40_CS_END, memcpy_chan + BCM2838_DMA40_CS);
-+ writel(BCM2838_DMA40_END, memcpy_chan + BCM2838_DMA40_CS);
-
- spin_unlock_irqrestore(&memcpy_lock, flags);
- }
- EXPORT_SYMBOL(bcm2838_dma40_memcpy);
-
- static const struct of_device_id bcm2835_dma_of_match[] = {
-- { .compatible = "brcm,bcm2835-dma", },
-+ { .compatible = "brcm,bcm2835-dma", .data = &bcm2835_dma_cfg },
-+ { .compatible = "brcm,bcm2838-dma", .data = &bcm2838_dma_cfg },
- {},
- };
- MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match);
-@@ -1001,6 +1185,8 @@ static int bcm2835_dma_probe(struct plat
- int irq_flags;
- uint32_t chans_available;
- char chan_name[BCM2835_DMA_CHAN_NAME_SIZE];
-+ const struct of_device_id *of_id;
-+ int chan_count, chan_start, chan_end;
-
- if (!pdev->dev.dma_mask)
- pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-@@ -1020,9 +1206,13 @@ static int bcm2835_dma_probe(struct plat
- base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(base))
- return PTR_ERR(base);
-- rc = bcm_dmaman_probe(pdev, base, BCM2835_DMA_BULK_MASK);
-- if (rc)
-- dev_err(&pdev->dev, "Failed to initialize the legacy API\n");
-+
-+ /* The set of channels can be split across multiple instances. */
-+ chan_start = ((u32)base / BCM2835_DMA_CHAN_SIZE) & 0xf;
-+ base -= BCM2835_DMA_CHAN(chan_start);
-+ chan_count = resource_size(res) / BCM2835_DMA_CHAN_SIZE;
-+ chan_end = min(chan_start + chan_count,
-+ BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED + 1);
-
- od->base = base;
-
-@@ -1052,6 +1242,14 @@ static int bcm2835_dma_probe(struct plat
-
- platform_set_drvdata(pdev, od);
-
-+ of_id = of_match_node(bcm2835_dma_of_match, pdev->dev.of_node);
-+ if (!of_id) {
-+ dev_err(&pdev->dev, "Failed to match compatible string\n");
-+ return -EINVAL;
-+ }
-+
-+ od->cfg_data = of_id->data;
-+
- /* Request DMA channel mask from device tree */
- if (of_property_read_u32(pdev->dev.of_node,
- "brcm,dma-channel-mask",
-@@ -1061,18 +1259,34 @@ static int bcm2835_dma_probe(struct plat
- goto err_no_dma;
- }
-
-- /* Channel 0 is used by the legacy API */
-- chans_available &= ~BCM2835_DMA_BULK_MASK;
-+ /* One channel is reserved for the legacy API */
-+ if (chans_available & BCM2835_DMA_BULK_MASK) {
-+ rc = bcm_dmaman_probe(pdev, base,
-+ chans_available & BCM2835_DMA_BULK_MASK);
-+ if (rc)
-+ dev_err(&pdev->dev,
-+ "Failed to initialize the legacy API\n");
-+
-+ chans_available &= ~BCM2835_DMA_BULK_MASK;
-+ }
-
-- /* We can't use channels 11-13 yet */
-- chans_available &= ~(BIT(11) | BIT(12) | BIT(13));
-+ /* And possibly one for the 40-bit DMA memcpy API */
-+ if (chans_available & od->cfg_data->chan_40bit_mask &
-+ BIT(BCM2838_DMA_MEMCPY_CHAN)) {
-+ memcpy_parent = od;
-+ memcpy_chan = BCM2835_DMA_CHANIO(base, BCM2838_DMA_MEMCPY_CHAN);
-+ memcpy_scb = dma_alloc_coherent(memcpy_parent->ddev.dev,
-+ sizeof(*memcpy_scb),
-+ &memcpy_scb_dma, GFP_KERNEL);
-+ if (!memcpy_scb)
-+ dev_warn(&pdev->dev,
-+ "Failed to allocated memcpy scb\n");
-
-- /* Grab channel 14 for the 40-bit DMA memcpy */
-- chans_available &= ~BIT(14);
-- memcpy_chan = BCM2835_DMA_CHANIO(base, 14);
-+ chans_available &= ~BIT(BCM2838_DMA_MEMCPY_CHAN);
-+ }
-
- /* get irqs for each channel that we support */
-- for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
-+ for (i = chan_start; i < chan_end; i++) {
- /* skip masked out channels */
- if (!(chans_available & (1 << i))) {
- irq[i] = -1;
-@@ -1095,13 +1309,17 @@ static int bcm2835_dma_probe(struct plat
- irq[i] = platform_get_irq(pdev, i < 11 ? i : 11);
- }
-
-+ chan_count = 0;
-+
- /* get irqs for each channel */
-- for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
-+ for (i = chan_start; i < chan_end; i++) {
- /* skip channels without irq */
- if (irq[i] < 0)
- continue;
-
- /* check if there are other channels that also use this irq */
-+ /* FIXME: This will fail if interrupts are shared across
-+ instances */
- irq_flags = 0;
- for (j = 0; j <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; j++)
- if ((i != j) && (irq[j] == irq[i])) {
-@@ -1113,9 +1331,10 @@ static int bcm2835_dma_probe(struct plat
- rc = bcm2835_dma_chan_init(od, i, irq[i], irq_flags);
- if (rc)
- goto err_no_dma;
-+ chan_count++;
- }
-
-- dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", i);
-+ dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", chan_count);
-
- /* Device-tree DMA controller registration */
- rc = of_dma_controller_register(pdev->dev.of_node,
-@@ -1147,6 +1366,13 @@ static int bcm2835_dma_remove(struct pla
-
- bcm_dmaman_remove(pdev);
- dma_async_device_unregister(&od->ddev);
-+ if (memcpy_parent == od) {
-+ dma_free_coherent(&pdev->dev, sizeof(*memcpy_scb), memcpy_scb,
-+ memcpy_scb_dma);
-+ memcpy_parent = NULL;
-+ memcpy_scb = NULL;
-+ memcpy_chan = NULL;
-+ }
- bcm2835_dma_free(od);
-
- return 0;
---- a/drivers/pci/controller/pcie-brcmstb-bounce.c
-+++ b/drivers/pci/controller/pcie-brcmstb-bounce.c
-@@ -91,7 +91,7 @@ struct dmabounce_device_info {
-
- static struct dmabounce_device_info *g_dmabounce_device_info;
-
--extern int bcm2838_dma40_memcpy_init(struct device *dev);
-+extern int bcm2838_dma40_memcpy_init(void);
- extern void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size);
-
- #ifdef STATS
-@@ -471,9 +471,9 @@ static const struct dma_map_ops dmabounc
- .mapping_error = dmabounce_mapping_error,
- };
-
--int brcm_pcie_bounce_register_dev(struct device *dev,
-- unsigned long buffer_size,
-- dma_addr_t threshold)
-+int brcm_pcie_bounce_init(struct device *dev,
-+ unsigned long buffer_size,
-+ dma_addr_t threshold)
- {
- struct dmabounce_device_info *device_info;
- int ret;
-@@ -482,9 +482,9 @@ int brcm_pcie_bounce_register_dev(struct
- if (g_dmabounce_device_info)
- return -EBUSY;
-
-- ret = bcm2838_dma40_memcpy_init(dev);
-+ ret = bcm2838_dma40_memcpy_init();
- if (ret)
-- return ret;
-+ return ret;
-
- device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
- if (!device_info) {
-@@ -515,9 +515,8 @@ int brcm_pcie_bounce_register_dev(struct
- device_create_file(dev, &dev_attr_dmabounce_stats));
-
- g_dmabounce_device_info = device_info;
-- set_dma_ops(dev, &dmabounce_ops);
-
-- dev_info(dev, "dmabounce: registered device - %ld kB, threshold %pad\n",
-+ dev_info(dev, "dmabounce: initialised - %ld kB, threshold %pad\n",
- buffer_size / 1024, &threshold);
-
- return 0;
-@@ -526,14 +525,13 @@ int brcm_pcie_bounce_register_dev(struct
- kfree(device_info);
- return ret;
- }
--EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
-+EXPORT_SYMBOL(brcm_pcie_bounce_init);
-
--void brcm_pcie_bounce_unregister_dev(struct device *dev)
-+void brcm_pcie_bounce_uninit(struct device *dev)
- {
- struct dmabounce_device_info *device_info = g_dmabounce_device_info;
-
- g_dmabounce_device_info = NULL;
-- set_dma_ops(dev, NULL);
-
- if (!device_info) {
- dev_warn(dev,
-@@ -554,10 +552,16 @@ void brcm_pcie_bounce_unregister_dev(str
- device_remove_file(dev, &dev_attr_dmabounce_stats));
-
- kfree(device_info);
-+}
-+EXPORT_SYMBOL(brcm_pcie_bounce_uninit);
-+
-+int brcm_pcie_bounce_register_dev(struct device *dev)
-+{
-+ set_dma_ops(dev, &dmabounce_ops);
-
-- dev_info(dev, "dmabounce: device unregistered\n");
-+ return 0;
- }
--EXPORT_SYMBOL(brcm_pcie_bounce_unregister_dev);
-+EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
-
- MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.org>");
- MODULE_DESCRIPTION("Dedicate DMA bounce support for pcie-brcmstb");
---- a/drivers/pci/controller/pcie-brcmstb-bounce.h
-+++ b/drivers/pci/controller/pcie-brcmstb-bounce.h
-@@ -8,21 +8,26 @@
-
- #ifdef CONFIG_ARM
-
--int brcm_pcie_bounce_register_dev(struct device *dev, unsigned long buffer_size,
-- dma_addr_t threshold);
--
--int brcm_pcie_bounce_unregister_dev(struct device *dev);
-+int brcm_pcie_bounce_init(struct device *dev, unsigned long buffer_size,
-+ dma_addr_t threshold);
-+int brcm_pcie_bounce_uninit(struct device *dev);
-+int brcm_pcie_bounce_register_dev(struct device *dev);
-
- #else
-
--static inline int brcm_pcie_bounce_register_dev(struct device *dev,
-- unsigned long buffer_size,
-- dma_addr_t threshold)
-+static inline int brcm_pcie_bounce_init(struct device *dev,
-+ unsigned long buffer_size,
-+ dma_addr_t threshold)
-+{
-+ return 0;
-+}
-+
-+static inline int brcm_pcie_bounce_uninit(struct device *dev)
- {
- return 0;
- }
-
--static inline int brcm_pcie_bounce_unregister_dev(struct device *dev)
-+static inline int brcm_pcie_bounce_register_dev(struct device *dev)
- {
- return 0;
- }
---- a/drivers/pci/controller/pcie-brcmstb.c
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -650,6 +650,7 @@ static void brcm_set_dma_ops(struct devi
-
- static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie,
- unsigned int val);
-+
- static int brcmstb_platform_notifier(struct notifier_block *nb,
- unsigned long event, void *__dev)
- {
-@@ -663,12 +664,11 @@ static int brcmstb_platform_notifier(str
- strcmp(dev->kobj.name, rc_name)) {
- int ret;
-
-- ret = brcm_pcie_bounce_register_dev(dev, bounce_buffer,
-- (dma_addr_t)bounce_threshold);
-+ ret = brcm_pcie_bounce_register_dev(dev);
- if (ret) {
- dev_err(dev,
- "brcm_pcie_bounce_register_dev() failed: %d\n",
-- ret);
-+ ret);
- return ret;
- }
- }
-@@ -681,8 +681,6 @@ static int brcmstb_platform_notifier(str
- brcm_pcie_perst_set(g_pcie, 1);
- msleep(100);
- brcm_pcie_perst_set(g_pcie, 0);
-- } else if (max_pfn > (bounce_threshold/PAGE_SIZE)) {
-- brcm_pcie_bounce_unregister_dev(dev);
- }
- return NOTIFY_OK;
-
-@@ -1718,6 +1716,7 @@ static int brcm_pcie_probe(struct platfo
- void __iomem *base;
- struct pci_host_bridge *bridge;
- struct pci_bus *child;
-+ extern unsigned long max_pfn;
-
- bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie));
- if (!bridge)
-@@ -1753,6 +1752,20 @@ static int brcm_pcie_probe(struct platfo
- if (IS_ERR(base))
- return PTR_ERR(base);
-
-+ /* To Do: Add hardware check if this ever gets fixed */
-+ if (max_pfn > (bounce_threshold/PAGE_SIZE)) {
-+ int ret;
-+ ret = brcm_pcie_bounce_init(&pdev->dev, bounce_buffer,
-+ (dma_addr_t)bounce_threshold);
-+ if (ret) {
-+ if (ret != -EPROBE_DEFER)
-+ dev_err(&pdev->dev,
-+ "could not init bounce buffers: %d\n",
-+ ret);
-+ return ret;
-+ }
-+ }
-+
- pcie->clk = of_clk_get_by_name(dn, "sw_pcie");
- if (IS_ERR(pcie->clk)) {
- dev_warn(&pdev->dev, "could not get clock\n");
--- /dev/null
+From 8d2aeaf1d4eecfd8b11c2ba5dcf33d228dd76a6a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 31 May 2019 17:57:26 +0100
+Subject: [PATCH 650/725] dts: Include CSI lane config for csi1
+
+Without the include the peripheral is configured to have 0
+data lanes, which doesn't allow much data to be passed.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+
+ #include "bcm2711.dtsi"
++#include "bcm283x-rpi-csi1-2lane.dtsi"
+
+ / {
+ compatible = "raspberrypi,4-model-b", "brcm,bcm2838", "brcm,bcm2837";
+++ /dev/null
-From 9f8ebf6f517f48041ccb16b80493537eb8522738 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 5 Jun 2019 21:32:03 +0100
-Subject: [PATCH 651/703] BCM270X_DT: Leave bulk channel in dma channel mask
-
-The updated bcm2835-dma driver does not require the BULK channel
-to be removed from the set of available channels, as provided by
-dma-channel-mask.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2708-rpi.dtsi | 4 ----
- 1 file changed, 4 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
-@@ -124,10 +124,6 @@
- };
- };
-
--&dma {
-- brcm,dma-channel-mask = <0x7f34>;
--};
--
- &hdmi {
- power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
- };
--- /dev/null
+From cc761034521f5c47193a8c2f6ac48a7961f85761 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 7 Jun 2019 11:31:21 +0100
+Subject: [PATCH 651/725] drm/vc4: Fix T-format modifiers in FKMS.
+
+The wrong vc_image formats were being checked for in the switch
+statement. Correct these.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -458,10 +458,10 @@ static void vc4_plane_atomic_update(stru
+ switch (fb->modifier) {
+ case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
+ switch (mb->plane.vc_image_type) {
+- case VC_IMAGE_RGBX32:
++ case VC_IMAGE_XRGB8888:
+ mb->plane.vc_image_type = VC_IMAGE_TF_RGBX32;
+ break;
+- case VC_IMAGE_RGBA32:
++ case VC_IMAGE_ARGB8888:
+ mb->plane.vc_image_type = VC_IMAGE_TF_RGBA32;
+ break;
+ case VC_IMAGE_RGB565:
+++ /dev/null
-From b7780ddb8e7f651f247dfccba05bdc75727abc3c Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 6 Jun 2019 09:35:08 +0100
-Subject: [PATCH 652/703] SQUASH: bcm2835-dma: Remove debugging
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/dma/bcm2835-dma.c | 5 -----
- 1 file changed, 5 deletions(-)
-
---- a/drivers/dma/bcm2835-dma.c
-+++ b/drivers/dma/bcm2835-dma.c
-@@ -584,8 +584,6 @@ static void bcm2835_dma_fill_cb_chain_wi
- dma_addr_t addr;
- struct scatterlist *sgent;
-
-- pr_err("dma_fill_chain_with_sg(ch %d, dir %d):\n", c->ch, direction);
--
- max_len = bcm2835_dma_max_frame_length(c);
- for_each_sg(sgl, sgent, sg_len, i) {
- if (c->is_40bit_channel) {
-@@ -603,7 +601,6 @@ static void bcm2835_dma_fill_cb_chain_wi
- scb->srci = upper_32_bits(addr) | BCM2838_DMA40_INC;
- }
- scb->len = min(len, max_len);
-- pr_err(" %llx, %x\n", (u64)addr, scb->len);
- }
- } else {
- for (addr = sg_dma_address(sgent),
-@@ -616,7 +613,6 @@ static void bcm2835_dma_fill_cb_chain_wi
- else
- cb->cb->src = addr;
- cb->cb->length = min(len, max_len);
-- pr_err(" %llx, %x\n", (u64)addr, cb->cb->length);
- }
- }
- }
-@@ -659,7 +655,6 @@ static void bcm2835_dma_start_desc(struc
- struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
- struct bcm2835_desc *d;
-
-- pr_err("dma_start_desc(%px)\n", vd);
- if (!vd) {
- c->desc = NULL;
- return;
--- /dev/null
+From d2b90294279c1479a650f85256275624908033bf Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 7 Jun 2019 11:35:01 +0100
+Subject: [PATCH 652/725] defconfigs: Add FB_SIMPLE to both bcmrpi and bcm2709
+ configs
+
+The firmware sets up simple fb should one of the KMS drivers
+be enabled, but the driver isn't being built.
+Add it to the build.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -928,6 +928,7 @@ CONFIG_TINYDRM_REPAPER=m
+ CONFIG_FB=y
+ CONFIG_FB_BCM2708=y
+ CONFIG_FB_UDL=m
++CONFIG_FB_SIMPLE=y
+ CONFIG_FB_SSD1307=m
+ CONFIG_FB_RPISENSE=m
+ # CONFIG_BACKLIGHT_GENERIC is not set
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -920,6 +920,7 @@ CONFIG_TINYDRM_REPAPER=m
+ CONFIG_FB=y
+ CONFIG_FB_BCM2708=y
+ CONFIG_FB_UDL=m
++CONFIG_FB_SIMPLE=y
+ CONFIG_FB_SSD1307=m
+ CONFIG_FB_RPISENSE=m
+ # CONFIG_BACKLIGHT_GENERIC is not set
--- /dev/null
+From bf7cf5876d809d13cbab812b10c7549edbd20990 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 10 Jun 2019 17:22:44 +0100
+Subject: [PATCH 653/725] bcm2711 dts: Disable the v3d node by default
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2711.dtsi | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm2711.dtsi
++++ b/arch/arm/boot/dts/bcm2711.dtsi
+@@ -13,6 +13,10 @@
+ };
+ };
+
++&v3d {
++ status = "disabled";
++};
++
+ &dma {
+ brcm,dma-channel-mask = <0x7ef5>;
+ };
+++ /dev/null
-From 72ea8706ae509fb2d85c3eac6190e3fb43a6dc0f Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 6 Jun 2019 15:22:29 +0100
-Subject: [PATCH 653/703] defconfig: Update bcm2711 to match bcm2709 on extra
- modules
-
-Lots of things like USB DVB tuners were missing from the
-defconfig.
-Resync it with bcm2709_defconfig
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm/configs/bcm2711_defconfig | 97 ++++++++++++++++++++++++++++++
- 1 file changed, 97 insertions(+)
-
---- a/arch/arm/configs/bcm2711_defconfig
-+++ b/arch/arm/configs/bcm2711_defconfig
-@@ -14,6 +14,9 @@ CONFIG_TASK_XACCT=y
- CONFIG_TASK_IO_ACCOUNTING=y
- CONFIG_IKCONFIG=m
- CONFIG_IKCONFIG_PROC=y
-+CONFIG_MEMCG=y
-+CONFIG_BLK_CGROUP=y
-+CONFIG_CGROUP_PIDS=y
- CONFIG_CGROUP_FREEZER=y
- CONFIG_CPUSETS=y
- CONFIG_CGROUP_DEVICE=y
-@@ -65,8 +68,10 @@ CONFIG_MODULES=y
- CONFIG_MODULE_UNLOAD=y
- CONFIG_MODVERSIONS=y
- CONFIG_MODULE_SRCVERSION_ALL=y
-+CONFIG_BLK_DEV_THROTTLING=y
- CONFIG_PARTITION_ADVANCED=y
- CONFIG_MAC_PARTITION=y
-+CONFIG_CFQ_GROUP_IOSCHED=y
- CONFIG_BINFMT_MISC=m
- CONFIG_CLEANCACHE=y
- CONFIG_FRONTSWAP=y
-@@ -95,6 +100,7 @@ CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
- CONFIG_IP_PIMSM_V1=y
- CONFIG_IP_PIMSM_V2=y
- CONFIG_SYN_COOKIES=y
-+CONFIG_NET_IPVTI=m
- CONFIG_INET_AH=m
- CONFIG_INET_ESP=m
- CONFIG_INET_IPCOMP=m
-@@ -214,6 +220,7 @@ 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
-@@ -520,6 +527,7 @@ CONFIG_USB_RTL8150=m
- CONFIG_USB_RTL8152=y
- CONFIG_USB_LAN78XX=y
- CONFIG_USB_USBNET=y
-+CONFIG_USB_NET_AX8817X=m
- CONFIG_USB_NET_AX88179_178A=m
- CONFIG_USB_NET_CDCETHER=m
- CONFIG_USB_NET_CDC_EEM=m
-@@ -573,6 +581,8 @@ CONFIG_LIBERTAS_THINFIRM_USB=m
- CONFIG_MWIFIEX=m
- CONFIG_MWIFIEX_SDIO=m
- CONFIG_MT7601U=m
-+CONFIG_MT76x0U=m
-+CONFIG_MT76x2U=m
- CONFIG_RT2X00=m
- CONFIG_RT2500USB=m
- CONFIG_RT73USB=m
-@@ -613,6 +623,7 @@ CONFIG_TOUCHSCREEN_ADS7846=m
- CONFIG_TOUCHSCREEN_EGALAX=m
- CONFIG_TOUCHSCREEN_EXC3000=m
- CONFIG_TOUCHSCREEN_GOODIX=m
-+CONFIG_TOUCHSCREEN_ILI210X=m
- CONFIG_TOUCHSCREEN_EDT_FT5X06=m
- CONFIG_TOUCHSCREEN_RPI_FT5406=m
- CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
-@@ -657,8 +668,13 @@ CONFIG_SERIAL_DEV_BUS=m
- CONFIG_TTY_PRINTK=y
- CONFIG_HW_RANDOM=y
- CONFIG_RAW_DRIVER=y
-+CONFIG_TCG_TPM=m
-+CONFIG_TCG_TIS_SPI=m
- CONFIG_I2C=y
- CONFIG_I2C_CHARDEV=m
-+CONFIG_I2C_MUX=m
-+CONFIG_I2C_MUX_GPMUX=m
-+CONFIG_I2C_MUX_PCA954x=m
- CONFIG_I2C_BCM2708=m
- CONFIG_I2C_BCM2835=m
- CONFIG_I2C_GPIO=m
-@@ -667,6 +683,7 @@ CONFIG_I2C_TINY_USB=m
- CONFIG_SPI=y
- CONFIG_SPI_BCM2835=m
- CONFIG_SPI_BCM2835AUX=m
-+CONFIG_SPI_GPIO=m
- CONFIG_SPI_SPIDEV=m
- CONFIG_SPI_SLAVE=y
- CONFIG_PPS=m
-@@ -698,11 +715,14 @@ CONFIG_W1_SLAVE_DS28E04=m
- CONFIG_POWER_RESET=y
- CONFIG_POWER_RESET_GPIO=y
- CONFIG_BATTERY_DS2760=m
-+CONFIG_BATTERY_MAX17040=m
- CONFIG_BATTERY_GAUGE_LTC2941=m
- CONFIG_HWMON=m
- CONFIG_SENSORS_DS1621=m
-+CONFIG_SENSORS_GPIO_FAN=m
- CONFIG_SENSORS_JC42=m
- CONFIG_SENSORS_LM75=m
-+CONFIG_SENSORS_RASPBERRYPI_HWMON=m
- CONFIG_SENSORS_RPI_POE_FAN=m
- CONFIG_SENSORS_SHT21=m
- CONFIG_SENSORS_SHT3x=m
-@@ -726,6 +746,31 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=m
- CONFIG_REGULATOR_ARIZONA_LDO1=m
- CONFIG_REGULATOR_ARIZONA_MICSUPP=m
- CONFIG_REGULATOR_GPIO=y
-+CONFIG_RC_CORE=y
-+CONFIG_LIRC=y
-+CONFIG_RC_DECODERS=y
-+CONFIG_IR_NEC_DECODER=m
-+CONFIG_IR_RC5_DECODER=m
-+CONFIG_IR_RC6_DECODER=m
-+CONFIG_IR_JVC_DECODER=m
-+CONFIG_IR_SONY_DECODER=m
-+CONFIG_IR_SANYO_DECODER=m
-+CONFIG_IR_SHARP_DECODER=m
-+CONFIG_IR_MCE_KBD_DECODER=m
-+CONFIG_IR_XMP_DECODER=m
-+CONFIG_IR_IMON_DECODER=m
-+CONFIG_RC_DEVICES=y
-+CONFIG_RC_ATI_REMOTE=m
-+CONFIG_IR_IMON=m
-+CONFIG_IR_MCEUSB=m
-+CONFIG_IR_REDRAT3=m
-+CONFIG_IR_STREAMZAP=m
-+CONFIG_IR_IGUANA=m
-+CONFIG_IR_TTUSBIR=m
-+CONFIG_RC_LOOPBACK=m
-+CONFIG_IR_GPIO_CIR=m
-+CONFIG_IR_GPIO_TX=m
-+CONFIG_IR_PWM_TX=m
- CONFIG_MEDIA_SUPPORT=m
- CONFIG_MEDIA_CAMERA_SUPPORT=y
- CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
-@@ -797,7 +842,40 @@ CONFIG_VIDEO_GO7007=m
- CONFIG_VIDEO_GO7007_USB=m
- CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m
- CONFIG_VIDEO_AU0828=m
-+CONFIG_VIDEO_AU0828_RC=y
-+CONFIG_VIDEO_CX231XX=m
-+CONFIG_VIDEO_CX231XX_ALSA=m
-+CONFIG_VIDEO_CX231XX_DVB=m
-+CONFIG_VIDEO_TM6000=m
-+CONFIG_VIDEO_TM6000_ALSA=m
-+CONFIG_VIDEO_TM6000_DVB=m
-+CONFIG_DVB_USB=m
-+CONFIG_DVB_USB_A800=m
-+CONFIG_DVB_USB_DIBUSB_MB=m
-+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y
-+CONFIG_DVB_USB_DIBUSB_MC=m
-+CONFIG_DVB_USB_DIB0700=m
-+CONFIG_DVB_USB_UMT_010=m
-+CONFIG_DVB_USB_CXUSB=m
-+CONFIG_DVB_USB_M920X=m
-+CONFIG_DVB_USB_DIGITV=m
-+CONFIG_DVB_USB_VP7045=m
-+CONFIG_DVB_USB_VP702X=m
-+CONFIG_DVB_USB_GP8PSK=m
-+CONFIG_DVB_USB_NOVA_T_USB2=m
-+CONFIG_DVB_USB_TTUSB2=m
-+CONFIG_DVB_USB_DTT200U=m
-+CONFIG_DVB_USB_OPERA1=m
-+CONFIG_DVB_USB_AF9005=m
-+CONFIG_DVB_USB_AF9005_REMOTE=m
-+CONFIG_DVB_USB_PCTV452E=m
-+CONFIG_DVB_USB_DW2102=m
-+CONFIG_DVB_USB_CINERGY_T2=m
-+CONFIG_DVB_USB_DTV5100=m
-+CONFIG_DVB_USB_AZ6027=m
-+CONFIG_DVB_USB_TECHNISAT_USB2=m
- CONFIG_DVB_USB_V2=m
-+CONFIG_DVB_USB_AF9015=m
- CONFIG_DVB_USB_AF9035=m
- CONFIG_DVB_USB_ANYSEE=m
- CONFIG_DVB_USB_AU6610=m
-@@ -805,7 +883,9 @@ CONFIG_DVB_USB_AZ6007=m
- CONFIG_DVB_USB_CE6230=m
- CONFIG_DVB_USB_EC168=m
- CONFIG_DVB_USB_GL861=m
-+CONFIG_DVB_USB_LME2510=m
- CONFIG_DVB_USB_MXL111SF=m
-+CONFIG_DVB_USB_RTL28XXU=m
- CONFIG_DVB_USB_DVBSKY=m
- CONFIG_SMS_USB_DRV=m
- CONFIG_DVB_B2C2_FLEXCOP_USB=m
-@@ -900,9 +980,11 @@ CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m
-+CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M=m
- CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
- CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m
- CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m
-+CONFIG_SND_AUDIOSENSE_PI=m
- CONFIG_SND_DIGIDAC1_SOUNDCARD=m
- CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m
- CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m
-@@ -913,10 +995,14 @@ CONFIG_SND_BCM2708_SOC_ALLO_DIGIONE=m
- CONFIG_SND_BCM2708_SOC_ALLO_KATANA_DAC=m
- CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m
- CONFIG_SND_PISOUND=m
-+CONFIG_SND_SOC_AD193X_SPI=m
-+CONFIG_SND_SOC_AD193X_I2C=m
- CONFIG_SND_SOC_ADAU1701=m
- CONFIG_SND_SOC_ADAU7002=m
- CONFIG_SND_SOC_AK4554=m
-+CONFIG_SND_SOC_CS4265=m
- CONFIG_SND_SOC_CS4271_I2C=m
-+CONFIG_SND_SOC_ICS43432=m
- CONFIG_SND_SOC_SPDIF=m
- CONFIG_SND_SOC_WM8804_I2C=m
- CONFIG_SND_SIMPLE_CARD=m
-@@ -929,6 +1015,7 @@ CONFIG_HID_APPLE=m
- CONFIG_HID_ASUS=m
- CONFIG_HID_BELKIN=m
- CONFIG_HID_BETOP_FF=m
-+CONFIG_HID_BIGBEN_FF=m
- CONFIG_HID_CHERRY=m
- CONFIG_HID_CHICONY=m
- CONFIG_HID_CYPRESS=m
-@@ -986,6 +1073,7 @@ CONFIG_USB_XHCI_HCD=y
- CONFIG_USB_XHCI_PLATFORM=y
- CONFIG_USB_DWCOTG=y
- CONFIG_USB_PRINTER=m
-+CONFIG_USB_TMC=m
- CONFIG_USB_STORAGE=y
- CONFIG_USB_STORAGE_REALTEK=m
- CONFIG_USB_STORAGE_DATAFAB=m
-@@ -1006,6 +1094,7 @@ CONFIG_USB_MICROTEK=m
- CONFIG_USBIP_CORE=m
- CONFIG_USBIP_VHCI_HCD=m
- CONFIG_USBIP_HOST=m
-+CONFIG_USBIP_VUDC=m
- CONFIG_USB_DWC2=m
- CONFIG_USB_SERIAL=m
- CONFIG_USB_SERIAL_GENERIC=y
-@@ -1122,6 +1211,8 @@ CONFIG_MMC_SDHCI_IPROC=y
- CONFIG_MMC_SPI=m
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
-+CONFIG_LEDS_PCA963X=m
-+CONFIG_LEDS_IS31FL32XX=m
- CONFIG_LEDS_TRIGGER_TIMER=y
- CONFIG_LEDS_TRIGGER_ONESHOT=y
- CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-@@ -1133,6 +1224,7 @@ CONFIG_LEDS_TRIGGER_TRANSIENT=m
- CONFIG_LEDS_TRIGGER_CAMERA=m
- CONFIG_LEDS_TRIGGER_INPUT=y
- CONFIG_LEDS_TRIGGER_PANIC=y
-+CONFIG_LEDS_TRIGGER_NETDEV=m
- CONFIG_RTC_CLASS=y
- # CONFIG_RTC_HCTOSYS is not set
- CONFIG_RTC_DRV_ABX80X=m
-@@ -1154,6 +1246,7 @@ CONFIG_RTC_DRV_FM3130=m
- CONFIG_RTC_DRV_RX8581=m
- CONFIG_RTC_DRV_RX8025=m
- CONFIG_RTC_DRV_EM3027=m
-+CONFIG_RTC_DRV_RV3028=m
- CONFIG_RTC_DRV_M41T93=m
- CONFIG_RTC_DRV_M41T94=m
- CONFIG_RTC_DRV_DS1302=m
-@@ -1170,6 +1263,8 @@ CONFIG_RTC_DRV_RV3029C2=m
- CONFIG_DMADEVICES=y
- CONFIG_DMA_BCM2835=y
- CONFIG_DMA_BCM2708=y
-+CONFIG_AUXDISPLAY=y
-+CONFIG_HD44780=m
- CONFIG_UIO=m
- CONFIG_UIO_PDRV_GENIRQ=m
- CONFIG_STAGING=y
-@@ -1198,6 +1293,7 @@ CONFIG_FB_TFT_PCD8544=m
- CONFIG_FB_TFT_RA8875=m
- CONFIG_FB_TFT_S6D02A1=m
- CONFIG_FB_TFT_S6D1121=m
-+CONFIG_FB_TFT_SH1106=m
- CONFIG_FB_TFT_SSD1289=m
- CONFIG_FB_TFT_SSD1306=m
- CONFIG_FB_TFT_SSD1331=m
-@@ -1229,6 +1325,7 @@ CONFIG_MCP3422=m
- CONFIG_DHT11=m
- CONFIG_HDC100X=m
- CONFIG_HTU21=m
-+CONFIG_INV_MPU6050_I2C=m
- CONFIG_TSL4531=m
- CONFIG_VEML6070=m
- CONFIG_BMP280=m
--- /dev/null
+From 33a9109c32beaf418bd72165d598db1c792051f5 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 10 Jun 2019 16:32:51 +0100
+Subject: [PATCH 654/725] drm/vc4: Remove 340MHz clock limit from FKMS now
+ scrambling issues resolved
+
+Firmware TMDS scrambling is now being correctly configured, so
+we can use it.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 ------
+ 1 file changed, 6 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -830,12 +830,6 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
+ break;
+ }
+
+- /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
+- * working.
+- */
+- if (mode->clock > 340000)
+- return MODE_CLOCK_HIGH;
+-
+ return MODE_OK;
+ }
+
+++ /dev/null
-From e38baaa7198fc28f746a6b72c5cb125920d5145b Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 31 May 2019 17:57:26 +0100
-Subject: [PATCH 654/703] dts: Include CSI lane config for csi1
-
-Without the include the peripheral is configured to have 0
-data lanes, which doesn't allow much data to be passed.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
-
- #include "bcm2711.dtsi"
-+#include "bcm283x-rpi-csi1-2lane.dtsi"
-
- / {
- compatible = "raspberrypi,4-model-b", "brcm,bcm2838", "brcm,bcm2837";
--- /dev/null
+From 255fb8869fe765f8ee9dbdad61ddfab333ff45ae Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Fri, 7 Jun 2019 14:50:12 +0100
+Subject: [PATCH 655/725] Revert "usb: xhci: hack xhci_urb_enqueue to support
+ hid.mousepoll behaviour"
+
+This reverts commit 1cf1071a79f320bc4497a3ade77431f04442eb17.
+---
+ drivers/usb/host/xhci.c | 86 -----------------------------------------
+ 1 file changed, 86 deletions(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -1416,87 +1416,6 @@ command_cleanup:
+ }
+
+ /*
+- * RPI: Fixup endpoint intervals when requested
+- * - Check interval versus the (cached) endpoint context
+- * - set the endpoint interval to the new value
+- * - force an endpoint configure command
+- */
+-static void xhci_fixup_interval(struct xhci_hcd *xhci, struct urb *urb,
+- unsigned int slot_id, unsigned int ep_index)
+-{
+- struct xhci_ep_ctx *ep_ctx_out, *ep_ctx_in;
+- struct xhci_command *command;
+- struct xhci_input_control_ctx *ctrl_ctx;
+- struct xhci_virt_device *vdev;
+- int xhci_interval, ep_interval;
+- int ret;
+- unsigned long flags;
+- u32 ep_info_tmp;
+-
+- spin_lock_irqsave(&xhci->lock, flags);
+-
+- vdev = xhci->devs[slot_id];
+- /* Get context-derived endpoint interval */
+- ep_ctx_out = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
+- ep_ctx_in = xhci_get_ep_ctx(xhci, vdev->in_ctx, ep_index);
+- xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx_out->ep_info));
+- ep_interval = urb->interval * 8;
+-
+- if (ep_interval == xhci_interval) {
+- spin_unlock_irqrestore(&xhci->lock, flags);
+- return;
+- }
+-
+- xhci_dbg(xhci, "Fixup interval ep_interval=%d xhci_interval=%d\n",
+- ep_interval, xhci_interval);
+- command = xhci_alloc_command_with_ctx(xhci, true, GFP_ATOMIC);
+- if (!command) {
+- /* Failure here is benign, poll at the original rate */
+- spin_unlock_irqrestore(&xhci->lock, flags);
+- return;
+- }
+-
+- /* xHCI uses exponents for intervals... */
+- xhci_interval = fls(ep_interval) - 1;
+- xhci_interval = clamp_val(xhci_interval, 3, 10);
+- ep_info_tmp = le32_to_cpu(ep_ctx_out->ep_info);
+- ep_info_tmp &= ~EP_INTERVAL(255);
+- ep_info_tmp |= EP_INTERVAL(xhci_interval);
+-
+- /* Keep the endpoint context up-to-date while issuing the command. */
+- xhci_endpoint_copy(xhci, vdev->in_ctx,
+- vdev->out_ctx, ep_index);
+- ep_ctx_in->ep_info = cpu_to_le32(ep_info_tmp);
+-
+- /*
+- * We need to drop the lock, so take an explicit copy
+- * of the ep context.
+- */
+- xhci_endpoint_copy(xhci, command->in_ctx, vdev->in_ctx, ep_index);
+-
+- ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx);
+- if (!ctrl_ctx) {
+- xhci_warn(xhci,
+- "%s: Could not get input context, bad type.\n",
+- __func__);
+- spin_unlock_irqrestore(&xhci->lock, flags);
+- xhci_free_command(xhci, command);
+- return;
+- }
+- ctrl_ctx->add_flags = xhci_get_endpoint_flag_from_index(ep_index);
+- ctrl_ctx->drop_flags = 0;
+-
+- spin_unlock_irqrestore(&xhci->lock, flags);
+-
+- ret = xhci_configure_endpoint(xhci, urb->dev, command,
+- false, false);
+- if (ret)
+- xhci_warn(xhci, "%s: Configure endpoint failed: %d\n",
+- __func__, ret);
+- xhci_free_command(xhci, command);
+-}
+-
+-/*
+ * non-error returns are a promise to giveback() the urb later
+ * we drop ownership so next owner (or urb unlink) can get it
+ */
+@@ -1564,11 +1483,6 @@ static int xhci_urb_enqueue(struct usb_h
+ }
+ }
+
+- if (usb_endpoint_xfer_int(&urb->ep->desc) &&
+- (urb->dev->speed == USB_SPEED_FULL ||
+- urb->dev->speed == USB_SPEED_LOW))
+- xhci_fixup_interval(xhci, urb, slot_id, ep_index);
+-
+ spin_lock_irqsave(&xhci->lock, flags);
+
+ if (xhci->xhc_state & XHCI_STATE_DYING) {
+++ /dev/null
-From 07455c93159c15c8838f53716210713376db7065 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 7 Jun 2019 11:31:21 +0100
-Subject: [PATCH 655/703] drm/vc4: Fix T-format modifiers in FKMS.
-
-The wrong vc_image formats were being checked for in the switch
-statement. Correct these.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -458,10 +458,10 @@ static void vc4_plane_atomic_update(stru
- switch (fb->modifier) {
- case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
- switch (mb->plane.vc_image_type) {
-- case VC_IMAGE_RGBX32:
-+ case VC_IMAGE_XRGB8888:
- mb->plane.vc_image_type = VC_IMAGE_TF_RGBX32;
- break;
-- case VC_IMAGE_RGBA32:
-+ case VC_IMAGE_ARGB8888:
- mb->plane.vc_image_type = VC_IMAGE_TF_RGBA32;
- break;
- case VC_IMAGE_RGB565:
+++ /dev/null
-From db56c3edb3b30f3884537bca47019e7a715a4333 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 7 Jun 2019 11:35:01 +0100
-Subject: [PATCH 656/703] defconfigs: Add FB_SIMPLE to both bcmrpi and bcm2709
- configs
-
-The firmware sets up simple fb should one of the KMS drivers
-be enabled, but the driver isn't being built.
-Add it to the build.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm/configs/bcm2709_defconfig | 1 +
- arch/arm/configs/bcmrpi_defconfig | 1 +
- 2 files changed, 2 insertions(+)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -928,6 +928,7 @@ CONFIG_TINYDRM_REPAPER=m
- CONFIG_FB=y
- CONFIG_FB_BCM2708=y
- CONFIG_FB_UDL=m
-+CONFIG_FB_SIMPLE=y
- CONFIG_FB_SSD1307=m
- CONFIG_FB_RPISENSE=m
- # CONFIG_BACKLIGHT_GENERIC is not set
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -920,6 +920,7 @@ CONFIG_TINYDRM_REPAPER=m
- CONFIG_FB=y
- CONFIG_FB_BCM2708=y
- CONFIG_FB_UDL=m
-+CONFIG_FB_SIMPLE=y
- CONFIG_FB_SSD1307=m
- CONFIG_FB_RPISENSE=m
- # CONFIG_BACKLIGHT_GENERIC is not set
--- /dev/null
+From fbb878b2370c655ea989191167b338fff636687a Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 11 Jun 2019 10:55:00 +0100
+Subject: [PATCH 656/725] usb: add plumbing for updating interrupt endpoint
+ interval state
+
+xHCI caches device and endpoint data after the interface is configured,
+so an explicit command needs to be issued for any device driver wanting
+to alter the polling interval of an endpoint.
+
+Add usb_fixup_endpoint() to allow drivers to do this. The fixup must be
+called after calculating endpoint bandwidth requirements but before any
+URBs are submitted.
+
+If polling intervals are shortened, any bandwidth reservations are no
+longer valid but in practice polling intervals are only ever relaxed.
+
+Limit the scope to interrupt transfers for now.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/core/hcd.c | 10 ++++++++++
+ drivers/usb/core/message.c | 15 +++++++++++++++
+ include/linux/usb.h | 2 ++
+ include/linux/usb/hcd.h | 7 +++++++
+ 4 files changed, 34 insertions(+)
+
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -2071,6 +2071,16 @@ reset:
+ return ret;
+ }
+
++void usb_hcd_fixup_endpoint(struct usb_device *udev,
++ struct usb_host_endpoint *ep, int interval)
++{
++ struct usb_hcd *hcd;
++
++ hcd = bus_to_hcd(udev->bus);
++ if (hcd->driver->fixup_endpoint)
++ hcd->driver->fixup_endpoint(hcd, udev, ep, interval);
++}
++
+ /* Disables the endpoint: synchronizes with the hcd to make sure all
+ * endpoint state is gone from hardware. usb_hcd_flush_endpoint() must
+ * have been called previously. Use for set_configuration, set_interface,
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1113,6 +1113,21 @@ static void remove_intf_ep_devs(struct u
+ intf->ep_devs_created = 0;
+ }
+
++void usb_fixup_endpoint(struct usb_device *dev, int epaddr, int interval)
++{
++ unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
++ struct usb_host_endpoint *ep;
++
++ if (usb_endpoint_out(epaddr))
++ ep = dev->ep_out[epnum];
++ else
++ ep = dev->ep_in[epnum];
++
++ if (ep && usb_endpoint_xfer_int(&ep->desc))
++ usb_hcd_fixup_endpoint(dev, ep, interval);
++}
++EXPORT_SYMBOL_GPL(usb_fixup_endpoint);
++
+ /**
+ * usb_disable_endpoint -- Disable an endpoint by address
+ * @dev: the device whose endpoint is being disabled
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1809,6 +1809,8 @@ extern int usb_clear_halt(struct usb_dev
+ extern int usb_reset_configuration(struct usb_device *dev);
+ extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
+ extern void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr);
++extern void usb_fixup_endpoint(struct usb_device *dev, int epaddr,
++ int interval);
+
+ /* this request isn't really synchronous, but it belongs with the others */
+ extern int usb_driver_set_configuration(struct usb_device *udev, int config);
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -379,6 +379,11 @@ struct hc_driver {
+ * or bandwidth constraints.
+ */
+ void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
++ /* Override the endpoint-derived interval
++ * (if there is any cached hardware state).
++ */
++ void (*fixup_endpoint)(struct usb_hcd *hcd, struct usb_device *udev,
++ struct usb_host_endpoint *ep, int interval);
+ /* Returns the hardware-chosen device address */
+ int (*address_device)(struct usb_hcd *, struct usb_device *udev);
+ /* prepares the hardware to send commands to the device */
+@@ -435,6 +440,8 @@ extern void usb_hcd_unmap_urb_setup_for_
+ extern void usb_hcd_unmap_urb_for_dma(struct usb_hcd *, struct urb *);
+ extern void usb_hcd_flush_endpoint(struct usb_device *udev,
+ struct usb_host_endpoint *ep);
++extern void usb_hcd_fixup_endpoint(struct usb_device *udev,
++ struct usb_host_endpoint *ep, int interval);
+ extern void usb_hcd_disable_endpoint(struct usb_device *udev,
+ struct usb_host_endpoint *ep);
+ extern void usb_hcd_reset_endpoint(struct usb_device *udev,
+++ /dev/null
-From cacc213626d0435a7c9dd1192e0757c082ed048b Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 10 Jun 2019 17:22:44 +0100
-Subject: [PATCH 657/703] bcm2711 dts: Disable the v3d node by default
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2711.dtsi | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/arch/arm/boot/dts/bcm2711.dtsi
-+++ b/arch/arm/boot/dts/bcm2711.dtsi
-@@ -13,6 +13,10 @@
- };
- };
-
-+&v3d {
-+ status = "disabled";
-+};
-+
- &dma {
- brcm,dma-channel-mask = <0x7ef5>;
- };
--- /dev/null
+From 3328d995046331f734b44a5f03471efd8682c8dd Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 11 Jun 2019 11:33:39 +0100
+Subject: [PATCH 657/725] xhci: implement xhci_fixup_endpoint for interval
+ adjustments
+
+Must be called in a non-atomic context, after the endpoint
+has been registered with the hardware via xhci_add_endpoint
+and before the first URB is submitted for the endpoint.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/host/xhci.c | 98 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 98 insertions(+)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -1416,6 +1416,103 @@ command_cleanup:
+ }
+
+ /*
++ * RPI: Fixup endpoint intervals when requested
++ * - Check interval versus the (cached) endpoint context
++ * - set the endpoint interval to the new value
++ * - force an endpoint configure command
++ * XXX: bandwidth is not recalculated. We should probably do that.
++ */
++static void xhci_fixup_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
++ struct usb_host_endpoint *ep, int interval)
++{
++ struct xhci_hcd *xhci;
++ struct xhci_ep_ctx *ep_ctx_out, *ep_ctx_in;
++ struct xhci_command *command;
++ struct xhci_input_control_ctx *ctrl_ctx;
++ struct xhci_virt_device *vdev;
++ int xhci_interval;
++ int ret;
++ int ep_index;
++ unsigned long flags;
++ u32 ep_info_tmp;
++
++ xhci = hcd_to_xhci(hcd);
++ ep_index = xhci_get_endpoint_index(&ep->desc);
++
++ /* FS/LS interval translations */
++ if ((udev->speed == USB_SPEED_FULL ||
++ udev->speed == USB_SPEED_LOW))
++ interval *= 8;
++
++ mutex_lock(&xhci->mutex);
++
++ spin_lock_irqsave(&xhci->lock, flags);
++
++ vdev = xhci->devs[udev->slot_id];
++ /* Get context-derived endpoint interval */
++ ep_ctx_out = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
++ ep_ctx_in = xhci_get_ep_ctx(xhci, vdev->in_ctx, ep_index);
++ xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx_out->ep_info));
++
++ if (interval == xhci_interval) {
++ spin_unlock_irqrestore(&xhci->lock, flags);
++ mutex_unlock(&xhci->mutex);
++ return;
++ }
++
++ xhci_dbg(xhci, "Fixup interval=%d xhci_interval=%d\n",
++ interval, xhci_interval);
++ command = xhci_alloc_command_with_ctx(xhci, true, GFP_ATOMIC);
++ if (!command) {
++ /* Failure here is benign, poll at the original rate */
++ spin_unlock_irqrestore(&xhci->lock, flags);
++ mutex_unlock(&xhci->mutex);
++ return;
++ }
++
++ /* xHCI uses exponents for intervals... */
++ xhci_interval = fls(interval) - 1;
++ xhci_interval = clamp_val(xhci_interval, 3, 10);
++ ep_info_tmp = le32_to_cpu(ep_ctx_out->ep_info);
++ ep_info_tmp &= ~EP_INTERVAL(255);
++ ep_info_tmp |= EP_INTERVAL(xhci_interval);
++
++ /* Keep the endpoint context up-to-date while issuing the command. */
++ xhci_endpoint_copy(xhci, vdev->in_ctx,
++ vdev->out_ctx, ep_index);
++ ep_ctx_in->ep_info = cpu_to_le32(ep_info_tmp);
++
++ /*
++ * We need to drop the lock, so take an explicit copy
++ * of the ep context.
++ */
++ xhci_endpoint_copy(xhci, command->in_ctx, vdev->in_ctx, ep_index);
++
++ ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx);
++ if (!ctrl_ctx) {
++ xhci_warn(xhci,
++ "%s: Could not get input context, bad type.\n",
++ __func__);
++ spin_unlock_irqrestore(&xhci->lock, flags);
++ xhci_free_command(xhci, command);
++ mutex_unlock(&xhci->mutex);
++ return;
++ }
++ ctrl_ctx->add_flags = xhci_get_endpoint_flag_from_index(ep_index);
++ ctrl_ctx->drop_flags = 0;
++
++ spin_unlock_irqrestore(&xhci->lock, flags);
++
++ ret = xhci_configure_endpoint(xhci, udev, command,
++ false, false);
++ if (ret)
++ xhci_warn(xhci, "%s: Configure endpoint failed: %d\n",
++ __func__, ret);
++ xhci_free_command(xhci, command);
++ mutex_unlock(&xhci->mutex);
++}
++
++/*
+ * non-error returns are a promise to giveback() the urb later
+ * we drop ownership so next owner (or urb unlink) can get it
+ */
+@@ -5180,6 +5277,7 @@ static const struct hc_driver xhci_hc_dr
+ .endpoint_reset = xhci_endpoint_reset,
+ .check_bandwidth = xhci_check_bandwidth,
+ .reset_bandwidth = xhci_reset_bandwidth,
++ .fixup_endpoint = xhci_fixup_endpoint,
+ .address_device = xhci_address_device,
+ .enable_device = xhci_enable_device,
+ .update_hub_device = xhci_update_hub_device,
+++ /dev/null
-From e63e050360bfe8d06552ed5fb0f037d8f18b61bc Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 10 Jun 2019 16:32:51 +0100
-Subject: [PATCH 658/703] drm/vc4: Remove 340MHz clock limit from FKMS now
- scrambling issues resolved
-
-Firmware TMDS scrambling is now being correctly configured, so
-we can use it.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 ------
- 1 file changed, 6 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -830,12 +830,6 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
- break;
- }
-
-- /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
-- * working.
-- */
-- if (mode->clock > 340000)
-- return MODE_CLOCK_HIGH;
--
- return MODE_OK;
- }
-
--- /dev/null
+From bc52b79141e51a6cbd1b5def5c300dee3c6d0b84 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 11 Jun 2019 11:42:03 +0100
+Subject: [PATCH 658/725] usbhid: call usb_fixup_endpoint after mangling
+ intervals
+
+Lets the mousepoll override mechanism work with xhci.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/hid/usbhid/hid-core.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -1118,6 +1118,7 @@ static int usbhid_start(struct hid_devic
+ interval = hid_kbpoll_interval;
+ break;
+ }
++ usb_fixup_endpoint(dev, endpoint->bEndpointAddress, interval);
+
+ ret = -ENOMEM;
+ if (usb_endpoint_dir_in(endpoint)) {
+++ /dev/null
-From e019f0ccbfab3caccd5c5a8434c48e0a3b8e12cc Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Fri, 7 Jun 2019 14:50:12 +0100
-Subject: [PATCH 659/703] Revert "usb: xhci: hack xhci_urb_enqueue to support
- hid.mousepoll behaviour"
-
-This reverts commit 1cf1071a79f320bc4497a3ade77431f04442eb17.
----
- drivers/usb/host/xhci.c | 86 -----------------------------------------
- 1 file changed, 86 deletions(-)
-
---- a/drivers/usb/host/xhci.c
-+++ b/drivers/usb/host/xhci.c
-@@ -1416,87 +1416,6 @@ command_cleanup:
- }
-
- /*
-- * RPI: Fixup endpoint intervals when requested
-- * - Check interval versus the (cached) endpoint context
-- * - set the endpoint interval to the new value
-- * - force an endpoint configure command
-- */
--static void xhci_fixup_interval(struct xhci_hcd *xhci, struct urb *urb,
-- unsigned int slot_id, unsigned int ep_index)
--{
-- struct xhci_ep_ctx *ep_ctx_out, *ep_ctx_in;
-- struct xhci_command *command;
-- struct xhci_input_control_ctx *ctrl_ctx;
-- struct xhci_virt_device *vdev;
-- int xhci_interval, ep_interval;
-- int ret;
-- unsigned long flags;
-- u32 ep_info_tmp;
--
-- spin_lock_irqsave(&xhci->lock, flags);
--
-- vdev = xhci->devs[slot_id];
-- /* Get context-derived endpoint interval */
-- ep_ctx_out = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
-- ep_ctx_in = xhci_get_ep_ctx(xhci, vdev->in_ctx, ep_index);
-- xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx_out->ep_info));
-- ep_interval = urb->interval * 8;
--
-- if (ep_interval == xhci_interval) {
-- spin_unlock_irqrestore(&xhci->lock, flags);
-- return;
-- }
--
-- xhci_dbg(xhci, "Fixup interval ep_interval=%d xhci_interval=%d\n",
-- ep_interval, xhci_interval);
-- command = xhci_alloc_command_with_ctx(xhci, true, GFP_ATOMIC);
-- if (!command) {
-- /* Failure here is benign, poll at the original rate */
-- spin_unlock_irqrestore(&xhci->lock, flags);
-- return;
-- }
--
-- /* xHCI uses exponents for intervals... */
-- xhci_interval = fls(ep_interval) - 1;
-- xhci_interval = clamp_val(xhci_interval, 3, 10);
-- ep_info_tmp = le32_to_cpu(ep_ctx_out->ep_info);
-- ep_info_tmp &= ~EP_INTERVAL(255);
-- ep_info_tmp |= EP_INTERVAL(xhci_interval);
--
-- /* Keep the endpoint context up-to-date while issuing the command. */
-- xhci_endpoint_copy(xhci, vdev->in_ctx,
-- vdev->out_ctx, ep_index);
-- ep_ctx_in->ep_info = cpu_to_le32(ep_info_tmp);
--
-- /*
-- * We need to drop the lock, so take an explicit copy
-- * of the ep context.
-- */
-- xhci_endpoint_copy(xhci, command->in_ctx, vdev->in_ctx, ep_index);
--
-- ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx);
-- if (!ctrl_ctx) {
-- xhci_warn(xhci,
-- "%s: Could not get input context, bad type.\n",
-- __func__);
-- spin_unlock_irqrestore(&xhci->lock, flags);
-- xhci_free_command(xhci, command);
-- return;
-- }
-- ctrl_ctx->add_flags = xhci_get_endpoint_flag_from_index(ep_index);
-- ctrl_ctx->drop_flags = 0;
--
-- spin_unlock_irqrestore(&xhci->lock, flags);
--
-- ret = xhci_configure_endpoint(xhci, urb->dev, command,
-- false, false);
-- if (ret)
-- xhci_warn(xhci, "%s: Configure endpoint failed: %d\n",
-- __func__, ret);
-- xhci_free_command(xhci, command);
--}
--
--/*
- * non-error returns are a promise to giveback() the urb later
- * we drop ownership so next owner (or urb unlink) can get it
- */
-@@ -1564,11 +1483,6 @@ static int xhci_urb_enqueue(struct usb_h
- }
- }
-
-- if (usb_endpoint_xfer_int(&urb->ep->desc) &&
-- (urb->dev->speed == USB_SPEED_FULL ||
-- urb->dev->speed == USB_SPEED_LOW))
-- xhci_fixup_interval(xhci, urb, slot_id, ep_index);
--
- spin_lock_irqsave(&xhci->lock, flags);
-
- if (xhci->xhc_state & XHCI_STATE_DYING) {
--- /dev/null
+From 779fbe67ca1737d5450d393a6e893dcda8111786 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 4 Jun 2019 12:14:30 +0100
+Subject: [PATCH 659/725] drm: vc4: Add status of which display is updated
+ through vblank
+
+Previously multiple displays were slaved off the same SMI
+interrupt, triggered by HVS channel 1 (HDMI0).
+This doesn't work if you only have a DPI or DSI screen (HVS channel
+0), and gives slightly erroneous results with dual HDMI as the
+events for HDMI1 are incorrect.
+
+Use SMIDSW0 and SMIDSW1 registers to denote which display has
+triggered the vblank.
+Handling should be backwards compatible with older firmware.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 41 ++++++++++++++++++++++----
+ 1 file changed, 36 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -230,8 +230,13 @@ static const struct vc_image_format *vc4
+ * hardware, which has only this one register.
+ */
+ #define SMICS 0x0
++#define SMIDSW0 0x14
++#define SMIDSW1 0x1C
+ #define SMICS_INTERRUPTS (BIT(9) | BIT(10) | BIT(11))
+
++/* Flag to denote that the firmware is giving multiple display callbacks */
++#define SMI_NEW 0xabcd0000
++
+ #define vc4_crtc vc4_kms_crtc
+ #define to_vc4_crtc to_vc4_kms_crtc
+ struct vc4_crtc {
+@@ -884,16 +889,42 @@ static irqreturn_t vc4_crtc_irq_handler(
+ int i;
+ u32 stat = readl(crtc_list[0]->regs + SMICS);
+ irqreturn_t ret = IRQ_NONE;
++ u32 chan;
+
+ if (stat & SMICS_INTERRUPTS) {
+ writel(0, crtc_list[0]->regs + SMICS);
+
+- for (i = 0; crtc_list[i]; i++) {
+- if (crtc_list[i]->vblank_enabled)
+- drm_crtc_handle_vblank(&crtc_list[i]->base);
+- vc4_crtc_handle_page_flip(crtc_list[i]);
+- ret = IRQ_HANDLED;
++ chan = readl(crtc_list[0]->regs + SMIDSW0);
++
++ if ((chan & 0xFFFF0000) != SMI_NEW) {
++ /* Older firmware. Treat the one interrupt as vblank/
++ * complete for all crtcs.
++ */
++ for (i = 0; crtc_list[i]; i++) {
++ if (crtc_list[i]->vblank_enabled)
++ drm_crtc_handle_vblank(&crtc_list[i]->base);
++ vc4_crtc_handle_page_flip(crtc_list[i]);
++ }
++ } else {
++ if (chan & 1) {
++ writel(SMI_NEW, crtc_list[0]->regs + SMIDSW0);
++ if (crtc_list[0]->vblank_enabled)
++ drm_crtc_handle_vblank(&crtc_list[0]->base);
++ vc4_crtc_handle_page_flip(crtc_list[0]);
++ }
++
++ /* Check for the secondary display too */
++ chan = readl(crtc_list[0]->regs + SMIDSW1);
++
++ if (chan & 1) {
++ writel(SMI_NEW, crtc_list[0]->regs + SMIDSW1);
++ if (crtc_list[1]->vblank_enabled)
++ drm_crtc_handle_vblank(&crtc_list[1]->base);
++ vc4_crtc_handle_page_flip(crtc_list[1]);
++ }
+ }
++
++ ret = IRQ_HANDLED;
+ }
+
+ return ret;
--- /dev/null
+From 06467a053320efedf24a7facbd58873b22106992 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 12 Jun 2019 17:13:21 +0100
+Subject: [PATCH 660/725] drm/vc4: In FKMS look at the modifiers correctly for
+ SAND
+
+Incorrect masking was used in the switch for the modifier,
+therefore for SAND (which puts the column pitch in the
+modifier) it didn't match.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -460,7 +460,7 @@ static void vc4_plane_atomic_update(stru
+ }
+ mb->plane.planes[3] = 0;
+
+- switch (fb->modifier) {
++ switch (fourcc_mod_broadcom_mod(fb->modifier)) {
+ case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
+ switch (mb->plane.vc_image_type) {
+ case VC_IMAGE_XRGB8888:
+@@ -476,6 +476,9 @@ static void vc4_plane_atomic_update(stru
+ break;
+ case DRM_FORMAT_MOD_BROADCOM_SAND128:
+ mb->plane.vc_image_type = VC_IMAGE_YUV_UV;
++ /* Note that the column pitch is passed across in lines, not
++ * bytes.
++ */
+ mb->plane.pitch = fourcc_mod_broadcom_param(fb->modifier);
+ break;
+ }
+++ /dev/null
-From 8a6b7be03aaf91419a6dbc91dba10cf6e7f6eb73 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Tue, 11 Jun 2019 10:55:00 +0100
-Subject: [PATCH 660/703] usb: add plumbing for updating interrupt endpoint
- interval state
-
-xHCI caches device and endpoint data after the interface is configured,
-so an explicit command needs to be issued for any device driver wanting
-to alter the polling interval of an endpoint.
-
-Add usb_fixup_endpoint() to allow drivers to do this. The fixup must be
-called after calculating endpoint bandwidth requirements but before any
-URBs are submitted.
-
-If polling intervals are shortened, any bandwidth reservations are no
-longer valid but in practice polling intervals are only ever relaxed.
-
-Limit the scope to interrupt transfers for now.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/usb/core/hcd.c | 10 ++++++++++
- drivers/usb/core/message.c | 15 +++++++++++++++
- include/linux/usb.h | 2 ++
- include/linux/usb/hcd.h | 7 +++++++
- 4 files changed, 34 insertions(+)
-
---- a/drivers/usb/core/hcd.c
-+++ b/drivers/usb/core/hcd.c
-@@ -2071,6 +2071,16 @@ reset:
- return ret;
- }
-
-+void usb_hcd_fixup_endpoint(struct usb_device *udev,
-+ struct usb_host_endpoint *ep, int interval)
-+{
-+ struct usb_hcd *hcd;
-+
-+ hcd = bus_to_hcd(udev->bus);
-+ if (hcd->driver->fixup_endpoint)
-+ hcd->driver->fixup_endpoint(hcd, udev, ep, interval);
-+}
-+
- /* Disables the endpoint: synchronizes with the hcd to make sure all
- * endpoint state is gone from hardware. usb_hcd_flush_endpoint() must
- * have been called previously. Use for set_configuration, set_interface,
---- a/drivers/usb/core/message.c
-+++ b/drivers/usb/core/message.c
-@@ -1113,6 +1113,21 @@ static void remove_intf_ep_devs(struct u
- intf->ep_devs_created = 0;
- }
-
-+void usb_fixup_endpoint(struct usb_device *dev, int epaddr, int interval)
-+{
-+ unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
-+ struct usb_host_endpoint *ep;
-+
-+ if (usb_endpoint_out(epaddr))
-+ ep = dev->ep_out[epnum];
-+ else
-+ ep = dev->ep_in[epnum];
-+
-+ if (ep && usb_endpoint_xfer_int(&ep->desc))
-+ usb_hcd_fixup_endpoint(dev, ep, interval);
-+}
-+EXPORT_SYMBOL_GPL(usb_fixup_endpoint);
-+
- /**
- * usb_disable_endpoint -- Disable an endpoint by address
- * @dev: the device whose endpoint is being disabled
---- a/include/linux/usb.h
-+++ b/include/linux/usb.h
-@@ -1809,6 +1809,8 @@ extern int usb_clear_halt(struct usb_dev
- extern int usb_reset_configuration(struct usb_device *dev);
- extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
- extern void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr);
-+extern void usb_fixup_endpoint(struct usb_device *dev, int epaddr,
-+ int interval);
-
- /* this request isn't really synchronous, but it belongs with the others */
- extern int usb_driver_set_configuration(struct usb_device *udev, int config);
---- a/include/linux/usb/hcd.h
-+++ b/include/linux/usb/hcd.h
-@@ -379,6 +379,11 @@ struct hc_driver {
- * or bandwidth constraints.
- */
- void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
-+ /* Override the endpoint-derived interval
-+ * (if there is any cached hardware state).
-+ */
-+ void (*fixup_endpoint)(struct usb_hcd *hcd, struct usb_device *udev,
-+ struct usb_host_endpoint *ep, int interval);
- /* Returns the hardware-chosen device address */
- int (*address_device)(struct usb_hcd *, struct usb_device *udev);
- /* prepares the hardware to send commands to the device */
-@@ -435,6 +440,8 @@ extern void usb_hcd_unmap_urb_setup_for_
- extern void usb_hcd_unmap_urb_for_dma(struct usb_hcd *, struct urb *);
- extern void usb_hcd_flush_endpoint(struct usb_device *udev,
- struct usb_host_endpoint *ep);
-+extern void usb_hcd_fixup_endpoint(struct usb_device *udev,
-+ struct usb_host_endpoint *ep, int interval);
- extern void usb_hcd_disable_endpoint(struct usb_device *udev,
- struct usb_host_endpoint *ep);
- extern void usb_hcd_reset_endpoint(struct usb_device *udev,
--- /dev/null
+From 497f21437f6203798657467ffbc5d9e1f80c8cbb Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 17 Jun 2019 10:06:55 +0100
+Subject: [PATCH 661/725] arm: dts: Fix Pi4 PWR LED configuration
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -126,13 +126,13 @@
+ act_led: act {
+ label = "led0";
+ linux,default-trigger = "mmc0";
+- gpios = <&gpio 42 0>;
++ gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
+ };
+
+ pwr_led: pwr {
+ label = "led1";
+- linux,default-trigger = "input";
+- gpios = <&expgpio 2 0>;
++ linux,default-trigger = "default-on";
++ gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+++ /dev/null
-From ef57358754e9ab16429739d0ea1e479967ad4a40 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Tue, 11 Jun 2019 11:33:39 +0100
-Subject: [PATCH 661/703] xhci: implement xhci_fixup_endpoint for interval
- adjustments
-
-Must be called in a non-atomic context, after the endpoint
-has been registered with the hardware via xhci_add_endpoint
-and before the first URB is submitted for the endpoint.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/usb/host/xhci.c | 98 +++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 98 insertions(+)
-
---- a/drivers/usb/host/xhci.c
-+++ b/drivers/usb/host/xhci.c
-@@ -1416,6 +1416,103 @@ command_cleanup:
- }
-
- /*
-+ * RPI: Fixup endpoint intervals when requested
-+ * - Check interval versus the (cached) endpoint context
-+ * - set the endpoint interval to the new value
-+ * - force an endpoint configure command
-+ * XXX: bandwidth is not recalculated. We should probably do that.
-+ */
-+static void xhci_fixup_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
-+ struct usb_host_endpoint *ep, int interval)
-+{
-+ struct xhci_hcd *xhci;
-+ struct xhci_ep_ctx *ep_ctx_out, *ep_ctx_in;
-+ struct xhci_command *command;
-+ struct xhci_input_control_ctx *ctrl_ctx;
-+ struct xhci_virt_device *vdev;
-+ int xhci_interval;
-+ int ret;
-+ int ep_index;
-+ unsigned long flags;
-+ u32 ep_info_tmp;
-+
-+ xhci = hcd_to_xhci(hcd);
-+ ep_index = xhci_get_endpoint_index(&ep->desc);
-+
-+ /* FS/LS interval translations */
-+ if ((udev->speed == USB_SPEED_FULL ||
-+ udev->speed == USB_SPEED_LOW))
-+ interval *= 8;
-+
-+ mutex_lock(&xhci->mutex);
-+
-+ spin_lock_irqsave(&xhci->lock, flags);
-+
-+ vdev = xhci->devs[udev->slot_id];
-+ /* Get context-derived endpoint interval */
-+ ep_ctx_out = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
-+ ep_ctx_in = xhci_get_ep_ctx(xhci, vdev->in_ctx, ep_index);
-+ xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx_out->ep_info));
-+
-+ if (interval == xhci_interval) {
-+ spin_unlock_irqrestore(&xhci->lock, flags);
-+ mutex_unlock(&xhci->mutex);
-+ return;
-+ }
-+
-+ xhci_dbg(xhci, "Fixup interval=%d xhci_interval=%d\n",
-+ interval, xhci_interval);
-+ command = xhci_alloc_command_with_ctx(xhci, true, GFP_ATOMIC);
-+ if (!command) {
-+ /* Failure here is benign, poll at the original rate */
-+ spin_unlock_irqrestore(&xhci->lock, flags);
-+ mutex_unlock(&xhci->mutex);
-+ return;
-+ }
-+
-+ /* xHCI uses exponents for intervals... */
-+ xhci_interval = fls(interval) - 1;
-+ xhci_interval = clamp_val(xhci_interval, 3, 10);
-+ ep_info_tmp = le32_to_cpu(ep_ctx_out->ep_info);
-+ ep_info_tmp &= ~EP_INTERVAL(255);
-+ ep_info_tmp |= EP_INTERVAL(xhci_interval);
-+
-+ /* Keep the endpoint context up-to-date while issuing the command. */
-+ xhci_endpoint_copy(xhci, vdev->in_ctx,
-+ vdev->out_ctx, ep_index);
-+ ep_ctx_in->ep_info = cpu_to_le32(ep_info_tmp);
-+
-+ /*
-+ * We need to drop the lock, so take an explicit copy
-+ * of the ep context.
-+ */
-+ xhci_endpoint_copy(xhci, command->in_ctx, vdev->in_ctx, ep_index);
-+
-+ ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx);
-+ if (!ctrl_ctx) {
-+ xhci_warn(xhci,
-+ "%s: Could not get input context, bad type.\n",
-+ __func__);
-+ spin_unlock_irqrestore(&xhci->lock, flags);
-+ xhci_free_command(xhci, command);
-+ mutex_unlock(&xhci->mutex);
-+ return;
-+ }
-+ ctrl_ctx->add_flags = xhci_get_endpoint_flag_from_index(ep_index);
-+ ctrl_ctx->drop_flags = 0;
-+
-+ spin_unlock_irqrestore(&xhci->lock, flags);
-+
-+ ret = xhci_configure_endpoint(xhci, udev, command,
-+ false, false);
-+ if (ret)
-+ xhci_warn(xhci, "%s: Configure endpoint failed: %d\n",
-+ __func__, ret);
-+ xhci_free_command(xhci, command);
-+ mutex_unlock(&xhci->mutex);
-+}
-+
-+/*
- * non-error returns are a promise to giveback() the urb later
- * we drop ownership so next owner (or urb unlink) can get it
- */
-@@ -5180,6 +5277,7 @@ static const struct hc_driver xhci_hc_dr
- .endpoint_reset = xhci_endpoint_reset,
- .check_bandwidth = xhci_check_bandwidth,
- .reset_bandwidth = xhci_reset_bandwidth,
-+ .fixup_endpoint = xhci_fixup_endpoint,
- .address_device = xhci_address_device,
- .enable_device = xhci_enable_device,
- .update_hub_device = xhci_update_hub_device,
--- /dev/null
+From 734c5130809cf1df460c80ef1c3805d4d56d89cb Mon Sep 17 00:00:00 2001
+From: dp111 <dominic.plunkett@gmail.com>
+Date: Sat, 15 Jun 2019 18:19:50 +0100
+Subject: [PATCH 662/725] bcm2838.dtsi : Correct gic400 memory address ranges
+
+It appears to me the addresses for the gic400 are slightly wrong . See section 3.2 https://static.docs.arm.com/ddi0471/a/DDI0471A_gic400_r0p0_trm.pdf
+---
+ arch/arm/boot/dts/bcm2838.dtsi | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -30,8 +30,8 @@
+ compatible = "arm,gic-400";
+ reg = <0x40041000 0x1000>,
+ <0x40042000 0x2000>,
+- <0x40046000 0x2000>,
+- <0x40048000 0x2000>;
++ <0x40044000 0x2000>,
++ <0x40046000 0x2000>;
+ };
+
+ thermal: thermal@7d5d2200 {
+++ /dev/null
-From df99e61b9b0ce2018cb796f1b7b3298fd583c196 Mon Sep 17 00:00:00 2001
-From: Jonathan Bell <jonathan@raspberrypi.org>
-Date: Tue, 11 Jun 2019 11:42:03 +0100
-Subject: [PATCH 662/703] usbhid: call usb_fixup_endpoint after mangling
- intervals
-
-Lets the mousepoll override mechanism work with xhci.
-
-Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
----
- drivers/hid/usbhid/hid-core.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/hid/usbhid/hid-core.c
-+++ b/drivers/hid/usbhid/hid-core.c
-@@ -1118,6 +1118,7 @@ static int usbhid_start(struct hid_devic
- interval = hid_kbpoll_interval;
- break;
- }
-+ usb_fixup_endpoint(dev, endpoint->bEndpointAddress, interval);
-
- ret = -ENOMEM;
- if (usb_endpoint_dir_in(endpoint)) {
+++ /dev/null
-From 6d90716cd7eac0219310ec8ba8a07e585db05932 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 4 Jun 2019 12:14:30 +0100
-Subject: [PATCH 663/703] drm: vc4: Add status of which display is updated
- through vblank
-
-Previously multiple displays were slaved off the same SMI
-interrupt, triggered by HVS channel 1 (HDMI0).
-This doesn't work if you only have a DPI or DSI screen (HVS channel
-0), and gives slightly erroneous results with dual HDMI as the
-events for HDMI1 are incorrect.
-
-Use SMIDSW0 and SMIDSW1 registers to denote which display has
-triggered the vblank.
-Handling should be backwards compatible with older firmware.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 41 ++++++++++++++++++++++----
- 1 file changed, 36 insertions(+), 5 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -230,8 +230,13 @@ static const struct vc_image_format *vc4
- * hardware, which has only this one register.
- */
- #define SMICS 0x0
-+#define SMIDSW0 0x14
-+#define SMIDSW1 0x1C
- #define SMICS_INTERRUPTS (BIT(9) | BIT(10) | BIT(11))
-
-+/* Flag to denote that the firmware is giving multiple display callbacks */
-+#define SMI_NEW 0xabcd0000
-+
- #define vc4_crtc vc4_kms_crtc
- #define to_vc4_crtc to_vc4_kms_crtc
- struct vc4_crtc {
-@@ -884,16 +889,42 @@ static irqreturn_t vc4_crtc_irq_handler(
- int i;
- u32 stat = readl(crtc_list[0]->regs + SMICS);
- irqreturn_t ret = IRQ_NONE;
-+ u32 chan;
-
- if (stat & SMICS_INTERRUPTS) {
- writel(0, crtc_list[0]->regs + SMICS);
-
-- for (i = 0; crtc_list[i]; i++) {
-- if (crtc_list[i]->vblank_enabled)
-- drm_crtc_handle_vblank(&crtc_list[i]->base);
-- vc4_crtc_handle_page_flip(crtc_list[i]);
-- ret = IRQ_HANDLED;
-+ chan = readl(crtc_list[0]->regs + SMIDSW0);
-+
-+ if ((chan & 0xFFFF0000) != SMI_NEW) {
-+ /* Older firmware. Treat the one interrupt as vblank/
-+ * complete for all crtcs.
-+ */
-+ for (i = 0; crtc_list[i]; i++) {
-+ if (crtc_list[i]->vblank_enabled)
-+ drm_crtc_handle_vblank(&crtc_list[i]->base);
-+ vc4_crtc_handle_page_flip(crtc_list[i]);
-+ }
-+ } else {
-+ if (chan & 1) {
-+ writel(SMI_NEW, crtc_list[0]->regs + SMIDSW0);
-+ if (crtc_list[0]->vblank_enabled)
-+ drm_crtc_handle_vblank(&crtc_list[0]->base);
-+ vc4_crtc_handle_page_flip(crtc_list[0]);
-+ }
-+
-+ /* Check for the secondary display too */
-+ chan = readl(crtc_list[0]->regs + SMIDSW1);
-+
-+ if (chan & 1) {
-+ writel(SMI_NEW, crtc_list[0]->regs + SMIDSW1);
-+ if (crtc_list[1]->vblank_enabled)
-+ drm_crtc_handle_vblank(&crtc_list[1]->base);
-+ vc4_crtc_handle_page_flip(crtc_list[1]);
-+ }
- }
-+
-+ ret = IRQ_HANDLED;
- }
-
- return ret;
--- /dev/null
+From 2d7cb00a7971c8384aacd0455a6d5e50abedb1e9 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 18 Jun 2019 12:15:50 +0100
+Subject: [PATCH 663/725] staging: vchiq: Use the old dma controller for OF
+ config on platform devices
+
+vchiq on Pi4 is no longer under the soc node, therefore it
+doesn't get the dma-ranges for the VPU.
+
+Switch to using the configuration of the old dma controller as
+that will set the dma-ranges correctly.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../interface/vchiq_arm/vchiq_arm.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -3599,6 +3599,7 @@ vchiq_register_child(struct platform_dev
+ {
+ struct platform_device_info pdevinfo;
+ struct platform_device *new_dev;
++ struct device_node *np;
+
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+
+@@ -3612,10 +3613,20 @@ vchiq_register_child(struct platform_dev
+ return NULL;
+
+ /*
+- * We want the dma-ranges etc to be copied from the parent VCHIQ device
+- * to be passed on to the children too.
++ * We want the dma-ranges etc to be copied from a device with the
++ * correct dma-ranges for the VPU.
++ * VCHIQ on Pi4 is now under scb which doesn't get those dma-ranges.
++ * Take the "dma" node as going to be suitable as it sees the world
++ * through the same eyes as the VPU.
+ */
+- of_dma_configure(&new_dev->dev, pdev->dev.of_node, true);
++ np = of_find_node_by_path("dma");
++ if (!np)
++ np = pdev->dev.of_node;
++
++ of_dma_configure(&new_dev->dev, np, true);
++
++ if (np != pdev->dev.of_node)
++ of_node_put(np);
+
+ return new_dev;
+ }
+++ /dev/null
-From da7972664ce5c26a876d092d8161901985f9fa8f Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 12 Jun 2019 17:13:21 +0100
-Subject: [PATCH 664/703] drm/vc4: In FKMS look at the modifiers correctly for
- SAND
-
-Incorrect masking was used in the switch for the modifier,
-therefore for SAND (which puts the column pitch in the
-modifier) it didn't match.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -460,7 +460,7 @@ static void vc4_plane_atomic_update(stru
- }
- mb->plane.planes[3] = 0;
-
-- switch (fb->modifier) {
-+ switch (fourcc_mod_broadcom_mod(fb->modifier)) {
- case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
- switch (mb->plane.vc_image_type) {
- case VC_IMAGE_XRGB8888:
-@@ -476,6 +476,9 @@ static void vc4_plane_atomic_update(stru
- break;
- case DRM_FORMAT_MOD_BROADCOM_SAND128:
- mb->plane.vc_image_type = VC_IMAGE_YUV_UV;
-+ /* Note that the column pitch is passed across in lines, not
-+ * bytes.
-+ */
- mb->plane.pitch = fourcc_mod_broadcom_param(fb->modifier);
- break;
- }
--- /dev/null
+From 9fef544e7d4981b5611b857609e18a20dea246e8 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 18 Jun 2019 21:37:45 +0100
+Subject: [PATCH 664/725] drm/vc4: Limit fkms to modes <= 85Hz
+
+Selecting 1080p100 and 120 has very limited gain, but don't want
+to block VGA85 and similar.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -822,6 +822,10 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
+ return MODE_NO_DBLESCAN;
+ }
+
++ /* Disable refresh rates > 85Hz as limited gain from them */
++ if (drm_mode_vrefresh(mode) > 85)
++ return MODE_BAD_VVALUE;
++
+ /* Limit the pixel clock based on the HDMI clock limits from the
+ * firmware
+ */
--- /dev/null
+From 9c89497bb48601b3b1cbf8b868840da3091cc00f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 11 Jun 2019 17:38:28 +0100
+Subject: [PATCH 665/725] arm: bcm2835: Add bcm2838 compatible string.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/mach-bcm/board_bcm2835.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/mach-bcm/board_bcm2835.c
++++ b/arch/arm/mach-bcm/board_bcm2835.c
+@@ -118,6 +118,7 @@ static const char * const bcm2835_compat
+ #ifdef CONFIG_ARCH_MULTI_V7
+ "brcm,bcm2836",
+ "brcm,bcm2837",
++ "brcm,bcm2838",
+ #endif
+ NULL
+ };
+++ /dev/null
-From 119a795378e218aef556999cdeb7ebb44e5fa106 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 17 Jun 2019 10:06:55 +0100
-Subject: [PATCH 665/703] arm: dts: Fix Pi4 PWR LED configuration
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -126,13 +126,13 @@
- act_led: act {
- label = "led0";
- linux,default-trigger = "mmc0";
-- gpios = <&gpio 42 0>;
-+ gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
- };
-
- pwr_led: pwr {
- label = "led1";
-- linux,default-trigger = "input";
-- gpios = <&expgpio 2 0>;
-+ linux,default-trigger = "default-on";
-+ gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
- };
- };
-
--- /dev/null
+From 22742682cf7b7840f50006022350b40b9b095902 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 4 Jun 2019 16:22:22 +0100
+Subject: [PATCH 666/725] arm: dts: Improve the bcm27xx inclusion hierarchy
+
+1) The top-level .dts files now include parallel chains of bcm27xx.dtsi
+ and bcm27xx-rpi.dtsi files, with no cross-inclusion between the two
+ chains.
+
+2) Move definitions and deletions to the point of maximum commonality
+ to reduce redundancy.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 1 +
+ arch/arm/boot/dts/bcm2708-rpi-b.dts | 1 +
+ arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 1 +
+ arch/arm/boot/dts/bcm2708-rpi-zero-w.dts | 1 +
+ arch/arm/boot/dts/bcm2708-rpi-zero.dts | 1 +
+ arch/arm/boot/dts/bcm2708-rpi.dtsi | 63 +++++++---------------
+ arch/arm/boot/dts/bcm2708.dtsi | 1 -
+ arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 1 +
+ arch/arm/boot/dts/bcm2709.dtsi | 1 -
+ arch/arm/boot/dts/bcm270x.dtsi | 18 +------
+ arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 1 +
+ arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 1 +
+ arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 1 +
+ arch/arm/boot/dts/bcm2710.dtsi | 1 -
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 15 ++++--
+ arch/arm/boot/dts/bcm2711-rpi.dtsi | 7 +++
+ arch/arm/boot/dts/bcm2711.dtsi | 10 ----
+ arch/arm/boot/dts/bcm2835-rpi.dtsi | 16 ++++++
+ arch/arm/boot/dts/bcm2838.dtsi | 33 ++++++++----
+ arch/arm/boot/dts/bcm283x.dtsi | 2 +-
+ 20 files changed, 86 insertions(+), 90 deletions(-)
+ create mode 100644 arch/arm/boot/dts/bcm2711-rpi.dtsi
+
+--- 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 "bcm2708-rpi.dtsi"
+ #include "bcm283x-rpi-smsc9514.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+
+--- 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 "bcm2708-rpi.dtsi"
+ #include "bcm283x-rpi-smsc9512.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+
+--- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi
++++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi
+@@ -1,4 +1,5 @@
+ #include "bcm2708.dtsi"
++#include "bcm2708-rpi.dtsi"
+
+ &leds {
+ act_led: act {
+--- a/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+
+ #include "bcm2708.dtsi"
++#include "bcm2708-rpi.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+
+ / {
+--- a/arch/arm/boot/dts/bcm2708-rpi-zero.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+
+ #include "bcm2708.dtsi"
++#include "bcm2708-rpi.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+
+ / {
+--- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
+@@ -1,6 +1,6 @@
+-/* Downstream version of bcm2835-rpi.dtsi */
++/* Downstream modifications to bcm2835-rpi.dtsi */
+
+-#include <dt-bindings/power/raspberrypi-power.h>
++#include "bcm2835-rpi.dtsi"
+
+ / {
+ memory {
+@@ -49,29 +49,10 @@
+ reg = <0x7e200000 0x1000>;
+ };
+
+- firmware: firmware {
+- compatible = "raspberrypi,bcm2835-firmware", "simple-bus";
+- #address-cells = <0>;
+- #size-cells = <0>;
+- mboxes = <&mailbox>;
+- };
+-
+- power: power {
+- compatible = "raspberrypi,bcm2835-power";
+- firmware = <&firmware>;
+- #power-domain-cells = <1>;
+- };
+-
+ fb: fb {
+ compatible = "brcm,bcm2708-fb";
+ firmware = <&firmware>;
+- status = "disabled";
+- };
+-
+- vchiq: mailbox@7e00b840 {
+- compatible = "brcm,bcm2835-vchiq";
+- reg = <0x7e00b840 0x3c>;
+- interrupts = <0 2>;
++ status = "okay";
+ };
+
+ vcsm: vcsm {
+@@ -91,10 +72,6 @@
+ sound: sound {
+ status = "disabled";
+ };
+-
+- txp: txp@7e004000 {
+- status = "disabled";
+- };
+ };
+
+ __overrides__ {
+@@ -125,11 +102,23 @@
+ };
+
+ &hdmi {
+- power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
++ status = "disabled";
+ };
+
+-&usb {
+- power-domains = <&power RPI_POWER_DOMAIN_USB>;
++&txp {
++ status = "disabled";
++};
++
++&i2c0 {
++ status = "disabled";
++};
++
++&i2c1 {
++ status = "disabled";
++};
++
++&i2c2 {
++ status = "disabled";
+ };
+
+ &clocks {
+@@ -141,16 +130,8 @@ sdhost_pins: &sdhost_gpio48 {
+ };
+
+ &sdhost {
+- pinctrl-names = "default";
+- pinctrl-0 = <&sdhost_gpio48>;
+- bus-width = <4>;
+ brcm,overclock-50 = <0>;
+ brcm,pio-limit = <1>;
+- status = "okay";
+-};
+-
+-&fb {
+- status = "okay";
+ };
+
+ &cpu_thermal {
+@@ -160,11 +141,3 @@ sdhost_pins: &sdhost_gpio48 {
+ &vec {
+ status = "disabled";
+ };
+-
+-&csi0 {
+- power-domains = <&power RPI_POWER_DOMAIN_UNICAM0>;
+-};
+-
+-&csi1 {
+- power-domains = <&power RPI_POWER_DOMAIN_UNICAM1>;
+-};
+--- a/arch/arm/boot/dts/bcm2708.dtsi
++++ b/arch/arm/boot/dts/bcm2708.dtsi
+@@ -1,6 +1,5 @@
+ #include "bcm2835.dtsi"
+ #include "bcm270x.dtsi"
+-#include "bcm2708-rpi.dtsi"
+
+ / {
+ /delete-node/ cpus;
+--- 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 "bcm2709-rpi.dtsi"
+ #include "bcm283x-rpi-smsc9514.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+
+--- a/arch/arm/boot/dts/bcm2709.dtsi
++++ b/arch/arm/boot/dts/bcm2709.dtsi
+@@ -1,6 +1,5 @@
+ #include "bcm2836.dtsi"
+ #include "bcm270x.dtsi"
+-#include "bcm2709-rpi.dtsi"
+
+ / {
+ soc {
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -68,7 +68,7 @@
+
+ /delete-node/ sdhci@7e300000;
+
+- mmc: mmc@7e300000 {
++ sdhci: mmc: mmc@7e300000 {
+ compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci";
+ reg = <0x7e300000 0x100>;
+ interrupts = <2 30>;
+@@ -152,22 +152,6 @@
+ };
+ };
+
+- 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;
+- };
+-
+ __overrides__ {
+ cam0-pwdn-ctrl;
+ cam0-pwdn;
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+
+ #include "bcm2710.dtsi"
++#include "bcm2709-rpi.dtsi"
+ #include "bcm283x-rpi-lan7515.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+
+ #include "bcm2710.dtsi"
++#include "bcm2709-rpi.dtsi"
+ #include "bcm283x-rpi-smsc9514.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+
+--- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
+@@ -1,6 +1,7 @@
+ /dts-v1/;
+
+ #include "bcm2710.dtsi"
++#include "bcm2709-rpi.dtsi"
+ #include "bcm283x-rpi-csi0-2lane.dtsi"
+ #include "bcm283x-rpi-csi1-4lane.dtsi"
+
+--- a/arch/arm/boot/dts/bcm2710.dtsi
++++ b/arch/arm/boot/dts/bcm2710.dtsi
+@@ -1,6 +1,5 @@
+ #include "bcm2837.dtsi"
+ #include "bcm270x.dtsi"
+-#include "bcm2709-rpi.dtsi"
+
+ / {
+ compatible = "brcm,bcm2837", "brcm,bcm2836";
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -1,13 +1,12 @@
+ /dts-v1/;
+
+ #include "bcm2711.dtsi"
++#include "bcm2711-rpi.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+
+ / {
+- compatible = "raspberrypi,4-model-b", "brcm,bcm2838", "brcm,bcm2837";
++ compatible = "raspberrypi,4-model-b", "brcm,bcm2838";
+ model = "Raspberry Pi 4 Model B";
+- #address-cells = <2>;
+- #size-cells = <1>;
+
+ memory {
+ device_type = "memory";
+@@ -48,10 +47,18 @@
+ };
+
+ &firmware {
+- expgpio: expgpio {
++ expgpio: gpio {
+ compatible = "raspberrypi,firmware-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
++ gpio-line-names = "BT_ON",
++ "WL_ON",
++ "PWR_LED_OFF",
++ "GLOBAL_RESET",
++ "VDD_SD_IO_SEL",
++ "CAM_GPIO",
++ "",
++ "";
+ status = "okay";
+ };
+ };
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
+@@ -0,0 +1,7 @@
++#include "bcm2708-rpi.dtsi"
++#include "bcm2838-rpi.dtsi"
++
++&v3d {
++ /* Undo the overwriting by bcm270x.dtsi */
++ power-domains = <&pm BCM2835_POWER_DOMAIN_GRAFX_V3D>;
++};
+--- a/arch/arm/boot/dts/bcm2711.dtsi
++++ b/arch/arm/boot/dts/bcm2711.dtsi
+@@ -1,10 +1,8 @@
+ #include "bcm2838.dtsi"
+ #include "bcm270x.dtsi"
+-#include "bcm2708-rpi.dtsi"
+
+ / {
+ soc {
+- /delete-node/ mailbox@7e00b840;
+ /delete-node/ v3d@7ec00000;
+ };
+
+@@ -17,14 +15,6 @@
+ status = "disabled";
+ };
+
+-&dma {
+- brcm,dma-channel-mask = <0x7ef5>;
+-};
+-
+-&txp {
+- interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+-};
+-
+ &firmwarekms {
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ };
+--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
+@@ -36,6 +36,22 @@
+ interrupts = <0 2>;
+ };
+ };
++
++ vdd_3v3_reg: fixedregulator_3v3 {
++ compatible = "regulator-fixed";
++ regulator-name = "3v3";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-always-on;
++ };
++
++ vdd_5v0_reg: fixedregulator_5v0 {
++ compatible = "regulator-fixed";
++ regulator-name = "5v0";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ regulator-always-on;
++ };
+ };
+
+ &gpio {
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -5,7 +5,10 @@
+ #include <dt-bindings/soc/bcm2835-pm.h>
+
+ / {
+- compatible = "brcm,bcm2838", "brcm,bcm2837";
++ compatible = "brcm,bcm2838";
++
++ #address-cells = <2>;
++ #size-cells = <1>;
+
+ interrupt-parent = <&gicv2>;
+
+@@ -16,8 +19,8 @@
+ /* Emulate a contiguous 30-bit address range for DMA */
+ dma-ranges = <0xc0000000 0x0 0x00000000 0x3c000000>;
+
+- /delete-node/ mailbox@7e00b840;
+ /delete-node/ interrupt-controller@7e00f300;
++ /delete-node/ v3d@7ec00000;
+
+ local_intc: local_intc@40000000 {
+ compatible = "brcm,bcm2836-l1-intc";
+@@ -191,6 +194,16 @@
+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
++ pwm1: pwm@7e20c800 {
++ compatible = "brcm,bcm2835-pwm";
++ reg = <0x7e20c800 0x28>;
++ clocks = <&clocks BCM2835_CLOCK_PWM>;
++ assigned-clocks = <&clocks BCM2835_CLOCK_PWM>;
++ assigned-clock-rates = <10000000>;
++ #pwm-cells = <2>;
++ status = "disabled";
++ };
++
+ emmc2: emmc2@7e340000 {
+ compatible = "brcm,bcm2711-emmc2";
+ status = "okay";
+@@ -385,7 +398,7 @@
+ "dma13",
+ "dma14";
+ #dma-cells = <1>;
+- brcm,dma-channel-mask = <0x7000>;
++ brcm,dma-channel-mask = <0x7800>;
+ };
+ /* DMA4 - 40 bit DMA engines */
+
+@@ -396,12 +409,6 @@
+ interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+- vchiq: mailbox@7e00b840 {
+- compatible = "brcm,bcm2838-vchiq";
+- reg = <0 0x7e00b840 0x3c>;
+- interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+- };
+-
+ hevc-decoder@7eb00000 {
+ compatible = "raspberrypi,argon-hevc-decoder";
+ reg = <0x0 0x7eb00000 0x10000>;
+@@ -450,6 +457,8 @@
+ };
+
+ &gpio {
++ compatible = "brcm,bcm2838-gpio", "brcm,bcm2835-gpio";
++
+ gpclk0_gpio49: gpclk0_gpio49 {
+ brcm,pins = <49>;
+ brcm,function = <BCM2835_FSEL_ALT1>;
+@@ -729,5 +738,9 @@
+ "dma8",
+ "dma9",
+ "dma10";
+- brcm,dma-channel-mask = <0x01f5>;
++ brcm,dma-channel-mask = <0x07f5>;
++};
++
++&txp {
++ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+ };
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -55,7 +55,7 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+- txp@7e004000 {
++ txp: txp@7e004000 {
+ compatible = "brcm,bcm2835-txp";
+ reg = <0x7e004000 0x20>;
+ interrupts = <1 11>;
+++ /dev/null
-From 8514b037813eddea0ecc044978a36fe815a29b01 Mon Sep 17 00:00:00 2001
-From: dp111 <dominic.plunkett@gmail.com>
-Date: Sat, 15 Jun 2019 18:19:50 +0100
-Subject: [PATCH 666/703] bcm2838.dtsi : Correct gic400 memory address ranges
-
-It appears to me the addresses for the gic400 are slightly wrong . See section 3.2 https://static.docs.arm.com/ddi0471/a/DDI0471A_gic400_r0p0_trm.pdf
----
- arch/arm/boot/dts/bcm2838.dtsi | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2838.dtsi
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -30,8 +30,8 @@
- compatible = "arm,gic-400";
- reg = <0x40041000 0x1000>,
- <0x40042000 0x2000>,
-- <0x40046000 0x2000>,
-- <0x40048000 0x2000>;
-+ <0x40044000 0x2000>,
-+ <0x40046000 0x2000>;
- };
-
- thermal: thermal@7d5d2200 {
--- /dev/null
+From 3183783f2a7db515671c6c612988627f946b4a36 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 11 Jun 2019 18:08:05 +0100
+Subject: [PATCH 667/725] arm: dts: First draft of upstream Pi4 DTS
+
+I've attempted to follow the upstream conventions in the DT commits,
+but this is just presented here initially as a talking point.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/Makefile | 1 +
+ arch/arm/boot/dts/bcm2838-rpi-4-b.dts | 118 ++++++++++++++++++++++++++
+ arch/arm/boot/dts/bcm2838-rpi.dtsi | 25 ++++++
+ 3 files changed, 144 insertions(+)
+ create mode 100644 arch/arm/boot/dts/bcm2838-rpi-4-b.dts
+ create mode 100644 arch/arm/boot/dts/bcm2838-rpi.dtsi
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -94,6 +94,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+ bcm2836-rpi-2-b.dtb \
+ bcm2837-rpi-3-b.dtb \
+ bcm2837-rpi-3-b-plus.dtb \
++ bcm2838-rpi-4-b.dtb \
+ bcm2835-rpi-zero.dtb \
+ bcm2835-rpi-zero-w.dtb
+ dtb-$(CONFIG_ARCH_BCM_5301X) += \
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2838-rpi-4-b.dts
+@@ -0,0 +1,118 @@
++// SPDX-License-Identifier: GPL-2.0
++/dts-v1/;
++#include "bcm2838.dtsi"
++#include "bcm2835-rpi.dtsi"
++#include "bcm2838-rpi.dtsi"
++
++/ {
++ compatible = "raspberrypi,4-model-b", "brcm,bcm2838";
++ model = "Raspberry Pi 4 Model B";
++
++ chosen {
++ /* 8250 auxiliary UART instead of pl011 */
++ stdout-path = "serial1:115200n8";
++ };
++
++ memory {
++ reg = <0 0 0x40000000>;
++ };
++
++ leds {
++ act {
++ gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
++ };
++
++ pwr {
++ label = "PWR";
++ gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
++ };
++ };
++
++ wifi_pwrseq: wifi-pwrseq {
++ compatible = "mmc-pwrseq-simple";
++ reset-gpios = <&expgpio 1 GPIO_ACTIVE_LOW>;
++ };
++
++ sd_io_1v8_reg: sd_io_1v8_reg {
++ status = "okay";
++ compatible = "regulator-gpio";
++ vin-supply = <&vdd_5v0_reg>;
++ regulator-name = "vdd-sd-io";
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-boot-on;
++ regulator-always-on;
++ regulator-settling-time-us = <5000>;
++
++ gpios = <&expgpio 4 GPIO_ACTIVE_HIGH>;
++ states = <1800000 0x1
++ 3300000 0x0>;
++ };
++};
++
++&firmware {
++ expgpio: gpio {
++ compatible = "raspberrypi,firmware-gpio";
++ gpio-controller;
++ #gpio-cells = <2>;
++ gpio-line-names = "BT_ON",
++ "WL_ON",
++ "PWR_LED_OFF",
++ "GLOBAL_RESET",
++ "VDD_SD_IO_SEL",
++ "CAM_GPIO",
++ "",
++ "";
++ status = "okay";
++ };
++};
++
++&pwm1 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio41>;
++ status = "okay";
++};
++
++/* SDHCI is used to control the SDIO for wireless */
++&sdhci {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&emmc_gpio34>;
++ status = "okay";
++ bus-width = <4>;
++ non-removable;
++ mmc-pwrseq = <&wifi_pwrseq>;
++
++ brcmf: wifi@1 {
++ reg = <1>;
++ compatible = "brcm,bcm4329-fmac";
++ };
++};
++
++/* EMMC2 is used to drive the SD card */
++&emmc2 {
++ status = "okay";
++ broken-cd;
++ vqmmc-supply = <&sd_io_1v8_reg>;
++};
++
++/* uart0 communicates with the BT module */
++&uart0 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart0_ctsrts_gpio30 &uart0_gpio32 &gpclk2_gpio43>;
++ status = "okay";
++
++ bluetooth {
++ compatible = "brcm,bcm43438-bt";
++ max-speed = <2000000>;
++ shutdown-gpios = <&expgpio 0 GPIO_ACTIVE_HIGH>;
++ };
++};
++
++/* uart1 is mapped to the pin header */
++&uart1 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart1_gpio14>;
++ status = "okay";
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2838-rpi.dtsi
+@@ -0,0 +1,25 @@
++// SPDX-License-Identifier: GPL-2.0
++
++/ {
++ soc {
++ /delete-node/ mailbox@7e00b840;
++ };
++};
++
++&scb {
++ vchiq: mailbox@7e00b840 {
++ compatible = "brcm,bcm2838-vchiq";
++ reg = <0 0x7e00b840 0x3c>;
++ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
++ };
++};
++
++&dma {
++ /* The VPU firmware uses DMA channel 11 for VCHIQ */
++ brcm,dma-channel-mask = <0x1f5>;
++};
++
++&dma40 {
++ /* The VPU firmware DMA channel 11 for VCHIQ */
++ brcm,dma-channel-mask = <0x7000>;
++};
+++ /dev/null
-From 9d6d168d99226d7f31cb1ba56ada37913ebd690a Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 18 Jun 2019 12:15:50 +0100
-Subject: [PATCH 667/703] staging: vchiq: Use the old dma controller for OF
- config on platform devices
-
-vchiq on Pi4 is no longer under the soc node, therefore it
-doesn't get the dma-ranges for the VPU.
-
-Switch to using the configuration of the old dma controller as
-that will set the dma-ranges correctly.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../interface/vchiq_arm/vchiq_arm.c | 17 ++++++++++++++---
- 1 file changed, 14 insertions(+), 3 deletions(-)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -3599,6 +3599,7 @@ vchiq_register_child(struct platform_dev
- {
- struct platform_device_info pdevinfo;
- struct platform_device *new_dev;
-+ struct device_node *np;
-
- memset(&pdevinfo, 0, sizeof(pdevinfo));
-
-@@ -3612,10 +3613,20 @@ vchiq_register_child(struct platform_dev
- return NULL;
-
- /*
-- * We want the dma-ranges etc to be copied from the parent VCHIQ device
-- * to be passed on to the children too.
-+ * We want the dma-ranges etc to be copied from a device with the
-+ * correct dma-ranges for the VPU.
-+ * VCHIQ on Pi4 is now under scb which doesn't get those dma-ranges.
-+ * Take the "dma" node as going to be suitable as it sees the world
-+ * through the same eyes as the VPU.
- */
-- of_dma_configure(&new_dev->dev, pdev->dev.of_node, true);
-+ np = of_find_node_by_path("dma");
-+ if (!np)
-+ np = pdev->dev.of_node;
-+
-+ of_dma_configure(&new_dev->dev, np, true);
-+
-+ if (np != pdev->dev.of_node)
-+ of_node_put(np);
-
- return new_dev;
- }
+++ /dev/null
-From 912084a11b3b27c771dddfaf670fdf35433c969f Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 18 Jun 2019 21:37:45 +0100
-Subject: [PATCH 668/703] drm/vc4: Limit fkms to modes <= 85Hz
-
-Selecting 1080p100 and 120 has very limited gain, but don't want
-to block VGA85 and similar.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -822,6 +822,10 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
- return MODE_NO_DBLESCAN;
- }
-
-+ /* Disable refresh rates > 85Hz as limited gain from them */
-+ if (drm_mode_vrefresh(mode) > 85)
-+ return MODE_BAD_VVALUE;
-+
- /* Limit the pixel clock based on the HDMI clock limits from the
- * firmware
- */
--- /dev/null
+From 6c53b393a82affcdb32ca7a81871130db5ec149b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 17 Jun 2019 14:36:12 +0100
+Subject: [PATCH 668/725] overlays: Fix compatible string for ds1307 RTC
+
+Kernels since 4.19 have required the correct manufacture name in the
+compatible string for I2C devices, and unfortunately the one for the
+Dallas/Maxim DS1307 should have been "dallas,ds1307" and not
+"maxim,ds1307".
+
+See: https://github.com/raspberrypi/linux/issues/3013
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -30,7 +30,7 @@
+ status = "okay";
+
+ ds1307: ds1307@68 {
+- compatible = "maxim,ds1307";
++ compatible = "dallas,ds1307";
+ reg = <0x68>;
+ status = "okay";
+ };
+++ /dev/null
-From 7142fbe9edf1c608d788569cb399aa075f2ee837 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 11 Jun 2019 17:38:28 +0100
-Subject: [PATCH 669/703] arm: bcm2835: Add bcm2838 compatible string.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/mach-bcm/board_bcm2835.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/mach-bcm/board_bcm2835.c
-+++ b/arch/arm/mach-bcm/board_bcm2835.c
-@@ -118,6 +118,7 @@ static const char * const bcm2835_compat
- #ifdef CONFIG_ARCH_MULTI_V7
- "brcm,bcm2836",
- "brcm,bcm2837",
-+ "brcm,bcm2838",
- #endif
- NULL
- };
--- /dev/null
+From a0a581e7019049be7f62f9251bdbe4f9e09485a0 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 18 Jun 2019 11:16:13 +0100
+Subject: [PATCH 669/725] overlays: Fix further maxim,ds1307 references
+
+See: https://github.com/raspberrypi/linux/issues/3013
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/balena-fin-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/tinylcd35-overlay.dts | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
++++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
+@@ -84,7 +84,7 @@
+
+ // rtc clock
+ ds1307: ds1307@68 {
+- compatible = "maxim,ds1307";
++ compatible = "dallas,ds1307";
+ reg = <0x68>;
+ status = "okay";
+ };
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
+@@ -46,7 +46,7 @@
+ status = "okay";
+
+ ds1307: ds1307@68 {
+- compatible = "maxim,ds1307";
++ compatible = "dallas,ds1307";
+ reg = <0x68>;
+ status = "okay";
+ };
+--- a/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
++++ b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
+@@ -155,7 +155,7 @@
+ status = "okay";
+
+ ds1307: ds1307@68 {
+- compatible = "maxim,ds1307";
++ compatible = "dallas,ds1307";
+ reg = <0x68>;
+ status = "okay";
+ };
+++ /dev/null
-From c0cff263c6927ed494f81fcde6bf6fe00e33271b Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 4 Jun 2019 16:22:22 +0100
-Subject: [PATCH 670/703] arm: dts: Improve the bcm27xx inclusion hierarchy
-
-1) The top-level .dts files now include parallel chains of bcm27xx.dtsi
- and bcm27xx-rpi.dtsi files, with no cross-inclusion between the two
- chains.
-
-2) Move definitions and deletions to the point of maximum commonality
- to reduce redundancy.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 1 +
- arch/arm/boot/dts/bcm2708-rpi-b.dts | 1 +
- arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 1 +
- arch/arm/boot/dts/bcm2708-rpi-zero-w.dts | 1 +
- arch/arm/boot/dts/bcm2708-rpi-zero.dts | 1 +
- arch/arm/boot/dts/bcm2708-rpi.dtsi | 63 +++++++---------------
- arch/arm/boot/dts/bcm2708.dtsi | 1 -
- arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 1 +
- arch/arm/boot/dts/bcm2709.dtsi | 1 -
- arch/arm/boot/dts/bcm270x.dtsi | 18 +------
- arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 1 +
- arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 1 +
- arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 1 +
- arch/arm/boot/dts/bcm2710.dtsi | 1 -
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 15 ++++--
- arch/arm/boot/dts/bcm2711-rpi.dtsi | 7 +++
- arch/arm/boot/dts/bcm2711.dtsi | 10 ----
- arch/arm/boot/dts/bcm2835-rpi.dtsi | 16 ++++++
- arch/arm/boot/dts/bcm2838.dtsi | 33 ++++++++----
- arch/arm/boot/dts/bcm283x.dtsi | 2 +-
- 20 files changed, 86 insertions(+), 90 deletions(-)
- create mode 100644 arch/arm/boot/dts/bcm2711-rpi.dtsi
-
---- 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 "bcm2708-rpi.dtsi"
- #include "bcm283x-rpi-smsc9514.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
-
---- 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 "bcm2708-rpi.dtsi"
- #include "bcm283x-rpi-smsc9512.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
-
---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi
-+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi
-@@ -1,4 +1,5 @@
- #include "bcm2708.dtsi"
-+#include "bcm2708-rpi.dtsi"
-
- &leds {
- act_led: act {
---- a/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
-+++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
-
- #include "bcm2708.dtsi"
-+#include "bcm2708-rpi.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
-
- / {
---- a/arch/arm/boot/dts/bcm2708-rpi-zero.dts
-+++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
-
- #include "bcm2708.dtsi"
-+#include "bcm2708-rpi.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
-
- / {
---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi
-@@ -1,6 +1,6 @@
--/* Downstream version of bcm2835-rpi.dtsi */
-+/* Downstream modifications to bcm2835-rpi.dtsi */
-
--#include <dt-bindings/power/raspberrypi-power.h>
-+#include "bcm2835-rpi.dtsi"
-
- / {
- memory {
-@@ -49,29 +49,10 @@
- reg = <0x7e200000 0x1000>;
- };
-
-- firmware: firmware {
-- compatible = "raspberrypi,bcm2835-firmware", "simple-bus";
-- #address-cells = <0>;
-- #size-cells = <0>;
-- mboxes = <&mailbox>;
-- };
--
-- power: power {
-- compatible = "raspberrypi,bcm2835-power";
-- firmware = <&firmware>;
-- #power-domain-cells = <1>;
-- };
--
- fb: fb {
- compatible = "brcm,bcm2708-fb";
- firmware = <&firmware>;
-- status = "disabled";
-- };
--
-- vchiq: mailbox@7e00b840 {
-- compatible = "brcm,bcm2835-vchiq";
-- reg = <0x7e00b840 0x3c>;
-- interrupts = <0 2>;
-+ status = "okay";
- };
-
- vcsm: vcsm {
-@@ -91,10 +72,6 @@
- sound: sound {
- status = "disabled";
- };
--
-- txp: txp@7e004000 {
-- status = "disabled";
-- };
- };
-
- __overrides__ {
-@@ -125,11 +102,23 @@
- };
-
- &hdmi {
-- power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
-+ status = "disabled";
- };
-
--&usb {
-- power-domains = <&power RPI_POWER_DOMAIN_USB>;
-+&txp {
-+ status = "disabled";
-+};
-+
-+&i2c0 {
-+ status = "disabled";
-+};
-+
-+&i2c1 {
-+ status = "disabled";
-+};
-+
-+&i2c2 {
-+ status = "disabled";
- };
-
- &clocks {
-@@ -141,16 +130,8 @@ sdhost_pins: &sdhost_gpio48 {
- };
-
- &sdhost {
-- pinctrl-names = "default";
-- pinctrl-0 = <&sdhost_gpio48>;
-- bus-width = <4>;
- brcm,overclock-50 = <0>;
- brcm,pio-limit = <1>;
-- status = "okay";
--};
--
--&fb {
-- status = "okay";
- };
-
- &cpu_thermal {
-@@ -160,11 +141,3 @@ sdhost_pins: &sdhost_gpio48 {
- &vec {
- status = "disabled";
- };
--
--&csi0 {
-- power-domains = <&power RPI_POWER_DOMAIN_UNICAM0>;
--};
--
--&csi1 {
-- power-domains = <&power RPI_POWER_DOMAIN_UNICAM1>;
--};
---- a/arch/arm/boot/dts/bcm2708.dtsi
-+++ b/arch/arm/boot/dts/bcm2708.dtsi
-@@ -1,6 +1,5 @@
- #include "bcm2835.dtsi"
- #include "bcm270x.dtsi"
--#include "bcm2708-rpi.dtsi"
-
- / {
- /delete-node/ cpus;
---- 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 "bcm2709-rpi.dtsi"
- #include "bcm283x-rpi-smsc9514.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
-
---- a/arch/arm/boot/dts/bcm2709.dtsi
-+++ b/arch/arm/boot/dts/bcm2709.dtsi
-@@ -1,6 +1,5 @@
- #include "bcm2836.dtsi"
- #include "bcm270x.dtsi"
--#include "bcm2709-rpi.dtsi"
-
- / {
- soc {
---- a/arch/arm/boot/dts/bcm270x.dtsi
-+++ b/arch/arm/boot/dts/bcm270x.dtsi
-@@ -68,7 +68,7 @@
-
- /delete-node/ sdhci@7e300000;
-
-- mmc: mmc@7e300000 {
-+ sdhci: mmc: mmc@7e300000 {
- compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci";
- reg = <0x7e300000 0x100>;
- interrupts = <2 30>;
-@@ -152,22 +152,6 @@
- };
- };
-
-- 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;
-- };
--
- __overrides__ {
- cam0-pwdn-ctrl;
- cam0-pwdn;
---- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
-
- #include "bcm2710.dtsi"
-+#include "bcm2709-rpi.dtsi"
- #include "bcm283x-rpi-lan7515.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
-
---- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
-
- #include "bcm2710.dtsi"
-+#include "bcm2709-rpi.dtsi"
- #include "bcm283x-rpi-smsc9514.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
-
---- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
-+++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
-@@ -1,6 +1,7 @@
- /dts-v1/;
-
- #include "bcm2710.dtsi"
-+#include "bcm2709-rpi.dtsi"
- #include "bcm283x-rpi-csi0-2lane.dtsi"
- #include "bcm283x-rpi-csi1-4lane.dtsi"
-
---- a/arch/arm/boot/dts/bcm2710.dtsi
-+++ b/arch/arm/boot/dts/bcm2710.dtsi
-@@ -1,6 +1,5 @@
- #include "bcm2837.dtsi"
- #include "bcm270x.dtsi"
--#include "bcm2709-rpi.dtsi"
-
- / {
- compatible = "brcm,bcm2837", "brcm,bcm2836";
---- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -1,13 +1,12 @@
- /dts-v1/;
-
- #include "bcm2711.dtsi"
-+#include "bcm2711-rpi.dtsi"
- #include "bcm283x-rpi-csi1-2lane.dtsi"
-
- / {
-- compatible = "raspberrypi,4-model-b", "brcm,bcm2838", "brcm,bcm2837";
-+ compatible = "raspberrypi,4-model-b", "brcm,bcm2838";
- model = "Raspberry Pi 4 Model B";
-- #address-cells = <2>;
-- #size-cells = <1>;
-
- memory {
- device_type = "memory";
-@@ -48,10 +47,18 @@
- };
-
- &firmware {
-- expgpio: expgpio {
-+ expgpio: gpio {
- compatible = "raspberrypi,firmware-gpio";
- gpio-controller;
- #gpio-cells = <2>;
-+ gpio-line-names = "BT_ON",
-+ "WL_ON",
-+ "PWR_LED_OFF",
-+ "GLOBAL_RESET",
-+ "VDD_SD_IO_SEL",
-+ "CAM_GPIO",
-+ "",
-+ "";
- status = "okay";
- };
- };
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
-@@ -0,0 +1,7 @@
-+#include "bcm2708-rpi.dtsi"
-+#include "bcm2838-rpi.dtsi"
-+
-+&v3d {
-+ /* Undo the overwriting by bcm270x.dtsi */
-+ power-domains = <&pm BCM2835_POWER_DOMAIN_GRAFX_V3D>;
-+};
---- a/arch/arm/boot/dts/bcm2711.dtsi
-+++ b/arch/arm/boot/dts/bcm2711.dtsi
-@@ -1,10 +1,8 @@
- #include "bcm2838.dtsi"
- #include "bcm270x.dtsi"
--#include "bcm2708-rpi.dtsi"
-
- / {
- soc {
-- /delete-node/ mailbox@7e00b840;
- /delete-node/ v3d@7ec00000;
- };
-
-@@ -17,14 +15,6 @@
- status = "disabled";
- };
-
--&dma {
-- brcm,dma-channel-mask = <0x7ef5>;
--};
--
--&txp {
-- interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
--};
--
- &firmwarekms {
- interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
- };
---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
-+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
-@@ -36,6 +36,22 @@
- interrupts = <0 2>;
- };
- };
-+
-+ vdd_3v3_reg: fixedregulator_3v3 {
-+ compatible = "regulator-fixed";
-+ regulator-name = "3v3";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ regulator-always-on;
-+ };
-+
-+ vdd_5v0_reg: fixedregulator_5v0 {
-+ compatible = "regulator-fixed";
-+ regulator-name = "5v0";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ regulator-always-on;
-+ };
- };
-
- &gpio {
---- a/arch/arm/boot/dts/bcm2838.dtsi
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -5,7 +5,10 @@
- #include <dt-bindings/soc/bcm2835-pm.h>
-
- / {
-- compatible = "brcm,bcm2838", "brcm,bcm2837";
-+ compatible = "brcm,bcm2838";
-+
-+ #address-cells = <2>;
-+ #size-cells = <1>;
-
- interrupt-parent = <&gicv2>;
-
-@@ -16,8 +19,8 @@
- /* Emulate a contiguous 30-bit address range for DMA */
- dma-ranges = <0xc0000000 0x0 0x00000000 0x3c000000>;
-
-- /delete-node/ mailbox@7e00b840;
- /delete-node/ interrupt-controller@7e00f300;
-+ /delete-node/ v3d@7ec00000;
-
- local_intc: local_intc@40000000 {
- compatible = "brcm,bcm2836-l1-intc";
-@@ -191,6 +194,16 @@
- interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
- };
-
-+ pwm1: pwm@7e20c800 {
-+ compatible = "brcm,bcm2835-pwm";
-+ reg = <0x7e20c800 0x28>;
-+ clocks = <&clocks BCM2835_CLOCK_PWM>;
-+ assigned-clocks = <&clocks BCM2835_CLOCK_PWM>;
-+ assigned-clock-rates = <10000000>;
-+ #pwm-cells = <2>;
-+ status = "disabled";
-+ };
-+
- emmc2: emmc2@7e340000 {
- compatible = "brcm,bcm2711-emmc2";
- status = "okay";
-@@ -385,7 +398,7 @@
- "dma13",
- "dma14";
- #dma-cells = <1>;
-- brcm,dma-channel-mask = <0x7000>;
-+ brcm,dma-channel-mask = <0x7800>;
- };
- /* DMA4 - 40 bit DMA engines */
-
-@@ -396,12 +409,6 @@
- interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
- };
-
-- vchiq: mailbox@7e00b840 {
-- compatible = "brcm,bcm2838-vchiq";
-- reg = <0 0x7e00b840 0x3c>;
-- interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
-- };
--
- hevc-decoder@7eb00000 {
- compatible = "raspberrypi,argon-hevc-decoder";
- reg = <0x0 0x7eb00000 0x10000>;
-@@ -450,6 +457,8 @@
- };
-
- &gpio {
-+ compatible = "brcm,bcm2838-gpio", "brcm,bcm2835-gpio";
-+
- gpclk0_gpio49: gpclk0_gpio49 {
- brcm,pins = <49>;
- brcm,function = <BCM2835_FSEL_ALT1>;
-@@ -729,5 +738,9 @@
- "dma8",
- "dma9",
- "dma10";
-- brcm,dma-channel-mask = <0x01f5>;
-+ brcm,dma-channel-mask = <0x07f5>;
-+};
-+
-+&txp {
-+ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
- };
---- a/arch/arm/boot/dts/bcm283x.dtsi
-+++ b/arch/arm/boot/dts/bcm283x.dtsi
-@@ -55,7 +55,7 @@
- #address-cells = <1>;
- #size-cells = <1>;
-
-- txp@7e004000 {
-+ txp: txp@7e004000 {
- compatible = "brcm,bcm2835-txp";
- reg = <0x7e004000 0x20>;
- interrupts = <1 11>;
--- /dev/null
+From 0794b3c523e484608cfd87db2ce8ee7cd30e5e43 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 18 Jun 2019 11:19:59 +0100
+Subject: [PATCH 670/725] overlays: Cosmetic change to upstream overlay
+
+The dwc2 overlay no longer uses the dwc2_usb label, and the latest
+ovmerge (which generates the upstream overlay) removes unused labels.
+Update the checked-in version to match.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/upstream-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
+@@ -113,7 +113,7 @@
+ target = <&usb>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+- dwc2_usb: __overlay__ {
++ __overlay__ {
+ compatible = "brcm,bcm2835-usb";
+ dr_mode = "otg";
+ g-np-tx-fifo-size = <32>;
+++ /dev/null
-From 575145094f904ca3c50e07f69a4ffaea902eadd7 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 11 Jun 2019 18:08:05 +0100
-Subject: [PATCH 671/703] arm: dts: First draft of upstream Pi4 DTS
-
-I've attempted to follow the upstream conventions in the DT commits,
-but this is just presented here initially as a talking point.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/Makefile | 1 +
- arch/arm/boot/dts/bcm2838-rpi-4-b.dts | 118 ++++++++++++++++++++++++++
- arch/arm/boot/dts/bcm2838-rpi.dtsi | 25 ++++++
- 3 files changed, 144 insertions(+)
- create mode 100644 arch/arm/boot/dts/bcm2838-rpi-4-b.dts
- create mode 100644 arch/arm/boot/dts/bcm2838-rpi.dtsi
-
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -94,6 +94,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
- bcm2836-rpi-2-b.dtb \
- bcm2837-rpi-3-b.dtb \
- bcm2837-rpi-3-b-plus.dtb \
-+ bcm2838-rpi-4-b.dtb \
- bcm2835-rpi-zero.dtb \
- bcm2835-rpi-zero-w.dtb
- dtb-$(CONFIG_ARCH_BCM_5301X) += \
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2838-rpi-4-b.dts
-@@ -0,0 +1,118 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/dts-v1/;
-+#include "bcm2838.dtsi"
-+#include "bcm2835-rpi.dtsi"
-+#include "bcm2838-rpi.dtsi"
-+
-+/ {
-+ compatible = "raspberrypi,4-model-b", "brcm,bcm2838";
-+ model = "Raspberry Pi 4 Model B";
-+
-+ chosen {
-+ /* 8250 auxiliary UART instead of pl011 */
-+ stdout-path = "serial1:115200n8";
-+ };
-+
-+ memory {
-+ reg = <0 0 0x40000000>;
-+ };
-+
-+ leds {
-+ act {
-+ gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
-+ };
-+
-+ pwr {
-+ label = "PWR";
-+ gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
-+ };
-+ };
-+
-+ wifi_pwrseq: wifi-pwrseq {
-+ compatible = "mmc-pwrseq-simple";
-+ reset-gpios = <&expgpio 1 GPIO_ACTIVE_LOW>;
-+ };
-+
-+ sd_io_1v8_reg: sd_io_1v8_reg {
-+ status = "okay";
-+ compatible = "regulator-gpio";
-+ vin-supply = <&vdd_5v0_reg>;
-+ regulator-name = "vdd-sd-io";
-+ regulator-min-microvolt = <1800000>;
-+ regulator-max-microvolt = <3300000>;
-+ regulator-boot-on;
-+ regulator-always-on;
-+ regulator-settling-time-us = <5000>;
-+
-+ gpios = <&expgpio 4 GPIO_ACTIVE_HIGH>;
-+ states = <1800000 0x1
-+ 3300000 0x0>;
-+ };
-+};
-+
-+&firmware {
-+ expgpio: gpio {
-+ compatible = "raspberrypi,firmware-gpio";
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+ gpio-line-names = "BT_ON",
-+ "WL_ON",
-+ "PWR_LED_OFF",
-+ "GLOBAL_RESET",
-+ "VDD_SD_IO_SEL",
-+ "CAM_GPIO",
-+ "",
-+ "";
-+ status = "okay";
-+ };
-+};
-+
-+&pwm1 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio41>;
-+ status = "okay";
-+};
-+
-+/* SDHCI is used to control the SDIO for wireless */
-+&sdhci {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&emmc_gpio34>;
-+ status = "okay";
-+ bus-width = <4>;
-+ non-removable;
-+ mmc-pwrseq = <&wifi_pwrseq>;
-+
-+ brcmf: wifi@1 {
-+ reg = <1>;
-+ compatible = "brcm,bcm4329-fmac";
-+ };
-+};
-+
-+/* EMMC2 is used to drive the SD card */
-+&emmc2 {
-+ status = "okay";
-+ broken-cd;
-+ vqmmc-supply = <&sd_io_1v8_reg>;
-+};
-+
-+/* uart0 communicates with the BT module */
-+&uart0 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart0_ctsrts_gpio30 &uart0_gpio32 &gpclk2_gpio43>;
-+ status = "okay";
-+
-+ bluetooth {
-+ compatible = "brcm,bcm43438-bt";
-+ max-speed = <2000000>;
-+ shutdown-gpios = <&expgpio 0 GPIO_ACTIVE_HIGH>;
-+ };
-+};
-+
-+/* uart1 is mapped to the pin header */
-+&uart1 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart1_gpio14>;
-+ status = "okay";
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/bcm2838-rpi.dtsi
-@@ -0,0 +1,25 @@
-+// SPDX-License-Identifier: GPL-2.0
-+
-+/ {
-+ soc {
-+ /delete-node/ mailbox@7e00b840;
-+ };
-+};
-+
-+&scb {
-+ vchiq: mailbox@7e00b840 {
-+ compatible = "brcm,bcm2838-vchiq";
-+ reg = <0 0x7e00b840 0x3c>;
-+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
-+ };
-+};
-+
-+&dma {
-+ /* The VPU firmware uses DMA channel 11 for VCHIQ */
-+ brcm,dma-channel-mask = <0x1f5>;
-+};
-+
-+&dma40 {
-+ /* The VPU firmware DMA channel 11 for VCHIQ */
-+ brcm,dma-channel-mask = <0x7000>;
-+};
--- /dev/null
+From 0d91e3b824bb24692b50bf7f31f07adb8f2370c6 Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Sat, 25 May 2019 10:45:38 +0200
+Subject: [PATCH 671/725] w1: ds2805: rename w1_family struct, fixing c-p typo
+
+commit 0e3743d870711ae4daf1e7170c8d9381564e244d upstream.
+
+The ds2805 has a structure named: w1_family_2d, which surely
+comes from a w1_ds2431 module. This commit fixes this name to
+prevent confusion and mark a correct family name.
+
+Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_ds2805.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/w1/slaves/w1_ds2805.c
++++ b/drivers/w1/slaves/w1_ds2805.c
+@@ -288,7 +288,7 @@ static struct w1_family_ops w1_f0d_fops
+ .remove_slave = w1_f0d_remove_slave,
+ };
+
+-static struct w1_family w1_family_2d = {
++static struct w1_family w1_family_0d = {
+ .fid = W1_EEPROM_DS2805,
+ .fops = &w1_f0d_fops,
+ };
+@@ -296,13 +296,13 @@ static struct w1_family w1_family_2d = {
+ static int __init w1_f0d_init(void)
+ {
+ pr_info("%s()\n", __func__);
+- return w1_register_family(&w1_family_2d);
++ return w1_register_family(&w1_family_0d);
+ }
+
+ static void __exit w1_f0d_fini(void)
+ {
+ pr_info("%s()\n", __func__);
+- w1_unregister_family(&w1_family_2d);
++ w1_unregister_family(&w1_family_0d);
+ }
+
+ module_init(w1_f0d_init);
+++ /dev/null
-From c39c0e9e9c90dc39b5190d3673b88af7cb126e75 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 17 Jun 2019 14:36:12 +0100
-Subject: [PATCH 672/703] overlays: Fix compatible string for ds1307 RTC
-
-Kernels since 4.19 have required the correct manufacture name in the
-compatible string for I2C devices, and unfortunately the one for the
-Dallas/Maxim DS1307 should have been "dallas,ds1307" and not
-"maxim,ds1307".
-
-See: https://github.com/raspberrypi/linux/issues/3013
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-@@ -30,7 +30,7 @@
- status = "okay";
-
- ds1307: ds1307@68 {
-- compatible = "maxim,ds1307";
-+ compatible = "dallas,ds1307";
- reg = <0x68>;
- status = "okay";
- };
--- /dev/null
+From 8cebfa181f4bead15fb2dd73756a4d139339c83b Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Mon, 20 May 2019 09:05:55 +0200
+Subject: [PATCH 672/725] w1: ds2413: output_write() cosmetic fixes / simplify
+
+commit ae2ee27aa985232f66421d7cd1c7f4b87c7dba7d upstream.
+
+Make the output_write simpler.
+Based on Jean-Francois Dagenais code from:
+49695ac46861 ("w1: ds2408: reset on output_write retry with readback")
+
+Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_ds2413.c | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+--- a/drivers/w1/slaves/w1_ds2413.c
++++ b/drivers/w1/slaves/w1_ds2413.c
+@@ -69,6 +69,7 @@ static ssize_t output_write(struct file
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+ u8 w1_buf[3];
+ unsigned int retries = W1_F3A_RETRIES;
++ ssize_t bytes_written = -EIO;
+
+ if (count != 1 || off != 0)
+ return -EFAULT;
+@@ -78,7 +79,7 @@ static ssize_t output_write(struct file
+ dev_dbg(&sl->dev, "mutex locked");
+
+ if (w1_reset_select_slave(sl))
+- goto error;
++ goto out;
+
+ /* according to the DS2413 datasheet the most significant 6 bits
+ should be set to "1"s, so do it now */
+@@ -91,18 +92,20 @@ static ssize_t output_write(struct file
+ w1_write_block(sl->master, w1_buf, 3);
+
+ if (w1_read_8(sl->master) == W1_F3A_SUCCESS_CONFIRM_BYTE) {
+- mutex_unlock(&sl->master->bus_mutex);
+- dev_dbg(&sl->dev, "mutex unlocked, retries:%d", retries);
+- return 1;
++ bytes_written = 1;
++ goto out;
+ }
+ if (w1_reset_resume_command(sl->master))
+- goto error;
++ goto out; /* unrecoverable error */
++
++ dev_warn(&sl->dev, "PIO_ACCESS_WRITE error, retries left: %d\n", retries);
+ }
+
+-error:
++out:
+ mutex_unlock(&sl->master->bus_mutex);
+- dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
+- return -EIO;
++ dev_dbg(&sl->dev, "%s, mutex unlocked, retries: %d\n",
++ (bytes_written > 0) ? "succeeded" : "error", retries);
++ return bytes_written;
+ }
+
+ static BIN_ATTR(output, S_IRUGO | S_IWUSR | S_IWGRP, NULL, output_write, 1);
+++ /dev/null
-From c29c9843fd16b4df1dc21ff7e1243f680f41e2a9 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 18 Jun 2019 11:16:13 +0100
-Subject: [PATCH 673/703] overlays: Fix further maxim,ds1307 references
-
-See: https://github.com/raspberrypi/linux/issues/3013
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/balena-fin-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts | 2 +-
- arch/arm/boot/dts/overlays/tinylcd35-overlay.dts | 2 +-
- 3 files changed, 3 insertions(+), 3 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
-@@ -84,7 +84,7 @@
-
- // rtc clock
- ds1307: ds1307@68 {
-- compatible = "maxim,ds1307";
-+ compatible = "dallas,ds1307";
- reg = <0x68>;
- status = "okay";
- };
---- a/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
-@@ -46,7 +46,7 @@
- status = "okay";
-
- ds1307: ds1307@68 {
-- compatible = "maxim,ds1307";
-+ compatible = "dallas,ds1307";
- reg = <0x68>;
- status = "okay";
- };
---- a/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
-@@ -155,7 +155,7 @@
- status = "okay";
-
- ds1307: ds1307@68 {
-- compatible = "maxim,ds1307";
-+ compatible = "dallas,ds1307";
- reg = <0x68>;
- status = "okay";
- };
--- /dev/null
+From 37dfb88eed2cb32e7c2a704d0d4b590c68175ae1 Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Mon, 20 May 2019 09:05:56 +0200
+Subject: [PATCH 673/725] w1: ds2413: add retry support to state_read()
+
+commit c50d09a86172073f55ebac0b92ad5a75907d64e7 upstream.
+
+The state_read() was calling PIO_ACCESS_READ once and bail out if it
+failed for this first time.
+This commit is improving this to trying more times before it give up,
+similarly as the write call is currently doing.
+
+Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_ds2413.c | 37 +++++++++++++++++++++++------------
+ 1 file changed, 24 insertions(+), 13 deletions(-)
+
+--- a/drivers/w1/slaves/w1_ds2413.c
++++ b/drivers/w1/slaves/w1_ds2413.c
+@@ -30,6 +30,9 @@ static ssize_t state_read(struct file *f
+ size_t count)
+ {
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
++ unsigned int retries = W1_F3A_RETRIES;
++ ssize_t bytes_read = -EIO;
++
+ dev_dbg(&sl->dev,
+ "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
+ bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
+@@ -42,22 +45,30 @@ static ssize_t state_read(struct file *f
+ mutex_lock(&sl->master->bus_mutex);
+ dev_dbg(&sl->dev, "mutex locked");
+
+- if (w1_reset_select_slave(sl)) {
+- mutex_unlock(&sl->master->bus_mutex);
+- return -EIO;
+- }
++ if (w1_reset_select_slave(sl))
++ goto out;
+
+- w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
+- *buf = w1_read_8(sl->master);
++ while (retries--) {
++ w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
+
+- mutex_unlock(&sl->master->bus_mutex);
+- dev_dbg(&sl->dev, "mutex unlocked");
++ *buf = w1_read_8(sl->master);
++ /* check for correct complement */
++ if ((*buf & 0x0F) == ((~*buf >> 4) & 0x0F)) {
++ bytes_read = 1;
++ goto out;
++ }
++
++ if (w1_reset_resume_command(sl->master))
++ goto out; /* unrecoverable error */
+
+- /* check for correct complement */
+- if ((*buf & 0x0F) != ((~*buf >> 4) & 0x0F))
+- return -EIO;
+- else
+- return 1;
++ dev_warn(&sl->dev, "PIO_ACCESS_READ error, retries left: %d\n", retries);
++ }
++
++out:
++ mutex_unlock(&sl->master->bus_mutex);
++ dev_dbg(&sl->dev, "%s, mutex unlocked, retries: %d\n",
++ (bytes_read > 0) ? "succeeded" : "error", retries);
++ return bytes_read;
+ }
+
+ static BIN_ATTR_RO(state, 1);
+++ /dev/null
-From 7ab24b7d5ceb098af03e95c0cd261fa89d077cd3 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 18 Jun 2019 11:19:59 +0100
-Subject: [PATCH 674/703] overlays: Cosmetic change to upstream overlay
-
-The dwc2 overlay no longer uses the dwc2_usb label, and the latest
-ovmerge (which generates the upstream overlay) removes unused labels.
-Update the checked-in version to match.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/upstream-overlay.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
-@@ -113,7 +113,7 @@
- target = <&usb>;
- #address-cells = <1>;
- #size-cells = <1>;
-- dwc2_usb: __overlay__ {
-+ __overlay__ {
- compatible = "brcm,bcm2835-usb";
- dr_mode = "otg";
- g-np-tx-fifo-size = <32>;
--- /dev/null
+From 4dba5d66cc91bf70b6bafd1a14b7db411d588745 Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Wed, 22 May 2019 12:40:53 +0200
+Subject: [PATCH 674/725] w1: ds2413: when the slave is not responding during
+ read, select it again
+
+commit 3856032a0628e6b94badb9131a706dda185e071d upstream.
+
+The protocol is not allowing to obtain a byte of 0xff for PIO_ACCESS_READ
+call. It is very likely that the slave was not addressed properly and
+it is just not respoding (leaving the bus in logic high state) during
+the read of sampled PIO value.
+We cannot just call w1_reset_resume_command() because the problem will
+persist, instead try selecting (addressing) the slave again.
+
+Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_ds2413.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/drivers/w1/slaves/w1_ds2413.c
++++ b/drivers/w1/slaves/w1_ds2413.c
+@@ -24,6 +24,7 @@
+ #define W1_F3A_FUNC_PIO_ACCESS_READ 0xF5
+ #define W1_F3A_FUNC_PIO_ACCESS_WRITE 0x5A
+ #define W1_F3A_SUCCESS_CONFIRM_BYTE 0xAA
++#define W1_F3A_INVALID_PIO_STATE 0xFF
+
+ static ssize_t state_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *buf, loff_t off,
+@@ -45,6 +46,7 @@ static ssize_t state_read(struct file *f
+ mutex_lock(&sl->master->bus_mutex);
+ dev_dbg(&sl->dev, "mutex locked");
+
++next:
+ if (w1_reset_select_slave(sl))
+ goto out;
+
+@@ -52,10 +54,15 @@ static ssize_t state_read(struct file *f
+ w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
+
+ *buf = w1_read_8(sl->master);
+- /* check for correct complement */
+ if ((*buf & 0x0F) == ((~*buf >> 4) & 0x0F)) {
++ /* complement is correct */
+ bytes_read = 1;
+ goto out;
++ } else if (*buf == W1_F3A_INVALID_PIO_STATE) {
++ /* slave didn't respond, try to select it again */
++ dev_warn(&sl->dev, "slave device did not respond to PIO_ACCESS_READ, " \
++ "reselecting, retries left: %d\n", retries);
++ goto next;
+ }
+
+ if (w1_reset_resume_command(sl->master))
--- /dev/null
+From 8604b2fb9843248b9bc792c52393cb05b7a29836 Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Thu, 30 May 2019 09:51:25 +0200
+Subject: [PATCH 675/725] w1: ds2413: fix state byte comparision
+
+commit aacd152ecd7b18af5d2d96dea9e7284c1c93abea upstream.
+
+This commit is fixing a smatch warning:
+drivers/w1/slaves/w1_ds2413.c:61 state_read() warn: impossible condition '(*buf == 255) => ((-128)-127 == 255)'
+by creating additional u8 variable for the bus reading and comparision
+
+Reported-by: kbuild test robot <lkp@intel.com>
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Cc: Dan Carpenter <dan.carpenter@oracle.com>
+Fixes: 3856032a0628 ("w1: ds2413: when the slave is not responding during read, select it again")
+Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_ds2413.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/w1/slaves/w1_ds2413.c
++++ b/drivers/w1/slaves/w1_ds2413.c
+@@ -33,6 +33,7 @@ static ssize_t state_read(struct file *f
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+ unsigned int retries = W1_F3A_RETRIES;
+ ssize_t bytes_read = -EIO;
++ u8 state;
+
+ dev_dbg(&sl->dev,
+ "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
+@@ -53,12 +54,13 @@ next:
+ while (retries--) {
+ w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
+
+- *buf = w1_read_8(sl->master);
+- if ((*buf & 0x0F) == ((~*buf >> 4) & 0x0F)) {
++ state = w1_read_8(sl->master);
++ if ((state & 0x0F) == ((~state >> 4) & 0x0F)) {
+ /* complement is correct */
++ *buf = state;
+ bytes_read = 1;
+ goto out;
+- } else if (*buf == W1_F3A_INVALID_PIO_STATE) {
++ } else if (state == W1_F3A_INVALID_PIO_STATE) {
+ /* slave didn't respond, try to select it again */
+ dev_warn(&sl->dev, "slave device did not respond to PIO_ACCESS_READ, " \
+ "reselecting, retries left: %d\n", retries);
+++ /dev/null
-From 5b1cc85a28180a73cbe56be7913ae03ea9a42d2f Mon Sep 17 00:00:00 2001
-From: Mariusz Bialonczyk <manio@skyboo.net>
-Date: Sat, 25 May 2019 10:45:38 +0200
-Subject: [PATCH 675/703] w1: ds2805: rename w1_family struct, fixing c-p typo
-
-commit 0e3743d870711ae4daf1e7170c8d9381564e244d upstream.
-
-The ds2805 has a structure named: w1_family_2d, which surely
-comes from a w1_ds2431 module. This commit fixes this name to
-prevent confusion and mark a correct family name.
-
-Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/slaves/w1_ds2805.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/drivers/w1/slaves/w1_ds2805.c
-+++ b/drivers/w1/slaves/w1_ds2805.c
-@@ -288,7 +288,7 @@ static struct w1_family_ops w1_f0d_fops
- .remove_slave = w1_f0d_remove_slave,
- };
-
--static struct w1_family w1_family_2d = {
-+static struct w1_family w1_family_0d = {
- .fid = W1_EEPROM_DS2805,
- .fops = &w1_f0d_fops,
- };
-@@ -296,13 +296,13 @@ static struct w1_family w1_family_2d = {
- static int __init w1_f0d_init(void)
- {
- pr_info("%s()\n", __func__);
-- return w1_register_family(&w1_family_2d);
-+ return w1_register_family(&w1_family_0d);
- }
-
- static void __exit w1_f0d_fini(void)
- {
- pr_info("%s()\n", __func__);
-- w1_unregister_family(&w1_family_2d);
-+ w1_unregister_family(&w1_family_0d);
- }
-
- module_init(w1_f0d_init);
--- /dev/null
+From bf56ee503a31864237c40aac90fe338bbca6d5a0 Mon Sep 17 00:00:00 2001
+From: Chris Miller <chris@mesl2.co.uk>
+Date: Wed, 26 Jun 2019 10:40:30 +0100
+Subject: [PATCH 676/725] drm: vc4_dsi: Fix DMA channel and memory leak in vc4
+ (#3012)
+
+Signed-off-by: Chris G Miller <chris@creative-electronics.net>
+---
+ drivers/gpu/drm/vc4/vc4_dsi.c | 35 ++++++++++++++++++++++++-----------
+ 1 file changed, 24 insertions(+), 11 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_dsi.c
++++ b/drivers/gpu/drm/vc4/vc4_dsi.c
+@@ -1536,9 +1536,11 @@ static int vc4_dsi_bind(struct device *d
+ /* 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.
++ * Where possible managed resource providers are used, but the DMA channel
++ * must - if acquired - be explicitly released prior to taking an error exit path.
+ */
+ if (dsi->port == 1) {
+- dsi->reg_dma_mem = dma_alloc_coherent(dev, 4,
++ dsi->reg_dma_mem = dmam_alloc_coherent(dev, 4,
+ &dsi->reg_dma_paddr,
+ GFP_KERNEL);
+ if (!dsi->reg_dma_mem) {
+@@ -1557,6 +1559,8 @@ static int vc4_dsi_bind(struct device *d
+ return ret;
+ }
+
++ /* From here on, any error exits must release the dma channel */
++
+ /* Get the physical address of the device's registers. The
+ * struct resource for the regs gives us the bus address
+ * instead.
+@@ -1583,7 +1587,7 @@ static int vc4_dsi_bind(struct device *d
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Failed to get interrupt: %d\n", ret);
+- return ret;
++ goto rel_dma_exit;
+ }
+
+ dsi->escape_clock = devm_clk_get(dev, "escape");
+@@ -1591,7 +1595,7 @@ static int vc4_dsi_bind(struct device *d
+ ret = PTR_ERR(dsi->escape_clock);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Failed to get escape clock: %d\n", ret);
+- return ret;
++ goto rel_dma_exit;
+ }
+
+ dsi->pll_phy_clock = devm_clk_get(dev, "phy");
+@@ -1599,7 +1603,7 @@ static int vc4_dsi_bind(struct device *d
+ ret = PTR_ERR(dsi->pll_phy_clock);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Failed to get phy clock: %d\n", ret);
+- return ret;
++ goto rel_dma_exit;
+ }
+
+ dsi->pixel_clock = devm_clk_get(dev, "pixel");
+@@ -1607,7 +1611,7 @@ static int vc4_dsi_bind(struct device *d
+ ret = PTR_ERR(dsi->pixel_clock);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Failed to get pixel clock: %d\n", ret);
+- return ret;
++ goto rel_dma_exit;
+ }
+
+ ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
+@@ -1622,26 +1626,28 @@ static int vc4_dsi_bind(struct device *d
+ if (ret == -ENODEV)
+ return 0;
+
+- return ret;
++ goto rel_dma_exit;
+ }
+
+ if (panel) {
+ dsi->bridge = devm_drm_panel_bridge_add(dev, panel,
+ DRM_MODE_CONNECTOR_DSI);
+- if (IS_ERR(dsi->bridge))
+- return PTR_ERR(dsi->bridge);
++ if (IS_ERR(dsi->bridge)){
++ ret = PTR_ERR(dsi->bridge);
++ goto rel_dma_exit;
++ }
+ }
+
+ /* 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;
++ goto rel_dma_exit;
+ }
+
+ ret = vc4_dsi_init_phy_clocks(dsi);
+ if (ret)
+- return ret;
++ goto rel_dma_exit;
+
+ if (dsi->port == 1)
+ vc4->dsi1 = dsi;
+@@ -1653,7 +1659,7 @@ static int vc4_dsi_bind(struct device *d
+ ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL);
+ if (ret) {
+ dev_err(dev, "bridge attach failed: %d\n", ret);
+- return ret;
++ goto rel_dma_exit;
+ }
+ /* Disable the atomic helper calls into the bridge. We
+ * manually call the bridge pre_enable / enable / etc. calls
+@@ -1665,6 +1671,11 @@ static int vc4_dsi_bind(struct device *d
+ pm_runtime_enable(dev);
+
+ return 0;
++
++rel_dma_exit:
++ dma_release_channel(dsi->reg_dma_chan);
++
++ return ret;
+ }
+
+ static void vc4_dsi_unbind(struct device *dev, struct device *master,
+@@ -1679,6 +1690,8 @@ static void vc4_dsi_unbind(struct device
+
+ vc4_dsi_encoder_destroy(dsi->encoder);
+
++ dma_release_channel(dsi->reg_dma_chan);
++
+ if (dsi->port == 1)
+ vc4->dsi1 = NULL;
+ }
+++ /dev/null
-From b6d4c7b839620c8d955b1887ed71c3911df90684 Mon Sep 17 00:00:00 2001
-From: Mariusz Bialonczyk <manio@skyboo.net>
-Date: Mon, 20 May 2019 09:05:55 +0200
-Subject: [PATCH 676/703] w1: ds2413: output_write() cosmetic fixes / simplify
-
-commit ae2ee27aa985232f66421d7cd1c7f4b87c7dba7d upstream.
-
-Make the output_write simpler.
-Based on Jean-Francois Dagenais code from:
-49695ac46861 ("w1: ds2408: reset on output_write retry with readback")
-
-Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/slaves/w1_ds2413.c | 19 +++++++++++--------
- 1 file changed, 11 insertions(+), 8 deletions(-)
-
---- a/drivers/w1/slaves/w1_ds2413.c
-+++ b/drivers/w1/slaves/w1_ds2413.c
-@@ -69,6 +69,7 @@ static ssize_t output_write(struct file
- struct w1_slave *sl = kobj_to_w1_slave(kobj);
- u8 w1_buf[3];
- unsigned int retries = W1_F3A_RETRIES;
-+ ssize_t bytes_written = -EIO;
-
- if (count != 1 || off != 0)
- return -EFAULT;
-@@ -78,7 +79,7 @@ static ssize_t output_write(struct file
- dev_dbg(&sl->dev, "mutex locked");
-
- if (w1_reset_select_slave(sl))
-- goto error;
-+ goto out;
-
- /* according to the DS2413 datasheet the most significant 6 bits
- should be set to "1"s, so do it now */
-@@ -91,18 +92,20 @@ static ssize_t output_write(struct file
- w1_write_block(sl->master, w1_buf, 3);
-
- if (w1_read_8(sl->master) == W1_F3A_SUCCESS_CONFIRM_BYTE) {
-- mutex_unlock(&sl->master->bus_mutex);
-- dev_dbg(&sl->dev, "mutex unlocked, retries:%d", retries);
-- return 1;
-+ bytes_written = 1;
-+ goto out;
- }
- if (w1_reset_resume_command(sl->master))
-- goto error;
-+ goto out; /* unrecoverable error */
-+
-+ dev_warn(&sl->dev, "PIO_ACCESS_WRITE error, retries left: %d\n", retries);
- }
-
--error:
-+out:
- mutex_unlock(&sl->master->bus_mutex);
-- dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
-- return -EIO;
-+ dev_dbg(&sl->dev, "%s, mutex unlocked, retries: %d\n",
-+ (bytes_written > 0) ? "succeeded" : "error", retries);
-+ return bytes_written;
- }
-
- static BIN_ATTR(output, S_IRUGO | S_IWUSR | S_IWGRP, NULL, output_write, 1);
--- /dev/null
+From 8f0ceec888aaa21d703dc9b16bca77d57104b7cf Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 19 Jun 2019 03:55:50 +0100
+Subject: [PATCH 677/725] video/bcm2708_fb: Revert cma allocation attempt
+
+"4600e91 Pulled in the multi frame buffer support from the Pi3 repo"
+pulled back in the code for allocating the framebuffer from the CMA
+heap.
+Revert it again.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/video/fbdev/bcm2708_fb.c | 101 +++------------------
+ include/soc/bcm2835/raspberrypi-firmware.h | 1 -
+ 2 files changed, 13 insertions(+), 89 deletions(-)
+
+--- a/drivers/video/fbdev/bcm2708_fb.c
++++ b/drivers/video/fbdev/bcm2708_fb.c
+@@ -112,9 +112,6 @@ struct bcm2708_fb {
+ struct vc4_display_settings_t display_settings;
+ struct debugfs_regset32 screeninfo_regset;
+ struct bcm2708_fb_dev *fbdev;
+- unsigned int image_size;
+- dma_addr_t dma_addr;
+- void *cpuaddr;
+ };
+
+ #define MAX_FRAMEBUFFERS 3
+@@ -377,12 +374,12 @@ static int bcm2708_fb_set_par(struct fb_
+ .xoffset = info->var.xoffset,
+ .yoffset = info->var.yoffset,
+ .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
+- /* base and screen_size will be initialised later */
+- .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
+- /* pitch will be initialised later */
++ .base = 0,
++ .screen_size = 0,
++ .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
++ .pitch = 0,
+ };
+- int ret, image_size;
+-
++ int ret;
+
+ print_debug("%s(%p) %dx%d (%dx%d), %d, %d (display %d)\n", __func__,
+ info,
+@@ -397,76 +394,12 @@ static int bcm2708_fb_set_par(struct fb_
+ */
+ set_display_num(fb);
+
+- /* Try allocating our own buffer. We can specify all the parameters */
+- image_size = ((info->var.xres * info->var.yres) *
+- info->var.bits_per_pixel) >> 3;
+-
+- if (!fb->fbdev->disable_arm_alloc &&
+- (image_size != fb->image_size || !fb->dma_addr)) {
+- if (fb->dma_addr) {
+- dma_free_coherent(info->device, fb->image_size,
+- fb->cpuaddr, fb->dma_addr);
+- fb->image_size = 0;
+- fb->cpuaddr = NULL;
+- fb->dma_addr = 0;
+- }
+-
+- fb->cpuaddr = dma_alloc_coherent(info->device, image_size,
+- &fb->dma_addr, GFP_KERNEL);
+-
+- if (!fb->cpuaddr) {
+- fb->dma_addr = 0;
+- fb->fbdev->disable_arm_alloc = true;
+- } else {
+- fb->image_size = image_size;
+- }
+- }
+-
+- if (fb->cpuaddr) {
+- fbinfo.base = fb->dma_addr;
+- fbinfo.screen_size = image_size;
+- fbinfo.pitch = (info->var.xres * info->var.bits_per_pixel) >> 3;
+-
+- ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
+- sizeof(fbinfo));
+- if (ret || fbinfo.base != fb->dma_addr) {
+- /* Firmware either failed, or assigned a different base
+- * address (ie it doesn't support being passed an FB
+- * allocation).
+- * Destroy the allocation, and don't try again.
+- */
+- dma_free_coherent(info->device, fb->image_size,
+- fb->cpuaddr, fb->dma_addr);
+- fb->image_size = 0;
+- fb->cpuaddr = NULL;
+- fb->dma_addr = 0;
+- fb->fbdev->disable_arm_alloc = true;
+- }
+- } else {
+- /* Our allocation failed - drop into the old scheme of
+- * allocation by the VPU.
+- */
+- ret = -ENOMEM;
+- }
+-
++ ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
++ sizeof(fbinfo));
+ if (ret) {
+- /* Old scheme:
+- * - FRAMEBUFFER_ALLOCATE passes 0 for base and screen_size.
+- * - GET_PITCH instead of SET_PITCH.
+- */
+- fbinfo.base = 0;
+- fbinfo.screen_size = 0;
+- fbinfo.tag6.tag = RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH;
+- fbinfo.pitch = 0;
+-
+- ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
+- sizeof(fbinfo));
+- if (ret) {
+- dev_err(info->device,
+- "Failed to allocate GPU framebuffer (%d)\n",
+- ret);
+- return ret;
+- }
++ dev_err(info->device,
++ "Failed to allocate GPU framebuffer (%d)\n", ret);
++ return ret;
+ }
+
+ if (info->var.bits_per_pixel <= 8)
+@@ -481,17 +414,9 @@ static int bcm2708_fb_set_par(struct fb_
+ fb->fb.fix.smem_start = fbinfo.base;
+ fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual;
+ fb->fb.screen_size = fbinfo.screen_size;
+-
+- if (!fb->dma_addr) {
+- if (fb->fb.screen_base)
+- iounmap(fb->fb.screen_base);
+-
+- fb->fb.screen_base = ioremap_wc(fbinfo.base,
+- fb->fb.screen_size);
+- } else {
+- fb->fb.screen_base = fb->cpuaddr;
+- }
+-
++ if (fb->fb.screen_base)
++ iounmap(fb->fb.screen_base);
++ fb->fb.screen_base = ioremap_wc(fbinfo.base, fb->fb.screen_size);
+ if (!fb->fb.screen_base) {
+ /* the console may currently be locked */
+ console_trylock();
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -138,7 +138,6 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
+- RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH = 0x00048008,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
+++ /dev/null
-From f88a22ce466ccac98bf4aa1c38d36b0e0bb52adb Mon Sep 17 00:00:00 2001
-From: Mariusz Bialonczyk <manio@skyboo.net>
-Date: Mon, 20 May 2019 09:05:56 +0200
-Subject: [PATCH 677/703] w1: ds2413: add retry support to state_read()
-
-commit c50d09a86172073f55ebac0b92ad5a75907d64e7 upstream.
-
-The state_read() was calling PIO_ACCESS_READ once and bail out if it
-failed for this first time.
-This commit is improving this to trying more times before it give up,
-similarly as the write call is currently doing.
-
-Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/slaves/w1_ds2413.c | 37 +++++++++++++++++++++++------------
- 1 file changed, 24 insertions(+), 13 deletions(-)
-
---- a/drivers/w1/slaves/w1_ds2413.c
-+++ b/drivers/w1/slaves/w1_ds2413.c
-@@ -30,6 +30,9 @@ static ssize_t state_read(struct file *f
- size_t count)
- {
- struct w1_slave *sl = kobj_to_w1_slave(kobj);
-+ unsigned int retries = W1_F3A_RETRIES;
-+ ssize_t bytes_read = -EIO;
-+
- dev_dbg(&sl->dev,
- "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
- bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
-@@ -42,22 +45,30 @@ static ssize_t state_read(struct file *f
- mutex_lock(&sl->master->bus_mutex);
- dev_dbg(&sl->dev, "mutex locked");
-
-- if (w1_reset_select_slave(sl)) {
-- mutex_unlock(&sl->master->bus_mutex);
-- return -EIO;
-- }
-+ if (w1_reset_select_slave(sl))
-+ goto out;
-
-- w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
-- *buf = w1_read_8(sl->master);
-+ while (retries--) {
-+ w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
-
-- mutex_unlock(&sl->master->bus_mutex);
-- dev_dbg(&sl->dev, "mutex unlocked");
-+ *buf = w1_read_8(sl->master);
-+ /* check for correct complement */
-+ if ((*buf & 0x0F) == ((~*buf >> 4) & 0x0F)) {
-+ bytes_read = 1;
-+ goto out;
-+ }
-+
-+ if (w1_reset_resume_command(sl->master))
-+ goto out; /* unrecoverable error */
-
-- /* check for correct complement */
-- if ((*buf & 0x0F) != ((~*buf >> 4) & 0x0F))
-- return -EIO;
-- else
-- return 1;
-+ dev_warn(&sl->dev, "PIO_ACCESS_READ error, retries left: %d\n", retries);
-+ }
-+
-+out:
-+ mutex_unlock(&sl->master->bus_mutex);
-+ dev_dbg(&sl->dev, "%s, mutex unlocked, retries: %d\n",
-+ (bytes_read > 0) ? "succeeded" : "error", retries);
-+ return bytes_read;
- }
-
- static BIN_ATTR_RO(state, 1);
--- /dev/null
+From a79005b13c374c78f6d96f5ab2cd12377357d82f Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Jun 2019 02:29:40 +0100
+Subject: [PATCH 678/725] drm/vc4: Add support for color encoding on YUV planes
+
+Adds signalling for BT601/709/2020, and limited/full range
+(on BT601).
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 32 +++++++++++++++++++++++++-
+ drivers/gpu/drm/vc4/vc_image_types.h | 28 ++++++++++++++++++++++
+ 2 files changed, 59 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -66,7 +66,7 @@ struct set_plane {
+ u8 alpha;
+ u8 num_planes;
+ u8 is_vu;
+- u8 padding;
++ u8 color_encoding;
+
+ u32 planes[4]; /* DMA address of each plane */
+
+@@ -454,6 +454,28 @@ static void vc4_plane_atomic_update(stru
+ if (num_planes == 3 &&
+ (fb->offsets[2] - fb->offsets[1]) == fb->pitches[1])
+ mb->plane.vc_image_type = VC_IMAGE_YUV420_S;
++
++ switch (state->color_encoding) {
++ default:
++ case DRM_COLOR_YCBCR_BT601:
++ if (state->color_range == DRM_COLOR_YCBCR_LIMITED_RANGE)
++ mb->plane.color_encoding =
++ VC_IMAGE_YUVINFO_CSC_ITUR_BT601;
++ else
++ mb->plane.color_encoding =
++ VC_IMAGE_YUVINFO_CSC_JPEG_JFIF;
++ break;
++ case DRM_COLOR_YCBCR_BT709:
++ /* Currently no support for a full range BT709 */
++ mb->plane.color_encoding =
++ VC_IMAGE_YUVINFO_CSC_ITUR_BT709;
++ break;
++ case DRM_COLOR_YCBCR_BT2020:
++ /* Currently no support for a full range BT2020 */
++ mb->plane.color_encoding =
++ VC_IMAGE_YUVINFO_CSC_REC_2020;
++ break;
++ }
+ } else {
+ mb->plane.planes[1] = 0;
+ mb->plane.planes[2] = 0;
+@@ -643,6 +665,14 @@ static struct drm_plane *vc4_fkms_plane_
+ drm_plane_create_alpha_property(plane);
+ drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
+ SUPPORTED_ROTATIONS);
++ drm_plane_create_color_properties(plane,
++ BIT(DRM_COLOR_YCBCR_BT601) |
++ BIT(DRM_COLOR_YCBCR_BT709) |
++ BIT(DRM_COLOR_YCBCR_BT2020),
++ BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
++ BIT(DRM_COLOR_YCBCR_FULL_RANGE),
++ DRM_COLOR_YCBCR_BT709,
++ DRM_COLOR_YCBCR_LIMITED_RANGE);
+
+ /*
+ * Default frame buffer setup is with FB on -127, and raspistill etc
+--- a/drivers/gpu/drm/vc4/vc_image_types.h
++++ b/drivers/gpu/drm/vc4/vc_image_types.h
+@@ -4,6 +4,8 @@
+ *
+ * Values taken from vc_image_types.h released by Broadcom at
+ * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h
++ * and vc_image_structs.h at
++ * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_structs.h
+ *
+ * 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
+@@ -141,3 +143,29 @@ enum {
+ VC_IMAGE_MAX, /* bounds for error checking */
+ VC_IMAGE_FORCE_ENUM_16BIT = 0xffff,
+ };
++
++enum {
++ /* Unknown or unset - defaults to BT601 interstitial */
++ VC_IMAGE_YUVINFO_UNSPECIFIED = 0,
++
++ /* colour-space conversions data [4 bits] */
++
++ /* ITU-R BT.601-5 [SDTV] (compatible with VideoCore-II) */
++ VC_IMAGE_YUVINFO_CSC_ITUR_BT601 = 1,
++ /* ITU-R BT.709-3 [HDTV] */
++ VC_IMAGE_YUVINFO_CSC_ITUR_BT709 = 2,
++ /* JPEG JFIF */
++ VC_IMAGE_YUVINFO_CSC_JPEG_JFIF = 3,
++ /* Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
++ VC_IMAGE_YUVINFO_CSC_FCC = 4,
++ /* Society of Motion Picture and Television Engineers 240M (1999) */
++ VC_IMAGE_YUVINFO_CSC_SMPTE_240M = 5,
++ /* ITU-R BT.470-2 System M */
++ VC_IMAGE_YUVINFO_CSC_ITUR_BT470_2_M = 6,
++ /* ITU-R BT.470-2 System B,G */
++ VC_IMAGE_YUVINFO_CSC_ITUR_BT470_2_BG = 7,
++ /* JPEG JFIF, but with 16..255 luma */
++ VC_IMAGE_YUVINFO_CSC_JPEG_JFIF_Y16_255 = 8,
++ /* Rec 2020 */
++ VC_IMAGE_YUVINFO_CSC_REC_2020 = 9,
++};
+++ /dev/null
-From 1808665b2b2e06d6f14762eb0ab82d65e3af3e2b Mon Sep 17 00:00:00 2001
-From: Mariusz Bialonczyk <manio@skyboo.net>
-Date: Wed, 22 May 2019 12:40:53 +0200
-Subject: [PATCH 678/703] w1: ds2413: when the slave is not responding during
- read, select it again
-
-commit 3856032a0628e6b94badb9131a706dda185e071d upstream.
-
-The protocol is not allowing to obtain a byte of 0xff for PIO_ACCESS_READ
-call. It is very likely that the slave was not addressed properly and
-it is just not respoding (leaving the bus in logic high state) during
-the read of sampled PIO value.
-We cannot just call w1_reset_resume_command() because the problem will
-persist, instead try selecting (addressing) the slave again.
-
-Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/slaves/w1_ds2413.c | 9 ++++++++-
- 1 file changed, 8 insertions(+), 1 deletion(-)
-
---- a/drivers/w1/slaves/w1_ds2413.c
-+++ b/drivers/w1/slaves/w1_ds2413.c
-@@ -24,6 +24,7 @@
- #define W1_F3A_FUNC_PIO_ACCESS_READ 0xF5
- #define W1_F3A_FUNC_PIO_ACCESS_WRITE 0x5A
- #define W1_F3A_SUCCESS_CONFIRM_BYTE 0xAA
-+#define W1_F3A_INVALID_PIO_STATE 0xFF
-
- static ssize_t state_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf, loff_t off,
-@@ -45,6 +46,7 @@ static ssize_t state_read(struct file *f
- mutex_lock(&sl->master->bus_mutex);
- dev_dbg(&sl->dev, "mutex locked");
-
-+next:
- if (w1_reset_select_slave(sl))
- goto out;
-
-@@ -52,10 +54,15 @@ static ssize_t state_read(struct file *f
- w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
-
- *buf = w1_read_8(sl->master);
-- /* check for correct complement */
- if ((*buf & 0x0F) == ((~*buf >> 4) & 0x0F)) {
-+ /* complement is correct */
- bytes_read = 1;
- goto out;
-+ } else if (*buf == W1_F3A_INVALID_PIO_STATE) {
-+ /* slave didn't respond, try to select it again */
-+ dev_warn(&sl->dev, "slave device did not respond to PIO_ACCESS_READ, " \
-+ "reselecting, retries left: %d\n", retries);
-+ goto next;
- }
-
- if (w1_reset_resume_command(sl->master))
--- /dev/null
+From 4798e87ece1dbf90c42f4def09401ee4c051e003 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 28 Jun 2019 16:05:25 +0100
+Subject: [PATCH 679/725] configs: Drop V4L2 camera and codec drivers from
+ bcmrpi3_defconfig
+
+They rely on mmal_vchiq, which in turn wants vc-sm-cma.
+vc-sm-cma needs some attention for 64 bit, so drop it for now.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm64/configs/bcmrpi3_defconfig | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -1086,8 +1086,6 @@ CONFIG_FB_TFT_WATTEROTT=m
+ CONFIG_FB_FLEX=m
+ CONFIG_FB_TFT_FBTFT_DEVICE=m
+ CONFIG_SND_BCM2835=m
+-CONFIG_VIDEO_BCM2835=m
+-CONFIG_VIDEO_CODEC_BCM2835=m
+ CONFIG_MAILBOX=y
+ CONFIG_BCM2835_MBOX=y
+ # CONFIG_IOMMU_SUPPORT is not set
+++ /dev/null
-From 7a5972e019d1f4cef5ea50b9077b43f097b23084 Mon Sep 17 00:00:00 2001
-From: Mariusz Bialonczyk <manio@skyboo.net>
-Date: Thu, 30 May 2019 09:51:25 +0200
-Subject: [PATCH 679/703] w1: ds2413: fix state byte comparision
-
-commit aacd152ecd7b18af5d2d96dea9e7284c1c93abea upstream.
-
-This commit is fixing a smatch warning:
-drivers/w1/slaves/w1_ds2413.c:61 state_read() warn: impossible condition '(*buf == 255) => ((-128)-127 == 255)'
-by creating additional u8 variable for the bus reading and comparision
-
-Reported-by: kbuild test robot <lkp@intel.com>
-Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
-Cc: Dan Carpenter <dan.carpenter@oracle.com>
-Fixes: 3856032a0628 ("w1: ds2413: when the slave is not responding during read, select it again")
-Signed-off-by: Mariusz Bialonczyk <manio@skyboo.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/w1/slaves/w1_ds2413.c | 8 +++++---
- 1 file changed, 5 insertions(+), 3 deletions(-)
-
---- a/drivers/w1/slaves/w1_ds2413.c
-+++ b/drivers/w1/slaves/w1_ds2413.c
-@@ -33,6 +33,7 @@ static ssize_t state_read(struct file *f
- struct w1_slave *sl = kobj_to_w1_slave(kobj);
- unsigned int retries = W1_F3A_RETRIES;
- ssize_t bytes_read = -EIO;
-+ u8 state;
-
- dev_dbg(&sl->dev,
- "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
-@@ -53,12 +54,13 @@ next:
- while (retries--) {
- w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ);
-
-- *buf = w1_read_8(sl->master);
-- if ((*buf & 0x0F) == ((~*buf >> 4) & 0x0F)) {
-+ state = w1_read_8(sl->master);
-+ if ((state & 0x0F) == ((~state >> 4) & 0x0F)) {
- /* complement is correct */
-+ *buf = state;
- bytes_read = 1;
- goto out;
-- } else if (*buf == W1_F3A_INVALID_PIO_STATE) {
-+ } else if (state == W1_F3A_INVALID_PIO_STATE) {
- /* slave didn't respond, try to select it again */
- dev_warn(&sl->dev, "slave device did not respond to PIO_ACCESS_READ, " \
- "reselecting, retries left: %d\n", retries);
--- /dev/null
+From 6dadf48ceed847ed814d9fa3ab3cf902c4ce6e25 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 28 Jun 2019 22:44:09 +0100
+Subject: [PATCH 680/725] configs: arm64/bcm2711: Remove CONFIG_VIDEO_BCM2835
+
+Undefine CONFIG_VIDEO_BCM2835 until it builds for arm64.
+
+See: https://github.com/raspberrypi/linux/issues/3024
+See: https://github.com/raspberrypi/linux/pull/3030
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/configs/bcm2709_defconfig | 2 +-
+ arch/arm64/configs/bcm2711_defconfig | 2 --
+ 2 files changed, 1 insertion(+), 3 deletions(-)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -16,11 +16,11 @@ CONFIG_IKCONFIG=m
+ CONFIG_IKCONFIG_PROC=y
+ CONFIG_MEMCG=y
+ CONFIG_BLK_CGROUP=y
++CONFIG_CGROUP_PIDS=y
+ CONFIG_CGROUP_FREEZER=y
+ CONFIG_CPUSETS=y
+ CONFIG_CGROUP_DEVICE=y
+ CONFIG_CGROUP_CPUACCT=y
+-CONFIG_CGROUP_PIDS=y
+ CONFIG_NAMESPACES=y
+ CONFIG_USER_NS=y
+ CONFIG_SCHED_AUTOGROUP=y
+--- a/arch/arm64/configs/bcm2711_defconfig
++++ b/arch/arm64/configs/bcm2711_defconfig
+@@ -1031,7 +1031,6 @@ CONFIG_USB_G_HID=m
+ CONFIG_USB_G_WEBCAM=m
+ CONFIG_MMC=y
+ CONFIG_MMC_BLOCK_MINORS=32
+-CONFIG_MMC_SDHCI_BCM2711=y
+ CONFIG_MMC_BCM2835_MMC=y
+ CONFIG_MMC_BCM2835_DMA=y
+ CONFIG_MMC_BCM2835_SDHOST=y
+@@ -1130,7 +1129,6 @@ CONFIG_FB_TFT_WATTEROTT=m
+ CONFIG_FB_FLEX=m
+ CONFIG_FB_TFT_FBTFT_DEVICE=m
+ CONFIG_SND_BCM2835=m
+-CONFIG_VIDEO_BCM2835=m
+ CONFIG_MAILBOX=y
+ CONFIG_BCM2835_MBOX=y
+ # CONFIG_IOMMU_SUPPORT is not set
+++ /dev/null
-From 47ac9aac7067b0415ed2ffe7251a5bfc05114b41 Mon Sep 17 00:00:00 2001
-From: Chris Miller <chris@mesl2.co.uk>
-Date: Wed, 26 Jun 2019 10:40:30 +0100
-Subject: [PATCH 680/703] drm: vc4_dsi: Fix DMA channel and memory leak in vc4
- (#3012)
-
-Signed-off-by: Chris G Miller <chris@creative-electronics.net>
----
- drivers/gpu/drm/vc4/vc4_dsi.c | 35 ++++++++++++++++++++++++-----------
- 1 file changed, 24 insertions(+), 11 deletions(-)
-
---- a/drivers/gpu/drm/vc4/vc4_dsi.c
-+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
-@@ -1536,9 +1536,11 @@ static int vc4_dsi_bind(struct device *d
- /* 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.
-+ * Where possible managed resource providers are used, but the DMA channel
-+ * must - if acquired - be explicitly released prior to taking an error exit path.
- */
- if (dsi->port == 1) {
-- dsi->reg_dma_mem = dma_alloc_coherent(dev, 4,
-+ dsi->reg_dma_mem = dmam_alloc_coherent(dev, 4,
- &dsi->reg_dma_paddr,
- GFP_KERNEL);
- if (!dsi->reg_dma_mem) {
-@@ -1557,6 +1559,8 @@ static int vc4_dsi_bind(struct device *d
- return ret;
- }
-
-+ /* From here on, any error exits must release the dma channel */
-+
- /* Get the physical address of the device's registers. The
- * struct resource for the regs gives us the bus address
- * instead.
-@@ -1583,7 +1587,7 @@ static int vc4_dsi_bind(struct device *d
- if (ret) {
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "Failed to get interrupt: %d\n", ret);
-- return ret;
-+ goto rel_dma_exit;
- }
-
- dsi->escape_clock = devm_clk_get(dev, "escape");
-@@ -1591,7 +1595,7 @@ static int vc4_dsi_bind(struct device *d
- ret = PTR_ERR(dsi->escape_clock);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "Failed to get escape clock: %d\n", ret);
-- return ret;
-+ goto rel_dma_exit;
- }
-
- dsi->pll_phy_clock = devm_clk_get(dev, "phy");
-@@ -1599,7 +1603,7 @@ static int vc4_dsi_bind(struct device *d
- ret = PTR_ERR(dsi->pll_phy_clock);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "Failed to get phy clock: %d\n", ret);
-- return ret;
-+ goto rel_dma_exit;
- }
-
- dsi->pixel_clock = devm_clk_get(dev, "pixel");
-@@ -1607,7 +1611,7 @@ static int vc4_dsi_bind(struct device *d
- ret = PTR_ERR(dsi->pixel_clock);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "Failed to get pixel clock: %d\n", ret);
-- return ret;
-+ goto rel_dma_exit;
- }
-
- ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
-@@ -1622,26 +1626,28 @@ static int vc4_dsi_bind(struct device *d
- if (ret == -ENODEV)
- return 0;
-
-- return ret;
-+ goto rel_dma_exit;
- }
-
- if (panel) {
- dsi->bridge = devm_drm_panel_bridge_add(dev, panel,
- DRM_MODE_CONNECTOR_DSI);
-- if (IS_ERR(dsi->bridge))
-- return PTR_ERR(dsi->bridge);
-+ if (IS_ERR(dsi->bridge)){
-+ ret = PTR_ERR(dsi->bridge);
-+ goto rel_dma_exit;
-+ }
- }
-
- /* 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;
-+ goto rel_dma_exit;
- }
-
- ret = vc4_dsi_init_phy_clocks(dsi);
- if (ret)
-- return ret;
-+ goto rel_dma_exit;
-
- if (dsi->port == 1)
- vc4->dsi1 = dsi;
-@@ -1653,7 +1659,7 @@ static int vc4_dsi_bind(struct device *d
- ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL);
- if (ret) {
- dev_err(dev, "bridge attach failed: %d\n", ret);
-- return ret;
-+ goto rel_dma_exit;
- }
- /* Disable the atomic helper calls into the bridge. We
- * manually call the bridge pre_enable / enable / etc. calls
-@@ -1665,6 +1671,11 @@ static int vc4_dsi_bind(struct device *d
- pm_runtime_enable(dev);
-
- return 0;
-+
-+rel_dma_exit:
-+ dma_release_channel(dsi->reg_dma_chan);
-+
-+ return ret;
- }
-
- static void vc4_dsi_unbind(struct device *dev, struct device *master,
-@@ -1679,6 +1690,8 @@ static void vc4_dsi_unbind(struct device
-
- vc4_dsi_encoder_destroy(dsi->encoder);
-
-+ dma_release_channel(dsi->reg_dma_chan);
-+
- if (dsi->port == 1)
- vc4->dsi1 = NULL;
- }
--- /dev/null
+From 626e81656bc5a27656180d8faf6173e9bcd7e512 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 2 Jul 2019 17:13:05 +0100
+Subject: [PATCH 681/725] arm: dts: Add coherent_pool=1M to Pi 4 bootargs
+
+Downstream Raspberry Pi dts files add "coherent_pool=1M" to the kernel
+command line to aid the dwc_otg driver, but this excluded Pi 4 which
+uses a new XCHI interface instead. UAS also benefits from a larger
+coherent_pool value, so replicate the addition in bcm2711-rpi-4-b.dts.
+
+See: https://github.com/raspberrypi/linux/pull/3040
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -14,7 +14,7 @@
+ };
+
+ chosen {
+- bootargs = "8250.nr_uarts=1 cma=64M";
++ bootargs = "coherent_pool=1M 8250.nr_uarts=1 cma=64M";
+ };
+
+ aliases {
+++ /dev/null
-From d14f0987d0a03c122f6a713df8969109a6213333 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Wed, 19 Jun 2019 03:55:50 +0100
-Subject: [PATCH 681/703] video/bcm2708_fb: Revert cma allocation attempt
-
-"4600e91 Pulled in the multi frame buffer support from the Pi3 repo"
-pulled back in the code for allocating the framebuffer from the CMA
-heap.
-Revert it again.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/video/fbdev/bcm2708_fb.c | 101 +++------------------
- include/soc/bcm2835/raspberrypi-firmware.h | 1 -
- 2 files changed, 13 insertions(+), 89 deletions(-)
-
---- a/drivers/video/fbdev/bcm2708_fb.c
-+++ b/drivers/video/fbdev/bcm2708_fb.c
-@@ -112,9 +112,6 @@ struct bcm2708_fb {
- struct vc4_display_settings_t display_settings;
- struct debugfs_regset32 screeninfo_regset;
- struct bcm2708_fb_dev *fbdev;
-- unsigned int image_size;
-- dma_addr_t dma_addr;
-- void *cpuaddr;
- };
-
- #define MAX_FRAMEBUFFERS 3
-@@ -377,12 +374,12 @@ static int bcm2708_fb_set_par(struct fb_
- .xoffset = info->var.xoffset,
- .yoffset = info->var.yoffset,
- .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
-- /* base and screen_size will be initialised later */
-- .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
-- /* pitch will be initialised later */
-+ .base = 0,
-+ .screen_size = 0,
-+ .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
-+ .pitch = 0,
- };
-- int ret, image_size;
--
-+ int ret;
-
- print_debug("%s(%p) %dx%d (%dx%d), %d, %d (display %d)\n", __func__,
- info,
-@@ -397,76 +394,12 @@ static int bcm2708_fb_set_par(struct fb_
- */
- set_display_num(fb);
-
-- /* Try allocating our own buffer. We can specify all the parameters */
-- image_size = ((info->var.xres * info->var.yres) *
-- info->var.bits_per_pixel) >> 3;
--
-- if (!fb->fbdev->disable_arm_alloc &&
-- (image_size != fb->image_size || !fb->dma_addr)) {
-- if (fb->dma_addr) {
-- dma_free_coherent(info->device, fb->image_size,
-- fb->cpuaddr, fb->dma_addr);
-- fb->image_size = 0;
-- fb->cpuaddr = NULL;
-- fb->dma_addr = 0;
-- }
--
-- fb->cpuaddr = dma_alloc_coherent(info->device, image_size,
-- &fb->dma_addr, GFP_KERNEL);
--
-- if (!fb->cpuaddr) {
-- fb->dma_addr = 0;
-- fb->fbdev->disable_arm_alloc = true;
-- } else {
-- fb->image_size = image_size;
-- }
-- }
--
-- if (fb->cpuaddr) {
-- fbinfo.base = fb->dma_addr;
-- fbinfo.screen_size = image_size;
-- fbinfo.pitch = (info->var.xres * info->var.bits_per_pixel) >> 3;
--
-- ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
-- sizeof(fbinfo));
-- if (ret || fbinfo.base != fb->dma_addr) {
-- /* Firmware either failed, or assigned a different base
-- * address (ie it doesn't support being passed an FB
-- * allocation).
-- * Destroy the allocation, and don't try again.
-- */
-- dma_free_coherent(info->device, fb->image_size,
-- fb->cpuaddr, fb->dma_addr);
-- fb->image_size = 0;
-- fb->cpuaddr = NULL;
-- fb->dma_addr = 0;
-- fb->fbdev->disable_arm_alloc = true;
-- }
-- } else {
-- /* Our allocation failed - drop into the old scheme of
-- * allocation by the VPU.
-- */
-- ret = -ENOMEM;
-- }
--
-+ ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
-+ sizeof(fbinfo));
- if (ret) {
-- /* Old scheme:
-- * - FRAMEBUFFER_ALLOCATE passes 0 for base and screen_size.
-- * - GET_PITCH instead of SET_PITCH.
-- */
-- fbinfo.base = 0;
-- fbinfo.screen_size = 0;
-- fbinfo.tag6.tag = RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH;
-- fbinfo.pitch = 0;
--
-- ret = rpi_firmware_property_list(fb->fbdev->fw, &fbinfo,
-- sizeof(fbinfo));
-- if (ret) {
-- dev_err(info->device,
-- "Failed to allocate GPU framebuffer (%d)\n",
-- ret);
-- return ret;
-- }
-+ dev_err(info->device,
-+ "Failed to allocate GPU framebuffer (%d)\n", ret);
-+ return ret;
- }
-
- if (info->var.bits_per_pixel <= 8)
-@@ -481,17 +414,9 @@ static int bcm2708_fb_set_par(struct fb_
- fb->fb.fix.smem_start = fbinfo.base;
- fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual;
- fb->fb.screen_size = fbinfo.screen_size;
--
-- if (!fb->dma_addr) {
-- if (fb->fb.screen_base)
-- iounmap(fb->fb.screen_base);
--
-- fb->fb.screen_base = ioremap_wc(fbinfo.base,
-- fb->fb.screen_size);
-- } else {
-- fb->fb.screen_base = fb->cpuaddr;
-- }
--
-+ if (fb->fb.screen_base)
-+ iounmap(fb->fb.screen_base);
-+ fb->fb.screen_base = ioremap_wc(fbinfo.base, fb->fb.screen_size);
- if (!fb->fb.screen_base) {
- /* the console may currently be locked */
- console_trylock();
---- a/include/soc/bcm2835/raspberrypi-firmware.h
-+++ b/include/soc/bcm2835/raspberrypi-firmware.h
-@@ -138,7 +138,6 @@ enum rpi_firmware_property_tag {
- RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
- RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
- RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
-- RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH = 0x00048008,
- RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
- RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
- RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
--- /dev/null
+From d7e89477b16559fc407ad5cc001244346aa8f733 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 2 Jul 2019 21:25:59 +0100
+Subject: [PATCH 682/725] configs: Enable USB_CONFIGFS=m in bcmrpi_defconfig
+
+See: https://github.com/raspberrypi/linux/issues/3042
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -1150,6 +1150,7 @@ CONFIG_USB_CXACRU=m
+ CONFIG_USB_UEAGLEATM=m
+ CONFIG_USB_XUSBATM=m
+ CONFIG_USB_GADGET=m
++CONFIG_USB_CONFIGFS=m
+ CONFIG_USB_ZERO=m
+ CONFIG_USB_AUDIO=m
+ CONFIG_USB_ETH=m
+++ /dev/null
-From 5edffe06ee9b72d3fb56853d0652dd9cdc02e44d Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 24 Jun 2019 02:29:40 +0100
-Subject: [PATCH 682/703] drm/vc4: Add support for color encoding on YUV planes
-
-Adds signalling for BT601/709/2020, and limited/full range
-(on BT601).
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 32 +++++++++++++++++++++++++-
- drivers/gpu/drm/vc4/vc_image_types.h | 28 ++++++++++++++++++++++
- 2 files changed, 59 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
-@@ -66,7 +66,7 @@ struct set_plane {
- u8 alpha;
- u8 num_planes;
- u8 is_vu;
-- u8 padding;
-+ u8 color_encoding;
-
- u32 planes[4]; /* DMA address of each plane */
-
-@@ -454,6 +454,28 @@ static void vc4_plane_atomic_update(stru
- if (num_planes == 3 &&
- (fb->offsets[2] - fb->offsets[1]) == fb->pitches[1])
- mb->plane.vc_image_type = VC_IMAGE_YUV420_S;
-+
-+ switch (state->color_encoding) {
-+ default:
-+ case DRM_COLOR_YCBCR_BT601:
-+ if (state->color_range == DRM_COLOR_YCBCR_LIMITED_RANGE)
-+ mb->plane.color_encoding =
-+ VC_IMAGE_YUVINFO_CSC_ITUR_BT601;
-+ else
-+ mb->plane.color_encoding =
-+ VC_IMAGE_YUVINFO_CSC_JPEG_JFIF;
-+ break;
-+ case DRM_COLOR_YCBCR_BT709:
-+ /* Currently no support for a full range BT709 */
-+ mb->plane.color_encoding =
-+ VC_IMAGE_YUVINFO_CSC_ITUR_BT709;
-+ break;
-+ case DRM_COLOR_YCBCR_BT2020:
-+ /* Currently no support for a full range BT2020 */
-+ mb->plane.color_encoding =
-+ VC_IMAGE_YUVINFO_CSC_REC_2020;
-+ break;
-+ }
- } else {
- mb->plane.planes[1] = 0;
- mb->plane.planes[2] = 0;
-@@ -643,6 +665,14 @@ static struct drm_plane *vc4_fkms_plane_
- drm_plane_create_alpha_property(plane);
- drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
- SUPPORTED_ROTATIONS);
-+ drm_plane_create_color_properties(plane,
-+ BIT(DRM_COLOR_YCBCR_BT601) |
-+ BIT(DRM_COLOR_YCBCR_BT709) |
-+ BIT(DRM_COLOR_YCBCR_BT2020),
-+ BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
-+ BIT(DRM_COLOR_YCBCR_FULL_RANGE),
-+ DRM_COLOR_YCBCR_BT709,
-+ DRM_COLOR_YCBCR_LIMITED_RANGE);
-
- /*
- * Default frame buffer setup is with FB on -127, and raspistill etc
---- a/drivers/gpu/drm/vc4/vc_image_types.h
-+++ b/drivers/gpu/drm/vc4/vc_image_types.h
-@@ -4,6 +4,8 @@
- *
- * Values taken from vc_image_types.h released by Broadcom at
- * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h
-+ * and vc_image_structs.h at
-+ * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_structs.h
- *
- * 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
-@@ -141,3 +143,29 @@ enum {
- VC_IMAGE_MAX, /* bounds for error checking */
- VC_IMAGE_FORCE_ENUM_16BIT = 0xffff,
- };
-+
-+enum {
-+ /* Unknown or unset - defaults to BT601 interstitial */
-+ VC_IMAGE_YUVINFO_UNSPECIFIED = 0,
-+
-+ /* colour-space conversions data [4 bits] */
-+
-+ /* ITU-R BT.601-5 [SDTV] (compatible with VideoCore-II) */
-+ VC_IMAGE_YUVINFO_CSC_ITUR_BT601 = 1,
-+ /* ITU-R BT.709-3 [HDTV] */
-+ VC_IMAGE_YUVINFO_CSC_ITUR_BT709 = 2,
-+ /* JPEG JFIF */
-+ VC_IMAGE_YUVINFO_CSC_JPEG_JFIF = 3,
-+ /* Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
-+ VC_IMAGE_YUVINFO_CSC_FCC = 4,
-+ /* Society of Motion Picture and Television Engineers 240M (1999) */
-+ VC_IMAGE_YUVINFO_CSC_SMPTE_240M = 5,
-+ /* ITU-R BT.470-2 System M */
-+ VC_IMAGE_YUVINFO_CSC_ITUR_BT470_2_M = 6,
-+ /* ITU-R BT.470-2 System B,G */
-+ VC_IMAGE_YUVINFO_CSC_ITUR_BT470_2_BG = 7,
-+ /* JPEG JFIF, but with 16..255 luma */
-+ VC_IMAGE_YUVINFO_CSC_JPEG_JFIF_Y16_255 = 8,
-+ /* Rec 2020 */
-+ VC_IMAGE_YUVINFO_CSC_REC_2020 = 9,
-+};
--- /dev/null
+From 8320deccc7df04c3a094f4c8361b3afc0f85215c Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 2 Jul 2019 21:43:13 +0100
+Subject: [PATCH 683/725] configs: And all the other USB_CONFIGFS options
+
+And all Rabbit's friends-and-relations.
+
+See: https://github.com/raspberrypi/linux/issues/3042
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/configs/bcmrpi_defconfig | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -1151,6 +1151,23 @@ CONFIG_USB_UEAGLEATM=m
+ CONFIG_USB_XUSBATM=m
+ CONFIG_USB_GADGET=m
+ CONFIG_USB_CONFIGFS=m
++CONFIG_USB_CONFIGFS_SERIAL=y
++CONFIG_USB_CONFIGFS_ACM=y
++CONFIG_USB_CONFIGFS_OBEX=y
++CONFIG_USB_CONFIGFS_NCM=y
++CONFIG_USB_CONFIGFS_ECM=y
++CONFIG_USB_CONFIGFS_ECM_SUBSET=y
++CONFIG_USB_CONFIGFS_RNDIS=y
++CONFIG_USB_CONFIGFS_EEM=y
++CONFIG_USB_CONFIGFS_MASS_STORAGE=y
++CONFIG_USB_CONFIGFS_F_LB_SS=y
++CONFIG_USB_CONFIGFS_F_FS=y
++CONFIG_USB_CONFIGFS_F_UAC1=y
++CONFIG_USB_CONFIGFS_F_UAC2=y
++CONFIG_USB_CONFIGFS_F_MIDI=y
++CONFIG_USB_CONFIGFS_F_HID=y
++CONFIG_USB_CONFIGFS_F_UVC=y
++CONFIG_USB_CONFIGFS_F_PRINTER=y
+ CONFIG_USB_ZERO=m
+ CONFIG_USB_AUDIO=m
+ CONFIG_USB_ETH=m
+++ /dev/null
-From 3467b4cfdf72b5b6f4c5a493be9c3d632aa72211 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 28 Jun 2019 16:05:25 +0100
-Subject: [PATCH 683/703] configs: Drop V4L2 camera and codec drivers from
- bcmrpi3_defconfig
-
-They rely on mmal_vchiq, which in turn wants vc-sm-cma.
-vc-sm-cma needs some attention for 64 bit, so drop it for now.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm64/configs/bcmrpi3_defconfig | 2 --
- 1 file changed, 2 deletions(-)
-
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -1086,8 +1086,6 @@ CONFIG_FB_TFT_WATTEROTT=m
- CONFIG_FB_FLEX=m
- CONFIG_FB_TFT_FBTFT_DEVICE=m
- CONFIG_SND_BCM2835=m
--CONFIG_VIDEO_BCM2835=m
--CONFIG_VIDEO_CODEC_BCM2835=m
- CONFIG_MAILBOX=y
- CONFIG_BCM2835_MBOX=y
- # CONFIG_IOMMU_SUPPORT is not set
--- /dev/null
+From ccf319da9985453198ecbc34e7ea490584cc9398 Mon Sep 17 00:00:00 2001
+From: Andrei Gherzan <andrei@gherzan.ro>
+Date: Wed, 3 Jul 2019 13:53:29 +0100
+Subject: [PATCH 684/725] configs: arm64/bcm2711: Add MMC_SDHCI_IPROC
+
+This driver is used in the device tree for the emmc2 node.
+
+See #3032
+
+Signed-off-by: Andrei Gherzan <andrei@gherzan.ro>
+---
+ arch/arm64/configs/bcm2711_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm64/configs/bcm2711_defconfig
++++ b/arch/arm64/configs/bcm2711_defconfig
+@@ -1036,6 +1036,7 @@ CONFIG_MMC_BCM2835_DMA=y
+ CONFIG_MMC_BCM2835_SDHOST=y
+ CONFIG_MMC_SDHCI=y
+ CONFIG_MMC_SDHCI_PLTFM=y
++CONFIG_MMC_SDHCI_IPROC=y
+ CONFIG_MMC_SPI=m
+ CONFIG_LEDS_CLASS=y
+ CONFIG_LEDS_GPIO=y
+++ /dev/null
-From 548a9808b61de74ad57e904d4952bfbfaabf89a7 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 28 Jun 2019 22:44:09 +0100
-Subject: [PATCH 684/703] configs: arm64/bcm2711: Remove CONFIG_VIDEO_BCM2835
-
-Undefine CONFIG_VIDEO_BCM2835 until it builds for arm64.
-
-See: https://github.com/raspberrypi/linux/issues/3024
-See: https://github.com/raspberrypi/linux/pull/3030
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/configs/bcm2709_defconfig | 2 +-
- arch/arm64/configs/bcm2711_defconfig | 2 --
- 2 files changed, 1 insertion(+), 3 deletions(-)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -16,11 +16,11 @@ CONFIG_IKCONFIG=m
- CONFIG_IKCONFIG_PROC=y
- CONFIG_MEMCG=y
- CONFIG_BLK_CGROUP=y
-+CONFIG_CGROUP_PIDS=y
- CONFIG_CGROUP_FREEZER=y
- CONFIG_CPUSETS=y
- CONFIG_CGROUP_DEVICE=y
- CONFIG_CGROUP_CPUACCT=y
--CONFIG_CGROUP_PIDS=y
- CONFIG_NAMESPACES=y
- CONFIG_USER_NS=y
- CONFIG_SCHED_AUTOGROUP=y
---- a/arch/arm64/configs/bcm2711_defconfig
-+++ b/arch/arm64/configs/bcm2711_defconfig
-@@ -1031,7 +1031,6 @@ CONFIG_USB_G_HID=m
- CONFIG_USB_G_WEBCAM=m
- CONFIG_MMC=y
- CONFIG_MMC_BLOCK_MINORS=32
--CONFIG_MMC_SDHCI_BCM2711=y
- CONFIG_MMC_BCM2835_MMC=y
- CONFIG_MMC_BCM2835_DMA=y
- CONFIG_MMC_BCM2835_SDHOST=y
-@@ -1130,7 +1129,6 @@ CONFIG_FB_TFT_WATTEROTT=m
- CONFIG_FB_FLEX=m
- CONFIG_FB_TFT_FBTFT_DEVICE=m
- CONFIG_SND_BCM2835=m
--CONFIG_VIDEO_BCM2835=m
- CONFIG_MAILBOX=y
- CONFIG_BCM2835_MBOX=y
- # CONFIG_IOMMU_SUPPORT is not set
+++ /dev/null
-From bce3d83c8d1b9e2cab6001f079287ca79912a2fa Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 2 Jul 2019 17:13:05 +0100
-Subject: [PATCH 685/703] arm: dts: Add coherent_pool=1M to Pi 4 bootargs
-
-Downstream Raspberry Pi dts files add "coherent_pool=1M" to the kernel
-command line to aid the dwc_otg driver, but this excluded Pi 4 which
-uses a new XCHI interface instead. UAS also benefits from a larger
-coherent_pool value, so replicate the addition in bcm2711-rpi-4-b.dts.
-
-See: https://github.com/raspberrypi/linux/pull/3040
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
-@@ -14,7 +14,7 @@
- };
-
- chosen {
-- bootargs = "8250.nr_uarts=1 cma=64M";
-+ bootargs = "coherent_pool=1M 8250.nr_uarts=1 cma=64M";
- };
-
- aliases {
--- /dev/null
+From ccf4542628ee44ac6acf62361a531ac9479b7872 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 3 Jul 2019 20:37:14 +0100
+Subject: [PATCH 685/725] overlays: Correct gpio-fan gpio flags for 4.19
+
+The gpio-fan overlay was submitted for the 4.14 kernel where the second
+value in the Device Tree gpios declaration was ignored (thanks to an
+old-style driver), allowing the fan-control output to be active-high
+even though the declaration appears to request it be active-low.
+The gpio-fan driver in 4.19 uses GPIO descriptors and honours the
+active-low flag that the overlay (accidentally?) supplies.
+
+Change/correct the flags field to mark the GPIO as active-high.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/gpio-fan-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts
+@@ -45,7 +45,7 @@
+ __overlay__ {
+ fan0: gpio-fan@0 {
+ compatible = "gpio-fan";
+- gpios = <&gpio 12 1>;
++ gpios = <&gpio 12 0>;
+ gpio-fan,speed-map = <0 0>,
+ <5000 1>;
+ #cooling-cells = <2>;
+++ /dev/null
-From 31ddd6caf3ac6c77b6b2e30acc2551c8597a969b Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 2 Jul 2019 21:25:59 +0100
-Subject: [PATCH 686/703] configs: Enable USB_CONFIGFS=m in bcmrpi_defconfig
-
-See: https://github.com/raspberrypi/linux/issues/3042
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/configs/bcmrpi_defconfig | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -1150,6 +1150,7 @@ CONFIG_USB_CXACRU=m
- CONFIG_USB_UEAGLEATM=m
- CONFIG_USB_XUSBATM=m
- CONFIG_USB_GADGET=m
-+CONFIG_USB_CONFIGFS=m
- CONFIG_USB_ZERO=m
- CONFIG_USB_AUDIO=m
- CONFIG_USB_ETH=m
--- /dev/null
+From ced45257bef9255fda33051f882c83623d9e0699 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 25 Jun 2019 00:29:44 +0100
+Subject: [PATCH 686/725] staging: vcsm-cma: Remove cache manipulation ioctl
+ from ARM64
+
+The cache flushing ioctls are used by the Pi3 HEVC hw-assisted
+decoder as it needs finer grained flushing control than dma_ops
+allow.
+These cache calls are not present for ARM64, therefore disable
+them. We are not actively supporting 64bit kernels at present,
+and the use case of the HEVC decoder is fairly limited.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -1259,6 +1259,7 @@ error:
+ return ret;
+ }
+
++#ifndef CONFIG_ARM64
+ /* Converts VCSM_CACHE_OP_* to an operating function. */
+ static void (*cache_op_to_func(const unsigned int cache_op))
+ (const void*, const void*)
+@@ -1351,6 +1352,7 @@ out:
+
+ return ret;
+ }
++#endif
+
+ static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+@@ -1448,6 +1450,7 @@ static long vc_sm_cma_ioctl(struct file
+ break;
+ }
+
++#ifndef CONFIG_ARM64
+ /*
+ * Flush/Invalidate the cache for a given mapping.
+ * Blocks must be pinned (i.e. accessed) before this call.
+@@ -1455,6 +1458,7 @@ static long vc_sm_cma_ioctl(struct file
+ case VC_SM_CMA_CMD_CLEAN_INVALID2:
+ ret = vc_sm_cma_clean_invalid2(cmdnr, arg);
+ break;
++#endif
+
+ default:
+ pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
+@@ -1467,6 +1471,7 @@ static long vc_sm_cma_ioctl(struct file
+ return ret;
+ }
+
++#ifndef CONFIG_ARM64
+ #ifdef CONFIG_COMPAT
+ struct vc_sm_cma_ioctl_clean_invalid2_32 {
+ u32 op_count;
+@@ -1496,14 +1501,17 @@ static long vc_sm_cma_compat_ioctl(struc
+ }
+ }
+ #endif
++#endif
+
+ /* Device operations that we managed in this driver. */
+ static const struct file_operations vc_sm_ops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = vc_sm_cma_ioctl,
++#ifndef CONFIG_ARM64
+ #ifdef CONFIG_COMPAT
+ .compat_ioctl = vc_sm_cma_compat_ioctl,
+ #endif
++#endif
+ .open = vc_sm_cma_open,
+ .release = vc_sm_cma_release,
+ };
+++ /dev/null
-From 04958bf394a778098ead8eedb27c51c44f58ef21 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 2 Jul 2019 21:43:13 +0100
-Subject: [PATCH 687/703] configs: And all the other USB_CONFIGFS options
-
-And all Rabbit's friends-and-relations.
-
-See: https://github.com/raspberrypi/linux/issues/3042
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/configs/bcmrpi_defconfig | 17 +++++++++++++++++
- 1 file changed, 17 insertions(+)
-
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -1151,6 +1151,23 @@ CONFIG_USB_UEAGLEATM=m
- CONFIG_USB_XUSBATM=m
- CONFIG_USB_GADGET=m
- CONFIG_USB_CONFIGFS=m
-+CONFIG_USB_CONFIGFS_SERIAL=y
-+CONFIG_USB_CONFIGFS_ACM=y
-+CONFIG_USB_CONFIGFS_OBEX=y
-+CONFIG_USB_CONFIGFS_NCM=y
-+CONFIG_USB_CONFIGFS_ECM=y
-+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
-+CONFIG_USB_CONFIGFS_RNDIS=y
-+CONFIG_USB_CONFIGFS_EEM=y
-+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
-+CONFIG_USB_CONFIGFS_F_LB_SS=y
-+CONFIG_USB_CONFIGFS_F_FS=y
-+CONFIG_USB_CONFIGFS_F_UAC1=y
-+CONFIG_USB_CONFIGFS_F_UAC2=y
-+CONFIG_USB_CONFIGFS_F_MIDI=y
-+CONFIG_USB_CONFIGFS_F_HID=y
-+CONFIG_USB_CONFIGFS_F_UVC=y
-+CONFIG_USB_CONFIGFS_F_PRINTER=y
- CONFIG_USB_ZERO=m
- CONFIG_USB_AUDIO=m
- CONFIG_USB_ETH=m
--- /dev/null
+From 03d574236ca07cd6ffec88a8124426e5e42722e1 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 1 Jul 2019 11:57:25 +0100
+Subject: [PATCH 687/725] staging: vcsm-cma: Rework to use dma APIs, not CMA
+
+Due to a misunderstanding of the DMA mapping APIs, I made
+the wrong decision on how to implement this.
+
+Rework to use dma_alloc_coherent instead of the CMA
+API. This also allows it to be built as a module easily.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vc-sm-cma/Kconfig | 4 +-
+ .../staging/vc04_services/vc-sm-cma/Makefile | 2 +-
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c | 291 ++++++++++--------
+ .../staging/vc04_services/vc-sm-cma/vc_sm.h | 13 +-
+ .../vc04_services/vc-sm-cma/vc_sm_cma.c | 98 ------
+ .../vc04_services/vc-sm-cma/vc_sm_cma.h | 39 ---
+ 6 files changed, 168 insertions(+), 279 deletions(-)
+ delete mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
+ delete mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/Kconfig
++++ b/drivers/staging/vc04_services/vc-sm-cma/Kconfig
+@@ -1,6 +1,6 @@
+ config BCM_VC_SM_CMA
+- bool "VideoCore Shared Memory (CMA) driver"
+- depends on BCM2835_VCHIQ && DMA_CMA
++ tristate "VideoCore Shared Memory (CMA) driver"
++ depends on BCM2835_VCHIQ
+ select RBTREE
+ select DMA_SHARED_BUFFER
+ help
+--- a/drivers/staging/vc04_services/vc-sm-cma/Makefile
++++ b/drivers/staging/vc04_services/vc-sm-cma/Makefile
+@@ -3,6 +3,6 @@ ccflags-y += -Idrivers/staging/vc04_serv
+ ccflags-y += -D__VCCOREVER__=0
+
+ vc-sm-cma-$(CONFIG_BCM_VC_SM_CMA) := \
+- vc_sm.o vc_sm_cma_vchi.o vc_sm_cma.o
++ vc_sm.o vc_sm_cma_vchi.o
+
+ obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma.o
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -6,8 +6,8 @@
+ * Dave Stevenson <dave.stevenson@raspberrypi.org>
+ *
+ * Based on vmcs_sm driver from Broadcom Corporation for some API,
+- * and taking some code for CMA/dmabuf handling from the Android Ion
+- * driver (Google/Linaro).
++ * and taking some code for buffer allocation and dmabuf handling from
++ * videobuf2.
+ *
+ *
+ * This driver has 3 main uses:
+@@ -52,7 +52,6 @@
+ #include "vc_sm_cma_vchi.h"
+
+ #include "vc_sm.h"
+-#include "vc_sm_cma.h"
+ #include "vc_sm_knl.h"
+ #include <linux/broadcom/vc_sm_cma_ioctl.h>
+
+@@ -89,7 +88,6 @@ struct sm_state_t {
+ struct miscdevice misc_dev;
+
+ struct sm_instance *sm_handle; /* Handle for videocore service. */
+- struct cma *cma_heap;
+
+ spinlock_t kernelid_map_lock; /* Spinlock protecting kernelid_map */
+ struct idr kernelid_map;
+@@ -110,8 +108,9 @@ struct sm_state_t {
+
+ struct vc_sm_dma_buf_attachment {
+ struct device *dev;
+- struct sg_table *table;
++ struct sg_table sg_table;
+ struct list_head list;
++ enum dma_data_direction dma_dir;
+ };
+
+ /* ---- Private Variables ----------------------------------------------- */
+@@ -202,9 +201,10 @@ static int vc_sm_cma_global_state_show(s
+ resource->import.attach);
+ seq_printf(s, " SGT %p\n",
+ resource->import.sgt);
++ } else {
++ seq_printf(s, " SGT %p\n",
++ resource->alloc.sg_table);
+ }
+- seq_printf(s, " SG_TABLE %p\n",
+- resource->sg_table);
+ seq_printf(s, " DMA_ADDR %pad\n",
+ &resource->dma_addr);
+ seq_printf(s, " VC_HANDLE %08x\n",
+@@ -296,8 +296,9 @@ static void vc_sm_vpu_free(struct vc_sm_
+ */
+ static void vc_sm_release_resource(struct vc_sm_buffer *buffer)
+ {
+- pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
+- __func__, buffer, buffer->name, buffer->size);
++ pr_debug("[%s]: buffer %p (name %s, size %zu), imported %u\n",
++ __func__, buffer, buffer->name, buffer->size,
++ buffer->imported);
+
+ if (buffer->vc_handle) {
+ /* We've sent the unmap request but not had the response. */
+@@ -313,8 +314,6 @@ static void vc_sm_release_resource(struc
+
+ /* Release the allocation (whether imported dmabuf or CMA allocation) */
+ if (buffer->imported) {
+- pr_debug("%s: Release imported dmabuf %p\n", __func__,
+- buffer->import.dma_buf);
+ if (buffer->import.dma_buf)
+ dma_buf_put(buffer->import.dma_buf);
+ else
+@@ -322,16 +321,8 @@ static void vc_sm_release_resource(struc
+ __func__, buffer);
+ buffer->import.dma_buf = NULL;
+ } else {
+- if (buffer->sg_table) {
+- /* Our own allocation that we need to dma_unmap_sg */
+- dma_unmap_sg(&sm_state->pdev->dev,
+- buffer->sg_table->sgl,
+- buffer->sg_table->nents,
+- DMA_BIDIRECTIONAL);
+- }
+- pr_debug("%s: Release our allocation\n", __func__);
+- vc_sm_cma_buffer_free(&buffer->alloc);
+- pr_debug("%s: Release our allocation - done\n", __func__);
++ dma_free_coherent(&sm_state->pdev->dev, buffer->size,
++ buffer->cookie, buffer->dma_addr);
+ }
+
+
+@@ -371,38 +362,6 @@ static struct vc_sm_privdata_t *vc_sm_cm
+ return file_data;
+ }
+
+-static struct sg_table *dup_sg_table(struct sg_table *table)
+-{
+- struct sg_table *new_table;
+- int ret, i;
+- struct scatterlist *sg, *new_sg;
+-
+- new_table = kzalloc(sizeof(*new_table), GFP_KERNEL);
+- if (!new_table)
+- return ERR_PTR(-ENOMEM);
+-
+- ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL);
+- if (ret) {
+- kfree(new_table);
+- return ERR_PTR(ret);
+- }
+-
+- new_sg = new_table->sgl;
+- for_each_sg(table->sgl, sg, table->nents, i) {
+- memcpy(new_sg, sg, sizeof(*sg));
+- sg->dma_address = 0;
+- new_sg = sg_next(new_sg);
+- }
+-
+- return new_table;
+-}
+-
+-static void free_duped_table(struct sg_table *table)
+-{
+- sg_free_table(table);
+- kfree(table);
+-}
+-
+ /* Dma buf operations for use with our own allocations */
+
+ static int vc_sm_dma_buf_attach(struct dma_buf *dmabuf,
+@@ -410,28 +369,45 @@ static int vc_sm_dma_buf_attach(struct d
+
+ {
+ struct vc_sm_dma_buf_attachment *a;
+- struct sg_table *table;
++ struct sg_table *sgt;
+ struct vc_sm_buffer *buf = dmabuf->priv;
++ struct scatterlist *rd, *wr;
++ int ret, i;
+
+ a = kzalloc(sizeof(*a), GFP_KERNEL);
+ if (!a)
+ return -ENOMEM;
+
+- table = dup_sg_table(buf->sg_table);
+- if (IS_ERR(table)) {
++ pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
++
++ mutex_lock(&buf->lock);
++
++ INIT_LIST_HEAD(&a->list);
++
++ sgt = &a->sg_table;
++
++ /* Copy the buf->base_sgt scatter list to the attachment, as we can't
++ * map the same scatter list to multiple attachments at the same time.
++ */
++ ret = sg_alloc_table(sgt, buf->alloc.sg_table->orig_nents, GFP_KERNEL);
++ if (ret) {
+ kfree(a);
+- return PTR_ERR(table);
++ return -ENOMEM;
+ }
+
+- a->table = table;
+- INIT_LIST_HEAD(&a->list);
++ rd = buf->alloc.sg_table->sgl;
++ wr = sgt->sgl;
++ for (i = 0; i < sgt->orig_nents; ++i) {
++ sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
++ rd = sg_next(rd);
++ wr = sg_next(wr);
++ }
+
++ a->dma_dir = DMA_NONE;
+ attachment->priv = a;
+
+- mutex_lock(&buf->lock);
+ list_add(&a->list, &buf->attachments);
+ mutex_unlock(&buf->lock);
+- pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
+
+ return 0;
+ }
+@@ -441,9 +417,20 @@ static void vc_sm_dma_buf_detach(struct
+ {
+ struct vc_sm_dma_buf_attachment *a = attachment->priv;
+ struct vc_sm_buffer *buf = dmabuf->priv;
++ struct sg_table *sgt;
+
+ pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
+- free_duped_table(a->table);
++ if (!a)
++ return;
++
++ sgt = &a->sg_table;
++
++ /* release the scatterlist cache */
++ if (a->dma_dir != DMA_NONE)
++ dma_unmap_sg(attachment->dev, sgt->sgl, sgt->orig_nents,
++ a->dma_dir);
++ sg_free_table(sgt);
++
+ mutex_lock(&buf->lock);
+ list_del(&a->list);
+ mutex_unlock(&buf->lock);
+@@ -455,13 +442,38 @@ static struct sg_table *vc_sm_map_dma_bu
+ enum dma_data_direction direction)
+ {
+ struct vc_sm_dma_buf_attachment *a = attachment->priv;
++ /* stealing dmabuf mutex to serialize map/unmap operations */
++ struct mutex *lock = &attachment->dmabuf->lock;
+ struct sg_table *table;
+
+- table = a->table;
++ mutex_lock(lock);
++ pr_debug("%s attachment %p\n", __func__, attachment);
++ table = &a->sg_table;
++
++ /* return previously mapped sg table */
++ if (a->dma_dir == direction) {
++ mutex_unlock(lock);
++ return table;
++ }
++
++ /* release any previous cache */
++ if (a->dma_dir != DMA_NONE) {
++ dma_unmap_sg(attachment->dev, table->sgl, table->orig_nents,
++ a->dma_dir);
++ a->dma_dir = DMA_NONE;
++ }
++
++ /* mapping to the client with new direction */
++ table->nents = dma_map_sg(attachment->dev, table->sgl,
++ table->orig_nents, direction);
++ if (!table->nents) {
++ pr_err("failed to map scatterlist\n");
++ mutex_unlock(lock);
++ return ERR_PTR(-EIO);
++ }
+
+- if (!dma_map_sg(attachment->dev, table->sgl, table->nents,
+- direction))
+- return ERR_PTR(-ENOMEM);
++ a->dma_dir = direction;
++ mutex_unlock(lock);
+
+ pr_debug("%s attachment %p\n", __func__, attachment);
+ return table;
+@@ -478,41 +490,26 @@ static void vc_sm_unmap_dma_buf(struct d
+ static int vc_sm_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
+ {
+ struct vc_sm_buffer *buf = dmabuf->priv;
+- struct sg_table *table = buf->sg_table;
+- unsigned long addr = vma->vm_start;
+- unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
+- struct scatterlist *sg;
+- int i;
+- int ret = 0;
++ int ret;
+
+ pr_debug("%s dmabuf %p, buf %p, vm_start %08lX\n", __func__, dmabuf,
+- buf, addr);
++ buf, vma->vm_start);
+
+ mutex_lock(&buf->lock);
+
+ /* now map it to userspace */
+- for_each_sg(table->sgl, sg, table->nents, i) {
+- struct page *page = sg_page(sg);
+- unsigned long remainder = vma->vm_end - addr;
+- unsigned long len = sg->length;
++ vma->vm_pgoff = 0;
+
+- if (offset >= sg->length) {
+- offset -= sg->length;
+- continue;
+- } else if (offset) {
+- page += offset / PAGE_SIZE;
+- len = sg->length - offset;
+- offset = 0;
+- }
+- len = min(len, remainder);
+- ret = remap_pfn_range(vma, addr, page_to_pfn(page), len,
+- vma->vm_page_prot);
+- if (ret)
+- break;
+- addr += len;
+- if (addr >= vma->vm_end)
+- break;
++ ret = dma_mmap_coherent(&sm_state->pdev->dev, vma, buf->cookie,
++ buf->dma_addr, buf->size);
++
++ if (ret) {
++ pr_err("Remapping memory failed, error: %d\n", ret);
++ return ret;
+ }
++
++ vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
++
+ mutex_unlock(&buf->lock);
+
+ if (ret)
+@@ -570,8 +567,8 @@ static int vc_sm_dma_buf_begin_cpu_acces
+ mutex_lock(&buf->lock);
+
+ list_for_each_entry(a, &buf->attachments, list) {
+- dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents,
+- direction);
++ dma_sync_sg_for_cpu(a->dev, a->sg_table.sgl,
++ a->sg_table.nents, direction);
+ }
+ mutex_unlock(&buf->lock);
+
+@@ -593,8 +590,8 @@ static int vc_sm_dma_buf_end_cpu_access(
+ mutex_lock(&buf->lock);
+
+ list_for_each_entry(a, &buf->attachments, list) {
+- dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents,
+- direction);
++ dma_sync_sg_for_device(a->dev, a->sg_table.sgl,
++ a->sg_table.nents, direction);
+ }
+ mutex_unlock(&buf->lock);
+
+@@ -625,7 +622,9 @@ static const struct dma_buf_ops dma_buf_
+ .map = vc_sm_dma_buf_kmap,
+ .unmap = vc_sm_dma_buf_kunmap,
+ };
++
+ /* Dma_buf operations for chaining through to an imported dma_buf */
++
+ static
+ int vc_sm_import_dma_buf_attach(struct dma_buf *dmabuf,
+ struct dma_buf_attachment *attachment)
+@@ -819,7 +818,7 @@ vc_sm_cma_import_dmabuf_internal(struct
+
+ import.type = VC_SM_ALLOC_NON_CACHED;
+ dma_addr = sg_dma_address(sgt->sgl);
+- import.addr = (uint32_t)dma_addr;
++ import.addr = (u32)dma_addr;
+ if ((import.addr & 0xC0000000) != 0xC0000000) {
+ pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
+ __func__, &dma_addr);
+@@ -911,11 +910,12 @@ error:
+ return ret;
+ }
+
+-static int vc_sm_cma_vpu_alloc(u32 size, uint32_t align, const char *name,
++static int vc_sm_cma_vpu_alloc(u32 size, u32 align, const char *name,
+ u32 mem_handle, struct vc_sm_buffer **ret_buffer)
+ {
+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+ struct vc_sm_buffer *buffer = NULL;
++ struct sg_table *sgt;
+ int aligned_size;
+ int ret = 0;
+
+@@ -938,23 +938,34 @@ static int vc_sm_cma_vpu_alloc(u32 size,
+ */
+ mutex_lock(&buffer->lock);
+
+- if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
+- aligned_size)) {
+- pr_err("[%s]: cma alloc of %d bytes failed\n",
++ buffer->cookie = dma_alloc_coherent(&sm_state->pdev->dev,
++ aligned_size, &buffer->dma_addr,
++ GFP_KERNEL);
++ if (!buffer->cookie) {
++ pr_err("[%s]: dma_alloc_coherent alloc of %d bytes failed\n",
+ __func__, aligned_size);
+ ret = -ENOMEM;
+ goto error;
+ }
+- buffer->sg_table = buffer->alloc.sg_table;
+
+- pr_debug("[%s]: cma alloc of %d bytes success\n",
++ pr_debug("[%s]: alloc of %d bytes success\n",
+ __func__, aligned_size);
+
+- if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
+- buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
+- pr_err("[%s]: dma_map_sg failed\n", __func__);
++ sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
++ if (!sgt) {
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ ret = dma_get_sgtable(&sm_state->pdev->dev, sgt, buffer->cookie,
++ buffer->dma_addr, buffer->size);
++ if (ret < 0) {
++ pr_err("failed to get scatterlist from DMA API\n");
++ kfree(sgt);
++ ret = -ENOMEM;
+ goto error;
+ }
++ buffer->alloc.sg_table = sgt;
+
+ INIT_LIST_HEAD(&buffer->attachments);
+
+@@ -971,10 +982,10 @@ static int vc_sm_cma_vpu_alloc(u32 size,
+ ret = PTR_ERR(buffer->dma_buf);
+ goto error;
+ }
+- buffer->dma_addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
++ buffer->dma_addr = (u32)sg_dma_address(buffer->alloc.sg_table->sgl);
+ if ((buffer->dma_addr & 0xC0000000) != 0xC0000000) {
+- pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
+- __func__, &buffer->dma_addr);
++ pr_warn_once("%s: Expecting an uncached alias for dma_addr %pad\n",
++ __func__, &buffer->dma_addr);
+ buffer->dma_addr |= 0xC0000000;
+ }
+ buffer->private = sm_state->vpu_allocs;
+@@ -1145,6 +1156,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+ struct vc_sm_import import = { 0 };
+ struct vc_sm_import_result result = { 0 };
+ struct dma_buf *dmabuf = NULL;
++ struct sg_table *sgt;
+ int aligned_size;
+ int ret = 0;
+ int status;
+@@ -1162,18 +1174,13 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+ goto error;
+ }
+
+- if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
+- aligned_size)) {
+- pr_err("[%s]: cma alloc of %d bytes failed\n",
++ buffer->cookie = dma_alloc_coherent(&sm_state->pdev->dev,
++ aligned_size,
++ &buffer->dma_addr,
++ GFP_KERNEL);
++ if (!buffer->cookie) {
++ pr_err("[%s]: dma_alloc_coherent alloc of %d bytes failed\n",
+ __func__, aligned_size);
+- kfree(buffer);
+- return -ENOMEM;
+- }
+- buffer->sg_table = buffer->alloc.sg_table;
+-
+- if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
+- buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
+- pr_err("[%s]: dma_map_sg failed\n", __func__);
+ ret = -ENOMEM;
+ goto error;
+ }
+@@ -1204,7 +1211,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+ }
+ buffer->dma_buf = dmabuf;
+
+- import.addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
++ import.addr = buffer->dma_addr;
+ import.size = aligned_size;
+ import.kernel_id = get_kernel_id(buffer);
+
+@@ -1229,10 +1236,25 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+ buffer->private = private;
+ buffer->vc_handle = result.res_handle;
+ buffer->size = import.size;
+- buffer->dma_addr = import.addr;
+ buffer->vpu_state = VPU_MAPPED;
+ buffer->kernel_id = import.kernel_id;
+- //buffer->res_cached = ioparam->cached;
++
++ sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
++ if (!sgt) {
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ ret = dma_get_sgtable(&sm_state->pdev->dev, sgt, buffer->cookie,
++ buffer->dma_addr, buffer->size);
++ if (ret < 0) {
++ /* FIXME: error handling */
++ pr_err("failed to get scatterlist from DMA API\n");
++ kfree(sgt);
++ ret = -ENOMEM;
++ goto error;
++ }
++ buffer->alloc.sg_table = sgt;
+
+ fd = dma_buf_fd(dmabuf, O_CLOEXEC);
+ if (fd < 0)
+@@ -1250,11 +1272,19 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
+ return 0;
+
+ error:
+- if (buffer) {
+- pr_err("[%s]: something failed - cleanup. ret %d\n", __func__,
+- ret);
++ pr_err("[%s]: something failed - cleanup. ret %d\n", __func__, ret);
+
++ if (dmabuf) {
++ /* dmabuf has been exported, therefore allow dmabuf cleanup to
++ * deal with this
++ */
+ dma_buf_put(dmabuf);
++ } else {
++ /* No dmabuf, therefore just free the buffer here */
++ if (buffer->cookie)
++ dma_free_coherent(&sm_state->pdev->dev, buffer->size,
++ buffer->cookie, buffer->dma_addr);
++ kfree(buffer);
+ }
+ return ret;
+ }
+@@ -1527,13 +1557,6 @@ static void vc_sm_connected_init(void)
+
+ pr_info("[%s]: start\n", __func__);
+
+- vc_sm_cma_add_heaps(&sm_state->cma_heap);
+- if (!sm_state->cma_heap) {
+- pr_err("[%s]: failed to initialise CMA heap\n",
+- __func__);
+- return;
+- }
+-
+ /*
+ * Initialize and create a VCHI connection for the shared memory service
+ * running on videocore.
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
+@@ -21,8 +21,6 @@
+ #include <linux/types.h>
+ #include <linux/miscdevice.h>
+
+-#include "vc_sm_cma.h"
+-
+ #define VC_SM_MAX_NAME_LEN 32
+
+ enum vc_sm_vpu_mapping_state {
+@@ -31,6 +29,12 @@ enum vc_sm_vpu_mapping_state {
+ VPU_UNMAPPING
+ };
+
++struct vc_sm_alloc_data {
++ unsigned long num_pages;
++ void *priv_virt;
++ struct sg_table *sg_table;
++};
++
+ struct vc_sm_imported {
+ struct dma_buf *dma_buf;
+ struct dma_buf_attachment *attach;
+@@ -56,8 +60,6 @@ struct vc_sm_buffer {
+ int in_use:1; /* Kernel is still using this resource */
+ int imported:1; /* Imported dmabuf */
+
+- struct sg_table *sg_table;
+-
+ enum vc_sm_vpu_mapping_state vpu_state;
+ u32 vc_handle; /* VideoCore handle for this buffer */
+ int vpu_allocated; /*
+@@ -69,11 +71,12 @@ struct vc_sm_buffer {
+ /* DMABUF related fields */
+ struct dma_buf *dma_buf;
+ dma_addr_t dma_addr;
++ void *cookie;
+
+ struct vc_sm_privdata_t *private;
+
+ union {
+- struct vc_sm_cma_alloc_data alloc;
++ struct vc_sm_alloc_data alloc;
+ struct vc_sm_imported import;
+ };
+ };
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
++++ /dev/null
+@@ -1,98 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/*
+- * VideoCore Shared Memory CMA allocator
+- *
+- * Copyright: 2018, Raspberry Pi (Trading) Ltd
+- *
+- * Based on the Android ION allocator
+- * Copyright (C) Linaro 2012
+- * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
+- *
+- */
+-
+-#include <linux/slab.h>
+-#include <linux/errno.h>
+-#include <linux/err.h>
+-#include <linux/cma.h>
+-#include <linux/scatterlist.h>
+-
+-#include "vc_sm_cma.h"
+-
+-/* CMA heap operations functions */
+-int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
+- struct vc_sm_cma_alloc_data *buffer,
+- unsigned long len)
+-{
+- /* len should already be page aligned */
+- unsigned long num_pages = len / PAGE_SIZE;
+- struct sg_table *table;
+- struct page *pages;
+- int ret;
+-
+- pages = cma_alloc(cma_heap, num_pages, 0, GFP_KERNEL);
+- if (!pages)
+- return -ENOMEM;
+-
+- table = kmalloc(sizeof(*table), GFP_KERNEL);
+- if (!table)
+- goto err;
+-
+- ret = sg_alloc_table(table, 1, GFP_KERNEL);
+- if (ret)
+- goto free_mem;
+-
+- sg_set_page(table->sgl, pages, len, 0);
+-
+- buffer->priv_virt = pages;
+- buffer->sg_table = table;
+- buffer->cma_heap = cma_heap;
+- buffer->num_pages = num_pages;
+- return 0;
+-
+-free_mem:
+- kfree(table);
+-err:
+- cma_release(cma_heap, pages, num_pages);
+- return -ENOMEM;
+-}
+-
+-void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer)
+-{
+- struct cma *cma_heap = buffer->cma_heap;
+- struct page *pages = buffer->priv_virt;
+-
+- /* release memory */
+- if (cma_heap)
+- cma_release(cma_heap, pages, buffer->num_pages);
+-
+- /* release sg table */
+- if (buffer->sg_table) {
+- sg_free_table(buffer->sg_table);
+- kfree(buffer->sg_table);
+- buffer->sg_table = NULL;
+- }
+-}
+-
+-int __vc_sm_cma_add_heaps(struct cma *cma, void *priv)
+-{
+- struct cma **heap = (struct cma **)priv;
+- const char *name = cma_get_name(cma);
+-
+- if (!(*heap)) {
+- phys_addr_t phys_addr = cma_get_base(cma);
+-
+- pr_debug("%s: Adding cma heap %s (start %pap, size %lu) for use by vcsm\n",
+- __func__, name, &phys_addr, cma_get_size(cma));
+- *heap = cma;
+- } else {
+- pr_err("%s: Ignoring heap %s as already set\n",
+- __func__, name);
+- }
+-
+- return 0;
+-}
+-
+-void vc_sm_cma_add_heaps(struct cma **cma_heap)
+-{
+- cma_for_each_area(__vc_sm_cma_add_heaps, cma_heap);
+-}
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
++++ /dev/null
+@@ -1,39 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-
+-/*
+- * VideoCore Shared Memory CMA allocator
+- *
+- * Copyright: 2018, Raspberry Pi (Trading) Ltd
+- *
+- * Based on the Android ION allocator
+- * Copyright (C) Linaro 2012
+- * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
+- *
+- * This software is licensed under the terms of the GNU General Public
+- * License version 2, as published by the Free Software Foundation, and
+- * may be copied, distributed, and modified under those terms.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- */
+-#ifndef VC_SM_CMA_H
+-#define VC_SM_CMA_H
+-
+-struct vc_sm_cma_alloc_data {
+- struct cma *cma_heap;
+- unsigned long num_pages;
+- void *priv_virt;
+- struct sg_table *sg_table;
+-};
+-
+-int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
+- struct vc_sm_cma_alloc_data *buffer,
+- unsigned long len);
+-void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer);
+-
+-void vc_sm_cma_add_heaps(struct cma **cma_heap);
+-
+-#endif
--- /dev/null
+From 9c2c5607d3210f9d582547465aae6c9883daf0d9 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 1 Jul 2019 12:00:27 +0100
+Subject: [PATCH 688/725] Revert "configs: Drop V4L2 camera and codec drivers
+ from bcmrpi3_defconfig"
+
+This reverts commit e8a66b4f610b3a20bae8f706256d230135916c26.
+
+The issues are now resolved.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm64/configs/bcmrpi3_defconfig | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -1086,6 +1086,8 @@ CONFIG_FB_TFT_WATTEROTT=m
+ CONFIG_FB_FLEX=m
+ CONFIG_FB_TFT_FBTFT_DEVICE=m
+ CONFIG_SND_BCM2835=m
++CONFIG_VIDEO_BCM2835=m
++CONFIG_VIDEO_CODEC_BCM2835=m
+ CONFIG_MAILBOX=y
+ CONFIG_BCM2835_MBOX=y
+ # CONFIG_IOMMU_SUPPORT is not set
+++ /dev/null
-From efdc8dd4cb2e2d607f2c1cc0689faa6590c164f2 Mon Sep 17 00:00:00 2001
-From: Andrei Gherzan <andrei@gherzan.ro>
-Date: Wed, 3 Jul 2019 13:53:29 +0100
-Subject: [PATCH 688/703] configs: arm64/bcm2711: Add MMC_SDHCI_IPROC
-
-This driver is used in the device tree for the emmc2 node.
-
-See #3032
-
-Signed-off-by: Andrei Gherzan <andrei@gherzan.ro>
----
- arch/arm64/configs/bcm2711_defconfig | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm64/configs/bcm2711_defconfig
-+++ b/arch/arm64/configs/bcm2711_defconfig
-@@ -1036,6 +1036,7 @@ CONFIG_MMC_BCM2835_DMA=y
- CONFIG_MMC_BCM2835_SDHOST=y
- CONFIG_MMC_SDHCI=y
- CONFIG_MMC_SDHCI_PLTFM=y
-+CONFIG_MMC_SDHCI_IPROC=y
- CONFIG_MMC_SPI=m
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
--- /dev/null
+From c113d9a69caa55d8b0d5bd4bfbb7fdf502565edb Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 1 Jul 2019 12:06:54 +0100
+Subject: [PATCH 689/725] Revert "configs: arm64/bcm2711: Remove
+ CONFIG_VIDEO_BCM2835"
+
+This reverts commit 9d1deec93fa8b1b4953ff5e9210349f3c85b9a8d.
+
+The issues are resolved, so reenable.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm/configs/bcm2709_defconfig | 2 +-
+ arch/arm64/configs/bcm2711_defconfig | 2 ++
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -16,11 +16,11 @@ CONFIG_IKCONFIG=m
+ CONFIG_IKCONFIG_PROC=y
+ CONFIG_MEMCG=y
+ CONFIG_BLK_CGROUP=y
+-CONFIG_CGROUP_PIDS=y
+ CONFIG_CGROUP_FREEZER=y
+ CONFIG_CPUSETS=y
+ CONFIG_CGROUP_DEVICE=y
+ CONFIG_CGROUP_CPUACCT=y
++CONFIG_CGROUP_PIDS=y
+ CONFIG_NAMESPACES=y
+ CONFIG_USER_NS=y
+ CONFIG_SCHED_AUTOGROUP=y
+--- a/arch/arm64/configs/bcm2711_defconfig
++++ b/arch/arm64/configs/bcm2711_defconfig
+@@ -1031,6 +1031,7 @@ CONFIG_USB_G_HID=m
+ CONFIG_USB_G_WEBCAM=m
+ CONFIG_MMC=y
+ CONFIG_MMC_BLOCK_MINORS=32
++CONFIG_MMC_SDHCI_BCM2711=y
+ CONFIG_MMC_BCM2835_MMC=y
+ CONFIG_MMC_BCM2835_DMA=y
+ CONFIG_MMC_BCM2835_SDHOST=y
+@@ -1130,6 +1131,7 @@ CONFIG_FB_TFT_WATTEROTT=m
+ CONFIG_FB_FLEX=m
+ CONFIG_FB_TFT_FBTFT_DEVICE=m
+ CONFIG_SND_BCM2835=m
++CONFIG_VIDEO_BCM2835=m
+ CONFIG_MAILBOX=y
+ CONFIG_BCM2835_MBOX=y
+ # CONFIG_IOMMU_SUPPORT is not set
+++ /dev/null
-From feace5977af2dc38e4b089b52f6915e538cdf9e9 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 3 Jul 2019 20:37:14 +0100
-Subject: [PATCH 689/703] overlays: Correct gpio-fan gpio flags for 4.19
-
-The gpio-fan overlay was submitted for the 4.14 kernel where the second
-value in the Device Tree gpios declaration was ignored (thanks to an
-old-style driver), allowing the fan-control output to be active-high
-even though the declaration appears to request it be active-low.
-The gpio-fan driver in 4.19 uses GPIO descriptors and honours the
-active-low flag that the overlay (accidentally?) supplies.
-
-Change/correct the flags field to mark the GPIO as active-high.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/gpio-fan-overlay.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts
-@@ -45,7 +45,7 @@
- __overlay__ {
- fan0: gpio-fan@0 {
- compatible = "gpio-fan";
-- gpios = <&gpio 12 1>;
-+ gpios = <&gpio 12 0>;
- gpio-fan,speed-map = <0 0>,
- <5000 1>;
- #cooling-cells = <2>;
--- /dev/null
+From c6293ea00d55c0d48fd723da6072212f896a74b1 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 2 Jul 2019 17:19:04 +0100
+Subject: [PATCH 690/725] staging: vc-sm-cma: Fix the few remaining coding
+ style issues
+
+Fix a few minor checkpatch complaints to make the driver clean
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c | 6 +-
+ .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c | 128 +++++++++---------
+ 2 files changed, 65 insertions(+), 69 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -325,7 +325,6 @@ static void vc_sm_release_resource(struc
+ buffer->cookie, buffer->dma_addr);
+ }
+
+-
+ /* Free our buffer. Start by removing it from the list */
+ mutex_lock(&sm_state->map_lock);
+ list_del(&buffer->global_buffer_list);
+@@ -1365,7 +1364,8 @@ static int vc_sm_cma_clean_invalid2(unsi
+ }
+
+ for (i = 0; i < ioparam.op_count; i++) {
+- const struct vc_sm_cma_ioctl_clean_invalid_block * const op = block + i;
++ const struct vc_sm_cma_ioctl_clean_invalid_block * const op =
++ block + i;
+
+ if (op->invalidate_mode == VC_SM_CACHE_OP_NOP)
+ continue;
+@@ -1637,8 +1637,6 @@ err_remove_misc_dev:
+ err_remove_debugfs:
+ debugfs_remove_recursive(sm_state->dir_root);
+ vc_sm_cma_vchi_stop(&sm_state->sm_handle);
+-
+- return;
+ }
+
+ /* Driver loading. */
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
+@@ -188,79 +188,77 @@ static int vc_sm_cma_vchi_videocore_io(v
+ if (svc_use)
+ vchi_service_release(instance->vchi_handle[0]);
+ svc_use = 0;
+- if (!wait_for_completion_interruptible(&instance->io_cmplt)) {
+- vchi_service_use(instance->vchi_handle[0]);
+- svc_use = 1;
+-
+- do {
+- /*
+- * Get new command and move it to response list
+- */
+- mutex_lock(&instance->lock);
+- if (list_empty(&instance->cmd_list)) {
+- /* no more commands to process */
+- mutex_unlock(&instance->lock);
+- break;
+- }
+- cmd =
+- list_first_entry(&instance->cmd_list,
+- struct sm_cmd_rsp_blk,
+- head);
+- list_move(&cmd->head, &instance->rsp_list);
+- cmd->sent = 1;
+- mutex_unlock(&instance->lock);
+
+- /* Send the command */
+- status = bcm2835_vchi_msg_queue(
+- instance->vchi_handle[0],
+- cmd->msg, cmd->length);
+- if (status) {
+- pr_err("%s: failed to queue message (%d)",
+- __func__, status);
+- }
+-
+- /* If no reply is needed then we're done */
+- if (!cmd->wait) {
+- mutex_lock(&instance->lock);
+- list_del(&cmd->head);
+- mutex_unlock(&instance->lock);
+- vc_vchi_cmd_delete(instance, cmd);
+- continue;
+- }
+-
+- if (status) {
+- complete(&cmd->cmplt);
+- continue;
+- }
+-
+- } while (1);
+-
+- while (!vchi_msg_peek(instance->vchi_handle[0],
+- (void **)&reply, &reply_len,
+- VCHI_FLAGS_NONE)) {
+- if (reply->trans_id & 0x80000000) {
+- /* Async event or cmd from the VPU */
+- if (instance->vpu_event)
+- instance->vpu_event(
+- instance, reply,
+- reply_len);
+- } else {
+- vc_sm_cma_vchi_rx_ack(instance, cmd,
+- reply, reply_len);
+- }
++ if (wait_for_completion_interruptible(&instance->io_cmplt))
++ continue;
+
+- vchi_msg_remove(instance->vchi_handle[0]);
+- }
++ vchi_service_use(instance->vchi_handle[0]);
++ svc_use = 1;
+
+- /* Go through the dead list and free them */
++ do {
++ /*
++ * Get new command and move it to response list
++ */
+ mutex_lock(&instance->lock);
+- list_for_each_entry_safe(cmd, cmd_tmp,
+- &instance->dead_list, head) {
++ if (list_empty(&instance->cmd_list)) {
++ /* no more commands to process */
++ mutex_unlock(&instance->lock);
++ break;
++ }
++ cmd = list_first_entry(&instance->cmd_list,
++ struct sm_cmd_rsp_blk, head);
++ list_move(&cmd->head, &instance->rsp_list);
++ cmd->sent = 1;
++ mutex_unlock(&instance->lock);
++
++ /* Send the command */
++ status =
++ bcm2835_vchi_msg_queue(instance->vchi_handle[0],
++ cmd->msg, cmd->length);
++ if (status) {
++ pr_err("%s: failed to queue message (%d)",
++ __func__, status);
++ }
++
++ /* If no reply is needed then we're done */
++ if (!cmd->wait) {
++ mutex_lock(&instance->lock);
+ list_del(&cmd->head);
++ mutex_unlock(&instance->lock);
+ vc_vchi_cmd_delete(instance, cmd);
++ continue;
+ }
+- mutex_unlock(&instance->lock);
++
++ if (status) {
++ complete(&cmd->cmplt);
++ continue;
++ }
++
++ } while (1);
++
++ while (!vchi_msg_peek(instance->vchi_handle[0], (void **)&reply,
++ &reply_len, VCHI_FLAGS_NONE)) {
++ if (reply->trans_id & 0x80000000) {
++ /* Async event or cmd from the VPU */
++ if (instance->vpu_event)
++ instance->vpu_event(instance, reply,
++ reply_len);
++ } else {
++ vc_sm_cma_vchi_rx_ack(instance, cmd, reply,
++ reply_len);
++ }
++
++ vchi_msg_remove(instance->vchi_handle[0]);
++ }
++
++ /* Go through the dead list and free them */
++ mutex_lock(&instance->lock);
++ list_for_each_entry_safe(cmd, cmd_tmp, &instance->dead_list,
++ head) {
++ list_del(&cmd->head);
++ vc_vchi_cmd_delete(instance, cmd);
+ }
++ mutex_unlock(&instance->lock);
+ }
+
+ return 0;
+++ /dev/null
-From fbcf72909974b3dda42a292013c349647bcfa945 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 25 Jun 2019 00:29:44 +0100
-Subject: [PATCH 690/703] staging: vcsm-cma: Remove cache manipulation ioctl
- from ARM64
-
-The cache flushing ioctls are used by the Pi3 HEVC hw-assisted
-decoder as it needs finer grained flushing control than dma_ops
-allow.
-These cache calls are not present for ARM64, therefore disable
-them. We are not actively supporting 64bit kernels at present,
-and the use case of the HEVC decoder is fairly limited.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -1259,6 +1259,7 @@ error:
- return ret;
- }
-
-+#ifndef CONFIG_ARM64
- /* Converts VCSM_CACHE_OP_* to an operating function. */
- static void (*cache_op_to_func(const unsigned int cache_op))
- (const void*, const void*)
-@@ -1351,6 +1352,7 @@ out:
-
- return ret;
- }
-+#endif
-
- static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-@@ -1448,6 +1450,7 @@ static long vc_sm_cma_ioctl(struct file
- break;
- }
-
-+#ifndef CONFIG_ARM64
- /*
- * Flush/Invalidate the cache for a given mapping.
- * Blocks must be pinned (i.e. accessed) before this call.
-@@ -1455,6 +1458,7 @@ static long vc_sm_cma_ioctl(struct file
- case VC_SM_CMA_CMD_CLEAN_INVALID2:
- ret = vc_sm_cma_clean_invalid2(cmdnr, arg);
- break;
-+#endif
-
- default:
- pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
-@@ -1467,6 +1471,7 @@ static long vc_sm_cma_ioctl(struct file
- return ret;
- }
-
-+#ifndef CONFIG_ARM64
- #ifdef CONFIG_COMPAT
- struct vc_sm_cma_ioctl_clean_invalid2_32 {
- u32 op_count;
-@@ -1496,14 +1501,17 @@ static long vc_sm_cma_compat_ioctl(struc
- }
- }
- #endif
-+#endif
-
- /* Device operations that we managed in this driver. */
- static const struct file_operations vc_sm_ops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = vc_sm_cma_ioctl,
-+#ifndef CONFIG_ARM64
- #ifdef CONFIG_COMPAT
- .compat_ioctl = vc_sm_cma_compat_ioctl,
- #endif
-+#endif
- .open = vc_sm_cma_open,
- .release = vc_sm_cma_release,
- };
--- /dev/null
+From a8d9b98abf93405b56ad420c2337b9c16d443555 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 4 Jul 2019 11:52:43 +0100
+Subject: [PATCH 691/725] configs: Drop MMC_SDHCI_BCM2711 from
+ arm64/bcm2711_defconfig
+
+Apparently this is a vestigial setting and should be removed.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ arch/arm64/configs/bcm2711_defconfig | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/arch/arm64/configs/bcm2711_defconfig
++++ b/arch/arm64/configs/bcm2711_defconfig
+@@ -1031,7 +1031,6 @@ CONFIG_USB_G_HID=m
+ CONFIG_USB_G_WEBCAM=m
+ CONFIG_MMC=y
+ CONFIG_MMC_BLOCK_MINORS=32
+-CONFIG_MMC_SDHCI_BCM2711=y
+ CONFIG_MMC_BCM2835_MMC=y
+ CONFIG_MMC_BCM2835_DMA=y
+ CONFIG_MMC_BCM2835_SDHOST=y
+++ /dev/null
-From 6c3a3d85c8877cb506d8a646fea01a97695fab14 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 1 Jul 2019 11:57:25 +0100
-Subject: [PATCH 691/703] staging: vcsm-cma: Rework to use dma APIs, not CMA
-
-Due to a misunderstanding of the DMA mapping APIs, I made
-the wrong decision on how to implement this.
-
-Rework to use dma_alloc_coherent instead of the CMA
-API. This also allows it to be built as a module easily.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vc-sm-cma/Kconfig | 4 +-
- .../staging/vc04_services/vc-sm-cma/Makefile | 2 +-
- .../staging/vc04_services/vc-sm-cma/vc_sm.c | 291 ++++++++++--------
- .../staging/vc04_services/vc-sm-cma/vc_sm.h | 13 +-
- .../vc04_services/vc-sm-cma/vc_sm_cma.c | 98 ------
- .../vc04_services/vc-sm-cma/vc_sm_cma.h | 39 ---
- 6 files changed, 168 insertions(+), 279 deletions(-)
- delete mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
- delete mode 100644 drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
-
---- a/drivers/staging/vc04_services/vc-sm-cma/Kconfig
-+++ b/drivers/staging/vc04_services/vc-sm-cma/Kconfig
-@@ -1,6 +1,6 @@
- config BCM_VC_SM_CMA
-- bool "VideoCore Shared Memory (CMA) driver"
-- depends on BCM2835_VCHIQ && DMA_CMA
-+ tristate "VideoCore Shared Memory (CMA) driver"
-+ depends on BCM2835_VCHIQ
- select RBTREE
- select DMA_SHARED_BUFFER
- help
---- a/drivers/staging/vc04_services/vc-sm-cma/Makefile
-+++ b/drivers/staging/vc04_services/vc-sm-cma/Makefile
-@@ -3,6 +3,6 @@ ccflags-y += -Idrivers/staging/vc04_serv
- ccflags-y += -D__VCCOREVER__=0
-
- vc-sm-cma-$(CONFIG_BCM_VC_SM_CMA) := \
-- vc_sm.o vc_sm_cma_vchi.o vc_sm_cma.o
-+ vc_sm.o vc_sm_cma_vchi.o
-
- obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma.o
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -6,8 +6,8 @@
- * Dave Stevenson <dave.stevenson@raspberrypi.org>
- *
- * Based on vmcs_sm driver from Broadcom Corporation for some API,
-- * and taking some code for CMA/dmabuf handling from the Android Ion
-- * driver (Google/Linaro).
-+ * and taking some code for buffer allocation and dmabuf handling from
-+ * videobuf2.
- *
- *
- * This driver has 3 main uses:
-@@ -52,7 +52,6 @@
- #include "vc_sm_cma_vchi.h"
-
- #include "vc_sm.h"
--#include "vc_sm_cma.h"
- #include "vc_sm_knl.h"
- #include <linux/broadcom/vc_sm_cma_ioctl.h>
-
-@@ -89,7 +88,6 @@ struct sm_state_t {
- struct miscdevice misc_dev;
-
- struct sm_instance *sm_handle; /* Handle for videocore service. */
-- struct cma *cma_heap;
-
- spinlock_t kernelid_map_lock; /* Spinlock protecting kernelid_map */
- struct idr kernelid_map;
-@@ -110,8 +108,9 @@ struct sm_state_t {
-
- struct vc_sm_dma_buf_attachment {
- struct device *dev;
-- struct sg_table *table;
-+ struct sg_table sg_table;
- struct list_head list;
-+ enum dma_data_direction dma_dir;
- };
-
- /* ---- Private Variables ----------------------------------------------- */
-@@ -202,9 +201,10 @@ static int vc_sm_cma_global_state_show(s
- resource->import.attach);
- seq_printf(s, " SGT %p\n",
- resource->import.sgt);
-+ } else {
-+ seq_printf(s, " SGT %p\n",
-+ resource->alloc.sg_table);
- }
-- seq_printf(s, " SG_TABLE %p\n",
-- resource->sg_table);
- seq_printf(s, " DMA_ADDR %pad\n",
- &resource->dma_addr);
- seq_printf(s, " VC_HANDLE %08x\n",
-@@ -296,8 +296,9 @@ static void vc_sm_vpu_free(struct vc_sm_
- */
- static void vc_sm_release_resource(struct vc_sm_buffer *buffer)
- {
-- pr_debug("[%s]: buffer %p (name %s, size %zu)\n",
-- __func__, buffer, buffer->name, buffer->size);
-+ pr_debug("[%s]: buffer %p (name %s, size %zu), imported %u\n",
-+ __func__, buffer, buffer->name, buffer->size,
-+ buffer->imported);
-
- if (buffer->vc_handle) {
- /* We've sent the unmap request but not had the response. */
-@@ -313,8 +314,6 @@ static void vc_sm_release_resource(struc
-
- /* Release the allocation (whether imported dmabuf or CMA allocation) */
- if (buffer->imported) {
-- pr_debug("%s: Release imported dmabuf %p\n", __func__,
-- buffer->import.dma_buf);
- if (buffer->import.dma_buf)
- dma_buf_put(buffer->import.dma_buf);
- else
-@@ -322,16 +321,8 @@ static void vc_sm_release_resource(struc
- __func__, buffer);
- buffer->import.dma_buf = NULL;
- } else {
-- if (buffer->sg_table) {
-- /* Our own allocation that we need to dma_unmap_sg */
-- dma_unmap_sg(&sm_state->pdev->dev,
-- buffer->sg_table->sgl,
-- buffer->sg_table->nents,
-- DMA_BIDIRECTIONAL);
-- }
-- pr_debug("%s: Release our allocation\n", __func__);
-- vc_sm_cma_buffer_free(&buffer->alloc);
-- pr_debug("%s: Release our allocation - done\n", __func__);
-+ dma_free_coherent(&sm_state->pdev->dev, buffer->size,
-+ buffer->cookie, buffer->dma_addr);
- }
-
-
-@@ -371,38 +362,6 @@ static struct vc_sm_privdata_t *vc_sm_cm
- return file_data;
- }
-
--static struct sg_table *dup_sg_table(struct sg_table *table)
--{
-- struct sg_table *new_table;
-- int ret, i;
-- struct scatterlist *sg, *new_sg;
--
-- new_table = kzalloc(sizeof(*new_table), GFP_KERNEL);
-- if (!new_table)
-- return ERR_PTR(-ENOMEM);
--
-- ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL);
-- if (ret) {
-- kfree(new_table);
-- return ERR_PTR(ret);
-- }
--
-- new_sg = new_table->sgl;
-- for_each_sg(table->sgl, sg, table->nents, i) {
-- memcpy(new_sg, sg, sizeof(*sg));
-- sg->dma_address = 0;
-- new_sg = sg_next(new_sg);
-- }
--
-- return new_table;
--}
--
--static void free_duped_table(struct sg_table *table)
--{
-- sg_free_table(table);
-- kfree(table);
--}
--
- /* Dma buf operations for use with our own allocations */
-
- static int vc_sm_dma_buf_attach(struct dma_buf *dmabuf,
-@@ -410,28 +369,45 @@ static int vc_sm_dma_buf_attach(struct d
-
- {
- struct vc_sm_dma_buf_attachment *a;
-- struct sg_table *table;
-+ struct sg_table *sgt;
- struct vc_sm_buffer *buf = dmabuf->priv;
-+ struct scatterlist *rd, *wr;
-+ int ret, i;
-
- a = kzalloc(sizeof(*a), GFP_KERNEL);
- if (!a)
- return -ENOMEM;
-
-- table = dup_sg_table(buf->sg_table);
-- if (IS_ERR(table)) {
-+ pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
-+
-+ mutex_lock(&buf->lock);
-+
-+ INIT_LIST_HEAD(&a->list);
-+
-+ sgt = &a->sg_table;
-+
-+ /* Copy the buf->base_sgt scatter list to the attachment, as we can't
-+ * map the same scatter list to multiple attachments at the same time.
-+ */
-+ ret = sg_alloc_table(sgt, buf->alloc.sg_table->orig_nents, GFP_KERNEL);
-+ if (ret) {
- kfree(a);
-- return PTR_ERR(table);
-+ return -ENOMEM;
- }
-
-- a->table = table;
-- INIT_LIST_HEAD(&a->list);
-+ rd = buf->alloc.sg_table->sgl;
-+ wr = sgt->sgl;
-+ for (i = 0; i < sgt->orig_nents; ++i) {
-+ sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
-+ rd = sg_next(rd);
-+ wr = sg_next(wr);
-+ }
-
-+ a->dma_dir = DMA_NONE;
- attachment->priv = a;
-
-- mutex_lock(&buf->lock);
- list_add(&a->list, &buf->attachments);
- mutex_unlock(&buf->lock);
-- pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
-
- return 0;
- }
-@@ -441,9 +417,20 @@ static void vc_sm_dma_buf_detach(struct
- {
- struct vc_sm_dma_buf_attachment *a = attachment->priv;
- struct vc_sm_buffer *buf = dmabuf->priv;
-+ struct sg_table *sgt;
-
- pr_debug("%s dmabuf %p attachment %p\n", __func__, dmabuf, attachment);
-- free_duped_table(a->table);
-+ if (!a)
-+ return;
-+
-+ sgt = &a->sg_table;
-+
-+ /* release the scatterlist cache */
-+ if (a->dma_dir != DMA_NONE)
-+ dma_unmap_sg(attachment->dev, sgt->sgl, sgt->orig_nents,
-+ a->dma_dir);
-+ sg_free_table(sgt);
-+
- mutex_lock(&buf->lock);
- list_del(&a->list);
- mutex_unlock(&buf->lock);
-@@ -455,13 +442,38 @@ static struct sg_table *vc_sm_map_dma_bu
- enum dma_data_direction direction)
- {
- struct vc_sm_dma_buf_attachment *a = attachment->priv;
-+ /* stealing dmabuf mutex to serialize map/unmap operations */
-+ struct mutex *lock = &attachment->dmabuf->lock;
- struct sg_table *table;
-
-- table = a->table;
-+ mutex_lock(lock);
-+ pr_debug("%s attachment %p\n", __func__, attachment);
-+ table = &a->sg_table;
-+
-+ /* return previously mapped sg table */
-+ if (a->dma_dir == direction) {
-+ mutex_unlock(lock);
-+ return table;
-+ }
-+
-+ /* release any previous cache */
-+ if (a->dma_dir != DMA_NONE) {
-+ dma_unmap_sg(attachment->dev, table->sgl, table->orig_nents,
-+ a->dma_dir);
-+ a->dma_dir = DMA_NONE;
-+ }
-+
-+ /* mapping to the client with new direction */
-+ table->nents = dma_map_sg(attachment->dev, table->sgl,
-+ table->orig_nents, direction);
-+ if (!table->nents) {
-+ pr_err("failed to map scatterlist\n");
-+ mutex_unlock(lock);
-+ return ERR_PTR(-EIO);
-+ }
-
-- if (!dma_map_sg(attachment->dev, table->sgl, table->nents,
-- direction))
-- return ERR_PTR(-ENOMEM);
-+ a->dma_dir = direction;
-+ mutex_unlock(lock);
-
- pr_debug("%s attachment %p\n", __func__, attachment);
- return table;
-@@ -478,41 +490,26 @@ static void vc_sm_unmap_dma_buf(struct d
- static int vc_sm_dmabuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
- {
- struct vc_sm_buffer *buf = dmabuf->priv;
-- struct sg_table *table = buf->sg_table;
-- unsigned long addr = vma->vm_start;
-- unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
-- struct scatterlist *sg;
-- int i;
-- int ret = 0;
-+ int ret;
-
- pr_debug("%s dmabuf %p, buf %p, vm_start %08lX\n", __func__, dmabuf,
-- buf, addr);
-+ buf, vma->vm_start);
-
- mutex_lock(&buf->lock);
-
- /* now map it to userspace */
-- for_each_sg(table->sgl, sg, table->nents, i) {
-- struct page *page = sg_page(sg);
-- unsigned long remainder = vma->vm_end - addr;
-- unsigned long len = sg->length;
-+ vma->vm_pgoff = 0;
-
-- if (offset >= sg->length) {
-- offset -= sg->length;
-- continue;
-- } else if (offset) {
-- page += offset / PAGE_SIZE;
-- len = sg->length - offset;
-- offset = 0;
-- }
-- len = min(len, remainder);
-- ret = remap_pfn_range(vma, addr, page_to_pfn(page), len,
-- vma->vm_page_prot);
-- if (ret)
-- break;
-- addr += len;
-- if (addr >= vma->vm_end)
-- break;
-+ ret = dma_mmap_coherent(&sm_state->pdev->dev, vma, buf->cookie,
-+ buf->dma_addr, buf->size);
-+
-+ if (ret) {
-+ pr_err("Remapping memory failed, error: %d\n", ret);
-+ return ret;
- }
-+
-+ vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
-+
- mutex_unlock(&buf->lock);
-
- if (ret)
-@@ -570,8 +567,8 @@ static int vc_sm_dma_buf_begin_cpu_acces
- mutex_lock(&buf->lock);
-
- list_for_each_entry(a, &buf->attachments, list) {
-- dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents,
-- direction);
-+ dma_sync_sg_for_cpu(a->dev, a->sg_table.sgl,
-+ a->sg_table.nents, direction);
- }
- mutex_unlock(&buf->lock);
-
-@@ -593,8 +590,8 @@ static int vc_sm_dma_buf_end_cpu_access(
- mutex_lock(&buf->lock);
-
- list_for_each_entry(a, &buf->attachments, list) {
-- dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents,
-- direction);
-+ dma_sync_sg_for_device(a->dev, a->sg_table.sgl,
-+ a->sg_table.nents, direction);
- }
- mutex_unlock(&buf->lock);
-
-@@ -625,7 +622,9 @@ static const struct dma_buf_ops dma_buf_
- .map = vc_sm_dma_buf_kmap,
- .unmap = vc_sm_dma_buf_kunmap,
- };
-+
- /* Dma_buf operations for chaining through to an imported dma_buf */
-+
- static
- int vc_sm_import_dma_buf_attach(struct dma_buf *dmabuf,
- struct dma_buf_attachment *attachment)
-@@ -819,7 +818,7 @@ vc_sm_cma_import_dmabuf_internal(struct
-
- import.type = VC_SM_ALLOC_NON_CACHED;
- dma_addr = sg_dma_address(sgt->sgl);
-- import.addr = (uint32_t)dma_addr;
-+ import.addr = (u32)dma_addr;
- if ((import.addr & 0xC0000000) != 0xC0000000) {
- pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
- __func__, &dma_addr);
-@@ -911,11 +910,12 @@ error:
- return ret;
- }
-
--static int vc_sm_cma_vpu_alloc(u32 size, uint32_t align, const char *name,
-+static int vc_sm_cma_vpu_alloc(u32 size, u32 align, const char *name,
- u32 mem_handle, struct vc_sm_buffer **ret_buffer)
- {
- DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
- struct vc_sm_buffer *buffer = NULL;
-+ struct sg_table *sgt;
- int aligned_size;
- int ret = 0;
-
-@@ -938,23 +938,34 @@ static int vc_sm_cma_vpu_alloc(u32 size,
- */
- mutex_lock(&buffer->lock);
-
-- if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
-- aligned_size)) {
-- pr_err("[%s]: cma alloc of %d bytes failed\n",
-+ buffer->cookie = dma_alloc_coherent(&sm_state->pdev->dev,
-+ aligned_size, &buffer->dma_addr,
-+ GFP_KERNEL);
-+ if (!buffer->cookie) {
-+ pr_err("[%s]: dma_alloc_coherent alloc of %d bytes failed\n",
- __func__, aligned_size);
- ret = -ENOMEM;
- goto error;
- }
-- buffer->sg_table = buffer->alloc.sg_table;
-
-- pr_debug("[%s]: cma alloc of %d bytes success\n",
-+ pr_debug("[%s]: alloc of %d bytes success\n",
- __func__, aligned_size);
-
-- if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
-- buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
-- pr_err("[%s]: dma_map_sg failed\n", __func__);
-+ sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
-+ if (!sgt) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ ret = dma_get_sgtable(&sm_state->pdev->dev, sgt, buffer->cookie,
-+ buffer->dma_addr, buffer->size);
-+ if (ret < 0) {
-+ pr_err("failed to get scatterlist from DMA API\n");
-+ kfree(sgt);
-+ ret = -ENOMEM;
- goto error;
- }
-+ buffer->alloc.sg_table = sgt;
-
- INIT_LIST_HEAD(&buffer->attachments);
-
-@@ -971,10 +982,10 @@ static int vc_sm_cma_vpu_alloc(u32 size,
- ret = PTR_ERR(buffer->dma_buf);
- goto error;
- }
-- buffer->dma_addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
-+ buffer->dma_addr = (u32)sg_dma_address(buffer->alloc.sg_table->sgl);
- if ((buffer->dma_addr & 0xC0000000) != 0xC0000000) {
-- pr_err("%s: Expecting an uncached alias for dma_addr %pad\n",
-- __func__, &buffer->dma_addr);
-+ pr_warn_once("%s: Expecting an uncached alias for dma_addr %pad\n",
-+ __func__, &buffer->dma_addr);
- buffer->dma_addr |= 0xC0000000;
- }
- buffer->private = sm_state->vpu_allocs;
-@@ -1145,6 +1156,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
- struct vc_sm_import import = { 0 };
- struct vc_sm_import_result result = { 0 };
- struct dma_buf *dmabuf = NULL;
-+ struct sg_table *sgt;
- int aligned_size;
- int ret = 0;
- int status;
-@@ -1162,18 +1174,13 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
- goto error;
- }
-
-- if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
-- aligned_size)) {
-- pr_err("[%s]: cma alloc of %d bytes failed\n",
-+ buffer->cookie = dma_alloc_coherent(&sm_state->pdev->dev,
-+ aligned_size,
-+ &buffer->dma_addr,
-+ GFP_KERNEL);
-+ if (!buffer->cookie) {
-+ pr_err("[%s]: dma_alloc_coherent alloc of %d bytes failed\n",
- __func__, aligned_size);
-- kfree(buffer);
-- return -ENOMEM;
-- }
-- buffer->sg_table = buffer->alloc.sg_table;
--
-- if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
-- buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
-- pr_err("[%s]: dma_map_sg failed\n", __func__);
- ret = -ENOMEM;
- goto error;
- }
-@@ -1204,7 +1211,7 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
- }
- buffer->dma_buf = dmabuf;
-
-- import.addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
-+ import.addr = buffer->dma_addr;
- import.size = aligned_size;
- import.kernel_id = get_kernel_id(buffer);
-
-@@ -1229,10 +1236,25 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
- buffer->private = private;
- buffer->vc_handle = result.res_handle;
- buffer->size = import.size;
-- buffer->dma_addr = import.addr;
- buffer->vpu_state = VPU_MAPPED;
- buffer->kernel_id = import.kernel_id;
-- //buffer->res_cached = ioparam->cached;
-+
-+ sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
-+ if (!sgt) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ ret = dma_get_sgtable(&sm_state->pdev->dev, sgt, buffer->cookie,
-+ buffer->dma_addr, buffer->size);
-+ if (ret < 0) {
-+ /* FIXME: error handling */
-+ pr_err("failed to get scatterlist from DMA API\n");
-+ kfree(sgt);
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+ buffer->alloc.sg_table = sgt;
-
- fd = dma_buf_fd(dmabuf, O_CLOEXEC);
- if (fd < 0)
-@@ -1250,11 +1272,19 @@ int vc_sm_cma_ioctl_alloc(struct vc_sm_p
- return 0;
-
- error:
-- if (buffer) {
-- pr_err("[%s]: something failed - cleanup. ret %d\n", __func__,
-- ret);
-+ pr_err("[%s]: something failed - cleanup. ret %d\n", __func__, ret);
-
-+ if (dmabuf) {
-+ /* dmabuf has been exported, therefore allow dmabuf cleanup to
-+ * deal with this
-+ */
- dma_buf_put(dmabuf);
-+ } else {
-+ /* No dmabuf, therefore just free the buffer here */
-+ if (buffer->cookie)
-+ dma_free_coherent(&sm_state->pdev->dev, buffer->size,
-+ buffer->cookie, buffer->dma_addr);
-+ kfree(buffer);
- }
- return ret;
- }
-@@ -1527,13 +1557,6 @@ static void vc_sm_connected_init(void)
-
- pr_info("[%s]: start\n", __func__);
-
-- vc_sm_cma_add_heaps(&sm_state->cma_heap);
-- if (!sm_state->cma_heap) {
-- pr_err("[%s]: failed to initialise CMA heap\n",
-- __func__);
-- return;
-- }
--
- /*
- * Initialize and create a VCHI connection for the shared memory service
- * running on videocore.
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
-@@ -21,8 +21,6 @@
- #include <linux/types.h>
- #include <linux/miscdevice.h>
-
--#include "vc_sm_cma.h"
--
- #define VC_SM_MAX_NAME_LEN 32
-
- enum vc_sm_vpu_mapping_state {
-@@ -31,6 +29,12 @@ enum vc_sm_vpu_mapping_state {
- VPU_UNMAPPING
- };
-
-+struct vc_sm_alloc_data {
-+ unsigned long num_pages;
-+ void *priv_virt;
-+ struct sg_table *sg_table;
-+};
-+
- struct vc_sm_imported {
- struct dma_buf *dma_buf;
- struct dma_buf_attachment *attach;
-@@ -56,8 +60,6 @@ struct vc_sm_buffer {
- int in_use:1; /* Kernel is still using this resource */
- int imported:1; /* Imported dmabuf */
-
-- struct sg_table *sg_table;
--
- enum vc_sm_vpu_mapping_state vpu_state;
- u32 vc_handle; /* VideoCore handle for this buffer */
- int vpu_allocated; /*
-@@ -69,11 +71,12 @@ struct vc_sm_buffer {
- /* DMABUF related fields */
- struct dma_buf *dma_buf;
- dma_addr_t dma_addr;
-+ void *cookie;
-
- struct vc_sm_privdata_t *private;
-
- union {
-- struct vc_sm_cma_alloc_data alloc;
-+ struct vc_sm_alloc_data alloc;
- struct vc_sm_imported import;
- };
- };
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
-+++ /dev/null
-@@ -1,98 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0
--/*
-- * VideoCore Shared Memory CMA allocator
-- *
-- * Copyright: 2018, Raspberry Pi (Trading) Ltd
-- *
-- * Based on the Android ION allocator
-- * Copyright (C) Linaro 2012
-- * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
-- *
-- */
--
--#include <linux/slab.h>
--#include <linux/errno.h>
--#include <linux/err.h>
--#include <linux/cma.h>
--#include <linux/scatterlist.h>
--
--#include "vc_sm_cma.h"
--
--/* CMA heap operations functions */
--int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
-- struct vc_sm_cma_alloc_data *buffer,
-- unsigned long len)
--{
-- /* len should already be page aligned */
-- unsigned long num_pages = len / PAGE_SIZE;
-- struct sg_table *table;
-- struct page *pages;
-- int ret;
--
-- pages = cma_alloc(cma_heap, num_pages, 0, GFP_KERNEL);
-- if (!pages)
-- return -ENOMEM;
--
-- table = kmalloc(sizeof(*table), GFP_KERNEL);
-- if (!table)
-- goto err;
--
-- ret = sg_alloc_table(table, 1, GFP_KERNEL);
-- if (ret)
-- goto free_mem;
--
-- sg_set_page(table->sgl, pages, len, 0);
--
-- buffer->priv_virt = pages;
-- buffer->sg_table = table;
-- buffer->cma_heap = cma_heap;
-- buffer->num_pages = num_pages;
-- return 0;
--
--free_mem:
-- kfree(table);
--err:
-- cma_release(cma_heap, pages, num_pages);
-- return -ENOMEM;
--}
--
--void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer)
--{
-- struct cma *cma_heap = buffer->cma_heap;
-- struct page *pages = buffer->priv_virt;
--
-- /* release memory */
-- if (cma_heap)
-- cma_release(cma_heap, pages, buffer->num_pages);
--
-- /* release sg table */
-- if (buffer->sg_table) {
-- sg_free_table(buffer->sg_table);
-- kfree(buffer->sg_table);
-- buffer->sg_table = NULL;
-- }
--}
--
--int __vc_sm_cma_add_heaps(struct cma *cma, void *priv)
--{
-- struct cma **heap = (struct cma **)priv;
-- const char *name = cma_get_name(cma);
--
-- if (!(*heap)) {
-- phys_addr_t phys_addr = cma_get_base(cma);
--
-- pr_debug("%s: Adding cma heap %s (start %pap, size %lu) for use by vcsm\n",
-- __func__, name, &phys_addr, cma_get_size(cma));
-- *heap = cma;
-- } else {
-- pr_err("%s: Ignoring heap %s as already set\n",
-- __func__, name);
-- }
--
-- return 0;
--}
--
--void vc_sm_cma_add_heaps(struct cma **cma_heap)
--{
-- cma_for_each_area(__vc_sm_cma_add_heaps, cma_heap);
--}
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
-+++ /dev/null
-@@ -1,39 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--
--/*
-- * VideoCore Shared Memory CMA allocator
-- *
-- * Copyright: 2018, Raspberry Pi (Trading) Ltd
-- *
-- * Based on the Android ION allocator
-- * Copyright (C) Linaro 2012
-- * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
-- *
-- * This software is licensed under the terms of the GNU General Public
-- * License version 2, as published by the Free Software Foundation, and
-- * may be copied, distributed, and modified under those terms.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- */
--#ifndef VC_SM_CMA_H
--#define VC_SM_CMA_H
--
--struct vc_sm_cma_alloc_data {
-- struct cma *cma_heap;
-- unsigned long num_pages;
-- void *priv_virt;
-- struct sg_table *sg_table;
--};
--
--int vc_sm_cma_buffer_allocate(struct cma *cma_heap,
-- struct vc_sm_cma_alloc_data *buffer,
-- unsigned long len);
--void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer);
--
--void vc_sm_cma_add_heaps(struct cma **cma_heap);
--
--#endif
+++ /dev/null
-From 5268102a3b9f7fc36e18e4cc913f42218a578487 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 1 Jul 2019 12:00:27 +0100
-Subject: [PATCH 692/703] Revert "configs: Drop V4L2 camera and codec drivers
- from bcmrpi3_defconfig"
-
-This reverts commit e8a66b4f610b3a20bae8f706256d230135916c26.
-
-The issues are now resolved.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm64/configs/bcmrpi3_defconfig | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/arch/arm64/configs/bcmrpi3_defconfig
-+++ b/arch/arm64/configs/bcmrpi3_defconfig
-@@ -1086,6 +1086,8 @@ CONFIG_FB_TFT_WATTEROTT=m
- CONFIG_FB_FLEX=m
- CONFIG_FB_TFT_FBTFT_DEVICE=m
- CONFIG_SND_BCM2835=m
-+CONFIG_VIDEO_BCM2835=m
-+CONFIG_VIDEO_CODEC_BCM2835=m
- CONFIG_MAILBOX=y
- CONFIG_BCM2835_MBOX=y
- # CONFIG_IOMMU_SUPPORT is not set
--- /dev/null
+From 2a099853599054a17621463365f7bd48223e0e4c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 28 Jun 2019 11:30:49 +0100
+Subject: [PATCH 692/725] Revert "media: vb2: Allow reqbufs(0) with "in use"
+ MMAP buffers"
+
+This reverts commit a2c73e18c1f657de6d654f51effa0a94863abbd8.
+An alternative version was accepted upstream. Revert this patch to
+apply that one.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../media/common/videobuf2/videobuf2-core.c | 23 +++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+--- a/drivers/media/common/videobuf2/videobuf2-core.c
++++ b/drivers/media/common/videobuf2/videobuf2-core.c
+@@ -554,6 +554,20 @@ bool vb2_buffer_in_use(struct vb2_queue
+ }
+ EXPORT_SYMBOL(vb2_buffer_in_use);
+
++/*
++ * __buffers_in_use() - return true if any buffers on the queue are in use and
++ * the queue cannot be freed (by the means of REQBUFS(0)) call
++ */
++static bool __buffers_in_use(struct vb2_queue *q)
++{
++ unsigned int buffer;
++ for (buffer = 0; buffer < q->num_buffers; ++buffer) {
++ if (vb2_buffer_in_use(q, q->bufs[buffer]))
++ return true;
++ }
++ return false;
++}
++
+ void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
+ {
+ call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
+@@ -665,7 +679,16 @@ int vb2_core_reqbufs(struct vb2_queue *q
+
+ if (*count == 0 || q->num_buffers != 0 ||
+ (q->memory != VB2_MEMORY_UNKNOWN && q->memory != memory)) {
++ /*
++ * We already have buffers allocated, so first check if they
++ * are not in use and can be freed.
++ */
+ mutex_lock(&q->mmap_lock);
++ if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
++ mutex_unlock(&q->mmap_lock);
++ dprintk(1, "memory in use, cannot free\n");
++ return -EBUSY;
++ }
+
+ /*
+ * Call queue_cancel to clean up any buffers in the PREPARED or
+++ /dev/null
-From 0e02c0b0f706a76e117298e7d4c6b730eeeed80c Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Mon, 1 Jul 2019 12:06:54 +0100
-Subject: [PATCH 693/703] Revert "configs: arm64/bcm2711: Remove
- CONFIG_VIDEO_BCM2835"
-
-This reverts commit 9d1deec93fa8b1b4953ff5e9210349f3c85b9a8d.
-
-The issues are resolved, so reenable.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm/configs/bcm2709_defconfig | 2 +-
- arch/arm64/configs/bcm2711_defconfig | 2 ++
- 2 files changed, 3 insertions(+), 1 deletion(-)
-
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -16,11 +16,11 @@ CONFIG_IKCONFIG=m
- CONFIG_IKCONFIG_PROC=y
- CONFIG_MEMCG=y
- CONFIG_BLK_CGROUP=y
--CONFIG_CGROUP_PIDS=y
- CONFIG_CGROUP_FREEZER=y
- CONFIG_CPUSETS=y
- CONFIG_CGROUP_DEVICE=y
- CONFIG_CGROUP_CPUACCT=y
-+CONFIG_CGROUP_PIDS=y
- CONFIG_NAMESPACES=y
- CONFIG_USER_NS=y
- CONFIG_SCHED_AUTOGROUP=y
---- a/arch/arm64/configs/bcm2711_defconfig
-+++ b/arch/arm64/configs/bcm2711_defconfig
-@@ -1031,6 +1031,7 @@ CONFIG_USB_G_HID=m
- CONFIG_USB_G_WEBCAM=m
- CONFIG_MMC=y
- CONFIG_MMC_BLOCK_MINORS=32
-+CONFIG_MMC_SDHCI_BCM2711=y
- CONFIG_MMC_BCM2835_MMC=y
- CONFIG_MMC_BCM2835_DMA=y
- CONFIG_MMC_BCM2835_SDHOST=y
-@@ -1130,6 +1131,7 @@ CONFIG_FB_TFT_WATTEROTT=m
- CONFIG_FB_FLEX=m
- CONFIG_FB_TFT_FBTFT_DEVICE=m
- CONFIG_SND_BCM2835=m
-+CONFIG_VIDEO_BCM2835=m
- CONFIG_MAILBOX=y
- CONFIG_BCM2835_MBOX=y
- # CONFIG_IOMMU_SUPPORT is not set
--- /dev/null
+From 237e15f3caec01b144b2409829a731b734972539 Mon Sep 17 00:00:00 2001
+From: Hans Verkuil <hansverk@cisco.com>
+Date: Thu, 23 Aug 2018 09:56:22 -0400
+Subject: [PATCH 693/725] media: videodev2.h: add new capabilities for buffer
+ types
+
+Upstream commit f35f5d72e70e6b91389eb98fcabf43b79f40587f
+
+VIDIOC_REQBUFS and VIDIOC_CREATE_BUFFERS will return capabilities
+telling userspace what the given buffer type is capable of.
+
+Signed-off-by: Hans Verkuil <hansverk@cisco.com>
+Reviewed-by: Tomasz Figa <tfiga@chromium.org>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+---
+ .../media/uapi/v4l/vidioc-create-bufs.rst | 14 ++++++-
+ .../media/uapi/v4l/vidioc-reqbufs.rst | 42 ++++++++++++++++++-
+ include/uapi/linux/videodev2.h | 13 +++++-
+ 3 files changed, 65 insertions(+), 4 deletions(-)
+
+--- a/Documentation/media/uapi/v4l/vidioc-create-bufs.rst
++++ b/Documentation/media/uapi/v4l/vidioc-create-bufs.rst
+@@ -102,7 +102,19 @@ than the number requested.
+ - ``format``
+ - Filled in by the application, preserved by the driver.
+ * - __u32
+- - ``reserved``\ [8]
++ - ``capabilities``
++ - Set by the driver. If 0, then the driver doesn't support
++ capabilities. In that case all you know is that the driver is
++ guaranteed to support ``V4L2_MEMORY_MMAP`` and *might* support
++ other :c:type:`v4l2_memory` types. It will not support any others
++ capabilities. See :ref:`here <v4l2-buf-capabilities>` for a list of the
++ capabilities.
++
++ If you want to just query the capabilities without making any
++ other changes, then set ``count`` to 0, ``memory`` to
++ ``V4L2_MEMORY_MMAP`` and ``format.type`` to the buffer type.
++ * - __u32
++ - ``reserved``\ [7]
+ - A place holder for future extensions. Drivers and applications
+ must set the array to zero.
+
+--- a/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
++++ b/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
+@@ -88,10 +88,50 @@ any DMA in progress, an implicit
+ ``V4L2_MEMORY_DMABUF`` or ``V4L2_MEMORY_USERPTR``. See
+ :c:type:`v4l2_memory`.
+ * - __u32
+- - ``reserved``\ [2]
++ - ``capabilities``
++ - Set by the driver. If 0, then the driver doesn't support
++ capabilities. In that case all you know is that the driver is
++ guaranteed to support ``V4L2_MEMORY_MMAP`` and *might* support
++ other :c:type:`v4l2_memory` types. It will not support any others
++ capabilities.
++
++ If you want to query the capabilities with a minimum of side-effects,
++ then this can be called with ``count`` set to 0, ``memory`` set to
++ ``V4L2_MEMORY_MMAP`` and ``type`` set to the buffer type. This will
++ free any previously allocated buffers, so this is typically something
++ that will be done at the start of the application.
++ * - __u32
++ - ``reserved``\ [1]
+ - A place holder for future extensions. Drivers and applications
+ must set the array to zero.
+
++.. tabularcolumns:: |p{6.1cm}|p{2.2cm}|p{8.7cm}|
++
++.. _v4l2-buf-capabilities:
++.. _V4L2-BUF-CAP-SUPPORTS-MMAP:
++.. _V4L2-BUF-CAP-SUPPORTS-USERPTR:
++.. _V4L2-BUF-CAP-SUPPORTS-DMABUF:
++.. _V4L2-BUF-CAP-SUPPORTS-REQUESTS:
++
++.. cssclass:: longtable
++
++.. flat-table:: V4L2 Buffer Capabilities Flags
++ :header-rows: 0
++ :stub-columns: 0
++ :widths: 3 1 4
++
++ * - ``V4L2_BUF_CAP_SUPPORTS_MMAP``
++ - 0x00000001
++ - This buffer type supports the ``V4L2_MEMORY_MMAP`` streaming mode.
++ * - ``V4L2_BUF_CAP_SUPPORTS_USERPTR``
++ - 0x00000002
++ - This buffer type supports the ``V4L2_MEMORY_USERPTR`` streaming mode.
++ * - ``V4L2_BUF_CAP_SUPPORTS_DMABUF``
++ - 0x00000004
++ - This buffer type supports the ``V4L2_MEMORY_DMABUF`` streaming mode.
++ * - ``V4L2_BUF_CAP_SUPPORTS_REQUESTS``
++ - 0x00000008
++ - This buffer type supports :ref:`requests <media-request-api>`.
+
+ Return Value
+ ============
+--- a/include/uapi/linux/videodev2.h
++++ b/include/uapi/linux/videodev2.h
+@@ -872,9 +872,16 @@ struct v4l2_requestbuffers {
+ __u32 count;
+ __u32 type; /* enum v4l2_buf_type */
+ __u32 memory; /* enum v4l2_memory */
+- __u32 reserved[2];
++ __u32 capabilities;
++ __u32 reserved[1];
+ };
+
++/* capabilities for struct v4l2_requestbuffers and v4l2_create_buffers */
++#define V4L2_BUF_CAP_SUPPORTS_MMAP (1 << 0)
++#define V4L2_BUF_CAP_SUPPORTS_USERPTR (1 << 1)
++#define V4L2_BUF_CAP_SUPPORTS_DMABUF (1 << 2)
++#define V4L2_BUF_CAP_SUPPORTS_REQUESTS (1 << 3)
++
+ /**
+ * struct v4l2_plane - plane info for multi-planar buffers
+ * @bytesused: number of bytes occupied by data in the plane (payload)
+@@ -2318,6 +2325,7 @@ struct v4l2_dbg_chip_info {
+ * return: number of created buffers
+ * @memory: enum v4l2_memory; buffer memory type
+ * @format: frame format, for which buffers are requested
++ * @capabilities: capabilities of this buffer type.
+ * @reserved: future extensions
+ */
+ struct v4l2_create_buffers {
+@@ -2325,7 +2333,8 @@ struct v4l2_create_buffers {
+ __u32 count;
+ __u32 memory;
+ struct v4l2_format format;
+- __u32 reserved[8];
++ __u32 capabilities;
++ __u32 reserved[7];
+ };
+
+ /*
--- /dev/null
+From b1da554db18a08164e0f4490e1b290d02dc8a042 Mon Sep 17 00:00:00 2001
+From: Hans Verkuil <hansverk@cisco.com>
+Date: Thu, 23 Aug 2018 10:18:35 -0400
+Subject: [PATCH 694/725] media: vb2: set reqbufs/create_bufs capabilities
+
+Upstream commit e5079cf11373e4cc98be8b1072aece429eb2d4d2.
+
+Set the capabilities field of v4l2_requestbuffers and v4l2_create_buffers.
+
+The various mapping modes were easy, but for signaling the request capability
+a new 'supports_requests' bitfield was added to videobuf2-core.h (and set in
+vim2m and vivid). Drivers have to set this bitfield for any queue where
+requests are supported.
+
+Signed-off-by: Hans Verkuil <hansverk@cisco.com>
+Reviewed-by: Tomasz Figa <tfiga@chromium.org>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+
+Minor modifications required on the backport
+---
+ drivers/media/common/videobuf2/videobuf2-v4l2.c | 17 +++++++++++++++++
+ drivers/media/platform/vim2m.c | 1 +
+ drivers/media/platform/vivid/vivid-core.c | 5 +++++
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 4 +++-
+ drivers/media/v4l2-core/v4l2-ioctl.c | 4 ++--
+ include/media/videobuf2-core.h | 2 ++
+ 6 files changed, 30 insertions(+), 3 deletions(-)
+
+--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
++++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
+@@ -482,10 +482,24 @@ int vb2_querybuf(struct vb2_queue *q, st
+ }
+ EXPORT_SYMBOL(vb2_querybuf);
+
++static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
++{
++ *caps = 0;
++ if (q->io_modes & VB2_MMAP)
++ *caps |= V4L2_BUF_CAP_SUPPORTS_MMAP;
++ if (q->io_modes & VB2_USERPTR)
++ *caps |= V4L2_BUF_CAP_SUPPORTS_USERPTR;
++ if (q->io_modes & VB2_DMABUF)
++ *caps |= V4L2_BUF_CAP_SUPPORTS_DMABUF;
++ if (q->supports_requests)
++ *caps |= V4L2_BUF_CAP_SUPPORTS_REQUESTS;
++}
++
+ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
+ {
+ int ret = vb2_verify_memory_type(q, req->memory, req->type);
+
++ fill_buf_caps(q, &req->capabilities);
+ return ret ? ret : vb2_core_reqbufs(q, req->memory, &req->count);
+ }
+ EXPORT_SYMBOL_GPL(vb2_reqbufs);
+@@ -513,6 +527,7 @@ int vb2_create_bufs(struct vb2_queue *q,
+ int ret = vb2_verify_memory_type(q, create->memory, f->type);
+ unsigned i;
+
++ fill_buf_caps(q, &create->capabilities);
+ create->index = q->num_buffers;
+ if (create->count == 0)
+ return ret != -EBUSY ? ret : 0;
+@@ -713,6 +728,7 @@ int vb2_ioctl_reqbufs(struct file *file,
+ struct video_device *vdev = video_devdata(file);
+ int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
+
++ fill_buf_caps(vdev->queue, &p->capabilities);
+ if (res)
+ return res;
+ if (vb2_queue_is_busy(vdev, file))
+@@ -734,6 +750,7 @@ int vb2_ioctl_create_bufs(struct file *f
+ p->format.type);
+
+ p->index = vdev->queue->num_buffers;
++ fill_buf_caps(vdev->queue, &p->capabilities);
+ /*
+ * If count == 0, then just check if memory and type are valid.
+ * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0.
+--- a/drivers/media/platform/vim2m.c
++++ b/drivers/media/platform/vim2m.c
+@@ -841,6 +841,7 @@ static int queue_init(void *priv, struct
+ src_vq->mem_ops = &vb2_vmalloc_memops;
+ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ src_vq->lock = &ctx->dev->dev_mutex;
++ src_vq->supports_requests = true;
+
+ ret = vb2_queue_init(src_vq);
+ if (ret)
+--- a/drivers/media/platform/vivid/vivid-core.c
++++ b/drivers/media/platform/vivid/vivid-core.c
+@@ -1060,6 +1060,7 @@ static int vivid_create_instance(struct
+ q->min_buffers_needed = 2;
+ q->lock = &dev->mutex;
+ q->dev = dev->v4l2_dev.dev;
++ q->supports_requests = true;
+
+ ret = vb2_queue_init(q);
+ if (ret)
+@@ -1080,6 +1081,7 @@ static int vivid_create_instance(struct
+ q->min_buffers_needed = 2;
+ q->lock = &dev->mutex;
+ q->dev = dev->v4l2_dev.dev;
++ q->supports_requests = true;
+
+ ret = vb2_queue_init(q);
+ if (ret)
+@@ -1100,6 +1102,7 @@ static int vivid_create_instance(struct
+ q->min_buffers_needed = 2;
+ q->lock = &dev->mutex;
+ q->dev = dev->v4l2_dev.dev;
++ q->supports_requests = true;
+
+ ret = vb2_queue_init(q);
+ if (ret)
+@@ -1120,6 +1123,7 @@ static int vivid_create_instance(struct
+ q->min_buffers_needed = 2;
+ q->lock = &dev->mutex;
+ q->dev = dev->v4l2_dev.dev;
++ q->supports_requests = true;
+
+ ret = vb2_queue_init(q);
+ if (ret)
+@@ -1139,6 +1143,7 @@ static int vivid_create_instance(struct
+ q->min_buffers_needed = 8;
+ q->lock = &dev->mutex;
+ q->dev = dev->v4l2_dev.dev;
++ q->supports_requests = true;
+
+ ret = vb2_queue_init(q);
+ if (ret)
+--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+@@ -251,7 +251,8 @@ struct v4l2_create_buffers32 {
+ __u32 count;
+ __u32 memory; /* enum v4l2_memory */
+ struct v4l2_format32 format;
+- __u32 reserved[8];
++ __u32 capabilities;
++ __u32 reserved[7];
+ };
+
+ static int __bufsize_v4l2_format(struct v4l2_format32 __user *p32, u32 *size)
+@@ -411,6 +412,7 @@ static int put_v4l2_create32(struct v4l2
+ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
+ copy_in_user(p32, p64,
+ offsetof(struct v4l2_create_buffers32, format)) ||
++ assign_in_user(&p32->capabilities, &p64->capabilities) ||
+ copy_in_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
+ return -EFAULT;
+ return __put_v4l2_format32(&p64->format, &p32->format);
+--- a/drivers/media/v4l2-core/v4l2-ioctl.c
++++ b/drivers/media/v4l2-core/v4l2-ioctl.c
+@@ -1879,7 +1879,7 @@ static int v4l_reqbufs(const struct v4l2
+ if (ret)
+ return ret;
+
+- CLEAR_AFTER_FIELD(p, memory);
++ CLEAR_AFTER_FIELD(p, capabilities);
+
+ return ops->vidioc_reqbufs(file, fh, p);
+ }
+@@ -1920,7 +1920,7 @@ static int v4l_create_bufs(const struct
+ if (ret)
+ return ret;
+
+- CLEAR_AFTER_FIELD(create, format);
++ CLEAR_AFTER_FIELD(create, capabilities);
+
+ v4l_sanitize_format(&create->format);
+
+--- a/include/media/videobuf2-core.h
++++ b/include/media/videobuf2-core.h
+@@ -449,6 +449,7 @@ struct vb2_buf_ops {
+ * @quirk_poll_must_check_waiting_for_buffers: Return %EPOLLERR at poll when QBUF
+ * has not been called. This is a vb1 idiom that has been adopted
+ * also by vb2.
++ * @supports_requests: this queue supports the Request API.
+ * @lock: pointer to a mutex that protects the &struct vb2_queue. The
+ * driver can set this to a mutex to let the v4l2 core serialize
+ * the queuing ioctls. If the driver wants to handle locking
+@@ -516,6 +517,7 @@ struct vb2_queue {
+ unsigned fileio_write_immediately:1;
+ unsigned allow_zero_bytesused:1;
+ unsigned quirk_poll_must_check_waiting_for_buffers:1;
++ unsigned supports_requests:1;
+
+ struct mutex *lock;
+ void *owner;
+++ /dev/null
-From af55660301d90af33724086223cd1c005c6af4ec Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Tue, 2 Jul 2019 17:19:04 +0100
-Subject: [PATCH 694/703] staging: vc-sm-cma: Fix the few remaining coding
- style issues
-
-Fix a few minor checkpatch complaints to make the driver clean
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../staging/vc04_services/vc-sm-cma/vc_sm.c | 6 +-
- .../vc04_services/vc-sm-cma/vc_sm_cma_vchi.c | 128 +++++++++---------
- 2 files changed, 65 insertions(+), 69 deletions(-)
-
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
-@@ -325,7 +325,6 @@ static void vc_sm_release_resource(struc
- buffer->cookie, buffer->dma_addr);
- }
-
--
- /* Free our buffer. Start by removing it from the list */
- mutex_lock(&sm_state->map_lock);
- list_del(&buffer->global_buffer_list);
-@@ -1365,7 +1364,8 @@ static int vc_sm_cma_clean_invalid2(unsi
- }
-
- for (i = 0; i < ioparam.op_count; i++) {
-- const struct vc_sm_cma_ioctl_clean_invalid_block * const op = block + i;
-+ const struct vc_sm_cma_ioctl_clean_invalid_block * const op =
-+ block + i;
-
- if (op->invalidate_mode == VC_SM_CACHE_OP_NOP)
- continue;
-@@ -1637,8 +1637,6 @@ err_remove_misc_dev:
- err_remove_debugfs:
- debugfs_remove_recursive(sm_state->dir_root);
- vc_sm_cma_vchi_stop(&sm_state->sm_handle);
--
-- return;
- }
-
- /* Driver loading. */
---- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma_vchi.c
-@@ -188,79 +188,77 @@ static int vc_sm_cma_vchi_videocore_io(v
- if (svc_use)
- vchi_service_release(instance->vchi_handle[0]);
- svc_use = 0;
-- if (!wait_for_completion_interruptible(&instance->io_cmplt)) {
-- vchi_service_use(instance->vchi_handle[0]);
-- svc_use = 1;
--
-- do {
-- /*
-- * Get new command and move it to response list
-- */
-- mutex_lock(&instance->lock);
-- if (list_empty(&instance->cmd_list)) {
-- /* no more commands to process */
-- mutex_unlock(&instance->lock);
-- break;
-- }
-- cmd =
-- list_first_entry(&instance->cmd_list,
-- struct sm_cmd_rsp_blk,
-- head);
-- list_move(&cmd->head, &instance->rsp_list);
-- cmd->sent = 1;
-- mutex_unlock(&instance->lock);
-
-- /* Send the command */
-- status = bcm2835_vchi_msg_queue(
-- instance->vchi_handle[0],
-- cmd->msg, cmd->length);
-- if (status) {
-- pr_err("%s: failed to queue message (%d)",
-- __func__, status);
-- }
--
-- /* If no reply is needed then we're done */
-- if (!cmd->wait) {
-- mutex_lock(&instance->lock);
-- list_del(&cmd->head);
-- mutex_unlock(&instance->lock);
-- vc_vchi_cmd_delete(instance, cmd);
-- continue;
-- }
--
-- if (status) {
-- complete(&cmd->cmplt);
-- continue;
-- }
--
-- } while (1);
--
-- while (!vchi_msg_peek(instance->vchi_handle[0],
-- (void **)&reply, &reply_len,
-- VCHI_FLAGS_NONE)) {
-- if (reply->trans_id & 0x80000000) {
-- /* Async event or cmd from the VPU */
-- if (instance->vpu_event)
-- instance->vpu_event(
-- instance, reply,
-- reply_len);
-- } else {
-- vc_sm_cma_vchi_rx_ack(instance, cmd,
-- reply, reply_len);
-- }
-+ if (wait_for_completion_interruptible(&instance->io_cmplt))
-+ continue;
-
-- vchi_msg_remove(instance->vchi_handle[0]);
-- }
-+ vchi_service_use(instance->vchi_handle[0]);
-+ svc_use = 1;
-
-- /* Go through the dead list and free them */
-+ do {
-+ /*
-+ * Get new command and move it to response list
-+ */
- mutex_lock(&instance->lock);
-- list_for_each_entry_safe(cmd, cmd_tmp,
-- &instance->dead_list, head) {
-+ if (list_empty(&instance->cmd_list)) {
-+ /* no more commands to process */
-+ mutex_unlock(&instance->lock);
-+ break;
-+ }
-+ cmd = list_first_entry(&instance->cmd_list,
-+ struct sm_cmd_rsp_blk, head);
-+ list_move(&cmd->head, &instance->rsp_list);
-+ cmd->sent = 1;
-+ mutex_unlock(&instance->lock);
-+
-+ /* Send the command */
-+ status =
-+ bcm2835_vchi_msg_queue(instance->vchi_handle[0],
-+ cmd->msg, cmd->length);
-+ if (status) {
-+ pr_err("%s: failed to queue message (%d)",
-+ __func__, status);
-+ }
-+
-+ /* If no reply is needed then we're done */
-+ if (!cmd->wait) {
-+ mutex_lock(&instance->lock);
- list_del(&cmd->head);
-+ mutex_unlock(&instance->lock);
- vc_vchi_cmd_delete(instance, cmd);
-+ continue;
- }
-- mutex_unlock(&instance->lock);
-+
-+ if (status) {
-+ complete(&cmd->cmplt);
-+ continue;
-+ }
-+
-+ } while (1);
-+
-+ while (!vchi_msg_peek(instance->vchi_handle[0], (void **)&reply,
-+ &reply_len, VCHI_FLAGS_NONE)) {
-+ if (reply->trans_id & 0x80000000) {
-+ /* Async event or cmd from the VPU */
-+ if (instance->vpu_event)
-+ instance->vpu_event(instance, reply,
-+ reply_len);
-+ } else {
-+ vc_sm_cma_vchi_rx_ack(instance, cmd, reply,
-+ reply_len);
-+ }
-+
-+ vchi_msg_remove(instance->vchi_handle[0]);
-+ }
-+
-+ /* Go through the dead list and free them */
-+ mutex_lock(&instance->lock);
-+ list_for_each_entry_safe(cmd, cmd_tmp, &instance->dead_list,
-+ head) {
-+ list_del(&cmd->head);
-+ vc_vchi_cmd_delete(instance, cmd);
- }
-+ mutex_unlock(&instance->lock);
- }
-
- return 0;
+++ /dev/null
-From ba55985a050750483553584ebf6b587f4e6b7f91 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Thu, 4 Jul 2019 11:52:43 +0100
-Subject: [PATCH 695/703] configs: Drop MMC_SDHCI_BCM2711 from
- arm64/bcm2711_defconfig
-
-Apparently this is a vestigial setting and should be removed.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- arch/arm64/configs/bcm2711_defconfig | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/arch/arm64/configs/bcm2711_defconfig
-+++ b/arch/arm64/configs/bcm2711_defconfig
-@@ -1031,7 +1031,6 @@ CONFIG_USB_G_HID=m
- CONFIG_USB_G_WEBCAM=m
- CONFIG_MMC=y
- CONFIG_MMC_BLOCK_MINORS=32
--CONFIG_MMC_SDHCI_BCM2711=y
- CONFIG_MMC_BCM2835_MMC=y
- CONFIG_MMC_BCM2835_DMA=y
- CONFIG_MMC_BCM2835_SDHOST=y
--- /dev/null
+From b7f5e21034ac7af2b8ceee726151f4635435694f Mon Sep 17 00:00:00 2001
+From: John Sheu <sheu@chromium.org>
+Date: Thu, 15 Nov 2018 10:57:16 -0500
+Subject: [PATCH 695/725] media: vb2: Allow reqbufs(0) with "in use" MMAP
+ buffers
+
+Upstream commit d644cca50f366cd109845ae92e37c09ed79adf81
+
+Videobuf2 presently does not allow VIDIOC_REQBUFS to destroy outstanding
+buffers if the queue is of type V4L2_MEMORY_MMAP, and if the buffers are
+considered "in use". This is different behavior than for other memory
+types and prevents us from deallocating buffers in following two cases:
+
+1) There are outstanding mmap()ed views on the buffer. However even if
+ we put the buffer in reqbufs(0), there will be remaining references,
+ due to vma .open/close() adjusting vb2 buffer refcount appropriately.
+ This means that the buffer will be in fact freed only when the last
+ mmap()ed view is unmapped.
+
+2) Buffer has been exported as a DMABUF. Refcount of the vb2 buffer
+ is managed properly by VB2 DMABUF ops, i.e. incremented on DMABUF
+ get and decremented on DMABUF release. This means that the buffer
+ will be alive until all importers release it.
+
+Considering both cases above, there does not seem to be any need to
+prevent reqbufs(0) operation, because buffer lifetime is already
+properly managed by both mmap() and DMABUF code paths. Let's remove it
+and allow userspace freeing the queue (and potentially allocating a new
+one) even though old buffers might be still in processing.
+
+To let userspace know that the kernel now supports orphaning buffers
+that are still in use, add a new V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS
+to be set by reqbufs and create_bufs.
+
+[p.zabel@pengutronix.de: added V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS,
+ updated documentation, and added back debug message]
+
+Signed-off-by: John Sheu <sheu@chromium.org>
+Reviewed-by: Pawel Osciak <posciak@chromium.org>
+Signed-off-by: Tomasz Figa <tfiga@chromium.org>
+Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+[hverkuil-cisco@xs4all.nl: added V4L2-BUF-CAP-SUPPORTS-ORPHANED-BUFS ref]
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+---
+ Documentation/media/uapi/v4l/vidioc-reqbufs.rst | 17 ++++++++++++++---
+ drivers/media/common/videobuf2/videobuf2-core.c | 8 +++-----
+ drivers/media/common/videobuf2/videobuf2-v4l2.c | 2 +-
+ include/uapi/linux/videodev2.h | 1 +
+ 4 files changed, 19 insertions(+), 9 deletions(-)
+
+--- a/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
++++ b/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
+@@ -59,9 +59,14 @@ When the I/O method is not supported the
+ code.
+
+ Applications can call :ref:`VIDIOC_REQBUFS` again to change the number of
+-buffers, however this cannot succeed when any buffers are still mapped.
+-A ``count`` value of zero frees all buffers, after aborting or finishing
+-any DMA in progress, an implicit
++buffers. Note that if any buffers are still mapped or exported via DMABUF,
++then :ref:`VIDIOC_REQBUFS` can only succeed if the
++``V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS`` capability is set. Otherwise
++:ref:`VIDIOC_REQBUFS` will return the ``EBUSY`` error code.
++If ``V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS`` is set, then these buffers are
++orphaned and will be freed when they are unmapped or when the exported DMABUF
++fds are closed. A ``count`` value of zero frees or orphans all buffers, after
++aborting or finishing any DMA in progress, an implicit
+ :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>`.
+
+
+@@ -112,6 +117,7 @@ any DMA in progress, an implicit
+ .. _V4L2-BUF-CAP-SUPPORTS-USERPTR:
+ .. _V4L2-BUF-CAP-SUPPORTS-DMABUF:
+ .. _V4L2-BUF-CAP-SUPPORTS-REQUESTS:
++.. _V4L2-BUF-CAP-SUPPORTS-ORPHANED-BUFS:
+
+ .. cssclass:: longtable
+
+@@ -132,6 +138,11 @@ any DMA in progress, an implicit
+ * - ``V4L2_BUF_CAP_SUPPORTS_REQUESTS``
+ - 0x00000008
+ - This buffer type supports :ref:`requests <media-request-api>`.
++ * - ``V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS``
++ - 0x00000010
++ - The kernel allows calling :ref:`VIDIOC_REQBUFS` while buffers are still
++ mapped or exported via DMABUF. These orphaned buffers will be freed
++ when they are unmapped or when the exported DMABUF fds are closed.
+
+ Return Value
+ ============
+--- a/drivers/media/common/videobuf2/videobuf2-core.c
++++ b/drivers/media/common/videobuf2/videobuf2-core.c
+@@ -684,11 +684,9 @@ int vb2_core_reqbufs(struct vb2_queue *q
+ * are not in use and can be freed.
+ */
+ mutex_lock(&q->mmap_lock);
+- if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
+- mutex_unlock(&q->mmap_lock);
+- dprintk(1, "memory in use, cannot free\n");
+- return -EBUSY;
+- }
++ if (debug && q->memory == VB2_MEMORY_MMAP &&
++ __buffers_in_use(q))
++ dprintk(1, "memory in use, orphaning buffers\n");
+
+ /*
+ * Call queue_cancel to clean up any buffers in the PREPARED or
+--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
++++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
+@@ -484,7 +484,7 @@ EXPORT_SYMBOL(vb2_querybuf);
+
+ static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
+ {
+- *caps = 0;
++ *caps = V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS;
+ if (q->io_modes & VB2_MMAP)
+ *caps |= V4L2_BUF_CAP_SUPPORTS_MMAP;
+ if (q->io_modes & VB2_USERPTR)
+--- a/include/uapi/linux/videodev2.h
++++ b/include/uapi/linux/videodev2.h
+@@ -881,6 +881,7 @@ struct v4l2_requestbuffers {
+ #define V4L2_BUF_CAP_SUPPORTS_USERPTR (1 << 1)
+ #define V4L2_BUF_CAP_SUPPORTS_DMABUF (1 << 2)
+ #define V4L2_BUF_CAP_SUPPORTS_REQUESTS (1 << 3)
++#define V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS (1 << 4)
+
+ /**
+ * struct v4l2_plane - plane info for multi-planar buffers
+++ /dev/null
-From 41079f8602ae082b78e33e7d326ff5f57b7d76e8 Mon Sep 17 00:00:00 2001
-From: Dave Stevenson <dave.stevenson@raspberrypi.org>
-Date: Fri, 28 Jun 2019 11:30:49 +0100
-Subject: [PATCH 696/703] Revert "media: vb2: Allow reqbufs(0) with "in use"
- MMAP buffers"
-
-This reverts commit a2c73e18c1f657de6d654f51effa0a94863abbd8.
-An alternative version was accepted upstream. Revert this patch to
-apply that one.
-
-Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
----
- .../media/common/videobuf2/videobuf2-core.c | 23 +++++++++++++++++++
- 1 file changed, 23 insertions(+)
-
---- a/drivers/media/common/videobuf2/videobuf2-core.c
-+++ b/drivers/media/common/videobuf2/videobuf2-core.c
-@@ -554,6 +554,20 @@ bool vb2_buffer_in_use(struct vb2_queue
- }
- EXPORT_SYMBOL(vb2_buffer_in_use);
-
-+/*
-+ * __buffers_in_use() - return true if any buffers on the queue are in use and
-+ * the queue cannot be freed (by the means of REQBUFS(0)) call
-+ */
-+static bool __buffers_in_use(struct vb2_queue *q)
-+{
-+ unsigned int buffer;
-+ for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-+ if (vb2_buffer_in_use(q, q->bufs[buffer]))
-+ return true;
-+ }
-+ return false;
-+}
-+
- void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
- {
- call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
-@@ -665,7 +679,16 @@ int vb2_core_reqbufs(struct vb2_queue *q
-
- if (*count == 0 || q->num_buffers != 0 ||
- (q->memory != VB2_MEMORY_UNKNOWN && q->memory != memory)) {
-+ /*
-+ * We already have buffers allocated, so first check if they
-+ * are not in use and can be freed.
-+ */
- mutex_lock(&q->mmap_lock);
-+ if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
-+ mutex_unlock(&q->mmap_lock);
-+ dprintk(1, "memory in use, cannot free\n");
-+ return -EBUSY;
-+ }
-
- /*
- * Call queue_cancel to clean up any buffers in the PREPARED or
--- /dev/null
+From 21cb98ad5ea375032112a5d7ee92acd4196de5fb Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 5 Jul 2019 09:22:10 +0100
+Subject: [PATCH 696/725] overlays: Add real parameters to the rpi-poe overlay
+
+As a result of being loaded by the POE HAT EEPROM, the rpi-poe overlay
+doesn't expose parameters in the usual way; instead it adds them to
+the base Device Tree, and the user is expected to use "dtparam=..."
+to access them.
+
+To make the documentation correct and to protect users who load the
+overlay explicitly, expecting to be able to use the parameters, add
+real parameters to the overlay as well.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/rpi-poe-overlay.dts | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
+@@ -60,4 +60,11 @@
+ poe_fan_temp1_hyst = <&trip1>,"hysteresis:0";
+ };
+ };
++
++ __overrides__ {
++ poe_fan_temp0 = <&trip0>,"temperature:0";
++ poe_fan_temp0_hyst = <&trip0>,"hysteresis:0";
++ poe_fan_temp1 = <&trip1>,"temperature:0";
++ poe_fan_temp1_hyst = <&trip1>,"hysteresis:0";
++ };
+ };
+++ /dev/null
-From e9ec6de11c358ff3bc389cfa0003544c60f859ef Mon Sep 17 00:00:00 2001
-From: Hans Verkuil <hansverk@cisco.com>
-Date: Thu, 23 Aug 2018 09:56:22 -0400
-Subject: [PATCH 697/703] media: videodev2.h: add new capabilities for buffer
- types
-
-Upstream commit f35f5d72e70e6b91389eb98fcabf43b79f40587f
-
-VIDIOC_REQBUFS and VIDIOC_CREATE_BUFFERS will return capabilities
-telling userspace what the given buffer type is capable of.
-
-Signed-off-by: Hans Verkuil <hansverk@cisco.com>
-Reviewed-by: Tomasz Figa <tfiga@chromium.org>
-Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
-Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
----
- .../media/uapi/v4l/vidioc-create-bufs.rst | 14 ++++++-
- .../media/uapi/v4l/vidioc-reqbufs.rst | 42 ++++++++++++++++++-
- include/uapi/linux/videodev2.h | 13 +++++-
- 3 files changed, 65 insertions(+), 4 deletions(-)
-
---- a/Documentation/media/uapi/v4l/vidioc-create-bufs.rst
-+++ b/Documentation/media/uapi/v4l/vidioc-create-bufs.rst
-@@ -102,7 +102,19 @@ than the number requested.
- - ``format``
- - Filled in by the application, preserved by the driver.
- * - __u32
-- - ``reserved``\ [8]
-+ - ``capabilities``
-+ - Set by the driver. If 0, then the driver doesn't support
-+ capabilities. In that case all you know is that the driver is
-+ guaranteed to support ``V4L2_MEMORY_MMAP`` and *might* support
-+ other :c:type:`v4l2_memory` types. It will not support any others
-+ capabilities. See :ref:`here <v4l2-buf-capabilities>` for a list of the
-+ capabilities.
-+
-+ If you want to just query the capabilities without making any
-+ other changes, then set ``count`` to 0, ``memory`` to
-+ ``V4L2_MEMORY_MMAP`` and ``format.type`` to the buffer type.
-+ * - __u32
-+ - ``reserved``\ [7]
- - A place holder for future extensions. Drivers and applications
- must set the array to zero.
-
---- a/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
-+++ b/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
-@@ -88,10 +88,50 @@ any DMA in progress, an implicit
- ``V4L2_MEMORY_DMABUF`` or ``V4L2_MEMORY_USERPTR``. See
- :c:type:`v4l2_memory`.
- * - __u32
-- - ``reserved``\ [2]
-+ - ``capabilities``
-+ - Set by the driver. If 0, then the driver doesn't support
-+ capabilities. In that case all you know is that the driver is
-+ guaranteed to support ``V4L2_MEMORY_MMAP`` and *might* support
-+ other :c:type:`v4l2_memory` types. It will not support any others
-+ capabilities.
-+
-+ If you want to query the capabilities with a minimum of side-effects,
-+ then this can be called with ``count`` set to 0, ``memory`` set to
-+ ``V4L2_MEMORY_MMAP`` and ``type`` set to the buffer type. This will
-+ free any previously allocated buffers, so this is typically something
-+ that will be done at the start of the application.
-+ * - __u32
-+ - ``reserved``\ [1]
- - A place holder for future extensions. Drivers and applications
- must set the array to zero.
-
-+.. tabularcolumns:: |p{6.1cm}|p{2.2cm}|p{8.7cm}|
-+
-+.. _v4l2-buf-capabilities:
-+.. _V4L2-BUF-CAP-SUPPORTS-MMAP:
-+.. _V4L2-BUF-CAP-SUPPORTS-USERPTR:
-+.. _V4L2-BUF-CAP-SUPPORTS-DMABUF:
-+.. _V4L2-BUF-CAP-SUPPORTS-REQUESTS:
-+
-+.. cssclass:: longtable
-+
-+.. flat-table:: V4L2 Buffer Capabilities Flags
-+ :header-rows: 0
-+ :stub-columns: 0
-+ :widths: 3 1 4
-+
-+ * - ``V4L2_BUF_CAP_SUPPORTS_MMAP``
-+ - 0x00000001
-+ - This buffer type supports the ``V4L2_MEMORY_MMAP`` streaming mode.
-+ * - ``V4L2_BUF_CAP_SUPPORTS_USERPTR``
-+ - 0x00000002
-+ - This buffer type supports the ``V4L2_MEMORY_USERPTR`` streaming mode.
-+ * - ``V4L2_BUF_CAP_SUPPORTS_DMABUF``
-+ - 0x00000004
-+ - This buffer type supports the ``V4L2_MEMORY_DMABUF`` streaming mode.
-+ * - ``V4L2_BUF_CAP_SUPPORTS_REQUESTS``
-+ - 0x00000008
-+ - This buffer type supports :ref:`requests <media-request-api>`.
-
- Return Value
- ============
---- a/include/uapi/linux/videodev2.h
-+++ b/include/uapi/linux/videodev2.h
-@@ -872,9 +872,16 @@ struct v4l2_requestbuffers {
- __u32 count;
- __u32 type; /* enum v4l2_buf_type */
- __u32 memory; /* enum v4l2_memory */
-- __u32 reserved[2];
-+ __u32 capabilities;
-+ __u32 reserved[1];
- };
-
-+/* capabilities for struct v4l2_requestbuffers and v4l2_create_buffers */
-+#define V4L2_BUF_CAP_SUPPORTS_MMAP (1 << 0)
-+#define V4L2_BUF_CAP_SUPPORTS_USERPTR (1 << 1)
-+#define V4L2_BUF_CAP_SUPPORTS_DMABUF (1 << 2)
-+#define V4L2_BUF_CAP_SUPPORTS_REQUESTS (1 << 3)
-+
- /**
- * struct v4l2_plane - plane info for multi-planar buffers
- * @bytesused: number of bytes occupied by data in the plane (payload)
-@@ -2318,6 +2325,7 @@ struct v4l2_dbg_chip_info {
- * return: number of created buffers
- * @memory: enum v4l2_memory; buffer memory type
- * @format: frame format, for which buffers are requested
-+ * @capabilities: capabilities of this buffer type.
- * @reserved: future extensions
- */
- struct v4l2_create_buffers {
-@@ -2325,7 +2333,8 @@ struct v4l2_create_buffers {
- __u32 count;
- __u32 memory;
- struct v4l2_format format;
-- __u32 reserved[8];
-+ __u32 capabilities;
-+ __u32 reserved[7];
- };
-
- /*
--- /dev/null
+From 75036ddc7b3ea2f1366cef40491d690396f34bdc Mon Sep 17 00:00:00 2001
+From: Phil Elwell <pelwell@users.noreply.github.com>
+Date: Fri, 5 Jul 2019 14:49:22 +0100
+Subject: [PATCH 697/725] overlays: Rename pi3- overlays to be less
+ model-specific (#3052)
+
+Rename the various pi3- overlays to be more generic, listing
+the devices they apply to in the README. The original names are
+retained for backwards compatibility as files that just include
+the new versions - the README marks them as being deprecated.
+
+See: https://github.com/raspberrypi/firmware/issues/1174
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/Makefile | 4 +
+ arch/arm/boot/dts/overlays/README | 97 ++++++++++++-------
+ .../arm/boot/dts/overlays/act-led-overlay.dts | 27 ++++++
+ .../boot/dts/overlays/disable-bt-overlay.dts | 55 +++++++++++
+ .../dts/overlays/disable-wifi-overlay.dts | 20 ++++
+ .../boot/dts/overlays/miniuart-bt-overlay.dts | 74 ++++++++++++++
+ .../boot/dts/overlays/pi3-act-led-overlay.dts | 28 +-----
+ .../dts/overlays/pi3-disable-bt-overlay.dts | 56 +----------
+ .../dts/overlays/pi3-disable-wifi-overlay.dts | 21 +---
+ .../dts/overlays/pi3-miniuart-bt-overlay.dts | 75 +-------------
+ 10 files changed, 246 insertions(+), 211 deletions(-)
+ create mode 100644 arch/arm/boot/dts/overlays/act-led-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/disable-bt-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/disable-wifi-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/miniuart-bt-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -1,6 +1,7 @@
+ # Overlays for the Raspberry Pi platform
+
+ dtbo-$(CONFIG_ARCH_BCM2835) += \
++ act-led.dtbo \
+ adau1977-adc.dtbo \
+ adau7002-simple.dtbo \
+ ads1015.dtbo \
+@@ -26,6 +27,8 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ dht11.dtbo \
+ dionaudio-loco.dtbo \
+ dionaudio-loco-v2.dtbo \
++ disable-bt.dtbo \
++ disable-wifi.dtbo \
+ dpi18.dtbo \
+ dpi24.dtbo \
+ draws.dtbo \
+@@ -91,6 +94,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ media-center.dtbo \
+ midi-uart0.dtbo \
+ midi-uart1.dtbo \
++ miniuart-bt.dtbo \
+ mmc.dtbo \
+ mpu6050.dtbo \
+ mz61581.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -180,14 +180,16 @@ Params:
+
+ act_led_activelow Set to "on" to invert the sense of the LED
+ (default "off")
+- N.B. For Pi3 see pi3-act-led overlay.
++ N.B. For Pi 3B, 3B+, 3A+ and 4B, use the act-led
++ overlay.
+
+ act_led_gpio Set which GPIO to use for the activity LED
+ (in case you want to connect it to an external
+ device)
+ (default "16" on a non-Plus board, "47" on a
+ Plus or Pi 2)
+- N.B. For Pi3 see pi3-act-led overlay.
++ N.B. For Pi 3B, 3B+, 3A+ and 4B, use the act-led
++ overlay.
+
+ pwr_led_trigger
+ pwr_led_activelow
+@@ -205,6 +207,23 @@ Params:
+ and the other i2c baudrate parameters.
+
+
++Name: act-led
++Info: Pi 3B, 3B+, 3A+ and 4B use a GPIO expander to drive the LEDs which can
++ only be accessed from the VPU. There is a special driver for this with a
++ separate DT node, which has the unfortunate consequence of breaking the
++ act_led_gpio and act_led_activelow dtparams.
++ This overlay changes the GPIO controller back to the standard one and
++ restores the dtparams.
++Load: dtoverlay=act-led,<param>=<val>
++Params: activelow Set to "on" to invert the sense of the LED
++ (default "off")
++
++ gpio Set which GPIO to use for the activity LED
++ (in case you want to connect it to an external
++ device)
++ REQUIRED
++
++
+ Name: adau1977-adc
+ Info: Overlay for activation of ADAU1977 ADC codec over I2C for control
+ and I2S for data.
+@@ -509,6 +528,21 @@ Params: 24db_digital_gain Allow ga
+ that does not result in clipping/distortion!)
+
+
++Name: disable-bt
++Info: Disable onboard Bluetooth on Pi 3B, 3B+, 3A+, 4B and Zero W, restoring
++ UART0/ttyAMA0 over GPIOs 14 & 15.
++ N.B. To disable the systemd service that initialises the modem so it
++ doesn't use the UART, use 'sudo systemctl disable hciuart'.
++Load: dtoverlay=disable-bt
++Params: <None>
++
++
++Name: disable-wifi
++Info: Disable onboard WiFi on Pi 3B, 3B+, 3A+, 4B and Zero W.
++Load: dtoverlay=disable-wifi
++Params: <None>
++
++
+ 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
+@@ -1447,6 +1481,20 @@ Load: dtoverlay=midi-uart1
+ Params: <None>
+
+
++Name: miniuart-bt
++Info: Switch the onboard Bluetooth function on Pi 3B, 3B+, 3A+, 4B and Zero W
++ to use the mini-UART (ttyS0) and restore UART0/ttyAMA0 over GPIOs 14 &
++ 15. Note that this may reduce the maximum usable baudrate.
++ N.B. It is also necessary to edit /lib/systemd/system/hciuart.service
++ and replace ttyAMA0 with ttyS0, unless using Raspbian or another
++ distribution with udev rules that create /dev/serial0 and /dev/serial1,
++ in which case use /dev/serial1 instead because it will always be
++ correct. Furthermore, you must also set core_freq and core_freq_min to
++ the same value in config.txt or the miniuart will not work.
++Load: dtoverlay=miniuart-bt
++Params: <None>
++
++
+ Name: mmc
+ Info: Selects the bcm2835-mmc SD/MMC driver, optionally with overclock
+ Load: dtoverlay=mmc,<param>=<val>
+@@ -1509,48 +1557,27 @@ Params: panel Display
+
+
+ Name: pi3-act-led
+-Info: Pi3 uses a GPIO expander to drive the LEDs which can only be accessed
+- from the VPU. There is a special driver for this with a separate DT
+- node, which has the unfortunate consequence of breaking the
+- act_led_gpio and act_led_activelow dtparams.
+- This overlay changes the GPIO controller back to the standard one and
+- restores the dtparams.
+-Load: dtoverlay=pi3-act-led,<param>=<val>
+-Params: activelow Set to "on" to invert the sense of the LED
+- (default "off")
+-
+- gpio Set which GPIO to use for the activity LED
+- (in case you want to connect it to an external
+- device)
+- REQUIRED
++Info: This overlay has been renamed act-led, keeping pi3-act-led as an alias
++ for backwards compatibility.
++Load: <Deprecated>
+
+
+ Name: pi3-disable-bt
+-Info: Disable Pi3 Bluetooth and restore UART0/ttyAMA0 over GPIOs 14 & 15
+- N.B. To disable the systemd service that initialises the modem so it
+- doesn't use the UART, use 'sudo systemctl disable hciuart'.
+-Load: dtoverlay=pi3-disable-bt
+-Params: <None>
++Info: This overlay has been renamed disable-bt, keeping pi3-disable-bt as an
++ alias for backwards compatibility.
++Load: <Deprecated>
+
+
+ Name: pi3-disable-wifi
+-Info: Disable Pi3 onboard WiFi
+-Load: dtoverlay=pi3-disable-wifi
+-Params: <None>
++Info: This overlay has been renamed disable-wifi, keeping pi3-disable-wifi as
++ an alias for backwards compatibility.
++Load: <Deprecated>
+
+
+ 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
+- usable baudrate.
+- N.B. It is also necessary to edit /lib/systemd/system/hciuart.service
+- and replace ttyAMA0 with ttyS0, unless you have a system with udev rules
+- that create /dev/serial0 and /dev/serial1, in which case use
+- /dev/serial1 instead because it will always be correct. Furthermore,
+- you must also set core_freq=250 in config.txt or the miniuart will not
+- work.
+-Load: dtoverlay=pi3-miniuart-bt
+-Params: <None>
++Info: This overlay has been renamed miniuart-bt, keeping pi3-miniuart-bt as
++ an alias for backwards compatibility.
++Load: <Deprecated>
+
+
+ Name: pibell
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/act-led-overlay.dts
+@@ -0,0 +1,27 @@
++/dts-v1/;
++/plugin/;
++
++/* Pi3 uses a GPIO expander to drive the LEDs which can only be accessed
++ from the VPU. There is a special driver for this with a separate DT node,
++ which has the unfortunate consequence of breaking the act_led_gpio and
++ act_led_activelow dtparams.
++
++ This overlay changes the GPIO controller back to the standard one and
++ restores the dtparams.
++*/
++
++/{
++ compatible = "brcm,bcm2835";
++
++ fragment@0 {
++ target = <&act_led>;
++ frag0: __overlay__ {
++ gpios = <&gpio 0 0>;
++ };
++ };
++
++ __overrides__ {
++ gpio = <&frag0>,"gpios:4";
++ activelow = <&frag0>,"gpios:8";
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/disable-bt-overlay.dts
+@@ -0,0 +1,55 @@
++/dts-v1/;
++/plugin/;
++
++/* Disable Bluetooth and restore UART0/ttyAMA0 over GPIOs 14 & 15.
++ To disable the systemd service that initialises the modem so it doesn't use
++ the UART:
++
++ sudo systemctl disable hciuart
++*/
++
++/{
++ compatible = "brcm,bcm2835";
++
++ fragment@0 {
++ target = <&uart1>;
++ __overlay__ {
++ status = "disabled";
++ };
++ };
++
++ fragment@1 {
++ target = <&uart0>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart0_pins>;
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&uart0_pins>;
++ __overlay__ {
++ brcm,pins;
++ brcm,function;
++ brcm,pull;
++ };
++ };
++
++ fragment@3 {
++ target = <&bt_pins>;
++ __overlay__ {
++ brcm,pins;
++ brcm,function;
++ brcm,pull;
++ };
++ };
++
++ fragment@4 {
++ target-path = "/aliases";
++ __overlay__ {
++ serial0 = "/soc/serial@7e201000";
++ serial1 = "/soc/serial@7e215040";
++ };
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/disable-wifi-overlay.dts
+@@ -0,0 +1,20 @@
++/dts-v1/;
++/plugin/;
++
++/{
++ compatible = "brcm,bcm2835";
++
++ fragment@0 {
++ target = <&mmc>;
++ __overlay__ {
++ status = "disabled";
++ };
++ };
++
++ fragment@1 {
++ target = <&mmcnr>;
++ __overlay__ {
++ status = "disabled";
++ };
++ };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/miniuart-bt-overlay.dts
+@@ -0,0 +1,74 @@
++/dts-v1/;
++/plugin/;
++
++/* 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
++ usable baudrate.
++
++ It is also necessary to edit /lib/systemd/system/hciuart.service and
++ replace ttyAMA0 with ttyS0, unless you have a system with udev rules
++ that create /dev/serial0 and /dev/serial1, in which case use /dev/serial1
++ instead because it will always be correct.
++
++ If cmdline.txt uses the alias serial0 to refer to the user-accessable port
++ then the firmware will replace with the appropriate port whether or not
++ this overlay is used.
++*/
++
++/{
++ compatible = "brcm,bcm2835";
++
++ fragment@0 {
++ target = <&uart0>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart0_pins>;
++ status = "okay";
++ };
++ };
++
++ fragment@1 {
++ target = <&uart1>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart1_pins &bt_pins &fake_bt_cts>;
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&uart0_pins>;
++ __overlay__ {
++ brcm,pins;
++ brcm,function;
++ brcm,pull;
++ };
++ };
++
++ fragment@3 {
++ target = <&uart1_pins>;
++ __overlay__ {
++ brcm,pins = <32 33>;
++ brcm,function = <2>; /* alt5=UART1 */
++ brcm,pull = <0 2>;
++ };
++ };
++
++ fragment@4 {
++ target = <&gpio>;
++ __overlay__ {
++ fake_bt_cts: fake_bt_cts {
++ brcm,pins = <31>;
++ brcm,function = <1>; /* output */
++ };
++ };
++ };
++
++ fragment@5 {
++ target-path = "/aliases";
++ __overlay__ {
++ serial0 = "/soc/serial@7e201000";
++ serial1 = "/soc/serial@7e215040";
++ };
++ };
++};
+--- a/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
+@@ -1,27 +1 @@
+-/dts-v1/;
+-/plugin/;
+-
+-/* Pi3 uses a GPIO expander to drive the LEDs which can only be accessed
+- from the VPU. There is a special driver for this with a separate DT node,
+- which has the unfortunate consequence of breaking the act_led_gpio and
+- act_led_activelow dtparams.
+-
+- This overlay changes the GPIO controller back to the standard one and
+- restores the dtparams.
+-*/
+-
+-/{
+- compatible = "brcm,bcm2835";
+-
+- fragment@0 {
+- target = <&act_led>;
+- frag0: __overlay__ {
+- gpios = <&gpio 0 0>;
+- };
+- };
+-
+- __overrides__ {
+- gpio = <&frag0>,"gpios:4";
+- activelow = <&frag0>,"gpios:8";
+- };
+-};
++#include "act-led-overlay.dts"
+--- a/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
+@@ -1,55 +1 @@
+-/dts-v1/;
+-/plugin/;
+-
+-/* Disable Bluetooth and restore UART0/ttyAMA0 over GPIOs 14 & 15.
+- To disable the systemd service that initialises the modem so it doesn't use
+- the UART:
+-
+- sudo systemctl disable hciuart
+-*/
+-
+-/{
+- compatible = "brcm,bcm2835";
+-
+- fragment@0 {
+- target = <&uart1>;
+- __overlay__ {
+- status = "disabled";
+- };
+- };
+-
+- fragment@1 {
+- target = <&uart0>;
+- __overlay__ {
+- pinctrl-names = "default";
+- pinctrl-0 = <&uart0_pins>;
+- status = "okay";
+- };
+- };
+-
+- fragment@2 {
+- target = <&uart0_pins>;
+- __overlay__ {
+- brcm,pins;
+- brcm,function;
+- brcm,pull;
+- };
+- };
+-
+- fragment@3 {
+- target = <&bt_pins>;
+- __overlay__ {
+- brcm,pins;
+- brcm,function;
+- brcm,pull;
+- };
+- };
+-
+- fragment@4 {
+- target-path = "/aliases";
+- __overlay__ {
+- serial0 = "/soc/serial@7e201000";
+- serial1 = "/soc/serial@7e215040";
+- };
+- };
+-};
++#include "disable-bt-overlay.dts"
+--- a/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
+@@ -1,20 +1 @@
+-/dts-v1/;
+-/plugin/;
+-
+-/{
+- compatible = "brcm,bcm2835";
+-
+- fragment@0 {
+- target = <&mmc>;
+- __overlay__ {
+- status = "disabled";
+- };
+- };
+-
+- fragment@1 {
+- target = <&mmcnr>;
+- __overlay__ {
+- status = "disabled";
+- };
+- };
+-};
++#include "disable-wifi-overlay.dts"
+--- a/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
++++ b/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
+@@ -1,74 +1 @@
+-/dts-v1/;
+-/plugin/;
+-
+-/* 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
+- usable baudrate.
+-
+- It is also necessary to edit /lib/systemd/system/hciuart.service and
+- replace ttyAMA0 with ttyS0, unless you have a system with udev rules
+- that create /dev/serial0 and /dev/serial1, in which case use /dev/serial1
+- instead because it will always be correct.
+-
+- If cmdline.txt uses the alias serial0 to refer to the user-accessable port
+- then the firmware will replace with the appropriate port whether or not
+- this overlay is used.
+-*/
+-
+-/{
+- compatible = "brcm,bcm2835";
+-
+- fragment@0 {
+- target = <&uart0>;
+- __overlay__ {
+- pinctrl-names = "default";
+- pinctrl-0 = <&uart0_pins>;
+- status = "okay";
+- };
+- };
+-
+- fragment@1 {
+- target = <&uart1>;
+- __overlay__ {
+- pinctrl-names = "default";
+- pinctrl-0 = <&uart1_pins &bt_pins &fake_bt_cts>;
+- status = "okay";
+- };
+- };
+-
+- fragment@2 {
+- target = <&uart0_pins>;
+- __overlay__ {
+- brcm,pins;
+- brcm,function;
+- brcm,pull;
+- };
+- };
+-
+- fragment@3 {
+- target = <&uart1_pins>;
+- __overlay__ {
+- brcm,pins = <32 33>;
+- brcm,function = <2>; /* alt5=UART1 */
+- brcm,pull = <0 2>;
+- };
+- };
+-
+- fragment@4 {
+- target = <&gpio>;
+- __overlay__ {
+- fake_bt_cts: fake_bt_cts {
+- brcm,pins = <31>;
+- brcm,function = <1>; /* output */
+- };
+- };
+- };
+-
+- fragment@5 {
+- target-path = "/aliases";
+- __overlay__ {
+- serial0 = "/soc/serial@7e201000";
+- serial1 = "/soc/serial@7e215040";
+- };
+- };
+-};
++#include "miniuart-bt-overlay.dts"
--- /dev/null
+From bd66036c354e430b73ac9c0113ad6a0a787d66c1 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Fri, 21 Jun 2019 03:52:49 -0700
+Subject: [PATCH 698/725] i2c: bcm2835: Move IRQ request after clock code in
+ probe
+
+Commit 4a5cfa39465cad25dd736d7ceba8a5d32eea4ecc upstream.
+
+If any of the clock code in the probe fails and returns, the IRQ
+will not be freed. Moving the IRQ request to last allows it to
+be freed on any errors further up in the probe function. devm_
+calls can apparently not be used because there are some potential
+race conditions that will arise.
+
+Fixes: bebff81fb8b9 ("i2c: bcm2835: Model Divider in CCF")
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Acked-by: Stefan Wahren <wahrenst@gmx.net>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 28 ++++++++++++++--------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -521,20 +521,6 @@ static int bcm2835_i2c_probe(struct plat
+ if (IS_ERR(i2c_dev->regs))
+ return PTR_ERR(i2c_dev->regs);
+
+- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+- if (!irq) {
+- dev_err(&pdev->dev, "No IRQ resource\n");
+- return -ENODEV;
+- }
+- i2c_dev->irq = irq->start;
+-
+- ret = request_irq(i2c_dev->irq, bcm2835_i2c_isr, IRQF_SHARED,
+- dev_name(&pdev->dev), i2c_dev);
+- if (ret) {
+- dev_err(&pdev->dev, "Could not request IRQ\n");
+- return -ENODEV;
+- }
+-
+ mclk_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
+
+ bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk_name, i2c_dev);
+@@ -564,6 +550,20 @@ static int bcm2835_i2c_probe(struct plat
+ return ret;
+ }
+
++ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++ if (!irq) {
++ dev_err(&pdev->dev, "No IRQ resource\n");
++ return -ENODEV;
++ }
++ i2c_dev->irq = irq->start;
++
++ ret = request_irq(i2c_dev->irq, bcm2835_i2c_isr, IRQF_SHARED,
++ dev_name(&pdev->dev), i2c_dev);
++ if (ret) {
++ dev_err(&pdev->dev, "Could not request IRQ\n");
++ return -ENODEV;
++ }
++
+ adap = &i2c_dev->adapter;
+ i2c_set_adapdata(adap, i2c_dev);
+ adap->owner = THIS_MODULE;
+++ /dev/null
-From af748ce92996933030288a0f85ca4775ad71edb0 Mon Sep 17 00:00:00 2001
-From: Hans Verkuil <hansverk@cisco.com>
-Date: Thu, 23 Aug 2018 10:18:35 -0400
-Subject: [PATCH 698/703] media: vb2: set reqbufs/create_bufs capabilities
-
-Upstream commit e5079cf11373e4cc98be8b1072aece429eb2d4d2.
-
-Set the capabilities field of v4l2_requestbuffers and v4l2_create_buffers.
-
-The various mapping modes were easy, but for signaling the request capability
-a new 'supports_requests' bitfield was added to videobuf2-core.h (and set in
-vim2m and vivid). Drivers have to set this bitfield for any queue where
-requests are supported.
-
-Signed-off-by: Hans Verkuil <hansverk@cisco.com>
-Reviewed-by: Tomasz Figa <tfiga@chromium.org>
-Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
-Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
-
-Minor modifications required on the backport
----
- drivers/media/common/videobuf2/videobuf2-v4l2.c | 17 +++++++++++++++++
- drivers/media/platform/vim2m.c | 1 +
- drivers/media/platform/vivid/vivid-core.c | 5 +++++
- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 4 +++-
- drivers/media/v4l2-core/v4l2-ioctl.c | 4 ++--
- include/media/videobuf2-core.h | 2 ++
- 6 files changed, 30 insertions(+), 3 deletions(-)
-
---- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
-+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
-@@ -482,10 +482,24 @@ int vb2_querybuf(struct vb2_queue *q, st
- }
- EXPORT_SYMBOL(vb2_querybuf);
-
-+static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
-+{
-+ *caps = 0;
-+ if (q->io_modes & VB2_MMAP)
-+ *caps |= V4L2_BUF_CAP_SUPPORTS_MMAP;
-+ if (q->io_modes & VB2_USERPTR)
-+ *caps |= V4L2_BUF_CAP_SUPPORTS_USERPTR;
-+ if (q->io_modes & VB2_DMABUF)
-+ *caps |= V4L2_BUF_CAP_SUPPORTS_DMABUF;
-+ if (q->supports_requests)
-+ *caps |= V4L2_BUF_CAP_SUPPORTS_REQUESTS;
-+}
-+
- int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
- {
- int ret = vb2_verify_memory_type(q, req->memory, req->type);
-
-+ fill_buf_caps(q, &req->capabilities);
- return ret ? ret : vb2_core_reqbufs(q, req->memory, &req->count);
- }
- EXPORT_SYMBOL_GPL(vb2_reqbufs);
-@@ -513,6 +527,7 @@ int vb2_create_bufs(struct vb2_queue *q,
- int ret = vb2_verify_memory_type(q, create->memory, f->type);
- unsigned i;
-
-+ fill_buf_caps(q, &create->capabilities);
- create->index = q->num_buffers;
- if (create->count == 0)
- return ret != -EBUSY ? ret : 0;
-@@ -713,6 +728,7 @@ int vb2_ioctl_reqbufs(struct file *file,
- struct video_device *vdev = video_devdata(file);
- int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
-
-+ fill_buf_caps(vdev->queue, &p->capabilities);
- if (res)
- return res;
- if (vb2_queue_is_busy(vdev, file))
-@@ -734,6 +750,7 @@ int vb2_ioctl_create_bufs(struct file *f
- p->format.type);
-
- p->index = vdev->queue->num_buffers;
-+ fill_buf_caps(vdev->queue, &p->capabilities);
- /*
- * If count == 0, then just check if memory and type are valid.
- * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0.
---- a/drivers/media/platform/vim2m.c
-+++ b/drivers/media/platform/vim2m.c
-@@ -841,6 +841,7 @@ static int queue_init(void *priv, struct
- src_vq->mem_ops = &vb2_vmalloc_memops;
- src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
- src_vq->lock = &ctx->dev->dev_mutex;
-+ src_vq->supports_requests = true;
-
- ret = vb2_queue_init(src_vq);
- if (ret)
---- a/drivers/media/platform/vivid/vivid-core.c
-+++ b/drivers/media/platform/vivid/vivid-core.c
-@@ -1060,6 +1060,7 @@ static int vivid_create_instance(struct
- q->min_buffers_needed = 2;
- q->lock = &dev->mutex;
- q->dev = dev->v4l2_dev.dev;
-+ q->supports_requests = true;
-
- ret = vb2_queue_init(q);
- if (ret)
-@@ -1080,6 +1081,7 @@ static int vivid_create_instance(struct
- q->min_buffers_needed = 2;
- q->lock = &dev->mutex;
- q->dev = dev->v4l2_dev.dev;
-+ q->supports_requests = true;
-
- ret = vb2_queue_init(q);
- if (ret)
-@@ -1100,6 +1102,7 @@ static int vivid_create_instance(struct
- q->min_buffers_needed = 2;
- q->lock = &dev->mutex;
- q->dev = dev->v4l2_dev.dev;
-+ q->supports_requests = true;
-
- ret = vb2_queue_init(q);
- if (ret)
-@@ -1120,6 +1123,7 @@ static int vivid_create_instance(struct
- q->min_buffers_needed = 2;
- q->lock = &dev->mutex;
- q->dev = dev->v4l2_dev.dev;
-+ q->supports_requests = true;
-
- ret = vb2_queue_init(q);
- if (ret)
-@@ -1139,6 +1143,7 @@ static int vivid_create_instance(struct
- q->min_buffers_needed = 8;
- q->lock = &dev->mutex;
- q->dev = dev->v4l2_dev.dev;
-+ q->supports_requests = true;
-
- ret = vb2_queue_init(q);
- if (ret)
---- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
-+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
-@@ -251,7 +251,8 @@ struct v4l2_create_buffers32 {
- __u32 count;
- __u32 memory; /* enum v4l2_memory */
- struct v4l2_format32 format;
-- __u32 reserved[8];
-+ __u32 capabilities;
-+ __u32 reserved[7];
- };
-
- static int __bufsize_v4l2_format(struct v4l2_format32 __user *p32, u32 *size)
-@@ -411,6 +412,7 @@ static int put_v4l2_create32(struct v4l2
- if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
- copy_in_user(p32, p64,
- offsetof(struct v4l2_create_buffers32, format)) ||
-+ assign_in_user(&p32->capabilities, &p64->capabilities) ||
- copy_in_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
- return -EFAULT;
- return __put_v4l2_format32(&p64->format, &p32->format);
---- a/drivers/media/v4l2-core/v4l2-ioctl.c
-+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
-@@ -1879,7 +1879,7 @@ static int v4l_reqbufs(const struct v4l2
- if (ret)
- return ret;
-
-- CLEAR_AFTER_FIELD(p, memory);
-+ CLEAR_AFTER_FIELD(p, capabilities);
-
- return ops->vidioc_reqbufs(file, fh, p);
- }
-@@ -1920,7 +1920,7 @@ static int v4l_create_bufs(const struct
- if (ret)
- return ret;
-
-- CLEAR_AFTER_FIELD(create, format);
-+ CLEAR_AFTER_FIELD(create, capabilities);
-
- v4l_sanitize_format(&create->format);
-
---- a/include/media/videobuf2-core.h
-+++ b/include/media/videobuf2-core.h
-@@ -449,6 +449,7 @@ struct vb2_buf_ops {
- * @quirk_poll_must_check_waiting_for_buffers: Return %EPOLLERR at poll when QBUF
- * has not been called. This is a vb1 idiom that has been adopted
- * also by vb2.
-+ * @supports_requests: this queue supports the Request API.
- * @lock: pointer to a mutex that protects the &struct vb2_queue. The
- * driver can set this to a mutex to let the v4l2 core serialize
- * the queuing ioctls. If the driver wants to handle locking
-@@ -516,6 +517,7 @@ struct vb2_queue {
- unsigned fileio_write_immediately:1;
- unsigned allow_zero_bytesused:1;
- unsigned quirk_poll_must_check_waiting_for_buffers:1;
-+ unsigned supports_requests:1;
-
- struct mutex *lock;
- void *owner;
--- /dev/null
+From 7da0d7cd3ee9b9e178873f380c47dda170fed67e Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Fri, 21 Jun 2019 03:52:50 -0700
+Subject: [PATCH 699/725] i2c: bcm2835: Ensure clock exists when probing
+
+Commit 9de93b04df16b055824e3f1f13fedb90fbcf2e4f upstream.
+
+Probe function fails to recognize that upstream clock actually
+doesn't yet exist because clock driver has not been initialized.
+Actually try to go get the clock and test for its existence
+before trying to set up a downstream clock based upon it.
+
+This fixes a bug that causes the i2c driver not to work with
+monolithic kernels.
+
+Fixes: bebff81fb8b9 ("i2c: bcm2835: Model Divider in CCF")
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+Acked-by: Stefan Wahren <wahrenst@gmx.net>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -244,15 +244,18 @@ static const struct clk_ops clk_bcm2835_
+ };
+
+ static struct clk *bcm2835_i2c_register_div(struct device *dev,
+- const char *mclk_name,
++ struct clk *mclk,
+ struct bcm2835_i2c_dev *i2c_dev)
+ {
+ struct clk_init_data init;
+ struct clk_bcm2835_i2c *priv;
+ char name[32];
++ const char *mclk_name;
+
+ snprintf(name, sizeof(name), "%s_div", dev_name(dev));
+
++ mclk_name = __clk_get_name(mclk);
++
+ init.ops = &clk_bcm2835_i2c_ops;
+ init.name = name;
+ init.parent_names = (const char* []) { mclk_name };
+@@ -505,8 +508,8 @@ static int bcm2835_i2c_probe(struct plat
+ struct resource *mem, *irq;
+ int ret;
+ struct i2c_adapter *adap;
+- const char *mclk_name;
+ struct clk *bus_clk;
++ struct clk *mclk;
+ u32 bus_clk_rate;
+
+ i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
+@@ -521,9 +524,14 @@ static int bcm2835_i2c_probe(struct plat
+ if (IS_ERR(i2c_dev->regs))
+ return PTR_ERR(i2c_dev->regs);
+
+- mclk_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
++ mclk = devm_clk_get(&pdev->dev, NULL);
++ if (IS_ERR(mclk)) {
++ if (PTR_ERR(mclk) != -EPROBE_DEFER)
++ dev_err(&pdev->dev, "Could not get clock\n");
++ return PTR_ERR(mclk);
++ }
+
+- bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk_name, i2c_dev);
++ bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev);
+
+ if (IS_ERR(bus_clk)) {
+ dev_err(&pdev->dev, "Could not register clock\n");
+++ /dev/null
-From b0102490b31330eb694a7956e1874e172ad07ec1 Mon Sep 17 00:00:00 2001
-From: John Sheu <sheu@chromium.org>
-Date: Thu, 15 Nov 2018 10:57:16 -0500
-Subject: [PATCH 699/703] media: vb2: Allow reqbufs(0) with "in use" MMAP
- buffers
-
-Upstream commit d644cca50f366cd109845ae92e37c09ed79adf81
-
-Videobuf2 presently does not allow VIDIOC_REQBUFS to destroy outstanding
-buffers if the queue is of type V4L2_MEMORY_MMAP, and if the buffers are
-considered "in use". This is different behavior than for other memory
-types and prevents us from deallocating buffers in following two cases:
-
-1) There are outstanding mmap()ed views on the buffer. However even if
- we put the buffer in reqbufs(0), there will be remaining references,
- due to vma .open/close() adjusting vb2 buffer refcount appropriately.
- This means that the buffer will be in fact freed only when the last
- mmap()ed view is unmapped.
-
-2) Buffer has been exported as a DMABUF. Refcount of the vb2 buffer
- is managed properly by VB2 DMABUF ops, i.e. incremented on DMABUF
- get and decremented on DMABUF release. This means that the buffer
- will be alive until all importers release it.
-
-Considering both cases above, there does not seem to be any need to
-prevent reqbufs(0) operation, because buffer lifetime is already
-properly managed by both mmap() and DMABUF code paths. Let's remove it
-and allow userspace freeing the queue (and potentially allocating a new
-one) even though old buffers might be still in processing.
-
-To let userspace know that the kernel now supports orphaning buffers
-that are still in use, add a new V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS
-to be set by reqbufs and create_bufs.
-
-[p.zabel@pengutronix.de: added V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS,
- updated documentation, and added back debug message]
-
-Signed-off-by: John Sheu <sheu@chromium.org>
-Reviewed-by: Pawel Osciak <posciak@chromium.org>
-Signed-off-by: Tomasz Figa <tfiga@chromium.org>
-Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
-Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
-Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-[hverkuil-cisco@xs4all.nl: added V4L2-BUF-CAP-SUPPORTS-ORPHANED-BUFS ref]
-Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
----
- Documentation/media/uapi/v4l/vidioc-reqbufs.rst | 17 ++++++++++++++---
- drivers/media/common/videobuf2/videobuf2-core.c | 8 +++-----
- drivers/media/common/videobuf2/videobuf2-v4l2.c | 2 +-
- include/uapi/linux/videodev2.h | 1 +
- 4 files changed, 19 insertions(+), 9 deletions(-)
-
---- a/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
-+++ b/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
-@@ -59,9 +59,14 @@ When the I/O method is not supported the
- code.
-
- Applications can call :ref:`VIDIOC_REQBUFS` again to change the number of
--buffers, however this cannot succeed when any buffers are still mapped.
--A ``count`` value of zero frees all buffers, after aborting or finishing
--any DMA in progress, an implicit
-+buffers. Note that if any buffers are still mapped or exported via DMABUF,
-+then :ref:`VIDIOC_REQBUFS` can only succeed if the
-+``V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS`` capability is set. Otherwise
-+:ref:`VIDIOC_REQBUFS` will return the ``EBUSY`` error code.
-+If ``V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS`` is set, then these buffers are
-+orphaned and will be freed when they are unmapped or when the exported DMABUF
-+fds are closed. A ``count`` value of zero frees or orphans all buffers, after
-+aborting or finishing any DMA in progress, an implicit
- :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>`.
-
-
-@@ -112,6 +117,7 @@ any DMA in progress, an implicit
- .. _V4L2-BUF-CAP-SUPPORTS-USERPTR:
- .. _V4L2-BUF-CAP-SUPPORTS-DMABUF:
- .. _V4L2-BUF-CAP-SUPPORTS-REQUESTS:
-+.. _V4L2-BUF-CAP-SUPPORTS-ORPHANED-BUFS:
-
- .. cssclass:: longtable
-
-@@ -132,6 +138,11 @@ any DMA in progress, an implicit
- * - ``V4L2_BUF_CAP_SUPPORTS_REQUESTS``
- - 0x00000008
- - This buffer type supports :ref:`requests <media-request-api>`.
-+ * - ``V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS``
-+ - 0x00000010
-+ - The kernel allows calling :ref:`VIDIOC_REQBUFS` while buffers are still
-+ mapped or exported via DMABUF. These orphaned buffers will be freed
-+ when they are unmapped or when the exported DMABUF fds are closed.
-
- Return Value
- ============
---- a/drivers/media/common/videobuf2/videobuf2-core.c
-+++ b/drivers/media/common/videobuf2/videobuf2-core.c
-@@ -684,11 +684,9 @@ int vb2_core_reqbufs(struct vb2_queue *q
- * are not in use and can be freed.
- */
- mutex_lock(&q->mmap_lock);
-- if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
-- mutex_unlock(&q->mmap_lock);
-- dprintk(1, "memory in use, cannot free\n");
-- return -EBUSY;
-- }
-+ if (debug && q->memory == VB2_MEMORY_MMAP &&
-+ __buffers_in_use(q))
-+ dprintk(1, "memory in use, orphaning buffers\n");
-
- /*
- * Call queue_cancel to clean up any buffers in the PREPARED or
---- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
-+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
-@@ -484,7 +484,7 @@ EXPORT_SYMBOL(vb2_querybuf);
-
- static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
- {
-- *caps = 0;
-+ *caps = V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS;
- if (q->io_modes & VB2_MMAP)
- *caps |= V4L2_BUF_CAP_SUPPORTS_MMAP;
- if (q->io_modes & VB2_USERPTR)
---- a/include/uapi/linux/videodev2.h
-+++ b/include/uapi/linux/videodev2.h
-@@ -881,6 +881,7 @@ struct v4l2_requestbuffers {
- #define V4L2_BUF_CAP_SUPPORTS_USERPTR (1 << 1)
- #define V4L2_BUF_CAP_SUPPORTS_DMABUF (1 << 2)
- #define V4L2_BUF_CAP_SUPPORTS_REQUESTS (1 << 3)
-+#define V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS (1 << 4)
-
- /**
- * struct v4l2_plane - plane info for multi-planar buffers
+++ /dev/null
-From 3476202ad0c40d466df8c82798b0ccb0a5e6ed8f Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 5 Jul 2019 09:22:10 +0100
-Subject: [PATCH 700/703] overlays: Add real parameters to the rpi-poe overlay
-
-As a result of being loaded by the POE HAT EEPROM, the rpi-poe overlay
-doesn't expose parameters in the usual way; instead it adds them to
-the base Device Tree, and the user is expected to use "dtparam=..."
-to access them.
-
-To make the documentation correct and to protect users who load the
-overlay explicitly, expecting to be able to use the parameters, add
-real parameters to the overlay as well.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/rpi-poe-overlay.dts | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts
-@@ -60,4 +60,11 @@
- poe_fan_temp1_hyst = <&trip1>,"hysteresis:0";
- };
- };
-+
-+ __overrides__ {
-+ poe_fan_temp0 = <&trip0>,"temperature:0";
-+ poe_fan_temp0_hyst = <&trip0>,"hysteresis:0";
-+ poe_fan_temp1 = <&trip1>,"temperature:0";
-+ poe_fan_temp1_hyst = <&trip1>,"hysteresis:0";
-+ };
- };
--- /dev/null
+From 55672983dee952815d614651a92f76044785ca46 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 9 Jul 2019 10:32:40 +0100
+Subject: [PATCH 700/725] overlays: i2c-gpio: Fix the "bus" parameter
+
+The "bus" parameter has two functions - providing unique names for
+multiple instances of the overlay, and allowing the number of the bus
+(i.e. "i2c-<bus>") to be specified. The second function hasn't worked
+as intended because the overlay doesn't include a "reg" property and
+the firmware intentionally won't create a "reg" property if one doesn't
+already exist.
+
+Allow the bus numbering scheme to work as intended by providing a "reg"
+with a default value that means "the next available one".
+
+See: https://github.com/raspberrypi/linux/issues/3062
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
+@@ -7,8 +7,10 @@
+
+ fragment@0 {
+ target-path = "/";
++
+ __overlay__ {
+ i2c_gpio: i2c@0 {
++ reg = <0xffffffff>;
+ compatible = "i2c-gpio";
+ gpios = <&gpio 23 0 /* sda */
+ &gpio 24 0 /* scl */
+++ /dev/null
-From 2683773c8d2092083bafbc64fe7e6a25c48b8f5f Mon Sep 17 00:00:00 2001
-From: Phil Elwell <pelwell@users.noreply.github.com>
-Date: Fri, 5 Jul 2019 14:49:22 +0100
-Subject: [PATCH 701/703] overlays: Rename pi3- overlays to be less
- model-specific (#3052)
-
-Rename the various pi3- overlays to be more generic, listing
-the devices they apply to in the README. The original names are
-retained for backwards compatibility as files that just include
-the new versions - the README marks them as being deprecated.
-
-See: https://github.com/raspberrypi/firmware/issues/1174
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/Makefile | 4 +
- arch/arm/boot/dts/overlays/README | 97 ++++++++++++-------
- .../arm/boot/dts/overlays/act-led-overlay.dts | 27 ++++++
- .../boot/dts/overlays/disable-bt-overlay.dts | 55 +++++++++++
- .../dts/overlays/disable-wifi-overlay.dts | 20 ++++
- .../boot/dts/overlays/miniuart-bt-overlay.dts | 74 ++++++++++++++
- .../boot/dts/overlays/pi3-act-led-overlay.dts | 28 +-----
- .../dts/overlays/pi3-disable-bt-overlay.dts | 56 +----------
- .../dts/overlays/pi3-disable-wifi-overlay.dts | 21 +---
- .../dts/overlays/pi3-miniuart-bt-overlay.dts | 75 +-------------
- 10 files changed, 246 insertions(+), 211 deletions(-)
- create mode 100644 arch/arm/boot/dts/overlays/act-led-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/disable-bt-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/disable-wifi-overlay.dts
- create mode 100644 arch/arm/boot/dts/overlays/miniuart-bt-overlay.dts
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -1,6 +1,7 @@
- # Overlays for the Raspberry Pi platform
-
- dtbo-$(CONFIG_ARCH_BCM2835) += \
-+ act-led.dtbo \
- adau1977-adc.dtbo \
- adau7002-simple.dtbo \
- ads1015.dtbo \
-@@ -26,6 +27,8 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- dht11.dtbo \
- dionaudio-loco.dtbo \
- dionaudio-loco-v2.dtbo \
-+ disable-bt.dtbo \
-+ disable-wifi.dtbo \
- dpi18.dtbo \
- dpi24.dtbo \
- draws.dtbo \
-@@ -91,6 +94,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- media-center.dtbo \
- midi-uart0.dtbo \
- midi-uart1.dtbo \
-+ miniuart-bt.dtbo \
- mmc.dtbo \
- mpu6050.dtbo \
- mz61581.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -180,14 +180,16 @@ Params:
-
- act_led_activelow Set to "on" to invert the sense of the LED
- (default "off")
-- N.B. For Pi3 see pi3-act-led overlay.
-+ N.B. For Pi 3B, 3B+, 3A+ and 4B, use the act-led
-+ overlay.
-
- act_led_gpio Set which GPIO to use for the activity LED
- (in case you want to connect it to an external
- device)
- (default "16" on a non-Plus board, "47" on a
- Plus or Pi 2)
-- N.B. For Pi3 see pi3-act-led overlay.
-+ N.B. For Pi 3B, 3B+, 3A+ and 4B, use the act-led
-+ overlay.
-
- pwr_led_trigger
- pwr_led_activelow
-@@ -205,6 +207,23 @@ Params:
- and the other i2c baudrate parameters.
-
-
-+Name: act-led
-+Info: Pi 3B, 3B+, 3A+ and 4B use a GPIO expander to drive the LEDs which can
-+ only be accessed from the VPU. There is a special driver for this with a
-+ separate DT node, which has the unfortunate consequence of breaking the
-+ act_led_gpio and act_led_activelow dtparams.
-+ This overlay changes the GPIO controller back to the standard one and
-+ restores the dtparams.
-+Load: dtoverlay=act-led,<param>=<val>
-+Params: activelow Set to "on" to invert the sense of the LED
-+ (default "off")
-+
-+ gpio Set which GPIO to use for the activity LED
-+ (in case you want to connect it to an external
-+ device)
-+ REQUIRED
-+
-+
- Name: adau1977-adc
- Info: Overlay for activation of ADAU1977 ADC codec over I2C for control
- and I2S for data.
-@@ -509,6 +528,21 @@ Params: 24db_digital_gain Allow ga
- that does not result in clipping/distortion!)
-
-
-+Name: disable-bt
-+Info: Disable onboard Bluetooth on Pi 3B, 3B+, 3A+, 4B and Zero W, restoring
-+ UART0/ttyAMA0 over GPIOs 14 & 15.
-+ N.B. To disable the systemd service that initialises the modem so it
-+ doesn't use the UART, use 'sudo systemctl disable hciuart'.
-+Load: dtoverlay=disable-bt
-+Params: <None>
-+
-+
-+Name: disable-wifi
-+Info: Disable onboard WiFi on Pi 3B, 3B+, 3A+, 4B and Zero W.
-+Load: dtoverlay=disable-wifi
-+Params: <None>
-+
-+
- 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
-@@ -1447,6 +1481,20 @@ Load: dtoverlay=midi-uart1
- Params: <None>
-
-
-+Name: miniuart-bt
-+Info: Switch the onboard Bluetooth function on Pi 3B, 3B+, 3A+, 4B and Zero W
-+ to use the mini-UART (ttyS0) and restore UART0/ttyAMA0 over GPIOs 14 &
-+ 15. Note that this may reduce the maximum usable baudrate.
-+ N.B. It is also necessary to edit /lib/systemd/system/hciuart.service
-+ and replace ttyAMA0 with ttyS0, unless using Raspbian or another
-+ distribution with udev rules that create /dev/serial0 and /dev/serial1,
-+ in which case use /dev/serial1 instead because it will always be
-+ correct. Furthermore, you must also set core_freq and core_freq_min to
-+ the same value in config.txt or the miniuart will not work.
-+Load: dtoverlay=miniuart-bt
-+Params: <None>
-+
-+
- Name: mmc
- Info: Selects the bcm2835-mmc SD/MMC driver, optionally with overclock
- Load: dtoverlay=mmc,<param>=<val>
-@@ -1509,48 +1557,27 @@ Params: panel Display
-
-
- Name: pi3-act-led
--Info: Pi3 uses a GPIO expander to drive the LEDs which can only be accessed
-- from the VPU. There is a special driver for this with a separate DT
-- node, which has the unfortunate consequence of breaking the
-- act_led_gpio and act_led_activelow dtparams.
-- This overlay changes the GPIO controller back to the standard one and
-- restores the dtparams.
--Load: dtoverlay=pi3-act-led,<param>=<val>
--Params: activelow Set to "on" to invert the sense of the LED
-- (default "off")
--
-- gpio Set which GPIO to use for the activity LED
-- (in case you want to connect it to an external
-- device)
-- REQUIRED
-+Info: This overlay has been renamed act-led, keeping pi3-act-led as an alias
-+ for backwards compatibility.
-+Load: <Deprecated>
-
-
- Name: pi3-disable-bt
--Info: Disable Pi3 Bluetooth and restore UART0/ttyAMA0 over GPIOs 14 & 15
-- N.B. To disable the systemd service that initialises the modem so it
-- doesn't use the UART, use 'sudo systemctl disable hciuart'.
--Load: dtoverlay=pi3-disable-bt
--Params: <None>
-+Info: This overlay has been renamed disable-bt, keeping pi3-disable-bt as an
-+ alias for backwards compatibility.
-+Load: <Deprecated>
-
-
- Name: pi3-disable-wifi
--Info: Disable Pi3 onboard WiFi
--Load: dtoverlay=pi3-disable-wifi
--Params: <None>
-+Info: This overlay has been renamed disable-wifi, keeping pi3-disable-wifi as
-+ an alias for backwards compatibility.
-+Load: <Deprecated>
-
-
- 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
-- usable baudrate.
-- N.B. It is also necessary to edit /lib/systemd/system/hciuart.service
-- and replace ttyAMA0 with ttyS0, unless you have a system with udev rules
-- that create /dev/serial0 and /dev/serial1, in which case use
-- /dev/serial1 instead because it will always be correct. Furthermore,
-- you must also set core_freq=250 in config.txt or the miniuart will not
-- work.
--Load: dtoverlay=pi3-miniuart-bt
--Params: <None>
-+Info: This overlay has been renamed miniuart-bt, keeping pi3-miniuart-bt as
-+ an alias for backwards compatibility.
-+Load: <Deprecated>
-
-
- Name: pibell
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/act-led-overlay.dts
-@@ -0,0 +1,27 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/* Pi3 uses a GPIO expander to drive the LEDs which can only be accessed
-+ from the VPU. There is a special driver for this with a separate DT node,
-+ which has the unfortunate consequence of breaking the act_led_gpio and
-+ act_led_activelow dtparams.
-+
-+ This overlay changes the GPIO controller back to the standard one and
-+ restores the dtparams.
-+*/
-+
-+/{
-+ compatible = "brcm,bcm2835";
-+
-+ fragment@0 {
-+ target = <&act_led>;
-+ frag0: __overlay__ {
-+ gpios = <&gpio 0 0>;
-+ };
-+ };
-+
-+ __overrides__ {
-+ gpio = <&frag0>,"gpios:4";
-+ activelow = <&frag0>,"gpios:8";
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/disable-bt-overlay.dts
-@@ -0,0 +1,55 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/* Disable Bluetooth and restore UART0/ttyAMA0 over GPIOs 14 & 15.
-+ To disable the systemd service that initialises the modem so it doesn't use
-+ the UART:
-+
-+ sudo systemctl disable hciuart
-+*/
-+
-+/{
-+ compatible = "brcm,bcm2835";
-+
-+ fragment@0 {
-+ target = <&uart1>;
-+ __overlay__ {
-+ status = "disabled";
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&uart0>;
-+ __overlay__ {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart0_pins>;
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@2 {
-+ target = <&uart0_pins>;
-+ __overlay__ {
-+ brcm,pins;
-+ brcm,function;
-+ brcm,pull;
-+ };
-+ };
-+
-+ fragment@3 {
-+ target = <&bt_pins>;
-+ __overlay__ {
-+ brcm,pins;
-+ brcm,function;
-+ brcm,pull;
-+ };
-+ };
-+
-+ fragment@4 {
-+ target-path = "/aliases";
-+ __overlay__ {
-+ serial0 = "/soc/serial@7e201000";
-+ serial1 = "/soc/serial@7e215040";
-+ };
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/disable-wifi-overlay.dts
-@@ -0,0 +1,20 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/{
-+ compatible = "brcm,bcm2835";
-+
-+ fragment@0 {
-+ target = <&mmc>;
-+ __overlay__ {
-+ status = "disabled";
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&mmcnr>;
-+ __overlay__ {
-+ status = "disabled";
-+ };
-+ };
-+};
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/miniuart-bt-overlay.dts
-@@ -0,0 +1,74 @@
-+/dts-v1/;
-+/plugin/;
-+
-+/* 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
-+ usable baudrate.
-+
-+ It is also necessary to edit /lib/systemd/system/hciuart.service and
-+ replace ttyAMA0 with ttyS0, unless you have a system with udev rules
-+ that create /dev/serial0 and /dev/serial1, in which case use /dev/serial1
-+ instead because it will always be correct.
-+
-+ If cmdline.txt uses the alias serial0 to refer to the user-accessable port
-+ then the firmware will replace with the appropriate port whether or not
-+ this overlay is used.
-+*/
-+
-+/{
-+ compatible = "brcm,bcm2835";
-+
-+ fragment@0 {
-+ target = <&uart0>;
-+ __overlay__ {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart0_pins>;
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&uart1>;
-+ __overlay__ {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart1_pins &bt_pins &fake_bt_cts>;
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@2 {
-+ target = <&uart0_pins>;
-+ __overlay__ {
-+ brcm,pins;
-+ brcm,function;
-+ brcm,pull;
-+ };
-+ };
-+
-+ fragment@3 {
-+ target = <&uart1_pins>;
-+ __overlay__ {
-+ brcm,pins = <32 33>;
-+ brcm,function = <2>; /* alt5=UART1 */
-+ brcm,pull = <0 2>;
-+ };
-+ };
-+
-+ fragment@4 {
-+ target = <&gpio>;
-+ __overlay__ {
-+ fake_bt_cts: fake_bt_cts {
-+ brcm,pins = <31>;
-+ brcm,function = <1>; /* output */
-+ };
-+ };
-+ };
-+
-+ fragment@5 {
-+ target-path = "/aliases";
-+ __overlay__ {
-+ serial0 = "/soc/serial@7e201000";
-+ serial1 = "/soc/serial@7e215040";
-+ };
-+ };
-+};
---- a/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts
-@@ -1,27 +1 @@
--/dts-v1/;
--/plugin/;
--
--/* Pi3 uses a GPIO expander to drive the LEDs which can only be accessed
-- from the VPU. There is a special driver for this with a separate DT node,
-- which has the unfortunate consequence of breaking the act_led_gpio and
-- act_led_activelow dtparams.
--
-- This overlay changes the GPIO controller back to the standard one and
-- restores the dtparams.
--*/
--
--/{
-- compatible = "brcm,bcm2835";
--
-- fragment@0 {
-- target = <&act_led>;
-- frag0: __overlay__ {
-- gpios = <&gpio 0 0>;
-- };
-- };
--
-- __overrides__ {
-- gpio = <&frag0>,"gpios:4";
-- activelow = <&frag0>,"gpios:8";
-- };
--};
-+#include "act-led-overlay.dts"
---- a/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts
-@@ -1,55 +1 @@
--/dts-v1/;
--/plugin/;
--
--/* Disable Bluetooth and restore UART0/ttyAMA0 over GPIOs 14 & 15.
-- To disable the systemd service that initialises the modem so it doesn't use
-- the UART:
--
-- sudo systemctl disable hciuart
--*/
--
--/{
-- compatible = "brcm,bcm2835";
--
-- fragment@0 {
-- target = <&uart1>;
-- __overlay__ {
-- status = "disabled";
-- };
-- };
--
-- fragment@1 {
-- target = <&uart0>;
-- __overlay__ {
-- pinctrl-names = "default";
-- pinctrl-0 = <&uart0_pins>;
-- status = "okay";
-- };
-- };
--
-- fragment@2 {
-- target = <&uart0_pins>;
-- __overlay__ {
-- brcm,pins;
-- brcm,function;
-- brcm,pull;
-- };
-- };
--
-- fragment@3 {
-- target = <&bt_pins>;
-- __overlay__ {
-- brcm,pins;
-- brcm,function;
-- brcm,pull;
-- };
-- };
--
-- fragment@4 {
-- target-path = "/aliases";
-- __overlay__ {
-- serial0 = "/soc/serial@7e201000";
-- serial1 = "/soc/serial@7e215040";
-- };
-- };
--};
-+#include "disable-bt-overlay.dts"
---- a/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts
-@@ -1,20 +1 @@
--/dts-v1/;
--/plugin/;
--
--/{
-- compatible = "brcm,bcm2835";
--
-- fragment@0 {
-- target = <&mmc>;
-- __overlay__ {
-- status = "disabled";
-- };
-- };
--
-- fragment@1 {
-- target = <&mmcnr>;
-- __overlay__ {
-- status = "disabled";
-- };
-- };
--};
-+#include "disable-wifi-overlay.dts"
---- a/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts
-@@ -1,74 +1 @@
--/dts-v1/;
--/plugin/;
--
--/* 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
-- usable baudrate.
--
-- It is also necessary to edit /lib/systemd/system/hciuart.service and
-- replace ttyAMA0 with ttyS0, unless you have a system with udev rules
-- that create /dev/serial0 and /dev/serial1, in which case use /dev/serial1
-- instead because it will always be correct.
--
-- If cmdline.txt uses the alias serial0 to refer to the user-accessable port
-- then the firmware will replace with the appropriate port whether or not
-- this overlay is used.
--*/
--
--/{
-- compatible = "brcm,bcm2835";
--
-- fragment@0 {
-- target = <&uart0>;
-- __overlay__ {
-- pinctrl-names = "default";
-- pinctrl-0 = <&uart0_pins>;
-- status = "okay";
-- };
-- };
--
-- fragment@1 {
-- target = <&uart1>;
-- __overlay__ {
-- pinctrl-names = "default";
-- pinctrl-0 = <&uart1_pins &bt_pins &fake_bt_cts>;
-- status = "okay";
-- };
-- };
--
-- fragment@2 {
-- target = <&uart0_pins>;
-- __overlay__ {
-- brcm,pins;
-- brcm,function;
-- brcm,pull;
-- };
-- };
--
-- fragment@3 {
-- target = <&uart1_pins>;
-- __overlay__ {
-- brcm,pins = <32 33>;
-- brcm,function = <2>; /* alt5=UART1 */
-- brcm,pull = <0 2>;
-- };
-- };
--
-- fragment@4 {
-- target = <&gpio>;
-- __overlay__ {
-- fake_bt_cts: fake_bt_cts {
-- brcm,pins = <31>;
-- brcm,function = <1>; /* output */
-- };
-- };
-- };
--
-- fragment@5 {
-- target-path = "/aliases";
-- __overlay__ {
-- serial0 = "/soc/serial@7e201000";
-- serial1 = "/soc/serial@7e215040";
-- };
-- };
--};
-+#include "miniuart-bt-overlay.dts"
--- /dev/null
+From e70cb8a67901499d75f4ed4d5bd120a1ceace698 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 11 Jul 2019 13:13:39 +0100
+Subject: [PATCH 701/725] tty: amba-pl011: Make TX optimisation conditional
+
+pl011_tx_chars takes a "from_irq" parameter to reduce the number of
+register accesses. When from_irq is true the function assumes that the
+FIFO is half empty and writes up to half a FIFO's worth of bytes
+without polling the FIFO status register, the reasoning being that
+the function is being called as a result of the TX interrupt being
+raised. This logic would work were it not for the fact that
+pl011_rx_chars, called from pl011_int before pl011_tx_chars, releases
+the spinlock before calling tty_flip_buffer_push.
+
+A user thread writing to the UART claims the spinlock and ultimately
+calls pl011_tx_chars with from_irq set to false. This reverts to the
+older logic that polls the FIFO status register before sending every
+byte. If this happen on an SMP system during the section of the IRQ
+handler where the spinlock has been released, then by the time the TX
+interrupt handler is called, the FIFO may already be full, and any
+further writes are likely to be lost.
+
+The fix involves adding a per-port flag that is true iff running from
+within the interrupt handler and the spinlock has not yet been released.
+This flag is then used as the value for the from_irq parameter of
+pl011_tx_chars, causing polling to be used in the unsafe case.
+
+Fixes: 1e84d22322ce ("serial/amba-pl011: Refactor and simplify TX FIFO handling")
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/tty/serial/amba-pl011.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/tty/serial/amba-pl011.c
++++ b/drivers/tty/serial/amba-pl011.c
+@@ -270,6 +270,7 @@ struct uart_amba_port {
+ unsigned int old_cr; /* state during shutdown */
+ unsigned int fixed_baud; /* vendor-set fixed baud rate */
+ char type[12];
++ bool irq_locked; /* in irq, unreleased lock */
+ #ifdef CONFIG_DMA_ENGINE
+ /* DMA stuff */
+ bool using_tx_dma;
+@@ -814,6 +815,7 @@ __acquires(&uap->port.lock)
+ return;
+
+ /* Avoid deadlock with the DMA engine callback */
++ uap->irq_locked = 0;
+ spin_unlock(&uap->port.lock);
+ dmaengine_terminate_all(uap->dmatx.chan);
+ spin_lock(&uap->port.lock);
+@@ -941,6 +943,7 @@ static void pl011_dma_rx_chars(struct ua
+ fifotaken = pl011_fifo_to_tty(uap);
+ }
+
++ uap->irq_locked = 0;
+ spin_unlock(&uap->port.lock);
+ dev_vdbg(uap->port.dev,
+ "Took %d chars from DMA buffer and %d chars from the FIFO\n",
+@@ -1349,6 +1352,7 @@ __acquires(&uap->port.lock)
+ {
+ pl011_fifo_to_tty(uap);
+
++ uap->irq_locked = 0;
+ spin_unlock(&uap->port.lock);
+ tty_flip_buffer_push(&uap->port.state->port);
+ /*
+@@ -1484,6 +1488,7 @@ static irqreturn_t pl011_int(int irq, vo
+ int handled = 0;
+
+ spin_lock_irqsave(&uap->port.lock, flags);
++ uap->irq_locked = 1;
+ status = pl011_read(uap, REG_RIS) & uap->im;
+ if (status) {
+ do {
+@@ -1503,7 +1508,7 @@ static irqreturn_t pl011_int(int irq, vo
+ UART011_CTSMIS|UART011_RIMIS))
+ pl011_modem_status(uap);
+ if (status & UART011_TXIS)
+- pl011_tx_chars(uap, true);
++ pl011_tx_chars(uap, uap->irq_locked);
+
+ if (pass_counter-- == 0)
+ break;
+++ /dev/null
-From 4baf16fc6d22fd948a597993d858d4de0c5b3bcc Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Fri, 21 Jun 2019 03:52:49 -0700
-Subject: [PATCH 702/703] i2c: bcm2835: Move IRQ request after clock code in
- probe
-
-Commit 4a5cfa39465cad25dd736d7ceba8a5d32eea4ecc upstream.
-
-If any of the clock code in the probe fails and returns, the IRQ
-will not be freed. Moving the IRQ request to last allows it to
-be freed on any errors further up in the probe function. devm_
-calls can apparently not be used because there are some potential
-race conditions that will arise.
-
-Fixes: bebff81fb8b9 ("i2c: bcm2835: Model Divider in CCF")
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Acked-by: Stefan Wahren <wahrenst@gmx.net>
-Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
----
- drivers/i2c/busses/i2c-bcm2835.c | 28 ++++++++++++++--------------
- 1 file changed, 14 insertions(+), 14 deletions(-)
-
---- a/drivers/i2c/busses/i2c-bcm2835.c
-+++ b/drivers/i2c/busses/i2c-bcm2835.c
-@@ -521,20 +521,6 @@ static int bcm2835_i2c_probe(struct plat
- if (IS_ERR(i2c_dev->regs))
- return PTR_ERR(i2c_dev->regs);
-
-- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-- if (!irq) {
-- dev_err(&pdev->dev, "No IRQ resource\n");
-- return -ENODEV;
-- }
-- i2c_dev->irq = irq->start;
--
-- ret = request_irq(i2c_dev->irq, bcm2835_i2c_isr, IRQF_SHARED,
-- dev_name(&pdev->dev), i2c_dev);
-- if (ret) {
-- dev_err(&pdev->dev, "Could not request IRQ\n");
-- return -ENODEV;
-- }
--
- mclk_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
-
- bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk_name, i2c_dev);
-@@ -564,6 +550,20 @@ static int bcm2835_i2c_probe(struct plat
- return ret;
- }
-
-+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-+ if (!irq) {
-+ dev_err(&pdev->dev, "No IRQ resource\n");
-+ return -ENODEV;
-+ }
-+ i2c_dev->irq = irq->start;
-+
-+ ret = request_irq(i2c_dev->irq, bcm2835_i2c_isr, IRQF_SHARED,
-+ dev_name(&pdev->dev), i2c_dev);
-+ if (ret) {
-+ dev_err(&pdev->dev, "Could not request IRQ\n");
-+ return -ENODEV;
-+ }
-+
- adap = &i2c_dev->adapter;
- i2c_set_adapdata(adap, i2c_dev);
- adap->owner = THIS_MODULE;
--- /dev/null
+From 92900af9134a2e5435ee68d69cdd23d1f8cb4980 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Thu, 11 Jul 2019 17:55:43 +0100
+Subject: [PATCH 702/725] xhci: add quirk for host controllers that don't
+ update endpoint DCS
+
+Seen on a VLI VL805 PCIe to USB controller. For non-stream endpoints
+at least, if the xHC halts on a particular TRB due to an error then
+the DCS field in the Out Endpoint Context maintained by the hardware
+is not updated with the current cycle state.
+
+Using the quirk XHCI_EP_CTX_BROKEN_DCS and instead fetch the DCS bit
+from the TRB that the xHC stopped on.
+
+See: https://github.com/raspberrypi/linux/issues/3060
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/host/xhci-pci.c | 4 +++-
+ drivers/usb/host/xhci-ring.c | 26 +++++++++++++++++++++++++-
+ drivers/usb/host/xhci.h | 1 +
+ 3 files changed, 29 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -223,8 +223,10 @@ static void xhci_pci_quirks(struct devic
+ xhci->quirks |= XHCI_BROKEN_STREAMS;
+
+ if (pdev->vendor == PCI_VENDOR_ID_VIA &&
+- pdev->device == 0x3483)
++ pdev->device == 0x3483) {
+ xhci->quirks |= XHCI_LPM_SUPPORT;
++ xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS;
++ }
+
+ if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+ pdev->device == 0x1042)
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -520,7 +520,10 @@ void xhci_find_new_dequeue_state(struct
+ struct xhci_virt_ep *ep = &dev->eps[ep_index];
+ struct xhci_ring *ep_ring;
+ struct xhci_segment *new_seg;
++ struct xhci_segment *halted_seg = NULL;
+ union xhci_trb *new_deq;
++ union xhci_trb *halted_trb;
++ int index = 0;
+ dma_addr_t addr;
+ u64 hw_dequeue;
+ bool cycle_found = false;
+@@ -541,7 +544,28 @@ void xhci_find_new_dequeue_state(struct
+ hw_dequeue = xhci_get_hw_deq(xhci, dev, ep_index, stream_id);
+ new_seg = ep_ring->deq_seg;
+ new_deq = ep_ring->dequeue;
+- state->new_cycle_state = hw_dequeue & 0x1;
++
++ /*
++ * Quirk: xHC write-back of the DCS field in the hardware dequeue
++ * pointer is wrong - use the cycle state of the TRB pointed to by
++ * the dequeue pointer.
++ */
++ if (xhci->quirks & XHCI_EP_CTX_BROKEN_DCS &&
++ !(ep->ep_state & EP_HAS_STREAMS))
++ halted_seg = trb_in_td(xhci, cur_td->start_seg,
++ cur_td->first_trb, cur_td->last_trb,
++ hw_dequeue & ~0xf, false);
++ if (halted_seg) {
++ index = ((dma_addr_t)(hw_dequeue & ~0xf) - halted_seg->dma) /
++ sizeof(*halted_trb);
++ halted_trb = &halted_seg->trbs[index];
++ state->new_cycle_state = halted_trb->generic.field[3] & 0x1;
++ xhci_dbg(xhci, "Endpoint DCS = %d TRB index = %d cycle = %d\n",
++ (u8)(hw_dequeue & 0x1), index,
++ state->new_cycle_state);
++ } else {
++ state->new_cycle_state = hw_dequeue & 0x1;
++ }
+ state->stream_id = stream_id;
+
+ /*
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1865,6 +1865,7 @@ struct xhci_hcd {
+ #define XHCI_ZERO_64B_REGS BIT_ULL(32)
+ #define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
+ #define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)
++#define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(36)
+
+ unsigned int num_active_eps;
+ unsigned int limit_active_eps;
+++ /dev/null
-From c08dfc37750b965a410c11eb157c0c0d75a13b88 Mon Sep 17 00:00:00 2001
-From: Annaliese McDermond <nh6z@nh6z.net>
-Date: Fri, 21 Jun 2019 03:52:50 -0700
-Subject: [PATCH 703/703] i2c: bcm2835: Ensure clock exists when probing
-
-Commit 9de93b04df16b055824e3f1f13fedb90fbcf2e4f upstream.
-
-Probe function fails to recognize that upstream clock actually
-doesn't yet exist because clock driver has not been initialized.
-Actually try to go get the clock and test for its existence
-before trying to set up a downstream clock based upon it.
-
-This fixes a bug that causes the i2c driver not to work with
-monolithic kernels.
-
-Fixes: bebff81fb8b9 ("i2c: bcm2835: Model Divider in CCF")
-Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
-Acked-by: Stefan Wahren <wahrenst@gmx.net>
-Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
----
- drivers/i2c/busses/i2c-bcm2835.c | 16 ++++++++++++----
- 1 file changed, 12 insertions(+), 4 deletions(-)
-
---- a/drivers/i2c/busses/i2c-bcm2835.c
-+++ b/drivers/i2c/busses/i2c-bcm2835.c
-@@ -244,15 +244,18 @@ static const struct clk_ops clk_bcm2835_
- };
-
- static struct clk *bcm2835_i2c_register_div(struct device *dev,
-- const char *mclk_name,
-+ struct clk *mclk,
- struct bcm2835_i2c_dev *i2c_dev)
- {
- struct clk_init_data init;
- struct clk_bcm2835_i2c *priv;
- char name[32];
-+ const char *mclk_name;
-
- snprintf(name, sizeof(name), "%s_div", dev_name(dev));
-
-+ mclk_name = __clk_get_name(mclk);
-+
- init.ops = &clk_bcm2835_i2c_ops;
- init.name = name;
- init.parent_names = (const char* []) { mclk_name };
-@@ -505,8 +508,8 @@ static int bcm2835_i2c_probe(struct plat
- struct resource *mem, *irq;
- int ret;
- struct i2c_adapter *adap;
-- const char *mclk_name;
- struct clk *bus_clk;
-+ struct clk *mclk;
- u32 bus_clk_rate;
-
- i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
-@@ -521,9 +524,14 @@ static int bcm2835_i2c_probe(struct plat
- if (IS_ERR(i2c_dev->regs))
- return PTR_ERR(i2c_dev->regs);
-
-- mclk_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
-+ mclk = devm_clk_get(&pdev->dev, NULL);
-+ if (IS_ERR(mclk)) {
-+ if (PTR_ERR(mclk) != -EPROBE_DEFER)
-+ dev_err(&pdev->dev, "Could not get clock\n");
-+ return PTR_ERR(mclk);
-+ }
-
-- bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk_name, i2c_dev);
-+ bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev);
-
- if (IS_ERR(bus_clk)) {
- dev_err(&pdev->dev, "Could not register clock\n");
--- /dev/null
+From 74cd0c8293ad0a05c45eaa29d986f840227867f8 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 12 Jul 2019 15:38:35 +0100
+Subject: [PATCH 703/725] i2c: bcm2835: Set clock-stretch timeout to 35ms
+
+The BCM2835 I2C blocks have a register to set the clock-stretch
+timeout - how long the device is allowed to hold SCL low - in bus
+cycles. The current driver doesn't write to the register, therefore
+the default value of 64 cycles is being used for all devices.
+
+Set the timeout to the value recommended for SMBus - 35ms.
+
+See: https://github.com/raspberrypi/linux/issues/3064
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -194,6 +194,7 @@ static int clk_bcm2835_i2c_set_rate(stru
+ {
+ struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
+ u32 redl, fedl;
++ u32 clk_tout;
+ u32 divider = clk_bcm2835_i2c_calc_divider(rate, parent_rate);
+
+ if (divider == -EINVAL)
+@@ -217,6 +218,17 @@ static int clk_bcm2835_i2c_set_rate(stru
+ bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DEL,
+ (fedl << BCM2835_I2C_FEDL_SHIFT) |
+ (redl << BCM2835_I2C_REDL_SHIFT));
++
++ /*
++ * Set the clock stretch timeout to the SMBUs-recommended 35ms.
++ */
++ if (rate > 0xffff*1000/35)
++ clk_tout = 0xffff;
++ else
++ clk_tout = 35*rate/1000;
++
++ bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_CLKT, clk_tout);
++
+ return 0;
+ }
+
--- /dev/null
+From d836c37cd387c438a86054bd52f82141513cfa19 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 8 Mar 2019 13:02:16 -0800
+Subject: [PATCH 704/725] arm64: bcm2835: Add missing dependency on MFD_CORE.
+
+commit 7a9b6be9fe58194d9a349159176e8cc0d8f10ef8 upstream.
+
+When adding the MFD dependency for power domains and WDT in bcm2835, I
+added it only on the arm32 side and missed it for arm64.
+
+Fixes: 5e6acc3e678e ("bcm2835-pm: Move bcm2835-watchdog's DT probe to an MFD.")
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Reported-by: Stefan Wahren <stefan.wahren@i2se.com>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+---
+ arch/arm64/Kconfig.platforms | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm64/Kconfig.platforms
++++ b/arch/arm64/Kconfig.platforms
+@@ -20,6 +20,7 @@ config ARCH_BCM2835
+ bool "Broadcom BCM2835 family"
+ select TIMER_OF
+ select GPIOLIB
++ select MFD_CORE
+ select PINCTRL
+ select PINCTRL_BCM2835
+ select ARM_AMBA
--- /dev/null
+From 4e534a6c926bee4a9e65c59ac81208ac0a7d280c Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 15 Jul 2019 10:39:05 +0100
+Subject: [PATCH 705/725] overlays: Add PCF2129 RTC
+
+Add support for the PCF2129 RTC to i2c-rtc and i2c-rtc-gpio overlays.
+Also add rv3028 to i2c-rtc-gpio (it was missed previously), and don't
+attempt to set an alternate address for the PCF2127.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README | 11 ++++-
+ .../dts/overlays/i2c-rtc-gpio-overlay.dts | 41 +++++++++++++++++--
+ .../arm/boot/dts/overlays/i2c-rtc-overlay.dts | 19 ++++++++-
+ 3 files changed, 64 insertions(+), 7 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1022,6 +1022,8 @@ Params: abx80x Select o
+
+ pcf2127 Select the PCF2127 device
+
++ pcf2129 Select the PCF2129 device
++
+ pcf8523 Select the PCF8523 device
+
+ pcf8563 Select the PCF8563 device
+@@ -1067,10 +1069,14 @@ Params: abx80x Select o
+
+ pcf2127 Select the PCF2127 device
+
++ pcf2129 Select the PCF2129 device
++
+ pcf8523 Select the PCF8523 device
+
+ pcf8563 Select the PCF8563 device
+
++ rv3028 Select the Micro Crystal RV3028 device
++
+ addr Sets the address for the RTC. Note that the
+ device must be configured to use the specified
+ address.
+@@ -1079,11 +1085,14 @@ Params: abx80x Select o
+ "schottky" (ABx80x only)
+
+ trickle-resistor-ohms Resistor value for trickle charge (DS1339,
+- ABx80x)
++ ABx80x, RV3028)
+
+ wakeup-source Specify that the RTC can be used as a wakeup
+ source
+
++ backup-switchover-mode Backup power supply switch mode. Must be 0 for
++ off or 1 for Vdd < VBackup (RV3028 only)
++
+ i2c_gpio_sda GPIO used for I2C data (default "23")
+
+ i2c_gpio_scl GPIO used for I2C clock (default "24")
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
+@@ -121,7 +121,7 @@
+ #size-cells = <0>;
+ status = "okay";
+
+- pcf2127: pcf2127@51 {
++ pcf2127@51 {
+ compatible = "nxp,pcf2127";
+ reg = <0x51>;
+ status = "okay";
+@@ -174,6 +174,36 @@
+ };
+ };
+
++ fragment@11 {
++ target = <&i2c_gpio>;
++ __dormant__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ rv3028: rv3028@52 {
++ compatible = "microcrystal,rv3028";
++ reg = <0x52>;
++ status = "okay";
++ };
++ };
++ };
++
++ fragment@12 {
++ target = <&i2c_gpio>;
++ __dormant__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ pcf2129@51 {
++ compatible = "nxp,pcf2129";
++ reg = <0x51>;
++ status = "okay";
++ };
++ };
++ };
++
+ __overrides__ {
+ abx80x = <0>,"+1";
+ ds1307 = <0>,"+2";
+@@ -185,6 +215,8 @@
+ pcf8523 = <0>,"+8";
+ pcf8563 = <0>,"+9";
+ m41t62 = <0>,"+10";
++ rv3028 = <0>,"+11";
++ pcf2129 = <0>,"+12";
+
+ addr = <&abx80x>, "reg:0",
+ <&ds1307>, "reg:0",
+@@ -192,18 +224,19 @@
+ <&ds3231>, "reg:0",
+ <&mcp7940x>, "reg:0",
+ <&mcp7941x>, "reg:0",
+- <&pcf2127>, "reg:0",
+ <&pcf8523>, "reg:0",
+ <&pcf8563>, "reg:0",
+ <&m41t62>, "reg:0";
+
+ trickle-diode-type = <&abx80x>,"abracon,tc-diode";
+ trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0",
+- <&abx80x>,"abracon,tc-resistor";
++ <&abx80x>,"abracon,tc-resistor",
++ <&rv3028>,"trickle-resistor-ohms:0";
++ backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0";
+ wakeup-source = <&ds1339>,"wakeup-source?",
+ <&ds3231>,"wakeup-source?",
+ <&mcp7940x>,"wakeup-source?",
+- <&mcp7941x>,"wakeup-source?";
++ <&mcp7941x>,"wakeup-source?";
+ i2c_gpio_sda = <&i2c_gpio>,"gpios:4";
+ i2c_gpio_scl = <&i2c_gpio>,"gpios:16";
+ i2c_gpio_delay_us = <&i2c_gpio>,"i2c-gpio,delay-us:0";
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -105,7 +105,7 @@
+ #size-cells = <0>;
+ status = "okay";
+
+- pcf2127: pcf2127@51 {
++ pcf2127@51 {
+ compatible = "nxp,pcf2127";
+ reg = <0x51>;
+ status = "okay";
+@@ -173,6 +173,21 @@
+ };
+ };
+
++ fragment@11 {
++ target = <&i2c_arm>;
++ __dormant__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ pcf2129@51 {
++ compatible = "nxp,pcf2129";
++ reg = <0x51>;
++ status = "okay";
++ };
++ };
++ };
++
+ __overrides__ {
+ abx80x = <0>,"+0";
+ ds1307 = <0>,"+1";
+@@ -185,6 +200,7 @@
+ pcf8563 = <0>,"+8";
+ m41t62 = <0>,"+9";
+ rv3028 = <0>,"+10";
++ pcf2129 = <0>,"+11";
+
+ addr = <&abx80x>, "reg:0",
+ <&ds1307>, "reg:0",
+@@ -192,7 +208,6 @@
+ <&ds3231>, "reg:0",
+ <&mcp7940x>, "reg:0",
+ <&mcp7941x>, "reg:0",
+- <&pcf2127>, "reg:0",
+ <&pcf8523>, "reg:0",
+ <&pcf8563>, "reg:0",
+ <&m41t62>, "reg:0";
--- /dev/null
+From 04f2cfb2130c52d8e01c5c2fddf1c0f5d0f3583c Mon Sep 17 00:00:00 2001
+From: Allen Wild <allenwild93@gmail.com>
+Date: Sat, 13 Jul 2019 11:14:02 -0400
+Subject: [PATCH 706/725] configs: arm64/bcm2711: Use CONFIG_BRCMSTB_THERMAL
+ instead of CONFIG_BCM2835_THERMAL
+
+The Raspberry Pi 4 uses the brcmstb thermal driver rather than brcm2835,
+based on the device tree compatible string 'brcm,avs-tmon-bcm2838'. With
+CONFIG_BRCMSTB_THERMAL enabled, reading temperature from
+/sys/class/thermal/thermal_zone0/temp works as expected instead of
+returning EINVAL.
+
+Fixes: https://github.com/raspberrypi/linux/issues/3071
+Signed-off-by: Allen Wild <allenwild93@gmail.com>
+---
+ arch/arm64/configs/bcm2711_defconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm64/configs/bcm2711_defconfig
++++ b/arch/arm64/configs/bcm2711_defconfig
+@@ -658,7 +658,7 @@ CONFIG_SENSORS_ADS1015=m
+ CONFIG_SENSORS_INA2XX=m
+ CONFIG_SENSORS_TMP102=m
+ CONFIG_THERMAL=y
+-CONFIG_BCM2835_THERMAL=y
++CONFIG_BRCMSTB_THERMAL=y
+ CONFIG_WATCHDOG=y
+ CONFIG_GPIO_WATCHDOG=m
+ CONFIG_BCM2835_WDT=y
--- /dev/null
+From a3dd548da9a2900eafb337eab2a3124f543ddc31 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 16 Jul 2019 15:24:12 +0100
+Subject: [PATCH 707/725] overlays: dpi18 and dpi24 vc4 compatibility
+
+The dpi overlays use the fb device tree node as a place to hang the
+necessary pinctrl changes. With one of the VC4 overlays loaded, the
+fb node is disabled so the changes have no effect.
+
+Modify the overlays to also use the vc4 node, to cover both use
+cases.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/dpi18-overlay.dts | 8 ++++++++
+ arch/arm/boot/dts/overlays/dpi24-overlay.dts | 8 ++++++++
+ 2 files changed, 16 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/dpi18-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dpi18-overlay.dts
+@@ -17,6 +17,14 @@
+ };
+
+ fragment@1 {
++ target = <&vc4>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&dpi18_pins>;
++ };
++ };
++
++ fragment@2 {
+ target = <&gpio>;
+ __overlay__ {
+ dpi18_pins: dpi18_pins {
+--- a/arch/arm/boot/dts/overlays/dpi24-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dpi24-overlay.dts
+@@ -17,6 +17,14 @@
+ };
+
+ fragment@1 {
++ target = <&vc4>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&dpi24_pins>;
++ };
++ };
++
++ fragment@2 {
+ target = <&gpio>;
+ __overlay__ {
+ dpi24_pins: dpi24_pins {
--- /dev/null
+From b61cc000ad6ee771f471a126dc80b7c083730a94 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 17 Jul 2019 10:08:55 +0100
+Subject: [PATCH 708/725] overlays: Add i2c0 and i2c1 for regularity
+
+The new i2c overlays for pi4 (i2c3, i2c4, i2c5, i2c6) have a
+standardised interface that allows pin groups to be chosen
+atomically rather than as individual pins. Add i2c0 and i2c1
+overlays to fit the naming scheme and parameter usage, deprecating
+i2c0-bcm2708 and i2c1-bcm2708.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/Makefile | 2 +
+ arch/arm/boot/dts/overlays/README | 33 +++++---
+ .../dts/overlays/i2c0-bcm2708-overlay.dts | 77 +++----------------
+ arch/arm/boot/dts/overlays/i2c0-overlay.dts | 61 +++++++++++++++
+ .../dts/overlays/i2c1-bcm2708-overlay.dts | 46 ++---------
+ arch/arm/boot/dts/overlays/i2c1-overlay.dts | 44 +++++++++++
+ 6 files changed, 147 insertions(+), 116 deletions(-)
+ create mode 100644 arch/arm/boot/dts/overlays/i2c0-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/i2c1-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -66,7 +66,9 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ i2c-rtc.dtbo \
+ i2c-rtc-gpio.dtbo \
+ i2c-sensor.dtbo \
++ i2c0.dtbo \
+ i2c0-bcm2708.dtbo \
++ i2c1.dtbo \
+ i2c1-bcm2708.dtbo \
+ i2c3.dtbo \
+ i2c4.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1151,14 +1151,12 @@ Params: addr Set the
+ sensor
+
+
+-Name: i2c0-bcm2708
++Name: i2c0
+ Info: Change i2c0 pin usage. Not all pin combinations are usable on all
+ platforms - platforms other then Compute Modules can only use this
+ to disable transaction combining.
+-Load: dtoverlay=i2c0-bcm2708,<param>=<val>
+-Params: sda0_pin GPIO pin for SDA0 (deprecated - use pins_*)
+- scl0_pin GPIO pin for SCL0 (deprecated - use pins_*)
+- pins_0_1 Use pins 0 and 1 (default)
++Load: dtoverlay=i2c0,<param>=<val>
++Params: pins_0_1 Use pins 0 and 1 (default)
+ pins_28_29 Use pins 28 and 29
+ pins_44_45 Use pins 44 and 45
+ pins_46_47 Use pins 46 and 47
+@@ -1166,18 +1164,33 @@ Params: sda0_pin GPIO pin
+ "yes")
+
+
+-Name: i2c1-bcm2708
++Name: i2c0-bcm2708
++Info: Deprecated, legacy version of i2c0, from which it inherits its
++ parameters, just adding the explicit individual pin specifiers.
++Load: <Deprecated>
++Params: sda0_pin GPIO pin for SDA0 (deprecated - use pins_*)
++ scl0_pin GPIO pin for SCL0 (deprecated - use pins_*)
++
++
++Name: i2c1
+ Info: Change i2c1 pin usage. Not all pin combinations are usable on all
+ platforms - platforms other then Compute Modules can only use this
+ to disable transaction combining.
+-Info: Enable the i2c_bcm2708 driver for the i2c1 bus
+-Load: dtoverlay=i2c1-bcm2708,<param>=<val>
++Load: dtoverlay=i2c1,<param>=<val>
++Params: pins_2_3 Use pins 2 and 3 (default)
++ pins_44_45 Use pins 44 and 45
++ combine Allow transactions to be combined (default
++ "yes")
++
++
++Name: i2c1-bcm2708
++Info: Deprecated, legacy version of i2c1, from which it inherits its
++ parameters, just adding the explicit individual pin specifiers.
++Load: <Deprecated>
+ Params: sda1_pin GPIO pin for SDA1 (2 or 44 - default 2)
+ scl1_pin GPIO pin for SCL1 (3 or 45 - default 3)
+ pin_func Alternative pin function (4 (alt0), 6 (alt2) -
+ default 4)
+- combine Allow transactions to be combined (default
+- "yes")
+
+
+ Name: i2c3
+--- a/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts
+@@ -1,69 +1,14 @@
+-/*
+- * Device tree overlay for i2c_bcm2708, i2c0 bus
+- *
+- * Compile:
+- * dtc -@ -I dts -O dtb -o i2c0-bcm2708-overlay.dtb i2c0-bcm2708-overlay.dts
+- */
+-
+-/dts-v1/;
+-/plugin/;
++#include "i2c0-overlay.dts"
+
+ /{
+- compatible = "brcm,bcm2835";
+-
+- fragment@0 {
+- target = <&i2c0>;
+- __overlay__ {
+- status = "okay";
+- };
+- };
+-
+- fragment@1 {
+- target = <&i2c0_pins>;
+- frag1: __overlay__ {
+- brcm,pins = <0 1>;
+- brcm,function = <4>; /* alt0 */
+- };
+- };
+-
+- fragment@2 {
+- target = <&i2c0_pins>;
+- __dormant__ {
+- brcm,pins = <28 29>;
+- brcm,function = <4>; /* alt0 */
+- };
+- };
+-
+- fragment@3 {
+- target = <&i2c0_pins>;
+- __dormant__ {
+- brcm,pins = <44 45>;
+- brcm,function = <5>; /* alt1 */
+- };
+- };
+-
+- fragment@4 {
+- target = <&i2c0_pins>;
+- __dormant__ {
+- brcm,pins = <46 47>;
+- brcm,function = <4>; /* alt0 */
+- };
+- };
+-
+- fragment@5 {
+- target = <&i2c0>;
+- __dormant__ {
+- compatible = "brcm,bcm2708-i2c";
+- };
+- };
+-
+- __overrides__ {
+- sda0_pin = <&frag1>,"brcm,pins:0";
+- scl0_pin = <&frag1>,"brcm,pins:4";
+- pins_0_1 = <0>,"+1-2-3-4";
+- pins_28_29 = <0>,"-1+2-3-4";
+- pins_44_45 = <0>,"-1-2+3-4";
+- pins_46_47 = <0>,"-1-2-3+4";
+- combine = <0>, "!5";
+- };
++ __overrides__ {
++ sda0_pin = <&pins1>,"brcm,pins:0",
++ <&pins2>,"brcm,pins:0",
++ <&pins3>,"brcm,pins:0",
++ <&pins4>,"brcm,pins:0";
++ scl0_pin = <&pins1>,"brcm,pins:4",
++ <&pins2>,"brcm,pins:4",
++ <&pins3>,"brcm,pins:4",
++ <&pins4>,"brcm,pins:4";
++ };
+ };
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/i2c0-overlay.dts
+@@ -0,0 +1,61 @@
++/dts-v1/;
++/plugin/;
++
++/{
++ compatible = "brcm,bcm2835";
++
++ fragment@0 {
++ target = <&i2c0>;
++ __overlay__ {
++ status = "okay";
++ pinctrl-0 = <&i2c0_pins>;
++ };
++ };
++
++ fragment@1 {
++ target = <&i2c0_pins>;
++ pins1: __overlay__ {
++ brcm,pins = <0 1>;
++ brcm,function = <4>; /* alt0 */
++ };
++ };
++
++ fragment@2 {
++ target = <&i2c0_pins>;
++ pins2: __dormant__ {
++ brcm,pins = <28 29>;
++ brcm,function = <4>; /* alt0 */
++ };
++ };
++
++ fragment@3 {
++ target = <&i2c0_pins>;
++ pins3: __dormant__ {
++ brcm,pins = <44 45>;
++ brcm,function = <5>; /* alt1 */
++ };
++ };
++
++ fragment@4 {
++ target = <&i2c0_pins>;
++ pins4: __dormant__ {
++ brcm,pins = <46 47>;
++ brcm,function = <4>; /* alt0 */
++ };
++ };
++
++ fragment@5 {
++ target = <&i2c0>;
++ __dormant__ {
++ compatible = "brcm,bcm2708-i2c";
++ };
++ };
++
++ __overrides__ {
++ pins_0_1 = <0>,"+1-2-3-4";
++ pins_28_29 = <0>,"-1+2-3-4";
++ pins_44_45 = <0>,"-1-2+3-4";
++ pins_46_47 = <0>,"-1-2-3+4";
++ combine = <0>, "!5";
++ };
++};
+--- a/arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts
+@@ -1,43 +1,9 @@
+-/*
+- * Device tree overlay for i2c_bcm2708, i2c1 bus
+- *
+- * Compile:
+- * dtc -@ -I dts -O dtb -o i2c1-bcm2708-overlay.dtb i2c1-bcm2708-overlay.dts
+- */
+-
+-/dts-v1/;
+-/plugin/;
++#include "i2c1-overlay.dts"
+
+ /{
+- compatible = "brcm,bcm2835";
+-
+- fragment@0 {
+- target = <&i2c1>;
+- __overlay__ {
+- pinctrl-0 = <&i2c1_pins>;
+- status = "okay";
+- };
+- };
+-
+- fragment@1 {
+- target = <&i2c1_pins>;
+- pins: __overlay__ {
+- brcm,pins = <2 3>;
+- brcm,function = <4>; /* alt 0 */
+- };
+- };
+-
+- fragment@2 {
+- target = <&i2c1>;
+- __dormant__ {
+- compatible = "brcm,bcm2708-i2c";
+- };
+- };
+-
+- __overrides__ {
+- sda1_pin = <&pins>,"brcm,pins:0";
+- scl1_pin = <&pins>,"brcm,pins:4";
+- pin_func = <&pins>,"brcm,function:0";
+- combine = <0>, "!2";
+- };
++ __overrides__ {
++ sda1_pin = <&pins1>,"brcm,pins:0", <&pins2>,"brcm,pins:0";
++ scl1_pin = <&pins1>,"brcm,pins:4", <&pins1>,"brcm,pins:4";
++ pin_func = <&pins1>,"brcm,function:0", <&pins2>,"brcm,function:0";
++ };
+ };
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/i2c1-overlay.dts
+@@ -0,0 +1,44 @@
++/dts-v1/;
++/plugin/;
++
++/{
++ compatible = "brcm,bcm2835";
++
++ fragment@0 {
++ target = <&i2c1>;
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c1_pins>;
++ };
++ };
++
++ fragment@1 {
++ target = <&i2c1_pins>;
++ pins1: __overlay__ {
++ brcm,pins = <2 3>;
++ brcm,function = <4>; /* alt 0 */
++ };
++ };
++
++ fragment@2 {
++ target = <&i2c1_pins>;
++ pins2: __dormant__ {
++ brcm,pins = <44 45>;
++ brcm,function = <6>; /* alt 2 */
++ };
++ };
++
++ fragment@3 {
++ target = <&i2c1>;
++ __dormant__ {
++ compatible = "brcm,bcm2708-i2c";
++ };
++ };
++
++ __overrides__ {
++ pins_2_3 = <0>,"=1!2";
++ pins_44_45 = <0>,"!1=2";
++ combine = <0>, "!3";
++ };
++};
--- /dev/null
+From e7efd5c5b3e6e7f900eca6323fb593f80471a380 Mon Sep 17 00:00:00 2001
+From: Giedrius <giedrius@blokas.io>
+Date: Fri, 12 Jul 2019 17:45:55 +0300
+Subject: [PATCH 709/725] Pisound: Remove spinlock usage around spi_sync
+
+---
+ sound/soc/bcm/pisound.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/sound/soc/bcm/pisound.c
++++ b/sound/soc/bcm/pisound.c
+@@ -286,9 +286,6 @@ static irqreturn_t data_available_interr
+ return IRQ_HANDLED;
+ }
+
+-static DEFINE_SPINLOCK(spilock);
+-static unsigned long spilockflags;
+-
+ static uint16_t spi_transfer16(uint16_t val)
+ {
+ uint8_t txbuf[2];
+@@ -333,9 +330,7 @@ static void spi_transfer(const uint8_t *
+ transfer.delay_usecs = 10;
+ spi_message_add_tail(&transfer, &msg);
+
+- spin_lock_irqsave(&spilock, spilockflags);
+ err = spi_sync(pisnd_spi_device, &msg);
+- spin_unlock_irqrestore(&spilock, spilockflags);
+
+ if (err < 0) {
+ printe("spi_sync error %d\n", err);
--- /dev/null
+From 804767a8871d01153c7a6e974730eda806fdbef6 Mon Sep 17 00:00:00 2001
+From: Andrei Gherzan <andrei@balena.io>
+Date: Tue, 16 Jul 2019 13:28:22 +0100
+Subject: [PATCH 710/725] arm64/mm: Limit the DMA zone for arm64
+
+On RaspberryPi, only the first 1Gb can be used for DMA[1].
+
+[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2019-July/665986.html
+
+Signed-off-by: Andrei Gherzan <andrei@balena.io>
+---
+ arch/arm64/mm/init.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm64/mm/init.c
++++ b/arch/arm64/mm/init.c
+@@ -224,7 +224,7 @@ static void __init reserve_elfcorehdr(vo
+ static phys_addr_t __init max_zone_dma_phys(void)
+ {
+ phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, 32);
+- return min(offset + (1ULL << 32), memblock_end_of_DRAM());
++ return min(offset + (1ULL << 30), memblock_end_of_DRAM());
+ }
+
+ #ifdef CONFIG_NUMA
--- /dev/null
+From f3fe10334b7073f38eb3e36441a5313e1d9b2324 Mon Sep 17 00:00:00 2001
+From: Aapo Vienamo <aapo.vienamo@iki.fi>
+Date: Wed, 17 Jul 2019 11:05:20 +0300
+Subject: [PATCH 711/725] configs: Enable iio driver for TI ADS1015
+
+Signed-off-by: Aapo Vienamo <aapo.vienamo@iki.fi>
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcm2711_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ 3 files changed, 3 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -1291,6 +1291,7 @@ CONFIG_IIO=m
+ CONFIG_IIO_BUFFER_CB=m
+ CONFIG_MCP320X=m
+ CONFIG_MCP3422=m
++CONFIG_TI_ADS1015=m
+ CONFIG_DHT11=m
+ CONFIG_HDC100X=m
+ CONFIG_HTU21=m
+--- a/arch/arm/configs/bcm2711_defconfig
++++ b/arch/arm/configs/bcm2711_defconfig
+@@ -1322,6 +1322,7 @@ CONFIG_IIO=m
+ CONFIG_IIO_BUFFER_CB=m
+ CONFIG_MCP320X=m
+ CONFIG_MCP3422=m
++CONFIG_TI_ADS1015=m
+ CONFIG_DHT11=m
+ CONFIG_HDC100X=m
+ CONFIG_HTU21=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -1301,6 +1301,7 @@ CONFIG_IIO=m
+ CONFIG_IIO_BUFFER_CB=m
+ CONFIG_MCP320X=m
+ CONFIG_MCP3422=m
++CONFIG_TI_ADS1015=m
+ CONFIG_DHT11=m
+ CONFIG_HDC100X=m
+ CONFIG_HTU21=m
--- /dev/null
+From 6c46cf889cfd831ecce288005f85c7a254a64cb1 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Thu, 18 Jul 2019 13:05:35 +0100
+Subject: [PATCH 712/725] bcm2711_defconfig: enable PCI portbus support (and
+ implicitly, PCIe AER)
+
+PCIe advanced error reporting is supported by the root complex, so make
+use of it.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ arch/arm/configs/bcm2711_defconfig | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm/configs/bcm2711_defconfig
++++ b/arch/arm/configs/bcm2711_defconfig
+@@ -33,6 +33,8 @@ CONFIG_ARCH_BCM2835=y
+ CONFIG_ARM_LPAE=y
+ # CONFIG_CACHE_L2X0 is not set
+ CONFIG_PCI=y
++CONFIG_PCIEPORTBUS=y
++# CONFIG_PCIEASPM is not set
+ CONFIG_PCI_MSI=y
+ CONFIG_PCIE_BRCMSTB=y
+ CONFIG_SMP=y
--- /dev/null
+From 9288f45112f6381ef5697d451b7f44b306e61f8e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 3 Jul 2019 17:44:53 +0100
+Subject: [PATCH 713/725] drm/vc4: Query firmware for custom HDMI mode
+
+Allow custom HDMI modes to be specified from config.txt,
+and these then override EDID parsing.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 142 ++++++++++++++-----------
+ 1 file changed, 81 insertions(+), 61 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -1035,6 +1035,58 @@ vc4_fkms_connector_detect(struct drm_con
+ return connector_status_connected;
+ }
+
++/* Queries the firmware to populate a drm_mode structure for this display */
++static int vc4_fkms_get_fw_mode(struct vc4_fkms_connector *fkms_connector,
++ struct drm_display_mode *mode)
++{
++ struct vc4_dev *vc4 = fkms_connector->vc4_dev;
++ struct set_timings timings = { 0 };
++ int ret;
++
++ timings.display = fkms_connector->display_number;
++
++ ret = rpi_firmware_property(vc4->firmware,
++ RPI_FIRMWARE_GET_DISPLAY_TIMING, &timings,
++ sizeof(timings));
++ if (ret || !timings.clock)
++ /* No mode returned - abort */
++ return -1;
++
++ /* Equivalent to DRM_MODE macro. */
++ memset(mode, 0, sizeof(*mode));
++ strncpy(mode->name, "FIXED_MODE", sizeof(mode->name));
++ mode->status = 0;
++ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
++ mode->clock = timings.clock;
++ mode->hdisplay = timings.hdisplay;
++ mode->hsync_start = timings.hsync_start;
++ mode->hsync_end = timings.hsync_end;
++ mode->htotal = timings.htotal;
++ mode->hskew = 0;
++ mode->vdisplay = timings.vdisplay;
++ mode->vsync_start = timings.vsync_start;
++ mode->vsync_end = timings.vsync_end;
++ mode->vtotal = timings.vtotal;
++ mode->vscan = timings.vscan;
++
++ if (timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
++ mode->flags |= DRM_MODE_FLAG_PHSYNC;
++ else
++ mode->flags |= DRM_MODE_FLAG_NHSYNC;
++
++ if (timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
++ mode->flags |= DRM_MODE_FLAG_PVSYNC;
++ else
++ mode->flags |= DRM_MODE_FLAG_NVSYNC;
++
++ if (timings.flags & TIMINGS_FLAGS_INTERLACE)
++ mode->flags |= DRM_MODE_FLAG_INTERLACE;
++
++ mode->base.type = DRM_MODE_OBJECT_MODE;
++
++ return 0;
++}
++
+ static int vc4_fkms_get_edid_block(void *data, u8 *buf, unsigned int block,
+ size_t len)
+ {
+@@ -1063,30 +1115,40 @@ static int vc4_fkms_connector_get_modes(
+ to_vc4_fkms_connector(connector);
+ struct drm_encoder *encoder = fkms_connector->encoder;
+ struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
+- int ret = 0;
++ struct drm_display_mode fw_mode;
++ struct drm_display_mode *mode;
+ struct edid *edid;
++ int num_modes;
+
+- edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block,
+- fkms_connector);
++ if (!vc4_fkms_get_fw_mode(fkms_connector, &fw_mode)) {
++ drm_mode_debug_printmodeline(&fw_mode);
++ mode = drm_mode_duplicate(connector->dev,
++ &fw_mode);
++ drm_mode_probed_add(connector, mode);
++ num_modes = 1; /* 1 mode */
++ } else {
++ edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block,
++ fkms_connector);
+
+- /* FIXME: Can we do CEC?
+- * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
+- * if (!edid)
+- * return -ENODEV;
+- */
+-
+- vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
+-
+- if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
+- vc4_encoder->rgb_range_selectable =
+- drm_rgb_quant_range_selectable(edid);
++ /* FIXME: Can we do CEC?
++ * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
++ * if (!edid)
++ * return -ENODEV;
++ */
++
++ vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
++
++ if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
++ vc4_encoder->rgb_range_selectable =
++ drm_rgb_quant_range_selectable(edid);
++ }
++
++ drm_connector_update_edid_property(connector, edid);
++ num_modes = drm_add_edid_modes(connector, edid);
++ kfree(edid);
+ }
+
+- drm_connector_update_edid_property(connector, edid);
+- ret = drm_add_edid_modes(connector, edid);
+- kfree(edid);
+-
+- return ret;
++ return num_modes;
+ }
+
+ /* This is the DSI panel resolution. Use this as a default should the firmware
+@@ -1104,57 +1166,15 @@ static int vc4_fkms_lcd_connector_get_mo
+ {
+ struct vc4_fkms_connector *fkms_connector =
+ to_vc4_fkms_connector(connector);
+- struct vc4_dev *vc4 = fkms_connector->vc4_dev;
+ struct drm_display_mode *mode;
+- struct mailbox_set_mode mb = {
+- .tag1 = { RPI_FIRMWARE_GET_DISPLAY_TIMING,
+- sizeof(struct set_timings), 0},
+- .timings = { .display = fkms_connector->display_number },
+- };
+ struct drm_display_mode fw_mode;
+- int ret = 0;
+-
+- ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
+- if (!ret) {
+- /* Equivalent to DRM_MODE macro. */
+- memset(&fw_mode, 0, sizeof(fw_mode));
+- strncpy(fw_mode.name, "LCD_MODE", sizeof(fw_mode.name));
+- fw_mode.status = 0;
+- fw_mode.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+- fw_mode.clock = mb.timings.clock;
+- fw_mode.hdisplay = mb.timings.hdisplay;
+- fw_mode.hsync_start = mb.timings.hsync_start;
+- fw_mode.hsync_end = mb.timings.hsync_end;
+- fw_mode.htotal = mb.timings.htotal;
+- fw_mode.hskew = 0;
+- fw_mode.vdisplay = mb.timings.vdisplay;
+- fw_mode.vsync_start = mb.timings.vsync_start;
+- fw_mode.vsync_end = mb.timings.vsync_end;
+- fw_mode.vtotal = mb.timings.vtotal;
+- fw_mode.vscan = mb.timings.vscan;
+- if (mb.timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
+- fw_mode.flags |= DRM_MODE_FLAG_PHSYNC;
+- else
+- fw_mode.flags |= DRM_MODE_FLAG_NHSYNC;
+- if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
+- fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
+- else
+- fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
+- if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
+- fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
+- else
+- fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
+- if (mb.timings.flags & TIMINGS_FLAGS_INTERLACE)
+- fw_mode.flags |= DRM_MODE_FLAG_INTERLACE;
+-
+- fw_mode.base.type = DRM_MODE_OBJECT_MODE;
+
++ if (!vc4_fkms_get_fw_mode(fkms_connector, &fw_mode) && fw_mode.clock)
+ mode = drm_mode_duplicate(connector->dev,
+ &fw_mode);
+- } else {
++ else
+ mode = drm_mode_duplicate(connector->dev,
+ &lcd_mode);
+- }
+
+ if (!mode) {
+ DRM_ERROR("Failed to create a new display mode\n");
--- /dev/null
+From 0dd10ab858ea90d6b8477c0ad54247b105e316b9 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 11 Jul 2019 15:12:05 +0100
+Subject: [PATCH 714/725] drm/vc4: Pass the drm vrefresh to the firmware on
+ mode set
+
+More for completeness than need, but use drm_mode_vrefresh
+to compute the vrefresh value, and pass that down to the
+firmware on mode set.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -737,8 +737,8 @@ static void vc4_crtc_mode_set_nofb(struc
+ mode->hdisplay, mode->hsync_start, mode->hsync_end,
+ mode->htotal, mode->hskew, mode->vdisplay,
+ mode->vsync_start, mode->vsync_end, mode->vtotal,
+- mode->vscan, mode->vrefresh, mode->picture_aspect_ratio,
+- mode->flags);
++ mode->vscan, drm_mode_vrefresh(mode),
++ mode->picture_aspect_ratio, mode->flags);
+ mb.timings.display = vc4_crtc->display_number;
+
+ mb.timings.video_id_code = frame.avi.video_code;
+@@ -754,7 +754,7 @@ static void vc4_crtc_mode_set_nofb(struc
+ mb.timings.vsync_end = mode->vsync_end;
+ mb.timings.vtotal = mode->vtotal;
+ mb.timings.vscan = mode->vscan;
+- mb.timings.vrefresh = 0;
++ mb.timings.vrefresh = drm_mode_vrefresh(mode);
+ mb.timings.flags = 0;
+ if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+ mb.timings.flags |= TIMINGS_FLAGS_H_SYNC_POS;
--- /dev/null
+From abd2aaea7bbe687aadff3f1dad14ea5458be2d00 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 23 Jul 2019 12:55:07 +0100
+Subject: [PATCH 715/725] overlays: audremap: Support GPIOs 18 & 19
+
+PWM audio can also be used on GPIOs 18 and 19, so add the pins_18_19
+parameter to select that location. pins_12_13 explicitly chooses GPIOs
+12 and 13, although this is the default behaviour so is there only for
+completeness.
+
+See: https://github.com/raspberrypi/firmware/issues/1178
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README | 4 +++-
+ arch/arm/boot/dts/overlays/audremap-overlay.dts | 16 ++++++++++++++++
+ 2 files changed, 19 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -475,12 +475,14 @@ Params: <None>
+
+
+ Name: audremap
+-Info: Switches PWM sound output to pins 12 (Right) & 13 (Left)
++Info: Switches PWM sound output to GPIOs on the 40-pin header
+ Load: dtoverlay=audremap,<param>=<val>
+ Params: swap_lr Reverse the channel allocation, which will also
+ swap the audio jack outputs (default off)
+ enable_jack Don't switch off the audio jack output
+ (default off)
++ pins_12_13 Select GPIOs 12 & 13 (default)
++ pins_18_19 Select GPIOs 18 & 19
+
+
+ Name: balena-fin
+--- a/arch/arm/boot/dts/overlays/audremap-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audremap-overlay.dts
+@@ -7,13 +7,29 @@
+ fragment@0 {
+ target = <&audio_pins>;
+ frag0: __overlay__ {
++ };
++ };
++
++ fragment@1 {
++ target = <&audio_pins>;
++ __overlay__ {
+ brcm,pins = < 12 13 >;
+ brcm,function = < 4 >; /* alt0 alt0 */
+ };
+ };
+
++ fragment@2 {
++ target = <&audio_pins>;
++ __dormant__ {
++ brcm,pins = < 18 19 >;
++ brcm,function = < 2 >; /* alt5 alt5 */
++ };
++ };
++
+ __overrides__ {
+ swap_lr = <&frag0>, "swap_lr?";
+ enable_jack = <&frag0>, "enable_jack?";
++ pins_12_13 = <0>,"+1-2";
++ pins_18_19 = <0>,"-1+2";
+ };
+ };
--- /dev/null
+From 522215d35cc376e452584dfc9d78aa68600861b8 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Thu, 6 Dec 2018 15:24:35 +0100
+Subject: [PATCH 716/725] drm/connector: Fix drm_mode_create_tv_properties()
+ doc
+
+Commit eda6887f1961e0d2fb866b1a520b2de5b3828de5 upstream.
+
+The in the kernel-doc header did not match the function name.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-2-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/drm_connector.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/drm_connector.c
++++ b/drivers/gpu/drm/drm_connector.c
+@@ -1110,7 +1110,7 @@ void drm_hdmi_avi_infoframe_content_type
+ EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
+
+ /**
+- * drm_create_tv_properties - create TV specific connector properties
++ * drm_mode_create_tv_properties - create TV specific connector properties
+ * @dev: DRM device
+ * @num_modes: number of different TV formats (modes) supported
+ * @modes: array of pointers to strings containing name of each format
--- /dev/null
+From ef59d7d000bea6755a9e57bd0d7b6558172dad22 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Thu, 6 Dec 2018 15:24:36 +0100
+Subject: [PATCH 717/725] drm/connector: Clarify the unit of TV margins
+
+Commit 56406e15b5e83256151ef74eb1a219cbf13d91c8 upstream.
+
+All margins are expressed in pixels. Clarify that in the doc.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-3-boris.brezillon@bootlin.com
+---
+ include/drm/drm_connector.h | 2 +-
+ include/drm/drm_mode_config.h | 8 ++++----
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -346,7 +346,7 @@ int drm_display_info_set_bus_formats(str
+ /**
+ * struct drm_tv_connector_state - TV connector related states
+ * @subconnector: selected subconnector
+- * @margins: margins
++ * @margins: margins (all margins are expressed in pixels)
+ * @margins.left: left margin
+ * @margins.right: right margin
+ * @margins.top: top margin
+--- a/include/drm/drm_mode_config.h
++++ b/include/drm/drm_mode_config.h
+@@ -668,22 +668,22 @@ struct drm_mode_config {
+ struct drm_property *tv_mode_property;
+ /**
+ * @tv_left_margin_property: Optional TV property to set the left
+- * margin.
++ * margin (expressed in pixels).
+ */
+ struct drm_property *tv_left_margin_property;
+ /**
+ * @tv_right_margin_property: Optional TV property to set the right
+- * margin.
++ * margin (expressed in pixels).
+ */
+ struct drm_property *tv_right_margin_property;
+ /**
+ * @tv_top_margin_property: Optional TV property to set the right
+- * margin.
++ * margin (expressed in pixels).
+ */
+ struct drm_property *tv_top_margin_property;
+ /**
+ * @tv_bottom_margin_property: Optional TV property to set the right
+- * margin.
++ * margin (expressed in pixels).
+ */
+ struct drm_property *tv_bottom_margin_property;
+ /**
--- /dev/null
+From 551ce8969f5b671760523202b4af7e059389917e Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Thu, 6 Dec 2018 15:24:37 +0100
+Subject: [PATCH 718/725] drm/connector: Allow creation of margin props alone
+
+Commit 6c4f52dca36f5e3e2354c30591d38e92f4657ed9 upstream.
+
+TV margins properties can only be added as part of the SDTV TV
+connector properties creation, but we might need those props for HDMI
+TVs too, so let's move the margins props creation in a separate
+function and expose it to drivers.
+
+We also add an helper to attach margins props to a connector.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-4-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/drm_connector.c | 83 ++++++++++++++++++++++++++-------
+ include/drm/drm_connector.h | 2 +
+ 2 files changed, 67 insertions(+), 18 deletions(-)
+
+--- a/drivers/gpu/drm/drm_connector.c
++++ b/drivers/gpu/drm/drm_connector.c
+@@ -1110,6 +1110,70 @@ void drm_hdmi_avi_infoframe_content_type
+ EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
+
+ /**
++ * drm_mode_attach_tv_margin_properties - attach TV connector margin properties
++ * @connector: DRM connector
++ *
++ * Called by a driver when it needs to attach TV margin props to a connector.
++ * Typically used on SDTV and HDMI connectors.
++ */
++void drm_connector_attach_tv_margin_properties(struct drm_connector *connector)
++{
++ struct drm_device *dev = connector->dev;
++
++ drm_object_attach_property(&connector->base,
++ dev->mode_config.tv_left_margin_property,
++ 0);
++ drm_object_attach_property(&connector->base,
++ dev->mode_config.tv_right_margin_property,
++ 0);
++ drm_object_attach_property(&connector->base,
++ dev->mode_config.tv_top_margin_property,
++ 0);
++ drm_object_attach_property(&connector->base,
++ dev->mode_config.tv_bottom_margin_property,
++ 0);
++}
++EXPORT_SYMBOL(drm_connector_attach_tv_margin_properties);
++
++/**
++ * drm_mode_create_tv_margin_properties - create TV connector margin properties
++ * @dev: DRM device
++ *
++ * Called by a driver's HDMI connector initialization routine, this function
++ * creates the TV margin properties for a given device. No need to call this
++ * function for an SDTV connector, it's already called from
++ * drm_mode_create_tv_properties().
++ */
++int drm_mode_create_tv_margin_properties(struct drm_device *dev)
++{
++ if (dev->mode_config.tv_left_margin_property)
++ return 0;
++
++ dev->mode_config.tv_left_margin_property =
++ drm_property_create_range(dev, 0, "left margin", 0, 100);
++ if (!dev->mode_config.tv_left_margin_property)
++ return -ENOMEM;
++
++ dev->mode_config.tv_right_margin_property =
++ drm_property_create_range(dev, 0, "right margin", 0, 100);
++ if (!dev->mode_config.tv_right_margin_property)
++ return -ENOMEM;
++
++ dev->mode_config.tv_top_margin_property =
++ drm_property_create_range(dev, 0, "top margin", 0, 100);
++ if (!dev->mode_config.tv_top_margin_property)
++ return -ENOMEM;
++
++ dev->mode_config.tv_bottom_margin_property =
++ drm_property_create_range(dev, 0, "bottom margin", 0, 100);
++ if (!dev->mode_config.tv_bottom_margin_property)
++ return -ENOMEM;
++
++ return 0;
++}
++EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
++
++/**
+ * drm_mode_create_tv_properties - create TV specific connector properties
+ * @dev: DRM device
+ * @num_modes: number of different TV formats (modes) supported
+@@ -1155,24 +1219,7 @@ int drm_mode_create_tv_properties(struct
+ /*
+ * Other, TV specific properties: margins & TV modes.
+ */
+- dev->mode_config.tv_left_margin_property =
+- drm_property_create_range(dev, 0, "left margin", 0, 100);
+- if (!dev->mode_config.tv_left_margin_property)
+- goto nomem;
+-
+- dev->mode_config.tv_right_margin_property =
+- drm_property_create_range(dev, 0, "right margin", 0, 100);
+- if (!dev->mode_config.tv_right_margin_property)
+- goto nomem;
+-
+- dev->mode_config.tv_top_margin_property =
+- drm_property_create_range(dev, 0, "top margin", 0, 100);
+- if (!dev->mode_config.tv_top_margin_property)
+- goto nomem;
+-
+- dev->mode_config.tv_bottom_margin_property =
+- drm_property_create_range(dev, 0, "bottom margin", 0, 100);
+- if (!dev->mode_config.tv_bottom_margin_property)
++ if (drm_mode_create_tv_margin_properties(dev))
+ goto nomem;
+
+ dev->mode_config.tv_mode_property =
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -1175,9 +1175,11 @@ const char *drm_get_tv_select_name(int v
+ const char *drm_get_content_protection_name(int val);
+
+ int drm_mode_create_dvi_i_properties(struct drm_device *dev);
++int drm_mode_create_tv_margin_properties(struct drm_device *dev);
+ int drm_mode_create_tv_properties(struct drm_device *dev,
+ unsigned int num_modes,
+ const char * const modes[]);
++void drm_connector_attach_tv_margin_properties(struct drm_connector *conn);
+ int drm_mode_create_scaling_mode_property(struct drm_device *dev);
+ int drm_connector_attach_content_type_property(struct drm_connector *dev);
+ int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
--- /dev/null
+From 4ede5cbb2dffb6c2d5a29a1da8daa851b8351c55 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Thu, 6 Dec 2018 15:24:38 +0100
+Subject: [PATCH 719/725] drm/vc4: Take margin setup into account when updating
+ planes
+
+Commit 666e73587f90f42d90385c1bea1009a650bf73f4 upstream.
+
+Applyin margins is just a matter of scaling all planes appropriately
+and adjusting the CRTC X/Y offset to account for the
+left/right/top/bottom borders.
+
+Create a vc4_plane_margins_adj() function doing that and call it from
+vc4_plane_setup_clipping_and_scaling() so that we are ready to attach
+margins properties to the HDMI connector.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-5-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_crtc.c | 43 +++++++++++++++++++++++++++
+ drivers/gpu/drm/vc4/vc4_drv.h | 3 ++
+ drivers/gpu/drm/vc4/vc4_plane.c | 51 +++++++++++++++++++++++++++++++++
+ 3 files changed, 97 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_crtc.c
++++ b/drivers/gpu/drm/vc4/vc4_crtc.c
+@@ -48,6 +48,13 @@ struct vc4_crtc_state {
+ struct drm_mm_node mm;
+ bool feed_txp;
+ bool txp_armed;
++
++ struct {
++ unsigned int left;
++ unsigned int right;
++ unsigned int top;
++ unsigned int bottom;
++ } margins;
+ };
+
+ static inline struct vc4_crtc_state *
+@@ -623,6 +630,37 @@ static enum drm_mode_status vc4_crtc_mod
+ return MODE_OK;
+ }
+
++void vc4_crtc_get_margins(struct drm_crtc_state *state,
++ unsigned int *left, unsigned int *right,
++ unsigned int *top, unsigned int *bottom)
++{
++ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
++ struct drm_connector_state *conn_state;
++ struct drm_connector *conn;
++ int i;
++
++ *left = vc4_state->margins.left;
++ *right = vc4_state->margins.right;
++ *top = vc4_state->margins.top;
++ *bottom = vc4_state->margins.bottom;
++
++ /* We have to interate over all new connector states because
++ * vc4_crtc_get_margins() might be called before
++ * vc4_crtc_atomic_check() which means margins info in vc4_crtc_state
++ * might be outdated.
++ */
++ for_each_new_connector_in_state(state->state, conn, conn_state, i) {
++ if (conn_state->crtc != state->crtc)
++ continue;
++
++ *left = conn_state->tv.margins.left;
++ *right = conn_state->tv.margins.right;
++ *top = conn_state->tv.margins.top;
++ *bottom = conn_state->tv.margins.bottom;
++ break;
++ }
++}
++
+ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+ {
+@@ -670,6 +708,10 @@ static int vc4_crtc_atomic_check(struct
+ vc4_state->feed_txp = false;
+ }
+
++ vc4_state->margins.left = conn_state->tv.margins.left;
++ vc4_state->margins.right = conn_state->tv.margins.right;
++ vc4_state->margins.top = conn_state->tv.margins.top;
++ vc4_state->margins.bottom = conn_state->tv.margins.bottom;
+ break;
+ }
+
+@@ -971,6 +1013,7 @@ static struct drm_crtc_state *vc4_crtc_d
+
+ old_vc4_state = to_vc4_crtc_state(crtc->state);
+ vc4_state->feed_txp = old_vc4_state->feed_txp;
++ vc4_state->margins = old_vc4_state->margins;
+
+ __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
+ return &vc4_state->base;
+--- a/drivers/gpu/drm/vc4/vc4_drv.h
++++ b/drivers/gpu/drm/vc4/vc4_drv.h
+@@ -705,6 +705,9 @@ bool vc4_crtc_get_scanoutpos(struct drm_
+ const struct drm_display_mode *mode);
+ void vc4_crtc_handle_vblank(struct vc4_crtc *crtc);
+ void vc4_crtc_txp_armed(struct drm_crtc_state *state);
++void vc4_crtc_get_margins(struct drm_crtc_state *state,
++ unsigned int *right, unsigned int *left,
++ unsigned int *top, unsigned int *bottom);
+
+ /* vc4_debugfs.c */
+ int vc4_debugfs_init(struct drm_minor *minor);
+--- a/drivers/gpu/drm/vc4/vc4_plane.c
++++ b/drivers/gpu/drm/vc4/vc4_plane.c
+@@ -258,6 +258,52 @@ static u32 vc4_get_scl_field(struct drm_
+ }
+ }
+
++static int vc4_plane_margins_adj(struct drm_plane_state *pstate)
++{
++ struct vc4_plane_state *vc4_pstate = to_vc4_plane_state(pstate);
++ unsigned int left, right, top, bottom, adjhdisplay, adjvdisplay;
++ struct drm_crtc_state *crtc_state;
++
++ crtc_state = drm_atomic_get_new_crtc_state(pstate->state,
++ pstate->crtc);
++
++ vc4_crtc_get_margins(crtc_state, &left, &right, &top, &bottom);
++ if (!left && !right && !top && !bottom)
++ return 0;
++
++ if (left + right >= crtc_state->mode.hdisplay ||
++ top + bottom >= crtc_state->mode.vdisplay)
++ return -EINVAL;
++
++ adjhdisplay = crtc_state->mode.hdisplay - (left + right);
++ vc4_pstate->crtc_x = DIV_ROUND_CLOSEST(vc4_pstate->crtc_x *
++ adjhdisplay,
++ crtc_state->mode.hdisplay);
++ vc4_pstate->crtc_x += left;
++ if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - left)
++ vc4_pstate->crtc_x = crtc_state->mode.hdisplay - left;
++
++ adjvdisplay = crtc_state->mode.vdisplay - (top + bottom);
++ vc4_pstate->crtc_y = DIV_ROUND_CLOSEST(vc4_pstate->crtc_y *
++ adjvdisplay,
++ crtc_state->mode.vdisplay);
++ vc4_pstate->crtc_y += top;
++ if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - top)
++ vc4_pstate->crtc_y = crtc_state->mode.vdisplay - top;
++
++ vc4_pstate->crtc_w = DIV_ROUND_CLOSEST(vc4_pstate->crtc_w *
++ adjhdisplay,
++ crtc_state->mode.hdisplay);
++ vc4_pstate->crtc_h = DIV_ROUND_CLOSEST(vc4_pstate->crtc_h *
++ adjvdisplay,
++ crtc_state->mode.vdisplay);
++
++ if (!vc4_pstate->crtc_w || !vc4_pstate->crtc_h)
++ return -EINVAL;
++
++ return 0;
++}
++
+ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
+ {
+ struct drm_plane *plane = state->plane;
+@@ -269,6 +315,7 @@ static int vc4_plane_setup_clipping_and_
+ int num_planes = fb->format->num_planes;
+ u32 h_subsample = 1;
+ u32 v_subsample = 1;
++ int ret;
+ int i;
+
+ for (i = 0; i < num_planes; i++)
+@@ -292,6 +339,10 @@ static int vc4_plane_setup_clipping_and_
+ vc4_state->crtc_w = state->crtc_w;
+ vc4_state->crtc_h = state->crtc_h;
+
++ ret = vc4_plane_margins_adj(state);
++ if (ret)
++ return ret;
++
+ vc4_state->x_scaling[0] = vc4_get_scaling_mode(vc4_state->src_w[0],
+ vc4_state->crtc_w);
+ vc4_state->y_scaling[0] = vc4_get_scaling_mode(vc4_state->src_h[0],
--- /dev/null
+From c0f966a04d5ff984a33d7d7b9c3cdc32514ebc14 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Thu, 6 Dec 2018 15:24:39 +0100
+Subject: [PATCH 720/725] drm/vc4: Attach margin props to the HDMI connector
+
+Commit db999538fdb0679629d90652f8a1437df1e85a7d upstream.
+
+Now that the plane code takes the margins setup into account, we can
+safely attach margin props to the HDMI connector.
+
+We also take care of filling AVI infoframes correctly to expose the
+top/botton/left/right bar.
+
+Note that those margin props match pretty well the
+overscan_{left,right,top,bottom} properties defined in config.txt and
+parsed by the VC4 firmware.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-6-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -310,6 +310,7 @@ static struct drm_connector *vc4_hdmi_co
+ {
+ struct drm_connector *connector;
+ struct vc4_hdmi_connector *hdmi_connector;
++ int ret;
+
+ hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
+ GFP_KERNEL);
+@@ -323,6 +324,13 @@ static struct drm_connector *vc4_hdmi_co
+ DRM_MODE_CONNECTOR_HDMIA);
+ drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
+
++ /* Create and attach TV margin props to this connector. */
++ ret = drm_mode_create_tv_margin_properties(dev);
++ if (ret)
++ return ERR_PTR(ret);
++
++ drm_connector_attach_tv_margin_properties(connector);
++
+ connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT);
+
+@@ -408,6 +416,9 @@ static void vc4_hdmi_write_infoframe(str
+ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
+ {
+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
++ struct vc4_dev *vc4 = encoder->dev->dev_private;
++ struct vc4_hdmi *hdmi = vc4->hdmi;
++ struct drm_connector_state *cstate = hdmi->connector->state;
+ struct drm_crtc *crtc = encoder->crtc;
+ const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+ union hdmi_infoframe frame;
+@@ -426,6 +437,11 @@ static void vc4_hdmi_set_avi_infoframe(s
+ vc4_encoder->rgb_range_selectable,
+ false);
+
++ frame.avi.right_bar = cstate->tv.margins.right;
++ frame.avi.left_bar = cstate->tv.margins.left;
++ frame.avi.top_bar = cstate->tv.margins.top;
++ frame.avi.bottom_bar = cstate->tv.margins.bottom;
++
+ vc4_hdmi_write_infoframe(encoder, &frame);
+ }
+
--- /dev/null
+From c72b6c3836cf40b2a72e613db2d4a225b75e2e92 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 19 Jul 2019 15:35:13 +0100
+Subject: [PATCH 721/725] drm/vc4: Add support for margins to fkms
+
+Allows for overscan to be configured under FKMS.
+NB This is rescaling the planes, not reducing the size of the
+display mode.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 241 +++++++++++++++++++------
+ 1 file changed, 190 insertions(+), 51 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -256,6 +256,23 @@ static inline struct vc4_crtc *to_vc4_cr
+ return container_of(crtc, struct vc4_crtc, base);
+ }
+
++struct vc4_crtc_state {
++ struct drm_crtc_state base;
++
++ struct {
++ unsigned int left;
++ unsigned int right;
++ unsigned int top;
++ unsigned int bottom;
++ } margins;
++};
++
++static inline struct vc4_crtc_state *
++to_vc4_crtc_state(struct drm_crtc_state *crtc_state)
++{
++ return (struct vc4_crtc_state *)crtc_state;
++}
++
+ struct vc4_fkms_encoder {
+ struct drm_encoder base;
+ bool hdmi_monitor;
+@@ -365,17 +382,127 @@ static int vc4_plane_set_blank(struct dr
+ return ret;
+ }
+
++static void vc4_fkms_crtc_get_margins(struct drm_crtc_state *state,
++ unsigned int *left, unsigned int *right,
++ unsigned int *top, unsigned int *bottom)
++{
++ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
++ struct drm_connector_state *conn_state;
++ struct drm_connector *conn;
++ int i;
++
++ *left = vc4_state->margins.left;
++ *right = vc4_state->margins.right;
++ *top = vc4_state->margins.top;
++ *bottom = vc4_state->margins.bottom;
++
++ /* We have to interate over all new connector states because
++ * vc4_fkms_crtc_get_margins() might be called before
++ * vc4_fkms_crtc_atomic_check() which means margins info in
++ * vc4_crtc_state might be outdated.
++ */
++ for_each_new_connector_in_state(state->state, conn, conn_state, i) {
++ if (conn_state->crtc != state->crtc)
++ continue;
++
++ *left = conn_state->tv.margins.left;
++ *right = conn_state->tv.margins.right;
++ *top = conn_state->tv.margins.top;
++ *bottom = conn_state->tv.margins.bottom;
++ break;
++ }
++}
++
++static int vc4_fkms_margins_adj(struct drm_plane_state *pstate,
++ struct set_plane *plane)
++{
++ unsigned int left, right, top, bottom;
++ int adjhdisplay, adjvdisplay;
++ struct drm_crtc_state *crtc_state;
++
++ crtc_state = drm_atomic_get_new_crtc_state(pstate->state,
++ pstate->crtc);
++
++ vc4_fkms_crtc_get_margins(crtc_state, &left, &right, &top, &bottom);
++
++ if (!left && !right && !top && !bottom)
++ return 0;
++
++ if (left + right >= crtc_state->mode.hdisplay ||
++ top + bottom >= crtc_state->mode.vdisplay)
++ return -EINVAL;
++
++ adjhdisplay = crtc_state->mode.hdisplay - (left + right);
++ plane->dst_x = DIV_ROUND_CLOSEST(plane->dst_x * adjhdisplay,
++ (int)crtc_state->mode.hdisplay);
++ plane->dst_x += left;
++ if (plane->dst_x > (int)(crtc_state->mode.hdisplay - left))
++ plane->dst_x = crtc_state->mode.hdisplay - left;
++
++ adjvdisplay = crtc_state->mode.vdisplay - (top + bottom);
++ plane->dst_y = DIV_ROUND_CLOSEST(plane->dst_y * adjvdisplay,
++ (int)crtc_state->mode.vdisplay);
++ plane->dst_y += top;
++ if (plane->dst_y > (int)(crtc_state->mode.vdisplay - top))
++ plane->dst_y = crtc_state->mode.vdisplay - top;
++
++ plane->dst_w = DIV_ROUND_CLOSEST(plane->dst_w * adjhdisplay,
++ crtc_state->mode.hdisplay);
++ plane->dst_h = DIV_ROUND_CLOSEST(plane->dst_h * adjvdisplay,
++ crtc_state->mode.vdisplay);
++
++ if (!plane->dst_w || !plane->dst_h)
++ return -EINVAL;
++
++ return 0;
++}
++
+ static void vc4_plane_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+ {
+ struct drm_plane_state *state = plane->state;
++
++ /*
++ * Do NOT set now, as we haven't checked if the crtc is active or not.
++ * Set from vc4_plane_set_blank instead.
++ *
++ * If the CRTC is on (or going to be on) and we're enabled,
++ * then unblank. Otherwise, stay blank until CRTC enable.
++ */
++ if (state->crtc->state->active)
++ vc4_plane_set_blank(plane, false);
++}
++
++static void vc4_plane_atomic_disable(struct drm_plane *plane,
++ struct drm_plane_state *old_state)
++{
++ struct drm_plane_state *state = plane->state;
++ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
++
++ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane disable %dx%d@%d +%d,%d\n",
++ plane->base.id, plane->name,
++ state->crtc_w,
++ state->crtc_h,
++ vc4_plane->mb.plane.vc_image_type,
++ state->crtc_x,
++ state->crtc_y);
++ vc4_plane_set_blank(plane, true);
++}
++
++static bool plane_enabled(struct drm_plane_state *state)
++{
++ return state->fb && state->crtc;
++}
++
++static int vc4_plane_to_mb(struct drm_plane *plane,
++ struct mailbox_set_plane *mb,
++ struct drm_plane_state *state)
++{
+ struct drm_framebuffer *fb = state->fb;
+ struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
+ const struct drm_format_info *drm_fmt = fb->format;
+ const struct vc_image_format *vc_fmt =
+ vc4_get_vc_image_fmt(drm_fmt->format);
+- struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
+- struct mailbox_set_plane *mb = &vc4_plane->mb;
+ int num_planes = fb->format->num_planes;
+ struct drm_display_mode *mode = &state->crtc->mode;
+ unsigned int rotation = SUPPORTED_ROTATIONS;
+@@ -417,25 +544,7 @@ static void vc4_plane_atomic_update(stru
+ break;
+ }
+
+- /* FIXME: If the dest rect goes off screen then clip the src rect so we
+- * don't have off-screen pixels.
+- */
+- if (plane->type == DRM_PLANE_TYPE_CURSOR) {
+- /* There is no scaling on the cursor plane, therefore the calcs
+- * to alter the source crop as the cursor goes off the screen
+- * are simple.
+- */
+- if (mb->plane.dst_x + mb->plane.dst_w > mode->hdisplay) {
+- mb->plane.dst_w = mode->hdisplay - mb->plane.dst_x;
+- mb->plane.src_w = (mode->hdisplay - mb->plane.dst_x)
+- << 16;
+- }
+- if (mb->plane.dst_y + mb->plane.dst_h > mode->vdisplay) {
+- mb->plane.dst_h = mode->vdisplay - mb->plane.dst_y;
+- mb->plane.src_h = (mode->vdisplay - mb->plane.dst_y)
+- << 16;
+- }
+- }
++ vc4_fkms_margins_adj(state, &mb->plane);
+
+ if (num_planes > 1) {
+ /* Assume this must be YUV */
+@@ -525,38 +634,19 @@ static void vc4_plane_atomic_update(stru
+ state->alpha,
+ state->normalized_zpos);
+
+- /*
+- * Do NOT set now, as we haven't checked if the crtc is active or not.
+- * Set from vc4_plane_set_blank instead.
+- *
+- * If the CRTC is on (or going to be on) and we're enabled,
+- * then unblank. Otherwise, stay blank until CRTC enable.
+- */
+- if (state->crtc->state->active)
+- vc4_plane_set_blank(plane, false);
++ return 0;
+ }
+
+-static void vc4_plane_atomic_disable(struct drm_plane *plane,
+- struct drm_plane_state *old_state)
++static int vc4_plane_atomic_check(struct drm_plane *plane,
++ struct drm_plane_state *state)
+ {
+- //struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
+- struct drm_plane_state *state = plane->state;
+ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
+
+- DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane disable %dx%d@%d +%d,%d\n",
+- plane->base.id, plane->name,
+- state->crtc_w,
+- state->crtc_h,
+- vc4_plane->mb.plane.vc_image_type,
+- state->crtc_x,
+- state->crtc_y);
+- vc4_plane_set_blank(plane, true);
+-}
++ if (!plane_enabled(state))
++ return 0;
++
++ return vc4_plane_to_mb(plane, &vc4_plane->mb, state);
+
+-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)
+@@ -878,8 +968,23 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
+ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+ {
+- DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_check.\n",
+- crtc->base.id);
++ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
++ struct drm_connector *conn;
++ struct drm_connector_state *conn_state;
++ int i;
++
++ DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_check.\n", crtc->base.id);
++
++ for_each_new_connector_in_state(state->state, conn, conn_state, i) {
++ if (conn_state->crtc != crtc)
++ continue;
++
++ vc4_state->margins.left = conn_state->tv.margins.left;
++ vc4_state->margins.right = conn_state->tv.margins.right;
++ vc4_state->margins.top = conn_state->tv.margins.top;
++ vc4_state->margins.bottom = conn_state->tv.margins.bottom;
++ break;
++ }
+ return 0;
+ }
+
+@@ -980,6 +1085,33 @@ static int vc4_page_flip(struct drm_crtc
+ return drm_atomic_helper_page_flip(crtc, fb, event, flags, ctx);
+ }
+
++static struct drm_crtc_state *
++vc4_crtc_duplicate_state(struct drm_crtc *crtc)
++{
++ struct vc4_crtc_state *vc4_state, *old_vc4_state;
++
++ vc4_state = kzalloc(sizeof(*vc4_state), GFP_KERNEL);
++ if (!vc4_state)
++ return NULL;
++
++ old_vc4_state = to_vc4_crtc_state(crtc->state);
++ vc4_state->margins = old_vc4_state->margins;
++
++ __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
++ return &vc4_state->base;
++}
++
++static void
++vc4_crtc_reset(struct drm_crtc *crtc)
++{
++ if (crtc->state)
++ __drm_atomic_helper_crtc_destroy_state(crtc->state);
++
++ crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
++ if (crtc->state)
++ crtc->state->crtc = crtc;
++}
++
+ static int vc4_fkms_enable_vblank(struct drm_crtc *crtc)
+ {
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+@@ -1007,8 +1139,8 @@ static const struct drm_crtc_funcs vc4_c
+ .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,
++ .reset = vc4_crtc_reset,
++ .atomic_duplicate_state = vc4_crtc_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+ .enable_vblank = vc4_fkms_enable_vblank,
+ .disable_vblank = vc4_fkms_disable_vblank,
+@@ -1267,6 +1399,13 @@ vc4_fkms_connector_init(struct drm_devic
+ connector->interlace_allowed = 0;
+ }
+
++ /* Create and attach TV margin props to this connector. */
++ ret = drm_mode_create_tv_margin_properties(dev);
++ if (ret)
++ return ERR_PTR(ret);
++
++ drm_connector_attach_tv_margin_properties(connector);
++
+ connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT);
+
--- /dev/null
+From 261c08d7841e46294700409ae6b9c25f479ad94a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 19 Jul 2019 17:49:00 +0100
+Subject: [PATCH 722/725] drm/vc4: Ensure zpos is always initialised
+
+The compiler is warning that default_zpos can be used
+uninitialised as there is no default case to catch all plane
+types.
+No other plane types should ever be presented to vc4_fkms_plane_init,
+but add a default case regardless.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -773,6 +773,7 @@ static struct drm_plane *vc4_fkms_plane_
+ * other layers as requested by KMS.
+ */
+ switch (type) {
++ default:
+ case DRM_PLANE_TYPE_PRIMARY:
+ default_zpos = 0;
+ break;
--- /dev/null
+From c803db37ac929c9732ae02edf92925a00e600236 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Wed, 24 Jul 2019 14:36:53 +0100
+Subject: [PATCH 723/725] dts: bcm2838: add missing properties for pmu and gic
+ nodes
+
+The GIC has a virtual interface maintenance interrupt and the PMU
+interrupts need affinity mappings as they are wired to generic SPIs.
+
+Also, delete incorrect PMU compatible string.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2838.dtsi | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -35,6 +35,8 @@
+ <0x40042000 0x2000>,
+ <0x40044000 0x2000>,
+ <0x40046000 0x2000>;
++ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) |
++ IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+ thermal: thermal@7d5d2200 {
+@@ -222,15 +224,12 @@
+ };
+
+ arm-pmu {
+- /*
+- * N.B. the A72 PMU support only exists in arch/arm64, hence
+- * the fallback to the A53 version.
+- */
+- compatible = "arm,cortex-a72-pmu", "arm,cortex-a53-pmu";
++ compatible = "arm,cortex-a72-pmu";
+ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+ };
+
+ timer {
--- /dev/null
+From 9404c34f9d9aef6f1c5a8f8c223865a5adb81518 Mon Sep 17 00:00:00 2001
+From: Joerg Schambacher <joscha@schambacher.com>
+Date: Tue, 23 Jul 2019 16:57:35 +0200
+Subject: [PATCH 724/725] adds the Hifiberry DAC+ADC PRO version
+
+This adds the driver for the DAC+ADC PRO version of the Hifiberry soundcard with software controlled PCM1863 ADC
+Signed-off-by: Joerg Schambacher joerg@i2audio.com
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 21 +
+ .../hifiberry-dacplusadcpro-overlay.dts | 64 +++
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcm2711_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ sound/soc/bcm/Kconfig | 8 +
+ sound/soc/bcm/Makefile | 2 +
+ sound/soc/bcm/hifiberry_dacplusadcpro.c | 538 ++++++++++++++++++
+ 9 files changed, 637 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts
+ create mode 100644 sound/soc/bcm/hifiberry_dacplusadcpro.c
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -53,6 +53,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ hifiberry-dac.dtbo \
+ hifiberry-dacplus.dtbo \
+ hifiberry-dacplusadc.dtbo \
++ hifiberry-dacplusadcpro.dtbo \
+ hifiberry-digi.dtbo \
+ hifiberry-digi-pro.dtbo \
+ hy28a.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -883,6 +883,27 @@ Params: 24db_digital_gain Allow ga
+ master for bit clock and frame clock.
+
+
++Name: hifiberry-dacplusadcpro
++Info: Configures the HifiBerry DAC+ADC PRO audio card
++Load: dtoverlay=hifiberry-dacplusadcpro,<param>=<val>
++Params: 24db_digital_gain Allow gain to be applied via the PCM512x codec
++ Digital volume control. Enable with
++ "dtoverlay=hifiberry-dacplusadcpro,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!)
++ slave Force DAC+ADC Pro into slave mode, using Pi as
++ master for bit clock and frame clock.
++
++
+ Name: hifiberry-digi
+ Info: Configures the HifiBerry Digi and Digi+ audio card
+ Load: dtoverlay=hifiberry-digi
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts
+@@ -0,0 +1,64 @@
++// Definitions for HiFiBerry DAC+ADC PRO
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "brcm,bcm2708";
++
++ fragment@0 {
++ target-path = "/clocks";
++ __overlay__ {
++ dacpro_osc: dacpro_osc {
++ compatible = "hifiberry,dacpro-clk";
++ #clock-cells = <0>;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&i2s>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&i2c1>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ hb_dac: pcm5122@4d {
++ #sound-dai-cells = <0>;
++ compatible = "ti,pcm5122";
++ reg = <0x4d>;
++ clocks = <&dacpro_osc>;
++ status = "okay";
++ };
++ hb_adc: pcm186x@4a {
++ #sound-dai-cells = <0>;
++ compatible = "ti,pcm1863";
++ reg = <0x4a>;
++ clocks = <&dacpro_osc>;
++ status = "okay";
++ };
++ };
++ };
++
++ fragment@3 {
++ target = <&sound>;
++ hifiberry_dacplusadcpro: __overlay__ {
++ compatible = "hifiberry,hifiberry-dacplusadcpro";
++ audio-codec = <&hb_dac &hb_adc>;
++ i2s-controller = <&i2s>;
++ status = "okay";
++ };
++ };
++
++ __overrides__ {
++ 24db_digital_gain =
++ <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,24db_digital_gain?";
++ slave = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,slave?";
++ };
++};
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -961,6 +961,7 @@ CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SO
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
+ CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m
+--- a/arch/arm/configs/bcm2711_defconfig
++++ b/arch/arm/configs/bcm2711_defconfig
+@@ -972,6 +972,7 @@ CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SO
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
+ CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -953,6 +953,7 @@ CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SO
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC=m
++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
+ CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
+ CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -48,6 +48,14 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
+ help
+ Say Y or M if you want to add support for HifiBerry DAC+ADC.
+
++config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO
++ tristate "Support for HifiBerry DAC+ADC PRO"
++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++ select SND_SOC_PCM512x_I2C
++ select SND_SOC_PCM186X_I2C
++ help
++ Say Y or M if you want to add support for HifiBerry DAC+ADC PRO.
++
+ config SND_BCM2708_SOC_HIFIBERRY_DIGI
+ tristate "Support for HifiBerry Digi"
+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -14,6 +14,7 @@ snd-soc-googlevoicehat-codec-objs := goo
+ # BCM2708 Machine Support
+ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
+ snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
++snd-soc-hifiberry-dacplusadcpro-objs := hifiberry_dacplusadcpro.o
+ snd-soc-justboom-dac-objs := justboom-dac.o
+ snd-soc-rpi-cirrus-objs := rpi-cirrus.o
+ snd-soc-rpi-proto-objs := rpi-proto.o
+@@ -38,6 +39,7 @@ snd-soc-rpi-wm8804-soundcard-objs := rpi
+ obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD) += snd-soc-googlevoicehat-codec.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO) += snd-soc-hifiberry-dacplusadcpro.o
+ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
+--- /dev/null
++++ b/sound/soc/bcm/hifiberry_dacplusadcpro.c
+@@ -0,0 +1,538 @@
++/*
++ * ASoC Driver for HiFiBerry DAC+ / DAC Pro with ADC PRO Version (SW control)
++ *
++ * Author: Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
++ * Copyright 2014-2015
++ * based on code by Florian Meier <florian.meier@koalo.de>
++ * ADC added by Joerg Schambacher <joerg@i2audio.com>
++ * Copyright 2018-19
++ *
++ * 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 <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/kernel.h>
++#include <linux/clk.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/jack.h>
++#include <sound/tlv.h>
++
++#include "../codecs/pcm512x.h"
++#include "../codecs/pcm186x.h"
++
++#define HIFIBERRY_DACPRO_NOCLOCK 0
++#define HIFIBERRY_DACPRO_CLK44EN 1
++#define HIFIBERRY_DACPRO_CLK48EN 2
++
++struct pcm512x_priv {
++ struct regmap *regmap;
++ struct clk *sclk;
++};
++
++/* Clock rate of CLK44EN attached to GPIO6 pin */
++#define CLK_44EN_RATE 22579200UL
++/* Clock rate of CLK48EN attached to GPIO3 pin */
++#define CLK_48EN_RATE 24576000UL
++
++static bool slave;
++static bool snd_rpi_hifiberry_is_dacpro;
++static bool digital_gain_0db_limit = true;
++
++static const unsigned int pcm186x_adc_input_channel_sel_value[] = {
++ 0x00, 0x01, 0x02, 0x03, 0x10
++};
++
++static const char * const pcm186x_adcl_input_channel_sel_text[] = {
++ "No Select",
++ "VINL1[SE]", /* Default for ADCL */
++ "VINL2[SE]",
++ "VINL2[SE] + VINL1[SE]",
++ "{VIN1P, VIN1M}[DIFF]"
++};
++
++static const char * const pcm186x_adcr_input_channel_sel_text[] = {
++ "No Select",
++ "VINR1[SE]", /* Default for ADCR */
++ "VINR2[SE]",
++ "VINR2[SE] + VINR1[SE]",
++ "{VIN2P, VIN2M}[DIFF]"
++};
++
++static const struct soc_enum pcm186x_adc_input_channel_sel[] = {
++ SOC_VALUE_ENUM_SINGLE(PCM186X_ADC1_INPUT_SEL_L, 0,
++ PCM186X_ADC_INPUT_SEL_MASK,
++ ARRAY_SIZE(pcm186x_adcl_input_channel_sel_text),
++ pcm186x_adcl_input_channel_sel_text,
++ pcm186x_adc_input_channel_sel_value),
++ SOC_VALUE_ENUM_SINGLE(PCM186X_ADC1_INPUT_SEL_R, 0,
++ PCM186X_ADC_INPUT_SEL_MASK,
++ ARRAY_SIZE(pcm186x_adcr_input_channel_sel_text),
++ pcm186x_adcr_input_channel_sel_text,
++ pcm186x_adc_input_channel_sel_value),
++};
++
++static const unsigned int pcm186x_mic_bias_sel_value[] = {
++ 0x00, 0x01, 0x11
++};
++
++static const char * const pcm186x_mic_bias_sel_text[] = {
++ "Mic Bias off",
++ "Mic Bias on",
++ "Mic Bias with Bypass Resistor"
++};
++
++static const struct soc_enum pcm186x_mic_bias_sel[] = {
++ SOC_VALUE_ENUM_SINGLE(PCM186X_MIC_BIAS_CTRL, 0,
++ GENMASK(4, 0),
++ ARRAY_SIZE(pcm186x_mic_bias_sel_text),
++ pcm186x_mic_bias_sel_text,
++ pcm186x_mic_bias_sel_value),
++};
++
++static const unsigned int pcm186x_gain_sel_value[] = {
++ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
++ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
++ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
++ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
++ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
++ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
++ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
++ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
++ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
++ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
++ 0x50
++};
++
++static const char * const pcm186x_gain_sel_text[] = {
++ "-12.0dB", "-11.5dB", "-11.0dB", "-10.5dB", "-10.0dB", "-9.5dB",
++ "-9.0dB", "-8.5dB", "-8.0dB", "-7.5dB", "-7.0dB", "-6.5dB",
++ "-6.0dB", "-5.5dB", "-5.0dB", "-4.5dB", "-4.0dB", "-3.5dB",
++ "-3.0dB", "-2.5dB", "-2.0dB", "-1.5dB", "-1.0dB", "-0.5dB",
++ "0.0dB", "0.5dB", "1.0dB", "1.5dB", "2.0dB", "2.5dB",
++ "3.0dB", "3.5dB", "4.0dB", "4.5dB", "5.0dB", "5.5dB",
++ "6.0dB", "6.5dB", "7.0dB", "7.5dB", "8.0dB", "8.5dB",
++ "9.0dB", "9.5dB", "10.0dB", "10.5dB", "11.0dB", "11.5dB",
++ "12.0dB", "12.5dB", "13.0dB", "13.5dB", "14.0dB", "14.5dB",
++ "15.0dB", "15.5dB", "16.0dB", "16.5dB", "17.0dB", "17.5dB",
++ "18.0dB", "18.5dB", "19.0dB", "19.5dB", "20.0dB", "20.5dB",
++ "21.0dB", "21.5dB", "22.0dB", "22.5dB", "23.0dB", "23.5dB",
++ "24.0dB", "24.5dB", "25.0dB", "25.5dB", "26.0dB", "26.5dB",
++ "27.0dB", "27.5dB", "28.0dB", "28.5dB", "29.0dB", "29.5dB",
++ "30.0dB", "30.5dB", "31.0dB", "31.5dB", "32.0dB", "32.5dB",
++ "33.0dB", "33.5dB", "34.0dB", "34.5dB", "35.0dB", "35.5dB",
++ "36.0dB", "36.5dB", "37.0dB", "37.5dB", "38.0dB", "38.5dB",
++ "39.0dB", "39.5dB", "40.0dB"};
++
++static const struct soc_enum pcm186x_gain_sel[] = {
++ SOC_VALUE_ENUM_SINGLE(PCM186X_PGA_VAL_CH1_L, 0,
++ 0xff,
++ ARRAY_SIZE(pcm186x_gain_sel_text),
++ pcm186x_gain_sel_text,
++ pcm186x_gain_sel_value),
++ SOC_VALUE_ENUM_SINGLE(PCM186X_PGA_VAL_CH1_R, 0,
++ 0xff,
++ ARRAY_SIZE(pcm186x_gain_sel_text),
++ pcm186x_gain_sel_text,
++ pcm186x_gain_sel_value),
++};
++
++static const struct snd_kcontrol_new pcm1863_snd_controls_card[] = {
++ SOC_ENUM("ADC Left Input", pcm186x_adc_input_channel_sel[0]),
++ SOC_ENUM("ADC Right Input", pcm186x_adc_input_channel_sel[1]),
++ SOC_ENUM("ADC Mic Bias", pcm186x_mic_bias_sel),
++ SOC_ENUM("PGA Gain Left", pcm186x_gain_sel[0]),
++ SOC_ENUM("PGA Gain Right", pcm186x_gain_sel[1]),
++};
++
++static int pcm1863_add_controls(struct snd_soc_component *component)
++{
++ snd_soc_add_component_controls(component,
++ pcm1863_snd_controls_card,
++ ARRAY_SIZE(pcm1863_snd_controls_card));
++ return 0;
++}
++
++static void snd_rpi_hifiberry_dacplusadcpro_select_clk(
++ struct snd_soc_component *component, int clk_id)
++{
++ switch (clk_id) {
++ case HIFIBERRY_DACPRO_NOCLOCK:
++ snd_soc_component_update_bits(component,
++ PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
++ break;
++ case HIFIBERRY_DACPRO_CLK44EN:
++ snd_soc_component_update_bits(component,
++ PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
++ break;
++ case HIFIBERRY_DACPRO_CLK48EN:
++ snd_soc_component_update_bits(component,
++ PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
++ break;
++ }
++}
++
++static void snd_rpi_hifiberry_dacplusadcpro_clk_gpio(struct snd_soc_component *component)
++{
++ snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
++ snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
++ snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
++}
++
++static bool snd_rpi_hifiberry_dacplusadcpro_is_sclk(struct snd_soc_component *component)
++{
++ unsigned int sck;
++
++ snd_soc_component_read(component, PCM512x_RATE_DET_4, &sck);
++ return (!(sck & 0x40));
++}
++
++static bool snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(
++ struct snd_soc_component *component)
++{
++ msleep(2);
++ return snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
++}
++
++static bool snd_rpi_hifiberry_dacplusadcpro_is_pro_card(struct snd_soc_component *component)
++{
++ bool isClk44EN, isClk48En, isNoClk;
++
++ snd_rpi_hifiberry_dacplusadcpro_clk_gpio(component);
++
++ snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
++ isClk44EN = snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(component);
++
++ snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
++ isNoClk = snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(component);
++
++ snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
++ isClk48En = snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(component);
++
++ return (isClk44EN && isClk48En && !isNoClk);
++}
++
++static int snd_rpi_hifiberry_dacplusadcpro_clk_for_rate(int sample_rate)
++{
++ int type;
++
++ switch (sample_rate) {
++ case 11025:
++ case 22050:
++ case 44100:
++ case 88200:
++ case 176400:
++ case 352800:
++ type = HIFIBERRY_DACPRO_CLK44EN;
++ break;
++ default:
++ type = HIFIBERRY_DACPRO_CLK48EN;
++ break;
++ }
++ return type;
++}
++
++static void snd_rpi_hifiberry_dacplusadcpro_set_sclk(struct snd_soc_component *component,
++ int sample_rate)
++{
++ struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
++
++ if (!IS_ERR(pcm512x->sclk)) {
++ int ctype;
++
++ ctype = snd_rpi_hifiberry_dacplusadcpro_clk_for_rate(sample_rate);
++ clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN)
++ ? CLK_44EN_RATE : CLK_48EN_RATE);
++ snd_rpi_hifiberry_dacplusadcpro_select_clk(component, ctype);
++ }
++}
++
++static int snd_rpi_hifiberry_dacplusadcpro_init(struct snd_soc_pcm_runtime *rtd)
++{
++ struct snd_soc_component *dac = rtd->codec_dais[0]->component;
++ struct snd_soc_component *adc = rtd->codec_dais[1]->component;
++ struct snd_soc_dai_driver *adc_driver = rtd->codec_dais[1]->driver;
++ struct pcm512x_priv *priv;
++ int ret;
++
++ if (slave)
++ snd_rpi_hifiberry_is_dacpro = false;
++ else
++ snd_rpi_hifiberry_is_dacpro =
++ snd_rpi_hifiberry_dacplusadcpro_is_pro_card(dac);
++
++ if (snd_rpi_hifiberry_is_dacpro) {
++ struct snd_soc_dai_link *dai = rtd->dai_link;
++
++ dai->name = "HiFiBerry DAC+ADC Pro";
++ dai->stream_name = "HiFiBerry DAC+ADC Pro HiFi";
++
++ // set DAC DAI configuration
++ ret = snd_soc_dai_set_fmt(rtd->codec_dais[0],
++ SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
++ | SND_SOC_DAIFMT_CBM_CFM);
++ if (ret < 0)
++ return ret;
++
++ // set ADC DAI configuration
++ ret = snd_soc_dai_set_fmt(rtd->codec_dais[1],
++ SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
++ | SND_SOC_DAIFMT_CBS_CFS);
++ if (ret < 0)
++ return ret;
++
++ // set CPU DAI configuration
++ ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
++ SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
++ if (ret < 0)
++ return ret;
++
++ snd_soc_component_update_bits(dac, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
++ snd_soc_component_update_bits(dac, PCM512x_MASTER_MODE, 0x03, 0x03);
++ snd_soc_component_update_bits(dac, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
++ } else {
++ priv = snd_soc_component_get_drvdata(dac);
++ priv->sclk = ERR_PTR(-ENOENT);
++ }
++
++ /* disable 24bit mode as long as I2S module does not have sign extension fixed */
++ adc_driver->capture.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE;
++
++ snd_soc_component_update_bits(dac, PCM512x_GPIO_EN, 0x08, 0x08);
++ snd_soc_component_update_bits(dac, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
++ snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
++
++ ret = pcm1863_add_controls(adc);
++ if (ret < 0)
++ dev_warn(rtd->dev, "Failed to add pcm1863 controls: %d\n",
++ ret);
++
++ /* set GPIO2 to output, GPIO3 input */
++ snd_soc_component_write(adc, PCM186X_GPIO3_2_CTRL, 0x00);
++ snd_soc_component_write(adc, PCM186X_GPIO3_2_DIR_CTRL, 0x04);
++ snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
++
++ if (digital_gain_0db_limit) {
++ int ret;
++ struct snd_soc_card *card = rtd->card;
++
++ ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
++ if (ret < 0)
++ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
++ }
++
++ return 0;
++}
++
++static int snd_rpi_hifiberry_dacplusadcpro_update_rate_den(
++ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_component *component = rtd->codec_dais[0]->component; /* only use DAC */
++ struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
++ struct snd_ratnum *rats_no_pll;
++ unsigned int num = 0, den = 0;
++ int err;
++
++ rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
++ if (!rats_no_pll)
++ return -ENOMEM;
++
++ rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
++ rats_no_pll->den_min = 1;
++ rats_no_pll->den_max = 128;
++ rats_no_pll->den_step = 1;
++
++ err = snd_interval_ratnum(hw_param_interval(params,
++ SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
++ if (err >= 0 && den) {
++ params->rate_num = num;
++ params->rate_den = den;
++ }
++
++ devm_kfree(rtd->dev, rats_no_pll);
++ return 0;
++}
++
++static int snd_rpi_hifiberry_dacplusadcpro_hw_params(
++ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
++{
++ int ret = 0;
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ int channels = params_channels(params);
++ int width = 32;
++ struct snd_soc_component *dac = rtd->codec_dais[0]->component;
++
++ if (snd_rpi_hifiberry_is_dacpro) {
++
++ width = snd_pcm_format_physical_width(params_format(params));
++
++ snd_rpi_hifiberry_dacplusadcpro_set_sclk(dac,
++ params_rate(params));
++
++ ret = snd_rpi_hifiberry_dacplusadcpro_update_rate_den(
++ substream, params);
++ if (ret)
++ return ret;
++ }
++
++ ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x03, 0x03,
++ channels, width);
++ if (ret)
++ return ret;
++ ret = snd_soc_dai_set_tdm_slot(rtd->codec_dais[0], 0x03, 0x03,
++ channels, width);
++ if (ret)
++ return ret;
++ ret = snd_soc_dai_set_tdm_slot(rtd->codec_dais[1], 0x03, 0x03,
++ channels, width);
++ return ret;
++}
++
++static int snd_rpi_hifiberry_dacplusadcpro_startup(
++ struct snd_pcm_substream *substream)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_component *dac = rtd->codec_dais[0]->component;
++ struct snd_soc_component *adc = rtd->codec_dais[1]->component;
++
++ /* switch on respective LED */
++ if (!substream->stream)
++ snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
++ else
++ snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
++ return 0;
++}
++
++static void snd_rpi_hifiberry_dacplusadcpro_shutdown(
++ struct snd_pcm_substream *substream)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_component *dac = rtd->codec_dais[0]->component;
++ struct snd_soc_component *adc = rtd->codec_dais[1]->component;
++
++ /* switch off respective LED */
++ if (!substream->stream)
++ snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
++ else
++ snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x00);
++}
++
++
++/* machine stream operations */
++static struct snd_soc_ops snd_rpi_hifiberry_dacplusadcpro_ops = {
++ .hw_params = snd_rpi_hifiberry_dacplusadcpro_hw_params,
++ .startup = snd_rpi_hifiberry_dacplusadcpro_startup,
++ .shutdown = snd_rpi_hifiberry_dacplusadcpro_shutdown,
++};
++
++static struct snd_soc_dai_link_component snd_rpi_hifiberry_dacplusadcpro_codecs[] = {
++ {
++ .name = "pcm512x.1-004d",
++ .dai_name = "pcm512x-hifi",
++ },
++ {
++ .name = "pcm186x.1-004a",
++ .dai_name = "pcm1863-aif",
++ },
++};
++
++static struct snd_soc_dai_link snd_rpi_hifiberry_dacplusadcpro_dai[] = {
++{
++ .name = "HiFiBerry DAC+ADC PRO",
++ .stream_name = "HiFiBerry DAC+ADC PRO HiFi",
++ .cpu_dai_name = "bcm2708-i2s.0",
++ .platform_name = "bcm2708-i2s.0",
++ .codecs = snd_rpi_hifiberry_dacplusadcpro_codecs,
++ .num_codecs = 2,
++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBS_CFS,
++ .ops = &snd_rpi_hifiberry_dacplusadcpro_ops,
++ .init = snd_rpi_hifiberry_dacplusadcpro_init,
++},
++};
++
++/* audio machine driver */
++static struct snd_soc_card snd_rpi_hifiberry_dacplusadcpro = {
++ .name = "snd_rpi_hifiberry_dacplusadcpro",
++ .driver_name = "HifiberryDacpAdcPro",
++ .owner = THIS_MODULE,
++ .dai_link = snd_rpi_hifiberry_dacplusadcpro_dai,
++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplusadcpro_dai),
++};
++
++static int snd_rpi_hifiberry_dacplusadcpro_probe(struct platform_device *pdev)
++{
++ int ret = 0, i = 0;
++ struct snd_soc_card *card = &snd_rpi_hifiberry_dacplusadcpro;
++
++ snd_rpi_hifiberry_dacplusadcpro.dev = &pdev->dev;
++ if (pdev->dev.of_node) {
++ struct device_node *i2s_node;
++ struct snd_soc_dai_link *dai;
++
++ dai = &snd_rpi_hifiberry_dacplusadcpro_dai[0];
++ i2s_node = of_parse_phandle(pdev->dev.of_node,
++ "i2s-controller", 0);
++ if (i2s_node) {
++ for (i = 0; i < card->num_links; i++) {
++ dai->cpu_dai_name = NULL;
++ dai->cpu_of_node = i2s_node;
++ dai->platform_name = NULL;
++ dai->platform_of_node = i2s_node;
++ }
++ }
++ }
++ digital_gain_0db_limit = !of_property_read_bool(
++ pdev->dev.of_node, "hifiberry-dacplusadcpro,24db_digital_gain");
++ slave = of_property_read_bool(pdev->dev.of_node,
++ "hifiberry-dacplusadcpro,slave");
++ ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplusadcpro);
++ if (ret && ret != -EPROBE_DEFER)
++ dev_err(&pdev->dev,
++ "snd_soc_register_card() failed: %d\n", ret);
++
++ return ret;
++}
++
++static const struct of_device_id snd_rpi_hifiberry_dacplusadcpro_of_match[] = {
++ { .compatible = "hifiberry,hifiberry-dacplusadcpro", },
++ {},
++};
++
++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplusadcpro_of_match);
++
++static struct platform_driver snd_rpi_hifiberry_dacplusadcpro_driver = {
++ .driver = {
++ .name = "snd-rpi-hifiberry-dacplusadcpro",
++ .owner = THIS_MODULE,
++ .of_match_table = snd_rpi_hifiberry_dacplusadcpro_of_match,
++ },
++ .probe = snd_rpi_hifiberry_dacplusadcpro_probe,
++};
++
++module_platform_driver(snd_rpi_hifiberry_dacplusadcpro_driver);
++
++MODULE_AUTHOR("Joerg Schambacher <joerg@i2audio.com>");
++MODULE_AUTHOR("Daniel Matuschek <daniel@hifiberry.com>");
++MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ADC");
++MODULE_LICENSE("GPL v2");
--- /dev/null
+From 25b5f8d3fdadafccc34e4ae24525ddfb5e6b2ae0 Mon Sep 17 00:00:00 2001
+From: allo-com <jaikumar@cem-solutions.net>
+Date: Mon, 29 Jul 2019 15:06:57 +0530
+Subject: [PATCH 725/725] codecs: Correct Katana minimum volume
+
+Update Katana minimum volume to get the exact 0.5 dB value in each step.
+
+Signed-off-by: Sudeep Kumar <sudeepkumar@cem-solutions.net>
+---
+ sound/soc/bcm/allo-katana-codec.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/soc/bcm/allo-katana-codec.c
++++ b/sound/soc/bcm/allo-katana-codec.c
+@@ -126,7 +126,7 @@ static SOC_VALUE_ENUM_SINGLE_DECL(katana
+ katana_codec_deemphasis_texts,
+ katana_codec_deemphasis_values);
+
+-static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(master_tlv, -12700, 0);
++static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(master_tlv, -12750, 0);
+
+ static const struct snd_kcontrol_new katana_codec_controls[] = {
+ SOC_DOUBLE_R_TLV("Master Playback Volume", KATANA_CODEC_VOLUME_1,
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
-@@ -25,6 +25,7 @@ config ARCH_BCM2835
+@@ -26,6 +26,7 @@ config ARCH_BCM2835
select ARM_AMBA
select ARM_TIMER_SP804
select HAVE_ARM_ARCH_TIMER
# CONFIG_BT_LE is not set
# CONFIG_BT_LEDS is not set
# CONFIG_BT_MRVL is not set
+# CONFIG_BT_MTKUART is not set
# CONFIG_BT_RFCOMM is not set
CONFIG_BT_RFCOMM_TTY=y
# CONFIG_BT_SELFTEST is not set
CONFIG_EXT4_USE_FOR_EXT2=y
# CONFIG_EXTCON is not set
# CONFIG_EXTCON_ADC_JACK is not set
+# CONFIG_EXTCON_ARIZONA is not set
# CONFIG_EXTCON_AXP288 is not set
# CONFIG_EXTCON_GPIO is not set
# CONFIG_EXTCON_INTEL_INT3496 is not set
# CONFIG_HID_BATTERY_STRENGTH is not set
# CONFIG_HID_BELKIN is not set
# CONFIG_HID_BETOP_FF is not set
+# CONFIG_HID_BIGBEN_FF is not set
# CONFIG_HID_CHERRY is not set
# CONFIG_HID_CHICONY is not set
# CONFIG_HID_CMEDIA is not set
# CONFIG_TOUCHSCREEN_PROPERTIES is not set
# CONFIG_TOUCHSCREEN_RM_TS is not set
# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set
+# CONFIG_TOUCHSCREEN_RPI_FT5406 is not set
# CONFIG_TOUCHSCREEN_S3C2410 is not set
# CONFIG_TOUCHSCREEN_S6SY761 is not set
# CONFIG_TOUCHSCREEN_SILEAD is not set