CONFIG_ARM_HAS_SG_CHAIN=y
CONFIG_ARM_L1_CACHE_SHIFT=5
CONFIG_ARM_PATCH_PHYS_VIRT=y
+# CONFIG_ARM_RASPBERRYPI_CPUFREQ is not set
# CONFIG_ARM_SCMI_PROTOCOL is not set
CONFIG_ARM_THUMB=y
CONFIG_ARM_TIMER_SP804=y
CONFIG_CLKDEV_LOOKUP=y
CONFIG_CLKSRC_MMIO=y
CONFIG_CLK_BCM2835=y
-# CONFIG_CLK_RASPBERRYPI is not set
+CONFIG_CLK_RASPBERRYPI=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_CMA=y
CONFIG_CMA_ALIGNMENT=8
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+CONFIG_DMABUF_HEAPS=y
+CONFIG_DMABUF_HEAPS_CMA=y
+CONFIG_DMABUF_HEAPS_SYSTEM=y
CONFIG_DMADEVICES=y
CONFIG_DMA_BCM2708=y
CONFIG_DMA_BCM2835=y
CONFIG_I2C=y
# CONFIG_I2C_BCM2708 is not set
CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_BRCMSTB is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_INPUT=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_RESET_CONTROLLER=y
+CONFIG_RESET_SIMPLE=y
# CONFIG_RPIVID_MEM is not set
CONFIG_SCSI=y
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
CONFIG_DIMLIB=y
+CONFIG_DMABUF_HEAPS=y
+CONFIG_DMABUF_HEAPS_CMA=y
+CONFIG_DMABUF_HEAPS_SYSTEM=y
CONFIG_DMADEVICES=y
CONFIG_DMA_BCM2708=y
CONFIG_DMA_BCM2835=y
CONFIG_I2C=y
# CONFIG_I2C_BCM2708 is not set
CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_BRCMSTB is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_INPUT=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_GPIO=y
CONFIG_RESET_CONTROLLER=y
+CONFIG_RESET_SIMPLE=y
CONFIG_RFS_ACCEL=y
# CONFIG_RPIVID_MEM is not set
CONFIG_RPS=y
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
+CONFIG_DMABUF_HEAPS=y
+CONFIG_DMABUF_HEAPS_CMA=y
+CONFIG_DMABUF_HEAPS_SYSTEM=y
CONFIG_DMADEVICES=y
CONFIG_DMA_BCM2708=y
CONFIG_DMA_BCM2835=y
CONFIG_DMA_ENGINE=y
CONFIG_DMA_OF=y
CONFIG_DMA_REMAP=y
+CONFIG_DMA_SHARED_BUFFER=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
CONFIG_DNOTIFY=y
CONFIG_DRM_RCAR_WRITEBACK=y
CONFIG_I2C=y
# CONFIG_I2C_BCM2708 is not set
CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_BRCMSTB is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_GPIO=y
CONFIG_RESET_CONTROLLER=y
+CONFIG_RESET_SIMPLE=y
CONFIG_RFS_ACCEL=y
CONFIG_RODATA_FULL_DEFAULT_ENABLED=y
# CONFIG_RPIVID_MEM is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
CONFIG_DIMLIB=y
+CONFIG_DMABUF_HEAPS=y
+CONFIG_DMABUF_HEAPS_CMA=y
+CONFIG_DMABUF_HEAPS_SYSTEM=y
CONFIG_DMADEVICES=y
CONFIG_DMA_BCM2708=y
CONFIG_DMA_BCM2835=y
CONFIG_DMA_ENGINE=y
CONFIG_DMA_OF=y
CONFIG_DMA_REMAP=y
+CONFIG_DMA_SHARED_BUFFER=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
CONFIG_DNOTIFY=y
CONFIG_DRM_RCAR_WRITEBACK=y
CONFIG_I2C=y
# CONFIG_I2C_BCM2708 is not set
CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_BRCMSTB is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_GPIO=y
CONFIG_RESET_CONTROLLER=y
+CONFIG_RESET_SIMPLE=y
CONFIG_RFS_ACCEL=y
CONFIG_RODATA_FULL_DEFAULT_ENABLED=y
# CONFIG_RPIVID_MEM is not set
$(eval $(call KernelPackage,sound-soc-allo-katana-codec))
+define KernelPackage/sound-soc-audioinjector-isolated-soundcard
+ TITLE:=Support for AudioInjector Isolated soundcard
+ KCONFIG:= \
+ CONFIG_SND_AUDIOINJECTOR_ISOLATED_SOUNDCARD \
+ CONFIG_SND_SOC_CS4271 \
+ CONFIG_SND_SOC_CS4271_I2C
+ FILES:= \
+ $(LINUX_DIR)/sound/soc/bcm/snd-soc-audioinjector-isolated-soundcard.ko \
+ $(LINUX_DIR)/sound/soc/codecs/snd-soc-wm8731.ko
+ AUTOLOAD:=$(call AutoLoad,68,snd-soc-cs4271.o \
+ snd-soc-cs4271-i2c \
+ snd-soc-audioinjector-isolated-soundcard)
+ DEPENDS:= \
+ kmod-sound-soc-bcm2835-i2s \
+ +kmod-i2c-bcm2835 \
+ +kmod-regmap-i2c \
+ +kmod-regmap-spi
+ $(call AddDepends/sound)
+endef
+
+define KernelPackage/sound-soc-audioinjector-isolated-soundcard/description
+ This package contains support for AudioInjector Isolated soundcard
+endef
+
+$(eval $(call KernelPackage,sound-soc-audioinjector-isolated-soundcard))
+
+
define KernelPackage/sound-soc-audioinjector-octo-soundcard
TITLE:=Support for AudioInjector Octo soundcard
KCONFIG:= \
$(eval $(call KernelPackage,sound-soc-rpi-dac))
+define KernelPackage/sound-soc-merus-amp
+ TITLE:=Support for Infineon Merus Amp
+ KCONFIG:= \
+ CONFIG_SND_SOC_MA120X0P
+ FILES:= \
+ $(LINUX_DIR)/sound/soc/codecs/snd-soc-ma120x0p.ko
+ AUTOLOAD:=$(call AutoLoad,68,snd-soc-ma120x0p)
+ DEPENDS:= \
+ kmod-sound-soc-bcm2835-i2s \
+ +kmod-sound-soc-rpi-simple-soundcard \
+ +kmod-i2c-bcm2835 \
+ +kmod-regmap-i2c
+ $(call AddDepends/sound)
+endef
+
+define KernelPackage/sound-soc-merus-amp/description
+ This package contains support for Infineon Merus Amp
+endef
+
+$(eval $(call KernelPackage,sound-soc-merus-amp))
+
+
define KernelPackage/sound-soc-rpi-proto
TITLE:=Support for RPi-PROTO
KCONFIG:= \
+kmod-sound-soc-core
KCONFIG:= \
CONFIG_DRM_VC4 \
- CONFIG_DRM_VC4_HDMI_CEC=n \
+ CONFIG_DRM_VC4_HDMI_CEC=y \
CONFIG_DRM_V3D=n \
CONFIG_DRM_TVE200=n
FILES:= \
$(LINUX_DIR)/drivers/gpu/drm/vc4/vc4.ko \
- $(LINUX_DIR)/drivers/gpu/drm/drm_kms_helper.ko
+ $(LINUX_DIR)/drivers/gpu/drm/drm_kms_helper.ko \
+ $(LINUX_DIR)/drivers/media/cec/cec.ko
AUTOLOAD:=$(call AutoProbe,vc4)
endef
+++ /dev/null
-From a19956ff2941b73204c96127a22edef71b5d0d34 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Mon, 9 Sep 2019 23:50:44 +0100
-Subject: [PATCH] v3d_drv: Allow clock retrieval by name
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/gpu/drm/v3d/v3d_drv.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -285,7 +285,9 @@ static int v3d_platform_drm_probe(struct
- }
- }
-
-- v3d->clk = devm_clk_get(dev, NULL);
-+ v3d->clk = devm_clk_get(dev, "v3d");
-+ if (!v3d->clk)
-+ v3d->clk = devm_clk_get(dev, NULL);
- if (IS_ERR_OR_NULL(v3d->clk)) {
- if (PTR_ERR(v3d->clk) != -EPROBE_DEFER)
- dev_err(dev, "Failed to get clock (%ld)\n", PTR_ERR(v3d->clk));
--- /dev/null
+From dfc842c139ef08e21647c43c19c2a23090b65b27 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Thu, 5 Sep 2019 17:59:14 +0100
+Subject: [PATCH] v3d_gem: Kick the clock so firmware knows we are
+ using firmware clock interface
+
+Setting the v3d clock to low value allows firmware to handle dvfs in case
+where v3d hardware is not being actively used (e.g. console use).
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ drivers/gpu/drm/v3d/v3d_gem.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -918,6 +918,10 @@ v3d_gem_init(struct drm_device *dev)
+ mutex_init(&v3d->clk_lock);
+ INIT_DELAYED_WORK(&v3d->clk_down_work, v3d_clock_down_work);
+
++ /* kick the clock so firmware knows we are using firmware clock interface */
++ v3d_clock_up_get(v3d);
++ v3d_clock_up_put(v3d);
++
+ /* 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 6c37f43308f29a59bc67d4ed010f8fbbf076ec79 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Tue, 3 Sep 2019 20:28:00 +0100
+Subject: [PATCH] clk-bcm2835: Disable v3d clock
+
+This is controlled by firmware, see clk-raspberrypi.c
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 30 ++++++++++++------------------
+ 1 file changed, 12 insertions(+), 18 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1716,16 +1716,12 @@ static const struct bcm2835_clk_desc clk
+ .hold_mask = CM_PLLA_HOLDCORE,
+ .fixed_divider = 1,
+ .flags = CLK_SET_RATE_PARENT),
+- [BCM2835_PLLA_PER] = REGISTER_PLL_DIV(
+- SOC_ALL,
+- .name = "plla_per",
+- .source_pll = "plla",
+- .cm_reg = CM_PLLA,
+- .a2w_reg = A2W_PLLA_PER,
+- .load_mask = CM_PLLA_LOADPER,
+- .hold_mask = CM_PLLA_HOLDPER,
+- .fixed_divider = 1,
+- .flags = CLK_SET_RATE_PARENT),
++
++ /*
++ * PLLA_PER is used for gpu clocks. Controlled by firmware, see
++ * clk-raspberrypi.c.
++ */
++
+ [BCM2835_PLLA_DSI0] = REGISTER_PLL_DIV(
+ SOC_ALL,
+ .name = "plla_dsi0",
+@@ -2003,14 +1999,12 @@ static const struct bcm2835_clk_desc clk
+ .int_bits = 6,
+ .frac_bits = 0,
+ .tcnt_mux = 3),
+- [BCM2835_CLOCK_V3D] = REGISTER_VPU_CLK(
+- SOC_ALL,
+- .name = "v3d",
+- .ctl_reg = CM_V3DCTL,
+- .div_reg = CM_V3DDIV,
+- .int_bits = 4,
+- .frac_bits = 8,
+- .tcnt_mux = 4),
++
++ /*
++ * CLOCK_V3D is used for v3d clock. Controlled by firmware, see
++ * clk-raspberrypi.c.
++ */
++
+ /*
+ * VPU clock. This doesn't have an enable bit, since it drives
+ * the bus for everything else, and is special so it doesn't need
+++ /dev/null
-From dfc842c139ef08e21647c43c19c2a23090b65b27 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Thu, 5 Sep 2019 17:59:14 +0100
-Subject: [PATCH] v3d_gem: Kick the clock so firmware knows we are
- using firmware clock interface
-
-Setting the v3d clock to low value allows firmware to handle dvfs in case
-where v3d hardware is not being actively used (e.g. console use).
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- drivers/gpu/drm/v3d/v3d_gem.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/gpu/drm/v3d/v3d_gem.c
-+++ b/drivers/gpu/drm/v3d/v3d_gem.c
-@@ -918,6 +918,10 @@ v3d_gem_init(struct drm_device *dev)
- mutex_init(&v3d->clk_lock);
- INIT_DELAYED_WORK(&v3d->clk_down_work, v3d_clock_down_work);
-
-+ /* kick the clock so firmware knows we are using firmware clock interface */
-+ v3d_clock_up_get(v3d);
-+ v3d_clock_up_put(v3d);
-+
- /* 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 3e2eb77ba8d0c6913138382512309e7892907a1c Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Mon, 9 Sep 2019 15:49:56 +0100
-Subject: [PATCH] clk-raspberrypi: Allow cpufreq driver to also adjust
- gpu clocks
-
-For performance/power it is beneficial to adjust gpu clocks with arm clock.
-This is how the downstream cpufreq driver works
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- drivers/clk/bcm/clk-raspberrypi.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/clk/bcm/clk-raspberrypi.c
-+++ b/drivers/clk/bcm/clk-raspberrypi.c
-@@ -70,7 +70,7 @@ static int raspberrypi_clock_property(st
- struct raspberrypi_firmware_prop msg = {
- .id = cpu_to_le32(clk),
- .val = cpu_to_le32(*val),
-- .disable_turbo = cpu_to_le32(1),
-+ .disable_turbo = cpu_to_le32(0),
- };
- int ret;
-
--- /dev/null
+From 814af1a008845b61a08111f2f9cf7e66511ab362 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Fri, 13 Sep 2019 13:45:11 +0100
+Subject: [PATCH] raspberrypi-cpufreq: Only report integer pll divisor
+ frequencies
+
+---
+ drivers/cpufreq/raspberrypi-cpufreq.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/cpufreq/raspberrypi-cpufreq.c
++++ b/drivers/cpufreq/raspberrypi-cpufreq.c
+@@ -8,6 +8,7 @@
+ #include <linux/clk.h>
+ #include <linux/cpu.h>
+ #include <linux/cpufreq.h>
++#include <linux/math64.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_opp.h>
+@@ -22,6 +23,7 @@ static int raspberrypi_cpufreq_probe(str
+ unsigned long min, max;
+ unsigned long rate;
+ struct clk *clk;
++ int div;
+ int ret;
+
+ cpu_dev = get_cpu_device(0);
+@@ -44,7 +46,10 @@ static int raspberrypi_cpufreq_probe(str
+ max = roundup(clk_round_rate(clk, ULONG_MAX), RASPBERRYPI_FREQ_INTERVAL);
+ clk_put(clk);
+
+- for (rate = min; rate <= max; rate += RASPBERRYPI_FREQ_INTERVAL) {
++ for (div = 2; ; div++) {
++ rate = div_u64((u64)max * 2, div);
++ if (rate < min)
++ break;
+ ret = dev_pm_opp_add(cpu_dev, rate, 0);
+ if (ret)
+ goto remove_opp;
--- /dev/null
+From 4768e4d0e87e5814d3f315f7a575cad123fc2e36 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 22 Nov 2019 15:08:25 +0000
+Subject: [PATCH] arm/dts: Correct Pi 4B LED values
+
+The initial PHY LED settings are wrong Pi 4B (the correct values got
+dropped somewhere along the way). The PHY declaration should arguably
+go in a separate file included by bcm2711-rpi-4-b.dts, but we can
+fix that as we switch over to using more of the upstream BCM2711
+support in 5.4 and later.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2838.dtsi | 2 +-
+ arch/arm/boot/dts/overlays/README | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -380,7 +380,7 @@
+ /* No interrupts - use PHY_POLL */
+ max-speed = <1000>;
+ reg = <0x1>;
+- led-modes = <0x02 0x02>;
++ led-modes = <0x00 0x08>; /* link/activity link */
+ };
+ };
+ };
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -128,7 +128,7 @@ Params:
+ 8=Link 9=Activity
+
+ eth_led1 Set mode of LED1 (usually green) (Pi3B+ default
+- "6", Pi4 default "0"). See eth_led0 for legal
++ "6", Pi4 default "8"). See eth_led0 for legal
+ values.
+
+ eth_max_speed Set the maximum speed a link is allowed
+++ /dev/null
-From e2262c8ab4755ab574580611d7da22509f07871c Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Wed, 21 Aug 2019 14:55:56 +0100
-Subject: [PATCH] clk-raspberrypi: Also support v3d clock
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- drivers/clk/bcm/clk-raspberrypi.c | 501 ++++++++++++++++++++++++------
- 1 file changed, 412 insertions(+), 89 deletions(-)
-
---- a/drivers/clk/bcm/clk-raspberrypi.c
-+++ b/drivers/clk/bcm/clk-raspberrypi.c
-@@ -15,33 +15,103 @@
- #include <linux/io.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
--
-+#include <dt-bindings/clock/bcm2835.h>
- #include <soc/bcm2835/raspberrypi-firmware.h>
-
- #define RPI_FIRMWARE_ARM_CLK_ID 0x00000003
-+#define RPI_FIRMWARE_V3D_CLK_ID 0x00000005
-
- #define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0)
- #define RPI_FIRMWARE_STATE_WAIT_BIT BIT(1)
-
--/*
-- * Even though the firmware interface alters 'pllb' the frequencies are
-- * provided as per 'pllb_arm'. We need to scale before passing them trough.
-- */
--#define RPI_FIRMWARE_PLLB_ARM_DIV_RATE 2
--
- #define A2W_PLL_FRAC_BITS 20
-
-+#define SOC_BCM2835 BIT(0)
-+#define SOC_BCM2711 BIT(1)
-+#define SOC_ALL (SOC_BCM2835 | SOC_BCM2711)
-+
- struct raspberrypi_clk {
- struct device *dev;
- struct rpi_firmware *firmware;
- struct platform_device *cpufreq;
-+};
-+
-+typedef int (*raspberrypi_clk_register)(struct raspberrypi_clk *rpi,
-+ const void *data);
-+
-+
-+/* assignment helper macros for different clock types */
-+#define _REGISTER(f, s, ...) { .clk_register = (raspberrypi_clk_register)f, \
-+ .supported = s, \
-+ .data = __VA_ARGS__ }
-+#define REGISTER_PLL(s, ...) _REGISTER(&raspberrypi_register_pll, \
-+ s, \
-+ &(struct raspberrypi_pll_data) \
-+ {__VA_ARGS__})
-+#define REGISTER_PLL_DIV(s, ...) _REGISTER(&raspberrypi_register_pll_divider, \
-+ s, \
-+ &(struct raspberrypi_pll_divider_data) \
-+ {__VA_ARGS__})
-+#define REGISTER_CLK(s, ...) _REGISTER(&raspberrypi_register_clock, \
-+ s, \
-+ &(struct raspberrypi_clock_data) \
-+ {__VA_ARGS__})
-+
-+
-+struct raspberrypi_pll_data {
-+ const char *name;
-+ const char *const *parents;
-+ int num_parents;
-+ u32 clock_id;
-+};
-+
-+struct raspberrypi_clock_data {
-+ const char *name;
-+ const char *const *parents;
-+ int num_parents;
-+ u32 flags;
-+ u32 clock_id;
-+};
-+
-+struct raspberrypi_pll_divider_data {
-+ const char *name;
-+ const char *divider_name;
-+ const char *lookup;
-+ const char *source_pll;
-+
-+ u32 fixed_divider;
-+ u32 flags;
-+ u32 clock_id;
-+};
-
-- unsigned long min_rate;
-- unsigned long max_rate;
-+struct raspberrypi_clk_desc {
-+ raspberrypi_clk_register clk_register;
-+ unsigned int supported;
-+ const void *data;
-+};
-
-- struct clk_hw pllb;
-- struct clk_hw *pllb_arm;
-- struct clk_lookup *pllb_arm_lookup;
-+struct raspberrypi_clock {
-+ struct clk_hw hw;
-+ struct raspberrypi_clk *rpi;
-+ u32 min_rate;
-+ u32 max_rate;
-+ const struct raspberrypi_clock_data *data;
-+};
-+
-+struct raspberrypi_pll {
-+ struct clk_hw hw;
-+ struct raspberrypi_clk *rpi;
-+ u32 min_rate;
-+ u32 max_rate;
-+ const struct raspberrypi_pll_data *data;
-+};
-+
-+struct raspberrypi_pll_divider {
-+ struct clk_divider div;
-+ struct raspberrypi_clk *rpi;
-+ u32 min_rate;
-+ u32 max_rate;
-+ const struct raspberrypi_pll_divider_data *data;
- };
-
- /*
-@@ -83,56 +153,49 @@ static int raspberrypi_clock_property(st
- return 0;
- }
-
--static int raspberrypi_fw_pll_is_on(struct clk_hw *hw)
-+static int raspberrypi_fw_is_on(struct raspberrypi_clk *rpi, u32 clock_id, const char *name)
- {
-- struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
-- pllb);
- u32 val = 0;
- int ret;
-
- ret = raspberrypi_clock_property(rpi->firmware,
- RPI_FIRMWARE_GET_CLOCK_STATE,
-- RPI_FIRMWARE_ARM_CLK_ID, &val);
-+ clock_id, &val);
- if (ret)
- return 0;
-
- return !!(val & RPI_FIRMWARE_STATE_ENABLE_BIT);
- }
-
--
--static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw,
-- unsigned long parent_rate)
-+static unsigned long raspberrypi_fw_get_rate(struct raspberrypi_clk *rpi,
-+ u32 clock_id, const char *name, unsigned long parent_rate)
- {
-- struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
-- pllb);
- u32 val = 0;
- int ret;
-
- ret = raspberrypi_clock_property(rpi->firmware,
- RPI_FIRMWARE_GET_CLOCK_RATE,
-- RPI_FIRMWARE_ARM_CLK_ID,
-+ clock_id,
- &val);
- if (ret)
-- return ret;
--
-- return val * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
-+ dev_err_ratelimited(rpi->dev, "Failed to get %s frequency: %d",
-+ name, ret);
-+ return val;
- }
-
--static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate,
-- unsigned long parent_rate)
-+static int raspberrypi_fw_set_rate(struct raspberrypi_clk *rpi,
-+ u32 clock_id, const char *name, u32 rate,
-+ unsigned long parent_rate)
- {
-- struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
-- pllb);
-- u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
- int ret;
-
- ret = raspberrypi_clock_property(rpi->firmware,
- RPI_FIRMWARE_SET_CLOCK_RATE,
-- RPI_FIRMWARE_ARM_CLK_ID,
-- &new_rate);
-+ clock_id,
-+ &rate);
- if (ret)
- dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d",
-- clk_hw_get_name(hw), ret);
-+ name, ret);
-
- return ret;
- }
-@@ -141,16 +204,18 @@ static int raspberrypi_fw_pll_set_rate(s
- * Sadly there is no firmware rate rounding interface. We borrowed it from
- * clk-bcm2835.
- */
--static int raspberrypi_pll_determine_rate(struct clk_hw *hw,
-+static int raspberrypi_determine_rate(struct raspberrypi_clk *rpi,
-+ u32 clock_id, const char *name, unsigned long min_rate, unsigned long max_rate,
- struct clk_rate_request *req)
- {
-- struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
-- pllb);
-+#if 1
-+ req->rate = clamp(req->rate, min_rate, max_rate);
-+#else
- u64 div, final_rate;
- u32 ndiv, fdiv;
-
- /* We can't use req->rate directly as it would overflow */
-- final_rate = clamp(req->rate, rpi->min_rate, rpi->max_rate);
-+ final_rate = clamp(req->rate, min_rate, max_rate);
-
- div = (u64)final_rate << A2W_PLL_FRAC_BITS;
- do_div(div, req->best_parent_rate);
-@@ -163,9 +228,129 @@ static int raspberrypi_pll_determine_rat
-
- req->rate = final_rate >> A2W_PLL_FRAC_BITS;
-
-+#endif
- return 0;
- }
-
-+static int raspberrypi_fw_clock_is_on(struct clk_hw *hw)
-+{
-+ struct raspberrypi_clock *pll = container_of(hw, struct raspberrypi_clock, hw);
-+ struct raspberrypi_clk *rpi = pll->rpi;
-+ const struct raspberrypi_clock_data *data = pll->data;
-+
-+ return raspberrypi_fw_is_on(rpi, data->clock_id, data->name);
-+}
-+
-+static unsigned long raspberrypi_fw_clock_get_rate(struct clk_hw *hw,
-+ unsigned long parent_rate)
-+{
-+ struct raspberrypi_clock *pll = container_of(hw, struct raspberrypi_clock, hw);
-+ struct raspberrypi_clk *rpi = pll->rpi;
-+ const struct raspberrypi_clock_data *data = pll->data;
-+
-+ return raspberrypi_fw_get_rate(rpi, data->clock_id, data->name, parent_rate);
-+}
-+
-+static int raspberrypi_fw_clock_set_rate(struct clk_hw *hw, unsigned long rate,
-+ unsigned long parent_rate)
-+{
-+ struct raspberrypi_clock *pll = container_of(hw, struct raspberrypi_clock, hw);
-+ struct raspberrypi_clk *rpi = pll->rpi;
-+ const struct raspberrypi_clock_data *data = pll->data;
-+
-+ return raspberrypi_fw_set_rate(rpi, data->clock_id, data->name, rate, parent_rate);
-+}
-+
-+static int raspberrypi_clock_determine_rate(struct clk_hw *hw,
-+ struct clk_rate_request *req)
-+{
-+ struct raspberrypi_clock *pll = container_of(hw, struct raspberrypi_clock, hw);
-+ struct raspberrypi_clk *rpi = pll->rpi;
-+ const struct raspberrypi_clock_data *data = pll->data;
-+
-+ return raspberrypi_determine_rate(rpi, data->clock_id, data->name, pll->min_rate, pll->max_rate, req);
-+}
-+
-+static int raspberrypi_fw_pll_is_on(struct clk_hw *hw)
-+{
-+ struct raspberrypi_pll *pll = container_of(hw, struct raspberrypi_pll, hw);
-+ struct raspberrypi_clk *rpi = pll->rpi;
-+ const struct raspberrypi_pll_data *data = pll->data;
-+
-+ return raspberrypi_fw_is_on(rpi, data->clock_id, data->name);
-+}
-+
-+static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw,
-+ unsigned long parent_rate)
-+{
-+ struct raspberrypi_pll *pll = container_of(hw, struct raspberrypi_pll, hw);
-+ struct raspberrypi_clk *rpi = pll->rpi;
-+ const struct raspberrypi_pll_data *data = pll->data;
-+
-+ return raspberrypi_fw_get_rate(rpi, data->clock_id, data->name, parent_rate);
-+}
-+
-+static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate,
-+ unsigned long parent_rate)
-+{
-+ struct raspberrypi_pll *pll = container_of(hw, struct raspberrypi_pll, hw);
-+ struct raspberrypi_clk *rpi = pll->rpi;
-+ const struct raspberrypi_pll_data *data = pll->data;
-+
-+ return raspberrypi_fw_set_rate(rpi, data->clock_id, data->name, rate, parent_rate);
-+}
-+
-+static int raspberrypi_pll_determine_rate(struct clk_hw *hw,
-+ struct clk_rate_request *req)
-+{
-+ struct raspberrypi_pll *pll = container_of(hw, struct raspberrypi_pll, hw);
-+ struct raspberrypi_clk *rpi = pll->rpi;
-+ const struct raspberrypi_pll_data *data = pll->data;
-+
-+ return raspberrypi_determine_rate(rpi, data->clock_id, data->name, pll->min_rate, pll->max_rate, req);
-+}
-+
-+
-+static int raspberrypi_fw_pll_div_is_on(struct clk_hw *hw)
-+{
-+ struct raspberrypi_pll_divider *pll = container_of(hw, struct raspberrypi_pll_divider, div.hw);
-+ struct raspberrypi_clk *rpi = pll->rpi;
-+ const struct raspberrypi_pll_divider_data *data = pll->data;
-+
-+ return raspberrypi_fw_is_on(rpi, data->clock_id, data->name);
-+}
-+
-+static unsigned long raspberrypi_fw_pll_div_get_rate(struct clk_hw *hw,
-+ unsigned long parent_rate)
-+{
-+ struct raspberrypi_pll_divider *pll = container_of(hw, struct raspberrypi_pll_divider, div.hw);
-+ struct raspberrypi_clk *rpi = pll->rpi;
-+ const struct raspberrypi_pll_divider_data *data = pll->data;
-+
-+ return raspberrypi_fw_get_rate(rpi, data->clock_id, data->name, parent_rate);
-+}
-+
-+static int raspberrypi_fw_pll_div_set_rate(struct clk_hw *hw, unsigned long rate,
-+ unsigned long parent_rate)
-+{
-+ struct raspberrypi_pll_divider *pll = container_of(hw, struct raspberrypi_pll_divider, div.hw);
-+ struct raspberrypi_clk *rpi = pll->rpi;
-+ const struct raspberrypi_pll_divider_data *data = pll->data;
-+
-+ return raspberrypi_fw_set_rate(rpi, data->clock_id, data->name, rate, parent_rate);
-+}
-+
-+static int raspberrypi_pll_div_determine_rate(struct clk_hw *hw,
-+ struct clk_rate_request *req)
-+{
-+ struct raspberrypi_pll_divider *pll = container_of(hw, struct raspberrypi_pll_divider, div.hw);
-+ struct raspberrypi_clk *rpi = pll->rpi;
-+ const struct raspberrypi_pll_divider_data *data = pll->data;
-+
-+ return raspberrypi_determine_rate(rpi, data->clock_id, data->name, pll->min_rate, pll->max_rate, req);
-+}
-+
-+
- static const struct clk_ops raspberrypi_firmware_pll_clk_ops = {
- .is_prepared = raspberrypi_fw_pll_is_on,
- .recalc_rate = raspberrypi_fw_pll_get_rate,
-@@ -173,87 +358,225 @@ static const struct clk_ops raspberrypi_
- .determine_rate = raspberrypi_pll_determine_rate,
- };
-
--static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi)
-+static const struct clk_ops raspberrypi_firmware_pll_divider_clk_ops = {
-+ .is_prepared = raspberrypi_fw_pll_div_is_on,
-+ .recalc_rate = raspberrypi_fw_pll_div_get_rate,
-+ .set_rate = raspberrypi_fw_pll_div_set_rate,
-+ .determine_rate = raspberrypi_pll_div_determine_rate,
-+};
-+
-+static const struct clk_ops raspberrypi_firmware_clk_ops = {
-+ .is_prepared = raspberrypi_fw_clock_is_on,
-+ .recalc_rate = raspberrypi_fw_clock_get_rate,
-+ .set_rate = raspberrypi_fw_clock_set_rate,
-+ .determine_rate = raspberrypi_clock_determine_rate,
-+};
-+
-+
-+static int raspberrypi_get_clock_range(struct raspberrypi_clk *rpi, u32 clock_id, u32 *min_rate, u32 *max_rate)
- {
-- u32 min_rate = 0, max_rate = 0;
-+ int ret;
-+
-+ /* Get min & max rates set by the firmware */
-+ ret = raspberrypi_clock_property(rpi->firmware,
-+ RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
-+ clock_id,
-+ min_rate);
-+ if (ret) {
-+ dev_err(rpi->dev, "Failed to get clock %d min freq: %d (%d)\n",
-+ clock_id, *min_rate, ret);
-+ return ret;
-+ }
-+
-+ ret = raspberrypi_clock_property(rpi->firmware,
-+ RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
-+ clock_id,
-+ max_rate);
-+ if (ret) {
-+ dev_err(rpi->dev, "Failed to get clock %d max freq: %d (%d)\n",
-+ clock_id, *max_rate, ret);
-+ return ret;
-+ }
-+ return 0;
-+}
-+
-+
-+static int raspberrypi_register_pll(struct raspberrypi_clk *rpi,
-+ const struct raspberrypi_pll_data *data)
-+{
-+ struct raspberrypi_pll *pll;
- struct clk_init_data init;
- int ret;
-
- memset(&init, 0, sizeof(init));
-
- /* All of the PLLs derive from the external oscillator. */
-- init.parent_names = (const char *[]){ "osc" };
-- init.num_parents = 1;
-- init.name = "pllb";
-+ init.parent_names = data->parents;
-+ init.num_parents = data->num_parents;
-+ init.name = data->name;
- init.ops = &raspberrypi_firmware_pll_clk_ops;
- init.flags = CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED;
-
-- /* Get min & max rates set by the firmware */
-- ret = raspberrypi_clock_property(rpi->firmware,
-- RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
-- RPI_FIRMWARE_ARM_CLK_ID,
-- &min_rate);
-+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
-+ if (!pll)
-+ return -ENOMEM;
-+ pll->rpi = rpi;
-+ pll->data = data;
-+ pll->hw.init = &init;
-+
-+ ret = raspberrypi_get_clock_range(rpi, data->clock_id, &pll->min_rate, &pll->max_rate);
- if (ret) {
-- dev_err(rpi->dev, "Failed to get %s min freq: %d\n",
-- init.name, ret);
-+ dev_err(rpi->dev, "%s: raspberrypi_get_clock_range(%s) failed: %d\n", __func__, init.name, ret);
- return ret;
- }
-
-- ret = raspberrypi_clock_property(rpi->firmware,
-- RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
-- RPI_FIRMWARE_ARM_CLK_ID,
-- &max_rate);
-+ ret = devm_clk_hw_register(rpi->dev, &pll->hw);
- if (ret) {
-- dev_err(rpi->dev, "Failed to get %s max freq: %d\n",
-- init.name, ret);
-+ dev_err(rpi->dev, "%s: devm_clk_hw_register(%s) failed: %d\n", __func__, init.name, ret);
- return ret;
- }
-+ return 0;
-+}
-
-- if (!min_rate || !max_rate) {
-- dev_err(rpi->dev, "Unexpected frequency range: min %u, max %u\n",
-- min_rate, max_rate);
-- return -EINVAL;
-- }
-+static int
-+raspberrypi_register_pll_divider(struct raspberrypi_clk *rpi,
-+ const struct raspberrypi_pll_divider_data *data)
-+{
-+ struct raspberrypi_pll_divider *divider;
-+ struct clk_init_data init;
-+ int ret;
-+
-+ memset(&init, 0, sizeof(init));
-+
-+ init.parent_names = &data->source_pll;
-+ init.num_parents = 1;
-+ init.name = data->name;
-+ init.ops = &raspberrypi_firmware_pll_divider_clk_ops;
-+ init.flags = data->flags | CLK_IGNORE_UNUSED;
-
-- dev_info(rpi->dev, "CPU frequency range: min %u, max %u\n",
-- min_rate, max_rate);
-+ divider = devm_kzalloc(rpi->dev, sizeof(*divider), GFP_KERNEL);
-+ if (!divider)
-+ return -ENOMEM;
-+
-+ divider->div.hw.init = &init;
-+ divider->rpi = rpi;
-+ divider->data = data;
-+
-+ ret = raspberrypi_get_clock_range(rpi, data->clock_id, ÷r->min_rate, ÷r->max_rate);
-+ if (ret) {
-+ dev_err(rpi->dev, "%s: raspberrypi_get_clock_range(%s) failed: %d\n", __func__, init.name, ret);
-+ return ret;
-+ }
-
-- rpi->min_rate = min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
-- rpi->max_rate = max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
-+ ret = devm_clk_hw_register(rpi->dev, ÷r->div.hw);
-+ if (ret) {
-+ dev_err(rpi->dev, "%s: devm_clk_hw_register(%s) failed: %d\n", __func__, init.name, ret);
-+ return ret;
-+ }
-
-- rpi->pllb.init = &init;
-+ /*
-+ * PLLH's channels have a fixed divide by 10 afterwards, which
-+ * is what our consumers are actually using.
-+ */
-+ if (data->fixed_divider != 0) {
-+ struct clk_lookup *lookup;
-+ struct clk_hw *clk = clk_hw_register_fixed_factor(rpi->dev,
-+ data->divider_name,
-+ data->name,
-+ CLK_SET_RATE_PARENT,
-+ 1,
-+ data->fixed_divider);
-+ if (IS_ERR(clk)) {
-+ dev_err(rpi->dev, "%s: clk_hw_register_fixed_factor(%s) failed: %ld\n", __func__, init.name, PTR_ERR(clk));
-+ return PTR_ERR(clk);
-+ }
-+ if (data->lookup) {
-+ lookup = clkdev_hw_create(clk, NULL, data->lookup);
-+ if (IS_ERR(lookup)) {
-+ dev_err(rpi->dev, "%s: clk_hw_register_fixed_factor(%s) failed: %ld\n", __func__, init.name, PTR_ERR(lookup));
-+ return PTR_ERR(lookup);
-+ }
-+ }
-+ }
-
-- return devm_clk_hw_register(rpi->dev, &rpi->pllb);
-+ return 0;
- }
-
--static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
-+static int raspberrypi_register_clock(struct raspberrypi_clk *rpi,
-+ const struct raspberrypi_clock_data *data)
- {
-- rpi->pllb_arm = clk_hw_register_fixed_factor(rpi->dev,
-- "pllb_arm", "pllb",
-- CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
-- 1, 2);
-- if (IS_ERR(rpi->pllb_arm)) {
-- dev_err(rpi->dev, "Failed to initialize pllb_arm\n");
-- return PTR_ERR(rpi->pllb_arm);
-- }
-+ struct raspberrypi_clock *clock;
-+ struct clk_init_data init;
-+ struct clk *clk;
-+ int ret;
-+
-+ memset(&init, 0, sizeof(init));
-+ init.parent_names = data->parents;
-+ init.num_parents = data->num_parents;
-+ init.name = data->name;
-+ init.flags = data->flags | CLK_IGNORE_UNUSED;
-
-- rpi->pllb_arm_lookup = clkdev_hw_create(rpi->pllb_arm, NULL, "cpu0");
-- if (!rpi->pllb_arm_lookup) {
-- dev_err(rpi->dev, "Failed to initialize pllb_arm_lookup\n");
-- clk_hw_unregister_fixed_factor(rpi->pllb_arm);
-+ init.ops = &raspberrypi_firmware_clk_ops;
-+
-+ clock = devm_kzalloc(rpi->dev, sizeof(*clock), GFP_KERNEL);
-+ if (!clock)
- return -ENOMEM;
-- }
-
-+ clock->rpi = rpi;
-+ clock->data = data;
-+ clock->hw.init = &init;
-+
-+ ret = raspberrypi_get_clock_range(rpi, data->clock_id, &clock->min_rate, &clock->max_rate);
-+ if (ret) {
-+ dev_err(rpi->dev, "%s: raspberrypi_get_clock_range(%s) failed: %d\n", __func__, init.name, ret);
-+ return ret;
-+ }
-+ clk = devm_clk_register(rpi->dev, &clock->hw);
-+ if (IS_ERR(clk)) {
-+ dev_err(rpi->dev, "%s: devm_clk_register(%s) failed: %ld\n", __func__, init.name, PTR_ERR(clk));
-+ return PTR_ERR(clk);
-+ }
-+ ret = clk_register_clkdev(clk, init.name, NULL);
-+ if (ret) {
-+ dev_err(rpi->dev, "%s: clk_register_clkdev(%s) failed: %d\n", __func__, init.name, ret);
-+ return ret;
-+ }
- return 0;
- }
-
-+
-+/*
-+ * the real definition of all the pll, pll_dividers and clocks
-+ * these make use of the above REGISTER_* macros
-+ */
-+static const struct raspberrypi_clk_desc clk_desc_array[] = {
-+ /* the PLL + PLL dividers */
-+ [BCM2835_CLOCK_V3D] = REGISTER_CLK(
-+ SOC_ALL,
-+ .name = "v3d",
-+ .parents = (const char *[]){ "osc" },
-+ .num_parents = 1,
-+ .clock_id = RPI_FIRMWARE_V3D_CLK_ID),
-+ [BCM2835_PLLB_ARM] = REGISTER_PLL_DIV(
-+ SOC_ALL,
-+ .name = "pllb",
-+ .source_pll = "osc",
-+ .divider_name = "pllb_arm",
-+ .lookup = "cpu0",
-+ .fixed_divider = 1,
-+ .clock_id = RPI_FIRMWARE_ARM_CLK_ID,
-+ .flags = CLK_SET_RATE_PARENT),
-+};
-+
- static int raspberrypi_clk_probe(struct platform_device *pdev)
- {
- struct device_node *firmware_node;
- struct device *dev = &pdev->dev;
- struct rpi_firmware *firmware;
- struct raspberrypi_clk *rpi;
-- int ret;
-+ const struct raspberrypi_clk_desc *desc;
-+ const size_t asize = ARRAY_SIZE(clk_desc_array);
-+ int i;
-
- firmware_node = of_find_compatible_node(NULL, NULL,
- "raspberrypi,bcm2835-firmware");
-@@ -275,16 +598,16 @@ static int raspberrypi_clk_probe(struct
- rpi->firmware = firmware;
- platform_set_drvdata(pdev, rpi);
-
-- ret = raspberrypi_register_pllb(rpi);
-- if (ret) {
-- dev_err(dev, "Failed to initialize pllb, %d\n", ret);
-- return ret;
-+ for (i = 0; i < asize; i++) {
-+ desc = &clk_desc_array[i];
-+ if (desc->clk_register && desc->data /*&&
-+ (desc->supported & pdata->soc)*/) {
-+ int ret = desc->clk_register(rpi, desc->data);
-+ if (ret)
-+ return ret;
-+ }
- }
-
-- ret = raspberrypi_register_pllb_arm(rpi);
-- if (ret)
-- return ret;
--
- rpi->cpufreq = platform_device_register_data(dev, "raspberrypi-cpufreq",
- -1, NULL, 0);
-
+++ /dev/null
-From 6c37f43308f29a59bc67d4ed010f8fbbf076ec79 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Tue, 3 Sep 2019 20:28:00 +0100
-Subject: [PATCH] clk-bcm2835: Disable v3d clock
-
-This is controlled by firmware, see clk-raspberrypi.c
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- drivers/clk/bcm/clk-bcm2835.c | 30 ++++++++++++------------------
- 1 file changed, 12 insertions(+), 18 deletions(-)
-
---- a/drivers/clk/bcm/clk-bcm2835.c
-+++ b/drivers/clk/bcm/clk-bcm2835.c
-@@ -1716,16 +1716,12 @@ static const struct bcm2835_clk_desc clk
- .hold_mask = CM_PLLA_HOLDCORE,
- .fixed_divider = 1,
- .flags = CLK_SET_RATE_PARENT),
-- [BCM2835_PLLA_PER] = REGISTER_PLL_DIV(
-- SOC_ALL,
-- .name = "plla_per",
-- .source_pll = "plla",
-- .cm_reg = CM_PLLA,
-- .a2w_reg = A2W_PLLA_PER,
-- .load_mask = CM_PLLA_LOADPER,
-- .hold_mask = CM_PLLA_HOLDPER,
-- .fixed_divider = 1,
-- .flags = CLK_SET_RATE_PARENT),
-+
-+ /*
-+ * PLLA_PER is used for gpu clocks. Controlled by firmware, see
-+ * clk-raspberrypi.c.
-+ */
-+
- [BCM2835_PLLA_DSI0] = REGISTER_PLL_DIV(
- SOC_ALL,
- .name = "plla_dsi0",
-@@ -2003,14 +1999,12 @@ static const struct bcm2835_clk_desc clk
- .int_bits = 6,
- .frac_bits = 0,
- .tcnt_mux = 3),
-- [BCM2835_CLOCK_V3D] = REGISTER_VPU_CLK(
-- SOC_ALL,
-- .name = "v3d",
-- .ctl_reg = CM_V3DCTL,
-- .div_reg = CM_V3DDIV,
-- .int_bits = 4,
-- .frac_bits = 8,
-- .tcnt_mux = 4),
-+
-+ /*
-+ * CLOCK_V3D is used for v3d clock. Controlled by firmware, see
-+ * clk-raspberrypi.c.
-+ */
-+
- /*
- * VPU clock. This doesn't have an enable bit, since it drives
- * the bus for everything else, and is special so it doesn't need
--- /dev/null
+From 159ccf0090f202cf031fa429df22e8b3f775ece8 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 22 Nov 2019 16:23:32 +0000
+Subject: [PATCH] drm/v3d: Set dma_mask as well as coherent_dma_mask
+
+Both coherent_dma_mask and dma_mask act as constraints on allocations
+and bounce buffer usage, so be sure to set dma_mask to the appropriate
+value otherwise the effective mask could be incorrect.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/gpu/drm/v3d/v3d_drv.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -259,8 +259,8 @@ static int v3d_platform_drm_probe(struct
+ goto dev_free;
+
+ mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO);
+- dev->coherent_dma_mask =
+- DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH));
++ dma_set_mask_and_coherent(dev,
++ DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH)));
+ v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH);
+
+ ident1 = V3D_READ(V3D_HUB_IDENT1);
--- /dev/null
+From ea94fb0b5693c354e5281eb3fcdbc9700cdd3d7f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 28 Nov 2019 15:49:08 +0000
+Subject: [PATCH] arm/dts: 2711: Add 'pcie0' alias
+
+It is useful for the firmware to be able to locate the pcie DT node,
+so add an alias pointing to it in the same way that "ethernet0"
+points to the genet.
+
+Signed-off-by: Phil Elwell <phil@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
+@@ -30,6 +30,7 @@
+ /delete-property/ ethernet;
+ /delete-property/ intc;
+ ethernet0 = &genet;
++ pcie0 = &pcie_0;
+ };
+ };
+
+++ /dev/null
-From 814af1a008845b61a08111f2f9cf7e66511ab362 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Fri, 13 Sep 2019 13:45:11 +0100
-Subject: [PATCH] raspberrypi-cpufreq: Only report integer pll divisor
- frequencies
-
----
- drivers/cpufreq/raspberrypi-cpufreq.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
---- a/drivers/cpufreq/raspberrypi-cpufreq.c
-+++ b/drivers/cpufreq/raspberrypi-cpufreq.c
-@@ -8,6 +8,7 @@
- #include <linux/clk.h>
- #include <linux/cpu.h>
- #include <linux/cpufreq.h>
-+#include <linux/math64.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/pm_opp.h>
-@@ -22,6 +23,7 @@ static int raspberrypi_cpufreq_probe(str
- unsigned long min, max;
- unsigned long rate;
- struct clk *clk;
-+ int div;
- int ret;
-
- cpu_dev = get_cpu_device(0);
-@@ -44,7 +46,10 @@ static int raspberrypi_cpufreq_probe(str
- max = roundup(clk_round_rate(clk, ULONG_MAX), RASPBERRYPI_FREQ_INTERVAL);
- clk_put(clk);
-
-- for (rate = min; rate <= max; rate += RASPBERRYPI_FREQ_INTERVAL) {
-+ for (div = 2; ; div++) {
-+ rate = div_u64((u64)max * 2, div);
-+ if (rate < min)
-+ break;
- ret = dev_pm_opp_add(cpu_dev, rate, 0);
- if (ret)
- goto remove_opp;
+++ /dev/null
-From 4768e4d0e87e5814d3f315f7a575cad123fc2e36 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 22 Nov 2019 15:08:25 +0000
-Subject: [PATCH] arm/dts: Correct Pi 4B LED values
-
-The initial PHY LED settings are wrong Pi 4B (the correct values got
-dropped somewhere along the way). The PHY declaration should arguably
-go in a separate file included by bcm2711-rpi-4-b.dts, but we can
-fix that as we switch over to using more of the upstream BCM2711
-support in 5.4 and later.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/bcm2838.dtsi | 2 +-
- arch/arm/boot/dts/overlays/README | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/bcm2838.dtsi
-+++ b/arch/arm/boot/dts/bcm2838.dtsi
-@@ -380,7 +380,7 @@
- /* No interrupts - use PHY_POLL */
- max-speed = <1000>;
- reg = <0x1>;
-- led-modes = <0x02 0x02>;
-+ led-modes = <0x00 0x08>; /* link/activity link */
- };
- };
- };
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -128,7 +128,7 @@ Params:
- 8=Link 9=Activity
-
- eth_led1 Set mode of LED1 (usually green) (Pi3B+ default
-- "6", Pi4 default "0"). See eth_led0 for legal
-+ "6", Pi4 default "8"). See eth_led0 for legal
- values.
-
- eth_max_speed Set the maximum speed a link is allowed
--- /dev/null
+From 01f45f7d4403e40f28f626296bec3ccae1b1f65b Mon Sep 17 00:00:00 2001
+From: Matthias Reichl <hias@horus.com>
+Date: Sat, 30 Nov 2019 23:10:26 +0100
+Subject: [PATCH] rpi-cirrus-wm5102-overlay: fix pinctrl configuration
+
+Separate GPIOs connected to wm5102 and wm8804 into 2 pinctrl
+blocks and properly reference them from the DT nodes to have
+correct pinmux owners.
+
+Setup spi0 to use only one CS line on GPIO7 so that GPIO8 is
+no longer claimed by spi0 but can be used by wm8804.
+
+Signed-off-by: Matthias Reichl <hias@horus.com>
+---
+ .../overlays/rpi-cirrus-wm5102-overlay.dts | 40 ++++++++++++++-----
+ 1 file changed, 30 insertions(+), 10 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
+@@ -18,19 +18,31 @@
+ fragment@1 {
+ target = <&gpio>;
+ __overlay__ {
+- wlf_pins: wlf_pins {
+- brcm,pins = <17 22 27 8>;
++ wlf_5102_pins: wlf_5102_pins {
++ brcm,pins = <17 22 27>;
+ brcm,function = <
+ BCM2835_FSEL_GPIO_OUT
+ BCM2835_FSEL_GPIO_OUT
+ BCM2835_FSEL_GPIO_IN
+- BCM2835_FSEL_GPIO_OUT
+ >;
+ };
++ wlf_8804_pins: wlf_8804_pins {
++ brcm,pins = <8>;
++ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++ };
+ };
+ };
+
+ fragment@2 {
++ target = <&spi0_cs_pins>;
++ __overlay__ {
++ brcm,pins = <7>;
++ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++ };
++ };
++
++
++ fragment@3 {
+ target-path = "/";
+ __overlay__ {
+ rpi_cirrus_reg_1v8: rpi_cirrus_reg_1v8 {
+@@ -43,30 +55,34 @@
+ };
+ };
+
+- fragment@3 {
++ fragment@4 {
+ target = <&spidev0>;
+ __overlay__ {
+ status = "disabled";
+ };
+ };
+
+- fragment@4 {
++ fragment@5 {
+ target = <&spidev1>;
+ __overlay__ {
+ status = "disabled";
+ };
+ };
+
+- fragment@5 {
++ fragment@6 {
+ target = <&spi0>;
+ __overlay__ {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
++ cs-gpios = <&gpio 7 GPIO_ACTIVE_LOW>;
+
+- wm5102@1{
++ wm5102@0{
+ compatible = "wlf,wm5102";
+- reg = <1>;
++ reg = <0>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&wlf_5102_pins>;
+
+ spi-max-frequency = <500000>;
+
+@@ -123,7 +139,7 @@
+ };
+ };
+
+- fragment@6 {
++ fragment@7 {
+ target = <&i2c1>;
+ __overlay__ {
+ status = "okay";
+@@ -134,6 +150,10 @@
+ compatible = "wlf,wm8804";
+ reg = <0x3b>;
+ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&wlf_8804_pins>;
++
+ PVDD-supply = <&vdd_3v3_reg>;
+ DVDD-supply = <&vdd_3v3_reg>;
+ wlf,reset-gpio = <&gpio 8 GPIO_ACTIVE_HIGH>;
+@@ -141,7 +161,7 @@
+ };
+ };
+
+- fragment@7 {
++ fragment@8 {
+ target = <&sound>;
+ __overlay__ {
+ compatible = "wlf,rpi-cirrus";
+++ /dev/null
-From 159ccf0090f202cf031fa429df22e8b3f775ece8 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 22 Nov 2019 16:23:32 +0000
-Subject: [PATCH] drm/v3d: Set dma_mask as well as coherent_dma_mask
-
-Both coherent_dma_mask and dma_mask act as constraints on allocations
-and bounce buffer usage, so be sure to set dma_mask to the appropriate
-value otherwise the effective mask could be incorrect.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/gpu/drm/v3d/v3d_drv.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/v3d/v3d_drv.c
-+++ b/drivers/gpu/drm/v3d/v3d_drv.c
-@@ -259,8 +259,8 @@ static int v3d_platform_drm_probe(struct
- goto dev_free;
-
- mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO);
-- dev->coherent_dma_mask =
-- DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH));
-+ dma_set_mask_and_coherent(dev,
-+ DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH)));
- v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH);
-
- ident1 = V3D_READ(V3D_HUB_IDENT1);
--- /dev/null
+From a9b691174273348a6818213b9f008ae555e1c98c 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] 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>
+---
+ .../staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -3195,6 +3195,12 @@ vchiq_register_child(struct platform_dev
+ child = 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 child;
+ }
+
+++ /dev/null
-From ea94fb0b5693c354e5281eb3fcdbc9700cdd3d7f Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Thu, 28 Nov 2019 15:49:08 +0000
-Subject: [PATCH] arm/dts: 2711: Add 'pcie0' alias
-
-It is useful for the firmware to be able to locate the pcie DT node,
-so add an alias pointing to it in the same way that "ethernet0"
-points to the genet.
-
-Signed-off-by: Phil Elwell <phil@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
-@@ -30,6 +30,7 @@
- /delete-property/ ethernet;
- /delete-property/ intc;
- ethernet0 = &genet;
-+ pcie0 = &pcie_0;
- };
- };
-
--- /dev/null
+From 6aa74a52e014952b1a144def670a03a7deb0e112 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] 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
+@@ -3181,6 +3181,7 @@ vchiq_register_child(struct platform_dev
+ {
+ struct platform_device_info pdevinfo;
+ struct platform_device *child;
++ struct device_node *np;
+
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+
+@@ -3196,10 +3197,20 @@ vchiq_register_child(struct platform_dev
+ }
+
+ /*
+- * 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(&child->dev, np, true);
++
++ if (np != pdev->dev.of_node)
++ of_node_put(np);
+
+ return child;
+ }
--- /dev/null
+From 271a9dfee2eb426ca9ec1ef51c6205de8496b803 Mon Sep 17 00:00:00 2001
+From: Hui Wang <hui.wang@canonical.com>
+Date: Sun, 17 Nov 2019 10:31:46 +0800
+Subject: [PATCH] dwc_otg: checking the urb->transfer_buffer too early
+ (#3332)
+
+After enable the HIGHMEM and VMSPLIT_3G, the dwc_otg driver doesn't
+work well on Pi2/3 boards with 1G physical ram. Users experience
+the failure when copying a file of 600M size to the USB stick. And
+at the same time, the dmesg shows:
+usb 1-1.1.2: reset high-speed USB device number 8 using dwc_otg
+sd 0:0:0:0: [sda] tag#0 FAILED Result: hostbyte=DID_ERROR driverbyte=DRIVER_OK
+blk_update_request: I/O error, dev sda, sector 3024048 op 0x1:(WRITE) flags 0x4000 phys_seg 15 prio class 0
+
+When this happens, the sg_buf sent to the driver is located in the
+highmem region, the usb_sg_init() in the core/message.c will leave
+transfer_buffer to NULL if the sg_buf is in highmem, but in the
+dwc_otg driver, it returns -EINVAL unconditionally if transfer_buffer
+is NULL.
+
+The driver can handle the situation of buffer to be NULL, if it is in
+DMA mode, it will convert an address from transfer_dma.
+
+But if the conversion fails or it is in the PIO mode, we should check
+buffer and return -EINVAL if it is NULL.
+
+BugLink: https://bugs.launchpad.net/bugs/1852510
+Signed-off-by: Hui Wang <hui.wang@canonical.com>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+@@ -782,10 +782,6 @@ static int dwc_otg_urb_enqueue(struct us
+ dump_urb_info(urb, "dwc_otg_urb_enqueue");
+ }
+ #endif
+-
+- if (!urb->transfer_buffer && urb->transfer_buffer_length)
+- return -EINVAL;
+-
+ if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+ || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
+ if (!dwc_otg_hcd_is_bandwidth_allocated
+@@ -842,6 +838,13 @@ static int dwc_otg_urb_enqueue(struct us
+ &urb->transfer_dma, buf);
+ }
+
++ if (!buf && urb->transfer_buffer_length) {
++ DWC_FREE(dwc_otg_urb);
++ DWC_ERROR("transfer_buffer is NULL in PIO mode or both "
++ "transfer_buffer and transfer_dma are NULL in DMA mode\n");
++ return -EINVAL;
++ }
++
+ if (!(urb->transfer_flags & URB_NO_INTERRUPT))
+ flags |= URB_GIVEBACK_ASAP;
+ if (urb->transfer_flags & URB_ZERO_PACKET)
+++ /dev/null
-From 01f45f7d4403e40f28f626296bec3ccae1b1f65b Mon Sep 17 00:00:00 2001
-From: Matthias Reichl <hias@horus.com>
-Date: Sat, 30 Nov 2019 23:10:26 +0100
-Subject: [PATCH] rpi-cirrus-wm5102-overlay: fix pinctrl configuration
-
-Separate GPIOs connected to wm5102 and wm8804 into 2 pinctrl
-blocks and properly reference them from the DT nodes to have
-correct pinmux owners.
-
-Setup spi0 to use only one CS line on GPIO7 so that GPIO8 is
-no longer claimed by spi0 but can be used by wm8804.
-
-Signed-off-by: Matthias Reichl <hias@horus.com>
----
- .../overlays/rpi-cirrus-wm5102-overlay.dts | 40 ++++++++++++++-----
- 1 file changed, 30 insertions(+), 10 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
-@@ -18,19 +18,31 @@
- fragment@1 {
- target = <&gpio>;
- __overlay__ {
-- wlf_pins: wlf_pins {
-- brcm,pins = <17 22 27 8>;
-+ wlf_5102_pins: wlf_5102_pins {
-+ brcm,pins = <17 22 27>;
- brcm,function = <
- BCM2835_FSEL_GPIO_OUT
- BCM2835_FSEL_GPIO_OUT
- BCM2835_FSEL_GPIO_IN
-- BCM2835_FSEL_GPIO_OUT
- >;
- };
-+ wlf_8804_pins: wlf_8804_pins {
-+ brcm,pins = <8>;
-+ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
-+ };
- };
- };
-
- fragment@2 {
-+ target = <&spi0_cs_pins>;
-+ __overlay__ {
-+ brcm,pins = <7>;
-+ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
-+ };
-+ };
-+
-+
-+ fragment@3 {
- target-path = "/";
- __overlay__ {
- rpi_cirrus_reg_1v8: rpi_cirrus_reg_1v8 {
-@@ -43,30 +55,34 @@
- };
- };
-
-- fragment@3 {
-+ fragment@4 {
- target = <&spidev0>;
- __overlay__ {
- status = "disabled";
- };
- };
-
-- fragment@4 {
-+ fragment@5 {
- target = <&spidev1>;
- __overlay__ {
- status = "disabled";
- };
- };
-
-- fragment@5 {
-+ fragment@6 {
- target = <&spi0>;
- __overlay__ {
- #address-cells = <1>;
- #size-cells = <0>;
- status = "okay";
-+ cs-gpios = <&gpio 7 GPIO_ACTIVE_LOW>;
-
-- wm5102@1{
-+ wm5102@0{
- compatible = "wlf,wm5102";
-- reg = <1>;
-+ reg = <0>;
-+
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&wlf_5102_pins>;
-
- spi-max-frequency = <500000>;
-
-@@ -123,7 +139,7 @@
- };
- };
-
-- fragment@6 {
-+ fragment@7 {
- target = <&i2c1>;
- __overlay__ {
- status = "okay";
-@@ -134,6 +150,10 @@
- compatible = "wlf,wm8804";
- reg = <0x3b>;
- status = "okay";
-+
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&wlf_8804_pins>;
-+
- PVDD-supply = <&vdd_3v3_reg>;
- DVDD-supply = <&vdd_3v3_reg>;
- wlf,reset-gpio = <&gpio 8 GPIO_ACTIVE_HIGH>;
-@@ -141,7 +161,7 @@
- };
- };
-
-- fragment@7 {
-+ fragment@8 {
- target = <&sound>;
- __overlay__ {
- compatible = "wlf,rpi-cirrus";
--- /dev/null
+From 00f01136b1c165e0f4a190fcb5ec8aa11428362f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 9 Dec 2019 12:32:20 +0000
+Subject: [PATCH] overlays: Make mcp342x run-time compatible
+
+The order of processing of run-time overlays differs from that done by
+the firmware. This means that certain parameter processing techniques
+are not compatible with run-time use. The mcp342x overlay is one such
+overlay, but it is easy to change the implementation without changing
+the interface.
+
+See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=258294
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ .../arm/boot/dts/overlays/mcp342x-overlay.dts | 133 ++++++++++++++----
+ 1 file changed, 102 insertions(+), 31 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
+@@ -8,14 +8,15 @@
+
+ fragment@0 {
+ target = <&i2c1>;
+- __overlay__ {
++ __dormant__ {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "okay";
+
+- mcp342x: mcp@68 {
++ mcp3421: mcp@68 {
+ reg = <0x68>;
++ compatible = "microchip,mcp3421";
+
+ status = "okay";
+ };
+@@ -23,71 +24,141 @@
+ };
+
+ fragment@1 {
+- target = <&mcp342x>;
++ target = <&i2c1>;
+ __dormant__ {
+- compatible = "microchip,mcp3421";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "okay";
++
++ mcp3422: mcp@68 {
++ reg = <0x68>;
++ compatible = "microchip,mcp3422";
++
++ status = "okay";
++ };
+ };
+ };
+
+ fragment@2 {
+- target = <&mcp342x>;
++ target = <&i2c1>;
+ __dormant__ {
+- compatible = "microchip,mcp3422";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "okay";
++
++ mcp3423: mcp@68 {
++ reg = <0x68>;
++ compatible = "microchip,mcp3423";
++
++ status = "okay";
++ };
+ };
+ };
+
+ fragment@3 {
+- target = <&mcp342x>;
++ target = <&i2c1>;
+ __dormant__ {
+- compatible = "microchip,mcp3423";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "okay";
++
++ mcp3424: mcp@68 {
++ reg = <0x68>;
++ compatible = "microchip,mcp3424";
++
++ status = "okay";
++ };
+ };
+ };
+
+ fragment@4 {
+- target = <&mcp342x>;
++ target = <&i2c1>;
+ __dormant__ {
+- compatible = "microchip,mcp3424";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "okay";
++
++ mcp3425: mcp@68 {
++ reg = <0x68>;
++ compatible = "microchip,mcp3425","mcp3425";
++
++ status = "okay";
++ };
+ };
+ };
+
+ fragment@5 {
+- target = <&mcp342x>;
++ target = <&i2c1>;
+ __dormant__ {
+- compatible = "microchip,mcp3425";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "okay";
++
++ mcp3426: mcp@68 {
++ reg = <0x68>;
++ compatible = "microchip,mcp3426";
++
++ status = "okay";
++ };
+ };
+ };
+
+ fragment@6 {
+- target = <&mcp342x>;
++ target = <&i2c1>;
+ __dormant__ {
+- compatible = "microchip,mcp3426";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "okay";
++
++ mcp3427: mcp@68 {
++ reg = <0x68>;
++ compatible = "microchip,mcp3427";
++
++ status = "okay";
++ };
+ };
+ };
+
+ fragment@7 {
+- target = <&mcp342x>;
++ target = <&i2c1>;
+ __dormant__ {
+- compatible = "microchip,mcp3427";
+- };
+- };
++ #address-cells = <1>;
++ #size-cells = <0>;
+
+- fragment@8 {
+- target = <&mcp342x>;
+- __dormant__ {
+- compatible = "microchip,mcp3428";
++ status = "okay";
++
++ mcp3428: mcp@68 {
++ reg = <0x68>;
++ compatible = "microchip,mcp3428";
++
++ status = "okay";
++ };
+ };
+ };
+
+ __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";
++ addr = <&mcp3421>,"reg:0",
++ <&mcp3422>,"reg:0",
++ <&mcp3423>,"reg:0",
++ <&mcp3424>,"reg:0",
++ <&mcp3425>,"reg:0",
++ <&mcp3426>,"reg:0",
++ <&mcp3427>,"reg:0",
++ <&mcp3428>,"reg:0";
++ mcp3421 = <0>,"=0";
++ mcp3422 = <0>,"=1";
++ mcp3423 = <0>,"=2";
++ mcp3424 = <0>,"=3";
++ mcp3425 = <0>,"=4";
++ mcp3426 = <0>,"=5";
++ mcp3427 = <0>,"=6";
++ mcp3428 = <0>,"=7";
+ };
+ };
+
+++ /dev/null
-From a9b691174273348a6818213b9f008ae555e1c98c 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] 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>
----
- .../staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
-@@ -3195,6 +3195,12 @@ vchiq_register_child(struct platform_dev
- child = 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 child;
- }
-
--- /dev/null
+From ea2cfc97596be37164d2f5d3d1a4f5e2d6cca062 Mon Sep 17 00:00:00 2001
+From: Matthias Reichl <hias@horus.com>
+Date: Mon, 16 Dec 2019 23:25:44 +0100
+Subject: [PATCH] rpi-cirrus-wm5102-overlay: use reset-gpios instead of
+ wlf,reset
+
+wlf,reset has been deprecated in favour of the standard reset-gpios
+DT property in commit fced2963d84b44990f4aa99ed7268223c294c0df so
+let's use that instead of the old property.
+
+Signed-off-by: Matthias Reichl <hias@horus.com>
+---
+ arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
+@@ -104,7 +104,7 @@
+ SPKVDDR-supply = <&vdd_5v0_reg>;
+ DCVDD-supply = <&arizona_ldo1>;
+
+- wlf,reset = <&gpio 17 GPIO_ACTIVE_HIGH>;
++ reset-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
+ wlf,ldoena = <&gpio 22 GPIO_ACTIVE_HIGH>;
+ wlf,gpio-defaults = <
+ ARIZONA_GP_DEFAULT
+++ /dev/null
-From 6aa74a52e014952b1a144def670a03a7deb0e112 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] 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
-@@ -3181,6 +3181,7 @@ vchiq_register_child(struct platform_dev
- {
- struct platform_device_info pdevinfo;
- struct platform_device *child;
-+ struct device_node *np;
-
- memset(&pdevinfo, 0, sizeof(pdevinfo));
-
-@@ -3196,10 +3197,20 @@ vchiq_register_child(struct platform_dev
- }
-
- /*
-- * 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(&child->dev, np, true);
-+
-+ if (np != pdev->dev.of_node)
-+ of_node_put(np);
-
- return child;
- }
+++ /dev/null
-From 271a9dfee2eb426ca9ec1ef51c6205de8496b803 Mon Sep 17 00:00:00 2001
-From: Hui Wang <hui.wang@canonical.com>
-Date: Sun, 17 Nov 2019 10:31:46 +0800
-Subject: [PATCH] dwc_otg: checking the urb->transfer_buffer too early
- (#3332)
-
-After enable the HIGHMEM and VMSPLIT_3G, the dwc_otg driver doesn't
-work well on Pi2/3 boards with 1G physical ram. Users experience
-the failure when copying a file of 600M size to the USB stick. And
-at the same time, the dmesg shows:
-usb 1-1.1.2: reset high-speed USB device number 8 using dwc_otg
-sd 0:0:0:0: [sda] tag#0 FAILED Result: hostbyte=DID_ERROR driverbyte=DRIVER_OK
-blk_update_request: I/O error, dev sda, sector 3024048 op 0x1:(WRITE) flags 0x4000 phys_seg 15 prio class 0
-
-When this happens, the sg_buf sent to the driver is located in the
-highmem region, the usb_sg_init() in the core/message.c will leave
-transfer_buffer to NULL if the sg_buf is in highmem, but in the
-dwc_otg driver, it returns -EINVAL unconditionally if transfer_buffer
-is NULL.
-
-The driver can handle the situation of buffer to be NULL, if it is in
-DMA mode, it will convert an address from transfer_dma.
-
-But if the conversion fails or it is in the PIO mode, we should check
-buffer and return -EINVAL if it is NULL.
-
-BugLink: https://bugs.launchpad.net/bugs/1852510
-Signed-off-by: Hui Wang <hui.wang@canonical.com>
----
- drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 11 +++++++----
- 1 file changed, 7 insertions(+), 4 deletions(-)
-
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-@@ -782,10 +782,6 @@ static int dwc_otg_urb_enqueue(struct us
- dump_urb_info(urb, "dwc_otg_urb_enqueue");
- }
- #endif
--
-- if (!urb->transfer_buffer && urb->transfer_buffer_length)
-- return -EINVAL;
--
- if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
- || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
- if (!dwc_otg_hcd_is_bandwidth_allocated
-@@ -842,6 +838,13 @@ static int dwc_otg_urb_enqueue(struct us
- &urb->transfer_dma, buf);
- }
-
-+ if (!buf && urb->transfer_buffer_length) {
-+ DWC_FREE(dwc_otg_urb);
-+ DWC_ERROR("transfer_buffer is NULL in PIO mode or both "
-+ "transfer_buffer and transfer_dma are NULL in DMA mode\n");
-+ return -EINVAL;
-+ }
-+
- if (!(urb->transfer_flags & URB_NO_INTERRUPT))
- flags |= URB_GIVEBACK_ASAP;
- if (urb->transfer_flags & URB_ZERO_PACKET)
--- /dev/null
+From 3a0fad11000e1533c3132e024304cbe8b4f0f826 Mon Sep 17 00:00:00 2001
+From: Johannes Krude <johannes@krude.de>
+Date: Sat, 16 Nov 2019 12:41:06 +0100
+Subject: [PATCH] sound/soc: only first codec is master in multicodec
+ setup
+
+When using multiple codecs, at most one codec should generate the master
+clock. All codecs except the first are therefore configured for slave
+mode.
+
+Signed-off-by: Johannes Krude <johannes@krude.de>
+---
+ sound/soc/soc-core.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/sound/soc/soc-core.c
++++ b/sound/soc/soc-core.c
+@@ -1656,7 +1656,15 @@ int snd_soc_runtime_set_dai_fmt(struct s
+ int ret;
+
+ for_each_rtd_codec_dai(rtd, i, codec_dai) {
+- ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
++ unsigned int codec_dai_fmt = dai_fmt;
++
++ // there can only be one master when using multiple codecs
++ if (i && (codec_dai_fmt & SND_SOC_DAIFMT_MASTER_MASK)) {
++ codec_dai_fmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
++ codec_dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
++ }
++
++ ret = snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
+ if (ret != 0 && ret != -ENOTSUPP) {
+ dev_warn(codec_dai->dev,
+ "ASoC: Failed to set DAI format: %d\n", ret);
--- /dev/null
+From eecd29a4a5ede49427e48ea27e372b96d11f3d04 Mon Sep 17 00:00:00 2001
+From: Johannes Krude <johannes@krude.de>
+Date: Sat, 16 Nov 2019 13:14:43 +0100
+Subject: [PATCH] Allow simultaneous use of JustBoom DAC and Digi
+
+Signed-off-by: Johannes Krude <johannes@krude.de>
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 20 ++
+ .../dts/overlays/justboom-both-overlay.dts | 65 +++++
+ sound/soc/bcm/Kconfig | 12 +
+ sound/soc/bcm/Makefile | 2 +
+ sound/soc/bcm/justboom-both.c | 266 ++++++++++++++++++
+ 11 files changed, 371 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/justboom-both-overlay.dts
+ create mode 100644 sound/soc/bcm/justboom-both.c
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -86,6 +86,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ iqaudio-digi-wm8804-audio.dtbo \
+ irs1125.dtbo \
+ jedec-spi-nor.dtbo \
++ justboom-both.dtbo \
+ justboom-dac.dtbo \
+ justboom-digi.dtbo \
+ ltc294x.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1388,6 +1388,26 @@ Params: flash-spi<n>-<m> Enables
+ on SPI<n>, CS#<m>.
+
+
++Name: justboom-both
++Info: Simultaneous usage of an justboom-dac and justboom-digi based
++ card
++Load: dtoverlay=justboom-both,<param>=<val>
++Params: 24db_digital_gain Allow gain to be applied via the PCM512x codec
++ Digital volume control. Enable with
++ "dtoverlay=justboom-dac,24db_digital_gain"
++ (The default behaviour is that the Digital
++ volume control is limited to a maximum of
++ 0dB. ie. it can attenuate but not provide
++ gain. For most users, this will be desired
++ as it will prevent clipping. By appending
++ the 24dB_digital_gain parameter, the Digital
++ volume control will allow up to 24dB of
++ gain. If this parameter is enabled, it is the
++ responsibility of the user to ensure that
++ the Digital volume control is set to a value
++ that does not result in clipping/distortion!)
++
++
+ Name: justboom-dac
+ Info: Configures the JustBoom DAC HAT, Amp HAT, DAC Zero and Amp Zero audio
+ cards
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/justboom-both-overlay.dts
+@@ -0,0 +1,65 @@
++// SPDX-License-Identifier: GPL-2.0
++// Definitions for JustBoom Both (Digi+DAC)
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "brcm,bcm2835";
++
++ fragment@0 {
++ target = <&i2s>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@1 {
++ target = <&i2c1>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ wm8804@3b {
++ #sound-dai-cells = <0>;
++ compatible = "wlf,wm8804";
++ reg = <0x3b>;
++ PVDD-supply = <&vdd_3v3_reg>;
++ DVDD-supply = <&vdd_3v3_reg>;
++ status = "okay";
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&i2c1>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ pcm5122@4d {
++ #sound-dai-cells = <0>;
++ compatible = "ti,pcm5122";
++ reg = <0x4d>;
++ AVDD-supply = <&vdd_3v3_reg>;
++ DVDD-supply = <&vdd_3v3_reg>;
++ CPVDD-supply = <&vdd_3v3_reg>;
++ status = "okay";
++ };
++ };
++ };
++
++ fragment@3 {
++ target = <&sound>;
++ frag3: __overlay__ {
++ compatible = "justboom,justboom-both";
++ i2s-controller = <&i2s>;
++ status = "okay";
++ };
++ };
++
++ __overrides__ {
++ 24db_digital_gain = <&frag3>,"justboom,24db_digital_gain?";
++ };
++};
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -105,6 +105,18 @@ config SND_BCM2708_SOC_RPI_PROTO
+ help
+ Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731).
+
++config SND_BCM2708_SOC_JUSTBOOM_BOTH
++ tristate "Support for simultaneous JustBoom Digi and JustBoom DAC"
++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++ select SND_SOC_WM8804
++ select SND_SOC_PCM512x
++ help
++ Say Y or M if you want to add support for simultaneous
++ JustBoom Digi and JustBoom DAC.
++
++ This is not the right choice if you only have one but both of
++ these cards.
++
+ config SND_BCM2708_SOC_JUSTBOOM_DAC
+ tristate "Support for JustBoom DAC"
+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -17,6 +17,7 @@ snd-soc-hifiberry-dacplus-objs := hifibe
+ snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
+ snd-soc-hifiberry-dacplusadcpro-objs := hifiberry_dacplusadcpro.o
+ snd-soc-hifiberry-dacplusdsp-objs := hifiberry_dacplusdsp.o
++snd-soc-justboom-both-objs := justboom-both.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
+@@ -43,6 +44,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D
+ 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_HIFIBERRY_DACPLUSDSP) += snd-soc-hifiberry-dacplusdsp.o
++obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_BOTH) += snd-soc-justboom-both.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/justboom-both.c
+@@ -0,0 +1,266 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * rpi--wm8804.c -- ALSA SoC Raspberry Pi soundcard.
++ *
++ * Authors: Johannes Krude <johannes@krude.de
++ *
++ * Driver for when connecting simultaneously justboom-digi and justboom-dac
++ *
++ * Based upon code from:
++ * justboom-digi.c
++ * by Milan Neskovic <info@justboom.co>
++ * justboom-dac.c
++ * by Milan Neskovic <info@justboom.co>
++ *
++ * 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 <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/jack.h>
++
++#include "../codecs/wm8804.h"
++#include "../codecs/pcm512x.h"
++
++
++static bool digital_gain_0db_limit = true;
++
++static int snd_rpi_justboom_both_init(struct snd_soc_pcm_runtime *rtd)
++{
++ struct snd_soc_component *digi = rtd->codec_dais[0]->component;
++ struct snd_soc_component *dac = rtd->codec_dais[1]->component;
++
++ /* enable TX output */
++ snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x4, 0x0);
++
++ snd_soc_component_update_bits(dac, PCM512x_GPIO_EN, 0x08, 0x08);
++ snd_soc_component_update_bits(dac, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02);
++ snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
++
++ if (digital_gain_0db_limit) {
++ int ret;
++ struct snd_soc_card *card = rtd->card;
++
++ ret = snd_soc_limit_volume(card, "Digital Playback Volume",
++ 207);
++ if (ret < 0)
++ dev_warn(card->dev, "Failed to set volume limit: %d\n",
++ ret);
++ }
++
++ return 0;
++}
++
++static int snd_rpi_justboom_both_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_dai *codec_dai = rtd->codec_dai;
++ struct snd_soc_component *digi = rtd->codec_dais[0]->component;
++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
++
++ int sysclk = 27000000; /* This is fixed on this board */
++
++ long mclk_freq = 0;
++ int mclk_div = 1;
++ int sampling_freq = 1;
++
++ int ret;
++
++ int samplerate = params_rate(params);
++
++ if (samplerate <= 96000) {
++ mclk_freq = samplerate*256;
++ mclk_div = WM8804_MCLKDIV_256FS;
++ } else {
++ mclk_freq = samplerate*128;
++ mclk_div = WM8804_MCLKDIV_128FS;
++ }
++
++ switch (samplerate) {
++ case 32000:
++ sampling_freq = 0x03;
++ break;
++ case 44100:
++ sampling_freq = 0x00;
++ break;
++ case 48000:
++ sampling_freq = 0x02;
++ break;
++ case 88200:
++ sampling_freq = 0x08;
++ break;
++ case 96000:
++ sampling_freq = 0x0a;
++ break;
++ case 176400:
++ sampling_freq = 0x0c;
++ break;
++ case 192000:
++ sampling_freq = 0x0e;
++ break;
++ default:
++ dev_err(rtd->card->dev,
++ "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n",
++ samplerate);
++ }
++
++ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div);
++ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq);
++
++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL,
++ sysclk, SND_SOC_CLOCK_OUT);
++ if (ret < 0) {
++ dev_err(rtd->card->dev,
++ "Failed to set WM8804 SYSCLK: %d\n", ret);
++ return ret;
++ }
++
++ /* Enable TX output */
++ snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x4, 0x0);
++
++ /* Power on */
++ snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x9, 0);
++
++ /* set sampling frequency status bits */
++ snd_soc_component_update_bits(digi, WM8804_SPDTX4, 0x0f, sampling_freq);
++
++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
++}
++
++static int snd_rpi_justboom_both_startup(struct snd_pcm_substream *substream)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_component *digi = rtd->codec_dais[0]->component;
++ struct snd_soc_component *dac = rtd->codec_dais[1]->component;
++
++ /* turn on digital output */
++ snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x3c, 0x00);
++
++ snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
++
++ return 0;
++}
++
++static void snd_rpi_justboom_both_shutdown(struct snd_pcm_substream *substream)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_component *digi = rtd->codec_dais[0]->component;
++ struct snd_soc_component *dac = rtd->codec_dais[1]->component;
++
++ snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
++
++ /* turn off output */
++ snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x3c, 0x3c);
++}
++
++/* machine stream operations */
++static struct snd_soc_ops snd_rpi_justboom_both_ops = {
++ .hw_params = snd_rpi_justboom_both_hw_params,
++ .startup = snd_rpi_justboom_both_startup,
++ .shutdown = snd_rpi_justboom_both_shutdown,
++};
++
++SND_SOC_DAILINK_DEFS(rpi_justboom_both,
++ DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
++ DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi"),
++ COMP_CODEC("wm8804.1-003b", "wm8804-spdif")),
++ DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
++
++static struct snd_soc_dai_link snd_rpi_justboom_both_dai[] = {
++{
++ .name = "JustBoom Digi",
++ .stream_name = "JustBoom Digi HiFi",
++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBM_CFM,
++ .ops = &snd_rpi_justboom_both_ops,
++ .init = snd_rpi_justboom_both_init,
++ SND_SOC_DAILINK_REG(rpi_justboom_both),
++},
++};
++
++/* audio machine driver */
++static struct snd_soc_card snd_rpi_justboom_both = {
++ .name = "snd_rpi_justboom_both",
++ .driver_name = "JustBoomBoth",
++ .owner = THIS_MODULE,
++ .dai_link = snd_rpi_justboom_both_dai,
++ .num_links = ARRAY_SIZE(snd_rpi_justboom_both_dai),
++};
++
++static int snd_rpi_justboom_both_probe(struct platform_device *pdev)
++{
++ int ret = 0;
++ struct snd_soc_card *card = &snd_rpi_justboom_both;
++
++ snd_rpi_justboom_both.dev = &pdev->dev;
++
++ if (pdev->dev.of_node) {
++ struct device_node *i2s_node;
++ struct snd_soc_dai_link *dai = &snd_rpi_justboom_both_dai[0];
++
++ i2s_node = of_parse_phandle(pdev->dev.of_node,
++ "i2s-controller", 0);
++
++ if (i2s_node) {
++ int i;
++
++ for (i = 0; i < card->num_links; i++) {
++ dai->cpus->dai_name = NULL;
++ dai->cpus->of_node = i2s_node;
++ dai->platforms->name = NULL;
++ dai->platforms->of_node = i2s_node;
++ }
++ }
++
++ digital_gain_0db_limit = !of_property_read_bool(
++ pdev->dev.of_node, "justboom,24db_digital_gain");
++ }
++
++ ret = snd_soc_register_card(card);
++ if (ret && ret != -EPROBE_DEFER) {
++ dev_err(&pdev->dev,
++ "snd_soc_register_card() failed: %d\n", ret);
++ }
++
++ return ret;
++}
++
++static int snd_rpi_justboom_both_remove(struct platform_device *pdev)
++{
++ return snd_soc_unregister_card(&snd_rpi_justboom_both);
++}
++
++static const struct of_device_id snd_rpi_justboom_both_of_match[] = {
++ { .compatible = "justboom,justboom-both", },
++ {},
++};
++MODULE_DEVICE_TABLE(of, snd_rpi_justboom_both_of_match);
++
++static struct platform_driver snd_rpi_justboom_both_driver = {
++ .driver = {
++ .name = "snd-rpi-justboom-both",
++ .owner = THIS_MODULE,
++ .of_match_table = snd_rpi_justboom_both_of_match,
++ },
++ .probe = snd_rpi_justboom_both_probe,
++ .remove = snd_rpi_justboom_both_remove,
++};
++
++module_platform_driver(snd_rpi_justboom_both_driver);
++
++MODULE_AUTHOR("Johannes Krude <johannes@krude.de>");
++MODULE_DESCRIPTION("ASoC Driver for simultaneous use of JustBoom PI Digi & DAC HAT Sound Cards");
++MODULE_LICENSE("GPL v2");
+++ /dev/null
-From 00f01136b1c165e0f4a190fcb5ec8aa11428362f Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 9 Dec 2019 12:32:20 +0000
-Subject: [PATCH] overlays: Make mcp342x run-time compatible
-
-The order of processing of run-time overlays differs from that done by
-the firmware. This means that certain parameter processing techniques
-are not compatible with run-time use. The mcp342x overlay is one such
-overlay, but it is easy to change the implementation without changing
-the interface.
-
-See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=258294
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- .../arm/boot/dts/overlays/mcp342x-overlay.dts | 133 ++++++++++++++----
- 1 file changed, 102 insertions(+), 31 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/mcp342x-overlay.dts
-@@ -8,14 +8,15 @@
-
- fragment@0 {
- target = <&i2c1>;
-- __overlay__ {
-+ __dormant__ {
- #address-cells = <1>;
- #size-cells = <0>;
-
- status = "okay";
-
-- mcp342x: mcp@68 {
-+ mcp3421: mcp@68 {
- reg = <0x68>;
-+ compatible = "microchip,mcp3421";
-
- status = "okay";
- };
-@@ -23,71 +24,141 @@
- };
-
- fragment@1 {
-- target = <&mcp342x>;
-+ target = <&i2c1>;
- __dormant__ {
-- compatible = "microchip,mcp3421";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ status = "okay";
-+
-+ mcp3422: mcp@68 {
-+ reg = <0x68>;
-+ compatible = "microchip,mcp3422";
-+
-+ status = "okay";
-+ };
- };
- };
-
- fragment@2 {
-- target = <&mcp342x>;
-+ target = <&i2c1>;
- __dormant__ {
-- compatible = "microchip,mcp3422";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ status = "okay";
-+
-+ mcp3423: mcp@68 {
-+ reg = <0x68>;
-+ compatible = "microchip,mcp3423";
-+
-+ status = "okay";
-+ };
- };
- };
-
- fragment@3 {
-- target = <&mcp342x>;
-+ target = <&i2c1>;
- __dormant__ {
-- compatible = "microchip,mcp3423";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ status = "okay";
-+
-+ mcp3424: mcp@68 {
-+ reg = <0x68>;
-+ compatible = "microchip,mcp3424";
-+
-+ status = "okay";
-+ };
- };
- };
-
- fragment@4 {
-- target = <&mcp342x>;
-+ target = <&i2c1>;
- __dormant__ {
-- compatible = "microchip,mcp3424";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ status = "okay";
-+
-+ mcp3425: mcp@68 {
-+ reg = <0x68>;
-+ compatible = "microchip,mcp3425","mcp3425";
-+
-+ status = "okay";
-+ };
- };
- };
-
- fragment@5 {
-- target = <&mcp342x>;
-+ target = <&i2c1>;
- __dormant__ {
-- compatible = "microchip,mcp3425";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ status = "okay";
-+
-+ mcp3426: mcp@68 {
-+ reg = <0x68>;
-+ compatible = "microchip,mcp3426";
-+
-+ status = "okay";
-+ };
- };
- };
-
- fragment@6 {
-- target = <&mcp342x>;
-+ target = <&i2c1>;
- __dormant__ {
-- compatible = "microchip,mcp3426";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ status = "okay";
-+
-+ mcp3427: mcp@68 {
-+ reg = <0x68>;
-+ compatible = "microchip,mcp3427";
-+
-+ status = "okay";
-+ };
- };
- };
-
- fragment@7 {
-- target = <&mcp342x>;
-+ target = <&i2c1>;
- __dormant__ {
-- compatible = "microchip,mcp3427";
-- };
-- };
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-
-- fragment@8 {
-- target = <&mcp342x>;
-- __dormant__ {
-- compatible = "microchip,mcp3428";
-+ status = "okay";
-+
-+ mcp3428: mcp@68 {
-+ reg = <0x68>;
-+ compatible = "microchip,mcp3428";
-+
-+ status = "okay";
-+ };
- };
- };
-
- __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";
-+ addr = <&mcp3421>,"reg:0",
-+ <&mcp3422>,"reg:0",
-+ <&mcp3423>,"reg:0",
-+ <&mcp3424>,"reg:0",
-+ <&mcp3425>,"reg:0",
-+ <&mcp3426>,"reg:0",
-+ <&mcp3427>,"reg:0",
-+ <&mcp3428>,"reg:0";
-+ mcp3421 = <0>,"=0";
-+ mcp3422 = <0>,"=1";
-+ mcp3423 = <0>,"=2";
-+ mcp3424 = <0>,"=3";
-+ mcp3425 = <0>,"=4";
-+ mcp3426 = <0>,"=5";
-+ mcp3427 = <0>,"=6";
-+ mcp3428 = <0>,"=7";
- };
- };
-
--- /dev/null
+From 5c1a2df946720816c155ff38b01bcd49a0f44f78 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 18 Dec 2019 10:41:33 +0000
+Subject: [PATCH] overlays: dht11: Allow multiple instantiation
+
+Add addresses to the dht11 and dht11_pins nodes to allow unique names
+to be generated by assigning to the "reg" property.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/dht11-overlay.dts | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/dht11-overlay.dts
++++ b/arch/arm/boot/dts/overlays/dht11-overlay.dts
+@@ -24,7 +24,7 @@
+ fragment@1 {
+ target = <&gpio>;
+ __overlay__ {
+- dht11_pins: dht11_pins {
++ dht11_pins: dht11_pins@0 {
+ brcm,pins = <4>;
+ brcm,function = <0>; // in
+ brcm,pull = <0>; // off
+@@ -34,6 +34,8 @@
+
+ __overrides__ {
+ gpiopin = <&dht11_pins>,"brcm,pins:0",
+- <&dht11>,"gpios:4";
++ <&dht11_pins>, "reg:0",
++ <&dht11>,"gpios:4",
++ <&dht11>,"reg:0";
+ };
+ };
+++ /dev/null
-From ea2cfc97596be37164d2f5d3d1a4f5e2d6cca062 Mon Sep 17 00:00:00 2001
-From: Matthias Reichl <hias@horus.com>
-Date: Mon, 16 Dec 2019 23:25:44 +0100
-Subject: [PATCH] rpi-cirrus-wm5102-overlay: use reset-gpios instead of
- wlf,reset
-
-wlf,reset has been deprecated in favour of the standard reset-gpios
-DT property in commit fced2963d84b44990f4aa99ed7268223c294c0df so
-let's use that instead of the old property.
-
-Signed-off-by: Matthias Reichl <hias@horus.com>
----
- arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
-@@ -104,7 +104,7 @@
- SPKVDDR-supply = <&vdd_5v0_reg>;
- DCVDD-supply = <&arizona_ldo1>;
-
-- wlf,reset = <&gpio 17 GPIO_ACTIVE_HIGH>;
-+ reset-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
- wlf,ldoena = <&gpio 22 GPIO_ACTIVE_HIGH>;
- wlf,gpio-defaults = <
- ARIZONA_GP_DEFAULT
--- /dev/null
+From 32dbe4ebb10b96eed117852f1643bf1f854d96c0 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Sun, 22 Dec 2019 15:29:40 +0000
+Subject: [PATCH] overlays: i2c-rtc: Add pcf85363 support
+
+See: https://github.com/raspberrypi/firmware/issues/1309
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ arch/arm/boot/dts/overlays/README | 2 ++
+ arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 16 ++++++++++++++++
+ 2 files changed, 18 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1078,6 +1078,8 @@ Params: abx80x Select o
+
+ pcf8523 Select the PCF8523 device
+
++ pcf85363 Select the PCF85363 device
++
+ pcf8563 Select the PCF8563 device
+
+ rv3028 Select the Micro Crystal RV3028 device
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -188,6 +188,21 @@
+ };
+ };
+
++ fragment@12 {
++ target = <&i2c_arm>;
++ __dormant__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ pcf85363@51 {
++ compatible = "nxp,pcf85363";
++ reg = <0x51>;
++ status = "okay";
++ };
++ };
++ };
++
+ __overrides__ {
+ abx80x = <0>,"+0";
+ ds1307 = <0>,"+1";
+@@ -201,6 +216,7 @@
+ m41t62 = <0>,"+9";
+ rv3028 = <0>,"+10";
+ pcf2129 = <0>,"+11";
++ pcf85363 = <0>,"+12";
+
+ addr = <&abx80x>, "reg:0",
+ <&ds1307>, "reg:0",
+++ /dev/null
-From 3a0fad11000e1533c3132e024304cbe8b4f0f826 Mon Sep 17 00:00:00 2001
-From: Johannes Krude <johannes@krude.de>
-Date: Sat, 16 Nov 2019 12:41:06 +0100
-Subject: [PATCH] sound/soc: only first codec is master in multicodec
- setup
-
-When using multiple codecs, at most one codec should generate the master
-clock. All codecs except the first are therefore configured for slave
-mode.
-
-Signed-off-by: Johannes Krude <johannes@krude.de>
----
- sound/soc/soc-core.c | 10 +++++++++-
- 1 file changed, 9 insertions(+), 1 deletion(-)
-
---- a/sound/soc/soc-core.c
-+++ b/sound/soc/soc-core.c
-@@ -1656,7 +1656,15 @@ int snd_soc_runtime_set_dai_fmt(struct s
- int ret;
-
- for_each_rtd_codec_dai(rtd, i, codec_dai) {
-- ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
-+ unsigned int codec_dai_fmt = dai_fmt;
-+
-+ // there can only be one master when using multiple codecs
-+ if (i && (codec_dai_fmt & SND_SOC_DAIFMT_MASTER_MASK)) {
-+ codec_dai_fmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
-+ codec_dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
-+ }
-+
-+ ret = snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
- if (ret != 0 && ret != -ENOTSUPP) {
- dev_warn(codec_dai->dev,
- "ASoC: Failed to set DAI format: %d\n", ret);
+++ /dev/null
-From eecd29a4a5ede49427e48ea27e372b96d11f3d04 Mon Sep 17 00:00:00 2001
-From: Johannes Krude <johannes@krude.de>
-Date: Sat, 16 Nov 2019 13:14:43 +0100
-Subject: [PATCH] Allow simultaneous use of JustBoom DAC and Digi
-
-Signed-off-by: Johannes Krude <johannes@krude.de>
----
- arch/arm/boot/dts/overlays/Makefile | 1 +
- arch/arm/boot/dts/overlays/README | 20 ++
- .../dts/overlays/justboom-both-overlay.dts | 65 +++++
- sound/soc/bcm/Kconfig | 12 +
- sound/soc/bcm/Makefile | 2 +
- sound/soc/bcm/justboom-both.c | 266 ++++++++++++++++++
- 11 files changed, 371 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/justboom-both-overlay.dts
- create mode 100644 sound/soc/bcm/justboom-both.c
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -86,6 +86,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
- iqaudio-digi-wm8804-audio.dtbo \
- irs1125.dtbo \
- jedec-spi-nor.dtbo \
-+ justboom-both.dtbo \
- justboom-dac.dtbo \
- justboom-digi.dtbo \
- ltc294x.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1388,6 +1388,26 @@ Params: flash-spi<n>-<m> Enables
- on SPI<n>, CS#<m>.
-
-
-+Name: justboom-both
-+Info: Simultaneous usage of an justboom-dac and justboom-digi based
-+ card
-+Load: dtoverlay=justboom-both,<param>=<val>
-+Params: 24db_digital_gain Allow gain to be applied via the PCM512x codec
-+ Digital volume control. Enable with
-+ "dtoverlay=justboom-dac,24db_digital_gain"
-+ (The default behaviour is that the Digital
-+ volume control is limited to a maximum of
-+ 0dB. ie. it can attenuate but not provide
-+ gain. For most users, this will be desired
-+ as it will prevent clipping. By appending
-+ the 24dB_digital_gain parameter, the Digital
-+ volume control will allow up to 24dB of
-+ gain. If this parameter is enabled, it is the
-+ responsibility of the user to ensure that
-+ the Digital volume control is set to a value
-+ that does not result in clipping/distortion!)
-+
-+
- Name: justboom-dac
- Info: Configures the JustBoom DAC HAT, Amp HAT, DAC Zero and Amp Zero audio
- cards
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/justboom-both-overlay.dts
-@@ -0,0 +1,65 @@
-+// SPDX-License-Identifier: GPL-2.0
-+// Definitions for JustBoom Both (Digi+DAC)
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+ compatible = "brcm,bcm2835";
-+
-+ fragment@0 {
-+ target = <&i2s>;
-+ __overlay__ {
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&i2c1>;
-+ __overlay__ {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "okay";
-+
-+ wm8804@3b {
-+ #sound-dai-cells = <0>;
-+ compatible = "wlf,wm8804";
-+ reg = <0x3b>;
-+ PVDD-supply = <&vdd_3v3_reg>;
-+ DVDD-supply = <&vdd_3v3_reg>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ fragment@2 {
-+ target = <&i2c1>;
-+ __overlay__ {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "okay";
-+
-+ pcm5122@4d {
-+ #sound-dai-cells = <0>;
-+ compatible = "ti,pcm5122";
-+ reg = <0x4d>;
-+ AVDD-supply = <&vdd_3v3_reg>;
-+ DVDD-supply = <&vdd_3v3_reg>;
-+ CPVDD-supply = <&vdd_3v3_reg>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ fragment@3 {
-+ target = <&sound>;
-+ frag3: __overlay__ {
-+ compatible = "justboom,justboom-both";
-+ i2s-controller = <&i2s>;
-+ status = "okay";
-+ };
-+ };
-+
-+ __overrides__ {
-+ 24db_digital_gain = <&frag3>,"justboom,24db_digital_gain?";
-+ };
-+};
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -105,6 +105,18 @@ config SND_BCM2708_SOC_RPI_PROTO
- help
- Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731).
-
-+config SND_BCM2708_SOC_JUSTBOOM_BOTH
-+ tristate "Support for simultaneous JustBoom Digi and JustBoom DAC"
-+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+ select SND_SOC_WM8804
-+ select SND_SOC_PCM512x
-+ help
-+ Say Y or M if you want to add support for simultaneous
-+ JustBoom Digi and JustBoom DAC.
-+
-+ This is not the right choice if you only have one but both of
-+ these cards.
-+
- config SND_BCM2708_SOC_JUSTBOOM_DAC
- tristate "Support for JustBoom DAC"
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -17,6 +17,7 @@ snd-soc-hifiberry-dacplus-objs := hifibe
- snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
- snd-soc-hifiberry-dacplusadcpro-objs := hifiberry_dacplusadcpro.o
- snd-soc-hifiberry-dacplusdsp-objs := hifiberry_dacplusdsp.o
-+snd-soc-justboom-both-objs := justboom-both.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
-@@ -43,6 +44,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D
- 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_HIFIBERRY_DACPLUSDSP) += snd-soc-hifiberry-dacplusdsp.o
-+obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_BOTH) += snd-soc-justboom-both.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/justboom-both.c
-@@ -0,0 +1,266 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * rpi--wm8804.c -- ALSA SoC Raspberry Pi soundcard.
-+ *
-+ * Authors: Johannes Krude <johannes@krude.de
-+ *
-+ * Driver for when connecting simultaneously justboom-digi and justboom-dac
-+ *
-+ * Based upon code from:
-+ * justboom-digi.c
-+ * by Milan Neskovic <info@justboom.co>
-+ * justboom-dac.c
-+ * by Milan Neskovic <info@justboom.co>
-+ *
-+ * 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 <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/jack.h>
-+
-+#include "../codecs/wm8804.h"
-+#include "../codecs/pcm512x.h"
-+
-+
-+static bool digital_gain_0db_limit = true;
-+
-+static int snd_rpi_justboom_both_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+ struct snd_soc_component *digi = rtd->codec_dais[0]->component;
-+ struct snd_soc_component *dac = rtd->codec_dais[1]->component;
-+
-+ /* enable TX output */
-+ snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x4, 0x0);
-+
-+ snd_soc_component_update_bits(dac, PCM512x_GPIO_EN, 0x08, 0x08);
-+ snd_soc_component_update_bits(dac, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02);
-+ snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
-+
-+ if (digital_gain_0db_limit) {
-+ int ret;
-+ struct snd_soc_card *card = rtd->card;
-+
-+ ret = snd_soc_limit_volume(card, "Digital Playback Volume",
-+ 207);
-+ if (ret < 0)
-+ dev_warn(card->dev, "Failed to set volume limit: %d\n",
-+ ret);
-+ }
-+
-+ return 0;
-+}
-+
-+static int snd_rpi_justboom_both_hw_params(struct snd_pcm_substream *substream,
-+ struct snd_pcm_hw_params *params)
-+{
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
-+ struct snd_soc_component *digi = rtd->codec_dais[0]->component;
-+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-+
-+ int sysclk = 27000000; /* This is fixed on this board */
-+
-+ long mclk_freq = 0;
-+ int mclk_div = 1;
-+ int sampling_freq = 1;
-+
-+ int ret;
-+
-+ int samplerate = params_rate(params);
-+
-+ if (samplerate <= 96000) {
-+ mclk_freq = samplerate*256;
-+ mclk_div = WM8804_MCLKDIV_256FS;
-+ } else {
-+ mclk_freq = samplerate*128;
-+ mclk_div = WM8804_MCLKDIV_128FS;
-+ }
-+
-+ switch (samplerate) {
-+ case 32000:
-+ sampling_freq = 0x03;
-+ break;
-+ case 44100:
-+ sampling_freq = 0x00;
-+ break;
-+ case 48000:
-+ sampling_freq = 0x02;
-+ break;
-+ case 88200:
-+ sampling_freq = 0x08;
-+ break;
-+ case 96000:
-+ sampling_freq = 0x0a;
-+ break;
-+ case 176400:
-+ sampling_freq = 0x0c;
-+ break;
-+ case 192000:
-+ sampling_freq = 0x0e;
-+ break;
-+ default:
-+ dev_err(rtd->card->dev,
-+ "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n",
-+ samplerate);
-+ }
-+
-+ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div);
-+ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq);
-+
-+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL,
-+ sysclk, SND_SOC_CLOCK_OUT);
-+ if (ret < 0) {
-+ dev_err(rtd->card->dev,
-+ "Failed to set WM8804 SYSCLK: %d\n", ret);
-+ return ret;
-+ }
-+
-+ /* Enable TX output */
-+ snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x4, 0x0);
-+
-+ /* Power on */
-+ snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x9, 0);
-+
-+ /* set sampling frequency status bits */
-+ snd_soc_component_update_bits(digi, WM8804_SPDTX4, 0x0f, sampling_freq);
-+
-+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
-+}
-+
-+static int snd_rpi_justboom_both_startup(struct snd_pcm_substream *substream)
-+{
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct snd_soc_component *digi = rtd->codec_dais[0]->component;
-+ struct snd_soc_component *dac = rtd->codec_dais[1]->component;
-+
-+ /* turn on digital output */
-+ snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x3c, 0x00);
-+
-+ snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
-+
-+ return 0;
-+}
-+
-+static void snd_rpi_justboom_both_shutdown(struct snd_pcm_substream *substream)
-+{
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct snd_soc_component *digi = rtd->codec_dais[0]->component;
-+ struct snd_soc_component *dac = rtd->codec_dais[1]->component;
-+
-+ snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
-+
-+ /* turn off output */
-+ snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x3c, 0x3c);
-+}
-+
-+/* machine stream operations */
-+static struct snd_soc_ops snd_rpi_justboom_both_ops = {
-+ .hw_params = snd_rpi_justboom_both_hw_params,
-+ .startup = snd_rpi_justboom_both_startup,
-+ .shutdown = snd_rpi_justboom_both_shutdown,
-+};
-+
-+SND_SOC_DAILINK_DEFS(rpi_justboom_both,
-+ DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
-+ DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi"),
-+ COMP_CODEC("wm8804.1-003b", "wm8804-spdif")),
-+ DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
-+
-+static struct snd_soc_dai_link snd_rpi_justboom_both_dai[] = {
-+{
-+ .name = "JustBoom Digi",
-+ .stream_name = "JustBoom Digi HiFi",
-+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-+ SND_SOC_DAIFMT_CBM_CFM,
-+ .ops = &snd_rpi_justboom_both_ops,
-+ .init = snd_rpi_justboom_both_init,
-+ SND_SOC_DAILINK_REG(rpi_justboom_both),
-+},
-+};
-+
-+/* audio machine driver */
-+static struct snd_soc_card snd_rpi_justboom_both = {
-+ .name = "snd_rpi_justboom_both",
-+ .driver_name = "JustBoomBoth",
-+ .owner = THIS_MODULE,
-+ .dai_link = snd_rpi_justboom_both_dai,
-+ .num_links = ARRAY_SIZE(snd_rpi_justboom_both_dai),
-+};
-+
-+static int snd_rpi_justboom_both_probe(struct platform_device *pdev)
-+{
-+ int ret = 0;
-+ struct snd_soc_card *card = &snd_rpi_justboom_both;
-+
-+ snd_rpi_justboom_both.dev = &pdev->dev;
-+
-+ if (pdev->dev.of_node) {
-+ struct device_node *i2s_node;
-+ struct snd_soc_dai_link *dai = &snd_rpi_justboom_both_dai[0];
-+
-+ i2s_node = of_parse_phandle(pdev->dev.of_node,
-+ "i2s-controller", 0);
-+
-+ if (i2s_node) {
-+ int i;
-+
-+ for (i = 0; i < card->num_links; i++) {
-+ dai->cpus->dai_name = NULL;
-+ dai->cpus->of_node = i2s_node;
-+ dai->platforms->name = NULL;
-+ dai->platforms->of_node = i2s_node;
-+ }
-+ }
-+
-+ digital_gain_0db_limit = !of_property_read_bool(
-+ pdev->dev.of_node, "justboom,24db_digital_gain");
-+ }
-+
-+ ret = snd_soc_register_card(card);
-+ if (ret && ret != -EPROBE_DEFER) {
-+ dev_err(&pdev->dev,
-+ "snd_soc_register_card() failed: %d\n", ret);
-+ }
-+
-+ return ret;
-+}
-+
-+static int snd_rpi_justboom_both_remove(struct platform_device *pdev)
-+{
-+ return snd_soc_unregister_card(&snd_rpi_justboom_both);
-+}
-+
-+static const struct of_device_id snd_rpi_justboom_both_of_match[] = {
-+ { .compatible = "justboom,justboom-both", },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, snd_rpi_justboom_both_of_match);
-+
-+static struct platform_driver snd_rpi_justboom_both_driver = {
-+ .driver = {
-+ .name = "snd-rpi-justboom-both",
-+ .owner = THIS_MODULE,
-+ .of_match_table = snd_rpi_justboom_both_of_match,
-+ },
-+ .probe = snd_rpi_justboom_both_probe,
-+ .remove = snd_rpi_justboom_both_remove,
-+};
-+
-+module_platform_driver(snd_rpi_justboom_both_driver);
-+
-+MODULE_AUTHOR("Johannes Krude <johannes@krude.de>");
-+MODULE_DESCRIPTION("ASoC Driver for simultaneous use of JustBoom PI Digi & DAC HAT Sound Cards");
-+MODULE_LICENSE("GPL v2");
--- /dev/null
+From 0cddfafa817a776063ba6f00fb439d9a415235f9 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 6 Jan 2020 16:04:30 +0000
+Subject: [PATCH] pinctrl: bcm2835: Remove gpiochip on error
+
+A failure in gpiochip_irqchip_add leads to a leak of a gpiochip. Fix
+the leak with the use of devm_gpiochip_add_data.
+
+Fixes: 85ae9e512f43 ("pinctrl: bcm2835: switch to GPIOLIB_IRQCHIP")
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+@@ -1135,7 +1135,7 @@ static int bcm2835_pinctrl_probe(struct
+ raw_spin_lock_init(&pc->irq_lock[i]);
+ }
+
+- err = gpiochip_add_data(&pc->gpio_chip, pc);
++ err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc);
+ if (err) {
+ dev_err(dev, "could not add GPIO chip\n");
+ return err;
+++ /dev/null
-From 5c1a2df946720816c155ff38b01bcd49a0f44f78 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 18 Dec 2019 10:41:33 +0000
-Subject: [PATCH] overlays: dht11: Allow multiple instantiation
-
-Add addresses to the dht11 and dht11_pins nodes to allow unique names
-to be generated by assigning to the "reg" property.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/dht11-overlay.dts | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/overlays/dht11-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/dht11-overlay.dts
-@@ -24,7 +24,7 @@
- fragment@1 {
- target = <&gpio>;
- __overlay__ {
-- dht11_pins: dht11_pins {
-+ dht11_pins: dht11_pins@0 {
- brcm,pins = <4>;
- brcm,function = <0>; // in
- brcm,pull = <0>; // off
-@@ -34,6 +34,8 @@
-
- __overrides__ {
- gpiopin = <&dht11_pins>,"brcm,pins:0",
-- <&dht11>,"gpios:4";
-+ <&dht11_pins>, "reg:0",
-+ <&dht11>,"gpios:4",
-+ <&dht11>,"reg:0";
- };
- };
--- /dev/null
+From 27cb8bf0442f677380a1df93b93b7589b7ce5243 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 6 Jan 2020 14:05:42 +0000
+Subject: [PATCH] pinctrl: bcm2835: Change init order for gpio hogs
+
+pinctrl-bcm2835 is a combined pinctrl/gpio driver. Currently the gpio
+side is registered first, but this breaks gpio hogs (which are
+configured during gpiochip_add_data). Part of the hog initialisation
+is a call to pinctrl_gpio_request, and since the pinctrl driver hasn't
+yet been registered this results in an -EPROBE_DEFER from which it can
+never recover.
+
+Change the initialisation sequence to register the pinctrl driver
+first.
+
+See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=260600
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/pinctrl/bcm/pinctrl-bcm2835.c | 40 ++++++++++++---------------
+ 1 file changed, 17 insertions(+), 23 deletions(-)
+
+--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+@@ -1135,9 +1135,25 @@ static int bcm2835_pinctrl_probe(struct
+ raw_spin_lock_init(&pc->irq_lock[i]);
+ }
+
++ match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
++ if (match) {
++ bcm2835_pinctrl_desc.confops =
++ (const struct pinconf_ops *)match->data;
++ }
++
++ pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
++ if (IS_ERR(pc->pctl_dev))
++ return PTR_ERR(pc->pctl_dev);
++
++ pc->gpio_range = bcm2835_pinctrl_gpio_range;
++ pc->gpio_range.base = pc->gpio_chip.base;
++ pc->gpio_range.gc = &pc->gpio_chip;
++ pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
++
+ err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc);
+ if (err) {
+ dev_err(dev, "could not add GPIO chip\n");
++ pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
+ return err;
+ }
+
+@@ -1145,6 +1161,7 @@ static int bcm2835_pinctrl_probe(struct
+ 0, handle_level_irq, IRQ_TYPE_NONE);
+ if (err) {
+ dev_info(dev, "could not add irqchip\n");
++ pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
+ return err;
+ }
+
+@@ -1167,29 +1184,6 @@ static int bcm2835_pinctrl_probe(struct
+ bcm2835_gpio_irq_handler);
+ }
+
+- match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
+- if (match) {
+- bcm2835_pinctrl_desc.confops =
+- (const struct pinconf_ops *)match->data;
+- }
+-
+- match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
+- if (match) {
+- bcm2835_pinctrl_desc.confops =
+- (const struct pinconf_ops *)match->data;
+- }
+-
+- pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
+- if (IS_ERR(pc->pctl_dev)) {
+- gpiochip_remove(&pc->gpio_chip);
+- return PTR_ERR(pc->pctl_dev);
+- }
+-
+- pc->gpio_range = bcm2835_pinctrl_gpio_range;
+- pc->gpio_range.base = pc->gpio_chip.base;
+- pc->gpio_range.gc = &pc->gpio_chip;
+- pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
+-
+ return 0;
+ }
+
--- /dev/null
+From 67dd4d137557909279a21c1b5de87a24c84903f9 Mon Sep 17 00:00:00 2001
+From: Giedrius <giedrius@blokas.io>
+Date: Tue, 7 Jan 2020 11:04:21 +0200
+Subject: [PATCH] Pisound: MIDI communication fixes for scaled down
+ CPU.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+* Increased maximum SPI communication speed to avoid running too slow
+ when the CPU is scaled down and losing MIDI data.
+
+* Keep track of buffer usage in millibytes for higher precision.
+
+Signed-off-by: Giedrius Trainavičius <giedrius@blokas.io>
+---
+ sound/soc/bcm/pisound.c | 31 ++++++++++++++++++-------------
+ 1 file changed, 18 insertions(+), 13 deletions(-)
+
+--- a/sound/soc/bcm/pisound.c
++++ b/sound/soc/bcm/pisound.c
+@@ -1,6 +1,6 @@
+ /*
+ * Pisound Linux kernel module.
+- * Copyright (C) 2016-2019 Vilniaus Blokas UAB, https://blokas.io/pisound
++ * Copyright (C) 2016-2020 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
+@@ -326,7 +326,7 @@ static void spi_transfer(const uint8_t *
+ transfer.tx_buf = txbuf;
+ transfer.rx_buf = rxbuf;
+ transfer.len = len;
+- transfer.speed_hz = 100000;
++ transfer.speed_hz = 150000;
+ transfer.delay_usecs = 10;
+ spi_message_add_tail(&transfer, &msg);
+
+@@ -403,9 +403,9 @@ static struct spi_device *pisnd_spi_find
+ static void pisnd_work_handler(struct work_struct *work)
+ {
+ enum { TRANSFER_SIZE = 4 };
+- enum { PISOUND_OUTPUT_BUFFER_SIZE = 128 };
+- enum { MIDI_BYTES_PER_SECOND = 3125 };
+- int out_buffer_used = 0;
++ enum { PISOUND_OUTPUT_BUFFER_SIZE_MILLIBYTES = 127 * 1000 };
++ enum { MIDI_MILLIBYTES_PER_JIFFIE = (3125 * 1000) / HZ };
++ int out_buffer_used_millibytes = 0;
+ unsigned long now;
+ uint8_t val;
+ uint8_t txbuf[TRANSFER_SIZE];
+@@ -445,7 +445,9 @@ static void pisnd_work_handler(struct wo
+ had_data = false;
+ memset(txbuf, 0, sizeof(txbuf));
+ for (i = 0; i < sizeof(txbuf) &&
+- out_buffer_used < PISOUND_OUTPUT_BUFFER_SIZE;
++ ((out_buffer_used_millibytes+1000 <
++ PISOUND_OUTPUT_BUFFER_SIZE_MILLIBYTES) ||
++ g_ledFlashDurationChanged);
+ i += 2) {
+
+ val = 0;
+@@ -458,7 +460,7 @@ static void pisnd_work_handler(struct wo
+ } else if (kfifo_get(&spi_fifo_out, &val)) {
+ txbuf[i+0] = 0x0f;
+ txbuf[i+1] = val;
+- ++out_buffer_used;
++ out_buffer_used_millibytes += 1000;
+ }
+ }
+
+@@ -469,12 +471,14 @@ static void pisnd_work_handler(struct wo
+ * rate.
+ */
+ now = jiffies;
+- out_buffer_used -=
+- (MIDI_BYTES_PER_SECOND / HZ) /
+- (now - last_transfer_at);
+- if (out_buffer_used < 0)
+- out_buffer_used = 0;
+- last_transfer_at = now;
++ if (now != last_transfer_at) {
++ out_buffer_used_millibytes -=
++ (now - last_transfer_at) *
++ MIDI_MILLIBYTES_PER_JIFFIE;
++ if (out_buffer_used_millibytes < 0)
++ out_buffer_used_millibytes = 0;
++ last_transfer_at = now;
++ }
+
+ for (i = 0; i < sizeof(rxbuf); i += 2) {
+ if (rxbuf[i]) {
+@@ -489,6 +493,7 @@ static void pisnd_work_handler(struct wo
+ || !kfifo_is_empty(&spi_fifo_out)
+ || pisnd_spi_has_more()
+ || g_ledFlashDurationChanged
++ || out_buffer_used_millibytes != 0
+ );
+
+ if (!kfifo_is_empty(&spi_fifo_in) && g_recvCallback)
+++ /dev/null
-From 32dbe4ebb10b96eed117852f1643bf1f854d96c0 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Sun, 22 Dec 2019 15:29:40 +0000
-Subject: [PATCH] overlays: i2c-rtc: Add pcf85363 support
-
-See: https://github.com/raspberrypi/firmware/issues/1309
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- arch/arm/boot/dts/overlays/README | 2 ++
- arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 16 ++++++++++++++++
- 2 files changed, 18 insertions(+)
-
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -1078,6 +1078,8 @@ Params: abx80x Select o
-
- pcf8523 Select the PCF8523 device
-
-+ pcf85363 Select the PCF85363 device
-+
- pcf8563 Select the PCF8563 device
-
- rv3028 Select the Micro Crystal RV3028 device
---- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
-@@ -188,6 +188,21 @@
- };
- };
-
-+ fragment@12 {
-+ target = <&i2c_arm>;
-+ __dormant__ {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "okay";
-+
-+ pcf85363@51 {
-+ compatible = "nxp,pcf85363";
-+ reg = <0x51>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
- __overrides__ {
- abx80x = <0>,"+0";
- ds1307 = <0>,"+1";
-@@ -201,6 +216,7 @@
- m41t62 = <0>,"+9";
- rv3028 = <0>,"+10";
- pcf2129 = <0>,"+11";
-+ pcf85363 = <0>,"+12";
-
- addr = <&abx80x>, "reg:0",
- <&ds1307>, "reg:0",
--- /dev/null
+From 238506ebdea7a0bb928af8403287d5b0d71cdfee Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Fri, 16 Aug 2019 22:32:02 +0200
+Subject: [PATCH] ARM: dts: bcm283x: Remove simple-bus from fixed
+ clocks
+
+commit 4b2d24662126b1e2a6b95c9dfe9e9044e105e5bd upstream.
+
+The fixed clocks doesn't form some kind of bus. So let's remove it.
+This fixes the follow DT schema warnings:
+
+clocks: clock@3:reg:0: [3] is too short
+clocks: clock@4:reg:0: [4] is too short
+clocks: $nodename:0: 'clocks' does not match '^(bus|soc|axi|ahb|apb)(@[0-9a-f]+)?$'
+clocks: #size-cells:0:0: 0 is not one of [1, 2]
+clocks: 'ranges' is a required property
+clock@3: 'reg' does not match any of the regexes: 'pinctrl-[0-9]+'
+clock@4: 'reg' does not match any of the regexes: 'pinctrl-[0-9]+'
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ arch/arm/boot/dts/bcm283x.dtsi | 10 ++--------
+ 1 file changed, 2 insertions(+), 8 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -635,22 +635,16 @@
+ };
+
+ clocks {
+- compatible = "simple-bus";
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+ /* The oscillator is the root of the clock tree. */
+- clk_osc: clock@3 {
++ clk_osc: clk-osc {
+ compatible = "fixed-clock";
+- reg = <3>;
+ #clock-cells = <0>;
+ clock-output-names = "osc";
+ clock-frequency = <19200000>;
+ };
+
+- clk_usb: clock@4 {
++ clk_usb: clk-usb {
+ compatible = "fixed-clock";
+- reg = <4>;
+ #clock-cells = <0>;
+ clock-output-names = "otg";
+ clock-frequency = <480000000>;
+++ /dev/null
-From 0cddfafa817a776063ba6f00fb439d9a415235f9 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 6 Jan 2020 16:04:30 +0000
-Subject: [PATCH] pinctrl: bcm2835: Remove gpiochip on error
-
-A failure in gpiochip_irqchip_add leads to a leak of a gpiochip. Fix
-the leak with the use of devm_gpiochip_add_data.
-
-Fixes: 85ae9e512f43 ("pinctrl: bcm2835: switch to GPIOLIB_IRQCHIP")
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-@@ -1135,7 +1135,7 @@ static int bcm2835_pinctrl_probe(struct
- raw_spin_lock_init(&pc->irq_lock[i]);
- }
-
-- err = gpiochip_add_data(&pc->gpio_chip, pc);
-+ err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc);
- if (err) {
- dev_err(dev, "could not add GPIO chip\n");
- return err;
--- /dev/null
+From fcd4bc412167d2a79bf63603e883f4960ca6b2a1 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Fri, 27 Dec 2019 11:15:00 +0100
+Subject: [PATCH] ARM: dts: bcm283x: Move system timer back to
+ bcm283x.dtsi
+
+During Raspberry Pi 4 upstream discussion Tim Gover confirmed that the
+system timer also exists on BCM2711. So move it back to bcm283x.dtsi and
+overwrite the interrupt definition in bcm2838.dtsi.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+---
+ arch/arm/boot/dts/bcm2835-common.dtsi | 11 -----------
+ arch/arm/boot/dts/bcm2838.dtsi | 7 +++++++
+ arch/arm/boot/dts/bcm283x.dtsi | 11 +++++++++++
+ 3 files changed, 18 insertions(+), 11 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2835-common.dtsi
++++ b/arch/arm/boot/dts/bcm2835-common.dtsi
+@@ -6,17 +6,6 @@
+
+ / {
+ 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>;
+--- a/arch/arm/boot/dts/bcm2838.dtsi
++++ b/arch/arm/boot/dts/bcm2838.dtsi
+@@ -711,6 +711,13 @@
+ interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
++&system_timer {
++ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
++};
++
+ &uart0 {
+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ };
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -56,6 +56,17 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+
++ system_timer: 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: txp@7e004000 {
+ compatible = "brcm,bcm2835-txp";
+ reg = <0x7e004000 0x20>;
+++ /dev/null
-From 27cb8bf0442f677380a1df93b93b7589b7ce5243 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Mon, 6 Jan 2020 14:05:42 +0000
-Subject: [PATCH] pinctrl: bcm2835: Change init order for gpio hogs
-
-pinctrl-bcm2835 is a combined pinctrl/gpio driver. Currently the gpio
-side is registered first, but this breaks gpio hogs (which are
-configured during gpiochip_add_data). Part of the hog initialisation
-is a call to pinctrl_gpio_request, and since the pinctrl driver hasn't
-yet been registered this results in an -EPROBE_DEFER from which it can
-never recover.
-
-Change the initialisation sequence to register the pinctrl driver
-first.
-
-See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=260600
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 40 ++++++++++++---------------
- 1 file changed, 17 insertions(+), 23 deletions(-)
-
---- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
-@@ -1135,9 +1135,25 @@ static int bcm2835_pinctrl_probe(struct
- raw_spin_lock_init(&pc->irq_lock[i]);
- }
-
-+ match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
-+ if (match) {
-+ bcm2835_pinctrl_desc.confops =
-+ (const struct pinconf_ops *)match->data;
-+ }
-+
-+ pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
-+ if (IS_ERR(pc->pctl_dev))
-+ return PTR_ERR(pc->pctl_dev);
-+
-+ pc->gpio_range = bcm2835_pinctrl_gpio_range;
-+ pc->gpio_range.base = pc->gpio_chip.base;
-+ pc->gpio_range.gc = &pc->gpio_chip;
-+ pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
-+
- err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc);
- if (err) {
- dev_err(dev, "could not add GPIO chip\n");
-+ pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
- return err;
- }
-
-@@ -1145,6 +1161,7 @@ static int bcm2835_pinctrl_probe(struct
- 0, handle_level_irq, IRQ_TYPE_NONE);
- if (err) {
- dev_info(dev, "could not add irqchip\n");
-+ pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
- return err;
- }
-
-@@ -1167,29 +1184,6 @@ static int bcm2835_pinctrl_probe(struct
- bcm2835_gpio_irq_handler);
- }
-
-- match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
-- if (match) {
-- bcm2835_pinctrl_desc.confops =
-- (const struct pinconf_ops *)match->data;
-- }
--
-- match = of_match_node(bcm2835_pinctrl_m