aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/asahi-kasei,ak4375.yaml (renamed from Documentation/devicetree/bindings/sound/ak4375.yaml)2
-rw-r--r--Documentation/devicetree/bindings/sound/asahi-kasei,ak4613.yaml (renamed from Documentation/devicetree/bindings/sound/ak4613.yaml)2
-rw-r--r--Documentation/devicetree/bindings/sound/asahi-kasei,ak4642.yaml (renamed from Documentation/devicetree/bindings/sound/ak4642.yaml)2
-rw-r--r--Documentation/devicetree/bindings/sound/cirrus,cs530x.yaml85
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,sgtl5000.yaml (renamed from Documentation/devicetree/bindings/sound/sgtl5000.yaml)2
-rw-r--r--Documentation/devicetree/bindings/sound/mscc,zl38060.yaml (renamed from Documentation/devicetree/bindings/sound/zl38060.yaml)2
-rw-r--r--Documentation/devicetree/bindings/sound/realtek,rt1019.yaml (renamed from Documentation/devicetree/bindings/sound/rt1019.yaml)2
-rw-r--r--Documentation/devicetree/bindings/sound/ti,tas2562.yaml (renamed from Documentation/devicetree/bindings/sound/tas2562.yaml)2
-rw-r--r--Documentation/devicetree/bindings/sound/ti,tas2770.yaml (renamed from Documentation/devicetree/bindings/sound/tas2770.yaml)2
-rw-r--r--Documentation/devicetree/bindings/sound/ti,tas27xx.yaml (renamed from Documentation/devicetree/bindings/sound/tas27xx.yaml)2
-rw-r--r--Documentation/devicetree/bindings/sound/ti,tas5805m.yaml (renamed from Documentation/devicetree/bindings/sound/tas5805m.yaml)2
-rw-r--r--Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml24
-rw-r--r--Documentation/devicetree/bindings/sound/ti,tlv320adcx140.yaml (renamed from Documentation/devicetree/bindings/sound/tlv320adcx140.yaml)2
-rw-r--r--Documentation/devicetree/bindings/sound/wlf,wm8750.yaml (renamed from Documentation/devicetree/bindings/sound/wm8750.yaml)2
-rw-r--r--MAINTAINERS1
-rw-r--r--include/sound/dmaengine_pcm.h1
-rw-r--r--sound/core/pcm_dmaengine.c10
-rw-r--r--sound/soc/amd/acp/acp-i2s.c26
-rw-r--r--sound/soc/amd/acp/acp-pci.c12
-rw-r--r--sound/soc/amd/acp/acp-platform.c14
-rw-r--r--sound/soc/amd/acp/acp-rembrandt.c7
-rw-r--r--sound/soc/amd/acp/acp-renoir.c2
-rw-r--r--sound/soc/amd/acp/acp63.c7
-rw-r--r--sound/soc/amd/acp/acp70.c2
-rw-r--r--sound/soc/amd/acp/amd.h3
-rw-r--r--sound/soc/atmel/atmel-classd.c7
-rw-r--r--sound/soc/codecs/Kconfig14
-rw-r--r--sound/soc/codecs/Makefile4
-rw-r--r--sound/soc/codecs/cs35l56-shared.c4
-rw-r--r--sound/soc/codecs/cs42l43-jack.c4
-rw-r--r--sound/soc/codecs/cs530x-i2c.c72
-rw-r--r--sound/soc/codecs/cs530x.c966
-rw-r--r--sound/soc/codecs/cs530x.h223
-rw-r--r--sound/soc/codecs/es8326.c8
-rw-r--r--sound/soc/codecs/pcm6240.c6
-rw-r--r--sound/soc/codecs/rt722-sdca-sdw.c4
-rw-r--r--sound/soc/codecs/tlv320adc3xxx.c105
-rw-r--r--sound/soc/fsl/fsl-asoc-card.c3
-rw-r--r--sound/soc/fsl/imx-pcm-dma.c1
-rw-r--r--sound/soc/intel/avs/topology.c19
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c11
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-mtl-match.c2
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c10
-rw-r--r--sound/soc/mxs/mxs-pcm.c1
-rw-r--r--sound/soc/qcom/qdsp6/q6apm-lpass-dais.c32
-rw-r--r--sound/soc/qcom/sdw.c1
-rw-r--r--sound/soc/rockchip/rockchip_i2s_tdm.c13
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c8
-rw-r--r--sound/soc/soc-topology.c35
-rw-r--r--sound/soc/sof/intel/hda-dai.c6
-rw-r--r--sound/soc/sof/sof-audio.c2
-rw-r--r--sound/soc/ti/davinci-mcasp.c9
-rw-r--r--sound/soc/ti/omap-hdmi.c6
53 files changed, 1653 insertions, 141 deletions
diff --git a/Documentation/devicetree/bindings/sound/ak4375.yaml b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4375.yaml
index 587598e122c6..bc07fcba535b 100644
--- a/Documentation/devicetree/bindings/sound/ak4375.yaml
+++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4375.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/sound/ak4375.yaml#
+$id: http://devicetree.org/schemas/sound/asahi-kasei,ak4375.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: AK4375 DAC and headphones amplifier
diff --git a/Documentation/devicetree/bindings/sound/ak4613.yaml b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4613.yaml
index 75e13414d6eb..b49a6cff9f1f 100644
--- a/Documentation/devicetree/bindings/sound/ak4613.yaml
+++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4613.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/sound/ak4613.yaml#
+$id: http://devicetree.org/schemas/sound/asahi-kasei,ak4613.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: AK4613 I2C transmitter
diff --git a/Documentation/devicetree/bindings/sound/ak4642.yaml b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4642.yaml
index 437fe5d7cae1..fc03f0373a1a 100644
--- a/Documentation/devicetree/bindings/sound/ak4642.yaml
+++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4642.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
-$id: http://devicetree.org/schemas/sound/ak4642.yaml#
+$id: http://devicetree.org/schemas/sound/asahi-kasei,ak4642.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: AK4642 I2C transmitter
diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs530x.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs530x.yaml
new file mode 100644
index 000000000000..9582eb8eb418
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/cirrus,cs530x.yaml
@@ -0,0 +1,85 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/cirrus,cs530x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cirrus Logic cs530x family of audio ADCs
+
+maintainers:
+ - Paul Handrigan <[email protected]>
+
+description:
+ The CS530X devices are a family of high performance audio ADCs.
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ enum:
+ - cirrus,cs5302
+ - cirrus,cs5304
+ - cirrus,cs5308
+
+ reg:
+ maxItems: 1
+
+ '#sound-dai-cells':
+ const: 1
+
+ reset-gpios:
+ maxItems: 1
+
+ vdd-a-supply:
+ description: Analog power supply
+
+ vdd-io-supply:
+ description: Digital IO power supply
+
+ cirrus,in-hiz-pin12:
+ description:
+ Sets input channels one and two to high impedance.
+ type: boolean
+
+ cirrus,in-hiz-pin34:
+ description:
+ Sets input channels three and four to high impedance.
+ type: boolean
+
+ cirrus,in-hiz-pin56:
+ description:
+ Sets input channels five and six to high impedance.
+ type: boolean
+
+ cirrus,in-hiz-pin78:
+ description:
+ Sets input channels seven and eight to high impedance.
+ type: boolean
+
+required:
+ - compatible
+ - reg
+ - "#sound-dai-cells"
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cs5304: adc@48 {
+ compatible = "cirrus,cs5304";
+ reg = <0x48>;
+ #sound-dai-cells = <1>;
+ reset-gpios = <&gpio 110 GPIO_ACTIVE_LOW>;
+ vdd-a-supply = <&vreg>;
+ vdd-io-supply = <&vreg>;
+ cirrus,in-hiz-pin34;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/sgtl5000.yaml b/Documentation/devicetree/bindings/sound/fsl,sgtl5000.yaml
index 1353c051488f..c6ab1ca16763 100644
--- a/Documentation/devicetree/bindings/sound/sgtl5000.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,sgtl5000.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
%YAML 1.2
---
-$id: http://devicetree.org/schemas/sound/sgtl5000.yaml#
+$id: http://devicetree.org/schemas/sound/fsl,sgtl5000.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale SGTL5000 Stereo Codec
diff --git a/Documentation/devicetree/bindings/sound/zl38060.yaml b/Documentation/devicetree/bindings/sound/mscc,zl38060.yaml
index 8bd201e573aa..994313fd12b2 100644
--- a/Documentation/devicetree/bindings/sound/zl38060.yaml
+++ b/Documentation/devicetree/bindings/sound/mscc,zl38060.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/sound/zl38060.yaml#
+$id: http://devicetree.org/schemas/sound/mscc,zl38060.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ZL38060 Connected Home Audio Processor from Microsemi.
diff --git a/Documentation/devicetree/bindings/sound/rt1019.yaml b/Documentation/devicetree/bindings/sound/realtek,rt1019.yaml
index 3d5a91a942f4..adf5e38f4dbc 100644
--- a/Documentation/devicetree/bindings/sound/rt1019.yaml
+++ b/Documentation/devicetree/bindings/sound/realtek,rt1019.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/sound/rt1019.yaml#
+$id: http://devicetree.org/schemas/sound/realtek,rt1019.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: RT1019 Mono Class-D Audio Amplifier
diff --git a/Documentation/devicetree/bindings/sound/tas2562.yaml b/Documentation/devicetree/bindings/sound/ti,tas2562.yaml
index d28c102c0ce7..8bc3b0c7531e 100644
--- a/Documentation/devicetree/bindings/sound/tas2562.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tas2562.yaml
@@ -2,7 +2,7 @@
# Copyright (C) 2019 Texas Instruments Incorporated
%YAML 1.2
---
-$id: http://devicetree.org/schemas/sound/tas2562.yaml#
+$id: http://devicetree.org/schemas/sound/ti,tas2562.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments TAS2562 Smart PA
diff --git a/Documentation/devicetree/bindings/sound/tas2770.yaml b/Documentation/devicetree/bindings/sound/ti,tas2770.yaml
index be2536e8c440..362c2e6154f0 100644
--- a/Documentation/devicetree/bindings/sound/tas2770.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tas2770.yaml
@@ -2,7 +2,7 @@
# Copyright (C) 2019-20 Texas Instruments Incorporated
%YAML 1.2
---
-$id: http://devicetree.org/schemas/sound/tas2770.yaml#
+$id: http://devicetree.org/schemas/sound/ti,tas2770.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments TAS2770 Smart PA
diff --git a/Documentation/devicetree/bindings/sound/tas27xx.yaml b/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml
index f2d878f6f495..530bc3937847 100644
--- a/Documentation/devicetree/bindings/sound/tas27xx.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml
@@ -2,7 +2,7 @@
# Copyright (C) 2020-2022 Texas Instruments Incorporated
%YAML 1.2
---
-$id: http://devicetree.org/schemas/sound/tas27xx.yaml#
+$id: http://devicetree.org/schemas/sound/ti,tas27xx.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments TAS2764/TAS2780 Smart PA
diff --git a/Documentation/devicetree/bindings/sound/tas5805m.yaml b/Documentation/devicetree/bindings/sound/ti,tas5805m.yaml
index 12c41974274e..c2c2835a9e1d 100644
--- a/Documentation/devicetree/bindings/sound/tas5805m.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tas5805m.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/sound/tas5805m.yaml#
+$id: http://devicetree.org/schemas/sound/ti,tas5805m.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TAS5805M audio amplifier
diff --git a/Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml b/Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml
index 8ac741f4cd56..66b76656229f 100644
--- a/Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml
@@ -82,6 +82,26 @@ properties:
Note that there is currently no support for reading the GPIO pins as
inputs.
+ ti,micbias1-gpo:
+ type: boolean
+ description: |
+ When set, the MICBIAS1 pin may be controlled via the GPIO framework,
+ as pin number 3 on the device.
+
+ In this mode, when the pin is activated, it will be set to the voltage
+ specified by the ti,micbias1-vg property. When deactivated, the pin will
+ float.
+
+ ti,micbias2-gpo:
+ type: boolean
+ description: |
+ When set, the MICBIAS2 pin may be controlled via the GPIO framework,
+ as pin number 4 on the device.
+
+ In this mode, when the pin is activated, it will be set to the voltage
+ specified by the ti,micbias2-vg property. When deactivated, the pin will
+ float.
+
ti,micbias1-vg:
$ref: /schemas/types.yaml#/definitions/uint32
enum:
@@ -104,6 +124,10 @@ properties:
description: |
Mic bias voltage output on MICBIAS2 pin
+dependencies:
+ ti,micbias1-gpo: ['ti,micbias1-vg']
+ ti,micbias2-gpo: ['ti,micbias2-vg']
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml b/Documentation/devicetree/bindings/sound/ti,tlv320adcx140.yaml
index f3274bcc4c05..876fa97bfbcd 100644
--- a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tlv320adcx140.yaml
@@ -2,7 +2,7 @@
# Copyright (C) 2019 Texas Instruments Incorporated
%YAML 1.2
---
-$id: http://devicetree.org/schemas/sound/tlv320adcx140.yaml#
+$id: http://devicetree.org/schemas/sound/ti,tlv320adcx140.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments TLV320ADCX140 Quad Channel Analog-to-Digital Converter
diff --git a/Documentation/devicetree/bindings/sound/wm8750.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8750.yaml
index 24246ac7bbdf..96859e38315b 100644
--- a/Documentation/devicetree/bindings/sound/wm8750.yaml
+++ b/Documentation/devicetree/bindings/sound/wlf,wm8750.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
-$id: http://devicetree.org/schemas/sound/wm8750.yaml#
+$id: http://devicetree.org/schemas/sound/wlf,wm8750.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: WM8750 and WM8987 audio CODECs
diff --git a/MAINTAINERS b/MAINTAINERS
index aacccb376c28..c35c03901252 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18210,6 +18210,7 @@ QCOM AUDIO (ASoC) DRIVERS
M: Srinivas Kandagatla <[email protected]>
M: Banajit Goswami <[email protected]>
L: [email protected] (moderated for non-subscribers)
S: Supported
F: Documentation/devicetree/bindings/soc/qcom/qcom,apr*
F: Documentation/devicetree/bindings/sound/qcom,*
diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index c11aaf8079fb..f6baa9a01868 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -36,6 +36,7 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream
int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
struct dma_chan *chan);
int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream);
+int snd_dmaengine_pcm_sync_stop(struct snd_pcm_substream *substream);
int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
dma_filter_fn filter_fn, void *filter_data);
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index 12aa1cef11a1..ed07fa5693d2 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -349,6 +349,16 @@ int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan);
+int snd_dmaengine_pcm_sync_stop(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ dmaengine_synchronize(prtd->dma_chan);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_sync_stop);
+
/**
* snd_dmaengine_pcm_close - Close a dmaengine based PCM substream
* @substream: PCM substream
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c
index 0bc8617e922a..97258b4cf89b 100644
--- a/sound/soc/amd/acp/acp-i2s.c
+++ b/sound/soc/amd/acp/acp-i2s.c
@@ -369,12 +369,12 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
}
writel(period_bytes, adata->acp_base + water_val);
writel(buf_size, adata->acp_base + buf_reg);
+ if (rsrc->soc_mclk)
+ acp_set_i2s_clk(adata, dai->driver->id);
val = readl(adata->acp_base + reg_val);
val = val | BIT(0);
writel(val, adata->acp_base + reg_val);
writel(1, adata->acp_base + ier_val);
- if (rsrc->soc_mclk)
- acp_set_i2s_clk(adata, dai->driver->id);
return 0;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -584,29 +584,7 @@ static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d
return 0;
}
-static int acp_i2s_probe(struct snd_soc_dai *dai)
-{
- struct device *dev = dai->component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
- struct acp_resource *rsrc = adata->rsrc;
- unsigned int val;
-
- if (!adata->acp_base) {
- dev_err(dev, "I2S base is NULL\n");
- return -EINVAL;
- }
-
- val = readl(adata->acp_base + rsrc->i2s_pin_cfg_offset);
- if (val != rsrc->i2s_mode) {
- dev_err(dev, "I2S Mode not supported val %x\n", val);
- return -EINVAL;
- }
-
- return 0;
-}
-
const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
- .probe = acp_i2s_probe,
.startup = acp_i2s_startup,
.hw_params = acp_i2s_hwparams,
.prepare = acp_i2s_prepare,
diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
index 565623afd42e..b0304b813cad 100644
--- a/sound/soc/amd/acp/acp-pci.c
+++ b/sound/soc/amd/acp/acp-pci.c
@@ -100,6 +100,7 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
ret = -EINVAL;
goto release_regions;
}
+ chip->flag = flag;
dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0);
if (IS_ERR(dmic_dev)) {
dev_err(dev, "failed to create DMIC device\n");
@@ -139,7 +140,6 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
}
}
- chip->flag = flag;
memset(&pdevinfo, 0, sizeof(pdevinfo));
pdevinfo.name = chip->name;
@@ -199,10 +199,12 @@ static int __maybe_unused snd_acp_resume(struct device *dev)
ret = acp_init(chip);
if (ret)
dev_err(dev, "ACP init failed\n");
- child = chip->chip_pdev->dev;
- adata = dev_get_drvdata(&child);
- if (adata)
- acp_enable_interrupts(adata);
+ if (chip->chip_pdev) {
+ child = chip->chip_pdev->dev;
+ adata = dev_get_drvdata(&child);
+ if (adata)
+ acp_enable_interrupts(adata);
+ }
return ret;
}
diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c
index aaac8aa744cb..4f409cd09c11 100644
--- a/sound/soc/amd/acp/acp-platform.c
+++ b/sound/soc/amd/acp/acp-platform.c
@@ -197,6 +197,20 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs
else
runtime->hw = acp_pcm_hardware_capture;
+ ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, DMA_SIZE);
+ if (ret) {
+ dev_err(component->dev, "set hw constraint HW_PARAM_PERIOD_BYTES failed\n");
+ kfree(stream);
+ return ret;
+ }
+
+ ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, DMA_SIZE);
+ if (ret) {
+ dev_err(component->dev, "set hw constraint HW_PARAM_BUFFER_BYTES failed\n");
+ kfree(stream);
+ return ret;
+ }
+
ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
if (ret < 0) {
dev_err(component->dev, "set integer constraint failed\n");
diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c
index 158f819f8da4..e19981c7d65a 100644
--- a/sound/soc/amd/acp/acp-rembrandt.c
+++ b/sound/soc/amd/acp/acp-rembrandt.c
@@ -39,8 +39,6 @@ static struct acp_resource rsrc = {
.irqp_used = 1,
.soc_mclk = true,
.irq_reg_offset = 0x1a00,
- .i2s_pin_cfg_offset = 0x1440,
- .i2s_mode = 0x0a,
.scratch_reg_offset = 0x12800,
.sram_pte_offset = 0x03802800,
};
@@ -231,12 +229,13 @@ static int rembrandt_audio_probe(struct platform_device *pdev)
adata->rsrc = &rsrc;
adata->platform = REMBRANDT;
adata->flag = chip->flag;
+ adata->is_i2s_config = chip->is_i2s_config;
adata->machines = snd_soc_acpi_amd_rmb_acp_machines;
acp_machine_select(adata);
dev_set_drvdata(dev, adata);
- if (chip->flag != FLAG_AMD_LEGACY_ONLY_DMIC) {
+ if (chip->is_i2s_config && rsrc.soc_mclk) {
ret = acp6x_master_clock_generate(dev);
if (ret)
return ret;
@@ -269,7 +268,7 @@ static int __maybe_unused rmb_pcm_resume(struct device *dev)
snd_pcm_uframes_t buf_in_frames;
u64 buf_size;
- if (adata->flag != FLAG_AMD_LEGACY_ONLY_DMIC)
+ if (adata->is_i2s_config && adata->rsrc->soc_mclk)
acp6x_master_clock_generate(dev);
spin_lock(&adata->acp_lock);
diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
index b0e181c9a733..db835ed7c208 100644
--- a/sound/soc/amd/acp/acp-renoir.c
+++ b/sound/soc/amd/acp/acp-renoir.c
@@ -32,8 +32,6 @@ static struct acp_resource rsrc = {
.no_of_ctrls = 1,
.irqp_used = 0,
.irq_reg_offset = 0x1800,
- .i2s_pin_cfg_offset = 0x1400,
- .i2s_mode = 0x04,
.scratch_reg_offset = 0x12800,
.sram_pte_offset = 0x02052800,
};
diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c
index 4d342441a650..f340920b3289 100644
--- a/sound/soc/amd/acp/acp63.c
+++ b/sound/soc/amd/acp/acp63.c
@@ -55,8 +55,6 @@ static struct acp_resource rsrc = {
.irqp_used = 1,
.soc_mclk = true,
.irq_reg_offset = 0x1a00,
- .i2s_pin_cfg_offset = 0x1440,
- .i2s_mode = 0x0a,
.scratch_reg_offset = 0x12800,
.sram_pte_offset = 0x03802800,
};
@@ -241,11 +239,12 @@ static int acp63_audio_probe(struct platform_device *pdev)
adata->rsrc = &rsrc;
adata->platform = ACP63;
adata->flag = chip->flag;
+ adata->is_i2s_config = chip->is_i2s_config;
adata->machines = snd_soc_acpi_amd_acp63_acp_machines;
acp_machine_select(adata);
dev_set_drvdata(dev, adata);
- if (chip->flag != FLAG_AMD_LEGACY_ONLY_DMIC) {
+ if (chip->is_i2s_config && rsrc.soc_mclk) {
ret = acp63_i2s_master_clock_generate(adata);
if (ret)
return ret;
@@ -278,7 +277,7 @@ static int __maybe_unused acp63_pcm_resume(struct device *dev)
snd_pcm_uframes_t buf_in_frames;
u64 buf_size;
- if (adata->flag != FLAG_AMD_LEGACY_ONLY_DMIC)
+ if (adata->is_i2s_config && adata->rsrc->soc_mclk)
acp63_i2s_master_clock_generate(adata);
spin_lock(&adata->acp_lock);
diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c
index 0d7cdd4017e5..a2cbdcca4313 100644
--- a/sound/soc/amd/acp/acp70.c
+++ b/sound/soc/amd/acp/acp70.c
@@ -31,8 +31,6 @@ static struct acp_resource rsrc = {
.irqp_used = 1,
.soc_mclk = true,
.irq_reg_offset = 0x1a00,
- .i2s_pin_cfg_offset = 0x1440,
- .i2s_mode = 0x0a,
.scratch_reg_offset = 0x12800,
.sram_pte_offset = 0x03802800,
};
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index d75b4eb34de8..87a4813783f9 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -162,8 +162,6 @@ struct acp_resource {
int irqp_used;
bool soc_mclk;
u32 irq_reg_offset;
- u32 i2s_pin_cfg_offset;
- int i2s_mode;
u64 scratch_reg_offset;
u64 sram_pte_offset;
};
@@ -175,6 +173,7 @@ struct acp_dev_data {
unsigned int i2s_irq;
bool tdm_mode;
+ bool is_i2s_config;
/* SOC specific dais */
struct snd_soc_dai_driver *dai_driver;
int num_dai;
diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c
index 6aed1ee443b4..ba314b279919 100644
--- a/sound/soc/atmel/atmel-classd.c
+++ b/sound/soc/atmel/atmel-classd.c
@@ -473,19 +473,22 @@ static int atmel_classd_asoc_card_init(struct device *dev,
if (!dai_link)
return -ENOMEM;
- comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
+ comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL);
if (!comp)
return -ENOMEM;
- dai_link->cpus = comp;
+ dai_link->cpus = &comp[0];
dai_link->codecs = &snd_soc_dummy_dlc;
+ dai_link->platforms = &comp[1];
dai_link->num_cpus = 1;
dai_link->num_codecs = 1;
+ dai_link->num_platforms = 1;
dai_link->name = "CLASSD";
dai_link->stream_name = "CLASSD PCM";
dai_link->cpus->dai_name = dev_name(dev);
+ dai_link->platforms->name = dev_name(dev);
card->dai_link = dai_link;
card->num_links = 1;
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index a99cb26eb280..1f539c4b9432 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -99,6 +99,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_CS47L90
imply SND_SOC_CS47L92
imply SND_SOC_CS53L30
+ imply SND_SOC_CS530X_I2C
imply SND_SOC_CX20442
imply SND_SOC_CX2072X
imply SND_SOC_DA7210
@@ -1000,6 +1001,19 @@ config SND_SOC_CS53L30
tristate "Cirrus Logic CS53L30 CODEC"
depends on I2C
+config SND_SOC_CS530X
+ tristate
+
+config SND_SOC_CS530X_I2C
+ tristate "Cirrus Logic CS530x ADCs (I2C)"
+ depends on I2C
+ select REGMAP
+ select REGMAP_I2C
+ select SND_SOC_CS530X
+ help
+ Enable support for Cirrus Logic CS530X ADCs
+ with I2C control.
+
config SND_SOC_CX20442
tristate
depends on TTY
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index ad0f77224c74..c2c0d02b5484 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -107,6 +107,8 @@ snd-soc-cs47l85-y := cs47l85.o
snd-soc-cs47l90-y := cs47l90.o
snd-soc-cs47l92-y := cs47l92.o
snd-soc-cs53l30-y := cs53l30.o
+snd-soc-cs530x-y := cs530x.o
+snd-soc-cs530x-i2c-y := cs530x-i2c.o
snd-soc-cx20442-y := cx20442.o
snd-soc-cx2072x-y := cx2072x.o
snd-soc-da7210-y := da7210.o
@@ -509,6 +511,8 @@ obj-$(CONFIG_SND_SOC_CS47L85) += snd-soc-cs47l85.o
obj-$(CONFIG_SND_SOC_CS47L90) += snd-soc-cs47l90.o
obj-$(CONFIG_SND_SOC_CS47L92) += snd-soc-cs47l92.o
obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o
+obj-$(CONFIG_SND_SOC_CS530X) += snd-soc-cs530x.o
+obj-$(CONFIG_SND_SOC_CS530X_I2C) += snd-soc-cs530x-i2c.o
obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
obj-$(CONFIG_SND_SOC_CX2072X) += snd-soc-cx2072x.o
obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c
index 569bab3a2a6e..880228f89baf 100644
--- a/sound/soc/codecs/cs35l56-shared.c
+++ b/sound/soc/codecs/cs35l56-shared.c
@@ -215,6 +215,10 @@ static const struct reg_sequence cs35l56_asp1_defaults[] = {
REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL5, 0x00020100),
REG_SEQ0(CS35L56_ASP1_DATA_CONTROL1, 0x00000018),
REG_SEQ0(CS35L56_ASP1_DATA_CONTROL5, 0x00000018),
+ REG_SEQ0(CS35L56_ASP1TX1_INPUT, 0x00000000),
+ REG_SEQ0(CS35L56_ASP1TX2_INPUT, 0x00000000),
+ REG_SEQ0(CS35L56_ASP1TX3_INPUT, 0x00000000),
+ REG_SEQ0(CS35L56_ASP1TX4_INPUT, 0x00000000),
};
/*
diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c
index 901b9dbcf585..d9ab003e166b 100644
--- a/sound/soc/codecs/cs42l43-jack.c
+++ b/sound/soc/codecs/cs42l43-jack.c
@@ -121,7 +121,7 @@ int cs42l43_set_jack(struct snd_soc_component *component,
priv->buttons[3] = 735;
}
- ret = cs42l43_find_index(priv, "cirrus,detect-us", 1000, &priv->detect_us,
+ ret = cs42l43_find_index(priv, "cirrus,detect-us", 50000, &priv->detect_us,
cs42l43_accdet_us, ARRAY_SIZE(cs42l43_accdet_us));
if (ret < 0)
goto error;
@@ -433,7 +433,7 @@ irqreturn_t cs42l43_button_press(int irq, void *data)
// Wait for 2 full cycles of comb filter to ensure good reading
queue_delayed_work(system_wq, &priv->button_press_work,
- msecs_to_jiffies(10));
+ msecs_to_jiffies(20));
return IRQ_HANDLED;
}
diff --git a/sound/soc/codecs/cs530x-i2c.c b/sound/soc/codecs/cs530x-i2c.c
new file mode 100644
index 000000000000..56659bf735db
--- /dev/null
+++ b/sound/soc/codecs/cs530x-i2c.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// CS530x CODEC driver
+//
+// Copyright (C) 2024 Cirrus Logic, Inc. and
+// Cirrus Logic International Semiconductor Ltd.
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+#include "cs530x.h"
+
+static const struct of_device_id cs530x_of_match[] = {
+ {
+ .compatible = "cirrus,cs5302",
+ .data = (void *)CS5302,
+ }, {
+ .compatible = "cirrus,cs5304",
+ .data = (void *)CS5304,
+ }, {
+ .compatible = "cirrus,cs5308",
+ .data = (void *)CS5308,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, cs530x_of_match);
+
+static const struct i2c_device_id cs530x_i2c_id[] = {
+ { "cs5302", CS5302 },
+ { "cs5304", CS5304 },
+ { "cs5308", CS5308 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, cs530x_i2c_id);
+
+static int cs530x_i2c_probe(struct i2c_client *client)
+{
+ struct cs530x_priv *cs530x;
+
+ cs530x = devm_kzalloc(&client->dev, sizeof(*cs530x), GFP_KERNEL);
+ if (!cs530x)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, cs530x);
+
+ cs530x->regmap = devm_regmap_init_i2c(client, &cs530x_regmap);
+ if (IS_ERR(cs530x->regmap))
+ return dev_err_probe(&client->dev, PTR_ERR(cs530x->regmap),
+ "Failed to allocate register map\n");
+
+ cs530x->devtype = (uintptr_t)i2c_get_match_data(client);
+ cs530x->dev = &client->dev;
+
+ return cs530x_probe(cs530x);
+}
+
+static struct i2c_driver cs530x_i2c_driver = {
+ .driver = {
+ .name = "cs530x",
+ .of_match_table = cs530x_of_match,
+ },
+ .probe = cs530x_i2c_probe,
+ .id_table = cs530x_i2c_id,
+};
+module_i2c_driver(cs530x_i2c_driver);
+
+MODULE_DESCRIPTION("I2C CS530X driver");
+MODULE_IMPORT_NS(SND_SOC_CS530X);
+MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <[email protected]>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs530x.c b/sound/soc/codecs/cs530x.c
new file mode 100644
index 000000000000..036d0f45e3ba
--- /dev/null
+++ b/sound/soc/codecs/cs530x.c
@@ -0,0 +1,966 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// CS530x CODEC driver
+//
+// Copyright (C) 2024 Cirrus Logic, Inc. and
+// Cirrus Logic International Semiconductor Ltd.
+
+#include <sound/core.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <sound/initval.h>
+#include <linux/module.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <linux/pm.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+#include "cs530x.h"
+
+#define CS530X_MAX_ADC_CH 8
+#define CS530X_MIN_ADC_CH 2
+
+static const char *cs530x_supply_names[CS530X_NUM_SUPPLIES] = {
+ "vdd-a",
+ "vdd-io",
+};
+
+static const struct reg_default cs530x_reg_defaults[] = {
+ { CS530X_CLK_CFG_0, 0x30 },
+ { CS530X_CLK_CFG_1, 0x0001 },
+ { CS530X_CHIP_ENABLE, 0 },
+ { CS530X_ASP_CFG, 0 },
+ { CS530X_SIGNAL_PATH_CFG, 0 },
+ { CS530X_IN_ENABLES, 0 },
+ { CS530X_IN_RAMP_SUM, 0x0022 },
+ { CS530X_IN_FILTER, 0 },
+ { CS530X_IN_HIZ, 0 },
+ { CS530X_IN_INV, 0 },
+ { CS530X_IN_VOL_CTRL1_0, 0x8000 },
+ { CS530X_IN_VOL_CTRL1_1, 0x8000 },
+ { CS530X_IN_VOL_CTRL2_0, 0x8000 },
+ { CS530X_IN_VOL_CTRL2_1, 0x8000 },
+ { CS530X_IN_VOL_CTRL3_0, 0x8000 },
+ { CS530X_IN_VOL_CTRL3_1, 0x8000 },
+ { CS530X_IN_VOL_CTRL4_0, 0x8000 },
+ { CS530X_IN_VOL_CTRL4_1, 0x8000 },
+ { CS530X_PAD_FN, 0 },
+ { CS530X_PAD_LVL, 0 },
+};
+
+static bool cs530x_read_and_write_regs(unsigned int reg)
+{
+ switch (reg) {
+ case CS530X_CLK_CFG_0:
+ case CS530X_CLK_CFG_1:
+ case CS530X_CHIP_ENABLE:
+ case CS530X_ASP_CFG:
+ case CS530X_SIGNAL_PATH_CFG:
+ case CS530X_IN_ENABLES:
+ case CS530X_IN_RAMP_SUM:
+ case CS530X_IN_FILTER:
+ case CS530X_IN_HIZ:
+ case CS530X_IN_INV:
+ case CS530X_IN_VOL_CTRL1_0:
+ case CS530X_IN_VOL_CTRL1_1:
+ case CS530X_IN_VOL_CTRL2_0:
+ case CS530X_IN_VOL_CTRL2_1:
+ case CS530X_IN_VOL_CTRL3_0:
+ case CS530X_IN_VOL_CTRL3_1:
+ case CS530X_IN_VOL_CTRL4_0:
+ case CS530X_IN_VOL_CTRL4_1:
+ case CS530X_PAD_FN:
+ case CS530X_PAD_LVL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs530x_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS530X_DEVID:
+ case CS530X_REVID:
+ return true;
+ default:
+ return cs530x_read_and_write_regs(reg);
+ }
+}
+
+static bool cs530x_writeable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS530X_SW_RESET:
+ case CS530X_IN_VOL_CTRL5:
+ return true;
+ default:
+ return cs530x_read_and_write_regs(reg);
+ }
+}
+
+static int cs530x_put_volsw_vu(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+ struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+ struct regmap *regmap = cs530x->regmap;
+ int ret;
+
+ snd_soc_dapm_mutex_lock(dapm);
+
+ ret = snd_soc_put_volsw(kcontrol, ucontrol);
+ if (ret)
+ goto volsw_err;
+
+ /* Write IN_VU bit for the volume change to take effect */
+ regmap_write(regmap, CS530X_IN_VOL_CTRL5, CS530X_IN_VU);
+
+volsw_err:
+ snd_soc_dapm_mutex_unlock(dapm);
+
+ return ret;
+}
+
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1270, 50, 0);
+
+static const char * const cs530x_in_hpf_text[] = {
+ "Min Phase Slow Roll-off",
+ "Min Phase Fast Roll-off",
+ "Linear Phase Slow Roll-off",
+ "Linear Phase Fast Roll-off",
+};
+
+static SOC_ENUM_SINGLE_DECL(cs530x_in_hpf_enum, CS530X_IN_FILTER,
+ CS530X_IN_FILTER_SHIFT,
+ cs530x_in_hpf_text);
+
+static const char * const cs530x_in_4ch_sum_text[] = {
+ "None",
+ "Groups of 2",
+ "Groups of 4",
+};
+
+static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch4_enum, CS530X_IN_RAMP_SUM,
+ CS530X_IN_SUM_MODE_SHIFT,
+ cs530x_in_4ch_sum_text);
+
+static const struct snd_kcontrol_new cs530x_in_sum_4ch_controls[] = {
+SOC_ENUM("IN Sum Select", cs530x_in_sum_ch4_enum),
+};
+
+static const char * const cs530x_in_8ch_sum_text[] = {
+ "None",
+ "Groups of 2",
+ "Groups of 4",
+ "Groups of 8",
+};
+
+static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch8_enum, CS530X_IN_RAMP_SUM,
+ CS530X_IN_SUM_MODE_SHIFT,
+ cs530x_in_8ch_sum_text);
+
+static const struct snd_kcontrol_new cs530x_in_sum_8ch_controls[] = {
+SOC_ENUM("IN Sum Select", cs530x_in_sum_ch8_enum),
+};
+
+
+static const char * const cs530x_vol_ramp_text[] = {
+ "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
+ "15ms/6dB", "30ms/6dB",
+};
+
+static SOC_ENUM_SINGLE_DECL(cs530x_ramp_inc_enum, CS530X_IN_RAMP_SUM,
+ CS530X_RAMP_RATE_INC_SHIFT,
+ cs530x_vol_ramp_text);
+
+static SOC_ENUM_SINGLE_DECL(cs530x_ramp_dec_enum, CS530X_IN_RAMP_SUM,
+ CS530X_RAMP_RATE_DEC_SHIFT,
+ cs530x_vol_ramp_text);
+
+static const struct snd_kcontrol_new cs530x_in_1_to_2_controls[] = {
+SOC_SINGLE_EXT_TLV("IN1 Volume", CS530X_IN_VOL_CTRL1_0, 0, 255, 1,
+ snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+SOC_SINGLE_EXT_TLV("IN2 Volume", CS530X_IN_VOL_CTRL1_1, 0, 255, 1,
+ snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+
+SOC_ENUM("IN HPF Select", cs530x_in_hpf_enum),
+SOC_ENUM("Input Ramp Up", cs530x_ramp_inc_enum),
+SOC_ENUM("Input Ramp Down", cs530x_ramp_dec_enum),
+
+SOC_SINGLE("ADC1 Invert Switch", CS530X_IN_INV, CS530X_IN1_INV_SHIFT, 1, 0),
+SOC_SINGLE("ADC2 Invert Switch", CS530X_IN_INV, CS530X_IN2_INV_SHIFT, 1, 0),
+};
+
+static const struct snd_kcontrol_new cs530x_in_3_to_4_controls[] = {
+SOC_SINGLE_EXT_TLV("IN3 Volume", CS530X_IN_VOL_CTRL2_0, 0, 255, 1,
+ snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+SOC_SINGLE_EXT_TLV("IN4 Volume", CS530X_IN_VOL_CTRL2_1, 0, 255, 1,
+ snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+
+SOC_SINGLE("ADC3 Invert Switch", CS530X_IN_INV, CS530X_IN3_INV_SHIFT, 1, 0),
+SOC_SINGLE("ADC4 Invert Switch", CS530X_IN_INV, CS530X_IN4_INV_SHIFT, 1, 0),
+};
+
+static const struct snd_kcontrol_new cs530x_in_5_to_8_controls[] = {
+SOC_SINGLE_EXT_TLV("IN5 Volume", CS530X_IN_VOL_CTRL3_0, 0, 255, 1,
+ snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+SOC_SINGLE_EXT_TLV("IN6 Volume", CS530X_IN_VOL_CTRL3_1, 0, 255, 1,
+ snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+SOC_SINGLE_EXT_TLV("IN7 Volume", CS530X_IN_VOL_CTRL4_0, 0, 255, 1,
+ snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+SOC_SINGLE_EXT_TLV("IN8 Volume", CS530X_IN_VOL_CTRL4_1, 0, 255, 1,
+ snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
+
+SOC_SINGLE("ADC5 Invert Switch", CS530X_IN_INV, CS530X_IN5_INV_SHIFT, 1, 0),
+SOC_SINGLE("ADC6 Invert Switch", CS530X_IN_INV, CS530X_IN6_INV_SHIFT, 1, 0),
+SOC_SINGLE("ADC7 Invert Switch", CS530X_IN_INV, CS530X_IN7_INV_SHIFT, 1, 0),
+SOC_SINGLE("ADC8 Invert Switch", CS530X_IN_INV, CS530X_IN8_INV_SHIFT, 1, 0),
+};
+
+static int cs530x_adc_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+ struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+ struct regmap *regmap = cs530x->regmap;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ cs530x->adc_pairs_count++;
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
+ (w->shift * 2), CS530X_IN_MUTE);
+ regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
+ ((w->shift+1) * 2), CS530X_IN_MUTE);
+
+ cs530x->adc_pairs_count--;
+ if (!cs530x->adc_pairs_count) {
+ usleep_range(1000, 1100);
+ return regmap_write(regmap, CS530X_IN_VOL_CTRL5,
+ CS530X_IN_VU);
+ }
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
+ (w->shift * 2), CS530X_IN_MUTE);
+ regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
+ ((w->shift+1) * 2), CS530X_IN_MUTE);
+ return regmap_write(regmap, CS530X_IN_VOL_CTRL5,
+ CS530X_IN_VU);
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new adc12_ctrl =
+ SOC_DAPM_SINGLE_VIRT("Switch", 1);
+
+static const struct snd_kcontrol_new adc34_ctrl =
+ SOC_DAPM_SINGLE_VIRT("Switch", 1);
+
+static const struct snd_kcontrol_new adc56_ctrl =
+ SOC_DAPM_SINGLE_VIRT("Switch", 1);
+
+static const struct snd_kcontrol_new adc78_ctrl =
+ SOC_DAPM_SINGLE_VIRT("Switch", 1);
+
+static const struct snd_kcontrol_new in_hpf_ctrl =
+ SOC_DAPM_SINGLE_VIRT("Switch", 1);
+
+/* General DAPM widgets for all devices */
+static const struct snd_soc_dapm_widget cs530x_gen_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("Global Enable", CS530X_CHIP_ENABLE, 0, 0, NULL, 0),
+};
+
+/* ADC's Channels 1 and 2 plus generic ADC DAPM events */
+static const struct snd_soc_dapm_widget cs530x_adc_ch12_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("IN1"),
+SND_SOC_DAPM_INPUT("IN2"),
+SND_SOC_DAPM_ADC_E("ADC1", NULL, CS530X_IN_ENABLES, 0, 0,
+ cs530x_adc_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_ADC("ADC2", NULL, CS530X_IN_ENABLES, 1, 0),
+SND_SOC_DAPM_SWITCH("ADC12 Enable", SND_SOC_NOPM, 0, 0, &adc12_ctrl),
+SND_SOC_DAPM_SWITCH("IN HPF", CS530X_IN_FILTER, CS530X_IN_HPF_EN_SHIFT,
+ 0, &in_hpf_ctrl),
+};
+
+/* ADC's Channels 3 and 4 */
+static const struct snd_soc_dapm_widget cs530x_adc_ch34_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("IN3"),
+SND_SOC_DAPM_INPUT("IN4"),
+SND_SOC_DAPM_ADC_E("ADC3", NULL, CS530X_IN_ENABLES, 2, 0,
+ cs530x_adc_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_ADC("ADC4", NULL, CS530X_IN_ENABLES, 3, 0),
+SND_SOC_DAPM_SWITCH("ADC34 Enable", SND_SOC_NOPM, 0, 0, &adc34_ctrl),
+};
+
+/* ADC's Channels 5 to 8 */
+static const struct snd_soc_dapm_widget cs530x_adc_ch58_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("IN5"),
+SND_SOC_DAPM_INPUT("IN6"),
+SND_SOC_DAPM_INPUT("IN7"),
+SND_SOC_DAPM_INPUT("IN8"),
+SND_SOC_DAPM_ADC_E("ADC5", NULL, CS530X_IN_ENABLES, 4, 0,
+ cs530x_adc_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_ADC("ADC6", NULL, CS530X_IN_ENABLES, 5, 0),
+SND_SOC_DAPM_SWITCH("ADC56 Enable", SND_SOC_NOPM, 0, 0, &adc56_ctrl),
+SND_SOC_DAPM_ADC_E("ADC7", NULL, CS530X_IN_ENABLES, 6, 0,
+ cs530x_adc_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_ADC("ADC8", NULL, CS530X_IN_ENABLES, 7, 0),
+SND_SOC_DAPM_SWITCH("ADC78 Enable", SND_SOC_NOPM, 0, 0, &adc78_ctrl),
+};
+
+static const struct snd_soc_dapm_route adc_ch1_2_routes[] = {
+ { "ADC1", NULL, "Global Enable" },
+ { "ADC2", NULL, "Global Enable" },
+
+ { "ADC12 Enable", "Switch", "IN1" },
+ { "ADC12 Enable", "Switch", "IN2" },
+ { "ADC1", NULL, "ADC12 Enable" },
+ { "ADC2", NULL, "ADC12 Enable" },
+ { "IN HPF", "Switch", "ADC1" },
+ { "IN HPF", "Switch", "ADC2" },
+
+ { "AIF Capture", NULL, "IN HPF" },
+ { "AIF Capture", NULL, "ADC1" },
+ { "AIF Capture", NULL, "ADC2" },
+};
+
+static const struct snd_soc_dapm_route adc_ch3_4_routes[] = {
+ { "ADC3", NULL, "Global Enable" },
+ { "ADC4", NULL, "Global Enable" },
+
+ { "ADC34 Enable", "Switch", "IN3" },
+ { "ADC34 Enable", "Switch", "IN4" },
+ { "ADC3", NULL, "ADC34 Enable" },
+ { "ADC4", NULL, "ADC34 Enable" },
+ { "IN HPF", "Switch", "ADC3" },
+ { "IN HPF", "Switch", "ADC4" },
+
+ { "AIF Capture", NULL, "ADC3" },
+ { "AIF Capture", NULL, "ADC4" },
+};
+
+static const struct snd_soc_dapm_route adc_ch5_8_routes[] = {
+ { "ADC5", NULL, "Global Enable" },
+ { "ADC6", NULL, "Global Enable" },
+ { "ADC7", NULL, "Global Enable" },
+ { "ADC8", NULL, "Global Enable" },
+
+ { "ADC56 Enable", "Switch", "IN5" },
+ { "ADC56 Enable", "Switch", "IN6" },
+ { "ADC5", NULL, "ADC56 Enable" },
+ { "ADC6", NULL, "ADC56 Enable" },
+ { "IN HPF", "Switch", "ADC5" },
+ { "IN HPF", "Switch", "ADC6" },
+
+ { "AIF Capture", NULL, "ADC5" },
+ { "AIF Capture", NULL, "ADC6" },
+
+ { "ADC78 Enable", "Switch", "IN7" },
+ { "ADC78 Enable", "Switch", "IN8" },
+ { "ADC7", NULL, "ADC78 Enable" },
+ { "ADC8", NULL, "ADC78 Enable" },
+ { "IN HPF", "Switch", "ADC7" },
+ { "IN HPF", "Switch", "ADC8" },
+
+ { "AIF Capture", NULL, "ADC7" },
+ { "AIF Capture", NULL, "ADC8" },
+};
+
+static void cs530x_add_12_adc_widgets(struct snd_soc_component *component)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+
+ snd_soc_add_component_controls(component,
+ cs530x_in_1_to_2_controls,
+ ARRAY_SIZE(cs530x_in_1_to_2_controls));
+
+ snd_soc_dapm_new_controls(dapm, cs530x_adc_ch12_dapm_widgets,
+ ARRAY_SIZE(cs530x_adc_ch12_dapm_widgets));
+
+ snd_soc_dapm_add_routes(dapm, adc_ch1_2_routes,
+ ARRAY_SIZE(adc_ch1_2_routes));
+}
+
+static void cs530x_add_34_adc_widgets(struct snd_soc_component *component)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+
+ snd_soc_add_component_controls(component,
+ cs530x_in_3_to_4_controls,
+ ARRAY_SIZE(cs530x_in_3_to_4_controls));
+
+ snd_soc_dapm_new_controls(dapm, cs530x_adc_ch34_dapm_widgets,
+ ARRAY_SIZE(cs530x_adc_ch34_dapm_widgets));
+
+ snd_soc_dapm_add_routes(dapm, adc_ch3_4_routes,
+ ARRAY_SIZE(adc_ch3_4_routes));
+}
+
+static int cs530x_set_bclk(struct snd_soc_component *component)
+{
+ struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+ struct regmap *regmap = cs530x->regmap;
+ unsigned int bclk_val;
+
+ switch (cs530x->bclk) {
+ case 2822400:
+ case 3072000:
+ bclk_val = CS530X_BCLK_2P822_3P072;
+ break;
+ case 5644800:
+ case 6144000:
+ bclk_val = CS530X_BCLK_5P6448_6P144;
+ break;
+ case 11289600:
+ case 12288000:
+ bclk_val = CS530X_BCLK_11P2896_12P288;
+ break;
+ case 22579200:
+ case 24576000:
+ bclk_val = CS530X_BCLK_24P5792_24P576;
+ break;
+ default:
+ dev_err(component->dev, "Invalid BCLK %d\n", cs530x->bclk);
+ return -EINVAL;
+ }
+
+ dev_dbg(component->dev, "BCLK is %d\n", cs530x->bclk);
+
+ return regmap_update_bits(regmap, CS530X_ASP_CFG,
+ CS530X_ASP_BCLK_FREQ_MASK, bclk_val);
+}
+
+static int cs530x_set_pll_refclk(struct snd_soc_component *component,
+ const unsigned int freq)
+{
+ struct cs530x_priv *priv = snd_soc_component_get_drvdata(component);
+ struct regmap *regmap = priv->regmap;
+ unsigned int refclk;
+
+ switch (freq) {
+ case 2822400:
+ case 3072000:
+ refclk = CS530X_REFCLK_2P822_3P072;
+ break;
+ case 5644800:
+ case 6144000:
+ refclk = CS530X_REFCLK_5P6448_6P144;
+ break;
+ case 11289600:
+ case 12288000:
+ refclk = CS530X_REFCLK_11P2896_12P288;
+ break;
+ case 22579200:
+ case 24576000:
+ refclk = CS530X_REFCLK_24P5792_24P576;
+ break;
+ default:
+ dev_err(component->dev, "Invalid PLL refclk %d\n", freq);
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(regmap, CS530X_CLK_CFG_0,
+ CS530X_PLL_REFCLK_FREQ_MASK, refclk);
+}
+
+static int cs530x_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+ struct regmap *regmap = cs530x->regmap;
+ int ret = 0, fs = params_rate(params);
+ unsigned int fs_val;
+
+
+ switch (fs) {
+ case 32000:
+ fs_val = CS530X_FS_32K;
+ break;
+ case 44100:
+ case 48000:
+ fs_val = CS530X_FS_48K_44P1K;
+ break;
+ case 88200:
+ case 96000:
+ fs_val = CS530X_FS_96K_88P2K;
+ break;
+ case 176400:
+ case 192000:
+ fs_val = CS530X_FS_192K_176P4K;
+ break;
+ case 356800:
+ case 384000:
+ fs_val = CS530X_FS_384K_356P8K;
+ break;
+ case 705600:
+ case 768000:
+ fs_val = CS530X_FS_768K_705P6K;
+ break;
+ default:
+ dev_err(component->dev, "Invalid sample rate %d\n", fs);
+ return -EINVAL;
+ }
+
+ cs530x->fs = fs;
+ regmap_update_bits(regmap, CS530X_CLK_CFG_1,
+ CS530X_SAMPLE_RATE_MASK, fs_val);
+
+ if (cs530x->tdm_slots) {
+ dev_dbg(component->dev, "Configuring for %d %d bit TDM slots\n",
+ cs530x->tdm_slots, cs530x->tdm_width);
+ cs530x->bclk = snd_soc_calc_bclk(cs530x->fs,
+ cs530x->tdm_width,
+ params_channels(params),
+ cs530x->tdm_slots);
+ } else {
+ cs530x->bclk = snd_soc_params_to_bclk(params);
+ }
+
+ if (!regmap_test_bits(regmap, CS530X_CLK_CFG_0,
+ CS530X_PLL_REFCLK_SRC_MASK)) {
+ ret = cs530x_set_pll_refclk(component, cs530x->bclk);
+ if (ret)
+ return ret;
+ }
+
+ return cs530x_set_bclk(component);
+}
+
+static int cs530x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_component *component = dai->component;
+ struct cs530x_priv *priv = snd_soc_component_get_drvdata(component);
+ struct regmap *regmap = priv->regmap;
+ unsigned int asp_fmt, asp_cfg = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ asp_cfg = CS530X_ASP_PRIMARY;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ asp_fmt = CS530X_ASP_FMT_DSP_A;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ asp_fmt = CS530X_ASP_FMT_I2S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ asp_fmt = CS530X_ASP_FMT_LJ;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ asp_cfg |= CS530X_ASP_BCLK_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(regmap, CS530X_ASP_CFG,
+ CS530X_ASP_PRIMARY | CS530X_ASP_BCLK_INV,
+ asp_cfg);
+
+ return regmap_update_bits(regmap, CS530X_SIGNAL_PATH_CFG,
+ CS530X_ASP_FMT_MASK, asp_fmt);
+}
+
+static bool cs530x_check_mclk_freq(struct snd_soc_component *component,
+ const unsigned int freq)
+{
+ switch (freq) {
+ case 24576000:
+ case 22579200:
+ case 12288000:
+ case 11289600:
+ return true;
+ default:
+ dev_err(component->dev, "Invalid MCLK %d\n", freq);
+ return false;
+ }
+}
+
+static int cs530x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+ unsigned int rx_mask, int slots, int slot_width)
+{
+ struct snd_soc_component *component = dai->component;
+ struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+ struct regmap *regmap = cs530x->regmap;
+ unsigned int val;
+
+ switch (tx_mask) {
+ case CS530X_0_1_TDM_SLOT_MASK:
+ case CS530X_0_3_TDM_SLOT_MASK:
+ case CS530X_0_7_TDM_SLOT_MASK:
+ val = CS530X_0_7_TDM_SLOT_VAL;
+ break;
+ case CS530X_2_3_TDM_SLOT_MASK:
+ val = CS530X_2_3_TDM_SLOT_VAL;
+ break;
+ case CS530X_4_5_TDM_SLOT_MASK:
+ case CS530X_4_7_TDM_SLOT_MASK:
+ val = CS530X_4_7_TDM_SLOT_VAL;
+ break;
+ case CS530X_6_7_TDM_SLOT_MASK:
+ val = CS530X_6_7_TDM_SLOT_VAL;
+ break;
+ case CS530X_8_9_TDM_SLOT_MASK:
+ case CS530X_8_11_TDM_SLOT_MASK:
+ case CS530X_8_15_TDM_SLOT_MASK:
+ val = CS530X_8_15_TDM_SLOT_VAL;
+ break;
+ case CS530X_10_11_TDM_SLOT_MASK:
+ val = CS530X_10_11_TDM_SLOT_VAL;
+ break;
+ case CS530X_12_13_TDM_SLOT_MASK:
+ case CS530X_12_15_TDM_SLOT_MASK:
+ val = CS530X_12_15_TDM_SLOT_VAL;
+ break;
+ case CS530X_14_15_TDM_SLOT_MASK:
+ val = CS530X_14_15_TDM_SLOT_VAL;
+ break;
+ default:
+ dev_err(component->dev, "Invalid TX slot(s) 0x%x\n", tx_mask);
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(regmap, CS530X_SIGNAL_PATH_CFG,
+ CS530X_ASP_TDM_SLOT_MASK,
+ val << CS530X_ASP_TDM_SLOT_SHIFT);
+}
+
+static const struct snd_soc_dai_ops cs530x_dai_ops = {
+ .set_fmt = cs530x_set_fmt,
+ .hw_params = cs530x_hw_params,
+ .set_tdm_slot = cs530x_set_tdm_slot,
+};
+
+static const struct snd_soc_dai_driver cs530x_dai = {
+ .name = "cs530x-dai",
+ .capture = {
+ .stream_name = "AIF Capture",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .ops = &cs530x_dai_ops,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
+};
+
+static int cs530x_set_pll(struct snd_soc_component *component, int pll_id,
+ int source, unsigned int freq_in,
+ unsigned int freq_out)
+{
+ struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+ struct regmap *regmap = cs530x->regmap;
+ unsigned int sysclk_src;
+ int ret;
+
+ regmap_read(regmap, CS530X_CLK_CFG_0, &sysclk_src);
+
+ /* Check if the source is the PLL */
+ if ((sysclk_src & CS530X_SYSCLK_SRC_MASK) == 0)
+ return 0;
+
+ switch (source) {
+ case CS530X_PLL_SRC_MCLK:
+ if (!cs530x_check_mclk_freq(component, freq_in))
+ return -EINVAL;
+
+ ret = cs530x_set_pll_refclk(component, freq_in);
+ if (ret)
+ return ret;
+
+ break;
+ case CS530X_PLL_SRC_BCLK:
+ break;
+ default:
+ dev_err(component->dev, "Invalid PLL source %d\n", source);
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(regmap, CS530X_CLK_CFG_0,
+ CS530X_PLL_REFCLK_SRC_MASK, source);
+}
+
+static int cs530x_component_probe(struct snd_soc_component *component)
+{
+ struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+ struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+ int num_widgets;
+
+ snd_soc_dapm_new_controls(dapm, cs530x_gen_dapm_widgets,
+ ARRAY_SIZE(cs530x_gen_dapm_widgets));
+
+ switch (cs530x->devtype) {
+ case CS5302:
+ cs530x_add_12_adc_widgets(component);
+ break;
+ case CS5304:
+ cs530x_add_12_adc_widgets(component);
+ cs530x_add_34_adc_widgets(component);
+
+ num_widgets = ARRAY_SIZE(cs530x_in_sum_4ch_controls);
+ snd_soc_add_component_controls(component,
+ cs530x_in_sum_4ch_controls,
+ num_widgets);
+ break;
+
+ case CS5308:
+ cs530x_add_12_adc_widgets(component);
+ cs530x_add_34_adc_widgets(component);
+
+ num_widgets = ARRAY_SIZE(cs530x_in_5_to_8_controls);
+ snd_soc_add_component_controls(component,
+ cs530x_in_5_to_8_controls,
+ num_widgets);
+
+ num_widgets = ARRAY_SIZE(cs530x_in_sum_8ch_controls);
+ snd_soc_add_component_controls(component,
+ cs530x_in_sum_8ch_controls,
+ num_widgets);
+
+ num_widgets = ARRAY_SIZE(cs530x_adc_ch58_dapm_widgets);
+ snd_soc_dapm_new_controls(dapm, cs530x_adc_ch58_dapm_widgets,
+ num_widgets);
+
+ snd_soc_dapm_add_routes(dapm, adc_ch5_8_routes,
+ ARRAY_SIZE(adc_ch5_8_routes));
+ break;
+ default:
+ dev_err(component->dev, "Invalid device type %d\n",
+ cs530x->devtype);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cs530x_set_sysclk(struct snd_soc_component *component, int clk_id,
+ int source, unsigned int freq, int dir)
+{
+ struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
+ struct regmap *regmap = cs530x->regmap;
+
+ switch (source) {
+ case CS530X_SYSCLK_SRC_MCLK:
+ if (freq != 24560000 && freq != 22572000) {
+ dev_err(component->dev, "Invalid MCLK source rate %d\n",
+ freq);
+ return -EINVAL;
+ }
+
+ cs530x->mclk_rate = freq;
+ break;
+ case CS530X_SYSCLK_SRC_PLL:
+ break;
+ default:
+ dev_err(component->dev, "Invalid clock id %d\n", clk_id);
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(regmap, CS530X_CLK_CFG_0,
+ CS530X_SYSCLK_SRC_MASK,
+ source << CS530X_SYSCLK_SRC_SHIFT);
+}
+
+static const struct snd_soc_component_driver soc_component_dev_cs530x = {
+ .probe = cs530x_component_probe,
+ .set_sysclk = cs530x_set_sysclk,
+ .set_pll = cs530x_set_pll,
+ .endianness = 1,
+};
+
+const struct regmap_config cs530x_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .max_register = CS530X_MAX_REGISTER,
+ .readable_reg = cs530x_readable_register,
+ .writeable_reg = cs530x_writeable_register,
+
+ .cache_type = REGCACHE_MAPLE,
+ .reg_defaults = cs530x_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(cs530x_reg_defaults),
+};
+EXPORT_SYMBOL_NS_GPL(cs530x_regmap, SND_SOC_CS530X);
+
+static int cs530x_check_device_id(struct cs530x_priv *cs530x)
+{
+ struct device *dev = cs530x->dev;
+ unsigned int dev_id, rev;
+ int ret;
+
+ ret = regmap_read(cs530x->regmap, CS530X_DEVID, &dev_id);
+ if (ret)
+ return dev_err_probe(dev, ret, "Can't read device ID\n");
+
+ ret = regmap_read(cs530x->regmap, CS530X_REVID, &rev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Can't read REV ID\n");
+
+ dev_dbg(dev, "Device ID 0x%x Rev ID 0x%x\n", dev_id, rev);
+
+ switch (dev_id) {
+ case CS530X_2CH_ADC_DEV_ID:
+ cs530x->num_adcs = 2;
+ break;
+ case CS530X_4CH_ADC_DEV_ID:
+ cs530x->num_adcs = 4;
+ break;
+ case CS530X_8CH_ADC_DEV_ID:
+ cs530x->num_adcs = 8;
+ break;
+ default:
+ return dev_err_probe(dev, -EINVAL, "Invalid device ID 0x%x\n",
+ dev_id);
+ }
+
+ return 0;
+}
+
+static int cs530x_parse_device_properties(struct cs530x_priv *cs530x)
+{
+ struct regmap *regmap = cs530x->regmap;
+ struct device *dev = cs530x->dev;
+ unsigned int val = 0;
+
+ switch (cs530x->num_adcs) {
+ case 8:
+ if (device_property_read_bool(dev, "cirrus,in-hiz-pin78"))
+ val = CS530X_IN78_HIZ;
+
+ if (device_property_read_bool(dev, "cirrus,in-hiz-pin56"))
+ val |= CS530X_IN56_HIZ;
+
+ fallthrough;
+ case 4:
+ if (device_property_read_bool(dev, "cirrus,in-hiz-pin34"))
+ val |= CS530X_IN34_HIZ;
+
+ fallthrough;
+ case 2:
+ if (device_property_read_bool(dev, "cirrus,in-hiz-pin12"))
+ val |= CS530X_IN12_HIZ;
+
+ return regmap_set_bits(regmap, CS530X_IN_HIZ, val);
+ default:
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid number of adcs %d\n",
+ cs530x->num_adcs);
+ }
+}
+
+int cs530x_probe(struct cs530x_priv *cs530x)
+{
+ struct device *dev = cs530x->dev;
+ int ret, i;
+
+ cs530x->dev_dai = devm_kmemdup(dev, &cs530x_dai,
+ sizeof(*(cs530x->dev_dai)),
+ GFP_KERNEL);
+ if (!cs530x->dev_dai)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(cs530x->supplies); i++)
+ cs530x->supplies[i].supply = cs530x_supply_names[i];
+
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs530x->supplies),
+ cs530x->supplies);
+ if (ret != 0)
+ return dev_err_probe(dev, ret, "Failed to request supplies");
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(cs530x->supplies),
+ cs530x->supplies);
+ if (ret != 0)
+ return dev_err_probe(dev, ret, "Failed to enable supplies");
+
+ cs530x->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(cs530x->reset_gpio)) {
+ ret = dev_err_probe(dev, PTR_ERR(cs530x->reset_gpio),
+ "Reset gpio not available\n");
+ goto err_regulator;
+ }
+
+ if (cs530x->reset_gpio) {
+ usleep_range(2000, 2100);
+ gpiod_set_value_cansleep(cs530x->reset_gpio, 0);
+ }
+
+ usleep_range(5000, 5100);
+ ret = cs530x_check_device_id(cs530x);
+ if (ret)
+ goto err_reset;
+
+ if (!cs530x->reset_gpio) {
+ ret = regmap_write(cs530x->regmap, CS530X_SW_RESET,
+ CS530X_SW_RST_VAL);
+ if (ret) {
+ dev_err_probe(dev, ret, "Soft Reset Failed\n");
+ goto err_reset;
+ }
+ }
+
+ ret = cs530x_parse_device_properties(cs530x);
+ if (ret)
+ goto err_reset;
+
+ cs530x->dev_dai->capture.channels_max = cs530x->num_adcs;
+
+ ret = devm_snd_soc_register_component(dev,
+ &soc_component_dev_cs530x, cs530x->dev_dai, 1);
+ if (ret) {
+ dev_err_probe(dev, ret, "Can't register cs530x component\n");
+ goto err_reset;
+ }
+
+ return 0;
+
+err_reset:
+ gpiod_set_value_cansleep(cs530x->reset_gpio, 1);
+
+err_regulator:
+ regulator_bulk_disable(ARRAY_SIZE(cs530x->supplies),
+ cs530x->supplies);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(cs530x_probe, SND_SOC_CS530X);
+
+MODULE_DESCRIPTION("CS530X CODEC Driver");
+MODULE_AUTHOR("Paul Handrigan <[email protected]>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs530x.h b/sound/soc/codecs/cs530x.h
new file mode 100644
index 000000000000..1c85310a5d03
--- /dev/null
+++ b/sound/soc/codecs/cs530x.h
@@ -0,0 +1,223 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * CS530x CODEC driver internal data
+ *
+ * Copyright (C) 2023-2024 Cirrus Logic, Inc. and
+ * Cirrus Logic International Semiconductor Ltd.
+ */
+
+#ifndef _CS530X_H
+#define _CS530X_H
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+/* Devices */
+#define CS530X_2CH_ADC_DEV_ID 0x5302
+#define CS530X_4CH_ADC_DEV_ID 0x5304
+#define CS530X_8CH_ADC_DEV_ID 0x5308
+
+/* Registers */
+
+#define CS530X_DEVID 0x0000000
+#define CS530X_REVID 0x0000004
+#define CS530X_SW_RESET 0x0000022
+
+#define CS530X_CLK_CFG_0 0x0000040
+#define CS530X_CLK_CFG_1 0x0000042
+#define CS530X_CHIP_ENABLE 0x0000044
+#define CS530X_ASP_CFG 0x0000048
+#define CS530X_SIGNAL_PATH_CFG 0x0000050
+#define CS530X_IN_ENABLES 0x0000080
+#define CS530X_IN_RAMP_SUM 0x0000082
+#define CS530X_IN_FILTER 0x0000086
+#define CS530X_IN_HIZ 0x0000088
+#define CS530X_IN_INV 0x000008A
+#define CS530X_IN_VOL_CTRL1_0 0x0000090
+#define CS530X_IN_VOL_CTRL1_1 0x0000092
+#define CS530X_IN_VOL_CTRL2_0 0x0000094
+#define CS530X_IN_VOL_CTRL2_1 0x0000096
+#define CS530X_IN_VOL_CTRL3_0 0x0000098
+#define CS530X_IN_VOL_CTRL3_1 0x000009A
+#define CS530X_IN_VOL_CTRL4_0 0x000009C
+#define CS530X_IN_VOL_CTRL4_1 0x000009E
+#define CS530X_IN_VOL_CTRL5 0x00000A0
+
+#define CS530X_PAD_FN 0x0003D24
+#define CS530X_PAD_LVL 0x0003D28
+
+#define CS530X_MAX_REGISTER CS530X_PAD_LVL
+
+/* Register Fields */
+
+/* REVID */
+#define CS530X_MTLREVID GENMASK(3, 0)
+#define CS530X_AREVID GENMASK(7, 4)
+
+/* SW_RESET */
+#define CS530X_SW_RST_SHIFT 8
+#define CS530X_SW_RST_VAL (0x5A << CS530X_SW_RST_SHIFT)
+
+/* CLK_CFG_0 */
+#define CS530X_PLL_REFCLK_SRC_MASK BIT(0)
+#define CS530X_PLL_REFCLK_FREQ_MASK GENMASK(5, 4)
+#define CS530X_SYSCLK_SRC_MASK BIT(12)
+#define CS530X_SYSCLK_SRC_SHIFT 12
+#define CS530X_REFCLK_2P822_3P072 0
+#define CS530X_REFCLK_5P6448_6P144 0x10
+#define CS530X_REFCLK_11P2896_12P288 0x20
+#define CS530X_REFCLK_24P5792_24P576 0x30
+
+/* CLK_CFG_1 */
+#define CS530X_SAMPLE_RATE_MASK GENMASK(2, 0)
+#define CS530X_FS_32K 0
+#define CS530X_FS_48K_44P1K 1
+#define CS530X_FS_96K_88P2K 2
+#define CS530X_FS_192K_176P4K 3
+#define CS530X_FS_384K_356P8K 4
+#define CS530X_FS_768K_705P6K 5
+
+/* CHIP_ENABLE */
+#define CS530X_GLOBAL_EN BIT(0)
+
+/* ASP_CFG */
+#define CS530X_ASP_BCLK_FREQ_MASK GENMASK(1, 0)
+#define CS530X_ASP_PRIMARY BIT(5)
+#define CS530X_ASP_BCLK_INV BIT(6)
+#define CS530X_BCLK_2P822_3P072 0
+#define CS530X_BCLK_5P6448_6P144 1
+#define CS530X_BCLK_11P2896_12P288 2
+#define CS530X_BCLK_24P5792_24P576 3
+
+/* SIGNAL_PATH_CFG */
+#define CS530X_ASP_FMT_MASK GENMASK(2, 0)
+#define CS530X_ASP_TDM_SLOT_MASK GENMASK(5, 3)
+#define CS530X_ASP_TDM_SLOT_SHIFT 3
+#define CS530X_ASP_CH_REVERSE BIT(9)
+#define CS530X_ASP_FMT_I2S 0
+#define CS530X_ASP_FMT_LJ 1
+#define CS530X_ASP_FMT_DSP_A 0x6
+
+/* TDM Slots */
+#define CS530X_0_1_TDM_SLOT_MASK GENMASK(1, 0)
+#define CS530X_0_3_TDM_SLOT_MASK GENMASK(3, 0)
+#define CS530X_0_7_TDM_SLOT_MASK GENMASK(7, 0)
+#define CS530X_0_7_TDM_SLOT_VAL 0
+
+#define CS530X_2_3_TDM_SLOT_MASK GENMASK(3, 2)
+#define CS530X_2_3_TDM_SLOT_VAL 1
+
+#define CS530X_4_5_TDM_SLOT_MASK GENMASK(5, 4)
+#define CS530X_4_7_TDM_SLOT_MASK GENMASK(7, 4)
+#define CS530X_4_7_TDM_SLOT_VAL 2
+
+#define CS530X_6_7_TDM_SLOT_MASK GENMASK(7, 6)
+#define CS530X_6_7_TDM_SLOT_VAL 3
+
+#define CS530X_8_9_TDM_SLOT_MASK GENMASK(9, 8)
+#define CS530X_8_11_TDM_SLOT_MASK GENMASK(11, 8)
+#define CS530X_8_15_TDM_SLOT_MASK GENMASK(15, 8)
+#define CS530X_8_15_TDM_SLOT_VAL 4
+
+#define CS530X_10_11_TDM_SLOT_MASK GENMASK(11, 10)
+#define CS530X_10_11_TDM_SLOT_VAL 5
+
+#define CS530X_12_13_TDM_SLOT_MASK GENMASK(13, 12)
+#define CS530X_12_15_TDM_SLOT_MASK GENMASK(15, 12)
+#define CS530X_12_15_TDM_SLOT_VAL 6
+
+#define CS530X_14_15_TDM_SLOT_MASK GENMASK(15, 14)
+#define CS530X_14_15_TDM_SLOT_VAL 7
+
+/* IN_RAMP_SUM */
+#define CS530X_RAMP_RATE_INC_SHIFT 0
+#define CS530X_RAMP_RATE_DEC_SHIFT 4
+#define CS530X_IN_SUM_MODE_SHIFT 13
+
+/* IN_FILTER */
+#define CS530X_IN_FILTER_SHIFT 8
+#define CS530X_IN_HPF_EN_SHIFT 12
+
+/* IN_HIZ */
+#define CS530X_IN12_HIZ BIT(0)
+#define CS530X_IN34_HIZ BIT(1)
+#define CS530X_IN56_HIZ BIT(2)
+#define CS530X_IN78_HIZ BIT(3)
+
+/* IN_INV */
+#define CS530X_IN1_INV_SHIFT 0
+#define CS530X_IN2_INV_SHIFT 1
+#define CS530X_IN3_INV_SHIFT 2
+#define CS530X_IN4_INV_SHIFT 3
+#define CS530X_IN5_INV_SHIFT 4
+#define CS530X_IN6_INV_SHIFT 5
+#define CS530X_IN7_INV_SHIFT 6
+#define CS530X_IN8_INV_SHIFT 7
+
+/* IN_VOL_CTLy_z */
+#define CS530X_IN_MUTE BIT(15)
+
+/* IN_VOL_CTL5 */
+#define CS530X_IN_VU BIT(0)
+
+/* PAD_FN */
+#define CS530X_DOUT2_FN BIT(0)
+#define CS530X_DOUT3_FN BIT(1)
+#define CS530X_DOUT4_FN BIT(2)
+#define CS530X_SPI_CS_FN BIT(3)
+#define CS530X_CONFIG2_FN BIT(6)
+#define CS530X_CONFIG3_FN BIT(7)
+#define CS530X_CONFIG4_FN BIT(8)
+#define CS530X_CONFIG5_FN BIT(9)
+
+/* PAD_LVL */
+#define CS530X_CONFIG2_LVL BIT(6)
+#define CS530X_CONFIG3_LVL BIT(7)
+#define CS530X_CONFIG4_LVL BIT(8)
+#define CS530X_CONFIG5_LVL BIT(9)
+
+/* System Clock Source */
+#define CS530X_SYSCLK_SRC_MCLK 0
+#define CS530X_SYSCLK_SRC_PLL 1
+
+/* PLL Reference Clock Source */
+#define CS530X_PLL_SRC_BCLK 0
+#define CS530X_PLL_SRC_MCLK 1
+
+#define CS530X_NUM_SUPPLIES 2
+
+enum cs530x_type {
+ CS5302,
+ CS5304,
+ CS5308,
+};
+
+/* codec private data */
+struct cs530x_priv {
+ struct regmap *regmap;
+ struct device *dev;
+ struct snd_soc_dai_driver *dev_dai;
+
+ enum cs530x_type devtype;
+ int num_adcs;
+ int num_dacs;
+
+ struct regulator_bulk_data supplies[CS530X_NUM_SUPPLIES];
+
+ unsigned int mclk_rate;
+
+ int tdm_width;
+ int tdm_slots;
+ int bclk;
+ int fs;
+ int adc_pairs_count;
+
+ struct gpio_desc *reset_gpio;
+};
+
+extern const struct regmap_config cs530x_regmap;
+int cs530x_probe(struct cs530x_priv *cs530x);
+
+#endif
diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c
index 03b539ba540f..6a4e42e5e35b 100644
--- a/sound/soc/codecs/es8326.c
+++ b/sound/soc/codecs/es8326.c
@@ -857,12 +857,16 @@ static void es8326_jack_detect_handler(struct work_struct *work)
* set auto-check mode, then restart jack_detect_work after 400ms.
* Don't report jack status.
*/
- regmap_write(es8326->regmap, ES8326_INT_SOURCE,
- (ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON));
+ regmap_write(es8326->regmap, ES8326_INT_SOURCE, 0x00);
regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01);
+ regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x10, 0x00);
es8326_enable_micbias(es8326->component);
usleep_range(50000, 70000);
regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00);
+ regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x10, 0x10);
+ usleep_range(50000, 70000);
+ regmap_write(es8326->regmap, ES8326_INT_SOURCE,
+ (ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON));
regmap_write(es8326->regmap, ES8326_SYS_BIAS, 0x1f);
regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x0f, 0x08);
queue_delayed_work(system_wq, &es8326->jack_detect_work,
diff --git a/sound/soc/codecs/pcm6240.c b/sound/soc/codecs/pcm6240.c
index 86e126783a1d..8f7057e689fb 100644
--- a/sound/soc/codecs/pcm6240.c
+++ b/sound/soc/codecs/pcm6240.c
@@ -2087,10 +2087,8 @@ static int pcmdevice_i2c_probe(struct i2c_client *i2c)
#endif
pcm_dev = devm_kzalloc(&i2c->dev, sizeof(*pcm_dev), GFP_KERNEL);
- if (!pcm_dev) {
- ret = -ENOMEM;
- goto out;
- }
+ if (!pcm_dev)
+ return -ENOMEM;
pcm_dev->chip_id = (id != NULL) ? id->driver_data : 0;
diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c
index b33da2215ade..87354bb1564e 100644
--- a/sound/soc/codecs/rt722-sdca-sdw.c
+++ b/sound/soc/codecs/rt722-sdca-sdw.c
@@ -68,6 +68,7 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re
case 0x200007f:
case 0x2000082 ... 0x200008e:
case 0x2000090 ... 0x2000094:
+ case 0x3110000:
case 0x5300000 ... 0x5300002:
case 0x5400002:
case 0x5600000 ... 0x5600007:
@@ -125,6 +126,7 @@ static bool rt722_sdca_mbq_volatile_register(struct device *dev, unsigned int re
case 0x2000067:
case 0x2000084:
case 0x2000086:
+ case 0x3110000:
return true;
default:
return false;
@@ -350,7 +352,7 @@ static int rt722_sdca_interrupt_callback(struct sdw_slave *slave,
if (status->sdca_cascade && !rt722->disable_irq)
mod_delayed_work(system_power_efficient_wq,
- &rt722->jack_detect_work, msecs_to_jiffies(30));
+ &rt722->jack_detect_work, msecs_to_jiffies(280));
mutex_unlock(&rt722->disable_irq_lock);
diff --git a/sound/soc/codecs/tlv320adc3xxx.c b/sound/soc/codecs/tlv320adc3xxx.c
index eb180df9a72a..7073b9d1cda8 100644
--- a/sound/soc/codecs/tlv320adc3xxx.c
+++ b/sound/soc/codecs/tlv320adc3xxx.c
@@ -39,9 +39,10 @@
*/
#define ADC3XXX_MICBIAS_PINS 2
+#define ADC3XXX_GPIO_PINS 2
/* Number of GPIO pins exposed via the gpiolib interface */
-#define ADC3XXX_GPIOS_MAX 2
+#define ADC3XXX_GPIOS_MAX (ADC3XXX_MICBIAS_PINS + ADC3XXX_GPIO_PINS)
#define ADC3XXX_RATES SNDRV_PCM_RATE_8000_96000
#define ADC3XXX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
@@ -320,7 +321,8 @@ struct adc3xxx {
struct gpio_desc *rst_pin;
unsigned int pll_mode;
unsigned int sysclk;
- unsigned int gpio_cfg[ADC3XXX_GPIOS_MAX]; /* value+1 (0 => not set) */
+ unsigned int gpio_cfg[ADC3XXX_GPIO_PINS]; /* value+1 (0 => not set) */
+ unsigned int micbias_gpo[ADC3XXX_MICBIAS_PINS]; /* 1 => pin is GPO */
unsigned int micbias_vg[ADC3XXX_MICBIAS_PINS];
int master;
u8 page_no;
@@ -328,7 +330,7 @@ struct adc3xxx {
struct gpio_chip gpio_chip;
};
-static const unsigned int adc3xxx_gpio_ctrl_reg[ADC3XXX_GPIOS_MAX] = {
+static const unsigned int adc3xxx_gpio_ctrl_reg[ADC3XXX_GPIO_PINS] = {
ADC3XXX_GPIO1_CTRL,
ADC3XXX_GPIO2_CTRL
};
@@ -959,14 +961,23 @@ static int adc3xxx_gpio_request(struct gpio_chip *chip, unsigned int offset)
if (offset >= ADC3XXX_GPIOS_MAX)
return -EINVAL;
- /* GPIO1 is offset 0, GPIO2 is offset 1 */
- /* We check here that the GPIO pins are either not configured in the
- * DT, or that they purposely are set as outputs.
- * (Input mode not yet implemented).
- */
- if (adc3xxx->gpio_cfg[offset] != 0 &&
- adc3xxx->gpio_cfg[offset] != ADC3XXX_GPIO_GPO + 1)
- return -EINVAL;
+ if (offset >= 0 && offset < ADC3XXX_GPIO_PINS) {
+ /* GPIO1 is offset 0, GPIO2 is offset 1 */
+ /* We check here that the GPIO pins are either not configured
+ * in the DT, or that they purposely are set as outputs.
+ * (Input mode not yet implemented).
+ */
+ if (adc3xxx->gpio_cfg[offset] != 0 &&
+ adc3xxx->gpio_cfg[offset] != ADC3XXX_GPIO_GPO + 1)
+ return -EINVAL;
+ } else if (offset >= ADC3XXX_GPIO_PINS && offset < ADC3XXX_GPIOS_MAX) {
+ /* MICBIAS1 is offset 2, MICBIAS2 is offset 3 */
+ /* We check here if the MICBIAS pins are in fact configured
+ * as GPOs.
+ */
+ if (!adc3xxx->micbias_gpo[offset - ADC3XXX_GPIO_PINS])
+ return -EINVAL;
+ }
return 0;
}
@@ -976,6 +987,21 @@ static int adc3xxx_gpio_direction_out(struct gpio_chip *chip,
{
struct adc3xxx *adc3xxx = gpiochip_get_data(chip);
+ /* For the MICBIAS pins, they are by definition outputs. */
+ if (offset >= ADC3XXX_GPIO_PINS) {
+ unsigned int vg;
+ unsigned int micbias = offset - ADC3XXX_GPIO_PINS;
+
+ if (value)
+ vg = adc3xxx->micbias_vg[micbias];
+ else
+ vg = ADC3XXX_MICBIAS_OFF;
+ return regmap_update_bits(adc3xxx->regmap,
+ ADC3XXX_MICBIAS_CTRL,
+ ADC3XXX_MICBIAS_MASK << adc3xxx_micbias_shift[micbias],
+ vg << adc3xxx_micbias_shift[micbias]);
+ }
+
/* Set GPIO output function. */
return regmap_update_bits(adc3xxx->regmap,
adc3xxx_gpio_ctrl_reg[offset],
@@ -1004,9 +1030,17 @@ static int adc3xxx_gpio_get(struct gpio_chip *chip, unsigned int offset)
unsigned int regval;
int ret;
- /* We only allow output pins, so just read the value set in the output
- * pin register field.
- */
+ /* We only allow output pins, so just read the value prevously set. */
+ if (offset >= ADC3XXX_GPIO_PINS) {
+ /* MICBIAS pins */
+ unsigned int micbias = offset - ADC3XXX_GPIO_PINS;
+
+ ret = regmap_read(adc3xxx->regmap, ADC3XXX_MICBIAS_CTRL, &regval);
+ if (ret)
+ return ret;
+ return ((regval >> adc3xxx_micbias_shift[micbias]) & ADC3XXX_MICBIAS_MASK) !=
+ ADC3XXX_MICBIAS_OFF;
+ }
ret = regmap_read(adc3xxx->regmap, adc3xxx_gpio_ctrl_reg[offset], &regval);
if (ret)
return ret;
@@ -1048,7 +1082,7 @@ static void adc3xxx_init_gpio(struct adc3xxx *adc3xxx)
* This allows us to set up things which are not software
* controllable GPIOs, such as PDM microphone I/O,
*/
- for (gpio = 0; gpio < ADC3XXX_GPIOS_MAX; gpio++) {
+ for (gpio = 0; gpio < ADC3XXX_GPIO_PINS; gpio++) {
unsigned int cfg = adc3xxx->gpio_cfg[gpio];
if (cfg) {
@@ -1060,9 +1094,15 @@ static void adc3xxx_init_gpio(struct adc3xxx *adc3xxx)
}
}
- /* Set up micbias voltage */
+ /* Set up micbias voltage. */
+ /* If pin is configured as GPO, set off initially. */
for (micbias = 0; micbias < ADC3XXX_MICBIAS_PINS; micbias++) {
- unsigned int vg = adc3xxx->micbias_vg[micbias];
+ unsigned int vg;
+
+ if (adc3xxx->micbias_gpo[micbias])
+ vg = ADC3XXX_MICBIAS_OFF;
+ else
+ vg = adc3xxx->micbias_vg[micbias];
regmap_update_bits(adc3xxx->regmap,
ADC3XXX_MICBIAS_CTRL,
@@ -1090,8 +1130,19 @@ static int adc3xxx_parse_dt_gpio(struct adc3xxx *adc3xxx,
return 0;
}
-static int adc3xxx_parse_dt_micbias(struct adc3xxx *adc3xxx,
- const char *propname, unsigned int *vg)
+static int adc3xxx_parse_dt_micbias_gpo(struct adc3xxx *adc3xxx,
+ const char *propname,
+ unsigned int *cfg)
+{
+ struct device *dev = adc3xxx->dev;
+ struct device_node *np = dev->of_node;
+
+ *cfg = of_property_read_bool(np, propname);
+ return 0;
+}
+
+static int adc3xxx_parse_dt_micbias_vg(struct adc3xxx *adc3xxx,
+ const char *propname, unsigned int *vg)
{
struct device *dev = adc3xxx->dev;
struct device_node *np = dev->of_node;
@@ -1382,16 +1433,28 @@ static int adc3xxx_i2c_probe(struct i2c_client *i2c)
dev_dbg(dev, "Enabled MCLK, freq %lu Hz\n", clk_get_rate(adc3xxx->mclk));
}
+ /* Configure mode for DMDIN/GPIO1 pin */
ret = adc3xxx_parse_dt_gpio(adc3xxx, "ti,dmdin-gpio1", &adc3xxx->gpio_cfg[0]);
if (ret < 0)
goto err_unprepare_mclk;
+ /* Configure mode for DMCLK/GPIO2 pin */
ret = adc3xxx_parse_dt_gpio(adc3xxx, "ti,dmclk-gpio2", &adc3xxx->gpio_cfg[1]);
if (ret < 0)
goto err_unprepare_mclk;
- ret = adc3xxx_parse_dt_micbias(adc3xxx, "ti,micbias1-vg", &adc3xxx->micbias_vg[0]);
+ /* Configure mode for MICBIAS1: as Mic Bias output or GPO */
+ ret = adc3xxx_parse_dt_micbias_gpo(adc3xxx, "ti,micbias1-gpo", &adc3xxx->micbias_gpo[0]);
+ if (ret < 0)
+ goto err_unprepare_mclk;
+ /* Configure mode for MICBIAS2: as Mic Bias output or GPO */
+ ret = adc3xxx_parse_dt_micbias_gpo(adc3xxx, "ti,micbias2-gpo", &adc3xxx->micbias_gpo[1]);
+ if (ret < 0)
+ goto err_unprepare_mclk;
+ /* Configure voltage for MICBIAS1 pin (ON voltage when used as GPO) */
+ ret = adc3xxx_parse_dt_micbias_vg(adc3xxx, "ti,micbias1-vg", &adc3xxx->micbias_vg[0]);
if (ret < 0)
goto err_unprepare_mclk;
- ret = adc3xxx_parse_dt_micbias(adc3xxx, "ti,micbias2-vg", &adc3xxx->micbias_vg[1]);
+ /* Configure voltage for MICBIAS2 pin (ON voltage when used as GPO) */
+ ret = adc3xxx_parse_dt_micbias_vg(adc3xxx, "ti,micbias2-vg", &adc3xxx->micbias_vg[1]);
if (ret < 0)
goto err_unprepare_mclk;
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index 5ddc0c2fe53f..eb67689dcd6e 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -559,6 +559,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
+ priv->pdev = pdev;
+
cpu_np = of_parse_phandle(np, "audio-cpu", 0);
/* Give a chance to old DT binding */
if (!cpu_np)
@@ -787,7 +789,6 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
}
/* Initialize sound card */
- priv->pdev = pdev;
priv->card.dev = &pdev->dev;
priv->card.owner = THIS_MODULE;
ret = snd_soc_of_parse_card_name(&priv->card, "model");
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index 14e94270911c..4fa208d6a032 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -50,4 +50,5 @@ int imx_pcm_dma_init(struct platform_device *pdev)
}
EXPORT_SYMBOL_GPL(imx_pcm_dma_init);
+MODULE_DESCRIPTION("Freescale i.MX PCM DMA interface");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c
index 35381a835c93..5cda527020c7 100644
--- a/sound/soc/intel/avs/topology.c
+++ b/sound/soc/intel/avs/topology.c
@@ -1545,8 +1545,8 @@ static int avs_route_load(struct snd_soc_component *comp, int index,
{
struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
size_t len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
- char buf[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
int ssp_port, tdm_slot;
+ char *buf;
/* See parse_link_formatted_string() for dynamic naming when(s). */
if (!avs_mach_singular_ssp(mach))
@@ -1557,13 +1557,24 @@ static int avs_route_load(struct snd_soc_component *comp, int index,
return 0;
tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);
+ buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
avs_ssp_sprint(buf, len, route->source, ssp_port, tdm_slot);
- strscpy((char *)route->source, buf, len);
+ route->source = buf;
+
+ buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
avs_ssp_sprint(buf, len, route->sink, ssp_port, tdm_slot);
- strscpy((char *)route->sink, buf, len);
+ route->sink = buf;
+
if (route->control) {
+ buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
avs_ssp_sprint(buf, len, route->control, ssp_port, tdm_slot);
- strscpy((char *)route->control, buf, len);
+ route->control = buf;
}
return 0;
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index b41a1147f1c3..a64d1989e28a 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -613,6 +613,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 101 CESIUM"),
+ },
+ .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
+ BYT_RT5640_JD_NOT_INV |
+ BYT_RT5640_DIFF_MIC |
+ BYT_RT5640_SSP0_AIF1 |
+ BYT_RT5640_MCLK_EN),
+ },
+ {
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 140 CESIUM"),
},
.driver_data = (void *)(BYT_RT5640_IN1_MAP |
diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
index 48252fa9e39e..8e0ae3635a35 100644
--- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
@@ -293,7 +293,7 @@ static const struct snd_soc_acpi_adr_device rt1318_1_single_adr[] = {
.adr = 0x000130025D131801,
.num_endpoints = 1,
.endpoints = &single_endpoint,
- .name_prefix = "rt1318"
+ .name_prefix = "rt1318-1"
}
};
diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
index acaf81fd6c9b..f848e14b091a 100644
--- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
+++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
@@ -31,7 +31,7 @@ struct mt8183_da7219_max98357_priv {
static struct snd_soc_jack_pin mt8183_da7219_max98357_jack_pins[] = {
{
- .pin = "Headphone",
+ .pin = "Headphones",
.mask = SND_JACK_HEADPHONE,
},
{
@@ -626,7 +626,7 @@ static struct snd_soc_codec_conf mt6358_codec_conf[] = {
};
static const struct snd_kcontrol_new mt8183_da7219_max98357_snd_controls[] = {
- SOC_DAPM_PIN_SWITCH("Headphone"),
+ SOC_DAPM_PIN_SWITCH("Headphones"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Speakers"),
SOC_DAPM_PIN_SWITCH("Line Out"),
@@ -634,7 +634,7 @@ static const struct snd_kcontrol_new mt8183_da7219_max98357_snd_controls[] = {
static const
struct snd_soc_dapm_widget mt8183_da7219_max98357_dapm_widgets[] = {
- SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_HP("Headphones", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_SPK("Speakers", NULL),
SND_SOC_DAPM_SPK("Line Out", NULL),
@@ -680,7 +680,7 @@ static struct snd_soc_codec_conf mt8183_da7219_rt1015_codec_conf[] = {
};
static const struct snd_kcontrol_new mt8183_da7219_rt1015_snd_controls[] = {
- SOC_DAPM_PIN_SWITCH("Headphone"),
+ SOC_DAPM_PIN_SWITCH("Headphones"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Left Spk"),
SOC_DAPM_PIN_SWITCH("Right Spk"),
@@ -689,7 +689,7 @@ static const struct snd_kcontrol_new mt8183_da7219_rt1015_snd_controls[] = {
static const
struct snd_soc_dapm_widget mt8183_da7219_rt1015_dapm_widgets[] = {
- SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_HP("Headphones", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_SPK("Left Spk", NULL),
SND_SOC_DAPM_SPK("Right Spk", NULL),
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index df2e4be992d2..9bb08cadeb18 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -43,4 +43,5 @@ int mxs_pcm_platform_register(struct device *dev)
}
EXPORT_SYMBOL_GPL(mxs_pcm_platform_register);
+MODULE_DESCRIPTION("MXS ASoC PCM driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
index ba28ec9dff86..9c98a35ad099 100644
--- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
+++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
@@ -146,14 +146,17 @@ static void q6apm_lpass_dai_shutdown(struct snd_pcm_substream *substream, struct
struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev);
int rc;
- if (!dai_data->is_port_started[dai->id])
- return;
- rc = q6apm_graph_stop(dai_data->graph[dai->id]);
- if (rc < 0)
- dev_err(dai->dev, "fail to close APM port (%d)\n", rc);
+ if (dai_data->is_port_started[dai->id]) {
+ rc = q6apm_graph_stop(dai_data->graph[dai->id]);
+ dai_data->is_port_started[dai->id] = false;
+ if (rc < 0)
+ dev_err(dai->dev, "fail to close APM port (%d)\n", rc);
+ }
- q6apm_graph_close(dai_data->graph[dai->id]);
- dai_data->is_port_started[dai->id] = false;
+ if (dai_data->graph[dai->id]) {
+ q6apm_graph_close(dai_data->graph[dai->id]);
+ dai_data->graph[dai->id] = NULL;
+ }
}
static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
@@ -168,8 +171,10 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
q6apm_graph_stop(dai_data->graph[dai->id]);
dai_data->is_port_started[dai->id] = false;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
q6apm_graph_close(dai_data->graph[dai->id]);
+ dai_data->graph[dai->id] = NULL;
+ }
}
/**
@@ -188,26 +193,29 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
cfg->direction = substream->stream;
rc = q6apm_graph_media_format_pcm(dai_data->graph[dai->id], cfg);
-
if (rc) {
dev_err(dai->dev, "Failed to set media format %d\n", rc);
- return rc;
+ goto err;
}
rc = q6apm_graph_prepare(dai_data->graph[dai->id]);
if (rc) {
dev_err(dai->dev, "Failed to prepare Graph %d\n", rc);
- return rc;
+ goto err;
}
rc = q6apm_graph_start(dai_data->graph[dai->id]);
if (rc < 0) {
dev_err(dai->dev, "fail to start APM port %x\n", dai->id);
- return rc;
+ goto err;
}
dai_data->is_port_started[dai->id] = true;
return 0;
+err:
+ q6apm_graph_close(dai_data->graph[dai->id]);
+ dai_data->graph[dai->id] = NULL;
+ return rc;
}
static int q6apm_lpass_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c
index eaa8bb016e50..f2eda2ff46c0 100644
--- a/sound/soc/qcom/sdw.c
+++ b/sound/soc/qcom/sdw.c
@@ -160,4 +160,5 @@ int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
return 0;
}
EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free);
+MODULE_DESCRIPTION("Qualcomm ASoC SoundWire helper functions");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c
index 9fa020ef7eab..ee517d7b5b7b 100644
--- a/sound/soc/rockchip/rockchip_i2s_tdm.c
+++ b/sound/soc/rockchip/rockchip_i2s_tdm.c
@@ -655,8 +655,17 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
int err;
if (i2s_tdm->is_master_mode) {
- struct clk *mclk = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
- i2s_tdm->mclk_tx : i2s_tdm->mclk_rx;
+ struct clk *mclk;
+
+ if (i2s_tdm->clk_trcm == TRCM_TX) {
+ mclk = i2s_tdm->mclk_tx;
+ } else if (i2s_tdm->clk_trcm == TRCM_RX) {
+ mclk = i2s_tdm->mclk_rx;
+ } else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ mclk = i2s_tdm->mclk_tx;
+ } else {
+ mclk = i2s_tdm->mclk_rx;
+ }
err = clk_set_rate(mclk, DEFAULT_MCLK_FS * params_rate(params));
if (err)
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index ea3bc9318412..a63e942fdc0b 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -318,6 +318,12 @@ static int dmaengine_copy(struct snd_soc_component *component,
return 0;
}
+static int dmaengine_pcm_sync_stop(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ return snd_dmaengine_pcm_sync_stop(substream);
+}
+
static const struct snd_soc_component_driver dmaengine_pcm_component = {
.name = SND_DMAENGINE_PCM_DRV_NAME,
.probe_order = SND_SOC_COMP_ORDER_LATE,
@@ -327,6 +333,7 @@ static const struct snd_soc_component_driver dmaengine_pcm_component = {
.trigger = dmaengine_pcm_trigger,
.pointer = dmaengine_pcm_pointer,
.pcm_construct = dmaengine_pcm_new,
+ .sync_stop = dmaengine_pcm_sync_stop,
};
static const struct snd_soc_component_driver dmaengine_pcm_component_process = {
@@ -339,6 +346,7 @@ static const struct snd_soc_component_driver dmaengine_pcm_component_process = {
.pointer = dmaengine_pcm_pointer,
.copy = dmaengine_copy,
.pcm_construct = dmaengine_pcm_new,
+ .sync_stop = dmaengine_pcm_sync_stop,
};
static const char * const dmaengine_pcm_dma_channel_names[] = {
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index b00ec01361c2..4b166294602f 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -1021,6 +1021,7 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
struct snd_soc_tplg_hdr *hdr)
{
struct snd_soc_dapm_context *dapm = &tplg->comp->dapm;
+ const size_t maxlen = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
struct snd_soc_tplg_dapm_graph_elem *elem;
struct snd_soc_dapm_route *route;
int count, i;
@@ -1044,31 +1045,27 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
tplg->pos += sizeof(struct snd_soc_tplg_dapm_graph_elem);
/* validate routes */
- if (strnlen(elem->source, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
- SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
+ if ((strnlen(elem->source, maxlen) == maxlen) ||
+ (strnlen(elem->sink, maxlen) == maxlen) ||
+ (strnlen(elem->control, maxlen) == maxlen)) {
ret = -EINVAL;
break;
}
- if (strnlen(elem->sink, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
- SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
- ret = -EINVAL;
- break;
- }
- if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
- SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
- ret = -EINVAL;
+
+ route->source = devm_kstrdup(tplg->dev, elem->source, GFP_KERNEL);
+ route->sink = devm_kstrdup(tplg->dev, elem->sink, GFP_KERNEL);
+ if (!route->source || !route->sink) {
+ ret = -ENOMEM;
break;
}
- route->source = elem->source;
- route->sink = elem->sink;
-
- /* set to NULL atm for tplg users */
- route->connected = NULL;
- if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0)
- route->control = NULL;
- else
- route->control = elem->control;
+ if (strnlen(elem->control, maxlen) != 0) {
+ route->control = devm_kstrdup(tplg->dev, elem->control, GFP_KERNEL);
+ if (!route->control) {
+ ret = -ENOMEM;
+ break;
+ }
+ }
/* add route dobj to dobj_list */
route->dobj.type = SND_SOC_DOBJ_GRAPH;
diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c
index ce675c22a5ab..c61d298ea6b3 100644
--- a/sound/soc/sof/intel/hda-dai.c
+++ b/sound/soc/sof/intel/hda-dai.c
@@ -379,7 +379,7 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream,
sdev = widget_to_sdev(w);
if (sdev->dspless_mode_selected)
- goto skip_tlv;
+ return 0;
/* get stream_id */
hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
@@ -423,7 +423,6 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream,
dma_config->dma_stream_channel_map.device_count = 1;
dma_config->dma_priv_config_size = 0;
-skip_tlv:
return 0;
}
@@ -525,6 +524,9 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
return ret;
}
+ if (sdev->dspless_mode_selected)
+ return 0;
+
ipc4_copier = widget_to_copier(w);
dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id];
dma_config = &dma_config_tlv->dma_config;
diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index 881eec38c2e2..9a52781bf8d8 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -485,7 +485,7 @@ sink_prepare:
if (ret < 0) {
/* unprepare the source widget */
if (widget_ops[widget->id].ipc_unprepare &&
- swidget && swidget->prepared) {
+ swidget && swidget->prepared && swidget->use_count == 0) {
widget_ops[widget->id].ipc_unprepare(swidget);
swidget->prepared = false;
}
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
index 1e760c315521..2b1ed91a736c 100644
--- a/sound/soc/ti/davinci-mcasp.c
+++ b/sound/soc/ti/davinci-mcasp.c
@@ -1472,10 +1472,11 @@ static int davinci_mcasp_hw_rule_min_periodsize(
{
struct snd_interval *period_size = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+ u8 numevt = *((u8 *)rule->private);
struct snd_interval frames;
snd_interval_any(&frames);
- frames.min = 64;
+ frames.min = numevt;
frames.integer = 1;
return snd_interval_refine(period_size, &frames);
@@ -1490,6 +1491,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
u32 max_channels = 0;
int i, dir, ret;
int tdm_slots = mcasp->tdm_slots;
+ u8 *numevt;
/* Do not allow more then one stream per direction */
if (mcasp->substreams[substream->stream])
@@ -1589,9 +1591,12 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
return ret;
}
+ numevt = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ &mcasp->txnumevt :
+ &mcasp->rxnumevt;
snd_pcm_hw_rule_add(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
- davinci_mcasp_hw_rule_min_periodsize, NULL,
+ davinci_mcasp_hw_rule_min_periodsize, numevt,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
return 0;
diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c
index 639bc83f4263..cf43ac19c4a6 100644
--- a/sound/soc/ti/omap-hdmi.c
+++ b/sound/soc/ti/omap-hdmi.c
@@ -354,11 +354,7 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev)
if (!card)
return -ENOMEM;
- card->name = devm_kasprintf(dev, GFP_KERNEL,
- "HDMI %s", dev_name(ad->dssdev));
- if (!card->name)
- return -ENOMEM;
-
+ card->name = "HDMI";
card->owner = THIS_MODULE;
card->dai_link =
devm_kzalloc(dev, sizeof(*(card->dai_link)), GFP_KERNEL);