CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
-# CONFIG_ARGON_MEM is not set
CONFIG_ARM=y
CONFIG_ARM_AMBA=y
CONFIG_ARM_BCM2835_CPUFREQ=y
# CONFIG_FPE_NWFPE is not set
CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
CONFIG_FREEZER=y
CONFIG_FS_IOMAP=y
CONFIG_FS_MBCACHE=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_RESET_CONTROLLER=y
+# CONFIG_RPIVID_MEM is not set
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_SCSI=y
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
-# CONFIG_ARGON_MEM is not set
CONFIG_ARM=y
CONFIG_ARM_AMBA=y
CONFIG_ARM_ARCH_TIMER=y
# CONFIG_FPE_NWFPE is not set
CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
CONFIG_FREEZER=y
CONFIG_FS_IOMAP=y
CONFIG_FS_MBCACHE=y
CONFIG_REGULATOR_GPIO=y
CONFIG_RESET_CONTROLLER=y
CONFIG_RFS_ACCEL=y
+# CONFIG_RPIVID_MEM is not set
CONFIG_RPS=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
CONFIG_ARCH_WANT_FRAME_POINTERS=y
CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
-# CONFIG_ARGON_MEM is not set
CONFIG_ARM64=y
# CONFIG_ARM64_16K_PAGES is not set
CONFIG_ARM64_4K_PAGES=y
CONFIG_FONT_SUPPORT=y
CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
CONFIG_FRAME_POINTER=y
CONFIG_FREEZER=y
CONFIG_FSL_ERRATUM_A008585=y
CONFIG_REGULATOR_GPIO=y
CONFIG_RESET_CONTROLLER=y
CONFIG_RFS_ACCEL=y
+# CONFIG_RPIVID_MEM is not set
CONFIG_RPS=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
CONFIG_ARCH_WANT_FRAME_POINTERS=y
CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
-# CONFIG_ARGON_MEM is not set
CONFIG_ARM64=y
# CONFIG_ARM64_16K_PAGES is not set
CONFIG_ARM64_4K_PAGES=y
CONFIG_FONT_SUPPORT=y
CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
CONFIG_FRAME_POINTER=y
CONFIG_FREEZER=y
CONFIG_FSL_ERRATUM_A008585=y
CONFIG_REGULATOR_GPIO=y
CONFIG_RESET_CONTROLLER=y
CONFIG_RFS_ACCEL=y
+# CONFIG_RPIVID_MEM is not set
CONFIG_RPS=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
# Force aarch64
arm_64bit=1
-
-# USBs not working with > 3GB
-total_mem=3072
-From 623cca7c1ef73b6b164d487d3bb3b2bddc60abab Mon Sep 17 00:00:00 2001
+From 5aeff609a8dadb82acf69650bd98faba80a47b6e 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/725] arm: partially revert
+Subject: [PATCH 001/773] arm: partially revert
702b94bff3c50542a6e4ab9a4f4cef093262fe65
* Re-expose some dmi APIs for use in VCSM
-From b356c22b7c3cce97ba7c20af22f508510387a3f2 Mon Sep 17 00:00:00 2001
+From 4a6d6180a843971e60a6e3b7f21e9e5b0fb57071 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/725] smsx95xx: fix crimes against truesize
+Subject: [PATCH 002/773] 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 440ed9d083956067ffbaaefd3e2411b746126593 Mon Sep 17 00:00:00 2001
+From 0f28cdfa1b52e770ee13f4dcc5ad732225b75b17 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/725] smsc95xx: Experimental: Enable turbo_mode and
+Subject: [PATCH 003/773] smsc95xx: Experimental: Enable turbo_mode and
packetsize=2560 by default
See: http://forum.kodi.tv/showthread.php?tid=285288
-From 3590eb29c3b4307a50daf24c1d58e188b1aaf65d Mon Sep 17 00:00:00 2001
+From 9f83838979d7bfc5f4b4123c51871403208de521 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 26 Mar 2013 17:26:38 +0000
-Subject: [PATCH 004/725] Allow mac address to be set in smsc95xx
+Subject: [PATCH 004/773] Allow mac address to be set in smsc95xx
Signed-off-by: popcornmix <popcornmix@gmail.com>
---
-From 42773929bcec27d195b93b11c10527be7fccd2d8 Mon Sep 17 00:00:00 2001
+From 063b764f6c762935b3a12a84185f98cfbf759aaa 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/725] Protect __release_resource against resources without
+Subject: [PATCH 005/773] Protect __release_resource against resources without
parents
Without this patch, removing a device tree overlay can crash here.
-From ca08ef4827614912c6f07fa734a2eede3420a9c6 Mon Sep 17 00:00:00 2001
+From b46a87040e3d0996bfd76d3c325130fafe76f89a 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/725] irq-bcm2836: Prevent spurious interrupts, and trap
+Subject: [PATCH 006/773] irq-bcm2836: Prevent spurious interrupts, and trap
them early
The old arch-specific IRQ macros included a dsb to ensure the
-From b3b97bc061e22d03569cd7eedaf7cc1b4fb403f3 Mon Sep 17 00:00:00 2001
+From 8fa468320f67f77ad7cb4181c4add57aab75c5b0 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/725] irq-bcm2836: Avoid "Invalid trigger warning"
+Subject: [PATCH 007/773] irq-bcm2836: Avoid "Invalid trigger warning"
Initialise the level for each IRQ to avoid a warning from the
arm arch timer code.
-From 9920e74cfd7571c36fce1caf84736f89e275fe22 Mon Sep 17 00:00:00 2001
+From de43634ad18a2cf230dfc7645c6d97819669252d 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/725] irqchip: bcm2835: Add FIQ support
+Subject: [PATCH 008/773] irqchip: bcm2835: Add FIQ support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From b08bd87913c001b0f3d7f86d73abfc2074b0cab2 Mon Sep 17 00:00:00 2001
+From c4d05e2af315b0666879b0f34b0f8d0b05d8d63c 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/725] irqchip: irq-bcm2835: Add 2836 FIQ support
+Subject: [PATCH 009/773] irqchip: irq-bcm2835: Add 2836 FIQ support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From e73e4e6923289a3055d5fd10c7726fbe358505ad Mon Sep 17 00:00:00 2001
+From 851317f6443a19c32aea5b68c119573982fa396b 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/725] spidev: Add "spidev" compatible string to silence
+Subject: [PATCH 010/773] spidev: Add "spidev" compatible string to silence
warning
See: https://github.com/raspberrypi/linux/issues/1054
-From e1ebc1b8dcb6990e2541e3503cb2cdd3f5edfc1e Mon Sep 17 00:00:00 2001
+From 23bb48d83e2a820b8371a3512261981b52630eee 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/725] spi-bcm2835: Support pin groups other than 7-11
+Subject: [PATCH 011/773] 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 e901e4ff32c1f3c10342b4607579a1d9613c3c66 Mon Sep 17 00:00:00 2001
+From 69d97bffaad932f5ba5c5b1ad347ad0495a55117 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/725] spi-bcm2835: Disable forced software CS
+Subject: [PATCH 012/773] 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 f1b841cc75bcd8c655c9cd6c3dbed439a1f4d24a Mon Sep 17 00:00:00 2001
+From cb5388ad2851ec7a7fcb58ca1ebec0a1ab84a66f 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/725] spi-bcm2835: Remove unused code
+Subject: [PATCH 013/773] spi-bcm2835: Remove unused code
---
drivers/spi/spi-bcm2835.c | 61 ---------------------------------------
-From 568609dad2f29b45931c2fc869f87d4abb6c7486 Mon Sep 17 00:00:00 2001
+From 8db77ac342dc3bb179c5e6610805706ebfdafc7c 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/725] dmaengine: bcm2835: Load driver early and support
+Subject: [PATCH 014/773] dmaengine: bcm2835: Load driver early and support
legacy API
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
-From 8151b76346ed89410b20db4fb4bc8f1784e0fd19 Mon Sep 17 00:00:00 2001
+From f27da16a911e08fe3cb210014d5f0795ddb812b3 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 25 Jan 2016 17:25:12 +0000
-Subject: [PATCH 015/725] firmware: Updated mailbox header
+Subject: [PATCH 015/773] firmware: Updated mailbox header
---
include/soc/bcm2835/raspberrypi-firmware.h | 5 +++++
-From 0af4ce25fc884c07db940d61e7677bba37a4130d Mon Sep 17 00:00:00 2001
+From 9c5cca27567e50f9224439ff45c83d23725a6d04 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/725] rtc: Add SPI alias for pcf2123 driver
+Subject: [PATCH 016/773] rtc: Add SPI alias for pcf2123 driver
Without this alias, Device Tree won't cause the driver
to be loaded.
-From 726d38c5f2aee110f7e3b0f03fc17e5fc69aa8c3 Mon Sep 17 00:00:00 2001
+From b8779c374c61ce6f8cafe3c054279d510781cc75 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/725] watchdog: bcm2835: Support setting reboot partition
+Subject: [PATCH 017/773] watchdog: bcm2835: Support setting reboot partition
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From a48963920cbab4a54fb8c1a12cab6f51249c8938 Mon Sep 17 00:00:00 2001
+From 5deffd890e33238ae82b5fe306d3c258b6527c66 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 5 Apr 2016 19:40:12 +0100
-Subject: [PATCH 018/725] reboot: Use power off rather than busy spinning when
+Subject: [PATCH 018/773] reboot: Use power off rather than busy spinning when
halt is requested
---
-From 5b4c3e8bea1e40ae39e8e1d557f71c2262e41740 Mon Sep 17 00:00:00 2001
+From 82876bead4101ba80c7ddfe76a3a2375deff1c2f Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 9 Nov 2016 13:02:52 +0000
-Subject: [PATCH 019/725] bcm: Make RASPBERRYPI_POWER depend on PM
+Subject: [PATCH 019/773] bcm: Make RASPBERRYPI_POWER depend on PM
---
drivers/soc/bcm/Kconfig | 1 +
-From 2d35d5929c505731a490ea56a6a78f487c082e01 Mon Sep 17 00:00:00 2001
+From 5d6464320ab7db4198d9568c20d25063c9c236f8 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/725] Register the clocks early during the boot process, so
+Subject: [PATCH 020/773] 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 241096d58e818f8f471eb141b1183e8b5e8ffea8 Mon Sep 17 00:00:00 2001
+From 291ee006cdd9854201d82d78fa0930142e224990 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 6 Dec 2016 17:05:39 +0000
-Subject: [PATCH 021/725] bcm2835-rng: Avoid initialising if already enabled
+Subject: [PATCH 021/773] bcm2835-rng: Avoid initialising if already enabled
Avoids the 0x40000 cycles of warmup again if firmware has already used it
---
-From 8bf56ee660bf07a25ba3a2081d9a498435d16a32 Mon Sep 17 00:00:00 2001
+From 7936498ab3bf4dfd05779c3b8f4766e983f40036 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/725] kbuild: Ignore dtco targets when filtering symbols
+Subject: [PATCH 022/773] kbuild: Ignore dtco targets when filtering symbols
---
scripts/Kbuild.include | 2 +-
-From a87e7ca656f8b80caf7db0056ba4b6191018359f Mon Sep 17 00:00:00 2001
+From 6980d928a2cc130ae52f0e0ba80d96c1b96c9f0c 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/725] clk-bcm2835: Mark used PLLs and dividers CRITICAL
+Subject: [PATCH 023/773] 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 b0d7a3297087a0a78e12e9e8fc41e9c91a114304 Mon Sep 17 00:00:00 2001
+From 585c5e6c9c70caf1feaedc1f1f6c0b0ca0c1ec05 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/725] clk-bcm2835: Add claim-clocks property
+Subject: [PATCH 024/773] 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 91e0734c2ca8c8629b0537329c7e6d538fa1c085 Mon Sep 17 00:00:00 2001
+From f78e04a056cdf4c294decfdf75cf811ce314bc02 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/725] clk-bcm2835: Read max core clock from firmware
+Subject: [PATCH 025/773] 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 e61099f2c51b1583663e5868f87056d4c11b6e9d Mon Sep 17 00:00:00 2001
+From 00e7c106f7155879a33137169bf4e795969afb09 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/725] clk: bcm2835: Mark GPIO clocks enabled at boot as
+Subject: [PATCH 026/773] 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 4d94da034003c8f8ba44ba4a8abdf5c9cf56d684 Mon Sep 17 00:00:00 2001
+From d2437667bc502cf28a40ca6cae80e131a4c9a218 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/725] sound: Demote deferral errors to INFO level
+Subject: [PATCH 027/773] 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 be7a5d79d1f4d8f8db39f092e7f07d8cb05eebf7 Mon Sep 17 00:00:00 2001
+From 6ae13148b5a909c4485b30b4a8ed04c75d776e80 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/725] Update vfpmodule.c
+Subject: [PATCH 028/773] 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 97549c7735e937cafdbeff241c9aac738fa560ce Mon Sep 17 00:00:00 2001
+From 88bf0aa4b8e700d05f649ca0eaef4c8d4d38a9d7 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/725] i2c: bcm2835: Add debug support
+Subject: [PATCH 029/773] i2c: bcm2835: Add debug support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 41dda0f0591a3b2e73439a3af562ac937927dd15 Mon Sep 17 00:00:00 2001
+From 15eda8d8af9dd8ef00be8d0e559db099fbb6c1ee 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/725] mm: Remove the PFN busy warning
+Subject: [PATCH 030/773] mm: Remove the PFN busy warning
See commit dae803e165a11bc88ca8dbc07a11077caf97bbcb -- the warning is
expected sometimes when using CMA. However, that commit still spams
-From 9d9d7ba0d4296bb2b0270a1e5dfbc8a3eb7cf192 Mon Sep 17 00:00:00 2001
+From f9a73252c4cb6e419bf80b25612c7bbd82bb1ae2 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/725] ASoC: Add prompt for ICS43432 codec
+Subject: [PATCH 031/773] 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 1c14a9ccc7c3b57c55374295a4a7a9a80090b095 Mon Sep 17 00:00:00 2001
+From d692d8494e74c3965084a3d5322671e29c09e939 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/725] irqchip: irq-bcm2836: Remove regmap and syscon use
+Subject: [PATCH 032/773] 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 37be14f62e3545c46cd86a11ba68cc036f34c638 Mon Sep 17 00:00:00 2001
+From a4c058db46978b5cd47ce3d43235cee561951e09 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/725] lan78xx: Enable LEDs and auto-negotiation
+Subject: [PATCH 033/773] 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 00a9f57a05b9f62c1c8b44479b6e700958ef1400 Mon Sep 17 00:00:00 2001
+From 2bdcdb66ae0a6e47e92e4d9e1ea770a8fb2d5d9b 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/725] amba_pl011: Don't use DT aliases for numbering
+Subject: [PATCH 034/773] 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 f6c9045d3e326e9b3f6c5d93fe09f517443d9075 Mon Sep 17 00:00:00 2001
+From 651015f8120bffcd35d6ede0084a82142b6d4be2 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/725] amba_pl011: Round input clock up
+Subject: [PATCH 035/773] 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 95ea844e0a7addac38e0385f5ab4215921e1c86b Mon Sep 17 00:00:00 2001
+From 4f3db8602a4b64007a1e9016915f59c924787c05 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/725] amba_pl011: Insert mb() for correct FIFO handling
+Subject: [PATCH 036/773] 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 92cd7f1608ffea6325748373f9464a035743c3c3 Mon Sep 17 00:00:00 2001
+From 1c0a79159b5fd87cd14f1edb60b8d6d7c5e88b5e 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/725] amba_pl011: Add cts-event-workaround DT property
+Subject: [PATCH 037/773] 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 af8d6777f0c606b8c6a472651e4d00c595db8cdf Mon Sep 17 00:00:00 2001
+From 96f571906f77a982630e4fee23a96ebb1f83ce45 Mon Sep 17 00:00:00 2001
From: notro <notro@tronnes.org>
Date: Thu, 10 Jul 2014 13:59:47 +0200
-Subject: [PATCH 038/725] pinctrl-bcm2835: Set base to 0 give expected gpio
+Subject: [PATCH 038/773] pinctrl-bcm2835: Set base to 0 give expected gpio
numbering
Signed-off-by: Noralf Tronnes <notro@tronnes.org>
-From f395eddcb1dad5b6b2905efa3ccb3916f91cadb9 Mon Sep 17 00:00:00 2001
+From 71c4c305410c72a3293ecf55e72188abc016c65f Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Sun, 12 May 2013 12:24:19 +0100
-Subject: [PATCH 039/725] Main bcm2708/bcm2709 linux port
+Subject: [PATCH 039/773] Main bcm2708/bcm2709 linux port
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 7d7d160ca73faa35ab961ce201194ea6c419e9af Mon Sep 17 00:00:00 2001
+From ae5f6b6b0d350cf7366945b0b73e87f1d0162ba0 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 1 May 2013 19:46:17 +0100
-Subject: [PATCH 040/725] Add dwc_otg driver
+Subject: [PATCH 040/773] Add dwc_otg driver
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 051c5a36a676f82455f356ef42279814992fca50 Mon Sep 17 00:00:00 2001
+From 5a5edbd9aaeb32c7890fc181cd637ff1c05a6d59 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 17 Jun 2015 17:06:34 +0100
-Subject: [PATCH 041/725] bcm2708 framebuffer driver
+Subject: [PATCH 041/773] bcm2708 framebuffer driver
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From d73294bd1cceb3b51801d136b3ba8b38d3d23b59 Mon Sep 17 00:00:00 2001
+From c998771d7edc1c3ce16828a1580ad75421ea98d8 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/725] Speed up console framebuffer imageblit function
+Subject: [PATCH 042/773] 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 4a615d508ab20ee974c7f787739157ad86fcd410 Mon Sep 17 00:00:00 2001
+From 1793cc7704dcbf4931dc8d04867004353d00f3d9 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/725] dmaengine: Add support for BCM2708
+Subject: [PATCH 043/773] dmaengine: Add support for BCM2708
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From b780980e2f381fd19c8d42af07d3d0b8aac3a8e2 Mon Sep 17 00:00:00 2001
+From aa92feca9ae2674e9191bf9a4c8d165c87ae5189 Mon Sep 17 00:00:00 2001
From: gellert <gellert@raspberrypi.org>
Date: Fri, 15 Aug 2014 16:35:06 +0100
-Subject: [PATCH 044/725] MMC: added alternative MMC driver
+Subject: [PATCH 044/773] MMC: added alternative MMC driver
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From d09bc280308712a775258a4ddf6198ba0d3bcfd5 Mon Sep 17 00:00:00 2001
+From 7ad5e921f530063f046ce235ed6f55d01eb78413 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/725] Adding bcm2835-sdhost driver, and an overlay to
+Subject: [PATCH 045/773] Adding bcm2835-sdhost driver, and an overlay to
enable it
BCM2835 has two SD card interfaces. This driver uses the other one.
-From 754aa63cbba18514970ea307d54fdfe4eb7072ea Mon Sep 17 00:00:00 2001
+From 93b3b9250376bb35bca0bde19bc89bb63c180ff0 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Fri, 28 Oct 2016 15:36:43 +0100
-Subject: [PATCH 046/725] vc_mem: Add vc_mem driver for querying firmware
+Subject: [PATCH 046/773] vc_mem: Add vc_mem driver for querying firmware
memory addresses
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
-From 42afc949534ce6402c3e2e13d7c939af45573376 Mon Sep 17 00:00:00 2001
+From 476134eef8d9653ecaeff0381af84e2504ce5bd8 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/725] vcsm: VideoCore shared memory service for BCM2835
+Subject: [PATCH 047/773] vcsm: VideoCore shared memory service for BCM2835
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 66a15ff847fb92d85deb19e694d999ad5d806401 Mon Sep 17 00:00:00 2001
+From 08f9a940fe1b035594d00429b9f6d419e8cd3462 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/725] Add /dev/gpiomem device for rootless user GPIO access
+Subject: [PATCH 048/773] Add /dev/gpiomem device for rootless user GPIO access
Signed-off-by: Luke Wren <luke@raspberrypi.org>
-From dfb42085ee75db965bffe304287bea68b93b4b39 Mon Sep 17 00:00:00 2001
+From f6a37d5b1049bede71ce494b8012147c894cc952 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/725] Add SMI driver
+Subject: [PATCH 049/773] Add SMI driver
Signed-off-by: Luke Wren <wren6991@gmail.com>
---
-From f468b36a6b998cf9848bfcc24370cf13b2730b93 Mon Sep 17 00:00:00 2001
+From bb78ae5643905df0ce416f9eaffe2f9213177a77 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/725] MISC: bcm2835: smi: use clock manager and fix reload
+Subject: [PATCH 050/773] MISC: bcm2835: smi: use clock manager and fix reload
issues
Use clock manager instead of self-made clockmanager.
-From 680df120e2054ce209e24415795a972bf76826b3 Mon Sep 17 00:00:00 2001
+From 7df8e7537434f4f3749c638b546525fc41b4a57d 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/725] Add SMI NAND driver
+Subject: [PATCH 051/773] Add SMI NAND driver
Signed-off-by: Luke Wren <wren6991@gmail.com>
---
-From 7e52446393c3cc4200fa08dcfd1ea555d77c7068 Mon Sep 17 00:00:00 2001
+From de152ef18b69c7a911fab5c2f3b72c70d0e680b2 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 3 Jul 2013 00:49:20 +0100
-Subject: [PATCH 052/725] Add cpufreq driver
+Subject: [PATCH 052/773] Add cpufreq driver
Signed-off-by: popcornmix <popcornmix@gmail.com>
-From 92480253067c3534b16f4827f075f5590120b046 Mon Sep 17 00:00:00 2001
+From 6ad4f3378258d91a52e78b0e13f2ecee4e978658 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 17 Jun 2015 15:44:08 +0100
-Subject: [PATCH 053/725] Add Chris Boot's i2c driver
+Subject: [PATCH 053/773] Add Chris Boot's i2c driver
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From a9c2c59a13c9138494b3adb1ce918def9825c376 Mon Sep 17 00:00:00 2001
+From bfa7594cc289ff4a8c5acec645f087c3ff2ce5aa 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/725] char: broadcom: Add vcio module
+Subject: [PATCH 054/773] char: broadcom: Add vcio module
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From c31f46a51f80fe435de05dc07859291d3540c096 Mon Sep 17 00:00:00 2001
+From 53433ceaacdb15fe60eefcc268f2fe168f04c1e2 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/725] firmware: bcm2835: Support ARCH_BCM270x
+Subject: [PATCH 055/773] firmware: bcm2835: Support ARCH_BCM270x
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 429e2d968172360c0b7a443229503158910abb92 Mon Sep 17 00:00:00 2001
+From d57d7f5a9a634a635704cedb1c966905825cdc89 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/725] scripts: Add mkknlimg and knlinfo scripts from tools
+Subject: [PATCH 056/773] scripts: Add mkknlimg and knlinfo scripts from tools
repo
The Raspberry Pi firmware looks for a trailer on the kernel image to
-From 2b8bc69a15a59b93330d37fb8629ae113231a0fb Mon Sep 17 00:00:00 2001
+From d7fb08d8e23af05a7248394430a01a2555597799 Mon Sep 17 00:00:00 2001
From: notro <notro@tronnes.org>
Date: Wed, 9 Jul 2014 14:46:08 +0200
-Subject: [PATCH 057/725] BCM2708: Add core Device Tree support
+Subject: [PATCH 057/773] BCM2708: Add core Device Tree support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From ed4300c1a1c2432efd902454146e2ca909b23192 Mon Sep 17 00:00:00 2001
+From ffa37fefc5277263e7179fe8457bd0cda6b03c8b 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/725] BCM270x_DT: Add pwr_led, and the required "input"
+Subject: [PATCH 058/773] BCM270x_DT: Add pwr_led, and the required "input"
trigger
The "input" trigger makes the associated GPIO an input. This is to support
-From 4f3938a0decb1d939978df44ac060deaa886b7c1 Mon Sep 17 00:00:00 2001
+From fcaf4a45648aac0dfd88fbd280ecf5e1ac5be59f 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/725] fbdev: add FBIOCOPYAREA ioctl
+Subject: [PATCH 059/773] fbdev: add FBIOCOPYAREA ioctl
Based on the patch authored by Ali Gholami Rudi at
https://lkml.org/lkml/2009/7/13/153
-From e408564fff425286f3acf9f625aa763d5cb8408b Mon Sep 17 00:00:00 2001
+From ae6c23aa172d13ca72927870ab611e9d3670e97e Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 3 Jul 2013 00:54:08 +0100
-Subject: [PATCH 060/725] Added Device IDs for August DVB-T 205
+Subject: [PATCH 060/773] Added Device IDs for August DVB-T 205
---
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 4 ++++
-From e04d6501cf52bc69d75adef77482d6f6b027032d Mon Sep 17 00:00:00 2001
+From f045ca6af84df7b50066af98513d8e68ad899c38 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/725] rpi-ft5406: Add touchscreen driver for pi LCD display
+Subject: [PATCH 061/773] 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 4db2d4944e658ce809e6366a3a1338d0c2939231 Mon Sep 17 00:00:00 2001
+From c48528dc592ebe7948cd7a8198eb5667026ca020 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 28 Nov 2016 16:50:04 +0000
-Subject: [PATCH 062/725] Improve __copy_to_user and __copy_from_user
+Subject: [PATCH 062/773] Improve __copy_to_user and __copy_from_user
performance
Provide a __copy_from_user that uses memcpy. On BCM2708, use
-From 799527e3596ebb96f5df8174818c193a8ca68781 Mon Sep 17 00:00:00 2001
+From e0b5d4946d64b18bcf69082d7d6091b9f43b77ce 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/725] gpio-poweroff: Allow it to work on Raspberry Pi
+Subject: [PATCH 063/773] 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 8d80ce248d128b583244b0b00ce89ffa39598fe7 Mon Sep 17 00:00:00 2001
+From 0a50f4e59434ca8fd5c21b19248563e5b5c9f38f 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/725] mfd: Add Raspberry Pi Sense HAT core driver
+Subject: [PATCH 064/773] mfd: Add Raspberry Pi Sense HAT core driver
---
drivers/input/joystick/Kconfig | 8 +
-From b63482e725f4dd2c6adcda4878e5eadac238f05b Mon Sep 17 00:00:00 2001
+From d7a232c8d27cf9285c554779e40178330c17491f 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/725] ASoC: pcm512x: implement set_tdm_slot interface
+Subject: [PATCH 065/773] 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 5a5287ced8232a84e624c198b4595684134ff8f7 Mon Sep 17 00:00:00 2001
+From 104942fa9bff9c350d43bfe4d28c2e2df1fd1ac8 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/725] ASoC: Add support for Rpi-DAC
+Subject: [PATCH 066/773] ASoC: Add support for Rpi-DAC
---
sound/soc/codecs/Kconfig | 5 +++
-From 6cea04a434dfd4f3fbf02fdb5652d50a24586b18 Mon Sep 17 00:00:00 2001
+From a70c182f8eb7a022361dd64dab060f560f84a671 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/725] Add IQaudIO Sound Card support for Raspberry Pi
+Subject: [PATCH 067/773] Add IQaudIO Sound Card support for Raspberry Pi
Set a limit of 0dB on Digital Volume Control
-From 015277e926834c77787f4b6b15871f72e7b22d47 Mon Sep 17 00:00:00 2001
+From 9b55a252e259414db47de0f981708521fc51d181 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/725] Added support for HiFiBerry DAC+
+Subject: [PATCH 068/773] 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 87a94fcef688251a514e9fa209a8c4ff63cdee73 Mon Sep 17 00:00:00 2001
+From c0af89bc141d0c72bab672b5cce696dfc4e1eea1 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/725] Added driver for HiFiBerry Amp amplifier add-on board
+Subject: [PATCH 069/773] 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 931b6e6c23f08ac08c5542ae2fae4ae6ab6eeec1 Mon Sep 17 00:00:00 2001
+From 691d5ded2ab2655fdc0c8307b1c3b08be392b28c 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/725] Add driver for rpi-proto
+Subject: [PATCH 070/773] 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 dc3e8f3e1d03f43d2af2709b6d5f09d72ef8d47e Mon Sep 17 00:00:00 2001
+From 4765b12ebb0465999c213d53f94d7c60105f98f3 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/725] Add Support for JustBoom Audio boards
+Subject: [PATCH 071/773] Add Support for JustBoom Audio boards
justboom-dac: Adjust for ALSA API change
-From 7a3906eb4db44354f2a3f7a330c1648964e51681 Mon Sep 17 00:00:00 2001
+From 224b829d4334d2390f0293926f0c99253f4d5b14 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/725] New AudioInjector.net Pi soundcard with low jitter
+Subject: [PATCH 072/773] 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 c2c45a480f012a6d939f39470e9d3a5e689b8b03 Mon Sep 17 00:00:00 2001
+From 1e69f580c1615e9d6bfc3cd858aee581f3adb997 Mon Sep 17 00:00:00 2001
From: escalator2015 <jmtasende@gmail.com>
Date: Tue, 24 May 2016 16:20:09 +0100
-Subject: [PATCH 073/725] New driver for RRA DigiDAC1 soundcard using WM8741 +
+Subject: [PATCH 073/773] New driver for RRA DigiDAC1 soundcard using WM8741 +
WM8804
---
-From 54fc10a745ca32f55c504e6b08238da56ec3fa83 Mon Sep 17 00:00:00 2001
+From f4161c46775cd324c810a5180ed8fa9b52c05e2f 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/725] Add support for Dion Audio LOCO DAC-AMP HAT
+Subject: [PATCH 074/773] Add support for Dion Audio LOCO DAC-AMP HAT
Using dedicated machine driver and pcm5102a codec driver.
-From 45f28f47c5b4a3fabf33304c3660496da0b9dbcd Mon Sep 17 00:00:00 2001
+From 24cf9801cad90b0339f3598941cb9acf9c174cd2 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/725] Allo Piano DAC boards: Initial 2 channel (stereo)
+Subject: [PATCH 075/773] 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 9659dfa0a5626b730b3b72431204ce541392e9f7 Mon Sep 17 00:00:00 2001
+From 13ecb19ca5c74eab30e3299e5ac0bd7691fe2ad4 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/725] Add support for Allo Piano DAC 2.1 plus add-on board
+Subject: [PATCH 076/773] 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 337c790ae688ad33941262b852a1ab88c3a9960b Mon Sep 17 00:00:00 2001
+From 67af45a08ac8e54898184f46f73695c3fef0e288 Mon Sep 17 00:00:00 2001
From: BabuSubashChandar <babuenir@gmail.com>
Date: Tue, 28 Mar 2017 20:04:42 +0530
-Subject: [PATCH 077/725] Add support for Allo Boss DAC add-on board for
+Subject: [PATCH 077/773] Add support for Allo Boss DAC add-on board for
Raspberry Pi. (#1924)
Signed-off-by: Baswaraj K <jaikumar@cem-solutions.net>
-From 225c4a483b34eb88cab2d617a961fef9cb5a876e Mon Sep 17 00:00:00 2001
+From ab57d8cfcba75b62aba894166ca543adda239b53 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/725] Support for Blokas Labs pisound board
+Subject: [PATCH 078/773] Support for Blokas Labs pisound board
Pisound dynamic overlay (#1760)
-From 8341fbb96fa8a6802b316530d00799e2eeaf2962 Mon Sep 17 00:00:00 2001
+From f8b2aa93bbf3d97b56708575b3530dcdfc8148e9 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/725] ASoC: Add driver for Cirrus Logic Audio Card
+Subject: [PATCH 079/773] 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 261e3e2577768d848277489e26759f3f37b25aae Mon Sep 17 00:00:00 2001
+From f375073d23af1f3818c8a4fcf24406e1ab6fcc5c Mon Sep 17 00:00:00 2001
From: Miquel <miquelblauw@hotmail.com>
Date: Fri, 24 Feb 2017 20:51:06 +0100
-Subject: [PATCH 080/725] sound: Support for Dion Audio LOCO-V2 DAC-AMP HAT
+Subject: [PATCH 080/773] sound: Support for Dion Audio LOCO-V2 DAC-AMP HAT
Signed-off-by: Miquel Blauw <info@dionaudio.nl>
-From 132ffc095977fbd3e3b4099deaba2b80ed4d13ed Mon Sep 17 00:00:00 2001
+From d27ecf8d98bba570fbb2bac88a9a01d4eedcf3fe 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/725] Add support for Fe-Pi audio sound card. (#1867)
+Subject: [PATCH 081/773] 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 3c3d9b8ffa1f47da2225262dc2bac5decc043f6d Mon Sep 17 00:00:00 2001
+From 1f7175bb016838bfbac59f80bef52797f7f2af98 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/725] Add support for the AudioInjector.net Octo sound card
+Subject: [PATCH 082/773] Add support for the AudioInjector.net Octo sound card
AudioInjector Octo: sample rates, regulators, reset
-From 18914c73280bbb74c77f7d5fef622e26ea4e4ffc Mon Sep 17 00:00:00 2001
+From 2276f398046e7da29637248b6b4ca69ca629f0e0 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/725] Driver support for Google voiceHAT soundcard.
+Subject: [PATCH 083/773] Driver support for Google voiceHAT soundcard.
ASoC: googlevoicehat-codec: Use correct device when grabbing GPIO
-From 414559d38e5fb6fe74e8a54a2b9de22f6d238a05 Mon Sep 17 00:00:00 2001
+From 4ad6eeb13a6827931f9c7ecde992b7170906aeee 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/725] Driver and overlay for Allo Katana DAC
+Subject: [PATCH 084/773] Driver and overlay for Allo Katana DAC
Allo Katana DAC: Updated default values
-From 0d0387de52b82694b9df90476e21e6828025d1e9 Mon Sep 17 00:00:00 2001
+From a8198b0a3da790941874ee60dbc5df59dc77c20d 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/725] ASoC: wm8804: MCLK configuration options, 32-bit
+Subject: [PATCH 085/773] 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 49d8b4eebd733c26bdd95f44352c0344af5b4472 Mon Sep 17 00:00:00 2001
+From a2ae45419ff9d010052bbeb6780371b3cfa18350 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/725] ASoC: Add generic RPI driver for simple soundcards.
+Subject: [PATCH 086/773] 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 3f31d54804aebb748f200841dafdc8ff1f05b7a7 Mon Sep 17 00:00:00 2001
+From 89ac5c03f7ab842fb3ef6d520f0a45ff5498d4ae Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 3 Sep 2018 17:00:36 +0100
-Subject: [PATCH 087/725] ASoC: Add Kconfig and Makefile for sound/soc/bcm
+Subject: [PATCH 087/773] ASoC: Add Kconfig and Makefile for sound/soc/bcm
Signed-off-by: popcornmix <popcornmix@gmail.com>
---
-From 5b797e80e454e59af7381b579305cc25f70871d8 Mon Sep 17 00:00:00 2001
+From 058ee9a51d642274c5c934da7718ddc161dff612 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/725] ASoC: Create a generic Pi Hat WM8804 driver
+Subject: [PATCH 088/773] 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 a9adc2921cd7b460c25c4149374c7e94675d04fc Mon Sep 17 00:00:00 2001
+From 43620b62fe1375fdc5bbceab390fcb218f5f931d Mon Sep 17 00:00:00 2001
From: P33M <P33M@github.com>
Date: Wed, 21 Oct 2015 14:55:21 +0100
-Subject: [PATCH 089/725] rpi_display: add backlight driver and overlay
+Subject: [PATCH 089/773] 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 2839c328b46a97314f6f9cfb5cd0c1be9bc174f3 Mon Sep 17 00:00:00 2001
+From 4c4b56d57c963d20437c9c8669f1e8e38c32d70f Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 23 Feb 2016 19:56:04 +0000
-Subject: [PATCH 090/725] bcm2835-virtgpio: Virtual GPIO driver
+Subject: [PATCH 090/773] bcm2835-virtgpio: Virtual GPIO driver
Add a virtual GPIO driver that uses the firmware mailbox interface to
request that the VPU toggles LEDs.
-From de205caf53ef335d29f3d68f18f7bf996d1e0728 Mon Sep 17 00:00:00 2001
+From 89994ba722850d5e3834ed5af575335598c02900 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 3 Sep 2012 17:10:23 +0100
-Subject: [PATCH 091/725] net: Add non-mainline source for rtl8192cu wlan
+Subject: [PATCH 091/773] net: Add non-mainline source for rtl8192cu wlan
We are now syncing with version from:
https://github.com/pvaret/rtl8192cu-fixes
-From 40d6d85f902e7de4721db52394da172d3d5f2724 Mon Sep 17 00:00:00 2001
+From 5b3aba3e1bf3c6206eb9128cc428a5f9219626ca 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/725] OF: DT-Overlay configfs interface
+Subject: [PATCH 092/773] 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 7f688c61d8a1f881e58ae32af51506141a64b1e2 Mon Sep 17 00:00:00 2001
+From d9a6207ccbad2478e72617ef46f766804bb76587 Mon Sep 17 00:00:00 2001
From: Cheong2K <cheong@redbear.cc>
Date: Fri, 26 Feb 2016 18:20:10 +0800
-Subject: [PATCH 093/725] brcm: adds support for BCM43341 wifi
+Subject: [PATCH 093/773] brcm: adds support for BCM43341 wifi
brcmfmac: Disable power management
-From 99150b44461c1b5a988297cab7f0188a291afec9 Mon Sep 17 00:00:00 2001
+From 5b79e8e149653e295ae236e1822043da4b48374d 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/725] brcmfmac: Mute expected startup 'errors'
+Subject: [PATCH 094/773] brcmfmac: Mute expected startup 'errors'
The brcmfmac WiFi driver always complains about the '00' country code.
Modify the driver to ignore '00' silently.
-From bddfcc074a6f46d2d107d5c6b06c5b6c906bbe19 Mon Sep 17 00:00:00 2001
+From 2494b1364a65c2dc1129595679072648a07d335f 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/725] hci_h5: Don't send conf_req when ACTIVE
+Subject: [PATCH 095/773] 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 97cc0418de0e851cf4a850a99878f8ddf31f8a64 Mon Sep 17 00:00:00 2001
+From 2068b119f839ba4cdfda454d78aa62d3c3acc131 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 13 Apr 2015 17:16:29 +0100
-Subject: [PATCH 096/725] config: Add default configs
+Subject: [PATCH 096/773] config: Add default configs
---
arch/arm/configs/bcm2709_defconfig | 1360 ++++++++++++++++++++++++++++
-From 974e489f199d585ebe57440969ab9661ce2156c9 Mon Sep 17 00:00:00 2001
+From 43340f82810a4a42fba9de7a9b1e86fd1627cf59 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/725] Add arm64 configuration and device tree differences.
+Subject: [PATCH 097/773] Add arm64 configuration and device tree differences.
Disable MMC_BCM2835_SDHOST and MMC_BCM2835 since these drivers are crashing
at the moment.
-From e65d132bca6b87ae1606ef156581f1de76b80962 Mon Sep 17 00:00:00 2001
+From 879edf5a5f22f59fd74ca76600893824f03a0377 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/725] ARM64/DWC_OTG: Port dwc_otg driver to ARM64
+Subject: [PATCH 098/773] 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 6b47138814b0e244c65c9d06d08fa9aca67b7904 Mon Sep 17 00:00:00 2001
+From da17ee9a28d7eca27180f7be2da4c8dbba933cda 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/725] ARM64: Round-Robin dispatch IRQs between CPUs.
+Subject: [PATCH 099/773] 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 89c5a60b701b67a5bb3458fbe99a45da1d718e47 Mon Sep 17 00:00:00 2001
+From 8e4c9f6bf61c397d57c04ff788f6bf829ab0e71d 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/725] ARM64: Force hardware emulation of deprecated
+Subject: [PATCH 100/773] ARM64: Force hardware emulation of deprecated
instructions.
---
-From 0a1ea6126555abaf874f76c7d0c45f8d34b9c7a4 Mon Sep 17 00:00:00 2001
+From 70cb983c5f4eb3113b0db5ff942436f654cb7070 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/725] build/arm64: Add rules for .dtbo files for dts
+Subject: [PATCH 101/773] build/arm64: Add rules for .dtbo files for dts
overlays
We now create overlays as .dtbo files.
-From 007008145da2e877e32090a4861440f56bc40080 Mon Sep 17 00:00:00 2001
+From 92ea93a96eb1da7c749e21d6fc7ee4a262c0c9be Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Fri, 25 Aug 2017 19:18:13 +0100
-Subject: [PATCH 102/725] cache: export clean and invalidate
+Subject: [PATCH 102/773] cache: export clean and invalidate
---
arch/arm/mm/cache-v6.S | 4 ++--
-From a7a7bff51039648f4d09d690bb037d02b26e593c Mon Sep 17 00:00:00 2001
+From 648684da0a63367994b3dcf4ef942b7318e8241e 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/725] AXI performance monitor driver (#2222)
+Subject: [PATCH 103/773] AXI performance monitor driver (#2222)
Uses the debugfs I/F to provide access to the AXI
bus performance monitors.
-From 8ad27448ac0130fe78dbe1eaa1ce2d640669fb05 Mon Sep 17 00:00:00 2001
+From 02d5e4bd4cc97f5560eae4a81213628223371f9b 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/725] mcp2515: Use DT-supplied interrupt flags
+Subject: [PATCH 104/773] 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 4d326f3b4817e2a29d4ae69239c1ec2ef4a321a1 Mon Sep 17 00:00:00 2001
+From 75e6be3515cf5adc08911c91257fe79ede211b40 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/725] Tidy up of the ft5406 driver to use DT (#2189)
+Subject: [PATCH 105/773] 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 15dc7e960b0de2d10a312e2be3ed6674f440cf61 Mon Sep 17 00:00:00 2001
+From 93d1bb6413ea50140a7af5b14765b8805b1daa1c 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/725] cgroup: Disable cgroup "memory" by default
+Subject: [PATCH 106/773] 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 5f4a7f6cabf2f7fdd75f8dba64394ed3f5c96d09 Mon Sep 17 00:00:00 2001
+From 16b1975469af109908a05ac3a1d03a3091332786 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/725] ARM: bcm2835: Set Serial number and Revision
+Subject: [PATCH 107/773] ARM: bcm2835: Set Serial number and Revision
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 83846923572c7b606ba85dfe613e38236e8bd695 Mon Sep 17 00:00:00 2001
+From ba20268292856cc3949f441be006a2ca0c1c912e 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/725] ARM: Activate FIQs to avoid __irq_startup warnings
+Subject: [PATCH 108/773] 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 3d00548e917e42a5d9da031c8dab8a52ff3cd1cc Mon Sep 17 00:00:00 2001
+From d5ffaa38d9c117b03dac00a07dbc67e3e2c34258 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/725] serial: 8250: bcm2835aux - suppress EPROBE_DEFER
+Subject: [PATCH 109/773] serial: 8250: bcm2835aux - suppress EPROBE_DEFER
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From 46828eb52e1d51dafb26f9073bd2b36dcf18596b Mon Sep 17 00:00:00 2001
+From 95017b7441b7eddb6c9b6f372e447e739b25fca2 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/725] raspberrypi-firmware: Export the general transaction
+Subject: [PATCH 110/773] raspberrypi-firmware: Export the general transaction
function.
The vc4-firmware-kms module is going to be doing the MBOX FB call.
-From c8ae9b8e203f05c0a87f2576a58dbc6c747527c4 Mon Sep 17 00:00:00 2001
+From a59320bbcf8c137b180517324a4ba97debe0125e 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/725] drm/vc4: Add a mode for using the closed firmware for
+Subject: [PATCH 111/773] drm/vc4: Add a mode for using the closed firmware for
display.
Signed-off-by: Eric Anholt <eric@anholt.net>
-From f42394aee8bcd3b7159029a4b9c66fcf35b16ba8 Mon Sep 17 00:00:00 2001
+From 7787724ab91459c78b5163e78a9e971f19fb3baf 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/725] drm/vc4: Name the primary and cursor planes in fkms.
+Subject: [PATCH 112/773] drm/vc4: Name the primary and cursor planes in fkms.
This makes debugging nicer, compared to trying to remember what the
IDs are.
-From a54d059398df5799cc17789f11d40817f2cca3ed Mon Sep 17 00:00:00 2001
+From 21bcc045d7da7c27ce9db10b188716ccfe9cd308 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/725] drm/vc4: Add DRM_DEBUG_ATOMIC for the insides of
+Subject: [PATCH 113/773] 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 d36cddb19f380051aae81cc384fce9b49625798f Mon Sep 17 00:00:00 2001
+From 78a937b1afc655d2b8f0db7058fedb5957667eb1 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/725] drm/vc4: Fix sending of page flip completion events
+Subject: [PATCH 114/773] 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 dbf8328dec97e1df1a61ca75e98b8b60e4e2e68e Mon Sep 17 00:00:00 2001
+From 23eb470a4e4f6b377b623f7449a2cbfbd18e08ab 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/725] drm/vc4: Add support for setting DPMS in firmwarekms.
+Subject: [PATCH 115/773] 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 ba6bffb620f0f25868ed7d84add448f771201947 Mon Sep 17 00:00:00 2001
+From 196ec3784c92a18582db5a64c5f4e3830467b0df 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/725] drm/vc4: Add FB modifier support to firmwarekms.
+Subject: [PATCH 116/773] drm/vc4: Add FB modifier support to firmwarekms.
Signed-off-by: Eric Anholt <eric@anholt.net>
(cherry picked from commit 11752d73488e08aaeb65fe8289a9c016acde26c2)
-From 46652925942d2947afabc11abfdfb5d42d1559d5 Mon Sep 17 00:00:00 2001
+From 5b20c39c3e8890783c448bcc3887783ec4977ff5 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/725] drm/vc4: Add missing enable/disable vblank handlers
+Subject: [PATCH 117/773] drm/vc4: Add missing enable/disable vblank handlers
in fkms.
Fixes hang at boot in 4.14.
-From e1ce159091e4bc8ce78ed9838d5935534dc40dbe Mon Sep 17 00:00:00 2001
+From aef749410ca9658579bbee07fa73d627fe916744 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 18 Apr 2017 21:43:46 +0100
-Subject: [PATCH 118/725] vc4_fkms: Apply firmware overscan offset to hardware
+Subject: [PATCH 118/773] vc4_fkms: Apply firmware overscan offset to hardware
cursor
---
-From fd2b049cb8beed1b80e9f314e55116db2d960eef Mon Sep 17 00:00:00 2001
+From 36be247fe225fdfcad65d26f491eb876a6a656de 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/725] drm/vc4: Fix warning about vblank interrupts before
+Subject: [PATCH 119/773] 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 2d976e5035d98f5ada75f088a3e16079c8eee99a Mon Sep 17 00:00:00 2001
+From 071c2a05ae5ee85bf4a439a5b91e245238e3c39b 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/725] drm/vc4: Skip SET_CURSOR_INFO when the cursor
+Subject: [PATCH 120/773] drm/vc4: Skip SET_CURSOR_INFO when the cursor
contents didn't change.
Signed-off-by: Eric Anholt <eric@anholt.net>
-From 9c3d03b62cec67df4f3c989a2eceb38c1415fa71 Mon Sep 17 00:00:00 2001
+From 8282169de778b3b84664ec322f0b1087635dda0c 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/725] drm/vc4: Remove duplicate primary/cursor fields from
+Subject: [PATCH 121/773] drm/vc4: Remove duplicate primary/cursor fields from
FKMS driver.
The CRTC has those fields and we can just use them.
-From 9c0ae7d4e7e70bd0b30073f66045a66bfabdb307 Mon Sep 17 00:00:00 2001
+From bd64f735cce50326776752622fe572b07b2faa20 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Sun, 17 Jun 2018 13:22:07 +0100
-Subject: [PATCH 122/725] vc4_firmware_kms: fix build
+Subject: [PATCH 122/773] vc4_firmware_kms: fix build
---
drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 ++++--
-From 48d20770b1aa96c6e3095316f493eab948e68c19 Mon Sep 17 00:00:00 2001
+From 98079eb738f177f7c1b70347756c975fd23f850e Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 20 Feb 2018 20:53:46 +0000
-Subject: [PATCH 123/725] hack: cache: Fix linker error
+Subject: [PATCH 123/773] hack: cache: Fix linker error
---
arch/arm/mm/cache-v7.S | 2 ++
-From b6109ee12acbda2c79f7a7a7b76806aebfcd9ed9 Mon Sep 17 00:00:00 2001
+From 4d0036813f6436a4379b7e419a33b0f3133ab657 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/725] i2c-gpio: Also set bus numbers from reg property
+Subject: [PATCH 124/773] 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 2b43c222f32b1a51a36a7511ea610adb9a51fb2b Mon Sep 17 00:00:00 2001
+From d59a35bbcea0558c6ce6d764c564e374cde349be 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/725] sound: bcm: Fix memset dereference warning
+Subject: [PATCH 125/773] sound: bcm: Fix memset dereference warning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
-From 876356d4be81b4341cbc53a42c8a88dc49d7b56d Mon Sep 17 00:00:00 2001
+From 09b89102daf86678498ce778006afea533191412 Mon Sep 17 00:00:00 2001
From: hdoverobinson <hdoverobinson@gmail.com>
Date: Tue, 13 Mar 2018 06:58:39 -0400
-Subject: [PATCH 126/725] added capture_clear option to pps-gpio via dtoverlay
+Subject: [PATCH 126/773] added capture_clear option to pps-gpio via dtoverlay
(#2433)
---
-From c2da5c5af7a2d872d2b55c818cf9e67e34923a65 Mon Sep 17 00:00:00 2001
+From 41c60a1c9ca1c94d0b1ba3a0da01715df3371134 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/725] lan78xx: Read initial EEE status from DT
+Subject: [PATCH 127/773] lan78xx: Read initial EEE status from DT
Add two new DT properties:
* microchip,eee-enabled - a boolean to enable EEE
-From 827f677549361a68c8bed46ae9bc3c6210273ace Mon Sep 17 00:00:00 2001
+From 09a9d9f973f6425de4f0fa0e7f5e5c2ce88a5385 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 14 Jul 2014 22:02:09 +0100
-Subject: [PATCH 128/725] hid: Reduce default mouse polling interval to 60Hz
+Subject: [PATCH 128/773] hid: Reduce default mouse polling interval to 60Hz
Reduces overhead when using X
---
-From 886c2877fcd6fdbff3c8cdec0e68bbb7570bc8ff Mon Sep 17 00:00:00 2001
+From 08e8005d7c7b062cd2d19b836fc3299d8f95b299 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/725] gpiolib: Don't prevent IRQ usage of output GPIOs
+Subject: [PATCH 129/773] 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 3e25c39320a501e57a5e232f6e98740357bd5bc6 Mon Sep 17 00:00:00 2001
+From 43f139a5ed053952593b71890caf5315993f873b 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/725] Add ability to export gpio used by gpio-poweroff
+Subject: [PATCH 130/773] Add ability to export gpio used by gpio-poweroff
Signed-off-by: Nick Bulleid <nedbulleid@fastmail.com>
-From ab5a0cc750eefdabd58b67c2558c46029ceb2a51 Mon Sep 17 00:00:00 2001
+From 7e7ab8da578ae366a1563f2f28837967efdee39e 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/725] firmware/raspberrypi: Notify firmware of a reboot
+Subject: [PATCH 131/773] firmware/raspberrypi: Notify firmware of a reboot
Register for reboot notifications, sending RPI_FIRMWARE_NOTIFY_REBOOT
over the mailbox interface on reception.
-From af6f3cf33a864c397f6ab43c0403b0a92797694e Mon Sep 17 00:00:00 2001
+From a5c612917a1a9ffe0d7ae7c080de1b26fda3b4ec 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/725] irqchip: irq-bcm2835: Calc. FIQ_START at boot-time
+Subject: [PATCH 132/773] 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 3a05e59e7c1866f46df63f0f11c46d3187d3adc9 Mon Sep 17 00:00:00 2001
+From 5c2c8c9b74a2418a5eee4254ac73ce1cff1fd353 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/725] of: configfs: Use of_overlay_fdt_apply API call
+Subject: [PATCH 133/773] 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 aa624ea88f53750c15729e82c0ac380b2b0768ac Mon Sep 17 00:00:00 2001
+From adf49ae8478b25486ee0df306a4a7bb973694a45 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/725] net: lan78xx: Disable TCP Segmentation Offload (TSO)
+Subject: [PATCH 134/773] 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 5ef577082ea0d6fb498e5189bd55071aed9696e7 Mon Sep 17 00:00:00 2001
+From 0da8a94476e36566743283e5037a2a964981f06e 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/725] brcmfmac: Re-enable firmware roaming support
+Subject: [PATCH 135/773] 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 95e0c441040464722e1abb50a365224e7bf9058d Mon Sep 17 00:00:00 2001
+From 8defd8d174653daae7da39d815a4f59aa48f9b53 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/725] lan78xx: Move enabling of EEE into PHY init code
+Subject: [PATCH 136/773] 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 3e9ee1b0f8b5b8ad3fc688e785de479cbde00b5c Mon Sep 17 00:00:00 2001
+From 4be8b9877d1174efea1ece7b776940795e23bd61 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/725] staging/vc04_services: Derive g_cache_line_size
+Subject: [PATCH 137/773] 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 1c1f26355604567bc11084cb3c4db204d7420941 Mon Sep 17 00:00:00 2001
+From dc8892d5b8d9a6dced6294477c33cdc9770de147 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/725] Add rpi-poe-fan driver
+Subject: [PATCH 138/773] Add rpi-poe-fan driver
Signed-off-by: Serge Schneider <serge@raspberrypi.org>
-From f78d450f7ce53a644fae11f359c133fd015cda12 Mon Sep 17 00:00:00 2001
+From c9c6842ecc6ac834d51b6368548fc9364ddc8465 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 17 Sep 2018 17:31:18 +0100
-Subject: [PATCH 139/725] cxd2880: CXD2880_SPI_DRV should select DVB_CXD2880
+Subject: [PATCH 139/773] cxd2880: CXD2880_SPI_DRV should select DVB_CXD2880
with MEDIA_SUBDRV_AUTOSELECT
---
-From 572ba427304c769cdf4d19d8d93c3d413ad57f72 Mon Sep 17 00:00:00 2001
+From 4d742a446559b31f189dba5cbcddae053e883eab Mon Sep 17 00:00:00 2001
From: wm4 <wm4@nowhere>
Date: Wed, 13 Jan 2016 19:44:47 +0100
-Subject: [PATCH 140/725] bcm2835: interpolate audio delay
+Subject: [PATCH 140/773] 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 77b81e05d19c1c25d8139eddc45c0a2da0585be2 Mon Sep 17 00:00:00 2001
+From d58a6bedcd9dc9afef4f9f56b553a03f01a7765a Mon Sep 17 00:00:00 2001
From: detule <ogjoneski@gmail.com>
Date: Tue, 2 Oct 2018 04:10:08 -0400
-Subject: [PATCH 141/725] vchiq_2835_arm: Implement a DMA pool for small bulk
+Subject: [PATCH 141/773] 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 fdac3a95e9af79a125e41d7c16e4deac80742ac5 Mon Sep 17 00:00:00 2001
+From c74590643b336259b9dc2a378e2c71c3e7fd9db1 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/725] BCM2708_DT: Use upstreamed GPIO expander driver
+Subject: [PATCH 142/773] 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 920732ad22a1e352b757d854aec4814c95d061a9 Mon Sep 17 00:00:00 2001
+From e792cc6341ac1fe205bd57bb5c06dbd46c0d11d0 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/725] overlays: Fix a few dtc warnings
+Subject: [PATCH 143/773] overlays: Fix a few dtc warnings
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From d659979d89c1de698fa7c7e28951c4f09f9dfafd Mon Sep 17 00:00:00 2001
+From 2b98edf196878141997aae6acca84ec64ed72952 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Wed, 17 Oct 2018 16:32:52 +0100
-Subject: [PATCH 144/725] bcm2708-rpi: Disable txp interrupt unless using
+Subject: [PATCH 144/773] bcm2708-rpi: Disable txp interrupt unless using
vc4-kms-v3d overlay
Signed-off-by: popcornmix <popcornmix@gmail.com>
-From 0bb32ea31ade963bfe81c67dbb2a4dbb090895c2 Mon Sep 17 00:00:00 2001
+From 8444ee737e27effe16f419a5599263029ce775af 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/725] config: Enable Raspberry Pi voltage monitor
+Subject: [PATCH 145/773] 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 af7c9bdc7c407c585fd3c6eac2ad42e78e1fb08c Mon Sep 17 00:00:00 2001
+From 8c5cc4ccdeb3bfbd0fb93dff2ac8afd49cb1f839 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/725] hwmon: raspberrypi: Prevent voltage low warnings from
+Subject: [PATCH 146/773] hwmon: raspberrypi: Prevent voltage low warnings from
filling log
Although the correct fix for low voltage warnings is to
-From 53250b67aca386f2e01881623c192089226bbae3 Mon Sep 17 00:00:00 2001
+From 87e5b540bb37f8b767f7b5480f45a9d9da38f1f5 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/725] firmware: raspberrypi: Add backward compatible
+Subject: [PATCH 147/773] firmware: raspberrypi: Add backward compatible
get_throttled
Avoid a hard userspace ABI change by adding a compatible get_throttled
-From 5ff0d8351ea1bae67c1fd8d565bb4912cf201a71 Mon Sep 17 00:00:00 2001
+From 9a94bd6bb43994d313fd8fc5ce7269985642d555 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/725] Increase firmware call buffer size to 48 bytes
+Subject: [PATCH 148/773] 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 692350cd48454616db5bde755b6d2ef29946ade7 Mon Sep 17 00:00:00 2001
+From b3722cdaf35ac854458a513680792e7ddf40fbc3 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/725] sc16is7xx: Don't spin if no data received
+Subject: [PATCH 149/773] sc16is7xx: Don't spin if no data received
See: https://github.com/raspberrypi/linux/issues/2676
-From 049db5dc012f133a8838503426a0cfa1cf9367a6 Mon Sep 17 00:00:00 2001
+From 6353f037ada4c36c7be8d56d58b3b709200e7793 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/725] configs: Rebuild bcmrpi3_defconfig to fix warnings
+Subject: [PATCH 150/773] configs: Rebuild bcmrpi3_defconfig to fix warnings
Also disable CONFIG_MMC_BCM2835 to avoid a runtime conflict.
-From f54f72309a110bbb583335dd72d84908b1f56043 Mon Sep 17 00:00:00 2001
+From c39b385b5600918ab46d4ca2d42af6609eb8676e 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/725] brcmfmac: Disable ARP offloading when promiscuous
+Subject: [PATCH 151/773] 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 d96b4839eea5d6d0a776bed39d3fb6d8cc198662 Mon Sep 17 00:00:00 2001
+From 98d0c289a857a2c55f658a2ac1d21d28f4bf4ed2 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/725] config: enable Audio Graph Card module
+Subject: [PATCH 152/773] config: enable Audio Graph Card module
Signed-off-by: Matthias Reichl <hias@horus.com>
---
-From 52c06bef6f690f7fd5ab3fde9049a022344cb0bb Mon Sep 17 00:00:00 2001
+From 4e344198693b73c3e84548cf1d343633660cc55d Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Thu, 29 Mar 2018 16:05:28 +0100
-Subject: [PATCH 153/725] config: Add IPVLAN module
+Subject: [PATCH 153/773] config: Add IPVLAN module
---
arch/arm/configs/bcm2709_defconfig | 1 +
-From 511b2e25825ff53cb5dbb5d224c747c8dd37dc8b Mon Sep 17 00:00:00 2001
+From be41c6404280c690776bbd3a2c173e3468db582a 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/725] config: Add I2C_TINY_USB=m
+Subject: [PATCH 154/773] config: Add I2C_TINY_USB=m
Enable the I2C Tiny USB module.
-From c02e400776f6cba9abef5bfec91765e694f35d3b Mon Sep 17 00:00:00 2001
+From 9b703ce83feacfe4215a392fd6b093fa624b971c 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/725] Add device tree overlay for HD44780
+Subject: [PATCH 155/773] Add device tree overlay for HD44780
---
arch/arm/boot/dts/overlays/Makefile | 1 +
-From a7523a743a928748b2961de56fe5345f653da15e Mon Sep 17 00:00:00 2001
+From 331c984914ce7c4edc432930716a6aee9899231f 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/725] Add hd44780 module to defconfig
+Subject: [PATCH 156/773] Add hd44780 module to defconfig
---
arch/arm/configs/bcm2709_defconfig | 2 ++
-From 7eaf324bc93496bb2462da74aa575a4b5c6b39da Mon Sep 17 00:00:00 2001
+From 7d32f48d6e7ba3090b0eb4b19da444a7e17ce5f6 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/725] overlays: Add addr parameter to i2c-rtc (& -gpio)
+Subject: [PATCH 157/773] overlays: Add addr parameter to i2c-rtc (& -gpio)
See: https://github.com/raspberrypi/linux/issues/2611
-From c4620c94d1a5ec51908bb670968b68fd1aa692b1 Mon Sep 17 00:00:00 2001
+From fadd4b8432f04b11898b32715e40cf03f1cd0a5f 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/725] ARM: BCM270X: Add the 18-bit DPI pinmux to the RPI
+Subject: [PATCH 158/773] 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 2fc67f0d898fb7be4e68bdb94959fdebe07b529d Mon Sep 17 00:00:00 2001
+From 78fa27dabb41e2409ee92b25c72b91e2bf8d919e 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/725] overlays: Add an overlay for the Adafruit Kippah with
+Subject: [PATCH 159/773] overlays: Add an overlay for the Adafruit Kippah with
their 7" panel
Signed-off-by: Eric Anholt <eric@anholt.net>
-From e5d4483bb784c5602ba585692cbdde1d0fbbfff9 Mon Sep 17 00:00:00 2001
+From ec2bfcc8a43b16a6892a8535bb094ad1666d16c3 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/725] overlays: Remove stale notes about vc4's CMA
+Subject: [PATCH 160/773] overlays: Remove stale notes about vc4's CMA
alignment in the README.
We haven't needed alignment since
-From 2910d986df71ea75845706084fd257d2b9127e74 Mon Sep 17 00:00:00 2001
+From 89502b903bcfb759933dab352341348c07171e7d 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/725] spi: Make GPIO CSs honour the SPI_NO_CS flag
+Subject: [PATCH 161/773] 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 bb5657317c40a44f4a550f7f7101edc6fe5f50af Mon Sep 17 00:00:00 2001
+From effbee05f84d01577c8bd95a9e79f2183f590af2 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/725] devicetree: add RPi CM3 dts to arm64; mimic the RPi
+Subject: [PATCH 162/773] 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 4accaf8828da84a10053475c100a07ae91d75c8e Mon Sep 17 00:00:00 2001
+From 703e6ff221abb10b9cd119166d4a29f5db9fd028 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/725] Add support for audioinjector.net ultra soundcard.
+Subject: [PATCH 163/773] Add support for audioinjector.net ultra soundcard.
(#2664)
Uses the simple-audio-card ALSA machine driver. Sets up the machine
-From 84e563dc0f76f480dc00ec72c04621810cf2bcb1 Mon Sep 17 00:00:00 2001
+From c42fc0c653cb19942b07ccae46e2b91346e28a2e 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/725] ASoC: cs4265: Add a S/PDIF enable switch
+Subject: [PATCH 164/773] ASoC: cs4265: Add a S/PDIF enable switch
commit f853d6b3ba345297974d877d8ed0f4a91eaca739 upstream.
-From 515db674b59d2d693b8a6dd8fc9bb2827a71335e Mon Sep 17 00:00:00 2001
+From 3c06ca7900d7c6ae6b84682d0e9f5d345d5166ca 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/725] ASoC: cs4265: Add native 32bit I2S transport
+Subject: [PATCH 165/773] ASoC: cs4265: Add native 32bit I2S transport
commit be47e75eb1419ffc1d9c26230963fd5fa3055097 upstream.
-From 160ed28c5e56e859e8e1c415e1012a9cab451af1 Mon Sep 17 00:00:00 2001
+From 41a7e42755ef7b490c0058464ee97d11f1bdd461 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/725] configs: Add SENSOR_GPIO_FAN=m
+Subject: [PATCH 166/773] configs: Add SENSOR_GPIO_FAN=m
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From 8b33ef9c1afe19c6d7e3f833e73a4bd3afa0225d Mon Sep 17 00:00:00 2001
+From b0d5a983269fef011d3e3abda047a8064f9af5e2 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/725] BCM270X_DT: Add gpio-fan overlay
+Subject: [PATCH 167/773] BCM270X_DT: Add gpio-fan overlay
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From 2403affd9cfe04af6326ccc9ba7ee64832b1881d Mon Sep 17 00:00:00 2001
+From 0576572c83348bbe268349ebf12c092ca0fba48b 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/725] HID: hid-bigbenff: driver for BigBen Interactive
+Subject: [PATCH 168/773] HID: hid-bigbenff: driver for BigBen Interactive
PS3OFMINIPAD gamepad
commit 256a90ed9e46b270bbc4e15ef05216ff049c3721 upstream.
-From f8ce06486d1946376160c956d1bc1784c9472fdb Mon Sep 17 00:00:00 2001
+From f2dd7d8a2c1206d74eb84ef4f63b13a7f63392b1 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/725] configs: Add CONFIG_HID_BIGBEN_FF=m
+Subject: [PATCH 169/773] configs: Add CONFIG_HID_BIGBEN_FF=m
See: https://github.com/raspberrypi/linux/issues/2690
-From 8a868455243fec7abfe55d4f6af9eeb94755d4b7 Mon Sep 17 00:00:00 2001
+From cc2c7587954540fc1d2954151750271bc008cf62 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/725] ASoC: cs4265: Add a MIC pre. route (#2696)
+Subject: [PATCH 170/773] ASoC: cs4265: Add a MIC pre. route (#2696)
Commit b0ef5011b981ece1fde8063243a56d3038b87adb upstream.
-From e4c16c37899bacb3a1a10c5830459fc09f3135d9 Mon Sep 17 00:00:00 2001
+From 88e367f987034c82be7a8d5c49e19ec3cad8eed1 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/725] Update gpio-fan-overlay.dts (#2711)
+Subject: [PATCH 171/773] Update gpio-fan-overlay.dts (#2711)
Add references, links, clear details, some typo correction.
---
-From 158b0f9b48e2974cbe8b83ab0024a05ebcefbe99 Mon Sep 17 00:00:00 2001
+From 6721879de09edff1a89b382b6e3914477ce08c5c 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/725] drivers: thermal: step_wise: add support for
+Subject: [PATCH 172/773] drivers: thermal: step_wise: add support for
hysteresis
From: Ram Chandrasekar <rkumbako@codeaurora.org>
-From e381db8721f2658d7c90183b4685bb62e96db6fe Mon Sep 17 00:00:00 2001
+From f6614c4064acb5faaced0bb6597d7eac914c8ec5 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/725] drivers: thermal: step_wise: avoid throttling at
+Subject: [PATCH 173/773] drivers: thermal: step_wise: avoid throttling at
hysteresis temperature after dropping below it
Signed-off-by: Serge Schneider <serge@raspberrypi.org>
-From 6699b062f9bebb291c65f8402a62e99c71402ed0 Mon Sep 17 00:00:00 2001
+From dfa854f6d944d5e6fa84588639f7e19dba9cc366 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/725] hwmon: adjust rpi-poe-fan overlay trip points
+Subject: [PATCH 174/773] hwmon: adjust rpi-poe-fan overlay trip points
Signed-off-by: Serge Schneider <serge@raspberrypi.org>
---
-From db562e1eaed352231730eebcdc22b5c305e42338 Mon Sep 17 00:00:00 2001
+From 684d123ddc0b21807daca521d3b96f53ca9d2c8f 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/725] overlays: add overrides for PoE HAT fan control
+Subject: [PATCH 175/773] overlays: add overrides for PoE HAT fan control
Signed-off-by: Serge Schneider <serge@raspberrypi.org>
---
-From dc7881193fbee4ac1235d5a87af7d3abef3bee14 Mon Sep 17 00:00:00 2001
+From 00a2e04120a68c286d7fd86ed28ea9214d7c110e 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/725] overlays: Add gpio-no-bank0-irq overlay
+Subject: [PATCH 176/773] overlays: Add gpio-no-bank0-irq overlay
See: https://github.com/raspberrypi/linux/issues/2590
-From ea5d66b73d721b0a21d6b3eb677dd8f65cb8a3dd Mon Sep 17 00:00:00 2001
+From c26aaad256a30f6643b13c51c474f73ddc687907 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/725] Add hy28b 2017 model device tree overlay (#2721)
+Subject: [PATCH 177/773] Add hy28b 2017 model device tree overlay (#2721)
The 2017 version of the hy28b display requires a different
initialisation sequence.
-From e7010b9f0497dd34e8b054b321d82e44925594dc Mon Sep 17 00:00:00 2001
+From a8a78956e8ec25d8bb02a4c61ef3e3d79d76ea6e Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Thu, 25 Oct 2018 14:08:43 +0100
-Subject: [PATCH 178/725] config: Add CONFIG_USBIP_VUDC
+Subject: [PATCH 178/773] config: Add CONFIG_USBIP_VUDC
See: https://github.com/raspberrypi/firmware/issues/353
---
-From d5188bb19c7c3a01091e0779a94c67c2b6314005 Mon Sep 17 00:00:00 2001
+From 867f8cafac844f77a96bd953e7062295c4c11e6e 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/725] mmc/bcm2835-sdhost: Recover from MMC_SEND_EXT_CSD
+Subject: [PATCH 179/773] 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 4f60a9f26c17f3722c6cc6b4af149ff8db4f6e47 Mon Sep 17 00:00:00 2001
+From 61f8d9f6ea34868d97338bef3408402ffe3ada10 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/725] overlays: pi3-disable-bt: Clear out bt_pins node
+Subject: [PATCH 180/773] 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 759061b16cf853b38c8cce3688fb8566b3e8b413 Mon Sep 17 00:00:00 2001
+From c1c90b4f7c49fc0372fa032387e9f34100dcd4bf 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/725] Revert "rtc: pcf8523: properly handle oscillator stop
+Subject: [PATCH 181/773] Revert "rtc: pcf8523: properly handle oscillator stop
bit"
This reverts commit ede44c908d44b166a5b6bd7caacd105c2ff5a70f.
-From 70971c0ca8a15bca1ff755494bc83b161cf363f6 Mon Sep 17 00:00:00 2001
+From d2dd787367a5ec388288f0de44e2723c01d067a0 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/725] Update issue templates (#2736)
+Subject: [PATCH 182/773] Update issue templates (#2736)
---
.github/ISSUE_TEMPLATE/bug_report.md | 34 ++++++++++++++++++++++++++++
-From 964ca9ac6a8e55a3563734d0e9c1219bc6e42813 Mon Sep 17 00:00:00 2001
+From 1b6b32c9ea654fc7920093c007634495710bae95 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/725] overlays: uart0 - return GPIOs 14 and 15 to inputs
+Subject: [PATCH 183/773] 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 cebac10c14079ce87b94a9e7caa77cdbf883f458 Mon Sep 17 00:00:00 2001
+From 65f18edd464048b79cb099dce34be1598991fe62 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/725] mmc: bcm2835-sdhost: Fix warnings on arm64
+Subject: [PATCH 184/773] mmc: bcm2835-sdhost: Fix warnings on arm64
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From 2a1d1f77ccfc4e5f4b2b4df23504df77d5aceda1 Mon Sep 17 00:00:00 2001
+From 1129112e098f6e62294315dc648c3d087e9b22c6 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/725] Fix warning in bcm2835-smi-nand
+Subject: [PATCH 185/773] Fix warning in bcm2835-smi-nand
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From 5d582dbe8344f87fb726b4e35620dc0ca554337f Mon Sep 17 00:00:00 2001
+From c9193b85075262576cd7cfc841a62ff0e7337415 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/725] media: ov5647: Add set_fmt and get_fmt calls.
+Subject: [PATCH 186/773] media: ov5647: Add set_fmt and get_fmt calls.
There's no way to query the subdevice for the supported
resolutions.
-From 31f9d16b849bc50df1a0393a5b858fe3e56e7809 Mon Sep 17 00:00:00 2001
+From 77769b83fb4c81159a067832405ac5d6603658f7 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/725] [media] Documentation: DT: add device tree for PWDN
+Subject: [PATCH 187/773] [media] Documentation: DT: add device tree for PWDN
control
Add optional GPIO pwdn to connect to the PWDN line on the sensor.
-From 7330f9a31cb271e4b148bf171cec1ce32c25338a Mon Sep 17 00:00:00 2001
+From e145348320361d66bcc6e733be36849d22816dee 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/725] media: ov5647: Add support for PWDN GPIO.
+Subject: [PATCH 188/773] media: ov5647: Add support for PWDN GPIO.
Add support for an optional GPIO connected to PWDN on the sensor.
-From 39de5418b771d8506e2836fec7d4296983fee954 Mon Sep 17 00:00:00 2001
+From db4060811ce6f11c7765201104292907d2e7a709 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/725] media: ov5647: Add support for non-continuous clock
+Subject: [PATCH 189/773] media: ov5647: Add support for non-continuous clock
mode
The driver was only supporting continuous clock mode
-From 9774cb0c44ed8d6394b6cb7c742517a2c7989f09 Mon Sep 17 00:00:00 2001
+From c2d3413f2eea6311207d90e6087ca9d0f26f0b51 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/725] media: tc358743: Increase FIFO level to 374.
+Subject: [PATCH 190/773] 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 5edf7cf2cfe901e8df2d698eaf518f856308313f Mon Sep 17 00:00:00 2001
+From f0b7ea20f73980abefc5cf63bbb2550429a30213 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/725] media: tc358743: fix connected/active CSI-2 lane
+Subject: [PATCH 191/773] media: tc358743: fix connected/active CSI-2 lane
reporting
g_mbus_config was supposed to indicate all supported lane numbers, not
-From f372eaac56da0592bef997c681b05525f1950745 Mon Sep 17 00:00:00 2001
+From 79aaa6bcdc029ca754ee00c79865d2a92eba63ec 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/725] media: tc358743: Add support for 972Mbit/s link freq.
+Subject: [PATCH 192/773] 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 02d715b6d479f2f67244056d731f37c5b1475f37 Mon Sep 17 00:00:00 2001
+From 552313759a2e78b5cf9f912700632c2eedad86dc 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/725] media: tc358743: Check I2C succeeded during probe.
+Subject: [PATCH 193/773] 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 156dcf0046229d377ab882094f7ea7b80c411eaa Mon Sep 17 00:00:00 2001
+From 22d9c8913dec1a208080a19f887c9139fe763c78 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/725] media: adv7180: Default to the first valid input
+Subject: [PATCH 194/773] media: adv7180: Default to the first valid input
The hardware default is differential CVBS on AIN1 & 2, which
isn't very useful.
-From 888202a50fd8f8eb16e57d2f35621bdcaff3c0c5 Mon Sep 17 00:00:00 2001
+From 17bcb47714e64b5895cacd53c13256b71096ea4c 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/725] media: adv7180: Add YPrPb support for ADV7282M
+Subject: [PATCH 195/773] 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 37a1cdda51bc5989510ccfe28ccf149a1e5c3f76 Mon Sep 17 00:00:00 2001
+From c657a29da3a1e182d04f109f6429f543ce628092 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/725] media: videodev2: Add helper defines for printing
+Subject: [PATCH 196/773] media: videodev2: Add helper defines for printing
FOURCCs
New helper defines that allow printing of a FOURCC using
-From 1f7138cdbf10ca6225ba4b1df6ab4e3c7db996bc Mon Sep 17 00:00:00 2001
+From 87a265d7cc0ba5eab2089093900e16f0ba0d12d9 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/725] dt-bindings: Document BCM283x CSI2/CCP2 receiver
+Subject: [PATCH 197/773] dt-bindings: Document BCM283x CSI2/CCP2 receiver
Document the DT bindings for the CSI2/CCP2 receiver peripheral
(known as Unicam) on BCM283x SoCs.
-From c43d7b532dd2e502330fa1457e5e952ef307504e Mon Sep 17 00:00:00 2001
+From 9ab24ead3a088215161810d46eeac4c3e6f820df 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/725] media: bcm2835-unicam: Driver for CCP2/CSI2 camera
+Subject: [PATCH 198/773] media: bcm2835-unicam: Driver for CCP2/CSI2 camera
interface
Add driver for the Unicam camera receiver block on
-From f363e576611799627bd2f5dbe3cf07c4792ccf84 Mon Sep 17 00:00:00 2001
+From f307136bb1fa010970be201765c99a844631a382 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/725] MAINTAINERS: Add entry for BCM2835 Unicam driver
+Subject: [PATCH 199/773] MAINTAINERS: Add entry for BCM2835 Unicam driver
Adds entry for the new BCM2835 Unicam (CSI-2 receiver) driver
-From ba8758df732d320e5647d23f245a8a134dde92e1 Mon Sep 17 00:00:00 2001
+From 4b02f3a9eb7af5dd98e7481be7441a88d65d012e 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/725] defconfig: Enable Unicam driver and various sources
+Subject: [PATCH 200/773] defconfig: Enable Unicam driver and various sources
on Pi platforms.
Enable:
-From 63714d94e345ffeaf2042cfe552fa2a00ed8764c Mon Sep 17 00:00:00 2001
+From 2338afc3ac82a113207a48d8b6cf70657570fc02 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/725] media: adv7180: Nasty hack to allow input selection.
+Subject: [PATCH 201/773] 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 5672dd9e874730f5a0db0b7697e5f66a7707e130 Mon Sep 17 00:00:00 2001
+From 4cd7ac090db0bb3deb0a6cb594eb27f4b296f388 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/725] BCM283x DT: Add CSI nodes to the device tree.
+Subject: [PATCH 202/773] BCM283x DT: Add CSI nodes to the device tree.
Adds CSI nodes to all the upstream device tree configs
-From 5da3b99c82d6a93af9490e759fa83caecc11550f Mon Sep 17 00:00:00 2001
+From 92a1631e84ebe27e9ef9676a20bd7ce52bcb4e7d 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/725] BCM270X_DT: Add CSI defines for all the downstream Pi
+Subject: [PATCH 203/773] BCM270X_DT: Add CSI defines for all the downstream Pi
platforms
Adds the CSI device includes for the bcm27xx platform DTS files
-From ba7e742c925b5a46ac63fe0c6e3d988eb6ea3e79 Mon Sep 17 00:00:00 2001
+From eb81063adcd2697b43ae48644d84ee333e7efa8b 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/725] arm: dt: Add DT overlays for ADV7282M, OV5647, and
+Subject: [PATCH 204/773] arm: dt: Add DT overlays for ADV7282M, OV5647, and
TC358743
DT overlays to setup the above devices via i2c_arm and csi1.
-From 9ab30d7658ba3c6ddf77661b6ca4440ef2d6e38d Mon Sep 17 00:00:00 2001
+From 0ed1f7b915bfd2167bed13b40e88cda57517faf8 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/725] dtoverlays: Add support for ADV7280-M, ADV7281-M and
+Subject: [PATCH 205/773] 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 2491694e7b0b8c09b13130f9c165a812b773e57e Mon Sep 17 00:00:00 2001
+From 7f0ab028db7c5a56d77dcbc640c71c7ab6e03eca 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/725] Mailbox firmware calls now use kmalloc (#2749)
+Subject: [PATCH 206/773] 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 c050abb666638d8f9eaa7b5557713e7d9335495f Mon Sep 17 00:00:00 2001
+From b8b33d5d5ed79adf13940f0a220a19a6ca654464 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/725] vcsm: Fix an NULL dereference in the import_dmabuf
+Subject: [PATCH 207/773] vcsm: Fix an NULL dereference in the import_dmabuf
error path
resource was dereferenced even though it was NULL.
-From 74e24f7ba3e0443ffc4d026e96848c9ec51e2dcf Mon Sep 17 00:00:00 2001
+From b2a6f4c178700de320e2ef26998f1018186b4685 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/725] Update README (#2750)
+Subject: [PATCH 208/773] Update README (#2750)
Small update to the DT blob docs to include the axiperf option.
-From 755f5c2690bd5c2b4db803600815cb1007057326 Mon Sep 17 00:00:00 2001
+From 8e81ea63bd78c944e2534844934e57b381db76ba 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/725] overlays: Remove superfluous #address/size-cells
+Subject: [PATCH 209/773] overlays: Remove superfluous #address/size-cells
Newer versions of dtc warn about unnecessary usage of #address-cells
and #size-cells, so remove them.
-From dbe949065c6b3de54cc172f6b2a906135392a4c1 Mon Sep 17 00:00:00 2001
+From 3c6e1660cc3ec16cff1c9d04559c6074378f7c06 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/725] Revert "ASoC: wm8804: MCLK configuration options,
+Subject: [PATCH 210/773] Revert "ASoC: wm8804: MCLK configuration options,
32-bit"
This reverts commit 3b12dcf797f5a4635aecd7f5c090dc507b124ffd.
-From a93fcdaf72291fea4661690cc35e1a45834e3cb7 Mon Sep 17 00:00:00 2001
+From 4477e66f7375862148dc1858328131cc1cfcaf6c 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/725] rpi-wm8804-soundcard: drop PWRDN register writes
+Subject: [PATCH 211/773] rpi-wm8804-soundcard: drop PWRDN register writes
Since kernel 4.0 the PWRDN register bits are under DAPM
control from the wm8804 driver.
-From cf634513d2b238ae041d4fd836e48c63b94c0e6b Mon Sep 17 00:00:00 2001
+From 8ecd0e38be0422967e5323f5f276466e9d206d32 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/725] rpi-wm8804-soundcard: configure wm8804 clocks only on
+Subject: [PATCH 212/773] rpi-wm8804-soundcard: configure wm8804 clocks only on
rate change
This should avoid clicks when stopping and immediately afterwards
-From c305b2c14d9ec6f297062a0410010325d783eec6 Mon Sep 17 00:00:00 2001
+From 894af91ef3da6a3d4290726d0be4a442f3757970 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/725] dtoverlays: Add i2c on 0&1 option to TC358743,
+Subject: [PATCH 213/773] 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 be3c95b4f638fc037188705615fabe0d3f25e72c Mon Sep 17 00:00:00 2001
+From 17373c6f98cd1f09159af417aa10e243480f243c 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/725] overlays: Update upstream overlay
+Subject: [PATCH 214/773] 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 16bf1291c3ffcdee88ee4838b2aa77f18bcfdd02 Mon Sep 17 00:00:00 2001
+From 051d9855062ae38032a4438cefeb827286da8562 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/725] BCM2708_DT: update firmware node binding
+Subject: [PATCH 215/773] 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 d167329afba66f1c7ac58a60941f6ee716e303b2 Mon Sep 17 00:00:00 2001
+From 040353be1c2245f875b6be2c583dd769d945e34e 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/725] BCM2710_DT: fix gpio expander bindings
+Subject: [PATCH 216/773] BCM2710_DT: fix gpio expander bindings
The upstreamed driver for the GPIO expander expects to be a children of
the "firmware" node.
-From 3cb3a4cf65c1daf812e5b29447e3282e953f308b Mon Sep 17 00:00:00 2001
+From 255c72ee64db2e0a7dd3626d7a8d72c6f9d9a1a0 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/725] ARM: dts: bcm283x: The lan7515 PHY node has moved
+Subject: [PATCH 217/773] 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 0c5f8dac2daa64a5bc4793ec5c39004ae077b739 Mon Sep 17 00:00:00 2001
+From dd7a5e5494bf5a43f33aa20eb7a9ebf233bd5f06 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/725] net: lan78xx: Support auto-downshift to 100Mb/s
+Subject: [PATCH 218/773] 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 557a6998397903dd9416fdc717fa8016ef6b6d31 Mon Sep 17 00:00:00 2001
+From 27d13833587a1c8655744d56b45ac2fdc2c5b483 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/725] dt-bindings: Document microchip,downshift-after
+Subject: [PATCH 219/773] dt-bindings: Document microchip,downshift-after
Document the optional downshift-after property of the lan78xx's PHY.
-From 1ee1b7cac821e90ac203c4274623fc03154be42d Mon Sep 17 00:00:00 2001
+From 649fc3935ba058e6ae4c97a02c2a0af24ef6de2a 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/725] ARM: dts: bcm283x: Set downshift-after for Pi 3B+
+Subject: [PATCH 220/773] 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 398295a34e3ee4b8817f868b4b81ae0462e6abe0 Mon Sep 17 00:00:00 2001
+From f949d268f735033111e74d58046e6430e574543e 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/725] BCM270X_DT: Add new Ethernet DT parameters
+Subject: [PATCH 221/773] 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 cb156dbcbd7fd138d0abb96855e2e472cb1ba3d3 Mon Sep 17 00:00:00 2001
+From e729d667463c4c012b2178fc793f03103ed7fadd 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/725] BCM270X_DT: Mark eth_downshift_after as an integer
+Subject: [PATCH 222/773] BCM270X_DT: Mark eth_downshift_after as an integer
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From e0cb60557d0127240de57893416068d60e90757a Mon Sep 17 00:00:00 2001
+From 5fc2a0f0fe8bb75b4c3d87e93049bba96320b1ce 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/725] dwc-otg: FIQ: Fix "bad mode in data abort handler"
+Subject: [PATCH 223/773] 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 06a217704d5b7acc8680b9ff4cb837f8dd7b4b5d Mon Sep 17 00:00:00 2001
+From 20a8ea04c17931e9acbf3a6ced1a4eab10903df0 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Fri, 30 Nov 2018 18:55:23 +0000
-Subject: [PATCH 224/725] lirc-rpi: Remove in favour of gpio-ir
+Subject: [PATCH 224/773] lirc-rpi: Remove in favour of gpio-ir
---
arch/arm/boot/dts/overlays/Makefile | 1 -
-From 9e280b87eaf77735f0b9d1fd56a72ec11e7230cb Mon Sep 17 00:00:00 2001
+From 847b20775351c9d1f0a5758415dc09e96fa5280b 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/725] media: bcm2835-unicam: Pass through the colorspace on
+Subject: [PATCH 225/773] media: bcm2835-unicam: Pass through the colorspace on
try_fmt
The current colorspace was always returned from try_fmt for no
-From 88ebe04c5b8feff596e3d373eb3d779fa13ff8c9 Mon Sep 17 00:00:00 2001
+From 9f831f53fc87c0e55106843dffb24f19047b42a5 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/725] media: tc358743: Return an appropriate colorspace
+Subject: [PATCH 226/773] media: tc358743: Return an appropriate colorspace
from tc358743_set_fmt
When calling tc358743_set_fmt, the code was calling tc358743_get_fmt
-From d248e54f2c13facdde31e13ab8c3acb26f63a8cd Mon Sep 17 00:00:00 2001
+From aca8d0ffa1ee9d051565f7baf2ac93a973b7407b 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/725] staging: bcm2835-camera: fix module autoloading
+Subject: [PATCH 227/773] staging: bcm2835-camera: fix module autoloading
In order to make the module bcm2835-camera load automatically, we need to
add a module alias.
-From 87c91dbd458eb312449a9b300e13d7ca43ba9105 Mon Sep 17 00:00:00 2001
+From 2aaaf77d47a01c8234824cefaa1704801610e55e 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/725] staging: bcm2835-camera: Move module info to the end
+Subject: [PATCH 228/773] 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 f5072609c720b1f50098d69e208113735f6b31fa Mon Sep 17 00:00:00 2001
+From e6e647594bc4c533fb0f5b8a1158dd3747ab4dea 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/725] staging: vchiq_arm: Fix platform device
+Subject: [PATCH 229/773] staging: vchiq_arm: Fix platform device
unregistration
In error case platform_device_register_data would return an ERR_PTR
-From c9adbf27cebcbd0bd144eb3c282f9d9115121526 Mon Sep 17 00:00:00 2001
+From 7a4ec3c9c597a39e3172eedb53565f00cc9f9241 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/725] staging: vchiq_arm: Fix camera device registration
+Subject: [PATCH 230/773] staging: vchiq_arm: Fix camera device registration
Since the camera driver isn't probed via DT, we need to properly setup DMA.
-From 9a52240005032514c0df20bbcbac6a2efdc1ba04 Mon Sep 17 00:00:00 2001
+From 8e02498b963eff87bda0a8a6d636b0b5740314fe 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/725] staging: vchiq_arm: Register a platform device for
+Subject: [PATCH 231/773] staging: vchiq_arm: Register a platform device for
the audio driver
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-From fb56caeb8f51fd08ff898bb679ac53bb5d9eb04e Mon Sep 17 00:00:00 2001
+From 020612c4edfda89d125e35abe8bb39a9d7e7cfd8 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/725] staging: bcm2835-audio: Enable compile test
+Subject: [PATCH 232/773] staging: bcm2835-audio: Enable compile test
Enable the compilation test for bcm2835-audio.
-From 57d6f481243f83f9ee1d62e0581d20d54005fb90 Mon Sep 17 00:00:00 2001
+From 3dbeaecc47252914318164e668e6cea6d01f774b 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/725] staging: bcm2835-audio: use module_platform_driver()
+Subject: [PATCH 233/773] staging: bcm2835-audio: use module_platform_driver()
macro
There is not much value behind this boilerplate, so use
-From c396f36045c306f7d928c487455d0450585bbf4e Mon Sep 17 00:00:00 2001
+From ff7a595f3acb9dad4674d740963715bba1cfe3de 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/725] staging: bcm2835-audio: Drop DT dependency
+Subject: [PATCH 234/773] 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 acf4b3ea7ec32069d8f3bd2b541ccb56ed1d0db5 Mon Sep 17 00:00:00 2001
+From ac66f1708e56da5463f0d5a88e03871deefa78f8 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/725] staging: bcm2835-camera: Provide more specific probe
+Subject: [PATCH 235/773] staging: bcm2835-camera: Provide more specific probe
error messages
Currently there is only a catch-all info message which print the
-From 362ea23e6c338b589e9fcc5e91e942b00c37a93b Mon Sep 17 00:00:00 2001
+From 670fb10630bb53df3e216254be027910c4c70d00 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/725] staging: bcm2835-camera: Add hint about possible
+Subject: [PATCH 236/773] 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 eb3b747986fbc23defe3942b91e24d3b0e007e3e Mon Sep 17 00:00:00 2001
+From 1508167e99ee5e5ee81030c4923aeafae48a6940 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/725] staging: bcm2835: Don't probe if no camera is
+Subject: [PATCH 237/773] 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 8c25a73d376b538692aa0128d57ff95c71479561 Mon Sep 17 00:00:00 2001
+From 71cbb943b8598f6f35f2d735e64608b60d61574f 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/725] staging: vchiq_arm: Improve error handling on loading
+Subject: [PATCH 238/773] staging: vchiq_arm: Improve error handling on loading
drivers
The handling of loading platform drivers requires checking IS_ERR
-From c668ed917ce492f9448245078e0a2e9f9f4eef3a Mon Sep 17 00:00:00 2001
+From 6e119efbf757d22045039272b5b6f2aaf9b706fa 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/725] staging: bcm2835-camera: Do not bulk receive from
+Subject: [PATCH 239/773] staging: bcm2835-camera: Do not bulk receive from
service thread
vchi_bulk_queue_receive will queue up to a default of 4
-From 873220449e4532c76d9ff86a75a482d1f78887db Mon Sep 17 00:00:00 2001
+From a89e41616615bc55db4946aad1b0ec0afeb71bb4 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/725] staging: bcm2835-camera: Ensure H264 header bytes get
+Subject: [PATCH 240/773] 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 4bbbd45f2e47c52b89cd77c6b7cd7b5075836f86 Mon Sep 17 00:00:00 2001
+From a1a5660a9bd4b3a36759f7c8d2b7d7340c480445 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/725] staging: bcm2835-camera: Correctly denote key frames
+Subject: [PATCH 241/773] staging: bcm2835-camera: Correctly denote key frames
in encoded data
Forward MMAL key frame flags to the V4L2 buffers.
-From 7270f7555eb3d8144844c110e10f20558e563de6 Mon Sep 17 00:00:00 2001
+From 6220cc477c124471c69563230760c59f57806a67 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/725] staging: bcm2835-camera: Return early on errors
+Subject: [PATCH 242/773] 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 fbea466b9b1178cf7b20607a3aa4ba7e98090e72 Mon Sep 17 00:00:00 2001
+From 388d6d769c8b2a93fe2e41cf381b3909a599865e 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/725] staging: bcm2835-camera: Remove dead email addresses
+Subject: [PATCH 243/773] 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 d6c47fa1f829bfd7d85829bf5b507ac5aafe1172 Mon Sep 17 00:00:00 2001
+From ca54d4eaacaf618ce0683ab7d980ca0b050bcefc 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/725] staging: bcm2835-camera: Fix comment style
+Subject: [PATCH 244/773] staging: bcm2835-camera: Fix comment style
violations.
Fix comment style violations in the header files.
-From 9b4f48ebb4bad6ed87d15874967d446327b0e65f Mon Sep 17 00:00:00 2001
+From 76690b81775284e9974b3355922d530af2e3e8d6 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/725] staging: bcm2835-camera: Fix spacing around operators
+Subject: [PATCH 245/773] 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 562d78a33091aaeb7c2f2a975a262438d4b6ff30 Mon Sep 17 00:00:00 2001
+From bc36f52a49bbb49b7770b57e32d2ec439a02aaa3 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/725] staging: bcm2835-camera: Reduce length of enum names
+Subject: [PATCH 246/773] 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 bec59483afd1d335649fd26c83e448aae6602e4a Mon Sep 17 00:00:00 2001
+From b466cb62aebf3b3821fe0607c7e0fa8ad8f9c00e 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/725] staging: bcm2835-camera: Fix multiple line
+Subject: [PATCH 247/773] staging: bcm2835-camera: Fix multiple line
dereference errors
Fix checkpatch errors "Avoid multiple line dereference"
-From c6fd809a48f06d2319c2391bafef0cf912fd9aa9 Mon Sep 17 00:00:00 2001
+From 287c52b9d059cce51ae88a55a1ea56d3971db405 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/725] staging: bcm2835-camera: Fix brace style issues.
+Subject: [PATCH 248/773] staging: bcm2835-camera: Fix brace style issues.
Fix mismatched or missing brace issues flagged by checkpatch.
-From cd004c183f3080cd6ec13337e63dded7a625bee4 Mon Sep 17 00:00:00 2001
+From 7bf6ffcf043b908cebd92d37b9f946d359f3793f 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/725] staging: bcm2835-camera: Fix missing lines between
+Subject: [PATCH 249/773] staging: bcm2835-camera: Fix missing lines between
items
Fix checkpatch errors for missing blank lines after variable
-From 1a1fb6d6e25aa33db217c5109aa6b440fedee415 Mon Sep 17 00:00:00 2001
+From e0f8234cf59fcdcafe93bdfcf10409e46eb3853f 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/725] staging: bcm2835-camera: Fix logical continuation
+Subject: [PATCH 250/773] staging: bcm2835-camera: Fix logical continuation
splits
Fix checkpatch errors for "Logical continuations should be
-From 636f4fad6c786c006e32c86b2f0d769c19177414 Mon Sep 17 00:00:00 2001
+From 591a1777d9be9229a90d40be00c204613c44524b 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/725] staging: bcm2835-camera: Fix open parenthesis
+Subject: [PATCH 251/773] staging: bcm2835-camera: Fix open parenthesis
alignment
Fix checkpatch "Alignment should match open parenthesis"
-From 12f0df5a07a37ebc3669784fe234e7a24d5867c3 Mon Sep 17 00:00:00 2001
+From 00ebef37248960b21f3f7586c22c009d22823d79 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
+Subject: [PATCH 252/773] staging: bcm2835-camera: Set sequence number
correctly
Set the sequence number in vb2_v4l2_buffer mainly so the
-From b29685ae7838b052cab7c7e26ff16e249edea294 Mon Sep 17 00:00:00 2001
+From fff5c759b7dbfc20ea446443586e5e0b1fad21cd 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
+Subject: [PATCH 253/773] staging: bcm2835-camera: Ensure timestamps never go
backwards.
There is an awkward situation with H264 header bytes. Currently
-From 4ae496b855e158789383247cde55591fe9ce4ceb Mon Sep 17 00:00:00 2001
+From 2da5f9c4a7e4cd332203bc5fc5febf91a51d7a5b 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
+Subject: [PATCH 254/773] staging: bcm2835-camera: Avoid unneeded internal
declaration warning
Clang warns:
-From 66becb1e25c43817c0f46e401557955d2f763d07 Mon Sep 17 00:00:00 2001
+From ea45d3cb3798a6714e060b66592b8869257aa4be 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
+Subject: [PATCH 255/773] staging: bcm2835-camera: Add multiple inclusion
protection to headers
mmal-common.h and mmal-msg.h didn't have the normal
-From dc86a3318afa6e113b3094380fdab904d900c90b Mon Sep 17 00:00:00 2001
+From 66e6361afa8f222603b55dee1f788bc94aaeb0c4 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
+Subject: [PATCH 256/773] staging: bcm2835-camera: Unify header inclusion
defines
Most of the headers use ifndef FOO_H, whilst mmal-parameters.h
-From 8f2e8949f937462d749e19b28a8208e286caf605 Mon Sep 17 00:00:00 2001
+From 4ee32ce3c2c062edd8e82c828f99ee908d3b27aa 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
+Subject: [PATCH 257/773] ARM: bcm2835_defconfig: Enable bcm2835-camera
Enables the V4L2 camera driver as a module.
-From d8c77a920cd800c375e1040f61ed15ec53219c1c Mon Sep 17 00:00:00 2001
+From 934b335cc97b8d29a93e669419fb23a58450a02d 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
+Subject: [PATCH 258/773] staging: bcm2835-camera: Fix alignment should match
open parenthesis
Fix up checkpatch "Alignment should match open parenthesis" errors
-From 816336e4081a5180c5b8524b2839e31f43a5ddf8 Mon Sep 17 00:00:00 2001
+From 7be4e14ed4e4538d1872f75a34f740bf3908f94f 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
+Subject: [PATCH 259/773] staging: bcm2835-camera: Fix multiple assignments
should be avoided
Clear checkpatch complaints of "multiple assignments should be avoided"
-From 2af5efec3dd9186edee08f14dffcee638955c909 Mon Sep 17 00:00:00 2001
+From 095ced68f4892a32981dbede20cee409d68d70cd 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
+Subject: [PATCH 260/773] staging: bcm2835-camera: Fix up all formatting in
mmal-paramters.h
Fixes up all checkpatch errors in mmal-parameters.h
-From 8d81b25c2bdc73f4d5d0985c0ec8e2d19f181768 Mon Sep 17 00:00:00 2001
+From 77643f0cb59ace8d5af28e9b220a03844ac98160 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
+Subject: [PATCH 261/773] staging: bcm2835-camera: Use enums for max value in
controls
Controls of type MMAL_CONTROL_TYPE_STD_MENU call v4l2_ctrl_new_std_menu
-From d0b848e7dde7eb67abd7cd14a2746ee09ffcfacb Mon Sep 17 00:00:00 2001
+From 9b101f513a73bf19ab73f89b16b5c76396b0998d 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
+Subject: [PATCH 262/773] staging: bcm2835-camera: Correct
V4L2_CID_COLORFX_CBCR behaviour
With V4L2_CID_COLORFX_CBCR calling ctrl_set_colfx it was incorrectly
-From f214d9ca66942c23a839e5ba54524fa39a8e08b1 Mon Sep 17 00:00:00 2001
+From 30e24c9adc26a51e03c22b98a4f75423b59f099b 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
+Subject: [PATCH 263/773] staging: bcm2835-camera: Remove/amend some obsolete
comments
Remove a todo which has been done.
-From 5ba9f10bdb359e285f9052484814ef61a7bcb276 Mon Sep 17 00:00:00 2001
+From 8ddad6ba50d786a57deb447c58aac5f57896be31 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
+Subject: [PATCH 264/773] staging: vc04_services: Split vchiq-mmal into a
module
In preparation for adding a video codec V4L2 module which also
-From 0be8a2fb0d0986f48ba31375f9c5a8620aa82edd Mon Sep 17 00:00:00 2001
+From e375e2bfbf4e76a2eab633576d13e7c957dc9dc1 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
+Subject: [PATCH 265/773] staging: mmal-vchiq: Allocate and free components as
required
The existing code assumed that there would only ever be 4 components,
-From 4938924a490f11659b8661bbe9a7f250c2a62237 Mon Sep 17 00:00:00 2001
+From 4c8770fc22d69cde5332c08abd2ff00eb50fb620 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
+Subject: [PATCH 266/773] staging: mmal-vchiq: Avoid use of bool in structures
Fixes up a checkpatch error "Avoid using bool structure members
because of possible alignment issues".
-From 609bd5dbe6c1f9cbe2fc50124e4e8a99e4a5042a Mon Sep 17 00:00:00 2001
+From a7631f38aa3d8d5e704a1fa4e8553c76798a71bd 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
+Subject: [PATCH 267/773] staging: mmal-vchiq: Make timeout a defined parameter
The timeout period for VPU communications is a useful thing
to extend when debugging.
-From 2fba609cb0baec25ef32de6ca340951e55aea464 Mon Sep 17 00:00:00 2001
+From a0fa0ee0757099fcbab15c668ec3b76e6dbffbaf 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
+Subject: [PATCH 268/773] staging: mmal-vchiq: Make a mmal_buf struct for
passing parameters
The callback from vchi_mmal to the client was growing lots of extra
-From 4b5f21b730dae52710a930a295c405044557e319 Mon Sep 17 00:00:00 2001
+From b209e9d2fd89a0d1861cb5f43539bb44eb0135ad 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.
+Subject: [PATCH 269/773] staging: mmal-vchiq: Add support for event callbacks.
(Preparation for the codec driver).
The codec uses the event mechanism to report things such as
-From c117bd7886d4d4079f33fb27b07ddd9add7310ee Mon Sep 17 00:00:00 2001
+From 234616b7ea364a57fa7d14b98b022d9633ca9e68 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
+Subject: [PATCH 270/773] staging: vc04_services: Support sending data to MMAL
ports
Add the ability to send data to ports. This only supports
-From e28f85053dc8de18935993bee4c9e5d9483787bd Mon Sep 17 00:00:00 2001
+From 552d912beb38481b95de0baef53420dd924208f6 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
+Subject: [PATCH 271/773] staging: vc04_services: Fixup vchiq-mmal include
ordering
There were dependencies on including the headers in the correct
-From 3b89c864ffec186fc4b3d31ddb575533e97225eb Mon Sep 17 00:00:00 2001
+From 6cb5de8099e37a517174aec29ceb77959ef53063 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
+Subject: [PATCH 272/773] 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
-From 0a36165c509c40a0551831efdbd2e957cba12f80 Mon Sep 17 00:00:00 2001
+From 0602ff25e62f5356e0e669b79c909a38c5fbc726 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
+Subject: [PATCH 273/773] 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
-From b821e47df883a3325062a68cbe1504bf62129fd6 Mon Sep 17 00:00:00 2001
+From 362a822169d4a589b803e270f1e2bf325d6f77a5 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
+Subject: [PATCH 274/773] 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
-From 46f9f09f99867b8211974aa2426bd68fe5ddb2d6 Mon Sep 17 00:00:00 2001
+From ac1d0e4556839b5297d05c2c2fc8eb7fd96fc263 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
+Subject: [PATCH 275/773] 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
-From e99f0a65a7159b35cd8dbf753d7e12b3331b0ca4 Mon Sep 17 00:00:00 2001
+From f9c24ad1d3a31cd0260b68238ebcaff6560dfed6 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
+Subject: [PATCH 276/773] 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
-From d5e800f52f43d8be95d78d4f95b0e5825bc5c4fb Mon Sep 17 00:00:00 2001
+From d3859630aa35969199fabcb084bd97719041158b 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
+Subject: [PATCH 277/773] staging: vchiq_arm: Register bcm2835-codec as a
platform driver
Following the same pattern as bcm2835-camera and bcm2835-audio,
-From 37dfe69edd33c0ed92770207f55f97ae3fa77607 Mon Sep 17 00:00:00 2001
+From 11938496dd97f6cb8a79a27df293e23036153939 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
+Subject: [PATCH 278/773] staging: vchiq_arm: Register vcsm-cma as a platform
driver
Following the same pattern as bcm2835-camera and bcm2835-audio,
-From 73ba32bae3b1afd20a8b9c116c620d47020f1720 Mon Sep 17 00:00:00 2001
+From 2c5b6f976b8cc7f221698c07a1030d130fe4d94a 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
+Subject: [PATCH 279/773] ARM: bcm2835_defconfig: Enable bcm2835-codec
Enables the V4L2 M2M codec driver as a module.
-From 1e3afe8e33c7ea7d2d64298d7800291766e17a15 Mon Sep 17 00:00:00 2001
+From 47b107c813bc93334a6bb2177dcdf09cd0fe1ce3 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.
+Subject: [PATCH 280/773] config: Add bcm2835-codec to Pi defconfigs.
Adds the V4L2 M2M codec driver to the config.
-From f82bc2707af229ea9b55c5b9ec7b489aad928232 Mon Sep 17 00:00:00 2001
+From 79f3433a85bb8128dca78bd05588a2a4b7a389ae 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
+Subject: [PATCH 281/773] staging: bcm2835-camera: Fix stride on RGB3/BGR3
formats
RGB3/BGR3 end up being 3 bytes per pixel, which meant that
-From b326f198daeac021ba83802b5e4502f8b22c1604 Mon Sep 17 00:00:00 2001
+From f3e2cc8a995e644fc5aca9a382643096084e6edc 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
+Subject: [PATCH 282/773] media: vb2: Allow reqbufs(0) with "in use" MMAP
buffers
Videobuf2 presently does not allow VIDIOC_REQBUFS to destroy outstanding
-From 710a31a64daa6929cf1940a7664609be39f442bc Mon Sep 17 00:00:00 2001
+From 875aab16fb495998df264f2d1c20ca68fcc27869 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
+Subject: [PATCH 283/773] tpm: Make SECURITYFS a weak dependency
commit 2f7d8dbb11287cbe9da6380ca14ed5d38c9ed91f upstream.
-From 63015baea6a1b3c2cb4c84d18efdbb43ff838028 Mon Sep 17 00:00:00 2001
+From 8e5de6a0565874b0531f4801bbb235444fad05d9 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
+Subject: [PATCH 284/773] 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
-From d3bff43fb2a1a1ba28c7770daa28565cfc2abd5e Mon Sep 17 00:00:00 2001
+From 77616ebc4f63c6cd87dc81dc7e75805823348012 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
+Subject: [PATCH 285/773] 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.
-From d77f611dd04cab8310455d93106c503cde89175e Mon Sep 17 00:00:00 2001
+From 46ebb05d9d2f6f86b1e4f85475fd9a461261010f 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
+Subject: [PATCH 286/773] Revert "staging: vchiq_arm: Register a platform
device for the audio driver"
This reverts commit ab59590ed562b89db51fe46cee5db96b9bc5abd8.
-From 3005ff34fcaea926cfc0c062c44f875568828ca7 Mon Sep 17 00:00:00 2001
+From 627e9a60b75ebc7876c655fca169250adaad3199 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"
+Subject: [PATCH 287/773] Revert "staging: bcm2835-audio: Drop DT dependency"
This reverts commit 933bc853bb764e476b0b0f633588f46d20f1f76a.
-From d3a8ba2147f62a30eba236976ce9ff6291ed9636 Mon Sep 17 00:00:00 2001
+From 545e6262c2218c2e6e440a08b72b58902646f654 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)
+Subject: [PATCH 288/773] ASoC: add driver for 3Dlab Nano soundcard (#2758)
Signed-off-by: GT <dev@3d-lab-av.com>
---
-From 2a7770becf1b2bf289836ea19dcc2f6744d7e413 Mon Sep 17 00:00:00 2001
+From f5ac89eb4657ce4e43aba739a671fc475ba7099f 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
+Subject: [PATCH 289/773] overlays: Update README with removal of lirc-rpi
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
-From c38a34a4f9465df9bfeff355772555efa0cd574b Mon Sep 17 00:00:00 2001
+From 57c6930510fd76201fddc352d6b96f5b8d1a8911 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
+Subject: [PATCH 290/773] staging: bcm2835-camera: Check the error for
REPEAT_SEQ_HEADER (#2782)
When handling for V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER was added
-From 92ac07c588df68c6cbc6c7965b679ba02d3c994b Mon Sep 17 00:00:00 2001
+From ca04bf45b9d33ebc574d2fc6af5cca9a9e4ffc89 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
+Subject: [PATCH 291/773] 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
-From bf6b1c361f3e01a5d7ce6ac2c6cb29ece28bf41a Mon Sep 17 00:00:00 2001
+From cecf301be9223fef4eda71e48a12ead310ec6e89 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
+Subject: [PATCH 292/773] firmware: raspberrypi: Report the fw variant during
probe
The driver already reported the firmware build date during probe.
-From 6a9b19e48f8503ca3ac0c4ef29f34d6b6a96dfac Mon Sep 17 00:00:00 2001
+From b51dda6c8cca5db35f73a2f8a26396699cdebf77 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
+Subject: [PATCH 293/773] firmware: raspberrypi: Report the fw git hash during
probe
The firmware can now report the git hash from which it was built
-From 848168d31f850623d2837c2cc154587189a5fd47 Mon Sep 17 00:00:00 2001
+From 8390a0a036f76ab39bc8f44b6f29dd690318b4bd 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
+Subject: [PATCH 294/773] arm64: dts: broadcom: Enable fixups for overlays
See: https://github.com/raspberrypi/linux/pull/2733
-From 699bca131fe01413d547e40a9e0d1db57b56e697 Mon Sep 17 00:00:00 2001
+From 379ca7f3ea4501b11779bc6dd6a350873b6ff948 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"
+Subject: [PATCH 295/773] 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
-From 4db271be1ee58a646878a17aa1007533897c095b Mon Sep 17 00:00:00 2001
+From 93c7046bc6203b275a898a256c6777b7414d195c 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
+Subject: [PATCH 296/773] dtoverlays: fe-pi-audio: fix sgtl5000 compatible
string
The compatible string was set to "fepi,sgtl5000", which worked for some
-From 4e11b14186707dfb88be344f227737eaf8adc608 Mon Sep 17 00:00:00 2001
+From f59fbca1296b4d60bc82b636f4b3c86f76efdcd9 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
+Subject: [PATCH 297/773] bcm2835_smi: re-add dereference to fix DMA transfers
---
drivers/misc/bcm2835_smi.c | 2 +-
-From a1bcab7b0deee8cf7d7bec2707cb50c269070d41 Mon Sep 17 00:00:00 2001
+From 48f22938df85dab9dd9fb036f755f8e95ad64fe9 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
+Subject: [PATCH 298/773] 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
-From 93952495f34e255ab4a3ce4631edd1520200f586 Mon Sep 17 00:00:00 2001
+From a261f0db876f556d520c312f4b7730601f6fea62 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
+Subject: [PATCH 299/773] ASoC: Add support for AudioSense-Pi add-on soundcard
AudioSense-Pi is a RPi HAT based on a TI's TLV320AIC32x4 stereo codec
-From 92192e0410d1c38596ca387c1680ff37847dcdc3 Mon Sep 17 00:00:00 2001
+From 67aa948d8c028ae67697a06cd8cc88e8626a9d5f 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
+Subject: [PATCH 300/773] BCM270X: Adding device tree support for AudioSense-Pi
add-on soundcard
Device tree overlay for AudioSense-Pi card.
-From f737d88ed6add8f6197bf1a26ace908b13a19d96 Mon Sep 17 00:00:00 2001
+From 60c0330e90ab343a36f65d91847a4271f90a45af 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
+Subject: [PATCH 301/773] configs: Add CONFIG_SND_AUDIOSENSE_PI=m
AudioSense-Pi add on soundcard configuration definitions
-From 3e9204fb393ff539359a1dd1da228d2817116f3a Mon Sep 17 00:00:00 2001
+From 15cf02160409bce25ba32acacf20f0afb30b5056 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
+Subject: [PATCH 302/773] configs: Add CONFIG_USB_TMC=m
Enable the Test & Measurement Class USB driver module.
-From d92f631ece6e1fca95462d8b0ffd3fee97be257a Mon Sep 17 00:00:00 2001
+From 89ddc12e60ce7da90c78d6710eca1904c8d48ad9 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
+Subject: [PATCH 303/773] 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.
-From 0384e9ec7b5a3d8e6e2162ce8adf019d0f5c94cf Mon Sep 17 00:00:00 2001
+From ba152d9f0ed0b2d0cded255618a7d0b7150ac433 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
+Subject: [PATCH 304/773] dwc_otg: fix bug with port_addr assignment for
single-TT hubs
See https://github.com/raspberrypi/linux/issues/2734
-From e775807c64a610be5f2fcb82e152109d9b9d30f8 Mon Sep 17 00:00:00 2001
+From 4e858578c2c96d5202d5eb73cf6cce4921f1edf6 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
+Subject: [PATCH 305/773] configs: Add CONFIG_USB_UAS=m
Enable support for USB-attached-SCSI devicess.
-From a4bda3453c292c7b75ca0e3163daa7879d5fa952 Mon Sep 17 00:00:00 2001
+From 4431d86306afc081e04532564614f3be7eb6094c 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)
+Subject: [PATCH 306/773] Added driver for the HiFiBerry DAC+ ADC (#2694)
Signed-off-by: Daniel Matuschek <daniel@hifiberry.com>
---
-From 01a031fa350f9fa197451a3b4aed04c43c46c50e Mon Sep 17 00:00:00 2001
+From 50edca9454fa2c35a2c3537a024a587addb4e823 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
+Subject: [PATCH 307/773] Revert "pwm: Set class for exported channels in
sysfs"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
-From 30759f3a1d9090c99769dc76964ea414b5129d85 Mon Sep 17 00:00:00 2001
+From 8c2925d1981738ba8d8db4cbbb1052dfa2d42766 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
+Subject: [PATCH 308/773] pwm: Send a uevent on the pwmchip device upon channel
sysfs (un)export
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
--- /dev/null
+From 120af8681859ee0b4d03ea9bd498075e21e6332b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 21 Jan 2019 21:17:27 +0000
+Subject: [PATCH 309/773] 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 78d42658217a0301694564eb02d01e69ce326a32 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 21 Jan 2019 12:19:57 +0000
+Subject: [PATCH 310/773] 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 a9f91d72dd27a97dd7a8547e52c2ee2ab945a26c Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 21 Jan 2019 12:23:55 +0000
+Subject: [PATCH 311/773] 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 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 bd3e02b4297016f8d126f8caafdf7c50f7e27c44 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 312/773] 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 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 92f132ebff6c46e5a5cb5af689988c3a6e7725c8 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 313/773] 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 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 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 d8ef81fc96db5d2e11d4476435f5eb45ad7a2c66 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 314/773] 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 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 73ee9ac76651e7e52f23e0f69c2944918e659fe7 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 315/773] 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 1cbfa86f148c2ab519b04ce9a3e3b21a9cb51f2e 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 316/773] 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 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 68d963b8d82f7fc5dcae235f3efb5151ea2ce258 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 317/773] 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 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 13a47248597d82510f9a3ca2d17ff1214ad5216a 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 318/773] 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 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 bbfe2b3119cc3ee3656f059c17dc24260d0c54bf 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 319/773] 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 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 a211e48e8dfe5d53f09f56d7c02519c3b18ec3bf Mon Sep 17 00:00:00 2001
+From: Serge Schneider <serge@raspberrypi.org>
+Date: Tue, 29 Jan 2019 12:05:49 +0000
+Subject: [PATCH 320/773] 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 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 35f14d8d7ca31484d79e6ad8ec2f6ad1d15531f2 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 321/773] 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 faacf8c01e29e8d1d8e8e6dae7c2f642c19a4049 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 322/773] 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 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 272b4a8b54d9aa54b889839f391062d167976d6c 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 323/773] 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 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 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 1b288333b646bc496ffd12d1319bed07665fadd0 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 324/773] 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 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 14dccf96c00c9c1cd18843e5a4bb37e12eebe01e 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 325/773] 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 310cdebd4b630b0b618595a3fd393ca8a80311d1 Mon Sep 17 00:00:00 2001
+From: Matt Flax <flatmax@flatmax.org>
+Date: Tue, 29 Jan 2019 14:56:03 +1100
+Subject: [PATCH 326/773] 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 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 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 8894fd21a50523e30ce4bb478d54f2bd47098785 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 327/773] 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 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 eecc64a7461ec622c1a52b95996475e05aa0805a 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 328/773] 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 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 c0414e76f810112e8aa12935f898048e42755309 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 329/773] 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 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 95ec26bfa0bb7a795f60f6689e959ed1f845c329 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 330/773] 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 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 f9b68cece60f58318b350772b732ddac81c6f0d4 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 331/773] 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 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 8c765494f608d80c51ab19838ab428b5984ca684 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 332/773] 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 f64a82df270c494b5857508d7e5287b1f3fee3e6 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 20 Jul 2018 22:03:41 +0100
+Subject: [PATCH 333/773] 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 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 d3f3bb6aa32c371b207db913d037775d3c07e872 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 20 Jul 2018 22:08:05 +0100
+Subject: [PATCH 334/773] 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 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 6890e531417c6f03b9b65279d354622b40d0f685 Mon Sep 17 00:00:00 2001
+From: Dimitris Papavasiliou <dpapavas@gmail.com>
+Date: Sat, 24 Nov 2018 22:05:42 +0200
+Subject: [PATCH 335/773] 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 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 47b24be0bda7091c1caa52e2d376408d024cd951 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 336/773] 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 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 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 58c69efc71cd89aa187b333df93bf0d59cb2f18c 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 337/773] 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 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 1f3f31854a8f073ca97633192179055770d6bb88 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 338/773] 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 40002e5f988a815a9bdfc20a015b64ebed0b7383 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 339/773] 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 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 6afaa5b0979652ba9cf1f6fc312089ac99b29264 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 340/773] 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 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 214e70c418ffa33753c5e4cf9b9b79a45c5c7b10 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 341/773] 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 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 089f8e668fc58953362a62e2031da7c194d96d31 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 342/773] 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 4dc2f642e3be9005b29a1ed5b0d0418edda77264 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 343/773] 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 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 a37d181c1f7a83fe929a3ce05f048b47bc309ac5 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 344/773] 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 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 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 d9dc83cdca70487efcd71e7760388fa8952f7d88 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 345/773] 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 5ea3b3e2a280f4aa6191bd79a8c606b3d7ca78d6 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 346/773] 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 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 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 1b58612a44597525052617f2cb23e873ad433d2f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 7 Feb 2019 18:16:25 +0000
+Subject: [PATCH 347/773] 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 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 0ea3707233c090b6978f7cd941a75d5a3d1eacc8 Mon Sep 17 00:00:00 2001
+From: Zahari Petkov <zahari@balena.io>
+Date: Fri, 8 Feb 2019 13:03:38 +0200
+Subject: [PATCH 348/773] 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 4fba1540bd76c356a0c9930f5cccba019e6be3ad Mon Sep 17 00:00:00 2001
+From: Zahari Petkov <zahari@balena.io>
+Date: Fri, 8 Feb 2019 13:33:47 +0200
+Subject: [PATCH 349/773] 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 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 206ac51ef76b535c3f37690189000d0a34b38282 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 18 Feb 2019 15:43:30 +0000
+Subject: [PATCH 350/773] 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 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 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 a38d0527a01e53499a5c54b49c2e56b518b75b48 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 351/773] 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 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 c4e9410fc4e06792f4b895b9bfbd70f5e842c7de 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 352/773] 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 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 7b6ac66bdaa9740352437ee94b8bb63f579a13bd 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 353/773] 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 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 2e3718da526ecc343731733439626a16be7518ac 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 354/773] 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 c6cf0e080fcd24679c1ca26eb26896893f7f306b 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 355/773] 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 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 0b3a511aa20437ad3d4c0dc00f7b95dcb161d2d9 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 356/773] 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 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 6e89f0ac95adca46daa52324681edf43a2f6f613 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 357/773] 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 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 84d340e55471df729fb0c7b3cf37d160a03f8e67 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 358/773] 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 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 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 bfdc0b6e57d8fe0cbfd141cf13c2443506450ff8 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 359/773] 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 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 c301c3be5aefbb9fc6fb9070157d24105785815b 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 360/773] 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 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 0cff1c25107689ee36e658b1bb85d83b0481ef17 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 361/773] 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 93281e638545955769ee1706e510624b7d6073c4 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 5 Feb 2018 18:53:18 +0000
+Subject: [PATCH 362/773] 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 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 8bf7bcb1cc1bb6e382445c50094f2fba2d0afcef Mon Sep 17 00:00:00 2001
+From: Giedrius <giedrius@blokas.io>
+Date: Wed, 27 Feb 2019 14:27:28 +0000
+Subject: [PATCH 363/773] 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 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 512d3de73d6d05e683aef2f7626a75f01e5e0bab Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 27 Feb 2019 20:08:48 +0000
+Subject: [PATCH 364/773] 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 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 5feb58606710065f2032817176560cdec72f1f40 Mon Sep 17 00:00:00 2001
+From: Jaikumar <jaikumar@cem-solutions.net>
+Date: Thu, 7 Jun 2018 21:22:45 +0530
+Subject: [PATCH 365/773] 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 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 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 818e8f77d76efd684b2ea5796d3866fdd4f0e768 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 5 Mar 2019 09:51:22 +0000
+Subject: [PATCH 366/773] 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 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 ea9d3e8b98633b3d449ec0a786be6a95c940b027 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 367/773] 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 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 5e4bc7e0e9ea34cabc14c6028fe2eaf7b8295999 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 368/773] 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 5cf95fae9985aa80ba36a47027a254a29fa92372 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 369/773] 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 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 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 614592644f6c107d0f8cb6145d95437d53ac8dff 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 370/773] 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 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 dfc0c4f36a4ff2707a2c00117050f6465f94acb3 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 371/773] 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 e861be56136fd16394248f501bd3fbb327e40d1a 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 372/773] 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 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 9c63a140609809ff686622090893ba69e3929019 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 373/773] 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 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 367031afc970012f096292691d9509382118fb02 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 374/773] 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 1e49e92dc627e30dc329ee856a81d90d454bab03 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 375/773] 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 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 0382cc0391c16a76fdf6f1e53c17a0704648c6fb 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 376/773] 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 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 d0a4aa37997f5532159dc5f506b4bd1d533d1991 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 377/773] 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 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 7d2089d213ac26b66585c3573302ddc95ce06dc1 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 378/773] 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 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 5eb927e238d953d7b471d4c81cb6ba0303dad02c Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 13 Mar 2019 14:19:11 +0000
+Subject: [PATCH 379/773] 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 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 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 357aeb8b38198e59a5d62f966e945b6c08ae43e7 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 380/773] 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 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 bf926c922d5cca1a0d2eacfea0c4803d3debc94a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 22 Mar 2019 16:44:47 +0000
+Subject: [PATCH 381/773] 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 588ba94f9647b91ac205f296129548c5eb1265c6 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Sun, 24 Mar 2019 20:54:25 +0000
+Subject: [PATCH 382/773] 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 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 227e011d31adee13c727dd38f7e47895b3a8c49b Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Wed, 16 Jan 2019 12:22:32 +0100
+Subject: [PATCH 383/773] 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 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 dcf1a5feb6095c5aca75cc18330680778e59b517 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Sat, 19 Jan 2019 08:06:48 +0100
+Subject: [PATCH 384/773] 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 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 931465226104cb10935af8f66fe6fdd29d898ec9 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Sat, 19 Jan 2019 09:00:26 +0100
+Subject: [PATCH 385/773] 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 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 b511e73e01d03df0ee7fffeae26b8db6d138c82e Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Tue, 22 Jan 2019 12:29:45 +0100
+Subject: [PATCH 386/773] 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 42c70eb8066b0e91cd184a5f166c391f82e3f4b5 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Sat, 19 Jan 2019 08:42:40 +0100
+Subject: [PATCH 387/773] 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 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 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 0cdf702e5ea015c034fa222da1647baf0b0c42f3 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 25 Mar 2019 17:54:05 +0000
+Subject: [PATCH 388/773] 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 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 255761d610f7ef977196da27f13d702743cd99b7 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 25 Mar 2019 18:03:48 +0000
+Subject: [PATCH 389/773] 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 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 53986e21f8d6687c6266ec0daaa18c34630c5f98 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 390/773] 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 faeaf9544c1803c77b6bd22b850360d15eba2eb9 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 391/773] 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 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 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 4a7501a80598c159be341d0b52011882556b077e 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 392/773] 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 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 855040143a256199d362f32d6de071ef5c801314 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 393/773] 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 824810872428425fbf3e3e5d0b45e20ab8937b32 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 394/773] 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 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 9b996b5adaaff82f7752cc65dbcf5864277f22bf Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 28 Mar 2019 13:13:52 +0000
+Subject: [PATCH 395/773] 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 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 a196d4df496546cf0e521c6aedf7e37025dde785 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 28 Mar 2019 13:26:59 +0000
+Subject: [PATCH 396/773] 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 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 6401f3831443dc2eeb588f8d08e7513298dd2c52 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 397/773] 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 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 27053ee9edee96b33fd8a6ff0311fa9ad17bb5cc Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Mon, 18 Mar 2019 20:37:44 -0700
+Subject: [PATCH 398/773] 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 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 85c1b0992bb403298c7fe36a2d96cc9b4d888ec1 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 20 Mar 2019 19:38:44 -0700
+Subject: [PATCH 399/773] 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 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 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 5cf3feb4772646be2eac9f9e9bd730ede0be7568 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:45 -0700
+Subject: [PATCH 400/773] 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 ea2e656f039961331db8e83322d461f56feae325 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:46 -0700
+Subject: [PATCH 401/773] 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 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 e9c691396d5e78be3d71090924d42a19b4959ac2 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:47 -0700
+Subject: [PATCH 402/773] 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 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 e8a7d56b23d0caa7fbe0d6304fb73431229b2b9d Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:48 -0700
+Subject: [PATCH 403/773] 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 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 0d5aca18bd8a4ad3fa82f1f7f82cc0b95575a492 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:49 -0700
+Subject: [PATCH 404/773] 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 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 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 fec4f0b76b1641917c9d2f60169194a00aee5916 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:50 -0700
+Subject: [PATCH 405/773] 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 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 bb3ce792b7f1064d7b9326714fc9ad3eb399fe2f Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:51 -0700
+Subject: [PATCH 406/773] 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 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 3dddc847d2889d096879b81480850ae4de1f3efe Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:52 -0700
+Subject: [PATCH 407/773] 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 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 061b34c3cce2b8d1d2039119137b943bf1934429 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:53 -0700
+Subject: [PATCH 408/773] 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 88410f24832eca9a9b7a870601f15226ced06b45 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Thu, 21 Mar 2019 17:58:54 -0700
+Subject: [PATCH 409/773] 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 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 f581673c8896d351653f85185ef27293d1359b44 Mon Sep 17 00:00:00 2001
+From: Mark Brown <broonie@kernel.org>
+Date: Tue, 26 Mar 2019 13:10:13 +0000
+Subject: [PATCH 410/773] 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 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 0cf49c5a3e560901a98562abb00f8402f1ac3a14 Mon Sep 17 00:00:00 2001
+From: FERHAT Nicolas <contact@audiophonics.fr>
+Date: Fri, 5 Apr 2019 13:06:42 +0100
+Subject: [PATCH 411/773] 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 e4e57bd8465edf59a02b8e2841c700dd7f454176 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 3 Apr 2019 21:17:15 -0700
+Subject: [PATCH 412/773] 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 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 c9508a7de9cac03d8fc482af363d886b17931e3d Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 3 Apr 2019 21:17:16 -0700
+Subject: [PATCH 413/773] 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 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 dd1eb4f52da71e7f8d44f96445129864ce25ec2a Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 3 Apr 2019 21:01:54 -0700
+Subject: [PATCH 414/773] 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 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 a4e379a25c1f3a132e7508e59e44e2d58b322498 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Wed, 3 Apr 2019 21:01:55 -0700
+Subject: [PATCH 415/773] 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 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 d6731331f00859fd9b172db1ae71eb76e4239c8c Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Sun, 17 Mar 2019 16:48:36 -0700
+Subject: [PATCH 416/773] 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 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 4bdf5b3f1aca778bfce24ffebf8d00db24321e36 Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Mon, 8 Apr 2019 12:45:23 +0100
+Subject: [PATCH 417/773] 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 7b8839dc268225574109471283cd7c38618b68f2 Mon Sep 17 00:00:00 2001
+From: Samuel Hsu <hsu@distec.de>
+Date: Mon, 8 Apr 2019 16:42:17 +0200
+Subject: [PATCH 418/773] 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 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 f1676cc3d7dbeb175906cd1aafe7a39bbe08ce8a Mon Sep 17 00:00:00 2001
+From: Samuel Hsu <hsu@distec.de>
+Date: Mon, 8 Apr 2019 16:49:51 +0200
+Subject: [PATCH 419/773] 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 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 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 14f64762184b51f575da05b5731e0a32a048c6bc Mon Sep 17 00:00:00 2001
+From: Samuel Hsu <hsu@distec.de>
+Date: Mon, 8 Apr 2019 16:54:34 +0200
+Subject: [PATCH 420/773] 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 63cbc9d36724e5f939f2003bdf73739cbfbac724 Mon Sep 17 00:00:00 2001
+From: Samuel Hsu <hsu@distec.de>
+Date: Mon, 8 Apr 2019 17:06:44 +0200
+Subject: [PATCH 421/773] 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 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 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 ae80b2795f6084ec8daa5840b3ea5dc70ffb0d3b Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Tue, 9 Apr 2019 16:40:48 +0100
+Subject: [PATCH 422/773] 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 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 e3273d6c63ea4956b2ee428be1cf7cae9b848614 Mon Sep 17 00:00:00 2001
+From: Phil Howard <phil@gadgetoid.com>
+Date: Fri, 29 Mar 2019 10:53:14 +0000
+Subject: [PATCH 423/773] 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 b31ebf3a7ef8fb645ea199b90d0c568b85ee558f Mon Sep 17 00:00:00 2001
+From: Phil Howard <phil@gadgetoid.com>
+Date: Fri, 29 Mar 2019 10:57:07 +0000
+Subject: [PATCH 424/773] 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 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 918ce6082732828dd525c0a6a48e5232dadd4019 Mon Sep 17 00:00:00 2001
+From: Phil Howard <phil@gadgetoid.com>
+Date: Fri, 29 Mar 2019 10:59:55 +0000
+Subject: [PATCH 425/773] 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 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 a1e9cfcbdb2182c6b9ee86403f2000907ff56d26 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 426/773] 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 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 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 b0acc464355ae39bff22f99cf8b63636ce246da4 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 21 Mar 2019 11:19:46 +0000
+Subject: [PATCH 427/773] 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 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 058236ea822406c145b76174c8833e46a6b0a4a7 Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Wed, 24 Apr 2019 14:25:09 +0100
+Subject: [PATCH 428/773] 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
+@@ -5334,8 +5334,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
+@@ -5376,12 +5374,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 =
+@@ -5773,28 +5765,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 437f429eabf773fe5e50d13b98b341eb6969b349 Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Wed, 24 Apr 2019 14:25:41 +0100
+Subject: [PATCH 429/773] 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 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
-@@ -5334,8 +5334,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
-@@ -5376,12 +5374,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 =
-@@ -5773,28 +5765,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 02b423ddf63dfd3c34619923b4052f120f5d0807 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Mon, 29 Apr 2019 19:35:33 +0200
+Subject: [PATCH 430/773] 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 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 9ce243fb88cc752a4a807e19277f0203376a2796 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Mon, 29 Apr 2019 19:28:51 +0200
+Subject: [PATCH 431/773] 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 2b37269c2b8987fd4cb548c63bff824e73b35c99 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 29 Apr 2019 19:16:14 +0100
+Subject: [PATCH 432/773] 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 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 008aadaeb36373557d79b0e092cd54016230231b Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 29 Apr 2019 19:16:15 +0100
+Subject: [PATCH 433/773] 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 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 77f4c32bb54987b8bf1682fea6ccf40e1da5a5a2 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 29 Apr 2019 19:16:16 +0100
+Subject: [PATCH 434/773] 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 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 6d623d81da84bf401e64bc0be1fc0c7db67d3ce0 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:30 +0200
+Subject: [PATCH 435/773] 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 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 b6225a1d58d920b8c013fbc9b8e6c8674e6cfdb6 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:31 +0200
+Subject: [PATCH 436/773] 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 c71543e34229b46f05ecbe83a1202a08baed8f74 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:32 +0200
+Subject: [PATCH 437/773] 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 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 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 cbe5f48a35763e4414305be5e607a3cc327230e9 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:33 +0200
+Subject: [PATCH 438/773] 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 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 9d218cda96bad69fb3281c67b225cf1a312ede37 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:34 +0200
+Subject: [PATCH 439/773] 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 481546fda1bf4b63b668d50211f982ac06fda073 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:35 +0200
+Subject: [PATCH 440/773] 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 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 e09b2224769855077ccd9a16efb5949b6520b6ee Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:36 +0200
+Subject: [PATCH 441/773] 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 4629c2d6374924f28ee9e23eaa0b44215ffc7a5c Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:37 +0200
+Subject: [PATCH 442/773] 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 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 79b036b042717037d23760dd94ba87ee6ddd5a33 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:38 +0200
+Subject: [PATCH 443/773] 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 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 75d41a9194b0f67725d47a767815ea917c7a2016 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:39 +0200
+Subject: [PATCH 444/773] 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 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 41bf796b8c7b904b293c51331096ee4b7123c344 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:40 +0200
+Subject: [PATCH 445/773] 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 0e087050b07f96f05537f986918f265dce8ce5d4 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:41 +0200
+Subject: [PATCH 446/773] 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 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 59aebb4b935a7f4a7aaf17e91746190ce50460aa Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:42 +0200
+Subject: [PATCH 447/773] 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 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 444b043248d5dc8949cc3ccea92ce1a1ae281401 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:43 +0200
+Subject: [PATCH 448/773] 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 f28e4fbf66332a2f9f14b43191ef3f208eff2bd2 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:44 +0200
+Subject: [PATCH 449/773] 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 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 5d5721bc8f85b12e9064655020761edba10ba9ce Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:45 +0200
+Subject: [PATCH 450/773] 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 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 4f25670ed874ada94086d930e3d9349b359fe089 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:46 +0200
+Subject: [PATCH 451/773] 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 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 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 367a95c4865c984877834ac5f36e103c9153d236 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:47 +0200
+Subject: [PATCH 452/773] 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 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 a7bf741a30699a4144415cb33c249749da047402 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:48 +0200
+Subject: [PATCH 453/773] 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 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 911255bc6a42edd994f4bd5423af4a37ea6dc014 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:49 +0200
+Subject: [PATCH 454/773] 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 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 8b93d558dd51a625eef6d79472831768bd20eedd Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:50 +0200
+Subject: [PATCH 455/773] 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 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 eae9d25dcb7710311db48f0e0a4d2f522c69c693 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:51 +0200
+Subject: [PATCH 456/773] 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 609c0f2acb7e19cac5729cd50a5d20c1f052f81e Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:52 +0200
+Subject: [PATCH 457/773] 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 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 5e3435522b2244bd41f6450c1833f4f6b7c5d88f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:53 +0200
+Subject: [PATCH 458/773] 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 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 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 94f44e5e684f35345de973b7df022ce1d4d124fa Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:54 +0200
+Subject: [PATCH 459/773] 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 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 f7b0fa3d8c5bdb4f7271dd291ef8d9f3636633a6 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:55 +0200
+Subject: [PATCH 460/773] 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 45b83d5330c46aa1ce7263efba96cf14817e3b5f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:56 +0200
+Subject: [PATCH 461/773] 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 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 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 7dcdb52543c4d3d1a203b563d02ac9b1e2fe145a Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:57 +0200
+Subject: [PATCH 462/773] 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 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 c69fbfe4f9dde3389f982a41a2d66db1c49f722d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 4 Sep 2018 17:58:58 +0200
+Subject: [PATCH 463/773] 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 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 ddd93720464f96d17d04cd4327276a24b8f92958 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 464/773] 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 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 85b86a93d240f28c10bb0dced805e1921ba3200c 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 465/773] 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 dd4a89f63d646fb22aa92d84a5f56b0afed4490b 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 466/773] 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 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 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 6a13b16a222f0bcf5477eaed697860f3d9f25bbd 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 467/773] 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 31408d8f63e0ab590b209e9896482819c42c1b8d 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 468/773] 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 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 d51fefa5d289a940bf2632d6d76a6a1acb8fe0f3 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 469/773] 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 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 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 7a5c01bf9a68549e4224dcaa4fe3e1a32f6540ac 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 470/773] 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 15bf3de940ef7ea2e3ec4fde51f530b5f2b9b516 Mon Sep 17 00:00:00 2001
+From: Mike Brady <mikebrady@eircom.net>
+Date: Mon, 22 Oct 2018 20:17:08 +0100
+Subject: [PATCH 471/773] 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 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 64132a3d49d2458d946499bc236d54c34a370a83 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 472/773] 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 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 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 5a4fdee47fc5368c1be2184a0bb1069773b58a74 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 473/773] 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 9031c962b5f4ad439441eb9d82633c469ff1678e 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 474/773] 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 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 bd76661620e6389823baf3a64d47996923133604 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 475/773] 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 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 a22984710359546d84ab80232856b21ed9843925 Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Wed, 1 May 2019 15:00:05 +0100
+Subject: [PATCH 476/773] 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 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 b91f6229cdbf53e27cc2ceb7539208c31aacae84 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Wed, 1 May 2019 14:23:39 +0100
+Subject: [PATCH 477/773] 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 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 d9956ad9c4c17a8221c65689cb0e634cdcea1d7c 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 478/773] 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 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 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 3ba615169e1f9866f70c2967a664f0fac36c5699 Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Wed, 1 May 2019 17:04:32 +0100
+Subject: [PATCH 479/773] 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 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 60970bd8d01c0557d1bdd2a9af322b6033c6a0c0 Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Thu, 2 May 2019 11:53:45 +0100
+Subject: [PATCH 480/773] 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 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 142f63ac7af5a318bcba7ff6ebac94a52ddf53c2 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 481/773] 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 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 3543d5bc1e7ea7df27daa91353001fa401581532 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 482/773] 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 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 e8ebe52344c73c8edad490c0ff601a763893c276 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 483/773] 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 9e95568ba995f644f6523689a07ca49867b50693 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 2 May 2019 22:14:34 +0100
+Subject: [PATCH 484/773] 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 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 87e3efd10789a1dadcf0058409f9422ae1b2f5c7 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 485/773] 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 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 8513e54e9ed5d448fb11cc10e346962a2418d822 Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Sun, 5 May 2019 21:07:12 +0100
+Subject: [PATCH 486/773] 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 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 93fc53b9daca722f049a8eeef75c2300de724f09 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 487/773] 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 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 81a3b647e09fdd8258bf24479fd5bc8ce99b861e 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 488/773] 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 04480e9068abb6ce7f0bf7ee73c5a00cc854a04d 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 489/773] 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 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 d7653f82018e4621c7ec046b0f40e0c7a316bbce Mon Sep 17 00:00:00 2001
+From: IQaudIO <gordon@iqaudio.com>
+Date: Mon, 13 May 2019 21:53:05 +0100
+Subject: [PATCH 490/773] 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 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 d7126c242190ab444fe69a0e323700887c5a5a56 Mon Sep 17 00:00:00 2001
+From: P33M <p33m@github.com>
+Date: Tue, 14 May 2019 14:55:19 +0100
+Subject: [PATCH 491/773] 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 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 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 d6fe3387911dea5b07c0d30874f96c38942e2926 Mon Sep 17 00:00:00 2001
+From: Henrique Gontijo <hgontijo@guidewire.com>
+Date: Sun, 12 May 2019 17:11:02 -0700
+Subject: [PATCH 492/773] 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 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 b2cedbb455090a3ffce788a74a5290fa193782db 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 493/773] 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 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 2310c816beacba84d544e0ffc54b51ecba7ca853 Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Mon, 4 Mar 2019 12:23:36 +0100
+Subject: [PATCH 494/773] 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 298b6f8174623c1893ac9a4d93bc60b3ca151c76 Mon Sep 17 00:00:00 2001
+From: Klaus Schulz <klsschlz@gmail.com>
+Date: Thu, 16 May 2019 13:35:32 +0200
+Subject: [PATCH 495/773] 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 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 a75cd9664fb5a0a7e691ccd3643fc8016bb4dc55 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 496/773] 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 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 013e2879b14dc488b5e81c39f4aa96461a69161f Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Tue, 21 May 2019 15:17:33 +0100
+Subject: [PATCH 497/773] .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 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 435aff3962d16737376bdfb2d6f71b33802011c9 Mon Sep 17 00:00:00 2001
+From: Marcel Holtmann <marcel@holtmann.org>
+Date: Wed, 22 May 2019 09:05:40 +0200
+Subject: [PATCH 498/773] 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 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 f88e6077d4043c58da9a57f850bca89d594a84d3 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 7 May 2019 17:23:41 +0100
+Subject: [PATCH 499/773] 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 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 3054d166c457fb4782075068d5e72bd6db4e96f2 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 7 May 2019 14:27:35 +0100
+Subject: [PATCH 500/773] 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 444d27bbcc7017061a2a49c5dbc5865d34fc7a65 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 7 May 2019 10:06:04 +0100
+Subject: [PATCH 501/773] 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 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 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 afef44707505b1f8ab6e3ca026dfdc890b485c8e Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 14 May 2019 13:33:05 +0100
+Subject: [PATCH 502/773] 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 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 1c25162b7357dcdcf2370e9c2ec37ed8b2c9feb8 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 22 May 2019 12:58:47 +0100
+Subject: [PATCH 503/773] 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 e577bda00e07473910a871108d154e7a5f83d648 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 7 May 2019 14:29:38 +0100
+Subject: [PATCH 504/773] 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 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 d6feb60e7835a4f5dd0f29b636c7a39cea58abc6 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 8 May 2019 10:08:31 +0100
+Subject: [PATCH 505/773] 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 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 66fc53c0825adeabc6c5bb5cd9fc7ce172c60549 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 22 May 2019 13:29:56 +0100
+Subject: [PATCH 506/773] 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 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 4d0427080ea4dc06a4a068bb246bbf960aedc792 Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Thu, 16 May 2019 14:39:21 +0200
+Subject: [PATCH 507/773] 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 3f5b0f5bbd6bcc236999b79389dd30c728a3a047 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 28 May 2019 16:36:04 +0100
+Subject: [PATCH 508/773] 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 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 2dd2eff4a3bb8b1069b28f68c636f2cf03479638 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 28 May 2019 16:23:51 +0100
+Subject: [PATCH 509/773] 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 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 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 45f37ac857d1700c810deb154a60415212f7f4bf Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 30 May 2019 12:25:29 +0100
+Subject: [PATCH 510/773] 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 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 b491245e487b15b57e543c18cdc3e5236ddbf6a7 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 3 Jun 2019 14:57:56 +0100
+Subject: [PATCH 511/773] 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 503981056ebed755cb46a721cad6067598fe80f1 Mon Sep 17 00:00:00 2001
+From: IQaudIO <gordon@iqaudio.com>
+Date: Thu, 6 Jun 2019 10:20:55 +0100
+Subject: [PATCH 512/773] 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 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 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 ab4be0bc5cce7c699d654d7f88a3c1bec57b5570 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 513/773] 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 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 4a4c0e852e353c27a806ee393bf365213e34267b 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 514/773] 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 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 c348ccd68f85473e13faaaba6f409b00fa06efff Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 12 Jun 2019 17:15:05 +0100
+Subject: [PATCH 515/773] 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 56108cfacde8cb051126de99092e67ca02635184 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 12 Jun 2019 17:32:11 +0100
+Subject: [PATCH 516/773] 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 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 0e3b70d74a8ab5187a05e48dfec974f650cfbd83 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 12 Jun 2019 20:45:17 +0100
+Subject: [PATCH 517/773] 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 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 060db9ab233a8d887adfbfa0dc4357b620d8182e Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Sat, 8 Jun 2019 10:14:43 -0700
+Subject: [PATCH 518/773] 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 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 58bf0ee75ceb54208037f0e4f3b3896aeda443de Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 17 Sep 2018 09:22:21 +0100
+Subject: [PATCH 519/773] 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 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 f7b4af251d2e0f80ef21c9be6969bfca0fcd8955 Mon Sep 17 00:00:00 2001
+From: Doug Berger <opendmb@gmail.com>
+Date: Mon, 13 May 2019 20:59:45 +0200
+Subject: [PATCH 520/773] 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 74a4dd8daf47253654d13143608b6b3518d8dc42 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sun, 19 May 2019 12:20:00 +0200
+Subject: [PATCH 521/773] 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 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 195eb3a9fc9a03bf6cbd4cd95c39ca7d9f9df4d5 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 12 Dec 2018 15:51:49 -0800
+Subject: [PATCH 522/773] 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 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 31462c12bc2bb4d20fa6f5b30bb39d91eaa78363 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sat, 4 May 2019 17:06:54 +0200
+Subject: [PATCH 523/773] 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 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 48a12a229f61b9f86fa09d44cd04a4e2c3ca9879 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Thu, 12 Oct 2017 18:11:32 +0100
+Subject: [PATCH 524/773] 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 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 e6f7fd2d2124fe71f5c3f44034a1911221ff6dda Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 May 2019 15:19:21 +0100
+Subject: [PATCH 525/773] 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 1b6929dcb41f65f6edc10c59d9ed6aeda413640d Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 20 Feb 2019 08:49:39 +0000
+Subject: [PATCH 526/773] 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 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 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 87bf382f67d4c10eddb9dacf545c03877feb95a6 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 527/773] 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 4b37db9986aab268e474226fc02edc5c32002f55 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 19 Feb 2019 22:06:59 +0000
+Subject: [PATCH 528/773] 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 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 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 8c846a50fd244e719c7f463c38e9333c7bd95977 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 19 Feb 2019 22:06:59 +0000
+Subject: [PATCH 529/773] 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 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 267ce95d56a523e7720f1da5ed1b8f9c3c7e7420 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/773] 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 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 c5a1328b9ddca9db14b25ff8a5c3ead24ec32dff Mon Sep 17 00:00:00 2001
+From: Jim Quinlan <jim2101024@gmail.com>
+Date: Mon, 15 Jan 2018 18:28:39 -0500
+Subject: [PATCH 531/773] 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 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 4cf752e8c6b0ec63f932d28c48a652ff682be861 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/773] 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 163210578ebc3365d92bb292666583dceb28a947 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 May 2019 15:47:42 +0100
+Subject: [PATCH 533/773] 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 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 660caa15e0857ec1e6d443907d846bafd45b28be Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 Aug 2018 09:05:15 +0100
+Subject: [PATCH 534/773] 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 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 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 7028b50bd6d167a4bc57b9a356235d21ace20d55 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 28 Sep 2018 16:24:05 +0100
+Subject: [PATCH 535/773] 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 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 f17934b2f3f7ccf2d20ff37b7f7b72675b73cfd4 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sat, 27 Apr 2019 12:33:57 +0200
+Subject: [PATCH 536/773] 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 e6a56923caeb2d27d86d049cf11a3af6cf6dd6e7 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sat, 4 May 2019 17:06:15 +0200
+Subject: [PATCH 537/773] 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 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 001069da98632fa4b268c4c8906c448ff3ed3fdc Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sat, 18 May 2019 12:26:11 +0200
+Subject: [PATCH 538/773] 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 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 2c52bddb08678377ba855256b3b5dc8aa7ee72f1 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 1 Nov 2018 17:31:37 +0000
+Subject: [PATCH 539/773] 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 e69a797a57b9e0fd52bed980c2cd7bee41d7b664 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Tue, 30 Apr 2019 19:15:30 +0100
+Subject: [PATCH 540/773] 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 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 5f0a793c24abfa5fa33ecc2eb1cc0a9083336854 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Wed, 12 Sep 2018 14:44:53 +0100
+Subject: [PATCH 541/773] 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 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 57f174958ca1e2579c020ff0eb876f7052aba402 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 27 Mar 2019 13:45:46 +0000
+Subject: [PATCH 542/773] 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 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 259098c80b022b81abf94a37f3928c3fc4f2455e Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 14 May 2019 17:17:59 +0100
+Subject: [PATCH 543/773] 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 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 6d674e0c255b0a4f2ec2211fbfdf3b73265cc843 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 14 May 2019 17:00:41 +0100
+Subject: [PATCH 544/773] 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 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 3e82f4b81c49f3a4406930080b21bd985453d036 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Fri, 17 May 2019 13:31:21 +0100
+Subject: [PATCH 545/773] 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 8d81496c0b751297bc6f847268e1e278f958de24 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 21 May 2019 13:36:52 +0100
+Subject: [PATCH 546/773] 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 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 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 c322d8eeee2d186b790fced2e567101d165a7452 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 547/773] 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 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 f9aa5f43485741d4f866070ffe4dbdd28a1937e4 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 23 May 2019 15:08:30 +0100
+Subject: [PATCH 548/773] 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 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 2b9c74a0458e9f1e27feb27086e841f773530401 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Thu, 30 May 2019 10:38:40 +0100
+Subject: [PATCH 549/773] 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 34e6cb1e6f79b24d66353f7c0ac75cd0ae749208 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 550/773] 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 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 9d848c0af8245c674ad7a91d157362334e822361 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 551/773] 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 */
+@@ -756,7 +760,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 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 910f74bae7c97fafd4a834b9a5e261d4ef2d9676 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Thu, 9 May 2019 14:30:37 +0100
+Subject: [PATCH 552/773] 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 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 47b633ce2623b1108224bf3b80c8827a7a85d556 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 23 Jan 2019 16:11:50 +0000
+Subject: [PATCH 553/773] 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 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 */
-@@ -756,7 +760,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 0718ee0a5ed119e57e69307baced70e1dd2236df Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 12 Dec 2018 15:51:47 -0800
+Subject: [PATCH 554/773] 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 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 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 00be0bc0ae077a87cb8660af2204aaa2e092af56 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 12 Dec 2018 15:51:48 -0800
+Subject: [PATCH 555/773] 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 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 cfa59f455705193753c58674490791627b093410 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 11 Jan 2019 17:29:10 -0800
+Subject: [PATCH 556/773] 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 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 b2b716960b1e007900b3b423bad133b0cc37c975 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Sat, 12 Jan 2019 08:07:43 -0800
+Subject: [PATCH 557/773] 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 03e675c9f6504a799f89e319419aa3ff4188e6d3 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 11 Jan 2019 17:31:07 -0800
+Subject: [PATCH 558/773] 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 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 0738d9361eaebde9a4ad058f7fb5d554d2ad803c 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 559/773] 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 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 c21e17ec6f4525ccf85ca496f8ffe19ce88db7c2 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 28 Sep 2018 16:21:23 -0700
+Subject: [PATCH 560/773] 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 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 2c0ed343c8ded92db2a93ef58eef03774409bc66 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 28 Sep 2018 16:21:24 -0700
+Subject: [PATCH 561/773] 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 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 daff6b7eeba8a177a2d406531807143d0dd497bc Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 8 Nov 2018 08:16:52 -0800
+Subject: [PATCH 562/773] 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 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 e2f393595cec106de3656854084f77f7dc06c111 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 8 Nov 2018 08:16:53 -0800
+Subject: [PATCH 563/773] 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 f2589a672830d7c71a98fdbbcd6e009a033e6491 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 28 Nov 2018 15:09:25 -0800
+Subject: [PATCH 564/773] 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 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 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 47ca36207d373c1114e9c19d68d0548bfa74e96d Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 28 Nov 2018 15:09:26 -0800
+Subject: [PATCH 565/773] 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 dc3e81ebd4f232646e10e63e25b048edb4ebc007 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 30 Nov 2018 16:57:59 -0800
+Subject: [PATCH 566/773] 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 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 45825b7a8fe40a6b8d03312cc433713b0cc4b63f Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 30 Nov 2018 16:57:58 -0800
+Subject: [PATCH 567/773] 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 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 a29692f6e1d732419ba24fb51959597514eda190 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:34 -0800
+Subject: [PATCH 568/773] 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 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 c44a4bd02a38b30b58e61ead45c4b530a87568c6 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:35 -0800
+Subject: [PATCH 569/773] 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 384cb5c7acae08a9ec07b8eaa67de697b7ad9a5a Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:36 -0800
+Subject: [PATCH 570/773] 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 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 1e22cd2f91ce5abc1587f14c7cafb72f12334fe8 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:37 -0800
+Subject: [PATCH 571/773] 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 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 e106cc466d4e85d294dd211984d9bc2aeb926f5a Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 3 Dec 2018 14:24:38 -0800
+Subject: [PATCH 572/773] 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 0e031dc68877a44cc11e2692b3f4b46164330db2 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 7 Feb 2019 15:26:13 -0800
+Subject: [PATCH 573/773] 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 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 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 a86b8d88a3bad7cb79ec7e4abd6e5395d5fe8159 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 7 Feb 2019 12:09:58 -0800
+Subject: [PATCH 574/773] 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 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 d231c07d344ad8259bb88ba12497346d61050821 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 4 Mar 2019 11:59:34 -0800
+Subject: [PATCH 575/773] 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 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 54fb807d394537bbe866c30b1bad30244e374f01 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 20 Feb 2019 13:03:41 -0800
+Subject: [PATCH 576/773] 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 5aaf1e394512bf2f1486f19c69fd0ee83d6e1a6a Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 4 Oct 2018 17:22:43 -0700
+Subject: [PATCH 577/773] 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 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 157d2df805d880b7ba014ae7c89b2d1d90c77bb2 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 16 Oct 2018 10:13:41 -0700
+Subject: [PATCH 578/773] 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 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 452de2d412157502f7365517eb21d2aaa25d5133 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 14 Jan 2019 17:26:04 -0800
+Subject: [PATCH 579/773] 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 cd166c9bfda92698961f76e9807da6e6cfcbab16 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 4 Oct 2018 17:22:43 -0700
+Subject: [PATCH 580/773] 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 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 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 3a371c1a0d3e574faac4d1ce87c9577c34a966e8 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 14 Jan 2019 12:35:43 -0800
+Subject: [PATCH 581/773] 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 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 9b25c56a149566181394f8d005413513e8bea63c Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 14 Jan 2019 14:47:57 -0800
+Subject: [PATCH 582/773] 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 d33359888913c1317afa8bf22d755807b24899ef Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 14 Jan 2019 15:13:17 -0800
+Subject: [PATCH 583/773] 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 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 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 c6e6c508b5ab90ac310b9686fd63732c05e07b06 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 12 Mar 2019 09:08:10 -0700
+Subject: [PATCH 584/773] 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 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 64f7c33da2df2c9b7d92652142bfe7ac5602b99e Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 27 Dec 2018 14:04:44 -0800
+Subject: [PATCH 585/773] 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 af7079937088946ade149f0bfbb553d6fe51ce7f Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 27 Dec 2018 12:11:52 -0800
+Subject: [PATCH 586/773] 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 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 9691f6245f13a92f49143602f47f6e7f0b6b5f55 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 27 Mar 2019 17:44:40 -0700
+Subject: [PATCH 587/773] 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 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 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 0a27b06c9a1dd637abc5940a318620b539a75b5b Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 28 Mar 2019 11:58:51 -0700
+Subject: [PATCH 588/773] 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 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 31290e7ce363dc0bf6e3bae9c7b879e52f2e2a55 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 29 Mar 2019 12:04:36 -0700
+Subject: [PATCH 589/773] 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 c4d47982f89af5e6b87f35e95ef4529561ada6c4 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 18 Mar 2019 16:38:32 -0700
+Subject: [PATCH 590/773] 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 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 2372381c6850bf862a43997d95f4a5abcde156e9 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 2 Apr 2019 13:29:00 -0700
+Subject: [PATCH 591/773] 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 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 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 8a64687192f4bbe09c9c365fdcff8207fe2004d4 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 592/773] 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 129c59fcd6a75f718c5d6dd1042fc0c7e33f70a3 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 593/773] 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 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 25b8ee91f37d732a47c25bfb81921c0ae52a5643 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 594/773] 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 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 ab8a7cf65365cd1639ae4f24efe8d6e6be2c828e 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 595/773] 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 f112dfa1500ce107f5cddac5da6d5802245ae800 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 596/773] 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 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 ce058e6a897ddd5103248b4c2a143f9e11c0ad9f 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 597/773] 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 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 0b1a0ecc378cc8587de0345a2239290dc31384dd 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 598/773] 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 7029b71f2c474c3dc80beeec61ac89b01d56f32f 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 599/773] 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 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 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 47700425df8d50679d75ba663cb7aa5d43138156 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 600/773] 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 1f2718aa829aac2c918f48bad20e686add305819 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 601/773] 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 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 73d9ab0eca460e20dfa3856195a618241842cf63 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 602/773] 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 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 6f97c5f506b5d3044b6475c0526a81eba9205097 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 603/773] 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 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 3e4d01d192cf5ecb7c79e77ab7bdda166d3ad036 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 604/773] 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 496a9697b13e4a03c3b2272601f2040e6a5e41bf 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 605/773] 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 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 00937ea83ad39562fe1b57a423f9648ac8266810 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 606/773] 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 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 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 8909268e4c9bbd1854ad12e4cde6b53346198e90 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 607/773] 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 6c11f6cfbd34888b476e2f0eb9df0f165b5e945f Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 2 May 2019 15:11:05 -0700
+Subject: [PATCH 608/773] 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 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 fed6543dedef6a7863bcc54911adc54de3f238d5 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 2 May 2019 15:24:04 -0700
+Subject: [PATCH 609/773] 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 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 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 0e26e8b14d72d122ed1a3f66a53829944980fd4e Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 16 Apr 2019 15:58:54 -0700
+Subject: [PATCH 610/773] 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 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 b8634066965cc851b112290e5f2cd8c437a065d3 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 2 May 2019 13:22:53 -0700
+Subject: [PATCH 611/773] 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 57c5dc71b8727396309b9572724ae2dd1ec69ba7 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Thu, 2 May 2019 23:42:29 +0200
+Subject: [PATCH 612/773] 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 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 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 bafadb1b6a91fe020fdbf637f295003c4b919a0d 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 613/773] 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 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 dc10fecf7ecb39ff236e26879cb02d2f781b6b09 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 614/773] 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 bf373ea14cb8d5b0691953dfb5398e3e34dfb54d 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 615/773] 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 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 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 2787e876c661f4cec8d05de0e7cc2ec033a8a7bf 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 616/773] 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 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 a39d6a00d02a2e1d1afce976ded233bc40bf6b33 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 28 May 2019 13:56:06 +0100
+Subject: [PATCH 617/773] 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 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 54ffea83f539f01436acaa73df648a8279c77918 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 618/773] 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 8181d789a017ae9e5c0503f2878add96d4b83197 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 619/773] 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 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 0489db39ef4afce7fe37ca7ec8ff5858ec04fe31 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 620/773] 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 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 430e4ee48af03ffccfcd51fb7bb07663eff0cc7e 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 621/773] 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 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 06ca175284fcd32c7aa9198d05fb3ef87e33cf52 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 622/773] 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 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 38030171e53bf65ba74f57fc66cd797b106af834 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 623/773] 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 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 8986657f9145f5d5a2c3389aaa063a67965cd606 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 624/773] 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 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 011333a8c778023081a176de7b5d09d91980568d 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 625/773] 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 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 b55553b491ccfb9fc7b9b3b399c4796bd802c812 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 626/773] 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 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 18b1d1f37982d617bda0cac175d117a4d43ea4c2 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 627/773] 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 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 55eeb95f5c99e15c86ff9c67c2cfe0ee4a409031 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 628/773] 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 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 1d9c0a0c7681824a0168dc19cebb2975cfae5efb 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 629/773] 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 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 7966c5cd279f808fa6d62dd5b22bb4837456e972 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 630/773] 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 180af60db3526e997b4363925a6c181c21c00bbb 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 631/773] 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 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 d6c8d3492b8204d2da0c94a22e8e7087f50604b8 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sun, 19 May 2019 12:26:21 +0200
+Subject: [PATCH 632/773] 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 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 c71ece7992a28b9b58f4b5fffc688b91985bc841 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 May 2019 13:54:21 +0100
+Subject: [PATCH 633/773] 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 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 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 eee4d80265dc70bec12445e2271077bec86f7e09 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 30 May 2019 16:44:24 +0100
+Subject: [PATCH 634/773] 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 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 3873070310f64046c1e0ee27a2d9568a3eabb0d9 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 635/773] 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 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 49ef6fe265b68e0229ba5cb9f4a6169800eb8b02 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 636/773] 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 46a1fe9e384cdb9d0e38fc2d34bc09f589119736 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 4 Sep 2018 11:50:25 +0100
+Subject: [PATCH 637/773] 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 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 964cdb9a447cbc0f797e6a47158eaeead4a000a4 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 29 May 2019 15:40:21 +0100
+Subject: [PATCH 638/773] 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 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 2444150b95e0fba1bcbdb28ceaf682d30023e929 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 8 Mar 2019 21:12:39 +0000
+Subject: [PATCH 639/773] 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 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 5edcf271242f01646376a3850312f94da3d90f75 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 3 Jun 2019 14:57:56 +0100
+Subject: [PATCH 640/773] 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 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 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 7272cd8bbc0ac6c5ef86d7512f213babf011ecb2 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Mon, 3 Jun 2019 15:33:02 +0100
+Subject: [PATCH 641/773] 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 5da18ac4c71393a00a31921b26e64eaf40636943 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 642/773] 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 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 3fea68f6c39f83bfcd8de2c52351e82a82ed05aa Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 6 Feb 2019 20:45:16 +0000
+Subject: [PATCH 643/773] 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 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 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 87da99333106c7933d81371db471e98bc5795ae8 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 4 Apr 2019 13:33:47 +0100
+Subject: [PATCH 644/773] 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 5aacd9e3b4c30316abb4e037604f43d9ecd315b3 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 5 Jun 2019 21:32:03 +0100
+Subject: [PATCH 645/773] 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 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 241ac53547a6d427835e52f52764dfafe33fcfde Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 6 Jun 2019 09:35:08 +0100
+Subject: [PATCH 646/773] 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 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 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 ae5791e01639ece446aa59eb2af40b46138cbc4a 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 647/773] 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 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 c6d6956b9083b654c86e2ab3feb19c9867c01c28 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 648/773] 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 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 2fb2e6ea673d427dbc37654d258df59059cfab4b 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 649/773] 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 854ab95d215c4824b785e49c9ca3b90796d2bc6a 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 650/773] 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 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 f5d74e55edf6504f6f857b23b06dca7b4d3d3306 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 10 Jun 2019 17:22:44 +0100
+Subject: [PATCH 651/773] 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 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 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 3f57e5c46db3cf27a36b61534238fbd8903390fe 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 652/773] 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 729a88af476bf34a7b76d4dfdf7723c57cfd1533 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Fri, 7 Jun 2019 14:50:12 +0100
+Subject: [PATCH 653/773] 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 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 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 8a84d16debf7243c49bc63a38732c51e16781bc1 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 11 Jun 2019 10:55:00 +0100
+Subject: [PATCH 654/773] 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 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 44943168f36c02b224a963c805a100f47c58a9c6 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 11 Jun 2019 11:33:39 +0100
+Subject: [PATCH 655/773] 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 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 383795def3c6401a3f596f5cd657c2ce86cb544a Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 11 Jun 2019 11:42:03 +0100
+Subject: [PATCH 656/773] 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 1b8faaeb3d705b1babc5de8cbd1f32653d1c5d64 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 657/773] 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 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 8f897344c4828db157231786326ea865cbfb6582 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 658/773] 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 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 d0e00483c95c2d67b42ac74a60cfc424cc75c089 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 17 Jun 2019 10:06:55 +0100
+Subject: [PATCH 659/773] 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 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 6b38721bd9dc2a3e604c77c6ca2e908064f36162 Mon Sep 17 00:00:00 2001
+From: dp111 <dominic.plunkett@gmail.com>
+Date: Sat, 15 Jun 2019 18:19:50 +0100
+Subject: [PATCH 660/773] 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 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 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 01f43125781d5558b82f87fbb2f9a6745e3942a6 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 661/773] 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 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 d9656156d4c00d678e0c3a684af3f2fc953daf63 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 662/773] 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 4517180418205e454d6d200d4b015aab2f5aeed8 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 11 Jun 2019 17:38:28 +0100
+Subject: [PATCH 663/773] 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 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 6198fc61e2a06a6ac7b2f264368b882905dfda71 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 4 Jun 2019 16:22:22 +0100
+Subject: [PATCH 664/773] 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 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 f906d34555ffd801f91cd8c93385395d189c308a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 11 Jun 2019 18:08:05 +0100
+Subject: [PATCH 665/773] 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 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 32097e77387b54b4757e2a92c63523b4a9ecbc75 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 17 Jun 2019 14:36:12 +0100
+Subject: [PATCH 666/773] 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 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 f9e286bc95f5441c321a8a04cef61ab3815cbbbb Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 18 Jun 2019 11:16:13 +0100
+Subject: [PATCH 667/773] 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 08cbbda5b4c0a52965ac5ba008c1de4f241c2abd Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 18 Jun 2019 11:19:59 +0100
+Subject: [PATCH 668/773] 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 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 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 f7250362d2619244fb4fa3ddcf26c2872ff0097a Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Sat, 25 May 2019 10:45:38 +0200
+Subject: [PATCH 669/773] 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 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 c87eb45563002656a45b51573bc2051c671734d9 Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Mon, 20 May 2019 09:05:55 +0200
+Subject: [PATCH 670/773] 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 d6f29e7be3c7b181cf2d630bfeec9b3499eae2e6 Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Mon, 20 May 2019 09:05:56 +0200
+Subject: [PATCH 671/773] 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 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 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 2c5817c444e95254ed4888c12345c2dabe401fda Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Wed, 22 May 2019 12:40:53 +0200
+Subject: [PATCH 672/773] 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 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 d928cdb13ddd26dd4695d8626990303e9f348a8d Mon Sep 17 00:00:00 2001
+From: Mariusz Bialonczyk <manio@skyboo.net>
+Date: Thu, 30 May 2019 09:51:25 +0200
+Subject: [PATCH 673/773] 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 322895008e3f342c3363a6c92e4a04e35ecb5892 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 674/773] 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 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 97371a5040a9ac012d1e057a10e188f15dcc8e8e 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 675/773] 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 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 c89ee8bbd3fb045bf610e8ea8f59b2db3d3f88b6 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 676/773] 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 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 891a7d8b2309f2526c1746e5be026915f27af5ec 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 677/773] 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 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 ebc5880578193fa828a26beaa91ffd9a90d69cd2 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 28 Jun 2019 22:44:09 +0100
+Subject: [PATCH 678/773] 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 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 57539d5c7be69774e030825b0b6ec7979956182f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 2 Jul 2019 17:13:05 +0100
+Subject: [PATCH 679/773] 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 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 eccada7c8b878c0caf164b3e3a68ad8c9176a2ac Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 2 Jul 2019 21:25:59 +0100
+Subject: [PATCH 680/773] 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 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 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 4112f55d9486a663a572593741b2b47ba59c017d Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 2 Jul 2019 21:43:13 +0100
+Subject: [PATCH 681/773] 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 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 beae1957f04c31207a69e293bb4c595e4aa4480d Mon Sep 17 00:00:00 2001
+From: Andrei Gherzan <andrei@gherzan.ro>
+Date: Wed, 3 Jul 2019 13:53:29 +0100
+Subject: [PATCH 682/773] 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 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 755c7c9c4f39b690892d2b38a2fd44f4dd602d4a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 3 Jul 2019 20:37:14 +0100
+Subject: [PATCH 683/773] 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 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 9fce5008a9183cfe5dc5393b726e93020b21f580 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 684/773] 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 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 d35867a1bb8e7f963132e626f5432239969e92c9 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 685/773] 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 69a0a11878ffe57f71232872b3971670dfec3b21 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 686/773] 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 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 06ab322c9baaa3e2c8bcb0609ccbf858b5444150 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 687/773] 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 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 d3075e61796e6748b238203d5c5c852a1a5727ea 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 688/773] 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 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 79edd467648bbd35cfb01574800edd8e435cdc2f 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 689/773] 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 db26693701ac11d20a16ca455886d810a6b67c2c 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 690/773] 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 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 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 948ebd5405bde063d68cb05e5250eefe167fd48c Mon Sep 17 00:00:00 2001
+From: Hans Verkuil <hansverk@cisco.com>
+Date: Thu, 23 Aug 2018 09:56:22 -0400
+Subject: [PATCH 691/773] 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 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 8867c69465720f32ae8be1271ab5d6237757bf39 Mon Sep 17 00:00:00 2001
+From: Hans Verkuil <hansverk@cisco.com>
+Date: Thu, 23 Aug 2018 10:18:35 -0400
+Subject: [PATCH 692/773] 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 5f17a43ba98013bf6683a50faabef29c3bdc3117 Mon Sep 17 00:00:00 2001
+From: John Sheu <sheu@chromium.org>
+Date: Thu, 15 Nov 2018 10:57:16 -0500
+Subject: [PATCH 693/773] 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 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 437170389e1ec50855f000d6a6043474b8af85d4 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 5 Jul 2019 09:22:10 +0100
+Subject: [PATCH 694/773] 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 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 efd44306b7202c5e038cc98ea213e1146a93a960 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 695/773] 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 b085eb8eed7f2da7c76ec0cea3abd70953367093 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Fri, 21 Jun 2019 03:52:49 -0700
+Subject: [PATCH 696/773] 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 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 5b395c9b5adc1bcb42b1ca473de2a3fb478efd1b Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Fri, 21 Jun 2019 03:52:50 -0700
+Subject: [PATCH 697/773] 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 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 903fe021059f70162175066f034de618064ca0bb Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 9 Jul 2019 10:32:40 +0100
+Subject: [PATCH 698/773] 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 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 bad29ba77266dd37bdaf3bded68111c8a0a9de15 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 11 Jul 2019 13:13:39 +0100
+Subject: [PATCH 699/773] 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 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 d01af13ec60ee5b8ee944a4e38986b13fea701eb Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Thu, 11 Jul 2019 17:55:43 +0100
+Subject: [PATCH 700/773] 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 26d8063c76c0243c0a12e59e37b9efd3fb100326 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 12 Jul 2019 15:38:35 +0100
+Subject: [PATCH 701/773] 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 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 2dbe147b0baa9ad36dd5150f249d48ef3cb0a524 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 8 Mar 2019 13:02:16 -0800
+Subject: [PATCH 702/773] 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 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 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 747a71aefc4990f9db830f18c41e0a52b0d7b4e0 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 15 Jul 2019 10:39:05 +0100
+Subject: [PATCH 703/773] 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 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 37dac3b99a4e26d0d9df3f5297da90e65f5ed978 Mon Sep 17 00:00:00 2001
+From: Allen Wild <allenwild93@gmail.com>
+Date: Sat, 13 Jul 2019 11:14:02 -0400
+Subject: [PATCH 704/773] 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 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 e398200b9e0746bb9bcdf4900ed8fc6f7f813cb6 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 16 Jul 2019 15:24:12 +0100
+Subject: [PATCH 705/773] 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 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 50be150dc853d2ce75215cc220cc6ff0def89a3a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 17 Jul 2019 10:08:55 +0100
+Subject: [PATCH 706/773] 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 e7bf2e5b1b86a11a0ccf59222cb31b06213d9276 Mon Sep 17 00:00:00 2001
+From: Giedrius <giedrius@blokas.io>
+Date: Fri, 12 Jul 2019 17:45:55 +0300
+Subject: [PATCH 707/773] 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 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 5f7837a8024b971e5cdb338d6e41007be77cc31e Mon Sep 17 00:00:00 2001
+From: Andrei Gherzan <andrei@balena.io>
+Date: Tue, 16 Jul 2019 13:28:22 +0100
+Subject: [PATCH 708/773] 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 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 c9f653b477a97ef65ac69c8bdb27a4bc790fe2d0 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 709/773] 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 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 cafde1b8ce97409f642c0a851e6a8b98f7cbd295 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Thu, 18 Jul 2019 13:05:35 +0100
+Subject: [PATCH 710/773] 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 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 0b83bc12aa07be8457f9de2d3ad25fbb48a82fe5 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 711/773] 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 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 3d15f23340782daa9f244e725df3770d5634fcfe 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 712/773] 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 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 17f3a0913e581da33dc7bed5f526e1c4c3181937 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 23 Jul 2019 12:55:07 +0100
+Subject: [PATCH 713/773] 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 734ea10c982bde32609d05be84d9c3a32830540b 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 714/773] 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 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 96ed8334b9bf4cd4ddb95a4f4324bda6adee40d1 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 715/773] 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 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 a39d399ecb26cad762a057cabceb965ffda71d81 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 716/773] 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 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 ec6240540c2467c6d34c8e7bc6dbb8ac50dbccd8 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 717/773] 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 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 cd63ed6ede9cad42a556710dddb776614d15c0fa 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 718/773] 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 e1c466862ce282dd632ef03dd396b56f04d51732 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 719/773] 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 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 330b973824c6d835fd8c43f56d2bc05f931fc919 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 720/773] 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 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 b20c06f84d29855ce2400d7012b990196b70e6d1 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Wed, 24 Jul 2019 14:36:53 +0100
+Subject: [PATCH 721/773] 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 efdfbd4028324a38a55ea81036012da9988388ff Mon Sep 17 00:00:00 2001
+From: Joerg Schambacher <joscha@schambacher.com>
+Date: Tue, 23 Jul 2019 16:57:35 +0200
+Subject: [PATCH 722/773] 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 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 47f8fa0e373037e0c3ee9d6915546bd30226a9ed 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 723/773] 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,
+++ /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 e23eda71bf8f1180f6d9491be8eda93e11ec39f2 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 31 Jul 2019 17:36:34 +0100
+Subject: [PATCH 724/773] drm/vc4: A present but empty dmas disables audio
+
+Overlays are unable to remove properties in the base DTB, but they
+can overwrite them. Allow a present but empty 'dmas' property
+to also disable the HDMI audio interface.
+
+See: https://github.com/raspberrypi/linux/issues/2489
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -1087,10 +1087,12 @@ static int vc4_hdmi_audio_init(struct vc
+ struct device *dev = &hdmi->pdev->dev;
+ const __be32 *addr;
+ int ret;
++ int len;
+
+- if (!of_find_property(dev->of_node, "dmas", NULL)) {
++ if (!of_find_property(dev->of_node, "dmas", &len) ||
++ len == 0) {
+ dev_warn(dev,
+- "'dmas' DT property is missing, no HDMI audio\n");
++ "'dmas' DT property is missing or empty, no HDMI audio\n");
+ return 0;
+ }
+
+++ /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,
--- /dev/null
+From 3c9e313f7ff7d1649a137834ba205c665c2ab007 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 31 Jul 2019 17:39:37 +0100
+Subject: [PATCH 725/773] overlays: Add audio parameter to vc4-kms-v3d
+
+The audio parameter to the vc4-kms-v3d overlay allows audio support
+to be disabled (it defaults to on) by adding "audio=off" to the
+dtoverlay parameters.
+
+See: https://github.com/raspberrypi/linux/issues/2489
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README | 1 +
+ arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 8 ++++++++
+ 2 files changed, 9 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2480,6 +2480,7 @@ Params: cma-256 CMA is 2
+ cma-128 CMA is 128MB
+ cma-96 CMA is 96MB
+ cma-64 CMA is 64MB
++ audio Enable or disable audio over HDMI (default "on")
+
+
+ Name: vga666
+--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
+@@ -134,11 +134,19 @@
+ };
+ };
+
++ fragment@17 {
++ target = <&hdmi>;
++ __dormant__ {
++ dmas;
++ };
++ };
++
+ __overrides__ {
+ cma-256 = <0>,"+0-1-2-3-4";
+ cma-192 = <0>,"-0+1-2-3-4";
+ cma-128 = <0>,"-0-1+2-3-4";
+ cma-96 = <0>,"-0-1-2+3-4";
+ cma-64 = <0>,"-0-1-2-3+4";
++ audio = <0>,"!17";
+ };
+ };
--- /dev/null
+From fa65229070744c7c073f8869d34ba778b5d79a86 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 31 Jul 2019 17:41:47 +0100
+Subject: [PATCH 726/773] overlays: Update the upstream overlay
+
+The recent vc4-kms-v3d commit has changed the content of the
+upstream overlay (even though the extra fragment is disabled).
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/upstream-overlay.dts | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
+@@ -110,6 +110,12 @@
+ };
+ };
+ fragment@17 {
++ target = <&hdmi>;
++ __dormant__ {
++ dmas;
++ };
++ };
++ fragment@18 {
+ target = <&usb>;
+ #address-cells = <1>;
+ #size-cells = <1>;
--- /dev/null
+From 0bcf10eaed142257cbac31a6bcf18de03379fe38 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 1 Aug 2019 08:58:48 +0100
+Subject: [PATCH 727/773] can: mcp251x: Allow more time after a reset
+
+Some boards take longer than 5ms to power up after a reset, so allow
+a few retry attempts before giving up.
+
+See: https://github.com/raspberrypi/linux/issues/2767
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/net/can/spi/mcp251x.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/can/spi/mcp251x.c
++++ b/drivers/net/can/spi/mcp251x.c
+@@ -628,6 +628,7 @@ static int mcp251x_hw_reset(struct spi_d
+ struct mcp251x_priv *priv = spi_get_drvdata(spi);
+ u8 reg;
+ int ret;
++ int retries = 10;
+
+ /* Wait for oscillator startup timer after power up */
+ mdelay(MCP251X_OST_DELAY_MS);
+@@ -637,10 +638,18 @@ static int mcp251x_hw_reset(struct spi_d
+ if (ret)
+ return ret;
+
+- /* Wait for oscillator startup timer after reset */
+- mdelay(MCP251X_OST_DELAY_MS);
++ /*
++ * Wait for oscillator startup timer after reset
++ *
++ * Some devices can take longer than the expected 5ms to wake
++ * up, so allow a few retries.
++ */
++
++ do {
++ mdelay(MCP251X_OST_DELAY_MS);
++ reg = mcp251x_read_reg(spi, CANSTAT);
++ } while (!reg && retries--);
+
+- reg = mcp251x_read_reg(spi, CANSTAT);
+ if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF)
+ return -ENODEV;
+
--- /dev/null
+From 7a6d95656a758098058460b9635f37338a2a22cf Mon Sep 17 00:00:00 2001
+From: James Hughes <james.hughes@raspberrypi.org>
+Date: Mon, 29 Jul 2019 12:02:59 +0100
+Subject: [PATCH 728/773] Fixup FKMS interrupt handing for non-existent display
+
+If an errant interrupt flag was received from a non-existent display,
+a NULL pointer access was made. Protect against this by checking if a
+second display is present prior to checking the interrupt flags.
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -1056,14 +1056,17 @@ static irqreturn_t vc4_crtc_irq_handler(
+ vc4_crtc_handle_page_flip(crtc_list[0]);
+ }
+
+- /* Check for the secondary display too */
+- chan = readl(crtc_list[0]->regs + SMIDSW1);
++ if (crtc_list[1]) {
++ /* 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]);
++ 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]);
++ }
+ }
+ }
+
--- /dev/null
+From 171e91bd7e8f9541aabae98e6b39ea61a31f2c3f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Sun, 28 Jul 2019 22:22:36 +0100
+Subject: [PATCH 729/773] drivers: char: Use correct name for the Raspberry Pi
+ video decoder
+
+Replace the old code name with a more appropriate name - RPiVid.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2838.dtsi | 10 +-
+ arch/arm/configs/bcm2711_defconfig | 2 +-
+ drivers/char/broadcom/Kconfig | 8 +-
+ drivers/char/broadcom/Makefile | 2 +-
+ .../broadcom/{argon-mem.c => rpivid-mem.c} | 105 +++++++++---------
+ drivers/mfd/bcm2835-pm.c | 12 +-
+ drivers/soc/bcm/bcm2835-power.c | 6 +-
+ include/linux/mfd/bcm2835-pm.h | 2 +-
+ 8 files changed, 71 insertions(+), 76 deletions(-)
+ rename drivers/char/broadcom/{argon-mem.c => rpivid-mem.c} (69%)
+
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -409,26 +409,26 @@
+ };
+
+ hevc-decoder@7eb00000 {
+- compatible = "raspberrypi,argon-hevc-decoder";
++ compatible = "raspberrypi,rpivid-hevc-decoder";
+ reg = <0x0 0x7eb00000 0x10000>;
+ status = "okay";
+ };
+
+- argon-local-intc@7eb10000 {
+- compatible = "raspberrypi,argon-local-intc";
++ rpivid-local-intc@7eb10000 {
++ compatible = "raspberrypi,rpivid-local-intc";
+ reg = <0x0 0x7eb10000 0x1000>;
+ status = "okay";
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ h264-decoder@7eb20000 {
+- compatible = "raspberrypi,argon-h264-decoder";
++ compatible = "raspberrypi,rpivid-h264-decoder";
+ reg = <0x0 0x7eb20000 0x10000>;
+ status = "okay";
+ };
+
+ vp9-decoder@7eb30000 {
+- compatible = "raspberrypi,argon-vp9-decoder";
++ compatible = "raspberrypi,rpivid-vp9-decoder";
+ reg = <0x0 0x7eb30000 0x10000>;
+ status = "okay";
+ };
+--- a/arch/arm/configs/bcm2711_defconfig
++++ b/arch/arm/configs/bcm2711_defconfig
+@@ -650,7 +650,7 @@ CONFIG_BRCM_CHAR_DRIVERS=y
+ CONFIG_BCM_VCIO=y
+ CONFIG_BCM_VC_SM=y
+ CONFIG_BCM2835_DEVGPIOMEM=y
+-CONFIG_ARGON_MEM=m
++CONFIG_RPIVID_MEM=m
+ # CONFIG_LEGACY_PTYS is not set
+ CONFIG_SERIAL_8250=y
+ # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+--- a/drivers/char/broadcom/Kconfig
++++ b/drivers/char/broadcom/Kconfig
+@@ -50,10 +50,10 @@ config BCM2835_SMI_DEV
+ 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"
++config RPIVID_MEM
++ tristate "Character device driver for the Raspberry Pi RPIVid video 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.
++ so userspace tools can access the control and status registers of the
++ Raspberry Pi RPiVid video decoder hardware.
+--- a/drivers/char/broadcom/Makefile
++++ b/drivers/char/broadcom/Makefile
+@@ -4,4 +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
++obj-$(CONFIG_RPIVID_MEM) += rpivid-mem.o
+--- a/drivers/char/broadcom/argon-mem.c
++++ /dev/null
+@@ -1,277 +0,0 @@
+-/**
+- * 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
++++ b/drivers/char/broadcom/rpivid-mem.c
+@@ -0,0 +1,272 @@
++/**
++ * rpivid-mem.c - character device access to the RPiVid 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 "rpivid-mem"
++#define DEVICE_MINOR 0
++
++struct rpivid_mem_priv {
++ dev_t devid;
++ struct class *class;
++ struct cdev rpivid_mem_cdev;
++ unsigned long regs_phys;
++ unsigned long mem_window_len;
++ struct device *dev;
++ const char *name;
++};
++
++static int rpivid_mem_open(struct inode *inode, struct file *file)
++{
++ int dev = iminor(inode);
++ int ret = 0;
++ struct rpivid_mem_priv *priv;
++ if (dev != DEVICE_MINOR)
++ ret = -ENXIO;
++
++ priv = container_of(inode->i_cdev, struct rpivid_mem_priv,
++ rpivid_mem_cdev);
++ if (!priv)
++ return -EINVAL;
++ file->private_data = priv;
++ return ret;
++}
++
++static int rpivid_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 rpivid_mem_vm_ops = {
++#ifdef CONFIG_HAVE_IOREMAP_PROT
++ .access = generic_access_phys
++#endif
++};
++
++static int rpivid_mem_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ struct rpivid_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 = &rpivid_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
++rpivid_mem_fops = {
++ .owner = THIS_MODULE,
++ .open = rpivid_mem_open,
++ .release = rpivid_mem_release,
++ .mmap = rpivid_mem_mmap,
++};
++
++static const struct of_device_id rpivid_mem_of_match[];
++static int rpivid_mem_probe(struct platform_device *pdev)
++{
++ int err;
++ void *ptr_err;
++ const struct of_device_id *id;
++ struct device *dev = &pdev->dev;
++ struct device *rpivid_mem_dev;
++ struct resource *ioresource;
++ struct rpivid_mem_priv *priv;
++
++
++ /* Allocate buffers and instance data */
++
++ priv = kzalloc(sizeof(struct rpivid_mem_priv), GFP_KERNEL);
++
++ if (!priv) {
++ err = -ENOMEM;
++ goto failed_inst_alloc;
++ }
++ platform_set_drvdata(pdev, priv);
++
++ priv->dev = dev;
++ id = of_match_device(rpivid_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->rpivid_mem_cdev, &rpivid_mem_fops);
++ priv->rpivid_mem_cdev.owner = THIS_MODULE;
++ err = cdev_add(&priv->rpivid_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;
++
++ rpivid_mem_dev = device_create(priv->class, NULL,
++ priv->devid, NULL,
++ priv->name);
++ ptr_err = rpivid_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->rpivid_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 rpivid_mem");
++ return err;
++}
++
++static int rpivid_mem_remove(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct rpivid_mem_priv *priv = platform_get_drvdata(pdev);
++
++ device_destroy(priv->class, priv->devid);
++ class_destroy(priv->class);
++ cdev_del(&priv->rpivid_mem_cdev);
++ unregister_chrdev_region(priv->devid, 1);
++ kfree(priv);
++
++ dev_info(dev, "%s driver removed - OK", priv->name);
++ return 0;
++}
++
++static const struct of_device_id rpivid_mem_of_match[] = {
++ {
++ .compatible = "raspberrypi,rpivid-hevc-decoder",
++ .data = "rpivid-hevcmem",
++ },
++ {
++ .compatible = "raspberrypi,rpivid-h264-decoder",
++ .data = "rpivid-h264mem",
++ },
++ {
++ .compatible = "raspberrypi,rpivid-vp9-decoder",
++ .data = "rpivid-vp9mem",
++ },
++ /* The "intc" is included as this block of hardware contains the
++ * "frame done" status flags.
++ */
++ {
++ .compatible = "raspberrypi,rpivid-local-intc",
++ .data = "rpivid-intcmem",
++ },
++ { /* sentinel */ },
++};
++
++MODULE_DEVICE_TABLE(of, rpivid_mem_of_match);
++
++static struct platform_driver rpivid_mem_driver = {
++ .probe = rpivid_mem_probe,
++ .remove = rpivid_mem_remove,
++ .driver = {
++ .name = DRIVER_NAME,
++ .owner = THIS_MODULE,
++ .of_match_table = rpivid_mem_of_match,
++ },
++};
++
++module_platform_driver(rpivid_mem_driver);
++
++MODULE_ALIAS("platform:rpivid-mem");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Driver for accessing RPiVid decoder registers from userspace");
++MODULE_AUTHOR("Jonathan Bell <jonathan@raspberrypi.org>");
+--- a/drivers/mfd/bcm2835-pm.c
++++ b/drivers/mfd/bcm2835-pm.c
+@@ -50,14 +50,14 @@ static int bcm2835_pm_probe(struct platf
+ if (ret)
+ return ret;
+
+- /* Map the ARGON ASB regs if present. */
++ /* Map the RPiVid 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);
++ pm->rpivid_asb = devm_ioremap_resource(dev, res);
++ if (IS_ERR(pm->rpivid_asb)) {
++ dev_err(dev, "Failed to map RPiVid ASB: %ld\n",
++ PTR_ERR(pm->rpivid_asb));
++ return PTR_ERR(pm->rpivid_asb);
+ }
+ }
+
+--- a/drivers/soc/bcm/bcm2835-power.c
++++ b/drivers/soc/bcm/bcm2835-power.c
+@@ -637,15 +637,15 @@ 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
++ /* 2711 hack: the new RPiVid 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;
++ if (pm->rpivid_asb) {
++ power->asb = pm->rpivid_asb;
+ power->is_2711 = true;
+ }
+
+--- a/include/linux/mfd/bcm2835-pm.h
++++ b/include/linux/mfd/bcm2835-pm.h
+@@ -9,7 +9,7 @@ struct bcm2835_pm {
+ struct device *dev;
+ void __iomem *base;
+ void __iomem *asb;
+- void __iomem *arg_asb;
++ void __iomem *rpivid_asb;
+ };
+
+ #endif /* BCM2835_MFD_PM_H */
--- /dev/null
+From 597375f0bc034cbef2f3ab23a926445f1e7879c4 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 29 Jul 2019 12:03:21 +0100
+Subject: [PATCH 730/773] driver: char: rpivid - also support legacy name
+
+Provide transitional support for the previous names of
+the character devices.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/char/broadcom/rpivid-mem.c | 22 ++++++++++++++++++----
+ 1 file changed, 18 insertions(+), 4 deletions(-)
+
+--- a/drivers/char/broadcom/rpivid-mem.c
++++ b/drivers/char/broadcom/rpivid-mem.c
+@@ -66,7 +66,7 @@ static int rpivid_mem_open(struct inode
+ int dev = iminor(inode);
+ int ret = 0;
+ struct rpivid_mem_priv *priv;
+- if (dev != DEVICE_MINOR)
++ if (dev != DEVICE_MINOR && dev != DEVICE_MINOR + 1)
+ ret = -ENXIO;
+
+ priv = container_of(inode->i_cdev, struct rpivid_mem_priv,
+@@ -82,7 +82,7 @@ static int rpivid_mem_release(struct ino
+ int dev = iminor(inode);
+ int ret = 0;
+
+- if (dev != DEVICE_MINOR)
++ if (dev != DEVICE_MINOR && dev != DEVICE_MINOR + 1)
+ ret = -ENXIO;
+
+ return ret;
+@@ -167,14 +167,14 @@ static int rpivid_mem_probe(struct platf
+ /* Create character device entries */
+
+ err = alloc_chrdev_region(&priv->devid,
+- DEVICE_MINOR, 1, priv->name);
++ DEVICE_MINOR, 2, priv->name);
+ if (err != 0) {
+ dev_err(priv->dev, "unable to allocate device number");
+ goto failed_alloc_chrdev;
+ }
+ cdev_init(&priv->rpivid_mem_cdev, &rpivid_mem_fops);
+ priv->rpivid_mem_cdev.owner = THIS_MODULE;
+- err = cdev_add(&priv->rpivid_mem_cdev, priv->devid, 1);
++ err = cdev_add(&priv->rpivid_mem_cdev, priv->devid, 2);
+ if (err != 0) {
+ dev_err(priv->dev, "unable to register device");
+ goto failed_cdev_add;
+@@ -194,6 +194,20 @@ static int rpivid_mem_probe(struct platf
+ if (IS_ERR(ptr_err))
+ goto failed_device_create;
+
++ /* Legacy alias */
++ {
++ char *oldname = kstrdup(priv->name, GFP_KERNEL);
++
++ oldname[1] = 'a';
++ oldname[2] = 'r';
++ oldname[3] = 'g';
++ oldname[4] = 'o';
++ oldname[5] = 'n';
++ (void)device_create(priv->class, NULL, priv->devid + 1, NULL,
++ oldname + 1);
++ kfree(oldname);
++ }
++
+ dev_info(priv->dev, "%s initialised: Registers at 0x%08lx length 0x%08lx",
+ priv->name, priv->regs_phys, priv->mem_window_len);
+
--- /dev/null
+From ae90a6635a8f8d2265999b9374d490da1fe3bf9c Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Thu, 1 Aug 2019 16:41:20 +0100
+Subject: [PATCH 731/773] hid: usb: Add device quirks for Freeway Airmouse T3
+ and MX3
+
+These wireless mouse/keyboard combo remote control devices specify
+multiple "wheel" events in their report descriptors. The wheel events
+are incorrectly defined and apparently map to accelerometer data, leading
+to spurious mouse scroll events being generated at an extreme rate when
+the device is moved.
+
+As a workaround, use HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE to mask
+feeding the extra wheel events to the input subsystem.
+
+See: https://github.com/raspberrypi/firmware/issues/1189
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/hid/hid-ids.h | 6 ++++++
+ drivers/hid/hid-quirks.c | 2 ++
+ 2 files changed, 8 insertions(+)
+
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -222,6 +222,9 @@
+ #define USB_VENDOR_ID_BAANTO 0x2453
+ #define USB_DEVICE_ID_BAANTO_MT_190W2 0x0100
+
++#define USB_VENDOR_ID_BEKEN 0x25a7
++#define USB_DEVICE_ID_AIRMOUSE_T3 0x2402
++
+ #define USB_VENDOR_ID_BELKIN 0x050d
+ #define USB_DEVICE_ID_FLIP_KVM 0x3201
+
+@@ -1187,6 +1190,9 @@
+ #define USB_VENDOR_ID_XAT 0x2505
+ #define USB_DEVICE_ID_XAT_CSR 0x0220
+
++#define USB_VENDOR_ID_XENTA 0x1d57
++#define USB_DEVICE_ID_AIRMOUSE_MX3 0xad03
++
+ #define USB_VENDOR_ID_XIN_MO 0x16c0
+ #define USB_DEVICE_ID_XIN_MO_DUAL_ARCADE 0x05e1
+ #define USB_DEVICE_ID_THT_2P_ARCADE 0x75e1
+--- a/drivers/hid/hid-quirks.c
++++ b/drivers/hid/hid-quirks.c
+@@ -43,6 +43,7 @@ static const struct hid_device_id hid_qu
+ { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682), HID_QUIRK_NOGET },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692), HID_QUIRK_NOGET },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM), HID_QUIRK_NOGET },
++ { HID_USB_DEVICE(USB_VENDOR_ID_BEKEN, USB_DEVICE_ID_AIRMOUSE_T3), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH), HID_QUIRK_MULTI_INPUT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE2), HID_QUIRK_ALWAYS_POLL },
+@@ -172,6 +173,7 @@ static const struct hid_device_id hid_qu
+ { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
++ { HID_USB_DEVICE(USB_VENDOR_ID_XENTA, USB_DEVICE_ID_AIRMOUSE_MX3), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+
+ { 0 }
+ };
--- /dev/null
+From d59aba5dd2232295486e4fc4f3843b8a47596f3f Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Fri, 14 Jun 2019 10:12:07 +0100
+Subject: [PATCH 732/773] drm/vc4: Add "Broadcast RGB" connector property
+
+Some HDMI monitors do not abide by the full or limited
+(16-235) range RGB flags in the AVI infoframe. This can
+result in images looking washed out (if given limited and
+interpreting as full), or detail disappearing at the extremes
+(given full and interpreting as limited).
+
+Copy the Intel i915 driver's approach of adding an override
+property ("Broadcast RGB") to force one mode or the other.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 190 +++++++++++++++++++++++--
+ 1 file changed, 177 insertions(+), 13 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -285,6 +285,13 @@ to_vc4_fkms_encoder(struct drm_encoder *
+ return container_of(encoder, struct vc4_fkms_encoder, base);
+ }
+
++/* "Broadcast RGB" property.
++ * Allows overriding of HDMI full or limited range RGB
++ */
++#define VC4_BROADCAST_RGB_AUTO 0
++#define VC4_BROADCAST_RGB_FULL 1
++#define VC4_BROADCAST_RGB_LIMITED 2
++
+ /* VC4 FKMS connector KMS struct */
+ struct vc4_fkms_connector {
+ struct drm_connector base;
+@@ -297,6 +304,8 @@ struct vc4_fkms_connector {
+ struct vc4_dev *vc4_dev;
+ u32 display_number;
+ u32 display_type;
++
++ struct drm_property *broadcast_rgb_property;
+ };
+
+ static inline struct vc4_fkms_connector *
+@@ -305,6 +314,16 @@ to_vc4_fkms_connector(struct drm_connect
+ return container_of(connector, struct vc4_fkms_connector, base);
+ }
+
++/* VC4 FKMS connector state */
++struct vc4_fkms_connector_state {
++ struct drm_connector_state base;
++
++ int broadcast_rgb;
++};
++
++#define to_vc4_fkms_connector_state(x) \
++ container_of(x, struct vc4_fkms_connector_state, base)
++
+ static u32 vc4_get_display_type(u32 display_number)
+ {
+ const u32 display_types[] = {
+@@ -832,8 +851,6 @@ static void vc4_crtc_mode_set_nofb(struc
+ mode->picture_aspect_ratio, mode->flags);
+ 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;
+@@ -871,11 +888,30 @@ static void vc4_crtc_mode_set_nofb(struc
+ break;
+ }
+
+- if (!vc4_encoder->hdmi_monitor)
++ if (!vc4_encoder->hdmi_monitor) {
+ mb.timings.flags |= TIMINGS_FLAGS_DVI;
+- else if (drm_default_rgb_quant_range(mode) ==
++ mb.timings.video_id_code = frame.avi.video_code;
++ } else {
++ struct vc4_fkms_connector_state *conn_state =
++ to_vc4_fkms_connector_state(vc4_crtc->connector->state);
++
++ /* Do not provide a VIC as the HDMI spec requires that we do not
++ * signal the opposite of the defined range in the AVI
++ * infoframe.
++ */
++ mb.timings.video_id_code = 0;
++
++ if (conn_state->broadcast_rgb == VC4_BROADCAST_RGB_AUTO) {
++ /* See CEA-861-E - 5.1 Default Encoding Parameters */
++ if (drm_default_rgb_quant_range(mode) ==
+ HDMI_QUANTIZATION_RANGE_LIMITED)
+- mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
++ mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
++ } else {
++ if (conn_state->broadcast_rgb ==
++ VC4_BROADCAST_RGB_LIMITED)
++ mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
++ }
++ }
+
+ /*
+ FIXME: To implement
+@@ -1340,13 +1376,95 @@ static void vc4_fkms_connector_destroy(s
+ drm_connector_cleanup(connector);
+ }
+
++/**
++ * vc4_connector_duplicate_state - duplicate connector state
++ * @connector: digital connector
++ *
++ * Allocates and returns a copy of the connector state (both common and
++ * digital connector specific) for the specified connector.
++ *
++ * Returns: The newly allocated connector state, or NULL on failure.
++ */
++struct drm_connector_state *
++vc4_connector_duplicate_state(struct drm_connector *connector)
++{
++ struct vc4_fkms_connector_state *state;
++
++ state = kmemdup(connector->state, sizeof(*state), GFP_KERNEL);
++ if (!state)
++ return NULL;
++
++ __drm_atomic_helper_connector_duplicate_state(connector, &state->base);
++ return &state->base;
++}
++
++/**
++ * vc4_connector_atomic_get_property - hook for connector->atomic_get_property.
++ * @connector: Connector to get the property for.
++ * @state: Connector state to retrieve the property from.
++ * @property: Property to retrieve.
++ * @val: Return value for the property.
++ *
++ * Returns the atomic property value for a digital connector.
++ */
++int vc4_connector_atomic_get_property(struct drm_connector *connector,
++ const struct drm_connector_state *state,
++ struct drm_property *property,
++ uint64_t *val)
++{
++ struct vc4_fkms_connector *fkms_connector =
++ to_vc4_fkms_connector(connector);
++ struct vc4_fkms_connector_state *vc4_conn_state =
++ to_vc4_fkms_connector_state(state);
++
++ if (property == fkms_connector->broadcast_rgb_property) {
++ *val = vc4_conn_state->broadcast_rgb;
++ } else {
++ DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
++ property->base.id, property->name);
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++/**
++ * vc4_connector_atomic_set_property - hook for connector->atomic_set_property.
++ * @connector: Connector to set the property for.
++ * @state: Connector state to set the property on.
++ * @property: Property to set.
++ * @val: New value for the property.
++ *
++ * Sets the atomic property value for a digital connector.
++ */
++int vc4_connector_atomic_set_property(struct drm_connector *connector,
++ struct drm_connector_state *state,
++ struct drm_property *property,
++ uint64_t val)
++{
++ struct vc4_fkms_connector *fkms_connector =
++ to_vc4_fkms_connector(connector);
++ struct vc4_fkms_connector_state *vc4_conn_state =
++ to_vc4_fkms_connector_state(state);
++
++ if (property == fkms_connector->broadcast_rgb_property) {
++ vc4_conn_state->broadcast_rgb = val;
++ return 0;
++ }
++
++ DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
++ property->base.id, property->name);
++ return -EINVAL;
++}
++
+ static const struct drm_connector_funcs vc4_fkms_connector_funcs = {
+ .detect = vc4_fkms_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = vc4_fkms_connector_destroy,
+- .reset = drm_atomic_helper_connector_reset,
+- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
++ .atomic_duplicate_state = vc4_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
++ .atomic_get_property = vc4_connector_atomic_get_property,
++ .atomic_set_property = vc4_connector_atomic_set_property,
+ };
+
+ static const struct drm_connector_helper_funcs vc4_fkms_connector_helper_funcs = {
+@@ -1359,12 +1477,40 @@ static const struct drm_connector_helper
+ .best_encoder = vc4_fkms_connector_best_encoder,
+ };
+
++static const struct drm_prop_enum_list broadcast_rgb_names[] = {
++ { VC4_BROADCAST_RGB_AUTO, "Automatic" },
++ { VC4_BROADCAST_RGB_FULL, "Full" },
++ { VC4_BROADCAST_RGB_LIMITED, "Limited 16:235" },
++};
++
++static void
++vc4_attach_broadcast_rgb_property(struct vc4_fkms_connector *fkms_connector)
++{
++ struct drm_device *dev = fkms_connector->base.dev;
++ struct drm_property *prop;
++
++ prop = fkms_connector->broadcast_rgb_property;
++ if (!prop) {
++ prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
++ "Broadcast RGB",
++ broadcast_rgb_names,
++ ARRAY_SIZE(broadcast_rgb_names));
++ if (!prop)
++ return;
++
++ fkms_connector->broadcast_rgb_property = prop;
++ }
++
++ drm_object_attach_property(&fkms_connector->base.base, prop, 0);
++}
++
+ static struct drm_connector *
+ vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
+ u32 display_num)
+ {
+ struct drm_connector *connector = NULL;
+ struct vc4_fkms_connector *fkms_connector;
++ struct vc4_fkms_connector_state *conn_state = NULL;
+ struct vc4_dev *vc4_dev = to_vc4_dev(dev);
+ int ret = 0;
+
+@@ -1373,9 +1519,18 @@ vc4_fkms_connector_init(struct drm_devic
+ fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector),
+ GFP_KERNEL);
+ if (!fkms_connector) {
+- ret = -ENOMEM;
+- goto fail;
++ return ERR_PTR(-ENOMEM);
++ }
++
++ /*
++ * Allocate enough memory to hold vc4_fkms_connector_state,
++ */
++ conn_state = kzalloc(sizeof(*conn_state), GFP_KERNEL);
++ if (!conn_state) {
++ kfree(fkms_connector);
++ return ERR_PTR(-ENOMEM);
+ }
++
+ connector = &fkms_connector->base;
+
+ fkms_connector->encoder = encoder;
+@@ -1383,6 +1538,9 @@ vc4_fkms_connector_init(struct drm_devic
+ fkms_connector->display_type = vc4_get_display_type(display_num);
+ fkms_connector->vc4_dev = vc4_dev;
+
++ __drm_atomic_helper_connector_reset(connector,
++ &conn_state->base);
++
+ if (fkms_connector->display_type == DRM_MODE_ENCODER_DSI) {
+ drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+@@ -1403,10 +1561,14 @@ 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);
++ /* Create and attach TV margin props to this connector.
++ * Already done for SDTV outputs.
++ */
++ if (fkms_connector->display_type != DRM_MODE_ENCODER_TVDAC) {
++ ret = drm_mode_create_tv_margin_properties(dev);
++ if (ret)
++ goto fail;
++ }
+
+ drm_connector_attach_tv_margin_properties(connector);
+
+@@ -1415,6 +1577,8 @@ vc4_fkms_connector_init(struct drm_devic
+
+ connector->doublescan_allowed = 0;
+
++ vc4_attach_broadcast_rgb_property(fkms_connector);
++
+ drm_connector_attach_encoder(connector, encoder);
+
+ return connector;
--- /dev/null
+From 0e3126a6288c7816c30075369332ccf5f614f2dc Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:48 +0200
+Subject: [PATCH 733/773] drm/connector: Add documentation for drm_cmdline_mode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit 772cd52c5574b04b00a97d638b2cfe94c0c1a9b6 upstream.
+
+The struct drm_cmdline_mode holds the result of the command line parsers.
+However, it wasn't documented so far, so let's do that.
+
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/963c893c16c6a25fc469b53c726f493d99bdc578.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ include/drm/drm_connector.h | 86 ++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 84 insertions(+), 2 deletions(-)
+
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -755,18 +755,100 @@ struct drm_connector_funcs {
+ const struct drm_connector_state *state);
+ };
+
+-/* mode specified on the command line */
++/**
++ * struct drm_cmdline_mode - DRM Mode passed through the kernel command-line
++ *
++ * Each connector can have an initial mode with additional options
++ * passed through the kernel command line. This structure allows to
++ * express those parameters and will be filled by the command-line
++ * parser.
++ */
+ struct drm_cmdline_mode {
++ /**
++ * @specified:
++ *
++ * Has a mode been read from the command-line?
++ */
+ bool specified;
++
++ /**
++ * @refresh_specified:
++ *
++ * Did the mode have a preferred refresh rate?
++ */
+ bool refresh_specified;
++
++ /**
++ * @bpp_specified:
++ *
++ * Did the mode have a preferred BPP?
++ */
+ bool bpp_specified;
+- int xres, yres;
++
++ /**
++ * @xres:
++ *
++ * Active resolution on the X axis, in pixels.
++ */
++ int xres;
++
++ /**
++ * @yres:
++ *
++ * Active resolution on the Y axis, in pixels.
++ */
++ int yres;
++
++ /**
++ * @bpp:
++ *
++ * Bits per pixels for the mode.
++ */
+ int bpp;
++
++ /**
++ * @refresh:
++ *
++ * Refresh rate, in Hertz.
++ */
+ int refresh;
++
++ /**
++ * @rb:
++ *
++ * Do we need to use reduced blanking?
++ */
+ bool rb;
++
++ /**
++ * @interlace:
++ *
++ * The mode is interlaced.
++ */
+ bool interlace;
++
++ /**
++ * @cvt:
++ *
++ * The timings will be calculated using the VESA Coordinated
++ * Video Timings instead of looking up the mode from a table.
++ */
+ bool cvt;
++
++ /**
++ * @margins:
++ *
++ * Add margins to the mode calculation (1.8% of xres rounded
++ * down to 8 pixels and 1.8% of yres).
++ */
+ bool margins;
++
++ /**
++ * @force:
++ *
++ * Ignore the hotplug state of the connector, and force its
++ * state to one of the DRM_FORCE_* values.
++ */
+ enum drm_connector_force force;
+ };
+
--- /dev/null
+From c9a5e3181442ca4558c8c1ca4438b153b87a1b3f Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:49 +0200
+Subject: [PATCH 734/773] drm/modes: Rewrite the command line parser
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit e08ab74bd4c7a5fe311bc05f32dbb4f1e7fa3428 upstream.
+
+Rewrite the command line parser in order to get away from the state machine
+parsing the video mode lines.
+
+Hopefully, this will allow to extend it more easily to support named modes
+and / or properties set directly on the command line.
+
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/e32cd4009153b184103554009135c7bf7c9975d7.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ drivers/gpu/drm/drm_modes.c | 325 +++++++++++++++++++++++-------------
+ 1 file changed, 210 insertions(+), 115 deletions(-)
+
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -30,6 +30,7 @@
+ * authorization from the copyright holder(s) and author(s).
+ */
+
++#include <linux/ctype.h>
+ #include <linux/list.h>
+ #include <linux/list_sort.h>
+ #include <linux/export.h>
+@@ -1414,6 +1415,151 @@ void drm_connector_list_update(struct dr
+ }
+ EXPORT_SYMBOL(drm_connector_list_update);
+
++static int drm_mode_parse_cmdline_bpp(const char *str, char **end_ptr,
++ struct drm_cmdline_mode *mode)
++{
++ unsigned int bpp;
++
++ if (str[0] != '-')
++ return -EINVAL;
++
++ str++;
++ bpp = simple_strtol(str, end_ptr, 10);
++ if (*end_ptr == str)
++ return -EINVAL;
++
++ mode->bpp = bpp;
++ mode->bpp_specified = true;
++
++ return 0;
++}
++
++static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
++ struct drm_cmdline_mode *mode)
++{
++ unsigned int refresh;
++
++ if (str[0] != '@')
++ return -EINVAL;
++
++ str++;
++ refresh = simple_strtol(str, end_ptr, 10);
++ if (*end_ptr == str)
++ return -EINVAL;
++
++ mode->refresh = refresh;
++ mode->refresh_specified = true;
++
++ return 0;
++}
++
++static int drm_mode_parse_cmdline_extra(const char *str, int length,
++ struct drm_connector *connector,
++ struct drm_cmdline_mode *mode)
++{
++ int i;
++
++ for (i = 0; i < length; i++) {
++ switch (str[i]) {
++ case 'i':
++ mode->interlace = true;
++ break;
++ case 'm':
++ mode->margins = true;
++ break;
++ case 'D':
++ if (mode->force != DRM_FORCE_UNSPECIFIED)
++ return -EINVAL;
++
++ if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
++ (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
++ mode->force = DRM_FORCE_ON;
++ else
++ mode->force = DRM_FORCE_ON_DIGITAL;
++ break;
++ case 'd':
++ if (mode->force != DRM_FORCE_UNSPECIFIED)
++ return -EINVAL;
++
++ mode->force = DRM_FORCE_OFF;
++ break;
++ case 'e':
++ if (mode->force != DRM_FORCE_UNSPECIFIED)
++ return -EINVAL;
++
++ mode->force = DRM_FORCE_ON;
++ break;
++ default:
++ return -EINVAL;
++ }
++ }
++
++ return 0;
++}
++
++static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
++ bool extras,
++ struct drm_connector *connector,
++ struct drm_cmdline_mode *mode)
++{
++ const char *str_start = str;
++ bool rb = false, cvt = false;
++ int xres = 0, yres = 0;
++ int remaining, i;
++ char *end_ptr;
++
++ xres = simple_strtol(str, &end_ptr, 10);
++ if (end_ptr == str)
++ return -EINVAL;
++
++ if (end_ptr[0] != 'x')
++ return -EINVAL;
++ end_ptr++;
++
++ str = end_ptr;
++ yres = simple_strtol(str, &end_ptr, 10);
++ if (end_ptr == str)
++ return -EINVAL;
++
++ remaining = length - (end_ptr - str_start);
++ if (remaining < 0)
++ return -EINVAL;
++
++ for (i = 0; i < remaining; i++) {
++ switch (end_ptr[i]) {
++ case 'M':
++ cvt = true;
++ break;
++ case 'R':
++ rb = true;
++ break;
++ default:
++ /*
++ * Try to pass that to our extras parsing
++ * function to handle the case where the
++ * extras are directly after the resolution
++ */
++ if (extras) {
++ int ret = drm_mode_parse_cmdline_extra(end_ptr + i,
++ 1,
++ connector,
++ mode);
++ if (ret)
++ return ret;
++ } else {
++ return -EINVAL;
++ }
++ }
++ }
++
++ mode->xres = xres;
++ mode->yres = yres;
++ mode->cvt = cvt;
++ mode->rb = rb;
++
++ return 0;
++}
++
+ /**
+ * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
+ * @mode_option: optional per connector mode option
+@@ -1440,13 +1586,12 @@ bool drm_mode_parse_command_line_for_con
+ struct drm_cmdline_mode *mode)
+ {
+ const char *name;
+- unsigned int namelen;
+- bool res_specified = false, bpp_specified = false, refresh_specified = false;
+- unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
+- bool yres_specified = false, cvt = false, rb = false;
+- bool interlace = false, margins = false, was_digit = false;
+- int i;
+- enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
++ bool parse_extras = false;
++ unsigned int bpp_off = 0, refresh_off = 0;
++ unsigned int mode_end = 0;
++ char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
++ char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
++ int ret;
+
+ #ifdef CONFIG_FB
+ if (!mode_option)
+@@ -1459,127 +1604,77 @@ bool drm_mode_parse_command_line_for_con
+ }
+
+ name = mode_option;
+- namelen = strlen(name);
+- for (i = namelen-1; i >= 0; i--) {
+- switch (name[i]) {
+- case '@':
+- if (!refresh_specified && !bpp_specified &&
+- !yres_specified && !cvt && !rb && was_digit) {
+- refresh = simple_strtol(&name[i+1], NULL, 10);
+- refresh_specified = true;
+- was_digit = false;
+- } else
+- goto done;
+- break;
+- case '-':
+- if (!bpp_specified && !yres_specified && !cvt &&
+- !rb && was_digit) {
+- bpp = simple_strtol(&name[i+1], NULL, 10);
+- bpp_specified = true;
+- was_digit = false;
+- } else
+- goto done;
+- break;
+- case 'x':
+- if (!yres_specified && was_digit) {
+- yres = simple_strtol(&name[i+1], NULL, 10);
+- yres_specified = true;
+- was_digit = false;
+- } else
+- goto done;
+- break;
+- case '0' ... '9':
+- was_digit = true;
+- break;
+- case 'M':
+- if (yres_specified || cvt || was_digit)
+- goto done;
+- cvt = true;
+- break;
+- case 'R':
+- if (yres_specified || cvt || rb || was_digit)
+- goto done;
+- rb = true;
+- break;
+- case 'm':
+- if (cvt || yres_specified || was_digit)
+- goto done;
+- margins = true;
+- break;
+- case 'i':
+- if (cvt || yres_specified || was_digit)
+- goto done;
+- interlace = true;
+- break;
+- case 'e':
+- if (yres_specified || bpp_specified || refresh_specified ||
+- was_digit || (force != DRM_FORCE_UNSPECIFIED))
+- goto done;
+
+- force = DRM_FORCE_ON;
+- break;
+- case 'D':
+- if (yres_specified || bpp_specified || refresh_specified ||
+- was_digit || (force != DRM_FORCE_UNSPECIFIED))
+- goto done;
++ if (!isdigit(name[0]))
++ return false;
+
+- if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
+- (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
+- force = DRM_FORCE_ON;
+- else
+- force = DRM_FORCE_ON_DIGITAL;
+- break;
+- case 'd':
+- if (yres_specified || bpp_specified || refresh_specified ||
+- was_digit || (force != DRM_FORCE_UNSPECIFIED))
+- goto done;
++ /* Try to locate the bpp and refresh specifiers, if any */
++ bpp_ptr = strchr(name, '-');
++ if (bpp_ptr) {
++ bpp_off = bpp_ptr - name;
++ mode->bpp_specified = true;
++ }
+
+- force = DRM_FORCE_OFF;
+- break;
+- default:
+- goto done;
+- }
++ refresh_ptr = strchr(name, '@');
++ if (refresh_ptr) {
++ refresh_off = refresh_ptr - name;
++ mode->refresh_specified = true;
+ }
+
+- if (i < 0 && yres_specified) {
+- char *ch;
+- xres = simple_strtol(name, &ch, 10);
+- if ((ch != NULL) && (*ch == 'x'))
+- res_specified = true;
+- else
+- i = ch - name;
+- } else if (!yres_specified && was_digit) {
+- /* catch mode that begins with digits but has no 'x' */
+- i = 0;
+- }
+-done:
+- if (i >= 0) {
+- pr_warn("[drm] parse error at position %i in video mode '%s'\n",
+- i, name);
+- mode->specified = false;
+- return false;
++ /* Locate the end of the name / resolution, and parse it */
++ if (bpp_ptr && refresh_ptr) {
++ mode_end = min(bpp_off, refresh_off);
++ } else if (bpp_ptr) {
++ mode_end = bpp_off;
++ } else if (refresh_ptr) {
++ mode_end = refresh_off;
++ } else {
++ mode_end = strlen(name);
++ parse_extras = true;
+ }
+
+- if (res_specified) {
+- mode->specified = true;
+- mode->xres = xres;
+- mode->yres = yres;
++ ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
++ parse_extras,
++ connector,
++ mode);
++ if (ret)
++ return false;
++ mode->specified = true;
++
++ if (bpp_ptr) {
++ ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode);
++ if (ret)
++ return false;
+ }
+
+- if (refresh_specified) {
+- mode->refresh_specified = true;
+- mode->refresh = refresh;
++ if (refresh_ptr) {
++ ret = drm_mode_parse_cmdline_refresh(refresh_ptr,
++ &refresh_end_ptr, mode);
++ if (ret)
++ return false;
+ }
+
+- if (bpp_specified) {
+- mode->bpp_specified = true;
+- mode->bpp = bpp;
++ /*
++ * Locate the end of the bpp / refresh, and parse the extras
++ * if relevant
++ */
++ if (bpp_ptr && refresh_ptr)
++ extra_ptr = max(bpp_end_ptr, refresh_end_ptr);
++ else if (bpp_ptr)
++ extra_ptr = bpp_end_ptr;
++ else if (refresh_ptr)
++ extra_ptr = refresh_end_ptr;
++
++ if (extra_ptr) {
++ int remaining = strlen(name) - (extra_ptr - name);
++
++ /*
++ * We still have characters to process, while
++ * we shouldn't have any
++ */
++ if (remaining > 0)
++ return false;
+ }
+- mode->rb = rb;
+- mode->cvt = cvt;
+- mode->interlace = interlace;
+- mode->margins = margins;
+- mode->force = force;
+
+ return true;
+ }
--- /dev/null
+From aec195ba9d647eb9e70e77c68c04e073a7c0e75e Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:50 +0200
+Subject: [PATCH 735/773] drm/modes: Support modes names on the command line
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit 3aeeb13d899627fe2b86bdbdcd0927cf7192234f upstream.
+Minor conflict resolution as upstream has moved functions
+from drm_fb_helper.c to a new drm_client_modeset.c
+
+The drm subsystem also uses the video= kernel parameter, and in the
+documentation refers to the fbdev documentation for that parameter.
+
+However, that documentation also says that instead of giving the mode using
+its resolution we can also give a name. However, DRM doesn't handle that
+case at the moment. Even though in most case it shouldn't make any
+difference, it might be useful for analog modes, where different standards
+might have the same resolution, but still have a few different parameters
+that are not encoded in the modes (NTSC vs NTSC-J vs PAL-M for example).
+
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/18443e0c3bdbbd16cea4ec63bc7f2079b820b43b.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ drivers/gpu/drm/drm_connector.c | 3 +-
+ drivers/gpu/drm/drm_fb_helper.c | 4 +++
+ drivers/gpu/drm/drm_modes.c | 62 ++++++++++++++++++++++++---------
+ include/drm/drm_connector.h | 7 ++++
+ 4 files changed, 59 insertions(+), 17 deletions(-)
+
+--- a/drivers/gpu/drm/drm_connector.c
++++ b/drivers/gpu/drm/drm_connector.c
+@@ -135,8 +135,9 @@ static void drm_connector_get_cmdline_mo
+ connector->force = mode->force;
+ }
+
+- DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
++ DRM_DEBUG_KMS("cmdline mode for connector %s %s %dx%d@%dHz%s%s%s\n",
+ connector->name,
++ mode->name ? mode->name : "",
+ mode->xres, mode->yres,
+ mode->refresh_specified ? mode->refresh : 60,
+ mode->rb ? " reduced blanking" : "",
+--- a/drivers/gpu/drm/drm_fb_helper.c
++++ b/drivers/gpu/drm/drm_fb_helper.c
+@@ -2099,6 +2099,10 @@ struct drm_display_mode *drm_pick_cmdlin
+ prefer_non_interlace = !cmdline_mode->interlace;
+ again:
+ list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
++ /* Check (optional) mode name first */
++ if (!strcmp(mode->name, cmdline_mode->name))
++ return mode;
++
+ /* check width/height */
+ if (mode->hdisplay != cmdline_mode->xres ||
+ mode->vdisplay != cmdline_mode->yres)
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1586,7 +1586,7 @@ bool drm_mode_parse_command_line_for_con
+ struct drm_cmdline_mode *mode)
+ {
+ const char *name;
+- bool parse_extras = false;
++ bool named_mode = false, parse_extras = false;
+ unsigned int bpp_off = 0, refresh_off = 0;
+ unsigned int mode_end = 0;
+ char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
+@@ -1605,8 +1605,22 @@ bool drm_mode_parse_command_line_for_con
+
+ name = mode_option;
+
+- if (!isdigit(name[0]))
+- return false;
++ /*
++ * This is a bit convoluted. To differentiate between the
++ * named modes and poorly formatted resolutions, we need a
++ * bunch of things:
++ * - We need to make sure that the first character (which
++ * would be our resolution in X) is a digit.
++ * - However, if the X resolution is missing, then we end up
++ * with something like x<yres>, with our first character
++ * being an alpha-numerical character, which would be
++ * considered a named mode.
++ *
++ * If this isn't enough, we should add more heuristics here,
++ * and matching unit-tests.
++ */
++ if (!isdigit(name[0]) && name[0] != 'x')
++ named_mode = true;
+
+ /* Try to locate the bpp and refresh specifiers, if any */
+ bpp_ptr = strchr(name, '-');
+@@ -1617,6 +1631,9 @@ bool drm_mode_parse_command_line_for_con
+
+ refresh_ptr = strchr(name, '@');
+ if (refresh_ptr) {
++ if (named_mode)
++ return false;
++
+ refresh_off = refresh_ptr - name;
+ mode->refresh_specified = true;
+ }
+@@ -1633,12 +1650,16 @@ bool drm_mode_parse_command_line_for_con
+ parse_extras = true;
+ }
+
+- ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
+- parse_extras,
+- connector,
+- mode);
+- if (ret)
+- return false;
++ if (named_mode) {
++ strncpy(mode->name, name, mode_end);
++ } else {
++ ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
++ parse_extras,
++ connector,
++ mode);
++ if (ret)
++ return false;
++ }
+ mode->specified = true;
+
+ if (bpp_ptr) {
+@@ -1666,14 +1687,23 @@ bool drm_mode_parse_command_line_for_con
+ extra_ptr = refresh_end_ptr;
+
+ if (extra_ptr) {
+- int remaining = strlen(name) - (extra_ptr - name);
++ if (!named_mode) {
++ int len = strlen(name) - (extra_ptr - name);
+
+- /*
+- * We still have characters to process, while
+- * we shouldn't have any
+- */
+- if (remaining > 0)
+- return false;
++ ret = drm_mode_parse_cmdline_extra(extra_ptr, len,
++ connector, mode);
++ if (ret)
++ return false;
++ } else {
++ int remaining = strlen(name) - (extra_ptr - name);
++
++ /*
++ * We still have characters to process, while
++ * we shouldn't have any
++ */
++ if (remaining > 0)
++ return false;
++ }
+ }
+
+ return true;
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -765,6 +765,13 @@ struct drm_connector_funcs {
+ */
+ struct drm_cmdline_mode {
+ /**
++ * @name:
++ *
++ * Name of the mode.
++ */
++ char name[DRM_DISPLAY_MODE_LEN];
++
++ /**
+ * @specified:
+ *
+ * Has a mode been read from the command-line?
--- /dev/null
+From 5c884f9e2ff691d972f86677167fa2bda5c8221a Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:51 +0200
+Subject: [PATCH 736/773] drm/modes: Allow to specify rotation and reflection
+ on the commandline
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 1bf4e09227c345e246062285eba4b8fe660e512e upstream.
+Minor conflict resolution as upstream has moved functions
+from drm_fb_helper.c to a new drm_client_modeset.c
+
+Rotations and reflections setup are needed in some scenarios to initialise
+properly the initial framebuffer. Some drivers already had a bunch of
+quirks to deal with this, such as either a private kernel command line
+parameter (omapdss) or on the device tree (various panels).
+
+In order to accomodate this, let's create a video mode parameter to deal
+with the rotation and reflexion.
+
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/777da16e42db757c1f5b414b5ca34507097fed5c.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ Documentation/fb/modedb.txt | 12 ++++
+ drivers/gpu/drm/drm_fb_helper.c | 30 +++++++++
+ drivers/gpu/drm/drm_modes.c | 114 ++++++++++++++++++++++++++------
+ include/drm/drm_connector.h | 10 +++
+ 4 files changed, 146 insertions(+), 20 deletions(-)
+
+--- a/Documentation/fb/modedb.txt
++++ b/Documentation/fb/modedb.txt
+@@ -51,6 +51,18 @@ To force the VGA output to be enabled an
+ Specifying the option multiple times for different ports is possible, e.g.:
+ video=LVDS-1:d video=HDMI-1:D
+
++Options can also be passed after the mode, using commas as separator.
++
++ Sample usage: 720x480,rotate=180 - 720x480 mode, rotated by 180 degrees
++
++Valid options are:
++
++ - reflect_x (boolean): Perform an axial symmetry on the X axis
++ - reflect_y (boolean): Perform an axial symmetry on the Y axis
++ - rotate (integer): Rotate the initial framebuffer by x
++ degrees. Valid values are 0, 90, 180 and 270.
++
++
+ ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo *****
+
+ What is the VESA(TM) Coordinated Video Timings (CVT)?
+--- a/drivers/gpu/drm/drm_fb_helper.c
++++ b/drivers/gpu/drm/drm_fb_helper.c
+@@ -2464,6 +2464,7 @@ static void drm_setup_crtc_rotation(stru
+ struct drm_connector *connector)
+ {
+ struct drm_plane *plane = fb_crtc->mode_set.crtc->primary;
++ struct drm_cmdline_mode *cmdline;
+ uint64_t valid_mask = 0;
+ int i, rotation;
+
+@@ -2483,6 +2484,35 @@ static void drm_setup_crtc_rotation(stru
+ rotation = DRM_MODE_ROTATE_0;
+ }
+
++ /**
++ * The panel already defined the default rotation
++ * through its orientation. Whatever has been provided
++ * on the command line needs to be added to that.
++ *
++ * Unfortunately, the rotations are at different bit
++ * indices, so the math to add them up are not as
++ * trivial as they could.
++ *
++ * Reflections on the other hand are pretty trivial to deal with, a
++ * simple XOR between the two handle the addition nicely.
++ */
++ cmdline = &connector->cmdline_mode;
++ if (cmdline->specified) {
++ unsigned int cmdline_rest, panel_rest;
++ unsigned int cmdline_rot, panel_rot;
++ unsigned int sum_rot, sum_rest;
++
++ panel_rot = ilog2(rotation & DRM_MODE_ROTATE_MASK);
++ cmdline_rot = ilog2(cmdline->rotation_reflection & DRM_MODE_ROTATE_MASK);
++ sum_rot = (panel_rot + cmdline_rot) % 4;
++
++ panel_rest = rotation & ~DRM_MODE_ROTATE_MASK;
++ cmdline_rest = cmdline->rotation_reflection & ~DRM_MODE_ROTATE_MASK;
++ sum_rest = panel_rest ^ cmdline_rest;
++
++ rotation = (1 << sum_rot) | sum_rest;
++ }
++
+ /*
+ * TODO: support 90 / 270 degree hardware rotation,
+ * depending on the hardware this may require the framebuffer
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1560,6 +1560,71 @@ static int drm_mode_parse_cmdline_res_mo
+ return 0;
+ }
+
++static int drm_mode_parse_cmdline_options(char *str, size_t len,
++ struct drm_connector *connector,
++ struct drm_cmdline_mode *mode)
++{
++ unsigned int rotation = 0;
++ char *sep = str;
++
++ while ((sep = strchr(sep, ','))) {
++ char *delim, *option;
++
++ option = sep + 1;
++ delim = strchr(option, '=');
++ if (!delim) {
++ delim = strchr(option, ',');
++
++ if (!delim)
++ delim = str + len;
++ }
++
++ if (!strncmp(option, "rotate", delim - option)) {
++ const char *value = delim + 1;
++ unsigned int deg;
++
++ deg = simple_strtol(value, &sep, 10);
++
++ /* Make sure we have parsed something */
++ if (sep == value)
++ return -EINVAL;
++
++ switch (deg) {
++ case 0:
++ rotation |= DRM_MODE_ROTATE_0;
++ break;
++
++ case 90:
++ rotation |= DRM_MODE_ROTATE_90;
++ break;
++
++ case 180:
++ rotation |= DRM_MODE_ROTATE_180;
++ break;
++
++ case 270:
++ rotation |= DRM_MODE_ROTATE_270;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++ } else if (!strncmp(option, "reflect_x", delim - option)) {
++ rotation |= DRM_MODE_REFLECT_X;
++ sep = delim;
++ } else if (!strncmp(option, "reflect_y", delim - option)) {
++ rotation |= DRM_MODE_REFLECT_Y;
++ sep = delim;
++ } else {
++ return -EINVAL;
++ }
++ }
++
++ mode->rotation_reflection = rotation;
++
++ return 0;
++}
++
+ /**
+ * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
+ * @mode_option: optional per connector mode option
+@@ -1575,6 +1640,10 @@ static int drm_mode_parse_cmdline_res_mo
+ *
+ * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
+ *
++ * Additionals options can be provided following the mode, using a comma to
++ * separate each option. Valid options can be found in
++ * Documentation/fb/modedb.txt.
++ *
+ * The intermediate drm_cmdline_mode structure is required to store additional
+ * options from the command line modline like the force-enable/disable flag.
+ *
+@@ -1587,9 +1656,10 @@ bool drm_mode_parse_command_line_for_con
+ {
+ const char *name;
+ bool named_mode = false, parse_extras = false;
+- unsigned int bpp_off = 0, refresh_off = 0;
++ unsigned int bpp_off = 0, refresh_off = 0, options_off = 0;
+ unsigned int mode_end = 0;
+ char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
++ char *options_ptr = NULL;
+ char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
+ int ret;
+
+@@ -1638,13 +1708,18 @@ bool drm_mode_parse_command_line_for_con
+ mode->refresh_specified = true;
+ }
+
++ /* Locate the start of named options */
++ options_ptr = strchr(name, ',');
++ if (options_ptr)
++ options_off = options_ptr - name;
++
+ /* Locate the end of the name / resolution, and parse it */
+- if (bpp_ptr && refresh_ptr) {
+- mode_end = min(bpp_off, refresh_off);
+- } else if (bpp_ptr) {
++ if (bpp_ptr) {
+ mode_end = bpp_off;
+ } else if (refresh_ptr) {
+ mode_end = refresh_off;
++ } else if (options_ptr) {
++ mode_end = options_off;
+ } else {
+ mode_end = strlen(name);
+ parse_extras = true;
+@@ -1686,24 +1761,23 @@ bool drm_mode_parse_command_line_for_con
+ else if (refresh_ptr)
+ extra_ptr = refresh_end_ptr;
+
+- if (extra_ptr) {
+- if (!named_mode) {
+- int len = strlen(name) - (extra_ptr - name);
+-
+- ret = drm_mode_parse_cmdline_extra(extra_ptr, len,
+- connector, mode);
+- if (ret)
+- return false;
+- } else {
+- int remaining = strlen(name) - (extra_ptr - name);
++ if (extra_ptr &&
++ extra_ptr != options_ptr) {
++ int len = strlen(name) - (extra_ptr - name);
+
+- /*
+- * We still have characters to process, while
+- * we shouldn't have any
+- */
+- if (remaining > 0)
+- return false;
+- }
++ ret = drm_mode_parse_cmdline_extra(extra_ptr, len,
++ connector, mode);
++ if (ret)
++ return false;
++ }
++
++ if (options_ptr) {
++ int len = strlen(name) - (options_ptr - name);
++
++ ret = drm_mode_parse_cmdline_options(options_ptr, len,
++ connector, mode);
++ if (ret)
++ return false;
+ }
+
+ return true;
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -857,6 +857,16 @@ struct drm_cmdline_mode {
+ * state to one of the DRM_FORCE_* values.
+ */
+ enum drm_connector_force force;
++
++ /**
++ * @rotation_reflection:
++ *
++ * Initial rotation and reflection of the mode setup from the
++ * command line. See DRM_MODE_ROTATE_* and
++ * DRM_MODE_REFLECT_*. The only rotations supported are
++ * DRM_MODE_ROTATE_0 and DRM_MODE_ROTATE_180.
++ */
++ unsigned int rotation_reflection;
+ };
+
+ /**
--- /dev/null
+From 4b97b05ce469797c0e16e5e164dc6a0dae7f520b Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:51 +0200
+Subject: [PATCH 737/773] drm/connector: Introduce a TV margins structure
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 22045e8e52bd802f743f0471242782fc3b479707 upstream.
+
+The TV margins has been defined as a structure inside the
+drm_connector_state structure so far. However, we will need it in other
+structures as well, so let's move that structure definition so that it can
+be reused.
+
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/38b773b03f15ec7a135cdf8f7db669e5ada20cf2.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ include/drm/drm_connector.h | 41 +++++++++++++++++++++++++++----------
+ 1 file changed, 30 insertions(+), 11 deletions(-)
+
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -344,13 +344,37 @@ int drm_display_info_set_bus_formats(str
+ unsigned int num_formats);
+
+ /**
++ * struct drm_connector_tv_margins - TV connector related margins
++ *
++ * Describes the margins in pixels to put around the image on TV
++ * connectors to deal with overscan.
++ */
++struct drm_connector_tv_margins {
++ /**
++ * @bottom: Bottom margin in pixels.
++ */
++ unsigned int bottom;
++
++ /**
++ * @left: Left margin in pixels.
++ */
++ unsigned int left;
++
++ /**
++ * @right: Right margin in pixels.
++ */
++ unsigned int right;
++
++ /**
++ * @top: Top margin in pixels.
++ */
++ unsigned int top;
++};
++
++/**
+ * struct drm_tv_connector_state - TV connector related states
+ * @subconnector: selected subconnector
+- * @margins: margins (all margins are expressed in pixels)
+- * @margins.left: left margin
+- * @margins.right: right margin
+- * @margins.top: top margin
+- * @margins.bottom: bottom margin
++ * @margins: TV margins
+ * @mode: TV mode
+ * @brightness: brightness in percent
+ * @contrast: contrast in percent
+@@ -361,12 +385,7 @@ int drm_display_info_set_bus_formats(str
+ */
+ struct drm_tv_connector_state {
+ enum drm_mode_subconnector subconnector;
+- struct {
+- unsigned int left;
+- unsigned int right;
+- unsigned int top;
+- unsigned int bottom;
+- } margins;
++ struct drm_connector_tv_margins margins;
+ unsigned int mode;
+ unsigned int brightness;
+ unsigned int contrast;
--- /dev/null
+From 31205d1091f42eb6c9efc38243fd473c29ae1537 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:51 +0200
+Subject: [PATCH 738/773] drm/modes: Parse overscan properties
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 3d46a3007cd8f73bae502bf5c171977b91d7aacc upstream.
+
+Properly configuring the overscan properties might be needed for the
+initial setup of the framebuffer for display that still have overscan.
+Let's allow for more properties on the kernel command line to setup each
+margin.
+
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/e481f1628e3768ca49226ec2115cfa4dfcbd5e4c.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ Documentation/fb/modedb.txt | 2 ++
+ drivers/gpu/drm/drm_modes.c | 44 +++++++++++++++++++++++++++++++++++++
+ include/drm/drm_connector.h | 5 +++++
+ 3 files changed, 51 insertions(+)
+
+--- a/Documentation/fb/modedb.txt
++++ b/Documentation/fb/modedb.txt
+@@ -57,6 +57,8 @@ Options can also be passed after the mod
+
+ Valid options are:
+
++ - margin_top, margin_bottom, margin_left, margin_right (integer):
++ Number of pixels in the margins, typically to deal with overscan on TVs
+ - reflect_x (boolean): Perform an axial symmetry on the X axis
+ - reflect_y (boolean): Perform an axial symmetry on the Y axis
+ - rotate (integer): Rotate the initial framebuffer by x
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1615,6 +1615,50 @@ static int drm_mode_parse_cmdline_option
+ } else if (!strncmp(option, "reflect_y", delim - option)) {
+ rotation |= DRM_MODE_REFLECT_Y;
+ sep = delim;
++ } else if (!strncmp(option, "margin_right", delim - option)) {
++ const char *value = delim + 1;
++ unsigned int margin;
++
++ margin = simple_strtol(value, &sep, 10);
++
++ /* Make sure we have parsed something */
++ if (sep == value)
++ return -EINVAL;
++
++ mode->tv_margins.right = margin;
++ } else if (!strncmp(option, "margin_left", delim - option)) {
++ const char *value = delim + 1;
++ unsigned int margin;
++
++ margin = simple_strtol(value, &sep, 10);
++
++ /* Make sure we have parsed something */
++ if (sep == value)
++ return -EINVAL;
++
++ mode->tv_margins.left = margin;
++ } else if (!strncmp(option, "margin_top", delim - option)) {
++ const char *value = delim + 1;
++ unsigned int margin;
++
++ margin = simple_strtol(value, &sep, 10);
++
++ /* Make sure we have parsed something */
++ if (sep == value)
++ return -EINVAL;
++
++ mode->tv_margins.top = margin;
++ } else if (!strncmp(option, "margin_bottom", delim - option)) {
++ const char *value = delim + 1;
++ unsigned int margin;
++
++ margin = simple_strtol(value, &sep, 10);
++
++ /* Make sure we have parsed something */
++ if (sep == value)
++ return -EINVAL;
++
++ mode->tv_margins.bottom = margin;
+ } else {
+ return -EINVAL;
+ }
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -886,6 +886,11 @@ struct drm_cmdline_mode {
+ * DRM_MODE_ROTATE_0 and DRM_MODE_ROTATE_180.
+ */
+ unsigned int rotation_reflection;
++
++ /**
++ * @tv_margins: TV margins to apply to the mode.
++ */
++ struct drm_connector_tv_margins tv_margins;
+ };
+
+ /**
--- /dev/null
+From deec13c32eadba904622dd65e8ed0a8c641e4c83 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:52 +0200
+Subject: [PATCH 739/773] drm/atomic: Add a function to reset connector TV
+ properties
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 731514b446fe6748d5a55a3dff202efb45c7d8df upstream.
+Reworked as functions have been moved from drm_atomic_helper.[c|h]
+to drm_atomic_state_helper.[c|h].
+
+During the connector reset, if that connector has a TV property, it needs
+to be reset to the value provided on the command line.
+
+Provide a helper to do that.
+
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/84a7b657f09303a2850e1cc79e68f623547f3fdd.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ drivers/gpu/drm/drm_atomic_helper.c | 18 ++++++++++++++++++
+ include/drm/drm_atomic_helper.h | 1 +
+ 2 files changed, 19 insertions(+)
+
+--- a/drivers/gpu/drm/drm_atomic_helper.c
++++ b/drivers/gpu/drm/drm_atomic_helper.c
+@@ -3737,6 +3737,24 @@ void drm_atomic_helper_connector_reset(s
+ EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
+
+ /**
++ * drm_atomic_helper_connector_tv_reset - Resets TV connector properties
++ * @connector: DRM connector
++ *
++ * Resets the TV-related properties attached to a connector.
++ */
++void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
++{
++ struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
++ struct drm_connector_state *state = connector->state;
++
++ state->tv.margins.left = cmdline->tv_margins.left;
++ state->tv.margins.right = cmdline->tv_margins.right;
++ state->tv.margins.top = cmdline->tv_margins.top;
++ state->tv.margins.bottom = cmdline->tv_margins.bottom;
++}
++EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
++
++/**
+ * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
+ * @connector: connector object
+ * @state: atomic connector state
+--- a/include/drm/drm_atomic_helper.h
++++ b/include/drm/drm_atomic_helper.h
+@@ -168,6 +168,7 @@ void drm_atomic_helper_plane_destroy_sta
+ void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
+ struct drm_connector_state *conn_state);
+ void drm_atomic_helper_connector_reset(struct drm_connector *connector);
++void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector);
+ void
+ __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
+ struct drm_connector_state *state);
--- /dev/null
+From f5b8fc2a73c5f7d5bc64ec5a9e3019372a0ac4fb Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@bootlin.com>
+Date: Wed, 19 Jun 2019 12:17:53 +0200
+Subject: [PATCH 740/773] drm/vc4: hdmi: Set default state margin at reset
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Now that the TV margins are properly parsed and filled into
+drm_cmdline_mode, we just need to initialise the first state at reset to
+get those values and start using them.
+
+Acked-by: Eric Anholt <eric@anholt.net>
+Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/44e24172e300be6a41578517021ef6a6e90ed682.1560783090.git-series.maxime.ripard@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -292,11 +292,17 @@ static int vc4_hdmi_connector_get_modes(
+ return ret;
+ }
+
++static void vc4_hdmi_connector_reset(struct drm_connector *connector)
++{
++ drm_atomic_helper_connector_reset(connector);
++ drm_atomic_helper_connector_tv_reset(connector);
++}
++
+ static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
+ .detect = vc4_hdmi_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = vc4_hdmi_connector_destroy,
+- .reset = drm_atomic_helper_connector_reset,
++ .reset = vc4_hdmi_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+ };
--- /dev/null
+From 6eb133cbb462898a897b5206ac0ce75eebf43c3f Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 23 Jul 2019 11:09:26 +0100
+Subject: [PATCH 741/773] drm/vc4: fkms: Set default state margin at reset
+
+Now that the TV margins are properly parsed and filled into
+drm_cmdline_mode, we just need to initialise the first state at reset to
+get those values and start using them.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -1457,10 +1457,17 @@ int vc4_connector_atomic_set_property(st
+ return -EINVAL;
+ }
+
++static void vc4_hdmi_connector_reset(struct drm_connector *connector)
++{
++ drm_atomic_helper_connector_reset(connector);
++ drm_atomic_helper_connector_tv_reset(connector);
++}
++
+ static const struct drm_connector_funcs vc4_fkms_connector_funcs = {
+ .detect = vc4_fkms_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = vc4_fkms_connector_destroy,
++ .reset = vc4_hdmi_connector_reset,
+ .atomic_duplicate_state = vc4_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+ .atomic_get_property = vc4_connector_atomic_get_property,
--- /dev/null
+From 2c5f444ed22474f3c61a3d242d67b6aa6c523009 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 23 Jul 2019 14:10:31 +0100
+Subject: [PATCH 742/773] drm/modes: Don't apply cmdline's rotation if it
+ wasn't specified
+
+Taken from the dri-devel mailing list (11/7/2019) to fixup the cmdline
+parsing, but requires changes as things have moved between 4.19 and 5.2.
+
+From: Dmitry Osipenko <digetx@gmail.com>
+
+The rotation mode from cmdline shouldn't be taken into account if it
+wasn't specified in the cmdline. This fixes ignored default display
+orientation when display mode is given using cmdline without the
+rotation being specified.
+
+Fixes: 1bf4e09227c3 ("drm/modes: Allow to specify rotation and reflection on the commandline")
+Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/drm_fb_helper.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/drm_fb_helper.c
++++ b/drivers/gpu/drm/drm_fb_helper.c
+@@ -2497,7 +2497,7 @@ static void drm_setup_crtc_rotation(stru
+ * simple XOR between the two handle the addition nicely.
+ */
+ cmdline = &connector->cmdline_mode;
+- if (cmdline->specified) {
++ if (cmdline->specified && cmdline->rotation_reflection) {
+ unsigned int cmdline_rest, panel_rest;
+ unsigned int cmdline_rot, panel_rot;
+ unsigned int sum_rot, sum_rest;
--- /dev/null
+From 80bd4ddd5332820668f6ab7aa8e76ddd2e9c1083 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Tue, 23 Jul 2019 14:14:05 +0100
+Subject: [PATCH 743/773] configs: Add CONFIG_FRAMEBUFFER_CONSOLE_ROTATION to
+ Pi configs
+
+To allow for console rotation under DRM (where the firmware
+can't lie about geometry), add FRAMEBUFFER_CONSOLE_ROTATION
+so that the kernel can do it.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ 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
+@@ -935,6 +935,7 @@ CONFIG_FB_RPISENSE=m
+ CONFIG_BACKLIGHT_RPI=m
+ CONFIG_BACKLIGHT_GPIO=m
+ CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+ CONFIG_LOGO=y
+ # CONFIG_LOGO_LINUX_MONO is not set
+ # CONFIG_LOGO_LINUX_VGA16 is not set
+--- a/arch/arm/configs/bcm2711_defconfig
++++ b/arch/arm/configs/bcm2711_defconfig
+@@ -946,6 +946,7 @@ CONFIG_FB_RPISENSE=m
+ CONFIG_BACKLIGHT_RPI=m
+ CONFIG_BACKLIGHT_GPIO=m
+ CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+ CONFIG_LOGO=y
+ # CONFIG_LOGO_LINUX_MONO is not set
+ # CONFIG_LOGO_LINUX_VGA16 is not set
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -927,6 +927,7 @@ CONFIG_FB_RPISENSE=m
+ CONFIG_BACKLIGHT_RPI=m
+ CONFIG_BACKLIGHT_GPIO=m
+ CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+ CONFIG_LOGO=y
+ # CONFIG_LOGO_LINUX_MONO is not set
+ # CONFIG_LOGO_LINUX_VGA16 is not set
--- /dev/null
+From 25f880ad558d2738fa88825124afc5b342777d6f Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Thu, 18 Jul 2019 17:07:05 +0800
+Subject: [PATCH 744/773] staging: bcm2835-codec: switch to multi-planar API
+
+There are two APIs for mem2mem devices, the older single-planar API and
+the newer multi-planar one. Without making things overly complex, the
+driver can only support one or the other. However the userspace libv4l2
+library has a plugin that allows multi-planar API devices to service
+single-planar consumers.
+
+Chromium supports the multi-planar API exclusively, though this is
+currently limited to ChromiumOS. It would be possible to add support
+for generic Linux.
+
+Switching to the multi-planar API would allow usage of both APIs from
+userspace.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c | 145 +++++++++---------
+ 1 file changed, 76 insertions(+), 69 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -504,7 +504,7 @@ static struct bcm2835_codec_fmt *find_fo
+
+ for (k = 0; k < fmts->num_entries; k++) {
+ fmt = &fmts->list[k];
+- if (fmt->fourcc == f->fmt.pix.pixelformat)
++ if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
+ break;
+ }
+ if (k == fmts->num_entries)
+@@ -522,9 +522,9 @@ static struct bcm2835_codec_q_data *get_
+ enum v4l2_buf_type type)
+ {
+ switch (type) {
+- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
++ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ return &ctx->q_data[V4L2_M2M_SRC];
+- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ return &ctx->q_data[V4L2_M2M_DST];
+ default:
+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
+@@ -541,9 +541,9 @@ static struct vchiq_mmal_port *get_port_
+ return NULL;
+
+ switch (type) {
+- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
++ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ return &ctx->component->input[0];
+- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ return &ctx->component->output[0];
+ default:
+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
+@@ -752,7 +752,7 @@ static void handle_fmt_changed(struct bc
+ 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 = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ 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;
+@@ -945,7 +945,7 @@ static int vidioc_querycap(struct file *
+ 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->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ return 0;
+ }
+@@ -996,16 +996,20 @@ static int vidioc_g_fmt(struct bcm2835_c
+
+ 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;
++ f->fmt.pix_mp.width = q_data->crop_width;
++ f->fmt.pix_mp.height = q_data->height;
++ f->fmt.pix_mp.pixelformat = q_data->fmt->fourcc;
++ f->fmt.pix_mp.field = V4L2_FIELD_NONE;
++ f->fmt.pix_mp.colorspace = ctx->colorspace;
++ f->fmt.pix_mp.plane_fmt[0].sizeimage = q_data->sizeimage;
++ f->fmt.pix_mp.plane_fmt[0].bytesperline = q_data->bytesperline;
++ f->fmt.pix_mp.num_planes = 1;
++ f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc;
++ f->fmt.pix_mp.quantization = ctx->quant;
++ f->fmt.pix_mp.xfer_func = ctx->xfer_func;
++
++ memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
++ sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
+
+ return 0;
+ }
+@@ -1029,17 +1033,17 @@ static int vidioc_try_fmt(struct bcm2835
+ * 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 (f->fmt.pix_mp.width > MAX_W)
++ f->fmt.pix_mp.width = MAX_W;
++ if (f->fmt.pix_mp.height > MAX_H)
++ f->fmt.pix_mp.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;
++ if (f->fmt.pix_mp.width < MIN_W)
++ f->fmt.pix_mp.width = MIN_W;
++ if (f->fmt.pix_mp.height < MIN_H)
++ f->fmt.pix_mp.height = MIN_H;
+
+ /*
+ * For codecs the buffer must have a vertical alignment of 16
+@@ -1048,16 +1052,18 @@ static int vidioc_try_fmt(struct bcm2835
+ * some of the pixels are active.
+ */
+ if (ctx->dev->role != ISP)
+- f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
++ f->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.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.width,
+- f->fmt.pix.height,
+- fmt);
++ f->fmt.pix_mp.num_planes = 1;
++ f->fmt.pix_mp.plane_fmt[0].bytesperline =
++ get_bytesperline(f->fmt.pix_mp.width, fmt);
++ f->fmt.pix_mp.plane_fmt[0].sizeimage =
++ get_sizeimage(f->fmt.pix_mp.plane_fmt[0].bytesperline,
++ f->fmt.pix_mp.width, f->fmt.pix_mp.height, fmt);
++ memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
++ sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
+
+- f->fmt.pix.field = V4L2_FIELD_NONE;
++ f->fmt.pix_mp.field = V4L2_FIELD_NONE;
+
+ return 0;
+ }
+@@ -1070,8 +1076,8 @@ static int vidioc_try_fmt_vid_cap(struct
+
+ fmt = find_format(f, ctx->dev, true);
+ if (!fmt) {
+- f->fmt.pix.pixelformat = get_default_format(ctx->dev,
+- true)->fourcc;
++ f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev,
++ true)->fourcc;
+ fmt = find_format(f, ctx->dev, true);
+ }
+
+@@ -1086,13 +1092,13 @@ static int vidioc_try_fmt_vid_out(struct
+
+ fmt = find_format(f, ctx->dev, false);
+ if (!fmt) {
+- f->fmt.pix.pixelformat = get_default_format(ctx->dev,
+- false)->fourcc;
++ f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev,
++ false)->fourcc;
+ fmt = find_format(f, ctx->dev, false);
+ }
+
+- if (!f->fmt.pix.colorspace)
+- f->fmt.pix.colorspace = ctx->colorspace;
++ if (!f->fmt.pix_mp.colorspace)
++ f->fmt.pix_mp.colorspace = ctx->colorspace;
+
+ return vidioc_try_fmt(ctx, f, fmt);
+ }
+@@ -1106,9 +1112,10 @@ static int vidioc_s_fmt(struct bcm2835_c
+ 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);
++ 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_mp.width, f->fmt.pix_mp.height,
++ f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.plane_fmt[0].sizeimage);
++
+
+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+ if (!vq)
+@@ -1124,9 +1131,9 @@ static int vidioc_s_fmt(struct bcm2835_c
+ }
+
+ 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;
++ f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
++ q_data->crop_width = f->fmt.pix_mp.width;
++ q_data->height = f->fmt.pix_mp.height;
+ if (!q_data->selection_set)
+ q_data->crop_height = requested_height;
+
+@@ -1134,21 +1141,21 @@ static int vidioc_s_fmt(struct bcm2835_c
+ * 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;
++ ctx->colorspace = f->fmt.pix_mp.colorspace;
++ ctx->xfer_func = f->fmt.pix_mp.xfer_func;
++ ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
++ ctx->quant = f->fmt.pix_mp.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;
++ q_data->bytesperline = f->fmt.pix_mp.plane_fmt[0].bytesperline;
++ q_data->sizeimage = f->fmt.pix_mp.plane_fmt[0].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->role == DECODE &&
+ q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
+- f->fmt.pix.width && f->fmt.pix.height) {
++ q_data->crop_width && q_data->height) {
+ /*
+ * On the decoder, if provided with a resolution on the input
+ * side, then replicate that to the output side.
+@@ -1165,7 +1172,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+ q_data_dst->height = ALIGN(q_data->crop_height, 16);
+
+ q_data_dst->bytesperline =
+- get_bytesperline(f->fmt.pix.width, q_data_dst->fmt);
++ get_bytesperline(f->fmt.pix_mp.width, q_data_dst->fmt);
+ q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
+ q_data_dst->crop_width,
+ q_data_dst->height,
+@@ -1215,7 +1222,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+ {
+- unsigned int height = f->fmt.pix.height;
++ unsigned int height = f->fmt.pix_mp.height;
+ int ret;
+
+ ret = vidioc_try_fmt_vid_cap(file, priv, f);
+@@ -1228,7 +1235,7 @@ static int vidioc_s_fmt_vid_cap(struct f
+ static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_format *f)
+ {
+- unsigned int height = f->fmt.pix.height;
++ unsigned int height = f->fmt.pix_mp.height;
+ int ret;
+
+ ret = vidioc_try_fmt_vid_out(file, priv, f);
+@@ -1244,7 +1251,7 @@ static int vidioc_g_selection(struct fil
+ {
+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
+ struct bcm2835_codec_q_data *q_data;
+- bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
++ bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
+ true : false;
+
+ if ((ctx->dev->role == DECODE && !capture_queue) ||
+@@ -1307,7 +1314,7 @@ static int vidioc_s_selection(struct fil
+ {
+ 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 ?
++ bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
+ 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",
+@@ -1368,7 +1375,7 @@ static int vidioc_s_parm(struct file *fi
+ {
+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
+
+- if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
++ if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ return -EINVAL;
+
+ ctx->framerate_num =
+@@ -1738,15 +1745,15 @@ static int vidioc_encoder_cmd(struct fil
+ 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_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap,
++ .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap,
++ .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap,
++ .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap,
++
++ .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out,
++ .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out,
++ .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out,
++ .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out,
+
+ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+@@ -2089,7 +2096,7 @@ static int bcm2835_codec_start_streaming
+ ctx->component_enabled = true;
+ }
+
+- if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
++ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ /*
+ * Create the EOS buffer.
+ * We only need the MMAL part, and want to NOT attach a memory
+@@ -2216,7 +2223,7 @@ static int queue_init(void *priv, struct
+ struct bcm2835_codec_ctx *ctx = priv;
+ int ret;
+
+- src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
++ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+ src_vq->drv_priv = ctx;
+ src_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
+@@ -2230,7 +2237,7 @@ static int queue_init(void *priv, struct
+ if (ret)
+ return ret;
+
+- dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+ dst_vq->drv_priv = ctx;
+ dst_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
--- /dev/null
+From bf7f91921fd94c1599b515fa8a94197bad3a294b Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 22 Jul 2019 22:13:30 +0800
+Subject: [PATCH 745/773] staging: bcm2835-codec: implement
+ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE
+
+The stateful decoder specification shows an optional step for retrieving
+the miminum number of capture buffers required for the decoder to
+proceed. While not a required parameter, having it makes some
+applications happy.
+
+bcm2835-codec is a little different from other decoder implementations
+in that there is an intermediate format conversion between the hardware
+and V4L2 buffers. The number of capture buffers required is therefore
+independent of the stream and DPB etc.
+
+There are plans to remove the conversion, but it requires a fair amount
+of rework within the firmware. Until that is done, simply return a value
+of 1.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.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
+@@ -2357,6 +2357,18 @@ static int bcm2835_codec_open(struct fil
+ }
+ ctx->fh.ctrl_handler = hdl;
+ v4l2_ctrl_handler_setup(hdl);
++ } else if (dev->role == DECODE) {
++ v4l2_ctrl_handler_init(hdl, 1);
++
++ v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
++ 1, 1, 1, 1);
++ 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);
--- /dev/null
+From f0c7dafd823a7b5fc53566f51baaceaf7663ddcc Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 22 Jul 2019 22:20:55 +0800
+Subject: [PATCH 746/773] staging: bcm2835-codec: set device_caps in struct
+ video_device
+
+Instead of filling in the struct v4l2_capability device_caps
+field, fill in the struct video_device device_caps field.
+
+That way the V4L2 core knows what the capabilities of the
+video device are.
+
+This is similar to a cleanup series by Hans Verkuil [1].
+
+[1] https://www.spinics.net/lists/linux-media/msg153313.html
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+---
+ .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -945,8 +945,6 @@ static int vidioc_querycap(struct file *
+ 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_MPLANE | V4L2_CAP_STREAMING;
+- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ return 0;
+ }
+
+@@ -2600,6 +2598,7 @@ static int bcm2835_codec_create(struct p
+ vfd = &dev->vfd;
+ vfd->lock = &dev->dev_mutex;
+ vfd->v4l2_dev = &dev->v4l2_dev;
++ vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+
+ switch (role) {
+ case DECODE:
--- /dev/null
+From fdda86a2f220d10e5feeeb19972142da1694cb40 Mon Sep 17 00:00:00 2001
+From: James Hughes <james.hughes@raspberrypi.org>
+Date: Tue, 16 Jul 2019 12:18:21 +0100
+Subject: [PATCH 747/773] Add HDMI1 facility to the driver.
+
+For generic ALSA, all you need is the bcm2835.h change, but
+have also added structures for IEC958 HDMI. Not sure how to
+test those.
+---
+ .../vc04_services/bcm2835-audio/bcm2835.c | 29 ++++++++++++++++---
+ .../vc04_services/bcm2835-audio/bcm2835.h | 4 ++-
+ 2 files changed, 28 insertions(+), 5 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -79,7 +79,11 @@ static int bcm2835_audio_alsa_newpcm(str
+ if (err)
+ return err;
+
+- err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI", 1, 0, 1, true);
++ err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI", 1, AUDIO_DEST_HDMI0, 1, true);
++ if (err)
++ return err;
++
++ err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI1", 2, AUDIO_DEST_HDMI1, 1, true);
+ if (err)
+ return err;
+
+@@ -106,7 +110,7 @@ static struct bcm2835_audio_driver bcm28
+ .newctl = snd_bcm2835_new_ctl,
+ };
+
+-static struct bcm2835_audio_driver bcm2835_audio_hdmi = {
++static struct bcm2835_audio_driver bcm2835_audio_hdmi0 = {
+ .driver = {
+ .name = "bcm2835_hdmi",
+ .owner = THIS_MODULE,
+@@ -116,7 +120,20 @@ static struct bcm2835_audio_driver bcm28
+ .minchannels = 1,
+ .newpcm = bcm2835_audio_simple_newpcm,
+ .newctl = snd_bcm2835_new_hdmi_ctl,
+- .route = AUDIO_DEST_HDMI
++ .route = AUDIO_DEST_HDMI0
++};
++
++static struct bcm2835_audio_driver bcm2835_audio_hdmi1 = {
++ .driver = {
++ .name = "bcm2835_hdmi",
++ .owner = THIS_MODULE,
++ },
++ .shortname = "bcm2835 HDMI 1",
++ .longname = "bcm2835 HDMI 1",
++ .minchannels = 1,
++ .newpcm = bcm2835_audio_simple_newpcm,
++ .newctl = snd_bcm2835_new_hdmi_ctl,
++ .route = AUDIO_DEST_HDMI1
+ };
+
+ static struct bcm2835_audio_driver bcm2835_audio_headphones = {
+@@ -143,7 +160,11 @@ static struct bcm2835_audio_drivers chil
+ .is_enabled = &enable_compat_alsa,
+ },
+ {
+- .audio_driver = &bcm2835_audio_hdmi,
++ .audio_driver = &bcm2835_audio_hdmi0,
++ .is_enabled = &enable_hdmi,
++ },
++ {
++ .audio_driver = &bcm2835_audio_hdmi1,
+ .is_enabled = &enable_hdmi,
+ },
+ {
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+@@ -33,7 +33,9 @@ enum {
+ enum snd_bcm2835_route {
+ AUDIO_DEST_AUTO = 0,
+ AUDIO_DEST_HEADPHONES = 1,
+- AUDIO_DEST_HDMI = 2,
++ AUDIO_DEST_HDMI = 2, // for backwards compatibility.
++ AUDIO_DEST_HDMI0 = 2,
++ AUDIO_DEST_HDMI1 = 3,
+ AUDIO_DEST_MAX,
+ };
+
--- /dev/null
+From 73d2665f0756435e50bb94039a28d47f6134bcb9 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 5 Aug 2019 14:17:14 +0100
+Subject: [PATCH 748/773] overlays: Add baudrate parameter to i2c3-i2c6
+
+The overlays for enabling the new BCM2711 I2C interfaces were lacking
+the means to configure the baud/clock rate.
+
+Also explictly set the default pins, rather than relying on the values
+in the base DTB.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README | 8 ++++++++
+ arch/arm/boot/dts/overlays/i2c3-overlay.dts | 15 ++++++++++++---
+ arch/arm/boot/dts/overlays/i2c4-overlay.dts | 15 ++++++++++++---
+ arch/arm/boot/dts/overlays/i2c5-overlay.dts | 15 ++++++++++++---
+ arch/arm/boot/dts/overlays/i2c6-overlay.dts | 15 ++++++++++++---
+ 5 files changed, 56 insertions(+), 12 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1221,6 +1221,8 @@ 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)
++ baudrate Set the baudrate for the interface (default
++ "100000")
+
+
+ Name: i2c4
+@@ -1228,6 +1230,8 @@ 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)
++ baudrate Set the baudrate for the interface (default
++ "100000")
+
+
+ Name: i2c5
+@@ -1235,6 +1239,8 @@ 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)
++ baudrate Set the baudrate for the interface (default
++ "100000")
+
+
+ Name: i2c6
+@@ -1242,6 +1248,8 @@ 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)
++ baudrate Set the baudrate for the interface (default
++ "100000")
+
+
+ Name: i2s-gpio28-31
+--- a/arch/arm/boot/dts/overlays/i2c3-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c3-overlay.dts
+@@ -6,10 +6,11 @@
+
+ fragment@0 {
+ target = <&i2c3>;
+- __overlay__ {
++ frag0: __overlay__ {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c3_pins>;
++ clock-frequency = <100000>;
+ };
+ };
+
+@@ -20,8 +21,16 @@
+ };
+ };
+
++ fragment@2 {
++ target = <&i2c3_pins>;
++ __overlay__ {
++ brcm,pins = <4 5>;
++ };
++ };
++
+ __overrides__ {
+- pins_2_3 = <0>,"=1";
+- pins_4_5 = <0>,"!1";
++ pins_2_3 = <0>,"=1!2";
++ pins_4_5 = <0>,"!1=2";
++ baudrate = <&frag0>, "clock-frequency:0";
+ };
+ };
+--- a/arch/arm/boot/dts/overlays/i2c4-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c4-overlay.dts
+@@ -6,10 +6,11 @@
+
+ fragment@0 {
+ target = <&i2c4>;
+- __overlay__ {
++ frag0: __overlay__ {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c4_pins>;
++ clock-frequency = <100000>;
+ };
+ };
+
+@@ -20,8 +21,16 @@
+ };
+ };
+
++ fragment@2 {
++ target = <&i2c4_pins>;
++ __overlay__ {
++ brcm,pins = <8 9>;
++ };
++ };
++
+ __overrides__ {
+- pins_6_7 = <0>,"=1";
+- pins_8_9 = <0>,"!1";
++ pins_6_7 = <0>,"=1!2";
++ pins_8_9 = <0>,"!1=2";
++ baudrate = <&frag0>, "clock-frequency:0";
+ };
+ };
+--- a/arch/arm/boot/dts/overlays/i2c5-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c5-overlay.dts
+@@ -6,10 +6,11 @@
+
+ fragment@0 {
+ target = <&i2c5>;
+- __overlay__ {
++ frag0: __overlay__ {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c5_pins>;
++ clock-frequency = <100000>;
+ };
+ };
+
+@@ -20,8 +21,16 @@
+ };
+ };
+
++ fragment@2 {
++ target = <&i2c5_pins>;
++ __overlay__ {
++ brcm,pins = <12 13>;
++ };
++ };
++
+ __overrides__ {
+- pins_10_11 = <0>,"=1";
+- pins_12_13 = <0>,"!1";
++ pins_10_11 = <0>,"=1!2";
++ pins_12_13 = <0>,"!1=2";
++ baudrate = <&frag0>, "clock-frequency:0";
+ };
+ };
+--- a/arch/arm/boot/dts/overlays/i2c6-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c6-overlay.dts
+@@ -6,10 +6,11 @@
+
+ fragment@0 {
+ target = <&i2c6>;
+- __overlay__ {
++ frag0: __overlay__ {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c6_pins>;
++ clock-frequency = <100000>;
+ };
+ };
+
+@@ -20,8 +21,16 @@
+ };
+ };
+
++ fragment@2 {
++ target = <&i2c6_pins>;
++ __overlay__ {
++ brcm,pins = <22 23>;
++ };
++ };
++
+ __overrides__ {
+- pins_0_1 = <0>,"=1";
+- pins_22_23 = <0>,"!1";
++ pins_0_1 = <0>,"=1!2";
++ pins_22_23 = <0>,"!1=2";
++ baudrate = <&frag0>, "clock-frequency:0";
+ };
+ };
--- /dev/null
+From 29109f495f5842f4e9a09ffb54ae3e13298fff07 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 2 Aug 2019 22:25:27 +0100
+Subject: [PATCH 749/773] net: bcmgenet: Workaround for Pi 4B network issue
+
+Some combinations of Pi 4Bs and Ethernet switches don't reliably get a
+DCHP-assigned IP address, leaving the unit with a self=assigned 169.254
+address.
+
+Forcing renegotiation has been found to be an effective workaround, so
+add an automatic renegotiation after the link comes up for the first
+time; enable it with genet.force_reneg=y - by default it is disabled.
+
+See: https://github.com/raspberrypi/linux/issues/3108
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ .../net/ethernet/broadcom/genet/bcmgenet.c | 22 +++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+@@ -72,6 +72,10 @@
+ #define GENET_RDMA_REG_OFF (priv->hw_params->rdma_offset + \
+ TOTAL_DESC * DMA_DESC_SIZE)
+
++static bool force_reneg = false;
++module_param(force_reneg, bool, 0444);
++MODULE_PARM_DESC(force_reneg, "Force a renegotiation after the initial link-up");
++
+ static inline void bcmgenet_writel(u32 value, void __iomem *offset)
+ {
+ /* MIPS chips strapped for BE will automagically configure the
+@@ -2610,6 +2614,7 @@ static void bcmgenet_irq_task(struct wor
+ unsigned int status;
+ struct bcmgenet_priv *priv = container_of(
+ work, struct bcmgenet_priv, bcmgenet_irq_work);
++ static int first_link = 1;
+
+ netif_dbg(priv, intr, priv->dev, "%s\n", __func__);
+
+@@ -2622,6 +2627,23 @@ static void bcmgenet_irq_task(struct wor
+ if (status & UMAC_IRQ_LINK_EVENT) {
+ priv->dev->phydev->link = !!(status & UMAC_IRQ_LINK_UP);
+ phy_mac_interrupt(priv->dev->phydev);
++
++ if (priv->dev->phydev->link && first_link) {
++ first_link = 0;
++ /*
++ * HACK: Some Pi4Bs, when paired with some switches,
++ * come up in a strange state where they are unable to
++ * transmit, causing them to fail to get an IP address.
++ * Although the failure mechanism is not yet understood,
++ * forcing renegotiation at this point has been shown
++ * to be effective in avoiding the problem.
++ */
++ if (force_reneg) {
++ dev_info(&priv->pdev->dev,
++ "Forcing renegotiation\n");
++ genphy_restart_aneg(priv->dev->phydev);
++ }
++ }
+ }
+ }
+
--- /dev/null
+From ae0ab9791a91359d280c6a73f338fd697eb453cc Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 25 Jul 2019 17:27:44 +0100
+Subject: [PATCH 750/773] drm/vc4: Resolve the vblank warnings on mode
+ switching
+
+The details over when and how a driver is to service the
+vblank events are sketchy, and the fkms driver was triggering
+a kernel warning every time the crtc was enabled or disabled.
+
+Copy the event handling as used by the vc4-kms driver slightly
+more closely, and we avoid the warnings.
+
+https://github.com/raspberrypi/linux/issues/3020
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 48 ++++++++++++++++++--------
+ 1 file changed, 33 insertions(+), 15 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -933,6 +933,7 @@ 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_device *dev = crtc->dev;
+ struct drm_plane *plane;
+
+ DRM_DEBUG_KMS("[CRTC:%d] vblanks off.\n",
+@@ -948,6 +949,35 @@ static void vc4_crtc_disable(struct drm_
+
+ drm_atomic_crtc_for_each_plane(plane, crtc)
+ vc4_plane_atomic_disable(plane, plane->state);
++
++ /*
++ * Make sure we issue a vblank event after disabling the CRTC if
++ * someone was waiting it.
++ */
++ if (crtc->state->event) {
++ unsigned long flags;
++
++ spin_lock_irqsave(&dev->event_lock, flags);
++ drm_crtc_send_vblank_event(crtc, crtc->state->event);
++ crtc->state->event = NULL;
++ spin_unlock_irqrestore(&dev->event_lock, flags);
++ }
++}
++
++static void vc4_crtc_consume_event(struct drm_crtc *crtc)
++{
++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
++ struct drm_device *dev = crtc->dev;
++ unsigned long flags;
++
++ crtc->state->event->pipe = drm_crtc_index(crtc);
++
++ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
++
++ spin_lock_irqsave(&dev->event_lock, flags);
++ vc4_crtc->event = crtc->state->event;
++ crtc->state->event = NULL;
++ spin_unlock_irqrestore(&dev->event_lock, flags);
+ }
+
+ static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
+@@ -957,6 +987,7 @@ static void vc4_crtc_enable(struct drm_c
+ DRM_DEBUG_KMS("[CRTC:%d] vblanks on.\n",
+ crtc->base.id);
+ drm_crtc_vblank_on(crtc);
++ vc4_crtc_consume_event(crtc);
+
+ /* Unblank the planes (if they're supposed to be displayed). */
+ drm_atomic_crtc_for_each_plane(plane, crtc)
+@@ -1028,23 +1059,10 @@ static int vc4_crtc_atomic_check(struct
+ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
+ {
+- struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+- struct drm_device *dev = crtc->dev;
+-
+ DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_flush.\n",
+ crtc->base.id);
+- if (crtc->state->event) {
+- unsigned long flags;
+-
+- crtc->state->event->pipe = drm_crtc_index(crtc);
+-
+- WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+-
+- spin_lock_irqsave(&dev->event_lock, flags);
+- vc4_crtc->event = crtc->state->event;
+- crtc->state->event = NULL;
+- spin_unlock_irqrestore(&dev->event_lock, flags);
+- }
++ if (crtc->state->active && old_state->active && crtc->state->event)
++ vc4_crtc_consume_event(crtc);
+ }
+
+ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
--- /dev/null
+From 12fa5c539dd001cba73195a4a94ce08eb1834345 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 25 Jul 2019 17:34:29 +0100
+Subject: [PATCH 751/773] drm/vc4: Remove unused mode variable
+
+"89d1376 drm/vc4: Add support for margins to fkms" removed
+the requirement for having the mode structure from vc4_plane_to_mb,
+but didn't remove it as a local to the function, causing a
+compiler warning.
+
+Remove the unused variable.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -523,7 +523,6 @@ static int vc4_plane_to_mb(struct drm_pl
+ const struct vc_image_format *vc_fmt =
+ vc4_get_vc_image_fmt(drm_fmt->format);
+ 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;
--- /dev/null
+From e22301426242b180ed0511da2a0846ddc3ac802f Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 11 Jul 2019 14:57:09 +0100
+Subject: [PATCH 752/773] staging:bcm2835-codec: Expand logging on format
+ setting
+
+Adds some more useful logging during format changed events and
+s_fmt.
+
+Reported by: zillevdr <zillevdr@gmx.de>
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 10 +++++++---
+ 1 file changed, 7 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
+@@ -753,6 +753,10 @@ static void handle_fmt_changed(struct bc
+ format->es.video.color_space);
+
+ q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format was %ux%u, crop %ux%u\n",
++ __func__, q_data->bytesperline, q_data->height,
++ q_data->crop_width, q_data->crop_height);
++
+ 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;
+@@ -1110,10 +1114,10 @@ static int vidioc_s_fmt(struct bcm2835_c
+ 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",
++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: " V4L2_FOURCC_CONV ", size %u\n",
+ f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
+- f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.plane_fmt[0].sizeimage);
+-
++ V4L2_FOURCC_CONV_ARGS(f->fmt.pix_mp.pixelformat),
++ f->fmt.pix_mp.plane_fmt[0].sizeimage);
+
+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+ if (!vq)
--- /dev/null
+From f486c102af723f7de4a0f2a3426986ce574d96ee Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 11 Jul 2019 14:58:35 +0100
+Subject: [PATCH 753/773] staging: bcm2835-codec: Correct bytesperline on
+ format changed
+
+The handling of format changed events incorrectly set bytesperline
+to the cropped width, which ignored padding and formats with
+more than 8bpp.
+Fix these.
+
+Reported by: zillevdr <zillevdr@gmx.de>
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 4 +++-
+ 1 file changed, 3 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
+@@ -759,7 +759,9 @@ static void handle_fmt_changed(struct bc
+
+ 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->bytesperline = get_bytesperline(format->es.video.width,
++ q_data->fmt);
++
+ q_data->height = format->es.video.height;
+ q_data->sizeimage = format->buffer_size_min;
+ if (format->es.video.color_space)
--- /dev/null
+From 3d00cd70d91f7839ed62b283e9141dfebeda0ffc Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 7 Aug 2019 11:31:08 +0100
+Subject: [PATCH 754/773] drm/vc4: Add missing NULL check to
+ vc4_crtc_consume_event
+
+vc4_crtc_consume_event wasn't checking crtc->state->event was
+set before dereferencing it, leading to an OOPS.
+
+Fixes "a5b534b drm/vc4: Resolve the vblank warnings on mode switching"
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -969,6 +969,9 @@ static void vc4_crtc_consume_event(struc
+ struct drm_device *dev = crtc->dev;
+ unsigned long flags;
+
++ if (!crtc->state->event)
++ return;
++
+ crtc->state->event->pipe = drm_crtc_index(crtc);
+
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
--- /dev/null
+From 4c247e982b2e0f35371195241528282aade02899 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 9 Aug 2019 08:52:16 +0100
+Subject: [PATCH 755/773] Revert "net: bcmgenet: Workaround for Pi 4B network
+ issue"
+
+This reverts commit 9c0770ea7682a84a22c33410ef6870af258abacc.
+---
+ .../net/ethernet/broadcom/genet/bcmgenet.c | 22 -------------------
+ 1 file changed, 22 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+@@ -72,10 +72,6 @@
+ #define GENET_RDMA_REG_OFF (priv->hw_params->rdma_offset + \
+ TOTAL_DESC * DMA_DESC_SIZE)
+
+-static bool force_reneg = false;
+-module_param(force_reneg, bool, 0444);
+-MODULE_PARM_DESC(force_reneg, "Force a renegotiation after the initial link-up");
+-
+ static inline void bcmgenet_writel(u32 value, void __iomem *offset)
+ {
+ /* MIPS chips strapped for BE will automagically configure the
+@@ -2614,7 +2610,6 @@ static void bcmgenet_irq_task(struct wor
+ unsigned int status;
+ struct bcmgenet_priv *priv = container_of(
+ work, struct bcmgenet_priv, bcmgenet_irq_work);
+- static int first_link = 1;
+
+ netif_dbg(priv, intr, priv->dev, "%s\n", __func__);
+
+@@ -2627,23 +2622,6 @@ static void bcmgenet_irq_task(struct wor
+ if (status & UMAC_IRQ_LINK_EVENT) {
+ priv->dev->phydev->link = !!(status & UMAC_IRQ_LINK_UP);
+ phy_mac_interrupt(priv->dev->phydev);
+-
+- if (priv->dev->phydev->link && first_link) {
+- first_link = 0;
+- /*
+- * HACK: Some Pi4Bs, when paired with some switches,
+- * come up in a strange state where they are unable to
+- * transmit, causing them to fail to get an IP address.
+- * Although the failure mechanism is not yet understood,
+- * forcing renegotiation at this point has been shown
+- * to be effective in avoiding the problem.
+- */
+- if (force_reneg) {
+- dev_info(&priv->pdev->dev,
+- "Forcing renegotiation\n");
+- genphy_restart_aneg(priv->dev->phydev);
+- }
+- }
+ }
+ }
+
--- /dev/null
+From 692d62e8ae7ed39115465aac95a7737c92b07f66 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 9 Aug 2019 08:51:43 +0100
+Subject: [PATCH 756/773] net: bcmgenet: Workaround #2 for Pi4 Ethernet fail
+
+Some combinations of Pi 4Bs and Ethernet switches don't reliably get a
+DCHP-assigned IP address, leaving the unit with a self=assigned 169.254
+address. In the failure case, the Pi is left able to receive packets
+but not send them, suggesting that the MAC<->PHY link is getting into
+a bad state.
+
+It has been found empirically that skipping a reset step by the genet
+driver prevents the failures. No downsides have been discovered yet,
+and unlike the forced renegotiation it doesn't increase the time to
+get an IP address, so the workaround is enabled by default; add
+
+ genet.skip_umac_reset=n
+
+to the command line to disable it.
+
+See: https://github.com/raspberrypi/linux/issues/3108
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/net/ethernet/broadcom/genet/bcmgenet.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+@@ -72,6 +72,10 @@
+ #define GENET_RDMA_REG_OFF (priv->hw_params->rdma_offset + \
+ TOTAL_DESC * DMA_DESC_SIZE)
+
++static bool skip_umac_reset = true;
++module_param(skip_umac_reset, bool, 0444);
++MODULE_PARM_DESC(skip_umac_reset, "Skip UMAC reset step");
++
+ static inline void bcmgenet_writel(u32 value, void __iomem *offset)
+ {
+ /* MIPS chips strapped for BE will automagically configure the
+@@ -1993,6 +1997,11 @@ static void reset_umac(struct bcmgenet_p
+ bcmgenet_rbuf_ctrl_set(priv, 0);
+ udelay(10);
+
++ if (skip_umac_reset) {
++ pr_warn("Skipping UMAC reset\n");
++ return;
++ }
++
+ /* disable MAC while updating its registers */
+ bcmgenet_umac_writel(priv, 0, UMAC_CMD);
+
--- /dev/null
+From d48758030d1c09b7ce8a757637086e94a4f57968 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 3 Aug 2018 11:22:27 +0200
+Subject: [PATCH 757/773] drm/vc4: Fix TILE_Y_OFFSET definitions
+
+Y_OFFSET field starts at bit 8 not 7.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-1-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_regs.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_regs.h
++++ b/drivers/gpu/drm/vc4/vc4_regs.h
+@@ -1043,8 +1043,8 @@ enum hvs_pixel_format {
+ #define SCALER_PITCH0_TILE_LINE_DIR BIT(15)
+ #define SCALER_PITCH0_TILE_INITIAL_LINE_DIR BIT(14)
+ /* Y offset within a tile. */
+-#define SCALER_PITCH0_TILE_Y_OFFSET_MASK VC4_MASK(13, 7)
+-#define SCALER_PITCH0_TILE_Y_OFFSET_SHIFT 7
++#define SCALER_PITCH0_TILE_Y_OFFSET_MASK VC4_MASK(13, 8)
++#define SCALER_PITCH0_TILE_Y_OFFSET_SHIFT 8
+ #define SCALER_PITCH0_TILE_WIDTH_R_MASK VC4_MASK(6, 0)
+ #define SCALER_PITCH0_TILE_WIDTH_R_SHIFT 0
+
--- /dev/null
+From 8becab5374fb24f266017024d2c0650899c4ab22 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Fri, 3 Aug 2018 11:22:28 +0200
+Subject: [PATCH 758/773] drm/vc4: Define missing PITCH0_SINK_PIX field
+
+This is needed to support X/Y negative placement of planes using
+T-format buffers.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-2-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_regs.h | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_regs.h
++++ b/drivers/gpu/drm/vc4/vc4_regs.h
+@@ -1037,6 +1037,10 @@ enum hvs_pixel_format {
+ #define SCALER_TILE_HEIGHT_MASK VC4_MASK(15, 0)
+ #define SCALER_TILE_HEIGHT_SHIFT 0
+
++/* Common PITCH0 fields */
++#define SCALER_PITCH0_SINK_PIX_MASK VC4_MASK(31, 26)
++#define SCALER_PITCH0_SINK_PIX_SHIFT 26
++
+ /* PITCH0 fields for T-tiled. */
+ #define SCALER_PITCH0_TILE_WIDTH_L_MASK VC4_MASK(22, 16)
+ #define SCALER_PITCH0_TILE_WIDTH_L_SHIFT 16
--- /dev/null
+From b4bd8206c0c1e8f0cfa07c19f0b77ad2ff23d662 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Fri, 3 Aug 2018 11:22:29 +0200
+Subject: [PATCH 759/773] drm/vc4: Use drm_atomic_helper_check_plane_state() to
+ simplify the logic
+
+drm_atomic_helper_check_plane_state() takes care of checking the
+scaling capabilities and calculating the clipped X/Y offsets for us.
+
+Rely on this function instead of open-coding the logic.
+
+Incidentally, it seems to fix a problem we had with negative X/Y
+positioning of YUV planes.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-3-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_plane.c | 103 ++++++++++++++++----------------
+ 1 file changed, 52 insertions(+), 51 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_plane.c
++++ b/drivers/gpu/drm/vc4/vc4_plane.c
+@@ -313,31 +313,59 @@ static int vc4_plane_setup_clipping_and_
+ u32 subpixel_src_mask = (1 << 16) - 1;
+ u32 format = fb->format->format;
+ int num_planes = fb->format->num_planes;
+- u32 h_subsample = 1;
+- u32 v_subsample = 1;
+- int ret;
+- int i;
++ int min_scale = 1, max_scale = INT_MAX;
++ struct drm_crtc_state *crtc_state;
++ u32 h_subsample, v_subsample;
++ int i, ret;
++
++ crtc_state = drm_atomic_get_existing_crtc_state(state->state,
++ state->crtc);
++ if (!crtc_state) {
++ DRM_DEBUG_KMS("Invalid crtc state\n");
++ return -EINVAL;
++ }
++
++ /* No configuring scaling on the cursor plane, since it gets
++ * non-vblank-synced updates, and scaling requires LBM changes which
++ * have to be vblank-synced.
++ */
++ if (plane->type == DRM_PLANE_TYPE_CURSOR) {
++ min_scale = DRM_PLANE_HELPER_NO_SCALING;
++ max_scale = DRM_PLANE_HELPER_NO_SCALING;
++ } else {
++ min_scale = 1;
++ max_scale = INT_MAX;
++ }
++
++ ret = drm_atomic_helper_check_plane_state(state, crtc_state,
++ min_scale, max_scale,
++ true, true);
++ if (ret)
++ return ret;
++
++ h_subsample = drm_format_horz_chroma_subsampling(format);
++ v_subsample = drm_format_vert_chroma_subsampling(format);
+
+ for (i = 0; i < num_planes; i++)
+ vc4_state->offsets[i] = bo->paddr + fb->offsets[i];
+
+ /* We don't support subpixel source positioning for scaling. */
+- if ((state->src_x & subpixel_src_mask) ||
+- (state->src_y & subpixel_src_mask) ||
+- (state->src_w & subpixel_src_mask) ||
+- (state->src_h & subpixel_src_mask)) {
++ if ((state->src.x1 & subpixel_src_mask) ||
++ (state->src.x2 & subpixel_src_mask) ||
++ (state->src.y1 & subpixel_src_mask) ||
++ (state->src.y2 & subpixel_src_mask)) {
+ return -EINVAL;
+ }
+
+- vc4_state->src_x = state->src_x >> 16;
+- vc4_state->src_y = state->src_y >> 16;
+- vc4_state->src_w[0] = state->src_w >> 16;
+- vc4_state->src_h[0] = state->src_h >> 16;
+-
+- vc4_state->crtc_x = state->crtc_x;
+- vc4_state->crtc_y = state->crtc_y;
+- vc4_state->crtc_w = state->crtc_w;
+- vc4_state->crtc_h = state->crtc_h;
++ vc4_state->src_x = state->src.x1 >> 16;
++ vc4_state->src_y = state->src.y1 >> 16;
++ vc4_state->src_w[0] = (state->src.x2 - state->src.x1) >> 16;
++ vc4_state->src_h[0] = (state->src.y2 - state->src.y1) >> 16;
++
++ vc4_state->crtc_x = state->dst.x1;
++ vc4_state->crtc_y = state->dst.y1;
++ vc4_state->crtc_w = state->dst.x2 - state->dst.x1;
++ vc4_state->crtc_h = state->dst.y2 - state->dst.y1;
+
+ ret = vc4_plane_margins_adj(state);
+ if (ret)
+@@ -354,8 +382,6 @@ static int vc4_plane_setup_clipping_and_
+ if (num_planes > 1) {
+ vc4_state->is_yuv = true;
+
+- h_subsample = drm_format_horz_chroma_subsampling(format);
+- v_subsample = drm_format_vert_chroma_subsampling(format);
+ vc4_state->src_w[1] = vc4_state->src_w[0] / h_subsample;
+ vc4_state->src_h[1] = vc4_state->src_h[0] / v_subsample;
+
+@@ -380,39 +406,14 @@ static int vc4_plane_setup_clipping_and_
+ vc4_state->y_scaling[1] = VC4_SCALING_NONE;
+ }
+
+- /* No configuring scaling on the cursor plane, since it gets
+- non-vblank-synced updates, and scaling requires requires
+- LBM changes which have to be vblank-synced.
+- */
+- if (plane->type == DRM_PLANE_TYPE_CURSOR && !vc4_state->is_unity)
+- return -EINVAL;
+-
+- /* Clamp the on-screen start x/y to 0. The hardware doesn't
+- * support negative y, and negative x wastes bandwidth.
+- */
+- if (vc4_state->crtc_x < 0) {
+- for (i = 0; i < num_planes; i++) {
+- u32 cpp = fb->format->cpp[i];
+- u32 subs = ((i == 0) ? 1 : h_subsample);
+-
+- vc4_state->offsets[i] += (cpp *
+- (-vc4_state->crtc_x) / subs);
+- }
+- vc4_state->src_w[0] += vc4_state->crtc_x;
+- vc4_state->src_w[1] += vc4_state->crtc_x / h_subsample;
+- vc4_state->crtc_x = 0;
+- }
+-
+- if (vc4_state->crtc_y < 0) {
+- for (i = 0; i < num_planes; i++) {
+- u32 subs = ((i == 0) ? 1 : v_subsample);
+-
+- vc4_state->offsets[i] += (fb->pitches[i] *
+- (-vc4_state->crtc_y) / subs);
+- }
+- vc4_state->src_h[0] += vc4_state->crtc_y;
+- vc4_state->src_h[1] += vc4_state->crtc_y / v_subsample;
+- vc4_state->crtc_y = 0;
++ /* Adjust the base pointer to the first pixel to be scanned out. */
++ for (i = 0; i < num_planes; i++) {
++ vc4_state->offsets[i] += (vc4_state->src_y /
++ (i ? v_subsample : 1)) *
++ fb->pitches[i];
++ vc4_state->offsets[i] += (vc4_state->src_x /
++ (i ? h_subsample : 1)) *
++ fb->format->cpp[i];
+ }
+
+ return 0;
--- /dev/null
+From b371e04f38668a3dcde575879c557a5a8e348829 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Fri, 3 Aug 2018 11:22:30 +0200
+Subject: [PATCH 760/773] drm/vc4: Move ->offsets[] adjustment out of
+ setup_clipping_and_scaling()
+
+The offset adjustment depends on the framebuffer modified, so let's
+just move this operation in the DRM_FORMAT_MOD_LINEAR case inside
+vc4_plane_mode_set().
+
+This we'll be able to fix offset calculation for
+DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED and DRM_FORMAT_MOD_BROADCOM_SANDXXX.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-4-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_plane.c | 26 ++++++++++++++++----------
+ 1 file changed, 16 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_plane.c
++++ b/drivers/gpu/drm/vc4/vc4_plane.c
+@@ -406,16 +406,6 @@ static int vc4_plane_setup_clipping_and_
+ vc4_state->y_scaling[1] = VC4_SCALING_NONE;
+ }
+
+- /* Adjust the base pointer to the first pixel to be scanned out. */
+- for (i = 0; i < num_planes; i++) {
+- vc4_state->offsets[i] += (vc4_state->src_y /
+- (i ? v_subsample : 1)) *
+- fb->pitches[i];
+- vc4_state->offsets[i] += (vc4_state->src_x /
+- (i ? h_subsample : 1)) *
+- fb->format->cpp[i];
+- }
+-
+ return 0;
+ }
+
+@@ -523,6 +513,7 @@ static int vc4_plane_mode_set(struct drm
+ const struct hvs_format *format = vc4_get_hvs_format(fb->format->format);
+ u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier);
+ int num_planes = drm_format_num_planes(format->drm);
++ u32 h_subsample, v_subsample;
+ bool mix_plane_alpha;
+ bool covers_screen;
+ u32 scl0, scl1, pitch0;
+@@ -568,10 +559,25 @@ static int vc4_plane_mode_set(struct drm
+ scl1 = vc4_get_scl_field(state, 0);
+ }
+
++ h_subsample = drm_format_horz_chroma_subsampling(format->drm);
++ v_subsample = drm_format_vert_chroma_subsampling(format->drm);
++
+ switch (base_format_mod) {
+ case DRM_FORMAT_MOD_LINEAR:
+ tiling = SCALER_CTL0_TILING_LINEAR;
+ pitch0 = VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH);
++
++ /* Adjust the base pointer to the first pixel to be scanned
++ * out.
++ */
++ for (i = 0; i < num_planes; i++) {
++ vc4_state->offsets[i] += vc4_state->src_y /
++ (i ? v_subsample : 1) *
++ fb->pitches[i];
++ vc4_state->offsets[i] += vc4_state->src_x /
++ (i ? h_subsample : 1) *
++ fb->format->cpp[i];
++ }
+ break;
+
+ case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: {
--- /dev/null
+From f55f26750fa582a9ab9eddc0980b0633bb42d75b Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Fri, 3 Aug 2018 11:22:31 +0200
+Subject: [PATCH 761/773] drm/vc4: Fix X/Y positioning of planes using T_TILES
+ modifier
+
+X/Y positioning of T-format buffers is quite tricky and the current
+implementation was failing to position a plane using this format
+correctly when the CRTC X, Y or both X and Y offsets were negative.
+It was also failing when the SRC X/Y offsets were != 0.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-5-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_plane.c | 50 ++++++++++++++++++++++++++++-----
+ 1 file changed, 43 insertions(+), 7 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_plane.c
++++ b/drivers/gpu/drm/vc4/vc4_plane.c
+@@ -578,22 +578,58 @@ static int vc4_plane_mode_set(struct drm
+ (i ? h_subsample : 1) *
+ fb->format->cpp[i];
+ }
++
+ break;
+
+ case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: {
+- /* For T-tiled, the FB pitch is "how many bytes from
+- * one row to the next, such that pitch * tile_h ==
+- * tile_size * tiles_per_row."
+- */
+ u32 tile_size_shift = 12; /* T tiles are 4kb */
++ /* Whole-tile offsets, mostly for setting the pitch. */
++ u32 tile_w_shift = fb->format->cpp[0] == 2 ? 6 : 5;
+ u32 tile_h_shift = 5; /* 16 and 32bpp are 32 pixels high */
++ u32 tile_w_mask = (1 << tile_w_shift) - 1;
++ /* The height mask on 32-bit-per-pixel tiles is 63, i.e. twice
++ * the height (in pixels) of a 4k tile.
++ */
++ u32 tile_h_mask = (2 << tile_h_shift) - 1;
++ /* For T-tiled, the FB pitch is "how many bytes from one row to
++ * the next, such that
++ *
++ * pitch * tile_h == tile_size * tiles_per_row
++ */
+ u32 tiles_w = fb->pitches[0] >> (tile_size_shift - tile_h_shift);
++ u32 tiles_l = vc4_state->src_x >> tile_w_shift;
++ u32 tiles_r = tiles_w - tiles_l;
++ u32 tiles_t = vc4_state->src_y >> tile_h_shift;
++ /* Intra-tile offsets, which modify the base address (the
++ * SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that
++ * base address).
++ */
++ u32 tile_y = (vc4_state->src_y >> 4) & 1;
++ u32 subtile_y = (vc4_state->src_y >> 2) & 3;
++ u32 utile_y = vc4_state->src_y & 3;
++ u32 x_off = vc4_state->src_x & tile_w_mask;
++ u32 y_off = vc4_state->src_y & tile_h_mask;
+
+ tiling = SCALER_CTL0_TILING_256B_OR_T;
++ pitch0 = (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
++ VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
++ VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
++ VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
++ vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift);
++ vc4_state->offsets[0] += subtile_y << 8;
++ vc4_state->offsets[0] += utile_y << 4;
++
++ /* Rows of tiles alternate left-to-right and right-to-left. */
++ if (tiles_t & 1) {
++ pitch0 |= SCALER_PITCH0_TILE_INITIAL_LINE_DIR;
++ vc4_state->offsets[0] += (tiles_w - tiles_l) <<
++ tile_size_shift;
++ vc4_state->offsets[0] -= (1 + !tile_y) << 10;
++ } else {
++ vc4_state->offsets[0] += tiles_l << tile_size_shift;
++ vc4_state->offsets[0] += tile_y << 10;
++ }
+
+- pitch0 = (VC4_SET_FIELD(0, SCALER_PITCH0_TILE_Y_OFFSET) |
+- VC4_SET_FIELD(0, SCALER_PITCH0_TILE_WIDTH_L) |
+- VC4_SET_FIELD(tiles_w, SCALER_PITCH0_TILE_WIDTH_R));
+ break;
+ }
+
--- /dev/null
+From 8f73c4a08531d65fc4ce12d9a61deb16a7d601cb Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@bootlin.com>
+Date: Thu, 15 Nov 2018 11:58:51 +0100
+Subject: [PATCH 762/773] drm/vc4: Fix NULL pointer dereference in the async
+ update path
+
+vc4_plane_atomic_async_update() calls vc4_plane_atomic_check()
+which in turn calls vc4_plane_setup_clipping_and_scaling(), and since
+commit 58a6a36fe8e0 ("drm/vc4: Use
+drm_atomic_helper_check_plane_state() to simplify the logic"), this
+function accesses plane_state->state which will be NULL when called
+from the async update path because we're passing the current plane
+state, and plane_state->state has been assigned to NULL in
+drm_atomic_helper_swap_state().
+
+Pass the new state instead of the current one (the new state has
+->state set to a non-NULL value).
+
+Fixes: 58a6a36fe8e0 ("drm/vc4: Use drm_atomic_helper_check_plane_state() to simplify the logic")
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181115105852.9844-1-boris.brezillon@bootlin.com
+---
+ drivers/gpu/drm/vc4/vc4_plane.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_plane.c
++++ b/drivers/gpu/drm/vc4/vc4_plane.c
+@@ -905,7 +905,7 @@ void vc4_plane_async_set_fb(struct drm_p
+ static void vc4_plane_atomic_async_update(struct drm_plane *plane,
+ struct drm_plane_state *state)
+ {
+- struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state);
++ struct vc4_plane_state *vc4_state, *new_vc4_state;
+
+ if (plane->state->fb != state->fb) {
+ vc4_plane_async_set_fb(plane, state->fb);
+@@ -927,7 +927,18 @@ static void vc4_plane_atomic_async_updat
+ plane->state->src_y = state->src_y;
+
+ /* Update the display list based on the new crtc_x/y. */
+- vc4_plane_atomic_check(plane, plane->state);
++ vc4_plane_atomic_check(plane, state);
++
++ new_vc4_state = to_vc4_plane_state(state);
++ vc4_state = to_vc4_plane_state(plane->state);
++
++ /* Update the current vc4_state pos0, pos2 and ptr0 dlist entries. */
++ vc4_state->dlist[vc4_state->pos0_offset] =
++ new_vc4_state->dlist[vc4_state->pos0_offset];
++ vc4_state->dlist[vc4_state->pos2_offset] =
++ new_vc4_state->dlist[vc4_state->pos2_offset];
++ vc4_state->dlist[vc4_state->ptr0_offset] =
++ new_vc4_state->dlist[vc4_state->ptr0_offset];
+
+ /* Note that we can't just call vc4_plane_write_dlist()
+ * because that would smash the context data that the HVS is
--- /dev/null
+From b67dc43c90c8d9871d79313c4d5b04368bd6859c Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Sun, 11 Aug 2019 21:31:46 +0100
+Subject: [PATCH 763/773] configs: Regenerate the defconfigs
+
+Update bcm2709_defconfig to match the output from savedefconfig.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/configs/bcm2709_defconfig | 2 +-
+ 1 file changed, 1 insertion(+), 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
--- /dev/null
+From 739a3cd3ae724818dc3d93fc98141e59077932c8 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Sun, 11 Aug 2019 21:34:43 +0100
+Subject: [PATCH 764/773] configs: Enable building the DS28E17 driver module
+
+See: https://github.com/raspberrypi/linux/issues/3141
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/configs/bcm2709_defconfig | 1 +
+ arch/arm/configs/bcm2711_defconfig | 1 +
+ arch/arm/configs/bcmrpi_defconfig | 1 +
+ arch/arm64/configs/bcm2711_defconfig | 1 +
+ arch/arm64/configs/bcmrpi3_defconfig | 1 +
+ 5 files changed, 5 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -706,6 +706,7 @@ CONFIG_W1_SLAVE_DS2438=m
+ CONFIG_W1_SLAVE_DS2780=m
+ CONFIG_W1_SLAVE_DS2781=m
+ CONFIG_W1_SLAVE_DS28E04=m
++CONFIG_W1_SLAVE_DS28E17=m
+ CONFIG_POWER_RESET=y
+ CONFIG_POWER_RESET_GPIO=y
+ CONFIG_BATTERY_DS2760=m
+--- a/arch/arm/configs/bcm2711_defconfig
++++ b/arch/arm/configs/bcm2711_defconfig
+@@ -714,6 +714,7 @@ CONFIG_W1_SLAVE_DS2438=m
+ CONFIG_W1_SLAVE_DS2780=m
+ CONFIG_W1_SLAVE_DS2781=m
+ CONFIG_W1_SLAVE_DS28E04=m
++CONFIG_W1_SLAVE_DS28E17=m
+ CONFIG_POWER_RESET=y
+ CONFIG_POWER_RESET_GPIO=y
+ CONFIG_BATTERY_DS2760=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -698,6 +698,7 @@ CONFIG_W1_SLAVE_DS2438=m
+ CONFIG_W1_SLAVE_DS2780=m
+ CONFIG_W1_SLAVE_DS2781=m
+ CONFIG_W1_SLAVE_DS28E04=m
++CONFIG_W1_SLAVE_DS28E17=m
+ CONFIG_POWER_RESET=y
+ CONFIG_POWER_RESET_GPIO=y
+ CONFIG_BATTERY_DS2760=m
+--- a/arch/arm64/configs/bcm2711_defconfig
++++ b/arch/arm64/configs/bcm2711_defconfig
+@@ -644,6 +644,7 @@ CONFIG_W1_SLAVE_DS2438=m
+ CONFIG_W1_SLAVE_DS2780=m
+ CONFIG_W1_SLAVE_DS2781=m
+ CONFIG_W1_SLAVE_DS28E04=m
++CONFIG_W1_SLAVE_DS28E17=m
+ CONFIG_POWER_RESET_GPIO=y
+ CONFIG_BATTERY_DS2760=m
+ CONFIG_BATTERY_GAUGE_LTC2941=m
+--- a/arch/arm64/configs/bcmrpi3_defconfig
++++ b/arch/arm64/configs/bcmrpi3_defconfig
+@@ -628,6 +628,7 @@ CONFIG_W1_SLAVE_DS2433=m
+ CONFIG_W1_SLAVE_DS2780=m
+ CONFIG_W1_SLAVE_DS2781=m
+ CONFIG_W1_SLAVE_DS28E04=m
++CONFIG_W1_SLAVE_DS28E17=m
+ CONFIG_POWER_RESET_GPIO=y
+ CONFIG_BATTERY_DS2760=m
+ CONFIG_BATTERY_MAX17040=m
--- /dev/null
+From 633d53276f8a94025f0cf60df37519136272434d Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 12 Aug 2019 15:48:39 +0100
+Subject: [PATCH 765/773] ARM: dts: bcm2711-rpi-4-b: I2C aliases and pulls
+
+The I2C interface nodes need aliases to give them fixed bus numbers,
+and setting the pulls on the GPIOs (particularly 9-13) increases the
+chances of the bus working with weak or absent external pulls.
+
+See: https://www.raspberrypi.org/forums/posting.php?mode=reply&f=107&t=248439
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -23,6 +23,10 @@
+ mmc0 = &emmc2;
+ mmc1 = &mmcnr;
+ mmc2 = &sdhost;
++ i2c3 = &i2c3;
++ i2c4 = &i2c4;
++ i2c5 = &i2c5;
++ i2c6 = &i2c6;
+ /delete-property/ ethernet;
+ /delete-property/ intc;
+ ethernet0 = &genet;
+@@ -207,31 +211,37 @@
+ i2c0_pins: i2c0 {
+ brcm,pins = <0 1>;
+ brcm,function = <BCM2835_FSEL_ALT0>;
++ brcm,pull = <BCM2835_PUD_UP>;
+ };
+
+ i2c1_pins: i2c1 {
+ brcm,pins = <2 3>;
+ brcm,function = <BCM2835_FSEL_ALT0>;
++ brcm,pull = <BCM2835_PUD_UP>;
+ };
+
+ i2c3_pins: i2c3 {
+ brcm,pins = <4 5>;
+ brcm,function = <BCM2835_FSEL_ALT5>;
++ brcm,pull = <BCM2835_PUD_UP>;
+ };
+
+ i2c4_pins: i2c4 {
+ brcm,pins = <8 9>;
+ brcm,function = <BCM2835_FSEL_ALT5>;
++ brcm,pull = <BCM2835_PUD_UP>;
+ };
+
+ i2c5_pins: i2c5 {
+ brcm,pins = <12 13>;
+ brcm,function = <BCM2835_FSEL_ALT5>;
++ brcm,pull = <BCM2835_PUD_UP>;
+ };
+
+ i2c6_pins: i2c6 {
+ brcm,pins = <22 23>;
+ brcm,function = <BCM2835_FSEL_ALT5>;
++ brcm,pull = <BCM2835_PUD_UP>;
+ };
+
+ i2s_pins: i2s {
--- /dev/null
+From cba43f76fe083fb735257410b10d3904355207fe Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 13 Aug 2019 15:53:29 +0100
+Subject: [PATCH 766/773] xhci: Use more event ring segment table entries
+
+Users have reported log spam created by "Event Ring Full" xHC event
+TRBs. These are caused by interrupt latency in conjunction with a very
+busy set of devices on the bus. The errors are benign, but throughput
+will suffer as the xHC will pause processing of transfers until the
+event ring is drained by the kernel. Expand the number of event TRB slots
+available by increasing the number of event ring segments in the ERST.
+
+Controllers have a hardware-defined limit as to the number of ERST
+entries they can process, so make the actual number in use
+min(ERST_MAX_SEGS, hw_max).
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/host/xhci-mem.c | 8 +++++---
+ drivers/usb/host/xhci.h | 4 ++--
+ 2 files changed, 7 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -2491,9 +2491,11 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+ * Event ring setup: Allocate a normal ring, but also setup
+ * the event ring segment table (ERST). Section 4.9.3.
+ */
++ val2 = 1 << HCS_ERST_MAX(xhci->hcs_params2);
++ val2 = min_t(unsigned int, ERST_MAX_SEGS, val2);
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Allocating event ring");
+- xhci->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, 1, TYPE_EVENT,
+- 0, flags);
++ xhci->event_ring = xhci_ring_alloc(xhci, val2, 1, TYPE_EVENT,
++ 0, flags);
+ if (!xhci->event_ring)
+ goto fail;
+ if (xhci_check_trb_in_td_math(xhci) < 0)
+@@ -2506,7 +2508,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+ /* set ERST count with the number of entries in the segment table */
+ val = readl(&xhci->ir_set->erst_size);
+ val &= ERST_SIZE_MASK;
+- val |= ERST_NUM_SEGS;
++ val |= val2;
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+ "// Write ERST size = %i to ir_set 0 (some bits preserved)",
+ val);
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1643,8 +1643,8 @@ struct urb_priv {
+ * Each segment table entry is 4*32bits long. 1K seems like an ok size:
+ * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table,
+ * meaning 64 ring segments.
+- * Initial allocated size of the ERST, in number of entries */
+-#define ERST_NUM_SEGS 1
++ * Maximum number of segments in the ERST */
++#define ERST_MAX_SEGS 8
+ /* Initial allocated size of the ERST, in number of entries */
+ #define ERST_SIZE 64
+ /* Initial number of event segment rings allocated */
--- /dev/null
+From e6510a4c6b282ccbf8fdb6d8e035a72ac88aa94b Mon Sep 17 00:00:00 2001
+From: P33M <2474547+P33M@users.noreply.github.com>
+Date: Wed, 14 Aug 2019 14:35:50 +0100
+Subject: [PATCH 767/773] dwc_otg: use align_buf for small IN control transfers
+ (#3150)
+
+The hardware will do a 4-byte write to memory on any IN packet received
+that is between 1 and 3 bytes long. This tramples memory in the uvcvideo
+driver, as it uses a sequence of 1- and 2-byte control transfers to
+query the min/max/range/step of each individual camera control and
+gives us buffers that are offsets into a struct.
+
+Catch small control transfers in the data phase and use the align_buf
+to bounce the correct number of bytes into the URB's buffer.
+
+In general, short packets on non-control endpoints should be OK as URBs
+should have enough buffer space for a wMaxPacket size transfer.
+
+See: https://github.com/raspberrypi/linux/issues/3148
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+@@ -1182,6 +1182,7 @@ static void assign_and_init_hc(dwc_otg_h
+ dwc_otg_qtd_t *qtd;
+ dwc_otg_hcd_urb_t *urb;
+ void* ptr = NULL;
++ uint16_t wLength;
+ uint32_t intr_enable;
+ unsigned long flags;
+ gintmsk_data_t gintmsk = { .d32 = 0, };
+@@ -1293,6 +1294,23 @@ static void assign_and_init_hc(dwc_otg_h
+ break;
+ case DWC_OTG_CONTROL_DATA:
+ DWC_DEBUGPL(DBG_HCDV, " Control data transaction\n");
++ /*
++ * Hardware bug: small IN packets with length < 4
++ * cause a 4-byte write to memory. We can only catch
++ * the case where we know a short packet is going to be
++ * returned in a control transfer, as the length is
++ * specified in the setup packet. This is only an issue
++ * for drivers that insist on packing a device's various
++ * properties into a struct and querying them one at a
++ * time (uvcvideo).
++ * Force the use of align_buf so that the subsequent
++ * memcpy puts the right number of bytes in the URB's
++ * buffer.
++ */
++ wLength = ((uint16_t *)urb->setup_packet)[3];
++ if (hc->ep_is_in && wLength < 4)
++ ptr = hc->xfer_buff;
++
+ hc->data_pid_start = qtd->data_toggle;
+ break;
+ case DWC_OTG_CONTROL_STATUS:
--- /dev/null
+From 2f9799e1c9bd7f03792a89ff7c9d55f0c570d661 Mon Sep 17 00:00:00 2001
+From: yaroslavros <yaroslavros@gmail.com>
+Date: Wed, 14 Aug 2019 15:22:55 +0100
+Subject: [PATCH 768/773] Ported pcie-brcmstb bounce buffer implementation to
+ ARM64. (#3144)
+
+Ported pcie-brcmstb bounce buffer implementation to ARM64.
+This enables full 4G RAM usage on Raspberry Pi in 64-bit mode.
+
+Signed-off-by: Yaroslav Rosomakho <yaroslavros@gmail.com>
+---
+ arch/arm64/include/asm/dma-mapping.h | 21 +
+ arch/arm64/mm/dma-mapping.c | 50 ++
+ drivers/pci/controller/Makefile | 3 +
+ drivers/pci/controller/pcie-brcmstb-bounce.h | 2 +-
+ .../pci/controller/pcie-brcmstb-bounce64.c | 576 ++++++++++++++++++
+ drivers/pci/controller/pcie-brcmstb.c | 30 +-
+ 6 files changed, 658 insertions(+), 24 deletions(-)
+ create mode 100644 drivers/pci/controller/pcie-brcmstb-bounce64.c
+
+--- a/arch/arm64/include/asm/dma-mapping.h
++++ b/arch/arm64/include/asm/dma-mapping.h
+@@ -24,6 +24,27 @@
+ #include <xen/xen.h>
+ #include <asm/xen/hypervisor.h>
+
++extern void *arm64_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
++ gfp_t gfp, unsigned long attrs);
++extern void arm64_dma_free(struct device *dev, size_t size, void *cpu_addr,
++ dma_addr_t handle, unsigned long attrs);
++extern int arm64_dma_mmap(struct device *dev, struct vm_area_struct *vma,
++ void *cpu_addr, dma_addr_t dma_addr, size_t size,
++ unsigned long attrs);
++extern int arm64_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
++ void *cpu_addr, dma_addr_t dma_addr, size_t size,
++ unsigned long attrs);
++extern int arm64_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nelems,
++ enum dma_data_direction dir, unsigned long attrs);
++extern void arm64_dma_unmap_sg(struct device *dev, struct scatterlist *sgl, int,
++ enum dma_data_direction dir, unsigned long attrs);
++extern void arm64_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, int nelems,
++ enum dma_data_direction dir);
++extern void arm64_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl, int nelems,
++ enum dma_data_direction dir);
++
++
++
+ extern const struct dma_map_ops dummy_dma_ops;
+
+ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
+--- a/arch/arm64/mm/dma-mapping.c
++++ b/arch/arm64/mm/dma-mapping.c
+@@ -138,6 +138,12 @@ no_mem:
+ return NULL;
+ }
+
++void *arm64_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
++ gfp_t gfp, unsigned long attrs)
++{
++ return __dma_alloc(dev, size, handle, gfp, attrs);
++}
++
+ static void __dma_free(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle,
+ unsigned long attrs)
+@@ -154,6 +160,12 @@ static void __dma_free(struct device *de
+ swiotlb_free(dev, size, swiotlb_addr, dma_handle, attrs);
+ }
+
++void arm64_dma_free(struct device *dev, size_t size, void *cpu_addr,
++ dma_addr_t handle, unsigned long attrs)
++{
++ __dma_free(dev, size, cpu_addr, handle, attrs);
++}
++
+ static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir,
+@@ -197,6 +209,12 @@ static int __swiotlb_map_sg_attrs(struct
+ return ret;
+ }
+
++int arm64_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nelems,
++ enum dma_data_direction dir, unsigned long attrs)
++{
++ return __swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs);
++}
++
+ static void __swiotlb_unmap_sg_attrs(struct device *dev,
+ struct scatterlist *sgl, int nelems,
+ enum dma_data_direction dir,
+@@ -213,6 +231,12 @@ static void __swiotlb_unmap_sg_attrs(str
+ swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs);
+ }
+
++void arm64_dma_unmap_sg(struct device *dev, struct scatterlist *sgl, int nelems,
++ enum dma_data_direction dir, unsigned long attrs)
++{
++ __swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs);
++}
++
+ static void __swiotlb_sync_single_for_cpu(struct device *dev,
+ dma_addr_t dev_addr, size_t size,
+ enum dma_data_direction dir)
+@@ -245,6 +269,12 @@ static void __swiotlb_sync_sg_for_cpu(st
+ swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir);
+ }
+
++void arm64_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, int nelems,
++ enum dma_data_direction dir)
++{
++ __swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir);
++}
++
+ static void __swiotlb_sync_sg_for_device(struct device *dev,
+ struct scatterlist *sgl, int nelems,
+ enum dma_data_direction dir)
+@@ -259,6 +289,12 @@ static void __swiotlb_sync_sg_for_device
+ sg->length, dir);
+ }
+
++void arm64_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl, int nelems,
++ enum dma_data_direction dir)
++{
++ __swiotlb_sync_sg_for_device(dev, sgl, nelems, dir);
++}
++
+ static int __swiotlb_mmap_pfn(struct vm_area_struct *vma,
+ unsigned long pfn, size_t size)
+ {
+@@ -294,6 +330,13 @@ static int __swiotlb_mmap(struct device
+ return __swiotlb_mmap_pfn(vma, pfn, size);
+ }
+
++int arm64_dma_mmap(struct device *dev, struct vm_area_struct *vma,
++ void *cpu_addr, dma_addr_t dma_addr, size_t size,
++ unsigned long attrs)
++{
++ return __swiotlb_mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
++}
++
+ static int __swiotlb_get_sgtable_page(struct sg_table *sgt,
+ struct page *page, size_t size)
+ {
+@@ -314,6 +357,13 @@ static int __swiotlb_get_sgtable(struct
+ return __swiotlb_get_sgtable_page(sgt, page, size);
+ }
+
++int arm64_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
++ void *cpu_addr, dma_addr_t dma_addr, size_t size,
++ unsigned long attrs)
++{
++ return __swiotlb_get_sgtable(dev, sgt, cpu_addr, dma_addr, size, attrs);
++}
++
+ static int __swiotlb_dma_supported(struct device *hwdev, u64 mask)
+ {
+ if (swiotlb)
+--- a/drivers/pci/controller/Makefile
++++ b/drivers/pci/controller/Makefile
+@@ -32,6 +32,9 @@ obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcms
+ ifdef CONFIG_ARM
+ obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb-bounce.o
+ endif
++ifdef CONFIG_ARM64
++obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb-bounce64.o
++endif
+
+ obj-$(CONFIG_VMD) += vmd.o
+ # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
+--- a/drivers/pci/controller/pcie-brcmstb-bounce.h
++++ b/drivers/pci/controller/pcie-brcmstb-bounce.h
+@@ -6,7 +6,7 @@
+ #ifndef _PCIE_BRCMSTB_BOUNCE_H
+ #define _PCIE_BRCMSTB_BOUNCE_H
+
+-#ifdef CONFIG_ARM
++#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+
+ int brcm_pcie_bounce_init(struct device *dev, unsigned long buffer_size,
+ dma_addr_t threshold);
+--- /dev/null
++++ b/drivers/pci/controller/pcie-brcmstb-bounce64.c
+@@ -0,0 +1,576 @@
++/*
++ * 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/dma-direct.h>
++#include <linux/dmapool.h>
++#include <linux/list.h>
++#include <linux/scatterlist.h>
++#include <linux/bitmap.h>
++#include <linux/swiotlb.h>
++
++#include <asm/cacheflush.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(void);
++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 = phys_to_dma(dev, page_to_phys(page)) + offset;
++
++ swiotlb_sync_single_for_device(dev, dma_addr, size, dir);
++ if (!is_device_dma_coherent(dev))
++ __dma_map_area(phys_to_virt(dma_to_phys(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 (~(dma_addr_t)0x0);
++ }
++
++ 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);
++ }
++
++ if (!is_device_dma_coherent(dev))
++ __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dma_addr)), size, dir);
++ swiotlb_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;
++
++ swiotlb_sync_single_for_device(dev, dma_addr, size, dir);
++ if (!is_device_dma_coherent(dev))
++ __dma_map_area(phys_to_virt(dma_to_phys(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);
++ }
++
++ if (!is_device_dma_coherent(dev))
++ __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dma_addr)), size, dir);
++ swiotlb_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 swiotlb_dma_supported(dev, dma_mask);
++}
++
++static int dmabounce_mapping_error(struct device *dev, dma_addr_t dma_addr)
++{
++ return swiotlb_dma_mapping_error(dev, dma_addr);
++}
++
++static const struct dma_map_ops dmabounce_ops = {
++ .alloc = arm64_dma_alloc,
++ .free = arm64_dma_free,
++ .mmap = arm64_dma_mmap,
++ .get_sgtable = arm64_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 = arm64_dma_map_sg,
++ .unmap_sg = arm64_dma_unmap_sg,
++ .sync_sg_for_cpu = arm64_dma_sync_sg_for_cpu,
++ .sync_sg_for_device = arm64_dma_sync_sg_for_device,
++ .dma_supported = dmabounce_dma_supported,
++ .mapping_error = dmabounce_mapping_error,
++};
++
++int brcm_pcie_bounce_init(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();
++ 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;
++
++ dev_err(dev, "dmabounce: initialised - %ld kB, threshold %pad\n",
++ buffer_size / 1024, &threshold);
++
++ return 0;
++
++ err_bounce:
++ kfree(device_info);
++ return ret;
++}
++EXPORT_SYMBOL(brcm_pcie_bounce_init);
++
++void brcm_pcie_bounce_uninit(struct device *dev)
++{
++ struct dmabounce_device_info *device_info = g_dmabounce_device_info;
++
++ g_dmabounce_device_info = 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);
++}
++EXPORT_SYMBOL(brcm_pcie_bounce_uninit);
++
++int brcm_pcie_bounce_register_dev(struct device *dev)
++{
++ set_dma_ops(dev, &dmabounce_ops);
++
++ return 0;
++}
++EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
++
++MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.org>");
++MODULE_DESCRIPTION("Dedicate DMA bounce support for pcie-brcmstb");
++MODULE_LICENSE("GPL");
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -617,28 +617,6 @@ static const struct dma_map_ops brcm_dma
+
+ 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");
+@@ -657,12 +635,12 @@ static int brcmstb_platform_notifier(str
+ extern unsigned long max_pfn;
+ struct device *dev = __dev;
+ const char *rc_name = "0000:00:00.0";
++ int ret;
+
+ 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);
+ if (ret) {
+@@ -671,6 +649,12 @@ static int brcmstb_platform_notifier(str
+ ret);
+ return ret;
+ }
++ } else if (IS_ENABLED(CONFIG_ARM64)) {
++ ret = of_dma_configure(dev, dev->of_node, true);
++ if (ret) {
++ dev_err(dev, "of_dma_configure() failed: %d\n", ret);
++ return;
++ }
+ }
+ brcm_set_dma_ops(dev);
+ return NOTIFY_OK;
--- /dev/null
+From 8a537f8c712f837ac154fb91e90f136ffa304882 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 15 Aug 2019 12:02:34 +0100
+Subject: [PATCH 769/773] configs: arm64/vcm2711: Enable V3D
+
+Enable the V3D driver, which depends on BCM2835_POWER.
+
+Originally submitted by GitHub user 'phire' in a slightly different
+form.
+
+See: https://github.com/raspberrypi/linux/pull/3063
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm64/configs/bcm2711_defconfig | 2 ++
+ drivers/gpu/drm/v3d/Kconfig | 2 +-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+--- a/arch/arm64/configs/bcm2711_defconfig
++++ b/arch/arm64/configs/bcm2711_defconfig
+@@ -791,6 +791,7 @@ 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
+@@ -1135,6 +1136,7 @@ CONFIG_VIDEO_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
+--- a/drivers/gpu/drm/v3d/Kconfig
++++ b/drivers/gpu/drm/v3d/Kconfig
+@@ -1,6 +1,6 @@
+ config DRM_V3D
+ tristate "Broadcom V3D 3.x and newer"
+- depends on ARCH_BCM || ARCH_BCMSTB || COMPILE_TEST
++ depends on ARCH_BCM || ARCH_BCMSTB || ARCH_BCM2835 || COMPILE_TEST
+ depends on DRM
+ depends on COMMON_CLK
+ depends on MMU
--- /dev/null
+From 1a0aa89304eba1b10a0d122501af7f2b96b36fda Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Sat, 17 Aug 2019 19:47:30 +0100
+Subject: [PATCH 770/773] overlays: sc16ic752-i2c: Fix xtal parameter
+
+The xtal parameter is targetting the wrong node - fix it.
+
+See: https://github.com/raspberrypi/linux/issues/3156
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
+@@ -35,6 +35,6 @@
+ __overrides__ {
+ int_pin = <&sc16is752>,"interrupts:0";
+ addr = <&sc16is752>,"reg:0",<&sc16is752_clk>,"name";
+- xtal = <&sc16is752>,"clock-frequency:0";
++ xtal = <&sc16is752_clk>,"clock-frequency:0";
+ };
+ };
--- /dev/null
+From 907be7d1c6c442cb20c0731026d119f9017dd375 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 19 Aug 2019 15:45:20 +0100
+Subject: [PATCH 771/773] vc-sm-cma: Fix compatibility ioctl
+
+This code path hasn't been used previously.
+Fixed up after testing with kodi on 32-bit userland and 64-bit kernel
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -1501,11 +1501,10 @@ 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;
+- struct vc_sm_cma_ioctl_clean_invalid_block {
++ struct vc_sm_cma_ioctl_clean_invalid_block_32 {
+ u16 invalidate_mode;
+ u16 block_count;
+ compat_uptr_t start_address;
+@@ -1516,7 +1515,7 @@ struct vc_sm_cma_ioctl_clean_invalid2_32
+
+ #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)
++ struct vc_sm_cma_ioctl_clean_invalid2_32)
+
+ static long vc_sm_cma_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+@@ -1524,24 +1523,21 @@ static long vc_sm_cma_compat_ioctl(struc
+ switch (cmd) {
+ case VC_SM_CMA_CMD_CLEAN_INVALID2_32:
+ /* FIXME */
+- break;
++ return -EINVAL;
+
+ default:
+- return vc_sm_cma_compat_ioctl(file, cmd, arg);
++ return vc_sm_cma_ioctl(file, cmd, arg);
+ }
+ }
+ #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 931cfc501b0df7513f7aa30f96a9f26043de89cb Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Thu, 22 Aug 2019 17:20:58 +0100
+Subject: [PATCH 772/773] configs: Add TINYDRM modules
+
+---
+ arch/arm/configs/bcm2709_defconfig | 4 ++++
+ arch/arm/configs/bcm2711_defconfig | 4 ++++
+ arch/arm/configs/bcmrpi_defconfig | 4 ++++
+ 3 files changed, 12 insertions(+)
+
+--- a/arch/arm/configs/bcm2709_defconfig
++++ b/arch/arm/configs/bcm2709_defconfig
+@@ -924,8 +924,12 @@ CONFIG_DRM_PANEL_SIMPLE=m
+ CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m
+ CONFIG_DRM_VC4=m
+ CONFIG_DRM_TINYDRM=m
++CONFIG_TINYDRM_ILI9225=m
++CONFIG_TINYDRM_ILI9341=m
+ CONFIG_TINYDRM_MI0283QT=m
+ CONFIG_TINYDRM_REPAPER=m
++CONFIG_TINYDRM_ST7586=m
++CONFIG_TINYDRM_ST7735R=m
+ CONFIG_FB=y
+ CONFIG_FB_BCM2708=y
+ CONFIG_FB_UDL=m
+--- a/arch/arm/configs/bcm2711_defconfig
++++ b/arch/arm/configs/bcm2711_defconfig
+@@ -935,8 +935,12 @@ CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN
+ CONFIG_DRM_V3D=m
+ CONFIG_DRM_VC4=m
+ CONFIG_DRM_TINYDRM=m
++CONFIG_TINYDRM_ILI9225=m
++CONFIG_TINYDRM_ILI9341=m
+ CONFIG_TINYDRM_MI0283QT=m
+ CONFIG_TINYDRM_REPAPER=m
++CONFIG_TINYDRM_ST7586=m
++CONFIG_TINYDRM_ST7735R=m
+ CONFIG_FB=y
+ CONFIG_FB_BCM2708=y
+ CONFIG_FB_UDL=m
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -916,8 +916,12 @@ CONFIG_DRM_PANEL_SIMPLE=m
+ CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m
+ CONFIG_DRM_VC4=m
+ CONFIG_DRM_TINYDRM=m
++CONFIG_TINYDRM_ILI9225=m
++CONFIG_TINYDRM_ILI9341=m
+ CONFIG_TINYDRM_MI0283QT=m
+ CONFIG_TINYDRM_REPAPER=m
++CONFIG_TINYDRM_ST7586=m
++CONFIG_TINYDRM_ST7735R=m
+ CONFIG_FB=y
+ CONFIG_FB_BCM2708=y
+ CONFIG_FB_UDL=m
--- /dev/null
+From 9392bdcc241adb527dcb42caab2204c59c02cef3 Mon Sep 17 00:00:00 2001
+From: Aman Gupta <aman@tmm1.net>
+Date: Thu, 22 Aug 2019 22:31:37 +0000
+Subject: [PATCH 773/773] staging: bcm2835-codec: add support for
+ V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME
+
+fixes #3171
+
+Signed-off-by: Aman Gupta <aman@tmm1.net>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c | 19 ++++++++++++++++++-
+ 1 file changed, 18 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
+@@ -1587,6 +1587,20 @@ static int bcm2835_codec_s_ctrl(struct v
+ ret = bcm2835_codec_set_level_profile(ctx, ctrl);
+ break;
+
++ case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: {
++ u32 mmal_bool = 1;
++
++ if (!ctx->component)
++ break;
++
++ ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
++ &ctx->component->output[0],
++ MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME,
++ &mmal_bool,
++ sizeof(mmal_bool));
++ break;
++ }
++
+ default:
+ v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
+ return -EINVAL;
+@@ -2311,7 +2325,7 @@ static int bcm2835_codec_open(struct fil
+ hdl = &ctx->hdl;
+ if (dev->role == ENCODE) {
+ /* Encode controls */
+- v4l2_ctrl_handler_init(hdl, 6);
++ v4l2_ctrl_handler_init(hdl, 7);
+
+ v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+@@ -2355,6 +2369,9 @@ static int bcm2835_codec_open(struct fil
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
+ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
++ v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
++ V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME,
++ 0, 0, 0, 0);
+ if (hdl->error) {
+ rc = hdl->error;
+ goto free_ctrl_handler;