Merge remote-tracking branch 'asoc/for-5.12' into asoc-linus

This commit is contained in:
Mark Brown 2021-02-17 18:52:26 +00:00
commit 0969db0d8d
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0
280 changed files with 10761 additions and 5946 deletions

View file

@ -71,9 +71,6 @@ properties:
description: CPU to Codec rate channels.
$ref: /schemas/types.yaml#/definitions/uint32
required:
- remote-endpoint
ports:
description: multi OF-Graph subnode
type: object

View file

@ -15,9 +15,14 @@ properties:
compatible:
oneOf:
- const: ingenic,jz4770-codec
- const: ingenic,jz4725b-codec
- const: ingenic,jz4740-codec
- enum:
- ingenic,jz4770-codec
- ingenic,jz4760-codec
- ingenic,jz4725b-codec
- ingenic,jz4740-codec
- items:
- const: ingenic,jz4760b-codec
- const: ingenic,jz4760-codec
reg:
maxItems: 1

View file

@ -18,6 +18,7 @@ properties:
enum:
- intel,keembay-i2s
- intel,keembay-tdm
- intel,keembay-hdmi-i2s
"#sound-dai-cells":
const: 0
@ -45,6 +46,16 @@ properties:
- const: osc
- const: apb_clk
dmas:
items:
- description: DMA TX channel
- description: DMA RX channel
dma-names:
items:
- const: tx
- const: rx
required:
- compatible
- "#sound-dai-cells"
@ -70,4 +81,6 @@ examples:
interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "osc", "apb_clk";
clocks = <&scmi_clk KEEM_BAY_PSS_AUX_I2S3>, <&scmi_clk KEEM_BAY_PSS_I2S3>;
dmas = <&axi_dma0 29 &axi_dma0 33>;
dma-names = "tx", "rx";
};

View file

@ -23,6 +23,10 @@ properties:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of MT8192 ASoC platform.
mediatek,hdmi-codec:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of HDMI codec.
additionalProperties: false
required:
@ -35,6 +39,7 @@ examples:
sound: mt8192-sound {
compatible = "mediatek,mt8192_mt6359_rt1015_rt5682";
mediatek,platform = <&afe>;
mediatek,hdmi-codec = <&anx_bridge_dp>;
pinctrl-names = "aud_clk_mosi_off",
"aud_clk_mosi_on";
pinctrl-0 = <&aud_clk_mosi_off>;

View file

@ -0,0 +1,190 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-graph-card.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Audio Graph based Tegra sound card driver
description: |
This is based on generic audio graph card driver along with additional
customizations for Tegra platforms. It uses the same bindings with
additional standard clock DT bindings required for Tegra.
maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: audio-graph.yaml#
properties:
compatible:
enum:
- nvidia,tegra210-audio-graph-card
- nvidia,tegra186-audio-graph-card
clocks:
minItems: 2
clock-names:
minItems: 2
items:
- const: pll_a
- const: plla_out0
assigned-clocks:
minItems: 1
maxItems: 3
assigned-clock-parents:
minItems: 1
maxItems: 3
assigned-clock-rates:
minItems: 1
maxItems: 3
iommus:
maxItems: 1
required:
- clocks
- clock-names
- assigned-clocks
- assigned-clock-parents
unevaluatedProperties: false
examples:
- |
#include<dt-bindings/clock/tegra210-car.h>
tegra_sound {
compatible = "nvidia,tegra210-audio-graph-card";
clocks = <&tegra_car TEGRA210_CLK_PLL_A>,
<&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
clock-names = "pll_a", "plla_out0";
assigned-clocks = <&tegra_car TEGRA210_CLK_PLL_A>,
<&tegra_car TEGRA210_CLK_PLL_A_OUT0>,
<&tegra_car TEGRA210_CLK_EXTERN1>;
assigned-clock-parents = <0>, <0>, <&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
assigned-clock-rates = <368640000>, <49152000>, <12288000>;
dais = /* FE */
<&admaif1_port>,
/* Router */
<&xbar_i2s1_port>,
/* I/O DAP Ports */
<&i2s1_port>;
label = "jetson-tx1-ape";
};
// The ports are defined for AHUB and its child devices.
ahub@702d0800 {
compatible = "nvidia,tegra210-ahub";
reg = <0x702d0800 0x800>;
clocks = <&tegra_car TEGRA210_CLK_D_AUDIO>;
clock-names = "ahub";
assigned-clocks = <&tegra_car TEGRA210_CLK_D_AUDIO>;
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x702d0000 0x702d0000 0x0000e400>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0x0>;
xbar_admaif1_ep: endpoint {
remote-endpoint = <&admaif1_ep>;
};
};
// ...
xbar_i2s1_port: port@a {
reg = <0xa>;
xbar_i2s1_ep: endpoint {
remote-endpoint = <&i2s1_cif_ep>;
};
};
};
admaif@702d0000 {
compatible = "nvidia,tegra210-admaif";
reg = <0x702d0000 0x800>;
dmas = <&adma 1>, <&adma 1>,
<&adma 2>, <&adma 2>,
<&adma 3>, <&adma 3>,
<&adma 4>, <&adma 4>,
<&adma 5>, <&adma 5>,
<&adma 6>, <&adma 6>,
<&adma 7>, <&adma 7>,
<&adma 8>, <&adma 8>,
<&adma 9>, <&adma 9>,
<&adma 10>, <&adma 10>;
dma-names = "rx1", "tx1",
"rx2", "tx2",
"rx3", "tx3",
"rx4", "tx4",
"rx5", "tx5",
"rx6", "tx6",
"rx7", "tx7",
"rx8", "tx8",
"rx9", "tx9",
"rx10", "tx10";
ports {
#address-cells = <1>;
#size-cells = <0>;
admaif1_port: port@0 {
reg = <0x0>;
admaif1_ep: endpoint {
remote-endpoint = <&xbar_admaif1_ep>;
};
};
// More ADMAIF ports to follow
};
};
i2s@702d1000 {
compatible = "nvidia,tegra210-i2s";
clocks = <&tegra_car TEGRA210_CLK_I2S0>;
clock-names = "i2s";
assigned-clocks = <&tegra_car TEGRA210_CLK_I2S0>;
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
assigned-clock-rates = <1536000>;
reg = <0x702d1000 0x100>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0x0>;
i2s1_cif_ep: endpoint {
remote-endpoint = <&xbar_i2s1_ep>;
};
};
i2s1_port: port@1 {
reg = <0x1>;
i2s1_dap: endpoint {
dai-format = "i2s";
};
};
};
};
};
...

View file

@ -17,6 +17,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: audio-graph-port.yaml#
properties:
$nodename:
pattern: "^dspk@[0-9a-f]*$"
@ -55,6 +58,19 @@ properties:
The name can be "DSPK1" or "DSPKx", where x depends on the maximum
available instances on a Tegra SoC.
ports:
type: object
properties:
port@0:
description: |
DSPK ACIF (Audio Client Interface) port connected to the
corresponding AHUB (Audio Hub) ACIF port.
port@1:
description: |
DSPK DAP (Digital Audio Port) interface which can be connected
to external audio codec for playback.
required:
- compatible
- reg
@ -64,7 +80,7 @@ required:
- assigned-clock-parents
- sound-name-prefix
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View file

@ -17,6 +17,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: audio-graph-port.yaml#
properties:
$nodename:
pattern: "^admaif@[0-9a-f]*$"
@ -37,6 +40,14 @@ properties:
dma-names: true
ports:
description: |
Contains list of ACIF (Audio CIF) port nodes for ADMAIF channels.
The number of port nodes depends on the number of ADMAIF channels
that SoC may have. These are interfaced with respective ACIF ports
in AHUB (Audio Hub). Each port is capable of data transfers in
both directions.
if:
properties:
compatible:
@ -81,7 +92,7 @@ required:
- dmas
- dma-names
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View file

@ -17,6 +17,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: audio-graph-port.yaml#
properties:
$nodename:
pattern: "^ahub@[0-9a-f]*$"
@ -56,6 +59,13 @@ properties:
ranges: true
ports:
description: |
Contains list of ACIF (Audio CIF) port nodes for AHUB (Audio Hub).
These are connected to ACIF interfaces of AHUB clients. Thus the
number of port nodes depend on the number of clients that AHUB may
have depending on the SoC revision.
required:
- compatible
- reg
@ -67,8 +77,7 @@ required:
- "#size-cells"
- ranges
additionalProperties:
type: object
unevaluatedProperties: false
examples:
- |

View file

@ -16,6 +16,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: audio-graph-port.yaml#
properties:
$nodename:
pattern: "^dmic@[0-9a-f]*$"
@ -56,6 +59,19 @@ properties:
The name can be "DMIC1" or "DMIC2" ... "DMICx", where x depends
on the maximum available instances on a Tegra SoC.
ports:
type: object
properties:
port@0:
description: |
DMIC ACIF (Audio Client Interface) port connected to the
corresponding AHUB (Audio Hub) ACIF port.
port@1:
description: |
DMIC DAP (Digital Audio Port) interface which can be connected
to external audio codec for capture.
required:
- compatible
- reg
@ -64,7 +80,7 @@ required:
- assigned-clocks
- assigned-clock-parents
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View file

@ -16,6 +16,9 @@ maintainers:
- Jon Hunter <jonathanh@nvidia.com>
- Sameer Pujar <spujar@nvidia.com>
allOf:
- $ref: audio-graph-port.yaml#
properties:
$nodename:
pattern: "^i2s@[0-9a-f]*$"
@ -74,6 +77,19 @@ properties:
The name can be "I2S1" or "I2S2" ... "I2Sx", where x depends
on the maximum available instances on a Tegra SoC.
ports:
type: object
properties:
port@0:
description: |
I2S ACIF (Audio Client Interface) port connected to the
corresponding AHUB (Audio Hub) ACIF port.
port@1:
description: |
I2S DAP (Digital Audio Port) interface which can be connected
to external audio codec for playback or capture.
required:
- compatible
- reg
@ -82,7 +98,7 @@ required:
- assigned-clocks
- assigned-clock-parents
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View file

@ -0,0 +1,62 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,lpass-rx-macro.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: LPASS(Low Power Audio Subsystem) RX Macro audio codec DT bindings
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
properties:
compatible:
const: qcom,sm8250-lpass-rx-macro
reg:
maxItems: 1
"#sound-dai-cells":
const: 1
'#clock-cells':
const: 0
clocks:
maxItems: 5
clock-names:
items:
- const: mclk
- const: npl
- const: macro
- const: dcodec
- const: fsgen
clock-output-names:
items:
- const: mclk
required:
- compatible
- reg
- "#sound-dai-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/sound/qcom,q6afe.h>
codec@3200000 {
compatible = "qcom,sm8250-lpass-rx-macro";
reg = <0x3200000 0x1000>;
#sound-dai-cells = <1>;
#clock-cells = <0>;
clocks = <&audiocc 0>,
<&audiocc 1>,
<&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&vamacro>;
clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
clock-output-names = "mclk";
};

View file

@ -0,0 +1,67 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,lpass-tx-macro.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: LPASS(Low Power Audio Subsystem) TX Macro audio codec DT bindings
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
properties:
compatible:
const: qcom,sm8250-lpass-tx-macro
reg:
maxItems: 1
"#sound-dai-cells":
const: 1
'#clock-cells':
const: 0
clocks:
maxItems: 5
clock-names:
items:
- const: mclk
- const: npl
- const: macro
- const: dcodec
- const: fsgen
clock-output-names:
items:
- const: mclk
qcom,dmic-sample-rate:
description: dmic sample rate
$ref: /schemas/types.yaml#/definitions/uint32
required:
- compatible
- reg
- "#sound-dai-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/sound/qcom,q6afe.h>
codec@3220000 {
compatible = "qcom,sm8250-lpass-tx-macro";
reg = <0x3220000 0x1000>;
#sound-dai-cells = <1>;
#clock-cells = <0>;
clocks = <&aoncc 0>,
<&aoncc 1>,
<&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&vamacro>;
clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
clock-output-names = "mclk";
qcom,dmic-sample-rate = <600000>;
};

View file

@ -404,7 +404,7 @@ examples:
/* DAI base */
rcar_sound,dai {
dai0 {
playback = <&ssi5 &src5>;
playback = <&ssi5>, <&src5>;
capture = <&ssi6>;
};
dai1 {
@ -430,8 +430,8 @@ examples:
bitclock-master = <&rsnd_endpoint0>;
frame-master = <&rsnd_endpoint0>;
playback = <&ssi0 &src0 &dvc0>;
capture = <&ssi1 &src1 &dvc1>;
playback = <&ssi0>, <&src0>, <&dvc0>;
capture = <&ssi1>, <&src1>, <&dvc1>;
};
};
};

View file

@ -37,10 +37,21 @@ Optional properties:
- realtek,jd-src
0: No JD is used
1: using JD3 as JD source
2: JD source for Intel HDA header
- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
- realtek,reset-gpios : The GPIO that controls the CODEC's RESET pin.
- sound-name-prefix: Please refer to name-prefix.txt
- ports: A Codec may have a single or multiple I2S interfaces. These
interfaces on Codec side can be described under 'ports' or 'port'.
When the SoC or host device is connected to multiple interfaces of
the Codec, the connectivity can be described using 'ports' property.
If a single interface is used, then 'port' can be used. The usage
depends on the platform or board design.
Please refer to Documentation/devicetree/bindings/graph.txt
Pins on the device (for linking into audio routes) for RT5659/RT5658:
* DMIC L1

View file

@ -1,17 +0,0 @@
SiRF internal audio CODEC
Required properties:
- compatible : "sirf,atlas6-audio-codec" or "sirf,prima2-audio-codec"
- reg : the register address of the device.
- clocks: the clock of SiRF internal audio codec
Example:
audiocodec: audiocodec@b0040000 {
compatible = "sirf,atlas6-audio-codec";
reg = <0xb0040000 0x10000>;
clocks = <&clks 27>;
};

View file

@ -1,27 +0,0 @@
* SiRF SoC USP module
Required properties:
- compatible: "sirf,prima2-usp-pcm"
- reg: Base address and size entries:
- dmas: List of DMA controller phandle and DMA request line ordered pairs.
- dma-names: Identifier string for each DMA request line in the dmas property.
These strings correspond 1:1 with the ordered pairs in dmas.
One of the DMA channels will be responsible for transmission (should be
named "tx") and one for reception (should be named "rx").
- clocks: USP controller clock source
- pinctrl-names: Must contain a "default" entry.
- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
Example:
usp0: usp@b0080000 {
compatible = "sirf,prima2-usp-pcm";
reg = <0xb0080000 0x10000>;
clocks = <&clks 28>;
dmas = <&dmac1 1>, <&dmac1 2>;
dma-names = "rx", "tx";
pinctrl-names = "default";
pinctrl-0 = <&usp0_only_utfs_pins_a>;
};

View file

@ -54,6 +54,10 @@ properties:
resets:
maxItems: 1
"#clock-cells":
description: Configure the I2S device as MCLK clock provider.
const: 0
required:
- compatible
- "#sound-dai-cells"

View file

@ -9,6 +9,9 @@ Required properties:
- reg : the I2C address of the device.
Optional properties:
- clocks : The clock source of the mclk
- spk-mono: This is a boolean property. If present, the SPK_MONO bit
of R51 (Class D Control 2) gets set, indicating that the speaker is
in mono mode.
@ -27,6 +30,7 @@ Example:
wm8962: codec@1a {
compatible = "wlf,wm8962";
reg = <0x1a>;
clocks = <&clks IMX6QDL_CLK_CKO>;
gpio-cfg = <
0x0000 /* 0:Default */

View file

@ -1,30 +0,0 @@
ZTE TDM DAI driver
Required properties:
- compatible : should be one of the following.
* zte,zx296718-tdm
- reg : physical base address of the controller and length of memory mapped
region.
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
- clock-names: "wclk" for the wclk.
"pclk" for the pclk.
-#clock-cells: should be 1.
- zte,tdm-dma-sysctrl : Reference to the sysctrl controller controlling
the dma. includes:
phandle of sysctrl.
register offset in sysctrl for control dma.
mask of the register that be written to sysctrl.
Example:
tdm: tdm@1487000 {
compatible = "zte,zx296718-tdm";
reg = <0x01487000 0x1000>;
clocks = <&audiocrm AUDIO_TDM_WCLK>, <&audiocrm AUDIO_TDM_PCLK>;
clock-names = "wclk", "pclk";
#clock-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&tdm_global_pin>;
zte,tdm-dma-sysctrl = <&sysctrl 0x10c 4>;
};

View file

@ -1,24 +0,0 @@
ZTE ZX AUD96P22 Audio Codec
Required properties:
- compatible: Must be "zte,zx-aud96p22"
- #sound-dai-cells: Should be 0
- reg: I2C bus slave address of AUD96P22
Example:
i2c0: i2c@1486000 {
compatible = "zte,zx296718-i2c";
reg = <0x01486000 0x1000>;
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&audiocrm AUDIO_I2C0_WCLK>;
clock-frequency = <1600000>;
aud96p22: codec@22 {
compatible = "zte,zx-aud96p22";
#sound-dai-cells = <0>;
reg = <0x22>;
};
};

View file

@ -1,45 +0,0 @@
ZTE ZX296702 I2S controller
Required properties:
- compatible : Must be one of:
"zte,zx296718-i2s", "zte,zx296702-i2s"
"zte,zx296702-i2s"
- reg : Must contain I2S core's registers location and length
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
- clock-names: "wclk" for the wclk, "pclk" for the pclk to the I2S interface.
- dmas: Pairs of phandle and specifier for the DMA channel that is used by
the core. The core expects two dma channels for transmit.
- dma-names : Must be "tx" and "rx"
For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
please check:
* resource-names.txt
* clock/clock-bindings.txt
* dma/dma.txt
Example:
i2s0: i2s@b005000 {
#sound-dai-cells = <0>;
compatible = "zte,zx296718-i2s", "zte,zx296702-i2s";
reg = <0x0b005000 0x1000>;
clocks = <&audiocrm AUDIO_I2S0_WCLK>, <&audiocrm AUDIO_I2S0_PCLK>;
clock-names = "wclk", "pclk";
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&dma 5>, <&dma 6>;
dma-names = "tx", "rx";
};
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "zx296702_snd";
simple-audio-card,format = "left_j";
simple-audio-card,bitclock-master = <&sndcodec>;
simple-audio-card,frame-master = <&sndcodec>;
sndcpu: simple-audio-card,cpu {
sound-dai = <&i2s0>;
};
sndcodec: simple-audio-card,codec {
sound-dai = <&acodec>;
};
};

View file

@ -1,27 +0,0 @@
ZTE ZX296702 SPDIF controller
Required properties:
- compatible : Must be "zte,zx296702-spdif"
- reg : Must contain SPDIF core's registers location and length
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
- clock-names: "tx" for the clock to the SPDIF interface.
- dmas: Pairs of phandle and specifier for the DMA channel that is used by
the core. The core expects one dma channel for transmit.
- dma-names : Must be "tx"
For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
please check:
* resource-names.txt
* clock/clock-bindings.txt
* dma/dma.txt
Example:
spdif0: spdif0@b004000 {
compatible = "zte,zx296702-spdif";
reg = <0x0b004000 0x1000>;
clocks = <&lsp0clk ZX296702_SPDIF0_DIV>;
clock-names = "tx";
interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&dma 4>;
dma-names = "tx";
};

View file

@ -797,17 +797,6 @@ const struct dev_pm_ops arizona_pm_ops = {
EXPORT_SYMBOL_GPL(arizona_pm_ops);
#ifdef CONFIG_OF
unsigned long arizona_of_get_type(struct device *dev)
{
const struct of_device_id *id = of_match_device(arizona_of_match, dev);
if (id)
return (unsigned long)id->data;
else
return 0;
}
EXPORT_SYMBOL_GPL(arizona_of_get_type);
static int arizona_of_get_core_pdata(struct arizona *arizona)
{
struct arizona_pdata *pdata = &arizona->pdata;

View file

@ -23,14 +23,16 @@
static int arizona_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
const void *match_data;
struct arizona *arizona;
const struct regmap_config *regmap_config = NULL;
unsigned long type;
unsigned long type = 0;
int ret;
if (i2c->dev.of_node)
type = arizona_of_get_type(&i2c->dev);
else
match_data = device_get_match_data(&i2c->dev);
if (match_data)
type = (unsigned long)match_data;
else if (id)
type = id->driver_data;
switch (type) {
@ -115,6 +117,7 @@ static struct i2c_driver arizona_i2c_driver = {
module_i2c_driver(arizona_i2c_driver);
MODULE_SOFTDEP("pre: arizona_ldo1");
MODULE_DESCRIPTION("Arizona I2C bus interface");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");

View file

@ -7,7 +7,10 @@
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*/
#include <linux/acpi.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/machine.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
@ -15,22 +18,141 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
#include <uapi/linux/input-event-codes.h>
#include <linux/mfd/arizona/core.h>
#include "arizona.h"
#ifdef CONFIG_ACPI
const struct acpi_gpio_params reset_gpios = { 1, 0, false };
const struct acpi_gpio_params ldoena_gpios = { 2, 0, false };
static const struct acpi_gpio_mapping arizona_acpi_gpios[] = {
{ "reset-gpios", &reset_gpios, 1, },
{ "wlf,ldoena-gpios", &ldoena_gpios, 1 },
{ }
};
/*
* The ACPI resources for the device only describe external GPIO-s. They do
* not provide mappings for the GPIO-s coming from the Arizona codec itself.
*/
static const struct gpiod_lookup arizona_soc_gpios[] = {
{ "arizona", 2, "wlf,spkvdd-ena", 0, GPIO_ACTIVE_HIGH },
{ "arizona", 4, "wlf,micd-pol", 0, GPIO_ACTIVE_LOW },
};
/*
* The AOSP 3.5 mm Headset: Accessory Specification gives the following values:
* Function A Play/Pause: 0 ohm
* Function D Voice assistant: 135 ohm
* Function B Volume Up 240 ohm
* Function C Volume Down 470 ohm
* Minimum Mic DC resistance 1000 ohm
* Minimum Ear speaker impedance 16 ohm
* Note the first max value below must be less then the min. speaker impedance,
* to allow CTIA/OMTP detection to work. The other max values are the closest
* value from extcon-arizona.c:arizona_micd_levels halfway 2 button resistances.
*/
static const struct arizona_micd_range arizona_micd_aosp_ranges[] = {
{ .max = 11, .key = KEY_PLAYPAUSE },
{ .max = 186, .key = KEY_VOICECOMMAND },
{ .max = 348, .key = KEY_VOLUMEUP },
{ .max = 752, .key = KEY_VOLUMEDOWN },
};
static void arizona_spi_acpi_remove_lookup(void *lookup)
{
gpiod_remove_lookup_table(lookup);
}
static int arizona_spi_acpi_probe(struct arizona *arizona)
{
struct gpiod_lookup_table *lookup;
acpi_status status;
int ret;
/* Add mappings for the 2 ACPI declared GPIOs used for reset and ldo-ena */
devm_acpi_dev_add_driver_gpios(arizona->dev, arizona_acpi_gpios);
/* Add lookups for the SoCs own GPIOs used for micdet-polarity and spkVDD-enable */
lookup = devm_kzalloc(arizona->dev,
struct_size(lookup, table, ARRAY_SIZE(arizona_soc_gpios) + 1),
GFP_KERNEL);
if (!lookup)
return -ENOMEM;
lookup->dev_id = dev_name(arizona->dev);
memcpy(lookup->table, arizona_soc_gpios, sizeof(arizona_soc_gpios));
gpiod_add_lookup_table(lookup);
ret = devm_add_action_or_reset(arizona->dev, arizona_spi_acpi_remove_lookup, lookup);
if (ret)
return ret;
/* Enable 32KHz clock from SoC to codec for jack-detect */
status = acpi_evaluate_object(ACPI_HANDLE(arizona->dev), "CLKE", NULL, NULL);
if (ACPI_FAILURE(status))
dev_warn(arizona->dev, "Failed to enable 32KHz clk ACPI error %d\n", status);
/*
* Some DSDTs wrongly declare the IRQ trigger-type as IRQF_TRIGGER_FALLING
* The IRQ line will stay low when a new IRQ event happens between reading
* the IRQ status flags and acknowledging them. When the IRQ line stays
* low like this the IRQ will never trigger again when its type is set
* to IRQF_TRIGGER_FALLING. Correct the IRQ trigger-type to fix this.
*
* Note theoretically it is possible that some boards are not capable
* of handling active low level interrupts. In that case setting the
* flag to IRQF_TRIGGER_FALLING would not be a bug (and we would need
* to work around this) but so far all known usages of IRQF_TRIGGER_FALLING
* are a bug in the board's DSDT.
*/
arizona->pdata.irq_flags = IRQF_TRIGGER_LOW;
/* Wait 200 ms after jack insertion */
arizona->pdata.micd_detect_debounce = 200;
/* Use standard AOSP values for headset-button mappings */
arizona->pdata.micd_ranges = arizona_micd_aosp_ranges;
arizona->pdata.num_micd_ranges = ARRAY_SIZE(arizona_micd_aosp_ranges);
return 0;
}
static const struct acpi_device_id arizona_acpi_match[] = {
{
.id = "WM510204",
.driver_data = WM5102,
},
{
.id = "WM510205",
.driver_data = WM5102,
},
{ }
};
MODULE_DEVICE_TABLE(acpi, arizona_acpi_match);
#else
static int arizona_spi_acpi_probe(struct arizona *arizona)
{
return -ENODEV;
}
#endif
static int arizona_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
const void *match_data;
struct arizona *arizona;
const struct regmap_config *regmap_config = NULL;
unsigned long type;
unsigned long type = 0;
int ret;
if (spi->dev.of_node)
type = arizona_of_get_type(&spi->dev);
else
match_data = device_get_match_data(&spi->dev);
if (match_data)
type = (unsigned long)match_data;
else if (id)
type = id->driver_data;
switch (type) {
@ -75,6 +197,12 @@ static int arizona_spi_probe(struct spi_device *spi)
arizona->dev = &spi->dev;
arizona->irq = spi->irq;
if (has_acpi_companion(&spi->dev)) {
ret = arizona_spi_acpi_probe(arizona);
if (ret)
return ret;
}
return arizona_dev_init(arizona);
}
@ -102,6 +230,7 @@ static struct spi_driver arizona_spi_driver = {
.name = "arizona",
.pm = &arizona_pm_ops,
.of_match_table = of_match_ptr(arizona_of_match),
.acpi_match_table = ACPI_PTR(arizona_acpi_match),
},
.probe = arizona_spi_probe,
.remove = arizona_spi_remove,
@ -110,6 +239,7 @@ static struct spi_driver arizona_spi_driver = {
module_spi_driver(arizona_spi_driver);
MODULE_SOFTDEP("pre: arizona_ldo1");
MODULE_DESCRIPTION("Arizona SPI bus interface");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");

View file

@ -50,13 +50,4 @@ int arizona_dev_exit(struct arizona *arizona);
int arizona_irq_init(struct arizona *arizona);
int arizona_irq_exit(struct arizona *arizona);
#ifdef CONFIG_OF
unsigned long arizona_of_get_type(struct device *dev);
#else
static inline unsigned long arizona_of_get_type(struct device *dev)
{
return 0;
}
#endif
#endif

View file

@ -4600,6 +4600,7 @@ enum ec_codec_i2s_rx_subcmd {
EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH = 0x2,
EC_CODEC_I2S_RX_SET_DAIFMT = 0x3,
EC_CODEC_I2S_RX_SET_BCLK = 0x4,
EC_CODEC_I2S_RX_RESET = 0x5,
EC_CODEC_I2S_RX_SUBCMD_COUNT,
};

View file

@ -66,6 +66,9 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream)
* @chan_name: Custom channel name to use when requesting DMA channel.
* @fifo_size: FIFO size of the DAI controller in bytes
* @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now
* @peripheral_config: peripheral configuration for programming peripheral
* for dmaengine transfer
* @peripheral_size: peripheral configuration buffer size
*/
struct snd_dmaengine_dai_dma_data {
dma_addr_t addr;
@ -76,6 +79,8 @@ struct snd_dmaengine_dai_dma_data {
const char *chan_name;
unsigned int fifo_size;
unsigned int flags;
void *peripheral_config;
size_t peripheral_size;
};
void snd_dmaengine_pcm_set_config_from_dai_data(

View file

@ -9,8 +9,10 @@
#include <sound/simple_card_utils.h>
int graph_card_probe(struct snd_soc_card *card);
int audio_graph_card_probe(struct snd_soc_card *card);
int graph_parse_of(struct asoc_simple_priv *priv, struct device *dev);
int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev);
int audio_graph_remove(struct platform_device *pdev);
#endif /* __GRAPH_CARD_H */

View file

@ -34,6 +34,11 @@ struct hdmi_codec_daifmt {
unsigned int frame_clk_inv:1;
unsigned int bit_clk_master:1;
unsigned int frame_clk_master:1;
/* bit_fmt could be standard PCM format or
* IEC958 encoded format. ALSA IEC958 plugin will pass
* IEC958_SUBFRAME format to the underneath driver.
*/
snd_pcm_format_t bit_fmt;
};
/*

View file

@ -22,6 +22,8 @@ struct rt5645_platform_data {
bool level_trigger_irq;
/* Invert JD1_1 status polarity */
bool inv_jd1_1;
/* Invert HP detect status polarity */
bool inv_hp_pol;
/* Value to asign to snd_soc_card.long_name */
const char *long_name;

View file

@ -353,6 +353,12 @@ int snd_soc_component_test_bits(struct snd_soc_component *component,
unsigned int reg, unsigned int mask,
unsigned int value);
unsigned int snd_soc_component_read_field(struct snd_soc_component *component,
unsigned int reg, unsigned int mask);
int snd_soc_component_write_field(struct snd_soc_component *component,
unsigned int reg, unsigned int mask,
unsigned int val);
/* component wide operations */
int snd_soc_component_set_sysclk(struct snd_soc_component *component,
int clk_id, int source,

View file

@ -353,9 +353,9 @@ struct snd_soc_dai_driver {
/* DAI capabilities */
struct snd_soc_pcm_stream capture;
struct snd_soc_pcm_stream playback;
unsigned int symmetric_rates:1;
unsigned int symmetric_rate:1;
unsigned int symmetric_channels:1;
unsigned int symmetric_samplebits:1;
unsigned int symmetric_sample_bits:1;
/* probe ordering - for components with runtime dependencies */
int probe_order;

View file

@ -685,9 +685,9 @@ struct snd_soc_dai_link {
unsigned int ignore_suspend:1;
/* Symmetry requirements */
unsigned int symmetric_rates:1;
unsigned int symmetric_rate:1;
unsigned int symmetric_channels:1;
unsigned int symmetric_samplebits:1;
unsigned int symmetric_sample_bits:1;
/* Do not create a PCM for this DAI link (Backend link) */
unsigned int no_pcm:1;

View file

@ -58,9 +58,9 @@ struct sof_ext_man_header {
/* Extended manifest elements types */
enum sof_ext_man_elem_type {
SOF_EXT_MAN_ELEM_FW_VERSION = 0,
SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW,
SOF_EXT_MAN_ELEM_CC_VERSION = SOF_IPC_EXT_CC_INFO,
SOF_EXT_MAN_ELEM_DBG_ABI = SOF_IPC_EXT_USER_ABI_INFO,
SOF_EXT_MAN_ELEM_WINDOW = 1,
SOF_EXT_MAN_ELEM_CC_VERSION = 2,
SOF_EXT_MAN_ELEM_DBG_ABI = 4,
SOF_EXT_MAN_ELEM_CONFIG_DATA = 5, /**< ABI3.17 */
SOF_EXT_MAN_ELEM_PLATFORM_CONFIG_DATA = 6,
};

View file

@ -125,6 +125,8 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
}
slave_config->slave_id = dma_data->slave_id;
slave_config->peripheral_config = dma_data->peripheral_config;
slave_config->peripheral_size = dma_data->peripheral_size;
}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data);

View file

@ -37,6 +37,23 @@ config SND_SOC_COMPRESS
config SND_SOC_TOPOLOGY
bool
config SND_SOC_TOPOLOGY_KUNIT_TESTS
tristate "KUnit tests for SoC topology"
depends on KUNIT
depends on SND_SOC_TOPOLOGY
default KUNIT_ALL_TESTS
help
If you want to perform tests on ALSA SoC topology support say Y here.
This builds a module which can be later manually loaded to run KUNIT
test cases against soc-topology.c API. This should be primarily used
by developers to test their changes to ASoC.
Do note that it creates fake playback devices which do not interact
well with userspace. When running tests one may want to disable
userspace applications such as pulseaudio, to prevent unnecessary
problems.
config SND_SOC_ACPI
tristate
@ -62,7 +79,6 @@ source "sound/soc/qcom/Kconfig"
source "sound/soc/rockchip/Kconfig"
source "sound/soc/samsung/Kconfig"
source "sound/soc/sh/Kconfig"
source "sound/soc/sirf/Kconfig"
source "sound/soc/sof/Kconfig"
source "sound/soc/spear/Kconfig"
source "sound/soc/sprd/Kconfig"
@ -71,12 +87,10 @@ source "sound/soc/stm/Kconfig"
source "sound/soc/sunxi/Kconfig"
source "sound/soc/tegra/Kconfig"
source "sound/soc/ti/Kconfig"
source "sound/soc/txx9/Kconfig"
source "sound/soc/uniphier/Kconfig"
source "sound/soc/ux500/Kconfig"
source "sound/soc/xilinx/Kconfig"
source "sound/soc/xtensa/Kconfig"
source "sound/soc/zte/Kconfig"
# Supported codecs
source "sound/soc/codecs/Kconfig"

View file

@ -7,6 +7,11 @@ ifneq ($(CONFIG_SND_SOC_TOPOLOGY),)
snd-soc-core-objs += soc-topology.o
endif
ifneq ($(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TESTS),)
# snd-soc-test-objs := soc-topology-test.o
obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TESTS) := soc-topology-test.o
endif
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
snd-soc-core-objs += soc-generic-dmaengine-pcm.o
endif
@ -45,7 +50,6 @@ obj-$(CONFIG_SND_SOC) += qcom/
obj-$(CONFIG_SND_SOC) += rockchip/
obj-$(CONFIG_SND_SOC) += samsung/
obj-$(CONFIG_SND_SOC) += sh/
obj-$(CONFIG_SND_SOC) += sirf/
obj-$(CONFIG_SND_SOC) += sof/
obj-$(CONFIG_SND_SOC) += spear/
obj-$(CONFIG_SND_SOC) += sprd/
@ -54,9 +58,7 @@ obj-$(CONFIG_SND_SOC) += stm/
obj-$(CONFIG_SND_SOC) += sunxi/
obj-$(CONFIG_SND_SOC) += tegra/
obj-$(CONFIG_SND_SOC) += ti/
obj-$(CONFIG_SND_SOC) += txx9/
obj-$(CONFIG_SND_SOC) += uniphier/
obj-$(CONFIG_SND_SOC) += ux500/
obj-$(CONFIG_SND_SOC) += xilinx/
obj-$(CONFIG_SND_SOC) += xtensa/
obj-$(CONFIG_SND_SOC) += zte/

View file

@ -156,7 +156,7 @@ static const struct snd_soc_dai_ops axi_i2s_dai_ops = {
static struct snd_soc_dai_driver axi_i2s_dai = {
.probe = axi_i2s_dai_probe,
.ops = &axi_i2s_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static const struct snd_soc_component_driver axi_i2s_component = {

View file

@ -140,9 +140,7 @@ static int acp3x_1015_hw_params(struct snd_pcm_substream *substream,
for_each_rtd_codec_dais(rtd, i, codec_dai) {
if (strcmp(codec_dai->name, "rt1015-aif"))
continue;
ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
if (ret < 0)
return ret;
ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
64 * srate, 256 * srate);
if (ret < 0)

View file

@ -541,7 +541,7 @@ static struct snd_soc_dai_driver atmel_i2s_dai = {
.formats = ATMEL_I2S_FORMATS,
},
.ops = &atmel_i2s_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static const struct snd_soc_component_driver atmel_i2s_component = {

View file

@ -34,86 +34,21 @@
#include "atmel-pcm.h"
static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
int stream)
{
struct snd_pcm_substream *substream = pcm->streams[stream].substream;
struct snd_dma_buffer *buf = &substream->dma_buffer;
size_t size = ATMEL_SSC_DMABUF_SIZE;
buf->dev.type = SNDRV_DMA_TYPE_DEV;
buf->dev.dev = pcm->card->dev;
buf->private_data = NULL;
buf->area = dma_alloc_coherent(pcm->card->dev, size,
&buf->addr, GFP_KERNEL);
pr_debug("atmel-pcm: alloc dma buffer: area=%p, addr=%p, size=%zu\n",
(void *)buf->area, (void *)(long)buf->addr, size);
if (!buf->area)
return -ENOMEM;
buf->bytes = size;
return 0;
}
static int atmel_pcm_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
return remap_pfn_range(vma, vma->vm_start,
substream->dma_buffer.addr >> PAGE_SHIFT,
vma->vm_end - vma->vm_start, vma->vm_page_prot);
}
static int atmel_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
int ret;
ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
pr_debug("atmel-pcm: allocating PCM playback DMA buffer\n");
ret = atmel_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
card->dev, ATMEL_SSC_DMABUF_SIZE,
ATMEL_SSC_DMABUF_SIZE);
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
pr_debug("atmel-pcm: allocating PCM capture DMA buffer\n");
ret = atmel_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
goto out;
}
out:
return ret;
}
static void atmel_pcm_free(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
int stream;
for (stream = 0; stream < 2; stream++) {
substream = pcm->streams[stream].substream;
if (!substream)
continue;
buf = &substream->dma_buffer;
if (!buf->area)
continue;
dma_free_coherent(pcm->card->dev, buf->bytes,
buf->area, buf->addr);
buf->area = NULL;
}
return 0;
}
/*--------------------------------------------------------------------------*\
@ -210,9 +145,6 @@ static int atmel_pcm_hw_params(struct snd_soc_component *component,
/* this may get called several times by oss emulation
* with different params */
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
runtime->dma_bytes = params_buffer_bytes(params);
prtd->params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
@ -384,9 +316,7 @@ static const struct snd_soc_component_driver atmel_soc_platform = {
.prepare = atmel_pcm_prepare,
.trigger = atmel_pcm_trigger,
.pointer = atmel_pcm_pointer,
.mmap = atmel_pcm_mmap,
.pcm_construct = atmel_pcm_new,
.pcm_destruct = atmel_pcm_free,
};
int atmel_pcm_pdc_platform_register(struct device *dev)

View file

@ -859,8 +859,8 @@ static struct snd_soc_dai_driver mchp_i2s_mcc_dai = {
.formats = MCHP_I2SMCC_FORMATS,
},
.ops = &mchp_i2s_mcc_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
.symmetric_channels = 1,
};

View file

@ -210,7 +210,7 @@ static const struct snd_soc_dai_ops au1xi2s_dai_ops = {
};
static struct snd_soc_dai_driver au1xi2s_dai_driver = {
.symmetric_rates = 1,
.symmetric_rate = 1,
.playback = {
.rates = AU1XI2SC_RATES,
.formats = AU1XI2SC_FMTS,

View file

@ -783,8 +783,8 @@ static struct snd_soc_dai_driver bcm2835_i2s_dai = {
| SNDRV_PCM_FMTBIT_S32_LE
},
.ops = &bcm2835_i2s_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
};
static bool bcm2835_i2s_volatile_reg(struct device *dev, unsigned int reg)

View file

@ -212,7 +212,7 @@ static struct snd_soc_dai_driver bcm63xx_i2s_dai = {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &bcm63xx_i2s_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
.symmetric_channels = 1,
};

View file

@ -636,36 +636,6 @@ static int cygnus_pcm_close(struct snd_soc_component *component,
return 0;
}
static int cygnus_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
struct cygnus_aio_port *aio;
aio = cygnus_dai_get_dma_data(substream);
dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s port %d\n", __func__, aio->portnum);
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
runtime->dma_bytes = params_buffer_bytes(params);
return 0;
}
static int cygnus_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct cygnus_aio_port *aio;
aio = cygnus_dai_get_dma_data(substream);
dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s port %d\n", __func__, aio->portnum);
snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
}
static int cygnus_pcm_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
@ -730,87 +700,19 @@ static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_soc_component *component,
return bytes_to_frames(substream->runtime, res);
}
static int cygnus_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
{
struct snd_pcm_substream *substream = pcm->streams[stream].substream;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_dma_buffer *buf = &substream->dma_buffer;
size_t size;
size = cygnus_pcm_hw.buffer_bytes_max;
buf->dev.type = SNDRV_DMA_TYPE_DEV;
buf->dev.dev = pcm->card->dev;
buf->private_data = NULL;
buf->area = dma_alloc_coherent(pcm->card->dev, size,
&buf->addr, GFP_KERNEL);
dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s: size 0x%zx @ %pK\n",
__func__, size, buf->area);
if (!buf->area) {
dev_err(asoc_rtd_to_cpu(rtd, 0)->dev, "%s: dma_alloc failed\n", __func__);
return -ENOMEM;
}
buf->bytes = size;
return 0;
}
static void cygnus_dma_free_dma_buffers(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
if (substream) {
buf = &substream->dma_buffer;
if (buf->area) {
dma_free_coherent(pcm->card->dev, buf->bytes,
buf->area, buf->addr);
buf->area = NULL;
}
}
substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
if (substream) {
buf = &substream->dma_buffer;
if (buf->area) {
dma_free_coherent(pcm->card->dev, buf->bytes,
buf->area, buf->addr);
buf->area = NULL;
}
}
}
static int cygnus_dma_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
size_t size = cygnus_pcm_hw.buffer_bytes_max;
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
int ret;
if (!card->dev->dma_mask)
card->dev->dma_mask = &cygnus_dma_dmamask;
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = cygnus_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
return ret;
}
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = cygnus_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret) {
cygnus_dma_free_dma_buffers(component, pcm);
return ret;
}
}
snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
card->dev, size, size);
return 0;
}
@ -818,13 +720,10 @@ static int cygnus_dma_new(struct snd_soc_component *component,
static struct snd_soc_component_driver cygnus_soc_platform = {
.open = cygnus_pcm_open,
.close = cygnus_pcm_close,
.hw_params = cygnus_pcm_hw_params,
.hw_free = cygnus_pcm_hw_free,
.prepare = cygnus_pcm_prepare,
.trigger = cygnus_pcm_trigger,
.pointer = cygnus_pcm_pointer,
.pcm_construct = cygnus_dma_new,
.pcm_destruct = cygnus_dma_free_dma_buffers,
};
int cygnus_soc_platform_register(struct device *dev,

View file

@ -404,7 +404,7 @@ static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_driver ep93xx_i2s_dai = {
.symmetric_rates= 1,
.symmetric_rate = 1,
.probe = ep93xx_i2s_dai_probe,
.playback = {
.channels_min = 2,

View file

@ -104,6 +104,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_ISABELLE
imply SND_SOC_JZ4740_CODEC
imply SND_SOC_JZ4725B_CODEC
imply SND_SOC_JZ4760_CODEC
imply SND_SOC_JZ4770_CODEC
imply SND_SOC_LM4857
imply SND_SOC_LM49453
@ -227,6 +228,8 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_UDA1380
imply SND_SOC_WCD9335
imply SND_SOC_WCD934X
imply SND_SOC_LPASS_RX_MACRO
imply SND_SOC_LPASS_TX_MACRO
imply SND_SOC_WL1273
imply SND_SOC_WM0010
imply SND_SOC_WM1250_EV1
@ -712,7 +715,7 @@ config SND_SOC_CX2072X
Enable support for Conexant CX20721 and CX20723 codec chips.
config SND_SOC_JZ4740_CODEC
depends on MIPS || COMPILE_TEST
depends on MACH_INGENIC || COMPILE_TEST
depends on OF
select REGMAP_MMIO
tristate "Ingenic JZ4740 internal CODEC"
@ -724,7 +727,7 @@ config SND_SOC_JZ4740_CODEC
will be called snd-soc-jz4740-codec.
config SND_SOC_JZ4725B_CODEC
depends on MIPS || COMPILE_TEST
depends on MACH_INGENIC || COMPILE_TEST
depends on OF
select REGMAP
tristate "Ingenic JZ4725B internal CODEC"
@ -735,8 +738,20 @@ config SND_SOC_JZ4725B_CODEC
This driver can also be built as a module. If so, the module
will be called snd-soc-jz4725b-codec.
config SND_SOC_JZ4760_CODEC
depends on MACH_INGENIC || COMPILE_TEST
depends on OF
select REGMAP
tristate "Ingenic JZ4760 internal CODEC"
help
Enable support for the internal CODEC found in the JZ4760 SoC
from Ingenic.
This driver can also be built as a module. If so, the module
will be called snd-soc-jz4760-codec.
config SND_SOC_JZ4770_CODEC
depends on MIPS || COMPILE_TEST
depends on MACH_INGENIC || COMPILE_TEST
depends on OF
select REGMAP
tristate "Ingenic JZ4770 internal CODEC"
@ -1162,7 +1177,7 @@ config SND_SOC_RT5651
depends on I2C
config SND_SOC_RT5659
tristate
tristate "Realtek RT5658/RT5659 Codec"
depends on I2C
config SND_SOC_RT5660
@ -1820,4 +1835,12 @@ config SND_SOC_LPASS_VA_MACRO
depends on COMMON_CLK
tristate "Qualcomm VA Macro in LPASS(Low Power Audio SubSystem)"
config SND_SOC_LPASS_RX_MACRO
depends on COMMON_CLK
tristate "Qualcomm RX Macro in LPASS(Low Power Audio SubSystem)"
config SND_SOC_LPASS_TX_MACRO
depends on COMMON_CLK
tristate "Qualcomm TX Macro in LPASS(Low Power Audio SubSystem)"
endmenu

View file

@ -101,11 +101,14 @@ snd-soc-inno-rk3036-objs := inno_rk3036.o
snd-soc-isabelle-objs := isabelle.o
snd-soc-jz4740-codec-objs := jz4740.o
snd-soc-jz4725b-codec-objs := jz4725b.o
snd-soc-jz4760-codec-objs := jz4760.o
snd-soc-jz4770-codec-objs := jz4770.o
snd-soc-l3-objs := l3.o
snd-soc-lm4857-objs := lm4857.o
snd-soc-lm49453-objs := lm49453.o
snd-soc-lochnagar-sc-objs := lochnagar-sc.o
snd-soc-lpass-rx-macro-objs := lpass-rx-macro.o
snd-soc-lpass-tx-macro-objs := lpass-tx-macro.o
snd-soc-lpass-wsa-macro-objs := lpass-wsa-macro.o
snd-soc-lpass-va-macro-objs := lpass-va-macro.o
snd-soc-madera-objs := madera.o
@ -201,7 +204,6 @@ snd-soc-sigmadsp-objs := sigmadsp.o
snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o
snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o
snd-soc-si476x-objs := si476x.o
snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o
snd-soc-spdif-tx-objs := spdif_transmitter.o
snd-soc-spdif-rx-objs := spdif_receiver.o
snd-soc-ssm2305-objs := ssm2305.o
@ -302,7 +304,6 @@ snd-soc-wm9713-objs := wm9713.o
snd-soc-wm-hubs-objs := wm_hubs.o
snd-soc-wsa881x-objs := wsa881x.o
snd-soc-zl38060-objs := zl38060.o
snd-soc-zx-aud96p22-objs := zx_aud96p22.o
# Amp
snd-soc-max9877-objs := max9877.o
snd-soc-max98504-objs := max98504.o
@ -418,6 +419,7 @@ obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o
obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
obj-$(CONFIG_SND_SOC_JZ4725B_CODEC) += snd-soc-jz4725b-codec.o
obj-$(CONFIG_SND_SOC_JZ4760_CODEC) += snd-soc-jz4760-codec.o
obj-$(CONFIG_SND_SOC_JZ4770_CODEC) += snd-soc-jz4770-codec.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
@ -516,7 +518,6 @@ obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o
obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP) += snd-soc-sigmadsp-regmap.o
obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
obj-$(CONFIG_SND_SOC_SIRF_AUDIO_CODEC) += sirf-audio-codec.o
obj-$(CONFIG_SND_SOC_SSM2305) += snd-soc-ssm2305.o
obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
@ -618,7 +619,6 @@ obj-$(CONFIG_SND_SOC_WM_ADSP) += snd-soc-wm-adsp.o
obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
obj-$(CONFIG_SND_SOC_WSA881X) += snd-soc-wsa881x.o
obj-$(CONFIG_SND_SOC_ZL38060) += snd-soc-zl38060.o
obj-$(CONFIG_SND_SOC_ZX_AUD96P22) += snd-soc-zx-aud96p22.o
# Amp
obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
@ -627,6 +627,8 @@ obj-$(CONFIG_SND_SOC_SIMPLE_AMPLIFIER) += snd-soc-simple-amplifier.o
obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
obj-$(CONFIG_SND_SOC_LPASS_WSA_MACRO) += snd-soc-lpass-wsa-macro.o
obj-$(CONFIG_SND_SOC_LPASS_VA_MACRO) += snd-soc-lpass-va-macro.o
obj-$(CONFIG_SND_SOC_LPASS_RX_MACRO) += snd-soc-lpass-rx-macro.o
obj-$(CONFIG_SND_SOC_LPASS_TX_MACRO) += snd-soc-lpass-tx-macro.o
# Mux
obj-$(CONFIG_SND_SOC_SIMPLE_MUX) += snd-soc-simple-mux.o

View file

@ -2384,7 +2384,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = {
.formats = AB8500_SUPPORTED_FMT,
},
.ops = &ab8500_codec_ops,
.symmetric_rates = 1
.symmetric_rate = 1
},
{
.name = "ab8500-codec-dai.1",
@ -2397,7 +2397,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = {
.formats = AB8500_SUPPORTED_FMT,
},
.ops = &ab8500_codec_ops,
.symmetric_rates = 1
.symmetric_rate = 1
}
};

View file

@ -890,7 +890,7 @@ static struct snd_soc_dai_driver adau1372_dai_driver = {
.sig_bits = 24,
},
.ops = &adau1372_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static int adau1372_setup_pll(struct adau1372 *adau1372, unsigned int rate)

View file

@ -1205,7 +1205,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = {
.formats = ADAU1373_FORMATS,
},
.ops = &adau1373_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
{
.id = 1,
@ -1225,7 +1225,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = {
.formats = ADAU1373_FORMATS,
},
.ops = &adau1373_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
{
.id = 2,
@ -1245,7 +1245,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = {
.formats = ADAU1373_FORMATS,
},
.ops = &adau1373_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
};

View file

@ -653,7 +653,7 @@ static struct snd_soc_dai_driver adau1701_dai = {
.formats = ADAU1701_FORMATS,
},
.ops = &adau1701_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
#ifdef CONFIG_OF

View file

@ -1095,8 +1095,7 @@ void adau17x1_remove(struct device *dev)
{
struct adau *adau = dev_get_drvdata(dev);
if (adau->mclk)
clk_disable_unprepare(adau->mclk);
clk_disable_unprepare(adau->mclk);
}
EXPORT_SYMBOL_GPL(adau17x1_remove);

View file

@ -56,7 +56,7 @@ static struct snd_soc_dai_driver ak4554_dai = {
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static const struct snd_soc_component_driver soc_component_dev_ak4554 = {

View file

@ -575,7 +575,7 @@ static struct snd_soc_dai_driver ak4613_dai = {
.formats = AK4613_PCM_FMTBIT,
},
.ops = &ak4613_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static int ak4613_suspend(struct snd_soc_component *component)

View file

@ -499,7 +499,7 @@ static struct snd_soc_dai_driver ak4641_dai[] = {
.formats = AK4641_FORMATS,
},
.ops = &ak4641_i2s_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
{
.name = "ak4641-voice",
@ -519,7 +519,7 @@ static struct snd_soc_dai_driver ak4641_dai[] = {
.formats = AK4641_FORMATS,
},
.ops = &ak4641_pcm_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
};

View file

@ -516,7 +516,7 @@ static struct snd_soc_dai_driver ak4642_dai = {
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE },
.ops = &ak4642_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static int ak4642_suspend(struct snd_soc_component *component)

View file

@ -1032,7 +1032,7 @@ static struct snd_soc_dai_driver alc5632_dai = {
.formats = ALC5632_FORMATS,},
.ops = &alc5632_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
#ifdef CONFIG_PM

View file

@ -16,6 +16,14 @@
#include <sound/soc.h>
#include <sound/tlv.h>
/* Register 512 CPCAP_REG_VAUDIOC --- Audio Regulator and Bias Voltage */
#define CPCAP_BIT_AUDIO_LOW_PWR 6
#define CPCAP_BIT_AUD_LOWPWR_SPEED 5
#define CPCAP_BIT_VAUDIOPRISTBY 4
#define CPCAP_BIT_VAUDIO_MODE1 2
#define CPCAP_BIT_VAUDIO_MODE0 1
#define CPCAP_BIT_V_AUDIO_EN 0
/* Register 513 CPCAP_REG_CC --- CODEC */
#define CPCAP_BIT_CDC_CLK2 15
#define CPCAP_BIT_CDC_CLK1 14
@ -221,6 +229,7 @@ struct cpcap_reg_info {
};
static const struct cpcap_reg_info cpcap_default_regs[] = {
{ CPCAP_REG_VAUDIOC, 0x003F, 0x0000 },
{ CPCAP_REG_CC, 0xFFFF, 0x0000 },
{ CPCAP_REG_CC, 0xFFFF, 0x0000 },
{ CPCAP_REG_CDI, 0xBFFF, 0x0000 },
@ -1371,8 +1380,121 @@ static int cpcap_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
return 0;
}
static int cpcap_voice_set_mute(struct snd_soc_dai *dai,
int mute, int direction)
/*
* Configure codec for voice call if requested.
*
* We can configure most with snd_soc_dai_set_sysclk(), snd_soc_dai_set_fmt()
* and snd_soc_dai_set_tdm_slot(). This function configures the rest of the
* cpcap related hardware as CPU is not involved in the voice call.
*/
static int cpcap_voice_call(struct cpcap_audio *cpcap, struct snd_soc_dai *dai,
bool voice_call)
{
int mask, err;
/* Modem to codec VAUDIO_MODE1 */
mask = BIT(CPCAP_BIT_VAUDIO_MODE1);
err = regmap_update_bits(cpcap->regmap, CPCAP_REG_VAUDIOC,
mask, voice_call ? mask : 0);
if (err)
return err;
/* Clear MIC1_MUX for call */
mask = BIT(CPCAP_BIT_MIC1_MUX);
err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,
mask, voice_call ? 0 : mask);
if (err)
return err;
/* Set MIC2_MUX for call */
mask = BIT(CPCAP_BIT_MB_ON1L) | BIT(CPCAP_BIT_MB_ON1R) |
BIT(CPCAP_BIT_MIC2_MUX) | BIT(CPCAP_BIT_MIC2_PGA_EN);
err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,
mask, voice_call ? mask : 0);
if (err)
return err;
/* Enable LDSP for call */
mask = BIT(CPCAP_BIT_A2_LDSP_L_EN) | BIT(CPCAP_BIT_A2_LDSP_R_EN);
err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXOA,
mask, voice_call ? mask : 0);
if (err)
return err;
/* Enable CPCAP_BIT_PGA_CDC_EN for call */
mask = BIT(CPCAP_BIT_PGA_CDC_EN);
err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXCOA,
mask, voice_call ? mask : 0);
if (err)
return err;
/* Unmute voice for call */
if (dai) {
err = snd_soc_dai_digital_mute(dai, !voice_call,
SNDRV_PCM_STREAM_PLAYBACK);
if (err)
return err;
}
/* Set modem to codec mic CDC and HPF for call */
mask = BIT(CPCAP_BIT_MIC2_CDC_EN) | BIT(CPCAP_BIT_CDC_EN_RX) |
BIT(CPCAP_BIT_AUDOHPF_1) | BIT(CPCAP_BIT_AUDOHPF_0) |
BIT(CPCAP_BIT_AUDIHPF_1) | BIT(CPCAP_BIT_AUDIHPF_0);
err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CC,
mask, voice_call ? mask : 0);
if (err)
return err;
/* Enable modem to codec CDC for call*/
mask = BIT(CPCAP_BIT_CDC_CLK_EN);
err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI,
mask, voice_call ? mask : 0);
return err;
}
static int cpcap_voice_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 cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
int err, ts_mask, mask;
bool voice_call;
/*
* Primitive test for voice call, probably needs more checks
* later on for 16-bit calls detected, Bluetooth headset etc.
*/
if (tx_mask == 0 && rx_mask == 1 && slot_width == 8)
voice_call = true;
else
voice_call = false;
ts_mask = 0x7 << CPCAP_BIT_MIC2_TIMESLOT0;
ts_mask |= 0x7 << CPCAP_BIT_MIC1_RX_TIMESLOT0;
mask = (tx_mask & 0x7) << CPCAP_BIT_MIC2_TIMESLOT0;
mask |= (rx_mask & 0x7) << CPCAP_BIT_MIC1_RX_TIMESLOT0;
err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI,
ts_mask, mask);
if (err)
return err;
err = cpcap_set_samprate(cpcap, CPCAP_DAI_VOICE, slot_width * 1000);
if (err)
return err;
err = cpcap_voice_call(cpcap, dai, voice_call);
if (err)
return err;
return 0;
}
static int cpcap_voice_set_mute(struct snd_soc_dai *dai, int mute, int direction)
{
struct snd_soc_component *component = dai->component;
struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
@ -1393,6 +1515,7 @@ static const struct snd_soc_dai_ops cpcap_dai_voice_ops = {
.hw_params = cpcap_voice_hw_params,
.set_sysclk = cpcap_voice_set_dai_sysclk,
.set_fmt = cpcap_voice_set_dai_fmt,
.set_tdm_slot = cpcap_voice_set_tdm_slot,
.mute_stream = cpcap_voice_set_mute,
.no_capture_mute = 1,
};

View file

@ -1011,6 +1011,18 @@ static int cros_ec_codec_platform_probe(struct platform_device *pdev)
}
priv->ec_capabilities = r.capabilities;
/* Reset EC codec i2s rx. */
p.cmd = EC_CODEC_I2S_RX_RESET;
ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
(uint8_t *)&p, sizeof(p), NULL, 0);
if (ret == -ENOPROTOOPT) {
dev_info(dev,
"Missing reset command. Please update EC firmware.\n");
} else if (ret) {
dev_err(dev, "failed to EC_CODEC_I2S_RESET: %d\n", ret);
return ret;
}
platform_set_drvdata(pdev, priv);
ret = devm_snd_soc_register_component(dev, &i2s_rx_component_driver,

View file

@ -194,7 +194,7 @@ static struct snd_soc_dai_driver cs35l32_dai[] = {
.formats = CS35L32_FORMATS,
},
.ops = &cs35l32_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
}
};

View file

@ -691,7 +691,7 @@ static struct snd_soc_dai_driver cs35l33_dai = {
.formats = CS35L33_FORMATS,
},
.ops = &cs35l33_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static int cs35l33_set_hg_data(struct snd_soc_component *component,

View file

@ -666,7 +666,7 @@ static struct snd_soc_dai_driver cs35l34_dai = {
.formats = CS35L34_FORMATS,
},
.ops = &cs35l34_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static int cs35l34_boost_inductor(struct cs35l34_private *cs35l34,

View file

@ -692,7 +692,7 @@ static struct snd_soc_dai_driver cs35l35_dai[] = {
.formats = CS35L35_FORMATS,
},
.ops = &cs35l35_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
{
.name = "cs35l35-pdm",

View file

@ -995,7 +995,7 @@ static struct snd_soc_dai_driver cs35l36_dai[] = {
.formats = CS35L36_TX_FORMATS,
},
.ops = &cs35l36_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
};

View file

@ -585,7 +585,7 @@ static struct snd_soc_dai_driver cs4234_dai[] = {
.formats = CS4234_FORMATS,
},
.ops = &cs4234_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
};

View file

@ -481,7 +481,7 @@ static struct snd_soc_dai_driver cs4271_dai = {
.formats = CS4271_PCM_FORMATS,
},
.ops = &cs4271_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static int cs4271_reset(struct snd_soc_component *component)

View file

@ -1250,6 +1250,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
dev_err(&i2c_client->dev,
"CS42L56 Device ID (%X). Expected %X\n",
devid, CS42L56_DEVID);
ret = -EINVAL;
goto err_enable;
}
alpha_rev = reg & CS42L56_AREV_MASK;
@ -1307,7 +1308,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
ret = devm_snd_soc_register_component(&i2c_client->dev,
&soc_component_dev_cs42l56, &cs42l56_dai, 1);
if (ret < 0)
return ret;
goto err_enable;
return 0;

View file

@ -1181,7 +1181,7 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
.formats = CS42L73_FORMATS,
},
.ops = &cs42l73_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
{
.name = "cs42l73-asp",
@ -1201,7 +1201,7 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
.formats = CS42L73_FORMATS,
},
.ops = &cs42l73_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
{
.name = "cs42l73-vsp",
@ -1221,7 +1221,7 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
.formats = CS42L73_FORMATS,
},
.ops = &cs42l73_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
}
};

View file

@ -1581,7 +1581,7 @@ static struct snd_soc_dai_driver cs43130_dai[] = {
.formats = CS43130_PCM_FORMATS,
},
.ops = &cs43130_pcm_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
{
.name = "cs43130-asp-dop",
@ -1594,7 +1594,7 @@ static struct snd_soc_dai_driver cs43130_dai[] = {
.formats = CS43130_DOP_FORMATS,
},
.ops = &cs43130_dop_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
{
.name = "cs43130-xsp-dop",
@ -1607,7 +1607,7 @@ static struct snd_soc_dai_driver cs43130_dai[] = {
.formats = CS43130_DOP_FORMATS,
},
.ops = &cs43130_dop_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
{
.name = "cs43130-xsp-dsd",

View file

@ -189,7 +189,7 @@ static struct snd_soc_dai_driver cs4341_dai = {
SNDRV_PCM_FMTBIT_S24_LE,
},
.ops = &cs4341_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static const struct snd_soc_component_driver soc_component_cs4341 = {

View file

@ -250,7 +250,7 @@ static struct snd_soc_dai_driver cs4349_dai = {
.formats = CS4349_PCM_FORMATS,
},
.ops = &cs4349_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static const struct snd_soc_component_driver soc_component_dev_cs4349 = {

View file

@ -1160,8 +1160,8 @@ static struct snd_soc_dai_driver cs47l15_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l15-aif2",
@ -1182,8 +1182,8 @@ static struct snd_soc_dai_driver cs47l15_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l15-aif3",
@ -1204,8 +1204,8 @@ static struct snd_soc_dai_driver cs47l15_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l15-cpu-trace",

View file

@ -977,8 +977,8 @@ static struct snd_soc_dai_driver cs47l24_dai[] = {
.formats = CS47L24_FORMATS,
},
.ops = &arizona_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l24-aif2",
@ -999,8 +999,8 @@ static struct snd_soc_dai_driver cs47l24_dai[] = {
.formats = CS47L24_FORMATS,
},
.ops = &arizona_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l24-aif3",
@ -1021,8 +1021,8 @@ static struct snd_soc_dai_driver cs47l24_dai[] = {
.formats = CS47L24_FORMATS,
},
.ops = &arizona_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l24-cpu-voicectrl",

View file

@ -1368,8 +1368,8 @@ static struct snd_soc_dai_driver cs47l35_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l35-aif2",
@ -1390,8 +1390,8 @@ static struct snd_soc_dai_driver cs47l35_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l35-aif3",
@ -1412,8 +1412,8 @@ static struct snd_soc_dai_driver cs47l35_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l35-slim1",

View file

@ -2269,8 +2269,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l85-aif2",
@ -2291,8 +2291,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l85-aif3",
@ -2313,8 +2313,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l85-aif4",
@ -2335,8 +2335,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l85-slim1",

View file

@ -2188,8 +2188,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l90-aif2",
@ -2210,8 +2210,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l90-aif3",
@ -2232,8 +2232,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l90-aif4",
@ -2254,8 +2254,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l90-slim1",

View file

@ -1704,8 +1704,8 @@ static struct snd_soc_dai_driver cs47l92_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l92-aif2",
@ -1726,8 +1726,8 @@ static struct snd_soc_dai_driver cs47l92_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l92-aif3",
@ -1748,8 +1748,8 @@ static struct snd_soc_dai_driver cs47l92_dai[] = {
.formats = MADERA_FORMATS,
},
.ops = &madera_dai_ops,
.symmetric_rates = 1,
.symmetric_samplebits = 1,
.symmetric_rate = 1,
.symmetric_sample_bits = 1,
},
{
.name = "cs47l92-slim1",

View file

@ -869,7 +869,7 @@ static struct snd_soc_dai_driver cs53l30_dai = {
.formats = CS53L30_FORMATS,
},
.ops = &cs53l30_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static int cs53l30_component_probe(struct snd_soc_component *component)

View file

@ -1572,7 +1572,7 @@ static struct snd_soc_dai_driver soc_codec_cx2072x_dai[] = {
.formats = CX2072X_FORMATS,
},
.ops = &cx2072x_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
{ /* plabayck only, return echo reference to Conexant DSP chip */
.name = "cx2072x-dsp",

View file

@ -1059,7 +1059,7 @@ static struct snd_soc_dai_driver da7210_dai = {
.formats = DA7210_FORMATS,
},
.ops = &da7210_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static int da7210_probe(struct snd_soc_component *component)

View file

@ -1551,7 +1551,7 @@ static struct snd_soc_dai_driver da7213_dai = {
.formats = DA7213_FORMATS,
},
.ops = &da7213_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static int da7213_set_auto_pll(struct snd_soc_component *component, bool enable)

View file

@ -2194,9 +2194,9 @@ static struct snd_soc_dai_driver da7218_dai = {
.formats = DA7218_FORMATS,
},
.ops = &da7218_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
.symmetric_channels = 1,
.symmetric_samplebits = 1,
.symmetric_sample_bits = 1,
};
@ -2278,14 +2278,12 @@ static irqreturn_t da7218_irq_thread(int irq, void *data)
* DT
*/
#ifdef CONFIG_OF
static const struct of_device_id da7218_of_match[] = {
{ .compatible = "dlg,da7217", .data = (void *) DA7217_DEV_ID },
{ .compatible = "dlg,da7218", .data = (void *) DA7218_DEV_ID },
{ }
};
MODULE_DEVICE_TABLE(of, da7218_of_match);
#endif
static inline int da7218_of_get_id(struct device *dev)
{
@ -3311,7 +3309,7 @@ MODULE_DEVICE_TABLE(i2c, da7218_i2c_id);
static struct i2c_driver da7218_i2c_driver = {
.driver = {
.name = "da7218",
.of_match_table = of_match_ptr(da7218_of_match),
.of_match_table = da7218_of_match,
},
.probe = da7218_i2c_probe,
.id_table = da7218_i2c_id,

View file

@ -1692,9 +1692,9 @@ static struct snd_soc_dai_driver da7219_dai = {
.formats = DA7219_FORMATS,
},
.ops = &da7219_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
.symmetric_channels = 1,
.symmetric_samplebits = 1,
.symmetric_sample_bits = 1,
};

View file

@ -1347,7 +1347,7 @@ static struct snd_soc_dai_driver da9055_dai = {
.formats = DA9055_FORMATS,
},
.ops = &da9055_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static int da9055_set_bias_level(struct snd_soc_component *component,

View file

@ -543,7 +543,7 @@ static struct snd_soc_dai_driver es8316_dai = {
.formats = ES8316_FORMATS,
},
.ops = &es8316_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static void es8316_enable_micbias_for_mic_gnd_short_detect(
@ -681,6 +681,9 @@ static void es8316_disable_jack_detect(struct snd_soc_component *component)
{
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
if (!es8316->jack)
return; /* Already disabled (or never enabled) */
disable_irq(es8316->irq);
mutex_lock(&es8316->lock);

View file

@ -715,7 +715,7 @@ static struct snd_soc_dai_driver es8328_dai = {
.formats = ES8328_FORMATS,
},
.ops = &es8328_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static int es8328_suspend(struct snd_soc_component *component)
@ -809,8 +809,7 @@ static void es8328_remove(struct snd_soc_component *component)
es8328 = snd_soc_component_get_drvdata(component);
if (es8328->clk)
clk_disable_unprepare(es8328->clk);
clk_disable_unprepare(es8328->clk);
regulator_bulk_disable(ARRAY_SIZE(es8328->supplies),
es8328->supplies);

View file

@ -489,6 +489,7 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
hp.sample_rate = params_rate(params);
hp.channels = params_channels(params);
cf->bit_fmt = params_format(params);
return hcp->hcd.ops->hw_params(dai->dev->parent, hcp->hcd.data,
cf, &hp);
}
@ -617,7 +618,8 @@ static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = {
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\
SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |\
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_dai *dai)

View file

@ -325,7 +325,7 @@ static struct snd_soc_dai_driver rk3036_codec_dai_driver[] = {
.formats = RK3036_CODEC_FMTS,
},
.ops = &rk3036_codec_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
};

View file

@ -214,7 +214,7 @@ static struct snd_soc_dai_driver jz4740_codec_dai = {
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
},
.ops = &jz4740_codec_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static void jz4740_codec_wakeup(struct regmap *regmap)

889
sound/soc/codecs/jz4760.c Normal file
View file

@ -0,0 +1,889 @@
// SPDX-License-Identifier: GPL-2.0
//
// Ingenic JZ4760 CODEC driver
//
// Copyright (C) 2021, Christophe Branchereau <cbranchereau@gmail.com>
// Copyright (C) 2021, Paul Cercueil <paul@crapouillou.net>
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/time64.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#define ICDC_RGADW_OFFSET 0x00
#define ICDC_RGDATA_OFFSET 0x04
/* ICDC internal register access control register(RGADW) */
#define ICDC_RGADW_RGWR BIT(16)
#define ICDC_RGADW_RGADDR_MASK GENMASK(14, 8)
#define ICDC_RGADW_RGDIN_MASK GENMASK(7, 0)
/* ICDC internal register data output register (RGDATA)*/
#define ICDC_RGDATA_IRQ BIT(8)
#define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, 0)
/* Internal register space, accessed through regmap */
enum {
JZ4760_CODEC_REG_SR,
JZ4760_CODEC_REG_AICR,
JZ4760_CODEC_REG_CR1,
JZ4760_CODEC_REG_CR2,
JZ4760_CODEC_REG_CR3,
JZ4760_CODEC_REG_CR4,
JZ4760_CODEC_REG_CCR1,
JZ4760_CODEC_REG_CCR2,
JZ4760_CODEC_REG_PMR1,
JZ4760_CODEC_REG_PMR2,
JZ4760_CODEC_REG_ICR,
JZ4760_CODEC_REG_IFR,
JZ4760_CODEC_REG_GCR1,
JZ4760_CODEC_REG_GCR2,
JZ4760_CODEC_REG_GCR3,
JZ4760_CODEC_REG_GCR4,
JZ4760_CODEC_REG_GCR5,
JZ4760_CODEC_REG_GCR6,
JZ4760_CODEC_REG_GCR7,
JZ4760_CODEC_REG_GCR8,
JZ4760_CODEC_REG_GCR9,
JZ4760_CODEC_REG_AGC1,
JZ4760_CODEC_REG_AGC2,
JZ4760_CODEC_REG_AGC3,
JZ4760_CODEC_REG_AGC4,
JZ4760_CODEC_REG_AGC5,
JZ4760_CODEC_REG_MIX1,
JZ4760_CODEC_REG_MIX2,
};
#define REG_AICR_DAC_ADWL_MASK GENMASK(7, 6)
#define REG_AICR_DAC_SERIAL BIT(3)
#define REG_AICR_DAC_I2S BIT(1)
#define REG_AICR_ADC_ADWL_MASK GENMASK(5, 4)
#define REG_AICR_ADC_SERIAL BIT(2)
#define REG_AICR_ADC_I2S BIT(0)
#define REG_CR1_HP_LOAD BIT(7)
#define REG_CR1_HP_MUTE BIT(5)
#define REG_CR1_LO_MUTE_OFFSET 4
#define REG_CR1_BTL_MUTE_OFFSET 3
#define REG_CR1_OUTSEL_OFFSET 0
#define REG_CR1_OUTSEL_MASK GENMASK(1, REG_CR1_OUTSEL_OFFSET)
#define REG_CR2_DAC_MONO BIT(7)
#define REG_CR2_DAC_MUTE BIT(5)
#define REG_CR2_DAC_NOMAD BIT(1)
#define REG_CR2_DAC_RIGHT_ONLY BIT(0)
#define REG_CR3_ADC_INSEL_OFFSET 2
#define REG_CR3_ADC_INSEL_MASK GENMASK(3, REG_CR3_ADC_INSEL_OFFSET)
#define REG_CR3_MICSTEREO_OFFSET 1
#define REG_CR3_MICDIFF_OFFSET 0
#define REG_CR4_ADC_HPF_OFFSET 7
#define REG_CR4_ADC_RIGHT_ONLY BIT(0)
#define REG_CCR1_CRYSTAL_MASK GENMASK(3, 0)
#define REG_CCR2_DAC_FREQ_MASK GENMASK(7, 4)
#define REG_CCR2_ADC_FREQ_MASK GENMASK(3, 0)
#define REG_PMR1_SB BIT(7)
#define REG_PMR1_SB_SLEEP BIT(6)
#define REG_PMR1_SB_AIP_OFFSET 5
#define REG_PMR1_SB_LINE_OFFSET 4
#define REG_PMR1_SB_MIC1_OFFSET 3
#define REG_PMR1_SB_MIC2_OFFSET 2
#define REG_PMR1_SB_BYPASS_OFFSET 1
#define REG_PMR1_SB_MICBIAS_OFFSET 0
#define REG_PMR2_SB_ADC_OFFSET 4
#define REG_PMR2_SB_HP_OFFSET 3
#define REG_PMR2_SB_BTL_OFFSET 2
#define REG_PMR2_SB_LOUT_OFFSET 1
#define REG_PMR2_SB_DAC_OFFSET 0
#define REG_ICR_INT_FORM_MASK GENMASK(7, 6)
#define REG_ICR_ALL_MASK GENMASK(5, 0)
#define REG_ICR_JACK_MASK BIT(5)
#define REG_ICR_SCMC_MASK BIT(4)
#define REG_ICR_RUP_MASK BIT(3)
#define REG_ICR_RDO_MASK BIT(2)
#define REG_ICR_GUP_MASK BIT(1)
#define REG_ICR_GDO_MASK BIT(0)
#define REG_IFR_ALL_MASK GENMASK(5, 0)
#define REG_IFR_JACK BIT(6)
#define REG_IFR_JACK_EVENT BIT(5)
#define REG_IFR_SCMC BIT(4)
#define REG_IFR_RUP BIT(3)
#define REG_IFR_RDO BIT(2)
#define REG_IFR_GUP BIT(1)
#define REG_IFR_GDO BIT(0)
#define REG_GCR_GAIN_OFFSET 0
#define REG_GCR_GAIN_MAX 0x1f
#define REG_GCR_RL BIT(7)
#define REG_GCR_GIM1_MASK GENMASK(5, 3)
#define REG_GCR_GIM2_MASK GENMASK(2, 0)
#define REG_GCR_GIM_GAIN_MAX 7
#define REG_AGC1_EN BIT(7)
#define REG_AGC1_TARGET_MASK GENMASK(5, 2)
#define REG_AGC2_NG_THR_MASK GENMASK(6, 4)
#define REG_AGC2_HOLD_MASK GENMASK(3, 0)
#define REG_AGC3_ATK_MASK GENMASK(7, 4)
#define REG_AGC3_DCY_MASK GENMASK(3, 0)
#define REG_AGC4_AGC_MAX_MASK GENMASK(4, 0)
#define REG_AGC5_AGC_MIN_MASK GENMASK(4, 0)
#define REG_MIX1_MIX_REC_MASK GENMASK(7, 6)
#define REG_MIX1_GIMIX_MASK GENMASK(4, 0)
#define REG_MIX2_DAC_MIX_MASK GENMASK(7, 6)
#define REG_MIX2_GOMIX_MASK GENMASK(4, 0)
/* codec private data */
struct jz_codec {
struct device *dev;
struct regmap *regmap;
void __iomem *base;
struct clk *clk;
};
static int jz4760_codec_set_bias_level(struct snd_soc_component *codec,
enum snd_soc_bias_level level)
{
struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
struct regmap *regmap = jz_codec->regmap;
switch (level) {
case SND_SOC_BIAS_PREPARE:
/* Reset all interrupt flags. */
regmap_write(regmap, JZ4760_CODEC_REG_IFR, REG_IFR_ALL_MASK);
regmap_clear_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB);
msleep(250);
regmap_clear_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB_SLEEP);
msleep(400);
break;
case SND_SOC_BIAS_STANDBY:
regmap_set_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB_SLEEP);
regmap_set_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB);
break;
default:
break;
}
return 0;
}
static int jz4760_codec_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_component *codec = dai->component;
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
int ret;
/*
* SYSCLK output from the codec to the AIC is required to keep the
* DMA transfer going during playback when all audible outputs have
* been disabled.
*/
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
ret = snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");
return 0;
}
static void jz4760_codec_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_component *codec = dai->component;
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
snd_soc_dapm_disable_pin(dapm, "SYSCLK");
}
static int jz4760_codec_pcm_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
struct snd_soc_component *codec = dai->component;
int ret = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
snd_soc_component_force_bias_level(codec, SND_SOC_BIAS_ON);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
/* do nothing */
break;
default:
ret = -EINVAL;
}
return ret;
}
static int jz4760_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
{
struct snd_soc_component *codec = dai->component;
struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
unsigned int gain_bit = mute ? REG_IFR_GDO : REG_IFR_GUP;
unsigned int val, reg;
int change, err;
change = snd_soc_component_update_bits(codec, JZ4760_CODEC_REG_CR2,
REG_CR2_DAC_MUTE,
mute ? REG_CR2_DAC_MUTE : 0);
if (change == 1) {
regmap_read(jz_codec->regmap, JZ4760_CODEC_REG_PMR2, &val);
if (val & BIT(REG_PMR2_SB_DAC_OFFSET))
return 1;
err = regmap_read_poll_timeout(jz_codec->regmap,
JZ4760_CODEC_REG_IFR,
val, val & gain_bit,
1000, 1 * USEC_PER_SEC);
if (err) {
dev_err(jz_codec->dev,
"Timeout while setting digital mute: %d", err);
return err;
}
/* clear GUP/GDO flag */
regmap_write(jz_codec->regmap, JZ4760_CODEC_REG_IFR, gain_bit);
}
regmap_read(jz_codec->regmap, JZ4760_CODEC_REG_CR2, &reg);
return 0;
}
/* unit: 0.01dB */
static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 100);
static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 100);
static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);
/* Unconditional controls. */
static const struct snd_kcontrol_new jz4760_codec_snd_controls[] = {
/* record gain control */
SOC_DOUBLE_R_TLV("PCM Capture Volume",
JZ4760_CODEC_REG_GCR9, JZ4760_CODEC_REG_GCR8,
REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 0, adc_tlv),
SOC_DOUBLE_R_TLV("Line In Bypass Playback Volume",
JZ4760_CODEC_REG_GCR4, JZ4760_CODEC_REG_GCR3,
REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, linein_tlv),
SOC_SINGLE("High-Pass Filter Capture Switch",
JZ4760_CODEC_REG_CR4,
REG_CR4_ADC_HPF_OFFSET, 1, 0),
};
static const struct snd_kcontrol_new jz4760_codec_pcm_playback_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Volume",
.info = snd_soc_info_volsw,
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
| SNDRV_CTL_ELEM_ACCESS_READWRITE,
.tlv.p = dac_tlv,
.get = snd_soc_dapm_get_volsw,
.put = snd_soc_dapm_put_volsw,
.private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR6,
JZ4760_CODEC_REG_GCR5,
REG_GCR_GAIN_OFFSET,
REG_GCR_GAIN_MAX, 1),
},
};
static const struct snd_kcontrol_new jz4760_codec_hp_playback_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Volume",
.info = snd_soc_info_volsw,
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
| SNDRV_CTL_ELEM_ACCESS_READWRITE,
.tlv.p = out_tlv,
.get = snd_soc_dapm_get_volsw,
.put = snd_soc_dapm_put_volsw,
.private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR2,
JZ4760_CODEC_REG_GCR1,
REG_GCR_GAIN_OFFSET,
REG_GCR_GAIN_MAX, 1),
},
};
static int hpout_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
unsigned int val;
int err;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
/* unmute HP */
regmap_clear_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR1,
REG_CR1_HP_MUTE);
break;
case SND_SOC_DAPM_POST_PMU:
/* wait for ramp-up complete (RUP) */
err = regmap_read_poll_timeout(jz_codec->regmap,
JZ4760_CODEC_REG_IFR,
val, val & REG_IFR_RUP,
1000, 1 * USEC_PER_SEC);
if (err) {
dev_err(jz_codec->dev, "RUP timeout: %d", err);
return err;
}
/* clear RUP flag */
regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_IFR,
REG_IFR_RUP);
break;
case SND_SOC_DAPM_POST_PMD:
/* mute HP */
regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR1,
REG_CR1_HP_MUTE);
err = regmap_read_poll_timeout(jz_codec->regmap,
JZ4760_CODEC_REG_IFR,
val, val & REG_IFR_RDO,
1000, 1 * USEC_PER_SEC);
if (err) {
dev_err(jz_codec->dev, "RDO timeout: %d", err);
return err;
}
/* clear RDO flag */
regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_IFR,
REG_IFR_RDO);
break;
}
return 0;
}
static const char * const jz4760_codec_hp_texts[] = {
"PCM", "Line In", "Mic 1", "Mic 2"
};
static const unsigned int jz4760_codec_hp_values[] = { 3, 2, 0, 1 };
static SOC_VALUE_ENUM_SINGLE_DECL(jz4760_codec_hp_enum,
JZ4760_CODEC_REG_CR1,
REG_CR1_OUTSEL_OFFSET,
REG_CR1_OUTSEL_MASK >> REG_CR1_OUTSEL_OFFSET,
jz4760_codec_hp_texts,
jz4760_codec_hp_values);
static const struct snd_kcontrol_new jz4760_codec_hp_source =
SOC_DAPM_ENUM("Route", jz4760_codec_hp_enum);
static const char * const jz4760_codec_cap_texts[] = {
"Line In", "Mic 1", "Mic 2"
};
static const unsigned int jz4760_codec_cap_values[] = { 2, 0, 1 };
static SOC_VALUE_ENUM_SINGLE_DECL(jz4760_codec_cap_enum,
JZ4760_CODEC_REG_CR3,
REG_CR3_ADC_INSEL_OFFSET,
REG_CR3_ADC_INSEL_MASK >> REG_CR3_ADC_INSEL_OFFSET,
jz4760_codec_cap_texts,
jz4760_codec_cap_values);
static const struct snd_kcontrol_new jz4760_codec_cap_source =
SOC_DAPM_ENUM("Route", jz4760_codec_cap_enum);
static const struct snd_kcontrol_new jz4760_codec_mic_controls[] = {
SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4760_CODEC_REG_CR3,
REG_CR3_MICSTEREO_OFFSET, 1, 0),
};
static const struct snd_kcontrol_new jz4760_codec_line_out_switch =
SOC_DAPM_SINGLE("Switch", JZ4760_CODEC_REG_CR1,
REG_CR1_LO_MUTE_OFFSET, 0, 0);
static const struct snd_kcontrol_new jz4760_codec_btl_out_switch =
SOC_DAPM_SINGLE("Switch", JZ4760_CODEC_REG_CR1,
REG_CR1_BTL_MUTE_OFFSET, 0, 0);
static const struct snd_soc_dapm_widget jz4760_codec_dapm_widgets[] = {
SND_SOC_DAPM_PGA_E("HP Out", JZ4760_CODEC_REG_PMR2,
REG_PMR2_SB_HP_OFFSET, 1, NULL, 0, hpout_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SWITCH("Line Out", JZ4760_CODEC_REG_PMR2,
REG_PMR2_SB_LOUT_OFFSET, 1,
&jz4760_codec_line_out_switch),
SND_SOC_DAPM_SWITCH("BTL Out", JZ4760_CODEC_REG_PMR2,
REG_PMR2_SB_BTL_OFFSET, 1,
&jz4760_codec_btl_out_switch),
SND_SOC_DAPM_PGA("Line In", JZ4760_CODEC_REG_PMR1,
REG_PMR1_SB_LINE_OFFSET, 1, NULL, 0),
SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0,
&jz4760_codec_hp_source),
SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
&jz4760_codec_cap_source),
SND_SOC_DAPM_PGA("Mic 1", JZ4760_CODEC_REG_PMR1,
REG_PMR1_SB_MIC1_OFFSET, 1, NULL, 0),
SND_SOC_DAPM_PGA("Mic 2", JZ4760_CODEC_REG_PMR1,
REG_PMR1_SB_MIC2_OFFSET, 1, NULL, 0),
SND_SOC_DAPM_PGA("Mic Diff", JZ4760_CODEC_REG_CR3,
REG_CR3_MICDIFF_OFFSET, 0, NULL, 0),
SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,
jz4760_codec_mic_controls,
ARRAY_SIZE(jz4760_codec_mic_controls)),
SND_SOC_DAPM_PGA("Line In Bypass", JZ4760_CODEC_REG_PMR1,
REG_PMR1_SB_BYPASS_OFFSET, 1, NULL, 0),
SND_SOC_DAPM_ADC("ADC", "Capture", JZ4760_CODEC_REG_PMR2,
REG_PMR2_SB_ADC_OFFSET, 1),
SND_SOC_DAPM_DAC("DAC", "Playback", JZ4760_CODEC_REG_PMR2,
REG_PMR2_SB_DAC_OFFSET, 1),
SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0,
jz4760_codec_pcm_playback_controls,
ARRAY_SIZE(jz4760_codec_pcm_playback_controls)),
SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0,
jz4760_codec_hp_playback_controls,
ARRAY_SIZE(jz4760_codec_hp_playback_controls)),
SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4760_CODEC_REG_PMR1,
REG_PMR1_SB_MICBIAS_OFFSET, 1, NULL, 0),
SND_SOC_DAPM_INPUT("MIC1P"),
SND_SOC_DAPM_INPUT("MIC1N"),
SND_SOC_DAPM_INPUT("MIC2P"),
SND_SOC_DAPM_INPUT("MIC2N"),
SND_SOC_DAPM_INPUT("LLINEIN"),
SND_SOC_DAPM_INPUT("RLINEIN"),
SND_SOC_DAPM_OUTPUT("LHPOUT"),
SND_SOC_DAPM_OUTPUT("RHPOUT"),
SND_SOC_DAPM_OUTPUT("LOUT"),
SND_SOC_DAPM_OUTPUT("ROUT"),
SND_SOC_DAPM_OUTPUT("BTLP"),
SND_SOC_DAPM_OUTPUT("BTLN"),
SND_SOC_DAPM_OUTPUT("SYSCLK"),
};
/* Unconditional routes. */
static const struct snd_soc_dapm_route jz4760_codec_dapm_routes[] = {
{ "Mic 1", NULL, "MIC1P" },
{ "Mic Diff", NULL, "MIC1N" },
{ "Mic 1", NULL, "Mic Diff" },
{ "Mic 2", NULL, "MIC2P" },
{ "Mic Diff", NULL, "MIC2N" },
{ "Mic 2", NULL, "Mic Diff" },
{ "Line In", NULL, "LLINEIN" },
{ "Line In", NULL, "RLINEIN" },
{ "Mic", "Stereo Capture Switch", "Mic 1" },
{ "Mic", "Stereo Capture Switch", "Mic 2" },
{ "Headphones Source", "Mic 1", "Mic" },
{ "Headphones Source", "Mic 2", "Mic" },
{ "Capture Source", "Mic 1", "Mic" },
{ "Capture Source", "Mic 2", "Mic" },
{ "Capture Source", "Line In", "Line In" },
{ "Capture Source", "Mic 1", "Mic 1" },
{ "Capture Source", "Mic 2", "Mic 2" },
{ "ADC", NULL, "Capture Source" },
{ "Line In Bypass", NULL, "Line In" },
{ "Headphones Source", "Mic 1", "Mic 1" },
{ "Headphones Source", "Mic 2", "Mic 2" },
{ "Headphones Source", "Line In", "Line In Bypass" },
{ "Headphones Source", "PCM", "Headphones Playback" },
{ "HP Out", NULL, "Headphones Source" },
{ "LHPOUT", NULL, "HP Out" },
{ "RHPOUT", NULL, "HP Out" },
{ "Line Out", "Switch", "HP Out" },
{ "LOUT", NULL, "Line Out" },
{ "ROUT", NULL, "Line Out" },
{ "BTL Out", "Switch", "Line Out" },
{ "BTLP", NULL, "BTL Out"},
{ "BTLN", NULL, "BTL Out"},
{ "PCM Playback", "Volume", "DAC" },
{ "Headphones Playback", "Volume", "PCM Playback" },
{ "SYSCLK", NULL, "DAC" },
};
static void jz4760_codec_codec_init_regs(struct snd_soc_component *codec)
{
struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
struct regmap *regmap = jz_codec->regmap;
/* Collect updates for later sending. */
regcache_cache_only(regmap, true);
/* default Amp output to PCM */
regmap_set_bits(regmap, JZ4760_CODEC_REG_CR1, REG_CR1_OUTSEL_MASK);
/* Disable stereo mic */
regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR3,
BIT(REG_CR3_MICSTEREO_OFFSET));
/* Set mic 1 as default source for ADC */
regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR3,
REG_CR3_ADC_INSEL_MASK);
/* ADC/DAC: serial + i2s */
regmap_set_bits(regmap, JZ4760_CODEC_REG_AICR,
REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S |
REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S);
/* The generated IRQ is a high level */
regmap_clear_bits(regmap, JZ4760_CODEC_REG_ICR, REG_ICR_INT_FORM_MASK);
regmap_update_bits(regmap, JZ4760_CODEC_REG_ICR, REG_ICR_ALL_MASK,
REG_ICR_JACK_MASK | REG_ICR_RUP_MASK |
REG_ICR_RDO_MASK | REG_ICR_GUP_MASK |
REG_ICR_GDO_MASK);
/* 12M oscillator */
regmap_clear_bits(regmap, JZ4760_CODEC_REG_CCR1, REG_CCR1_CRYSTAL_MASK);
/* 0: 16ohm/220uF, 1: 10kohm/1uF */
regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR1, REG_CR1_HP_LOAD);
/* default to NOMAD */
regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR2,
REG_CR2_DAC_NOMAD);
/* disable automatic gain */
regmap_clear_bits(regmap, JZ4760_CODEC_REG_AGC1, REG_AGC1_EN);
/* Independent L/R DAC gain control */
regmap_clear_bits(regmap, JZ4760_CODEC_REG_GCR5,
REG_GCR_RL);
/* Send collected updates. */
regcache_cache_only(regmap, false);
regcache_sync(regmap);
}
static int jz4760_codec_codec_probe(struct snd_soc_component *codec)
{
struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
clk_prepare_enable(jz_codec->clk);
jz4760_codec_codec_init_regs(codec);
return 0;
}
static void jz4760_codec_codec_remove(struct snd_soc_component *codec)
{
struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
clk_disable_unprepare(jz_codec->clk);
}
static const struct snd_soc_component_driver jz4760_codec_soc_codec_dev = {
.probe = jz4760_codec_codec_probe,
.remove = jz4760_codec_codec_remove,
.set_bias_level = jz4760_codec_set_bias_level,
.controls = jz4760_codec_snd_controls,
.num_controls = ARRAY_SIZE(jz4760_codec_snd_controls),
.dapm_widgets = jz4760_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(jz4760_codec_dapm_widgets),
.dapm_routes = jz4760_codec_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(jz4760_codec_dapm_routes),
.suspend_bias_off = 1,
.use_pmdown_time = 1,
};
static const unsigned int jz4760_codec_sample_rates[] = {
96000, 48000, 44100, 32000,
24000, 22050, 16000, 12000,
11025, 9600, 8000,
};
static int jz4760_codec_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);
unsigned int rate, bit_width;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
bit_width = 0;
break;
case SNDRV_PCM_FORMAT_S18_3LE:
bit_width = 1;
break;
case SNDRV_PCM_FORMAT_S20_3LE:
bit_width = 2;
break;
case SNDRV_PCM_FORMAT_S24_3LE:
bit_width = 3;
break;
default:
return -EINVAL;
}
for (rate = 0; rate < ARRAY_SIZE(jz4760_codec_sample_rates); rate++) {
if (jz4760_codec_sample_rates[rate] == params_rate(params))
break;
}
if (rate == ARRAY_SIZE(jz4760_codec_sample_rates))
return -EINVAL;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_AICR,
REG_AICR_DAC_ADWL_MASK,
FIELD_PREP(REG_AICR_DAC_ADWL_MASK, bit_width));
regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_CCR2,
REG_CCR2_DAC_FREQ_MASK,
FIELD_PREP(REG_CCR2_DAC_FREQ_MASK, rate));
} else {
regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_AICR,
REG_AICR_ADC_ADWL_MASK,
FIELD_PREP(REG_AICR_ADC_ADWL_MASK, bit_width));
regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_CCR2,
REG_CCR2_ADC_FREQ_MASK,
FIELD_PREP(REG_CCR2_ADC_FREQ_MASK, rate));
}
return 0;
}
static const struct snd_soc_dai_ops jz4760_codec_dai_ops = {
.startup = jz4760_codec_startup,
.shutdown = jz4760_codec_shutdown,
.hw_params = jz4760_codec_hw_params,
.trigger = jz4760_codec_pcm_trigger,
.mute_stream = jz4760_codec_mute_stream,
.no_capture_mute = 1,
};
#define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S18_3LE | \
SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_3LE)
static struct snd_soc_dai_driver jz4760_codec_dai = {
.name = "jz4760-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = JZ_CODEC_FORMATS,
},
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = JZ_CODEC_FORMATS,
},
.ops = &jz4760_codec_dai_ops,
};
static bool jz4760_codec_volatile(struct device *dev, unsigned int reg)
{
return reg == JZ4760_CODEC_REG_SR || reg == JZ4760_CODEC_REG_IFR;
}
static bool jz4760_codec_writeable(struct device *dev, unsigned int reg)
{
switch (reg) {
case JZ4760_CODEC_REG_SR:
return false;
default:
return true;
}
}
static int jz4760_codec_io_wait(struct jz_codec *codec)
{
u32 reg;
return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,
!(reg & ICDC_RGADW_RGWR),
1000, 1 * USEC_PER_SEC);
}
static int jz4760_codec_reg_read(void *context, unsigned int reg,
unsigned int *val)
{
struct jz_codec *codec = context;
unsigned int i;
u32 tmp;
int ret;
ret = jz4760_codec_io_wait(codec);
if (ret)
return ret;
tmp = readl(codec->base + ICDC_RGADW_OFFSET);
tmp &= ~ICDC_RGADW_RGADDR_MASK;
tmp |= FIELD_PREP(ICDC_RGADW_RGADDR_MASK, reg);
writel(tmp, codec->base + ICDC_RGADW_OFFSET);
/* wait 6+ cycles */
for (i = 0; i < 6; i++)
*val = readl(codec->base + ICDC_RGDATA_OFFSET) &
ICDC_RGDATA_RGDOUT_MASK;
return 0;
}
static int jz4760_codec_reg_write(void *context, unsigned int reg,
unsigned int val)
{
struct jz_codec *codec = context;
int ret;
ret = jz4760_codec_io_wait(codec);
if (ret)
return ret;
writel(ICDC_RGADW_RGWR | FIELD_PREP(ICDC_RGADW_RGADDR_MASK, reg) | val,
codec->base + ICDC_RGADW_OFFSET);
ret = jz4760_codec_io_wait(codec);
if (ret)
return ret;
return 0;
}
static const u8 jz4760_codec_reg_defaults[] = {
0x00, 0xFC, 0x1B, 0x20, 0x00, 0x80, 0x00, 0x00,
0xFF, 0x1F, 0x3F, 0x00, 0x06, 0x06, 0x06, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x07, 0x44,
0x1F, 0x00, 0x00, 0x00
};
static struct regmap_config jz4760_codec_regmap_config = {
.reg_bits = 7,
.val_bits = 8,
.max_register = JZ4760_CODEC_REG_MIX2,
.volatile_reg = jz4760_codec_volatile,
.writeable_reg = jz4760_codec_writeable,
.reg_read = jz4760_codec_reg_read,
.reg_write = jz4760_codec_reg_write,
.reg_defaults_raw = jz4760_codec_reg_defaults,
.num_reg_defaults_raw = ARRAY_SIZE(jz4760_codec_reg_defaults),
.cache_type = REGCACHE_FLAT,
};
static int jz4760_codec_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct jz_codec *codec;
int ret;
codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
if (!codec)
return -ENOMEM;
codec->dev = dev;
codec->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(codec->base)) {
ret = PTR_ERR(codec->base);
dev_err(dev, "Failed to ioremap mmio memory: %d\n", ret);
return ret;
}
codec->regmap = devm_regmap_init(dev, NULL, codec,
&jz4760_codec_regmap_config);
if (IS_ERR(codec->regmap))
return PTR_ERR(codec->regmap);
codec->clk = devm_clk_get(dev, "aic");
if (IS_ERR(codec->clk))
return PTR_ERR(codec->clk);
platform_set_drvdata(pdev, codec);
ret = devm_snd_soc_register_component(dev, &jz4760_codec_soc_codec_dev,
&jz4760_codec_dai, 1);
if (ret) {
dev_err(dev, "Failed to register codec: %d\n", ret);
return ret;
}
return 0;
}
static const struct of_device_id jz4760_codec_of_matches[] = {
{ .compatible = "ingenic,jz4760-codec", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, jz4760_codec_of_matches);
static struct platform_driver jz4760_codec_driver = {
.probe = jz4760_codec_probe,
.driver = {
.name = "jz4760-codec",
.of_match_table = jz4760_codec_of_matches,
},
};
module_platform_driver(jz4760_codec_driver);
MODULE_DESCRIPTION("JZ4760 SoC internal codec driver");
MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>");
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
MODULE_LICENSE("GPL v2");

View file

@ -1343,7 +1343,7 @@ static struct snd_soc_dai_driver lm49453_dai[] = {
.formats = LM49453_FORMATS,
},
.ops = &lm49453_headset_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
},
{
.name = "LM49453 Speaker",

View file

@ -166,8 +166,8 @@ static struct snd_soc_dai_driver lochnagar_sc_dai[] = {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &lochnagar_sc_line_ops,
.symmetric_rates = true,
.symmetric_samplebits = true,
.symmetric_rate = true,
.symmetric_sample_bits = true,
},
{
.name = "lochnagar-usb1",
@ -186,8 +186,8 @@ static struct snd_soc_dai_driver lochnagar_sc_dai[] = {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &lochnagar_sc_usb_ops,
.symmetric_rates = true,
.symmetric_samplebits = true,
.symmetric_rate = true,
.symmetric_sample_bits = true,
},
{
.name = "lochnagar-usb2",
@ -206,8 +206,8 @@ static struct snd_soc_dai_driver lochnagar_sc_dai[] = {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &lochnagar_sc_usb_ops,
.symmetric_rates = true,
.symmetric_samplebits = true,
.symmetric_rate = true,
.symmetric_sample_bits = true,
},
};

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -40,9 +40,11 @@
#define CDC_WSA_TOP_I2S_CLK (0x00A4)
#define CDC_WSA_TOP_I2S_RESET (0x00A8)
#define CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 (0x0100)
#define CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK GENMASK(5, 3)
#define CDC_WSA_RX_INTX_2_SEL_MASK GENMASK(2, 0)
#define CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK GENMASK(2, 0)
#define CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK GENMASK(5, 3)
#define CDC_WSA_RX_INP_MUX_RX_INT0_CFG1 (0x0104)
#define CDC_WSA_RX_INTX_2_SEL_MASK GENMASK(2, 0)
#define CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK GENMASK(5, 3)
#define CDC_WSA_RX_INP_MUX_RX_INT1_CFG0 (0x0108)
#define CDC_WSA_RX_INP_MUX_RX_INT1_CFG1 (0x010C)
#define CDC_WSA_RX_INP_MUX_RX_MIX_CFG0 (0x0110)
@ -229,8 +231,6 @@
#define NUM_INTERPOLATORS 2
#define WSA_NUM_CLKS_MAX 5
#define WSA_MACRO_MCLK_FREQ 19200000
#define WSA_MACRO_MUX_INP_SHFT 0x3
#define WSA_MACRO_MUX_INP_MASK1 0x07
#define WSA_MACRO_MUX_INP_MASK2 0x38
#define WSA_MACRO_MUX_CFG_OFFSET 0x8
#define WSA_MACRO_MUX_CFG1_OFFSET 0x4
@ -843,7 +843,6 @@ static int wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
u32 j, port;
u16 int_mux_cfg0, int_mux_cfg1;
u16 int_fs_reg;
u8 int_mux_cfg0_val, int_mux_cfg1_val;
u8 inp0_sel, inp1_sel, inp2_sel;
struct snd_soc_component *component = dai->component;
struct wsa_macro *wsa = snd_soc_component_get_drvdata(component);
@ -865,15 +864,13 @@ static int wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai,
*/
for (j = 0; j < NUM_INTERPOLATORS; j++) {
int_mux_cfg1 = int_mux_cfg0 + WSA_MACRO_MUX_CFG1_OFFSET;
int_mux_cfg0_val = snd_soc_component_read(component,
int_mux_cfg0);
int_mux_cfg1_val = snd_soc_component_read(component,
int_mux_cfg1);
inp0_sel = int_mux_cfg0_val & WSA_MACRO_MUX_INP_MASK1;
inp1_sel = (int_mux_cfg0_val >> WSA_MACRO_MUX_INP_SHFT) &
WSA_MACRO_MUX_INP_MASK1;
inp2_sel = (int_mux_cfg1_val >> WSA_MACRO_MUX_INP_SHFT) &
WSA_MACRO_MUX_INP_MASK1;
inp0_sel = snd_soc_component_read_field(component, int_mux_cfg0,
CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK);
inp1_sel = snd_soc_component_read_field(component, int_mux_cfg0,
CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK);
inp2_sel = snd_soc_component_read_field(component, int_mux_cfg1,
CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK);
if ((inp0_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) ||
(inp1_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) ||
(inp2_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0)) {
@ -912,9 +909,9 @@ static int wsa_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai,
int_mux_cfg1 = CDC_WSA_RX_INP_MUX_RX_INT0_CFG1;
for (j = 0; j < NUM_INTERPOLATORS; j++) {
int_mux_cfg1_val = snd_soc_component_read(component,
int_mux_cfg1) &
WSA_MACRO_MUX_INP_MASK1;
int_mux_cfg1_val = snd_soc_component_read_field(component, int_mux_cfg1,
CDC_WSA_RX_INTX_2_SEL_MASK);
if (int_mux_cfg1_val == int_2_inp + INTn_2_INP_SEL_RX0) {
int_fs_reg = CDC_WSA_RX0_RX_PATH_MIX_CTL +
WSA_MACRO_RX_PATH_OFFSET * j;
@ -1410,25 +1407,25 @@ static bool wsa_macro_adie_lb(struct snd_soc_component *component,
int interp_idx)
{
u16 int_mux_cfg0, int_mux_cfg1;
u8 int_mux_cfg0_val, int_mux_cfg1_val;
u8 int_n_inp0, int_n_inp1, int_n_inp2;
int_mux_cfg0 = CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 + interp_idx * 8;
int_mux_cfg1 = int_mux_cfg0 + 4;
int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0);
int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1);
int_n_inp0 = int_mux_cfg0_val & 0x0F;
int_n_inp0 = snd_soc_component_read_field(component, int_mux_cfg0,
CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK);
if (int_n_inp0 == INTn_1_INP_SEL_DEC0 ||
int_n_inp0 == INTn_1_INP_SEL_DEC1)
return true;
int_n_inp1 = int_mux_cfg0_val >> 4;
int_n_inp1 = snd_soc_component_read_field(component, int_mux_cfg0,
CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK);
if (int_n_inp1 == INTn_1_INP_SEL_DEC0 ||
int_n_inp1 == INTn_1_INP_SEL_DEC1)
return true;
int_n_inp2 = int_mux_cfg1_val >> 4;
int_n_inp2 = snd_soc_component_read_field(component, int_mux_cfg1,
CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK);
if (int_n_inp2 == INTn_1_INP_SEL_DEC0 ||
int_n_inp2 == INTn_1_INP_SEL_DEC1)
return true;

View file

@ -262,6 +262,8 @@ static __maybe_unused int max98373_suspend(struct device *dev)
return 0;
}
#define MAX98373_PROBE_TIMEOUT 5000
static __maybe_unused int max98373_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
@ -275,7 +277,7 @@ static __maybe_unused int max98373_resume(struct device *dev)
goto regmap_sync;
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(2000));
msecs_to_jiffies(MAX98373_PROBE_TIMEOUT));
if (!time) {
dev_err(dev, "Initialization not complete, timed out\n");
return -ETIMEDOUT;

View file

@ -489,7 +489,7 @@ static struct snd_soc_dai_driver max9860_dai = {
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &max9860_dai_ops,
.symmetric_rates = 1,
.symmetric_rate = 1,
};
static int max9860_set_bias_level(struct snd_soc_component *component,

Some files were not shown because too many files have changed in this diff Show more