aboutsummaryrefslogtreecommitdiffstats
path: root/main/linux-rpi
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2016-06-02 11:00:57 +0000
committerTimo Teräs <timo.teras@iki.fi>2016-06-02 11:01:51 +0000
commitbd87780d5cca8b28eb53f39a3c12abc29fc5148a (patch)
treeba33111ed76fbac8c03650fd98a986a4dfc7760d /main/linux-rpi
parent526628d341e39ea0ba9de83e9e19d00d4921aebf (diff)
downloadaports-bd87780d5cca8b28eb53f39a3c12abc29fc5148a.tar.bz2
aports-bd87780d5cca8b28eb53f39a3c12abc29fc5148a.tar.xz
main/linux-rpi: upgrade to 4.4.12
Diffstat (limited to 'main/linux-rpi')
-rw-r--r--main/linux-rpi/APKBUILD26
-rw-r--r--main/linux-rpi/rpi-cirrus-4.4.y-20160514.patch1534
2 files changed, 13 insertions, 1547 deletions
diff --git a/main/linux-rpi/APKBUILD b/main/linux-rpi/APKBUILD
index a6b4696ec8..9fccd274a8 100644
--- a/main/linux-rpi/APKBUILD
+++ b/main/linux-rpi/APKBUILD
@@ -1,12 +1,12 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=linux-rpi
-pkgver=4.4.11
+pkgver=4.4.12
case $pkgver in
*.*.*) _kernver=${pkgver%.*};;
*.*) _kernver=${pkgver};;
esac
-pkgrel=3
+pkgrel=0
pkgdesc="Linux kernel with Raspberry Pi patches"
url=https://github.com/raspberrypi/linux
depends="mkinitfs linux-firmware"
@@ -15,8 +15,8 @@ options="!strip"
install=
source="http://ftp.kernel.org/pub/linux/kernel/v4.x/linux-$_kernver.tar.xz
http://ftp.kernel.org/pub/linux/kernel/v4.x/patch-$pkgver.xz
- http://dev.alpinelinux.org/~tteras/rpi/linux-4.4.y-rpi-20160514.patch
- rpi-cirrus-4.4.y-20160514.patch
+ http://dev.alpinelinux.org/~tteras/rpi/linux-4.4.y-rpi-20160602.patch
+ http://dev.alpinelinux.org/~tteras/rpi/rpi-cirrus-4.4.y-20160602.patch
gpio-mcp23s08-pullups.patch
rotary-encoder-fix.patch
issue-4973.patch
@@ -196,9 +196,9 @@ for _f in $_flavors; do
done
md5sums="9a78fa2eb6c68ca5a40ed5af08142599 linux-4.4.tar.xz
-5c1d328f03aaafb9cf7fdc442468c348 patch-4.4.11.xz
-1d08efb60aaa1a161aaa128807fcd8ce linux-4.4.y-rpi-20160514.patch
-1ac525e064919fd4ffec5d40b910cae1 rpi-cirrus-4.4.y-20160514.patch
+80d71a51152029a3f2fe99ba94548009 patch-4.4.12.xz
+1609c27d419440bc5eb338feffa4ab9d linux-4.4.y-rpi-20160602.patch
+f7142b2154dd5cfb5688ba692195ef6f rpi-cirrus-4.4.y-20160602.patch
b66e8aa4991ca5c2ccd61559ed7e6491 gpio-mcp23s08-pullups.patch
5508d2b3e5967bd57f92f551d90b3e54 rotary-encoder-fix.patch
29281b74d2cef6965fa4ab6d826a2aa4 issue-4973.patch
@@ -206,9 +206,9 @@ b66e8aa4991ca5c2ccd61559ed7e6491 gpio-mcp23s08-pullups.patch
26fbc79db35af5f371caf258336d5ab9 config-rpi2.armhf
e587cae1dca2f5992555d9bcf53deecf markdt"
sha256sums="401d7c8fef594999a460d10c72c5a94e9c2e1022f16795ec51746b0d165418b2 linux-4.4.tar.xz
-394c3970865c092f21cd02b8f433024adbf8539114567d6bde197fed6612f553 patch-4.4.11.xz
-68b19c4c589afa869d6278d775a34bb30bc83b3e09c703d9df3163f144a9d36e linux-4.4.y-rpi-20160514.patch
-651845267ee7ee815cc5e78cad9dad87d3de388ce07f911f68b20880ca1e3292 rpi-cirrus-4.4.y-20160514.patch
+1eb89dddd7e89caf2df17470b4b15da451ef1aa97f8e1a88578a8ee2da75729a patch-4.4.12.xz
+f05f9cb93a6445b07231afd4ac1052ca572bf7441c7d5c073edc2c99a28af096 linux-4.4.y-rpi-20160602.patch
+2e108a1d5e261e9193a2999afafef41e04e274db4c43607a1164d03d744c1e8e rpi-cirrus-4.4.y-20160602.patch
b389a556bbd98053881b43deef1adf20640f980557c5f37cfd7ece2daeecbda9 gpio-mcp23s08-pullups.patch
ab6740577fe8c1d71d2c716720ebbbf9a750985963d6938093b4ca9194b6e871 rotary-encoder-fix.patch
3a16e927ce53a8c56e7f1dd86fe8ad08b1c06466f5206c521a7e2de1e4796d6c issue-4973.patch
@@ -216,9 +216,9 @@ ab6740577fe8c1d71d2c716720ebbbf9a750985963d6938093b4ca9194b6e871 rotary-encoder
b46b7f6fece372840d8818c35fc74f09de7f2fba71eb2b86b184e37b5ed07484 config-rpi2.armhf
0f6681fc5c3590e1dbe13a2bde796403bd1529cf0fe19720899eaa0db79bcb49 markdt"
sha512sums="13c8459933a8b80608e226a1398e3d1848352ace84bcfb7e6a4a33cb230bbe1ab719d4b58e067283df91ce5311be6d2d595fc8c19e2ae6ecc652499415614b3e linux-4.4.tar.xz
-697e6dd2b85da13ae65ac70b9654c9c3fa00c3120d425fdb53104fc234457cda40b9f0ebe29e7ae5c1a191730666c0bbd291721b16623ee8e402287771f20def patch-4.4.11.xz
-77818e23a9ae1854589da425377f8ea96581166597a18f5fd70f1cfca2a7049d42aea239c25836e91702436b079369f0aa427c4eee58e43d1e4d5dcf7d62488d linux-4.4.y-rpi-20160514.patch
-abe4d482a98450335eb935cf49be468accc8955a464553c45280f15d4114a87e96b158800536c2f6c09be07474386bef952d1f96e58eaac5a4f6d6bd47e845c1 rpi-cirrus-4.4.y-20160514.patch
+c3aca55f26fc883b489635a90b79c03d7c6d591efddb4e406b5bfe49fc4326ff2a957521b1d8ea126b95f1d0573e5185d96bce10d05eae595a51f8eb27690404 patch-4.4.12.xz
+bb7bde9521281e5507bf0b0ed8912f56bd374df908f7f5f348a2faf223f3b92702988bdd07d0515aa90b4b03630de0edba598b3ebe49653483992828eea59e2b linux-4.4.y-rpi-20160602.patch
+9313a0553eee9d21efc019444273a4f6359afa6efaf12f1a65876f0fec43358e0a82ac851c6b830e28f8ae7f30e803949dcc40bcab43d57b3c50234fad2e621a rpi-cirrus-4.4.y-20160602.patch
36724ba56cb8fdf3a3d347cffb67ae1cc3d7b1052d526b6b5134ebf6baae9f9724b586c97833453dc7697ab24699426f0749af78b6a80be36967a80033a0cf40 gpio-mcp23s08-pullups.patch
3a711e2cdb6c0ecaceb3755437d38626dec8403e8aa167a6e16f64d8a8b7cc5bdc7e04aa7c05938719ebc90e319ec4124ee2151a7855e7838ee143b62d140ad0 rotary-encoder-fix.patch
501c91bf2538a18102da59bbccc3097f9c3c90079acc0e946ff075074160c09b8a66934e5ce5470e170f0e4f93d114709a95230367426d0bb7ea02c4bdf4cc9b issue-4973.patch
diff --git a/main/linux-rpi/rpi-cirrus-4.4.y-20160514.patch b/main/linux-rpi/rpi-cirrus-4.4.y-20160514.patch
deleted file mode 100644
index 26c41b867d..0000000000
--- a/main/linux-rpi/rpi-cirrus-4.4.y-20160514.patch
+++ /dev/null
@@ -1,1534 +0,0 @@
-diff --git a/Documentation/devicetree/bindings/mfd/arizona.txt b/Documentation/devicetree/bindings/mfd/arizona.txt
-index 18be0cb..4b3510a 100644
---- a/Documentation/devicetree/bindings/mfd/arizona.txt
-+++ b/Documentation/devicetree/bindings/mfd/arizona.txt
-@@ -44,6 +44,23 @@ Required properties:
- Optional properties:
-
- - wlf,reset : GPIO specifier for the GPIO controlling /RESET
-+ - wlf,clk32k-src : set input source for codec 32kHz clock.
-+ 0 = default, 1 = MCLK1, 2 = MCLK2, 3 = None
-+
-+ - wlf,micd-ranges : Microphone detection level and key configuration, this
-+ field can be of variable length but should always be a multiple of 2 cells
-+ long, each two cell group represents one button configuration
-+ The first cell is the maximum impedance for this button in ohms
-+ The second cell the key that should be reported to the input layer
-+ - wlf,micd-configs : Headset polarity configurations, the field can be of
-+ variable length but should always be a multiple of 3 cells long, each two
-+ cell group represents one polarity configration
-+ The first cell is the accessory detection source as per the ACCDET_SRC bits
-+ in the ACCESSORY_DETECT_MODE_1 register
-+ The second cell represents the MICBIAS to be used as per the MICD_BIAS_SRC
-+ bits in the MIC_DETECT_1 register
-+ The third cell represents the value of the micd-pol-gpio pin, a non-zero
-+ value indicates this should be on
-
- - wlf,gpio-defaults : A list of GPIO configuration register values. Defines
- for the appropriate values can found in <dt-bindings/mfd/arizona.txt>. If
-@@ -51,6 +68,10 @@ Optional properties:
- a value that is out of range for a 16 bit register then the chip default
- will be used. If present exactly five values must be specified.
-
-+ - wlf,dmic-ref : DMIC reference for each input, must contain four cells if
-+ specified. 0 indicates MICVDD and is the default, 1,2,3 indicate the
-+ respective MICBIAS.
-+
- - wlf,inmode : A list of INn_MODE register values, where n is the number
- of input signals. Valid values are 0 (Differential), 1 (Single-ended) and
- 2 (Digital Microphone). If absent, INn_MODE registers set to 0 by default.
-@@ -87,6 +108,19 @@ codec: wm5102@1a {
- gpio-controller;
- #gpio-cells = <2>;
-
-+ wlf,micd-ranges = <
-+ 11 0x100
-+ 28 0x101
-+ 54 0x102
-+ 100 0x103
-+ 186 0x104
-+ 430 0x105
-+ >;
-+ wlf,micd-configs = <
-+ 0x1 1 0
-+ 0x0 2 1
-+ >;
-+
- wlf,gpio-defaults = <
- ARIZONA_GP_FN_TXLRCLK
- ARIZONA_GP_DEFAULT
-@@ -94,4 +128,6 @@ codec: wm5102@1a {
- ARIZONA_GP_DEFAULT
- ARIZONA_GP_DEFAULT
- >;
-+
-+ wlf,dmic-ref = <0 0 1 0>;
- };
-diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile
-index 3d8de47..156c29d 100644
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -61,6 +61,7 @@ dtbo-$(RPI_DT_OVERLAYS) += pwm-2chan.dtbo
- dtbo-$(RPI_DT_OVERLAYS) += qca7000.dtbo
- dtbo-$(RPI_DT_OVERLAYS) += raspidac3.dtbo
- dtbo-$(RPI_DT_OVERLAYS) += rpi-backlight.dtbo
-+dtbo-$(RPI_DT_OVERLAYS) += rpi-cirrus-wm5102.dtbo
- dtbo-$(RPI_DT_OVERLAYS) += rpi-dac.dtbo
- dtbo-$(RPI_DT_OVERLAYS) += rpi-display.dtbo
- dtbo-$(RPI_DT_OVERLAYS) += rpi-ft5406.dtbo
-diff --git a/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
-new file mode 100644
-index 0000000..3cb63a5
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts
-@@ -0,0 +1,138 @@
-+// Definitions for Cirrus audio card
-+/dts-v1/;
-+/plugin/;
-+
-+/ {
-+ compatible = "brcm,bcm2708";
-+
-+ fragment@0 {
-+ target-path = "/";
-+ __overlay__ {
-+ aliases {
-+ ldo0 = &ldo0;
-+ ldo1 = &ldo1;
-+ };
-+ };
-+ };
-+
-+ fragment@1 {
-+ target = <&sound>;
-+ __overlay__ {
-+ compatible = "wlf,rpi-wm5102";
-+ i2s-controller = <&i2s>;
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@2 {
-+ target = <&i2s>;
-+ __overlay__ {
-+ status = "okay";
-+ };
-+ };
-+
-+ fragment@3 {
-+ target = <&gpio>;
-+ __overlay__ {
-+ wlf_pins: wlf_pins {
-+ brcm,pins = <17 22 27 8>;
-+ brcm,function = <1 1 0 1>;
-+ };
-+ };
-+ };
-+
-+ fragment@4 {
-+ target-path = "/soc";
-+ __overlay__ {
-+
-+ ldo1: ldo1 {
-+ compatible = "regulator-fixed";
-+ regulator-name = "DC_5V";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ enable-active-high;
-+ regulator-always-on;
-+ };
-+
-+ ldo0: ldo0 {
-+ compatible = "regulator-fixed";
-+ regulator-name = "DC_1V8";
-+ regulator-min-microvolt = <1800000>;
-+ regulator-max-microvolt = <1800000>;
-+ enable-active-high;
-+ regulator-always-on;
-+ };
-+ };
-+ };
-+
-+ fragment@5 {
-+ target = <&spi0>;
-+ __overlay__ {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "okay";
-+
-+ spidev@0{
-+ status = "disabled";
-+ };
-+
-+ spidev@1{
-+ status = "disabled";
-+ };
-+
-+ wm5102@1{
-+ compatible = "wlf,wm5102";
-+ reg = <1>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ spi-max-frequency = <500000>;
-+
-+ interrupt-parent = <&gpio>;
-+ interrupts = <27 8>;
-+
-+ LDOVDD-supply = <&ldo0>;
-+ AVDD-supply = <&ldo0>;
-+ DBVDD1-supply = <&ldo0>;
-+ DBVDD2-supply = <&ldo0>;
-+ DBVDD3-supply = <&ldo0>;
-+ CPVDD-supply = <&ldo0>;
-+ SPKVDDL-supply = <&ldo1>;
-+ SPKVDDR-supply = <&ldo1>;
-+
-+ wlf,reset = <&gpio 17 0>;
-+ wlf,ldoena = <&gpio 22 0>;
-+ wlf,gpio-defaults = <
-+ 0x000fffff
-+ 0x000fffff
-+ 0x000fffff
-+ 0x000fffff
-+ 0x000fffff
-+ >;
-+ wlf,micd-configs = <0 1 0>;
-+ wlf,dmic-ref = <0 2 0 0>;
-+ wlf,clk32k-src = <3>;
-+ wlf,inmode = <0 2 1 0>;
-+ status = "okay";
-+ };
-+ };
-+ };
-+
-+ fragment@6 {
-+ target = <&i2c1>;
-+ __overlay__ {
-+ status = "okay";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ wm8804@3b {
-+ #sound-dai-cells = <0>;
-+ compatible = "wlf,wm8804";
-+ reg = <0x3b>;
-+ status = "okay";
-+ PVDD-supply = <&ldo0>;
-+ DVDD-supply = <&ldo0>;
-+ wlf,reset-gpio = <&gpio 8 0>;
-+ };
-+ };
-+ };
-+};
-diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig
-index 0bdc631..4de55c8 100644
---- a/arch/arm/configs/bcm2709_defconfig
-+++ b/arch/arm/configs/bcm2709_defconfig
-@@ -650,6 +650,9 @@ CONFIG_STMPE_SPI=y
- CONFIG_MFD_ARIZONA_I2C=m
- CONFIG_MFD_ARIZONA_SPI=m
- CONFIG_MFD_WM5102=y
-+CONFIG_REGULATOR=y
-+CONFIG_REGULATOR_FIXED_VOLTAGE=m
-+CONFIG_REGULATOR_ARIZONA=m
- CONFIG_MEDIA_SUPPORT=m
- CONFIG_MEDIA_CAMERA_SUPPORT=y
- CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
-@@ -863,6 +866,7 @@ CONFIG_SND_BCM2708_SOC_BOOMBERRY_DIGI=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
- CONFIG_SND_BCM2708_SOC_RASPIDAC3=m
- CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
-+CONFIG_SND_BCM2708_SOC_RPI_CODEC_WSP=m
- CONFIG_SND_SOC_ADAU1701=m
- CONFIG_SND_SOC_WM8804_I2C=m
- CONFIG_SND_SIMPLE_CARD=m
-diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig
-index 57393b5..55ef0a5 100644
---- a/arch/arm/configs/bcmrpi_defconfig
-+++ b/arch/arm/configs/bcmrpi_defconfig
-@@ -642,6 +642,9 @@ CONFIG_STMPE_SPI=y
- CONFIG_MFD_ARIZONA_I2C=m
- CONFIG_MFD_ARIZONA_SPI=m
- CONFIG_MFD_WM5102=y
-+CONFIG_REGULATOR=y
-+CONFIG_REGULATOR_FIXED_VOLTAGE=m
-+CONFIG_REGULATOR_ARIZONA=m
- CONFIG_MEDIA_SUPPORT=m
- CONFIG_MEDIA_CAMERA_SUPPORT=y
- CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
-@@ -855,6 +858,7 @@ CONFIG_SND_BCM2708_SOC_BOOMBERRY_DIGI=m
- CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
- CONFIG_SND_BCM2708_SOC_RASPIDAC3=m
- CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m
-+CONFIG_SND_BCM2708_SOC_RPI_CODEC_WSP=m
- CONFIG_SND_SOC_ADAU1701=m
- CONFIG_SND_SOC_WM8804_I2C=m
- CONFIG_SND_SIMPLE_CARD=m
-diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
-index d26b6bd..dad4f48 100644
---- a/drivers/dma/bcm2835-dma.c
-+++ b/drivers/dma/bcm2835-dma.c
-@@ -144,12 +144,6 @@ struct bcm2835_desc {
- */
- #define MAX_LITE_TRANSFER (SZ_64K - 4)
-
--/*
-- * Transfers larger than 32k cause issues with the bcm2708-i2s driver,
-- * so limit transfer size to 32k as bcm2708-dmaengine did.
-- */
--#define MAX_CYCLIC_LITE_TRANSFER SZ_32K
--
- static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d)
- {
- return container_of(d, struct bcm2835_dmadev, ddev);
-@@ -385,6 +379,15 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
- unsigned int frame, max_size;
- int i;
-
-+ if (!buf_len || !period_len)
-+ return NULL;
-+
-+ if (buf_len % period_len) {
-+ dev_err(chan->device->dev,
-+ "Buffer length should be a multiple of period\n");
-+ return NULL;
-+ }
-+
- /* Grab configuration */
- if (!is_slave_direction(direction)) {
- dev_err(chan->device->dev, "%s: bad direction?\n", __func__);
-@@ -410,6 +413,18 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
- return NULL;
- }
-
-+ if (c->ch >= 8) /* LITE channel */
-+ max_size = MAX_LITE_TRANSFER;
-+ else
-+ max_size = MAX_NORMAL_TRANSFER;
-+
-+ if (period_len > max_size) {
-+ dev_err(chan->device->dev,
-+ "Period length %d larger than maximum %d\n",
-+ period_len, max_size);
-+ return NULL;
-+ }
-+
- /* Now allocate and setup the descriptor. */
- d = kzalloc(sizeof(*d), GFP_NOWAIT);
- if (!d)
-@@ -417,12 +432,8 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
-
- d->c = c;
- d->dir = direction;
-- if (c->ch >= 8) /* LITE channel */
-- max_size = MAX_CYCLIC_LITE_TRANSFER;
-- else
-- max_size = MAX_NORMAL_TRANSFER;
-- period_len = min(period_len, max_size);
-- d->frames = (buf_len - 1) / (period_len + 1);
-+ d->frames = buf_len / period_len;
-+ d->size = buf_len;
-
- d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL);
- if (!d->cb_list) {
-@@ -470,12 +481,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
- BCM2835_DMA_PER_MAP(c->dreq);
-
- /* Length of a frame */
-- if (frame != d->frames - 1)
-- control_block->length = period_len;
-- else
-- control_block->length = buf_len - (d->frames - 1) *
-- period_len;
-- d->size += control_block->length;
-+ control_block->length = period_len;
-
- /*
- * Next block is the next frame.
-diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
-index d474732..a899b57 100644
---- a/drivers/mfd/arizona-core.c
-+++ b/drivers/mfd/arizona-core.c
-@@ -16,6 +16,7 @@
- #include <linux/interrupt.h>
- #include <linux/mfd/core.h>
- #include <linux/module.h>
-+#include <linux/notifier.h>
- #include <linux/of.h>
- #include <linux/of_device.h>
- #include <linux/of_gpio.h>
-@@ -460,6 +461,20 @@ static int wm5102_clear_write_sequencer(struct arizona *arizona)
- return 0;
- }
-
-+static int arizona_dcvdd_notify(struct notifier_block *nb,
-+ unsigned long action, void *data)
-+{
-+ struct arizona *arizona = container_of(nb, struct arizona,
-+ dcvdd_notifier);
-+
-+ dev_dbg(arizona->dev, "DCVDD notify %lx\n", action);
-+
-+ if (action & REGULATOR_EVENT_DISABLE)
-+ msleep(20);
-+
-+ return NOTIFY_DONE;
-+}
-+
- #ifdef CONFIG_PM
- static int arizona_isolate_dcvdd(struct arizona *arizona)
- {
-@@ -800,6 +815,154 @@ int arizona_of_get_named_gpio(struct arizona *arizona, const char *prop,
- }
- EXPORT_SYMBOL_GPL(arizona_of_get_named_gpio);
-
-+static int arizona_of_get_u32_num_groups(struct arizona *arizona,
-+ const char *prop,
-+ int group_size)
-+{
-+ int len_prop;
-+ int num_groups;
-+
-+ if (!of_get_property(arizona->dev->of_node, prop, &len_prop))
-+ return -EINVAL;
-+
-+ num_groups = len_prop / (group_size * sizeof(u32));
-+
-+ if (num_groups * group_size * sizeof(u32) != len_prop) {
-+ dev_err(arizona->dev,
-+ "DT property %s is malformed: %d\n",
-+ prop, -EOVERFLOW);
-+ return -EOVERFLOW;
-+ }
-+
-+ return num_groups;
-+}
-+
-+static int arizona_of_get_micd_ranges(struct arizona *arizona,
-+ const char *prop)
-+{
-+ int nranges;
-+ int i, j;
-+ int ret = 0;
-+ u32 value;
-+ struct arizona_micd_range *micd_ranges;
-+
-+ nranges = arizona_of_get_u32_num_groups(arizona, prop, 2);
-+ if (nranges < 0)
-+ return nranges;
-+
-+ micd_ranges = devm_kzalloc(arizona->dev,
-+ nranges * sizeof(struct arizona_micd_range),
-+ GFP_KERNEL);
-+
-+ for (i = 0, j = 0; i < nranges; ++i) {
-+ ret = of_property_read_u32_index(arizona->dev->of_node,
-+ prop, j++, &value);
-+ if (ret < 0)
-+ goto error;
-+ micd_ranges[i].max = value;
-+
-+ ret = of_property_read_u32_index(arizona->dev->of_node,
-+ prop, j++, &value);
-+ if (ret < 0)
-+ goto error;
-+ micd_ranges[i].key = value;
-+ }
-+
-+ arizona->pdata.micd_ranges = micd_ranges;
-+ arizona->pdata.num_micd_ranges = nranges;
-+
-+ return ret;
-+
-+error:
-+ devm_kfree(arizona->dev, micd_ranges);
-+ dev_err(arizona->dev, "DT property %s is malformed: %d\n", prop, ret);
-+ return ret;
-+}
-+
-+static int arizona_of_get_micd_configs(struct arizona *arizona,
-+ const char *prop)
-+{
-+ int nconfigs;
-+ int i, j;
-+ int ret = 0;
-+ u32 value;
-+ struct arizona_micd_config *micd_configs;
-+
-+ nconfigs = arizona_of_get_u32_num_groups(arizona, prop, 3);
-+ if (nconfigs < 0)
-+ return nconfigs;
-+
-+ micd_configs = devm_kzalloc(arizona->dev,
-+ nconfigs *
-+ sizeof(struct arizona_micd_config),
-+ GFP_KERNEL);
-+
-+ for (i = 0, j = 0; i < nconfigs; ++i) {
-+ ret = of_property_read_u32_index(arizona->dev->of_node,
-+ prop, j++, &value);
-+ if (ret < 0)
-+ goto error;
-+ micd_configs[i].src = value;
-+
-+ ret = of_property_read_u32_index(arizona->dev->of_node,
-+ prop, j++, &value);
-+ if (ret < 0)
-+ goto error;
-+ micd_configs[i].bias = value;
-+
-+ ret = of_property_read_u32_index(arizona->dev->of_node,
-+ prop, j++, &value);
-+ if (ret < 0)
-+ goto error;
-+ micd_configs[i].gpio = value;
-+ }
-+
-+ arizona->pdata.micd_configs = micd_configs;
-+ arizona->pdata.num_micd_configs = nconfigs;
-+
-+ return ret;
-+
-+error:
-+ devm_kfree(arizona->dev, micd_configs);
-+ dev_err(arizona->dev, "DT property %s is malformed: %d\n", prop, ret);
-+ return ret;
-+}
-+
-+static int arizona_of_read_u32_array(struct arizona *arizona,
-+ const char *prop, bool mandatory,
-+ u32 *data, size_t num)
-+{
-+ int ret;
-+
-+ ret = of_property_read_u32_array(arizona->dev->of_node, prop,
-+ data, num);
-+
-+ if (ret >= 0)
-+ return 0;
-+
-+ switch (ret) {
-+ case -EINVAL:
-+ if (mandatory)
-+ dev_err(arizona->dev,
-+ "Mandatory DT property %s is missing\n",
-+ prop);
-+ break;
-+ default:
-+ dev_err(arizona->dev,
-+ "DT property %s is malformed: %d\n",
-+ prop, ret);
-+ }
-+
-+ return ret;
-+}
-+
-+static int arizona_of_read_u32(struct arizona *arizona,
-+ const char* prop, bool mandatory,
-+ u32 *data)
-+{
-+ return arizona_of_read_u32_array(arizona, prop, mandatory, data, 1);
-+}
-+
- static int arizona_of_get_core_pdata(struct arizona *arizona)
- {
- struct arizona_pdata *pdata = &arizona->pdata;
-@@ -833,6 +996,15 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
- ret);
- }
-
-+ arizona_of_read_u32(arizona, "wlf,clk32k-src", false,
-+ &pdata->clk32k_src);
-+
-+ arizona_of_get_micd_ranges(arizona, "wlf,micd-ranges");
-+ arizona_of_get_micd_configs(arizona, "wlf,micd-configs");
-+
-+ arizona_of_read_u32_array(arizona, "wlf,dmic-ref", false,
-+ pdata->dmic_ref, ARRAY_SIZE(pdata->dmic_ref));
-+
- of_property_for_each_u32(arizona->dev->of_node, "wlf,inmode", prop,
- cur, val) {
- if (count == ARRAY_SIZE(pdata->inmode))
-@@ -852,6 +1024,9 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
- count++;
- }
-
-+ arizona_of_read_u32(arizona, "wlf,irq_gpio", false,
-+ &pdata->irq_gpio);
-+
- return 0;
- }
-
-@@ -1029,6 +1204,14 @@ int arizona_dev_init(struct arizona *arizona)
- goto err_early;
- }
-
-+ arizona->dcvdd_notifier.notifier_call = arizona_dcvdd_notify;
-+ ret = regulator_register_notifier(arizona->dcvdd,
-+ &arizona->dcvdd_notifier);
-+ if (ret < 0) {
-+ dev_err(dev, "Failed to register DCVDD notifier %d\n", ret);
-+ goto err_dcvdd;
-+ }
-+
- if (arizona->pdata.reset) {
- /* Start out with /RESET low to put the chip into reset */
- ret = devm_gpio_request_one(arizona->dev, arizona->pdata.reset,
-@@ -1036,16 +1219,19 @@ int arizona_dev_init(struct arizona *arizona)
- "arizona /RESET");
- if (ret != 0) {
- dev_err(dev, "Failed to request /RESET: %d\n", ret);
-- goto err_dcvdd;
-+ goto err_notifier;
- }
- }
-
-+ /* Ensure period of reset asserted before we apply the supplies */
-+ msleep(20);
-+
- ret = regulator_bulk_enable(arizona->num_core_supplies,
- arizona->core_supplies);
- if (ret != 0) {
- dev_err(dev, "Failed to enable core supplies: %d\n",
- ret);
-- goto err_dcvdd;
-+ goto err_notifier;
- }
-
- ret = regulator_enable(arizona->dcvdd);
-@@ -1420,6 +1606,8 @@ err_reset:
- err_enable:
- regulator_bulk_disable(arizona->num_core_supplies,
- arizona->core_supplies);
-+err_notifier:
-+ regulator_unregister_notifier(arizona->dcvdd, &arizona->dcvdd_notifier);
- err_dcvdd:
- regulator_put(arizona->dcvdd);
- err_early:
-@@ -1433,6 +1621,7 @@ int arizona_dev_exit(struct arizona *arizona)
- pm_runtime_disable(arizona->dev);
-
- regulator_disable(arizona->dcvdd);
-+ regulator_unregister_notifier(arizona->dcvdd, &arizona->dcvdd_notifier);
- regulator_put(arizona->dcvdd);
-
- mfd_remove_devices(arizona->dev);
-diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
-index f7c88ff..19fdcd4 100644
---- a/drivers/regulator/arizona-ldo1.c
-+++ b/drivers/regulator/arizona-ldo1.c
-@@ -288,6 +288,7 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
- }
-
- config.ena_gpio = arizona->pdata.ldoena;
-+ config.ena_gpio_flags = GPIOF_OUT_INIT_LOW;
-
- if (arizona->pdata.ldo1)
- config.init_data = arizona->pdata.ldo1;
-diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h
-index 79e607e..39a23eb 100644
---- a/include/linux/mfd/arizona/core.h
-+++ b/include/linux/mfd/arizona/core.h
-@@ -119,6 +119,7 @@ struct arizona {
- int num_core_supplies;
- struct regulator_bulk_data core_supplies[ARIZONA_MAX_CORE_SUPPLIES];
- struct regulator *dcvdd;
-+ struct notifier_block dcvdd_notifier;
- bool has_fully_powered_off;
-
- struct arizona_pdata pdata;
-diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
-index 95a937e..8262719 100644
---- a/include/sound/soc-dapm.h
-+++ b/include/sound/soc-dapm.h
-@@ -383,10 +383,11 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
- int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
- void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card);
- int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
-- const struct snd_soc_pcm_stream *params,
-+ struct snd_soc_pcm_stream *params,
- unsigned int num_params,
- struct snd_soc_dapm_widget *source,
-- struct snd_soc_dapm_widget *sink);
-+ struct snd_soc_dapm_widget *sink,
-+ void *priv);
-
- /* dapm path setup */
- int snd_soc_dapm_new_widgets(struct snd_soc_card *card);
-@@ -553,7 +554,7 @@ struct snd_soc_dapm_widget {
-
- void *priv; /* widget specific data */
- struct regulator *regulator; /* attached regulator */
-- const struct snd_soc_pcm_stream *params; /* params for dai links */
-+ struct snd_soc_pcm_stream *params; /* params for dai links */
- unsigned int num_params; /* number of params for dai links */
- unsigned int params_select; /* currently selected param for dai link */
-
-diff --git a/include/sound/soc.h b/include/sound/soc.h
-index fb955e6..bbdc05d 100644
---- a/include/sound/soc.h
-+++ b/include/sound/soc.h
-@@ -989,7 +989,9 @@ struct snd_soc_dai_link {
- struct device_node *platform_of_node;
- int be_id; /* optional ID for machine driver BE identification */
-
-- const struct snd_soc_pcm_stream *params;
-+ struct snd_soc_pcm_stream *params;
-+ /* optional params re-writing for dai links */
-+ int (*params_fixup)(struct snd_soc_dapm_widget *w, int event);
- unsigned int num_params;
-
- unsigned int dai_fmt; /* format to set on init */
-diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig
-index c05e656..0fb2384 100644
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -85,3 +85,12 @@ config SND_BCM2708_SOC_ADAU1977_ADC
- select SND_SOC_ADAU1977_I2C
- help
- Say Y or M if you want to add support for ADAU1977 ADC.
-+
-+config SND_BCM2708_SOC_RPI_CODEC_WSP
-+ tristate "Support for Cirrus sound pi"
-+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+ select SND_SOC_WM5102
-+ select SND_SOC_WM8804
-+ help
-+ Say Y or M if you want to add support for Cirrus sound pi
-+
-diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile
-index 7de2ef1..4d6c910 100644
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -15,6 +15,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-rpi-wsp-objs := rpi-cirrus-sound-pi.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
-@@ -27,3 +28,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o
- obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
- obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
- obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o
-+obj-$(CONFIG_SND_BCM2708_SOC_RPI_CODEC_WSP) += snd-soc-rpi-wsp.o
-diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c
-index aedb01f..c413973 100644
---- a/sound/soc/bcm/bcm2835-i2s.c
-+++ b/sound/soc/bcm/bcm2835-i2s.c
-@@ -813,16 +813,16 @@ static struct snd_pcm_hardware bcm2835_pcm_hardware = {
- SNDRV_PCM_FMTBIT_S24_LE |
- SNDRV_PCM_FMTBIT_S32_LE,
- .period_bytes_min = 32,
-- .period_bytes_max = 64 * PAGE_SIZE,
-+ .period_bytes_max = SZ_64K - 4,
- .periods_min = 2,
- .periods_max = 255,
-- .buffer_bytes_max = 128 * PAGE_SIZE,
-+ .buffer_bytes_max = SZ_512K,
- };
-
- static const struct snd_dmaengine_pcm_config bcm2835_dmaengine_pcm_config = {
- .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
- .pcm_hardware = &bcm2835_pcm_hardware,
-- .prealloc_buffer_size = 256 * PAGE_SIZE,
-+ .prealloc_buffer_size = SZ_1M,
- };
-
- static int bcm2835_i2s_probe(struct platform_device *pdev)
-diff --git a/sound/soc/bcm/rpi-cirrus-sound-pi.c b/sound/soc/bcm/rpi-cirrus-sound-pi.c
-new file mode 100644
-index 0000000..3abfff1
---- /dev/null
-+++ b/sound/soc/bcm/rpi-cirrus-sound-pi.c
-@@ -0,0 +1,638 @@
-+/*
-+ * ASoC machine driver for Cirrus Audio Card (with a WM5102 and WM8804 codecs )
-+ * connected to a Raspberry Pi
-+ *
-+ * Copyright 2015 Cirrus Logic Inc.
-+ *
-+ * Author: Nikesh Oswal, <Nikesh.Oswal@wolfsonmicro.com>
-+ * Partly based on sound/soc/bcm/iqaudio-dac.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/mutex.h>
-+#include <linux/slab.h>
-+#include <sound/pcm_params.h>
-+
-+#include "../codecs/wm5102.h"
-+#include "../codecs/wm8804.h"
-+
-+#define WM8804_CLKOUT_HZ 12000000
-+
-+#define RPI_WLF_SR 44100
-+#define WM5102_MAX_SYSCLK_1 49152000 /*max sysclk for 4K family*/
-+#define WM5102_MAX_SYSCLK_2 45158400 /*max sysclk for 11.025K family*/
-+
-+#define DAI_WM5102 0
-+#define DAI_WM8804 1
-+
-+static struct snd_soc_card snd_rpi_wsp;
-+
-+struct wm5102_machine_priv {
-+ int wm8804_sr;
-+ int wm5102_sr;
-+ int sync_path_enable;
-+ int fll1_freq; /* negative means RefClock in spdif rx case */
-+ /* mutex for synchronzing FLL1 access with DAPM */
-+ struct mutex fll1_mutex;
-+};
-+
-+int spdif_rx_enable_event(struct snd_soc_dapm_widget *w,
-+ struct snd_kcontrol *kcontrol, int event)
-+{
-+ struct snd_soc_card *card = &snd_rpi_wsp;
-+ struct wm5102_machine_priv *priv = snd_soc_card_get_drvdata(card);
-+ struct snd_soc_pcm_runtime *wm5102_rtd;
-+ struct snd_soc_codec *wm5102_codec;
-+ int ret = 0;
-+ int clk_freq;
-+ int sr = priv->wm8804_sr;
-+
-+ dev_dbg(card->dev, "spdif_rx event %d\n", event);
-+
-+ wm5102_rtd = snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM5102].name);
-+ if (!wm5102_rtd) {
-+ dev_warn(card->dev, "spdif_rx_enable_event: couldn't get WM5102 rtd\n");
-+ return -EFAULT;
-+ }
-+ wm5102_codec = wm5102_rtd->codec;
-+
-+ switch (event) {
-+ case SND_SOC_DAPM_POST_PMU:
-+ mutex_lock(&priv->fll1_mutex);
-+
-+ dev_dbg(wm5102_codec->dev,
-+ "spdif_rx: changing FLL1 to use Ref Clock\n");
-+
-+ /* Enable sync path in case of SPDIF capture use case */
-+ clk_freq = (sr % 4000 == 0) ? WM5102_MAX_SYSCLK_1 : WM5102_MAX_SYSCLK_2;
-+
-+ /*reset FLL1*/
-+ snd_soc_codec_set_pll(wm5102_codec, WM5102_FLL1_REFCLK,
-+ ARIZONA_FLL_SRC_NONE, 0, 0);
-+ snd_soc_codec_set_pll(wm5102_codec, WM5102_FLL1,
-+ ARIZONA_FLL_SRC_NONE, 0, 0);
-+
-+ ret = snd_soc_codec_set_pll(wm5102_codec, WM5102_FLL1_REFCLK,
-+ ARIZONA_CLK_SRC_MCLK1,
-+ WM8804_CLKOUT_HZ,
-+ clk_freq);
-+ if (ret != 0) {
-+ dev_err(wm5102_codec->dev, "Failed to enable FLL1 with Ref Clock Loop: %d\n", ret);
-+ mutex_unlock(&priv->fll1_mutex);
-+ return ret;
-+ }
-+
-+ ret = snd_soc_codec_set_pll(wm5102_codec, WM5102_FLL1,
-+ ARIZONA_CLK_SRC_AIF2BCLK,
-+ sr * 64, clk_freq);
-+ if (!ret)
-+ /* set to negative to indicate we're doing spdif rx */
-+ priv->fll1_freq = -clk_freq;
-+
-+ mutex_unlock(&priv->fll1_mutex);
-+
-+ if (ret != 0) {
-+ dev_err(wm5102_codec->dev, "Failed to enable FLL1 Sync Clock Loop: %d\n", ret);
-+ return ret;
-+ }
-+ priv->sync_path_enable = 1;
-+ break;
-+ case SND_SOC_DAPM_POST_PMD:
-+ priv->sync_path_enable = 0;
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+static const struct snd_kcontrol_new rpi_wsp_controls[] = {
-+ SOC_DAPM_PIN_SWITCH("DMIC"),
-+ SOC_DAPM_PIN_SWITCH("Headset Mic"),
-+ SOC_DAPM_PIN_SWITCH("SPDIF Out"),
-+ SOC_DAPM_PIN_SWITCH("SPDIF In"),
-+ SOC_DAPM_PIN_SWITCH("Line Input"),
-+};
-+
-+const struct snd_soc_dapm_widget rpi_wsp_dapm_widgets[] = {
-+ SND_SOC_DAPM_MIC("DMIC", NULL),
-+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
-+ SND_SOC_DAPM_MIC("Line Input", NULL),
-+ SND_SOC_DAPM_INPUT("dummy SPDIF in"),
-+ SND_SOC_DAPM_PGA_E("dummy SPDIFRX", SND_SOC_NOPM, 0, 0,NULL, 0,
-+ spdif_rx_enable_event,
-+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-+};
-+
-+const struct snd_soc_dapm_route rpi_wsp_dapm_routes[] = {
-+ { "IN1L", NULL, "Headset Mic" },
-+ { "IN1R", NULL, "Headset Mic" },
-+ { "Headset Mic", NULL, "MICBIAS1" },
-+
-+ { "IN2L", NULL, "DMIC" },
-+ { "IN2R", NULL, "DMIC" },
-+ { "DMIC", NULL, "MICBIAS2" },
-+
-+ { "IN3L", NULL, "Line Input" },
-+ { "IN3R", NULL, "Line Input" },
-+ { "Line Input", NULL, "MICBIAS3" },
-+
-+ /* Dummy routes to check whether SPDIF RX is enabled or not */
-+ {"dummy SPDIFRX", NULL, "dummy SPDIF in"},
-+ {"AIFTX", NULL, "dummy SPDIFRX"},
-+};
-+
-+static int rpi_set_bias_level(struct snd_soc_card *card,
-+ struct snd_soc_dapm_context *dapm,
-+ enum snd_soc_bias_level level)
-+{
-+ struct snd_soc_pcm_runtime *wm5102_rtd;
-+ struct snd_soc_codec *wm5102_codec;
-+ struct snd_soc_dai *wm5102_codec_dai;
-+ struct wm5102_machine_priv *priv = snd_soc_card_get_drvdata(card);
-+
-+ int ret;
-+ int sr = priv->wm5102_sr;
-+ int clk_freq = (sr % 4000 == 0) ? WM5102_MAX_SYSCLK_1 : WM5102_MAX_SYSCLK_2;
-+
-+ wm5102_rtd = snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM5102].name);
-+ if (!wm5102_rtd) {
-+ dev_warn(card->dev, "rpi_set_bias_level: couldn't get WM5102 rtd\n");
-+ return -EFAULT;
-+ }
-+ wm5102_codec = wm5102_rtd->codec;
-+ wm5102_codec_dai = wm5102_rtd->codec_dai;
-+
-+ if (dapm->dev != wm5102_codec_dai->dev)
-+ return 0;
-+
-+ dev_dbg(wm5102_codec->dev, "change bias level from %d to %d, sync=%d\n",
-+ dapm->bias_level, level, priv->sync_path_enable);
-+
-+ switch (level) {
-+ case SND_SOC_BIAS_ON:
-+ /* no need to check current level, it can only be PREPARE */
-+ if (!priv->sync_path_enable) {
-+ mutex_lock(&priv->fll1_mutex);
-+
-+ dev_dbg(wm5102_codec->dev,
-+ "bias_on: changing FLL1 from %d to %d\n",
-+ priv->fll1_freq, clk_freq);
-+
-+ ret = snd_soc_codec_set_pll(wm5102_codec, WM5102_FLL1,
-+ ARIZONA_CLK_SRC_MCLK1,
-+ WM8804_CLKOUT_HZ,
-+ clk_freq);
-+ if (!ret)
-+ priv->fll1_freq = clk_freq;
-+
-+ mutex_unlock(&priv->fll1_mutex);
-+
-+ if (ret != 0) {
-+ dev_err(wm5102_codec->dev, "Failed to enable FLL1: %d\n", ret);
-+ return ret;
-+ }
-+ }
-+ break;
-+ case SND_SOC_BIAS_STANDBY:
-+ if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
-+ break;
-+
-+ mutex_lock(&priv->fll1_mutex);
-+
-+ dev_dbg(wm5102_codec->dev,
-+ "bias_standby: changing FLL1 from %d to off\n",
-+ priv->fll1_freq);
-+
-+ ret = snd_soc_codec_set_pll(wm5102_codec, WM5102_FLL1,
-+ ARIZONA_FLL_SRC_NONE, 0, 0);
-+ if (ret)
-+ dev_warn(wm5102_codec->dev, "set_bias_level: Failed to stop FLL1: %d\n", ret);
-+
-+ ret = snd_soc_codec_set_pll(wm5102_codec, WM5102_FLL1_REFCLK,
-+ ARIZONA_FLL_SRC_NONE, 0, 0);
-+ if (ret)
-+ dev_warn(wm5102_codec->dev, "set_bias_level: Failed to stop FLL1_REFCLK: %d\n", ret);
-+
-+ priv->fll1_freq = 0;
-+
-+ mutex_unlock(&priv->fll1_mutex);
-+
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+static int snd_rpi_wsp_config_5102_clks(
-+ struct wm5102_machine_priv *priv,
-+ struct snd_soc_codec *wm5102_codec, int sr)
-+{
-+ int ret;
-+ int clk_freq = (sr % 4000 == 0) ? WM5102_MAX_SYSCLK_1 : WM5102_MAX_SYSCLK_2;
-+
-+ /*
-+ * Manually set up FLL1 if it's configured to another rate but only
-+ * if we are not using spdif rx (fll1_freq negative).
-+ * This is necessary if delayed DAPM powerdown hasn't stopped
-+ * the FLL before.
-+ */
-+ if ((priv->fll1_freq > 0) && (priv->fll1_freq != clk_freq)) {
-+ mutex_lock(&priv->fll1_mutex);
-+
-+ dev_dbg(wm5102_codec->dev,
-+ "config_5102_clks: changing FLL1 from %d to %d\n",
-+ priv->fll1_freq, clk_freq);
-+
-+ /*reset FLL1*/
-+ snd_soc_codec_set_pll(wm5102_codec, WM5102_FLL1,
-+ ARIZONA_FLL_SRC_NONE, 0, 0);
-+
-+ ret = snd_soc_codec_set_pll(wm5102_codec, WM5102_FLL1,
-+ ARIZONA_CLK_SRC_MCLK1,
-+ WM8804_CLKOUT_HZ,
-+ clk_freq);
-+ if (!ret)
-+ priv->fll1_freq = clk_freq;
-+
-+ mutex_unlock(&priv->fll1_mutex);
-+
-+ if (ret) {
-+ dev_err(wm5102_codec->dev, "Failed to set FLL1: %d\n", ret);
-+ return ret;
-+ }
-+
-+ }
-+
-+ ret = snd_soc_codec_set_sysclk(wm5102_codec,
-+ ARIZONA_CLK_SYSCLK,
-+ ARIZONA_CLK_SRC_FLL1,
-+ clk_freq,
-+ SND_SOC_CLOCK_IN);
-+ if (ret != 0) {
-+ dev_err(wm5102_codec->dev, "Failed to set AYNCCLK: %d\n", ret);
-+ return ret;
-+ }
-+
-+ return 0;
-+ }
-+
-+static int snd_rpi_wsp_config_8804_clks(struct snd_soc_codec *wm8804_codec,
-+ struct snd_soc_dai *wm8804_dai, int sr)
-+ {
-+ int ret;
-+
-+ /*Set OSC(12MHz) to CLK2 freq*/
-+ /*Based on MCLKDIV it will be 128fs (MCLKDIV=1) or 256fs mode (MCLKDIV=0)*/
-+ /*BCLK will be MCLK/2 (MCLKDIV=1) or MCLK/4 (MCLKDIV=0) so BCLK is 64fs always*/
-+ ret = snd_soc_dai_set_pll(wm8804_dai, 0, 0, WM8804_CLKOUT_HZ, sr * 256);
-+ if (ret != 0) {
-+ dev_err(wm8804_codec->dev, "Failed to set OSC to CLK2 frequency: %d\n", ret);
-+ return ret;
-+ }
-+
-+ /*Set MCLK as PLL Output*/
-+ ret = snd_soc_dai_set_sysclk(wm8804_dai, WM8804_TX_CLKSRC_PLL, sr * 256, 0);
-+ if (ret != 0) {
-+ dev_err(wm8804_codec->dev, "Failed to set MCLK as PLL Output: %d\n", ret);
-+ return ret;
-+ }
-+
-+ /*Fix MCLKDIV=0 for 256fs to avoid any issues switching between TX and RX. RX always expects 256fs*/
-+ ret = snd_soc_dai_set_clkdiv(wm8804_dai, WM8804_MCLK_DIV, 0 );
-+ if (ret != 0) {
-+ dev_err(wm8804_codec->dev, "Failed to set MCLK_DIV to 256fs: %d\n", ret);
-+ return ret;
-+ }
-+
-+ /*Set CLKOUT as OSC Frequency*/
-+ ret = snd_soc_dai_set_sysclk(wm8804_dai, WM8804_CLKOUT_SRC_OSCCLK, WM8804_CLKOUT_HZ, 0);
-+ if (ret != 0) {
-+ dev_err(wm8804_codec->dev, "Failed to set CLKOUT as OSC Frequency: %d\n", ret);
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static int snd_rpi_wsp_hw_params(struct snd_pcm_substream *substream,
-+ struct snd_pcm_hw_params *params)
-+{
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct snd_soc_card *card = rtd->card;
-+ struct snd_soc_pcm_runtime *wm5102_rtd, *wm8804_rtd;
-+ struct snd_soc_codec *wm5102_codec, *wm8804_codec;
-+ struct snd_soc_dai *wm8804_codec_dai, *bcm_i2s_dai = rtd->cpu_dai;
-+ struct wm5102_machine_priv *priv = snd_soc_card_get_drvdata(card);
-+ int ret, capture_stream_opened,playback_stream_opened;
-+ unsigned int bclkratio, tx_mask, rx_mask;
-+ int width, num_slots=1;
-+
-+ wm5102_rtd = snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM5102].name);
-+ if (!wm5102_rtd) {
-+ dev_warn(card->dev, "snd_rpi_wsp_hw_params: couldn't get WM5102 rtd\n");
-+ return -EFAULT;
-+ }
-+ wm8804_rtd = snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM8804].name);
-+ if (!wm8804_rtd) {
-+ dev_warn(card->dev, "snd_rpi_wsp_hw_params: couldn't get WM8804 rtd\n");
-+ return -EFAULT;
-+ }
-+ wm5102_codec = wm5102_rtd->codec;
-+ wm8804_codec = wm8804_rtd->codec;
-+ wm8804_codec_dai = wm8804_rtd->codec_dai;
-+
-+ bclkratio = 2 * snd_pcm_format_physical_width(params_format(params));
-+
-+ ret = snd_soc_dai_set_bclk_ratio(bcm_i2s_dai, bclkratio);
-+ if (ret < 0) {
-+ dev_err(wm5102_codec->dev, "set_bclk_ratio failed: %d\n", ret);
-+ return ret;
-+ }
-+
-+ /*8804 supports sample rates from 32k only*/
-+ /*Setting <32k raises error from 8804 driver while setting the clock*/
-+ if(params_rate(params) >= 32000)
-+ {
-+ ret = snd_rpi_wsp_config_8804_clks(wm8804_codec, wm8804_codec_dai,
-+ params_rate(params));
-+
-+ if (ret != 0) {
-+ dev_err(wm8804_codec->dev, "snd_rpi_wsp_config_8804_clks failed: %d\n",
-+ ret);
-+ return ret;
-+ }
-+ }
-+
-+ capture_stream_opened =
-+ substream->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_opened;
-+ playback_stream_opened =
-+ substream->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_opened;
-+
-+ priv->wm5102_sr = params_rate(params);
-+
-+ ret = snd_rpi_wsp_config_5102_clks(priv, wm5102_codec, params_rate(params));
-+ if (ret != 0) {
-+ dev_err(wm5102_codec->dev, "snd_rpi_wsp_config_5102_clks failed: %d\n", ret);
-+ return ret;
-+ }
-+
-+ width = snd_pcm_format_physical_width(params_format(params));
-+
-+ if (capture_stream_opened) {
-+ tx_mask = 0;
-+ rx_mask = 1;
-+ }
-+ if (playback_stream_opened) {
-+ tx_mask = 1;
-+ rx_mask = 0;
-+ }
-+ ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, tx_mask, rx_mask, num_slots, width);
-+ if (ret < 0)
-+ return ret;
-+
-+ priv->wm8804_sr = params_rate(params);
-+
-+ return 0;
-+}
-+
-+static int dai_link2_params_fixup(struct snd_soc_dapm_widget *w, int event)
-+{
-+ struct snd_soc_card *card = &snd_rpi_wsp;
-+ struct wm5102_machine_priv *priv = snd_soc_card_get_drvdata(card);
-+ struct snd_soc_pcm_stream *config = w->params;
-+
-+ if (event == SND_SOC_DAPM_PRE_PMU) {
-+ config->rate_min = priv->wm8804_sr;
-+ config->rate_max = priv->wm8804_sr;
-+ } else if (event == SND_SOC_DAPM_PRE_PMD) {
-+ config->rate_min = RPI_WLF_SR;
-+ config->rate_max = RPI_WLF_SR;
-+ }
-+
-+ return 0;
-+}
-+
-+static int snd_rpi_wsp_hw_free(struct snd_pcm_substream *substream)
-+{
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct snd_soc_codec *wm5102_codec = rtd->codec;
-+ int ret,playback_stream_opened,capture_stream_opened;
-+
-+ playback_stream_opened = substream->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_opened;
-+
-+ capture_stream_opened = substream->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_opened;
-+
-+ if((playback_stream_opened + capture_stream_opened) == 1){
-+
-+ ret = snd_soc_codec_set_sysclk(wm5102_codec,
-+ ARIZONA_CLK_SYSCLK,
-+ ARIZONA_CLK_SRC_FLL1,
-+ 0,
-+ SND_SOC_CLOCK_IN);
-+
-+ if (ret != 0) {
-+ dev_err(wm5102_codec->dev, "Failed to set SYSCLK to Zero: %d\n", ret);
-+ return ret;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static struct snd_soc_ops snd_rpi_wsp_ops = {
-+ .hw_params = snd_rpi_wsp_hw_params,
-+ .hw_free = snd_rpi_wsp_hw_free,
-+};
-+
-+static struct snd_soc_pcm_stream dai_link2_params = {
-+ .formats = SNDRV_PCM_FMTBIT_S24_LE,
-+ .rate_min = RPI_WLF_SR,
-+ .rate_max = RPI_WLF_SR,
-+ .channels_min = 2,
-+ .channels_max = 2,
-+};
-+
-+static struct snd_soc_dai_link snd_rpi_wsp_dai[] = {
-+ {
-+ .name = "WM5102",
-+ .stream_name = "WM5102 AiFi",
-+ .cpu_dai_name = "bcm2708-i2s.0",
-+ .codec_dai_name = "wm5102-aif1",
-+ .platform_name = "bcm2708-i2s.0",
-+ .codec_name = "wm5102-codec",
-+ .dai_fmt = SND_SOC_DAIFMT_I2S
-+ | SND_SOC_DAIFMT_NB_NF
-+ | SND_SOC_DAIFMT_CBM_CFM,
-+ .ops = &snd_rpi_wsp_ops,
-+ },
-+ {
-+ .name = "WM5102 SPDIF",
-+ .stream_name = "SPDIF Tx/Rx",
-+ .cpu_dai_name = "wm5102-aif2",
-+ .codec_dai_name = "wm8804-spdif",
-+ .codec_name = "wm8804.1-003b",
-+ .dai_fmt = SND_SOC_DAIFMT_I2S
-+ | SND_SOC_DAIFMT_NB_NF
-+ | SND_SOC_DAIFMT_CBM_CFM,
-+ .ignore_suspend = 1,
-+ .params = &dai_link2_params,
-+ .params_fixup = dai_link2_params_fixup,
-+ },
-+};
-+
-+static int snd_rpi_wsp_late_probe(struct snd_soc_card *card)
-+{
-+ struct wm5102_machine_priv *priv = snd_soc_card_get_drvdata(card);
-+ struct snd_soc_pcm_runtime *wm5102_rtd, *wm8804_rtd;
-+ struct snd_soc_codec *wm5102_codec, *wm8804_codec;
-+ struct snd_soc_dai *wm5102_codec_dai, *wm8804_codec_dai, *wm8804_cpu_dai;
-+ int ret;
-+
-+ wm5102_rtd = snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM5102].name);
-+ if (!wm5102_rtd) {
-+ dev_warn(card->dev, "snd_rpi_wsp_late_probe: couldn't get WM5102 rtd\n");
-+ return -EFAULT;
-+ }
-+ wm8804_rtd = snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM8804].name);
-+ if (!wm8804_rtd) {
-+ dev_warn(card->dev, "snd_rpi_wsp_late_probe: couldn't get WM8804 rtd\n");
-+ return -EFAULT;
-+ }
-+ wm5102_codec = wm5102_rtd->codec;
-+ wm5102_codec_dai = wm5102_rtd->codec_dai;
-+ wm8804_codec = wm8804_rtd->codec;
-+ wm8804_codec_dai = wm8804_rtd->codec_dai;
-+ wm8804_cpu_dai = wm8804_rtd->cpu_dai;
-+
-+ priv->wm8804_sr = RPI_WLF_SR;
-+ priv->wm5102_sr = RPI_WLF_SR;
-+ priv->sync_path_enable = 0;
-+
-+ ret = snd_soc_codec_set_sysclk(wm5102_codec, ARIZONA_CLK_SYSCLK, ARIZONA_CLK_SRC_FLL1,
-+ 0, SND_SOC_CLOCK_IN);
-+ if (ret != 0) {
-+ dev_err(wm5102_codec->dev, "Failed to set SYSCLK to Zero: %d\n", ret);
-+ return ret;
-+ }
-+
-+ ret = snd_rpi_wsp_config_8804_clks(wm8804_codec, wm8804_codec_dai, RPI_WLF_SR);
-+
-+ if (ret != 0) {
-+ dev_err(wm8804_codec->dev, "snd_rpi_wsp_config_8804_clks failed: %d\n", ret);
-+ return ret;
-+ }
-+
-+ ret = snd_soc_dai_set_sysclk(wm5102_codec_dai, ARIZONA_CLK_SYSCLK, 0, 0);
-+ if (ret != 0) {
-+ dev_err(wm5102_codec_dai->dev, "Failed to set codec dai clk domain: %d\n", ret);
-+ return ret;
-+ }
-+
-+ ret = snd_soc_dai_set_sysclk(wm8804_cpu_dai, ARIZONA_CLK_SYSCLK, 0, 0);
-+ if (ret != 0) {
-+ dev_err(wm8804_cpu_dai->dev, "Failed to set codec dai clk domain: %d\n", ret);
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+/* audio machine driver */
-+static struct snd_soc_card snd_rpi_wsp = {
-+ .name = "snd_rpi_wsp",
-+ .owner = THIS_MODULE,
-+ .dai_link = snd_rpi_wsp_dai,
-+ .num_links = ARRAY_SIZE(snd_rpi_wsp_dai),
-+ .late_probe = snd_rpi_wsp_late_probe,
-+ .controls = rpi_wsp_controls,
-+ .num_controls = ARRAY_SIZE(rpi_wsp_controls),
-+ .dapm_widgets = rpi_wsp_dapm_widgets,
-+ .num_dapm_widgets = ARRAY_SIZE(rpi_wsp_dapm_widgets),
-+ .dapm_routes = rpi_wsp_dapm_routes,
-+ .num_dapm_routes = ARRAY_SIZE(rpi_wsp_dapm_routes),
-+ .set_bias_level = rpi_set_bias_level,
-+};
-+
-+static int snd_rpi_wsp_probe(struct platform_device *pdev)
-+{
-+ int ret = 0;
-+ struct wm5102_machine_priv *wm5102;
-+
-+ wm5102 = kzalloc(sizeof *wm5102, GFP_KERNEL);
-+ if (!wm5102)
-+ return -ENOMEM;
-+
-+ wm5102->fll1_freq = 0;
-+ mutex_init(&wm5102->fll1_mutex);
-+
-+ snd_soc_card_set_drvdata(&snd_rpi_wsp, wm5102);
-+
-+ if (pdev->dev.of_node) {
-+ struct device_node *i2s_node;
-+ struct snd_soc_dai_link *dai = &snd_rpi_wsp_dai[DAI_WM5102];
-+ 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;
-+ }
-+ }
-+
-+ snd_rpi_wsp.dev = &pdev->dev;
-+ ret = snd_soc_register_card(&snd_rpi_wsp);
-+ if (ret) {
-+ if (ret == -EPROBE_DEFER)
-+ dev_dbg(&pdev->dev, "register card requested probe deferral\n");
-+ else
-+ dev_err(&pdev->dev, "Failed to register card: %d\n", ret);
-+
-+ kfree(wm5102);
-+ }
-+
-+ return ret;
-+}
-+
-+static int snd_rpi_wsp_remove(struct platform_device *pdev)
-+{
-+ struct snd_soc_card *card = &snd_rpi_wsp;
-+ struct wm5102_machine_priv *wm5102 = snd_soc_card_get_drvdata(card);
-+
-+ snd_soc_unregister_card(&snd_rpi_wsp);
-+ kfree(wm5102);
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_OF
-+static const struct of_device_id snd_rpi_wsp_of_match[] = {
-+ { .compatible = "wlf,rpi-wm5102", },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, snd_rpi_wsp_of_match);
-+#endif /* CONFIG_OF */
-+
-+static struct platform_driver snd_rpi_wsp_driver = {
-+ .driver = {
-+ .name = "snd-rpi-wsp",
-+ .owner = THIS_MODULE,
-+ .of_match_table = of_match_ptr(snd_rpi_wsp_of_match),
-+ },
-+ .probe = snd_rpi_wsp_probe,
-+ .remove = snd_rpi_wsp_remove,
-+};
-+
-+module_platform_driver(snd_rpi_wsp_driver);
-+
-+MODULE_AUTHOR("Nikesh Oswal");
-+MODULE_AUTHOR("Liu Xin");
-+MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to Cirrus sound pi");
-+MODULE_LICENSE("GPL");
-diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
-index 93b4008..1be8d2e 100644
---- a/sound/soc/codecs/arizona.c
-+++ b/sound/soc/codecs/arizona.c
-@@ -1095,7 +1095,7 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
- unsigned int reg;
- unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
- unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
-- unsigned int *clk;
-+ int *clk;
-
- switch (clk_id) {
- case ARIZONA_CLK_SYSCLK:
-@@ -1375,6 +1375,9 @@ static int arizona_startup(struct snd_pcm_substream *substream,
- const struct snd_pcm_hw_constraint_list *constraint;
- unsigned int base_rate;
-
-+ if (!substream->runtime)
-+ return 0;
-+
- switch (dai_priv->clk) {
- case ARIZONA_CLK_SYSCLK:
- base_rate = priv->sysclk;
-@@ -2093,9 +2096,9 @@ static int arizona_enable_fll(struct arizona_fll *fll)
- /* Facilitate smooth refclk across the transition */
- regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9,
- ARIZONA_FLL1_GAIN_MASK, 0);
-- regmap_update_bits_async(fll->arizona->regmap, fll->base + 1,
-- ARIZONA_FLL1_FREERUN,
-- ARIZONA_FLL1_FREERUN);
-+ regmap_update_bits(fll->arizona->regmap, fll->base + 1,
-+ ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
-+ udelay(32);
- }
-
- /*
-@@ -2180,6 +2183,8 @@ static void arizona_disable_fll(struct arizona_fll *fll)
- {
- struct arizona *arizona = fll->arizona;
- bool change;
-+ int i;
-+ unsigned int val;
-
- regmap_update_bits_async(arizona->regmap, fll->base + 1,
- ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
-@@ -2190,6 +2195,25 @@ static void arizona_disable_fll(struct arizona_fll *fll)
- regmap_update_bits_async(arizona->regmap, fll->base + 1,
- ARIZONA_FLL1_FREERUN, 0);
-
-+ arizona_fll_dbg(fll, "Waiting for FLL disable...\n");
-+ val = 0;
-+ for (i = 0; i < 15; i++) {
-+ if (i < 5)
-+ usleep_range(200, 400);
-+ else
-+ msleep(20);
-+
-+ regmap_read(arizona->regmap,
-+ ARIZONA_INTERRUPT_RAW_STATUS_5,
-+ &val);
-+ if (!(val & (ARIZONA_FLL1_CLOCK_OK_STS << (fll->id - 1))))
-+ break;
-+ }
-+ if (i == 15)
-+ arizona_fll_warn(fll, "Timed out waiting for disable\n");
-+ else
-+ arizona_fll_dbg(fll, "FLL disabled (%d polls)\n", i);
-+
- if (change)
- pm_runtime_put_autosuspend(arizona->dev);
- }
-diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
-index a1305f8..31f36e6 100644
---- a/sound/soc/soc-core.c
-+++ b/sound/soc/soc-core.c
-@@ -1295,7 +1295,7 @@ static int soc_link_dai_widgets(struct snd_soc_card *card,
- if (play_w && capture_w) {
- ret = snd_soc_dapm_new_pcm(card, dai_link->params,
- dai_link->num_params, capture_w,
-- play_w);
-+ play_w, dai_link);
- if (ret != 0) {
- dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
- play_w->name, capture_w->name, ret);
-@@ -1308,7 +1308,7 @@ static int soc_link_dai_widgets(struct snd_soc_card *card,
- if (play_w && capture_w) {
- ret = snd_soc_dapm_new_pcm(card, dai_link->params,
- dai_link->num_params, capture_w,
-- play_w);
-+ play_w, dai_link);
- if (ret != 0) {
- dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
- play_w->name, capture_w->name, ret);
-diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
-index afb70a5..104888d 100644
---- a/sound/soc/soc-dapm.c
-+++ b/sound/soc/soc-dapm.c
-@@ -3450,11 +3450,12 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
- {
- struct snd_soc_dapm_path *source_p, *sink_p;
- struct snd_soc_dai *source, *sink;
-- const struct snd_soc_pcm_stream *config = w->params + w->params_select;
-+ struct snd_soc_pcm_stream *config = w->params + w->params_select;
-+ struct snd_soc_dai_link *dai_link = w->priv;
- struct snd_pcm_substream substream;
- struct snd_pcm_hw_params *params = NULL;
- u64 fmt;
-- int ret;
-+ int ret = 0;
-
- if (WARN_ON(!config) ||
- WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) ||
-@@ -3472,6 +3473,16 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
- source = source_p->source->priv;
- sink = sink_p->sink->priv;
-
-+ if (dai_link && dai_link->params_fixup) {
-+ ret = dai_link->params_fixup(w, event);
-+ if (ret < 0) {
-+ dev_err(w->dapm->dev,
-+ "ASoC: params_fixup for dai link widget failed %d\n",
-+ ret);
-+ goto out;
-+ }
-+ }
-+
- /* Be a little careful as we don't want to overflow the mask array */
- if (config->formats) {
- fmt = ffs(config->formats) - 1;
-@@ -3601,10 +3612,11 @@ static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol,
- }
-
- int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
-- const struct snd_soc_pcm_stream *params,
-+ struct snd_soc_pcm_stream *params,
- unsigned int num_params,
- struct snd_soc_dapm_widget *source,
-- struct snd_soc_dapm_widget *sink)
-+ struct snd_soc_dapm_widget *sink,
-+ void *priv)
- {
- struct snd_soc_dapm_widget template;
- struct snd_soc_dapm_widget *w;
-@@ -3706,6 +3718,7 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
-
- w->params = params;
- w->num_params = num_params;
-+ w->priv = priv;
-
- ret = snd_soc_dapm_add_path(&card->dapm, source, w, NULL, NULL);
- if (ret)