Merge tag 'asoc-fix-v5.7-rc2' of https://git.kernel.org/pub/scm/linux/kernel/git...
authorTakashi Iwai <tiwai@suse.de>
Tue, 21 Apr 2020 19:41:36 +0000 (21:41 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 21 Apr 2020 19:41:36 +0000 (21:41 +0200)
ASoC: Fixes for v5.7

Quite a lot of fixes here, a lot of driver specific ones but the biggest
one is the revert of changes to the startup and shutdown sequence for
DAIs that went in during the merge window - they broke some older x86
platforms and attempts to fix them didn't succeed so it's safer to just
roll them back and try to make sure those platforms are handled properly
in any future attempt.

The rockchip S/PDIF DT stuff was IIRC for validation issues.

32 files changed:
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
Documentation/devicetree/bindings/sound/rockchip-spdif.txt [deleted file]
Documentation/devicetree/bindings/sound/rockchip-spdif.yaml [new file with mode: 0644]
include/sound/soc-dai.h
include/sound/soc.h
sound/soc/amd/acp3x-rt5682-max9836.c
sound/soc/codecs/Kconfig
sound/soc/codecs/hdac_hdmi.c
sound/soc/codecs/madera.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/sgtl5000.h
sound/soc/codecs/tas571x.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wsa881x.c
sound/soc/intel/common/soc-acpi-intel-cml-match.c
sound/soc/intel/common/soc-acpi-intel-icl-match.c
sound/soc/meson/axg-card.c
sound/soc/meson/gx-card.c
sound/soc/qcom/apq8096.c
sound/soc/qcom/qdsp6/q6afe-dai.c
sound/soc/qcom/sdm845.c
sound/soc/samsung/s3c-i2s-v2.c
sound/soc/samsung/s3c2412-i2s.c
sound/soc/sh/rcar/ssi.c
sound/soc/sh/rcar/ssiu.c
sound/soc/soc-dai.c
sound/soc/soc-dapm.c
sound/soc/soc-pcm.c
sound/soc/soc-topology.c
sound/soc/sof/intel/bdw.c
sound/soc/sof/intel/byt.c
sound/soc/stm/stm32_sai_sub.c

index 7cd0e27..a3ba218 100644 (file)
@@ -56,6 +56,9 @@ properties:
       - const: tx
       - const: rx
 
+  power-domains:
+    maxItems: 1
+
   rockchip,capture-channels:
     allOf:
       - $ref: /schemas/types.yaml#/definitions/uint32
diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.txt b/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
deleted file mode 100644 (file)
index ec20c12..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-* Rockchip SPDIF transceiver
-
-The S/PDIF audio block is a stereo transceiver that allows the
-processor to receive and transmit digital audio via an coaxial cable or
-a fibre cable.
-
-Required properties:
-
-- compatible: should be one of the following:
-   - "rockchip,rk3066-spdif"
-   - "rockchip,rk3188-spdif"
-   - "rockchip,rk3228-spdif"
-   - "rockchip,rk3288-spdif"
-   - "rockchip,rk3328-spdif"
-   - "rockchip,rk3366-spdif"
-   - "rockchip,rk3368-spdif"
-   - "rockchip,rk3399-spdif"
-- reg: physical base address of the controller and length of memory mapped
-  region.
-- interrupts: should contain the SPDIF interrupt.
-- dmas: DMA specifiers for tx dma. See the DMA client binding,
-  Documentation/devicetree/bindings/dma/dma.txt
-- dma-names: should be "tx"
-- clocks: a list of phandle + clock-specifier pairs, one for each entry
-  in clock-names.
-- clock-names: should contain following:
-   - "hclk": clock for SPDIF controller
-   - "mclk" : clock for SPDIF bus
-
-Required properties on RK3288:
-  - rockchip,grf: the phandle of the syscon node for the general register
-                   file (GRF)
-
-Example for the rk3188 SPDIF controller:
-
-spdif: spdif@1011e000 {
-       compatible = "rockchip,rk3188-spdif", "rockchip,rk3066-spdif";
-       reg = <0x1011e000 0x2000>;
-       interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
-       dmas = <&dmac1_s 8>;
-       dma-names = "tx";
-       clock-names = "hclk", "mclk";
-       clocks = <&cru HCLK_SPDIF>, <&cru SCLK_SPDIF>;
-       #sound-dai-cells = <0>;
-};
diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml b/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml
new file mode 100644 (file)
index 0000000..c467152
--- /dev/null
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/rockchip-spdif.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip SPDIF transceiver
+
+description:
+  The S/PDIF audio block is a stereo transceiver that allows the
+  processor to receive and transmit digital audio via a coaxial or
+  fibre cable.
+
+maintainers:
+  - Heiko Stuebner <heiko@sntech.de>
+
+properties:
+  compatible:
+    oneOf:
+      - const: rockchip,rk3066-spdif
+      - const: rockchip,rk3228-spdif
+      - const: rockchip,rk3328-spdif
+      - const: rockchip,rk3366-spdif
+      - const: rockchip,rk3368-spdif
+      - const: rockchip,rk3399-spdif
+      - items:
+          - enum:
+            - rockchip,rk3188-spdif
+            - rockchip,rk3288-spdif
+          - const: rockchip,rk3066-spdif
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: clock for SPDIF bus
+      - description: clock for SPDIF controller
+
+  clock-names:
+    items:
+      - const: mclk
+      - const: hclk
+
+  dmas:
+    maxItems: 1
+
+  dma-names:
+    const: tx
+
+  power-domains:
+    maxItems: 1
+
+  rockchip,grf:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      The phandle of the syscon node for the GRF register.
+      Required property on RK3288.
+
+  "#sound-dai-cells":
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - dmas
+  - dma-names
+  - "#sound-dai-cells"
+
+if:
+  properties:
+    compatible:
+      contains:
+        const: rockchip,rk3288-spdif
+
+then:
+  required:
+    - rockchip,grf
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/rk3188-cru.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    spdif: spdif@1011e000 {
+      compatible = "rockchip,rk3188-spdif", "rockchip,rk3066-spdif";
+      reg = <0x1011e000 0x2000>;
+      interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+      clocks = <&cru SCLK_SPDIF>, <&cru HCLK_SPDIF>;
+      clock-names = "mclk", "hclk";
+      dmas = <&dmac1_s 8>;
+      dma-names = "tx";
+      #sound-dai-cells = <0>;
+    };
index d4825b8..b33abe9 100644 (file)
@@ -351,7 +351,6 @@ struct snd_soc_dai {
 
        /* bit field */
        unsigned int probed:1;
-       unsigned int started[SNDRV_PCM_STREAM_LAST + 1];
 };
 
 static inline struct snd_soc_pcm_stream *
index 13458e4..946f88a 100644 (file)
@@ -790,6 +790,9 @@ struct snd_soc_dai_link {
        const struct snd_soc_pcm_stream *params;
        unsigned int num_params;
 
+       struct snd_soc_dapm_widget *playback_widget;
+       struct snd_soc_dapm_widget *capture_widget;
+
        unsigned int dai_fmt;           /* format to set on init */
 
        enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */
index 024a7ee..e499c00 100644 (file)
@@ -89,9 +89,9 @@ static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd)
        }
 
        snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
-       snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
-       snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
-       snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
+       snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+       snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+       snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
 
        ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
        if (ret) {
index e6a0c5d..e60e0b6 100644 (file)
@@ -1525,6 +1525,7 @@ config SND_SOC_WM8804_SPI
 
 config SND_SOC_WM8900
        tristate
+       depends on SND_SOC_I2C_AND_SPI
 
 config SND_SOC_WM8903
        tristate "Wolfson Microelectronics WM8903 CODEC"
@@ -1576,6 +1577,7 @@ config SND_SOC_WM8985
 
 config SND_SOC_WM8988
        tristate
+       depends on SND_SOC_I2C_AND_SPI
 
 config SND_SOC_WM8990
        tristate
@@ -1594,6 +1596,7 @@ config SND_SOC_WM8994
 
 config SND_SOC_WM8995
        tristate
+       depends on SND_SOC_I2C_AND_SPI
 
 config SND_SOC_WM8996
        tristate
index fba9b74..f26b77f 100644 (file)
@@ -142,14 +142,14 @@ static struct hdac_hdmi_pcm *
 hdac_hdmi_get_pcm_from_cvt(struct hdac_hdmi_priv *hdmi,
                           struct hdac_hdmi_cvt *cvt)
 {
-       struct hdac_hdmi_pcm *pcm = NULL;
+       struct hdac_hdmi_pcm *pcm;
 
        list_for_each_entry(pcm, &hdmi->pcm_list, head) {
                if (pcm->cvt == cvt)
-                       break;
+                       return pcm;
        }
 
-       return pcm;
+       return NULL;
 }
 
 static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm,
index 40de9d7..a448d2a 100644 (file)
@@ -1903,7 +1903,6 @@ const struct soc_enum madera_isrc_fsh[] = {
                              MADERA_ISRC4_FSH_SHIFT, 0xf,
                              MADERA_RATE_ENUM_SIZE,
                              madera_rate_text, madera_rate_val),
-
 };
 EXPORT_SYMBOL_GPL(madera_isrc_fsh);
 
@@ -1924,7 +1923,6 @@ const struct soc_enum madera_isrc_fsl[] = {
                              MADERA_ISRC4_FSL_SHIFT, 0xf,
                              MADERA_RATE_ENUM_SIZE,
                              madera_rate_text, madera_rate_val),
-
 };
 EXPORT_SYMBOL_GPL(madera_isrc_fsl);
 
@@ -1938,7 +1936,6 @@ const struct soc_enum madera_asrc1_rate[] = {
                              MADERA_ASYNC_RATE_ENUM_SIZE,
                              madera_rate_text + MADERA_SYNC_RATE_ENUM_SIZE,
                              madera_rate_val + MADERA_SYNC_RATE_ENUM_SIZE),
-
 };
 EXPORT_SYMBOL_GPL(madera_asrc1_rate);
 
@@ -1964,7 +1961,6 @@ const struct soc_enum madera_asrc2_rate[] = {
                              MADERA_ASYNC_RATE_ENUM_SIZE,
                              madera_rate_text + MADERA_SYNC_RATE_ENUM_SIZE,
                              madera_rate_val + MADERA_SYNC_RATE_ENUM_SIZE),
-
 };
 EXPORT_SYMBOL_GPL(madera_asrc2_rate);
 
index d513019..e8a8bf7 100644 (file)
@@ -1653,6 +1653,40 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
                dev_err(&client->dev,
                        "Error %d initializing CHIP_CLK_CTRL\n", ret);
 
+       /* Mute everything to avoid pop from the following power-up */
+       ret = regmap_write(sgtl5000->regmap, SGTL5000_CHIP_ANA_CTRL,
+                          SGTL5000_CHIP_ANA_CTRL_DEFAULT);
+       if (ret) {
+               dev_err(&client->dev,
+                       "Error %d muting outputs via CHIP_ANA_CTRL\n", ret);
+               goto disable_clk;
+       }
+
+       /*
+        * If VAG is powered-on (e.g. from previous boot), it would be disabled
+        * by the write to ANA_POWER in later steps of the probe code. This
+        * may create a loud pop even with all outputs muted. The proper way
+        * to circumvent this is disabling the bit first and waiting the proper
+        * cool-down time.
+        */
+       ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ANA_POWER, &value);
+       if (ret) {
+               dev_err(&client->dev, "Failed to read ANA_POWER: %d\n", ret);
+               goto disable_clk;
+       }
+       if (value & SGTL5000_VAG_POWERUP) {
+               ret = regmap_update_bits(sgtl5000->regmap,
+                                        SGTL5000_CHIP_ANA_POWER,
+                                        SGTL5000_VAG_POWERUP,
+                                        0);
+               if (ret) {
+                       dev_err(&client->dev, "Error %d disabling VAG\n", ret);
+                       goto disable_clk;
+               }
+
+               msleep(SGTL5000_VAG_POWERDOWN_DELAY);
+       }
+
        /* Follow section 2.2.1.1 of AN3663 */
        ana_pwr = SGTL5000_ANA_POWER_DEFAULT;
        if (sgtl5000->num_supplies <= VDDD) {
index a4bf4bc..56ec586 100644 (file)
 /*
  * SGTL5000_CHIP_ANA_CTRL
  */
+#define SGTL5000_CHIP_ANA_CTRL_DEFAULT         0x0133
 #define SGTL5000_LINE_OUT_MUTE                 0x0100
 #define SGTL5000_HP_SEL_MASK                   0x0040
 #define SGTL5000_HP_SEL_SHIFT                  6
index 1554631..5b7f9fc 100644 (file)
@@ -820,8 +820,10 @@ static int tas571x_i2c_probe(struct i2c_client *client,
 
        priv->regmap = devm_regmap_init(dev, NULL, client,
                                        priv->chip->regmap_config);
-       if (IS_ERR(priv->regmap))
-               return PTR_ERR(priv->regmap);
+       if (IS_ERR(priv->regmap)) {
+               ret = PTR_ERR(priv->regmap);
+               goto disable_regs;
+       }
 
        priv->pdn_gpio = devm_gpiod_get_optional(dev, "pdn", GPIOD_OUT_LOW);
        if (IS_ERR(priv->pdn_gpio)) {
@@ -845,7 +847,7 @@ static int tas571x_i2c_probe(struct i2c_client *client,
 
        ret = regmap_write(priv->regmap, TAS571X_OSC_TRIM_REG, 0);
        if (ret)
-               return ret;
+               goto disable_regs;
 
        usleep_range(50000, 60000);
 
@@ -861,12 +863,20 @@ static int tas571x_i2c_probe(struct i2c_client *client,
                 */
                ret = regmap_update_bits(priv->regmap, TAS571X_MVOL_REG, 1, 0);
                if (ret)
-                       return ret;
+                       goto disable_regs;
        }
 
-       return devm_snd_soc_register_component(&client->dev,
+       ret = devm_snd_soc_register_component(&client->dev,
                                      &priv->component_driver,
                                      &tas571x_dai, 1);
+       if (ret)
+               goto disable_regs;
+
+       return ret;
+
+disable_regs:
+       regulator_bulk_disable(priv->chip->num_supply_names, priv->supplies);
+       return ret;
 }
 
 static int tas571x_i2c_remove(struct i2c_client *client)
index 55112c1..6cf0f66 100644 (file)
@@ -860,8 +860,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
 
        wm8960->is_stream_in_use[tx] = true;
 
-       if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_ON &&
-           !wm8960->is_stream_in_use[!tx])
+       if (!wm8960->is_stream_in_use[!tx])
                return wm8960_configure_clocking(component);
 
        return 0;
index f2d6f2f..d39d479 100644 (file)
@@ -394,6 +394,7 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = {
                .min_ch = 1,
                .max_ch = 1,
                .simple_ch_prep_sm = true,
+               .read_only_wordlength = true,
        }, {
                /* COMP */
                .num = 2,
@@ -401,6 +402,7 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = {
                .min_ch = 1,
                .max_ch = 1,
                .simple_ch_prep_sm = true,
+               .read_only_wordlength = true,
        }, {
                /* BOOST */
                .num = 3,
@@ -408,6 +410,7 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = {
                .min_ch = 1,
                .max_ch = 1,
                .simple_ch_prep_sm = true,
+               .read_only_wordlength = true,
        }, {
                /* VISENSE */
                .num = 4,
@@ -415,6 +418,7 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = {
                .min_ch = 1,
                .max_ch = 1,
                .simple_ch_prep_sm = true,
+               .read_only_wordlength = true,
        }
 };
 
index bcedec6..7d85bd5 100644 (file)
@@ -113,14 +113,6 @@ static const struct snd_soc_acpi_adr_device rt1308_1_adr[] = {
        }
 };
 
-static const struct snd_soc_acpi_adr_device rt1308_2_adr[] = {
-       {
-               .adr = 0x000210025D130800,
-               .num_endpoints = 1,
-               .endpoints = &single_endpoint,
-       }
-};
-
 static const struct snd_soc_acpi_adr_device rt1308_1_group1_adr[] = {
        {
                .adr = 0x000110025D130800,
index ef85003..16ec9f3 100644 (file)
@@ -87,14 +87,6 @@ static const struct snd_soc_acpi_adr_device rt1308_1_adr[] = {
        }
 };
 
-static const struct snd_soc_acpi_adr_device rt1308_2_adr[] = {
-       {
-               .adr = 0x000210025D130800,
-               .num_endpoints = 1,
-               .endpoints = &single_endpoint,
-       }
-};
-
 static const struct snd_soc_acpi_adr_device rt1308_1_group1_adr[] = {
        {
                .adr = 0x000110025D130800,
index af46845..89f7f64 100644 (file)
@@ -338,8 +338,10 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np,
 
        if (axg_card_cpu_is_tdm_iface(dai_link->cpus->of_node))
                ret = axg_card_parse_tdm(card, np, index);
-       else if (axg_card_cpu_is_codec(dai_link->cpus->of_node))
+       else if (axg_card_cpu_is_codec(dai_link->cpus->of_node)) {
                dai_link->params = &codec_params;
+               dai_link->no_pcm = 0; /* link is not a DPCM BE */
+       }
 
        return ret;
 }
index 7b01dcb..4abf7ef 100644 (file)
@@ -108,8 +108,10 @@ static int gx_card_add_link(struct snd_soc_card *card, struct device_node *np,
                ret = gx_card_parse_i2s(card, np, index);
 
        /* Or apply codec to codec params if necessary */
-       else if (gx_card_cpu_identify(dai_link->cpus, "CODEC CTRL"))
+       else if (gx_card_cpu_identify(dai_link->cpus, "CODEC CTRL")) {
                dai_link->params = &codec_params;
+               dai_link->no_pcm = 0; /* link is not a DPCM BE */
+       }
 
        return ret;
 }
index d55e3ad..287ad2a 100644 (file)
@@ -116,10 +116,8 @@ static int apq8096_platform_probe(struct platform_device *pdev)
        card->dev = dev;
        dev_set_drvdata(dev, card);
        ret = qcom_snd_parse_of(card);
-       if (ret) {
-               dev_err(dev, "Error parsing OF data\n");
+       if (ret)
                goto err;
-       }
 
        apq8096_add_be_ops(card);
        ret = snd_soc_register_card(card);
index c1a7624..2a5302f 100644 (file)
@@ -902,6 +902,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE |
                                   SNDRV_PCM_FMTBIT_S24_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
@@ -917,6 +919,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE |
                                   SNDRV_PCM_FMTBIT_S24_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
@@ -931,6 +935,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                        .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
@@ -946,6 +952,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE |
                                   SNDRV_PCM_FMTBIT_S24_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
@@ -960,6 +968,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                        .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
@@ -975,6 +985,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE |
                                   SNDRV_PCM_FMTBIT_S24_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
@@ -989,6 +1001,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                        .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
@@ -1004,6 +1018,8 @@ static struct snd_soc_dai_driver q6afe_dais[] = {
                                 SNDRV_PCM_RATE_16000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE |
                                   SNDRV_PCM_FMTBIT_S24_LE,
+                       .channels_min = 1,
+                       .channels_max = 8,
                        .rate_min =     8000,
                        .rate_max =     48000,
                },
index b2de65c..68e9388 100644 (file)
@@ -559,10 +559,8 @@ static int sdm845_snd_platform_probe(struct platform_device *pdev)
        card->dev = dev;
        dev_set_drvdata(dev, card);
        ret = qcom_snd_parse_of(card);
-       if (ret) {
-               dev_err(dev, "Error parsing OF data\n");
+       if (ret)
                goto parse_dt_fail;
-       }
 
        data->card = card;
        snd_soc_card_set_drvdata(card, data);
index 3588878..5e95c30 100644 (file)
@@ -656,60 +656,6 @@ void s3c_i2sv2_cleanup(struct snd_soc_dai *dai,
 }
 EXPORT_SYMBOL_GPL(s3c_i2sv2_cleanup);
 
-#ifdef CONFIG_PM
-static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
-{
-       struct s3c_i2sv2_info *i2s = to_info(dai);
-       u32 iismod;
-
-       if (dai->active) {
-               i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
-               i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
-               i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
-
-               /* some basic suspend checks */
-
-               iismod = readl(i2s->regs + S3C2412_IISMOD);
-
-               if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
-                       pr_warn("%s: RXDMA active?\n", __func__);
-
-               if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
-                       pr_warn("%s: TXDMA active?\n", __func__);
-
-               if (iismod & S3C2412_IISCON_IIS_ACTIVE)
-                       pr_warn("%s: IIS active\n", __func__);
-       }
-
-       return 0;
-}
-
-static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
-{
-       struct s3c_i2sv2_info *i2s = to_info(dai);
-
-       pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
-               dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
-
-       if (dai->active) {
-               writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
-               writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
-               writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
-
-               writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
-                      i2s->regs + S3C2412_IISFIC);
-
-               ndelay(250);
-               writel(0x0, i2s->regs + S3C2412_IISFIC);
-       }
-
-       return 0;
-}
-#else
-#define s3c2412_i2s_suspend NULL
-#define s3c2412_i2s_resume  NULL
-#endif
-
 int s3c_i2sv2_register_component(struct device *dev, int id,
                           const struct snd_soc_component_driver *cmp_drv,
                           struct snd_soc_dai_driver *dai_drv)
@@ -727,9 +673,6 @@ int s3c_i2sv2_register_component(struct device *dev, int id,
        if (!ops->delay)
                ops->delay = s3c2412_i2s_delay;
 
-       dai_drv->suspend = s3c2412_i2s_suspend;
-       dai_drv->resume = s3c2412_i2s_resume;
-
        return devm_snd_soc_register_component(dev, cmp_drv, dai_drv, 1);
 }
 EXPORT_SYMBOL_GPL(s3c_i2sv2_register_component);
index 787a3f6..b35d828 100644 (file)
@@ -117,6 +117,60 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int s3c2412_i2s_suspend(struct snd_soc_component *component)
+{
+       struct s3c_i2sv2_info *i2s = snd_soc_component_get_drvdata(component);
+       u32 iismod;
+
+       if (component->active) {
+               i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
+               i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
+               i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
+
+               /* some basic suspend checks */
+
+               iismod = readl(i2s->regs + S3C2412_IISMOD);
+
+               if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
+                       pr_warn("%s: RXDMA active?\n", __func__);
+
+               if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
+                       pr_warn("%s: TXDMA active?\n", __func__);
+
+               if (iismod & S3C2412_IISCON_IIS_ACTIVE)
+                       pr_warn("%s: IIS active\n", __func__);
+       }
+
+       return 0;
+}
+
+static int s3c2412_i2s_resume(struct snd_soc_component *component)
+{
+       struct s3c_i2sv2_info *i2s = snd_soc_component_get_drvdata(component);
+
+       pr_info("component_active %d, IISMOD %08x, IISCON %08x\n",
+               component->active, i2s->suspend_iismod, i2s->suspend_iiscon);
+
+       if (component->active) {
+               writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
+               writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
+               writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
+
+               writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
+                      i2s->regs + S3C2412_IISFIC);
+
+               ndelay(250);
+               writel(0x0, i2s->regs + S3C2412_IISFIC);
+       }
+
+       return 0;
+}
+#else
+#define s3c2412_i2s_suspend NULL
+#define s3c2412_i2s_resume  NULL
+#endif
+
 #define S3C2412_I2S_RATES \
        (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
        SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
@@ -146,6 +200,8 @@ static struct snd_soc_dai_driver s3c2412_i2s_dai = {
 
 static const struct snd_soc_component_driver s3c2412_i2s_component = {
        .name           = "s3c2412-i2s",
+       .suspend        = s3c2412_i2s_suspend,
+       .resume         = s3c2412_i2s_resume,
 };
 
 static int s3c2412_iis_dev_probe(struct platform_device *pdev)
index fc5d089..4a7d341 100644 (file)
@@ -594,10 +594,16 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod,
         * Capture:  It might not receave data. Do nothing
         */
        if (rsnd_io_is_play(io)) {
-               rsnd_mod_write(mod, SSICR, cr | EN);
+               rsnd_mod_write(mod, SSICR, cr | ssi->cr_en);
                rsnd_ssi_status_check(mod, DIRQ);
        }
 
+       /* In multi-SSI mode, stop is performed by setting ssi0129 in
+        * SSI_CONTROL to 0 (in rsnd_ssio_stop_gen2). Do nothing here.
+        */
+       if (rsnd_ssi_multi_slaves_runtime(io))
+               return 0;
+
        /*
         * disable SSI,
         * and, wait idle state
@@ -737,6 +743,9 @@ static void rsnd_ssi_parent_attach(struct rsnd_mod *mod,
        if (!rsnd_rdai_is_clk_master(rdai))
                return;
 
+       if (rsnd_ssi_is_multi_slave(mod, io))
+               return;
+
        switch (rsnd_mod_id(mod)) {
        case 1:
        case 2:
index f35d882..9c7c3e7 100644 (file)
@@ -221,7 +221,7 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
                        i;
 
                for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) {
-                       shift   = (i * 4) + 16;
+                       shift   = (i * 4) + 20;
                        val     = (val & ~(0xF << shift)) |
                                rsnd_mod_id(pos) << shift;
                }
index 8f3cad8..31c4155 100644 (file)
@@ -295,24 +295,17 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai,
 {
        int ret = 0;
 
-       if (!dai->started[substream->stream] &&
-           dai->driver->ops->startup)
+       if (dai->driver->ops->startup)
                ret = dai->driver->ops->startup(substream, dai);
 
-       if (ret == 0)
-               dai->started[substream->stream] = 1;
-
        return ret;
 }
 
 void snd_soc_dai_shutdown(struct snd_soc_dai *dai,
                         struct snd_pcm_substream *substream)
 {
-       if (dai->started[substream->stream] &&
-           dai->driver->ops->shutdown)
+       if (dai->driver->ops->shutdown)
                dai->driver->ops->shutdown(substream, dai);
-
-       dai->started[substream->stream] = 0;
 }
 
 int snd_soc_dai_prepare(struct snd_soc_dai *dai,
index 679ed60..e263284 100644 (file)
@@ -423,7 +423,7 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
 
                        memset(&template, 0, sizeof(template));
                        template.reg = e->reg;
-                       template.mask = e->mask << e->shift_l;
+                       template.mask = e->mask;
                        template.shift = e->shift_l;
                        template.off_val = snd_soc_enum_item_to_val(e, 0);
                        template.on_val = template.off_val;
@@ -546,8 +546,22 @@ static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol,
        if (data->value == value)
                return false;
 
-       if (data->widget)
-               data->widget->on_val = value;
+       if (data->widget) {
+               switch (dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->id) {
+               case snd_soc_dapm_switch:
+               case snd_soc_dapm_mixer:
+               case snd_soc_dapm_mixer_named_ctl:
+                       data->widget->on_val = value & data->widget->mask;
+                       break;
+               case snd_soc_dapm_demux:
+               case snd_soc_dapm_mux:
+                       data->widget->on_val = value >> data->widget->shift;
+                       break;
+               default:
+                       data->widget->on_val = value;
+                       break;
+               }
+       }
 
        data->value = value;
 
@@ -4165,6 +4179,8 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card,
        w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template);
        if (IS_ERR(w)) {
                ret = PTR_ERR(w);
+               dev_err(rtd->dev, "ASoC: Failed to create %s widget: %d\n",
+                       link_name, ret);
                goto outfree_kcontrol_news;
        }
 
@@ -4283,52 +4299,58 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
        return 0;
 }
 
-static void dapm_add_valid_dai_widget(struct snd_soc_card *card,
-                                     struct snd_soc_pcm_runtime *rtd,
-                                     struct snd_soc_dai *codec_dai,
-                                     struct snd_soc_dai *cpu_dai)
+static void dapm_connect_dai_routes(struct snd_soc_dapm_context *dapm,
+                                   struct snd_soc_dai *src_dai,
+                                   struct snd_soc_dapm_widget *src,
+                                   struct snd_soc_dapm_widget *dai,
+                                   struct snd_soc_dai *sink_dai,
+                                   struct snd_soc_dapm_widget *sink)
 {
-       struct snd_soc_dapm_widget *playback = NULL, *capture = NULL;
-       struct snd_soc_dapm_widget *codec, *playback_cpu, *capture_cpu;
+       dev_dbg(dapm->dev, "connected DAI link %s:%s -> %s:%s\n",
+               src_dai->component->name, src->name,
+               sink_dai->component->name, sink->name);
+
+       if (dai) {
+               snd_soc_dapm_add_path(dapm, src, dai, NULL, NULL);
+               src = dai;
+       }
+
+       snd_soc_dapm_add_path(dapm, src, sink, NULL, NULL);
+}
+
+static void dapm_connect_dai_pair(struct snd_soc_card *card,
+                                 struct snd_soc_pcm_runtime *rtd,
+                                 struct snd_soc_dai *codec_dai,
+                                 struct snd_soc_dai *cpu_dai)
+{
+       struct snd_soc_dai_link *dai_link = rtd->dai_link;
+       struct snd_soc_dapm_widget *dai, *codec, *playback_cpu, *capture_cpu;
        struct snd_pcm_substream *substream;
        struct snd_pcm_str *streams = rtd->pcm->streams;
 
-       if (rtd->dai_link->params) {
+       if (dai_link->params) {
                playback_cpu = cpu_dai->capture_widget;
                capture_cpu = cpu_dai->playback_widget;
        } else {
-               playback = cpu_dai->playback_widget;
-               capture = cpu_dai->capture_widget;
-               playback_cpu = playback;
-               capture_cpu = capture;
+               playback_cpu = cpu_dai->playback_widget;
+               capture_cpu = cpu_dai->capture_widget;
        }
 
        /* connect BE DAI playback if widgets are valid */
        codec = codec_dai->playback_widget;
 
        if (playback_cpu && codec) {
-               if (!playback) {
+               if (dai_link->params && !dai_link->playback_widget) {
                        substream = streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
-                       playback = snd_soc_dapm_new_dai(card, substream,
-                                                       "playback");
-                       if (IS_ERR(playback)) {
-                               dev_err(rtd->dev,
-                                       "ASoC: Failed to create DAI %s: %ld\n",
-                                       codec_dai->name,
-                                       PTR_ERR(playback));
+                       dai = snd_soc_dapm_new_dai(card, substream, "playback");
+                       if (IS_ERR(dai))
                                goto capture;
-                       }
-
-                       snd_soc_dapm_add_path(&card->dapm, playback_cpu,
-                                             playback, NULL, NULL);
+                       dai_link->playback_widget = dai;
                }
 
-               dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
-                       cpu_dai->component->name, playback_cpu->name,
-                       codec_dai->component->name, codec->name);
-
-               snd_soc_dapm_add_path(&card->dapm, playback, codec,
-                                     NULL, NULL);
+               dapm_connect_dai_routes(&card->dapm, cpu_dai, playback_cpu,
+                                       dai_link->playback_widget,
+                                       codec_dai, codec);
        }
 
 capture:
@@ -4336,50 +4358,18 @@ capture:
        codec = codec_dai->capture_widget;
 
        if (codec && capture_cpu) {
-               if (!capture) {
+               if (dai_link->params && !dai_link->capture_widget) {
                        substream = streams[SNDRV_PCM_STREAM_CAPTURE].substream;
-                       capture = snd_soc_dapm_new_dai(card, substream,
-                                                      "capture");
-                       if (IS_ERR(capture)) {
-                               dev_err(rtd->dev,
-                                       "ASoC: Failed to create DAI %s: %ld\n",
-                                       codec_dai->name,
-                                       PTR_ERR(capture));
+                       dai = snd_soc_dapm_new_dai(card, substream, "capture");
+                       if (IS_ERR(dai))
                                return;
-                       }
-
-                       snd_soc_dapm_add_path(&card->dapm, capture,
-                                             capture_cpu, NULL, NULL);
+                       dai_link->capture_widget = dai;
                }
 
-               dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
-                       codec_dai->component->name, codec->name,
-                       cpu_dai->component->name, capture_cpu->name);
-
-               snd_soc_dapm_add_path(&card->dapm, codec, capture,
-                                     NULL, NULL);
-       }
-}
-
-static void dapm_connect_dai_link_widgets(struct snd_soc_card *card,
-                                         struct snd_soc_pcm_runtime *rtd)
-{
-       struct snd_soc_dai *codec_dai;
-       int i;
-
-       if (rtd->num_cpus == 1) {
-               for_each_rtd_codec_dais(rtd, i, codec_dai)
-                       dapm_add_valid_dai_widget(card, rtd, codec_dai,
-                                                 rtd->cpu_dais[0]);
-       } else if (rtd->num_codecs == rtd->num_cpus) {
-               for_each_rtd_codec_dais(rtd, i, codec_dai)
-                       dapm_add_valid_dai_widget(card, rtd, codec_dai,
-                                                 rtd->cpu_dais[i]);
-       } else {
-               dev_err(card->dev,
-                       "N cpus to M codecs link is not supported yet\n");
+               dapm_connect_dai_routes(&card->dapm, codec_dai, codec,
+                                       dai_link->capture_widget,
+                                       cpu_dai, capture_cpu);
        }
-
 }
 
 static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
@@ -4422,6 +4412,8 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
 void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
 {
        struct snd_soc_pcm_runtime *rtd;
+       struct snd_soc_dai *codec_dai;
+       int i;
 
        /* for each BE DAI link... */
        for_each_card_rtds(card, rtd)  {
@@ -4432,7 +4424,18 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
                if (rtd->dai_link->dynamic)
                        continue;
 
-               dapm_connect_dai_link_widgets(card, rtd);
+               if (rtd->num_cpus == 1) {
+                       for_each_rtd_codec_dais(rtd, i, codec_dai)
+                               dapm_connect_dai_pair(card, rtd, codec_dai,
+                                                     rtd->cpu_dais[0]);
+               } else if (rtd->num_codecs == rtd->num_cpus) {
+                       for_each_rtd_codec_dais(rtd, i, codec_dai)
+                               dapm_connect_dai_pair(card, rtd, codec_dai,
+                                                     rtd->cpu_dais[i]);
+               } else {
+                       dev_err(card->dev,
+                               "N cpus to M codecs link is not supported yet\n");
+               }
        }
 }
 
index 289aebc..1f302de 100644 (file)
@@ -2911,8 +2911,17 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
        int i;
 
        if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
-               playback = rtd->dai_link->dpcm_playback;
-               capture = rtd->dai_link->dpcm_capture;
+               cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+               if (rtd->num_cpus > 1) {
+                       dev_err(rtd->dev,
+                               "DPCM doesn't support Multi CPU yet\n");
+                       return -EINVAL;
+               }
+
+               playback = rtd->dai_link->dpcm_playback &&
+                          snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK);
+               capture = rtd->dai_link->dpcm_capture &&
+                         snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE);
        } else {
                /* Adapt stream for codec2codec links */
                int cpu_capture = rtd->dai_link->params ?
index 87f75ed..6df3b0d 100644 (file)
@@ -894,7 +894,13 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count,
                }
 
                /* create any TLV data */
-               soc_tplg_create_tlv(tplg, &kc, &mc->hdr);
+               err = soc_tplg_create_tlv(tplg, &kc, &mc->hdr);
+               if (err < 0) {
+                       dev_err(tplg->dev, "ASoC: failed to create TLV %s\n",
+                               mc->hdr.name);
+                       kfree(sm);
+                       continue;
+               }
 
                /* pass control to driver for optional further init */
                err = soc_tplg_init_kcontrol(tplg, &kc,
@@ -1118,6 +1124,7 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
        struct snd_soc_tplg_hdr *hdr)
 {
        struct snd_soc_tplg_ctl_hdr *control_hdr;
+       int ret;
        int i;
 
        if (tplg->pass != SOC_TPLG_PASS_MIXER) {
@@ -1146,25 +1153,30 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
                case SND_SOC_TPLG_CTL_RANGE:
                case SND_SOC_TPLG_DAPM_CTL_VOLSW:
                case SND_SOC_TPLG_DAPM_CTL_PIN:
-                       soc_tplg_dmixer_create(tplg, 1,
-                                              le32_to_cpu(hdr->payload_size));
+                       ret = soc_tplg_dmixer_create(tplg, 1,
+                                       le32_to_cpu(hdr->payload_size));
                        break;
                case SND_SOC_TPLG_CTL_ENUM:
                case SND_SOC_TPLG_CTL_ENUM_VALUE:
                case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
                case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
                case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
-                       soc_tplg_denum_create(tplg, 1,
-                                             le32_to_cpu(hdr->payload_size));
+                       ret = soc_tplg_denum_create(tplg, 1,
+                                       le32_to_cpu(hdr->payload_size));
                        break;
                case SND_SOC_TPLG_CTL_BYTES:
-                       soc_tplg_dbytes_create(tplg, 1,
-                                              le32_to_cpu(hdr->payload_size));
+                       ret = soc_tplg_dbytes_create(tplg, 1,
+                                       le32_to_cpu(hdr->payload_size));
                        break;
                default:
                        soc_bind_err(tplg, control_hdr, i);
                        return -EINVAL;
                }
+               if (ret < 0) {
+                       dev_err(tplg->dev, "ASoC: invalid control\n");
+                       return ret;
+               }
+
        }
 
        return 0;
@@ -1272,7 +1284,9 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
                routes[i]->dobj.index = tplg->index;
                list_add(&routes[i]->dobj.list, &tplg->comp->dobj_list);
 
-               soc_tplg_add_route(tplg, routes[i]);
+               ret = soc_tplg_add_route(tplg, routes[i]);
+               if (ret < 0)
+                       break;
 
                /* add route, but keep going if some fail */
                snd_soc_dapm_add_routes(dapm, routes[i], 1);
@@ -1355,7 +1369,13 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create(
                }
 
                /* create any TLV data */
-               soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr);
+               err = soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr);
+               if (err < 0) {
+                       dev_err(tplg->dev, "ASoC: failed to create TLV %s\n",
+                               mc->hdr.name);
+                       kfree(sm);
+                       continue;
+               }
 
                /* pass control to driver for optional further init */
                err = soc_tplg_init_kcontrol(tplg, &kc[i],
@@ -1766,10 +1786,13 @@ static int soc_tplg_dapm_complete(struct soc_tplg *tplg)
        return 0;
 }
 
-static void set_stream_info(struct snd_soc_pcm_stream *stream,
+static int set_stream_info(struct snd_soc_pcm_stream *stream,
        struct snd_soc_tplg_stream_caps *caps)
 {
        stream->stream_name = kstrdup(caps->name, GFP_KERNEL);
+       if (!stream->stream_name)
+               return -ENOMEM;
+
        stream->channels_min = le32_to_cpu(caps->channels_min);
        stream->channels_max = le32_to_cpu(caps->channels_max);
        stream->rates = le32_to_cpu(caps->rates);
@@ -1777,6 +1800,8 @@ static void set_stream_info(struct snd_soc_pcm_stream *stream,
        stream->rate_max = le32_to_cpu(caps->rate_max);
        stream->formats = le64_to_cpu(caps->formats);
        stream->sig_bits = le32_to_cpu(caps->sig_bits);
+
+       return 0;
 }
 
 static void set_dai_flags(struct snd_soc_dai_driver *dai_drv,
@@ -1812,20 +1837,29 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
        if (dai_drv == NULL)
                return -ENOMEM;
 
-       if (strlen(pcm->dai_name))
+       if (strlen(pcm->dai_name)) {
                dai_drv->name = kstrdup(pcm->dai_name, GFP_KERNEL);
+               if (!dai_drv->name) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+       }
        dai_drv->id = le32_to_cpu(pcm->dai_id);
 
        if (pcm->playback) {
                stream = &dai_drv->playback;
                caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
-               set_stream_info(stream, caps);
+               ret = set_stream_info(stream, caps);
+               if (ret < 0)
+                       goto err;
        }
 
        if (pcm->capture) {
                stream = &dai_drv->capture;
                caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE];
-               set_stream_info(stream, caps);
+               ret = set_stream_info(stream, caps);
+               if (ret < 0)
+                       goto err;
        }
 
        if (pcm->compress)
@@ -1835,11 +1869,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
        ret = soc_tplg_dai_load(tplg, dai_drv, pcm, NULL);
        if (ret < 0) {
                dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
-               kfree(dai_drv->playback.stream_name);
-               kfree(dai_drv->capture.stream_name);
-               kfree(dai_drv->name);
-               kfree(dai_drv);
-               return ret;
+               goto err;
        }
 
        dai_drv->dobj.index = tplg->index;
@@ -1860,6 +1890,14 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
                return ret;
        }
 
+       return 0;
+
+err:
+       kfree(dai_drv->playback.stream_name);
+       kfree(dai_drv->capture.stream_name);
+       kfree(dai_drv->name);
+       kfree(dai_drv);
+
        return ret;
 }
 
@@ -1916,11 +1954,20 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
        if (strlen(pcm->pcm_name)) {
                link->name = kstrdup(pcm->pcm_name, GFP_KERNEL);
                link->stream_name = kstrdup(pcm->pcm_name, GFP_KERNEL);
+               if (!link->name || !link->stream_name) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
        }
        link->id = le32_to_cpu(pcm->pcm_id);
 
-       if (strlen(pcm->dai_name))
+       if (strlen(pcm->dai_name)) {
                link->cpus->dai_name = kstrdup(pcm->dai_name, GFP_KERNEL);
+               if (!link->cpus->dai_name) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+       }
 
        link->codecs->name = "snd-soc-dummy";
        link->codecs->dai_name = "snd-soc-dummy-dai";
@@ -2088,7 +2135,9 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
                        _pcm = pcm;
                } else {
                        abi_match = false;
-                       pcm_new_ver(tplg, pcm, &_pcm);
+                       ret = pcm_new_ver(tplg, pcm, &_pcm);
+                       if (ret < 0)
+                               return ret;
                }
 
                /* create the FE DAIs and DAI links */
@@ -2436,13 +2485,17 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg,
        if (d->playback) {
                stream = &dai_drv->playback;
                caps = &d->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
-               set_stream_info(stream, caps);
+               ret = set_stream_info(stream, caps);
+               if (ret < 0)
+                       goto err;
        }
 
        if (d->capture) {
                stream = &dai_drv->capture;
                caps = &d->caps[SND_SOC_TPLG_STREAM_CAPTURE];
-               set_stream_info(stream, caps);
+               ret = set_stream_info(stream, caps);
+               if (ret < 0)
+                       goto err;
        }
 
        if (d->flag_mask)
@@ -2454,10 +2507,15 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg,
        ret = soc_tplg_dai_load(tplg, dai_drv, NULL, dai);
        if (ret < 0) {
                dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
-               return ret;
+               goto err;
        }
 
        return 0;
+
+err:
+       kfree(dai_drv->playback.stream_name);
+       kfree(dai_drv->capture.stream_name);
+       return ret;
 }
 
 /* load physical DAI elements */
@@ -2466,7 +2524,7 @@ static int soc_tplg_dai_elems_load(struct soc_tplg *tplg,
 {
        struct snd_soc_tplg_dai *dai;
        int count;
-       int i;
+       int i, ret;
 
        count = le32_to_cpu(hdr->count);
 
@@ -2481,7 +2539,12 @@ static int soc_tplg_dai_elems_load(struct soc_tplg *tplg,
                        return -EINVAL;
                }
 
-               soc_tplg_dai_config(tplg, dai);
+               ret = soc_tplg_dai_config(tplg, dai);
+               if (ret < 0) {
+                       dev_err(tplg->dev, "ASoC: failed to configure DAI\n");
+                       return ret;
+               }
+
                tplg->pos += (sizeof(*dai) + le32_to_cpu(dai->priv.size));
        }
 
@@ -2589,7 +2652,7 @@ static int soc_valid_header(struct soc_tplg *tplg,
        }
 
        /* big endian firmware objects not supported atm */
-       if (hdr->magic == SOC_TPLG_MAGIC_BIG_ENDIAN) {
+       if (le32_to_cpu(hdr->magic) == SOC_TPLG_MAGIC_BIG_ENDIAN) {
                dev_err(tplg->dev,
                        "ASoC: pass %d big endian not supported header got %x at offset 0x%lx size 0x%zx.\n",
                        tplg->pass, hdr->magic,
index 6c23c57..a32a3ef 100644 (file)
@@ -567,9 +567,25 @@ static void bdw_set_mach_params(const struct snd_soc_acpi_mach *mach,
 static struct snd_soc_dai_driver bdw_dai[] = {
 {
        .name = "ssp0-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 {
        .name = "ssp1-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 };
 
index f843912..29fd1d8 100644 (file)
@@ -459,21 +459,69 @@ static void byt_set_mach_params(const struct snd_soc_acpi_mach *mach,
 static struct snd_soc_dai_driver byt_dai[] = {
 {
        .name = "ssp0-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 {
        .name = "ssp1-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 {
        .name = "ssp2-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       }
 },
 {
        .name = "ssp3-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 {
        .name = "ssp4-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 {
        .name = "ssp5-port",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+       },
 },
 };
 
index 0d0c9af..41f01c3 100644 (file)
@@ -837,7 +837,7 @@ static int stm32_sai_set_config(struct snd_soc_dai *cpu_dai,
                cr1 = SAI_XCR1_DS_SET(SAI_DATASIZE_32);
                break;
        default:
-               dev_err(cpu_dai->dev, "Data format not supported");
+               dev_err(cpu_dai->dev, "Data format not supported\n");
                return -EINVAL;
        }
 
@@ -1547,6 +1547,9 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
                return ret;
        }
 
+       if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
+               conf = &stm32_sai_pcm_config_spdif;
+
        ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
        if (ret) {
                if (ret != -EPROBE_DEFER)
@@ -1556,15 +1559,10 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
 
        ret = snd_soc_register_component(&pdev->dev, &stm32_component,
                                         &sai->cpu_dai_drv, 1);
-       if (ret) {
+       if (ret)
                snd_dmaengine_pcm_unregister(&pdev->dev);
-               return ret;
-       }
-
-       if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
-               conf = &stm32_sai_pcm_config_spdif;
 
-       return 0;
+       return ret;
 }
 
 static int stm32_sai_sub_remove(struct platform_device *pdev)