From: Álvaro Fernández Rojas Date: Sat, 4 Mar 2017 18:37:50 +0000 (+0100) Subject: brcm2708: update linux 4.9 patches to latest version X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=baad22eed3ea3242051bbde6ebf56e74deb11ea6;p=openwrt%2Fstaging%2Fluka.git brcm2708: update linux 4.9 patches to latest version As usual these patches were extracted and rebased from the raspberry pi repo: https://github.com/raspberrypi/linux/tree/rpi-4.9.y - Remove led1 from diag.sh for RPi3 since it causes boot issues. - Fix modules.mk typos. Signed-off-by: Álvaro Fernández Rojas --- diff --git a/target/linux/brcm2708/base-files/etc/diag.sh b/target/linux/brcm2708/base-files/etc/diag.sh index 2a866e4339..ecc6242d73 100644 --- a/target/linux/brcm2708/base-files/etc/diag.sh +++ b/target/linux/brcm2708/base-files/etc/diag.sh @@ -12,8 +12,7 @@ set_state() { status_led="led0" ;; rpi-b-plus |\ - rpi-2-b |\ - rpi-3-b) + rpi-2-b) status_led="led1" ;; esac diff --git a/target/linux/brcm2708/bcm2708/config-4.9 b/target/linux/brcm2708/bcm2708/config-4.9 index 1619ba941d..c1bed074c3 100644 --- a/target/linux/brcm2708/bcm2708/config-4.9 +++ b/target/linux/brcm2708/bcm2708/config-4.9 @@ -164,6 +164,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GPIOLIB=y +# CONFIG_GPIO_BCM_EXP is not set # CONFIG_GPIO_BCM_VIRT is not set CONFIG_GPIO_SYSFS=y CONFIG_HANDLE_DOMAIN_IRQ=y diff --git a/target/linux/brcm2708/bcm2709/config-4.9 b/target/linux/brcm2708/bcm2709/config-4.9 index dffc368eb2..0c9adec710 100644 --- a/target/linux/brcm2708/bcm2709/config-4.9 +++ b/target/linux/brcm2708/bcm2709/config-4.9 @@ -179,6 +179,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GPIOLIB=y +CONFIG_GPIO_BCM_EXP=y CONFIG_GPIO_BCM_VIRT=y CONFIG_GPIO_SYSFS=y CONFIG_HANDLE_DOMAIN_IRQ=y diff --git a/target/linux/brcm2708/bcm2710/config-4.9 b/target/linux/brcm2708/bcm2710/config-4.9 index 04d0da8f7a..e07d8cf4e6 100644 --- a/target/linux/brcm2708/bcm2710/config-4.9 +++ b/target/linux/brcm2708/bcm2710/config-4.9 @@ -191,6 +191,7 @@ CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GPIOLIB=y +CONFIG_GPIO_BCM_EXP=y CONFIG_GPIO_BCM_VIRT=y CONFIG_GPIO_SYSFS=y CONFIG_HANDLE_DOMAIN_IRQ=y diff --git a/target/linux/brcm2708/modules.mk b/target/linux/brcm2708/modules.mk index e2b3fdb59e..a49f9d48b6 100644 --- a/target/linux/brcm2708/modules.mk +++ b/target/linux/brcm2708/modules.mk @@ -126,8 +126,8 @@ define KernelPackage/sound-soc-digidac1-soundcard $(LINUX_DIR)/sound/soc/codecs/snd-soc-wm8741.ko \ $(LINUX_DIR)/sound/soc/codecs/snd-soc-wm8804.ko \ $(LINUX_DIR)/sound/soc/codecs/snd-soc-wm8804-i2c.ko - AUTOLOAD:=$(call AutoLoad,68,snd-soc-snd-soc-wm8741 \ - snd-soc-snd-soc-wm8804 snd-soc-snd-soc-wm8804-i2c \ + AUTOLOAD:=$(call AutoLoad,68,snd-soc-wm8741 \ + snd-soc-wm8804 snd-soc-wm8804-i2c \ snd-soc-digidac1-soundcard) DEPENDS:= \ kmod-sound-soc-bcm2835-i2s \ @@ -149,7 +149,7 @@ define KernelPackage/sound-soc-dionaudio-loco FILES:= \ $(LINUX_DIR)/sound/soc/bcm/snd-soc-dionaudio-loco.ko \ $(LINUX_DIR)/sound/soc/codecs/snd-soc-pcm5102a.ko - AUTOLOAD:=$(call AutoLoad,68,snd-soc-snd-soc-pcm5102a \ + AUTOLOAD:=$(call AutoLoad,68,snd-soc-pcm5102a \ snd-soc-dionaudio-loco) DEPENDS:= \ kmod-sound-soc-bcm2835-i2s @@ -162,6 +162,50 @@ endef $(eval $(call KernelPackage,sound-soc-dionaudio-loco)) +define KernelPackage/sound-soc-dionaudio-loco-v2 + TITLE:=Support for Dion Audio LOCO-V2 DAC-AMP + KCONFIG:= \ + CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2 \ + CONFIG_SND_SOC_PCM512x \ + CONFIG_SND_SOC_PCM512x_I2C + FILES:= \ + $(LINUX_DIR)/sound/soc/bcm/snd-soc-dionaudio-loco.ko \ + $(LINUX_DIR)/sound/soc/codecs/snd-soc-pcm512x.ko \ + $(LINUX_DIR)/sound/soc/codecs/snd-soc-pcm512x-i2c.ko + AUTOLOAD:=$(call AutoLoad,68,snd-soc-pcm512x snd-soc-pcm512x-i2c \ + snd-soc-dionaudio-loco) + DEPENDS:= \ + kmod-sound-soc-bcm2835-i2s + $(call AddDepends/sound) +endef + +define KernelPackage/sound-soc-dionaudio-loco-v2/description + This package contains support for Dion Audio LOCO-V2 DAC-AMP +endef + +$(eval $(call KernelPackage,sound-soc-dionaudio-loco-v2)) + +define KernelPackage/sound-soc-fe-pi + TITLE:=Support for Fe-Pi Audio Sound Card + KCONFIG:= \ + CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO \ + CONFIG_SND_SOC_SGTL5000 + FILES:= \ + $(LINUX_DIR)/sound/soc/bcm/snd-soc-fe-pi-audio.ko \ + $(LINUX_DIR)/sound/soc/codecs/snd-soc-sgtl5000.ko + AUTOLOAD:=$(call AutoLoad,68,snd-soc-sgtl5000 \ + snd-soc-fe-pi-audio) + DEPENDS:= \ + kmod-sound-soc-bcm2835-i2s + $(call AddDepends/sound) +endef + +define KernelPackage/sound-soc-fe-pi/description + This package contains support for Fe-Pi Audio Sound Card +endef + +$(eval $(call KernelPackage,sound-soc-fe-pi)) + define KernelPackage/sound-soc-hifiberry-dac TITLE:=Support for HifiBerry DAC KCONFIG:= \ diff --git a/target/linux/brcm2708/patches-4.9/0001-smsx95xx-fix-crimes-against-truesize.patch b/target/linux/brcm2708/patches-4.9/0001-smsx95xx-fix-crimes-against-truesize.patch index b8b424beee..a5737e3c83 100644 --- a/target/linux/brcm2708/patches-4.9/0001-smsx95xx-fix-crimes-against-truesize.patch +++ b/target/linux/brcm2708/patches-4.9/0001-smsx95xx-fix-crimes-against-truesize.patch @@ -1,4 +1,4 @@ -From 3df8aa3aa981f3c463d793b69fa23c5aab53fec2 Mon Sep 17 00:00:00 2001 +From c01a3230d8cdd396dcec2619646f6cf2753481d8 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 19 Feb 2015 18:47:12 +0000 Subject: [PATCH] smsx95xx: fix crimes against truesize diff --git a/target/linux/brcm2708/patches-4.9/0002-smsc95xx-Experimental-Enable-turbo_mode-and-packetsi.patch b/target/linux/brcm2708/patches-4.9/0002-smsc95xx-Experimental-Enable-turbo_mode-and-packetsi.patch index 9d47276af6..fc7ac4d8b9 100644 --- a/target/linux/brcm2708/patches-4.9/0002-smsc95xx-Experimental-Enable-turbo_mode-and-packetsi.patch +++ b/target/linux/brcm2708/patches-4.9/0002-smsc95xx-Experimental-Enable-turbo_mode-and-packetsi.patch @@ -1,4 +1,4 @@ -From aefca8fa1aefb12cc7ac1862b4c6e94c1ec9e74c Mon Sep 17 00:00:00 2001 +From 8272cd893c3bca2f047dcf06ae11d9ada6d26f33 Mon Sep 17 00:00:00 2001 From: Sam Nazarko Date: Fri, 1 Apr 2016 17:27:21 +0100 Subject: [PATCH] smsc95xx: Experimental: Enable turbo_mode and packetsize=2560 diff --git a/target/linux/brcm2708/patches-4.9/0003-Allow-mac-address-to-be-set-in-smsc95xx.patch b/target/linux/brcm2708/patches-4.9/0003-Allow-mac-address-to-be-set-in-smsc95xx.patch index dbcf303232..8075dff2f3 100644 --- a/target/linux/brcm2708/patches-4.9/0003-Allow-mac-address-to-be-set-in-smsc95xx.patch +++ b/target/linux/brcm2708/patches-4.9/0003-Allow-mac-address-to-be-set-in-smsc95xx.patch @@ -1,4 +1,4 @@ -From a4774fe88b0a06562a7b6c5d3181f13e7444a3f0 Mon Sep 17 00:00:00 2001 +From 2e70eba32ed21b1a909b9ae6a06b3384a33fc5a4 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 17:26:38 +0000 Subject: [PATCH] Allow mac address to be set in smsc95xx diff --git a/target/linux/brcm2708/patches-4.9/0004-Protect-__release_resource-against-resources-without.patch b/target/linux/brcm2708/patches-4.9/0004-Protect-__release_resource-against-resources-without.patch index f46579b943..4b80ab0bec 100644 --- a/target/linux/brcm2708/patches-4.9/0004-Protect-__release_resource-against-resources-without.patch +++ b/target/linux/brcm2708/patches-4.9/0004-Protect-__release_resource-against-resources-without.patch @@ -1,4 +1,4 @@ -From 0b4480a51b80954e34605c9bf42947d97e37d1c3 Mon Sep 17 00:00:00 2001 +From 3115fe312a2c751954f1ab0f0ba07aea1c1c7d1b Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 13 Mar 2015 12:43:36 +0000 Subject: [PATCH] Protect __release_resource against resources without parents diff --git a/target/linux/brcm2708/patches-4.9/0005-mm-Remove-the-PFN-busy-warning.patch b/target/linux/brcm2708/patches-4.9/0005-mm-Remove-the-PFN-busy-warning.patch index 376d6a8eed..b271d2606d 100644 --- a/target/linux/brcm2708/patches-4.9/0005-mm-Remove-the-PFN-busy-warning.patch +++ b/target/linux/brcm2708/patches-4.9/0005-mm-Remove-the-PFN-busy-warning.patch @@ -1,4 +1,4 @@ -From 029f649c29d81583b412cb6ff5792a3cf9102a95 Mon Sep 17 00:00:00 2001 +From 55d0c167f73b9583357fc0af36d7a01666885e0e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 18 Dec 2014 16:07:15 -0800 Subject: [PATCH] mm: Remove the PFN busy warning diff --git a/target/linux/brcm2708/patches-4.9/0006-irq-bcm2836-Prevent-spurious-interrupts-and-trap-the.patch b/target/linux/brcm2708/patches-4.9/0006-irq-bcm2836-Prevent-spurious-interrupts-and-trap-the.patch index 3ebcb0a45f..5f5bd83600 100644 --- a/target/linux/brcm2708/patches-4.9/0006-irq-bcm2836-Prevent-spurious-interrupts-and-trap-the.patch +++ b/target/linux/brcm2708/patches-4.9/0006-irq-bcm2836-Prevent-spurious-interrupts-and-trap-the.patch @@ -1,4 +1,4 @@ -From 3fad09910dafeb93a351aefa90ca4fd490f68c84 Mon Sep 17 00:00:00 2001 +From 0badcb291f4fb5c3477c37b4ad4a0e27dd863272 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 4 Dec 2015 17:41:50 +0000 Subject: [PATCH] irq-bcm2836: Prevent spurious interrupts, and trap them early diff --git a/target/linux/brcm2708/patches-4.9/0007-irqchip-bcm2835-Add-FIQ-support.patch b/target/linux/brcm2708/patches-4.9/0007-irqchip-bcm2835-Add-FIQ-support.patch index a25275f073..56be640fd2 100644 --- a/target/linux/brcm2708/patches-4.9/0007-irqchip-bcm2835-Add-FIQ-support.patch +++ b/target/linux/brcm2708/patches-4.9/0007-irqchip-bcm2835-Add-FIQ-support.patch @@ -1,4 +1,4 @@ -From 0c9c73fafac86e96a1d1fb59b13aac0ce6d70692 Mon Sep 17 00:00:00 2001 +From 697bdb968798a2bb37c767582ba54fc6486c5de8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 12 Jun 2015 19:01:05 +0200 Subject: [PATCH] irqchip: bcm2835: Add FIQ support diff --git a/target/linux/brcm2708/patches-4.9/0008-irqchip-irq-bcm2835-Add-2836-FIQ-support.patch b/target/linux/brcm2708/patches-4.9/0008-irqchip-irq-bcm2835-Add-2836-FIQ-support.patch index 710e73ab00..9c7515f4eb 100644 --- a/target/linux/brcm2708/patches-4.9/0008-irqchip-irq-bcm2835-Add-2836-FIQ-support.patch +++ b/target/linux/brcm2708/patches-4.9/0008-irqchip-irq-bcm2835-Add-2836-FIQ-support.patch @@ -1,4 +1,4 @@ -From 3b662c4466e336bab7ebb438b65bd5487d30305d Mon Sep 17 00:00:00 2001 +From 78b53021ae0715792fb6a89bd9e7c02fc254be5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 23 Oct 2015 16:26:55 +0200 Subject: [PATCH] irqchip: irq-bcm2835: Add 2836 FIQ support diff --git a/target/linux/brcm2708/patches-4.9/0010-serial-8250-Don-t-crash-when-nr_uarts-is-0.patch b/target/linux/brcm2708/patches-4.9/0010-serial-8250-Don-t-crash-when-nr_uarts-is-0.patch index be8e9031cd..447f1ce085 100644 --- a/target/linux/brcm2708/patches-4.9/0010-serial-8250-Don-t-crash-when-nr_uarts-is-0.patch +++ b/target/linux/brcm2708/patches-4.9/0010-serial-8250-Don-t-crash-when-nr_uarts-is-0.patch @@ -1,4 +1,4 @@ -From 0059a02a50c6d01a399024cad56ec5254c645fd0 Mon Sep 17 00:00:00 2001 +From cc016c1876877aa42a84cc9c0c89af1b7410ff67 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 30 Jun 2015 14:12:42 +0100 Subject: [PATCH] serial: 8250: Don't crash when nr_uarts is 0 diff --git a/target/linux/brcm2708/patches-4.9/0011-pinctrl-bcm2835-Set-base-to-0-give-expected-gpio-num.patch b/target/linux/brcm2708/patches-4.9/0011-pinctrl-bcm2835-Set-base-to-0-give-expected-gpio-num.patch index 978d675dbf..319eafbb19 100644 --- a/target/linux/brcm2708/patches-4.9/0011-pinctrl-bcm2835-Set-base-to-0-give-expected-gpio-num.patch +++ b/target/linux/brcm2708/patches-4.9/0011-pinctrl-bcm2835-Set-base-to-0-give-expected-gpio-num.patch @@ -1,4 +1,4 @@ -From c9d0e1314de3cde0674ef5a2c8688b1dc10b2091 Mon Sep 17 00:00:00 2001 +From ea9188a48450ddab740fe5ffe6733fb2362ea5c8 Mon Sep 17 00:00:00 2001 From: notro Date: Thu, 10 Jul 2014 13:59:47 +0200 Subject: [PATCH] pinctrl-bcm2835: Set base to 0 give expected gpio numbering diff --git a/target/linux/brcm2708/patches-4.9/0012-pinctrl-bcm2835-Fix-interrupt-handling-for-GPIOs-28-.patch b/target/linux/brcm2708/patches-4.9/0012-pinctrl-bcm2835-Fix-interrupt-handling-for-GPIOs-28-.patch index 67cc420511..b29aa8d7fb 100644 --- a/target/linux/brcm2708/patches-4.9/0012-pinctrl-bcm2835-Fix-interrupt-handling-for-GPIOs-28-.patch +++ b/target/linux/brcm2708/patches-4.9/0012-pinctrl-bcm2835-Fix-interrupt-handling-for-GPIOs-28-.patch @@ -1,4 +1,4 @@ -From c7ab4eb8e79ceaa923a7c9f4e14dc085a1934a29 Mon Sep 17 00:00:00 2001 +From 6f92d02f7af5a9b5ed5ded7dbeb18bf2bbb2ad85 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 24 Feb 2015 13:40:50 +0000 Subject: [PATCH] pinctrl-bcm2835: Fix interrupt handling for GPIOs 28-31 and diff --git a/target/linux/brcm2708/patches-4.9/0013-pinctrl-bcm2835-Only-request-the-interrupts-listed-i.patch b/target/linux/brcm2708/patches-4.9/0013-pinctrl-bcm2835-Only-request-the-interrupts-listed-i.patch index e16f89a98e..d2b764f98a 100644 --- a/target/linux/brcm2708/patches-4.9/0013-pinctrl-bcm2835-Only-request-the-interrupts-listed-i.patch +++ b/target/linux/brcm2708/patches-4.9/0013-pinctrl-bcm2835-Only-request-the-interrupts-listed-i.patch @@ -1,4 +1,4 @@ -From a5a46d240c25576b901f0afa76575c1ab4a1469a Mon Sep 17 00:00:00 2001 +From 6b37913f47f5fbd2748ea9abfb9a17fcfb1b5d29 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 26 Feb 2015 09:58:22 +0000 Subject: [PATCH] pinctrl-bcm2835: Only request the interrupts listed in the diff --git a/target/linux/brcm2708/patches-4.9/0014-pinctrl-bcm2835-Return-pins-to-inputs-when-freed.patch b/target/linux/brcm2708/patches-4.9/0014-pinctrl-bcm2835-Return-pins-to-inputs-when-freed.patch index bac0573ba2..4eb4923021 100644 --- a/target/linux/brcm2708/patches-4.9/0014-pinctrl-bcm2835-Return-pins-to-inputs-when-freed.patch +++ b/target/linux/brcm2708/patches-4.9/0014-pinctrl-bcm2835-Return-pins-to-inputs-when-freed.patch @@ -1,4 +1,4 @@ -From 403ea1795165839348e5953b80ec4da31b639f8e Mon Sep 17 00:00:00 2001 +From e64023aab5addf920379e9f919d7c5cd4c8d0981 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 May 2016 12:32:47 +0100 Subject: [PATCH] pinctrl-bcm2835: Return pins to inputs when freed diff --git a/target/linux/brcm2708/patches-4.9/0015-spi-bcm2835-Support-pin-groups-other-than-7-11.patch b/target/linux/brcm2708/patches-4.9/0015-spi-bcm2835-Support-pin-groups-other-than-7-11.patch index 9b8e869ddc..62145a2f07 100644 --- a/target/linux/brcm2708/patches-4.9/0015-spi-bcm2835-Support-pin-groups-other-than-7-11.patch +++ b/target/linux/brcm2708/patches-4.9/0015-spi-bcm2835-Support-pin-groups-other-than-7-11.patch @@ -1,4 +1,4 @@ -From d4a8fe93bffd4cab698a2630ee7125da93d55d8a Mon Sep 17 00:00:00 2001 +From 6603973d0897c1a9b3b1a813c8ab1204efe98fe0 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 24 Jun 2015 14:10:44 +0100 Subject: [PATCH] spi-bcm2835: Support pin groups other than 7-11 diff --git a/target/linux/brcm2708/patches-4.9/0016-spi-bcm2835-Disable-forced-software-CS.patch b/target/linux/brcm2708/patches-4.9/0016-spi-bcm2835-Disable-forced-software-CS.patch index 3ec353702c..5d4062c4e4 100644 --- a/target/linux/brcm2708/patches-4.9/0016-spi-bcm2835-Disable-forced-software-CS.patch +++ b/target/linux/brcm2708/patches-4.9/0016-spi-bcm2835-Disable-forced-software-CS.patch @@ -1,4 +1,4 @@ -From fa79e1013557f418119bd9dd2c0cf4c51eb4c093 Mon Sep 17 00:00:00 2001 +From c0aaf0d4213bfc9df85c397cd974f7a6f15255f2 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 1 Jul 2016 22:09:24 +0100 Subject: [PATCH] spi-bcm2835: Disable forced software CS diff --git a/target/linux/brcm2708/patches-4.9/0017-spi-bcm2835-Remove-unused-code.patch b/target/linux/brcm2708/patches-4.9/0017-spi-bcm2835-Remove-unused-code.patch index 4143498a9d..08577fce2a 100644 --- a/target/linux/brcm2708/patches-4.9/0017-spi-bcm2835-Remove-unused-code.patch +++ b/target/linux/brcm2708/patches-4.9/0017-spi-bcm2835-Remove-unused-code.patch @@ -1,4 +1,4 @@ -From 85bb42acd1c5a045d372d187c26b77c6bf1b617a Mon Sep 17 00:00:00 2001 +From 21f7f9d8146dd9e5a860198781febf78aafee3d1 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 8 Nov 2016 21:35:38 +0000 Subject: [PATCH] spi-bcm2835: Remove unused code diff --git a/target/linux/brcm2708/patches-4.9/0018-ARM-bcm2835-Set-Serial-number-and-Revision.patch b/target/linux/brcm2708/patches-4.9/0018-ARM-bcm2835-Set-Serial-number-and-Revision.patch index 1311ccb93b..cd14dcc181 100644 --- a/target/linux/brcm2708/patches-4.9/0018-ARM-bcm2835-Set-Serial-number-and-Revision.patch +++ b/target/linux/brcm2708/patches-4.9/0018-ARM-bcm2835-Set-Serial-number-and-Revision.patch @@ -1,4 +1,4 @@ -From c33ee72bce07fc83e4797ebea1bce97c0b301ba2 Mon Sep 17 00:00:00 2001 +From 78678f8e9f7fbbafadfecd54a5fb166a94d8d84f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Wed, 3 Jun 2015 12:26:13 +0200 Subject: [PATCH] ARM: bcm2835: Set Serial number and Revision diff --git a/target/linux/brcm2708/patches-4.9/0019-dmaengine-bcm2835-Load-driver-early-and-support-lega.patch b/target/linux/brcm2708/patches-4.9/0019-dmaengine-bcm2835-Load-driver-early-and-support-lega.patch index e3bde68d9a..e800713ab8 100644 --- a/target/linux/brcm2708/patches-4.9/0019-dmaengine-bcm2835-Load-driver-early-and-support-lega.patch +++ b/target/linux/brcm2708/patches-4.9/0019-dmaengine-bcm2835-Load-driver-early-and-support-lega.patch @@ -1,4 +1,4 @@ -From b4e0c1c3facd38ef5e615248c42dba90d2622257 Mon Sep 17 00:00:00 2001 +From e4f0f7daebca7005c67bf7ae3f6f59df587e91d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Sat, 3 Oct 2015 22:22:55 +0200 Subject: [PATCH] dmaengine: bcm2835: Load driver early and support legacy API diff --git a/target/linux/brcm2708/patches-4.9/0020-firmware-Updated-mailbox-header.patch b/target/linux/brcm2708/patches-4.9/0020-firmware-Updated-mailbox-header.patch index deb271c892..37eb154393 100644 --- a/target/linux/brcm2708/patches-4.9/0020-firmware-Updated-mailbox-header.patch +++ b/target/linux/brcm2708/patches-4.9/0020-firmware-Updated-mailbox-header.patch @@ -1,4 +1,4 @@ -From 05f9e93200ec5d5e27c8a93f69588180cddda924 Mon Sep 17 00:00:00 2001 +From e4edca57f8db4d03ad4dc82dd6761c0142ab310d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 25 Jan 2016 17:25:12 +0000 Subject: [PATCH] firmware: Updated mailbox header diff --git a/target/linux/brcm2708/patches-4.9/0021-clk-bcm2835-Mark-GPIO-clocks-enabled-at-boot-as-crit.patch b/target/linux/brcm2708/patches-4.9/0021-clk-bcm2835-Mark-GPIO-clocks-enabled-at-boot-as-crit.patch index 94862f5bed..dfa312bc37 100644 --- a/target/linux/brcm2708/patches-4.9/0021-clk-bcm2835-Mark-GPIO-clocks-enabled-at-boot-as-crit.patch +++ b/target/linux/brcm2708/patches-4.9/0021-clk-bcm2835-Mark-GPIO-clocks-enabled-at-boot-as-crit.patch @@ -1,4 +1,4 @@ -From c9cb54929b3466ed0da304563e22739477055d3b Mon Sep 17 00:00:00 2001 +From 599e7165ec6477139dae4f32a12e8d49d5dd8859 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 9 May 2016 17:28:18 -0700 Subject: [PATCH] clk: bcm2835: Mark GPIO clocks enabled at boot as critical. diff --git a/target/linux/brcm2708/patches-4.9/0022-rtc-Add-SPI-alias-for-pcf2123-driver.patch b/target/linux/brcm2708/patches-4.9/0022-rtc-Add-SPI-alias-for-pcf2123-driver.patch index 8c197fce85..4992165a21 100644 --- a/target/linux/brcm2708/patches-4.9/0022-rtc-Add-SPI-alias-for-pcf2123-driver.patch +++ b/target/linux/brcm2708/patches-4.9/0022-rtc-Add-SPI-alias-for-pcf2123-driver.patch @@ -1,4 +1,4 @@ -From 6c8399fb8dcc815aa9d6b4488a519785912ea983 Mon Sep 17 00:00:00 2001 +From ffa1e97926ba3e22f7e41e2b5e16737461bf31ae Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 15 Jun 2016 16:48:41 +0100 Subject: [PATCH] rtc: Add SPI alias for pcf2123 driver diff --git a/target/linux/brcm2708/patches-4.9/0023-watchdog-bcm2835-Support-setting-reboot-partition.patch b/target/linux/brcm2708/patches-4.9/0023-watchdog-bcm2835-Support-setting-reboot-partition.patch index 160c5767f0..392ce70232 100644 --- a/target/linux/brcm2708/patches-4.9/0023-watchdog-bcm2835-Support-setting-reboot-partition.patch +++ b/target/linux/brcm2708/patches-4.9/0023-watchdog-bcm2835-Support-setting-reboot-partition.patch @@ -1,4 +1,4 @@ -From 259f169ef05f12bc7fed007befc11ed6c66dd9c8 Mon Sep 17 00:00:00 2001 +From 0e690096e05c3b4e806381ff38124dbdae3ba877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 7 Oct 2016 16:50:59 +0200 Subject: [PATCH] watchdog: bcm2835: Support setting reboot partition diff --git a/target/linux/brcm2708/patches-4.9/0024-reboot-Use-power-off-rather-than-busy-spinning-when-.patch b/target/linux/brcm2708/patches-4.9/0024-reboot-Use-power-off-rather-than-busy-spinning-when-.patch index dee1fed06b..d29517e23f 100644 --- a/target/linux/brcm2708/patches-4.9/0024-reboot-Use-power-off-rather-than-busy-spinning-when-.patch +++ b/target/linux/brcm2708/patches-4.9/0024-reboot-Use-power-off-rather-than-busy-spinning-when-.patch @@ -1,4 +1,4 @@ -From 79d93260c98e0164ca89c9f7c767528d7a3aaeae Mon Sep 17 00:00:00 2001 +From 527f4308ee55e8727c486528879b7945b6404a72 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 5 Apr 2016 19:40:12 +0100 Subject: [PATCH] reboot: Use power off rather than busy spinning when halt is diff --git a/target/linux/brcm2708/patches-4.9/0025-bcm-Make-RASPBERRYPI_POWER-depend-on-PM.patch b/target/linux/brcm2708/patches-4.9/0025-bcm-Make-RASPBERRYPI_POWER-depend-on-PM.patch index 120f25dff5..90c0a0eca8 100644 --- a/target/linux/brcm2708/patches-4.9/0025-bcm-Make-RASPBERRYPI_POWER-depend-on-PM.patch +++ b/target/linux/brcm2708/patches-4.9/0025-bcm-Make-RASPBERRYPI_POWER-depend-on-PM.patch @@ -1,4 +1,4 @@ -From 9799ea4ba8ae1e6c586a3dd728ad75f68830e93f Mon Sep 17 00:00:00 2001 +From d63e8989dc891121464a86cec95952f104edf383 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 9 Nov 2016 13:02:52 +0000 Subject: [PATCH] bcm: Make RASPBERRYPI_POWER depend on PM diff --git a/target/linux/brcm2708/patches-4.9/0026-Register-the-clocks-early-during-the-boot-process.patch b/target/linux/brcm2708/patches-4.9/0026-Register-the-clocks-early-during-the-boot-process.patch index d4f4fec92a..9b2a613236 100644 --- a/target/linux/brcm2708/patches-4.9/0026-Register-the-clocks-early-during-the-boot-process.patch +++ b/target/linux/brcm2708/patches-4.9/0026-Register-the-clocks-early-during-the-boot-process.patch @@ -1,4 +1,4 @@ -From 261269cc41f6b77f7264f0e44f9b9da5cc36de00 Mon Sep 17 00:00:00 2001 +From 492d6b9c3f1f8cc1eb890dc0eafacae51d6ba2f0 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Fri, 2 Sep 2016 16:45:27 +0100 Subject: [PATCH] Register the clocks early during the boot process, so that diff --git a/target/linux/brcm2708/patches-4.9/0027-bcm2835-rng-Avoid-initialising-if-already-enabled.patch b/target/linux/brcm2708/patches-4.9/0027-bcm2835-rng-Avoid-initialising-if-already-enabled.patch index 1fb21843ba..97309da0e1 100644 --- a/target/linux/brcm2708/patches-4.9/0027-bcm2835-rng-Avoid-initialising-if-already-enabled.patch +++ b/target/linux/brcm2708/patches-4.9/0027-bcm2835-rng-Avoid-initialising-if-already-enabled.patch @@ -1,4 +1,4 @@ -From a195976d635c3672cae684d6338655aa25f6d98c Mon Sep 17 00:00:00 2001 +From ecba31015228961644ad8e17bcf132eea9c7a7f3 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 6 Dec 2016 17:05:39 +0000 Subject: [PATCH] bcm2835-rng: Avoid initialising if already enabled diff --git a/target/linux/brcm2708/patches-4.9/0028-kbuild-Ignore-dtco-targets-when-filtering-symbols.patch b/target/linux/brcm2708/patches-4.9/0028-kbuild-Ignore-dtco-targets-when-filtering-symbols.patch index 16d32ccb29..0f5afac4ea 100644 --- a/target/linux/brcm2708/patches-4.9/0028-kbuild-Ignore-dtco-targets-when-filtering-symbols.patch +++ b/target/linux/brcm2708/patches-4.9/0028-kbuild-Ignore-dtco-targets-when-filtering-symbols.patch @@ -1,4 +1,4 @@ -From 6c52812a34fa4ab0d40b57fef10d23fe2fb0768b Mon Sep 17 00:00:00 2001 +From d438958d741a4edbb641791461ee8f6c34495a89 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 24 Aug 2016 16:28:44 +0100 Subject: [PATCH] kbuild: Ignore dtco targets when filtering symbols diff --git a/target/linux/brcm2708/patches-4.9/0029-BCM2835_DT-Fix-I2S-register-map.patch b/target/linux/brcm2708/patches-4.9/0029-BCM2835_DT-Fix-I2S-register-map.patch index 4eecc143a4..c193ef9167 100644 --- a/target/linux/brcm2708/patches-4.9/0029-BCM2835_DT-Fix-I2S-register-map.patch +++ b/target/linux/brcm2708/patches-4.9/0029-BCM2835_DT-Fix-I2S-register-map.patch @@ -1,4 +1,4 @@ -From 8ee6fd93aa3328d325524b8503714e3b4839d1b9 Mon Sep 17 00:00:00 2001 +From 317560a92ebfdac14df54b6a242dd8f5ecc1fd58 Mon Sep 17 00:00:00 2001 From: Robert Tiemann Date: Mon, 20 Jul 2015 11:01:25 +0200 Subject: [PATCH] BCM2835_DT: Fix I2S register map diff --git a/target/linux/brcm2708/patches-4.9/0030-Main-bcm2708-bcm2709-linux-port.patch b/target/linux/brcm2708/patches-4.9/0030-Main-bcm2708-bcm2709-linux-port.patch index 81d48b7984..20e5419a74 100644 --- a/target/linux/brcm2708/patches-4.9/0030-Main-bcm2708-bcm2709-linux-port.patch +++ b/target/linux/brcm2708/patches-4.9/0030-Main-bcm2708-bcm2709-linux-port.patch @@ -1,4 +1,4 @@ -From 28a1aeb6b49ffdf5cb5ba9e326df962c270c1f34 Mon Sep 17 00:00:00 2001 +From 9874eb6473865b9d975a7c3756099955e7454e21 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 Subject: [PATCH] Main bcm2708/bcm2709 linux port diff --git a/target/linux/brcm2708/patches-4.9/0031-Add-dwc_otg-driver.patch b/target/linux/brcm2708/patches-4.9/0031-Add-dwc_otg-driver.patch index 971581ad0b..0610d038b6 100644 --- a/target/linux/brcm2708/patches-4.9/0031-Add-dwc_otg-driver.patch +++ b/target/linux/brcm2708/patches-4.9/0031-Add-dwc_otg-driver.patch @@ -1,4 +1,4 @@ -From 4c7d2ae77def863967cbc6e73597d92fe0fb24e7 Mon Sep 17 00:00:00 2001 +From 65f57e56fcf9d40383718f0bcd9e6f95a34ca1aa Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:46:17 +0100 Subject: [PATCH] Add dwc_otg driver diff --git a/target/linux/brcm2708/patches-4.9/0032-bcm2708-framebuffer-driver.patch b/target/linux/brcm2708/patches-4.9/0032-bcm2708-framebuffer-driver.patch index a306868728..b7c05c1611 100644 --- a/target/linux/brcm2708/patches-4.9/0032-bcm2708-framebuffer-driver.patch +++ b/target/linux/brcm2708/patches-4.9/0032-bcm2708-framebuffer-driver.patch @@ -1,4 +1,4 @@ -From a5db9164cfc4fdbd25b20962f3da042cdc75a4dc Mon Sep 17 00:00:00 2001 +From cca69d888eb770c496cca83d37accb62a22e84c7 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 17:06:34 +0100 Subject: [PATCH] bcm2708 framebuffer driver diff --git a/target/linux/brcm2708/patches-4.9/0033-dmaengine-Add-support-for-BCM2708.patch b/target/linux/brcm2708/patches-4.9/0033-dmaengine-Add-support-for-BCM2708.patch index d21f18777a..a2f45519b6 100644 --- a/target/linux/brcm2708/patches-4.9/0033-dmaengine-Add-support-for-BCM2708.patch +++ b/target/linux/brcm2708/patches-4.9/0033-dmaengine-Add-support-for-BCM2708.patch @@ -1,4 +1,4 @@ -From 5ab35842ff7cc211dcfbf1113953778923097496 Mon Sep 17 00:00:00 2001 +From 33444cee555204ee605e6ec9050b04e874fb0090 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:22:53 +0100 Subject: [PATCH] dmaengine: Add support for BCM2708 diff --git a/target/linux/brcm2708/patches-4.9/0034-MMC-added-alternative-MMC-driver.patch b/target/linux/brcm2708/patches-4.9/0034-MMC-added-alternative-MMC-driver.patch index 00920a6223..70fb8f3d8c 100644 --- a/target/linux/brcm2708/patches-4.9/0034-MMC-added-alternative-MMC-driver.patch +++ b/target/linux/brcm2708/patches-4.9/0034-MMC-added-alternative-MMC-driver.patch @@ -1,4 +1,4 @@ -From feab5b6b38842fca38720e0b2e9bfdc66d41c991 Mon Sep 17 00:00:00 2001 +From 1620619c5fa6acae1e119d6461b5c9a2a9416e69 Mon Sep 17 00:00:00 2001 From: gellert Date: Fri, 15 Aug 2014 16:35:06 +0100 Subject: [PATCH] MMC: added alternative MMC driver diff --git a/target/linux/brcm2708/patches-4.9/0035-Adding-bcm2835-sdhost-driver-and-an-overlay-to-enabl.patch b/target/linux/brcm2708/patches-4.9/0035-Adding-bcm2835-sdhost-driver-and-an-overlay-to-enabl.patch index c6ceef081a..c4597ec3c1 100644 --- a/target/linux/brcm2708/patches-4.9/0035-Adding-bcm2835-sdhost-driver-and-an-overlay-to-enabl.patch +++ b/target/linux/brcm2708/patches-4.9/0035-Adding-bcm2835-sdhost-driver-and-an-overlay-to-enabl.patch @@ -1,4 +1,4 @@ -From 3d0f0b3db1b62e5d913517ce305913cc71803ef1 Mon Sep 17 00:00:00 2001 +From 5da331581bb2a8d90f6a7a7bdf8c1b30efe3cf64 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 25 Mar 2015 17:49:47 +0000 Subject: [PATCH] Adding bcm2835-sdhost driver, and an overlay to enable it diff --git a/target/linux/brcm2708/patches-4.9/0036-mmc-Add-MMC_QUIRK_ERASE_BROKEN-for-some-cards.patch b/target/linux/brcm2708/patches-4.9/0036-mmc-Add-MMC_QUIRK_ERASE_BROKEN-for-some-cards.patch index 100c8b1685..d84a0fe892 100644 --- a/target/linux/brcm2708/patches-4.9/0036-mmc-Add-MMC_QUIRK_ERASE_BROKEN-for-some-cards.patch +++ b/target/linux/brcm2708/patches-4.9/0036-mmc-Add-MMC_QUIRK_ERASE_BROKEN-for-some-cards.patch @@ -1,4 +1,4 @@ -From f6be5bc28ee258731e13b5e917d69f601d062014 Mon Sep 17 00:00:00 2001 +From 6d11059a087b8101cf34a09a1e3342bb4f1576de Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 11 May 2016 12:50:33 +0100 Subject: [PATCH] mmc: Add MMC_QUIRK_ERASE_BROKEN for some cards diff --git a/target/linux/brcm2708/patches-4.9/0037-cma-Add-vc_cma-driver-to-enable-use-of-CMA.patch b/target/linux/brcm2708/patches-4.9/0037-cma-Add-vc_cma-driver-to-enable-use-of-CMA.patch index 87b62dcf8f..50bad76c51 100644 --- a/target/linux/brcm2708/patches-4.9/0037-cma-Add-vc_cma-driver-to-enable-use-of-CMA.patch +++ b/target/linux/brcm2708/patches-4.9/0037-cma-Add-vc_cma-driver-to-enable-use-of-CMA.patch @@ -1,4 +1,4 @@ -From a079bbcd1d23f00392eb79d7bcad867844f84cd9 Mon Sep 17 00:00:00 2001 +From 4d96064d4c95d73d22563cea403eccd72e7b0da0 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:31:47 +0100 Subject: [PATCH] cma: Add vc_cma driver to enable use of CMA diff --git a/target/linux/brcm2708/patches-4.9/0038-bcm2708-alsa-sound-driver.patch b/target/linux/brcm2708/patches-4.9/0038-bcm2708-alsa-sound-driver.patch index c951b6f52c..58b45dec6e 100644 --- a/target/linux/brcm2708/patches-4.9/0038-bcm2708-alsa-sound-driver.patch +++ b/target/linux/brcm2708/patches-4.9/0038-bcm2708-alsa-sound-driver.patch @@ -1,4 +1,4 @@ -From 340dfdd9f8dfad3f60665cac7f19d774c001b0de Mon Sep 17 00:00:00 2001 +From 41a90e24c272c84fb8c6d23ac451f0c725dcded6 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 26 Mar 2012 22:15:50 +0100 Subject: [PATCH] bcm2708: alsa sound driver diff --git a/target/linux/brcm2708/patches-4.9/0039-vc_mem-Add-vc_mem-driver-for-querying-firmware-memor.patch b/target/linux/brcm2708/patches-4.9/0039-vc_mem-Add-vc_mem-driver-for-querying-firmware-memor.patch index fbfddde33a..6a22bdf970 100644 --- a/target/linux/brcm2708/patches-4.9/0039-vc_mem-Add-vc_mem-driver-for-querying-firmware-memor.patch +++ b/target/linux/brcm2708/patches-4.9/0039-vc_mem-Add-vc_mem-driver-for-querying-firmware-memor.patch @@ -1,4 +1,4 @@ -From 079c7a4a324b1baa4e727c9e3dfacf503345bb18 Mon Sep 17 00:00:00 2001 +From 94c0e75bc85ad2a034c501b6d3640b880b9c3bb7 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 28 Oct 2016 15:36:43 +0100 Subject: [PATCH] vc_mem: Add vc_mem driver for querying firmware memory diff --git a/target/linux/brcm2708/patches-4.9/0040-vcsm-VideoCore-shared-memory-service-for-BCM2835.patch b/target/linux/brcm2708/patches-4.9/0040-vcsm-VideoCore-shared-memory-service-for-BCM2835.patch index d7bce81d59..ff1cfad30a 100644 --- a/target/linux/brcm2708/patches-4.9/0040-vcsm-VideoCore-shared-memory-service-for-BCM2835.patch +++ b/target/linux/brcm2708/patches-4.9/0040-vcsm-VideoCore-shared-memory-service-for-BCM2835.patch @@ -1,4 +1,4 @@ -From 148da7d48af0416c716b0103bcc14d01cc97d09b Mon Sep 17 00:00:00 2001 +From b62c07606f1673e2e0b9e70ce89e48fc240a7ee1 Mon Sep 17 00:00:00 2001 From: Tim Gover Date: Tue, 22 Jul 2014 15:41:04 +0100 Subject: [PATCH] vcsm: VideoCore shared memory service for BCM2835 diff --git a/target/linux/brcm2708/patches-4.9/0041-Add-dev-gpiomem-device-for-rootless-user-GPIO-access.patch b/target/linux/brcm2708/patches-4.9/0041-Add-dev-gpiomem-device-for-rootless-user-GPIO-access.patch index 66949f5e9b..618cb9f8dd 100644 --- a/target/linux/brcm2708/patches-4.9/0041-Add-dev-gpiomem-device-for-rootless-user-GPIO-access.patch +++ b/target/linux/brcm2708/patches-4.9/0041-Add-dev-gpiomem-device-for-rootless-user-GPIO-access.patch @@ -1,4 +1,4 @@ -From f035c5328fecc8970b9a9713cd345d56f5e81f98 Mon Sep 17 00:00:00 2001 +From 0f326aa0cf8a16ab7f29606b2eda7186f1fb9367 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Fri, 21 Aug 2015 23:14:48 +0100 Subject: [PATCH] Add /dev/gpiomem device for rootless user GPIO access diff --git a/target/linux/brcm2708/patches-4.9/0042-Add-SMI-driver.patch b/target/linux/brcm2708/patches-4.9/0042-Add-SMI-driver.patch index 7a05db457b..3d75e705ba 100644 --- a/target/linux/brcm2708/patches-4.9/0042-Add-SMI-driver.patch +++ b/target/linux/brcm2708/patches-4.9/0042-Add-SMI-driver.patch @@ -1,4 +1,4 @@ -From ddedd1f135c5311bb4615dda5b285ce688cc50d4 Mon Sep 17 00:00:00 2001 +From 8b3f935c48ff65dfb8985ce3e6c631530cd1471a Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Sat, 5 Sep 2015 01:14:45 +0100 Subject: [PATCH] Add SMI driver diff --git a/target/linux/brcm2708/patches-4.9/0043-MISC-bcm2835-smi-use-clock-manager-and-fix-reload-is.patch b/target/linux/brcm2708/patches-4.9/0043-MISC-bcm2835-smi-use-clock-manager-and-fix-reload-is.patch index 312a294bc7..69f68c79ed 100644 --- a/target/linux/brcm2708/patches-4.9/0043-MISC-bcm2835-smi-use-clock-manager-and-fix-reload-is.patch +++ b/target/linux/brcm2708/patches-4.9/0043-MISC-bcm2835-smi-use-clock-manager-and-fix-reload-is.patch @@ -1,4 +1,4 @@ -From 6e5058f6cb203dd31935ba03eeff0d98c7531bcf Mon Sep 17 00:00:00 2001 +From 6bc6d433aaed4d4a5d5be44e70d9de865a850048 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Tue, 26 Apr 2016 14:59:21 +0000 Subject: [PATCH] MISC: bcm2835: smi: use clock manager and fix reload issues diff --git a/target/linux/brcm2708/patches-4.9/0044-Add-SMI-NAND-driver.patch b/target/linux/brcm2708/patches-4.9/0044-Add-SMI-NAND-driver.patch index dee3c1d8b0..ec6010a296 100644 --- a/target/linux/brcm2708/patches-4.9/0044-Add-SMI-NAND-driver.patch +++ b/target/linux/brcm2708/patches-4.9/0044-Add-SMI-NAND-driver.patch @@ -1,4 +1,4 @@ -From 83148030b231764e7a5fc14bd2c9ccc6a104a872 Mon Sep 17 00:00:00 2001 +From be64c4dbf6be17ce20ee214478509a3738256d46 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Sat, 5 Sep 2015 01:16:10 +0100 Subject: [PATCH] Add SMI NAND driver diff --git a/target/linux/brcm2708/patches-4.9/0045-lirc-added-support-for-RaspberryPi-GPIO.patch b/target/linux/brcm2708/patches-4.9/0045-lirc-added-support-for-RaspberryPi-GPIO.patch index ea529b89a0..0cbc1c45a4 100644 --- a/target/linux/brcm2708/patches-4.9/0045-lirc-added-support-for-RaspberryPi-GPIO.patch +++ b/target/linux/brcm2708/patches-4.9/0045-lirc-added-support-for-RaspberryPi-GPIO.patch @@ -1,4 +1,4 @@ -From e12517458be7d5ec0eccc2c23db2b78badd54587 Mon Sep 17 00:00:00 2001 +From 277c109833c1d78543bec0723ab42f4c79937df9 Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 Subject: [PATCH] lirc: added support for RaspberryPi GPIO diff --git a/target/linux/brcm2708/patches-4.9/0046-Add-cpufreq-driver.patch b/target/linux/brcm2708/patches-4.9/0046-Add-cpufreq-driver.patch index 8929ee23ab..7c5691c120 100644 --- a/target/linux/brcm2708/patches-4.9/0046-Add-cpufreq-driver.patch +++ b/target/linux/brcm2708/patches-4.9/0046-Add-cpufreq-driver.patch @@ -1,4 +1,4 @@ -From 91eeb6693671b5ae0220f4a276b84e6597266cb9 Mon Sep 17 00:00:00 2001 +From 7d4719c360b755637c2e68f9855be282cd0065b6 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:49:20 +0100 Subject: [PATCH] Add cpufreq driver diff --git a/target/linux/brcm2708/patches-4.9/0047-Added-hwmon-thermal-driver-for-reporting-core-temper.patch b/target/linux/brcm2708/patches-4.9/0047-Added-hwmon-thermal-driver-for-reporting-core-temper.patch index fa826cbaf4..ff6084fe6a 100644 --- a/target/linux/brcm2708/patches-4.9/0047-Added-hwmon-thermal-driver-for-reporting-core-temper.patch +++ b/target/linux/brcm2708/patches-4.9/0047-Added-hwmon-thermal-driver-for-reporting-core-temper.patch @@ -1,4 +1,4 @@ -From c83d1bbc2d9feaf23252482682824babbbd7bbd9 Mon Sep 17 00:00:00 2001 +From 3c847bc6c9d6f4115c82943c869c55244b39a5c4 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 Subject: [PATCH] Added hwmon/thermal driver for reporting core temperature. diff --git a/target/linux/brcm2708/patches-4.9/0048-Add-Chris-Boot-s-i2c-driver.patch b/target/linux/brcm2708/patches-4.9/0048-Add-Chris-Boot-s-i2c-driver.patch index acb199d848..b86fb40b62 100644 --- a/target/linux/brcm2708/patches-4.9/0048-Add-Chris-Boot-s-i2c-driver.patch +++ b/target/linux/brcm2708/patches-4.9/0048-Add-Chris-Boot-s-i2c-driver.patch @@ -1,4 +1,4 @@ -From d34838cfa7c139fa069b7e038d3ea2b56c50a353 Mon Sep 17 00:00:00 2001 +From af4e8a3c7b645480f57ec14ded02fba6976ff2d5 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 15:44:08 +0100 Subject: [PATCH] Add Chris Boot's i2c driver diff --git a/target/linux/brcm2708/patches-4.9/0049-char-broadcom-Add-vcio-module.patch b/target/linux/brcm2708/patches-4.9/0049-char-broadcom-Add-vcio-module.patch index cd62abe4d1..c37c0f6133 100644 --- a/target/linux/brcm2708/patches-4.9/0049-char-broadcom-Add-vcio-module.patch +++ b/target/linux/brcm2708/patches-4.9/0049-char-broadcom-Add-vcio-module.patch @@ -1,4 +1,4 @@ -From e826eaf145a568f477ab9e5554a563233ad7fb49 Mon Sep 17 00:00:00 2001 +From 2e8101a5e6228109d2cd5b965b6077e63e643d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 26 Jun 2015 14:27:06 +0200 Subject: [PATCH] char: broadcom: Add vcio module diff --git a/target/linux/brcm2708/patches-4.9/0050-firmware-bcm2835-Support-ARCH_BCM270x.patch b/target/linux/brcm2708/patches-4.9/0050-firmware-bcm2835-Support-ARCH_BCM270x.patch index 3e47d68ef4..ecaf614c16 100644 --- a/target/linux/brcm2708/patches-4.9/0050-firmware-bcm2835-Support-ARCH_BCM270x.patch +++ b/target/linux/brcm2708/patches-4.9/0050-firmware-bcm2835-Support-ARCH_BCM270x.patch @@ -1,4 +1,4 @@ -From 2838aca7eb2ef14cb94ac43921fc2db291af96a7 Mon Sep 17 00:00:00 2001 +From f281fd683848cd432f7b73c869676be6362ce1b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 26 Jun 2015 14:25:01 +0200 Subject: [PATCH] firmware: bcm2835: Support ARCH_BCM270x diff --git a/target/linux/brcm2708/patches-4.9/0051-bcm2835-add-v4l2-camera-device.patch b/target/linux/brcm2708/patches-4.9/0051-bcm2835-add-v4l2-camera-device.patch index 2e77160a85..e6baeabfd3 100644 --- a/target/linux/brcm2708/patches-4.9/0051-bcm2835-add-v4l2-camera-device.patch +++ b/target/linux/brcm2708/patches-4.9/0051-bcm2835-add-v4l2-camera-device.patch @@ -1,4 +1,4 @@ -From 35fa034f52f341a95e10034b2f36e2af05fee117 Mon Sep 17 00:00:00 2001 +From 88f7fe5348a24191969b07537b38449a83369d32 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 30 Jan 2013 12:45:18 +0000 Subject: [PATCH] bcm2835: add v4l2 camera device diff --git a/target/linux/brcm2708/patches-4.9/0052-scripts-Add-mkknlimg-and-knlinfo-scripts-from-tools-.patch b/target/linux/brcm2708/patches-4.9/0052-scripts-Add-mkknlimg-and-knlinfo-scripts-from-tools-.patch index 6feda0ee07..7ae4edd5c2 100644 --- a/target/linux/brcm2708/patches-4.9/0052-scripts-Add-mkknlimg-and-knlinfo-scripts-from-tools-.patch +++ b/target/linux/brcm2708/patches-4.9/0052-scripts-Add-mkknlimg-and-knlinfo-scripts-from-tools-.patch @@ -1,4 +1,4 @@ -From 59799351c2a2951565e10b2ef69ccff34f94fd30 Mon Sep 17 00:00:00 2001 +From c1275c733d61290f7477eb7bbaea96d04206eff3 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 11 May 2015 09:00:42 +0100 Subject: [PATCH] scripts: Add mkknlimg and knlinfo scripts from tools repo diff --git a/target/linux/brcm2708/patches-4.9/0053-scripts-dtc-Update-to-upstream-version-1.4.1.patch b/target/linux/brcm2708/patches-4.9/0053-scripts-dtc-Update-to-upstream-version-1.4.1.patch index 5fdf0241d3..ed4b27092b 100644 --- a/target/linux/brcm2708/patches-4.9/0053-scripts-dtc-Update-to-upstream-version-1.4.1.patch +++ b/target/linux/brcm2708/patches-4.9/0053-scripts-dtc-Update-to-upstream-version-1.4.1.patch @@ -1,4 +1,4 @@ -From 913a79481bedcfed6727e899ab3f5a9291328f55 Mon Sep 17 00:00:00 2001 +From 61ad4b70c72fd7d1d3930b50e180d9727eeae150 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 10 Aug 2015 09:49:15 +0100 Subject: [PATCH] scripts/dtc: Update to upstream version 1.4.1 diff --git a/target/linux/brcm2708/patches-4.9/0054-BCM2708-Add-core-Device-Tree-support.patch b/target/linux/brcm2708/patches-4.9/0054-BCM2708-Add-core-Device-Tree-support.patch index 6767122451..d9d1fa9a58 100644 --- a/target/linux/brcm2708/patches-4.9/0054-BCM2708-Add-core-Device-Tree-support.patch +++ b/target/linux/brcm2708/patches-4.9/0054-BCM2708-Add-core-Device-Tree-support.patch @@ -1,4 +1,4 @@ -From 2ad7caa56296821bfab4ce0e808a0d1d2c8ac9f4 Mon Sep 17 00:00:00 2001 +From 589cd87acedc0e24214934816b6c16b4e76a894d Mon Sep 17 00:00:00 2001 From: notro Date: Wed, 9 Jul 2014 14:46:08 +0200 Subject: [PATCH] BCM2708: Add core Device Tree support diff --git a/target/linux/brcm2708/patches-4.9/0055-BCM270x_DT-Add-pwr_led-and-the-required-input-trigge.patch b/target/linux/brcm2708/patches-4.9/0055-BCM270x_DT-Add-pwr_led-and-the-required-input-trigge.patch index 50a0ed7a1e..725ac70e44 100644 --- a/target/linux/brcm2708/patches-4.9/0055-BCM270x_DT-Add-pwr_led-and-the-required-input-trigge.patch +++ b/target/linux/brcm2708/patches-4.9/0055-BCM270x_DT-Add-pwr_led-and-the-required-input-trigge.patch @@ -1,4 +1,4 @@ -From f760337032ce3078b0ecfe2ec8420bbdf173151d Mon Sep 17 00:00:00 2001 +From 766357a4f8476461035dcfe2c6b43f532366f533 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 Feb 2015 13:50:57 +0000 Subject: [PATCH] BCM270x_DT: Add pwr_led, and the required "input" trigger diff --git a/target/linux/brcm2708/patches-4.9/0056-fbdev-add-FBIOCOPYAREA-ioctl.patch b/target/linux/brcm2708/patches-4.9/0056-fbdev-add-FBIOCOPYAREA-ioctl.patch index 44414e5481..34346903da 100644 --- a/target/linux/brcm2708/patches-4.9/0056-fbdev-add-FBIOCOPYAREA-ioctl.patch +++ b/target/linux/brcm2708/patches-4.9/0056-fbdev-add-FBIOCOPYAREA-ioctl.patch @@ -1,4 +1,4 @@ -From c19ea76c6206a3e5a897cef2da65d82c6dd76430 Mon Sep 17 00:00:00 2001 +From 65422160b21224e6d26641a4c1fa3082c0281488 Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 13:32:11 +0300 Subject: [PATCH] fbdev: add FBIOCOPYAREA ioctl diff --git a/target/linux/brcm2708/patches-4.9/0057-Speed-up-console-framebuffer-imageblit-function.patch b/target/linux/brcm2708/patches-4.9/0057-Speed-up-console-framebuffer-imageblit-function.patch index f0e7392e64..8d6337a94d 100644 --- a/target/linux/brcm2708/patches-4.9/0057-Speed-up-console-framebuffer-imageblit-function.patch +++ b/target/linux/brcm2708/patches-4.9/0057-Speed-up-console-framebuffer-imageblit-function.patch @@ -1,4 +1,4 @@ -From 11db806d75a8958fb706d8a1b4e67818a04d68c7 Mon Sep 17 00:00:00 2001 +From fead9bc9e55df547b54a9cd55d932b209090cfeb Mon Sep 17 00:00:00 2001 From: Harm Hanemaaijer Date: Thu, 20 Jun 2013 20:21:39 +0200 Subject: [PATCH] Speed up console framebuffer imageblit function diff --git a/target/linux/brcm2708/patches-4.9/0058-enabling-the-realtime-clock-1-wire-chip-DS1307-and-1.patch b/target/linux/brcm2708/patches-4.9/0058-enabling-the-realtime-clock-1-wire-chip-DS1307-and-1.patch index 5c3e0641cb..408ac045f7 100644 --- a/target/linux/brcm2708/patches-4.9/0058-enabling-the-realtime-clock-1-wire-chip-DS1307-and-1.patch +++ b/target/linux/brcm2708/patches-4.9/0058-enabling-the-realtime-clock-1-wire-chip-DS1307-and-1.patch @@ -1,4 +1,4 @@ -From d387edf492067aa0d298b90829b784f640375e7c Mon Sep 17 00:00:00 2001 +From 5edc95eee5ef69d7bfe03eede0e711e8f196dedc Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 May 2013 11:46:50 +0100 Subject: [PATCH] enabling the realtime clock 1-wire chip DS1307 and 1-wire on diff --git a/target/linux/brcm2708/patches-4.9/0059-Added-Device-IDs-for-August-DVB-T-205.patch b/target/linux/brcm2708/patches-4.9/0059-Added-Device-IDs-for-August-DVB-T-205.patch index ec376d40f2..a9906f3e3c 100644 --- a/target/linux/brcm2708/patches-4.9/0059-Added-Device-IDs-for-August-DVB-T-205.patch +++ b/target/linux/brcm2708/patches-4.9/0059-Added-Device-IDs-for-August-DVB-T-205.patch @@ -1,4 +1,4 @@ -From c7850d63ac4cf12c0a70c2014cc2451a5118e717 Mon Sep 17 00:00:00 2001 +From 0d3a6a7484390def36773cb4fee0e16d6b8c45d1 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:54:08 +0100 Subject: [PATCH] Added Device IDs for August DVB-T 205 diff --git a/target/linux/brcm2708/patches-4.9/0060-config-Enable-CONFIG_MEMCG-but-leave-it-disabled-due.patch b/target/linux/brcm2708/patches-4.9/0060-config-Enable-CONFIG_MEMCG-but-leave-it-disabled-due.patch index a2eca8a994..73c9edeea4 100644 --- a/target/linux/brcm2708/patches-4.9/0060-config-Enable-CONFIG_MEMCG-but-leave-it-disabled-due.patch +++ b/target/linux/brcm2708/patches-4.9/0060-config-Enable-CONFIG_MEMCG-but-leave-it-disabled-due.patch @@ -1,4 +1,4 @@ -From d8fe940fffef38e498beaa5bd182647452d98de9 Mon Sep 17 00:00:00 2001 +From c50fe09c78e9b87137e0188139c774bd4f12dcb2 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 18 Dec 2013 22:16:19 +0000 Subject: [PATCH] config: Enable CONFIG_MEMCG, but leave it disabled (due to diff --git a/target/linux/brcm2708/patches-4.9/0061-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch b/target/linux/brcm2708/patches-4.9/0061-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch index e9f34194c7..444c64e471 100644 --- a/target/linux/brcm2708/patches-4.9/0061-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch +++ b/target/linux/brcm2708/patches-4.9/0061-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch @@ -1,4 +1,4 @@ -From 1697df63a0dd1cdc54f304cfb7c4a3a997661f06 Mon Sep 17 00:00:00 2001 +From 56f13ae9d518c5aec8736ccc639f2f5e2c3784ad Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 14 Jul 2014 22:02:09 +0100 Subject: [PATCH] hid: Reduce default mouse polling interval to 60Hz diff --git a/target/linux/brcm2708/patches-4.9/0062-rpi-ft5406-Add-touchscreen-driver-for-pi-LCD-display.patch b/target/linux/brcm2708/patches-4.9/0062-rpi-ft5406-Add-touchscreen-driver-for-pi-LCD-display.patch index 3d98c22570..43ed3faa9c 100644 --- a/target/linux/brcm2708/patches-4.9/0062-rpi-ft5406-Add-touchscreen-driver-for-pi-LCD-display.patch +++ b/target/linux/brcm2708/patches-4.9/0062-rpi-ft5406-Add-touchscreen-driver-for-pi-LCD-display.patch @@ -1,4 +1,4 @@ -From e7fa4e5d3db9996074a22db9eff4833d33d11fb6 Mon Sep 17 00:00:00 2001 +From 18c740925ca44b8a2f55ac201acf935f9fa97515 Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Tue, 12 May 2015 14:47:56 +0100 Subject: [PATCH] rpi-ft5406: Add touchscreen driver for pi LCD display diff --git a/target/linux/brcm2708/patches-4.9/0063-Improve-__copy_to_user-and-__copy_from_user-performa.patch b/target/linux/brcm2708/patches-4.9/0063-Improve-__copy_to_user-and-__copy_from_user-performa.patch index 2d92f77a6f..a7ce64ba38 100644 --- a/target/linux/brcm2708/patches-4.9/0063-Improve-__copy_to_user-and-__copy_from_user-performa.patch +++ b/target/linux/brcm2708/patches-4.9/0063-Improve-__copy_to_user-and-__copy_from_user-performa.patch @@ -1,4 +1,4 @@ -From 77346574b6cd6bfbeac98ac6c711c281a71adebb Mon Sep 17 00:00:00 2001 +From ebd731dd71ec9728a5a87ec1cd695be15828c32c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 28 Nov 2016 16:50:04 +0000 Subject: [PATCH] Improve __copy_to_user and __copy_from_user performance diff --git a/target/linux/brcm2708/patches-4.9/0064-gpio-poweroff-Allow-it-to-work-on-Raspberry-Pi.patch b/target/linux/brcm2708/patches-4.9/0064-gpio-poweroff-Allow-it-to-work-on-Raspberry-Pi.patch index 3a86d97108..5d73a28246 100644 --- a/target/linux/brcm2708/patches-4.9/0064-gpio-poweroff-Allow-it-to-work-on-Raspberry-Pi.patch +++ b/target/linux/brcm2708/patches-4.9/0064-gpio-poweroff-Allow-it-to-work-on-Raspberry-Pi.patch @@ -1,4 +1,4 @@ -From da2b72916e1fa0824a139bda7f28216640d6727c Mon Sep 17 00:00:00 2001 +From 7e8bb86739df17e38a0ebe6e17b7a9056ab421e9 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 25 Jun 2015 12:16:11 +0100 Subject: [PATCH] gpio-poweroff: Allow it to work on Raspberry Pi diff --git a/target/linux/brcm2708/patches-4.9/0065-mfd-Add-Raspberry-Pi-Sense-HAT-core-driver.patch b/target/linux/brcm2708/patches-4.9/0065-mfd-Add-Raspberry-Pi-Sense-HAT-core-driver.patch index 77079e0493..b5ae3f954c 100644 --- a/target/linux/brcm2708/patches-4.9/0065-mfd-Add-Raspberry-Pi-Sense-HAT-core-driver.patch +++ b/target/linux/brcm2708/patches-4.9/0065-mfd-Add-Raspberry-Pi-Sense-HAT-core-driver.patch @@ -1,4 +1,4 @@ -From 91d2e7c60d71cd4450ee3ac68b8fcdfe7f93a1f0 Mon Sep 17 00:00:00 2001 +From 157f59328885549a0f2c1fe35e9ec3aff0f0b52e Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 14 Jul 2015 14:32:47 +0100 Subject: [PATCH] mfd: Add Raspberry Pi Sense HAT core driver diff --git a/target/linux/brcm2708/patches-4.9/0066-ASoC-Add-support-for-HifiBerry-DAC.patch b/target/linux/brcm2708/patches-4.9/0066-ASoC-Add-support-for-HifiBerry-DAC.patch index 22f8654d68..107ed28c1b 100644 --- a/target/linux/brcm2708/patches-4.9/0066-ASoC-Add-support-for-HifiBerry-DAC.patch +++ b/target/linux/brcm2708/patches-4.9/0066-ASoC-Add-support-for-HifiBerry-DAC.patch @@ -1,4 +1,4 @@ -From c9f07d6d39019ae80e97e0d1cf070a78c4a6c974 Mon Sep 17 00:00:00 2001 +From fe9fdf49ba81e28860e5367ea8bb9c6b1c6a0460 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 19:19:08 +0100 Subject: [PATCH] ASoC: Add support for HifiBerry DAC diff --git a/target/linux/brcm2708/patches-4.9/0067-ASoC-Add-support-for-Rpi-DAC.patch b/target/linux/brcm2708/patches-4.9/0067-ASoC-Add-support-for-Rpi-DAC.patch index 0353820121..26ae5b3d76 100644 --- a/target/linux/brcm2708/patches-4.9/0067-ASoC-Add-support-for-Rpi-DAC.patch +++ b/target/linux/brcm2708/patches-4.9/0067-ASoC-Add-support-for-Rpi-DAC.patch @@ -1,4 +1,4 @@ -From fd63dade0da2751e1b4d38a7bc1f70611bf85e31 Mon Sep 17 00:00:00 2001 +From 3a890b43d08fbfe10895f733578f095a6449ba0b Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Mon, 25 Jan 2016 15:48:59 +0000 Subject: [PATCH] ASoC: Add support for Rpi-DAC diff --git a/target/linux/brcm2708/patches-4.9/0068-ASoC-wm8804-Implement-MCLK-configuration-options-add.patch b/target/linux/brcm2708/patches-4.9/0068-ASoC-wm8804-Implement-MCLK-configuration-options-add.patch index 7accb99842..1be734befa 100644 --- a/target/linux/brcm2708/patches-4.9/0068-ASoC-wm8804-Implement-MCLK-configuration-options-add.patch +++ b/target/linux/brcm2708/patches-4.9/0068-ASoC-wm8804-Implement-MCLK-configuration-options-add.patch @@ -1,4 +1,4 @@ -From c137d8fd4fd6a01ca8afc140cab7d7c3c39f3f33 Mon Sep 17 00:00:00 2001 +From 8432dc7c8a843e7c35d7624adc6653e13dd488a7 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Wed, 15 Jan 2014 21:41:23 +0100 Subject: [PATCH] ASoC: wm8804: Implement MCLK configuration options, add 32bit diff --git a/target/linux/brcm2708/patches-4.9/0069-ASoC-BCM-Add-support-for-HiFiBerry-Digi.-Driver-is-b.patch b/target/linux/brcm2708/patches-4.9/0069-ASoC-BCM-Add-support-for-HiFiBerry-Digi.-Driver-is-b.patch index d9dc426649..5f8477cd7b 100644 --- a/target/linux/brcm2708/patches-4.9/0069-ASoC-BCM-Add-support-for-HiFiBerry-Digi.-Driver-is-b.patch +++ b/target/linux/brcm2708/patches-4.9/0069-ASoC-BCM-Add-support-for-HiFiBerry-Digi.-Driver-is-b.patch @@ -1,4 +1,4 @@ -From 8a6178b707acd262871cb08791f8d9e7248a4107 Mon Sep 17 00:00:00 2001 +From ded3c4c0c46af840159e4fc79a065d69cbb7b534 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Wed, 15 Jan 2014 21:42:08 +0100 Subject: [PATCH] ASoC: BCM:Add support for HiFiBerry Digi. Driver is based on diff --git a/target/linux/brcm2708/patches-4.9/0070-Add-IQaudIO-Sound-Card-support-for-Raspberry-Pi.patch b/target/linux/brcm2708/patches-4.9/0070-Add-IQaudIO-Sound-Card-support-for-Raspberry-Pi.patch index 483fc6e791..08bf856c9f 100644 --- a/target/linux/brcm2708/patches-4.9/0070-Add-IQaudIO-Sound-Card-support-for-Raspberry-Pi.patch +++ b/target/linux/brcm2708/patches-4.9/0070-Add-IQaudIO-Sound-Card-support-for-Raspberry-Pi.patch @@ -1,4 +1,4 @@ -From db63efa8452156b71aedb5aa1e77182d25bc6906 Mon Sep 17 00:00:00 2001 +From fcfe9087b79176b5d8afd0ecc4c66013866ef239 Mon Sep 17 00:00:00 2001 From: Gordon Garrity Date: Sat, 8 Mar 2014 16:56:57 +0000 Subject: [PATCH] Add IQaudIO Sound Card support for Raspberry Pi diff --git a/target/linux/brcm2708/patches-4.9/0071-iqaudio-dac-Compile-fix-untested.patch b/target/linux/brcm2708/patches-4.9/0071-iqaudio-dac-Compile-fix-untested.patch index 51d731aded..edfb9f5e1f 100644 --- a/target/linux/brcm2708/patches-4.9/0071-iqaudio-dac-Compile-fix-untested.patch +++ b/target/linux/brcm2708/patches-4.9/0071-iqaudio-dac-Compile-fix-untested.patch @@ -1,4 +1,4 @@ -From bde9a1a68dbc0fe50a899b2178128068482f4ec9 Mon Sep 17 00:00:00 2001 +From 711f7413d72af6328a3958eecd400bd8911af211 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 25 Jul 2016 17:06:50 +0100 Subject: [PATCH] iqaudio-dac: Compile fix - untested diff --git a/target/linux/brcm2708/patches-4.9/0072-Added-support-for-HiFiBerry-DAC.patch b/target/linux/brcm2708/patches-4.9/0072-Added-support-for-HiFiBerry-DAC.patch index daccc7c144..21d30af475 100644 --- a/target/linux/brcm2708/patches-4.9/0072-Added-support-for-HiFiBerry-DAC.patch +++ b/target/linux/brcm2708/patches-4.9/0072-Added-support-for-HiFiBerry-DAC.patch @@ -1,4 +1,4 @@ -From 728a454670c1c65e518a81122683f6cd1e08e967 Mon Sep 17 00:00:00 2001 +From 9c6b8bd0db7564a2124290e3bc30215906371fa9 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Mon, 4 Aug 2014 10:06:56 +0200 Subject: [PATCH] Added support for HiFiBerry DAC+ diff --git a/target/linux/brcm2708/patches-4.9/0073-Added-driver-for-HiFiBerry-Amp-amplifier-add-on-boar.patch b/target/linux/brcm2708/patches-4.9/0073-Added-driver-for-HiFiBerry-Amp-amplifier-add-on-boar.patch index fb823d2e7c..9826be5725 100644 --- a/target/linux/brcm2708/patches-4.9/0073-Added-driver-for-HiFiBerry-Amp-amplifier-add-on-boar.patch +++ b/target/linux/brcm2708/patches-4.9/0073-Added-driver-for-HiFiBerry-Amp-amplifier-add-on-boar.patch @@ -1,4 +1,4 @@ -From a9a8a1127418a342cfd7409d10137cbe4e20b951 Mon Sep 17 00:00:00 2001 +From 0f11b0757d5950ee7a8ba00e49ebefd2c649a6ba Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Mon, 4 Aug 2014 11:09:58 +0200 Subject: [PATCH] Added driver for HiFiBerry Amp amplifier add-on board @@ -16,15 +16,19 @@ reported correctly by a non-zero return code. HiFiBerry Amp: fix device-tree problems Some code to load the driver based on device-tree-overlays was missing. This is added by this patch. + +hifiberry-amp: Adjust for ALSA object refactoring + +See: https://github.com/raspberrypi/linux/issues/1775 --- sound/soc/bcm/Kconfig | 7 + sound/soc/bcm/Makefile | 2 + sound/soc/bcm/hifiberry_amp.c | 129 +++++++++++++++ sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + - sound/soc/codecs/tas5713.c | 369 ++++++++++++++++++++++++++++++++++++++++++ + sound/soc/codecs/tas5713.c | 371 ++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/tas5713.h | 210 ++++++++++++++++++++++++ - 7 files changed, 723 insertions(+) + 7 files changed, 725 insertions(+) create mode 100644 sound/soc/bcm/hifiberry_amp.c create mode 100644 sound/soc/codecs/tas5713.c create mode 100644 sound/soc/codecs/tas5713.h @@ -47,20 +51,21 @@ Some code to load the driver based on device-tree-overlays was missing. This is depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -12,11 +12,13 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc- +@@ -9,12 +9,14 @@ snd-soc-cygnus-objs := cygnus-pcm.o cygn + obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-cygnus.o + + # BCM2708 Machine Support ++snd-soc-hifiberry-amp-objs := hifiberry_amp.o snd-soc-hifiberry-dac-objs := hifiberry_dac.o snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o snd-soc-hifiberry-digi-objs := hifiberry_digi.o -+snd-soc-hifiberry-amp-objs := hifiberry_amp.o snd-soc-rpi-dac-objs := rpi-dac.o snd-soc-iqaudio-dac-objs := iqaudio-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o --- /dev/null +++ b/sound/soc/bcm/hifiberry_amp.c @@ -0,0 +1,129 @@ @@ -233,7 +238,7 @@ Some code to load the driver based on device-tree-overlays was missing. This is obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o --- /dev/null +++ b/sound/soc/codecs/tas5713.c -@@ -0,0 +1,369 @@ +@@ -0,0 +1,371 @@ +/* + * ASoC Driver for TAS5713 + * @@ -468,8 +473,10 @@ Some code to load the driver based on device-tree-overlays was missing. This is +static struct snd_soc_codec_driver soc_codec_dev_tas5713 = { + .probe = tas5713_probe, + .remove = tas5713_remove, -+ .controls = tas5713_snd_controls, -+ .num_controls = ARRAY_SIZE(tas5713_snd_controls), ++ .component_driver = { ++ .controls = tas5713_snd_controls, ++ .num_controls = ARRAY_SIZE(tas5713_snd_controls), ++ }, +}; + + diff --git a/target/linux/brcm2708/patches-4.9/0074-Revert-Added-driver-for-HiFiBerry-Amp-amplifier-add-.patch b/target/linux/brcm2708/patches-4.9/0074-Revert-Added-driver-for-HiFiBerry-Amp-amplifier-add-.patch deleted file mode 100644 index 412398731e..0000000000 --- a/target/linux/brcm2708/patches-4.9/0074-Revert-Added-driver-for-HiFiBerry-Amp-amplifier-add-.patch +++ /dev/null @@ -1,807 +0,0 @@ -From 321a000ddec470ccbe496e6ae2cdc65286d8f491 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 12 Dec 2016 16:26:54 +0000 -Subject: [PATCH] Revert "Added driver for HiFiBerry Amp amplifier add-on - board" - -This reverts commit 3e6b00833d92a50cbcc9922deb6e1bc8fcdbb587. ---- - sound/soc/bcm/Kconfig | 7 - - sound/soc/bcm/Makefile | 2 - - sound/soc/bcm/hifiberry_amp.c | 129 --------------- - sound/soc/codecs/Kconfig | 4 - - sound/soc/codecs/Makefile | 2 - - sound/soc/codecs/tas5713.c | 369 ------------------------------------------ - sound/soc/codecs/tas5713.h | 210 ------------------------ - 7 files changed, 723 deletions(-) - delete mode 100644 sound/soc/bcm/hifiberry_amp.c - delete mode 100644 sound/soc/codecs/tas5713.c - delete mode 100644 sound/soc/codecs/tas5713.h - ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -38,13 +38,6 @@ config SND_BCM2708_SOC_HIFIBERRY_DIGI - help - Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. - --config SND_BCM2708_SOC_HIFIBERRY_AMP -- tristate "Support for the HifiBerry Amp" -- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -- select SND_SOC_TAS5713 -- help -- Say Y or M if you want to add support for the HifiBerry Amp amplifier board. -- - config SND_BCM2708_SOC_RPI_DAC - tristate "Support for RPi-DAC" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -12,13 +12,11 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc- - snd-soc-hifiberry-dac-objs := hifiberry_dac.o - snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o --snd-soc-hifiberry-amp-objs := hifiberry_amp.o - snd-soc-rpi-dac-objs := rpi-dac.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o --obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o ---- a/sound/soc/bcm/hifiberry_amp.c -+++ /dev/null -@@ -1,129 +0,0 @@ --/* -- * ASoC Driver for HifiBerry AMP -- * -- * Author: Sebastian Eickhoff -- * Copyright 2014 -- * -- * This program is free software; you can redistribute it and/or -- * modify it under the terms of the GNU General Public License -- * version 2 as published by the Free Software Foundation. -- * -- * This program is distributed in the hope that it will be useful, but -- * WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * General Public License for more details. -- */ -- --#include --#include -- --#include --#include --#include --#include --#include -- --static int snd_rpi_hifiberry_amp_init(struct snd_soc_pcm_runtime *rtd) --{ -- // ToDo: init of the dsp-registers. -- return 0; --} -- --static int snd_rpi_hifiberry_amp_hw_params( struct snd_pcm_substream *substream, -- struct snd_pcm_hw_params *params ) --{ -- struct snd_soc_pcm_runtime *rtd = substream->private_data; -- struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -- -- return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); --} -- --static struct snd_soc_ops snd_rpi_hifiberry_amp_ops = { -- .hw_params = snd_rpi_hifiberry_amp_hw_params, --}; -- --static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = { -- { -- .name = "HifiBerry AMP", -- .stream_name = "HifiBerry AMP HiFi", -- .cpu_dai_name = "bcm2708-i2s.0", -- .codec_dai_name = "tas5713-hifi", -- .platform_name = "bcm2708-i2s.0", -- .codec_name = "tas5713.1-001b", -- .dai_fmt = SND_SOC_DAIFMT_I2S | -- SND_SOC_DAIFMT_NB_NF | -- SND_SOC_DAIFMT_CBS_CFS, -- .ops = &snd_rpi_hifiberry_amp_ops, -- .init = snd_rpi_hifiberry_amp_init, -- }, --}; -- -- --static struct snd_soc_card snd_rpi_hifiberry_amp = { -- .name = "snd_rpi_hifiberry_amp", -- .driver_name = "HifiberryAmp", -- .owner = THIS_MODULE, -- .dai_link = snd_rpi_hifiberry_amp_dai, -- .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), --}; -- --static const struct of_device_id snd_rpi_hifiberry_amp_of_match[] = { -- { .compatible = "hifiberry,hifiberry-amp", }, -- {}, --}; --MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_amp_of_match); -- -- --static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) --{ -- int ret = 0; -- -- snd_rpi_hifiberry_amp.dev = &pdev->dev; -- -- if (pdev->dev.of_node) { -- struct device_node *i2s_node; -- struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_amp_dai[0]; -- i2s_node = of_parse_phandle(pdev->dev.of_node, -- "i2s-controller", 0); -- -- if (i2s_node) { -- dai->cpu_dai_name = NULL; -- dai->cpu_of_node = i2s_node; -- dai->platform_name = NULL; -- dai->platform_of_node = i2s_node; -- } -- } -- -- ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); -- -- if (ret != 0) { -- dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -- } -- -- return ret; --} -- -- --static int snd_rpi_hifiberry_amp_remove(struct platform_device *pdev) --{ -- return snd_soc_unregister_card(&snd_rpi_hifiberry_amp); --} -- -- --static struct platform_driver snd_rpi_hifiberry_amp_driver = { -- .driver = { -- .name = "snd-hifiberry-amp", -- .owner = THIS_MODULE, -- .of_match_table = snd_rpi_hifiberry_amp_of_match, -- }, -- .probe = snd_rpi_hifiberry_amp_probe, -- .remove = snd_rpi_hifiberry_amp_remove, --}; -- -- --module_platform_driver(snd_rpi_hifiberry_amp_driver); -- -- --MODULE_AUTHOR("Sebastian Eickhoff "); --MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); --MODULE_LICENSE("GPL v2"); ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -139,7 +139,6 @@ config SND_SOC_ALL_CODECS - select SND_SOC_TFA9879 if I2C - select SND_SOC_TLV320AIC23_I2C if I2C - select SND_SOC_TLV320AIC23_SPI if SPI_MASTER -- select SND_SOC_TAS5713 if I2C - select SND_SOC_TLV320AIC26 if SPI_MASTER - select SND_SOC_TLV320AIC31XX if I2C - select SND_SOC_TLV320AIC32X4_I2C if I2C -@@ -822,9 +821,6 @@ config SND_SOC_TFA9879 - tristate "NXP Semiconductors TFA9879 amplifier" - depends on I2C - --config SND_SOC_TAS5713 -- tristate -- - config SND_SOC_TLV320AIC23 - tristate - ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -144,7 +144,6 @@ snd-soc-tas5086-objs := tas5086.o - snd-soc-tas571x-objs := tas571x.o - snd-soc-tas5720-objs := tas5720.o - snd-soc-tfa9879-objs := tfa9879.o --snd-soc-tas5713-objs := tas5713.o - snd-soc-tlv320aic23-objs := tlv320aic23.o - snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o - snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o -@@ -367,7 +366,6 @@ obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc - obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o - obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o - obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o --obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o - obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o - obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o - obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o ---- a/sound/soc/codecs/tas5713.c -+++ /dev/null -@@ -1,369 +0,0 @@ --/* -- * ASoC Driver for TAS5713 -- * -- * Author: Sebastian Eickhoff -- * Copyright 2014 -- * -- * This program is free software; you can redistribute it and/or -- * modify it under the terms of the GNU General Public License -- * version 2 as published by the Free Software Foundation. -- * -- * This program is distributed in the hope that it will be useful, but -- * WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * General Public License for more details. -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include --#include --#include --#include -- --#include "tas5713.h" -- -- --static struct i2c_client *i2c; -- --struct tas5713_priv { -- struct regmap *regmap; -- int mclk_div; -- struct snd_soc_codec *codec; --}; -- --static struct tas5713_priv *priv_data; -- -- -- -- --/* -- * _ _ ___ _ ___ _ _ -- * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___ -- * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-< -- * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/ -- * -- */ -- --static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1); -- -- --static const struct snd_kcontrol_new tas5713_snd_controls[] = { -- SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv), -- SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv) --}; -- -- -- -- --/* -- * __ __ _ _ ___ _ -- * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _ -- * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_| -- * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_| -- * -- */ -- --static int tas5713_hw_params(struct snd_pcm_substream *substream, -- struct snd_pcm_hw_params *params, -- struct snd_soc_dai *dai) --{ -- u16 blen = 0x00; -- -- struct snd_soc_codec *codec; -- codec = dai->codec; -- priv_data->codec = dai->codec; -- -- switch (params_format(params)) { -- case SNDRV_PCM_FORMAT_S16_LE: -- blen = 0x03; -- break; -- case SNDRV_PCM_FORMAT_S20_3LE: -- blen = 0x1; -- break; -- case SNDRV_PCM_FORMAT_S24_LE: -- blen = 0x04; -- break; -- case SNDRV_PCM_FORMAT_S32_LE: -- blen = 0x05; -- break; -- default: -- dev_err(dai->dev, "Unsupported word length: %u\n", -- params_format(params)); -- return -EINVAL; -- } -- -- // set word length -- snd_soc_update_bits(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen); -- -- return 0; --} -- -- --static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream) --{ -- unsigned int val = 0; -- -- struct tas5713_priv *tas5713; -- struct snd_soc_codec *codec = dai->codec; -- tas5713 = snd_soc_codec_get_drvdata(codec); -- -- if (mute) { -- val = TAS5713_SOFT_MUTE_ALL; -- } -- -- return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val); --} -- -- --static const struct snd_soc_dai_ops tas5713_dai_ops = { -- .hw_params = tas5713_hw_params, -- .mute_stream = tas5713_mute_stream, --}; -- -- --static struct snd_soc_dai_driver tas5713_dai = { -- .name = "tas5713-hifi", -- .playback = { -- .stream_name = "Playback", -- .channels_min = 2, -- .channels_max = 2, -- .rates = SNDRV_PCM_RATE_8000_48000, -- .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ), -- }, -- .ops = &tas5713_dai_ops, --}; -- -- -- -- --/* -- * ___ _ ___ _ -- * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _ -- * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_| -- * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_| -- * -- */ -- --static int tas5713_remove(struct snd_soc_codec *codec) --{ -- struct tas5713_priv *tas5713; -- -- tas5713 = snd_soc_codec_get_drvdata(codec); -- -- return 0; --} -- -- --static int tas5713_probe(struct snd_soc_codec *codec) --{ -- struct tas5713_priv *tas5713; -- int i, ret; -- -- i2c = container_of(codec->dev, struct i2c_client, dev); -- -- tas5713 = snd_soc_codec_get_drvdata(codec); -- -- // Reset error -- ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -- if (ret < 0) return ret; -- -- // Trim oscillator -- ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); -- if (ret < 0) return ret; -- msleep(1000); -- -- // Reset error -- ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -- if (ret < 0) return ret; -- -- // Clock mode: 44/48kHz, MCLK=64xfs -- ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60); -- if (ret < 0) return ret; -- -- // I2S 24bit -- ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05); -- if (ret < 0) return ret; -- -- // Unmute -- ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -- if (ret < 0) return ret; -- ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00); -- if (ret < 0) return ret; -- -- // Set volume to 0db -- ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00); -- if (ret < 0) return ret; -- -- // Now start programming the default initialization sequence -- for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) { -- ret = i2c_master_send(i2c, -- tas5713_init_sequence[i].data, -- tas5713_init_sequence[i].size); -- if (ret < 0) { -- printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret); -- } -- } -- -- // Unmute -- ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -- if (ret < 0) return ret; -- -- return 0; --} -- -- --static struct snd_soc_codec_driver soc_codec_dev_tas5713 = { -- .probe = tas5713_probe, -- .remove = tas5713_remove, -- .controls = tas5713_snd_controls, -- .num_controls = ARRAY_SIZE(tas5713_snd_controls), --}; -- -- -- -- --/* -- * ___ ___ ___ ___ _ -- * |_ _|_ ) __| | \ _ _(_)_ _____ _ _ -- * | | / / (__ | |) | '_| \ V / -_) '_| -- * |___/___\___| |___/|_| |_|\_/\___|_| -- * -- */ -- --static const struct reg_default tas5713_reg_defaults[] = { -- { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB -- { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB -- { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB -- { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB --}; -- -- --static bool tas5713_reg_volatile(struct device *dev, unsigned int reg) --{ -- switch (reg) { -- case TAS5713_DEVICE_ID: -- case TAS5713_ERROR_STATUS: -- return true; -- default: -- return false; -- } --} -- -- --static const struct of_device_id tas5713_of_match[] = { -- { .compatible = "ti,tas5713", }, -- { } --}; --MODULE_DEVICE_TABLE(of, tas5713_of_match); -- -- --static struct regmap_config tas5713_regmap_config = { -- .reg_bits = 8, -- .val_bits = 8, -- -- .max_register = TAS5713_MAX_REGISTER, -- .volatile_reg = tas5713_reg_volatile, -- -- .cache_type = REGCACHE_RBTREE, -- .reg_defaults = tas5713_reg_defaults, -- .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults), --}; -- -- --static int tas5713_i2c_probe(struct i2c_client *i2c, -- const struct i2c_device_id *id) --{ -- int ret; -- -- priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL); -- if (!priv_data) -- return -ENOMEM; -- -- priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config); -- if (IS_ERR(priv_data->regmap)) { -- ret = PTR_ERR(priv_data->regmap); -- return ret; -- } -- -- i2c_set_clientdata(i2c, priv_data); -- -- ret = snd_soc_register_codec(&i2c->dev, -- &soc_codec_dev_tas5713, &tas5713_dai, 1); -- -- return ret; --} -- -- --static int tas5713_i2c_remove(struct i2c_client *i2c) --{ -- snd_soc_unregister_codec(&i2c->dev); -- i2c_set_clientdata(i2c, NULL); -- -- kfree(priv_data); -- -- return 0; --} -- -- --static const struct i2c_device_id tas5713_i2c_id[] = { -- { "tas5713", 0 }, -- { } --}; -- --MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id); -- -- --static struct i2c_driver tas5713_i2c_driver = { -- .driver = { -- .name = "tas5713", -- .owner = THIS_MODULE, -- .of_match_table = tas5713_of_match, -- }, -- .probe = tas5713_i2c_probe, -- .remove = tas5713_i2c_remove, -- .id_table = tas5713_i2c_id --}; -- -- --static int __init tas5713_modinit(void) --{ -- int ret = 0; -- -- ret = i2c_add_driver(&tas5713_i2c_driver); -- if (ret) { -- printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n", -- ret); -- } -- -- return ret; --} --module_init(tas5713_modinit); -- -- --static void __exit tas5713_exit(void) --{ -- i2c_del_driver(&tas5713_i2c_driver); --} --module_exit(tas5713_exit); -- -- --MODULE_AUTHOR("Sebastian Eickhoff "); --MODULE_DESCRIPTION("ASoC driver for TAS5713"); --MODULE_LICENSE("GPL v2"); ---- a/sound/soc/codecs/tas5713.h -+++ /dev/null -@@ -1,210 +0,0 @@ --/* -- * ASoC Driver for TAS5713 -- * -- * Author: Sebastian Eickhoff -- * Copyright 2014 -- * -- * This program is free software; you can redistribute it and/or -- * modify it under the terms of the GNU General Public License -- * version 2 as published by the Free Software Foundation. -- * -- * This program is distributed in the hope that it will be useful, but -- * WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * General Public License for more details. -- */ -- --#ifndef _TAS5713_H --#define _TAS5713_H -- -- --// TAS5713 I2C-bus register addresses -- --#define TAS5713_CLOCK_CTRL 0x00 --#define TAS5713_DEVICE_ID 0x01 --#define TAS5713_ERROR_STATUS 0x02 --#define TAS5713_SYSTEM_CTRL1 0x03 --#define TAS5713_SERIAL_DATA_INTERFACE 0x04 --#define TAS5713_SYSTEM_CTRL2 0x05 --#define TAS5713_SOFT_MUTE 0x06 --#define TAS5713_VOL_MASTER 0x07 --#define TAS5713_VOL_CH1 0x08 --#define TAS5713_VOL_CH2 0x09 --#define TAS5713_VOL_HEADPHONE 0x0A --#define TAS5713_VOL_CONFIG 0x0E --#define TAS5713_MODULATION_LIMIT 0x10 --#define TAS5713_IC_DLY_CH1 0x11 --#define TAS5713_IC_DLY_CH2 0x12 --#define TAS5713_IC_DLY_CH3 0x13 --#define TAS5713_IC_DLY_CH4 0x14 -- --#define TAS5713_START_STOP_PERIOD 0x1A --#define TAS5713_OSC_TRIM 0x1B --#define TAS5713_BKND_ERR 0x1C -- --#define TAS5713_INPUT_MUX 0x20 --#define TAS5713_SRC_SELECT_CH4 0x21 --#define TAS5713_PWM_MUX 0x25 -- --#define TAS5713_CH1_BQ0 0x29 --#define TAS5713_CH1_BQ1 0x2A --#define TAS5713_CH1_BQ2 0x2B --#define TAS5713_CH1_BQ3 0x2C --#define TAS5713_CH1_BQ4 0x2D --#define TAS5713_CH1_BQ5 0x2E --#define TAS5713_CH1_BQ6 0x2F --#define TAS5713_CH1_BQ7 0x58 --#define TAS5713_CH1_BQ8 0x59 -- --#define TAS5713_CH2_BQ0 0x30 --#define TAS5713_CH2_BQ1 0x31 --#define TAS5713_CH2_BQ2 0x32 --#define TAS5713_CH2_BQ3 0x33 --#define TAS5713_CH2_BQ4 0x34 --#define TAS5713_CH2_BQ5 0x35 --#define TAS5713_CH2_BQ6 0x36 --#define TAS5713_CH2_BQ7 0x5C --#define TAS5713_CH2_BQ8 0x5D -- --#define TAS5713_CH4_BQ0 0x5A --#define TAS5713_CH4_BQ1 0x5B --#define TAS5713_CH3_BQ0 0x5E --#define TAS5713_CH3_BQ1 0x5F -- --#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B --#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C --#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E --#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F --#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40 --#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43 --#define TAS5713_DRC_CTRL 0x46 -- --#define TAS5713_BANK_SW_CTRL 0x50 --#define TAS5713_CH1_OUTPUT_MIXER 0x51 --#define TAS5713_CH2_OUTPUT_MIXER 0x52 --#define TAS5713_CH1_INPUT_MIXER 0x53 --#define TAS5713_CH2_INPUT_MIXER 0x54 --#define TAS5713_OUTPUT_POST_SCALE 0x56 --#define TAS5713_OUTPUT_PRESCALE 0x57 -- --#define TAS5713_IDF_POST_SCALE 0x62 -- --#define TAS5713_CH1_INLINE_MIXER 0x70 --#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71 --#define TAS5713_CH1_R_CHANNEL_MIXER 0x72 --#define TAS5713_CH1_L_CHANNEL_MIXER 0x73 --#define TAS5713_CH2_INLINE_MIXER 0x74 --#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75 --#define TAS5713_CH2_L_CHANNEL_MIXER 0x76 --#define TAS5713_CH2_R_CHANNEL_MIXER 0x77 -- --#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8 --#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9 -- --#define TAS5713_REGISTER_COUNT 0x46 --#define TAS5713_MAX_REGISTER 0xF9 -- -- --// Bitmasks for registers --#define TAS5713_SOFT_MUTE_ALL 0x07 -- -- -- --struct tas5713_init_command { -- const int size; -- const char *const data; --}; -- --static const struct tas5713_init_command tas5713_init_sequence[] = { -- -- // Trim oscillator -- { .size = 2, .data = "\x1B\x00" }, -- // System control register 1 (0x03): block DC -- { .size = 2, .data = "\x03\x80" }, -- // Mute everything -- { .size = 2, .data = "\x05\x40" }, -- // Modulation limit register (0x10): 97.7% -- { .size = 2, .data = "\x10\x02" }, -- // Interchannel delay registers -- // (0x11, 0x12, 0x13, and 0x14): BD mode -- { .size = 2, .data = "\x11\xB8" }, -- { .size = 2, .data = "\x12\x60" }, -- { .size = 2, .data = "\x13\xA0" }, -- { .size = 2, .data = "\x14\x48" }, -- // PWM shutdown group register (0x19): no shutdown -- { .size = 2, .data = "\x19\x00" }, -- // Input multiplexer register (0x20): BD mode -- { .size = 2, .data = "\x20\x00\x89\x77\x72" }, -- // PWM output mux register (0x25) -- // Channel 1 --> OUTA, channel 1 neg --> OUTB -- // Channel 2 --> OUTC, channel 2 neg --> OUTD -- { .size = 5, .data = "\x25\x01\x02\x13\x45" }, -- // DRC control (0x46): DRC off -- { .size = 5, .data = "\x46\x00\x00\x00\x00" }, -- // BKND_ERR register (0x1C): 299ms reset period -- { .size = 2, .data = "\x1C\x07" }, -- // Mute channel 3 -- { .size = 2, .data = "\x0A\xFF" }, -- // Volume configuration register (0x0E): volume slew 512 steps -- { .size = 2, .data = "\x0E\x90" }, -- // Clock control register (0x00): 44/48kHz, MCLK=64xfs -- { .size = 2, .data = "\x00\x60" }, -- // Bank switch and eq control (0x50): no bank switching -- { .size = 5, .data = "\x50\x00\x00\x00\x00" }, -- // Volume registers (0x07, 0x08, 0x09, 0x0A) -- { .size = 2, .data = "\x07\x20" }, -- { .size = 2, .data = "\x08\x30" }, -- { .size = 2, .data = "\x09\x30" }, -- { .size = 2, .data = "\x0A\xFF" }, -- // 0x72, 0x73, 0x76, 0x77 input mixer: -- // no intermix between channels -- { .size = 5, .data = "\x72\x00\x00\x00\x00" }, -- { .size = 5, .data = "\x73\x00\x80\x00\x00" }, -- { .size = 5, .data = "\x76\x00\x00\x00\x00" }, -- { .size = 5, .data = "\x77\x00\x80\x00\x00" }, -- // 0x70, 0x71, 0x74, 0x75 inline DRC mixer: -- // no inline DRC inmix -- { .size = 5, .data = "\x70\x00\x80\x00\x00" }, -- { .size = 5, .data = "\x71\x00\x00\x00\x00" }, -- { .size = 5, .data = "\x74\x00\x80\x00\x00" }, -- { .size = 5, .data = "\x75\x00\x00\x00\x00" }, -- // 0x56, 0x57 Output scale -- { .size = 5, .data = "\x56\x00\x80\x00\x00" }, -- { .size = 5, .data = "\x57\x00\x02\x00\x00" }, -- // 0x3B, 0x3c -- { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" }, -- { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -- { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" }, -- { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -- { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -- { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -- // 0x51, 0x52: output mixer -- { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" }, -- { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" }, -- // PEQ defaults -- { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -- { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, --}; -- -- --#endif /* _TAS5713_H */ diff --git a/target/linux/brcm2708/patches-4.9/0074-Update-ds1307-driver-for-device-tree-support.patch b/target/linux/brcm2708/patches-4.9/0074-Update-ds1307-driver-for-device-tree-support.patch new file mode 100644 index 0000000000..d4f7e762c2 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0074-Update-ds1307-driver-for-device-tree-support.patch @@ -0,0 +1,27 @@ +From b3ff56f28a9531048812a51ded7c16a952d1ead4 Mon Sep 17 00:00:00 2001 +From: Ryan Coe +Date: Sat, 31 Jan 2015 18:25:49 -0700 +Subject: [PATCH] Update ds1307 driver for device-tree support + +Signed-off-by: Ryan Coe +--- + drivers/rtc/rtc-ds1307.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/rtc/rtc-ds1307.c ++++ b/drivers/rtc/rtc-ds1307.c +@@ -1675,6 +1675,14 @@ static int ds1307_remove(struct i2c_clie + return 0; + } + ++#ifdef CONFIG_OF ++static const struct of_device_id ds1307_of_match[] = { ++ { .compatible = "maxim,ds1307" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ds1307_of_match); ++#endif ++ + static struct i2c_driver ds1307_driver = { + .driver = { + .name = "rtc-ds1307", diff --git a/target/linux/brcm2708/patches-4.9/0075-Add-driver-for-rpi-proto.patch b/target/linux/brcm2708/patches-4.9/0075-Add-driver-for-rpi-proto.patch new file mode 100644 index 0000000000..b8db1d5608 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0075-Add-driver-for-rpi-proto.patch @@ -0,0 +1,211 @@ +From b351d2ffe294c9d5e8cde9caa3a94017ecec81d9 Mon Sep 17 00:00:00 2001 +From: Waldemar Brodkorb +Date: Wed, 25 Mar 2015 09:26:17 +0100 +Subject: [PATCH] Add driver for rpi-proto + +Forward port of 3.10.x driver from https://github.com/koalo +We are using a custom board and would like to use rpi 3.18.x +kernel. Patch works fine for our embedded system. + +URL to the audio chip: +http://www.mikroe.com/add-on-boards/audio-voice/audio-codec-proto/ + +Playback tested with devicetree enabled. + +Signed-off-by: Waldemar Brodkorb +--- + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/rpi-proto.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 163 insertions(+) + create mode 100644 sound/soc/bcm/rpi-proto.c + +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -52,6 +52,13 @@ config SND_BCM2708_SOC_RPI_DAC + help + Say Y or M if you want to add support for RPi-DAC. + ++config SND_BCM2708_SOC_RPI_PROTO ++ tristate "Support for Rpi-PROTO" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_WM8731 ++ help ++ Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731). ++ + config SND_BCM2708_SOC_IQAUDIO_DAC + tristate "Support for IQaudIO-DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -14,6 +14,7 @@ snd-soc-hifiberry-dac-objs := hifiberry_ + snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o + snd-soc-rpi-dac-objs := rpi-dac.o ++snd-soc-rpi-proto-objs := rpi-proto.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o +@@ -21,4 +22,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +--- /dev/null ++++ b/sound/soc/bcm/rpi-proto.c +@@ -0,0 +1,154 @@ ++/* ++ * ASoC driver for PROTO AudioCODEC (with a WM8731) ++ * connected to a Raspberry Pi ++ * ++ * Author: Florian Meier, ++ * Copyright 2013 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "../codecs/wm8731.h" ++ ++static const unsigned int wm8731_rates_12288000[] = { ++ 8000, 32000, 48000, 96000, ++}; ++ ++static struct snd_pcm_hw_constraint_list wm8731_constraints_12288000 = { ++ .list = wm8731_rates_12288000, ++ .count = ARRAY_SIZE(wm8731_rates_12288000), ++}; ++ ++static int snd_rpi_proto_startup(struct snd_pcm_substream *substream) ++{ ++ /* Setup constraints, because there is a 12.288 MHz XTAL on the board */ ++ snd_pcm_hw_constraint_list(substream->runtime, 0, ++ SNDRV_PCM_HW_PARAM_RATE, ++ &wm8731_constraints_12288000); ++ return 0; ++} ++ ++static int snd_rpi_proto_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ int sysclk = 12288000; /* This is fixed on this board */ ++ ++ /* Set proto bclk */ ++ int ret = snd_soc_dai_set_bclk_ratio(cpu_dai,32*2); ++ if (ret < 0){ ++ dev_err(codec->dev, ++ "Failed to set BCLK ratio %d\n", ret); ++ return ret; ++ } ++ ++ /* Set proto sysclk */ ++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, ++ sysclk, SND_SOC_CLOCK_IN); ++ if (ret < 0) { ++ dev_err(codec->dev, ++ "Failed to set WM8731 SYSCLK: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_proto_ops = { ++ .startup = snd_rpi_proto_startup, ++ .hw_params = snd_rpi_proto_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_proto_dai[] = { ++{ ++ .name = "WM8731", ++ .stream_name = "WM8731 HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "wm8731-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "wm8731.1-001a", ++ .dai_fmt = SND_SOC_DAIFMT_I2S ++ | SND_SOC_DAIFMT_NB_NF ++ | SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &snd_rpi_proto_ops, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_proto = { ++ .name = "snd_rpi_proto", ++ .owner = THIS_MODULE, ++ .dai_link = snd_rpi_proto_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_proto_dai), ++}; ++ ++static int snd_rpi_proto_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_proto.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_proto_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_proto); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++ ++static int snd_rpi_proto_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_proto); ++} ++ ++static const struct of_device_id snd_rpi_proto_of_match[] = { ++ { .compatible = "rpi,rpi-proto", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_proto_of_match); ++ ++static struct platform_driver snd_rpi_proto_driver = { ++ .driver = { ++ .name = "snd-rpi-proto", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_proto_of_match, ++ }, ++ .probe = snd_rpi_proto_probe, ++ .remove = snd_rpi_proto_remove, ++}; ++ ++module_platform_driver(snd_rpi_proto_driver); ++ ++MODULE_AUTHOR("Florian Meier"); ++MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/brcm2708/patches-4.9/0075-Update-ds1307-driver-for-device-tree-support.patch b/target/linux/brcm2708/patches-4.9/0075-Update-ds1307-driver-for-device-tree-support.patch deleted file mode 100644 index 1dfed15876..0000000000 --- a/target/linux/brcm2708/patches-4.9/0075-Update-ds1307-driver-for-device-tree-support.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 682c095597876ff7d669f92dc2a0f1f49526444c Mon Sep 17 00:00:00 2001 -From: Ryan Coe -Date: Sat, 31 Jan 2015 18:25:49 -0700 -Subject: [PATCH] Update ds1307 driver for device-tree support - -Signed-off-by: Ryan Coe ---- - drivers/rtc/rtc-ds1307.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/rtc/rtc-ds1307.c -+++ b/drivers/rtc/rtc-ds1307.c -@@ -1675,6 +1675,14 @@ static int ds1307_remove(struct i2c_clie - return 0; - } - -+#ifdef CONFIG_OF -+static const struct of_device_id ds1307_of_match[] = { -+ { .compatible = "maxim,ds1307" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ds1307_of_match); -+#endif -+ - static struct i2c_driver ds1307_driver = { - .driver = { - .name = "rtc-ds1307", diff --git a/target/linux/brcm2708/patches-4.9/0076-Add-driver-for-rpi-proto.patch b/target/linux/brcm2708/patches-4.9/0076-Add-driver-for-rpi-proto.patch deleted file mode 100644 index b23ff22d34..0000000000 --- a/target/linux/brcm2708/patches-4.9/0076-Add-driver-for-rpi-proto.patch +++ /dev/null @@ -1,210 +0,0 @@ -From 001f8b8dc231bf3e20fd6802e2664788891ed8c4 Mon Sep 17 00:00:00 2001 -From: Waldemar Brodkorb -Date: Wed, 25 Mar 2015 09:26:17 +0100 -Subject: [PATCH] Add driver for rpi-proto - -Forward port of 3.10.x driver from https://github.com/koalo -We are using a custom board and would like to use rpi 3.18.x -kernel. Patch works fine for our embedded system. - -URL to the audio chip: -http://www.mikroe.com/add-on-boards/audio-voice/audio-codec-proto/ - -Playback tested with devicetree enabled. - -Signed-off-by: Waldemar Brodkorb ---- - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/rpi-proto.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 163 insertions(+) - create mode 100644 sound/soc/bcm/rpi-proto.c - ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -45,6 +45,13 @@ config SND_BCM2708_SOC_RPI_DAC - help - Say Y or M if you want to add support for RPi-DAC. - -+config SND_BCM2708_SOC_RPI_PROTO -+ tristate "Support for Rpi-PROTO" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_WM8731 -+ help -+ Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731). -+ - config SND_BCM2708_SOC_IQAUDIO_DAC - tristate "Support for IQaudIO-DAC" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -13,10 +13,12 @@ snd-soc-hifiberry-dac-objs := hifiberry_ - snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-rpi-dac-objs := rpi-dac.o -+snd-soc-rpi-proto-objs := rpi-proto.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o ---- /dev/null -+++ b/sound/soc/bcm/rpi-proto.c -@@ -0,0 +1,154 @@ -+/* -+ * ASoC driver for PROTO AudioCODEC (with a WM8731) -+ * connected to a Raspberry Pi -+ * -+ * Author: Florian Meier, -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "../codecs/wm8731.h" -+ -+static const unsigned int wm8731_rates_12288000[] = { -+ 8000, 32000, 48000, 96000, -+}; -+ -+static struct snd_pcm_hw_constraint_list wm8731_constraints_12288000 = { -+ .list = wm8731_rates_12288000, -+ .count = ARRAY_SIZE(wm8731_rates_12288000), -+}; -+ -+static int snd_rpi_proto_startup(struct snd_pcm_substream *substream) -+{ -+ /* Setup constraints, because there is a 12.288 MHz XTAL on the board */ -+ snd_pcm_hw_constraint_list(substream->runtime, 0, -+ SNDRV_PCM_HW_PARAM_RATE, -+ &wm8731_constraints_12288000); -+ return 0; -+} -+ -+static int snd_rpi_proto_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ struct snd_soc_dai *codec_dai = rtd->codec_dai; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ int sysclk = 12288000; /* This is fixed on this board */ -+ -+ /* Set proto bclk */ -+ int ret = snd_soc_dai_set_bclk_ratio(cpu_dai,32*2); -+ if (ret < 0){ -+ dev_err(codec->dev, -+ "Failed to set BCLK ratio %d\n", ret); -+ return ret; -+ } -+ -+ /* Set proto sysclk */ -+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, -+ sysclk, SND_SOC_CLOCK_IN); -+ if (ret < 0) { -+ dev_err(codec->dev, -+ "Failed to set WM8731 SYSCLK: %d\n", ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_proto_ops = { -+ .startup = snd_rpi_proto_startup, -+ .hw_params = snd_rpi_proto_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_proto_dai[] = { -+{ -+ .name = "WM8731", -+ .stream_name = "WM8731 HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "wm8731-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "wm8731.1-001a", -+ .dai_fmt = SND_SOC_DAIFMT_I2S -+ | SND_SOC_DAIFMT_NB_NF -+ | SND_SOC_DAIFMT_CBM_CFM, -+ .ops = &snd_rpi_proto_ops, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_proto = { -+ .name = "snd_rpi_proto", -+ .owner = THIS_MODULE, -+ .dai_link = snd_rpi_proto_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_proto_dai), -+}; -+ -+static int snd_rpi_proto_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_proto.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_proto_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ ret = snd_soc_register_card(&snd_rpi_proto); -+ if (ret) { -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); -+ } -+ -+ return ret; -+} -+ -+ -+static int snd_rpi_proto_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_proto); -+} -+ -+static const struct of_device_id snd_rpi_proto_of_match[] = { -+ { .compatible = "rpi,rpi-proto", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_proto_of_match); -+ -+static struct platform_driver snd_rpi_proto_driver = { -+ .driver = { -+ .name = "snd-rpi-proto", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_proto_of_match, -+ }, -+ .probe = snd_rpi_proto_probe, -+ .remove = snd_rpi_proto_remove, -+}; -+ -+module_platform_driver(snd_rpi_proto_driver); -+ -+MODULE_AUTHOR("Florian Meier"); -+MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/brcm2708/patches-4.9/0076-RaspiDAC3-support.patch b/target/linux/brcm2708/patches-4.9/0076-RaspiDAC3-support.patch new file mode 100644 index 0000000000..de68bbf6b6 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0076-RaspiDAC3-support.patch @@ -0,0 +1,238 @@ +From b545537294ffc7e21fcc5e0c78ea8ac20c9ecd3f Mon Sep 17 00:00:00 2001 +From: Jan Grulich +Date: Mon, 24 Aug 2015 16:03:47 +0100 +Subject: [PATCH] RaspiDAC3 support + +Signed-off-by: Jan Grulich + +config: fix RaspiDAC Rev.3x dependencies + +Change depends to SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +like the other I2S soundcard drivers. + +Signed-off-by: Matthias Reichl +--- + sound/soc/bcm/Kconfig | 8 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/raspidac3.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 196 insertions(+) + create mode 100644 sound/soc/bcm/raspidac3.c + +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -65,3 +65,11 @@ config SND_BCM2708_SOC_IQAUDIO_DAC + select SND_SOC_PCM512x_I2C + help + Say Y or M if you want to add support for IQaudIO-DAC. ++ ++config SND_BCM2708_SOC_RASPIDAC3 ++ tristate "Support for RaspiDAC Rev.3x" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM512x_I2C ++ select SND_SOC_TPA6130A2 ++ help ++ Say Y or M if you want to add support for RaspiDAC Rev.3x. +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -16,6 +16,7 @@ snd-soc-hifiberry-digi-objs := hifiberry + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-rpi-proto-objs := rpi-proto.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o ++snd-soc-raspidac3-objs := raspidac3.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o +@@ -24,3 +25,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o +--- /dev/null ++++ b/sound/soc/bcm/raspidac3.c +@@ -0,0 +1,186 @@ ++/* ++ * ASoC Driver for RaspiDAC v3 ++ * ++ * Author: Jan Grulich ++ * Copyright 2015 ++ * based on code by Daniel Matuschek ++ * based on code by Florian Meier ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../codecs/pcm512x.h" ++#include "../codecs/tpa6130a2.h" ++ ++/* sound card init */ ++static int snd_rpi_raspidac3_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ int ret; ++ struct snd_soc_card *card = rtd->card; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08); ++ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02); ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x00); ++ ++ 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); ++ else { ++ struct snd_kcontrol *kctl; ++ ++ ret = snd_soc_limit_volume(card, ++ "TPA6130A2 Headphone Playback Volume", ++ 54); ++ if (ret < 0) ++ dev_warn(card->dev, "Failed to set TPA6130A2 volume limit: %d\n", ++ ret); ++ kctl = snd_soc_card_get_kcontrol(card, ++ "TPA6130A2 Headphone Playback Volume"); ++ if (kctl) { ++ strcpy(kctl->id.name, "Headphones Playback Volume"); ++ /* disable the volume dB scale so alsamixer works */ ++ kctl->vd[0].access = SNDRV_CTL_ELEM_ACCESS_READWRITE; ++ } ++ ++ kctl = snd_soc_card_get_kcontrol(card, ++ "TPA6130A2 Headphone Playback Switch"); ++ if (kctl) ++ strcpy(kctl->id.name, "Headphones Playback Switch"); ++ } ++ ++ return 0; ++} ++ ++/* set hw parameters */ ++static int snd_rpi_raspidac3_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ unsigned int sample_bits = ++ snd_pcm_format_physical_width(params_format(params)); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); ++} ++ ++/* startup */ ++static int snd_rpi_raspidac3_startup(struct snd_pcm_substream *substream) { ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08); ++ return 0; ++} ++ ++/* shutdown */ ++static void snd_rpi_raspidac3_shutdown(struct snd_pcm_substream *substream) { ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x00); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_raspidac3_ops = { ++ .hw_params = snd_rpi_raspidac3_hw_params, ++ .startup = snd_rpi_raspidac3_startup, ++ .shutdown = snd_rpi_raspidac3_shutdown, ++}; ++ ++/* interface setup */ ++static struct snd_soc_dai_link snd_rpi_raspidac3_dai[] = { ++{ ++ .name = "RaspiDAC Rev.3x", ++ .stream_name = "RaspiDAC HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm512x-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm512x.1-004c", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_raspidac3_ops, ++ .init = snd_rpi_raspidac3_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_raspidac3 = { ++ .name = "RaspiDAC Rev.3x HiFi Audio Card", ++ .owner = THIS_MODULE, ++ .dai_link = snd_rpi_raspidac3_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_raspidac3_dai), ++}; ++ ++/* sound card test */ ++static int snd_rpi_raspidac3_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_raspidac3.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_raspidac3_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_raspidac3); ++ if (ret) ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++/* sound card disconnect */ ++static int snd_rpi_raspidac3_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_raspidac3); ++} ++ ++static const struct of_device_id raspidac3_of_match[] = { ++ { .compatible = "jg,raspidacv3", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, raspidac3_of_match); ++ ++/* sound card platform driver */ ++static struct platform_driver snd_rpi_raspidac3_driver = { ++ .driver = { ++ .name = "snd-rpi-raspidac3", ++ .owner = THIS_MODULE, ++ .of_match_table = raspidac3_of_match, ++ }, ++ .probe = snd_rpi_raspidac3_probe, ++ .remove = snd_rpi_raspidac3_remove, ++}; ++ ++module_platform_driver(snd_rpi_raspidac3_driver); ++ ++MODULE_AUTHOR("Jan Grulich "); ++MODULE_DESCRIPTION("ASoC Driver for RaspiDAC Rev.3x"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0077-Add-Support-for-JustBoom-Audio-boards.patch b/target/linux/brcm2708/patches-4.9/0077-Add-Support-for-JustBoom-Audio-boards.patch new file mode 100644 index 0000000000..96545872f1 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0077-Add-Support-for-JustBoom-Audio-boards.patch @@ -0,0 +1,446 @@ +From 4a8ebf575ea143c14fd815ecd1f5398b6a6aee67 Mon Sep 17 00:00:00 2001 +From: Aaron Shaw +Date: Thu, 7 Apr 2016 21:26:21 +0100 +Subject: [PATCH] Add Support for JustBoom Audio boards + +justboom-dac: Adjust for ALSA API change + +As of 4.4, snd_soc_limit_volume now takes a struct snd_soc_card * +rather than a struct snd_soc_codec *. + +Signed-off-by: Phil Elwell +--- + sound/soc/bcm/Kconfig | 14 +++ + sound/soc/bcm/Makefile | 4 + + sound/soc/bcm/justboom-dac.c | 162 +++++++++++++++++++++++++++++++ + sound/soc/bcm/justboom-digi.c | 215 ++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 395 insertions(+) + create mode 100644 sound/soc/bcm/justboom-dac.c + create mode 100644 sound/soc/bcm/justboom-digi.c + +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -59,6 +59,20 @@ 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_DAC ++ tristate "Support for JustBoom DAC" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM512x ++ help ++ Say Y or M if you want to add support for JustBoom DAC. ++ ++config SND_BCM2708_SOC_JUSTBOOM_DIGI ++ tristate "Support for JustBoom Digi" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_WM8804 ++ help ++ Say Y or M if you want to add support for JustBoom Digi. ++ + config SND_BCM2708_SOC_IQAUDIO_DAC + tristate "Support for IQaudIO-DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -13,6 +13,8 @@ snd-soc-hifiberry-amp-objs := hifiberry_ + snd-soc-hifiberry-dac-objs := hifiberry_dac.o + snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o ++snd-soc-justboom-dac-objs := justboom-dac.o ++snd-soc-justboom-digi-objs := justboom-digi.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-rpi-proto-objs := rpi-proto.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o +@@ -22,6 +24,8 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_A + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o ++obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +--- /dev/null ++++ b/sound/soc/bcm/justboom-dac.c +@@ -0,0 +1,162 @@ ++/* ++ * ASoC Driver for JustBoom DAC Raspberry Pi HAT Sound Card ++ * ++ * Author: Milan Neskovic ++ * Copyright 2016 ++ * based on code by Daniel Matuschek ++ * based on code by Florian Meier ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "../codecs/pcm512x.h" ++ ++static bool digital_gain_0db_limit = true; ++ ++static int snd_rpi_justboom_dac_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08); ++ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02); ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08); ++ ++ if (digital_gain_0db_limit) ++ { ++ int ret; ++ struct snd_soc_card *card = rtd->card; ++ ++ ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207); ++ if (ret < 0) ++ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); ++ } ++ ++ return 0; ++} ++ ++static int snd_rpi_justboom_dac_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ /*return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);*/ ++ unsigned int sample_bits = ++ snd_pcm_format_physical_width(params_format(params)); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); ++} ++ ++static int snd_rpi_justboom_dac_startup(struct snd_pcm_substream *substream) { ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08); ++ return 0; ++} ++ ++static void snd_rpi_justboom_dac_shutdown(struct snd_pcm_substream *substream) { ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x00); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_justboom_dac_ops = { ++ .hw_params = snd_rpi_justboom_dac_hw_params, ++ .startup = snd_rpi_justboom_dac_startup, ++ .shutdown = snd_rpi_justboom_dac_shutdown, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_justboom_dac_dai[] = { ++{ ++ .name = "JustBoom DAC", ++ .stream_name = "JustBoom DAC HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm512x-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm512x.1-004d", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_justboom_dac_ops, ++ .init = snd_rpi_justboom_dac_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_justboom_dac = { ++ .name = "snd_rpi_justboom_dac", ++ .owner = THIS_MODULE, ++ .dai_link = snd_rpi_justboom_dac_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_justboom_dac_dai), ++}; ++ ++static int snd_rpi_justboom_dac_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_justboom_dac.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_justboom_dac_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ ++ digital_gain_0db_limit = !of_property_read_bool( ++ pdev->dev.of_node, "justboom,24db_digital_gain"); ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_justboom_dac); ++ if (ret) ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_justboom_dac_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_justboom_dac); ++} ++ ++static const struct of_device_id snd_rpi_justboom_dac_of_match[] = { ++ { .compatible = "justboom,justboom-dac", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_justboom_dac_of_match); ++ ++static struct platform_driver snd_rpi_justboom_dac_driver = { ++ .driver = { ++ .name = "snd-rpi-justboom-dac", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_justboom_dac_of_match, ++ }, ++ .probe = snd_rpi_justboom_dac_probe, ++ .remove = snd_rpi_justboom_dac_remove, ++}; ++ ++module_platform_driver(snd_rpi_justboom_dac_driver); ++ ++MODULE_AUTHOR("Milan Neskovic "); ++MODULE_DESCRIPTION("ASoC Driver for JustBoom PI DAC HAT Sound Card"); ++MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/sound/soc/bcm/justboom-digi.c +@@ -0,0 +1,215 @@ ++/* ++ * ASoC Driver for JustBoom Raspberry Pi Digi HAT Sound Card ++ * ++ * Author: Milan Neskovic ++ * Copyright 2016 ++ * based on code by Daniel Matuschek ++ * based on code by Florian Meier ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "../codecs/wm8804.h" ++ ++static int snd_rpi_justboom_digi_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ /* enable TX output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); ++ ++ return 0; ++} ++ ++static int snd_rpi_justboom_digi_startup(struct snd_pcm_substream *substream) { ++ /* turn on digital output */ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); ++ return 0; ++} ++ ++static void snd_rpi_justboom_digi_shutdown(struct snd_pcm_substream *substream) { ++ /* turn off output */ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); ++} ++ ++static int snd_rpi_justboom_digi_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ int sysclk = 27000000; /* This is fixed on this board */ ++ ++ long mclk_freq=0; ++ int mclk_div=1; ++ int sampling_freq=1; ++ ++ int ret; ++ ++ int samplerate = params_rate(params); ++ ++ if (samplerate<=96000) { ++ mclk_freq=samplerate*256; ++ mclk_div=WM8804_MCLKDIV_256FS; ++ } else { ++ mclk_freq=samplerate*128; ++ mclk_div=WM8804_MCLKDIV_128FS; ++ } ++ ++ switch (samplerate) { ++ case 32000: ++ sampling_freq=0x03; ++ break; ++ case 44100: ++ sampling_freq=0x00; ++ break; ++ case 48000: ++ sampling_freq=0x02; ++ break; ++ case 88200: ++ sampling_freq=0x08; ++ break; ++ case 96000: ++ sampling_freq=0x0a; ++ break; ++ case 176400: ++ sampling_freq=0x0c; ++ break; ++ case 192000: ++ sampling_freq=0x0e; ++ break; ++ default: ++ dev_err(codec->dev, ++ "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", ++ samplerate); ++ } ++ ++ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); ++ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); ++ ++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, ++ sysclk, SND_SOC_CLOCK_OUT); ++ if (ret < 0) { ++ dev_err(codec->dev, ++ "Failed to set WM8804 SYSCLK: %d\n", ret); ++ return ret; ++ } ++ ++ /* Enable TX output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); ++ ++ /* Power on */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0); ++ ++ /* set sampling frequency status bits */ ++ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai,64); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_justboom_digi_ops = { ++ .hw_params = snd_rpi_justboom_digi_hw_params, ++ .startup = snd_rpi_justboom_digi_startup, ++ .shutdown = snd_rpi_justboom_digi_shutdown, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_justboom_digi_dai[] = { ++{ ++ .name = "JustBoom Digi", ++ .stream_name = "JustBoom Digi HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "wm8804-spdif", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "wm8804.1-003b", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &snd_rpi_justboom_digi_ops, ++ .init = snd_rpi_justboom_digi_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_justboom_digi = { ++ .name = "snd_rpi_justboom_digi", ++ .owner = THIS_MODULE, ++ .dai_link = snd_rpi_justboom_digi_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_justboom_digi_dai), ++}; ++ ++static int snd_rpi_justboom_digi_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_justboom_digi.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_justboom_digi_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_justboom_digi); ++ if (ret) ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_justboom_digi_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_justboom_digi); ++} ++ ++static const struct of_device_id snd_rpi_justboom_digi_of_match[] = { ++ { .compatible = "justboom,justboom-digi", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_justboom_digi_of_match); ++ ++static struct platform_driver snd_rpi_justboom_digi_driver = { ++ .driver = { ++ .name = "snd-rpi-justboom-digi", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_justboom_digi_of_match, ++ }, ++ .probe = snd_rpi_justboom_digi_probe, ++ .remove = snd_rpi_justboom_digi_remove, ++}; ++ ++module_platform_driver(snd_rpi_justboom_digi_driver); ++ ++MODULE_AUTHOR("Milan Neskovic "); ++MODULE_DESCRIPTION("ASoC Driver for JustBoom PI Digi HAT Sound Card"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0077-RaspiDAC3-support.patch b/target/linux/brcm2708/patches-4.9/0077-RaspiDAC3-support.patch deleted file mode 100644 index 32bc86af9b..0000000000 --- a/target/linux/brcm2708/patches-4.9/0077-RaspiDAC3-support.patch +++ /dev/null @@ -1,238 +0,0 @@ -From 26084a968083e88298416426576dbd4c006e5dea Mon Sep 17 00:00:00 2001 -From: Jan Grulich -Date: Mon, 24 Aug 2015 16:03:47 +0100 -Subject: [PATCH] RaspiDAC3 support - -Signed-off-by: Jan Grulich - -config: fix RaspiDAC Rev.3x dependencies - -Change depends to SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -like the other I2S soundcard drivers. - -Signed-off-by: Matthias Reichl ---- - sound/soc/bcm/Kconfig | 8 ++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/raspidac3.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 196 insertions(+) - create mode 100644 sound/soc/bcm/raspidac3.c - ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -58,3 +58,11 @@ config SND_BCM2708_SOC_IQAUDIO_DAC - select SND_SOC_PCM512x_I2C - help - Say Y or M if you want to add support for IQaudIO-DAC. -+ -+config SND_BCM2708_SOC_RASPIDAC3 -+ tristate "Support for RaspiDAC Rev.3x" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_PCM512x_I2C -+ select SND_SOC_TPA6130A2 -+ help -+ Say Y or M if you want to add support for RaspiDAC Rev.3x. ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -15,6 +15,7 @@ snd-soc-hifiberry-digi-objs := hifiberry - snd-soc-rpi-dac-objs := rpi-dac.o - snd-soc-rpi-proto-objs := rpi-proto.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o -+snd-soc-raspidac3-objs := raspidac3.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o -@@ -22,3 +23,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o ---- /dev/null -+++ b/sound/soc/bcm/raspidac3.c -@@ -0,0 +1,186 @@ -+/* -+ * ASoC Driver for RaspiDAC v3 -+ * -+ * Author: Jan Grulich -+ * Copyright 2015 -+ * based on code by Daniel Matuschek -+ * based on code by Florian Meier -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "../codecs/pcm512x.h" -+#include "../codecs/tpa6130a2.h" -+ -+/* sound card init */ -+static int snd_rpi_raspidac3_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ int ret; -+ struct snd_soc_card *card = rtd->card; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08); -+ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02); -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x00); -+ -+ 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); -+ else { -+ struct snd_kcontrol *kctl; -+ -+ ret = snd_soc_limit_volume(card, -+ "TPA6130A2 Headphone Playback Volume", -+ 54); -+ if (ret < 0) -+ dev_warn(card->dev, "Failed to set TPA6130A2 volume limit: %d\n", -+ ret); -+ kctl = snd_soc_card_get_kcontrol(card, -+ "TPA6130A2 Headphone Playback Volume"); -+ if (kctl) { -+ strcpy(kctl->id.name, "Headphones Playback Volume"); -+ /* disable the volume dB scale so alsamixer works */ -+ kctl->vd[0].access = SNDRV_CTL_ELEM_ACCESS_READWRITE; -+ } -+ -+ kctl = snd_soc_card_get_kcontrol(card, -+ "TPA6130A2 Headphone Playback Switch"); -+ if (kctl) -+ strcpy(kctl->id.name, "Headphones Playback Switch"); -+ } -+ -+ return 0; -+} -+ -+/* set hw parameters */ -+static int snd_rpi_raspidac3_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ unsigned int sample_bits = -+ snd_pcm_format_physical_width(params_format(params)); -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); -+} -+ -+/* startup */ -+static int snd_rpi_raspidac3_startup(struct snd_pcm_substream *substream) { -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08); -+ return 0; -+} -+ -+/* shutdown */ -+static void snd_rpi_raspidac3_shutdown(struct snd_pcm_substream *substream) { -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x00); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_raspidac3_ops = { -+ .hw_params = snd_rpi_raspidac3_hw_params, -+ .startup = snd_rpi_raspidac3_startup, -+ .shutdown = snd_rpi_raspidac3_shutdown, -+}; -+ -+/* interface setup */ -+static struct snd_soc_dai_link snd_rpi_raspidac3_dai[] = { -+{ -+ .name = "RaspiDAC Rev.3x", -+ .stream_name = "RaspiDAC HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm512x-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm512x.1-004c", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_raspidac3_ops, -+ .init = snd_rpi_raspidac3_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_raspidac3 = { -+ .name = "RaspiDAC Rev.3x HiFi Audio Card", -+ .owner = THIS_MODULE, -+ .dai_link = snd_rpi_raspidac3_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_raspidac3_dai), -+}; -+ -+/* sound card test */ -+static int snd_rpi_raspidac3_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_raspidac3.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_raspidac3_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ ret = snd_soc_register_card(&snd_rpi_raspidac3); -+ if (ret) -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+/* sound card disconnect */ -+static int snd_rpi_raspidac3_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_raspidac3); -+} -+ -+static const struct of_device_id raspidac3_of_match[] = { -+ { .compatible = "jg,raspidacv3", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, raspidac3_of_match); -+ -+/* sound card platform driver */ -+static struct platform_driver snd_rpi_raspidac3_driver = { -+ .driver = { -+ .name = "snd-rpi-raspidac3", -+ .owner = THIS_MODULE, -+ .of_match_table = raspidac3_of_match, -+ }, -+ .probe = snd_rpi_raspidac3_probe, -+ .remove = snd_rpi_raspidac3_remove, -+}; -+ -+module_platform_driver(snd_rpi_raspidac3_driver); -+ -+MODULE_AUTHOR("Jan Grulich "); -+MODULE_DESCRIPTION("ASoC Driver for RaspiDAC Rev.3x"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0078-ARM-adau1977-adc-Add-basic-machine-driver-for-adau19.patch b/target/linux/brcm2708/patches-4.9/0078-ARM-adau1977-adc-Add-basic-machine-driver-for-adau19.patch new file mode 100644 index 0000000000..1b87b13efd --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0078-ARM-adau1977-adc-Add-basic-machine-driver-for-adau19.patch @@ -0,0 +1,177 @@ +From 9bbd8a3c8378eac9e605e0f37f4005583e122527 Mon Sep 17 00:00:00 2001 +From: Andrey Grodzovsky +Date: Tue, 3 May 2016 22:10:59 -0400 +Subject: [PATCH] ARM: adau1977-adc: Add basic machine driver for adau1977 + codec driver. + +This commit adds basic support for the codec usage including: Device tree overlay, +binding I2S bus and setting I2S mode, clock source and frequency setting according +to spec. + +Signed-off-by: Andrey Grodzovsky +--- + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/adau1977-adc.c | 125 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 134 insertions(+) + create mode 100644 sound/soc/bcm/adau1977-adc.c + +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -87,3 +87,10 @@ config SND_BCM2708_SOC_RASPIDAC3 + select SND_SOC_TPA6130A2 + help + Say Y or M if you want to add support for RaspiDAC Rev.3x. ++ ++config SND_BCM2708_SOC_ADAU1977_ADC ++ tristate "Support for ADAU1977 ADC" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_ADAU1977_I2C ++ help ++ Say Y or M if you want to add support for ADAU1977 ADC. +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -9,6 +9,7 @@ snd-soc-cygnus-objs := cygnus-pcm.o cygn + obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-cygnus.o + + # BCM2708 Machine Support ++snd-soc-adau1977-adc-objs := adau1977-adc.o + snd-soc-hifiberry-amp-objs := hifiberry_amp.o + snd-soc-hifiberry-dac-objs := hifiberry_dac.o + snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o +@@ -20,6 +21,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o + snd-soc-raspidac3-objs := raspidac3.o + ++obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o +--- /dev/null ++++ b/sound/soc/bcm/adau1977-adc.c +@@ -0,0 +1,125 @@ ++/* ++ * ASoC Driver for ADAU1977 ADC ++ * ++ * Author: Andrey Grodzovsky ++ * Copyright 2016 ++ * ++ * This file is based on hifibery_dac driver by Florian Meier. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++enum adau1977_clk_id { ++ ADAU1977_SYSCLK, ++}; ++ ++enum adau1977_sysclk_src { ++ ADAU1977_SYSCLK_SRC_MCLK, ++ ADAU1977_SYSCLK_SRC_LRCLK, ++}; ++ ++static int eval_adau1977_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ int ret; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ ++ ret = snd_soc_dai_set_tdm_slot(codec_dai, 0, 0, 0, 0); ++ if (ret < 0) ++ return ret; ++ ++ return snd_soc_codec_set_sysclk(rtd->codec, ADAU1977_SYSCLK, ++ ADAU1977_SYSCLK_SRC_MCLK, 11289600, SND_SOC_CLOCK_IN); ++} ++ ++static struct snd_soc_dai_link snd_rpi_adau1977_dai[] = { ++ { ++ .name = "adau1977", ++ .stream_name = "ADAU1977", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "adau1977-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "adau1977.1-0011", ++ .init = eval_adau1977_init, ++ .dai_fmt = SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM, ++ }, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_adau1977_adc = { ++ .name = "snd_rpi_adau1977_adc", ++ .owner = THIS_MODULE, ++ .dai_link = snd_rpi_adau1977_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_adau1977_dai), ++}; ++ ++static int snd_adau1977_adc_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_adau1977_adc.dev = &pdev->dev; ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_adau1977_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ ret = snd_soc_register_card(&snd_adau1977_adc); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_adau1977_adc_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_adau1977_adc); ++} ++ ++static const struct of_device_id snd_adau1977_adc_of_match[] = { ++ { .compatible = "adi,adau1977-adc", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, snd_adau1977_adc_of_match); ++ ++static struct platform_driver snd_adau1977_adc_driver = { ++ .driver = { ++ .name = "snd-adau1977-adc", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_adau1977_adc_of_match, ++ }, ++ .probe = snd_adau1977_adc_probe, ++ .remove = snd_adau1977_adc_remove, ++}; ++ ++module_platform_driver(snd_adau1977_adc_driver); ++ ++MODULE_AUTHOR("Andrey Grodzovsky "); ++MODULE_DESCRIPTION("ASoC Driver for ADAU1977 ADC"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0078-Add-Support-for-JustBoom-Audio-boards.patch b/target/linux/brcm2708/patches-4.9/0078-Add-Support-for-JustBoom-Audio-boards.patch deleted file mode 100644 index 95bf9a53c2..0000000000 --- a/target/linux/brcm2708/patches-4.9/0078-Add-Support-for-JustBoom-Audio-boards.patch +++ /dev/null @@ -1,446 +0,0 @@ -From 16e3f935b10cbd118056806ebd3afe6eed4c0183 Mon Sep 17 00:00:00 2001 -From: Aaron Shaw -Date: Thu, 7 Apr 2016 21:26:21 +0100 -Subject: [PATCH] Add Support for JustBoom Audio boards - -justboom-dac: Adjust for ALSA API change - -As of 4.4, snd_soc_limit_volume now takes a struct snd_soc_card * -rather than a struct snd_soc_codec *. - -Signed-off-by: Phil Elwell ---- - sound/soc/bcm/Kconfig | 14 +++ - sound/soc/bcm/Makefile | 4 + - sound/soc/bcm/justboom-dac.c | 162 +++++++++++++++++++++++++++++++ - sound/soc/bcm/justboom-digi.c | 215 ++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 395 insertions(+) - create mode 100644 sound/soc/bcm/justboom-dac.c - create mode 100644 sound/soc/bcm/justboom-digi.c - ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -52,6 +52,20 @@ 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_DAC -+ tristate "Support for JustBoom DAC" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_PCM512x -+ help -+ Say Y or M if you want to add support for JustBoom DAC. -+ -+config SND_BCM2708_SOC_JUSTBOOM_DIGI -+ tristate "Support for JustBoom Digi" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_WM8804 -+ help -+ Say Y or M if you want to add support for JustBoom Digi. -+ - config SND_BCM2708_SOC_IQAUDIO_DAC - tristate "Support for IQaudIO-DAC" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -12,6 +12,8 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc- - snd-soc-hifiberry-dac-objs := hifiberry_dac.o - snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o -+snd-soc-justboom-dac-objs := justboom-dac.o -+snd-soc-justboom-digi-objs := justboom-digi.o - snd-soc-rpi-dac-objs := rpi-dac.o - snd-soc-rpi-proto-objs := rpi-proto.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o -@@ -20,6 +22,8 @@ snd-soc-raspidac3-objs := raspidac3.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o -+obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o ---- /dev/null -+++ b/sound/soc/bcm/justboom-dac.c -@@ -0,0 +1,162 @@ -+/* -+ * ASoC Driver for JustBoom DAC Raspberry Pi HAT Sound Card -+ * -+ * Author: Milan Neskovic -+ * Copyright 2016 -+ * based on code by Daniel Matuschek -+ * based on code by Florian Meier -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "../codecs/pcm512x.h" -+ -+static bool digital_gain_0db_limit = true; -+ -+static int snd_rpi_justboom_dac_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08); -+ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02); -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08); -+ -+ if (digital_gain_0db_limit) -+ { -+ int ret; -+ struct snd_soc_card *card = rtd->card; -+ -+ ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207); -+ if (ret < 0) -+ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); -+ } -+ -+ return 0; -+} -+ -+static int snd_rpi_justboom_dac_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ /*return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);*/ -+ unsigned int sample_bits = -+ snd_pcm_format_physical_width(params_format(params)); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); -+} -+ -+static int snd_rpi_justboom_dac_startup(struct snd_pcm_substream *substream) { -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08); -+ return 0; -+} -+ -+static void snd_rpi_justboom_dac_shutdown(struct snd_pcm_substream *substream) { -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x00); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_justboom_dac_ops = { -+ .hw_params = snd_rpi_justboom_dac_hw_params, -+ .startup = snd_rpi_justboom_dac_startup, -+ .shutdown = snd_rpi_justboom_dac_shutdown, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_justboom_dac_dai[] = { -+{ -+ .name = "JustBoom DAC", -+ .stream_name = "JustBoom DAC HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm512x-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm512x.1-004d", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_justboom_dac_ops, -+ .init = snd_rpi_justboom_dac_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_justboom_dac = { -+ .name = "snd_rpi_justboom_dac", -+ .owner = THIS_MODULE, -+ .dai_link = snd_rpi_justboom_dac_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_justboom_dac_dai), -+}; -+ -+static int snd_rpi_justboom_dac_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_justboom_dac.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_justboom_dac_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ -+ digital_gain_0db_limit = !of_property_read_bool( -+ pdev->dev.of_node, "justboom,24db_digital_gain"); -+ } -+ -+ ret = snd_soc_register_card(&snd_rpi_justboom_dac); -+ if (ret) -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_justboom_dac_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_justboom_dac); -+} -+ -+static const struct of_device_id snd_rpi_justboom_dac_of_match[] = { -+ { .compatible = "justboom,justboom-dac", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_justboom_dac_of_match); -+ -+static struct platform_driver snd_rpi_justboom_dac_driver = { -+ .driver = { -+ .name = "snd-rpi-justboom-dac", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_justboom_dac_of_match, -+ }, -+ .probe = snd_rpi_justboom_dac_probe, -+ .remove = snd_rpi_justboom_dac_remove, -+}; -+ -+module_platform_driver(snd_rpi_justboom_dac_driver); -+ -+MODULE_AUTHOR("Milan Neskovic "); -+MODULE_DESCRIPTION("ASoC Driver for JustBoom PI DAC HAT Sound Card"); -+MODULE_LICENSE("GPL v2"); ---- /dev/null -+++ b/sound/soc/bcm/justboom-digi.c -@@ -0,0 +1,215 @@ -+/* -+ * ASoC Driver for JustBoom Raspberry Pi Digi HAT Sound Card -+ * -+ * Author: Milan Neskovic -+ * Copyright 2016 -+ * based on code by Daniel Matuschek -+ * based on code by Florian Meier -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "../codecs/wm8804.h" -+ -+static int snd_rpi_justboom_digi_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ /* enable TX output */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); -+ -+ return 0; -+} -+ -+static int snd_rpi_justboom_digi_startup(struct snd_pcm_substream *substream) { -+ /* turn on digital output */ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); -+ return 0; -+} -+ -+static void snd_rpi_justboom_digi_shutdown(struct snd_pcm_substream *substream) { -+ /* turn off output */ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); -+} -+ -+static int snd_rpi_justboom_digi_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *codec_dai = rtd->codec_dai; -+ struct snd_soc_codec *codec = rtd->codec; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ int sysclk = 27000000; /* This is fixed on this board */ -+ -+ long mclk_freq=0; -+ int mclk_div=1; -+ int sampling_freq=1; -+ -+ int ret; -+ -+ int samplerate = params_rate(params); -+ -+ if (samplerate<=96000) { -+ mclk_freq=samplerate*256; -+ mclk_div=WM8804_MCLKDIV_256FS; -+ } else { -+ mclk_freq=samplerate*128; -+ mclk_div=WM8804_MCLKDIV_128FS; -+ } -+ -+ switch (samplerate) { -+ case 32000: -+ sampling_freq=0x03; -+ break; -+ case 44100: -+ sampling_freq=0x00; -+ break; -+ case 48000: -+ sampling_freq=0x02; -+ break; -+ case 88200: -+ sampling_freq=0x08; -+ break; -+ case 96000: -+ sampling_freq=0x0a; -+ break; -+ case 176400: -+ sampling_freq=0x0c; -+ break; -+ case 192000: -+ sampling_freq=0x0e; -+ break; -+ default: -+ dev_err(codec->dev, -+ "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", -+ samplerate); -+ } -+ -+ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); -+ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); -+ -+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, -+ sysclk, SND_SOC_CLOCK_OUT); -+ if (ret < 0) { -+ dev_err(codec->dev, -+ "Failed to set WM8804 SYSCLK: %d\n", ret); -+ return ret; -+ } -+ -+ /* Enable TX output */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); -+ -+ /* Power on */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0); -+ -+ /* set sampling frequency status bits */ -+ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai,64); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_justboom_digi_ops = { -+ .hw_params = snd_rpi_justboom_digi_hw_params, -+ .startup = snd_rpi_justboom_digi_startup, -+ .shutdown = snd_rpi_justboom_digi_shutdown, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_justboom_digi_dai[] = { -+{ -+ .name = "JustBoom Digi", -+ .stream_name = "JustBoom Digi HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "wm8804-spdif", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "wm8804.1-003b", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBM_CFM, -+ .ops = &snd_rpi_justboom_digi_ops, -+ .init = snd_rpi_justboom_digi_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_justboom_digi = { -+ .name = "snd_rpi_justboom_digi", -+ .owner = THIS_MODULE, -+ .dai_link = snd_rpi_justboom_digi_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_justboom_digi_dai), -+}; -+ -+static int snd_rpi_justboom_digi_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_justboom_digi.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_justboom_digi_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ ret = snd_soc_register_card(&snd_rpi_justboom_digi); -+ if (ret) -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_justboom_digi_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_justboom_digi); -+} -+ -+static const struct of_device_id snd_rpi_justboom_digi_of_match[] = { -+ { .compatible = "justboom,justboom-digi", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_justboom_digi_of_match); -+ -+static struct platform_driver snd_rpi_justboom_digi_driver = { -+ .driver = { -+ .name = "snd-rpi-justboom-digi", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_justboom_digi_of_match, -+ }, -+ .probe = snd_rpi_justboom_digi_probe, -+ .remove = snd_rpi_justboom_digi_remove, -+}; -+ -+module_platform_driver(snd_rpi_justboom_digi_driver); -+ -+MODULE_AUTHOR("Milan Neskovic "); -+MODULE_DESCRIPTION("ASoC Driver for JustBoom PI Digi HAT Sound Card"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0079-ARM-adau1977-adc-Add-basic-machine-driver-for-adau19.patch b/target/linux/brcm2708/patches-4.9/0079-ARM-adau1977-adc-Add-basic-machine-driver-for-adau19.patch deleted file mode 100644 index 54d659f015..0000000000 --- a/target/linux/brcm2708/patches-4.9/0079-ARM-adau1977-adc-Add-basic-machine-driver-for-adau19.patch +++ /dev/null @@ -1,177 +0,0 @@ -From 55bbfc45096c8046134a2062acb2dd0806f48250 Mon Sep 17 00:00:00 2001 -From: Andrey Grodzovsky -Date: Tue, 3 May 2016 22:10:59 -0400 -Subject: [PATCH] ARM: adau1977-adc: Add basic machine driver for adau1977 - codec driver. - -This commit adds basic support for the codec usage including: Device tree overlay, -binding I2S bus and setting I2S mode, clock source and frequency setting according -to spec. - -Signed-off-by: Andrey Grodzovsky ---- - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/adau1977-adc.c | 125 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 134 insertions(+) - create mode 100644 sound/soc/bcm/adau1977-adc.c - ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -80,3 +80,10 @@ config SND_BCM2708_SOC_RASPIDAC3 - select SND_SOC_TPA6130A2 - help - Say Y or M if you want to add support for RaspiDAC Rev.3x. -+ -+config SND_BCM2708_SOC_ADAU1977_ADC -+ tristate "Support for ADAU1977 ADC" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_ADAU1977_I2C -+ help -+ Say Y or M if you want to add support for ADAU1977 ADC. ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -9,6 +9,7 @@ snd-soc-cygnus-objs := cygnus-pcm.o cygn - obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-cygnus.o - - # BCM2708 Machine Support -+snd-soc-adau1977-adc-objs := adau1977-adc.o - snd-soc-hifiberry-dac-objs := hifiberry_dac.o - snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o -@@ -19,6 +20,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o - snd-soc-raspidac3-objs := raspidac3.o - -+obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o ---- /dev/null -+++ b/sound/soc/bcm/adau1977-adc.c -@@ -0,0 +1,125 @@ -+/* -+ * ASoC Driver for ADAU1977 ADC -+ * -+ * Author: Andrey Grodzovsky -+ * Copyright 2016 -+ * -+ * This file is based on hifibery_dac driver by Florian Meier. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+enum adau1977_clk_id { -+ ADAU1977_SYSCLK, -+}; -+ -+enum adau1977_sysclk_src { -+ ADAU1977_SYSCLK_SRC_MCLK, -+ ADAU1977_SYSCLK_SRC_LRCLK, -+}; -+ -+static int eval_adau1977_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ int ret; -+ struct snd_soc_dai *codec_dai = rtd->codec_dai; -+ -+ ret = snd_soc_dai_set_tdm_slot(codec_dai, 0, 0, 0, 0); -+ if (ret < 0) -+ return ret; -+ -+ return snd_soc_codec_set_sysclk(rtd->codec, ADAU1977_SYSCLK, -+ ADAU1977_SYSCLK_SRC_MCLK, 11289600, SND_SOC_CLOCK_IN); -+} -+ -+static struct snd_soc_dai_link snd_rpi_adau1977_dai[] = { -+ { -+ .name = "adau1977", -+ .stream_name = "ADAU1977", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "adau1977-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "adau1977.1-0011", -+ .init = eval_adau1977_init, -+ .dai_fmt = SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBM_CFM, -+ }, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_adau1977_adc = { -+ .name = "snd_rpi_adau1977_adc", -+ .owner = THIS_MODULE, -+ .dai_link = snd_rpi_adau1977_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_adau1977_dai), -+}; -+ -+static int snd_adau1977_adc_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_adau1977_adc.dev = &pdev->dev; -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_adau1977_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ ret = snd_soc_register_card(&snd_adau1977_adc); -+ if (ret) -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_adau1977_adc_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_adau1977_adc); -+} -+ -+static const struct of_device_id snd_adau1977_adc_of_match[] = { -+ { .compatible = "adi,adau1977-adc", }, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(of, snd_adau1977_adc_of_match); -+ -+static struct platform_driver snd_adau1977_adc_driver = { -+ .driver = { -+ .name = "snd-adau1977-adc", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_adau1977_adc_of_match, -+ }, -+ .probe = snd_adau1977_adc_probe, -+ .remove = snd_adau1977_adc_remove, -+}; -+ -+module_platform_driver(snd_adau1977_adc_driver); -+ -+MODULE_AUTHOR("Andrey Grodzovsky "); -+MODULE_DESCRIPTION("ASoC Driver for ADAU1977 ADC"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0079-New-AudioInjector.net-Pi-soundcard-with-low-jitter-a.patch b/target/linux/brcm2708/patches-4.9/0079-New-AudioInjector.net-Pi-soundcard-with-low-jitter-a.patch new file mode 100644 index 0000000000..71d4fef697 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0079-New-AudioInjector.net-Pi-soundcard-with-low-jitter-a.patch @@ -0,0 +1,246 @@ +From 235989cb582a29be0bea6a7e306f7b839789053c Mon Sep 17 00:00:00 2001 +From: Matt Flax +Date: Mon, 16 May 2016 21:36:31 +1000 +Subject: [PATCH] New AudioInjector.net Pi soundcard with low jitter audio in + and out. + +Contains the sound/soc/bcm ALSA machine driver and necessary alterations to the Kconfig and Makefile. +Adds the dts overlay and updates the Makefile and README. +Updates the relevant defconfig files to enable building for the Raspberry Pi. +Thanks to Phil Elwell (pelwell) for the review, simple-card concepts and discussion. Thanks to Clive Messer for overlay naming suggestions. + +Added support for headphones, microphone and bclk_ratio settings. + +This patch adds headphone and microphone capability to the Audio Injector sound card. The patch also sets the bit clock ratio for use in the bcm2835-i2s driver. The bcm2835-i2s can't handle an 8 kHz sample rate when the bit clock is at 12 MHz because its register is only 10 bits wide which can't represent the ch2 offset of 1508. For that reason, the rate constraint is added. +--- + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 3 + + sound/soc/bcm/audioinjector-pi-soundcard.c | 193 +++++++++++++++++++++++++++++ + 3 files changed, 203 insertions(+) + create mode 100644 sound/soc/bcm/audioinjector-pi-soundcard.c + +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -94,3 +94,10 @@ config SND_BCM2708_SOC_ADAU1977_ADC + select SND_SOC_ADAU1977_I2C + help + Say Y or M if you want to add support for ADAU1977 ADC. ++ ++config SND_AUDIOINJECTOR_PI_SOUNDCARD ++ tristate "Support for audioinjector.net Pi add on soundcard" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_WM8731 ++ help ++ Say Y or M if you want to add support for audioinjector.net Pi Hat +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -20,6 +20,7 @@ snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-rpi-proto-objs := rpi-proto.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o + snd-soc-raspidac3-objs := raspidac3.o ++snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o + + obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o +@@ -32,3 +33,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += + obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o ++obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o ++ +--- /dev/null ++++ b/sound/soc/bcm/audioinjector-pi-soundcard.c +@@ -0,0 +1,193 @@ ++/* ++ * ASoC Driver for AudioInjector Pi add on soundcard ++ * ++ * Created on: 13-May-2016 ++ * Author: flatmax@flatmax.org ++ * based on code by Cliff Cai for the ssm2602 machine blackfin. ++ * with help from Lars-Peter Clausen for simplifying the original code to use the dai_fmt field. ++ * i2s_node code taken from the other sound/soc/bcm machine drivers. ++ * ++ * Copyright (C) 2016 Flatmax Pty. Ltd. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "../codecs/wm8731.h" ++ ++static const unsigned int bcm2835_rates_12000000[] = { ++ 8000, 16000, 32000, 44100, 48000, 96000, 88200, ++}; ++ ++static struct snd_pcm_hw_constraint_list bcm2835_constraints_12000000 = { ++ .list = bcm2835_rates_12000000, ++ .count = ARRAY_SIZE(bcm2835_rates_12000000), ++}; ++ ++static int snd_audioinjector_pi_soundcard_startup(struct snd_pcm_substream *substream) ++{ ++ /* Setup constraints, because there is a 12 MHz XTAL on the board */ ++ snd_pcm_hw_constraint_list(substream->runtime, 0, ++ SNDRV_PCM_HW_PARAM_RATE, ++ &bcm2835_constraints_12000000); ++ return 0; ++} ++ ++static int snd_audioinjector_pi_soundcard_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ switch (params_rate(params)){ ++ case 8000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 1); ++ case 16000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 750); ++ case 32000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 375); ++ case 44100: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 272); ++ case 48000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 250); ++ case 88200: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 136); ++ case 96000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 125); ++ default: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 125); ++ } ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_audioinjector_pi_soundcard_ops = { ++ .startup = snd_audioinjector_pi_soundcard_startup, ++ .hw_params = snd_audioinjector_pi_soundcard_hw_params, ++}; ++ ++static int audioinjector_pi_soundcard_dai_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ return snd_soc_dai_set_sysclk(rtd->codec_dai, WM8731_SYSCLK_XTAL, 12000000, SND_SOC_CLOCK_IN); ++} ++ ++static struct snd_soc_dai_link audioinjector_pi_soundcard_dai[] = { ++ { ++ .name = "AudioInjector audio", ++ .stream_name = "AudioInjector audio", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "wm8731-hifi", ++ .platform_name = "bcm2835-i2s.0", ++ .codec_name = "wm8731.1-001a", ++ .ops = &snd_audioinjector_pi_soundcard_ops, ++ .init = audioinjector_pi_soundcard_dai_init, ++ .dai_fmt = SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF, ++ }, ++}; ++ ++static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { ++ SND_SOC_DAPM_HP("Headphone Jack", NULL), ++ SND_SOC_DAPM_SPK("Ext Spk", NULL), ++ SND_SOC_DAPM_LINE("Line In Jacks", NULL), ++ SND_SOC_DAPM_MIC("Microphone", NULL), ++}; ++ ++static const struct snd_soc_dapm_route audioinjector_audio_map[] = { ++ /* headphone connected to LHPOUT, RHPOUT */ ++ {"Headphone Jack", NULL, "LHPOUT"}, ++ {"Headphone Jack", NULL, "RHPOUT"}, ++ ++ /* speaker connected to LOUT, ROUT */ ++ {"Ext Spk", NULL, "ROUT"}, ++ {"Ext Spk", NULL, "LOUT"}, ++ ++ /* line inputs */ ++ {"Line In Jacks", NULL, "Line Input"}, ++ ++ /* mic is connected to Mic Jack, with WM8731 Mic Bias */ ++ {"Microphone", NULL, "Mic Bias"}, ++}; ++ ++static struct snd_soc_card snd_soc_audioinjector = { ++ .name = "audioinjector-pi-soundcard", ++ .dai_link = audioinjector_pi_soundcard_dai, ++ .num_links = ARRAY_SIZE(audioinjector_pi_soundcard_dai), ++ ++ .dapm_widgets = wm8731_dapm_widgets, ++ .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), ++ .dapm_routes = audioinjector_audio_map, ++ .num_dapm_routes = ARRAY_SIZE(audioinjector_audio_map), ++}; ++ ++static int audioinjector_pi_soundcard_probe(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = &snd_soc_audioinjector; ++ int ret; ++ ++ card->dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct snd_soc_dai_link *dai = &audioinjector_pi_soundcard_dai[0]; ++ struct device_node *i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } else ++ if (!dai->cpu_of_node) { ++ dev_err(&pdev->dev, "Property 'i2s-controller' missing or invalid\n"); ++ return -EINVAL; ++ } ++ } ++ ++ if ((ret = snd_soc_register_card(card))) { ++ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); ++ } ++ return ret; ++} ++ ++static int audioinjector_pi_soundcard_remove(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = platform_get_drvdata(pdev); ++ return snd_soc_unregister_card(card); ++ ++} ++ ++static const struct of_device_id audioinjector_pi_soundcard_of_match[] = { ++ { .compatible = "ai,audioinjector-pi-soundcard", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, audioinjector_pi_soundcard_of_match); ++ ++static struct platform_driver audioinjector_pi_soundcard_driver = { ++ .driver = { ++ .name = "audioinjector-audio", ++ .owner = THIS_MODULE, ++ .of_match_table = audioinjector_pi_soundcard_of_match, ++ }, ++ .probe = audioinjector_pi_soundcard_probe, ++ .remove = audioinjector_pi_soundcard_remove, ++}; ++ ++module_platform_driver(audioinjector_pi_soundcard_driver); ++MODULE_AUTHOR("Matt Flax "); ++MODULE_DESCRIPTION("AudioInjector.net Pi Soundcard"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:audioinjector-pi-soundcard"); ++ diff --git a/target/linux/brcm2708/patches-4.9/0080-Add-IQAudIO-Digi-WM8804-board-support.patch b/target/linux/brcm2708/patches-4.9/0080-Add-IQAudIO-Digi-WM8804-board-support.patch new file mode 100644 index 0000000000..f6a23f91f4 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0080-Add-IQAudIO-Digi-WM8804-board-support.patch @@ -0,0 +1,295 @@ +From 5d70e6012f390d6292ea8017cebb947a003fce00 Mon Sep 17 00:00:00 2001 +From: DigitalDreamtime +Date: Thu, 30 Jun 2016 18:38:42 +0100 +Subject: [PATCH] Add IQAudIO Digi WM8804 board support + +Support IQAudIO Digi board with iqaudio_digi machine driver and + iqaudio-digi-wm8804-audio overlay. + +NB. Machine driver is a cut and paste of hifiberry_digi code, with format + and general cleanup to comply with kernel coding standards. + +Signed-off-by: DigitalDreamtime +--- + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/iqaudio_digi.c | 239 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 248 insertions(+) + create mode 100644 sound/soc/bcm/iqaudio_digi.c + +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -80,6 +80,13 @@ config SND_BCM2708_SOC_IQAUDIO_DAC + help + Say Y or M if you want to add support for IQaudIO-DAC. + ++config SND_BCM2708_SOC_IQAUDIO_DIGI ++ tristate "Support for IQAudIO Digi" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_WM8804 ++ help ++ Say Y or M if you want to add support for IQAudIO Digital IO board. ++ + config SND_BCM2708_SOC_RASPIDAC3 + tristate "Support for RaspiDAC Rev.3x" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -19,6 +19,7 @@ snd-soc-justboom-digi-objs := justboom-d + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-rpi-proto-objs := rpi-proto.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o ++snd-soc-iqaudio-digi-objs := iqaudio_digi.o + snd-soc-raspidac3-objs := raspidac3.o + snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o + +@@ -32,6 +33,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DI + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o + obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o + +--- /dev/null ++++ b/sound/soc/bcm/iqaudio_digi.c +@@ -0,0 +1,239 @@ ++/* ++ * ASoC Driver for IQAudIO WM8804 Digi ++ * ++ * Author: Daniel Matuschek ++ * based on the HifiBerry DAC driver by Florian Meier ++ * Copyright 2013 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "../codecs/wm8804.h" ++ ++static short int auto_shutdown_output; ++module_param(auto_shutdown_output, short, ++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); ++MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); ++ ++static int snd_rpi_iqaudio_digi_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ /* enable TX output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); ++ ++ return 0; ++} ++ ++static int snd_rpi_iqaudio_digi_startup(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ /* turn on digital output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); ++ ++ return 0; ++} ++ ++static void snd_rpi_iqaudio_digi_shutdown(struct snd_pcm_substream *substream) ++{ ++ if (auto_shutdown_output) { ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ /* turn off digital output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); ++ } ++} ++ ++ ++static int snd_rpi_iqaudio_digi_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ int sysclk = 27000000; /* This is fixed on this board */ ++ ++ long mclk_freq = 0; ++ int mclk_div = 1; ++ int sampling_freq = 1; ++ ++ int ret; ++ ++ int samplerate = params_rate(params); ++ ++ if (samplerate <= 96000) { ++ mclk_freq = samplerate * 256; ++ mclk_div = WM8804_MCLKDIV_256FS; ++ } else { ++ mclk_freq = samplerate * 128; ++ mclk_div = WM8804_MCLKDIV_128FS; ++ } ++ ++ switch (samplerate) { ++ case 32000: ++ sampling_freq = 0x03; ++ break; ++ case 44100: ++ sampling_freq = 0x00; ++ break; ++ case 48000: ++ sampling_freq = 0x02; ++ break; ++ case 88200: ++ sampling_freq = 0x08; ++ break; ++ case 96000: ++ sampling_freq = 0x0a; ++ break; ++ case 176400: ++ sampling_freq = 0x0c; ++ break; ++ case 192000: ++ sampling_freq = 0x0e; ++ break; ++ default: ++ dev_err(codec->dev, "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", ++ samplerate); ++ } ++ ++ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); ++ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); ++ ++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, ++ sysclk, SND_SOC_CLOCK_OUT); ++ if (ret < 0) { ++ dev_err(codec->dev, "Failed to set WM8804 SYSCLK: %d\n", ret); ++ return ret; ++ } ++ ++ /* Enable TX output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); ++ ++ /* Power on */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0); ++ ++ /* set sampling frequency status bits */ ++ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_iqaudio_digi_ops = { ++ .hw_params = snd_rpi_iqaudio_digi_hw_params, ++ .startup = snd_rpi_iqaudio_digi_startup, ++ .shutdown = snd_rpi_iqaudio_digi_shutdown, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_iqaudio_digi_dai[] = { ++{ ++ .name = "IQAudIO Digi", ++ .stream_name = "IQAudIO Digi HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "wm8804-spdif", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "wm8804.1-003b", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &snd_rpi_iqaudio_digi_ops, ++ .init = snd_rpi_iqaudio_digi_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_iqaudio_digi = { ++ .name = "IQAudIODigi", ++ .owner = THIS_MODULE, ++ .dai_link = snd_rpi_iqaudio_digi_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_digi_dai), ++}; ++ ++static int snd_rpi_iqaudio_digi_probe(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = &snd_rpi_iqaudio_digi; ++ char *prefix = "wm8804-digi,"; ++ char prop[128]; ++ struct device_node *np; ++ int ret = 0; ++ ++ snd_rpi_iqaudio_digi.dev = &pdev->dev; ++ ++ np = pdev->dev.of_node; ++ if (np) { ++ struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_digi_dai[0]; ++ struct device_node *i2s_node; ++ ++ i2s_node = of_parse_phandle(np, "i2s-controller", 0); ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ ++ snprintf(prop, sizeof(prop), "%scard-name", prefix); ++ of_property_read_string(np, prop, &card->name); ++ ++ snprintf(prop, sizeof(prop), "%sdai-name", prefix); ++ of_property_read_string(np, prop, &dai->name); ++ ++ snprintf(prop, sizeof(prop), "%sdai-stream-name", prefix); ++ of_property_read_string(np, prop, &dai->stream_name); ++ } ++ ++ ret = snd_soc_register_card(card); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ++ ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_iqaudio_digi_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_iqaudio_digi); ++} ++ ++static const struct of_device_id snd_rpi_iqaudio_digi_of_match[] = { ++ { .compatible = "iqaudio,wm8804-digi", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_iqaudio_digi_of_match); ++ ++static struct platform_driver snd_rpi_iqaudio_digi_driver = { ++ .driver = { ++ .name = "IQAudIODigi", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_iqaudio_digi_of_match, ++ }, ++ .probe = snd_rpi_iqaudio_digi_probe, ++ .remove = snd_rpi_iqaudio_digi_remove, ++}; ++ ++module_platform_driver(snd_rpi_iqaudio_digi_driver); ++ ++MODULE_AUTHOR("Daniel Matuschek "); ++MODULE_DESCRIPTION("ASoC Driver for IQAudIO WM8804 Digi"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0080-New-AudioInjector.net-Pi-soundcard-with-low-jitter-a.patch b/target/linux/brcm2708/patches-4.9/0080-New-AudioInjector.net-Pi-soundcard-with-low-jitter-a.patch deleted file mode 100644 index 207cc66588..0000000000 --- a/target/linux/brcm2708/patches-4.9/0080-New-AudioInjector.net-Pi-soundcard-with-low-jitter-a.patch +++ /dev/null @@ -1,246 +0,0 @@ -From 14502b0564fc2e7181857de254a6f6bd07db4038 Mon Sep 17 00:00:00 2001 -From: Matt Flax -Date: Mon, 16 May 2016 21:36:31 +1000 -Subject: [PATCH] New AudioInjector.net Pi soundcard with low jitter audio in - and out. - -Contains the sound/soc/bcm ALSA machine driver and necessary alterations to the Kconfig and Makefile. -Adds the dts overlay and updates the Makefile and README. -Updates the relevant defconfig files to enable building for the Raspberry Pi. -Thanks to Phil Elwell (pelwell) for the review, simple-card concepts and discussion. Thanks to Clive Messer for overlay naming suggestions. - -Added support for headphones, microphone and bclk_ratio settings. - -This patch adds headphone and microphone capability to the Audio Injector sound card. The patch also sets the bit clock ratio for use in the bcm2835-i2s driver. The bcm2835-i2s can't handle an 8 kHz sample rate when the bit clock is at 12 MHz because its register is only 10 bits wide which can't represent the ch2 offset of 1508. For that reason, the rate constraint is added. ---- - sound/soc/bcm/Kconfig | 7 ++ - sound/soc/bcm/Makefile | 3 + - sound/soc/bcm/audioinjector-pi-soundcard.c | 193 +++++++++++++++++++++++++++++ - 3 files changed, 203 insertions(+) - create mode 100644 sound/soc/bcm/audioinjector-pi-soundcard.c - ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -87,3 +87,10 @@ config SND_BCM2708_SOC_ADAU1977_ADC - select SND_SOC_ADAU1977_I2C - help - Say Y or M if you want to add support for ADAU1977 ADC. -+ -+config SND_AUDIOINJECTOR_PI_SOUNDCARD -+ tristate "Support for audioinjector.net Pi add on soundcard" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_WM8731 -+ help -+ Say Y or M if you want to add support for audioinjector.net Pi Hat ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -19,6 +19,7 @@ snd-soc-rpi-dac-objs := rpi-dac.o - snd-soc-rpi-proto-objs := rpi-proto.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o - snd-soc-raspidac3-objs := raspidac3.o -+snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o - - obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -30,3 +31,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += - obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o -+obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o -+ ---- /dev/null -+++ b/sound/soc/bcm/audioinjector-pi-soundcard.c -@@ -0,0 +1,193 @@ -+/* -+ * ASoC Driver for AudioInjector Pi add on soundcard -+ * -+ * Created on: 13-May-2016 -+ * Author: flatmax@flatmax.org -+ * based on code by Cliff Cai for the ssm2602 machine blackfin. -+ * with help from Lars-Peter Clausen for simplifying the original code to use the dai_fmt field. -+ * i2s_node code taken from the other sound/soc/bcm machine drivers. -+ * -+ * Copyright (C) 2016 Flatmax Pty. Ltd. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "../codecs/wm8731.h" -+ -+static const unsigned int bcm2835_rates_12000000[] = { -+ 8000, 16000, 32000, 44100, 48000, 96000, 88200, -+}; -+ -+static struct snd_pcm_hw_constraint_list bcm2835_constraints_12000000 = { -+ .list = bcm2835_rates_12000000, -+ .count = ARRAY_SIZE(bcm2835_rates_12000000), -+}; -+ -+static int snd_audioinjector_pi_soundcard_startup(struct snd_pcm_substream *substream) -+{ -+ /* Setup constraints, because there is a 12 MHz XTAL on the board */ -+ snd_pcm_hw_constraint_list(substream->runtime, 0, -+ SNDRV_PCM_HW_PARAM_RATE, -+ &bcm2835_constraints_12000000); -+ return 0; -+} -+ -+static int snd_audioinjector_pi_soundcard_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ switch (params_rate(params)){ -+ case 8000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 1); -+ case 16000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 750); -+ case 32000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 375); -+ case 44100: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 272); -+ case 48000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 250); -+ case 88200: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 136); -+ case 96000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 125); -+ default: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 125); -+ } -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_audioinjector_pi_soundcard_ops = { -+ .startup = snd_audioinjector_pi_soundcard_startup, -+ .hw_params = snd_audioinjector_pi_soundcard_hw_params, -+}; -+ -+static int audioinjector_pi_soundcard_dai_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ return snd_soc_dai_set_sysclk(rtd->codec_dai, WM8731_SYSCLK_XTAL, 12000000, SND_SOC_CLOCK_IN); -+} -+ -+static struct snd_soc_dai_link audioinjector_pi_soundcard_dai[] = { -+ { -+ .name = "AudioInjector audio", -+ .stream_name = "AudioInjector audio", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "wm8731-hifi", -+ .platform_name = "bcm2835-i2s.0", -+ .codec_name = "wm8731.1-001a", -+ .ops = &snd_audioinjector_pi_soundcard_ops, -+ .init = audioinjector_pi_soundcard_dai_init, -+ .dai_fmt = SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF, -+ }, -+}; -+ -+static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { -+ SND_SOC_DAPM_HP("Headphone Jack", NULL), -+ SND_SOC_DAPM_SPK("Ext Spk", NULL), -+ SND_SOC_DAPM_LINE("Line In Jacks", NULL), -+ SND_SOC_DAPM_MIC("Microphone", NULL), -+}; -+ -+static const struct snd_soc_dapm_route audioinjector_audio_map[] = { -+ /* headphone connected to LHPOUT, RHPOUT */ -+ {"Headphone Jack", NULL, "LHPOUT"}, -+ {"Headphone Jack", NULL, "RHPOUT"}, -+ -+ /* speaker connected to LOUT, ROUT */ -+ {"Ext Spk", NULL, "ROUT"}, -+ {"Ext Spk", NULL, "LOUT"}, -+ -+ /* line inputs */ -+ {"Line In Jacks", NULL, "Line Input"}, -+ -+ /* mic is connected to Mic Jack, with WM8731 Mic Bias */ -+ {"Microphone", NULL, "Mic Bias"}, -+}; -+ -+static struct snd_soc_card snd_soc_audioinjector = { -+ .name = "audioinjector-pi-soundcard", -+ .dai_link = audioinjector_pi_soundcard_dai, -+ .num_links = ARRAY_SIZE(audioinjector_pi_soundcard_dai), -+ -+ .dapm_widgets = wm8731_dapm_widgets, -+ .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), -+ .dapm_routes = audioinjector_audio_map, -+ .num_dapm_routes = ARRAY_SIZE(audioinjector_audio_map), -+}; -+ -+static int audioinjector_pi_soundcard_probe(struct platform_device *pdev) -+{ -+ struct snd_soc_card *card = &snd_soc_audioinjector; -+ int ret; -+ -+ card->dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct snd_soc_dai_link *dai = &audioinjector_pi_soundcard_dai[0]; -+ struct device_node *i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } else -+ if (!dai->cpu_of_node) { -+ dev_err(&pdev->dev, "Property 'i2s-controller' missing or invalid\n"); -+ return -EINVAL; -+ } -+ } -+ -+ if ((ret = snd_soc_register_card(card))) { -+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); -+ } -+ return ret; -+} -+ -+static int audioinjector_pi_soundcard_remove(struct platform_device *pdev) -+{ -+ struct snd_soc_card *card = platform_get_drvdata(pdev); -+ return snd_soc_unregister_card(card); -+ -+} -+ -+static const struct of_device_id audioinjector_pi_soundcard_of_match[] = { -+ { .compatible = "ai,audioinjector-pi-soundcard", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, audioinjector_pi_soundcard_of_match); -+ -+static struct platform_driver audioinjector_pi_soundcard_driver = { -+ .driver = { -+ .name = "audioinjector-audio", -+ .owner = THIS_MODULE, -+ .of_match_table = audioinjector_pi_soundcard_of_match, -+ }, -+ .probe = audioinjector_pi_soundcard_probe, -+ .remove = audioinjector_pi_soundcard_remove, -+}; -+ -+module_platform_driver(audioinjector_pi_soundcard_driver); -+MODULE_AUTHOR("Matt Flax "); -+MODULE_DESCRIPTION("AudioInjector.net Pi Soundcard"); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:audioinjector-pi-soundcard"); -+ diff --git a/target/linux/brcm2708/patches-4.9/0081-Add-IQAudIO-Digi-WM8804-board-support.patch b/target/linux/brcm2708/patches-4.9/0081-Add-IQAudIO-Digi-WM8804-board-support.patch deleted file mode 100644 index e931c992c7..0000000000 --- a/target/linux/brcm2708/patches-4.9/0081-Add-IQAudIO-Digi-WM8804-board-support.patch +++ /dev/null @@ -1,295 +0,0 @@ -From 1b18f3be9f034c2e9aefab9b97c5100d5f914a89 Mon Sep 17 00:00:00 2001 -From: DigitalDreamtime -Date: Thu, 30 Jun 2016 18:38:42 +0100 -Subject: [PATCH] Add IQAudIO Digi WM8804 board support - -Support IQAudIO Digi board with iqaudio_digi machine driver and - iqaudio-digi-wm8804-audio overlay. - -NB. Machine driver is a cut and paste of hifiberry_digi code, with format - and general cleanup to comply with kernel coding standards. - -Signed-off-by: DigitalDreamtime ---- - sound/soc/bcm/Kconfig | 7 ++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/iqaudio_digi.c | 239 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 248 insertions(+) - create mode 100644 sound/soc/bcm/iqaudio_digi.c - ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -73,6 +73,13 @@ config SND_BCM2708_SOC_IQAUDIO_DAC - help - Say Y or M if you want to add support for IQaudIO-DAC. - -+config SND_BCM2708_SOC_IQAUDIO_DIGI -+ tristate "Support for IQAudIO Digi" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_WM8804 -+ help -+ Say Y or M if you want to add support for IQAudIO Digital IO board. -+ - config SND_BCM2708_SOC_RASPIDAC3 - tristate "Support for RaspiDAC Rev.3x" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -18,6 +18,7 @@ snd-soc-justboom-digi-objs := justboom-d - snd-soc-rpi-dac-objs := rpi-dac.o - snd-soc-rpi-proto-objs := rpi-proto.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o -+snd-soc-iqaudio-digi-objs := iqaudio_digi.o - snd-soc-raspidac3-objs := raspidac3.o - snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o - -@@ -30,6 +31,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DI - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o - obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o - ---- /dev/null -+++ b/sound/soc/bcm/iqaudio_digi.c -@@ -0,0 +1,239 @@ -+/* -+ * ASoC Driver for IQAudIO WM8804 Digi -+ * -+ * Author: Daniel Matuschek -+ * based on the HifiBerry DAC driver by Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "../codecs/wm8804.h" -+ -+static short int auto_shutdown_output; -+module_param(auto_shutdown_output, short, -+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); -+MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); -+ -+static int snd_rpi_iqaudio_digi_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ /* enable TX output */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); -+ -+ return 0; -+} -+ -+static int snd_rpi_iqaudio_digi_startup(struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ /* turn on digital output */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); -+ -+ return 0; -+} -+ -+static void snd_rpi_iqaudio_digi_shutdown(struct snd_pcm_substream *substream) -+{ -+ if (auto_shutdown_output) { -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ /* turn off digital output */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); -+ } -+} -+ -+ -+static int snd_rpi_iqaudio_digi_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *codec_dai = rtd->codec_dai; -+ struct snd_soc_codec *codec = rtd->codec; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ int sysclk = 27000000; /* This is fixed on this board */ -+ -+ long mclk_freq = 0; -+ int mclk_div = 1; -+ int sampling_freq = 1; -+ -+ int ret; -+ -+ int samplerate = params_rate(params); -+ -+ if (samplerate <= 96000) { -+ mclk_freq = samplerate * 256; -+ mclk_div = WM8804_MCLKDIV_256FS; -+ } else { -+ mclk_freq = samplerate * 128; -+ mclk_div = WM8804_MCLKDIV_128FS; -+ } -+ -+ switch (samplerate) { -+ case 32000: -+ sampling_freq = 0x03; -+ break; -+ case 44100: -+ sampling_freq = 0x00; -+ break; -+ case 48000: -+ sampling_freq = 0x02; -+ break; -+ case 88200: -+ sampling_freq = 0x08; -+ break; -+ case 96000: -+ sampling_freq = 0x0a; -+ break; -+ case 176400: -+ sampling_freq = 0x0c; -+ break; -+ case 192000: -+ sampling_freq = 0x0e; -+ break; -+ default: -+ dev_err(codec->dev, "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", -+ samplerate); -+ } -+ -+ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); -+ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); -+ -+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, -+ sysclk, SND_SOC_CLOCK_OUT); -+ if (ret < 0) { -+ dev_err(codec->dev, "Failed to set WM8804 SYSCLK: %d\n", ret); -+ return ret; -+ } -+ -+ /* Enable TX output */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); -+ -+ /* Power on */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0); -+ -+ /* set sampling frequency status bits */ -+ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_iqaudio_digi_ops = { -+ .hw_params = snd_rpi_iqaudio_digi_hw_params, -+ .startup = snd_rpi_iqaudio_digi_startup, -+ .shutdown = snd_rpi_iqaudio_digi_shutdown, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_iqaudio_digi_dai[] = { -+{ -+ .name = "IQAudIO Digi", -+ .stream_name = "IQAudIO Digi HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "wm8804-spdif", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "wm8804.1-003b", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBM_CFM, -+ .ops = &snd_rpi_iqaudio_digi_ops, -+ .init = snd_rpi_iqaudio_digi_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_iqaudio_digi = { -+ .name = "IQAudIODigi", -+ .owner = THIS_MODULE, -+ .dai_link = snd_rpi_iqaudio_digi_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_digi_dai), -+}; -+ -+static int snd_rpi_iqaudio_digi_probe(struct platform_device *pdev) -+{ -+ struct snd_soc_card *card = &snd_rpi_iqaudio_digi; -+ char *prefix = "wm8804-digi,"; -+ char prop[128]; -+ struct device_node *np; -+ int ret = 0; -+ -+ snd_rpi_iqaudio_digi.dev = &pdev->dev; -+ -+ np = pdev->dev.of_node; -+ if (np) { -+ struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_digi_dai[0]; -+ struct device_node *i2s_node; -+ -+ i2s_node = of_parse_phandle(np, "i2s-controller", 0); -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ -+ snprintf(prop, sizeof(prop), "%scard-name", prefix); -+ of_property_read_string(np, prop, &card->name); -+ -+ snprintf(prop, sizeof(prop), "%sdai-name", prefix); -+ of_property_read_string(np, prop, &dai->name); -+ -+ snprintf(prop, sizeof(prop), "%sdai-stream-name", prefix); -+ of_property_read_string(np, prop, &dai->stream_name); -+ } -+ -+ ret = snd_soc_register_card(card); -+ if (ret) -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", -+ ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_iqaudio_digi_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_iqaudio_digi); -+} -+ -+static const struct of_device_id snd_rpi_iqaudio_digi_of_match[] = { -+ { .compatible = "iqaudio,wm8804-digi", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_iqaudio_digi_of_match); -+ -+static struct platform_driver snd_rpi_iqaudio_digi_driver = { -+ .driver = { -+ .name = "IQAudIODigi", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_iqaudio_digi_of_match, -+ }, -+ .probe = snd_rpi_iqaudio_digi_probe, -+ .remove = snd_rpi_iqaudio_digi_remove, -+}; -+ -+module_platform_driver(snd_rpi_iqaudio_digi_driver); -+ -+MODULE_AUTHOR("Daniel Matuschek "); -+MODULE_DESCRIPTION("ASoC Driver for IQAudIO WM8804 Digi"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0081-New-driver-for-RRA-DigiDAC1-soundcard-using-WM8741-W.patch b/target/linux/brcm2708/patches-4.9/0081-New-driver-for-RRA-DigiDAC1-soundcard-using-WM8741-W.patch new file mode 100644 index 0000000000..45a5a379be --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0081-New-driver-for-RRA-DigiDAC1-soundcard-using-WM8741-W.patch @@ -0,0 +1,467 @@ +From e5d85d533e7ea8fd5c68d4601ff2b8034bc4aaa9 Mon Sep 17 00:00:00 2001 +From: escalator2015 +Date: Tue, 24 May 2016 16:20:09 +0100 +Subject: [PATCH] New driver for RRA DigiDAC1 soundcard using WM8741 + WM8804 + +--- + sound/soc/bcm/Kconfig | 8 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/digidac1-soundcard.c | 422 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 432 insertions(+) + create mode 100644 sound/soc/bcm/digidac1-soundcard.c + +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -108,3 +108,11 @@ config SND_AUDIOINJECTOR_PI_SOUNDCARD + select SND_SOC_WM8731 + help + Say Y or M if you want to add support for audioinjector.net Pi Hat ++ ++config SND_DIGIDAC1_SOUNDCARD ++ tristate "Support for Red Rocks Audio DigiDAC1" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_WM8804 ++ select SND_SOC_WM8741 ++ help ++ Say Y or M if you want to add support for Red Rocks Audio DigiDAC1 board. +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -22,6 +22,7 @@ snd-soc-iqaudio-dac-objs := iqaudio-dac. + snd-soc-iqaudio-digi-objs := iqaudio_digi.o + snd-soc-raspidac3-objs := raspidac3.o + snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o ++snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o + + obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o +@@ -36,4 +37,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o + obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o ++obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o + +--- /dev/null ++++ b/sound/soc/bcm/digidac1-soundcard.c +@@ -0,0 +1,422 @@ ++/* ++ * ASoC Driver for RRA DigiDAC1 ++ * Copyright 2016 ++ * Author: José M. Tasende ++ * based on the HifiBerry DAC driver by Florian Meier ++ * and the Wolfson card driver by Nikesh Oswal, ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../codecs/wm8804.h" ++#include "../codecs/wm8741.h" ++ ++#define WM8741_NUM_SUPPLIES 2 ++ ++/* codec private data */ ++struct wm8741_priv { ++ struct wm8741_platform_data pdata; ++ struct regmap *regmap; ++ struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; ++ unsigned int sysclk; ++ const struct snd_pcm_hw_constraint_list *sysclk_constraints; ++}; ++ ++static int samplerate = 44100; ++ ++/* New Alsa Controls not exposed by original wm8741 codec driver */ ++/* in actual driver the att. adjustment is wrong because */ ++/* this DAC has a coarse attenuation register with 4dB steps */ ++/* and a fine level register with 0.125dB steps */ ++/* each register has 32 steps so combining both we have 1024 steps */ ++/* of 0.125 dB. */ ++/* The original level controls from driver are removed at startup */ ++/* and replaced by the corrected ones. */ ++/* The same wm8741 driver can be used for wm8741 and wm8742 devices */ ++ ++static const DECLARE_TLV_DB_SCALE(dac_tlv_fine, 0, 13, 0); ++static const DECLARE_TLV_DB_SCALE(dac_tlv_coarse, -12700, 400, 1); ++static const char *w8741_dither[4] = {"Off", "RPDF", "TPDF", "HPDF"}; ++static const char *w8741_filter[5] = { ++ "Type 1", "Type 2", "Type 3", "Type 4", "Type 5"}; ++static const char *w8741_switch[2] = {"Off", "On"}; ++static const struct soc_enum w8741_enum[] = { ++SOC_ENUM_SINGLE(WM8741_MODE_CONTROL_2, 0, 4, w8741_dither),/* dithering type */ ++SOC_ENUM_SINGLE(WM8741_FILTER_CONTROL, 0, 5, w8741_filter),/* filter type */ ++SOC_ENUM_SINGLE(WM8741_FORMAT_CONTROL, 6, 2, w8741_switch),/* phase invert */ ++SOC_ENUM_SINGLE(WM8741_VOLUME_CONTROL, 0, 2, w8741_switch),/* volume ramp */ ++SOC_ENUM_SINGLE(WM8741_VOLUME_CONTROL, 3, 2, w8741_switch),/* soft mute */ ++}; ++ ++static const struct snd_kcontrol_new w8741_snd_controls_stereo[] = { ++SOC_DOUBLE_R_TLV("DAC Fine Playback Volume", WM8741_DACLLSB_ATTENUATION, ++ WM8741_DACRLSB_ATTENUATION, 0, 31, 1, dac_tlv_fine), ++SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8741_DACLMSB_ATTENUATION, ++ WM8741_DACRMSB_ATTENUATION, 0, 31, 1, dac_tlv_coarse), ++SOC_ENUM("DAC Dither", w8741_enum[0]), ++SOC_ENUM("DAC Digital Filter", w8741_enum[1]), ++SOC_ENUM("DAC Phase Invert", w8741_enum[2]), ++SOC_ENUM("DAC Volume Ramp", w8741_enum[3]), ++SOC_ENUM("DAC Soft Mute", w8741_enum[4]), ++}; ++ ++static const struct snd_kcontrol_new w8741_snd_controls_mono_left[] = { ++SOC_SINGLE_TLV("DAC Fine Playback Volume", WM8741_DACLLSB_ATTENUATION, ++ 0, 31, 0, dac_tlv_fine), ++SOC_SINGLE_TLV("Digital Playback Volume", WM8741_DACLMSB_ATTENUATION, ++ 0, 31, 1, dac_tlv_coarse), ++SOC_ENUM("DAC Dither", w8741_enum[0]), ++SOC_ENUM("DAC Digital Filter", w8741_enum[1]), ++SOC_ENUM("DAC Phase Invert", w8741_enum[2]), ++SOC_ENUM("DAC Volume Ramp", w8741_enum[3]), ++SOC_ENUM("DAC Soft Mute", w8741_enum[4]), ++}; ++ ++static const struct snd_kcontrol_new w8741_snd_controls_mono_right[] = { ++SOC_SINGLE_TLV("DAC Fine Playback Volume", WM8741_DACRLSB_ATTENUATION, ++ 0, 31, 0, dac_tlv_fine), ++SOC_SINGLE_TLV("Digital Playback Volume", WM8741_DACRMSB_ATTENUATION, ++ 0, 31, 1, dac_tlv_coarse), ++SOC_ENUM("DAC Dither", w8741_enum[0]), ++SOC_ENUM("DAC Digital Filter", w8741_enum[1]), ++SOC_ENUM("DAC Phase Invert", w8741_enum[2]), ++SOC_ENUM("DAC Volume Ramp", w8741_enum[3]), ++SOC_ENUM("DAC Soft Mute", w8741_enum[4]), ++}; ++ ++static int w8741_add_controls(struct snd_soc_codec *codec) ++{ ++ struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); ++ ++ switch (wm8741->pdata.diff_mode) { ++ case WM8741_DIFF_MODE_STEREO: ++ case WM8741_DIFF_MODE_STEREO_REVERSED: ++ snd_soc_add_codec_controls(codec, ++ w8741_snd_controls_stereo, ++ ARRAY_SIZE(w8741_snd_controls_stereo)); ++ break; ++ case WM8741_DIFF_MODE_MONO_LEFT: ++ snd_soc_add_codec_controls(codec, ++ w8741_snd_controls_mono_left, ++ ARRAY_SIZE(w8741_snd_controls_mono_left)); ++ break; ++ case WM8741_DIFF_MODE_MONO_RIGHT: ++ snd_soc_add_codec_controls(codec, ++ w8741_snd_controls_mono_right, ++ ARRAY_SIZE(w8741_snd_controls_mono_right)); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int digidac1_soundcard_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_card *card = rtd->card; ++ struct snd_soc_pcm_runtime *wm8741_rtd; ++ struct snd_soc_codec *wm8741_codec; ++ struct snd_card *sound_card = card->snd_card; ++ struct snd_kcontrol *kctl; ++ int ret; ++ ++ wm8741_rtd = snd_soc_get_pcm_runtime(card, card->dai_link[1].name); ++ if (!wm8741_rtd) { ++ dev_warn(card->dev, "digidac1_soundcard_init: couldn't get wm8741 rtd\n"); ++ return -EFAULT; ++ } ++ wm8741_codec = wm8741_rtd->codec; ++ ret = w8741_add_controls(wm8741_codec); ++ if (ret < 0) ++ dev_warn(card->dev, "Failed to add new wm8741 controls: %d\n", ++ ret); ++ ++ /* enable TX output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); ++ ++ kctl = snd_soc_card_get_kcontrol(card, ++ "Playback Volume"); ++ if (kctl) { ++ kctl->vd[0].access = SNDRV_CTL_ELEM_ACCESS_READWRITE; ++ snd_ctl_remove(sound_card, kctl); ++ } ++ kctl = snd_soc_card_get_kcontrol(card, ++ "Fine Playback Volume"); ++ if (kctl) { ++ kctl->vd[0].access = SNDRV_CTL_ELEM_ACCESS_READWRITE; ++ snd_ctl_remove(sound_card, kctl); ++ } ++ return 0; ++} ++ ++static int digidac1_soundcard_startup(struct snd_pcm_substream *substream) ++{ ++ /* turn on wm8804 digital output */ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_card *card = rtd->card; ++ struct snd_soc_pcm_runtime *wm8741_rtd; ++ struct snd_soc_codec *wm8741_codec; ++ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); ++ wm8741_rtd = snd_soc_get_pcm_runtime(card, card->dai_link[1].name); ++ if (!wm8741_rtd) { ++ dev_warn(card->dev, "digidac1_soundcard_startup: couldn't get WM8741 rtd\n"); ++ return -EFAULT; ++ } ++ wm8741_codec = wm8741_rtd->codec; ++ ++ /* latch wm8741 level */ ++ snd_soc_update_bits(wm8741_codec, WM8741_DACLLSB_ATTENUATION, ++ WM8741_UPDATELL, WM8741_UPDATELL); ++ snd_soc_update_bits(wm8741_codec, WM8741_DACLMSB_ATTENUATION, ++ WM8741_UPDATELM, WM8741_UPDATELM); ++ snd_soc_update_bits(wm8741_codec, WM8741_DACRLSB_ATTENUATION, ++ WM8741_UPDATERL, WM8741_UPDATERL); ++ snd_soc_update_bits(wm8741_codec, WM8741_DACRMSB_ATTENUATION, ++ WM8741_UPDATERM, WM8741_UPDATERM); ++ ++ return 0; ++} ++ ++static void digidac1_soundcard_shutdown(struct snd_pcm_substream *substream) ++{ ++ /* turn off wm8804 digital output */ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); ++} ++ ++static int digidac1_soundcard_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ struct snd_soc_card *card = rtd->card; ++ struct snd_soc_pcm_runtime *wm8741_rtd; ++ struct snd_soc_codec *wm8741_codec; ++ ++ int sysclk = 27000000; ++ long mclk_freq = 0; ++ int mclk_div = 1; ++ int sampling_freq = 1; ++ int ret; ++ ++ wm8741_rtd = snd_soc_get_pcm_runtime(card, card->dai_link[1].name); ++ if (!wm8741_rtd) { ++ dev_warn(card->dev, "digidac1_soundcard_hw_params: couldn't get WM8741 rtd\n"); ++ return -EFAULT; ++ } ++ wm8741_codec = wm8741_rtd->codec; ++ samplerate = params_rate(params); ++ ++ if (samplerate <= 96000) { ++ mclk_freq = samplerate*256; ++ mclk_div = WM8804_MCLKDIV_256FS; ++ } else { ++ mclk_freq = samplerate*128; ++ mclk_div = WM8804_MCLKDIV_128FS; ++ } ++ ++ switch (samplerate) { ++ case 32000: ++ sampling_freq = 0x03; ++ break; ++ case 44100: ++ sampling_freq = 0x00; ++ break; ++ case 48000: ++ sampling_freq = 0x02; ++ break; ++ case 88200: ++ sampling_freq = 0x08; ++ break; ++ case 96000: ++ sampling_freq = 0x0a; ++ break; ++ case 176400: ++ sampling_freq = 0x0c; ++ break; ++ case 192000: ++ sampling_freq = 0x0e; ++ break; ++ default: ++ dev_err(codec->dev, ++ "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", ++ samplerate); ++ } ++ ++ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); ++ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); ++ ++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, ++ sysclk, SND_SOC_CLOCK_OUT); ++ if (ret < 0) { ++ dev_err(codec->dev, ++ "Failed to set WM8804 SYSCLK: %d\n", ret); ++ return ret; ++ } ++ /* Enable wm8804 TX output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); ++ ++ /* wm8804 Power on */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0); ++ ++ /* wm8804 set sampling frequency status bits */ ++ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); ++ ++ /* Now update wm8741 registers for the correct oversampling */ ++ if (samplerate <= 48000) ++ snd_soc_update_bits(wm8741_codec, WM8741_MODE_CONTROL_1, ++ WM8741_OSR_MASK, 0x00); ++ else if (samplerate <= 96000) ++ snd_soc_update_bits(wm8741_codec, WM8741_MODE_CONTROL_1, ++ WM8741_OSR_MASK, 0x20); ++ else ++ snd_soc_update_bits(wm8741_codec, WM8741_MODE_CONTROL_1, ++ WM8741_OSR_MASK, 0x40); ++ ++ /* wm8741 bit size */ ++ switch (params_width(params)) { ++ case 16: ++ snd_soc_update_bits(wm8741_codec, WM8741_FORMAT_CONTROL, ++ WM8741_IWL_MASK, 0x00); ++ break; ++ case 20: ++ snd_soc_update_bits(wm8741_codec, WM8741_FORMAT_CONTROL, ++ WM8741_IWL_MASK, 0x01); ++ break; ++ case 24: ++ snd_soc_update_bits(wm8741_codec, WM8741_FORMAT_CONTROL, ++ WM8741_IWL_MASK, 0x02); ++ break; ++ case 32: ++ snd_soc_update_bits(wm8741_codec, WM8741_FORMAT_CONTROL, ++ WM8741_IWL_MASK, 0x03); ++ break; ++ default: ++ dev_dbg(codec->dev, "wm8741_hw_params: Unsupported bit size param = %d", ++ params_width(params)); ++ return -EINVAL; ++ } ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); ++} ++/* machine stream operations */ ++static struct snd_soc_ops digidac1_soundcard_ops = { ++ .hw_params = digidac1_soundcard_hw_params, ++ .startup = digidac1_soundcard_startup, ++ .shutdown = digidac1_soundcard_shutdown, ++}; ++ ++static struct snd_soc_dai_link digidac1_soundcard_dai[] = { ++ { ++ .name = "RRA DigiDAC1", ++ .stream_name = "RRA DigiDAC1 HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "wm8804-spdif", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "wm8804.1-003b", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &digidac1_soundcard_ops, ++ .init = digidac1_soundcard_init, ++ }, ++ { ++ .name = "RRA DigiDAC11", ++ .stream_name = "RRA DigiDAC11 HiFi", ++ .cpu_dai_name = "wm8804-spdif", ++ .codec_dai_name = "wm8741", ++ .codec_name = "wm8741.1-001a", ++ .dai_fmt = SND_SOC_DAIFMT_I2S ++ | SND_SOC_DAIFMT_NB_NF ++ | SND_SOC_DAIFMT_CBS_CFS, ++ }, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card digidac1_soundcard = { ++ .name = "digidac1-soundcard", ++ .owner = THIS_MODULE, ++ .dai_link = digidac1_soundcard_dai, ++ .num_links = ARRAY_SIZE(digidac1_soundcard_dai), ++}; ++ ++static int digidac1_soundcard_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ digidac1_soundcard.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &digidac1_soundcard_dai[0]; ++ ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ ret = snd_soc_register_card(&digidac1_soundcard); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ++ ret); ++ ++ return ret; ++} ++ ++static int digidac1_soundcard_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&digidac1_soundcard); ++} ++ ++static const struct of_device_id digidac1_soundcard_of_match[] = { ++ { .compatible = "rra,digidac1-soundcard", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, digidac1_soundcard_of_match); ++ ++static struct platform_driver digidac1_soundcard_driver = { ++ .driver = { ++ .name = "digidac1-audio", ++ .owner = THIS_MODULE, ++ .of_match_table = digidac1_soundcard_of_match, ++ }, ++ .probe = digidac1_soundcard_probe, ++ .remove = digidac1_soundcard_remove, ++}; ++ ++module_platform_driver(digidac1_soundcard_driver); ++ ++MODULE_AUTHOR("José M. Tasende "); ++MODULE_DESCRIPTION("ASoC Driver for RRA DigiDAC1"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0082-Add-support-for-Dion-Audio-LOCO-DAC-AMP-HAT.patch b/target/linux/brcm2708/patches-4.9/0082-Add-support-for-Dion-Audio-LOCO-DAC-AMP-HAT.patch new file mode 100644 index 0000000000..b06cd35b72 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0082-Add-support-for-Dion-Audio-LOCO-DAC-AMP-HAT.patch @@ -0,0 +1,168 @@ +From 999d3e615247d1921d245f7084194efbc697bb66 Mon Sep 17 00:00:00 2001 +From: DigitalDreamtime +Date: Sat, 2 Jul 2016 16:26:19 +0100 +Subject: [PATCH] Add support for Dion Audio LOCO DAC-AMP HAT + +Using dedicated machine driver and pcm5102a codec driver. + +Signed-off-by: DigitalDreamtime +--- + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 3 +- + sound/soc/bcm/dionaudio_loco.c | 121 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 130 insertions(+), 1 deletion(-) + create mode 100644 sound/soc/bcm/dionaudio_loco.c + +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -116,3 +116,10 @@ config SND_DIGIDAC1_SOUNDCARD + select SND_SOC_WM8741 + help + Say Y or M if you want to add support for Red Rocks Audio DigiDAC1 board. ++ ++config SND_BCM2708_SOC_DIONAUDIO_LOCO ++ tristate "Support for Dion Audio LOCO DAC-AMP" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM5102a ++ help ++ Say Y or M if you want to add support for Dion Audio LOCO. +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -23,6 +23,7 @@ snd-soc-iqaudio-digi-objs := iqaudio_dig + snd-soc-raspidac3-objs := raspidac3.o + snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o + snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o ++snd-soc-dionaudio-loco-objs := dionaudio_loco.o + + obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o +@@ -38,4 +39,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIG + obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o + obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o + obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o +- ++obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o +--- /dev/null ++++ b/sound/soc/bcm/dionaudio_loco.c +@@ -0,0 +1,121 @@ ++/* ++ * ASoC Driver for Dion Audio LOCO DAC-AMP ++ * ++ * Author: Miquel Blauw ++ * Copyright 2016 ++ * ++ * Based on the software of the RPi-DAC writen by Florian Meier ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++static int snd_rpi_dionaudio_loco_hw_params( ++ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ unsigned int sample_bits = ++ snd_pcm_format_physical_width(params_format(params)); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_dionaudio_loco_ops = { ++ .hw_params = snd_rpi_dionaudio_loco_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_dionaudio_loco_dai[] = { ++{ ++ .name = "DionAudio LOCO", ++ .stream_name = "DionAudio LOCO DAC-AMP", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm5102a-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm5102a-codec", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_dionaudio_loco_ops, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_dionaudio_loco = { ++ .name = "snd_rpi_dionaudio_loco", ++ .dai_link = snd_rpi_dionaudio_loco_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_dionaudio_loco_dai), ++}; ++ ++static int snd_rpi_dionaudio_loco_probe(struct platform_device *pdev) ++{ ++ struct device_node *np; ++ int ret = 0; ++ ++ snd_rpi_dionaudio_loco.dev = &pdev->dev; ++ ++ np = pdev->dev.of_node; ++ if (np) { ++ struct snd_soc_dai_link *dai = &snd_rpi_dionaudio_loco_dai[0]; ++ struct device_node *i2s_np; ++ ++ i2s_np = of_parse_phandle(np, "i2s-controller", 0); ++ if (i2s_np) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_np; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_np; ++ } ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_dionaudio_loco); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ++ ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_dionaudio_loco_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_dionaudio_loco); ++} ++ ++static const struct of_device_id snd_rpi_dionaudio_loco_of_match[] = { ++ { .compatible = "dionaudio,loco-pcm5242-tpa3118", }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_dionaudio_loco_of_match); ++ ++static struct platform_driver snd_rpi_dionaudio_loco_driver = { ++ .driver = { ++ .name = "snd-dionaudio-loco", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_dionaudio_loco_of_match, ++ }, ++ .probe = snd_rpi_dionaudio_loco_probe, ++ .remove = snd_rpi_dionaudio_loco_remove, ++}; ++ ++module_platform_driver(snd_rpi_dionaudio_loco_driver); ++ ++MODULE_AUTHOR("Miquel Blauw "); ++MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0082-New-driver-for-RRA-DigiDAC1-soundcard-using-WM8741-W.patch b/target/linux/brcm2708/patches-4.9/0082-New-driver-for-RRA-DigiDAC1-soundcard-using-WM8741-W.patch deleted file mode 100644 index 55d32df1c5..0000000000 --- a/target/linux/brcm2708/patches-4.9/0082-New-driver-for-RRA-DigiDAC1-soundcard-using-WM8741-W.patch +++ /dev/null @@ -1,467 +0,0 @@ -From 6daac5c03a5a96f6ae711e90d46e3d5de3ba1298 Mon Sep 17 00:00:00 2001 -From: escalator2015 -Date: Tue, 24 May 2016 16:20:09 +0100 -Subject: [PATCH] New driver for RRA DigiDAC1 soundcard using WM8741 + WM8804 - ---- - sound/soc/bcm/Kconfig | 8 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/digidac1-soundcard.c | 422 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 432 insertions(+) - create mode 100644 sound/soc/bcm/digidac1-soundcard.c - ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -101,3 +101,11 @@ config SND_AUDIOINJECTOR_PI_SOUNDCARD - select SND_SOC_WM8731 - help - Say Y or M if you want to add support for audioinjector.net Pi Hat -+ -+config SND_DIGIDAC1_SOUNDCARD -+ tristate "Support for Red Rocks Audio DigiDAC1" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_WM8804 -+ select SND_SOC_WM8741 -+ help -+ Say Y or M if you want to add support for Red Rocks Audio DigiDAC1 board. ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -21,6 +21,7 @@ snd-soc-iqaudio-dac-objs := iqaudio-dac. - snd-soc-iqaudio-digi-objs := iqaudio_digi.o - snd-soc-raspidac3-objs := raspidac3.o - snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o -+snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o - - obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -34,4 +35,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o - obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o -+obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o - ---- /dev/null -+++ b/sound/soc/bcm/digidac1-soundcard.c -@@ -0,0 +1,422 @@ -+/* -+ * ASoC Driver for RRA DigiDAC1 -+ * Copyright 2016 -+ * Author: José M. Tasende -+ * based on the HifiBerry DAC driver by Florian Meier -+ * and the Wolfson card driver by Nikesh Oswal, -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "../codecs/wm8804.h" -+#include "../codecs/wm8741.h" -+ -+#define WM8741_NUM_SUPPLIES 2 -+ -+/* codec private data */ -+struct wm8741_priv { -+ struct wm8741_platform_data pdata; -+ struct regmap *regmap; -+ struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; -+ unsigned int sysclk; -+ const struct snd_pcm_hw_constraint_list *sysclk_constraints; -+}; -+ -+static int samplerate = 44100; -+ -+/* New Alsa Controls not exposed by original wm8741 codec driver */ -+/* in actual driver the att. adjustment is wrong because */ -+/* this DAC has a coarse attenuation register with 4dB steps */ -+/* and a fine level register with 0.125dB steps */ -+/* each register has 32 steps so combining both we have 1024 steps */ -+/* of 0.125 dB. */ -+/* The original level controls from driver are removed at startup */ -+/* and replaced by the corrected ones. */ -+/* The same wm8741 driver can be used for wm8741 and wm8742 devices */ -+ -+static const DECLARE_TLV_DB_SCALE(dac_tlv_fine, 0, 13, 0); -+static const DECLARE_TLV_DB_SCALE(dac_tlv_coarse, -12700, 400, 1); -+static const char *w8741_dither[4] = {"Off", "RPDF", "TPDF", "HPDF"}; -+static const char *w8741_filter[5] = { -+ "Type 1", "Type 2", "Type 3", "Type 4", "Type 5"}; -+static const char *w8741_switch[2] = {"Off", "On"}; -+static const struct soc_enum w8741_enum[] = { -+SOC_ENUM_SINGLE(WM8741_MODE_CONTROL_2, 0, 4, w8741_dither),/* dithering type */ -+SOC_ENUM_SINGLE(WM8741_FILTER_CONTROL, 0, 5, w8741_filter),/* filter type */ -+SOC_ENUM_SINGLE(WM8741_FORMAT_CONTROL, 6, 2, w8741_switch),/* phase invert */ -+SOC_ENUM_SINGLE(WM8741_VOLUME_CONTROL, 0, 2, w8741_switch),/* volume ramp */ -+SOC_ENUM_SINGLE(WM8741_VOLUME_CONTROL, 3, 2, w8741_switch),/* soft mute */ -+}; -+ -+static const struct snd_kcontrol_new w8741_snd_controls_stereo[] = { -+SOC_DOUBLE_R_TLV("DAC Fine Playback Volume", WM8741_DACLLSB_ATTENUATION, -+ WM8741_DACRLSB_ATTENUATION, 0, 31, 1, dac_tlv_fine), -+SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8741_DACLMSB_ATTENUATION, -+ WM8741_DACRMSB_ATTENUATION, 0, 31, 1, dac_tlv_coarse), -+SOC_ENUM("DAC Dither", w8741_enum[0]), -+SOC_ENUM("DAC Digital Filter", w8741_enum[1]), -+SOC_ENUM("DAC Phase Invert", w8741_enum[2]), -+SOC_ENUM("DAC Volume Ramp", w8741_enum[3]), -+SOC_ENUM("DAC Soft Mute", w8741_enum[4]), -+}; -+ -+static const struct snd_kcontrol_new w8741_snd_controls_mono_left[] = { -+SOC_SINGLE_TLV("DAC Fine Playback Volume", WM8741_DACLLSB_ATTENUATION, -+ 0, 31, 0, dac_tlv_fine), -+SOC_SINGLE_TLV("Digital Playback Volume", WM8741_DACLMSB_ATTENUATION, -+ 0, 31, 1, dac_tlv_coarse), -+SOC_ENUM("DAC Dither", w8741_enum[0]), -+SOC_ENUM("DAC Digital Filter", w8741_enum[1]), -+SOC_ENUM("DAC Phase Invert", w8741_enum[2]), -+SOC_ENUM("DAC Volume Ramp", w8741_enum[3]), -+SOC_ENUM("DAC Soft Mute", w8741_enum[4]), -+}; -+ -+static const struct snd_kcontrol_new w8741_snd_controls_mono_right[] = { -+SOC_SINGLE_TLV("DAC Fine Playback Volume", WM8741_DACRLSB_ATTENUATION, -+ 0, 31, 0, dac_tlv_fine), -+SOC_SINGLE_TLV("Digital Playback Volume", WM8741_DACRMSB_ATTENUATION, -+ 0, 31, 1, dac_tlv_coarse), -+SOC_ENUM("DAC Dither", w8741_enum[0]), -+SOC_ENUM("DAC Digital Filter", w8741_enum[1]), -+SOC_ENUM("DAC Phase Invert", w8741_enum[2]), -+SOC_ENUM("DAC Volume Ramp", w8741_enum[3]), -+SOC_ENUM("DAC Soft Mute", w8741_enum[4]), -+}; -+ -+static int w8741_add_controls(struct snd_soc_codec *codec) -+{ -+ struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); -+ -+ switch (wm8741->pdata.diff_mode) { -+ case WM8741_DIFF_MODE_STEREO: -+ case WM8741_DIFF_MODE_STEREO_REVERSED: -+ snd_soc_add_codec_controls(codec, -+ w8741_snd_controls_stereo, -+ ARRAY_SIZE(w8741_snd_controls_stereo)); -+ break; -+ case WM8741_DIFF_MODE_MONO_LEFT: -+ snd_soc_add_codec_controls(codec, -+ w8741_snd_controls_mono_left, -+ ARRAY_SIZE(w8741_snd_controls_mono_left)); -+ break; -+ case WM8741_DIFF_MODE_MONO_RIGHT: -+ snd_soc_add_codec_controls(codec, -+ w8741_snd_controls_mono_right, -+ ARRAY_SIZE(w8741_snd_controls_mono_right)); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int digidac1_soundcard_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_codec *codec = rtd->codec; -+ struct snd_soc_card *card = rtd->card; -+ struct snd_soc_pcm_runtime *wm8741_rtd; -+ struct snd_soc_codec *wm8741_codec; -+ struct snd_card *sound_card = card->snd_card; -+ struct snd_kcontrol *kctl; -+ int ret; -+ -+ wm8741_rtd = snd_soc_get_pcm_runtime(card, card->dai_link[1].name); -+ if (!wm8741_rtd) { -+ dev_warn(card->dev, "digidac1_soundcard_init: couldn't get wm8741 rtd\n"); -+ return -EFAULT; -+ } -+ wm8741_codec = wm8741_rtd->codec; -+ ret = w8741_add_controls(wm8741_codec); -+ if (ret < 0) -+ dev_warn(card->dev, "Failed to add new wm8741 controls: %d\n", -+ ret); -+ -+ /* enable TX output */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); -+ -+ kctl = snd_soc_card_get_kcontrol(card, -+ "Playback Volume"); -+ if (kctl) { -+ kctl->vd[0].access = SNDRV_CTL_ELEM_ACCESS_READWRITE; -+ snd_ctl_remove(sound_card, kctl); -+ } -+ kctl = snd_soc_card_get_kcontrol(card, -+ "Fine Playback Volume"); -+ if (kctl) { -+ kctl->vd[0].access = SNDRV_CTL_ELEM_ACCESS_READWRITE; -+ snd_ctl_remove(sound_card, kctl); -+ } -+ return 0; -+} -+ -+static int digidac1_soundcard_startup(struct snd_pcm_substream *substream) -+{ -+ /* turn on wm8804 digital output */ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ struct snd_soc_card *card = rtd->card; -+ struct snd_soc_pcm_runtime *wm8741_rtd; -+ struct snd_soc_codec *wm8741_codec; -+ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); -+ wm8741_rtd = snd_soc_get_pcm_runtime(card, card->dai_link[1].name); -+ if (!wm8741_rtd) { -+ dev_warn(card->dev, "digidac1_soundcard_startup: couldn't get WM8741 rtd\n"); -+ return -EFAULT; -+ } -+ wm8741_codec = wm8741_rtd->codec; -+ -+ /* latch wm8741 level */ -+ snd_soc_update_bits(wm8741_codec, WM8741_DACLLSB_ATTENUATION, -+ WM8741_UPDATELL, WM8741_UPDATELL); -+ snd_soc_update_bits(wm8741_codec, WM8741_DACLMSB_ATTENUATION, -+ WM8741_UPDATELM, WM8741_UPDATELM); -+ snd_soc_update_bits(wm8741_codec, WM8741_DACRLSB_ATTENUATION, -+ WM8741_UPDATERL, WM8741_UPDATERL); -+ snd_soc_update_bits(wm8741_codec, WM8741_DACRMSB_ATTENUATION, -+ WM8741_UPDATERM, WM8741_UPDATERM); -+ -+ return 0; -+} -+ -+static void digidac1_soundcard_shutdown(struct snd_pcm_substream *substream) -+{ -+ /* turn off wm8804 digital output */ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); -+} -+ -+static int digidac1_soundcard_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *codec_dai = rtd->codec_dai; -+ struct snd_soc_codec *codec = rtd->codec; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ struct snd_soc_card *card = rtd->card; -+ struct snd_soc_pcm_runtime *wm8741_rtd; -+ struct snd_soc_codec *wm8741_codec; -+ -+ int sysclk = 27000000; -+ long mclk_freq = 0; -+ int mclk_div = 1; -+ int sampling_freq = 1; -+ int ret; -+ -+ wm8741_rtd = snd_soc_get_pcm_runtime(card, card->dai_link[1].name); -+ if (!wm8741_rtd) { -+ dev_warn(card->dev, "digidac1_soundcard_hw_params: couldn't get WM8741 rtd\n"); -+ return -EFAULT; -+ } -+ wm8741_codec = wm8741_rtd->codec; -+ samplerate = params_rate(params); -+ -+ if (samplerate <= 96000) { -+ mclk_freq = samplerate*256; -+ mclk_div = WM8804_MCLKDIV_256FS; -+ } else { -+ mclk_freq = samplerate*128; -+ mclk_div = WM8804_MCLKDIV_128FS; -+ } -+ -+ switch (samplerate) { -+ case 32000: -+ sampling_freq = 0x03; -+ break; -+ case 44100: -+ sampling_freq = 0x00; -+ break; -+ case 48000: -+ sampling_freq = 0x02; -+ break; -+ case 88200: -+ sampling_freq = 0x08; -+ break; -+ case 96000: -+ sampling_freq = 0x0a; -+ break; -+ case 176400: -+ sampling_freq = 0x0c; -+ break; -+ case 192000: -+ sampling_freq = 0x0e; -+ break; -+ default: -+ dev_err(codec->dev, -+ "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", -+ samplerate); -+ } -+ -+ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); -+ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); -+ -+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, -+ sysclk, SND_SOC_CLOCK_OUT); -+ if (ret < 0) { -+ dev_err(codec->dev, -+ "Failed to set WM8804 SYSCLK: %d\n", ret); -+ return ret; -+ } -+ /* Enable wm8804 TX output */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); -+ -+ /* wm8804 Power on */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0); -+ -+ /* wm8804 set sampling frequency status bits */ -+ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); -+ -+ /* Now update wm8741 registers for the correct oversampling */ -+ if (samplerate <= 48000) -+ snd_soc_update_bits(wm8741_codec, WM8741_MODE_CONTROL_1, -+ WM8741_OSR_MASK, 0x00); -+ else if (samplerate <= 96000) -+ snd_soc_update_bits(wm8741_codec, WM8741_MODE_CONTROL_1, -+ WM8741_OSR_MASK, 0x20); -+ else -+ snd_soc_update_bits(wm8741_codec, WM8741_MODE_CONTROL_1, -+ WM8741_OSR_MASK, 0x40); -+ -+ /* wm8741 bit size */ -+ switch (params_width(params)) { -+ case 16: -+ snd_soc_update_bits(wm8741_codec, WM8741_FORMAT_CONTROL, -+ WM8741_IWL_MASK, 0x00); -+ break; -+ case 20: -+ snd_soc_update_bits(wm8741_codec, WM8741_FORMAT_CONTROL, -+ WM8741_IWL_MASK, 0x01); -+ break; -+ case 24: -+ snd_soc_update_bits(wm8741_codec, WM8741_FORMAT_CONTROL, -+ WM8741_IWL_MASK, 0x02); -+ break; -+ case 32: -+ snd_soc_update_bits(wm8741_codec, WM8741_FORMAT_CONTROL, -+ WM8741_IWL_MASK, 0x03); -+ break; -+ default: -+ dev_dbg(codec->dev, "wm8741_hw_params: Unsupported bit size param = %d", -+ params_width(params)); -+ return -EINVAL; -+ } -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); -+} -+/* machine stream operations */ -+static struct snd_soc_ops digidac1_soundcard_ops = { -+ .hw_params = digidac1_soundcard_hw_params, -+ .startup = digidac1_soundcard_startup, -+ .shutdown = digidac1_soundcard_shutdown, -+}; -+ -+static struct snd_soc_dai_link digidac1_soundcard_dai[] = { -+ { -+ .name = "RRA DigiDAC1", -+ .stream_name = "RRA DigiDAC1 HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "wm8804-spdif", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "wm8804.1-003b", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBM_CFM, -+ .ops = &digidac1_soundcard_ops, -+ .init = digidac1_soundcard_init, -+ }, -+ { -+ .name = "RRA DigiDAC11", -+ .stream_name = "RRA DigiDAC11 HiFi", -+ .cpu_dai_name = "wm8804-spdif", -+ .codec_dai_name = "wm8741", -+ .codec_name = "wm8741.1-001a", -+ .dai_fmt = SND_SOC_DAIFMT_I2S -+ | SND_SOC_DAIFMT_NB_NF -+ | SND_SOC_DAIFMT_CBS_CFS, -+ }, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card digidac1_soundcard = { -+ .name = "digidac1-soundcard", -+ .owner = THIS_MODULE, -+ .dai_link = digidac1_soundcard_dai, -+ .num_links = ARRAY_SIZE(digidac1_soundcard_dai), -+}; -+ -+static int digidac1_soundcard_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ digidac1_soundcard.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &digidac1_soundcard_dai[0]; -+ -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ ret = snd_soc_register_card(&digidac1_soundcard); -+ if (ret) -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", -+ ret); -+ -+ return ret; -+} -+ -+static int digidac1_soundcard_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&digidac1_soundcard); -+} -+ -+static const struct of_device_id digidac1_soundcard_of_match[] = { -+ { .compatible = "rra,digidac1-soundcard", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, digidac1_soundcard_of_match); -+ -+static struct platform_driver digidac1_soundcard_driver = { -+ .driver = { -+ .name = "digidac1-audio", -+ .owner = THIS_MODULE, -+ .of_match_table = digidac1_soundcard_of_match, -+ }, -+ .probe = digidac1_soundcard_probe, -+ .remove = digidac1_soundcard_remove, -+}; -+ -+module_platform_driver(digidac1_soundcard_driver); -+ -+MODULE_AUTHOR("José M. Tasende "); -+MODULE_DESCRIPTION("ASoC Driver for RRA DigiDAC1"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0083-Add-support-for-Dion-Audio-LOCO-DAC-AMP-HAT.patch b/target/linux/brcm2708/patches-4.9/0083-Add-support-for-Dion-Audio-LOCO-DAC-AMP-HAT.patch deleted file mode 100644 index 39366abe45..0000000000 --- a/target/linux/brcm2708/patches-4.9/0083-Add-support-for-Dion-Audio-LOCO-DAC-AMP-HAT.patch +++ /dev/null @@ -1,168 +0,0 @@ -From ce97723802a6e68483111819f29d777e0ff0b975 Mon Sep 17 00:00:00 2001 -From: DigitalDreamtime -Date: Sat, 2 Jul 2016 16:26:19 +0100 -Subject: [PATCH] Add support for Dion Audio LOCO DAC-AMP HAT - -Using dedicated machine driver and pcm5102a codec driver. - -Signed-off-by: DigitalDreamtime ---- - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 3 +- - sound/soc/bcm/dionaudio_loco.c | 121 +++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 130 insertions(+), 1 deletion(-) - create mode 100644 sound/soc/bcm/dionaudio_loco.c - ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -109,3 +109,10 @@ config SND_DIGIDAC1_SOUNDCARD - select SND_SOC_WM8741 - help - Say Y or M if you want to add support for Red Rocks Audio DigiDAC1 board. -+ -+config SND_BCM2708_SOC_DIONAUDIO_LOCO -+ tristate "Support for Dion Audio LOCO DAC-AMP" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_PCM5102a -+ help -+ Say Y or M if you want to add support for Dion Audio LOCO. ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -22,6 +22,7 @@ snd-soc-iqaudio-digi-objs := iqaudio_dig - snd-soc-raspidac3-objs := raspidac3.o - snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o - snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o -+snd-soc-dionaudio-loco-objs := dionaudio_loco.o - - obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -36,4 +37,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIG - obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o - obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o - obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o -- -+obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o ---- /dev/null -+++ b/sound/soc/bcm/dionaudio_loco.c -@@ -0,0 +1,121 @@ -+/* -+ * ASoC Driver for Dion Audio LOCO DAC-AMP -+ * -+ * Author: Miquel Blauw -+ * Copyright 2016 -+ * -+ * Based on the software of the RPi-DAC writen by Florian Meier -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static int snd_rpi_dionaudio_loco_hw_params( -+ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ unsigned int sample_bits = -+ snd_pcm_format_physical_width(params_format(params)); -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_dionaudio_loco_ops = { -+ .hw_params = snd_rpi_dionaudio_loco_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_dionaudio_loco_dai[] = { -+{ -+ .name = "DionAudio LOCO", -+ .stream_name = "DionAudio LOCO DAC-AMP", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm5102a-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm5102a-codec", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_dionaudio_loco_ops, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_dionaudio_loco = { -+ .name = "snd_rpi_dionaudio_loco", -+ .dai_link = snd_rpi_dionaudio_loco_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_dionaudio_loco_dai), -+}; -+ -+static int snd_rpi_dionaudio_loco_probe(struct platform_device *pdev) -+{ -+ struct device_node *np; -+ int ret = 0; -+ -+ snd_rpi_dionaudio_loco.dev = &pdev->dev; -+ -+ np = pdev->dev.of_node; -+ if (np) { -+ struct snd_soc_dai_link *dai = &snd_rpi_dionaudio_loco_dai[0]; -+ struct device_node *i2s_np; -+ -+ i2s_np = of_parse_phandle(np, "i2s-controller", 0); -+ if (i2s_np) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_np; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_np; -+ } -+ } -+ -+ ret = snd_soc_register_card(&snd_rpi_dionaudio_loco); -+ if (ret) -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", -+ ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_dionaudio_loco_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_dionaudio_loco); -+} -+ -+static const struct of_device_id snd_rpi_dionaudio_loco_of_match[] = { -+ { .compatible = "dionaudio,loco-pcm5242-tpa3118", }, -+ { /* sentinel */ }, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_dionaudio_loco_of_match); -+ -+static struct platform_driver snd_rpi_dionaudio_loco_driver = { -+ .driver = { -+ .name = "snd-dionaudio-loco", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_dionaudio_loco_of_match, -+ }, -+ .probe = snd_rpi_dionaudio_loco_probe, -+ .remove = snd_rpi_dionaudio_loco_remove, -+}; -+ -+module_platform_driver(snd_rpi_dionaudio_loco_driver); -+ -+MODULE_AUTHOR("Miquel Blauw "); -+MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0083-Allo-Piano-DAC-boards-Initial-2-channel-stereo-suppo.patch b/target/linux/brcm2708/patches-4.9/0083-Allo-Piano-DAC-boards-Initial-2-channel-stereo-suppo.patch new file mode 100644 index 0000000000..64e785d2a6 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0083-Allo-Piano-DAC-boards-Initial-2-channel-stereo-suppo.patch @@ -0,0 +1,202 @@ +From 779409817cf1af2c38055af64c11e026cb0bb4e9 Mon Sep 17 00:00:00 2001 +From: Clive Messer +Date: Mon, 19 Sep 2016 14:01:04 +0100 +Subject: [PATCH] Allo Piano DAC boards: Initial 2 channel (stereo) support + (#1645) + +Add initial 2 channel (stereo) support for Allo Piano DAC (2.0/2.1) boards, +using allo-piano-dac-pcm512x-audio overlay and allo-piano-dac ALSA ASoC +machine driver. + +NB. The initial support is 2 channel (stereo) ONLY! +(The Piano DAC 2.1 will only support 2 channel (stereo) left/right output, + pending an update to the upstream pcm512x codec driver, which will have + to be submitted via upstream. With the initial downstream support, + provided by this patch, the Piano DAC 2.1 subwoofer outputs will + not function.) + +Signed-off-by: Baswaraj K +Signed-off-by: Clive Messer +Tested-by: Clive Messer +--- + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/allo-piano-dac.c | 144 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 153 insertions(+) + create mode 100644 sound/soc/bcm/allo-piano-dac.c + +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -123,3 +123,10 @@ config SND_BCM2708_SOC_DIONAUDIO_LOCO + select SND_SOC_PCM5102a + help + Say Y or M if you want to add support for Dion Audio LOCO. ++ ++config SND_BCM2708_SOC_ALLO_PIANO_DAC ++ tristate "Support for Allo Piano DAC" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM512x_I2C ++ help ++ Say Y or M if you want to add support for Allo Piano DAC. +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -24,6 +24,7 @@ snd-soc-raspidac3-objs := raspidac3.o + snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o + snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o + snd-soc-dionaudio-loco-objs := dionaudio_loco.o ++snd-soc-allo-piano-dac-objs := allo-piano-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o +@@ -40,3 +41,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) + obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o + obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o + obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o ++obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o +--- /dev/null ++++ b/sound/soc/bcm/allo-piano-dac.c +@@ -0,0 +1,144 @@ ++/* ++ * ALSA ASoC Machine Driver for Allo Piano DAC ++ * ++ * Author: Baswaraj K ++ * Copyright 2016 ++ * based on code by Daniel Matuschek ++ * based on code by Florian Meier ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++static bool digital_gain_0db_limit = true; ++ ++static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ if (digital_gain_0db_limit) { ++ int ret; ++ struct snd_soc_card *card = rtd->card; ++ ++ ret = snd_soc_limit_volume(card, "Digital Playback Volume", ++ 207); ++ if (ret < 0) ++ dev_warn(card->dev, "Failed to set volume limit: %d\n", ++ ret); ++ } ++ ++ return 0; ++} ++ ++static int snd_allo_piano_dac_hw_params( ++ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ unsigned int sample_bits = ++ snd_pcm_format_physical_width(params_format(params)); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_allo_piano_dac_ops = { ++ .hw_params = snd_allo_piano_dac_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_allo_piano_dac_dai[] = { ++{ ++ .name = "Piano DAC", ++ .stream_name = "Piano DAC HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm512x-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm512x.1-004c", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_allo_piano_dac_ops, ++ .init = snd_allo_piano_dac_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_allo_piano_dac = { ++ .name = "PianoDAC", ++ .owner = THIS_MODULE, ++ .dai_link = snd_allo_piano_dac_dai, ++ .num_links = ARRAY_SIZE(snd_allo_piano_dac_dai), ++}; ++ ++static int snd_allo_piano_dac_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_allo_piano_dac.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai; ++ ++ dai = &snd_allo_piano_dac_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ ++ digital_gain_0db_limit = !of_property_read_bool( ++ pdev->dev.of_node, "allo,24db_digital_gain"); ++ } ++ ++ ret = snd_soc_register_card(&snd_allo_piano_dac); ++ if (ret) ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_allo_piano_dac_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_allo_piano_dac); ++} ++ ++static const struct of_device_id snd_allo_piano_dac_of_match[] = { ++ { .compatible = "allo,piano-dac", }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, snd_allo_piano_dac_of_match); ++ ++static struct platform_driver snd_allo_piano_dac_driver = { ++ .driver = { ++ .name = "snd-allo-piano-dac", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_allo_piano_dac_of_match, ++ }, ++ .probe = snd_allo_piano_dac_probe, ++ .remove = snd_allo_piano_dac_remove, ++}; ++ ++module_platform_driver(snd_allo_piano_dac_driver); ++ ++MODULE_AUTHOR("Baswaraj K "); ++MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Piano DAC"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0084-Allo-Piano-DAC-boards-Initial-2-channel-stereo-suppo.patch b/target/linux/brcm2708/patches-4.9/0084-Allo-Piano-DAC-boards-Initial-2-channel-stereo-suppo.patch deleted file mode 100644 index 7455fa92da..0000000000 --- a/target/linux/brcm2708/patches-4.9/0084-Allo-Piano-DAC-boards-Initial-2-channel-stereo-suppo.patch +++ /dev/null @@ -1,202 +0,0 @@ -From 203501a533e71e5f76f9e06c0f0b8bfb0fc27147 Mon Sep 17 00:00:00 2001 -From: Clive Messer -Date: Mon, 19 Sep 2016 14:01:04 +0100 -Subject: [PATCH] Allo Piano DAC boards: Initial 2 channel (stereo) support - (#1645) - -Add initial 2 channel (stereo) support for Allo Piano DAC (2.0/2.1) boards, -using allo-piano-dac-pcm512x-audio overlay and allo-piano-dac ALSA ASoC -machine driver. - -NB. The initial support is 2 channel (stereo) ONLY! -(The Piano DAC 2.1 will only support 2 channel (stereo) left/right output, - pending an update to the upstream pcm512x codec driver, which will have - to be submitted via upstream. With the initial downstream support, - provided by this patch, the Piano DAC 2.1 subwoofer outputs will - not function.) - -Signed-off-by: Baswaraj K -Signed-off-by: Clive Messer -Tested-by: Clive Messer ---- - sound/soc/bcm/Kconfig | 7 ++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/allo-piano-dac.c | 144 +++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 153 insertions(+) - create mode 100644 sound/soc/bcm/allo-piano-dac.c - ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -116,3 +116,10 @@ config SND_BCM2708_SOC_DIONAUDIO_LOCO - select SND_SOC_PCM5102a - help - Say Y or M if you want to add support for Dion Audio LOCO. -+ -+config SND_BCM2708_SOC_ALLO_PIANO_DAC -+ tristate "Support for Allo Piano DAC" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_PCM512x_I2C -+ help -+ Say Y or M if you want to add support for Allo Piano DAC. ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -23,6 +23,7 @@ snd-soc-raspidac3-objs := raspidac3.o - snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o - snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o - snd-soc-dionaudio-loco-objs := dionaudio_loco.o -+snd-soc-allo-piano-dac-objs := allo-piano-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -38,3 +39,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) - obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o - obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o - obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o -+obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o ---- /dev/null -+++ b/sound/soc/bcm/allo-piano-dac.c -@@ -0,0 +1,144 @@ -+/* -+ * ALSA ASoC Machine Driver for Allo Piano DAC -+ * -+ * Author: Baswaraj K -+ * Copyright 2016 -+ * based on code by Daniel Matuschek -+ * based on code by Florian Meier -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+static bool digital_gain_0db_limit = true; -+ -+static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ if (digital_gain_0db_limit) { -+ int ret; -+ struct snd_soc_card *card = rtd->card; -+ -+ ret = snd_soc_limit_volume(card, "Digital Playback Volume", -+ 207); -+ if (ret < 0) -+ dev_warn(card->dev, "Failed to set volume limit: %d\n", -+ ret); -+ } -+ -+ return 0; -+} -+ -+static int snd_allo_piano_dac_hw_params( -+ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ unsigned int sample_bits = -+ snd_pcm_format_physical_width(params_format(params)); -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_allo_piano_dac_ops = { -+ .hw_params = snd_allo_piano_dac_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_allo_piano_dac_dai[] = { -+{ -+ .name = "Piano DAC", -+ .stream_name = "Piano DAC HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm512x-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm512x.1-004c", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_allo_piano_dac_ops, -+ .init = snd_allo_piano_dac_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_allo_piano_dac = { -+ .name = "PianoDAC", -+ .owner = THIS_MODULE, -+ .dai_link = snd_allo_piano_dac_dai, -+ .num_links = ARRAY_SIZE(snd_allo_piano_dac_dai), -+}; -+ -+static int snd_allo_piano_dac_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_allo_piano_dac.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai; -+ -+ dai = &snd_allo_piano_dac_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ -+ digital_gain_0db_limit = !of_property_read_bool( -+ pdev->dev.of_node, "allo,24db_digital_gain"); -+ } -+ -+ ret = snd_soc_register_card(&snd_allo_piano_dac); -+ if (ret) -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_allo_piano_dac_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_allo_piano_dac); -+} -+ -+static const struct of_device_id snd_allo_piano_dac_of_match[] = { -+ { .compatible = "allo,piano-dac", }, -+ { /* sentinel */ }, -+}; -+MODULE_DEVICE_TABLE(of, snd_allo_piano_dac_of_match); -+ -+static struct platform_driver snd_allo_piano_dac_driver = { -+ .driver = { -+ .name = "snd-allo-piano-dac", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_allo_piano_dac_of_match, -+ }, -+ .probe = snd_allo_piano_dac_probe, -+ .remove = snd_allo_piano_dac_remove, -+}; -+ -+module_platform_driver(snd_allo_piano_dac_driver); -+ -+MODULE_AUTHOR("Baswaraj K "); -+MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Piano DAC"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0084-Support-for-Blokas-Labs-pisound-board.patch b/target/linux/brcm2708/patches-4.9/0084-Support-for-Blokas-Labs-pisound-board.patch new file mode 100644 index 0000000000..21f43347b3 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0084-Support-for-Blokas-Labs-pisound-board.patch @@ -0,0 +1,1168 @@ +From 7d8efd6f3198fd3dafe5a74003616a2aea5dc6c5 Mon Sep 17 00:00:00 2001 +From: gtrainavicius +Date: Sun, 23 Oct 2016 12:06:53 +0300 +Subject: [PATCH] Support for Blokas Labs pisound board + +Pisound dynamic overlay (#1760) + +Restructuring pisound-overlay.dts, so it can be loaded and unloaded dynamically using dtoverlay. + +Print a logline when the kernel module is removed. +--- + .../devicetree/bindings/vendor-prefixes.txt | 1 + + arch/arm/boot/dts/overlays/pisound-overlay.dts | 94 +- + sound/soc/bcm/Kconfig | 6 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/pisound.c | 989 +++++++++++++++++++++ + 5 files changed, 1048 insertions(+), 44 deletions(-) + create mode 100644 sound/soc/bcm/pisound.c + +--- a/Documentation/devicetree/bindings/vendor-prefixes.txt ++++ b/Documentation/devicetree/bindings/vendor-prefixes.txt +@@ -40,6 +40,7 @@ auvidea Auvidea GmbH + avago Avago Technologies + avic Shanghai AVIC Optoelectronics Co., Ltd. + axis Axis Communications AB ++blokaslabs Vilniaus Blokas UAB + boe BOE Technology Group Co., Ltd. + bosch Bosch Sensortec GmbH + boundary Boundary Devices Inc. +--- a/arch/arm/boot/dts/overlays/pisound-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts +@@ -26,6 +26,54 @@ + compatible = "brcm,bcm2708"; + + fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spidev0>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spidev1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&spi0>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pisound_spi: pisound_spi@0{ ++ compatible = "blokaslabs,pisound-spi"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins>; ++ spi-max-frequency = <1000000>; ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target-path = "/"; ++ __overlay__ { ++ pcm5102a-codec { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5102a"; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@5 { + target = <&sound>; + __overlay__ { + compatible = "blokaslabs,pisound"; +@@ -49,7 +97,7 @@ + }; + }; + +- fragment@1 { ++ fragment@6 { + target = <&gpio>; + __overlay__ { + pinctrl-names = "default"; +@@ -63,52 +111,10 @@ + }; + }; + +- fragment@2 { ++ fragment@7 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; +- +- fragment@3 { +- target-path = "/"; +- __overlay__ { +- pcm5102a-codec { +- #sound-dai-cells = <0>; +- compatible = "ti,pcm5102a"; +- status = "okay"; +- }; +- }; +- }; +- +- fragment@4 { +- target = <&spi0>; +- __overlay__ { +- status = "okay"; +- +- spidev@0{ +- status = "disabled"; +- }; +- +- spidev@1{ +- status = "okay"; +- }; +- }; +- }; +- +- fragment@5 { +- target = <&spi0>; +- __overlay__ { +- #address-cells = <1>; +- #size-cells = <0>; +- +- pisound_spi: pisound_spi@0{ +- compatible = "blokaslabs,pisound-spi"; +- reg = <0>; +- pinctrl-names = "default"; +- pinctrl-0 = <&spi0_pins>; +- spi-max-frequency = <1000000>; +- }; +- }; +- }; + }; +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -130,3 +130,9 @@ config SND_BCM2708_SOC_ALLO_PIANO_DAC + select SND_SOC_PCM512x_I2C + help + Say Y or M if you want to add support for Allo Piano DAC. ++ ++config SND_PISOUND ++ tristate "Support for Blokas Labs pisound" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ help ++ Say Y or M if you want to add support for Blokas Labs pisound. +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -25,6 +25,7 @@ snd-soc-audioinjector-pi-soundcard-objs + snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o + snd-soc-dionaudio-loco-objs := dionaudio_loco.o + snd-soc-allo-piano-dac-objs := allo-piano-dac.o ++snd-soc-pisound-objs := pisound.o + + obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o +@@ -42,3 +43,4 @@ obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDC + obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o + obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o + obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o ++obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o +--- /dev/null ++++ b/sound/soc/bcm/pisound.c +@@ -0,0 +1,989 @@ ++/* ++ * pisound Linux kernel module. ++ * Copyright (C) 2016 Vilniaus Blokas UAB, http://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 ++ * as published by the Free Software Foundation; version 2 of the ++ * License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, ++ * MA 02110-1301, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int pisnd_spi_init(struct device *dev); ++static void pisnd_spi_uninit(void); ++ ++static void pisnd_spi_send(uint8_t val); ++static uint8_t pisnd_spi_recv(uint8_t *buffer, uint8_t length); ++ ++typedef void (*pisnd_spi_recv_cb)(void *data); ++static void pisnd_spi_set_callback(pisnd_spi_recv_cb cb, void *data); ++ ++static const char *pisnd_spi_get_serial(void); ++static const char *pisnd_spi_get_id(void); ++static const char *pisnd_spi_get_version(void); ++ ++static int pisnd_midi_init(struct snd_card *card); ++static void pisnd_midi_uninit(void); ++ ++#define PISOUND_LOG_PREFIX "pisound: " ++ ++#ifdef DEBUG ++# define printd(...) pr_alert(PISOUND_LOG_PREFIX __VA_ARGS__) ++#else ++# define printd(...) do {} while (0) ++#endif ++ ++#define printe(...) pr_err(PISOUND_LOG_PREFIX __VA_ARGS__) ++#define printi(...) pr_info(PISOUND_LOG_PREFIX __VA_ARGS__) ++ ++static int pisnd_output_open(struct snd_rawmidi_substream *substream) ++{ ++ return 0; ++} ++ ++static int pisnd_output_close(struct snd_rawmidi_substream *substream) ++{ ++ return 0; ++} ++ ++static void pisnd_output_trigger( ++ struct snd_rawmidi_substream *substream, ++ int up ++ ) ++{ ++ uint8_t data; ++ ++ if (!up) ++ return; ++ ++ while (snd_rawmidi_transmit_peek(substream, &data, 1)) { ++ pisnd_spi_send(data); ++ snd_rawmidi_transmit_ack(substream, 1); ++ } ++} ++ ++static void pisnd_output_drain(struct snd_rawmidi_substream *substream) ++{ ++ uint8_t data; ++ ++ while (snd_rawmidi_transmit_peek(substream, &data, 1)) { ++ pisnd_spi_send(data); ++ ++ snd_rawmidi_transmit_ack(substream, 1); ++ } ++} ++ ++static int pisnd_input_open(struct snd_rawmidi_substream *substream) ++{ ++ return 0; ++} ++ ++static int pisnd_input_close(struct snd_rawmidi_substream *substream) ++{ ++ return 0; ++} ++ ++static void pisnd_midi_recv_callback(void *substream) ++{ ++ uint8_t data[128]; ++ uint8_t n = 0; ++ ++ while ((n = pisnd_spi_recv(data, sizeof(data)))) { ++ int res = snd_rawmidi_receive(substream, data, n); ++ (void)res; ++ printd("midi recv 0x%02x, res = %d\n", data, res); ++ } ++} ++ ++static void pisnd_input_trigger(struct snd_rawmidi_substream *substream, int up) ++{ ++ if (up) { ++ pisnd_spi_set_callback(pisnd_midi_recv_callback, substream); ++ pisnd_midi_recv_callback(substream); ++ } else { ++ pisnd_spi_set_callback(NULL, NULL); ++ } ++} ++ ++static struct snd_rawmidi *g_rmidi; ++ ++static struct snd_rawmidi_ops pisnd_output_ops = { ++ .open = pisnd_output_open, ++ .close = pisnd_output_close, ++ .trigger = pisnd_output_trigger, ++ .drain = pisnd_output_drain, ++}; ++ ++static struct snd_rawmidi_ops pisnd_input_ops = { ++ .open = pisnd_input_open, ++ .close = pisnd_input_close, ++ .trigger = pisnd_input_trigger, ++}; ++ ++static void pisnd_get_port_info( ++ struct snd_rawmidi *rmidi, ++ int number, ++ struct snd_seq_port_info *seq_port_info ++ ) ++{ ++ seq_port_info->type = ++ SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | ++ SNDRV_SEQ_PORT_TYPE_HARDWARE | ++ SNDRV_SEQ_PORT_TYPE_PORT; ++ seq_port_info->midi_voices = 0; ++} ++ ++static struct snd_rawmidi_global_ops pisnd_global_ops = { ++ .get_port_info = pisnd_get_port_info, ++}; ++ ++static int pisnd_midi_init(struct snd_card *card) ++{ ++ int err = snd_rawmidi_new(card, "pisound MIDI", 0, 1, 1, &g_rmidi); ++ ++ if (err < 0) { ++ printe("snd_rawmidi_new failed: %d\n", err); ++ return err; ++ } ++ ++ strcpy(g_rmidi->name, "pisound MIDI "); ++ strcat(g_rmidi->name, pisnd_spi_get_serial()); ++ ++ g_rmidi->info_flags = ++ SNDRV_RAWMIDI_INFO_OUTPUT | ++ SNDRV_RAWMIDI_INFO_INPUT | ++ SNDRV_RAWMIDI_INFO_DUPLEX; ++ ++ g_rmidi->ops = &pisnd_global_ops; ++ ++ g_rmidi->private_data = (void *)0; ++ ++ snd_rawmidi_set_ops( ++ g_rmidi, ++ SNDRV_RAWMIDI_STREAM_OUTPUT, ++ &pisnd_output_ops ++ ); ++ ++ snd_rawmidi_set_ops( ++ g_rmidi, ++ SNDRV_RAWMIDI_STREAM_INPUT, ++ &pisnd_input_ops ++ ); ++ ++ return 0; ++} ++ ++static void pisnd_midi_uninit(void) ++{ ++} ++ ++static void *g_recvData; ++static pisnd_spi_recv_cb g_recvCallback; ++ ++#define FIFO_SIZE 512 ++ ++static char g_serial_num[11]; ++static char g_id[25]; ++static char g_version[5]; ++ ++DEFINE_KFIFO(spi_fifo_in, uint8_t, FIFO_SIZE); ++DEFINE_KFIFO(spi_fifo_out, uint8_t, FIFO_SIZE); ++ ++static struct gpio_desc *data_available; ++static struct gpio_desc *spi_reset; ++ ++static struct spi_device *pisnd_spi_device; ++ ++static struct workqueue_struct *pisnd_workqueue; ++static struct work_struct pisnd_work_process; ++ ++static void pisnd_work_handler(struct work_struct *work); ++ ++static uint16_t spi_transfer16(uint16_t val); ++ ++static int pisnd_init_workqueues(void) ++{ ++ pisnd_workqueue = create_singlethread_workqueue("pisnd_workqueue"); ++ INIT_WORK(&pisnd_work_process, pisnd_work_handler); ++ ++ return 0; ++} ++ ++static void pisnd_uninit_workqueues(void) ++{ ++ flush_workqueue(pisnd_workqueue); ++ destroy_workqueue(pisnd_workqueue); ++ ++ pisnd_workqueue = NULL; ++} ++ ++static bool pisnd_spi_has_more(void) ++{ ++ return gpiod_get_value(data_available); ++} ++ ++enum task_e { ++ TASK_PROCESS = 0, ++}; ++ ++static void pisnd_schedule_process(enum task_e task) ++{ ++ if (pisnd_spi_device != NULL && ++ pisnd_workqueue != NULL && ++ !work_pending(&pisnd_work_process) ++ ) { ++ printd("schedule: has more = %d\n", pisnd_spi_has_more()); ++ if (task == TASK_PROCESS) ++ queue_work(pisnd_workqueue, &pisnd_work_process); ++ } ++} ++ ++static irqreturn_t data_available_interrupt_handler(int irq, void *dev_id) ++{ ++ if (irq == gpiod_to_irq(data_available) && pisnd_spi_has_more()) { ++ printd("schedule from irq\n"); ++ pisnd_schedule_process(TASK_PROCESS); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static DEFINE_SPINLOCK(spilock); ++static unsigned long spilockflags; ++ ++static uint16_t spi_transfer16(uint16_t val) ++{ ++ int err; ++ struct spi_transfer transfer; ++ struct spi_message msg; ++ uint8_t txbuf[2]; ++ uint8_t rxbuf[2]; ++ ++ if (!pisnd_spi_device) { ++ printe("pisnd_spi_device null, returning\n"); ++ return 0; ++ } ++ ++ spi_message_init(&msg); ++ ++ memset(&transfer, 0, sizeof(transfer)); ++ memset(&rxbuf, 0, sizeof(rxbuf)); ++ ++ txbuf[0] = val >> 8; ++ txbuf[1] = val & 0xff; ++ ++ transfer.tx_buf = &txbuf; ++ transfer.rx_buf = &rxbuf; ++ transfer.len = sizeof(txbuf); ++ transfer.speed_hz = 125000; ++ transfer.delay_usecs = 100; ++ spi_message_add_tail(&transfer, &msg); ++ ++ spin_lock_irqsave(&spilock, spilockflags); ++ err = spi_sync(pisnd_spi_device, &msg); ++ spin_unlock_irqrestore(&spilock, spilockflags); ++ ++ if (err < 0) { ++ printe("spi_sync error %d\n", err); ++ return 0; ++ } ++ ++ printd("received: %02x%02x\n", rxbuf[0], rxbuf[1]); ++ printd("hasMore %d\n", pisnd_spi_has_more()); ++ ++ return (rxbuf[0] << 8) | rxbuf[1]; ++} ++ ++static int spi_read_bytes(char *dst, size_t length, uint8_t *bytesRead) ++{ ++ uint16_t rx; ++ uint8_t size; ++ uint8_t i; ++ ++ memset(dst, 0, length); ++ *bytesRead = 0; ++ ++ rx = spi_transfer16(0); ++ if (!(rx >> 8)) ++ return -EINVAL; ++ ++ size = rx & 0xff; ++ ++ if (size > length) ++ return -EINVAL; ++ ++ for (i = 0; i < size; ++i) { ++ rx = spi_transfer16(0); ++ if (!(rx >> 8)) ++ return -EINVAL; ++ ++ dst[i] = rx & 0xff; ++ } ++ ++ *bytesRead = i; ++ ++ return 0; ++} ++ ++static int spi_device_match(struct device *dev, void *data) ++{ ++ struct spi_device *spi = container_of(dev, struct spi_device, dev); ++ ++ printd(" %s %s %dkHz %d bits mode=0x%02X\n", ++ spi->modalias, dev_name(dev), spi->max_speed_hz/1000, ++ spi->bits_per_word, spi->mode); ++ ++ if (strcmp("pisound-spi", spi->modalias) == 0) { ++ printi("\tFound!\n"); ++ return 1; ++ } ++ ++ printe("\tNot found!\n"); ++ return 0; ++} ++ ++static struct spi_device *pisnd_spi_find_device(void) ++{ ++ struct device *dev; ++ ++ printi("Searching for spi device...\n"); ++ dev = bus_find_device(&spi_bus_type, NULL, NULL, spi_device_match); ++ if (dev != NULL) ++ return container_of(dev, struct spi_device, dev); ++ else ++ return NULL; ++} ++ ++static void pisnd_work_handler(struct work_struct *work) ++{ ++ uint16_t rx; ++ uint16_t tx; ++ uint8_t val; ++ ++ if (work == &pisnd_work_process) { ++ if (pisnd_spi_device == NULL) ++ return; ++ ++ do { ++ val = 0; ++ tx = 0; ++ ++ if (kfifo_get(&spi_fifo_out, &val)) ++ tx = 0x0f00 | val; ++ ++ rx = spi_transfer16(tx); ++ ++ if (rx & 0xff00) { ++ kfifo_put(&spi_fifo_in, rx & 0xff); ++ if (kfifo_len(&spi_fifo_in) > 16 ++ && g_recvCallback) ++ g_recvCallback(g_recvData); ++ } ++ } while (rx != 0 ++ || !kfifo_is_empty(&spi_fifo_out) ++ || pisnd_spi_has_more() ++ ); ++ ++ if (!kfifo_is_empty(&spi_fifo_in) && g_recvCallback) ++ g_recvCallback(g_recvData); ++ } ++} ++ ++static int pisnd_spi_gpio_init(struct device *dev) ++{ ++ spi_reset = gpiod_get_index(dev, "reset", 1, GPIOD_ASIS); ++ data_available = gpiod_get_index(dev, "data_available", 0, GPIOD_ASIS); ++ ++ gpiod_direction_output(spi_reset, 1); ++ gpiod_direction_input(data_available); ++ ++ /* Reset the slave. */ ++ gpiod_set_value(spi_reset, false); ++ mdelay(1); ++ gpiod_set_value(spi_reset, true); ++ ++ /* Give time for spi slave to start. */ ++ mdelay(64); ++ ++ return 0; ++} ++ ++static void pisnd_spi_gpio_uninit(void) ++{ ++ gpiod_set_value(spi_reset, false); ++ gpiod_put(spi_reset); ++ spi_reset = NULL; ++ ++ gpiod_put(data_available); ++ data_available = NULL; ++} ++ ++static int pisnd_spi_gpio_irq_init(struct device *dev) ++{ ++ return request_irq( ++ gpiod_to_irq(data_available), ++ data_available_interrupt_handler, ++ IRQF_TIMER | IRQF_TRIGGER_RISING, ++ "data_available_int", ++ NULL ++ ); ++} ++ ++static void pisnd_spi_gpio_irq_uninit(void) ++{ ++ free_irq(gpiod_to_irq(data_available), NULL); ++} ++ ++static int spi_read_info(void) ++{ ++ uint16_t tmp; ++ uint8_t count; ++ uint8_t n; ++ uint8_t i; ++ uint8_t j; ++ char buffer[257]; ++ int ret; ++ char *p; ++ ++ memset(g_serial_num, 0, sizeof(g_serial_num)); ++ memset(g_version, 0, sizeof(g_version)); ++ memset(g_id, 0, sizeof(g_id)); ++ ++ tmp = spi_transfer16(0); ++ ++ if (!(tmp >> 8)) ++ return -EINVAL; ++ ++ count = tmp & 0xff; ++ ++ for (i = 0; i < count; ++i) { ++ memset(buffer, 0, sizeof(buffer)); ++ ret = spi_read_bytes(buffer, sizeof(buffer)-1, &n); ++ ++ if (ret < 0) ++ return ret; ++ ++ switch (i) { ++ case 0: ++ if (n != 2) ++ return -EINVAL; ++ ++ snprintf( ++ g_version, ++ sizeof(g_version), ++ "%x.%02x", ++ buffer[0], ++ buffer[1] ++ ); ++ break; ++ case 1: ++ if (n >= sizeof(g_serial_num)) ++ return -EINVAL; ++ ++ memcpy(g_serial_num, buffer, sizeof(g_serial_num)); ++ break; ++ case 2: ++ { ++ if (n >= sizeof(g_id)) ++ return -EINVAL; ++ ++ p = g_id; ++ for (j = 0; j < n; ++j) ++ p += sprintf(p, "%02x", buffer[j]); ++ } ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++static int pisnd_spi_init(struct device *dev) ++{ ++ int ret; ++ struct spi_device *spi; ++ ++ memset(g_serial_num, 0, sizeof(g_serial_num)); ++ memset(g_id, 0, sizeof(g_id)); ++ memset(g_version, 0, sizeof(g_version)); ++ ++ spi = pisnd_spi_find_device(); ++ ++ if (spi != NULL) { ++ printd("initializing spi!\n"); ++ pisnd_spi_device = spi; ++ ret = spi_setup(pisnd_spi_device); ++ } else { ++ printe("SPI device not found, deferring!\n"); ++ return -EPROBE_DEFER; ++ } ++ ++ ret = pisnd_spi_gpio_init(dev); ++ ++ if (ret < 0) { ++ printe("SPI GPIO init failed: %d\n", ret); ++ spi_dev_put(pisnd_spi_device); ++ pisnd_spi_device = NULL; ++ pisnd_spi_gpio_uninit(); ++ return ret; ++ } ++ ++ ret = spi_read_info(); ++ ++ if (ret < 0) { ++ printe("Reading card info failed: %d\n", ret); ++ spi_dev_put(pisnd_spi_device); ++ pisnd_spi_device = NULL; ++ pisnd_spi_gpio_uninit(); ++ return ret; ++ } ++ ++ /* Flash the LEDs. */ ++ spi_transfer16(0xf000); ++ ++ ret = pisnd_spi_gpio_irq_init(dev); ++ if (ret < 0) { ++ printe("SPI irq request failed: %d\n", ret); ++ spi_dev_put(pisnd_spi_device); ++ pisnd_spi_device = NULL; ++ pisnd_spi_gpio_irq_uninit(); ++ pisnd_spi_gpio_uninit(); ++ } ++ ++ ret = pisnd_init_workqueues(); ++ if (ret != 0) { ++ printe("Workqueue initialization failed: %d\n", ret); ++ spi_dev_put(pisnd_spi_device); ++ pisnd_spi_device = NULL; ++ pisnd_spi_gpio_irq_uninit(); ++ pisnd_spi_gpio_uninit(); ++ pisnd_uninit_workqueues(); ++ return ret; ++ } ++ ++ if (pisnd_spi_has_more()) { ++ printd("data is available, scheduling from init\n"); ++ pisnd_schedule_process(TASK_PROCESS); ++ } ++ ++ return 0; ++} ++ ++static void pisnd_spi_uninit(void) ++{ ++ pisnd_uninit_workqueues(); ++ ++ spi_dev_put(pisnd_spi_device); ++ pisnd_spi_device = NULL; ++ ++ pisnd_spi_gpio_irq_uninit(); ++ pisnd_spi_gpio_uninit(); ++} ++ ++static void pisnd_spi_send(uint8_t val) ++{ ++ kfifo_put(&spi_fifo_out, val); ++ printd("schedule from spi_send\n"); ++ pisnd_schedule_process(TASK_PROCESS); ++} ++ ++static uint8_t pisnd_spi_recv(uint8_t *buffer, uint8_t length) ++{ ++ return kfifo_out(&spi_fifo_in, buffer, length); ++} ++ ++static void pisnd_spi_set_callback(pisnd_spi_recv_cb cb, void *data) ++{ ++ g_recvData = data; ++ g_recvCallback = cb; ++} ++ ++static const char *pisnd_spi_get_serial(void) ++{ ++ if (strlen(g_serial_num)) ++ return g_serial_num; ++ ++ return ""; ++} ++ ++static const char *pisnd_spi_get_id(void) ++{ ++ if (strlen(g_id)) ++ return g_id; ++ ++ return ""; ++} ++ ++static const char *pisnd_spi_get_version(void) ++{ ++ if (strlen(g_version)) ++ return g_version; ++ ++ return ""; ++} ++ ++static const struct of_device_id pisound_of_match[] = { ++ { .compatible = "blokaslabs,pisound", }, ++ { .compatible = "blokaslabs,pisound-spi", }, ++ {}, ++}; ++ ++static struct gpio_desc *osr0, *osr1, *osr2; ++static struct gpio_desc *reset; ++static struct gpio_desc *button; ++ ++static int pisnd_hw_params( ++ struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params ++ ) ++{ ++ printd("rate = %d\n", params_rate(params)); ++ printd("ch = %d\n", params_channels(params)); ++ printd("bits = %u\n", ++ snd_pcm_format_physical_width(params_format(params))); ++ printd("format = %d\n", params_format(params)); ++ ++ gpiod_set_value(reset, false); ++ ++ switch (params_rate(params)) { ++ case 48000: ++ gpiod_set_value(osr0, true); ++ gpiod_set_value(osr1, false); ++ gpiod_set_value(osr2, false); ++ break; ++ case 96000: ++ gpiod_set_value(osr0, true); ++ gpiod_set_value(osr1, true); ++ gpiod_set_value(osr2, false); ++ break; ++ case 192000: ++ gpiod_set_value(osr0, true); ++ gpiod_set_value(osr1, true); ++ gpiod_set_value(osr2, true); ++ break; ++ default: ++ printe("Unsupported rate %u!\n", params_rate(params)); ++ return -EINVAL; ++ } ++ ++ gpiod_set_value(reset, true); ++ ++ return 0; ++} ++ ++static unsigned int rates[3] = { ++ 48000, 96000, 192000 ++}; ++ ++static struct snd_pcm_hw_constraint_list constraints_rates = { ++ .count = ARRAY_SIZE(rates), ++ .list = rates, ++ .mask = 0, ++}; ++ ++static unsigned int sample_bits[] = { ++ 24, 32 ++}; ++ ++static struct snd_pcm_hw_constraint_list constraints_sample_bits = { ++ .count = ARRAY_SIZE(sample_bits), ++ .list = sample_bits, ++ .mask = 0, ++}; ++ ++static int pisnd_startup(struct snd_pcm_substream *substream) ++{ ++ int err = snd_pcm_hw_constraint_list( ++ substream->runtime, ++ 0, ++ SNDRV_PCM_HW_PARAM_RATE, ++ &constraints_rates ++ ); ++ ++ if (err < 0) ++ return err; ++ ++ err = snd_pcm_hw_constraint_list( ++ substream->runtime, ++ 0, ++ SNDRV_PCM_HW_PARAM_SAMPLE_BITS, ++ &constraints_sample_bits ++ ); ++ ++ if (err < 0) ++ return err; ++ ++ return 0; ++} ++ ++static struct snd_soc_ops pisnd_ops = { ++ .startup = pisnd_startup, ++ .hw_params = pisnd_hw_params, ++}; ++ ++static struct snd_soc_dai_link pisnd_dai[] = { ++ { ++ .name = "pisound", ++ .stream_name = "pisound", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "snd-soc-dummy-dai", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "snd-soc-dummy", ++ .dai_fmt = ++ SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &pisnd_ops, ++ }, ++}; ++ ++static int pisnd_card_probe(struct snd_soc_card *card) ++{ ++ int err = pisnd_midi_init(card->snd_card); ++ ++ if (err < 0) ++ printe("pisnd_midi_init failed: %d\n", err); ++ ++ return err; ++} ++ ++static int pisnd_card_remove(struct snd_soc_card *card) ++{ ++ pisnd_midi_uninit(); ++ return 0; ++} ++ ++static struct snd_soc_card pisnd_card = { ++ .name = "pisound", ++ .owner = THIS_MODULE, ++ .dai_link = pisnd_dai, ++ .num_links = ARRAY_SIZE(pisnd_dai), ++ .probe = pisnd_card_probe, ++ .remove = pisnd_card_remove, ++}; ++ ++static int pisnd_init_gpio(struct device *dev) ++{ ++ osr0 = gpiod_get_index(dev, "osr", 0, GPIOD_ASIS); ++ osr1 = gpiod_get_index(dev, "osr", 1, GPIOD_ASIS); ++ osr2 = gpiod_get_index(dev, "osr", 2, GPIOD_ASIS); ++ ++ reset = gpiod_get_index(dev, "reset", 0, GPIOD_ASIS); ++ ++ button = gpiod_get_index(dev, "button", 0, GPIOD_ASIS); ++ ++ gpiod_direction_output(osr0, 1); ++ gpiod_direction_output(osr1, 1); ++ gpiod_direction_output(osr2, 1); ++ gpiod_direction_output(reset, 1); ++ ++ gpiod_set_value(reset, false); ++ gpiod_set_value(osr0, true); ++ gpiod_set_value(osr1, false); ++ gpiod_set_value(osr2, false); ++ gpiod_set_value(reset, true); ++ ++ gpiod_export(button, false); ++ ++ return 0; ++} ++ ++static int pisnd_uninit_gpio(void) ++{ ++ int i; ++ ++ struct gpio_desc **gpios[] = { ++ &osr0, &osr1, &osr2, &reset, &button, ++ }; ++ ++ gpiod_unexport(button); ++ ++ for (i = 0; i < ARRAY_SIZE(gpios); ++i) { ++ if (*gpios[i] == NULL) { ++ printd("weird, GPIO[%d] is NULL already\n", i); ++ continue; ++ } ++ ++ gpiod_put(*gpios[i]); ++ *gpios[i] = NULL; ++ } ++ ++ return 0; ++} ++ ++static struct kobject *pisnd_kobj; ++ ++static ssize_t pisnd_serial_show( ++ struct kobject *kobj, ++ struct kobj_attribute *attr, ++ char *buf ++ ) ++{ ++ return sprintf(buf, "%s\n", pisnd_spi_get_serial()); ++} ++ ++static ssize_t pisnd_id_show( ++ struct kobject *kobj, ++ struct kobj_attribute *attr, ++ char *buf ++ ) ++{ ++ return sprintf(buf, "%s\n", pisnd_spi_get_id()); ++} ++ ++static ssize_t pisnd_version_show( ++ struct kobject *kobj, ++ struct kobj_attribute *attr, ++ char *buf ++ ) ++{ ++ return sprintf(buf, "%s\n", pisnd_spi_get_version()); ++} ++ ++static struct kobj_attribute pisnd_serial_attribute = ++ __ATTR(serial, 0644, pisnd_serial_show, NULL); ++static struct kobj_attribute pisnd_id_attribute = ++ __ATTR(id, 0644, pisnd_id_show, NULL); ++static struct kobj_attribute pisnd_version_attribute = ++ __ATTR(version, 0644, pisnd_version_show, NULL); ++ ++static struct attribute *attrs[] = { ++ &pisnd_serial_attribute.attr, ++ &pisnd_id_attribute.attr, ++ &pisnd_version_attribute.attr, ++ NULL ++}; ++ ++static struct attribute_group attr_group = { .attrs = attrs }; ++ ++static int pisnd_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ int i; ++ ++ ret = pisnd_spi_init(&pdev->dev); ++ if (ret < 0) { ++ printe("pisnd_spi_init failed: %d\n", ret); ++ return ret; ++ } ++ ++ printi("Detected pisound card:\n"); ++ printi("\tSerial: %s\n", pisnd_spi_get_serial()); ++ printi("\tVersion: %s\n", pisnd_spi_get_version()); ++ printi("\tId: %s\n", pisnd_spi_get_id()); ++ ++ pisnd_kobj = kobject_create_and_add("pisound", kernel_kobj); ++ if (!pisnd_kobj) { ++ pisnd_spi_uninit(); ++ return -ENOMEM; ++ } ++ ++ ret = sysfs_create_group(pisnd_kobj, &attr_group); ++ if (ret < 0) { ++ pisnd_spi_uninit(); ++ kobject_put(pisnd_kobj); ++ return -ENOMEM; ++ } ++ ++ pisnd_init_gpio(&pdev->dev); ++ pisnd_card.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ ++ i2s_node = of_parse_phandle( ++ pdev->dev.of_node, ++ "i2s-controller", ++ 0 ++ ); ++ ++ for (i = 0; i < pisnd_card.num_links; ++i) { ++ struct snd_soc_dai_link *dai = &pisnd_dai[i]; ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ dai->stream_name = pisnd_spi_get_serial(); ++ } ++ } ++ } ++ ++ ret = snd_soc_register_card(&pisnd_card); ++ ++ if (ret < 0) { ++ printe("snd_soc_register_card() failed: %d\n", ret); ++ pisnd_uninit_gpio(); ++ kobject_put(pisnd_kobj); ++ pisnd_spi_uninit(); ++ } ++ ++ return ret; ++} ++ ++static int pisnd_remove(struct platform_device *pdev) ++{ ++ printi("Unloading.\n"); ++ ++ if (pisnd_kobj) { ++ kobject_put(pisnd_kobj); ++ pisnd_kobj = NULL; ++ } ++ ++ pisnd_spi_uninit(); ++ ++ /* Turn off */ ++ gpiod_set_value(reset, false); ++ pisnd_uninit_gpio(); ++ ++ return snd_soc_unregister_card(&pisnd_card); ++} ++ ++MODULE_DEVICE_TABLE(of, pisound_of_match); ++ ++static struct platform_driver pisnd_driver = { ++ .driver = { ++ .name = "snd-rpi-pisound", ++ .owner = THIS_MODULE, ++ .of_match_table = pisound_of_match, ++ }, ++ .probe = pisnd_probe, ++ .remove = pisnd_remove, ++}; ++ ++module_platform_driver(pisnd_driver); ++ ++MODULE_AUTHOR("Giedrius Trainavicius "); ++MODULE_DESCRIPTION("ASoC Driver for pisound, http://blokas.io/pisound"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0085-Support-for-Blokas-Labs-pisound-board.patch b/target/linux/brcm2708/patches-4.9/0085-Support-for-Blokas-Labs-pisound-board.patch deleted file mode 100644 index 51d5733737..0000000000 --- a/target/linux/brcm2708/patches-4.9/0085-Support-for-Blokas-Labs-pisound-board.patch +++ /dev/null @@ -1,1168 +0,0 @@ -From aa46aa94c5ca5683fd815c57a78ea5fb05e7c3e5 Mon Sep 17 00:00:00 2001 -From: gtrainavicius -Date: Sun, 23 Oct 2016 12:06:53 +0300 -Subject: [PATCH] Support for Blokas Labs pisound board - -Pisound dynamic overlay (#1760) - -Restructuring pisound-overlay.dts, so it can be loaded and unloaded dynamically using dtoverlay. - -Print a logline when the kernel module is removed. ---- - .../devicetree/bindings/vendor-prefixes.txt | 1 + - arch/arm/boot/dts/overlays/pisound-overlay.dts | 94 +- - sound/soc/bcm/Kconfig | 6 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/pisound.c | 989 +++++++++++++++++++++ - 5 files changed, 1048 insertions(+), 44 deletions(-) - create mode 100644 sound/soc/bcm/pisound.c - ---- a/Documentation/devicetree/bindings/vendor-prefixes.txt -+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt -@@ -40,6 +40,7 @@ auvidea Auvidea GmbH - avago Avago Technologies - avic Shanghai AVIC Optoelectronics Co., Ltd. - axis Axis Communications AB -+blokaslabs Vilniaus Blokas UAB - boe BOE Technology Group Co., Ltd. - bosch Bosch Sensortec GmbH - boundary Boundary Devices Inc. ---- a/arch/arm/boot/dts/overlays/pisound-overlay.dts -+++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts -@@ -26,6 +26,54 @@ - compatible = "brcm,bcm2708"; - - fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&spidev0>; -+ __overlay__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spidev1>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@3 { -+ target = <&spi0>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pisound_spi: pisound_spi@0{ -+ compatible = "blokaslabs,pisound-spi"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_pins>; -+ spi-max-frequency = <1000000>; -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target-path = "/"; -+ __overlay__ { -+ pcm5102a-codec { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5102a"; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@5 { - target = <&sound>; - __overlay__ { - compatible = "blokaslabs,pisound"; -@@ -49,7 +97,7 @@ - }; - }; - -- fragment@1 { -+ fragment@6 { - target = <&gpio>; - __overlay__ { - pinctrl-names = "default"; -@@ -63,52 +111,10 @@ - }; - }; - -- fragment@2 { -+ fragment@7 { - target = <&i2s>; - __overlay__ { - status = "okay"; - }; - }; -- -- fragment@3 { -- target-path = "/"; -- __overlay__ { -- pcm5102a-codec { -- #sound-dai-cells = <0>; -- compatible = "ti,pcm5102a"; -- status = "okay"; -- }; -- }; -- }; -- -- fragment@4 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "okay"; -- }; -- }; -- }; -- -- fragment@5 { -- target = <&spi0>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- -- pisound_spi: pisound_spi@0{ -- compatible = "blokaslabs,pisound-spi"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&spi0_pins>; -- spi-max-frequency = <1000000>; -- }; -- }; -- }; - }; ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -123,3 +123,9 @@ config SND_BCM2708_SOC_ALLO_PIANO_DAC - select SND_SOC_PCM512x_I2C - help - Say Y or M if you want to add support for Allo Piano DAC. -+ -+config SND_PISOUND -+ tristate "Support for Blokas Labs pisound" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ help -+ Say Y or M if you want to add support for Blokas Labs pisound. ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -24,6 +24,7 @@ snd-soc-audioinjector-pi-soundcard-objs - snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o - snd-soc-dionaudio-loco-objs := dionaudio_loco.o - snd-soc-allo-piano-dac-objs := allo-piano-dac.o -+snd-soc-pisound-objs := pisound.o - - obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -40,3 +41,4 @@ obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDC - obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o - obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o - obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o -+obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o ---- /dev/null -+++ b/sound/soc/bcm/pisound.c -@@ -0,0 +1,989 @@ -+/* -+ * pisound Linux kernel module. -+ * Copyright (C) 2016 Vilniaus Blokas UAB, http://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 -+ * as published by the Free Software Foundation; version 2 of the -+ * License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -+ * MA 02110-1301, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static int pisnd_spi_init(struct device *dev); -+static void pisnd_spi_uninit(void); -+ -+static void pisnd_spi_send(uint8_t val); -+static uint8_t pisnd_spi_recv(uint8_t *buffer, uint8_t length); -+ -+typedef void (*pisnd_spi_recv_cb)(void *data); -+static void pisnd_spi_set_callback(pisnd_spi_recv_cb cb, void *data); -+ -+static const char *pisnd_spi_get_serial(void); -+static const char *pisnd_spi_get_id(void); -+static const char *pisnd_spi_get_version(void); -+ -+static int pisnd_midi_init(struct snd_card *card); -+static void pisnd_midi_uninit(void); -+ -+#define PISOUND_LOG_PREFIX "pisound: " -+ -+#ifdef DEBUG -+# define printd(...) pr_alert(PISOUND_LOG_PREFIX __VA_ARGS__) -+#else -+# define printd(...) do {} while (0) -+#endif -+ -+#define printe(...) pr_err(PISOUND_LOG_PREFIX __VA_ARGS__) -+#define printi(...) pr_info(PISOUND_LOG_PREFIX __VA_ARGS__) -+ -+static int pisnd_output_open(struct snd_rawmidi_substream *substream) -+{ -+ return 0; -+} -+ -+static int pisnd_output_close(struct snd_rawmidi_substream *substream) -+{ -+ return 0; -+} -+ -+static void pisnd_output_trigger( -+ struct snd_rawmidi_substream *substream, -+ int up -+ ) -+{ -+ uint8_t data; -+ -+ if (!up) -+ return; -+ -+ while (snd_rawmidi_transmit_peek(substream, &data, 1)) { -+ pisnd_spi_send(data); -+ snd_rawmidi_transmit_ack(substream, 1); -+ } -+} -+ -+static void pisnd_output_drain(struct snd_rawmidi_substream *substream) -+{ -+ uint8_t data; -+ -+ while (snd_rawmidi_transmit_peek(substream, &data, 1)) { -+ pisnd_spi_send(data); -+ -+ snd_rawmidi_transmit_ack(substream, 1); -+ } -+} -+ -+static int pisnd_input_open(struct snd_rawmidi_substream *substream) -+{ -+ return 0; -+} -+ -+static int pisnd_input_close(struct snd_rawmidi_substream *substream) -+{ -+ return 0; -+} -+ -+static void pisnd_midi_recv_callback(void *substream) -+{ -+ uint8_t data[128]; -+ uint8_t n = 0; -+ -+ while ((n = pisnd_spi_recv(data, sizeof(data)))) { -+ int res = snd_rawmidi_receive(substream, data, n); -+ (void)res; -+ printd("midi recv 0x%02x, res = %d\n", data, res); -+ } -+} -+ -+static void pisnd_input_trigger(struct snd_rawmidi_substream *substream, int up) -+{ -+ if (up) { -+ pisnd_spi_set_callback(pisnd_midi_recv_callback, substream); -+ pisnd_midi_recv_callback(substream); -+ } else { -+ pisnd_spi_set_callback(NULL, NULL); -+ } -+} -+ -+static struct snd_rawmidi *g_rmidi; -+ -+static struct snd_rawmidi_ops pisnd_output_ops = { -+ .open = pisnd_output_open, -+ .close = pisnd_output_close, -+ .trigger = pisnd_output_trigger, -+ .drain = pisnd_output_drain, -+}; -+ -+static struct snd_rawmidi_ops pisnd_input_ops = { -+ .open = pisnd_input_open, -+ .close = pisnd_input_close, -+ .trigger = pisnd_input_trigger, -+}; -+ -+static void pisnd_get_port_info( -+ struct snd_rawmidi *rmidi, -+ int number, -+ struct snd_seq_port_info *seq_port_info -+ ) -+{ -+ seq_port_info->type = -+ SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | -+ SNDRV_SEQ_PORT_TYPE_HARDWARE | -+ SNDRV_SEQ_PORT_TYPE_PORT; -+ seq_port_info->midi_voices = 0; -+} -+ -+static struct snd_rawmidi_global_ops pisnd_global_ops = { -+ .get_port_info = pisnd_get_port_info, -+}; -+ -+static int pisnd_midi_init(struct snd_card *card) -+{ -+ int err = snd_rawmidi_new(card, "pisound MIDI", 0, 1, 1, &g_rmidi); -+ -+ if (err < 0) { -+ printe("snd_rawmidi_new failed: %d\n", err); -+ return err; -+ } -+ -+ strcpy(g_rmidi->name, "pisound MIDI "); -+ strcat(g_rmidi->name, pisnd_spi_get_serial()); -+ -+ g_rmidi->info_flags = -+ SNDRV_RAWMIDI_INFO_OUTPUT | -+ SNDRV_RAWMIDI_INFO_INPUT | -+ SNDRV_RAWMIDI_INFO_DUPLEX; -+ -+ g_rmidi->ops = &pisnd_global_ops; -+ -+ g_rmidi->private_data = (void *)0; -+ -+ snd_rawmidi_set_ops( -+ g_rmidi, -+ SNDRV_RAWMIDI_STREAM_OUTPUT, -+ &pisnd_output_ops -+ ); -+ -+ snd_rawmidi_set_ops( -+ g_rmidi, -+ SNDRV_RAWMIDI_STREAM_INPUT, -+ &pisnd_input_ops -+ ); -+ -+ return 0; -+} -+ -+static void pisnd_midi_uninit(void) -+{ -+} -+ -+static void *g_recvData; -+static pisnd_spi_recv_cb g_recvCallback; -+ -+#define FIFO_SIZE 512 -+ -+static char g_serial_num[11]; -+static char g_id[25]; -+static char g_version[5]; -+ -+DEFINE_KFIFO(spi_fifo_in, uint8_t, FIFO_SIZE); -+DEFINE_KFIFO(spi_fifo_out, uint8_t, FIFO_SIZE); -+ -+static struct gpio_desc *data_available; -+static struct gpio_desc *spi_reset; -+ -+static struct spi_device *pisnd_spi_device; -+ -+static struct workqueue_struct *pisnd_workqueue; -+static struct work_struct pisnd_work_process; -+ -+static void pisnd_work_handler(struct work_struct *work); -+ -+static uint16_t spi_transfer16(uint16_t val); -+ -+static int pisnd_init_workqueues(void) -+{ -+ pisnd_workqueue = create_singlethread_workqueue("pisnd_workqueue"); -+ INIT_WORK(&pisnd_work_process, pisnd_work_handler); -+ -+ return 0; -+} -+ -+static void pisnd_uninit_workqueues(void) -+{ -+ flush_workqueue(pisnd_workqueue); -+ destroy_workqueue(pisnd_workqueue); -+ -+ pisnd_workqueue = NULL; -+} -+ -+static bool pisnd_spi_has_more(void) -+{ -+ return gpiod_get_value(data_available); -+} -+ -+enum task_e { -+ TASK_PROCESS = 0, -+}; -+ -+static void pisnd_schedule_process(enum task_e task) -+{ -+ if (pisnd_spi_device != NULL && -+ pisnd_workqueue != NULL && -+ !work_pending(&pisnd_work_process) -+ ) { -+ printd("schedule: has more = %d\n", pisnd_spi_has_more()); -+ if (task == TASK_PROCESS) -+ queue_work(pisnd_workqueue, &pisnd_work_process); -+ } -+} -+ -+static irqreturn_t data_available_interrupt_handler(int irq, void *dev_id) -+{ -+ if (irq == gpiod_to_irq(data_available) && pisnd_spi_has_more()) { -+ printd("schedule from irq\n"); -+ pisnd_schedule_process(TASK_PROCESS); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static DEFINE_SPINLOCK(spilock); -+static unsigned long spilockflags; -+ -+static uint16_t spi_transfer16(uint16_t val) -+{ -+ int err; -+ struct spi_transfer transfer; -+ struct spi_message msg; -+ uint8_t txbuf[2]; -+ uint8_t rxbuf[2]; -+ -+ if (!pisnd_spi_device) { -+ printe("pisnd_spi_device null, returning\n"); -+ return 0; -+ } -+ -+ spi_message_init(&msg); -+ -+ memset(&transfer, 0, sizeof(transfer)); -+ memset(&rxbuf, 0, sizeof(rxbuf)); -+ -+ txbuf[0] = val >> 8; -+ txbuf[1] = val & 0xff; -+ -+ transfer.tx_buf = &txbuf; -+ transfer.rx_buf = &rxbuf; -+ transfer.len = sizeof(txbuf); -+ transfer.speed_hz = 125000; -+ transfer.delay_usecs = 100; -+ spi_message_add_tail(&transfer, &msg); -+ -+ spin_lock_irqsave(&spilock, spilockflags); -+ err = spi_sync(pisnd_spi_device, &msg); -+ spin_unlock_irqrestore(&spilock, spilockflags); -+ -+ if (err < 0) { -+ printe("spi_sync error %d\n", err); -+ return 0; -+ } -+ -+ printd("received: %02x%02x\n", rxbuf[0], rxbuf[1]); -+ printd("hasMore %d\n", pisnd_spi_has_more()); -+ -+ return (rxbuf[0] << 8) | rxbuf[1]; -+} -+ -+static int spi_read_bytes(char *dst, size_t length, uint8_t *bytesRead) -+{ -+ uint16_t rx; -+ uint8_t size; -+ uint8_t i; -+ -+ memset(dst, 0, length); -+ *bytesRead = 0; -+ -+ rx = spi_transfer16(0); -+ if (!(rx >> 8)) -+ return -EINVAL; -+ -+ size = rx & 0xff; -+ -+ if (size > length) -+ return -EINVAL; -+ -+ for (i = 0; i < size; ++i) { -+ rx = spi_transfer16(0); -+ if (!(rx >> 8)) -+ return -EINVAL; -+ -+ dst[i] = rx & 0xff; -+ } -+ -+ *bytesRead = i; -+ -+ return 0; -+} -+ -+static int spi_device_match(struct device *dev, void *data) -+{ -+ struct spi_device *spi = container_of(dev, struct spi_device, dev); -+ -+ printd(" %s %s %dkHz %d bits mode=0x%02X\n", -+ spi->modalias, dev_name(dev), spi->max_speed_hz/1000, -+ spi->bits_per_word, spi->mode); -+ -+ if (strcmp("pisound-spi", spi->modalias) == 0) { -+ printi("\tFound!\n"); -+ return 1; -+ } -+ -+ printe("\tNot found!\n"); -+ return 0; -+} -+ -+static struct spi_device *pisnd_spi_find_device(void) -+{ -+ struct device *dev; -+ -+ printi("Searching for spi device...\n"); -+ dev = bus_find_device(&spi_bus_type, NULL, NULL, spi_device_match); -+ if (dev != NULL) -+ return container_of(dev, struct spi_device, dev); -+ else -+ return NULL; -+} -+ -+static void pisnd_work_handler(struct work_struct *work) -+{ -+ uint16_t rx; -+ uint16_t tx; -+ uint8_t val; -+ -+ if (work == &pisnd_work_process) { -+ if (pisnd_spi_device == NULL) -+ return; -+ -+ do { -+ val = 0; -+ tx = 0; -+ -+ if (kfifo_get(&spi_fifo_out, &val)) -+ tx = 0x0f00 | val; -+ -+ rx = spi_transfer16(tx); -+ -+ if (rx & 0xff00) { -+ kfifo_put(&spi_fifo_in, rx & 0xff); -+ if (kfifo_len(&spi_fifo_in) > 16 -+ && g_recvCallback) -+ g_recvCallback(g_recvData); -+ } -+ } while (rx != 0 -+ || !kfifo_is_empty(&spi_fifo_out) -+ || pisnd_spi_has_more() -+ ); -+ -+ if (!kfifo_is_empty(&spi_fifo_in) && g_recvCallback) -+ g_recvCallback(g_recvData); -+ } -+} -+ -+static int pisnd_spi_gpio_init(struct device *dev) -+{ -+ spi_reset = gpiod_get_index(dev, "reset", 1, GPIOD_ASIS); -+ data_available = gpiod_get_index(dev, "data_available", 0, GPIOD_ASIS); -+ -+ gpiod_direction_output(spi_reset, 1); -+ gpiod_direction_input(data_available); -+ -+ /* Reset the slave. */ -+ gpiod_set_value(spi_reset, false); -+ mdelay(1); -+ gpiod_set_value(spi_reset, true); -+ -+ /* Give time for spi slave to start. */ -+ mdelay(64); -+ -+ return 0; -+} -+ -+static void pisnd_spi_gpio_uninit(void) -+{ -+ gpiod_set_value(spi_reset, false); -+ gpiod_put(spi_reset); -+ spi_reset = NULL; -+ -+ gpiod_put(data_available); -+ data_available = NULL; -+} -+ -+static int pisnd_spi_gpio_irq_init(struct device *dev) -+{ -+ return request_irq( -+ gpiod_to_irq(data_available), -+ data_available_interrupt_handler, -+ IRQF_TIMER | IRQF_TRIGGER_RISING, -+ "data_available_int", -+ NULL -+ ); -+} -+ -+static void pisnd_spi_gpio_irq_uninit(void) -+{ -+ free_irq(gpiod_to_irq(data_available), NULL); -+} -+ -+static int spi_read_info(void) -+{ -+ uint16_t tmp; -+ uint8_t count; -+ uint8_t n; -+ uint8_t i; -+ uint8_t j; -+ char buffer[257]; -+ int ret; -+ char *p; -+ -+ memset(g_serial_num, 0, sizeof(g_serial_num)); -+ memset(g_version, 0, sizeof(g_version)); -+ memset(g_id, 0, sizeof(g_id)); -+ -+ tmp = spi_transfer16(0); -+ -+ if (!(tmp >> 8)) -+ return -EINVAL; -+ -+ count = tmp & 0xff; -+ -+ for (i = 0; i < count; ++i) { -+ memset(buffer, 0, sizeof(buffer)); -+ ret = spi_read_bytes(buffer, sizeof(buffer)-1, &n); -+ -+ if (ret < 0) -+ return ret; -+ -+ switch (i) { -+ case 0: -+ if (n != 2) -+ return -EINVAL; -+ -+ snprintf( -+ g_version, -+ sizeof(g_version), -+ "%x.%02x", -+ buffer[0], -+ buffer[1] -+ ); -+ break; -+ case 1: -+ if (n >= sizeof(g_serial_num)) -+ return -EINVAL; -+ -+ memcpy(g_serial_num, buffer, sizeof(g_serial_num)); -+ break; -+ case 2: -+ { -+ if (n >= sizeof(g_id)) -+ return -EINVAL; -+ -+ p = g_id; -+ for (j = 0; j < n; ++j) -+ p += sprintf(p, "%02x", buffer[j]); -+ } -+ break; -+ default: -+ break; -+ } -+ } -+ -+ return 0; -+} -+ -+static int pisnd_spi_init(struct device *dev) -+{ -+ int ret; -+ struct spi_device *spi; -+ -+ memset(g_serial_num, 0, sizeof(g_serial_num)); -+ memset(g_id, 0, sizeof(g_id)); -+ memset(g_version, 0, sizeof(g_version)); -+ -+ spi = pisnd_spi_find_device(); -+ -+ if (spi != NULL) { -+ printd("initializing spi!\n"); -+ pisnd_spi_device = spi; -+ ret = spi_setup(pisnd_spi_device); -+ } else { -+ printe("SPI device not found, deferring!\n"); -+ return -EPROBE_DEFER; -+ } -+ -+ ret = pisnd_spi_gpio_init(dev); -+ -+ if (ret < 0) { -+ printe("SPI GPIO init failed: %d\n", ret); -+ spi_dev_put(pisnd_spi_device); -+ pisnd_spi_device = NULL; -+ pisnd_spi_gpio_uninit(); -+ return ret; -+ } -+ -+ ret = spi_read_info(); -+ -+ if (ret < 0) { -+ printe("Reading card info failed: %d\n", ret); -+ spi_dev_put(pisnd_spi_device); -+ pisnd_spi_device = NULL; -+ pisnd_spi_gpio_uninit(); -+ return ret; -+ } -+ -+ /* Flash the LEDs. */ -+ spi_transfer16(0xf000); -+ -+ ret = pisnd_spi_gpio_irq_init(dev); -+ if (ret < 0) { -+ printe("SPI irq request failed: %d\n", ret); -+ spi_dev_put(pisnd_spi_device); -+ pisnd_spi_device = NULL; -+ pisnd_spi_gpio_irq_uninit(); -+ pisnd_spi_gpio_uninit(); -+ } -+ -+ ret = pisnd_init_workqueues(); -+ if (ret != 0) { -+ printe("Workqueue initialization failed: %d\n", ret); -+ spi_dev_put(pisnd_spi_device); -+ pisnd_spi_device = NULL; -+ pisnd_spi_gpio_irq_uninit(); -+ pisnd_spi_gpio_uninit(); -+ pisnd_uninit_workqueues(); -+ return ret; -+ } -+ -+ if (pisnd_spi_has_more()) { -+ printd("data is available, scheduling from init\n"); -+ pisnd_schedule_process(TASK_PROCESS); -+ } -+ -+ return 0; -+} -+ -+static void pisnd_spi_uninit(void) -+{ -+ pisnd_uninit_workqueues(); -+ -+ spi_dev_put(pisnd_spi_device); -+ pisnd_spi_device = NULL; -+ -+ pisnd_spi_gpio_irq_uninit(); -+ pisnd_spi_gpio_uninit(); -+} -+ -+static void pisnd_spi_send(uint8_t val) -+{ -+ kfifo_put(&spi_fifo_out, val); -+ printd("schedule from spi_send\n"); -+ pisnd_schedule_process(TASK_PROCESS); -+} -+ -+static uint8_t pisnd_spi_recv(uint8_t *buffer, uint8_t length) -+{ -+ return kfifo_out(&spi_fifo_in, buffer, length); -+} -+ -+static void pisnd_spi_set_callback(pisnd_spi_recv_cb cb, void *data) -+{ -+ g_recvData = data; -+ g_recvCallback = cb; -+} -+ -+static const char *pisnd_spi_get_serial(void) -+{ -+ if (strlen(g_serial_num)) -+ return g_serial_num; -+ -+ return ""; -+} -+ -+static const char *pisnd_spi_get_id(void) -+{ -+ if (strlen(g_id)) -+ return g_id; -+ -+ return ""; -+} -+ -+static const char *pisnd_spi_get_version(void) -+{ -+ if (strlen(g_version)) -+ return g_version; -+ -+ return ""; -+} -+ -+static const struct of_device_id pisound_of_match[] = { -+ { .compatible = "blokaslabs,pisound", }, -+ { .compatible = "blokaslabs,pisound-spi", }, -+ {}, -+}; -+ -+static struct gpio_desc *osr0, *osr1, *osr2; -+static struct gpio_desc *reset; -+static struct gpio_desc *button; -+ -+static int pisnd_hw_params( -+ struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params -+ ) -+{ -+ printd("rate = %d\n", params_rate(params)); -+ printd("ch = %d\n", params_channels(params)); -+ printd("bits = %u\n", -+ snd_pcm_format_physical_width(params_format(params))); -+ printd("format = %d\n", params_format(params)); -+ -+ gpiod_set_value(reset, false); -+ -+ switch (params_rate(params)) { -+ case 48000: -+ gpiod_set_value(osr0, true); -+ gpiod_set_value(osr1, false); -+ gpiod_set_value(osr2, false); -+ break; -+ case 96000: -+ gpiod_set_value(osr0, true); -+ gpiod_set_value(osr1, true); -+ gpiod_set_value(osr2, false); -+ break; -+ case 192000: -+ gpiod_set_value(osr0, true); -+ gpiod_set_value(osr1, true); -+ gpiod_set_value(osr2, true); -+ break; -+ default: -+ printe("Unsupported rate %u!\n", params_rate(params)); -+ return -EINVAL; -+ } -+ -+ gpiod_set_value(reset, true); -+ -+ return 0; -+} -+ -+static unsigned int rates[3] = { -+ 48000, 96000, 192000 -+}; -+ -+static struct snd_pcm_hw_constraint_list constraints_rates = { -+ .count = ARRAY_SIZE(rates), -+ .list = rates, -+ .mask = 0, -+}; -+ -+static unsigned int sample_bits[] = { -+ 24, 32 -+}; -+ -+static struct snd_pcm_hw_constraint_list constraints_sample_bits = { -+ .count = ARRAY_SIZE(sample_bits), -+ .list = sample_bits, -+ .mask = 0, -+}; -+ -+static int pisnd_startup(struct snd_pcm_substream *substream) -+{ -+ int err = snd_pcm_hw_constraint_list( -+ substream->runtime, -+ 0, -+ SNDRV_PCM_HW_PARAM_RATE, -+ &constraints_rates -+ ); -+ -+ if (err < 0) -+ return err; -+ -+ err = snd_pcm_hw_constraint_list( -+ substream->runtime, -+ 0, -+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -+ &constraints_sample_bits -+ ); -+ -+ if (err < 0) -+ return err; -+ -+ return 0; -+} -+ -+static struct snd_soc_ops pisnd_ops = { -+ .startup = pisnd_startup, -+ .hw_params = pisnd_hw_params, -+}; -+ -+static struct snd_soc_dai_link pisnd_dai[] = { -+ { -+ .name = "pisound", -+ .stream_name = "pisound", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "snd-soc-dummy-dai", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "snd-soc-dummy", -+ .dai_fmt = -+ SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBM_CFM, -+ .ops = &pisnd_ops, -+ }, -+}; -+ -+static int pisnd_card_probe(struct snd_soc_card *card) -+{ -+ int err = pisnd_midi_init(card->snd_card); -+ -+ if (err < 0) -+ printe("pisnd_midi_init failed: %d\n", err); -+ -+ return err; -+} -+ -+static int pisnd_card_remove(struct snd_soc_card *card) -+{ -+ pisnd_midi_uninit(); -+ return 0; -+} -+ -+static struct snd_soc_card pisnd_card = { -+ .name = "pisound", -+ .owner = THIS_MODULE, -+ .dai_link = pisnd_dai, -+ .num_links = ARRAY_SIZE(pisnd_dai), -+ .probe = pisnd_card_probe, -+ .remove = pisnd_card_remove, -+}; -+ -+static int pisnd_init_gpio(struct device *dev) -+{ -+ osr0 = gpiod_get_index(dev, "osr", 0, GPIOD_ASIS); -+ osr1 = gpiod_get_index(dev, "osr", 1, GPIOD_ASIS); -+ osr2 = gpiod_get_index(dev, "osr", 2, GPIOD_ASIS); -+ -+ reset = gpiod_get_index(dev, "reset", 0, GPIOD_ASIS); -+ -+ button = gpiod_get_index(dev, "button", 0, GPIOD_ASIS); -+ -+ gpiod_direction_output(osr0, 1); -+ gpiod_direction_output(osr1, 1); -+ gpiod_direction_output(osr2, 1); -+ gpiod_direction_output(reset, 1); -+ -+ gpiod_set_value(reset, false); -+ gpiod_set_value(osr0, true); -+ gpiod_set_value(osr1, false); -+ gpiod_set_value(osr2, false); -+ gpiod_set_value(reset, true); -+ -+ gpiod_export(button, false); -+ -+ return 0; -+} -+ -+static int pisnd_uninit_gpio(void) -+{ -+ int i; -+ -+ struct gpio_desc **gpios[] = { -+ &osr0, &osr1, &osr2, &reset, &button, -+ }; -+ -+ gpiod_unexport(button); -+ -+ for (i = 0; i < ARRAY_SIZE(gpios); ++i) { -+ if (*gpios[i] == NULL) { -+ printd("weird, GPIO[%d] is NULL already\n", i); -+ continue; -+ } -+ -+ gpiod_put(*gpios[i]); -+ *gpios[i] = NULL; -+ } -+ -+ return 0; -+} -+ -+static struct kobject *pisnd_kobj; -+ -+static ssize_t pisnd_serial_show( -+ struct kobject *kobj, -+ struct kobj_attribute *attr, -+ char *buf -+ ) -+{ -+ return sprintf(buf, "%s\n", pisnd_spi_get_serial()); -+} -+ -+static ssize_t pisnd_id_show( -+ struct kobject *kobj, -+ struct kobj_attribute *attr, -+ char *buf -+ ) -+{ -+ return sprintf(buf, "%s\n", pisnd_spi_get_id()); -+} -+ -+static ssize_t pisnd_version_show( -+ struct kobject *kobj, -+ struct kobj_attribute *attr, -+ char *buf -+ ) -+{ -+ return sprintf(buf, "%s\n", pisnd_spi_get_version()); -+} -+ -+static struct kobj_attribute pisnd_serial_attribute = -+ __ATTR(serial, 0644, pisnd_serial_show, NULL); -+static struct kobj_attribute pisnd_id_attribute = -+ __ATTR(id, 0644, pisnd_id_show, NULL); -+static struct kobj_attribute pisnd_version_attribute = -+ __ATTR(version, 0644, pisnd_version_show, NULL); -+ -+static struct attribute *attrs[] = { -+ &pisnd_serial_attribute.attr, -+ &pisnd_id_attribute.attr, -+ &pisnd_version_attribute.attr, -+ NULL -+}; -+ -+static struct attribute_group attr_group = { .attrs = attrs }; -+ -+static int pisnd_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ int i; -+ -+ ret = pisnd_spi_init(&pdev->dev); -+ if (ret < 0) { -+ printe("pisnd_spi_init failed: %d\n", ret); -+ return ret; -+ } -+ -+ printi("Detected pisound card:\n"); -+ printi("\tSerial: %s\n", pisnd_spi_get_serial()); -+ printi("\tVersion: %s\n", pisnd_spi_get_version()); -+ printi("\tId: %s\n", pisnd_spi_get_id()); -+ -+ pisnd_kobj = kobject_create_and_add("pisound", kernel_kobj); -+ if (!pisnd_kobj) { -+ pisnd_spi_uninit(); -+ return -ENOMEM; -+ } -+ -+ ret = sysfs_create_group(pisnd_kobj, &attr_group); -+ if (ret < 0) { -+ pisnd_spi_uninit(); -+ kobject_put(pisnd_kobj); -+ return -ENOMEM; -+ } -+ -+ pisnd_init_gpio(&pdev->dev); -+ pisnd_card.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ -+ i2s_node = of_parse_phandle( -+ pdev->dev.of_node, -+ "i2s-controller", -+ 0 -+ ); -+ -+ for (i = 0; i < pisnd_card.num_links; ++i) { -+ struct snd_soc_dai_link *dai = &pisnd_dai[i]; -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ dai->stream_name = pisnd_spi_get_serial(); -+ } -+ } -+ } -+ -+ ret = snd_soc_register_card(&pisnd_card); -+ -+ if (ret < 0) { -+ printe("snd_soc_register_card() failed: %d\n", ret); -+ pisnd_uninit_gpio(); -+ kobject_put(pisnd_kobj); -+ pisnd_spi_uninit(); -+ } -+ -+ return ret; -+} -+ -+static int pisnd_remove(struct platform_device *pdev) -+{ -+ printi("Unloading.\n"); -+ -+ if (pisnd_kobj) { -+ kobject_put(pisnd_kobj); -+ pisnd_kobj = NULL; -+ } -+ -+ pisnd_spi_uninit(); -+ -+ /* Turn off */ -+ gpiod_set_value(reset, false); -+ pisnd_uninit_gpio(); -+ -+ return snd_soc_unregister_card(&pisnd_card); -+} -+ -+MODULE_DEVICE_TABLE(of, pisound_of_match); -+ -+static struct platform_driver pisnd_driver = { -+ .driver = { -+ .name = "snd-rpi-pisound", -+ .owner = THIS_MODULE, -+ .of_match_table = pisound_of_match, -+ }, -+ .probe = pisnd_probe, -+ .remove = pisnd_remove, -+}; -+ -+module_platform_driver(pisnd_driver); -+ -+MODULE_AUTHOR("Giedrius Trainavicius "); -+MODULE_DESCRIPTION("ASoC Driver for pisound, http://blokas.io/pisound"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0085-rpi_display-add-backlight-driver-and-overlay.patch b/target/linux/brcm2708/patches-4.9/0085-rpi_display-add-backlight-driver-and-overlay.patch new file mode 100644 index 0000000000..67c0e3f5cd --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0085-rpi_display-add-backlight-driver-and-overlay.patch @@ -0,0 +1,164 @@ +From ae5ae9278768c3d096910705bfa9af85da20a8cf Mon Sep 17 00:00:00 2001 +From: P33M +Date: Wed, 21 Oct 2015 14:55:21 +0100 +Subject: [PATCH] rpi_display: add backlight driver and overlay + +Add a mailbox-driven backlight controller for the Raspberry Pi DSI +touchscreen display. Requires updated GPU firmware to recognise the +mailbox request. + +Signed-off-by: Gordon Hollingworth +--- + drivers/video/backlight/Kconfig | 6 ++ + drivers/video/backlight/Makefile | 1 + + drivers/video/backlight/rpi_backlight.c | 119 ++++++++++++++++++++++++++++++++ + 3 files changed, 126 insertions(+) + create mode 100644 drivers/video/backlight/rpi_backlight.c + +--- a/drivers/video/backlight/Kconfig ++++ b/drivers/video/backlight/Kconfig +@@ -265,6 +265,12 @@ config BACKLIGHT_PWM + If you have a LCD backlight adjustable by PWM, say Y to enable + this driver. + ++config BACKLIGHT_RPI ++ tristate "Raspberry Pi display firmware driven backlight" ++ help ++ If you have the Raspberry Pi DSI touchscreen display, say Y to ++ enable the mailbox-controlled backlight driver. ++ + config BACKLIGHT_DA903X + tristate "Backlight Driver for DA9030/DA9034 using WLED" + depends on PMIC_DA903X +--- a/drivers/video/backlight/Makefile ++++ b/drivers/video/backlight/Makefile +@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pand + obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o + obj-$(CONFIG_BACKLIGHT_PM8941_WLED) += pm8941-wled.o + obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o ++obj-$(CONFIG_BACKLIGHT_RPI) += rpi_backlight.o + obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o + obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o + obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o +--- /dev/null ++++ b/drivers/video/backlight/rpi_backlight.c +@@ -0,0 +1,119 @@ ++/* ++ * rpi_bl.c - Backlight controller through VPU ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct rpi_backlight { ++ struct device *dev; ++ struct device *fbdev; ++ struct rpi_firmware *fw; ++}; ++ ++static int rpi_backlight_update_status(struct backlight_device *bl) ++{ ++ struct rpi_backlight *gbl = bl_get_data(bl); ++ int brightness = bl->props.brightness; ++ int ret; ++ ++ if (bl->props.power != FB_BLANK_UNBLANK || ++ bl->props.fb_blank != FB_BLANK_UNBLANK || ++ bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) ++ brightness = 0; ++ ++ ret = rpi_firmware_property(gbl->fw, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT, ++ &brightness, sizeof(brightness)); ++ if (ret) { ++ dev_err(gbl->dev, "Failed to set brightness\n"); ++ return ret; ++ } ++ ++ if (brightness < 0) { ++ dev_err(gbl->dev, "Backlight change failed\n"); ++ return -EAGAIN; ++ } ++ ++ return 0; ++} ++ ++static const struct backlight_ops rpi_backlight_ops = { ++ .options = BL_CORE_SUSPENDRESUME, ++ .update_status = rpi_backlight_update_status, ++}; ++ ++static int rpi_backlight_probe(struct platform_device *pdev) ++{ ++ struct backlight_properties props; ++ struct backlight_device *bl; ++ struct rpi_backlight *gbl; ++ struct device_node *fw_node; ++ ++ gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL); ++ if (gbl == NULL) ++ return -ENOMEM; ++ ++ gbl->dev = &pdev->dev; ++ ++ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); ++ if (!fw_node) { ++ dev_err(&pdev->dev, "Missing firmware node\n"); ++ return -ENOENT; ++ } ++ ++ gbl->fw = rpi_firmware_get(fw_node); ++ if (!gbl->fw) ++ return -EPROBE_DEFER; ++ ++ memset(&props, 0, sizeof(props)); ++ props.type = BACKLIGHT_RAW; ++ props.max_brightness = 255; ++ bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), ++ &pdev->dev, gbl, &rpi_backlight_ops, ++ &props); ++ if (IS_ERR(bl)) { ++ dev_err(&pdev->dev, "failed to register backlight\n"); ++ return PTR_ERR(bl); ++ } ++ ++ bl->props.brightness = 255; ++ backlight_update_status(bl); ++ ++ platform_set_drvdata(pdev, bl); ++ return 0; ++} ++ ++static const struct of_device_id rpi_backlight_of_match[] = { ++ { .compatible = "raspberrypi,rpi-backlight" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, rpi_backlight_of_match); ++ ++static struct platform_driver rpi_backlight_driver = { ++ .driver = { ++ .name = "rpi-backlight", ++ .of_match_table = of_match_ptr(rpi_backlight_of_match), ++ }, ++ .probe = rpi_backlight_probe, ++}; ++ ++module_platform_driver(rpi_backlight_driver); ++ ++MODULE_AUTHOR("Gordon Hollingworth "); ++MODULE_DESCRIPTION("Raspberry Pi mailbox based Backlight Driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/brcm2708/patches-4.9/0086-bcm2835-virtgpio-Virtual-GPIO-driver.patch b/target/linux/brcm2708/patches-4.9/0086-bcm2835-virtgpio-Virtual-GPIO-driver.patch new file mode 100644 index 0000000000..425224e5a5 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0086-bcm2835-virtgpio-Virtual-GPIO-driver.patch @@ -0,0 +1,267 @@ +From 1b6bee75a64ca43404e6bc8ff2fdbe8b1d0a0423 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 23 Feb 2016 19:56:04 +0000 +Subject: [PATCH] bcm2835-virtgpio: Virtual GPIO driver + +Add a virtual GPIO driver that uses the firmware mailbox interface to +request that the VPU toggles LEDs. +--- + drivers/gpio/Kconfig | 6 + + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-bcm-virt.c | 214 +++++++++++++++++++++++++++++ + include/soc/bcm2835/raspberrypi-firmware.h | 1 + + 4 files changed, 222 insertions(+) + create mode 100644 drivers/gpio/gpio-bcm-virt.c + +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -134,6 +134,12 @@ config GPIO_BCM_KONA + help + Turn on GPIO support for Broadcom "Kona" chips. + ++config GPIO_BCM_VIRT ++ bool "Broadcom Virt GPIO" ++ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || COMPILE_TEST) ++ help ++ Turn on virtual GPIO support for Broadcom BCM283X chips. ++ + config GPIO_BRCMSTB + tristate "BRCMSTB GPIO support" + default y if (ARCH_BRCMSTB || BMIPS_GENERIC) +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -31,6 +31,7 @@ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o + obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o + obj-$(CONFIG_GPIO_AXP209) += gpio-axp209.o + obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o ++obj-$(CONFIG_GPIO_BCM_VIRT) += gpio-bcm-virt.o + obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o + obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o + obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o +--- /dev/null ++++ b/drivers/gpio/gpio-bcm-virt.c +@@ -0,0 +1,214 @@ ++/* ++ * brcmvirt GPIO driver ++ * ++ * Copyright (C) 2012,2013 Dom Cobley ++ * Based on gpio-clps711x.c by Alexander Shiyan ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MODULE_NAME "brcmvirt-gpio" ++#define NUM_GPIO 2 ++ ++struct brcmvirt_gpio { ++ struct gpio_chip gc; ++ u32 __iomem *ts_base; ++ /* two packed 16-bit counts of enabled and disables ++ Allows host to detect a brief enable that was missed */ ++ u32 enables_disables[NUM_GPIO]; ++ dma_addr_t bus_addr; ++}; ++ ++static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off) ++{ ++ struct brcmvirt_gpio *gpio; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ return -EINVAL; ++} ++ ++static int brcmvirt_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) ++{ ++ struct brcmvirt_gpio *gpio; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ return 0; ++} ++ ++static int brcmvirt_gpio_get(struct gpio_chip *gc, unsigned off) ++{ ++ struct brcmvirt_gpio *gpio; ++ unsigned v; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ v = readl(gpio->ts_base + off); ++ return (v >> off) & 1; ++} ++ ++static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val) ++{ ++ struct brcmvirt_gpio *gpio; ++ u16 enables, disables; ++ s16 diff; ++ bool lit; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ enables = gpio->enables_disables[off] >> 16; ++ disables = gpio->enables_disables[off] >> 0; ++ diff = (s16)(enables - disables); ++ lit = diff > 0; ++ if ((val && lit) || (!val && !lit)) ++ return; ++ if (val) ++ enables++; ++ else ++ disables++; ++ diff = (s16)(enables - disables); ++ BUG_ON(diff != 0 && diff != 1); ++ gpio->enables_disables[off] = (enables << 16) | (disables << 0); ++ writel(gpio->enables_disables[off], gpio->ts_base + off); ++} ++ ++static int brcmvirt_gpio_probe(struct platform_device *pdev) ++{ ++ int err = 0; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct device_node *fw_node; ++ struct rpi_firmware *fw; ++ struct brcmvirt_gpio *ucb; ++ u32 gpiovirtbuf; ++ ++ fw_node = of_parse_phandle(np, "firmware", 0); ++ if (!fw_node) { ++ dev_err(dev, "Missing firmware node\n"); ++ return -ENOENT; ++ } ++ ++ fw = rpi_firmware_get(fw_node); ++ if (!fw) ++ return -EPROBE_DEFER; ++ ++ ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL); ++ if (!ucb) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ ucb->ts_base = dma_zalloc_coherent(dev, PAGE_SIZE, &ucb->bus_addr, GFP_KERNEL); ++ if (!ucb->ts_base) { ++ pr_err("[%s]: failed to dma_alloc_coherent(%ld)\n", ++ __func__, PAGE_SIZE); ++ err = -ENOMEM; ++ goto out; ++ } ++ ++ gpiovirtbuf = (u32)ucb->bus_addr; ++ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF, ++ &gpiovirtbuf, sizeof(gpiovirtbuf)); ++ ++ if (err || gpiovirtbuf != 0) { ++ dev_warn(dev, "Failed to set gpiovirtbuf, trying to get err:%x\n", err); ++ dma_free_coherent(dev, PAGE_SIZE, ucb->ts_base, ucb->bus_addr); ++ ucb->ts_base = 0; ++ ucb->bus_addr = 0; ++ } ++ ++ if (!ucb->ts_base) { ++ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF, ++ &gpiovirtbuf, sizeof(gpiovirtbuf)); ++ ++ if (err) { ++ dev_err(dev, "Failed to get gpiovirtbuf\n"); ++ goto out; ++ } ++ ++ if (!gpiovirtbuf) { ++ dev_err(dev, "No virtgpio buffer\n"); ++ err = -ENOENT; ++ goto out; ++ } ++ ++ // mmap the physical memory ++ gpiovirtbuf &= ~0xc0000000; ++ ucb->ts_base = ioremap(gpiovirtbuf, 4096); ++ if (ucb->ts_base == NULL) { ++ dev_err(dev, "Failed to map physical address\n"); ++ err = -ENOENT; ++ goto out; ++ } ++ ucb->bus_addr = 0; ++ } ++ ucb->gc.label = MODULE_NAME; ++ ucb->gc.owner = THIS_MODULE; ++ //ucb->gc.dev = dev; ++ ucb->gc.of_node = np; ++ ucb->gc.base = 100; ++ ucb->gc.ngpio = NUM_GPIO; ++ ++ ucb->gc.direction_input = brcmvirt_gpio_dir_in; ++ ucb->gc.direction_output = brcmvirt_gpio_dir_out; ++ ucb->gc.get = brcmvirt_gpio_get; ++ ucb->gc.set = brcmvirt_gpio_set; ++ ucb->gc.can_sleep = true; ++ ++ err = gpiochip_add(&ucb->gc); ++ if (err) ++ goto out; ++ ++ platform_set_drvdata(pdev, ucb); ++ ++ return 0; ++out: ++ if (ucb->bus_addr) { ++ dma_free_coherent(dev, PAGE_SIZE, ucb->ts_base, ucb->bus_addr); ++ ucb->bus_addr = 0; ++ ucb->ts_base = NULL; ++ } else if (ucb->ts_base) { ++ iounmap(ucb->ts_base); ++ ucb->ts_base = NULL; ++ } ++ return err; ++} ++ ++static int brcmvirt_gpio_remove(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ int err = 0; ++ struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev); ++ ++ gpiochip_remove(&ucb->gc); ++ if (ucb->bus_addr) ++ dma_free_coherent(dev, PAGE_SIZE, ucb->ts_base, ucb->bus_addr); ++ else if (ucb->ts_base) ++ iounmap(ucb->ts_base); ++ return err; ++} ++ ++static const struct of_device_id __maybe_unused brcmvirt_gpio_ids[] = { ++ { .compatible = "brcm,bcm2835-virtgpio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, brcmvirt_gpio_ids); ++ ++static struct platform_driver brcmvirt_gpio_driver = { ++ .driver = { ++ .name = MODULE_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(brcmvirt_gpio_ids), ++ }, ++ .probe = brcmvirt_gpio_probe, ++ .remove = brcmvirt_gpio_remove, ++}; ++module_platform_driver(brcmvirt_gpio_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Dom Cobley "); ++MODULE_DESCRIPTION("brcmvirt GPIO driver"); ++MODULE_ALIAS("platform:brcmvirt-gpio"); +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -116,6 +116,7 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, + RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b, + RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020, + RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e, + RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, + diff --git a/target/linux/brcm2708/patches-4.9/0086-rpi_display-add-backlight-driver-and-overlay.patch b/target/linux/brcm2708/patches-4.9/0086-rpi_display-add-backlight-driver-and-overlay.patch deleted file mode 100644 index 4706e7ae93..0000000000 --- a/target/linux/brcm2708/patches-4.9/0086-rpi_display-add-backlight-driver-and-overlay.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 42d919a6d8c63ca32dd6caee1288d58319e0e22e Mon Sep 17 00:00:00 2001 -From: P33M -Date: Wed, 21 Oct 2015 14:55:21 +0100 -Subject: [PATCH] rpi_display: add backlight driver and overlay - -Add a mailbox-driven backlight controller for the Raspberry Pi DSI -touchscreen display. Requires updated GPU firmware to recognise the -mailbox request. - -Signed-off-by: Gordon Hollingworth ---- - drivers/video/backlight/Kconfig | 6 ++ - drivers/video/backlight/Makefile | 1 + - drivers/video/backlight/rpi_backlight.c | 119 ++++++++++++++++++++++++++++++++ - 3 files changed, 126 insertions(+) - create mode 100644 drivers/video/backlight/rpi_backlight.c - ---- a/drivers/video/backlight/Kconfig -+++ b/drivers/video/backlight/Kconfig -@@ -265,6 +265,12 @@ config BACKLIGHT_PWM - If you have a LCD backlight adjustable by PWM, say Y to enable - this driver. - -+config BACKLIGHT_RPI -+ tristate "Raspberry Pi display firmware driven backlight" -+ help -+ If you have the Raspberry Pi DSI touchscreen display, say Y to -+ enable the mailbox-controlled backlight driver. -+ - config BACKLIGHT_DA903X - tristate "Backlight Driver for DA9030/DA9034 using WLED" - depends on PMIC_DA903X ---- a/drivers/video/backlight/Makefile -+++ b/drivers/video/backlight/Makefile -@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pand - obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o - obj-$(CONFIG_BACKLIGHT_PM8941_WLED) += pm8941-wled.o - obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o -+obj-$(CONFIG_BACKLIGHT_RPI) += rpi_backlight.o - obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o - obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o - obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o ---- /dev/null -+++ b/drivers/video/backlight/rpi_backlight.c -@@ -0,0 +1,119 @@ -+/* -+ * rpi_bl.c - Backlight controller through VPU -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct rpi_backlight { -+ struct device *dev; -+ struct device *fbdev; -+ struct rpi_firmware *fw; -+}; -+ -+static int rpi_backlight_update_status(struct backlight_device *bl) -+{ -+ struct rpi_backlight *gbl = bl_get_data(bl); -+ int brightness = bl->props.brightness; -+ int ret; -+ -+ if (bl->props.power != FB_BLANK_UNBLANK || -+ bl->props.fb_blank != FB_BLANK_UNBLANK || -+ bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) -+ brightness = 0; -+ -+ ret = rpi_firmware_property(gbl->fw, -+ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT, -+ &brightness, sizeof(brightness)); -+ if (ret) { -+ dev_err(gbl->dev, "Failed to set brightness\n"); -+ return ret; -+ } -+ -+ if (brightness < 0) { -+ dev_err(gbl->dev, "Backlight change failed\n"); -+ return -EAGAIN; -+ } -+ -+ return 0; -+} -+ -+static const struct backlight_ops rpi_backlight_ops = { -+ .options = BL_CORE_SUSPENDRESUME, -+ .update_status = rpi_backlight_update_status, -+}; -+ -+static int rpi_backlight_probe(struct platform_device *pdev) -+{ -+ struct backlight_properties props; -+ struct backlight_device *bl; -+ struct rpi_backlight *gbl; -+ struct device_node *fw_node; -+ -+ gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL); -+ if (gbl == NULL) -+ return -ENOMEM; -+ -+ gbl->dev = &pdev->dev; -+ -+ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); -+ if (!fw_node) { -+ dev_err(&pdev->dev, "Missing firmware node\n"); -+ return -ENOENT; -+ } -+ -+ gbl->fw = rpi_firmware_get(fw_node); -+ if (!gbl->fw) -+ return -EPROBE_DEFER; -+ -+ memset(&props, 0, sizeof(props)); -+ props.type = BACKLIGHT_RAW; -+ props.max_brightness = 255; -+ bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), -+ &pdev->dev, gbl, &rpi_backlight_ops, -+ &props); -+ if (IS_ERR(bl)) { -+ dev_err(&pdev->dev, "failed to register backlight\n"); -+ return PTR_ERR(bl); -+ } -+ -+ bl->props.brightness = 255; -+ backlight_update_status(bl); -+ -+ platform_set_drvdata(pdev, bl); -+ return 0; -+} -+ -+static const struct of_device_id rpi_backlight_of_match[] = { -+ { .compatible = "raspberrypi,rpi-backlight" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, rpi_backlight_of_match); -+ -+static struct platform_driver rpi_backlight_driver = { -+ .driver = { -+ .name = "rpi-backlight", -+ .of_match_table = of_match_ptr(rpi_backlight_of_match), -+ }, -+ .probe = rpi_backlight_probe, -+}; -+ -+module_platform_driver(rpi_backlight_driver); -+ -+MODULE_AUTHOR("Gordon Hollingworth "); -+MODULE_DESCRIPTION("Raspberry Pi mailbox based Backlight Driver"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/brcm2708/patches-4.9/0087-amba_pl011-Don-t-use-DT-aliases-for-numbering.patch b/target/linux/brcm2708/patches-4.9/0087-amba_pl011-Don-t-use-DT-aliases-for-numbering.patch new file mode 100644 index 0000000000..40963de876 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0087-amba_pl011-Don-t-use-DT-aliases-for-numbering.patch @@ -0,0 +1,29 @@ +From b34475b447c7e97fa9c4a854849f6e856fe59931 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 23 Feb 2016 17:26:48 +0000 +Subject: [PATCH] amba_pl011: Don't use DT aliases for numbering + +The pl011 driver looks for DT aliases of the form "serial", +and if found uses as the device ID. This can cause +/dev/ttyAMA0 to become /dev/ttyAMA1, which is confusing if the +other serial port is provided by the 8250 driver which doesn't +use the same logic. +--- + drivers/tty/serial/amba-pl011.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -2441,7 +2441,12 @@ static int pl011_setup_port(struct devic + if (IS_ERR(base)) + return PTR_ERR(base); + ++ /* Don't use DT serial aliases - it causes the device to ++ be renumbered to ttyAMA1 if it is the second serial port in the ++ system, even though the other one is ttyS0. The 8250 driver ++ doesn't use this logic, so always remains ttyS0. + index = pl011_probe_dt_alias(index, dev); ++ */ + + uap->old_cr = 0; + uap->port.dev = dev; diff --git a/target/linux/brcm2708/patches-4.9/0087-bcm2835-virtgpio-Virtual-GPIO-driver.patch b/target/linux/brcm2708/patches-4.9/0087-bcm2835-virtgpio-Virtual-GPIO-driver.patch deleted file mode 100644 index ce523e289d..0000000000 --- a/target/linux/brcm2708/patches-4.9/0087-bcm2835-virtgpio-Virtual-GPIO-driver.patch +++ /dev/null @@ -1,267 +0,0 @@ -From 1b4e68b09ba226afac9414b11f89d3b833236e13 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 23 Feb 2016 19:56:04 +0000 -Subject: [PATCH] bcm2835-virtgpio: Virtual GPIO driver - -Add a virtual GPIO driver that uses the firmware mailbox interface to -request that the VPU toggles LEDs. ---- - drivers/gpio/Kconfig | 6 + - drivers/gpio/Makefile | 1 + - drivers/gpio/gpio-bcm-virt.c | 214 +++++++++++++++++++++++++++++ - include/soc/bcm2835/raspberrypi-firmware.h | 1 + - 4 files changed, 222 insertions(+) - create mode 100644 drivers/gpio/gpio-bcm-virt.c - ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -134,6 +134,12 @@ config GPIO_BCM_KONA - help - Turn on GPIO support for Broadcom "Kona" chips. - -+config GPIO_BCM_VIRT -+ bool "Broadcom Virt GPIO" -+ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || COMPILE_TEST) -+ help -+ Turn on virtual GPIO support for Broadcom BCM283X chips. -+ - config GPIO_BRCMSTB - tristate "BRCMSTB GPIO support" - default y if (ARCH_BRCMSTB || BMIPS_GENERIC) ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -31,6 +31,7 @@ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o - obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o - obj-$(CONFIG_GPIO_AXP209) += gpio-axp209.o - obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o -+obj-$(CONFIG_GPIO_BCM_VIRT) += gpio-bcm-virt.o - obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o - obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o - obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o ---- /dev/null -+++ b/drivers/gpio/gpio-bcm-virt.c -@@ -0,0 +1,214 @@ -+/* -+ * brcmvirt GPIO driver -+ * -+ * Copyright (C) 2012,2013 Dom Cobley -+ * Based on gpio-clps711x.c by Alexander Shiyan -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MODULE_NAME "brcmvirt-gpio" -+#define NUM_GPIO 2 -+ -+struct brcmvirt_gpio { -+ struct gpio_chip gc; -+ u32 __iomem *ts_base; -+ /* two packed 16-bit counts of enabled and disables -+ Allows host to detect a brief enable that was missed */ -+ u32 enables_disables[NUM_GPIO]; -+ dma_addr_t bus_addr; -+}; -+ -+static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off) -+{ -+ struct brcmvirt_gpio *gpio; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ return -EINVAL; -+} -+ -+static int brcmvirt_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) -+{ -+ struct brcmvirt_gpio *gpio; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ return 0; -+} -+ -+static int brcmvirt_gpio_get(struct gpio_chip *gc, unsigned off) -+{ -+ struct brcmvirt_gpio *gpio; -+ unsigned v; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ v = readl(gpio->ts_base + off); -+ return (v >> off) & 1; -+} -+ -+static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val) -+{ -+ struct brcmvirt_gpio *gpio; -+ u16 enables, disables; -+ s16 diff; -+ bool lit; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ enables = gpio->enables_disables[off] >> 16; -+ disables = gpio->enables_disables[off] >> 0; -+ diff = (s16)(enables - disables); -+ lit = diff > 0; -+ if ((val && lit) || (!val && !lit)) -+ return; -+ if (val) -+ enables++; -+ else -+ disables++; -+ diff = (s16)(enables - disables); -+ BUG_ON(diff != 0 && diff != 1); -+ gpio->enables_disables[off] = (enables << 16) | (disables << 0); -+ writel(gpio->enables_disables[off], gpio->ts_base + off); -+} -+ -+static int brcmvirt_gpio_probe(struct platform_device *pdev) -+{ -+ int err = 0; -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct device_node *fw_node; -+ struct rpi_firmware *fw; -+ struct brcmvirt_gpio *ucb; -+ u32 gpiovirtbuf; -+ -+ fw_node = of_parse_phandle(np, "firmware", 0); -+ if (!fw_node) { -+ dev_err(dev, "Missing firmware node\n"); -+ return -ENOENT; -+ } -+ -+ fw = rpi_firmware_get(fw_node); -+ if (!fw) -+ return -EPROBE_DEFER; -+ -+ ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL); -+ if (!ucb) { -+ err = -EINVAL; -+ goto out; -+ } -+ -+ ucb->ts_base = dma_zalloc_coherent(dev, PAGE_SIZE, &ucb->bus_addr, GFP_KERNEL); -+ if (!ucb->ts_base) { -+ pr_err("[%s]: failed to dma_alloc_coherent(%ld)\n", -+ __func__, PAGE_SIZE); -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ gpiovirtbuf = (u32)ucb->bus_addr; -+ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF, -+ &gpiovirtbuf, sizeof(gpiovirtbuf)); -+ -+ if (err || gpiovirtbuf != 0) { -+ dev_warn(dev, "Failed to set gpiovirtbuf, trying to get err:%x\n", err); -+ dma_free_coherent(dev, PAGE_SIZE, ucb->ts_base, ucb->bus_addr); -+ ucb->ts_base = 0; -+ ucb->bus_addr = 0; -+ } -+ -+ if (!ucb->ts_base) { -+ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF, -+ &gpiovirtbuf, sizeof(gpiovirtbuf)); -+ -+ if (err) { -+ dev_err(dev, "Failed to get gpiovirtbuf\n"); -+ goto out; -+ } -+ -+ if (!gpiovirtbuf) { -+ dev_err(dev, "No virtgpio buffer\n"); -+ err = -ENOENT; -+ goto out; -+ } -+ -+ // mmap the physical memory -+ gpiovirtbuf &= ~0xc0000000; -+ ucb->ts_base = ioremap(gpiovirtbuf, 4096); -+ if (ucb->ts_base == NULL) { -+ dev_err(dev, "Failed to map physical address\n"); -+ err = -ENOENT; -+ goto out; -+ } -+ ucb->bus_addr = 0; -+ } -+ ucb->gc.label = MODULE_NAME; -+ ucb->gc.owner = THIS_MODULE; -+ //ucb->gc.dev = dev; -+ ucb->gc.of_node = np; -+ ucb->gc.base = 100; -+ ucb->gc.ngpio = NUM_GPIO; -+ -+ ucb->gc.direction_input = brcmvirt_gpio_dir_in; -+ ucb->gc.direction_output = brcmvirt_gpio_dir_out; -+ ucb->gc.get = brcmvirt_gpio_get; -+ ucb->gc.set = brcmvirt_gpio_set; -+ ucb->gc.can_sleep = true; -+ -+ err = gpiochip_add(&ucb->gc); -+ if (err) -+ goto out; -+ -+ platform_set_drvdata(pdev, ucb); -+ -+ return 0; -+out: -+ if (ucb->bus_addr) { -+ dma_free_coherent(dev, PAGE_SIZE, ucb->ts_base, ucb->bus_addr); -+ ucb->bus_addr = 0; -+ ucb->ts_base = NULL; -+ } else if (ucb->ts_base) { -+ iounmap(ucb->ts_base); -+ ucb->ts_base = NULL; -+ } -+ return err; -+} -+ -+static int brcmvirt_gpio_remove(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ int err = 0; -+ struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev); -+ -+ gpiochip_remove(&ucb->gc); -+ if (ucb->bus_addr) -+ dma_free_coherent(dev, PAGE_SIZE, ucb->ts_base, ucb->bus_addr); -+ else if (ucb->ts_base) -+ iounmap(ucb->ts_base); -+ return err; -+} -+ -+static const struct of_device_id __maybe_unused brcmvirt_gpio_ids[] = { -+ { .compatible = "brcm,bcm2835-virtgpio" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, brcmvirt_gpio_ids); -+ -+static struct platform_driver brcmvirt_gpio_driver = { -+ .driver = { -+ .name = MODULE_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(brcmvirt_gpio_ids), -+ }, -+ .probe = brcmvirt_gpio_probe, -+ .remove = brcmvirt_gpio_remove, -+}; -+module_platform_driver(brcmvirt_gpio_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Dom Cobley "); -+MODULE_DESCRIPTION("brcmvirt GPIO driver"); -+MODULE_ALIAS("platform:brcmvirt-gpio"); ---- a/include/soc/bcm2835/raspberrypi-firmware.h -+++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -116,6 +116,7 @@ enum rpi_firmware_property_tag { - RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, - RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b, - RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, -+ RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020, - RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e, - RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, - diff --git a/target/linux/brcm2708/patches-4.9/0088-amba_pl011-Don-t-use-DT-aliases-for-numbering.patch b/target/linux/brcm2708/patches-4.9/0088-amba_pl011-Don-t-use-DT-aliases-for-numbering.patch deleted file mode 100644 index 1f69465d3e..0000000000 --- a/target/linux/brcm2708/patches-4.9/0088-amba_pl011-Don-t-use-DT-aliases-for-numbering.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0c3101c247b410c7e73dbb3ede7d0031fb622044 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 23 Feb 2016 17:26:48 +0000 -Subject: [PATCH] amba_pl011: Don't use DT aliases for numbering - -The pl011 driver looks for DT aliases of the form "serial", -and if found uses as the device ID. This can cause -/dev/ttyAMA0 to become /dev/ttyAMA1, which is confusing if the -other serial port is provided by the 8250 driver which doesn't -use the same logic. ---- - drivers/tty/serial/amba-pl011.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -2441,7 +2441,12 @@ static int pl011_setup_port(struct devic - if (IS_ERR(base)) - return PTR_ERR(base); - -+ /* Don't use DT serial aliases - it causes the device to -+ be renumbered to ttyAMA1 if it is the second serial port in the -+ system, even though the other one is ttyS0. The 8250 driver -+ doesn't use this logic, so always remains ttyS0. - index = pl011_probe_dt_alias(index, dev); -+ */ - - uap->old_cr = 0; - uap->port.dev = dev; diff --git a/target/linux/brcm2708/patches-4.9/0090-OF-DT-Overlay-configfs-interface.patch b/target/linux/brcm2708/patches-4.9/0090-OF-DT-Overlay-configfs-interface.patch new file mode 100644 index 0000000000..941047adc5 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0090-OF-DT-Overlay-configfs-interface.patch @@ -0,0 +1,424 @@ +From ef4a8376af32bb6722e1ea933a9e1a83ebc8f175 Mon Sep 17 00:00:00 2001 +From: Pantelis Antoniou +Date: Wed, 3 Dec 2014 13:23:28 +0200 +Subject: [PATCH] OF: DT-Overlay configfs interface + +This is a port of Pantelis Antoniou's v3 port that makes use of the +new upstreamed configfs support for binary attributes. + +Original commit message: + +Add a runtime interface to using configfs for generic device tree overlay +usage. With it its possible to use device tree overlays without having +to use a per-platform overlay manager. + +Please see Documentation/devicetree/configfs-overlays.txt for more info. + +Changes since v2: +- Removed ifdef CONFIG_OF_OVERLAY (since for now it's required) +- Created a documentation entry +- Slight rewording in Kconfig + +Changes since v1: +- of_resolve() -> of_resolve_phandles(). + +Originally-signed-off-by: Pantelis Antoniou +Signed-off-by: Phil Elwell + +DT configfs: Fix build errors on other platforms + +Signed-off-by: Phil Elwell + +DT configfs: fix build error + +There is an error when compiling rpi-4.6.y branch: + CC drivers/of/configfs.o +drivers/of/configfs.c:291:21: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] + .default_groups = of_cfs_def_groups, + ^ +drivers/of/configfs.c:291:21: note: (near initialization for 'of_cfs_subsys.su_group.default_groups.next') + +The .default_groups is linked list since commit +1ae1602de028acaa42a0f6ff18d19756f8e825c6. +This commit uses configfs_add_default_group to fix this problem. + +Signed-off-by: Slawomir Stepien +--- + Documentation/devicetree/configfs-overlays.txt | 31 +++ + drivers/of/Kconfig | 7 + + drivers/of/Makefile | 1 + + drivers/of/configfs.c | 311 +++++++++++++++++++++++++ + 4 files changed, 350 insertions(+) + create mode 100644 Documentation/devicetree/configfs-overlays.txt + create mode 100644 drivers/of/configfs.c + +--- /dev/null ++++ b/Documentation/devicetree/configfs-overlays.txt +@@ -0,0 +1,31 @@ ++Howto use the configfs overlay interface. ++ ++A device-tree configfs entry is created in /config/device-tree/overlays ++and and it is manipulated using standard file system I/O. ++Note that this is a debug level interface, for use by developers and ++not necessarily something accessed by normal users due to the ++security implications of having direct access to the kernel's device tree. ++ ++* To create an overlay you mkdir the directory: ++ ++ # mkdir /config/device-tree/overlays/foo ++ ++* Either you echo the overlay firmware file to the path property file. ++ ++ # echo foo.dtbo >/config/device-tree/overlays/foo/path ++ ++* Or you cat the contents of the overlay to the dtbo file ++ ++ # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo ++ ++The overlay file will be applied, and devices will be created/destroyed ++as required. ++ ++To remove it simply rmdir the directory. ++ ++ # rmdir /config/device-tree/overlays/foo ++ ++The rationalle of the dual interface (firmware & direct copy) is that each is ++better suited to different use patterns. The firmware interface is what's ++intended to be used by hardware managers in the kernel, while the copy interface ++make sense for developers (since it avoids problems with namespaces). +--- a/drivers/of/Kconfig ++++ b/drivers/of/Kconfig +@@ -112,4 +112,11 @@ config OF_OVERLAY + config OF_NUMA + bool + ++config OF_CONFIGFS ++ bool "Device Tree Overlay ConfigFS interface" ++ select CONFIGFS_FS ++ select OF_OVERLAY ++ help ++ Enable a simple user-space driven DT overlay interface. ++ + endif # OF +--- a/drivers/of/Makefile ++++ b/drivers/of/Makefile +@@ -1,4 +1,5 @@ + obj-y = base.o device.o platform.o ++obj-$(CONFIG_OF_CONFIGFS) += configfs.o + obj-$(CONFIG_OF_DYNAMIC) += dynamic.o + obj-$(CONFIG_OF_FLATTREE) += fdt.o + obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o +--- /dev/null ++++ b/drivers/of/configfs.c +@@ -0,0 +1,311 @@ ++/* ++ * Configfs entries for device-tree ++ * ++ * Copyright (C) 2013 - Pantelis Antoniou ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "of_private.h" ++ ++struct cfs_overlay_item { ++ struct config_item item; ++ ++ char path[PATH_MAX]; ++ ++ const struct firmware *fw; ++ struct device_node *overlay; ++ int ov_id; ++ ++ void *dtbo; ++ int dtbo_size; ++}; ++ ++static int create_overlay(struct cfs_overlay_item *overlay, void *blob) ++{ ++ int err; ++ ++ /* unflatten the tree */ ++ of_fdt_unflatten_tree(blob, NULL, &overlay->overlay); ++ if (overlay->overlay == NULL) { ++ pr_err("%s: failed to unflatten tree\n", __func__); ++ err = -EINVAL; ++ goto out_err; ++ } ++ pr_debug("%s: unflattened OK\n", __func__); ++ ++ /* mark it as detached */ ++ of_node_set_flag(overlay->overlay, OF_DETACHED); ++ ++ /* perform resolution */ ++ err = of_resolve_phandles(overlay->overlay); ++ if (err != 0) { ++ pr_err("%s: Failed to resolve tree\n", __func__); ++ goto out_err; ++ } ++ pr_debug("%s: resolved OK\n", __func__); ++ ++ err = of_overlay_create(overlay->overlay); ++ if (err < 0) { ++ pr_err("%s: Failed to create overlay (err=%d)\n", ++ __func__, err); ++ goto out_err; ++ } ++ overlay->ov_id = err; ++ ++out_err: ++ return err; ++} ++ ++static inline struct cfs_overlay_item *to_cfs_overlay_item( ++ struct config_item *item) ++{ ++ return item ? container_of(item, struct cfs_overlay_item, item) : NULL; ++} ++ ++static ssize_t cfs_overlay_item_path_show(struct config_item *item, ++ char *page) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ return sprintf(page, "%s\n", overlay->path); ++} ++ ++static ssize_t cfs_overlay_item_path_store(struct config_item *item, ++ const char *page, size_t count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ const char *p = page; ++ char *s; ++ int err; ++ ++ /* if it's set do not allow changes */ ++ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) ++ return -EPERM; ++ ++ /* copy to path buffer (and make sure it's always zero terminated */ ++ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); ++ overlay->path[sizeof(overlay->path) - 1] = '\0'; ++ ++ /* strip trailing newlines */ ++ s = overlay->path + strlen(overlay->path); ++ while (s > overlay->path && *--s == '\n') ++ *s = '\0'; ++ ++ pr_debug("%s: path is '%s'\n", __func__, overlay->path); ++ ++ err = request_firmware(&overlay->fw, overlay->path, NULL); ++ if (err != 0) ++ goto out_err; ++ ++ err = create_overlay(overlay, (void *)overlay->fw->data); ++ if (err != 0) ++ goto out_err; ++ ++ return count; ++ ++out_err: ++ ++ release_firmware(overlay->fw); ++ overlay->fw = NULL; ++ ++ overlay->path[0] = '\0'; ++ return err; ++} ++ ++static ssize_t cfs_overlay_item_status_show(struct config_item *item, ++ char *page) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ return sprintf(page, "%s\n", ++ overlay->ov_id >= 0 ? "applied" : "unapplied"); ++} ++ ++CONFIGFS_ATTR(cfs_overlay_item_, path); ++CONFIGFS_ATTR_RO(cfs_overlay_item_, status); ++ ++static struct configfs_attribute *cfs_overlay_attrs[] = { ++ &cfs_overlay_item_attr_path, ++ &cfs_overlay_item_attr_status, ++ NULL, ++}; ++ ++ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, ++ void *buf, size_t max_count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ pr_debug("%s: buf=%p max_count=%zu\n", __func__, ++ buf, max_count); ++ ++ if (overlay->dtbo == NULL) ++ return 0; ++ ++ /* copy if buffer provided */ ++ if (buf != NULL) { ++ /* the buffer must be large enough */ ++ if (overlay->dtbo_size > max_count) ++ return -ENOSPC; ++ ++ memcpy(buf, overlay->dtbo, overlay->dtbo_size); ++ } ++ ++ return overlay->dtbo_size; ++} ++ ++ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, ++ const void *buf, size_t count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ int err; ++ ++ /* if it's set do not allow changes */ ++ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) ++ return -EPERM; ++ ++ /* copy the contents */ ++ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); ++ if (overlay->dtbo == NULL) ++ return -ENOMEM; ++ ++ overlay->dtbo_size = count; ++ ++ err = create_overlay(overlay, overlay->dtbo); ++ if (err != 0) ++ goto out_err; ++ ++ return count; ++ ++out_err: ++ kfree(overlay->dtbo); ++ overlay->dtbo = NULL; ++ overlay->dtbo_size = 0; ++ ++ return err; ++} ++ ++CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); ++ ++static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { ++ &cfs_overlay_item_attr_dtbo, ++ NULL, ++}; ++ ++static void cfs_overlay_release(struct config_item *item) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ if (overlay->ov_id >= 0) ++ of_overlay_destroy(overlay->ov_id); ++ if (overlay->fw) ++ release_firmware(overlay->fw); ++ /* kfree with NULL is safe */ ++ kfree(overlay->dtbo); ++ kfree(overlay); ++} ++ ++static struct configfs_item_operations cfs_overlay_item_ops = { ++ .release = cfs_overlay_release, ++}; ++ ++static struct config_item_type cfs_overlay_type = { ++ .ct_item_ops = &cfs_overlay_item_ops, ++ .ct_attrs = cfs_overlay_attrs, ++ .ct_bin_attrs = cfs_overlay_bin_attrs, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct config_item *cfs_overlay_group_make_item( ++ struct config_group *group, const char *name) ++{ ++ struct cfs_overlay_item *overlay; ++ ++ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); ++ if (!overlay) ++ return ERR_PTR(-ENOMEM); ++ overlay->ov_id = -1; ++ ++ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); ++ return &overlay->item; ++} ++ ++static void cfs_overlay_group_drop_item(struct config_group *group, ++ struct config_item *item) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ config_item_put(&overlay->item); ++} ++ ++static struct configfs_group_operations overlays_ops = { ++ .make_item = cfs_overlay_group_make_item, ++ .drop_item = cfs_overlay_group_drop_item, ++}; ++ ++static struct config_item_type overlays_type = { ++ .ct_group_ops = &overlays_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct configfs_group_operations of_cfs_ops = { ++ /* empty - we don't allow anything to be created */ ++}; ++ ++static struct config_item_type of_cfs_type = { ++ .ct_group_ops = &of_cfs_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++struct config_group of_cfs_overlay_group; ++ ++static struct configfs_subsystem of_cfs_subsys = { ++ .su_group = { ++ .cg_item = { ++ .ci_namebuf = "device-tree", ++ .ci_type = &of_cfs_type, ++ }, ++ }, ++ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), ++}; ++ ++static int __init of_cfs_init(void) ++{ ++ int ret; ++ ++ pr_info("%s\n", __func__); ++ ++ config_group_init(&of_cfs_subsys.su_group); ++ config_group_init_type_name(&of_cfs_overlay_group, "overlays", ++ &overlays_type); ++ configfs_add_default_group(&of_cfs_overlay_group, ++ &of_cfs_subsys.su_group); ++ ++ ret = configfs_register_subsystem(&of_cfs_subsys); ++ if (ret != 0) { ++ pr_err("%s: failed to register subsys\n", __func__); ++ goto out; ++ } ++ pr_info("%s: OK\n", __func__); ++out: ++ return ret; ++} ++late_initcall(of_cfs_init); diff --git a/target/linux/brcm2708/patches-4.9/0091-OF-DT-Overlay-configfs-interface.patch b/target/linux/brcm2708/patches-4.9/0091-OF-DT-Overlay-configfs-interface.patch deleted file mode 100644 index c864eba323..0000000000 --- a/target/linux/brcm2708/patches-4.9/0091-OF-DT-Overlay-configfs-interface.patch +++ /dev/null @@ -1,424 +0,0 @@ -From af8af738c62584683c75cbcbbd80ac4425c8986c Mon Sep 17 00:00:00 2001 -From: Pantelis Antoniou -Date: Wed, 3 Dec 2014 13:23:28 +0200 -Subject: [PATCH] OF: DT-Overlay configfs interface - -This is a port of Pantelis Antoniou's v3 port that makes use of the -new upstreamed configfs support for binary attributes. - -Original commit message: - -Add a runtime interface to using configfs for generic device tree overlay -usage. With it its possible to use device tree overlays without having -to use a per-platform overlay manager. - -Please see Documentation/devicetree/configfs-overlays.txt for more info. - -Changes since v2: -- Removed ifdef CONFIG_OF_OVERLAY (since for now it's required) -- Created a documentation entry -- Slight rewording in Kconfig - -Changes since v1: -- of_resolve() -> of_resolve_phandles(). - -Originally-signed-off-by: Pantelis Antoniou -Signed-off-by: Phil Elwell - -DT configfs: Fix build errors on other platforms - -Signed-off-by: Phil Elwell - -DT configfs: fix build error - -There is an error when compiling rpi-4.6.y branch: - CC drivers/of/configfs.o -drivers/of/configfs.c:291:21: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] - .default_groups = of_cfs_def_groups, - ^ -drivers/of/configfs.c:291:21: note: (near initialization for 'of_cfs_subsys.su_group.default_groups.next') - -The .default_groups is linked list since commit -1ae1602de028acaa42a0f6ff18d19756f8e825c6. -This commit uses configfs_add_default_group to fix this problem. - -Signed-off-by: Slawomir Stepien ---- - Documentation/devicetree/configfs-overlays.txt | 31 +++ - drivers/of/Kconfig | 7 + - drivers/of/Makefile | 1 + - drivers/of/configfs.c | 311 +++++++++++++++++++++++++ - 4 files changed, 350 insertions(+) - create mode 100644 Documentation/devicetree/configfs-overlays.txt - create mode 100644 drivers/of/configfs.c - ---- /dev/null -+++ b/Documentation/devicetree/configfs-overlays.txt -@@ -0,0 +1,31 @@ -+Howto use the configfs overlay interface. -+ -+A device-tree configfs entry is created in /config/device-tree/overlays -+and and it is manipulated using standard file system I/O. -+Note that this is a debug level interface, for use by developers and -+not necessarily something accessed by normal users due to the -+security implications of having direct access to the kernel's device tree. -+ -+* To create an overlay you mkdir the directory: -+ -+ # mkdir /config/device-tree/overlays/foo -+ -+* Either you echo the overlay firmware file to the path property file. -+ -+ # echo foo.dtbo >/config/device-tree/overlays/foo/path -+ -+* Or you cat the contents of the overlay to the dtbo file -+ -+ # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo -+ -+The overlay file will be applied, and devices will be created/destroyed -+as required. -+ -+To remove it simply rmdir the directory. -+ -+ # rmdir /config/device-tree/overlays/foo -+ -+The rationalle of the dual interface (firmware & direct copy) is that each is -+better suited to different use patterns. The firmware interface is what's -+intended to be used by hardware managers in the kernel, while the copy interface -+make sense for developers (since it avoids problems with namespaces). ---- a/drivers/of/Kconfig -+++ b/drivers/of/Kconfig -@@ -112,4 +112,11 @@ config OF_OVERLAY - config OF_NUMA - bool - -+config OF_CONFIGFS -+ bool "Device Tree Overlay ConfigFS interface" -+ select CONFIGFS_FS -+ select OF_OVERLAY -+ help -+ Enable a simple user-space driven DT overlay interface. -+ - endif # OF ---- a/drivers/of/Makefile -+++ b/drivers/of/Makefile -@@ -1,4 +1,5 @@ - obj-y = base.o device.o platform.o -+obj-$(CONFIG_OF_CONFIGFS) += configfs.o - obj-$(CONFIG_OF_DYNAMIC) += dynamic.o - obj-$(CONFIG_OF_FLATTREE) += fdt.o - obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o ---- /dev/null -+++ b/drivers/of/configfs.c -@@ -0,0 +1,311 @@ -+/* -+ * Configfs entries for device-tree -+ * -+ * Copyright (C) 2013 - Pantelis Antoniou -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "of_private.h" -+ -+struct cfs_overlay_item { -+ struct config_item item; -+ -+ char path[PATH_MAX]; -+ -+ const struct firmware *fw; -+ struct device_node *overlay; -+ int ov_id; -+ -+ void *dtbo; -+ int dtbo_size; -+}; -+ -+static int create_overlay(struct cfs_overlay_item *overlay, void *blob) -+{ -+ int err; -+ -+ /* unflatten the tree */ -+ of_fdt_unflatten_tree(blob, NULL, &overlay->overlay); -+ if (overlay->overlay == NULL) { -+ pr_err("%s: failed to unflatten tree\n", __func__); -+ err = -EINVAL; -+ goto out_err; -+ } -+ pr_debug("%s: unflattened OK\n", __func__); -+ -+ /* mark it as detached */ -+ of_node_set_flag(overlay->overlay, OF_DETACHED); -+ -+ /* perform resolution */ -+ err = of_resolve_phandles(overlay->overlay); -+ if (err != 0) { -+ pr_err("%s: Failed to resolve tree\n", __func__); -+ goto out_err; -+ } -+ pr_debug("%s: resolved OK\n", __func__); -+ -+ err = of_overlay_create(overlay->overlay); -+ if (err < 0) { -+ pr_err("%s: Failed to create overlay (err=%d)\n", -+ __func__, err); -+ goto out_err; -+ } -+ overlay->ov_id = err; -+ -+out_err: -+ return err; -+} -+ -+static inline struct cfs_overlay_item *to_cfs_overlay_item( -+ struct config_item *item) -+{ -+ return item ? container_of(item, struct cfs_overlay_item, item) : NULL; -+} -+ -+static ssize_t cfs_overlay_item_path_show(struct config_item *item, -+ char *page) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ return sprintf(page, "%s\n", overlay->path); -+} -+ -+static ssize_t cfs_overlay_item_path_store(struct config_item *item, -+ const char *page, size_t count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ const char *p = page; -+ char *s; -+ int err; -+ -+ /* if it's set do not allow changes */ -+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) -+ return -EPERM; -+ -+ /* copy to path buffer (and make sure it's always zero terminated */ -+ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); -+ overlay->path[sizeof(overlay->path) - 1] = '\0'; -+ -+ /* strip trailing newlines */ -+ s = overlay->path + strlen(overlay->path); -+ while (s > overlay->path && *--s == '\n') -+ *s = '\0'; -+ -+ pr_debug("%s: path is '%s'\n", __func__, overlay->path); -+ -+ err = request_firmware(&overlay->fw, overlay->path, NULL); -+ if (err != 0) -+ goto out_err; -+ -+ err = create_overlay(overlay, (void *)overlay->fw->data); -+ if (err != 0) -+ goto out_err; -+ -+ return count; -+ -+out_err: -+ -+ release_firmware(overlay->fw); -+ overlay->fw = NULL; -+ -+ overlay->path[0] = '\0'; -+ return err; -+} -+ -+static ssize_t cfs_overlay_item_status_show(struct config_item *item, -+ char *page) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ return sprintf(page, "%s\n", -+ overlay->ov_id >= 0 ? "applied" : "unapplied"); -+} -+ -+CONFIGFS_ATTR(cfs_overlay_item_, path); -+CONFIGFS_ATTR_RO(cfs_overlay_item_, status); -+ -+static struct configfs_attribute *cfs_overlay_attrs[] = { -+ &cfs_overlay_item_attr_path, -+ &cfs_overlay_item_attr_status, -+ NULL, -+}; -+ -+ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, -+ void *buf, size_t max_count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ pr_debug("%s: buf=%p max_count=%zu\n", __func__, -+ buf, max_count); -+ -+ if (overlay->dtbo == NULL) -+ return 0; -+ -+ /* copy if buffer provided */ -+ if (buf != NULL) { -+ /* the buffer must be large enough */ -+ if (overlay->dtbo_size > max_count) -+ return -ENOSPC; -+ -+ memcpy(buf, overlay->dtbo, overlay->dtbo_size); -+ } -+ -+ return overlay->dtbo_size; -+} -+ -+ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, -+ const void *buf, size_t count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ int err; -+ -+ /* if it's set do not allow changes */ -+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) -+ return -EPERM; -+ -+ /* copy the contents */ -+ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); -+ if (overlay->dtbo == NULL) -+ return -ENOMEM; -+ -+ overlay->dtbo_size = count; -+ -+ err = create_overlay(overlay, overlay->dtbo); -+ if (err != 0) -+ goto out_err; -+ -+ return count; -+ -+out_err: -+ kfree(overlay->dtbo); -+ overlay->dtbo = NULL; -+ overlay->dtbo_size = 0; -+ -+ return err; -+} -+ -+CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); -+ -+static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { -+ &cfs_overlay_item_attr_dtbo, -+ NULL, -+}; -+ -+static void cfs_overlay_release(struct config_item *item) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ if (overlay->ov_id >= 0) -+ of_overlay_destroy(overlay->ov_id); -+ if (overlay->fw) -+ release_firmware(overlay->fw); -+ /* kfree with NULL is safe */ -+ kfree(overlay->dtbo); -+ kfree(overlay); -+} -+ -+static struct configfs_item_operations cfs_overlay_item_ops = { -+ .release = cfs_overlay_release, -+}; -+ -+static struct config_item_type cfs_overlay_type = { -+ .ct_item_ops = &cfs_overlay_item_ops, -+ .ct_attrs = cfs_overlay_attrs, -+ .ct_bin_attrs = cfs_overlay_bin_attrs, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct config_item *cfs_overlay_group_make_item( -+ struct config_group *group, const char *name) -+{ -+ struct cfs_overlay_item *overlay; -+ -+ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); -+ if (!overlay) -+ return ERR_PTR(-ENOMEM); -+ overlay->ov_id = -1; -+ -+ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); -+ return &overlay->item; -+} -+ -+static void cfs_overlay_group_drop_item(struct config_group *group, -+ struct config_item *item) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ config_item_put(&overlay->item); -+} -+ -+static struct configfs_group_operations overlays_ops = { -+ .make_item = cfs_overlay_group_make_item, -+ .drop_item = cfs_overlay_group_drop_item, -+}; -+ -+static struct config_item_type overlays_type = { -+ .ct_group_ops = &overlays_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct configfs_group_operations of_cfs_ops = { -+ /* empty - we don't allow anything to be created */ -+}; -+ -+static struct config_item_type of_cfs_type = { -+ .ct_group_ops = &of_cfs_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+struct config_group of_cfs_overlay_group; -+ -+static struct configfs_subsystem of_cfs_subsys = { -+ .su_group = { -+ .cg_item = { -+ .ci_namebuf = "device-tree", -+ .ci_type = &of_cfs_type, -+ }, -+ }, -+ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), -+}; -+ -+static int __init of_cfs_init(void) -+{ -+ int ret; -+ -+ pr_info("%s\n", __func__); -+ -+ config_group_init(&of_cfs_subsys.su_group); -+ config_group_init_type_name(&of_cfs_overlay_group, "overlays", -+ &overlays_type); -+ configfs_add_default_group(&of_cfs_overlay_group, -+ &of_cfs_subsys.su_group); -+ -+ ret = configfs_register_subsystem(&of_cfs_subsys); -+ if (ret != 0) { -+ pr_err("%s: failed to register subsys\n", __func__); -+ goto out; -+ } -+ pr_info("%s: OK\n", __func__); -+out: -+ return ret; -+} -+late_initcall(of_cfs_init); diff --git a/target/linux/brcm2708/patches-4.9/0092-hci_h5-Don-t-send-conf_req-when-ACTIVE.patch b/target/linux/brcm2708/patches-4.9/0092-hci_h5-Don-t-send-conf_req-when-ACTIVE.patch new file mode 100644 index 0000000000..780a211c8c --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0092-hci_h5-Don-t-send-conf_req-when-ACTIVE.patch @@ -0,0 +1,23 @@ +From 0224b0469a7f5c2ee6420aac66e89e3206029633 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 17 Dec 2015 13:37:07 +0000 +Subject: [PATCH] hci_h5: Don't send conf_req when ACTIVE + +Without this patch, a modem and kernel can continuously bombard each +other with conf_req and conf_rsp messages, in a demented game of tag. +--- + drivers/bluetooth/hci_h5.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -310,7 +310,8 @@ static void h5_handle_internal_rx(struct + h5_link_control(hu, conf_req, 3); + } else if (memcmp(data, conf_req, 2) == 0) { + h5_link_control(hu, conf_rsp, 2); +- h5_link_control(hu, conf_req, 3); ++ if (h5->state != H5_ACTIVE) ++ h5_link_control(hu, conf_req, 3); + } else if (memcmp(data, conf_rsp, 2) == 0) { + if (H5_HDR_LEN(hdr) > 2) + h5->tx_win = (data[2] & 0x07); diff --git a/target/linux/brcm2708/patches-4.9/0093-config-Add-default-configs.patch b/target/linux/brcm2708/patches-4.9/0093-config-Add-default-configs.patch new file mode 100644 index 0000000000..da92f04b4c --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0093-config-Add-default-configs.patch @@ -0,0 +1,2623 @@ +From 9455097dbb0c961edb6a47b451e18a985f5d9a3f Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 13 Apr 2015 17:16:29 +0100 +Subject: [PATCH] config: Add default configs + +--- + arch/arm/configs/bcm2709_defconfig | 1297 +++++++++++++++++++++++++++++++++++ + arch/arm/configs/bcmrpi_defconfig | 1308 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 2605 insertions(+) + create mode 100644 arch/arm/configs/bcm2709_defconfig + create mode 100644 arch/arm/configs/bcmrpi_defconfig + +--- /dev/null ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -0,0 +1,1297 @@ ++CONFIG_LOCALVERSION="-v7" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y ++CONFIG_NMI_LOG_BUF_SHIFT=12 ++CONFIG_MEMCG=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CPUSETS=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_NAMESPACES=y ++CONFIG_USER_NS=y ++CONFIG_SCHED_AUTOGROUP=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_EMBEDDED=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_PROFILING=y ++CONFIG_OPROFILE=m ++CONFIG_KPROBES=y ++CONFIG_JUMP_LABEL=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_BLK_DEV_THROTTLING=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_MAC_PARTITION=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++CONFIG_ARCH_BCM=y ++CONFIG_ARCH_BCM2835=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_SMP=y ++CONFIG_VMSPLIT_2G=y ++CONFIG_PREEMPT_VOLUNTARY=y ++CONFIG_AEABI=y ++# CONFIG_CPU_SW_DOMAIN_PAN is not set ++CONFIG_CLEANCACHE=y ++CONFIG_FRONTSWAP=y ++CONFIG_CMA=y ++CONFIG_ZSMALLOC=m ++CONFIG_PGTABLE_MAPPING=y ++CONFIG_UACCESS_WITH_MEMCPY=y ++CONFIG_SECCOMP=y ++# CONFIG_ATAGS is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y ++CONFIG_VFP=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_BINFMT_MISC=m ++# CONFIG_SUSPEND is not set ++CONFIG_PM=y ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM_USER=y ++CONFIG_NET_KEY=m ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NET_IPGRE=m ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m ++CONFIG_INET_IPCOMP=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_DIAG=m ++CONFIG_IPV6=m ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_SUBTREES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y ++CONFIG_NETFILTER=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_ZONES=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++CONFIG_NF_CT_PROTO_DCCP=m ++CONFIG_NF_CT_PROTO_UDPLITE=m ++CONFIG_NF_CONNTRACK_AMANDA=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_CONNTRACK_H323=m ++CONFIG_NF_CONNTRACK_IRC=m ++CONFIG_NF_CONNTRACK_NETBIOS_NS=m ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++CONFIG_NF_CONNTRACK_SANE=m ++CONFIG_NF_CONNTRACK_SIP=m ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_NETFILTER_XT_SET=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HMARK=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_LED=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TPROXY=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_NETFILTER_XT_MATCH_BPF=m ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_NFACCT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SOCKET=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++CONFIG_IP_SET=m ++CONFIG_IP_SET_BITMAP_IP=m ++CONFIG_IP_SET_BITMAP_IPMAC=m ++CONFIG_IP_SET_BITMAP_PORT=m ++CONFIG_IP_SET_HASH_IP=m ++CONFIG_IP_SET_HASH_IPPORT=m ++CONFIG_IP_SET_HASH_IPPORTIP=m ++CONFIG_IP_SET_HASH_IPPORTNET=m ++CONFIG_IP_SET_HASH_NET=m ++CONFIG_IP_SET_HASH_NETPORT=m ++CONFIG_IP_SET_HASH_NETIFACE=m ++CONFIG_IP_SET_LIST_SET=m ++CONFIG_IP_VS=m ++CONFIG_IP_VS_PROTO_TCP=y ++CONFIG_IP_VS_PROTO_UDP=y ++CONFIG_IP_VS_PROTO_ESP=y ++CONFIG_IP_VS_PROTO_AH=y ++CONFIG_IP_VS_PROTO_SCTP=y ++CONFIG_IP_VS_RR=m ++CONFIG_IP_VS_WRR=m ++CONFIG_IP_VS_LC=m ++CONFIG_IP_VS_WLC=m ++CONFIG_IP_VS_LBLC=m ++CONFIG_IP_VS_LBLCR=m ++CONFIG_IP_VS_DH=m ++CONFIG_IP_VS_SH=m ++CONFIG_IP_VS_SED=m ++CONFIG_IP_VS_NQ=m ++CONFIG_IP_VS_FTP=m ++CONFIG_IP_VS_PE_SIP=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_RPFILTER=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_CLUSTERIP=m ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=m ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RPFILTER=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP6_NF_RAW=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_NPT=m ++CONFIG_BRIDGE_NF_EBTABLES=m ++CONFIG_BRIDGE_EBT_BROUTE=m ++CONFIG_BRIDGE_EBT_T_FILTER=m ++CONFIG_BRIDGE_EBT_T_NAT=m ++CONFIG_BRIDGE_EBT_802_3=m ++CONFIG_BRIDGE_EBT_AMONG=m ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++CONFIG_BRIDGE_EBT_LIMIT=m ++CONFIG_BRIDGE_EBT_MARK=m ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++CONFIG_BRIDGE_EBT_STP=m ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=m ++CONFIG_BRIDGE_EBT_MARK_T=m ++CONFIG_BRIDGE_EBT_REDIRECT=m ++CONFIG_BRIDGE_EBT_SNAT=m ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_NFLOG=m ++CONFIG_SCTP_COOKIE_HMAC_SHA1=y ++CONFIG_ATM=m ++CONFIG_L2TP=m ++CONFIG_L2TP_V3=y ++CONFIG_L2TP_IP=m ++CONFIG_L2TP_ETH=m ++CONFIG_BRIDGE=m ++CONFIG_VLAN_8021Q=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_ATALK=m ++CONFIG_6LOWPAN=m ++CONFIG_IEEE802154=m ++CONFIG_IEEE802154_6LOWPAN=m ++CONFIG_MAC802154=m ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_MULTIQ=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFB=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_SCH_DRR=m ++CONFIG_NET_SCH_MQPRIO=m ++CONFIG_NET_SCH_CHOKE=m ++CONFIG_NET_SCH_QFQ=m ++CONFIG_NET_SCH_CODEL=m ++CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_INGRESS=m ++CONFIG_NET_SCH_PLUG=m ++CONFIG_NET_CLS_BASIC=m ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_CLS_U32_MARK=y ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_FLOW=m ++CONFIG_NET_CLS_CGROUP=m ++CONFIG_NET_EMATCH=y ++CONFIG_NET_EMATCH_CMP=m ++CONFIG_NET_EMATCH_NBYTE=m ++CONFIG_NET_EMATCH_U32=m ++CONFIG_NET_EMATCH_META=m ++CONFIG_NET_EMATCH_TEXT=m ++CONFIG_NET_EMATCH_IPSET=m ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_GACT_PROB=y ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m ++CONFIG_BATMAN_ADV=m ++CONFIG_OPENVSWITCH=m ++CONFIG_NET_PKTGEN=m ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++CONFIG_MKISS=m ++CONFIG_6PACK=m ++CONFIG_BPQETHER=m ++CONFIG_BAYCOM_SER_FDX=m ++CONFIG_BAYCOM_SER_HDX=m ++CONFIG_YAM=m ++CONFIG_CAN=m ++CONFIG_CAN_VCAN=m ++CONFIG_CAN_MCP251X=m ++CONFIG_IRDA=m ++CONFIG_IRLAN=m ++CONFIG_IRNET=m ++CONFIG_IRCOMM=m ++CONFIG_IRDA_ULTRA=y ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++CONFIG_IRTTY_SIR=m ++CONFIG_KINGSUN_DONGLE=m ++CONFIG_KSDAZZLE_DONGLE=m ++CONFIG_KS959_DONGLE=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_MCS_FIR=m ++CONFIG_BT=m ++CONFIG_BT_RFCOMM=m ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_BNEP=m ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HIDP=m ++CONFIG_BT_6LOWPAN=m ++CONFIG_BT_HCIBTUSB=m ++CONFIG_BT_HCIUART=m ++CONFIG_BT_HCIUART_3WIRE=y ++CONFIG_BT_HCIUART_BCM=y ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++CONFIG_BT_MRVL=m ++CONFIG_BT_MRVL_SDIO=m ++CONFIG_BT_ATH3K=m ++CONFIG_BT_WILINK=m ++CONFIG_CFG80211=m ++CONFIG_MAC80211=m ++CONFIG_MAC80211_MESH=y ++CONFIG_WIMAX=m ++CONFIG_RFKILL=m ++CONFIG_RFKILL_INPUT=y ++CONFIG_NET_9P=m ++CONFIG_NFC=m ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_MTD=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_NAND=m ++CONFIG_MTD_UBI=m ++CONFIG_OF_CONFIGFS=y ++CONFIG_ZRAM=m ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_CRYPTOLOOP=m ++CONFIG_BLK_DEV_DRBD=m ++CONFIG_BLK_DEV_NBD=m ++CONFIG_BLK_DEV_RAM=y ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_ATA_OVER_ETH=m ++CONFIG_EEPROM_AT24=m ++CONFIG_TI_ST=m ++CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=m ++CONFIG_CHR_DEV_OSST=m ++CONFIG_BLK_DEV_SR=m ++CONFIG_CHR_DEV_SG=m ++CONFIG_SCSI_ISCSI_ATTRS=y ++CONFIG_ISCSI_TCP=m ++CONFIG_ISCSI_BOOT_SYSFS=m ++CONFIG_MD=y ++CONFIG_MD_LINEAR=m ++CONFIG_MD_RAID0=m ++CONFIG_BLK_DEV_DM=m ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++CONFIG_DM_THIN_PROVISIONING=m ++CONFIG_DM_MIRROR=m ++CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_RAID=m ++CONFIG_DM_ZERO=m ++CONFIG_DM_DELAY=m ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=m ++CONFIG_DUMMY=m ++CONFIG_IFB=m ++CONFIG_MACVLAN=m ++CONFIG_VXLAN=m ++CONFIG_NETCONSOLE=m ++CONFIG_TUN=m ++CONFIG_VETH=m ++CONFIG_ENC28J60=m ++CONFIG_QCA7000=m ++CONFIG_MDIO_BITBANG=m ++CONFIG_PPP=m ++CONFIG_PPP_BSDCOMP=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MPPE=m ++CONFIG_PPP_MULTILINK=y ++CONFIG_PPPOATM=m ++CONFIG_PPPOE=m ++CONFIG_PPPOL2TP=m ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_SLIP=m ++CONFIG_SLIP_COMPRESSED=y ++CONFIG_SLIP_SMART=y ++CONFIG_USB_CATC=m ++CONFIG_USB_KAWETH=m ++CONFIG_USB_PEGASUS=m ++CONFIG_USB_RTL8150=m ++CONFIG_USB_RTL8152=m ++CONFIG_USB_USBNET=y ++CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_AX88179_178A=m ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_CDC_NCM=m ++CONFIG_USB_NET_HUAWEI_CDC_NCM=m ++CONFIG_USB_NET_CDC_MBIM=m ++CONFIG_USB_NET_DM9601=m ++CONFIG_USB_NET_SR9700=m ++CONFIG_USB_NET_SR9800=m ++CONFIG_USB_NET_SMSC75XX=m ++CONFIG_USB_NET_SMSC95XX=y ++CONFIG_USB_NET_GL620A=m ++CONFIG_USB_NET_NET1080=m ++CONFIG_USB_NET_PLUSB=m ++CONFIG_USB_NET_MCS7830=m ++CONFIG_USB_NET_CDC_SUBSET=m ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_EPSON2888=y ++CONFIG_USB_KC2190=y ++CONFIG_USB_NET_ZAURUS=m ++CONFIG_USB_NET_CX82310_ETH=m ++CONFIG_USB_NET_KALMIA=m ++CONFIG_USB_NET_QMI_WWAN=m ++CONFIG_USB_HSO=m ++CONFIG_USB_NET_INT51X1=m ++CONFIG_USB_IPHETH=m ++CONFIG_USB_SIERRA_NET=m ++CONFIG_USB_VL600=m ++CONFIG_ATH9K=m ++CONFIG_ATH9K_HTC=m ++CONFIG_CARL9170=m ++CONFIG_ATH6KL=m ++CONFIG_ATH6KL_USB=m ++CONFIG_AR5523=m ++CONFIG_AT76C50X_USB=m ++CONFIG_B43=m ++# CONFIG_B43_PHY_N is not set ++CONFIG_B43LEGACY=m ++CONFIG_BRCMFMAC=m ++CONFIG_BRCMFMAC_USB=y ++CONFIG_HOSTAP=m ++CONFIG_P54_COMMON=m ++CONFIG_P54_USB=m ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++CONFIG_LIBERTAS_SDIO=m ++CONFIG_LIBERTAS_THINFIRM=m ++CONFIG_LIBERTAS_THINFIRM_USB=m ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++CONFIG_MT7601U=m ++CONFIG_RT2X00=m ++CONFIG_RT2500USB=m ++CONFIG_RT73USB=m ++CONFIG_RT2800USB=m ++CONFIG_RT2800USB_RT3573=y ++CONFIG_RT2800USB_RT53XX=y ++CONFIG_RT2800USB_RT55XX=y ++CONFIG_RT2800USB_UNKNOWN=y ++CONFIG_RTL8187=m ++CONFIG_RTL8192CU=m ++CONFIG_USB_ZD1201=m ++CONFIG_ZD1211RW=m ++CONFIG_MAC80211_HWSIM=m ++CONFIG_USB_NET_RNDIS_WLAN=m ++CONFIG_WIMAX_I2400M_USB=m ++CONFIG_IEEE802154_AT86RF230=m ++CONFIG_IEEE802154_MRF24J40=m ++CONFIG_IEEE802154_CC2520=m ++CONFIG_INPUT_POLLDEV=m ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_JOYDEV=m ++CONFIG_INPUT_EVDEV=m ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_INPUT_JOYSTICK=y ++CONFIG_JOYSTICK_IFORCE=m ++CONFIG_JOYSTICK_IFORCE_USB=y ++CONFIG_JOYSTICK_XPAD=m ++CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y ++CONFIG_JOYSTICK_RPISENSE=m ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ADS7846=m ++CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_EKTF2127=m ++CONFIG_TOUCHSCREEN_RPI_FT5406=m ++CONFIG_TOUCHSCREEN_USB_COMPOSITE=m ++CONFIG_TOUCHSCREEN_STMPE=m ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_AD714X=m ++CONFIG_INPUT_ATI_REMOTE2=m ++CONFIG_INPUT_KEYSPAN_REMOTE=m ++CONFIG_INPUT_POWERMATE=m ++CONFIG_INPUT_YEALINK=m ++CONFIG_INPUT_CM109=m ++CONFIG_INPUT_UINPUT=m ++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m ++CONFIG_INPUT_ADXL34X=m ++CONFIG_INPUT_CMA3000=m ++CONFIG_SERIO=m ++CONFIG_SERIO_RAW=m ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++CONFIG_BRCM_CHAR_DRIVERS=y ++CONFIG_BCM_VC_CMA=y ++CONFIG_BCM_VCIO=y ++CONFIG_BCM_VC_SM=y ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_DMA is not set ++CONFIG_SERIAL_8250_NR_UARTS=1 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=0 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_BCM2835AUX=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_SERIAL_SC16IS7XX=m ++CONFIG_SERIAL_SC16IS7XX_SPI=y ++CONFIG_TTY_PRINTK=y ++CONFIG_HW_RANDOM=y ++CONFIG_RAW_DRIVER=y ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_MUX_PCA954x=m ++CONFIG_I2C_BCM2708=m ++CONFIG_I2C_BCM2835=m ++CONFIG_I2C_GPIO=m ++CONFIG_SPI=y ++CONFIG_SPI_BCM2835=m ++CONFIG_SPI_BCM2835AUX=m ++CONFIG_SPI_SPIDEV=y ++CONFIG_PPS=m ++CONFIG_PPS_CLIENT_LDISC=m ++CONFIG_PPS_CLIENT_GPIO=m ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_BCM_VIRT=y ++CONFIG_GPIO_ARIZONA=m ++CONFIG_GPIO_STMPE=y ++CONFIG_GPIO_MCP23S08=m ++CONFIG_W1=m ++CONFIG_W1_MASTER_DS2490=m ++CONFIG_W1_MASTER_DS2482=m ++CONFIG_W1_MASTER_DS1WM=m ++CONFIG_W1_MASTER_GPIO=m ++CONFIG_W1_SLAVE_THERM=m ++CONFIG_W1_SLAVE_SMEM=m ++CONFIG_W1_SLAVE_DS2408=m ++CONFIG_W1_SLAVE_DS2413=m ++CONFIG_W1_SLAVE_DS2406=m ++CONFIG_W1_SLAVE_DS2423=m ++CONFIG_W1_SLAVE_DS2431=m ++CONFIG_W1_SLAVE_DS2433=m ++CONFIG_W1_SLAVE_DS2760=m ++CONFIG_W1_SLAVE_DS2780=m ++CONFIG_W1_SLAVE_DS2781=m ++CONFIG_W1_SLAVE_DS28E04=m ++CONFIG_W1_SLAVE_BQ27000=m ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO=y ++CONFIG_BATTERY_DS2760=m ++CONFIG_HWMON=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_SHT21=m ++CONFIG_SENSORS_SHTC1=m ++CONFIG_SENSORS_INA2XX=m ++CONFIG_THERMAL=y ++CONFIG_THERMAL_BCM2835=y ++CONFIG_WATCHDOG=y ++CONFIG_BCM2835_WDT=y ++CONFIG_UCB1400_CORE=m ++CONFIG_MFD_STMPE=y ++CONFIG_STMPE_SPI=y ++CONFIG_MFD_ARIZONA_I2C=m ++CONFIG_MFD_ARIZONA_SPI=m ++CONFIG_MFD_WM5102=y ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y ++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y ++CONFIG_MEDIA_RADIO_SUPPORT=y ++CONFIG_MEDIA_RC_SUPPORT=y ++CONFIG_MEDIA_CONTROLLER=y ++CONFIG_LIRC=m ++CONFIG_RC_DEVICES=y ++CONFIG_RC_ATI_REMOTE=m ++CONFIG_IR_IMON=m ++CONFIG_IR_MCEUSB=m ++CONFIG_IR_REDRAT3=m ++CONFIG_IR_STREAMZAP=m ++CONFIG_IR_IGUANA=m ++CONFIG_IR_TTUSBIR=m ++CONFIG_RC_LOOPBACK=m ++CONFIG_IR_GPIO_CIR=m ++CONFIG_MEDIA_USB_SUPPORT=y ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_USB_M5602=m ++CONFIG_USB_STV06XX=m ++CONFIG_USB_GL860=m ++CONFIG_USB_GSPCA_BENQ=m ++CONFIG_USB_GSPCA_CONEX=m ++CONFIG_USB_GSPCA_CPIA1=m ++CONFIG_USB_GSPCA_DTCS033=m ++CONFIG_USB_GSPCA_ETOMS=m ++CONFIG_USB_GSPCA_FINEPIX=m ++CONFIG_USB_GSPCA_JEILINJ=m ++CONFIG_USB_GSPCA_JL2005BCD=m ++CONFIG_USB_GSPCA_KINECT=m ++CONFIG_USB_GSPCA_KONICA=m ++CONFIG_USB_GSPCA_MARS=m ++CONFIG_USB_GSPCA_MR97310A=m ++CONFIG_USB_GSPCA_NW80X=m ++CONFIG_USB_GSPCA_OV519=m ++CONFIG_USB_GSPCA_OV534=m ++CONFIG_USB_GSPCA_OV534_9=m ++CONFIG_USB_GSPCA_PAC207=m ++CONFIG_USB_GSPCA_PAC7302=m ++CONFIG_USB_GSPCA_PAC7311=m ++CONFIG_USB_GSPCA_SE401=m ++CONFIG_USB_GSPCA_SN9C2028=m ++CONFIG_USB_GSPCA_SN9C20X=m ++CONFIG_USB_GSPCA_SONIXB=m ++CONFIG_USB_GSPCA_SONIXJ=m ++CONFIG_USB_GSPCA_SPCA500=m ++CONFIG_USB_GSPCA_SPCA501=m ++CONFIG_USB_GSPCA_SPCA505=m ++CONFIG_USB_GSPCA_SPCA506=m ++CONFIG_USB_GSPCA_SPCA508=m ++CONFIG_USB_GSPCA_SPCA561=m ++CONFIG_USB_GSPCA_SPCA1528=m ++CONFIG_USB_GSPCA_SQ905=m ++CONFIG_USB_GSPCA_SQ905C=m ++CONFIG_USB_GSPCA_SQ930X=m ++CONFIG_USB_GSPCA_STK014=m ++CONFIG_USB_GSPCA_STK1135=m ++CONFIG_USB_GSPCA_STV0680=m ++CONFIG_USB_GSPCA_SUNPLUS=m ++CONFIG_USB_GSPCA_T613=m ++CONFIG_USB_GSPCA_TOPRO=m ++CONFIG_USB_GSPCA_TV8532=m ++CONFIG_USB_GSPCA_VC032X=m ++CONFIG_USB_GSPCA_VICAM=m ++CONFIG_USB_GSPCA_XIRLINK_CIT=m ++CONFIG_USB_GSPCA_ZC3XX=m ++CONFIG_USB_PWC=m ++CONFIG_VIDEO_CPIA2=m ++CONFIG_USB_ZR364XX=m ++CONFIG_USB_STKWEBCAM=m ++CONFIG_USB_S2255=m ++CONFIG_VIDEO_USBTV=m ++CONFIG_VIDEO_PVRUSB2=m ++CONFIG_VIDEO_HDPVR=m ++CONFIG_VIDEO_USBVISION=m ++CONFIG_VIDEO_STK1160_COMMON=m ++CONFIG_VIDEO_STK1160_AC97=y ++CONFIG_VIDEO_GO7007=m ++CONFIG_VIDEO_GO7007_USB=m ++CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m ++CONFIG_VIDEO_AU0828=m ++CONFIG_VIDEO_AU0828_RC=y ++CONFIG_VIDEO_CX231XX=m ++CONFIG_VIDEO_CX231XX_ALSA=m ++CONFIG_VIDEO_CX231XX_DVB=m ++CONFIG_VIDEO_TM6000=m ++CONFIG_VIDEO_TM6000_ALSA=m ++CONFIG_VIDEO_TM6000_DVB=m ++CONFIG_DVB_USB=m ++CONFIG_DVB_USB_A800=m ++CONFIG_DVB_USB_DIBUSB_MB=m ++CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y ++CONFIG_DVB_USB_DIBUSB_MC=m ++CONFIG_DVB_USB_DIB0700=m ++CONFIG_DVB_USB_UMT_010=m ++CONFIG_DVB_USB_CXUSB=m ++CONFIG_DVB_USB_M920X=m ++CONFIG_DVB_USB_DIGITV=m ++CONFIG_DVB_USB_VP7045=m ++CONFIG_DVB_USB_VP702X=m ++CONFIG_DVB_USB_GP8PSK=m ++CONFIG_DVB_USB_NOVA_T_USB2=m ++CONFIG_DVB_USB_TTUSB2=m ++CONFIG_DVB_USB_DTT200U=m ++CONFIG_DVB_USB_OPERA1=m ++CONFIG_DVB_USB_AF9005=m ++CONFIG_DVB_USB_AF9005_REMOTE=m ++CONFIG_DVB_USB_PCTV452E=m ++CONFIG_DVB_USB_DW2102=m ++CONFIG_DVB_USB_CINERGY_T2=m ++CONFIG_DVB_USB_DTV5100=m ++CONFIG_DVB_USB_FRIIO=m ++CONFIG_DVB_USB_AZ6027=m ++CONFIG_DVB_USB_TECHNISAT_USB2=m ++CONFIG_DVB_USB_V2=m ++CONFIG_DVB_USB_AF9015=m ++CONFIG_DVB_USB_AF9035=m ++CONFIG_DVB_USB_ANYSEE=m ++CONFIG_DVB_USB_AU6610=m ++CONFIG_DVB_USB_AZ6007=m ++CONFIG_DVB_USB_CE6230=m ++CONFIG_DVB_USB_EC168=m ++CONFIG_DVB_USB_GL861=m ++CONFIG_DVB_USB_LME2510=m ++CONFIG_DVB_USB_MXL111SF=m ++CONFIG_DVB_USB_RTL28XXU=m ++CONFIG_DVB_USB_DVBSKY=m ++CONFIG_SMS_USB_DRV=m ++CONFIG_DVB_B2C2_FLEXCOP_USB=m ++CONFIG_DVB_AS102=m ++CONFIG_VIDEO_EM28XX=m ++CONFIG_VIDEO_EM28XX_V4L2=m ++CONFIG_VIDEO_EM28XX_ALSA=m ++CONFIG_VIDEO_EM28XX_DVB=m ++CONFIG_V4L_PLATFORM_DRIVERS=y ++CONFIG_VIDEO_BCM2835=y ++CONFIG_VIDEO_BCM2835_MMAL=m ++CONFIG_RADIO_SI470X=y ++CONFIG_USB_SI470X=m ++CONFIG_I2C_SI470X=m ++CONFIG_RADIO_SI4713=m ++CONFIG_I2C_SI4713=m ++CONFIG_USB_MR800=m ++CONFIG_USB_DSBR=m ++CONFIG_RADIO_SHARK=m ++CONFIG_RADIO_SHARK2=m ++CONFIG_USB_KEENE=m ++CONFIG_USB_MA901=m ++CONFIG_RADIO_TEA5764=m ++CONFIG_RADIO_SAA7706H=m ++CONFIG_RADIO_TEF6862=m ++CONFIG_RADIO_WL1273=m ++CONFIG_RADIO_WL128X=m ++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set ++CONFIG_VIDEO_UDA1342=m ++CONFIG_VIDEO_SONY_BTF_MPX=m ++CONFIG_VIDEO_TVP5150=m ++CONFIG_VIDEO_TW2804=m ++CONFIG_VIDEO_TW9903=m ++CONFIG_VIDEO_TW9906=m ++CONFIG_VIDEO_OV7640=m ++CONFIG_VIDEO_MT9V011=m ++CONFIG_DRM=m ++CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_UDL=m ++CONFIG_DRM_VC4=m ++CONFIG_FB=y ++CONFIG_FB_BCM2708=y ++CONFIG_FB_UDL=m ++CONFIG_FB_SSD1307=m ++CONFIG_FB_RPISENSE=m ++# CONFIG_BACKLIGHT_GENERIC is not set ++CONFIG_BACKLIGHT_RPI=m ++CONFIG_BACKLIGHT_GPIO=m ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_SOUND=y ++CONFIG_SND=m ++CONFIG_SND_SEQUENCER=m ++CONFIG_SND_SEQ_DUMMY=m ++CONFIG_SND_MIXER_OSS=m ++CONFIG_SND_PCM_OSS=m ++CONFIG_SND_SEQUENCER_OSS=y ++CONFIG_SND_HRTIMER=m ++CONFIG_SND_DUMMY=m ++CONFIG_SND_ALOOP=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++CONFIG_SND_BCM2835=m ++CONFIG_SND_USB_AUDIO=m ++CONFIG_SND_USB_UA101=m ++CONFIG_SND_USB_CAIAQ=m ++CONFIG_SND_USB_CAIAQ_INPUT=y ++CONFIG_SND_USB_6FIRE=m ++CONFIG_SND_SOC=m ++CONFIG_SND_BCM2835_SOC_I2S=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_DAC=m ++CONFIG_SND_BCM2708_SOC_RPI_PROTO=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m ++CONFIG_SND_BCM2708_SOC_RASPIDAC3=m ++CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m ++CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_DIGIDAC1_SOUNDCARD=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m ++CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m ++CONFIG_SND_PISOUND=m ++CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_AK4554=m ++CONFIG_SND_SOC_WM8804_I2C=m ++CONFIG_SND_SIMPLE_CARD=m ++CONFIG_SOUND_PRIME=m ++CONFIG_HIDRAW=y ++CONFIG_UHID=m ++CONFIG_HID_A4TECH=m ++CONFIG_HID_ACRUX=m ++CONFIG_HID_APPLE=m ++CONFIG_HID_BELKIN=m ++CONFIG_HID_BETOP_FF=m ++CONFIG_HID_CHERRY=m ++CONFIG_HID_CHICONY=m ++CONFIG_HID_CYPRESS=m ++CONFIG_HID_DRAGONRISE=m ++CONFIG_HID_EMS_FF=m ++CONFIG_HID_ELECOM=m ++CONFIG_HID_ELO=m ++CONFIG_HID_EZKEY=m ++CONFIG_HID_GEMBIRD=m ++CONFIG_HID_HOLTEK=m ++CONFIG_HID_KEYTOUCH=m ++CONFIG_HID_KYE=m ++CONFIG_HID_UCLOGIC=m ++CONFIG_HID_WALTOP=m ++CONFIG_HID_GYRATION=m ++CONFIG_HID_TWINHAN=m ++CONFIG_HID_KENSINGTON=m ++CONFIG_HID_LCPOWER=m ++CONFIG_HID_LOGITECH=m ++CONFIG_HID_LOGITECH_DJ=m ++CONFIG_LOGITECH_FF=y ++CONFIG_LOGIRUMBLEPAD2_FF=y ++CONFIG_LOGIG940_FF=y ++CONFIG_HID_MAGICMOUSE=m ++CONFIG_HID_MICROSOFT=m ++CONFIG_HID_MONTEREY=m ++CONFIG_HID_MULTITOUCH=m ++CONFIG_HID_NTRIG=m ++CONFIG_HID_ORTEK=m ++CONFIG_HID_PANTHERLORD=m ++CONFIG_HID_PETALYNX=m ++CONFIG_HID_PICOLCD=m ++CONFIG_HID_ROCCAT=m ++CONFIG_HID_SAMSUNG=m ++CONFIG_HID_SONY=m ++CONFIG_HID_SPEEDLINK=m ++CONFIG_HID_SUNPLUS=m ++CONFIG_HID_GREENASIA=m ++CONFIG_HID_SMARTJOYPLUS=m ++CONFIG_HID_TOPSEED=m ++CONFIG_HID_THINGM=m ++CONFIG_HID_THRUSTMASTER=m ++CONFIG_HID_WACOM=m ++CONFIG_HID_WIIMOTE=m ++CONFIG_HID_XINMO=m ++CONFIG_HID_ZEROPLUS=m ++CONFIG_HID_ZYDACRON=m ++CONFIG_HID_PID=y ++CONFIG_USB_HIDDEV=y ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_MON=m ++CONFIG_USB_DWCOTG=y ++CONFIG_USB_PRINTER=m ++CONFIG_USB_STORAGE=y ++CONFIG_USB_STORAGE_REALTEK=m ++CONFIG_USB_STORAGE_DATAFAB=m ++CONFIG_USB_STORAGE_FREECOM=m ++CONFIG_USB_STORAGE_ISD200=m ++CONFIG_USB_STORAGE_USBAT=m ++CONFIG_USB_STORAGE_SDDR09=m ++CONFIG_USB_STORAGE_SDDR55=m ++CONFIG_USB_STORAGE_JUMPSHOT=m ++CONFIG_USB_STORAGE_ALAUDA=m ++CONFIG_USB_STORAGE_ONETOUCH=m ++CONFIG_USB_STORAGE_KARMA=m ++CONFIG_USB_STORAGE_CYPRESS_ATACB=m ++CONFIG_USB_STORAGE_ENE_UB6250=m ++CONFIG_USB_MDC800=m ++CONFIG_USB_MICROTEK=m ++CONFIG_USBIP_CORE=m ++CONFIG_USBIP_VHCI_HCD=m ++CONFIG_USBIP_HOST=m ++CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_GENERIC=y ++CONFIG_USB_SERIAL_AIRCABLE=m ++CONFIG_USB_SERIAL_ARK3116=m ++CONFIG_USB_SERIAL_BELKIN=m ++CONFIG_USB_SERIAL_CH341=m ++CONFIG_USB_SERIAL_WHITEHEAT=m ++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m ++CONFIG_USB_SERIAL_CP210X=m ++CONFIG_USB_SERIAL_CYPRESS_M8=m ++CONFIG_USB_SERIAL_EMPEG=m ++CONFIG_USB_SERIAL_FTDI_SIO=m ++CONFIG_USB_SERIAL_VISOR=m ++CONFIG_USB_SERIAL_IPAQ=m ++CONFIG_USB_SERIAL_IR=m ++CONFIG_USB_SERIAL_EDGEPORT=m ++CONFIG_USB_SERIAL_EDGEPORT_TI=m ++CONFIG_USB_SERIAL_F81232=m ++CONFIG_USB_SERIAL_GARMIN=m ++CONFIG_USB_SERIAL_IPW=m ++CONFIG_USB_SERIAL_IUU=m ++CONFIG_USB_SERIAL_KEYSPAN_PDA=m ++CONFIG_USB_SERIAL_KEYSPAN=m ++CONFIG_USB_SERIAL_KLSI=m ++CONFIG_USB_SERIAL_KOBIL_SCT=m ++CONFIG_USB_SERIAL_MCT_U232=m ++CONFIG_USB_SERIAL_METRO=m ++CONFIG_USB_SERIAL_MOS7720=m ++CONFIG_USB_SERIAL_MOS7840=m ++CONFIG_USB_SERIAL_NAVMAN=m ++CONFIG_USB_SERIAL_PL2303=m ++CONFIG_USB_SERIAL_OTI6858=m ++CONFIG_USB_SERIAL_QCAUX=m ++CONFIG_USB_SERIAL_QUALCOMM=m ++CONFIG_USB_SERIAL_SPCP8X5=m ++CONFIG_USB_SERIAL_SAFE=m ++CONFIG_USB_SERIAL_SIERRAWIRELESS=m ++CONFIG_USB_SERIAL_SYMBOL=m ++CONFIG_USB_SERIAL_TI=m ++CONFIG_USB_SERIAL_CYBERJACK=m ++CONFIG_USB_SERIAL_XIRCOM=m ++CONFIG_USB_SERIAL_OPTION=m ++CONFIG_USB_SERIAL_OMNINET=m ++CONFIG_USB_SERIAL_OPTICON=m ++CONFIG_USB_SERIAL_XSENS_MT=m ++CONFIG_USB_SERIAL_WISHBONE=m ++CONFIG_USB_SERIAL_SSU100=m ++CONFIG_USB_SERIAL_QT2=m ++CONFIG_USB_SERIAL_DEBUG=m ++CONFIG_USB_EMI62=m ++CONFIG_USB_EMI26=m ++CONFIG_USB_ADUTUX=m ++CONFIG_USB_SEVSEG=m ++CONFIG_USB_RIO500=m ++CONFIG_USB_LEGOTOWER=m ++CONFIG_USB_LCD=m ++CONFIG_USB_CYPRESS_CY7C63=m ++CONFIG_USB_CYTHERM=m ++CONFIG_USB_IDMOUSE=m ++CONFIG_USB_FTDI_ELAN=m ++CONFIG_USB_APPLEDISPLAY=m ++CONFIG_USB_LD=m ++CONFIG_USB_TRANCEVIBRATOR=m ++CONFIG_USB_IOWARRIOR=m ++CONFIG_USB_TEST=m ++CONFIG_USB_ISIGHTFW=m ++CONFIG_USB_YUREX=m ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++CONFIG_USB_CXACRU=m ++CONFIG_USB_UEAGLEATM=m ++CONFIG_USB_XUSBATM=m ++CONFIG_MMC=y ++CONFIG_MMC_BLOCK_MINORS=32 ++CONFIG_MMC_BCM2835=y ++CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_PLTFM=y ++CONFIG_MMC_SPI=m ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_ONESHOT=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_BACKLIGHT=y ++CONFIG_LEDS_TRIGGER_CPU=y ++CONFIG_LEDS_TRIGGER_GPIO=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_LEDS_TRIGGER_TRANSIENT=m ++CONFIG_LEDS_TRIGGER_CAMERA=m ++CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_LEDS_TRIGGER_PANIC=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++CONFIG_RTC_DRV_ABX80X=m ++CONFIG_RTC_DRV_DS1307=m ++CONFIG_RTC_DRV_DS1374=m ++CONFIG_RTC_DRV_DS1672=m ++CONFIG_RTC_DRV_MAX6900=m ++CONFIG_RTC_DRV_RS5C372=m ++CONFIG_RTC_DRV_ISL1208=m ++CONFIG_RTC_DRV_ISL12022=m ++CONFIG_RTC_DRV_X1205=m ++CONFIG_RTC_DRV_PCF8523=m ++CONFIG_RTC_DRV_PCF8563=m ++CONFIG_RTC_DRV_PCF8583=m ++CONFIG_RTC_DRV_M41T80=m ++CONFIG_RTC_DRV_BQ32K=m ++CONFIG_RTC_DRV_S35390A=m ++CONFIG_RTC_DRV_FM3130=m ++CONFIG_RTC_DRV_RX8581=m ++CONFIG_RTC_DRV_RX8025=m ++CONFIG_RTC_DRV_EM3027=m ++CONFIG_RTC_DRV_M41T93=m ++CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1302=m ++CONFIG_RTC_DRV_DS1305=m ++CONFIG_RTC_DRV_DS1390=m ++CONFIG_RTC_DRV_R9701=m ++CONFIG_RTC_DRV_RX4581=m ++CONFIG_RTC_DRV_RS5C348=m ++CONFIG_RTC_DRV_MAX6902=m ++CONFIG_RTC_DRV_PCF2123=m ++CONFIG_RTC_DRV_DS3232=m ++CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_RV3029C2=m ++CONFIG_DMADEVICES=y ++CONFIG_DMA_BCM2835=y ++CONFIG_DMA_BCM2708=y ++CONFIG_UIO=m ++CONFIG_UIO_PDRV_GENIRQ=m ++CONFIG_STAGING=y ++CONFIG_PRISM2_USB=m ++CONFIG_R8712U=m ++CONFIG_R8188EU=m ++CONFIG_VT6656=m ++CONFIG_SPEAKUP=m ++CONFIG_SPEAKUP_SYNTH_SOFT=m ++CONFIG_STAGING_MEDIA=y ++CONFIG_LIRC_STAGING=y ++CONFIG_LIRC_IMON=m ++CONFIG_LIRC_RPI=m ++CONFIG_LIRC_SASEM=m ++CONFIG_LIRC_SERIAL=m ++CONFIG_FB_TFT=m ++CONFIG_FB_TFT_AGM1264K_FL=m ++CONFIG_FB_TFT_BD663474=m ++CONFIG_FB_TFT_HX8340BN=m ++CONFIG_FB_TFT_HX8347D=m ++CONFIG_FB_TFT_HX8353D=m ++CONFIG_FB_TFT_HX8357D=m ++CONFIG_FB_TFT_ILI9163=m ++CONFIG_FB_TFT_ILI9320=m ++CONFIG_FB_TFT_ILI9325=m ++CONFIG_FB_TFT_ILI9340=m ++CONFIG_FB_TFT_ILI9341=m ++CONFIG_FB_TFT_ILI9481=m ++CONFIG_FB_TFT_ILI9486=m ++CONFIG_FB_TFT_PCD8544=m ++CONFIG_FB_TFT_RA8875=m ++CONFIG_FB_TFT_S6D02A1=m ++CONFIG_FB_TFT_S6D1121=m ++CONFIG_FB_TFT_SSD1289=m ++CONFIG_FB_TFT_SSD1306=m ++CONFIG_FB_TFT_SSD1331=m ++CONFIG_FB_TFT_SSD1351=m ++CONFIG_FB_TFT_ST7735R=m ++CONFIG_FB_TFT_TINYLCD=m ++CONFIG_FB_TFT_TLS8204=m ++CONFIG_FB_TFT_UC1701=m ++CONFIG_FB_TFT_UPD161704=m ++CONFIG_FB_TFT_WATTEROTT=m ++CONFIG_FB_FLEX=m ++CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2835_MBOX=y ++# CONFIG_IOMMU_SUPPORT is not set ++CONFIG_RASPBERRYPI_POWER=y ++CONFIG_EXTCON=m ++CONFIG_EXTCON_ARIZONA=m ++CONFIG_IIO=m ++CONFIG_IIO_BUFFER=y ++CONFIG_IIO_BUFFER_CB=m ++CONFIG_IIO_KFIFO_BUF=m ++CONFIG_MCP320X=m ++CONFIG_MCP3422=m ++CONFIG_DHT11=m ++CONFIG_HTU21=m ++CONFIG_PWM_BCM2835=m ++CONFIG_PWM_PCA9685=m ++CONFIG_RASPBERRYPI_FIRMWARE=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_GFS2_FS=m ++CONFIG_OCFS2_FS=m ++CONFIG_BTRFS_FS=m ++CONFIG_BTRFS_FS_POSIX_ACL=y ++CONFIG_NILFS2_FS=m ++CONFIG_F2FS_FS=y ++CONFIG_FANOTIFY=y ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_AUTOFS4_FS=y ++CONFIG_FUSE_FS=m ++CONFIG_CUSE=m ++CONFIG_OVERLAY_FS=m ++CONFIG_FSCACHE=y ++CONFIG_FSCACHE_STATS=y ++CONFIG_FSCACHE_HISTOGRAM=y ++CONFIG_CACHEFILES=y ++CONFIG_ISO9660_FS=m ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=m ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" ++CONFIG_NTFS_FS=m ++CONFIG_NTFS_RW=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_ECRYPT_FS=m ++CONFIG_HFS_FS=m ++CONFIG_HFSPLUS_FS=m ++CONFIG_JFFS2_FS=m ++CONFIG_JFFS2_SUMMARY=y ++CONFIG_UBIFS_FS=m ++CONFIG_SQUASHFS=m ++CONFIG_SQUASHFS_XATTR=y ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFS_FSCACHE=y ++CONFIG_NFSD=m ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_CIFS=m ++CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_POSIX=y ++CONFIG_CIFS_ACL=y ++CONFIG_CIFS_DFS_UPCALL=y ++CONFIG_CIFS_SMB2=y ++CONFIG_CIFS_FSCACHE=y ++CONFIG_9P_FS=m ++CONFIG_9P_FS_POSIX_ACL=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_737=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=m ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=m ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++CONFIG_DLM=m ++CONFIG_PRINTK_TIME=y ++CONFIG_BOOT_PRINTK_DELAY=y ++CONFIG_DEBUG_MEMORY_INIT=y ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_TIMER_STATS=y ++CONFIG_LATENCYTOP=y ++CONFIG_IRQSOFF_TRACER=y ++CONFIG_SCHED_TRACER=y ++CONFIG_STACK_TRACER=y ++CONFIG_BLK_DEV_IO_TRACE=y ++# CONFIG_KPROBE_EVENT is not set ++CONFIG_FUNCTION_PROFILER=y ++CONFIG_KGDB=y ++CONFIG_KGDB_KDB=y ++CONFIG_KDB_KEYBOARD=y ++CONFIG_CRYPTO_USER=m ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_CTS=m ++CONFIG_CRYPTO_XTS=m ++CONFIG_CRYPTO_XCBC=m ++CONFIG_CRYPTO_TGR192=m ++CONFIG_CRYPTO_WP512=m ++CONFIG_CRYPTO_CAST5=m ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_USER_API_SKCIPHER=m ++# CONFIG_CRYPTO_HW is not set ++CONFIG_ARM_CRYPTO=y ++CONFIG_CRYPTO_SHA1_ARM_NEON=m ++CONFIG_CRYPTO_AES_ARM_BS=m ++CONFIG_CRC_ITU_T=y ++CONFIG_LIBCRC32C=y +--- /dev/null ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -0,0 +1,1308 @@ ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y ++CONFIG_NMI_LOG_BUF_SHIFT=12 ++CONFIG_MEMCG=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CPUSETS=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_NAMESPACES=y ++CONFIG_USER_NS=y ++CONFIG_SCHED_AUTOGROUP=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_EMBEDDED=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_PROFILING=y ++CONFIG_OPROFILE=m ++CONFIG_KPROBES=y ++CONFIG_JUMP_LABEL=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_BLK_DEV_THROTTLING=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_MAC_PARTITION=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++CONFIG_ARCH_MULTI_V6=y ++# CONFIG_ARCH_MULTI_V7 is not set ++CONFIG_ARCH_BCM=y ++CONFIG_ARCH_BCM2835=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_PREEMPT_VOLUNTARY=y ++CONFIG_AEABI=y ++# CONFIG_CPU_SW_DOMAIN_PAN is not set ++CONFIG_CLEANCACHE=y ++CONFIG_FRONTSWAP=y ++CONFIG_CMA=y ++CONFIG_ZSMALLOC=m ++CONFIG_PGTABLE_MAPPING=y ++CONFIG_UACCESS_WITH_MEMCPY=y ++CONFIG_SECCOMP=y ++# CONFIG_ATAGS is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_VFP=y ++CONFIG_BINFMT_MISC=m ++# CONFIG_SUSPEND is not set ++CONFIG_PM=y ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM_USER=y ++CONFIG_NET_KEY=m ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NET_IPGRE=m ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m ++CONFIG_INET_IPCOMP=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_DIAG=m ++CONFIG_IPV6=m ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_SUBTREES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y ++CONFIG_NETFILTER=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_ZONES=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++CONFIG_NF_CT_PROTO_DCCP=m ++CONFIG_NF_CT_PROTO_UDPLITE=m ++CONFIG_NF_CONNTRACK_AMANDA=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_CONNTRACK_H323=m ++CONFIG_NF_CONNTRACK_IRC=m ++CONFIG_NF_CONNTRACK_NETBIOS_NS=m ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++CONFIG_NF_CONNTRACK_SANE=m ++CONFIG_NF_CONNTRACK_SIP=m ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_NETFILTER_XT_SET=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HMARK=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_LED=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TPROXY=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_NETFILTER_XT_MATCH_BPF=m ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_NFACCT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SOCKET=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++CONFIG_IP_SET=m ++CONFIG_IP_SET_BITMAP_IP=m ++CONFIG_IP_SET_BITMAP_IPMAC=m ++CONFIG_IP_SET_BITMAP_PORT=m ++CONFIG_IP_SET_HASH_IP=m ++CONFIG_IP_SET_HASH_IPPORT=m ++CONFIG_IP_SET_HASH_IPPORTIP=m ++CONFIG_IP_SET_HASH_IPPORTNET=m ++CONFIG_IP_SET_HASH_NET=m ++CONFIG_IP_SET_HASH_NETPORT=m ++CONFIG_IP_SET_HASH_NETIFACE=m ++CONFIG_IP_SET_LIST_SET=m ++CONFIG_IP_VS=m ++CONFIG_IP_VS_PROTO_TCP=y ++CONFIG_IP_VS_PROTO_UDP=y ++CONFIG_IP_VS_PROTO_ESP=y ++CONFIG_IP_VS_PROTO_AH=y ++CONFIG_IP_VS_PROTO_SCTP=y ++CONFIG_IP_VS_RR=m ++CONFIG_IP_VS_WRR=m ++CONFIG_IP_VS_LC=m ++CONFIG_IP_VS_WLC=m ++CONFIG_IP_VS_LBLC=m ++CONFIG_IP_VS_LBLCR=m ++CONFIG_IP_VS_DH=m ++CONFIG_IP_VS_SH=m ++CONFIG_IP_VS_SED=m ++CONFIG_IP_VS_NQ=m ++CONFIG_IP_VS_FTP=m ++CONFIG_IP_VS_PE_SIP=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_RPFILTER=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_CLUSTERIP=m ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=m ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RPFILTER=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP6_NF_RAW=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_NPT=m ++CONFIG_BRIDGE_NF_EBTABLES=m ++CONFIG_BRIDGE_EBT_BROUTE=m ++CONFIG_BRIDGE_EBT_T_FILTER=m ++CONFIG_BRIDGE_EBT_T_NAT=m ++CONFIG_BRIDGE_EBT_802_3=m ++CONFIG_BRIDGE_EBT_AMONG=m ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++CONFIG_BRIDGE_EBT_LIMIT=m ++CONFIG_BRIDGE_EBT_MARK=m ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++CONFIG_BRIDGE_EBT_STP=m ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=m ++CONFIG_BRIDGE_EBT_MARK_T=m ++CONFIG_BRIDGE_EBT_REDIRECT=m ++CONFIG_BRIDGE_EBT_SNAT=m ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_NFLOG=m ++CONFIG_SCTP_COOKIE_HMAC_SHA1=y ++CONFIG_ATM=m ++CONFIG_L2TP=m ++CONFIG_L2TP_V3=y ++CONFIG_L2TP_IP=m ++CONFIG_L2TP_ETH=m ++CONFIG_BRIDGE=m ++CONFIG_VLAN_8021Q=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_ATALK=m ++CONFIG_6LOWPAN=m ++CONFIG_IEEE802154=m ++CONFIG_IEEE802154_6LOWPAN=m ++CONFIG_MAC802154=m ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_MULTIQ=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFB=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_SCH_DRR=m ++CONFIG_NET_SCH_MQPRIO=m ++CONFIG_NET_SCH_CHOKE=m ++CONFIG_NET_SCH_QFQ=m ++CONFIG_NET_SCH_CODEL=m ++CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_INGRESS=m ++CONFIG_NET_SCH_PLUG=m ++CONFIG_NET_CLS_BASIC=m ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_CLS_U32_MARK=y ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_FLOW=m ++CONFIG_NET_CLS_CGROUP=m ++CONFIG_NET_EMATCH=y ++CONFIG_NET_EMATCH_CMP=m ++CONFIG_NET_EMATCH_NBYTE=m ++CONFIG_NET_EMATCH_U32=m ++CONFIG_NET_EMATCH_META=m ++CONFIG_NET_EMATCH_TEXT=m ++CONFIG_NET_EMATCH_IPSET=m ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_GACT_PROB=y ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m ++CONFIG_BATMAN_ADV=m ++CONFIG_OPENVSWITCH=m ++CONFIG_NET_PKTGEN=m ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++CONFIG_MKISS=m ++CONFIG_6PACK=m ++CONFIG_BPQETHER=m ++CONFIG_BAYCOM_SER_FDX=m ++CONFIG_BAYCOM_SER_HDX=m ++CONFIG_YAM=m ++CONFIG_CAN=m ++CONFIG_CAN_VCAN=m ++CONFIG_CAN_MCP251X=m ++CONFIG_IRDA=m ++CONFIG_IRLAN=m ++CONFIG_IRNET=m ++CONFIG_IRCOMM=m ++CONFIG_IRDA_ULTRA=y ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++CONFIG_IRTTY_SIR=m ++CONFIG_KINGSUN_DONGLE=m ++CONFIG_KSDAZZLE_DONGLE=m ++CONFIG_KS959_DONGLE=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_MCS_FIR=m ++CONFIG_BT=m ++CONFIG_BT_RFCOMM=m ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_BNEP=m ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HIDP=m ++CONFIG_BT_6LOWPAN=m ++CONFIG_BT_HCIBTUSB=m ++CONFIG_BT_HCIUART=m ++CONFIG_BT_HCIUART_3WIRE=y ++CONFIG_BT_HCIUART_BCM=y ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++CONFIG_BT_MRVL=m ++CONFIG_BT_MRVL_SDIO=m ++CONFIG_BT_ATH3K=m ++CONFIG_BT_WILINK=m ++CONFIG_CFG80211=m ++CONFIG_MAC80211=m ++CONFIG_MAC80211_MESH=y ++CONFIG_WIMAX=m ++CONFIG_RFKILL=m ++CONFIG_RFKILL_INPUT=y ++CONFIG_NET_9P=m ++CONFIG_NFC=m ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_MTD=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_NAND=m ++CONFIG_MTD_UBI=m ++CONFIG_OF_CONFIGFS=y ++CONFIG_ZRAM=m ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_CRYPTOLOOP=m ++CONFIG_BLK_DEV_DRBD=m ++CONFIG_BLK_DEV_NBD=m ++CONFIG_BLK_DEV_RAM=y ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_ATA_OVER_ETH=m ++CONFIG_EEPROM_AT24=m ++CONFIG_TI_ST=m ++CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=m ++CONFIG_CHR_DEV_OSST=m ++CONFIG_BLK_DEV_SR=m ++CONFIG_CHR_DEV_SG=m ++CONFIG_SCSI_ISCSI_ATTRS=y ++CONFIG_ISCSI_TCP=m ++CONFIG_ISCSI_BOOT_SYSFS=m ++CONFIG_MD=y ++CONFIG_MD_LINEAR=m ++CONFIG_MD_RAID0=m ++CONFIG_BLK_DEV_DM=m ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++CONFIG_DM_THIN_PROVISIONING=m ++CONFIG_DM_MIRROR=m ++CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_RAID=m ++CONFIG_DM_ZERO=m ++CONFIG_DM_DELAY=m ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=m ++CONFIG_DUMMY=m ++CONFIG_IFB=m ++CONFIG_MACVLAN=m ++CONFIG_VXLAN=m ++CONFIG_NETCONSOLE=m ++CONFIG_TUN=m ++CONFIG_VETH=m ++CONFIG_ENC28J60=m ++CONFIG_QCA7000=m ++CONFIG_MDIO_BITBANG=m ++CONFIG_PPP=m ++CONFIG_PPP_BSDCOMP=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MPPE=m ++CONFIG_PPP_MULTILINK=y ++CONFIG_PPPOATM=m ++CONFIG_PPPOE=m ++CONFIG_PPPOL2TP=m ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_SLIP=m ++CONFIG_SLIP_COMPRESSED=y ++CONFIG_SLIP_SMART=y ++CONFIG_USB_CATC=m ++CONFIG_USB_KAWETH=m ++CONFIG_USB_PEGASUS=m ++CONFIG_USB_RTL8150=m ++CONFIG_USB_RTL8152=m ++CONFIG_USB_USBNET=y ++CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_AX88179_178A=m ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_CDC_NCM=m ++CONFIG_USB_NET_HUAWEI_CDC_NCM=m ++CONFIG_USB_NET_CDC_MBIM=m ++CONFIG_USB_NET_DM9601=m ++CONFIG_USB_NET_SR9700=m ++CONFIG_USB_NET_SR9800=m ++CONFIG_USB_NET_SMSC75XX=m ++CONFIG_USB_NET_SMSC95XX=y ++CONFIG_USB_NET_GL620A=m ++CONFIG_USB_NET_NET1080=m ++CONFIG_USB_NET_PLUSB=m ++CONFIG_USB_NET_MCS7830=m ++CONFIG_USB_NET_CDC_SUBSET=m ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_EPSON2888=y ++CONFIG_USB_KC2190=y ++CONFIG_USB_NET_ZAURUS=m ++CONFIG_USB_NET_CX82310_ETH=m ++CONFIG_USB_NET_KALMIA=m ++CONFIG_USB_NET_QMI_WWAN=m ++CONFIG_USB_HSO=m ++CONFIG_USB_NET_INT51X1=m ++CONFIG_USB_IPHETH=m ++CONFIG_USB_SIERRA_NET=m ++CONFIG_USB_VL600=m ++CONFIG_ATH9K=m ++CONFIG_ATH9K_HTC=m ++CONFIG_CARL9170=m ++CONFIG_ATH6KL=m ++CONFIG_ATH6KL_USB=m ++CONFIG_AR5523=m ++CONFIG_AT76C50X_USB=m ++CONFIG_B43=m ++# CONFIG_B43_PHY_N is not set ++CONFIG_B43LEGACY=m ++CONFIG_BRCMFMAC=m ++CONFIG_BRCMFMAC_USB=y ++CONFIG_HOSTAP=m ++CONFIG_P54_COMMON=m ++CONFIG_P54_USB=m ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++CONFIG_LIBERTAS_SDIO=m ++CONFIG_LIBERTAS_THINFIRM=m ++CONFIG_LIBERTAS_THINFIRM_USB=m ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++CONFIG_MT7601U=m ++CONFIG_RT2X00=m ++CONFIG_RT2500USB=m ++CONFIG_RT73USB=m ++CONFIG_RT2800USB=m ++CONFIG_RT2800USB_RT3573=y ++CONFIG_RT2800USB_RT53XX=y ++CONFIG_RT2800USB_RT55XX=y ++CONFIG_RT2800USB_UNKNOWN=y ++CONFIG_RTL8187=m ++CONFIG_RTL8192CU=m ++CONFIG_USB_ZD1201=m ++CONFIG_ZD1211RW=m ++CONFIG_MAC80211_HWSIM=m ++CONFIG_USB_NET_RNDIS_WLAN=m ++CONFIG_WIMAX_I2400M_USB=m ++CONFIG_IEEE802154_AT86RF230=m ++CONFIG_IEEE802154_MRF24J40=m ++CONFIG_IEEE802154_CC2520=m ++CONFIG_INPUT_POLLDEV=m ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_JOYDEV=m ++CONFIG_INPUT_EVDEV=m ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_INPUT_JOYSTICK=y ++CONFIG_JOYSTICK_IFORCE=m ++CONFIG_JOYSTICK_IFORCE_USB=y ++CONFIG_JOYSTICK_XPAD=m ++CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y ++CONFIG_JOYSTICK_RPISENSE=m ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ADS7846=m ++CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_RPI_FT5406=m ++CONFIG_TOUCHSCREEN_USB_COMPOSITE=m ++CONFIG_TOUCHSCREEN_STMPE=m ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_AD714X=m ++CONFIG_INPUT_ATI_REMOTE2=m ++CONFIG_INPUT_KEYSPAN_REMOTE=m ++CONFIG_INPUT_POWERMATE=m ++CONFIG_INPUT_YEALINK=m ++CONFIG_INPUT_CM109=m ++CONFIG_INPUT_UINPUT=m ++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m ++CONFIG_INPUT_ADXL34X=m ++CONFIG_INPUT_CMA3000=m ++CONFIG_SERIO=m ++CONFIG_SERIO_RAW=m ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++CONFIG_BRCM_CHAR_DRIVERS=y ++CONFIG_BCM_VC_CMA=y ++CONFIG_BCM_VCIO=y ++CONFIG_BCM_VC_SM=y ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_DMA is not set ++CONFIG_SERIAL_8250_NR_UARTS=1 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=0 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_BCM2835AUX=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_SERIAL_SC16IS7XX=m ++CONFIG_SERIAL_SC16IS7XX_SPI=y ++CONFIG_TTY_PRINTK=y ++CONFIG_HW_RANDOM=y ++CONFIG_RAW_DRIVER=y ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_MUX_PCA954x=m ++CONFIG_I2C_BCM2708=m ++CONFIG_I2C_BCM2835=m ++CONFIG_I2C_GPIO=m ++CONFIG_SPI=y ++CONFIG_SPI_BCM2835=m ++CONFIG_SPI_BCM2835AUX=m ++CONFIG_SPI_SPIDEV=y ++CONFIG_PPS=m ++CONFIG_PPS_CLIENT_LDISC=m ++CONFIG_PPS_CLIENT_GPIO=m ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_ARIZONA=m ++CONFIG_GPIO_STMPE=y ++CONFIG_GPIO_MCP23S08=m ++CONFIG_W1=m ++CONFIG_W1_MASTER_DS2490=m ++CONFIG_W1_MASTER_DS2482=m ++CONFIG_W1_MASTER_DS1WM=m ++CONFIG_W1_MASTER_GPIO=m ++CONFIG_W1_SLAVE_THERM=m ++CONFIG_W1_SLAVE_SMEM=m ++CONFIG_W1_SLAVE_DS2408=m ++CONFIG_W1_SLAVE_DS2413=m ++CONFIG_W1_SLAVE_DS2406=m ++CONFIG_W1_SLAVE_DS2423=m ++CONFIG_W1_SLAVE_DS2431=m ++CONFIG_W1_SLAVE_DS2433=m ++CONFIG_W1_SLAVE_DS2760=m ++CONFIG_W1_SLAVE_DS2780=m ++CONFIG_W1_SLAVE_DS2781=m ++CONFIG_W1_SLAVE_DS28E04=m ++CONFIG_W1_SLAVE_BQ27000=m ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO=y ++CONFIG_BATTERY_DS2760=m ++CONFIG_HWMON=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_SHT21=m ++CONFIG_SENSORS_SHTC1=m ++CONFIG_SENSORS_INA2XX=m ++CONFIG_THERMAL=y ++CONFIG_THERMAL_BCM2835=y ++CONFIG_WATCHDOG=y ++CONFIG_BCM2835_WDT=y ++CONFIG_UCB1400_CORE=m ++CONFIG_MFD_STMPE=y ++CONFIG_STMPE_SPI=y ++CONFIG_MFD_ARIZONA_I2C=m ++CONFIG_MFD_ARIZONA_SPI=m ++CONFIG_MFD_WM5102=y ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y ++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y ++CONFIG_MEDIA_RADIO_SUPPORT=y ++CONFIG_MEDIA_RC_SUPPORT=y ++CONFIG_MEDIA_CONTROLLER=y ++CONFIG_LIRC=m ++CONFIG_RC_DEVICES=y ++CONFIG_RC_ATI_REMOTE=m ++CONFIG_IR_IMON=m ++CONFIG_IR_MCEUSB=m ++CONFIG_IR_REDRAT3=m ++CONFIG_IR_STREAMZAP=m ++CONFIG_IR_IGUANA=m ++CONFIG_IR_TTUSBIR=m ++CONFIG_RC_LOOPBACK=m ++CONFIG_IR_GPIO_CIR=m ++CONFIG_MEDIA_USB_SUPPORT=y ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_USB_M5602=m ++CONFIG_USB_STV06XX=m ++CONFIG_USB_GL860=m ++CONFIG_USB_GSPCA_BENQ=m ++CONFIG_USB_GSPCA_CONEX=m ++CONFIG_USB_GSPCA_CPIA1=m ++CONFIG_USB_GSPCA_DTCS033=m ++CONFIG_USB_GSPCA_ETOMS=m ++CONFIG_USB_GSPCA_FINEPIX=m ++CONFIG_USB_GSPCA_JEILINJ=m ++CONFIG_USB_GSPCA_JL2005BCD=m ++CONFIG_USB_GSPCA_KINECT=m ++CONFIG_USB_GSPCA_KONICA=m ++CONFIG_USB_GSPCA_MARS=m ++CONFIG_USB_GSPCA_MR97310A=m ++CONFIG_USB_GSPCA_NW80X=m ++CONFIG_USB_GSPCA_OV519=m ++CONFIG_USB_GSPCA_OV534=m ++CONFIG_USB_GSPCA_OV534_9=m ++CONFIG_USB_GSPCA_PAC207=m ++CONFIG_USB_GSPCA_PAC7302=m ++CONFIG_USB_GSPCA_PAC7311=m ++CONFIG_USB_GSPCA_SE401=m ++CONFIG_USB_GSPCA_SN9C2028=m ++CONFIG_USB_GSPCA_SN9C20X=m ++CONFIG_USB_GSPCA_SONIXB=m ++CONFIG_USB_GSPCA_SONIXJ=m ++CONFIG_USB_GSPCA_SPCA500=m ++CONFIG_USB_GSPCA_SPCA501=m ++CONFIG_USB_GSPCA_SPCA505=m ++CONFIG_USB_GSPCA_SPCA506=m ++CONFIG_USB_GSPCA_SPCA508=m ++CONFIG_USB_GSPCA_SPCA561=m ++CONFIG_USB_GSPCA_SPCA1528=m ++CONFIG_USB_GSPCA_SQ905=m ++CONFIG_USB_GSPCA_SQ905C=m ++CONFIG_USB_GSPCA_SQ930X=m ++CONFIG_USB_GSPCA_STK014=m ++CONFIG_USB_GSPCA_STK1135=m ++CONFIG_USB_GSPCA_STV0680=m ++CONFIG_USB_GSPCA_SUNPLUS=m ++CONFIG_USB_GSPCA_T613=m ++CONFIG_USB_GSPCA_TOPRO=m ++CONFIG_USB_GSPCA_TV8532=m ++CONFIG_USB_GSPCA_VC032X=m ++CONFIG_USB_GSPCA_VICAM=m ++CONFIG_USB_GSPCA_XIRLINK_CIT=m ++CONFIG_USB_GSPCA_ZC3XX=m ++CONFIG_USB_PWC=m ++CONFIG_VIDEO_CPIA2=m ++CONFIG_USB_ZR364XX=m ++CONFIG_USB_STKWEBCAM=m ++CONFIG_USB_S2255=m ++CONFIG_VIDEO_USBTV=m ++CONFIG_VIDEO_PVRUSB2=m ++CONFIG_VIDEO_HDPVR=m ++CONFIG_VIDEO_USBVISION=m ++CONFIG_VIDEO_STK1160_COMMON=m ++CONFIG_VIDEO_STK1160_AC97=y ++CONFIG_VIDEO_GO7007=m ++CONFIG_VIDEO_GO7007_USB=m ++CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m ++CONFIG_VIDEO_AU0828=m ++CONFIG_VIDEO_AU0828_RC=y ++CONFIG_VIDEO_CX231XX=m ++CONFIG_VIDEO_CX231XX_ALSA=m ++CONFIG_VIDEO_CX231XX_DVB=m ++CONFIG_VIDEO_TM6000=m ++CONFIG_VIDEO_TM6000_ALSA=m ++CONFIG_VIDEO_TM6000_DVB=m ++CONFIG_DVB_USB=m ++CONFIG_DVB_USB_A800=m ++CONFIG_DVB_USB_DIBUSB_MB=m ++CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y ++CONFIG_DVB_USB_DIBUSB_MC=m ++CONFIG_DVB_USB_DIB0700=m ++CONFIG_DVB_USB_UMT_010=m ++CONFIG_DVB_USB_CXUSB=m ++CONFIG_DVB_USB_M920X=m ++CONFIG_DVB_USB_DIGITV=m ++CONFIG_DVB_USB_VP7045=m ++CONFIG_DVB_USB_VP702X=m ++CONFIG_DVB_USB_GP8PSK=m ++CONFIG_DVB_USB_NOVA_T_USB2=m ++CONFIG_DVB_USB_TTUSB2=m ++CONFIG_DVB_USB_DTT200U=m ++CONFIG_DVB_USB_OPERA1=m ++CONFIG_DVB_USB_AF9005=m ++CONFIG_DVB_USB_AF9005_REMOTE=m ++CONFIG_DVB_USB_PCTV452E=m ++CONFIG_DVB_USB_DW2102=m ++CONFIG_DVB_USB_CINERGY_T2=m ++CONFIG_DVB_USB_DTV5100=m ++CONFIG_DVB_USB_FRIIO=m ++CONFIG_DVB_USB_AZ6027=m ++CONFIG_DVB_USB_TECHNISAT_USB2=m ++CONFIG_DVB_USB_V2=m ++CONFIG_DVB_USB_AF9015=m ++CONFIG_DVB_USB_AF9035=m ++CONFIG_DVB_USB_ANYSEE=m ++CONFIG_DVB_USB_AU6610=m ++CONFIG_DVB_USB_AZ6007=m ++CONFIG_DVB_USB_CE6230=m ++CONFIG_DVB_USB_EC168=m ++CONFIG_DVB_USB_GL861=m ++CONFIG_DVB_USB_LME2510=m ++CONFIG_DVB_USB_MXL111SF=m ++CONFIG_DVB_USB_RTL28XXU=m ++CONFIG_DVB_USB_DVBSKY=m ++CONFIG_SMS_USB_DRV=m ++CONFIG_DVB_B2C2_FLEXCOP_USB=m ++CONFIG_DVB_AS102=m ++CONFIG_VIDEO_EM28XX=m ++CONFIG_VIDEO_EM28XX_V4L2=m ++CONFIG_VIDEO_EM28XX_ALSA=m ++CONFIG_VIDEO_EM28XX_DVB=m ++CONFIG_V4L_PLATFORM_DRIVERS=y ++CONFIG_VIDEO_BCM2835=y ++CONFIG_VIDEO_BCM2835_MMAL=m ++CONFIG_RADIO_SI470X=y ++CONFIG_USB_SI470X=m ++CONFIG_I2C_SI470X=m ++CONFIG_RADIO_SI4713=m ++CONFIG_I2C_SI4713=m ++CONFIG_USB_MR800=m ++CONFIG_USB_DSBR=m ++CONFIG_RADIO_SHARK=m ++CONFIG_RADIO_SHARK2=m ++CONFIG_USB_KEENE=m ++CONFIG_USB_MA901=m ++CONFIG_RADIO_TEA5764=m ++CONFIG_RADIO_SAA7706H=m ++CONFIG_RADIO_TEF6862=m ++CONFIG_RADIO_WL1273=m ++CONFIG_RADIO_WL128X=m ++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set ++CONFIG_VIDEO_UDA1342=m ++CONFIG_VIDEO_SONY_BTF_MPX=m ++CONFIG_VIDEO_TVP5150=m ++CONFIG_VIDEO_TW2804=m ++CONFIG_VIDEO_TW9903=m ++CONFIG_VIDEO_TW9906=m ++CONFIG_VIDEO_OV7640=m ++CONFIG_VIDEO_MT9V011=m ++CONFIG_DRM=m ++CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_UDL=m ++CONFIG_DRM_VC4=m ++CONFIG_FB=y ++CONFIG_FB_BCM2708=y ++CONFIG_FB_UDL=m ++CONFIG_FB_SSD1307=m ++CONFIG_FB_RPISENSE=m ++# CONFIG_BACKLIGHT_GENERIC is not set ++CONFIG_BACKLIGHT_RPI=m ++CONFIG_BACKLIGHT_GPIO=m ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_SOUND=y ++CONFIG_SND=m ++CONFIG_SND_SEQUENCER=m ++CONFIG_SND_SEQ_DUMMY=m ++CONFIG_SND_MIXER_OSS=m ++CONFIG_SND_PCM_OSS=m ++CONFIG_SND_SEQUENCER_OSS=y ++CONFIG_SND_HRTIMER=m ++CONFIG_SND_DUMMY=m ++CONFIG_SND_ALOOP=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++CONFIG_SND_BCM2835=m ++CONFIG_SND_USB_AUDIO=m ++CONFIG_SND_USB_UA101=m ++CONFIG_SND_USB_CAIAQ=m ++CONFIG_SND_USB_CAIAQ_INPUT=y ++CONFIG_SND_USB_6FIRE=m ++CONFIG_SND_SOC=m ++CONFIG_SND_BCM2835_SOC_I2S=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_DAC=m ++CONFIG_SND_BCM2708_SOC_RPI_PROTO=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m ++CONFIG_SND_BCM2708_SOC_RASPIDAC3=m ++CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m ++CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_DIGIDAC1_SOUNDCARD=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m ++CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m ++CONFIG_SND_PISOUND=m ++CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_AK4554=m ++CONFIG_SND_SOC_WM8804_I2C=m ++CONFIG_SND_SIMPLE_CARD=m ++CONFIG_SOUND_PRIME=m ++CONFIG_HIDRAW=y ++CONFIG_UHID=m ++CONFIG_HID_A4TECH=m ++CONFIG_HID_ACRUX=m ++CONFIG_HID_APPLE=m ++CONFIG_HID_BELKIN=m ++CONFIG_HID_BETOP_FF=m ++CONFIG_HID_CHERRY=m ++CONFIG_HID_CHICONY=m ++CONFIG_HID_CYPRESS=m ++CONFIG_HID_DRAGONRISE=m ++CONFIG_HID_EMS_FF=m ++CONFIG_HID_ELECOM=m ++CONFIG_HID_ELO=m ++CONFIG_HID_EZKEY=m ++CONFIG_HID_GEMBIRD=m ++CONFIG_HID_HOLTEK=m ++CONFIG_HID_KEYTOUCH=m ++CONFIG_HID_KYE=m ++CONFIG_HID_UCLOGIC=m ++CONFIG_HID_WALTOP=m ++CONFIG_HID_GYRATION=m ++CONFIG_HID_TWINHAN=m ++CONFIG_HID_KENSINGTON=m ++CONFIG_HID_LCPOWER=m ++CONFIG_HID_LOGITECH=m ++CONFIG_HID_LOGITECH_DJ=m ++CONFIG_LOGITECH_FF=y ++CONFIG_LOGIRUMBLEPAD2_FF=y ++CONFIG_LOGIG940_FF=y ++CONFIG_HID_MAGICMOUSE=m ++CONFIG_HID_MICROSOFT=m ++CONFIG_HID_MONTEREY=m ++CONFIG_HID_MULTITOUCH=m ++CONFIG_HID_NTRIG=m ++CONFIG_HID_ORTEK=m ++CONFIG_HID_PANTHERLORD=m ++CONFIG_HID_PETALYNX=m ++CONFIG_HID_PICOLCD=m ++CONFIG_HID_ROCCAT=m ++CONFIG_HID_SAMSUNG=m ++CONFIG_HID_SONY=m ++CONFIG_HID_SPEEDLINK=m ++CONFIG_HID_SUNPLUS=m ++CONFIG_HID_GREENASIA=m ++CONFIG_HID_SMARTJOYPLUS=m ++CONFIG_HID_TOPSEED=m ++CONFIG_HID_THINGM=m ++CONFIG_HID_THRUSTMASTER=m ++CONFIG_HID_WACOM=m ++CONFIG_HID_WIIMOTE=m ++CONFIG_HID_XINMO=m ++CONFIG_HID_ZEROPLUS=m ++CONFIG_HID_ZYDACRON=m ++CONFIG_HID_PID=y ++CONFIG_USB_HIDDEV=y ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_MON=m ++CONFIG_USB_DWCOTG=y ++CONFIG_USB_PRINTER=m ++CONFIG_USB_STORAGE=y ++CONFIG_USB_STORAGE_REALTEK=m ++CONFIG_USB_STORAGE_DATAFAB=m ++CONFIG_USB_STORAGE_FREECOM=m ++CONFIG_USB_STORAGE_ISD200=m ++CONFIG_USB_STORAGE_USBAT=m ++CONFIG_USB_STORAGE_SDDR09=m ++CONFIG_USB_STORAGE_SDDR55=m ++CONFIG_USB_STORAGE_JUMPSHOT=m ++CONFIG_USB_STORAGE_ALAUDA=m ++CONFIG_USB_STORAGE_ONETOUCH=m ++CONFIG_USB_STORAGE_KARMA=m ++CONFIG_USB_STORAGE_CYPRESS_ATACB=m ++CONFIG_USB_STORAGE_ENE_UB6250=m ++CONFIG_USB_MDC800=m ++CONFIG_USB_MICROTEK=m ++CONFIG_USBIP_CORE=m ++CONFIG_USBIP_VHCI_HCD=m ++CONFIG_USBIP_HOST=m ++CONFIG_USB_DWC2=m ++CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_GENERIC=y ++CONFIG_USB_SERIAL_AIRCABLE=m ++CONFIG_USB_SERIAL_ARK3116=m ++CONFIG_USB_SERIAL_BELKIN=m ++CONFIG_USB_SERIAL_CH341=m ++CONFIG_USB_SERIAL_WHITEHEAT=m ++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m ++CONFIG_USB_SERIAL_CP210X=m ++CONFIG_USB_SERIAL_CYPRESS_M8=m ++CONFIG_USB_SERIAL_EMPEG=m ++CONFIG_USB_SERIAL_FTDI_SIO=m ++CONFIG_USB_SERIAL_VISOR=m ++CONFIG_USB_SERIAL_IPAQ=m ++CONFIG_USB_SERIAL_IR=m ++CONFIG_USB_SERIAL_EDGEPORT=m ++CONFIG_USB_SERIAL_EDGEPORT_TI=m ++CONFIG_USB_SERIAL_F81232=m ++CONFIG_USB_SERIAL_GARMIN=m ++CONFIG_USB_SERIAL_IPW=m ++CONFIG_USB_SERIAL_IUU=m ++CONFIG_USB_SERIAL_KEYSPAN_PDA=m ++CONFIG_USB_SERIAL_KEYSPAN=m ++CONFIG_USB_SERIAL_KLSI=m ++CONFIG_USB_SERIAL_KOBIL_SCT=m ++CONFIG_USB_SERIAL_MCT_U232=m ++CONFIG_USB_SERIAL_METRO=m ++CONFIG_USB_SERIAL_MOS7720=m ++CONFIG_USB_SERIAL_MOS7840=m ++CONFIG_USB_SERIAL_NAVMAN=m ++CONFIG_USB_SERIAL_PL2303=m ++CONFIG_USB_SERIAL_OTI6858=m ++CONFIG_USB_SERIAL_QCAUX=m ++CONFIG_USB_SERIAL_QUALCOMM=m ++CONFIG_USB_SERIAL_SPCP8X5=m ++CONFIG_USB_SERIAL_SAFE=m ++CONFIG_USB_SERIAL_SIERRAWIRELESS=m ++CONFIG_USB_SERIAL_SYMBOL=m ++CONFIG_USB_SERIAL_TI=m ++CONFIG_USB_SERIAL_CYBERJACK=m ++CONFIG_USB_SERIAL_XIRCOM=m ++CONFIG_USB_SERIAL_OPTION=m ++CONFIG_USB_SERIAL_OMNINET=m ++CONFIG_USB_SERIAL_OPTICON=m ++CONFIG_USB_SERIAL_XSENS_MT=m ++CONFIG_USB_SERIAL_WISHBONE=m ++CONFIG_USB_SERIAL_SSU100=m ++CONFIG_USB_SERIAL_QT2=m ++CONFIG_USB_SERIAL_DEBUG=m ++CONFIG_USB_EMI62=m ++CONFIG_USB_EMI26=m ++CONFIG_USB_ADUTUX=m ++CONFIG_USB_SEVSEG=m ++CONFIG_USB_RIO500=m ++CONFIG_USB_LEGOTOWER=m ++CONFIG_USB_LCD=m ++CONFIG_USB_CYPRESS_CY7C63=m ++CONFIG_USB_CYTHERM=m ++CONFIG_USB_IDMOUSE=m ++CONFIG_USB_FTDI_ELAN=m ++CONFIG_USB_APPLEDISPLAY=m ++CONFIG_USB_LD=m ++CONFIG_USB_TRANCEVIBRATOR=m ++CONFIG_USB_IOWARRIOR=m ++CONFIG_USB_TEST=m ++CONFIG_USB_ISIGHTFW=m ++CONFIG_USB_YUREX=m ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++CONFIG_USB_CXACRU=m ++CONFIG_USB_UEAGLEATM=m ++CONFIG_USB_XUSBATM=m ++CONFIG_USB_GADGET=m ++CONFIG_USB_ZERO=m ++CONFIG_USB_AUDIO=m ++CONFIG_USB_ETH=m ++CONFIG_USB_GADGETFS=m ++CONFIG_USB_MASS_STORAGE=m ++CONFIG_USB_G_SERIAL=m ++CONFIG_USB_MIDI_GADGET=m ++CONFIG_USB_G_PRINTER=m ++CONFIG_USB_CDC_COMPOSITE=m ++CONFIG_USB_G_ACM_MS=m ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_HID=m ++CONFIG_USB_G_WEBCAM=m ++CONFIG_MMC=y ++CONFIG_MMC_BLOCK_MINORS=32 ++CONFIG_MMC_BCM2835=y ++CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_PLTFM=y ++CONFIG_MMC_SPI=m ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_ONESHOT=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_BACKLIGHT=y ++CONFIG_LEDS_TRIGGER_CPU=y ++CONFIG_LEDS_TRIGGER_GPIO=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_LEDS_TRIGGER_TRANSIENT=m ++CONFIG_LEDS_TRIGGER_CAMERA=m ++CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_LEDS_TRIGGER_PANIC=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++CONFIG_RTC_DRV_ABX80X=m ++CONFIG_RTC_DRV_DS1307=m ++CONFIG_RTC_DRV_DS1374=m ++CONFIG_RTC_DRV_DS1672=m ++CONFIG_RTC_DRV_MAX6900=m ++CONFIG_RTC_DRV_RS5C372=m ++CONFIG_RTC_DRV_ISL1208=m ++CONFIG_RTC_DRV_ISL12022=m ++CONFIG_RTC_DRV_X1205=m ++CONFIG_RTC_DRV_PCF8523=m ++CONFIG_RTC_DRV_PCF8563=m ++CONFIG_RTC_DRV_PCF8583=m ++CONFIG_RTC_DRV_M41T80=m ++CONFIG_RTC_DRV_BQ32K=m ++CONFIG_RTC_DRV_S35390A=m ++CONFIG_RTC_DRV_FM3130=m ++CONFIG_RTC_DRV_RX8581=m ++CONFIG_RTC_DRV_RX8025=m ++CONFIG_RTC_DRV_EM3027=m ++CONFIG_RTC_DRV_M41T93=m ++CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1302=m ++CONFIG_RTC_DRV_DS1305=m ++CONFIG_RTC_DRV_DS1390=m ++CONFIG_RTC_DRV_R9701=m ++CONFIG_RTC_DRV_RX4581=m ++CONFIG_RTC_DRV_RS5C348=m ++CONFIG_RTC_DRV_MAX6902=m ++CONFIG_RTC_DRV_PCF2123=m ++CONFIG_RTC_DRV_DS3232=m ++CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_RV3029C2=m ++CONFIG_DMADEVICES=y ++CONFIG_DMA_BCM2835=y ++CONFIG_DMA_BCM2708=y ++CONFIG_UIO=m ++CONFIG_UIO_PDRV_GENIRQ=m ++CONFIG_STAGING=y ++CONFIG_PRISM2_USB=m ++CONFIG_R8712U=m ++CONFIG_R8188EU=m ++CONFIG_VT6656=m ++CONFIG_SPEAKUP=m ++CONFIG_SPEAKUP_SYNTH_SOFT=m ++CONFIG_STAGING_MEDIA=y ++CONFIG_LIRC_STAGING=y ++CONFIG_LIRC_IMON=m ++CONFIG_LIRC_RPI=m ++CONFIG_LIRC_SASEM=m ++CONFIG_LIRC_SERIAL=m ++CONFIG_FB_TFT=m ++CONFIG_FB_TFT_AGM1264K_FL=m ++CONFIG_FB_TFT_BD663474=m ++CONFIG_FB_TFT_HX8340BN=m ++CONFIG_FB_TFT_HX8347D=m ++CONFIG_FB_TFT_HX8353D=m ++CONFIG_FB_TFT_HX8357D=m ++CONFIG_FB_TFT_ILI9163=m ++CONFIG_FB_TFT_ILI9320=m ++CONFIG_FB_TFT_ILI9325=m ++CONFIG_FB_TFT_ILI9340=m ++CONFIG_FB_TFT_ILI9341=m ++CONFIG_FB_TFT_ILI9481=m ++CONFIG_FB_TFT_ILI9486=m ++CONFIG_FB_TFT_PCD8544=m ++CONFIG_FB_TFT_RA8875=m ++CONFIG_FB_TFT_S6D02A1=m ++CONFIG_FB_TFT_S6D1121=m ++CONFIG_FB_TFT_SSD1289=m ++CONFIG_FB_TFT_SSD1306=m ++CONFIG_FB_TFT_SSD1331=m ++CONFIG_FB_TFT_SSD1351=m ++CONFIG_FB_TFT_ST7735R=m ++CONFIG_FB_TFT_TINYLCD=m ++CONFIG_FB_TFT_TLS8204=m ++CONFIG_FB_TFT_UC1701=m ++CONFIG_FB_TFT_UPD161704=m ++CONFIG_FB_TFT_WATTEROTT=m ++CONFIG_FB_FLEX=m ++CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2835_MBOX=y ++# CONFIG_IOMMU_SUPPORT is not set ++CONFIG_RASPBERRYPI_POWER=y ++CONFIG_EXTCON=m ++CONFIG_EXTCON_ARIZONA=m ++CONFIG_IIO=m ++CONFIG_IIO_BUFFER=y ++CONFIG_IIO_BUFFER_CB=m ++CONFIG_IIO_KFIFO_BUF=m ++CONFIG_MCP320X=m ++CONFIG_MCP3422=m ++CONFIG_DHT11=m ++CONFIG_HTU21=m ++CONFIG_PWM_BCM2835=m ++CONFIG_PWM_PCA9685=m ++CONFIG_RASPBERRYPI_FIRMWARE=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_GFS2_FS=m ++CONFIG_OCFS2_FS=m ++CONFIG_BTRFS_FS=m ++CONFIG_BTRFS_FS_POSIX_ACL=y ++CONFIG_NILFS2_FS=m ++CONFIG_F2FS_FS=y ++CONFIG_FANOTIFY=y ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_AUTOFS4_FS=y ++CONFIG_FUSE_FS=m ++CONFIG_CUSE=m ++CONFIG_OVERLAY_FS=m ++CONFIG_FSCACHE=y ++CONFIG_FSCACHE_STATS=y ++CONFIG_FSCACHE_HISTOGRAM=y ++CONFIG_CACHEFILES=y ++CONFIG_ISO9660_FS=m ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=m ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" ++CONFIG_NTFS_FS=m ++CONFIG_NTFS_RW=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_ECRYPT_FS=m ++CONFIG_HFS_FS=m ++CONFIG_HFSPLUS_FS=m ++CONFIG_JFFS2_FS=m ++CONFIG_JFFS2_SUMMARY=y ++CONFIG_UBIFS_FS=m ++CONFIG_SQUASHFS=m ++CONFIG_SQUASHFS_XATTR=y ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFS_FSCACHE=y ++CONFIG_NFSD=m ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_CIFS=m ++CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_POSIX=y ++CONFIG_CIFS_ACL=y ++CONFIG_CIFS_DFS_UPCALL=y ++CONFIG_CIFS_SMB2=y ++CONFIG_CIFS_FSCACHE=y ++CONFIG_9P_FS=m ++CONFIG_9P_FS_POSIX_ACL=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_737=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=m ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=m ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++CONFIG_DLM=m ++CONFIG_PRINTK_TIME=y ++CONFIG_BOOT_PRINTK_DELAY=y ++CONFIG_DEBUG_MEMORY_INIT=y ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_TIMER_STATS=y ++CONFIG_LATENCYTOP=y ++CONFIG_IRQSOFF_TRACER=y ++CONFIG_SCHED_TRACER=y ++CONFIG_STACK_TRACER=y ++CONFIG_BLK_DEV_IO_TRACE=y ++# CONFIG_KPROBE_EVENT is not set ++CONFIG_FUNCTION_PROFILER=y ++CONFIG_KGDB=y ++CONFIG_KGDB_KDB=y ++CONFIG_KDB_KEYBOARD=y ++CONFIG_CRYPTO_USER=m ++CONFIG_CRYPTO_CRYPTD=m ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_CTS=m ++CONFIG_CRYPTO_XTS=m ++CONFIG_CRYPTO_XCBC=m ++CONFIG_CRYPTO_SHA512=m ++CONFIG_CRYPTO_TGR192=m ++CONFIG_CRYPTO_WP512=m ++CONFIG_CRYPTO_CAST5=m ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_USER_API_SKCIPHER=m ++# CONFIG_CRYPTO_HW is not set ++CONFIG_ARM_CRYPTO=y ++CONFIG_CRYPTO_SHA1_ARM=m ++CONFIG_CRYPTO_AES_ARM=m ++CONFIG_CRC_ITU_T=y ++CONFIG_LIBCRC32C=y diff --git a/target/linux/brcm2708/patches-4.9/0093-hci_h5-Don-t-send-conf_req-when-ACTIVE.patch b/target/linux/brcm2708/patches-4.9/0093-hci_h5-Don-t-send-conf_req-when-ACTIVE.patch deleted file mode 100644 index 0ebf29c7a3..0000000000 --- a/target/linux/brcm2708/patches-4.9/0093-hci_h5-Don-t-send-conf_req-when-ACTIVE.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 63e3b21d72b4542cd0f7527bbc7dc0aef13eb16d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 17 Dec 2015 13:37:07 +0000 -Subject: [PATCH] hci_h5: Don't send conf_req when ACTIVE - -Without this patch, a modem and kernel can continuously bombard each -other with conf_req and conf_rsp messages, in a demented game of tag. ---- - drivers/bluetooth/hci_h5.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/bluetooth/hci_h5.c -+++ b/drivers/bluetooth/hci_h5.c -@@ -310,7 +310,8 @@ static void h5_handle_internal_rx(struct - h5_link_control(hu, conf_req, 3); - } else if (memcmp(data, conf_req, 2) == 0) { - h5_link_control(hu, conf_rsp, 2); -- h5_link_control(hu, conf_req, 3); -+ if (h5->state != H5_ACTIVE) -+ h5_link_control(hu, conf_req, 3); - } else if (memcmp(data, conf_rsp, 2) == 0) { - if (H5_HDR_LEN(hdr) > 2) - h5->tx_win = (data[2] & 0x07); diff --git a/target/linux/brcm2708/patches-4.9/0094-Add-arm64-configuration-and-device-tree-differences.patch b/target/linux/brcm2708/patches-4.9/0094-Add-arm64-configuration-and-device-tree-differences.patch new file mode 100644 index 0000000000..0cbb4d77f3 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0094-Add-arm64-configuration-and-device-tree-differences.patch @@ -0,0 +1,1407 @@ +From 64d1c392baa391243d0a7963379ab957d5d9b8b1 Mon Sep 17 00:00:00 2001 +From: Michael Zoran +Date: Wed, 24 Aug 2016 03:35:56 -0700 +Subject: [PATCH] Add arm64 configuration and device tree differences. Disable + MMC_BCM2835_SDHOST and MMC_BCM2835 since these drivers are crashing at the + moment. + +ARM64: Modify default config to get raspbian to boot (#1686) + +1. Enable emulation of deprecated instructions. +2. Enable ARM 8.1 and 8.2 features which are not detected at runtime. +3. Switch the default governer to powersave. +4. Include the watchdog timer driver in the kernel image rather then a module. + +Tested with raspbian-jessie 2016-09-23. +--- + arch/arm64/Kconfig.platforms | 22 + + arch/arm64/boot/dts/broadcom/Makefile | 1 + + arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts | 3 + + arch/arm64/configs/bcmrpi3_defconfig | 1334 ++++++++++++++++++++++ + 4 files changed, 1360 insertions(+) + create mode 100644 arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts + create mode 100644 arch/arm64/configs/bcmrpi3_defconfig + +--- a/arch/arm64/Kconfig.platforms ++++ b/arch/arm64/Kconfig.platforms +@@ -1,5 +1,27 @@ + menu "Platform selection" + ++config MACH_BCM2709 ++ bool ++ ++config ARCH_BCM2709 ++ bool "Broadcom BCM2709 family" ++ select MACH_BCM2709 ++ select HAVE_SMP ++ select ARM_AMBA ++ select COMMON_CLK ++ select ARCH_HAS_CPUFREQ ++ select GENERIC_CLOCKEVENTS ++ select MULTI_IRQ_HANDLER ++ select SPARSE_IRQ ++ select MFD_SYSCON ++ select VC4 ++ select USE_OF ++ select ARCH_REQUIRE_GPIOLIB ++ select PINCTRL ++ select PINCTRL_BCM2835 ++ help ++ This enables support for Broadcom BCM2709 boards. ++ + config ARCH_SUNXI + bool "Allwinner sunxi 64-bit SoC Family" + select GENERIC_IRQ_CHIP +--- a/arch/arm64/boot/dts/broadcom/Makefile ++++ b/arch/arm64/boot/dts/broadcom/Makefile +@@ -1,6 +1,7 @@ + dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb + dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb + dtb-$(CONFIG_ARCH_VULCAN) += vulcan-eval.dtb ++dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb + + always := $(dtb-y) + subdir-y := $(dts-dirs) +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts +@@ -0,0 +1,3 @@ ++#define RPI364 ++ ++#include "../../../../arm/boot/dts/bcm2710-rpi-3-b.dts" +--- /dev/null ++++ b/arch/arm64/configs/bcmrpi3_defconfig +@@ -0,0 +1,1334 @@ ++# CONFIG_ARM_PATCH_PHYS_VIRT is not set ++CONFIG_PHYS_OFFSET=0 ++CONFIG_LOCALVERSION="-v8" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_64BIT=y ++CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++ ++# ++# ARM errata workarounds via the alternatives framework ++# ++CONFIG_ARM64_ERRATUM_826319=n ++CONFIG_ARM64_ERRATUM_827319=n ++CONFIG_ARM64_ERRATUM_824069=n ++CONFIG_ARM64_ERRATUM_819472=n ++CONFIG_ARM64_ERRATUM_832075=n ++CONFIG_ARM64_ERRATUM_845719=n ++CONFIG_ARM64_ERRATUM_843419=n ++CONFIG_CAVIUM_ERRATUM_22375=n ++CONFIG_CAVIUM_ERRATUM_23154=n ++CONFIG_CAVIUM_ERRATUM_27456=n ++CONFIG_ARM64_4K_PAGES=y ++CONFIG_ARM64_VA_BITS_39=y ++CONFIG_ARM64_VA_BITS=39 ++CONFIG_SCHED_MC=y ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++CONFIG_ARMV8_DEPRECATED=y ++CONFIG_SWP_EMULATION=y ++CONFIG_CP15_BARRIER_EMULATION=y ++CONFIG_SETEND_EMULATION=y ++ ++# ++# ARMv8.1 architectural features ++# ++CONFIG_ARM64_HW_AFDBM=y ++CONFIG_ARM64_PAN=y ++CONFIG_ARM64_LSE_ATOMICS=y ++CONFIG_ARM64_VHE=y ++ ++# ++# ARMv8.2 architectural features ++# ++CONFIG_ARM64_UAO=y ++CONFIG_ARM64_MODULE_CMODEL_LARGE=n ++CONFIG_RANDOMIZE_BASE=n ++ ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y ++CONFIG_NMI_LOG_BUF_SHIFT=12 ++CONFIG_MEMCG=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CPUSETS=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_NAMESPACES=y ++CONFIG_USER_NS=y ++CONFIG_SCHED_AUTOGROUP=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_EMBEDDED=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_PROFILING=y ++CONFIG_OPROFILE=m ++CONFIG_KPROBES=y ++CONFIG_JUMP_LABEL=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_TRIM_UNUSED_KSYMS=y ++CONFIG_BLK_DEV_THROTTLING=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_MAC_PARTITION=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++CONFIG_ARCH_BCM2709=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_SMP=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++CONFIG_VMSPLIT_2G=y ++CONFIG_PREEMPT_VOLUNTARY=y ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++# CONFIG_CPU_SW_DOMAIN_PAN is not set ++CONFIG_CLEANCACHE=y ++CONFIG_FRONTSWAP=y ++CONFIG_CMA=y ++CONFIG_ZSMALLOC=m ++CONFIG_PGTABLE_MAPPING=y ++CONFIG_UACCESS_WITH_MEMCPY=y ++CONFIG_SECCOMP=y ++# CONFIG_ATAGS is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y ++CONFIG_VFP=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_BINFMT_MISC=m ++CONFIG_COMPAT=y ++CONFIG_SYSVIPC_COMPAT=y ++ ++# CONFIG_SUSPEND is not set ++CONFIG_PM=y ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM_USER=y ++CONFIG_NET_KEY=m ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NET_IPGRE=m ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m ++CONFIG_INET_IPCOMP=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_DIAG=m ++CONFIG_IPV6=m ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_SUBTREES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y ++CONFIG_NETFILTER=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_ZONES=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++CONFIG_NF_CT_PROTO_DCCP=m ++CONFIG_NF_CT_PROTO_UDPLITE=m ++CONFIG_NF_CONNTRACK_AMANDA=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_CONNTRACK_H323=m ++CONFIG_NF_CONNTRACK_IRC=m ++CONFIG_NF_CONNTRACK_NETBIOS_NS=m ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++CONFIG_NF_CONNTRACK_SANE=m ++CONFIG_NF_CONNTRACK_SIP=m ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_NETFILTER_XT_SET=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HMARK=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_LED=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TPROXY=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_NETFILTER_XT_MATCH_BPF=m ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_NFACCT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SOCKET=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++CONFIG_IP_SET=m ++CONFIG_IP_SET_BITMAP_IP=m ++CONFIG_IP_SET_BITMAP_IPMAC=m ++CONFIG_IP_SET_BITMAP_PORT=m ++CONFIG_IP_SET_HASH_IP=m ++CONFIG_IP_SET_HASH_IPPORT=m ++CONFIG_IP_SET_HASH_IPPORTIP=m ++CONFIG_IP_SET_HASH_IPPORTNET=m ++CONFIG_IP_SET_HASH_NET=m ++CONFIG_IP_SET_HASH_NETPORT=m ++CONFIG_IP_SET_HASH_NETIFACE=m ++CONFIG_IP_SET_LIST_SET=m ++CONFIG_IP_VS=m ++CONFIG_IP_VS_PROTO_TCP=y ++CONFIG_IP_VS_PROTO_UDP=y ++CONFIG_IP_VS_PROTO_ESP=y ++CONFIG_IP_VS_PROTO_AH=y ++CONFIG_IP_VS_PROTO_SCTP=y ++CONFIG_IP_VS_RR=m ++CONFIG_IP_VS_WRR=m ++CONFIG_IP_VS_LC=m ++CONFIG_IP_VS_WLC=m ++CONFIG_IP_VS_LBLC=m ++CONFIG_IP_VS_LBLCR=m ++CONFIG_IP_VS_DH=m ++CONFIG_IP_VS_SH=m ++CONFIG_IP_VS_SED=m ++CONFIG_IP_VS_NQ=m ++CONFIG_IP_VS_FTP=m ++CONFIG_IP_VS_PE_SIP=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_RPFILTER=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_CLUSTERIP=m ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=m ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RPFILTER=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP6_NF_RAW=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_NPT=m ++CONFIG_BRIDGE_NF_EBTABLES=m ++CONFIG_BRIDGE_EBT_BROUTE=m ++CONFIG_BRIDGE_EBT_T_FILTER=m ++CONFIG_BRIDGE_EBT_T_NAT=m ++CONFIG_BRIDGE_EBT_802_3=m ++CONFIG_BRIDGE_EBT_AMONG=m ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++CONFIG_BRIDGE_EBT_LIMIT=m ++CONFIG_BRIDGE_EBT_MARK=m ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++CONFIG_BRIDGE_EBT_STP=m ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=m ++CONFIG_BRIDGE_EBT_MARK_T=m ++CONFIG_BRIDGE_EBT_REDIRECT=m ++CONFIG_BRIDGE_EBT_SNAT=m ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_NFLOG=m ++CONFIG_SCTP_COOKIE_HMAC_SHA1=y ++CONFIG_ATM=m ++CONFIG_L2TP=m ++CONFIG_L2TP_V3=y ++CONFIG_L2TP_IP=m ++CONFIG_L2TP_ETH=m ++CONFIG_BRIDGE=m ++CONFIG_VLAN_8021Q=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_ATALK=m ++CONFIG_6LOWPAN=m ++CONFIG_IEEE802154=m ++CONFIG_IEEE802154_6LOWPAN=m ++CONFIG_MAC802154=m ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_MULTIQ=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFB=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_SCH_DRR=m ++CONFIG_NET_SCH_MQPRIO=m ++CONFIG_NET_SCH_CHOKE=m ++CONFIG_NET_SCH_QFQ=m ++CONFIG_NET_SCH_CODEL=m ++CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_INGRESS=m ++CONFIG_NET_SCH_PLUG=m ++CONFIG_NET_CLS_BASIC=m ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_CLS_U32_MARK=y ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_FLOW=m ++CONFIG_NET_CLS_CGROUP=m ++CONFIG_NET_EMATCH=y ++CONFIG_NET_EMATCH_CMP=m ++CONFIG_NET_EMATCH_NBYTE=m ++CONFIG_NET_EMATCH_U32=m ++CONFIG_NET_EMATCH_META=m ++CONFIG_NET_EMATCH_TEXT=m ++CONFIG_NET_EMATCH_IPSET=m ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_GACT_PROB=y ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m ++CONFIG_BATMAN_ADV=m ++CONFIG_OPENVSWITCH=m ++CONFIG_NET_PKTGEN=m ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++CONFIG_MKISS=m ++CONFIG_6PACK=m ++CONFIG_BPQETHER=m ++CONFIG_BAYCOM_SER_FDX=m ++CONFIG_BAYCOM_SER_HDX=m ++CONFIG_YAM=m ++CONFIG_CAN=m ++CONFIG_CAN_VCAN=m ++CONFIG_CAN_MCP251X=m ++CONFIG_IRDA=m ++CONFIG_IRLAN=m ++CONFIG_IRNET=m ++CONFIG_IRCOMM=m ++CONFIG_IRDA_ULTRA=y ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++CONFIG_IRTTY_SIR=m ++CONFIG_KINGSUN_DONGLE=m ++CONFIG_KSDAZZLE_DONGLE=m ++CONFIG_KS959_DONGLE=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_MCS_FIR=m ++CONFIG_BT=m ++CONFIG_BT_RFCOMM=m ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_BNEP=m ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HIDP=m ++CONFIG_BT_6LOWPAN=m ++CONFIG_BT_HCIBTUSB=m ++CONFIG_BT_HCIUART=m ++CONFIG_BT_HCIUART_3WIRE=y ++CONFIG_BT_HCIUART_BCM=y ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++CONFIG_BT_MRVL=m ++CONFIG_BT_MRVL_SDIO=m ++CONFIG_BT_ATH3K=m ++CONFIG_BT_WILINK=m ++CONFIG_MAC80211=m ++CONFIG_MAC80211_MESH=y ++CONFIG_WIMAX=m ++CONFIG_RFKILL=m ++CONFIG_RFKILL_INPUT=y ++CONFIG_NET_9P=m ++CONFIG_NFC=m ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_MTD=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_NAND=m ++CONFIG_MTD_UBI=m ++CONFIG_OF_CONFIGFS=y ++CONFIG_ZRAM=m ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_CRYPTOLOOP=m ++CONFIG_BLK_DEV_DRBD=m ++CONFIG_BLK_DEV_NBD=m ++CONFIG_BLK_DEV_RAM=y ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_ATA_OVER_ETH=m ++CONFIG_EEPROM_AT24=m ++CONFIG_TI_ST=m ++CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=m ++CONFIG_CHR_DEV_OSST=m ++CONFIG_BLK_DEV_SR=m ++CONFIG_CHR_DEV_SG=m ++CONFIG_SCSI_ISCSI_ATTRS=y ++CONFIG_ISCSI_TCP=m ++CONFIG_ISCSI_BOOT_SYSFS=m ++CONFIG_MD=y ++CONFIG_MD_LINEAR=m ++CONFIG_MD_RAID0=m ++CONFIG_BLK_DEV_DM=m ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++CONFIG_DM_THIN_PROVISIONING=m ++CONFIG_DM_MIRROR=m ++CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_RAID=m ++CONFIG_DM_ZERO=m ++CONFIG_DM_DELAY=m ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=m ++CONFIG_DUMMY=m ++CONFIG_IFB=m ++CONFIG_MACVLAN=m ++CONFIG_IPVLAN=m ++CONFIG_VXLAN=m ++CONFIG_NETCONSOLE=m ++CONFIG_TUN=m ++CONFIG_VETH=m ++CONFIG_ENC28J60=m ++CONFIG_QCA7000=m ++CONFIG_MDIO_BITBANG=m ++CONFIG_PPP=m ++CONFIG_PPP_BSDCOMP=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MPPE=m ++CONFIG_PPP_MULTILINK=y ++CONFIG_PPPOATM=m ++CONFIG_PPPOE=m ++CONFIG_PPPOL2TP=m ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_SLIP=m ++CONFIG_SLIP_COMPRESSED=y ++CONFIG_SLIP_SMART=y ++CONFIG_USB_CATC=m ++CONFIG_USB_KAWETH=m ++CONFIG_USB_PEGASUS=m ++CONFIG_USB_RTL8150=m ++CONFIG_USB_RTL8152=m ++CONFIG_USB_USBNET=y ++CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_AX88179_178A=m ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_CDC_NCM=m ++CONFIG_USB_NET_HUAWEI_CDC_NCM=m ++CONFIG_USB_NET_CDC_MBIM=m ++CONFIG_USB_NET_DM9601=m ++CONFIG_USB_NET_SR9700=m ++CONFIG_USB_NET_SR9800=m ++CONFIG_USB_NET_SMSC75XX=m ++CONFIG_USB_NET_SMSC95XX=y ++CONFIG_USB_NET_GL620A=m ++CONFIG_USB_NET_NET1080=m ++CONFIG_USB_NET_PLUSB=m ++CONFIG_USB_NET_MCS7830=m ++CONFIG_USB_NET_CDC_SUBSET=m ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_EPSON2888=y ++CONFIG_USB_KC2190=y ++CONFIG_USB_NET_ZAURUS=m ++CONFIG_USB_NET_CX82310_ETH=m ++CONFIG_USB_NET_KALMIA=m ++CONFIG_USB_NET_QMI_WWAN=m ++CONFIG_USB_HSO=m ++CONFIG_USB_NET_INT51X1=m ++CONFIG_USB_IPHETH=m ++CONFIG_USB_SIERRA_NET=m ++CONFIG_USB_VL600=m ++CONFIG_ATH9K=m ++CONFIG_ATH9K_HTC=m ++CONFIG_CARL9170=m ++CONFIG_ATH6KL=m ++CONFIG_ATH6KL_USB=m ++CONFIG_AR5523=m ++CONFIG_AT76C50X_USB=m ++CONFIG_B43=m ++# CONFIG_B43_PHY_N is not set ++CONFIG_B43LEGACY=m ++CONFIG_BRCMFMAC=m ++CONFIG_BRCMFMAC_USB=y ++CONFIG_HOSTAP=m ++CONFIG_P54_COMMON=m ++CONFIG_P54_USB=m ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++CONFIG_LIBERTAS_SDIO=m ++CONFIG_LIBERTAS_THINFIRM=m ++CONFIG_LIBERTAS_THINFIRM_USB=m ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++CONFIG_MT7601U=m ++CONFIG_RT2X00=m ++CONFIG_RT2500USB=m ++CONFIG_RT73USB=m ++CONFIG_RT2800USB=m ++CONFIG_RT2800USB_RT3573=y ++CONFIG_RT2800USB_RT53XX=y ++CONFIG_RT2800USB_RT55XX=y ++CONFIG_RT2800USB_UNKNOWN=y ++CONFIG_RTL8187=m ++CONFIG_RTL8192CU=n ++CONFIG_USB_ZD1201=m ++CONFIG_ZD1211RW=m ++CONFIG_MAC80211_HWSIM=m ++CONFIG_USB_NET_RNDIS_WLAN=m ++CONFIG_WIMAX_I2400M_USB=m ++CONFIG_IEEE802154_AT86RF230=m ++CONFIG_IEEE802154_MRF24J40=m ++CONFIG_IEEE802154_CC2520=m ++CONFIG_INPUT_POLLDEV=m ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_JOYDEV=m ++CONFIG_INPUT_EVDEV=m ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_INPUT_JOYSTICK=y ++CONFIG_JOYSTICK_IFORCE=m ++CONFIG_JOYSTICK_IFORCE_USB=y ++CONFIG_JOYSTICK_XPAD=m ++CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y ++CONFIG_JOYSTICK_RPISENSE=m ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ADS7846=m ++CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_FT6236=m ++CONFIG_TOUCHSCREEN_RPI_FT5406=m ++CONFIG_TOUCHSCREEN_USB_COMPOSITE=m ++CONFIG_TOUCHSCREEN_STMPE=m ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_AD714X=m ++CONFIG_INPUT_ATI_REMOTE2=m ++CONFIG_INPUT_KEYSPAN_REMOTE=m ++CONFIG_INPUT_POWERMATE=m ++CONFIG_INPUT_YEALINK=m ++CONFIG_INPUT_CM109=m ++CONFIG_INPUT_UINPUT=m ++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m ++CONFIG_INPUT_ADXL34X=m ++CONFIG_INPUT_CMA3000=m ++CONFIG_SERIO=m ++CONFIG_SERIO_RAW=m ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++CONFIG_BRCM_CHAR_DRIVERS=n ++CONFIG_BCM_VC_CMA=n ++CONFIG_BCM_VCIO=n ++CONFIG_BCM_VC_SM=n ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_DMA is not set ++CONFIG_SERIAL_8250_NR_UARTS=1 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=0 ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_SERIAL_SC16IS7XX=m ++CONFIG_SERIAL_SC16IS7XX_SPI=y ++CONFIG_TTY_PRINTK=y ++CONFIG_HW_RANDOM=y ++CONFIG_RAW_DRIVER=y ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_MUX_PCA954x=m ++CONFIG_I2C_BCM2708=m ++CONFIG_I2C_GPIO=m ++CONFIG_SPI=y ++CONFIG_SPI_BCM2835=m ++CONFIG_SPI_BCM2835AUX=m ++CONFIG_SPI_SPIDEV=y ++CONFIG_PPS=m ++CONFIG_PPS_CLIENT_LDISC=m ++CONFIG_PPS_CLIENT_GPIO=m ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_BCM_VIRT=y ++CONFIG_GPIO_ARIZONA=m ++CONFIG_GPIO_STMPE=y ++CONFIG_GPIO_MCP23S08=m ++CONFIG_W1=m ++CONFIG_W1_MASTER_DS2490=m ++CONFIG_W1_MASTER_DS2482=m ++CONFIG_W1_MASTER_DS1WM=m ++CONFIG_W1_MASTER_GPIO=m ++CONFIG_W1_SLAVE_THERM=m ++CONFIG_W1_SLAVE_SMEM=m ++CONFIG_W1_SLAVE_DS2408=m ++CONFIG_W1_SLAVE_DS2413=m ++CONFIG_W1_SLAVE_DS2406=m ++CONFIG_W1_SLAVE_DS2423=m ++CONFIG_W1_SLAVE_DS2431=m ++CONFIG_W1_SLAVE_DS2433=m ++CONFIG_W1_SLAVE_DS2760=m ++CONFIG_W1_SLAVE_DS2780=m ++CONFIG_W1_SLAVE_DS2781=m ++CONFIG_W1_SLAVE_DS28E04=m ++CONFIG_W1_SLAVE_BQ27000=m ++CONFIG_BATTERY_DS2760=m ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO=y ++CONFIG_HWMON=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_SHT21=m ++CONFIG_SENSORS_SHTC1=m ++CONFIG_THERMAL=y ++CONFIG_THERMAL_BCM2835=y ++CONFIG_WATCHDOG=y ++CONFIG_BCM2835_WDT=y ++CONFIG_UCB1400_CORE=m ++CONFIG_MFD_STMPE=y ++CONFIG_STMPE_SPI=y ++CONFIG_MFD_ARIZONA_I2C=m ++CONFIG_MFD_ARIZONA_SPI=m ++CONFIG_MFD_WM5102=y ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y ++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y ++CONFIG_MEDIA_RADIO_SUPPORT=y ++CONFIG_MEDIA_RC_SUPPORT=y ++CONFIG_MEDIA_CONTROLLER=y ++CONFIG_LIRC=m ++CONFIG_RC_DEVICES=y ++CONFIG_RC_ATI_REMOTE=m ++CONFIG_IR_IMON=m ++CONFIG_IR_MCEUSB=m ++CONFIG_IR_REDRAT3=m ++CONFIG_IR_STREAMZAP=m ++CONFIG_IR_IGUANA=m ++CONFIG_IR_TTUSBIR=m ++CONFIG_RC_LOOPBACK=m ++CONFIG_IR_GPIO_CIR=m ++CONFIG_MEDIA_USB_SUPPORT=y ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_USB_M5602=m ++CONFIG_USB_STV06XX=m ++CONFIG_USB_GL860=m ++CONFIG_USB_GSPCA_BENQ=m ++CONFIG_USB_GSPCA_CONEX=m ++CONFIG_USB_GSPCA_CPIA1=m ++CONFIG_USB_GSPCA_DTCS033=m ++CONFIG_USB_GSPCA_ETOMS=m ++CONFIG_USB_GSPCA_FINEPIX=m ++CONFIG_USB_GSPCA_JEILINJ=m ++CONFIG_USB_GSPCA_JL2005BCD=m ++CONFIG_USB_GSPCA_KINECT=m ++CONFIG_USB_GSPCA_KONICA=m ++CONFIG_USB_GSPCA_MARS=m ++CONFIG_USB_GSPCA_MR97310A=m ++CONFIG_USB_GSPCA_NW80X=m ++CONFIG_USB_GSPCA_OV519=m ++CONFIG_USB_GSPCA_OV534=m ++CONFIG_USB_GSPCA_OV534_9=m ++CONFIG_USB_GSPCA_PAC207=m ++CONFIG_USB_GSPCA_PAC7302=m ++CONFIG_USB_GSPCA_PAC7311=m ++CONFIG_USB_GSPCA_SE401=m ++CONFIG_USB_GSPCA_SN9C2028=m ++CONFIG_USB_GSPCA_SN9C20X=m ++CONFIG_USB_GSPCA_SONIXB=m ++CONFIG_USB_GSPCA_SONIXJ=m ++CONFIG_USB_GSPCA_SPCA500=m ++CONFIG_USB_GSPCA_SPCA501=m ++CONFIG_USB_GSPCA_SPCA505=m ++CONFIG_USB_GSPCA_SPCA506=m ++CONFIG_USB_GSPCA_SPCA508=m ++CONFIG_USB_GSPCA_SPCA561=m ++CONFIG_USB_GSPCA_SPCA1528=m ++CONFIG_USB_GSPCA_SQ905=m ++CONFIG_USB_GSPCA_SQ905C=m ++CONFIG_USB_GSPCA_SQ930X=m ++CONFIG_USB_GSPCA_STK014=m ++CONFIG_USB_GSPCA_STK1135=m ++CONFIG_USB_GSPCA_STV0680=m ++CONFIG_USB_GSPCA_SUNPLUS=m ++CONFIG_USB_GSPCA_T613=m ++CONFIG_USB_GSPCA_TOPRO=m ++CONFIG_USB_GSPCA_TV8532=m ++CONFIG_USB_GSPCA_VC032X=m ++CONFIG_USB_GSPCA_VICAM=m ++CONFIG_USB_GSPCA_XIRLINK_CIT=m ++CONFIG_USB_GSPCA_ZC3XX=m ++CONFIG_USB_PWC=m ++CONFIG_VIDEO_CPIA2=m ++CONFIG_USB_ZR364XX=m ++CONFIG_USB_STKWEBCAM=m ++CONFIG_USB_S2255=m ++CONFIG_VIDEO_USBTV=m ++CONFIG_VIDEO_PVRUSB2=m ++CONFIG_VIDEO_HDPVR=m ++CONFIG_VIDEO_USBVISION=m ++CONFIG_VIDEO_STK1160_COMMON=m ++CONFIG_VIDEO_STK1160_AC97=y ++CONFIG_VIDEO_GO7007=m ++CONFIG_VIDEO_GO7007_USB=m ++CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m ++CONFIG_VIDEO_AU0828=m ++CONFIG_VIDEO_AU0828_RC=y ++CONFIG_VIDEO_CX231XX=m ++CONFIG_VIDEO_CX231XX_ALSA=m ++CONFIG_VIDEO_CX231XX_DVB=m ++CONFIG_VIDEO_TM6000=m ++CONFIG_VIDEO_TM6000_ALSA=m ++CONFIG_VIDEO_TM6000_DVB=m ++CONFIG_DVB_USB=m ++CONFIG_DVB_USB_A800=m ++CONFIG_DVB_USB_DIBUSB_MB=m ++CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y ++CONFIG_DVB_USB_DIBUSB_MC=m ++CONFIG_DVB_USB_DIB0700=m ++CONFIG_DVB_USB_UMT_010=m ++CONFIG_DVB_USB_CXUSB=m ++CONFIG_DVB_USB_M920X=m ++CONFIG_DVB_USB_DIGITV=m ++CONFIG_DVB_USB_VP7045=m ++CONFIG_DVB_USB_VP702X=m ++CONFIG_DVB_USB_GP8PSK=m ++CONFIG_DVB_USB_NOVA_T_USB2=m ++CONFIG_DVB_USB_TTUSB2=m ++CONFIG_DVB_USB_DTT200U=m ++CONFIG_DVB_USB_OPERA1=m ++CONFIG_DVB_USB_AF9005=m ++CONFIG_DVB_USB_AF9005_REMOTE=m ++CONFIG_DVB_USB_PCTV452E=m ++CONFIG_DVB_USB_DW2102=m ++CONFIG_DVB_USB_CINERGY_T2=m ++CONFIG_DVB_USB_DTV5100=m ++CONFIG_DVB_USB_FRIIO=m ++CONFIG_DVB_USB_AZ6027=m ++CONFIG_DVB_USB_TECHNISAT_USB2=m ++CONFIG_DVB_USB_V2=m ++CONFIG_DVB_USB_AF9015=m ++CONFIG_DVB_USB_AF9035=m ++CONFIG_DVB_USB_ANYSEE=m ++CONFIG_DVB_USB_AU6610=m ++CONFIG_DVB_USB_AZ6007=m ++CONFIG_DVB_USB_CE6230=m ++CONFIG_DVB_USB_EC168=m ++CONFIG_DVB_USB_GL861=m ++CONFIG_DVB_USB_LME2510=m ++CONFIG_DVB_USB_MXL111SF=m ++CONFIG_DVB_USB_RTL28XXU=m ++CONFIG_DVB_USB_DVBSKY=m ++CONFIG_SMS_USB_DRV=m ++CONFIG_DVB_B2C2_FLEXCOP_USB=m ++CONFIG_DVB_AS102=m ++CONFIG_VIDEO_EM28XX=m ++CONFIG_VIDEO_EM28XX_V4L2=m ++CONFIG_VIDEO_EM28XX_ALSA=m ++CONFIG_VIDEO_EM28XX_DVB=m ++CONFIG_V4L_PLATFORM_DRIVERS=y ++CONFIG_VIDEO_BCM2835=n ++CONFIG_VIDEO_BCM2835_MMAL=n ++CONFIG_RADIO_SI470X=y ++CONFIG_USB_SI470X=m ++CONFIG_I2C_SI470X=m ++CONFIG_RADIO_SI4713=m ++CONFIG_I2C_SI4713=m ++CONFIG_USB_MR800=m ++CONFIG_USB_DSBR=m ++CONFIG_RADIO_SHARK=m ++CONFIG_RADIO_SHARK2=m ++CONFIG_USB_KEENE=m ++CONFIG_USB_MA901=m ++CONFIG_RADIO_TEA5764=m ++CONFIG_RADIO_SAA7706H=m ++CONFIG_RADIO_TEF6862=m ++CONFIG_RADIO_WL1273=m ++CONFIG_RADIO_WL128X=m ++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set ++CONFIG_VIDEO_UDA1342=m ++CONFIG_VIDEO_SONY_BTF_MPX=m ++CONFIG_VIDEO_TVP5150=m ++CONFIG_VIDEO_TW2804=m ++CONFIG_VIDEO_TW9903=m ++CONFIG_VIDEO_TW9906=m ++CONFIG_VIDEO_OV7640=m ++CONFIG_VIDEO_MT9V011=m ++CONFIG_DRM=m ++CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_UDL=m ++CONFIG_DRM_VC4=m ++CONFIG_FB=y ++CONFIG_FB_BCM2708=y ++CONFIG_FB_UDL=m ++CONFIG_FB_SSD1307=m ++CONFIG_FB_RPISENSE=m ++# CONFIG_BACKLIGHT_GENERIC is not set ++CONFIG_BACKLIGHT_RPI=m ++CONFIG_BACKLIGHT_GPIO=m ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_SOUND=y ++CONFIG_SND=m ++CONFIG_SND_SEQUENCER=m ++CONFIG_SND_SEQ_DUMMY=m ++CONFIG_SND_MIXER_OSS=m ++CONFIG_SND_PCM_OSS=m ++CONFIG_SND_SEQUENCER_OSS=y ++CONFIG_SND_HRTIMER=m ++CONFIG_SND_DUMMY=m ++CONFIG_SND_ALOOP=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++CONFIG_SND_ARM=n ++CONFIG_SND_BCM2835=n ++CONFIG_SND_USB_AUDIO=m ++CONFIG_SND_USB_UA101=m ++CONFIG_SND_USB_CAIAQ=m ++CONFIG_SND_USB_CAIAQ_INPUT=y ++CONFIG_SND_USB_6FIRE=m ++CONFIG_SND_SOC=m ++CONFIG_SND_BCM2835_SOC_I2S=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_DAC=m ++CONFIG_SND_BCM2708_SOC_RPI_PROTO=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m ++CONFIG_SND_BCM2708_SOC_RASPIDAC3=m ++CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m ++CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_DIGIDAC1_SOUNDCARD=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m ++CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_WM8804_I2C=m ++CONFIG_SND_SIMPLE_CARD=m ++CONFIG_SOUND_PRIME=m ++CONFIG_HIDRAW=y ++CONFIG_UHID=m ++CONFIG_HID_A4TECH=m ++CONFIG_HID_ACRUX=m ++CONFIG_HID_APPLE=m ++CONFIG_HID_BELKIN=m ++CONFIG_HID_BETOP_FF=m ++CONFIG_HID_CHERRY=m ++CONFIG_HID_CHICONY=m ++CONFIG_HID_CYPRESS=m ++CONFIG_HID_DRAGONRISE=m ++CONFIG_HID_EMS_FF=m ++CONFIG_HID_ELECOM=m ++CONFIG_HID_ELO=m ++CONFIG_HID_EZKEY=m ++CONFIG_HID_GEMBIRD=m ++CONFIG_HID_HOLTEK=m ++CONFIG_HID_KEYTOUCH=m ++CONFIG_HID_KYE=m ++CONFIG_HID_UCLOGIC=m ++CONFIG_HID_WALTOP=m ++CONFIG_HID_GYRATION=m ++CONFIG_HID_TWINHAN=m ++CONFIG_HID_KENSINGTON=m ++CONFIG_HID_LCPOWER=m ++CONFIG_HID_LOGITECH=m ++CONFIG_HID_LOGITECH_DJ=m ++CONFIG_LOGITECH_FF=y ++CONFIG_LOGIRUMBLEPAD2_FF=y ++CONFIG_LOGIG940_FF=y ++CONFIG_HID_MAGICMOUSE=m ++CONFIG_HID_MICROSOFT=m ++CONFIG_HID_MONTEREY=m ++CONFIG_HID_MULTITOUCH=m ++CONFIG_HID_NTRIG=m ++CONFIG_HID_ORTEK=m ++CONFIG_HID_PANTHERLORD=m ++CONFIG_HID_PETALYNX=m ++CONFIG_HID_PICOLCD=m ++CONFIG_HID_ROCCAT=m ++CONFIG_HID_SAMSUNG=m ++CONFIG_HID_SONY=m ++CONFIG_HID_SPEEDLINK=m ++CONFIG_HID_SUNPLUS=m ++CONFIG_HID_GREENASIA=m ++CONFIG_HID_SMARTJOYPLUS=m ++CONFIG_HID_TOPSEED=m ++CONFIG_HID_THINGM=m ++CONFIG_HID_THRUSTMASTER=m ++CONFIG_HID_WACOM=m ++CONFIG_HID_WIIMOTE=m ++CONFIG_HID_XINMO=m ++CONFIG_HID_ZEROPLUS=m ++CONFIG_HID_ZYDACRON=m ++CONFIG_HID_PID=y ++CONFIG_USB_HIDDEV=y ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_MON=m ++CONFIG_USB_DWCOTG=n ++CONFIG_USB_DWC2=y ++CONFIG_USB_PRINTER=m ++CONFIG_USB_STORAGE=y ++CONFIG_USB_STORAGE_REALTEK=m ++CONFIG_USB_STORAGE_DATAFAB=m ++CONFIG_USB_STORAGE_FREECOM=m ++CONFIG_USB_STORAGE_ISD200=m ++CONFIG_USB_STORAGE_USBAT=m ++CONFIG_USB_STORAGE_SDDR09=m ++CONFIG_USB_STORAGE_SDDR55=m ++CONFIG_USB_STORAGE_JUMPSHOT=m ++CONFIG_USB_STORAGE_ALAUDA=m ++CONFIG_USB_STORAGE_ONETOUCH=m ++CONFIG_USB_STORAGE_KARMA=m ++CONFIG_USB_STORAGE_CYPRESS_ATACB=m ++CONFIG_USB_STORAGE_ENE_UB6250=m ++CONFIG_USB_MDC800=m ++CONFIG_USB_MICROTEK=m ++CONFIG_USBIP_CORE=m ++CONFIG_USBIP_VHCI_HCD=m ++CONFIG_USBIP_HOST=m ++CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_GENERIC=y ++CONFIG_USB_SERIAL_AIRCABLE=m ++CONFIG_USB_SERIAL_ARK3116=m ++CONFIG_USB_SERIAL_BELKIN=m ++CONFIG_USB_SERIAL_CH341=m ++CONFIG_USB_SERIAL_WHITEHEAT=m ++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m ++CONFIG_USB_SERIAL_CP210X=m ++CONFIG_USB_SERIAL_CYPRESS_M8=m ++CONFIG_USB_SERIAL_EMPEG=m ++CONFIG_USB_SERIAL_FTDI_SIO=m ++CONFIG_USB_SERIAL_VISOR=m ++CONFIG_USB_SERIAL_IPAQ=m ++CONFIG_USB_SERIAL_IR=m ++CONFIG_USB_SERIAL_EDGEPORT=m ++CONFIG_USB_SERIAL_EDGEPORT_TI=m ++CONFIG_USB_SERIAL_F81232=m ++CONFIG_USB_SERIAL_GARMIN=m ++CONFIG_USB_SERIAL_IPW=m ++CONFIG_USB_SERIAL_IUU=m ++CONFIG_USB_SERIAL_KEYSPAN_PDA=m ++CONFIG_USB_SERIAL_KEYSPAN=m ++CONFIG_USB_SERIAL_KLSI=m ++CONFIG_USB_SERIAL_KOBIL_SCT=m ++CONFIG_USB_SERIAL_MCT_U232=m ++CONFIG_USB_SERIAL_METRO=m ++CONFIG_USB_SERIAL_MOS7720=m ++CONFIG_USB_SERIAL_MOS7840=m ++CONFIG_USB_SERIAL_NAVMAN=m ++CONFIG_USB_SERIAL_PL2303=m ++CONFIG_USB_SERIAL_OTI6858=m ++CONFIG_USB_SERIAL_QCAUX=m ++CONFIG_USB_SERIAL_QUALCOMM=m ++CONFIG_USB_SERIAL_SPCP8X5=m ++CONFIG_USB_SERIAL_SAFE=m ++CONFIG_USB_SERIAL_SIERRAWIRELESS=m ++CONFIG_USB_SERIAL_SYMBOL=m ++CONFIG_USB_SERIAL_TI=m ++CONFIG_USB_SERIAL_CYBERJACK=m ++CONFIG_USB_SERIAL_XIRCOM=m ++CONFIG_USB_SERIAL_OPTION=m ++CONFIG_USB_SERIAL_OMNINET=m ++CONFIG_USB_SERIAL_OPTICON=m ++CONFIG_USB_SERIAL_XSENS_MT=m ++CONFIG_USB_SERIAL_WISHBONE=m ++CONFIG_USB_SERIAL_SSU100=m ++CONFIG_USB_SERIAL_QT2=m ++CONFIG_USB_SERIAL_DEBUG=m ++CONFIG_USB_EMI62=m ++CONFIG_USB_EMI26=m ++CONFIG_USB_ADUTUX=m ++CONFIG_USB_SEVSEG=m ++CONFIG_USB_RIO500=m ++CONFIG_USB_LEGOTOWER=m ++CONFIG_USB_LCD=m ++CONFIG_USB_CYPRESS_CY7C63=m ++CONFIG_USB_CYTHERM=m ++CONFIG_USB_IDMOUSE=m ++CONFIG_USB_FTDI_ELAN=m ++CONFIG_USB_APPLEDISPLAY=m ++CONFIG_USB_LD=m ++CONFIG_USB_TRANCEVIBRATOR=m ++CONFIG_USB_IOWARRIOR=m ++CONFIG_USB_TEST=m ++CONFIG_USB_ISIGHTFW=m ++CONFIG_USB_YUREX=m ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++CONFIG_USB_CXACRU=m ++CONFIG_USB_UEAGLEATM=m ++CONFIG_USB_XUSBATM=m ++CONFIG_MMC=y ++CONFIG_MMC_BLOCK_MINORS=32 ++CONFIG_MMC_BCM2835=y ++CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_PLTFM=y ++CONFIG_MMC_SPI=m ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_ONESHOT=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_BACKLIGHT=y ++CONFIG_LEDS_TRIGGER_CPU=y ++CONFIG_LEDS_TRIGGER_GPIO=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_LEDS_TRIGGER_TRANSIENT=m ++CONFIG_LEDS_TRIGGER_CAMERA=m ++CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_LEDS_TRIGGER_PANIC=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++CONFIG_RTC_DRV_DS1307=m ++CONFIG_RTC_DRV_DS1374=m ++CONFIG_RTC_DRV_DS1672=m ++CONFIG_RTC_DRV_MAX6900=m ++CONFIG_RTC_DRV_RS5C372=m ++CONFIG_RTC_DRV_ISL1208=m ++CONFIG_RTC_DRV_ISL12022=m ++CONFIG_RTC_DRV_ISL12057=m ++CONFIG_RTC_DRV_X1205=m ++CONFIG_RTC_DRV_PCF8523=m ++CONFIG_RTC_DRV_PCF8563=m ++CONFIG_RTC_DRV_PCF8583=m ++CONFIG_RTC_DRV_M41T80=m ++CONFIG_RTC_DRV_BQ32K=m ++CONFIG_RTC_DRV_S35390A=m ++CONFIG_RTC_DRV_FM3130=m ++CONFIG_RTC_DRV_RX8581=m ++CONFIG_RTC_DRV_RX8025=m ++CONFIG_RTC_DRV_EM3027=m ++CONFIG_RTC_DRV_M41T93=m ++CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1302=m ++CONFIG_RTC_DRV_DS1305=m ++CONFIG_RTC_DRV_DS1390=m ++CONFIG_RTC_DRV_R9701=m ++CONFIG_RTC_DRV_RX4581=m ++CONFIG_RTC_DRV_RS5C348=m ++CONFIG_RTC_DRV_MAX6902=m ++CONFIG_RTC_DRV_PCF2123=m ++CONFIG_RTC_DRV_DS3232=m ++CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_RV3029C2=m ++CONFIG_DMADEVICES=y ++CONFIG_DMA_BCM2835=y ++CONFIG_DMA_BCM2708=y ++CONFIG_UIO=m ++CONFIG_UIO_PDRV_GENIRQ=m ++CONFIG_STAGING=y ++CONFIG_PRISM2_USB=m ++CONFIG_R8712U=m ++CONFIG_R8188EU=m ++CONFIG_R8723AU=m ++CONFIG_VT6656=m ++CONFIG_SPEAKUP=m ++CONFIG_SPEAKUP_SYNTH_SOFT=m ++CONFIG_STAGING_MEDIA=y ++CONFIG_LIRC_STAGING=y ++CONFIG_LIRC_IMON=m ++CONFIG_LIRC_RPI=m ++CONFIG_LIRC_SASEM=m ++CONFIG_LIRC_SERIAL=m ++CONFIG_FB_TFT=m ++CONFIG_FB_TFT_AGM1264K_FL=m ++CONFIG_FB_TFT_BD663474=m ++CONFIG_FB_TFT_HX8340BN=m ++CONFIG_FB_TFT_HX8347D=m ++CONFIG_FB_TFT_HX8353D=m ++CONFIG_FB_TFT_ILI9163=m ++CONFIG_FB_TFT_ILI9320=m ++CONFIG_FB_TFT_ILI9325=m ++CONFIG_FB_TFT_ILI9340=m ++CONFIG_FB_TFT_ILI9341=m ++CONFIG_FB_TFT_ILI9481=m ++CONFIG_FB_TFT_ILI9486=m ++CONFIG_FB_TFT_PCD8544=m ++CONFIG_FB_TFT_RA8875=m ++CONFIG_FB_TFT_S6D02A1=m ++CONFIG_FB_TFT_S6D1121=m ++CONFIG_FB_TFT_SSD1289=m ++CONFIG_FB_TFT_SSD1306=m ++CONFIG_FB_TFT_SSD1331=m ++CONFIG_FB_TFT_SSD1351=m ++CONFIG_FB_TFT_ST7735R=m ++CONFIG_FB_TFT_TINYLCD=m ++CONFIG_FB_TFT_TLS8204=m ++CONFIG_FB_TFT_UC1701=m ++CONFIG_FB_TFT_UPD161704=m ++CONFIG_FB_TFT_WATTEROTT=m ++CONFIG_FB_FLEX=m ++CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2835_MBOX=y ++# CONFIG_IOMMU_SUPPORT is not set ++CONFIG_RASPBERRYPI_POWER=y ++CONFIG_EXTCON=m ++CONFIG_EXTCON_ARIZONA=m ++CONFIG_IIO=m ++CONFIG_IIO_BUFFER=y ++CONFIG_IIO_BUFFER_CB=m ++CONFIG_IIO_KFIFO_BUF=m ++CONFIG_MCP320X=m ++CONFIG_MCP3422=m ++CONFIG_DHT11=m ++CONFIG_PWM_BCM2835=m ++CONFIG_PWM_PCA9685=m ++CONFIG_RASPBERRYPI_FIRMWARE=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_GFS2_FS=m ++CONFIG_OCFS2_FS=m ++CONFIG_BTRFS_FS=m ++CONFIG_BTRFS_FS_POSIX_ACL=y ++CONFIG_NILFS2_FS=m ++CONFIG_F2FS_FS=y ++CONFIG_FANOTIFY=y ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_AUTOFS4_FS=y ++CONFIG_FUSE_FS=m ++CONFIG_CUSE=m ++CONFIG_OVERLAY_FS=m ++CONFIG_FSCACHE=y ++CONFIG_FSCACHE_STATS=y ++CONFIG_FSCACHE_HISTOGRAM=y ++CONFIG_CACHEFILES=y ++CONFIG_ISO9660_FS=m ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=m ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" ++CONFIG_NTFS_FS=m ++CONFIG_NTFS_RW=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_ECRYPT_FS=m ++CONFIG_HFS_FS=m ++CONFIG_HFSPLUS_FS=m ++CONFIG_JFFS2_FS=m ++CONFIG_JFFS2_SUMMARY=y ++CONFIG_UBIFS_FS=m ++CONFIG_SQUASHFS=m ++CONFIG_SQUASHFS_XATTR=y ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFS_FSCACHE=y ++CONFIG_NFSD=m ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_CIFS=m ++CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_POSIX=y ++CONFIG_CIFS_ACL=y ++CONFIG_CIFS_DFS_UPCALL=y ++CONFIG_CIFS_SMB2=y ++CONFIG_CIFS_FSCACHE=y ++CONFIG_9P_FS=m ++CONFIG_9P_FS_POSIX_ACL=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_737=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=m ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=m ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++CONFIG_DLM=m ++CONFIG_PRINTK_TIME=y ++CONFIG_BOOT_PRINTK_DELAY=y ++CONFIG_DEBUG_MEMORY_INIT=y ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_TIMER_STATS=y ++CONFIG_IRQSOFF_TRACER=y ++CONFIG_SCHED_TRACER=y ++CONFIG_STACK_TRACER=y ++CONFIG_BLK_DEV_IO_TRACE=y ++# CONFIG_KPROBE_EVENT is not set ++CONFIG_FUNCTION_PROFILER=y ++CONFIG_KGDB=y ++CONFIG_KGDB_KDB=y ++CONFIG_KDB_KEYBOARD=y ++CONFIG_CRYPTO_USER=m ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_CTS=m ++CONFIG_CRYPTO_XTS=m ++CONFIG_CRYPTO_XCBC=m ++CONFIG_CRYPTO_TGR192=m ++CONFIG_CRYPTO_WP512=m ++CONFIG_CRYPTO_CAST5=m ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_USER_API_SKCIPHER=m ++CONFIG_ARM64_CRYPTO=y ++CONFIG_CRC_ITU_T=y ++CONFIG_LIBCRC32C=y ++CONFIG_BCM2708_VCHIQ=n diff --git a/target/linux/brcm2708/patches-4.9/0094-config-Add-default-configs.patch b/target/linux/brcm2708/patches-4.9/0094-config-Add-default-configs.patch deleted file mode 100644 index c940298c96..0000000000 --- a/target/linux/brcm2708/patches-4.9/0094-config-Add-default-configs.patch +++ /dev/null @@ -1,2623 +0,0 @@ -From dcfe6cf60a2f84f321f64267f09f8a0f19b7a609 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 13 Apr 2015 17:16:29 +0100 -Subject: [PATCH] config: Add default configs - ---- - arch/arm/configs/bcm2709_defconfig | 1297 +++++++++++++++++++++++++++++++++++ - arch/arm/configs/bcmrpi_defconfig | 1308 ++++++++++++++++++++++++++++++++++++ - 2 files changed, 2605 insertions(+) - create mode 100644 arch/arm/configs/bcm2709_defconfig - create mode 100644 arch/arm/configs/bcmrpi_defconfig - ---- /dev/null -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -0,0 +1,1297 @@ -+CONFIG_LOCALVERSION="-v7" -+# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_SYSVIPC=y -+CONFIG_POSIX_MQUEUE=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_BSD_PROCESS_ACCT_V3=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_IKCONFIG=m -+CONFIG_IKCONFIG_PROC=y -+CONFIG_NMI_LOG_BUF_SHIFT=12 -+CONFIG_MEMCG=y -+CONFIG_BLK_CGROUP=y -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CPUSETS=y -+CONFIG_CGROUP_DEVICE=y -+CONFIG_CGROUP_CPUACCT=y -+CONFIG_NAMESPACES=y -+CONFIG_USER_NS=y -+CONFIG_SCHED_AUTOGROUP=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_EMBEDDED=y -+# CONFIG_COMPAT_BRK is not set -+CONFIG_PROFILING=y -+CONFIG_OPROFILE=m -+CONFIG_KPROBES=y -+CONFIG_JUMP_LABEL=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+CONFIG_BLK_DEV_THROTTLING=y -+CONFIG_PARTITION_ADVANCED=y -+CONFIG_MAC_PARTITION=y -+CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_ARCH_BCM=y -+CONFIG_ARCH_BCM2835=y -+# CONFIG_CACHE_L2X0 is not set -+CONFIG_SMP=y -+CONFIG_VMSPLIT_2G=y -+CONFIG_PREEMPT_VOLUNTARY=y -+CONFIG_AEABI=y -+# CONFIG_CPU_SW_DOMAIN_PAN is not set -+CONFIG_CLEANCACHE=y -+CONFIG_FRONTSWAP=y -+CONFIG_CMA=y -+CONFIG_ZSMALLOC=m -+CONFIG_PGTABLE_MAPPING=y -+CONFIG_UACCESS_WITH_MEMCPY=y -+CONFIG_SECCOMP=y -+# CONFIG_ATAGS is not set -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+CONFIG_ZBOOT_ROM_BSS=0x0 -+CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_STAT=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -+CONFIG_VFP=y -+CONFIG_NEON=y -+CONFIG_KERNEL_MODE_NEON=y -+CONFIG_BINFMT_MISC=m -+# CONFIG_SUSPEND is not set -+CONFIG_PM=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_NET_KEY=m -+CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_MULTIPATH=y -+CONFIG_IP_ROUTE_VERBOSE=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+CONFIG_IP_PNP_RARP=y -+CONFIG_NET_IPIP=m -+CONFIG_NET_IPGRE_DEMUX=m -+CONFIG_NET_IPGRE=m -+CONFIG_IP_MROUTE=y -+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IP_PIMSM_V1=y -+CONFIG_IP_PIMSM_V2=y -+CONFIG_SYN_COOKIES=y -+CONFIG_INET_AH=m -+CONFIG_INET_ESP=m -+CONFIG_INET_IPCOMP=m -+CONFIG_INET_XFRM_MODE_TRANSPORT=m -+CONFIG_INET_XFRM_MODE_TUNNEL=m -+CONFIG_INET_XFRM_MODE_BEET=m -+CONFIG_INET_DIAG=m -+CONFIG_IPV6=m -+CONFIG_IPV6_ROUTER_PREF=y -+CONFIG_INET6_AH=m -+CONFIG_INET6_ESP=m -+CONFIG_INET6_IPCOMP=m -+CONFIG_IPV6_TUNNEL=m -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_IPV6_SUBTREES=y -+CONFIG_IPV6_MROUTE=y -+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IPV6_PIMSM_V2=y -+CONFIG_NETFILTER=y -+CONFIG_NF_CONNTRACK=m -+CONFIG_NF_CONNTRACK_ZONES=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_TIMESTAMP=y -+CONFIG_NF_CT_PROTO_DCCP=m -+CONFIG_NF_CT_PROTO_UDPLITE=m -+CONFIG_NF_CONNTRACK_AMANDA=m -+CONFIG_NF_CONNTRACK_FTP=m -+CONFIG_NF_CONNTRACK_H323=m -+CONFIG_NF_CONNTRACK_IRC=m -+CONFIG_NF_CONNTRACK_NETBIOS_NS=m -+CONFIG_NF_CONNTRACK_SNMP=m -+CONFIG_NF_CONNTRACK_PPTP=m -+CONFIG_NF_CONNTRACK_SANE=m -+CONFIG_NF_CONNTRACK_SIP=m -+CONFIG_NF_CONNTRACK_TFTP=m -+CONFIG_NF_CT_NETLINK=m -+CONFIG_NETFILTER_XT_SET=m -+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -+CONFIG_NETFILTER_XT_TARGET_DSCP=m -+CONFIG_NETFILTER_XT_TARGET_HMARK=m -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -+CONFIG_NETFILTER_XT_TARGET_LED=m -+CONFIG_NETFILTER_XT_TARGET_LOG=m -+CONFIG_NETFILTER_XT_TARGET_MARK=m -+CONFIG_NETFILTER_XT_TARGET_NFLOG=m -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -+CONFIG_NETFILTER_XT_TARGET_TEE=m -+CONFIG_NETFILTER_XT_TARGET_TPROXY=m -+CONFIG_NETFILTER_XT_TARGET_TRACE=m -+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m -+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -+CONFIG_NETFILTER_XT_MATCH_BPF=m -+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -+CONFIG_NETFILTER_XT_MATCH_COMMENT=m -+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m -+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -+CONFIG_NETFILTER_XT_MATCH_CPU=m -+CONFIG_NETFILTER_XT_MATCH_DCCP=m -+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -+CONFIG_NETFILTER_XT_MATCH_DSCP=m -+CONFIG_NETFILTER_XT_MATCH_ESP=m -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_HELPER=m -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -+CONFIG_NETFILTER_XT_MATCH_IPVS=m -+CONFIG_NETFILTER_XT_MATCH_LENGTH=m -+CONFIG_NETFILTER_XT_MATCH_LIMIT=m -+CONFIG_NETFILTER_XT_MATCH_MAC=m -+CONFIG_NETFILTER_XT_MATCH_MARK=m -+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -+CONFIG_NETFILTER_XT_MATCH_NFACCT=m -+CONFIG_NETFILTER_XT_MATCH_OSF=m -+CONFIG_NETFILTER_XT_MATCH_OWNER=m -+CONFIG_NETFILTER_XT_MATCH_POLICY=m -+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -+CONFIG_NETFILTER_XT_MATCH_QUOTA=m -+CONFIG_NETFILTER_XT_MATCH_RATEEST=m -+CONFIG_NETFILTER_XT_MATCH_REALM=m -+CONFIG_NETFILTER_XT_MATCH_RECENT=m -+CONFIG_NETFILTER_XT_MATCH_SOCKET=m -+CONFIG_NETFILTER_XT_MATCH_STATE=m -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -+CONFIG_NETFILTER_XT_MATCH_STRING=m -+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -+CONFIG_NETFILTER_XT_MATCH_TIME=m -+CONFIG_NETFILTER_XT_MATCH_U32=m -+CONFIG_IP_SET=m -+CONFIG_IP_SET_BITMAP_IP=m -+CONFIG_IP_SET_BITMAP_IPMAC=m -+CONFIG_IP_SET_BITMAP_PORT=m -+CONFIG_IP_SET_HASH_IP=m -+CONFIG_IP_SET_HASH_IPPORT=m -+CONFIG_IP_SET_HASH_IPPORTIP=m -+CONFIG_IP_SET_HASH_IPPORTNET=m -+CONFIG_IP_SET_HASH_NET=m -+CONFIG_IP_SET_HASH_NETPORT=m -+CONFIG_IP_SET_HASH_NETIFACE=m -+CONFIG_IP_SET_LIST_SET=m -+CONFIG_IP_VS=m -+CONFIG_IP_VS_PROTO_TCP=y -+CONFIG_IP_VS_PROTO_UDP=y -+CONFIG_IP_VS_PROTO_ESP=y -+CONFIG_IP_VS_PROTO_AH=y -+CONFIG_IP_VS_PROTO_SCTP=y -+CONFIG_IP_VS_RR=m -+CONFIG_IP_VS_WRR=m -+CONFIG_IP_VS_LC=m -+CONFIG_IP_VS_WLC=m -+CONFIG_IP_VS_LBLC=m -+CONFIG_IP_VS_LBLCR=m -+CONFIG_IP_VS_DH=m -+CONFIG_IP_VS_SH=m -+CONFIG_IP_VS_SED=m -+CONFIG_IP_VS_NQ=m -+CONFIG_IP_VS_FTP=m -+CONFIG_IP_VS_PE_SIP=m -+CONFIG_NF_CONNTRACK_IPV4=m -+CONFIG_IP_NF_IPTABLES=m -+CONFIG_IP_NF_MATCH_AH=m -+CONFIG_IP_NF_MATCH_ECN=m -+CONFIG_IP_NF_MATCH_RPFILTER=m -+CONFIG_IP_NF_MATCH_TTL=m -+CONFIG_IP_NF_FILTER=m -+CONFIG_IP_NF_TARGET_REJECT=m -+CONFIG_IP_NF_NAT=m -+CONFIG_IP_NF_TARGET_MASQUERADE=m -+CONFIG_IP_NF_TARGET_NETMAP=m -+CONFIG_IP_NF_TARGET_REDIRECT=m -+CONFIG_IP_NF_MANGLE=m -+CONFIG_IP_NF_TARGET_CLUSTERIP=m -+CONFIG_IP_NF_TARGET_ECN=m -+CONFIG_IP_NF_TARGET_TTL=m -+CONFIG_IP_NF_RAW=m -+CONFIG_IP_NF_ARPTABLES=m -+CONFIG_IP_NF_ARPFILTER=m -+CONFIG_IP_NF_ARP_MANGLE=m -+CONFIG_NF_CONNTRACK_IPV6=m -+CONFIG_IP6_NF_IPTABLES=m -+CONFIG_IP6_NF_MATCH_AH=m -+CONFIG_IP6_NF_MATCH_EUI64=m -+CONFIG_IP6_NF_MATCH_FRAG=m -+CONFIG_IP6_NF_MATCH_OPTS=m -+CONFIG_IP6_NF_MATCH_HL=m -+CONFIG_IP6_NF_MATCH_IPV6HEADER=m -+CONFIG_IP6_NF_MATCH_MH=m -+CONFIG_IP6_NF_MATCH_RPFILTER=m -+CONFIG_IP6_NF_MATCH_RT=m -+CONFIG_IP6_NF_TARGET_HL=m -+CONFIG_IP6_NF_FILTER=m -+CONFIG_IP6_NF_TARGET_REJECT=m -+CONFIG_IP6_NF_MANGLE=m -+CONFIG_IP6_NF_RAW=m -+CONFIG_IP6_NF_NAT=m -+CONFIG_IP6_NF_TARGET_MASQUERADE=m -+CONFIG_IP6_NF_TARGET_NPT=m -+CONFIG_BRIDGE_NF_EBTABLES=m -+CONFIG_BRIDGE_EBT_BROUTE=m -+CONFIG_BRIDGE_EBT_T_FILTER=m -+CONFIG_BRIDGE_EBT_T_NAT=m -+CONFIG_BRIDGE_EBT_802_3=m -+CONFIG_BRIDGE_EBT_AMONG=m -+CONFIG_BRIDGE_EBT_ARP=m -+CONFIG_BRIDGE_EBT_IP=m -+CONFIG_BRIDGE_EBT_IP6=m -+CONFIG_BRIDGE_EBT_LIMIT=m -+CONFIG_BRIDGE_EBT_MARK=m -+CONFIG_BRIDGE_EBT_PKTTYPE=m -+CONFIG_BRIDGE_EBT_STP=m -+CONFIG_BRIDGE_EBT_VLAN=m -+CONFIG_BRIDGE_EBT_ARPREPLY=m -+CONFIG_BRIDGE_EBT_DNAT=m -+CONFIG_BRIDGE_EBT_MARK_T=m -+CONFIG_BRIDGE_EBT_REDIRECT=m -+CONFIG_BRIDGE_EBT_SNAT=m -+CONFIG_BRIDGE_EBT_LOG=m -+CONFIG_BRIDGE_EBT_NFLOG=m -+CONFIG_SCTP_COOKIE_HMAC_SHA1=y -+CONFIG_ATM=m -+CONFIG_L2TP=m -+CONFIG_L2TP_V3=y -+CONFIG_L2TP_IP=m -+CONFIG_L2TP_ETH=m -+CONFIG_BRIDGE=m -+CONFIG_VLAN_8021Q=m -+CONFIG_VLAN_8021Q_GVRP=y -+CONFIG_ATALK=m -+CONFIG_6LOWPAN=m -+CONFIG_IEEE802154=m -+CONFIG_IEEE802154_6LOWPAN=m -+CONFIG_MAC802154=m -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_CBQ=m -+CONFIG_NET_SCH_HTB=m -+CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_PRIO=m -+CONFIG_NET_SCH_MULTIQ=m -+CONFIG_NET_SCH_RED=m -+CONFIG_NET_SCH_SFB=m -+CONFIG_NET_SCH_SFQ=m -+CONFIG_NET_SCH_TEQL=m -+CONFIG_NET_SCH_TBF=m -+CONFIG_NET_SCH_GRED=m -+CONFIG_NET_SCH_DSMARK=m -+CONFIG_NET_SCH_NETEM=m -+CONFIG_NET_SCH_DRR=m -+CONFIG_NET_SCH_MQPRIO=m -+CONFIG_NET_SCH_CHOKE=m -+CONFIG_NET_SCH_QFQ=m -+CONFIG_NET_SCH_CODEL=m -+CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_INGRESS=m -+CONFIG_NET_SCH_PLUG=m -+CONFIG_NET_CLS_BASIC=m -+CONFIG_NET_CLS_TCINDEX=m -+CONFIG_NET_CLS_ROUTE4=m -+CONFIG_NET_CLS_FW=m -+CONFIG_NET_CLS_U32=m -+CONFIG_CLS_U32_MARK=y -+CONFIG_NET_CLS_RSVP=m -+CONFIG_NET_CLS_RSVP6=m -+CONFIG_NET_CLS_FLOW=m -+CONFIG_NET_CLS_CGROUP=m -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_CMP=m -+CONFIG_NET_EMATCH_NBYTE=m -+CONFIG_NET_EMATCH_U32=m -+CONFIG_NET_EMATCH_META=m -+CONFIG_NET_EMATCH_TEXT=m -+CONFIG_NET_EMATCH_IPSET=m -+CONFIG_NET_CLS_ACT=y -+CONFIG_NET_ACT_POLICE=m -+CONFIG_NET_ACT_GACT=m -+CONFIG_GACT_PROB=y -+CONFIG_NET_ACT_MIRRED=m -+CONFIG_NET_ACT_IPT=m -+CONFIG_NET_ACT_NAT=m -+CONFIG_NET_ACT_PEDIT=m -+CONFIG_NET_ACT_SIMP=m -+CONFIG_NET_ACT_SKBEDIT=m -+CONFIG_NET_ACT_CSUM=m -+CONFIG_BATMAN_ADV=m -+CONFIG_OPENVSWITCH=m -+CONFIG_NET_PKTGEN=m -+CONFIG_HAMRADIO=y -+CONFIG_AX25=m -+CONFIG_NETROM=m -+CONFIG_ROSE=m -+CONFIG_MKISS=m -+CONFIG_6PACK=m -+CONFIG_BPQETHER=m -+CONFIG_BAYCOM_SER_FDX=m -+CONFIG_BAYCOM_SER_HDX=m -+CONFIG_YAM=m -+CONFIG_CAN=m -+CONFIG_CAN_VCAN=m -+CONFIG_CAN_MCP251X=m -+CONFIG_IRDA=m -+CONFIG_IRLAN=m -+CONFIG_IRNET=m -+CONFIG_IRCOMM=m -+CONFIG_IRDA_ULTRA=y -+CONFIG_IRDA_CACHE_LAST_LSAP=y -+CONFIG_IRDA_FAST_RR=y -+CONFIG_IRTTY_SIR=m -+CONFIG_KINGSUN_DONGLE=m -+CONFIG_KSDAZZLE_DONGLE=m -+CONFIG_KS959_DONGLE=m -+CONFIG_USB_IRDA=m -+CONFIG_SIGMATEL_FIR=m -+CONFIG_MCS_FIR=m -+CONFIG_BT=m -+CONFIG_BT_RFCOMM=m -+CONFIG_BT_RFCOMM_TTY=y -+CONFIG_BT_BNEP=m -+CONFIG_BT_BNEP_MC_FILTER=y -+CONFIG_BT_BNEP_PROTO_FILTER=y -+CONFIG_BT_HIDP=m -+CONFIG_BT_6LOWPAN=m -+CONFIG_BT_HCIBTUSB=m -+CONFIG_BT_HCIUART=m -+CONFIG_BT_HCIUART_3WIRE=y -+CONFIG_BT_HCIUART_BCM=y -+CONFIG_BT_HCIBCM203X=m -+CONFIG_BT_HCIBPA10X=m -+CONFIG_BT_HCIBFUSB=m -+CONFIG_BT_HCIVHCI=m -+CONFIG_BT_MRVL=m -+CONFIG_BT_MRVL_SDIO=m -+CONFIG_BT_ATH3K=m -+CONFIG_BT_WILINK=m -+CONFIG_CFG80211=m -+CONFIG_MAC80211=m -+CONFIG_MAC80211_MESH=y -+CONFIG_WIMAX=m -+CONFIG_RFKILL=m -+CONFIG_RFKILL_INPUT=y -+CONFIG_NET_9P=m -+CONFIG_NFC=m -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+CONFIG_DMA_CMA=y -+CONFIG_CMA_SIZE_MBYTES=5 -+CONFIG_MTD=m -+CONFIG_MTD_BLOCK=m -+CONFIG_MTD_NAND=m -+CONFIG_MTD_UBI=m -+CONFIG_OF_CONFIGFS=y -+CONFIG_ZRAM=m -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_CRYPTOLOOP=m -+CONFIG_BLK_DEV_DRBD=m -+CONFIG_BLK_DEV_NBD=m -+CONFIG_BLK_DEV_RAM=y -+CONFIG_CDROM_PKTCDVD=m -+CONFIG_ATA_OVER_ETH=m -+CONFIG_EEPROM_AT24=m -+CONFIG_TI_ST=m -+CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_CHR_DEV_ST=m -+CONFIG_CHR_DEV_OSST=m -+CONFIG_BLK_DEV_SR=m -+CONFIG_CHR_DEV_SG=m -+CONFIG_SCSI_ISCSI_ATTRS=y -+CONFIG_ISCSI_TCP=m -+CONFIG_ISCSI_BOOT_SYSFS=m -+CONFIG_MD=y -+CONFIG_MD_LINEAR=m -+CONFIG_MD_RAID0=m -+CONFIG_BLK_DEV_DM=m -+CONFIG_DM_CRYPT=m -+CONFIG_DM_SNAPSHOT=m -+CONFIG_DM_THIN_PROVISIONING=m -+CONFIG_DM_MIRROR=m -+CONFIG_DM_LOG_USERSPACE=m -+CONFIG_DM_RAID=m -+CONFIG_DM_ZERO=m -+CONFIG_DM_DELAY=m -+CONFIG_NETDEVICES=y -+CONFIG_BONDING=m -+CONFIG_DUMMY=m -+CONFIG_IFB=m -+CONFIG_MACVLAN=m -+CONFIG_VXLAN=m -+CONFIG_NETCONSOLE=m -+CONFIG_TUN=m -+CONFIG_VETH=m -+CONFIG_ENC28J60=m -+CONFIG_QCA7000=m -+CONFIG_MDIO_BITBANG=m -+CONFIG_PPP=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_FILTER=y -+CONFIG_PPP_MPPE=m -+CONFIG_PPP_MULTILINK=y -+CONFIG_PPPOATM=m -+CONFIG_PPPOE=m -+CONFIG_PPPOL2TP=m -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_SLIP_SMART=y -+CONFIG_USB_CATC=m -+CONFIG_USB_KAWETH=m -+CONFIG_USB_PEGASUS=m -+CONFIG_USB_RTL8150=m -+CONFIG_USB_RTL8152=m -+CONFIG_USB_USBNET=y -+CONFIG_USB_NET_AX8817X=m -+CONFIG_USB_NET_AX88179_178A=m -+CONFIG_USB_NET_CDCETHER=m -+CONFIG_USB_NET_CDC_EEM=m -+CONFIG_USB_NET_CDC_NCM=m -+CONFIG_USB_NET_HUAWEI_CDC_NCM=m -+CONFIG_USB_NET_CDC_MBIM=m -+CONFIG_USB_NET_DM9601=m -+CONFIG_USB_NET_SR9700=m -+CONFIG_USB_NET_SR9800=m -+CONFIG_USB_NET_SMSC75XX=m -+CONFIG_USB_NET_SMSC95XX=y -+CONFIG_USB_NET_GL620A=m -+CONFIG_USB_NET_NET1080=m -+CONFIG_USB_NET_PLUSB=m -+CONFIG_USB_NET_MCS7830=m -+CONFIG_USB_NET_CDC_SUBSET=m -+CONFIG_USB_ALI_M5632=y -+CONFIG_USB_AN2720=y -+CONFIG_USB_EPSON2888=y -+CONFIG_USB_KC2190=y -+CONFIG_USB_NET_ZAURUS=m -+CONFIG_USB_NET_CX82310_ETH=m -+CONFIG_USB_NET_KALMIA=m -+CONFIG_USB_NET_QMI_WWAN=m -+CONFIG_USB_HSO=m -+CONFIG_USB_NET_INT51X1=m -+CONFIG_USB_IPHETH=m -+CONFIG_USB_SIERRA_NET=m -+CONFIG_USB_VL600=m -+CONFIG_ATH9K=m -+CONFIG_ATH9K_HTC=m -+CONFIG_CARL9170=m -+CONFIG_ATH6KL=m -+CONFIG_ATH6KL_USB=m -+CONFIG_AR5523=m -+CONFIG_AT76C50X_USB=m -+CONFIG_B43=m -+# CONFIG_B43_PHY_N is not set -+CONFIG_B43LEGACY=m -+CONFIG_BRCMFMAC=m -+CONFIG_BRCMFMAC_USB=y -+CONFIG_HOSTAP=m -+CONFIG_P54_COMMON=m -+CONFIG_P54_USB=m -+CONFIG_LIBERTAS=m -+CONFIG_LIBERTAS_USB=m -+CONFIG_LIBERTAS_SDIO=m -+CONFIG_LIBERTAS_THINFIRM=m -+CONFIG_LIBERTAS_THINFIRM_USB=m -+CONFIG_MWIFIEX=m -+CONFIG_MWIFIEX_SDIO=m -+CONFIG_MT7601U=m -+CONFIG_RT2X00=m -+CONFIG_RT2500USB=m -+CONFIG_RT73USB=m -+CONFIG_RT2800USB=m -+CONFIG_RT2800USB_RT3573=y -+CONFIG_RT2800USB_RT53XX=y -+CONFIG_RT2800USB_RT55XX=y -+CONFIG_RT2800USB_UNKNOWN=y -+CONFIG_RTL8187=m -+CONFIG_RTL8192CU=m -+CONFIG_USB_ZD1201=m -+CONFIG_ZD1211RW=m -+CONFIG_MAC80211_HWSIM=m -+CONFIG_USB_NET_RNDIS_WLAN=m -+CONFIG_WIMAX_I2400M_USB=m -+CONFIG_IEEE802154_AT86RF230=m -+CONFIG_IEEE802154_MRF24J40=m -+CONFIG_IEEE802154_CC2520=m -+CONFIG_INPUT_POLLDEV=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+CONFIG_INPUT_JOYDEV=m -+CONFIG_INPUT_EVDEV=m -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m -+# CONFIG_INPUT_MOUSE is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_JOYSTICK_IFORCE=m -+CONFIG_JOYSTICK_IFORCE_USB=y -+CONFIG_JOYSTICK_XPAD=m -+CONFIG_JOYSTICK_XPAD_FF=y -+CONFIG_JOYSTICK_XPAD_LEDS=y -+CONFIG_JOYSTICK_RPISENSE=m -+CONFIG_INPUT_TOUCHSCREEN=y -+CONFIG_TOUCHSCREEN_ADS7846=m -+CONFIG_TOUCHSCREEN_EGALAX=m -+CONFIG_TOUCHSCREEN_EKTF2127=m -+CONFIG_TOUCHSCREEN_RPI_FT5406=m -+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -+CONFIG_TOUCHSCREEN_STMPE=m -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_AD714X=m -+CONFIG_INPUT_ATI_REMOTE2=m -+CONFIG_INPUT_KEYSPAN_REMOTE=m -+CONFIG_INPUT_POWERMATE=m -+CONFIG_INPUT_YEALINK=m -+CONFIG_INPUT_CM109=m -+CONFIG_INPUT_UINPUT=m -+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -+CONFIG_INPUT_ADXL34X=m -+CONFIG_INPUT_CMA3000=m -+CONFIG_SERIO=m -+CONFIG_SERIO_RAW=m -+CONFIG_GAMEPORT=m -+CONFIG_GAMEPORT_NS558=m -+CONFIG_GAMEPORT_L4=m -+CONFIG_BRCM_CHAR_DRIVERS=y -+CONFIG_BCM_VC_CMA=y -+CONFIG_BCM_VCIO=y -+CONFIG_BCM_VC_SM=y -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set -+CONFIG_SERIAL_8250=y -+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -+CONFIG_SERIAL_8250_CONSOLE=y -+# CONFIG_SERIAL_8250_DMA is not set -+CONFIG_SERIAL_8250_NR_UARTS=1 -+CONFIG_SERIAL_8250_RUNTIME_UARTS=0 -+CONFIG_SERIAL_8250_EXTENDED=y -+CONFIG_SERIAL_8250_SHARE_IRQ=y -+CONFIG_SERIAL_8250_BCM2835AUX=y -+CONFIG_SERIAL_OF_PLATFORM=y -+CONFIG_SERIAL_AMBA_PL011=y -+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -+CONFIG_SERIAL_SC16IS7XX=m -+CONFIG_SERIAL_SC16IS7XX_SPI=y -+CONFIG_TTY_PRINTK=y -+CONFIG_HW_RANDOM=y -+CONFIG_RAW_DRIVER=y -+CONFIG_I2C=y -+CONFIG_I2C_CHARDEV=m -+CONFIG_I2C_MUX_PCA954x=m -+CONFIG_I2C_BCM2708=m -+CONFIG_I2C_BCM2835=m -+CONFIG_I2C_GPIO=m -+CONFIG_SPI=y -+CONFIG_SPI_BCM2835=m -+CONFIG_SPI_BCM2835AUX=m -+CONFIG_SPI_SPIDEV=y -+CONFIG_PPS=m -+CONFIG_PPS_CLIENT_LDISC=m -+CONFIG_PPS_CLIENT_GPIO=m -+CONFIG_GPIO_SYSFS=y -+CONFIG_GPIO_BCM_VIRT=y -+CONFIG_GPIO_ARIZONA=m -+CONFIG_GPIO_STMPE=y -+CONFIG_GPIO_MCP23S08=m -+CONFIG_W1=m -+CONFIG_W1_MASTER_DS2490=m -+CONFIG_W1_MASTER_DS2482=m -+CONFIG_W1_MASTER_DS1WM=m -+CONFIG_W1_MASTER_GPIO=m -+CONFIG_W1_SLAVE_THERM=m -+CONFIG_W1_SLAVE_SMEM=m -+CONFIG_W1_SLAVE_DS2408=m -+CONFIG_W1_SLAVE_DS2413=m -+CONFIG_W1_SLAVE_DS2406=m -+CONFIG_W1_SLAVE_DS2423=m -+CONFIG_W1_SLAVE_DS2431=m -+CONFIG_W1_SLAVE_DS2433=m -+CONFIG_W1_SLAVE_DS2760=m -+CONFIG_W1_SLAVE_DS2780=m -+CONFIG_W1_SLAVE_DS2781=m -+CONFIG_W1_SLAVE_DS28E04=m -+CONFIG_W1_SLAVE_BQ27000=m -+CONFIG_POWER_RESET=y -+CONFIG_POWER_RESET_GPIO=y -+CONFIG_BATTERY_DS2760=m -+CONFIG_HWMON=m -+CONFIG_SENSORS_LM75=m -+CONFIG_SENSORS_SHT21=m -+CONFIG_SENSORS_SHTC1=m -+CONFIG_SENSORS_INA2XX=m -+CONFIG_THERMAL=y -+CONFIG_THERMAL_BCM2835=y -+CONFIG_WATCHDOG=y -+CONFIG_BCM2835_WDT=y -+CONFIG_UCB1400_CORE=m -+CONFIG_MFD_STMPE=y -+CONFIG_STMPE_SPI=y -+CONFIG_MFD_ARIZONA_I2C=m -+CONFIG_MFD_ARIZONA_SPI=m -+CONFIG_MFD_WM5102=y -+CONFIG_MEDIA_SUPPORT=m -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y -+CONFIG_MEDIA_RADIO_SUPPORT=y -+CONFIG_MEDIA_RC_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y -+CONFIG_LIRC=m -+CONFIG_RC_DEVICES=y -+CONFIG_RC_ATI_REMOTE=m -+CONFIG_IR_IMON=m -+CONFIG_IR_MCEUSB=m -+CONFIG_IR_REDRAT3=m -+CONFIG_IR_STREAMZAP=m -+CONFIG_IR_IGUANA=m -+CONFIG_IR_TTUSBIR=m -+CONFIG_RC_LOOPBACK=m -+CONFIG_IR_GPIO_CIR=m -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_USB_M5602=m -+CONFIG_USB_STV06XX=m -+CONFIG_USB_GL860=m -+CONFIG_USB_GSPCA_BENQ=m -+CONFIG_USB_GSPCA_CONEX=m -+CONFIG_USB_GSPCA_CPIA1=m -+CONFIG_USB_GSPCA_DTCS033=m -+CONFIG_USB_GSPCA_ETOMS=m -+CONFIG_USB_GSPCA_FINEPIX=m -+CONFIG_USB_GSPCA_JEILINJ=m -+CONFIG_USB_GSPCA_JL2005BCD=m -+CONFIG_USB_GSPCA_KINECT=m -+CONFIG_USB_GSPCA_KONICA=m -+CONFIG_USB_GSPCA_MARS=m -+CONFIG_USB_GSPCA_MR97310A=m -+CONFIG_USB_GSPCA_NW80X=m -+CONFIG_USB_GSPCA_OV519=m -+CONFIG_USB_GSPCA_OV534=m -+CONFIG_USB_GSPCA_OV534_9=m -+CONFIG_USB_GSPCA_PAC207=m -+CONFIG_USB_GSPCA_PAC7302=m -+CONFIG_USB_GSPCA_PAC7311=m -+CONFIG_USB_GSPCA_SE401=m -+CONFIG_USB_GSPCA_SN9C2028=m -+CONFIG_USB_GSPCA_SN9C20X=m -+CONFIG_USB_GSPCA_SONIXB=m -+CONFIG_USB_GSPCA_SONIXJ=m -+CONFIG_USB_GSPCA_SPCA500=m -+CONFIG_USB_GSPCA_SPCA501=m -+CONFIG_USB_GSPCA_SPCA505=m -+CONFIG_USB_GSPCA_SPCA506=m -+CONFIG_USB_GSPCA_SPCA508=m -+CONFIG_USB_GSPCA_SPCA561=m -+CONFIG_USB_GSPCA_SPCA1528=m -+CONFIG_USB_GSPCA_SQ905=m -+CONFIG_USB_GSPCA_SQ905C=m -+CONFIG_USB_GSPCA_SQ930X=m -+CONFIG_USB_GSPCA_STK014=m -+CONFIG_USB_GSPCA_STK1135=m -+CONFIG_USB_GSPCA_STV0680=m -+CONFIG_USB_GSPCA_SUNPLUS=m -+CONFIG_USB_GSPCA_T613=m -+CONFIG_USB_GSPCA_TOPRO=m -+CONFIG_USB_GSPCA_TV8532=m -+CONFIG_USB_GSPCA_VC032X=m -+CONFIG_USB_GSPCA_VICAM=m -+CONFIG_USB_GSPCA_XIRLINK_CIT=m -+CONFIG_USB_GSPCA_ZC3XX=m -+CONFIG_USB_PWC=m -+CONFIG_VIDEO_CPIA2=m -+CONFIG_USB_ZR364XX=m -+CONFIG_USB_STKWEBCAM=m -+CONFIG_USB_S2255=m -+CONFIG_VIDEO_USBTV=m -+CONFIG_VIDEO_PVRUSB2=m -+CONFIG_VIDEO_HDPVR=m -+CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160_COMMON=m -+CONFIG_VIDEO_STK1160_AC97=y -+CONFIG_VIDEO_GO7007=m -+CONFIG_VIDEO_GO7007_USB=m -+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m -+CONFIG_VIDEO_AU0828=m -+CONFIG_VIDEO_AU0828_RC=y -+CONFIG_VIDEO_CX231XX=m -+CONFIG_VIDEO_CX231XX_ALSA=m -+CONFIG_VIDEO_CX231XX_DVB=m -+CONFIG_VIDEO_TM6000=m -+CONFIG_VIDEO_TM6000_ALSA=m -+CONFIG_VIDEO_TM6000_DVB=m -+CONFIG_DVB_USB=m -+CONFIG_DVB_USB_A800=m -+CONFIG_DVB_USB_DIBUSB_MB=m -+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y -+CONFIG_DVB_USB_DIBUSB_MC=m -+CONFIG_DVB_USB_DIB0700=m -+CONFIG_DVB_USB_UMT_010=m -+CONFIG_DVB_USB_CXUSB=m -+CONFIG_DVB_USB_M920X=m -+CONFIG_DVB_USB_DIGITV=m -+CONFIG_DVB_USB_VP7045=m -+CONFIG_DVB_USB_VP702X=m -+CONFIG_DVB_USB_GP8PSK=m -+CONFIG_DVB_USB_NOVA_T_USB2=m -+CONFIG_DVB_USB_TTUSB2=m -+CONFIG_DVB_USB_DTT200U=m -+CONFIG_DVB_USB_OPERA1=m -+CONFIG_DVB_USB_AF9005=m -+CONFIG_DVB_USB_AF9005_REMOTE=m -+CONFIG_DVB_USB_PCTV452E=m -+CONFIG_DVB_USB_DW2102=m -+CONFIG_DVB_USB_CINERGY_T2=m -+CONFIG_DVB_USB_DTV5100=m -+CONFIG_DVB_USB_FRIIO=m -+CONFIG_DVB_USB_AZ6027=m -+CONFIG_DVB_USB_TECHNISAT_USB2=m -+CONFIG_DVB_USB_V2=m -+CONFIG_DVB_USB_AF9015=m -+CONFIG_DVB_USB_AF9035=m -+CONFIG_DVB_USB_ANYSEE=m -+CONFIG_DVB_USB_AU6610=m -+CONFIG_DVB_USB_AZ6007=m -+CONFIG_DVB_USB_CE6230=m -+CONFIG_DVB_USB_EC168=m -+CONFIG_DVB_USB_GL861=m -+CONFIG_DVB_USB_LME2510=m -+CONFIG_DVB_USB_MXL111SF=m -+CONFIG_DVB_USB_RTL28XXU=m -+CONFIG_DVB_USB_DVBSKY=m -+CONFIG_SMS_USB_DRV=m -+CONFIG_DVB_B2C2_FLEXCOP_USB=m -+CONFIG_DVB_AS102=m -+CONFIG_VIDEO_EM28XX=m -+CONFIG_VIDEO_EM28XX_V4L2=m -+CONFIG_VIDEO_EM28XX_ALSA=m -+CONFIG_VIDEO_EM28XX_DVB=m -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_BCM2835=y -+CONFIG_VIDEO_BCM2835_MMAL=m -+CONFIG_RADIO_SI470X=y -+CONFIG_USB_SI470X=m -+CONFIG_I2C_SI470X=m -+CONFIG_RADIO_SI4713=m -+CONFIG_I2C_SI4713=m -+CONFIG_USB_MR800=m -+CONFIG_USB_DSBR=m -+CONFIG_RADIO_SHARK=m -+CONFIG_RADIO_SHARK2=m -+CONFIG_USB_KEENE=m -+CONFIG_USB_MA901=m -+CONFIG_RADIO_TEA5764=m -+CONFIG_RADIO_SAA7706H=m -+CONFIG_RADIO_TEF6862=m -+CONFIG_RADIO_WL1273=m -+CONFIG_RADIO_WL128X=m -+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -+CONFIG_VIDEO_UDA1342=m -+CONFIG_VIDEO_SONY_BTF_MPX=m -+CONFIG_VIDEO_TVP5150=m -+CONFIG_VIDEO_TW2804=m -+CONFIG_VIDEO_TW9903=m -+CONFIG_VIDEO_TW9906=m -+CONFIG_VIDEO_OV7640=m -+CONFIG_VIDEO_MT9V011=m -+CONFIG_DRM=m -+CONFIG_DRM_LOAD_EDID_FIRMWARE=y -+CONFIG_DRM_UDL=m -+CONFIG_DRM_VC4=m -+CONFIG_FB=y -+CONFIG_FB_BCM2708=y -+CONFIG_FB_UDL=m -+CONFIG_FB_SSD1307=m -+CONFIG_FB_RPISENSE=m -+# CONFIG_BACKLIGHT_GENERIC is not set -+CONFIG_BACKLIGHT_RPI=m -+CONFIG_BACKLIGHT_GPIO=m -+CONFIG_FRAMEBUFFER_CONSOLE=y -+CONFIG_LOGO=y -+# CONFIG_LOGO_LINUX_MONO is not set -+# CONFIG_LOGO_LINUX_VGA16 is not set -+CONFIG_SOUND=y -+CONFIG_SND=m -+CONFIG_SND_SEQUENCER=m -+CONFIG_SND_SEQ_DUMMY=m -+CONFIG_SND_MIXER_OSS=m -+CONFIG_SND_PCM_OSS=m -+CONFIG_SND_SEQUENCER_OSS=y -+CONFIG_SND_HRTIMER=m -+CONFIG_SND_DUMMY=m -+CONFIG_SND_ALOOP=m -+CONFIG_SND_VIRMIDI=m -+CONFIG_SND_MTPAV=m -+CONFIG_SND_SERIAL_U16550=m -+CONFIG_SND_MPU401=m -+CONFIG_SND_BCM2835=m -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_USB_UA101=m -+CONFIG_SND_USB_CAIAQ=m -+CONFIG_SND_USB_CAIAQ_INPUT=y -+CONFIG_SND_USB_6FIRE=m -+CONFIG_SND_SOC=m -+CONFIG_SND_BCM2835_SOC_I2S=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_DAC=m -+CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m -+CONFIG_SND_BCM2708_SOC_RASPIDAC3=m -+CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m -+CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m -+CONFIG_SND_DIGIDAC1_SOUNDCARD=m -+CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m -+CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_PISOUND=m -+CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_AK4554=m -+CONFIG_SND_SOC_WM8804_I2C=m -+CONFIG_SND_SIMPLE_CARD=m -+CONFIG_SOUND_PRIME=m -+CONFIG_HIDRAW=y -+CONFIG_UHID=m -+CONFIG_HID_A4TECH=m -+CONFIG_HID_ACRUX=m -+CONFIG_HID_APPLE=m -+CONFIG_HID_BELKIN=m -+CONFIG_HID_BETOP_FF=m -+CONFIG_HID_CHERRY=m -+CONFIG_HID_CHICONY=m -+CONFIG_HID_CYPRESS=m -+CONFIG_HID_DRAGONRISE=m -+CONFIG_HID_EMS_FF=m -+CONFIG_HID_ELECOM=m -+CONFIG_HID_ELO=m -+CONFIG_HID_EZKEY=m -+CONFIG_HID_GEMBIRD=m -+CONFIG_HID_HOLTEK=m -+CONFIG_HID_KEYTOUCH=m -+CONFIG_HID_KYE=m -+CONFIG_HID_UCLOGIC=m -+CONFIG_HID_WALTOP=m -+CONFIG_HID_GYRATION=m -+CONFIG_HID_TWINHAN=m -+CONFIG_HID_KENSINGTON=m -+CONFIG_HID_LCPOWER=m -+CONFIG_HID_LOGITECH=m -+CONFIG_HID_LOGITECH_DJ=m -+CONFIG_LOGITECH_FF=y -+CONFIG_LOGIRUMBLEPAD2_FF=y -+CONFIG_LOGIG940_FF=y -+CONFIG_HID_MAGICMOUSE=m -+CONFIG_HID_MICROSOFT=m -+CONFIG_HID_MONTEREY=m -+CONFIG_HID_MULTITOUCH=m -+CONFIG_HID_NTRIG=m -+CONFIG_HID_ORTEK=m -+CONFIG_HID_PANTHERLORD=m -+CONFIG_HID_PETALYNX=m -+CONFIG_HID_PICOLCD=m -+CONFIG_HID_ROCCAT=m -+CONFIG_HID_SAMSUNG=m -+CONFIG_HID_SONY=m -+CONFIG_HID_SPEEDLINK=m -+CONFIG_HID_SUNPLUS=m -+CONFIG_HID_GREENASIA=m -+CONFIG_HID_SMARTJOYPLUS=m -+CONFIG_HID_TOPSEED=m -+CONFIG_HID_THINGM=m -+CONFIG_HID_THRUSTMASTER=m -+CONFIG_HID_WACOM=m -+CONFIG_HID_WIIMOTE=m -+CONFIG_HID_XINMO=m -+CONFIG_HID_ZEROPLUS=m -+CONFIG_HID_ZYDACRON=m -+CONFIG_HID_PID=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB=y -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+CONFIG_USB_MON=m -+CONFIG_USB_DWCOTG=y -+CONFIG_USB_PRINTER=m -+CONFIG_USB_STORAGE=y -+CONFIG_USB_STORAGE_REALTEK=m -+CONFIG_USB_STORAGE_DATAFAB=m -+CONFIG_USB_STORAGE_FREECOM=m -+CONFIG_USB_STORAGE_ISD200=m -+CONFIG_USB_STORAGE_USBAT=m -+CONFIG_USB_STORAGE_SDDR09=m -+CONFIG_USB_STORAGE_SDDR55=m -+CONFIG_USB_STORAGE_JUMPSHOT=m -+CONFIG_USB_STORAGE_ALAUDA=m -+CONFIG_USB_STORAGE_ONETOUCH=m -+CONFIG_USB_STORAGE_KARMA=m -+CONFIG_USB_STORAGE_CYPRESS_ATACB=m -+CONFIG_USB_STORAGE_ENE_UB6250=m -+CONFIG_USB_MDC800=m -+CONFIG_USB_MICROTEK=m -+CONFIG_USBIP_CORE=m -+CONFIG_USBIP_VHCI_HCD=m -+CONFIG_USBIP_HOST=m -+CONFIG_USB_SERIAL=m -+CONFIG_USB_SERIAL_GENERIC=y -+CONFIG_USB_SERIAL_AIRCABLE=m -+CONFIG_USB_SERIAL_ARK3116=m -+CONFIG_USB_SERIAL_BELKIN=m -+CONFIG_USB_SERIAL_CH341=m -+CONFIG_USB_SERIAL_WHITEHEAT=m -+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -+CONFIG_USB_SERIAL_CP210X=m -+CONFIG_USB_SERIAL_CYPRESS_M8=m -+CONFIG_USB_SERIAL_EMPEG=m -+CONFIG_USB_SERIAL_FTDI_SIO=m -+CONFIG_USB_SERIAL_VISOR=m -+CONFIG_USB_SERIAL_IPAQ=m -+CONFIG_USB_SERIAL_IR=m -+CONFIG_USB_SERIAL_EDGEPORT=m -+CONFIG_USB_SERIAL_EDGEPORT_TI=m -+CONFIG_USB_SERIAL_F81232=m -+CONFIG_USB_SERIAL_GARMIN=m -+CONFIG_USB_SERIAL_IPW=m -+CONFIG_USB_SERIAL_IUU=m -+CONFIG_USB_SERIAL_KEYSPAN_PDA=m -+CONFIG_USB_SERIAL_KEYSPAN=m -+CONFIG_USB_SERIAL_KLSI=m -+CONFIG_USB_SERIAL_KOBIL_SCT=m -+CONFIG_USB_SERIAL_MCT_U232=m -+CONFIG_USB_SERIAL_METRO=m -+CONFIG_USB_SERIAL_MOS7720=m -+CONFIG_USB_SERIAL_MOS7840=m -+CONFIG_USB_SERIAL_NAVMAN=m -+CONFIG_USB_SERIAL_PL2303=m -+CONFIG_USB_SERIAL_OTI6858=m -+CONFIG_USB_SERIAL_QCAUX=m -+CONFIG_USB_SERIAL_QUALCOMM=m -+CONFIG_USB_SERIAL_SPCP8X5=m -+CONFIG_USB_SERIAL_SAFE=m -+CONFIG_USB_SERIAL_SIERRAWIRELESS=m -+CONFIG_USB_SERIAL_SYMBOL=m -+CONFIG_USB_SERIAL_TI=m -+CONFIG_USB_SERIAL_CYBERJACK=m -+CONFIG_USB_SERIAL_XIRCOM=m -+CONFIG_USB_SERIAL_OPTION=m -+CONFIG_USB_SERIAL_OMNINET=m -+CONFIG_USB_SERIAL_OPTICON=m -+CONFIG_USB_SERIAL_XSENS_MT=m -+CONFIG_USB_SERIAL_WISHBONE=m -+CONFIG_USB_SERIAL_SSU100=m -+CONFIG_USB_SERIAL_QT2=m -+CONFIG_USB_SERIAL_DEBUG=m -+CONFIG_USB_EMI62=m -+CONFIG_USB_EMI26=m -+CONFIG_USB_ADUTUX=m -+CONFIG_USB_SEVSEG=m -+CONFIG_USB_RIO500=m -+CONFIG_USB_LEGOTOWER=m -+CONFIG_USB_LCD=m -+CONFIG_USB_CYPRESS_CY7C63=m -+CONFIG_USB_CYTHERM=m -+CONFIG_USB_IDMOUSE=m -+CONFIG_USB_FTDI_ELAN=m -+CONFIG_USB_APPLEDISPLAY=m -+CONFIG_USB_LD=m -+CONFIG_USB_TRANCEVIBRATOR=m -+CONFIG_USB_IOWARRIOR=m -+CONFIG_USB_TEST=m -+CONFIG_USB_ISIGHTFW=m -+CONFIG_USB_YUREX=m -+CONFIG_USB_ATM=m -+CONFIG_USB_SPEEDTOUCH=m -+CONFIG_USB_CXACRU=m -+CONFIG_USB_UEAGLEATM=m -+CONFIG_USB_XUSBATM=m -+CONFIG_MMC=y -+CONFIG_MMC_BLOCK_MINORS=32 -+CONFIG_MMC_BCM2835=y -+CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SPI=m -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_GPIO=y -+CONFIG_LEDS_TRIGGER_TIMER=y -+CONFIG_LEDS_TRIGGER_ONESHOT=y -+CONFIG_LEDS_TRIGGER_HEARTBEAT=y -+CONFIG_LEDS_TRIGGER_BACKLIGHT=y -+CONFIG_LEDS_TRIGGER_CPU=y -+CONFIG_LEDS_TRIGGER_GPIO=y -+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -+CONFIG_LEDS_TRIGGER_TRANSIENT=m -+CONFIG_LEDS_TRIGGER_CAMERA=m -+CONFIG_LEDS_TRIGGER_INPUT=y -+CONFIG_LEDS_TRIGGER_PANIC=y -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_ABX80X=m -+CONFIG_RTC_DRV_DS1307=m -+CONFIG_RTC_DRV_DS1374=m -+CONFIG_RTC_DRV_DS1672=m -+CONFIG_RTC_DRV_MAX6900=m -+CONFIG_RTC_DRV_RS5C372=m -+CONFIG_RTC_DRV_ISL1208=m -+CONFIG_RTC_DRV_ISL12022=m -+CONFIG_RTC_DRV_X1205=m -+CONFIG_RTC_DRV_PCF8523=m -+CONFIG_RTC_DRV_PCF8563=m -+CONFIG_RTC_DRV_PCF8583=m -+CONFIG_RTC_DRV_M41T80=m -+CONFIG_RTC_DRV_BQ32K=m -+CONFIG_RTC_DRV_S35390A=m -+CONFIG_RTC_DRV_FM3130=m -+CONFIG_RTC_DRV_RX8581=m -+CONFIG_RTC_DRV_RX8025=m -+CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_M41T93=m -+CONFIG_RTC_DRV_M41T94=m -+CONFIG_RTC_DRV_DS1302=m -+CONFIG_RTC_DRV_DS1305=m -+CONFIG_RTC_DRV_DS1390=m -+CONFIG_RTC_DRV_R9701=m -+CONFIG_RTC_DRV_RX4581=m -+CONFIG_RTC_DRV_RS5C348=m -+CONFIG_RTC_DRV_MAX6902=m -+CONFIG_RTC_DRV_PCF2123=m -+CONFIG_RTC_DRV_DS3232=m -+CONFIG_RTC_DRV_PCF2127=m -+CONFIG_RTC_DRV_RV3029C2=m -+CONFIG_DMADEVICES=y -+CONFIG_DMA_BCM2835=y -+CONFIG_DMA_BCM2708=y -+CONFIG_UIO=m -+CONFIG_UIO_PDRV_GENIRQ=m -+CONFIG_STAGING=y -+CONFIG_PRISM2_USB=m -+CONFIG_R8712U=m -+CONFIG_R8188EU=m -+CONFIG_VT6656=m -+CONFIG_SPEAKUP=m -+CONFIG_SPEAKUP_SYNTH_SOFT=m -+CONFIG_STAGING_MEDIA=y -+CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_IMON=m -+CONFIG_LIRC_RPI=m -+CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SERIAL=m -+CONFIG_FB_TFT=m -+CONFIG_FB_TFT_AGM1264K_FL=m -+CONFIG_FB_TFT_BD663474=m -+CONFIG_FB_TFT_HX8340BN=m -+CONFIG_FB_TFT_HX8347D=m -+CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_HX8357D=m -+CONFIG_FB_TFT_ILI9163=m -+CONFIG_FB_TFT_ILI9320=m -+CONFIG_FB_TFT_ILI9325=m -+CONFIG_FB_TFT_ILI9340=m -+CONFIG_FB_TFT_ILI9341=m -+CONFIG_FB_TFT_ILI9481=m -+CONFIG_FB_TFT_ILI9486=m -+CONFIG_FB_TFT_PCD8544=m -+CONFIG_FB_TFT_RA8875=m -+CONFIG_FB_TFT_S6D02A1=m -+CONFIG_FB_TFT_S6D1121=m -+CONFIG_FB_TFT_SSD1289=m -+CONFIG_FB_TFT_SSD1306=m -+CONFIG_FB_TFT_SSD1331=m -+CONFIG_FB_TFT_SSD1351=m -+CONFIG_FB_TFT_ST7735R=m -+CONFIG_FB_TFT_TINYLCD=m -+CONFIG_FB_TFT_TLS8204=m -+CONFIG_FB_TFT_UC1701=m -+CONFIG_FB_TFT_UPD161704=m -+CONFIG_FB_TFT_WATTEROTT=m -+CONFIG_FB_FLEX=m -+CONFIG_FB_TFT_FBTFT_DEVICE=m -+CONFIG_MAILBOX=y -+CONFIG_BCM2835_MBOX=y -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_RASPBERRYPI_POWER=y -+CONFIG_EXTCON=m -+CONFIG_EXTCON_ARIZONA=m -+CONFIG_IIO=m -+CONFIG_IIO_BUFFER=y -+CONFIG_IIO_BUFFER_CB=m -+CONFIG_IIO_KFIFO_BUF=m -+CONFIG_MCP320X=m -+CONFIG_MCP3422=m -+CONFIG_DHT11=m -+CONFIG_HTU21=m -+CONFIG_PWM_BCM2835=m -+CONFIG_PWM_PCA9685=m -+CONFIG_RASPBERRYPI_FIRMWARE=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_REISERFS_FS=m -+CONFIG_REISERFS_FS_XATTR=y -+CONFIG_REISERFS_FS_POSIX_ACL=y -+CONFIG_REISERFS_FS_SECURITY=y -+CONFIG_JFS_FS=m -+CONFIG_JFS_POSIX_ACL=y -+CONFIG_JFS_SECURITY=y -+CONFIG_JFS_STATISTICS=y -+CONFIG_XFS_FS=m -+CONFIG_XFS_QUOTA=y -+CONFIG_XFS_POSIX_ACL=y -+CONFIG_XFS_RT=y -+CONFIG_GFS2_FS=m -+CONFIG_OCFS2_FS=m -+CONFIG_BTRFS_FS=m -+CONFIG_BTRFS_FS_POSIX_ACL=y -+CONFIG_NILFS2_FS=m -+CONFIG_F2FS_FS=y -+CONFIG_FANOTIFY=y -+CONFIG_QFMT_V1=m -+CONFIG_QFMT_V2=m -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=m -+CONFIG_CUSE=m -+CONFIG_OVERLAY_FS=m -+CONFIG_FSCACHE=y -+CONFIG_FSCACHE_STATS=y -+CONFIG_FSCACHE_HISTOGRAM=y -+CONFIG_CACHEFILES=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -+CONFIG_NTFS_FS=m -+CONFIG_NTFS_RW=y -+CONFIG_TMPFS=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_ECRYPT_FS=m -+CONFIG_HFS_FS=m -+CONFIG_HFSPLUS_FS=m -+CONFIG_JFFS2_FS=m -+CONFIG_JFFS2_SUMMARY=y -+CONFIG_UBIFS_FS=m -+CONFIG_SQUASHFS=m -+CONFIG_SQUASHFS_XATTR=y -+CONFIG_SQUASHFS_LZO=y -+CONFIG_SQUASHFS_XZ=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_NFS_SWAP=y -+CONFIG_ROOT_NFS=y -+CONFIG_NFS_FSCACHE=y -+CONFIG_NFSD=m -+CONFIG_NFSD_V3_ACL=y -+CONFIG_NFSD_V4=y -+CONFIG_CIFS=m -+CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y -+CONFIG_CIFS_XATTR=y -+CONFIG_CIFS_POSIX=y -+CONFIG_CIFS_ACL=y -+CONFIG_CIFS_DFS_UPCALL=y -+CONFIG_CIFS_SMB2=y -+CONFIG_CIFS_FSCACHE=y -+CONFIG_9P_FS=m -+CONFIG_9P_FS_POSIX_ACL=y -+CONFIG_NLS_DEFAULT="utf8" -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_737=m -+CONFIG_NLS_CODEPAGE_775=m -+CONFIG_NLS_CODEPAGE_850=m -+CONFIG_NLS_CODEPAGE_852=m -+CONFIG_NLS_CODEPAGE_855=m -+CONFIG_NLS_CODEPAGE_857=m -+CONFIG_NLS_CODEPAGE_860=m -+CONFIG_NLS_CODEPAGE_861=m -+CONFIG_NLS_CODEPAGE_862=m -+CONFIG_NLS_CODEPAGE_863=m -+CONFIG_NLS_CODEPAGE_864=m -+CONFIG_NLS_CODEPAGE_865=m -+CONFIG_NLS_CODEPAGE_866=m -+CONFIG_NLS_CODEPAGE_869=m -+CONFIG_NLS_CODEPAGE_936=m -+CONFIG_NLS_CODEPAGE_950=m -+CONFIG_NLS_CODEPAGE_932=m -+CONFIG_NLS_CODEPAGE_949=m -+CONFIG_NLS_CODEPAGE_874=m -+CONFIG_NLS_ISO8859_8=m -+CONFIG_NLS_CODEPAGE_1250=m -+CONFIG_NLS_CODEPAGE_1251=m -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=m -+CONFIG_NLS_ISO8859_2=m -+CONFIG_NLS_ISO8859_3=m -+CONFIG_NLS_ISO8859_4=m -+CONFIG_NLS_ISO8859_5=m -+CONFIG_NLS_ISO8859_6=m -+CONFIG_NLS_ISO8859_7=m -+CONFIG_NLS_ISO8859_9=m -+CONFIG_NLS_ISO8859_13=m -+CONFIG_NLS_ISO8859_14=m -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_KOI8_R=m -+CONFIG_NLS_KOI8_U=m -+CONFIG_DLM=m -+CONFIG_PRINTK_TIME=y -+CONFIG_BOOT_PRINTK_DELAY=y -+CONFIG_DEBUG_MEMORY_INIT=y -+CONFIG_DETECT_HUNG_TASK=y -+CONFIG_TIMER_STATS=y -+CONFIG_LATENCYTOP=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+# CONFIG_KPROBE_EVENT is not set -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_KGDB=y -+CONFIG_KGDB_KDB=y -+CONFIG_KDB_KEYBOARD=y -+CONFIG_CRYPTO_USER=m -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=m -+CONFIG_CRYPTO_XTS=m -+CONFIG_CRYPTO_XCBC=m -+CONFIG_CRYPTO_TGR192=m -+CONFIG_CRYPTO_WP512=m -+CONFIG_CRYPTO_CAST5=m -+CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_USER_API_SKCIPHER=m -+# CONFIG_CRYPTO_HW is not set -+CONFIG_ARM_CRYPTO=y -+CONFIG_CRYPTO_SHA1_ARM_NEON=m -+CONFIG_CRYPTO_AES_ARM_BS=m -+CONFIG_CRC_ITU_T=y -+CONFIG_LIBCRC32C=y ---- /dev/null -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -0,0 +1,1308 @@ -+# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_SYSVIPC=y -+CONFIG_POSIX_MQUEUE=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_BSD_PROCESS_ACCT_V3=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_IKCONFIG=m -+CONFIG_IKCONFIG_PROC=y -+CONFIG_NMI_LOG_BUF_SHIFT=12 -+CONFIG_MEMCG=y -+CONFIG_BLK_CGROUP=y -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CPUSETS=y -+CONFIG_CGROUP_DEVICE=y -+CONFIG_CGROUP_CPUACCT=y -+CONFIG_NAMESPACES=y -+CONFIG_USER_NS=y -+CONFIG_SCHED_AUTOGROUP=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_EMBEDDED=y -+# CONFIG_COMPAT_BRK is not set -+CONFIG_PROFILING=y -+CONFIG_OPROFILE=m -+CONFIG_KPROBES=y -+CONFIG_JUMP_LABEL=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+CONFIG_BLK_DEV_THROTTLING=y -+CONFIG_PARTITION_ADVANCED=y -+CONFIG_MAC_PARTITION=y -+CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_ARCH_MULTI_V6=y -+# CONFIG_ARCH_MULTI_V7 is not set -+CONFIG_ARCH_BCM=y -+CONFIG_ARCH_BCM2835=y -+# CONFIG_CACHE_L2X0 is not set -+CONFIG_PREEMPT_VOLUNTARY=y -+CONFIG_AEABI=y -+# CONFIG_CPU_SW_DOMAIN_PAN is not set -+CONFIG_CLEANCACHE=y -+CONFIG_FRONTSWAP=y -+CONFIG_CMA=y -+CONFIG_ZSMALLOC=m -+CONFIG_PGTABLE_MAPPING=y -+CONFIG_UACCESS_WITH_MEMCPY=y -+CONFIG_SECCOMP=y -+# CONFIG_ATAGS is not set -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+CONFIG_ZBOOT_ROM_BSS=0x0 -+CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_STAT=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_VFP=y -+CONFIG_BINFMT_MISC=m -+# CONFIG_SUSPEND is not set -+CONFIG_PM=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_NET_KEY=m -+CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_MULTIPATH=y -+CONFIG_IP_ROUTE_VERBOSE=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+CONFIG_IP_PNP_RARP=y -+CONFIG_NET_IPIP=m -+CONFIG_NET_IPGRE_DEMUX=m -+CONFIG_NET_IPGRE=m -+CONFIG_IP_MROUTE=y -+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IP_PIMSM_V1=y -+CONFIG_IP_PIMSM_V2=y -+CONFIG_SYN_COOKIES=y -+CONFIG_INET_AH=m -+CONFIG_INET_ESP=m -+CONFIG_INET_IPCOMP=m -+CONFIG_INET_XFRM_MODE_TRANSPORT=m -+CONFIG_INET_XFRM_MODE_TUNNEL=m -+CONFIG_INET_XFRM_MODE_BEET=m -+CONFIG_INET_DIAG=m -+CONFIG_IPV6=m -+CONFIG_IPV6_ROUTER_PREF=y -+CONFIG_INET6_AH=m -+CONFIG_INET6_ESP=m -+CONFIG_INET6_IPCOMP=m -+CONFIG_IPV6_TUNNEL=m -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_IPV6_SUBTREES=y -+CONFIG_IPV6_MROUTE=y -+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IPV6_PIMSM_V2=y -+CONFIG_NETFILTER=y -+CONFIG_NF_CONNTRACK=m -+CONFIG_NF_CONNTRACK_ZONES=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_TIMESTAMP=y -+CONFIG_NF_CT_PROTO_DCCP=m -+CONFIG_NF_CT_PROTO_UDPLITE=m -+CONFIG_NF_CONNTRACK_AMANDA=m -+CONFIG_NF_CONNTRACK_FTP=m -+CONFIG_NF_CONNTRACK_H323=m -+CONFIG_NF_CONNTRACK_IRC=m -+CONFIG_NF_CONNTRACK_NETBIOS_NS=m -+CONFIG_NF_CONNTRACK_SNMP=m -+CONFIG_NF_CONNTRACK_PPTP=m -+CONFIG_NF_CONNTRACK_SANE=m -+CONFIG_NF_CONNTRACK_SIP=m -+CONFIG_NF_CONNTRACK_TFTP=m -+CONFIG_NF_CT_NETLINK=m -+CONFIG_NETFILTER_XT_SET=m -+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -+CONFIG_NETFILTER_XT_TARGET_DSCP=m -+CONFIG_NETFILTER_XT_TARGET_HMARK=m -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -+CONFIG_NETFILTER_XT_TARGET_LED=m -+CONFIG_NETFILTER_XT_TARGET_LOG=m -+CONFIG_NETFILTER_XT_TARGET_MARK=m -+CONFIG_NETFILTER_XT_TARGET_NFLOG=m -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -+CONFIG_NETFILTER_XT_TARGET_TEE=m -+CONFIG_NETFILTER_XT_TARGET_TPROXY=m -+CONFIG_NETFILTER_XT_TARGET_TRACE=m -+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m -+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -+CONFIG_NETFILTER_XT_MATCH_BPF=m -+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -+CONFIG_NETFILTER_XT_MATCH_COMMENT=m -+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m -+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -+CONFIG_NETFILTER_XT_MATCH_CPU=m -+CONFIG_NETFILTER_XT_MATCH_DCCP=m -+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -+CONFIG_NETFILTER_XT_MATCH_DSCP=m -+CONFIG_NETFILTER_XT_MATCH_ESP=m -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_HELPER=m -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -+CONFIG_NETFILTER_XT_MATCH_IPVS=m -+CONFIG_NETFILTER_XT_MATCH_LENGTH=m -+CONFIG_NETFILTER_XT_MATCH_LIMIT=m -+CONFIG_NETFILTER_XT_MATCH_MAC=m -+CONFIG_NETFILTER_XT_MATCH_MARK=m -+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -+CONFIG_NETFILTER_XT_MATCH_NFACCT=m -+CONFIG_NETFILTER_XT_MATCH_OSF=m -+CONFIG_NETFILTER_XT_MATCH_OWNER=m -+CONFIG_NETFILTER_XT_MATCH_POLICY=m -+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -+CONFIG_NETFILTER_XT_MATCH_QUOTA=m -+CONFIG_NETFILTER_XT_MATCH_RATEEST=m -+CONFIG_NETFILTER_XT_MATCH_REALM=m -+CONFIG_NETFILTER_XT_MATCH_RECENT=m -+CONFIG_NETFILTER_XT_MATCH_SOCKET=m -+CONFIG_NETFILTER_XT_MATCH_STATE=m -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -+CONFIG_NETFILTER_XT_MATCH_STRING=m -+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -+CONFIG_NETFILTER_XT_MATCH_TIME=m -+CONFIG_NETFILTER_XT_MATCH_U32=m -+CONFIG_IP_SET=m -+CONFIG_IP_SET_BITMAP_IP=m -+CONFIG_IP_SET_BITMAP_IPMAC=m -+CONFIG_IP_SET_BITMAP_PORT=m -+CONFIG_IP_SET_HASH_IP=m -+CONFIG_IP_SET_HASH_IPPORT=m -+CONFIG_IP_SET_HASH_IPPORTIP=m -+CONFIG_IP_SET_HASH_IPPORTNET=m -+CONFIG_IP_SET_HASH_NET=m -+CONFIG_IP_SET_HASH_NETPORT=m -+CONFIG_IP_SET_HASH_NETIFACE=m -+CONFIG_IP_SET_LIST_SET=m -+CONFIG_IP_VS=m -+CONFIG_IP_VS_PROTO_TCP=y -+CONFIG_IP_VS_PROTO_UDP=y -+CONFIG_IP_VS_PROTO_ESP=y -+CONFIG_IP_VS_PROTO_AH=y -+CONFIG_IP_VS_PROTO_SCTP=y -+CONFIG_IP_VS_RR=m -+CONFIG_IP_VS_WRR=m -+CONFIG_IP_VS_LC=m -+CONFIG_IP_VS_WLC=m -+CONFIG_IP_VS_LBLC=m -+CONFIG_IP_VS_LBLCR=m -+CONFIG_IP_VS_DH=m -+CONFIG_IP_VS_SH=m -+CONFIG_IP_VS_SED=m -+CONFIG_IP_VS_NQ=m -+CONFIG_IP_VS_FTP=m -+CONFIG_IP_VS_PE_SIP=m -+CONFIG_NF_CONNTRACK_IPV4=m -+CONFIG_IP_NF_IPTABLES=m -+CONFIG_IP_NF_MATCH_AH=m -+CONFIG_IP_NF_MATCH_ECN=m -+CONFIG_IP_NF_MATCH_RPFILTER=m -+CONFIG_IP_NF_MATCH_TTL=m -+CONFIG_IP_NF_FILTER=m -+CONFIG_IP_NF_TARGET_REJECT=m -+CONFIG_IP_NF_NAT=m -+CONFIG_IP_NF_TARGET_MASQUERADE=m -+CONFIG_IP_NF_TARGET_NETMAP=m -+CONFIG_IP_NF_TARGET_REDIRECT=m -+CONFIG_IP_NF_MANGLE=m -+CONFIG_IP_NF_TARGET_CLUSTERIP=m -+CONFIG_IP_NF_TARGET_ECN=m -+CONFIG_IP_NF_TARGET_TTL=m -+CONFIG_IP_NF_RAW=m -+CONFIG_IP_NF_ARPTABLES=m -+CONFIG_IP_NF_ARPFILTER=m -+CONFIG_IP_NF_ARP_MANGLE=m -+CONFIG_NF_CONNTRACK_IPV6=m -+CONFIG_IP6_NF_IPTABLES=m -+CONFIG_IP6_NF_MATCH_AH=m -+CONFIG_IP6_NF_MATCH_EUI64=m -+CONFIG_IP6_NF_MATCH_FRAG=m -+CONFIG_IP6_NF_MATCH_OPTS=m -+CONFIG_IP6_NF_MATCH_HL=m -+CONFIG_IP6_NF_MATCH_IPV6HEADER=m -+CONFIG_IP6_NF_MATCH_MH=m -+CONFIG_IP6_NF_MATCH_RPFILTER=m -+CONFIG_IP6_NF_MATCH_RT=m -+CONFIG_IP6_NF_TARGET_HL=m -+CONFIG_IP6_NF_FILTER=m -+CONFIG_IP6_NF_TARGET_REJECT=m -+CONFIG_IP6_NF_MANGLE=m -+CONFIG_IP6_NF_RAW=m -+CONFIG_IP6_NF_NAT=m -+CONFIG_IP6_NF_TARGET_MASQUERADE=m -+CONFIG_IP6_NF_TARGET_NPT=m -+CONFIG_BRIDGE_NF_EBTABLES=m -+CONFIG_BRIDGE_EBT_BROUTE=m -+CONFIG_BRIDGE_EBT_T_FILTER=m -+CONFIG_BRIDGE_EBT_T_NAT=m -+CONFIG_BRIDGE_EBT_802_3=m -+CONFIG_BRIDGE_EBT_AMONG=m -+CONFIG_BRIDGE_EBT_ARP=m -+CONFIG_BRIDGE_EBT_IP=m -+CONFIG_BRIDGE_EBT_IP6=m -+CONFIG_BRIDGE_EBT_LIMIT=m -+CONFIG_BRIDGE_EBT_MARK=m -+CONFIG_BRIDGE_EBT_PKTTYPE=m -+CONFIG_BRIDGE_EBT_STP=m -+CONFIG_BRIDGE_EBT_VLAN=m -+CONFIG_BRIDGE_EBT_ARPREPLY=m -+CONFIG_BRIDGE_EBT_DNAT=m -+CONFIG_BRIDGE_EBT_MARK_T=m -+CONFIG_BRIDGE_EBT_REDIRECT=m -+CONFIG_BRIDGE_EBT_SNAT=m -+CONFIG_BRIDGE_EBT_LOG=m -+CONFIG_BRIDGE_EBT_NFLOG=m -+CONFIG_SCTP_COOKIE_HMAC_SHA1=y -+CONFIG_ATM=m -+CONFIG_L2TP=m -+CONFIG_L2TP_V3=y -+CONFIG_L2TP_IP=m -+CONFIG_L2TP_ETH=m -+CONFIG_BRIDGE=m -+CONFIG_VLAN_8021Q=m -+CONFIG_VLAN_8021Q_GVRP=y -+CONFIG_ATALK=m -+CONFIG_6LOWPAN=m -+CONFIG_IEEE802154=m -+CONFIG_IEEE802154_6LOWPAN=m -+CONFIG_MAC802154=m -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_CBQ=m -+CONFIG_NET_SCH_HTB=m -+CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_PRIO=m -+CONFIG_NET_SCH_MULTIQ=m -+CONFIG_NET_SCH_RED=m -+CONFIG_NET_SCH_SFB=m -+CONFIG_NET_SCH_SFQ=m -+CONFIG_NET_SCH_TEQL=m -+CONFIG_NET_SCH_TBF=m -+CONFIG_NET_SCH_GRED=m -+CONFIG_NET_SCH_DSMARK=m -+CONFIG_NET_SCH_NETEM=m -+CONFIG_NET_SCH_DRR=m -+CONFIG_NET_SCH_MQPRIO=m -+CONFIG_NET_SCH_CHOKE=m -+CONFIG_NET_SCH_QFQ=m -+CONFIG_NET_SCH_CODEL=m -+CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_INGRESS=m -+CONFIG_NET_SCH_PLUG=m -+CONFIG_NET_CLS_BASIC=m -+CONFIG_NET_CLS_TCINDEX=m -+CONFIG_NET_CLS_ROUTE4=m -+CONFIG_NET_CLS_FW=m -+CONFIG_NET_CLS_U32=m -+CONFIG_CLS_U32_MARK=y -+CONFIG_NET_CLS_RSVP=m -+CONFIG_NET_CLS_RSVP6=m -+CONFIG_NET_CLS_FLOW=m -+CONFIG_NET_CLS_CGROUP=m -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_CMP=m -+CONFIG_NET_EMATCH_NBYTE=m -+CONFIG_NET_EMATCH_U32=m -+CONFIG_NET_EMATCH_META=m -+CONFIG_NET_EMATCH_TEXT=m -+CONFIG_NET_EMATCH_IPSET=m -+CONFIG_NET_CLS_ACT=y -+CONFIG_NET_ACT_POLICE=m -+CONFIG_NET_ACT_GACT=m -+CONFIG_GACT_PROB=y -+CONFIG_NET_ACT_MIRRED=m -+CONFIG_NET_ACT_IPT=m -+CONFIG_NET_ACT_NAT=m -+CONFIG_NET_ACT_PEDIT=m -+CONFIG_NET_ACT_SIMP=m -+CONFIG_NET_ACT_SKBEDIT=m -+CONFIG_NET_ACT_CSUM=m -+CONFIG_BATMAN_ADV=m -+CONFIG_OPENVSWITCH=m -+CONFIG_NET_PKTGEN=m -+CONFIG_HAMRADIO=y -+CONFIG_AX25=m -+CONFIG_NETROM=m -+CONFIG_ROSE=m -+CONFIG_MKISS=m -+CONFIG_6PACK=m -+CONFIG_BPQETHER=m -+CONFIG_BAYCOM_SER_FDX=m -+CONFIG_BAYCOM_SER_HDX=m -+CONFIG_YAM=m -+CONFIG_CAN=m -+CONFIG_CAN_VCAN=m -+CONFIG_CAN_MCP251X=m -+CONFIG_IRDA=m -+CONFIG_IRLAN=m -+CONFIG_IRNET=m -+CONFIG_IRCOMM=m -+CONFIG_IRDA_ULTRA=y -+CONFIG_IRDA_CACHE_LAST_LSAP=y -+CONFIG_IRDA_FAST_RR=y -+CONFIG_IRTTY_SIR=m -+CONFIG_KINGSUN_DONGLE=m -+CONFIG_KSDAZZLE_DONGLE=m -+CONFIG_KS959_DONGLE=m -+CONFIG_USB_IRDA=m -+CONFIG_SIGMATEL_FIR=m -+CONFIG_MCS_FIR=m -+CONFIG_BT=m -+CONFIG_BT_RFCOMM=m -+CONFIG_BT_RFCOMM_TTY=y -+CONFIG_BT_BNEP=m -+CONFIG_BT_BNEP_MC_FILTER=y -+CONFIG_BT_BNEP_PROTO_FILTER=y -+CONFIG_BT_HIDP=m -+CONFIG_BT_6LOWPAN=m -+CONFIG_BT_HCIBTUSB=m -+CONFIG_BT_HCIUART=m -+CONFIG_BT_HCIUART_3WIRE=y -+CONFIG_BT_HCIUART_BCM=y -+CONFIG_BT_HCIBCM203X=m -+CONFIG_BT_HCIBPA10X=m -+CONFIG_BT_HCIBFUSB=m -+CONFIG_BT_HCIVHCI=m -+CONFIG_BT_MRVL=m -+CONFIG_BT_MRVL_SDIO=m -+CONFIG_BT_ATH3K=m -+CONFIG_BT_WILINK=m -+CONFIG_CFG80211=m -+CONFIG_MAC80211=m -+CONFIG_MAC80211_MESH=y -+CONFIG_WIMAX=m -+CONFIG_RFKILL=m -+CONFIG_RFKILL_INPUT=y -+CONFIG_NET_9P=m -+CONFIG_NFC=m -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+CONFIG_DMA_CMA=y -+CONFIG_CMA_SIZE_MBYTES=5 -+CONFIG_MTD=m -+CONFIG_MTD_BLOCK=m -+CONFIG_MTD_NAND=m -+CONFIG_MTD_UBI=m -+CONFIG_OF_CONFIGFS=y -+CONFIG_ZRAM=m -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_CRYPTOLOOP=m -+CONFIG_BLK_DEV_DRBD=m -+CONFIG_BLK_DEV_NBD=m -+CONFIG_BLK_DEV_RAM=y -+CONFIG_CDROM_PKTCDVD=m -+CONFIG_ATA_OVER_ETH=m -+CONFIG_EEPROM_AT24=m -+CONFIG_TI_ST=m -+CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_CHR_DEV_ST=m -+CONFIG_CHR_DEV_OSST=m -+CONFIG_BLK_DEV_SR=m -+CONFIG_CHR_DEV_SG=m -+CONFIG_SCSI_ISCSI_ATTRS=y -+CONFIG_ISCSI_TCP=m -+CONFIG_ISCSI_BOOT_SYSFS=m -+CONFIG_MD=y -+CONFIG_MD_LINEAR=m -+CONFIG_MD_RAID0=m -+CONFIG_BLK_DEV_DM=m -+CONFIG_DM_CRYPT=m -+CONFIG_DM_SNAPSHOT=m -+CONFIG_DM_THIN_PROVISIONING=m -+CONFIG_DM_MIRROR=m -+CONFIG_DM_LOG_USERSPACE=m -+CONFIG_DM_RAID=m -+CONFIG_DM_ZERO=m -+CONFIG_DM_DELAY=m -+CONFIG_NETDEVICES=y -+CONFIG_BONDING=m -+CONFIG_DUMMY=m -+CONFIG_IFB=m -+CONFIG_MACVLAN=m -+CONFIG_VXLAN=m -+CONFIG_NETCONSOLE=m -+CONFIG_TUN=m -+CONFIG_VETH=m -+CONFIG_ENC28J60=m -+CONFIG_QCA7000=m -+CONFIG_MDIO_BITBANG=m -+CONFIG_PPP=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_FILTER=y -+CONFIG_PPP_MPPE=m -+CONFIG_PPP_MULTILINK=y -+CONFIG_PPPOATM=m -+CONFIG_PPPOE=m -+CONFIG_PPPOL2TP=m -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_SLIP_SMART=y -+CONFIG_USB_CATC=m -+CONFIG_USB_KAWETH=m -+CONFIG_USB_PEGASUS=m -+CONFIG_USB_RTL8150=m -+CONFIG_USB_RTL8152=m -+CONFIG_USB_USBNET=y -+CONFIG_USB_NET_AX8817X=m -+CONFIG_USB_NET_AX88179_178A=m -+CONFIG_USB_NET_CDCETHER=m -+CONFIG_USB_NET_CDC_EEM=m -+CONFIG_USB_NET_CDC_NCM=m -+CONFIG_USB_NET_HUAWEI_CDC_NCM=m -+CONFIG_USB_NET_CDC_MBIM=m -+CONFIG_USB_NET_DM9601=m -+CONFIG_USB_NET_SR9700=m -+CONFIG_USB_NET_SR9800=m -+CONFIG_USB_NET_SMSC75XX=m -+CONFIG_USB_NET_SMSC95XX=y -+CONFIG_USB_NET_GL620A=m -+CONFIG_USB_NET_NET1080=m -+CONFIG_USB_NET_PLUSB=m -+CONFIG_USB_NET_MCS7830=m -+CONFIG_USB_NET_CDC_SUBSET=m -+CONFIG_USB_ALI_M5632=y -+CONFIG_USB_AN2720=y -+CONFIG_USB_EPSON2888=y -+CONFIG_USB_KC2190=y -+CONFIG_USB_NET_ZAURUS=m -+CONFIG_USB_NET_CX82310_ETH=m -+CONFIG_USB_NET_KALMIA=m -+CONFIG_USB_NET_QMI_WWAN=m -+CONFIG_USB_HSO=m -+CONFIG_USB_NET_INT51X1=m -+CONFIG_USB_IPHETH=m -+CONFIG_USB_SIERRA_NET=m -+CONFIG_USB_VL600=m -+CONFIG_ATH9K=m -+CONFIG_ATH9K_HTC=m -+CONFIG_CARL9170=m -+CONFIG_ATH6KL=m -+CONFIG_ATH6KL_USB=m -+CONFIG_AR5523=m -+CONFIG_AT76C50X_USB=m -+CONFIG_B43=m -+# CONFIG_B43_PHY_N is not set -+CONFIG_B43LEGACY=m -+CONFIG_BRCMFMAC=m -+CONFIG_BRCMFMAC_USB=y -+CONFIG_HOSTAP=m -+CONFIG_P54_COMMON=m -+CONFIG_P54_USB=m -+CONFIG_LIBERTAS=m -+CONFIG_LIBERTAS_USB=m -+CONFIG_LIBERTAS_SDIO=m -+CONFIG_LIBERTAS_THINFIRM=m -+CONFIG_LIBERTAS_THINFIRM_USB=m -+CONFIG_MWIFIEX=m -+CONFIG_MWIFIEX_SDIO=m -+CONFIG_MT7601U=m -+CONFIG_RT2X00=m -+CONFIG_RT2500USB=m -+CONFIG_RT73USB=m -+CONFIG_RT2800USB=m -+CONFIG_RT2800USB_RT3573=y -+CONFIG_RT2800USB_RT53XX=y -+CONFIG_RT2800USB_RT55XX=y -+CONFIG_RT2800USB_UNKNOWN=y -+CONFIG_RTL8187=m -+CONFIG_RTL8192CU=m -+CONFIG_USB_ZD1201=m -+CONFIG_ZD1211RW=m -+CONFIG_MAC80211_HWSIM=m -+CONFIG_USB_NET_RNDIS_WLAN=m -+CONFIG_WIMAX_I2400M_USB=m -+CONFIG_IEEE802154_AT86RF230=m -+CONFIG_IEEE802154_MRF24J40=m -+CONFIG_IEEE802154_CC2520=m -+CONFIG_INPUT_POLLDEV=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+CONFIG_INPUT_JOYDEV=m -+CONFIG_INPUT_EVDEV=m -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m -+# CONFIG_INPUT_MOUSE is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_JOYSTICK_IFORCE=m -+CONFIG_JOYSTICK_IFORCE_USB=y -+CONFIG_JOYSTICK_XPAD=m -+CONFIG_JOYSTICK_XPAD_FF=y -+CONFIG_JOYSTICK_XPAD_LEDS=y -+CONFIG_JOYSTICK_RPISENSE=m -+CONFIG_INPUT_TOUCHSCREEN=y -+CONFIG_TOUCHSCREEN_ADS7846=m -+CONFIG_TOUCHSCREEN_EGALAX=m -+CONFIG_TOUCHSCREEN_RPI_FT5406=m -+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -+CONFIG_TOUCHSCREEN_STMPE=m -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_AD714X=m -+CONFIG_INPUT_ATI_REMOTE2=m -+CONFIG_INPUT_KEYSPAN_REMOTE=m -+CONFIG_INPUT_POWERMATE=m -+CONFIG_INPUT_YEALINK=m -+CONFIG_INPUT_CM109=m -+CONFIG_INPUT_UINPUT=m -+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -+CONFIG_INPUT_ADXL34X=m -+CONFIG_INPUT_CMA3000=m -+CONFIG_SERIO=m -+CONFIG_SERIO_RAW=m -+CONFIG_GAMEPORT=m -+CONFIG_GAMEPORT_NS558=m -+CONFIG_GAMEPORT_L4=m -+CONFIG_BRCM_CHAR_DRIVERS=y -+CONFIG_BCM_VC_CMA=y -+CONFIG_BCM_VCIO=y -+CONFIG_BCM_VC_SM=y -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set -+CONFIG_SERIAL_8250=y -+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -+CONFIG_SERIAL_8250_CONSOLE=y -+# CONFIG_SERIAL_8250_DMA is not set -+CONFIG_SERIAL_8250_NR_UARTS=1 -+CONFIG_SERIAL_8250_RUNTIME_UARTS=0 -+CONFIG_SERIAL_8250_EXTENDED=y -+CONFIG_SERIAL_8250_SHARE_IRQ=y -+CONFIG_SERIAL_8250_BCM2835AUX=y -+CONFIG_SERIAL_OF_PLATFORM=y -+CONFIG_SERIAL_AMBA_PL011=y -+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -+CONFIG_SERIAL_SC16IS7XX=m -+CONFIG_SERIAL_SC16IS7XX_SPI=y -+CONFIG_TTY_PRINTK=y -+CONFIG_HW_RANDOM=y -+CONFIG_RAW_DRIVER=y -+CONFIG_I2C=y -+CONFIG_I2C_CHARDEV=m -+CONFIG_I2C_MUX_PCA954x=m -+CONFIG_I2C_BCM2708=m -+CONFIG_I2C_BCM2835=m -+CONFIG_I2C_GPIO=m -+CONFIG_SPI=y -+CONFIG_SPI_BCM2835=m -+CONFIG_SPI_BCM2835AUX=m -+CONFIG_SPI_SPIDEV=y -+CONFIG_PPS=m -+CONFIG_PPS_CLIENT_LDISC=m -+CONFIG_PPS_CLIENT_GPIO=m -+CONFIG_GPIO_SYSFS=y -+CONFIG_GPIO_ARIZONA=m -+CONFIG_GPIO_STMPE=y -+CONFIG_GPIO_MCP23S08=m -+CONFIG_W1=m -+CONFIG_W1_MASTER_DS2490=m -+CONFIG_W1_MASTER_DS2482=m -+CONFIG_W1_MASTER_DS1WM=m -+CONFIG_W1_MASTER_GPIO=m -+CONFIG_W1_SLAVE_THERM=m -+CONFIG_W1_SLAVE_SMEM=m -+CONFIG_W1_SLAVE_DS2408=m -+CONFIG_W1_SLAVE_DS2413=m -+CONFIG_W1_SLAVE_DS2406=m -+CONFIG_W1_SLAVE_DS2423=m -+CONFIG_W1_SLAVE_DS2431=m -+CONFIG_W1_SLAVE_DS2433=m -+CONFIG_W1_SLAVE_DS2760=m -+CONFIG_W1_SLAVE_DS2780=m -+CONFIG_W1_SLAVE_DS2781=m -+CONFIG_W1_SLAVE_DS28E04=m -+CONFIG_W1_SLAVE_BQ27000=m -+CONFIG_POWER_RESET=y -+CONFIG_POWER_RESET_GPIO=y -+CONFIG_BATTERY_DS2760=m -+CONFIG_HWMON=m -+CONFIG_SENSORS_LM75=m -+CONFIG_SENSORS_SHT21=m -+CONFIG_SENSORS_SHTC1=m -+CONFIG_SENSORS_INA2XX=m -+CONFIG_THERMAL=y -+CONFIG_THERMAL_BCM2835=y -+CONFIG_WATCHDOG=y -+CONFIG_BCM2835_WDT=y -+CONFIG_UCB1400_CORE=m -+CONFIG_MFD_STMPE=y -+CONFIG_STMPE_SPI=y -+CONFIG_MFD_ARIZONA_I2C=m -+CONFIG_MFD_ARIZONA_SPI=m -+CONFIG_MFD_WM5102=y -+CONFIG_MEDIA_SUPPORT=m -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y -+CONFIG_MEDIA_RADIO_SUPPORT=y -+CONFIG_MEDIA_RC_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y -+CONFIG_LIRC=m -+CONFIG_RC_DEVICES=y -+CONFIG_RC_ATI_REMOTE=m -+CONFIG_IR_IMON=m -+CONFIG_IR_MCEUSB=m -+CONFIG_IR_REDRAT3=m -+CONFIG_IR_STREAMZAP=m -+CONFIG_IR_IGUANA=m -+CONFIG_IR_TTUSBIR=m -+CONFIG_RC_LOOPBACK=m -+CONFIG_IR_GPIO_CIR=m -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_USB_M5602=m -+CONFIG_USB_STV06XX=m -+CONFIG_USB_GL860=m -+CONFIG_USB_GSPCA_BENQ=m -+CONFIG_USB_GSPCA_CONEX=m -+CONFIG_USB_GSPCA_CPIA1=m -+CONFIG_USB_GSPCA_DTCS033=m -+CONFIG_USB_GSPCA_ETOMS=m -+CONFIG_USB_GSPCA_FINEPIX=m -+CONFIG_USB_GSPCA_JEILINJ=m -+CONFIG_USB_GSPCA_JL2005BCD=m -+CONFIG_USB_GSPCA_KINECT=m -+CONFIG_USB_GSPCA_KONICA=m -+CONFIG_USB_GSPCA_MARS=m -+CONFIG_USB_GSPCA_MR97310A=m -+CONFIG_USB_GSPCA_NW80X=m -+CONFIG_USB_GSPCA_OV519=m -+CONFIG_USB_GSPCA_OV534=m -+CONFIG_USB_GSPCA_OV534_9=m -+CONFIG_USB_GSPCA_PAC207=m -+CONFIG_USB_GSPCA_PAC7302=m -+CONFIG_USB_GSPCA_PAC7311=m -+CONFIG_USB_GSPCA_SE401=m -+CONFIG_USB_GSPCA_SN9C2028=m -+CONFIG_USB_GSPCA_SN9C20X=m -+CONFIG_USB_GSPCA_SONIXB=m -+CONFIG_USB_GSPCA_SONIXJ=m -+CONFIG_USB_GSPCA_SPCA500=m -+CONFIG_USB_GSPCA_SPCA501=m -+CONFIG_USB_GSPCA_SPCA505=m -+CONFIG_USB_GSPCA_SPCA506=m -+CONFIG_USB_GSPCA_SPCA508=m -+CONFIG_USB_GSPCA_SPCA561=m -+CONFIG_USB_GSPCA_SPCA1528=m -+CONFIG_USB_GSPCA_SQ905=m -+CONFIG_USB_GSPCA_SQ905C=m -+CONFIG_USB_GSPCA_SQ930X=m -+CONFIG_USB_GSPCA_STK014=m -+CONFIG_USB_GSPCA_STK1135=m -+CONFIG_USB_GSPCA_STV0680=m -+CONFIG_USB_GSPCA_SUNPLUS=m -+CONFIG_USB_GSPCA_T613=m -+CONFIG_USB_GSPCA_TOPRO=m -+CONFIG_USB_GSPCA_TV8532=m -+CONFIG_USB_GSPCA_VC032X=m -+CONFIG_USB_GSPCA_VICAM=m -+CONFIG_USB_GSPCA_XIRLINK_CIT=m -+CONFIG_USB_GSPCA_ZC3XX=m -+CONFIG_USB_PWC=m -+CONFIG_VIDEO_CPIA2=m -+CONFIG_USB_ZR364XX=m -+CONFIG_USB_STKWEBCAM=m -+CONFIG_USB_S2255=m -+CONFIG_VIDEO_USBTV=m -+CONFIG_VIDEO_PVRUSB2=m -+CONFIG_VIDEO_HDPVR=m -+CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160_COMMON=m -+CONFIG_VIDEO_STK1160_AC97=y -+CONFIG_VIDEO_GO7007=m -+CONFIG_VIDEO_GO7007_USB=m -+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m -+CONFIG_VIDEO_AU0828=m -+CONFIG_VIDEO_AU0828_RC=y -+CONFIG_VIDEO_CX231XX=m -+CONFIG_VIDEO_CX231XX_ALSA=m -+CONFIG_VIDEO_CX231XX_DVB=m -+CONFIG_VIDEO_TM6000=m -+CONFIG_VIDEO_TM6000_ALSA=m -+CONFIG_VIDEO_TM6000_DVB=m -+CONFIG_DVB_USB=m -+CONFIG_DVB_USB_A800=m -+CONFIG_DVB_USB_DIBUSB_MB=m -+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y -+CONFIG_DVB_USB_DIBUSB_MC=m -+CONFIG_DVB_USB_DIB0700=m -+CONFIG_DVB_USB_UMT_010=m -+CONFIG_DVB_USB_CXUSB=m -+CONFIG_DVB_USB_M920X=m -+CONFIG_DVB_USB_DIGITV=m -+CONFIG_DVB_USB_VP7045=m -+CONFIG_DVB_USB_VP702X=m -+CONFIG_DVB_USB_GP8PSK=m -+CONFIG_DVB_USB_NOVA_T_USB2=m -+CONFIG_DVB_USB_TTUSB2=m -+CONFIG_DVB_USB_DTT200U=m -+CONFIG_DVB_USB_OPERA1=m -+CONFIG_DVB_USB_AF9005=m -+CONFIG_DVB_USB_AF9005_REMOTE=m -+CONFIG_DVB_USB_PCTV452E=m -+CONFIG_DVB_USB_DW2102=m -+CONFIG_DVB_USB_CINERGY_T2=m -+CONFIG_DVB_USB_DTV5100=m -+CONFIG_DVB_USB_FRIIO=m -+CONFIG_DVB_USB_AZ6027=m -+CONFIG_DVB_USB_TECHNISAT_USB2=m -+CONFIG_DVB_USB_V2=m -+CONFIG_DVB_USB_AF9015=m -+CONFIG_DVB_USB_AF9035=m -+CONFIG_DVB_USB_ANYSEE=m -+CONFIG_DVB_USB_AU6610=m -+CONFIG_DVB_USB_AZ6007=m -+CONFIG_DVB_USB_CE6230=m -+CONFIG_DVB_USB_EC168=m -+CONFIG_DVB_USB_GL861=m -+CONFIG_DVB_USB_LME2510=m -+CONFIG_DVB_USB_MXL111SF=m -+CONFIG_DVB_USB_RTL28XXU=m -+CONFIG_DVB_USB_DVBSKY=m -+CONFIG_SMS_USB_DRV=m -+CONFIG_DVB_B2C2_FLEXCOP_USB=m -+CONFIG_DVB_AS102=m -+CONFIG_VIDEO_EM28XX=m -+CONFIG_VIDEO_EM28XX_V4L2=m -+CONFIG_VIDEO_EM28XX_ALSA=m -+CONFIG_VIDEO_EM28XX_DVB=m -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_BCM2835=y -+CONFIG_VIDEO_BCM2835_MMAL=m -+CONFIG_RADIO_SI470X=y -+CONFIG_USB_SI470X=m -+CONFIG_I2C_SI470X=m -+CONFIG_RADIO_SI4713=m -+CONFIG_I2C_SI4713=m -+CONFIG_USB_MR800=m -+CONFIG_USB_DSBR=m -+CONFIG_RADIO_SHARK=m -+CONFIG_RADIO_SHARK2=m -+CONFIG_USB_KEENE=m -+CONFIG_USB_MA901=m -+CONFIG_RADIO_TEA5764=m -+CONFIG_RADIO_SAA7706H=m -+CONFIG_RADIO_TEF6862=m -+CONFIG_RADIO_WL1273=m -+CONFIG_RADIO_WL128X=m -+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -+CONFIG_VIDEO_UDA1342=m -+CONFIG_VIDEO_SONY_BTF_MPX=m -+CONFIG_VIDEO_TVP5150=m -+CONFIG_VIDEO_TW2804=m -+CONFIG_VIDEO_TW9903=m -+CONFIG_VIDEO_TW9906=m -+CONFIG_VIDEO_OV7640=m -+CONFIG_VIDEO_MT9V011=m -+CONFIG_DRM=m -+CONFIG_DRM_LOAD_EDID_FIRMWARE=y -+CONFIG_DRM_UDL=m -+CONFIG_DRM_VC4=m -+CONFIG_FB=y -+CONFIG_FB_BCM2708=y -+CONFIG_FB_UDL=m -+CONFIG_FB_SSD1307=m -+CONFIG_FB_RPISENSE=m -+# CONFIG_BACKLIGHT_GENERIC is not set -+CONFIG_BACKLIGHT_RPI=m -+CONFIG_BACKLIGHT_GPIO=m -+CONFIG_FRAMEBUFFER_CONSOLE=y -+CONFIG_LOGO=y -+# CONFIG_LOGO_LINUX_MONO is not set -+# CONFIG_LOGO_LINUX_VGA16 is not set -+CONFIG_SOUND=y -+CONFIG_SND=m -+CONFIG_SND_SEQUENCER=m -+CONFIG_SND_SEQ_DUMMY=m -+CONFIG_SND_MIXER_OSS=m -+CONFIG_SND_PCM_OSS=m -+CONFIG_SND_SEQUENCER_OSS=y -+CONFIG_SND_HRTIMER=m -+CONFIG_SND_DUMMY=m -+CONFIG_SND_ALOOP=m -+CONFIG_SND_VIRMIDI=m -+CONFIG_SND_MTPAV=m -+CONFIG_SND_SERIAL_U16550=m -+CONFIG_SND_MPU401=m -+CONFIG_SND_BCM2835=m -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_USB_UA101=m -+CONFIG_SND_USB_CAIAQ=m -+CONFIG_SND_USB_CAIAQ_INPUT=y -+CONFIG_SND_USB_6FIRE=m -+CONFIG_SND_SOC=m -+CONFIG_SND_BCM2835_SOC_I2S=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_DAC=m -+CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m -+CONFIG_SND_BCM2708_SOC_RASPIDAC3=m -+CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m -+CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m -+CONFIG_SND_DIGIDAC1_SOUNDCARD=m -+CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m -+CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_PISOUND=m -+CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_AK4554=m -+CONFIG_SND_SOC_WM8804_I2C=m -+CONFIG_SND_SIMPLE_CARD=m -+CONFIG_SOUND_PRIME=m -+CONFIG_HIDRAW=y -+CONFIG_UHID=m -+CONFIG_HID_A4TECH=m -+CONFIG_HID_ACRUX=m -+CONFIG_HID_APPLE=m -+CONFIG_HID_BELKIN=m -+CONFIG_HID_BETOP_FF=m -+CONFIG_HID_CHERRY=m -+CONFIG_HID_CHICONY=m -+CONFIG_HID_CYPRESS=m -+CONFIG_HID_DRAGONRISE=m -+CONFIG_HID_EMS_FF=m -+CONFIG_HID_ELECOM=m -+CONFIG_HID_ELO=m -+CONFIG_HID_EZKEY=m -+CONFIG_HID_GEMBIRD=m -+CONFIG_HID_HOLTEK=m -+CONFIG_HID_KEYTOUCH=m -+CONFIG_HID_KYE=m -+CONFIG_HID_UCLOGIC=m -+CONFIG_HID_WALTOP=m -+CONFIG_HID_GYRATION=m -+CONFIG_HID_TWINHAN=m -+CONFIG_HID_KENSINGTON=m -+CONFIG_HID_LCPOWER=m -+CONFIG_HID_LOGITECH=m -+CONFIG_HID_LOGITECH_DJ=m -+CONFIG_LOGITECH_FF=y -+CONFIG_LOGIRUMBLEPAD2_FF=y -+CONFIG_LOGIG940_FF=y -+CONFIG_HID_MAGICMOUSE=m -+CONFIG_HID_MICROSOFT=m -+CONFIG_HID_MONTEREY=m -+CONFIG_HID_MULTITOUCH=m -+CONFIG_HID_NTRIG=m -+CONFIG_HID_ORTEK=m -+CONFIG_HID_PANTHERLORD=m -+CONFIG_HID_PETALYNX=m -+CONFIG_HID_PICOLCD=m -+CONFIG_HID_ROCCAT=m -+CONFIG_HID_SAMSUNG=m -+CONFIG_HID_SONY=m -+CONFIG_HID_SPEEDLINK=m -+CONFIG_HID_SUNPLUS=m -+CONFIG_HID_GREENASIA=m -+CONFIG_HID_SMARTJOYPLUS=m -+CONFIG_HID_TOPSEED=m -+CONFIG_HID_THINGM=m -+CONFIG_HID_THRUSTMASTER=m -+CONFIG_HID_WACOM=m -+CONFIG_HID_WIIMOTE=m -+CONFIG_HID_XINMO=m -+CONFIG_HID_ZEROPLUS=m -+CONFIG_HID_ZYDACRON=m -+CONFIG_HID_PID=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB=y -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+CONFIG_USB_MON=m -+CONFIG_USB_DWCOTG=y -+CONFIG_USB_PRINTER=m -+CONFIG_USB_STORAGE=y -+CONFIG_USB_STORAGE_REALTEK=m -+CONFIG_USB_STORAGE_DATAFAB=m -+CONFIG_USB_STORAGE_FREECOM=m -+CONFIG_USB_STORAGE_ISD200=m -+CONFIG_USB_STORAGE_USBAT=m -+CONFIG_USB_STORAGE_SDDR09=m -+CONFIG_USB_STORAGE_SDDR55=m -+CONFIG_USB_STORAGE_JUMPSHOT=m -+CONFIG_USB_STORAGE_ALAUDA=m -+CONFIG_USB_STORAGE_ONETOUCH=m -+CONFIG_USB_STORAGE_KARMA=m -+CONFIG_USB_STORAGE_CYPRESS_ATACB=m -+CONFIG_USB_STORAGE_ENE_UB6250=m -+CONFIG_USB_MDC800=m -+CONFIG_USB_MICROTEK=m -+CONFIG_USBIP_CORE=m -+CONFIG_USBIP_VHCI_HCD=m -+CONFIG_USBIP_HOST=m -+CONFIG_USB_DWC2=m -+CONFIG_USB_SERIAL=m -+CONFIG_USB_SERIAL_GENERIC=y -+CONFIG_USB_SERIAL_AIRCABLE=m -+CONFIG_USB_SERIAL_ARK3116=m -+CONFIG_USB_SERIAL_BELKIN=m -+CONFIG_USB_SERIAL_CH341=m -+CONFIG_USB_SERIAL_WHITEHEAT=m -+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -+CONFIG_USB_SERIAL_CP210X=m -+CONFIG_USB_SERIAL_CYPRESS_M8=m -+CONFIG_USB_SERIAL_EMPEG=m -+CONFIG_USB_SERIAL_FTDI_SIO=m -+CONFIG_USB_SERIAL_VISOR=m -+CONFIG_USB_SERIAL_IPAQ=m -+CONFIG_USB_SERIAL_IR=m -+CONFIG_USB_SERIAL_EDGEPORT=m -+CONFIG_USB_SERIAL_EDGEPORT_TI=m -+CONFIG_USB_SERIAL_F81232=m -+CONFIG_USB_SERIAL_GARMIN=m -+CONFIG_USB_SERIAL_IPW=m -+CONFIG_USB_SERIAL_IUU=m -+CONFIG_USB_SERIAL_KEYSPAN_PDA=m -+CONFIG_USB_SERIAL_KEYSPAN=m -+CONFIG_USB_SERIAL_KLSI=m -+CONFIG_USB_SERIAL_KOBIL_SCT=m -+CONFIG_USB_SERIAL_MCT_U232=m -+CONFIG_USB_SERIAL_METRO=m -+CONFIG_USB_SERIAL_MOS7720=m -+CONFIG_USB_SERIAL_MOS7840=m -+CONFIG_USB_SERIAL_NAVMAN=m -+CONFIG_USB_SERIAL_PL2303=m -+CONFIG_USB_SERIAL_OTI6858=m -+CONFIG_USB_SERIAL_QCAUX=m -+CONFIG_USB_SERIAL_QUALCOMM=m -+CONFIG_USB_SERIAL_SPCP8X5=m -+CONFIG_USB_SERIAL_SAFE=m -+CONFIG_USB_SERIAL_SIERRAWIRELESS=m -+CONFIG_USB_SERIAL_SYMBOL=m -+CONFIG_USB_SERIAL_TI=m -+CONFIG_USB_SERIAL_CYBERJACK=m -+CONFIG_USB_SERIAL_XIRCOM=m -+CONFIG_USB_SERIAL_OPTION=m -+CONFIG_USB_SERIAL_OMNINET=m -+CONFIG_USB_SERIAL_OPTICON=m -+CONFIG_USB_SERIAL_XSENS_MT=m -+CONFIG_USB_SERIAL_WISHBONE=m -+CONFIG_USB_SERIAL_SSU100=m -+CONFIG_USB_SERIAL_QT2=m -+CONFIG_USB_SERIAL_DEBUG=m -+CONFIG_USB_EMI62=m -+CONFIG_USB_EMI26=m -+CONFIG_USB_ADUTUX=m -+CONFIG_USB_SEVSEG=m -+CONFIG_USB_RIO500=m -+CONFIG_USB_LEGOTOWER=m -+CONFIG_USB_LCD=m -+CONFIG_USB_CYPRESS_CY7C63=m -+CONFIG_USB_CYTHERM=m -+CONFIG_USB_IDMOUSE=m -+CONFIG_USB_FTDI_ELAN=m -+CONFIG_USB_APPLEDISPLAY=m -+CONFIG_USB_LD=m -+CONFIG_USB_TRANCEVIBRATOR=m -+CONFIG_USB_IOWARRIOR=m -+CONFIG_USB_TEST=m -+CONFIG_USB_ISIGHTFW=m -+CONFIG_USB_YUREX=m -+CONFIG_USB_ATM=m -+CONFIG_USB_SPEEDTOUCH=m -+CONFIG_USB_CXACRU=m -+CONFIG_USB_UEAGLEATM=m -+CONFIG_USB_XUSBATM=m -+CONFIG_USB_GADGET=m -+CONFIG_USB_ZERO=m -+CONFIG_USB_AUDIO=m -+CONFIG_USB_ETH=m -+CONFIG_USB_GADGETFS=m -+CONFIG_USB_MASS_STORAGE=m -+CONFIG_USB_G_SERIAL=m -+CONFIG_USB_MIDI_GADGET=m -+CONFIG_USB_G_PRINTER=m -+CONFIG_USB_CDC_COMPOSITE=m -+CONFIG_USB_G_ACM_MS=m -+CONFIG_USB_G_MULTI=m -+CONFIG_USB_G_HID=m -+CONFIG_USB_G_WEBCAM=m -+CONFIG_MMC=y -+CONFIG_MMC_BLOCK_MINORS=32 -+CONFIG_MMC_BCM2835=y -+CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SPI=m -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_GPIO=y -+CONFIG_LEDS_TRIGGER_TIMER=y -+CONFIG_LEDS_TRIGGER_ONESHOT=y -+CONFIG_LEDS_TRIGGER_HEARTBEAT=y -+CONFIG_LEDS_TRIGGER_BACKLIGHT=y -+CONFIG_LEDS_TRIGGER_CPU=y -+CONFIG_LEDS_TRIGGER_GPIO=y -+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -+CONFIG_LEDS_TRIGGER_TRANSIENT=m -+CONFIG_LEDS_TRIGGER_CAMERA=m -+CONFIG_LEDS_TRIGGER_INPUT=y -+CONFIG_LEDS_TRIGGER_PANIC=y -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_ABX80X=m -+CONFIG_RTC_DRV_DS1307=m -+CONFIG_RTC_DRV_DS1374=m -+CONFIG_RTC_DRV_DS1672=m -+CONFIG_RTC_DRV_MAX6900=m -+CONFIG_RTC_DRV_RS5C372=m -+CONFIG_RTC_DRV_ISL1208=m -+CONFIG_RTC_DRV_ISL12022=m -+CONFIG_RTC_DRV_X1205=m -+CONFIG_RTC_DRV_PCF8523=m -+CONFIG_RTC_DRV_PCF8563=m -+CONFIG_RTC_DRV_PCF8583=m -+CONFIG_RTC_DRV_M41T80=m -+CONFIG_RTC_DRV_BQ32K=m -+CONFIG_RTC_DRV_S35390A=m -+CONFIG_RTC_DRV_FM3130=m -+CONFIG_RTC_DRV_RX8581=m -+CONFIG_RTC_DRV_RX8025=m -+CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_M41T93=m -+CONFIG_RTC_DRV_M41T94=m -+CONFIG_RTC_DRV_DS1302=m -+CONFIG_RTC_DRV_DS1305=m -+CONFIG_RTC_DRV_DS1390=m -+CONFIG_RTC_DRV_R9701=m -+CONFIG_RTC_DRV_RX4581=m -+CONFIG_RTC_DRV_RS5C348=m -+CONFIG_RTC_DRV_MAX6902=m -+CONFIG_RTC_DRV_PCF2123=m -+CONFIG_RTC_DRV_DS3232=m -+CONFIG_RTC_DRV_PCF2127=m -+CONFIG_RTC_DRV_RV3029C2=m -+CONFIG_DMADEVICES=y -+CONFIG_DMA_BCM2835=y -+CONFIG_DMA_BCM2708=y -+CONFIG_UIO=m -+CONFIG_UIO_PDRV_GENIRQ=m -+CONFIG_STAGING=y -+CONFIG_PRISM2_USB=m -+CONFIG_R8712U=m -+CONFIG_R8188EU=m -+CONFIG_VT6656=m -+CONFIG_SPEAKUP=m -+CONFIG_SPEAKUP_SYNTH_SOFT=m -+CONFIG_STAGING_MEDIA=y -+CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_IMON=m -+CONFIG_LIRC_RPI=m -+CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SERIAL=m -+CONFIG_FB_TFT=m -+CONFIG_FB_TFT_AGM1264K_FL=m -+CONFIG_FB_TFT_BD663474=m -+CONFIG_FB_TFT_HX8340BN=m -+CONFIG_FB_TFT_HX8347D=m -+CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_HX8357D=m -+CONFIG_FB_TFT_ILI9163=m -+CONFIG_FB_TFT_ILI9320=m -+CONFIG_FB_TFT_ILI9325=m -+CONFIG_FB_TFT_ILI9340=m -+CONFIG_FB_TFT_ILI9341=m -+CONFIG_FB_TFT_ILI9481=m -+CONFIG_FB_TFT_ILI9486=m -+CONFIG_FB_TFT_PCD8544=m -+CONFIG_FB_TFT_RA8875=m -+CONFIG_FB_TFT_S6D02A1=m -+CONFIG_FB_TFT_S6D1121=m -+CONFIG_FB_TFT_SSD1289=m -+CONFIG_FB_TFT_SSD1306=m -+CONFIG_FB_TFT_SSD1331=m -+CONFIG_FB_TFT_SSD1351=m -+CONFIG_FB_TFT_ST7735R=m -+CONFIG_FB_TFT_TINYLCD=m -+CONFIG_FB_TFT_TLS8204=m -+CONFIG_FB_TFT_UC1701=m -+CONFIG_FB_TFT_UPD161704=m -+CONFIG_FB_TFT_WATTEROTT=m -+CONFIG_FB_FLEX=m -+CONFIG_FB_TFT_FBTFT_DEVICE=m -+CONFIG_MAILBOX=y -+CONFIG_BCM2835_MBOX=y -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_RASPBERRYPI_POWER=y -+CONFIG_EXTCON=m -+CONFIG_EXTCON_ARIZONA=m -+CONFIG_IIO=m -+CONFIG_IIO_BUFFER=y -+CONFIG_IIO_BUFFER_CB=m -+CONFIG_IIO_KFIFO_BUF=m -+CONFIG_MCP320X=m -+CONFIG_MCP3422=m -+CONFIG_DHT11=m -+CONFIG_HTU21=m -+CONFIG_PWM_BCM2835=m -+CONFIG_PWM_PCA9685=m -+CONFIG_RASPBERRYPI_FIRMWARE=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_REISERFS_FS=m -+CONFIG_REISERFS_FS_XATTR=y -+CONFIG_REISERFS_FS_POSIX_ACL=y -+CONFIG_REISERFS_FS_SECURITY=y -+CONFIG_JFS_FS=m -+CONFIG_JFS_POSIX_ACL=y -+CONFIG_JFS_SECURITY=y -+CONFIG_JFS_STATISTICS=y -+CONFIG_XFS_FS=m -+CONFIG_XFS_QUOTA=y -+CONFIG_XFS_POSIX_ACL=y -+CONFIG_XFS_RT=y -+CONFIG_GFS2_FS=m -+CONFIG_OCFS2_FS=m -+CONFIG_BTRFS_FS=m -+CONFIG_BTRFS_FS_POSIX_ACL=y -+CONFIG_NILFS2_FS=m -+CONFIG_F2FS_FS=y -+CONFIG_FANOTIFY=y -+CONFIG_QFMT_V1=m -+CONFIG_QFMT_V2=m -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=m -+CONFIG_CUSE=m -+CONFIG_OVERLAY_FS=m -+CONFIG_FSCACHE=y -+CONFIG_FSCACHE_STATS=y -+CONFIG_FSCACHE_HISTOGRAM=y -+CONFIG_CACHEFILES=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -+CONFIG_NTFS_FS=m -+CONFIG_NTFS_RW=y -+CONFIG_TMPFS=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_ECRYPT_FS=m -+CONFIG_HFS_FS=m -+CONFIG_HFSPLUS_FS=m -+CONFIG_JFFS2_FS=m -+CONFIG_JFFS2_SUMMARY=y -+CONFIG_UBIFS_FS=m -+CONFIG_SQUASHFS=m -+CONFIG_SQUASHFS_XATTR=y -+CONFIG_SQUASHFS_LZO=y -+CONFIG_SQUASHFS_XZ=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_NFS_SWAP=y -+CONFIG_ROOT_NFS=y -+CONFIG_NFS_FSCACHE=y -+CONFIG_NFSD=m -+CONFIG_NFSD_V3_ACL=y -+CONFIG_NFSD_V4=y -+CONFIG_CIFS=m -+CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y -+CONFIG_CIFS_XATTR=y -+CONFIG_CIFS_POSIX=y -+CONFIG_CIFS_ACL=y -+CONFIG_CIFS_DFS_UPCALL=y -+CONFIG_CIFS_SMB2=y -+CONFIG_CIFS_FSCACHE=y -+CONFIG_9P_FS=m -+CONFIG_9P_FS_POSIX_ACL=y -+CONFIG_NLS_DEFAULT="utf8" -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_737=m -+CONFIG_NLS_CODEPAGE_775=m -+CONFIG_NLS_CODEPAGE_850=m -+CONFIG_NLS_CODEPAGE_852=m -+CONFIG_NLS_CODEPAGE_855=m -+CONFIG_NLS_CODEPAGE_857=m -+CONFIG_NLS_CODEPAGE_860=m -+CONFIG_NLS_CODEPAGE_861=m -+CONFIG_NLS_CODEPAGE_862=m -+CONFIG_NLS_CODEPAGE_863=m -+CONFIG_NLS_CODEPAGE_864=m -+CONFIG_NLS_CODEPAGE_865=m -+CONFIG_NLS_CODEPAGE_866=m -+CONFIG_NLS_CODEPAGE_869=m -+CONFIG_NLS_CODEPAGE_936=m -+CONFIG_NLS_CODEPAGE_950=m -+CONFIG_NLS_CODEPAGE_932=m -+CONFIG_NLS_CODEPAGE_949=m -+CONFIG_NLS_CODEPAGE_874=m -+CONFIG_NLS_ISO8859_8=m -+CONFIG_NLS_CODEPAGE_1250=m -+CONFIG_NLS_CODEPAGE_1251=m -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=m -+CONFIG_NLS_ISO8859_2=m -+CONFIG_NLS_ISO8859_3=m -+CONFIG_NLS_ISO8859_4=m -+CONFIG_NLS_ISO8859_5=m -+CONFIG_NLS_ISO8859_6=m -+CONFIG_NLS_ISO8859_7=m -+CONFIG_NLS_ISO8859_9=m -+CONFIG_NLS_ISO8859_13=m -+CONFIG_NLS_ISO8859_14=m -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_KOI8_R=m -+CONFIG_NLS_KOI8_U=m -+CONFIG_DLM=m -+CONFIG_PRINTK_TIME=y -+CONFIG_BOOT_PRINTK_DELAY=y -+CONFIG_DEBUG_MEMORY_INIT=y -+CONFIG_DETECT_HUNG_TASK=y -+CONFIG_TIMER_STATS=y -+CONFIG_LATENCYTOP=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+# CONFIG_KPROBE_EVENT is not set -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_KGDB=y -+CONFIG_KGDB_KDB=y -+CONFIG_KDB_KEYBOARD=y -+CONFIG_CRYPTO_USER=m -+CONFIG_CRYPTO_CRYPTD=m -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=m -+CONFIG_CRYPTO_XTS=m -+CONFIG_CRYPTO_XCBC=m -+CONFIG_CRYPTO_SHA512=m -+CONFIG_CRYPTO_TGR192=m -+CONFIG_CRYPTO_WP512=m -+CONFIG_CRYPTO_CAST5=m -+CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_USER_API_SKCIPHER=m -+# CONFIG_CRYPTO_HW is not set -+CONFIG_ARM_CRYPTO=y -+CONFIG_CRYPTO_SHA1_ARM=m -+CONFIG_CRYPTO_AES_ARM=m -+CONFIG_CRC_ITU_T=y -+CONFIG_LIBCRC32C=y diff --git a/target/linux/brcm2708/patches-4.9/0095-Add-arm64-configuration-and-device-tree-differences.patch b/target/linux/brcm2708/patches-4.9/0095-Add-arm64-configuration-and-device-tree-differences.patch deleted file mode 100644 index 9c76d38550..0000000000 --- a/target/linux/brcm2708/patches-4.9/0095-Add-arm64-configuration-and-device-tree-differences.patch +++ /dev/null @@ -1,1407 +0,0 @@ -From 24273c675c44f730b89416a40fac0aa35df6cfe0 Mon Sep 17 00:00:00 2001 -From: Michael Zoran -Date: Wed, 24 Aug 2016 03:35:56 -0700 -Subject: [PATCH] Add arm64 configuration and device tree differences. Disable - MMC_BCM2835_SDHOST and MMC_BCM2835 since these drivers are crashing at the - moment. - -ARM64: Modify default config to get raspbian to boot (#1686) - -1. Enable emulation of deprecated instructions. -2. Enable ARM 8.1 and 8.2 features which are not detected at runtime. -3. Switch the default governer to powersave. -4. Include the watchdog timer driver in the kernel image rather then a module. - -Tested with raspbian-jessie 2016-09-23. ---- - arch/arm64/Kconfig.platforms | 22 + - arch/arm64/boot/dts/broadcom/Makefile | 1 + - arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts | 3 + - arch/arm64/configs/bcmrpi3_defconfig | 1334 ++++++++++++++++++++++ - 4 files changed, 1360 insertions(+) - create mode 100644 arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts - create mode 100644 arch/arm64/configs/bcmrpi3_defconfig - ---- a/arch/arm64/Kconfig.platforms -+++ b/arch/arm64/Kconfig.platforms -@@ -1,5 +1,27 @@ - menu "Platform selection" - -+config MACH_BCM2709 -+ bool -+ -+config ARCH_BCM2709 -+ bool "Broadcom BCM2709 family" -+ select MACH_BCM2709 -+ select HAVE_SMP -+ select ARM_AMBA -+ select COMMON_CLK -+ select ARCH_HAS_CPUFREQ -+ select GENERIC_CLOCKEVENTS -+ select MULTI_IRQ_HANDLER -+ select SPARSE_IRQ -+ select MFD_SYSCON -+ select VC4 -+ select USE_OF -+ select ARCH_REQUIRE_GPIOLIB -+ select PINCTRL -+ select PINCTRL_BCM2835 -+ help -+ This enables support for Broadcom BCM2709 boards. -+ - config ARCH_SUNXI - bool "Allwinner sunxi 64-bit SoC Family" - select GENERIC_IRQ_CHIP ---- a/arch/arm64/boot/dts/broadcom/Makefile -+++ b/arch/arm64/boot/dts/broadcom/Makefile -@@ -1,6 +1,7 @@ - dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb - dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb - dtb-$(CONFIG_ARCH_VULCAN) += vulcan-eval.dtb -+dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb - - always := $(dtb-y) - subdir-y := $(dts-dirs) ---- /dev/null -+++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts -@@ -0,0 +1,3 @@ -+#define RPI364 -+ -+#include "../../../../arm/boot/dts/bcm2710-rpi-3-b.dts" ---- /dev/null -+++ b/arch/arm64/configs/bcmrpi3_defconfig -@@ -0,0 +1,1334 @@ -+# CONFIG_ARM_PATCH_PHYS_VIRT is not set -+CONFIG_PHYS_OFFSET=0 -+CONFIG_LOCALVERSION="-v8" -+# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_64BIT=y -+CONFIG_SYSVIPC=y -+CONFIG_POSIX_MQUEUE=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+ -+# -+# ARM errata workarounds via the alternatives framework -+# -+CONFIG_ARM64_ERRATUM_826319=n -+CONFIG_ARM64_ERRATUM_827319=n -+CONFIG_ARM64_ERRATUM_824069=n -+CONFIG_ARM64_ERRATUM_819472=n -+CONFIG_ARM64_ERRATUM_832075=n -+CONFIG_ARM64_ERRATUM_845719=n -+CONFIG_ARM64_ERRATUM_843419=n -+CONFIG_CAVIUM_ERRATUM_22375=n -+CONFIG_CAVIUM_ERRATUM_23154=n -+CONFIG_CAVIUM_ERRATUM_27456=n -+CONFIG_ARM64_4K_PAGES=y -+CONFIG_ARM64_VA_BITS_39=y -+CONFIG_ARM64_VA_BITS=39 -+CONFIG_SCHED_MC=y -+CONFIG_NR_CPUS=4 -+CONFIG_HOTPLUG_CPU=y -+CONFIG_ARMV8_DEPRECATED=y -+CONFIG_SWP_EMULATION=y -+CONFIG_CP15_BARRIER_EMULATION=y -+CONFIG_SETEND_EMULATION=y -+ -+# -+# ARMv8.1 architectural features -+# -+CONFIG_ARM64_HW_AFDBM=y -+CONFIG_ARM64_PAN=y -+CONFIG_ARM64_LSE_ATOMICS=y -+CONFIG_ARM64_VHE=y -+ -+# -+# ARMv8.2 architectural features -+# -+CONFIG_ARM64_UAO=y -+CONFIG_ARM64_MODULE_CMODEL_LARGE=n -+CONFIG_RANDOMIZE_BASE=n -+ -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_BSD_PROCESS_ACCT_V3=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_IKCONFIG=m -+CONFIG_IKCONFIG_PROC=y -+CONFIG_NMI_LOG_BUF_SHIFT=12 -+CONFIG_MEMCG=y -+CONFIG_BLK_CGROUP=y -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CPUSETS=y -+CONFIG_CGROUP_DEVICE=y -+CONFIG_CGROUP_CPUACCT=y -+CONFIG_NAMESPACES=y -+CONFIG_USER_NS=y -+CONFIG_SCHED_AUTOGROUP=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_EMBEDDED=y -+# CONFIG_COMPAT_BRK is not set -+CONFIG_PROFILING=y -+CONFIG_OPROFILE=m -+CONFIG_KPROBES=y -+CONFIG_JUMP_LABEL=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+CONFIG_TRIM_UNUSED_KSYMS=y -+CONFIG_BLK_DEV_THROTTLING=y -+CONFIG_PARTITION_ADVANCED=y -+CONFIG_MAC_PARTITION=y -+CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_ARCH_BCM2709=y -+# CONFIG_CACHE_L2X0 is not set -+CONFIG_SMP=y -+CONFIG_HAVE_ARM_ARCH_TIMER=y -+CONFIG_VMSPLIT_2G=y -+CONFIG_PREEMPT_VOLUNTARY=y -+CONFIG_AEABI=y -+CONFIG_OABI_COMPAT=y -+# CONFIG_CPU_SW_DOMAIN_PAN is not set -+CONFIG_CLEANCACHE=y -+CONFIG_FRONTSWAP=y -+CONFIG_CMA=y -+CONFIG_ZSMALLOC=m -+CONFIG_PGTABLE_MAPPING=y -+CONFIG_UACCESS_WITH_MEMCPY=y -+CONFIG_SECCOMP=y -+# CONFIG_ATAGS is not set -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+CONFIG_ZBOOT_ROM_BSS=0x0 -+CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -+CONFIG_VFP=y -+CONFIG_NEON=y -+CONFIG_KERNEL_MODE_NEON=y -+CONFIG_BINFMT_MISC=m -+CONFIG_COMPAT=y -+CONFIG_SYSVIPC_COMPAT=y -+ -+# CONFIG_SUSPEND is not set -+CONFIG_PM=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_NET_KEY=m -+CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_MULTIPATH=y -+CONFIG_IP_ROUTE_VERBOSE=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+CONFIG_IP_PNP_RARP=y -+CONFIG_NET_IPIP=m -+CONFIG_NET_IPGRE_DEMUX=m -+CONFIG_NET_IPGRE=m -+CONFIG_IP_MROUTE=y -+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IP_PIMSM_V1=y -+CONFIG_IP_PIMSM_V2=y -+CONFIG_SYN_COOKIES=y -+CONFIG_INET_AH=m -+CONFIG_INET_ESP=m -+CONFIG_INET_IPCOMP=m -+CONFIG_INET_XFRM_MODE_TRANSPORT=m -+CONFIG_INET_XFRM_MODE_TUNNEL=m -+CONFIG_INET_XFRM_MODE_BEET=m -+CONFIG_INET_DIAG=m -+CONFIG_IPV6=m -+CONFIG_IPV6_ROUTER_PREF=y -+CONFIG_INET6_AH=m -+CONFIG_INET6_ESP=m -+CONFIG_INET6_IPCOMP=m -+CONFIG_IPV6_TUNNEL=m -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_IPV6_SUBTREES=y -+CONFIG_IPV6_MROUTE=y -+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IPV6_PIMSM_V2=y -+CONFIG_NETFILTER=y -+CONFIG_NF_CONNTRACK=m -+CONFIG_NF_CONNTRACK_ZONES=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_TIMESTAMP=y -+CONFIG_NF_CT_PROTO_DCCP=m -+CONFIG_NF_CT_PROTO_UDPLITE=m -+CONFIG_NF_CONNTRACK_AMANDA=m -+CONFIG_NF_CONNTRACK_FTP=m -+CONFIG_NF_CONNTRACK_H323=m -+CONFIG_NF_CONNTRACK_IRC=m -+CONFIG_NF_CONNTRACK_NETBIOS_NS=m -+CONFIG_NF_CONNTRACK_SNMP=m -+CONFIG_NF_CONNTRACK_PPTP=m -+CONFIG_NF_CONNTRACK_SANE=m -+CONFIG_NF_CONNTRACK_SIP=m -+CONFIG_NF_CONNTRACK_TFTP=m -+CONFIG_NF_CT_NETLINK=m -+CONFIG_NETFILTER_XT_SET=m -+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -+CONFIG_NETFILTER_XT_TARGET_DSCP=m -+CONFIG_NETFILTER_XT_TARGET_HMARK=m -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -+CONFIG_NETFILTER_XT_TARGET_LED=m -+CONFIG_NETFILTER_XT_TARGET_LOG=m -+CONFIG_NETFILTER_XT_TARGET_MARK=m -+CONFIG_NETFILTER_XT_TARGET_NFLOG=m -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -+CONFIG_NETFILTER_XT_TARGET_TEE=m -+CONFIG_NETFILTER_XT_TARGET_TPROXY=m -+CONFIG_NETFILTER_XT_TARGET_TRACE=m -+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m -+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -+CONFIG_NETFILTER_XT_MATCH_BPF=m -+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -+CONFIG_NETFILTER_XT_MATCH_COMMENT=m -+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m -+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -+CONFIG_NETFILTER_XT_MATCH_CPU=m -+CONFIG_NETFILTER_XT_MATCH_DCCP=m -+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -+CONFIG_NETFILTER_XT_MATCH_DSCP=m -+CONFIG_NETFILTER_XT_MATCH_ESP=m -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_HELPER=m -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -+CONFIG_NETFILTER_XT_MATCH_IPVS=m -+CONFIG_NETFILTER_XT_MATCH_LENGTH=m -+CONFIG_NETFILTER_XT_MATCH_LIMIT=m -+CONFIG_NETFILTER_XT_MATCH_MAC=m -+CONFIG_NETFILTER_XT_MATCH_MARK=m -+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -+CONFIG_NETFILTER_XT_MATCH_NFACCT=m -+CONFIG_NETFILTER_XT_MATCH_OSF=m -+CONFIG_NETFILTER_XT_MATCH_OWNER=m -+CONFIG_NETFILTER_XT_MATCH_POLICY=m -+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -+CONFIG_NETFILTER_XT_MATCH_QUOTA=m -+CONFIG_NETFILTER_XT_MATCH_RATEEST=m -+CONFIG_NETFILTER_XT_MATCH_REALM=m -+CONFIG_NETFILTER_XT_MATCH_RECENT=m -+CONFIG_NETFILTER_XT_MATCH_SOCKET=m -+CONFIG_NETFILTER_XT_MATCH_STATE=m -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -+CONFIG_NETFILTER_XT_MATCH_STRING=m -+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -+CONFIG_NETFILTER_XT_MATCH_TIME=m -+CONFIG_NETFILTER_XT_MATCH_U32=m -+CONFIG_IP_SET=m -+CONFIG_IP_SET_BITMAP_IP=m -+CONFIG_IP_SET_BITMAP_IPMAC=m -+CONFIG_IP_SET_BITMAP_PORT=m -+CONFIG_IP_SET_HASH_IP=m -+CONFIG_IP_SET_HASH_IPPORT=m -+CONFIG_IP_SET_HASH_IPPORTIP=m -+CONFIG_IP_SET_HASH_IPPORTNET=m -+CONFIG_IP_SET_HASH_NET=m -+CONFIG_IP_SET_HASH_NETPORT=m -+CONFIG_IP_SET_HASH_NETIFACE=m -+CONFIG_IP_SET_LIST_SET=m -+CONFIG_IP_VS=m -+CONFIG_IP_VS_PROTO_TCP=y -+CONFIG_IP_VS_PROTO_UDP=y -+CONFIG_IP_VS_PROTO_ESP=y -+CONFIG_IP_VS_PROTO_AH=y -+CONFIG_IP_VS_PROTO_SCTP=y -+CONFIG_IP_VS_RR=m -+CONFIG_IP_VS_WRR=m -+CONFIG_IP_VS_LC=m -+CONFIG_IP_VS_WLC=m -+CONFIG_IP_VS_LBLC=m -+CONFIG_IP_VS_LBLCR=m -+CONFIG_IP_VS_DH=m -+CONFIG_IP_VS_SH=m -+CONFIG_IP_VS_SED=m -+CONFIG_IP_VS_NQ=m -+CONFIG_IP_VS_FTP=m -+CONFIG_IP_VS_PE_SIP=m -+CONFIG_NF_CONNTRACK_IPV4=m -+CONFIG_IP_NF_IPTABLES=m -+CONFIG_IP_NF_MATCH_AH=m -+CONFIG_IP_NF_MATCH_ECN=m -+CONFIG_IP_NF_MATCH_RPFILTER=m -+CONFIG_IP_NF_MATCH_TTL=m -+CONFIG_IP_NF_FILTER=m -+CONFIG_IP_NF_TARGET_REJECT=m -+CONFIG_IP_NF_NAT=m -+CONFIG_IP_NF_TARGET_MASQUERADE=m -+CONFIG_IP_NF_TARGET_NETMAP=m -+CONFIG_IP_NF_TARGET_REDIRECT=m -+CONFIG_IP_NF_MANGLE=m -+CONFIG_IP_NF_TARGET_CLUSTERIP=m -+CONFIG_IP_NF_TARGET_ECN=m -+CONFIG_IP_NF_TARGET_TTL=m -+CONFIG_IP_NF_RAW=m -+CONFIG_IP_NF_ARPTABLES=m -+CONFIG_IP_NF_ARPFILTER=m -+CONFIG_IP_NF_ARP_MANGLE=m -+CONFIG_NF_CONNTRACK_IPV6=m -+CONFIG_IP6_NF_IPTABLES=m -+CONFIG_IP6_NF_MATCH_AH=m -+CONFIG_IP6_NF_MATCH_EUI64=m -+CONFIG_IP6_NF_MATCH_FRAG=m -+CONFIG_IP6_NF_MATCH_OPTS=m -+CONFIG_IP6_NF_MATCH_HL=m -+CONFIG_IP6_NF_MATCH_IPV6HEADER=m -+CONFIG_IP6_NF_MATCH_MH=m -+CONFIG_IP6_NF_MATCH_RPFILTER=m -+CONFIG_IP6_NF_MATCH_RT=m -+CONFIG_IP6_NF_TARGET_HL=m -+CONFIG_IP6_NF_FILTER=m -+CONFIG_IP6_NF_TARGET_REJECT=m -+CONFIG_IP6_NF_MANGLE=m -+CONFIG_IP6_NF_RAW=m -+CONFIG_IP6_NF_NAT=m -+CONFIG_IP6_NF_TARGET_MASQUERADE=m -+CONFIG_IP6_NF_TARGET_NPT=m -+CONFIG_BRIDGE_NF_EBTABLES=m -+CONFIG_BRIDGE_EBT_BROUTE=m -+CONFIG_BRIDGE_EBT_T_FILTER=m -+CONFIG_BRIDGE_EBT_T_NAT=m -+CONFIG_BRIDGE_EBT_802_3=m -+CONFIG_BRIDGE_EBT_AMONG=m -+CONFIG_BRIDGE_EBT_ARP=m -+CONFIG_BRIDGE_EBT_IP=m -+CONFIG_BRIDGE_EBT_IP6=m -+CONFIG_BRIDGE_EBT_LIMIT=m -+CONFIG_BRIDGE_EBT_MARK=m -+CONFIG_BRIDGE_EBT_PKTTYPE=m -+CONFIG_BRIDGE_EBT_STP=m -+CONFIG_BRIDGE_EBT_VLAN=m -+CONFIG_BRIDGE_EBT_ARPREPLY=m -+CONFIG_BRIDGE_EBT_DNAT=m -+CONFIG_BRIDGE_EBT_MARK_T=m -+CONFIG_BRIDGE_EBT_REDIRECT=m -+CONFIG_BRIDGE_EBT_SNAT=m -+CONFIG_BRIDGE_EBT_LOG=m -+CONFIG_BRIDGE_EBT_NFLOG=m -+CONFIG_SCTP_COOKIE_HMAC_SHA1=y -+CONFIG_ATM=m -+CONFIG_L2TP=m -+CONFIG_L2TP_V3=y -+CONFIG_L2TP_IP=m -+CONFIG_L2TP_ETH=m -+CONFIG_BRIDGE=m -+CONFIG_VLAN_8021Q=m -+CONFIG_VLAN_8021Q_GVRP=y -+CONFIG_ATALK=m -+CONFIG_6LOWPAN=m -+CONFIG_IEEE802154=m -+CONFIG_IEEE802154_6LOWPAN=m -+CONFIG_MAC802154=m -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_CBQ=m -+CONFIG_NET_SCH_HTB=m -+CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_PRIO=m -+CONFIG_NET_SCH_MULTIQ=m -+CONFIG_NET_SCH_RED=m -+CONFIG_NET_SCH_SFB=m -+CONFIG_NET_SCH_SFQ=m -+CONFIG_NET_SCH_TEQL=m -+CONFIG_NET_SCH_TBF=m -+CONFIG_NET_SCH_GRED=m -+CONFIG_NET_SCH_DSMARK=m -+CONFIG_NET_SCH_NETEM=m -+CONFIG_NET_SCH_DRR=m -+CONFIG_NET_SCH_MQPRIO=m -+CONFIG_NET_SCH_CHOKE=m -+CONFIG_NET_SCH_QFQ=m -+CONFIG_NET_SCH_CODEL=m -+CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_INGRESS=m -+CONFIG_NET_SCH_PLUG=m -+CONFIG_NET_CLS_BASIC=m -+CONFIG_NET_CLS_TCINDEX=m -+CONFIG_NET_CLS_ROUTE4=m -+CONFIG_NET_CLS_FW=m -+CONFIG_NET_CLS_U32=m -+CONFIG_CLS_U32_MARK=y -+CONFIG_NET_CLS_RSVP=m -+CONFIG_NET_CLS_RSVP6=m -+CONFIG_NET_CLS_FLOW=m -+CONFIG_NET_CLS_CGROUP=m -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_CMP=m -+CONFIG_NET_EMATCH_NBYTE=m -+CONFIG_NET_EMATCH_U32=m -+CONFIG_NET_EMATCH_META=m -+CONFIG_NET_EMATCH_TEXT=m -+CONFIG_NET_EMATCH_IPSET=m -+CONFIG_NET_CLS_ACT=y -+CONFIG_NET_ACT_POLICE=m -+CONFIG_NET_ACT_GACT=m -+CONFIG_GACT_PROB=y -+CONFIG_NET_ACT_MIRRED=m -+CONFIG_NET_ACT_IPT=m -+CONFIG_NET_ACT_NAT=m -+CONFIG_NET_ACT_PEDIT=m -+CONFIG_NET_ACT_SIMP=m -+CONFIG_NET_ACT_SKBEDIT=m -+CONFIG_NET_ACT_CSUM=m -+CONFIG_BATMAN_ADV=m -+CONFIG_OPENVSWITCH=m -+CONFIG_NET_PKTGEN=m -+CONFIG_HAMRADIO=y -+CONFIG_AX25=m -+CONFIG_NETROM=m -+CONFIG_ROSE=m -+CONFIG_MKISS=m -+CONFIG_6PACK=m -+CONFIG_BPQETHER=m -+CONFIG_BAYCOM_SER_FDX=m -+CONFIG_BAYCOM_SER_HDX=m -+CONFIG_YAM=m -+CONFIG_CAN=m -+CONFIG_CAN_VCAN=m -+CONFIG_CAN_MCP251X=m -+CONFIG_IRDA=m -+CONFIG_IRLAN=m -+CONFIG_IRNET=m -+CONFIG_IRCOMM=m -+CONFIG_IRDA_ULTRA=y -+CONFIG_IRDA_CACHE_LAST_LSAP=y -+CONFIG_IRDA_FAST_RR=y -+CONFIG_IRTTY_SIR=m -+CONFIG_KINGSUN_DONGLE=m -+CONFIG_KSDAZZLE_DONGLE=m -+CONFIG_KS959_DONGLE=m -+CONFIG_USB_IRDA=m -+CONFIG_SIGMATEL_FIR=m -+CONFIG_MCS_FIR=m -+CONFIG_BT=m -+CONFIG_BT_RFCOMM=m -+CONFIG_BT_RFCOMM_TTY=y -+CONFIG_BT_BNEP=m -+CONFIG_BT_BNEP_MC_FILTER=y -+CONFIG_BT_BNEP_PROTO_FILTER=y -+CONFIG_BT_HIDP=m -+CONFIG_BT_6LOWPAN=m -+CONFIG_BT_HCIBTUSB=m -+CONFIG_BT_HCIUART=m -+CONFIG_BT_HCIUART_3WIRE=y -+CONFIG_BT_HCIUART_BCM=y -+CONFIG_BT_HCIBCM203X=m -+CONFIG_BT_HCIBPA10X=m -+CONFIG_BT_HCIBFUSB=m -+CONFIG_BT_HCIVHCI=m -+CONFIG_BT_MRVL=m -+CONFIG_BT_MRVL_SDIO=m -+CONFIG_BT_ATH3K=m -+CONFIG_BT_WILINK=m -+CONFIG_MAC80211=m -+CONFIG_MAC80211_MESH=y -+CONFIG_WIMAX=m -+CONFIG_RFKILL=m -+CONFIG_RFKILL_INPUT=y -+CONFIG_NET_9P=m -+CONFIG_NFC=m -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+CONFIG_DMA_CMA=y -+CONFIG_CMA_SIZE_MBYTES=5 -+CONFIG_MTD=m -+CONFIG_MTD_BLOCK=m -+CONFIG_MTD_NAND=m -+CONFIG_MTD_UBI=m -+CONFIG_OF_CONFIGFS=y -+CONFIG_ZRAM=m -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_CRYPTOLOOP=m -+CONFIG_BLK_DEV_DRBD=m -+CONFIG_BLK_DEV_NBD=m -+CONFIG_BLK_DEV_RAM=y -+CONFIG_CDROM_PKTCDVD=m -+CONFIG_ATA_OVER_ETH=m -+CONFIG_EEPROM_AT24=m -+CONFIG_TI_ST=m -+CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_CHR_DEV_ST=m -+CONFIG_CHR_DEV_OSST=m -+CONFIG_BLK_DEV_SR=m -+CONFIG_CHR_DEV_SG=m -+CONFIG_SCSI_ISCSI_ATTRS=y -+CONFIG_ISCSI_TCP=m -+CONFIG_ISCSI_BOOT_SYSFS=m -+CONFIG_MD=y -+CONFIG_MD_LINEAR=m -+CONFIG_MD_RAID0=m -+CONFIG_BLK_DEV_DM=m -+CONFIG_DM_CRYPT=m -+CONFIG_DM_SNAPSHOT=m -+CONFIG_DM_THIN_PROVISIONING=m -+CONFIG_DM_MIRROR=m -+CONFIG_DM_LOG_USERSPACE=m -+CONFIG_DM_RAID=m -+CONFIG_DM_ZERO=m -+CONFIG_DM_DELAY=m -+CONFIG_NETDEVICES=y -+CONFIG_BONDING=m -+CONFIG_DUMMY=m -+CONFIG_IFB=m -+CONFIG_MACVLAN=m -+CONFIG_IPVLAN=m -+CONFIG_VXLAN=m -+CONFIG_NETCONSOLE=m -+CONFIG_TUN=m -+CONFIG_VETH=m -+CONFIG_ENC28J60=m -+CONFIG_QCA7000=m -+CONFIG_MDIO_BITBANG=m -+CONFIG_PPP=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_FILTER=y -+CONFIG_PPP_MPPE=m -+CONFIG_PPP_MULTILINK=y -+CONFIG_PPPOATM=m -+CONFIG_PPPOE=m -+CONFIG_PPPOL2TP=m -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_SLIP_SMART=y -+CONFIG_USB_CATC=m -+CONFIG_USB_KAWETH=m -+CONFIG_USB_PEGASUS=m -+CONFIG_USB_RTL8150=m -+CONFIG_USB_RTL8152=m -+CONFIG_USB_USBNET=y -+CONFIG_USB_NET_AX8817X=m -+CONFIG_USB_NET_AX88179_178A=m -+CONFIG_USB_NET_CDCETHER=m -+CONFIG_USB_NET_CDC_EEM=m -+CONFIG_USB_NET_CDC_NCM=m -+CONFIG_USB_NET_HUAWEI_CDC_NCM=m -+CONFIG_USB_NET_CDC_MBIM=m -+CONFIG_USB_NET_DM9601=m -+CONFIG_USB_NET_SR9700=m -+CONFIG_USB_NET_SR9800=m -+CONFIG_USB_NET_SMSC75XX=m -+CONFIG_USB_NET_SMSC95XX=y -+CONFIG_USB_NET_GL620A=m -+CONFIG_USB_NET_NET1080=m -+CONFIG_USB_NET_PLUSB=m -+CONFIG_USB_NET_MCS7830=m -+CONFIG_USB_NET_CDC_SUBSET=m -+CONFIG_USB_ALI_M5632=y -+CONFIG_USB_AN2720=y -+CONFIG_USB_EPSON2888=y -+CONFIG_USB_KC2190=y -+CONFIG_USB_NET_ZAURUS=m -+CONFIG_USB_NET_CX82310_ETH=m -+CONFIG_USB_NET_KALMIA=m -+CONFIG_USB_NET_QMI_WWAN=m -+CONFIG_USB_HSO=m -+CONFIG_USB_NET_INT51X1=m -+CONFIG_USB_IPHETH=m -+CONFIG_USB_SIERRA_NET=m -+CONFIG_USB_VL600=m -+CONFIG_ATH9K=m -+CONFIG_ATH9K_HTC=m -+CONFIG_CARL9170=m -+CONFIG_ATH6KL=m -+CONFIG_ATH6KL_USB=m -+CONFIG_AR5523=m -+CONFIG_AT76C50X_USB=m -+CONFIG_B43=m -+# CONFIG_B43_PHY_N is not set -+CONFIG_B43LEGACY=m -+CONFIG_BRCMFMAC=m -+CONFIG_BRCMFMAC_USB=y -+CONFIG_HOSTAP=m -+CONFIG_P54_COMMON=m -+CONFIG_P54_USB=m -+CONFIG_LIBERTAS=m -+CONFIG_LIBERTAS_USB=m -+CONFIG_LIBERTAS_SDIO=m -+CONFIG_LIBERTAS_THINFIRM=m -+CONFIG_LIBERTAS_THINFIRM_USB=m -+CONFIG_MWIFIEX=m -+CONFIG_MWIFIEX_SDIO=m -+CONFIG_MT7601U=m -+CONFIG_RT2X00=m -+CONFIG_RT2500USB=m -+CONFIG_RT73USB=m -+CONFIG_RT2800USB=m -+CONFIG_RT2800USB_RT3573=y -+CONFIG_RT2800USB_RT53XX=y -+CONFIG_RT2800USB_RT55XX=y -+CONFIG_RT2800USB_UNKNOWN=y -+CONFIG_RTL8187=m -+CONFIG_RTL8192CU=n -+CONFIG_USB_ZD1201=m -+CONFIG_ZD1211RW=m -+CONFIG_MAC80211_HWSIM=m -+CONFIG_USB_NET_RNDIS_WLAN=m -+CONFIG_WIMAX_I2400M_USB=m -+CONFIG_IEEE802154_AT86RF230=m -+CONFIG_IEEE802154_MRF24J40=m -+CONFIG_IEEE802154_CC2520=m -+CONFIG_INPUT_POLLDEV=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+CONFIG_INPUT_JOYDEV=m -+CONFIG_INPUT_EVDEV=m -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m -+# CONFIG_INPUT_MOUSE is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_JOYSTICK_IFORCE=m -+CONFIG_JOYSTICK_IFORCE_USB=y -+CONFIG_JOYSTICK_XPAD=m -+CONFIG_JOYSTICK_XPAD_FF=y -+CONFIG_JOYSTICK_XPAD_LEDS=y -+CONFIG_JOYSTICK_RPISENSE=m -+CONFIG_INPUT_TOUCHSCREEN=y -+CONFIG_TOUCHSCREEN_ADS7846=m -+CONFIG_TOUCHSCREEN_EGALAX=m -+CONFIG_TOUCHSCREEN_FT6236=m -+CONFIG_TOUCHSCREEN_RPI_FT5406=m -+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -+CONFIG_TOUCHSCREEN_STMPE=m -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_AD714X=m -+CONFIG_INPUT_ATI_REMOTE2=m -+CONFIG_INPUT_KEYSPAN_REMOTE=m -+CONFIG_INPUT_POWERMATE=m -+CONFIG_INPUT_YEALINK=m -+CONFIG_INPUT_CM109=m -+CONFIG_INPUT_UINPUT=m -+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -+CONFIG_INPUT_ADXL34X=m -+CONFIG_INPUT_CMA3000=m -+CONFIG_SERIO=m -+CONFIG_SERIO_RAW=m -+CONFIG_GAMEPORT=m -+CONFIG_GAMEPORT_NS558=m -+CONFIG_GAMEPORT_L4=m -+CONFIG_BRCM_CHAR_DRIVERS=n -+CONFIG_BCM_VC_CMA=n -+CONFIG_BCM_VCIO=n -+CONFIG_BCM_VC_SM=n -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set -+CONFIG_SERIAL_8250=y -+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -+CONFIG_SERIAL_8250_CONSOLE=y -+# CONFIG_SERIAL_8250_DMA is not set -+CONFIG_SERIAL_8250_NR_UARTS=1 -+CONFIG_SERIAL_8250_RUNTIME_UARTS=0 -+CONFIG_SERIAL_OF_PLATFORM=y -+CONFIG_SERIAL_AMBA_PL011=y -+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -+CONFIG_SERIAL_SC16IS7XX=m -+CONFIG_SERIAL_SC16IS7XX_SPI=y -+CONFIG_TTY_PRINTK=y -+CONFIG_HW_RANDOM=y -+CONFIG_RAW_DRIVER=y -+CONFIG_I2C=y -+CONFIG_I2C_CHARDEV=m -+CONFIG_I2C_MUX_PCA954x=m -+CONFIG_I2C_BCM2708=m -+CONFIG_I2C_GPIO=m -+CONFIG_SPI=y -+CONFIG_SPI_BCM2835=m -+CONFIG_SPI_BCM2835AUX=m -+CONFIG_SPI_SPIDEV=y -+CONFIG_PPS=m -+CONFIG_PPS_CLIENT_LDISC=m -+CONFIG_PPS_CLIENT_GPIO=m -+CONFIG_GPIO_SYSFS=y -+CONFIG_GPIO_BCM_VIRT=y -+CONFIG_GPIO_ARIZONA=m -+CONFIG_GPIO_STMPE=y -+CONFIG_GPIO_MCP23S08=m -+CONFIG_W1=m -+CONFIG_W1_MASTER_DS2490=m -+CONFIG_W1_MASTER_DS2482=m -+CONFIG_W1_MASTER_DS1WM=m -+CONFIG_W1_MASTER_GPIO=m -+CONFIG_W1_SLAVE_THERM=m -+CONFIG_W1_SLAVE_SMEM=m -+CONFIG_W1_SLAVE_DS2408=m -+CONFIG_W1_SLAVE_DS2413=m -+CONFIG_W1_SLAVE_DS2406=m -+CONFIG_W1_SLAVE_DS2423=m -+CONFIG_W1_SLAVE_DS2431=m -+CONFIG_W1_SLAVE_DS2433=m -+CONFIG_W1_SLAVE_DS2760=m -+CONFIG_W1_SLAVE_DS2780=m -+CONFIG_W1_SLAVE_DS2781=m -+CONFIG_W1_SLAVE_DS28E04=m -+CONFIG_W1_SLAVE_BQ27000=m -+CONFIG_BATTERY_DS2760=m -+CONFIG_POWER_RESET=y -+CONFIG_POWER_RESET_GPIO=y -+CONFIG_HWMON=m -+CONFIG_SENSORS_LM75=m -+CONFIG_SENSORS_SHT21=m -+CONFIG_SENSORS_SHTC1=m -+CONFIG_THERMAL=y -+CONFIG_THERMAL_BCM2835=y -+CONFIG_WATCHDOG=y -+CONFIG_BCM2835_WDT=y -+CONFIG_UCB1400_CORE=m -+CONFIG_MFD_STMPE=y -+CONFIG_STMPE_SPI=y -+CONFIG_MFD_ARIZONA_I2C=m -+CONFIG_MFD_ARIZONA_SPI=m -+CONFIG_MFD_WM5102=y -+CONFIG_MEDIA_SUPPORT=m -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y -+CONFIG_MEDIA_RADIO_SUPPORT=y -+CONFIG_MEDIA_RC_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y -+CONFIG_LIRC=m -+CONFIG_RC_DEVICES=y -+CONFIG_RC_ATI_REMOTE=m -+CONFIG_IR_IMON=m -+CONFIG_IR_MCEUSB=m -+CONFIG_IR_REDRAT3=m -+CONFIG_IR_STREAMZAP=m -+CONFIG_IR_IGUANA=m -+CONFIG_IR_TTUSBIR=m -+CONFIG_RC_LOOPBACK=m -+CONFIG_IR_GPIO_CIR=m -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_USB_M5602=m -+CONFIG_USB_STV06XX=m -+CONFIG_USB_GL860=m -+CONFIG_USB_GSPCA_BENQ=m -+CONFIG_USB_GSPCA_CONEX=m -+CONFIG_USB_GSPCA_CPIA1=m -+CONFIG_USB_GSPCA_DTCS033=m -+CONFIG_USB_GSPCA_ETOMS=m -+CONFIG_USB_GSPCA_FINEPIX=m -+CONFIG_USB_GSPCA_JEILINJ=m -+CONFIG_USB_GSPCA_JL2005BCD=m -+CONFIG_USB_GSPCA_KINECT=m -+CONFIG_USB_GSPCA_KONICA=m -+CONFIG_USB_GSPCA_MARS=m -+CONFIG_USB_GSPCA_MR97310A=m -+CONFIG_USB_GSPCA_NW80X=m -+CONFIG_USB_GSPCA_OV519=m -+CONFIG_USB_GSPCA_OV534=m -+CONFIG_USB_GSPCA_OV534_9=m -+CONFIG_USB_GSPCA_PAC207=m -+CONFIG_USB_GSPCA_PAC7302=m -+CONFIG_USB_GSPCA_PAC7311=m -+CONFIG_USB_GSPCA_SE401=m -+CONFIG_USB_GSPCA_SN9C2028=m -+CONFIG_USB_GSPCA_SN9C20X=m -+CONFIG_USB_GSPCA_SONIXB=m -+CONFIG_USB_GSPCA_SONIXJ=m -+CONFIG_USB_GSPCA_SPCA500=m -+CONFIG_USB_GSPCA_SPCA501=m -+CONFIG_USB_GSPCA_SPCA505=m -+CONFIG_USB_GSPCA_SPCA506=m -+CONFIG_USB_GSPCA_SPCA508=m -+CONFIG_USB_GSPCA_SPCA561=m -+CONFIG_USB_GSPCA_SPCA1528=m -+CONFIG_USB_GSPCA_SQ905=m -+CONFIG_USB_GSPCA_SQ905C=m -+CONFIG_USB_GSPCA_SQ930X=m -+CONFIG_USB_GSPCA_STK014=m -+CONFIG_USB_GSPCA_STK1135=m -+CONFIG_USB_GSPCA_STV0680=m -+CONFIG_USB_GSPCA_SUNPLUS=m -+CONFIG_USB_GSPCA_T613=m -+CONFIG_USB_GSPCA_TOPRO=m -+CONFIG_USB_GSPCA_TV8532=m -+CONFIG_USB_GSPCA_VC032X=m -+CONFIG_USB_GSPCA_VICAM=m -+CONFIG_USB_GSPCA_XIRLINK_CIT=m -+CONFIG_USB_GSPCA_ZC3XX=m -+CONFIG_USB_PWC=m -+CONFIG_VIDEO_CPIA2=m -+CONFIG_USB_ZR364XX=m -+CONFIG_USB_STKWEBCAM=m -+CONFIG_USB_S2255=m -+CONFIG_VIDEO_USBTV=m -+CONFIG_VIDEO_PVRUSB2=m -+CONFIG_VIDEO_HDPVR=m -+CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160_COMMON=m -+CONFIG_VIDEO_STK1160_AC97=y -+CONFIG_VIDEO_GO7007=m -+CONFIG_VIDEO_GO7007_USB=m -+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m -+CONFIG_VIDEO_AU0828=m -+CONFIG_VIDEO_AU0828_RC=y -+CONFIG_VIDEO_CX231XX=m -+CONFIG_VIDEO_CX231XX_ALSA=m -+CONFIG_VIDEO_CX231XX_DVB=m -+CONFIG_VIDEO_TM6000=m -+CONFIG_VIDEO_TM6000_ALSA=m -+CONFIG_VIDEO_TM6000_DVB=m -+CONFIG_DVB_USB=m -+CONFIG_DVB_USB_A800=m -+CONFIG_DVB_USB_DIBUSB_MB=m -+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y -+CONFIG_DVB_USB_DIBUSB_MC=m -+CONFIG_DVB_USB_DIB0700=m -+CONFIG_DVB_USB_UMT_010=m -+CONFIG_DVB_USB_CXUSB=m -+CONFIG_DVB_USB_M920X=m -+CONFIG_DVB_USB_DIGITV=m -+CONFIG_DVB_USB_VP7045=m -+CONFIG_DVB_USB_VP702X=m -+CONFIG_DVB_USB_GP8PSK=m -+CONFIG_DVB_USB_NOVA_T_USB2=m -+CONFIG_DVB_USB_TTUSB2=m -+CONFIG_DVB_USB_DTT200U=m -+CONFIG_DVB_USB_OPERA1=m -+CONFIG_DVB_USB_AF9005=m -+CONFIG_DVB_USB_AF9005_REMOTE=m -+CONFIG_DVB_USB_PCTV452E=m -+CONFIG_DVB_USB_DW2102=m -+CONFIG_DVB_USB_CINERGY_T2=m -+CONFIG_DVB_USB_DTV5100=m -+CONFIG_DVB_USB_FRIIO=m -+CONFIG_DVB_USB_AZ6027=m -+CONFIG_DVB_USB_TECHNISAT_USB2=m -+CONFIG_DVB_USB_V2=m -+CONFIG_DVB_USB_AF9015=m -+CONFIG_DVB_USB_AF9035=m -+CONFIG_DVB_USB_ANYSEE=m -+CONFIG_DVB_USB_AU6610=m -+CONFIG_DVB_USB_AZ6007=m -+CONFIG_DVB_USB_CE6230=m -+CONFIG_DVB_USB_EC168=m -+CONFIG_DVB_USB_GL861=m -+CONFIG_DVB_USB_LME2510=m -+CONFIG_DVB_USB_MXL111SF=m -+CONFIG_DVB_USB_RTL28XXU=m -+CONFIG_DVB_USB_DVBSKY=m -+CONFIG_SMS_USB_DRV=m -+CONFIG_DVB_B2C2_FLEXCOP_USB=m -+CONFIG_DVB_AS102=m -+CONFIG_VIDEO_EM28XX=m -+CONFIG_VIDEO_EM28XX_V4L2=m -+CONFIG_VIDEO_EM28XX_ALSA=m -+CONFIG_VIDEO_EM28XX_DVB=m -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_BCM2835=n -+CONFIG_VIDEO_BCM2835_MMAL=n -+CONFIG_RADIO_SI470X=y -+CONFIG_USB_SI470X=m -+CONFIG_I2C_SI470X=m -+CONFIG_RADIO_SI4713=m -+CONFIG_I2C_SI4713=m -+CONFIG_USB_MR800=m -+CONFIG_USB_DSBR=m -+CONFIG_RADIO_SHARK=m -+CONFIG_RADIO_SHARK2=m -+CONFIG_USB_KEENE=m -+CONFIG_USB_MA901=m -+CONFIG_RADIO_TEA5764=m -+CONFIG_RADIO_SAA7706H=m -+CONFIG_RADIO_TEF6862=m -+CONFIG_RADIO_WL1273=m -+CONFIG_RADIO_WL128X=m -+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -+CONFIG_VIDEO_UDA1342=m -+CONFIG_VIDEO_SONY_BTF_MPX=m -+CONFIG_VIDEO_TVP5150=m -+CONFIG_VIDEO_TW2804=m -+CONFIG_VIDEO_TW9903=m -+CONFIG_VIDEO_TW9906=m -+CONFIG_VIDEO_OV7640=m -+CONFIG_VIDEO_MT9V011=m -+CONFIG_DRM=m -+CONFIG_DRM_LOAD_EDID_FIRMWARE=y -+CONFIG_DRM_UDL=m -+CONFIG_DRM_VC4=m -+CONFIG_FB=y -+CONFIG_FB_BCM2708=y -+CONFIG_FB_UDL=m -+CONFIG_FB_SSD1307=m -+CONFIG_FB_RPISENSE=m -+# CONFIG_BACKLIGHT_GENERIC is not set -+CONFIG_BACKLIGHT_RPI=m -+CONFIG_BACKLIGHT_GPIO=m -+CONFIG_FRAMEBUFFER_CONSOLE=y -+CONFIG_LOGO=y -+# CONFIG_LOGO_LINUX_MONO is not set -+# CONFIG_LOGO_LINUX_VGA16 is not set -+CONFIG_SOUND=y -+CONFIG_SND=m -+CONFIG_SND_SEQUENCER=m -+CONFIG_SND_SEQ_DUMMY=m -+CONFIG_SND_MIXER_OSS=m -+CONFIG_SND_PCM_OSS=m -+CONFIG_SND_SEQUENCER_OSS=y -+CONFIG_SND_HRTIMER=m -+CONFIG_SND_DUMMY=m -+CONFIG_SND_ALOOP=m -+CONFIG_SND_VIRMIDI=m -+CONFIG_SND_MTPAV=m -+CONFIG_SND_SERIAL_U16550=m -+CONFIG_SND_MPU401=m -+CONFIG_SND_ARM=n -+CONFIG_SND_BCM2835=n -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_USB_UA101=m -+CONFIG_SND_USB_CAIAQ=m -+CONFIG_SND_USB_CAIAQ_INPUT=y -+CONFIG_SND_USB_6FIRE=m -+CONFIG_SND_SOC=m -+CONFIG_SND_BCM2835_SOC_I2S=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_DAC=m -+CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m -+CONFIG_SND_BCM2708_SOC_RASPIDAC3=m -+CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m -+CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m -+CONFIG_SND_DIGIDAC1_SOUNDCARD=m -+CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m -+CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_WM8804_I2C=m -+CONFIG_SND_SIMPLE_CARD=m -+CONFIG_SOUND_PRIME=m -+CONFIG_HIDRAW=y -+CONFIG_UHID=m -+CONFIG_HID_A4TECH=m -+CONFIG_HID_ACRUX=m -+CONFIG_HID_APPLE=m -+CONFIG_HID_BELKIN=m -+CONFIG_HID_BETOP_FF=m -+CONFIG_HID_CHERRY=m -+CONFIG_HID_CHICONY=m -+CONFIG_HID_CYPRESS=m -+CONFIG_HID_DRAGONRISE=m -+CONFIG_HID_EMS_FF=m -+CONFIG_HID_ELECOM=m -+CONFIG_HID_ELO=m -+CONFIG_HID_EZKEY=m -+CONFIG_HID_GEMBIRD=m -+CONFIG_HID_HOLTEK=m -+CONFIG_HID_KEYTOUCH=m -+CONFIG_HID_KYE=m -+CONFIG_HID_UCLOGIC=m -+CONFIG_HID_WALTOP=m -+CONFIG_HID_GYRATION=m -+CONFIG_HID_TWINHAN=m -+CONFIG_HID_KENSINGTON=m -+CONFIG_HID_LCPOWER=m -+CONFIG_HID_LOGITECH=m -+CONFIG_HID_LOGITECH_DJ=m -+CONFIG_LOGITECH_FF=y -+CONFIG_LOGIRUMBLEPAD2_FF=y -+CONFIG_LOGIG940_FF=y -+CONFIG_HID_MAGICMOUSE=m -+CONFIG_HID_MICROSOFT=m -+CONFIG_HID_MONTEREY=m -+CONFIG_HID_MULTITOUCH=m -+CONFIG_HID_NTRIG=m -+CONFIG_HID_ORTEK=m -+CONFIG_HID_PANTHERLORD=m -+CONFIG_HID_PETALYNX=m -+CONFIG_HID_PICOLCD=m -+CONFIG_HID_ROCCAT=m -+CONFIG_HID_SAMSUNG=m -+CONFIG_HID_SONY=m -+CONFIG_HID_SPEEDLINK=m -+CONFIG_HID_SUNPLUS=m -+CONFIG_HID_GREENASIA=m -+CONFIG_HID_SMARTJOYPLUS=m -+CONFIG_HID_TOPSEED=m -+CONFIG_HID_THINGM=m -+CONFIG_HID_THRUSTMASTER=m -+CONFIG_HID_WACOM=m -+CONFIG_HID_WIIMOTE=m -+CONFIG_HID_XINMO=m -+CONFIG_HID_ZEROPLUS=m -+CONFIG_HID_ZYDACRON=m -+CONFIG_HID_PID=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB=y -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+CONFIG_USB_MON=m -+CONFIG_USB_DWCOTG=n -+CONFIG_USB_DWC2=y -+CONFIG_USB_PRINTER=m -+CONFIG_USB_STORAGE=y -+CONFIG_USB_STORAGE_REALTEK=m -+CONFIG_USB_STORAGE_DATAFAB=m -+CONFIG_USB_STORAGE_FREECOM=m -+CONFIG_USB_STORAGE_ISD200=m -+CONFIG_USB_STORAGE_USBAT=m -+CONFIG_USB_STORAGE_SDDR09=m -+CONFIG_USB_STORAGE_SDDR55=m -+CONFIG_USB_STORAGE_JUMPSHOT=m -+CONFIG_USB_STORAGE_ALAUDA=m -+CONFIG_USB_STORAGE_ONETOUCH=m -+CONFIG_USB_STORAGE_KARMA=m -+CONFIG_USB_STORAGE_CYPRESS_ATACB=m -+CONFIG_USB_STORAGE_ENE_UB6250=m -+CONFIG_USB_MDC800=m -+CONFIG_USB_MICROTEK=m -+CONFIG_USBIP_CORE=m -+CONFIG_USBIP_VHCI_HCD=m -+CONFIG_USBIP_HOST=m -+CONFIG_USB_SERIAL=m -+CONFIG_USB_SERIAL_GENERIC=y -+CONFIG_USB_SERIAL_AIRCABLE=m -+CONFIG_USB_SERIAL_ARK3116=m -+CONFIG_USB_SERIAL_BELKIN=m -+CONFIG_USB_SERIAL_CH341=m -+CONFIG_USB_SERIAL_WHITEHEAT=m -+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -+CONFIG_USB_SERIAL_CP210X=m -+CONFIG_USB_SERIAL_CYPRESS_M8=m -+CONFIG_USB_SERIAL_EMPEG=m -+CONFIG_USB_SERIAL_FTDI_SIO=m -+CONFIG_USB_SERIAL_VISOR=m -+CONFIG_USB_SERIAL_IPAQ=m -+CONFIG_USB_SERIAL_IR=m -+CONFIG_USB_SERIAL_EDGEPORT=m -+CONFIG_USB_SERIAL_EDGEPORT_TI=m -+CONFIG_USB_SERIAL_F81232=m -+CONFIG_USB_SERIAL_GARMIN=m -+CONFIG_USB_SERIAL_IPW=m -+CONFIG_USB_SERIAL_IUU=m -+CONFIG_USB_SERIAL_KEYSPAN_PDA=m -+CONFIG_USB_SERIAL_KEYSPAN=m -+CONFIG_USB_SERIAL_KLSI=m -+CONFIG_USB_SERIAL_KOBIL_SCT=m -+CONFIG_USB_SERIAL_MCT_U232=m -+CONFIG_USB_SERIAL_METRO=m -+CONFIG_USB_SERIAL_MOS7720=m -+CONFIG_USB_SERIAL_MOS7840=m -+CONFIG_USB_SERIAL_NAVMAN=m -+CONFIG_USB_SERIAL_PL2303=m -+CONFIG_USB_SERIAL_OTI6858=m -+CONFIG_USB_SERIAL_QCAUX=m -+CONFIG_USB_SERIAL_QUALCOMM=m -+CONFIG_USB_SERIAL_SPCP8X5=m -+CONFIG_USB_SERIAL_SAFE=m -+CONFIG_USB_SERIAL_SIERRAWIRELESS=m -+CONFIG_USB_SERIAL_SYMBOL=m -+CONFIG_USB_SERIAL_TI=m -+CONFIG_USB_SERIAL_CYBERJACK=m -+CONFIG_USB_SERIAL_XIRCOM=m -+CONFIG_USB_SERIAL_OPTION=m -+CONFIG_USB_SERIAL_OMNINET=m -+CONFIG_USB_SERIAL_OPTICON=m -+CONFIG_USB_SERIAL_XSENS_MT=m -+CONFIG_USB_SERIAL_WISHBONE=m -+CONFIG_USB_SERIAL_SSU100=m -+CONFIG_USB_SERIAL_QT2=m -+CONFIG_USB_SERIAL_DEBUG=m -+CONFIG_USB_EMI62=m -+CONFIG_USB_EMI26=m -+CONFIG_USB_ADUTUX=m -+CONFIG_USB_SEVSEG=m -+CONFIG_USB_RIO500=m -+CONFIG_USB_LEGOTOWER=m -+CONFIG_USB_LCD=m -+CONFIG_USB_CYPRESS_CY7C63=m -+CONFIG_USB_CYTHERM=m -+CONFIG_USB_IDMOUSE=m -+CONFIG_USB_FTDI_ELAN=m -+CONFIG_USB_APPLEDISPLAY=m -+CONFIG_USB_LD=m -+CONFIG_USB_TRANCEVIBRATOR=m -+CONFIG_USB_IOWARRIOR=m -+CONFIG_USB_TEST=m -+CONFIG_USB_ISIGHTFW=m -+CONFIG_USB_YUREX=m -+CONFIG_USB_ATM=m -+CONFIG_USB_SPEEDTOUCH=m -+CONFIG_USB_CXACRU=m -+CONFIG_USB_UEAGLEATM=m -+CONFIG_USB_XUSBATM=m -+CONFIG_MMC=y -+CONFIG_MMC_BLOCK_MINORS=32 -+CONFIG_MMC_BCM2835=y -+CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SPI=m -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_GPIO=y -+CONFIG_LEDS_TRIGGER_TIMER=y -+CONFIG_LEDS_TRIGGER_ONESHOT=y -+CONFIG_LEDS_TRIGGER_HEARTBEAT=y -+CONFIG_LEDS_TRIGGER_BACKLIGHT=y -+CONFIG_LEDS_TRIGGER_CPU=y -+CONFIG_LEDS_TRIGGER_GPIO=y -+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -+CONFIG_LEDS_TRIGGER_TRANSIENT=m -+CONFIG_LEDS_TRIGGER_CAMERA=m -+CONFIG_LEDS_TRIGGER_INPUT=y -+CONFIG_LEDS_TRIGGER_PANIC=y -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_DS1307=m -+CONFIG_RTC_DRV_DS1374=m -+CONFIG_RTC_DRV_DS1672=m -+CONFIG_RTC_DRV_MAX6900=m -+CONFIG_RTC_DRV_RS5C372=m -+CONFIG_RTC_DRV_ISL1208=m -+CONFIG_RTC_DRV_ISL12022=m -+CONFIG_RTC_DRV_ISL12057=m -+CONFIG_RTC_DRV_X1205=m -+CONFIG_RTC_DRV_PCF8523=m -+CONFIG_RTC_DRV_PCF8563=m -+CONFIG_RTC_DRV_PCF8583=m -+CONFIG_RTC_DRV_M41T80=m -+CONFIG_RTC_DRV_BQ32K=m -+CONFIG_RTC_DRV_S35390A=m -+CONFIG_RTC_DRV_FM3130=m -+CONFIG_RTC_DRV_RX8581=m -+CONFIG_RTC_DRV_RX8025=m -+CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_M41T93=m -+CONFIG_RTC_DRV_M41T94=m -+CONFIG_RTC_DRV_DS1302=m -+CONFIG_RTC_DRV_DS1305=m -+CONFIG_RTC_DRV_DS1390=m -+CONFIG_RTC_DRV_R9701=m -+CONFIG_RTC_DRV_RX4581=m -+CONFIG_RTC_DRV_RS5C348=m -+CONFIG_RTC_DRV_MAX6902=m -+CONFIG_RTC_DRV_PCF2123=m -+CONFIG_RTC_DRV_DS3232=m -+CONFIG_RTC_DRV_PCF2127=m -+CONFIG_RTC_DRV_RV3029C2=m -+CONFIG_DMADEVICES=y -+CONFIG_DMA_BCM2835=y -+CONFIG_DMA_BCM2708=y -+CONFIG_UIO=m -+CONFIG_UIO_PDRV_GENIRQ=m -+CONFIG_STAGING=y -+CONFIG_PRISM2_USB=m -+CONFIG_R8712U=m -+CONFIG_R8188EU=m -+CONFIG_R8723AU=m -+CONFIG_VT6656=m -+CONFIG_SPEAKUP=m -+CONFIG_SPEAKUP_SYNTH_SOFT=m -+CONFIG_STAGING_MEDIA=y -+CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_IMON=m -+CONFIG_LIRC_RPI=m -+CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SERIAL=m -+CONFIG_FB_TFT=m -+CONFIG_FB_TFT_AGM1264K_FL=m -+CONFIG_FB_TFT_BD663474=m -+CONFIG_FB_TFT_HX8340BN=m -+CONFIG_FB_TFT_HX8347D=m -+CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_ILI9163=m -+CONFIG_FB_TFT_ILI9320=m -+CONFIG_FB_TFT_ILI9325=m -+CONFIG_FB_TFT_ILI9340=m -+CONFIG_FB_TFT_ILI9341=m -+CONFIG_FB_TFT_ILI9481=m -+CONFIG_FB_TFT_ILI9486=m -+CONFIG_FB_TFT_PCD8544=m -+CONFIG_FB_TFT_RA8875=m -+CONFIG_FB_TFT_S6D02A1=m -+CONFIG_FB_TFT_S6D1121=m -+CONFIG_FB_TFT_SSD1289=m -+CONFIG_FB_TFT_SSD1306=m -+CONFIG_FB_TFT_SSD1331=m -+CONFIG_FB_TFT_SSD1351=m -+CONFIG_FB_TFT_ST7735R=m -+CONFIG_FB_TFT_TINYLCD=m -+CONFIG_FB_TFT_TLS8204=m -+CONFIG_FB_TFT_UC1701=m -+CONFIG_FB_TFT_UPD161704=m -+CONFIG_FB_TFT_WATTEROTT=m -+CONFIG_FB_FLEX=m -+CONFIG_FB_TFT_FBTFT_DEVICE=m -+CONFIG_MAILBOX=y -+CONFIG_BCM2835_MBOX=y -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_RASPBERRYPI_POWER=y -+CONFIG_EXTCON=m -+CONFIG_EXTCON_ARIZONA=m -+CONFIG_IIO=m -+CONFIG_IIO_BUFFER=y -+CONFIG_IIO_BUFFER_CB=m -+CONFIG_IIO_KFIFO_BUF=m -+CONFIG_MCP320X=m -+CONFIG_MCP3422=m -+CONFIG_DHT11=m -+CONFIG_PWM_BCM2835=m -+CONFIG_PWM_PCA9685=m -+CONFIG_RASPBERRYPI_FIRMWARE=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_REISERFS_FS=m -+CONFIG_REISERFS_FS_XATTR=y -+CONFIG_REISERFS_FS_POSIX_ACL=y -+CONFIG_REISERFS_FS_SECURITY=y -+CONFIG_JFS_FS=m -+CONFIG_JFS_POSIX_ACL=y -+CONFIG_JFS_SECURITY=y -+CONFIG_JFS_STATISTICS=y -+CONFIG_XFS_FS=m -+CONFIG_XFS_QUOTA=y -+CONFIG_XFS_POSIX_ACL=y -+CONFIG_XFS_RT=y -+CONFIG_GFS2_FS=m -+CONFIG_OCFS2_FS=m -+CONFIG_BTRFS_FS=m -+CONFIG_BTRFS_FS_POSIX_ACL=y -+CONFIG_NILFS2_FS=m -+CONFIG_F2FS_FS=y -+CONFIG_FANOTIFY=y -+CONFIG_QFMT_V1=m -+CONFIG_QFMT_V2=m -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=m -+CONFIG_CUSE=m -+CONFIG_OVERLAY_FS=m -+CONFIG_FSCACHE=y -+CONFIG_FSCACHE_STATS=y -+CONFIG_FSCACHE_HISTOGRAM=y -+CONFIG_CACHEFILES=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -+CONFIG_NTFS_FS=m -+CONFIG_NTFS_RW=y -+CONFIG_TMPFS=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_ECRYPT_FS=m -+CONFIG_HFS_FS=m -+CONFIG_HFSPLUS_FS=m -+CONFIG_JFFS2_FS=m -+CONFIG_JFFS2_SUMMARY=y -+CONFIG_UBIFS_FS=m -+CONFIG_SQUASHFS=m -+CONFIG_SQUASHFS_XATTR=y -+CONFIG_SQUASHFS_LZO=y -+CONFIG_SQUASHFS_XZ=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_NFS_SWAP=y -+CONFIG_ROOT_NFS=y -+CONFIG_NFS_FSCACHE=y -+CONFIG_NFSD=m -+CONFIG_NFSD_V3_ACL=y -+CONFIG_NFSD_V4=y -+CONFIG_CIFS=m -+CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y -+CONFIG_CIFS_XATTR=y -+CONFIG_CIFS_POSIX=y -+CONFIG_CIFS_ACL=y -+CONFIG_CIFS_DFS_UPCALL=y -+CONFIG_CIFS_SMB2=y -+CONFIG_CIFS_FSCACHE=y -+CONFIG_9P_FS=m -+CONFIG_9P_FS_POSIX_ACL=y -+CONFIG_NLS_DEFAULT="utf8" -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_737=m -+CONFIG_NLS_CODEPAGE_775=m -+CONFIG_NLS_CODEPAGE_850=m -+CONFIG_NLS_CODEPAGE_852=m -+CONFIG_NLS_CODEPAGE_855=m -+CONFIG_NLS_CODEPAGE_857=m -+CONFIG_NLS_CODEPAGE_860=m -+CONFIG_NLS_CODEPAGE_861=m -+CONFIG_NLS_CODEPAGE_862=m -+CONFIG_NLS_CODEPAGE_863=m -+CONFIG_NLS_CODEPAGE_864=m -+CONFIG_NLS_CODEPAGE_865=m -+CONFIG_NLS_CODEPAGE_866=m -+CONFIG_NLS_CODEPAGE_869=m -+CONFIG_NLS_CODEPAGE_936=m -+CONFIG_NLS_CODEPAGE_950=m -+CONFIG_NLS_CODEPAGE_932=m -+CONFIG_NLS_CODEPAGE_949=m -+CONFIG_NLS_CODEPAGE_874=m -+CONFIG_NLS_ISO8859_8=m -+CONFIG_NLS_CODEPAGE_1250=m -+CONFIG_NLS_CODEPAGE_1251=m -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=m -+CONFIG_NLS_ISO8859_2=m -+CONFIG_NLS_ISO8859_3=m -+CONFIG_NLS_ISO8859_4=m -+CONFIG_NLS_ISO8859_5=m -+CONFIG_NLS_ISO8859_6=m -+CONFIG_NLS_ISO8859_7=m -+CONFIG_NLS_ISO8859_9=m -+CONFIG_NLS_ISO8859_13=m -+CONFIG_NLS_ISO8859_14=m -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_KOI8_R=m -+CONFIG_NLS_KOI8_U=m -+CONFIG_DLM=m -+CONFIG_PRINTK_TIME=y -+CONFIG_BOOT_PRINTK_DELAY=y -+CONFIG_DEBUG_MEMORY_INIT=y -+CONFIG_DETECT_HUNG_TASK=y -+CONFIG_TIMER_STATS=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+# CONFIG_KPROBE_EVENT is not set -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_KGDB=y -+CONFIG_KGDB_KDB=y -+CONFIG_KDB_KEYBOARD=y -+CONFIG_CRYPTO_USER=m -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=m -+CONFIG_CRYPTO_XTS=m -+CONFIG_CRYPTO_XCBC=m -+CONFIG_CRYPTO_TGR192=m -+CONFIG_CRYPTO_WP512=m -+CONFIG_CRYPTO_CAST5=m -+CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_USER_API_SKCIPHER=m -+CONFIG_ARM64_CRYPTO=y -+CONFIG_CRC_ITU_T=y -+CONFIG_LIBCRC32C=y -+CONFIG_BCM2708_VCHIQ=n diff --git a/target/linux/brcm2708/patches-4.9/0095-vchiq_arm-Tweak-the-logging-output.patch b/target/linux/brcm2708/patches-4.9/0095-vchiq_arm-Tweak-the-logging-output.patch new file mode 100644 index 0000000000..ef3c97ddc3 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0095-vchiq_arm-Tweak-the-logging-output.patch @@ -0,0 +1,75 @@ +From 60486e8778192830c0e5369d4f05954c1f7cc12c Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 7 Mar 2016 15:05:11 +0000 +Subject: [PATCH] vchiq_arm: Tweak the logging output + +Signed-off-by: Phil Elwell +--- + .../vc04_services/interface/vchiq_arm/vchiq_core.c | 31 +++++++++------------- + 1 file changed, 13 insertions(+), 18 deletions(-) + +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +@@ -891,16 +891,14 @@ queue_message(VCHIQ_STATE_T *state, VCHI + error_count); + return VCHIQ_ERROR; + } +- if (i == 0) { +- if (SRVTRACE_ENABLED(service, +- VCHIQ_LOG_INFO)) +- vchiq_log_dump_mem("Sent", 0, +- header->data + pos, +- min(64u, +- elements[0].size)); +- } + } + ++ if (SRVTRACE_ENABLED(service, ++ VCHIQ_LOG_INFO)) ++ vchiq_log_dump_mem("Sent", 0, ++ header->data, ++ min(16, pos)); ++ + spin_lock("a_spinlock); + service_quota->message_use_count++; + +@@ -1039,16 +1037,13 @@ queue_message_sync(VCHIQ_STATE_T *state, + error_count); + return VCHIQ_ERROR; + } +- if (i == 0) { +- if (vchiq_sync_log_level >= +- VCHIQ_LOG_TRACE) +- vchiq_log_dump_mem("Sent Sync", +- 0, header->data + pos, +- min(64u, +- elements[0].size)); +- } + } + ++ if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) ++ vchiq_log_dump_mem("Sent Sync", ++ 0, header->data, ++ min(16, pos)); ++ + VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); + VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); + } else { +@@ -1720,7 +1715,7 @@ parse_rx_slots(VCHIQ_STATE_T *state) + remoteport, localport, size); + if (size > 0) + vchiq_log_dump_mem("Rcvd", 0, header->data, +- min(64, size)); ++ min(16, size)); + } + + if (((unsigned int)header & VCHIQ_SLOT_MASK) + calc_stride(size) +@@ -2187,7 +2182,7 @@ sync_func(void *v) + remoteport, localport, size); + if (size > 0) + vchiq_log_dump_mem("Rcvd", 0, header->data, +- min(64, size)); ++ min(16, size)); + } + + switch (type) { diff --git a/target/linux/brcm2708/patches-4.9/0096-vchiq_arm-Access-the-dequeue_pending-flag-locked.patch b/target/linux/brcm2708/patches-4.9/0096-vchiq_arm-Access-the-dequeue_pending-flag-locked.patch new file mode 100644 index 0000000000..71c0e304dd --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0096-vchiq_arm-Access-the-dequeue_pending-flag-locked.patch @@ -0,0 +1,58 @@ +From 64e39b18b8d51eb332a84ef79ed3ce0dd2a76808 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 23 Mar 2016 14:16:25 +0000 +Subject: [PATCH] vchiq_arm: Access the dequeue_pending flag locked + +Reading through this code looking for another problem (now found in userland) +the use of dequeue_pending outside a lock didn't seem safe. + +Signed-off-by: Phil Elwell +--- + .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -279,6 +279,7 @@ service_callback(VCHIQ_REASON_T reason, + USER_SERVICE_T *user_service; + VCHIQ_SERVICE_T *service; + VCHIQ_INSTANCE_T instance; ++ int skip_completion = 0; + DEBUG_INITIALISE(g_state.local) + + DEBUG_TRACE(SERVICE_CALLBACK_LINE); +@@ -345,9 +346,6 @@ service_callback(VCHIQ_REASON_T reason, + user_service->msg_queue[user_service->msg_insert & + (MSG_QUEUE_SIZE - 1)] = header; + user_service->msg_insert++; +- spin_unlock(&msg_queue_spinlock); +- +- up(&user_service->insert_event); + + /* If there is a thread waiting in DEQUEUE_MESSAGE, or if + ** there is a MESSAGE_AVAILABLE in the completion queue then +@@ -356,13 +354,22 @@ service_callback(VCHIQ_REASON_T reason, + if (((user_service->message_available_pos - + instance->completion_remove) >= 0) || + user_service->dequeue_pending) { +- DEBUG_TRACE(SERVICE_CALLBACK_LINE); + user_service->dequeue_pending = 0; +- return VCHIQ_SUCCESS; ++ skip_completion = 1; + } + ++ spin_unlock(&msg_queue_spinlock); ++ ++ up(&user_service->insert_event); ++ + header = NULL; + } ++ ++ if (skip_completion) { ++ DEBUG_TRACE(SERVICE_CALLBACK_LINE); ++ return VCHIQ_SUCCESS; ++ } ++ + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + + return add_completion(instance, reason, header, user_service, diff --git a/target/linux/brcm2708/patches-4.9/0096-vchiq_arm-Tweak-the-logging-output.patch b/target/linux/brcm2708/patches-4.9/0096-vchiq_arm-Tweak-the-logging-output.patch deleted file mode 100644 index 294689bcf9..0000000000 --- a/target/linux/brcm2708/patches-4.9/0096-vchiq_arm-Tweak-the-logging-output.patch +++ /dev/null @@ -1,75 +0,0 @@ -From c5a316c09e241260f6131e0dc968209b053fcd56 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 7 Mar 2016 15:05:11 +0000 -Subject: [PATCH] vchiq_arm: Tweak the logging output - -Signed-off-by: Phil Elwell ---- - .../vc04_services/interface/vchiq_arm/vchiq_core.c | 31 +++++++++------------- - 1 file changed, 13 insertions(+), 18 deletions(-) - ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c -@@ -891,16 +891,14 @@ queue_message(VCHIQ_STATE_T *state, VCHI - error_count); - return VCHIQ_ERROR; - } -- if (i == 0) { -- if (SRVTRACE_ENABLED(service, -- VCHIQ_LOG_INFO)) -- vchiq_log_dump_mem("Sent", 0, -- header->data + pos, -- min(64u, -- elements[0].size)); -- } - } - -+ if (SRVTRACE_ENABLED(service, -+ VCHIQ_LOG_INFO)) -+ vchiq_log_dump_mem("Sent", 0, -+ header->data, -+ min(16, pos)); -+ - spin_lock("a_spinlock); - service_quota->message_use_count++; - -@@ -1039,16 +1037,13 @@ queue_message_sync(VCHIQ_STATE_T *state, - error_count); - return VCHIQ_ERROR; - } -- if (i == 0) { -- if (vchiq_sync_log_level >= -- VCHIQ_LOG_TRACE) -- vchiq_log_dump_mem("Sent Sync", -- 0, header->data + pos, -- min(64u, -- elements[0].size)); -- } - } - -+ if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) -+ vchiq_log_dump_mem("Sent Sync", -+ 0, header->data, -+ min(16, pos)); -+ - VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); - VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); - } else { -@@ -1720,7 +1715,7 @@ parse_rx_slots(VCHIQ_STATE_T *state) - remoteport, localport, size); - if (size > 0) - vchiq_log_dump_mem("Rcvd", 0, header->data, -- min(64, size)); -+ min(16, size)); - } - - if (((unsigned int)header & VCHIQ_SLOT_MASK) + calc_stride(size) -@@ -2187,7 +2182,7 @@ sync_func(void *v) - remoteport, localport, size); - if (size > 0) - vchiq_log_dump_mem("Rcvd", 0, header->data, -- min(64, size)); -+ min(16, size)); - } - - switch (type) { diff --git a/target/linux/brcm2708/patches-4.9/0097-vchiq_arm-Access-the-dequeue_pending-flag-locked.patch b/target/linux/brcm2708/patches-4.9/0097-vchiq_arm-Access-the-dequeue_pending-flag-locked.patch deleted file mode 100644 index fef600b8b6..0000000000 --- a/target/linux/brcm2708/patches-4.9/0097-vchiq_arm-Access-the-dequeue_pending-flag-locked.patch +++ /dev/null @@ -1,58 +0,0 @@ -From c451a1169c71ef984e367a81d619a7089dfb14e0 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 23 Mar 2016 14:16:25 +0000 -Subject: [PATCH] vchiq_arm: Access the dequeue_pending flag locked - -Reading through this code looking for another problem (now found in userland) -the use of dequeue_pending outside a lock didn't seem safe. - -Signed-off-by: Phil Elwell ---- - .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 17 ++++++++++++----- - 1 file changed, 12 insertions(+), 5 deletions(-) - ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -279,6 +279,7 @@ service_callback(VCHIQ_REASON_T reason, - USER_SERVICE_T *user_service; - VCHIQ_SERVICE_T *service; - VCHIQ_INSTANCE_T instance; -+ int skip_completion = 0; - DEBUG_INITIALISE(g_state.local) - - DEBUG_TRACE(SERVICE_CALLBACK_LINE); -@@ -345,9 +346,6 @@ service_callback(VCHIQ_REASON_T reason, - user_service->msg_queue[user_service->msg_insert & - (MSG_QUEUE_SIZE - 1)] = header; - user_service->msg_insert++; -- spin_unlock(&msg_queue_spinlock); -- -- up(&user_service->insert_event); - - /* If there is a thread waiting in DEQUEUE_MESSAGE, or if - ** there is a MESSAGE_AVAILABLE in the completion queue then -@@ -356,13 +354,22 @@ service_callback(VCHIQ_REASON_T reason, - if (((user_service->message_available_pos - - instance->completion_remove) >= 0) || - user_service->dequeue_pending) { -- DEBUG_TRACE(SERVICE_CALLBACK_LINE); - user_service->dequeue_pending = 0; -- return VCHIQ_SUCCESS; -+ skip_completion = 1; - } - -+ spin_unlock(&msg_queue_spinlock); -+ -+ up(&user_service->insert_event); -+ - header = NULL; - } -+ -+ if (skip_completion) { -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ return VCHIQ_SUCCESS; -+ } -+ - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - - return add_completion(instance, reason, header, user_service, diff --git a/target/linux/brcm2708/patches-4.9/0097-vchiq_arm-Service-callbacks-must-not-fail.patch b/target/linux/brcm2708/patches-4.9/0097-vchiq_arm-Service-callbacks-must-not-fail.patch new file mode 100644 index 0000000000..f60af85307 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0097-vchiq_arm-Service-callbacks-must-not-fail.patch @@ -0,0 +1,26 @@ +From e518e4dcd42f5a9e3b32a3a54c258320c4752d7e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 23 Mar 2016 20:53:47 +0000 +Subject: [PATCH] vchiq_arm: Service callbacks must not fail + +Service callbacks are not allowed to return an error. The internal callback +that delivers events and messages to user tasks does not enqueue them if +the service is closing, but this is not an error and should not be +reported as such. + +Signed-off-by: Phil Elwell +--- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -224,7 +224,7 @@ add_completion(VCHIQ_INSTANCE_T instance + } else if (instance->closing) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); +- return VCHIQ_ERROR; ++ return VCHIQ_SUCCESS; + } + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + } diff --git a/target/linux/brcm2708/patches-4.9/0098-vchiq_arm-Add-completion-records-under-the-mutex.patch b/target/linux/brcm2708/patches-4.9/0098-vchiq_arm-Add-completion-records-under-the-mutex.patch new file mode 100644 index 0000000000..1b8647e86a --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0098-vchiq_arm-Add-completion-records-under-the-mutex.patch @@ -0,0 +1,63 @@ +From 152fc9447942bad4e2c6c1e6b86fd252689cc596 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 21 Apr 2016 13:49:32 +0100 +Subject: [PATCH] vchiq_arm: Add completion records under the mutex + +An issue was observed when flushing openmax components +which generate a large number of messages returning +buffers to host. + +We occasionally found a duplicate message from 16 +messages prior, resulting in a buffer returned twice. + +While only one thread adds completions, without the +mutex you don't get the protection of the automatic +memory barrier you get with synchronisation objects. + +Signed-off-by: Phil Elwell +--- + .../staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -210,6 +210,8 @@ add_completion(VCHIQ_INSTANCE_T instance + VCHIQ_COMPLETION_DATA_T *completion; + DEBUG_INITIALISE(g_state.local) + ++ mutex_lock(&instance->completion_mutex); ++ + while (instance->completion_insert == + (instance->completion_remove + MAX_COMPLETIONS)) { + /* Out of space - wait for the client */ +@@ -217,11 +219,17 @@ add_completion(VCHIQ_INSTANCE_T instance + vchiq_log_trace(vchiq_arm_log_level, + "add_completion - completion queue full"); + DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); ++ ++ mutex_unlock(&instance->completion_mutex); + if (down_interruptible(&instance->remove_event) != 0) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback interrupted"); + return VCHIQ_RETRY; +- } else if (instance->closing) { ++ } ++ ++ mutex_lock(&instance->completion_mutex); ++ if (instance->closing) { ++ mutex_unlock(&instance->completion_mutex); + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); + return VCHIQ_SUCCESS; +@@ -254,8 +262,11 @@ add_completion(VCHIQ_INSTANCE_T instance + if (reason == VCHIQ_MESSAGE_AVAILABLE) + user_service->message_available_pos = + instance->completion_insert; ++ + instance->completion_insert++; + ++ mutex_unlock(&instance->completion_mutex); ++ + up(&instance->insert_event); + + return VCHIQ_SUCCESS; diff --git a/target/linux/brcm2708/patches-4.9/0098-vchiq_arm-Service-callbacks-must-not-fail.patch b/target/linux/brcm2708/patches-4.9/0098-vchiq_arm-Service-callbacks-must-not-fail.patch deleted file mode 100644 index 1f30478d98..0000000000 --- a/target/linux/brcm2708/patches-4.9/0098-vchiq_arm-Service-callbacks-must-not-fail.patch +++ /dev/null @@ -1,26 +0,0 @@ -From db2437c557a5095022610b672c066aa2c16a684d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 23 Mar 2016 20:53:47 +0000 -Subject: [PATCH] vchiq_arm: Service callbacks must not fail - -Service callbacks are not allowed to return an error. The internal callback -that delivers events and messages to user tasks does not enqueue them if -the service is closing, but this is not an error and should not be -reported as such. - -Signed-off-by: Phil Elwell ---- - drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -224,7 +224,7 @@ add_completion(VCHIQ_INSTANCE_T instance - } else if (instance->closing) { - vchiq_log_info(vchiq_arm_log_level, - "service_callback closing"); -- return VCHIQ_ERROR; -+ return VCHIQ_SUCCESS; - } - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - } diff --git a/target/linux/brcm2708/patches-4.9/0099-vchiq_arm-Add-completion-records-under-the-mutex.patch b/target/linux/brcm2708/patches-4.9/0099-vchiq_arm-Add-completion-records-under-the-mutex.patch deleted file mode 100644 index ea1731bbfa..0000000000 --- a/target/linux/brcm2708/patches-4.9/0099-vchiq_arm-Add-completion-records-under-the-mutex.patch +++ /dev/null @@ -1,63 +0,0 @@ -From ed2a687b8fc8cd8c1154a9ae7c9fdb2e03176ed0 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 21 Apr 2016 13:49:32 +0100 -Subject: [PATCH] vchiq_arm: Add completion records under the mutex - -An issue was observed when flushing openmax components -which generate a large number of messages returning -buffers to host. - -We occasionally found a duplicate message from 16 -messages prior, resulting in a buffer returned twice. - -While only one thread adds completions, without the -mutex you don't get the protection of the automatic -memory barrier you get with synchronisation objects. - -Signed-off-by: Phil Elwell ---- - .../staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -210,6 +210,8 @@ add_completion(VCHIQ_INSTANCE_T instance - VCHIQ_COMPLETION_DATA_T *completion; - DEBUG_INITIALISE(g_state.local) - -+ mutex_lock(&instance->completion_mutex); -+ - while (instance->completion_insert == - (instance->completion_remove + MAX_COMPLETIONS)) { - /* Out of space - wait for the client */ -@@ -217,11 +219,17 @@ add_completion(VCHIQ_INSTANCE_T instance - vchiq_log_trace(vchiq_arm_log_level, - "add_completion - completion queue full"); - DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); -+ -+ mutex_unlock(&instance->completion_mutex); - if (down_interruptible(&instance->remove_event) != 0) { - vchiq_log_info(vchiq_arm_log_level, - "service_callback interrupted"); - return VCHIQ_RETRY; -- } else if (instance->closing) { -+ } -+ -+ mutex_lock(&instance->completion_mutex); -+ if (instance->closing) { -+ mutex_unlock(&instance->completion_mutex); - vchiq_log_info(vchiq_arm_log_level, - "service_callback closing"); - return VCHIQ_SUCCESS; -@@ -254,8 +262,11 @@ add_completion(VCHIQ_INSTANCE_T instance - if (reason == VCHIQ_MESSAGE_AVAILABLE) - user_service->message_available_pos = - instance->completion_insert; -+ - instance->completion_insert++; - -+ mutex_unlock(&instance->completion_mutex); -+ - up(&instance->insert_event); - - return VCHIQ_SUCCESS; diff --git a/target/linux/brcm2708/patches-4.9/0099-vchiq_arm-Avoid-use-of-mutex-in-add_completion.patch b/target/linux/brcm2708/patches-4.9/0099-vchiq_arm-Avoid-use-of-mutex-in-add_completion.patch new file mode 100644 index 0000000000..c8cc5b7837 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0099-vchiq_arm-Avoid-use-of-mutex-in-add_completion.patch @@ -0,0 +1,192 @@ +From 965475a1620ba1c4f19d6585925a40e3c749d7d1 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 20 Jun 2016 13:51:44 +0100 +Subject: [PATCH] vchiq_arm: Avoid use of mutex in add_completion + +Claiming the completion_mutex within add_completion did prevent some +messages appearing twice, but provokes a deadlock caused by vcsm using +vchiq within a page fault handler. + +Revert the use of completion_mutex, and instead fix the original +problem using more memory barriers. + +Signed-off-by: Phil Elwell +--- + .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 55 +++++++++++----------- + .../vc04_services/interface/vchiq_arm/vchiq_core.c | 14 ++++-- + 2 files changed, 37 insertions(+), 32 deletions(-) + +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -64,10 +64,10 @@ + #define VCHIQ_MINOR 0 + + /* Some per-instance constants */ +-#define MAX_COMPLETIONS 16 ++#define MAX_COMPLETIONS 128 + #define MAX_SERVICES 64 + #define MAX_ELEMENTS 8 +-#define MSG_QUEUE_SIZE 64 ++#define MSG_QUEUE_SIZE 128 + + #define KEEPALIVE_VER 1 + #define KEEPALIVE_VER_MIN KEEPALIVE_VER +@@ -208,28 +208,24 @@ add_completion(VCHIQ_INSTANCE_T instance + void *bulk_userdata) + { + VCHIQ_COMPLETION_DATA_T *completion; ++ int insert; + DEBUG_INITIALISE(g_state.local) + +- mutex_lock(&instance->completion_mutex); +- +- while (instance->completion_insert == +- (instance->completion_remove + MAX_COMPLETIONS)) { ++ insert = instance->completion_insert; ++ while ((insert - instance->completion_remove) >= MAX_COMPLETIONS) { + /* Out of space - wait for the client */ + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + vchiq_log_trace(vchiq_arm_log_level, + "add_completion - completion queue full"); + DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); + +- mutex_unlock(&instance->completion_mutex); + if (down_interruptible(&instance->remove_event) != 0) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback interrupted"); + return VCHIQ_RETRY; + } + +- mutex_lock(&instance->completion_mutex); + if (instance->closing) { +- mutex_unlock(&instance->completion_mutex); + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); + return VCHIQ_SUCCESS; +@@ -237,9 +233,7 @@ add_completion(VCHIQ_INSTANCE_T instance + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + } + +- completion = +- &instance->completions[instance->completion_insert & +- (MAX_COMPLETIONS - 1)]; ++ completion = &instance->completions[insert & (MAX_COMPLETIONS - 1)]; + + completion->header = header; + completion->reason = reason; +@@ -260,12 +254,9 @@ add_completion(VCHIQ_INSTANCE_T instance + wmb(); + + if (reason == VCHIQ_MESSAGE_AVAILABLE) +- user_service->message_available_pos = +- instance->completion_insert; +- +- instance->completion_insert++; ++ user_service->message_available_pos = insert; + +- mutex_unlock(&instance->completion_mutex); ++ instance->completion_insert = ++insert; + + up(&instance->insert_event); + +@@ -795,6 +786,7 @@ vchiq_ioctl(struct file *file, unsigned + instance->completion_insert) + && !instance->closing) { + int rc; ++ + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + mutex_unlock(&instance->completion_mutex); + rc = down_interruptible(&instance->insert_event); +@@ -809,24 +801,29 @@ vchiq_ioctl(struct file *file, unsigned + } + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + +- /* A read memory barrier is needed to stop prefetch of a stale +- ** completion record +- */ +- rmb(); +- + if (ret == 0) { + int msgbufcount = args.msgbufcount; ++ int remove; ++ ++ remove = instance->completion_remove; ++ + for (ret = 0; ret < args.count; ret++) { + VCHIQ_COMPLETION_DATA_T *completion; + VCHIQ_SERVICE_T *service; + USER_SERVICE_T *user_service; + VCHIQ_HEADER_T *header; +- if (instance->completion_remove == +- instance->completion_insert) ++ ++ if (remove == instance->completion_insert) + break; ++ + completion = &instance->completions[ +- instance->completion_remove & +- (MAX_COMPLETIONS - 1)]; ++ remove & (MAX_COMPLETIONS - 1)]; ++ ++ ++ /* A read memory barrier is needed to prevent ++ ** the prefetch of a stale completion record ++ */ ++ rmb(); + + service = completion->service_userdata; + user_service = service->base.userdata; +@@ -903,7 +900,11 @@ vchiq_ioctl(struct file *file, unsigned + break; + } + +- instance->completion_remove++; ++ /* Ensure that the above copy has completed ++ ** before advancing the remove pointer. */ ++ mb(); ++ ++ instance->completion_remove = ++remove; + } + + if (msgbufcount != args.msgbufcount) { +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +@@ -610,15 +610,15 @@ process_free_queue(VCHIQ_STATE_T *state) + BITSET_T service_found[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; + int slot_queue_available; + +- /* Use a read memory barrier to ensure that any state that may have +- ** been modified by another thread is not masked by stale prefetched +- ** values. */ +- rmb(); +- + /* Find slots which have been freed by the other side, and return them + ** to the available queue. */ + slot_queue_available = state->slot_queue_available; + ++ /* Use a memory barrier to ensure that any state that may have been ++ ** modified by another thread is not masked by stale prefetched ++ ** values. */ ++ mb(); ++ + while (slot_queue_available != local->slot_queue_recycle) { + unsigned int pos; + int slot_index = local->slot_queue[slot_queue_available++ & +@@ -626,6 +626,8 @@ process_free_queue(VCHIQ_STATE_T *state) + char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index); + int data_found = 0; + ++ rmb(); ++ + vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%x %x %x", + state->id, slot_index, (unsigned int)data, + local->slot_queue_recycle, slot_queue_available); +@@ -741,6 +743,8 @@ process_free_queue(VCHIQ_STATE_T *state) + up(&state->data_quota_event); + } + ++ mb(); ++ + state->slot_queue_available = slot_queue_available; + up(&state->slot_available_event); + } diff --git a/target/linux/brcm2708/patches-4.9/0100-staging-vchi-Convert-to-current-get_user_pages-argum.patch b/target/linux/brcm2708/patches-4.9/0100-staging-vchi-Convert-to-current-get_user_pages-argum.patch new file mode 100644 index 0000000000..e80c414633 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0100-staging-vchi-Convert-to-current-get_user_pages-argum.patch @@ -0,0 +1,34 @@ +From ec643be82b145a65d9c78d24eea7470b9bb6e0c4 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Mon, 3 Oct 2016 10:14:10 -0700 +Subject: [PATCH] staging/vchi: Convert to current get_user_pages() arguments. + +Signed-off-by: Eric Anholt +--- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 2 +- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 3 +-- + 2 files changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +@@ -420,7 +420,7 @@ create_pagelist(char __user *buf, size_t + *need_release = 0; /* do not try and release vmalloc pages */ + } else { + down_read(&task->mm->mmap_sem); +- actual_pages = get_user_pages(task, task->mm, ++ actual_pages = get_user_pages( + (unsigned long)buf & ~(PAGE_SIZE - 1), + num_pages, + (type == PAGELIST_READ) ? FOLL_WRITE : 0, +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -1492,8 +1492,7 @@ dump_phys_mem(void *virt_addr, uint32_t + } + + down_read(¤t->mm->mmap_sem); +- rc = get_user_pages(current, /* task */ +- current->mm, /* mm */ ++ rc = get_user_pages( + (unsigned long)virt_addr, /* start */ + num_pages, /* len */ + 0, /* gup_flags */ diff --git a/target/linux/brcm2708/patches-4.9/0100-vchiq_arm-Avoid-use-of-mutex-in-add_completion.patch b/target/linux/brcm2708/patches-4.9/0100-vchiq_arm-Avoid-use-of-mutex-in-add_completion.patch deleted file mode 100644 index 55d2f68a26..0000000000 --- a/target/linux/brcm2708/patches-4.9/0100-vchiq_arm-Avoid-use-of-mutex-in-add_completion.patch +++ /dev/null @@ -1,192 +0,0 @@ -From 59d2abf4834befa2d2ef8e8a37ab896df4a04868 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 20 Jun 2016 13:51:44 +0100 -Subject: [PATCH] vchiq_arm: Avoid use of mutex in add_completion - -Claiming the completion_mutex within add_completion did prevent some -messages appearing twice, but provokes a deadlock caused by vcsm using -vchiq within a page fault handler. - -Revert the use of completion_mutex, and instead fix the original -problem using more memory barriers. - -Signed-off-by: Phil Elwell ---- - .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 55 +++++++++++----------- - .../vc04_services/interface/vchiq_arm/vchiq_core.c | 14 ++++-- - 2 files changed, 37 insertions(+), 32 deletions(-) - ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -64,10 +64,10 @@ - #define VCHIQ_MINOR 0 - - /* Some per-instance constants */ --#define MAX_COMPLETIONS 16 -+#define MAX_COMPLETIONS 128 - #define MAX_SERVICES 64 - #define MAX_ELEMENTS 8 --#define MSG_QUEUE_SIZE 64 -+#define MSG_QUEUE_SIZE 128 - - #define KEEPALIVE_VER 1 - #define KEEPALIVE_VER_MIN KEEPALIVE_VER -@@ -208,28 +208,24 @@ add_completion(VCHIQ_INSTANCE_T instance - void *bulk_userdata) - { - VCHIQ_COMPLETION_DATA_T *completion; -+ int insert; - DEBUG_INITIALISE(g_state.local) - -- mutex_lock(&instance->completion_mutex); -- -- while (instance->completion_insert == -- (instance->completion_remove + MAX_COMPLETIONS)) { -+ insert = instance->completion_insert; -+ while ((insert - instance->completion_remove) >= MAX_COMPLETIONS) { - /* Out of space - wait for the client */ - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - vchiq_log_trace(vchiq_arm_log_level, - "add_completion - completion queue full"); - DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); - -- mutex_unlock(&instance->completion_mutex); - if (down_interruptible(&instance->remove_event) != 0) { - vchiq_log_info(vchiq_arm_log_level, - "service_callback interrupted"); - return VCHIQ_RETRY; - } - -- mutex_lock(&instance->completion_mutex); - if (instance->closing) { -- mutex_unlock(&instance->completion_mutex); - vchiq_log_info(vchiq_arm_log_level, - "service_callback closing"); - return VCHIQ_SUCCESS; -@@ -237,9 +233,7 @@ add_completion(VCHIQ_INSTANCE_T instance - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - } - -- completion = -- &instance->completions[instance->completion_insert & -- (MAX_COMPLETIONS - 1)]; -+ completion = &instance->completions[insert & (MAX_COMPLETIONS - 1)]; - - completion->header = header; - completion->reason = reason; -@@ -260,12 +254,9 @@ add_completion(VCHIQ_INSTANCE_T instance - wmb(); - - if (reason == VCHIQ_MESSAGE_AVAILABLE) -- user_service->message_available_pos = -- instance->completion_insert; -- -- instance->completion_insert++; -+ user_service->message_available_pos = insert; - -- mutex_unlock(&instance->completion_mutex); -+ instance->completion_insert = ++insert; - - up(&instance->insert_event); - -@@ -795,6 +786,7 @@ vchiq_ioctl(struct file *file, unsigned - instance->completion_insert) - && !instance->closing) { - int rc; -+ - DEBUG_TRACE(AWAIT_COMPLETION_LINE); - mutex_unlock(&instance->completion_mutex); - rc = down_interruptible(&instance->insert_event); -@@ -809,24 +801,29 @@ vchiq_ioctl(struct file *file, unsigned - } - DEBUG_TRACE(AWAIT_COMPLETION_LINE); - -- /* A read memory barrier is needed to stop prefetch of a stale -- ** completion record -- */ -- rmb(); -- - if (ret == 0) { - int msgbufcount = args.msgbufcount; -+ int remove; -+ -+ remove = instance->completion_remove; -+ - for (ret = 0; ret < args.count; ret++) { - VCHIQ_COMPLETION_DATA_T *completion; - VCHIQ_SERVICE_T *service; - USER_SERVICE_T *user_service; - VCHIQ_HEADER_T *header; -- if (instance->completion_remove == -- instance->completion_insert) -+ -+ if (remove == instance->completion_insert) - break; -+ - completion = &instance->completions[ -- instance->completion_remove & -- (MAX_COMPLETIONS - 1)]; -+ remove & (MAX_COMPLETIONS - 1)]; -+ -+ -+ /* A read memory barrier is needed to prevent -+ ** the prefetch of a stale completion record -+ */ -+ rmb(); - - service = completion->service_userdata; - user_service = service->base.userdata; -@@ -903,7 +900,11 @@ vchiq_ioctl(struct file *file, unsigned - break; - } - -- instance->completion_remove++; -+ /* Ensure that the above copy has completed -+ ** before advancing the remove pointer. */ -+ mb(); -+ -+ instance->completion_remove = ++remove; - } - - if (msgbufcount != args.msgbufcount) { ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c -@@ -610,15 +610,15 @@ process_free_queue(VCHIQ_STATE_T *state) - BITSET_T service_found[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; - int slot_queue_available; - -- /* Use a read memory barrier to ensure that any state that may have -- ** been modified by another thread is not masked by stale prefetched -- ** values. */ -- rmb(); -- - /* Find slots which have been freed by the other side, and return them - ** to the available queue. */ - slot_queue_available = state->slot_queue_available; - -+ /* Use a memory barrier to ensure that any state that may have been -+ ** modified by another thread is not masked by stale prefetched -+ ** values. */ -+ mb(); -+ - while (slot_queue_available != local->slot_queue_recycle) { - unsigned int pos; - int slot_index = local->slot_queue[slot_queue_available++ & -@@ -626,6 +626,8 @@ process_free_queue(VCHIQ_STATE_T *state) - char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index); - int data_found = 0; - -+ rmb(); -+ - vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%x %x %x", - state->id, slot_index, (unsigned int)data, - local->slot_queue_recycle, slot_queue_available); -@@ -741,6 +743,8 @@ process_free_queue(VCHIQ_STATE_T *state) - up(&state->data_quota_event); - } - -+ mb(); -+ - state->slot_queue_available = slot_queue_available; - up(&state->slot_available_event); - } diff --git a/target/linux/brcm2708/patches-4.9/0101-staging-vchi-Convert-to-current-get_user_pages-argum.patch b/target/linux/brcm2708/patches-4.9/0101-staging-vchi-Convert-to-current-get_user_pages-argum.patch deleted file mode 100644 index e5d9528885..0000000000 --- a/target/linux/brcm2708/patches-4.9/0101-staging-vchi-Convert-to-current-get_user_pages-argum.patch +++ /dev/null @@ -1,34 +0,0 @@ -From d2a51ea3b1f32cd7e53e20dbcd59aea48f09b1a6 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Mon, 3 Oct 2016 10:14:10 -0700 -Subject: [PATCH] staging/vchi: Convert to current get_user_pages() arguments. - -Signed-off-by: Eric Anholt ---- - drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 2 +- - drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 3 +-- - 2 files changed, 2 insertions(+), 3 deletions(-) - ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -@@ -420,7 +420,7 @@ create_pagelist(char __user *buf, size_t - *need_release = 0; /* do not try and release vmalloc pages */ - } else { - down_read(&task->mm->mmap_sem); -- actual_pages = get_user_pages(task, task->mm, -+ actual_pages = get_user_pages( - (unsigned long)buf & ~(PAGE_SIZE - 1), - num_pages, - (type == PAGELIST_READ) ? FOLL_WRITE : 0, ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -1492,8 +1492,7 @@ dump_phys_mem(void *virt_addr, uint32_t - } - - down_read(¤t->mm->mmap_sem); -- rc = get_user_pages(current, /* task */ -- current->mm, /* mm */ -+ rc = get_user_pages( - (unsigned long)virt_addr, /* start */ - num_pages, /* len */ - 0, /* gup_flags */ diff --git a/target/linux/brcm2708/patches-4.9/0101-staging-vchi-Update-for-rename-of-page_cache_release.patch b/target/linux/brcm2708/patches-4.9/0101-staging-vchi-Update-for-rename-of-page_cache_release.patch new file mode 100644 index 0000000000..eccb792ee9 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0101-staging-vchi-Update-for-rename-of-page_cache_release.patch @@ -0,0 +1,43 @@ +From 5e8386a65d2b7fd157d2a6e2f9b8ca79011976b7 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Mon, 3 Oct 2016 10:16:03 -0700 +Subject: [PATCH] staging/vchi: Update for rename of page_cache_release() to + put_page(). + +Signed-off-by: Eric Anholt +--- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 4 ++-- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +@@ -438,7 +438,7 @@ create_pagelist(char __user *buf, size_t + while (actual_pages > 0) + { + actual_pages--; +- page_cache_release(pages[actual_pages]); ++ put_page(pages[actual_pages]); + } + kfree(pagelist); + if (actual_pages == 0) +@@ -577,7 +577,7 @@ free_pagelist(PAGELIST_T *pagelist, int + offset = 0; + set_page_dirty(pg); + } +- page_cache_release(pg); ++ put_page(pg); + } + } + +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -1530,7 +1530,7 @@ dump_phys_mem(void *virt_addr, uint32_t + kunmap(page); + + for (page_idx = 0; page_idx < num_pages; page_idx++) +- page_cache_release(pages[page_idx]); ++ put_page(pages[page_idx]); + + kfree(pages); + } diff --git a/target/linux/brcm2708/patches-4.9/0102-drivers-vchi-Remove-dependency-on-CONFIG_BROKEN.patch b/target/linux/brcm2708/patches-4.9/0102-drivers-vchi-Remove-dependency-on-CONFIG_BROKEN.patch new file mode 100644 index 0000000000..8ec807e065 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0102-drivers-vchi-Remove-dependency-on-CONFIG_BROKEN.patch @@ -0,0 +1,22 @@ +From b909c0f36c535e3f3042517d1b59b9c0538cc1d0 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Mon, 3 Oct 2016 10:21:17 -0700 +Subject: [PATCH] drivers/vchi: Remove dependency on CONFIG_BROKEN. + +The driver builds now. + +Signed-off-by: Eric Anholt +--- + drivers/staging/vc04_services/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/vc04_services/Kconfig ++++ b/drivers/staging/vc04_services/Kconfig +@@ -1,6 +1,6 @@ + config BCM2708_VCHIQ + tristate "Videocore VCHIQ" +- depends on RASPBERRYPI_FIRMWARE && BROKEN ++ depends on RASPBERRYPI_FIRMWARE + default y + help + Kernel to VideoCore communication interface for the diff --git a/target/linux/brcm2708/patches-4.9/0102-staging-vchi-Update-for-rename-of-page_cache_release.patch b/target/linux/brcm2708/patches-4.9/0102-staging-vchi-Update-for-rename-of-page_cache_release.patch deleted file mode 100644 index 4be551f0ee..0000000000 --- a/target/linux/brcm2708/patches-4.9/0102-staging-vchi-Update-for-rename-of-page_cache_release.patch +++ /dev/null @@ -1,43 +0,0 @@ -From d47b4b7130260ada73a3520d43ca2df2032dc526 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Mon, 3 Oct 2016 10:16:03 -0700 -Subject: [PATCH] staging/vchi: Update for rename of page_cache_release() to - put_page(). - -Signed-off-by: Eric Anholt ---- - drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 4 ++-- - drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 2 +- - 2 files changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -@@ -438,7 +438,7 @@ create_pagelist(char __user *buf, size_t - while (actual_pages > 0) - { - actual_pages--; -- page_cache_release(pages[actual_pages]); -+ put_page(pages[actual_pages]); - } - kfree(pagelist); - if (actual_pages == 0) -@@ -577,7 +577,7 @@ free_pagelist(PAGELIST_T *pagelist, int - offset = 0; - set_page_dirty(pg); - } -- page_cache_release(pg); -+ put_page(pg); - } - } - ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -1530,7 +1530,7 @@ dump_phys_mem(void *virt_addr, uint32_t - kunmap(page); - - for (page_idx = 0; page_idx < num_pages; page_idx++) -- page_cache_release(pages[page_idx]); -+ put_page(pages[page_idx]); - - kfree(pages); - } diff --git a/target/linux/brcm2708/patches-4.9/0103-drivers-vchi-Remove-dependency-on-CONFIG_BROKEN.patch b/target/linux/brcm2708/patches-4.9/0103-drivers-vchi-Remove-dependency-on-CONFIG_BROKEN.patch deleted file mode 100644 index 52fd44aa81..0000000000 --- a/target/linux/brcm2708/patches-4.9/0103-drivers-vchi-Remove-dependency-on-CONFIG_BROKEN.patch +++ /dev/null @@ -1,22 +0,0 @@ -From b5282b49812b3f0ec18f2b998f6070b9af34edf6 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Mon, 3 Oct 2016 10:21:17 -0700 -Subject: [PATCH] drivers/vchi: Remove dependency on CONFIG_BROKEN. - -The driver builds now. - -Signed-off-by: Eric Anholt ---- - drivers/staging/vc04_services/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/staging/vc04_services/Kconfig -+++ b/drivers/staging/vc04_services/Kconfig -@@ -1,6 +1,6 @@ - config BCM2708_VCHIQ - tristate "Videocore VCHIQ" -- depends on RASPBERRYPI_FIRMWARE && BROKEN -+ depends on RASPBERRYPI_FIRMWARE - default y - help - Kernel to VideoCore communication interface for the diff --git a/target/linux/brcm2708/patches-4.9/0103-raspberrypi-firmware-Export-the-general-transaction-.patch b/target/linux/brcm2708/patches-4.9/0103-raspberrypi-firmware-Export-the-general-transaction-.patch new file mode 100644 index 0000000000..a316b409c4 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0103-raspberrypi-firmware-Export-the-general-transaction-.patch @@ -0,0 +1,42 @@ +From 34454ca8cf9b63b0973fb23271810461a45a9884 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Wed, 14 Sep 2016 09:16:19 +0100 +Subject: [PATCH] raspberrypi-firmware: Export the general transaction + function. + +The vc4-firmware-kms module is going to be doing the MBOX FB call. + +Signed-off-by: Eric Anholt +--- + drivers/firmware/raspberrypi.c | 3 ++- + include/soc/bcm2835/raspberrypi-firmware.h | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/firmware/raspberrypi.c ++++ b/drivers/firmware/raspberrypi.c +@@ -42,7 +42,7 @@ static void response_callback(struct mbo + * Sends a request to the firmware through the BCM2835 mailbox driver, + * and synchronously waits for the reply. + */ +-static int ++int + rpi_firmware_transaction(struct rpi_firmware *fw, u32 chan, u32 data) + { + u32 message = MBOX_MSG(chan, data); +@@ -63,6 +63,7 @@ rpi_firmware_transaction(struct rpi_firm + + return ret; + } ++EXPORT_SYMBOL_GPL(rpi_firmware_transaction); + + /** + * rpi_firmware_property_list - Submit firmware property list +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -131,5 +131,6 @@ int rpi_firmware_property(struct rpi_fir + int rpi_firmware_property_list(struct rpi_firmware *fw, + void *data, size_t tag_size); + struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node); ++int rpi_firmware_transaction(struct rpi_firmware *fw, u32 chan, u32 data); + + #endif /* __SOC_RASPBERRY_FIRMWARE_H__ */ diff --git a/target/linux/brcm2708/patches-4.9/0104-raspberrypi-firmware-Define-the-MBOX-channel-in-the-.patch b/target/linux/brcm2708/patches-4.9/0104-raspberrypi-firmware-Define-the-MBOX-channel-in-the-.patch new file mode 100644 index 0000000000..0b9ef71823 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0104-raspberrypi-firmware-Define-the-MBOX-channel-in-the-.patch @@ -0,0 +1,21 @@ +From bf20c77c459b00873d5862cfe7ba745a543d53de Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Wed, 14 Sep 2016 09:18:09 +0100 +Subject: [PATCH] raspberrypi-firmware: Define the MBOX channel in the header. + +Signed-off-by: Eric Anholt +--- + include/soc/bcm2835/raspberrypi-firmware.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -12,6 +12,8 @@ + #include + #include + ++#define RPI_FIRMWARE_CHAN_FB 1 ++ + struct rpi_firmware; + + enum rpi_firmware_property_status { diff --git a/target/linux/brcm2708/patches-4.9/0104-raspberrypi-firmware-Export-the-general-transaction-.patch b/target/linux/brcm2708/patches-4.9/0104-raspberrypi-firmware-Export-the-general-transaction-.patch deleted file mode 100644 index 5dc6f85e95..0000000000 --- a/target/linux/brcm2708/patches-4.9/0104-raspberrypi-firmware-Export-the-general-transaction-.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 207c380da679f31a62a1bb604dd22834d902acaf Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 14 Sep 2016 09:16:19 +0100 -Subject: [PATCH] raspberrypi-firmware: Export the general transaction - function. - -The vc4-firmware-kms module is going to be doing the MBOX FB call. - -Signed-off-by: Eric Anholt ---- - drivers/firmware/raspberrypi.c | 3 ++- - include/soc/bcm2835/raspberrypi-firmware.h | 1 + - 2 files changed, 3 insertions(+), 1 deletion(-) - ---- a/drivers/firmware/raspberrypi.c -+++ b/drivers/firmware/raspberrypi.c -@@ -42,7 +42,7 @@ static void response_callback(struct mbo - * Sends a request to the firmware through the BCM2835 mailbox driver, - * and synchronously waits for the reply. - */ --static int -+int - rpi_firmware_transaction(struct rpi_firmware *fw, u32 chan, u32 data) - { - u32 message = MBOX_MSG(chan, data); -@@ -63,6 +63,7 @@ rpi_firmware_transaction(struct rpi_firm - - return ret; - } -+EXPORT_SYMBOL_GPL(rpi_firmware_transaction); - - /** - * rpi_firmware_property_list - Submit firmware property list ---- a/include/soc/bcm2835/raspberrypi-firmware.h -+++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -131,5 +131,6 @@ int rpi_firmware_property(struct rpi_fir - int rpi_firmware_property_list(struct rpi_firmware *fw, - void *data, size_t tag_size); - struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node); -+int rpi_firmware_transaction(struct rpi_firmware *fw, u32 chan, u32 data); - - #endif /* __SOC_RASPBERRY_FIRMWARE_H__ */ diff --git a/target/linux/brcm2708/patches-4.9/0105-drm-vc4-Add-a-mode-for-using-the-closed-firmware-for.patch b/target/linux/brcm2708/patches-4.9/0105-drm-vc4-Add-a-mode-for-using-the-closed-firmware-for.patch new file mode 100644 index 0000000000..88952dc0c0 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0105-drm-vc4-Add-a-mode-for-using-the-closed-firmware-for.patch @@ -0,0 +1,758 @@ +From ffd9952ec22321af8e891aa4cf9d79d90c4b23b6 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Wed, 14 Sep 2016 08:39:33 +0100 +Subject: [PATCH] drm/vc4: Add a mode for using the closed firmware for + display. + +Signed-off-by: Eric Anholt +--- + drivers/gpu/drm/vc4/Makefile | 1 + + drivers/gpu/drm/vc4/vc4_crtc.c | 13 + + drivers/gpu/drm/vc4/vc4_drv.c | 1 + + drivers/gpu/drm/vc4/vc4_drv.h | 7 + + drivers/gpu/drm/vc4/vc4_firmware_kms.c | 660 +++++++++++++++++++++++++++++++++ + 5 files changed, 682 insertions(+) + create mode 100644 drivers/gpu/drm/vc4/vc4_firmware_kms.c + +--- a/drivers/gpu/drm/vc4/Makefile ++++ b/drivers/gpu/drm/vc4/Makefile +@@ -8,6 +8,7 @@ vc4-y := \ + vc4_crtc.o \ + vc4_drv.o \ + vc4_dpi.o \ ++ vc4_firmware_kms.o \ + vc4_kms.o \ + vc4_gem.o \ + vc4_hdmi.o \ +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -163,6 +163,9 @@ int vc4_crtc_get_scanoutpos(struct drm_d + int vblank_lines; + int ret = 0; + ++ if (vc4->firmware_kms) ++ return 0; ++ + /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ + + /* Get optional system timestamp before query. */ +@@ -656,6 +659,11 @@ int vc4_enable_vblank(struct drm_device + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_crtc *vc4_crtc = vc4->crtc[crtc_id]; + ++ if (vc4->firmware_kms) { ++ /* XXX: Can we mask the SMI interrupt? */ ++ return 0; ++ } ++ + CRTC_WRITE(PV_INTEN, PV_INT_VFP_START); + + return 0; +@@ -666,6 +674,11 @@ void vc4_disable_vblank(struct drm_devic + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_crtc *vc4_crtc = vc4->crtc[crtc_id]; + ++ if (vc4->firmware_kms) { ++ /* XXX: Can we mask the SMI interrupt? */ ++ return; ++ } ++ + CRTC_WRITE(PV_INTEN, 0); + } + +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -292,6 +292,7 @@ static struct platform_driver *const com + &vc4_dpi_driver, + &vc4_hvs_driver, + &vc4_crtc_driver, ++ &vc4_firmware_kms_driver, + &vc4_v3d_driver, + }; + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -12,6 +12,9 @@ + struct vc4_dev { + struct drm_device *dev; + ++ bool firmware_kms; ++ struct rpi_firmware *firmware; ++ + struct vc4_hdmi *hdmi; + struct vc4_hvs *hvs; + struct vc4_crtc *crtc[3]; +@@ -460,6 +463,10 @@ void __iomem *vc4_ioremap_regs(struct pl + extern struct platform_driver vc4_dpi_driver; + int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused); + ++/* vc4_firmware_kms.c */ ++extern struct platform_driver vc4_firmware_kms_driver; ++void vc4_fkms_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file); ++ + /* vc4_gem.c */ + void vc4_gem_init(struct drm_device *dev); + void vc4_gem_destroy(struct drm_device *dev); +--- /dev/null ++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c +@@ -0,0 +1,660 @@ ++/* ++ * Copyright (C) 2016 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++/** ++ * DOC: VC4 firmware KMS module. ++ * ++ * As a hack to get us from the current closed source driver world ++ * toward a totally open stack, implement KMS on top of the Raspberry ++ * Pi's firmware display stack. ++ */ ++ ++#include "drm_atomic.h" ++#include "drm_atomic_helper.h" ++#include "drm_plane_helper.h" ++#include "drm_crtc_helper.h" ++#include "linux/clk.h" ++#include "linux/debugfs.h" ++#include "drm_fb_cma_helper.h" ++#include "linux/component.h" ++#include "linux/of_device.h" ++#include "vc4_drv.h" ++#include "vc4_regs.h" ++#include ++ ++/* The firmware delivers a vblank interrupt to us through the SMI ++ * hardware, which has only this one register. ++ */ ++#define SMICS 0x0 ++#define SMICS_INTERRUPTS (BIT(9) | BIT(10) | BIT(11)) ++ ++struct vc4_crtc { ++ struct drm_crtc base; ++ struct drm_encoder *encoder; ++ struct drm_connector *connector; ++ void __iomem *regs; ++ ++ struct drm_pending_vblank_event *event; ++}; ++ ++static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc) ++{ ++ return container_of(crtc, struct vc4_crtc, base); ++} ++ ++struct vc4_fkms_encoder { ++ struct drm_encoder base; ++}; ++ ++static inline struct vc4_fkms_encoder * ++to_vc4_fkms_encoder(struct drm_encoder *encoder) ++{ ++ return container_of(encoder, struct vc4_fkms_encoder, base); ++} ++ ++/* VC4 FKMS connector KMS struct */ ++struct vc4_fkms_connector { ++ struct drm_connector base; ++ ++ /* Since the connector is attached to just the one encoder, ++ * this is the reference to it so we can do the best_encoder() ++ * hook. ++ */ ++ struct drm_encoder *encoder; ++}; ++ ++static inline struct vc4_fkms_connector * ++to_vc4_fkms_connector(struct drm_connector *connector) ++{ ++ return container_of(connector, struct vc4_fkms_connector, base); ++} ++ ++/* Firmware's structure for making an FB mbox call. */ ++struct fbinfo_s { ++ u32 xres, yres, xres_virtual, yres_virtual; ++ u32 pitch, bpp; ++ u32 xoffset, yoffset; ++ u32 base; ++ u32 screen_size; ++ u16 cmap[256]; ++}; ++ ++struct vc4_fkms_plane { ++ struct drm_plane base; ++ struct fbinfo_s *fbinfo; ++ dma_addr_t fbinfo_bus_addr; ++ u32 pitch; ++}; ++ ++static inline struct vc4_fkms_plane *to_vc4_fkms_plane(struct drm_plane *plane) ++{ ++ return (struct vc4_fkms_plane *)plane; ++} ++ ++/* Turns the display on/off. */ ++static int vc4_plane_set_primary_blank(struct drm_plane *plane, bool blank) ++{ ++ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); ++ ++ u32 packet = blank; ++ return rpi_firmware_property(vc4->firmware, ++ RPI_FIRMWARE_FRAMEBUFFER_BLANK, ++ &packet, sizeof(packet)); ++} ++ ++static void vc4_primary_plane_atomic_update(struct drm_plane *plane, ++ struct drm_plane_state *old_state) ++{ ++ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); ++ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane); ++ struct drm_plane_state *state = plane->state; ++ struct drm_framebuffer *fb = state->fb; ++ struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); ++ volatile struct fbinfo_s *fbinfo = vc4_plane->fbinfo; ++ u32 bpp = 32; ++ int ret; ++ ++ vc4_plane_set_primary_blank(plane, false); ++ ++ fbinfo->xres = state->crtc_w; ++ fbinfo->yres = state->crtc_h; ++ fbinfo->xres_virtual = state->crtc_w; ++ fbinfo->yres_virtual = state->crtc_h; ++ fbinfo->bpp = bpp; ++ fbinfo->xoffset = state->crtc_x; ++ fbinfo->yoffset = state->crtc_y; ++ fbinfo->base = bo->paddr + fb->offsets[0]; ++ fbinfo->pitch = fb->pitches[0]; ++ /* A bug in the firmware makes it so that if the fb->base is ++ * set to nonzero, the configured pitch gets overwritten with ++ * the previous pitch. So, to get the configured pitch ++ * recomputed, we have to make it allocate itself a new buffer ++ * in VC memory, first. ++ */ ++ if (vc4_plane->pitch != fb->pitches[0]) { ++ u32 saved_base = fbinfo->base; ++ fbinfo->base = 0; ++ ++ ret = rpi_firmware_transaction(vc4->firmware, ++ RPI_FIRMWARE_CHAN_FB, ++ vc4_plane->fbinfo_bus_addr); ++ fbinfo->base = saved_base; ++ ++ vc4_plane->pitch = fbinfo->pitch; ++ WARN_ON_ONCE(vc4_plane->pitch != fb->pitches[0]); ++ } ++ ++ ret = rpi_firmware_transaction(vc4->firmware, ++ RPI_FIRMWARE_CHAN_FB, ++ vc4_plane->fbinfo_bus_addr); ++ WARN_ON_ONCE(fbinfo->pitch != fb->pitches[0]); ++ WARN_ON_ONCE(fbinfo->base != bo->paddr + fb->offsets[0]); ++} ++ ++static void vc4_primary_plane_atomic_disable(struct drm_plane *plane, ++ struct drm_plane_state *old_state) ++{ ++ vc4_plane_set_primary_blank(plane, true); ++} ++ ++static void vc4_cursor_plane_atomic_update(struct drm_plane *plane, ++ struct drm_plane_state *old_state) ++{ ++ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); ++ struct drm_plane_state *state = plane->state; ++ struct drm_framebuffer *fb = state->fb; ++ struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); ++ int ret; ++ u32 packet_state[] = { true, state->crtc_x, state->crtc_y, 0 }; ++ u32 packet_info[] = { state->crtc_w, state->crtc_h, ++ 0, /* unused */ ++ bo->paddr + fb->offsets[0], ++ 0, 0, /* hotx, hoty */}; ++ WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4); ++ WARN_ON_ONCE(fb->bits_per_pixel != 32); ++ ++ ret = rpi_firmware_property(vc4->firmware, ++ RPI_FIRMWARE_SET_CURSOR_STATE, ++ &packet_state, ++ sizeof(packet_state)); ++ if (ret || packet_state[0] != 0) ++ DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]); ++ ++ ret = rpi_firmware_property(vc4->firmware, ++ RPI_FIRMWARE_SET_CURSOR_INFO, ++ &packet_info, ++ sizeof(packet_info)); ++ if (ret || packet_info[0] != 0) ++ DRM_ERROR("Failed to set cursor info: 0x%08x\n", packet_info[0]); ++} ++ ++static void vc4_cursor_plane_atomic_disable(struct drm_plane *plane, ++ struct drm_plane_state *old_state) ++{ ++ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); ++ u32 packet_state[] = { false, 0, 0, 0 }; ++ int ret; ++ ++ ret = rpi_firmware_property(vc4->firmware, ++ RPI_FIRMWARE_SET_CURSOR_STATE, ++ &packet_state, ++ sizeof(packet_state)); ++ if (ret || packet_state[0] != 0) ++ DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]); ++} ++ ++static int vc4_plane_atomic_check(struct drm_plane *plane, ++ struct drm_plane_state *state) ++{ ++ return 0; ++} ++ ++static void vc4_plane_destroy(struct drm_plane *plane) ++{ ++ drm_plane_helper_disable(plane); ++ drm_plane_cleanup(plane); ++} ++ ++static const struct drm_plane_funcs vc4_plane_funcs = { ++ .update_plane = drm_atomic_helper_update_plane, ++ .disable_plane = drm_atomic_helper_disable_plane, ++ .destroy = vc4_plane_destroy, ++ .set_property = NULL, ++ .reset = drm_atomic_helper_plane_reset, ++ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, ++}; ++ ++static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = { ++ .prepare_fb = NULL, ++ .cleanup_fb = NULL, ++ .atomic_check = vc4_plane_atomic_check, ++ .atomic_update = vc4_primary_plane_atomic_update, ++ .atomic_disable = vc4_primary_plane_atomic_disable, ++}; ++ ++static const struct drm_plane_helper_funcs vc4_cursor_plane_helper_funcs = { ++ .prepare_fb = NULL, ++ .cleanup_fb = NULL, ++ .atomic_check = vc4_plane_atomic_check, ++ .atomic_update = vc4_cursor_plane_atomic_update, ++ .atomic_disable = vc4_cursor_plane_atomic_disable, ++}; ++ ++static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev, ++ enum drm_plane_type type) ++{ ++ struct drm_plane *plane = NULL; ++ struct vc4_fkms_plane *vc4_plane; ++ u32 xrgb8888 = DRM_FORMAT_XRGB8888; ++ u32 argb8888 = DRM_FORMAT_ARGB8888; ++ int ret = 0; ++ bool primary = (type == DRM_PLANE_TYPE_PRIMARY); ++ ++ vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane), ++ GFP_KERNEL); ++ if (!vc4_plane) { ++ ret = -ENOMEM; ++ goto fail; ++ } ++ ++ plane = &vc4_plane->base; ++ ret = drm_universal_plane_init(dev, plane, 0xff, ++ &vc4_plane_funcs, ++ primary ? &xrgb8888 : &argb8888, 1, ++ type, NULL); ++ ++ if (type == DRM_PLANE_TYPE_PRIMARY) { ++ vc4_plane->fbinfo = ++ dma_alloc_coherent(dev->dev, ++ sizeof(*vc4_plane->fbinfo), ++ &vc4_plane->fbinfo_bus_addr, ++ GFP_KERNEL); ++ memset(vc4_plane->fbinfo, 0, sizeof(*vc4_plane->fbinfo)); ++ ++ drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs); ++ } else { ++ drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs); ++ } ++ ++ return plane; ++fail: ++ if (plane) ++ vc4_plane_destroy(plane); ++ ++ return ERR_PTR(ret); ++} ++ ++static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) ++{ ++ /* Everyting is handled in the planes. */ ++} ++ ++static void vc4_crtc_disable(struct drm_crtc *crtc) ++{ ++} ++ ++static void vc4_crtc_enable(struct drm_crtc *crtc) ++{ ++} ++ ++static int vc4_crtc_atomic_check(struct drm_crtc *crtc, ++ struct drm_crtc_state *state) ++{ ++ return 0; ++} ++ ++static void vc4_crtc_atomic_flush(struct drm_crtc *crtc, ++ struct drm_crtc_state *old_state) ++{ ++} ++ ++static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) ++{ ++ struct drm_crtc *crtc = &vc4_crtc->base; ++ struct drm_device *dev = crtc->dev; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev->event_lock, flags); ++ if (vc4_crtc->event) { ++ drm_crtc_send_vblank_event(crtc, vc4_crtc->event); ++ vc4_crtc->event = NULL; ++ drm_crtc_vblank_put(crtc); ++ } ++ spin_unlock_irqrestore(&dev->event_lock, flags); ++} ++ ++static irqreturn_t vc4_crtc_irq_handler(int irq, void *data) ++{ ++ struct vc4_crtc *vc4_crtc = data; ++ u32 stat = readl(vc4_crtc->regs + SMICS); ++ irqreturn_t ret = IRQ_NONE; ++ ++ if (stat & SMICS_INTERRUPTS) { ++ writel(0, vc4_crtc->regs + SMICS); ++ drm_crtc_handle_vblank(&vc4_crtc->base); ++ vc4_crtc_handle_page_flip(vc4_crtc); ++ ret = IRQ_HANDLED; ++ } ++ ++ return ret; ++} ++ ++static int vc4_page_flip(struct drm_crtc *crtc, ++ struct drm_framebuffer *fb, ++ struct drm_pending_vblank_event *event, ++ uint32_t flags) ++{ ++ if (flags & DRM_MODE_PAGE_FLIP_ASYNC) { ++ DRM_ERROR("Async flips aren't allowed\n"); ++ return -EINVAL; ++ } ++ ++ return drm_atomic_helper_page_flip(crtc, fb, event, flags); ++} ++ ++static const struct drm_crtc_funcs vc4_crtc_funcs = { ++ .set_config = drm_atomic_helper_set_config, ++ .destroy = drm_crtc_cleanup, ++ .page_flip = vc4_page_flip, ++ .set_property = NULL, ++ .cursor_set = NULL, /* handled by drm_mode_cursor_universal */ ++ .cursor_move = NULL, /* handled by drm_mode_cursor_universal */ ++ .reset = drm_atomic_helper_crtc_reset, ++ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, ++}; ++ ++static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { ++ .mode_set_nofb = vc4_crtc_mode_set_nofb, ++ .disable = vc4_crtc_disable, ++ .enable = vc4_crtc_enable, ++ .atomic_check = vc4_crtc_atomic_check, ++ .atomic_flush = vc4_crtc_atomic_flush, ++}; ++ ++/* Frees the page flip event when the DRM device is closed with the ++ * event still outstanding. ++ */ ++void vc4_fkms_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) ++{ ++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); ++ struct drm_device *dev = crtc->dev; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev->event_lock, flags); ++ ++ if (vc4_crtc->event && vc4_crtc->event->base.file_priv == file) { ++ kfree(&vc4_crtc->event->base); ++ drm_crtc_vblank_put(crtc); ++ vc4_crtc->event = NULL; ++ } ++ ++ spin_unlock_irqrestore(&dev->event_lock, flags); ++} ++ ++static const struct of_device_id vc4_firmware_kms_dt_match[] = { ++ { .compatible = "raspberrypi,rpi-firmware-kms" }, ++ {} ++}; ++ ++static enum drm_connector_status ++vc4_fkms_connector_detect(struct drm_connector *connector, bool force) ++{ ++ return connector_status_connected; ++} ++ ++static int vc4_fkms_connector_get_modes(struct drm_connector *connector) ++{ ++ struct drm_device *dev = connector->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ u32 wh[2] = {0, 0}; ++ int ret; ++ struct drm_display_mode *mode; ++ ++ ret = rpi_firmware_property(vc4->firmware, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT, ++ &wh, sizeof(wh)); ++ if (ret) { ++ DRM_ERROR("Failed to get screen size: %d (0x%08x 0x%08x)\n", ++ ret, wh[0], wh[1]); ++ return 0; ++ } ++ ++ mode = drm_cvt_mode(dev, wh[0], wh[1], 60 /* vrefresh */, ++ 0, 0, false); ++ drm_mode_probed_add(connector, mode); ++ ++ return 1; ++} ++ ++static struct drm_encoder * ++vc4_fkms_connector_best_encoder(struct drm_connector *connector) ++{ ++ struct vc4_fkms_connector *fkms_connector = ++ to_vc4_fkms_connector(connector); ++ return fkms_connector->encoder; ++} ++ ++static void vc4_fkms_connector_destroy(struct drm_connector *connector) ++{ ++ drm_connector_unregister(connector); ++ drm_connector_cleanup(connector); ++} ++ ++static const struct drm_connector_funcs vc4_fkms_connector_funcs = { ++ .dpms = drm_atomic_helper_connector_dpms, ++ .detect = vc4_fkms_connector_detect, ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .destroy = vc4_fkms_connector_destroy, ++ .reset = drm_atomic_helper_connector_reset, ++ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, ++}; ++ ++static const struct drm_connector_helper_funcs vc4_fkms_connector_helper_funcs = { ++ .get_modes = vc4_fkms_connector_get_modes, ++ .best_encoder = vc4_fkms_connector_best_encoder, ++}; ++ ++static struct drm_connector *vc4_fkms_connector_init(struct drm_device *dev, ++ struct drm_encoder *encoder) ++{ ++ struct drm_connector *connector = NULL; ++ struct vc4_fkms_connector *fkms_connector; ++ int ret = 0; ++ ++ fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector), ++ GFP_KERNEL); ++ if (!fkms_connector) { ++ ret = -ENOMEM; ++ goto fail; ++ } ++ connector = &fkms_connector->base; ++ ++ fkms_connector->encoder = encoder; ++ ++ drm_connector_init(dev, connector, &vc4_fkms_connector_funcs, ++ DRM_MODE_CONNECTOR_HDMIA); ++ drm_connector_helper_add(connector, &vc4_fkms_connector_helper_funcs); ++ ++ connector->polled = (DRM_CONNECTOR_POLL_CONNECT | ++ DRM_CONNECTOR_POLL_DISCONNECT); ++ ++ connector->interlace_allowed = 0; ++ connector->doublescan_allowed = 0; ++ ++ drm_mode_connector_attach_encoder(connector, encoder); ++ ++ return connector; ++ ++ fail: ++ if (connector) ++ vc4_fkms_connector_destroy(connector); ++ ++ return ERR_PTR(ret); ++} ++ ++static void vc4_fkms_encoder_destroy(struct drm_encoder *encoder) ++{ ++ drm_encoder_cleanup(encoder); ++} ++ ++static const struct drm_encoder_funcs vc4_fkms_encoder_funcs = { ++ .destroy = vc4_fkms_encoder_destroy, ++}; ++ ++static void vc4_fkms_encoder_enable(struct drm_encoder *encoder) ++{ ++} ++ ++static void vc4_fkms_encoder_disable(struct drm_encoder *encoder) ++{ ++} ++ ++static const struct drm_encoder_helper_funcs vc4_fkms_encoder_helper_funcs = { ++ .enable = vc4_fkms_encoder_enable, ++ .disable = vc4_fkms_encoder_disable, ++}; ++ ++static int vc4_fkms_bind(struct device *dev, struct device *master, void *data) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct drm_device *drm = dev_get_drvdata(master); ++ struct vc4_dev *vc4 = to_vc4_dev(drm); ++ struct vc4_crtc *vc4_crtc; ++ struct vc4_fkms_encoder *vc4_encoder; ++ struct drm_crtc *crtc; ++ struct drm_plane *primary_plane, *cursor_plane, *destroy_plane, *temp; ++ struct device_node *firmware_node; ++ int ret; ++ ++ vc4->firmware_kms = true; ++ ++ vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL); ++ if (!vc4_crtc) ++ return -ENOMEM; ++ crtc = &vc4_crtc->base; ++ ++ firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0); ++ vc4->firmware = rpi_firmware_get(firmware_node); ++ if (!vc4->firmware) { ++ DRM_DEBUG("Failed to get Raspberry Pi firmware reference.\n"); ++ return -EPROBE_DEFER; ++ } ++ of_node_put(firmware_node); ++ ++ /* Map the SMI interrupt reg */ ++ vc4_crtc->regs = vc4_ioremap_regs(pdev, 0); ++ if (IS_ERR(vc4_crtc->regs)) ++ return PTR_ERR(vc4_crtc->regs); ++ ++ /* For now, we create just the primary and the legacy cursor ++ * planes. We should be able to stack more planes on easily, ++ * but to do that we would need to compute the bandwidth ++ * requirement of the plane configuration, and reject ones ++ * that will take too much. ++ */ ++ primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY); ++ if (IS_ERR(primary_plane)) { ++ dev_err(dev, "failed to construct primary plane\n"); ++ ret = PTR_ERR(primary_plane); ++ goto err; ++ } ++ ++ cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR); ++ if (IS_ERR(cursor_plane)) { ++ dev_err(dev, "failed to construct cursor plane\n"); ++ ret = PTR_ERR(cursor_plane); ++ goto err; ++ } ++ ++ drm_crtc_init_with_planes(drm, crtc, primary_plane, cursor_plane, ++ &vc4_crtc_funcs, NULL); ++ drm_crtc_helper_add(crtc, &vc4_crtc_helper_funcs); ++ primary_plane->crtc = crtc; ++ cursor_plane->crtc = crtc; ++ vc4->crtc[drm_crtc_index(crtc)] = vc4_crtc; ++ ++ vc4_encoder = devm_kzalloc(dev, sizeof(*vc4_encoder), GFP_KERNEL); ++ if (!vc4_encoder) ++ return -ENOMEM; ++ vc4_crtc->encoder = &vc4_encoder->base; ++ vc4_encoder->base.possible_crtcs |= drm_crtc_mask(crtc) ; ++ drm_encoder_init(drm, &vc4_encoder->base, &vc4_fkms_encoder_funcs, ++ DRM_MODE_ENCODER_TMDS, NULL); ++ drm_encoder_helper_add(&vc4_encoder->base, ++ &vc4_fkms_encoder_helper_funcs); ++ ++ vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base); ++ if (IS_ERR(vc4_crtc->connector)) { ++ ret = PTR_ERR(vc4_crtc->connector); ++ goto err_destroy_encoder; ++ } ++ ++ writel(0, vc4_crtc->regs + SMICS); ++ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), ++ vc4_crtc_irq_handler, 0, "vc4 firmware kms", ++ vc4_crtc); ++ if (ret) ++ goto err_destroy_connector; ++ ++ platform_set_drvdata(pdev, vc4_crtc); ++ ++ return 0; ++ ++err_destroy_connector: ++ vc4_fkms_connector_destroy(vc4_crtc->connector); ++err_destroy_encoder: ++ vc4_fkms_encoder_destroy(vc4_crtc->encoder); ++ list_for_each_entry_safe(destroy_plane, temp, ++ &drm->mode_config.plane_list, head) { ++ if (destroy_plane->possible_crtcs == 1 << drm_crtc_index(crtc)) ++ destroy_plane->funcs->destroy(destroy_plane); ++ } ++err: ++ return ret; ++} ++ ++static void vc4_fkms_unbind(struct device *dev, struct device *master, ++ void *data) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct vc4_crtc *vc4_crtc = dev_get_drvdata(dev); ++ ++ vc4_fkms_connector_destroy(vc4_crtc->connector); ++ vc4_fkms_encoder_destroy(vc4_crtc->encoder); ++ drm_crtc_cleanup(&vc4_crtc->base); ++ ++ platform_set_drvdata(pdev, NULL); ++} ++ ++static const struct component_ops vc4_fkms_ops = { ++ .bind = vc4_fkms_bind, ++ .unbind = vc4_fkms_unbind, ++}; ++ ++static int vc4_fkms_probe(struct platform_device *pdev) ++{ ++ return component_add(&pdev->dev, &vc4_fkms_ops); ++} ++ ++static int vc4_fkms_remove(struct platform_device *pdev) ++{ ++ component_del(&pdev->dev, &vc4_fkms_ops); ++ return 0; ++} ++ ++struct platform_driver vc4_firmware_kms_driver = { ++ .probe = vc4_fkms_probe, ++ .remove = vc4_fkms_remove, ++ .driver = { ++ .name = "vc4_firmware_kms", ++ .of_match_table = vc4_firmware_kms_dt_match, ++ }, ++}; diff --git a/target/linux/brcm2708/patches-4.9/0105-raspberrypi-firmware-Define-the-MBOX-channel-in-the-.patch b/target/linux/brcm2708/patches-4.9/0105-raspberrypi-firmware-Define-the-MBOX-channel-in-the-.patch deleted file mode 100644 index 0909929a2f..0000000000 --- a/target/linux/brcm2708/patches-4.9/0105-raspberrypi-firmware-Define-the-MBOX-channel-in-the-.patch +++ /dev/null @@ -1,21 +0,0 @@ -From f918546b8d35b4051d79245027037492e15a7efe Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 14 Sep 2016 09:18:09 +0100 -Subject: [PATCH] raspberrypi-firmware: Define the MBOX channel in the header. - -Signed-off-by: Eric Anholt ---- - include/soc/bcm2835/raspberrypi-firmware.h | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/include/soc/bcm2835/raspberrypi-firmware.h -+++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -12,6 +12,8 @@ - #include - #include - -+#define RPI_FIRMWARE_CHAN_FB 1 -+ - struct rpi_firmware; - - enum rpi_firmware_property_status { diff --git a/target/linux/brcm2708/patches-4.9/0106-drm-vc4-Add-a-mode-for-using-the-closed-firmware-for.patch b/target/linux/brcm2708/patches-4.9/0106-drm-vc4-Add-a-mode-for-using-the-closed-firmware-for.patch deleted file mode 100644 index 3d1e684226..0000000000 --- a/target/linux/brcm2708/patches-4.9/0106-drm-vc4-Add-a-mode-for-using-the-closed-firmware-for.patch +++ /dev/null @@ -1,758 +0,0 @@ -From 12d493c17841adf193361623a64cd85804dea94f Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 14 Sep 2016 08:39:33 +0100 -Subject: [PATCH] drm/vc4: Add a mode for using the closed firmware for - display. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/Makefile | 1 + - drivers/gpu/drm/vc4/vc4_crtc.c | 13 + - drivers/gpu/drm/vc4/vc4_drv.c | 1 + - drivers/gpu/drm/vc4/vc4_drv.h | 7 + - drivers/gpu/drm/vc4/vc4_firmware_kms.c | 660 +++++++++++++++++++++++++++++++++ - 5 files changed, 682 insertions(+) - create mode 100644 drivers/gpu/drm/vc4/vc4_firmware_kms.c - ---- a/drivers/gpu/drm/vc4/Makefile -+++ b/drivers/gpu/drm/vc4/Makefile -@@ -8,6 +8,7 @@ vc4-y := \ - vc4_crtc.o \ - vc4_drv.o \ - vc4_dpi.o \ -+ vc4_firmware_kms.o \ - vc4_kms.o \ - vc4_gem.o \ - vc4_hdmi.o \ ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -163,6 +163,9 @@ int vc4_crtc_get_scanoutpos(struct drm_d - int vblank_lines; - int ret = 0; - -+ if (vc4->firmware_kms) -+ return 0; -+ - /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ - - /* Get optional system timestamp before query. */ -@@ -656,6 +659,11 @@ int vc4_enable_vblank(struct drm_device - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_crtc *vc4_crtc = vc4->crtc[crtc_id]; - -+ if (vc4->firmware_kms) { -+ /* XXX: Can we mask the SMI interrupt? */ -+ return 0; -+ } -+ - CRTC_WRITE(PV_INTEN, PV_INT_VFP_START); - - return 0; -@@ -666,6 +674,11 @@ void vc4_disable_vblank(struct drm_devic - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_crtc *vc4_crtc = vc4->crtc[crtc_id]; - -+ if (vc4->firmware_kms) { -+ /* XXX: Can we mask the SMI interrupt? */ -+ return; -+ } -+ - CRTC_WRITE(PV_INTEN, 0); - } - ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -292,6 +292,7 @@ static struct platform_driver *const com - &vc4_dpi_driver, - &vc4_hvs_driver, - &vc4_crtc_driver, -+ &vc4_firmware_kms_driver, - &vc4_v3d_driver, - }; - ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -12,6 +12,9 @@ - struct vc4_dev { - struct drm_device *dev; - -+ bool firmware_kms; -+ struct rpi_firmware *firmware; -+ - struct vc4_hdmi *hdmi; - struct vc4_hvs *hvs; - struct vc4_crtc *crtc[3]; -@@ -460,6 +463,10 @@ void __iomem *vc4_ioremap_regs(struct pl - extern struct platform_driver vc4_dpi_driver; - int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused); - -+/* vc4_firmware_kms.c */ -+extern struct platform_driver vc4_firmware_kms_driver; -+void vc4_fkms_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file); -+ - /* vc4_gem.c */ - void vc4_gem_init(struct drm_device *dev); - void vc4_gem_destroy(struct drm_device *dev); ---- /dev/null -+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c -@@ -0,0 +1,660 @@ -+/* -+ * Copyright (C) 2016 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+/** -+ * DOC: VC4 firmware KMS module. -+ * -+ * As a hack to get us from the current closed source driver world -+ * toward a totally open stack, implement KMS on top of the Raspberry -+ * Pi's firmware display stack. -+ */ -+ -+#include "drm_atomic.h" -+#include "drm_atomic_helper.h" -+#include "drm_plane_helper.h" -+#include "drm_crtc_helper.h" -+#include "linux/clk.h" -+#include "linux/debugfs.h" -+#include "drm_fb_cma_helper.h" -+#include "linux/component.h" -+#include "linux/of_device.h" -+#include "vc4_drv.h" -+#include "vc4_regs.h" -+#include -+ -+/* The firmware delivers a vblank interrupt to us through the SMI -+ * hardware, which has only this one register. -+ */ -+#define SMICS 0x0 -+#define SMICS_INTERRUPTS (BIT(9) | BIT(10) | BIT(11)) -+ -+struct vc4_crtc { -+ struct drm_crtc base; -+ struct drm_encoder *encoder; -+ struct drm_connector *connector; -+ void __iomem *regs; -+ -+ struct drm_pending_vblank_event *event; -+}; -+ -+static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc) -+{ -+ return container_of(crtc, struct vc4_crtc, base); -+} -+ -+struct vc4_fkms_encoder { -+ struct drm_encoder base; -+}; -+ -+static inline struct vc4_fkms_encoder * -+to_vc4_fkms_encoder(struct drm_encoder *encoder) -+{ -+ return container_of(encoder, struct vc4_fkms_encoder, base); -+} -+ -+/* VC4 FKMS connector KMS struct */ -+struct vc4_fkms_connector { -+ struct drm_connector base; -+ -+ /* Since the connector is attached to just the one encoder, -+ * this is the reference to it so we can do the best_encoder() -+ * hook. -+ */ -+ struct drm_encoder *encoder; -+}; -+ -+static inline struct vc4_fkms_connector * -+to_vc4_fkms_connector(struct drm_connector *connector) -+{ -+ return container_of(connector, struct vc4_fkms_connector, base); -+} -+ -+/* Firmware's structure for making an FB mbox call. */ -+struct fbinfo_s { -+ u32 xres, yres, xres_virtual, yres_virtual; -+ u32 pitch, bpp; -+ u32 xoffset, yoffset; -+ u32 base; -+ u32 screen_size; -+ u16 cmap[256]; -+}; -+ -+struct vc4_fkms_plane { -+ struct drm_plane base; -+ struct fbinfo_s *fbinfo; -+ dma_addr_t fbinfo_bus_addr; -+ u32 pitch; -+}; -+ -+static inline struct vc4_fkms_plane *to_vc4_fkms_plane(struct drm_plane *plane) -+{ -+ return (struct vc4_fkms_plane *)plane; -+} -+ -+/* Turns the display on/off. */ -+static int vc4_plane_set_primary_blank(struct drm_plane *plane, bool blank) -+{ -+ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); -+ -+ u32 packet = blank; -+ return rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_FRAMEBUFFER_BLANK, -+ &packet, sizeof(packet)); -+} -+ -+static void vc4_primary_plane_atomic_update(struct drm_plane *plane, -+ struct drm_plane_state *old_state) -+{ -+ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); -+ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane); -+ struct drm_plane_state *state = plane->state; -+ struct drm_framebuffer *fb = state->fb; -+ struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); -+ volatile struct fbinfo_s *fbinfo = vc4_plane->fbinfo; -+ u32 bpp = 32; -+ int ret; -+ -+ vc4_plane_set_primary_blank(plane, false); -+ -+ fbinfo->xres = state->crtc_w; -+ fbinfo->yres = state->crtc_h; -+ fbinfo->xres_virtual = state->crtc_w; -+ fbinfo->yres_virtual = state->crtc_h; -+ fbinfo->bpp = bpp; -+ fbinfo->xoffset = state->crtc_x; -+ fbinfo->yoffset = state->crtc_y; -+ fbinfo->base = bo->paddr + fb->offsets[0]; -+ fbinfo->pitch = fb->pitches[0]; -+ /* A bug in the firmware makes it so that if the fb->base is -+ * set to nonzero, the configured pitch gets overwritten with -+ * the previous pitch. So, to get the configured pitch -+ * recomputed, we have to make it allocate itself a new buffer -+ * in VC memory, first. -+ */ -+ if (vc4_plane->pitch != fb->pitches[0]) { -+ u32 saved_base = fbinfo->base; -+ fbinfo->base = 0; -+ -+ ret = rpi_firmware_transaction(vc4->firmware, -+ RPI_FIRMWARE_CHAN_FB, -+ vc4_plane->fbinfo_bus_addr); -+ fbinfo->base = saved_base; -+ -+ vc4_plane->pitch = fbinfo->pitch; -+ WARN_ON_ONCE(vc4_plane->pitch != fb->pitches[0]); -+ } -+ -+ ret = rpi_firmware_transaction(vc4->firmware, -+ RPI_FIRMWARE_CHAN_FB, -+ vc4_plane->fbinfo_bus_addr); -+ WARN_ON_ONCE(fbinfo->pitch != fb->pitches[0]); -+ WARN_ON_ONCE(fbinfo->base != bo->paddr + fb->offsets[0]); -+} -+ -+static void vc4_primary_plane_atomic_disable(struct drm_plane *plane, -+ struct drm_plane_state *old_state) -+{ -+ vc4_plane_set_primary_blank(plane, true); -+} -+ -+static void vc4_cursor_plane_atomic_update(struct drm_plane *plane, -+ struct drm_plane_state *old_state) -+{ -+ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); -+ struct drm_plane_state *state = plane->state; -+ struct drm_framebuffer *fb = state->fb; -+ struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); -+ int ret; -+ u32 packet_state[] = { true, state->crtc_x, state->crtc_y, 0 }; -+ u32 packet_info[] = { state->crtc_w, state->crtc_h, -+ 0, /* unused */ -+ bo->paddr + fb->offsets[0], -+ 0, 0, /* hotx, hoty */}; -+ WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4); -+ WARN_ON_ONCE(fb->bits_per_pixel != 32); -+ -+ ret = rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_SET_CURSOR_STATE, -+ &packet_state, -+ sizeof(packet_state)); -+ if (ret || packet_state[0] != 0) -+ DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]); -+ -+ ret = rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_SET_CURSOR_INFO, -+ &packet_info, -+ sizeof(packet_info)); -+ if (ret || packet_info[0] != 0) -+ DRM_ERROR("Failed to set cursor info: 0x%08x\n", packet_info[0]); -+} -+ -+static void vc4_cursor_plane_atomic_disable(struct drm_plane *plane, -+ struct drm_plane_state *old_state) -+{ -+ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); -+ u32 packet_state[] = { false, 0, 0, 0 }; -+ int ret; -+ -+ ret = rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_SET_CURSOR_STATE, -+ &packet_state, -+ sizeof(packet_state)); -+ if (ret || packet_state[0] != 0) -+ DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]); -+} -+ -+static int vc4_plane_atomic_check(struct drm_plane *plane, -+ struct drm_plane_state *state) -+{ -+ return 0; -+} -+ -+static void vc4_plane_destroy(struct drm_plane *plane) -+{ -+ drm_plane_helper_disable(plane); -+ drm_plane_cleanup(plane); -+} -+ -+static const struct drm_plane_funcs vc4_plane_funcs = { -+ .update_plane = drm_atomic_helper_update_plane, -+ .disable_plane = drm_atomic_helper_disable_plane, -+ .destroy = vc4_plane_destroy, -+ .set_property = NULL, -+ .reset = drm_atomic_helper_plane_reset, -+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, -+}; -+ -+static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = { -+ .prepare_fb = NULL, -+ .cleanup_fb = NULL, -+ .atomic_check = vc4_plane_atomic_check, -+ .atomic_update = vc4_primary_plane_atomic_update, -+ .atomic_disable = vc4_primary_plane_atomic_disable, -+}; -+ -+static const struct drm_plane_helper_funcs vc4_cursor_plane_helper_funcs = { -+ .prepare_fb = NULL, -+ .cleanup_fb = NULL, -+ .atomic_check = vc4_plane_atomic_check, -+ .atomic_update = vc4_cursor_plane_atomic_update, -+ .atomic_disable = vc4_cursor_plane_atomic_disable, -+}; -+ -+static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev, -+ enum drm_plane_type type) -+{ -+ struct drm_plane *plane = NULL; -+ struct vc4_fkms_plane *vc4_plane; -+ u32 xrgb8888 = DRM_FORMAT_XRGB8888; -+ u32 argb8888 = DRM_FORMAT_ARGB8888; -+ int ret = 0; -+ bool primary = (type == DRM_PLANE_TYPE_PRIMARY); -+ -+ vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane), -+ GFP_KERNEL); -+ if (!vc4_plane) { -+ ret = -ENOMEM; -+ goto fail; -+ } -+ -+ plane = &vc4_plane->base; -+ ret = drm_universal_plane_init(dev, plane, 0xff, -+ &vc4_plane_funcs, -+ primary ? &xrgb8888 : &argb8888, 1, -+ type, NULL); -+ -+ if (type == DRM_PLANE_TYPE_PRIMARY) { -+ vc4_plane->fbinfo = -+ dma_alloc_coherent(dev->dev, -+ sizeof(*vc4_plane->fbinfo), -+ &vc4_plane->fbinfo_bus_addr, -+ GFP_KERNEL); -+ memset(vc4_plane->fbinfo, 0, sizeof(*vc4_plane->fbinfo)); -+ -+ drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs); -+ } else { -+ drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs); -+ } -+ -+ return plane; -+fail: -+ if (plane) -+ vc4_plane_destroy(plane); -+ -+ return ERR_PTR(ret); -+} -+ -+static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) -+{ -+ /* Everyting is handled in the planes. */ -+} -+ -+static void vc4_crtc_disable(struct drm_crtc *crtc) -+{ -+} -+ -+static void vc4_crtc_enable(struct drm_crtc *crtc) -+{ -+} -+ -+static int vc4_crtc_atomic_check(struct drm_crtc *crtc, -+ struct drm_crtc_state *state) -+{ -+ return 0; -+} -+ -+static void vc4_crtc_atomic_flush(struct drm_crtc *crtc, -+ struct drm_crtc_state *old_state) -+{ -+} -+ -+static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) -+{ -+ struct drm_crtc *crtc = &vc4_crtc->base; -+ struct drm_device *dev = crtc->dev; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ if (vc4_crtc->event) { -+ drm_crtc_send_vblank_event(crtc, vc4_crtc->event); -+ vc4_crtc->event = NULL; -+ drm_crtc_vblank_put(crtc); -+ } -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+} -+ -+static irqreturn_t vc4_crtc_irq_handler(int irq, void *data) -+{ -+ struct vc4_crtc *vc4_crtc = data; -+ u32 stat = readl(vc4_crtc->regs + SMICS); -+ irqreturn_t ret = IRQ_NONE; -+ -+ if (stat & SMICS_INTERRUPTS) { -+ writel(0, vc4_crtc->regs + SMICS); -+ drm_crtc_handle_vblank(&vc4_crtc->base); -+ vc4_crtc_handle_page_flip(vc4_crtc); -+ ret = IRQ_HANDLED; -+ } -+ -+ return ret; -+} -+ -+static int vc4_page_flip(struct drm_crtc *crtc, -+ struct drm_framebuffer *fb, -+ struct drm_pending_vblank_event *event, -+ uint32_t flags) -+{ -+ if (flags & DRM_MODE_PAGE_FLIP_ASYNC) { -+ DRM_ERROR("Async flips aren't allowed\n"); -+ return -EINVAL; -+ } -+ -+ return drm_atomic_helper_page_flip(crtc, fb, event, flags); -+} -+ -+static const struct drm_crtc_funcs vc4_crtc_funcs = { -+ .set_config = drm_atomic_helper_set_config, -+ .destroy = drm_crtc_cleanup, -+ .page_flip = vc4_page_flip, -+ .set_property = NULL, -+ .cursor_set = NULL, /* handled by drm_mode_cursor_universal */ -+ .cursor_move = NULL, /* handled by drm_mode_cursor_universal */ -+ .reset = drm_atomic_helper_crtc_reset, -+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, -+}; -+ -+static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { -+ .mode_set_nofb = vc4_crtc_mode_set_nofb, -+ .disable = vc4_crtc_disable, -+ .enable = vc4_crtc_enable, -+ .atomic_check = vc4_crtc_atomic_check, -+ .atomic_flush = vc4_crtc_atomic_flush, -+}; -+ -+/* Frees the page flip event when the DRM device is closed with the -+ * event still outstanding. -+ */ -+void vc4_fkms_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) -+{ -+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); -+ struct drm_device *dev = crtc->dev; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ -+ if (vc4_crtc->event && vc4_crtc->event->base.file_priv == file) { -+ kfree(&vc4_crtc->event->base); -+ drm_crtc_vblank_put(crtc); -+ vc4_crtc->event = NULL; -+ } -+ -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+} -+ -+static const struct of_device_id vc4_firmware_kms_dt_match[] = { -+ { .compatible = "raspberrypi,rpi-firmware-kms" }, -+ {} -+}; -+ -+static enum drm_connector_status -+vc4_fkms_connector_detect(struct drm_connector *connector, bool force) -+{ -+ return connector_status_connected; -+} -+ -+static int vc4_fkms_connector_get_modes(struct drm_connector *connector) -+{ -+ struct drm_device *dev = connector->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); -+ u32 wh[2] = {0, 0}; -+ int ret; -+ struct drm_display_mode *mode; -+ -+ ret = rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT, -+ &wh, sizeof(wh)); -+ if (ret) { -+ DRM_ERROR("Failed to get screen size: %d (0x%08x 0x%08x)\n", -+ ret, wh[0], wh[1]); -+ return 0; -+ } -+ -+ mode = drm_cvt_mode(dev, wh[0], wh[1], 60 /* vrefresh */, -+ 0, 0, false); -+ drm_mode_probed_add(connector, mode); -+ -+ return 1; -+} -+ -+static struct drm_encoder * -+vc4_fkms_connector_best_encoder(struct drm_connector *connector) -+{ -+ struct vc4_fkms_connector *fkms_connector = -+ to_vc4_fkms_connector(connector); -+ return fkms_connector->encoder; -+} -+ -+static void vc4_fkms_connector_destroy(struct drm_connector *connector) -+{ -+ drm_connector_unregister(connector); -+ drm_connector_cleanup(connector); -+} -+ -+static const struct drm_connector_funcs vc4_fkms_connector_funcs = { -+ .dpms = drm_atomic_helper_connector_dpms, -+ .detect = vc4_fkms_connector_detect, -+ .fill_modes = drm_helper_probe_single_connector_modes, -+ .destroy = vc4_fkms_connector_destroy, -+ .reset = drm_atomic_helper_connector_reset, -+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -+}; -+ -+static const struct drm_connector_helper_funcs vc4_fkms_connector_helper_funcs = { -+ .get_modes = vc4_fkms_connector_get_modes, -+ .best_encoder = vc4_fkms_connector_best_encoder, -+}; -+ -+static struct drm_connector *vc4_fkms_connector_init(struct drm_device *dev, -+ struct drm_encoder *encoder) -+{ -+ struct drm_connector *connector = NULL; -+ struct vc4_fkms_connector *fkms_connector; -+ int ret = 0; -+ -+ fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector), -+ GFP_KERNEL); -+ if (!fkms_connector) { -+ ret = -ENOMEM; -+ goto fail; -+ } -+ connector = &fkms_connector->base; -+ -+ fkms_connector->encoder = encoder; -+ -+ drm_connector_init(dev, connector, &vc4_fkms_connector_funcs, -+ DRM_MODE_CONNECTOR_HDMIA); -+ drm_connector_helper_add(connector, &vc4_fkms_connector_helper_funcs); -+ -+ connector->polled = (DRM_CONNECTOR_POLL_CONNECT | -+ DRM_CONNECTOR_POLL_DISCONNECT); -+ -+ connector->interlace_allowed = 0; -+ connector->doublescan_allowed = 0; -+ -+ drm_mode_connector_attach_encoder(connector, encoder); -+ -+ return connector; -+ -+ fail: -+ if (connector) -+ vc4_fkms_connector_destroy(connector); -+ -+ return ERR_PTR(ret); -+} -+ -+static void vc4_fkms_encoder_destroy(struct drm_encoder *encoder) -+{ -+ drm_encoder_cleanup(encoder); -+} -+ -+static const struct drm_encoder_funcs vc4_fkms_encoder_funcs = { -+ .destroy = vc4_fkms_encoder_destroy, -+}; -+ -+static void vc4_fkms_encoder_enable(struct drm_encoder *encoder) -+{ -+} -+ -+static void vc4_fkms_encoder_disable(struct drm_encoder *encoder) -+{ -+} -+ -+static const struct drm_encoder_helper_funcs vc4_fkms_encoder_helper_funcs = { -+ .enable = vc4_fkms_encoder_enable, -+ .disable = vc4_fkms_encoder_disable, -+}; -+ -+static int vc4_fkms_bind(struct device *dev, struct device *master, void *data) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct drm_device *drm = dev_get_drvdata(master); -+ struct vc4_dev *vc4 = to_vc4_dev(drm); -+ struct vc4_crtc *vc4_crtc; -+ struct vc4_fkms_encoder *vc4_encoder; -+ struct drm_crtc *crtc; -+ struct drm_plane *primary_plane, *cursor_plane, *destroy_plane, *temp; -+ struct device_node *firmware_node; -+ int ret; -+ -+ vc4->firmware_kms = true; -+ -+ vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL); -+ if (!vc4_crtc) -+ return -ENOMEM; -+ crtc = &vc4_crtc->base; -+ -+ firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0); -+ vc4->firmware = rpi_firmware_get(firmware_node); -+ if (!vc4->firmware) { -+ DRM_DEBUG("Failed to get Raspberry Pi firmware reference.\n"); -+ return -EPROBE_DEFER; -+ } -+ of_node_put(firmware_node); -+ -+ /* Map the SMI interrupt reg */ -+ vc4_crtc->regs = vc4_ioremap_regs(pdev, 0); -+ if (IS_ERR(vc4_crtc->regs)) -+ return PTR_ERR(vc4_crtc->regs); -+ -+ /* For now, we create just the primary and the legacy cursor -+ * planes. We should be able to stack more planes on easily, -+ * but to do that we would need to compute the bandwidth -+ * requirement of the plane configuration, and reject ones -+ * that will take too much. -+ */ -+ primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY); -+ if (IS_ERR(primary_plane)) { -+ dev_err(dev, "failed to construct primary plane\n"); -+ ret = PTR_ERR(primary_plane); -+ goto err; -+ } -+ -+ cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR); -+ if (IS_ERR(cursor_plane)) { -+ dev_err(dev, "failed to construct cursor plane\n"); -+ ret = PTR_ERR(cursor_plane); -+ goto err; -+ } -+ -+ drm_crtc_init_with_planes(drm, crtc, primary_plane, cursor_plane, -+ &vc4_crtc_funcs, NULL); -+ drm_crtc_helper_add(crtc, &vc4_crtc_helper_funcs); -+ primary_plane->crtc = crtc; -+ cursor_plane->crtc = crtc; -+ vc4->crtc[drm_crtc_index(crtc)] = vc4_crtc; -+ -+ vc4_encoder = devm_kzalloc(dev, sizeof(*vc4_encoder), GFP_KERNEL); -+ if (!vc4_encoder) -+ return -ENOMEM; -+ vc4_crtc->encoder = &vc4_encoder->base; -+ vc4_encoder->base.possible_crtcs |= drm_crtc_mask(crtc) ; -+ drm_encoder_init(drm, &vc4_encoder->base, &vc4_fkms_encoder_funcs, -+ DRM_MODE_ENCODER_TMDS, NULL); -+ drm_encoder_helper_add(&vc4_encoder->base, -+ &vc4_fkms_encoder_helper_funcs); -+ -+ vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base); -+ if (IS_ERR(vc4_crtc->connector)) { -+ ret = PTR_ERR(vc4_crtc->connector); -+ goto err_destroy_encoder; -+ } -+ -+ writel(0, vc4_crtc->regs + SMICS); -+ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), -+ vc4_crtc_irq_handler, 0, "vc4 firmware kms", -+ vc4_crtc); -+ if (ret) -+ goto err_destroy_connector; -+ -+ platform_set_drvdata(pdev, vc4_crtc); -+ -+ return 0; -+ -+err_destroy_connector: -+ vc4_fkms_connector_destroy(vc4_crtc->connector); -+err_destroy_encoder: -+ vc4_fkms_encoder_destroy(vc4_crtc->encoder); -+ list_for_each_entry_safe(destroy_plane, temp, -+ &drm->mode_config.plane_list, head) { -+ if (destroy_plane->possible_crtcs == 1 << drm_crtc_index(crtc)) -+ destroy_plane->funcs->destroy(destroy_plane); -+ } -+err: -+ return ret; -+} -+ -+static void vc4_fkms_unbind(struct device *dev, struct device *master, -+ void *data) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct vc4_crtc *vc4_crtc = dev_get_drvdata(dev); -+ -+ vc4_fkms_connector_destroy(vc4_crtc->connector); -+ vc4_fkms_encoder_destroy(vc4_crtc->encoder); -+ drm_crtc_cleanup(&vc4_crtc->base); -+ -+ platform_set_drvdata(pdev, NULL); -+} -+ -+static const struct component_ops vc4_fkms_ops = { -+ .bind = vc4_fkms_bind, -+ .unbind = vc4_fkms_unbind, -+}; -+ -+static int vc4_fkms_probe(struct platform_device *pdev) -+{ -+ return component_add(&pdev->dev, &vc4_fkms_ops); -+} -+ -+static int vc4_fkms_remove(struct platform_device *pdev) -+{ -+ component_del(&pdev->dev, &vc4_fkms_ops); -+ return 0; -+} -+ -+struct platform_driver vc4_firmware_kms_driver = { -+ .probe = vc4_fkms_probe, -+ .remove = vc4_fkms_remove, -+ .driver = { -+ .name = "vc4_firmware_kms", -+ .of_match_table = vc4_firmware_kms_dt_match, -+ }, -+}; diff --git a/target/linux/brcm2708/patches-4.9/0106-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch b/target/linux/brcm2708/patches-4.9/0106-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch new file mode 100644 index 0000000000..899c75e0db --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0106-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch @@ -0,0 +1,90 @@ +From 89b466914a0d49f08d00be25556ba22497b9a284 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Sat, 17 Sep 2016 15:07:10 +0200 +Subject: [PATCH] i2c: bcm2835: Fix hang for writing messages larger than 16 + bytes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Writing messages larger than the FIFO size results in a hang, rendering +the machine unusable. This is because the RXD status flag is set on the +first interrupt which results in bcm2835_drain_rxfifo() stealing bytes +from the buffer. The controller continues to trigger interrupts waiting +for the missing bytes, but bcm2835_fill_txfifo() has none to give. +In this situation wait_for_completion_timeout() apparently is unable to +stop the madness. + +The BCM2835 ARM Peripherals datasheet has this to say about the flags: + TXD: is set when the FIFO has space for at least one byte of data. + RXD: is set when the FIFO contains at least one byte of data. + TXW: is set during a write transfer and the FIFO is less than full. + RXR: is set during a read transfer and the FIFO is or more full. + +Implementing the logic from the downstream i2c-bcm2708 driver solved +the hang problem. + +Signed-off-by: Noralf Trønnes +Reviewed-by: Eric Anholt +Reviewed-by: Martin Sperl +--- + drivers/i2c/busses/i2c-bcm2835.c | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -64,6 +64,7 @@ struct bcm2835_i2c_dev { + int irq; + struct i2c_adapter adapter; + struct completion completion; ++ struct i2c_msg *curr_msg; + u32 msg_err; + u8 *msg_buf; + size_t msg_buf_remaining; +@@ -126,14 +127,13 @@ static irqreturn_t bcm2835_i2c_isr(int t + return IRQ_HANDLED; + } + +- if (val & BCM2835_I2C_S_RXD) { +- bcm2835_drain_rxfifo(i2c_dev); +- if (!(val & BCM2835_I2C_S_DONE)) +- return IRQ_HANDLED; +- } +- + if (val & BCM2835_I2C_S_DONE) { +- if (i2c_dev->msg_buf_remaining) ++ if (i2c_dev->curr_msg->flags & I2C_M_RD) { ++ bcm2835_drain_rxfifo(i2c_dev); ++ val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); ++ } ++ ++ if ((val & BCM2835_I2C_S_RXD) || i2c_dev->msg_buf_remaining) + i2c_dev->msg_err = BCM2835_I2C_S_LEN; + else + i2c_dev->msg_err = 0; +@@ -141,11 +141,16 @@ static irqreturn_t bcm2835_i2c_isr(int t + return IRQ_HANDLED; + } + +- if (val & BCM2835_I2C_S_TXD) { ++ if (val & BCM2835_I2C_S_TXW) { + bcm2835_fill_txfifo(i2c_dev); + return IRQ_HANDLED; + } + ++ if (val & BCM2835_I2C_S_RXR) { ++ bcm2835_drain_rxfifo(i2c_dev); ++ return IRQ_HANDLED; ++ } ++ + return IRQ_NONE; + } + +@@ -155,6 +160,7 @@ static int bcm2835_i2c_xfer_msg(struct b + u32 c; + unsigned long time_left; + ++ i2c_dev->curr_msg = msg; + i2c_dev->msg_buf = msg->buf; + i2c_dev->msg_buf_remaining = msg->len; + reinit_completion(&i2c_dev->completion); diff --git a/target/linux/brcm2708/patches-4.9/0107-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch b/target/linux/brcm2708/patches-4.9/0107-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch deleted file mode 100644 index 7692a92467..0000000000 --- a/target/linux/brcm2708/patches-4.9/0107-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch +++ /dev/null @@ -1,90 +0,0 @@ -From b302b7c9025334ef6680955a906cee579bf3c85c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 17 Sep 2016 15:07:10 +0200 -Subject: [PATCH] i2c: bcm2835: Fix hang for writing messages larger than 16 - bytes -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Writing messages larger than the FIFO size results in a hang, rendering -the machine unusable. This is because the RXD status flag is set on the -first interrupt which results in bcm2835_drain_rxfifo() stealing bytes -from the buffer. The controller continues to trigger interrupts waiting -for the missing bytes, but bcm2835_fill_txfifo() has none to give. -In this situation wait_for_completion_timeout() apparently is unable to -stop the madness. - -The BCM2835 ARM Peripherals datasheet has this to say about the flags: - TXD: is set when the FIFO has space for at least one byte of data. - RXD: is set when the FIFO contains at least one byte of data. - TXW: is set during a write transfer and the FIFO is less than full. - RXR: is set during a read transfer and the FIFO is or more full. - -Implementing the logic from the downstream i2c-bcm2708 driver solved -the hang problem. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt -Reviewed-by: Martin Sperl ---- - drivers/i2c/busses/i2c-bcm2835.c | 22 ++++++++++++++-------- - 1 file changed, 14 insertions(+), 8 deletions(-) - ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -64,6 +64,7 @@ struct bcm2835_i2c_dev { - int irq; - struct i2c_adapter adapter; - struct completion completion; -+ struct i2c_msg *curr_msg; - u32 msg_err; - u8 *msg_buf; - size_t msg_buf_remaining; -@@ -126,14 +127,13 @@ static irqreturn_t bcm2835_i2c_isr(int t - return IRQ_HANDLED; - } - -- if (val & BCM2835_I2C_S_RXD) { -- bcm2835_drain_rxfifo(i2c_dev); -- if (!(val & BCM2835_I2C_S_DONE)) -- return IRQ_HANDLED; -- } -- - if (val & BCM2835_I2C_S_DONE) { -- if (i2c_dev->msg_buf_remaining) -+ if (i2c_dev->curr_msg->flags & I2C_M_RD) { -+ bcm2835_drain_rxfifo(i2c_dev); -+ val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); -+ } -+ -+ if ((val & BCM2835_I2C_S_RXD) || i2c_dev->msg_buf_remaining) - i2c_dev->msg_err = BCM2835_I2C_S_LEN; - else - i2c_dev->msg_err = 0; -@@ -141,11 +141,16 @@ static irqreturn_t bcm2835_i2c_isr(int t - return IRQ_HANDLED; - } - -- if (val & BCM2835_I2C_S_TXD) { -+ if (val & BCM2835_I2C_S_TXW) { - bcm2835_fill_txfifo(i2c_dev); - return IRQ_HANDLED; - } - -+ if (val & BCM2835_I2C_S_RXR) { -+ bcm2835_drain_rxfifo(i2c_dev); -+ return IRQ_HANDLED; -+ } -+ - return IRQ_NONE; - } - -@@ -155,6 +160,7 @@ static int bcm2835_i2c_xfer_msg(struct b - u32 c; - unsigned long time_left; - -+ i2c_dev->curr_msg = msg; - i2c_dev->msg_buf = msg->buf; - i2c_dev->msg_buf_remaining = msg->len; - reinit_completion(&i2c_dev->completion); diff --git a/target/linux/brcm2708/patches-4.9/0107-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch b/target/linux/brcm2708/patches-4.9/0107-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch new file mode 100644 index 0000000000..6646d77944 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0107-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch @@ -0,0 +1,124 @@ +From 8feb8081c74d15ce368baa42981ca98e77800c03 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Fri, 23 Sep 2016 18:24:38 +0200 +Subject: [PATCH] i2c: bcm2835: Protect against unexpected TXW/RXR interrupts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If an unexpected TXW or RXR interrupt occurs (msg_buf_remaining == 0), +the driver has no way to fill/drain the FIFO to stop the interrupts. +In this case the controller has to be disabled and the transfer +completed to avoid hang. + +(CLKT | ERR) and DONE interrupts are completed in their own paths, and +the controller is disabled in the transfer function after completion. +Unite the code paths and do disabling inside the interrupt routine. + +Clear interrupt status bits in the united completion path instead of +trying to do it on every interrupt which isn't necessary. +Only CLKT, ERR and DONE can be cleared that way. + +Add the status value to the error value in case of TXW/RXR errors to +distinguish them from the other S_LEN error. + +Signed-off-by: Noralf Trønnes +Reviewed-by: Eric Anholt +--- + drivers/i2c/busses/i2c-bcm2835.c | 40 +++++++++++++++++++++++++++++++--------- + 1 file changed, 31 insertions(+), 9 deletions(-) + +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -50,8 +50,6 @@ + #define BCM2835_I2C_S_CLKT BIT(9) + #define BCM2835_I2C_S_LEN BIT(10) /* Fake bit for SW error reporting */ + +-#define BCM2835_I2C_BITMSK_S 0x03FF +- + #define BCM2835_I2C_CDIV_MIN 0x0002 + #define BCM2835_I2C_CDIV_MAX 0xFFFE + +@@ -111,20 +109,26 @@ static void bcm2835_drain_rxfifo(struct + } + } + ++/* ++ * Note about I2C_C_CLEAR on error: ++ * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in ++ * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through ++ * the state machine to send a NACK and a STOP. Since we're setting CLEAR ++ * without I2CEN, that NACK will be hanging around queued up for next time ++ * we start the engine. ++ */ ++ + static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + { + struct bcm2835_i2c_dev *i2c_dev = data; + u32 val, err; + + val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); +- val &= BCM2835_I2C_BITMSK_S; +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val); + + err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); + if (err) { + i2c_dev->msg_err = err; +- complete(&i2c_dev->completion); +- return IRQ_HANDLED; ++ goto complete; + } + + if (val & BCM2835_I2C_S_DONE) { +@@ -137,21 +141,38 @@ static irqreturn_t bcm2835_i2c_isr(int t + i2c_dev->msg_err = BCM2835_I2C_S_LEN; + else + i2c_dev->msg_err = 0; +- complete(&i2c_dev->completion); +- return IRQ_HANDLED; ++ goto complete; + } + + if (val & BCM2835_I2C_S_TXW) { ++ if (!i2c_dev->msg_buf_remaining) { ++ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; ++ goto complete; ++ } ++ + bcm2835_fill_txfifo(i2c_dev); + return IRQ_HANDLED; + } + + if (val & BCM2835_I2C_S_RXR) { ++ if (!i2c_dev->msg_buf_remaining) { ++ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; ++ goto complete; ++ } ++ + bcm2835_drain_rxfifo(i2c_dev); + return IRQ_HANDLED; + } + + return IRQ_NONE; ++ ++complete: ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, BCM2835_I2C_S_CLKT | ++ BCM2835_I2C_S_ERR | BCM2835_I2C_S_DONE); ++ complete(&i2c_dev->completion); ++ ++ return IRQ_HANDLED; + } + + static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, +@@ -181,8 +202,9 @@ static int bcm2835_i2c_xfer_msg(struct b + + time_left = wait_for_completion_timeout(&i2c_dev->completion, + BCM2835_I2C_TIMEOUT); +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); + if (!time_left) { ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, ++ BCM2835_I2C_C_CLEAR); + dev_err(i2c_dev->dev, "i2c transfer timed out\n"); + return -ETIMEDOUT; + } diff --git a/target/linux/brcm2708/patches-4.9/0108-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch b/target/linux/brcm2708/patches-4.9/0108-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch deleted file mode 100644 index 0a616ff7ad..0000000000 --- a/target/linux/brcm2708/patches-4.9/0108-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 95729fe299cca5ef749f4b6a2c3e0f40ec7b43b9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 23 Sep 2016 18:24:38 +0200 -Subject: [PATCH] i2c: bcm2835: Protect against unexpected TXW/RXR interrupts -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -If an unexpected TXW or RXR interrupt occurs (msg_buf_remaining == 0), -the driver has no way to fill/drain the FIFO to stop the interrupts. -In this case the controller has to be disabled and the transfer -completed to avoid hang. - -(CLKT | ERR) and DONE interrupts are completed in their own paths, and -the controller is disabled in the transfer function after completion. -Unite the code paths and do disabling inside the interrupt routine. - -Clear interrupt status bits in the united completion path instead of -trying to do it on every interrupt which isn't necessary. -Only CLKT, ERR and DONE can be cleared that way. - -Add the status value to the error value in case of TXW/RXR errors to -distinguish them from the other S_LEN error. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 40 +++++++++++++++++++++++++++++++--------- - 1 file changed, 31 insertions(+), 9 deletions(-) - ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -50,8 +50,6 @@ - #define BCM2835_I2C_S_CLKT BIT(9) - #define BCM2835_I2C_S_LEN BIT(10) /* Fake bit for SW error reporting */ - --#define BCM2835_I2C_BITMSK_S 0x03FF -- - #define BCM2835_I2C_CDIV_MIN 0x0002 - #define BCM2835_I2C_CDIV_MAX 0xFFFE - -@@ -111,20 +109,26 @@ static void bcm2835_drain_rxfifo(struct - } - } - -+/* -+ * Note about I2C_C_CLEAR on error: -+ * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in -+ * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through -+ * the state machine to send a NACK and a STOP. Since we're setting CLEAR -+ * without I2CEN, that NACK will be hanging around queued up for next time -+ * we start the engine. -+ */ -+ - static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) - { - struct bcm2835_i2c_dev *i2c_dev = data; - u32 val, err; - - val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); -- val &= BCM2835_I2C_BITMSK_S; -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val); - - err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); - if (err) { - i2c_dev->msg_err = err; -- complete(&i2c_dev->completion); -- return IRQ_HANDLED; -+ goto complete; - } - - if (val & BCM2835_I2C_S_DONE) { -@@ -137,21 +141,38 @@ static irqreturn_t bcm2835_i2c_isr(int t - i2c_dev->msg_err = BCM2835_I2C_S_LEN; - else - i2c_dev->msg_err = 0; -- complete(&i2c_dev->completion); -- return IRQ_HANDLED; -+ goto complete; - } - - if (val & BCM2835_I2C_S_TXW) { -+ if (!i2c_dev->msg_buf_remaining) { -+ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; -+ goto complete; -+ } -+ - bcm2835_fill_txfifo(i2c_dev); - return IRQ_HANDLED; - } - - if (val & BCM2835_I2C_S_RXR) { -+ if (!i2c_dev->msg_buf_remaining) { -+ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; -+ goto complete; -+ } -+ - bcm2835_drain_rxfifo(i2c_dev); - return IRQ_HANDLED; - } - - return IRQ_NONE; -+ -+complete: -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, BCM2835_I2C_S_CLKT | -+ BCM2835_I2C_S_ERR | BCM2835_I2C_S_DONE); -+ complete(&i2c_dev->completion); -+ -+ return IRQ_HANDLED; - } - - static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, -@@ -181,8 +202,9 @@ static int bcm2835_i2c_xfer_msg(struct b - - time_left = wait_for_completion_timeout(&i2c_dev->completion, - BCM2835_I2C_TIMEOUT); -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); - if (!time_left) { -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, -+ BCM2835_I2C_C_CLEAR); - dev_err(i2c_dev->dev, "i2c transfer timed out\n"); - return -ETIMEDOUT; - } diff --git a/target/linux/brcm2708/patches-4.9/0108-i2c-bcm2835-Use-dev_dbg-logging-on-transfer-errors.patch b/target/linux/brcm2708/patches-4.9/0108-i2c-bcm2835-Use-dev_dbg-logging-on-transfer-errors.patch new file mode 100644 index 0000000000..acc2ade0a3 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0108-i2c-bcm2835-Use-dev_dbg-logging-on-transfer-errors.patch @@ -0,0 +1,32 @@ +From bff25210b88dc7b71ee9c2626e42a939072dec64 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Mon, 19 Sep 2016 17:19:41 +0200 +Subject: [PATCH] i2c: bcm2835: Use dev_dbg logging on transfer errors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Writing to an AT24C32 generates on average 2x i2c transfer errors per +32-byte page write. Which amounts to a lot for a 4k write. This is due +to the fact that the chip doesn't respond during it's internal write +cycle when the at24 driver tries and retries the next write. +Only a handful drivers use dev_err() on transfer error, so switch to +dev_dbg() instead. + +Signed-off-by: Noralf Trønnes +Reviewed-by: Eric Anholt +--- + drivers/i2c/busses/i2c-bcm2835.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -216,7 +216,7 @@ static int bcm2835_i2c_xfer_msg(struct b + (msg->flags & I2C_M_IGNORE_NAK)) + return 0; + +- dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); ++ dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); + + if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) + return -EREMOTEIO; diff --git a/target/linux/brcm2708/patches-4.9/0109-i2c-bcm2835-Can-t-support-I2C_M_IGNORE_NAK.patch b/target/linux/brcm2708/patches-4.9/0109-i2c-bcm2835-Can-t-support-I2C_M_IGNORE_NAK.patch new file mode 100644 index 0000000000..a913c50082 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0109-i2c-bcm2835-Can-t-support-I2C_M_IGNORE_NAK.patch @@ -0,0 +1,44 @@ +From 40c63177d4c0f4755a148503c3b8bb2192ce8c0e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Thu, 22 Sep 2016 22:05:50 +0200 +Subject: [PATCH] i2c: bcm2835: Can't support I2C_M_IGNORE_NAK +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The controller can't support this flag, so remove it. + +Documentation/i2c/i2c-protocol states that all of the message is sent: + +I2C_M_IGNORE_NAK: + Normally message is interrupted immediately if there is [NA] from the + client. Setting this flag treats any [NA] as [A], and all of + message is sent. + +From the BCM2835 ARM Peripherals datasheet: + + The ERR field is set when the slave fails to acknowledge either + its address or a data byte written to it. + +So when the controller doesn't receive an ack, it sets ERR and raises +an interrupt. In other words, the whole message is not sent. + +Signed-off-by: Noralf Trønnes +Reviewed-by: Eric Anholt +--- + drivers/i2c/busses/i2c-bcm2835.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -212,10 +212,6 @@ static int bcm2835_i2c_xfer_msg(struct b + if (likely(!i2c_dev->msg_err)) + return 0; + +- if ((i2c_dev->msg_err & BCM2835_I2C_S_ERR) && +- (msg->flags & I2C_M_IGNORE_NAK)) +- return 0; +- + dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); + + if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) diff --git a/target/linux/brcm2708/patches-4.9/0109-i2c-bcm2835-Use-dev_dbg-logging-on-transfer-errors.patch b/target/linux/brcm2708/patches-4.9/0109-i2c-bcm2835-Use-dev_dbg-logging-on-transfer-errors.patch deleted file mode 100644 index b8cbe10452..0000000000 --- a/target/linux/brcm2708/patches-4.9/0109-i2c-bcm2835-Use-dev_dbg-logging-on-transfer-errors.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 3e9e15ec9e56874764fdaa43b2af8008469b87b2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 19 Sep 2016 17:19:41 +0200 -Subject: [PATCH] i2c: bcm2835: Use dev_dbg logging on transfer errors -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Writing to an AT24C32 generates on average 2x i2c transfer errors per -32-byte page write. Which amounts to a lot for a 4k write. This is due -to the fact that the chip doesn't respond during it's internal write -cycle when the at24 driver tries and retries the next write. -Only a handful drivers use dev_err() on transfer error, so switch to -dev_dbg() instead. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -216,7 +216,7 @@ static int bcm2835_i2c_xfer_msg(struct b - (msg->flags & I2C_M_IGNORE_NAK)) - return 0; - -- dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); -+ dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); - - if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) - return -EREMOTEIO; diff --git a/target/linux/brcm2708/patches-4.9/0110-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch b/target/linux/brcm2708/patches-4.9/0110-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch new file mode 100644 index 0000000000..0cd5aa4693 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0110-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch @@ -0,0 +1,181 @@ +From db656eb11aebb0d7e4b833f9b452503ddb1351f1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Fri, 23 Sep 2016 04:54:27 +0200 +Subject: [PATCH] i2c: bcm2835: Add support for Repeated Start Condition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Documentation/i2c/i2c-protocol states that Combined transactions should +separate messages with a Start bit and end the whole transaction with a +Stop bit. This patch adds support for issuing only a Start between +messages instead of a Stop followed by a Start. + +This implementation differs from downstream i2c-bcm2708 in 2 respects: +- it uses an interrupt to detect that the transfer is active instead + of using polling. There is no interrupt for Transfer Active, but by + not prefilling the FIFO it's possible to use the TXW interrupt. +- when resetting/disabling the controller between transfers it writes + CLEAR to the control register instead of just zero. + Using just zero gave many errors. This might be the reason why + downstream had to disable this feature and make it available with a + module parameter. + +I have run thousands of transfers to a DS1307 (rtc), MMA8451 (accel) +and AT24C32 (eeprom) in parallel without problems. + +Signed-off-by: Noralf Trønnes +Acked-by: Eric Anholt +--- + drivers/i2c/busses/i2c-bcm2835.c | 101 ++++++++++++++++++++++++--------------- + 1 file changed, 63 insertions(+), 38 deletions(-) + +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -63,6 +63,7 @@ struct bcm2835_i2c_dev { + struct i2c_adapter adapter; + struct completion completion; + struct i2c_msg *curr_msg; ++ int num_msgs; + u32 msg_err; + u8 *msg_buf; + size_t msg_buf_remaining; +@@ -110,6 +111,45 @@ static void bcm2835_drain_rxfifo(struct + } + + /* ++ * Repeated Start Condition (Sr) ++ * The BCM2835 ARM Peripherals datasheet mentions a way to trigger a Sr when it ++ * talks about reading from a slave with 10 bit address. This is achieved by ++ * issuing a write, poll the I2CS.TA flag and wait for it to be set, and then ++ * issue a read. ++ * A comment in https://github.com/raspberrypi/linux/issues/254 shows how the ++ * firmware actually does it using polling and says that it's a workaround for ++ * a problem in the state machine. ++ * It turns out that it is possible to use the TXW interrupt to know when the ++ * transfer is active, provided the FIFO has not been prefilled. ++ */ ++ ++static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) ++{ ++ u32 c = BCM2835_I2C_C_ST | BCM2835_I2C_C_I2CEN; ++ struct i2c_msg *msg = i2c_dev->curr_msg; ++ bool last_msg = (i2c_dev->num_msgs == 1); ++ ++ if (!i2c_dev->num_msgs) ++ return; ++ ++ i2c_dev->num_msgs--; ++ i2c_dev->msg_buf = msg->buf; ++ i2c_dev->msg_buf_remaining = msg->len; ++ ++ if (msg->flags & I2C_M_RD) ++ c |= BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; ++ else ++ c |= BCM2835_I2C_C_INTT; ++ ++ if (last_msg) ++ c |= BCM2835_I2C_C_INTD; ++ ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); ++} ++ ++/* + * Note about I2C_C_CLEAR on error: + * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in + * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through +@@ -151,6 +191,12 @@ static irqreturn_t bcm2835_i2c_isr(int t + } + + bcm2835_fill_txfifo(i2c_dev); ++ ++ if (i2c_dev->num_msgs && !i2c_dev->msg_buf_remaining) { ++ i2c_dev->curr_msg++; ++ bcm2835_i2c_start_transfer(i2c_dev); ++ } ++ + return IRQ_HANDLED; + } + +@@ -175,30 +221,25 @@ complete: + return IRQ_HANDLED; + } + +-static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, +- struct i2c_msg *msg) ++static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], ++ int num) + { +- u32 c; ++ struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); + unsigned long time_left; ++ int i; + +- i2c_dev->curr_msg = msg; +- i2c_dev->msg_buf = msg->buf; +- i2c_dev->msg_buf_remaining = msg->len; +- reinit_completion(&i2c_dev->completion); +- +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); ++ for (i = 0; i < (num - 1); i++) ++ if (msgs[i].flags & I2C_M_RD) { ++ dev_warn_once(i2c_dev->dev, ++ "only one read message supported, has to be last\n"); ++ return -EOPNOTSUPP; ++ } + +- if (msg->flags & I2C_M_RD) { +- c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; +- } else { +- c = BCM2835_I2C_C_INTT; +- bcm2835_fill_txfifo(i2c_dev); +- } +- c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN; ++ i2c_dev->curr_msg = msgs; ++ i2c_dev->num_msgs = num; ++ reinit_completion(&i2c_dev->completion); + +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); ++ bcm2835_i2c_start_transfer(i2c_dev); + + time_left = wait_for_completion_timeout(&i2c_dev->completion, + BCM2835_I2C_TIMEOUT); +@@ -209,31 +250,15 @@ static int bcm2835_i2c_xfer_msg(struct b + return -ETIMEDOUT; + } + +- if (likely(!i2c_dev->msg_err)) +- return 0; ++ if (!i2c_dev->msg_err) ++ return num; + + dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); + + if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) + return -EREMOTEIO; +- else +- return -EIO; +-} +- +-static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], +- int num) +-{ +- struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); +- int i; +- int ret = 0; +- +- for (i = 0; i < num; i++) { +- ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]); +- if (ret) +- break; +- } + +- return ret ?: i; ++ return -EIO; + } + + static u32 bcm2835_i2c_func(struct i2c_adapter *adap) diff --git a/target/linux/brcm2708/patches-4.9/0110-i2c-bcm2835-Can-t-support-I2C_M_IGNORE_NAK.patch b/target/linux/brcm2708/patches-4.9/0110-i2c-bcm2835-Can-t-support-I2C_M_IGNORE_NAK.patch deleted file mode 100644 index 946c316bc1..0000000000 --- a/target/linux/brcm2708/patches-4.9/0110-i2c-bcm2835-Can-t-support-I2C_M_IGNORE_NAK.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 9d8c576116c4818dd745ff112504f0fdf78c9e1e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 22 Sep 2016 22:05:50 +0200 -Subject: [PATCH] i2c: bcm2835: Can't support I2C_M_IGNORE_NAK -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The controller can't support this flag, so remove it. - -Documentation/i2c/i2c-protocol states that all of the message is sent: - -I2C_M_IGNORE_NAK: - Normally message is interrupted immediately if there is [NA] from the - client. Setting this flag treats any [NA] as [A], and all of - message is sent. - -From the BCM2835 ARM Peripherals datasheet: - - The ERR field is set when the slave fails to acknowledge either - its address or a data byte written to it. - -So when the controller doesn't receive an ack, it sets ERR and raises -an interrupt. In other words, the whole message is not sent. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 4 ---- - 1 file changed, 4 deletions(-) - ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -212,10 +212,6 @@ static int bcm2835_i2c_xfer_msg(struct b - if (likely(!i2c_dev->msg_err)) - return 0; - -- if ((i2c_dev->msg_err & BCM2835_I2C_S_ERR) && -- (msg->flags & I2C_M_IGNORE_NAK)) -- return 0; -- - dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); - - if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) diff --git a/target/linux/brcm2708/patches-4.9/0111-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch b/target/linux/brcm2708/patches-4.9/0111-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch deleted file mode 100644 index a481aaf235..0000000000 --- a/target/linux/brcm2708/patches-4.9/0111-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 1099ac9cbf927e62883b363cfe3d33db105ff3dc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 23 Sep 2016 04:54:27 +0200 -Subject: [PATCH] i2c: bcm2835: Add support for Repeated Start Condition -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Documentation/i2c/i2c-protocol states that Combined transactions should -separate messages with a Start bit and end the whole transaction with a -Stop bit. This patch adds support for issuing only a Start between -messages instead of a Stop followed by a Start. - -This implementation differs from downstream i2c-bcm2708 in 2 respects: -- it uses an interrupt to detect that the transfer is active instead - of using polling. There is no interrupt for Transfer Active, but by - not prefilling the FIFO it's possible to use the TXW interrupt. -- when resetting/disabling the controller between transfers it writes - CLEAR to the control register instead of just zero. - Using just zero gave many errors. This might be the reason why - downstream had to disable this feature and make it available with a - module parameter. - -I have run thousands of transfers to a DS1307 (rtc), MMA8451 (accel) -and AT24C32 (eeprom) in parallel without problems. - -Signed-off-by: Noralf Trønnes -Acked-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 101 ++++++++++++++++++++++++--------------- - 1 file changed, 63 insertions(+), 38 deletions(-) - ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -63,6 +63,7 @@ struct bcm2835_i2c_dev { - struct i2c_adapter adapter; - struct completion completion; - struct i2c_msg *curr_msg; -+ int num_msgs; - u32 msg_err; - u8 *msg_buf; - size_t msg_buf_remaining; -@@ -110,6 +111,45 @@ static void bcm2835_drain_rxfifo(struct - } - - /* -+ * Repeated Start Condition (Sr) -+ * The BCM2835 ARM Peripherals datasheet mentions a way to trigger a Sr when it -+ * talks about reading from a slave with 10 bit address. This is achieved by -+ * issuing a write, poll the I2CS.TA flag and wait for it to be set, and then -+ * issue a read. -+ * A comment in https://github.com/raspberrypi/linux/issues/254 shows how the -+ * firmware actually does it using polling and says that it's a workaround for -+ * a problem in the state machine. -+ * It turns out that it is possible to use the TXW interrupt to know when the -+ * transfer is active, provided the FIFO has not been prefilled. -+ */ -+ -+static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) -+{ -+ u32 c = BCM2835_I2C_C_ST | BCM2835_I2C_C_I2CEN; -+ struct i2c_msg *msg = i2c_dev->curr_msg; -+ bool last_msg = (i2c_dev->num_msgs == 1); -+ -+ if (!i2c_dev->num_msgs) -+ return; -+ -+ i2c_dev->num_msgs--; -+ i2c_dev->msg_buf = msg->buf; -+ i2c_dev->msg_buf_remaining = msg->len; -+ -+ if (msg->flags & I2C_M_RD) -+ c |= BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; -+ else -+ c |= BCM2835_I2C_C_INTT; -+ -+ if (last_msg) -+ c |= BCM2835_I2C_C_INTD; -+ -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); -+} -+ -+/* - * Note about I2C_C_CLEAR on error: - * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in - * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through -@@ -151,6 +191,12 @@ static irqreturn_t bcm2835_i2c_isr(int t - } - - bcm2835_fill_txfifo(i2c_dev); -+ -+ if (i2c_dev->num_msgs && !i2c_dev->msg_buf_remaining) { -+ i2c_dev->curr_msg++; -+ bcm2835_i2c_start_transfer(i2c_dev); -+ } -+ - return IRQ_HANDLED; - } - -@@ -175,30 +221,25 @@ complete: - return IRQ_HANDLED; - } - --static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, -- struct i2c_msg *msg) -+static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], -+ int num) - { -- u32 c; -+ struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); - unsigned long time_left; -+ int i; - -- i2c_dev->curr_msg = msg; -- i2c_dev->msg_buf = msg->buf; -- i2c_dev->msg_buf_remaining = msg->len; -- reinit_completion(&i2c_dev->completion); -- -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); -+ for (i = 0; i < (num - 1); i++) -+ if (msgs[i].flags & I2C_M_RD) { -+ dev_warn_once(i2c_dev->dev, -+ "only one read message supported, has to be last\n"); -+ return -EOPNOTSUPP; -+ } - -- if (msg->flags & I2C_M_RD) { -- c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; -- } else { -- c = BCM2835_I2C_C_INTT; -- bcm2835_fill_txfifo(i2c_dev); -- } -- c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN; -+ i2c_dev->curr_msg = msgs; -+ i2c_dev->num_msgs = num; -+ reinit_completion(&i2c_dev->completion); - -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); -+ bcm2835_i2c_start_transfer(i2c_dev); - - time_left = wait_for_completion_timeout(&i2c_dev->completion, - BCM2835_I2C_TIMEOUT); -@@ -209,31 +250,15 @@ static int bcm2835_i2c_xfer_msg(struct b - return -ETIMEDOUT; - } - -- if (likely(!i2c_dev->msg_err)) -- return 0; -+ if (!i2c_dev->msg_err) -+ return num; - - dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); - - if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) - return -EREMOTEIO; -- else -- return -EIO; --} -- --static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], -- int num) --{ -- struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); -- int i; -- int ret = 0; -- -- for (i = 0; i < num; i++) { -- ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]); -- if (ret) -- break; -- } - -- return ret ?: i; -+ return -EIO; - } - - static u32 bcm2835_i2c_func(struct i2c_adapter *adap) diff --git a/target/linux/brcm2708/patches-4.9/0111-i2c-bcm2835-Support-i2c-dev-ioctl-I2C_TIMEOUT.patch b/target/linux/brcm2708/patches-4.9/0111-i2c-bcm2835-Support-i2c-dev-ioctl-I2C_TIMEOUT.patch new file mode 100644 index 0000000000..07016d9782 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0111-i2c-bcm2835-Support-i2c-dev-ioctl-I2C_TIMEOUT.patch @@ -0,0 +1,37 @@ +From 0c2744e901150b27a60bded1acb058ce26709d5a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Fri, 23 Sep 2016 04:57:17 +0200 +Subject: [PATCH] i2c: bcm2835: Support i2c-dev ioctl I2C_TIMEOUT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use i2c_adapter->timeout for the completion timeout value. The core +default is 1 second. + +Signed-off-by: Noralf Trønnes +Reviewed-by: Eric Anholt +--- + drivers/i2c/busses/i2c-bcm2835.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -53,8 +53,6 @@ + #define BCM2835_I2C_CDIV_MIN 0x0002 + #define BCM2835_I2C_CDIV_MAX 0xFFFE + +-#define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000)) +- + struct bcm2835_i2c_dev { + struct device *dev; + void __iomem *regs; +@@ -242,7 +240,7 @@ static int bcm2835_i2c_xfer(struct i2c_a + bcm2835_i2c_start_transfer(i2c_dev); + + time_left = wait_for_completion_timeout(&i2c_dev->completion, +- BCM2835_I2C_TIMEOUT); ++ adap->timeout); + if (!time_left) { + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, + BCM2835_I2C_C_CLEAR); diff --git a/target/linux/brcm2708/patches-4.9/0112-i2c-bcm2835-Add-support-for-dynamic-clock.patch b/target/linux/brcm2708/patches-4.9/0112-i2c-bcm2835-Add-support-for-dynamic-clock.patch new file mode 100644 index 0000000000..afe2b2297c --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0112-i2c-bcm2835-Add-support-for-dynamic-clock.patch @@ -0,0 +1,117 @@ +From ce8663f1f101f8c7b9037c31269b0b31373737ad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Tue, 27 Sep 2016 01:00:08 +0200 +Subject: [PATCH] i2c: bcm2835: Add support for dynamic clock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Support a dynamic clock by reading the frequency and setting the +divisor in the transfer function instead of during probe. + +Signed-off-by: Noralf Trønnes +Reviewed-by: Martin Sperl +--- + drivers/i2c/busses/i2c-bcm2835.c | 51 +++++++++++++++++++++++++--------------- + 1 file changed, 32 insertions(+), 19 deletions(-) + +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -58,6 +58,7 @@ struct bcm2835_i2c_dev { + void __iomem *regs; + struct clk *clk; + int irq; ++ u32 bus_clk_rate; + struct i2c_adapter adapter; + struct completion completion; + struct i2c_msg *curr_msg; +@@ -78,6 +79,30 @@ static inline u32 bcm2835_i2c_readl(stru + return readl(i2c_dev->regs + reg); + } + ++static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) ++{ ++ u32 divider; ++ ++ divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), ++ i2c_dev->bus_clk_rate); ++ /* ++ * Per the datasheet, the register is always interpreted as an even ++ * number, by rounding down. In other words, the LSB is ignored. So, ++ * if the LSB is set, increment the divider to avoid any issue. ++ */ ++ if (divider & 1) ++ divider++; ++ if ((divider < BCM2835_I2C_CDIV_MIN) || ++ (divider > BCM2835_I2C_CDIV_MAX)) { ++ dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n"); ++ return -EINVAL; ++ } ++ ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); ++ ++ return 0; ++} ++ + static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev) + { + u32 val; +@@ -224,7 +249,7 @@ static int bcm2835_i2c_xfer(struct i2c_a + { + struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); + unsigned long time_left; +- int i; ++ int i, ret; + + for (i = 0; i < (num - 1); i++) + if (msgs[i].flags & I2C_M_RD) { +@@ -233,6 +258,10 @@ static int bcm2835_i2c_xfer(struct i2c_a + return -EOPNOTSUPP; + } + ++ ret = bcm2835_i2c_set_divider(i2c_dev); ++ if (ret) ++ return ret; ++ + i2c_dev->curr_msg = msgs; + i2c_dev->num_msgs = num; + reinit_completion(&i2c_dev->completion); +@@ -282,7 +311,6 @@ static int bcm2835_i2c_probe(struct plat + { + struct bcm2835_i2c_dev *i2c_dev; + struct resource *mem, *irq; +- u32 bus_clk_rate, divider; + int ret; + struct i2c_adapter *adap; + +@@ -306,28 +334,13 @@ static int bcm2835_i2c_probe(struct plat + } + + ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", +- &bus_clk_rate); ++ &i2c_dev->bus_clk_rate); + if (ret < 0) { + dev_warn(&pdev->dev, + "Could not read clock-frequency property\n"); +- bus_clk_rate = 100000; ++ i2c_dev->bus_clk_rate = 100000; + } + +- divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), bus_clk_rate); +- /* +- * Per the datasheet, the register is always interpreted as an even +- * number, by rounding down. In other words, the LSB is ignored. So, +- * if the LSB is set, increment the divider to avoid any issue. +- */ +- if (divider & 1) +- divider++; +- if ((divider < BCM2835_I2C_CDIV_MIN) || +- (divider > BCM2835_I2C_CDIV_MAX)) { +- dev_err(&pdev->dev, "Invalid clock-frequency\n"); +- return -ENODEV; +- } +- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); +- + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!irq) { + dev_err(&pdev->dev, "No IRQ resource\n"); diff --git a/target/linux/brcm2708/patches-4.9/0112-i2c-bcm2835-Support-i2c-dev-ioctl-I2C_TIMEOUT.patch b/target/linux/brcm2708/patches-4.9/0112-i2c-bcm2835-Support-i2c-dev-ioctl-I2C_TIMEOUT.patch deleted file mode 100644 index ef70b978bf..0000000000 --- a/target/linux/brcm2708/patches-4.9/0112-i2c-bcm2835-Support-i2c-dev-ioctl-I2C_TIMEOUT.patch +++ /dev/null @@ -1,37 +0,0 @@ -From d42e4206e0e273b195881614a317688830fc56a2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 23 Sep 2016 04:57:17 +0200 -Subject: [PATCH] i2c: bcm2835: Support i2c-dev ioctl I2C_TIMEOUT -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use i2c_adapter->timeout for the completion timeout value. The core -default is 1 second. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Eric Anholt ---- - drivers/i2c/busses/i2c-bcm2835.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -53,8 +53,6 @@ - #define BCM2835_I2C_CDIV_MIN 0x0002 - #define BCM2835_I2C_CDIV_MAX 0xFFFE - --#define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000)) -- - struct bcm2835_i2c_dev { - struct device *dev; - void __iomem *regs; -@@ -242,7 +240,7 @@ static int bcm2835_i2c_xfer(struct i2c_a - bcm2835_i2c_start_transfer(i2c_dev); - - time_left = wait_for_completion_timeout(&i2c_dev->completion, -- BCM2835_I2C_TIMEOUT); -+ adap->timeout); - if (!time_left) { - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, - BCM2835_I2C_C_CLEAR); diff --git a/target/linux/brcm2708/patches-4.9/0113-i2c-bcm2835-Add-debug-support.patch b/target/linux/brcm2708/patches-4.9/0113-i2c-bcm2835-Add-debug-support.patch new file mode 100644 index 0000000000..f69a48f623 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0113-i2c-bcm2835-Add-debug-support.patch @@ -0,0 +1,189 @@ +From 98629f09f3ceb7f2a559b48b4a70028485583f5e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Tue, 1 Nov 2016 15:15:41 +0100 +Subject: [PATCH] i2c: bcm2835: Add debug support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This adds a debug module parameter to aid in debugging transfer issues +by printing info to the kernel log. When enabled, status values are +collected in the interrupt routine and msg info in +bcm2835_i2c_start_transfer(). This is done in a way that tries to avoid +affecting timing. Having printk in the isr can mask issues. + +debug values (additive): +1: Print info on error +2: Print info on all transfers +3: Print messages before transfer is started + +The value can be changed at runtime: +/sys/module/i2c_bcm2835/parameters/debug + +Example output, debug=3: +[ 747.114448] bcm2835_i2c_xfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] +[ 747.114463] bcm2835_i2c_xfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] +[ 747.117809] start_transfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] +[ 747.117825] isr: remain=2, status=0x30000055 : TA TXW TXD TXE [i2c1] +[ 747.117839] start_transfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] +[ 747.117849] isr: remain=32, status=0xd0000039 : TA RXR TXD RXD [i2c1] +[ 747.117861] isr: remain=20, status=0xd0000039 : TA RXR TXD RXD [i2c1] +[ 747.117870] isr: remain=8, status=0x32 : DONE TXD RXD [i2c1] + +Signed-off-by: Noralf Trønnes +--- + drivers/i2c/busses/i2c-bcm2835.c | 99 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 98 insertions(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -53,6 +53,18 @@ + #define BCM2835_I2C_CDIV_MIN 0x0002 + #define BCM2835_I2C_CDIV_MAX 0xFFFE + ++static unsigned int debug; ++module_param(debug, uint, 0644); ++MODULE_PARM_DESC(debug, "1=err, 2=isr, 3=xfer"); ++ ++#define BCM2835_DEBUG_MAX 512 ++struct bcm2835_debug { ++ struct i2c_msg *msg; ++ int msg_idx; ++ size_t remain; ++ u32 status; ++}; ++ + struct bcm2835_i2c_dev { + struct device *dev; + void __iomem *regs; +@@ -66,8 +78,78 @@ struct bcm2835_i2c_dev { + u32 msg_err; + u8 *msg_buf; + size_t msg_buf_remaining; ++ struct bcm2835_debug debug[BCM2835_DEBUG_MAX]; ++ unsigned int debug_num; ++ unsigned int debug_num_msgs; + }; + ++static inline void bcm2835_debug_add(struct bcm2835_i2c_dev *i2c_dev, u32 s) ++{ ++ if (!i2c_dev->debug_num_msgs || i2c_dev->debug_num >= BCM2835_DEBUG_MAX) ++ return; ++ ++ i2c_dev->debug[i2c_dev->debug_num].msg = i2c_dev->curr_msg; ++ i2c_dev->debug[i2c_dev->debug_num].msg_idx = ++ i2c_dev->debug_num_msgs - i2c_dev->num_msgs; ++ i2c_dev->debug[i2c_dev->debug_num].remain = i2c_dev->msg_buf_remaining; ++ i2c_dev->debug[i2c_dev->debug_num].status = s; ++ i2c_dev->debug_num++; ++} ++ ++static void bcm2835_debug_print_status(struct bcm2835_i2c_dev *i2c_dev, ++ struct bcm2835_debug *d) ++{ ++ u32 s = d->status; ++ ++ pr_info("isr: remain=%zu, status=0x%x : %s%s%s%s%s%s%s%s%s%s [i2c%d]\n", ++ d->remain, s, ++ s & BCM2835_I2C_S_TA ? "TA " : "", ++ s & BCM2835_I2C_S_DONE ? "DONE " : "", ++ s & BCM2835_I2C_S_TXW ? "TXW " : "", ++ s & BCM2835_I2C_S_RXR ? "RXR " : "", ++ s & BCM2835_I2C_S_TXD ? "TXD " : "", ++ s & BCM2835_I2C_S_RXD ? "RXD " : "", ++ s & BCM2835_I2C_S_TXE ? "TXE " : "", ++ s & BCM2835_I2C_S_RXF ? "RXF " : "", ++ s & BCM2835_I2C_S_ERR ? "ERR " : "", ++ s & BCM2835_I2C_S_CLKT ? "CLKT " : "", ++ i2c_dev->adapter.nr); ++} ++ ++static void bcm2835_debug_print_msg(struct bcm2835_i2c_dev *i2c_dev, ++ struct i2c_msg *msg, int i, int total, ++ const char *fname) ++{ ++ pr_info("%s: msg(%d/%d) %s addr=0x%02x, len=%u flags=%s%s%s%s%s%s%s [i2c%d]\n", ++ fname, i, total, ++ msg->flags & I2C_M_RD ? "read" : "write", msg->addr, msg->len, ++ msg->flags & I2C_M_TEN ? "TEN" : "", ++ msg->flags & I2C_M_RECV_LEN ? "RECV_LEN" : "", ++ msg->flags & I2C_M_NO_RD_ACK ? "NO_RD_ACK" : "", ++ msg->flags & I2C_M_IGNORE_NAK ? "IGNORE_NAK" : "", ++ msg->flags & I2C_M_REV_DIR_ADDR ? "REV_DIR_ADDR" : "", ++ msg->flags & I2C_M_NOSTART ? "NOSTART" : "", ++ msg->flags & I2C_M_STOP ? "STOP" : "", ++ i2c_dev->adapter.nr); ++} ++ ++static void bcm2835_debug_print(struct bcm2835_i2c_dev *i2c_dev) ++{ ++ struct bcm2835_debug *d; ++ unsigned int i; ++ ++ for (i = 0; i < i2c_dev->debug_num; i++) { ++ d = &i2c_dev->debug[i]; ++ if (d->status == ~0) ++ bcm2835_debug_print_msg(i2c_dev, d->msg, d->msg_idx, ++ i2c_dev->debug_num_msgs, "start_transfer"); ++ else ++ bcm2835_debug_print_status(i2c_dev, d); ++ } ++ if (i2c_dev->debug_num >= BCM2835_DEBUG_MAX) ++ pr_info("BCM2835_DEBUG_MAX reached\n"); ++} ++ + static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev, + u32 reg, u32 val) + { +@@ -170,6 +252,7 @@ static void bcm2835_i2c_start_transfer(s + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); ++ bcm2835_debug_add(i2c_dev, ~0); + } + + /* +@@ -187,6 +270,7 @@ static irqreturn_t bcm2835_i2c_isr(int t + u32 val, err; + + val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); ++ bcm2835_debug_add(i2c_dev, val); + + err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); + if (err) { +@@ -251,6 +335,13 @@ static int bcm2835_i2c_xfer(struct i2c_a + unsigned long time_left; + int i, ret; + ++ if (debug) ++ i2c_dev->debug_num_msgs = num; ++ ++ if (debug > 2) ++ for (i = 0; i < num; i++) ++ bcm2835_debug_print_msg(i2c_dev, &msgs[i], i + 1, num, __func__); ++ + for (i = 0; i < (num - 1); i++) + if (msgs[i].flags & I2C_M_RD) { + dev_warn_once(i2c_dev->dev, +@@ -270,6 +361,10 @@ static int bcm2835_i2c_xfer(struct i2c_a + + time_left = wait_for_completion_timeout(&i2c_dev->completion, + adap->timeout); ++ if (debug > 1 || (debug && (!time_left || i2c_dev->msg_err))) ++ bcm2835_debug_print(i2c_dev); ++ i2c_dev->debug_num_msgs = 0; ++ i2c_dev->debug_num = 0; + if (!time_left) { + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, + BCM2835_I2C_C_CLEAR); +@@ -280,7 +375,9 @@ static int bcm2835_i2c_xfer(struct i2c_a + if (!i2c_dev->msg_err) + return num; + +- dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); ++ if (debug) ++ dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", ++ i2c_dev->msg_err); + + if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) + return -EREMOTEIO; diff --git a/target/linux/brcm2708/patches-4.9/0113-i2c-bcm2835-Add-support-for-dynamic-clock.patch b/target/linux/brcm2708/patches-4.9/0113-i2c-bcm2835-Add-support-for-dynamic-clock.patch deleted file mode 100644 index 35ab56c510..0000000000 --- a/target/linux/brcm2708/patches-4.9/0113-i2c-bcm2835-Add-support-for-dynamic-clock.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 788daf43a9078fc592eddfa0b959bc92b03bbb53 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 27 Sep 2016 01:00:08 +0200 -Subject: [PATCH] i2c: bcm2835: Add support for dynamic clock -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Support a dynamic clock by reading the frequency and setting the -divisor in the transfer function instead of during probe. - -Signed-off-by: Noralf Trønnes -Reviewed-by: Martin Sperl ---- - drivers/i2c/busses/i2c-bcm2835.c | 51 +++++++++++++++++++++++++--------------- - 1 file changed, 32 insertions(+), 19 deletions(-) - ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -58,6 +58,7 @@ struct bcm2835_i2c_dev { - void __iomem *regs; - struct clk *clk; - int irq; -+ u32 bus_clk_rate; - struct i2c_adapter adapter; - struct completion completion; - struct i2c_msg *curr_msg; -@@ -78,6 +79,30 @@ static inline u32 bcm2835_i2c_readl(stru - return readl(i2c_dev->regs + reg); - } - -+static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) -+{ -+ u32 divider; -+ -+ divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), -+ i2c_dev->bus_clk_rate); -+ /* -+ * Per the datasheet, the register is always interpreted as an even -+ * number, by rounding down. In other words, the LSB is ignored. So, -+ * if the LSB is set, increment the divider to avoid any issue. -+ */ -+ if (divider & 1) -+ divider++; -+ if ((divider < BCM2835_I2C_CDIV_MIN) || -+ (divider > BCM2835_I2C_CDIV_MAX)) { -+ dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n"); -+ return -EINVAL; -+ } -+ -+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); -+ -+ return 0; -+} -+ - static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev) - { - u32 val; -@@ -224,7 +249,7 @@ static int bcm2835_i2c_xfer(struct i2c_a - { - struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); - unsigned long time_left; -- int i; -+ int i, ret; - - for (i = 0; i < (num - 1); i++) - if (msgs[i].flags & I2C_M_RD) { -@@ -233,6 +258,10 @@ static int bcm2835_i2c_xfer(struct i2c_a - return -EOPNOTSUPP; - } - -+ ret = bcm2835_i2c_set_divider(i2c_dev); -+ if (ret) -+ return ret; -+ - i2c_dev->curr_msg = msgs; - i2c_dev->num_msgs = num; - reinit_completion(&i2c_dev->completion); -@@ -282,7 +311,6 @@ static int bcm2835_i2c_probe(struct plat - { - struct bcm2835_i2c_dev *i2c_dev; - struct resource *mem, *irq; -- u32 bus_clk_rate, divider; - int ret; - struct i2c_adapter *adap; - -@@ -306,28 +334,13 @@ static int bcm2835_i2c_probe(struct plat - } - - ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", -- &bus_clk_rate); -+ &i2c_dev->bus_clk_rate); - if (ret < 0) { - dev_warn(&pdev->dev, - "Could not read clock-frequency property\n"); -- bus_clk_rate = 100000; -+ i2c_dev->bus_clk_rate = 100000; - } - -- divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), bus_clk_rate); -- /* -- * Per the datasheet, the register is always interpreted as an even -- * number, by rounding down. In other words, the LSB is ignored. So, -- * if the LSB is set, increment the divider to avoid any issue. -- */ -- if (divider & 1) -- divider++; -- if ((divider < BCM2835_I2C_CDIV_MIN) || -- (divider > BCM2835_I2C_CDIV_MAX)) { -- dev_err(&pdev->dev, "Invalid clock-frequency\n"); -- return -ENODEV; -- } -- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); -- - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!irq) { - dev_err(&pdev->dev, "No IRQ resource\n"); diff --git a/target/linux/brcm2708/patches-4.9/0114-arm64-Add-CONFIG_ARCH_BCM2835.patch b/target/linux/brcm2708/patches-4.9/0114-arm64-Add-CONFIG_ARCH_BCM2835.patch new file mode 100644 index 0000000000..34ab47e7b4 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0114-arm64-Add-CONFIG_ARCH_BCM2835.patch @@ -0,0 +1,16 @@ +From c3dc479ae9620756f981ad2c5afeee92295f8ea3 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 31 Dec 2016 14:15:50 +0000 +Subject: [PATCH] arm64: Add CONFIG_ARCH_BCM2835 + +--- + arch/arm64/configs/bcmrpi3_defconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm64/configs/bcmrpi3_defconfig ++++ b/arch/arm64/configs/bcmrpi3_defconfig +@@ -1332,3 +1332,4 @@ CONFIG_ARM64_CRYPTO=y + CONFIG_CRC_ITU_T=y + CONFIG_LIBCRC32C=y + CONFIG_BCM2708_VCHIQ=n ++CONFIG_ARCH_BCM2835=y diff --git a/target/linux/brcm2708/patches-4.9/0114-i2c-bcm2835-Add-debug-support.patch b/target/linux/brcm2708/patches-4.9/0114-i2c-bcm2835-Add-debug-support.patch deleted file mode 100644 index 30830672f9..0000000000 --- a/target/linux/brcm2708/patches-4.9/0114-i2c-bcm2835-Add-debug-support.patch +++ /dev/null @@ -1,189 +0,0 @@ -From 133b068ffc08e2c1a0c9d5fa781107e3d95ba9bc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 1 Nov 2016 15:15:41 +0100 -Subject: [PATCH] i2c: bcm2835: Add debug support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This adds a debug module parameter to aid in debugging transfer issues -by printing info to the kernel log. When enabled, status values are -collected in the interrupt routine and msg info in -bcm2835_i2c_start_transfer(). This is done in a way that tries to avoid -affecting timing. Having printk in the isr can mask issues. - -debug values (additive): -1: Print info on error -2: Print info on all transfers -3: Print messages before transfer is started - -The value can be changed at runtime: -/sys/module/i2c_bcm2835/parameters/debug - -Example output, debug=3: -[ 747.114448] bcm2835_i2c_xfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] -[ 747.114463] bcm2835_i2c_xfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] -[ 747.117809] start_transfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] -[ 747.117825] isr: remain=2, status=0x30000055 : TA TXW TXD TXE [i2c1] -[ 747.117839] start_transfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] -[ 747.117849] isr: remain=32, status=0xd0000039 : TA RXR TXD RXD [i2c1] -[ 747.117861] isr: remain=20, status=0xd0000039 : TA RXR TXD RXD [i2c1] -[ 747.117870] isr: remain=8, status=0x32 : DONE TXD RXD [i2c1] - -Signed-off-by: Noralf Trønnes ---- - drivers/i2c/busses/i2c-bcm2835.c | 99 +++++++++++++++++++++++++++++++++++++++- - 1 file changed, 98 insertions(+), 1 deletion(-) - ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -53,6 +53,18 @@ - #define BCM2835_I2C_CDIV_MIN 0x0002 - #define BCM2835_I2C_CDIV_MAX 0xFFFE - -+static unsigned int debug; -+module_param(debug, uint, 0644); -+MODULE_PARM_DESC(debug, "1=err, 2=isr, 3=xfer"); -+ -+#define BCM2835_DEBUG_MAX 512 -+struct bcm2835_debug { -+ struct i2c_msg *msg; -+ int msg_idx; -+ size_t remain; -+ u32 status; -+}; -+ - struct bcm2835_i2c_dev { - struct device *dev; - void __iomem *regs; -@@ -66,8 +78,78 @@ struct bcm2835_i2c_dev { - u32 msg_err; - u8 *msg_buf; - size_t msg_buf_remaining; -+ struct bcm2835_debug debug[BCM2835_DEBUG_MAX]; -+ unsigned int debug_num; -+ unsigned int debug_num_msgs; - }; - -+static inline void bcm2835_debug_add(struct bcm2835_i2c_dev *i2c_dev, u32 s) -+{ -+ if (!i2c_dev->debug_num_msgs || i2c_dev->debug_num >= BCM2835_DEBUG_MAX) -+ return; -+ -+ i2c_dev->debug[i2c_dev->debug_num].msg = i2c_dev->curr_msg; -+ i2c_dev->debug[i2c_dev->debug_num].msg_idx = -+ i2c_dev->debug_num_msgs - i2c_dev->num_msgs; -+ i2c_dev->debug[i2c_dev->debug_num].remain = i2c_dev->msg_buf_remaining; -+ i2c_dev->debug[i2c_dev->debug_num].status = s; -+ i2c_dev->debug_num++; -+} -+ -+static void bcm2835_debug_print_status(struct bcm2835_i2c_dev *i2c_dev, -+ struct bcm2835_debug *d) -+{ -+ u32 s = d->status; -+ -+ pr_info("isr: remain=%zu, status=0x%x : %s%s%s%s%s%s%s%s%s%s [i2c%d]\n", -+ d->remain, s, -+ s & BCM2835_I2C_S_TA ? "TA " : "", -+ s & BCM2835_I2C_S_DONE ? "DONE " : "", -+ s & BCM2835_I2C_S_TXW ? "TXW " : "", -+ s & BCM2835_I2C_S_RXR ? "RXR " : "", -+ s & BCM2835_I2C_S_TXD ? "TXD " : "", -+ s & BCM2835_I2C_S_RXD ? "RXD " : "", -+ s & BCM2835_I2C_S_TXE ? "TXE " : "", -+ s & BCM2835_I2C_S_RXF ? "RXF " : "", -+ s & BCM2835_I2C_S_ERR ? "ERR " : "", -+ s & BCM2835_I2C_S_CLKT ? "CLKT " : "", -+ i2c_dev->adapter.nr); -+} -+ -+static void bcm2835_debug_print_msg(struct bcm2835_i2c_dev *i2c_dev, -+ struct i2c_msg *msg, int i, int total, -+ const char *fname) -+{ -+ pr_info("%s: msg(%d/%d) %s addr=0x%02x, len=%u flags=%s%s%s%s%s%s%s [i2c%d]\n", -+ fname, i, total, -+ msg->flags & I2C_M_RD ? "read" : "write", msg->addr, msg->len, -+ msg->flags & I2C_M_TEN ? "TEN" : "", -+ msg->flags & I2C_M_RECV_LEN ? "RECV_LEN" : "", -+ msg->flags & I2C_M_NO_RD_ACK ? "NO_RD_ACK" : "", -+ msg->flags & I2C_M_IGNORE_NAK ? "IGNORE_NAK" : "", -+ msg->flags & I2C_M_REV_DIR_ADDR ? "REV_DIR_ADDR" : "", -+ msg->flags & I2C_M_NOSTART ? "NOSTART" : "", -+ msg->flags & I2C_M_STOP ? "STOP" : "", -+ i2c_dev->adapter.nr); -+} -+ -+static void bcm2835_debug_print(struct bcm2835_i2c_dev *i2c_dev) -+{ -+ struct bcm2835_debug *d; -+ unsigned int i; -+ -+ for (i = 0; i < i2c_dev->debug_num; i++) { -+ d = &i2c_dev->debug[i]; -+ if (d->status == ~0) -+ bcm2835_debug_print_msg(i2c_dev, d->msg, d->msg_idx, -+ i2c_dev->debug_num_msgs, "start_transfer"); -+ else -+ bcm2835_debug_print_status(i2c_dev, d); -+ } -+ if (i2c_dev->debug_num >= BCM2835_DEBUG_MAX) -+ pr_info("BCM2835_DEBUG_MAX reached\n"); -+} -+ - static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev, - u32 reg, u32 val) - { -@@ -170,6 +252,7 @@ static void bcm2835_i2c_start_transfer(s - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); -+ bcm2835_debug_add(i2c_dev, ~0); - } - - /* -@@ -187,6 +270,7 @@ static irqreturn_t bcm2835_i2c_isr(int t - u32 val, err; - - val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); -+ bcm2835_debug_add(i2c_dev, val); - - err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); - if (err) { -@@ -251,6 +335,13 @@ static int bcm2835_i2c_xfer(struct i2c_a - unsigned long time_left; - int i, ret; - -+ if (debug) -+ i2c_dev->debug_num_msgs = num; -+ -+ if (debug > 2) -+ for (i = 0; i < num; i++) -+ bcm2835_debug_print_msg(i2c_dev, &msgs[i], i + 1, num, __func__); -+ - for (i = 0; i < (num - 1); i++) - if (msgs[i].flags & I2C_M_RD) { - dev_warn_once(i2c_dev->dev, -@@ -270,6 +361,10 @@ static int bcm2835_i2c_xfer(struct i2c_a - - time_left = wait_for_completion_timeout(&i2c_dev->completion, - adap->timeout); -+ if (debug > 1 || (debug && (!time_left || i2c_dev->msg_err))) -+ bcm2835_debug_print(i2c_dev); -+ i2c_dev->debug_num_msgs = 0; -+ i2c_dev->debug_num = 0; - if (!time_left) { - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, - BCM2835_I2C_C_CLEAR); -@@ -280,7 +375,9 @@ static int bcm2835_i2c_xfer(struct i2c_a - if (!i2c_dev->msg_err) - return num; - -- dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); -+ if (debug) -+ dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", -+ i2c_dev->msg_err); - - if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) - return -EREMOTEIO; diff --git a/target/linux/brcm2708/patches-4.9/0115-Add-support-for-Silicon-Labs-Si7013-20-21-humidity-t.patch b/target/linux/brcm2708/patches-4.9/0115-Add-support-for-Silicon-Labs-Si7013-20-21-humidity-t.patch new file mode 100644 index 0000000000..119b054260 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0115-Add-support-for-Silicon-Labs-Si7013-20-21-humidity-t.patch @@ -0,0 +1,77 @@ +From 69d0de7d07ec016f2956237ec141bb62ff7ae36c Mon Sep 17 00:00:00 2001 +From: Alex Tucker +Date: Tue, 13 Dec 2016 19:50:18 +0000 +Subject: [PATCH] Add support for Silicon Labs Si7013/20/21 + humidity/temperature sensor. + +--- + arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts | 49 +++++++++++++---------- + 1 file changed, 28 insertions(+), 21 deletions(-) + +--- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts +@@ -1,34 +1,41 @@ +-// Definitions for a few digital barometric pressure and temperature sensors ++// Definitions for I2C based sensors using the Industrial IO interface. + /dts-v1/; + /plugin/; + + / { +- compatible = "brcm,bcm2708"; ++ compatible = "brcm,bcm2708"; + +- fragment@0 { +- target = <&i2c_arm>; +- __overlay__ { +- #address-cells = <1>; +- #size-cells = <0>; +- status = "okay"; +- +- bmp085: bmp085@77 { +- compatible = "bosch,bmp085"; +- reg = <0x77>; +- default-oversampling = <3>; +- status = "disable"; +- }; +- +- bmp280: bmp280@76 { +- compatible = "bosch,bmp280"; +- reg = <0x76>; +- status = "disable"; +- }; +- }; +- }; ++ fragment@0 { ++ target = <&i2c_arm>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ bmp085: bmp085@77 { ++ compatible = "bosch,bmp085"; ++ reg = <0x77>; ++ default-oversampling = <3>; ++ status = "disable"; ++ }; ++ ++ bmp280: bmp280@76 { ++ compatible = "bosch,bmp280"; ++ reg = <0x76>; ++ status = "disable"; ++ }; ++ ++ si7020: si7020@40 { ++ compatible = "si7020"; ++ reg = <0x40>; ++ status = "disable"; ++ }; ++ }; ++ }; + + __overrides__ { + bmp085 = <&bmp085>,"status"; + bmp280 = <&bmp280>,"status"; ++ si7020 = <&si7020>,"status"; + }; + }; diff --git a/target/linux/brcm2708/patches-4.9/0115-arm64-Add-CONFIG_ARCH_BCM2835.patch b/target/linux/brcm2708/patches-4.9/0115-arm64-Add-CONFIG_ARCH_BCM2835.patch deleted file mode 100644 index 2f84052eb0..0000000000 --- a/target/linux/brcm2708/patches-4.9/0115-arm64-Add-CONFIG_ARCH_BCM2835.patch +++ /dev/null @@ -1,16 +0,0 @@ -From fbf6217ff64c7bf6fac6eafd07f23d8c2356b088 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 31 Dec 2016 14:15:50 +0000 -Subject: [PATCH] arm64: Add CONFIG_ARCH_BCM2835 - ---- - arch/arm64/configs/bcmrpi3_defconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm64/configs/bcmrpi3_defconfig -+++ b/arch/arm64/configs/bcmrpi3_defconfig -@@ -1332,3 +1332,4 @@ CONFIG_ARM64_CRYPTO=y - CONFIG_CRC_ITU_T=y - CONFIG_LIBCRC32C=y - CONFIG_BCM2708_VCHIQ=n -+CONFIG_ARCH_BCM2835=y diff --git a/target/linux/brcm2708/patches-4.9/0116-Add-support-for-Silicon-Labs-Si7013-20-21-humidity-t.patch b/target/linux/brcm2708/patches-4.9/0116-Add-support-for-Silicon-Labs-Si7013-20-21-humidity-t.patch deleted file mode 100644 index 8ab820756e..0000000000 --- a/target/linux/brcm2708/patches-4.9/0116-Add-support-for-Silicon-Labs-Si7013-20-21-humidity-t.patch +++ /dev/null @@ -1,77 +0,0 @@ -From d7a7355799204dc94d323d8e58ff6d2d3296e764 Mon Sep 17 00:00:00 2001 -From: Alex Tucker -Date: Tue, 13 Dec 2016 19:50:18 +0000 -Subject: [PATCH] Add support for Silicon Labs Si7013/20/21 - humidity/temperature sensor. - ---- - arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts | 49 +++++++++++++---------- - 1 file changed, 28 insertions(+), 21 deletions(-) - ---- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts -+++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts -@@ -1,34 +1,41 @@ --// Definitions for a few digital barometric pressure and temperature sensors -+// Definitions for I2C based sensors using the Industrial IO interface. - /dts-v1/; - /plugin/; - - / { -- compatible = "brcm,bcm2708"; -+ compatible = "brcm,bcm2708"; - -- fragment@0 { -- target = <&i2c_arm>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- bmp085: bmp085@77 { -- compatible = "bosch,bmp085"; -- reg = <0x77>; -- default-oversampling = <3>; -- status = "disable"; -- }; -- -- bmp280: bmp280@76 { -- compatible = "bosch,bmp280"; -- reg = <0x76>; -- status = "disable"; -- }; -- }; -- }; -+ fragment@0 { -+ target = <&i2c_arm>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ bmp085: bmp085@77 { -+ compatible = "bosch,bmp085"; -+ reg = <0x77>; -+ default-oversampling = <3>; -+ status = "disable"; -+ }; -+ -+ bmp280: bmp280@76 { -+ compatible = "bosch,bmp280"; -+ reg = <0x76>; -+ status = "disable"; -+ }; -+ -+ si7020: si7020@40 { -+ compatible = "si7020"; -+ reg = <0x40>; -+ status = "disable"; -+ }; -+ }; -+ }; - - __overrides__ { - bmp085 = <&bmp085>,"status"; - bmp280 = <&bmp280>,"status"; -+ si7020 = <&si7020>,"status"; - }; - }; diff --git a/target/linux/brcm2708/patches-4.9/0116-Document-the-si7020-option.patch b/target/linux/brcm2708/patches-4.9/0116-Document-the-si7020-option.patch new file mode 100644 index 0000000000..0319ca43a2 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0116-Document-the-si7020-option.patch @@ -0,0 +1,21 @@ +From ed753b7389b8c65af0b4266c001ef0343fb1c30e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 3 Jan 2017 21:27:46 +0000 +Subject: [PATCH] Document the si7020 option + +--- + arch/arm/boot/dts/overlays/README | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -549,6 +549,9 @@ Params: bmp085 Select t + + bmp280 Select the Bosch sensortronic BMP280 + ++ si7020 Select the Silicon Labs Si7013/20/21 humidity/ ++ temperature sensor ++ + + Name: i2c0-bcm2708 + Info: Enable the i2c_bcm2708 driver for the i2c0 bus. Not all pin combinations diff --git a/target/linux/brcm2708/patches-4.9/0117-Document-the-si7020-option.patch b/target/linux/brcm2708/patches-4.9/0117-Document-the-si7020-option.patch deleted file mode 100644 index 67b72c9f3c..0000000000 --- a/target/linux/brcm2708/patches-4.9/0117-Document-the-si7020-option.patch +++ /dev/null @@ -1,21 +0,0 @@ -From e6be13c337640f69fc71dcf6b6dd741dc5664f85 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 3 Jan 2017 21:27:46 +0000 -Subject: [PATCH] Document the si7020 option - ---- - arch/arm/boot/dts/overlays/README | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -549,6 +549,9 @@ Params: bmp085 Select t - - bmp280 Select the Bosch sensortronic BMP280 - -+ si7020 Select the Silicon Labs Si7013/20/21 humidity/ -+ temperature sensor -+ - - Name: i2c0-bcm2708 - Info: Enable the i2c_bcm2708 driver for the i2c0 bus. Not all pin combinations diff --git a/target/linux/brcm2708/patches-4.9/0117-pisound-improvements.patch b/target/linux/brcm2708/patches-4.9/0117-pisound-improvements.patch new file mode 100644 index 0000000000..f914bfc3ad --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0117-pisound-improvements.patch @@ -0,0 +1,294 @@ +From 8ed8e29b19dba95a7a6c2364c2bb32d926601713 Mon Sep 17 00:00:00 2001 +From: Giedrius Trainavicius +Date: Thu, 5 Jan 2017 02:38:16 +0200 +Subject: [PATCH] pisound improvements: + +* Added a writable sysfs object to enable scripts / user space software +to blink MIDI activity LEDs for variable duration. +* Improved hw_param constraints setting. +* Added compatibility with S16_LE sample format. +* Exposed some simple placeholder volume controls, so the card appears +in volumealsa widget. + +Signed-off-by: Giedrius Trainavicius +--- + sound/soc/bcm/pisound.c | 175 ++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 154 insertions(+), 21 deletions(-) + +--- a/sound/soc/bcm/pisound.c ++++ b/sound/soc/bcm/pisound.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + static int pisnd_spi_init(struct device *dev); + static void pisnd_spi_uninit(void); +@@ -214,6 +215,9 @@ static char g_serial_num[11]; + static char g_id[25]; + static char g_version[5]; + ++static uint8_t g_ledFlashDuration; ++static bool g_ledFlashDurationChanged; ++ + DEFINE_KFIFO(spi_fifo_in, uint8_t, FIFO_SIZE); + DEFINE_KFIFO(spi_fifo_out, uint8_t, FIFO_SIZE); + +@@ -396,8 +400,13 @@ static void pisnd_work_handler(struct wo + val = 0; + tx = 0; + +- if (kfifo_get(&spi_fifo_out, &val)) ++ if (g_ledFlashDurationChanged) { ++ tx = 0xf000 | g_ledFlashDuration; ++ g_ledFlashDuration = 0; ++ g_ledFlashDurationChanged = false; ++ } else if (kfifo_get(&spi_fifo_out, &val)) { + tx = 0x0f00 | val; ++ } + + rx = spi_transfer16(tx); + +@@ -410,6 +419,7 @@ static void pisnd_work_handler(struct wo + } while (rx != 0 + || !kfifo_is_empty(&spi_fifo_out) + || pisnd_spi_has_more() ++ || g_ledFlashDurationChanged + ); + + if (!kfifo_is_empty(&spi_fifo_in) && g_recvCallback) +@@ -569,7 +579,7 @@ static int pisnd_spi_init(struct device + } + + /* Flash the LEDs. */ +- spi_transfer16(0xf000); ++ spi_transfer16(0xf008); + + ret = pisnd_spi_gpio_irq_init(dev); + if (ret < 0) { +@@ -610,6 +620,14 @@ static void pisnd_spi_uninit(void) + pisnd_spi_gpio_uninit(); + } + ++static void pisnd_spi_flash_leds(uint8_t duration) ++{ ++ g_ledFlashDuration = duration; ++ g_ledFlashDurationChanged = true; ++ printd("schedule from spi_flash_leds\n"); ++ pisnd_schedule_process(TASK_PROCESS); ++} ++ + static void pisnd_spi_send(uint8_t val) + { + kfifo_put(&spi_fifo_out, val); +@@ -658,6 +676,83 @@ static const struct of_device_id pisound + {}, + }; + ++enum { ++ SWITCH = 0, ++ VOLUME = 1, ++}; ++ ++static int pisnd_ctl_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ if (kcontrol->private_value == SWITCH) { ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; ++ uinfo->count = 1; ++ uinfo->value.integer.min = 0; ++ uinfo->value.integer.max = 1; ++ return 0; ++ } else if (kcontrol->private_value == VOLUME) { ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; ++ uinfo->count = 1; ++ uinfo->value.integer.min = 0; ++ uinfo->value.integer.max = 100; ++ return 0; ++ } ++ return -EINVAL; ++} ++ ++static int pisnd_ctl_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ if (kcontrol->private_value == SWITCH) { ++ ucontrol->value.integer.value[0] = 1; ++ return 0; ++ } else if (kcontrol->private_value == VOLUME) { ++ ucontrol->value.integer.value[0] = 100; ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static struct snd_kcontrol_new pisnd_ctl[] = { ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "PCM Playback Switch", ++ .index = 0, ++ .private_value = SWITCH, ++ .access = SNDRV_CTL_ELEM_ACCESS_READ, ++ .info = pisnd_ctl_info, ++ .get = pisnd_ctl_get, ++ }, ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "PCM Playback Volume", ++ .index = 0, ++ .private_value = VOLUME, ++ .access = SNDRV_CTL_ELEM_ACCESS_READ, ++ .info = pisnd_ctl_info, ++ .get = pisnd_ctl_get, ++ }, ++}; ++ ++static int pisnd_ctl_init(struct snd_card *card) ++{ ++ int err, i; ++ ++ for (i = 0; i < ARRAY_SIZE(pisnd_ctl); ++i) { ++ err = snd_ctl_add(card, snd_ctl_new1(&pisnd_ctl[i], NULL)); ++ if (err < 0) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int pisnd_ctl_uninit(void) ++{ ++ return 0; ++} ++ + static struct gpio_desc *osr0, *osr1, *osr2; + static struct gpio_desc *reset; + static struct gpio_desc *button; +@@ -667,6 +762,14 @@ static int pisnd_hw_params( + struct snd_pcm_hw_params *params + ) + { ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ /* pisound runs on fixed 32 clock counts per channel, ++ * as generated by the master ADC. ++ */ ++ snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2); ++ + printd("rate = %d\n", params_rate(params)); + printd("ch = %d\n", params_channels(params)); + printd("bits = %u\n", +@@ -711,16 +814,6 @@ static struct snd_pcm_hw_constraint_list + .mask = 0, + }; + +-static unsigned int sample_bits[] = { +- 24, 32 +-}; +- +-static struct snd_pcm_hw_constraint_list constraints_sample_bits = { +- .count = ARRAY_SIZE(sample_bits), +- .list = sample_bits, +- .mask = 0, +-}; +- + static int pisnd_startup(struct snd_pcm_substream *substream) + { + int err = snd_pcm_hw_constraint_list( +@@ -733,11 +826,21 @@ static int pisnd_startup(struct snd_pcm_ + if (err < 0) + return err; + +- err = snd_pcm_hw_constraint_list( ++ err = snd_pcm_hw_constraint_single( + substream->runtime, +- 0, +- SNDRV_PCM_HW_PARAM_SAMPLE_BITS, +- &constraints_sample_bits ++ SNDRV_PCM_HW_PARAM_CHANNELS, ++ 2 ++ ); ++ ++ if (err < 0) ++ return err; ++ ++ err = snd_pcm_hw_constraint_mask64( ++ substream->runtime, ++ SNDRV_PCM_HW_PARAM_FORMAT, ++ SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S24_LE | ++ SNDRV_PCM_FMTBIT_S32_LE + ); + + if (err < 0) +@@ -771,14 +874,23 @@ static int pisnd_card_probe(struct snd_s + { + int err = pisnd_midi_init(card->snd_card); + +- if (err < 0) ++ if (err < 0) { + printe("pisnd_midi_init failed: %d\n", err); ++ return err; ++ } + +- return err; ++ err = pisnd_ctl_init(card->snd_card); ++ if (err < 0) { ++ printe("pisnd_ctl_init failed: %d\n", err); ++ return err; ++ } ++ ++ return 0; + } + + static int pisnd_card_remove(struct snd_soc_card *card) + { ++ pisnd_ctl_uninit(); + pisnd_midi_uninit(); + return 0; + } +@@ -870,17 +982,38 @@ static ssize_t pisnd_version_show( + return sprintf(buf, "%s\n", pisnd_spi_get_version()); + } + ++static ssize_t pisnd_led_store( ++ struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, ++ size_t length ++ ) ++{ ++ uint32_t timeout; ++ int err; ++ ++ err = kstrtou32(buf, 10, &timeout); ++ ++ if (err == 0 && timeout <= 255) ++ pisnd_spi_flash_leds(timeout); ++ ++ return length; ++} ++ + static struct kobj_attribute pisnd_serial_attribute = +- __ATTR(serial, 0644, pisnd_serial_show, NULL); ++ __ATTR(serial, 0444, pisnd_serial_show, NULL); + static struct kobj_attribute pisnd_id_attribute = +- __ATTR(id, 0644, pisnd_id_show, NULL); ++ __ATTR(id, 0444, pisnd_id_show, NULL); + static struct kobj_attribute pisnd_version_attribute = +- __ATTR(version, 0644, pisnd_version_show, NULL); ++ __ATTR(version, 0444, pisnd_version_show, NULL); ++static struct kobj_attribute pisnd_led_attribute = ++ __ATTR(led, 0644, NULL, pisnd_led_store); + + static struct attribute *attrs[] = { + &pisnd_serial_attribute.attr, + &pisnd_id_attribute.attr, + &pisnd_version_attribute.attr, ++ &pisnd_led_attribute.attr, + NULL + }; + diff --git a/target/linux/brcm2708/patches-4.9/0118-Add-driver_name-property.patch b/target/linux/brcm2708/patches-4.9/0118-Add-driver_name-property.patch new file mode 100644 index 0000000000..bfda58aa5a --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0118-Add-driver_name-property.patch @@ -0,0 +1,20 @@ +From 341bc67d361def1f23a96c512ab6bc39f32b3601 Mon Sep 17 00:00:00 2001 +From: Aaron Shaw +Date: Tue, 10 Jan 2017 16:05:41 +0000 +Subject: [PATCH] Add driver_name property + +Add driver name property for use with 5.1 passthrough audio in LibreElec and other Kodi based OSs +--- + sound/soc/bcm/justboom-dac.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/soc/bcm/justboom-dac.c ++++ b/sound/soc/bcm/justboom-dac.c +@@ -98,6 +98,7 @@ static struct snd_soc_dai_link snd_rpi_j + /* audio machine driver */ + static struct snd_soc_card snd_rpi_justboom_dac = { + .name = "snd_rpi_justboom_dac", ++ .driver_name = "JustBoomDac", + .owner = THIS_MODULE, + .dai_link = snd_rpi_justboom_dac_dai, + .num_links = ARRAY_SIZE(snd_rpi_justboom_dac_dai), diff --git a/target/linux/brcm2708/patches-4.9/0118-pisound-improvements.patch b/target/linux/brcm2708/patches-4.9/0118-pisound-improvements.patch deleted file mode 100644 index af5c3b3fa6..0000000000 --- a/target/linux/brcm2708/patches-4.9/0118-pisound-improvements.patch +++ /dev/null @@ -1,294 +0,0 @@ -From 811d783519254a955ccb7a43b1d8d3f2d29a9a79 Mon Sep 17 00:00:00 2001 -From: Giedrius Trainavicius -Date: Thu, 5 Jan 2017 02:38:16 +0200 -Subject: [PATCH] pisound improvements: - -* Added a writable sysfs object to enable scripts / user space software -to blink MIDI activity LEDs for variable duration. -* Improved hw_param constraints setting. -* Added compatibility with S16_LE sample format. -* Exposed some simple placeholder volume controls, so the card appears -in volumealsa widget. - -Signed-off-by: Giedrius Trainavicius ---- - sound/soc/bcm/pisound.c | 175 ++++++++++++++++++++++++++++++++++++++++++------ - 1 file changed, 154 insertions(+), 21 deletions(-) - ---- a/sound/soc/bcm/pisound.c -+++ b/sound/soc/bcm/pisound.c -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include - - static int pisnd_spi_init(struct device *dev); - static void pisnd_spi_uninit(void); -@@ -214,6 +215,9 @@ static char g_serial_num[11]; - static char g_id[25]; - static char g_version[5]; - -+static uint8_t g_ledFlashDuration; -+static bool g_ledFlashDurationChanged; -+ - DEFINE_KFIFO(spi_fifo_in, uint8_t, FIFO_SIZE); - DEFINE_KFIFO(spi_fifo_out, uint8_t, FIFO_SIZE); - -@@ -396,8 +400,13 @@ static void pisnd_work_handler(struct wo - val = 0; - tx = 0; - -- if (kfifo_get(&spi_fifo_out, &val)) -+ if (g_ledFlashDurationChanged) { -+ tx = 0xf000 | g_ledFlashDuration; -+ g_ledFlashDuration = 0; -+ g_ledFlashDurationChanged = false; -+ } else if (kfifo_get(&spi_fifo_out, &val)) { - tx = 0x0f00 | val; -+ } - - rx = spi_transfer16(tx); - -@@ -410,6 +419,7 @@ static void pisnd_work_handler(struct wo - } while (rx != 0 - || !kfifo_is_empty(&spi_fifo_out) - || pisnd_spi_has_more() -+ || g_ledFlashDurationChanged - ); - - if (!kfifo_is_empty(&spi_fifo_in) && g_recvCallback) -@@ -569,7 +579,7 @@ static int pisnd_spi_init(struct device - } - - /* Flash the LEDs. */ -- spi_transfer16(0xf000); -+ spi_transfer16(0xf008); - - ret = pisnd_spi_gpio_irq_init(dev); - if (ret < 0) { -@@ -610,6 +620,14 @@ static void pisnd_spi_uninit(void) - pisnd_spi_gpio_uninit(); - } - -+static void pisnd_spi_flash_leds(uint8_t duration) -+{ -+ g_ledFlashDuration = duration; -+ g_ledFlashDurationChanged = true; -+ printd("schedule from spi_flash_leds\n"); -+ pisnd_schedule_process(TASK_PROCESS); -+} -+ - static void pisnd_spi_send(uint8_t val) - { - kfifo_put(&spi_fifo_out, val); -@@ -658,6 +676,83 @@ static const struct of_device_id pisound - {}, - }; - -+enum { -+ SWITCH = 0, -+ VOLUME = 1, -+}; -+ -+static int pisnd_ctl_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ if (kcontrol->private_value == SWITCH) { -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; -+ uinfo->count = 1; -+ uinfo->value.integer.min = 0; -+ uinfo->value.integer.max = 1; -+ return 0; -+ } else if (kcontrol->private_value == VOLUME) { -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -+ uinfo->count = 1; -+ uinfo->value.integer.min = 0; -+ uinfo->value.integer.max = 100; -+ return 0; -+ } -+ return -EINVAL; -+} -+ -+static int pisnd_ctl_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ if (kcontrol->private_value == SWITCH) { -+ ucontrol->value.integer.value[0] = 1; -+ return 0; -+ } else if (kcontrol->private_value == VOLUME) { -+ ucontrol->value.integer.value[0] = 100; -+ return 0; -+ } -+ -+ return -EINVAL; -+} -+ -+static struct snd_kcontrol_new pisnd_ctl[] = { -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "PCM Playback Switch", -+ .index = 0, -+ .private_value = SWITCH, -+ .access = SNDRV_CTL_ELEM_ACCESS_READ, -+ .info = pisnd_ctl_info, -+ .get = pisnd_ctl_get, -+ }, -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "PCM Playback Volume", -+ .index = 0, -+ .private_value = VOLUME, -+ .access = SNDRV_CTL_ELEM_ACCESS_READ, -+ .info = pisnd_ctl_info, -+ .get = pisnd_ctl_get, -+ }, -+}; -+ -+static int pisnd_ctl_init(struct snd_card *card) -+{ -+ int err, i; -+ -+ for (i = 0; i < ARRAY_SIZE(pisnd_ctl); ++i) { -+ err = snd_ctl_add(card, snd_ctl_new1(&pisnd_ctl[i], NULL)); -+ if (err < 0) -+ return err; -+ } -+ -+ return 0; -+} -+ -+static int pisnd_ctl_uninit(void) -+{ -+ return 0; -+} -+ - static struct gpio_desc *osr0, *osr1, *osr2; - static struct gpio_desc *reset; - static struct gpio_desc *button; -@@ -667,6 +762,14 @@ static int pisnd_hw_params( - struct snd_pcm_hw_params *params - ) - { -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ /* pisound runs on fixed 32 clock counts per channel, -+ * as generated by the master ADC. -+ */ -+ snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2); -+ - printd("rate = %d\n", params_rate(params)); - printd("ch = %d\n", params_channels(params)); - printd("bits = %u\n", -@@ -711,16 +814,6 @@ static struct snd_pcm_hw_constraint_list - .mask = 0, - }; - --static unsigned int sample_bits[] = { -- 24, 32 --}; -- --static struct snd_pcm_hw_constraint_list constraints_sample_bits = { -- .count = ARRAY_SIZE(sample_bits), -- .list = sample_bits, -- .mask = 0, --}; -- - static int pisnd_startup(struct snd_pcm_substream *substream) - { - int err = snd_pcm_hw_constraint_list( -@@ -733,11 +826,21 @@ static int pisnd_startup(struct snd_pcm_ - if (err < 0) - return err; - -- err = snd_pcm_hw_constraint_list( -+ err = snd_pcm_hw_constraint_single( - substream->runtime, -- 0, -- SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -- &constraints_sample_bits -+ SNDRV_PCM_HW_PARAM_CHANNELS, -+ 2 -+ ); -+ -+ if (err < 0) -+ return err; -+ -+ err = snd_pcm_hw_constraint_mask64( -+ substream->runtime, -+ SNDRV_PCM_HW_PARAM_FORMAT, -+ SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE - ); - - if (err < 0) -@@ -771,14 +874,23 @@ static int pisnd_card_probe(struct snd_s - { - int err = pisnd_midi_init(card->snd_card); - -- if (err < 0) -+ if (err < 0) { - printe("pisnd_midi_init failed: %d\n", err); -+ return err; -+ } - -- return err; -+ err = pisnd_ctl_init(card->snd_card); -+ if (err < 0) { -+ printe("pisnd_ctl_init failed: %d\n", err); -+ return err; -+ } -+ -+ return 0; - } - - static int pisnd_card_remove(struct snd_soc_card *card) - { -+ pisnd_ctl_uninit(); - pisnd_midi_uninit(); - return 0; - } -@@ -870,17 +982,38 @@ static ssize_t pisnd_version_show( - return sprintf(buf, "%s\n", pisnd_spi_get_version()); - } - -+static ssize_t pisnd_led_store( -+ struct kobject *kobj, -+ struct kobj_attribute *attr, -+ const char *buf, -+ size_t length -+ ) -+{ -+ uint32_t timeout; -+ int err; -+ -+ err = kstrtou32(buf, 10, &timeout); -+ -+ if (err == 0 && timeout <= 255) -+ pisnd_spi_flash_leds(timeout); -+ -+ return length; -+} -+ - static struct kobj_attribute pisnd_serial_attribute = -- __ATTR(serial, 0644, pisnd_serial_show, NULL); -+ __ATTR(serial, 0444, pisnd_serial_show, NULL); - static struct kobj_attribute pisnd_id_attribute = -- __ATTR(id, 0644, pisnd_id_show, NULL); -+ __ATTR(id, 0444, pisnd_id_show, NULL); - static struct kobj_attribute pisnd_version_attribute = -- __ATTR(version, 0644, pisnd_version_show, NULL); -+ __ATTR(version, 0444, pisnd_version_show, NULL); -+static struct kobj_attribute pisnd_led_attribute = -+ __ATTR(led, 0644, NULL, pisnd_led_store); - - static struct attribute *attrs[] = { - &pisnd_serial_attribute.attr, - &pisnd_id_attribute.attr, - &pisnd_version_attribute.attr, -+ &pisnd_led_attribute.attr, - NULL - }; - diff --git a/target/linux/brcm2708/patches-4.9/0119-Add-driver_name-paramater.patch b/target/linux/brcm2708/patches-4.9/0119-Add-driver_name-paramater.patch new file mode 100644 index 0000000000..2a3a6d8061 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0119-Add-driver_name-paramater.patch @@ -0,0 +1,20 @@ +From d87b665c7e4c09bf713ef6f45ceb11a8aacbcf5e Mon Sep 17 00:00:00 2001 +From: Aaron Shaw +Date: Tue, 10 Jan 2017 16:11:04 +0000 +Subject: [PATCH] Add driver_name paramater + +Add driver_name parameter for use with 5.1 passthrough audio in LibreElec and other Kodi OSs +--- + sound/soc/bcm/justboom-digi.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/soc/bcm/justboom-digi.c ++++ b/sound/soc/bcm/justboom-digi.c +@@ -154,6 +154,7 @@ static struct snd_soc_dai_link snd_rpi_j + /* audio machine driver */ + static struct snd_soc_card snd_rpi_justboom_digi = { + .name = "snd_rpi_justboom_digi", ++ .driver_name = "JustBoomDigi", + .owner = THIS_MODULE, + .dai_link = snd_rpi_justboom_digi_dai, + .num_links = ARRAY_SIZE(snd_rpi_justboom_digi_dai), diff --git a/target/linux/brcm2708/patches-4.9/0119-Revert-Revert-Added-driver-for-HiFiBerry-Amp-amplifi.patch b/target/linux/brcm2708/patches-4.9/0119-Revert-Revert-Added-driver-for-HiFiBerry-Amp-amplifi.patch deleted file mode 100644 index d57bfe19ba..0000000000 --- a/target/linux/brcm2708/patches-4.9/0119-Revert-Revert-Added-driver-for-HiFiBerry-Amp-amplifi.patch +++ /dev/null @@ -1,809 +0,0 @@ -From 20779cac1f8632b2315e1421fdecc960dac7f1c3 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 9 Jan 2017 09:23:06 +0000 -Subject: [PATCH] Revert "Revert "Added driver for HiFiBerry Amp amplifier - add-on board"" - -This reverts commit bf84babd8fffcb79c60f1342c2416f8e1e4b7af9. ---- - sound/soc/bcm/Kconfig | 7 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_amp.c | 129 +++++++++++++++ - sound/soc/codecs/Kconfig | 4 + - sound/soc/codecs/Makefile | 2 + - sound/soc/codecs/tas5713.c | 369 ++++++++++++++++++++++++++++++++++++++++++ - sound/soc/codecs/tas5713.h | 210 ++++++++++++++++++++++++ - 7 files changed, 723 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_amp.c - create mode 100644 sound/soc/codecs/tas5713.c - create mode 100644 sound/soc/codecs/tas5713.h - ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -38,6 +38,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DIGI - help - Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. - -+config SND_BCM2708_SOC_HIFIBERRY_AMP -+ tristate "Support for the HifiBerry Amp" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_TAS5713 -+ help -+ Say Y or M if you want to add support for the HifiBerry Amp amplifier board. -+ - config SND_BCM2708_SOC_RPI_DAC - tristate "Support for RPi-DAC" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -10,6 +10,7 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc- - - # BCM2708 Machine Support - snd-soc-adau1977-adc-objs := adau1977-adc.o -+snd-soc-hifiberry-amp-objs := hifiberry_amp.o - snd-soc-hifiberry-dac-objs := hifiberry_dac.o - snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o -@@ -27,6 +28,7 @@ snd-soc-allo-piano-dac-objs := allo-pian - snd-soc-pisound-objs := pisound.o - - obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_amp.c -@@ -0,0 +1,129 @@ -+/* -+ * ASoC Driver for HifiBerry AMP -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static int snd_rpi_hifiberry_amp_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ // ToDo: init of the dsp-registers. -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_amp_hw_params( struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params ) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); -+} -+ -+static struct snd_soc_ops snd_rpi_hifiberry_amp_ops = { -+ .hw_params = snd_rpi_hifiberry_amp_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = { -+ { -+ .name = "HifiBerry AMP", -+ .stream_name = "HifiBerry AMP HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "tas5713-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "tas5713.1-001b", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_hifiberry_amp_ops, -+ .init = snd_rpi_hifiberry_amp_init, -+ }, -+}; -+ -+ -+static struct snd_soc_card snd_rpi_hifiberry_amp = { -+ .name = "snd_rpi_hifiberry_amp", -+ .driver_name = "HifiberryAmp", -+ .owner = THIS_MODULE, -+ .dai_link = snd_rpi_hifiberry_amp_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), -+}; -+ -+static const struct of_device_id snd_rpi_hifiberry_amp_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-amp", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_amp_of_match); -+ -+ -+static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_hifiberry_amp.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_amp_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); -+ -+ if (ret != 0) { -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ } -+ -+ return ret; -+} -+ -+ -+static int snd_rpi_hifiberry_amp_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_hifiberry_amp); -+} -+ -+ -+static struct platform_driver snd_rpi_hifiberry_amp_driver = { -+ .driver = { -+ .name = "snd-hifiberry-amp", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_amp_of_match, -+ }, -+ .probe = snd_rpi_hifiberry_amp_probe, -+ .remove = snd_rpi_hifiberry_amp_remove, -+}; -+ -+ -+module_platform_driver(snd_rpi_hifiberry_amp_driver); -+ -+ -+MODULE_AUTHOR("Sebastian Eickhoff "); -+MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); -+MODULE_LICENSE("GPL v2"); ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -139,6 +139,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_TFA9879 if I2C - select SND_SOC_TLV320AIC23_I2C if I2C - select SND_SOC_TLV320AIC23_SPI if SPI_MASTER -+ select SND_SOC_TAS5713 if I2C - select SND_SOC_TLV320AIC26 if SPI_MASTER - select SND_SOC_TLV320AIC31XX if I2C - select SND_SOC_TLV320AIC32X4_I2C if I2C -@@ -821,6 +822,9 @@ config SND_SOC_TFA9879 - tristate "NXP Semiconductors TFA9879 amplifier" - depends on I2C - -+config SND_SOC_TAS5713 -+ tristate -+ - config SND_SOC_TLV320AIC23 - tristate - ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -144,6 +144,7 @@ snd-soc-tas5086-objs := tas5086.o - snd-soc-tas571x-objs := tas571x.o - snd-soc-tas5720-objs := tas5720.o - snd-soc-tfa9879-objs := tfa9879.o -+snd-soc-tas5713-objs := tas5713.o - snd-soc-tlv320aic23-objs := tlv320aic23.o - snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o - snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o -@@ -366,6 +367,7 @@ obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc - obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o - obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o - obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o -+obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o - obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o - obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o - obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o ---- /dev/null -+++ b/sound/soc/codecs/tas5713.c -@@ -0,0 +1,369 @@ -+/* -+ * ASoC Driver for TAS5713 -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "tas5713.h" -+ -+ -+static struct i2c_client *i2c; -+ -+struct tas5713_priv { -+ struct regmap *regmap; -+ int mclk_div; -+ struct snd_soc_codec *codec; -+}; -+ -+static struct tas5713_priv *priv_data; -+ -+ -+ -+ -+/* -+ * _ _ ___ _ ___ _ _ -+ * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___ -+ * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-< -+ * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/ -+ * -+ */ -+ -+static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1); -+ -+ -+static const struct snd_kcontrol_new tas5713_snd_controls[] = { -+ SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv), -+ SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv) -+}; -+ -+ -+ -+ -+/* -+ * __ __ _ _ ___ _ -+ * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _ -+ * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_| -+ * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static int tas5713_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ u16 blen = 0x00; -+ -+ struct snd_soc_codec *codec; -+ codec = dai->codec; -+ priv_data->codec = dai->codec; -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ blen = 0x03; -+ break; -+ case SNDRV_PCM_FORMAT_S20_3LE: -+ blen = 0x1; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ blen = 0x04; -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ blen = 0x05; -+ break; -+ default: -+ dev_err(dai->dev, "Unsupported word length: %u\n", -+ params_format(params)); -+ return -EINVAL; -+ } -+ -+ // set word length -+ snd_soc_update_bits(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen); -+ -+ return 0; -+} -+ -+ -+static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream) -+{ -+ unsigned int val = 0; -+ -+ struct tas5713_priv *tas5713; -+ struct snd_soc_codec *codec = dai->codec; -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ if (mute) { -+ val = TAS5713_SOFT_MUTE_ALL; -+ } -+ -+ return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val); -+} -+ -+ -+static const struct snd_soc_dai_ops tas5713_dai_ops = { -+ .hw_params = tas5713_hw_params, -+ .mute_stream = tas5713_mute_stream, -+}; -+ -+ -+static struct snd_soc_dai_driver tas5713_dai = { -+ .name = "tas5713-hifi", -+ .playback = { -+ .stream_name = "Playback", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_48000, -+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ), -+ }, -+ .ops = &tas5713_dai_ops, -+}; -+ -+ -+ -+ -+/* -+ * ___ _ ___ _ -+ * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _ -+ * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_| -+ * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static int tas5713_remove(struct snd_soc_codec *codec) -+{ -+ struct tas5713_priv *tas5713; -+ -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ return 0; -+} -+ -+ -+static int tas5713_probe(struct snd_soc_codec *codec) -+{ -+ struct tas5713_priv *tas5713; -+ int i, ret; -+ -+ i2c = container_of(codec->dev, struct i2c_client, dev); -+ -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ // Reset error -+ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -+ if (ret < 0) return ret; -+ -+ // Trim oscillator -+ ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); -+ if (ret < 0) return ret; -+ msleep(1000); -+ -+ // Reset error -+ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -+ if (ret < 0) return ret; -+ -+ // Clock mode: 44/48kHz, MCLK=64xfs -+ ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60); -+ if (ret < 0) return ret; -+ -+ // I2S 24bit -+ ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05); -+ if (ret < 0) return ret; -+ -+ // Unmute -+ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -+ if (ret < 0) return ret; -+ ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00); -+ if (ret < 0) return ret; -+ -+ // Set volume to 0db -+ ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00); -+ if (ret < 0) return ret; -+ -+ // Now start programming the default initialization sequence -+ for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) { -+ ret = i2c_master_send(i2c, -+ tas5713_init_sequence[i].data, -+ tas5713_init_sequence[i].size); -+ if (ret < 0) { -+ printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret); -+ } -+ } -+ -+ // Unmute -+ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -+ if (ret < 0) return ret; -+ -+ return 0; -+} -+ -+ -+static struct snd_soc_codec_driver soc_codec_dev_tas5713 = { -+ .probe = tas5713_probe, -+ .remove = tas5713_remove, -+ .controls = tas5713_snd_controls, -+ .num_controls = ARRAY_SIZE(tas5713_snd_controls), -+}; -+ -+ -+ -+ -+/* -+ * ___ ___ ___ ___ _ -+ * |_ _|_ ) __| | \ _ _(_)_ _____ _ _ -+ * | | / / (__ | |) | '_| \ V / -_) '_| -+ * |___/___\___| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static const struct reg_default tas5713_reg_defaults[] = { -+ { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB -+ { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB -+ { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB -+ { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB -+}; -+ -+ -+static bool tas5713_reg_volatile(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case TAS5713_DEVICE_ID: -+ case TAS5713_ERROR_STATUS: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+ -+static const struct of_device_id tas5713_of_match[] = { -+ { .compatible = "ti,tas5713", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, tas5713_of_match); -+ -+ -+static struct regmap_config tas5713_regmap_config = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ -+ .max_register = TAS5713_MAX_REGISTER, -+ .volatile_reg = tas5713_reg_volatile, -+ -+ .cache_type = REGCACHE_RBTREE, -+ .reg_defaults = tas5713_reg_defaults, -+ .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults), -+}; -+ -+ -+static int tas5713_i2c_probe(struct i2c_client *i2c, -+ const struct i2c_device_id *id) -+{ -+ int ret; -+ -+ priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL); -+ if (!priv_data) -+ return -ENOMEM; -+ -+ priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config); -+ if (IS_ERR(priv_data->regmap)) { -+ ret = PTR_ERR(priv_data->regmap); -+ return ret; -+ } -+ -+ i2c_set_clientdata(i2c, priv_data); -+ -+ ret = snd_soc_register_codec(&i2c->dev, -+ &soc_codec_dev_tas5713, &tas5713_dai, 1); -+ -+ return ret; -+} -+ -+ -+static int tas5713_i2c_remove(struct i2c_client *i2c) -+{ -+ snd_soc_unregister_codec(&i2c->dev); -+ i2c_set_clientdata(i2c, NULL); -+ -+ kfree(priv_data); -+ -+ return 0; -+} -+ -+ -+static const struct i2c_device_id tas5713_i2c_id[] = { -+ { "tas5713", 0 }, -+ { } -+}; -+ -+MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id); -+ -+ -+static struct i2c_driver tas5713_i2c_driver = { -+ .driver = { -+ .name = "tas5713", -+ .owner = THIS_MODULE, -+ .of_match_table = tas5713_of_match, -+ }, -+ .probe = tas5713_i2c_probe, -+ .remove = tas5713_i2c_remove, -+ .id_table = tas5713_i2c_id -+}; -+ -+ -+static int __init tas5713_modinit(void) -+{ -+ int ret = 0; -+ -+ ret = i2c_add_driver(&tas5713_i2c_driver); -+ if (ret) { -+ printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n", -+ ret); -+ } -+ -+ return ret; -+} -+module_init(tas5713_modinit); -+ -+ -+static void __exit tas5713_exit(void) -+{ -+ i2c_del_driver(&tas5713_i2c_driver); -+} -+module_exit(tas5713_exit); -+ -+ -+MODULE_AUTHOR("Sebastian Eickhoff "); -+MODULE_DESCRIPTION("ASoC driver for TAS5713"); -+MODULE_LICENSE("GPL v2"); ---- /dev/null -+++ b/sound/soc/codecs/tas5713.h -@@ -0,0 +1,210 @@ -+/* -+ * ASoC Driver for TAS5713 -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#ifndef _TAS5713_H -+#define _TAS5713_H -+ -+ -+// TAS5713 I2C-bus register addresses -+ -+#define TAS5713_CLOCK_CTRL 0x00 -+#define TAS5713_DEVICE_ID 0x01 -+#define TAS5713_ERROR_STATUS 0x02 -+#define TAS5713_SYSTEM_CTRL1 0x03 -+#define TAS5713_SERIAL_DATA_INTERFACE 0x04 -+#define TAS5713_SYSTEM_CTRL2 0x05 -+#define TAS5713_SOFT_MUTE 0x06 -+#define TAS5713_VOL_MASTER 0x07 -+#define TAS5713_VOL_CH1 0x08 -+#define TAS5713_VOL_CH2 0x09 -+#define TAS5713_VOL_HEADPHONE 0x0A -+#define TAS5713_VOL_CONFIG 0x0E -+#define TAS5713_MODULATION_LIMIT 0x10 -+#define TAS5713_IC_DLY_CH1 0x11 -+#define TAS5713_IC_DLY_CH2 0x12 -+#define TAS5713_IC_DLY_CH3 0x13 -+#define TAS5713_IC_DLY_CH4 0x14 -+ -+#define TAS5713_START_STOP_PERIOD 0x1A -+#define TAS5713_OSC_TRIM 0x1B -+#define TAS5713_BKND_ERR 0x1C -+ -+#define TAS5713_INPUT_MUX 0x20 -+#define TAS5713_SRC_SELECT_CH4 0x21 -+#define TAS5713_PWM_MUX 0x25 -+ -+#define TAS5713_CH1_BQ0 0x29 -+#define TAS5713_CH1_BQ1 0x2A -+#define TAS5713_CH1_BQ2 0x2B -+#define TAS5713_CH1_BQ3 0x2C -+#define TAS5713_CH1_BQ4 0x2D -+#define TAS5713_CH1_BQ5 0x2E -+#define TAS5713_CH1_BQ6 0x2F -+#define TAS5713_CH1_BQ7 0x58 -+#define TAS5713_CH1_BQ8 0x59 -+ -+#define TAS5713_CH2_BQ0 0x30 -+#define TAS5713_CH2_BQ1 0x31 -+#define TAS5713_CH2_BQ2 0x32 -+#define TAS5713_CH2_BQ3 0x33 -+#define TAS5713_CH2_BQ4 0x34 -+#define TAS5713_CH2_BQ5 0x35 -+#define TAS5713_CH2_BQ6 0x36 -+#define TAS5713_CH2_BQ7 0x5C -+#define TAS5713_CH2_BQ8 0x5D -+ -+#define TAS5713_CH4_BQ0 0x5A -+#define TAS5713_CH4_BQ1 0x5B -+#define TAS5713_CH3_BQ0 0x5E -+#define TAS5713_CH3_BQ1 0x5F -+ -+#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B -+#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C -+#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E -+#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F -+#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40 -+#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43 -+#define TAS5713_DRC_CTRL 0x46 -+ -+#define TAS5713_BANK_SW_CTRL 0x50 -+#define TAS5713_CH1_OUTPUT_MIXER 0x51 -+#define TAS5713_CH2_OUTPUT_MIXER 0x52 -+#define TAS5713_CH1_INPUT_MIXER 0x53 -+#define TAS5713_CH2_INPUT_MIXER 0x54 -+#define TAS5713_OUTPUT_POST_SCALE 0x56 -+#define TAS5713_OUTPUT_PRESCALE 0x57 -+ -+#define TAS5713_IDF_POST_SCALE 0x62 -+ -+#define TAS5713_CH1_INLINE_MIXER 0x70 -+#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71 -+#define TAS5713_CH1_R_CHANNEL_MIXER 0x72 -+#define TAS5713_CH1_L_CHANNEL_MIXER 0x73 -+#define TAS5713_CH2_INLINE_MIXER 0x74 -+#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75 -+#define TAS5713_CH2_L_CHANNEL_MIXER 0x76 -+#define TAS5713_CH2_R_CHANNEL_MIXER 0x77 -+ -+#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8 -+#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9 -+ -+#define TAS5713_REGISTER_COUNT 0x46 -+#define TAS5713_MAX_REGISTER 0xF9 -+ -+ -+// Bitmasks for registers -+#define TAS5713_SOFT_MUTE_ALL 0x07 -+ -+ -+ -+struct tas5713_init_command { -+ const int size; -+ const char *const data; -+}; -+ -+static const struct tas5713_init_command tas5713_init_sequence[] = { -+ -+ // Trim oscillator -+ { .size = 2, .data = "\x1B\x00" }, -+ // System control register 1 (0x03): block DC -+ { .size = 2, .data = "\x03\x80" }, -+ // Mute everything -+ { .size = 2, .data = "\x05\x40" }, -+ // Modulation limit register (0x10): 97.7% -+ { .size = 2, .data = "\x10\x02" }, -+ // Interchannel delay registers -+ // (0x11, 0x12, 0x13, and 0x14): BD mode -+ { .size = 2, .data = "\x11\xB8" }, -+ { .size = 2, .data = "\x12\x60" }, -+ { .size = 2, .data = "\x13\xA0" }, -+ { .size = 2, .data = "\x14\x48" }, -+ // PWM shutdown group register (0x19): no shutdown -+ { .size = 2, .data = "\x19\x00" }, -+ // Input multiplexer register (0x20): BD mode -+ { .size = 2, .data = "\x20\x00\x89\x77\x72" }, -+ // PWM output mux register (0x25) -+ // Channel 1 --> OUTA, channel 1 neg --> OUTB -+ // Channel 2 --> OUTC, channel 2 neg --> OUTD -+ { .size = 5, .data = "\x25\x01\x02\x13\x45" }, -+ // DRC control (0x46): DRC off -+ { .size = 5, .data = "\x46\x00\x00\x00\x00" }, -+ // BKND_ERR register (0x1C): 299ms reset period -+ { .size = 2, .data = "\x1C\x07" }, -+ // Mute channel 3 -+ { .size = 2, .data = "\x0A\xFF" }, -+ // Volume configuration register (0x0E): volume slew 512 steps -+ { .size = 2, .data = "\x0E\x90" }, -+ // Clock control register (0x00): 44/48kHz, MCLK=64xfs -+ { .size = 2, .data = "\x00\x60" }, -+ // Bank switch and eq control (0x50): no bank switching -+ { .size = 5, .data = "\x50\x00\x00\x00\x00" }, -+ // Volume registers (0x07, 0x08, 0x09, 0x0A) -+ { .size = 2, .data = "\x07\x20" }, -+ { .size = 2, .data = "\x08\x30" }, -+ { .size = 2, .data = "\x09\x30" }, -+ { .size = 2, .data = "\x0A\xFF" }, -+ // 0x72, 0x73, 0x76, 0x77 input mixer: -+ // no intermix between channels -+ { .size = 5, .data = "\x72\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x73\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x76\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x77\x00\x80\x00\x00" }, -+ // 0x70, 0x71, 0x74, 0x75 inline DRC mixer: -+ // no inline DRC inmix -+ { .size = 5, .data = "\x70\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x71\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x74\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x75\x00\x00\x00\x00" }, -+ // 0x56, 0x57 Output scale -+ { .size = 5, .data = "\x56\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x57\x00\x02\x00\x00" }, -+ // 0x3B, 0x3c -+ { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" }, -+ { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" }, -+ { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ // 0x51, 0x52: output mixer -+ { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" }, -+ { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" }, -+ // PEQ defaults -+ { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+}; -+ -+ -+#endif /* _TAS5713_H */ diff --git a/target/linux/brcm2708/patches-4.9/0120-BCM270X_DT-Add-pi3-disable-wifi-overlay.patch b/target/linux/brcm2708/patches-4.9/0120-BCM270X_DT-Add-pi3-disable-wifi-overlay.patch new file mode 100644 index 0000000000..4bc80bef04 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0120-BCM270X_DT-Add-pi3-disable-wifi-overlay.patch @@ -0,0 +1,56 @@ +From b76839857c9b553f52f8d14cf54a22579b362db9 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 11 Jan 2017 13:01:21 +0000 +Subject: [PATCH] BCM270X_DT: Add pi3-disable-wifi overlay + +pi3-disable-wifi is a minimal overlay to disable the onboard WiFi. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 6 ++++++ + arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts | 13 +++++++++++++ + 3 files changed, 20 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -51,6 +51,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + mz61581.dtbo \ + pi3-act-led.dtbo \ + pi3-disable-bt.dtbo \ ++ pi3-disable-wifi.dtbo \ + pi3-miniuart-bt.dtbo \ + piscreen.dtbo \ + piscreen2r.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -800,6 +800,12 @@ Load: dtoverlay=pi3-disable-bt + Params: + + ++Name: pi3-disable-wifi ++Info: Disable Pi3 onboard WiFi ++Load: dtoverlay=pi3-disable-wifi ++Params: ++ ++ + Name: pi3-miniuart-bt + Info: Switch Pi3 Bluetooth function to use the mini-UART (ttyS0) and restore + UART0/ttyAMA0 over GPIOs 14 & 15. Note that this may reduce the maximum +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts +@@ -0,0 +1,13 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&mmc>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++}; diff --git a/target/linux/brcm2708/patches-4.9/0120-hifiberry-amp-Adjust-for-ALSA-object-refactoring.patch b/target/linux/brcm2708/patches-4.9/0120-hifiberry-amp-Adjust-for-ALSA-object-refactoring.patch deleted file mode 100644 index 0de8da03e6..0000000000 --- a/target/linux/brcm2708/patches-4.9/0120-hifiberry-amp-Adjust-for-ALSA-object-refactoring.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 5f73a356386a40f331c86a68e2dad1dd0a4bbcd8 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 9 Jan 2017 09:42:09 +0000 -Subject: [PATCH] hifiberry-amp: Adjust for ALSA object refactoring - -See: https://github.com/raspberrypi/linux/issues/1775 ---- - sound/soc/codecs/tas5713.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/sound/soc/codecs/tas5713.c -+++ b/sound/soc/codecs/tas5713.c -@@ -232,8 +232,10 @@ static int tas5713_probe(struct snd_soc_ - static struct snd_soc_codec_driver soc_codec_dev_tas5713 = { - .probe = tas5713_probe, - .remove = tas5713_remove, -- .controls = tas5713_snd_controls, -- .num_controls = ARRAY_SIZE(tas5713_snd_controls), -+ .component_driver = { -+ .controls = tas5713_snd_controls, -+ .num_controls = ARRAY_SIZE(tas5713_snd_controls), -+ }, - }; - - diff --git a/target/linux/brcm2708/patches-4.9/0121-ARM64-Make-it-work-again-on-4.9-1790.patch b/target/linux/brcm2708/patches-4.9/0121-ARM64-Make-it-work-again-on-4.9-1790.patch new file mode 100644 index 0000000000..96b298dd1b --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0121-ARM64-Make-it-work-again-on-4.9-1790.patch @@ -0,0 +1,410 @@ +From fe3c34c6196cfc708a515e44dd432da0e6cc0aba Mon Sep 17 00:00:00 2001 +From: Electron752 +Date: Thu, 12 Jan 2017 07:07:08 -0800 +Subject: [PATCH] ARM64: Make it work again on 4.9 (#1790) + +* Invoke the dtc compiler with the same options used in arm mode. +* ARM64 now uses the bcm2835 platform just like ARM32. +* ARM64: Update bcmrpi3_defconfig + +Signed-off-by: Michael Zoran +--- + arch/arm64/Kconfig.platforms | 22 ------ + arch/arm64/boot/dts/broadcom/Makefile | 10 ++- + arch/arm64/boot/dts/overlays | 1 + + arch/arm64/configs/bcmrpi3_defconfig | 126 ++++++++++------------------------ + 4 files changed, 48 insertions(+), 111 deletions(-) + create mode 120000 arch/arm64/boot/dts/overlays + +diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms +index 7d213c2c..101794f 100644 +--- a/arch/arm64/Kconfig.platforms ++++ b/arch/arm64/Kconfig.platforms +@@ -1,27 +1,5 @@ + menu "Platform selection" + +-config MACH_BCM2709 +- bool +- +-config ARCH_BCM2709 +- bool "Broadcom BCM2709 family" +- select MACH_BCM2709 +- select HAVE_SMP +- select ARM_AMBA +- select COMMON_CLK +- select ARCH_HAS_CPUFREQ +- select GENERIC_CLOCKEVENTS +- select MULTI_IRQ_HANDLER +- select SPARSE_IRQ +- select MFD_SYSCON +- select VC4 +- select USE_OF +- select ARCH_REQUIRE_GPIOLIB +- select PINCTRL +- select PINCTRL_BCM2835 +- help +- This enables support for Broadcom BCM2709 boards. +- + config ARCH_SUNXI + bool "Allwinner sunxi 64-bit SoC Family" + select GENERIC_IRQ_CHIP +diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile +index 2152448..7aa03be 100644 +--- a/arch/arm64/boot/dts/broadcom/Makefile ++++ b/arch/arm64/boot/dts/broadcom/Makefile +@@ -1,7 +1,15 @@ ++# Enable fixups to support overlays on BCM2835 platforms ++ ++ifeq ($(CONFIG_ARCH_BCM2835),y) ++DTC_FLAGS ?= -@ -H epapr ++endif ++ + dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb + dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb + dtb-$(CONFIG_ARCH_VULCAN) += vulcan-eval.dtb +-dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb ++dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b.dtb ++ ++dts-dirs += ../overlays + + always := $(dtb-y) + subdir-y := $(dts-dirs) +diff --git a/arch/arm64/boot/dts/overlays b/arch/arm64/boot/dts/overlays +new file mode 120000 +index 0000000..ded0864 +--- /dev/null ++++ b/arch/arm64/boot/dts/overlays +@@ -0,0 +1 @@ ++../../../arm/boot/dts/overlays +\ No newline at end of file +diff --git a/arch/arm64/configs/bcmrpi3_defconfig b/arch/arm64/configs/bcmrpi3_defconfig +index 53da5c7..c7e891d 100644 +--- a/arch/arm64/configs/bcmrpi3_defconfig ++++ b/arch/arm64/configs/bcmrpi3_defconfig +@@ -1,52 +1,9 @@ +-# CONFIG_ARM_PATCH_PHYS_VIRT is not set +-CONFIG_PHYS_OFFSET=0 + CONFIG_LOCALVERSION="-v8" + # CONFIG_LOCALVERSION_AUTO is not set +-CONFIG_64BIT=y + CONFIG_SYSVIPC=y + CONFIG_POSIX_MQUEUE=y + CONFIG_NO_HZ=y + CONFIG_HIGH_RES_TIMERS=y +- +-# +-# ARM errata workarounds via the alternatives framework +-# +-CONFIG_ARM64_ERRATUM_826319=n +-CONFIG_ARM64_ERRATUM_827319=n +-CONFIG_ARM64_ERRATUM_824069=n +-CONFIG_ARM64_ERRATUM_819472=n +-CONFIG_ARM64_ERRATUM_832075=n +-CONFIG_ARM64_ERRATUM_845719=n +-CONFIG_ARM64_ERRATUM_843419=n +-CONFIG_CAVIUM_ERRATUM_22375=n +-CONFIG_CAVIUM_ERRATUM_23154=n +-CONFIG_CAVIUM_ERRATUM_27456=n +-CONFIG_ARM64_4K_PAGES=y +-CONFIG_ARM64_VA_BITS_39=y +-CONFIG_ARM64_VA_BITS=39 +-CONFIG_SCHED_MC=y +-CONFIG_NR_CPUS=4 +-CONFIG_HOTPLUG_CPU=y +-CONFIG_ARMV8_DEPRECATED=y +-CONFIG_SWP_EMULATION=y +-CONFIG_CP15_BARRIER_EMULATION=y +-CONFIG_SETEND_EMULATION=y +- +-# +-# ARMv8.1 architectural features +-# +-CONFIG_ARM64_HW_AFDBM=y +-CONFIG_ARM64_PAN=y +-CONFIG_ARM64_LSE_ATOMICS=y +-CONFIG_ARM64_VHE=y +- +-# +-# ARMv8.2 architectural features +-# +-CONFIG_ARM64_UAO=y +-CONFIG_ARM64_MODULE_CMODEL_LARGE=n +-CONFIG_RANDOMIZE_BASE=n +- + CONFIG_BSD_PROCESS_ACCT=y + CONFIG_BSD_PROCESS_ACCT_V3=y + CONFIG_TASKSTATS=y +@@ -55,7 +12,6 @@ CONFIG_TASK_XACCT=y + CONFIG_TASK_IO_ACCOUNTING=y + CONFIG_IKCONFIG=m + CONFIG_IKCONFIG_PROC=y +-CONFIG_NMI_LOG_BUF_SHIFT=12 + CONFIG_MEMCG=y + CONFIG_BLK_CGROUP=y + CONFIG_CGROUP_FREEZER=y +@@ -69,54 +25,49 @@ CONFIG_BLK_DEV_INITRD=y + CONFIG_EMBEDDED=y + # CONFIG_COMPAT_BRK is not set + CONFIG_PROFILING=y +-CONFIG_OPROFILE=m + CONFIG_KPROBES=y + CONFIG_JUMP_LABEL=y + CONFIG_MODULES=y + CONFIG_MODULE_UNLOAD=y + CONFIG_MODVERSIONS=y + CONFIG_MODULE_SRCVERSION_ALL=y +-CONFIG_TRIM_UNUSED_KSYMS=y + CONFIG_BLK_DEV_THROTTLING=y + CONFIG_PARTITION_ADVANCED=y + CONFIG_MAC_PARTITION=y + CONFIG_CFQ_GROUP_IOSCHED=y +-CONFIG_ARCH_BCM2709=y +-# CONFIG_CACHE_L2X0 is not set +-CONFIG_SMP=y +-CONFIG_HAVE_ARM_ARCH_TIMER=y +-CONFIG_VMSPLIT_2G=y +-CONFIG_PREEMPT_VOLUNTARY=y +-CONFIG_AEABI=y +-CONFIG_OABI_COMPAT=y +-# CONFIG_CPU_SW_DOMAIN_PAN is not set ++CONFIG_ARCH_BCM2835=y ++# CONFIG_CAVIUM_ERRATUM_22375 is not set ++# CONFIG_CAVIUM_ERRATUM_23154 is not set ++# CONFIG_CAVIUM_ERRATUM_27456 is not set ++CONFIG_SCHED_MC=y ++CONFIG_NR_CPUS=4 ++CONFIG_PREEMPT=y ++CONFIG_HZ_1000=y + CONFIG_CLEANCACHE=y + CONFIG_FRONTSWAP=y + CONFIG_CMA=y + CONFIG_ZSMALLOC=m + CONFIG_PGTABLE_MAPPING=y +-CONFIG_UACCESS_WITH_MEMCPY=y + CONFIG_SECCOMP=y +-# CONFIG_ATAGS is not set +-CONFIG_ZBOOT_ROM_TEXT=0x0 +-CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_ARMV8_DEPRECATED=y ++CONFIG_SWP_EMULATION=y ++CONFIG_CP15_BARRIER_EMULATION=y ++CONFIG_SETEND_EMULATION=y + CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" ++CONFIG_BINFMT_MISC=y ++CONFIG_COMPAT=y ++# CONFIG_SUSPEND is not set ++CONFIG_PM=y ++CONFIG_CPU_IDLE=y ++CONFIG_ARM_CPUIDLE=y + CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y + CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y + CONFIG_CPU_FREQ_GOV_PERFORMANCE=y + CONFIG_CPU_FREQ_GOV_USERSPACE=y + CONFIG_CPU_FREQ_GOV_ONDEMAND=y + CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y + CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +-CONFIG_VFP=y +-CONFIG_NEON=y +-CONFIG_KERNEL_MODE_NEON=y +-CONFIG_BINFMT_MISC=m +-CONFIG_COMPAT=y +-CONFIG_SYSVIPC_COMPAT=y +- +-# CONFIG_SUSPEND is not set +-CONFIG_PM=y + CONFIG_NET=y + CONFIG_PACKET=y + CONFIG_UNIX=y +@@ -437,6 +388,7 @@ CONFIG_BT_MRVL=m + CONFIG_BT_MRVL_SDIO=m + CONFIG_BT_ATH3K=m + CONFIG_BT_WILINK=m ++CONFIG_CFG80211=m + CONFIG_MAC80211=m + CONFIG_MAC80211_MESH=y + CONFIG_WIMAX=m +@@ -490,7 +442,6 @@ CONFIG_BONDING=m + CONFIG_DUMMY=m + CONFIG_IFB=m + CONFIG_MACVLAN=m +-CONFIG_IPVLAN=m + CONFIG_VXLAN=m + CONFIG_NETCONSOLE=m + CONFIG_TUN=m +@@ -579,8 +530,6 @@ CONFIG_RT2800USB_RT3573=y + CONFIG_RT2800USB_RT53XX=y + CONFIG_RT2800USB_RT55XX=y + CONFIG_RT2800USB_UNKNOWN=y +-CONFIG_RTL8187=m +-CONFIG_RTL8192CU=n + CONFIG_USB_ZD1201=m + CONFIG_ZD1211RW=m + CONFIG_MAC80211_HWSIM=m +@@ -606,7 +555,7 @@ CONFIG_JOYSTICK_RPISENSE=m + CONFIG_INPUT_TOUCHSCREEN=y + CONFIG_TOUCHSCREEN_ADS7846=m + CONFIG_TOUCHSCREEN_EGALAX=m +-CONFIG_TOUCHSCREEN_FT6236=m ++CONFIG_TOUCHSCREEN_EKTF2127=m + CONFIG_TOUCHSCREEN_RPI_FT5406=m + CONFIG_TOUCHSCREEN_USB_COMPOSITE=m + CONFIG_TOUCHSCREEN_STMPE=m +@@ -626,10 +575,8 @@ CONFIG_SERIO_RAW=m + CONFIG_GAMEPORT=m + CONFIG_GAMEPORT_NS558=m + CONFIG_GAMEPORT_L4=m +-CONFIG_BRCM_CHAR_DRIVERS=n +-CONFIG_BCM_VC_CMA=n +-CONFIG_BCM_VCIO=n +-CONFIG_BCM_VC_SM=n ++# CONFIG_BCM2835_DEVGPIOMEM is not set ++# CONFIG_BCM2835_SMI_DEV is not set + # CONFIG_LEGACY_PTYS is not set + # CONFIG_DEVKMEM is not set + CONFIG_SERIAL_8250=y +@@ -638,6 +585,9 @@ CONFIG_SERIAL_8250_CONSOLE=y + # CONFIG_SERIAL_8250_DMA is not set + CONFIG_SERIAL_8250_NR_UARTS=1 + CONFIG_SERIAL_8250_RUNTIME_UARTS=0 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_BCM2835AUX=y + CONFIG_SERIAL_OF_PLATFORM=y + CONFIG_SERIAL_AMBA_PL011=y + CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +@@ -650,6 +600,7 @@ CONFIG_I2C=y + CONFIG_I2C_CHARDEV=m + CONFIG_I2C_MUX_PCA954x=m + CONFIG_I2C_BCM2708=m ++CONFIG_I2C_BCM2835=m + CONFIG_I2C_GPIO=m + CONFIG_SPI=y + CONFIG_SPI_BCM2835=m +@@ -681,13 +632,13 @@ CONFIG_W1_SLAVE_DS2780=m + CONFIG_W1_SLAVE_DS2781=m + CONFIG_W1_SLAVE_DS28E04=m + CONFIG_W1_SLAVE_BQ27000=m +-CONFIG_BATTERY_DS2760=m +-CONFIG_POWER_RESET=y + CONFIG_POWER_RESET_GPIO=y ++CONFIG_BATTERY_DS2760=m + CONFIG_HWMON=m + CONFIG_SENSORS_LM75=m + CONFIG_SENSORS_SHT21=m + CONFIG_SENSORS_SHTC1=m ++CONFIG_SENSORS_INA2XX=m + CONFIG_THERMAL=y + CONFIG_THERMAL_BCM2835=y + CONFIG_WATCHDOG=y +@@ -835,8 +786,6 @@ CONFIG_VIDEO_EM28XX_V4L2=m + CONFIG_VIDEO_EM28XX_ALSA=m + CONFIG_VIDEO_EM28XX_DVB=m + CONFIG_V4L_PLATFORM_DRIVERS=y +-CONFIG_VIDEO_BCM2835=n +-CONFIG_VIDEO_BCM2835_MMAL=n + CONFIG_RADIO_SI470X=y + CONFIG_USB_SI470X=m + CONFIG_I2C_SI470X=m +@@ -892,8 +841,6 @@ CONFIG_SND_VIRMIDI=m + CONFIG_SND_MTPAV=m + CONFIG_SND_SERIAL_U16550=m + CONFIG_SND_MPU401=m +-CONFIG_SND_ARM=n +-CONFIG_SND_BCM2835=n + CONFIG_SND_USB_AUDIO=m + CONFIG_SND_USB_UA101=m + CONFIG_SND_USB_CAIAQ=m +@@ -916,7 +863,10 @@ CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m + CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m + CONFIG_SND_DIGIDAC1_SOUNDCARD=m + CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m ++CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m ++CONFIG_SND_PISOUND=m + CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_AK4554=m + CONFIG_SND_SOC_WM8804_I2C=m + CONFIG_SND_SIMPLE_CARD=m + CONFIG_SOUND_PRIME=m +@@ -979,8 +929,6 @@ CONFIG_USB_HIDDEV=y + CONFIG_USB=y + CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + CONFIG_USB_MON=m +-CONFIG_USB_DWCOTG=n +-CONFIG_USB_DWC2=y + CONFIG_USB_PRINTER=m + CONFIG_USB_STORAGE=y + CONFIG_USB_STORAGE_REALTEK=m +@@ -1001,6 +949,7 @@ CONFIG_USB_MICROTEK=m + CONFIG_USBIP_CORE=m + CONFIG_USBIP_VHCI_HCD=m + CONFIG_USBIP_HOST=m ++CONFIG_USB_DWC2=y + CONFIG_USB_SERIAL=m + CONFIG_USB_SERIAL_GENERIC=y + CONFIG_USB_SERIAL_AIRCABLE=m +@@ -1096,6 +1045,7 @@ CONFIG_LEDS_TRIGGER_INPUT=y + CONFIG_LEDS_TRIGGER_PANIC=y + CONFIG_RTC_CLASS=y + # CONFIG_RTC_HCTOSYS is not set ++CONFIG_RTC_DRV_ABX80X=m + CONFIG_RTC_DRV_DS1307=m + CONFIG_RTC_DRV_DS1374=m + CONFIG_RTC_DRV_DS1672=m +@@ -1103,7 +1053,6 @@ CONFIG_RTC_DRV_MAX6900=m + CONFIG_RTC_DRV_RS5C372=m + CONFIG_RTC_DRV_ISL1208=m + CONFIG_RTC_DRV_ISL12022=m +-CONFIG_RTC_DRV_ISL12057=m + CONFIG_RTC_DRV_X1205=m + CONFIG_RTC_DRV_PCF8523=m + CONFIG_RTC_DRV_PCF8563=m +@@ -1137,7 +1086,6 @@ CONFIG_STAGING=y + CONFIG_PRISM2_USB=m + CONFIG_R8712U=m + CONFIG_R8188EU=m +-CONFIG_R8723AU=m + CONFIG_VT6656=m + CONFIG_SPEAKUP=m + CONFIG_SPEAKUP_SYNTH_SOFT=m +@@ -1153,6 +1101,7 @@ CONFIG_FB_TFT_BD663474=m + CONFIG_FB_TFT_HX8340BN=m + CONFIG_FB_TFT_HX8347D=m + CONFIG_FB_TFT_HX8353D=m ++CONFIG_FB_TFT_HX8357D=m + CONFIG_FB_TFT_ILI9163=m + CONFIG_FB_TFT_ILI9320=m + CONFIG_FB_TFT_ILI9325=m +@@ -1176,6 +1125,7 @@ CONFIG_FB_TFT_UPD161704=m + CONFIG_FB_TFT_WATTEROTT=m + CONFIG_FB_FLEX=m + CONFIG_FB_TFT_FBTFT_DEVICE=m ++# CONFIG_BCM2708_VCHIQ is not set + CONFIG_MAILBOX=y + CONFIG_BCM2835_MBOX=y + # CONFIG_IOMMU_SUPPORT is not set +@@ -1189,6 +1139,7 @@ CONFIG_IIO_KFIFO_BUF=m + CONFIG_MCP320X=m + CONFIG_MCP3422=m + CONFIG_DHT11=m ++CONFIG_HTU21=m + CONFIG_PWM_BCM2835=m + CONFIG_PWM_PCA9685=m + CONFIG_RASPBERRYPI_FIRMWARE=y +@@ -1309,6 +1260,7 @@ CONFIG_BOOT_PRINTK_DELAY=y + CONFIG_DEBUG_MEMORY_INIT=y + CONFIG_DETECT_HUNG_TASK=y + CONFIG_TIMER_STATS=y ++CONFIG_LATENCYTOP=y + CONFIG_IRQSOFF_TRACER=y + CONFIG_SCHED_TRACER=y + CONFIG_STACK_TRACER=y +@@ -1331,5 +1283,3 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m + CONFIG_ARM64_CRYPTO=y + CONFIG_CRC_ITU_T=y + CONFIG_LIBCRC32C=y +-CONFIG_BCM2708_VCHIQ=n +-CONFIG_ARCH_BCM2835=y +-- +2.1.4 + diff --git a/target/linux/brcm2708/patches-4.9/0121-bcm2835-i2s-Changes-for-allowing-asymmetric-sample-f.patch b/target/linux/brcm2708/patches-4.9/0121-bcm2835-i2s-Changes-for-allowing-asymmetric-sample-f.patch deleted file mode 100644 index 0cc0f8848d..0000000000 --- a/target/linux/brcm2708/patches-4.9/0121-bcm2835-i2s-Changes-for-allowing-asymmetric-sample-f.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 425ee76116894c97d5d97ad4883eb2612b8692f3 Mon Sep 17 00:00:00 2001 -From: Giedrius Trainavicius -Date: Sun, 8 Jan 2017 15:58:54 +0200 -Subject: [PATCH] bcm2835-i2s: Changes for allowing asymmetric sample formats. - -This is achieved by making changes only to the requested -stream direction format, keeping the other stream direction -configuration intact. - -Signed-off-by: Giedrius Trainavicius ---- - sound/soc/bcm/bcm2835-i2s.c | 54 +++++++++++++++++++++++++++++++-------------- - 1 file changed, 38 insertions(+), 16 deletions(-) - ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -237,7 +237,9 @@ static int bcm2835_i2s_hw_params(struct - unsigned int sampling_rate = params_rate(params); - unsigned int data_length, data_delay, bclk_ratio; - unsigned int ch1pos, ch2pos, mode, format; -+ unsigned int previous_ftxp, previous_frxp; - uint32_t csreg; -+ bool packed; - - /* - * If a stream is already enabled, -@@ -320,26 +322,46 @@ static int bcm2835_i2s_hw_params(struct - return -EINVAL; - } - -- /* -- * Set format for both streams. -- * We cannot set another frame length -- * (and therefore word length) anyway, -- * so the format will be the same. -- */ -- regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format); -- regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format); -+ /* Set the format for the matching stream direction. */ -+ switch (substream->stream) { -+ case SNDRV_PCM_STREAM_PLAYBACK: -+ regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format); -+ break; -+ case SNDRV_PCM_STREAM_CAPTURE: -+ regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format); -+ break; -+ default: -+ return -EINVAL; -+ } - - /* Setup the I2S mode */ -+ /* Keep existing FTXP and FRXP values. */ -+ regmap_read(dev->i2s_regmap, BCM2835_I2S_MODE_A_REG, &mode); -+ -+ previous_ftxp = mode & BCM2835_I2S_FTXP; -+ previous_frxp = mode & BCM2835_I2S_FRXP; -+ - mode = 0; - -- if (data_length <= 16) { -- /* -- * Use frame packed mode (2 channels per 32 bit word) -- * We cannot set another frame length in the second stream -- * (and therefore word length) anyway, -- * so the format will be the same. -- */ -- mode |= BCM2835_I2S_FTXP | BCM2835_I2S_FRXP; -+ /* -+ * Retain the frame packed mode (2 channels per 32 bit word) -+ * of the other direction stream intact. The formats of each -+ * direction can be different as long as the frame length is -+ * shared for both. -+ */ -+ packed = data_length <= 16; -+ -+ switch (substream->stream) { -+ case SNDRV_PCM_STREAM_PLAYBACK: -+ mode |= previous_frxp; -+ mode |= packed ? BCM2835_I2S_FTXP : 0; -+ break; -+ case SNDRV_PCM_STREAM_CAPTURE: -+ mode |= previous_ftxp; -+ mode |= packed ? BCM2835_I2S_FRXP : 0; -+ break; -+ default: -+ return -EINVAL; - } - - mode |= BCM2835_I2S_FLEN(bclk_ratio - 1); diff --git a/target/linux/brcm2708/patches-4.9/0122-ARM64-Enable-Kernel-Address-Space-Randomization-1792.patch b/target/linux/brcm2708/patches-4.9/0122-ARM64-Enable-Kernel-Address-Space-Randomization-1792.patch new file mode 100644 index 0000000000..423db95e9e --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0122-ARM64-Enable-Kernel-Address-Space-Randomization-1792.patch @@ -0,0 +1,31 @@ +From 6dfa60daaa0966a8e414ab0a7fd002a99001920a Mon Sep 17 00:00:00 2001 +From: Electron752 +Date: Sat, 14 Jan 2017 02:54:26 -0800 +Subject: [PATCH] ARM64: Enable Kernel Address Space Randomization (#1792) + +Randomization allows the mapping between virtual addresses and physical +address to be different on each boot. This makes it more difficult +to exploit security vulnerabilities that require knowledge of fixed +hardware addresses. + +The firmware generates a 8 byte random number during bootup and stores +it in the device tree under chosen/kaslr-seed. This number is used +to randomize the address mapping. + +This change enables this feature in the build configuration for ARM64. + +Signed-off-by: Michael Zoran +--- + arch/arm64/configs/bcmrpi3_defconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm64/configs/bcmrpi3_defconfig ++++ b/arch/arm64/configs/bcmrpi3_defconfig +@@ -53,6 +53,7 @@ CONFIG_ARMV8_DEPRECATED=y + CONFIG_SWP_EMULATION=y + CONFIG_CP15_BARRIER_EMULATION=y + CONFIG_SETEND_EMULATION=y ++CONFIG_RANDOMIZE_BASE=y + CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" + CONFIG_BINFMT_MISC=y + CONFIG_COMPAT=y diff --git a/target/linux/brcm2708/patches-4.9/0122-Add-driver_name-property.patch b/target/linux/brcm2708/patches-4.9/0122-Add-driver_name-property.patch deleted file mode 100644 index 4acafa562c..0000000000 --- a/target/linux/brcm2708/patches-4.9/0122-Add-driver_name-property.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 6e7ad272d08767455aef658066b981f513ad0cec Mon Sep 17 00:00:00 2001 -From: Aaron Shaw -Date: Tue, 10 Jan 2017 16:05:41 +0000 -Subject: [PATCH] Add driver_name property - -Add driver name property for use with 5.1 passthrough audio in LibreElec and other Kodi based OSs ---- - sound/soc/bcm/justboom-dac.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/sound/soc/bcm/justboom-dac.c -+++ b/sound/soc/bcm/justboom-dac.c -@@ -98,6 +98,7 @@ static struct snd_soc_dai_link snd_rpi_j - /* audio machine driver */ - static struct snd_soc_card snd_rpi_justboom_dac = { - .name = "snd_rpi_justboom_dac", -+ .driver_name = "JustBoomDac", - .owner = THIS_MODULE, - .dai_link = snd_rpi_justboom_dac_dai, - .num_links = ARRAY_SIZE(snd_rpi_justboom_dac_dai), diff --git a/target/linux/brcm2708/patches-4.9/0123-Add-driver_name-paramater.patch b/target/linux/brcm2708/patches-4.9/0123-Add-driver_name-paramater.patch deleted file mode 100644 index c85bb445dc..0000000000 --- a/target/linux/brcm2708/patches-4.9/0123-Add-driver_name-paramater.patch +++ /dev/null @@ -1,20 +0,0 @@ -From d9f58694b229b6f7e8b03c718ef80ac7082213d1 Mon Sep 17 00:00:00 2001 -From: Aaron Shaw -Date: Tue, 10 Jan 2017 16:11:04 +0000 -Subject: [PATCH] Add driver_name paramater - -Add driver_name parameter for use with 5.1 passthrough audio in LibreElec and other Kodi OSs ---- - sound/soc/bcm/justboom-digi.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/sound/soc/bcm/justboom-digi.c -+++ b/sound/soc/bcm/justboom-digi.c -@@ -154,6 +154,7 @@ static struct snd_soc_dai_link snd_rpi_j - /* audio machine driver */ - static struct snd_soc_card snd_rpi_justboom_digi = { - .name = "snd_rpi_justboom_digi", -+ .driver_name = "JustBoomDigi", - .owner = THIS_MODULE, - .dai_link = snd_rpi_justboom_digi_dai, - .num_links = ARRAY_SIZE(snd_rpi_justboom_digi_dai), diff --git a/target/linux/brcm2708/patches-4.9/0124-ARM64-Enable-RTL8187-RTL8192CU-wifi-in-build-config.patch b/target/linux/brcm2708/patches-4.9/0124-ARM64-Enable-RTL8187-RTL8192CU-wifi-in-build-config.patch new file mode 100644 index 0000000000..c947a74c5d --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0124-ARM64-Enable-RTL8187-RTL8192CU-wifi-in-build-config.patch @@ -0,0 +1,25 @@ +From 564df2de35a212639eb7e357442f35fa89bcbde4 Mon Sep 17 00:00:00 2001 +From: Michael Zoran +Date: Sun, 15 Jan 2017 07:31:59 -0800 +Subject: [PATCH] ARM64: Enable RTL8187/RTL8192CU wifi in build config + +These drivers build now, so they can be enabled back +in the build configuration just like they are for +32 bit. + +Signed-off-by: Michael Zoran +--- + arch/arm64/configs/bcmrpi3_defconfig | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/configs/bcmrpi3_defconfig ++++ b/arch/arm64/configs/bcmrpi3_defconfig +@@ -531,6 +531,8 @@ CONFIG_RT2800USB_RT3573=y + CONFIG_RT2800USB_RT53XX=y + CONFIG_RT2800USB_RT55XX=y + CONFIG_RT2800USB_UNKNOWN=y ++CONFIG_RTL8187=m ++CONFIG_RTL8192CU=m + CONFIG_USB_ZD1201=m + CONFIG_ZD1211RW=m + CONFIG_MAC80211_HWSIM=m diff --git a/target/linux/brcm2708/patches-4.9/0124-BCM270X_DT-Add-pi3-disable-wifi-overlay.patch b/target/linux/brcm2708/patches-4.9/0124-BCM270X_DT-Add-pi3-disable-wifi-overlay.patch deleted file mode 100644 index 473876bf98..0000000000 --- a/target/linux/brcm2708/patches-4.9/0124-BCM270X_DT-Add-pi3-disable-wifi-overlay.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 11e7774ca60d3e6e9063ecfb497f15aa808f7ca2 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 11 Jan 2017 13:01:21 +0000 -Subject: [PATCH] BCM270X_DT: Add pi3-disable-wifi overlay - -pi3-disable-wifi is a minimal overlay to disable the onboard WiFi. - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 ++++++ - arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts | 13 +++++++++++++ - 3 files changed, 20 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts - ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -51,6 +51,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - mz61581.dtbo \ - pi3-act-led.dtbo \ - pi3-disable-bt.dtbo \ -+ pi3-disable-wifi.dtbo \ - pi3-miniuart-bt.dtbo \ - piscreen.dtbo \ - piscreen2r.dtbo \ ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -800,6 +800,12 @@ Load: dtoverlay=pi3-disable-bt - Params: - - -+Name: pi3-disable-wifi -+Info: Disable Pi3 onboard WiFi -+Load: dtoverlay=pi3-disable-wifi -+Params: -+ -+ - Name: pi3-miniuart-bt - Info: Switch Pi3 Bluetooth function to use the mini-UART (ttyS0) and restore - UART0/ttyAMA0 over GPIOs 14 & 15. Note that this may reduce the maximum ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts -@@ -0,0 +1,13 @@ -+/dts-v1/; -+/plugin/; -+ -+/{ -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&mmc>; -+ __overlay__ { -+ status = "disabled"; -+ }; -+ }; -+}; diff --git a/target/linux/brcm2708/patches-4.9/0125-ARM64-Make-it-work-again-on-4.9-1790.patch b/target/linux/brcm2708/patches-4.9/0125-ARM64-Make-it-work-again-on-4.9-1790.patch deleted file mode 100644 index a60080cb27..0000000000 --- a/target/linux/brcm2708/patches-4.9/0125-ARM64-Make-it-work-again-on-4.9-1790.patch +++ /dev/null @@ -1,410 +0,0 @@ -From d6fbb7bbbe2fcc6b348ba0cfc3523d7f8f18a619 Mon Sep 17 00:00:00 2001 -From: Electron752 -Date: Thu, 12 Jan 2017 07:07:08 -0800 -Subject: [PATCH] ARM64: Make it work again on 4.9 (#1790) - -* Invoke the dtc compiler with the same options used in arm mode. -* ARM64 now uses the bcm2835 platform just like ARM32. -* ARM64: Update bcmrpi3_defconfig - -Signed-off-by: Michael Zoran ---- - arch/arm64/Kconfig.platforms | 22 ------ - arch/arm64/boot/dts/broadcom/Makefile | 10 ++- - arch/arm64/boot/dts/overlays | 1 + - arch/arm64/configs/bcmrpi3_defconfig | 126 ++++++++++------------------------ - 4 files changed, 48 insertions(+), 111 deletions(-) - create mode 120000 arch/arm64/boot/dts/overlays - -diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms -index 7d213c2c..101794f 100644 ---- a/arch/arm64/Kconfig.platforms -+++ b/arch/arm64/Kconfig.platforms -@@ -1,27 +1,5 @@ - menu "Platform selection" - --config MACH_BCM2709 -- bool -- --config ARCH_BCM2709 -- bool "Broadcom BCM2709 family" -- select MACH_BCM2709 -- select HAVE_SMP -- select ARM_AMBA -- select COMMON_CLK -- select ARCH_HAS_CPUFREQ -- select GENERIC_CLOCKEVENTS -- select MULTI_IRQ_HANDLER -- select SPARSE_IRQ -- select MFD_SYSCON -- select VC4 -- select USE_OF -- select ARCH_REQUIRE_GPIOLIB -- select PINCTRL -- select PINCTRL_BCM2835 -- help -- This enables support for Broadcom BCM2709 boards. -- - config ARCH_SUNXI - bool "Allwinner sunxi 64-bit SoC Family" - select GENERIC_IRQ_CHIP -diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile -index 2152448..7aa03be 100644 ---- a/arch/arm64/boot/dts/broadcom/Makefile -+++ b/arch/arm64/boot/dts/broadcom/Makefile -@@ -1,7 +1,15 @@ -+# Enable fixups to support overlays on BCM2835 platforms -+ -+ifeq ($(CONFIG_ARCH_BCM2835),y) -+DTC_FLAGS ?= -@ -H epapr -+endif -+ - dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb - dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb - dtb-$(CONFIG_ARCH_VULCAN) += vulcan-eval.dtb --dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb -+dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b.dtb -+ -+dts-dirs += ../overlays - - always := $(dtb-y) - subdir-y := $(dts-dirs) -diff --git a/arch/arm64/boot/dts/overlays b/arch/arm64/boot/dts/overlays -new file mode 120000 -index 0000000..ded0864 ---- /dev/null -+++ b/arch/arm64/boot/dts/overlays -@@ -0,0 +1 @@ -+../../../arm/boot/dts/overlays -\ No newline at end of file -diff --git a/arch/arm64/configs/bcmrpi3_defconfig b/arch/arm64/configs/bcmrpi3_defconfig -index 53da5c7..c7e891d 100644 ---- a/arch/arm64/configs/bcmrpi3_defconfig -+++ b/arch/arm64/configs/bcmrpi3_defconfig -@@ -1,52 +1,9 @@ --# CONFIG_ARM_PATCH_PHYS_VIRT is not set --CONFIG_PHYS_OFFSET=0 - CONFIG_LOCALVERSION="-v8" - # CONFIG_LOCALVERSION_AUTO is not set --CONFIG_64BIT=y - CONFIG_SYSVIPC=y - CONFIG_POSIX_MQUEUE=y - CONFIG_NO_HZ=y - CONFIG_HIGH_RES_TIMERS=y -- --# --# ARM errata workarounds via the alternatives framework --# --CONFIG_ARM64_ERRATUM_826319=n --CONFIG_ARM64_ERRATUM_827319=n --CONFIG_ARM64_ERRATUM_824069=n --CONFIG_ARM64_ERRATUM_819472=n --CONFIG_ARM64_ERRATUM_832075=n --CONFIG_ARM64_ERRATUM_845719=n --CONFIG_ARM64_ERRATUM_843419=n --CONFIG_CAVIUM_ERRATUM_22375=n --CONFIG_CAVIUM_ERRATUM_23154=n --CONFIG_CAVIUM_ERRATUM_27456=n --CONFIG_ARM64_4K_PAGES=y --CONFIG_ARM64_VA_BITS_39=y --CONFIG_ARM64_VA_BITS=39 --CONFIG_SCHED_MC=y --CONFIG_NR_CPUS=4 --CONFIG_HOTPLUG_CPU=y --CONFIG_ARMV8_DEPRECATED=y --CONFIG_SWP_EMULATION=y --CONFIG_CP15_BARRIER_EMULATION=y --CONFIG_SETEND_EMULATION=y -- --# --# ARMv8.1 architectural features --# --CONFIG_ARM64_HW_AFDBM=y --CONFIG_ARM64_PAN=y --CONFIG_ARM64_LSE_ATOMICS=y --CONFIG_ARM64_VHE=y -- --# --# ARMv8.2 architectural features --# --CONFIG_ARM64_UAO=y --CONFIG_ARM64_MODULE_CMODEL_LARGE=n --CONFIG_RANDOMIZE_BASE=n -- - CONFIG_BSD_PROCESS_ACCT=y - CONFIG_BSD_PROCESS_ACCT_V3=y - CONFIG_TASKSTATS=y -@@ -55,7 +12,6 @@ CONFIG_TASK_XACCT=y - CONFIG_TASK_IO_ACCOUNTING=y - CONFIG_IKCONFIG=m - CONFIG_IKCONFIG_PROC=y --CONFIG_NMI_LOG_BUF_SHIFT=12 - CONFIG_MEMCG=y - CONFIG_BLK_CGROUP=y - CONFIG_CGROUP_FREEZER=y -@@ -69,54 +25,49 @@ CONFIG_BLK_DEV_INITRD=y - CONFIG_EMBEDDED=y - # CONFIG_COMPAT_BRK is not set - CONFIG_PROFILING=y --CONFIG_OPROFILE=m - CONFIG_KPROBES=y - CONFIG_JUMP_LABEL=y - CONFIG_MODULES=y - CONFIG_MODULE_UNLOAD=y - CONFIG_MODVERSIONS=y - CONFIG_MODULE_SRCVERSION_ALL=y --CONFIG_TRIM_UNUSED_KSYMS=y - CONFIG_BLK_DEV_THROTTLING=y - CONFIG_PARTITION_ADVANCED=y - CONFIG_MAC_PARTITION=y - CONFIG_CFQ_GROUP_IOSCHED=y --CONFIG_ARCH_BCM2709=y --# CONFIG_CACHE_L2X0 is not set --CONFIG_SMP=y --CONFIG_HAVE_ARM_ARCH_TIMER=y --CONFIG_VMSPLIT_2G=y --CONFIG_PREEMPT_VOLUNTARY=y --CONFIG_AEABI=y --CONFIG_OABI_COMPAT=y --# CONFIG_CPU_SW_DOMAIN_PAN is not set -+CONFIG_ARCH_BCM2835=y -+# CONFIG_CAVIUM_ERRATUM_22375 is not set -+# CONFIG_CAVIUM_ERRATUM_23154 is not set -+# CONFIG_CAVIUM_ERRATUM_27456 is not set -+CONFIG_SCHED_MC=y -+CONFIG_NR_CPUS=4 -+CONFIG_PREEMPT=y -+CONFIG_HZ_1000=y - CONFIG_CLEANCACHE=y - CONFIG_FRONTSWAP=y - CONFIG_CMA=y - CONFIG_ZSMALLOC=m - CONFIG_PGTABLE_MAPPING=y --CONFIG_UACCESS_WITH_MEMCPY=y - CONFIG_SECCOMP=y --# CONFIG_ATAGS is not set --CONFIG_ZBOOT_ROM_TEXT=0x0 --CONFIG_ZBOOT_ROM_BSS=0x0 -+CONFIG_ARMV8_DEPRECATED=y -+CONFIG_SWP_EMULATION=y -+CONFIG_CP15_BARRIER_EMULATION=y -+CONFIG_SETEND_EMULATION=y - CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" -+CONFIG_BINFMT_MISC=y -+CONFIG_COMPAT=y -+# CONFIG_SUSPEND is not set -+CONFIG_PM=y -+CONFIG_CPU_IDLE=y -+CONFIG_ARM_CPUIDLE=y - CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_STAT=y - CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y - CONFIG_CPU_FREQ_GOV_PERFORMANCE=y - CONFIG_CPU_FREQ_GOV_USERSPACE=y - CONFIG_CPU_FREQ_GOV_ONDEMAND=y - CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y - CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y --CONFIG_VFP=y --CONFIG_NEON=y --CONFIG_KERNEL_MODE_NEON=y --CONFIG_BINFMT_MISC=m --CONFIG_COMPAT=y --CONFIG_SYSVIPC_COMPAT=y -- --# CONFIG_SUSPEND is not set --CONFIG_PM=y - CONFIG_NET=y - CONFIG_PACKET=y - CONFIG_UNIX=y -@@ -437,6 +388,7 @@ CONFIG_BT_MRVL=m - CONFIG_BT_MRVL_SDIO=m - CONFIG_BT_ATH3K=m - CONFIG_BT_WILINK=m -+CONFIG_CFG80211=m - CONFIG_MAC80211=m - CONFIG_MAC80211_MESH=y - CONFIG_WIMAX=m -@@ -490,7 +442,6 @@ CONFIG_BONDING=m - CONFIG_DUMMY=m - CONFIG_IFB=m - CONFIG_MACVLAN=m --CONFIG_IPVLAN=m - CONFIG_VXLAN=m - CONFIG_NETCONSOLE=m - CONFIG_TUN=m -@@ -579,8 +530,6 @@ CONFIG_RT2800USB_RT3573=y - CONFIG_RT2800USB_RT53XX=y - CONFIG_RT2800USB_RT55XX=y - CONFIG_RT2800USB_UNKNOWN=y --CONFIG_RTL8187=m --CONFIG_RTL8192CU=n - CONFIG_USB_ZD1201=m - CONFIG_ZD1211RW=m - CONFIG_MAC80211_HWSIM=m -@@ -606,7 +555,7 @@ CONFIG_JOYSTICK_RPISENSE=m - CONFIG_INPUT_TOUCHSCREEN=y - CONFIG_TOUCHSCREEN_ADS7846=m - CONFIG_TOUCHSCREEN_EGALAX=m --CONFIG_TOUCHSCREEN_FT6236=m -+CONFIG_TOUCHSCREEN_EKTF2127=m - CONFIG_TOUCHSCREEN_RPI_FT5406=m - CONFIG_TOUCHSCREEN_USB_COMPOSITE=m - CONFIG_TOUCHSCREEN_STMPE=m -@@ -626,10 +575,8 @@ CONFIG_SERIO_RAW=m - CONFIG_GAMEPORT=m - CONFIG_GAMEPORT_NS558=m - CONFIG_GAMEPORT_L4=m --CONFIG_BRCM_CHAR_DRIVERS=n --CONFIG_BCM_VC_CMA=n --CONFIG_BCM_VCIO=n --CONFIG_BCM_VC_SM=n -+# CONFIG_BCM2835_DEVGPIOMEM is not set -+# CONFIG_BCM2835_SMI_DEV is not set - # CONFIG_LEGACY_PTYS is not set - # CONFIG_DEVKMEM is not set - CONFIG_SERIAL_8250=y -@@ -638,6 +585,9 @@ CONFIG_SERIAL_8250_CONSOLE=y - # CONFIG_SERIAL_8250_DMA is not set - CONFIG_SERIAL_8250_NR_UARTS=1 - CONFIG_SERIAL_8250_RUNTIME_UARTS=0 -+CONFIG_SERIAL_8250_EXTENDED=y -+CONFIG_SERIAL_8250_SHARE_IRQ=y -+CONFIG_SERIAL_8250_BCM2835AUX=y - CONFIG_SERIAL_OF_PLATFORM=y - CONFIG_SERIAL_AMBA_PL011=y - CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -@@ -650,6 +600,7 @@ CONFIG_I2C=y - CONFIG_I2C_CHARDEV=m - CONFIG_I2C_MUX_PCA954x=m - CONFIG_I2C_BCM2708=m -+CONFIG_I2C_BCM2835=m - CONFIG_I2C_GPIO=m - CONFIG_SPI=y - CONFIG_SPI_BCM2835=m -@@ -681,13 +632,13 @@ CONFIG_W1_SLAVE_DS2780=m - CONFIG_W1_SLAVE_DS2781=m - CONFIG_W1_SLAVE_DS28E04=m - CONFIG_W1_SLAVE_BQ27000=m --CONFIG_BATTERY_DS2760=m --CONFIG_POWER_RESET=y - CONFIG_POWER_RESET_GPIO=y -+CONFIG_BATTERY_DS2760=m - CONFIG_HWMON=m - CONFIG_SENSORS_LM75=m - CONFIG_SENSORS_SHT21=m - CONFIG_SENSORS_SHTC1=m -+CONFIG_SENSORS_INA2XX=m - CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - CONFIG_WATCHDOG=y -@@ -835,8 +786,6 @@ CONFIG_VIDEO_EM28XX_V4L2=m - CONFIG_VIDEO_EM28XX_ALSA=m - CONFIG_VIDEO_EM28XX_DVB=m - CONFIG_V4L_PLATFORM_DRIVERS=y --CONFIG_VIDEO_BCM2835=n --CONFIG_VIDEO_BCM2835_MMAL=n - CONFIG_RADIO_SI470X=y - CONFIG_USB_SI470X=m - CONFIG_I2C_SI470X=m -@@ -892,8 +841,6 @@ CONFIG_SND_VIRMIDI=m - CONFIG_SND_MTPAV=m - CONFIG_SND_SERIAL_U16550=m - CONFIG_SND_MPU401=m --CONFIG_SND_ARM=n --CONFIG_SND_BCM2835=n - CONFIG_SND_USB_AUDIO=m - CONFIG_SND_USB_UA101=m - CONFIG_SND_USB_CAIAQ=m -@@ -916,7 +863,10 @@ CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m - CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m - CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m -+CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_AK4554=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m - CONFIG_SOUND_PRIME=m -@@ -979,8 +929,6 @@ CONFIG_USB_HIDDEV=y - CONFIG_USB=y - CONFIG_USB_ANNOUNCE_NEW_DEVICES=y - CONFIG_USB_MON=m --CONFIG_USB_DWCOTG=n --CONFIG_USB_DWC2=y - CONFIG_USB_PRINTER=m - CONFIG_USB_STORAGE=y - CONFIG_USB_STORAGE_REALTEK=m -@@ -1001,6 +949,7 @@ CONFIG_USB_MICROTEK=m - CONFIG_USBIP_CORE=m - CONFIG_USBIP_VHCI_HCD=m - CONFIG_USBIP_HOST=m -+CONFIG_USB_DWC2=y - CONFIG_USB_SERIAL=m - CONFIG_USB_SERIAL_GENERIC=y - CONFIG_USB_SERIAL_AIRCABLE=m -@@ -1096,6 +1045,7 @@ CONFIG_LEDS_TRIGGER_INPUT=y - CONFIG_LEDS_TRIGGER_PANIC=y - CONFIG_RTC_CLASS=y - # CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_ABX80X=m - CONFIG_RTC_DRV_DS1307=m - CONFIG_RTC_DRV_DS1374=m - CONFIG_RTC_DRV_DS1672=m -@@ -1103,7 +1053,6 @@ CONFIG_RTC_DRV_MAX6900=m - CONFIG_RTC_DRV_RS5C372=m - CONFIG_RTC_DRV_ISL1208=m - CONFIG_RTC_DRV_ISL12022=m --CONFIG_RTC_DRV_ISL12057=m - CONFIG_RTC_DRV_X1205=m - CONFIG_RTC_DRV_PCF8523=m - CONFIG_RTC_DRV_PCF8563=m -@@ -1137,7 +1086,6 @@ CONFIG_STAGING=y - CONFIG_PRISM2_USB=m - CONFIG_R8712U=m - CONFIG_R8188EU=m --CONFIG_R8723AU=m - CONFIG_VT6656=m - CONFIG_SPEAKUP=m - CONFIG_SPEAKUP_SYNTH_SOFT=m -@@ -1153,6 +1101,7 @@ CONFIG_FB_TFT_BD663474=m - CONFIG_FB_TFT_HX8340BN=m - CONFIG_FB_TFT_HX8347D=m - CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_HX8357D=m - CONFIG_FB_TFT_ILI9163=m - CONFIG_FB_TFT_ILI9320=m - CONFIG_FB_TFT_ILI9325=m -@@ -1176,6 +1125,7 @@ CONFIG_FB_TFT_UPD161704=m - CONFIG_FB_TFT_WATTEROTT=m - CONFIG_FB_FLEX=m - CONFIG_FB_TFT_FBTFT_DEVICE=m -+# CONFIG_BCM2708_VCHIQ is not set - CONFIG_MAILBOX=y - CONFIG_BCM2835_MBOX=y - # CONFIG_IOMMU_SUPPORT is not set -@@ -1189,6 +1139,7 @@ CONFIG_IIO_KFIFO_BUF=m - CONFIG_MCP320X=m - CONFIG_MCP3422=m - CONFIG_DHT11=m -+CONFIG_HTU21=m - CONFIG_PWM_BCM2835=m - CONFIG_PWM_PCA9685=m - CONFIG_RASPBERRYPI_FIRMWARE=y -@@ -1309,6 +1260,7 @@ CONFIG_BOOT_PRINTK_DELAY=y - CONFIG_DEBUG_MEMORY_INIT=y - CONFIG_DETECT_HUNG_TASK=y - CONFIG_TIMER_STATS=y -+CONFIG_LATENCYTOP=y - CONFIG_IRQSOFF_TRACER=y - CONFIG_SCHED_TRACER=y - CONFIG_STACK_TRACER=y -@@ -1331,5 +1283,3 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m - CONFIG_ARM64_CRYPTO=y - CONFIG_CRC_ITU_T=y - CONFIG_LIBCRC32C=y --CONFIG_BCM2708_VCHIQ=n --CONFIG_ARCH_BCM2835=y --- -2.1.4 - diff --git a/target/linux/brcm2708/patches-4.9/0125-BCM270X_DT-Add-spi0-cs-overlay.patch b/target/linux/brcm2708/patches-4.9/0125-BCM270X_DT-Add-spi0-cs-overlay.patch new file mode 100644 index 0000000000..2fd8366f4e --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0125-BCM270X_DT-Add-spi0-cs-overlay.patch @@ -0,0 +1,83 @@ +From 48eea36959fb8d854b4cf1ee4284646be5a279e0 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 16 Jan 2017 14:53:12 +0000 +Subject: [PATCH] BCM270X_DT: Add spi0-cs overlay + +The spi0-cs overlay allows the software chip selectts to be modified +using the cs0_pin and cs1_pin parameters. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 9 +++++++- + arch/arm/boot/dts/overlays/spi0-cs-overlay.dts | 29 ++++++++++++++++++++++++++ + 3 files changed, 38 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/boot/dts/overlays/spi0-cs-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -83,6 +83,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + smi-nand.dtbo \ + spi-gpio35-39.dtbo \ + spi-rtc.dtbo \ ++ spi0-cs.dtbo \ + spi0-hw-cs.dtbo \ + spi1-1cs.dtbo \ + spi1-2cs.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -1138,7 +1138,7 @@ Params: + + + Name: spi-gpio35-39 +-Info: move SPI function block to GPIO 35 to 39 ++Info: Move SPI function block to GPIO 35 to 39 + Load: dtoverlay=spi-gpio35-39 + Params: + +@@ -1149,6 +1149,13 @@ Load: dtoverlay=spi-rtc,= + Params: pcf2123 Select the PCF2123 device + + ++Name: spi0-cs ++Info: Allows the (software) CS pins for SPI0 to be changed ++Load: dtoverlay=spi0-cs,= ++Params: cs0_pin GPIO pin for CS0 (default 8) ++ cs1_pin GPIO pin for CS1 (default 7) ++ ++ + Name: spi0-hw-cs + Info: Re-enables hardware CS/CE (chip selects) for SPI0 + Load: dtoverlay=spi0-hw-cs +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts +@@ -0,0 +1,29 @@ ++/dts-v1/; ++/plugin/; ++ ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0_cs_pins>; ++ frag0: __overlay__ { ++ brcm,pins = <8 7>; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi0>; ++ frag1: __overlay__ { ++ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag0>,"brcm,pins:0", ++ <&frag1>,"cs-gpios:4"; ++ cs1_pin = <&frag0>,"brcm,pins:4", ++ <&frag1>,"cs-gpios:16"; ++ }; ++}; diff --git a/target/linux/brcm2708/patches-4.9/0126-ARM64-Enable-Kernel-Address-Space-Randomization-1792.patch b/target/linux/brcm2708/patches-4.9/0126-ARM64-Enable-Kernel-Address-Space-Randomization-1792.patch deleted file mode 100644 index dff27b9ef0..0000000000 --- a/target/linux/brcm2708/patches-4.9/0126-ARM64-Enable-Kernel-Address-Space-Randomization-1792.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 8930b9b96484e1fd68438c78e44b8ef7cb2d61ac Mon Sep 17 00:00:00 2001 -From: Electron752 -Date: Sat, 14 Jan 2017 02:54:26 -0800 -Subject: [PATCH] ARM64: Enable Kernel Address Space Randomization (#1792) - -Randomization allows the mapping between virtual addresses and physical -address to be different on each boot. This makes it more difficult -to exploit security vulnerabilities that require knowledge of fixed -hardware addresses. - -The firmware generates a 8 byte random number during bootup and stores -it in the device tree under chosen/kaslr-seed. This number is used -to randomize the address mapping. - -This change enables this feature in the build configuration for ARM64. - -Signed-off-by: Michael Zoran ---- - arch/arm64/configs/bcmrpi3_defconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm64/configs/bcmrpi3_defconfig -+++ b/arch/arm64/configs/bcmrpi3_defconfig -@@ -53,6 +53,7 @@ CONFIG_ARMV8_DEPRECATED=y - CONFIG_SWP_EMULATION=y - CONFIG_CP15_BARRIER_EMULATION=y - CONFIG_SETEND_EMULATION=y -+CONFIG_RANDOMIZE_BASE=y - CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" - CONFIG_BINFMT_MISC=y - CONFIG_COMPAT=y diff --git a/target/linux/brcm2708/patches-4.9/0126-spi-bcm2835-Disable-forced-software-CS.patch b/target/linux/brcm2708/patches-4.9/0126-spi-bcm2835-Disable-forced-software-CS.patch new file mode 100644 index 0000000000..544ccf6f0b --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0126-spi-bcm2835-Disable-forced-software-CS.patch @@ -0,0 +1,26 @@ +From a6ef8db0e46713da43c81bc15fed01a4da0bd5a4 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 1 Jul 2016 22:09:24 +0100 +Subject: [PATCH] spi-bcm2835: Disable forced software CS + +Select software CS in bcm2708_common.dtsi, and disable the automatic +conversion in the driver to allow hardware CS to be re-enabled with an +overlay. + +See: https://github.com/raspberrypi/linux/issues/1547 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm283x.dtsi | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/boot/dts/bcm283x.dtsi ++++ b/arch/arm/boot/dts/bcm283x.dtsi +@@ -163,6 +163,7 @@ + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; ++ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; + }; + + i2c0: i2c@7e205000 { diff --git a/target/linux/brcm2708/patches-4.9/0127-config-Add-CONFIG_TCP_CONG_BBR.patch b/target/linux/brcm2708/patches-4.9/0127-config-Add-CONFIG_TCP_CONG_BBR.patch new file mode 100644 index 0000000000..cec560e06e --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0127-config-Add-CONFIG_TCP_CONG_BBR.patch @@ -0,0 +1,33 @@ +From 6f95da255ded5f1da673f826de07963e6a619e3d Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 16 Jan 2017 16:33:54 +0000 +Subject: [PATCH] config: Add CONFIG_TCP_CONG_BBR See: + https://github.com/raspberrypi/linux/issues/1784 + +--- + arch/arm/configs/bcm2709_defconfig | 2 ++ + arch/arm/configs/bcmrpi_defconfig | 2 ++ + 2 files changed, 4 insertions(+) + +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -99,6 +99,8 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m + CONFIG_INET_XFRM_MODE_TUNNEL=m + CONFIG_INET_XFRM_MODE_BEET=m + CONFIG_INET_DIAG=m ++CONFIG_TCP_CONG_ADVANCED=y ++CONFIG_TCP_CONG_BBR=m + CONFIG_IPV6=m + CONFIG_IPV6_ROUTER_PREF=y + CONFIG_INET6_AH=m +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -95,6 +95,8 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m + CONFIG_INET_XFRM_MODE_TUNNEL=m + CONFIG_INET_XFRM_MODE_BEET=m + CONFIG_INET_DIAG=m ++CONFIG_TCP_CONG_ADVANCED=y ++CONFIG_TCP_CONG_BBR=m + CONFIG_IPV6=m + CONFIG_IPV6_ROUTER_PREF=y + CONFIG_INET6_AH=m diff --git a/target/linux/brcm2708/patches-4.9/0128-ARM64-Enable-RTL8187-RTL8192CU-wifi-in-build-config.patch b/target/linux/brcm2708/patches-4.9/0128-ARM64-Enable-RTL8187-RTL8192CU-wifi-in-build-config.patch deleted file mode 100644 index a309394994..0000000000 --- a/target/linux/brcm2708/patches-4.9/0128-ARM64-Enable-RTL8187-RTL8192CU-wifi-in-build-config.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0d1eefab92dbaca44fa241df4bbf234212782d43 Mon Sep 17 00:00:00 2001 -From: Michael Zoran -Date: Sun, 15 Jan 2017 07:31:59 -0800 -Subject: [PATCH] ARM64: Enable RTL8187/RTL8192CU wifi in build config - -These drivers build now, so they can be enabled back -in the build configuration just like they are for -32 bit. - -Signed-off-by: Michael Zoran ---- - arch/arm64/configs/bcmrpi3_defconfig | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/arch/arm64/configs/bcmrpi3_defconfig -+++ b/arch/arm64/configs/bcmrpi3_defconfig -@@ -531,6 +531,8 @@ CONFIG_RT2800USB_RT3573=y - CONFIG_RT2800USB_RT53XX=y - CONFIG_RT2800USB_RT55XX=y - CONFIG_RT2800USB_UNKNOWN=y -+CONFIG_RTL8187=m -+CONFIG_RTL8192CU=m - CONFIG_USB_ZD1201=m - CONFIG_ZD1211RW=m - CONFIG_MAC80211_HWSIM=m diff --git a/target/linux/brcm2708/patches-4.9/0128-BCM270X_DT-Enable-UART0-on-CM3.patch b/target/linux/brcm2708/patches-4.9/0128-BCM270X_DT-Enable-UART0-on-CM3.patch new file mode 100644 index 0000000000..4fbc443dcd --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0128-BCM270X_DT-Enable-UART0-on-CM3.patch @@ -0,0 +1,23 @@ +From 44586947e86f67ad71fdd3afca51f04fc27f3872 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 17 Jan 2017 11:34:58 +0000 +Subject: [PATCH] BCM270X_DT: Enable UART0 on CM3 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts +@@ -6,6 +6,10 @@ + model = "Raspberry Pi Compute Module 3"; + }; + ++&uart0 { ++ status = "okay"; ++}; ++ + &gpio { + sdhost_pins: sdhost_pins { + brcm,pins = <48 49 50 51 52 53>; diff --git a/target/linux/brcm2708/patches-4.9/0129-BCM270X_DT-Add-spi0-cs-overlay.patch b/target/linux/brcm2708/patches-4.9/0129-BCM270X_DT-Add-spi0-cs-overlay.patch deleted file mode 100644 index e90767a95a..0000000000 --- a/target/linux/brcm2708/patches-4.9/0129-BCM270X_DT-Add-spi0-cs-overlay.patch +++ /dev/null @@ -1,83 +0,0 @@ -From efdb964748f093780166ef56fa7873067d35074e Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 16 Jan 2017 14:53:12 +0000 -Subject: [PATCH] BCM270X_DT: Add spi0-cs overlay - -The spi0-cs overlay allows the software chip selectts to be modified -using the cs0_pin and cs1_pin parameters. - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 9 +++++++- - arch/arm/boot/dts/overlays/spi0-cs-overlay.dts | 29 ++++++++++++++++++++++++++ - 3 files changed, 38 insertions(+), 1 deletion(-) - create mode 100644 arch/arm/boot/dts/overlays/spi0-cs-overlay.dts - ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -83,6 +83,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - smi-nand.dtbo \ - spi-gpio35-39.dtbo \ - spi-rtc.dtbo \ -+ spi0-cs.dtbo \ - spi0-hw-cs.dtbo \ - spi1-1cs.dtbo \ - spi1-2cs.dtbo \ ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -1138,7 +1138,7 @@ Params: - - - Name: spi-gpio35-39 --Info: move SPI function block to GPIO 35 to 39 -+Info: Move SPI function block to GPIO 35 to 39 - Load: dtoverlay=spi-gpio35-39 - Params: - -@@ -1149,6 +1149,13 @@ Load: dtoverlay=spi-rtc,= - Params: pcf2123 Select the PCF2123 device - - -+Name: spi0-cs -+Info: Allows the (software) CS pins for SPI0 to be changed -+Load: dtoverlay=spi0-cs,= -+Params: cs0_pin GPIO pin for CS0 (default 8) -+ cs1_pin GPIO pin for CS1 (default 7) -+ -+ - Name: spi0-hw-cs - Info: Re-enables hardware CS/CE (chip selects) for SPI0 - Load: dtoverlay=spi0-hw-cs ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts -@@ -0,0 +1,29 @@ -+/dts-v1/; -+/plugin/; -+ -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0_cs_pins>; -+ frag0: __overlay__ { -+ brcm,pins = <8 7>; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&spi0>; -+ frag1: __overlay__ { -+ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; -+ status = "okay"; -+ }; -+ }; -+ -+ __overrides__ { -+ cs0_pin = <&frag0>,"brcm,pins:0", -+ <&frag1>,"cs-gpios:4"; -+ cs1_pin = <&frag0>,"brcm,pins:4", -+ <&frag1>,"cs-gpios:16"; -+ }; -+}; diff --git a/target/linux/brcm2708/patches-4.9/0129-config-Add-CONFIG_MD_M25P80-and-CONFIG_MD_SPI_NOR.patch b/target/linux/brcm2708/patches-4.9/0129-config-Add-CONFIG_MD_M25P80-and-CONFIG_MD_SPI_NOR.patch new file mode 100644 index 0000000000..ab5e409006 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0129-config-Add-CONFIG_MD_M25P80-and-CONFIG_MD_SPI_NOR.patch @@ -0,0 +1,37 @@ +From 3f6ad80c79570b157d651720bf161843a360e922 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 17 Jan 2017 14:39:39 +0000 +Subject: [PATCH] config: Add CONFIG_MD_M25P80 and CONFIG_MD_SPI_NOR + +See: https://github.com/raspberrypi/linux/issues/1781 + +Signed-off-by: Phil Elwell +--- + arch/arm/configs/bcm2709_defconfig | 2 ++ + arch/arm/configs/bcmrpi_defconfig | 2 ++ + 2 files changed, 4 insertions(+) + +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -406,7 +406,9 @@ CONFIG_DMA_CMA=y + CONFIG_CMA_SIZE_MBYTES=5 + CONFIG_MTD=m + CONFIG_MTD_BLOCK=m ++CONFIG_MTD_M25P80=m + CONFIG_MTD_NAND=m ++CONFIG_MTD_SPI_NOR=m + CONFIG_MTD_UBI=m + CONFIG_OF_CONFIGFS=y + CONFIG_ZRAM=m +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -402,7 +402,9 @@ CONFIG_DMA_CMA=y + CONFIG_CMA_SIZE_MBYTES=5 + CONFIG_MTD=m + CONFIG_MTD_BLOCK=m ++CONFIG_MTD_M25P80=m + CONFIG_MTD_NAND=m ++CONFIG_MTD_SPI_NOR=m + CONFIG_MTD_UBI=m + CONFIG_OF_CONFIGFS=y + CONFIG_ZRAM=m diff --git a/target/linux/brcm2708/patches-4.9/0130-ARM64-DWC_OTG-Port-dwc_otg-driver-to-ARM64.patch b/target/linux/brcm2708/patches-4.9/0130-ARM64-DWC_OTG-Port-dwc_otg-driver-to-ARM64.patch new file mode 100644 index 0000000000..a94fee4690 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0130-ARM64-DWC_OTG-Port-dwc_otg-driver-to-ARM64.patch @@ -0,0 +1,329 @@ +From 99c33b6e418cefebb461fee0ad3a927a0c4127f1 Mon Sep 17 00:00:00 2001 +From: Michael Zoran +Date: Sat, 14 Jan 2017 21:33:51 -0800 +Subject: [PATCH] ARM64/DWC_OTG: Port dwc_otg driver to ARM64 + +In ARM64, the FIQ mechanism used by this driver is not current +implemented. As a workaround, reqular IRQ is used instead +of FIQ. + +In a separate change, the IRQ-CPU mapping is round robined +on ARM64 to increase concurrency and allow multiple interrupts +to be serviced at a time. This reduces the need for FIQ. + +Tests Run: + +This mechanism is most likely to break when multiple USB devices +are attached at the same time. So the system was tested under +stress. + +Devices: + +1. USB Speakers playing back a FLAC audio through VLC + at 96KHz.(Higher then typically, but supported on my speakers). + +2. sftp transferring large files through the buildin ethernet + connection which is connected through USB. + +3. Keyboard and mouse attached and being used. + +Although I do occasionally hear some glitches, the music seems to +play quite well. + +Signed-off-by: Michael Zoran +--- + drivers/usb/host/dwc_otg/Makefile | 3 ++ + drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 17 +++++++ + drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 24 ++++++++++ + drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 4 ++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 4 ++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 3 +- + drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 72 ++++++++++++++++++++++++++++ + drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 2 + + 8 files changed, 128 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/dwc_otg/Makefile ++++ b/drivers/usb/host/dwc_otg/Makefile +@@ -37,7 +37,10 @@ dwc_otg-objs += dwc_otg_pcd_linux.o dwc_ + dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o + dwc_otg-objs += dwc_otg_adp.o + dwc_otg-objs += dwc_otg_fiq_fsm.o ++ifneq ($(CONFIG_ARM64),y) + dwc_otg-objs += dwc_otg_fiq_stub.o ++endif ++ + ifneq ($(CFI),) + dwc_otg-objs += dwc_otg_cfi.o + endif +--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c +@@ -74,6 +74,21 @@ void notrace _fiq_print(enum fiq_debug_l + } + } + ++ ++#ifdef CONFIG_ARM64 ++ ++inline void fiq_fsm_spin_lock(fiq_lock_t *lock) ++{ ++ spin_lock((spinlock_t *)lock); ++} ++ ++inline void fiq_fsm_spin_unlock(fiq_lock_t *lock) ++{ ++ spin_unlock((spinlock_t *)lock); ++} ++ ++#else ++ + /** + * fiq_fsm_spin_lock() - ARMv6+ bare bones spinlock + * Must be called with local interrupts and FIQ disabled. +@@ -122,6 +137,8 @@ inline void fiq_fsm_spin_unlock(fiq_lock + inline void fiq_fsm_spin_unlock(fiq_lock_t *lock) { } + #endif + ++#endif ++ + /** + * fiq_fsm_restart_channel() - Poke channel enable bit for a split transaction + * @channel: channel to re-enable +--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h ++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h +@@ -127,6 +127,12 @@ enum fiq_debug_level { + FIQDBG_PORTHUB = (1 << 3), + }; + ++#ifdef CONFIG_ARM64 ++ ++typedef spinlock_t fiq_lock_t; ++ ++#else ++ + typedef struct { + union { + uint32_t slock; +@@ -137,6 +143,8 @@ typedef struct { + }; + } fiq_lock_t; + ++#endif ++ + struct fiq_state; + + extern void _fiq_print (enum fiq_debug_level dbg_lvl, volatile struct fiq_state *state, char *fmt, ...); +@@ -355,6 +363,22 @@ struct fiq_state { + struct fiq_channel_state channel[0]; + }; + ++#ifdef CONFIG_ARM64 ++ ++#ifdef local_fiq_enable ++#undef local_fiq_enable ++#endif ++ ++#ifdef local_fiq_disable ++#undef local_fiq_disable ++#endif ++ ++extern void local_fiq_enable(void); ++ ++extern void local_fiq_disable(void); ++ ++#endif ++ + extern void fiq_fsm_spin_lock(fiq_lock_t *lock); + + extern void fiq_fsm_spin_unlock(fiq_lock_t *lock); +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +@@ -1021,6 +1021,10 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd + } + DWC_MEMSET(hcd->fiq_state, 0, (sizeof(struct fiq_state) + (sizeof(struct fiq_channel_state) * num_channels))); + ++#ifdef CONFIG_ARM64 ++ spin_lock_init(&hcd->fiq_state->lock); ++#endif ++ + for (i = 0; i < num_channels; i++) { + hcd->fiq_state->channel[i].fsm = FIQ_PASSTHROUGH; + } +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h +@@ -116,7 +116,11 @@ extern int32_t dwc_otg_hcd_handle_intr(d + /** This function is used to handle the fast interrupt + * + */ ++#ifdef CONFIG_ARM64 ++extern void dwc_otg_hcd_handle_fiq(void); ++#else + extern void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void); ++#endif + + /** + * Returns private data set by +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +@@ -36,8 +36,9 @@ + #include "dwc_otg_regs.h" + + #include ++#ifdef CONFIG_ARM + #include +- ++#endif + + extern bool microframe_schedule; + +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c +@@ -51,7 +51,9 @@ + #include + #include + #include ++#ifdef CONFIG_ARM + #include ++#endif + #include + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) + #include <../drivers/usb/core/hcd.h> +@@ -71,6 +73,13 @@ + #include "dwc_otg_driver.h" + #include "dwc_otg_hcd.h" + ++#ifndef __virt_to_bus ++#define __virt_to_bus __virt_to_phys ++#define __bus_to_virt __phys_to_virt ++#define __pfn_to_bus(x) __pfn_to_phys(x) ++#define __bus_to_pfn(x) __phys_to_pfn(x) ++#endif ++ + extern unsigned char _dwc_otg_fiq_stub, _dwc_otg_fiq_stub_end; + + /** +@@ -393,14 +402,49 @@ static struct dwc_otg_hcd_function_ops h + .get_b_hnp_enable = _get_b_hnp_enable, + }; + ++#ifdef CONFIG_ARM64 ++ ++static int simfiq_irq = -1; ++ ++void local_fiq_enable(void) ++{ ++ if (simfiq_irq >= 0) ++ enable_irq(simfiq_irq); ++} ++ ++void local_fiq_disable(void) ++{ ++ if (simfiq_irq >= 0) ++ disable_irq(simfiq_irq); ++} ++ ++irqreturn_t fiq_irq_handler(int irq, void *dev_id) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *)dev_id; ++ ++ if (fiq_fsm_enable) ++ dwc_otg_fiq_fsm(dwc_otg_hcd->fiq_state, dwc_otg_hcd->core_if->core_params->host_channels); ++ else ++ dwc_otg_fiq_nop(dwc_otg_hcd->fiq_state); ++ ++ return IRQ_HANDLED; ++} ++ ++#else + static struct fiq_handler fh = { + .name = "usb_fiq", + }; + ++#endif ++ + static void hcd_init_fiq(void *cookie) + { + dwc_otg_device_t *otg_dev = cookie; + dwc_otg_hcd_t *dwc_otg_hcd = otg_dev->hcd; ++#ifdef CONFIG_ARM64 ++ int retval = 0; ++ int irq; ++#else + struct pt_regs regs; + int irq; + +@@ -428,6 +472,7 @@ static void hcd_init_fiq(void *cookie) + + // __show_regs(®s); + set_fiq_regs(®s); ++#endif + + //Set the mphi periph to the required registers + dwc_otg_hcd->fiq_state->mphi_regs.base = otg_dev->os_dep.mphi_base; +@@ -446,6 +491,23 @@ static void hcd_init_fiq(void *cookie) + DWC_WARN("MPHI periph has NOT been enabled"); + #endif + // Enable FIQ interrupt from USB peripheral ++#ifdef CONFIG_ARM64 ++ irq = platform_get_irq(otg_dev->os_dep.platformdev, 1); ++ ++ if (irq < 0) { ++ DWC_ERROR("Can't get SIM-FIQ irq"); ++ return; ++ } ++ ++ retval = request_irq(irq, fiq_irq_handler, 0, "dwc_otg_sim-fiq", dwc_otg_hcd); ++ ++ if (retval < 0) { ++ DWC_ERROR("Unable to request SIM-FIQ irq\n"); ++ return; ++ } ++ ++ simfiq_irq = irq; ++#else + #ifdef CONFIG_MULTI_IRQ_HANDLER + irq = platform_get_irq(otg_dev->os_dep.platformdev, 1); + #else +@@ -457,6 +519,8 @@ static void hcd_init_fiq(void *cookie) + } + enable_fiq(irq); + local_fiq_enable(); ++#endif ++ + } + + /** +@@ -519,6 +583,13 @@ int hcd_init(dwc_bus_dev_t *_dev) + otg_dev->hcd = dwc_otg_hcd; + otg_dev->hcd->otg_dev = otg_dev; + ++#ifdef CONFIG_ARM64 ++ if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) ++ goto error2; ++ ++ if (fiq_enable) ++ hcd_init_fiq(otg_dev); ++#else + if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) { + goto error2; + } +@@ -531,6 +602,7 @@ int hcd_init(dwc_bus_dev_t *_dev) + smp_call_function_single(0, hcd_init_fiq, otg_dev, 1); + } + } ++#endif + + hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel) +--- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h ++++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h +@@ -76,8 +76,10 @@ + + #ifdef PLATFORM_INTERFACE + #include ++#ifdef CONFIG_ARM + #include + #endif ++#endif + + /** The OS page size */ + #define DWC_OS_PAGE_SIZE PAGE_SIZE diff --git a/target/linux/brcm2708/patches-4.9/0130-spi-bcm2835-Disable-forced-software-CS.patch b/target/linux/brcm2708/patches-4.9/0130-spi-bcm2835-Disable-forced-software-CS.patch deleted file mode 100644 index b4ade04396..0000000000 --- a/target/linux/brcm2708/patches-4.9/0130-spi-bcm2835-Disable-forced-software-CS.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 2248b18b5d21d0ce59bb874a8e20e53a39317eb0 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 1 Jul 2016 22:09:24 +0100 -Subject: [PATCH] spi-bcm2835: Disable forced software CS - -Select software CS in bcm2708_common.dtsi, and disable the automatic -conversion in the driver to allow hardware CS to be re-enabled with an -overlay. - -See: https://github.com/raspberrypi/linux/issues/1547 - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/bcm283x.dtsi | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm/boot/dts/bcm283x.dtsi -+++ b/arch/arm/boot/dts/bcm283x.dtsi -@@ -163,6 +163,7 @@ - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; -+ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; - }; - - i2c0: i2c@7e205000 { diff --git a/target/linux/brcm2708/patches-4.9/0131-ARM64-Round-Robin-dispatch-IRQs-between-CPUs.patch b/target/linux/brcm2708/patches-4.9/0131-ARM64-Round-Robin-dispatch-IRQs-between-CPUs.patch new file mode 100644 index 0000000000..d11ca6bffd --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0131-ARM64-Round-Robin-dispatch-IRQs-between-CPUs.patch @@ -0,0 +1,72 @@ +From 3a9b48156c6681e846d1a7dbe4ecbb3ae14c2f3c Mon Sep 17 00:00:00 2001 +From: Michael Zoran +Date: Sat, 14 Jan 2017 21:43:57 -0800 +Subject: [PATCH] ARM64: Round-Robin dispatch IRQs between CPUs. + +IRQ-CPU mapping is round robined on ARM64 to increase +concurrency and allow multiple interrupts to be serviced +at a time. This reduces the need for FIQ. + +Signed-off-by: Michael Zoran +--- + drivers/irqchip/irq-bcm2835.c | 15 ++++++++++++++- + drivers/irqchip/irq-bcm2836.c | 21 +++++++++++++++++++++ + 2 files changed, 35 insertions(+), 1 deletion(-) + +--- a/drivers/irqchip/irq-bcm2835.c ++++ b/drivers/irqchip/irq-bcm2835.c +@@ -168,10 +168,23 @@ static void armctrl_unmask_irq(struct ir + } + } + ++#ifdef CONFIG_ARM64 ++void bcm2836_arm_irqchip_spin_gpu_irq(void); ++ ++static void armctrl_ack_irq(struct irq_data *d) ++{ ++ bcm2836_arm_irqchip_spin_gpu_irq(); ++} ++ ++#endif ++ + static struct irq_chip armctrl_chip = { + .name = "ARMCTRL-level", + .irq_mask = armctrl_mask_irq, +- .irq_unmask = armctrl_unmask_irq ++ .irq_unmask = armctrl_unmask_irq, ++#ifdef CONFIG_ARM64 ++ .irq_ack = armctrl_ack_irq ++#endif + }; + + static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr, +--- a/drivers/irqchip/irq-bcm2836.c ++++ b/drivers/irqchip/irq-bcm2836.c +@@ -145,6 +145,27 @@ static void bcm2836_arm_irqchip_unmask_g + { + } + ++#ifdef CONFIG_ARM64 ++ ++void bcm2836_arm_irqchip_spin_gpu_irq(void) ++{ ++ u32 i; ++ void __iomem *gpurouting = (intc.base + LOCAL_GPU_ROUTING); ++ u32 routing_val = readl(gpurouting); ++ ++ for (i = 1; i <= 3; i++) { ++ u32 new_routing_val = (routing_val + i) & 3; ++ ++ if (cpu_active(new_routing_val)) { ++ writel(new_routing_val, gpurouting); ++ return; ++ } ++ } ++} ++EXPORT_SYMBOL(bcm2836_arm_irqchip_spin_gpu_irq); ++ ++#endif ++ + static struct irq_chip bcm2836_arm_irqchip_gpu = { + .name = "bcm2836-gpu", + .irq_mask = bcm2836_arm_irqchip_mask_gpu_irq, diff --git a/target/linux/brcm2708/patches-4.9/0131-config-Add-CONFIG_TCP_CONG_BBR.patch b/target/linux/brcm2708/patches-4.9/0131-config-Add-CONFIG_TCP_CONG_BBR.patch deleted file mode 100644 index f0076ce5ee..0000000000 --- a/target/linux/brcm2708/patches-4.9/0131-config-Add-CONFIG_TCP_CONG_BBR.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 7342a6ab0f9d60cc65a2a585ac43d3aa114f7e61 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 16 Jan 2017 16:33:54 +0000 -Subject: [PATCH] config: Add CONFIG_TCP_CONG_BBR See: - https://github.com/raspberrypi/linux/issues/1784 - ---- - arch/arm/configs/bcm2709_defconfig | 2 ++ - arch/arm/configs/bcmrpi_defconfig | 2 ++ - 2 files changed, 4 insertions(+) - ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -99,6 +99,8 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m - CONFIG_INET_XFRM_MODE_TUNNEL=m - CONFIG_INET_XFRM_MODE_BEET=m - CONFIG_INET_DIAG=m -+CONFIG_TCP_CONG_ADVANCED=y -+CONFIG_TCP_CONG_BBR=m - CONFIG_IPV6=m - CONFIG_IPV6_ROUTER_PREF=y - CONFIG_INET6_AH=m ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -95,6 +95,8 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m - CONFIG_INET_XFRM_MODE_TUNNEL=m - CONFIG_INET_XFRM_MODE_BEET=m - CONFIG_INET_DIAG=m -+CONFIG_TCP_CONG_ADVANCED=y -+CONFIG_TCP_CONG_BBR=m - CONFIG_IPV6=m - CONFIG_IPV6_ROUTER_PREF=y - CONFIG_INET6_AH=m diff --git a/target/linux/brcm2708/patches-4.9/0132-ARM64-Enable-DWC_OTG-Driver-In-ARM64-Build-Config-bc.patch b/target/linux/brcm2708/patches-4.9/0132-ARM64-Enable-DWC_OTG-Driver-In-ARM64-Build-Config-bc.patch new file mode 100644 index 0000000000..deae274af3 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0132-ARM64-Enable-DWC_OTG-Driver-In-ARM64-Build-Config-bc.patch @@ -0,0 +1,21 @@ +From ad17c9e5a03f835605560e7163e5e685a67abd1f Mon Sep 17 00:00:00 2001 +From: Michael Zoran +Date: Sat, 14 Jan 2017 21:45:03 -0800 +Subject: [PATCH] ARM64: Enable DWC_OTG Driver In ARM64 Build + Config(bcmrpi3_defconfig) + +Signed-off-by: Michael Zoran +--- + arch/arm64/configs/bcmrpi3_defconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm64/configs/bcmrpi3_defconfig ++++ b/arch/arm64/configs/bcmrpi3_defconfig +@@ -932,6 +932,7 @@ CONFIG_USB_HIDDEV=y + CONFIG_USB=y + CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + CONFIG_USB_MON=m ++CONFIG_USB_DWCOTG=y + CONFIG_USB_PRINTER=m + CONFIG_USB_STORAGE=y + CONFIG_USB_STORAGE_REALTEK=m diff --git a/target/linux/brcm2708/patches-4.9/0132-Revert-bcm2835-i2s-Changes-for-allowing-asymmetric-s.patch b/target/linux/brcm2708/patches-4.9/0132-Revert-bcm2835-i2s-Changes-for-allowing-asymmetric-s.patch deleted file mode 100644 index 189b288898..0000000000 --- a/target/linux/brcm2708/patches-4.9/0132-Revert-bcm2835-i2s-Changes-for-allowing-asymmetric-s.patch +++ /dev/null @@ -1,90 +0,0 @@ -From db51b292d97ecb021831ed380ce4e1152b1bd235 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 16 Jan 2017 21:02:26 +0000 -Subject: [PATCH] Revert "bcm2835-i2s: Changes for allowing asymmetric sample - formats." - -This reverts commit f5a6236a32e82068122301d246a94ca755d61704. - -See: https://github.com/raspberrypi/linux/issues/1799 - -Signed-off-by: Phil Elwell ---- - sound/soc/bcm/bcm2835-i2s.c | 54 ++++++++++++++------------------------------- - 1 file changed, 16 insertions(+), 38 deletions(-) - ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -237,9 +237,7 @@ static int bcm2835_i2s_hw_params(struct - unsigned int sampling_rate = params_rate(params); - unsigned int data_length, data_delay, bclk_ratio; - unsigned int ch1pos, ch2pos, mode, format; -- unsigned int previous_ftxp, previous_frxp; - uint32_t csreg; -- bool packed; - - /* - * If a stream is already enabled, -@@ -322,46 +320,26 @@ static int bcm2835_i2s_hw_params(struct - return -EINVAL; - } - -- /* Set the format for the matching stream direction. */ -- switch (substream->stream) { -- case SNDRV_PCM_STREAM_PLAYBACK: -- regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format); -- break; -- case SNDRV_PCM_STREAM_CAPTURE: -- regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format); -- break; -- default: -- return -EINVAL; -- } -+ /* -+ * Set format for both streams. -+ * We cannot set another frame length -+ * (and therefore word length) anyway, -+ * so the format will be the same. -+ */ -+ regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format); -+ regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format); - - /* Setup the I2S mode */ -- /* Keep existing FTXP and FRXP values. */ -- regmap_read(dev->i2s_regmap, BCM2835_I2S_MODE_A_REG, &mode); -- -- previous_ftxp = mode & BCM2835_I2S_FTXP; -- previous_frxp = mode & BCM2835_I2S_FRXP; -- - mode = 0; - -- /* -- * Retain the frame packed mode (2 channels per 32 bit word) -- * of the other direction stream intact. The formats of each -- * direction can be different as long as the frame length is -- * shared for both. -- */ -- packed = data_length <= 16; -- -- switch (substream->stream) { -- case SNDRV_PCM_STREAM_PLAYBACK: -- mode |= previous_frxp; -- mode |= packed ? BCM2835_I2S_FTXP : 0; -- break; -- case SNDRV_PCM_STREAM_CAPTURE: -- mode |= previous_ftxp; -- mode |= packed ? BCM2835_I2S_FRXP : 0; -- break; -- default: -- return -EINVAL; -+ if (data_length <= 16) { -+ /* -+ * Use frame packed mode (2 channels per 32 bit word) -+ * We cannot set another frame length in the second stream -+ * (and therefore word length) anyway, -+ * so the format will be the same. -+ */ -+ mode |= BCM2835_I2S_FTXP | BCM2835_I2S_FRXP; - } - - mode |= BCM2835_I2S_FLEN(bclk_ratio - 1); diff --git a/target/linux/brcm2708/patches-4.9/0133-ARM64-Use-dwc_otg-driver-by-default-for-USB.patch b/target/linux/brcm2708/patches-4.9/0133-ARM64-Use-dwc_otg-driver-by-default-for-USB.patch new file mode 100644 index 0000000000..53335b95fb --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0133-ARM64-Use-dwc_otg-driver-by-default-for-USB.patch @@ -0,0 +1,26 @@ +From 4eec6ce872ac46987efeb9b9cdab0ad78a563bdb Mon Sep 17 00:00:00 2001 +From: Michael Zoran +Date: Sat, 14 Jan 2017 21:46:04 -0800 +Subject: [PATCH] ARM64: Use dwc_otg driver by default for USB. + +If it breaks on anybody, they can use the standard device tree +overlays to switch back to the dwc2 driver. + +Signed-off-by: Michael Zoran +--- + arch/arm/boot/dts/bcm2710.dtsi | 7 ------- + 1 file changed, 7 deletions(-) + +--- a/arch/arm/boot/dts/bcm2710.dtsi ++++ b/arch/arm/boot/dts/bcm2710.dtsi +@@ -146,10 +146,3 @@ + interrupts = <8>; + }; + +-#ifdef RPI364 +-&usb { +- compatible = "brcm,bcm2835-usb"; +- reg = <0x7e980000 0x10000>; +- interrupts = <1 9>; +-}; +-#endif diff --git a/target/linux/brcm2708/patches-4.9/0133-BCM270X_DT-Enable-UART0-on-CM3.patch b/target/linux/brcm2708/patches-4.9/0133-BCM270X_DT-Enable-UART0-on-CM3.patch deleted file mode 100644 index c2ba65f9a9..0000000000 --- a/target/linux/brcm2708/patches-4.9/0133-BCM270X_DT-Enable-UART0-on-CM3.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 074d3a044fc1d3bc54c3728ae4ae045ef432a1d2 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 17 Jan 2017 11:34:58 +0000 -Subject: [PATCH] BCM270X_DT: Enable UART0 on CM3 - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -@@ -6,6 +6,10 @@ - model = "Raspberry Pi Compute Module 3"; - }; - -+&uart0 { -+ status = "okay"; -+}; -+ - &gpio { - sdhost_pins: sdhost_pins { - brcm,pins = <48 49 50 51 52 53>; diff --git a/target/linux/brcm2708/patches-4.9/0134-BCM270X_DT-Add-reference-to-audio_pins-to-CM-dtb.patch b/target/linux/brcm2708/patches-4.9/0134-BCM270X_DT-Add-reference-to-audio_pins-to-CM-dtb.patch new file mode 100644 index 0000000000..63df4a0378 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0134-BCM270X_DT-Add-reference-to-audio_pins-to-CM-dtb.patch @@ -0,0 +1,28 @@ +From 8630b0b3fea31138c52ef83848ae1a047baa3855 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 23 Jan 2017 17:36:50 +0000 +Subject: [PATCH] BCM270X_DT: Add reference to audio_pins to CM dtb + +The CM1 dtb contains an empty audio_pins node, but no reference to it. +Adding the usual pinctrl reference from the audio node enables the +audremap overlay (and others) to easily turn on audio. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2708-rpi-cm.dts | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/arch/arm/boot/dts/bcm2708-rpi-cm.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts +@@ -85,6 +85,11 @@ + pinctrl-0 = <&i2s_pins>; + }; + ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_pins>; ++}; ++ + &hdmi { + hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; + }; diff --git a/target/linux/brcm2708/patches-4.9/0134-config-Add-CONFIG_MD_M25P80-and-CONFIG_MD_SPI_NOR.patch b/target/linux/brcm2708/patches-4.9/0134-config-Add-CONFIG_MD_M25P80-and-CONFIG_MD_SPI_NOR.patch deleted file mode 100644 index 3d1bb7e0d0..0000000000 --- a/target/linux/brcm2708/patches-4.9/0134-config-Add-CONFIG_MD_M25P80-and-CONFIG_MD_SPI_NOR.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 1159cc636986b9915419efa87e136279b4ba7df9 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 17 Jan 2017 14:39:39 +0000 -Subject: [PATCH] config: Add CONFIG_MD_M25P80 and CONFIG_MD_SPI_NOR - -See: https://github.com/raspberrypi/linux/issues/1781 - -Signed-off-by: Phil Elwell ---- - arch/arm/configs/bcm2709_defconfig | 2 ++ - arch/arm/configs/bcmrpi_defconfig | 2 ++ - 2 files changed, 4 insertions(+) - ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -406,7 +406,9 @@ CONFIG_DMA_CMA=y - CONFIG_CMA_SIZE_MBYTES=5 - CONFIG_MTD=m - CONFIG_MTD_BLOCK=m -+CONFIG_MTD_M25P80=m - CONFIG_MTD_NAND=m -+CONFIG_MTD_SPI_NOR=m - CONFIG_MTD_UBI=m - CONFIG_OF_CONFIGFS=y - CONFIG_ZRAM=m ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -402,7 +402,9 @@ CONFIG_DMA_CMA=y - CONFIG_CMA_SIZE_MBYTES=5 - CONFIG_MTD=m - CONFIG_MTD_BLOCK=m -+CONFIG_MTD_M25P80=m - CONFIG_MTD_NAND=m -+CONFIG_MTD_SPI_NOR=m - CONFIG_MTD_UBI=m - CONFIG_OF_CONFIGFS=y - CONFIG_ZRAM=m diff --git a/target/linux/brcm2708/patches-4.9/0135-ARM64-DWC_OTG-Port-dwc_otg-driver-to-ARM64.patch b/target/linux/brcm2708/patches-4.9/0135-ARM64-DWC_OTG-Port-dwc_otg-driver-to-ARM64.patch deleted file mode 100644 index 4bb85d01c2..0000000000 --- a/target/linux/brcm2708/patches-4.9/0135-ARM64-DWC_OTG-Port-dwc_otg-driver-to-ARM64.patch +++ /dev/null @@ -1,329 +0,0 @@ -From 2f15deb5ab0fafa71f00bcf840cd01893b829555 Mon Sep 17 00:00:00 2001 -From: Michael Zoran -Date: Sat, 14 Jan 2017 21:33:51 -0800 -Subject: [PATCH] ARM64/DWC_OTG: Port dwc_otg driver to ARM64 - -In ARM64, the FIQ mechanism used by this driver is not current -implemented. As a workaround, reqular IRQ is used instead -of FIQ. - -In a separate change, the IRQ-CPU mapping is round robined -on ARM64 to increase concurrency and allow multiple interrupts -to be serviced at a time. This reduces the need for FIQ. - -Tests Run: - -This mechanism is most likely to break when multiple USB devices -are attached at the same time. So the system was tested under -stress. - -Devices: - -1. USB Speakers playing back a FLAC audio through VLC - at 96KHz.(Higher then typically, but supported on my speakers). - -2. sftp transferring large files through the buildin ethernet - connection which is connected through USB. - -3. Keyboard and mouse attached and being used. - -Although I do occasionally hear some glitches, the music seems to -play quite well. - -Signed-off-by: Michael Zoran ---- - drivers/usb/host/dwc_otg/Makefile | 3 ++ - drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 17 +++++++ - drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 24 ++++++++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 4 ++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 4 ++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 3 +- - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 72 ++++++++++++++++++++++++++++ - drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 2 + - 8 files changed, 128 insertions(+), 1 deletion(-) - ---- a/drivers/usb/host/dwc_otg/Makefile -+++ b/drivers/usb/host/dwc_otg/Makefile -@@ -37,7 +37,10 @@ dwc_otg-objs += dwc_otg_pcd_linux.o dwc_ - dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o - dwc_otg-objs += dwc_otg_adp.o - dwc_otg-objs += dwc_otg_fiq_fsm.o -+ifneq ($(CONFIG_ARM64),y) - dwc_otg-objs += dwc_otg_fiq_stub.o -+endif -+ - ifneq ($(CFI),) - dwc_otg-objs += dwc_otg_cfi.o - endif ---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c -@@ -74,6 +74,21 @@ void notrace _fiq_print(enum fiq_debug_l - } - } - -+ -+#ifdef CONFIG_ARM64 -+ -+inline void fiq_fsm_spin_lock(fiq_lock_t *lock) -+{ -+ spin_lock((spinlock_t *)lock); -+} -+ -+inline void fiq_fsm_spin_unlock(fiq_lock_t *lock) -+{ -+ spin_unlock((spinlock_t *)lock); -+} -+ -+#else -+ - /** - * fiq_fsm_spin_lock() - ARMv6+ bare bones spinlock - * Must be called with local interrupts and FIQ disabled. -@@ -122,6 +137,8 @@ inline void fiq_fsm_spin_unlock(fiq_lock - inline void fiq_fsm_spin_unlock(fiq_lock_t *lock) { } - #endif - -+#endif -+ - /** - * fiq_fsm_restart_channel() - Poke channel enable bit for a split transaction - * @channel: channel to re-enable ---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h -@@ -127,6 +127,12 @@ enum fiq_debug_level { - FIQDBG_PORTHUB = (1 << 3), - }; - -+#ifdef CONFIG_ARM64 -+ -+typedef spinlock_t fiq_lock_t; -+ -+#else -+ - typedef struct { - union { - uint32_t slock; -@@ -137,6 +143,8 @@ typedef struct { - }; - } fiq_lock_t; - -+#endif -+ - struct fiq_state; - - extern void _fiq_print (enum fiq_debug_level dbg_lvl, volatile struct fiq_state *state, char *fmt, ...); -@@ -355,6 +363,22 @@ struct fiq_state { - struct fiq_channel_state channel[0]; - }; - -+#ifdef CONFIG_ARM64 -+ -+#ifdef local_fiq_enable -+#undef local_fiq_enable -+#endif -+ -+#ifdef local_fiq_disable -+#undef local_fiq_disable -+#endif -+ -+extern void local_fiq_enable(void); -+ -+extern void local_fiq_disable(void); -+ -+#endif -+ - extern void fiq_fsm_spin_lock(fiq_lock_t *lock); - - extern void fiq_fsm_spin_unlock(fiq_lock_t *lock); ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -@@ -1021,6 +1021,10 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd - } - DWC_MEMSET(hcd->fiq_state, 0, (sizeof(struct fiq_state) + (sizeof(struct fiq_channel_state) * num_channels))); - -+#ifdef CONFIG_ARM64 -+ spin_lock_init(&hcd->fiq_state->lock); -+#endif -+ - for (i = 0; i < num_channels; i++) { - hcd->fiq_state->channel[i].fsm = FIQ_PASSTHROUGH; - } ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h -@@ -116,7 +116,11 @@ extern int32_t dwc_otg_hcd_handle_intr(d - /** This function is used to handle the fast interrupt - * - */ -+#ifdef CONFIG_ARM64 -+extern void dwc_otg_hcd_handle_fiq(void); -+#else - extern void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void); -+#endif - - /** - * Returns private data set by ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -@@ -36,8 +36,9 @@ - #include "dwc_otg_regs.h" - - #include -+#ifdef CONFIG_ARM - #include -- -+#endif - - extern bool microframe_schedule; - ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -51,7 +51,9 @@ - #include - #include - #include -+#ifdef CONFIG_ARM - #include -+#endif - #include - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) - #include <../drivers/usb/core/hcd.h> -@@ -71,6 +73,13 @@ - #include "dwc_otg_driver.h" - #include "dwc_otg_hcd.h" - -+#ifndef __virt_to_bus -+#define __virt_to_bus __virt_to_phys -+#define __bus_to_virt __phys_to_virt -+#define __pfn_to_bus(x) __pfn_to_phys(x) -+#define __bus_to_pfn(x) __phys_to_pfn(x) -+#endif -+ - extern unsigned char _dwc_otg_fiq_stub, _dwc_otg_fiq_stub_end; - - /** -@@ -393,14 +402,49 @@ static struct dwc_otg_hcd_function_ops h - .get_b_hnp_enable = _get_b_hnp_enable, - }; - -+#ifdef CONFIG_ARM64 -+ -+static int simfiq_irq = -1; -+ -+void local_fiq_enable(void) -+{ -+ if (simfiq_irq >= 0) -+ enable_irq(simfiq_irq); -+} -+ -+void local_fiq_disable(void) -+{ -+ if (simfiq_irq >= 0) -+ disable_irq(simfiq_irq); -+} -+ -+irqreturn_t fiq_irq_handler(int irq, void *dev_id) -+{ -+ dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *)dev_id; -+ -+ if (fiq_fsm_enable) -+ dwc_otg_fiq_fsm(dwc_otg_hcd->fiq_state, dwc_otg_hcd->core_if->core_params->host_channels); -+ else -+ dwc_otg_fiq_nop(dwc_otg_hcd->fiq_state); -+ -+ return IRQ_HANDLED; -+} -+ -+#else - static struct fiq_handler fh = { - .name = "usb_fiq", - }; - -+#endif -+ - static void hcd_init_fiq(void *cookie) - { - dwc_otg_device_t *otg_dev = cookie; - dwc_otg_hcd_t *dwc_otg_hcd = otg_dev->hcd; -+#ifdef CONFIG_ARM64 -+ int retval = 0; -+ int irq; -+#else - struct pt_regs regs; - int irq; - -@@ -428,6 +472,7 @@ static void hcd_init_fiq(void *cookie) - - // __show_regs(®s); - set_fiq_regs(®s); -+#endif - - //Set the mphi periph to the required registers - dwc_otg_hcd->fiq_state->mphi_regs.base = otg_dev->os_dep.mphi_base; -@@ -446,6 +491,23 @@ static void hcd_init_fiq(void *cookie) - DWC_WARN("MPHI periph has NOT been enabled"); - #endif - // Enable FIQ interrupt from USB peripheral -+#ifdef CONFIG_ARM64 -+ irq = platform_get_irq(otg_dev->os_dep.platformdev, 1); -+ -+ if (irq < 0) { -+ DWC_ERROR("Can't get SIM-FIQ irq"); -+ return; -+ } -+ -+ retval = request_irq(irq, fiq_irq_handler, 0, "dwc_otg_sim-fiq", dwc_otg_hcd); -+ -+ if (retval < 0) { -+ DWC_ERROR("Unable to request SIM-FIQ irq\n"); -+ return; -+ } -+ -+ simfiq_irq = irq; -+#else - #ifdef CONFIG_MULTI_IRQ_HANDLER - irq = platform_get_irq(otg_dev->os_dep.platformdev, 1); - #else -@@ -457,6 +519,8 @@ static void hcd_init_fiq(void *cookie) - } - enable_fiq(irq); - local_fiq_enable(); -+#endif -+ - } - - /** -@@ -519,6 +583,13 @@ int hcd_init(dwc_bus_dev_t *_dev) - otg_dev->hcd = dwc_otg_hcd; - otg_dev->hcd->otg_dev = otg_dev; - -+#ifdef CONFIG_ARM64 -+ if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) -+ goto error2; -+ -+ if (fiq_enable) -+ hcd_init_fiq(otg_dev); -+#else - if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) { - goto error2; - } -@@ -531,6 +602,7 @@ int hcd_init(dwc_bus_dev_t *_dev) - smp_call_function_single(0, hcd_init_fiq, otg_dev, 1); - } - } -+#endif - - hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd); - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel) ---- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h -@@ -76,8 +76,10 @@ - - #ifdef PLATFORM_INTERFACE - #include -+#ifdef CONFIG_ARM - #include - #endif -+#endif - - /** The OS page size */ - #define DWC_OS_PAGE_SIZE PAGE_SIZE diff --git a/target/linux/brcm2708/patches-4.9/0135-config-Add-additional-network-scheduling-modules.patch b/target/linux/brcm2708/patches-4.9/0135-config-Add-additional-network-scheduling-modules.patch new file mode 100644 index 0000000000..6c50870c7e --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0135-config-Add-additional-network-scheduling-modules.patch @@ -0,0 +1,50 @@ +From 56aef4ffcf12fdede0dad012de939c5a7c9cc55b Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 25 Jan 2017 11:30:38 +0000 +Subject: [PATCH] config: Add additional network scheduling modules + +--- + arch/arm/configs/bcm2709_defconfig | 4 ++++ + arch/arm/configs/bcmrpi_defconfig | 4 ++++ + 2 files changed, 8 insertions(+) + +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -296,6 +296,7 @@ CONFIG_NET_SCHED=y + CONFIG_NET_SCH_CBQ=m + CONFIG_NET_SCH_HTB=m + CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_ATM=m + CONFIG_NET_SCH_PRIO=m + CONFIG_NET_SCH_MULTIQ=m + CONFIG_NET_SCH_RED=m +@@ -312,6 +313,9 @@ CONFIG_NET_SCH_CHOKE=m + CONFIG_NET_SCH_QFQ=m + CONFIG_NET_SCH_CODEL=m + CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_FQ=m ++CONFIG_NET_SCH_HHF=m ++CONFIG_NET_SCH_PIE=m + CONFIG_NET_SCH_INGRESS=m + CONFIG_NET_SCH_PLUG=m + CONFIG_NET_CLS_BASIC=m +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -292,6 +292,7 @@ CONFIG_NET_SCHED=y + CONFIG_NET_SCH_CBQ=m + CONFIG_NET_SCH_HTB=m + CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_ATM=m + CONFIG_NET_SCH_PRIO=m + CONFIG_NET_SCH_MULTIQ=m + CONFIG_NET_SCH_RED=m +@@ -308,6 +309,9 @@ CONFIG_NET_SCH_CHOKE=m + CONFIG_NET_SCH_QFQ=m + CONFIG_NET_SCH_CODEL=m + CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_FQ=m ++CONFIG_NET_SCH_HHF=m ++CONFIG_NET_SCH_PIE=m + CONFIG_NET_SCH_INGRESS=m + CONFIG_NET_SCH_PLUG=m + CONFIG_NET_CLS_BASIC=m diff --git a/target/linux/brcm2708/patches-4.9/0136-ARM64-Round-Robin-dispatch-IRQs-between-CPUs.patch b/target/linux/brcm2708/patches-4.9/0136-ARM64-Round-Robin-dispatch-IRQs-between-CPUs.patch deleted file mode 100644 index 6685bbb7c1..0000000000 --- a/target/linux/brcm2708/patches-4.9/0136-ARM64-Round-Robin-dispatch-IRQs-between-CPUs.patch +++ /dev/null @@ -1,72 +0,0 @@ -From b51f35c59a6f40f7f58ff75a2c1b414421224ec2 Mon Sep 17 00:00:00 2001 -From: Michael Zoran -Date: Sat, 14 Jan 2017 21:43:57 -0800 -Subject: [PATCH] ARM64: Round-Robin dispatch IRQs between CPUs. - -IRQ-CPU mapping is round robined on ARM64 to increase -concurrency and allow multiple interrupts to be serviced -at a time. This reduces the need for FIQ. - -Signed-off-by: Michael Zoran ---- - drivers/irqchip/irq-bcm2835.c | 15 ++++++++++++++- - drivers/irqchip/irq-bcm2836.c | 21 +++++++++++++++++++++ - 2 files changed, 35 insertions(+), 1 deletion(-) - ---- a/drivers/irqchip/irq-bcm2835.c -+++ b/drivers/irqchip/irq-bcm2835.c -@@ -168,10 +168,23 @@ static void armctrl_unmask_irq(struct ir - } - } - -+#ifdef CONFIG_ARM64 -+void bcm2836_arm_irqchip_spin_gpu_irq(void); -+ -+static void armctrl_ack_irq(struct irq_data *d) -+{ -+ bcm2836_arm_irqchip_spin_gpu_irq(); -+} -+ -+#endif -+ - static struct irq_chip armctrl_chip = { - .name = "ARMCTRL-level", - .irq_mask = armctrl_mask_irq, -- .irq_unmask = armctrl_unmask_irq -+ .irq_unmask = armctrl_unmask_irq, -+#ifdef CONFIG_ARM64 -+ .irq_ack = armctrl_ack_irq -+#endif - }; - - static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr, ---- a/drivers/irqchip/irq-bcm2836.c -+++ b/drivers/irqchip/irq-bcm2836.c -@@ -145,6 +145,27 @@ static void bcm2836_arm_irqchip_unmask_g - { - } - -+#ifdef CONFIG_ARM64 -+ -+void bcm2836_arm_irqchip_spin_gpu_irq(void) -+{ -+ u32 i; -+ void __iomem *gpurouting = (intc.base + LOCAL_GPU_ROUTING); -+ u32 routing_val = readl(gpurouting); -+ -+ for (i = 1; i <= 3; i++) { -+ u32 new_routing_val = (routing_val + i) & 3; -+ -+ if (cpu_active(new_routing_val)) { -+ writel(new_routing_val, gpurouting); -+ return; -+ } -+ } -+} -+EXPORT_SYMBOL(bcm2836_arm_irqchip_spin_gpu_irq); -+ -+#endif -+ - static struct irq_chip bcm2836_arm_irqchip_gpu = { - .name = "bcm2836-gpu", - .irq_mask = bcm2836_arm_irqchip_mask_gpu_irq, diff --git a/target/linux/brcm2708/patches-4.9/0136-ASoC-A-simple-card-overlay-for-ADAU7002.patch b/target/linux/brcm2708/patches-4.9/0136-ASoC-A-simple-card-overlay-for-ADAU7002.patch new file mode 100644 index 0000000000..4f122fcdb0 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0136-ASoC-A-simple-card-overlay-for-ADAU7002.patch @@ -0,0 +1,93 @@ +From 1cd1f19adbe020544e18193a006af9c71c8c82ca Mon Sep 17 00:00:00 2001 +From: chris johnson +Date: Sun, 22 Jan 2017 03:27:31 +0000 +Subject: [PATCH] ASoC: A simple-card overlay for ADAU7002 + +Usage: `dtoverlay=adau7002-simple` +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 6 +++ + .../boot/dts/overlays/adau7002-simple-overlay.dts | 52 ++++++++++++++++++++++ + 3 files changed, 59 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -2,6 +2,7 @@ + + dtbo-$(CONFIG_ARCH_BCM2835) += \ + adau1977-adc.dtbo \ ++ adau7002-simple.dtbo \ + ads1015.dtbo \ + ads7846.dtbo \ + akkordion-iqdacplus.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -168,6 +168,12 @@ Load: dtoverlay=adau1977-adc + Params: + + ++Name: adau7002-simple ++Info: Overlay for the activation of ADAU7002 stereo PDM to I2S converter. ++Load: dtoverlay=adau7002-simple,= ++Params: card-name Override the default, "adau7002", card name. ++ ++ + Name: ads1015 + Info: Overlay for activation of Texas Instruments ADS1015 ADC over I2C + Load: dtoverlay=ads1015,= +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts +@@ -0,0 +1,52 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target-path = "/"; ++ __overlay__ { ++ adau7002_codec: adau7002-codec { ++ #sound-dai-cells = <0>; ++ compatible = "adi,adau7002"; ++/* IOVDD-supply = <&supply>;*/ ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&sound>; ++ sound_overlay: __overlay__ { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,name = "adau7002"; ++ simple-audio-card,bitclock-slave = <&dailink0_slave>; ++ simple-audio-card,frame-slave = <&dailink0_slave>; ++ simple-audio-card,widgets = ++ "Microphone", "Microphone Jack"; ++ simple-audio-card,routing = ++ "PDM_DAT", "Microphone Jack"; ++ status = "okay"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s>; ++ }; ++ dailink0_slave: simple-audio-card,codec { ++ sound-dai = <&adau7002_codec>; ++ }; ++ }; ++ }; ++ ++ ++ __overrides__ { ++ card-name = <&sound_overlay>,"simple-audio-card,name"; ++ }; ++}; diff --git a/target/linux/brcm2708/patches-4.9/0137-ARM64-Enable-DWC_OTG-Driver-In-ARM64-Build-Config-bc.patch b/target/linux/brcm2708/patches-4.9/0137-ARM64-Enable-DWC_OTG-Driver-In-ARM64-Build-Config-bc.patch deleted file mode 100644 index 4850c3ed87..0000000000 --- a/target/linux/brcm2708/patches-4.9/0137-ARM64-Enable-DWC_OTG-Driver-In-ARM64-Build-Config-bc.patch +++ /dev/null @@ -1,21 +0,0 @@ -From b0a66d71d5efa5ab172a2e561ef76f510f80b305 Mon Sep 17 00:00:00 2001 -From: Michael Zoran -Date: Sat, 14 Jan 2017 21:45:03 -0800 -Subject: [PATCH] ARM64: Enable DWC_OTG Driver In ARM64 Build - Config(bcmrpi3_defconfig) - -Signed-off-by: Michael Zoran ---- - arch/arm64/configs/bcmrpi3_defconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm64/configs/bcmrpi3_defconfig -+++ b/arch/arm64/configs/bcmrpi3_defconfig -@@ -932,6 +932,7 @@ CONFIG_USB_HIDDEV=y - CONFIG_USB=y - CONFIG_USB_ANNOUNCE_NEW_DEVICES=y - CONFIG_USB_MON=m -+CONFIG_USB_DWCOTG=y - CONFIG_USB_PRINTER=m - CONFIG_USB_STORAGE=y - CONFIG_USB_STORAGE_REALTEK=m diff --git a/target/linux/brcm2708/patches-4.9/0137-config-Add-SND_SOC_ADAU7002-codec-module.patch b/target/linux/brcm2708/patches-4.9/0137-config-Add-SND_SOC_ADAU7002-codec-module.patch new file mode 100644 index 0000000000..e4ef715fb3 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0137-config-Add-SND_SOC_ADAU7002-codec-module.patch @@ -0,0 +1,33 @@ +From 30db626576fa53cb6a0a27311baed4dd5c296c38 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 25 Jan 2017 21:17:23 +0000 +Subject: [PATCH] config: Add SND_SOC_ADAU7002 codec module + +As there is now an overlay requiring it, build the codec module. + +Signed-off-by: Phil Elwell +--- + arch/arm/configs/bcm2709_defconfig | 1 + + arch/arm/configs/bcmrpi_defconfig | 1 + + 2 files changed, 2 insertions(+) + +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -884,6 +884,7 @@ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m + CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m + CONFIG_SND_PISOUND=m + CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_ADAU7002=m + CONFIG_SND_SOC_AK4554=m + CONFIG_SND_SOC_WM8804_I2C=m + CONFIG_SND_SIMPLE_CARD=m +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -878,6 +878,7 @@ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m + CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m + CONFIG_SND_PISOUND=m + CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_ADAU7002=m + CONFIG_SND_SOC_AK4554=m + CONFIG_SND_SOC_WM8804_I2C=m + CONFIG_SND_SIMPLE_CARD=m diff --git a/target/linux/brcm2708/patches-4.9/0138-ARM64-Use-dwc_otg-driver-by-default-for-USB.patch b/target/linux/brcm2708/patches-4.9/0138-ARM64-Use-dwc_otg-driver-by-default-for-USB.patch deleted file mode 100644 index 05170990f7..0000000000 --- a/target/linux/brcm2708/patches-4.9/0138-ARM64-Use-dwc_otg-driver-by-default-for-USB.patch +++ /dev/null @@ -1,26 +0,0 @@ -From a81b40b75f5ae0feafcbc667394494e287cfe218 Mon Sep 17 00:00:00 2001 -From: Michael Zoran -Date: Sat, 14 Jan 2017 21:46:04 -0800 -Subject: [PATCH] ARM64: Use dwc_otg driver by default for USB. - -If it breaks on anybody, they can use the standard device tree -overlays to switch back to the dwc2 driver. - -Signed-off-by: Michael Zoran ---- - arch/arm/boot/dts/bcm2710.dtsi | 7 ------- - 1 file changed, 7 deletions(-) - ---- a/arch/arm/boot/dts/bcm2710.dtsi -+++ b/arch/arm/boot/dts/bcm2710.dtsi -@@ -146,10 +146,3 @@ - interrupts = <8>; - }; - --#ifdef RPI364 --&usb { -- compatible = "brcm,bcm2835-usb"; -- reg = <0x7e980000 0x10000>; -- interrupts = <1 9>; --}; --#endif diff --git a/target/linux/brcm2708/patches-4.9/0138-Add-overlay-for-mcp3008-adc-1818.patch b/target/linux/brcm2708/patches-4.9/0138-Add-overlay-for-mcp3008-adc-1818.patch new file mode 100644 index 0000000000..560dc6c854 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0138-Add-overlay-for-mcp3008-adc-1818.patch @@ -0,0 +1,281 @@ +From 33800ba2a14ff23db96fe5ea6e421a731f60c52b Mon Sep 17 00:00:00 2001 +From: Scott Ellis +Date: Fri, 27 Jan 2017 06:42:42 -0500 +Subject: [PATCH] Add overlay for mcp3008 adc (#1818) + +Some example usage: + +SPI0.0 +dtparam=spi=on +dtoverlay=mcp3008:spi0-0-present + +SPI0.1 +dtparam=spi=on +dtoverlay=mcp3008:spi0-1-present + +SPI0.0 and SPI0.1 +dtparam=spi=on +dtoverlay=mcp3008:spi0-0-present,spi0-1-present + +SPI1.0 +dtparam=spi=on +dtoverlay=spi1-1cs +dtoverlay=mcp3008:spi1-0-present + +SPI1.2 +dtparam=spi=on +dtoverlay=spi1-1cs:cs0_pin=16 +dtoverlay=mcp3008:spi1-0-present + +SPI1.0 and SPI1.1 +dtoverlay=spi1-2cs +dtoverlay=mcp3008:spi1-0-present,spi1-1-present + +Changing the speed + +SPI0.0 +dtparam=spi=on +dtoverlay=mcp3008:spi0-0-present,spi0-0-speed=2000000 +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 9 ++ + arch/arm/boot/dts/overlays/mcp3008-overlay.dts | 205 +++++++++++++++++++++++++ + 3 files changed, 215 insertions(+) + create mode 100755 arch/arm/boot/dts/overlays/mcp3008-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -47,6 +47,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + mcp23s17.dtbo \ + mcp2515-can0.dtbo \ + mcp2515-can1.dtbo \ ++ mcp3008.dtbo \ + midi-uart0.dtbo \ + mmc.dtbo \ + mz61581.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -742,6 +742,15 @@ Params: oscillator Clock fr + interrupt GPIO for interrupt signal + + ++Name: mcp3008 ++Info: Configures MCP3008 A/D converters ++ For devices on spi1 or spi2, the interfaces should be enabled ++ with one of the spi1-1/2/3cs and/or spi2-1/2/3cs overlays. ++Load: dtoverlay=mcp3008,[=] ++Params: spi--present boolean, configure device at spi, cs ++ spi--speed integer, set the spi bus speed for this device ++ ++ + Name: midi-uart0 + Info: Configures UART0 (ttyAMA0) so that a requested 38.4kbaud actually gets + 31.25kbaud, the frequency required for MIDI +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/mcp3008-overlay.dts +@@ -0,0 +1,205 @@ ++/* ++ * Device tree overlay for Microchip mcp3008 10-Bit A/D Converters ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spidev0>; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spidev1>; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "spi1/spidev@0"; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@3 { ++ target-path = "spi1/spidev@1"; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@4 { ++ target-path = "spi1/spidev@2"; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@5 { ++ target-path = "spi2/spidev@0"; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@6 { ++ target-path = "spi2/spidev@1"; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@7 { ++ target-path = "spi2/spidev@2"; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@8 { ++ target = <&spi0>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_00: mcp3008@0 { ++ compatible = "mcp3008"; ++ reg = <0>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ fragment@9 { ++ target = <&spi0>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_01: mcp3008@1 { ++ compatible = "mcp3008"; ++ reg = <1>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ fragment@10 { ++ target = <&spi1>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_10: mcp3008@0 { ++ compatible = "mcp3008"; ++ reg = <0>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ fragment@11 { ++ target = <&spi1>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_11: mcp3008@1 { ++ compatible = "mcp3008"; ++ reg = <1>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ fragment@12 { ++ target = <&spi1>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_12: mcp3008@2 { ++ compatible = "mcp3008"; ++ reg = <2>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ fragment@13 { ++ target = <&spi2>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_20: mcp3008@0 { ++ compatible = "mcp3008"; ++ reg = <0>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ fragment@14 { ++ target = <&spi2>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_21: mcp3008@1 { ++ compatible = "mcp3008"; ++ reg = <1>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ fragment@15 { ++ target = <&spi2>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_22: mcp3008@2 { ++ compatible = "mcp3008"; ++ reg = <2>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ spi0-0-present = <0>, "+0+8"; ++ spi0-1-present = <0>, "+1+9"; ++ spi1-0-present = <0>, "+2+10"; ++ spi1-1-present = <0>, "+3+11"; ++ spi1-2-present = <0>, "+4+12"; ++ spi2-0-present = <0>, "+5+13"; ++ spi2-1-present = <0>, "+6+14"; ++ spi2-2-present = <0>, "+7+15"; ++ spi0-0-speed = <&mcp3008_00>, "spi-max-frequency:0"; ++ spi0-1-speed = <&mcp3008_01>, "spi-max-frequency:0"; ++ spi1-0-speed = <&mcp3008_10>, "spi-max-frequency:0"; ++ spi1-1-speed = <&mcp3008_11>, "spi-max-frequency:0"; ++ spi1-2-speed = <&mcp3008_12>, "spi-max-frequency:0"; ++ spi2-0-speed = <&mcp3008_20>, "spi-max-frequency:0"; ++ spi2-1-speed = <&mcp3008_21>, "spi-max-frequency:0"; ++ spi2-2-speed = <&mcp3008_22>, "spi-max-frequency:0"; ++ }; ++}; diff --git a/target/linux/brcm2708/patches-4.9/0139-BCM270X_DT-Add-reference-to-audio_pins-to-CM-dtb.patch b/target/linux/brcm2708/patches-4.9/0139-BCM270X_DT-Add-reference-to-audio_pins-to-CM-dtb.patch deleted file mode 100644 index ed707a1cac..0000000000 --- a/target/linux/brcm2708/patches-4.9/0139-BCM270X_DT-Add-reference-to-audio_pins-to-CM-dtb.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 719ed1f8a1f93b2c9d855392a69493da107ae703 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 23 Jan 2017 17:36:50 +0000 -Subject: [PATCH] BCM270X_DT: Add reference to audio_pins to CM dtb - -The CM1 dtb contains an empty audio_pins node, but no reference to it. -Adding the usual pinctrl reference from the audio node enables the -audremap overlay (and others) to easily turn on audio. - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/bcm2708-rpi-cm.dts | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -@@ -85,6 +85,11 @@ - pinctrl-0 = <&i2s_pins>; - }; - -+&audio { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&audio_pins>; -+}; -+ - &hdmi { - hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; - }; diff --git a/target/linux/brcm2708/patches-4.9/0139-usb-dwc2-Avoid-suspending-if-we-re-in-gadget-mode-18.patch b/target/linux/brcm2708/patches-4.9/0139-usb-dwc2-Avoid-suspending-if-we-re-in-gadget-mode-18.patch new file mode 100644 index 0000000000..1ed31c2d2e --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0139-usb-dwc2-Avoid-suspending-if-we-re-in-gadget-mode-18.patch @@ -0,0 +1,51 @@ +From 2ca9749f5b4326dad52756eaf5e7865504b4d374 Mon Sep 17 00:00:00 2001 +From: ED6E0F17 +Date: Fri, 3 Feb 2017 14:52:42 +0000 +Subject: [PATCH] usb: dwc2: Avoid suspending if we're in gadget mode (#1825) + +I've found when booting HiKey with the usb gadget cable attached +if I then try to connect via adb, I get an infinite spew of: + +dwc2 f72c0000.usb: dwc2_hsotg_ep_sethalt(ep ffffffc0790ecb18 ep1out, 0) +dwc2 f72c0000.usb: dwc2_hsotg_ep_sethalt(ep ffffffc0790eca18 ep1in, 0) + +It seems that the usb autosuspend is suspending the bus shortly +after bootup when the gadget cable is attached. So when adbd +then tries to use the device, it doesn't work and it then tries +to restart it over and over via the ep_sethalt calls (via +FUNCTIONFS_CLEAR_HALT ioctl). + +Chen Yu suggested this patch to avoid suspending if we're +in device mode, and it avoids the problem. + +Cc: Wei Xu +Cc: Guodong Xu +Cc: Amit Pundir +Cc: Rob Herring +Cc: John Youn +Cc: Douglas Anderson +Cc: Chen Yu +Cc: Kishon Vijay Abraham I +Cc: Felipe Balbi +Cc: Greg Kroah-Hartman +Cc: linux-usb@vger.kernel.org +Suggested-by: Chen Yu +Signed-off-by: John Stultz +Signed-off-by: John Youn +Signed-off-by: Felipe Balbi +--- + drivers/usb/dwc2/hcd.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/dwc2/hcd.c ++++ b/drivers/usb/dwc2/hcd.c +@@ -4365,6 +4365,9 @@ static int _dwc2_hcd_suspend(struct usb_ + if (!HCD_HW_ACCESSIBLE(hcd)) + goto unlock; + ++ if (hsotg->op_state == OTG_STATE_B_PERIPHERAL) ++ goto unlock; ++ + if (!hsotg->core_params->hibernation) + goto skip_power_saving; + diff --git a/target/linux/brcm2708/patches-4.9/0140-config-Add-additional-network-scheduling-modules.patch b/target/linux/brcm2708/patches-4.9/0140-config-Add-additional-network-scheduling-modules.patch deleted file mode 100644 index 91a00193c8..0000000000 --- a/target/linux/brcm2708/patches-4.9/0140-config-Add-additional-network-scheduling-modules.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 6a4bb2c83c31f2d35397469454c3a54fbc32fce7 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 25 Jan 2017 11:30:38 +0000 -Subject: [PATCH] config: Add additional network scheduling modules - ---- - arch/arm/configs/bcm2709_defconfig | 4 ++++ - arch/arm/configs/bcmrpi_defconfig | 4 ++++ - 2 files changed, 8 insertions(+) - ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -296,6 +296,7 @@ CONFIG_NET_SCHED=y - CONFIG_NET_SCH_CBQ=m - CONFIG_NET_SCH_HTB=m - CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_ATM=m - CONFIG_NET_SCH_PRIO=m - CONFIG_NET_SCH_MULTIQ=m - CONFIG_NET_SCH_RED=m -@@ -312,6 +313,9 @@ CONFIG_NET_SCH_CHOKE=m - CONFIG_NET_SCH_QFQ=m - CONFIG_NET_SCH_CODEL=m - CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_FQ=m -+CONFIG_NET_SCH_HHF=m -+CONFIG_NET_SCH_PIE=m - CONFIG_NET_SCH_INGRESS=m - CONFIG_NET_SCH_PLUG=m - CONFIG_NET_CLS_BASIC=m ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -292,6 +292,7 @@ CONFIG_NET_SCHED=y - CONFIG_NET_SCH_CBQ=m - CONFIG_NET_SCH_HTB=m - CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_ATM=m - CONFIG_NET_SCH_PRIO=m - CONFIG_NET_SCH_MULTIQ=m - CONFIG_NET_SCH_RED=m -@@ -308,6 +309,9 @@ CONFIG_NET_SCH_CHOKE=m - CONFIG_NET_SCH_QFQ=m - CONFIG_NET_SCH_CODEL=m - CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_FQ=m -+CONFIG_NET_SCH_HHF=m -+CONFIG_NET_SCH_PIE=m - CONFIG_NET_SCH_INGRESS=m - CONFIG_NET_SCH_PLUG=m - CONFIG_NET_CLS_BASIC=m diff --git a/target/linux/brcm2708/patches-4.9/0140-gpio_mem-Remove-unnecessary-dev_info-output-1830.patch b/target/linux/brcm2708/patches-4.9/0140-gpio_mem-Remove-unnecessary-dev_info-output-1830.patch new file mode 100644 index 0000000000..8c2d162ccd --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0140-gpio_mem-Remove-unnecessary-dev_info-output-1830.patch @@ -0,0 +1,22 @@ +From 5ff260778264ec512ea879cea455c86d515cc6ba Mon Sep 17 00:00:00 2001 +From: JamesH65 +Date: Mon, 6 Feb 2017 15:24:47 +0000 +Subject: [PATCH] gpio_mem: Remove unnecessary dev_info output (#1830) + +The open function was spamming syslog every time +called, so have removed call completely. +--- + drivers/char/broadcom/bcm2835-gpiomem.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/char/broadcom/bcm2835-gpiomem.c ++++ b/drivers/char/broadcom/bcm2835-gpiomem.c +@@ -76,8 +76,6 @@ static int bcm2835_gpiomem_open(struct i + int dev = iminor(inode); + int ret = 0; + +- dev_info(inst->dev, "gpiomem device opened."); +- + if (dev != DEVICE_MINOR) { + dev_err(inst->dev, "Unknown minor device: %d", dev); + ret = -ENXIO; diff --git a/target/linux/brcm2708/patches-4.9/0141-ASoC-A-simple-card-overlay-for-ADAU7002.patch b/target/linux/brcm2708/patches-4.9/0141-ASoC-A-simple-card-overlay-for-ADAU7002.patch deleted file mode 100644 index 99e9414cc3..0000000000 --- a/target/linux/brcm2708/patches-4.9/0141-ASoC-A-simple-card-overlay-for-ADAU7002.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 05f8935c02d5f598055afc773d5bee2f2d91dff2 Mon Sep 17 00:00:00 2001 -From: chris johnson -Date: Sun, 22 Jan 2017 03:27:31 +0000 -Subject: [PATCH] ASoC: A simple-card overlay for ADAU7002 - -Usage: `dtoverlay=adau7002-simple` ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 +++ - .../boot/dts/overlays/adau7002-simple-overlay.dts | 52 ++++++++++++++++++++++ - 3 files changed, 59 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts - ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -2,6 +2,7 @@ - - dtbo-$(CONFIG_ARCH_BCM2835) += \ - adau1977-adc.dtbo \ -+ adau7002-simple.dtbo \ - ads1015.dtbo \ - ads7846.dtbo \ - akkordion-iqdacplus.dtbo \ ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -168,6 +168,12 @@ Load: dtoverlay=adau1977-adc - Params: - - -+Name: adau7002-simple -+Info: Overlay for the activation of ADAU7002 stereo PDM to I2S converter. -+Load: dtoverlay=adau7002-simple,= -+Params: card-name Override the default, "adau7002", card name. -+ -+ - Name: ads1015 - Info: Overlay for activation of Texas Instruments ADS1015 ADC over I2C - Load: dtoverlay=ads1015,= ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts -@@ -0,0 +1,52 @@ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target-path = "/"; -+ __overlay__ { -+ adau7002_codec: adau7002-codec { -+ #sound-dai-cells = <0>; -+ compatible = "adi,adau7002"; -+/* IOVDD-supply = <&supply>;*/ -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&sound>; -+ sound_overlay: __overlay__ { -+ compatible = "simple-audio-card"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,name = "adau7002"; -+ simple-audio-card,bitclock-slave = <&dailink0_slave>; -+ simple-audio-card,frame-slave = <&dailink0_slave>; -+ simple-audio-card,widgets = -+ "Microphone", "Microphone Jack"; -+ simple-audio-card,routing = -+ "PDM_DAT", "Microphone Jack"; -+ status = "okay"; -+ simple-audio-card,cpu { -+ sound-dai = <&i2s>; -+ }; -+ dailink0_slave: simple-audio-card,codec { -+ sound-dai = <&adau7002_codec>; -+ }; -+ }; -+ }; -+ -+ -+ __overrides__ { -+ card-name = <&sound_overlay>,"simple-audio-card,name"; -+ }; -+}; diff --git a/target/linux/brcm2708/patches-4.9/0141-config-Enable-regulator-support.patch b/target/linux/brcm2708/patches-4.9/0141-config-Enable-regulator-support.patch new file mode 100644 index 0000000000..bcd766f4d3 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0141-config-Enable-regulator-support.patch @@ -0,0 +1,33 @@ +From e36583656552b7827a1b9d513ec39e95efa7ce8d Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 22 Jan 2017 12:49:36 +0100 +Subject: [PATCH] config: Enable regulator support + +Signed-off-by: Matthias Reichl +--- + arch/arm/configs/bcm2709_defconfig | 2 ++ + arch/arm/configs/bcmrpi_defconfig | 2 ++ + 2 files changed, 4 insertions(+) + +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -664,6 +664,8 @@ CONFIG_STMPE_SPI=y + CONFIG_MFD_ARIZONA_I2C=m + CONFIG_MFD_ARIZONA_SPI=m + CONFIG_MFD_WM5102=y ++CONFIG_REGULATOR=y ++CONFIG_REGULATOR_FIXED_VOLTAGE=m + CONFIG_MEDIA_SUPPORT=m + CONFIG_MEDIA_CAMERA_SUPPORT=y + CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -658,6 +658,8 @@ CONFIG_STMPE_SPI=y + CONFIG_MFD_ARIZONA_I2C=m + CONFIG_MFD_ARIZONA_SPI=m + CONFIG_MFD_WM5102=y ++CONFIG_REGULATOR=y ++CONFIG_REGULATOR_FIXED_VOLTAGE=m + CONFIG_MEDIA_SUPPORT=m + CONFIG_MEDIA_CAMERA_SUPPORT=y + CONFIG_MEDIA_ANALOG_TV_SUPPORT=y diff --git a/target/linux/brcm2708/patches-4.9/0142-BCM270x-DT-expose-3.3V-and-5V-system-rails.patch b/target/linux/brcm2708/patches-4.9/0142-BCM270x-DT-expose-3.3V-and-5V-system-rails.patch new file mode 100644 index 0000000000..062e6e0256 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0142-BCM270x-DT-expose-3.3V-and-5V-system-rails.patch @@ -0,0 +1,33 @@ +From 3e2cb84235e904f0c127d34705852ba7893ec9ae Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 22 Jan 2017 12:49:36 +0100 +Subject: [PATCH] BCM270x DT: expose 3.3V and 5V system rails + +Signed-off-by: Matthias Reichl +--- + arch/arm/boot/dts/bcm270x.dtsi | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/arch/arm/boot/dts/bcm270x.dtsi ++++ b/arch/arm/boot/dts/bcm270x.dtsi +@@ -138,4 +138,20 @@ + status = "disabled"; + }; + }; ++ ++ vdd_5v0_reg: fixedregulator_5v0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "5v0"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ }; ++ ++ vdd_3v3_reg: fixedregulator_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ }; + }; diff --git a/target/linux/brcm2708/patches-4.9/0142-config-Add-SND_SOC_ADAU7002-codec-module.patch b/target/linux/brcm2708/patches-4.9/0142-config-Add-SND_SOC_ADAU7002-codec-module.patch deleted file mode 100644 index ab642957bb..0000000000 --- a/target/linux/brcm2708/patches-4.9/0142-config-Add-SND_SOC_ADAU7002-codec-module.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 86a9b1e76dd131156f3fa0436ee6bac7bd51bd90 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 25 Jan 2017 21:17:23 +0000 -Subject: [PATCH] config: Add SND_SOC_ADAU7002 codec module - -As there is now an overlay requiring it, build the codec module. - -Signed-off-by: Phil Elwell ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -884,6 +884,7 @@ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m - CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_ADAU7002=m - CONFIG_SND_SOC_AK4554=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -878,6 +878,7 @@ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m - CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_ADAU7002=m - CONFIG_SND_SOC_AK4554=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m diff --git a/target/linux/brcm2708/patches-4.9/0143-Add-overlay-for-mcp3008-adc-1818.patch b/target/linux/brcm2708/patches-4.9/0143-Add-overlay-for-mcp3008-adc-1818.patch deleted file mode 100644 index 57b3605c55..0000000000 --- a/target/linux/brcm2708/patches-4.9/0143-Add-overlay-for-mcp3008-adc-1818.patch +++ /dev/null @@ -1,281 +0,0 @@ -From ad0138f3a91bebc14be78809d738c302f0ac311d Mon Sep 17 00:00:00 2001 -From: Scott Ellis -Date: Fri, 27 Jan 2017 06:42:42 -0500 -Subject: [PATCH] Add overlay for mcp3008 adc (#1818) - -Some example usage: - -SPI0.0 -dtparam=spi=on -dtoverlay=mcp3008:spi0-0-present - -SPI0.1 -dtparam=spi=on -dtoverlay=mcp3008:spi0-1-present - -SPI0.0 and SPI0.1 -dtparam=spi=on -dtoverlay=mcp3008:spi0-0-present,spi0-1-present - -SPI1.0 -dtparam=spi=on -dtoverlay=spi1-1cs -dtoverlay=mcp3008:spi1-0-present - -SPI1.2 -dtparam=spi=on -dtoverlay=spi1-1cs:cs0_pin=16 -dtoverlay=mcp3008:spi1-0-present - -SPI1.0 and SPI1.1 -dtoverlay=spi1-2cs -dtoverlay=mcp3008:spi1-0-present,spi1-1-present - -Changing the speed - -SPI0.0 -dtparam=spi=on -dtoverlay=mcp3008:spi0-0-present,spi0-0-speed=2000000 ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 9 ++ - arch/arm/boot/dts/overlays/mcp3008-overlay.dts | 205 +++++++++++++++++++++++++ - 3 files changed, 215 insertions(+) - create mode 100755 arch/arm/boot/dts/overlays/mcp3008-overlay.dts - ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -47,6 +47,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - mcp23s17.dtbo \ - mcp2515-can0.dtbo \ - mcp2515-can1.dtbo \ -+ mcp3008.dtbo \ - midi-uart0.dtbo \ - mmc.dtbo \ - mz61581.dtbo \ ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -742,6 +742,15 @@ Params: oscillator Clock fr - interrupt GPIO for interrupt signal - - -+Name: mcp3008 -+Info: Configures MCP3008 A/D converters -+ For devices on spi1 or spi2, the interfaces should be enabled -+ with one of the spi1-1/2/3cs and/or spi2-1/2/3cs overlays. -+Load: dtoverlay=mcp3008,[=] -+Params: spi--present boolean, configure device at spi, cs -+ spi--speed integer, set the spi bus speed for this device -+ -+ - Name: midi-uart0 - Info: Configures UART0 (ttyAMA0) so that a requested 38.4kbaud actually gets - 31.25kbaud, the frequency required for MIDI ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/mcp3008-overlay.dts -@@ -0,0 +1,205 @@ -+/* -+ * Device tree overlay for Microchip mcp3008 10-Bit A/D Converters -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spidev0>; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&spidev1>; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "spi1/spidev@0"; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path = "spi1/spidev@1"; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@4 { -+ target-path = "spi1/spidev@2"; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@5 { -+ target-path = "spi2/spidev@0"; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@6 { -+ target-path = "spi2/spidev@1"; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@7 { -+ target-path = "spi2/spidev@2"; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@8 { -+ target = <&spi0>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_00: mcp3008@0 { -+ compatible = "mcp3008"; -+ reg = <0>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ fragment@9 { -+ target = <&spi0>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_01: mcp3008@1 { -+ compatible = "mcp3008"; -+ reg = <1>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ fragment@10 { -+ target = <&spi1>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_10: mcp3008@0 { -+ compatible = "mcp3008"; -+ reg = <0>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ fragment@11 { -+ target = <&spi1>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_11: mcp3008@1 { -+ compatible = "mcp3008"; -+ reg = <1>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ fragment@12 { -+ target = <&spi1>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_12: mcp3008@2 { -+ compatible = "mcp3008"; -+ reg = <2>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ fragment@13 { -+ target = <&spi2>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_20: mcp3008@0 { -+ compatible = "mcp3008"; -+ reg = <0>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ fragment@14 { -+ target = <&spi2>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_21: mcp3008@1 { -+ compatible = "mcp3008"; -+ reg = <1>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ fragment@15 { -+ target = <&spi2>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_22: mcp3008@2 { -+ compatible = "mcp3008"; -+ reg = <2>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ spi0-0-present = <0>, "+0+8"; -+ spi0-1-present = <0>, "+1+9"; -+ spi1-0-present = <0>, "+2+10"; -+ spi1-1-present = <0>, "+3+11"; -+ spi1-2-present = <0>, "+4+12"; -+ spi2-0-present = <0>, "+5+13"; -+ spi2-1-present = <0>, "+6+14"; -+ spi2-2-present = <0>, "+7+15"; -+ spi0-0-speed = <&mcp3008_00>, "spi-max-frequency:0"; -+ spi0-1-speed = <&mcp3008_01>, "spi-max-frequency:0"; -+ spi1-0-speed = <&mcp3008_10>, "spi-max-frequency:0"; -+ spi1-1-speed = <&mcp3008_11>, "spi-max-frequency:0"; -+ spi1-2-speed = <&mcp3008_12>, "spi-max-frequency:0"; -+ spi2-0-speed = <&mcp3008_20>, "spi-max-frequency:0"; -+ spi2-1-speed = <&mcp3008_21>, "spi-max-frequency:0"; -+ spi2-2-speed = <&mcp3008_22>, "spi-max-frequency:0"; -+ }; -+}; diff --git a/target/linux/brcm2708/patches-4.9/0143-BCM270x-DT-Consolidate-audio-card-overlays.patch b/target/linux/brcm2708/patches-4.9/0143-BCM270x-DT-Consolidate-audio-card-overlays.patch new file mode 100644 index 0000000000..4c123b414c --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0143-BCM270x-DT-Consolidate-audio-card-overlays.patch @@ -0,0 +1,273 @@ +From f134380c19eb38bc276d6d86fa575821c3493c60 Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 22 Jan 2017 12:49:36 +0100 +Subject: [PATCH] BCM270x DT: Consolidate audio card overlays + +Reference 3.3V / 5V system rails instead of instantiating local +regulators. + +Add missing power supply properties for codecs where these are +required according to the DT bindings docs. + +Signed-off-by: Matthias Reichl +--- + .../arm/boot/dts/overlays/adau1977-adc-overlay.dts | 19 ++-------- + .../dts/overlays/akkordion-iqdacplus-overlay.dts | 3 ++ + .../dts/overlays/hifiberry-dacplus-overlay.dts | 3 ++ + .../boot/dts/overlays/hifiberry-digi-overlay.dts | 2 + + .../dts/overlays/hifiberry-digi-pro-overlay.dts | 2 + + arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts | 3 ++ + .../boot/dts/overlays/iqaudio-dacplus-overlay.dts | 3 ++ + .../overlays/iqaudio-digi-wm8804-audio-overlay.dts | 4 +- + .../arm/boot/dts/overlays/justboom-dac-overlay.dts | 3 ++ + .../boot/dts/overlays/justboom-digi-overlay.dts | 2 + + arch/arm/boot/dts/overlays/raspidac3-overlay.dts | 4 ++ + .../overlays/rra-digidac1-wm8741-audio-overlay.dts | 44 +++------------------- + 12 files changed, 36 insertions(+), 56 deletions(-) + +--- a/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts ++++ b/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts +@@ -6,19 +6,6 @@ + compatible = "brcm,bcm2708"; + + fragment@0 { +- target = <&soc>; +- +- __overlay__ { +- codec_supply: fixedregulator@0 { +- compatible = "regulator-fixed"; +- regulator-name = "AVDD"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- }; +- }; +- }; +- +- fragment@1 { + target = <&i2c>; + + __overlay__ { +@@ -30,19 +17,19 @@ + compatible = "adi,adau1977"; + reg = <0x11>; + reset-gpios = <&gpio 5 0>; +- AVDD-supply = <&codec_supply>; ++ AVDD-supply = <&vdd_3v3_reg>; + }; + }; + }; + +- fragment@2 { ++ fragment@1 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + +- fragment@3 { ++ fragment@2 { + target = <&sound>; + __overlay__ { + compatible = "adi,adau1977-adc"; +--- a/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts ++++ b/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts +@@ -23,6 +23,9 @@ + #sound-dai-cells = <0>; + compatible = "ti,pcm5122"; + reg = <0x4c>; ++ AVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ CPVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts +@@ -34,6 +34,9 @@ + compatible = "ti,pcm5122"; + reg = <0x4d>; + clocks = <&dacpro_osc>; ++ AVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ CPVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts +@@ -23,6 +23,8 @@ + #sound-dai-cells = <0>; + compatible = "wlf,wm8804"; + reg = <0x3b>; ++ PVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts +@@ -23,6 +23,8 @@ + #sound-dai-cells = <0>; + compatible = "wlf,wm8804"; + reg = <0x3b>; ++ PVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts +@@ -23,6 +23,9 @@ + #sound-dai-cells = <0>; + compatible = "ti,pcm5122"; + reg = <0x4c>; ++ AVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ CPVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts ++++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts +@@ -23,6 +23,9 @@ + #sound-dai-cells = <0>; + compatible = "ti,pcm5122"; + reg = <0x4c>; ++ AVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ CPVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts +@@ -24,8 +24,8 @@ + compatible = "wlf,wm8804"; + reg = <0x3b>; + status = "okay"; +- // DVDD-supply = <®_3v3>; +- // PVDD-supply = <®_3v3>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ PVDD-supply = <&vdd_3v3_reg>; + }; + }; + }; +--- a/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts +@@ -23,6 +23,9 @@ + #sound-dai-cells = <0>; + compatible = "ti,pcm5122"; + reg = <0x4d>; ++ AVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ CPVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts ++++ b/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts +@@ -23,6 +23,8 @@ + #sound-dai-cells = <0>; + compatible = "wlf,wm8804"; + reg = <0x3b>; ++ PVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/raspidac3-overlay.dts ++++ b/arch/arm/boot/dts/overlays/raspidac3-overlay.dts +@@ -23,12 +23,16 @@ + #sound-dai-cells = <0>; + compatible = "ti,pcm5122"; + reg = <0x4c>; ++ AVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ CPVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + + tpa6130a2: tpa6130a2@60 { + compatible = "ti,tpa6130a2"; + reg = <0x60>; ++ Vdd-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts +@@ -6,45 +6,13 @@ + compatible = "brcm,bcm2708"; + + fragment@0 { +- target-path = "/"; +- __overlay__ { +- aliases { +- ldo0 = &ldo0; +- ldo1 = &ldo1; +- }; +- }; +- }; +- +- fragment@1 { +- target-path = "/soc"; +- __overlay__ { +- +- ldo1: ldo1 { +- compatible = "regulator-fixed"; +- regulator-name = "DC_5V"; +- regulator-min-microvolt = <5000000>; +- regulator-max-microvolt = <5000000>; +- regulator-always-on; +- }; +- +- ldo0: ldo0 { +- compatible = "regulator-fixed"; +- regulator-name = "DC_3V3"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-always-on; +- }; +- }; +- }; +- +- fragment@2 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + +- fragment@3 { ++ fragment@1 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; +@@ -56,21 +24,21 @@ + compatible = "wlf,wm8804"; + reg = <0x3b>; + status = "okay"; +- PVDD-supply = <&ldo0>; +- DVDD-supply = <&ldo0>; ++ PVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; + }; + + wm8742: wm8741@1a { + compatible = "wlf,wm8741"; + reg = <0x1a>; + status = "okay"; +- AVDD-supply = <&ldo1>; +- DVDD-supply = <&ldo0>; ++ AVDD-supply = <&vdd_5v0_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; + }; + }; + }; + +- fragment@4 { ++ fragment@2 { + target = <&sound>; + __overlay__ { + compatible = "rra,digidac1-soundcard"; diff --git a/target/linux/brcm2708/patches-4.9/0144-ASoC-Add-driver-for-Cirrus-Logic-Audio-Card.patch b/target/linux/brcm2708/patches-4.9/0144-ASoC-Add-driver-for-Cirrus-Logic-Audio-Card.patch new file mode 100644 index 0000000000..863d107541 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0144-ASoC-Add-driver-for-Cirrus-Logic-Audio-Card.patch @@ -0,0 +1,1238 @@ +From 01c84e09a331a3b4c29c1cd5ce364c91577c7cea Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 22 Jan 2017 12:49:37 +0100 +Subject: [PATCH] ASoC: Add driver for Cirrus Logic Audio Card + +Note: due to problems with deferred probing of regulators +the following softdep should be added to a modprobe.d file + +softdep arizona-spi pre: arizona-ldo1 + +Signed-off-by: Matthias Reichl +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 6 + + .../dts/overlays/rpi-cirrus-wm5102-overlay.dts | 146 +++ + sound/soc/bcm/Kconfig | 9 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/rpi-cirrus.c | 1003 ++++++++++++++++++++ + 6 files changed, 1167 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts + create mode 100644 sound/soc/bcm/rpi-cirrus.c + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -68,6 +68,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + qca7000.dtbo \ + raspidac3.dtbo \ + rpi-backlight.dtbo \ ++ rpi-cirrus-wm5102.dtbo \ + rpi-dac.dtbo \ + rpi-display.dtbo \ + rpi-ft5406.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -995,6 +995,12 @@ Load: dtoverlay=rpi-backlight + Params: + + ++Name: rpi-cirrus-wm5102 ++Info: Configures the Cirrus Logic Audio Card ++Load: dtoverlay=rpi-cirrus-wm5102 ++Params: ++ ++ + Name: rpi-dac + Info: Configures the RPi DAC audio card + Load: dtoverlay=rpi-dac +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts +@@ -0,0 +1,146 @@ ++// Definitions for the Cirrus Logic Audio Card ++/dts-v1/; ++/plugin/; ++#include ++#include ++#include ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ wlf_pins: wlf_pins { ++ brcm,pins = <17 22 27 8>; ++ brcm,function = < ++ BCM2835_FSEL_GPIO_OUT ++ BCM2835_FSEL_GPIO_OUT ++ BCM2835_FSEL_GPIO_IN ++ BCM2835_FSEL_GPIO_OUT ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "/"; ++ __overlay__ { ++ rpi_cirrus_reg_1v8: rpi_cirrus_reg_1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "RPi-Cirrus 1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&spi0>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ ++ wm5102@1{ ++ compatible = "wlf,wm5102"; ++ reg = <1>; ++ ++ spi-max-frequency = <500000>; ++ ++ interrupt-parent = <&gpio>; ++ interrupts = <27 8>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ LDOVDD-supply = <&rpi_cirrus_reg_1v8>; ++ AVDD-supply = <&rpi_cirrus_reg_1v8>; ++ DBVDD1-supply = <&rpi_cirrus_reg_1v8>; ++ DBVDD2-supply = <&vdd_3v3_reg>; ++ DBVDD3-supply = <&vdd_3v3_reg>; ++ CPVDD-supply = <&rpi_cirrus_reg_1v8>; ++ SPKVDDL-supply = <&vdd_5v0_reg>; ++ SPKVDDR-supply = <&vdd_5v0_reg>; ++ DCVDD-supply = <&arizona_ldo1>; ++ ++ wlf,reset = <&gpio 17 GPIO_ACTIVE_HIGH>; ++ wlf,ldoena = <&gpio 22 GPIO_ACTIVE_HIGH>; ++ wlf,gpio-defaults = < ++ ARIZONA_GP_DEFAULT ++ ARIZONA_GP_DEFAULT ++ ARIZONA_GP_DEFAULT ++ ARIZONA_GP_DEFAULT ++ ARIZONA_GP_DEFAULT ++ >; ++ wlf,micd-configs = <0 1 0>; ++ wlf,dmic-ref = < ++ ARIZONA_DMIC_MICVDD ++ ARIZONA_DMIC_MICBIAS2 ++ ARIZONA_DMIC_MICVDD ++ ARIZONA_DMIC_MICVDD ++ >; ++ wlf,inmode = < ++ ARIZONA_INMODE_DIFF ++ ARIZONA_INMODE_DMIC ++ ARIZONA_INMODE_SE ++ ARIZONA_INMODE_DIFF ++ >; ++ status = "okay"; ++ ++ arizona_ldo1: ldo1 { ++ regulator-name = "LDO1"; ++ // default constraints as in ++ // arizona-ldo1.c ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&i2c1>; ++ __overlay__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ wm8804@3b { ++ compatible = "wlf,wm8804"; ++ reg = <0x3b>; ++ status = "okay"; ++ PVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ wlf,reset-gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "wlf,rpi-cirrus"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++}; +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -45,6 +45,15 @@ config SND_BCM2708_SOC_HIFIBERRY_AMP + help + Say Y or M if you want to add support for the HifiBerry Amp amplifier board. + ++config SND_BCM2708_SOC_RPI_CIRRUS ++ tristate "Support for Cirrus Logic Audio Card" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_WM5102 ++ select SND_SOC_WM8804 ++ help ++ Say Y or M if you want to add support for the Wolfson and ++ Cirrus Logic audio cards. ++ + config SND_BCM2708_SOC_RPI_DAC + tristate "Support for RPi-DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -16,6 +16,7 @@ snd-soc-hifiberry-dacplus-objs := hifibe + snd-soc-hifiberry-digi-objs := hifiberry_digi.o + snd-soc-justboom-dac-objs := justboom-dac.o + snd-soc-justboom-digi-objs := justboom-digi.o ++snd-soc-rpi-cirrus-objs := rpi-cirrus.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-rpi-proto-objs := rpi-proto.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o +@@ -34,6 +35,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o ++obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +--- /dev/null ++++ b/sound/soc/bcm/rpi-cirrus.c +@@ -0,0 +1,1003 @@ ++/* ++ * ASoC machine driver for Cirrus Logic Audio Card ++ * (with WM5102 and WM8804 codecs) ++ * ++ * Copyright 2015-2017 Matthias Reichl ++ * ++ * Based on rpi-cirrus-sound-pi driver (c) Wolfson / Cirrus Logic Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "../codecs/wm5102.h" ++#include "../codecs/wm8804.h" ++ ++#define WM8804_CLKOUT_HZ 12000000 ++ ++#define RPI_CIRRUS_DEFAULT_RATE 44100 ++#define WM5102_MAX_SYSCLK_1 49152000 /* max sysclk for 4K family */ ++#define WM5102_MAX_SYSCLK_2 45158400 /* max sysclk for 11.025K family */ ++ ++static inline unsigned int calc_sysclk(unsigned int rate) ++{ ++ return (rate % 4000) ? WM5102_MAX_SYSCLK_2 : WM5102_MAX_SYSCLK_1; ++} ++ ++enum { ++ DAI_WM5102 = 0, ++ DAI_WM8804, ++}; ++ ++struct rpi_cirrus_priv { ++ /* mutex for synchronzing FLL1 access with DAPM */ ++ struct mutex lock; ++ unsigned int card_rate; ++ int sync_path_enable; ++ int fll1_freq; /* negative means RefClock in spdif rx case */ ++ ++ /* track hw params/free for substreams */ ++ unsigned int params_set; ++ unsigned int min_rate_idx, max_rate_idx; ++ unsigned char iec958_status[4]; ++}; ++ ++/* helper functions */ ++static inline struct snd_soc_pcm_runtime *get_wm5102_runtime( ++ struct snd_soc_card *card) { ++ return snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM5102].name); ++} ++ ++static inline struct snd_soc_pcm_runtime *get_wm8804_runtime( ++ struct snd_soc_card *card) { ++ return snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM8804].name); ++} ++ ++ ++struct rate_info { ++ unsigned int value; ++ char *text; ++}; ++ ++static struct rate_info min_rates[] = { ++ { 0, "off"}, ++ { 32000, "32kHz"}, ++ { 44100, "44.1kHz"} ++}; ++ ++#define NUM_MIN_RATES ARRAY_SIZE(min_rates) ++ ++static int rpi_cirrus_min_rate_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; ++ uinfo->count = 1; ++ uinfo->value.enumerated.items = NUM_MIN_RATES; ++ ++ if (uinfo->value.enumerated.item >= NUM_MIN_RATES) ++ uinfo->value.enumerated.item = NUM_MIN_RATES - 1; ++ strcpy(uinfo->value.enumerated.name, ++ min_rates[uinfo->value.enumerated.item].text); ++ return 0; ++} ++ ++static int rpi_cirrus_min_rate_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ ++ ucontrol->value.enumerated.item[0] = priv->min_rate_idx; ++ return 0; ++} ++ ++static int rpi_cirrus_min_rate_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ int changed = 0; ++ ++ if (priv->min_rate_idx != ucontrol->value.enumerated.item[0]) { ++ changed = 1; ++ priv->min_rate_idx = ucontrol->value.enumerated.item[0]; ++ } ++ ++ return changed; ++} ++ ++static struct rate_info max_rates[] = { ++ { 0, "off"}, ++ { 48000, "48kHz"}, ++ { 96000, "96kHz"} ++}; ++ ++#define NUM_MAX_RATES ARRAY_SIZE(max_rates) ++ ++static int rpi_cirrus_max_rate_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; ++ uinfo->count = 1; ++ uinfo->value.enumerated.items = NUM_MAX_RATES; ++ if (uinfo->value.enumerated.item >= NUM_MAX_RATES) ++ uinfo->value.enumerated.item = NUM_MAX_RATES - 1; ++ strcpy(uinfo->value.enumerated.name, ++ max_rates[uinfo->value.enumerated.item].text); ++ return 0; ++} ++ ++static int rpi_cirrus_max_rate_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ ++ ucontrol->value.enumerated.item[0] = priv->max_rate_idx; ++ return 0; ++} ++ ++static int rpi_cirrus_max_rate_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ int changed = 0; ++ ++ if (priv->max_rate_idx != ucontrol->value.enumerated.item[0]) { ++ changed = 1; ++ priv->max_rate_idx = ucontrol->value.enumerated.item[0]; ++ } ++ ++ return changed; ++} ++ ++static int rpi_cirrus_spdif_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; ++ uinfo->count = 1; ++ return 0; ++} ++ ++static int rpi_cirrus_spdif_playback_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ int i; ++ ++ for (i = 0; i < 4; i++) ++ ucontrol->value.iec958.status[i] = priv->iec958_status[i]; ++ ++ return 0; ++} ++ ++static int rpi_cirrus_spdif_playback_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ unsigned char *stat = priv->iec958_status; ++ unsigned char *ctrl_stat = ucontrol->value.iec958.status; ++ unsigned int mask; ++ int i, changed = 0; ++ ++ for (i = 0; i < 4; i++) { ++ mask = (i == 3) ? 0x3f : 0xff; ++ if ((ctrl_stat[i] & mask) != (stat[i] & mask)) { ++ changed = 1; ++ stat[i] = ctrl_stat[i] & mask; ++ snd_soc_update_bits(wm8804_codec, ++ WM8804_SPDTX1 + i, mask, stat[i]); ++ } ++ } ++ ++ return changed; ++} ++ ++static int rpi_cirrus_spdif_mask_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ ucontrol->value.iec958.status[0] = 0xff; ++ ucontrol->value.iec958.status[1] = 0xff; ++ ucontrol->value.iec958.status[2] = 0xff; ++ ucontrol->value.iec958.status[3] = 0x3f; ++ ++ return 0; ++} ++ ++static int rpi_cirrus_spdif_capture_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; ++ unsigned int mask; ++ int i; ++ ++ for (i = 0; i < 4; i++) { ++ mask = (i == 3) ? 0x3f : 0xff; ++ ucontrol->value.iec958.status[i] = ++ snd_soc_read(wm8804_codec, WM8804_RXCHAN1 + i) & mask; ++ } ++ ++ return 0; ++} ++ ++#define SPDIF_FLAG_CTRL(desc, reg, bit, invert) \ ++{ \ ++ .access = SNDRV_CTL_ELEM_ACCESS_READ \ ++ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ ++ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) \ ++ desc " Flag", \ ++ .info = snd_ctl_boolean_mono_info, \ ++ .get = rpi_cirrus_spdif_status_flag_get, \ ++ .private_value = \ ++ (bit) | ((reg) << 8) | ((invert) << 16) \ ++} ++ ++static int rpi_cirrus_spdif_status_flag_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; ++ ++ unsigned int bit = kcontrol->private_value & 0xff; ++ unsigned int reg = (kcontrol->private_value >> 8) & 0xff; ++ unsigned int invert = (kcontrol->private_value >> 16) & 0xff; ++ ++ bool flag = snd_soc_read(wm8804_codec, reg) & (1 << bit); ++ ++ ucontrol->value.integer.value[0] = invert ? !flag : flag; ++ ++ return 0; ++} ++ ++static const char * const recovered_frequency_texts[] = { ++ "176.4/192 kHz", ++ "88.2/96 kHz", ++ "44.1/48 kHz", ++ "32 kHz" ++}; ++ ++#define NUM_RECOVERED_FREQUENCIES \ ++ ARRAY_SIZE(recovered_frequency_texts) ++ ++static int rpi_cirrus_recovered_frequency_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; ++ uinfo->count = 1; ++ uinfo->value.enumerated.items = NUM_RECOVERED_FREQUENCIES; ++ if (uinfo->value.enumerated.item >= NUM_RECOVERED_FREQUENCIES) ++ uinfo->value.enumerated.item = NUM_RECOVERED_FREQUENCIES - 1; ++ strcpy(uinfo->value.enumerated.name, ++ recovered_frequency_texts[uinfo->value.enumerated.item]); ++ return 0; ++} ++ ++static int rpi_cirrus_recovered_frequency_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; ++ ++ ucontrol->value.enumerated.item[0] = ++ (snd_soc_read(wm8804_codec, WM8804_SPDSTAT) >> 4) & 0x03; ++ return 0; ++} ++ ++static const struct snd_kcontrol_new rpi_cirrus_controls[] = { ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "Min Sample Rate", ++ .info = rpi_cirrus_min_rate_info, ++ .get = rpi_cirrus_min_rate_get, ++ .put = rpi_cirrus_min_rate_put, ++ }, ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "Max Sample Rate", ++ .info = rpi_cirrus_max_rate_info, ++ .get = rpi_cirrus_max_rate_get, ++ .put = rpi_cirrus_max_rate_put, ++ }, ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), ++ .info = rpi_cirrus_spdif_info, ++ .get = rpi_cirrus_spdif_playback_get, ++ .put = rpi_cirrus_spdif_playback_put, ++ }, ++ { ++ .access = SNDRV_CTL_ELEM_ACCESS_READ ++ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), ++ .info = rpi_cirrus_spdif_info, ++ .get = rpi_cirrus_spdif_capture_get, ++ }, ++ { ++ .access = SNDRV_CTL_ELEM_ACCESS_READ, ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK), ++ .info = rpi_cirrus_spdif_info, ++ .get = rpi_cirrus_spdif_mask_get, ++ }, ++ { ++ .access = SNDRV_CTL_ELEM_ACCESS_READ ++ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) ++ "Recovered Frequency", ++ .info = rpi_cirrus_recovered_frequency_info, ++ .get = rpi_cirrus_recovered_frequency_get, ++ }, ++ SPDIF_FLAG_CTRL("Audio", WM8804_SPDSTAT, 0, 1), ++ SPDIF_FLAG_CTRL("Non-PCM", WM8804_SPDSTAT, 1, 0), ++ SPDIF_FLAG_CTRL("Copyright", WM8804_SPDSTAT, 2, 1), ++ SPDIF_FLAG_CTRL("De-Emphasis", WM8804_SPDSTAT, 3, 0), ++ SPDIF_FLAG_CTRL("Lock", WM8804_SPDSTAT, 6, 1), ++ SPDIF_FLAG_CTRL("Invalid", WM8804_INTSTAT, 1, 0), ++ SPDIF_FLAG_CTRL("TransErr", WM8804_INTSTAT, 3, 0), ++}; ++ ++static const char * const linein_micbias_texts[] = { ++ "off", "on", ++}; ++ ++static SOC_ENUM_SINGLE_VIRT_DECL(linein_micbias_enum, ++ linein_micbias_texts); ++ ++static const struct snd_kcontrol_new linein_micbias_mux = ++ SOC_DAPM_ENUM("Route", linein_micbias_enum); ++ ++static int rpi_cirrus_spdif_rx_enable_event(struct snd_soc_dapm_widget *w, ++ struct snd_kcontrol *kcontrol, int event); ++ ++const struct snd_soc_dapm_widget rpi_cirrus_dapm_widgets[] = { ++ SND_SOC_DAPM_MIC("DMIC", NULL), ++ SND_SOC_DAPM_MIC("Headset Mic", NULL), ++ SND_SOC_DAPM_INPUT("Line Input"), ++ SND_SOC_DAPM_MIC("Line Input with Micbias", NULL), ++ SND_SOC_DAPM_MUX("Line Input Micbias", SND_SOC_NOPM, 0, 0, ++ &linein_micbias_mux), ++ SND_SOC_DAPM_INPUT("dummy SPDIF in"), ++ SND_SOC_DAPM_PGA_E("dummy SPDIFRX", SND_SOC_NOPM, 0, 0, NULL, 0, ++ rpi_cirrus_spdif_rx_enable_event, ++ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), ++ SND_SOC_DAPM_INPUT("Dummy Input"), ++ SND_SOC_DAPM_OUTPUT("Dummy Output"), ++}; ++ ++const struct snd_soc_dapm_route rpi_cirrus_dapm_routes[] = { ++ { "IN1L", NULL, "Headset Mic" }, ++ { "IN1R", NULL, "Headset Mic" }, ++ { "Headset Mic", NULL, "MICBIAS1" }, ++ ++ { "IN2L", NULL, "DMIC" }, ++ { "IN2R", NULL, "DMIC" }, ++ { "DMIC", NULL, "MICBIAS2" }, ++ ++ { "IN3L", NULL, "Line Input Micbias" }, ++ { "IN3R", NULL, "Line Input Micbias" }, ++ ++ { "Line Input Micbias", "off", "Line Input" }, ++ { "Line Input Micbias", "on", "Line Input with Micbias" }, ++ ++ /* Make sure MICVDD is enabled, otherwise we get noise */ ++ { "Line Input", NULL, "MICVDD" }, ++ { "Line Input with Micbias", NULL, "MICBIAS3" }, ++ ++ /* Dummy routes to check whether SPDIF RX is enabled or not */ ++ {"dummy SPDIFRX", NULL, "dummy SPDIF in"}, ++ {"AIFTX", NULL, "dummy SPDIFRX"}, ++ ++ /* ++ * Dummy routes to keep wm5102 from staying off on ++ * playback/capture if all mixers are off. ++ */ ++ { "Dummy Output", NULL, "AIF1RX1" }, ++ { "Dummy Output", NULL, "AIF1RX2" }, ++ { "AIF1TX1", NULL, "Dummy Input" }, ++ { "AIF1TX2", NULL, "Dummy Input" }, ++}; ++ ++static int rpi_cirrus_clear_flls(struct snd_soc_card *card, ++ struct snd_soc_codec *wm5102_codec) { ++ ++ int ret1, ret2; ++ ++ ret1 = snd_soc_codec_set_pll(wm5102_codec, ++ WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0); ++ ret2 = snd_soc_codec_set_pll(wm5102_codec, ++ WM5102_FLL1_REFCLK, ARIZONA_FLL_SRC_NONE, 0, 0); ++ ++ if (ret1) { ++ dev_warn(card->dev, ++ "setting FLL1 to zero failed: %d\n", ret1); ++ return ret1; ++ } ++ if (ret2) { ++ dev_warn(card->dev, ++ "setting FLL1_REFCLK to zero failed: %d\n", ret2); ++ return ret2; ++ } ++ return 0; ++} ++ ++static int rpi_cirrus_set_fll(struct snd_soc_card *card, ++ struct snd_soc_codec *wm5102_codec, unsigned int clk_freq) ++{ ++ int ret = snd_soc_codec_set_pll(wm5102_codec, ++ WM5102_FLL1, ++ ARIZONA_CLK_SRC_MCLK1, ++ WM8804_CLKOUT_HZ, ++ clk_freq); ++ if (ret) ++ dev_err(card->dev, "Failed to set FLL1 to %d: %d\n", ++ clk_freq, ret); ++ ++ usleep_range(1000, 2000); ++ return ret; ++} ++ ++static int rpi_cirrus_set_fll_refclk(struct snd_soc_card *card, ++ struct snd_soc_codec *wm5102_codec, ++ unsigned int clk_freq, unsigned int aif2_freq) ++{ ++ int ret = snd_soc_codec_set_pll(wm5102_codec, ++ WM5102_FLL1_REFCLK, ++ ARIZONA_CLK_SRC_MCLK1, ++ WM8804_CLKOUT_HZ, ++ clk_freq); ++ if (ret) { ++ dev_err(card->dev, ++ "Failed to set FLL1_REFCLK to %d: %d\n", ++ clk_freq, ret); ++ return ret; ++ } ++ ++ ret = snd_soc_codec_set_pll(wm5102_codec, ++ WM5102_FLL1, ++ ARIZONA_CLK_SRC_AIF2BCLK, ++ aif2_freq, clk_freq); ++ if (ret) ++ dev_err(card->dev, ++ "Failed to set FLL1 with Sync Clock %d to %d: %d\n", ++ aif2_freq, clk_freq, ret); ++ ++ usleep_range(1000, 2000); ++ return ret; ++} ++ ++static int rpi_cirrus_spdif_rx_enable_event(struct snd_soc_dapm_widget *w, ++ struct snd_kcontrol *kcontrol, int event) ++{ ++ struct snd_soc_card *card = w->dapm->card; ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ struct snd_soc_codec *wm5102_codec = get_wm5102_runtime(card)->codec; ++ ++ unsigned int clk_freq, aif2_freq; ++ int ret = 0; ++ ++ switch (event) { ++ case SND_SOC_DAPM_POST_PMU: ++ mutex_lock(&priv->lock); ++ ++ /* Enable sync path in case of SPDIF capture use case */ ++ ++ clk_freq = calc_sysclk(priv->card_rate); ++ aif2_freq = 64 * priv->card_rate; ++ ++ dev_dbg(card->dev, ++ "spdif_rx: changing FLL1 to use Ref Clock clk: %d spdif: %d\n", ++ clk_freq, aif2_freq); ++ ++ ret = rpi_cirrus_clear_flls(card, wm5102_codec); ++ if (ret) { ++ dev_err(card->dev, "spdif_rx: failed to clear FLLs\n"); ++ goto out; ++ } ++ ++ ret = rpi_cirrus_set_fll_refclk(card, wm5102_codec, ++ clk_freq, aif2_freq); ++ ++ if (ret) { ++ dev_err(card->dev, "spdif_rx: failed to set FLLs\n"); ++ goto out; ++ } ++ ++ /* set to negative to indicate we're doing spdif rx */ ++ priv->fll1_freq = -clk_freq; ++ priv->sync_path_enable = 1; ++ break; ++ ++ case SND_SOC_DAPM_POST_PMD: ++ mutex_lock(&priv->lock); ++ priv->sync_path_enable = 0; ++ break; ++ ++ default: ++ return 0; ++ } ++ ++out: ++ mutex_unlock(&priv->lock); ++ return ret; ++} ++ ++static int rpi_cirrus_set_bias_level(struct snd_soc_card *card, ++ struct snd_soc_dapm_context *dapm, ++ enum snd_soc_bias_level level) ++{ ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card); ++ struct snd_soc_codec *wm5102_codec = wm5102_runtime->codec; ++ ++ int ret = 0; ++ unsigned int clk_freq; ++ ++ if (dapm->dev != wm5102_runtime->codec_dai->dev) ++ return 0; ++ ++ switch (level) { ++ case SND_SOC_BIAS_PREPARE: ++ if (dapm->bias_level == SND_SOC_BIAS_ON) ++ break; ++ ++ mutex_lock(&priv->lock); ++ ++ if (!priv->sync_path_enable) { ++ clk_freq = calc_sysclk(priv->card_rate); ++ ++ dev_dbg(card->dev, ++ "set_bias: changing FLL1 from %d to %d\n", ++ priv->fll1_freq, clk_freq); ++ ++ ret = rpi_cirrus_set_fll(card, wm5102_codec, clk_freq); ++ if (ret) ++ dev_err(card->dev, ++ "set_bias: Failed to set FLL1\n"); ++ else ++ priv->fll1_freq = clk_freq; ++ } ++ mutex_unlock(&priv->lock); ++ break; ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++static int rpi_cirrus_set_bias_level_post(struct snd_soc_card *card, ++ struct snd_soc_dapm_context *dapm, ++ enum snd_soc_bias_level level) ++{ ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card); ++ struct snd_soc_codec *wm5102_codec = wm5102_runtime->codec; ++ ++ if (dapm->dev != wm5102_runtime->codec_dai->dev) ++ return 0; ++ ++ switch (level) { ++ case SND_SOC_BIAS_STANDBY: ++ mutex_lock(&priv->lock); ++ ++ dev_dbg(card->dev, ++ "set_bias_post: changing FLL1 from %d to off\n", ++ priv->fll1_freq); ++ ++ if (rpi_cirrus_clear_flls(card, wm5102_codec)) ++ dev_err(card->dev, ++ "set_bias_post: failed to clear FLLs\n"); ++ else ++ priv->fll1_freq = 0; ++ ++ mutex_unlock(&priv->lock); ++ ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static int rpi_cirrus_set_wm8804_pll(struct snd_soc_card *card, ++ struct snd_soc_dai *wm8804_dai, unsigned int rate) ++{ ++ int ret; ++ ++ /* use 256fs */ ++ unsigned int clk_freq = rate * 256; ++ ++ ret = snd_soc_dai_set_pll(wm8804_dai, 0, 0, ++ WM8804_CLKOUT_HZ, clk_freq); ++ if (ret) { ++ dev_err(card->dev, ++ "Failed to set WM8804 PLL to %d: %d\n", clk_freq, ret); ++ return ret; ++ } ++ ++ /* Set MCLK as PLL Output */ ++ ret = snd_soc_dai_set_sysclk(wm8804_dai, ++ WM8804_TX_CLKSRC_PLL, clk_freq, 0); ++ if (ret) { ++ dev_err(card->dev, ++ "Failed to set MCLK as PLL Output: %d\n", ret); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++static int rpi_cirrus_startup(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_card *card = rtd->card; ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ unsigned int min_rate = min_rates[priv->min_rate_idx].value; ++ unsigned int max_rate = max_rates[priv->max_rate_idx].value; ++ ++ if (min_rate || max_rate) { ++ if (max_rate == 0) ++ max_rate = UINT_MAX; ++ ++ dev_dbg(card->dev, ++ "startup: limiting rate to %u-%u\n", ++ min_rate, max_rate); ++ ++ snd_pcm_hw_constraint_minmax(substream->runtime, ++ SNDRV_PCM_HW_PARAM_RATE, min_rate, max_rate); ++ } ++ ++ return 0; ++} ++ ++static struct snd_soc_pcm_stream rpi_cirrus_dai_link2_params = { ++ .formats = SNDRV_PCM_FMTBIT_S24_LE, ++ .channels_min = 2, ++ .channels_max = 2, ++ .rate_min = RPI_CIRRUS_DEFAULT_RATE, ++ .rate_max = RPI_CIRRUS_DEFAULT_RATE, ++}; ++ ++static int rpi_cirrus_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_card *card = rtd->card; ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ struct snd_soc_dai *bcm_i2s_dai = rtd->cpu_dai; ++ struct snd_soc_codec *wm5102_codec = rtd->codec; ++ struct snd_soc_dai *wm8804_dai = get_wm8804_runtime(card)->codec_dai; ++ ++ int ret; ++ ++ unsigned int width = snd_pcm_format_physical_width( ++ params_format(params)); ++ unsigned int rate = params_rate(params); ++ unsigned int clk_freq = calc_sysclk(rate); ++ ++ mutex_lock(&priv->lock); ++ ++ dev_dbg(card->dev, "hw_params: setting rate to %d\n", rate); ++ ++ ret = snd_soc_dai_set_bclk_ratio(bcm_i2s_dai, 2 * width); ++ if (ret) { ++ dev_err(card->dev, "set_bclk_ratio failed: %d\n", ret); ++ goto out; ++ } ++ ++ ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0x03, 0x03, 2, width); ++ if (ret) { ++ dev_err(card->dev, "set_tdm_slot failed: %d\n", ret); ++ goto out; ++ } ++ ++ /* WM8804 supports sample rates from 32k only */ ++ if (rate >= 32000) { ++ ret = rpi_cirrus_set_wm8804_pll(card, wm8804_dai, rate); ++ if (ret) ++ goto out; ++ } ++ ++ ret = snd_soc_codec_set_sysclk(wm5102_codec, ++ ARIZONA_CLK_SYSCLK, ++ ARIZONA_CLK_SRC_FLL1, ++ clk_freq, ++ SND_SOC_CLOCK_IN); ++ if (ret) { ++ dev_err(card->dev, "Failed to set SYSCLK: %d\n", ret); ++ goto out; ++ } ++ ++ if ((priv->fll1_freq > 0) && (priv->fll1_freq != clk_freq)) { ++ dev_dbg(card->dev, ++ "hw_params: changing FLL1 from %d to %d\n", ++ priv->fll1_freq, clk_freq); ++ ++ if (rpi_cirrus_clear_flls(card, wm5102_codec)) { ++ dev_err(card->dev, "hw_params: failed to clear FLLs\n"); ++ goto out; ++ } ++ ++ if (rpi_cirrus_set_fll(card, wm5102_codec, clk_freq)) { ++ dev_err(card->dev, "hw_params: failed to set FLL\n"); ++ goto out; ++ } ++ ++ priv->fll1_freq = clk_freq; ++ } ++ ++ priv->card_rate = rate; ++ rpi_cirrus_dai_link2_params.rate_min = rate; ++ rpi_cirrus_dai_link2_params.rate_max = rate; ++ ++ priv->params_set |= 1 << substream->stream; ++ ++out: ++ mutex_unlock(&priv->lock); ++ ++ return ret; ++} ++ ++static int rpi_cirrus_hw_free(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_card *card = rtd->card; ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ struct snd_soc_codec *wm5102_codec = rtd->codec; ++ int ret; ++ unsigned int old_params_set = priv->params_set; ++ ++ priv->params_set &= ~(1 << substream->stream); ++ ++ /* disable sysclk if this was the last open stream */ ++ if (priv->params_set == 0 && old_params_set) { ++ dev_dbg(card->dev, ++ "hw_free: Setting SYSCLK to Zero\n"); ++ ++ ret = snd_soc_codec_set_sysclk(wm5102_codec, ++ ARIZONA_CLK_SYSCLK, ++ ARIZONA_CLK_SRC_FLL1, ++ 0, ++ SND_SOC_CLOCK_IN); ++ if (ret) ++ dev_err(card->dev, ++ "hw_free: Failed to set SYSCLK to Zero: %d\n", ++ ret); ++ } ++ return 0; ++} ++ ++static int rpi_cirrus_init_wm5102(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ int ret; ++ ++ /* no 32kHz input, derive it from sysclk if needed */ ++ snd_soc_update_bits(codec, ++ ARIZONA_CLOCK_32K_1, ARIZONA_CLK_32K_SRC_MASK, 2); ++ ++ if (rpi_cirrus_clear_flls(rtd->card, codec)) ++ dev_warn(rtd->card->dev, ++ "init_wm5102: failed to clear FLLs\n"); ++ ++ ret = snd_soc_codec_set_sysclk(codec, ++ ARIZONA_CLK_SYSCLK, ARIZONA_CLK_SRC_FLL1, ++ 0, SND_SOC_CLOCK_IN); ++ if (ret) { ++ dev_err(rtd->card->dev, ++ "Failed to set SYSCLK to Zero: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int rpi_cirrus_init_wm8804(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_card *card = rtd->card; ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ unsigned int mask; ++ int i, ret; ++ ++ for (i = 0; i < 4; i++) { ++ mask = (i == 3) ? 0x3f : 0xff; ++ priv->iec958_status[i] = ++ snd_soc_read(codec, WM8804_SPDTX1 + i) & mask; ++ } ++ ++ /* Setup for 256fs */ ++ ret = snd_soc_dai_set_clkdiv(codec_dai, ++ WM8804_MCLK_DIV, WM8804_MCLKDIV_256FS); ++ if (ret) { ++ dev_err(card->dev, ++ "init_wm8804: Failed to set MCLK_DIV to 256fs: %d\n", ++ ret); ++ return ret; ++ } ++ ++ /* Output OSC on CLKOUT */ ++ ret = snd_soc_dai_set_sysclk(codec_dai, ++ WM8804_CLKOUT_SRC_OSCCLK, WM8804_CLKOUT_HZ, 0); ++ if (ret) ++ dev_err(card->dev, ++ "init_wm8804: Failed to set CLKOUT as OSC Frequency: %d\n", ++ ret); ++ ++ /* Init PLL with default samplerate */ ++ ret = rpi_cirrus_set_wm8804_pll(card, codec_dai, ++ RPI_CIRRUS_DEFAULT_RATE); ++ if (ret) ++ dev_err(card->dev, ++ "init_wm8804: Failed to setup PLL for %dHz: %d\n", ++ RPI_CIRRUS_DEFAULT_RATE, ret); ++ ++ return ret; ++} ++ ++static struct snd_soc_ops rpi_cirrus_ops = { ++ .startup = rpi_cirrus_startup, ++ .hw_params = rpi_cirrus_hw_params, ++ .hw_free = rpi_cirrus_hw_free, ++}; ++ ++static struct snd_soc_dai_link rpi_cirrus_dai[] = { ++ [DAI_WM5102] = { ++ .name = "WM5102", ++ .stream_name = "WM5102 AiFi", ++ .codec_dai_name = "wm5102-aif1", ++ .codec_name = "wm5102-codec", ++ .dai_fmt = SND_SOC_DAIFMT_I2S ++ | SND_SOC_DAIFMT_NB_NF ++ | SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &rpi_cirrus_ops, ++ .init = rpi_cirrus_init_wm5102, ++ }, ++ [DAI_WM8804] = { ++ .name = "WM5102 SPDIF", ++ .stream_name = "SPDIF Tx/Rx", ++ .cpu_dai_name = "wm5102-aif2", ++ .codec_dai_name = "wm8804-spdif", ++ .codec_name = "wm8804.1-003b", ++ .dai_fmt = SND_SOC_DAIFMT_I2S ++ | SND_SOC_DAIFMT_NB_NF ++ | SND_SOC_DAIFMT_CBM_CFM, ++ .ignore_suspend = 1, ++ .params = &rpi_cirrus_dai_link2_params, ++ .init = rpi_cirrus_init_wm8804, ++ }, ++}; ++ ++ ++static int rpi_cirrus_late_probe(struct snd_soc_card *card) ++{ ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card); ++ struct snd_soc_pcm_runtime *wm8804_runtime = get_wm8804_runtime(card); ++ int ret; ++ ++ dev_dbg(card->dev, "iec958_bits: %02x %02x %02x %02x\n", ++ priv->iec958_status[0], ++ priv->iec958_status[1], ++ priv->iec958_status[2], ++ priv->iec958_status[3]); ++ ++ ret = snd_soc_dai_set_sysclk( ++ wm5102_runtime->codec_dai, ARIZONA_CLK_SYSCLK, 0, 0); ++ if (ret) { ++ dev_err(card->dev, ++ "Failed to set WM5102 codec dai clk domain: %d\n", ret); ++ return ret; ++ } ++ ++ ret = snd_soc_dai_set_sysclk( ++ wm8804_runtime->cpu_dai, ARIZONA_CLK_SYSCLK, 0, 0); ++ if (ret) ++ dev_err(card->dev, ++ "Failed to set WM8804 codec dai clk domain: %d\n", ret); ++ ++ return ret; ++} ++ ++/* audio machine driver */ ++static struct snd_soc_card rpi_cirrus_card = { ++ .name = "RPi-Cirrus", ++ .driver_name = "RPiCirrus", ++ .owner = THIS_MODULE, ++ .dai_link = rpi_cirrus_dai, ++ .num_links = ARRAY_SIZE(rpi_cirrus_dai), ++ .late_probe = rpi_cirrus_late_probe, ++ .controls = rpi_cirrus_controls, ++ .num_controls = ARRAY_SIZE(rpi_cirrus_controls), ++ .dapm_widgets = rpi_cirrus_dapm_widgets, ++ .num_dapm_widgets = ARRAY_SIZE(rpi_cirrus_dapm_widgets), ++ .dapm_routes = rpi_cirrus_dapm_routes, ++ .num_dapm_routes = ARRAY_SIZE(rpi_cirrus_dapm_routes), ++ .set_bias_level = rpi_cirrus_set_bias_level, ++ .set_bias_level_post = rpi_cirrus_set_bias_level_post, ++}; ++ ++static int rpi_cirrus_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ struct rpi_cirrus_priv *priv; ++ struct device_node *i2s_node; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->min_rate_idx = 1; /* min samplerate 32kHz */ ++ priv->card_rate = RPI_CIRRUS_DEFAULT_RATE; ++ ++ mutex_init(&priv->lock); ++ ++ snd_soc_card_set_drvdata(&rpi_cirrus_card, priv); ++ ++ if (!pdev->dev.of_node) ++ return -ENODEV; ++ ++ i2s_node = of_parse_phandle( ++ pdev->dev.of_node, "i2s-controller", 0); ++ if (!i2s_node) { ++ dev_err(&pdev->dev, "i2s-controller missing in DT\n"); ++ return -ENODEV; ++ } ++ ++ rpi_cirrus_dai[DAI_WM5102].cpu_of_node = i2s_node; ++ rpi_cirrus_dai[DAI_WM5102].platform_of_node = i2s_node; ++ ++ rpi_cirrus_card.dev = &pdev->dev; ++ ++ ret = devm_snd_soc_register_card(&pdev->dev, &rpi_cirrus_card); ++ if (ret) { ++ if (ret == -EPROBE_DEFER) ++ dev_dbg(&pdev->dev, ++ "register card requested probe deferral\n"); ++ else ++ dev_err(&pdev->dev, ++ "Failed to register card: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++static const struct of_device_id rpi_cirrus_of_match[] = { ++ { .compatible = "wlf,rpi-cirrus", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rpi_cirrus_of_match); ++ ++static struct platform_driver rpi_cirrus_driver = { ++ .driver = { ++ .name = "snd-rpi-cirrus", ++ .of_match_table = of_match_ptr(rpi_cirrus_of_match), ++ }, ++ .probe = rpi_cirrus_probe, ++}; ++ ++module_platform_driver(rpi_cirrus_driver); ++ ++MODULE_AUTHOR("Matthias Reichl "); ++MODULE_DESCRIPTION("ASoC driver for Cirrus Logic Audio Card"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/brcm2708/patches-4.9/0144-usb-dwc2-Avoid-suspending-if-we-re-in-gadget-mode-18.patch b/target/linux/brcm2708/patches-4.9/0144-usb-dwc2-Avoid-suspending-if-we-re-in-gadget-mode-18.patch deleted file mode 100644 index cd82d4f8bc..0000000000 --- a/target/linux/brcm2708/patches-4.9/0144-usb-dwc2-Avoid-suspending-if-we-re-in-gadget-mode-18.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 7158cd0f806c91291c4f8e7c2e2b7e5be3023d30 Mon Sep 17 00:00:00 2001 -From: ED6E0F17 -Date: Fri, 3 Feb 2017 14:52:42 +0000 -Subject: [PATCH] usb: dwc2: Avoid suspending if we're in gadget mode (#1825) - -I've found when booting HiKey with the usb gadget cable attached -if I then try to connect via adb, I get an infinite spew of: - -dwc2 f72c0000.usb: dwc2_hsotg_ep_sethalt(ep ffffffc0790ecb18 ep1out, 0) -dwc2 f72c0000.usb: dwc2_hsotg_ep_sethalt(ep ffffffc0790eca18 ep1in, 0) - -It seems that the usb autosuspend is suspending the bus shortly -after bootup when the gadget cable is attached. So when adbd -then tries to use the device, it doesn't work and it then tries -to restart it over and over via the ep_sethalt calls (via -FUNCTIONFS_CLEAR_HALT ioctl). - -Chen Yu suggested this patch to avoid suspending if we're -in device mode, and it avoids the problem. - -Cc: Wei Xu -Cc: Guodong Xu -Cc: Amit Pundir -Cc: Rob Herring -Cc: John Youn -Cc: Douglas Anderson -Cc: Chen Yu -Cc: Kishon Vijay Abraham I -Cc: Felipe Balbi -Cc: Greg Kroah-Hartman -Cc: linux-usb@vger.kernel.org -Suggested-by: Chen Yu -Signed-off-by: John Stultz -Signed-off-by: John Youn -Signed-off-by: Felipe Balbi ---- - drivers/usb/dwc2/hcd.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/usb/dwc2/hcd.c -+++ b/drivers/usb/dwc2/hcd.c -@@ -4365,6 +4365,9 @@ static int _dwc2_hcd_suspend(struct usb_ - if (!HCD_HW_ACCESSIBLE(hcd)) - goto unlock; - -+ if (hsotg->op_state == OTG_STATE_B_PERIPHERAL) -+ goto unlock; -+ - if (!hsotg->core_params->hibernation) - goto skip_power_saving; - diff --git a/target/linux/brcm2708/patches-4.9/0145-config-Enable-regulator-support.patch b/target/linux/brcm2708/patches-4.9/0145-config-Enable-regulator-support.patch deleted file mode 100644 index 4c8cba110a..0000000000 --- a/target/linux/brcm2708/patches-4.9/0145-config-Enable-regulator-support.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 92105f7981fd207add7a09ace4570c9cd74f8757 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 22 Jan 2017 12:49:36 +0100 -Subject: [PATCH] config: Enable regulator support - -Signed-off-by: Matthias Reichl ---- - arch/arm/configs/bcm2709_defconfig | 2 ++ - arch/arm/configs/bcmrpi_defconfig | 2 ++ - 2 files changed, 4 insertions(+) - ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -664,6 +664,8 @@ CONFIG_STMPE_SPI=y - CONFIG_MFD_ARIZONA_I2C=m - CONFIG_MFD_ARIZONA_SPI=m - CONFIG_MFD_WM5102=y -+CONFIG_REGULATOR=y -+CONFIG_REGULATOR_FIXED_VOLTAGE=m - CONFIG_MEDIA_SUPPORT=m - CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_MEDIA_ANALOG_TV_SUPPORT=y ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -658,6 +658,8 @@ CONFIG_STMPE_SPI=y - CONFIG_MFD_ARIZONA_I2C=m - CONFIG_MFD_ARIZONA_SPI=m - CONFIG_MFD_WM5102=y -+CONFIG_REGULATOR=y -+CONFIG_REGULATOR_FIXED_VOLTAGE=m - CONFIG_MEDIA_SUPPORT=m - CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_MEDIA_ANALOG_TV_SUPPORT=y diff --git a/target/linux/brcm2708/patches-4.9/0145-config-enable-Cirrus-Logic-Audio-Card.patch b/target/linux/brcm2708/patches-4.9/0145-config-enable-Cirrus-Logic-Audio-Card.patch new file mode 100644 index 0000000000..be16a47d2b --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0145-config-enable-Cirrus-Logic-Audio-Card.patch @@ -0,0 +1,47 @@ +From e34099818448051c8fa84634534dff081540c7b7 Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 22 Jan 2017 12:49:37 +0100 +Subject: [PATCH] config: enable Cirrus Logic Audio Card + +Signed-off-by: Matthias Reichl +--- + arch/arm/configs/bcm2709_defconfig | 2 ++ + arch/arm/configs/bcmrpi_defconfig | 2 ++ + 2 files changed, 4 insertions(+) + +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -666,6 +666,7 @@ CONFIG_MFD_ARIZONA_SPI=m + CONFIG_MFD_WM5102=y + CONFIG_REGULATOR=y + CONFIG_REGULATOR_FIXED_VOLTAGE=m ++CONFIG_REGULATOR_ARIZONA=m + CONFIG_MEDIA_SUPPORT=m + CONFIG_MEDIA_CAMERA_SUPPORT=y + CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +@@ -872,6 +873,7 @@ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m + CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m + CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m + CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m + CONFIG_SND_BCM2708_SOC_RPI_DAC=m + CONFIG_SND_BCM2708_SOC_RPI_PROTO=m + CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -660,6 +660,7 @@ CONFIG_MFD_ARIZONA_SPI=m + CONFIG_MFD_WM5102=y + CONFIG_REGULATOR=y + CONFIG_REGULATOR_FIXED_VOLTAGE=m ++CONFIG_REGULATOR_ARIZONA=m + CONFIG_MEDIA_SUPPORT=m + CONFIG_MEDIA_CAMERA_SUPPORT=y + CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +@@ -866,6 +867,7 @@ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m + CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m + CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m + CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m + CONFIG_SND_BCM2708_SOC_RPI_DAC=m + CONFIG_SND_BCM2708_SOC_RPI_PROTO=m + CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m diff --git a/target/linux/brcm2708/patches-4.9/0146-BCM270x-DT-expose-3.3V-and-5V-system-rails.patch b/target/linux/brcm2708/patches-4.9/0146-BCM270x-DT-expose-3.3V-and-5V-system-rails.patch deleted file mode 100644 index 0deaa0ab63..0000000000 --- a/target/linux/brcm2708/patches-4.9/0146-BCM270x-DT-expose-3.3V-and-5V-system-rails.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 06b6fe1687cc560f36976cef615d38071ae07867 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 22 Jan 2017 12:49:36 +0100 -Subject: [PATCH] BCM270x DT: expose 3.3V and 5V system rails - -Signed-off-by: Matthias Reichl ---- - arch/arm/boot/dts/bcm270x.dtsi | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - ---- a/arch/arm/boot/dts/bcm270x.dtsi -+++ b/arch/arm/boot/dts/bcm270x.dtsi -@@ -138,4 +138,20 @@ - status = "disabled"; - }; - }; -+ -+ vdd_5v0_reg: fixedregulator_5v0 { -+ compatible = "regulator-fixed"; -+ regulator-name = "5v0"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ regulator-always-on; -+ }; -+ -+ vdd_3v3_reg: fixedregulator_3v3 { -+ compatible = "regulator-fixed"; -+ regulator-name = "3v3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; - }; diff --git a/target/linux/brcm2708/patches-4.9/0146-irq-bcm2836-Avoid-Invalid-trigger-warning.patch b/target/linux/brcm2708/patches-4.9/0146-irq-bcm2836-Avoid-Invalid-trigger-warning.patch new file mode 100644 index 0000000000..db9fd39d48 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0146-irq-bcm2836-Avoid-Invalid-trigger-warning.patch @@ -0,0 +1,24 @@ +From 4a849cef15885cf5dd901fafe45d3fa51b2b2a09 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 9 Feb 2017 14:33:30 +0000 +Subject: [PATCH] irq-bcm2836: Avoid "Invalid trigger warning" + +Initialise the level for each IRQ to avoid a warning from the +arm arch timer code. + +Signed-off-by: Phil Elwell +--- + drivers/irqchip/irq-bcm2836.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/irqchip/irq-bcm2836.c ++++ b/drivers/irqchip/irq-bcm2836.c +@@ -178,7 +178,7 @@ static void bcm2836_arm_irqchip_register + + irq_set_percpu_devid(irq); + irq_set_chip_and_handler(irq, chip, handle_percpu_devid_irq); +- irq_set_status_flags(irq, IRQ_NOAUTOEN); ++ irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_TYPE_LEVEL_LOW); + } + + static void diff --git a/target/linux/brcm2708/patches-4.9/0147-BCM270x-DT-Consolidate-audio-card-overlays.patch b/target/linux/brcm2708/patches-4.9/0147-BCM270x-DT-Consolidate-audio-card-overlays.patch deleted file mode 100644 index d865199317..0000000000 --- a/target/linux/brcm2708/patches-4.9/0147-BCM270x-DT-Consolidate-audio-card-overlays.patch +++ /dev/null @@ -1,273 +0,0 @@ -From 05798b17d672768e9e2c54c0c94df2ef019afe95 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 22 Jan 2017 12:49:36 +0100 -Subject: [PATCH] BCM270x DT: Consolidate audio card overlays - -Reference 3.3V / 5V system rails instead of instantiating local -regulators. - -Add missing power supply properties for codecs where these are -required according to the DT bindings docs. - -Signed-off-by: Matthias Reichl ---- - .../arm/boot/dts/overlays/adau1977-adc-overlay.dts | 19 ++-------- - .../dts/overlays/akkordion-iqdacplus-overlay.dts | 3 ++ - .../dts/overlays/hifiberry-dacplus-overlay.dts | 3 ++ - .../boot/dts/overlays/hifiberry-digi-overlay.dts | 2 + - .../dts/overlays/hifiberry-digi-pro-overlay.dts | 2 + - arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts | 3 ++ - .../boot/dts/overlays/iqaudio-dacplus-overlay.dts | 3 ++ - .../overlays/iqaudio-digi-wm8804-audio-overlay.dts | 4 +- - .../arm/boot/dts/overlays/justboom-dac-overlay.dts | 3 ++ - .../boot/dts/overlays/justboom-digi-overlay.dts | 2 + - arch/arm/boot/dts/overlays/raspidac3-overlay.dts | 4 ++ - .../overlays/rra-digidac1-wm8741-audio-overlay.dts | 44 +++------------------- - 12 files changed, 36 insertions(+), 56 deletions(-) - ---- a/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts -+++ b/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts -@@ -6,19 +6,6 @@ - compatible = "brcm,bcm2708"; - - fragment@0 { -- target = <&soc>; -- -- __overlay__ { -- codec_supply: fixedregulator@0 { -- compatible = "regulator-fixed"; -- regulator-name = "AVDD"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- }; -- }; -- }; -- -- fragment@1 { - target = <&i2c>; - - __overlay__ { -@@ -30,19 +17,19 @@ - compatible = "adi,adau1977"; - reg = <0x11>; - reset-gpios = <&gpio 5 0>; -- AVDD-supply = <&codec_supply>; -+ AVDD-supply = <&vdd_3v3_reg>; - }; - }; - }; - -- fragment@2 { -+ fragment@1 { - target = <&i2s>; - __overlay__ { - status = "okay"; - }; - }; - -- fragment@3 { -+ fragment@2 { - target = <&sound>; - __overlay__ { - compatible = "adi,adau1977-adc"; ---- a/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts -+++ b/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts -@@ -23,6 +23,9 @@ - #sound-dai-cells = <0>; - compatible = "ti,pcm5122"; - reg = <0x4c>; -+ AVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ CPVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; ---- a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts -+++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts -@@ -34,6 +34,9 @@ - compatible = "ti,pcm5122"; - reg = <0x4d>; - clocks = <&dacpro_osc>; -+ AVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ CPVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; ---- a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts -+++ b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts -@@ -23,6 +23,8 @@ - #sound-dai-cells = <0>; - compatible = "wlf,wm8804"; - reg = <0x3b>; -+ PVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; ---- a/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts -+++ b/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts -@@ -23,6 +23,8 @@ - #sound-dai-cells = <0>; - compatible = "wlf,wm8804"; - reg = <0x3b>; -+ PVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; ---- a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts -+++ b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts -@@ -23,6 +23,9 @@ - #sound-dai-cells = <0>; - compatible = "ti,pcm5122"; - reg = <0x4c>; -+ AVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ CPVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; ---- a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts -+++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts -@@ -23,6 +23,9 @@ - #sound-dai-cells = <0>; - compatible = "ti,pcm5122"; - reg = <0x4c>; -+ AVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ CPVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; ---- a/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts -+++ b/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts -@@ -24,8 +24,8 @@ - compatible = "wlf,wm8804"; - reg = <0x3b>; - status = "okay"; -- // DVDD-supply = <®_3v3>; -- // PVDD-supply = <®_3v3>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ PVDD-supply = <&vdd_3v3_reg>; - }; - }; - }; ---- a/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts -+++ b/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts -@@ -23,6 +23,9 @@ - #sound-dai-cells = <0>; - compatible = "ti,pcm5122"; - reg = <0x4d>; -+ AVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ CPVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; ---- a/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts -+++ b/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts -@@ -23,6 +23,8 @@ - #sound-dai-cells = <0>; - compatible = "wlf,wm8804"; - reg = <0x3b>; -+ PVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; ---- a/arch/arm/boot/dts/overlays/raspidac3-overlay.dts -+++ b/arch/arm/boot/dts/overlays/raspidac3-overlay.dts -@@ -23,12 +23,16 @@ - #sound-dai-cells = <0>; - compatible = "ti,pcm5122"; - reg = <0x4c>; -+ AVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ CPVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - - tpa6130a2: tpa6130a2@60 { - compatible = "ti,tpa6130a2"; - reg = <0x60>; -+ Vdd-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; ---- a/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts -+++ b/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts -@@ -6,45 +6,13 @@ - compatible = "brcm,bcm2708"; - - fragment@0 { -- target-path = "/"; -- __overlay__ { -- aliases { -- ldo0 = &ldo0; -- ldo1 = &ldo1; -- }; -- }; -- }; -- -- fragment@1 { -- target-path = "/soc"; -- __overlay__ { -- -- ldo1: ldo1 { -- compatible = "regulator-fixed"; -- regulator-name = "DC_5V"; -- regulator-min-microvolt = <5000000>; -- regulator-max-microvolt = <5000000>; -- regulator-always-on; -- }; -- -- ldo0: ldo0 { -- compatible = "regulator-fixed"; -- regulator-name = "DC_3V3"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- regulator-always-on; -- }; -- }; -- }; -- -- fragment@2 { - target = <&i2s>; - __overlay__ { - status = "okay"; - }; - }; - -- fragment@3 { -+ fragment@1 { - target = <&i2c1>; - __overlay__ { - #address-cells = <1>; -@@ -56,21 +24,21 @@ - compatible = "wlf,wm8804"; - reg = <0x3b>; - status = "okay"; -- PVDD-supply = <&ldo0>; -- DVDD-supply = <&ldo0>; -+ PVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; - }; - - wm8742: wm8741@1a { - compatible = "wlf,wm8741"; - reg = <0x1a>; - status = "okay"; -- AVDD-supply = <&ldo1>; -- DVDD-supply = <&ldo0>; -+ AVDD-supply = <&vdd_5v0_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; - }; - }; - }; - -- fragment@4 { -+ fragment@2 { - target = <&sound>; - __overlay__ { - compatible = "rra,digidac1-soundcard"; diff --git a/target/linux/brcm2708/patches-4.9/0147-sound-Demote-deferral-errors-to-INFO-level.patch b/target/linux/brcm2708/patches-4.9/0147-sound-Demote-deferral-errors-to-INFO-level.patch new file mode 100644 index 0000000000..0a08eb9a1d --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0147-sound-Demote-deferral-errors-to-INFO-level.patch @@ -0,0 +1,35 @@ +From b78e78fa375e3aa1e91b35030e8dfc930ba425f2 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 9 Feb 2017 14:36:44 +0000 +Subject: [PATCH] sound: Demote deferral errors to INFO level + +At present there is no mechanism to specify driver load order, +which can lead to deferrals and repeated retries until successful. +Since this situation is expected, reduce the dmesg level to +INFO and mention that the operation will be retried. + +Signed-off-by: Phil Elwell +--- + sound/soc/soc-core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/soc/soc-core.c ++++ b/sound/soc/soc-core.c +@@ -1013,7 +1013,7 @@ static int soc_bind_dai_link(struct snd_ + cpu_dai_component.dai_name = dai_link->cpu_dai_name; + rtd->cpu_dai = snd_soc_find_dai(&cpu_dai_component); + if (!rtd->cpu_dai) { +- dev_err(card->dev, "ASoC: CPU DAI %s not registered\n", ++ dev_info(card->dev, "ASoC: CPU DAI %s not registered - will retry\n", + dai_link->cpu_dai_name); + goto _err_defer; + } +@@ -1025,7 +1025,7 @@ static int soc_bind_dai_link(struct snd_ + for (i = 0; i < rtd->num_codecs; i++) { + codec_dais[i] = snd_soc_find_dai(&codecs[i]); + if (!codec_dais[i]) { +- dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n", ++ dev_info(card->dev, "ASoC: CODEC DAI %s not registered - will retry\n", + codecs[i].dai_name); + goto _err_defer; + } diff --git a/target/linux/brcm2708/patches-4.9/0148-ASoC-Add-driver-for-Cirrus-Logic-Audio-Card.patch b/target/linux/brcm2708/patches-4.9/0148-ASoC-Add-driver-for-Cirrus-Logic-Audio-Card.patch deleted file mode 100644 index 5c343bae91..0000000000 --- a/target/linux/brcm2708/patches-4.9/0148-ASoC-Add-driver-for-Cirrus-Logic-Audio-Card.patch +++ /dev/null @@ -1,1238 +0,0 @@ -From 8729879667d0668f20bd2aba8473879ac1d0216d Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 22 Jan 2017 12:49:37 +0100 -Subject: [PATCH] ASoC: Add driver for Cirrus Logic Audio Card - -Note: due to problems with deferred probing of regulators -the following softdep should be added to a modprobe.d file - -softdep arizona-spi pre: arizona-ldo1 - -Signed-off-by: Matthias Reichl ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 + - .../dts/overlays/rpi-cirrus-wm5102-overlay.dts | 146 +++ - sound/soc/bcm/Kconfig | 9 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/rpi-cirrus.c | 1003 ++++++++++++++++++++ - 6 files changed, 1167 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts - create mode 100644 sound/soc/bcm/rpi-cirrus.c - ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -68,6 +68,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - qca7000.dtbo \ - raspidac3.dtbo \ - rpi-backlight.dtbo \ -+ rpi-cirrus-wm5102.dtbo \ - rpi-dac.dtbo \ - rpi-display.dtbo \ - rpi-ft5406.dtbo \ ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -995,6 +995,12 @@ Load: dtoverlay=rpi-backlight - Params: - - -+Name: rpi-cirrus-wm5102 -+Info: Configures the Cirrus Logic Audio Card -+Load: dtoverlay=rpi-cirrus-wm5102 -+Params: -+ -+ - Name: rpi-dac - Info: Configures the RPi DAC audio card - Load: dtoverlay=rpi-dac ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts -@@ -0,0 +1,146 @@ -+// Definitions for the Cirrus Logic Audio Card -+/dts-v1/; -+/plugin/; -+#include -+#include -+#include -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ wlf_pins: wlf_pins { -+ brcm,pins = <17 22 27 8>; -+ brcm,function = < -+ BCM2835_FSEL_GPIO_OUT -+ BCM2835_FSEL_GPIO_OUT -+ BCM2835_FSEL_GPIO_IN -+ BCM2835_FSEL_GPIO_OUT -+ >; -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "/"; -+ __overlay__ { -+ rpi_cirrus_reg_1v8: rpi_cirrus_reg_1v8 { -+ compatible = "regulator-fixed"; -+ regulator-name = "RPi-Cirrus 1v8"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ }; -+ }; -+ }; -+ -+ fragment@3 { -+ target = <&spi0>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ -+ wm5102@1{ -+ compatible = "wlf,wm5102"; -+ reg = <1>; -+ -+ spi-max-frequency = <500000>; -+ -+ interrupt-parent = <&gpio>; -+ interrupts = <27 8>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ LDOVDD-supply = <&rpi_cirrus_reg_1v8>; -+ AVDD-supply = <&rpi_cirrus_reg_1v8>; -+ DBVDD1-supply = <&rpi_cirrus_reg_1v8>; -+ DBVDD2-supply = <&vdd_3v3_reg>; -+ DBVDD3-supply = <&vdd_3v3_reg>; -+ CPVDD-supply = <&rpi_cirrus_reg_1v8>; -+ SPKVDDL-supply = <&vdd_5v0_reg>; -+ SPKVDDR-supply = <&vdd_5v0_reg>; -+ DCVDD-supply = <&arizona_ldo1>; -+ -+ wlf,reset = <&gpio 17 GPIO_ACTIVE_HIGH>; -+ wlf,ldoena = <&gpio 22 GPIO_ACTIVE_HIGH>; -+ wlf,gpio-defaults = < -+ ARIZONA_GP_DEFAULT -+ ARIZONA_GP_DEFAULT -+ ARIZONA_GP_DEFAULT -+ ARIZONA_GP_DEFAULT -+ ARIZONA_GP_DEFAULT -+ >; -+ wlf,micd-configs = <0 1 0>; -+ wlf,dmic-ref = < -+ ARIZONA_DMIC_MICVDD -+ ARIZONA_DMIC_MICBIAS2 -+ ARIZONA_DMIC_MICVDD -+ ARIZONA_DMIC_MICVDD -+ >; -+ wlf,inmode = < -+ ARIZONA_INMODE_DIFF -+ ARIZONA_INMODE_DMIC -+ ARIZONA_INMODE_SE -+ ARIZONA_INMODE_DIFF -+ >; -+ status = "okay"; -+ -+ arizona_ldo1: ldo1 { -+ regulator-name = "LDO1"; -+ // default constraints as in -+ // arizona-ldo1.c -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1800000>; -+ }; -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target = <&i2c1>; -+ __overlay__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ wm8804@3b { -+ compatible = "wlf,wm8804"; -+ reg = <0x3b>; -+ status = "okay"; -+ PVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ wlf,reset-gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+ }; -+ -+ fragment@5 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "wlf,rpi-cirrus"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+}; ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -45,6 +45,15 @@ config SND_BCM2708_SOC_HIFIBERRY_AMP - help - Say Y or M if you want to add support for the HifiBerry Amp amplifier board. - -+config SND_BCM2708_SOC_RPI_CIRRUS -+ tristate "Support for Cirrus Logic Audio Card" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_WM5102 -+ select SND_SOC_WM8804 -+ help -+ Say Y or M if you want to add support for the Wolfson and -+ Cirrus Logic audio cards. -+ - config SND_BCM2708_SOC_RPI_DAC - tristate "Support for RPi-DAC" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -16,6 +16,7 @@ snd-soc-hifiberry-dacplus-objs := hifibe - snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-justboom-dac-objs := justboom-dac.o - snd-soc-justboom-digi-objs := justboom-digi.o -+snd-soc-rpi-cirrus-objs := rpi-cirrus.o - snd-soc-rpi-dac-objs := rpi-dac.o - snd-soc-rpi-proto-objs := rpi-proto.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o -@@ -34,6 +35,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o -+obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o ---- /dev/null -+++ b/sound/soc/bcm/rpi-cirrus.c -@@ -0,0 +1,1003 @@ -+/* -+ * ASoC machine driver for Cirrus Logic Audio Card -+ * (with WM5102 and WM8804 codecs) -+ * -+ * Copyright 2015-2017 Matthias Reichl -+ * -+ * Based on rpi-cirrus-sound-pi driver (c) Wolfson / Cirrus Logic Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "../codecs/wm5102.h" -+#include "../codecs/wm8804.h" -+ -+#define WM8804_CLKOUT_HZ 12000000 -+ -+#define RPI_CIRRUS_DEFAULT_RATE 44100 -+#define WM5102_MAX_SYSCLK_1 49152000 /* max sysclk for 4K family */ -+#define WM5102_MAX_SYSCLK_2 45158400 /* max sysclk for 11.025K family */ -+ -+static inline unsigned int calc_sysclk(unsigned int rate) -+{ -+ return (rate % 4000) ? WM5102_MAX_SYSCLK_2 : WM5102_MAX_SYSCLK_1; -+} -+ -+enum { -+ DAI_WM5102 = 0, -+ DAI_WM8804, -+}; -+ -+struct rpi_cirrus_priv { -+ /* mutex for synchronzing FLL1 access with DAPM */ -+ struct mutex lock; -+ unsigned int card_rate; -+ int sync_path_enable; -+ int fll1_freq; /* negative means RefClock in spdif rx case */ -+ -+ /* track hw params/free for substreams */ -+ unsigned int params_set; -+ unsigned int min_rate_idx, max_rate_idx; -+ unsigned char iec958_status[4]; -+}; -+ -+/* helper functions */ -+static inline struct snd_soc_pcm_runtime *get_wm5102_runtime( -+ struct snd_soc_card *card) { -+ return snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM5102].name); -+} -+ -+static inline struct snd_soc_pcm_runtime *get_wm8804_runtime( -+ struct snd_soc_card *card) { -+ return snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM8804].name); -+} -+ -+ -+struct rate_info { -+ unsigned int value; -+ char *text; -+}; -+ -+static struct rate_info min_rates[] = { -+ { 0, "off"}, -+ { 32000, "32kHz"}, -+ { 44100, "44.1kHz"} -+}; -+ -+#define NUM_MIN_RATES ARRAY_SIZE(min_rates) -+ -+static int rpi_cirrus_min_rate_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; -+ uinfo->count = 1; -+ uinfo->value.enumerated.items = NUM_MIN_RATES; -+ -+ if (uinfo->value.enumerated.item >= NUM_MIN_RATES) -+ uinfo->value.enumerated.item = NUM_MIN_RATES - 1; -+ strcpy(uinfo->value.enumerated.name, -+ min_rates[uinfo->value.enumerated.item].text); -+ return 0; -+} -+ -+static int rpi_cirrus_min_rate_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ -+ ucontrol->value.enumerated.item[0] = priv->min_rate_idx; -+ return 0; -+} -+ -+static int rpi_cirrus_min_rate_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ int changed = 0; -+ -+ if (priv->min_rate_idx != ucontrol->value.enumerated.item[0]) { -+ changed = 1; -+ priv->min_rate_idx = ucontrol->value.enumerated.item[0]; -+ } -+ -+ return changed; -+} -+ -+static struct rate_info max_rates[] = { -+ { 0, "off"}, -+ { 48000, "48kHz"}, -+ { 96000, "96kHz"} -+}; -+ -+#define NUM_MAX_RATES ARRAY_SIZE(max_rates) -+ -+static int rpi_cirrus_max_rate_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; -+ uinfo->count = 1; -+ uinfo->value.enumerated.items = NUM_MAX_RATES; -+ if (uinfo->value.enumerated.item >= NUM_MAX_RATES) -+ uinfo->value.enumerated.item = NUM_MAX_RATES - 1; -+ strcpy(uinfo->value.enumerated.name, -+ max_rates[uinfo->value.enumerated.item].text); -+ return 0; -+} -+ -+static int rpi_cirrus_max_rate_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ -+ ucontrol->value.enumerated.item[0] = priv->max_rate_idx; -+ return 0; -+} -+ -+static int rpi_cirrus_max_rate_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ int changed = 0; -+ -+ if (priv->max_rate_idx != ucontrol->value.enumerated.item[0]) { -+ changed = 1; -+ priv->max_rate_idx = ucontrol->value.enumerated.item[0]; -+ } -+ -+ return changed; -+} -+ -+static int rpi_cirrus_spdif_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; -+ uinfo->count = 1; -+ return 0; -+} -+ -+static int rpi_cirrus_spdif_playback_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ int i; -+ -+ for (i = 0; i < 4; i++) -+ ucontrol->value.iec958.status[i] = priv->iec958_status[i]; -+ -+ return 0; -+} -+ -+static int rpi_cirrus_spdif_playback_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ unsigned char *stat = priv->iec958_status; -+ unsigned char *ctrl_stat = ucontrol->value.iec958.status; -+ unsigned int mask; -+ int i, changed = 0; -+ -+ for (i = 0; i < 4; i++) { -+ mask = (i == 3) ? 0x3f : 0xff; -+ if ((ctrl_stat[i] & mask) != (stat[i] & mask)) { -+ changed = 1; -+ stat[i] = ctrl_stat[i] & mask; -+ snd_soc_update_bits(wm8804_codec, -+ WM8804_SPDTX1 + i, mask, stat[i]); -+ } -+ } -+ -+ return changed; -+} -+ -+static int rpi_cirrus_spdif_mask_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ ucontrol->value.iec958.status[0] = 0xff; -+ ucontrol->value.iec958.status[1] = 0xff; -+ ucontrol->value.iec958.status[2] = 0xff; -+ ucontrol->value.iec958.status[3] = 0x3f; -+ -+ return 0; -+} -+ -+static int rpi_cirrus_spdif_capture_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; -+ unsigned int mask; -+ int i; -+ -+ for (i = 0; i < 4; i++) { -+ mask = (i == 3) ? 0x3f : 0xff; -+ ucontrol->value.iec958.status[i] = -+ snd_soc_read(wm8804_codec, WM8804_RXCHAN1 + i) & mask; -+ } -+ -+ return 0; -+} -+ -+#define SPDIF_FLAG_CTRL(desc, reg, bit, invert) \ -+{ \ -+ .access = SNDRV_CTL_ELEM_ACCESS_READ \ -+ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -+ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) \ -+ desc " Flag", \ -+ .info = snd_ctl_boolean_mono_info, \ -+ .get = rpi_cirrus_spdif_status_flag_get, \ -+ .private_value = \ -+ (bit) | ((reg) << 8) | ((invert) << 16) \ -+} -+ -+static int rpi_cirrus_spdif_status_flag_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; -+ -+ unsigned int bit = kcontrol->private_value & 0xff; -+ unsigned int reg = (kcontrol->private_value >> 8) & 0xff; -+ unsigned int invert = (kcontrol->private_value >> 16) & 0xff; -+ -+ bool flag = snd_soc_read(wm8804_codec, reg) & (1 << bit); -+ -+ ucontrol->value.integer.value[0] = invert ? !flag : flag; -+ -+ return 0; -+} -+ -+static const char * const recovered_frequency_texts[] = { -+ "176.4/192 kHz", -+ "88.2/96 kHz", -+ "44.1/48 kHz", -+ "32 kHz" -+}; -+ -+#define NUM_RECOVERED_FREQUENCIES \ -+ ARRAY_SIZE(recovered_frequency_texts) -+ -+static int rpi_cirrus_recovered_frequency_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; -+ uinfo->count = 1; -+ uinfo->value.enumerated.items = NUM_RECOVERED_FREQUENCIES; -+ if (uinfo->value.enumerated.item >= NUM_RECOVERED_FREQUENCIES) -+ uinfo->value.enumerated.item = NUM_RECOVERED_FREQUENCIES - 1; -+ strcpy(uinfo->value.enumerated.name, -+ recovered_frequency_texts[uinfo->value.enumerated.item]); -+ return 0; -+} -+ -+static int rpi_cirrus_recovered_frequency_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; -+ -+ ucontrol->value.enumerated.item[0] = -+ (snd_soc_read(wm8804_codec, WM8804_SPDSTAT) >> 4) & 0x03; -+ return 0; -+} -+ -+static const struct snd_kcontrol_new rpi_cirrus_controls[] = { -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "Min Sample Rate", -+ .info = rpi_cirrus_min_rate_info, -+ .get = rpi_cirrus_min_rate_get, -+ .put = rpi_cirrus_min_rate_put, -+ }, -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "Max Sample Rate", -+ .info = rpi_cirrus_max_rate_info, -+ .get = rpi_cirrus_max_rate_get, -+ .put = rpi_cirrus_max_rate_put, -+ }, -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), -+ .info = rpi_cirrus_spdif_info, -+ .get = rpi_cirrus_spdif_playback_get, -+ .put = rpi_cirrus_spdif_playback_put, -+ }, -+ { -+ .access = SNDRV_CTL_ELEM_ACCESS_READ -+ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), -+ .info = rpi_cirrus_spdif_info, -+ .get = rpi_cirrus_spdif_capture_get, -+ }, -+ { -+ .access = SNDRV_CTL_ELEM_ACCESS_READ, -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK), -+ .info = rpi_cirrus_spdif_info, -+ .get = rpi_cirrus_spdif_mask_get, -+ }, -+ { -+ .access = SNDRV_CTL_ELEM_ACCESS_READ -+ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) -+ "Recovered Frequency", -+ .info = rpi_cirrus_recovered_frequency_info, -+ .get = rpi_cirrus_recovered_frequency_get, -+ }, -+ SPDIF_FLAG_CTRL("Audio", WM8804_SPDSTAT, 0, 1), -+ SPDIF_FLAG_CTRL("Non-PCM", WM8804_SPDSTAT, 1, 0), -+ SPDIF_FLAG_CTRL("Copyright", WM8804_SPDSTAT, 2, 1), -+ SPDIF_FLAG_CTRL("De-Emphasis", WM8804_SPDSTAT, 3, 0), -+ SPDIF_FLAG_CTRL("Lock", WM8804_SPDSTAT, 6, 1), -+ SPDIF_FLAG_CTRL("Invalid", WM8804_INTSTAT, 1, 0), -+ SPDIF_FLAG_CTRL("TransErr", WM8804_INTSTAT, 3, 0), -+}; -+ -+static const char * const linein_micbias_texts[] = { -+ "off", "on", -+}; -+ -+static SOC_ENUM_SINGLE_VIRT_DECL(linein_micbias_enum, -+ linein_micbias_texts); -+ -+static const struct snd_kcontrol_new linein_micbias_mux = -+ SOC_DAPM_ENUM("Route", linein_micbias_enum); -+ -+static int rpi_cirrus_spdif_rx_enable_event(struct snd_soc_dapm_widget *w, -+ struct snd_kcontrol *kcontrol, int event); -+ -+const struct snd_soc_dapm_widget rpi_cirrus_dapm_widgets[] = { -+ SND_SOC_DAPM_MIC("DMIC", NULL), -+ SND_SOC_DAPM_MIC("Headset Mic", NULL), -+ SND_SOC_DAPM_INPUT("Line Input"), -+ SND_SOC_DAPM_MIC("Line Input with Micbias", NULL), -+ SND_SOC_DAPM_MUX("Line Input Micbias", SND_SOC_NOPM, 0, 0, -+ &linein_micbias_mux), -+ SND_SOC_DAPM_INPUT("dummy SPDIF in"), -+ SND_SOC_DAPM_PGA_E("dummy SPDIFRX", SND_SOC_NOPM, 0, 0, NULL, 0, -+ rpi_cirrus_spdif_rx_enable_event, -+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), -+ SND_SOC_DAPM_INPUT("Dummy Input"), -+ SND_SOC_DAPM_OUTPUT("Dummy Output"), -+}; -+ -+const struct snd_soc_dapm_route rpi_cirrus_dapm_routes[] = { -+ { "IN1L", NULL, "Headset Mic" }, -+ { "IN1R", NULL, "Headset Mic" }, -+ { "Headset Mic", NULL, "MICBIAS1" }, -+ -+ { "IN2L", NULL, "DMIC" }, -+ { "IN2R", NULL, "DMIC" }, -+ { "DMIC", NULL, "MICBIAS2" }, -+ -+ { "IN3L", NULL, "Line Input Micbias" }, -+ { "IN3R", NULL, "Line Input Micbias" }, -+ -+ { "Line Input Micbias", "off", "Line Input" }, -+ { "Line Input Micbias", "on", "Line Input with Micbias" }, -+ -+ /* Make sure MICVDD is enabled, otherwise we get noise */ -+ { "Line Input", NULL, "MICVDD" }, -+ { "Line Input with Micbias", NULL, "MICBIAS3" }, -+ -+ /* Dummy routes to check whether SPDIF RX is enabled or not */ -+ {"dummy SPDIFRX", NULL, "dummy SPDIF in"}, -+ {"AIFTX", NULL, "dummy SPDIFRX"}, -+ -+ /* -+ * Dummy routes to keep wm5102 from staying off on -+ * playback/capture if all mixers are off. -+ */ -+ { "Dummy Output", NULL, "AIF1RX1" }, -+ { "Dummy Output", NULL, "AIF1RX2" }, -+ { "AIF1TX1", NULL, "Dummy Input" }, -+ { "AIF1TX2", NULL, "Dummy Input" }, -+}; -+ -+static int rpi_cirrus_clear_flls(struct snd_soc_card *card, -+ struct snd_soc_codec *wm5102_codec) { -+ -+ int ret1, ret2; -+ -+ ret1 = snd_soc_codec_set_pll(wm5102_codec, -+ WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0); -+ ret2 = snd_soc_codec_set_pll(wm5102_codec, -+ WM5102_FLL1_REFCLK, ARIZONA_FLL_SRC_NONE, 0, 0); -+ -+ if (ret1) { -+ dev_warn(card->dev, -+ "setting FLL1 to zero failed: %d\n", ret1); -+ return ret1; -+ } -+ if (ret2) { -+ dev_warn(card->dev, -+ "setting FLL1_REFCLK to zero failed: %d\n", ret2); -+ return ret2; -+ } -+ return 0; -+} -+ -+static int rpi_cirrus_set_fll(struct snd_soc_card *card, -+ struct snd_soc_codec *wm5102_codec, unsigned int clk_freq) -+{ -+ int ret = snd_soc_codec_set_pll(wm5102_codec, -+ WM5102_FLL1, -+ ARIZONA_CLK_SRC_MCLK1, -+ WM8804_CLKOUT_HZ, -+ clk_freq); -+ if (ret) -+ dev_err(card->dev, "Failed to set FLL1 to %d: %d\n", -+ clk_freq, ret); -+ -+ usleep_range(1000, 2000); -+ return ret; -+} -+ -+static int rpi_cirrus_set_fll_refclk(struct snd_soc_card *card, -+ struct snd_soc_codec *wm5102_codec, -+ unsigned int clk_freq, unsigned int aif2_freq) -+{ -+ int ret = snd_soc_codec_set_pll(wm5102_codec, -+ WM5102_FLL1_REFCLK, -+ ARIZONA_CLK_SRC_MCLK1, -+ WM8804_CLKOUT_HZ, -+ clk_freq); -+ if (ret) { -+ dev_err(card->dev, -+ "Failed to set FLL1_REFCLK to %d: %d\n", -+ clk_freq, ret); -+ return ret; -+ } -+ -+ ret = snd_soc_codec_set_pll(wm5102_codec, -+ WM5102_FLL1, -+ ARIZONA_CLK_SRC_AIF2BCLK, -+ aif2_freq, clk_freq); -+ if (ret) -+ dev_err(card->dev, -+ "Failed to set FLL1 with Sync Clock %d to %d: %d\n", -+ aif2_freq, clk_freq, ret); -+ -+ usleep_range(1000, 2000); -+ return ret; -+} -+ -+static int rpi_cirrus_spdif_rx_enable_event(struct snd_soc_dapm_widget *w, -+ struct snd_kcontrol *kcontrol, int event) -+{ -+ struct snd_soc_card *card = w->dapm->card; -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ struct snd_soc_codec *wm5102_codec = get_wm5102_runtime(card)->codec; -+ -+ unsigned int clk_freq, aif2_freq; -+ int ret = 0; -+ -+ switch (event) { -+ case SND_SOC_DAPM_POST_PMU: -+ mutex_lock(&priv->lock); -+ -+ /* Enable sync path in case of SPDIF capture use case */ -+ -+ clk_freq = calc_sysclk(priv->card_rate); -+ aif2_freq = 64 * priv->card_rate; -+ -+ dev_dbg(card->dev, -+ "spdif_rx: changing FLL1 to use Ref Clock clk: %d spdif: %d\n", -+ clk_freq, aif2_freq); -+ -+ ret = rpi_cirrus_clear_flls(card, wm5102_codec); -+ if (ret) { -+ dev_err(card->dev, "spdif_rx: failed to clear FLLs\n"); -+ goto out; -+ } -+ -+ ret = rpi_cirrus_set_fll_refclk(card, wm5102_codec, -+ clk_freq, aif2_freq); -+ -+ if (ret) { -+ dev_err(card->dev, "spdif_rx: failed to set FLLs\n"); -+ goto out; -+ } -+ -+ /* set to negative to indicate we're doing spdif rx */ -+ priv->fll1_freq = -clk_freq; -+ priv->sync_path_enable = 1; -+ break; -+ -+ case SND_SOC_DAPM_POST_PMD: -+ mutex_lock(&priv->lock); -+ priv->sync_path_enable = 0; -+ break; -+ -+ default: -+ return 0; -+ } -+ -+out: -+ mutex_unlock(&priv->lock); -+ return ret; -+} -+ -+static int rpi_cirrus_set_bias_level(struct snd_soc_card *card, -+ struct snd_soc_dapm_context *dapm, -+ enum snd_soc_bias_level level) -+{ -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card); -+ struct snd_soc_codec *wm5102_codec = wm5102_runtime->codec; -+ -+ int ret = 0; -+ unsigned int clk_freq; -+ -+ if (dapm->dev != wm5102_runtime->codec_dai->dev) -+ return 0; -+ -+ switch (level) { -+ case SND_SOC_BIAS_PREPARE: -+ if (dapm->bias_level == SND_SOC_BIAS_ON) -+ break; -+ -+ mutex_lock(&priv->lock); -+ -+ if (!priv->sync_path_enable) { -+ clk_freq = calc_sysclk(priv->card_rate); -+ -+ dev_dbg(card->dev, -+ "set_bias: changing FLL1 from %d to %d\n", -+ priv->fll1_freq, clk_freq); -+ -+ ret = rpi_cirrus_set_fll(card, wm5102_codec, clk_freq); -+ if (ret) -+ dev_err(card->dev, -+ "set_bias: Failed to set FLL1\n"); -+ else -+ priv->fll1_freq = clk_freq; -+ } -+ mutex_unlock(&priv->lock); -+ break; -+ default: -+ break; -+ } -+ -+ return ret; -+} -+ -+static int rpi_cirrus_set_bias_level_post(struct snd_soc_card *card, -+ struct snd_soc_dapm_context *dapm, -+ enum snd_soc_bias_level level) -+{ -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card); -+ struct snd_soc_codec *wm5102_codec = wm5102_runtime->codec; -+ -+ if (dapm->dev != wm5102_runtime->codec_dai->dev) -+ return 0; -+ -+ switch (level) { -+ case SND_SOC_BIAS_STANDBY: -+ mutex_lock(&priv->lock); -+ -+ dev_dbg(card->dev, -+ "set_bias_post: changing FLL1 from %d to off\n", -+ priv->fll1_freq); -+ -+ if (rpi_cirrus_clear_flls(card, wm5102_codec)) -+ dev_err(card->dev, -+ "set_bias_post: failed to clear FLLs\n"); -+ else -+ priv->fll1_freq = 0; -+ -+ mutex_unlock(&priv->lock); -+ -+ break; -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+static int rpi_cirrus_set_wm8804_pll(struct snd_soc_card *card, -+ struct snd_soc_dai *wm8804_dai, unsigned int rate) -+{ -+ int ret; -+ -+ /* use 256fs */ -+ unsigned int clk_freq = rate * 256; -+ -+ ret = snd_soc_dai_set_pll(wm8804_dai, 0, 0, -+ WM8804_CLKOUT_HZ, clk_freq); -+ if (ret) { -+ dev_err(card->dev, -+ "Failed to set WM8804 PLL to %d: %d\n", clk_freq, ret); -+ return ret; -+ } -+ -+ /* Set MCLK as PLL Output */ -+ ret = snd_soc_dai_set_sysclk(wm8804_dai, -+ WM8804_TX_CLKSRC_PLL, clk_freq, 0); -+ if (ret) { -+ dev_err(card->dev, -+ "Failed to set MCLK as PLL Output: %d\n", ret); -+ return ret; -+ } -+ -+ return ret; -+} -+ -+static int rpi_cirrus_startup(struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_card *card = rtd->card; -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ unsigned int min_rate = min_rates[priv->min_rate_idx].value; -+ unsigned int max_rate = max_rates[priv->max_rate_idx].value; -+ -+ if (min_rate || max_rate) { -+ if (max_rate == 0) -+ max_rate = UINT_MAX; -+ -+ dev_dbg(card->dev, -+ "startup: limiting rate to %u-%u\n", -+ min_rate, max_rate); -+ -+ snd_pcm_hw_constraint_minmax(substream->runtime, -+ SNDRV_PCM_HW_PARAM_RATE, min_rate, max_rate); -+ } -+ -+ return 0; -+} -+ -+static struct snd_soc_pcm_stream rpi_cirrus_dai_link2_params = { -+ .formats = SNDRV_PCM_FMTBIT_S24_LE, -+ .channels_min = 2, -+ .channels_max = 2, -+ .rate_min = RPI_CIRRUS_DEFAULT_RATE, -+ .rate_max = RPI_CIRRUS_DEFAULT_RATE, -+}; -+ -+static int rpi_cirrus_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_card *card = rtd->card; -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ struct snd_soc_dai *bcm_i2s_dai = rtd->cpu_dai; -+ struct snd_soc_codec *wm5102_codec = rtd->codec; -+ struct snd_soc_dai *wm8804_dai = get_wm8804_runtime(card)->codec_dai; -+ -+ int ret; -+ -+ unsigned int width = snd_pcm_format_physical_width( -+ params_format(params)); -+ unsigned int rate = params_rate(params); -+ unsigned int clk_freq = calc_sysclk(rate); -+ -+ mutex_lock(&priv->lock); -+ -+ dev_dbg(card->dev, "hw_params: setting rate to %d\n", rate); -+ -+ ret = snd_soc_dai_set_bclk_ratio(bcm_i2s_dai, 2 * width); -+ if (ret) { -+ dev_err(card->dev, "set_bclk_ratio failed: %d\n", ret); -+ goto out; -+ } -+ -+ ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0x03, 0x03, 2, width); -+ if (ret) { -+ dev_err(card->dev, "set_tdm_slot failed: %d\n", ret); -+ goto out; -+ } -+ -+ /* WM8804 supports sample rates from 32k only */ -+ if (rate >= 32000) { -+ ret = rpi_cirrus_set_wm8804_pll(card, wm8804_dai, rate); -+ if (ret) -+ goto out; -+ } -+ -+ ret = snd_soc_codec_set_sysclk(wm5102_codec, -+ ARIZONA_CLK_SYSCLK, -+ ARIZONA_CLK_SRC_FLL1, -+ clk_freq, -+ SND_SOC_CLOCK_IN); -+ if (ret) { -+ dev_err(card->dev, "Failed to set SYSCLK: %d\n", ret); -+ goto out; -+ } -+ -+ if ((priv->fll1_freq > 0) && (priv->fll1_freq != clk_freq)) { -+ dev_dbg(card->dev, -+ "hw_params: changing FLL1 from %d to %d\n", -+ priv->fll1_freq, clk_freq); -+ -+ if (rpi_cirrus_clear_flls(card, wm5102_codec)) { -+ dev_err(card->dev, "hw_params: failed to clear FLLs\n"); -+ goto out; -+ } -+ -+ if (rpi_cirrus_set_fll(card, wm5102_codec, clk_freq)) { -+ dev_err(card->dev, "hw_params: failed to set FLL\n"); -+ goto out; -+ } -+ -+ priv->fll1_freq = clk_freq; -+ } -+ -+ priv->card_rate = rate; -+ rpi_cirrus_dai_link2_params.rate_min = rate; -+ rpi_cirrus_dai_link2_params.rate_max = rate; -+ -+ priv->params_set |= 1 << substream->stream; -+ -+out: -+ mutex_unlock(&priv->lock); -+ -+ return ret; -+} -+ -+static int rpi_cirrus_hw_free(struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_card *card = rtd->card; -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ struct snd_soc_codec *wm5102_codec = rtd->codec; -+ int ret; -+ unsigned int old_params_set = priv->params_set; -+ -+ priv->params_set &= ~(1 << substream->stream); -+ -+ /* disable sysclk if this was the last open stream */ -+ if (priv->params_set == 0 && old_params_set) { -+ dev_dbg(card->dev, -+ "hw_free: Setting SYSCLK to Zero\n"); -+ -+ ret = snd_soc_codec_set_sysclk(wm5102_codec, -+ ARIZONA_CLK_SYSCLK, -+ ARIZONA_CLK_SRC_FLL1, -+ 0, -+ SND_SOC_CLOCK_IN); -+ if (ret) -+ dev_err(card->dev, -+ "hw_free: Failed to set SYSCLK to Zero: %d\n", -+ ret); -+ } -+ return 0; -+} -+ -+static int rpi_cirrus_init_wm5102(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_codec *codec = rtd->codec; -+ int ret; -+ -+ /* no 32kHz input, derive it from sysclk if needed */ -+ snd_soc_update_bits(codec, -+ ARIZONA_CLOCK_32K_1, ARIZONA_CLK_32K_SRC_MASK, 2); -+ -+ if (rpi_cirrus_clear_flls(rtd->card, codec)) -+ dev_warn(rtd->card->dev, -+ "init_wm5102: failed to clear FLLs\n"); -+ -+ ret = snd_soc_codec_set_sysclk(codec, -+ ARIZONA_CLK_SYSCLK, ARIZONA_CLK_SRC_FLL1, -+ 0, SND_SOC_CLOCK_IN); -+ if (ret) { -+ dev_err(rtd->card->dev, -+ "Failed to set SYSCLK to Zero: %d\n", ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int rpi_cirrus_init_wm8804(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_codec *codec = rtd->codec; -+ struct snd_soc_dai *codec_dai = rtd->codec_dai; -+ struct snd_soc_card *card = rtd->card; -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ unsigned int mask; -+ int i, ret; -+ -+ for (i = 0; i < 4; i++) { -+ mask = (i == 3) ? 0x3f : 0xff; -+ priv->iec958_status[i] = -+ snd_soc_read(codec, WM8804_SPDTX1 + i) & mask; -+ } -+ -+ /* Setup for 256fs */ -+ ret = snd_soc_dai_set_clkdiv(codec_dai, -+ WM8804_MCLK_DIV, WM8804_MCLKDIV_256FS); -+ if (ret) { -+ dev_err(card->dev, -+ "init_wm8804: Failed to set MCLK_DIV to 256fs: %d\n", -+ ret); -+ return ret; -+ } -+ -+ /* Output OSC on CLKOUT */ -+ ret = snd_soc_dai_set_sysclk(codec_dai, -+ WM8804_CLKOUT_SRC_OSCCLK, WM8804_CLKOUT_HZ, 0); -+ if (ret) -+ dev_err(card->dev, -+ "init_wm8804: Failed to set CLKOUT as OSC Frequency: %d\n", -+ ret); -+ -+ /* Init PLL with default samplerate */ -+ ret = rpi_cirrus_set_wm8804_pll(card, codec_dai, -+ RPI_CIRRUS_DEFAULT_RATE); -+ if (ret) -+ dev_err(card->dev, -+ "init_wm8804: Failed to setup PLL for %dHz: %d\n", -+ RPI_CIRRUS_DEFAULT_RATE, ret); -+ -+ return ret; -+} -+ -+static struct snd_soc_ops rpi_cirrus_ops = { -+ .startup = rpi_cirrus_startup, -+ .hw_params = rpi_cirrus_hw_params, -+ .hw_free = rpi_cirrus_hw_free, -+}; -+ -+static struct snd_soc_dai_link rpi_cirrus_dai[] = { -+ [DAI_WM5102] = { -+ .name = "WM5102", -+ .stream_name = "WM5102 AiFi", -+ .codec_dai_name = "wm5102-aif1", -+ .codec_name = "wm5102-codec", -+ .dai_fmt = SND_SOC_DAIFMT_I2S -+ | SND_SOC_DAIFMT_NB_NF -+ | SND_SOC_DAIFMT_CBM_CFM, -+ .ops = &rpi_cirrus_ops, -+ .init = rpi_cirrus_init_wm5102, -+ }, -+ [DAI_WM8804] = { -+ .name = "WM5102 SPDIF", -+ .stream_name = "SPDIF Tx/Rx", -+ .cpu_dai_name = "wm5102-aif2", -+ .codec_dai_name = "wm8804-spdif", -+ .codec_name = "wm8804.1-003b", -+ .dai_fmt = SND_SOC_DAIFMT_I2S -+ | SND_SOC_DAIFMT_NB_NF -+ | SND_SOC_DAIFMT_CBM_CFM, -+ .ignore_suspend = 1, -+ .params = &rpi_cirrus_dai_link2_params, -+ .init = rpi_cirrus_init_wm8804, -+ }, -+}; -+ -+ -+static int rpi_cirrus_late_probe(struct snd_soc_card *card) -+{ -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card); -+ struct snd_soc_pcm_runtime *wm8804_runtime = get_wm8804_runtime(card); -+ int ret; -+ -+ dev_dbg(card->dev, "iec958_bits: %02x %02x %02x %02x\n", -+ priv->iec958_status[0], -+ priv->iec958_status[1], -+ priv->iec958_status[2], -+ priv->iec958_status[3]); -+ -+ ret = snd_soc_dai_set_sysclk( -+ wm5102_runtime->codec_dai, ARIZONA_CLK_SYSCLK, 0, 0); -+ if (ret) { -+ dev_err(card->dev, -+ "Failed to set WM5102 codec dai clk domain: %d\n", ret); -+ return ret; -+ } -+ -+ ret = snd_soc_dai_set_sysclk( -+ wm8804_runtime->cpu_dai, ARIZONA_CLK_SYSCLK, 0, 0); -+ if (ret) -+ dev_err(card->dev, -+ "Failed to set WM8804 codec dai clk domain: %d\n", ret); -+ -+ return ret; -+} -+ -+/* audio machine driver */ -+static struct snd_soc_card rpi_cirrus_card = { -+ .name = "RPi-Cirrus", -+ .driver_name = "RPiCirrus", -+ .owner = THIS_MODULE, -+ .dai_link = rpi_cirrus_dai, -+ .num_links = ARRAY_SIZE(rpi_cirrus_dai), -+ .late_probe = rpi_cirrus_late_probe, -+ .controls = rpi_cirrus_controls, -+ .num_controls = ARRAY_SIZE(rpi_cirrus_controls), -+ .dapm_widgets = rpi_cirrus_dapm_widgets, -+ .num_dapm_widgets = ARRAY_SIZE(rpi_cirrus_dapm_widgets), -+ .dapm_routes = rpi_cirrus_dapm_routes, -+ .num_dapm_routes = ARRAY_SIZE(rpi_cirrus_dapm_routes), -+ .set_bias_level = rpi_cirrus_set_bias_level, -+ .set_bias_level_post = rpi_cirrus_set_bias_level_post, -+}; -+ -+static int rpi_cirrus_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct rpi_cirrus_priv *priv; -+ struct device_node *i2s_node; -+ -+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->min_rate_idx = 1; /* min samplerate 32kHz */ -+ priv->card_rate = RPI_CIRRUS_DEFAULT_RATE; -+ -+ mutex_init(&priv->lock); -+ -+ snd_soc_card_set_drvdata(&rpi_cirrus_card, priv); -+ -+ if (!pdev->dev.of_node) -+ return -ENODEV; -+ -+ i2s_node = of_parse_phandle( -+ pdev->dev.of_node, "i2s-controller", 0); -+ if (!i2s_node) { -+ dev_err(&pdev->dev, "i2s-controller missing in DT\n"); -+ return -ENODEV; -+ } -+ -+ rpi_cirrus_dai[DAI_WM5102].cpu_of_node = i2s_node; -+ rpi_cirrus_dai[DAI_WM5102].platform_of_node = i2s_node; -+ -+ rpi_cirrus_card.dev = &pdev->dev; -+ -+ ret = devm_snd_soc_register_card(&pdev->dev, &rpi_cirrus_card); -+ if (ret) { -+ if (ret == -EPROBE_DEFER) -+ dev_dbg(&pdev->dev, -+ "register card requested probe deferral\n"); -+ else -+ dev_err(&pdev->dev, -+ "Failed to register card: %d\n", ret); -+ } -+ -+ return ret; -+} -+ -+static const struct of_device_id rpi_cirrus_of_match[] = { -+ { .compatible = "wlf,rpi-cirrus", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, rpi_cirrus_of_match); -+ -+static struct platform_driver rpi_cirrus_driver = { -+ .driver = { -+ .name = "snd-rpi-cirrus", -+ .of_match_table = of_match_ptr(rpi_cirrus_of_match), -+ }, -+ .probe = rpi_cirrus_probe, -+}; -+ -+module_platform_driver(rpi_cirrus_driver); -+ -+MODULE_AUTHOR("Matthias Reichl "); -+MODULE_DESCRIPTION("ASoC driver for Cirrus Logic Audio Card"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/brcm2708/patches-4.9/0148-sound-Suppress-error-message-about-deferrals.patch b/target/linux/brcm2708/patches-4.9/0148-sound-Suppress-error-message-about-deferrals.patch new file mode 100644 index 0000000000..52e36b5332 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0148-sound-Suppress-error-message-about-deferrals.patch @@ -0,0 +1,217 @@ +From 6ebd83ad7b2bff00ad3e25811c38e73bb4201b07 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 9 Feb 2017 14:40:33 +0000 +Subject: [PATCH] sound: Suppress error message about deferrals + +Since driver load deferrals are expected and will already +have resulted in a kernel message, suppress an essentially +duplicate error message from the RPi audio board drivers. + +Signed-off-by: Phil Elwell +--- + sound/soc/bcm/adau1977-adc.c | 2 +- + sound/soc/bcm/allo-piano-dac.c | 2 +- + sound/soc/bcm/digidac1-soundcard.c | 4 ++-- + sound/soc/bcm/dionaudio_loco.c | 2 +- + sound/soc/bcm/hifiberry_amp.c | 3 +-- + sound/soc/bcm/hifiberry_dac.c | 2 +- + sound/soc/bcm/hifiberry_dacplus.c | 2 +- + sound/soc/bcm/hifiberry_digi.c | 2 +- + sound/soc/bcm/iqaudio-dac.c | 5 +++-- + sound/soc/bcm/iqaudio_digi.c | 2 +- + sound/soc/bcm/justboom-dac.c | 2 +- + sound/soc/bcm/justboom-digi.c | 2 +- + sound/soc/bcm/pisound.c | 3 ++- + sound/soc/bcm/raspidac3.c | 2 +- + sound/soc/bcm/rpi-dac.c | 2 +- + sound/soc/bcm/rpi-proto.c | 3 +-- + 16 files changed, 20 insertions(+), 20 deletions(-) + +--- a/sound/soc/bcm/adau1977-adc.c ++++ b/sound/soc/bcm/adau1977-adc.c +@@ -90,7 +90,7 @@ static int snd_adau1977_adc_probe(struct + } + + ret = snd_soc_register_card(&snd_adau1977_adc); +- if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); + + return ret; +--- a/sound/soc/bcm/allo-piano-dac.c ++++ b/sound/soc/bcm/allo-piano-dac.c +@@ -109,7 +109,7 @@ static int snd_allo_piano_dac_probe(stru + } + + ret = snd_soc_register_card(&snd_allo_piano_dac); +- if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "snd_soc_register_card() failed: %d\n", ret); + +--- a/sound/soc/bcm/digidac1-soundcard.c ++++ b/sound/soc/bcm/digidac1-soundcard.c +@@ -387,9 +387,9 @@ static int digidac1_soundcard_probe(stru + } + + ret = snd_soc_register_card(&digidac1_soundcard); +- if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", +- ret); ++ ret); + + return ret; + } +--- a/sound/soc/bcm/dionaudio_loco.c ++++ b/sound/soc/bcm/dionaudio_loco.c +@@ -86,7 +86,7 @@ static int snd_rpi_dionaudio_loco_probe( + } + + ret = snd_soc_register_card(&snd_rpi_dionaudio_loco); +- if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + ret); + +--- a/sound/soc/bcm/hifiberry_amp.c ++++ b/sound/soc/bcm/hifiberry_amp.c +@@ -96,9 +96,8 @@ static int snd_rpi_hifiberry_amp_probe(s + + ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); + +- if (ret != 0) { ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); +- } + + return ret; + } +--- a/sound/soc/bcm/hifiberry_dac.c ++++ b/sound/soc/bcm/hifiberry_dac.c +@@ -90,7 +90,7 @@ static int snd_rpi_hifiberry_dac_probe(s + } + + ret = snd_soc_register_card(&snd_rpi_hifiberry_dac); +- if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); + + return ret; +--- a/sound/soc/bcm/hifiberry_dacplus.c ++++ b/sound/soc/bcm/hifiberry_dacplus.c +@@ -324,7 +324,7 @@ static int snd_rpi_hifiberry_dacplus_pro + } + + ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); +- if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "snd_soc_register_card() failed: %d\n", ret); + +--- a/sound/soc/bcm/hifiberry_digi.c ++++ b/sound/soc/bcm/hifiberry_digi.c +@@ -242,7 +242,7 @@ static int snd_rpi_hifiberry_digi_probe( + } + + ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); +- if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); + + return ret; +--- a/sound/soc/bcm/iqaudio-dac.c ++++ b/sound/soc/bcm/iqaudio-dac.c +@@ -197,8 +197,9 @@ static int snd_rpi_iqaudio_dac_probe(str + + ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); + if (ret) { +- dev_err(&pdev->dev, +- "snd_soc_register_card() failed: %d\n", ret); ++ if (ret != -EPROBE_DEFER) ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); + return ret; + } + +--- a/sound/soc/bcm/iqaudio_digi.c ++++ b/sound/soc/bcm/iqaudio_digi.c +@@ -204,7 +204,7 @@ static int snd_rpi_iqaudio_digi_probe(st + } + + ret = snd_soc_register_card(card); +- if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + ret); + +--- a/sound/soc/bcm/justboom-dac.c ++++ b/sound/soc/bcm/justboom-dac.c +@@ -128,7 +128,7 @@ static int snd_rpi_justboom_dac_probe(st + } + + ret = snd_soc_register_card(&snd_rpi_justboom_dac); +- if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "snd_soc_register_card() failed: %d\n", ret); + +--- a/sound/soc/bcm/justboom-digi.c ++++ b/sound/soc/bcm/justboom-digi.c +@@ -181,7 +181,7 @@ static int snd_rpi_justboom_digi_probe(s + } + + ret = snd_soc_register_card(&snd_rpi_justboom_digi); +- if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "snd_soc_register_card() failed: %d\n", ret); + +--- a/sound/soc/bcm/pisound.c ++++ b/sound/soc/bcm/pisound.c +@@ -1076,7 +1076,8 @@ static int pisnd_probe(struct platform_d + ret = snd_soc_register_card(&pisnd_card); + + if (ret < 0) { +- printe("snd_soc_register_card() failed: %d\n", ret); ++ if (ret != -EPROBE_DEFER) ++ printe("snd_soc_register_card() failed: %d\n", ret); + pisnd_uninit_gpio(); + kobject_put(pisnd_kobj); + pisnd_spi_uninit(); +--- a/sound/soc/bcm/raspidac3.c ++++ b/sound/soc/bcm/raspidac3.c +@@ -149,7 +149,7 @@ static int snd_rpi_raspidac3_probe(struc + } + + ret = snd_soc_register_card(&snd_rpi_raspidac3); +- if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "snd_soc_register_card() failed: %d\n", ret); + +--- a/sound/soc/bcm/rpi-dac.c ++++ b/sound/soc/bcm/rpi-dac.c +@@ -85,7 +85,7 @@ static int snd_rpi_rpi_dac_probe(struct + } + + ret = snd_soc_register_card(&snd_rpi_rpi_dac); +- if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); + + return ret; +--- a/sound/soc/bcm/rpi-proto.c ++++ b/sound/soc/bcm/rpi-proto.c +@@ -117,10 +117,9 @@ static int snd_rpi_proto_probe(struct pl + } + + ret = snd_soc_register_card(&snd_rpi_proto); +- if (ret) { ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "snd_soc_register_card() failed: %d\n", ret); +- } + + return ret; + } diff --git a/target/linux/brcm2708/patches-4.9/0149-Update-vfpmodule.c.patch b/target/linux/brcm2708/patches-4.9/0149-Update-vfpmodule.c.patch new file mode 100644 index 0000000000..16d740aafb --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0149-Update-vfpmodule.c.patch @@ -0,0 +1,137 @@ +From aa00ca3b0296c40a6b5a1ad32258d5b655a28c70 Mon Sep 17 00:00:00 2001 +From: Claggy3 +Date: Sat, 11 Feb 2017 14:00:30 +0000 +Subject: [PATCH] Update vfpmodule.c + +Christopher Alexander Tobias Schulze - May 2, 2015, 11:57 a.m. +This patch fixes a problem with VFP state save and restore related +to exception handling (panic with message "BUG: unsupported FP +instruction in kernel mode") present on VFP11 floating point units +(as used with ARM1176JZF-S CPUs, e.g. on first generation Raspberry +Pi boards). This patch was developed and discussed on + + https://github.com/raspberrypi/linux/issues/859 + +A precondition to see the crashes is that floating point exception +traps are enabled. In this case, the VFP11 might determine that a FPU +operation needs to trap at a point in time when it is not possible to +signal this to the ARM11 core any more. The VFP11 will then set the +FPEXC.EX bit and store the trapped opcode in FPINST. (In some cases, +a second opcode might have been accepted by the VFP11 before the +exception was detected and could be reported to the ARM11 - in this +case, the VFP11 also sets FPEXC.FP2V and stores the second opcode in +FPINST2.) + +If FPEXC.EX is set, the VFP11 will "bounce" the next FPU opcode issued +by the ARM11 CPU, which will be seen by the ARM11 as an undefined opcode +trap. The VFP support code examines the FPEXC.EX and FPEXC.FP2V bits +to decide what actions to take, i.e., whether to emulate the opcodes +found in FPINST and FPINST2, and whether to retry the bounced instruction. + +If a user space application has left the VFP11 in this "pending trap" +state, the next FPU opcode issued to the VFP11 might actually be the +VSTMIA operation vfp_save_state() uses to store the FPU registers +to memory (in our test cases, when building the signal stack frame). +In this case, the kernel crashes as described above. + +This patch fixes the problem by making sure that vfp_save_state() is +always entered with FPEXC.EX cleared. (The current value of FPEXC has +already been saved, so this does not corrupt the context. Clearing +FPEXC.EX has no effects on FPINST or FPINST2. Also note that many +callers already modify FPEXC by setting FPEXC.EN before invoking +vfp_save_state().) + +This patch also addresses a second problem related to FPEXC.EX: After +returning from signal handling, the kernel reloads the VFP context +from the user mode stack. However, the current code explicitly clears +both FPEXC.EX and FPEXC.FP2V during reload. As VFP11 requires these +bits to be preserved, this patch disables clearing them for VFP +implementations belonging to architecture 1. There should be no +negative side effects: the user can set both bits by executing FPU +opcodes anyway, and while user code may now place arbitrary values +into FPINST and FPINST2 (e.g., non-VFP ARM opcodes) the VFP support +code knows which instructions can be emulated, and rejects other +opcodes with "unhandled bounce" messages, so there should be no +security impact from allowing reloading FPEXC.EX and FPEXC.FP2V. + +Signed-off-by: Christopher Alexander Tobias Schulze +--- + arch/arm/vfp/vfpmodule.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) + +--- a/arch/arm/vfp/vfpmodule.c ++++ b/arch/arm/vfp/vfpmodule.c +@@ -179,8 +179,11 @@ static int vfp_notifier(struct notifier_ + * case the thread migrates to a different CPU. The + * restoring is done lazily. + */ +- if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) ++ if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) { ++ /* vfp_save_state oopses on VFP11 if EX bit set */ ++ fmxr(FPEXC, fpexc & ~FPEXC_EX); + vfp_save_state(vfp_current_hw_state[cpu], fpexc); ++ } + #endif + + /* +@@ -463,13 +466,16 @@ static int vfp_pm_suspend(void) + /* if vfp is on, then save state for resumption */ + if (fpexc & FPEXC_EN) { + pr_debug("%s: saving vfp state\n", __func__); ++ /* vfp_save_state oopses on VFP11 if EX bit set */ ++ fmxr(FPEXC, fpexc & ~FPEXC_EX); + vfp_save_state(&ti->vfpstate, fpexc); + + /* disable, just in case */ + fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); + } else if (vfp_current_hw_state[ti->cpu]) { + #ifndef CONFIG_SMP +- fmxr(FPEXC, fpexc | FPEXC_EN); ++ /* vfp_save_state oopses on VFP11 if EX bit set */ ++ fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN); + vfp_save_state(vfp_current_hw_state[ti->cpu], fpexc); + fmxr(FPEXC, fpexc); + #endif +@@ -532,7 +538,8 @@ void vfp_sync_hwstate(struct thread_info + /* + * Save the last VFP state on this CPU. + */ +- fmxr(FPEXC, fpexc | FPEXC_EN); ++ /* vfp_save_state oopses on VFP11 if EX bit set */ ++ fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN); + vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN); + fmxr(FPEXC, fpexc); + } +@@ -604,6 +611,7 @@ int vfp_restore_user_hwstate(struct user + struct vfp_hard_struct *hwstate = &thread->vfpstate.hard; + unsigned long fpexc; + int err = 0; ++ u32 fpsid = fmrx(FPSID); + + /* Disable VFP to avoid corrupting the new thread state. */ + vfp_flush_hwstate(thread); +@@ -627,8 +635,12 @@ int vfp_restore_user_hwstate(struct user + /* Ensure the VFP is enabled. */ + fpexc |= FPEXC_EN; + +- /* Ensure FPINST2 is invalid and the exception flag is cleared. */ +- fpexc &= ~(FPEXC_EX | FPEXC_FP2V); ++ /* Mask FPXEC_EX and FPEXC_FP2V if not required by VFP arch */ ++ if ((fpsid & FPSID_ARCH_MASK) != (1 << FPSID_ARCH_BIT)) { ++ /* Ensure FPINST2 is invalid and the exception flag is cleared. */ ++ fpexc &= ~(FPEXC_EX | FPEXC_FP2V); ++ } ++ + hwstate->fpexc = fpexc; + + __get_user_error(hwstate->fpinst, &ufp_exc->fpinst, err); +@@ -698,7 +710,8 @@ void kernel_neon_begin(void) + cpu = get_cpu(); + + fpexc = fmrx(FPEXC) | FPEXC_EN; +- fmxr(FPEXC, fpexc); ++ /* vfp_save_state oopses on VFP11 if EX bit set */ ++ fmxr(FPEXC, fpexc & ~FPEXC_EX); + + /* + * Save the userland NEON/VFP state. Under UP, diff --git a/target/linux/brcm2708/patches-4.9/0149-config-enable-Cirrus-Logic-Audio-Card.patch b/target/linux/brcm2708/patches-4.9/0149-config-enable-Cirrus-Logic-Audio-Card.patch deleted file mode 100644 index c9e4fd1eea..0000000000 --- a/target/linux/brcm2708/patches-4.9/0149-config-enable-Cirrus-Logic-Audio-Card.patch +++ /dev/null @@ -1,47 +0,0 @@ -From e12d55ad45094a50ff25b70d76381bc7798ea3d5 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 22 Jan 2017 12:49:37 +0100 -Subject: [PATCH] config: enable Cirrus Logic Audio Card - -Signed-off-by: Matthias Reichl ---- - arch/arm/configs/bcm2709_defconfig | 2 ++ - arch/arm/configs/bcmrpi_defconfig | 2 ++ - 2 files changed, 4 insertions(+) - ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -666,6 +666,7 @@ CONFIG_MFD_ARIZONA_SPI=m - CONFIG_MFD_WM5102=y - CONFIG_REGULATOR=y - CONFIG_REGULATOR_FIXED_VOLTAGE=m -+CONFIG_REGULATOR_ARIZONA=m - CONFIG_MEDIA_SUPPORT=m - CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -@@ -872,6 +873,7 @@ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m - CONFIG_SND_BCM2708_SOC_RPI_DAC=m - CONFIG_SND_BCM2708_SOC_RPI_PROTO=m - CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -660,6 +660,7 @@ CONFIG_MFD_ARIZONA_SPI=m - CONFIG_MFD_WM5102=y - CONFIG_REGULATOR=y - CONFIG_REGULATOR_FIXED_VOLTAGE=m -+CONFIG_REGULATOR_ARIZONA=m - CONFIG_MEDIA_SUPPORT=m - CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -@@ -866,6 +867,7 @@ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m - CONFIG_SND_BCM2708_SOC_RPI_DAC=m - CONFIG_SND_BCM2708_SOC_RPI_PROTO=m - CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m diff --git a/target/linux/brcm2708/patches-4.9/0150-dwc_otg-fix-summarize-urb-actual_length-for-isochron.patch b/target/linux/brcm2708/patches-4.9/0150-dwc_otg-fix-summarize-urb-actual_length-for-isochron.patch new file mode 100644 index 0000000000..295db595ca --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0150-dwc_otg-fix-summarize-urb-actual_length-for-isochron.patch @@ -0,0 +1,28 @@ +From f9efb72c44da2cce9cceca01c8f6118ec1605c69 Mon Sep 17 00:00:00 2001 +From: Martin Cerveny +Date: Mon, 13 Feb 2017 17:23:47 +0100 +Subject: [PATCH] dwc_otg: fix summarize urb->actual_length for isochronous + transfers + +Kernel does not copy input data of ISO transfers to userspace +if actual_length is set only in ISO transfers and not summarized +in urb->actual_length. Fixes raspberrypi/linux#903 +--- + drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c +@@ -334,10 +334,12 @@ static int _complete(dwc_otg_hcd_t * hcd + int i; + + urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb); ++ urb->actual_length = 0; + for (i = 0; i < urb->number_of_packets; ++i) { + urb->iso_frame_desc[i].actual_length = + dwc_otg_hcd_urb_get_iso_desc_actual_length + (dwc_otg_urb, i); ++ urb->actual_length += urb->iso_frame_desc[i].actual_length; + urb->iso_frame_desc[i].status = + dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i); + } diff --git a/target/linux/brcm2708/patches-4.9/0150-gpio_mem-Remove-unnecessary-dev_info-output-1830.patch b/target/linux/brcm2708/patches-4.9/0150-gpio_mem-Remove-unnecessary-dev_info-output-1830.patch deleted file mode 100644 index 19d23fc630..0000000000 --- a/target/linux/brcm2708/patches-4.9/0150-gpio_mem-Remove-unnecessary-dev_info-output-1830.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 6a2c90127ab305604fa51f30bce4f23179fa4b63 Mon Sep 17 00:00:00 2001 -From: JamesH65 -Date: Mon, 6 Feb 2017 15:24:47 +0000 -Subject: [PATCH] gpio_mem: Remove unnecessary dev_info output (#1830) - -The open function was spamming syslog every time -called, so have removed call completely. ---- - drivers/char/broadcom/bcm2835-gpiomem.c | 2 -- - 1 file changed, 2 deletions(-) - ---- a/drivers/char/broadcom/bcm2835-gpiomem.c -+++ b/drivers/char/broadcom/bcm2835-gpiomem.c -@@ -76,8 +76,6 @@ static int bcm2835_gpiomem_open(struct i - int dev = iminor(inode); - int ret = 0; - -- dev_info(inst->dev, "gpiomem device opened."); -- - if (dev != DEVICE_MINOR) { - dev_err(inst->dev, "Unknown minor device: %d", dev); - ret = -ENXIO; diff --git a/target/linux/brcm2708/patches-4.9/0151-clk-bcm2835-Fix-fixed_divider-of-pllh_aux.patch b/target/linux/brcm2708/patches-4.9/0151-clk-bcm2835-Fix-fixed_divider-of-pllh_aux.patch new file mode 100644 index 0000000000..82f462847b --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0151-clk-bcm2835-Fix-fixed_divider-of-pllh_aux.patch @@ -0,0 +1,27 @@ +From b8ded4dca34feafd33f22eff47d19b17b7dd83f4 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Tue, 22 Nov 2016 12:45:28 -0800 +Subject: [PATCH] clk: bcm2835: Fix ->fixed_divider of pllh_aux + +There is no fixed divider on pllh_aux. + +Signed-off-by: Boris Brezillon +Signed-off-by: Eric Anholt +Reviewed-by: Eric Anholt +Signed-off-by: Stephen Boyd +(cherry picked from commit f2a46926aba1f0c33944901d2420a6a887455ddc) +--- + drivers/clk/bcm/clk-bcm2835.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -1607,7 +1607,7 @@ static const struct bcm2835_clk_desc clk + .a2w_reg = A2W_PLLH_AUX, + .load_mask = CM_PLLH_LOADAUX, + .hold_mask = 0, +- .fixed_divider = 10), ++ .fixed_divider = 1), + [BCM2835_PLLH_PIX] = REGISTER_PLL_DIV( + .name = "pllh_pix", + .source_pll = "pllh", diff --git a/target/linux/brcm2708/patches-4.9/0152-clk-bcm-Support-rate-change-propagation-on-bcm2835-c.patch b/target/linux/brcm2708/patches-4.9/0152-clk-bcm-Support-rate-change-propagation-on-bcm2835-c.patch new file mode 100644 index 0000000000..448b0375b3 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0152-clk-bcm-Support-rate-change-propagation-on-bcm2835-c.patch @@ -0,0 +1,124 @@ +From 2988239956fddb3fb808cfb50fa8d4e68b893f3d Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 1 Dec 2016 22:00:19 +0100 +Subject: [PATCH] clk: bcm: Support rate change propagation on bcm2835 clocks + +Some peripheral clocks, like the VEC (Video EnCoder) clock need to be set +to a precise rate (in our case 108MHz). With the current implementation, +where peripheral clocks are not allowed to forward rate change requests +to their parents, it is impossible to match this requirement unless the +bootloader has configured things correctly, or a specific rate has been +assigned through the DT (with the assigned-clk-rates property). + +Add a new field to struct bcm2835_clock_data to specify which parent +clocks accept rate change propagation, and support set rate propagation +in bcm2835_clock_determine_rate(). + +Signed-off-by: Boris Brezillon +Reviewed-by: Eric Anholt +Signed-off-by: Stephen Boyd +(cherry picked from commit 155e8b3b0ee320ae866b97dd31eba8a1f080a772) +--- + drivers/clk/bcm/clk-bcm2835.c | 67 ++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 63 insertions(+), 4 deletions(-) + +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -436,6 +436,9 @@ struct bcm2835_clock_data { + const char *const *parents; + int num_mux_parents; + ++ /* Bitmap encoding which parents accept rate change propagation. */ ++ unsigned int set_rate_parent; ++ + u32 ctl_reg; + u32 div_reg; + +@@ -1017,10 +1020,60 @@ bcm2835_clk_is_pllc(struct clk_hw *hw) + return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0; + } + ++static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw, ++ int parent_idx, ++ unsigned long rate, ++ u32 *div, ++ unsigned long *prate) ++{ ++ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); ++ struct bcm2835_cprman *cprman = clock->cprman; ++ const struct bcm2835_clock_data *data = clock->data; ++ unsigned long best_rate; ++ u32 curdiv, mindiv, maxdiv; ++ struct clk_hw *parent; ++ ++ parent = clk_hw_get_parent_by_index(hw, parent_idx); ++ ++ if (!(BIT(parent_idx) & data->set_rate_parent)) { ++ *prate = clk_hw_get_rate(parent); ++ *div = bcm2835_clock_choose_div(hw, rate, *prate, true); ++ ++ return bcm2835_clock_rate_from_divisor(clock, *prate, ++ *div); ++ } ++ ++ if (data->frac_bits) ++ dev_warn(cprman->dev, ++ "frac bits are not used when propagating rate change"); ++ ++ /* clamp to min divider of 2 if we're dealing with a mash clock */ ++ mindiv = data->is_mash_clock ? 2 : 1; ++ maxdiv = BIT(data->int_bits) - 1; ++ ++ /* TODO: Be smart, and only test a subset of the available divisors. */ ++ for (curdiv = mindiv; curdiv <= maxdiv; curdiv++) { ++ unsigned long tmp_rate; ++ ++ tmp_rate = clk_hw_round_rate(parent, rate * curdiv); ++ tmp_rate /= curdiv; ++ if (curdiv == mindiv || ++ (tmp_rate > best_rate && tmp_rate <= rate)) ++ best_rate = tmp_rate; ++ ++ if (best_rate == rate) ++ break; ++ } ++ ++ *div = curdiv << CM_DIV_FRAC_BITS; ++ *prate = curdiv * best_rate; ++ ++ return best_rate; ++} ++ + static int bcm2835_clock_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) + { +- struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); + struct clk_hw *parent, *best_parent = NULL; + bool current_parent_is_pllc; + unsigned long rate, best_rate = 0; +@@ -1048,9 +1101,8 @@ static int bcm2835_clock_determine_rate( + if (bcm2835_clk_is_pllc(parent) && !current_parent_is_pllc) + continue; + +- prate = clk_hw_get_rate(parent); +- div = bcm2835_clock_choose_div(hw, req->rate, prate, true); +- rate = bcm2835_clock_rate_from_divisor(clock, prate, div); ++ rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate, ++ &div, &prate); + if (rate > best_rate && rate <= req->rate) { + best_parent = parent; + best_prate = prate; +@@ -1271,6 +1323,13 @@ static struct clk_hw *bcm2835_register_c + if ((cprman_read(cprman, data->ctl_reg) & CM_ENABLE) == 0) + init.flags &= ~CLK_IS_CRITICAL; + ++ /* ++ * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate ++ * rate changes on at least of the parents. ++ */ ++ if (data->set_rate_parent) ++ init.flags |= CLK_SET_RATE_PARENT; ++ + if (data->is_vpu_clock) { + init.ops = &bcm2835_vpu_clock_clk_ops; + } else { diff --git a/target/linux/brcm2708/patches-4.9/0153-clk-bcm-Allow-rate-change-propagation-to-PLLH_AUX-on.patch b/target/linux/brcm2708/patches-4.9/0153-clk-bcm-Allow-rate-change-propagation-to-PLLH_AUX-on.patch new file mode 100644 index 0000000000..ed082abaa5 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0153-clk-bcm-Allow-rate-change-propagation-to-PLLH_AUX-on.patch @@ -0,0 +1,35 @@ +From 5209e1b8f78fd1184f25cf19cf0daa58f4ad6599 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 1 Dec 2016 22:00:20 +0100 +Subject: [PATCH] clk: bcm: Allow rate change propagation to PLLH_AUX on VEC + clock + +The VEC clock requires needs to be set at exactly 108MHz. Allow rate +change propagation on PLLH_AUX to match this requirement wihtout +impacting other IPs (PLLH is currently only used by the HDMI encoder, +which cannot be enabled when the VEC encoder is enabled). + +Signed-off-by: Boris Brezillon +Reviewed-by: Eric Anholt +Signed-off-by: Stephen Boyd +(cherry picked from commit d86d46af84855403c00018be1c3e7bc190f2a6cd) +--- + drivers/clk/bcm/clk-bcm2835.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -1870,7 +1870,12 @@ static const struct bcm2835_clk_desc clk + .ctl_reg = CM_VECCTL, + .div_reg = CM_VECDIV, + .int_bits = 4, +- .frac_bits = 0), ++ .frac_bits = 0, ++ /* ++ * Allow rate change propagation only on PLLH_AUX which is ++ * assigned index 7 in the parent array. ++ */ ++ .set_rate_parent = BIT(7)), + + /* dsi clocks */ + [BCM2835_CLOCK_DSI0E] = REGISTER_PER_CLK( diff --git a/target/linux/brcm2708/patches-4.9/0154-clk-bcm-Fix-maybe-uninitialized-warning-in-bcm2835_c.patch b/target/linux/brcm2708/patches-4.9/0154-clk-bcm-Fix-maybe-uninitialized-warning-in-bcm2835_c.patch new file mode 100644 index 0000000000..01e29775b9 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0154-clk-bcm-Fix-maybe-uninitialized-warning-in-bcm2835_c.patch @@ -0,0 +1,29 @@ +From 9db88c2a81a12eb2b2953ee1f9090624fcc47dab Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Mon, 12 Dec 2016 09:00:53 +0100 +Subject: [PATCH] clk: bcm: Fix 'maybe-uninitialized' warning in + bcm2835_clock_choose_div_and_prate() + +best_rate is reported as potentially uninitialized by gcc. + +Signed-off-by: Boris Brezillon +Fixes: 155e8b3b0ee3 ("clk: bcm: Support rate change propagation on bcm2835 clocks") +Reported-by: Stephen Rothwell +Reviewed-by: Eric Anholt +Signed-off-by: Stephen Boyd +(cherry picked from commit 2aab7a2055a1705c9e30920d95a596226999eb21) +--- + drivers/clk/bcm/clk-bcm2835.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -1029,7 +1029,7 @@ static unsigned long bcm2835_clock_choos + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); + struct bcm2835_cprman *cprman = clock->cprman; + const struct bcm2835_clock_data *data = clock->data; +- unsigned long best_rate; ++ unsigned long best_rate = 0; + u32 curdiv, mindiv, maxdiv; + struct clk_hw *parent; + diff --git a/target/linux/brcm2708/patches-4.9/0155-clk-bcm2835-Don-t-rate-change-PLLs-on-behalf-of-DSI-.patch b/target/linux/brcm2708/patches-4.9/0155-clk-bcm2835-Don-t-rate-change-PLLs-on-behalf-of-DSI-.patch new file mode 100644 index 0000000000..154e061155 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0155-clk-bcm2835-Don-t-rate-change-PLLs-on-behalf-of-DSI-.patch @@ -0,0 +1,172 @@ +From 999db52750c062708532e1357ea3942cc619794f Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Wed, 18 Jan 2017 07:31:55 +1100 +Subject: [PATCH] clk: bcm2835: Don't rate change PLLs on behalf of DSI PLL + dividers. + +Our core PLLs are intended to be configured once and left alone. With +the SET_RATE_PARENT, asking to set the PLLD_DSI1 clock rate would +change PLLD just to get closer to the requested DSI clock, thus +changing PLLD_PER, the UART and ethernet PHY clock rates downstream of +it, and breaking ethernet. + +We *do* want PLLH to change so that PLLH_AUX can be exactly the value +we want, though. Thus, we need to have a per-divider policy of +whether to pass rate changes up. + +Signed-off-by: Eric Anholt +Signed-off-by: Stephen Boyd +(cherry picked from commit 55486091bd1e1c5ed28c43c0d6b3392468a9adb5) +--- + drivers/clk/bcm/clk-bcm2835.c | 42 ++++++++++++++++++++++++++++-------------- + 1 file changed, 28 insertions(+), 14 deletions(-) + +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -428,6 +428,7 @@ struct bcm2835_pll_divider_data { + u32 load_mask; + u32 hold_mask; + u32 fixed_divider; ++ u32 flags; + }; + + struct bcm2835_clock_data { +@@ -1252,7 +1253,7 @@ bcm2835_register_pll_divider(struct bcm2 + init.num_parents = 1; + init.name = divider_name; + init.ops = &bcm2835_pll_divider_clk_ops; +- init.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED; ++ init.flags = data->flags | CLK_IGNORE_UNUSED; + + divider = devm_kzalloc(cprman->dev, sizeof(*divider), GFP_KERNEL); + if (!divider) +@@ -1475,7 +1476,8 @@ static const struct bcm2835_clk_desc clk + .a2w_reg = A2W_PLLA_CORE, + .load_mask = CM_PLLA_LOADCORE, + .hold_mask = CM_PLLA_HOLDCORE, +- .fixed_divider = 1), ++ .fixed_divider = 1, ++ .flags = CLK_SET_RATE_PARENT), + [BCM2835_PLLA_PER] = REGISTER_PLL_DIV( + .name = "plla_per", + .source_pll = "plla", +@@ -1483,7 +1485,8 @@ static const struct bcm2835_clk_desc clk + .a2w_reg = A2W_PLLA_PER, + .load_mask = CM_PLLA_LOADPER, + .hold_mask = CM_PLLA_HOLDPER, +- .fixed_divider = 1), ++ .fixed_divider = 1, ++ .flags = CLK_SET_RATE_PARENT), + [BCM2835_PLLA_DSI0] = REGISTER_PLL_DIV( + .name = "plla_dsi0", + .source_pll = "plla", +@@ -1499,7 +1502,8 @@ static const struct bcm2835_clk_desc clk + .a2w_reg = A2W_PLLA_CCP2, + .load_mask = CM_PLLA_LOADCCP2, + .hold_mask = CM_PLLA_HOLDCCP2, +- .fixed_divider = 1), ++ .fixed_divider = 1, ++ .flags = CLK_SET_RATE_PARENT), + + /* PLLB is used for the ARM's clock. */ + [BCM2835_PLLB] = REGISTER_PLL( +@@ -1523,7 +1527,8 @@ static const struct bcm2835_clk_desc clk + .a2w_reg = A2W_PLLB_ARM, + .load_mask = CM_PLLB_LOADARM, + .hold_mask = CM_PLLB_HOLDARM, +- .fixed_divider = 1), ++ .fixed_divider = 1, ++ .flags = CLK_SET_RATE_PARENT), + + /* + * PLLC is the core PLL, used to drive the core VPU clock. +@@ -1552,7 +1557,8 @@ static const struct bcm2835_clk_desc clk + .a2w_reg = A2W_PLLC_CORE0, + .load_mask = CM_PLLC_LOADCORE0, + .hold_mask = CM_PLLC_HOLDCORE0, +- .fixed_divider = 1), ++ .fixed_divider = 1, ++ .flags = CLK_SET_RATE_PARENT), + [BCM2835_PLLC_CORE1] = REGISTER_PLL_DIV( + .name = "pllc_core1", + .source_pll = "pllc", +@@ -1560,7 +1566,8 @@ static const struct bcm2835_clk_desc clk + .a2w_reg = A2W_PLLC_CORE1, + .load_mask = CM_PLLC_LOADCORE1, + .hold_mask = CM_PLLC_HOLDCORE1, +- .fixed_divider = 1), ++ .fixed_divider = 1, ++ .flags = CLK_SET_RATE_PARENT), + [BCM2835_PLLC_CORE2] = REGISTER_PLL_DIV( + .name = "pllc_core2", + .source_pll = "pllc", +@@ -1568,7 +1575,8 @@ static const struct bcm2835_clk_desc clk + .a2w_reg = A2W_PLLC_CORE2, + .load_mask = CM_PLLC_LOADCORE2, + .hold_mask = CM_PLLC_HOLDCORE2, +- .fixed_divider = 1), ++ .fixed_divider = 1, ++ .flags = CLK_SET_RATE_PARENT), + [BCM2835_PLLC_PER] = REGISTER_PLL_DIV( + .name = "pllc_per", + .source_pll = "pllc", +@@ -1576,7 +1584,8 @@ static const struct bcm2835_clk_desc clk + .a2w_reg = A2W_PLLC_PER, + .load_mask = CM_PLLC_LOADPER, + .hold_mask = CM_PLLC_HOLDPER, +- .fixed_divider = 1), ++ .fixed_divider = 1, ++ .flags = CLK_SET_RATE_PARENT), + + /* + * PLLD is the display PLL, used to drive DSI display panels. +@@ -1605,7 +1614,8 @@ static const struct bcm2835_clk_desc clk + .a2w_reg = A2W_PLLD_CORE, + .load_mask = CM_PLLD_LOADCORE, + .hold_mask = CM_PLLD_HOLDCORE, +- .fixed_divider = 1), ++ .fixed_divider = 1, ++ .flags = CLK_SET_RATE_PARENT), + [BCM2835_PLLD_PER] = REGISTER_PLL_DIV( + .name = "plld_per", + .source_pll = "plld", +@@ -1613,7 +1623,8 @@ static const struct bcm2835_clk_desc clk + .a2w_reg = A2W_PLLD_PER, + .load_mask = CM_PLLD_LOADPER, + .hold_mask = CM_PLLD_HOLDPER, +- .fixed_divider = 1), ++ .fixed_divider = 1, ++ .flags = CLK_SET_RATE_PARENT), + [BCM2835_PLLD_DSI0] = REGISTER_PLL_DIV( + .name = "plld_dsi0", + .source_pll = "plld", +@@ -1658,7 +1669,8 @@ static const struct bcm2835_clk_desc clk + .a2w_reg = A2W_PLLH_RCAL, + .load_mask = CM_PLLH_LOADRCAL, + .hold_mask = 0, +- .fixed_divider = 10), ++ .fixed_divider = 10, ++ .flags = CLK_SET_RATE_PARENT), + [BCM2835_PLLH_AUX] = REGISTER_PLL_DIV( + .name = "pllh_aux", + .source_pll = "pllh", +@@ -1666,7 +1678,8 @@ static const struct bcm2835_clk_desc clk + .a2w_reg = A2W_PLLH_AUX, + .load_mask = CM_PLLH_LOADAUX, + .hold_mask = 0, +- .fixed_divider = 1), ++ .fixed_divider = 1, ++ .flags = CLK_SET_RATE_PARENT), + [BCM2835_PLLH_PIX] = REGISTER_PLL_DIV( + .name = "pllh_pix", + .source_pll = "pllh", +@@ -1674,7 +1687,8 @@ static const struct bcm2835_clk_desc clk + .a2w_reg = A2W_PLLH_PIX, + .load_mask = CM_PLLH_LOADPIX, + .hold_mask = 0, +- .fixed_divider = 10), ++ .fixed_divider = 10, ++ .flags = CLK_SET_RATE_PARENT), + + /* the clocks */ + diff --git a/target/linux/brcm2708/patches-4.9/0156-clk-bcm2835-Register-the-DSI0-DSI1-pixel-clocks.patch b/target/linux/brcm2708/patches-4.9/0156-clk-bcm2835-Register-the-DSI0-DSI1-pixel-clocks.patch new file mode 100644 index 0000000000..24e8aedbdc --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0156-clk-bcm2835-Register-the-DSI0-DSI1-pixel-clocks.patch @@ -0,0 +1,238 @@ +From 876f8ef32ec09fb566cc6ecdf4c96a8348f135b6 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Wed, 18 Jan 2017 07:31:56 +1100 +Subject: [PATCH] clk: bcm2835: Register the DSI0/DSI1 pixel clocks. + +The DSI pixel clocks are muxed from clocks generated in the analog phy +by the DSI driver. In order to set them as parents, we need to do the +same name lookup dance on them as we do for our root oscillator. + +Signed-off-by: Eric Anholt +Signed-off-by: Stephen Boyd +(cherry picked from commit 8a39e9fa578229fd4604266c6ebb1a3a77d7994c) +--- + .../bindings/clock/brcm,bcm2835-cprman.txt | 15 ++- + drivers/clk/bcm/clk-bcm2835.c | 121 +++++++++++++++++++-- + include/dt-bindings/clock/bcm2835.h | 2 + + 3 files changed, 125 insertions(+), 13 deletions(-) + +--- a/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt ++++ b/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt +@@ -16,7 +16,20 @@ Required properties: + - #clock-cells: Should be <1>. The permitted clock-specifier values can be + found in include/dt-bindings/clock/bcm2835.h + - reg: Specifies base physical address and size of the registers +-- clocks: The external oscillator clock phandle ++- clocks: phandles to the parent clocks used as input to the module, in ++ the following order: ++ ++ - External oscillator ++ - DSI0 byte clock ++ - DSI0 DDR2 clock ++ - DSI0 DDR clock ++ - DSI1 byte clock ++ - DSI1 DDR2 clock ++ - DSI1 DDR clock ++ ++ Only external oscillator is required. The DSI clocks may ++ not be present, in which case their children will be ++ unusable. + + Example: + +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -297,11 +297,32 @@ + #define LOCK_TIMEOUT_NS 100000000 + #define BCM2835_MAX_FB_RATE 1750000000u + ++/* ++ * Names of clocks used within the driver that need to be replaced ++ * with an external parent's name. This array is in the order that ++ * the clocks node in the DT references external clocks. ++ */ ++static const char *const cprman_parent_names[] = { ++ "xosc", ++ "dsi0_byte", ++ "dsi0_ddr2", ++ "dsi0_ddr", ++ "dsi1_byte", ++ "dsi1_ddr2", ++ "dsi1_ddr", ++}; ++ + struct bcm2835_cprman { + struct device *dev; + void __iomem *regs; + spinlock_t regs_lock; /* spinlock for all clocks */ +- const char *osc_name; ++ ++ /* ++ * Real names of cprman clock parents looked up through ++ * of_clk_get_parent_name(), which will be used in the ++ * parent_names[] arrays for clock registration. ++ */ ++ const char *real_parent_names[ARRAY_SIZE(cprman_parent_names)]; + + /* Must be last */ + struct clk_hw_onecell_data onecell; +@@ -907,6 +928,9 @@ static long bcm2835_clock_rate_from_divi + const struct bcm2835_clock_data *data = clock->data; + u64 temp; + ++ if (data->int_bits == 0 && data->frac_bits == 0) ++ return parent_rate; ++ + /* + * The divisor is a 12.12 fixed point field, but only some of + * the bits are populated in any given clock. +@@ -930,7 +954,12 @@ static unsigned long bcm2835_clock_get_r + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); + struct bcm2835_cprman *cprman = clock->cprman; + const struct bcm2835_clock_data *data = clock->data; +- u32 div = cprman_read(cprman, data->div_reg); ++ u32 div; ++ ++ if (data->int_bits == 0 && data->frac_bits == 0) ++ return parent_rate; ++ ++ div = cprman_read(cprman, data->div_reg); + + return bcm2835_clock_rate_from_divisor(clock, parent_rate, div); + } +@@ -1209,7 +1238,7 @@ static struct clk_hw *bcm2835_register_p + memset(&init, 0, sizeof(init)); + + /* All of the PLLs derive from the external oscillator. */ +- init.parent_names = &cprman->osc_name; ++ init.parent_names = &cprman->real_parent_names[0]; + init.num_parents = 1; + init.name = data->name; + init.ops = &bcm2835_pll_clk_ops; +@@ -1295,18 +1324,22 @@ static struct clk_hw *bcm2835_register_c + struct bcm2835_clock *clock; + struct clk_init_data init; + const char *parents[1 << CM_SRC_BITS]; +- size_t i; ++ size_t i, j; + int ret; + + /* +- * Replace our "xosc" references with the oscillator's +- * actual name. ++ * Replace our strings referencing parent clocks with the ++ * actual clock-output-name of the parent. + */ + for (i = 0; i < data->num_mux_parents; i++) { +- if (strcmp(data->parents[i], "xosc") == 0) +- parents[i] = cprman->osc_name; +- else +- parents[i] = data->parents[i]; ++ parents[i] = data->parents[i]; ++ ++ for (j = 0; j < ARRAY_SIZE(cprman_parent_names); j++) { ++ if (strcmp(parents[i], cprman_parent_names[j]) == 0) { ++ parents[i] = cprman->real_parent_names[j]; ++ break; ++ } ++ } + } + + memset(&init, 0, sizeof(init)); +@@ -1442,6 +1475,47 @@ static const char *const bcm2835_clock_v + __VA_ARGS__) + + /* ++ * DSI parent clocks. The DSI byte/DDR/DDR2 clocks come from the DSI ++ * analog PHY. The _inv variants are generated internally to cprman, ++ * but we don't use them so they aren't hooked up. ++ */ ++static const char *const bcm2835_clock_dsi0_parents[] = { ++ "gnd", ++ "xosc", ++ "testdebug0", ++ "testdebug1", ++ "dsi0_ddr", ++ "dsi0_ddr_inv", ++ "dsi0_ddr2", ++ "dsi0_ddr2_inv", ++ "dsi0_byte", ++ "dsi0_byte_inv", ++}; ++ ++static const char *const bcm2835_clock_dsi1_parents[] = { ++ "gnd", ++ "xosc", ++ "testdebug0", ++ "testdebug1", ++ "dsi1_ddr", ++ "dsi1_ddr_inv", ++ "dsi1_ddr2", ++ "dsi1_ddr2_inv", ++ "dsi1_byte", ++ "dsi1_byte_inv", ++}; ++ ++#define REGISTER_DSI0_CLK(...) REGISTER_CLK( \ ++ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi0_parents), \ ++ .parents = bcm2835_clock_dsi0_parents, \ ++ __VA_ARGS__) ++ ++#define REGISTER_DSI1_CLK(...) REGISTER_CLK( \ ++ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi1_parents), \ ++ .parents = bcm2835_clock_dsi1_parents, \ ++ __VA_ARGS__) ++ ++/* + * the real definition of all the pll, pll_dividers and clocks + * these make use of the above REGISTER_* macros + */ +@@ -1904,6 +1978,18 @@ static const struct bcm2835_clk_desc clk + .div_reg = CM_DSI1EDIV, + .int_bits = 4, + .frac_bits = 8), ++ [BCM2835_CLOCK_DSI0P] = REGISTER_DSI0_CLK( ++ .name = "dsi0p", ++ .ctl_reg = CM_DSI0PCTL, ++ .div_reg = CM_DSI0PDIV, ++ .int_bits = 0, ++ .frac_bits = 0), ++ [BCM2835_CLOCK_DSI1P] = REGISTER_DSI1_CLK( ++ .name = "dsi1p", ++ .ctl_reg = CM_DSI1PCTL, ++ .div_reg = CM_DSI1PDIV, ++ .int_bits = 0, ++ .frac_bits = 0), + + /* the gates */ + +@@ -1962,8 +2048,19 @@ static int bcm2835_clk_probe(struct plat + if (IS_ERR(cprman->regs)) + return PTR_ERR(cprman->regs); + +- cprman->osc_name = of_clk_get_parent_name(dev->of_node, 0); +- if (!cprman->osc_name) ++ memcpy(cprman->real_parent_names, cprman_parent_names, ++ sizeof(cprman_parent_names)); ++ of_clk_parent_fill(dev->of_node, cprman->real_parent_names, ++ ARRAY_SIZE(cprman_parent_names)); ++ ++ /* ++ * Make sure the external oscillator has been registered. ++ * ++ * The other (DSI) clocks are not present on older device ++ * trees, which we still need to support for backwards ++ * compatibility. ++ */ ++ if (!cprman->real_parent_names[0]) + return -ENODEV; + + platform_set_drvdata(pdev, cprman); +--- a/include/dt-bindings/clock/bcm2835.h ++++ b/include/dt-bindings/clock/bcm2835.h +@@ -64,3 +64,5 @@ + #define BCM2835_CLOCK_CAM1 46 + #define BCM2835_CLOCK_DSI0E 47 + #define BCM2835_CLOCK_DSI1E 48 ++#define BCM2835_CLOCK_DSI0P 49 ++#define BCM2835_CLOCK_DSI1P 50 diff --git a/target/linux/brcm2708/patches-4.9/0157-clk-bcm2835-Add-leaf-clock-measurement-support-disab.patch b/target/linux/brcm2708/patches-4.9/0157-clk-bcm2835-Add-leaf-clock-measurement-support-disab.patch new file mode 100644 index 0000000000..16c5ec5cbf --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0157-clk-bcm2835-Add-leaf-clock-measurement-support-disab.patch @@ -0,0 +1,346 @@ +From 546bac0479e51024027f8c8820f912573643b101 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Wed, 18 Jan 2017 07:31:57 +1100 +Subject: [PATCH] clk: bcm2835: Add leaf clock measurement support, disabled by + default + +This proved incredibly useful during debugging of the DSI driver, to +see if our clocks were running at rate we requested. Let's leave it +here for the next person interacting with clocks on the platform (and +so that hopefully we can just hook it up to debugfs some day). + +Signed-off-by: Eric Anholt +Signed-off-by: Stephen Boyd +(cherry picked from commit 3f9195811d8d829556c4cd88d3f9e56a80d5ba60) +--- + drivers/clk/bcm/clk-bcm2835.c | 144 ++++++++++++++++++++++++++++++++++-------- + 1 file changed, 119 insertions(+), 25 deletions(-) + +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -98,7 +99,8 @@ + #define CM_SMIDIV 0x0b4 + /* no definition for 0x0b8 and 0x0bc */ + #define CM_TCNTCTL 0x0c0 +-#define CM_TCNTDIV 0x0c4 ++# define CM_TCNT_SRC1_SHIFT 12 ++#define CM_TCNTCNT 0x0c4 + #define CM_TECCTL 0x0c8 + #define CM_TECDIV 0x0cc + #define CM_TD0CTL 0x0d0 +@@ -338,6 +340,61 @@ static inline u32 cprman_read(struct bcm + return readl(cprman->regs + reg); + } + ++/* Does a cycle of measuring a clock through the TCNT clock, which may ++ * source from many other clocks in the system. ++ */ ++static unsigned long bcm2835_measure_tcnt_mux(struct bcm2835_cprman *cprman, ++ u32 tcnt_mux) ++{ ++ u32 osccount = 19200; /* 1ms */ ++ u32 count; ++ ktime_t timeout; ++ ++ spin_lock(&cprman->regs_lock); ++ ++ cprman_write(cprman, CM_TCNTCTL, CM_KILL); ++ ++ cprman_write(cprman, CM_TCNTCTL, ++ (tcnt_mux & CM_SRC_MASK) | ++ (tcnt_mux >> CM_SRC_BITS) << CM_TCNT_SRC1_SHIFT); ++ ++ cprman_write(cprman, CM_OSCCOUNT, osccount); ++ ++ /* do a kind delay at the start */ ++ mdelay(1); ++ ++ /* Finish off whatever is left of OSCCOUNT */ ++ timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS); ++ while (cprman_read(cprman, CM_OSCCOUNT)) { ++ if (ktime_after(ktime_get(), timeout)) { ++ dev_err(cprman->dev, "timeout waiting for OSCCOUNT\n"); ++ count = 0; ++ goto out; ++ } ++ cpu_relax(); ++ } ++ ++ /* Wait for BUSY to clear. */ ++ timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS); ++ while (cprman_read(cprman, CM_TCNTCTL) & CM_BUSY) { ++ if (ktime_after(ktime_get(), timeout)) { ++ dev_err(cprman->dev, "timeout waiting for !BUSY\n"); ++ count = 0; ++ goto out; ++ } ++ cpu_relax(); ++ } ++ ++ count = cprman_read(cprman, CM_TCNTCNT); ++ ++ cprman_write(cprman, CM_TCNTCTL, 0); ++ ++out: ++ spin_unlock(&cprman->regs_lock); ++ ++ return count * 1000; ++} ++ + static int bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base, + struct debugfs_reg32 *regs, size_t nregs, + struct dentry *dentry) +@@ -473,6 +530,8 @@ struct bcm2835_clock_data { + + bool is_vpu_clock; + bool is_mash_clock; ++ ++ u32 tcnt_mux; + }; + + struct bcm2835_gate_data { +@@ -1008,6 +1067,17 @@ static int bcm2835_clock_on(struct clk_h + CM_GATE); + spin_unlock(&cprman->regs_lock); + ++ /* Debug code to measure the clock once it's turned on to see ++ * if it's ticking at the rate we expect. ++ */ ++ if (data->tcnt_mux && false) { ++ dev_info(cprman->dev, ++ "clk %s: rate %ld, measure %ld\n", ++ data->name, ++ clk_hw_get_rate(hw), ++ bcm2835_measure_tcnt_mux(cprman, data->tcnt_mux)); ++ } ++ + return 0; + } + +@@ -1774,7 +1844,8 @@ static const struct bcm2835_clk_desc clk + .ctl_reg = CM_OTPCTL, + .div_reg = CM_OTPDIV, + .int_bits = 4, +- .frac_bits = 0), ++ .frac_bits = 0, ++ .tcnt_mux = 6), + /* + * Used for a 1Mhz clock for the system clocksource, and also used + * bythe watchdog timer and the camera pulse generator. +@@ -1808,13 +1879,15 @@ static const struct bcm2835_clk_desc clk + .ctl_reg = CM_H264CTL, + .div_reg = CM_H264DIV, + .int_bits = 4, +- .frac_bits = 8), ++ .frac_bits = 8, ++ .tcnt_mux = 1), + [BCM2835_CLOCK_ISP] = REGISTER_VPU_CLK( + .name = "isp", + .ctl_reg = CM_ISPCTL, + .div_reg = CM_ISPDIV, + .int_bits = 4, +- .frac_bits = 8), ++ .frac_bits = 8, ++ .tcnt_mux = 2), + + /* + * Secondary SDRAM clock. Used for low-voltage modes when the PLL +@@ -1825,13 +1898,15 @@ static const struct bcm2835_clk_desc clk + .ctl_reg = CM_SDCCTL, + .div_reg = CM_SDCDIV, + .int_bits = 6, +- .frac_bits = 0), ++ .frac_bits = 0, ++ .tcnt_mux = 3), + [BCM2835_CLOCK_V3D] = REGISTER_VPU_CLK( + .name = "v3d", + .ctl_reg = CM_V3DCTL, + .div_reg = CM_V3DDIV, + .int_bits = 4, +- .frac_bits = 8), ++ .frac_bits = 8, ++ .tcnt_mux = 4), + /* + * VPU clock. This doesn't have an enable bit, since it drives + * the bus for everything else, and is special so it doesn't need +@@ -1845,7 +1920,8 @@ static const struct bcm2835_clk_desc clk + .int_bits = 12, + .frac_bits = 8, + .flags = CLK_IS_CRITICAL, +- .is_vpu_clock = true), ++ .is_vpu_clock = true, ++ .tcnt_mux = 5), + + /* clocks with per parent mux */ + [BCM2835_CLOCK_AVEO] = REGISTER_PER_CLK( +@@ -1853,19 +1929,22 @@ static const struct bcm2835_clk_desc clk + .ctl_reg = CM_AVEOCTL, + .div_reg = CM_AVEODIV, + .int_bits = 4, +- .frac_bits = 0), ++ .frac_bits = 0, ++ .tcnt_mux = 38), + [BCM2835_CLOCK_CAM0] = REGISTER_PER_CLK( + .name = "cam0", + .ctl_reg = CM_CAM0CTL, + .div_reg = CM_CAM0DIV, + .int_bits = 4, +- .frac_bits = 8), ++ .frac_bits = 8, ++ .tcnt_mux = 14), + [BCM2835_CLOCK_CAM1] = REGISTER_PER_CLK( + .name = "cam1", + .ctl_reg = CM_CAM1CTL, + .div_reg = CM_CAM1DIV, + .int_bits = 4, +- .frac_bits = 8), ++ .frac_bits = 8, ++ .tcnt_mux = 15), + [BCM2835_CLOCK_DFT] = REGISTER_PER_CLK( + .name = "dft", + .ctl_reg = CM_DFTCTL, +@@ -1877,7 +1956,8 @@ static const struct bcm2835_clk_desc clk + .ctl_reg = CM_DPICTL, + .div_reg = CM_DPIDIV, + .int_bits = 4, +- .frac_bits = 8), ++ .frac_bits = 8, ++ .tcnt_mux = 17), + + /* Arasan EMMC clock */ + [BCM2835_CLOCK_EMMC] = REGISTER_PER_CLK( +@@ -1885,7 +1965,8 @@ static const struct bcm2835_clk_desc clk + .ctl_reg = CM_EMMCCTL, + .div_reg = CM_EMMCDIV, + .int_bits = 4, +- .frac_bits = 8), ++ .frac_bits = 8, ++ .tcnt_mux = 39), + + /* General purpose (GPIO) clocks */ + [BCM2835_CLOCK_GP0] = REGISTER_PER_CLK( +@@ -1894,7 +1975,8 @@ static const struct bcm2835_clk_desc clk + .div_reg = CM_GP0DIV, + .int_bits = 12, + .frac_bits = 12, +- .is_mash_clock = true), ++ .is_mash_clock = true, ++ .tcnt_mux = 20), + [BCM2835_CLOCK_GP1] = REGISTER_PER_CLK( + .name = "gp1", + .ctl_reg = CM_GP1CTL, +@@ -1902,7 +1984,8 @@ static const struct bcm2835_clk_desc clk + .int_bits = 12, + .frac_bits = 12, + .flags = CLK_IS_CRITICAL, +- .is_mash_clock = true), ++ .is_mash_clock = true, ++ .tcnt_mux = 21), + [BCM2835_CLOCK_GP2] = REGISTER_PER_CLK( + .name = "gp2", + .ctl_reg = CM_GP2CTL, +@@ -1917,40 +2000,46 @@ static const struct bcm2835_clk_desc clk + .ctl_reg = CM_HSMCTL, + .div_reg = CM_HSMDIV, + .int_bits = 4, +- .frac_bits = 8), ++ .frac_bits = 8, ++ .tcnt_mux = 22), + [BCM2835_CLOCK_PCM] = REGISTER_PER_CLK( + .name = "pcm", + .ctl_reg = CM_PCMCTL, + .div_reg = CM_PCMDIV, + .int_bits = 12, + .frac_bits = 12, +- .is_mash_clock = true), ++ .is_mash_clock = true, ++ .tcnt_mux = 23), + [BCM2835_CLOCK_PWM] = REGISTER_PER_CLK( + .name = "pwm", + .ctl_reg = CM_PWMCTL, + .div_reg = CM_PWMDIV, + .int_bits = 12, + .frac_bits = 12, +- .is_mash_clock = true), ++ .is_mash_clock = true, ++ .tcnt_mux = 24), + [BCM2835_CLOCK_SLIM] = REGISTER_PER_CLK( + .name = "slim", + .ctl_reg = CM_SLIMCTL, + .div_reg = CM_SLIMDIV, + .int_bits = 12, + .frac_bits = 12, +- .is_mash_clock = true), ++ .is_mash_clock = true, ++ .tcnt_mux = 25), + [BCM2835_CLOCK_SMI] = REGISTER_PER_CLK( + .name = "smi", + .ctl_reg = CM_SMICTL, + .div_reg = CM_SMIDIV, + .int_bits = 4, +- .frac_bits = 8), ++ .frac_bits = 8, ++ .tcnt_mux = 27), + [BCM2835_CLOCK_UART] = REGISTER_PER_CLK( + .name = "uart", + .ctl_reg = CM_UARTCTL, + .div_reg = CM_UARTDIV, + .int_bits = 10, +- .frac_bits = 12), ++ .frac_bits = 12, ++ .tcnt_mux = 28), + + /* TV encoder clock. Only operating frequency is 108Mhz. */ + [BCM2835_CLOCK_VEC] = REGISTER_PER_CLK( +@@ -1963,7 +2052,8 @@ static const struct bcm2835_clk_desc clk + * Allow rate change propagation only on PLLH_AUX which is + * assigned index 7 in the parent array. + */ +- .set_rate_parent = BIT(7)), ++ .set_rate_parent = BIT(7), ++ .tcnt_mux = 29), + + /* dsi clocks */ + [BCM2835_CLOCK_DSI0E] = REGISTER_PER_CLK( +@@ -1971,25 +2061,29 @@ static const struct bcm2835_clk_desc clk + .ctl_reg = CM_DSI0ECTL, + .div_reg = CM_DSI0EDIV, + .int_bits = 4, +- .frac_bits = 8), ++ .frac_bits = 8, ++ .tcnt_mux = 18), + [BCM2835_CLOCK_DSI1E] = REGISTER_PER_CLK( + .name = "dsi1e", + .ctl_reg = CM_DSI1ECTL, + .div_reg = CM_DSI1EDIV, + .int_bits = 4, +- .frac_bits = 8), ++ .frac_bits = 8, ++ .tcnt_mux = 19), + [BCM2835_CLOCK_DSI0P] = REGISTER_DSI0_CLK( + .name = "dsi0p", + .ctl_reg = CM_DSI0PCTL, + .div_reg = CM_DSI0PDIV, + .int_bits = 0, +- .frac_bits = 0), ++ .frac_bits = 0, ++ .tcnt_mux = 12), + [BCM2835_CLOCK_DSI1P] = REGISTER_DSI1_CLK( + .name = "dsi1p", + .ctl_reg = CM_DSI1PCTL, + .div_reg = CM_DSI1PDIV, + .int_bits = 0, +- .frac_bits = 0), ++ .frac_bits = 0, ++ .tcnt_mux = 13), + + /* the gates */ + diff --git a/target/linux/brcm2708/patches-4.9/0158-drm-panel-Add-support-for-the-Raspberry-Pi-7-Touchsc.patch b/target/linux/brcm2708/patches-4.9/0158-drm-panel-Add-support-for-the-Raspberry-Pi-7-Touchsc.patch new file mode 100644 index 0000000000..027e5c07e5 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0158-drm-panel-Add-support-for-the-Raspberry-Pi-7-Touchsc.patch @@ -0,0 +1,575 @@ +From e2d195723ec030733cdaf623c9419af5f308b230 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Tue, 26 Apr 2016 13:46:13 -0700 +Subject: [PATCH] drm/panel: Add support for the Raspberry Pi 7" Touchscreen. + +This driver communicates with the Atmel microcontroller for sequencing +the poweron of the TC358762 DSI-DPI bridge and controlling the +backlight PWM. + +The following lines are required in config.txt, to keep the firmware +from trying to bash our I2C lines and steal the DSI interrupts: + + disable_touchscreen=1 + ignore_lcd=2 + mask_gpu_interrupt1=0x1000 + +This means that the firmware won't power on the panel at boot time (no +rainbow) and the touchscreen input won't work. The native input +driver for the touchscreen still needs to be written. + +v2: Set the same default orientation as the closed source firmware + used, which is the best for viewing angle. + +Signed-off-by: Eric Anholt +--- + drivers/gpu/drm/panel/Kconfig | 8 + + drivers/gpu/drm/panel/Makefile | 1 + + .../gpu/drm/panel/panel-raspberrypi-touchscreen.c | 514 +++++++++++++++++++++ + 3 files changed, 523 insertions(+) + create mode 100644 drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c + +--- a/drivers/gpu/drm/panel/Kconfig ++++ b/drivers/gpu/drm/panel/Kconfig +@@ -52,6 +52,14 @@ config DRM_PANEL_PANASONIC_VVX10F034N00 + WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some + Xperia Z2 tablets + ++config DRM_PANEL_RASPBERRYPI_TOUCHSCREEN ++ tristate "Raspberry Pi 7-inch touchscreen panel" ++ depends on DRM_MIPI_DSI ++ help ++ Say Y here if you want to enable support for the Raspberry ++ Pi 7" Touchscreen. To compile this driver as a module, ++ choose M here. ++ + config DRM_PANEL_SAMSUNG_S6E8AA0 + tristate "Samsung S6E8AA0 DSI video mode panel" + depends on OF +--- a/drivers/gpu/drm/panel/Makefile ++++ b/drivers/gpu/drm/panel/Makefile +@@ -2,6 +2,7 @@ obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel- + obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o + obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o + obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o ++obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += panel-raspberrypi-touchscreen.o + obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o + obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o + obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o +--- /dev/null ++++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c +@@ -0,0 +1,514 @@ ++/* ++ * Copyright © 2016 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * Portions of this file (derived from panel-simple.c) are: ++ * ++ * Copyright (C) 2013, NVIDIA Corporation. All rights reserved. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sub license, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the ++ * next paragraph) shall be included in all copies or substantial portions ++ * of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ */ ++ ++/** ++ * DOC: Raspberry Pi 7" touchscreen panel driver. ++ * ++ * The 7" touchscreen consists of a DPI LCD panel, a Toshiba ++ * TC358762XBG DSI-DPI bridge, and an I2C-connected Atmel ATTINY88-MUR ++ * controlling power management, the LCD PWM, and the touchscreen. ++ * ++ * This driver presents this device as a MIPI DSI panel to the DRM ++ * driver, and should expose the touchscreen as a HID device. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* I2C registers of the Atmel microcontroller. */ ++enum REG_ADDR { ++ REG_ID = 0x80, ++ REG_PORTA, // BIT(2) for horizontal flip, BIT(3) for vertical flip ++ REG_PORTB, ++ REG_PORTC, ++ REG_PORTD, ++ REG_POWERON, ++ REG_PWM, ++ REG_DDRA, ++ REG_DDRB, ++ REG_DDRC, ++ REG_DDRD, ++ REG_TEST, ++ REG_WR_ADDRL, ++ REG_WR_ADDRH, ++ REG_READH, ++ REG_READL, ++ REG_WRITEH, ++ REG_WRITEL, ++ REG_ID2, ++}; ++ ++/* We only turn the PWM on or off, without varying values. */ ++#define RPI_TOUCHSCREEN_MAX_BRIGHTNESS 1 ++ ++/* DSI D-PHY Layer Registers */ ++#define D0W_DPHYCONTTX 0x0004 ++#define CLW_DPHYCONTRX 0x0020 ++#define D0W_DPHYCONTRX 0x0024 ++#define D1W_DPHYCONTRX 0x0028 ++#define COM_DPHYCONTRX 0x0038 ++#define CLW_CNTRL 0x0040 ++#define D0W_CNTRL 0x0044 ++#define D1W_CNTRL 0x0048 ++#define DFTMODE_CNTRL 0x0054 ++ ++/* DSI PPI Layer Registers */ ++#define PPI_STARTPPI 0x0104 ++#define PPI_BUSYPPI 0x0108 ++#define PPI_LINEINITCNT 0x0110 ++#define PPI_LPTXTIMECNT 0x0114 ++//#define PPI_LANEENABLE 0x0134 ++//#define PPI_TX_RX_TA 0x013C ++#define PPI_CLS_ATMR 0x0140 ++#define PPI_D0S_ATMR 0x0144 ++#define PPI_D1S_ATMR 0x0148 ++#define PPI_D0S_CLRSIPOCOUNT 0x0164 ++#define PPI_D1S_CLRSIPOCOUNT 0x0168 ++#define CLS_PRE 0x0180 ++#define D0S_PRE 0x0184 ++#define D1S_PRE 0x0188 ++#define CLS_PREP 0x01A0 ++#define D0S_PREP 0x01A4 ++#define D1S_PREP 0x01A8 ++#define CLS_ZERO 0x01C0 ++#define D0S_ZERO 0x01C4 ++#define D1S_ZERO 0x01C8 ++#define PPI_CLRFLG 0x01E0 ++#define PPI_CLRSIPO 0x01E4 ++#define HSTIMEOUT 0x01F0 ++#define HSTIMEOUTENABLE 0x01F4 ++ ++/* DSI Protocol Layer Registers */ ++#define DSI_STARTDSI 0x0204 ++#define DSI_BUSYDSI 0x0208 ++#define DSI_LANEENABLE 0x0210 ++# define DSI_LANEENABLE_CLOCK BIT(0) ++# define DSI_LANEENABLE_D0 BIT(1) ++# define DSI_LANEENABLE_D1 BIT(2) ++ ++#define DSI_LANESTATUS0 0x0214 ++#define DSI_LANESTATUS1 0x0218 ++#define DSI_INTSTATUS 0x0220 ++#define DSI_INTMASK 0x0224 ++#define DSI_INTCLR 0x0228 ++#define DSI_LPTXTO 0x0230 ++#define DSI_MODE 0x0260 ++#define DSI_PAYLOAD0 0x0268 ++#define DSI_PAYLOAD1 0x026C ++#define DSI_SHORTPKTDAT 0x0270 ++#define DSI_SHORTPKTREQ 0x0274 ++#define DSI_BTASTA 0x0278 ++#define DSI_BTACLR 0x027C ++ ++/* DSI General Registers */ ++#define DSIERRCNT 0x0300 ++#define DSISIGMOD 0x0304 ++ ++/* DSI Application Layer Registers */ ++#define APLCTRL 0x0400 ++#define APLSTAT 0x0404 ++#define APLERR 0x0408 ++#define PWRMOD 0x040C ++#define RDPKTLN 0x0410 ++#define PXLFMT 0x0414 ++#define MEMWRCMD 0x0418 ++ ++/* LCDC/DPI Host Registers */ ++#define LCDCTRL 0x0420 ++#define HSR 0x0424 ++#define HDISPR 0x0428 ++#define VSR 0x042C ++#define VDISPR 0x0430 ++#define VFUEN 0x0434 ++ ++/* DBI-B Host Registers */ ++#define DBIBCTRL 0x0440 ++ ++/* SPI Master Registers */ ++#define SPICMR 0x0450 ++#define SPITCR 0x0454 ++ ++/* System Controller Registers */ ++#define SYSSTAT 0x0460 ++#define SYSCTRL 0x0464 ++#define SYSPLL1 0x0468 ++#define SYSPLL2 0x046C ++#define SYSPLL3 0x0470 ++#define SYSPMCTRL 0x047C ++ ++/* GPIO Registers */ ++#define GPIOC 0x0480 ++#define GPIOO 0x0484 ++#define GPIOI 0x0488 ++ ++/* I2C Registers */ ++#define I2CCLKCTRL 0x0490 ++ ++/* Chip/Rev Registers */ ++#define IDREG 0x04A0 ++ ++/* Debug Registers */ ++#define WCMDQUEUE 0x0500 ++#define RCMDQUEUE 0x0504 ++ ++struct rpi_touchscreen { ++ struct drm_panel base; ++ struct mipi_dsi_device *dsi; ++ struct i2c_client *bridge_i2c; ++ ++ /* Version of the firmware on the bridge chip */ ++ int atmel_ver; ++}; ++ ++static const struct drm_display_mode rpi_touchscreen_modes[] = { ++ { ++ /* The DSI PLL can only integer divide from the 2Ghz ++ * PLLD, giving us few choices. We pick a divide by 3 ++ * as our DSI HS clock, giving us a pixel clock of ++ * that divided by 24 bits. Pad out HFP to get our ++ * panel to refresh at 60Hz, even if that doesn't ++ * match the datasheet. ++ */ ++#define PIXEL_CLOCK ((2000000000 / 3) / 24) ++#define VREFRESH 60 ++#define VTOTAL (480 + 7 + 2 + 21) ++#define HACT 800 ++#define HSW 2 ++#define HBP 46 ++#define HFP ((PIXEL_CLOCK / (VTOTAL * VREFRESH)) - (HACT + HSW + HBP)) ++ ++ .clock = PIXEL_CLOCK / 1000, ++ .hdisplay = HACT, ++ .hsync_start = HACT + HFP, ++ .hsync_end = HACT + HFP + HSW, ++ .htotal = HACT + HFP + HSW + HBP, ++ .vdisplay = 480, ++ .vsync_start = 480 + 7, ++ .vsync_end = 480 + 7 + 2, ++ .vtotal = VTOTAL, ++ .vrefresh = 60, ++ }, ++}; ++ ++static struct rpi_touchscreen *panel_to_ts(struct drm_panel *panel) ++{ ++ return container_of(panel, struct rpi_touchscreen, base); ++} ++ ++static u8 rpi_touchscreen_i2c_read(struct rpi_touchscreen *ts, u8 reg) ++{ ++ return i2c_smbus_read_byte_data(ts->bridge_i2c, reg); ++} ++ ++static void rpi_touchscreen_i2c_write(struct rpi_touchscreen *ts, ++ u8 reg, u8 val) ++{ ++ int ret; ++ ++ ret = i2c_smbus_write_byte_data(ts->bridge_i2c, reg, val); ++ if (ret) ++ dev_err(&ts->dsi->dev, "I2C write failed: %d\n", ret); ++} ++ ++static int rpi_touchscreen_write(struct rpi_touchscreen *ts, u16 reg, u32 val) ++{ ++#if 0 ++ /* The firmware uses LP DSI transactions like this to bring up ++ * the hardware, which should be faster than using I2C to then ++ * pass to the Toshiba. However, I was unable to get it to ++ * work. ++ */ ++ u8 msg[] = { ++ reg, ++ reg >> 8, ++ val, ++ val >> 8, ++ val >> 16, ++ val >> 24, ++ }; ++ ++ mipi_dsi_dcs_write_buffer(ts->dsi, msg, sizeof(msg)); ++#else ++ rpi_touchscreen_i2c_write(ts, REG_WR_ADDRH, reg >> 8); ++ rpi_touchscreen_i2c_write(ts, REG_WR_ADDRL, reg); ++ rpi_touchscreen_i2c_write(ts, REG_WRITEH, val >> 8); ++ rpi_touchscreen_i2c_write(ts, REG_WRITEL, val); ++#endif ++ ++ return 0; ++} ++ ++static int rpi_touchscreen_disable(struct drm_panel *panel) ++{ ++ struct rpi_touchscreen *ts = panel_to_ts(panel); ++ ++ rpi_touchscreen_i2c_write(ts, REG_PWM, 0); ++ ++ rpi_touchscreen_i2c_write(ts, REG_POWERON, 0); ++ udelay(1); ++ ++ return 0; ++} ++ ++static int rpi_touchscreen_noop(struct drm_panel *panel) ++{ ++ return 0; ++} ++ ++static int rpi_touchscreen_enable(struct drm_panel *panel) ++{ ++ struct rpi_touchscreen *ts = panel_to_ts(panel); ++ int i; ++ ++ rpi_touchscreen_i2c_write(ts, REG_POWERON, 1); ++ /* Wait for nPWRDWN to go low to indicate poweron is done. */ ++ for (i = 0; i < 100; i++) { ++ if (rpi_touchscreen_i2c_read(ts, REG_PORTB) & 1) ++ break; ++ } ++ ++ rpi_touchscreen_write(ts, DSI_LANEENABLE, ++ DSI_LANEENABLE_CLOCK | ++ DSI_LANEENABLE_D0 | ++ (ts->dsi->lanes > 1 ? DSI_LANEENABLE_D1 : 0)); ++ rpi_touchscreen_write(ts, PPI_D0S_CLRSIPOCOUNT, 0x05); ++ rpi_touchscreen_write(ts, PPI_D1S_CLRSIPOCOUNT, 0x05); ++ rpi_touchscreen_write(ts, PPI_D0S_ATMR, 0x00); ++ rpi_touchscreen_write(ts, PPI_D1S_ATMR, 0x00); ++ rpi_touchscreen_write(ts, PPI_LPTXTIMECNT, 0x03); ++ ++ rpi_touchscreen_write(ts, SPICMR, 0x00); ++ rpi_touchscreen_write(ts, LCDCTRL, 0x00100150); ++ rpi_touchscreen_write(ts, SYSCTRL, 0x040f); ++ msleep(100); ++ ++ rpi_touchscreen_write(ts, PPI_STARTPPI, 0x01); ++ rpi_touchscreen_write(ts, DSI_STARTDSI, 0x01); ++ msleep(100); ++ ++ /* Turn on the backlight. */ ++ rpi_touchscreen_i2c_write(ts, REG_PWM, 255); ++ ++ /* Default to the same orientation as the closed source ++ * firmware used for the panel. Runtime rotation ++ * configuration will be supported using VC4's plane ++ * orientation bits. ++ */ ++ rpi_touchscreen_i2c_write(ts, REG_PORTA, BIT(2)); ++ ++ return 0; ++} ++ ++static int rpi_touchscreen_get_modes(struct drm_panel *panel) ++{ ++ struct drm_connector *connector = panel->connector; ++ struct drm_device *drm = panel->drm; ++ unsigned int i, num = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(rpi_touchscreen_modes); i++) { ++ const struct drm_display_mode *m = &rpi_touchscreen_modes[i]; ++ struct drm_display_mode *mode; ++ ++ mode = drm_mode_duplicate(drm, m); ++ if (!mode) { ++ dev_err(drm->dev, "failed to add mode %ux%u@%u\n", ++ m->hdisplay, m->vdisplay, m->vrefresh); ++ continue; ++ } ++ ++ mode->type |= DRM_MODE_TYPE_DRIVER; ++ ++ if (i == 0) ++ mode->type |= DRM_MODE_TYPE_PREFERRED; ++ ++ drm_mode_set_name(mode); ++ ++ drm_mode_probed_add(connector, mode); ++ num++; ++ } ++ ++ connector->display_info.bpc = 8; ++ connector->display_info.width_mm = 154; ++ connector->display_info.height_mm = 86; ++ ++ return num; ++} ++ ++static const struct drm_panel_funcs rpi_touchscreen_funcs = { ++ .disable = rpi_touchscreen_disable, ++ .unprepare = rpi_touchscreen_noop, ++ .prepare = rpi_touchscreen_noop, ++ .enable = rpi_touchscreen_enable, ++ .get_modes = rpi_touchscreen_get_modes, ++}; ++ ++static struct i2c_client *rpi_touchscreen_get_i2c(struct device *dev, ++ const char *name) ++{ ++ struct device_node *node; ++ struct i2c_client *client; ++ ++ node = of_parse_phandle(dev->of_node, name, 0); ++ if (!node) ++ return ERR_PTR(-ENODEV); ++ ++ client = of_find_i2c_device_by_node(node); ++ ++ of_node_put(node); ++ ++ return client; ++} ++ ++static int rpi_touchscreen_dsi_probe(struct mipi_dsi_device *dsi) ++{ ++ struct device *dev = &dsi->dev; ++ struct rpi_touchscreen *ts; ++ int ret, ver; ++ ++ ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); ++ if (!ts) ++ return -ENOMEM; ++ ++ dev_set_drvdata(dev, ts); ++ ++ ts->dsi = dsi; ++ dsi->mode_flags = (MIPI_DSI_MODE_VIDEO | ++ MIPI_DSI_MODE_VIDEO_SYNC_PULSE | ++ MIPI_DSI_MODE_LPM); ++ dsi->format = MIPI_DSI_FMT_RGB888; ++ dsi->lanes = 1; ++ ++ ts->bridge_i2c = ++ rpi_touchscreen_get_i2c(dev, "raspberrypi,touchscreen-bridge"); ++ if (IS_ERR(ts->bridge_i2c)) { ++ ret = -EPROBE_DEFER; ++ return ret; ++ } ++ ++ ver = rpi_touchscreen_i2c_read(ts, REG_ID); ++ if (ver < 0) { ++ dev_err(dev, "Atmel I2C read failed: %d\n", ver); ++ return -ENODEV; ++ } ++ ++ switch (ver) { ++ case 0xde: ++ ts->atmel_ver = 1; ++ break; ++ case 0xc3: ++ ts->atmel_ver = 2; ++ break; ++ default: ++ dev_err(dev, "Unknown Atmel firmware revision: 0x%02x\n", ver); ++ return -ENODEV; ++ } ++ ++ /* Turn off at boot, so we can cleanly sequence powering on. */ ++ rpi_touchscreen_i2c_write(ts, REG_POWERON, 0); ++ ++ drm_panel_init(&ts->base); ++ ts->base.dev = dev; ++ ts->base.funcs = &rpi_touchscreen_funcs; ++ ++ ret = drm_panel_add(&ts->base); ++ if (ret < 0) ++ goto err_release_bridge; ++ ++ return mipi_dsi_attach(dsi); ++ ++err_release_bridge: ++ put_device(&ts->bridge_i2c->dev); ++ return ret; ++} ++ ++static int rpi_touchscreen_dsi_remove(struct mipi_dsi_device *dsi) ++{ ++ struct device *dev = &dsi->dev; ++ struct rpi_touchscreen *ts = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = mipi_dsi_detach(dsi); ++ if (ret < 0) { ++ dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); ++ return ret; ++ } ++ ++ drm_panel_detach(&ts->base); ++ drm_panel_remove(&ts->base); ++ ++ put_device(&ts->bridge_i2c->dev); ++ ++ return 0; ++} ++ ++static void rpi_touchscreen_dsi_shutdown(struct mipi_dsi_device *dsi) ++{ ++ struct device *dev = &dsi->dev; ++ struct rpi_touchscreen *ts = dev_get_drvdata(dev); ++ ++ rpi_touchscreen_i2c_write(ts, REG_POWERON, 0); ++} ++ ++static const struct of_device_id rpi_touchscreen_of_match[] = { ++ { .compatible = "raspberrypi,touchscreen" }, ++ { } /* sentinel */ ++}; ++MODULE_DEVICE_TABLE(of, rpi_touchscreen_of_match); ++ ++static struct mipi_dsi_driver rpi_touchscreen_driver = { ++ .driver = { ++ .name = "raspberrypi-touchscreen", ++ .of_match_table = rpi_touchscreen_of_match, ++ }, ++ .probe = rpi_touchscreen_dsi_probe, ++ .remove = rpi_touchscreen_dsi_remove, ++ .shutdown = rpi_touchscreen_dsi_shutdown, ++}; ++module_mipi_dsi_driver(rpi_touchscreen_driver); ++ ++MODULE_AUTHOR("Eric Anholt "); ++MODULE_DESCRIPTION("Raspberry Pi 7-inch touchscreen driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0159-BCM270X-Add-the-DSI-panel-to-the-defconfig.patch b/target/linux/brcm2708/patches-4.9/0159-BCM270X-Add-the-DSI-panel-to-the-defconfig.patch new file mode 100644 index 0000000000..1ba605bc39 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0159-BCM270X-Add-the-DSI-panel-to-the-defconfig.patch @@ -0,0 +1,45 @@ +From 22f86bb2d3cb5275877fc4784d2f6c4f5cc660e9 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Thu, 2 Jun 2016 12:29:45 -0700 +Subject: [PATCH] BCM270X: Add the DSI panel to the defconfig. + +Signed-off-by: Eric Anholt +--- + arch/arm/configs/bcm2709_defconfig | 2 ++ + arch/arm/configs/bcmrpi_defconfig | 2 ++ + arch/arm64/configs/bcmrpi3_defconfig | 2 ++ + 3 files changed, 6 insertions(+) + +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -833,6 +833,8 @@ CONFIG_VIDEO_OV7640=m + CONFIG_VIDEO_MT9V011=m + CONFIG_DRM=m + CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_PANEL_SIMPLE=m ++CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m + CONFIG_DRM_UDL=m + CONFIG_DRM_VC4=m + CONFIG_FB=y +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -827,6 +827,8 @@ CONFIG_VIDEO_OV7640=m + CONFIG_VIDEO_MT9V011=m + CONFIG_DRM=m + CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_PANEL_SIMPLE=m ++CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m + CONFIG_DRM_UDL=m + CONFIG_DRM_VC4=m + CONFIG_FB=y +--- a/arch/arm64/configs/bcmrpi3_defconfig ++++ b/arch/arm64/configs/bcmrpi3_defconfig +@@ -816,6 +816,8 @@ CONFIG_VIDEO_OV7640=m + CONFIG_VIDEO_MT9V011=m + CONFIG_DRM=m + CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_PANEL_SIMPLE=m ++CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m + CONFIG_DRM_UDL=m + CONFIG_DRM_VC4=m + CONFIG_FB=y diff --git a/target/linux/brcm2708/patches-4.9/0160-ARM-bcm2835-dt-Add-the-DSI-module-nodes-and-clocks.patch b/target/linux/brcm2708/patches-4.9/0160-ARM-bcm2835-dt-Add-the-DSI-module-nodes-and-clocks.patch new file mode 100644 index 0000000000..444c287eed --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0160-ARM-bcm2835-dt-Add-the-DSI-module-nodes-and-clocks.patch @@ -0,0 +1,101 @@ +From fc25cd03ca1c696dacb74d2006c0f176ce800566 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Tue, 13 Dec 2016 15:15:10 -0800 +Subject: [PATCH] ARM: bcm2835: dt: Add the DSI module nodes and clocks. + +The modules stay disabled by default, and if you want to enable DSI +you'll need an overlay that connects a panel to it. + +Signed-off-by: Eric Anholt +--- + arch/arm/boot/dts/bcm2835-rpi.dtsi | 8 +++++++ + arch/arm/boot/dts/bcm283x.dtsi | 49 +++++++++++++++++++++++++++++++++++--- + 2 files changed, 54 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi ++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi +@@ -84,3 +84,11 @@ + power-domains = <&power RPI_POWER_DOMAIN_HDMI>; + status = "okay"; + }; ++ ++&dsi0 { ++ power-domains = <&power RPI_POWER_DOMAIN_DSI0>; ++}; ++ ++&dsi1 { ++ power-domains = <&power RPI_POWER_DOMAIN_DSI1>; ++}; +--- a/arch/arm/boot/dts/bcm283x.dtsi ++++ b/arch/arm/boot/dts/bcm283x.dtsi +@@ -93,10 +93,13 @@ + #clock-cells = <1>; + reg = <0x7e101000 0x2000>; + +- /* CPRMAN derives everything from the platform's +- * oscillator. ++ /* CPRMAN derives almost everything from the ++ * platform's oscillator. However, the DSI ++ * pixel clocks come from the DSI analog PHY. + */ +- clocks = <&clk_osc>; ++ clocks = <&clk_osc>, ++ <&dsi0 0>, <&dsi0 1>, <&dsi0 2>, ++ <&dsi1 0>, <&dsi1 1>, <&dsi1 2>; + }; + + rng@7e104000 { +@@ -188,6 +191,26 @@ + interrupts = <2 14>; /* pwa1 */ + }; + ++ dsi0: dsi@7e209000 { ++ compatible = "brcm,bcm2835-dsi0"; ++ reg = <0x7e209000 0x78>; ++ interrupts = <2 4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #clock-cells = <1>; ++ ++ clocks = <&clocks BCM2835_PLLA_DSI0>, ++ <&clocks BCM2835_CLOCK_DSI0E>, ++ <&clocks BCM2835_CLOCK_DSI0P>; ++ clock-names = "phy", "escape", "pixel"; ++ ++ clock-output-names = "dsi0_byte", ++ "dsi0_ddr2", ++ "dsi0_ddr"; ++ ++ status = "disabled"; ++ }; ++ + aux: aux@0x7e215000 { + compatible = "brcm,bcm2835-aux"; + #clock-cells = <1>; +@@ -247,6 +270,26 @@ + interrupts = <2 1>; + }; + ++ dsi1: dsi@7e700000 { ++ compatible = "brcm,bcm2835-dsi1"; ++ reg = <0x7e700000 0x8c>; ++ interrupts = <2 12>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #clock-cells = <1>; ++ ++ clocks = <&clocks BCM2835_PLLD_DSI1>, ++ <&clocks BCM2835_CLOCK_DSI1E>, ++ <&clocks BCM2835_CLOCK_DSI1P>; ++ clock-names = "phy", "escape", "pixel"; ++ ++ clock-output-names = "dsi1_byte", ++ "dsi1_ddr2", ++ "dsi1_ddr"; ++ ++ status = "disabled"; ++ }; ++ + i2c1: i2c@7e804000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e804000 0x1000>; diff --git a/target/linux/brcm2708/patches-4.9/0161-BCM270X-Enable-the-DSI-panel-node-in-the-VC4-overlay.patch b/target/linux/brcm2708/patches-4.9/0161-BCM270X-Enable-the-DSI-panel-node-in-the-VC4-overlay.patch new file mode 100644 index 0000000000..3d65f5e269 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0161-BCM270X-Enable-the-DSI-panel-node-in-the-VC4-overlay.patch @@ -0,0 +1,138 @@ +From 2c62d430b6b3c20867e55465e0557a1543088f09 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Thu, 2 Jun 2016 15:09:35 -0700 +Subject: [PATCH] BCM270X: Enable the DSI panel node in the VC4 overlay. + +Signed-off-by: Eric Anholt +--- + arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 5 ++++ + arch/arm/boot/dts/bcm2708-rpi-b.dts | 5 ++++ + arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 5 ++++ + arch/arm/boot/dts/bcm270x.dtsi | 27 ++++++++++++++++++++++ + arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 5 ++++ + arch/arm/boot/dts/bcm2710.dtsi | 1 - + arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 22 ++++++++++++++++++ + 7 files changed, 69 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts +@@ -154,3 +154,8 @@ + sd_debug = <&sdhost>,"brcm,debug"; + }; + }; ++ ++&i2c_dsi { ++ gpios = <&gpio 28 0 ++ &gpio 29 0>; ++}; +--- a/arch/arm/boot/dts/bcm2708-rpi-b.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts +@@ -144,3 +144,8 @@ + sd_debug = <&sdhost>,"brcm,debug"; + }; + }; ++ ++&i2c_dsi { ++ gpios = <&gpio 2 0 ++ &gpio 3 0>; ++}; +--- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts ++++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts +@@ -154,3 +154,8 @@ + sd_debug = <&sdhost>,"brcm,debug"; + }; + }; ++ ++&i2c_dsi { ++ gpios = <&gpio 28 0 ++ &gpio 29 0>; ++}; +--- a/arch/arm/boot/dts/bcm270x.dtsi ++++ b/arch/arm/boot/dts/bcm270x.dtsi +@@ -137,6 +137,29 @@ + /* Add alias */ + status = "disabled"; + }; ++ ++ i2c_dsi: i2cdsi { ++ /* We have to use i2c-gpio because the ++ * firmware is also polling another device ++ * using the only hardware I2C bus that could ++ * connect to these pins. ++ */ ++ compatible = "i2c-gpio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ ++ pitouchscreen_bridge: bridge@45 { ++ compatible = "raspberrypi,touchscreen-bridge-i2c"; ++ reg = <0x45>; ++ }; ++ ++ pitouchscreen_touch: bridge@38 { ++ compatible = "raspberrypi,touchscreen-ts-i2c"; ++ reg = <0x38>; ++ }; ++ }; ++ + }; + + vdd_5v0_reg: fixedregulator_5v0 { +@@ -155,3 +178,7 @@ + regulator-always-on; + }; + }; ++ ++&dsi1 { ++ power-domains = <&power RPI_POWER_DOMAIN_DSI1>; ++}; +--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts +@@ -201,3 +201,8 @@ + sd_debug = <&sdhost>,"brcm,debug"; + }; + }; ++ ++&i2c_dsi { ++ gpios = <&gpio 44 0 ++ &gpio 45 0>; ++}; +--- a/arch/arm/boot/dts/bcm2710.dtsi ++++ b/arch/arm/boot/dts/bcm2710.dtsi +@@ -145,4 +145,3 @@ + interrupt-parent = <&local_intc>; + interrupts = <8>; + }; +- +--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts +@@ -126,6 +126,28 @@ + }; + }; + ++ fragment@16 { ++ target = <&dsi1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ pitouchscreen: panel@0 { ++ compatible = "raspberrypi,touchscreen"; ++ reg = <0>; ++ raspberrypi,touchscreen-bridge = <&pitouchscreen_bridge>; ++ }; ++ }; ++ }; ++ ++ fragment@17 { ++ target = <&i2c_dsi>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ + __overrides__ { + cma-256 = <0>,"+0-1-2-3-4"; + cma-192 = <0>,"-0+1-2-3-4"; diff --git a/target/linux/brcm2708/patches-4.9/0162-drm-vc4-Fix-termination-of-the-initial-scan-for-bran.patch b/target/linux/brcm2708/patches-4.9/0162-drm-vc4-Fix-termination-of-the-initial-scan-for-bran.patch new file mode 100644 index 0000000000..3326dca659 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0162-drm-vc4-Fix-termination-of-the-initial-scan-for-bran.patch @@ -0,0 +1,68 @@ +From 57b0774967d7ea8d4173f82387100a84e4ba05d8 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Thu, 20 Oct 2016 16:48:12 -0700 +Subject: [PATCH] drm/vc4: Fix termination of the initial scan for branch + targets. + +The loop is scanning until the original max_ip (size of the BO), but +we want to not examine any code after the PROG_END's delay slots. +There was a block trying to do that, except that we had some early +continue statements if the signal wasn't a PROG_END or a BRANCH. + +The failure mode would be that a valid shader is rejected because some +undefined memory after the PROG_END slots is parsed as a branch and +the rest of its setup is illegal. I haven't seen this in the wild, +but valgrind was complaining when about this up in the userland +simulator mode. + +Signed-off-by: Eric Anholt +(cherry picked from commit 457e67a728696c4f8e6423c64e93def50530db9a) +--- + drivers/gpu/drm/vc4/vc4_validate_shaders.c | 19 ++++++++----------- + 1 file changed, 8 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c ++++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c +@@ -608,9 +608,7 @@ static bool + vc4_validate_branches(struct vc4_shader_validation_state *validation_state) + { + uint32_t max_branch_target = 0; +- bool found_shader_end = false; + int ip; +- int shader_end_ip = 0; + int last_branch = -2; + + for (ip = 0; ip < validation_state->max_ip; ip++) { +@@ -621,8 +619,13 @@ vc4_validate_branches(struct vc4_shader_ + uint32_t branch_target_ip; + + if (sig == QPU_SIG_PROG_END) { +- shader_end_ip = ip; +- found_shader_end = true; ++ /* There are two delay slots after program end is ++ * signaled that are still executed, then we're ++ * finished. validation_state->max_ip is the ++ * instruction after the last valid instruction in the ++ * program. ++ */ ++ validation_state->max_ip = ip + 3; + continue; + } + +@@ -676,15 +679,9 @@ vc4_validate_branches(struct vc4_shader_ + } + set_bit(after_delay_ip, validation_state->branch_targets); + max_branch_target = max(max_branch_target, after_delay_ip); +- +- /* There are two delay slots after program end is signaled +- * that are still executed, then we're finished. +- */ +- if (found_shader_end && ip == shader_end_ip + 2) +- break; + } + +- if (max_branch_target > shader_end_ip) { ++ if (max_branch_target > validation_state->max_ip - 3) { + DRM_ERROR("Branch landed after QPU_SIG_PROG_END"); + return false; + } diff --git a/target/linux/brcm2708/patches-4.9/0163-drm-vc4-Add-support-for-rendering-with-ETC1-textures.patch b/target/linux/brcm2708/patches-4.9/0163-drm-vc4-Add-support-for-rendering-with-ETC1-textures.patch new file mode 100644 index 0000000000..2b81578768 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0163-drm-vc4-Add-support-for-rendering-with-ETC1-textures.patch @@ -0,0 +1,55 @@ +From 4b1b99ebbada744ef72af56b022492609feb9bba Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Thu, 3 Nov 2016 18:53:10 -0700 +Subject: [PATCH] drm/vc4: Add support for rendering with ETC1 textures. + +The validation for it ends up being quite simple, but I hadn't got +around to it before merging the driver. For backwards compatibility, +we also need to add a flag so that the userspace GL driver can easily +tell if the kernel will allow ETC1 textures (on an old kernel, it will +continue to convert to RGBA8) + +Signed-off-by: Eric Anholt +(cherry picked from commit 7154d76fedf549607afbc0d13db9aaf02da5cebf) +--- + drivers/gpu/drm/vc4/vc4_drv.c | 1 + + drivers/gpu/drm/vc4/vc4_validate.c | 7 +++++++ + include/uapi/drm/vc4_drm.h | 1 + + 3 files changed, 9 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -78,6 +78,7 @@ static int vc4_get_param_ioctl(struct dr + pm_runtime_put(&vc4->v3d->pdev->dev); + break; + case DRM_VC4_PARAM_SUPPORTS_BRANCHES: ++ case DRM_VC4_PARAM_SUPPORTS_ETC1: + args->value = true; + break; + default: +--- a/drivers/gpu/drm/vc4/vc4_validate.c ++++ b/drivers/gpu/drm/vc4/vc4_validate.c +@@ -644,6 +644,13 @@ reloc_tex(struct vc4_exec_info *exec, + cpp = 1; + break; + case VC4_TEXTURE_TYPE_ETC1: ++ /* ETC1 is arranged as 64-bit blocks, where each block is 4x4 ++ * pixels. ++ */ ++ cpp = 8; ++ width = (width + 3) >> 2; ++ height = (height + 3) >> 2; ++ break; + case VC4_TEXTURE_TYPE_BW1: + case VC4_TEXTURE_TYPE_A4: + case VC4_TEXTURE_TYPE_A1: +--- a/include/uapi/drm/vc4_drm.h ++++ b/include/uapi/drm/vc4_drm.h +@@ -286,6 +286,7 @@ struct drm_vc4_get_hang_state { + #define DRM_VC4_PARAM_V3D_IDENT1 1 + #define DRM_VC4_PARAM_V3D_IDENT2 2 + #define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3 ++#define DRM_VC4_PARAM_SUPPORTS_ETC1 4 + + struct drm_vc4_get_param { + __u32 param; diff --git a/target/linux/brcm2708/patches-4.9/0164-drm-vc4-Use-runtime-autosuspend-to-avoid-thrashing-V.patch b/target/linux/brcm2708/patches-4.9/0164-drm-vc4-Use-runtime-autosuspend-to-avoid-thrashing-V.patch new file mode 100644 index 0000000000..f6d738d941 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0164-drm-vc4-Use-runtime-autosuspend-to-avoid-thrashing-V.patch @@ -0,0 +1,78 @@ +From 936dc8b00ccd5072c5d610b97199402275bfdf26 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Fri, 4 Nov 2016 15:58:38 -0700 +Subject: [PATCH] drm/vc4: Use runtime autosuspend to avoid thrashing V3D power + state. + +The pm_runtime_put() we were using immediately released power on the +device, which meant that we were generally turning the device off and +on once per frame. In many profiles I've looked at, that added up to +about 1% of CPU time, but this could get worse in the case of frequent +rendering and readback (as may happen in X rendering). By keeping the +device on until we've been idle for a couple of frames, we drop the +overhead of runtime PM down to sub-.1%. + +Signed-off-by: Eric Anholt +(cherry picked from commit 3a62234680d86efa0239665ed8a0e908f1aef147) +--- + drivers/gpu/drm/vc4/vc4_drv.c | 9 ++++++--- + drivers/gpu/drm/vc4/vc4_gem.c | 6 ++++-- + drivers/gpu/drm/vc4/vc4_v3d.c | 2 ++ + 3 files changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -61,21 +61,24 @@ static int vc4_get_param_ioctl(struct dr + if (ret < 0) + return ret; + args->value = V3D_READ(V3D_IDENT0); +- pm_runtime_put(&vc4->v3d->pdev->dev); ++ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); ++ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); + break; + case DRM_VC4_PARAM_V3D_IDENT1: + ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); + if (ret < 0) + return ret; + args->value = V3D_READ(V3D_IDENT1); +- pm_runtime_put(&vc4->v3d->pdev->dev); ++ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); ++ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); + break; + case DRM_VC4_PARAM_V3D_IDENT2: + ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); + if (ret < 0) + return ret; + args->value = V3D_READ(V3D_IDENT2); +- pm_runtime_put(&vc4->v3d->pdev->dev); ++ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); ++ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); + break; + case DRM_VC4_PARAM_SUPPORTS_BRANCHES: + case DRM_VC4_PARAM_SUPPORTS_ETC1: +--- a/drivers/gpu/drm/vc4/vc4_gem.c ++++ b/drivers/gpu/drm/vc4/vc4_gem.c +@@ -711,8 +711,10 @@ vc4_complete_exec(struct drm_device *dev + } + + mutex_lock(&vc4->power_lock); +- if (--vc4->power_refcount == 0) +- pm_runtime_put(&vc4->v3d->pdev->dev); ++ if (--vc4->power_refcount == 0) { ++ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); ++ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); ++ } + mutex_unlock(&vc4->power_lock); + + kfree(exec); +--- a/drivers/gpu/drm/vc4/vc4_v3d.c ++++ b/drivers/gpu/drm/vc4/vc4_v3d.c +@@ -222,6 +222,8 @@ static int vc4_v3d_bind(struct device *d + return ret; + } + ++ pm_runtime_use_autosuspend(dev); ++ pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */ + pm_runtime_enable(dev); + + return 0; diff --git a/target/linux/brcm2708/patches-4.9/0165-drm-vc4-Add-fragment-shader-threading-support.patch b/target/linux/brcm2708/patches-4.9/0165-drm-vc4-Add-fragment-shader-threading-support.patch new file mode 100644 index 0000000000..ea0f4f1177 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0165-drm-vc4-Add-fragment-shader-threading-support.patch @@ -0,0 +1,228 @@ +From 8f5722ac3e42a33345bfd82b7ad6a153134a4239 Mon Sep 17 00:00:00 2001 +From: Jonas Pfeil +Date: Tue, 8 Nov 2016 00:18:39 +0100 +Subject: [PATCH] drm/vc4: Add fragment shader threading support + +FS threading brings performance improvements of 0-20% in glmark2. + +The validation code checks for thread switch signals and ensures that +the registers of the other thread are not touched, and that our clamps +are not live across thread switches. It also checks that the +threading and branching instructions do not interfere. + +(Original patch by Jonas, changes by anholt for style cleanup, +removing validation the kernel doesn't need to do, and adding the flag +for userspace). + +v2: Minor style fixes from checkpatch. + +Signed-off-by: Jonas Pfeil +Signed-off-by: Eric Anholt +(cherry picked from commit c778cc5df944291dcdb1ca7a6bb781fbc22550c5) +--- + drivers/gpu/drm/vc4/vc4_drv.c | 1 + + drivers/gpu/drm/vc4/vc4_drv.h | 2 + + drivers/gpu/drm/vc4/vc4_validate.c | 17 +++++--- + drivers/gpu/drm/vc4/vc4_validate_shaders.c | 63 ++++++++++++++++++++++++++++++ + include/uapi/drm/vc4_drm.h | 1 + + 5 files changed, 79 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -82,6 +82,7 @@ static int vc4_get_param_ioctl(struct dr + break; + case DRM_VC4_PARAM_SUPPORTS_BRANCHES: + case DRM_VC4_PARAM_SUPPORTS_ETC1: ++ case DRM_VC4_PARAM_SUPPORTS_THREADED_FS: + args->value = true; + break; + default: +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -384,6 +384,8 @@ struct vc4_validated_shader_info { + + uint32_t num_uniform_addr_offsets; + uint32_t *uniform_addr_offsets; ++ ++ bool is_threaded; + }; + + /** +--- a/drivers/gpu/drm/vc4/vc4_validate.c ++++ b/drivers/gpu/drm/vc4/vc4_validate.c +@@ -789,11 +789,6 @@ validate_gl_shader_rec(struct drm_device + exec->shader_rec_v += roundup(packet_size, 16); + exec->shader_rec_size -= packet_size; + +- if (!(*(uint16_t *)pkt_u & VC4_SHADER_FLAG_FS_SINGLE_THREAD)) { +- DRM_ERROR("Multi-threaded fragment shaders not supported.\n"); +- return -EINVAL; +- } +- + for (i = 0; i < shader_reloc_count; i++) { + if (src_handles[i] > exec->bo_count) { + DRM_ERROR("Shader handle %d too big\n", src_handles[i]); +@@ -810,6 +805,18 @@ validate_gl_shader_rec(struct drm_device + return -EINVAL; + } + ++ if (((*(uint16_t *)pkt_u & VC4_SHADER_FLAG_FS_SINGLE_THREAD) == 0) != ++ to_vc4_bo(&bo[0]->base)->validated_shader->is_threaded) { ++ DRM_ERROR("Thread mode of CL and FS do not match\n"); ++ return -EINVAL; ++ } ++ ++ if (to_vc4_bo(&bo[1]->base)->validated_shader->is_threaded || ++ to_vc4_bo(&bo[2]->base)->validated_shader->is_threaded) { ++ DRM_ERROR("cs and vs cannot be threaded\n"); ++ return -EINVAL; ++ } ++ + for (i = 0; i < shader_reloc_count; i++) { + struct vc4_validated_shader_info *validated_shader; + uint32_t o = shader_reloc_offsets[i]; +--- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c ++++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c +@@ -83,6 +83,13 @@ struct vc4_shader_validation_state { + * basic blocks. + */ + bool needs_uniform_address_for_loop; ++ ++ /* Set when we find an instruction writing the top half of the ++ * register files. If we allowed writing the unusable regs in ++ * a threaded shader, then the other shader running on our ++ * QPU's clamp validation would be invalid. ++ */ ++ bool all_registers_used; + }; + + static uint32_t +@@ -119,6 +126,13 @@ raddr_add_a_to_live_reg_index(uint64_t i + } + + static bool ++live_reg_is_upper_half(uint32_t lri) ++{ ++ return (lri >= 16 && lri < 32) || ++ (lri >= 32 + 16 && lri < 32 + 32); ++} ++ ++static bool + is_tmu_submit(uint32_t waddr) + { + return (waddr == QPU_W_TMU0_S || +@@ -390,6 +404,9 @@ check_reg_write(struct vc4_validated_sha + } else { + validation_state->live_immediates[lri] = ~0; + } ++ ++ if (live_reg_is_upper_half(lri)) ++ validation_state->all_registers_used = true; + } + + switch (waddr) { +@@ -598,6 +615,11 @@ check_instruction_reads(struct vc4_valid + } + } + ++ if ((raddr_a >= 16 && raddr_a < 32) || ++ (raddr_b >= 16 && raddr_b < 32 && sig != QPU_SIG_SMALL_IMM)) { ++ validation_state->all_registers_used = true; ++ } ++ + return true; + } + +@@ -753,6 +775,7 @@ vc4_validate_shader(struct drm_gem_cma_o + { + bool found_shader_end = false; + int shader_end_ip = 0; ++ uint32_t last_thread_switch_ip = -3; + uint32_t ip; + struct vc4_validated_shader_info *validated_shader = NULL; + struct vc4_shader_validation_state validation_state; +@@ -785,6 +808,17 @@ vc4_validate_shader(struct drm_gem_cma_o + if (!vc4_handle_branch_target(&validation_state)) + goto fail; + ++ if (ip == last_thread_switch_ip + 3) { ++ /* Reset r0-r3 live clamp data */ ++ int i; ++ ++ for (i = 64; i < LIVE_REG_COUNT; i++) { ++ validation_state.live_min_clamp_offsets[i] = ~0; ++ validation_state.live_max_clamp_regs[i] = false; ++ validation_state.live_immediates[i] = ~0; ++ } ++ } ++ + switch (sig) { + case QPU_SIG_NONE: + case QPU_SIG_WAIT_FOR_SCOREBOARD: +@@ -794,6 +828,8 @@ vc4_validate_shader(struct drm_gem_cma_o + case QPU_SIG_LOAD_TMU1: + case QPU_SIG_PROG_END: + case QPU_SIG_SMALL_IMM: ++ case QPU_SIG_THREAD_SWITCH: ++ case QPU_SIG_LAST_THREAD_SWITCH: + if (!check_instruction_writes(validated_shader, + &validation_state)) { + DRM_ERROR("Bad write at ip %d\n", ip); +@@ -809,6 +845,18 @@ vc4_validate_shader(struct drm_gem_cma_o + shader_end_ip = ip; + } + ++ if (sig == QPU_SIG_THREAD_SWITCH || ++ sig == QPU_SIG_LAST_THREAD_SWITCH) { ++ validated_shader->is_threaded = true; ++ ++ if (ip < last_thread_switch_ip + 3) { ++ DRM_ERROR("Thread switch too soon after " ++ "last switch at ip %d\n", ip); ++ goto fail; ++ } ++ last_thread_switch_ip = ip; ++ } ++ + break; + + case QPU_SIG_LOAD_IMM: +@@ -823,6 +871,13 @@ vc4_validate_shader(struct drm_gem_cma_o + if (!check_branch(inst, validated_shader, + &validation_state, ip)) + goto fail; ++ ++ if (ip < last_thread_switch_ip + 3) { ++ DRM_ERROR("Branch in thread switch at ip %d", ++ ip); ++ goto fail; ++ } ++ + break; + default: + DRM_ERROR("Unsupported QPU signal %d at " +@@ -844,6 +899,14 @@ vc4_validate_shader(struct drm_gem_cma_o + goto fail; + } + ++ /* Might corrupt other thread */ ++ if (validated_shader->is_threaded && ++ validation_state.all_registers_used) { ++ DRM_ERROR("Shader uses threading, but uses the upper " ++ "half of the registers, too\n"); ++ goto fail; ++ } ++ + /* If we did a backwards branch and we haven't emitted a uniforms + * reset since then, we still need the uniforms stream to have the + * uniforms address available so that the backwards branch can do its +--- a/include/uapi/drm/vc4_drm.h ++++ b/include/uapi/drm/vc4_drm.h +@@ -287,6 +287,7 @@ struct drm_vc4_get_hang_state { + #define DRM_VC4_PARAM_V3D_IDENT2 2 + #define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3 + #define DRM_VC4_PARAM_SUPPORTS_ETC1 4 ++#define DRM_VC4_PARAM_SUPPORTS_THREADED_FS 5 + + struct drm_vc4_get_param { + __u32 param; diff --git a/target/linux/brcm2708/patches-4.9/0166-drm-vc4-Fix-race-between-page-flip-completion-event-.patch b/target/linux/brcm2708/patches-4.9/0166-drm-vc4-Fix-race-between-page-flip-completion-event-.patch new file mode 100644 index 0000000000..3c66fefafd --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0166-drm-vc4-Fix-race-between-page-flip-completion-event-.patch @@ -0,0 +1,93 @@ +From d7f32f81cf7579ac7d13127db88e789ea864824c Mon Sep 17 00:00:00 2001 +From: Derek Foreman +Date: Thu, 24 Nov 2016 12:11:55 -0600 +Subject: [PATCH] drm/vc4: Fix race between page flip completion event and + clean-up + +There was a small window where a userspace program could submit +a pageflip after receiving a pageflip completion event yet still +receive EBUSY. + +Signed-off-by: Derek Foreman +Signed-off-by: Eric Anholt +Reviewed-by: Eric Anholt +Reviewed-by: Daniel Stone +(cherry picked from commit 26fc78f6fef39b9d7a15def5e7e9826ff68303f4) +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++++++ + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_kms.c | 33 +++++++++++++++++++++++++-------- + 3 files changed, 34 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -682,6 +682,14 @@ void vc4_disable_vblank(struct drm_devic + CRTC_WRITE(PV_INTEN, 0); + } + ++/* Must be called with the event lock held */ ++bool vc4_event_pending(struct drm_crtc *crtc) ++{ ++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); ++ ++ return !!vc4_crtc->event; ++} ++ + static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) + { + struct drm_crtc *crtc = &vc4_crtc->base; +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -445,6 +445,7 @@ int vc4_bo_stats_debugfs(struct seq_file + extern struct platform_driver vc4_crtc_driver; + int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id); + void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id); ++bool vc4_event_pending(struct drm_crtc *crtc); + int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg); + int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, + unsigned int flags, int *vpos, int *hpos, +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -119,17 +119,34 @@ static int vc4_atomic_commit(struct drm_ + + /* Make sure that any outstanding modesets have finished. */ + if (nonblock) { +- ret = down_trylock(&vc4->async_modeset); +- if (ret) { ++ struct drm_crtc *crtc; ++ struct drm_crtc_state *crtc_state; ++ unsigned long flags; ++ bool busy = false; ++ ++ /* ++ * If there's an undispatched event to send then we're ++ * obviously still busy. If there isn't, then we can ++ * unconditionally wait for the semaphore because it ++ * shouldn't be contended (for long). ++ * ++ * This is to prevent a race where queuing a new flip ++ * from userspace immediately on receipt of an event ++ * beats our clean-up and returns EBUSY. ++ */ ++ spin_lock_irqsave(&dev->event_lock, flags); ++ for_each_crtc_in_state(state, crtc, crtc_state, i) ++ busy |= vc4_event_pending(crtc); ++ spin_unlock_irqrestore(&dev->event_lock, flags); ++ if (busy) { + kfree(c); + return -EBUSY; + } +- } else { +- ret = down_interruptible(&vc4->async_modeset); +- if (ret) { +- kfree(c); +- return ret; +- } ++ } ++ ret = down_interruptible(&vc4->async_modeset); ++ if (ret) { ++ kfree(c); ++ return ret; + } + + ret = drm_atomic_helper_prepare_planes(dev, state); diff --git a/target/linux/brcm2708/patches-4.9/0167-drm-vc4-Fix-clock_select-setting-for-the-VEC-encoder.patch b/target/linux/brcm2708/patches-4.9/0167-drm-vc4-Fix-clock_select-setting-for-the-VEC-encoder.patch new file mode 100644 index 0000000000..c2499c130a --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0167-drm-vc4-Fix-clock_select-setting-for-the-VEC-encoder.patch @@ -0,0 +1,113 @@ +From 3b162fdf85d89829d58bbee2d7d79987aceaa595 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Fri, 2 Dec 2016 14:48:07 +0100 +Subject: [PATCH] drm/vc4: Fix ->clock_select setting for the VEC encoder + +PV_CONTROL_CLK_SELECT_VEC is actually 2 and not 0. Fix the definition and +rework the vc4_set_crtc_possible_masks() to cover the full range of the +PV_CONTROL_CLK_SELECT field. + +Signed-off-by: Boris Brezillon +Signed-off-by: Eric Anholt +(cherry picked from commit ab8df60e3a3b68420d0d4477c5f07c00fbfb078b) +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 38 +++++++++++++++++++++++--------------- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_regs.h | 3 ++- + 3 files changed, 26 insertions(+), 16 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -83,8 +83,7 @@ struct vc4_crtc_data { + /* Which channel of the HVS this pixelvalve sources from. */ + int hvs_channel; + +- enum vc4_encoder_type encoder0_type; +- enum vc4_encoder_type encoder1_type; ++ enum vc4_encoder_type encoder_types[4]; + }; + + #define CRTC_WRITE(offset, val) writel(val, vc4_crtc->regs + (offset)) +@@ -880,20 +879,26 @@ static const struct drm_crtc_helper_func + + static const struct vc4_crtc_data pv0_data = { + .hvs_channel = 0, +- .encoder0_type = VC4_ENCODER_TYPE_DSI0, +- .encoder1_type = VC4_ENCODER_TYPE_DPI, ++ .encoder_types = { ++ [PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0, ++ [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_DPI, ++ }, + }; + + static const struct vc4_crtc_data pv1_data = { + .hvs_channel = 2, +- .encoder0_type = VC4_ENCODER_TYPE_DSI1, +- .encoder1_type = VC4_ENCODER_TYPE_SMI, ++ .encoder_types = { ++ [PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1, ++ [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_SMI, ++ }, + }; + + static const struct vc4_crtc_data pv2_data = { + .hvs_channel = 1, +- .encoder0_type = VC4_ENCODER_TYPE_VEC, +- .encoder1_type = VC4_ENCODER_TYPE_HDMI, ++ .encoder_types = { ++ [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI, ++ [PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC, ++ }, + }; + + static const struct of_device_id vc4_crtc_dt_match[] = { +@@ -907,17 +912,20 @@ static void vc4_set_crtc_possible_masks( + struct drm_crtc *crtc) + { + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); ++ const struct vc4_crtc_data *crtc_data = vc4_crtc->data; ++ const enum vc4_encoder_type *encoder_types = crtc_data->encoder_types; + struct drm_encoder *encoder; + + drm_for_each_encoder(encoder, drm) { + struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); ++ int i; + +- if (vc4_encoder->type == vc4_crtc->data->encoder0_type) { +- vc4_encoder->clock_select = 0; +- encoder->possible_crtcs |= drm_crtc_mask(crtc); +- } else if (vc4_encoder->type == vc4_crtc->data->encoder1_type) { +- vc4_encoder->clock_select = 1; +- encoder->possible_crtcs |= drm_crtc_mask(crtc); ++ for (i = 0; i < ARRAY_SIZE(crtc_data->encoder_types); i++) { ++ if (vc4_encoder->type == encoder_types[i]) { ++ vc4_encoder->clock_select = i; ++ encoder->possible_crtcs |= drm_crtc_mask(crtc); ++ break; ++ } + } + } + } +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -197,6 +197,7 @@ to_vc4_plane(struct drm_plane *plane) + } + + enum vc4_encoder_type { ++ VC4_ENCODER_TYPE_NONE, + VC4_ENCODER_TYPE_HDMI, + VC4_ENCODER_TYPE_VEC, + VC4_ENCODER_TYPE_DSI0, +--- a/drivers/gpu/drm/vc4/vc4_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_regs.h +@@ -177,8 +177,9 @@ + # define PV_CONTROL_WAIT_HSTART BIT(12) + # define PV_CONTROL_PIXEL_REP_MASK VC4_MASK(5, 4) + # define PV_CONTROL_PIXEL_REP_SHIFT 4 +-# define PV_CONTROL_CLK_SELECT_DSI_VEC 0 ++# define PV_CONTROL_CLK_SELECT_DSI 0 + # define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1 ++# define PV_CONTROL_CLK_SELECT_VEC 2 + # define PV_CONTROL_CLK_SELECT_MASK VC4_MASK(3, 2) + # define PV_CONTROL_CLK_SELECT_SHIFT 2 + # define PV_CONTROL_FIFO_CLR BIT(1) diff --git a/target/linux/brcm2708/patches-4.9/0168-drm-Add-TV-connector-states-to-drm_connector_state.patch b/target/linux/brcm2708/patches-4.9/0168-drm-Add-TV-connector-states-to-drm_connector_state.patch new file mode 100644 index 0000000000..39e6f11665 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0168-drm-Add-TV-connector-states-to-drm_connector_state.patch @@ -0,0 +1,148 @@ +From 01ff94b770786a793c08fc7fcbecdd5f859a8958 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Fri, 2 Dec 2016 14:48:09 +0100 +Subject: [PATCH] drm: Add TV connector states to drm_connector_state + +Some generic TV connector properties are exposed in drm_mode_config, but +they are currently handled independently in each DRM encoder driver. + +Extend the drm_connector_state to store TV related states, and modify the +drm_atomic_connector_{set,get}_property() helpers to fill the connector +state accordingly. + +Each driver is then responsible for checking and applying the new config +in its ->atomic_mode_{check,set}() operations. + +Signed-off-by: Boris Brezillon +Reviewed-by: Daniel Vetter +Signed-off-by: Eric Anholt +(cherry picked from commit 299a16b163c95fbe1e3b1e142ba9c6ce9dab2c23) +--- + drivers/gpu/drm/drm_atomic.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ + include/drm/drm_connector.h | 32 ++++++++++++++++++++++++++++ + 2 files changed, 82 insertions(+) + +--- a/drivers/gpu/drm/drm_atomic.c ++++ b/drivers/gpu/drm/drm_atomic.c +@@ -989,12 +989,38 @@ int drm_atomic_connector_set_property(st + * now?) atomic writes to DPMS property: + */ + return -EINVAL; ++ } else if (property == config->tv_select_subconnector_property) { ++ state->tv.subconnector = val; ++ } else if (property == config->tv_left_margin_property) { ++ state->tv.margins.left = val; ++ } else if (property == config->tv_right_margin_property) { ++ state->tv.margins.right = val; ++ } else if (property == config->tv_top_margin_property) { ++ state->tv.margins.top = val; ++ } else if (property == config->tv_bottom_margin_property) { ++ state->tv.margins.bottom = val; ++ } else if (property == config->tv_mode_property) { ++ state->tv.mode = val; ++ } else if (property == config->tv_brightness_property) { ++ state->tv.brightness = val; ++ } else if (property == config->tv_contrast_property) { ++ state->tv.contrast = val; ++ } else if (property == config->tv_flicker_reduction_property) { ++ state->tv.flicker_reduction = val; ++ } else if (property == config->tv_overscan_property) { ++ state->tv.overscan = val; ++ } else if (property == config->tv_saturation_property) { ++ state->tv.saturation = val; ++ } else if (property == config->tv_hue_property) { ++ state->tv.hue = val; + } else if (connector->funcs->atomic_set_property) { + return connector->funcs->atomic_set_property(connector, + state, property, val); + } else { + return -EINVAL; + } ++ ++ return 0; + } + EXPORT_SYMBOL(drm_atomic_connector_set_property); + +@@ -1025,6 +1051,30 @@ drm_atomic_connector_get_property(struct + *val = (state->crtc) ? state->crtc->base.id : 0; + } else if (property == config->dpms_property) { + *val = connector->dpms; ++ } else if (property == config->tv_select_subconnector_property) { ++ *val = state->tv.subconnector; ++ } else if (property == config->tv_left_margin_property) { ++ *val = state->tv.margins.left; ++ } else if (property == config->tv_right_margin_property) { ++ *val = state->tv.margins.right; ++ } else if (property == config->tv_top_margin_property) { ++ *val = state->tv.margins.top; ++ } else if (property == config->tv_bottom_margin_property) { ++ *val = state->tv.margins.bottom; ++ } else if (property == config->tv_mode_property) { ++ *val = state->tv.mode; ++ } else if (property == config->tv_brightness_property) { ++ *val = state->tv.brightness; ++ } else if (property == config->tv_contrast_property) { ++ *val = state->tv.contrast; ++ } else if (property == config->tv_flicker_reduction_property) { ++ *val = state->tv.flicker_reduction; ++ } else if (property == config->tv_overscan_property) { ++ *val = state->tv.overscan; ++ } else if (property == config->tv_saturation_property) { ++ *val = state->tv.saturation; ++ } else if (property == config->tv_hue_property) { ++ *val = state->tv.hue; + } else if (connector->funcs->atomic_get_property) { + return connector->funcs->atomic_get_property(connector, + state, property, val); +--- a/include/drm/drm_connector.h ++++ b/include/drm/drm_connector.h +@@ -194,10 +194,40 @@ int drm_display_info_set_bus_formats(str + unsigned int num_formats); + + /** ++ * struct drm_tv_connector_state - TV connector related states ++ * @subconnector: selected subconnector ++ * @margins: left/right/top/bottom margins ++ * @mode: TV mode ++ * @brightness: brightness in percent ++ * @contrast: contrast in percent ++ * @flicker_reduction: flicker reduction in percent ++ * @overscan: overscan in percent ++ * @saturation: saturation in percent ++ * @hue: hue in percent ++ */ ++struct drm_tv_connector_state { ++ enum drm_mode_subconnector subconnector; ++ struct { ++ unsigned int left; ++ unsigned int right; ++ unsigned int top; ++ unsigned int bottom; ++ } margins; ++ unsigned int mode; ++ unsigned int brightness; ++ unsigned int contrast; ++ unsigned int flicker_reduction; ++ unsigned int overscan; ++ unsigned int saturation; ++ unsigned int hue; ++}; ++ ++/** + * struct drm_connector_state - mutable connector state + * @connector: backpointer to the connector + * @best_encoder: can be used by helpers and drivers to select the encoder + * @state: backpointer to global drm_atomic_state ++ * @tv: TV connector state + */ + struct drm_connector_state { + struct drm_connector *connector; +@@ -213,6 +243,8 @@ struct drm_connector_state { + struct drm_encoder *best_encoder; + + struct drm_atomic_state *state; ++ ++ struct drm_tv_connector_state tv; + }; + + /** diff --git a/target/linux/brcm2708/patches-4.9/0169-drm-Turn-DRM_MODE_SUBCONNECTOR_xx-definitions-into-a.patch b/target/linux/brcm2708/patches-4.9/0169-drm-Turn-DRM_MODE_SUBCONNECTOR_xx-definitions-into-a.patch new file mode 100644 index 0000000000..db82c0c5ac --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0169-drm-Turn-DRM_MODE_SUBCONNECTOR_xx-definitions-into-a.patch @@ -0,0 +1,46 @@ +From 1c18e33ab3ff21703925a427e5f55075427a598c Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Fri, 2 Dec 2016 14:48:08 +0100 +Subject: [PATCH] drm: Turn DRM_MODE_SUBCONNECTOR_xx definitions into an enum + +List of values like the DRM_MODE_SUBCONNECTOR_xx ones are better +represented with enums. + +Turn the DRM_MODE_SUBCONNECTOR_xx macros into an enum. + +Signed-off-by: Boris Brezillon +Suggested-by: Daniel Vetter +Reviewed-by: Daniel Vetter +Signed-off-by: Eric Anholt +(cherry picked from commit dee7a4fee730ca8908f335b6b66174cba4598ecd) +--- + include/uapi/drm/drm_mode.h | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +--- a/include/uapi/drm/drm_mode.h ++++ b/include/uapi/drm/drm_mode.h +@@ -220,14 +220,16 @@ struct drm_mode_get_encoder { + + /* This is for connectors with multiple signal types. */ + /* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */ +-#define DRM_MODE_SUBCONNECTOR_Automatic 0 +-#define DRM_MODE_SUBCONNECTOR_Unknown 0 +-#define DRM_MODE_SUBCONNECTOR_DVID 3 +-#define DRM_MODE_SUBCONNECTOR_DVIA 4 +-#define DRM_MODE_SUBCONNECTOR_Composite 5 +-#define DRM_MODE_SUBCONNECTOR_SVIDEO 6 +-#define DRM_MODE_SUBCONNECTOR_Component 8 +-#define DRM_MODE_SUBCONNECTOR_SCART 9 ++enum drm_mode_subconnector { ++ DRM_MODE_SUBCONNECTOR_Automatic = 0, ++ DRM_MODE_SUBCONNECTOR_Unknown = 0, ++ DRM_MODE_SUBCONNECTOR_DVID = 3, ++ DRM_MODE_SUBCONNECTOR_DVIA = 4, ++ DRM_MODE_SUBCONNECTOR_Composite = 5, ++ DRM_MODE_SUBCONNECTOR_SVIDEO = 6, ++ DRM_MODE_SUBCONNECTOR_Component = 8, ++ DRM_MODE_SUBCONNECTOR_SCART = 9, ++}; + + #define DRM_MODE_CONNECTOR_Unknown 0 + #define DRM_MODE_CONNECTOR_VGA 1 diff --git a/target/linux/brcm2708/patches-4.9/0170-drm-vc4-Add-support-for-the-VEC-Video-Encoder-IP.patch b/target/linux/brcm2708/patches-4.9/0170-drm-vc4-Add-support-for-the-VEC-Video-Encoder-IP.patch new file mode 100644 index 0000000000..0b5a853856 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0170-drm-vc4-Add-support-for-the-VEC-Video-Encoder-IP.patch @@ -0,0 +1,730 @@ +From d79cd118969fb3ad714feb834eefdddcc4348673 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Fri, 2 Dec 2016 14:48:10 +0100 +Subject: [PATCH] drm/vc4: Add support for the VEC (Video Encoder) IP + +The VEC IP is a TV DAC, providing support for PAL and NTSC standards. + +Signed-off-by: Boris Brezillon +Signed-off-by: Eric Anholt +(cherry picked from commit e4b81f8c74c82dbc0cb0e5ceb5ef9b713b325fc9) +--- + drivers/gpu/drm/vc4/Makefile | 1 + + drivers/gpu/drm/vc4/vc4_debugfs.c | 1 + + drivers/gpu/drm/vc4/vc4_drv.c | 1 + + drivers/gpu/drm/vc4/vc4_drv.h | 5 + + drivers/gpu/drm/vc4/vc4_vec.c | 657 ++++++++++++++++++++++++++++++++++++++ + 5 files changed, 665 insertions(+) + create mode 100644 drivers/gpu/drm/vc4/vc4_vec.c + +--- a/drivers/gpu/drm/vc4/Makefile ++++ b/drivers/gpu/drm/vc4/Makefile +@@ -12,6 +12,7 @@ vc4-y := \ + vc4_kms.o \ + vc4_gem.o \ + vc4_hdmi.o \ ++ vc4_vec.o \ + vc4_hvs.o \ + vc4_irq.o \ + vc4_plane.o \ +--- a/drivers/gpu/drm/vc4/vc4_debugfs.c ++++ b/drivers/gpu/drm/vc4/vc4_debugfs.c +@@ -19,6 +19,7 @@ static const struct drm_info_list vc4_de + {"bo_stats", vc4_bo_stats_debugfs, 0}, + {"dpi_regs", vc4_dpi_debugfs_regs, 0}, + {"hdmi_regs", vc4_hdmi_debugfs_regs, 0}, ++ {"vec_regs", vc4_vec_debugfs_regs, 0}, + {"hvs_regs", vc4_hvs_debugfs_regs, 0}, + {"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0}, + {"crtc1_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)1}, +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -294,6 +294,7 @@ static const struct component_master_ops + + static struct platform_driver *const component_drivers[] = { + &vc4_hdmi_driver, ++ &vc4_vec_driver, + &vc4_dpi_driver, + &vc4_hvs_driver, + &vc4_crtc_driver, +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -20,6 +20,7 @@ struct vc4_dev { + struct vc4_crtc *crtc[3]; + struct vc4_v3d *v3d; + struct vc4_dpi *dpi; ++ struct vc4_vec *vec; + + struct drm_fbdev_cma *fbdev; + +@@ -494,6 +495,10 @@ int vc4_queue_seqno_cb(struct drm_device + extern struct platform_driver vc4_hdmi_driver; + int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused); + ++/* vc4_hdmi.c */ ++extern struct platform_driver vc4_vec_driver; ++int vc4_vec_debugfs_regs(struct seq_file *m, void *unused); ++ + /* vc4_irq.c */ + irqreturn_t vc4_irq(int irq, void *arg); + void vc4_irq_preinstall(struct drm_device *dev); +--- /dev/null ++++ b/drivers/gpu/drm/vc4/vc4_vec.c +@@ -0,0 +1,657 @@ ++/* ++ * Copyright (C) 2016 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see . ++ */ ++ ++/** ++ * DOC: VC4 SDTV module ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "vc4_drv.h" ++#include "vc4_regs.h" ++ ++/* WSE Registers */ ++#define VEC_WSE_RESET 0xc0 ++ ++#define VEC_WSE_CONTROL 0xc4 ++#define VEC_WSE_WSS_ENABLE BIT(7) ++ ++#define VEC_WSE_WSS_DATA 0xc8 ++#define VEC_WSE_VPS_DATA1 0xcc ++#define VEC_WSE_VPS_CONTROL 0xd0 ++ ++/* VEC Registers */ ++#define VEC_REVID 0x100 ++ ++#define VEC_CONFIG0 0x104 ++#define VEC_CONFIG0_YDEL_MASK GENMASK(28, 26) ++#define VEC_CONFIG0_YDEL(x) ((x) << 26) ++#define VEC_CONFIG0_CDEL_MASK GENMASK(25, 24) ++#define VEC_CONFIG0_CDEL(x) ((x) << 24) ++#define VEC_CONFIG0_PBPR_FIL BIT(18) ++#define VEC_CONFIG0_CHROMA_GAIN_MASK GENMASK(17, 16) ++#define VEC_CONFIG0_CHROMA_GAIN_UNITY (0 << 16) ++#define VEC_CONFIG0_CHROMA_GAIN_1_32 (1 << 16) ++#define VEC_CONFIG0_CHROMA_GAIN_1_16 (2 << 16) ++#define VEC_CONFIG0_CHROMA_GAIN_1_8 (3 << 16) ++#define VEC_CONFIG0_CBURST_GAIN_MASK GENMASK(14, 13) ++#define VEC_CONFIG0_CBURST_GAIN_UNITY (0 << 13) ++#define VEC_CONFIG0_CBURST_GAIN_1_128 (1 << 13) ++#define VEC_CONFIG0_CBURST_GAIN_1_64 (2 << 13) ++#define VEC_CONFIG0_CBURST_GAIN_1_32 (3 << 13) ++#define VEC_CONFIG0_CHRBW1 BIT(11) ++#define VEC_CONFIG0_CHRBW0 BIT(10) ++#define VEC_CONFIG0_SYNCDIS BIT(9) ++#define VEC_CONFIG0_BURDIS BIT(8) ++#define VEC_CONFIG0_CHRDIS BIT(7) ++#define VEC_CONFIG0_PDEN BIT(6) ++#define VEC_CONFIG0_YCDELAY BIT(4) ++#define VEC_CONFIG0_RAMPEN BIT(2) ++#define VEC_CONFIG0_YCDIS BIT(2) ++#define VEC_CONFIG0_STD_MASK GENMASK(1, 0) ++#define VEC_CONFIG0_NTSC_STD 0 ++#define VEC_CONFIG0_PAL_BDGHI_STD 1 ++#define VEC_CONFIG0_PAL_N_STD 3 ++ ++#define VEC_SCHPH 0x108 ++#define VEC_SOFT_RESET 0x10c ++#define VEC_CLMP0_START 0x144 ++#define VEC_CLMP0_END 0x148 ++#define VEC_FREQ3_2 0x180 ++#define VEC_FREQ1_0 0x184 ++ ++#define VEC_CONFIG1 0x188 ++#define VEC_CONFIG_VEC_RESYNC_OFF BIT(18) ++#define VEC_CONFIG_RGB219 BIT(17) ++#define VEC_CONFIG_CBAR_EN BIT(16) ++#define VEC_CONFIG_TC_OBB BIT(15) ++#define VEC_CONFIG1_OUTPUT_MODE_MASK GENMASK(12, 10) ++#define VEC_CONFIG1_C_Y_CVBS (0 << 10) ++#define VEC_CONFIG1_CVBS_Y_C (1 << 10) ++#define VEC_CONFIG1_PR_Y_PB (2 << 10) ++#define VEC_CONFIG1_RGB (4 << 10) ++#define VEC_CONFIG1_Y_C_CVBS (5 << 10) ++#define VEC_CONFIG1_C_CVBS_Y (6 << 10) ++#define VEC_CONFIG1_C_CVBS_CVBS (7 << 10) ++#define VEC_CONFIG1_DIS_CHR BIT(9) ++#define VEC_CONFIG1_DIS_LUMA BIT(8) ++#define VEC_CONFIG1_YCBCR_IN BIT(6) ++#define VEC_CONFIG1_DITHER_TYPE_LFSR 0 ++#define VEC_CONFIG1_DITHER_TYPE_COUNTER BIT(5) ++#define VEC_CONFIG1_DITHER_EN BIT(4) ++#define VEC_CONFIG1_CYDELAY BIT(3) ++#define VEC_CONFIG1_LUMADIS BIT(2) ++#define VEC_CONFIG1_COMPDIS BIT(1) ++#define VEC_CONFIG1_CUSTOM_FREQ BIT(0) ++ ++#define VEC_CONFIG2 0x18c ++#define VEC_CONFIG2_PROG_SCAN BIT(15) ++#define VEC_CONFIG2_SYNC_ADJ_MASK GENMASK(14, 12) ++#define VEC_CONFIG2_SYNC_ADJ(x) (((x) / 2) << 12) ++#define VEC_CONFIG2_PBPR_EN BIT(10) ++#define VEC_CONFIG2_UV_DIG_DIS BIT(6) ++#define VEC_CONFIG2_RGB_DIG_DIS BIT(5) ++#define VEC_CONFIG2_TMUX_MASK GENMASK(3, 2) ++#define VEC_CONFIG2_TMUX_DRIVE0 (0 << 2) ++#define VEC_CONFIG2_TMUX_RG_COMP (1 << 2) ++#define VEC_CONFIG2_TMUX_UV_YC (2 << 2) ++#define VEC_CONFIG2_TMUX_SYNC_YC (3 << 2) ++ ++#define VEC_INTERRUPT_CONTROL 0x190 ++#define VEC_INTERRUPT_STATUS 0x194 ++#define VEC_FCW_SECAM_B 0x198 ++#define VEC_SECAM_GAIN_VAL 0x19c ++ ++#define VEC_CONFIG3 0x1a0 ++#define VEC_CONFIG3_HORIZ_LEN_STD (0 << 0) ++#define VEC_CONFIG3_HORIZ_LEN_MPEG1_SIF (1 << 0) ++#define VEC_CONFIG3_SHAPE_NON_LINEAR BIT(1) ++ ++#define VEC_STATUS0 0x200 ++#define VEC_MASK0 0x204 ++ ++#define VEC_CFG 0x208 ++#define VEC_CFG_SG_MODE_MASK GENMASK(6, 5) ++#define VEC_CFG_SG_MODE(x) ((x) << 5) ++#define VEC_CFG_SG_EN BIT(4) ++#define VEC_CFG_VEC_EN BIT(3) ++#define VEC_CFG_MB_EN BIT(2) ++#define VEC_CFG_ENABLE BIT(1) ++#define VEC_CFG_TB_EN BIT(0) ++ ++#define VEC_DAC_TEST 0x20c ++ ++#define VEC_DAC_CONFIG 0x210 ++#define VEC_DAC_CONFIG_LDO_BIAS_CTRL(x) ((x) << 24) ++#define VEC_DAC_CONFIG_DRIVER_CTRL(x) ((x) << 16) ++#define VEC_DAC_CONFIG_DAC_CTRL(x) (x) ++ ++#define VEC_DAC_MISC 0x214 ++#define VEC_DAC_MISC_VCD_CTRL_MASK GENMASK(31, 16) ++#define VEC_DAC_MISC_VCD_CTRL(x) ((x) << 16) ++#define VEC_DAC_MISC_VID_ACT BIT(8) ++#define VEC_DAC_MISC_VCD_PWRDN BIT(6) ++#define VEC_DAC_MISC_BIAS_PWRDN BIT(5) ++#define VEC_DAC_MISC_DAC_PWRDN BIT(2) ++#define VEC_DAC_MISC_LDO_PWRDN BIT(1) ++#define VEC_DAC_MISC_DAC_RST_N BIT(0) ++ ++ ++/* General VEC hardware state. */ ++struct vc4_vec { ++ struct platform_device *pdev; ++ ++ struct drm_encoder *encoder; ++ struct drm_connector *connector; ++ ++ void __iomem *regs; ++ ++ struct clk *clock; ++ ++ const struct vc4_vec_tv_mode *tv_mode; ++}; ++ ++#define VEC_READ(offset) readl(vec->regs + (offset)) ++#define VEC_WRITE(offset, val) writel(val, vec->regs + (offset)) ++ ++/* VC4 VEC encoder KMS struct */ ++struct vc4_vec_encoder { ++ struct vc4_encoder base; ++ struct vc4_vec *vec; ++}; ++ ++static inline struct vc4_vec_encoder * ++to_vc4_vec_encoder(struct drm_encoder *encoder) ++{ ++ return container_of(encoder, struct vc4_vec_encoder, base.base); ++} ++ ++/* VC4 VEC connector KMS struct */ ++struct vc4_vec_connector { ++ struct drm_connector base; ++ struct vc4_vec *vec; ++ ++ /* Since the connector is attached to just the one encoder, ++ * this is the reference to it so we can do the best_encoder() ++ * hook. ++ */ ++ struct drm_encoder *encoder; ++}; ++ ++static inline struct vc4_vec_connector * ++to_vc4_vec_connector(struct drm_connector *connector) ++{ ++ return container_of(connector, struct vc4_vec_connector, base); ++} ++ ++enum vc4_vec_tv_mode_id { ++ VC4_VEC_TV_MODE_NTSC, ++ VC4_VEC_TV_MODE_NTSC_J, ++ VC4_VEC_TV_MODE_PAL, ++ VC4_VEC_TV_MODE_PAL_M, ++}; ++ ++struct vc4_vec_tv_mode { ++ const struct drm_display_mode *mode; ++ void (*mode_set)(struct vc4_vec *vec); ++}; ++ ++#define VEC_REG(reg) { reg, #reg } ++static const struct { ++ u32 reg; ++ const char *name; ++} vec_regs[] = { ++ VEC_REG(VEC_WSE_CONTROL), ++ VEC_REG(VEC_WSE_WSS_DATA), ++ VEC_REG(VEC_WSE_VPS_DATA1), ++ VEC_REG(VEC_WSE_VPS_CONTROL), ++ VEC_REG(VEC_REVID), ++ VEC_REG(VEC_CONFIG0), ++ VEC_REG(VEC_SCHPH), ++ VEC_REG(VEC_CLMP0_START), ++ VEC_REG(VEC_CLMP0_END), ++ VEC_REG(VEC_FREQ3_2), ++ VEC_REG(VEC_FREQ1_0), ++ VEC_REG(VEC_CONFIG1), ++ VEC_REG(VEC_CONFIG2), ++ VEC_REG(VEC_INTERRUPT_CONTROL), ++ VEC_REG(VEC_INTERRUPT_STATUS), ++ VEC_REG(VEC_FCW_SECAM_B), ++ VEC_REG(VEC_SECAM_GAIN_VAL), ++ VEC_REG(VEC_CONFIG3), ++ VEC_REG(VEC_STATUS0), ++ VEC_REG(VEC_MASK0), ++ VEC_REG(VEC_CFG), ++ VEC_REG(VEC_DAC_TEST), ++ VEC_REG(VEC_DAC_CONFIG), ++ VEC_REG(VEC_DAC_MISC), ++}; ++ ++#ifdef CONFIG_DEBUG_FS ++int vc4_vec_debugfs_regs(struct seq_file *m, void *unused) ++{ ++ struct drm_info_node *node = (struct drm_info_node *)m->private; ++ struct drm_device *dev = node->minor->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ struct vc4_vec *vec = vc4->vec; ++ int i; ++ ++ if (!vec) ++ return 0; ++ ++ for (i = 0; i < ARRAY_SIZE(vec_regs); i++) { ++ seq_printf(m, "%s (0x%04x): 0x%08x\n", ++ vec_regs[i].name, vec_regs[i].reg, ++ VEC_READ(vec_regs[i].reg)); ++ } ++ ++ return 0; ++} ++#endif ++ ++static void vc4_vec_ntsc_mode_set(struct vc4_vec *vec) ++{ ++ VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN); ++ VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS); ++} ++ ++static void vc4_vec_ntsc_j_mode_set(struct vc4_vec *vec) ++{ ++ VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD); ++ VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS); ++} ++ ++static const struct drm_display_mode ntsc_mode = { ++ DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500, ++ 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0, ++ 480, 480 + 3, 480 + 3 + 3, 480 + 3 + 3 + 16, 0, ++ DRM_MODE_FLAG_INTERLACE) ++}; ++ ++static void vc4_vec_pal_mode_set(struct vc4_vec *vec) ++{ ++ VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD); ++ VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS); ++} ++ ++static void vc4_vec_pal_m_mode_set(struct vc4_vec *vec) ++{ ++ VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD); ++ VEC_WRITE(VEC_CONFIG1, ++ VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ); ++ VEC_WRITE(VEC_FREQ3_2, 0x223b); ++ VEC_WRITE(VEC_FREQ1_0, 0x61d1); ++} ++ ++static const struct drm_display_mode pal_mode = { ++ DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500, ++ 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0, ++ 576, 576 + 2, 576 + 2 + 3, 576 + 2 + 3 + 20, 0, ++ DRM_MODE_FLAG_INTERLACE) ++}; ++ ++static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = { ++ [VC4_VEC_TV_MODE_NTSC] = { ++ .mode = &ntsc_mode, ++ .mode_set = vc4_vec_ntsc_mode_set, ++ }, ++ [VC4_VEC_TV_MODE_NTSC_J] = { ++ .mode = &ntsc_mode, ++ .mode_set = vc4_vec_ntsc_j_mode_set, ++ }, ++ [VC4_VEC_TV_MODE_PAL] = { ++ .mode = &pal_mode, ++ .mode_set = vc4_vec_pal_mode_set, ++ }, ++ [VC4_VEC_TV_MODE_PAL_M] = { ++ .mode = &pal_mode, ++ .mode_set = vc4_vec_pal_m_mode_set, ++ }, ++}; ++ ++static enum drm_connector_status ++vc4_vec_connector_detect(struct drm_connector *connector, bool force) ++{ ++ return connector_status_unknown; ++} ++ ++static void vc4_vec_connector_destroy(struct drm_connector *connector) ++{ ++ drm_connector_unregister(connector); ++ drm_connector_cleanup(connector); ++} ++ ++static int vc4_vec_connector_get_modes(struct drm_connector *connector) ++{ ++ struct drm_connector_state *state = connector->state; ++ struct drm_display_mode *mode; ++ ++ mode = drm_mode_duplicate(connector->dev, ++ vc4_vec_tv_modes[state->tv.mode].mode); ++ if (!mode) { ++ DRM_ERROR("Failed to create a new display mode\n"); ++ return -ENOMEM; ++ } ++ ++ drm_mode_probed_add(connector, mode); ++ ++ return 1; ++} ++ ++static const struct drm_connector_funcs vc4_vec_connector_funcs = { ++ .dpms = drm_atomic_helper_connector_dpms, ++ .detect = vc4_vec_connector_detect, ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .set_property = drm_atomic_helper_connector_set_property, ++ .destroy = vc4_vec_connector_destroy, ++ .reset = drm_atomic_helper_connector_reset, ++ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, ++}; ++ ++static const struct drm_connector_helper_funcs vc4_vec_connector_helper_funcs = { ++ .get_modes = vc4_vec_connector_get_modes, ++}; ++ ++static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev, ++ struct vc4_vec *vec) ++{ ++ struct drm_connector *connector = NULL; ++ struct vc4_vec_connector *vec_connector; ++ ++ vec_connector = devm_kzalloc(dev->dev, sizeof(*vec_connector), ++ GFP_KERNEL); ++ if (!vec_connector) ++ return ERR_PTR(-ENOMEM); ++ ++ connector = &vec_connector->base; ++ connector->interlace_allowed = true; ++ ++ vec_connector->encoder = vec->encoder; ++ vec_connector->vec = vec; ++ ++ drm_connector_init(dev, connector, &vc4_vec_connector_funcs, ++ DRM_MODE_CONNECTOR_Composite); ++ drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs); ++ ++ drm_object_attach_property(&connector->base, ++ dev->mode_config.tv_mode_property, ++ VC4_VEC_TV_MODE_NTSC); ++ vec->tv_mode = &vc4_vec_tv_modes[VC4_VEC_TV_MODE_NTSC]; ++ ++ drm_mode_connector_attach_encoder(connector, vec->encoder); ++ ++ return connector; ++} ++ ++static const struct drm_encoder_funcs vc4_vec_encoder_funcs = { ++ .destroy = drm_encoder_cleanup, ++}; ++ ++static void vc4_vec_encoder_disable(struct drm_encoder *encoder) ++{ ++ struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder); ++ struct vc4_vec *vec = vc4_vec_encoder->vec; ++ int ret; ++ ++ VEC_WRITE(VEC_CFG, 0); ++ VEC_WRITE(VEC_DAC_MISC, ++ VEC_DAC_MISC_VCD_PWRDN | ++ VEC_DAC_MISC_BIAS_PWRDN | ++ VEC_DAC_MISC_DAC_PWRDN | ++ VEC_DAC_MISC_LDO_PWRDN); ++ ++ clk_disable_unprepare(vec->clock); ++ ++ ret = pm_runtime_put(&vec->pdev->dev); ++ if (ret < 0) { ++ DRM_ERROR("Failed to release power domain: %d\n", ret); ++ return; ++ } ++} ++ ++static void vc4_vec_encoder_enable(struct drm_encoder *encoder) ++{ ++ struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder); ++ struct vc4_vec *vec = vc4_vec_encoder->vec; ++ int ret; ++ ++ ret = pm_runtime_get_sync(&vec->pdev->dev); ++ if (ret < 0) { ++ DRM_ERROR("Failed to retain power domain: %d\n", ret); ++ return; ++ } ++ ++ /* ++ * We need to set the clock rate each time we enable the encoder ++ * because there's a chance we share the same parent with the HDMI ++ * clock, and both drivers are requesting different rates. ++ * The good news is, these 2 encoders cannot be enabled at the same ++ * time, thus preventing incompatible rate requests. ++ */ ++ ret = clk_set_rate(vec->clock, 108000000); ++ if (ret) { ++ DRM_ERROR("Failed to set clock rate: %d\n", ret); ++ return; ++ } ++ ++ ret = clk_prepare_enable(vec->clock); ++ if (ret) { ++ DRM_ERROR("Failed to turn on core clock: %d\n", ret); ++ return; ++ } ++ ++ /* Reset the different blocks */ ++ VEC_WRITE(VEC_WSE_RESET, 1); ++ VEC_WRITE(VEC_SOFT_RESET, 1); ++ ++ /* Disable the CGSM-A and WSE blocks */ ++ VEC_WRITE(VEC_WSE_CONTROL, 0); ++ ++ /* Write config common to all modes. */ ++ ++ /* ++ * Color subcarrier phase: phase = 360 * SCHPH / 256. ++ * 0x28 <=> 39.375 deg. ++ */ ++ VEC_WRITE(VEC_SCHPH, 0x28); ++ ++ /* ++ * Reset to default values. ++ */ ++ VEC_WRITE(VEC_CLMP0_START, 0xac); ++ VEC_WRITE(VEC_CLMP0_END, 0xec); ++ VEC_WRITE(VEC_CONFIG2, ++ VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS); ++ VEC_WRITE(VEC_CONFIG3, VEC_CONFIG3_HORIZ_LEN_STD); ++ VEC_WRITE(VEC_DAC_CONFIG, ++ VEC_DAC_CONFIG_DAC_CTRL(0xc) | ++ VEC_DAC_CONFIG_DRIVER_CTRL(0xc) | ++ VEC_DAC_CONFIG_LDO_BIAS_CTRL(0x46)); ++ ++ /* Mask all interrupts. */ ++ VEC_WRITE(VEC_MASK0, 0); ++ ++ vec->tv_mode->mode_set(vec); ++ ++ VEC_WRITE(VEC_DAC_MISC, ++ VEC_DAC_MISC_VID_ACT | VEC_DAC_MISC_DAC_RST_N); ++ VEC_WRITE(VEC_CFG, VEC_CFG_VEC_EN); ++} ++ ++ ++static bool vc4_vec_encoder_mode_fixup(struct drm_encoder *encoder, ++ const struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ return true; ++} ++ ++static void vc4_vec_encoder_atomic_mode_set(struct drm_encoder *encoder, ++ struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state) ++{ ++ struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder); ++ struct vc4_vec *vec = vc4_vec_encoder->vec; ++ ++ vec->tv_mode = &vc4_vec_tv_modes[conn_state->tv.mode]; ++} ++ ++static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder, ++ struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state) ++{ ++ const struct vc4_vec_tv_mode *vec_mode; ++ ++ vec_mode = &vc4_vec_tv_modes[conn_state->tv.mode]; ++ ++ if (conn_state->crtc && ++ !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode)) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = { ++ .disable = vc4_vec_encoder_disable, ++ .enable = vc4_vec_encoder_enable, ++ .mode_fixup = vc4_vec_encoder_mode_fixup, ++ .atomic_check = vc4_vec_encoder_atomic_check, ++ .atomic_mode_set = vc4_vec_encoder_atomic_mode_set, ++}; ++ ++static const struct of_device_id vc4_vec_dt_match[] = { ++ { .compatible = "brcm,bcm2835-vec", .data = NULL }, ++ { /* sentinel */ }, ++}; ++ ++static const char * const tv_mode_names[] = { ++ [VC4_VEC_TV_MODE_NTSC] = "NTSC", ++ [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J", ++ [VC4_VEC_TV_MODE_PAL] = "PAL", ++ [VC4_VEC_TV_MODE_PAL_M] = "PAL-M", ++}; ++ ++static int vc4_vec_bind(struct device *dev, struct device *master, void *data) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct drm_device *drm = dev_get_drvdata(master); ++ struct vc4_dev *vc4 = to_vc4_dev(drm); ++ struct vc4_vec *vec; ++ struct vc4_vec_encoder *vc4_vec_encoder; ++ int ret; ++ ++ ret = drm_mode_create_tv_properties(drm, ARRAY_SIZE(tv_mode_names), ++ tv_mode_names); ++ if (ret) ++ return ret; ++ ++ vec = devm_kzalloc(dev, sizeof(*vec), GFP_KERNEL); ++ if (!vec) ++ return -ENOMEM; ++ ++ vc4_vec_encoder = devm_kzalloc(dev, sizeof(*vc4_vec_encoder), ++ GFP_KERNEL); ++ if (!vc4_vec_encoder) ++ return -ENOMEM; ++ vc4_vec_encoder->base.type = VC4_ENCODER_TYPE_VEC; ++ vc4_vec_encoder->vec = vec; ++ vec->encoder = &vc4_vec_encoder->base.base; ++ ++ vec->pdev = pdev; ++ vec->regs = vc4_ioremap_regs(pdev, 0); ++ if (IS_ERR(vec->regs)) ++ return PTR_ERR(vec->regs); ++ ++ vec->clock = devm_clk_get(dev, NULL); ++ if (IS_ERR(vec->clock)) { ++ ret = PTR_ERR(vec->clock); ++ if (ret != -EPROBE_DEFER) ++ DRM_ERROR("Failed to get clock: %d\n", ret); ++ return ret; ++ } ++ ++ pm_runtime_enable(dev); ++ ++ drm_encoder_init(drm, vec->encoder, &vc4_vec_encoder_funcs, ++ DRM_MODE_ENCODER_TVDAC, NULL); ++ drm_encoder_helper_add(vec->encoder, &vc4_vec_encoder_helper_funcs); ++ ++ vec->connector = vc4_vec_connector_init(drm, vec); ++ if (IS_ERR(vec->connector)) { ++ ret = PTR_ERR(vec->connector); ++ goto err_destroy_encoder; ++ } ++ ++ dev_set_drvdata(dev, vec); ++ ++ vc4->vec = vec; ++ ++ return 0; ++ ++err_destroy_encoder: ++ drm_encoder_cleanup(vec->encoder); ++ pm_runtime_disable(dev); ++ ++ return ret; ++} ++ ++static void vc4_vec_unbind(struct device *dev, struct device *master, ++ void *data) ++{ ++ struct drm_device *drm = dev_get_drvdata(master); ++ struct vc4_dev *vc4 = to_vc4_dev(drm); ++ struct vc4_vec *vec = dev_get_drvdata(dev); ++ ++ vc4_vec_connector_destroy(vec->connector); ++ drm_encoder_cleanup(vec->encoder); ++ pm_runtime_disable(dev); ++ ++ vc4->vec = NULL; ++} ++ ++static const struct component_ops vc4_vec_ops = { ++ .bind = vc4_vec_bind, ++ .unbind = vc4_vec_unbind, ++}; ++ ++static int vc4_vec_dev_probe(struct platform_device *pdev) ++{ ++ return component_add(&pdev->dev, &vc4_vec_ops); ++} ++ ++static int vc4_vec_dev_remove(struct platform_device *pdev) ++{ ++ component_del(&pdev->dev, &vc4_vec_ops); ++ return 0; ++} ++ ++struct platform_driver vc4_vec_driver = { ++ .probe = vc4_vec_dev_probe, ++ .remove = vc4_vec_dev_remove, ++ .driver = { ++ .name = "vc4_vec", ++ .of_match_table = vc4_vec_dt_match, ++ }, ++}; diff --git a/target/linux/brcm2708/patches-4.9/0171-drm-vc4-Set-up-SCALER_DISPCTRL-at-boot.patch b/target/linux/brcm2708/patches-4.9/0171-drm-vc4-Set-up-SCALER_DISPCTRL-at-boot.patch new file mode 100644 index 0000000000..1a425cac00 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0171-drm-vc4-Set-up-SCALER_DISPCTRL-at-boot.patch @@ -0,0 +1,58 @@ +From e79b86a0c5ccd0e8c16e31b2d494d43e997253d1 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Thu, 15 Sep 2016 15:25:23 +0100 +Subject: [PATCH] drm/vc4: Set up SCALER_DISPCTRL at boot. + +We want the HVS on, obviously, and we also want DSP3 (PV1's source) to +be muxed from HVS channel 2 like we expect in vc4_crtc.c. The +firmware wasn't setting the DSP3 mux up when both the LCD and HDMI +were disabled. + +Signed-off-by: Eric Anholt +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 14 ++++++++++++++ + drivers/gpu/drm/vc4/vc4_regs.h | 3 +++ + 2 files changed, 17 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -170,6 +170,7 @@ static int vc4_hvs_bind(struct device *d + struct vc4_dev *vc4 = drm->dev_private; + struct vc4_hvs *hvs = NULL; + int ret; ++ u32 dispctrl; + + hvs = devm_kzalloc(&pdev->dev, sizeof(*hvs), GFP_KERNEL); + if (!hvs) +@@ -211,6 +212,19 @@ static int vc4_hvs_bind(struct device *d + return ret; + + vc4->hvs = hvs; ++ ++ dispctrl = HVS_READ(SCALER_DISPCTRL); ++ ++ dispctrl |= SCALER_DISPCTRL_ENABLE; ++ ++ /* Set DSP3 (PV1) to use HVS channel 2, which would otherwise ++ * be unused. ++ */ ++ dispctrl &= ~SCALER_DISPCTRL_DSP3_MUX_MASK; ++ dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX); ++ ++ HVS_WRITE(SCALER_DISPCTRL, dispctrl); ++ + return 0; + } + +--- a/drivers/gpu/drm/vc4/vc4_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_regs.h +@@ -244,6 +244,9 @@ + # define SCALER_DISPCTRL_ENABLE BIT(31) + # define SCALER_DISPCTRL_DSP2EISLUR BIT(15) + # define SCALER_DISPCTRL_DSP1EISLUR BIT(14) ++# define SCALER_DISPCTRL_DSP3_MUX_MASK VC4_MASK(19, 18) ++# define SCALER_DISPCTRL_DSP3_MUX_SHIFT 18 ++ + /* Enables Display 0 short line and underrun contribution to + * SCALER_DISPSTAT_IRQDISP0. Note that short frame contributions are + * always enabled. diff --git a/target/linux/brcm2708/patches-4.9/0172-drm-vc4-Add-support-for-feeding-DSI-encoders-from-th.patch b/target/linux/brcm2708/patches-4.9/0172-drm-vc4-Add-support-for-feeding-DSI-encoders-from-th.patch new file mode 100644 index 0000000000..15243a32b7 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0172-drm-vc4-Add-support-for-feeding-DSI-encoders-from-th.patch @@ -0,0 +1,113 @@ +From 01ffdd37dcd3c9e526ac9135bfd289beb45f84a0 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Wed, 10 Feb 2016 16:17:29 -0800 +Subject: [PATCH] drm/vc4: Add support for feeding DSI encoders from the pixel + valve. + +We have to set a different pixel format, which tells the hardware to +use the pix_width field that's fed in sideband from the DSI encoder to +divide the "pixel" clock. + +Signed-off-by: Eric Anholt +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 33 +++++++++++++++++++-------------- + drivers/gpu/drm/vc4/vc4_regs.h | 2 ++ + 2 files changed, 21 insertions(+), 14 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -352,38 +352,40 @@ static u32 vc4_get_fifo_full_level(u32 f + } + + /* +- * Returns the clock select bit for the connector attached to the +- * CRTC. ++ * Returns the encoder attached to the CRTC. ++ * ++ * VC4 can only scan out to one encoder at a time, while the DRM core ++ * allows drivers to push pixels to more than one encoder from the ++ * same CRTC. + */ +-static int vc4_get_clock_select(struct drm_crtc *crtc) ++static struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc) + { + struct drm_connector *connector; + + drm_for_each_connector(connector, crtc->dev) { + if (connector->state->crtc == crtc) { +- struct drm_encoder *encoder = connector->encoder; +- struct vc4_encoder *vc4_encoder = +- to_vc4_encoder(encoder); +- +- return vc4_encoder->clock_select; ++ return connector->encoder; + } + } + +- return -1; ++ return NULL; + } + + static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) + { + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); ++ struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); ++ struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct drm_crtc_state *state = crtc->state; + struct drm_display_mode *mode = &state->adjusted_mode; + bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; + u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; +- u32 format = PV_CONTROL_FORMAT_24; ++ bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 || ++ vc4_encoder->type == VC4_ENCODER_TYPE_DSI1); ++ u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; + bool debug_dump_regs = false; +- int clock_select = vc4_get_clock_select(crtc); + + if (debug_dump_regs) { + DRM_INFO("CRTC %d regs before:\n", drm_crtc_index(crtc)); +@@ -439,17 +441,19 @@ static void vc4_crtc_mode_set_nofb(struc + */ + CRTC_WRITE(PV_V_CONTROL, + PV_VCONTROL_CONTINUOUS | ++ (is_dsi ? PV_VCONTROL_DSI : 0) | + PV_VCONTROL_INTERLACE | + VC4_SET_FIELD(mode->htotal * pixel_rep / 2, + PV_VCONTROL_ODD_DELAY)); + CRTC_WRITE(PV_VSYNCD_EVEN, 0); + } else { +- CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS); ++ CRTC_WRITE(PV_V_CONTROL, ++ PV_VCONTROL_CONTINUOUS | ++ (is_dsi ? PV_VCONTROL_DSI : 0)); + } + + CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); + +- + CRTC_WRITE(PV_CONTROL, + VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | + VC4_SET_FIELD(vc4_get_fifo_full_level(format), +@@ -458,7 +462,8 @@ static void vc4_crtc_mode_set_nofb(struc + PV_CONTROL_CLR_AT_START | + PV_CONTROL_TRIGGER_UNDERFLOW | + PV_CONTROL_WAIT_HSTART | +- VC4_SET_FIELD(clock_select, PV_CONTROL_CLK_SELECT) | ++ VC4_SET_FIELD(vc4_encoder->clock_select, ++ PV_CONTROL_CLK_SELECT) | + PV_CONTROL_FIFO_CLR | + PV_CONTROL_EN); + +--- a/drivers/gpu/drm/vc4/vc4_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_regs.h +@@ -190,6 +190,8 @@ + # define PV_VCONTROL_ODD_DELAY_SHIFT 6 + # define PV_VCONTROL_ODD_FIRST BIT(5) + # define PV_VCONTROL_INTERLACE BIT(4) ++# define PV_VCONTROL_DSI BIT(3) ++# define PV_VCONTROL_COMMAND BIT(2) + # define PV_VCONTROL_CONTINUOUS BIT(1) + # define PV_VCONTROL_VIDEN BIT(0) + diff --git a/target/linux/brcm2708/patches-4.9/0173-drm-vc4-Add-DSI-driver.patch b/target/linux/brcm2708/patches-4.9/0173-drm-vc4-Add-DSI-driver.patch new file mode 100644 index 0000000000..97ae4a470a --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0173-drm-vc4-Add-DSI-driver.patch @@ -0,0 +1,1817 @@ +From 38ea3f3665eaa9deedc3588196fe9ba9bb4032ec Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Wed, 10 Feb 2016 11:42:32 -0800 +Subject: [PATCH] drm/vc4: Add DSI driver + +The DSI0 and DSI1 blocks on the 2835 are related hardware blocks. +Some registers move around, and the featureset is slightly different, +as DSI1 (the 4-lane DSI) is a later version of the hardware block. +This driver doesn't yet enable DSI0, since we don't have any hardware +to test against, but it does put a lot of the register definitions and +code in place. + +Signed-off-by: Eric Anholt +--- + drivers/gpu/drm/vc4/Kconfig | 2 + + drivers/gpu/drm/vc4/Makefile | 1 + + drivers/gpu/drm/vc4/vc4_debugfs.c | 1 + + drivers/gpu/drm/vc4/vc4_drv.c | 1 + + drivers/gpu/drm/vc4/vc4_drv.h | 5 + + drivers/gpu/drm/vc4/vc4_dsi.c | 1725 +++++++++++++++++++++++++++++++++++++ + 6 files changed, 1735 insertions(+) + create mode 100644 drivers/gpu/drm/vc4/vc4_dsi.c + +--- a/drivers/gpu/drm/vc4/Kconfig ++++ b/drivers/gpu/drm/vc4/Kconfig +@@ -2,10 +2,12 @@ config DRM_VC4 + tristate "Broadcom VC4 Graphics" + depends on ARCH_BCM2835 || COMPILE_TEST + depends on DRM ++ depends on COMMON_CLK + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER + select DRM_PANEL ++ select DRM_MIPI_DSI + help + Choose this option if you have a system that has a Broadcom + VC4 GPU, such as the Raspberry Pi or other BCM2708/BCM2835. +--- a/drivers/gpu/drm/vc4/Makefile ++++ b/drivers/gpu/drm/vc4/Makefile +@@ -8,6 +8,7 @@ vc4-y := \ + vc4_crtc.o \ + vc4_drv.o \ + vc4_dpi.o \ ++ vc4_dsi.o \ + vc4_firmware_kms.o \ + vc4_kms.o \ + vc4_gem.o \ +--- a/drivers/gpu/drm/vc4/vc4_debugfs.c ++++ b/drivers/gpu/drm/vc4/vc4_debugfs.c +@@ -18,6 +18,7 @@ + static const struct drm_info_list vc4_debugfs_list[] = { + {"bo_stats", vc4_bo_stats_debugfs, 0}, + {"dpi_regs", vc4_dpi_debugfs_regs, 0}, ++ {"dsi1_regs", vc4_dsi_debugfs_regs, 0, (void *)(uintptr_t)1}, + {"hdmi_regs", vc4_hdmi_debugfs_regs, 0}, + {"vec_regs", vc4_vec_debugfs_regs, 0}, + {"hvs_regs", vc4_hvs_debugfs_regs, 0}, +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -296,6 +296,7 @@ static struct platform_driver *const com + &vc4_hdmi_driver, + &vc4_vec_driver, + &vc4_dpi_driver, ++ &vc4_dsi_driver, + &vc4_hvs_driver, + &vc4_crtc_driver, + &vc4_firmware_kms_driver, +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -20,6 +20,7 @@ struct vc4_dev { + struct vc4_crtc *crtc[3]; + struct vc4_v3d *v3d; + struct vc4_dpi *dpi; ++ struct vc4_dsi *dsi1; + struct vc4_vec *vec; + + struct drm_fbdev_cma *fbdev; +@@ -468,6 +469,10 @@ void __iomem *vc4_ioremap_regs(struct pl + extern struct platform_driver vc4_dpi_driver; + int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused); + ++/* vc4_dsi.c */ ++extern struct platform_driver vc4_dsi_driver; ++int vc4_dsi_debugfs_regs(struct seq_file *m, void *unused); ++ + /* vc4_firmware_kms.c */ + extern struct platform_driver vc4_firmware_kms_driver; + void vc4_fkms_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file); +--- /dev/null ++++ b/drivers/gpu/drm/vc4/vc4_dsi.c +@@ -0,0 +1,1725 @@ ++/* ++ * Copyright (C) 2016 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see . ++ */ ++ ++/** ++ * DOC: VC4 DSI0/DSI1 module ++ * ++ * BCM2835 contains two DSI modules, DSI0 and DSI1. DSI0 is a ++ * single-lane DSI controller, while DSI1 is a more modern 4-lane DSI ++ * controller. ++ * ++ * Most Raspberry Pi boards expose DSI1 as their "DISPLAY" connector, ++ * while the compute module brings both DSI0 and DSI1 out. ++ * ++ * This driver has been tested for DSI1 video-mode display only ++ * currently, with most of the information necessary for DSI0 ++ * hopefully present. ++ */ ++ ++#include "drm_atomic_helper.h" ++#include "drm_crtc_helper.h" ++#include "drm_edid.h" ++#include "drm_mipi_dsi.h" ++#include "drm_panel.h" ++#include "linux/clk.h" ++#include "linux/clk-provider.h" ++#include "linux/completion.h" ++#include "linux/component.h" ++#include "linux/dmaengine.h" ++#include "linux/i2c.h" ++#include "linux/of_address.h" ++#include "linux/of_platform.h" ++#include "linux/pm_runtime.h" ++#include "vc4_drv.h" ++#include "vc4_regs.h" ++ ++#define DSI_CMD_FIFO_DEPTH 16 ++#define DSI_PIX_FIFO_DEPTH 256 ++#define DSI_PIX_FIFO_WIDTH 4 ++ ++#define DSI0_CTRL 0x00 ++ ++/* Command packet control. */ ++#define DSI0_TXPKT1C 0x04 /* AKA PKTC */ ++#define DSI1_TXPKT1C 0x04 ++# define DSI_TXPKT1C_TRIG_CMD_MASK VC4_MASK(31, 24) ++# define DSI_TXPKT1C_TRIG_CMD_SHIFT 24 ++# define DSI_TXPKT1C_CMD_REPEAT_MASK VC4_MASK(23, 10) ++# define DSI_TXPKT1C_CMD_REPEAT_SHIFT 10 ++ ++# define DSI_TXPKT1C_DISPLAY_NO_MASK VC4_MASK(9, 8) ++# define DSI_TXPKT1C_DISPLAY_NO_SHIFT 8 ++/* Short, trigger, BTA, or a long packet that fits all in CMDFIFO. */ ++# define DSI_TXPKT1C_DISPLAY_NO_SHORT 0 ++/* Primary display where cmdfifo provides part of the payload and ++ * pixelvalve the rest. ++ */ ++# define DSI_TXPKT1C_DISPLAY_NO_PRIMARY 1 ++/* Secondary display where cmdfifo provides part of the payload and ++ * pixfifo the rest. ++ */ ++# define DSI_TXPKT1C_DISPLAY_NO_SECONDARY 2 ++ ++# define DSI_TXPKT1C_CMD_TX_TIME_MASK VC4_MASK(7, 6) ++# define DSI_TXPKT1C_CMD_TX_TIME_SHIFT 6 ++ ++# define DSI_TXPKT1C_CMD_CTRL_MASK VC4_MASK(5, 4) ++# define DSI_TXPKT1C_CMD_CTRL_SHIFT 4 ++/* Command only. Uses TXPKT1H and DISPLAY_NO */ ++# define DSI_TXPKT1C_CMD_CTRL_TX 0 ++/* Command with BTA for either ack or read data. */ ++# define DSI_TXPKT1C_CMD_CTRL_RX 1 ++/* Trigger according to TRIG_CMD */ ++# define DSI_TXPKT1C_CMD_CTRL_TRIG 2 ++/* BTA alone for getting error status after a command, or a TE trigger ++ * without a previous command. ++ */ ++# define DSI_TXPKT1C_CMD_CTRL_BTA 3 ++ ++# define DSI_TXPKT1C_CMD_MODE_LP BIT(3) ++# define DSI_TXPKT1C_CMD_TYPE_LONG BIT(2) ++# define DSI_TXPKT1C_CMD_TE_EN BIT(1) ++# define DSI_TXPKT1C_CMD_EN BIT(0) ++ ++/* Command packet header. */ ++#define DSI0_TXPKT1H 0x08 /* AKA PKTH */ ++#define DSI1_TXPKT1H 0x08 ++# define DSI_TXPKT1H_BC_CMDFIFO_MASK VC4_MASK(31, 24) ++# define DSI_TXPKT1H_BC_CMDFIFO_SHIFT 24 ++# define DSI_TXPKT1H_BC_PARAM_MASK VC4_MASK(23, 8) ++# define DSI_TXPKT1H_BC_PARAM_SHIFT 8 ++# define DSI_TXPKT1H_BC_DT_MASK VC4_MASK(7, 0) ++# define DSI_TXPKT1H_BC_DT_SHIFT 0 ++ ++#define DSI0_RXPKT1H 0x0c /* AKA RX1_PKTH */ ++#define DSI1_RXPKT1H 0x14 ++# define DSI_RXPKT1H_CRC_ERR BIT(31) ++# define DSI_RXPKT1H_DET_ERR BIT(30) ++# define DSI_RXPKT1H_ECC_ERR BIT(29) ++# define DSI_RXPKT1H_COR_ERR BIT(28) ++# define DSI_RXPKT1H_INCOMP_PKT BIT(25) ++# define DSI_RXPKT1H_PKT_TYPE_LONG BIT(24) ++/* Byte count if DSI_RXPKT1H_PKT_TYPE_LONG */ ++# define DSI_RXPKT1H_BC_PARAM_MASK VC4_MASK(23, 8) ++# define DSI_RXPKT1H_BC_PARAM_SHIFT 8 ++/* Short return bytes if !DSI_RXPKT1H_PKT_TYPE_LONG */ ++# define DSI_RXPKT1H_SHORT_1_MASK VC4_MASK(23, 16) ++# define DSI_RXPKT1H_SHORT_1_SHIFT 16 ++# define DSI_RXPKT1H_SHORT_0_MASK VC4_MASK(15, 8) ++# define DSI_RXPKT1H_SHORT_0_SHIFT 8 ++# define DSI_RXPKT1H_DT_LP_CMD_MASK VC4_MASK(7, 0) ++# define DSI_RXPKT1H_DT_LP_CMD_SHIFT 0 ++ ++#define DSI0_RXPKT2H 0x10 /* AKA RX2_PKTH */ ++#define DSI1_RXPKT2H 0x18 ++# define DSI_RXPKT1H_DET_ERR BIT(30) ++# define DSI_RXPKT1H_ECC_ERR BIT(29) ++# define DSI_RXPKT1H_COR_ERR BIT(28) ++# define DSI_RXPKT1H_INCOMP_PKT BIT(25) ++# define DSI_RXPKT1H_BC_PARAM_MASK VC4_MASK(23, 8) ++# define DSI_RXPKT1H_BC_PARAM_SHIFT 8 ++# define DSI_RXPKT1H_DT_MASK VC4_MASK(7, 0) ++# define DSI_RXPKT1H_DT_SHIFT 0 ++ ++#define DSI0_TXPKT_CMD_FIFO 0x14 /* AKA CMD_DATAF */ ++#define DSI1_TXPKT_CMD_FIFO 0x1c ++ ++#define DSI0_DISP0_CTRL 0x18 ++# define DSI_DISP0_PIX_CLK_DIV_MASK VC4_MASK(21, 13) ++# define DSI_DISP0_PIX_CLK_DIV_SHIFT 13 ++# define DSI_DISP0_LP_STOP_CTRL_MASK VC4_MASK(12, 11) ++# define DSI_DISP0_LP_STOP_CTRL_SHIFT 11 ++# define DSI_DISP0_LP_STOP_DISABLE 0 ++# define DSI_DISP0_LP_STOP_PERLINE 1 ++# define DSI_DISP0_LP_STOP_PERFRAME 2 ++ ++/* Transmit RGB pixels and null packets only during HACTIVE, instead ++ * of going to LP-STOP. ++ */ ++# define DSI_DISP_HACTIVE_NULL BIT(10) ++/* Transmit blanking packet only during vblank, instead of allowing LP-STOP. */ ++# define DSI_DISP_VBLP_CTRL BIT(9) ++/* Transmit blanking packet only during HFP, instead of allowing LP-STOP. */ ++# define DSI_DISP_HFP_CTRL BIT(8) ++/* Transmit blanking packet only during HBP, instead of allowing LP-STOP. */ ++# define DSI_DISP_HBP_CTRL BIT(7) ++# define DSI_DISP0_CHANNEL_MASK VC4_MASK(6, 5) ++# define DSI_DISP0_CHANNEL_SHIFT 5 ++/* Enables end events for HSYNC/VSYNC, not just start events. */ ++# define DSI_DISP0_ST_END BIT(4) ++# define DSI_DISP0_PFORMAT_MASK VC4_MASK(3, 2) ++# define DSI_DISP0_PFORMAT_SHIFT 2 ++# define DSI_PFORMAT_RGB565 0 ++# define DSI_PFORMAT_RGB666_PACKED 1 ++# define DSI_PFORMAT_RGB666 2 ++# define DSI_PFORMAT_RGB888 3 ++/* Default is VIDEO mode. */ ++# define DSI_DISP0_COMMAND_MODE BIT(1) ++# define DSI_DISP0_ENABLE BIT(0) ++ ++#define DSI0_DISP1_CTRL 0x1c ++#define DSI1_DISP1_CTRL 0x2c ++/* Format of the data written to TXPKT_PIX_FIFO. */ ++# define DSI_DISP1_PFORMAT_MASK VC4_MASK(2, 1) ++# define DSI_DISP1_PFORMAT_SHIFT 1 ++# define DSI_DISP1_PFORMAT_16BIT 0 ++# define DSI_DISP1_PFORMAT_24BIT 1 ++# define DSI_DISP1_PFORMAT_32BIT_LE 2 ++# define DSI_DISP1_PFORMAT_32BIT_BE 3 ++ ++/* DISP1 is always command mode. */ ++# define DSI_DISP1_ENABLE BIT(0) ++ ++#define DSI0_TXPKT_PIX_FIFO 0x20 /* AKA PIX_FIFO */ ++ ++#define DSI0_INT_STAT 0x24 ++#define DSI0_INT_EN 0x28 ++# define DSI1_INT_PHY_D3_ULPS BIT(30) ++# define DSI1_INT_PHY_D3_STOP BIT(29) ++# define DSI1_INT_PHY_D2_ULPS BIT(28) ++# define DSI1_INT_PHY_D2_STOP BIT(27) ++# define DSI1_INT_PHY_D1_ULPS BIT(26) ++# define DSI1_INT_PHY_D1_STOP BIT(25) ++# define DSI1_INT_PHY_D0_ULPS BIT(24) ++# define DSI1_INT_PHY_D0_STOP BIT(23) ++# define DSI1_INT_FIFO_ERR BIT(22) ++# define DSI1_INT_PHY_DIR_RTF BIT(21) ++# define DSI1_INT_PHY_RXLPDT BIT(20) ++# define DSI1_INT_PHY_RXTRIG BIT(19) ++# define DSI1_INT_PHY_D0_LPDT BIT(18) ++# define DSI1_INT_PHY_DIR_FTR BIT(17) ++ ++/* Signaled when the clock lane enters the given state. */ ++# define DSI1_INT_PHY_CLOCK_ULPS BIT(16) ++# define DSI1_INT_PHY_CLOCK_HS BIT(15) ++# define DSI1_INT_PHY_CLOCK_STOP BIT(14) ++ ++/* Signaled on timeouts */ ++# define DSI1_INT_PR_TO BIT(13) ++# define DSI1_INT_TA_TO BIT(12) ++# define DSI1_INT_LPRX_TO BIT(11) ++# define DSI1_INT_HSTX_TO BIT(10) ++ ++/* Contention on a line when trying to drive the line low */ ++# define DSI1_INT_ERR_CONT_LP1 BIT(9) ++# define DSI1_INT_ERR_CONT_LP0 BIT(8) ++ ++/* Control error: incorrect line state sequence on data lane 0. */ ++# define DSI1_INT_ERR_CONTROL BIT(7) ++/* LPDT synchronization error (bits received not a multiple of 8. */ ++ ++# define DSI1_INT_ERR_SYNC_ESC BIT(6) ++/* Signaled after receiving an error packet from the display in ++ * response to a read. ++ */ ++# define DSI1_INT_RXPKT2 BIT(5) ++/* Signaled after receiving a packet. The header and optional short ++ * response will be in RXPKT1H, and a long response will be in the ++ * RXPKT_FIFO. ++ */ ++# define DSI1_INT_RXPKT1 BIT(4) ++# define DSI1_INT_TXPKT2_DONE BIT(3) ++# define DSI1_INT_TXPKT2_END BIT(2) ++/* Signaled after all repeats of TXPKT1 are transferred. */ ++# define DSI1_INT_TXPKT1_DONE BIT(1) ++/* Signaled after each TXPKT1 repeat is scheduled. */ ++# define DSI1_INT_TXPKT1_END BIT(0) ++ ++#define DSI1_INTERRUPTS_ALWAYS_ENABLED (DSI1_INT_ERR_SYNC_ESC | \ ++ DSI1_INT_ERR_CONTROL | \ ++ DSI1_INT_ERR_CONT_LP0 | \ ++ DSI1_INT_ERR_CONT_LP1 | \ ++ DSI1_INT_HSTX_TO | \ ++ DSI1_INT_LPRX_TO | \ ++ DSI1_INT_TA_TO | \ ++ DSI1_INT_PR_TO) ++ ++#define DSI0_STAT 0x2c ++#define DSI0_HSTX_TO_CNT 0x30 ++#define DSI0_LPRX_TO_CNT 0x34 ++#define DSI0_TA_TO_CNT 0x38 ++#define DSI0_PR_TO_CNT 0x3c ++#define DSI0_PHYC 0x40 ++# define DSI1_PHYC_ESC_CLK_LPDT_MASK VC4_MASK(25, 20) ++# define DSI1_PHYC_ESC_CLK_LPDT_SHIFT 20 ++# define DSI1_PHYC_HS_CLK_CONTINUOUS BIT(18) ++# define DSI0_PHYC_ESC_CLK_LPDT_MASK VC4_MASK(17, 12) ++# define DSI0_PHYC_ESC_CLK_LPDT_SHIFT 12 ++# define DSI1_PHYC_CLANE_ULPS BIT(17) ++# define DSI1_PHYC_CLANE_ENABLE BIT(16) ++# define DSI_PHYC_DLANE3_ULPS BIT(13) ++# define DSI_PHYC_DLANE3_ENABLE BIT(12) ++# define DSI0_PHYC_HS_CLK_CONTINUOUS BIT(10) ++# define DSI0_PHYC_CLANE_ULPS BIT(9) ++# define DSI_PHYC_DLANE2_ULPS BIT(9) ++# define DSI0_PHYC_CLANE_ENABLE BIT(8) ++# define DSI_PHYC_DLANE2_ENABLE BIT(8) ++# define DSI_PHYC_DLANE1_ULPS BIT(5) ++# define DSI_PHYC_DLANE1_ENABLE BIT(4) ++# define DSI_PHYC_DLANE0_FORCE_STOP BIT(2) ++# define DSI_PHYC_DLANE0_ULPS BIT(1) ++# define DSI_PHYC_DLANE0_ENABLE BIT(0) ++ ++#define DSI0_HS_CLT0 0x44 ++#define DSI0_HS_CLT1 0x48 ++#define DSI0_HS_CLT2 0x4c ++#define DSI0_HS_DLT3 0x50 ++#define DSI0_HS_DLT4 0x54 ++#define DSI0_HS_DLT5 0x58 ++#define DSI0_HS_DLT6 0x5c ++#define DSI0_HS_DLT7 0x60 ++ ++#define DSI0_PHY_AFEC0 0x64 ++# define DSI0_PHY_AFEC0_DDR2CLK_EN BIT(26) ++# define DSI0_PHY_AFEC0_DDRCLK_EN BIT(25) ++# define DSI0_PHY_AFEC0_LATCH_ULPS BIT(24) ++# define DSI1_PHY_AFEC0_IDR_DLANE3_MASK VC4_MASK(31, 29) ++# define DSI1_PHY_AFEC0_IDR_DLANE3_SHIFT 29 ++# define DSI1_PHY_AFEC0_IDR_DLANE2_MASK VC4_MASK(28, 26) ++# define DSI1_PHY_AFEC0_IDR_DLANE2_SHIFT 26 ++# define DSI1_PHY_AFEC0_IDR_DLANE1_MASK VC4_MASK(27, 23) ++# define DSI1_PHY_AFEC0_IDR_DLANE1_SHIFT 23 ++# define DSI1_PHY_AFEC0_IDR_DLANE0_MASK VC4_MASK(22, 20) ++# define DSI1_PHY_AFEC0_IDR_DLANE0_SHIFT 20 ++# define DSI1_PHY_AFEC0_IDR_CLANE_MASK VC4_MASK(19, 17) ++# define DSI1_PHY_AFEC0_IDR_CLANE_SHIFT 17 ++# define DSI0_PHY_AFEC0_ACTRL_DLANE1_MASK VC4_MASK(23, 20) ++# define DSI0_PHY_AFEC0_ACTRL_DLANE1_SHIFT 20 ++# define DSI0_PHY_AFEC0_ACTRL_DLANE0_MASK VC4_MASK(19, 16) ++# define DSI0_PHY_AFEC0_ACTRL_DLANE0_SHIFT 16 ++# define DSI0_PHY_AFEC0_ACTRL_CLANE_MASK VC4_MASK(15, 12) ++# define DSI0_PHY_AFEC0_ACTRL_CLANE_SHIFT 12 ++# define DSI1_PHY_AFEC0_DDR2CLK_EN BIT(16) ++# define DSI1_PHY_AFEC0_DDRCLK_EN BIT(15) ++# define DSI1_PHY_AFEC0_LATCH_ULPS BIT(14) ++# define DSI1_PHY_AFEC0_RESET BIT(13) ++# define DSI1_PHY_AFEC0_PD BIT(12) ++# define DSI0_PHY_AFEC0_RESET BIT(11) ++# define DSI1_PHY_AFEC0_PD_BG BIT(11) ++# define DSI0_PHY_AFEC0_PD BIT(10) ++# define DSI1_PHY_AFEC0_PD_DLANE3 BIT(10) ++# define DSI0_PHY_AFEC0_PD_BG BIT(9) ++# define DSI1_PHY_AFEC0_PD_DLANE2 BIT(9) ++# define DSI0_PHY_AFEC0_PD_DLANE1 BIT(8) ++# define DSI1_PHY_AFEC0_PD_DLANE1 BIT(8) ++# define DSI_PHY_AFEC0_PTATADJ_MASK VC4_MASK(7, 4) ++# define DSI_PHY_AFEC0_PTATADJ_SHIFT 4 ++# define DSI_PHY_AFEC0_CTATADJ_MASK VC4_MASK(3, 0) ++# define DSI_PHY_AFEC0_CTATADJ_SHIFT 0 ++ ++#define DSI0_PHY_AFEC1 0x68 ++# define DSI0_PHY_AFEC1_IDR_DLANE1_MASK VC4_MASK(10, 8) ++# define DSI0_PHY_AFEC1_IDR_DLANE1_SHIFT 8 ++# define DSI0_PHY_AFEC1_IDR_DLANE0_MASK VC4_MASK(6, 4) ++# define DSI0_PHY_AFEC1_IDR_DLANE0_SHIFT 4 ++# define DSI0_PHY_AFEC1_IDR_CLANE_MASK VC4_MASK(2, 0) ++# define DSI0_PHY_AFEC1_IDR_CLANE_SHIFT 0 ++ ++#define DSI0_TST_SEL 0x6c ++#define DSI0_TST_MON 0x70 ++#define DSI0_ID 0x74 ++# define DSI_ID_VALUE 0x00647369 ++ ++#define DSI1_CTRL 0x00 ++# define DSI_CTRL_HS_CLKC_MASK VC4_MASK(15, 14) ++# define DSI_CTRL_HS_CLKC_SHIFT 14 ++# define DSI_CTRL_HS_CLKC_BYTE 0 ++# define DSI_CTRL_HS_CLKC_DDR2 1 ++# define DSI_CTRL_HS_CLKC_DDR 2 ++ ++# define DSI_CTRL_RX_LPDT_EOT_DISABLE BIT(13) ++# define DSI_CTRL_LPDT_EOT_DISABLE BIT(12) ++# define DSI_CTRL_HSDT_EOT_DISABLE BIT(11) ++# define DSI_CTRL_SOFT_RESET_CFG BIT(10) ++# define DSI_CTRL_CAL_BYTE BIT(9) ++# define DSI_CTRL_INV_BYTE BIT(8) ++# define DSI_CTRL_CLR_LDF BIT(7) ++# define DSI0_CTRL_CLR_PBCF BIT(6) ++# define DSI1_CTRL_CLR_RXF BIT(6) ++# define DSI0_CTRL_CLR_CPBCF BIT(5) ++# define DSI1_CTRL_CLR_PDF BIT(5) ++# define DSI0_CTRL_CLR_PDF BIT(4) ++# define DSI1_CTRL_CLR_CDF BIT(4) ++# define DSI0_CTRL_CLR_CDF BIT(3) ++# define DSI0_CTRL_CTRL2 BIT(2) ++# define DSI1_CTRL_DISABLE_DISP_CRCC BIT(2) ++# define DSI0_CTRL_CTRL1 BIT(1) ++# define DSI1_CTRL_DISABLE_DISP_ECCC BIT(1) ++# define DSI0_CTRL_CTRL0 BIT(0) ++# define DSI1_CTRL_EN BIT(0) ++# define DSI0_CTRL_RESET_FIFOS (DSI_CTRL_CLR_LDF | \ ++ DSI0_CTRL_CLR_PBCF | \ ++ DSI0_CTRL_CLR_CPBCF | \ ++ DSI0_CTRL_CLR_PDF | \ ++ DSI0_CTRL_CLR_CDF) ++# define DSI1_CTRL_RESET_FIFOS (DSI_CTRL_CLR_LDF | \ ++ DSI1_CTRL_CLR_RXF | \ ++ DSI1_CTRL_CLR_PDF | \ ++ DSI1_CTRL_CLR_CDF) ++ ++#define DSI1_TXPKT2C 0x0c ++#define DSI1_TXPKT2H 0x10 ++#define DSI1_TXPKT_PIX_FIFO 0x20 ++#define DSI1_RXPKT_FIFO 0x24 ++#define DSI1_DISP0_CTRL 0x28 ++#define DSI1_INT_STAT 0x30 ++#define DSI1_INT_EN 0x34 ++/* State reporting bits. These mostly behave like INT_STAT, where ++ * writing a 1 clears the bit. ++ */ ++#define DSI1_STAT 0x38 ++# define DSI1_STAT_PHY_D3_ULPS BIT(31) ++# define DSI1_STAT_PHY_D3_STOP BIT(30) ++# define DSI1_STAT_PHY_D2_ULPS BIT(29) ++# define DSI1_STAT_PHY_D2_STOP BIT(28) ++# define DSI1_STAT_PHY_D1_ULPS BIT(27) ++# define DSI1_STAT_PHY_D1_STOP BIT(26) ++# define DSI1_STAT_PHY_D0_ULPS BIT(25) ++# define DSI1_STAT_PHY_D0_STOP BIT(24) ++# define DSI1_STAT_FIFO_ERR BIT(23) ++# define DSI1_STAT_PHY_RXLPDT BIT(22) ++# define DSI1_STAT_PHY_RXTRIG BIT(21) ++# define DSI1_STAT_PHY_D0_LPDT BIT(20) ++/* Set when in forward direction */ ++# define DSI1_STAT_PHY_DIR BIT(19) ++# define DSI1_STAT_PHY_CLOCK_ULPS BIT(18) ++# define DSI1_STAT_PHY_CLOCK_HS BIT(17) ++# define DSI1_STAT_PHY_CLOCK_STOP BIT(16) ++# define DSI1_STAT_PR_TO BIT(15) ++# define DSI1_STAT_TA_TO BIT(14) ++# define DSI1_STAT_LPRX_TO BIT(13) ++# define DSI1_STAT_HSTX_TO BIT(12) ++# define DSI1_STAT_ERR_CONT_LP1 BIT(11) ++# define DSI1_STAT_ERR_CONT_LP0 BIT(10) ++# define DSI1_STAT_ERR_CONTROL BIT(9) ++# define DSI1_STAT_ERR_SYNC_ESC BIT(8) ++# define DSI1_STAT_RXPKT2 BIT(7) ++# define DSI1_STAT_RXPKT1 BIT(6) ++# define DSI1_STAT_TXPKT2_BUSY BIT(5) ++# define DSI1_STAT_TXPKT2_DONE BIT(4) ++# define DSI1_STAT_TXPKT2_END BIT(3) ++# define DSI1_STAT_TXPKT1_BUSY BIT(2) ++# define DSI1_STAT_TXPKT1_DONE BIT(1) ++# define DSI1_STAT_TXPKT1_END BIT(0) ++ ++#define DSI1_HSTX_TO_CNT 0x3c ++#define DSI1_LPRX_TO_CNT 0x40 ++#define DSI1_TA_TO_CNT 0x44 ++#define DSI1_PR_TO_CNT 0x48 ++#define DSI1_PHYC 0x4c ++ ++#define DSI1_HS_CLT0 0x50 ++# define DSI_HS_CLT0_CZERO_MASK VC4_MASK(26, 18) ++# define DSI_HS_CLT0_CZERO_SHIFT 18 ++# define DSI_HS_CLT0_CPRE_MASK VC4_MASK(17, 9) ++# define DSI_HS_CLT0_CPRE_SHIFT 9 ++# define DSI_HS_CLT0_CPREP_MASK VC4_MASK(8, 0) ++# define DSI_HS_CLT0_CPREP_SHIFT 0 ++ ++#define DSI1_HS_CLT1 0x54 ++# define DSI_HS_CLT1_CTRAIL_MASK VC4_MASK(17, 9) ++# define DSI_HS_CLT1_CTRAIL_SHIFT 9 ++# define DSI_HS_CLT1_CPOST_MASK VC4_MASK(8, 0) ++# define DSI_HS_CLT1_CPOST_SHIFT 0 ++ ++#define DSI1_HS_CLT2 0x58 ++# define DSI_HS_CLT2_WUP_MASK VC4_MASK(23, 0) ++# define DSI_HS_CLT2_WUP_SHIFT 0 ++ ++#define DSI1_HS_DLT3 0x5c ++# define DSI_HS_DLT3_EXIT_MASK VC4_MASK(26, 18) ++# define DSI_HS_DLT3_EXIT_SHIFT 18 ++# define DSI_HS_DLT3_ZERO_MASK VC4_MASK(17, 9) ++# define DSI_HS_DLT3_ZERO_SHIFT 9 ++# define DSI_HS_DLT3_PRE_MASK VC4_MASK(8, 0) ++# define DSI_HS_DLT3_PRE_SHIFT 0 ++ ++#define DSI1_HS_DLT4 0x60 ++# define DSI_HS_DLT4_ANLAT_MASK VC4_MASK(22, 18) ++# define DSI_HS_DLT4_ANLAT_SHIFT 18 ++# define DSI_HS_DLT4_TRAIL_MASK VC4_MASK(17, 9) ++# define DSI_HS_DLT4_TRAIL_SHIFT 9 ++# define DSI_HS_DLT4_LPX_MASK VC4_MASK(8, 0) ++# define DSI_HS_DLT4_LPX_SHIFT 0 ++ ++#define DSI1_HS_DLT5 0x64 ++# define DSI_HS_DLT5_INIT_MASK VC4_MASK(23, 0) ++# define DSI_HS_DLT5_INIT_SHIFT 0 ++ ++#define DSI1_HS_DLT6 0x68 ++# define DSI_HS_DLT6_TA_GET_MASK VC4_MASK(31, 24) ++# define DSI_HS_DLT6_TA_GET_SHIFT 24 ++# define DSI_HS_DLT6_TA_SURE_MASK VC4_MASK(23, 16) ++# define DSI_HS_DLT6_TA_SURE_SHIFT 16 ++# define DSI_HS_DLT6_TA_GO_MASK VC4_MASK(15, 8) ++# define DSI_HS_DLT6_TA_GO_SHIFT 8 ++# define DSI_HS_DLT6_LP_LPX_MASK VC4_MASK(7, 0) ++# define DSI_HS_DLT6_LP_LPX_SHIFT 0 ++ ++#define DSI1_HS_DLT7 0x6c ++# define DSI_HS_DLT7_LP_WUP_MASK VC4_MASK(23, 0) ++# define DSI_HS_DLT7_LP_WUP_SHIFT 0 ++ ++#define DSI1_PHY_AFEC0 0x70 ++ ++#define DSI1_PHY_AFEC1 0x74 ++# define DSI1_PHY_AFEC1_ACTRL_DLANE3_MASK VC4_MASK(19, 16) ++# define DSI1_PHY_AFEC1_ACTRL_DLANE3_SHIFT 16 ++# define DSI1_PHY_AFEC1_ACTRL_DLANE2_MASK VC4_MASK(15, 12) ++# define DSI1_PHY_AFEC1_ACTRL_DLANE2_SHIFT 12 ++# define DSI1_PHY_AFEC1_ACTRL_DLANE1_MASK VC4_MASK(11, 8) ++# define DSI1_PHY_AFEC1_ACTRL_DLANE1_SHIFT 8 ++# define DSI1_PHY_AFEC1_ACTRL_DLANE0_MASK VC4_MASK(7, 4) ++# define DSI1_PHY_AFEC1_ACTRL_DLANE0_SHIFT 4 ++# define DSI1_PHY_AFEC1_ACTRL_CLANE_MASK VC4_MASK(3, 0) ++# define DSI1_PHY_AFEC1_ACTRL_CLANE_SHIFT 0 ++ ++#define DSI1_TST_SEL 0x78 ++#define DSI1_TST_MON 0x7c ++#define DSI1_PHY_TST1 0x80 ++#define DSI1_PHY_TST2 0x84 ++#define DSI1_PHY_FIFO_STAT 0x88 ++/* Actually, all registers in the range that aren't otherwise claimed ++ * will return the ID. ++ */ ++#define DSI1_ID 0x8c ++ ++/* General DSI hardware state. */ ++struct vc4_dsi { ++ struct platform_device *pdev; ++ ++ struct mipi_dsi_host dsi_host; ++ struct drm_encoder *encoder; ++ struct drm_connector *connector; ++ struct drm_panel *panel; ++ ++ void __iomem *regs; ++ ++ struct dma_chan *reg_dma_chan; ++ dma_addr_t reg_dma_paddr; ++ u32 *reg_dma_mem; ++ dma_addr_t reg_paddr; ++ ++ /* Whether we're on bcm2835's DSI0 or DSI1. */ ++ int port; ++ ++ /* DSI channel for the panel we're connected to. */ ++ u32 channel; ++ u32 lanes; ++ enum mipi_dsi_pixel_format format; ++ u32 mode_flags; ++ ++ /* Input clock from CPRMAN to the digital PHY, for the DSI ++ * escape clock. ++ */ ++ struct clk *escape_clock; ++ ++ /* Input clock to the analog PHY, used to generate the DSI bit ++ * clock. ++ */ ++ struct clk *pll_phy_clock; ++ ++ /* HS Clocks generated within the DSI analog PHY. */ ++ struct clk_fixed_factor phy_clocks[3]; ++ ++ struct clk_onecell_data clk_onecell; ++ ++ /* Pixel clock output to the pixelvalve, generated from the HS ++ * clock. ++ */ ++ struct clk *pixel_clock; ++ ++ struct completion xfer_completion; ++ int xfer_result; ++}; ++ ++#define host_to_dsi(host) container_of(host, struct vc4_dsi, dsi_host) ++ ++static inline void ++dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val) ++{ ++ struct dma_chan *chan = dsi->reg_dma_chan; ++ struct dma_async_tx_descriptor *tx; ++ dma_cookie_t cookie; ++ int ret; ++ ++ /* DSI0 should be able to write normally. */ ++ if (!chan) { ++ writel(val, dsi->regs + offset); ++ return; ++ } ++ ++ *dsi->reg_dma_mem = val; ++ ++ tx = chan->device->device_prep_dma_memcpy(chan, ++ dsi->reg_paddr + offset, ++ dsi->reg_dma_paddr, ++ 4, 0); ++ if (!tx) { ++ DRM_ERROR("Failed to set up DMA register write\n"); ++ return; ++ } ++ ++ cookie = tx->tx_submit(tx); ++ ret = dma_submit_error(cookie); ++ if (ret) { ++ DRM_ERROR("Failed to submit DMA: %d\n", ret); ++ return; ++ } ++ ret = dma_sync_wait(chan, cookie); ++ if (ret) ++ DRM_ERROR("Failed to wait for DMA: %d\n", ret); ++} ++ ++#define DSI_READ(offset) readl(dsi->regs + (offset)) ++#define DSI_WRITE(offset, val) dsi_dma_workaround_write(dsi, offset, val) ++#define DSI_PORT_READ(offset) \ ++ DSI_READ(dsi->port ? DSI1_##offset : DSI0_##offset) ++#define DSI_PORT_WRITE(offset, val) \ ++ DSI_WRITE(dsi->port ? DSI1_##offset : DSI0_##offset, val) ++#define DSI_PORT_BIT(bit) (dsi->port ? DSI1_##bit : DSI0_##bit) ++ ++/* VC4 DSI encoder KMS struct */ ++struct vc4_dsi_encoder { ++ struct vc4_encoder base; ++ struct vc4_dsi *dsi; ++}; ++ ++static inline struct vc4_dsi_encoder * ++to_vc4_dsi_encoder(struct drm_encoder *encoder) ++{ ++ return container_of(encoder, struct vc4_dsi_encoder, base.base); ++} ++ ++/* VC4 DSI connector KMS struct */ ++struct vc4_dsi_connector { ++ struct drm_connector base; ++ struct vc4_dsi *dsi; ++}; ++ ++static inline struct vc4_dsi_connector * ++to_vc4_dsi_connector(struct drm_connector *connector) ++{ ++ return container_of(connector, struct vc4_dsi_connector, base); ++} ++ ++#define DSI_REG(reg) { reg, #reg } ++static const struct { ++ u32 reg; ++ const char *name; ++} dsi0_regs[] = { ++ DSI_REG(DSI0_CTRL), ++ DSI_REG(DSI0_STAT), ++ DSI_REG(DSI0_HSTX_TO_CNT), ++ DSI_REG(DSI0_LPRX_TO_CNT), ++ DSI_REG(DSI0_TA_TO_CNT), ++ DSI_REG(DSI0_PR_TO_CNT), ++ DSI_REG(DSI0_DISP0_CTRL), ++ DSI_REG(DSI0_DISP1_CTRL), ++ DSI_REG(DSI0_INT_STAT), ++ DSI_REG(DSI0_INT_EN), ++ DSI_REG(DSI0_PHYC), ++ DSI_REG(DSI0_HS_CLT0), ++ DSI_REG(DSI0_HS_CLT1), ++ DSI_REG(DSI0_HS_CLT2), ++ DSI_REG(DSI0_HS_DLT3), ++ DSI_REG(DSI0_HS_DLT4), ++ DSI_REG(DSI0_HS_DLT5), ++ DSI_REG(DSI0_HS_DLT6), ++ DSI_REG(DSI0_HS_DLT7), ++ DSI_REG(DSI0_PHY_AFEC0), ++ DSI_REG(DSI0_PHY_AFEC1), ++ DSI_REG(DSI0_ID), ++}; ++ ++static const struct { ++ u32 reg; ++ const char *name; ++} dsi1_regs[] = { ++ DSI_REG(DSI1_CTRL), ++ DSI_REG(DSI1_STAT), ++ DSI_REG(DSI1_HSTX_TO_CNT), ++ DSI_REG(DSI1_LPRX_TO_CNT), ++ DSI_REG(DSI1_TA_TO_CNT), ++ DSI_REG(DSI1_PR_TO_CNT), ++ DSI_REG(DSI1_DISP0_CTRL), ++ DSI_REG(DSI1_DISP1_CTRL), ++ DSI_REG(DSI1_INT_STAT), ++ DSI_REG(DSI1_INT_EN), ++ DSI_REG(DSI1_PHYC), ++ DSI_REG(DSI1_HS_CLT0), ++ DSI_REG(DSI1_HS_CLT1), ++ DSI_REG(DSI1_HS_CLT2), ++ DSI_REG(DSI1_HS_DLT3), ++ DSI_REG(DSI1_HS_DLT4), ++ DSI_REG(DSI1_HS_DLT5), ++ DSI_REG(DSI1_HS_DLT6), ++ DSI_REG(DSI1_HS_DLT7), ++ DSI_REG(DSI1_PHY_AFEC0), ++ DSI_REG(DSI1_PHY_AFEC1), ++ DSI_REG(DSI1_ID), ++}; ++ ++static void vc4_dsi_dump_regs(struct vc4_dsi *dsi) ++{ ++ int i; ++ ++ if (dsi->port == 0) { ++ for (i = 0; i < ARRAY_SIZE(dsi0_regs); i++) { ++ DRM_INFO("0x%04x (%s): 0x%08x\n", ++ dsi0_regs[i].reg, dsi0_regs[i].name, ++ DSI_READ(dsi0_regs[i].reg)); ++ } ++ } else { ++ for (i = 0; i < ARRAY_SIZE(dsi1_regs); i++) { ++ DRM_INFO("0x%04x (%s): 0x%08x\n", ++ dsi1_regs[i].reg, dsi1_regs[i].name, ++ DSI_READ(dsi1_regs[i].reg)); ++ } ++ } ++} ++ ++#ifdef CONFIG_DEBUG_FS ++int vc4_dsi_debugfs_regs(struct seq_file *m, void *unused) ++{ ++ struct drm_info_node *node = (struct drm_info_node *)m->private; ++ struct drm_device *drm = node->minor->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(drm); ++ int dsi_index = (uintptr_t)node->info_ent->data; ++ struct vc4_dsi *dsi = (dsi_index == 1 ? vc4->dsi1 : NULL); ++ int i; ++ ++ if (!dsi) ++ return 0; ++ ++ if (dsi->port == 0) { ++ for (i = 0; i < ARRAY_SIZE(dsi0_regs); i++) { ++ seq_printf(m, "0x%04x (%s): 0x%08x\n", ++ dsi0_regs[i].reg, dsi0_regs[i].name, ++ DSI_READ(dsi0_regs[i].reg)); ++ } ++ } else { ++ for (i = 0; i < ARRAY_SIZE(dsi1_regs); i++) { ++ seq_printf(m, "0x%04x (%s): 0x%08x\n", ++ dsi1_regs[i].reg, dsi1_regs[i].name, ++ DSI_READ(dsi1_regs[i].reg)); ++ } ++ } ++ ++ return 0; ++} ++#endif ++ ++static enum drm_connector_status ++vc4_dsi_connector_detect(struct drm_connector *connector, bool force) ++{ ++ struct vc4_dsi_connector *vc4_connector = ++ to_vc4_dsi_connector(connector); ++ struct vc4_dsi *dsi = vc4_connector->dsi; ++ ++ if (dsi->panel) ++ return connector_status_connected; ++ else ++ return connector_status_disconnected; ++} ++ ++static void vc4_dsi_connector_destroy(struct drm_connector *connector) ++{ ++ drm_connector_unregister(connector); ++ drm_connector_cleanup(connector); ++} ++ ++static int vc4_dsi_connector_get_modes(struct drm_connector *connector) ++{ ++ struct vc4_dsi_connector *vc4_connector = ++ to_vc4_dsi_connector(connector); ++ struct vc4_dsi *dsi = vc4_connector->dsi; ++ ++ if (dsi->panel) ++ return drm_panel_get_modes(dsi->panel); ++ ++ return 0; ++} ++ ++static const struct drm_connector_funcs vc4_dsi_connector_funcs = { ++ .dpms = drm_atomic_helper_connector_dpms, ++ .detect = vc4_dsi_connector_detect, ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .destroy = vc4_dsi_connector_destroy, ++ .reset = drm_atomic_helper_connector_reset, ++ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, ++}; ++ ++static const struct drm_connector_helper_funcs vc4_dsi_connector_helper_funcs = { ++ .get_modes = vc4_dsi_connector_get_modes, ++}; ++ ++static struct drm_connector *vc4_dsi_connector_init(struct drm_device *dev, ++ struct vc4_dsi *dsi) ++{ ++ struct drm_connector *connector = NULL; ++ struct vc4_dsi_connector *dsi_connector; ++ int ret = 0; ++ ++ dsi_connector = devm_kzalloc(dev->dev, sizeof(*dsi_connector), ++ GFP_KERNEL); ++ if (!dsi_connector) { ++ ret = -ENOMEM; ++ goto fail; ++ } ++ connector = &dsi_connector->base; ++ ++ dsi_connector->dsi = dsi; ++ ++ drm_connector_init(dev, connector, &vc4_dsi_connector_funcs, ++ DRM_MODE_CONNECTOR_DSI); ++ drm_connector_helper_add(connector, &vc4_dsi_connector_helper_funcs); ++ ++ connector->polled = 0; ++ connector->interlace_allowed = 0; ++ connector->doublescan_allowed = 0; ++ ++ drm_mode_connector_attach_encoder(connector, dsi->encoder); ++ ++ return connector; ++ ++fail: ++ if (connector) ++ vc4_dsi_connector_destroy(connector); ++ ++ return ERR_PTR(ret); ++} ++ ++static void vc4_dsi_encoder_destroy(struct drm_encoder *encoder) ++{ ++ drm_encoder_cleanup(encoder); ++} ++ ++static const struct drm_encoder_funcs vc4_dsi_encoder_funcs = { ++ .destroy = vc4_dsi_encoder_destroy, ++}; ++ ++static void vc4_dsi_latch_ulps(struct vc4_dsi *dsi, bool latch) ++{ ++ u32 afec0 = DSI_PORT_READ(PHY_AFEC0); ++ ++ if (latch) ++ afec0 |= DSI_PORT_BIT(PHY_AFEC0_LATCH_ULPS); ++ else ++ afec0 &= ~DSI_PORT_BIT(PHY_AFEC0_LATCH_ULPS); ++ ++ DSI_PORT_WRITE(PHY_AFEC0, afec0); ++} ++ ++/* Enters or exits Ultra Low Power State. */ ++static void vc4_dsi_ulps(struct vc4_dsi *dsi, bool ulps) ++{ ++ bool continuous = dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS; ++ u32 phyc_ulps = ((continuous ? DSI_PORT_BIT(PHYC_CLANE_ULPS) : 0) | ++ DSI_PHYC_DLANE0_ULPS | ++ (dsi->lanes > 1 ? DSI_PHYC_DLANE1_ULPS : 0) | ++ (dsi->lanes > 2 ? DSI_PHYC_DLANE2_ULPS : 0) | ++ (dsi->lanes > 3 ? DSI_PHYC_DLANE3_ULPS : 0)); ++ u32 stat_ulps = ((continuous ? DSI1_STAT_PHY_CLOCK_ULPS : 0) | ++ DSI1_STAT_PHY_D0_ULPS | ++ (dsi->lanes > 1 ? DSI1_STAT_PHY_D1_ULPS : 0) | ++ (dsi->lanes > 2 ? DSI1_STAT_PHY_D2_ULPS : 0) | ++ (dsi->lanes > 3 ? DSI1_STAT_PHY_D3_ULPS : 0)); ++ u32 stat_stop = ((continuous ? DSI1_STAT_PHY_CLOCK_STOP : 0) | ++ DSI1_STAT_PHY_D0_STOP | ++ (dsi->lanes > 1 ? DSI1_STAT_PHY_D1_STOP : 0) | ++ (dsi->lanes > 2 ? DSI1_STAT_PHY_D2_STOP : 0) | ++ (dsi->lanes > 3 ? DSI1_STAT_PHY_D3_STOP : 0)); ++ int ret; ++ ++ DSI_PORT_WRITE(STAT, stat_ulps); ++ DSI_PORT_WRITE(PHYC, DSI_PORT_READ(PHYC) | phyc_ulps); ++ ret = wait_for((DSI_PORT_READ(STAT) & stat_ulps) == stat_ulps, 200); ++ if (ret) { ++ dev_warn(&dsi->pdev->dev, ++ "Timeout waiting for DSI ULPS entry: STAT 0x%08x", ++ DSI_PORT_READ(STAT)); ++ DSI_PORT_WRITE(PHYC, DSI_PORT_READ(PHYC) & ~phyc_ulps); ++ vc4_dsi_latch_ulps(dsi, false); ++ return; ++ } ++ ++ /* The DSI module can't be disabled while the module is ++ * generating ULPS state. So, to be able to disable the ++ * module, we have the AFE latch the ULPS state and continue ++ * on to having the module enter STOP. ++ */ ++ vc4_dsi_latch_ulps(dsi, ulps); ++ ++ DSI_PORT_WRITE(STAT, stat_stop); ++ DSI_PORT_WRITE(PHYC, DSI_PORT_READ(PHYC) & ~phyc_ulps); ++ ret = wait_for((DSI_PORT_READ(STAT) & stat_stop) == stat_stop, 200); ++ if (ret) { ++ dev_warn(&dsi->pdev->dev, ++ "Timeout waiting for DSI STOP entry: STAT 0x%08x", ++ DSI_PORT_READ(STAT)); ++ DSI_PORT_WRITE(PHYC, DSI_PORT_READ(PHYC) & ~phyc_ulps); ++ return; ++ } ++} ++ ++static u32 ++dsi_hs_timing(u32 ui_ns, u32 ns, u32 ui) ++{ ++ /* The HS timings have to be rounded up to a multiple of 8 ++ * because we're using the byte clock. ++ */ ++ return roundup(ui + DIV_ROUND_UP(ns, ui_ns), 8); ++} ++ ++/* ESC always runs at 100Mhz. */ ++#define ESC_TIME_NS 10 ++ ++static u32 ++dsi_esc_timing(u32 ns) ++{ ++ return DIV_ROUND_UP(ns, ESC_TIME_NS); ++} ++ ++static void vc4_dsi_encoder_disable(struct drm_encoder *encoder) ++{ ++ struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder); ++ struct vc4_dsi *dsi = vc4_encoder->dsi; ++ struct device *dev = &dsi->pdev->dev; ++ ++ drm_panel_disable(dsi->panel); ++ ++ vc4_dsi_ulps(dsi, true); ++ ++ drm_panel_unprepare(dsi->panel); ++ ++ clk_disable_unprepare(dsi->pll_phy_clock); ++ clk_disable_unprepare(dsi->escape_clock); ++ clk_disable_unprepare(dsi->pixel_clock); ++ ++ pm_runtime_put(dev); ++} ++ ++static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) ++{ ++ struct drm_display_mode *mode = &encoder->crtc->mode; ++ struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder); ++ struct vc4_dsi *dsi = vc4_encoder->dsi; ++ struct device *dev = &dsi->pdev->dev; ++ u32 format = 0, divider = 0; ++ bool debug_dump_regs = false; ++ unsigned long hs_clock; ++ u32 ui_ns; ++ /* Minimum LP state duration in escape clock cycles. */ ++ u32 lpx = dsi_esc_timing(60); ++ unsigned long pixel_clock_hz = mode->clock * 1000; ++ unsigned long dsip_clock; ++ unsigned long phy_clock; ++ int ret; ++ ++ ret = pm_runtime_get_sync(dev); ++ if (ret) { ++ DRM_ERROR("Failed to runtime PM enable on DSI%d\n", dsi->port); ++ return; ++ } ++ ++ ret = drm_panel_prepare(dsi->panel); ++ if (ret) { ++ DRM_ERROR("Panel failed to prepare\n"); ++ return; ++ } ++ ++ if (debug_dump_regs) { ++ DRM_INFO("DSI regs before:\n"); ++ vc4_dsi_dump_regs(dsi); ++ } ++ ++ switch (dsi->format) { ++ case MIPI_DSI_FMT_RGB888: ++ format = DSI_PFORMAT_RGB888; ++ divider = 24 / dsi->lanes; ++ break; ++ case MIPI_DSI_FMT_RGB666: ++ format = DSI_PFORMAT_RGB666; ++ divider = 24 / dsi->lanes; ++ break; ++ case MIPI_DSI_FMT_RGB666_PACKED: ++ format = DSI_PFORMAT_RGB666_PACKED; ++ divider = 18 / dsi->lanes; ++ break; ++ case MIPI_DSI_FMT_RGB565: ++ format = DSI_PFORMAT_RGB565; ++ divider = 16 / dsi->lanes; ++ break; ++ } ++ ++ phy_clock = pixel_clock_hz * divider; ++ ret = clk_set_rate(dsi->pll_phy_clock, phy_clock); ++ if (ret) { ++ dev_err(&dsi->pdev->dev, ++ "Failed to set phy clock to %ld: %d\n", phy_clock, ret); ++ } ++ ++ /* Reset the DSI and all its fifos. */ ++ DSI_PORT_WRITE(CTRL, ++ DSI_CTRL_SOFT_RESET_CFG | ++ DSI_PORT_BIT(CTRL_RESET_FIFOS)); ++ ++ DSI_PORT_WRITE(CTRL, ++ DSI_CTRL_HSDT_EOT_DISABLE | ++ DSI_CTRL_RX_LPDT_EOT_DISABLE); ++ ++ /* Clear all stat bits so we see what has happened during enable. */ ++ DSI_PORT_WRITE(STAT, DSI_PORT_READ(STAT)); ++ ++ /* Set AFE CTR00/CTR1 to release powerdown of analog. */ ++ if (dsi->port == 0) { ++ u32 afec0 = (VC4_SET_FIELD(7, DSI_PHY_AFEC0_PTATADJ) | ++ VC4_SET_FIELD(7, DSI_PHY_AFEC0_CTATADJ)); ++ ++ if (dsi->lanes < 2) ++ afec0 |= DSI0_PHY_AFEC0_PD_DLANE1; ++ ++ if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO)) ++ afec0 |= DSI0_PHY_AFEC0_RESET; ++ ++ DSI_PORT_WRITE(PHY_AFEC0, afec0); ++ ++ DSI_PORT_WRITE(PHY_AFEC1, ++ VC4_SET_FIELD(6, DSI0_PHY_AFEC1_IDR_DLANE1) | ++ VC4_SET_FIELD(6, DSI0_PHY_AFEC1_IDR_DLANE0) | ++ VC4_SET_FIELD(6, DSI0_PHY_AFEC1_IDR_CLANE)); ++ } else { ++ u32 afec0 = (VC4_SET_FIELD(7, DSI_PHY_AFEC0_PTATADJ) | ++ VC4_SET_FIELD(7, DSI_PHY_AFEC0_CTATADJ) | ++ VC4_SET_FIELD(6, DSI1_PHY_AFEC0_IDR_CLANE) | ++ VC4_SET_FIELD(6, DSI1_PHY_AFEC0_IDR_DLANE0) | ++ VC4_SET_FIELD(6, DSI1_PHY_AFEC0_IDR_DLANE1) | ++ VC4_SET_FIELD(6, DSI1_PHY_AFEC0_IDR_DLANE2) | ++ VC4_SET_FIELD(6, DSI1_PHY_AFEC0_IDR_DLANE3)); ++ ++ if (dsi->lanes < 4) ++ afec0 |= DSI1_PHY_AFEC0_PD_DLANE3; ++ if (dsi->lanes < 3) ++ afec0 |= DSI1_PHY_AFEC0_PD_DLANE2; ++ if (dsi->lanes < 2) ++ afec0 |= DSI1_PHY_AFEC0_PD_DLANE1; ++ ++ afec0 |= DSI1_PHY_AFEC0_RESET; ++ ++ DSI_PORT_WRITE(PHY_AFEC0, afec0); ++ ++ DSI_PORT_WRITE(PHY_AFEC1, 0); ++ ++ /* AFEC reset hold time */ ++ mdelay(1); ++ } ++ ++ ret = clk_prepare_enable(dsi->escape_clock); ++ if (ret) { ++ DRM_ERROR("Failed to turn on DSI escape clock: %d\n", ret); ++ return; ++ } ++ ++ ret = clk_prepare_enable(dsi->pll_phy_clock); ++ if (ret) { ++ DRM_ERROR("Failed to turn on DSI PLL: %d\n", ret); ++ return; ++ } ++ ++ hs_clock = clk_get_rate(dsi->pll_phy_clock); ++ ++ /* Yes, we set the DSI0P/DSI1P pixel clock to the byte rate, ++ * not the pixel clock rate. DSIxP take from the APHY's byte, ++ * DDR2, or DDR4 clock (we use byte) and feed into the PV at ++ * that rate. Separately, a value derived from PIX_CLK_DIV ++ * and HS_CLKC is fed into the PV to divide down to the actual ++ * pixel clock for pushing pixels into DSI. ++ */ ++ dsip_clock = phy_clock / 8; ++ ret = clk_set_rate(dsi->pixel_clock, dsip_clock); ++ if (ret) { ++ dev_err(dev, "Failed to set pixel clock to %ldHz: %d\n", ++ dsip_clock, ret); ++ } ++ ++ ret = clk_prepare_enable(dsi->pixel_clock); ++ if (ret) { ++ DRM_ERROR("Failed to turn on DSI pixel clock: %d\n", ret); ++ return; ++ } ++ ++ /* How many ns one DSI unit interval is. Note that the clock ++ * is DDR, so there's an extra divide by 2. ++ */ ++ ui_ns = DIV_ROUND_UP(500000000, hs_clock); ++ ++ DSI_PORT_WRITE(HS_CLT0, ++ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 262, 0), ++ DSI_HS_CLT0_CZERO) | ++ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 0, 8), ++ DSI_HS_CLT0_CPRE) | ++ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 38, 0), ++ DSI_HS_CLT0_CPREP)); ++ ++ DSI_PORT_WRITE(HS_CLT1, ++ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 60, 0), ++ DSI_HS_CLT1_CTRAIL) | ++ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 60, 52), ++ DSI_HS_CLT1_CPOST)); ++ ++ DSI_PORT_WRITE(HS_CLT2, ++ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 1000000, 0), ++ DSI_HS_CLT2_WUP)); ++ ++ DSI_PORT_WRITE(HS_DLT3, ++ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 100, 0), ++ DSI_HS_DLT3_EXIT) | ++ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 105, 6), ++ DSI_HS_DLT3_ZERO) | ++ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 40, 4), ++ DSI_HS_DLT3_PRE)); ++ ++ DSI_PORT_WRITE(HS_DLT4, ++ VC4_SET_FIELD(dsi_hs_timing(ui_ns, lpx * ESC_TIME_NS, 0), ++ DSI_HS_DLT4_LPX) | ++ VC4_SET_FIELD(max(dsi_hs_timing(ui_ns, 0, 8), ++ dsi_hs_timing(ui_ns, 60, 4)), ++ DSI_HS_DLT4_TRAIL) | ++ VC4_SET_FIELD(0, DSI_HS_DLT4_ANLAT)); ++ ++ DSI_PORT_WRITE(HS_DLT5, VC4_SET_FIELD(dsi_hs_timing(ui_ns, 1000, 5000), ++ DSI_HS_DLT5_INIT)); ++ ++ DSI_PORT_WRITE(HS_DLT6, ++ VC4_SET_FIELD(lpx * 5, DSI_HS_DLT6_TA_GET) | ++ VC4_SET_FIELD(lpx, DSI_HS_DLT6_TA_SURE) | ++ VC4_SET_FIELD(lpx * 4, DSI_HS_DLT6_TA_GO) | ++ VC4_SET_FIELD(lpx, DSI_HS_DLT6_LP_LPX)); ++ ++ DSI_PORT_WRITE(HS_DLT7, ++ VC4_SET_FIELD(dsi_esc_timing(1000000), ++ DSI_HS_DLT7_LP_WUP)); ++ ++ DSI_PORT_WRITE(PHYC, ++ DSI_PHYC_DLANE0_ENABLE | ++ (dsi->lanes >= 2 ? DSI_PHYC_DLANE1_ENABLE : 0) | ++ (dsi->lanes >= 3 ? DSI_PHYC_DLANE2_ENABLE : 0) | ++ (dsi->lanes >= 4 ? DSI_PHYC_DLANE3_ENABLE : 0) | ++ DSI_PORT_BIT(PHYC_CLANE_ENABLE) | ++ ((dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) ? ++ 0 : DSI_PORT_BIT(PHYC_HS_CLK_CONTINUOUS)) | ++ (dsi->port == 0 ? ++ VC4_SET_FIELD(lpx - 1, DSI0_PHYC_ESC_CLK_LPDT) : ++ VC4_SET_FIELD(lpx - 1, DSI1_PHYC_ESC_CLK_LPDT))); ++ ++ DSI_PORT_WRITE(CTRL, ++ DSI_PORT_READ(CTRL) | ++ DSI_CTRL_CAL_BYTE); ++ ++ /* HS timeout in HS clock cycles: disabled. */ ++ DSI_PORT_WRITE(HSTX_TO_CNT, 0); ++ /* LP receive timeout in HS clocks. */ ++ DSI_PORT_WRITE(LPRX_TO_CNT, 0xffffff); ++ /* Bus turnaround timeout */ ++ DSI_PORT_WRITE(TA_TO_CNT, 100000); ++ /* Display reset sequence timeout */ ++ DSI_PORT_WRITE(PR_TO_CNT, 100000); ++ ++ if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) { ++ DSI_PORT_WRITE(DISP0_CTRL, ++ VC4_SET_FIELD(divider, DSI_DISP0_PIX_CLK_DIV) | ++ VC4_SET_FIELD(format, DSI_DISP0_PFORMAT) | ++ VC4_SET_FIELD(DSI_DISP0_LP_STOP_PERFRAME, ++ DSI_DISP0_LP_STOP_CTRL) | ++ DSI_DISP0_ST_END | ++ DSI_DISP0_ENABLE); ++ } else { ++ DSI_PORT_WRITE(DISP0_CTRL, ++ DSI_DISP0_COMMAND_MODE | ++ DSI_DISP0_ENABLE); ++ } ++ ++ /* Set up DISP1 for transferring long command payloads through ++ * the pixfifo. ++ */ ++ DSI_PORT_WRITE(DISP1_CTRL, ++ VC4_SET_FIELD(DSI_DISP1_PFORMAT_32BIT_LE, ++ DSI_DISP1_PFORMAT) | ++ DSI_DISP1_ENABLE); ++ ++ /* Ungate the block. */ ++ if (dsi->port == 0) ++ DSI_PORT_WRITE(CTRL, DSI_PORT_READ(CTRL) | DSI0_CTRL_CTRL0); ++ else ++ DSI_PORT_WRITE(CTRL, DSI_PORT_READ(CTRL) | DSI1_CTRL_EN); ++ ++ /* Bring AFE out of reset. */ ++ if (dsi->port == 0) { ++ } else { ++ DSI_PORT_WRITE(PHY_AFEC0, ++ DSI_PORT_READ(PHY_AFEC0) & ++ ~DSI1_PHY_AFEC0_RESET); ++ } ++ ++ vc4_dsi_ulps(dsi, false); ++ ++ if (debug_dump_regs) { ++ DRM_INFO("DSI regs after:\n"); ++ vc4_dsi_dump_regs(dsi); ++ } ++ ++ ret = drm_panel_enable(dsi->panel); ++ if (ret) { ++ DRM_ERROR("Panel failed to enable\n"); ++ drm_panel_unprepare(dsi->panel); ++ return; ++ } ++} ++ ++static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host, ++ const struct mipi_dsi_msg *msg) ++{ ++ struct vc4_dsi *dsi = host_to_dsi(host); ++ struct mipi_dsi_packet packet; ++ u32 pkth = 0, pktc = 0; ++ int i, ret; ++ bool is_long = mipi_dsi_packet_format_is_long(msg->type); ++ u32 cmd_fifo_len = 0, pix_fifo_len = 0; ++ ++ mipi_dsi_create_packet(&packet, msg); ++ ++ pkth |= VC4_SET_FIELD(packet.header[0], DSI_TXPKT1H_BC_DT); ++ pkth |= VC4_SET_FIELD(packet.header[1] | ++ (packet.header[2] << 8), ++ DSI_TXPKT1H_BC_PARAM); ++ if (is_long) { ++ /* Divide data across the various FIFOs we have available. ++ * The command FIFO takes byte-oriented data, but is of ++ * limited size. The pixel FIFO (never actually used for ++ * pixel data in reality) is word oriented, and substantially ++ * larger. So, we use the pixel FIFO for most of the data, ++ * sending the residual bytes in the command FIFO at the start. ++ * ++ * With this arrangement, the command FIFO will never get full. ++ */ ++ if (packet.payload_length <= 16) { ++ cmd_fifo_len = packet.payload_length; ++ pix_fifo_len = 0; ++ } else { ++ cmd_fifo_len = (packet.payload_length % ++ DSI_PIX_FIFO_WIDTH); ++ pix_fifo_len = ((packet.payload_length - cmd_fifo_len) / ++ DSI_PIX_FIFO_WIDTH); ++ } ++ ++ WARN_ON_ONCE(pix_fifo_len >= DSI_PIX_FIFO_DEPTH); ++ ++ pkth |= VC4_SET_FIELD(cmd_fifo_len, DSI_TXPKT1H_BC_CMDFIFO); ++ } ++ ++ if (msg->rx_len) { ++ pktc |= VC4_SET_FIELD(DSI_TXPKT1C_CMD_CTRL_RX, ++ DSI_TXPKT1C_CMD_CTRL); ++ } else { ++ pktc |= VC4_SET_FIELD(DSI_TXPKT1C_CMD_CTRL_TX, ++ DSI_TXPKT1C_CMD_CTRL); ++ } ++ ++ for (i = 0; i < cmd_fifo_len; i++) ++ DSI_PORT_WRITE(TXPKT_CMD_FIFO, packet.payload[i]); ++ for (i = 0; i < pix_fifo_len; i++) { ++ const u8 *pix = packet.payload + cmd_fifo_len + i * 4; ++ ++ DSI_PORT_WRITE(TXPKT_PIX_FIFO, ++ pix[0] | ++ pix[1] << 8 | ++ pix[2] << 16 | ++ pix[3] << 24); ++ } ++ ++ if (msg->flags & MIPI_DSI_MSG_USE_LPM) ++ pktc |= DSI_TXPKT1C_CMD_MODE_LP; ++ if (is_long) ++ pktc |= DSI_TXPKT1C_CMD_TYPE_LONG; ++ ++ /* Send one copy of the packet. Larger repeats are used for pixel ++ * data in command mode. ++ */ ++ pktc |= VC4_SET_FIELD(1, DSI_TXPKT1C_CMD_REPEAT); ++ ++ pktc |= DSI_TXPKT1C_CMD_EN; ++ if (pix_fifo_len) { ++ pktc |= VC4_SET_FIELD(DSI_TXPKT1C_DISPLAY_NO_SECONDARY, ++ DSI_TXPKT1C_DISPLAY_NO); ++ } else { ++ pktc |= VC4_SET_FIELD(DSI_TXPKT1C_DISPLAY_NO_SHORT, ++ DSI_TXPKT1C_DISPLAY_NO); ++ } ++ ++ /* Enable the appropriate interrupt for the transfer completion. */ ++ dsi->xfer_result = 0; ++ reinit_completion(&dsi->xfer_completion); ++ DSI_PORT_WRITE(INT_STAT, DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF); ++ if (msg->rx_len) { ++ DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | ++ DSI1_INT_PHY_DIR_RTF)); ++ } else { ++ DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | ++ DSI1_INT_TXPKT1_DONE)); ++ } ++ ++ /* Send the packet. */ ++ DSI_PORT_WRITE(TXPKT1H, pkth); ++ DSI_PORT_WRITE(TXPKT1C, pktc); ++ ++ if (!wait_for_completion_timeout(&dsi->xfer_completion, ++ msecs_to_jiffies(1000))) { ++ dev_err(&dsi->pdev->dev, "transfer interrupt wait timeout"); ++ dev_err(&dsi->pdev->dev, "instat: 0x%08x\n", ++ DSI_PORT_READ(INT_STAT)); ++ ret = -ETIMEDOUT; ++ } else { ++ ret = dsi->xfer_result; ++ } ++ ++ DSI_PORT_WRITE(INT_EN, DSI1_INTERRUPTS_ALWAYS_ENABLED); ++ ++ if (ret) ++ goto reset_fifo_and_return; ++ ++ if (ret == 0 && msg->rx_len) { ++ u32 rxpkt1h = DSI_PORT_READ(RXPKT1H); ++ u8 *msg_rx = msg->rx_buf; ++ ++ if (rxpkt1h & DSI_RXPKT1H_PKT_TYPE_LONG) { ++ u32 rxlen = VC4_GET_FIELD(rxpkt1h, ++ DSI_RXPKT1H_BC_PARAM); ++ ++ if (rxlen != msg->rx_len) { ++ DRM_ERROR("DSI returned %db, expecting %db\n", ++ rxlen, (int)msg->rx_len); ++ ret = -ENXIO; ++ goto reset_fifo_and_return; ++ } ++ ++ for (i = 0; i < msg->rx_len; i++) ++ msg_rx[i] = DSI_READ(DSI1_RXPKT_FIFO); ++ } else { ++ /* FINISHME: Handle AWER */ ++ ++ msg_rx[0] = VC4_GET_FIELD(rxpkt1h, ++ DSI_RXPKT1H_SHORT_0); ++ if (msg->rx_len > 1) { ++ msg_rx[1] = VC4_GET_FIELD(rxpkt1h, ++ DSI_RXPKT1H_SHORT_1); ++ } ++ } ++ } ++ ++ return ret; ++ ++reset_fifo_and_return: ++ DRM_ERROR("DSI transfer failed, resetting: %d\n", ret); ++ ++ DSI_PORT_WRITE(TXPKT1C, DSI_PORT_READ(TXPKT1C) & ~DSI_TXPKT1C_CMD_EN); ++ udelay(1); ++ DSI_PORT_WRITE(CTRL, ++ DSI_PORT_READ(CTRL) | ++ DSI_PORT_BIT(CTRL_RESET_FIFOS)); ++ ++ DSI_PORT_WRITE(TXPKT1C, 0); ++ DSI_PORT_WRITE(INT_EN, DSI1_INTERRUPTS_ALWAYS_ENABLED); ++ return ret; ++} ++ ++static int vc4_dsi_host_attach(struct mipi_dsi_host *host, ++ struct mipi_dsi_device *device) ++{ ++ struct vc4_dsi *dsi = host_to_dsi(host); ++ int ret = 0; ++ ++ dsi->lanes = device->lanes; ++ dsi->channel = device->channel; ++ dsi->format = device->format; ++ dsi->mode_flags = device->mode_flags; ++ ++ if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO)) { ++ dev_err(&dsi->pdev->dev, ++ "Only VIDEO mode panels supported currently.\n"); ++ return 0; ++ } ++ ++ dsi->panel = of_drm_find_panel(device->dev.of_node); ++ if (!dsi->panel) ++ return 0; ++ ++ ret = drm_panel_attach(dsi->panel, dsi->connector); ++ if (ret != 0) ++ return ret; ++ ++ drm_helper_hpd_irq_event(dsi->connector->dev); ++ ++ return 0; ++} ++ ++static int vc4_dsi_host_detach(struct mipi_dsi_host *host, ++ struct mipi_dsi_device *device) ++{ ++ struct vc4_dsi *dsi = host_to_dsi(host); ++ ++ if (dsi->panel) { ++ int ret = drm_panel_detach(dsi->panel); ++ ++ if (ret) ++ return ret; ++ ++ dsi->panel = NULL; ++ ++ drm_helper_hpd_irq_event(dsi->connector->dev); ++ } ++ ++ return 0; ++} ++ ++static const struct mipi_dsi_host_ops vc4_dsi_host_ops = { ++ .attach = vc4_dsi_host_attach, ++ .detach = vc4_dsi_host_detach, ++ .transfer = vc4_dsi_host_transfer, ++}; ++ ++static const struct drm_encoder_helper_funcs vc4_dsi_encoder_helper_funcs = { ++ .disable = vc4_dsi_encoder_disable, ++ .enable = vc4_dsi_encoder_enable, ++}; ++ ++static const struct of_device_id vc4_dsi_dt_match[] = { ++ { .compatible = "brcm,bcm2835-dsi1", (void *)(uintptr_t)1 }, ++ {} ++}; ++ ++static void dsi_handle_error(struct vc4_dsi *dsi, ++ irqreturn_t *ret, u32 stat, u32 bit, ++ const char *type) ++{ ++ if (!(stat & bit)) ++ return; ++ ++ DRM_ERROR("DSI%d: %s error\n", dsi->port, type); ++ *ret = IRQ_HANDLED; ++} ++ ++static irqreturn_t vc4_dsi_irq_handler(int irq, void *data) ++{ ++ struct vc4_dsi *dsi = data; ++ u32 stat = DSI_PORT_READ(INT_STAT); ++ irqreturn_t ret = IRQ_NONE; ++ ++ DSI_PORT_WRITE(INT_STAT, stat); ++ ++ dsi_handle_error(dsi, &ret, stat, ++ DSI1_INT_ERR_SYNC_ESC, "LPDT sync"); ++ dsi_handle_error(dsi, &ret, stat, ++ DSI1_INT_ERR_CONTROL, "data lane 0 sequence"); ++ dsi_handle_error(dsi, &ret, stat, ++ DSI1_INT_ERR_CONT_LP0, "LP0 contention"); ++ dsi_handle_error(dsi, &ret, stat, ++ DSI1_INT_ERR_CONT_LP1, "LP1 contention"); ++ dsi_handle_error(dsi, &ret, stat, ++ DSI1_INT_HSTX_TO, "HSTX timeout"); ++ dsi_handle_error(dsi, &ret, stat, ++ DSI1_INT_LPRX_TO, "LPRX timeout"); ++ dsi_handle_error(dsi, &ret, stat, ++ DSI1_INT_TA_TO, "turnaround timeout"); ++ dsi_handle_error(dsi, &ret, stat, ++ DSI1_INT_PR_TO, "peripheral reset timeout"); ++ ++ if (stat & (DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF)) { ++ complete(&dsi->xfer_completion); ++ ret = IRQ_HANDLED; ++ } else if (stat & DSI1_INT_HSTX_TO) { ++ complete(&dsi->xfer_completion); ++ dsi->xfer_result = -ETIMEDOUT; ++ ret = IRQ_HANDLED; ++ } ++ ++ return ret; ++} ++ ++/** ++ * Exposes clocks generated by the analog PHY that are consumed by ++ * CPRMAN (clk-bcm2835.c). ++ */ ++static int ++vc4_dsi_init_phy_clocks(struct vc4_dsi *dsi) ++{ ++ struct device *dev = &dsi->pdev->dev; ++ const char *parent_name = __clk_get_name(dsi->pll_phy_clock); ++ static const struct { ++ const char *dsi0_name, *dsi1_name; ++ int div; ++ } phy_clocks[] = { ++ { "dsi0_byte", "dsi1_byte", 8 }, ++ { "dsi0_ddr2", "dsi1_ddr2", 4 }, ++ { "dsi0_ddr", "dsi1_ddr", 2 }, ++ }; ++ int i; ++ ++ dsi->clk_onecell.clk_num = ARRAY_SIZE(phy_clocks); ++ dsi->clk_onecell.clks = devm_kcalloc(dev, ++ dsi->clk_onecell.clk_num, ++ sizeof(*dsi->clk_onecell.clks), ++ GFP_KERNEL); ++ if (!dsi->clk_onecell.clks) ++ return -ENOMEM; ++ ++ for (i = 0; i < ARRAY_SIZE(phy_clocks); i++) { ++ struct clk_fixed_factor *fix = &dsi->phy_clocks[i]; ++ struct clk_init_data init; ++ struct clk *clk; ++ ++ /* We just use core fixed factor clock ops for the PHY ++ * clocks. The clocks are actually gated by the ++ * PHY_AFEC0_DDRCLK_EN bits, which we should be ++ * setting if we use the DDR/DDR2 clocks. However, ++ * vc4_dsi_encoder_enable() is setting up both AFEC0, ++ * setting both our parent DSI PLL's rate and this ++ * clock's rate, so it knows if DDR/DDR2 are going to ++ * be used and could enable the gates itself. ++ */ ++ fix->mult = 1; ++ fix->div = phy_clocks[i].div; ++ fix->hw.init = &init; ++ ++ memset(&init, 0, sizeof(init)); ++ init.parent_names = &parent_name; ++ init.num_parents = 1; ++ if (dsi->port == 1) ++ init.name = phy_clocks[i].dsi1_name; ++ else ++ init.name = phy_clocks[i].dsi0_name; ++ init.ops = &clk_fixed_factor_ops; ++ init.flags = CLK_IS_BASIC; ++ ++ clk = devm_clk_register(dev, &fix->hw); ++ if (IS_ERR(clk)) ++ return PTR_ERR(clk); ++ ++ dsi->clk_onecell.clks[i] = clk; ++ } ++ ++ return of_clk_add_provider(dev->of_node, ++ of_clk_src_onecell_get, ++ &dsi->clk_onecell); ++} ++ ++static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct drm_device *drm = dev_get_drvdata(master); ++ struct vc4_dev *vc4 = to_vc4_dev(drm); ++ struct vc4_dsi *dsi; ++ struct vc4_dsi_encoder *vc4_dsi_encoder; ++ const struct of_device_id *match; ++ dma_cap_mask_t dma_mask; ++ int ret; ++ ++ dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); ++ if (!dsi) ++ return -ENOMEM; ++ ++ match = of_match_device(vc4_dsi_dt_match, dev); ++ if (!match) ++ return -ENODEV; ++ ++ dsi->port = (uintptr_t)match->data; ++ ++ vc4_dsi_encoder = devm_kzalloc(dev, sizeof(*vc4_dsi_encoder), ++ GFP_KERNEL); ++ if (!vc4_dsi_encoder) ++ return -ENOMEM; ++ vc4_dsi_encoder->base.type = VC4_ENCODER_TYPE_DSI1; ++ vc4_dsi_encoder->dsi = dsi; ++ dsi->encoder = &vc4_dsi_encoder->base.base; ++ ++ dsi->pdev = pdev; ++ dsi->regs = vc4_ioremap_regs(pdev, 0); ++ if (IS_ERR(dsi->regs)) ++ return PTR_ERR(dsi->regs); ++ ++ if (DSI_PORT_READ(ID) != DSI_ID_VALUE) { ++ dev_err(dev, "Port returned 0x%08x for ID instead of 0x%08x\n", ++ DSI_PORT_READ(ID), DSI_ID_VALUE); ++ return -ENODEV; ++ } ++ ++ /* DSI1 has a broken AXI slave that doesn't respond to writes ++ * from the ARM. It does handle writes from the DMA engine, ++ * so set up a channel for talking to it. ++ */ ++ if (dsi->port == 1) { ++ dsi->reg_dma_mem = dma_alloc_coherent(dev, 4, ++ &dsi->reg_dma_paddr, ++ GFP_KERNEL); ++ if (!dsi->reg_dma_mem) { ++ DRM_ERROR("Failed to get DMA memory\n"); ++ return -ENOMEM; ++ } ++ ++ dma_cap_zero(dma_mask); ++ dma_cap_set(DMA_MEMCPY, dma_mask); ++ dsi->reg_dma_chan = dma_request_chan_by_mask(&dma_mask); ++ if (IS_ERR(dsi->reg_dma_chan)) { ++ ret = PTR_ERR(dsi->reg_dma_chan); ++ if (ret != -EPROBE_DEFER) ++ DRM_ERROR("Failed to get DMA channel: %d\n", ++ ret); ++ return ret; ++ } ++ ++ /* Get the physical address of the device's registers. The ++ * struct resource for the regs gives us the bus address ++ * instead. ++ */ ++ dsi->reg_paddr = be32_to_cpup(of_get_address(dev->of_node, ++ 0, NULL, NULL)); ++ } ++ ++ init_completion(&dsi->xfer_completion); ++ /* At startup enable error-reporting interrupts and nothing else. */ ++ DSI_PORT_WRITE(INT_EN, DSI1_INTERRUPTS_ALWAYS_ENABLED); ++ /* Clear any existing interrupt state. */ ++ DSI_PORT_WRITE(INT_STAT, DSI_PORT_READ(INT_STAT)); ++ ++ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), ++ vc4_dsi_irq_handler, 0, "vc4 dsi", dsi); ++ if (ret) { ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "Failed to get interrupt: %d\n", ret); ++ return ret; ++ } ++ ++ dsi->escape_clock = devm_clk_get(dev, "escape"); ++ if (IS_ERR(dsi->escape_clock)) { ++ ret = PTR_ERR(dsi->escape_clock); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "Failed to get escape clock: %d\n", ret); ++ return ret; ++ } ++ ++ dsi->pll_phy_clock = devm_clk_get(dev, "phy"); ++ if (IS_ERR(dsi->pll_phy_clock)) { ++ ret = PTR_ERR(dsi->pll_phy_clock); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "Failed to get phy clock: %d\n", ret); ++ return ret; ++ } ++ ++ dsi->pixel_clock = devm_clk_get(dev, "pixel"); ++ if (IS_ERR(dsi->pixel_clock)) { ++ ret = PTR_ERR(dsi->pixel_clock); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "Failed to get pixel clock: %d\n", ret); ++ return ret; ++ } ++ ++ /* The esc clock rate is supposed to always be 100Mhz. */ ++ ret = clk_set_rate(dsi->escape_clock, 100 * 1000000); ++ if (ret) { ++ dev_err(dev, "Failed to set esc clock: %d\n", ret); ++ return ret; ++ } ++ ++ ret = vc4_dsi_init_phy_clocks(dsi); ++ if (ret) ++ return ret; ++ ++ if (dsi->port == 1) ++ vc4->dsi1 = dsi; ++ ++ drm_encoder_init(drm, dsi->encoder, &vc4_dsi_encoder_funcs, ++ DRM_MODE_ENCODER_DSI, NULL); ++ drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs); ++ ++ dsi->connector = vc4_dsi_connector_init(drm, dsi); ++ if (IS_ERR(dsi->connector)) { ++ ret = PTR_ERR(dsi->connector); ++ goto err_destroy_encoder; ++ } ++ ++ dsi->dsi_host.ops = &vc4_dsi_host_ops; ++ dsi->dsi_host.dev = dev; ++ ++ mipi_dsi_host_register(&dsi->dsi_host); ++ ++ dev_set_drvdata(dev, dsi); ++ ++ pm_runtime_enable(dev); ++ ++ return 0; ++ ++err_destroy_encoder: ++ vc4_dsi_encoder_destroy(dsi->encoder); ++ ++ return ret; ++} ++ ++static void vc4_dsi_unbind(struct device *dev, struct device *master, ++ void *data) ++{ ++ struct drm_device *drm = dev_get_drvdata(master); ++ struct vc4_dev *vc4 = to_vc4_dev(drm); ++ struct vc4_dsi *dsi = dev_get_drvdata(dev); ++ ++ pm_runtime_disable(dev); ++ ++ vc4_dsi_connector_destroy(dsi->connector); ++ vc4_dsi_encoder_destroy(dsi->encoder); ++ ++ mipi_dsi_host_unregister(&dsi->dsi_host); ++ ++ clk_disable_unprepare(dsi->pll_phy_clock); ++ clk_disable_unprepare(dsi->escape_clock); ++ ++ if (dsi->port == 1) ++ vc4->dsi1 = NULL; ++} ++ ++static const struct component_ops vc4_dsi_ops = { ++ .bind = vc4_dsi_bind, ++ .unbind = vc4_dsi_unbind, ++}; ++ ++static int vc4_dsi_dev_probe(struct platform_device *pdev) ++{ ++ return component_add(&pdev->dev, &vc4_dsi_ops); ++} ++ ++static int vc4_dsi_dev_remove(struct platform_device *pdev) ++{ ++ component_del(&pdev->dev, &vc4_dsi_ops); ++ return 0; ++} ++ ++struct platform_driver vc4_dsi_driver = { ++ .probe = vc4_dsi_dev_probe, ++ .remove = vc4_dsi_dev_remove, ++ .driver = { ++ .name = "vc4_dsi", ++ .of_match_table = vc4_dsi_dt_match, ++ }, ++}; diff --git a/target/linux/brcm2708/patches-4.9/0174-ARM-dts-bcm283x-Add-VEC-node-in-bcm283x.dtsi.patch b/target/linux/brcm2708/patches-4.9/0174-ARM-dts-bcm283x-Add-VEC-node-in-bcm283x.dtsi.patch new file mode 100644 index 0000000000..a2671f2439 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0174-ARM-dts-bcm283x-Add-VEC-node-in-bcm283x.dtsi.patch @@ -0,0 +1,31 @@ +From 9389f17c3c92c3ec54e0d689ad46b95b90a8039a Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Fri, 2 Dec 2016 14:48:12 +0100 +Subject: [PATCH] ARM: dts: bcm283x: Add VEC node in bcm283x.dtsi + +Add the VEC (Video EnCoder) node definition in bcm283x.dtsi. + +Signed-off-by: Boris Brezillon +Signed-off-by: Eric Anholt +(cherry picked from commit b899c45208d6f204a6da9a1132577993eeecf0fb) +--- + arch/arm/boot/dts/bcm283x.dtsi | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/arch/arm/boot/dts/bcm283x.dtsi ++++ b/arch/arm/boot/dts/bcm283x.dtsi +@@ -310,6 +310,14 @@ + status = "disabled"; + }; + ++ vec: vec@7e806000 { ++ compatible = "brcm,bcm2835-vec"; ++ reg = <0x7e806000 0x1000>; ++ clocks = <&clocks BCM2835_CLOCK_VEC>; ++ interrupts = <2 27>; ++ status = "disabled"; ++ }; ++ + pixelvalve@7e807000 { + compatible = "brcm,bcm2835-pixelvalve2"; + reg = <0x7e807000 0x100>; diff --git a/target/linux/brcm2708/patches-4.9/0175-ARM-dts-bcm283x-Enable-the-VEC-IP-on-all-RaspberryPi.patch b/target/linux/brcm2708/patches-4.9/0175-ARM-dts-bcm283x-Enable-the-VEC-IP-on-all-RaspberryPi.patch new file mode 100644 index 0000000000..8689450266 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0175-ARM-dts-bcm283x-Enable-the-VEC-IP-on-all-RaspberryPi.patch @@ -0,0 +1,26 @@ +From 686aed7763ddc3bd31b45454cbe73fb217a3d1c1 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Fri, 2 Dec 2016 14:48:13 +0100 +Subject: [PATCH] ARM: dts: bcm283x: Enable the VEC IP on all RaspberryPi + boards + +Enable the VEC IP on all RaspberryPi boards. + +Signed-off-by: Boris Brezillon +Signed-off-by: Eric Anholt +(cherry picked from commit 5ab1a37c6027c114a87a1ae32cfc5ef303d643c5) +--- + arch/arm/boot/dts/bcm2835-rpi.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi ++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi +@@ -92,3 +92,8 @@ + &dsi1 { + power-domains = <&power RPI_POWER_DOMAIN_DSI1>; + }; ++ ++&vec { ++ power-domains = <&power RPI_POWER_DOMAIN_VEC>; ++ status = "okay"; ++}; diff --git a/target/linux/brcm2708/patches-4.9/0176-BCM270X-Disable-VEC-unless-vc4-kms-v3d-is-present.patch b/target/linux/brcm2708/patches-4.9/0176-BCM270X-Disable-VEC-unless-vc4-kms-v3d-is-present.patch new file mode 100644 index 0000000000..42c39650e7 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0176-BCM270X-Disable-VEC-unless-vc4-kms-v3d-is-present.patch @@ -0,0 +1,37 @@ +From 323d84f926d907f424c3e55bec55ec84a9d04657 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Mon, 23 Jan 2017 11:41:54 -0800 +Subject: [PATCH] BCM270X: Disable VEC unless vc4-kms-v3d is present. + +Signed-off-by: Eric Anholt +--- + arch/arm/boot/dts/bcm2708-rpi.dtsi | 4 ++++ + arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 7 +++++++ + 2 files changed, 11 insertions(+) + +--- a/arch/arm/boot/dts/bcm2708-rpi.dtsi ++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi +@@ -107,3 +107,7 @@ + &usb { + power-domains = <&power RPI_POWER_DOMAIN_USB>; + }; ++ ++&vec { ++ status = "disabled"; ++}; +--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts +@@ -148,6 +148,13 @@ + }; + }; + ++ fragment@18 { ++ target = <&vec>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ + __overrides__ { + cma-256 = <0>,"+0-1-2-3-4"; + cma-192 = <0>,"-0+1-2-3-4"; diff --git a/target/linux/brcm2708/patches-4.9/0177-drm-vc4-Name-the-primary-and-cursor-planes-in-fkms.patch b/target/linux/brcm2708/patches-4.9/0177-drm-vc4-Name-the-primary-and-cursor-planes-in-fkms.patch new file mode 100644 index 0000000000..208ff58efb --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0177-drm-vc4-Name-the-primary-and-cursor-planes-in-fkms.patch @@ -0,0 +1,24 @@ +From 789e1599cc6589b2a5c05c0f0bcd57fdaeb1b474 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Wed, 1 Feb 2017 17:09:18 -0800 +Subject: [PATCH] drm/vc4: Name the primary and cursor planes in fkms. + +This makes debugging nicer, compared to trying to remember what the +IDs are. + +Signed-off-by: Eric Anholt +--- + drivers/gpu/drm/vc4/vc4_firmware_kms.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c +@@ -267,7 +267,7 @@ static struct drm_plane *vc4_fkms_plane_ + ret = drm_universal_plane_init(dev, plane, 0xff, + &vc4_plane_funcs, + primary ? &xrgb8888 : &argb8888, 1, +- type, NULL); ++ type, primary ? "primary" : "cursor"); + + if (type == DRM_PLANE_TYPE_PRIMARY) { + vc4_plane->fbinfo = diff --git a/target/linux/brcm2708/patches-4.9/0178-drm-vc4-Add-DRM_DEBUG_ATOMIC-for-the-insides-of-fkms.patch b/target/linux/brcm2708/patches-4.9/0178-drm-vc4-Add-DRM_DEBUG_ATOMIC-for-the-insides-of-fkms.patch new file mode 100644 index 0000000000..f3f141097b --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0178-drm-vc4-Add-DRM_DEBUG_ATOMIC-for-the-insides-of-fkms.patch @@ -0,0 +1,69 @@ +From ac45ecdcbc38c6ec6b477980d0cd0760267f6057 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Wed, 1 Feb 2017 17:10:09 -0800 +Subject: [PATCH] drm/vc4: Add DRM_DEBUG_ATOMIC for the insides of fkms. + +Trying to debug weston on fkms involved figuring out what calls I was +making to the firmware. + +Signed-off-by: Eric Anholt +--- + drivers/gpu/drm/vc4/vc4_firmware_kms.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c +@@ -102,6 +102,11 @@ static int vc4_plane_set_primary_blank(s + struct vc4_dev *vc4 = to_vc4_dev(plane->dev); + + u32 packet = blank; ++ ++ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary plane %s", ++ plane->base.id, plane->name, ++ blank ? "blank" : "unblank"); ++ + return rpi_firmware_property(vc4->firmware, + RPI_FIRMWARE_FRAMEBUFFER_BLANK, + &packet, sizeof(packet)); +@@ -149,6 +154,16 @@ static void vc4_primary_plane_atomic_upd + WARN_ON_ONCE(vc4_plane->pitch != fb->pitches[0]); + } + ++ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%08x/%d\n", ++ plane->base.id, plane->name, ++ state->crtc_w, ++ state->crtc_h, ++ bpp, ++ state->crtc_x, ++ state->crtc_y, ++ bo->paddr + fb->offsets[0], ++ fb->pitches[0]); ++ + ret = rpi_firmware_transaction(vc4->firmware, + RPI_FIRMWARE_CHAN_FB, + vc4_plane->fbinfo_bus_addr); +@@ -178,6 +193,15 @@ static void vc4_cursor_plane_atomic_upda + WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4); + WARN_ON_ONCE(fb->bits_per_pixel != 32); + ++ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%08x/%d)", ++ plane->base.id, plane->name, ++ state->crtc_w, ++ state->crtc_h, ++ state->crtc_x, ++ state->crtc_y, ++ bo->paddr + fb->offsets[0], ++ fb->pitches[0]); ++ + ret = rpi_firmware_property(vc4->firmware, + RPI_FIRMWARE_SET_CURSOR_STATE, + &packet_state, +@@ -200,6 +224,8 @@ static void vc4_cursor_plane_atomic_disa + u32 packet_state[] = { false, 0, 0, 0 }; + int ret; + ++ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] disabling cursor", plane->base.id, plane->name); ++ + ret = rpi_firmware_property(vc4->firmware, + RPI_FIRMWARE_SET_CURSOR_STATE, + &packet_state, diff --git a/target/linux/brcm2708/patches-4.9/0179-drm-vc4-Fix-sending-of-page-flip-completion-events-i.patch b/target/linux/brcm2708/patches-4.9/0179-drm-vc4-Fix-sending-of-page-flip-completion-events-i.patch new file mode 100644 index 0000000000..73fbf2bc99 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0179-drm-vc4-Fix-sending-of-page-flip-completion-events-i.patch @@ -0,0 +1,42 @@ +From bc93583742c7ba9c84462664d4c798ba43bef26f Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Thu, 2 Feb 2017 09:42:18 -0800 +Subject: [PATCH] drm/vc4: Fix sending of page flip completion events in FKMS + mode. + +In the rewrite of vc4_crtc.c for fkms, I dropped the part of the +CRTC's atomic flush handler that moved the completion event from the +proposed atomic state change to the CRTC's current state. That meant +that when full screen pageflipping happened (glxgears -fullscreen in +X, compton, por weston), the app would end up blocked firever waiting +to draw its next frame. + +Signed-off-by: Eric Anholt +--- + drivers/gpu/drm/vc4/vc4_firmware_kms.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c +@@ -338,6 +338,21 @@ static int vc4_crtc_atomic_check(struct + static void vc4_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) + { ++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); ++ struct drm_device *dev = crtc->dev; ++ ++ if (crtc->state->event) { ++ unsigned long flags; ++ ++ crtc->state->event->pipe = drm_crtc_index(crtc); ++ ++ WARN_ON(drm_crtc_vblank_get(crtc) != 0); ++ ++ spin_lock_irqsave(&dev->event_lock, flags); ++ vc4_crtc->event = crtc->state->event; ++ crtc->state->event = NULL; ++ spin_unlock_irqrestore(&dev->event_lock, flags); ++ } + } + + static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) diff --git a/target/linux/brcm2708/patches-4.9/0180-drm-vc4-Fulfill-user-BO-creation-requests-from-the-k.patch b/target/linux/brcm2708/patches-4.9/0180-drm-vc4-Fulfill-user-BO-creation-requests-from-the-k.patch new file mode 100644 index 0000000000..c0967b4639 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0180-drm-vc4-Fulfill-user-BO-creation-requests-from-the-k.patch @@ -0,0 +1,53 @@ +From cb8a5a1cf8cfd5b88fe641ada9a2dfb318d43c3f Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Wed, 8 Feb 2017 15:00:54 -0800 +Subject: [PATCH] drm/vc4: Fulfill user BO creation requests from the kernel BO + cache. + +The from_cache flag was actually "the BO is invisible to userspace", +so we can repurpose to just zero out a cached BO and return it to +userspace. + +Improves wall time for a loop of 5 glsl-algebraic-add-add-1 by +-1.44989% +/- 0.862891% (n=28, 1 outlier removed from each that +appeared to be other system noise) + +Note that there's an intel-gpu-tools test to check for the proper +zeroing behavior here, which we continue to pass. + +Signed-off-by: Eric Anholt +--- + drivers/gpu/drm/vc4/vc4_bo.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_bo.c ++++ b/drivers/gpu/drm/vc4/vc4_bo.c +@@ -208,21 +208,22 @@ struct drm_gem_object *vc4_create_object + } + + struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size, +- bool from_cache) ++ bool allow_unzeroed) + { + size_t size = roundup(unaligned_size, PAGE_SIZE); + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_gem_cma_object *cma_obj; ++ struct vc4_bo *bo; + + if (size == 0) + return ERR_PTR(-EINVAL); + + /* First, try to get a vc4_bo from the kernel BO cache. */ +- if (from_cache) { +- struct vc4_bo *bo = vc4_bo_get_from_cache(dev, size); +- +- if (bo) +- return bo; ++ bo = vc4_bo_get_from_cache(dev, size); ++ if (bo) { ++ if (!allow_unzeroed) ++ memset(bo->base.vaddr, 0, bo->base.base.size); ++ return bo; + } + + cma_obj = drm_gem_cma_create(dev, size); diff --git a/target/linux/brcm2708/patches-4.9/0181-drm-vc4-Fix-OOPSes-from-trying-to-cache-a-partially-.patch b/target/linux/brcm2708/patches-4.9/0181-drm-vc4-Fix-OOPSes-from-trying-to-cache-a-partially-.patch new file mode 100644 index 0000000000..000f3a8df3 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0181-drm-vc4-Fix-OOPSes-from-trying-to-cache-a-partially-.patch @@ -0,0 +1,34 @@ +From 3f131f18e76bb3fa56158adea3abddeaac68e860 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Thu, 9 Feb 2017 09:23:34 -0800 +Subject: [PATCH] drm/vc4: Fix OOPSes from trying to cache a partially + constructed BO. + +If a CMA allocation failed, the partially constructed BO would be +unreferenced through the normal path, and we might choose to put it in +the BO cache. If we then reused it before it expired from the cache, +the kernel would OOPS. + +Signed-off-by: Eric Anholt +Fixes: c826a6e10644 ("drm/vc4: Add a BO cache.") +--- + drivers/gpu/drm/vc4/vc4_bo.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_bo.c ++++ b/drivers/gpu/drm/vc4/vc4_bo.c +@@ -314,6 +314,14 @@ void vc4_free_object(struct drm_gem_obje + goto out; + } + ++ /* If this object was partially constructed but CMA allocation ++ * had failed, just free it. ++ */ ++ if (!bo->base.vaddr) { ++ vc4_bo_destroy(bo); ++ goto out; ++ } ++ + cache_list = vc4_get_cache_list_for_size(dev, gem_bo->size); + if (!cache_list) { + vc4_bo_destroy(bo); diff --git a/target/linux/brcm2708/patches-4.9/0182-drm-vc4-Verify-at-boot-that-CMA-doesn-t-cross-a-256M.patch b/target/linux/brcm2708/patches-4.9/0182-drm-vc4-Verify-at-boot-that-CMA-doesn-t-cross-a-256M.patch new file mode 100644 index 0000000000..453d027ae9 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0182-drm-vc4-Verify-at-boot-that-CMA-doesn-t-cross-a-256M.patch @@ -0,0 +1,79 @@ +From b280acf3c32746106c81419390f5b1869d644f66 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Mon, 12 Oct 2015 08:58:08 -0700 +Subject: [PATCH] drm/vc4: Verify at boot that CMA doesn't cross a 256MB + boundary. + +I've seen lots of users cranking CMA up higher, so throw an error if +they do. + +Signed-off-by: Eric Anholt +--- + drivers/base/dma-contiguous.c | 1 + + drivers/gpu/drm/vc4/vc4_v3d.c | 18 ++++++++++++++++++ + mm/cma.c | 2 ++ + 3 files changed, 21 insertions(+) + +--- a/drivers/base/dma-contiguous.c ++++ b/drivers/base/dma-contiguous.c +@@ -35,6 +35,7 @@ + #endif + + struct cma *dma_contiguous_default_area; ++EXPORT_SYMBOL(dma_contiguous_default_area); + + /* + * Default global CMA area size can be defined in kernel's .config. +--- a/drivers/gpu/drm/vc4/vc4_v3d.c ++++ b/drivers/gpu/drm/vc4/vc4_v3d.c +@@ -16,7 +16,10 @@ + * this program. If not, see . + */ + ++#include "linux/init.h" ++#include "linux/cma.h" + #include "linux/component.h" ++#include "linux/dma-contiguous.h" + #include "linux/pm_runtime.h" + #include "vc4_drv.h" + #include "vc4_regs.h" +@@ -185,8 +188,23 @@ static int vc4_v3d_bind(struct device *d + struct drm_device *drm = dev_get_drvdata(master); + struct vc4_dev *vc4 = to_vc4_dev(drm); + struct vc4_v3d *v3d = NULL; ++ struct cma *cma; + int ret; + ++ cma = dev_get_cma_area(dev); ++ if (!cma) ++ return -EINVAL; ++ ++ if ((cma_get_base(cma) & 0xf0000000) != ++ ((cma_get_base(cma) + cma_get_size(cma) - 1) & 0xf0000000)) { ++ DRM_ERROR("V3D requires that the CMA area (0x%08lx - 0x%08lx) " ++ "not span a 256MB boundary, or memory corruption " ++ "would happen.\n", ++ (long)cma_get_base(cma), ++ cma_get_base(cma) + cma_get_size(cma)); ++ return -EINVAL; ++ } ++ + v3d = devm_kzalloc(&pdev->dev, sizeof(*v3d), GFP_KERNEL); + if (!v3d) + return -ENOMEM; +--- a/mm/cma.c ++++ b/mm/cma.c +@@ -47,11 +47,13 @@ phys_addr_t cma_get_base(const struct cm + { + return PFN_PHYS(cma->base_pfn); + } ++EXPORT_SYMBOL(cma_get_base); + + unsigned long cma_get_size(const struct cma *cma) + { + return cma->count << PAGE_SHIFT; + } ++EXPORT_SYMBOL(cma_get_size); + + static unsigned long cma_bitmap_aligned_mask(const struct cma *cma, + int align_order) diff --git a/target/linux/brcm2708/patches-4.9/0183-BCM270X_DT-Add-SMSC-ethernet-controller-to-DT.patch b/target/linux/brcm2708/patches-4.9/0183-BCM270X_DT-Add-SMSC-ethernet-controller-to-DT.patch new file mode 100644 index 0000000000..76b1bf3bbf --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0183-BCM270X_DT-Add-SMSC-ethernet-controller-to-DT.patch @@ -0,0 +1,57 @@ +From 35a2c1524b21318228f0566d9a4ac53bf3138bdc Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 17 Feb 2017 09:47:11 +0000 +Subject: [PATCH] BCM270X_DT: Add SMSC ethernet controller to DT + +With an ethernet node in the DT, a suitable firmware can populate the +local-mac-address property, removing the need for a downstream patch +to the driver to read its MAC address from a module parameter. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 1 + + arch/arm/boot/dts/bcm2708-rpi-b.dts | 1 + + arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 1 + + arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 1 + + 4 files changed, 4 insertions(+) + +--- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts +@@ -1,6 +1,7 @@ + /dts-v1/; + + #include "bcm2708.dtsi" ++#include "bcm283x-rpi-smsc9514.dtsi" + + / { + model = "Raspberry Pi Model B+"; +--- a/arch/arm/boot/dts/bcm2708-rpi-b.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts +@@ -1,6 +1,7 @@ + /dts-v1/; + + #include "bcm2708.dtsi" ++#include "bcm283x-rpi-smsc9512.dtsi" + + / { + model = "Raspberry Pi Model B"; +--- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts ++++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts +@@ -1,6 +1,7 @@ + /dts-v1/; + + #include "bcm2709.dtsi" ++#include "bcm283x-rpi-smsc9514.dtsi" + + / { + model = "Raspberry Pi 2 Model B"; +--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts +@@ -5,6 +5,7 @@ + #endif + + #include "bcm2710.dtsi" ++#include "bcm283x-rpi-smsc9514.dtsi" + + / { + model = "Raspberry Pi 3 Model B"; diff --git a/target/linux/brcm2708/patches-4.9/0185-clk-bcm2835-Mark-used-PLLs-and-dividers-CRITICAL.patch b/target/linux/brcm2708/patches-4.9/0185-clk-bcm2835-Mark-used-PLLs-and-dividers-CRITICAL.patch new file mode 100644 index 0000000000..13f6c11f59 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0185-clk-bcm2835-Mark-used-PLLs-and-dividers-CRITICAL.patch @@ -0,0 +1,28 @@ +From a2ca8b47db0d08735e1c0ebeaf34e88522091662 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 13 Feb 2017 17:20:08 +0000 +Subject: [PATCH] clk-bcm2835: Mark used PLLs and dividers CRITICAL + +The VPU configures and relies on several PLLs and dividers. Mark all +enabled dividers and their PLLs as CRITICAL to prevent the kernel from +switching them off. + +Signed-off-by: Phil Elwell +--- + drivers/clk/bcm/clk-bcm2835.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -1366,6 +1366,11 @@ bcm2835_register_pll_divider(struct bcm2 + divider->div.hw.init = &init; + divider->div.table = NULL; + ++ if (!(cprman_read(cprman, data->cm_reg) & data->hold_mask)) { ++ init.flags |= CLK_IS_CRITICAL; ++ divider->div.flags |= CLK_IS_CRITICAL; ++ } ++ + divider->cprman = cprman; + divider->data = data; + diff --git a/target/linux/brcm2708/patches-4.9/0186-clk-bcm2835-Add-claim-clocks-property.patch b/target/linux/brcm2708/patches-4.9/0186-clk-bcm2835-Add-claim-clocks-property.patch new file mode 100644 index 0000000000..09dcfa7a68 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0186-clk-bcm2835-Add-claim-clocks-property.patch @@ -0,0 +1,133 @@ +From 5c1128ebe6c7a4af3f1784a640df7f3698233e9d Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 13 Feb 2017 17:20:08 +0000 +Subject: [PATCH] clk-bcm2835: Add claim-clocks property + +The claim-clocks property can be used to prevent PLLs and dividers +from being marked as critical. It contains a vector of clock IDs, +as defined by dt-bindings/clock/bcm2835.h. + +Use this mechanism to claim PLLD_DSI0, PLLD_DSI1, PLLH_AUX and +PLLH_PIX for the vc4_kms_v3d driver. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 14 +++++++++ + drivers/clk/bcm/clk-bcm2835.c | 34 ++++++++++++++++++++-- + 2 files changed, 46 insertions(+), 2 deletions(-) + +--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts +@@ -5,6 +5,8 @@ + /dts-v1/; + /plugin/; + ++#include ++ + / { + compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; + +@@ -155,6 +157,18 @@ + }; + }; + ++ fragment@19 { ++ target = <&clocks>; ++ __overlay__ { ++ claim-clocks = < ++ BCM2835_PLLD_DSI0 ++ BCM2835_PLLD_DSI1 ++ BCM2835_PLLH_AUX ++ BCM2835_PLLH_PIX ++ >; ++ }; ++ }; ++ + __overrides__ { + cma-256 = <0>,"+0-1-2-3-4"; + cma-192 = <0>,"-0+1-2-3-4"; +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -1298,6 +1298,8 @@ static const struct clk_ops bcm2835_vpu_ + .debug_init = bcm2835_clock_debug_init, + }; + ++static bool bcm2835_clk_is_claimed(const char *name); ++ + static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman, + const struct bcm2835_pll_data *data) + { +@@ -1314,6 +1316,9 @@ static struct clk_hw *bcm2835_register_p + init.ops = &bcm2835_pll_clk_ops; + init.flags = CLK_IGNORE_UNUSED; + ++ if (!bcm2835_clk_is_claimed(data->name)) ++ init.flags |= CLK_IS_CRITICAL; ++ + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return NULL; +@@ -1367,8 +1372,10 @@ bcm2835_register_pll_divider(struct bcm2 + divider->div.table = NULL; + + if (!(cprman_read(cprman, data->cm_reg) & data->hold_mask)) { +- init.flags |= CLK_IS_CRITICAL; +- divider->div.flags |= CLK_IS_CRITICAL; ++ if (!bcm2835_clk_is_claimed(data->source_pll)) ++ init.flags |= CLK_IS_CRITICAL; ++ if (!bcm2835_clk_is_claimed(data->name)) ++ divider->div.flags |= CLK_IS_CRITICAL; + } + + divider->cprman = cprman; +@@ -2104,6 +2111,8 @@ static const struct bcm2835_clk_desc clk + .ctl_reg = CM_PERIICTL), + }; + ++static bool bcm2835_clk_claimed[ARRAY_SIZE(clk_desc_array)]; ++ + /* + * Permanently take a reference on the parent of the SDRAM clock. + * +@@ -2123,6 +2132,19 @@ static int bcm2835_mark_sdc_parent_criti + return clk_prepare_enable(parent); + } + ++static bool bcm2835_clk_is_claimed(const char *name) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(clk_desc_array); i++) { ++ const char *clk_name = *(const char **)(clk_desc_array[i].data); ++ if (!strcmp(name, clk_name)) ++ return bcm2835_clk_claimed[i]; ++ } ++ ++ return false; ++} ++ + static int bcm2835_clk_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -2132,6 +2154,7 @@ static int bcm2835_clk_probe(struct plat + const struct bcm2835_clk_desc *desc; + const size_t asize = ARRAY_SIZE(clk_desc_array); + size_t i; ++ u32 clk_id; + int ret; + + cprman = devm_kzalloc(dev, sizeof(*cprman) + +@@ -2147,6 +2170,13 @@ static int bcm2835_clk_probe(struct plat + if (IS_ERR(cprman->regs)) + return PTR_ERR(cprman->regs); + ++ memset(bcm2835_clk_claimed, 0, sizeof(bcm2835_clk_claimed)); ++ for (i = 0; ++ !of_property_read_u32_index(pdev->dev.of_node, "claim-clocks", ++ i, &clk_id); ++ i++) ++ bcm2835_clk_claimed[clk_id]= true; ++ + memcpy(cprman->real_parent_names, cprman_parent_names, + sizeof(cprman_parent_names)); + of_clk_parent_fill(dev->of_node, cprman->real_parent_names, diff --git a/target/linux/brcm2708/patches-4.9/0187-dmaengine-bcm2835-Fix-cyclic-DMA-period-splitting.patch b/target/linux/brcm2708/patches-4.9/0187-dmaengine-bcm2835-Fix-cyclic-DMA-period-splitting.patch new file mode 100644 index 0000000000..fa0d998a2d --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0187-dmaengine-bcm2835-Fix-cyclic-DMA-period-splitting.patch @@ -0,0 +1,39 @@ +From 9fd7a158ec098ab05b8d3ec2c2973b3dc7e498f3 Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Mon, 20 Feb 2017 20:01:16 +0100 +Subject: [PATCH] dmaengine: bcm2835: Fix cyclic DMA period splitting + +The code responsible for splitting periods into chunks that +can be handled by the DMA controller missed to update total_len, +the number of bytes processed in the current period, when there +are more chunks to follow. + +Therefore total_len was stuck at 0 and the code didn't work at all. +This resulted in a wrong control block layout and audio issues because +the cyclic DMA callback wasn't executing on period boundaries. + +Fix this by adding the missing total_len update. + +Signed-off-by: Matthias Reichl +Signed-off-by: Martin Sperl +Tested-by: Clive Messer +Reviewed-by: Eric Anholt +--- + drivers/dma/bcm2835-dma.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/dma/bcm2835-dma.c ++++ b/drivers/dma/bcm2835-dma.c +@@ -253,8 +253,11 @@ static void bcm2835_dma_create_cb_set_le + */ + + /* have we filled in period_length yet? */ +- if (*total_len + control_block->length < period_len) ++ if (*total_len + control_block->length < period_len) { ++ /* update number of bytes in this period so far */ ++ *total_len += control_block->length; + return; ++ } + + /* calculate the length that remains to reach period_length */ + control_block->length = period_len - *total_len; diff --git a/target/linux/brcm2708/patches-4.9/0188-Add-ads1015-driver-to-config.patch b/target/linux/brcm2708/patches-4.9/0188-Add-ads1015-driver-to-config.patch new file mode 100644 index 0000000000..1303bdc101 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0188-Add-ads1015-driver-to-config.patch @@ -0,0 +1,52 @@ +From 9e638878dd33652b34e51746d369afba6103d77e Mon Sep 17 00:00:00 2001 +From: Scott Ellis +Date: Thu, 23 Feb 2017 11:56:20 -0500 +Subject: [PATCH] Add ads1015 driver to config + +--- + arch/arm/configs/bcm2709_defconfig | 3 ++- + arch/arm/configs/bcmrpi_defconfig | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -653,6 +653,7 @@ CONFIG_HWMON=m + CONFIG_SENSORS_LM75=m + CONFIG_SENSORS_SHT21=m + CONFIG_SENSORS_SHTC1=m ++CONFIG_SENSORS_ADS1015=m + CONFIG_SENSORS_INA2XX=m + CONFIG_THERMAL=y + CONFIG_THERMAL_BCM2835=y +@@ -833,9 +834,9 @@ CONFIG_VIDEO_OV7640=m + CONFIG_VIDEO_MT9V011=m + CONFIG_DRM=m + CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_UDL=m + CONFIG_DRM_PANEL_SIMPLE=m + CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m +-CONFIG_DRM_UDL=m + CONFIG_DRM_VC4=m + CONFIG_FB=y + CONFIG_FB_BCM2708=y +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -647,6 +647,7 @@ CONFIG_HWMON=m + CONFIG_SENSORS_LM75=m + CONFIG_SENSORS_SHT21=m + CONFIG_SENSORS_SHTC1=m ++CONFIG_SENSORS_ADS1015=m + CONFIG_SENSORS_INA2XX=m + CONFIG_THERMAL=y + CONFIG_THERMAL_BCM2835=y +@@ -827,9 +828,9 @@ CONFIG_VIDEO_OV7640=m + CONFIG_VIDEO_MT9V011=m + CONFIG_DRM=m + CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_UDL=m + CONFIG_DRM_PANEL_SIMPLE=m + CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m +-CONFIG_DRM_UDL=m + CONFIG_DRM_VC4=m + CONFIG_FB=y + CONFIG_FB_BCM2708=y diff --git a/target/linux/brcm2708/patches-4.9/0189-config-add-slcan-kernel-module.patch b/target/linux/brcm2708/patches-4.9/0189-config-add-slcan-kernel-module.patch new file mode 100644 index 0000000000..021eb014c8 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0189-config-add-slcan-kernel-module.patch @@ -0,0 +1,31 @@ +From 2fd423706eb3afde2a36845488e18d194b18b0c6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 27 Jan 2017 18:49:30 +0000 +Subject: [PATCH] config: add slcan kernel module + +See: https://github.com/raspberrypi/linux/issues/1819 +--- + arch/arm/configs/bcm2709_defconfig | 1 + + arch/arm/configs/bcmrpi_defconfig | 1 + + 2 files changed, 2 insertions(+) + +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -361,6 +361,7 @@ CONFIG_BAYCOM_SER_HDX=m + CONFIG_YAM=m + CONFIG_CAN=m + CONFIG_CAN_VCAN=m ++CONFIG_CAN_SLCAN=m + CONFIG_CAN_MCP251X=m + CONFIG_IRDA=m + CONFIG_IRLAN=m +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -357,6 +357,7 @@ CONFIG_BAYCOM_SER_HDX=m + CONFIG_YAM=m + CONFIG_CAN=m + CONFIG_CAN_VCAN=m ++CONFIG_CAN_SLCAN=m + CONFIG_CAN_MCP251X=m + CONFIG_IRDA=m + CONFIG_IRLAN=m diff --git a/target/linux/brcm2708/patches-4.9/0190-sound-Support-for-Dion-Audio-LOCO-V2-DAC-AMP-HAT.patch b/target/linux/brcm2708/patches-4.9/0190-sound-Support-for-Dion-Audio-LOCO-V2-DAC-AMP-HAT.patch new file mode 100644 index 0000000000..eb6422a469 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0190-sound-Support-for-Dion-Audio-LOCO-V2-DAC-AMP-HAT.patch @@ -0,0 +1,251 @@ +From a20dbe4972ea3df27f24c5397102e1346462a4f4 Mon Sep 17 00:00:00 2001 +From: Miquel +Date: Fri, 24 Feb 2017 20:51:06 +0100 +Subject: [PATCH] sound: Support for Dion Audio LOCO-V2 DAC-AMP HAT + +Signed-off-by: Miquel Blauw +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 19 +++++ + arch/arm/configs/bcm2709_defconfig | 1 + + arch/arm/configs/bcmrpi_defconfig | 1 + + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/dionaudio_loco-v2.c | 140 ++++++++++++++++++++++++++++++++++++ + 7 files changed, 171 insertions(+) + create mode 100644 sound/soc/bcm/dionaudio_loco-v2.c + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -13,6 +13,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + bmp085_i2c-sensor.dtbo \ + dht11.dtbo \ + dionaudio-loco.dtbo \ ++ dionaudio-loco-v2.dtbo \ + dpi18.dtbo \ + dpi24.dtbo \ + dwc-otg.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -308,6 +308,25 @@ Load: dtoverlay=dionaudio-loco + Params: + + ++Name: dionaudio-loco-v2 ++Info: Configures the Dion Audio LOCO-V2 DAC-AMP ++Load: dtoverlay=dionaudio-loco-v2,= ++Params: 24db_digital_gain Allow gain to be applied via the PCM512x codec ++ Digital volume control. Enable with ++ "dtoverlay=hifiberry-dacplus,24db_digital_gain" ++ (The default behaviour is that the Digital ++ volume control is limited to a maximum of ++ 0dB. ie. it can attenuate but not provide ++ gain. For most users, this will be desired ++ as it will prevent clipping. By appending ++ the 24dB_digital_gain parameter, the Digital ++ volume control will allow up to 24dB of ++ gain. If this parameter is enabled, it is the ++ responsibility of the user to ensure that ++ the Digital volume control is set to a value ++ that does not result in clipping/distortion!) ++ ++ + Name: dpi18 + Info: Overlay for a generic 18-bit DPI display + This uses GPIOs 0-21 (so no I2C, uart etc.), and activates the output +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -889,6 +889,7 @@ CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m + CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m + CONFIG_SND_DIGIDAC1_SOUNDCARD=m + CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m + CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m + CONFIG_SND_PISOUND=m + CONFIG_SND_SOC_ADAU1701=m +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -883,6 +883,7 @@ CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m + CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m + CONFIG_SND_DIGIDAC1_SOUNDCARD=m + CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m + CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m + CONFIG_SND_PISOUND=m + CONFIG_SND_SOC_ADAU1701=m +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -133,6 +133,13 @@ config SND_BCM2708_SOC_DIONAUDIO_LOCO + help + Say Y or M if you want to add support for Dion Audio LOCO. + ++config SND_BCM2708_SOC_DIONAUDIO_LOCO_V2 ++ tristate "Support for Dion Audio LOCO-V2 DAC-AMP" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM5122 ++ help ++ Say Y or M if you want to add support for Dion Audio LOCO-V2. ++ + config SND_BCM2708_SOC_ALLO_PIANO_DAC + tristate "Support for Allo Piano DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -25,6 +25,7 @@ snd-soc-raspidac3-objs := raspidac3.o + snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o + snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o + snd-soc-dionaudio-loco-objs := dionaudio_loco.o ++snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o + snd-soc-allo-piano-dac-objs := allo-piano-dac.o + snd-soc-pisound-objs := pisound.o + +@@ -44,5 +45,6 @@ obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) + obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o + obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o + obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o ++obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) += snd-soc-dionaudio-loco-v2.o + obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o + obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o +--- /dev/null ++++ b/sound/soc/bcm/dionaudio_loco-v2.c +@@ -0,0 +1,140 @@ ++/* ++ * ASoC Driver for Dion Audio LOCO-V2 DAC-AMP ++ * ++ * Author: Miquel Blauw ++ * Copyright 2017 ++ * ++ * Based on the software of the RPi-DAC writen by Florian Meier ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++static bool digital_gain_0db_limit = true; ++ ++static int snd_rpi_dionaudio_loco_v2_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ if (digital_gain_0db_limit) { ++ int ret; ++ struct snd_soc_card *card = rtd->card; ++ ++ ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207); ++ if (ret < 0) ++ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); ++ } ++ ++ return 0; ++} ++ ++static int snd_rpi_dionaudio_loco_v2_hw_params( ++ struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ unsigned int sample_bits = ++ snd_pcm_format_physical_width(params_format(params)); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_dionaudio_loco_v2_ops = { ++ .hw_params = snd_rpi_dionaudio_loco_v2_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_dionaudio_loco_v2_dai[] = { ++{ ++ .name = "DionAudio LOCO-V2", ++ .stream_name = "DionAudio LOCO-V2 DAC-AMP", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm512x-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm512x.1-004d", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_dionaudio_loco_v2_ops, ++ .init = snd_rpi_dionaudio_loco_v2_init, ++},}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_dionaudio_loco_v2 = { ++ .name = "Dion Audio LOCO-V2", ++ .dai_link = snd_rpi_dionaudio_loco_v2_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_dionaudio_loco_v2_dai), ++}; ++ ++static int snd_rpi_dionaudio_loco_v2_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_dionaudio_loco_v2.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = ++ &snd_rpi_dionaudio_loco_v2_dai[0]; ++ ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ ++ digital_gain_0db_limit = !of_property_read_bool( ++ pdev->dev.of_node, "dionaudio,24db_digital_gain"); ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_dionaudio_loco_v2); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ++ ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_dionaudio_loco_v2_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_dionaudio_loco_v2); ++} ++ ++static const struct of_device_id dionaudio_of_match[] = { ++ { .compatible = "dionaudio,dionaudio-loco-v2", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, dionaudio_of_match); ++ ++static struct platform_driver snd_rpi_dionaudio_loco_v2_driver = { ++ .driver = { ++ .name = "snd-rpi-dionaudio-loco-v2", ++ .owner = THIS_MODULE, ++ .of_match_table = dionaudio_of_match, ++ }, ++ .probe = snd_rpi_dionaudio_loco_v2_probe, ++ .remove = snd_rpi_dionaudio_loco_v2_remove, ++}; ++ ++module_platform_driver(snd_rpi_dionaudio_loco_v2_driver); ++ ++MODULE_AUTHOR("Miquel Blauw "); ++MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO-V2"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0191-SQUASH-Add-LOCO-V2-overlay-from-last-commit.patch b/target/linux/brcm2708/patches-4.9/0191-SQUASH-Add-LOCO-V2-overlay-from-last-commit.patch new file mode 100644 index 0000000000..be3618a0bf --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0191-SQUASH-Add-LOCO-V2-overlay-from-last-commit.patch @@ -0,0 +1,62 @@ +From e3b5ca5cb69c36f41436ab8be96710e39442ce28 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Sun, 26 Feb 2017 01:13:02 +0000 +Subject: [PATCH] SQUASH: Add LOCO-V2 overlay from last commit + +--- + .../dts/overlays/dionaudio-loco-v2-overlay.dts | 49 ++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts + +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts +@@ -0,0 +1,49 @@ ++/* ++ * Definitions for Dion Audio LOCO-V2 DAC-AMP ++ * eg. dtoverlay=dionaudio-loco-v2 ++ * ++ * PCM5242 DAC (in software mode) and TPA3255 AMP. ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ frag0: __overlay__ { ++ compatible = "dionaudio,dionaudio-loco-v2"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ pcm5122@4c { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5122"; ++ reg = <0x4d>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ 24db_digital_gain = <&frag0>,"dionaudio,24db_digital_gain?"; ++ }; ++}; diff --git a/target/linux/brcm2708/patches-4.9/0192-Add-support-for-Fe-Pi-audio-sound-card.-1867.patch b/target/linux/brcm2708/patches-4.9/0192-Add-support-for-Fe-Pi-audio-sound-card.-1867.patch new file mode 100644 index 0000000000..262dc14bce --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0192-Add-support-for-Fe-Pi-audio-sound-card.-1867.patch @@ -0,0 +1,333 @@ +From c646d023c75607a9ebc7296fe424d6eb4e804164 Mon Sep 17 00:00:00 2001 +From: Fe-Pi +Date: Wed, 1 Mar 2017 04:42:43 -0700 +Subject: [PATCH] Add support for Fe-Pi audio sound card. (#1867) + +Fe-Pi Audio Sound Card is based on NXP SGTL5000 codec. +Mechanical specification of the board is the same the Raspberry Pi Zero. +3.5mm jacks for Headphone/Mic, Line In, and Line Out. + +Signed-off-by: Henry Kupis +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 6 + + arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts | 70 +++++++++ + arch/arm/configs/bcm2709_defconfig | 1 + + arch/arm/configs/bcmrpi_defconfig | 1 + + sound/soc/bcm/Kconfig | 7 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/fe-pi-audio.c | 158 +++++++++++++++++++++ + 8 files changed, 246 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts + create mode 100644 sound/soc/bcm/fe-pi-audio.c + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -20,6 +20,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + dwc2.dtbo \ + enc28j60.dtbo \ + enc28j60-spi2.dtbo \ ++ fe-pi-audio.dtbo \ + gpio-ir.dtbo \ + gpio-poweroff.dtbo \ + hifiberry-amp.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -383,6 +383,12 @@ Params: int_pin GPIO use + speed SPI bus speed (default 12000000) + + ++Name: fe-pi-audio ++Info: Configures the Fe-Pi Audio Sound Card ++Load: dtoverlay=fe-pi-audio ++Params: ++ ++ + Name: gpio-ir + Info: Use GPIO pin as rc-core style infrared receiver input. The rc-core- + based gpio_ir_recv driver maps received keys directly to a +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts +@@ -0,0 +1,70 @@ ++// Definitions for Fe-Pi Audio ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&clocks>; ++ __overlay__ { ++ sgtl5000_mclk: sgtl5000_mclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <12288000>; ++ clock-output-names = "sgtl5000-mclk"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&soc>; ++ __overlay__ { ++ reg_1v8: reg_1v8@0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ sgtl5000@0a { ++ #sound-dai-cells = <0>; ++ compatible = "fepi,sgtl5000"; ++ reg = <0x0a>; ++ clocks = <&sgtl5000_mclk>; ++ micbias-resistor-k-ohms = <2>; ++ micbias-voltage-m-volts = <3000>; ++ VDDA-supply = <&vdd_3v3_reg>; ++ VDDIO-supply = <&vdd_3v3_reg>; ++ VDDD-supply = <®_1v8>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "fe-pi,fe-pi-audio"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++}; +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -891,6 +891,7 @@ CONFIG_SND_DIGIDAC1_SOUNDCARD=m + CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m + CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m + CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m ++CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m + CONFIG_SND_PISOUND=m + CONFIG_SND_SOC_ADAU1701=m + CONFIG_SND_SOC_ADAU7002=m +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -885,6 +885,7 @@ CONFIG_SND_DIGIDAC1_SOUNDCARD=m + CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m + CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m + CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m ++CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m + CONFIG_SND_PISOUND=m + CONFIG_SND_SOC_ADAU1701=m + CONFIG_SND_SOC_ADAU7002=m +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -147,6 +147,13 @@ config SND_BCM2708_SOC_ALLO_PIANO_DAC + help + Say Y or M if you want to add support for Allo Piano DAC. + ++config SND_BCM2708_SOC_FE_PI_AUDIO ++ tristate "Support for Fe-Pi-Audio" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_SGTL5000 ++ help ++ Say Y or M if you want to add support for Fe-Pi-Audio. ++ + config SND_PISOUND + tristate "Support for Blokas Labs pisound" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -28,6 +28,7 @@ snd-soc-dionaudio-loco-objs := dionaudio + snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o + snd-soc-allo-piano-dac-objs := allo-piano-dac.o + snd-soc-pisound-objs := pisound.o ++snd-soc-fe-pi-audio-objs := fe-pi-audio.o + + obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o +@@ -48,3 +49,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_L + obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) += snd-soc-dionaudio-loco-v2.o + obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o + obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o ++obj-$(CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO) += snd-soc-fe-pi-audio.o +--- /dev/null ++++ b/sound/soc/bcm/fe-pi-audio.c +@@ -0,0 +1,158 @@ ++/* ++ * ASoC Driver for Fe-Pi Audio Sound Card ++ * ++ * Author: Henry Kupis ++ * Copyright 2016 ++ * based on code by Florian Meier ++ * based on code by Shawn Guo ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "../codecs/sgtl5000.h" ++ ++static int snd_fe_pi_audio_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_card *card = rtd->card; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ snd_soc_dapm_force_enable_pin(&card->dapm, "LO"); ++ snd_soc_dapm_force_enable_pin(&card->dapm, "ADC"); ++ snd_soc_dapm_force_enable_pin(&card->dapm, "DAC"); ++ snd_soc_dapm_force_enable_pin(&card->dapm, "HP"); ++ snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, ++ SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); ++ ++ return 0; ++} ++ ++static int snd_fe_pi_audio_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct device *dev = rtd->card->dev; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ ++ int ret; ++ ++ /* Set SGTL5000's SYSCLK */ ++ ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, 12288000, SND_SOC_CLOCK_IN); ++ if (ret) { ++ dev_err(dev, "could not set codec driver clock params\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++ ++static struct snd_soc_ops snd_fe_pi_audio_ops = { ++ .hw_params = snd_fe_pi_audio_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_fe_pi_audio_dai[] = { ++ { ++ .name = "FE-PI", ++ .stream_name = "Fe-Pi HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "sgtl5000", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "sgtl5000.1-000a", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &snd_fe_pi_audio_ops, ++ .init = snd_fe_pi_audio_init, ++ }, ++}; ++ ++static const struct snd_soc_dapm_route fe_pi_audio_dapm_routes[] = { ++ {"ADC", NULL, "Mic Bias"}, ++}; ++ ++ ++static struct snd_soc_card fe_pi_audio = { ++ .name = "Fe-Pi Audio", ++ .owner = THIS_MODULE, ++ .dai_link = snd_fe_pi_audio_dai, ++ .num_links = ARRAY_SIZE(snd_fe_pi_audio_dai), ++ ++ .dapm_routes = fe_pi_audio_dapm_routes, ++ .num_dapm_routes = ARRAY_SIZE(fe_pi_audio_dapm_routes), ++}; ++ ++static int snd_fe_pi_audio_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ struct snd_soc_card *card = &fe_pi_audio; ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_fe_pi_audio_dai[0]; ++ ++ fe_pi_audio.dev = &pdev->dev; ++ ++ i2s_node = of_parse_phandle(np, "i2s-controller", 0); ++ if (!i2s_node) { ++ dev_err(&pdev->dev, "i2s_node phandle missing or invalid\n"); ++ return -EINVAL; ++ } ++ ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ ++ of_node_put(i2s_node); ++ ++ card->dev = &pdev->dev; ++ platform_set_drvdata(pdev, card); ++ ++ ret = snd_soc_register_card(card); ++ if (ret && ret != -EPROBE_DEFER) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_fe_pi_audio_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&fe_pi_audio); ++} ++ ++static const struct of_device_id snd_fe_pi_audio_of_match[] = { ++ { .compatible = "fe-pi,fe-pi-audio", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_fe_pi_audio_of_match); ++ ++static struct platform_driver snd_fe_pi_audio_driver = { ++ .driver = { ++ .name = "snd-fe-pi-audio", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_fe_pi_audio_of_match, ++ }, ++ .probe = snd_fe_pi_audio_probe, ++ .remove = snd_fe_pi_audio_remove, ++}; ++ ++module_platform_driver(snd_fe_pi_audio_driver); ++ ++MODULE_AUTHOR("Henry Kupis "); ++MODULE_DESCRIPTION("ASoC Driver for Fe-Pi Audio"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/brcm2708/patches-4.9/0193-Add-overlay-for-ads1115-ADCs-1864.patch b/target/linux/brcm2708/patches-4.9/0193-Add-overlay-for-ads1115-ADCs-1864.patch new file mode 100644 index 0000000000..39d48e60b3 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0193-Add-overlay-for-ads1115-ADCs-1864.patch @@ -0,0 +1,159 @@ +From 6d5e32067cf3f3169ec15097c175878de365d247 Mon Sep 17 00:00:00 2001 +From: Scott Ellis +Date: Wed, 1 Mar 2017 07:22:24 -0500 +Subject: [PATCH] Add overlay for ads1115 ADCs (#1864) + +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 22 ++++++ + arch/arm/boot/dts/overlays/ads1115-overlay.dts | 103 +++++++++++++++++++++++++ + 3 files changed, 126 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/ads1115-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -4,6 +4,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + adau1977-adc.dtbo \ + adau7002-simple.dtbo \ + ads1015.dtbo \ ++ ads1115.dtbo \ + ads7846.dtbo \ + akkordion-iqdacplus.dtbo \ + allo-piano-dac-pcm512x-audio.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -196,6 +196,28 @@ Params: addr I2C bus + http://www.ti.com/lit/ds/symlink/ads1015.pdf + + ++Name: ads1115 ++Info: Texas Instruments ADS1115 ADC ++Load: dtoverlay=ads1115,[=] ++Params: addr I2C bus address of device. Set based on how the ++ addr pin is wired. (default=0x48 assumes addr ++ is pulled to GND) ++ cha_enable Enable virtual channel a. ++ cha_cfg Set the configuration for virtual channel a. ++ (default=4 configures this channel for the ++ voltage at A0 with respect to GND) ++ cha_datarate Set the datarate (samples/sec) for this channel. ++ (default=7 sets 860 sps) ++ cha_gain Set the gain of the Programmable Gain ++ Amplifier for this channel. (Default 1 sets the ++ full scale of the channel to 4.096 Volts) ++ ++ Channel parameters can be set for each enabled channel. ++ A maximum of 4 channels can be enabled (letters a thru d). ++ For more information refer to the device datasheet at: ++ http://www.ti.com/lit/ds/symlink/ads1115.pdf ++ ++ + Name: ads7846 + Info: ADS7846 Touch controller + Load: dtoverlay=ads7846,= +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/ads1115-overlay.dts +@@ -0,0 +1,103 @@ ++/* ++ * TI ADS1115 multi-channel ADC overlay ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2c_arm>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ ads1115: ads1115 { ++ compatible = "ti,ads1115"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x48>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target-path = "i2c_arm/ads1115"; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ channel_a: channel_a { ++ reg = <4>; ++ ti,gain = <1>; ++ ti,datarate = <7>; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "i2c_arm/ads1115"; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ channel_b: channel_b { ++ reg = <5>; ++ ti,gain = <1>; ++ ti,datarate = <7>; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target-path = "i2c_arm/ads1115"; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ channel_c: channel_c { ++ reg = <6>; ++ ti,gain = <1>; ++ ti,datarate = <7>; ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target-path = "i2c_arm/ads1115"; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ channel_d: channel_d { ++ reg = <7>; ++ ti,gain = <1>; ++ ti,datarate = <7>; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ addr = <&ads1115>,"reg:0"; ++ cha_enable = <0>,"=1"; ++ cha_cfg = <&channel_a>,"reg:0"; ++ cha_gain = <&channel_a>,"ti,gain:0"; ++ cha_datarate = <&channel_a>,"ti,datarate:0"; ++ chb_enable = <0>,"=2"; ++ chb_cfg = <&channel_b>,"reg:0"; ++ chb_gain = <&channel_b>,"ti,gain:0"; ++ chb_datarate = <&channel_b>,"ti,datarate:0"; ++ chc_enable = <0>,"=3"; ++ chc_cfg = <&channel_c>,"reg:0"; ++ chc_gain = <&channel_c>,"ti,gain:0"; ++ chc_datarate = <&channel_c>,"ti,datarate:0"; ++ chd_enable = <0>,"=4"; ++ chd_cfg = <&channel_d>,"reg:0"; ++ chd_gain = <&channel_d>,"ti,gain:0"; ++ chd_datarate = <&channel_d>,"ti,datarate:0"; ++ }; ++}; diff --git a/target/linux/brcm2708/patches-4.9/0194-clk-bcm2835-Correct-the-prediv-logic.patch b/target/linux/brcm2708/patches-4.9/0194-clk-bcm2835-Correct-the-prediv-logic.patch new file mode 100644 index 0000000000..c81194fe69 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0194-clk-bcm2835-Correct-the-prediv-logic.patch @@ -0,0 +1,27 @@ +From a9913dccdeaabca37343d0d8b0a48cda1e434e02 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 1 Mar 2017 16:06:53 +0000 +Subject: [PATCH] clk-bcm2835: Correct the prediv logic + +If a clock has the prediv flag set, both the integer and fractional +parts must be scaled when calculating the resulting frequency. + +Signed-off-by: Phil Elwell +--- + drivers/clk/bcm/clk-bcm2835.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -616,8 +616,10 @@ static unsigned long bcm2835_pll_get_rat + using_prediv = cprman_read(cprman, data->ana_reg_base + 4) & + data->ana->fb_prediv_mask; + +- if (using_prediv) ++ if (using_prediv) { + ndiv *= 2; ++ fdiv *= 2; ++ } + + return bcm2835_pll_rate_from_divisors(parent_rate, ndiv, fdiv, pdiv); + } diff --git a/target/linux/brcm2708/patches-4.9/0195-amba_pl011-Round-input-clock-up.patch b/target/linux/brcm2708/patches-4.9/0195-amba_pl011-Round-input-clock-up.patch new file mode 100644 index 0000000000..2bd501d8db --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0195-amba_pl011-Round-input-clock-up.patch @@ -0,0 +1,86 @@ +From 0360d687752df3c5546dd1534904a6e0168b6360 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 1 Mar 2017 16:07:39 +0000 +Subject: [PATCH] amba_pl011: Round input clock up + +The UART clock is initialised to be as close to the requested +frequency as possible without exceeding it. Now that there is a +clock manager that returns the actual frequencies, an expected +48MHz clock is reported as 47999625. If the requested baudrate +== requested clock/16, there is no headroom and the slight +reduction in actual clock rate results in failure. + +Detect cases where it looks like a "round" clock was chosen and +adjust the reported clock to match that "round" value. As the +code comment says: + +/* + * If increasing a clock by less than 0.1% changes it + * from ..999.. to ..000.., round up. + */ + +Signed-off-by: Phil Elwell +--- + drivers/tty/serial/amba-pl011.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -1646,6 +1646,23 @@ static void pl011_put_poll_char(struct u + + #endif /* CONFIG_CONSOLE_POLL */ + ++unsigned long pl011_clk_round(unsigned long clk) ++{ ++ unsigned long scaler; ++ ++ /* ++ * If increasing a clock by less than 0.1% changes it ++ * from ..999.. to ..000.., round up. ++ */ ++ scaler = 1; ++ while (scaler * 100000 < clk) ++ scaler *= 10; ++ if ((clk + scaler - 1)/scaler % 1000 == 0) ++ clk = (clk/scaler + 1) * scaler; ++ ++ return clk; ++} ++ + static int pl011_hwinit(struct uart_port *port) + { + struct uart_amba_port *uap = +@@ -1662,7 +1679,7 @@ static int pl011_hwinit(struct uart_port + if (retval) + return retval; + +- uap->port.uartclk = clk_get_rate(uap->clk); ++ uap->port.uartclk = pl011_clk_round(clk_get_rate(uap->clk)); + + /* Clear pending error and receive interrupts */ + pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS | +@@ -2300,7 +2317,7 @@ static int __init pl011_console_setup(st + plat->init(); + } + +- uap->port.uartclk = clk_get_rate(uap->clk); ++ uap->port.uartclk = pl011_clk_round(clk_get_rate(uap->clk)); + + if (uap->vendor->fixed_options) { + baud = uap->fixed_baud; +@@ -2372,6 +2389,7 @@ static struct uart_driver amba_reg = { + .cons = AMBA_CONSOLE, + }; + ++#if 0 + static int pl011_probe_dt_alias(int index, struct device *dev) + { + struct device_node *np; +@@ -2403,6 +2421,7 @@ static int pl011_probe_dt_alias(int inde + + return ret; + } ++#endif + + /* unregisters the driver also if no more ports are left */ + static void pl011_unregister_port(struct uart_amba_port *uap) diff --git a/target/linux/brcm2708/patches-4.9/0196-BCM2835-V4L2-Ensure-H264-header-bytes-get-a-sensible.patch b/target/linux/brcm2708/patches-4.9/0196-BCM2835-V4L2-Ensure-H264-header-bytes-get-a-sensible.patch new file mode 100644 index 0000000000..df8d4b4a4f --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0196-BCM2835-V4L2-Ensure-H264-header-bytes-get-a-sensible.patch @@ -0,0 +1,87 @@ +From 02ceda02182f6cb538be397b8d8f34b64a254559 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 13 Feb 2017 11:10:50 +0000 +Subject: [PATCH] BCM2835-V4L2: Ensure H264 header bytes get a sensible + timestamp + +H264 header come off VC with 0 timestamps, which means they get a +strange timestamp when processed with VC/kernel start times, +particularly if used with the inline header option. +Remember the last frame timestamp and use that if set, or otherwise +use the kernel start time. + +https://github.com/raspberrypi/linux/issues/1836 + +Signed-off-by: Dave Stevenson +--- + drivers/media/platform/bcm2835/bcm2835-camera.c | 30 ++++++++++++++++++++++--- + drivers/media/platform/bcm2835/bcm2835-camera.h | 2 ++ + 2 files changed, 29 insertions(+), 3 deletions(-) + +--- a/drivers/media/platform/bcm2835/bcm2835-camera.c ++++ b/drivers/media/platform/bcm2835/bcm2835-camera.c +@@ -356,8 +356,13 @@ static void buffer_cb(struct vchiq_mmal_ + } + } else { + if (dev->capture.frame_count) { +- if (dev->capture.vc_start_timestamp != -1 && +- pts != 0) { ++ if (dev->capture.vc_start_timestamp == -1) { ++ buf->vb.vb2_buf.timestamp = ktime_get_ns(); ++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, ++ "Buffer time set as current time - %lld", ++ buf->vb.vb2_buf.timestamp); ++ ++ } else if(pts != 0) { + struct timeval timestamp; + s64 runtime_us = pts - + dev->capture.vc_start_timestamp; +@@ -390,10 +395,27 @@ static void buffer_cb(struct vchiq_mmal_ + buf->vb.vb2_buf.timestamp = timestamp.tv_sec * 1000000000ULL + + timestamp.tv_usec * 1000ULL; + } else { +- buf->vb.vb2_buf.timestamp = ktime_get_ns(); ++ if (dev->capture.last_timestamp) { ++ buf->vb.vb2_buf.timestamp = dev->capture.last_timestamp; ++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, ++ "Buffer time set as last timestamp - %lld", ++ buf->vb.vb2_buf.timestamp); ++ } ++ else { ++ buf->vb.vb2_buf.timestamp = ++ dev->capture.kernel_start_ts.tv_sec * 1000000000ULL + ++ dev->capture.kernel_start_ts.tv_usec * 1000ULL; ++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, ++ "Buffer time set as start timestamp - %lld", ++ buf->vb.vb2_buf.timestamp); ++ } + } ++ dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp; + + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length); ++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, ++ "Buffer has ts %llu", ++ dev->capture.last_timestamp); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + + if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS && +@@ -559,6 +581,8 @@ static int start_streaming(struct vb2_qu + "Start time %lld size %d\n", + dev->capture.vc_start_timestamp, parameter_size); + ++ dev->capture.last_timestamp = 0; ++ + v4l2_get_timestamp(&dev->capture.kernel_start_ts); + + /* enable the camera port */ +--- a/drivers/media/platform/bcm2835/bcm2835-camera.h ++++ b/drivers/media/platform/bcm2835/bcm2835-camera.h +@@ -93,6 +93,8 @@ struct bm2835_mmal_dev { + s64 vc_start_timestamp; + /* Kernel start timestamp for streaming */ + struct timeval kernel_start_ts; ++ /* Timestamp of last frame */ ++ u64 last_timestamp; + + struct vchiq_mmal_port *port; /* port being used for capture */ + /* camera port being used for capture */ diff --git a/target/linux/brcm2708/patches-4.9/0197-BCM2835-V4L2-Correctly-denote-key-frames-in-encoded-.patch b/target/linux/brcm2708/patches-4.9/0197-BCM2835-V4L2-Correctly-denote-key-frames-in-encoded-.patch new file mode 100644 index 0000000000..4b375abad9 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0197-BCM2835-V4L2-Correctly-denote-key-frames-in-encoded-.patch @@ -0,0 +1,24 @@ +From 9136b739f4ecc714db0431a3e0f4f4d9b12ab670 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 13 Feb 2017 13:11:41 +0000 +Subject: [PATCH] BCM2835-V4L2: Correctly denote key frames in encoded data + +Forward MMAL key frame flags to the V4L2 buffers. + +Signed-off-by: Dave Stevenson +--- + drivers/media/platform/bcm2835/bcm2835-camera.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/media/platform/bcm2835/bcm2835-camera.c ++++ b/drivers/media/platform/bcm2835/bcm2835-camera.c +@@ -413,6 +413,9 @@ static void buffer_cb(struct vchiq_mmal_ + dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp; + + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length); ++ if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME) ++ buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME; ++ + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "Buffer has ts %llu", + dev->capture.last_timestamp); diff --git a/target/linux/brcm2708/patches-4.9/0198-bcm2835-gpio-exp-Driver-for-GPIO-expander-via-mailbo.patch b/target/linux/brcm2708/patches-4.9/0198-bcm2835-gpio-exp-Driver-for-GPIO-expander-via-mailbo.patch new file mode 100644 index 0000000000..3d09d1dc3f --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0198-bcm2835-gpio-exp-Driver-for-GPIO-expander-via-mailbo.patch @@ -0,0 +1,405 @@ +From 2f8f62fbd42a55825da437faba4b6164f2e0bee9 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 20 Feb 2017 17:01:21 +0000 +Subject: [PATCH] bcm2835-gpio-exp: Driver for GPIO expander via mailbox + service + +Pi3 and Compute Module 3 have a GPIO expander that the +VPU communicates with. +There is a mailbox service that now allows control of this +expander, so add a kernel driver that can make use of it. + +Pwr_led node added to device-tree for Pi3. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 22 +++ + arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 10 +- + arch/arm/configs/bcm2709_defconfig | 1 + + drivers/gpio/Kconfig | 7 + + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-bcm-exp.c | 256 +++++++++++++++++++++++++++++ + include/soc/bcm2835/raspberrypi-firmware.h | 4 + + 7 files changed, 300 insertions(+), 1 deletion(-) + create mode 100644 drivers/gpio/gpio-bcm-exp.c + +--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts +@@ -96,6 +96,14 @@ + firmware = <&firmware>; + status = "okay"; + }; ++ ++ expgpio: expgpio { ++ compatible = "brcm,bcm2835-expgpio"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ firmware = <&firmware>; ++ status = "okay"; ++ }; + }; + + &fb { +@@ -163,6 +171,16 @@ + linux,default-trigger = "mmc0"; + gpios = <&virtgpio 0 0>; + }; ++ ++ pwr_led: pwr { ++ label = "led1"; ++ linux,default-trigger = "input"; ++ gpios = <&expgpio 7 GPIO_ACTIVE_LOW>; ++ }; ++}; ++ ++&hdmi { ++ hpd-gpios = <&expgpio 4 GPIO_ACTIVE_LOW>; + }; + + &audio { +@@ -193,6 +211,10 @@ + act_led_activelow = <&act_led>,"gpios:8"; + act_led_trigger = <&act_led>,"linux,default-trigger"; + ++ pwr_led_gpio = <&pwr_led>,"gpios:4"; ++ pwr_led_activelow = <&pwr_led>,"gpios:8"; ++ pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; ++ + audio = <&audio>,"status"; + watchdog = <&watchdog>,"status"; + random = <&random>,"status"; +--- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts +@@ -65,6 +65,14 @@ + firmware = <&firmware>; + status = "okay"; + }; ++ ++ expgpio: expgpio { ++ compatible = "brcm,bcm2835-expgpio"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ firmware = <&firmware>; ++ status = "okay"; ++ }; + }; + + &fb { +@@ -123,7 +131,7 @@ + }; + + &hdmi { +- hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; ++ hpd-gpios = <&expgpio 0 GPIO_ACTIVE_LOW>; + }; + + &audio { +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -625,6 +625,7 @@ CONFIG_PPS=m + CONFIG_PPS_CLIENT_LDISC=m + CONFIG_PPS_CLIENT_GPIO=m + CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_BCM_EXP=y + CONFIG_GPIO_BCM_VIRT=y + CONFIG_GPIO_ARIZONA=m + CONFIG_GPIO_STMPE=y +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -128,6 +128,13 @@ config GPIO_AXP209 + help + Say yes to enable GPIO support for the AXP209 PMIC + ++config GPIO_BCM_EXP ++ bool "Broadcom Exp GPIO" ++ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || COMPILE_TEST) ++ help ++ Turn on GPIO support for Broadcom chips using the firmware mailbox ++ to communicate with VideoCore on BCM283x chips. ++ + config GPIO_BCM_KONA + bool "Broadcom Kona GPIO" + depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST) +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -30,6 +30,7 @@ obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizo + obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o + obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o + obj-$(CONFIG_GPIO_AXP209) += gpio-axp209.o ++obj-$(CONFIG_GPIO_BCM_EXP) += gpio-bcm-exp.o + obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o + obj-$(CONFIG_GPIO_BCM_VIRT) += gpio-bcm-virt.o + obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o +--- /dev/null ++++ b/drivers/gpio/gpio-bcm-exp.c +@@ -0,0 +1,256 @@ ++/* ++ * Broadcom expander GPIO driver ++ * ++ * Uses the firmware mailbox service to communicate with the ++ * GPIO expander on the VPU. ++ * ++ * Copyright (C) 2017 Raspberry Pi Trading Ltd. ++ * ++ * Author: Dave Stevenson ++ * Based on gpio-bcm-virt.c by Dom Cobley ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MODULE_NAME "brcmexp-gpio" ++#define NUM_GPIO 8 ++ ++struct brcmexp_gpio { ++ struct gpio_chip gc; ++ struct device *dev; ++ struct rpi_firmware *fw; ++}; ++ ++struct gpio_set_config { ++ u32 gpio, direction, polarity, term_en, term_pull_up, state; ++}; ++ ++struct gpio_get_config { ++ u32 gpio, direction, polarity, term_en, term_pull_up; ++}; ++ ++struct gpio_get_set_state { ++ u32 gpio, state; ++}; ++ ++static int brcmexp_gpio_get_polarity(struct gpio_chip *gc, unsigned int off) ++{ ++ struct brcmexp_gpio *gpio; ++ struct gpio_get_config get; ++ int ret; ++ ++ gpio = container_of(gc, struct brcmexp_gpio, gc); ++ ++ get.gpio = off + gpio->gc.base; /* GPIO to update */ ++ ++ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_CONFIG, ++ &get, sizeof(get)); ++ if (ret) { ++ dev_err(gpio->dev, ++ "Failed to get GPIO %u config (%d)\n", off, ret); ++ return ret; ++ } ++ return get.polarity; ++} ++ ++static int brcmexp_gpio_dir_in(struct gpio_chip *gc, unsigned int off) ++{ ++ struct brcmexp_gpio *gpio; ++ struct gpio_set_config set_in; ++ int ret; ++ ++ gpio = container_of(gc, struct brcmexp_gpio, gc); ++ ++ set_in.gpio = off + gpio->gc.base; /* GPIO to update */ ++ set_in.direction = 0; /* Input */ ++ set_in.polarity = brcmexp_gpio_get_polarity(gc, off); ++ /* Retain existing setting */ ++ set_in.term_en = 0; /* termination disabled */ ++ set_in.term_pull_up = 0; /* n/a as termination disabled */ ++ set_in.state = 0; /* n/a as configured as an input */ ++ ++ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_CONFIG, ++ &set_in, sizeof(set_in)); ++ if (ret) { ++ dev_err(gpio->dev, ++ "Failed to set GPIO %u to input (%d)\n", ++ off, ret); ++ return ret; ++ } ++ return 0; ++} ++ ++static int brcmexp_gpio_dir_out(struct gpio_chip *gc, unsigned int off, int val) ++{ ++ struct brcmexp_gpio *gpio; ++ struct gpio_set_config set_out; ++ int ret; ++ ++ gpio = container_of(gc, struct brcmexp_gpio, gc); ++ ++ set_out.gpio = off + gpio->gc.base; /* GPIO to update */ ++ set_out.direction = 1; /* Output */ ++ set_out.polarity = brcmexp_gpio_get_polarity(gc, off); ++ /* Retain existing setting */ ++ set_out.term_en = 0; /* n/a as an output */ ++ set_out.term_pull_up = 0; /* n/a as termination disabled */ ++ set_out.state = val; /* Output state */ ++ ++ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_CONFIG, ++ &set_out, sizeof(set_out)); ++ if (ret) { ++ dev_err(gpio->dev, ++ "Failed to set GPIO %u to output (%d)\n", off, ret); ++ return ret; ++ } ++ return 0; ++} ++ ++static int brcmexp_gpio_get_direction(struct gpio_chip *gc, unsigned int off) ++{ ++ struct brcmexp_gpio *gpio; ++ struct gpio_get_config get; ++ int ret; ++ ++ gpio = container_of(gc, struct brcmexp_gpio, gc); ++ ++ get.gpio = off + gpio->gc.base; /* GPIO to update */ ++ ++ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_CONFIG, ++ &get, sizeof(get)); ++ if (ret) { ++ dev_err(gpio->dev, ++ "Failed to get GPIO %u config (%d)\n", off, ret); ++ return ret; ++ } ++ return get.direction ? GPIOF_DIR_OUT : GPIOF_DIR_IN; ++} ++ ++static int brcmexp_gpio_get(struct gpio_chip *gc, unsigned int off) ++{ ++ struct brcmexp_gpio *gpio; ++ struct gpio_get_set_state get; ++ int ret; ++ ++ gpio = container_of(gc, struct brcmexp_gpio, gc); ++ ++ get.gpio = off + gpio->gc.base; /* GPIO to update */ ++ get.state = 0; /* storage for returned value */ ++ ++ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_STATE, ++ &get, sizeof(get)); ++ if (ret) { ++ dev_err(gpio->dev, ++ "Failed to get GPIO %u state (%d)\n", off, ret); ++ return ret; ++ } ++ return !!get.state; ++} ++ ++static void brcmexp_gpio_set(struct gpio_chip *gc, unsigned int off, int val) ++{ ++ struct brcmexp_gpio *gpio; ++ struct gpio_get_set_state set; ++ int ret; ++ ++ gpio = container_of(gc, struct brcmexp_gpio, gc); ++ ++ off += gpio->gc.base; ++ ++ set.gpio = off + gpio->gc.base; /* GPIO to update */ ++ set.state = val; /* Output state */ ++ ++ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_STATE, ++ &set, sizeof(set)); ++ if (ret) ++ dev_err(gpio->dev, ++ "Failed to set GPIO %u state (%d)\n", off, ret); ++} ++ ++static int brcmexp_gpio_probe(struct platform_device *pdev) ++{ ++ int err = 0; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct device_node *fw_node; ++ struct rpi_firmware *fw; ++ struct brcmexp_gpio *ucb; ++ ++ fw_node = of_parse_phandle(np, "firmware", 0); ++ if (!fw_node) { ++ dev_err(dev, "Missing firmware node\n"); ++ return -ENOENT; ++ } ++ ++ fw = rpi_firmware_get(fw_node); ++ if (!fw) ++ return -EPROBE_DEFER; ++ ++ ucb = devm_kzalloc(dev, sizeof(*ucb), GFP_KERNEL); ++ if (!ucb) ++ return -EINVAL; ++ ++ ucb->fw = fw; ++ ucb->dev = dev; ++ ucb->gc.label = MODULE_NAME; ++ ucb->gc.owner = THIS_MODULE; ++ ucb->gc.of_node = np; ++ ucb->gc.base = 128; ++ ucb->gc.ngpio = NUM_GPIO; ++ ++ ucb->gc.direction_input = brcmexp_gpio_dir_in; ++ ucb->gc.direction_output = brcmexp_gpio_dir_out; ++ ucb->gc.get_direction = brcmexp_gpio_get_direction; ++ ucb->gc.get = brcmexp_gpio_get; ++ ucb->gc.set = brcmexp_gpio_set; ++ ucb->gc.can_sleep = true; ++ ++ err = gpiochip_add(&ucb->gc); ++ if (err) ++ return err; ++ ++ platform_set_drvdata(pdev, ucb); ++ ++ return 0; ++} ++ ++static int brcmexp_gpio_remove(struct platform_device *pdev) ++{ ++ struct brcmexp_gpio *ucb = platform_get_drvdata(pdev); ++ ++ gpiochip_remove(&ucb->gc); ++ ++ return 0; ++} ++ ++static const struct of_device_id __maybe_unused brcmexp_gpio_ids[] = { ++ { .compatible = "brcm,bcm2835-expgpio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, brcmexp_gpio_ids); ++ ++static struct platform_driver brcmexp_gpio_driver = { ++ .driver = { ++ .name = MODULE_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(brcmexp_gpio_ids), ++ }, ++ .probe = brcmexp_gpio_probe, ++ .remove = brcmexp_gpio_remove, ++}; ++module_platform_driver(brcmexp_gpio_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Dave Stevenson "); ++MODULE_DESCRIPTION("brcm-exp GPIO driver"); ++MODULE_ALIAS("platform:brcmexp-gpio"); +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -83,7 +83,11 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_SET_TURBO = 0x00038009, + RPI_FIRMWARE_SET_CUSTOMER_OTP = 0x00038021, + RPI_FIRMWARE_SET_DOMAIN_STATE = 0x00038030, ++ RPI_FIRMWARE_GET_GPIO_STATE = 0x00030041, ++ RPI_FIRMWARE_SET_GPIO_STATE = 0x00038041, + RPI_FIRMWARE_SET_SDHOST_CLOCK = 0x00038042, ++ RPI_FIRMWARE_GET_GPIO_CONFIG = 0x00030043, ++ RPI_FIRMWARE_SET_GPIO_CONFIG = 0x00038043, + + /* Dispmanx TAGS */ + RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, diff --git a/target/linux/brcm2708/patches-4.9/0199-BCM270X_DT-Add-bcm2708-rpi-0-w.dts.patch b/target/linux/brcm2708/patches-4.9/0199-BCM270X_DT-Add-bcm2708-rpi-0-w.dts.patch new file mode 100644 index 0000000000..c3a87517e2 --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/0199-BCM270X_DT-Add-bcm2708-rpi-0-w.dts.patch @@ -0,0 +1,225 @@ +From 41620ad7f4b059be162f615a7be423df78406d29 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 24 May 2016 16:30:05 +0100 +Subject: [PATCH] BCM270X_DT: Add bcm2708-rpi-0-w.dts + +Add DT support for the Pi Zero W. N.B. It will not be loaded +automatically without a corresponding change to the firmware. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm2708-rpi-0-w.dts | 197 ++++++++++++++++++++++++++++++++++ + 2 files changed, 198 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm2708-rpi-0-w.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \ + bcm2708-rpi-b.dtb \ + bcm2708-rpi-b-plus.dtb \ + bcm2708-rpi-cm.dtb \ ++ bcm2708-rpi-0-w.dtb \ + bcm2709-rpi-2-b.dtb \ + bcm2710-rpi-3-b.dtb \ + bcm2710-rpi-cm3.dtb +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2708-rpi-0-w.dts +@@ -0,0 +1,197 @@ ++/dts-v1/; ++ ++#include "bcm2708.dtsi" ++ ++/ { ++ model = "Raspberry Pi Zero W"; ++}; ++ ++&gpio { ++ sdhost_pins: sdhost_pins { ++ brcm,pins = <48 49 50 51 52 53>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++ ++ spi0_pins: spi0_pins { ++ brcm,pins = <9 10 11>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++ ++ spi0_cs_pins: spi0_cs_pins { ++ brcm,pins = <8 7>; ++ brcm,function = <1>; /* output */ ++ }; ++ ++ i2c0_pins: i2c0 { ++ brcm,pins = <0 1>; ++ brcm,function = <4>; ++ }; ++ ++ i2c1_pins: i2c1 { ++ brcm,pins = <2 3>; ++ brcm,function = <4>; ++ }; ++ ++ i2s_pins: i2s { ++ brcm,pins = <18 19 20 21>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++ ++ sdio_pins: sdio_pins { ++ brcm,pins = <34 35 36 37 38 39>; ++ brcm,function = <7>; /* ALT3 = SD1 */ ++ brcm,pull = <0 2 2 2 2 2>; ++ }; ++ ++ bt_pins: bt_pins { ++ brcm,pins = <43>; ++ brcm,function = <4>; /* alt0:GPCLK2 */ ++ brcm,pull = <0>; /* none */ ++ }; ++ ++ uart0_pins: uart0_pins { ++ brcm,pins = <30 31 32 33>; ++ brcm,function = <7>; /* alt3=UART0 */ ++ brcm,pull = <2 0 0 2>; /* up none none up */ ++ }; ++ ++ uart1_pins: uart1_pins { ++ brcm,pins; ++ brcm,function; ++ brcm,pull; ++ }; ++ ++ audio_pins: audio_pins { ++ brcm,pins = <>; ++ brcm,function = <>; ++ }; ++}; ++ ++&sdhost { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdhost_pins>; ++ bus-width = <4>; ++ status = "okay"; ++}; ++ ++&mmc { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdio_pins>; ++ non-removable; ++ bus-width = <4>; ++ status = "okay"; ++}; ++ ++&fb { ++ status = "okay"; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins &bt_pins>; ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ status = "okay"; ++}; ++ ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins &spi0_cs_pins>; ++ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; ++ ++ spidev0: spidev@0{ ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; ++ }; ++ ++ spidev1: spidev@1{ ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; ++ }; ++}; ++ ++&i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; ++ clock-frequency = <100000>; ++}; ++ ++&i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ clock-frequency = <100000>; ++}; ++ ++&i2c2 { ++ clock-frequency = <100000>; ++}; ++ ++&i2s { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s_pins>; ++}; ++ ++&random { ++ status = "okay"; ++}; ++ ++&leds { ++ act_led: act { ++ label = "led0"; ++ linux,default-trigger = "mmc0"; ++ gpios = <&gpio 47 0>; ++ }; ++}; ++ ++&hdmi { ++ hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; ++}; ++ ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_pins>; ++}; ++ ++/ { ++ chosen { ++ bootargs = "8250.nr_uarts=1"; ++ }; ++}; ++ ++/ { ++ __overrides__ { ++ uart0 = <&uart0>,"status"; ++ uart1 = <&uart1>,"status"; ++ i2s = <&i2s>,"status"; ++ spi = <&spi0>,"status"; ++ i2c0 = <&i2c0>,"status"; ++ i2c1 = <&i2c1>,"status"; ++ i2c2_iknowwhatimdoing = <&i2c2>,"status"; ++ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; ++ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; ++ i2c2_baudrate = <&i2c2>,"clock-frequency:0"; ++ ++ act_led_gpio = <&act_led>,"gpios:4"; ++ act_led_activelow = <&act_led>,"gpios:8"; ++ act_led_trigger = <&act_led>,"linux,default-trigger"; ++ ++ audio = <&audio>,"status"; ++ watchdog = <&watchdog>,"status"; ++ random = <&random>,"status"; ++ sd_overclock = <&sdhost>,"brcm,overclock-50:0"; ++ sd_force_pio = <&sdhost>,"brcm,force-pio?"; ++ sd_pio_limit = <&sdhost>,"brcm,pio-limit:0"; ++ sd_debug = <&sdhost>,"brcm,debug"; ++ }; ++};