aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/ak4613.yaml7
-rw-r--r--Documentation/devicetree/bindings/sound/audio-graph-port.yaml65
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,sai.yaml38
-rw-r--r--Documentation/devicetree/bindings/sound/irondevice,sma1303.yaml13
-rw-r--r--Documentation/devicetree/bindings/sound/renesas,rsnd.yaml31
-rw-r--r--Documentation/devicetree/bindings/sound/simple-card.yaml4
-rw-r--r--Documentation/devicetree/bindings/sound/tas5720.txt2
-rw-r--r--Documentation/devicetree/bindings/sound/ti,pcm3168a.txt56
-rw-r--r--Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml107
-rw-r--r--MAINTAINERS7
-rw-r--r--include/sound/soc-topology.h2
-rw-r--r--sound/soc/amd/acp/acp-mach-common.c8
-rw-r--r--sound/soc/codecs/sma1303.c9
-rw-r--r--sound/soc/codecs/tas5720.c128
-rw-r--r--sound/soc/codecs/tas5720.h16
-rw-r--r--sound/soc/soc-topology.c183
16 files changed, 416 insertions, 260 deletions
diff --git a/Documentation/devicetree/bindings/sound/ak4613.yaml b/Documentation/devicetree/bindings/sound/ak4613.yaml
index 010574645e6a..75e13414d6eb 100644
--- a/Documentation/devicetree/bindings/sound/ak4613.yaml
+++ b/Documentation/devicetree/bindings/sound/ak4613.yaml
@@ -25,6 +25,13 @@ properties:
"#sound-dai-cells":
const: 0
+ ports:
+ $ref: audio-graph-port.yaml#/definitions/ports
+
+ port:
+ $ref: audio-graph-port.yaml#
+ unevaluatedProperties: false
+
patternProperties:
"^asahi-kasei,in[1-2]-single-end$":
description: Input Pin 1 - 2.
diff --git a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml
index f5b8b6d13077..6b4e02a0695a 100644
--- a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml
+++ b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml
@@ -11,32 +11,24 @@ maintainers:
select: false
-allOf:
- - $ref: /schemas/graph.yaml#/$defs/port-base
-
-properties:
- prefix:
- description: "device name prefix"
- $ref: /schemas/types.yaml#/definitions/string
- convert-rate:
- $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-rate"
- convert-channels:
- $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-channels"
- convert-sample-format:
- $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-format"
+definitions:
+ port-base:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ properties:
+ convert-rate:
+ $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-rate"
+ convert-channels:
+ $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-channels"
+ convert-sample-format:
+ $ref: "/schemas/sound/dai-params.yaml#/$defs/dai-sample-format"
+ mclk-fs:
+ $ref: "simple-card.yaml#/definitions/mclk-fs"
-patternProperties:
- "^endpoint(@[0-9a-f]+)?":
+ endpoint-base:
$ref: /schemas/graph.yaml#/$defs/endpoint-base
- unevaluatedProperties: false
-
properties:
mclk-fs:
- description: |
- Multiplication factor between stream rate and codec mclk.
- When defined, mclk-fs property defined in dai-link sub nodes are
- ignored.
- $ref: /schemas/types.yaml#/definitions/uint32
+ $ref: "simple-card.yaml#/definitions/mclk-fs"
frame-inversion:
description: dai-link uses frame clock inversion
$ref: /schemas/types.yaml#/definitions/flag
@@ -53,6 +45,15 @@ patternProperties:
oneOf:
- $ref: /schemas/types.yaml#/definitions/flag
- $ref: /schemas/types.yaml#/definitions/phandle
+ clocks:
+ description: Indicates system clock
+ $ref: /schemas/types.yaml#/definitions/phandle
+ system-clock-frequency:
+ $ref: "simple-card.yaml#/definitions/system-clock-frequency"
+ system-clock-direction-out:
+ $ref: "simple-card.yaml#/definitions/system-clock-direction-out"
+ system-clock-fixed:
+ $ref: "simple-card.yaml#/definitions/system-clock-fixed"
dai-format:
description: audio format.
@@ -100,4 +101,24 @@ patternProperties:
minimum: 1
maximum: 64
+ ports:
+ $ref: "#/definitions/port-base"
+ unevaluatedProperties: false
+ patternProperties:
+ "^port(@[0-9a-f]+)?$":
+ $ref: "#/definitions/port-base"
+ unevaluatedProperties: false
+ patternProperties:
+ "^endpoint(@[0-9a-f]+)?":
+ $ref: "#/definitions/endpoint-base"
+ unevaluatedProperties: false
+
+allOf:
+ - $ref: "#/definitions/port-base"
+
+patternProperties:
+ "^endpoint(@[0-9a-f]+)?":
+ $ref: "#/definitions/endpoint-base"
+ unevaluatedProperties: false
+
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/sound/fsl,sai.yaml b/Documentation/devicetree/bindings/sound/fsl,sai.yaml
index 7e56337d8edc..088c26b001cc 100644
--- a/Documentation/devicetree/bindings/sound/fsl,sai.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,sai.yaml
@@ -76,10 +76,14 @@ properties:
minItems: 4
dmas:
- maxItems: 2
+ items:
+ - description: DMA controller phandle and request line for RX
+ - description: DMA controller phandle and request line for TX
dma-names:
- maxItems: 2
+ items:
+ - const: rx
+ - const: tx
interrupts:
items:
@@ -143,31 +147,6 @@ properties:
allOf:
- $ref: dai-common.yaml#
- if:
- properties:
- compatible:
- contains:
- const: fsl,vf610-sai
- then:
- properties:
- dmas:
- items:
- - description: DMA controller phandle and request line for TX
- - description: DMA controller phandle and request line for RX
- dma-names:
- items:
- - const: tx
- - const: rx
- else:
- properties:
- dmas:
- items:
- - description: DMA controller phandle and request line for RX
- - description: DMA controller phandle and request line for TX
- dma-names:
- items:
- - const: rx
- - const: tx
- - if:
required:
- fsl,sai-asynchronous
then:
@@ -199,9 +178,8 @@ examples:
<&clks VF610_CLK_SAI2>,
<&clks 0>, <&clks 0>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
- dma-names = "tx", "rx";
- dmas = <&edma0 0 21>,
- <&edma0 0 20>;
+ dma-names = "rx", "tx";
+ dmas = <&edma0 0 20>, <&edma0 0 21>;
big-endian;
lsb-first;
};
diff --git a/Documentation/devicetree/bindings/sound/irondevice,sma1303.yaml b/Documentation/devicetree/bindings/sound/irondevice,sma1303.yaml
index eb87374cc812..162c52606635 100644
--- a/Documentation/devicetree/bindings/sound/irondevice,sma1303.yaml
+++ b/Documentation/devicetree/bindings/sound/irondevice,sma1303.yaml
@@ -19,14 +19,13 @@ required:
- compatible
- reg
-additionalProperties: true
+additionalProperties: false
examples:
- |
- #include <dt-bindings/gpio/gpio.h>
i2c_bus {
- sma1303_amp: sma1303@1e {
- compatible = "irondevice,sma1303";
- reg = <0x1e>;
- };
- };
+ amplifier@1e {
+ compatible = "irondevice,sma1303";
+ reg = <0x1e>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml
index b1f08d6af38d..66175aeba7a7 100644
--- a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml
+++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml
@@ -64,6 +64,7 @@ properties:
description: |
it must be 0 if your system is using single DAI
it must be 1 if your system is using multi DAIs
+ This is used on simple-audio-card
enum: [0, 1]
"#clock-cells":
@@ -109,15 +110,34 @@ properties:
- pattern: '^clk_(a|b|c|i)$'
ports:
- $ref: /schemas/graph.yaml#/properties/ports
+ $ref: audio-graph-port.yaml#/definitions/port-base
+ unevaluatedProperties: false
patternProperties:
'^port(@[0-9a-f]+)?$':
- $ref: audio-graph-port.yaml#
+ $ref: audio-graph-port.yaml#/definitions/port-base
unevaluatedProperties: false
+ patternProperties:
+ "^endpoint(@[0-9a-f]+)?":
+ $ref: audio-graph-port.yaml#/definitions/endpoint-base
+ properties:
+ playback:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ capture:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ unevaluatedProperties: false
port:
- $ref: audio-graph-port.yaml#
+ $ref: audio-graph-port.yaml#/definitions/port-base
unevaluatedProperties: false
+ patternProperties:
+ "^endpoint(@[0-9a-f]+)?":
+ $ref: audio-graph-port.yaml#/definitions/endpoint-base
+ properties:
+ playback:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ capture:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ unevaluatedProperties: false
rcar_sound,dvc:
description: DVC subnode.
@@ -174,10 +194,6 @@ properties:
enum:
- tx
- rx
- required:
- - interrupts
- - dmas
- - dma-names
additionalProperties: false
rcar_sound,ssiu:
@@ -267,7 +283,6 @@ required:
- reg-names
- clocks
- clock-names
- - "#sound-dai-cells"
allOf:
- $ref: dai-common.yaml#
diff --git a/Documentation/devicetree/bindings/sound/simple-card.yaml b/Documentation/devicetree/bindings/sound/simple-card.yaml
index cec68d42ee28..f0d81bfe2598 100644
--- a/Documentation/devicetree/bindings/sound/simple-card.yaml
+++ b/Documentation/devicetree/bindings/sound/simple-card.yaml
@@ -217,6 +217,10 @@ patternProperties:
reg:
maxItems: 1
+ "#address-cells":
+ const: 1
+ "#size-cells":
+ const: 0
# common properties
frame-master:
$ref: "#/definitions/frame-master"
diff --git a/Documentation/devicetree/bindings/sound/tas5720.txt b/Documentation/devicetree/bindings/sound/tas5720.txt
index df99ca9451b0..7d851ae2bba2 100644
--- a/Documentation/devicetree/bindings/sound/tas5720.txt
+++ b/Documentation/devicetree/bindings/sound/tas5720.txt
@@ -6,11 +6,13 @@ audio playback. For more product information please see the links below:
https://www.ti.com/product/TAS5720L
https://www.ti.com/product/TAS5720M
+https://www.ti.com/product/TAS5720A-Q1
https://www.ti.com/product/TAS5722L
Required properties:
- compatible : "ti,tas5720",
+ "ti,tas5720a-q1",
"ti,tas5722"
- reg : I2C slave address
- dvdd-supply : phandle to a 3.3-V supply for the digital circuitry
diff --git a/Documentation/devicetree/bindings/sound/ti,pcm3168a.txt b/Documentation/devicetree/bindings/sound/ti,pcm3168a.txt
deleted file mode 100644
index a02ecaab5183..000000000000
--- a/Documentation/devicetree/bindings/sound/ti,pcm3168a.txt
+++ /dev/null
@@ -1,56 +0,0 @@
-Texas Instruments pcm3168a DT bindings
-
-This driver supports both SPI and I2C bus access for this codec
-
-Required properties:
-
- - compatible: "ti,pcm3168a"
-
- - clocks : Contains an entry for each entry in clock-names
-
- - clock-names : Includes the following entries:
- "scki" The system clock
-
- - VDD1-supply : Digital power supply regulator 1 (+3.3V)
-
- - VDD2-supply : Digital power supply regulator 2 (+3.3V)
-
- - VCCAD1-supply : ADC power supply regulator 1 (+5V)
-
- - VCCAD2-supply : ADC power supply regulator 2 (+5V)
-
- - VCCDA1-supply : DAC power supply regulator 1 (+5V)
-
- - VCCDA2-supply : DAC power supply regulator 2 (+5V)
-
-For required properties on SPI/I2C, consult SPI/I2C device tree documentation
-
-Optional properties:
-
- - reset-gpios : Optional reset gpio line connected to RST pin of the codec.
- The RST line is low active:
- RST = low: device power-down
- RST = high: device is enabled
-
-Examples:
-
-i2c0: i2c0@0 {
-
- ...
-
- pcm3168a: audio-codec@44 {
- compatible = "ti,pcm3168a";
- reg = <0x44>;
- reset-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
- clocks = <&clk_core CLK_AUDIO>;
- clock-names = "scki";
- VDD1-supply = <&supply3v3>;
- VDD2-supply = <&supply3v3>;
- VCCAD1-supply = <&supply5v0>;
- VCCAD2-supply = <&supply5v0>;
- VCCDA1-supply = <&supply5v0>;
- VCCDA2-supply = <&supply5v0>;
- pinctrl-names = "default";
- pinctrl-0 = <&dac_clk_pin>;
- };
-};
diff --git a/Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml b/Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml
new file mode 100644
index 000000000000..b6a4360ab845
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml
@@ -0,0 +1,107 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/ti,pcm3168a.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments PCM3168A Audio Codec
+
+maintainers:
+ - Damien Horsley <[email protected]>
+ - Geert Uytterhoeven <[email protected]>
+ - Kuninori Morimoto <[email protected]>
+
+description:
+ The Texas Instruments PCM3168A is a 24-bit Multi-channel Audio CODEC with
+ 96/192kHz sampling rate, supporting both SPI and I2C bus access.
+
+properties:
+ compatible:
+ const: ti,pcm3168a
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: System clock input
+
+ clock-names:
+ items:
+ - const: scki
+
+ reset-gpios:
+ items:
+ - description: |
+ GPIO line connected to the active-low RST pin of the codec.
+ RST = low: device power-down
+ RST = high: device is enabled
+
+ "#sound-dai-cells":
+ enum: [0, 1]
+
+ VDD1-supply:
+ description: Digital power supply regulator 1 (+3.3V)
+
+ VDD2-supply:
+ description: Digital power supply regulator 2 (+3.3V)
+
+ VCCAD1-supply:
+ description: ADC power supply regulator 1 (+5V)
+
+ VCCAD2-supply:
+ description: ADC power supply regulator 2 (+5V)
+
+ VCCDA1-supply:
+ description: DAC power supply regulator 1 (+5V)
+
+ VCCDA2-supply:
+ description: DAC power supply regulator 2 (+5V)
+
+ ports:
+ $ref: audio-graph-port.yaml#/definitions/port-base
+ properties:
+ port@0:
+ $ref: audio-graph-port.yaml#
+ description: Audio input port.
+
+ port@1:
+ $ref: audio-graph-port.yaml#
+ description: Audio output port.
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - VDD1-supply
+ - VDD2-supply
+ - VCCAD1-supply
+ - VCCAD2-supply
+ - VCCDA1-supply
+ - VCCDA2-supply
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pcm3168a: audio-codec@44 {
+ compatible = "ti,pcm3168a";
+ reg = <0x44>;
+ reset-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
+ clocks = <&clk_core 42>;
+ clock-names = "scki";
+ VDD1-supply = <&supply3v3>;
+ VDD2-supply = <&supply3v3>;
+ VCCAD1-supply = <&supply5v0>;
+ VCCAD2-supply = <&supply5v0>;
+ VCCDA1-supply = <&supply5v0>;
+ VCCDA2-supply = <&supply5v0>;
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 3674675e83f5..3732dc391160 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10920,6 +10920,13 @@ M: David Sterba <[email protected]>
S: Odd Fixes
F: drivers/tty/ipwireless/
+IRON DEVICE AUDIO CODEC DRIVERS
+M: Kiseok Jo <[email protected]>
+L: [email protected] (moderated for non-subscribers)
+S: Maintained
+F: Documentation/devicetree/bindings/sound/irondevice,*
+F: sound/soc/codecs/sma*
+
IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
M: Marc Zyngier <[email protected]>
S: Maintained
diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h
index b4b896f83b94..f055c6917f6c 100644
--- a/include/sound/soc-topology.h
+++ b/include/sound/soc-topology.h
@@ -62,7 +62,7 @@ struct snd_soc_dobj {
enum snd_soc_dobj_type type;
unsigned int index; /* objects can belong in different groups */
struct list_head list;
- struct snd_soc_tplg_ops *ops;
+ int (*unload)(struct snd_soc_component *comp, struct snd_soc_dobj *dobj);
union {
struct snd_soc_dobj_control control;
struct snd_soc_dobj_widget widget;
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
index b83ae946b3e4..b4dcce4fbae9 100644
--- a/sound/soc/amd/acp/acp-mach-common.c
+++ b/sound/soc/amd/acp/acp-mach-common.c
@@ -186,7 +186,7 @@ static int acp_card_rt5682_hw_params(struct snd_pcm_substream *substream,
srate = params_rate(params);
ch = params_channels(params);
- format = 8 * params_format(params);
+ format = params_physical_width(params);
if (drvdata->tdm_mode)
fmt = SND_SOC_DAIFMT_DSP_A;
@@ -330,7 +330,7 @@ static int acp_card_rt5682s_hw_params(struct snd_pcm_substream *substream,
srate = params_rate(params);
ch = params_channels(params);
- format = 8 * params_format(params);
+ format = params_physical_width(params);
if (drvdata->tdm_mode)
fmt = SND_SOC_DAIFMT_DSP_A;
@@ -475,7 +475,7 @@ static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream,
srate = params_rate(params);
ch = params_channels(params);
- format = 8 * params_format(params);
+ format = params_physical_width(params);
if (drvdata->amp_codec_id != RT1019)
return -EINVAL;
@@ -616,7 +616,7 @@ static int acp_card_maxim_hw_params(struct snd_pcm_substream *substream,
srate = params_rate(params);
ch = params_channels(params);
- format = 8 * params_format(params);
+ format = params_physical_width(params);
if (drvdata->tdm_mode)
fmt = SND_SOC_DAIFMT_DSP_A;
diff --git a/sound/soc/codecs/sma1303.c b/sound/soc/codecs/sma1303.c
index d3ee831e88f0..fbedba574ff4 100644
--- a/sound/soc/codecs/sma1303.c
+++ b/sound/soc/codecs/sma1303.c
@@ -500,7 +500,7 @@ static int sma1303_aif_in_event(struct snd_soc_dapm_widget *w,
sma1303->amp_mode = SMA1303_STEREO;
break;
default:
- dev_err(sma1303->dev, "%s : Invald value (%d)\n",
+ dev_err(sma1303->dev, "%s : Invalid value (%d)\n",
__func__, mux);
return -EINVAL;
}
@@ -640,7 +640,7 @@ static int sma1303_aif_out_event(struct snd_soc_dapm_widget *w,
change = true;
break;
default:
- dev_err(sma1303->dev, "%s : Invald value (%d)\n",
+ dev_err(sma1303->dev, "%s : Invalid value (%d)\n",
__func__, mux);
return -EINVAL;
}
@@ -1597,8 +1597,7 @@ static struct attribute_group sma1303_attr_group = {
.attrs = sma1303_attr,
};
-static int sma1303_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int sma1303_i2c_probe(struct i2c_client *client)
{
struct sma1303_priv *sma1303;
struct device_node *np = client->dev.of_node;
@@ -1791,7 +1790,7 @@ static struct i2c_driver sma1303_i2c_driver = {
.name = "sma1303",
.of_match_table = sma1303_of_match,
},
- .probe = sma1303_i2c_probe,
+ .probe_new = sma1303_i2c_probe,
.remove = sma1303_i2c_remove,
.id_table = sma1303_i2c_id,
};
diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c
index 3885c0bf0b01..de6d01c8fdd3 100644
--- a/sound/soc/codecs/tas5720.c
+++ b/sound/soc/codecs/tas5720.c
@@ -30,6 +30,7 @@
enum tas572x_type {
TAS5720,
+ TAS5720A_Q1,
TAS5722,
};
@@ -166,17 +167,26 @@ static int tas5720_set_dai_tdm_slot(struct snd_soc_dai *dai,
return -EINVAL;
}
- /* Enable manual TDM slot selection (instead of I2C ID based) */
- ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL1_REG,
- TAS5720_TDM_CFG_SRC, TAS5720_TDM_CFG_SRC);
- if (ret < 0)
- goto error_snd_soc_component_update_bits;
+ /*
+ * Enable manual TDM slot selection (instead of I2C ID based).
+ * This is not applicable to TAS5720A-Q1.
+ */
+ switch (tas5720->devtype) {
+ case TAS5720A_Q1:
+ break;
+ default:
+ ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL1_REG,
+ TAS5720_TDM_CFG_SRC, TAS5720_TDM_CFG_SRC);
+ if (ret < 0)
+ goto error_snd_soc_component_update_bits;
- /* Configure the TDM slot to process audio from */
- ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL2_REG,
- TAS5720_TDM_SLOT_SEL_MASK, first_slot);
- if (ret < 0)
- goto error_snd_soc_component_update_bits;
+ /* Configure the TDM slot to process audio from */
+ ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL2_REG,
+ TAS5720_TDM_SLOT_SEL_MASK, first_slot);
+ if (ret < 0)
+ goto error_snd_soc_component_update_bits;
+ break;
+ }
/* Configure TDM slot width. This is only applicable to TAS5722. */
switch (tas5720->devtype) {
@@ -199,13 +209,24 @@ error_snd_soc_component_update_bits:
return ret;
}
-static int tas5720_mute(struct snd_soc_dai *dai, int mute, int direction)
+static int tas5720_mute_soc_component(struct snd_soc_component *component, int mute)
{
- struct snd_soc_component *component = dai->component;
+ struct tas5720_data *tas5720 = snd_soc_component_get_drvdata(component);
+ unsigned int reg, mask;
int ret;
- ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL2_REG,
- TAS5720_MUTE, mute ? TAS5720_MUTE : 0);
+ switch (tas5720->devtype) {
+ case TAS5720A_Q1:
+ reg = TAS5720_Q1_VOLUME_CTRL_CFG_REG;
+ mask = TAS5720_Q1_MUTE;
+ break;
+ default:
+ reg = TAS5720_DIGITAL_CTRL2_REG;
+ mask = TAS5720_MUTE;
+ break;
+ }
+
+ ret = snd_soc_component_update_bits(component, reg, mask, mute ? mask : 0);
if (ret < 0) {
dev_err(component->dev, "error (un-)muting device: %d\n", ret);
return ret;
@@ -214,6 +235,11 @@ static int tas5720_mute(struct snd_soc_dai *dai, int mute, int direction)
return 0;
}
+static int tas5720_mute(struct snd_soc_dai *dai, int mute, int direction)
+{
+ return tas5720_mute_soc_component(dai->component, mute);
+}
+
static void tas5720_fault_check_work(struct work_struct *work)
{
struct tas5720_data *tas5720 = container_of(work, struct tas5720_data,
@@ -305,6 +331,9 @@ static int tas5720_codec_probe(struct snd_soc_component *component)
case TAS5720:
expected_device_id = TAS5720_DEVICE_ID;
break;
+ case TAS5720A_Q1:
+ expected_device_id = TAS5720A_Q1_DEVICE_ID;
+ break;
case TAS5722:
expected_device_id = TAS5722_DEVICE_ID;
break;
@@ -318,8 +347,20 @@ static int tas5720_codec_probe(struct snd_soc_component *component)
expected_device_id, device_id);
/* Set device to mute */
- ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL2_REG,
- TAS5720_MUTE, TAS5720_MUTE);
+ ret = tas5720_mute_soc_component(component, 1);
+ if (ret < 0)
+ goto error_snd_soc_component_update_bits;
+
+ /* Set Bit 7 in TAS5720_ANALOG_CTRL_REG to 1 for TAS5720A_Q1 */
+ switch (tas5720->devtype) {
+ case TAS5720A_Q1:
+ ret = snd_soc_component_update_bits(component, TAS5720_ANALOG_CTRL_REG,
+ TAS5720_Q1_RESERVED7_BIT,
+ TAS5720_Q1_RESERVED7_BIT);
+ break;
+ default:
+ break;
+ }
if (ret < 0)
goto error_snd_soc_component_update_bits;
@@ -471,6 +512,15 @@ static const struct regmap_config tas5720_regmap_config = {
.volatile_reg = tas5720_is_volatile_reg,
};
+static const struct regmap_config tas5720a_q1_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = TAS5720_MAX_REG,
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_reg = tas5720_is_volatile_reg,
+};
+
static const struct regmap_config tas5722_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -492,6 +542,16 @@ static const DECLARE_TLV_DB_RANGE(dac_analog_tlv,
);
/*
+ * DAC analog gain for TAS5720A-Q1. There are three discrete values to select from, ranging
+ * from 19.2 dB to 25.0dB.
+ */
+static const DECLARE_TLV_DB_RANGE(dac_analog_tlv_a_q1,
+ 0x0, 0x0, TLV_DB_SCALE_ITEM(1920, 0, 0),
+ 0x1, 0x1, TLV_DB_SCALE_ITEM(2260, 0, 0),
+ 0x2, 0x2, TLV_DB_SCALE_ITEM(2500, 0, 0),
+);
+
+/*
* DAC digital volumes. From -103.5 to 24 dB in 0.5 dB or 0.25 dB steps
* depending on the device. Note that setting the gain below -100 dB
* (register value <0x7) is effectively a MUTE as per device datasheet.
@@ -537,6 +597,15 @@ static const struct snd_kcontrol_new tas5720_snd_controls[] = {
TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv),
};
+static const struct snd_kcontrol_new tas5720a_q1_snd_controls[] = {
+ SOC_DOUBLE_R_TLV("Speaker Driver Playback Volume",
+ TAS5720_Q1_VOLUME_CTRL_LEFT_REG,
+ TAS5720_Q1_VOLUME_CTRL_RIGHT_REG,
+ 0, 0xff, 0, tas5720_dac_tlv),
+ SOC_SINGLE_TLV("Speaker Driver Analog Gain", TAS5720_ANALOG_CTRL_REG,
+ TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv_a_q1),
+};
+
static const struct snd_kcontrol_new tas5722_snd_controls[] = {
SOC_SINGLE_EXT_TLV("Speaker Driver Playback Volume",
0, 0, 511, 0,
@@ -574,6 +643,22 @@ static const struct snd_soc_component_driver soc_component_dev_tas5720 = {
.endianness = 1,
};
+static const struct snd_soc_component_driver soc_component_dev_tas5720_a_q1 = {
+ .probe = tas5720_codec_probe,
+ .remove = tas5720_codec_remove,
+ .suspend = tas5720_suspend,
+ .resume = tas5720_resume,
+ .controls = tas5720a_q1_snd_controls,
+ .num_controls = ARRAY_SIZE(tas5720a_q1_snd_controls),
+ .dapm_widgets = tas5720_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets),
+ .dapm_routes = tas5720_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(tas5720_audio_map),
+ .idle_bias_on = 1,
+ .use_pmdown_time = 1,
+ .endianness = 1,
+};
+
static const struct snd_soc_component_driver soc_component_dev_tas5722 = {
.probe = tas5720_codec_probe,
.remove = tas5720_codec_remove,
@@ -633,6 +718,7 @@ static struct snd_soc_dai_driver tas5720_dai[] = {
static const struct i2c_device_id tas5720_id[] = {
{ "tas5720", TAS5720 },
+ { "tas5720a-q1", TAS5720A_Q1 },
{ "tas5722", TAS5722 },
{ }
};
@@ -659,6 +745,9 @@ static int tas5720_probe(struct i2c_client *client)
case TAS5720:
regmap_config = &tas5720_regmap_config;
break;
+ case TAS5720A_Q1:
+ regmap_config = &tas5720a_q1_regmap_config;
+ break;
case TAS5722:
regmap_config = &tas5722_regmap_config;
break;
@@ -692,6 +781,12 @@ static int tas5720_probe(struct i2c_client *client)
tas5720_dai,
ARRAY_SIZE(tas5720_dai));
break;
+ case TAS5720A_Q1:
+ ret = devm_snd_soc_register_component(&client->dev,
+ &soc_component_dev_tas5720_a_q1,
+ tas5720_dai,
+ ARRAY_SIZE(tas5720_dai));
+ break;
case TAS5722:
ret = devm_snd_soc_register_component(&client->dev,
&soc_component_dev_tas5722,
@@ -713,6 +808,7 @@ static int tas5720_probe(struct i2c_client *client)
#if IS_ENABLED(CONFIG_OF)
static const struct of_device_id tas5720_of_match[] = {
{ .compatible = "ti,tas5720", },
+ { .compatible = "ti,tas5720a-q1", },
{ .compatible = "ti,tas5722", },
{ },
};
diff --git a/sound/soc/codecs/tas5720.h b/sound/soc/codecs/tas5720.h
index 223858f0de71..54b59b05ef0a 100644
--- a/sound/soc/codecs/tas5720.h
+++ b/sound/soc/codecs/tas5720.h
@@ -10,7 +10,7 @@
#ifndef __TAS5720_H__
#define __TAS5720_H__
-/* Register Address Map */
+/* Register Address Map - first 3 regs are common for all variants */
#define TAS5720_DEVICE_ID_REG 0x00
#define TAS5720_POWER_CTRL_REG 0x01
#define TAS5720_DIGITAL_CTRL1_REG 0x02
@@ -27,7 +27,13 @@
#define TAS5722_ANALOG_CTRL2_REG 0x14
#define TAS5722_MAX_REG TAS5722_ANALOG_CTRL2_REG
+/* Register Address Map - volume controls for the TAS5720-Q1 variant */
+#define TAS5720_Q1_VOLUME_CTRL_CFG_REG 0x03
+#define TAS5720_Q1_VOLUME_CTRL_LEFT_REG 0x04
+#define TAS5720_Q1_VOLUME_CTRL_RIGHT_REG 0x05
+
/* TAS5720_DEVICE_ID_REG */
+#define TAS5720A_Q1_DEVICE_ID 0x00
#define TAS5720_DEVICE_ID 0x01
#define TAS5722_DEVICE_ID 0x12
@@ -53,6 +59,10 @@
#define TAS5720_MUTE BIT(4)
#define TAS5720_TDM_SLOT_SEL_MASK GENMASK(2, 0)
+/* TAS5720_Q1_VOLUME_CTRL_CFG_REG */
+#define TAS5720_Q1_FADE BIT(7)
+#define TAS5720_Q1_MUTE GENMASK(1, 0)
+
/* TAS5720_ANALOG_CTRL_REG */
#define TAS5720_PWM_RATE_6_3_FSYNC (0x0 << 4)
#define TAS5720_PWM_RATE_8_4_FSYNC (0x1 << 4)
@@ -70,6 +80,10 @@
#define TAS5720_ANALOG_GAIN_MASK GENMASK(3, 2)
#define TAS5720_ANALOG_GAIN_SHIFT (0x2)
+/* TAS5720_Q1_ANALOG_CTRL_REG */
+#define TAS5720_Q1_RESERVED7_BIT BIT(7)
+#define TAS5720_Q1_CHAN_SEL BIT(1)
+
/* TAS5720_FAULT_REG */
#define TAS5720_OC_THRESH_100PCT (0x0 << 4)
#define TAS5720_OC_THRESH_75PCT (0x1 << 4)
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index c3be24b2fac5..e66b0d9e387a 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -44,9 +44,8 @@
#define SOC_TPLG_PASS_WIDGET 3
#define SOC_TPLG_PASS_PCM_DAI 4
#define SOC_TPLG_PASS_GRAPH 5
-#define SOC_TPLG_PASS_PINS 6
-#define SOC_TPLG_PASS_BE_DAI 7
-#define SOC_TPLG_PASS_LINK 8
+#define SOC_TPLG_PASS_BE_DAI 6
+#define SOC_TPLG_PASS_LINK 7
#define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST
#define SOC_TPLG_PASS_END SOC_TPLG_PASS_LINK
@@ -77,9 +76,6 @@ struct soc_tplg {
struct snd_soc_tplg_ops *ops;
};
-static int soc_tplg_process_headers(struct soc_tplg *tplg);
-static int soc_tplg_complete(struct soc_tplg *tplg);
-
/* check we dont overflow the data for this control chunk */
static int soc_tplg_check_elem_count(struct soc_tplg *tplg, size_t elem_size,
unsigned int count, size_t bytes, const char *elem_type)
@@ -186,7 +182,7 @@ static const struct soc_tplg_map dapm_map[] = {
{SND_SOC_TPLG_DAPM_DECODER, snd_soc_dapm_decoder},
};
-static int tplc_chan_get_reg(struct soc_tplg *tplg,
+static int tplg_chan_get_reg(struct soc_tplg *tplg,
struct snd_soc_tplg_channel *chan, int map)
{
int i;
@@ -199,7 +195,7 @@ static int tplc_chan_get_reg(struct soc_tplg *tplg,
return -EINVAL;
}
-static int tplc_chan_get_shift(struct soc_tplg *tplg,
+static int tplg_chan_get_shift(struct soc_tplg *tplg,
struct snd_soc_tplg_channel *chan, int map)
{
int i;
@@ -354,69 +350,37 @@ static int soc_tplg_add_kcontrol(struct soc_tplg *tplg,
tplg->dev, k, comp->name_prefix, comp, kcontrol);
}
-/* remove a mixer kcontrol */
-static void remove_mixer(struct snd_soc_component *comp,
- struct snd_soc_dobj *dobj, int pass)
-{
- struct snd_card *card = comp->card->snd_card;
-
- if (pass != SOC_TPLG_PASS_CONTROL)
- return;
-
- if (dobj->ops && dobj->ops->control_unload)
- dobj->ops->control_unload(comp, dobj);
-
- snd_ctl_remove(card, dobj->control.kcontrol);
- list_del(&dobj->list);
-}
-
-/* remove an enum kcontrol */
-static void remove_enum(struct snd_soc_component *comp,
- struct snd_soc_dobj *dobj, int pass)
-{
- struct snd_card *card = comp->card->snd_card;
-
- if (pass != SOC_TPLG_PASS_CONTROL)
- return;
-
- if (dobj->ops && dobj->ops->control_unload)
- dobj->ops->control_unload(comp, dobj);
-
- snd_ctl_remove(card, dobj->control.kcontrol);
- list_del(&dobj->list);
-}
-
-/* remove a byte kcontrol */
-static void remove_bytes(struct snd_soc_component *comp,
- struct snd_soc_dobj *dobj, int pass)
+/* remove kcontrol */
+static void soc_tplg_remove_kcontrol(struct snd_soc_component *comp, struct snd_soc_dobj *dobj,
+ int pass)
{
struct snd_card *card = comp->card->snd_card;
if (pass != SOC_TPLG_PASS_CONTROL)
return;
- if (dobj->ops && dobj->ops->control_unload)
- dobj->ops->control_unload(comp, dobj);
+ if (dobj->unload)
+ dobj->unload(comp, dobj);
snd_ctl_remove(card, dobj->control.kcontrol);
list_del(&dobj->list);
}
/* remove a route */
-static void remove_route(struct snd_soc_component *comp,
+static void soc_tplg_remove_route(struct snd_soc_component *comp,
struct snd_soc_dobj *dobj, int pass)
{
if (pass != SOC_TPLG_PASS_GRAPH)
return;
- if (dobj->ops && dobj->ops->dapm_route_unload)
- dobj->ops->dapm_route_unload(comp, dobj);
+ if (dobj->unload)
+ dobj->unload(comp, dobj);
list_del(&dobj->list);
}
/* remove a widget and it's kcontrols - routes must be removed first */
-static void remove_widget(struct snd_soc_component *comp,
+static void soc_tplg_remove_widget(struct snd_soc_component *comp,
struct snd_soc_dobj *dobj, int pass)
{
struct snd_card *card = comp->card->snd_card;
@@ -427,8 +391,8 @@ static void remove_widget(struct snd_soc_component *comp,
if (pass != SOC_TPLG_PASS_WIDGET)
return;
- if (dobj->ops && dobj->ops->widget_unload)
- dobj->ops->widget_unload(comp, dobj);
+ if (dobj->unload)
+ dobj->unload(comp, dobj);
if (!w->kcontrols)
goto free_news;
@@ -444,7 +408,7 @@ free_news:
}
/* remove DAI configurations */
-static void remove_dai(struct snd_soc_component *comp,
+static void soc_tplg_remove_dai(struct snd_soc_component *comp,
struct snd_soc_dobj *dobj, int pass)
{
struct snd_soc_dai_driver *dai_drv =
@@ -454,8 +418,8 @@ static void remove_dai(struct snd_soc_component *comp,
if (pass != SOC_TPLG_PASS_PCM_DAI)
return;
- if (dobj->ops && dobj->ops->dai_unload)
- dobj->ops->dai_unload(comp, dobj);
+ if (dobj->unload)
+ dobj->unload(comp, dobj);
for_each_component_dais_safe(comp, dai, _dai)
if (dai->driver == dai_drv)
@@ -465,7 +429,7 @@ static void remove_dai(struct snd_soc_component *comp,
}
/* remove link configurations */
-static void remove_link(struct snd_soc_component *comp,
+static void soc_tplg_remove_link(struct snd_soc_component *comp,
struct snd_soc_dobj *dobj, int pass)
{
struct snd_soc_dai_link *link =
@@ -474,8 +438,8 @@ static void remove_link(struct snd_soc_component *comp,
if (pass != SOC_TPLG_PASS_PCM_DAI)
return;
- if (dobj->ops && dobj->ops->link_unload)
- dobj->ops->link_unload(comp, dobj);
+ if (dobj->unload)
+ dobj->unload(comp, dobj);
list_del(&dobj->list);
snd_soc_remove_pcm_runtime(comp->card,
@@ -489,11 +453,11 @@ static void remove_backend_link(struct snd_soc_component *comp,
if (pass != SOC_TPLG_PASS_LINK)
return;
- if (dobj->ops && dobj->ops->link_unload)
- dobj->ops->link_unload(comp, dobj);
+ if (dobj->unload)
+ dobj->unload(comp, dobj);
/*
- * We don't free the link here as what remove_link() do since BE
+ * We don't free the link here as what soc_tplg_remove_link() do since BE
* links are not allocated by topology.
* We however need to reset the dobj type to its initial values
*/
@@ -714,7 +678,8 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size)
sbe->max = le32_to_cpu(be->max);
sbe->dobj.type = SND_SOC_DOBJ_BYTES;
- sbe->dobj.ops = tplg->ops;
+ if (tplg->ops)
+ sbe->dobj.unload = tplg->ops->control_unload;
INIT_LIST_HEAD(&sbe->dobj.list);
/* map io handlers */
@@ -725,7 +690,7 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size)
}
/* pass control to driver for optional further init */
- ret = soc_tplg_control_load(tplg, &kc, (struct snd_soc_tplg_ctl_hdr *)be);
+ ret = soc_tplg_control_load(tplg, &kc, &be->hdr);
if (ret < 0) {
dev_err(tplg->dev, "ASoC: failed to init %s\n", be->hdr.name);
goto err;
@@ -780,18 +745,19 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, size_t size)
kc.access = le32_to_cpu(mc->hdr.access);
/* we only support FL/FR channel mapping atm */
- sm->reg = tplc_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL);
- sm->rreg = tplc_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR);
- sm->shift = tplc_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL);
- sm->rshift = tplc_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR);
+ sm->reg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL);
+ sm->rreg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR);
+ sm->shift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL);
+ sm->rshift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR);
sm->max = le32_to_cpu(mc->max);
sm->min = le32_to_cpu(mc->min);
sm->invert = le32_to_cpu(mc->invert);
sm->platform_max = le32_to_cpu(mc->platform_max);
sm->dobj.index = tplg->index;
- sm->dobj.ops = tplg->ops;
sm->dobj.type = SND_SOC_DOBJ_MIXER;
+ if (tplg->ops)
+ sm->dobj.unload = tplg->ops->control_unload;
INIT_LIST_HEAD(&sm->dobj.list);
/* map io handlers */
@@ -809,7 +775,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, size_t size)
}
/* pass control to driver for optional further init */
- ret = soc_tplg_control_load(tplg, &kc, (struct snd_soc_tplg_ctl_hdr *)mc);
+ ret = soc_tplg_control_load(tplg, &kc, &mc->hdr);
if (ret < 0) {
dev_err(tplg->dev, "ASoC: failed to init %s\n", mc->hdr.name);
goto err;
@@ -927,16 +893,17 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, size_t size)
kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
kc.access = le32_to_cpu(ec->hdr.access);
- se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL);
- se->shift_l = tplc_chan_get_shift(tplg, ec->channel,
+ se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL);
+ se->shift_l = tplg_chan_get_shift(tplg, ec->channel,
SNDRV_CHMAP_FL);
- se->shift_r = tplc_chan_get_shift(tplg, ec->channel,
+ se->shift_r = tplg_chan_get_shift(tplg, ec->channel,
SNDRV_CHMAP_FL);
se->mask = le32_to_cpu(ec->mask);
se->dobj.index = tplg->index;
se->dobj.type = SND_SOC_DOBJ_ENUM;
- se->dobj.ops = tplg->ops;
+ if (tplg->ops)
+ se->dobj.unload = tplg->ops->control_unload;
INIT_LIST_HEAD(&se->dobj.list);
switch (le32_to_cpu(ec->hdr.ops.info)) {
@@ -977,7 +944,7 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, size_t size)
}
/* pass control to driver for optional further init */
- ret = soc_tplg_control_load(tplg, &kc, (struct snd_soc_tplg_ctl_hdr *)ec);
+ ret = soc_tplg_control_load(tplg, &kc, &ec->hdr);
if (ret < 0) {
dev_err(tplg->dev, "ASoC: failed to init %s\n", ec->hdr.name);
goto err;
@@ -1113,7 +1080,8 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
/* add route dobj to dobj_list */
route->dobj.type = SND_SOC_DOBJ_GRAPH;
- route->dobj.ops = tplg->ops;
+ if (tplg->ops)
+ route->dobj.unload = tplg->ops->control_unload;
route->dobj.index = tplg->index;
list_add(&route->dobj.list, &tplg->comp->dobj_list);
@@ -1161,13 +1129,13 @@ static int soc_tplg_dapm_widget_dmixer_create(struct soc_tplg *tplg, struct snd_
kc->access = le32_to_cpu(mc->hdr.access);
/* we only support FL/FR channel mapping atm */
- sm->reg = tplc_chan_get_reg(tplg, mc->channel,
+ sm->reg = tplg_chan_get_reg(tplg, mc->channel,
SNDRV_CHMAP_FL);
- sm->rreg = tplc_chan_get_reg(tplg, mc->channel,
+ sm->rreg = tplg_chan_get_reg(tplg, mc->channel,
SNDRV_CHMAP_FR);
- sm->shift = tplc_chan_get_shift(tplg, mc->channel,
+ sm->shift = tplg_chan_get_shift(tplg, mc->channel,
SNDRV_CHMAP_FL);
- sm->rshift = tplc_chan_get_shift(tplg, mc->channel,
+ sm->rshift = tplg_chan_get_shift(tplg, mc->channel,
SNDRV_CHMAP_FR);
sm->max = le32_to_cpu(mc->max);
@@ -1193,7 +1161,7 @@ static int soc_tplg_dapm_widget_dmixer_create(struct soc_tplg *tplg, struct snd_
}
/* pass control to driver for optional further init */
- err = soc_tplg_control_load(tplg, kc, (struct snd_soc_tplg_ctl_hdr *)mc);
+ err = soc_tplg_control_load(tplg, kc, &mc->hdr);
if (err < 0) {
dev_err(tplg->dev, "ASoC: failed to init %s\n",
mc->hdr.name);
@@ -1233,10 +1201,10 @@ static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_k
kc->access = le32_to_cpu(ec->hdr.access);
/* we only support FL/FR channel mapping atm */
- se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL);
- se->shift_l = tplc_chan_get_shift(tplg, ec->channel,
+ se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL);
+ se->shift_l = tplg_chan_get_shift(tplg, ec->channel,
SNDRV_CHMAP_FL);
- se->shift_r = tplc_chan_get_shift(tplg, ec->channel,
+ se->shift_r = tplg_chan_get_shift(tplg, ec->channel,
SNDRV_CHMAP_FR);
se->items = le32_to_cpu(ec->items);
@@ -1277,7 +1245,7 @@ static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_k
}
/* pass control to driver for optional further init */
- err = soc_tplg_control_load(tplg, kc, (struct snd_soc_tplg_ctl_hdr *)ec);
+ err = soc_tplg_control_load(tplg, kc, &ec->hdr);
if (err < 0) {
dev_err(tplg->dev, "ASoC: failed to init %s\n",
ec->hdr.name);
@@ -1329,7 +1297,7 @@ static int soc_tplg_dapm_widget_dbytes_create(struct soc_tplg *tplg, struct snd_
}
/* pass control to driver for optional further init */
- err = soc_tplg_control_load(tplg, kc, (struct snd_soc_tplg_ctl_hdr *)be);
+ err = soc_tplg_control_load(tplg, kc, &be->hdr);
if (err < 0) {
dev_err(tplg->dev, "ASoC: failed to init %s\n",
be->hdr.name);
@@ -1479,7 +1447,8 @@ widget:
widget->dobj.type = SND_SOC_DOBJ_WIDGET;
widget->dobj.widget.kcontrol_type = kcontrol_type;
- widget->dobj.ops = tplg->ops;
+ if (tplg->ops)
+ widget->dobj.unload = tplg->ops->widget_unload;
widget->dobj.index = tplg->index;
list_add(&widget->dobj.list, &tplg->comp->dobj_list);
@@ -1493,7 +1462,7 @@ widget:
return 0;
ready_err:
- remove_widget(widget->dapm->component, &widget->dobj, SOC_TPLG_PASS_WIDGET);
+ soc_tplg_remove_widget(widget->dapm->component, &widget->dobj, SOC_TPLG_PASS_WIDGET);
snd_soc_dapm_free_widget(widget);
hdr_err:
kfree(template.sname);
@@ -1567,7 +1536,7 @@ static int soc_tplg_dapm_complete(struct soc_tplg *tplg)
dev_err(tplg->dev, "ASoC: failed to create new widgets %d\n",
ret);
- return 0;
+ return ret;
}
static int set_stream_info(struct soc_tplg *tplg, struct snd_soc_pcm_stream *stream,
@@ -1657,8 +1626,9 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
}
dai_drv->dobj.index = tplg->index;
- dai_drv->dobj.ops = tplg->ops;
dai_drv->dobj.type = SND_SOC_DOBJ_PCM;
+ if (tplg->ops)
+ dai_drv->dobj.unload = tplg->ops->dai_unload;
list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list);
/* register the DAI to the component */
@@ -1727,8 +1697,9 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
link->num_platforms = 1;
link->dobj.index = tplg->index;
- link->dobj.ops = tplg->ops;
link->dobj.type = SND_SOC_DOBJ_DAI_LINK;
+ if (tplg->ops)
+ link->dobj.unload = tplg->ops->link_unload;
if (strlen(pcm->pcm_name)) {
link->name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL);
@@ -2135,8 +2106,9 @@ static int soc_tplg_link_config(struct soc_tplg *tplg,
/* for unloading it in snd_soc_tplg_component_remove */
link->dobj.index = tplg->index;
- link->dobj.ops = tplg->ops;
link->dobj.type = SND_SOC_DOBJ_BACKEND_LINK;
+ if (tplg->ops)
+ link->dobj.unload = tplg->ops->link_unload;
list_add(&link->dobj.list, &tplg->comp->dobj_list);
return 0;
@@ -2390,12 +2362,9 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg,
}
/* validate header magic, size and type */
-static int soc_valid_header(struct soc_tplg *tplg,
+static int soc_tplg_valid_header(struct soc_tplg *tplg,
struct snd_soc_tplg_hdr *hdr)
{
- if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size)
- return 0;
-
if (le32_to_cpu(hdr->size) != sizeof(*hdr)) {
dev_err(tplg->dev,
"ASoC: invalid header size for type %d at offset 0x%lx size 0x%zx.\n",
@@ -2404,7 +2373,7 @@ static int soc_valid_header(struct soc_tplg *tplg,
return -EINVAL;
}
- if (soc_tplg_get_hdr_offset(tplg) + hdr->payload_size >= tplg->fw->size) {
+ if (soc_tplg_get_hdr_offset(tplg) + le32_to_cpu(hdr->payload_size) >= tplg->fw->size) {
dev_err(tplg->dev,
"ASoC: invalid header of type %d at offset %ld payload_size %d\n",
le32_to_cpu(hdr->type), soc_tplg_get_hdr_offset(tplg),
@@ -2446,7 +2415,7 @@ static int soc_valid_header(struct soc_tplg *tplg,
return -EINVAL;
}
- return 1;
+ return 0;
}
/* check header type and call appropriate handler */
@@ -2527,13 +2496,11 @@ static int soc_tplg_process_headers(struct soc_tplg *tplg)
while (!soc_tplg_is_eof(tplg)) {
/* make sure header is valid before loading */
- ret = soc_valid_header(tplg, hdr);
+ ret = soc_tplg_valid_header(tplg, hdr);
if (ret < 0) {
dev_err(tplg->dev,
"ASoC: topology: invalid header: %d\n", ret);
return ret;
- } else if (ret == 0) {
- break;
}
/* load the header object */
@@ -2627,26 +2594,22 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp)
list) {
switch (dobj->type) {
- case SND_SOC_DOBJ_MIXER:
- remove_mixer(comp, dobj, pass);
- break;
- case SND_SOC_DOBJ_ENUM:
- remove_enum(comp, dobj, pass);
- break;
case SND_SOC_DOBJ_BYTES:
- remove_bytes(comp, dobj, pass);
+ case SND_SOC_DOBJ_ENUM:
+ case SND_SOC_DOBJ_MIXER:
+ soc_tplg_remove_kcontrol(comp, dobj, pass);
break;
case SND_SOC_DOBJ_GRAPH:
- remove_route(comp, dobj, pass);
+ soc_tplg_remove_route(comp, dobj, pass);
break;
case SND_SOC_DOBJ_WIDGET:
- remove_widget(comp, dobj, pass);
+ soc_tplg_remove_widget(comp, dobj, pass);
break;
case SND_SOC_DOBJ_PCM:
- remove_dai(comp, dobj, pass);
+ soc_tplg_remove_dai(comp, dobj, pass);
break;
case SND_SOC_DOBJ_DAI_LINK:
- remove_link(comp, dobj, pass);
+ soc_tplg_remove_link(comp, dobj, pass);
break;
case SND_SOC_DOBJ_BACKEND_LINK:
/*