[source] brcm2708: update linux 4.9 patches to latest version

LEDE Commits lede-commits at lists.infradead.org
Sat Mar 4 10:48:16 PST 2017


noltari pushed a commit to source.git, branch master:
https://git.lede-project.org/baad22eed3ea3242051bbde6ebf56e74deb11ea6

commit baad22eed3ea3242051bbde6ebf56e74deb11ea6
Author: Álvaro Fernández Rojas <noltari at gmail.com>
AuthorDate: Sat Mar 4 19:37:50 2017 +0100

    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 <noltari at gmail.com>
---
 target/linux/brcm2708/base-files/etc/diag.sh       |    3 +-
 target/linux/brcm2708/bcm2708/config-4.9           |    1 +
 target/linux/brcm2708/bcm2709/config-4.9           |    1 +
 target/linux/brcm2708/bcm2710/config-4.9           |    1 +
 target/linux/brcm2708/modules.mk                   |   50 +-
 ...0001-smsx95xx-fix-crimes-against-truesize.patch |    2 +-
 ...perimental-Enable-turbo_mode-and-packetsi.patch |    2 +-
 ...3-Allow-mac-address-to-be-set-in-smsc95xx.patch |    2 +-
 ...elease_resource-against-resources-without.patch |    2 +-
 .../0005-mm-Remove-the-PFN-busy-warning.patch      |    2 +-
 ...-Prevent-spurious-interrupts-and-trap-the.patch |    2 +-
 .../0007-irqchip-bcm2835-Add-FIQ-support.patch     |    2 +-
 ...-irqchip-irq-bcm2835-Add-2836-FIQ-support.patch |    2 +-
 ...erial-8250-Don-t-crash-when-nr_uarts-is-0.patch |    2 +-
 ...2835-Set-base-to-0-give-expected-gpio-num.patch |    2 +-
 ...2835-Fix-interrupt-handling-for-GPIOs-28-.patch |    2 +-
 ...2835-Only-request-the-interrupts-listed-i.patch |    2 +-
 ...-bcm2835-Return-pins-to-inputs-when-freed.patch |    2 +-
 ...cm2835-Support-pin-groups-other-than-7-11.patch |    2 +-
 ...16-spi-bcm2835-Disable-forced-software-CS.patch |    2 +-
 .../0017-spi-bcm2835-Remove-unused-code.patch      |    2 +-
 ...RM-bcm2835-Set-Serial-number-and-Revision.patch |    2 +-
 ...cm2835-Load-driver-early-and-support-lega.patch |    2 +-
 .../0020-firmware-Updated-mailbox-header.patch     |    2 +-
 ...-Mark-GPIO-clocks-enabled-at-boot-as-crit.patch |    2 +-
 ...0022-rtc-Add-SPI-alias-for-pcf2123-driver.patch |    2 +-
 ...-bcm2835-Support-setting-reboot-partition.patch |    2 +-
 ...power-off-rather-than-busy-spinning-when-.patch |    2 +-
 ...5-bcm-Make-RASPBERRYPI_POWER-depend-on-PM.patch |    2 +-
 ...-the-clocks-early-during-the-boot-process.patch |    2 +-
 ...rng-Avoid-initialising-if-already-enabled.patch |    2 +-
 ...gnore-dtco-targets-when-filtering-symbols.patch |    2 +-
 .../0029-BCM2835_DT-Fix-I2S-register-map.patch     |    2 +-
 .../0030-Main-bcm2708-bcm2709-linux-port.patch     |    2 +-
 .../patches-4.9/0031-Add-dwc_otg-driver.patch      |    2 +-
 .../0032-bcm2708-framebuffer-driver.patch          |    2 +-
 .../0033-dmaengine-Add-support-for-BCM2708.patch   |    2 +-
 .../0034-MMC-added-alternative-MMC-driver.patch    |    2 +-
 ...835-sdhost-driver-and-an-overlay-to-enabl.patch |    2 +-
 ...Add-MMC_QUIRK_ERASE_BROKEN-for-some-cards.patch |    2 +-
 ...ma-Add-vc_cma-driver-to-enable-use-of-CMA.patch |    2 +-
 .../0038-bcm2708-alsa-sound-driver.patch           |    2 +-
 ...vc_mem-driver-for-querying-firmware-memor.patch |    2 +-
 ...deoCore-shared-memory-service-for-BCM2835.patch |    2 +-
 ...omem-device-for-rootless-user-GPIO-access.patch |    2 +-
 .../brcm2708/patches-4.9/0042-Add-SMI-driver.patch |    2 +-
 ...5-smi-use-clock-manager-and-fix-reload-is.patch |    2 +-
 .../patches-4.9/0044-Add-SMI-NAND-driver.patch     |    2 +-
 ...5-lirc-added-support-for-RaspberryPi-GPIO.patch |    2 +-
 .../patches-4.9/0046-Add-cpufreq-driver.patch      |    2 +-
 ...-thermal-driver-for-reporting-core-temper.patch |    2 +-
 .../0048-Add-Chris-Boot-s-i2c-driver.patch         |    2 +-
 .../0049-char-broadcom-Add-vcio-module.patch       |    2 +-
 ...050-firmware-bcm2835-Support-ARCH_BCM270x.patch |    2 +-
 .../0051-bcm2835-add-v4l2-camera-device.patch      |    2 +-
 ...-mkknlimg-and-knlinfo-scripts-from-tools-.patch |    2 +-
 ...ipts-dtc-Update-to-upstream-version-1.4.1.patch |    2 +-
 ...0054-BCM2708-Add-core-Device-Tree-support.patch |    2 +-
 ...Add-pwr_led-and-the-required-input-trigge.patch |    2 +-
 .../0056-fbdev-add-FBIOCOPYAREA-ioctl.patch        |    2 +-
 ...up-console-framebuffer-imageblit-function.patch |    2 +-
 ...e-realtime-clock-1-wire-chip-DS1307-and-1.patch |    2 +-
 ...059-Added-Device-IDs-for-August-DVB-T-205.patch |    2 +-
 ...le-CONFIG_MEMCG-but-leave-it-disabled-due.patch |    2 +-
 ...ce-default-mouse-polling-interval-to-60Hz.patch |    2 +-
 ...Add-touchscreen-driver-for-pi-LCD-display.patch |    2 +-
 ...opy_to_user-and-__copy_from_user-performa.patch |    2 +-
 ...poweroff-Allow-it-to-work-on-Raspberry-Pi.patch |    2 +-
 ...fd-Add-Raspberry-Pi-Sense-HAT-core-driver.patch |    2 +-
 .../0066-ASoC-Add-support-for-HifiBerry-DAC.patch  |    2 +-
 .../0067-ASoC-Add-support-for-Rpi-DAC.patch        |    2 +-
 ...-Implement-MCLK-configuration-options-add.patch |    2 +-
 ...d-support-for-HiFiBerry-Digi.-Driver-is-b.patch |    2 +-
 ...audIO-Sound-Card-support-for-Raspberry-Pi.patch |    2 +-
 .../0071-iqaudio-dac-Compile-fix-untested.patch    |    2 +-
 .../0072-Added-support-for-HiFiBerry-DAC.patch     |    2 +-
 ...r-for-HiFiBerry-Amp-amplifier-add-on-boar.patch |   29 +-
 ...d-driver-for-HiFiBerry-Amp-amplifier-add-.patch |  807 ---------
 ...te-ds1307-driver-for-device-tree-support.patch} |    2 +-
 ...o.patch => 0075-Add-driver-for-rpi-proto.patch} |    9 +-
 ...-support.patch => 0076-RaspiDAC3-support.patch} |   10 +-
 ...77-Add-Support-for-JustBoom-Audio-boards.patch} |    8 +-
 ...-adc-Add-basic-machine-driver-for-adau19.patch} |   10 +-
 ...ector.net-Pi-soundcard-with-low-jitter-a.patch} |   10 +-
 ...80-Add-IQAudIO-Digi-WM8804-board-support.patch} |    8 +-
 ...or-RRA-DigiDAC1-soundcard-using-WM8741-W.patch} |   10 +-
 ...-support-for-Dion-Audio-LOCO-DAC-AMP-HAT.patch} |   10 +-
 ...AC-boards-Initial-2-channel-stereo-suppo.patch} |   10 +-
 ...84-Support-for-Blokas-Labs-pisound-board.patch} |   10 +-
 ...display-add-backlight-driver-and-overlay.patch} |    2 +-
 ...086-bcm2835-virtgpio-Virtual-GPIO-driver.patch} |    2 +-
 ...pl011-Don-t-use-DT-aliases-for-numbering.patch} |    2 +-
 ...=> 0090-OF-DT-Overlay-configfs-interface.patch} |    2 +-
 ...2-hci_h5-Don-t-send-conf_req-when-ACTIVE.patch} |    2 +-
 ...patch => 0093-config-Add-default-configs.patch} |    2 +-
 ...onfiguration-and-device-tree-differences.patch} |    2 +-
 ... 0095-vchiq_arm-Tweak-the-logging-output.patch} |    2 +-
 ...m-Access-the-dequeue_pending-flag-locked.patch} |    2 +-
 ...chiq_arm-Service-callbacks-must-not-fail.patch} |    2 +-
 ...m-Add-completion-records-under-the-mutex.patch} |    2 +-
 ...arm-Avoid-use-of-mutex-in-add_completion.patch} |    2 +-
 ...-Convert-to-current-get_user_pages-argum.patch} |    2 +-
 ...-Update-for-rename-of-page_cache_release.patch} |    2 +-
 ...-vchi-Remove-dependency-on-CONFIG_BROKEN.patch} |    2 +-
 ...firmware-Export-the-general-transaction-.patch} |    2 +-
 ...firmware-Define-the-MBOX-channel-in-the-.patch} |    2 +-
 ...a-mode-for-using-the-closed-firmware-for.patch} |    2 +-
 ...Fix-hang-for-writing-messages-larger-tha.patch} |    2 +-
 ...Protect-against-unexpected-TXW-RXR-inter.patch} |    2 +-
 ...5-Use-dev_dbg-logging-on-transfer-errors.patch} |    2 +-
 ...c-bcm2835-Can-t-support-I2C_M_IGNORE_NAK.patch} |    2 +-
 ...Add-support-for-Repeated-Start-Condition.patch} |    2 +-
 ...cm2835-Support-i2c-dev-ioctl-I2C_TIMEOUT.patch} |    2 +-
 ...2c-bcm2835-Add-support-for-dynamic-clock.patch} |    2 +-
 ...ch => 0113-i2c-bcm2835-Add-debug-support.patch} |    2 +-
 ...ch => 0114-arm64-Add-CONFIG_ARCH_BCM2835.patch} |    2 +-
 ...for-Silicon-Labs-Si7013-20-21-humidity-t.patch} |    2 +-
 ...patch => 0116-Document-the-si7020-option.patch} |    2 +-
 ...ments.patch => 0117-pisound-improvements.patch} |    2 +-
 ...y.patch => 0118-Add-driver_name-property.patch} |    2 +-
 ....patch => 0119-Add-driver_name-paramater.patch} |    2 +-
 ...rt-Added-driver-for-HiFiBerry-Amp-amplifi.patch |  809 ---------
 ...-BCM270X_DT-Add-pi3-disable-wifi-overlay.patch} |    2 +-
 ...ry-amp-Adjust-for-ALSA-object-refactoring.patch |   25 -
 ...121-ARM64-Make-it-work-again-on-4.9-1790.patch} |    2 +-
 ...-Changes-for-allowing-asymmetric-sample-f.patch |   89 -
 ...-Kernel-Address-Space-Randomization-1792.patch} |    2 +-
 ...e-RTL8187-RTL8192CU-wifi-in-build-config.patch} |    2 +-
 ...h => 0125-BCM270X_DT-Add-spi0-cs-overlay.patch} |    2 +-
 ...6-spi-bcm2835-Disable-forced-software-CS.patch} |    2 +-
 ...h => 0127-config-Add-CONFIG_TCP_CONG_BBR.patch} |    2 +-
 ...h => 0128-BCM270X_DT-Enable-UART0-on-CM3.patch} |    2 +-
 ...d-CONFIG_MD_M25P80-and-CONFIG_MD_SPI_NOR.patch} |    2 +-
 ...M64-DWC_OTG-Port-dwc_otg-driver-to-ARM64.patch} |    2 +-
 ...4-Round-Robin-dispatch-IRQs-between-CPUs.patch} |    2 +-
 ...-DWC_OTG-Driver-In-ARM64-Build-Config-bc.patch} |    2 +-
 ...835-i2s-Changes-for-allowing-asymmetric-s.patch |   90 -
 ...64-Use-dwc_otg-driver-by-default-for-USB.patch} |    2 +-
 ...DT-Add-reference-to-audio_pins-to-CM-dtb.patch} |    2 +-
 ...dd-additional-network-scheduling-modules.patch} |    2 +-
 ...-ASoC-A-simple-card-overlay-for-ADAU7002.patch} |    2 +-
 ...config-Add-SND_SOC_ADAU7002-codec-module.patch} |    2 +-
 ...=> 0138-Add-overlay-for-mcp3008-adc-1818.patch} |    2 +-
 ...id-suspending-if-we-re-in-gadget-mode-18.patch} |    2 +-
 ...-Remove-unnecessary-dev_info-output-1830.patch} |    2 +-
 ... => 0141-config-Enable-regulator-support.patch} |    2 +-
 ...M270x-DT-expose-3.3V-and-5V-system-rails.patch} |    2 +-
 ...M270x-DT-Consolidate-audio-card-overlays.patch} |    2 +-
 ...C-Add-driver-for-Cirrus-Logic-Audio-Card.patch} |    2 +-
 ...45-config-enable-Cirrus-Logic-Audio-Card.patch} |    2 +-
 ...irq-bcm2836-Avoid-Invalid-trigger-warning.patch |   24 +
 ...ound-Demote-deferral-errors-to-INFO-level.patch |   35 +
 ...nd-Suppress-error-message-about-deferrals.patch |  217 +++
 .../patches-4.9/0149-Update-vfpmodule.c.patch      |  137 ++
 ...-summarize-urb-actual_length-for-isochron.patch |   28 +
 ...clk-bcm2835-Fix-fixed_divider-of-pllh_aux.patch |   27 +
 ...port-rate-change-propagation-on-bcm2835-c.patch |  124 ++
 ...ow-rate-change-propagation-to-PLLH_AUX-on.patch |   35 +
 ...-maybe-uninitialized-warning-in-bcm2835_c.patch |   29 +
 ...-Don-t-rate-change-PLLs-on-behalf-of-DSI-.patch |  172 ++
 ...m2835-Register-the-DSI0-DSI1-pixel-clocks.patch |  238 +++
 ...-Add-leaf-clock-measurement-support-disab.patch |  346 ++++
 ...dd-support-for-the-Raspberry-Pi-7-Touchsc.patch |  575 +++++++
 ...CM270X-Add-the-DSI-panel-to-the-defconfig.patch |   45 +
 ...35-dt-Add-the-DSI-module-nodes-and-clocks.patch |  101 ++
 ...ble-the-DSI-panel-node-in-the-VC4-overlay.patch |  138 ++
 ...-termination-of-the-initial-scan-for-bran.patch |   68 +
 ...-support-for-rendering-with-ETC1-textures.patch |   55 +
 ...-runtime-autosuspend-to-avoid-thrashing-V.patch |   78 +
 ...vc4-Add-fragment-shader-threading-support.patch |  228 +++
 ...-race-between-page-flip-completion-event-.patch |   93 +
 ...-clock_select-setting-for-the-VEC-encoder.patch |  113 ++
 ...V-connector-states-to-drm_connector_state.patch |  148 ++
 ...M_MODE_SUBCONNECTOR_xx-definitions-into-a.patch |   46 +
 ...-Add-support-for-the-VEC-Video-Encoder-IP.patch |  730 ++++++++
 ...71-drm-vc4-Set-up-SCALER_DISPCTRL-at-boot.patch |   58 +
 ...-support-for-feeding-DSI-encoders-from-th.patch |  113 ++
 .../patches-4.9/0173-drm-vc4-Add-DSI-driver.patch  | 1817 ++++++++++++++++++++
 ...-dts-bcm283x-Add-VEC-node-in-bcm283x.dtsi.patch |   31 +
 ...283x-Enable-the-VEC-IP-on-all-RaspberryPi.patch |   26 +
 ...Disable-VEC-unless-vc4-kms-v3d-is-present.patch |   37 +
 ...ame-the-primary-and-cursor-planes-in-fkms.patch |   24 +
 ...-DRM_DEBUG_ATOMIC-for-the-insides-of-fkms.patch |   69 +
 ...-sending-of-page-flip-completion-events-i.patch |   42 +
 ...fill-user-BO-creation-requests-from-the-k.patch |   53 +
 ...-OOPSes-from-trying-to-cache-a-partially-.patch |   34 +
 ...ify-at-boot-that-CMA-doesn-t-cross-a-256M.patch |   79 +
 ...70X_DT-Add-SMSC-ethernet-controller-to-DT.patch |   57 +
 ...2835-Mark-used-PLLs-and-dividers-CRITICAL.patch |   28 +
 ...186-clk-bcm2835-Add-claim-clocks-property.patch |  133 ++
 ...e-bcm2835-Fix-cyclic-DMA-period-splitting.patch |   39 +
 .../0188-Add-ads1015-driver-to-config.patch        |   52 +
 .../0189-config-add-slcan-kernel-module.patch      |   31 +
 ...upport-for-Dion-Audio-LOCO-V2-DAC-AMP-HAT.patch |  251 +++
 ...UASH-Add-LOCO-V2-overlay-from-last-commit.patch |   62 +
 ...-support-for-Fe-Pi-audio-sound-card.-1867.patch |  333 ++++
 .../0193-Add-overlay-for-ads1115-ADCs-1864.patch   |  159 ++
 ...0194-clk-bcm2835-Correct-the-prediv-logic.patch |   27 +
 .../0195-amba_pl011-Round-input-clock-up.patch     |   86 +
 ...2-Ensure-H264-header-bytes-get-a-sensible.patch |   87 +
 ...2-Correctly-denote-key-frames-in-encoded-.patch |   24 +
 ...o-exp-Driver-for-GPIO-expander-via-mailbo.patch |  405 +++++
 .../0199-BCM270X_DT-Add-bcm2708-rpi-0-w.dts.patch  |  225 +++
 203 files changed, 8458 insertions(+), 2012 deletions(-)

diff --git a/target/linux/brcm2708/base-files/etc/diag.sh b/target/linux/brcm2708/base-files/etc/diag.sh
index 2a866e4..ecc6242 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 1619ba9..c1bed07 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 dffc368..0c9adec 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 04d0da8..e07d8cf 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 e2b3fdb..a49f9d4 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 b8b424b..a5737e3 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 <steve.glendinning at smsc.com>
 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 9d47276..fc7ac4d 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 <email at samnazarko.co.uk>
 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 dbcf303..8075dff 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 <popcornmix at gmail.com>
 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 f46579b..4b80ab0 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 <phil at raspberrypi.org>
 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 376d6a8..b271d26 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 <eric at anholt.net>
 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 3ebcb0a..5f5bd83 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 <phil at raspberrypi.org>
 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 a25275f..56be640 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?= <noralf at tronnes.org>
 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 710e73a..9c7515f 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?= <noralf at tronnes.org>
 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 be8e903..447f1ce 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 <phil at raspberrypi.org>
 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 978d675..319eafb 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 <notro at tronnes.org>
 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 67cc420..b29aa8d 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 <phil at raspberrypi.org>
 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 e16f89a..d2b764f 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 <phil at raspberrypi.org>
 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 bac0573..4eb4923 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 <phil at raspberrypi.org>
 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 9b8e869..62145a2 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 <phil at raspberrypi.org>
 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 3ec3537..5d4062c 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 <phil at raspberrypi.org>
 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 4143498..08577fc 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 <phil at raspberrypi.org>
 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 1311ccb..cd14dcc 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?= <noralf at tronnes.org>
 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 e3bde68..e800713 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?= <noralf at tronnes.org>
 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 deb271c..37eb154 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 <popcornmix at gmail.com>
 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 94862f5..dfa312b 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 <eric at anholt.net>
 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 8c197fc..4992165 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 <phil at raspberrypi.org>
 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 160c576..392ce70 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?= <noralf at tronnes.org>
 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 dee1fed..d29517e 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 <popcornmix at gmail.com>
 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 120f25d..90c0a0e 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 <popcornmix at gmail.com>
 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 d4f4fec..9b2a613 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 <kernel at martin.sperl.org>
 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 1fb2184..97309da 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 <popcornmix at gmail.com>
 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 16d32cc..0f5afac 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 <phil at raspberrypi.org>
 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 4eecc14..c193ef9 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 <rtie at gmx.de>
 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 81d48b7..20e5419 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 <popcornmix at gmail.com>
 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 971581a..0610d03 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 <popcornmix at gmail.com>
 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 a306868..b7c05c1 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 <popcornmix at gmail.com>
 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 d21f187..a2f4551 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 <florian.meier at koalo.de>
 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 00920a6..70fb8f3 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 <gellert at raspberrypi.org>
 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 c6ceef0..c4597ec 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 <phil at raspberrypi.org>
 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 100c8b1..d84a0fe 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 <phil at raspberrypi.org>
 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 87b62dc..50bad76 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 <popcornmix at gmail.com>
 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 c951b6f..58b45de 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 <popcornmix at gmail.com>
 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 fbfddde..6a22bdf 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 <popcornmix at gmail.com>
 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 d7bce81..ff1cfad 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 <tgover at broadcom.com>
 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 66949f5..618cb9f 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 <luke at raspberrypi.org>
 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 7a05db4..3d75e70 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 <wren6991 at gmail.com>
 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 312a294..69f68c7 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 <kernel at martin.sperl.org>
 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 dee3c1d..ec6010a 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 <wren6991 at gmail.com>
 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 ea529b8..0cbc1c4 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 <aron at aron.ws>
 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 8929ee2..7c5691c 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 <popcornmix at gmail.com>
 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 fa826cb..ff6084f 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 <popcornmix at gmail.com>
 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 acb199d..b86fb40 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 <popcornmix at gmail.com>
 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 cd62abe..c37c0f6 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?= <noralf at tronnes.org>
 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 3e47d68..ecaf614 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?= <noralf at tronnes.org>
 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 2e77160..e6baeab 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 <vincent.sanders at collabora.co.uk>
 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 6feda0e..7ae4edd 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 <phil at raspberrypi.org>
 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 5fdf024..ed4b270 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 <phil at raspberrypi.org>
 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 6767122..d9d1fa9 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 <notro at tronnes.org>
 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 50a0ed7..725ac70 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 <phil at raspberrypi.org>
 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 44414e5..3434690 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 <siarhei.siamashka at gmail.com>
 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 f0e7392..8d6337a 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 <fgenfb at yahoo.com>
 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 5c3e064..408ac04 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 <popcornmix at gmail.com>
 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 ec376d4..a9906f3 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 <popcornmix at gmail.com>
 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 a2eca8a..73c9ede 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 <popcornmix at gmail.com>
 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 e9f3419..444c64e 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 <popcornmix at gmail.com>
 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 3d98c22..43ed3fa 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 <gordon at raspberrypi.org>
 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 2d92f77..a7ce64b 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 <popcornmix at gmail.com>
 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 3a86d97..5d73a28 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 <phil at raspberrypi.org>
 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 77079e0..b5ae3f9 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 <pelwell at users.noreply.github.com>
 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 22f8654..107ed28 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 <florian.meier at koalo.de>
 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 0353820..26ae5b3 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 <florian.meier at koalo.de>
 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 7accb99..1be734b 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 <info at crazy-audio.com>
 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 d9dc426..5f8477c 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 <info at crazy-audio.com>
 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 483fc6e..08bf856 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 <gordon at iqaudio.com>
 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 51d731a..edfb9f5 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 <popcornmix at gmail.com>
 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 daccc7c..21d30af 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 <info at crazy-audio.com>
 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 fb823d2..9826be5 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 <info at crazy-audio.com>
 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 4123987..0000000
--- 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 <popcornmix at gmail.com>
-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 <basti.eickhoff at googlemail.com>
-- *		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 <linux/module.h>
--#include <linux/platform_device.h>
--
--#include <sound/core.h>
--#include <sound/pcm.h>
--#include <sound/pcm_params.h>
--#include <sound/soc.h>
--#include <sound/jack.h>
--
--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 <basti.eickhoff at googlemail.com>");
--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 <basti.eickhoff at googlemail.com>
-- *		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 <linux/module.h>
--#include <linux/moduleparam.h>
--#include <linux/init.h>
--#include <linux/delay.h>
--#include <linux/pm.h>
--#include <linux/i2c.h>
--#include <linux/of_device.h>
--#include <linux/spi/spi.h>
--#include <linux/regmap.h>
--#include <linux/regulator/consumer.h>
--#include <linux/slab.h>
--#include <sound/core.h>
--#include <sound/pcm.h>
--#include <sound/pcm_params.h>
--#include <sound/soc.h>
--#include <sound/initval.h>
--#include <sound/tlv.h>
--
--#include <linux/kernel.h>
--#include <linux/string.h>
--#include <linux/fs.h>
--#include <asm/uaccess.h>
--
--#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 <basti.eickhoff at googlemail.com>");
--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 <basti.eickhoff at googlemail.com>
-- *              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/0075-Update-ds1307-driver-for-device-tree-support.patch b/target/linux/brcm2708/patches-4.9/0074-Update-ds1307-driver-for-device-tree-support.patch
similarity index 91%
rename from target/linux/brcm2708/patches-4.9/0075-Update-ds1307-driver-for-device-tree-support.patch
rename to target/linux/brcm2708/patches-4.9/0074-Update-ds1307-driver-for-device-tree-support.patch
index 1dfed15..d4f7e76 100644
--- a/target/linux/brcm2708/patches-4.9/0075-Update-ds1307-driver-for-device-tree-support.patch
+++ b/target/linux/brcm2708/patches-4.9/0074-Update-ds1307-driver-for-device-tree-support.patch
@@ -1,4 +1,4 @@
-From 682c095597876ff7d669f92dc2a0f1f49526444c Mon Sep 17 00:00:00 2001
+From b3ff56f28a9531048812a51ded7c16a952d1ead4 Mon Sep 17 00:00:00 2001
 From: Ryan Coe <bluemrp9 at gmail.com>
 Date: Sat, 31 Jan 2015 18:25:49 -0700
 Subject: [PATCH] Update ds1307 driver for device-tree support
diff --git a/target/linux/brcm2708/patches-4.9/0076-Add-driver-for-rpi-proto.patch b/target/linux/brcm2708/patches-4.9/0075-Add-driver-for-rpi-proto.patch
similarity index 95%
rename from target/linux/brcm2708/patches-4.9/0076-Add-driver-for-rpi-proto.patch
rename to target/linux/brcm2708/patches-4.9/0075-Add-driver-for-rpi-proto.patch
index b23ff22..b8db1d5 100644
--- a/target/linux/brcm2708/patches-4.9/0076-Add-driver-for-rpi-proto.patch
+++ b/target/linux/brcm2708/patches-4.9/0075-Add-driver-for-rpi-proto.patch
@@ -1,4 +1,4 @@
-From 001f8b8dc231bf3e20fd6802e2664788891ed8c4 Mon Sep 17 00:00:00 2001
+From b351d2ffe294c9d5e8cde9caa3a94017ecec81d9 Mon Sep 17 00:00:00 2001
 From: Waldemar Brodkorb <wbrodkorb at conet.de>
 Date: Wed, 25 Mar 2015 09:26:17 +0100
 Subject: [PATCH] Add driver for rpi-proto
@@ -22,7 +22,7 @@ Signed-off-by: Waldemar Brodkorb <wbrodkorb at conet.de>
 
 --- a/sound/soc/bcm/Kconfig
 +++ b/sound/soc/bcm/Kconfig
-@@ -45,6 +45,13 @@ config SND_BCM2708_SOC_RPI_DAC
+@@ -52,6 +52,13 @@ config SND_BCM2708_SOC_RPI_DAC
          help
           Say Y or M if you want to add support for RPi-DAC.
  
@@ -38,14 +38,15 @@ Signed-off-by: Waldemar Brodkorb <wbrodkorb at conet.de>
  	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_
+@@ -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_DAC) += snd-soc-hifiberry-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
diff --git a/target/linux/brcm2708/patches-4.9/0077-RaspiDAC3-support.patch b/target/linux/brcm2708/patches-4.9/0076-RaspiDAC3-support.patch
similarity index 95%
rename from target/linux/brcm2708/patches-4.9/0077-RaspiDAC3-support.patch
rename to target/linux/brcm2708/patches-4.9/0076-RaspiDAC3-support.patch
index 32bc86a..de68bbf 100644
--- a/target/linux/brcm2708/patches-4.9/0077-RaspiDAC3-support.patch
+++ b/target/linux/brcm2708/patches-4.9/0076-RaspiDAC3-support.patch
@@ -1,4 +1,4 @@
-From 26084a968083e88298416426576dbd4c006e5dea Mon Sep 17 00:00:00 2001
+From b545537294ffc7e21fcc5e0c78ea8ac20c9ecd3f Mon Sep 17 00:00:00 2001
 From: Jan Grulich <jan at grulich.eu>
 Date: Mon, 24 Aug 2015 16:03:47 +0100
 Subject: [PATCH] RaspiDAC3 support
@@ -20,7 +20,7 @@ Signed-off-by: Matthias Reichl <hias at horus.com>
 
 --- a/sound/soc/bcm/Kconfig
 +++ b/sound/soc/bcm/Kconfig
-@@ -58,3 +58,11 @@ config SND_BCM2708_SOC_IQAUDIO_DAC
+@@ -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.
@@ -34,15 +34,15 @@ Signed-off-by: Matthias Reichl <hias at horus.com>
 +	  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
+@@ -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
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
-@@ -22,3 +23,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D
+@@ -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
diff --git a/target/linux/brcm2708/patches-4.9/0078-Add-Support-for-JustBoom-Audio-boards.patch b/target/linux/brcm2708/patches-4.9/0077-Add-Support-for-JustBoom-Audio-boards.patch
similarity index 98%
rename from target/linux/brcm2708/patches-4.9/0078-Add-Support-for-JustBoom-Audio-boards.patch
rename to target/linux/brcm2708/patches-4.9/0077-Add-Support-for-JustBoom-Audio-boards.patch
index 95bf9a5..9654587 100644
--- a/target/linux/brcm2708/patches-4.9/0078-Add-Support-for-JustBoom-Audio-boards.patch
+++ b/target/linux/brcm2708/patches-4.9/0077-Add-Support-for-JustBoom-Audio-boards.patch
@@ -1,4 +1,4 @@
-From 16e3f935b10cbd118056806ebd3afe6eed4c0183 Mon Sep 17 00:00:00 2001
+From 4a8ebf575ea143c14fd815ecd1f5398b6a6aee67 Mon Sep 17 00:00:00 2001
 From: Aaron Shaw <shawaj at gmail.com>
 Date: Thu, 7 Apr 2016 21:26:21 +0100
 Subject: [PATCH] Add Support for JustBoom Audio boards
@@ -20,7 +20,7 @@ Signed-off-by: Phil Elwell <phil at raspberrypi.org>
 
 --- a/sound/soc/bcm/Kconfig
 +++ b/sound/soc/bcm/Kconfig
-@@ -52,6 +52,20 @@ config SND_BCM2708_SOC_RPI_PROTO
+@@ -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).
  
@@ -43,7 +43,7 @@ Signed-off-by: Phil Elwell <phil at raspberrypi.org>
  	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-
+@@ -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
@@ -52,7 +52,7 @@ Signed-off-by: Phil Elwell <phil at raspberrypi.org>
  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
+@@ -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
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/0078-ARM-adau1977-adc-Add-basic-machine-driver-for-adau19.patch
similarity index 94%
rename from target/linux/brcm2708/patches-4.9/0079-ARM-adau1977-adc-Add-basic-machine-driver-for-adau19.patch
rename to target/linux/brcm2708/patches-4.9/0078-ARM-adau1977-adc-Add-basic-machine-driver-for-adau19.patch
index 54d659f..1b87b13 100644
--- 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/0078-ARM-adau1977-adc-Add-basic-machine-driver-for-adau19.patch
@@ -1,4 +1,4 @@
-From 55bbfc45096c8046134a2062acb2dd0806f48250 Mon Sep 17 00:00:00 2001
+From 9bbd8a3c8378eac9e605e0f37f4005583e122527 Mon Sep 17 00:00:00 2001
 From: Andrey Grodzovsky <andrey2805 at gmail.com>
 Date: Tue, 3 May 2016 22:10:59 -0400
 Subject: [PATCH] ARM: adau1977-adc: Add basic machine driver for adau1977
@@ -18,7 +18,7 @@ Signed-off-by: Andrey Grodzovsky <andrey2805 at gmail.com>
 
 --- a/sound/soc/bcm/Kconfig
 +++ b/sound/soc/bcm/Kconfig
-@@ -80,3 +80,10 @@ config SND_BCM2708_SOC_RASPIDAC3
+@@ -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.
@@ -36,17 +36,17 @@ Signed-off-by: Andrey Grodzovsky <andrey2805 at gmail.com>
  
  # 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
-@@ -19,6 +20,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o
+@@ -20,6 +21,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o
  snd-soc-iqaudio-dac-objs := iqaudio-dac.o
  snd-soc-raspidac3-objs := raspidac3.o
  
 +obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o
  obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o
  obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o
 --- /dev/null
 +++ b/sound/soc/bcm/adau1977-adc.c
 @@ -0,0 +1,125 @@
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/0079-New-AudioInjector.net-Pi-soundcard-with-low-jitter-a.patch
similarity index 96%
rename from target/linux/brcm2708/patches-4.9/0080-New-AudioInjector.net-Pi-soundcard-with-low-jitter-a.patch
rename to target/linux/brcm2708/patches-4.9/0079-New-AudioInjector.net-Pi-soundcard-with-low-jitter-a.patch
index 207cc66..71d4fef 100644
--- 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/0079-New-AudioInjector.net-Pi-soundcard-with-low-jitter-a.patch
@@ -1,4 +1,4 @@
-From 14502b0564fc2e7181857de254a6f6bd07db4038 Mon Sep 17 00:00:00 2001
+From 235989cb582a29be0bea6a7e306f7b839789053c Mon Sep 17 00:00:00 2001
 From: Matt Flax <flatmax at flatmax.org>
 Date: Mon, 16 May 2016 21:36:31 +1000
 Subject: [PATCH] New AudioInjector.net Pi soundcard with low jitter audio in
@@ -21,7 +21,7 @@ This patch adds headphone and microphone capability to the Audio Injector sound
 
 --- a/sound/soc/bcm/Kconfig
 +++ b/sound/soc/bcm/Kconfig
-@@ -87,3 +87,10 @@ config SND_BCM2708_SOC_ADAU1977_ADC
+@@ -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.
@@ -34,15 +34,15 @@ This patch adds headphone and microphone capability to the Audio Injector sound
 +	  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
+@@ -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_DAC) += snd-soc-hifiberry-dac.o
-@@ -30,3 +31,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) +=
+ 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
diff --git a/target/linux/brcm2708/patches-4.9/0081-Add-IQAudIO-Digi-WM8804-board-support.patch b/target/linux/brcm2708/patches-4.9/0080-Add-IQAudIO-Digi-WM8804-board-support.patch
similarity index 97%
rename from target/linux/brcm2708/patches-4.9/0081-Add-IQAudIO-Digi-WM8804-board-support.patch
rename to target/linux/brcm2708/patches-4.9/0080-Add-IQAudIO-Digi-WM8804-board-support.patch
index e931c99..f6a23f9 100644
--- a/target/linux/brcm2708/patches-4.9/0081-Add-IQAudIO-Digi-WM8804-board-support.patch
+++ b/target/linux/brcm2708/patches-4.9/0080-Add-IQAudIO-Digi-WM8804-board-support.patch
@@ -1,4 +1,4 @@
-From 1b18f3be9f034c2e9aefab9b97c5100d5f914a89 Mon Sep 17 00:00:00 2001
+From 5d70e6012f390d6292ea8017cebb947a003fce00 Mon Sep 17 00:00:00 2001
 From: DigitalDreamtime <clive.messer at digitaldreamtime.co.uk>
 Date: Thu, 30 Jun 2016 18:38:42 +0100
 Subject: [PATCH] Add IQAudIO Digi WM8804 board support
@@ -19,7 +19,7 @@ Signed-off-by: DigitalDreamtime <clive.messer at digitaldreamtime.co.uk>
 
 --- a/sound/soc/bcm/Kconfig
 +++ b/sound/soc/bcm/Kconfig
-@@ -73,6 +73,13 @@ config SND_BCM2708_SOC_IQAUDIO_DAC
+@@ -80,6 +80,13 @@ config SND_BCM2708_SOC_IQAUDIO_DAC
  	help
  	  Say Y or M if you want to add support for IQaudIO-DAC.
  
@@ -35,7 +35,7 @@ Signed-off-by: DigitalDreamtime <clive.messer at digitaldreamtime.co.uk>
  	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
+@@ -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
@@ -43,7 +43,7 @@ Signed-off-by: DigitalDreamtime <clive.messer at digitaldreamtime.co.uk>
  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
+@@ -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
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/0081-New-driver-for-RRA-DigiDAC1-soundcard-using-WM8741-W.patch
similarity index 97%
rename from target/linux/brcm2708/patches-4.9/0082-New-driver-for-RRA-DigiDAC1-soundcard-using-WM8741-W.patch
rename to target/linux/brcm2708/patches-4.9/0081-New-driver-for-RRA-DigiDAC1-soundcard-using-WM8741-W.patch
index 55d32df..45a5a37 100644
--- 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/0081-New-driver-for-RRA-DigiDAC1-soundcard-using-WM8741-W.patch
@@ -1,4 +1,4 @@
-From 6daac5c03a5a96f6ae711e90d46e3d5de3ba1298 Mon Sep 17 00:00:00 2001
+From e5d85d533e7ea8fd5c68d4601ff2b8034bc4aaa9 Mon Sep 17 00:00:00 2001
 From: escalator2015 <jmtasende at gmail.com>
 Date: Tue, 24 May 2016 16:20:09 +0100
 Subject: [PATCH] New driver for RRA DigiDAC1 soundcard using WM8741 + WM8804
@@ -12,7 +12,7 @@ Subject: [PATCH] New driver for RRA DigiDAC1 soundcard using WM8741 + WM8804
 
 --- a/sound/soc/bcm/Kconfig
 +++ b/sound/soc/bcm/Kconfig
-@@ -101,3 +101,11 @@ config SND_AUDIOINJECTOR_PI_SOUNDCARD
+@@ -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
@@ -26,15 +26,15 @@ Subject: [PATCH] New driver for RRA DigiDAC1 soundcard using WM8741 + WM8804
 +         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.
+@@ -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_DAC) += snd-soc-hifiberry-dac.o
-@@ -34,4 +35,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC
+ 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
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/0082-Add-support-for-Dion-Audio-LOCO-DAC-AMP-HAT.patch
similarity index 94%
rename from target/linux/brcm2708/patches-4.9/0083-Add-support-for-Dion-Audio-LOCO-DAC-AMP-HAT.patch
rename to target/linux/brcm2708/patches-4.9/0082-Add-support-for-Dion-Audio-LOCO-DAC-AMP-HAT.patch
index 39366ab..b06cd35 100644
--- 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/0082-Add-support-for-Dion-Audio-LOCO-DAC-AMP-HAT.patch
@@ -1,4 +1,4 @@
-From ce97723802a6e68483111819f29d777e0ff0b975 Mon Sep 17 00:00:00 2001
+From 999d3e615247d1921d245f7084194efbc697bb66 Mon Sep 17 00:00:00 2001
 From: DigitalDreamtime <clive.messer at digitaldreamtime.co.uk>
 Date: Sat, 2 Jul 2016 16:26:19 +0100
 Subject: [PATCH] Add support for Dion Audio LOCO DAC-AMP HAT
@@ -15,7 +15,7 @@ Signed-off-by: DigitalDreamtime <clive.messer at digitaldreamtime.co.uk>
 
 --- a/sound/soc/bcm/Kconfig
 +++ b/sound/soc/bcm/Kconfig
-@@ -109,3 +109,10 @@ config SND_DIGIDAC1_SOUNDCARD
+@@ -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.
@@ -28,15 +28,15 @@ Signed-off-by: DigitalDreamtime <clive.messer at digitaldreamtime.co.uk>
 +	  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
+@@ -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_DAC) += snd-soc-hifiberry-dac.o
-@@ -36,4 +37,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIG
+ 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
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/0083-Allo-Piano-DAC-boards-Initial-2-channel-stereo-suppo.patch
similarity index 95%
rename from target/linux/brcm2708/patches-4.9/0084-Allo-Piano-DAC-boards-Initial-2-channel-stereo-suppo.patch
rename to target/linux/brcm2708/patches-4.9/0083-Allo-Piano-DAC-boards-Initial-2-channel-stereo-suppo.patch
index 7455fa9..64e785d 100644
--- 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/0083-Allo-Piano-DAC-boards-Initial-2-channel-stereo-suppo.patch
@@ -1,4 +1,4 @@
-From 203501a533e71e5f76f9e06c0f0b8bfb0fc27147 Mon Sep 17 00:00:00 2001
+From 779409817cf1af2c38055af64c11e026cb0bb4e9 Mon Sep 17 00:00:00 2001
 From: Clive Messer <clive.m.messer at gmail.com>
 Date: Mon, 19 Sep 2016 14:01:04 +0100
 Subject: [PATCH] Allo Piano DAC boards: Initial 2 channel (stereo) support
@@ -27,7 +27,7 @@ Tested-by: Clive Messer <clive.messer at digitaldreamtime.co.uk>
 
 --- a/sound/soc/bcm/Kconfig
 +++ b/sound/soc/bcm/Kconfig
-@@ -116,3 +116,10 @@ config SND_BCM2708_SOC_DIONAUDIO_LOCO
+@@ -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.
@@ -40,15 +40,15 @@ Tested-by: Clive Messer <clive.messer at digitaldreamtime.co.uk>
 +	  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
+@@ -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_DAC) += snd-soc-hifiberry-dac.o
-@@ -38,3 +39,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3)
+ 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
diff --git a/target/linux/brcm2708/patches-4.9/0085-Support-for-Blokas-Labs-pisound-board.patch b/target/linux/brcm2708/patches-4.9/0084-Support-for-Blokas-Labs-pisound-board.patch
similarity index 98%
rename from target/linux/brcm2708/patches-4.9/0085-Support-for-Blokas-Labs-pisound-board.patch
rename to target/linux/brcm2708/patches-4.9/0084-Support-for-Blokas-Labs-pisound-board.patch
index 51d5733..21f4334 100644
--- a/target/linux/brcm2708/patches-4.9/0085-Support-for-Blokas-Labs-pisound-board.patch
+++ b/target/linux/brcm2708/patches-4.9/0084-Support-for-Blokas-Labs-pisound-board.patch
@@ -1,4 +1,4 @@
-From aa46aa94c5ca5683fd815c57a78ea5fb05e7c3e5 Mon Sep 17 00:00:00 2001
+From 7d8efd6f3198fd3dafe5a74003616a2aea5dc6c5 Mon Sep 17 00:00:00 2001
 From: gtrainavicius <gtrainavicius at users.noreply.github.com>
 Date: Sun, 23 Oct 2016 12:06:53 +0300
 Subject: [PATCH] Support for Blokas Labs pisound board
@@ -149,7 +149,7 @@ Print a logline when the kernel module is removed.
  };
 --- a/sound/soc/bcm/Kconfig
 +++ b/sound/soc/bcm/Kconfig
-@@ -123,3 +123,9 @@ config SND_BCM2708_SOC_ALLO_PIANO_DAC
+@@ -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.
@@ -161,15 +161,15 @@ Print a logline when the kernel module is removed.
 +	  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
+@@ -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_DAC) += snd-soc-hifiberry-dac.o
-@@ -40,3 +41,4 @@ obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDC
+ 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
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/0085-rpi_display-add-backlight-driver-and-overlay.patch
similarity index 98%
rename from target/linux/brcm2708/patches-4.9/0086-rpi_display-add-backlight-driver-and-overlay.patch
rename to target/linux/brcm2708/patches-4.9/0085-rpi_display-add-backlight-driver-and-overlay.patch
index 4706e7a..67c0e3f 100644
--- a/target/linux/brcm2708/patches-4.9/0086-rpi_display-add-backlight-driver-and-overlay.patch
+++ b/target/linux/brcm2708/patches-4.9/0085-rpi_display-add-backlight-driver-and-overlay.patch
@@ -1,4 +1,4 @@
-From 42d919a6d8c63ca32dd6caee1288d58319e0e22e Mon Sep 17 00:00:00 2001
+From ae5ae9278768c3d096910705bfa9af85da20a8cf Mon Sep 17 00:00:00 2001
 From: P33M <P33M at github.com>
 Date: Wed, 21 Oct 2015 14:55:21 +0100
 Subject: [PATCH] rpi_display: add backlight driver and overlay
diff --git a/target/linux/brcm2708/patches-4.9/0087-bcm2835-virtgpio-Virtual-GPIO-driver.patch b/target/linux/brcm2708/patches-4.9/0086-bcm2835-virtgpio-Virtual-GPIO-driver.patch
similarity index 99%
rename from target/linux/brcm2708/patches-4.9/0087-bcm2835-virtgpio-Virtual-GPIO-driver.patch
rename to target/linux/brcm2708/patches-4.9/0086-bcm2835-virtgpio-Virtual-GPIO-driver.patch
index ce523e2..425224e 100644
--- a/target/linux/brcm2708/patches-4.9/0087-bcm2835-virtgpio-Virtual-GPIO-driver.patch
+++ b/target/linux/brcm2708/patches-4.9/0086-bcm2835-virtgpio-Virtual-GPIO-driver.patch
@@ -1,4 +1,4 @@
-From 1b4e68b09ba226afac9414b11f89d3b833236e13 Mon Sep 17 00:00:00 2001
+From 1b6bee75a64ca43404e6bc8ff2fdbe8b1d0a0423 Mon Sep 17 00:00:00 2001
 From: popcornmix <popcornmix at gmail.com>
 Date: Tue, 23 Feb 2016 19:56:04 +0000
 Subject: [PATCH] bcm2835-virtgpio: Virtual GPIO driver
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/0087-amba_pl011-Don-t-use-DT-aliases-for-numbering.patch
similarity index 94%
rename from target/linux/brcm2708/patches-4.9/0088-amba_pl011-Don-t-use-DT-aliases-for-numbering.patch
rename to target/linux/brcm2708/patches-4.9/0087-amba_pl011-Don-t-use-DT-aliases-for-numbering.patch
index 1f69465..40963de8 100644
--- 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/0087-amba_pl011-Don-t-use-DT-aliases-for-numbering.patch
@@ -1,4 +1,4 @@
-From 0c3101c247b410c7e73dbb3ede7d0031fb622044 Mon Sep 17 00:00:00 2001
+From b34475b447c7e97fa9c4a854849f6e856fe59931 Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil at raspberrypi.org>
 Date: Tue, 23 Feb 2016 17:26:48 +0000
 Subject: [PATCH] amba_pl011: Don't use DT aliases for numbering
diff --git a/target/linux/brcm2708/patches-4.9/0091-OF-DT-Overlay-configfs-interface.patch b/target/linux/brcm2708/patches-4.9/0090-OF-DT-Overlay-configfs-interface.patch
similarity index 99%
rename from target/linux/brcm2708/patches-4.9/0091-OF-DT-Overlay-configfs-interface.patch
rename to target/linux/brcm2708/patches-4.9/0090-OF-DT-Overlay-configfs-interface.patch
index c864eba..941047a 100644
--- a/target/linux/brcm2708/patches-4.9/0091-OF-DT-Overlay-configfs-interface.patch
+++ b/target/linux/brcm2708/patches-4.9/0090-OF-DT-Overlay-configfs-interface.patch
@@ -1,4 +1,4 @@
-From af8af738c62584683c75cbcbbd80ac4425c8986c Mon Sep 17 00:00:00 2001
+From ef4a8376af32bb6722e1ea933a9e1a83ebc8f175 Mon Sep 17 00:00:00 2001
 From: Pantelis Antoniou <pantelis.antoniou at konsulko.com>
 Date: Wed, 3 Dec 2014 13:23:28 +0200
 Subject: [PATCH] OF: DT-Overlay configfs interface
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/0092-hci_h5-Don-t-send-conf_req-when-ACTIVE.patch
similarity index 92%
rename from target/linux/brcm2708/patches-4.9/0093-hci_h5-Don-t-send-conf_req-when-ACTIVE.patch
rename to target/linux/brcm2708/patches-4.9/0092-hci_h5-Don-t-send-conf_req-when-ACTIVE.patch
index 0ebf29c..780a211 100644
--- 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/0092-hci_h5-Don-t-send-conf_req-when-ACTIVE.patch
@@ -1,4 +1,4 @@
-From 63e3b21d72b4542cd0f7527bbc7dc0aef13eb16d Mon Sep 17 00:00:00 2001
+From 0224b0469a7f5c2ee6420aac66e89e3206029633 Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil at raspberrypi.org>
 Date: Thu, 17 Dec 2015 13:37:07 +0000
 Subject: [PATCH] hci_h5: Don't send conf_req when ACTIVE
diff --git a/target/linux/brcm2708/patches-4.9/0094-config-Add-default-configs.patch b/target/linux/brcm2708/patches-4.9/0093-config-Add-default-configs.patch
similarity index 99%
rename from target/linux/brcm2708/patches-4.9/0094-config-Add-default-configs.patch
rename to target/linux/brcm2708/patches-4.9/0093-config-Add-default-configs.patch
index c940298..da92f04 100644
--- a/target/linux/brcm2708/patches-4.9/0094-config-Add-default-configs.patch
+++ b/target/linux/brcm2708/patches-4.9/0093-config-Add-default-configs.patch
@@ -1,4 +1,4 @@
-From dcfe6cf60a2f84f321f64267f09f8a0f19b7a609 Mon Sep 17 00:00:00 2001
+From 9455097dbb0c961edb6a47b451e18a985f5d9a3f Mon Sep 17 00:00:00 2001
 From: popcornmix <popcornmix at gmail.com>
 Date: Mon, 13 Apr 2015 17:16:29 +0100
 Subject: [PATCH] config: Add default configs
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/0094-Add-arm64-configuration-and-device-tree-differences.patch
similarity index 99%
rename from target/linux/brcm2708/patches-4.9/0095-Add-arm64-configuration-and-device-tree-differences.patch
rename to target/linux/brcm2708/patches-4.9/0094-Add-arm64-configuration-and-device-tree-differences.patch
index 9c76d38..0cbb4d7 100644
--- a/target/linux/brcm2708/patches-4.9/0095-Add-arm64-configuration-and-device-tree-differences.patch
+++ b/target/linux/brcm2708/patches-4.9/0094-Add-arm64-configuration-and-device-tree-differences.patch
@@ -1,4 +1,4 @@
-From 24273c675c44f730b89416a40fac0aa35df6cfe0 Mon Sep 17 00:00:00 2001
+From 64d1c392baa391243d0a7963379ab957d5d9b8b1 Mon Sep 17 00:00:00 2001
 From: Michael Zoran <mzoran at crowfest.net>
 Date: Wed, 24 Aug 2016 03:35:56 -0700
 Subject: [PATCH] Add arm64 configuration and device tree differences. Disable
diff --git a/target/linux/brcm2708/patches-4.9/0096-vchiq_arm-Tweak-the-logging-output.patch b/target/linux/brcm2708/patches-4.9/0095-vchiq_arm-Tweak-the-logging-output.patch
similarity index 96%
rename from target/linux/brcm2708/patches-4.9/0096-vchiq_arm-Tweak-the-logging-output.patch
rename to target/linux/brcm2708/patches-4.9/0095-vchiq_arm-Tweak-the-logging-output.patch
index 294689b..ef3c97d 100644
--- a/target/linux/brcm2708/patches-4.9/0096-vchiq_arm-Tweak-the-logging-output.patch
+++ b/target/linux/brcm2708/patches-4.9/0095-vchiq_arm-Tweak-the-logging-output.patch
@@ -1,4 +1,4 @@
-From c5a316c09e241260f6131e0dc968209b053fcd56 Mon Sep 17 00:00:00 2001
+From 60486e8778192830c0e5369d4f05954c1f7cc12c Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil at raspberrypi.org>
 Date: Mon, 7 Mar 2016 15:05:11 +0000
 Subject: [PATCH] vchiq_arm: Tweak the logging output
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/0096-vchiq_arm-Access-the-dequeue_pending-flag-locked.patch
similarity index 96%
rename from target/linux/brcm2708/patches-4.9/0097-vchiq_arm-Access-the-dequeue_pending-flag-locked.patch
rename to target/linux/brcm2708/patches-4.9/0096-vchiq_arm-Access-the-dequeue_pending-flag-locked.patch
index fef600b..71c0e30 100644
--- a/target/linux/brcm2708/patches-4.9/0097-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
@@ -1,4 +1,4 @@
-From c451a1169c71ef984e367a81d619a7089dfb14e0 Mon Sep 17 00:00:00 2001
+From 64e39b18b8d51eb332a84ef79ed3ce0dd2a76808 Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil at raspberrypi.org>
 Date: Wed, 23 Mar 2016 14:16:25 +0000
 Subject: [PATCH] vchiq_arm: Access the dequeue_pending flag locked
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/0097-vchiq_arm-Service-callbacks-must-not-fail.patch
similarity index 93%
rename from target/linux/brcm2708/patches-4.9/0098-vchiq_arm-Service-callbacks-must-not-fail.patch
rename to target/linux/brcm2708/patches-4.9/0097-vchiq_arm-Service-callbacks-must-not-fail.patch
index 1f30478..f60af85 100644
--- a/target/linux/brcm2708/patches-4.9/0098-vchiq_arm-Service-callbacks-must-not-fail.patch
+++ b/target/linux/brcm2708/patches-4.9/0097-vchiq_arm-Service-callbacks-must-not-fail.patch
@@ -1,4 +1,4 @@
-From db2437c557a5095022610b672c066aa2c16a684d Mon Sep 17 00:00:00 2001
+From e518e4dcd42f5a9e3b32a3a54c258320c4752d7e Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil at raspberrypi.org>
 Date: Wed, 23 Mar 2016 20:53:47 +0000
 Subject: [PATCH] vchiq_arm: Service callbacks must not fail
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/0098-vchiq_arm-Add-completion-records-under-the-mutex.patch
similarity index 97%
rename from target/linux/brcm2708/patches-4.9/0099-vchiq_arm-Add-completion-records-under-the-mutex.patch
rename to target/linux/brcm2708/patches-4.9/0098-vchiq_arm-Add-completion-records-under-the-mutex.patch
index ea1731b..1b8647e 100644
--- a/target/linux/brcm2708/patches-4.9/0099-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
@@ -1,4 +1,4 @@
-From ed2a687b8fc8cd8c1154a9ae7c9fdb2e03176ed0 Mon Sep 17 00:00:00 2001
+From 152fc9447942bad4e2c6c1e6b86fd252689cc596 Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil at raspberrypi.org>
 Date: Thu, 21 Apr 2016 13:49:32 +0100
 Subject: [PATCH] vchiq_arm: Add completion records under the mutex
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/0099-vchiq_arm-Avoid-use-of-mutex-in-add_completion.patch
similarity index 98%
rename from target/linux/brcm2708/patches-4.9/0100-vchiq_arm-Avoid-use-of-mutex-in-add_completion.patch
rename to target/linux/brcm2708/patches-4.9/0099-vchiq_arm-Avoid-use-of-mutex-in-add_completion.patch
index 55d2f68..c8cc5b7 100644
--- 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/0099-vchiq_arm-Avoid-use-of-mutex-in-add_completion.patch
@@ -1,4 +1,4 @@
-From 59d2abf4834befa2d2ef8e8a37ab896df4a04868 Mon Sep 17 00:00:00 2001
+From 965475a1620ba1c4f19d6585925a40e3c749d7d1 Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil at raspberrypi.org>
 Date: Mon, 20 Jun 2016 13:51:44 +0100
 Subject: [PATCH] vchiq_arm: Avoid use of mutex in add_completion
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/0100-staging-vchi-Convert-to-current-get_user_pages-argum.patch
similarity index 95%
rename from target/linux/brcm2708/patches-4.9/0101-staging-vchi-Convert-to-current-get_user_pages-argum.patch
rename to target/linux/brcm2708/patches-4.9/0100-staging-vchi-Convert-to-current-get_user_pages-argum.patch
index e5d9528..e80c414 100644
--- 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/0100-staging-vchi-Convert-to-current-get_user_pages-argum.patch
@@ -1,4 +1,4 @@
-From d2a51ea3b1f32cd7e53e20dbcd59aea48f09b1a6 Mon Sep 17 00:00:00 2001
+From ec643be82b145a65d9c78d24eea7470b9bb6e0c4 Mon Sep 17 00:00:00 2001
 From: Eric Anholt <eric at anholt.net>
 Date: Mon, 3 Oct 2016 10:14:10 -0700
 Subject: [PATCH] staging/vchi: Convert to current get_user_pages() arguments.
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/0101-staging-vchi-Update-for-rename-of-page_cache_release.patch
similarity index 95%
rename from target/linux/brcm2708/patches-4.9/0102-staging-vchi-Update-for-rename-of-page_cache_release.patch
rename to target/linux/brcm2708/patches-4.9/0101-staging-vchi-Update-for-rename-of-page_cache_release.patch
index 4be551f..eccb792 100644
--- 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/0101-staging-vchi-Update-for-rename-of-page_cache_release.patch
@@ -1,4 +1,4 @@
-From d47b4b7130260ada73a3520d43ca2df2032dc526 Mon Sep 17 00:00:00 2001
+From 5e8386a65d2b7fd157d2a6e2f9b8ca79011976b7 Mon Sep 17 00:00:00 2001
 From: Eric Anholt <eric at anholt.net>
 Date: Mon, 3 Oct 2016 10:16:03 -0700
 Subject: [PATCH] staging/vchi: Update for rename of page_cache_release() to
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/0102-drivers-vchi-Remove-dependency-on-CONFIG_BROKEN.patch
similarity index 90%
rename from target/linux/brcm2708/patches-4.9/0103-drivers-vchi-Remove-dependency-on-CONFIG_BROKEN.patch
rename to target/linux/brcm2708/patches-4.9/0102-drivers-vchi-Remove-dependency-on-CONFIG_BROKEN.patch
index 52fd44a..8ec807e 100644
--- a/target/linux/brcm2708/patches-4.9/0103-drivers-vchi-Remove-dependency-on-CONFIG_BROKEN.patch
+++ b/target/linux/brcm2708/patches-4.9/0102-drivers-vchi-Remove-dependency-on-CONFIG_BROKEN.patch
@@ -1,4 +1,4 @@
-From b5282b49812b3f0ec18f2b998f6070b9af34edf6 Mon Sep 17 00:00:00 2001
+From b909c0f36c535e3f3042517d1b59b9c0538cc1d0 Mon Sep 17 00:00:00 2001
 From: Eric Anholt <eric at anholt.net>
 Date: Mon, 3 Oct 2016 10:21:17 -0700
 Subject: [PATCH] drivers/vchi: Remove dependency on CONFIG_BROKEN.
diff --git a/target/linux/brcm2708/patches-4.9/0104-raspberrypi-firmware-Export-the-general-transaction-.patch b/target/linux/brcm2708/patches-4.9/0103-raspberrypi-firmware-Export-the-general-transaction-.patch
similarity index 95%
rename from target/linux/brcm2708/patches-4.9/0104-raspberrypi-firmware-Export-the-general-transaction-.patch
rename to target/linux/brcm2708/patches-4.9/0103-raspberrypi-firmware-Export-the-general-transaction-.patch
index 5dc6f85..a316b40 100644
--- a/target/linux/brcm2708/patches-4.9/0104-raspberrypi-firmware-Export-the-general-transaction-.patch
+++ b/target/linux/brcm2708/patches-4.9/0103-raspberrypi-firmware-Export-the-general-transaction-.patch
@@ -1,4 +1,4 @@
-From 207c380da679f31a62a1bb604dd22834d902acaf Mon Sep 17 00:00:00 2001
+From 34454ca8cf9b63b0973fb23271810461a45a9884 Mon Sep 17 00:00:00 2001
 From: Eric Anholt <eric at anholt.net>
 Date: Wed, 14 Sep 2016 09:16:19 +0100
 Subject: [PATCH] raspberrypi-firmware: Export the general transaction
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/0104-raspberrypi-firmware-Define-the-MBOX-channel-in-the-.patch
similarity index 89%
rename from target/linux/brcm2708/patches-4.9/0105-raspberrypi-firmware-Define-the-MBOX-channel-in-the-.patch
rename to target/linux/brcm2708/patches-4.9/0104-raspberrypi-firmware-Define-the-MBOX-channel-in-the-.patch
index 0909929..0b9ef71 100644
--- a/target/linux/brcm2708/patches-4.9/0105-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
@@ -1,4 +1,4 @@
-From f918546b8d35b4051d79245027037492e15a7efe Mon Sep 17 00:00:00 2001
+From bf20c77c459b00873d5862cfe7ba745a543d53de Mon Sep 17 00:00:00 2001
 From: Eric Anholt <eric at anholt.net>
 Date: Wed, 14 Sep 2016 09:18:09 +0100
 Subject: [PATCH] raspberrypi-firmware: Define the MBOX channel in the header.
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/0105-drm-vc4-Add-a-mode-for-using-the-closed-firmware-for.patch
similarity index 99%
rename from target/linux/brcm2708/patches-4.9/0106-drm-vc4-Add-a-mode-for-using-the-closed-firmware-for.patch
rename to target/linux/brcm2708/patches-4.9/0105-drm-vc4-Add-a-mode-for-using-the-closed-firmware-for.patch
index 3d1e684..88952dc 100644
--- 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/0105-drm-vc4-Add-a-mode-for-using-the-closed-firmware-for.patch
@@ -1,4 +1,4 @@
-From 12d493c17841adf193361623a64cd85804dea94f Mon Sep 17 00:00:00 2001
+From ffd9952ec22321af8e891aa4cf9d79d90c4b23b6 Mon Sep 17 00:00:00 2001
 From: Eric Anholt <eric at anholt.net>
 Date: Wed, 14 Sep 2016 08:39:33 +0100
 Subject: [PATCH] drm/vc4: Add a mode for using the closed firmware for
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/0106-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch
similarity index 97%
rename from target/linux/brcm2708/patches-4.9/0107-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch
rename to target/linux/brcm2708/patches-4.9/0106-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch
index 7692a92..899c75e 100644
--- 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/0106-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch
@@ -1,4 +1,4 @@
-From b302b7c9025334ef6680955a906cee579bf3c85c Mon Sep 17 00:00:00 2001
+From 89b466914a0d49f08d00be25556ba22497b9a284 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf at tronnes.org>
 Date: Sat, 17 Sep 2016 15:07:10 +0200
 Subject: [PATCH] i2c: bcm2835: Fix hang for writing messages larger than 16
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/0107-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch
similarity index 98%
rename from target/linux/brcm2708/patches-4.9/0108-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch
rename to target/linux/brcm2708/patches-4.9/0107-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch
index 0a616ff..6646d77 100644
--- a/target/linux/brcm2708/patches-4.9/0108-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
@@ -1,4 +1,4 @@
-From 95729fe299cca5ef749f4b6a2c3e0f40ec7b43b9 Mon Sep 17 00:00:00 2001
+From 8feb8081c74d15ce368baa42981ca98e77800c03 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf at tronnes.org>
 Date: Fri, 23 Sep 2016 18:24:38 +0200
 Subject: [PATCH] i2c: bcm2835: Protect against unexpected TXW/RXR interrupts
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/0108-i2c-bcm2835-Use-dev_dbg-logging-on-transfer-errors.patch
similarity index 95%
rename from target/linux/brcm2708/patches-4.9/0109-i2c-bcm2835-Use-dev_dbg-logging-on-transfer-errors.patch
rename to target/linux/brcm2708/patches-4.9/0108-i2c-bcm2835-Use-dev_dbg-logging-on-transfer-errors.patch
index b8cbe10..acc2ade 100644
--- 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/0108-i2c-bcm2835-Use-dev_dbg-logging-on-transfer-errors.patch
@@ -1,4 +1,4 @@
-From 3e9e15ec9e56874764fdaa43b2af8008469b87b2 Mon Sep 17 00:00:00 2001
+From bff25210b88dc7b71ee9c2626e42a939072dec64 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf at tronnes.org>
 Date: Mon, 19 Sep 2016 17:19:41 +0200
 Subject: [PATCH] i2c: bcm2835: Use dev_dbg logging on transfer errors
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/0109-i2c-bcm2835-Can-t-support-I2C_M_IGNORE_NAK.patch
similarity index 95%
rename from target/linux/brcm2708/patches-4.9/0110-i2c-bcm2835-Can-t-support-I2C_M_IGNORE_NAK.patch
rename to target/linux/brcm2708/patches-4.9/0109-i2c-bcm2835-Can-t-support-I2C_M_IGNORE_NAK.patch
index 946c316..a913c50 100644
--- 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/0109-i2c-bcm2835-Can-t-support-I2C_M_IGNORE_NAK.patch
@@ -1,4 +1,4 @@
-From 9d8c576116c4818dd745ff112504f0fdf78c9e1e Mon Sep 17 00:00:00 2001
+From 40c63177d4c0f4755a148503c3b8bb2192ce8c0e Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf at tronnes.org>
 Date: Thu, 22 Sep 2016 22:05:50 +0200
 Subject: [PATCH] i2c: bcm2835: Can't support I2C_M_IGNORE_NAK
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/0110-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch
similarity index 98%
rename from target/linux/brcm2708/patches-4.9/0111-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch
rename to target/linux/brcm2708/patches-4.9/0110-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch
index a481aaf..0cd5aa4 100644
--- a/target/linux/brcm2708/patches-4.9/0111-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
@@ -1,4 +1,4 @@
-From 1099ac9cbf927e62883b363cfe3d33db105ff3dc Mon Sep 17 00:00:00 2001
+From db656eb11aebb0d7e4b833f9b452503ddb1351f1 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf at tronnes.org>
 Date: Fri, 23 Sep 2016 04:54:27 +0200
 Subject: [PATCH] i2c: bcm2835: Add support for Repeated Start Condition
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/0111-i2c-bcm2835-Support-i2c-dev-ioctl-I2C_TIMEOUT.patch
similarity index 94%
rename from target/linux/brcm2708/patches-4.9/0112-i2c-bcm2835-Support-i2c-dev-ioctl-I2C_TIMEOUT.patch
rename to target/linux/brcm2708/patches-4.9/0111-i2c-bcm2835-Support-i2c-dev-ioctl-I2C_TIMEOUT.patch
index ef70b97..07016d9 100644
--- a/target/linux/brcm2708/patches-4.9/0112-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
@@ -1,4 +1,4 @@
-From d42e4206e0e273b195881614a317688830fc56a2 Mon Sep 17 00:00:00 2001
+From 0c2744e901150b27a60bded1acb058ce26709d5a Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf at tronnes.org>
 Date: Fri, 23 Sep 2016 04:57:17 +0200
 Subject: [PATCH] i2c: bcm2835: Support i2c-dev ioctl I2C_TIMEOUT
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/0112-i2c-bcm2835-Add-support-for-dynamic-clock.patch
similarity index 98%
rename from target/linux/brcm2708/patches-4.9/0113-i2c-bcm2835-Add-support-for-dynamic-clock.patch
rename to target/linux/brcm2708/patches-4.9/0112-i2c-bcm2835-Add-support-for-dynamic-clock.patch
index 35ab56c..afe2b22 100644
--- a/target/linux/brcm2708/patches-4.9/0113-i2c-bcm2835-Add-support-for-dynamic-clock.patch
+++ b/target/linux/brcm2708/patches-4.9/0112-i2c-bcm2835-Add-support-for-dynamic-clock.patch
@@ -1,4 +1,4 @@
-From 788daf43a9078fc592eddfa0b959bc92b03bbb53 Mon Sep 17 00:00:00 2001
+From ce8663f1f101f8c7b9037c31269b0b31373737ad Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf at tronnes.org>
 Date: Tue, 27 Sep 2016 01:00:08 +0200
 Subject: [PATCH] i2c: bcm2835: Add support for dynamic clock
diff --git a/target/linux/brcm2708/patches-4.9/0114-i2c-bcm2835-Add-debug-support.patch b/target/linux/brcm2708/patches-4.9/0113-i2c-bcm2835-Add-debug-support.patch
similarity index 98%
rename from target/linux/brcm2708/patches-4.9/0114-i2c-bcm2835-Add-debug-support.patch
rename to target/linux/brcm2708/patches-4.9/0113-i2c-bcm2835-Add-debug-support.patch
index 3083067..f69a48f 100644
--- a/target/linux/brcm2708/patches-4.9/0114-i2c-bcm2835-Add-debug-support.patch
+++ b/target/linux/brcm2708/patches-4.9/0113-i2c-bcm2835-Add-debug-support.patch
@@ -1,4 +1,4 @@
-From 133b068ffc08e2c1a0c9d5fa781107e3d95ba9bc Mon Sep 17 00:00:00 2001
+From 98629f09f3ceb7f2a559b48b4a70028485583f5e Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf at tronnes.org>
 Date: Tue, 1 Nov 2016 15:15:41 +0100
 Subject: [PATCH] i2c: bcm2835: Add debug support
diff --git a/target/linux/brcm2708/patches-4.9/0115-arm64-Add-CONFIG_ARCH_BCM2835.patch b/target/linux/brcm2708/patches-4.9/0114-arm64-Add-CONFIG_ARCH_BCM2835.patch
similarity index 87%
rename from target/linux/brcm2708/patches-4.9/0115-arm64-Add-CONFIG_ARCH_BCM2835.patch
rename to target/linux/brcm2708/patches-4.9/0114-arm64-Add-CONFIG_ARCH_BCM2835.patch
index 2f84052..34ab47e 100644
--- a/target/linux/brcm2708/patches-4.9/0115-arm64-Add-CONFIG_ARCH_BCM2835.patch
+++ b/target/linux/brcm2708/patches-4.9/0114-arm64-Add-CONFIG_ARCH_BCM2835.patch
@@ -1,4 +1,4 @@
-From fbf6217ff64c7bf6fac6eafd07f23d8c2356b088 Mon Sep 17 00:00:00 2001
+From c3dc479ae9620756f981ad2c5afeee92295f8ea3 Mon Sep 17 00:00:00 2001
 From: popcornmix <popcornmix at gmail.com>
 Date: Sat, 31 Dec 2016 14:15:50 +0000
 Subject: [PATCH] arm64: Add CONFIG_ARCH_BCM2835
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/0115-Add-support-for-Silicon-Labs-Si7013-20-21-humidity-t.patch
similarity index 97%
rename from target/linux/brcm2708/patches-4.9/0116-Add-support-for-Silicon-Labs-Si7013-20-21-humidity-t.patch
rename to target/linux/brcm2708/patches-4.9/0115-Add-support-for-Silicon-Labs-Si7013-20-21-humidity-t.patch
index 8ab8207..119b054 100644
--- 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/0115-Add-support-for-Silicon-Labs-Si7013-20-21-humidity-t.patch
@@ -1,4 +1,4 @@
-From d7a7355799204dc94d323d8e58ff6d2d3296e764 Mon Sep 17 00:00:00 2001
+From 69d0de7d07ec016f2956237ec141bb62ff7ae36c Mon Sep 17 00:00:00 2001
 From: Alex Tucker <alex at floop.org.uk>
 Date: Tue, 13 Dec 2016 19:50:18 +0000
 Subject: [PATCH] Add support for Silicon Labs Si7013/20/21
diff --git a/target/linux/brcm2708/patches-4.9/0117-Document-the-si7020-option.patch b/target/linux/brcm2708/patches-4.9/0116-Document-the-si7020-option.patch
similarity index 91%
rename from target/linux/brcm2708/patches-4.9/0117-Document-the-si7020-option.patch
rename to target/linux/brcm2708/patches-4.9/0116-Document-the-si7020-option.patch
index 67b72c9..0319ca4 100644
--- a/target/linux/brcm2708/patches-4.9/0117-Document-the-si7020-option.patch
+++ b/target/linux/brcm2708/patches-4.9/0116-Document-the-si7020-option.patch
@@ -1,4 +1,4 @@
-From e6be13c337640f69fc71dcf6b6dd741dc5664f85 Mon Sep 17 00:00:00 2001
+From ed753b7389b8c65af0b4266c001ef0343fb1c30e Mon Sep 17 00:00:00 2001
 From: Phil Elwell <pelwell at users.noreply.github.com>
 Date: Tue, 3 Jan 2017 21:27:46 +0000
 Subject: [PATCH] Document the si7020 option
diff --git a/target/linux/brcm2708/patches-4.9/0118-pisound-improvements.patch b/target/linux/brcm2708/patches-4.9/0117-pisound-improvements.patch
similarity index 99%
rename from target/linux/brcm2708/patches-4.9/0118-pisound-improvements.patch
rename to target/linux/brcm2708/patches-4.9/0117-pisound-improvements.patch
index af5c3b3..f914bfc 100644
--- a/target/linux/brcm2708/patches-4.9/0118-pisound-improvements.patch
+++ b/target/linux/brcm2708/patches-4.9/0117-pisound-improvements.patch
@@ -1,4 +1,4 @@
-From 811d783519254a955ccb7a43b1d8d3f2d29a9a79 Mon Sep 17 00:00:00 2001
+From 8ed8e29b19dba95a7a6c2364c2bb32d926601713 Mon Sep 17 00:00:00 2001
 From: Giedrius Trainavicius <giedrius at blokas.io>
 Date: Thu, 5 Jan 2017 02:38:16 +0200
 Subject: [PATCH] pisound improvements:
diff --git a/target/linux/brcm2708/patches-4.9/0122-Add-driver_name-property.patch b/target/linux/brcm2708/patches-4.9/0118-Add-driver_name-property.patch
similarity index 91%
rename from target/linux/brcm2708/patches-4.9/0122-Add-driver_name-property.patch
rename to target/linux/brcm2708/patches-4.9/0118-Add-driver_name-property.patch
index 4acafa5..bfda58a 100644
--- a/target/linux/brcm2708/patches-4.9/0122-Add-driver_name-property.patch
+++ b/target/linux/brcm2708/patches-4.9/0118-Add-driver_name-property.patch
@@ -1,4 +1,4 @@
-From 6e7ad272d08767455aef658066b981f513ad0cec Mon Sep 17 00:00:00 2001
+From 341bc67d361def1f23a96c512ab6bc39f32b3601 Mon Sep 17 00:00:00 2001
 From: Aaron Shaw <shawaj at gmail.com>
 Date: Tue, 10 Jan 2017 16:05:41 +0000
 Subject: [PATCH] Add driver_name property
diff --git a/target/linux/brcm2708/patches-4.9/0123-Add-driver_name-paramater.patch b/target/linux/brcm2708/patches-4.9/0119-Add-driver_name-paramater.patch
similarity index 91%
rename from target/linux/brcm2708/patches-4.9/0123-Add-driver_name-paramater.patch
rename to target/linux/brcm2708/patches-4.9/0119-Add-driver_name-paramater.patch
index c85bb44..2a3a6d8 100644
--- a/target/linux/brcm2708/patches-4.9/0123-Add-driver_name-paramater.patch
+++ b/target/linux/brcm2708/patches-4.9/0119-Add-driver_name-paramater.patch
@@ -1,4 +1,4 @@
-From d9f58694b229b6f7e8b03c718ef80ac7082213d1 Mon Sep 17 00:00:00 2001
+From d87b665c7e4c09bf713ef6f45ceb11a8aacbcf5e Mon Sep 17 00:00:00 2001
 From: Aaron Shaw <shawaj at gmail.com>
 Date: Tue, 10 Jan 2017 16:11:04 +0000
 Subject: [PATCH] Add driver_name paramater
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 d57bfe1..0000000
--- 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 <phil at raspberrypi.org>
-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 <basti.eickhoff at googlemail.com>
-+ *		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 <linux/module.h>
-+#include <linux/platform_device.h>
-+
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/jack.h>
-+
-+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 <basti.eickhoff at googlemail.com>");
-+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 <basti.eickhoff at googlemail.com>
-+ *		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 <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/i2c.h>
-+#include <linux/of_device.h>
-+#include <linux/spi/spi.h>
-+#include <linux/regmap.h>
-+#include <linux/regulator/consumer.h>
-+#include <linux/slab.h>
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/initval.h>
-+#include <sound/tlv.h>
-+
-+#include <linux/kernel.h>
-+#include <linux/string.h>
-+#include <linux/fs.h>
-+#include <asm/uaccess.h>
-+
-+#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 <basti.eickhoff at googlemail.com>");
-+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 <basti.eickhoff at googlemail.com>
-+ *              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/0124-BCM270X_DT-Add-pi3-disable-wifi-overlay.patch b/target/linux/brcm2708/patches-4.9/0120-BCM270X_DT-Add-pi3-disable-wifi-overlay.patch
similarity index 96%
rename from target/linux/brcm2708/patches-4.9/0124-BCM270X_DT-Add-pi3-disable-wifi-overlay.patch
rename to target/linux/brcm2708/patches-4.9/0120-BCM270X_DT-Add-pi3-disable-wifi-overlay.patch
index 473876b..4bc80be 100644
--- a/target/linux/brcm2708/patches-4.9/0124-BCM270X_DT-Add-pi3-disable-wifi-overlay.patch
+++ b/target/linux/brcm2708/patches-4.9/0120-BCM270X_DT-Add-pi3-disable-wifi-overlay.patch
@@ -1,4 +1,4 @@
-From 11e7774ca60d3e6e9063ecfb497f15aa808f7ca2 Mon Sep 17 00:00:00 2001
+From b76839857c9b553f52f8d14cf54a22579b362db9 Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil at raspberrypi.org>
 Date: Wed, 11 Jan 2017 13:01:21 +0000
 Subject: [PATCH] BCM270X_DT: Add pi3-disable-wifi overlay
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 0de8da0..0000000
--- 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 <phil at raspberrypi.org>
-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/0125-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
similarity index 99%
rename from target/linux/brcm2708/patches-4.9/0125-ARM64-Make-it-work-again-on-4.9-1790.patch
rename to target/linux/brcm2708/patches-4.9/0121-ARM64-Make-it-work-again-on-4.9-1790.patch
index a60080c..96b298d 100644
--- 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/0121-ARM64-Make-it-work-again-on-4.9-1790.patch
@@ -1,4 +1,4 @@
-From d6fbb7bbbe2fcc6b348ba0cfc3523d7f8f18a619 Mon Sep 17 00:00:00 2001
+From fe3c34c6196cfc708a515e44dd432da0e6cc0aba Mon Sep 17 00:00:00 2001
 From: Electron752 <mzoran at crowfest.net>
 Date: Thu, 12 Jan 2017 07:07:08 -0800
 Subject: [PATCH] ARM64: Make it work again on 4.9 (#1790)
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 0cc0f88..0000000
--- 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 <giedrius at blokas.io>
-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 <giedrius at blokas.io>
----
- 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/0126-ARM64-Enable-Kernel-Address-Space-Randomization-1792.patch b/target/linux/brcm2708/patches-4.9/0122-ARM64-Enable-Kernel-Address-Space-Randomization-1792.patch
similarity index 94%
rename from target/linux/brcm2708/patches-4.9/0126-ARM64-Enable-Kernel-Address-Space-Randomization-1792.patch
rename to target/linux/brcm2708/patches-4.9/0122-ARM64-Enable-Kernel-Address-Space-Randomization-1792.patch
index dff27b9..423db95 100644
--- a/target/linux/brcm2708/patches-4.9/0126-ARM64-Enable-Kernel-Address-Space-Randomization-1792.patch
+++ b/target/linux/brcm2708/patches-4.9/0122-ARM64-Enable-Kernel-Address-Space-Randomization-1792.patch
@@ -1,4 +1,4 @@
-From 8930b9b96484e1fd68438c78e44b8ef7cb2d61ac Mon Sep 17 00:00:00 2001
+From 6dfa60daaa0966a8e414ab0a7fd002a99001920a Mon Sep 17 00:00:00 2001
 From: Electron752 <mzoran at crowfest.net>
 Date: Sat, 14 Jan 2017 02:54:26 -0800
 Subject: [PATCH] ARM64: Enable Kernel Address Space Randomization (#1792)
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/0124-ARM64-Enable-RTL8187-RTL8192CU-wifi-in-build-config.patch
similarity index 91%
rename from target/linux/brcm2708/patches-4.9/0128-ARM64-Enable-RTL8187-RTL8192CU-wifi-in-build-config.patch
rename to target/linux/brcm2708/patches-4.9/0124-ARM64-Enable-RTL8187-RTL8192CU-wifi-in-build-config.patch
index a309394..c947a74 100644
--- a/target/linux/brcm2708/patches-4.9/0128-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
@@ -1,4 +1,4 @@
-From 0d1eefab92dbaca44fa241df4bbf234212782d43 Mon Sep 17 00:00:00 2001
+From 564df2de35a212639eb7e357442f35fa89bcbde4 Mon Sep 17 00:00:00 2001
 From: Michael Zoran <mzoran at crowfest.net>
 Date: Sun, 15 Jan 2017 07:31:59 -0800
 Subject: [PATCH] ARM64: Enable RTL8187/RTL8192CU wifi in build config
diff --git a/target/linux/brcm2708/patches-4.9/0129-BCM270X_DT-Add-spi0-cs-overlay.patch b/target/linux/brcm2708/patches-4.9/0125-BCM270X_DT-Add-spi0-cs-overlay.patch
similarity index 97%
rename from target/linux/brcm2708/patches-4.9/0129-BCM270X_DT-Add-spi0-cs-overlay.patch
rename to target/linux/brcm2708/patches-4.9/0125-BCM270X_DT-Add-spi0-cs-overlay.patch
index e90767a..2fd8366 100644
--- a/target/linux/brcm2708/patches-4.9/0129-BCM270X_DT-Add-spi0-cs-overlay.patch
+++ b/target/linux/brcm2708/patches-4.9/0125-BCM270X_DT-Add-spi0-cs-overlay.patch
@@ -1,4 +1,4 @@
-From efdb964748f093780166ef56fa7873067d35074e Mon Sep 17 00:00:00 2001
+From 48eea36959fb8d854b4cf1ee4284646be5a279e0 Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil at raspberrypi.org>
 Date: Mon, 16 Jan 2017 14:53:12 +0000
 Subject: [PATCH] BCM270X_DT: Add spi0-cs overlay
diff --git a/target/linux/brcm2708/patches-4.9/0130-spi-bcm2835-Disable-forced-software-CS.patch b/target/linux/brcm2708/patches-4.9/0126-spi-bcm2835-Disable-forced-software-CS.patch
similarity index 91%
rename from target/linux/brcm2708/patches-4.9/0130-spi-bcm2835-Disable-forced-software-CS.patch
rename to target/linux/brcm2708/patches-4.9/0126-spi-bcm2835-Disable-forced-software-CS.patch
index b4ade04..544ccf6 100644
--- a/target/linux/brcm2708/patches-4.9/0130-spi-bcm2835-Disable-forced-software-CS.patch
+++ b/target/linux/brcm2708/patches-4.9/0126-spi-bcm2835-Disable-forced-software-CS.patch
@@ -1,4 +1,4 @@
-From 2248b18b5d21d0ce59bb874a8e20e53a39317eb0 Mon Sep 17 00:00:00 2001
+From a6ef8db0e46713da43c81bc15fed01a4da0bd5a4 Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil at raspberrypi.org>
 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/0131-config-Add-CONFIG_TCP_CONG_BBR.patch b/target/linux/brcm2708/patches-4.9/0127-config-Add-CONFIG_TCP_CONG_BBR.patch
similarity index 93%
rename from target/linux/brcm2708/patches-4.9/0131-config-Add-CONFIG_TCP_CONG_BBR.patch
rename to target/linux/brcm2708/patches-4.9/0127-config-Add-CONFIG_TCP_CONG_BBR.patch
index f0076ce..cec560e 100644
--- a/target/linux/brcm2708/patches-4.9/0131-config-Add-CONFIG_TCP_CONG_BBR.patch
+++ b/target/linux/brcm2708/patches-4.9/0127-config-Add-CONFIG_TCP_CONG_BBR.patch
@@ -1,4 +1,4 @@
-From 7342a6ab0f9d60cc65a2a585ac43d3aa114f7e61 Mon Sep 17 00:00:00 2001
+From 6f95da255ded5f1da673f826de07963e6a619e3d Mon Sep 17 00:00:00 2001
 From: popcornmix <popcornmix at gmail.com>
 Date: Mon, 16 Jan 2017 16:33:54 +0000
 Subject: [PATCH] config: Add CONFIG_TCP_CONG_BBR See:
diff --git a/target/linux/brcm2708/patches-4.9/0133-BCM270X_DT-Enable-UART0-on-CM3.patch b/target/linux/brcm2708/patches-4.9/0128-BCM270X_DT-Enable-UART0-on-CM3.patch
similarity index 89%
rename from target/linux/brcm2708/patches-4.9/0133-BCM270X_DT-Enable-UART0-on-CM3.patch
rename to target/linux/brcm2708/patches-4.9/0128-BCM270X_DT-Enable-UART0-on-CM3.patch
index c2ba65f..4fbc443 100644
--- a/target/linux/brcm2708/patches-4.9/0133-BCM270X_DT-Enable-UART0-on-CM3.patch
+++ b/target/linux/brcm2708/patches-4.9/0128-BCM270X_DT-Enable-UART0-on-CM3.patch
@@ -1,4 +1,4 @@
-From 074d3a044fc1d3bc54c3728ae4ae045ef432a1d2 Mon Sep 17 00:00:00 2001
+From 44586947e86f67ad71fdd3afca51f04fc27f3872 Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil at raspberrypi.org>
 Date: Tue, 17 Jan 2017 11:34:58 +0000
 Subject: [PATCH] BCM270X_DT: Enable UART0 on CM3
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/0129-config-Add-CONFIG_MD_M25P80-and-CONFIG_MD_SPI_NOR.patch
similarity index 93%
rename from target/linux/brcm2708/patches-4.9/0134-config-Add-CONFIG_MD_M25P80-and-CONFIG_MD_SPI_NOR.patch
rename to target/linux/brcm2708/patches-4.9/0129-config-Add-CONFIG_MD_M25P80-and-CONFIG_MD_SPI_NOR.patch
index 3d1bb7e..ab5e409 100644
--- 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/0129-config-Add-CONFIG_MD_M25P80-and-CONFIG_MD_SPI_NOR.patch
@@ -1,4 +1,4 @@
-From 1159cc636986b9915419efa87e136279b4ba7df9 Mon Sep 17 00:00:00 2001
+From 3f6ad80c79570b157d651720bf161843a360e922 Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil at raspberrypi.org>
 Date: Tue, 17 Jan 2017 14:39:39 +0000
 Subject: [PATCH] config: Add CONFIG_MD_M25P80 and CONFIG_MD_SPI_NOR
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/0130-ARM64-DWC_OTG-Port-dwc_otg-driver-to-ARM64.patch
similarity index 99%
rename from target/linux/brcm2708/patches-4.9/0135-ARM64-DWC_OTG-Port-dwc_otg-driver-to-ARM64.patch
rename to target/linux/brcm2708/patches-4.9/0130-ARM64-DWC_OTG-Port-dwc_otg-driver-to-ARM64.patch
index 4bb85d0..a94fee4 100644
--- 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/0130-ARM64-DWC_OTG-Port-dwc_otg-driver-to-ARM64.patch
@@ -1,4 +1,4 @@
-From 2f15deb5ab0fafa71f00bcf840cd01893b829555 Mon Sep 17 00:00:00 2001
+From 99c33b6e418cefebb461fee0ad3a927a0c4127f1 Mon Sep 17 00:00:00 2001
 From: Michael Zoran <mzoran at crowfest.net>
 Date: Sat, 14 Jan 2017 21:33:51 -0800
 Subject: [PATCH] ARM64/DWC_OTG: Port dwc_otg driver to ARM64
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/0131-ARM64-Round-Robin-dispatch-IRQs-between-CPUs.patch
similarity index 96%
rename from target/linux/brcm2708/patches-4.9/0136-ARM64-Round-Robin-dispatch-IRQs-between-CPUs.patch
rename to target/linux/brcm2708/patches-4.9/0131-ARM64-Round-Robin-dispatch-IRQs-between-CPUs.patch
index 6685bbb..d11ca6b 100644
--- a/target/linux/brcm2708/patches-4.9/0136-ARM64-Round-Robin-dispatch-IRQs-between-CPUs.patch
+++ b/target/linux/brcm2708/patches-4.9/0131-ARM64-Round-Robin-dispatch-IRQs-between-CPUs.patch
@@ -1,4 +1,4 @@
-From b51f35c59a6f40f7f58ff75a2c1b414421224ec2 Mon Sep 17 00:00:00 2001
+From 3a9b48156c6681e846d1a7dbe4ecbb3ae14c2f3c Mon Sep 17 00:00:00 2001
 From: Michael Zoran <mzoran at crowfest.net>
 Date: Sat, 14 Jan 2017 21:43:57 -0800
 Subject: [PATCH] ARM64: Round-Robin dispatch IRQs between CPUs.
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/0132-ARM64-Enable-DWC_OTG-Driver-In-ARM64-Build-Config-bc.patch
similarity index 90%
rename from target/linux/brcm2708/patches-4.9/0137-ARM64-Enable-DWC_OTG-Driver-In-ARM64-Build-Config-bc.patch
rename to target/linux/brcm2708/patches-4.9/0132-ARM64-Enable-DWC_OTG-Driver-In-ARM64-Build-Config-bc.patch
index 4850c3e..deae274 100644
--- 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/0132-ARM64-Enable-DWC_OTG-Driver-In-ARM64-Build-Config-bc.patch
@@ -1,4 +1,4 @@
-From b0a66d71d5efa5ab172a2e561ef76f510f80b305 Mon Sep 17 00:00:00 2001
+From ad17c9e5a03f835605560e7163e5e685a67abd1f Mon Sep 17 00:00:00 2001
 From: Michael Zoran <mzoran at crowfest.net>
 Date: Sat, 14 Jan 2017 21:45:03 -0800
 Subject: [PATCH] ARM64: Enable DWC_OTG Driver In ARM64 Build
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 189b288..0000000
--- 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 <phil at raspberrypi.org>
-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 <phil at raspberrypi.org>
----
- 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/0138-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
similarity index 90%
rename from target/linux/brcm2708/patches-4.9/0138-ARM64-Use-dwc_otg-driver-by-default-for-USB.patch
rename to target/linux/brcm2708/patches-4.9/0133-ARM64-Use-dwc_otg-driver-by-default-for-USB.patch
index 0517099..53335b9 100644
--- 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/0133-ARM64-Use-dwc_otg-driver-by-default-for-USB.patch
@@ -1,4 +1,4 @@
-From a81b40b75f5ae0feafcbc667394494e287cfe218 Mon Sep 17 00:00:00 2001
+From 4eec6ce872ac46987efeb9b9cdab0ad78a563bdb Mon Sep 17 00:00:00 2001
 From: Michael Zoran <mzoran at crowfest.net>
 Date: Sat, 14 Jan 2017 21:46:04 -0800
 Subject: [PATCH] ARM64: Use dwc_otg driver by default for USB.
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/0134-BCM270X_DT-Add-reference-to-audio_pins-to-CM-dtb.patch
similarity index 92%
rename from target/linux/brcm2708/patches-4.9/0139-BCM270X_DT-Add-reference-to-audio_pins-to-CM-dtb.patch
rename to target/linux/brcm2708/patches-4.9/0134-BCM270X_DT-Add-reference-to-audio_pins-to-CM-dtb.patch
index ed707a1..63df4a0 100644
--- 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/0134-BCM270X_DT-Add-reference-to-audio_pins-to-CM-dtb.patch
@@ -1,4 +1,4 @@
-From 719ed1f8a1f93b2c9d855392a69493da107ae703 Mon Sep 17 00:00:00 2001
+From 8630b0b3fea31138c52ef83848ae1a047baa3855 Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil at raspberrypi.org>
 Date: Mon, 23 Jan 2017 17:36:50 +0000
 Subject: [PATCH] BCM270X_DT: Add reference to audio_pins to CM dtb
diff --git a/target/linux/brcm2708/patches-4.9/0140-config-Add-additional-network-scheduling-modules.patch b/target/linux/brcm2708/patches-4.9/0135-config-Add-additional-network-scheduling-modules.patch
similarity index 95%
rename from target/linux/brcm2708/patches-4.9/0140-config-Add-additional-network-scheduling-modules.patch
rename to target/linux/brcm2708/patches-4.9/0135-config-Add-additional-network-scheduling-modules.patch
index 91a0019..6c50870 100644
--- a/target/linux/brcm2708/patches-4.9/0140-config-Add-additional-network-scheduling-modules.patch
+++ b/target/linux/brcm2708/patches-4.9/0135-config-Add-additional-network-scheduling-modules.patch
@@ -1,4 +1,4 @@
-From 6a4bb2c83c31f2d35397469454c3a54fbc32fce7 Mon Sep 17 00:00:00 2001
+From 56aef4ffcf12fdede0dad012de939c5a7c9cc55b Mon Sep 17 00:00:00 2001
 From: popcornmix <popcornmix at gmail.com>
 Date: Wed, 25 Jan 2017 11:30:38 +0000
 Subject: [PATCH] config: Add additional network scheduling modules
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/0136-ASoC-A-simple-card-overlay-for-ADAU7002.patch
similarity index 97%
rename from target/linux/brcm2708/patches-4.9/0141-ASoC-A-simple-card-overlay-for-ADAU7002.patch
rename to target/linux/brcm2708/patches-4.9/0136-ASoC-A-simple-card-overlay-for-ADAU7002.patch
index 99e9414..4f122fc 100644
--- a/target/linux/brcm2708/patches-4.9/0141-ASoC-A-simple-card-overlay-for-ADAU7002.patch
+++ b/target/linux/brcm2708/patches-4.9/0136-ASoC-A-simple-card-overlay-for-ADAU7002.patch
@@ -1,4 +1,4 @@
-From 05f8935c02d5f598055afc773d5bee2f2d91dff2 Mon Sep 17 00:00:00 2001
+From 1cd1f19adbe020544e18193a006af9c71c8c82ca Mon Sep 17 00:00:00 2001
 From: chris johnson <plasticchris at gmail.com>
 Date: Sun, 22 Jan 2017 03:27:31 +0000
 Subject: [PATCH] ASoC: A simple-card overlay for ADAU7002
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/0137-config-Add-SND_SOC_ADAU7002-codec-module.patch
similarity index 94%
rename from target/linux/brcm2708/patches-4.9/0142-config-Add-SND_SOC_ADAU7002-codec-module.patch
rename to target/linux/brcm2708/patches-4.9/0137-config-Add-SND_SOC_ADAU7002-codec-module.patch
index ab64295..e4ef715 100644
--- a/target/linux/brcm2708/patches-4.9/0142-config-Add-SND_SOC_ADAU7002-codec-module.patch
+++ b/target/linux/brcm2708/patches-4.9/0137-config-Add-SND_SOC_ADAU7002-codec-module.patch
@@ -1,4 +1,4 @@
-From 86a9b1e76dd131156f3fa0436ee6bac7bd51bd90 Mon Sep 17 00:00:00 2001
+From 30db626576fa53cb6a0a27311baed4dd5c296c38 Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil at raspberrypi.org>
 Date: Wed, 25 Jan 2017 21:17:23 +0000
 Subject: [PATCH] config: Add SND_SOC_ADAU7002 codec module
diff --git a/target/linux/brcm2708/patches-4.9/0143-Add-overlay-for-mcp3008-adc-1818.patch b/target/linux/brcm2708/patches-4.9/0138-Add-overlay-for-mcp3008-adc-1818.patch
similarity index 98%
rename from target/linux/brcm2708/patches-4.9/0143-Add-overlay-for-mcp3008-adc-1818.patch
rename to target/linux/brcm2708/patches-4.9/0138-Add-overlay-for-mcp3008-adc-1818.patch
index 57b3605..560dc6c 100644
--- a/target/linux/brcm2708/patches-4.9/0143-Add-overlay-for-mcp3008-adc-1818.patch
+++ b/target/linux/brcm2708/patches-4.9/0138-Add-overlay-for-mcp3008-adc-1818.patch
@@ -1,4 +1,4 @@
-From ad0138f3a91bebc14be78809d738c302f0ac311d Mon Sep 17 00:00:00 2001
+From 33800ba2a14ff23db96fe5ea6e421a731f60c52b Mon Sep 17 00:00:00 2001
 From: Scott Ellis <scott at jumpnowtek.com>
 Date: Fri, 27 Jan 2017 06:42:42 -0500
 Subject: [PATCH] Add overlay for mcp3008 adc (#1818)
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/0139-usb-dwc2-Avoid-suspending-if-we-re-in-gadget-mode-18.patch
similarity index 96%
rename from target/linux/brcm2708/patches-4.9/0144-usb-dwc2-Avoid-suspending-if-we-re-in-gadget-mode-18.patch
rename to target/linux/brcm2708/patches-4.9/0139-usb-dwc2-Avoid-suspending-if-we-re-in-gadget-mode-18.patch
index cd82d4f..1ed31c2 100644
--- 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/0139-usb-dwc2-Avoid-suspending-if-we-re-in-gadget-mode-18.patch
@@ -1,4 +1,4 @@
-From 7158cd0f806c91291c4f8e7c2e2b7e5be3023d30 Mon Sep 17 00:00:00 2001
+From 2ca9749f5b4326dad52756eaf5e7865504b4d374 Mon Sep 17 00:00:00 2001
 From: ED6E0F17 <edge at karikoa.net>
 Date: Fri, 3 Feb 2017 14:52:42 +0000
 Subject: [PATCH] usb: dwc2: Avoid suspending if we're in gadget mode (#1825)
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/0140-gpio_mem-Remove-unnecessary-dev_info-output-1830.patch
similarity index 91%
rename from target/linux/brcm2708/patches-4.9/0150-gpio_mem-Remove-unnecessary-dev_info-output-1830.patch
rename to target/linux/brcm2708/patches-4.9/0140-gpio_mem-Remove-unnecessary-dev_info-output-1830.patch
index 19d23fc..8c2d162 100644
--- a/target/linux/brcm2708/patches-4.9/0150-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
@@ -1,4 +1,4 @@
-From 6a2c90127ab305604fa51f30bce4f23179fa4b63 Mon Sep 17 00:00:00 2001
+From 5ff260778264ec512ea879cea455c86d515cc6ba Mon Sep 17 00:00:00 2001
 From: JamesH65 <JamesH65 at users.noreply.github.com>
 Date: Mon, 6 Feb 2017 15:24:47 +0000
 Subject: [PATCH] gpio_mem: Remove unnecessary dev_info output (#1830)
diff --git a/target/linux/brcm2708/patches-4.9/0145-config-Enable-regulator-support.patch b/target/linux/brcm2708/patches-4.9/0141-config-Enable-regulator-support.patch
similarity index 93%
rename from target/linux/brcm2708/patches-4.9/0145-config-Enable-regulator-support.patch
rename to target/linux/brcm2708/patches-4.9/0141-config-Enable-regulator-support.patch
index 4c8cba1..bcd766f 100644
--- a/target/linux/brcm2708/patches-4.9/0145-config-Enable-regulator-support.patch
+++ b/target/linux/brcm2708/patches-4.9/0141-config-Enable-regulator-support.patch
@@ -1,4 +1,4 @@
-From 92105f7981fd207add7a09ace4570c9cd74f8757 Mon Sep 17 00:00:00 2001
+From e36583656552b7827a1b9d513ec39e95efa7ce8d Mon Sep 17 00:00:00 2001
 From: Matthias Reichl <hias at horus.com>
 Date: Sun, 22 Jan 2017 12:49:36 +0100
 Subject: [PATCH] config: Enable regulator support
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/0142-BCM270x-DT-expose-3.3V-and-5V-system-rails.patch
similarity index 92%
rename from target/linux/brcm2708/patches-4.9/0146-BCM270x-DT-expose-3.3V-and-5V-system-rails.patch
rename to target/linux/brcm2708/patches-4.9/0142-BCM270x-DT-expose-3.3V-and-5V-system-rails.patch
index 0deaa0a..062e6e0 100644
--- 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/0142-BCM270x-DT-expose-3.3V-and-5V-system-rails.patch
@@ -1,4 +1,4 @@
-From 06b6fe1687cc560f36976cef615d38071ae07867 Mon Sep 17 00:00:00 2001
+From 3e2cb84235e904f0c127d34705852ba7893ec9ae Mon Sep 17 00:00:00 2001
 From: Matthias Reichl <hias at horus.com>
 Date: Sun, 22 Jan 2017 12:49:36 +0100
 Subject: [PATCH] BCM270x DT: expose 3.3V and 5V system rails
diff --git a/target/linux/brcm2708/patches-4.9/0147-BCM270x-DT-Consolidate-audio-card-overlays.patch b/target/linux/brcm2708/patches-4.9/0143-BCM270x-DT-Consolidate-audio-card-overlays.patch
similarity index 99%
rename from target/linux/brcm2708/patches-4.9/0147-BCM270x-DT-Consolidate-audio-card-overlays.patch
rename to target/linux/brcm2708/patches-4.9/0143-BCM270x-DT-Consolidate-audio-card-overlays.patch
index d865199..4c123b4 100644
--- a/target/linux/brcm2708/patches-4.9/0147-BCM270x-DT-Consolidate-audio-card-overlays.patch
+++ b/target/linux/brcm2708/patches-4.9/0143-BCM270x-DT-Consolidate-audio-card-overlays.patch
@@ -1,4 +1,4 @@
-From 05798b17d672768e9e2c54c0c94df2ef019afe95 Mon Sep 17 00:00:00 2001
+From f134380c19eb38bc276d6d86fa575821c3493c60 Mon Sep 17 00:00:00 2001
 From: Matthias Reichl <hias at horus.com>
 Date: Sun, 22 Jan 2017 12:49:36 +0100
 Subject: [PATCH] BCM270x DT: Consolidate audio card overlays
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/0144-ASoC-Add-driver-for-Cirrus-Logic-Audio-Card.patch
similarity index 99%
rename from target/linux/brcm2708/patches-4.9/0148-ASoC-Add-driver-for-Cirrus-Logic-Audio-Card.patch
rename to target/linux/brcm2708/patches-4.9/0144-ASoC-Add-driver-for-Cirrus-Logic-Audio-Card.patch
index 5c343ba..863d107 100644
--- a/target/linux/brcm2708/patches-4.9/0148-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
@@ -1,4 +1,4 @@
-From 8729879667d0668f20bd2aba8473879ac1d0216d Mon Sep 17 00:00:00 2001
+From 01c84e09a331a3b4c29c1cd5ce364c91577c7cea Mon Sep 17 00:00:00 2001
 From: Matthias Reichl <hias at horus.com>
 Date: Sun, 22 Jan 2017 12:49:37 +0100
 Subject: [PATCH] ASoC: Add driver for Cirrus Logic Audio Card
diff --git a/target/linux/brcm2708/patches-4.9/0149-config-enable-Cirrus-Logic-Audio-Card.patch b/target/linux/brcm2708/patches-4.9/0145-config-enable-Cirrus-Logic-Audio-Card.patch
similarity index 96%
rename from target/linux/brcm2708/patches-4.9/0149-config-enable-Cirrus-Logic-Audio-Card.patch
rename to target/linux/brcm2708/patches-4.9/0145-config-enable-Cirrus-Logic-Audio-Card.patch
index c9e4fd1..be16a47 100644
--- a/target/linux/brcm2708/patches-4.9/0149-config-enable-Cirrus-Logic-Audio-Card.patch
+++ b/target/linux/brcm2708/patches-4.9/0145-config-enable-Cirrus-Logic-Audio-Card.patch
@@ -1,4 +1,4 @@
-From e12d55ad45094a50ff25b70d76381bc7798ea3d5 Mon Sep 17 00:00:00 2001
+From e34099818448051c8fa84634534dff081540c7b7 Mon Sep 17 00:00:00 2001
 From: Matthias Reichl <hias at horus.com>
 Date: Sun, 22 Jan 2017 12:49:37 +0100
 Subject: [PATCH] config: enable Cirrus Logic Audio Card
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 0000000..db9fd39
--- /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 <phil at raspberrypi.org>
+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 <phil at raspberrypi.org>
+---
+ 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-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 0000000..0a08eb9
--- /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 <phil at raspberrypi.org>
+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 <phil at raspberrypi.org>
+---
+ 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-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 0000000..52e36b5
--- /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 <phil at raspberrypi.org>
+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 <phil at raspberrypi.org>
+---
+ 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 0000000..16d740a
--- /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 <stephen.maclagan at hotmail.com>
+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 <cat.schulze at alice-dsl.net>
+---
+ 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/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 0000000..295db59
--- /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 <M.Cerveny at computer.org>
+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/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 0000000..82f4628
--- /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 <boris.brezillon at free-electrons.com>
+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 <boris.brezillon at free-electrons.com>
+Signed-off-by: Eric Anholt <eric at anholt.net>
+Reviewed-by: Eric Anholt <eric at anholt.net>
+Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
+(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 0000000..448b037
--- /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 <boris.brezillon at free-electrons.com>
+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 <boris.brezillon at free-electrons.com>
+Reviewed-by: Eric Anholt <eric at anholt.net>
+Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
+(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 0000000..ed082ab
--- /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 <boris.brezillon at free-electrons.com>
+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 <boris.brezillon at free-electrons.com>
+Reviewed-by: Eric Anholt <eric at anholt.net>
+Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
+(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 0000000..01e2977
--- /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 <boris.brezillon at free-electrons.com>
+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 <boris.brezillon at free-electrons.com>
+Fixes: 155e8b3b0ee3 ("clk: bcm: Support rate change propagation on bcm2835 clocks")
+Reported-by: Stephen Rothwell <sfr at canb.auug.org.au>
+Reviewed-by: Eric Anholt <eric at anholt.net>
+Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
+(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 0000000..154e061
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
+(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 0000000..24e8aed
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
+(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 0000000..16c5ec5
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
+(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 <linux/clk.h>
+ #include <linux/clk/bcm2835.h>
+ #include <linux/debugfs.h>
++#include <linux/delay.h>
+ #include <linux/module.h>
+ #include <linux/of.h>
+ #include <linux/platform_device.h>
+@@ -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 0000000..027e5c0
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+---
+ 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 <linux/delay.h>
++#include <linux/err.h>
++#include <linux/fb.h>
++#include <linux/gpio.h>
++#include <linux/gpio/consumer.h>
++#include <linux/i2c.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_graph.h>
++#include <linux/pm.h>
++
++#include <drm/drm_panel.h>
++#include <drm/drmP.h>
++#include <drm/drm_crtc.h>
++#include <drm/drm_mipi_dsi.h>
++#include <drm/drm_panel.h>
++
++/* 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 <eric at anholt.net>");
++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 0000000..1ba605b
--- /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 <eric at anholt.net>
+Date: Thu, 2 Jun 2016 12:29:45 -0700
+Subject: [PATCH] BCM270X: Add the DSI panel to the defconfig.
+
+Signed-off-by: Eric Anholt <eric at anholt.net>
+---
+ 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 0000000..444c287
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+---
+ 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 at 7e104000 {
+@@ -188,6 +191,26 @@
+ 			interrupts = <2 14>; /* pwa1 */
+ 		};
+ 
++		dsi0: dsi at 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 at 0x7e215000 {
+ 			compatible = "brcm,bcm2835-aux";
+ 			#clock-cells = <1>;
+@@ -247,6 +270,26 @@
+ 			interrupts = <2 1>;
+ 		};
+ 
++		dsi1: dsi at 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 at 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 0000000..3d65f5e
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+---
+ 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 at 45 {
++				compatible = "raspberrypi,touchscreen-bridge-i2c";
++				reg = <0x45>;
++			};
++
++			pitouchscreen_touch: bridge at 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 at 16 {
++		target = <&dsi1>;
++		__overlay__  {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			status = "okay";
++
++			pitouchscreen: panel at 0 {
++				compatible = "raspberrypi,touchscreen";
++				reg = <0>;
++				raspberrypi,touchscreen-bridge = <&pitouchscreen_bridge>;
++			};
++		};
++	};
++
++	fragment at 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 0000000..3326dca
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+(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 0000000..2b81578
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+(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 0000000..f6d738d
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+(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 0000000..ea0f4f1
--- /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 <pfeiljonas at gmx.de>
+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 <pfeiljonas at gmx.de>
+Signed-off-by: Eric Anholt <eric at anholt.net>
+(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 0000000..3c66fef
--- /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 <derekf at osg.samsung.com>
+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 <derekf at osg.samsung.com>
+Signed-off-by: Eric Anholt <eric at anholt.net>
+Reviewed-by: Eric Anholt <eric at anholt.net>
+Reviewed-by: Daniel Stone <daniels at collabora.com>
+(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 0000000..c2499c1
--- /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 <boris.brezillon at free-electrons.com>
+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 <boris.brezillon at free-electrons.com>
+Signed-off-by: Eric Anholt <eric at anholt.net>
+(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 0000000..39e6f11
--- /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 <boris.brezillon at free-electrons.com>
+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 <boris.brezillon at free-electrons.com>
+Reviewed-by: Daniel Vetter <daniel.vetter at ffwll.ch>
+Signed-off-by: Eric Anholt <eric at anholt.net>
+(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 0000000..db82c0c
--- /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 <boris.brezillon at free-electrons.com>
+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 <boris.brezillon at free-electrons.com>
+Suggested-by: Daniel Vetter <daniel.vetter at ffwll.ch>
+Reviewed-by: Daniel Vetter <daniel.vetter at ffwll.ch>
+Signed-off-by: Eric Anholt <eric at anholt.net>
+(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 0000000..0b5a853
--- /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 <boris.brezillon at free-electrons.com>
+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 <boris.brezillon at free-electrons.com>
+Signed-off-by: Eric Anholt <eric at anholt.net>
+(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 <http://www.gnu.org/licenses/>.
++ */
++
++/**
++ * DOC: VC4 SDTV module
++ */
++
++#include <drm/drm_atomic_helper.h>
++#include <drm/drm_crtc_helper.h>
++#include <drm/drm_edid.h>
++#include <drm/drm_panel.h>
++#include <linux/clk.h>
++#include <linux/component.h>
++#include <linux/of_graph.h>
++#include <linux/of_platform.h>
++#include <linux/pm_runtime.h>
++
++#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 0000000..1a425ca
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+---
+ 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 0000000..15243a3
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+---
+ 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 0000000..97ae4a4
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+---
+ 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 <http://www.gnu.org/licenses/>.
++ */
++
++/**
++ * 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 0000000..a2671f2
--- /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 <boris.brezillon at free-electrons.com>
+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 <boris.brezillon at free-electrons.com>
+Signed-off-by: Eric Anholt <eric at anholt.net>
+(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 at 7e806000 {
++			compatible = "brcm,bcm2835-vec";
++			reg = <0x7e806000 0x1000>;
++			clocks = <&clocks BCM2835_CLOCK_VEC>;
++			interrupts = <2 27>;
++			status = "disabled";
++		};
++
+ 		pixelvalve at 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 0000000..8689450
--- /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 <boris.brezillon at free-electrons.com>
+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 <boris.brezillon at free-electrons.com>
+Signed-off-by: Eric Anholt <eric at anholt.net>
+(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 0000000..42c3965
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+---
+ 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 at 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 0000000..208ff58
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+---
+ 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 0000000..f3f1410
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+---
+ 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 0000000..73fbf2b
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+---
+ 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 0000000..c0967b4
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+---
+ 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 0000000..000f3a8
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+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 0000000..453d027
--- /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 <eric at anholt.net>
+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 <eric at anholt.net>
+---
+ 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 <http://www.gnu.org/licenses/>.
+  */
+ 
++#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 0000000..76b1bf3
--- /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 <phil at raspberrypi.org>
+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 <phil at raspberrypi.org>
+---
+ arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 1 +
+ arch/arm/boot/dts/bcm2708-rpi-b.dts      | 1 +
+ arch/arm/boot/dts/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 0000000..13f6c11
--- /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 <phil at raspberrypi.org>
+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 <phil at raspberrypi.org>
+---
+ 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 0000000..09dcfa7
--- /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 <phil at raspberrypi.org>
+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 <phil at raspberrypi.org>
+---
+ 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 <dt-bindings/clock/bcm2835.h>
++
+ / {
+ 	compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
+ 
+@@ -155,6 +157,18 @@
+ 		};
+ 	};
+ 
++	fragment at 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 0000000..fa0d998
--- /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 <hias at horus.com>
+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 <hias at horus.com>
+Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
+Tested-by: Clive Messer <clive.messer at digitaldreamtime.co.uk>
+Reviewed-by: Eric Anholt <eric at anholt.net>
+---
+ 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 0000000..1303bdc
--- /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 <scott at jumpnowtek.com>
+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 0000000..021eb01
--- /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 <popcornmix at gmail.com>
+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 0000000..eb6422a
--- /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 <miquelblauw at hotmail.com>
+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 <info at dionaudio.nl>
+---
+ 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: <None>
+ 
+ 
++Name:   dionaudio-loco-v2
++Info:   Configures the Dion Audio LOCO-V2 DAC-AMP
++Load:   dtoverlay=dionaudio-loco-v2,<param>=<val>
++Params: 24db_digital_gain       Allow gain to be applied via the PCM512x codec
++                                Digital volume control. Enable with
++                                "dtoverlay=hifiberry-dacplus,24db_digital_gain"
++                                (The default behaviour is that the Digital
++                                volume control is limited to a maximum of
++                                0dB. ie. it can attenuate but not provide
++                                gain. For most users, this will be desired
++                                as it will prevent clipping. By appending
++                                the 24dB_digital_gain parameter, the Digital
++                                volume control will allow up to 24dB of
++                                gain. If this parameter is enabled, it is the
++                                responsibility of the user to ensure that
++                                the Digital volume control is set to a value
++                                that does not result in clipping/distortion!)
++
++
+ 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 <info at dionaudio.nl>
++ *              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 <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/jack.h>
++
++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 <info at dionaudio.nl>");
++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 0000000..be3618a
--- /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 <phil at raspberrypi.org>
+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 at 0 {
++		target = <&sound>;
++		frag0: __overlay__ {
++			compatible = "dionaudio,dionaudio-loco-v2";
++			i2s-controller = <&i2s>;
++			status = "okay";
++		};
++	};
++
++	fragment at 1 {
++		target = <&i2s>;
++		__overlay__ {
++			status = "okay";
++		};
++	};
++
++	fragment at 2 {
++		target = <&i2c1>;
++		__overlay__ {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			status = "okay";
++
++			pcm5122 at 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 0000000..262dc14
--- /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 <fe-pi at cox.net>
+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 <fe-pi at cox.net>
+---
+ 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: <None>
++
++
+ 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 at 0 {
++		target = <&clocks>;
++		__overlay__ {
++			sgtl5000_mclk: sgtl5000_mclk {
++				compatible = "fixed-clock";
++				#clock-cells = <0>;
++				clock-frequency = <12288000>;
++				clock-output-names = "sgtl5000-mclk";
++			};
++		};
++	};
++
++	fragment at 1 {
++		target = <&soc>;
++		__overlay__ {
++			reg_1v8: reg_1v8 at 0 {
++				compatible = "regulator-fixed";
++				regulator-name = "1V8";
++				regulator-min-microvolt = <1800000>;
++				regulator-max-microvolt = <1800000>;
++				regulator-always-on;
++			};
++		};
++	};
++
++	fragment at 2 {
++		target = <&i2c1>;
++		__overlay__ {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			status = "okay";
++
++			sgtl5000 at 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 = <&reg_1v8>;
++				status = "okay";
++			};
++		};
++	};
++
++	fragment at 3 {
++		target = <&i2s>;
++		__overlay__ {
++			status = "okay";
++		};
++	};
++
++	fragment at 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 <kuupaz at gmail.com>
++ *		Copyright 2016
++ *		based on code by Florian Meier <florian.meier at koalo.de>
++ *		based on code by Shawn Guo <shawn.guo at linaro.org>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/jack.h>
++
++#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 <fe-pi at cox.net>");
++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 0000000..39d48e6
--- /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 <scott at jumpnowtek.com>
+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,<param>[=<val>]
++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,<param>=<val>
+--- /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 at 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 at 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 at 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 at 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 at 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 0000000..c81194f
--- /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 <phil at raspberrypi.org>
+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 <phil at raspberrypi.org>
+---
+ 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 0000000..2bd501d
--- /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 <phil at raspberrypi.org>
+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 <phil at raspberrypi.org>
+---
+ 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 0000000..df8d4b4
--- /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 <dave.stevenson at raspberrypi.org>
+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 <dave.stevenson at raspberrypi.org>
+---
+ 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 0000000..4b375ab
--- /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 <dave.stevenson at raspberrypi.org>
+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 <dave.stevenson at raspberrypi.org>
+---
+ 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 0000000..3d09d1d
--- /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 <dave.stevenson at raspberrypi.org>
+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 <dave.stevenson at raspberrypi.org>
+---
+ 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 <dave.stevenson at raspberrypi.org>
++ *  Based on gpio-bcm-virt.c by Dom Cobley <popcornmix at gmail.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#include <linux/err.h>
++#include <linux/gpio.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/dma-mapping.h>
++#include <soc/bcm2835/raspberrypi-firmware.h>
++
++#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 <dave.stevenson at raspberrypi.org>");
++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 0000000..c3a8751
--- /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 <phil at raspberrypi.org>
+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 <phil at raspberrypi.org>
+---
+ 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 at 0{
++		compatible = "spidev";
++		reg = <0>;	/* CE0 */
++		#address-cells = <1>;
++		#size-cells = <0>;
++		spi-max-frequency = <500000>;
++	};
++
++	spidev1: spidev at 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";
++	};
++};



More information about the lede-commits mailing list