Merge branch 'asoc-5.3' into asoc-next

This commit is contained in:
Mark Brown 2019-07-06 12:25:26 +01:00
commit 043b35f281
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0
312 changed files with 26362 additions and 4794 deletions

View file

@ -11,7 +11,7 @@ Required properties:
- clock-names: must contain "mclk", which is the DCMI peripherial clock
- pinctrl: the pincontrol settings to configure muxing properly
for pins that connect to DCMI device.
See Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt.
See Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml.
- dmas: phandle to DMA controller node,
see Documentation/devicetree/bindings/dma/stm32-dma.txt
- dma-names: must contain "tx", which is the transmit channel from DCMI to DMA

View file

@ -0,0 +1,132 @@
# SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/allwinner,sun4i-a10-i2s.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A10 I2S Controller Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <maxime.ripard@bootlin.com>
properties:
"#sound-dai-cells":
const: 0
compatible:
oneOf:
- const: allwinner,sun4i-a10-i2s
- const: allwinner,sun6i-a31-i2s
- const: allwinner,sun8i-a83t-i2s
- const: allwinner,sun8i-h3-i2s
- const: allwinner,sun50i-a64-codec-i2s
- items:
- const: allwinner,sun50i-a64-i2s
- const: allwinner,sun8i-h3-i2s
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: Bus Clock
- description: Module Clock
clock-names:
items:
- const: apb
- const: mod
# Even though it only applies to subschemas under the conditionals,
# not listing them here will trigger a warning because of the
# additionalsProperties set to false.
dmas: true
dma-names: true
resets:
maxItems: 1
allOf:
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun6i-a31-i2s
- allwinner,sun8i-a83t-i2s
- allwinner,sun8i-h3-i2s
- allwinner,sun50i-a64-codec-i2s
then:
required:
- resets
- if:
properties:
compatible:
contains:
const: allwinner,sun8i-a83t-i2s
then:
properties:
dmas:
minItems: 1
maxItems: 2
items:
- description: RX DMA Channel
- description: TX DMA Channel
description:
Some controllers cannot receive but can only transmit
data. In such a case, the RX DMA channel is to be omitted.
dma-names:
oneOf:
- items:
- const: rx
- const: tx
- const: tx
description:
Some controllers cannot receive but can only transmit
data. In such a case, the RX name is to be omitted.
else:
properties:
dmas:
items:
- description: RX DMA Channel
- description: TX DMA Channel
dma-names:
items:
- const: rx
- const: tx
required:
- "#sound-dai-cells"
- compatible
- reg
- interrupts
- clocks
- clock-names
- dmas
- dma-names
additionalProperties: false
examples:
- |
i2s0: i2s@1c22400 {
#sound-dai-cells = <0>;
compatible = "allwinner,sun4i-a10-i2s";
reg = <0x01c22400 0x400>;
interrupts = <0 16 4>;
clocks = <&apb0_gates 3>, <&i2s0_clk>;
clock-names = "apb", "mod";
dmas = <&dma 0 3>, <&dma 0 3>;
dma-names = "rx", "tx";
};
...

View file

@ -0,0 +1,120 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/allwinner,sun4i-a10-spdif.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A10 S/PDIF Controller Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Liam Girdwood <lgirdwood@gmail.com>
- Mark Brown <broonie@kernel.org>
- Maxime Ripard <maxime.ripard@bootlin.com>
properties:
"#sound-dai-cells":
const: 0
compatible:
oneOf:
- const: allwinner,sun4i-a10-spdif
- const: allwinner,sun6i-a31-spdif
- const: allwinner,sun8i-h3-spdif
- const: allwinner,sun50i-h6-spdif
- items:
- const: allwinner,sun8i-a83t-spdif
- const: allwinner,sun8i-h3-spdif
- items:
- const: allwinner,sun50i-a64-spdif
- const: allwinner,sun8i-h3-spdif
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: Bus Clock
- description: Module Clock
clock-names:
items:
- const: apb
- const: spdif
# Even though it only applies to subschemas under the conditionals,
# not listing them here will trigger a warning because of the
# additionalsProperties set to false.
dmas: true
dma-names: true
resets:
maxItems: 1
allOf:
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun6i-a31-spdif
- allwinner,sun8i-h3-spdif
then:
required:
- resets
- if:
properties:
compatible:
contains:
const: allwinner,sun8i-h3-spdif
then:
properties:
dmas:
description: TX DMA Channel
dma-names:
const: tx
else:
properties:
dmas:
items:
- description: RX DMA Channel
- description: TX DMA Channel
dma-names:
items:
- const: rx
- const: tx
required:
- "#sound-dai-cells"
- compatible
- reg
- interrupts
- clocks
- clock-names
- dmas
- dma-names
additionalProperties: false
examples:
- |
spdif: spdif@1c21000 {
#sound-dai-cells = <0>;
compatible = "allwinner,sun4i-a10-spdif";
reg = <0x01c21000 0x40>;
interrupts = <13>;
clocks = <&apb0_gates 1>, <&spdif_clk>;
clock-names = "apb", "spdif";
dmas = <&dma 0 2>, <&dma 0 2>;
dma-names = "rx", "tx";
};
...

View file

@ -15,11 +15,15 @@ Required properties:
* "lrclk" : sample clock
* "lrclk_sel": sample clock input multiplexer
Example of TDMOUT_A on the A113 SoC:
Optional property:
- resets: phandle to the dedicated reset line of the tdm formatter.
Example of TDMOUT_A on the S905X2 SoC:
tdmout_a: audio-controller@500 {
compatible = "amlogic,axg-tdmout";
reg = <0x0 0x500 0x0 0x40>;
resets = <&clkc_audio AUD_RESET_TDMOUT_A>;
clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>,
<&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>,
<&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>,

View file

@ -0,0 +1,55 @@
* Amlogic HDMI Tx control glue
Required properties:
- compatible: "amlogic,g12a-tohdmitx"
- reg: physical base address of the controller and length of memory
mapped region.
- #sound-dai-cells: should be 1.
Example on the S905X2 SoC:
tohdmitx: audio-controller@744 {
compatible = "amlogic,g12a-tohdmitx";
reg = <0x0 0x744 0x0 0x4>;
#sound-dai-cells = <1>;
};
Example of an 'amlogic,axg-sound-card':
sound {
compatible = "amlogic,axg-sound-card";
[...]
dai-link-x {
sound-dai = <&tdmif_a>;
dai-format = "i2s";
dai-tdm-slot-tx-mask-0 = <1 1>;
codec-0 {
sound-dai = <&tohdmitx TOHDMITX_I2S_IN_A>;
};
codec-1 {
sound-dai = <&external_dac>;
};
};
dai-link-y {
sound-dai = <&tdmif_c>;
dai-format = "i2s";
dai-tdm-slot-tx-mask-0 = <1 1>;
codec {
sound-dai = <&tohdmitx TOHDMITX_I2S_IN_C>;
};
};
dai-link-z {
sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>;
codec {
sound-dai = <&hdmi_tx>;
};
};
};

View file

@ -14,6 +14,11 @@ Required properties:
- VA-supply, VD-supply, VLS-supply, VLC-supply: power supplies for the device,
as covered in Documentation/devicetree/bindings/regulator/regulator.txt
Optional properties:
- reset-gpios : a GPIO spec to define which pin is connected to the chip's
!RESET pin
Example:
cs42888: codec@48 {
@ -25,4 +30,5 @@ cs42888: codec@48 {
VD-supply = <&reg_audio>;
VLS-supply = <&reg_audio>;
VLC-supply = <&reg_audio>;
reset-gpios = <&pca9557_b 1 GPIO_ACTIVE_LOW>;
};

View file

@ -44,6 +44,9 @@ Optional properties:
please refer to pinctrl-bindings.txt
- fck_parent : Should contain a valid clock name which will be used as parent
for the McASP fck
- auxclk-fs-ratio: When McASP is bus master indicates the ratio between AUCLK
and FS rate if applicable:
AUCLK rate = auxclk-fs-ratio * FS rate
Optional GPIO support:
If any McASP pin need to be used as GPIO then the McASP node must have:

View file

@ -0,0 +1,67 @@
Cirrus Logic Madera class audio codecs
This describes audio configuration bindings for these codecs.
See also the core bindings for the parent MFD driver:
See Documentation/devicetree/bindings/mfd/madera.txt
and defines for values used in these bindings:
include/dt-bindings/sound/madera.h
These properties are all contained in the parent MFD node.
Optional properties:
- cirrus,dmic-ref : Indicates how the MICBIAS pins have been externally
connected to DMICs on each input, one cell per input.
<IN1 IN2 IN3 ...>
A value of 0 indicates MICVDD and is the default, other values depend on the
codec:
For CS47L35 one of the CS47L35_DMIC_REF_xxx values
For all other codecs one of the MADERA_DMIC_REF_xxx values
Also see the datasheet for a description of the INn_DMIC_SUP field.
- cirrus,inmode : A list of input mode settings for each input. A maximum of
16 cells, with four cells per input in the order INnAL, INnAR INnBL INnBR.
For non-muxed inputs the first two cells for that input set the mode for
the left and right channel and the second two cells must be 0.
For muxed inputs the first two cells for that input set the mode of the
left and right A inputs and the second two cells set the mode of the left
and right B inputs.
Valid mode values are one of the MADERA_INMODE_xxx. If the array is shorter
than the number of inputs the unspecified inputs default to
MADERA_INMODE_DIFF.
- cirrus,out-mono : Mono bit for each output, maximum of six cells if the
array is shorter outputs will be set to stereo.
- cirrus,max-channels-clocked : Maximum number of channels that I2S clocks
will be generated for. Useful when clock master for systems where the I2S
bus has multiple data lines.
One cell for each AIF, use a value of zero for AIFs that should be handled
normally.
- cirrus,pdm-fmt : PDM speaker data format, must contain 2 cells
(OUT5 and OUT6). See the PDM_SPKn_FMT field in the datasheet for a
description of this value.
The second cell is ignored for codecs that do not have OUT6.
- cirrus,pdm-mute : PDM mute format, must contain 2 cells
(OUT5 and OUT6). See the PDM_SPKn_CTRL_1 register in the datasheet for a
description of this value.
The second cell is ignored for codecs that do not have OUT6.
Example:
cs47l35@0 {
compatible = "cirrus,cs47l35";
cirrus,dmic-ref = <0 0 CS47L35_DMIC_REF_MICBIAS1B 0>;
cirrus,inmode = <
MADERA_INMODE_DMIC MADERA_INMODE_DMIC /* IN1A digital */
MADERA_INMODE_SE MADERA_INMODE_SE /* IN1B single-ended */
MADERA_INMODE_DIFF MADERA_INMODE_DIFF /* IN2 differential */
0 0 /* not used on this codec */
>;
cirrus,out-mono = <0 0 0 0 0 0>;
cirrus,max-channels-clocked = <2 0 0>;
};

View file

@ -9,6 +9,10 @@ Optional properties:
- sdmode-gpios : GPIO specifier for the chip's SD_MODE pin.
If this option is not specified then driver does not manage
the pin state (e.g. chip is always on).
- sdmode-delay : specify delay time for SD_MODE pin.
If this option is specified, which means it's required i2s clocks
ready before SD_MODE is unmuted in order to avoid the speaker pop noise.
It's observed that 5ms is sufficient.
Example:

View file

@ -0,0 +1,32 @@
RT1011 Mono Class D Audio Amplifier
This device supports I2C only.
Required properties:
- compatible : "realtek,rt1011".
- reg : The I2C address of the device. This I2C address decide by
two input pins (ASEL1 and ASEL2).
-------------------------------------
| ASEL2 | ASEL1 | Address |
-------------------------------------
| 0 | 0 | 0x38 |
-------------------------------------
| 0 | 1 | 0x39 |
-------------------------------------
| 1 | 0 | 0x3a |
-------------------------------------
| 1 | 1 | 0x3b |
-------------------------------------
Pins on the device (for linking into audio routes) for RT1011:
* SPO
Example:
rt1011: codec@38 {
compatible = "realtek,rt1011";
reg = <0x38>;
};

View file

@ -0,0 +1,17 @@
RT1308 audio Amplifier
This device supports I2C only.
Required properties:
- compatible : "realtek,rt1308".
- reg : The I2C address of the device.
Example:
rt1308: rt1308@10 {
compatible = "realtek,rt1308";
reg = <0x10>;
};

View file

@ -18,7 +18,7 @@ Required properties:
See Documentation/devicetree/bindings/dma/stm32-dma.txt.
- dma-names: Identifier for each DMA request line. Must be "tx" and "rx".
- pinctrl-names: should contain only value "default"
- pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt
- pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
Optional properties:
- resets: Reference to a reset controller asserting the reset controller

View file

@ -41,7 +41,7 @@ SAI subnodes required properties:
"tx": if sai sub-block is configured as playback DAI
"rx": if sai sub-block is configured as capture DAI
- pinctrl-names: should contain only value "default"
- pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt
- pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
SAI subnodes Optional properties:
- st,sync: specify synchronization mode.

View file

@ -1,45 +0,0 @@
* Allwinner A10 I2S controller
The I2S bus (Inter-IC sound bus) is a serial link for digital
audio data transfer between devices in the system.
Required properties:
- compatible: should be one of the following:
- "allwinner,sun4i-a10-i2s"
- "allwinner,sun6i-a31-i2s"
- "allwinner,sun8i-a83t-i2s"
- "allwinner,sun8i-h3-i2s"
- "allwinner,sun50i-a64-codec-i2s"
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: should contain the I2S interrupt.
- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
Documentation/devicetree/bindings/dma/dma.txt
- dma-names: should include "tx" and "rx".
- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
- clock-names: should contain the following:
- "apb" : clock for the I2S bus interface
- "mod" : module clock for the I2S controller
- #sound-dai-cells : Must be equal to 0
Required properties for the following compatibles:
- "allwinner,sun6i-a31-i2s"
- "allwinner,sun8i-a83t-i2s"
- "allwinner,sun8i-h3-i2s"
- "allwinner,sun50i-a64-codec-i2s"
- resets: phandle to the reset line for this codec
Example:
i2s0: i2s@1c22400 {
#sound-dai-cells = <0>;
compatible = "allwinner,sun4i-a10-i2s";
reg = <0x01c22400 0x400>;
interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&apb0_gates 3>, <&i2s0_clk>;
clock-names = "apb", "mod";
dmas = <&dma SUN4I_DMA_NORMAL 3>,
<&dma SUN4I_DMA_NORMAL 3>;
dma-names = "rx", "tx";
};

View file

@ -1,42 +0,0 @@
Allwinner Sony/Philips Digital Interface Format (S/PDIF) Controller
The Allwinner S/PDIF audio block is a transceiver that allows the
processor to receive and transmit digital audio via an coaxial cable or
a fibre cable.
For now only playback is supported.
Required properties:
- compatible : should be one of the following:
- "allwinner,sun4i-a10-spdif": for the Allwinner A10 SoC
- "allwinner,sun6i-a31-spdif": for the Allwinner A31 SoC
- "allwinner,sun8i-h3-spdif": for the Allwinner H3 SoC
- reg : Offset and length of the register set for the device.
- interrupts : Contains the spdif interrupt.
- dmas : Generic dma devicetree binding as described in
Documentation/devicetree/bindings/dma/dma.txt.
- dma-names : Two dmas have to be defined, "tx" and "rx".
- clocks : Contains an entry for each entry in clock-names.
- clock-names : Includes the following entries:
"apb" clock for the spdif bus.
"spdif" clock for spdif controller.
- resets : reset specifier for the ahb reset (A31 and newer only)
Example:
spdif: spdif@1c21000 {
compatible = "allwinner,sun4i-a10-spdif";
reg = <0x01c21000 0x40>;
interrupts = <13>;
clocks = <&apb0_gates 1>, <&spdif_clk>;
clock-names = "apb", "spdif";
dmas = <&dma 0 2>, <&dma 0 2>;
dma-names = "rx", "tx";
};

View file

@ -1290,7 +1290,7 @@ ARM PRIMECELL SSP PL022 SPI DRIVER
M: Linus Walleij <linus.walleij@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/spi/spi_pl022.txt
F: Documentation/devicetree/bindings/spi/spi-pl022.yaml
F: drivers/spi/spi-pl022.c
ARM PRIMECELL UART PL010 AND PL011 DRIVERS
@ -3929,13 +3929,18 @@ W: https://github.com/CirrusLogic/linux-drivers/wiki
S: Supported
F: Documentation/devicetree/bindings/mfd/madera.txt
F: Documentation/devicetree/bindings/pinctrl/cirrus,madera-pinctrl.txt
F: Documentation/devicetree/bindings/sound/madera.txt
F: include/dt-bindings/sound/madera*
F: include/linux/irqchip/irq-madera*
F: include/linux/mfd/madera/*
F: include/sound/madera*
F: drivers/gpio/gpio-madera*
F: drivers/irqchip/irq-madera*
F: drivers/mfd/madera*
F: drivers/mfd/cs47l*
F: drivers/pinctrl/cirrus/*
F: sound/soc/codecs/cs47l*
F: sound/soc/codecs/madera*
CLANG-FORMAT FILE
M: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>

View file

@ -58,6 +58,9 @@
struct vc4_hdmi_audio {
struct snd_soc_card card;
struct snd_soc_dai_link link;
struct snd_soc_dai_link_component cpu;
struct snd_soc_dai_link_component codec;
struct snd_soc_dai_link_component platform;
int samplerate;
int channels;
struct snd_dmaengine_dai_dma_data dma_data;
@ -1085,12 +1088,20 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
return ret;
}
dai_link->cpus = &hdmi->audio.cpu;
dai_link->codecs = &hdmi->audio.codec;
dai_link->platforms = &hdmi->audio.platform;
dai_link->num_cpus = 1;
dai_link->num_codecs = 1;
dai_link->num_platforms = 1;
dai_link->name = "MAI";
dai_link->stream_name = "MAI PCM";
dai_link->codec_dai_name = vc4_hdmi_audio_codec_dai_drv.name;
dai_link->cpu_dai_name = dev_name(dev);
dai_link->codec_name = dev_name(dev);
dai_link->platform_name = dev_name(dev);
dai_link->codecs->dai_name = vc4_hdmi_audio_codec_dai_drv.name;
dai_link->cpus->dai_name = dev_name(dev);
dai_link->codecs->name = dev_name(dev);
dai_link->platforms->name = dev_name(dev);
card->dai_link = dai_link;
card->num_links = 1;

View file

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Device Tree defines for Madera codecs
*
* Copyright (C) 2016-2017 Cirrus Logic, Inc. and
* Cirrus Logic International Semiconductor Ltd.
*/
#ifndef DT_BINDINGS_SOUND_MADERA_H
#define DT_BINDINGS_SOUND_MADERA_H
#define MADERA_INMODE_DIFF 0
#define MADERA_INMODE_SE 1
#define MADERA_INMODE_DMIC 2
#define MADERA_DMIC_REF_MICVDD 0
#define MADERA_DMIC_REF_MICBIAS1 1
#define MADERA_DMIC_REF_MICBIAS2 2
#define MADERA_DMIC_REF_MICBIAS3 3
#define CS47L35_DMIC_REF_MICBIAS1B 1
#define CS47L35_DMIC_REF_MICBIAS2A 2
#define CS47L35_DMIC_REF_MICBIAS2B 3
#endif

View file

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __DT_MESON_G12A_TOHDMITX_H
#define __DT_MESON_G12A_TOHDMITX_H
#define TOHDMITX_I2S_IN_A 0
#define TOHDMITX_I2S_IN_B 1
#define TOHDMITX_I2S_IN_C 2
#define TOHDMITX_I2S_OUT 3
#define TOHDMITX_SPDIF_IN_A 4
#define TOHDMITX_SPDIF_IN_B 5
#define TOHDMITX_SPDIF_OUT 6
#endif /* __DT_MESON_G12A_TOHDMITX_H */

View file

@ -16,6 +16,7 @@
#include <linux/regulator/arizona-ldo1.h>
#include <linux/regulator/arizona-micsupp.h>
#include <linux/regulator/machine.h>
#include <sound/madera-pdata.h>
#define MADERA_MAX_MICBIAS 4
#define MADERA_MAX_CHILD_MICBIAS 4
@ -39,6 +40,7 @@ struct madera_codec_pdata;
* @gpsw: General purpose switch mode setting. Depends on the external
* hardware connected to the switch. (See the SW1_MODE field
* in the datasheet for the available values for your codec)
* @codec: Substruct of pdata for the ASoC codec driver
*/
struct madera_pdata {
struct gpio_desc *reset;
@ -53,6 +55,8 @@ struct madera_pdata {
int n_gpio_configs;
u32 gpsw[MADERA_MAX_GPSW];
struct madera_codec_pdata codec;
};
#endif

View file

@ -18,6 +18,9 @@
#include <sound/hda_verbs.h>
#include <sound/hda_regmap.h>
#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348)
/*
* Structures
*/

View file

@ -0,0 +1,59 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Platform data for Madera codec driver
*
* Copyright (C) 2016-2019 Cirrus Logic, Inc. and
* Cirrus Logic International Semiconductor Ltd.
*/
#ifndef MADERA_CODEC_PDATA_H
#define MADERA_CODEC_PDATA_H
#include <linux/kernel.h>
#define MADERA_MAX_INPUT 6
#define MADERA_MAX_MUXED_CHANNELS 4
#define MADERA_MAX_OUTPUT 6
#define MADERA_MAX_AIF 4
#define MADERA_MAX_PDM_SPK 2
#define MADERA_MAX_DSP 7
/**
* struct madera_codec_pdata
*
* @max_channels_clocked: Maximum number of channels that I2S clocks will be
* generated for. Useful when clock master for systems
* where the I2S bus has multiple data lines.
* @dmic_ref: Indicates how the MICBIAS pins have been externally
* connected to DMICs on each input. A value of 0
* indicates MICVDD and is the default. Other values are:
* For CS47L35 one of the CS47L35_DMIC_REF_xxx values
* For all other codecs one of the MADERA_DMIC_REF_xxx
* Also see the datasheet for a description of the
* INn_DMIC_SUP field.
* @inmode: Mode for the ADC inputs. One of the MADERA_INMODE_xxx
* values. Two-dimensional array
* [input_number][channel number], with four slots per
* input in the order
* [n][0]=INnAL [n][1]=INnAR [n][2]=INnBL [n][3]=INnBR
* @out_mono: For each output set the value to TRUE to indicate that
* the output is mono. [0]=OUT1, [1]=OUT2, ...
* @pdm_fmt: PDM speaker data format. See the PDM_SPKn_FMT field in
* the datasheet for a description of this value.
* @pdm_mute: PDM mute format. See the PDM_SPKn_CTRL_1 register
* in the datasheet for a description of this value.
*/
struct madera_codec_pdata {
u32 max_channels_clocked[MADERA_MAX_AIF];
u32 dmic_ref[MADERA_MAX_INPUT];
u32 inmode[MADERA_MAX_INPUT][MADERA_MAX_MUXED_CHANNELS];
bool out_mono[MADERA_MAX_OUTPUT];
u32 pdm_fmt[MADERA_MAX_PDM_SPK];
u32 pdm_mute[MADERA_MAX_PDM_SPK];
};
#endif

View file

@ -42,6 +42,7 @@ struct asoc_simple_priv {
struct simple_dai_props {
struct asoc_simple_dai *cpu_dai;
struct asoc_simple_dai *codec_dai;
struct snd_soc_dai_link_component cpus; /* single cpu */
struct snd_soc_dai_link_component codecs; /* single codec */
struct snd_soc_dai_link_component platforms;
struct asoc_simple_data adata;
@ -80,16 +81,12 @@ int asoc_simple_parse_card_name(struct snd_soc_card *card,
char *prefix);
#define asoc_simple_parse_clk_cpu(dev, node, dai_link, simple_dai) \
asoc_simple_parse_clk(dev, node, dai_link->cpu_of_node, simple_dai, \
dai_link->cpu_dai_name, NULL)
asoc_simple_parse_clk(dev, node, simple_dai, dai_link->cpus)
#define asoc_simple_parse_clk_codec(dev, node, dai_link, simple_dai) \
asoc_simple_parse_clk(dev, node, dai_link->codec_of_node, simple_dai,\
dai_link->codec_dai_name, dai_link->codecs)
asoc_simple_parse_clk(dev, node, simple_dai, dai_link->codecs)
int asoc_simple_parse_clk(struct device *dev,
struct device_node *node,
struct device_node *dai_of_node,
struct asoc_simple_dai *simple_dai,
const char *dai_name,
struct snd_soc_dai_link_component *dlc);
int asoc_simple_startup(struct snd_pcm_substream *substream);
void asoc_simple_shutdown(struct snd_pcm_substream *substream);
@ -100,16 +97,11 @@ int asoc_simple_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
#define asoc_simple_parse_cpu(node, dai_link, is_single_link) \
asoc_simple_parse_dai(node, NULL, \
&dai_link->cpu_of_node, \
&dai_link->cpu_dai_name, is_single_link)
asoc_simple_parse_dai(node, dai_link->cpus, is_single_link)
#define asoc_simple_parse_codec(node, dai_link) \
asoc_simple_parse_dai(node, dai_link->codecs, \
&dai_link->codec_of_node, \
&dai_link->codec_dai_name, NULL)
asoc_simple_parse_dai(node, dai_link->codecs, NULL)
#define asoc_simple_parse_platform(node, dai_link) \
asoc_simple_parse_dai(node, dai_link->platforms, \
&dai_link->platform_of_node, NULL, NULL)
asoc_simple_parse_dai(node, dai_link->platforms, NULL)
#define asoc_simple_parse_tdm(np, dai) \
snd_soc_of_parse_tdm_slot(np, &(dai)->tx_slot_mask, \

View file

@ -900,17 +900,6 @@ struct snd_soc_dai_link {
const char *name; /* Codec name */
const char *stream_name; /* Stream name */
/*
* cpu_name
* cpu_of_node
* cpu_dai_name
*
* These are legacy style, and will be replaced to
* modern style (= snd_soc_dai_link_component) in the future,
* but, not yet supported so far.
* If modern style was supported for CPU, all driver will switch
* to use it, and, legacy style code will be removed from ALSA SoC.
*/
/*
* You MAY specify the link's CPU-side device, either by device name,
* or by DT/OF node, but not both. If this information is omitted,
@ -918,57 +907,27 @@ struct snd_soc_dai_link {
* must be globally unique. These fields are currently typically used
* only for codec to codec links, or systems using device tree.
*/
const char *cpu_name;
struct device_node *cpu_of_node;
/*
* You MAY specify the DAI name of the CPU DAI. If this information is
* omitted, the CPU-side DAI is matched using .cpu_name/.cpu_of_node
* only, which only works well when that device exposes a single DAI.
*/
const char *cpu_dai_name;
struct snd_soc_dai_link_component *cpus;
unsigned int num_cpus;
/*
* codec_name
* codec_of_node
* codec_dai_name
*
* These are legacy style, it will be converted to modern style
* (= snd_soc_dai_link_component) automatically in soc-core
* if driver is using legacy style.
* Driver shouldn't use both legacy and modern style in the same time.
* If modern style was supported for CPU, all driver will switch
* to use it, and, legacy style code will be removed from ALSA SoC.
*/
/*
* You MUST specify the link's codec, either by device name, or by
* DT/OF node, but not both.
*/
const char *codec_name;
struct device_node *codec_of_node;
/* You MUST specify the DAI name within the codec */
const char *codec_dai_name;
struct snd_soc_dai_link_component *codecs;
unsigned int num_codecs;
/*
* platform_name
* platform_of_node
*
* These are legacy style, it will be converted to modern style
* (= snd_soc_dai_link_component) automatically in soc-core
* if driver is using legacy style.
* Driver shouldn't use both legacy and modern style in the same time.
* If modern style was supported for CPU, all driver will switch
* to use it, and, legacy style code will be removed from ALSA SoC.
*/
/*
* You MAY specify the link's platform/PCM/DMA driver, either by
* device name, or by DT/OF node, but not both. Some forms of link
* do not need a platform.
* do not need a platform. In such case, platforms are not mandatory.
*/
const char *platform_name;
struct device_node *platform_of_node;
struct snd_soc_dai_link_component *platforms;
unsigned int num_platforms;
@ -1030,12 +989,6 @@ struct snd_soc_dai_link {
/* Do not create a PCM for this DAI link (Backend link) */
unsigned int ignore:1;
/*
* This driver uses legacy platform naming. Set by the core, machine
* drivers should not modify this value.
*/
unsigned int legacy_platform:1;
struct list_head list; /* DAI link list of the soc card */
struct snd_soc_dobj dobj; /* For topology */
};
@ -1044,6 +997,100 @@ struct snd_soc_dai_link {
((i) < link->num_codecs) && ((codec) = &link->codecs[i]); \
(i)++)
#define for_each_link_platforms(link, i, platform) \
for ((i) = 0; \
((i) < link->num_platforms) && \
((platform) = &link->platforms[i]); \
(i)++)
/*
* Sample 1 : Single CPU/Codec/Platform
*
* SND_SOC_DAILINK_DEFS(test,
* DAILINK_COMP_ARRAY(COMP_CPU("cpu_dai")),
* DAILINK_COMP_ARRAY(COMP_CODEC("codec", "codec_dai")),
* DAILINK_COMP_ARRAY(COMP_PLATFORM("platform")));
*
* struct snd_soc_dai_link link = {
* ...
* SND_SOC_DAILINK_REG(test),
* };
*
* Sample 2 : Multi CPU/Codec, no Platform
*
* SND_SOC_DAILINK_DEFS(test,
* DAILINK_COMP_ARRAY(COMP_CPU("cpu_dai1"),
* COMP_CPU("cpu_dai2")),
* DAILINK_COMP_ARRAY(COMP_CODEC("codec1", "codec_dai1"),
* COMP_CODEC("codec2", "codec_dai2")));
*
* struct snd_soc_dai_link link = {
* ...
* SND_SOC_DAILINK_REG(test),
* };
*
* Sample 3 : Define each CPU/Codec/Platform manually
*
* SND_SOC_DAILINK_DEF(test_cpu,
* DAILINK_COMP_ARRAY(COMP_CPU("cpu_dai1"),
* COMP_CPU("cpu_dai2")));
* SND_SOC_DAILINK_DEF(test_codec,
* DAILINK_COMP_ARRAY(COMP_CODEC("codec1", "codec_dai1"),
* COMP_CODEC("codec2", "codec_dai2")));
* SND_SOC_DAILINK_DEF(test_platform,
* DAILINK_COMP_ARRAY(COMP_PLATFORM("platform")));
*
* struct snd_soc_dai_link link = {
* ...
* SND_SOC_DAILINK_REG(test_cpu,
* test_codec,
* test_platform),
* };
*
* Sample 4 : Sample3 without platform
*
* struct snd_soc_dai_link link = {
* ...
* SND_SOC_DAILINK_REG(test_cpu,
* test_codec);
* };
*/
#define SND_SOC_DAILINK_REG1(name) SND_SOC_DAILINK_REG3(name##_cpus, name##_codecs, name##_platforms)
#define SND_SOC_DAILINK_REG2(cpu, codec) SND_SOC_DAILINK_REG3(cpu, codec, null_dailink_component)
#define SND_SOC_DAILINK_REG3(cpu, codec, platform) \
.cpus = cpu, \
.num_cpus = ARRAY_SIZE(cpu), \
.codecs = codec, \
.num_codecs = ARRAY_SIZE(codec), \
.platforms = platform, \
.num_platforms = ARRAY_SIZE(platform)
#define SND_SOC_DAILINK_REGx(_1, _2, _3, func, ...) func
#define SND_SOC_DAILINK_REG(...) \
SND_SOC_DAILINK_REGx(__VA_ARGS__, \
SND_SOC_DAILINK_REG3, \
SND_SOC_DAILINK_REG2, \
SND_SOC_DAILINK_REG1)(__VA_ARGS__)
#define SND_SOC_DAILINK_DEF(name, def...) \
static struct snd_soc_dai_link_component name[] = { def }
#define SND_SOC_DAILINK_DEFS(name, cpu, codec, platform...) \
SND_SOC_DAILINK_DEF(name##_cpus, cpu); \
SND_SOC_DAILINK_DEF(name##_codecs, codec); \
SND_SOC_DAILINK_DEF(name##_platforms, platform)
#define DAILINK_COMP_ARRAY(param...) param
#define COMP_EMPTY() { }
#define COMP_CPU(_dai) { .dai_name = _dai, }
#define COMP_CODEC(_name, _dai) { .name = _name, .dai_name = _dai, }
#define COMP_PLATFORM(_name) { .name = _name }
#define COMP_DUMMY() { .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", }
extern struct snd_soc_dai_link_component null_dailink_component[0];
struct snd_soc_codec_conf {
/*
* specify device either by device name, or by
@ -1189,7 +1236,7 @@ struct snd_soc_card {
(i)++)
#define for_each_card_links(card, link) \
list_for_each_entry(dai_link, &(card)->dai_link_list, list)
list_for_each_entry(link, &(card)->dai_link_list, list)
#define for_each_card_links_safe(card, link, _link) \
list_for_each_entry_safe(link, _link, &(card)->dai_link_list, list)
@ -1214,7 +1261,6 @@ struct snd_soc_pcm_runtime {
/* Dynamic PCM BE runtime data */
struct snd_soc_dpcm_runtime dpcm[2];
int fe_compr;
long pmdown_time;
@ -1239,6 +1285,7 @@ struct snd_soc_pcm_runtime {
/* bit field */
unsigned int dev_registered:1;
unsigned int pop_wait:1;
unsigned int fe_compr:1; /* for Dynamic PCM */
};
#define for_each_rtd_codec_dai(rtd, i, dai)\
for ((i) = 0; \
@ -1607,15 +1654,11 @@ int snd_soc_fixup_dai_links_platform_name(struct snd_soc_card *card,
if (!name)
return -ENOMEM;
if (dai_link->platforms)
/* only single platform is supported for now */
dai_link->platforms->name = name;
else
/*
* legacy mode, this case will be removed when all
* derivers are switched to modern style dai_link.
*/
dai_link->platform_name = name;
if (!dai_link->platforms)
return -EINVAL;
/* only single platform is supported for now */
dai_link->platforms->name = name;
}
return 0;

View file

@ -167,9 +167,10 @@ struct sof_ipc_dai_dmic_params {
uint32_t wake_up_time; /**< Time from clock start to data (us) */
uint32_t min_clock_on_time; /**< Min. time that clk is kept on (us) */
uint32_t unmute_ramp_time; /**< Length of logarithmic gain ramp (ms) */
/* reserved for future use */
uint32_t reserved[6];
uint32_t reserved[5];
/**< variable number of pdm controller config */
struct sof_ipc_dai_dmic_pdm_ctrl pdm[0];

View file

@ -49,6 +49,7 @@
#define SOF_IPC_GLB_DAI_MSG SOF_GLB_TYPE(0x8U)
#define SOF_IPC_GLB_TRACE_MSG SOF_GLB_TYPE(0x9U)
#define SOF_IPC_GLB_GDB_DEBUG SOF_GLB_TYPE(0xAU)
#define SOF_IPC_GLB_TEST_MSG SOF_GLB_TYPE(0xBU)
/*
* DSP Command Message Types
@ -99,9 +100,13 @@
#define SOF_IPC_STREAM_VORBIS_PARAMS SOF_CMD_TYPE(0x010)
#define SOF_IPC_STREAM_VORBIS_FREE SOF_CMD_TYPE(0x011)
/* trace and debug */
/* trace */
#define SOF_IPC_TRACE_DMA_PARAMS SOF_CMD_TYPE(0x001)
#define SOF_IPC_TRACE_DMA_POSITION SOF_CMD_TYPE(0x002)
#define SOF_IPC_TRACE_DMA_PARAMS_EXT SOF_CMD_TYPE(0x003)
/* debug */
#define SOF_IPC_TEST_IPC_FLOOD SOF_CMD_TYPE(0x001)
/* Get message component id */
#define SOF_IPC_MESSAGE_ID(x) ((x) & 0xffff)

View file

@ -35,6 +35,7 @@ enum sof_comp_type {
SOF_COMP_KEYWORD_DETECT,
SOF_COMP_KPB, /* A key phrase buffer component */
SOF_COMP_SELECTOR, /**< channel selector component */
SOF_COMP_DEMUX,
/* keep FILEREAD/FILEWRITE as the last ones */
SOF_COMP_FILEREAD = 10000, /**< host test based file IO */
SOF_COMP_FILEWRITE = 10001, /**< host test based file IO */
@ -83,9 +84,9 @@ struct sof_ipc_buffer {
struct sof_ipc_comp_config {
struct sof_ipc_cmd_hdr hdr;
uint32_t periods_sink; /**< 0 means variable */
uint32_t periods_source; /**< 0 means variable */
uint32_t periods_source;/**< 0 means variable */
uint32_t reserved1; /**< reserved */
uint32_t frame_fmt; /**< SOF_IPC_FRAME_ */
uint32_t frame_fmt; /**< SOF_IPC_FRAME_ */
uint32_t xrun_action;
/* reserved for future use */
@ -175,6 +176,8 @@ enum sof_ipc_process_type {
SOF_PROCESS_KEYWORD_DETECT, /**< Keyword Detection */
SOF_PROCESS_KPB, /**< KeyPhrase Buffer Manager */
SOF_PROCESS_CHAN_SELECTOR, /**< Channel Selector */
SOF_PROCESS_MUX,
SOF_PROCESS_DEMUX,
};
/* generic "effect", "codec" or proprietary processing component */

View file

@ -19,12 +19,22 @@
#define SOF_TRACE_FILENAME_SIZE 32
/* DMA for Trace params info - SOF_IPC_DEBUG_DMA_PARAMS */
/* Deprecated - use sof_ipc_dma_trace_params_ext */
struct sof_ipc_dma_trace_params {
struct sof_ipc_cmd_hdr hdr;
struct sof_ipc_host_buffer buffer;
uint32_t stream_tag;
} __packed;
/* DMA for Trace params info - SOF_IPC_DEBUG_DMA_PARAMS_EXT */
struct sof_ipc_dma_trace_params_ext {
struct sof_ipc_cmd_hdr hdr;
struct sof_ipc_host_buffer buffer;
uint32_t stream_tag;
uint64_t timestamp_ns; /* in nanosecond */
uint32_t reserved[8];
} __packed;
/* DMA for Trace params info - SOF_IPC_DEBUG_DMA_PARAMS */
struct sof_ipc_dma_trace_posn {
struct sof_ipc_reply rhdr;
@ -56,7 +66,9 @@ struct sof_ipc_dma_trace_posn {
#define SOF_IPC_PANIC_WFI (SOF_IPC_PANIC_MAGIC | 0xa)
#define SOF_IPC_PANIC_ASSERT (SOF_IPC_PANIC_MAGIC | 0xb)
/* panic info include filename and line number */
/* panic info include filename and line number
* filename array will not include null terminator if fully filled
*/
struct sof_ipc_panic_info {
struct sof_ipc_hdr hdr;
uint32_t code; /* SOF_IPC_PANIC_ */

View file

@ -26,7 +26,7 @@
/* SOF ABI version major, minor and patch numbers */
#define SOF_ABI_MAJOR 3
#define SOF_ABI_MINOR 6
#define SOF_ABI_MINOR 8
#define SOF_ABI_PATCH 0
/* SOF ABI version number. Format within 32bit word is MMmmmppp */

View file

@ -1,172 +0,0 @@
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_EQ_H__
#define __INCLUDE_UAPI_SOUND_SOF_USER_EQ_H__
/* FIR EQ type */
#define SOF_EQ_FIR_IDX_SWITCH 0
#define SOF_EQ_FIR_MAX_SIZE 4096 /* Max size allowed for coef data in bytes */
#define SOF_EQ_FIR_MAX_LENGTH 192 /* Max length for individual filter */
#define SOF_EQ_FIR_MAX_RESPONSES 8 /* A blob can define max 8 FIR EQs */
/*
* eq_fir_configuration data structure contains this information
* uint32_t size
* This is the number of bytes need to store the received EQ
* configuration.
* uint16_t channels_in_config
* This describes the number of channels in this EQ config data. It
* can be different from PLATFORM_MAX_CHANNELS.
* uint16_t number_of_responses
* 0=no responses, 1=one response defined, 2=two responses defined, etc.
* int16_t data[]
* assign_response[channels_in_config]
* 0 = use first response, 1 = use 2nd response, etc.
* E.g. {0, 0, 0, 0, 1, 1, 1, 1} would apply to channels 0-3 the
* same first defined response and for to channels 4-7 the second.
* coef_data[]
* Repeated data
* { filter_length, output_shift, h[] }
* for every EQ response defined where vector h has filter_length
* number of coefficients. Coefficients in h[] are in Q1.15 format.
* E.g. 16384 (Q1.15) = 0.5. The shifts are number of right shifts.
*
* NOTE: The channels_in_config must be even to have coef_data aligned to
* 32 bit word in RAM. Therefore a mono EQ assign must be duplicated to 2ch
* even if it would never used. Similarly a 5ch EQ assign must be increased
* to 6ch. EQ init will return an error if this is not met.
*
* NOTE: The filter_length must be multiple of four. Therefore the filter must
* be padded from the end with zeros have this condition met.
*/
struct sof_eq_fir_config {
uint32_t size;
uint16_t channels_in_config;
uint16_t number_of_responses;
/* reserved */
uint32_t reserved[4];
int16_t data[];
} __packed;
struct sof_eq_fir_coef_data {
int16_t length; /* Number of FIR taps */
int16_t out_shift; /* Amount of right shifts at output */
/* reserved */
uint32_t reserved[4];
int16_t coef[]; /* FIR coefficients */
} __packed;
/* In the struct above there's two 16 bit words (length, shift) and four
* reserved 32 bit words before the actual FIR coefficients. This information
* is used in parsing of the configuration blob.
*/
#define SOF_EQ_FIR_COEF_NHEADER \
(sizeof(struct sof_eq_fir_coef_data) / sizeof(int16_t))
/* IIR EQ type */
#define SOF_EQ_IIR_IDX_SWITCH 0
#define SOF_EQ_IIR_MAX_SIZE 1024 /* Max size allowed for coef data in bytes */
#define SOF_EQ_IIR_MAX_RESPONSES 8 /* A blob can define max 8 IIR EQs */
/* eq_iir_configuration
* uint32_t channels_in_config
* This describes the number of channels in this EQ config data. It
* can be different from PLATFORM_MAX_CHANNELS.
* uint32_t number_of_responses_defined
* 0=no responses, 1=one response defined, 2=two responses defined, etc.
* int32_t data[]
* Data consist of two parts. First is the response assign vector that
* has length of channels_in_config. The latter part is coefficient
* data.
* uint32_t assign_response[channels_in_config]
* -1 = not defined, 0 = use first response, 1 = use 2nd, etc.
* E.g. {0, 0, 0, 0, -1, -1, -1, -1} would apply to channels 0-3 the
* same first defined response and leave channels 4-7 unequalized.
* coefficient_data[]
* <1st EQ>
* uint32_t num_biquads
* uint32_t num_biquads_in_series
* <1st biquad>
* int32_t coef_a2 Q2.30 format
* int32_t coef_a1 Q2.30 format
* int32_t coef_b2 Q2.30 format
* int32_t coef_b1 Q2.30 format
* int32_t coef_b0 Q2.30 format
* int32_t output_shift number of shifts right, shift left is negative
* int32_t output_gain Q2.14 format
* <2nd biquad>
* ...
* <2nd EQ>
*
* Note: A flat response biquad can be made with a section set to
* b0 = 1.0, gain = 1.0, and other parameters set to 0
* {0, 0, 0, 0, 1073741824, 0, 16484}
*/
struct sof_eq_iir_config {
uint32_t size;
uint32_t channels_in_config;
uint32_t number_of_responses;
/* reserved */
uint32_t reserved[4];
int32_t data[]; /* eq_assign[channels], eq 0, eq 1, ... */
} __packed;
struct sof_eq_iir_header_df2t {
uint32_t num_sections;
uint32_t num_sections_in_series;
/* reserved */
uint32_t reserved[4];
int32_t biquads[]; /* Repeated biquad coefficients */
} __packed;
struct sof_eq_iir_biquad_df2t {
int32_t a2; /* Q2.30 */
int32_t a1; /* Q2.30 */
int32_t b2; /* Q2.30 */
int32_t b1; /* Q2.30 */
int32_t b0; /* Q2.30 */
int32_t output_shift; /* Number of right shifts */
int32_t output_gain; /* Q2.14 */
} __packed;
/* A full 22th order equalizer with 11 biquads cover octave bands 1-11 in
* in the 0 - 20 kHz bandwidth.
*/
#define SOF_EQ_IIR_DF2T_BIQUADS_MAX 11
/* The number of int32_t words in sof_eq_iir_header_df2t:
* num_sections, num_sections_in_series, reserved[4]
*/
#define SOF_EQ_IIR_NHEADER_DF2T \
(sizeof(struct sof_eq_iir_header_df2t) / sizeof(int32_t))
/* The number of int32_t words in sof_eq_iir_biquad_df2t:
* a2, a1, b2, b1, b0, output_shift, output_gain
*/
#define SOF_EQ_IIR_NBIQUAD_DF2T \
(sizeof(struct sof_eq_iir_biquad_df2t) / sizeof(int32_t))
#endif

View file

@ -1,188 +0,0 @@
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_MANIFEST_H__
#define __INCLUDE_UAPI_SOUND_SOF_USER_MANIFEST_H__
/* start offset for base FW module */
#define SOF_MAN_ELF_TEXT_OFFSET 0x2000
/* FW Extended Manifest Header id = $AE1 */
#define SOF_MAN_EXT_HEADER_MAGIC 0x31454124
/* module type load type */
#define SOF_MAN_MOD_TYPE_BUILTIN 0
#define SOF_MAN_MOD_TYPE_MODULE 1
struct sof_man_module_type {
uint32_t load_type:4; /* SOF_MAN_MOD_TYPE_ */
uint32_t auto_start:1;
uint32_t domain_ll:1;
uint32_t domain_dp:1;
uint32_t rsvd_:25;
};
/* segment flags.type */
#define SOF_MAN_SEGMENT_TEXT 0
#define SOF_MAN_SEGMENT_RODATA 1
#define SOF_MAN_SEGMENT_DATA 1
#define SOF_MAN_SEGMENT_BSS 2
#define SOF_MAN_SEGMENT_EMPTY 15
union sof_man_segment_flags {
uint32_t ul;
struct {
uint32_t contents:1;
uint32_t alloc:1;
uint32_t load:1;
uint32_t readonly:1;
uint32_t code:1;
uint32_t data:1;
uint32_t _rsvd0:2;
uint32_t type:4; /* MAN_SEGMENT_ */
uint32_t _rsvd1:4;
uint32_t length:16; /* of segment in pages */
} r;
} __packed;
/*
* Module segment descriptor. Used by ROM - Immutable.
*/
struct sof_man_segment_desc {
union sof_man_segment_flags flags;
uint32_t v_base_addr;
uint32_t file_offset;
} __packed;
/*
* The firmware binary can be split into several modules.
*/
#define SOF_MAN_MOD_ID_LEN 4
#define SOF_MAN_MOD_NAME_LEN 8
#define SOF_MAN_MOD_SHA256_LEN 32
#define SOF_MAN_MOD_ID {'$', 'A', 'M', 'E'}
/*
* Each module has an entry in the FW header. Used by ROM - Immutable.
*/
struct sof_man_module {
uint8_t struct_id[SOF_MAN_MOD_ID_LEN]; /* SOF_MAN_MOD_ID */
uint8_t name[SOF_MAN_MOD_NAME_LEN];
uint8_t uuid[16];
struct sof_man_module_type type;
uint8_t hash[SOF_MAN_MOD_SHA256_LEN];
uint32_t entry_point;
uint16_t cfg_offset;
uint16_t cfg_count;
uint32_t affinity_mask;
uint16_t instance_max_count; /* max number of instances */
uint16_t instance_bss_size; /* instance (pages) */
struct sof_man_segment_desc segment[3];
} __packed;
/*
* Each module has a configuration in the FW header. Used by ROM - Immutable.
*/
struct sof_man_mod_config {
uint32_t par[4]; /* module parameters */
uint32_t is_pages; /* actual size of instance .bss (pages) */
uint32_t cps; /* cycles per second */
uint32_t ibs; /* input buffer size (bytes) */
uint32_t obs; /* output buffer size (bytes) */
uint32_t module_flags; /* flags, reserved for future use */
uint32_t cpc; /* cycles per single run */
uint32_t obls; /* output block size, reserved for future use */
} __packed;
/*
* FW Manifest Header
*/
#define SOF_MAN_FW_HDR_FW_NAME_LEN 8
#define SOF_MAN_FW_HDR_ID {'$', 'A', 'M', '1'}
#define SOF_MAN_FW_HDR_NAME "ADSPFW"
#define SOF_MAN_FW_HDR_FLAGS 0x0
#define SOF_MAN_FW_HDR_FEATURES 0xff
/*
* The firmware has a standard header that is checked by the ROM on firmware
* loading. preload_page_count is used by DMA code loader and is entire
* image size on CNL. i.e. CNL: total size of the binarys .text and .rodata
* Used by ROM - Immutable.
*/
struct sof_man_fw_header {
uint8_t header_id[4];
uint32_t header_len;
uint8_t name[SOF_MAN_FW_HDR_FW_NAME_LEN];
/* number of pages of preloaded image loaded by driver */
uint32_t preload_page_count;
uint32_t fw_image_flags;
uint32_t feature_mask;
uint16_t major_version;
uint16_t minor_version;
uint16_t hotfix_version;
uint16_t build_version;
uint32_t num_module_entries;
uint32_t hw_buf_base_addr;
uint32_t hw_buf_length;
/* target address for binary loading as offset in IMR - must be == base offset */
uint32_t load_offset;
} __packed;
/*
* Firmware manifest descriptor. This can contain N modules and N module
* configs. Used by ROM - Immutable.
*/
struct sof_man_fw_desc {
struct sof_man_fw_header header;
/* Warning - hack for module arrays. For some unknown reason the we
* have a variable size array of struct man_module followed by a
* variable size array of struct mod_config. These should have been
* merged into a variable array of a parent structure. We have to hack
* around this in many places....
*
* struct sof_man_module man_module[];
* struct sof_man_mod_config mod_config[];
*/
} __packed;
/*
* Component Descriptor. Used by ROM - Immutable.
*/
struct sof_man_component_desc {
uint32_t reserved[2]; /* all 0 */
uint32_t version;
uint8_t hash[SOF_MAN_MOD_SHA256_LEN];
uint32_t base_offset;
uint32_t limit_offset;
uint32_t attributes[4];
} __packed;
/*
* Audio DSP extended metadata. Used by ROM - Immutable.
*/
struct sof_man_adsp_meta_file_ext {
uint32_t ext_type; /* always 17 for ADSP extension */
uint32_t ext_len;
uint32_t imr_type;
uint8_t reserved[16]; /* all 0 */
struct sof_man_component_desc comp_desc[1];
} __packed;
/*
* Module Manifest for rimage module metadata. Not used by ROM.
*/
struct sof_man_module_manifest {
struct sof_man_module module;
uint32_t text_size;
} __packed;
#endif

View file

@ -85,6 +85,7 @@
#define SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE 605
#define SOF_TKN_INTEL_DMIC_SAMPLE_RATE 608
#define SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH 609
#define SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS 610
/* DMIC PDM */
#define SOF_TKN_INTEL_DMIC_PDM_CTRL_ID 700

View file

@ -1,21 +0,0 @@
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_TONE_H__
#define __INCLUDE_UAPI_SOUND_SOF_USER_TONE_H__
#define SOF_TONE_IDX_FREQUENCY 0
#define SOF_TONE_IDX_AMPLITUDE 1
#define SOF_TONE_IDX_FREQ_MULT 2
#define SOF_TONE_IDX_AMPL_MULT 3
#define SOF_TONE_IDX_LENGTH 4
#define SOF_TONE_IDX_PERIOD 5
#define SOF_TONE_IDX_REPEATS 6
#define SOF_TONE_IDX_LIN_RAMP_STEP 7
#endif

View file

@ -1,66 +0,0 @@
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*/
#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_TRACE_H__
#define __INCLUDE_UAPI_SOUND_SOF_USER_TRACE_H__
/*
* Host system time.
*
* This property is used by the driver to pass down information about
* current system time. It is expressed in us.
* FW translates timestamps (in log entries, probe pockets) to this time
* domain.
*
* (cavs: SystemTime).
*/
struct system_time {
uint32_t val_l; /* Lower dword of current host time value */
uint32_t val_u; /* Upper dword of current host time value */
} __packed;
#define LOG_ENABLE 1 /* Enable logging */
#define LOG_DISABLE 0 /* Disable logging */
#define LOG_LEVEL_CRITICAL 1 /* (FDK fatal) */
#define LOG_LEVEL_VERBOSE 2
/*
* Layout of a log fifo.
*/
struct log_buffer_layout {
uint32_t read_ptr; /*read pointer */
uint32_t write_ptr; /* write pointer */
uint32_t buffer[0]; /* buffer */
} __packed;
/*
* Log buffer status reported by FW.
*/
struct log_buffer_status {
uint32_t core_id; /* ID of core that logged to other half */
} __packed;
#define TRACE_ID_LENGTH 12
/*
* Log entry header.
*
* The header is followed by an array of arguments (uint32_t[]).
* Number of arguments is specified by the params_num field of log_entry
*/
struct log_entry_header {
uint32_t id_0 : TRACE_ID_LENGTH; /* e.g. Pipeline ID */
uint32_t id_1 : TRACE_ID_LENGTH; /* e.g. Component ID */
uint32_t core_id : 8; /* Reporting core's id */
uint64_t timestamp; /* Timestamp (in dsp ticks) */
uint32_t log_entry_address; /* Address of log entry in ELF */
} __packed;
#endif

View file

@ -85,7 +85,6 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev,
const struct hdac_ext_bus_ops *ext_ops)
{
int ret;
static int idx;
/* check if io ops are provided, if not load the defaults */
if (io_ops == NULL)
@ -96,7 +95,12 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev,
return ret;
bus->ext_ops = ext_ops;
bus->idx = idx++;
/* FIXME:
* Currently only one bus is supported, if there is device with more
* buses, bus->idx should be greater than 0, but there needs to be a
* reliable way to always assign same number.
*/
bus->idx = 0;
bus->cmd_dma_state = true;
return 0;

View file

@ -298,69 +298,71 @@ static const struct snd_soc_ops cz_dmic1_cap_ops = {
.hw_params = cz_da7219_params,
};
SND_SOC_DAILINK_DEF(designware1,
DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.1.auto")));
SND_SOC_DAILINK_DEF(designware2,
DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.2.auto")));
SND_SOC_DAILINK_DEF(designware3,
DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.3.auto")));
SND_SOC_DAILINK_DEF(dlgs,
DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", "da7219-hifi")));
SND_SOC_DAILINK_DEF(mx,
DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi")));
SND_SOC_DAILINK_DEF(adau,
DAILINK_COMP_ARRAY(COMP_CODEC("ADAU7002:00", "adau7002-hifi")));
SND_SOC_DAILINK_DEF(platform,
DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_audio_dma.0.auto")));
static struct snd_soc_dai_link cz_dai_7219_98357[] = {
{
.name = "amd-da7219-play",
.stream_name = "Playback",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.1.auto",
.codec_dai_name = "da7219-hifi",
.codec_name = "i2c-DLGS7219:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.init = cz_da7219_init,
.dpcm_playback = 1,
.ops = &cz_da7219_play_ops,
SND_SOC_DAILINK_REG(designware1, dlgs, platform),
},
{
.name = "amd-da7219-cap",
.stream_name = "Capture",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.2.auto",
.codec_dai_name = "da7219-hifi",
.codec_name = "i2c-DLGS7219:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1,
.ops = &cz_da7219_cap_ops,
SND_SOC_DAILINK_REG(designware2, dlgs, platform),
},
{
.name = "amd-max98357-play",
.stream_name = "HiFi Playback",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.3.auto",
.codec_dai_name = "HiFi",
.codec_name = "MX98357A:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.dpcm_playback = 1,
.ops = &cz_max_play_ops,
SND_SOC_DAILINK_REG(designware3, mx, platform),
},
{
/* C panel DMIC */
.name = "dmic0",
.stream_name = "DMIC0 Capture",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.3.auto",
.codec_dai_name = "adau7002-hifi",
.codec_name = "ADAU7002:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1,
.ops = &cz_dmic0_cap_ops,
SND_SOC_DAILINK_REG(designware3, adau, platform),
},
{
/* A/B panel DMIC */
.name = "dmic1",
.stream_name = "DMIC1 Capture",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.2.auto",
.codec_dai_name = "adau7002-hifi",
.codec_name = "ADAU7002:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1,
.ops = &cz_dmic1_cap_ops,
SND_SOC_DAILINK_REG(designware2, adau, platform),
},
};

View file

@ -95,29 +95,34 @@ static struct snd_soc_ops cz_aif1_ops = {
.hw_params = cz_aif1_hw_params,
};
SND_SOC_DAILINK_DEF(designware1,
DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.1.auto")));
SND_SOC_DAILINK_DEF(designware2,
DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.2.auto")));
SND_SOC_DAILINK_DEF(codec,
DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5650:00", "rt5645-aif1")));
SND_SOC_DAILINK_DEF(platform,
DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_audio_dma.0.auto")));
static struct snd_soc_dai_link cz_dai_rt5650[] = {
{
.name = "amd-rt5645-play",
.stream_name = "RT5645_AIF1",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.1.auto",
.codec_dai_name = "rt5645-aif1",
.codec_name = "i2c-10EC5650:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.init = cz_init,
.ops = &cz_aif1_ops,
SND_SOC_DAILINK_REG(designware1, codec, platform),
},
{
.name = "amd-rt5645-cap",
.stream_name = "RT5645_AIF1",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.2.auto",
.codec_dai_name = "rt5645-aif1",
.codec_name = "i2c-10EC5650:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.ops = &cz_aif1_ops,
SND_SOC_DAILINK_REG(designware2, codec, platform),
},
};

View file

@ -32,6 +32,7 @@ struct i2s_stream_instance {
u16 channels;
u32 xfer_resolution;
struct page *pg;
u64 bytescount;
void __iomem *acp3x_base;
};
@ -317,6 +318,24 @@ static int acp3x_dma_open(struct snd_pcm_substream *substream)
return 0;
}
static u64 acp_get_byte_count(struct i2s_stream_instance *rtd, int direction)
{
u64 byte_count;
if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
byte_count = rv_readl(rtd->acp3x_base +
mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH);
byte_count |= rv_readl(rtd->acp3x_base +
mmACP_BT_TX_LINEARPOSITIONCNTR_LOW);
} else {
byte_count = rv_readl(rtd->acp3x_base +
mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH);
byte_count |= rv_readl(rtd->acp3x_base +
mmACP_BT_RX_LINEARPOSITIONCNTR_LOW);
}
return byte_count;
}
static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@ -350,18 +369,17 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream)
{
u32 pos = 0;
struct i2s_stream_instance *rtd = substream->runtime->private_data;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
pos = rv_readl(rtd->acp3x_base +
mmACP_BT_TX_LINKPOSITIONCNTR);
else
pos = rv_readl(rtd->acp3x_base +
mmACP_BT_RX_LINKPOSITIONCNTR);
if (pos >= MAX_BUFFER)
pos = 0;
u32 buffersize = 0;
u64 bytescount = 0;
struct i2s_stream_instance *rtd =
substream->runtime->private_data;
buffersize = frames_to_bytes(substream->runtime,
substream->runtime->buffer_size);
bytescount = acp_get_byte_count(rtd, substream->stream);
if (bytescount > rtd->bytescount)
bytescount -= rtd->bytescount;
pos = do_div(bytescount, buffersize);
return bytes_to_frames(substream->runtime, pos);
}
@ -521,6 +539,7 @@ static int acp3x_dai_i2s_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
rtd->bytescount = acp_get_byte_count(rtd, substream->stream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
rv_writel(period_bytes, rtd->acp3x_base +
mmACP_BT_TX_INTR_WATERMARK_SIZE);

View file

@ -497,17 +497,30 @@ static int atmel_classd_asoc_card_init(struct device *dev,
{
struct snd_soc_dai_link *dai_link;
struct atmel_classd *dd = snd_soc_card_get_drvdata(card);
struct snd_soc_dai_link_component *comp;
dai_link = devm_kzalloc(dev, sizeof(*dai_link), GFP_KERNEL);
if (!dai_link)
return -ENOMEM;
comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL);
if (!comp)
return -ENOMEM;
dai_link->cpus = &comp[0];
dai_link->codecs = &comp[1];
dai_link->platforms = &comp[2];
dai_link->num_cpus = 1;
dai_link->num_codecs = 1;
dai_link->num_platforms = 1;
dai_link->name = "CLASSD";
dai_link->stream_name = "CLASSD PCM";
dai_link->codec_dai_name = ATMEL_CLASSD_CODEC_DAI_NAME;
dai_link->cpu_dai_name = dev_name(dev);
dai_link->codec_name = dev_name(dev);
dai_link->platform_name = dev_name(dev);
dai_link->codecs->dai_name = ATMEL_CLASSD_CODEC_DAI_NAME;
dai_link->cpus->dai_name = dev_name(dev);
dai_link->codecs->name = dev_name(dev);
dai_link->platforms->name = dev_name(dev);
card->dai_link = dai_link;
card->num_links = 1;

View file

@ -111,16 +111,11 @@ static const struct snd_dmaengine_pcm_config atmel_dmaengine_pcm_config = {
int atmel_pcm_dma_platform_register(struct device *dev)
{
return snd_dmaengine_pcm_register(dev, &atmel_dmaengine_pcm_config, 0);
return devm_snd_dmaengine_pcm_register(dev,
&atmel_dmaengine_pcm_config, 0);
}
EXPORT_SYMBOL(atmel_pcm_dma_platform_register);
void atmel_pcm_dma_platform_unregister(struct device *dev)
{
snd_dmaengine_pcm_unregister(dev);
}
EXPORT_SYMBOL(atmel_pcm_dma_platform_unregister);
MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>");
MODULE_DESCRIPTION("Atmel DMA based PCM module");
MODULE_LICENSE("GPL");

View file

@ -393,11 +393,6 @@ int atmel_pcm_pdc_platform_register(struct device *dev)
}
EXPORT_SYMBOL(atmel_pcm_pdc_platform_register);
void atmel_pcm_pdc_platform_unregister(struct device *dev)
{
}
EXPORT_SYMBOL(atmel_pcm_pdc_platform_unregister);
MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
MODULE_DESCRIPTION("Atmel PCM module");
MODULE_LICENSE("GPL");

View file

@ -72,28 +72,20 @@ struct atmel_pcm_dma_params {
#if IS_ENABLED(CONFIG_SND_ATMEL_SOC_PDC)
int atmel_pcm_pdc_platform_register(struct device *dev);
void atmel_pcm_pdc_platform_unregister(struct device *dev);
#else
static inline int atmel_pcm_pdc_platform_register(struct device *dev)
{
return 0;
}
static inline void atmel_pcm_pdc_platform_unregister(struct device *dev)
{
}
#endif
#if IS_ENABLED(CONFIG_SND_ATMEL_SOC_DMA)
int atmel_pcm_dma_platform_register(struct device *dev);
void atmel_pcm_dma_platform_unregister(struct device *dev);
#else
static inline int atmel_pcm_dma_platform_register(struct device *dev)
{
return 0;
}
static inline void atmel_pcm_dma_platform_unregister(struct device *dev)
{
}
#endif
#endif /* _ATMEL_PCM_H */

View file

@ -508,17 +508,30 @@ static int atmel_pdmic_asoc_card_init(struct device *dev,
{
struct snd_soc_dai_link *dai_link;
struct atmel_pdmic *dd = snd_soc_card_get_drvdata(card);
struct snd_soc_dai_link_component *comp;
dai_link = devm_kzalloc(dev, sizeof(*dai_link), GFP_KERNEL);
if (!dai_link)
return -ENOMEM;
comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL);
if (!comp)
return -ENOMEM;
dai_link->cpus = &comp[0];
dai_link->codecs = &comp[1];
dai_link->platforms = &comp[2];
dai_link->num_cpus = 1;
dai_link->num_codecs = 1;
dai_link->num_platforms = 1;
dai_link->name = "PDMIC";
dai_link->stream_name = "PDMIC PCM";
dai_link->codec_dai_name = ATMEL_PDMIC_CODEC_DAI_NAME;
dai_link->cpu_dai_name = dev_name(dev);
dai_link->codec_name = dev_name(dev);
dai_link->platform_name = dev_name(dev);
dai_link->codecs->dai_name = ATMEL_PDMIC_CODEC_DAI_NAME;
dai_link->cpus->dai_name = dev_name(dev);
dai_link->codecs->name = dev_name(dev);
dai_link->platforms->name = dev_name(dev);
card->dai_link = dai_link;
card->num_links = 1;

View file

@ -1012,16 +1012,6 @@ static int asoc_ssc_init(struct device *dev)
return 0;
}
static void asoc_ssc_exit(struct device *dev)
{
struct ssc_device *ssc = dev_get_drvdata(dev);
if (ssc->pdata->use_dma)
atmel_pcm_dma_platform_unregister(dev);
else
atmel_pcm_pdc_platform_unregister(dev);
}
/**
* atmel_ssc_set_audio - Allocate the specified SSC for audio use.
*/
@ -1050,7 +1040,6 @@ void atmel_ssc_put_audio(int ssc_id)
{
struct ssc_device *ssc = ssc_info[ssc_id].ssc;
asoc_ssc_exit(&ssc->pdev->dev);
ssc_free(ssc);
}
EXPORT_SYMBOL_GPL(atmel_ssc_put_audio);

View file

@ -56,14 +56,19 @@ static const struct snd_soc_ops atmel_asoc_wm8904_ops = {
.hw_params = atmel_asoc_wm8904_hw_params,
};
SND_SOC_DAILINK_DEFS(pcm,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8904-hifi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = {
.name = "WM8904",
.stream_name = "WM8904 PCM",
.codec_dai_name = "wm8904-hifi",
.dai_fmt = SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.ops = &atmel_asoc_wm8904_ops,
SND_SOC_DAILINK_REG(pcm),
};
static struct snd_soc_card atmel_asoc_wm8904_card = {
@ -107,8 +112,8 @@ static int atmel_asoc_wm8904_dt_init(struct platform_device *pdev)
ret = -EINVAL;
return ret;
}
dailink->cpu_of_node = cpu_np;
dailink->platform_of_node = cpu_np;
dailink->cpus->of_node = cpu_np;
dailink->platforms->of_node = cpu_np;
of_node_put(cpu_np);
codec_np = of_parse_phandle(np, "atmel,audio-codec", 0);
@ -117,7 +122,7 @@ static int atmel_asoc_wm8904_dt_init(struct platform_device *pdev)
ret = -EINVAL;
return ret;
}
dailink->codec_of_node = codec_np;
dailink->codecs->of_node = codec_np;
of_node_put(codec_np);
return 0;
@ -136,7 +141,7 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev)
return ret;
}
id = of_alias_get_id((struct device_node *)dailink->cpu_of_node, "ssc");
id = of_alias_get_id((struct device_node *)dailink->cpus->of_node, "ssc");
ret = atmel_ssc_set_audio(id);
if (ret != 0) {
dev_err(&pdev->dev, "failed to set SSC %d for audio\n", id);
@ -162,7 +167,7 @@ static int atmel_asoc_wm8904_remove(struct platform_device *pdev)
struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
int id;
id = of_alias_get_id((struct device_node *)dailink->cpu_of_node, "ssc");
id = of_alias_get_id((struct device_node *)dailink->cpus->of_node, "ssc");
snd_soc_unregister_card(card);
atmel_ssc_put_audio(id);

View file

@ -63,6 +63,7 @@ static struct snd_soc_card snd_proto = {
static int snd_proto_probe(struct platform_device *pdev)
{
struct snd_soc_dai_link *dai;
struct snd_soc_dai_link_component *comp;
struct device_node *np = pdev->dev.of_node;
struct device_node *codec_np, *cpu_np;
struct device_node *bitclkmaster = NULL;
@ -84,12 +85,24 @@ static int snd_proto_probe(struct platform_device *pdev)
if (!dai)
return -ENOMEM;
/* for cpus/codecs/platforms */
comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL);
if (!comp)
return -ENOMEM;
snd_proto.dai_link = dai;
snd_proto.num_links = 1;
dai->cpus = &comp[0];
dai->num_cpus = 1;
dai->codecs = &comp[1];
dai->num_codecs = 1;
dai->platforms = &comp[2];
dai->num_platforms = 1;
dai->name = "WM8731";
dai->stream_name = "WM8731 HiFi";
dai->codec_dai_name = "wm8731-hifi";
dai->codecs->dai_name = "wm8731-hifi";
dai->init = &snd_proto_init;
codec_np = of_parse_phandle(np, "audio-codec", 0);
@ -97,15 +110,15 @@ static int snd_proto_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "audio-codec node missing\n");
return -EINVAL;
}
dai->codec_of_node = codec_np;
dai->codecs->of_node = codec_np;
cpu_np = of_parse_phandle(np, "i2s-controller", 0);
if (!cpu_np) {
dev_err(&pdev->dev, "i2s-controller missing\n");
return -EINVAL;
}
dai->cpu_of_node = cpu_np;
dai->platform_of_node = cpu_np;
dai->cpus->of_node = cpu_np;
dai->platforms->of_node = cpu_np;
dai_fmt = snd_soc_of_parse_daifmt(np, NULL,
&bitclkmaster, &framemaster);

View file

@ -116,16 +116,18 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
SND_SOC_DAILINK_DEFS(pcm,
DAILINK_COMP_ARRAY(COMP_CPU("at91rm9200_ssc.0")),
DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi")),
DAILINK_COMP_ARRAY(COMP_PLATFORM("at91rm9200_ssc.0")));
static struct snd_soc_dai_link at91sam9g20ek_dai = {
.name = "WM8731",
.stream_name = "WM8731 PCM",
.cpu_dai_name = "at91rm9200_ssc.0",
.codec_dai_name = "wm8731-hifi",
.init = at91sam9g20ek_wm8731_init,
.platform_name = "at91rm9200_ssc.0",
.codec_name = "wm8731.0-001b",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM,
SND_SOC_DAILINK_REG(pcm),
};
static struct snd_soc_card snd_soc_at91sam9g20ek = {
@ -198,24 +200,24 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
goto err;
/* Parse codec info */
at91sam9g20ek_dai.codec_name = NULL;
at91sam9g20ek_dai.codecs->name = NULL;
codec_np = of_parse_phandle(np, "atmel,audio-codec", 0);
if (!codec_np) {
dev_err(&pdev->dev, "codec info missing\n");
return -EINVAL;
}
at91sam9g20ek_dai.codec_of_node = codec_np;
at91sam9g20ek_dai.codecs->of_node = codec_np;
/* Parse dai and platform info */
at91sam9g20ek_dai.cpu_dai_name = NULL;
at91sam9g20ek_dai.platform_name = NULL;
at91sam9g20ek_dai.cpus->dai_name = NULL;
at91sam9g20ek_dai.platforms->name = NULL;
cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
if (!cpu_np) {
dev_err(&pdev->dev, "dai and pcm info missing\n");
return -EINVAL;
}
at91sam9g20ek_dai.cpu_of_node = cpu_np;
at91sam9g20ek_dai.platform_of_node = cpu_np;
at91sam9g20ek_dai.cpus->of_node = cpu_np;
at91sam9g20ek_dai.platforms->of_node = cpu_np;
of_node_put(codec_np);
of_node_put(cpu_np);

View file

@ -77,6 +77,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
struct snd_soc_card *card;
struct snd_soc_dai_link *dai;
struct sam9x5_drvdata *priv;
struct snd_soc_dai_link_component *comp;
int ret;
if (!np) {
@ -87,7 +88,8 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL);
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
dai = devm_kzalloc(&pdev->dev, sizeof(*dai), GFP_KERNEL);
if (!dai || !card || !priv) {
comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL);
if (!dai || !card || !priv || !comp) {
ret = -ENOMEM;
goto out;
}
@ -100,9 +102,17 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
card->num_links = 1;
card->dapm_widgets = sam9x5_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(sam9x5_dapm_widgets);
dai->cpus = &comp[0];
dai->num_cpus = 1;
dai->codecs = &comp[1];
dai->num_codecs = 1;
dai->platforms = &comp[2];
dai->num_platforms = 1;
dai->name = "WM8731";
dai->stream_name = "WM8731 PCM";
dai->codec_dai_name = "wm8731-hifi";
dai->codecs->dai_name = "wm8731-hifi";
dai->init = sam9x5_wm8731_init;
dai->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM;
@ -126,7 +136,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
goto out;
}
dai->codec_of_node = codec_np;
dai->codecs->of_node = codec_np;
cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
if (!cpu_np) {
@ -134,8 +144,8 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
ret = -EINVAL;
goto out;
}
dai->cpu_of_node = cpu_np;
dai->platform_of_node = cpu_np;
dai->cpus->of_node = cpu_np;
dai->platforms->of_node = cpu_np;
priv->ssc_id = of_alias_get_id(cpu_np, "ssc");

View file

@ -294,13 +294,18 @@ static const struct snd_soc_dapm_route tse850_intercon[] = {
{ "DAC", NULL, "OUTL" },
};
SND_SOC_DAILINK_DEFS(pcm,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "pcm512x-hifi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
static struct snd_soc_dai_link tse850_dailink = {
.name = "TSE-850",
.stream_name = "TSE-850-PCM",
.codec_dai_name = "pcm512x-hifi",
.dai_fmt = SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFS,
SND_SOC_DAILINK_REG(pcm),
};
static struct snd_soc_card tse850_card = {
@ -331,8 +336,8 @@ static int tse850_dt_init(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to get cpu dai\n");
return -EINVAL;
}
dailink->cpu_of_node = cpu_np;
dailink->platform_of_node = cpu_np;
dailink->cpus->of_node = cpu_np;
dailink->platforms->of_node = cpu_np;
of_node_put(cpu_np);
codec_np = of_parse_phandle(np, "axentia,audio-codec", 0);
@ -340,7 +345,7 @@ static int tse850_dt_init(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to get codec info\n");
return -EINVAL;
}
dailink->codec_of_node = codec_np;
dailink->codecs->of_node = codec_np;
of_node_put(codec_np);
return 0;

View file

@ -19,13 +19,15 @@
#include "psc.h"
SND_SOC_DAILINK_DEFS(hifi,
DAILINK_COMP_ARRAY(COMP_CPU("alchemy-ac97c")),
DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec", "ac97-hifi")),
DAILINK_COMP_ARRAY(COMP_PLATFORM("alchemy-pcm-dma.0")));
static struct snd_soc_dai_link db1000_ac97_dai = {
.name = "AC97",
.stream_name = "AC97 HiFi",
.codec_dai_name = "ac97-hifi",
.cpu_dai_name = "alchemy-ac97c",
.platform_name = "alchemy-pcm-dma.0",
.codec_name = "ac97-codec",
SND_SOC_DAILINK_REG(hifi),
};
static struct snd_soc_card db1000_ac97 = {

View file

@ -47,13 +47,15 @@ static const struct platform_device_id db1200_pids[] = {
/*------------------------- AC97 PART ---------------------------*/
SND_SOC_DAILINK_DEFS(db1200_ac97,
DAILINK_COMP_ARRAY(COMP_CPU("au1xpsc_ac97.1")),
DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec.1", "ac97-hifi")),
DAILINK_COMP_ARRAY(COMP_PLATFORM("au1xpsc-pcm.1")));
static struct snd_soc_dai_link db1200_ac97_dai = {
.name = "AC97",
.stream_name = "AC97 HiFi",
.codec_dai_name = "ac97-hifi",
.cpu_dai_name = "au1xpsc_ac97.1",
.platform_name = "au1xpsc-pcm.1",
.codec_name = "ac97-codec.1",
SND_SOC_DAILINK_REG(db1200_ac97),
};
static struct snd_soc_card db1200_ac97_machine = {
@ -63,13 +65,15 @@ static struct snd_soc_card db1200_ac97_machine = {
.num_links = 1,
};
SND_SOC_DAILINK_DEFS(db1300_ac97,
DAILINK_COMP_ARRAY(COMP_CPU("au1xpsc_ac97.1")),
DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec.1", "wm9712-hifi")),
DAILINK_COMP_ARRAY(COMP_PLATFORM("au1xpsc-pcm.1")));
static struct snd_soc_dai_link db1300_ac97_dai = {
.name = "AC97",
.stream_name = "AC97 HiFi",
.codec_dai_name = "wm9712-hifi",
.cpu_dai_name = "au1xpsc_ac97.1",
.platform_name = "au1xpsc-pcm.1",
.codec_name = "wm9712-codec.1",
SND_SOC_DAILINK_REG(db1300_ac97),
};
static struct snd_soc_card db1300_ac97_machine = {
@ -104,16 +108,18 @@ static const struct snd_soc_ops db1200_i2s_wm8731_ops = {
.startup = db1200_i2s_startup,
};
SND_SOC_DAILINK_DEFS(db1200_i2s,
DAILINK_COMP_ARRAY(COMP_CPU("au1xpsc_i2s.1")),
DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi")),
DAILINK_COMP_ARRAY(COMP_PLATFORM("au1xpsc-pcm.1")));
static struct snd_soc_dai_link db1200_i2s_dai = {
.name = "WM8731",
.stream_name = "WM8731 PCM",
.codec_dai_name = "wm8731-hifi",
.cpu_dai_name = "au1xpsc_i2s.1",
.platform_name = "au1xpsc-pcm.1",
.codec_name = "wm8731.0-001b",
.dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM,
.ops = &db1200_i2s_wm8731_ops,
SND_SOC_DAILINK_REG(db1200_i2s),
};
static struct snd_soc_card db1200_i2s_machine = {
@ -123,16 +129,18 @@ static struct snd_soc_card db1200_i2s_machine = {
.num_links = 1,
};
SND_SOC_DAILINK_DEFS(db1300_i2s,
DAILINK_COMP_ARRAY(COMP_CPU("au1xpsc_i2s.2")),
DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi")),
DAILINK_COMP_ARRAY(COMP_PLATFORM("au1xpsc-pcm.2")));
static struct snd_soc_dai_link db1300_i2s_dai = {
.name = "WM8731",
.stream_name = "WM8731 PCM",
.codec_dai_name = "wm8731-hifi",
.cpu_dai_name = "au1xpsc_i2s.2",
.platform_name = "au1xpsc-pcm.2",
.codec_name = "wm8731.0-001b",
.dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM,
.ops = &db1200_i2s_wm8731_ops,
SND_SOC_DAILINK_REG(db1300_i2s),
};
static struct snd_soc_card db1300_i2s_machine = {
@ -142,16 +150,18 @@ static struct snd_soc_card db1300_i2s_machine = {
.num_links = 1,
};
SND_SOC_DAILINK_DEFS(db1550_i2s,
DAILINK_COMP_ARRAY(COMP_CPU("au1xpsc_i2s.3")),
DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi")),
DAILINK_COMP_ARRAY(COMP_PLATFORM("au1xpsc-pcm.3")));
static struct snd_soc_dai_link db1550_i2s_dai = {
.name = "WM8731",
.stream_name = "WM8731 PCM",
.codec_dai_name = "wm8731-hifi",
.cpu_dai_name = "au1xpsc_i2s.3",
.platform_name = "au1xpsc-pcm.3",
.codec_name = "wm8731.0-001b",
.dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM,
.ops = &db1200_i2s_wm8731_ops,
SND_SOC_DAILINK_REG(db1550_i2s),
};
static struct snd_soc_card db1550_i2s_machine = {

View file

@ -340,16 +340,14 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
platform_set_drvdata(pdev, wd);
return snd_soc_register_component(&pdev->dev, &au1xpsc_i2s_component,
&wd->dai_drv, 1);
return devm_snd_soc_register_component(&pdev->dev,
&au1xpsc_i2s_component, &wd->dai_drv, 1);
}
static int au1xpsc_i2s_drvremove(struct platform_device *pdev)
{
struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
snd_soc_unregister_component(&pdev->dev);
__raw_writel(0, I2S_CFG(wd));
wmb(); /* drain writebuffer */
__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));

View file

@ -51,16 +51,18 @@ static const struct snd_soc_ops edb93xx_ops = {
.hw_params = edb93xx_hw_params,
};
SND_SOC_DAILINK_DEFS(hifi,
DAILINK_COMP_ARRAY(COMP_CPU("ep93xx-i2s")),
DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "cs4271-hifi")),
DAILINK_COMP_ARRAY(COMP_PLATFORM("ep93xx-i2s")));
static struct snd_soc_dai_link edb93xx_dai = {
.name = "CS4271",
.stream_name = "CS4271 HiFi",
.platform_name = "ep93xx-i2s",
.cpu_dai_name = "ep93xx-i2s",
.codec_name = "spi0.0",
.codec_dai_name = "cs4271-hifi",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
.ops = &edb93xx_ops,
SND_SOC_DAILINK_REG(hifi),
};
static struct snd_soc_card snd_soc_edb93xx = {

View file

@ -473,19 +473,17 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, info);
err = snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component,
err = devm_snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component,
&ep93xx_i2s_dai, 1);
if (err)
goto fail_put_lrclk;
err = devm_ep93xx_pcm_platform_register(&pdev->dev);
if (err)
goto fail_unregister;
goto fail_put_lrclk;
return 0;
fail_unregister:
snd_soc_unregister_component(&pdev->dev);
fail_put_lrclk:
clk_put(info->lrclk);
fail_put_sclk:
@ -500,7 +498,6 @@ static int ep93xx_i2s_remove(struct platform_device *pdev)
{
struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
snd_soc_unregister_component(&pdev->dev);
clk_put(info->lrclk);
clk_put(info->sclk);
clk_put(info->mclk);

View file

@ -18,13 +18,15 @@
#include <asm/mach-types.h>
SND_SOC_DAILINK_DEFS(hifi,
DAILINK_COMP_ARRAY(COMP_CPU("ep93xx-ac97")),
DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec", "ac97-hifi")),
DAILINK_COMP_ARRAY(COMP_PLATFORM("ep93xx-ac97")));
static struct snd_soc_dai_link simone_dai = {
.name = "AC97",
.stream_name = "AC97 HiFi",
.cpu_dai_name = "ep93xx-ac97",
.codec_dai_name = "ac97-hifi",
.codec_name = "ac97-codec",
.platform_name = "ep93xx-ac97",
SND_SOC_DAILINK_REG(hifi),
};
static struct snd_soc_card snd_soc_simone = {

View file

@ -60,16 +60,19 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"MICIN", NULL, "Mic Jack"},
};
SND_SOC_DAILINK_DEFS(aic23,
DAILINK_COMP_ARRAY(COMP_CPU("ep93xx-i2s")),
DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic23-codec.0-001a",
"tlv320aic23-hifi")),
DAILINK_COMP_ARRAY(COMP_PLATFORM("ep93xx-i2s")));
static struct snd_soc_dai_link snappercl15_dai = {
.name = "tlv320aic23",
.stream_name = "AIC23",
.cpu_dai_name = "ep93xx-i2s",
.codec_dai_name = "tlv320aic23-hifi",
.codec_name = "tlv320aic23-codec.0-001a",
.platform_name = "ep93xx-i2s",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
.ops = &snappercl15_ops,
SND_SOC_DAILINK_REG(aic23),
};
static struct snd_soc_card snd_soc_snappercl15 = {

View file

@ -71,8 +71,12 @@ config SND_SOC_ALL_CODECS
select SND_SOC_CS4341 if SND_SOC_I2C_AND_SPI
select SND_SOC_CS4349 if I2C
select SND_SOC_CS47L24 if MFD_CS47L24
select SND_SOC_CS47L35 if MFD_CS47L35
select SND_SOC_CS47L85 if MFD_CS47L85
select SND_SOC_CS47L90 if MFD_CS47L90
select SND_SOC_CS53L30 if I2C
select SND_SOC_CX20442 if TTY
select SND_SOC_CX2072X if I2C
select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI
select SND_SOC_DA7213 if I2C
select SND_SOC_DA7218 if I2C
@ -140,7 +144,9 @@ config SND_SOC_ALL_CODECS
select SND_SOC_RT274 if I2C
select SND_SOC_RT286 if I2C
select SND_SOC_RT298 if I2C
select SND_SOC_RT1011 if I2C
select SND_SOC_RT1305 if I2C
select SND_SOC_RT1308 if I2C
select SND_SOC_RT5514 if I2C
select SND_SOC_RT5616 if I2C
select SND_SOC_RT5631 if I2C
@ -283,10 +289,12 @@ config SND_SOC_WM_HUBS
config SND_SOC_WM_ADSP
tristate
select SND_SOC_COMPRESS
default y if SND_SOC_MADERA=y
default y if SND_SOC_CS47L24=y
default y if SND_SOC_WM5102=y
default y if SND_SOC_WM5110=y
default y if SND_SOC_WM2200=y
default m if SND_SOC_MADERA=m
default m if SND_SOC_CS47L24=m
default m if SND_SOC_WM5102=m
default m if SND_SOC_WM5110=m
@ -576,6 +584,15 @@ config SND_SOC_CS4349
config SND_SOC_CS47L24
tristate
config SND_SOC_CS47L35
tristate
config SND_SOC_CS47L85
tristate
config SND_SOC_CS47L90
tristate
# Cirrus Logic Quad-Channel ADC
config SND_SOC_CS53L30
tristate "Cirrus Logic CS53L30 CODEC"
@ -585,6 +602,12 @@ config SND_SOC_CX20442
tristate
depends on TTY
config SND_SOC_CX2072X
tristate "Conexant CX2072X CODEC"
depends on I2C
help
Enable support for Conexant CX20721 and CX20723 codec chips.
config SND_SOC_JZ4740_CODEC
depends on MIPS || COMPILE_TEST
select REGMAP_MMIO
@ -697,6 +720,15 @@ config SND_SOC_LOCHNAGAR_SC
This driver support the sound card functionality of the Cirrus
Logic Lochnagar audio development board.
config SND_SOC_MADERA
tristate
default y if SND_SOC_CS47L35=y
default y if SND_SOC_CS47L85=y
default y if SND_SOC_CS47L90=y
default m if SND_SOC_CS47L35=m
default m if SND_SOC_CS47L85=m
default m if SND_SOC_CS47L90=m
config SND_SOC_MAX98088
tristate "Maxim MAX98088/9 Low-Power, Stereo Audio Codec"
depends on I2C
@ -708,7 +740,8 @@ config SND_SOC_MAX98095
tristate
config SND_SOC_MAX98357A
tristate
tristate "Maxim MAX98357A CODEC"
depends on GPIOLIB
config SND_SOC_MAX98371
tristate
@ -870,7 +903,9 @@ config SND_SOC_RL6231
default y if SND_SOC_RT5670=y
default y if SND_SOC_RT5677=y
default y if SND_SOC_RT5682=y
default y if SND_SOC_RT1011=y
default y if SND_SOC_RT1305=y
default y if SND_SOC_RT1308=y
default m if SND_SOC_RT5514=m
default m if SND_SOC_RT5616=m
default m if SND_SOC_RT5640=m
@ -884,7 +919,9 @@ config SND_SOC_RL6231
default m if SND_SOC_RT5670=m
default m if SND_SOC_RT5677=m
default m if SND_SOC_RT5682=m
default m if SND_SOC_RT1011=m
default m if SND_SOC_RT1305=m
default m if SND_SOC_RT1308=m
config SND_SOC_RL6347A
tristate
@ -907,9 +944,15 @@ config SND_SOC_RT298
tristate
depends on I2C
config SND_SOC_RT1011
tristate
config SND_SOC_RT1305
tristate
config SND_SOC_RT1308
tristate
config SND_SOC_RT5514
tristate

View file

@ -65,8 +65,12 @@ snd-soc-cs43130-objs := cs43130.o
snd-soc-cs4341-objs := cs4341.o
snd-soc-cs4349-objs := cs4349.o
snd-soc-cs47l24-objs := cs47l24.o
snd-soc-cs47l35-objs := cs47l35.o
snd-soc-cs47l85-objs := cs47l85.o
snd-soc-cs47l90-objs := cs47l90.o
snd-soc-cs53l30-objs := cs53l30.o
snd-soc-cx20442-objs := cx20442.o
snd-soc-cx2072x-objs := cx2072x.o
snd-soc-da7210-objs := da7210.o
snd-soc-da7213-objs := da7213.o
snd-soc-da7218-objs := da7218.o
@ -92,6 +96,7 @@ 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-madera-objs := madera.o
snd-soc-max9759-objs := max9759.o
snd-soc-max9768-objs := max9768.o
snd-soc-max98088-objs := max98088.o
@ -141,7 +146,9 @@ snd-soc-pcm512x-spi-objs := pcm512x-spi.o
snd-soc-rk3328-objs := rk3328_codec.o
snd-soc-rl6231-objs := rl6231.o
snd-soc-rl6347a-objs := rl6347a.o
snd-soc-rt1011-objs := rt1011.o
snd-soc-rt1305-objs := rt1305.o
snd-soc-rt1308-objs := rt1308.o
snd-soc-rt274-objs := rt274.o
snd-soc-rt286-objs := rt286.o
snd-soc-rt298-objs := rt298.o
@ -339,8 +346,12 @@ obj-$(CONFIG_SND_SOC_CS43130) += snd-soc-cs43130.o
obj-$(CONFIG_SND_SOC_CS4341) += snd-soc-cs4341.o
obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o
obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o
obj-$(CONFIG_SND_SOC_CS47L35) += snd-soc-cs47l35.o
obj-$(CONFIG_SND_SOC_CS47L85) += snd-soc-cs47l85.o
obj-$(CONFIG_SND_SOC_CS47L90) += snd-soc-cs47l90.o
obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o
obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
obj-$(CONFIG_SND_SOC_CX2072X) += snd-soc-cx2072x.o
obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o
obj-$(CONFIG_SND_SOC_DA7218) += snd-soc-da7218.o
@ -366,6 +377,7 @@ obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
obj-$(CONFIG_SND_SOC_LM49453) += snd-soc-lm49453.o
obj-$(CONFIG_SND_SOC_LOCHNAGAR_SC) += snd-soc-lochnagar-sc.o
obj-$(CONFIG_SND_SOC_MADERA) += snd-soc-madera.o
obj-$(CONFIG_SND_SOC_MAX9759) += snd-soc-max9759.o
obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o
obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
@ -415,7 +427,9 @@ obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o
obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o
obj-$(CONFIG_SND_SOC_RT1011) += snd-soc-rt1011.o
obj-$(CONFIG_SND_SOC_RT1305) += snd-soc-rt1305.o
obj-$(CONFIG_SND_SOC_RT1308) += snd-soc-rt1308.o
obj-$(CONFIG_SND_SOC_RT274) += snd-soc-rt274.o
obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o
obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o

View file

@ -413,6 +413,48 @@ static struct snd_soc_dai_driver ad193x_no_adc_dai = {
.ops = &ad193x_dai_ops,
};
struct ad193x_reg_default {
unsigned int reg;
unsigned int val;
};
/* codec register values to set after reset */
static void ad193x_reg_default_init(struct ad193x_priv *ad193x)
{
const struct ad193x_reg_default reg_init[] = {
{ 0, 0x99 }, /* PLL_CLK_CTRL0: pll input: mclki/xi 12.288Mhz */
{ 1, 0x04 }, /* PLL_CLK_CTRL1: no on-chip Vref */
{ 2, 0x40 }, /* DAC_CTRL0: TDM mode */
{ 3, 0x00 }, /* DAC_CTRL1: reset */
{ 4, 0x1A }, /* DAC_CTRL2: 48kHz de-emphasis, unmute dac */
{ 5, 0x00 }, /* DAC_CHNL_MUTE: unmute DAC channels */
{ 6, 0x00 }, /* DAC_L1_VOL: no attenuation */
{ 7, 0x00 }, /* DAC_R1_VOL: no attenuation */
{ 8, 0x00 }, /* DAC_L2_VOL: no attenuation */
{ 9, 0x00 }, /* DAC_R2_VOL: no attenuation */
{ 10, 0x00 }, /* DAC_L3_VOL: no attenuation */
{ 11, 0x00 }, /* DAC_R3_VOL: no attenuation */
{ 12, 0x00 }, /* DAC_L4_VOL: no attenuation */
{ 13, 0x00 }, /* DAC_R4_VOL: no attenuation */
};
const struct ad193x_reg_default reg_adc_init[] = {
{ 14, 0x03 }, /* ADC_CTRL0: high-pass filter enable */
{ 15, 0x43 }, /* ADC_CTRL1: sata delay=1, adc aux mode */
{ 16, 0x00 }, /* ADC_CTRL2: reset */
};
int i;
for (i = 0; i < ARRAY_SIZE(reg_init); i++)
regmap_write(ad193x->regmap, reg_init[i].reg, reg_init[i].val);
if (ad193x_has_adc(ad193x)) {
for (i = 0; i < ARRAY_SIZE(reg_adc_init); i++) {
regmap_write(ad193x->regmap, reg_adc_init[i].reg,
reg_adc_init[i].val);
}
}
}
static int ad193x_component_probe(struct snd_soc_component *component)
{
struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component);
@ -420,25 +462,7 @@ static int ad193x_component_probe(struct snd_soc_component *component)
int num, ret;
/* default setting for ad193x */
/* unmute dac channels */
regmap_write(ad193x->regmap, AD193X_DAC_CHNL_MUTE, 0x0);
/* de-emphasis: 48kHz, powedown dac */
regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A);
/* dac in tdm mode */
regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x40);
/* adc only */
if (ad193x_has_adc(ad193x)) {
/* high-pass filter enable */
regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3);
/* sata delay=1, adc aux mode */
regmap_write(ad193x->regmap, AD193X_ADC_CTRL1, 0x43);
}
/* pll input: mclki/xi */
regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04);
ad193x_reg_default_init(ad193x);
/* adc only */
if (ad193x_has_adc(ad193x)) {

View file

@ -400,14 +400,8 @@ static int ak4118_i2c_probe(struct i2c_client *i2c,
return ret;
}
return snd_soc_register_component(&i2c->dev, &soc_component_drv_ak4118,
&ak4118_dai, 1);
}
static int ak4118_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_component(&i2c->dev);
return 0;
return devm_snd_soc_register_component(&i2c->dev,
&soc_component_drv_ak4118, &ak4118_dai, 1);
}
static const struct of_device_id ak4118_of_match[] = {
@ -429,7 +423,6 @@ static struct i2c_driver ak4118_i2c_driver = {
},
.id_table = ak4118_id_table,
.probe = ak4118_i2c_probe,
.remove = ak4118_i2c_remove,
};
module_i2c_driver(ak4118_i2c_driver);

View file

@ -413,7 +413,7 @@ static int cros_ec_codec_platform_probe(struct platform_device *pd)
platform_set_drvdata(pd, codec_data);
return snd_soc_register_component(dev, &cros_ec_component_driver,
return devm_snd_soc_register_component(dev, &cros_ec_component_driver,
cros_ec_dai, ARRAY_SIZE(cros_ec_dai));
}

View file

@ -14,6 +14,7 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/gpio/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <sound/pcm_params.h>
@ -45,6 +46,7 @@ struct cs42xx8_priv {
bool slave_mode;
unsigned long sysclk;
u32 tx_channels;
struct gpio_desc *gpiod_reset;
};
/* -127.5dB to 0dB with step of 0.5dB */
@ -467,6 +469,13 @@ int cs42xx8_probe(struct device *dev, struct regmap *regmap)
return -EINVAL;
}
cs42xx8->gpiod_reset = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_HIGH);
if (IS_ERR(cs42xx8->gpiod_reset))
return PTR_ERR(cs42xx8->gpiod_reset);
gpiod_set_value_cansleep(cs42xx8->gpiod_reset, 0);
cs42xx8->clk = devm_clk_get(dev, "mclk");
if (IS_ERR(cs42xx8->clk)) {
dev_err(dev, "failed to get the clock: %ld\n",
@ -547,6 +556,8 @@ static int cs42xx8_runtime_resume(struct device *dev)
return ret;
}
gpiod_set_value_cansleep(cs42xx8->gpiod_reset, 0);
ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies),
cs42xx8->supplies);
if (ret) {
@ -586,6 +597,8 @@ static int cs42xx8_runtime_suspend(struct device *dev)
regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies),
cs42xx8->supplies);
gpiod_set_value_cansleep(cs42xx8->gpiod_reset, 1);
clk_disable_unprepare(cs42xx8->clk);
return 0;

1777
sound/soc/codecs/cs47l35.c Normal file

File diff suppressed because it is too large Load diff

2730
sound/soc/codecs/cs47l85.c Normal file

File diff suppressed because it is too large Load diff

2653
sound/soc/codecs/cs47l90.c Normal file

File diff suppressed because it is too large Load diff

1725
sound/soc/codecs/cx2072x.c Normal file

File diff suppressed because it is too large Load diff

314
sound/soc/codecs/cx2072x.h Normal file
View file

@ -0,0 +1,314 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* ALSA SoC CX20721/CX20723 codec driver
*
* Copyright: (C) 2017 Conexant Systems, Inc.
* Author: Simon Ho, <Simon.ho@conexant.com>
*/
#ifndef __CX2072X_H__
#define __CX2072X_H__
#define CX2072X_MCLK_PLL 1
#define CX2072X_MCLK_EXTERNAL_PLL 1
#define CX2072X_MCLK_INTERNAL_OSC 2
/*#define CX2072X_RATES SNDRV_PCM_RATE_8000_192000*/
#define CX2072X_RATES_DSP SNDRV_PCM_RATE_48000
#define CX2072X_REG_MAX 0x8a3c
#define CX2072X_VENDOR_ID 0x0200
#define CX2072X_REVISION_ID 0x0208
#define CX2072X_CURRENT_BCLK_FREQUENCY 0x00dc
#define CX2072X_AFG_POWER_STATE 0x0414
#define CX2072X_UM_RESPONSE 0x0420
#define CX2072X_GPIO_DATA 0x0454
#define CX2072X_GPIO_ENABLE 0x0458
#define CX2072X_GPIO_DIRECTION 0x045c
#define CX2072X_GPIO_WAKE 0x0460
#define CX2072X_GPIO_UM_ENABLE 0x0464
#define CX2072X_GPIO_STICKY_MASK 0x0468
#define CX2072X_AFG_FUNCTION_RESET 0x07fc
#define CX2072X_DAC1_CONVERTER_FORMAT 0x43c8
#define CX2072X_DAC1_AMP_GAIN_RIGHT 0x41c0
#define CX2072X_DAC1_AMP_GAIN_LEFT 0x41e0
#define CX2072X_DAC1_POWER_STATE 0x4014
#define CX2072X_DAC1_CONVERTER_STREAM_CHANNEL 0x4018
#define CX2072X_DAC1_EAPD_ENABLE 0x4030
#define CX2072X_DAC2_CONVERTER_FORMAT 0x47c8
#define CX2072X_DAC2_AMP_GAIN_RIGHT 0x45c0
#define CX2072X_DAC2_AMP_GAIN_LEFT 0x45e0
#define CX2072X_DAC2_POWER_STATE 0x4414
#define CX2072X_DAC2_CONVERTER_STREAM_CHANNEL 0x4418
#define CX2072X_ADC1_CONVERTER_FORMAT 0x4fc8
#define CX2072X_ADC1_AMP_GAIN_RIGHT_0 0x4d80
#define CX2072X_ADC1_AMP_GAIN_LEFT_0 0x4da0
#define CX2072X_ADC1_AMP_GAIN_RIGHT_1 0x4d84
#define CX2072X_ADC1_AMP_GAIN_LEFT_1 0x4da4
#define CX2072X_ADC1_AMP_GAIN_RIGHT_2 0x4d88
#define CX2072X_ADC1_AMP_GAIN_LEFT_2 0x4da8
#define CX2072X_ADC1_AMP_GAIN_RIGHT_3 0x4d8c
#define CX2072X_ADC1_AMP_GAIN_LEFT_3 0x4dac
#define CX2072X_ADC1_AMP_GAIN_RIGHT_4 0x4d90
#define CX2072X_ADC1_AMP_GAIN_LEFT_4 0x4db0
#define CX2072X_ADC1_AMP_GAIN_RIGHT_5 0x4d94
#define CX2072X_ADC1_AMP_GAIN_LEFT_5 0x4db4
#define CX2072X_ADC1_AMP_GAIN_RIGHT_6 0x4d98
#define CX2072X_ADC1_AMP_GAIN_LEFT_6 0x4db8
#define CX2072X_ADC1_CONNECTION_SELECT_CONTROL 0x4c04
#define CX2072X_ADC1_POWER_STATE 0x4c14
#define CX2072X_ADC1_CONVERTER_STREAM_CHANNEL 0x4c18
#define CX2072X_ADC2_CONVERTER_FORMAT 0x53c8
#define CX2072X_ADC2_AMP_GAIN_RIGHT_0 0x5180
#define CX2072X_ADC2_AMP_GAIN_LEFT_0 0x51a0
#define CX2072X_ADC2_AMP_GAIN_RIGHT_1 0x5184
#define CX2072X_ADC2_AMP_GAIN_LEFT_1 0x51a4
#define CX2072X_ADC2_AMP_GAIN_RIGHT_2 0x5188
#define CX2072X_ADC2_AMP_GAIN_LEFT_2 0x51a8
#define CX2072X_ADC2_CONNECTION_SELECT_CONTROL 0x5004
#define CX2072X_ADC2_POWER_STATE 0x5014
#define CX2072X_ADC2_CONVERTER_STREAM_CHANNEL 0x5018
#define CX2072X_PORTA_CONNECTION_SELECT_CTRL 0x5804
#define CX2072X_PORTA_POWER_STATE 0x5814
#define CX2072X_PORTA_PIN_CTRL 0x581c
#define CX2072X_PORTA_UNSOLICITED_RESPONSE 0x5820
#define CX2072X_PORTA_PIN_SENSE 0x5824
#define CX2072X_PORTA_EAPD_BTL 0x5830
#define CX2072X_PORTB_POWER_STATE 0x6014
#define CX2072X_PORTB_PIN_CTRL 0x601c
#define CX2072X_PORTB_UNSOLICITED_RESPONSE 0x6020
#define CX2072X_PORTB_PIN_SENSE 0x6024
#define CX2072X_PORTB_EAPD_BTL 0x6030
#define CX2072X_PORTB_GAIN_RIGHT 0x6180
#define CX2072X_PORTB_GAIN_LEFT 0x61a0
#define CX2072X_PORTC_POWER_STATE 0x6814
#define CX2072X_PORTC_PIN_CTRL 0x681c
#define CX2072X_PORTC_GAIN_RIGHT 0x6980
#define CX2072X_PORTC_GAIN_LEFT 0x69a0
#define CX2072X_PORTD_POWER_STATE 0x6414
#define CX2072X_PORTD_PIN_CTRL 0x641c
#define CX2072X_PORTD_UNSOLICITED_RESPONSE 0x6420
#define CX2072X_PORTD_PIN_SENSE 0x6424
#define CX2072X_PORTD_GAIN_RIGHT 0x6580
#define CX2072X_PORTD_GAIN_LEFT 0x65a0
#define CX2072X_PORTE_CONNECTION_SELECT_CTRL 0x7404
#define CX2072X_PORTE_POWER_STATE 0x7414
#define CX2072X_PORTE_PIN_CTRL 0x741c
#define CX2072X_PORTE_UNSOLICITED_RESPONSE 0x7420
#define CX2072X_PORTE_PIN_SENSE 0x7424
#define CX2072X_PORTE_EAPD_BTL 0x7430
#define CX2072X_PORTE_GAIN_RIGHT 0x7580
#define CX2072X_PORTE_GAIN_LEFT 0x75a0
#define CX2072X_PORTF_POWER_STATE 0x7814
#define CX2072X_PORTF_PIN_CTRL 0x781c
#define CX2072X_PORTF_UNSOLICITED_RESPONSE 0x7820
#define CX2072X_PORTF_PIN_SENSE 0x7824
#define CX2072X_PORTF_GAIN_RIGHT 0x7980
#define CX2072X_PORTF_GAIN_LEFT 0x79a0
#define CX2072X_PORTG_POWER_STATE 0x5c14
#define CX2072X_PORTG_PIN_CTRL 0x5c1c
#define CX2072X_PORTG_CONNECTION_SELECT_CTRL 0x5c04
#define CX2072X_PORTG_EAPD_BTL 0x5c30
#define CX2072X_PORTM_POWER_STATE 0x8814
#define CX2072X_PORTM_PIN_CTRL 0x881c
#define CX2072X_PORTM_CONNECTION_SELECT_CTRL 0x8804
#define CX2072X_PORTM_EAPD_BTL 0x8830
#define CX2072X_MIXER_POWER_STATE 0x5414
#define CX2072X_MIXER_GAIN_RIGHT_0 0x5580
#define CX2072X_MIXER_GAIN_LEFT_0 0x55a0
#define CX2072X_MIXER_GAIN_RIGHT_1 0x5584
#define CX2072X_MIXER_GAIN_LEFT_1 0x55a4
#define CX2072X_EQ_ENABLE_BYPASS 0x6d00
#define CX2072X_EQ_B0_COEFF 0x6d02
#define CX2072X_EQ_B1_COEFF 0x6d04
#define CX2072X_EQ_B2_COEFF 0x6d06
#define CX2072X_EQ_A1_COEFF 0x6d08
#define CX2072X_EQ_A2_COEFF 0x6d0a
#define CX2072X_EQ_G_COEFF 0x6d0c
#define CX2072X_EQ_BAND 0x6d0d
#define CX2072X_SPKR_DRC_ENABLE_STEP 0x6d10
#define CX2072X_SPKR_DRC_CONTROL 0x6d14
#define CX2072X_SPKR_DRC_TEST 0x6d18
#define CX2072X_DIGITAL_BIOS_TEST0 0x6d80
#define CX2072X_DIGITAL_BIOS_TEST2 0x6d84
#define CX2072X_I2SPCM_CONTROL1 0x6e00
#define CX2072X_I2SPCM_CONTROL2 0x6e04
#define CX2072X_I2SPCM_CONTROL3 0x6e08
#define CX2072X_I2SPCM_CONTROL4 0x6e0c
#define CX2072X_I2SPCM_CONTROL5 0x6e10
#define CX2072X_I2SPCM_CONTROL6 0x6e18
#define CX2072X_UM_INTERRUPT_CRTL_E 0x6e14
#define CX2072X_CODEC_TEST2 0x7108
#define CX2072X_CODEC_TEST9 0x7124
#define CX2072X_CODEC_TESTXX 0x7290
#define CX2072X_CODEC_TEST20 0x7310
#define CX2072X_CODEC_TEST24 0x731c
#define CX2072X_CODEC_TEST26 0x7328
#define CX2072X_ANALOG_TEST3 0x718c
#define CX2072X_ANALOG_TEST4 0x7190
#define CX2072X_ANALOG_TEST5 0x7194
#define CX2072X_ANALOG_TEST6 0x7198
#define CX2072X_ANALOG_TEST7 0x719c
#define CX2072X_ANALOG_TEST8 0x71a0
#define CX2072X_ANALOG_TEST9 0x71a4
#define CX2072X_ANALOG_TEST10 0x71a8
#define CX2072X_ANALOG_TEST11 0x71ac
#define CX2072X_ANALOG_TEST12 0x71b0
#define CX2072X_ANALOG_TEST13 0x71b4
#define CX2072X_DIGITAL_TEST0 0x7200
#define CX2072X_DIGITAL_TEST1 0x7204
#define CX2072X_DIGITAL_TEST11 0x722c
#define CX2072X_DIGITAL_TEST12 0x7230
#define CX2072X_DIGITAL_TEST15 0x723c
#define CX2072X_DIGITAL_TEST16 0x7080
#define CX2072X_DIGITAL_TEST17 0x7084
#define CX2072X_DIGITAL_TEST18 0x7088
#define CX2072X_DIGITAL_TEST19 0x708c
#define CX2072X_DIGITAL_TEST20 0x7090
/* not used in the current code, for future extensions (if any) */
#define CX2072X_MAX_EQ_BAND 7
#define CX2072X_MAX_EQ_COEFF 11
#define CX2072X_MAX_DRC_REGS 9
#define CX2072X_MIC_EQ_COEFF 10
#define CX2072X_PLBK_EQ_BAND_NUM 7
#define CX2072X_PLBK_EQ_COEF_LEN 11
#define CX2072X_PLBK_DRC_PARM_LEN 9
#define CX2072X_CLASSD_AMP_LEN 6
/* DAI interfae type */
#define CX2072X_DAI_HIFI 1
#define CX2072X_DAI_DSP 2
#define CX2072X_DAI_DSP_PWM 3 /* 4 ch, including mic and AEC */
enum cx2072x_reg_sample_size {
CX2072X_SAMPLE_SIZE_8_BITS = 0,
CX2072X_SAMPLE_SIZE_16_BITS = 1,
CX2072X_SAMPLE_SIZE_24_BITS = 2,
CX2072X_SAMPLE_SIZE_RESERVED = 3,
};
union cx2072x_reg_i2spcm_ctrl_reg1 {
struct {
u32 rx_data_one_line:1;
u32 rx_ws_pol:1;
u32 rx_ws_wid:7;
u32 rx_frm_len:5;
u32 rx_sa_size:2;
u32 tx_data_one_line:1;
u32 tx_ws_pol:1;
u32 tx_ws_wid:7;
u32 tx_frm_len:5;
u32 tx_sa_size:2;
} r;
u32 ulval;
};
union cx2072x_reg_i2spcm_ctrl_reg2 {
struct {
u32 tx_en_ch1:1;
u32 tx_en_ch2:1;
u32 tx_en_ch3:1;
u32 tx_en_ch4:1;
u32 tx_en_ch5:1;
u32 tx_en_ch6:1;
u32 tx_slot_1:5;
u32 tx_slot_2:5;
u32 tx_slot_3:5;
u32 tx_slot_4:5;
u32 res:1;
u32 tx_data_neg_bclk:1;
u32 tx_master:1;
u32 tx_tri_n:1;
u32 tx_endian_sel:1;
u32 tx_dstart_dly:1;
} r;
u32 ulval;
};
union cx2072x_reg_i2spcm_ctrl_reg3 {
struct {
u32 rx_en_ch1:1;
u32 rx_en_ch2:1;
u32 rx_en_ch3:1;
u32 rx_en_ch4:1;
u32 rx_en_ch5:1;
u32 rx_en_ch6:1;
u32 rx_slot_1:5;
u32 rx_slot_2:5;
u32 rx_slot_3:5;
u32 rx_slot_4:5;
u32 res:1;
u32 rx_data_neg_bclk:1;
u32 rx_master:1;
u32 rx_tri_n:1;
u32 rx_endian_sel:1;
u32 rx_dstart_dly:1;
} r;
u32 ulval;
};
union cx2072x_reg_i2spcm_ctrl_reg4 {
struct {
u32 rx_mute:1;
u32 tx_mute:1;
u32 reserved:1;
u32 dac_34_independent:1;
u32 dac_bclk_lrck_share:1;
u32 bclk_lrck_share_en:1;
u32 reserved2:2;
u32 rx_last_dac_ch_en:1;
u32 rx_last_dac_ch:3;
u32 tx_last_adc_ch_en:1;
u32 tx_last_adc_ch:3;
u32 rx_slot_5:5;
u32 rx_slot_6:5;
u32 reserved3:6;
} r;
u32 ulval;
};
union cx2072x_reg_i2spcm_ctrl_reg5 {
struct {
u32 tx_slot_5:5;
u32 reserved:3;
u32 tx_slot_6:5;
u32 reserved2:3;
u32 reserved3:8;
u32 i2s_pcm_clk_div:7;
u32 i2s_pcm_clk_div_chan_en:1;
} r;
u32 ulval;
};
union cx2072x_reg_i2spcm_ctrl_reg6 {
struct {
u32 reserved:5;
u32 rx_pause_cycles:3;
u32 rx_pause_start_pos:8;
u32 reserved2:5;
u32 tx_pause_cycles:3;
u32 tx_pause_start_pos:8;
} r;
u32 ulval;
};
union cx2072x_reg_digital_bios_test2 {
struct {
u32 pull_down_eapd:2;
u32 input_en_eapd_pad:1;
u32 push_pull_mode:1;
u32 eapd_pad_output_driver:2;
u32 pll_source:1;
u32 i2s_bclk_en:1;
u32 i2s_bclk_invert:1;
u32 pll_ref_clock:1;
u32 class_d_shield_clk:1;
u32 audio_pll_bypass_mode:1;
u32 reserved:4;
} r;
u32 ulval;
};
#endif /* __CX2072X_H__ */

View file

@ -1890,6 +1890,12 @@ static void hdmi_codec_remove(struct snd_soc_component *component)
{
struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component);
struct hdac_device *hdev = hdmi->hdev;
int ret;
ret = snd_hdac_acomp_register_notifier(hdev->bus, NULL);
if (ret < 0)
dev_err(&hdev->dev, "notifier unregister failed: err: %d\n",
ret);
pm_runtime_disable(&hdev->dev);
}
@ -2113,6 +2119,7 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
return -EIO;
}
snd_hdac_codec_link_down(hdev);
snd_hdac_ext_bus_link_put(bus, hlink);
snd_hdac_display_power(bus, hdev->addr, false);
@ -2139,6 +2146,7 @@ static int hdac_hdmi_runtime_resume(struct device *dev)
}
snd_hdac_ext_bus_link_get(bus, hlink);
snd_hdac_codec_link_up(hdev);
snd_hdac_display_power(bus, hdev->addr, true);

View file

@ -270,13 +270,10 @@ static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = {
struct hdmi_codec_priv {
struct hdmi_codec_pdata hcd;
struct snd_soc_dai_driver *daidrv;
struct hdmi_codec_daifmt daifmt[2];
struct mutex current_stream_lock;
struct snd_pcm_substream *current_stream;
uint8_t eld[MAX_ELD_BYTES];
struct snd_pcm_chmap *chmap_info;
unsigned int chmap_idx;
struct mutex lock;
};
static const struct snd_soc_dapm_widget hdmi_widgets[] = {
@ -384,44 +381,22 @@ static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol,
return 0;
}
static int hdmi_codec_new_stream(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
int ret = 0;
mutex_lock(&hcp->current_stream_lock);
if (!hcp->current_stream) {
hcp->current_stream = substream;
} else if (hcp->current_stream != substream) {
dev_err(dai->dev, "Only one simultaneous stream supported!\n");
ret = -EINVAL;
}
mutex_unlock(&hcp->current_stream_lock);
return ret;
}
static int hdmi_codec_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
int ret = 0;
dev_dbg(dai->dev, "%s()\n", __func__);
ret = hdmi_codec_new_stream(substream, dai);
if (ret)
return ret;
ret = mutex_trylock(&hcp->lock);
if (!ret) {
dev_err(dai->dev, "Only one simultaneous stream supported!\n");
return -EINVAL;
}
if (hcp->hcd.ops->audio_startup) {
ret = hcp->hcd.ops->audio_startup(dai->dev->parent, hcp->hcd.data);
if (ret) {
mutex_lock(&hcp->current_stream_lock);
hcp->current_stream = NULL;
mutex_unlock(&hcp->current_stream_lock);
return ret;
}
if (ret)
goto err;
}
if (hcp->hcd.ops->get_eld) {
@ -431,17 +406,18 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,
if (!ret) {
ret = snd_pcm_hw_constraint_eld(substream->runtime,
hcp->eld);
if (ret) {
mutex_lock(&hcp->current_stream_lock);
hcp->current_stream = NULL;
mutex_unlock(&hcp->current_stream_lock);
return ret;
}
if (ret)
goto err;
}
/* Select chmap supported */
hdmi_codec_eld_chmap(hcp);
}
return 0;
err:
/* Release the exclusive lock on error */
mutex_unlock(&hcp->lock);
return ret;
}
static void hdmi_codec_shutdown(struct snd_pcm_substream *substream,
@ -449,16 +425,10 @@ static void hdmi_codec_shutdown(struct snd_pcm_substream *substream,
{
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
dev_dbg(dai->dev, "%s()\n", __func__);
WARN_ON(hcp->current_stream != substream);
hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data);
mutex_lock(&hcp->current_stream_lock);
hcp->current_stream = NULL;
mutex_unlock(&hcp->current_stream_lock);
mutex_unlock(&hcp->lock);
}
static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
@ -466,6 +436,7 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
struct hdmi_codec_params hp = {
.iec = {
.status = { 0 },
@ -510,30 +481,27 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
hp.channels = params_channels(params);
return hcp->hcd.ops->hw_params(dai->dev->parent, hcp->hcd.data,
&hcp->daifmt[dai->id], &hp);
cf, &hp);
}
static int hdmi_codec_set_fmt(struct snd_soc_dai *dai,
unsigned int fmt)
static int hdmi_codec_i2s_set_fmt(struct snd_soc_dai *dai,
unsigned int fmt)
{
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
struct hdmi_codec_daifmt cf = { 0 };
struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
dev_dbg(dai->dev, "%s()\n", __func__);
if (dai->id == DAI_ID_SPDIF)
return 0;
/* Reset daifmt */
memset(cf, 0, sizeof(*cf));
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
cf.bit_clk_master = 1;
cf.frame_clk_master = 1;
cf->bit_clk_master = 1;
cf->frame_clk_master = 1;
break;
case SND_SOC_DAIFMT_CBS_CFM:
cf.frame_clk_master = 1;
cf->frame_clk_master = 1;
break;
case SND_SOC_DAIFMT_CBM_CFS:
cf.bit_clk_master = 1;
cf->bit_clk_master = 1;
break;
case SND_SOC_DAIFMT_CBS_CFS:
break;
@ -545,43 +513,41 @@ static int hdmi_codec_set_fmt(struct snd_soc_dai *dai,
case SND_SOC_DAIFMT_NB_NF:
break;
case SND_SOC_DAIFMT_NB_IF:
cf.frame_clk_inv = 1;
cf->frame_clk_inv = 1;
break;
case SND_SOC_DAIFMT_IB_NF:
cf.bit_clk_inv = 1;
cf->bit_clk_inv = 1;
break;
case SND_SOC_DAIFMT_IB_IF:
cf.frame_clk_inv = 1;
cf.bit_clk_inv = 1;
cf->frame_clk_inv = 1;
cf->bit_clk_inv = 1;
break;
}
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
cf.fmt = HDMI_I2S;
cf->fmt = HDMI_I2S;
break;
case SND_SOC_DAIFMT_DSP_A:
cf.fmt = HDMI_DSP_A;
cf->fmt = HDMI_DSP_A;
break;
case SND_SOC_DAIFMT_DSP_B:
cf.fmt = HDMI_DSP_B;
cf->fmt = HDMI_DSP_B;
break;
case SND_SOC_DAIFMT_RIGHT_J:
cf.fmt = HDMI_RIGHT_J;
cf->fmt = HDMI_RIGHT_J;
break;
case SND_SOC_DAIFMT_LEFT_J:
cf.fmt = HDMI_LEFT_J;
cf->fmt = HDMI_LEFT_J;
break;
case SND_SOC_DAIFMT_AC97:
cf.fmt = HDMI_AC97;
cf->fmt = HDMI_AC97;
break;
default:
dev_err(dai->dev, "Invalid DAI interface format\n");
return -EINVAL;
}
hcp->daifmt[dai->id] = cf;
return 0;
}
@ -589,8 +555,6 @@ static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute)
{
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
dev_dbg(dai->dev, "%s()\n", __func__);
if (hcp->hcd.ops->digital_mute)
return hcp->hcd.ops->digital_mute(dai->dev->parent,
hcp->hcd.data, mute);
@ -598,14 +562,20 @@ static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute)
return 0;
}
static const struct snd_soc_dai_ops hdmi_dai_ops = {
static const struct snd_soc_dai_ops hdmi_codec_i2s_dai_ops = {
.startup = hdmi_codec_startup,
.shutdown = hdmi_codec_shutdown,
.hw_params = hdmi_codec_hw_params,
.set_fmt = hdmi_codec_set_fmt,
.set_fmt = hdmi_codec_i2s_set_fmt,
.digital_mute = hdmi_codec_digital_mute,
};
static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = {
.startup = hdmi_codec_startup,
.shutdown = hdmi_codec_shutdown,
.hw_params = hdmi_codec_hw_params,
.digital_mute = hdmi_codec_digital_mute,
};
#define HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
@ -648,8 +618,6 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
};
int ret;
dev_dbg(dai->dev, "%s()\n", __func__);
ret = snd_pcm_add_chmap_ctls(rtd->pcm, SNDRV_PCM_STREAM_PLAYBACK,
NULL, drv->playback.channels_max, 0,
&hcp->chmap_info);
@ -675,20 +643,52 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
static int hdmi_dai_probe(struct snd_soc_dai *dai)
{
struct snd_soc_dapm_context *dapm;
struct hdmi_codec_daifmt *daifmt;
struct snd_soc_dapm_route route = {
.sink = "TX",
.source = dai->driver->playback.stream_name,
};
int ret;
dapm = snd_soc_component_get_dapm(dai->component);
ret = snd_soc_dapm_add_routes(dapm, &route, 1);
if (ret)
return ret;
return snd_soc_dapm_add_routes(dapm, &route, 1);
daifmt = kzalloc(sizeof(*daifmt), GFP_KERNEL);
if (!daifmt)
return -ENOMEM;
dai->playback_dma_data = daifmt;
return 0;
}
static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)
{
struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
int ret;
ret = hdmi_dai_probe(dai);
if (ret)
return ret;
cf = dai->playback_dma_data;
cf->fmt = HDMI_SPDIF;
return 0;
}
static int hdmi_codec_dai_remove(struct snd_soc_dai *dai)
{
kfree(dai->playback_dma_data);
return 0;
}
static const struct snd_soc_dai_driver hdmi_i2s_dai = {
.name = "i2s-hifi",
.id = DAI_ID_I2S,
.probe = hdmi_dai_probe,
.remove = hdmi_codec_dai_remove,
.playback = {
.stream_name = "I2S Playback",
.channels_min = 2,
@ -697,14 +697,15 @@ static const struct snd_soc_dai_driver hdmi_i2s_dai = {
.formats = I2S_FORMATS,
.sig_bits = 24,
},
.ops = &hdmi_dai_ops,
.ops = &hdmi_codec_i2s_dai_ops,
.pcm_new = hdmi_codec_pcm_new,
};
static const struct snd_soc_dai_driver hdmi_spdif_dai = {
.name = "spdif-hifi",
.id = DAI_ID_SPDIF,
.probe = hdmi_dai_probe,
.probe = hdmi_dai_spdif_probe,
.remove = hdmi_codec_dai_remove,
.playback = {
.stream_name = "SPDIF Playback",
.channels_min = 2,
@ -712,7 +713,7 @@ static const struct snd_soc_dai_driver hdmi_spdif_dai = {
.rates = HDMI_RATES,
.formats = SPDIF_FORMATS,
},
.ops = &hdmi_dai_ops,
.ops = &hdmi_codec_spdif_dai_ops,
.pcm_new = hdmi_codec_pcm_new,
};
@ -741,13 +742,12 @@ static const struct snd_soc_component_driver hdmi_driver = {
static int hdmi_codec_probe(struct platform_device *pdev)
{
struct hdmi_codec_pdata *hcd = pdev->dev.platform_data;
struct snd_soc_dai_driver *daidrv;
struct device *dev = &pdev->dev;
struct hdmi_codec_priv *hcp;
int dai_count, i = 0;
int ret;
dev_dbg(dev, "%s()\n", __func__);
if (!hcd) {
dev_err(dev, "%s: No platform data\n", __func__);
return -EINVAL;
@ -765,29 +765,25 @@ static int hdmi_codec_probe(struct platform_device *pdev)
return -ENOMEM;
hcp->hcd = *hcd;
mutex_init(&hcp->current_stream_lock);
mutex_init(&hcp->lock);
hcp->daidrv = devm_kcalloc(dev, dai_count, sizeof(*hcp->daidrv),
GFP_KERNEL);
if (!hcp->daidrv)
daidrv = devm_kcalloc(dev, dai_count, sizeof(*daidrv), GFP_KERNEL);
if (!daidrv)
return -ENOMEM;
if (hcd->i2s) {
hcp->daidrv[i] = hdmi_i2s_dai;
hcp->daidrv[i].playback.channels_max =
hcd->max_i2s_channels;
daidrv[i] = hdmi_i2s_dai;
daidrv[i].playback.channels_max = hcd->max_i2s_channels;
i++;
}
if (hcd->spdif) {
hcp->daidrv[i] = hdmi_spdif_dai;
hcp->daifmt[DAI_ID_SPDIF].fmt = HDMI_SPDIF;
}
if (hcd->spdif)
daidrv[i] = hdmi_spdif_dai;
dev_set_drvdata(dev, hcp);
ret = devm_snd_soc_register_component(dev, &hdmi_driver, hcp->daidrv,
dai_count);
ret = devm_snd_soc_register_component(dev, &hdmi_driver, daidrv,
dai_count);
if (ret) {
dev_err(dev, "%s: snd_soc_register_component() failed (%d)\n",
__func__, ret);

4177
sound/soc/codecs/madera.c Normal file

File diff suppressed because it is too large Load diff

442
sound/soc/codecs/madera.h Normal file
View file

@ -0,0 +1,442 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Cirrus Logic Madera class codecs common support
*
* Copyright (C) 2015-2018 Cirrus Logic, Inc. and
* Cirrus Logic International Semiconductor Ltd.
*/
#ifndef ASOC_MADERA_H
#define ASOC_MADERA_H
#include <linux/completion.h>
#include <sound/soc.h>
#include <sound/madera-pdata.h>
#include "wm_adsp.h"
#define MADERA_FLL1_REFCLK 1
#define MADERA_FLL2_REFCLK 2
#define MADERA_FLL3_REFCLK 3
#define MADERA_FLLAO_REFCLK 4
#define MADERA_FLL1_SYNCCLK 5
#define MADERA_FLL2_SYNCCLK 6
#define MADERA_FLL3_SYNCCLK 7
#define MADERA_FLLAO_SYNCCLK 8
#define MADERA_FLL_SRC_NONE -1
#define MADERA_FLL_SRC_MCLK1 0
#define MADERA_FLL_SRC_MCLK2 1
#define MADERA_FLL_SRC_SLIMCLK 3
#define MADERA_FLL_SRC_FLL1 4
#define MADERA_FLL_SRC_FLL2 5
#define MADERA_FLL_SRC_AIF1BCLK 8
#define MADERA_FLL_SRC_AIF2BCLK 9
#define MADERA_FLL_SRC_AIF3BCLK 10
#define MADERA_FLL_SRC_AIF4BCLK 11
#define MADERA_FLL_SRC_AIF1LRCLK 12
#define MADERA_FLL_SRC_AIF2LRCLK 13
#define MADERA_FLL_SRC_AIF3LRCLK 14
#define MADERA_FLL_SRC_AIF4LRCLK 15
#define MADERA_CLK_SYSCLK_1 1
#define MADERA_CLK_ASYNCCLK_1 2
#define MADERA_CLK_OPCLK 3
#define MADERA_CLK_ASYNC_OPCLK 4
#define MADERA_CLK_SYSCLK_2 5
#define MADERA_CLK_SYSCLK_3 6
#define MADERA_CLK_ASYNCCLK_2 7
#define MADERA_CLK_DSPCLK 8
#define MADERA_CLK_SRC_MCLK1 0x0
#define MADERA_CLK_SRC_MCLK2 0x1
#define MADERA_CLK_SRC_FLL1 0x4
#define MADERA_CLK_SRC_FLL2 0x5
#define MADERA_CLK_SRC_FLL3 0x6
#define MADERA_CLK_SRC_FLLAO_HI 0x7
#define MADERA_CLK_SRC_FLL1_DIV6 0x7
#define MADERA_CLK_SRC_AIF1BCLK 0x8
#define MADERA_CLK_SRC_AIF2BCLK 0x9
#define MADERA_CLK_SRC_AIF3BCLK 0xA
#define MADERA_CLK_SRC_AIF4BCLK 0xB
#define MADERA_CLK_SRC_FLLAO 0xF
#define MADERA_MIXER_VOL_MASK 0x00FE
#define MADERA_MIXER_VOL_SHIFT 1
#define MADERA_MIXER_VOL_WIDTH 7
#define MADERA_DOM_GRP_FX 0
#define MADERA_DOM_GRP_ASRC1 1
#define MADERA_DOM_GRP_ASRC2 2
#define MADERA_DOM_GRP_ISRC1 3
#define MADERA_DOM_GRP_ISRC2 4
#define MADERA_DOM_GRP_ISRC3 5
#define MADERA_DOM_GRP_ISRC4 6
#define MADERA_DOM_GRP_OUT 7
#define MADERA_DOM_GRP_SPD 8
#define MADERA_DOM_GRP_DSP1 9
#define MADERA_DOM_GRP_DSP2 10
#define MADERA_DOM_GRP_DSP3 11
#define MADERA_DOM_GRP_DSP4 12
#define MADERA_DOM_GRP_DSP5 13
#define MADERA_DOM_GRP_DSP6 14
#define MADERA_DOM_GRP_DSP7 15
#define MADERA_DOM_GRP_AIF1 16
#define MADERA_DOM_GRP_AIF2 17
#define MADERA_DOM_GRP_AIF3 18
#define MADERA_DOM_GRP_AIF4 19
#define MADERA_DOM_GRP_SLIMBUS 20
#define MADERA_DOM_GRP_PWM 21
#define MADERA_DOM_GRP_DFC 22
#define MADERA_N_DOM_GRPS 23
#define MADERA_MAX_DAI 11
#define MADERA_MAX_ADSP 7
#define MADERA_NUM_MIXER_INPUTS 148
struct madera;
struct wm_adsp;
struct madera_voice_trigger_info {
/** Which core triggered, 1-based (1 = DSP1, ...) */
int core_num;
};
struct madera_dai_priv {
int clk;
struct snd_pcm_hw_constraint_list constraint;
};
struct madera_priv {
struct wm_adsp adsp[MADERA_MAX_ADSP];
struct madera *madera;
struct device *dev;
int sysclk;
int asyncclk;
int dspclk;
struct madera_dai_priv dai[MADERA_MAX_DAI];
int num_inputs;
unsigned int in_pending;
unsigned int out_up_pending;
unsigned int out_up_delay;
unsigned int out_down_pending;
unsigned int out_down_delay;
unsigned int adsp_rate_cache[MADERA_MAX_ADSP];
struct mutex rate_lock;
int tdm_width[MADERA_MAX_AIF];
int tdm_slots[MADERA_MAX_AIF];
int domain_group_ref[MADERA_N_DOM_GRPS];
};
struct madera_fll_cfg {
int n;
unsigned int theta;
unsigned int lambda;
int refdiv;
int fratio;
int gain;
int alt_gain;
};
struct madera_fll {
struct madera *madera;
int id;
unsigned int base;
unsigned int fout;
int sync_src;
unsigned int sync_freq;
int ref_src;
unsigned int ref_freq;
struct madera_fll_cfg ref_cfg;
};
struct madera_enum {
struct soc_enum mixer_enum;
int val;
};
extern const unsigned int madera_ana_tlv[];
extern const unsigned int madera_eq_tlv[];
extern const unsigned int madera_digital_tlv[];
extern const unsigned int madera_noise_tlv[];
extern const unsigned int madera_ng_tlv[];
extern const unsigned int madera_mixer_tlv[];
extern const char * const madera_mixer_texts[MADERA_NUM_MIXER_INPUTS];
extern const unsigned int madera_mixer_values[MADERA_NUM_MIXER_INPUTS];
#define MADERA_GAINMUX_CONTROLS(name, base) \
SOC_SINGLE_RANGE_TLV(name " Input Volume", base + 1, \
MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \
madera_mixer_tlv)
#define MADERA_MIXER_CONTROLS(name, base) \
SOC_SINGLE_RANGE_TLV(name " Input 1 Volume", base + 1, \
MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \
madera_mixer_tlv), \
SOC_SINGLE_RANGE_TLV(name " Input 2 Volume", base + 3, \
MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \
madera_mixer_tlv), \
SOC_SINGLE_RANGE_TLV(name " Input 3 Volume", base + 5, \
MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \
madera_mixer_tlv), \
SOC_SINGLE_RANGE_TLV(name " Input 4 Volume", base + 7, \
MADERA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \
madera_mixer_tlv)
#define MADERA_MUX_ENUM_DECL(name, reg) \
SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL( \
name, reg, 0, 0xff, madera_mixer_texts, madera_mixer_values)
#define MADERA_MUX_CTL_DECL(name) \
const struct snd_kcontrol_new name##_mux = \
SOC_DAPM_ENUM("Route", name##_enum)
#define MADERA_MUX_ENUMS(name, base_reg) \
static MADERA_MUX_ENUM_DECL(name##_enum, base_reg); \
static MADERA_MUX_CTL_DECL(name)
#define MADERA_MIXER_ENUMS(name, base_reg) \
MADERA_MUX_ENUMS(name##_in1, base_reg); \
MADERA_MUX_ENUMS(name##_in2, base_reg + 2); \
MADERA_MUX_ENUMS(name##_in3, base_reg + 4); \
MADERA_MUX_ENUMS(name##_in4, base_reg + 6)
#define MADERA_DSP_AUX_ENUMS(name, base_reg) \
MADERA_MUX_ENUMS(name##_aux1, base_reg); \
MADERA_MUX_ENUMS(name##_aux2, base_reg + 8); \
MADERA_MUX_ENUMS(name##_aux3, base_reg + 16); \
MADERA_MUX_ENUMS(name##_aux4, base_reg + 24); \
MADERA_MUX_ENUMS(name##_aux5, base_reg + 32); \
MADERA_MUX_ENUMS(name##_aux6, base_reg + 40)
#define MADERA_MUX(name, ctrl) \
SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
#define MADERA_MUX_WIDGETS(name, name_str) \
MADERA_MUX(name_str " Input 1", &name##_mux)
#define MADERA_MIXER_WIDGETS(name, name_str) \
MADERA_MUX(name_str " Input 1", &name##_in1_mux), \
MADERA_MUX(name_str " Input 2", &name##_in2_mux), \
MADERA_MUX(name_str " Input 3", &name##_in3_mux), \
MADERA_MUX(name_str " Input 4", &name##_in4_mux), \
SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
#define MADERA_DSP_WIDGETS(name, name_str) \
MADERA_MIXER_WIDGETS(name##L, name_str "L"), \
MADERA_MIXER_WIDGETS(name##R, name_str "R"), \
MADERA_MUX(name_str " Aux 1", &name##_aux1_mux), \
MADERA_MUX(name_str " Aux 2", &name##_aux2_mux), \
MADERA_MUX(name_str " Aux 3", &name##_aux3_mux), \
MADERA_MUX(name_str " Aux 4", &name##_aux4_mux), \
MADERA_MUX(name_str " Aux 5", &name##_aux5_mux), \
MADERA_MUX(name_str " Aux 6", &name##_aux6_mux)
#define MADERA_MUX_ROUTES(widget, name) \
{ widget, NULL, name " Input 1" }, \
MADERA_MIXER_INPUT_ROUTES(name " Input 1")
#define MADERA_MIXER_ROUTES(widget, name) \
{ widget, NULL, name " Mixer" }, \
{ name " Mixer", NULL, name " Input 1" }, \
{ name " Mixer", NULL, name " Input 2" }, \
{ name " Mixer", NULL, name " Input 3" }, \
{ name " Mixer", NULL, name " Input 4" }, \
MADERA_MIXER_INPUT_ROUTES(name " Input 1"), \
MADERA_MIXER_INPUT_ROUTES(name " Input 2"), \
MADERA_MIXER_INPUT_ROUTES(name " Input 3"), \
MADERA_MIXER_INPUT_ROUTES(name " Input 4")
#define MADERA_DSP_ROUTES(name) \
{ name, NULL, name " Preloader"}, \
{ name " Preload", NULL, name " Preloader"}, \
{ name, NULL, "SYSCLK"}, \
{ name, NULL, "DSPCLK"}, \
{ name, NULL, name " Aux 1" }, \
{ name, NULL, name " Aux 2" }, \
{ name, NULL, name " Aux 3" }, \
{ name, NULL, name " Aux 4" }, \
{ name, NULL, name " Aux 5" }, \
{ name, NULL, name " Aux 6" }, \
MADERA_MIXER_INPUT_ROUTES(name " Aux 1"), \
MADERA_MIXER_INPUT_ROUTES(name " Aux 2"), \
MADERA_MIXER_INPUT_ROUTES(name " Aux 3"), \
MADERA_MIXER_INPUT_ROUTES(name " Aux 4"), \
MADERA_MIXER_INPUT_ROUTES(name " Aux 5"), \
MADERA_MIXER_INPUT_ROUTES(name " Aux 6"), \
MADERA_MIXER_ROUTES(name, name "L"), \
MADERA_MIXER_ROUTES(name, name "R")
#define MADERA_RATE_ENUM(xname, xenum) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
.info = snd_soc_info_enum_double, \
.get = snd_soc_get_enum_double, .put = madera_rate_put, \
.private_value = (unsigned long)&xenum }
#define MADERA_EQ_CONTROL(xname, xbase) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
.put = madera_eq_coeff_put, .private_value = \
((unsigned long)&(struct soc_bytes) { .base = xbase, \
.num_regs = 20, .mask = ~MADERA_EQ1_B1_MODE }) }
#define MADERA_LHPF_CONTROL(xname, xbase) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
.put = madera_lhpf_coeff_put, .private_value = \
((unsigned long)&(struct soc_bytes) { .base = xbase, \
.num_regs = 1 }) }
#define MADERA_RATES SNDRV_PCM_RATE_KNOT
#define MADERA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
#define MADERA_OSR_ENUM_SIZE 5
#define MADERA_SYNC_RATE_ENUM_SIZE 3
#define MADERA_ASYNC_RATE_ENUM_SIZE 2
#define MADERA_RATE_ENUM_SIZE \
(MADERA_SYNC_RATE_ENUM_SIZE + MADERA_ASYNC_RATE_ENUM_SIZE)
#define MADERA_SAMPLE_RATE_ENUM_SIZE 16
#define MADERA_DFC_TYPE_ENUM_SIZE 5
#define MADERA_DFC_WIDTH_ENUM_SIZE 5
extern const struct snd_soc_dai_ops madera_dai_ops;
extern const struct snd_soc_dai_ops madera_simple_dai_ops;
extern const struct snd_kcontrol_new madera_inmux[];
extern const struct snd_kcontrol_new madera_inmode[];
extern const char * const madera_rate_text[MADERA_RATE_ENUM_SIZE];
extern const unsigned int madera_rate_val[MADERA_RATE_ENUM_SIZE];
extern const struct soc_enum madera_sample_rate[];
extern const struct soc_enum madera_isrc_fsl[];
extern const struct soc_enum madera_isrc_fsh[];
extern const struct soc_enum madera_asrc1_rate[];
extern const struct soc_enum madera_asrc2_rate[];
extern const struct soc_enum madera_dfc_width[];
extern const struct soc_enum madera_dfc_type[];
extern const struct soc_enum madera_in_vi_ramp;
extern const struct soc_enum madera_in_vd_ramp;
extern const struct soc_enum madera_out_vi_ramp;
extern const struct soc_enum madera_out_vd_ramp;
extern const struct soc_enum madera_lhpf1_mode;
extern const struct soc_enum madera_lhpf2_mode;
extern const struct soc_enum madera_lhpf3_mode;
extern const struct soc_enum madera_lhpf4_mode;
extern const struct soc_enum madera_ng_hold;
extern const struct soc_enum madera_in_hpf_cut_enum;
extern const struct soc_enum madera_in_dmic_osr[];
extern const struct soc_enum madera_output_anc_src[];
extern const struct soc_enum madera_anc_input_src[];
extern const struct soc_enum madera_anc_ng_enum;
extern const struct snd_kcontrol_new madera_dsp_trigger_output_mux[];
extern const struct snd_kcontrol_new madera_drc_activity_output_mux[];
extern const struct snd_kcontrol_new madera_adsp_rate_controls[];
int madera_dfc_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int madera_lp_mode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int madera_out1_demux_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int madera_out1_demux_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int madera_rate_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int madera_eq_coeff_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int madera_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int madera_sysclk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
int madera_spk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
int madera_in_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
int madera_out_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
int madera_hp_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
int madera_anc_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
int madera_domain_clk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
int madera_set_adsp_clk(struct madera_priv *priv, int dsp_num,
unsigned int freq);
int madera_set_sysclk(struct snd_soc_component *component, int clk_id,
int source, unsigned int freq, int dir);
int madera_init_fll(struct madera *madera, int id, int base,
struct madera_fll *fll);
int madera_set_fll_refclk(struct madera_fll *fll, int source,
unsigned int fref, unsigned int fout);
int madera_set_fll_syncclk(struct madera_fll *fll, int source,
unsigned int fref, unsigned int fout);
int madera_set_fll_ao_refclk(struct madera_fll *fll, int source,
unsigned int fin, unsigned int fout);
int madera_core_init(struct madera_priv *priv);
int madera_core_free(struct madera_priv *priv);
int madera_init_overheat(struct madera_priv *priv);
int madera_free_overheat(struct madera_priv *priv);
int madera_init_inputs(struct snd_soc_component *component);
int madera_init_outputs(struct snd_soc_component *component, int n_mono_routes);
int madera_init_bus_error_irq(struct madera_priv *priv, int dsp_num,
irq_handler_t handler);
void madera_free_bus_error_irq(struct madera_priv *priv, int dsp_num);
int madera_init_dai(struct madera_priv *priv, int dai);
int madera_set_output_mode(struct snd_soc_component *component, int output,
bool differential);
/* Following functions are for use by machine drivers */
static inline int madera_register_notifier(struct snd_soc_component *component,
struct notifier_block *nb)
{
struct madera_priv *priv = snd_soc_component_get_drvdata(component);
struct madera *madera = priv->madera;
return blocking_notifier_chain_register(&madera->notifier, nb);
}
static inline int
madera_unregister_notifier(struct snd_soc_component *component,
struct notifier_block *nb)
{
struct madera_priv *priv = snd_soc_component_get_drvdata(component);
struct madera *madera = priv->madera;
return blocking_notifier_chain_unregister(&madera->notifier, nb);
}
#endif

View file

@ -19,24 +19,42 @@
#include <sound/soc-dai.h>
#include <sound/soc-dapm.h>
struct max98357a_priv {
struct delayed_work enable_sdmode_work;
struct gpio_desc *sdmode;
unsigned int sdmode_delay;
};
static void max98357a_enable_sdmode_work(struct work_struct *work)
{
struct max98357a_priv *max98357a =
container_of(work, struct max98357a_priv,
enable_sdmode_work.work);
gpiod_set_value(max98357a->sdmode, 1);
}
static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
struct gpio_desc *sdmode = snd_soc_dai_get_drvdata(dai);
struct max98357a_priv *max98357a = snd_soc_dai_get_drvdata(dai);
if (!sdmode)
if (!max98357a->sdmode)
return 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
gpiod_set_value(sdmode, 1);
queue_delayed_work(system_power_efficient_wq,
&max98357a->enable_sdmode_work,
msecs_to_jiffies(max98357a->sdmode_delay));
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
gpiod_set_value(sdmode, 0);
cancel_delayed_work_sync(&max98357a->enable_sdmode_work);
gpiod_set_value(max98357a->sdmode, 0);
break;
}
@ -51,21 +69,7 @@ static const struct snd_soc_dapm_route max98357a_dapm_routes[] = {
{"Speaker", NULL, "HiFi Playback"},
};
static int max98357a_component_probe(struct snd_soc_component *component)
{
struct gpio_desc *sdmode;
sdmode = devm_gpiod_get_optional(component->dev, "sdmode", GPIOD_OUT_LOW);
if (IS_ERR(sdmode))
return PTR_ERR(sdmode);
snd_soc_component_set_drvdata(component, sdmode);
return 0;
}
static const struct snd_soc_component_driver max98357a_component_driver = {
.probe = max98357a_component_probe,
.dapm_widgets = max98357a_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(max98357a_dapm_widgets),
.dapm_routes = max98357a_dapm_routes,
@ -104,16 +108,39 @@ static struct snd_soc_dai_driver max98357a_dai_driver = {
static int max98357a_platform_probe(struct platform_device *pdev)
{
struct max98357a_priv *max98357a;
int ret;
max98357a = devm_kzalloc(&pdev->dev, sizeof(*max98357a), GFP_KERNEL);
if (!max98357a)
return -ENOMEM;
max98357a->sdmode = devm_gpiod_get_optional(&pdev->dev,
"sdmode", GPIOD_OUT_LOW);
if (IS_ERR(max98357a->sdmode))
return PTR_ERR(max98357a->sdmode);
ret = device_property_read_u32(&pdev->dev, "sdmode-delay",
&max98357a->sdmode_delay);
if (ret) {
max98357a->sdmode_delay = 0;
dev_dbg(&pdev->dev,
"no optional property 'sdmode-delay' found, default: no delay\n");
}
dev_set_drvdata(&pdev->dev, max98357a);
INIT_DELAYED_WORK(&max98357a->enable_sdmode_work,
max98357a_enable_sdmode_work);
return devm_snd_soc_register_component(&pdev->dev,
&max98357a_component_driver,
&max98357a_dai_driver, 1);
}
static int max98357a_platform_remove(struct platform_device *pdev)
{
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id max98357a_device_id[] = {
{ .compatible = "maxim,max98357a" },
@ -137,7 +164,6 @@ static struct platform_driver max98357a_platform_driver = {
.acpi_match_table = ACPI_PTR(max98357a_acpi_match),
},
.probe = max98357a_platform_probe,
.remove = max98357a_platform_remove,
};
module_platform_driver(max98357a_platform_driver);

View file

@ -187,6 +187,43 @@
#define MSM8916_WCD_DIGITAL_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S32_LE)
/* Codec supports 2 IIR filters */
enum {
IIR1 = 0,
IIR2,
IIR_MAX,
};
/* Codec supports 5 bands */
enum {
BAND1 = 0,
BAND2,
BAND3,
BAND4,
BAND5,
BAND_MAX,
};
#define WCD_IIR_FILTER_SIZE (sizeof(u32)*BAND_MAX)
#define WCD_IIR_FILTER_CTL(xname, iidx, bidx) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = wcd_iir_filter_info, \
.get = msm8x16_wcd_get_iir_band_audio_mixer, \
.put = msm8x16_wcd_put_iir_band_audio_mixer, \
.private_value = (unsigned long)&(struct wcd_iir_filter_ctl) { \
.iir_idx = iidx, \
.band_idx = bidx, \
.bytes_ext = {.max = WCD_IIR_FILTER_SIZE, }, \
} \
}
struct wcd_iir_filter_ctl {
unsigned int iir_idx;
unsigned int band_idx;
struct soc_bytes_ext bytes_ext;
};
struct msm8916_wcd_digital_priv {
struct clk *ahbclk, *mclk;
};
@ -298,6 +335,161 @@ static SOC_ENUM_SINGLE_DECL(rx2_dcb_cutoff_enum, LPASS_CDC_RX2_B4_CTL, 0,
static SOC_ENUM_SINGLE_DECL(rx3_dcb_cutoff_enum, LPASS_CDC_RX3_B4_CTL, 0,
dc_blocker_cutoff_text);
static int msm8x16_wcd_codec_set_iir_gain(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
int value = 0, reg = 0;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
if (w->shift == 0)
reg = LPASS_CDC_IIR1_GAIN_B1_CTL;
else if (w->shift == 1)
reg = LPASS_CDC_IIR2_GAIN_B1_CTL;
value = snd_soc_component_read32(component, reg);
snd_soc_component_write(component, reg, value);
break;
default:
break;
}
return 0;
}
static uint32_t get_iir_band_coeff(struct snd_soc_component *component,
int iir_idx, int band_idx,
int coeff_idx)
{
uint32_t value = 0;
/* Address does not automatically update if reading */
snd_soc_component_write(component,
(LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
((band_idx * BAND_MAX + coeff_idx)
* sizeof(uint32_t)) & 0x7F);
value |= snd_soc_component_read32(component,
(LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx));
snd_soc_component_write(component,
(LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
((band_idx * BAND_MAX + coeff_idx)
* sizeof(uint32_t) + 1) & 0x7F);
value |= (snd_soc_component_read32(component,
(LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 8);
snd_soc_component_write(component,
(LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
((band_idx * BAND_MAX + coeff_idx)
* sizeof(uint32_t) + 2) & 0x7F);
value |= (snd_soc_component_read32(component,
(LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 16);
snd_soc_component_write(component,
(LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
((band_idx * BAND_MAX + coeff_idx)
* sizeof(uint32_t) + 3) & 0x7F);
/* Mask bits top 2 bits since they are reserved */
value |= ((snd_soc_component_read32(component,
(LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) & 0x3f) << 24);
return value;
}
static int msm8x16_wcd_get_iir_band_audio_mixer(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct wcd_iir_filter_ctl *ctl =
(struct wcd_iir_filter_ctl *)kcontrol->private_value;
struct soc_bytes_ext *params = &ctl->bytes_ext;
int iir_idx = ctl->iir_idx;
int band_idx = ctl->band_idx;
u32 coeff[BAND_MAX];
coeff[0] = get_iir_band_coeff(component, iir_idx, band_idx, 0);
coeff[1] = get_iir_band_coeff(component, iir_idx, band_idx, 1);
coeff[2] = get_iir_band_coeff(component, iir_idx, band_idx, 2);
coeff[3] = get_iir_band_coeff(component, iir_idx, band_idx, 3);
coeff[4] = get_iir_band_coeff(component, iir_idx, band_idx, 4);
memcpy(ucontrol->value.bytes.data, &coeff[0], params->max);
return 0;
}
static void set_iir_band_coeff(struct snd_soc_component *component,
int iir_idx, int band_idx,
uint32_t value)
{
snd_soc_component_write(component,
(LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx),
(value & 0xFF));
snd_soc_component_write(component,
(LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx),
(value >> 8) & 0xFF);
snd_soc_component_write(component,
(LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx),
(value >> 16) & 0xFF);
/* Mask top 2 bits, 7-8 are reserved */
snd_soc_component_write(component,
(LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx),
(value >> 24) & 0x3F);
}
static int msm8x16_wcd_put_iir_band_audio_mixer(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct wcd_iir_filter_ctl *ctl =
(struct wcd_iir_filter_ctl *)kcontrol->private_value;
struct soc_bytes_ext *params = &ctl->bytes_ext;
int iir_idx = ctl->iir_idx;
int band_idx = ctl->band_idx;
u32 coeff[BAND_MAX];
memcpy(&coeff[0], ucontrol->value.bytes.data, params->max);
/* Mask top bit it is reserved */
/* Updates addr automatically for each B2 write */
snd_soc_component_write(component,
(LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
(band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
set_iir_band_coeff(component, iir_idx, band_idx, coeff[0]);
set_iir_band_coeff(component, iir_idx, band_idx, coeff[1]);
set_iir_band_coeff(component, iir_idx, band_idx, coeff[2]);
set_iir_band_coeff(component, iir_idx, band_idx, coeff[3]);
set_iir_band_coeff(component, iir_idx, band_idx, coeff[4]);
return 0;
}
static int wcd_iir_filter_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *ucontrol)
{
struct wcd_iir_filter_ctl *ctl =
(struct wcd_iir_filter_ctl *)kcontrol->private_value;
struct soc_bytes_ext *params = &ctl->bytes_ext;
ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES;
ucontrol->count = params->max;
return 0;
}
static const struct snd_kcontrol_new msm8916_wcd_digital_snd_controls[] = {
SOC_SINGLE_S8_TLV("RX1 Digital Volume", LPASS_CDC_RX1_VOL_CTL_B2_CTL,
-128, 127, digital_gain),
@ -322,6 +514,44 @@ static const struct snd_kcontrol_new msm8916_wcd_digital_snd_controls[] = {
SOC_SINGLE("RX1 Mute Switch", LPASS_CDC_RX1_B6_CTL, 0, 1, 0),
SOC_SINGLE("RX2 Mute Switch", LPASS_CDC_RX2_B6_CTL, 0, 1, 0),
SOC_SINGLE("RX3 Mute Switch", LPASS_CDC_RX3_B6_CTL, 0, 1, 0),
SOC_SINGLE("IIR1 Band1 Switch", LPASS_CDC_IIR1_CTL, 0, 1, 0),
SOC_SINGLE("IIR1 Band2 Switch", LPASS_CDC_IIR1_CTL, 1, 1, 0),
SOC_SINGLE("IIR1 Band3 Switch", LPASS_CDC_IIR1_CTL, 2, 1, 0),
SOC_SINGLE("IIR1 Band4 Switch", LPASS_CDC_IIR1_CTL, 3, 1, 0),
SOC_SINGLE("IIR1 Band5 Switch", LPASS_CDC_IIR1_CTL, 4, 1, 0),
SOC_SINGLE("IIR2 Band1 Switch", LPASS_CDC_IIR2_CTL, 0, 1, 0),
SOC_SINGLE("IIR2 Band2 Switch", LPASS_CDC_IIR2_CTL, 1, 1, 0),
SOC_SINGLE("IIR2 Band3 Switch", LPASS_CDC_IIR2_CTL, 2, 1, 0),
SOC_SINGLE("IIR2 Band4 Switch", LPASS_CDC_IIR2_CTL, 3, 1, 0),
SOC_SINGLE("IIR2 Band5 Switch", LPASS_CDC_IIR2_CTL, 4, 1, 0),
WCD_IIR_FILTER_CTL("IIR1 Band1", IIR1, BAND1),
WCD_IIR_FILTER_CTL("IIR1 Band2", IIR1, BAND2),
WCD_IIR_FILTER_CTL("IIR1 Band3", IIR1, BAND3),
WCD_IIR_FILTER_CTL("IIR1 Band4", IIR1, BAND4),
WCD_IIR_FILTER_CTL("IIR1 Band5", IIR1, BAND5),
WCD_IIR_FILTER_CTL("IIR2 Band1", IIR2, BAND1),
WCD_IIR_FILTER_CTL("IIR2 Band2", IIR2, BAND2),
WCD_IIR_FILTER_CTL("IIR2 Band3", IIR2, BAND3),
WCD_IIR_FILTER_CTL("IIR2 Band4", IIR2, BAND4),
WCD_IIR_FILTER_CTL("IIR2 Band5", IIR2, BAND5),
SOC_SINGLE_SX_TLV("IIR1 INP1 Volume", LPASS_CDC_IIR1_GAIN_B1_CTL,
0, -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP2 Volume", LPASS_CDC_IIR1_GAIN_B2_CTL,
0, -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP3 Volume", LPASS_CDC_IIR1_GAIN_B3_CTL,
0, -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP4 Volume", LPASS_CDC_IIR1_GAIN_B4_CTL,
0, -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR2 INP1 Volume", LPASS_CDC_IIR2_GAIN_B1_CTL,
0, -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR2 INP2 Volume", LPASS_CDC_IIR2_GAIN_B2_CTL,
0, -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR2 INP3 Volume", LPASS_CDC_IIR2_GAIN_B3_CTL,
0, -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR2 INP4 Volume", LPASS_CDC_IIR2_GAIN_B4_CTL,
0, -84, 40, digital_gain),
};
static int msm8916_wcd_digital_enable_interpolator(
@ -448,6 +678,24 @@ static int msm8916_wcd_digital_enable_dmic(struct snd_soc_dapm_widget *w,
return 0;
}
static const char * const iir_inp1_text[] = {
"ZERO", "DEC1", "DEC2", "RX1", "RX2", "RX3"
};
static const struct soc_enum iir1_inp1_mux_enum =
SOC_ENUM_SINGLE(LPASS_CDC_CONN_EQ1_B1_CTL,
0, 6, iir_inp1_text);
static const struct soc_enum iir2_inp1_mux_enum =
SOC_ENUM_SINGLE(LPASS_CDC_CONN_EQ2_B1_CTL,
0, 6, iir_inp1_text);
static const struct snd_kcontrol_new iir1_inp1_mux =
SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
static const struct snd_kcontrol_new iir2_inp1_mux =
SOC_DAPM_ENUM("IIR2 INP1 Mux", iir2_inp1_mux_enum);
static const struct snd_soc_dapm_widget msm8916_wcd_digital_dapm_widgets[] = {
/*RX stuff */
SND_SOC_DAPM_AIF_IN("I2S RX1", NULL, 0, SND_SOC_NOPM, 0, 0),
@ -534,6 +782,15 @@ static const struct snd_soc_dapm_widget msm8916_wcd_digital_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Digital Mic1", NULL),
SND_SOC_DAPM_MIC("Digital Mic2", NULL),
/* Sidetone */
SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
SND_SOC_DAPM_PGA_E("IIR1", LPASS_CDC_CLK_SD_CTL, 0, 0, NULL, 0,
msm8x16_wcd_codec_set_iir_gain, SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_MUX("IIR2 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp1_mux),
SND_SOC_DAPM_PGA_E("IIR2", LPASS_CDC_CLK_SD_CTL, 1, 0, NULL, 0,
msm8x16_wcd_codec_set_iir_gain, SND_SOC_DAPM_POST_PMU),
};
static int msm8916_wcd_digital_get_clks(struct platform_device *pdev,
@ -708,10 +965,14 @@ static const struct snd_soc_dapm_route msm8916_wcd_digital_audio_map[] = {
{"RX1 MIX1 INP1", "RX1", "I2S RX1"},
{"RX1 MIX1 INP1", "RX2", "I2S RX2"},
{"RX1 MIX1 INP1", "RX3", "I2S RX3"},
{"RX1 MIX1 INP1", "IIR1", "IIR1"},
{"RX1 MIX1 INP1", "IIR2", "IIR2"},
{"RX1 MIX1 INP2", "RX1", "I2S RX1"},
{"RX1 MIX1 INP2", "RX2", "I2S RX2"},
{"RX1 MIX1 INP2", "RX3", "I2S RX3"},
{"RX1 MIX1 INP2", "IIR1", "IIR1"},
{"RX1 MIX1 INP2", "IIR2", "IIR2"},
{"RX1 MIX1 INP3", "RX1", "I2S RX1"},
{"RX1 MIX1 INP3", "RX2", "I2S RX2"},
@ -728,10 +989,14 @@ static const struct snd_soc_dapm_route msm8916_wcd_digital_audio_map[] = {
{"RX2 MIX1 INP1", "RX1", "I2S RX1"},
{"RX2 MIX1 INP1", "RX2", "I2S RX2"},
{"RX2 MIX1 INP1", "RX3", "I2S RX3"},
{"RX2 MIX1 INP1", "IIR1", "IIR1"},
{"RX2 MIX1 INP1", "IIR2", "IIR2"},
{"RX2 MIX1 INP2", "RX1", "I2S RX1"},
{"RX2 MIX1 INP2", "RX2", "I2S RX2"},
{"RX2 MIX1 INP2", "RX3", "I2S RX3"},
{"RX2 MIX1 INP1", "IIR1", "IIR1"},
{"RX2 MIX1 INP1", "IIR2", "IIR2"},
{"RX2 MIX1 INP3", "RX1", "I2S RX1"},
{"RX2 MIX1 INP3", "RX2", "I2S RX2"},
@ -748,10 +1013,27 @@ static const struct snd_soc_dapm_route msm8916_wcd_digital_audio_map[] = {
{"RX3 MIX1 INP1", "RX1", "I2S RX1"},
{"RX3 MIX1 INP1", "RX2", "I2S RX2"},
{"RX3 MIX1 INP1", "RX3", "I2S RX3"},
{"RX3 MIX1 INP1", "IIR1", "IIR1"},
{"RX3 MIX1 INP1", "IIR2", "IIR2"},
{"RX3 MIX1 INP2", "RX1", "I2S RX1"},
{"RX3 MIX1 INP2", "RX2", "I2S RX2"},
{"RX3 MIX1 INP2", "RX3", "I2S RX3"},
{"RX3 MIX1 INP2", "IIR1", "IIR1"},
{"RX3 MIX1 INP2", "IIR2", "IIR2"},
{"RX1 MIX2 INP1", "IIR1", "IIR1"},
{"RX2 MIX2 INP1", "IIR1", "IIR1"},
{"RX1 MIX2 INP1", "IIR2", "IIR2"},
{"RX2 MIX2 INP1", "IIR2", "IIR2"},
{"IIR1", NULL, "IIR1 INP1 MUX"},
{"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
{"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
{"IIR2", NULL, "IIR2 INP1 MUX"},
{"IIR2 INP1 MUX", "DEC1", "DEC1 MUX"},
{"IIR2 INP1 MUX", "DEC2", "DEC2 MUX"},
{"RX3 MIX1 INP3", "RX1", "I2S RX1"},
{"RX3 MIX1 INP3", "RX2", "I2S RX2"},

View file

@ -828,6 +828,24 @@ static int nau8822_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_component *component = dai->component;
struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component);
int val_len = 0, val_rate = 0;
unsigned int ctrl_val, bclk_fs, bclk_div;
/* make BCLK and LRC divide configuration if the codec as master. */
snd_soc_component_read(component, NAU8822_REG_CLOCKING, &ctrl_val);
if (ctrl_val & NAU8822_CLK_MASTER) {
/* get the bclk and fs ratio */
bclk_fs = snd_soc_params_to_bclk(params) / params_rate(params);
if (bclk_fs <= 32)
bclk_div = NAU8822_BCLKDIV_8;
else if (bclk_fs <= 64)
bclk_div = NAU8822_BCLKDIV_4;
else if (bclk_fs <= 128)
bclk_div = NAU8822_BCLKDIV_2;
else
return -EINVAL;
snd_soc_component_update_bits(component, NAU8822_REG_CLOCKING,
NAU8822_BCLKSEL_MASK, bclk_div);
}
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:

View file

@ -107,10 +107,17 @@
/* NAU8822_REG_CLOCKING (0x6) */
#define NAU8822_CLKIOEN_MASK 0x1
#define NAU8822_CLK_MASTER 0x1
#define NAU8822_CLK_SLAVE 0x0
#define NAU8822_MCLKSEL_SFT 5
#define NAU8822_MCLKSEL_MASK (0x7 << 5)
#define NAU8822_BCLKSEL_SFT 2
#define NAU8822_BCLKSEL_MASK (0x7 << 2)
#define NAU8822_BCLKDIV_1 (0x0 << 2)
#define NAU8822_BCLKDIV_2 (0x1 << 2)
#define NAU8822_BCLKDIV_4 (0x2 << 2)
#define NAU8822_BCLKDIV_8 (0x3 << 2)
#define NAU8822_BCLKDIV_16 (0x4 << 2)
#define NAU8822_CLKM_MASK (0x1 << 8)
#define NAU8822_CLKM_MCLK (0x0 << 8)
#define NAU8822_CLKM_PLL (0x1 << 8)

View file

@ -53,6 +53,9 @@ struct pcm3168a_priv {
unsigned long sysclk;
unsigned int adc_fmt;
unsigned int dac_fmt;
int tdm_slots;
u32 tdm_mask[2];
int slot_width;
};
static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" };
@ -384,6 +387,47 @@ static int pcm3168a_set_dai_fmt_adc(struct snd_soc_dai *dai,
return pcm3168a_set_dai_fmt(dai, format, false);
}
static int pcm3168a_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 pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
if (tx_mask >= (1<<slots) || rx_mask >= (1<<slots)) {
dev_err(component->dev,
"Bad tdm mask tx: 0x%08x rx: 0x%08x slots %d\n",
tx_mask, rx_mask, slots);
return -EINVAL;
}
if (slot_width &&
(slot_width != 16 && slot_width != 24 && slot_width != 32 )) {
dev_err(component->dev, "Unsupported slot_width %d\n",
slot_width);
return -EINVAL;
}
if (pcm3168a->tdm_slots && pcm3168a->tdm_slots != slots) {
dev_err(component->dev, "Not matching slots %d vs %d\n",
pcm3168a->tdm_slots, slots);
return -EINVAL;
}
if (pcm3168a->slot_width && pcm3168a->slot_width != slot_width) {
dev_err(component->dev, "Not matching slot_width %d vs %d\n",
pcm3168a->slot_width, slot_width);
return -EINVAL;
}
pcm3168a->tdm_slots = slots;
pcm3168a->slot_width = slot_width;
pcm3168a->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
pcm3168a->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;
return 0;
}
static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@ -393,11 +437,10 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
bool tx, master_mode;
u32 val, mask, shift, reg;
unsigned int rate, fmt, ratio, max_ratio;
unsigned int chan;
int i, min_frame_size;
unsigned int tdm_slots;
int i, slot_width;
rate = params_rate(params);
chan = params_channels(params);
ratio = pcm3168a->sysclk / rate;
@ -428,30 +471,46 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
min_frame_size = params_width(params) * 2;
switch (min_frame_size) {
case 32:
if (pcm3168a->slot_width)
slot_width = pcm3168a->slot_width;
else
slot_width = params_width(params);
switch (slot_width) {
case 16:
if (master_mode || (fmt != PCM3168A_FMT_RIGHT_J)) {
dev_err(component->dev, "32-bit frames are supported only for slave mode using right justified\n");
dev_err(component->dev, "16-bit slots are supported only for slave mode using right justified\n");
return -EINVAL;
}
fmt = PCM3168A_FMT_RIGHT_J_16;
break;
case 48:
case 24:
if (master_mode || (fmt & PCM3168A_FMT_DSP_MASK)) {
dev_err(component->dev, "48-bit frames not supported in master mode, or slave mode using DSP\n");
dev_err(component->dev, "24-bit slots not supported in master mode, or slave mode using DSP\n");
return -EINVAL;
}
break;
case 64:
case 32:
break;
default:
dev_err(component->dev, "unsupported frame size: %d\n", min_frame_size);
dev_err(component->dev, "unsupported frame size: %d\n", slot_width);
return -EINVAL;
}
/* for TDM */
if (chan > 2) {
if (pcm3168a->tdm_slots)
tdm_slots = pcm3168a->tdm_slots;
else
tdm_slots = params_channels(params);
/*
* Switch the codec to TDM mode when more than 2 TDM slots are needed
* for the stream.
* If pcm3168a->tdm_slots is not set or set to more than 2 (8/6 usually)
* then DIN1/DOUT1 is used in TDM mode.
* If pcm3168a->tdm_slots is set to 2 then DIN1/2/3/4 and DOUT1/2/3 is
* used in normal mode, no need to switch to TDM modes.
*/
if (tdm_slots > 2) {
switch (fmt) {
case PCM3168A_FMT_I2S:
case PCM3168A_FMT_DSP_A:
@ -551,14 +610,16 @@ static const struct snd_soc_dai_ops pcm3168a_dac_dai_ops = {
.set_fmt = pcm3168a_set_dai_fmt_dac,
.set_sysclk = pcm3168a_set_dai_sysclk,
.hw_params = pcm3168a_hw_params,
.digital_mute = pcm3168a_digital_mute
.digital_mute = pcm3168a_digital_mute,
.set_tdm_slot = pcm3168a_set_tdm_slot,
};
static const struct snd_soc_dai_ops pcm3168a_adc_dai_ops = {
.startup = pcm3168a_startup,
.set_fmt = pcm3168a_set_dai_fmt_adc,
.set_sysclk = pcm3168a_set_dai_sysclk,
.hw_params = pcm3168a_hw_params
.hw_params = pcm3168a_hw_params,
.set_tdm_slot = pcm3168a_set_tdm_slot,
};
static struct snd_soc_dai_driver pcm3168a_dais[] = {

2244
sound/soc/codecs/rt1011.c Normal file

File diff suppressed because it is too large Load diff

672
sound/soc/codecs/rt1011.h Normal file
View file

@ -0,0 +1,672 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* rt1011.h -- RT1011 ALSA SoC amplifier component driver header
*
* Copyright(c) 2019 Realtek Semiconductor Corp.
*/
#ifndef _RT1011_H_
#define _RT1011_H_
#define RT1011_DEVICE_ID_NUM 0x1011
#define RT1011_RESET 0x0000
#define RT1011_CLK_1 0x0002
#define RT1011_CLK_2 0x0004
#define RT1011_CLK_3 0x0006
#define RT1011_CLK_4 0x0008
#define RT1011_PLL_1 0x000a
#define RT1011_PLL_2 0x000c
#define RT1011_SRC_1 0x000e
#define RT1011_SRC_2 0x0010
#define RT1011_SRC_3 0x0012
#define RT1011_CLK_DET 0x0020
#define RT1011_SIL_DET 0x0022
#define RT1011_PRIV_INDEX 0x006a
#define RT1011_PRIV_DATA 0x006c
#define RT1011_CUSTOMER_ID 0x0076
#define RT1011_FM_VER 0x0078
#define RT1011_VERSION_ID 0x007a
#define RT1011_VENDOR_ID 0x007c
#define RT1011_DEVICE_ID 0x007d
#define RT1011_DUM_RW_0 0x00f0
#define RT1011_DUM_YUN 0x00f2
#define RT1011_DUM_RW_1 0x00f3
#define RT1011_DUM_RO 0x00f4
#define RT1011_MAN_I2C_DEV 0x0100
#define RT1011_DAC_SET_1 0x0102
#define RT1011_DAC_SET_2 0x0104
#define RT1011_DAC_SET_3 0x0106
#define RT1011_ADC_SET 0x0107
#define RT1011_ADC_SET_1 0x0108
#define RT1011_ADC_SET_2 0x010a
#define RT1011_ADC_SET_3 0x010c
#define RT1011_ADC_SET_4 0x010e
#define RT1011_ADC_SET_5 0x0110
#define RT1011_TDM_TOTAL_SET 0x0111
#define RT1011_TDM1_SET_TCON 0x0112
#define RT1011_TDM1_SET_1 0x0114
#define RT1011_TDM1_SET_2 0x0116
#define RT1011_TDM1_SET_3 0x0118
#define RT1011_TDM1_SET_4 0x011a
#define RT1011_TDM1_SET_5 0x011c
#define RT1011_TDM2_SET_1 0x011e
#define RT1011_TDM2_SET_2 0x0120
#define RT1011_TDM2_SET_3 0x0122
#define RT1011_TDM2_SET_4 0x0124
#define RT1011_TDM2_SET_5 0x0126
#define RT1011_PWM_CAL 0x0200
#define RT1011_MIXER_1 0x0300
#define RT1011_MIXER_2 0x0302
#define RT1011_ADRC_LIMIT 0x0310
#define RT1011_A_PRO 0x0311
#define RT1011_A_TIMING_1 0x0313
#define RT1011_A_TIMING_2 0x0314
#define RT1011_A_TEMP_SEN 0x0316
#define RT1011_SPK_VOL_DET_1 0x0319
#define RT1011_SPK_VOL_DET_2 0x031a
#define RT1011_SPK_VOL_TEST_OUT 0x031b
#define RT1011_VBAT_VOL_DET_1 0x031c
#define RT1011_VBAT_VOL_DET_2 0x031d
#define RT1011_VBAT_TEST_OUT_1 0x031e
#define RT1011_VBAT_TEST_OUT_2 0x031f
#define RT1011_VBAT_PROTECTION 0x0320
#define RT1011_VBAT_DET 0x0321
#define RT1011_POWER_1 0x0322
#define RT1011_POWER_2 0x0324
#define RT1011_POWER_3 0x0326
#define RT1011_POWER_4 0x0328
#define RT1011_POWER_5 0x0329
#define RT1011_POWER_6 0x032a
#define RT1011_POWER_7 0x032b
#define RT1011_POWER_8 0x032c
#define RT1011_POWER_9 0x032d
#define RT1011_CLASS_D_POS 0x032e
#define RT1011_BOOST_CON_1 0x0330
#define RT1011_BOOST_CON_2 0x0332
#define RT1011_ANALOG_CTRL 0x0334
#define RT1011_POWER_SEQ 0x0340
#define RT1011_SHORT_CIRCUIT_DET_1 0x0508
#define RT1011_SHORT_CIRCUIT_DET_2 0x050a
#define RT1011_SPK_TEMP_PROTECT_0 0x050c
#define RT1011_SPK_TEMP_PROTECT_1 0x050d
#define RT1011_SPK_TEMP_PROTECT_2 0x050e
#define RT1011_SPK_TEMP_PROTECT_3 0x050f
#define RT1011_SPK_TEMP_PROTECT_4 0x0510
#define RT1011_SPK_TEMP_PROTECT_5 0x0511
#define RT1011_SPK_TEMP_PROTECT_6 0x0512
#define RT1011_SPK_TEMP_PROTECT_7 0x0516
#define RT1011_SPK_TEMP_PROTECT_8 0x0517
#define RT1011_SPK_TEMP_PROTECT_9 0x0518
#define RT1011_SPK_PRO_DC_DET_1 0x0519
#define RT1011_SPK_PRO_DC_DET_2 0x051a
#define RT1011_SPK_PRO_DC_DET_3 0x051b
#define RT1011_SPK_PRO_DC_DET_4 0x051c
#define RT1011_SPK_PRO_DC_DET_5 0x051d
#define RT1011_SPK_PRO_DC_DET_6 0x051e
#define RT1011_SPK_PRO_DC_DET_7 0x051f
#define RT1011_SPK_PRO_DC_DET_8 0x0520
#define RT1011_SPL_1 0x0521
#define RT1011_SPL_2 0x0522
#define RT1011_SPL_3 0x0524
#define RT1011_SPL_4 0x0526
#define RT1011_THER_FOLD_BACK_1 0x0528
#define RT1011_THER_FOLD_BACK_2 0x052a
#define RT1011_EXCUR_PROTECT_1 0x0530
#define RT1011_EXCUR_PROTECT_2 0x0532
#define RT1011_EXCUR_PROTECT_3 0x0534
#define RT1011_EXCUR_PROTECT_4 0x0535
#define RT1011_BAT_GAIN_1 0x0536
#define RT1011_BAT_GAIN_2 0x0538
#define RT1011_BAT_GAIN_3 0x053a
#define RT1011_BAT_GAIN_4 0x053c
#define RT1011_BAT_GAIN_5 0x053d
#define RT1011_BAT_GAIN_6 0x053e
#define RT1011_BAT_GAIN_7 0x053f
#define RT1011_BAT_GAIN_8 0x0540
#define RT1011_BAT_GAIN_9 0x0541
#define RT1011_BAT_GAIN_10 0x0542
#define RT1011_BAT_GAIN_11 0x0543
#define RT1011_BAT_RT_THMAX_1 0x0544
#define RT1011_BAT_RT_THMAX_2 0x0545
#define RT1011_BAT_RT_THMAX_3 0x0546
#define RT1011_BAT_RT_THMAX_4 0x0547
#define RT1011_BAT_RT_THMAX_5 0x0548
#define RT1011_BAT_RT_THMAX_6 0x0549
#define RT1011_BAT_RT_THMAX_7 0x054a
#define RT1011_BAT_RT_THMAX_8 0x054b
#define RT1011_BAT_RT_THMAX_9 0x054c
#define RT1011_BAT_RT_THMAX_10 0x054d
#define RT1011_BAT_RT_THMAX_11 0x054e
#define RT1011_BAT_RT_THMAX_12 0x054f
#define RT1011_SPREAD_SPECTURM 0x0568
#define RT1011_PRO_GAIN_MODE 0x056a
#define RT1011_RT_DRC_CROSS 0x0600
#define RT1011_RT_DRC_HB_1 0x0611
#define RT1011_RT_DRC_HB_2 0x0612
#define RT1011_RT_DRC_HB_3 0x0613
#define RT1011_RT_DRC_HB_4 0x0614
#define RT1011_RT_DRC_HB_5 0x0615
#define RT1011_RT_DRC_HB_6 0x0616
#define RT1011_RT_DRC_HB_7 0x0617
#define RT1011_RT_DRC_HB_8 0x0618
#define RT1011_RT_DRC_BB_1 0x0621
#define RT1011_RT_DRC_BB_2 0x0622
#define RT1011_RT_DRC_BB_3 0x0623
#define RT1011_RT_DRC_BB_4 0x0624
#define RT1011_RT_DRC_BB_5 0x0625
#define RT1011_RT_DRC_BB_6 0x0626
#define RT1011_RT_DRC_BB_7 0x0627
#define RT1011_RT_DRC_BB_8 0x0628
#define RT1011_RT_DRC_POS_1 0x0631
#define RT1011_RT_DRC_POS_2 0x0632
#define RT1011_RT_DRC_POS_3 0x0633
#define RT1011_RT_DRC_POS_4 0x0634
#define RT1011_RT_DRC_POS_5 0x0635
#define RT1011_RT_DRC_POS_6 0x0636
#define RT1011_RT_DRC_POS_7 0x0637
#define RT1011_RT_DRC_POS_8 0x0638
#define RT1011_CROSS_BQ_SET_1 0x0702
#define RT1011_CROSS_BQ_SET_2 0x0704
#define RT1011_BQ_SET_0 0x0706
#define RT1011_BQ_SET_1 0x0708
#define RT1011_BQ_SET_2 0x070a
#define RT1011_BQ_PRE_GAIN_28_16 0x0710
#define RT1011_BQ_PRE_GAIN_15_0 0x0711
#define RT1011_BQ_POST_GAIN_28_16 0x0712
#define RT1011_BQ_POST_GAIN_15_0 0x0713
#define RT1011_BQ_H0_28_16 0x0720
#define RT1011_BQ_A2_15_0 0x0729
#define RT1011_BQ_1_H0_28_16 0x0730
#define RT1011_BQ_1_A2_15_0 0x0739
#define RT1011_BQ_2_H0_28_16 0x0740
#define RT1011_BQ_2_A2_15_0 0x0749
#define RT1011_BQ_3_H0_28_16 0x0750
#define RT1011_BQ_3_A2_15_0 0x0759
#define RT1011_BQ_4_H0_28_16 0x0760
#define RT1011_BQ_4_A2_15_0 0x0769
#define RT1011_BQ_5_H0_28_16 0x0770
#define RT1011_BQ_5_A2_15_0 0x0779
#define RT1011_BQ_6_H0_28_16 0x0780
#define RT1011_BQ_6_A2_15_0 0x0789
#define RT1011_BQ_7_H0_28_16 0x0790
#define RT1011_BQ_7_A2_15_0 0x0799
#define RT1011_BQ_8_H0_28_16 0x07a0
#define RT1011_BQ_8_A2_15_0 0x07a9
#define RT1011_BQ_9_H0_28_16 0x07b0
#define RT1011_BQ_9_A2_15_0 0x07b9
#define RT1011_BQ_10_H0_28_16 0x07c0
#define RT1011_BQ_10_A2_15_0 0x07c9
#define RT1011_TEST_PAD_STATUS 0x1000
#define RT1011_SYSTEM_RESET_1 0x1007
#define RT1011_SYSTEM_RESET_2 0x1008
#define RT1011_SYSTEM_RESET_3 0x1009
#define RT1011_ADCDAT_OUT_SOURCE 0x100D
#define RT1011_PLL_INTERNAL_SET 0x1010
#define RT1011_TEST_OUT_1 0x1020
#define RT1011_TEST_OUT_3 0x1024
#define RT1011_DC_CALIB_CLASSD_1 0x1200
#define RT1011_DC_CALIB_CLASSD_2 0x1202
#define RT1011_DC_CALIB_CLASSD_3 0x1204
#define RT1011_DC_CALIB_CLASSD_5 0x1208
#define RT1011_DC_CALIB_CLASSD_6 0x120a
#define RT1011_DC_CALIB_CLASSD_7 0x120c
#define RT1011_DC_CALIB_CLASSD_8 0x120e
#define RT1011_DC_CALIB_CLASSD_10 0x1212
#define RT1011_CLASSD_INTERNAL_SET_1 0x1300
#define RT1011_CLASSD_INTERNAL_SET_3 0x1304
#define RT1011_CLASSD_INTERNAL_SET_8 0x130c
#define RT1011_VREF_LV_1 0x131a
#define RT1011_SMART_BOOST_TIMING_1 0x1322
#define RT1011_SMART_BOOST_TIMING_36 0x1349
#define RT1011_SINE_GEN_REG_1 0x1500
#define RT1011_SINE_GEN_REG_2 0x1502
#define RT1011_SINE_GEN_REG_3 0x1504
#define RT1011_STP_INITIAL_RS_TEMP 0x1510
#define RT1011_STP_CALIB_RS_TEMP 0x152a
#define RT1011_INIT_RECIPROCAL_REG_24_16 0x1538
#define RT1011_INIT_RECIPROCAL_REG_15_0 0x1539
#define RT1011_STP_ALPHA_RECIPROCAL_MSB 0x153e
#define RT1011_SPK_RESISTANCE_1 0x1544
#define RT1011_SPK_RESISTANCE_2 0x1546
#define RT1011_SPK_THERMAL 0x1548
#define RT1011_STP_OTP_TH 0x1552
#define RT1011_ALC_BK_GAIN_O 0x1554
#define RT1011_ALC_BK_GAIN_O_PRE 0x1556
#define RT1011_SPK_DC_O_23_16 0x155a
#define RT1011_SPK_DC_O_15_0 0x155c
#define RT1011_INIT_RECIPROCAL_SYN_24_16 0x1560
#define RT1011_INIT_RECIPROCAL_SYN_15_0 0x1562
#define RT1011_STP_BQ_1_A1_L_28_16 0x1570
#define RT1011_STP_BQ_1_H0_R_15_0 0x1583
#define RT1011_STP_BQ_2_A1_L_28_16 0x1590
#define RT1011_SPK_EXCURSION_23_16 0x15be
#define RT1011_SPK_EXCURSION_15_0 0x15bf
#define RT1011_SEP_MAIN_OUT_23_16 0x15c0
#define RT1011_SEP_MAIN_OUT_15_0 0x15c1
#define RT1011_SEP_RE_REG_15_0 0x15f9
#define RT1011_DRC_CF_PARAMS_1 0x1600
#define RT1011_DRC_CF_PARAMS_12 0x160b
#define RT1011_ALC_DRC_HB_INTERNAL_1 0x1611
#define RT1011_ALC_DRC_HB_INTERNAL_5 0x1615
#define RT1011_ALC_DRC_HB_INTERNAL_6 0x1616
#define RT1011_ALC_DRC_HB_INTERNAL_7 0x1617
#define RT1011_ALC_DRC_BB_INTERNAL_1 0x1621
#define RT1011_ALC_DRC_BB_INTERNAL_5 0x1625
#define RT1011_ALC_DRC_BB_INTERNAL_6 0x1626
#define RT1011_ALC_DRC_BB_INTERNAL_7 0x1627
#define RT1011_ALC_DRC_POS_INTERNAL_1 0x1631
#define RT1011_ALC_DRC_POS_INTERNAL_5 0x1635
#define RT1011_ALC_DRC_POS_INTERNAL_6 0x1636
#define RT1011_ALC_DRC_POS_INTERNAL_7 0x1637
#define RT1011_ALC_DRC_POS_INTERNAL_8 0x1638
#define RT1011_ALC_DRC_POS_INTERNAL_9 0x163a
#define RT1011_ALC_DRC_POS_INTERNAL_10 0x163c
#define RT1011_ALC_DRC_POS_INTERNAL_11 0x163e
#define RT1011_BQ_1_PARAMS_CHECK_5 0x1648
#define RT1011_BQ_2_PARAMS_CHECK_1 0x1650
#define RT1011_BQ_2_PARAMS_CHECK_5 0x1658
#define RT1011_BQ_3_PARAMS_CHECK_1 0x1660
#define RT1011_BQ_3_PARAMS_CHECK_5 0x1668
#define RT1011_BQ_4_PARAMS_CHECK_1 0x1670
#define RT1011_BQ_4_PARAMS_CHECK_5 0x1678
#define RT1011_BQ_5_PARAMS_CHECK_1 0x1680
#define RT1011_BQ_5_PARAMS_CHECK_5 0x1688
#define RT1011_BQ_6_PARAMS_CHECK_1 0x1690
#define RT1011_BQ_6_PARAMS_CHECK_5 0x1698
#define RT1011_BQ_7_PARAMS_CHECK_1 0x1700
#define RT1011_BQ_7_PARAMS_CHECK_5 0x1708
#define RT1011_BQ_8_PARAMS_CHECK_1 0x1710
#define RT1011_BQ_8_PARAMS_CHECK_5 0x1718
#define RT1011_BQ_9_PARAMS_CHECK_1 0x1720
#define RT1011_BQ_9_PARAMS_CHECK_5 0x1728
#define RT1011_BQ_10_PARAMS_CHECK_1 0x1730
#define RT1011_BQ_10_PARAMS_CHECK_5 0x1738
#define RT1011_IRQ_1 0x173a
#define RT1011_PART_NUMBER_EFUSE 0x173e
#define RT1011_EFUSE_CONTROL_1 0x17bb
#define RT1011_EFUSE_CONTROL_2 0x17bd
#define RT1011_EFUSE_MATCH_DONE 0x17cb
#define RT1011_EFUSE_ADC_OFFSET_18_16 0x17e5
#define RT1011_EFUSE_ADC_OFFSET_15_0 0x17e7
#define RT1011_EFUSE_DAC_OFFSET_G0_20_16 0x17e9
#define RT1011_EFUSE_DAC_OFFSET_G0_15_0 0x17eb
#define RT1011_EFUSE_DAC_OFFSET_G1_20_16 0x17ed
#define RT1011_EFUSE_DAC_OFFSET_G1_15_0 0x17ef
#define RT1011_EFUSE_READ_R0_3_15_0 0x1803
#define RT1011_MAX_REG 0x1803
#define RT1011_REG_DISP_LEN 23
/* CLOCK-2 (0x0004) */
#define RT1011_FS_SYS_PRE_MASK (0x3 << 14)
#define RT1011_FS_SYS_PRE_SFT 14
#define RT1011_FS_SYS_PRE_MCLK (0x0 << 14)
#define RT1011_FS_SYS_PRE_BCLK (0x1 << 14)
#define RT1011_FS_SYS_PRE_PLL1 (0x2 << 14)
#define RT1011_FS_SYS_PRE_RCCLK (0x3 << 14)
#define RT1011_PLL1_SRC_MASK (0x1 << 13)
#define RT1011_PLL1_SRC_SFT 13
#define RT1011_PLL1_SRC_PLL2 (0x0 << 13)
#define RT1011_PLL1_SRC_BCLK (0x1 << 13)
#define RT1011_PLL2_SRC_MASK (0x1 << 12)
#define RT1011_PLL2_SRC_SFT 12
#define RT1011_PLL2_SRC_MCLK (0x0 << 12)
#define RT1011_PLL2_SRC_RCCLK (0x1 << 12)
#define RT1011_PLL2_SRC_DIV_MASK (0x3 << 10)
#define RT1011_PLL2_SRC_DIV_SFT 10
#define RT1011_SRCIN_DIV_MASK (0x3 << 8)
#define RT1011_SRCIN_DIV_SFT 8
#define RT1011_FS_SYS_DIV_MASK (0x7 << 4)
#define RT1011_FS_SYS_DIV_SFT 4
/* PLL-1 (0x000a) */
#define RT1011_PLL1_QM_MASK (0xf << 12)
#define RT1011_PLL1_QM_SFT 12
#define RT1011_PLL1_BPM_MASK (0x1 << 11)
#define RT1011_PLL1_BPM_SFT 11
#define RT1011_PLL1_BPM (0x1 << 11)
#define RT1011_PLL1_QN_MASK (0x1ff << 0)
#define RT1011_PLL1_QN_SFT 0
/* PLL-2 (0x000c) */
#define RT1011_PLL2_BPK_MASK (0x1 << 5)
#define RT1011_PLL2_BPK_SFT 5
#define RT1011_PLL2_BPK (0x1 << 5)
#define RT1011_PLL2_QK_MASK (0x1f << 0)
#define RT1011_PLL2_QK_SFT 0
/* Clock Detect (0x0020) */
#define RT1011_EN_MCLK_DET_MASK (0x1 << 15)
#define RT1011_EN_MCLK_DET_SFT 15
#define RT1011_EN_MCLK_DET (0x1 << 15)
/* DAC Setting-2 (0x0104) */
#define RT1011_EN_CKGEN_DAC_MASK (0x1 << 13)
#define RT1011_EN_CKGEN_DAC_SFT 13
#define RT1011_EN_CKGEN_DAC (0x1 << 13)
/* DAC Setting-3 (0x0106) */
#define RT1011_DA_MUTE_EN_MASK (0x1 << 15)
#define RT1011_DA_MUTE_EN_SFT 15
/* ADC Setting-5 (0x0110) */
#define RT1011_AD_EN_CKGEN_ADC_MASK (0x1 << 9)
#define RT1011_AD_EN_CKGEN_ADC_SFT 9
#define RT1011_AD_EN_CKGEN_ADC (0x1 << 9)
/* TDM Total Setting (0x0111) */
#define RT1011_I2S_TDM_MS_MASK (0x1 << 14)
#define RT1011_I2S_TDM_MS_SFT 14
#define RT1011_I2S_TDM_MS_S (0x0 << 14)
#define RT1011_I2S_TDM_MS_M (0x1 << 14)
#define RT1011_I2S_TX_DL_MASK (0x7 << 8)
#define RT1011_I2S_TX_DL_SFT 8
#define RT1011_I2S_TX_DL_16B (0x0 << 8)
#define RT1011_I2S_TX_DL_20B (0x1 << 8)
#define RT1011_I2S_TX_DL_24B (0x2 << 8)
#define RT1011_I2S_TX_DL_32B (0x3 << 8)
#define RT1011_I2S_TX_DL_8B (0x4 << 8)
#define RT1011_I2S_RX_DL_MASK (0x7 << 5)
#define RT1011_I2S_RX_DL_SFT 5
#define RT1011_I2S_RX_DL_16B (0x0 << 5)
#define RT1011_I2S_RX_DL_20B (0x1 << 5)
#define RT1011_I2S_RX_DL_24B (0x2 << 5)
#define RT1011_I2S_RX_DL_32B (0x3 << 5)
#define RT1011_I2S_RX_DL_8B (0x4 << 5)
#define RT1011_ADCDAT1_PIN_CONFIG (0x1 << 4)
#define RT1011_ADCDAT1_OUTPUT (0x0 << 4)
#define RT1011_ADCDAT1_INPUT (0x1 << 4)
#define RT1011_ADCDAT2_PIN_CONFIG (0x1 << 3)
#define RT1011_ADCDAT2_OUTPUT (0x0 << 3)
#define RT1011_ADCDAT2_INPUT (0x1 << 3)
#define RT1011_I2S_TDM_DF_MASK (0x7 << 0)
#define RT1011_I2S_TDM_DF_SFT 0
#define RT1011_I2S_TDM_DF_I2S (0x0)
#define RT1011_I2S_TDM_DF_LEFT (0x1)
#define RT1011_I2S_TDM_DF_PCM_A (0x2)
#define RT1011_I2S_TDM_DF_PCM_B (0x3)
#define RT1011_I2S_TDM_DF_PCM_A_N (0x6)
#define RT1011_I2S_TDM_DF_PCM_B_N (0x7)
/* TDM_tcon Setting (0x0112) */
#define RT1011_TCON_DF_MASK (0x7 << 13)
#define RT1011_TCON_DF_SFT 13
#define RT1011_TCON_DF_I2S (0x0 << 13)
#define RT1011_TCON_DF_LEFT (0x1 << 13)
#define RT1011_TCON_DF_PCM_A (0x2 << 13)
#define RT1011_TCON_DF_PCM_B (0x3 << 13)
#define RT1011_TCON_DF_PCM_A_N (0x6 << 13)
#define RT1011_TCON_DF_PCM_B_N (0x7 << 13)
#define RT1011_TCON_BCLK_SEL_MASK (0x3 << 10)
#define RT1011_TCON_BCLK_SEL_SFT 10
#define RT1011_TCON_BCLK_SEL_32FS (0x0 << 10)
#define RT1011_TCON_BCLK_SEL_64FS (0x1 << 10)
#define RT1011_TCON_BCLK_SEL_128FS (0x2 << 10)
#define RT1011_TCON_BCLK_SEL_256FS (0x3 << 10)
#define RT1011_TCON_CH_LEN_MASK (0x3 << 5)
#define RT1011_TCON_CH_LEN_SFT 5
#define RT1011_TCON_CH_LEN_16B (0x0 << 5)
#define RT1011_TCON_CH_LEN_20B (0x1 << 5)
#define RT1011_TCON_CH_LEN_24B (0x2 << 5)
#define RT1011_TCON_CH_LEN_32B (0x3 << 5)
#define RT1011_TCON_BCLK_MST_MASK (0x1 << 4)
#define RT1011_TCON_BCLK_MST_SFT 4
#define RT1011_TCON_BCLK_MST_INV (0x1 << 4)
/* TDM1 Setting-1 (0x0114) */
#define RT1011_TDM_INV_BCLK_MASK (0x1 << 15)
#define RT1011_TDM_INV_BCLK_SFT 15
#define RT1011_TDM_INV_BCLK (0x1 << 15)
#define RT1011_I2S_CH_TX_MASK (0x3 << 10)
#define RT1011_I2S_CH_TX_SFT 10
#define RT1011_I2S_TX_2CH (0x0 << 10)
#define RT1011_I2S_TX_4CH (0x1 << 10)
#define RT1011_I2S_TX_6CH (0x2 << 10)
#define RT1011_I2S_TX_8CH (0x3 << 10)
#define RT1011_I2S_CH_RX_MASK (0x3 << 8)
#define RT1011_I2S_CH_RX_SFT 8
#define RT1011_I2S_RX_2CH (0x0 << 8)
#define RT1011_I2S_RX_4CH (0x1 << 8)
#define RT1011_I2S_RX_6CH (0x2 << 8)
#define RT1011_I2S_RX_8CH (0x3 << 8)
#define RT1011_I2S_LR_CH_SEL_MASK (0x1 << 7)
#define RT1011_I2S_LR_CH_SEL_SFT 7
#define RT1011_I2S_LEFT_CH_SEL (0x0 << 7)
#define RT1011_I2S_RIGHT_CH_SEL (0x1 << 7)
#define RT1011_I2S_CH_TX_LEN_MASK (0x7 << 4)
#define RT1011_I2S_CH_TX_LEN_SFT 4
#define RT1011_I2S_CH_TX_LEN_16B (0x0 << 4)
#define RT1011_I2S_CH_TX_LEN_20B (0x1 << 4)
#define RT1011_I2S_CH_TX_LEN_24B (0x2 << 4)
#define RT1011_I2S_CH_TX_LEN_32B (0x3 << 4)
#define RT1011_I2S_CH_TX_LEN_8B (0x4 << 4)
#define RT1011_I2S_CH_RX_LEN_MASK (0x7 << 0)
#define RT1011_I2S_CH_RX_LEN_SFT 0
#define RT1011_I2S_CH_RX_LEN_16B (0x0 << 0)
#define RT1011_I2S_CH_RX_LEN_20B (0x1 << 0)
#define RT1011_I2S_CH_RX_LEN_24B (0x2 << 0)
#define RT1011_I2S_CH_RX_LEN_32B (0x3 << 0)
#define RT1011_I2S_CH_RX_LEN_8B (0x4 << 0)
/* TDM1 Setting-2 (0x0116) */
#define RT1011_TDM_I2S_DOCK_ADCDAT_LEN_1_MASK (0x7 << 13)
#define RT1011_TDM_I2S_DOCK_ADCDAT_2CH (0x1 << 13)
#define RT1011_TDM_I2S_DOCK_ADCDAT_4CH (0x3 << 13)
#define RT1011_TDM_I2S_DOCK_ADCDAT_6CH (0x5 << 13)
#define RT1011_TDM_I2S_DOCK_ADCDAT_8CH (0x7 << 13)
#define RT1011_TDM_I2S_DOCK_EN_1_MASK (0x1 << 3)
#define RT1011_TDM_I2S_DOCK_EN_1_SFT 3
#define RT1011_TDM_I2S_DOCK_EN_1 (0x1 << 3)
/* TDM2 Setting-2 (0x0120) */
#define RT1011_TDM_I2S_DOCK_ADCDAT_LEN_2_MASK (0x7 << 13)
#define RT1011_TDM_I2S_DOCK_EN_2_MASK (0x1 << 3)
#define RT1011_TDM_I2S_DOCK_EN_2_SFT 3
#define RT1011_TDM_I2S_DOCK_EN_2 (0x1 << 3)
/* MIXER 1 (0x0300) */
#define RT1011_MIXER_MUTE_MIX_I_MASK (0x1 << 15)
#define RT1011_MIXER_MUTE_MIX_I_SFT 15
#define RT1011_MIXER_MUTE_MIX_I (0x1 << 15)
#define RT1011_MIXER_MUTE_SUM_I_MASK (0x1 << 14)
#define RT1011_MIXER_MUTE_SUM_I_SFT 14
#define RT1011_MIXER_MUTE_SUM_I (0x1 << 14)
#define RT1011_MIXER_MUTE_MIX_V_MASK (0x1 << 7)
#define RT1011_MIXER_MUTE_MIX_V_SFT 7
#define RT1011_MIXER_MUTE_MIX_V (0x1 << 7)
#define RT1011_MIXER_MUTE_SUM_V_MASK (0x1 << 6)
#define RT1011_MIXER_MUTE_SUM_V_SFT 6
#define RT1011_MIXER_MUTE_SUM_V (0x1 << 6)
/* Analog Temperature Sensor (0x0316) */
#define RT1011_POW_TEMP_REG (0x1 << 2)
#define RT1011_POW_TEMP_REG_BIT 2
/* POWER-1 (0x0322) */
#define RT1011_POW_LDO2 (0x1 << 15)
#define RT1011_POW_LDO2_BIT 15
#define RT1011_POW_DAC (0x1 << 14)
#define RT1011_POW_DAC_BIT 14
#define RT1011_POW_CLK12M (0x1 << 13)
#define RT1011_POW_CLK12M_BIT 13
#define RT1011_POW_TEMP (0x1 << 12)
#define RT1011_POW_TEMP_BIT 12
#define RT1011_POW_ISENSE_SPK (0x1 << 7)
#define RT1011_POW_ISENSE_SPK_BIT 7
#define RT1011_POW_LPF_SPK (0x1 << 6)
#define RT1011_POW_LPF_SPK_BIT 6
#define RT1011_POW_VSENSE_SPK (0x1 << 5)
#define RT1011_POW_VSENSE_SPK_BIT 5
#define RT1011_POW_TWO_BATTERY_SPK (0x1 << 4)
#define RT1011_POW_TWO_BATTERY_SPK_BIT 4
/* POWER-2 (0x0324) */
#define RT1011_PLLEN (0x1 << 2)
#define RT1011_PLLEN_BIT 2
#define RT1011_POW_BG (0x1 << 1)
#define RT1011_POW_BG_BIT 1
#define RT1011_POW_BG_MBIAS_LV (0x1 << 0)
#define RT1011_POW_BG_MBIAS_LV_BIT 0
/* POWER-3 (0x0326) */
#define RT1011_POW_DET_SPKVDD (0x1 << 15)
#define RT1011_POW_DET_SPKVDD_BIT 15
#define RT1011_POW_DET_VBAT (0x1 << 14)
#define RT1011_POW_DET_VBAT_BIT 14
#define RT1011_POW_FC (0x1 << 13)
#define RT1011_POW_FC_BIT 13
#define RT1011_POW_MBIAS_LV (0x1 << 12)
#define RT1011_POW_MBIAS_LV_BIT 12
#define RT1011_POW_ADC_I (0x1 << 11)
#define RT1011_POW_ADC_I_BIT 11
#define RT1011_POW_ADC_V (0x1 << 10)
#define RT1011_POW_ADC_V_BIT 10
#define RT1011_POW_ADC_T (0x1 << 9)
#define RT1011_POW_ADC_T_BIT 9
#define RT1011_POWD_ADC_T (0x1 << 8)
#define RT1011_POWD_ADC_T_BIT 8
#define RT1011_POW_MIX_I (0x1 << 7)
#define RT1011_POW_MIX_I_BIT 7
#define RT1011_POW_MIX_V (0x1 << 6)
#define RT1011_POW_MIX_V_BIT 6
#define RT1011_POW_SUM_I (0x1 << 5)
#define RT1011_POW_SUM_I_BIT 5
#define RT1011_POW_SUM_V (0x1 << 4)
#define RT1011_POW_SUM_V_BIT 4
#define RT1011_POW_MIX_T (0x1 << 2)
#define RT1011_POW_MIX_T_BIT 2
#define RT1011_BYPASS_MIX_T (0x1 << 1)
#define RT1011_BYPASS_MIX_T_BIT 1
#define RT1011_POW_VREF_LV (0x1 << 0)
#define RT1011_POW_VREF_LV_BIT 0
/* POWER-4 (0x0328) */
#define RT1011_POW_EN_SWR (0x1 << 12)
#define RT1011_POW_EN_SWR_BIT 12
#define RT1011_POW_EN_PASS_BGOK_SWR (0x1 << 10)
#define RT1011_POW_EN_PASS_BGOK_SWR_BIT 10
#define RT1011_POW_EN_PASS_VPOK_SWR (0x1 << 9)
#define RT1011_POW_EN_PASS_VPOK_SWR_BIT 9
/* POWER-9 (0x032d) */
#define RT1011_POW_SDB_REG_MASK (0x1 << 9)
#define RT1011_POW_SDB_REG_BIT 9
#define RT1011_POW_SDB_REG (0x1 << 9)
#define RT1011_POW_SEL_SDB_MODE_MASK (0x1 << 6)
#define RT1011_POW_SEL_SDB_MODE_BIT 6
#define RT1011_POW_SEL_SDB_MODE (0x1 << 6)
#define RT1011_POW_MNL_SDB_MASK (0x1 << 5)
#define RT1011_POW_MNL_SDB_BIT 5
#define RT1011_POW_MNL_SDB (0x1 << 5)
/* SPK Protection-Temperature Protection (0x050c) */
#define RT1011_STP_EN_MASK (0x1 << 15)
#define RT1011_STP_EN_BIT 15
#define RT1011_STP_EN (0x1 << 15)
#define RT1011_STP_RS_CLB_EN_MASK (0x1 << 14)
#define RT1011_STP_RS_CLB_EN_BIT 14
#define RT1011_STP_RS_CLB_EN (0x1 << 14)
/* SPK Protection-Temperature Protection-4 (0x0510) */
#define RT1011_STP_R0_SELECT_MASK (0x3 << 6)
#define RT1011_STP_R0_SELECT_EFUSE (0x0 << 6)
#define RT1011_STP_R0_SELECT_START_VAL (0x1 << 6)
#define RT1011_STP_R0_SELECT_REG (0x2 << 6)
#define RT1011_STP_R0_SELECT_FORCE_ZERO (0x3 << 6)
/* SPK Protection-Temperature Protection-6 (0x0512) */
#define RT1011_STP_R0_EN_MASK (0x1 << 7)
#define RT1011_STP_R0_EN_BIT 7
#define RT1011_STP_R0_EN (0x1 << 7)
#define RT1011_STP_T0_EN_MASK (0x1 << 6)
#define RT1011_STP_T0_EN_BIT 6
#define RT1011_STP_T0_EN (0x1 << 6)
/* ClassD Internal Setting-1 (0x1300) */
#define RT1011_DRIVER_READY_SPK (0x1 << 12)
#define RT1011_DRIVER_READY_SPK_BIT 12
#define RT1011_RECV_MODE_SPK_MASK (0x1 << 5)
#define RT1011_SPK_MODE (0x0 << 5)
#define RT1011_RECV_MODE (0x1 << 5)
#define RT1011_RECV_MODE_SPK_BIT 5
/* ClassD Internal Setting-3 (0x1304) */
#define RT1011_REG_GAIN_CLASSD_RI_SPK_MASK (0x7 << 12)
#define RT1011_REG_GAIN_CLASSD_RI_410K (0x0 << 12)
#define RT1011_REG_GAIN_CLASSD_RI_95K (0x1 << 12)
#define RT1011_REG_GAIN_CLASSD_RI_82P5K (0x2 << 12)
#define RT1011_REG_GAIN_CLASSD_RI_72P5K (0x3 << 12)
#define RT1011_REG_GAIN_CLASSD_RI_62P5K (0x4 << 12)
/* ClassD Internal Setting-8 (0x130c) */
#define RT1011_TM_PORPVDD_SPK (0x1 << 1)
#define RT1011_TM_PORPVDD_SPK_BIT 1
/* SPK Protection-Temperature Protection-SINE_GEN_REG-1 (0x1500) */
#define RT1011_STP_SIN_GEN_EN_MASK (0x1 << 13)
#define RT1011_STP_SIN_GEN_EN (0x1 << 13)
#define RT1011_STP_SIN_GEN_EN_BIT 13
/* System Clock Source */
enum {
RT1011_FS_SYS_PRE_S_MCLK,
RT1011_FS_SYS_PRE_S_BCLK,
RT1011_FS_SYS_PRE_S_PLL1,
RT1011_FS_SYS_PRE_S_RCCLK, /* 12M Hz */
};
/* PLL Source 1/2 */
enum {
RT1011_PLL1_S_BCLK,
RT1011_PLL2_S_MCLK,
RT1011_PLL2_S_RCCLK, /* 12M Hz */
};
enum {
RT1011_AIF1,
RT1011_AIFS
};
/* BiQual & DRC related settings */
#define RT1011_BQ_DRC_NUM 128
struct rt1011_bq_drc_params {
unsigned short val;
unsigned short reg;
#ifdef CONFIG_64BIT
unsigned int reserved;
#endif
};
enum {
RT1011_ADVMODE_INITIAL_SET,
RT1011_ADVMODE_SEP_BQ_COEFF,
RT1011_ADVMODE_EQ_BQ_COEFF,
RT1011_ADVMODE_BQ_UI_COEFF,
RT1011_ADVMODE_SMARTBOOST_COEFF,
RT1011_ADVMODE_NUM,
};
struct rt1011_priv {
struct snd_soc_component *component;
struct regmap *regmap;
struct work_struct cali_work;
struct rt1011_bq_drc_params **bq_drc_params;
int sysclk;
int sysclk_src;
int lrck;
int bclk;
int id;
int pll_src;
int pll_in;
int pll_out;
int bq_drc_set;
unsigned int r0_reg;
int recv_spk_mode;
};
#endif /* end of _RT1011_H_ */

898
sound/soc/codecs/rt1308.c Executable file
View file

@ -0,0 +1,898 @@
/*
* rt1308.c -- RT1308 ALSA SoC amplifier component driver
*
* Copyright 2019 Realtek Semiconductor Corp.
* Author: Derek Fang <derek.fang@realtek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/of_gpio.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
#include <linux/firmware.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include "rl6231.h"
#include "rt1308.h"
static const struct reg_sequence init_list[] = {
{ RT1308_I2C_I2S_SDW_SET, 0x01014005 },
{ RT1308_CLASS_D_SET_2, 0x227f5501 },
{ RT1308_PADS_1, 0x50150505 },
{ RT1308_VREF, 0x18100000 },
{ RT1308_IV_SENSE, 0x87010000 },
{ RT1308_DUMMY_REG, 0x00000200 },
{ RT1308_SIL_DET, 0x61c30000 },
{ RT1308_DC_CAL_2, 0x00ffff00 },
{ RT1308_CLK_DET, 0x01000000 },
{ RT1308_POWER_STATUS, 0x00800000 },
{ RT1308_DAC_SET, 0xafaf0700 },
};
#define RT1308_INIT_REG_LEN ARRAY_SIZE(init_list)
struct rt1308_priv {
struct snd_soc_component *component;
struct regmap *regmap;
int sysclk;
int sysclk_src;
int lrck;
int bclk;
int master;
int pll_src;
int pll_in;
int pll_out;
};
static const struct reg_default rt1308_reg[] = {
{ 0x01, 0x1f3f5f00 },
{ 0x02, 0x07000000 },
{ 0x03, 0x80003e00 },
{ 0x04, 0x80800600 },
{ 0x05, 0x0aaa1a0a },
{ 0x06, 0x52000000 },
{ 0x07, 0x00000000 },
{ 0x08, 0x00600000 },
{ 0x09, 0xe1030000 },
{ 0x0a, 0x00000000 },
{ 0x0b, 0x30000000 },
{ 0x0c, 0x7fff7000 },
{ 0x10, 0xffff0700 },
{ 0x11, 0x0a000000 },
{ 0x12, 0x60040000 },
{ 0x13, 0x00000000 },
{ 0x14, 0x0f300000 },
{ 0x15, 0x00000022 },
{ 0x16, 0x02000000 },
{ 0x17, 0x01004045 },
{ 0x18, 0x00000000 },
{ 0x19, 0x00000000 },
{ 0x1a, 0x80000000 },
{ 0x1b, 0x10325476 },
{ 0x1c, 0x1d1d0000 },
{ 0x20, 0xd2101300 },
{ 0x21, 0xf3ffff00 },
{ 0x22, 0x00000000 },
{ 0x23, 0x00000000 },
{ 0x24, 0x00000000 },
{ 0x25, 0x00000000 },
{ 0x26, 0x00000000 },
{ 0x27, 0x00000000 },
{ 0x28, 0x00000000 },
{ 0x29, 0x00000000 },
{ 0x2a, 0x00000000 },
{ 0x2b, 0x00000000 },
{ 0x2c, 0x00000000 },
{ 0x2d, 0x00000000 },
{ 0x2e, 0x00000000 },
{ 0x2f, 0x00000000 },
{ 0x30, 0x01000000 },
{ 0x31, 0x20025501 },
{ 0x32, 0x00000000 },
{ 0x33, 0x105a0000 },
{ 0x34, 0x10100000 },
{ 0x35, 0x2aaa52aa },
{ 0x36, 0x00c00000 },
{ 0x37, 0x20046100 },
{ 0x50, 0x10022f00 },
{ 0x51, 0x003c0000 },
{ 0x54, 0x04000000 },
{ 0x55, 0x01000000 },
{ 0x56, 0x02000000 },
{ 0x57, 0x02000000 },
{ 0x58, 0x02000000 },
{ 0x59, 0x02000000 },
{ 0x5b, 0x02000000 },
{ 0x5c, 0x00000000 },
{ 0x5d, 0x00000000 },
{ 0x5e, 0x00000000 },
{ 0x5f, 0x00000000 },
{ 0x60, 0x02000000 },
{ 0x61, 0x00000000 },
{ 0x62, 0x00000000 },
{ 0x63, 0x00000000 },
{ 0x64, 0x00000000 },
{ 0x65, 0x02000000 },
{ 0x66, 0x00000000 },
{ 0x67, 0x00000000 },
{ 0x68, 0x00000000 },
{ 0x69, 0x00000000 },
{ 0x6a, 0x02000000 },
{ 0x6c, 0x00000000 },
{ 0x6d, 0x00000000 },
{ 0x6e, 0x00000000 },
{ 0x70, 0x10EC1308 },
{ 0x71, 0x00000000 },
{ 0x72, 0x00000000 },
{ 0x73, 0x00000000 },
{ 0x74, 0x00000000 },
{ 0x75, 0x00000000 },
{ 0x76, 0x00000000 },
{ 0x77, 0x00000000 },
{ 0x78, 0x00000000 },
{ 0x79, 0x00000000 },
{ 0x7a, 0x00000000 },
{ 0x7b, 0x00000000 },
{ 0x7c, 0x00000000 },
{ 0x7d, 0x00000000 },
{ 0x7e, 0x00000000 },
{ 0x7f, 0x00020f00 },
{ 0x80, 0x00000000 },
{ 0x81, 0x00000000 },
{ 0x82, 0x00000000 },
{ 0x83, 0x00000000 },
{ 0x84, 0x00000000 },
{ 0x85, 0x00000000 },
{ 0x86, 0x00000000 },
{ 0x87, 0x00000000 },
{ 0x88, 0x00000000 },
{ 0x89, 0x00000000 },
{ 0x8a, 0x00000000 },
{ 0x8b, 0x00000000 },
{ 0x8c, 0x00000000 },
{ 0x8d, 0x00000000 },
{ 0x8e, 0x00000000 },
{ 0x90, 0x50250905 },
{ 0x91, 0x15050000 },
{ 0xa0, 0x00000000 },
{ 0xa1, 0x00000000 },
{ 0xa2, 0x00000000 },
{ 0xa3, 0x00000000 },
{ 0xa4, 0x00000000 },
{ 0xb0, 0x00000000 },
{ 0xb1, 0x00000000 },
{ 0xb2, 0x00000000 },
{ 0xb3, 0x00000000 },
{ 0xb4, 0x00000000 },
{ 0xb5, 0x00000000 },
{ 0xb6, 0x00000000 },
{ 0xb7, 0x00000000 },
{ 0xb8, 0x00000000 },
{ 0xb9, 0x00000000 },
{ 0xba, 0x00000000 },
{ 0xbb, 0x00000000 },
{ 0xc0, 0x01000000 },
{ 0xc1, 0x00000000 },
{ 0xf0, 0x00000000 },
};
static int rt1308_reg_init(struct snd_soc_component *component)
{
struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component);
return regmap_multi_reg_write(rt1308->regmap, init_list,
RT1308_INIT_REG_LEN);
}
static bool rt1308_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT1308_RESET:
case RT1308_RESET_N:
case RT1308_CLK_2:
case RT1308_SIL_DET:
case RT1308_CLK_DET:
case RT1308_DC_DET:
case RT1308_DAC_SET:
case RT1308_DAC_BUF:
case RT1308_SDW_REG_RDATA:
case RT1308_DC_CAL_1:
case RT1308_PVDD_OFFSET_CTL:
case RT1308_CAL_OFFSET_DAC_PBTL:
case RT1308_CAL_OFFSET_DAC_L:
case RT1308_CAL_OFFSET_DAC_R:
case RT1308_CAL_OFFSET_PWM_L:
case RT1308_CAL_OFFSET_PWM_R:
case RT1308_CAL_PWM_VOS_ADC_L:
case RT1308_CAL_PWM_VOS_ADC_R:
case RT1308_MBIAS:
case RT1308_POWER_STATUS:
case RT1308_POWER_INT:
case RT1308_SINE_TONE_GEN_2:
case RT1308_BQ_SET:
case RT1308_BQ_PARA_UPDATE:
case RT1308_VEN_DEV_ID:
case RT1308_VERSION_ID:
case RT1308_EFUSE_1:
case RT1308_EFUSE_READ_PVDD_L:
case RT1308_EFUSE_READ_PVDD_R:
case RT1308_EFUSE_READ_PVDD_PTBL:
case RT1308_EFUSE_READ_DEV:
case RT1308_EFUSE_READ_R0:
case RT1308_EFUSE_READ_ADC_L:
case RT1308_EFUSE_READ_ADC_R:
case RT1308_EFUSE_READ_ADC_PBTL:
case RT1308_EFUSE_RESERVE:
case RT1308_EFUSE_DATA_0_MSB:
case RT1308_EFUSE_DATA_0_LSB:
case RT1308_EFUSE_DATA_1_MSB:
case RT1308_EFUSE_DATA_1_LSB:
case RT1308_EFUSE_DATA_2_MSB:
case RT1308_EFUSE_DATA_2_LSB:
case RT1308_EFUSE_DATA_3_MSB:
case RT1308_EFUSE_DATA_3_LSB:
case RT1308_EFUSE_STATUS_1:
case RT1308_EFUSE_STATUS_2:
case RT1308_DUMMY_REG:
return true;
default:
return false;
}
}
static bool rt1308_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT1308_RESET:
case RT1308_RESET_N:
case RT1308_CLK_GATING ... RT1308_DC_DET_THRES:
case RT1308_DAC_SET ... RT1308_AD_FILTER_SET:
case RT1308_DC_CAL_1 ... RT1308_POWER_INT:
case RT1308_SINE_TONE_GEN_1:
case RT1308_SINE_TONE_GEN_2:
case RT1308_BQ_SET:
case RT1308_BQ_PARA_UPDATE:
case RT1308_BQ_PRE_VOL_L ... RT1308_BQ_POST_VOL_R:
case RT1308_BQ1_L_H0 ... RT1308_BQ2_R_A2:
case RT1308_VEN_DEV_ID:
case RT1308_VERSION_ID:
case RT1308_SPK_BOUND:
case RT1308_BQ1_EQ_L_1 ... RT1308_BQ2_EQ_R_3:
case RT1308_EFUSE_1 ... RT1308_EFUSE_RESERVE:
case RT1308_PADS_1:
case RT1308_PADS_2:
case RT1308_TEST_MODE:
case RT1308_TEST_1:
case RT1308_TEST_2:
case RT1308_TEST_3:
case RT1308_TEST_4:
case RT1308_EFUSE_DATA_0_MSB ... RT1308_EFUSE_STATUS_2:
case RT1308_TCON_1:
case RT1308_TCON_2:
case RT1308_DUMMY_REG:
case RT1308_MAX_REG:
return true;
default:
return false;
}
}
static int rt1308_classd_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
msleep(30);
snd_soc_component_update_bits(component, RT1308_POWER_STATUS,
RT1308_POW_PDB_REG_BIT, RT1308_POW_PDB_REG_BIT);
msleep(40);
break;
case SND_SOC_DAPM_PRE_PMD:
snd_soc_component_update_bits(component, RT1308_POWER_STATUS,
RT1308_POW_PDB_REG_BIT, 0);
usleep_range(150000, 200000);
break;
default:
break;
}
return 0;
}
static const char * const rt1308_rx_data_ch_select[] = {
"LR",
"LL",
"RL",
"RR",
};
static SOC_ENUM_SINGLE_DECL(rt1308_rx_data_ch_enum, RT1308_DATA_PATH, 24,
rt1308_rx_data_ch_select);
static const struct snd_kcontrol_new rt1308_snd_controls[] = {
/* I2S Data Channel Selection */
SOC_ENUM("RX Channel Select", rt1308_rx_data_ch_enum),
};
static const struct snd_kcontrol_new rt1308_sto_dac_l =
SOC_DAPM_SINGLE("Switch", RT1308_DAC_SET,
RT1308_DVOL_MUTE_L_EN_SFT, 1, 1);
static const struct snd_kcontrol_new rt1308_sto_dac_r =
SOC_DAPM_SINGLE("Switch", RT1308_DAC_SET,
RT1308_DVOL_MUTE_R_EN_SFT, 1, 1);
static const struct snd_soc_dapm_widget rt1308_dapm_widgets[] = {
/* Audio Interface */
SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
/* Supply Widgets */
SND_SOC_DAPM_SUPPLY("MBIAS20U", RT1308_POWER,
RT1308_POW_MBIAS20U_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ALDO", RT1308_POWER,
RT1308_POW_ALDO_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DBG", RT1308_POWER,
RT1308_POW_DBG_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DACL", RT1308_POWER,
RT1308_POW_DACL_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("CLK25M", RT1308_POWER,
RT1308_POW_CLK25M_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC_R", RT1308_POWER,
RT1308_POW_ADC_R_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC_L", RT1308_POWER,
RT1308_POW_ADC_L_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DLDO", RT1308_POWER,
RT1308_POW_DLDO_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("VREF", RT1308_POWER,
RT1308_POW_VREF_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MIXER_R", RT1308_POWER,
RT1308_POW_MIXER_R_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MIXER_L", RT1308_POWER,
RT1308_POW_MIXER_L_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MBIAS4U", RT1308_POWER,
RT1308_POW_MBIAS4U_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("PLL2_LDO", RT1308_POWER,
RT1308_POW_PLL2_LDO_EN_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("PLL2B", RT1308_POWER,
RT1308_POW_PLL2B_EN_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("PLL2F", RT1308_POWER,
RT1308_POW_PLL2F_EN_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("PLL2F2", RT1308_POWER,
RT1308_POW_PLL2F2_EN_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("PLL2B2", RT1308_POWER,
RT1308_POW_PLL2B2_EN_BIT, 0, NULL, 0),
/* Digital Interface */
SND_SOC_DAPM_SUPPLY("DAC Power", RT1308_POWER,
RT1308_POW_DAC1_BIT, 0, NULL, 0),
SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_SWITCH("DAC L", SND_SOC_NOPM, 0, 0, &rt1308_sto_dac_l),
SND_SOC_DAPM_SWITCH("DAC R", SND_SOC_NOPM, 0, 0, &rt1308_sto_dac_r),
/* Output Lines */
SND_SOC_DAPM_PGA_E("CLASS D", SND_SOC_NOPM, 0, 0, NULL, 0,
rt1308_classd_event,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_OUTPUT("SPOL"),
SND_SOC_DAPM_OUTPUT("SPOR"),
};
static const struct snd_soc_dapm_route rt1308_dapm_routes[] = {
{ "DAC", NULL, "AIF1RX" },
{ "DAC", NULL, "MBIAS20U" },
{ "DAC", NULL, "ALDO" },
{ "DAC", NULL, "DBG" },
{ "DAC", NULL, "DACL" },
{ "DAC", NULL, "CLK25M" },
{ "DAC", NULL, "ADC_R" },
{ "DAC", NULL, "ADC_L" },
{ "DAC", NULL, "DLDO" },
{ "DAC", NULL, "VREF" },
{ "DAC", NULL, "MIXER_R" },
{ "DAC", NULL, "MIXER_L" },
{ "DAC", NULL, "MBIAS4U" },
{ "DAC", NULL, "PLL2_LDO" },
{ "DAC", NULL, "PLL2B" },
{ "DAC", NULL, "PLL2F" },
{ "DAC", NULL, "PLL2F2" },
{ "DAC", NULL, "PLL2B2" },
{ "DAC L", "Switch", "DAC" },
{ "DAC R", "Switch", "DAC" },
{ "DAC L", NULL, "DAC Power" },
{ "DAC R", NULL, "DAC Power" },
{ "CLASS D", NULL, "DAC L" },
{ "CLASS D", NULL, "DAC R" },
{ "SPOL", NULL, "CLASS D" },
{ "SPOR", NULL, "CLASS D" },
};
static int rt1308_get_clk_info(int sclk, int rate)
{
int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
if (sclk <= 0 || rate <= 0)
return -EINVAL;
rate = rate << 8;
for (i = 0; i < ARRAY_SIZE(pd); i++)
if (sclk == rate * pd[i])
return i;
return -EINVAL;
}
static int rt1308_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component);
unsigned int val_len = 0, val_clk, mask_clk;
int pre_div, bclk_ms, frame_size;
rt1308->lrck = params_rate(params);
pre_div = rt1308_get_clk_info(rt1308->sysclk, rt1308->lrck);
if (pre_div < 0) {
dev_err(component->dev,
"Unsupported clock setting %d\n", rt1308->lrck);
return -EINVAL;
}
frame_size = snd_soc_params_to_frame_size(params);
if (frame_size < 0) {
dev_err(component->dev, "Unsupported frame size: %d\n",
frame_size);
return -EINVAL;
}
bclk_ms = frame_size > 32;
rt1308->bclk = rt1308->lrck * (32 << bclk_ms);
dev_dbg(component->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
bclk_ms, pre_div, dai->id);
dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n",
rt1308->lrck, pre_div, dai->id);
switch (params_width(params)) {
case 16:
val_len |= RT1308_I2S_DL_SEL_16B;
break;
case 20:
val_len |= RT1308_I2S_DL_SEL_20B;
break;
case 24:
val_len |= RT1308_I2S_DL_SEL_24B;
break;
case 8:
val_len |= RT1308_I2S_DL_SEL_8B;
break;
default:
return -EINVAL;
}
switch (dai->id) {
case RT1308_AIF1:
mask_clk = RT1308_DIV_FS_SYS_MASK;
val_clk = pre_div << RT1308_DIV_FS_SYS_SFT;
snd_soc_component_update_bits(component,
RT1308_I2S_SET_2, RT1308_I2S_DL_SEL_MASK,
val_len);
break;
default:
dev_err(component->dev, "Invalid dai->id: %d\n", dai->id);
return -EINVAL;
}
snd_soc_component_update_bits(component, RT1308_CLK_1,
mask_clk, val_clk);
return 0;
}
static int rt1308_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_component *component = dai->component;
struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component);
unsigned int reg_val = 0, reg1_val = 0;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
rt1308->master = 0;
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
break;
case SND_SOC_DAIFMT_LEFT_J:
reg_val |= RT1308_I2S_DF_SEL_LEFT;
break;
case SND_SOC_DAIFMT_DSP_A:
reg_val |= RT1308_I2S_DF_SEL_PCM_A;
break;
case SND_SOC_DAIFMT_DSP_B:
reg_val |= RT1308_I2S_DF_SEL_PCM_B;
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
case SND_SOC_DAIFMT_IB_NF:
reg1_val |= RT1308_I2S_BCLK_INV;
break;
default:
return -EINVAL;
}
switch (dai->id) {
case RT1308_AIF1:
snd_soc_component_update_bits(component,
RT1308_I2S_SET_1, RT1308_I2S_DF_SEL_MASK,
reg_val);
snd_soc_component_update_bits(component,
RT1308_I2S_SET_2, RT1308_I2S_BCLK_MASK,
reg1_val);
break;
default:
dev_err(component->dev, "Invalid dai->id: %d\n", dai->id);
return -EINVAL;
}
return 0;
}
static int rt1308_set_component_sysclk(struct snd_soc_component *component,
int clk_id, int source, unsigned int freq, int dir)
{
struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component);
unsigned int reg_val = 0;
if (freq == rt1308->sysclk && clk_id == rt1308->sysclk_src)
return 0;
switch (clk_id) {
case RT1308_FS_SYS_S_MCLK:
reg_val |= RT1308_SEL_FS_SYS_SRC_MCLK;
snd_soc_component_update_bits(component,
RT1308_CLK_DET, RT1308_MCLK_DET_EN_MASK,
RT1308_MCLK_DET_EN);
break;
case RT1308_FS_SYS_S_BCLK:
reg_val |= RT1308_SEL_FS_SYS_SRC_BCLK;
break;
case RT1308_FS_SYS_S_PLL:
reg_val |= RT1308_SEL_FS_SYS_SRC_PLL;
break;
case RT1308_FS_SYS_S_RCCLK:
reg_val |= RT1308_SEL_FS_SYS_SRC_RCCLK;
break;
default:
dev_err(component->dev, "Invalid clock id (%d)\n", clk_id);
return -EINVAL;
}
snd_soc_component_update_bits(component, RT1308_CLK_1,
RT1308_SEL_FS_SYS_MASK, reg_val);
rt1308->sysclk = freq;
rt1308->sysclk_src = clk_id;
dev_dbg(component->dev, "Sysclk is %dHz and clock id is %d\n",
freq, clk_id);
return 0;
}
static int rt1308_set_component_pll(struct snd_soc_component *component,
int pll_id, int source, unsigned int freq_in,
unsigned int freq_out)
{
struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component);
struct rl6231_pll_code pll_code;
int ret;
if (source == rt1308->pll_src && freq_in == rt1308->pll_in &&
freq_out == rt1308->pll_out)
return 0;
if (!freq_in || !freq_out) {
dev_dbg(component->dev, "PLL disabled\n");
rt1308->pll_in = 0;
rt1308->pll_out = 0;
snd_soc_component_update_bits(component,
RT1308_CLK_1, RT1308_SEL_FS_SYS_MASK,
RT1308_SEL_FS_SYS_SRC_MCLK);
return 0;
}
switch (source) {
case RT1308_PLL_S_MCLK:
snd_soc_component_update_bits(component,
RT1308_CLK_2, RT1308_SEL_PLL_SRC_MASK,
RT1308_SEL_PLL_SRC_MCLK);
snd_soc_component_update_bits(component,
RT1308_CLK_DET, RT1308_MCLK_DET_EN_MASK,
RT1308_MCLK_DET_EN);
break;
case RT1308_PLL_S_BCLK:
snd_soc_component_update_bits(component,
RT1308_CLK_2, RT1308_SEL_PLL_SRC_MASK,
RT1308_SEL_PLL_SRC_BCLK);
break;
case RT1308_PLL_S_RCCLK:
snd_soc_component_update_bits(component,
RT1308_CLK_2, RT1308_SEL_PLL_SRC_MASK,
RT1308_SEL_PLL_SRC_RCCLK);
freq_in = 25000000;
break;
default:
dev_err(component->dev, "Unknown PLL Source %d\n", source);
return -EINVAL;
}
ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
if (ret < 0) {
dev_err(component->dev, "Unsupport input clock %d\n", freq_in);
return ret;
}
dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n",
pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
pll_code.n_code, pll_code.k_code);
snd_soc_component_write(component, RT1308_PLL_1,
pll_code.k_code << RT1308_PLL1_K_SFT |
pll_code.m_bp << RT1308_PLL1_M_BYPASS_SFT |
(pll_code.m_bp ? 0 : pll_code.m_code) << RT1308_PLL1_M_SFT |
pll_code.n_code << RT1308_PLL1_N_SFT);
rt1308->pll_in = freq_in;
rt1308->pll_out = freq_out;
rt1308->pll_src = source;
return 0;
}
static int rt1308_probe(struct snd_soc_component *component)
{
struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component);
rt1308->component = component;
return rt1308_reg_init(component);
}
static void rt1308_remove(struct snd_soc_component *component)
{
struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component);
regmap_write(rt1308->regmap, RT1308_RESET, 0);
}
#ifdef CONFIG_PM
static int rt1308_suspend(struct snd_soc_component *component)
{
struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component);
regcache_cache_only(rt1308->regmap, true);
regcache_mark_dirty(rt1308->regmap);
return 0;
}
static int rt1308_resume(struct snd_soc_component *component)
{
struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component);
regcache_cache_only(rt1308->regmap, false);
regcache_sync(rt1308->regmap);
return 0;
}
#else
#define rt1308_suspend NULL
#define rt1308_resume NULL
#endif
#define RT1308_STEREO_RATES SNDRV_PCM_RATE_48000
#define RT1308_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE)
static const struct snd_soc_dai_ops rt1308_aif_dai_ops = {
.hw_params = rt1308_hw_params,
.set_fmt = rt1308_set_dai_fmt,
};
static struct snd_soc_dai_driver rt1308_dai[] = {
{
.name = "rt1308-aif",
.playback = {
.stream_name = "AIF1 Playback",
.channels_min = 1,
.channels_max = 2,
.rates = RT1308_STEREO_RATES,
.formats = RT1308_FORMATS,
},
.ops = &rt1308_aif_dai_ops,
},
};
static const struct snd_soc_component_driver soc_component_dev_rt1308 = {
.probe = rt1308_probe,
.remove = rt1308_remove,
.suspend = rt1308_suspend,
.resume = rt1308_resume,
.controls = rt1308_snd_controls,
.num_controls = ARRAY_SIZE(rt1308_snd_controls),
.dapm_widgets = rt1308_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(rt1308_dapm_widgets),
.dapm_routes = rt1308_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(rt1308_dapm_routes),
.set_sysclk = rt1308_set_component_sysclk,
.set_pll = rt1308_set_component_pll,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static const struct regmap_config rt1308_regmap = {
.reg_bits = 8,
.val_bits = 32,
.max_register = RT1308_MAX_REG,
.volatile_reg = rt1308_volatile_register,
.readable_reg = rt1308_readable_register,
.cache_type = REGCACHE_RBTREE,
.reg_defaults = rt1308_reg,
.num_reg_defaults = ARRAY_SIZE(rt1308_reg),
.use_single_read = true,
.use_single_write = true,
};
#ifdef CONFIG_OF
static const struct of_device_id rt1308_of_match[] = {
{ .compatible = "realtek,rt1308", },
{ },
};
MODULE_DEVICE_TABLE(of, rt1308_of_match);
#endif
#ifdef CONFIG_ACPI
static struct acpi_device_id rt1308_acpi_match[] = {
{ "10EC1308", 0, },
{ },
};
MODULE_DEVICE_TABLE(acpi, rt1308_acpi_match);
#endif
static const struct i2c_device_id rt1308_i2c_id[] = {
{ "rt1308", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt1308_i2c_id);
static void rt1308_efuse(struct rt1308_priv *rt1308)
{
regmap_write(rt1308->regmap, RT1308_RESET, 0);
regmap_write(rt1308->regmap, RT1308_POWER, 0xff371600);
regmap_write(rt1308->regmap, RT1308_CLK_1, 0x52100000);
regmap_write(rt1308->regmap, RT1308_I2C_I2S_SDW_SET, 0x01014005);
regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x227f5501);
regmap_write(rt1308->regmap, RT1308_PADS_1, 0x50150505);
regmap_write(rt1308->regmap, RT1308_VREF, 0x18100000);
regmap_write(rt1308->regmap, RT1308_IV_SENSE, 0x87010000);
regmap_write(rt1308->regmap, RT1308_DUMMY_REG, 0x00000200);
regmap_write(rt1308->regmap, RT1308_SIL_DET, 0x61c30000);
regmap_write(rt1308->regmap, RT1308_CLK_DET, 0x03700000);
regmap_write(rt1308->regmap, RT1308_SINE_TONE_GEN_1, 0x50022f00);
regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x01800000);
regmap_write(rt1308->regmap, RT1308_DC_CAL_2, 0x00ffff00);
regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x607e5501);
regmap_write(rt1308->regmap, RT1308_CLK_2, 0x0060e000);
regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x04fe0f00);
msleep(100);
regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x44fe0f00);
msleep(20);
regmap_write(rt1308->regmap, RT1308_PVDD_OFFSET_CTL, 0x10000000);
regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x00800000);
regmap_write(rt1308->regmap, RT1308_POWER, 0x0);
regmap_write(rt1308->regmap, RT1308_CLK_1, 0x52000000);
regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x227f5501);
regmap_write(rt1308->regmap, RT1308_SINE_TONE_GEN_1, 0x10022f00);
}
static int rt1308_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct rt1308_priv *rt1308;
int ret;
unsigned int val;
rt1308 = devm_kzalloc(&i2c->dev, sizeof(struct rt1308_priv),
GFP_KERNEL);
if (rt1308 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, rt1308);
rt1308->regmap = devm_regmap_init_i2c(i2c, &rt1308_regmap);
if (IS_ERR(rt1308->regmap)) {
ret = PTR_ERR(rt1308->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
return ret;
}
regmap_read(rt1308->regmap, RT1308_VEN_DEV_ID, &val);
/* ignore last byte difference */
if ((val & 0xFFFFFF00) != RT1308_DEVICE_ID_NUM) {
dev_err(&i2c->dev,
"Device with ID register %x is not rt1308\n", val);
return -ENODEV;
}
rt1308_efuse(rt1308);
return devm_snd_soc_register_component(&i2c->dev,
&soc_component_dev_rt1308,
rt1308_dai, ARRAY_SIZE(rt1308_dai));
}
static void rt1308_i2c_shutdown(struct i2c_client *client)
{
struct rt1308_priv *rt1308 = i2c_get_clientdata(client);
regmap_write(rt1308->regmap, RT1308_RESET, 0);
}
static struct i2c_driver rt1308_i2c_driver = {
.driver = {
.name = "rt1308",
.of_match_table = of_match_ptr(rt1308_of_match),
.acpi_match_table = ACPI_PTR(rt1308_acpi_match),
},
.probe = rt1308_i2c_probe,
.shutdown = rt1308_i2c_shutdown,
.id_table = rt1308_i2c_id,
};
module_i2c_driver(rt1308_i2c_driver);
MODULE_DESCRIPTION("ASoC RT1308 amplifier driver");
MODULE_AUTHOR("Derek Fang <derek.fang@realtek.com>");
MODULE_LICENSE("GPL v2");

291
sound/soc/codecs/rt1308.h Executable file
View file

@ -0,0 +1,291 @@
/*
* RT1308.h -- RT1308 ALSA SoC amplifier component driver
*
* Copyright 2019 Realtek Semiconductor Corp.
* Author: Derek Fang <derek.fang@realtek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _RT1308_H_
#define _RT1308_H_
#define RT1308_DEVICE_ID_NUM 0x10ec1300
#define RT1308_RESET 0x00
#define RT1308_RESET_N 0x01
#define RT1308_CLK_GATING 0x02
#define RT1308_PLL_1 0x03
#define RT1308_PLL_2 0x04
#define RT1308_PLL_INT 0x05
#define RT1308_CLK_1 0x06
#define RT1308_DATA_PATH 0x07
#define RT1308_CLK_2 0x08
#define RT1308_SIL_DET 0x09
#define RT1308_CLK_DET 0x0a
#define RT1308_DC_DET 0x0b
#define RT1308_DC_DET_THRES 0x0c
#define RT1308_DAC_SET 0x10
#define RT1308_SRC_SET 0x11
#define RT1308_DAC_BUF 0x12
#define RT1308_ADC_SET 0x13
#define RT1308_ADC_SET_INT 0x14
#define RT1308_I2S_SET_1 0x15
#define RT1308_I2S_SET_2 0x16
#define RT1308_I2C_I2S_SDW_SET 0x17
#define RT1308_SDW_REG_RW 0x18
#define RT1308_SDW_REG_RDATA 0x19
#define RT1308_IV_SENSE 0x1a
#define RT1308_I2S_TX_DAC_SET 0x1b
#define RT1308_AD_FILTER_SET 0x1c
#define RT1308_DC_CAL_1 0x20
#define RT1308_DC_CAL_2 0x21
#define RT1308_DC_CAL_L_OFFSET 0x22
#define RT1308_DC_CAL_R_OFFSET 0x23
#define RT1308_PVDD_OFFSET_CTL 0x24
#define RT1308_PVDD_OFFSET_L 0x25
#define RT1308_PVDD_OFFSET_R 0x26
#define RT1308_PVDD_OFFSET_PBTL 0x27
#define RT1308_PVDD_OFFSET_PVDD 0x28
#define RT1308_CAL_OFFSET_DAC_PBTL 0x29
#define RT1308_CAL_OFFSET_DAC_L 0x2a
#define RT1308_CAL_OFFSET_DAC_R 0x2b
#define RT1308_CAL_OFFSET_PWM_L 0x2c
#define RT1308_CAL_OFFSET_PWM_R 0x2d
#define RT1308_CAL_PWM_VOS_ADC_L 0x2e
#define RT1308_CAL_PWM_VOS_ADC_R 0x2f
#define RT1308_CLASS_D_SET_1 0x30
#define RT1308_CLASS_D_SET_2 0x31
#define RT1308_POWER 0x32
#define RT1308_LDO 0x33
#define RT1308_VREF 0x34
#define RT1308_MBIAS 0x35
#define RT1308_POWER_STATUS 0x36
#define RT1308_POWER_INT 0x37
#define RT1308_SINE_TONE_GEN_1 0x50
#define RT1308_SINE_TONE_GEN_2 0x51
#define RT1308_BQ_SET 0x54
#define RT1308_BQ_PARA_UPDATE 0x55
#define RT1308_BQ_PRE_VOL_L 0x56
#define RT1308_BQ_PRE_VOL_R 0x57
#define RT1308_BQ_POST_VOL_L 0x58
#define RT1308_BQ_POST_VOL_R 0x59
#define RT1308_BQ1_L_H0 0x5b
#define RT1308_BQ1_L_B1 0x5c
#define RT1308_BQ1_L_B2 0x5d
#define RT1308_BQ1_L_A1 0x5e
#define RT1308_BQ1_L_A2 0x5f
#define RT1308_BQ1_R_H0 0x60
#define RT1308_BQ1_R_B1 0x61
#define RT1308_BQ1_R_B2 0x62
#define RT1308_BQ1_R_A1 0x63
#define RT1308_BQ1_R_A2 0x64
#define RT1308_BQ2_L_H0 0x65
#define RT1308_BQ2_L_B1 0x66
#define RT1308_BQ2_L_B2 0x67
#define RT1308_BQ2_L_A1 0x68
#define RT1308_BQ2_L_A2 0x69
#define RT1308_BQ2_R_H0 0x6a
#define RT1308_BQ2_R_B1 0x6b
#define RT1308_BQ2_R_B2 0x6c
#define RT1308_BQ2_R_A1 0x6d
#define RT1308_BQ2_R_A2 0x6e
#define RT1308_VEN_DEV_ID 0x70
#define RT1308_VERSION_ID 0x71
#define RT1308_SPK_BOUND 0x72
#define RT1308_BQ1_EQ_L_1 0x73
#define RT1308_BQ1_EQ_L_2 0x74
#define RT1308_BQ1_EQ_L_3 0x75
#define RT1308_BQ1_EQ_R_1 0x76
#define RT1308_BQ1_EQ_R_2 0x77
#define RT1308_BQ1_EQ_R_3 0x78
#define RT1308_BQ2_EQ_L_1 0x79
#define RT1308_BQ2_EQ_L_2 0x7a
#define RT1308_BQ2_EQ_L_3 0x7b
#define RT1308_BQ2_EQ_R_1 0x7c
#define RT1308_BQ2_EQ_R_2 0x7d
#define RT1308_BQ2_EQ_R_3 0x7e
#define RT1308_EFUSE_1 0x7f
#define RT1308_EFUSE_2 0x80
#define RT1308_EFUSE_PROG_PVDD_L 0x81
#define RT1308_EFUSE_PROG_PVDD_R 0x82
#define RT1308_EFUSE_PROG_R0_L 0x83
#define RT1308_EFUSE_PROG_R0_R 0x84
#define RT1308_EFUSE_PROG_DEV 0x85
#define RT1308_EFUSE_READ_PVDD_L 0x86
#define RT1308_EFUSE_READ_PVDD_R 0x87
#define RT1308_EFUSE_READ_PVDD_PTBL 0x88
#define RT1308_EFUSE_READ_DEV 0x89
#define RT1308_EFUSE_READ_R0 0x8a
#define RT1308_EFUSE_READ_ADC_L 0x8b
#define RT1308_EFUSE_READ_ADC_R 0x8c
#define RT1308_EFUSE_READ_ADC_PBTL 0x8d
#define RT1308_EFUSE_RESERVE 0x8e
#define RT1308_PADS_1 0x90
#define RT1308_PADS_2 0x91
#define RT1308_TEST_MODE 0xa0
#define RT1308_TEST_1 0xa1
#define RT1308_TEST_2 0xa2
#define RT1308_TEST_3 0xa3
#define RT1308_TEST_4 0xa4
#define RT1308_EFUSE_DATA_0_MSB 0xb0
#define RT1308_EFUSE_DATA_0_LSB 0xb1
#define RT1308_EFUSE_DATA_1_MSB 0xb2
#define RT1308_EFUSE_DATA_1_LSB 0xb3
#define RT1308_EFUSE_DATA_2_MSB 0xb4
#define RT1308_EFUSE_DATA_2_LSB 0xb5
#define RT1308_EFUSE_DATA_3_MSB 0xb6
#define RT1308_EFUSE_DATA_3_LSB 0xb7
#define RT1308_EFUSE_DATA_TEST_MSB 0xb8
#define RT1308_EFUSE_DATA_TEST_LSB 0xb9
#define RT1308_EFUSE_STATUS_1 0xba
#define RT1308_EFUSE_STATUS_2 0xbb
#define RT1308_TCON_1 0xc0
#define RT1308_TCON_2 0xc1
#define RT1308_DUMMY_REG 0xf0
#define RT1308_MAX_REG 0xff
/* PLL1 M/N/K Code-1 (0x03) */
#define RT1308_PLL1_K_SFT 24
#define RT1308_PLL1_K_MASK (0x1f << 24)
#define RT1308_PLL1_M_BYPASS_MASK (0x1 << 23)
#define RT1308_PLL1_M_BYPASS_SFT 23
#define RT1308_PLL1_M_BYPASS (0x1 << 23)
#define RT1308_PLL1_M_MASK (0x3f << 16)
#define RT1308_PLL1_M_SFT 16
#define RT1308_PLL1_N_MASK (0x7f << 8)
#define RT1308_PLL1_N_SFT 8
/* CLOCK-1 (0x06) */
#define RT1308_DIV_FS_SYS_MASK (0xf << 28)
#define RT1308_DIV_FS_SYS_SFT 28
#define RT1308_SEL_FS_SYS_MASK (0x7 << 24)
#define RT1308_SEL_FS_SYS_SFT 24
#define RT1308_SEL_FS_SYS_SRC_MCLK (0x0 << 24)
#define RT1308_SEL_FS_SYS_SRC_BCLK (0x1 << 24)
#define RT1308_SEL_FS_SYS_SRC_PLL (0x2 << 24)
#define RT1308_SEL_FS_SYS_SRC_RCCLK (0x4 << 24)
/* CLOCK-2 (0x08) */
#define RT1308_DIV_PRE_PLL_MASK (0xf << 28)
#define RT1308_DIV_PRE_PLL_SFT 28
#define RT1308_SEL_PLL_SRC_MASK (0x7 << 24)
#define RT1308_SEL_PLL_SRC_SFT 24
#define RT1308_SEL_PLL_SRC_MCLK (0x0 << 24)
#define RT1308_SEL_PLL_SRC_BCLK (0x1 << 24)
#define RT1308_SEL_PLL_SRC_RCCLK (0x4 << 24)
/* Clock Detect (0x0a) */
#define RT1308_MCLK_DET_EN_MASK (0x1 << 25)
#define RT1308_MCLK_DET_EN_SFT 25
#define RT1308_MCLK_DET_EN (0x1 << 25)
#define RT1308_BCLK_DET_EN_MASK (0x1 << 24)
#define RT1308_BCLK_DET_EN_SFT 24
#define RT1308_BCLK_DET_EN (0x1 << 24)
/* DAC Setting (0x10) */
#define RT1308_DVOL_MUTE_R_EN_SFT 7
#define RT1308_DVOL_MUTE_L_EN_SFT 6
/* I2S Setting-1 (0x15) */
#define RT1308_I2S_DF_SEL_MASK (0x3 << 12)
#define RT1308_I2S_DF_SEL_SFT 12
#define RT1308_I2S_DF_SEL_I2S (0x0 << 12)
#define RT1308_I2S_DF_SEL_LEFT (0x1 << 12)
#define RT1308_I2S_DF_SEL_PCM_A (0x2 << 12)
#define RT1308_I2S_DF_SEL_PCM_B (0x3 << 12)
#define RT1308_I2S_DL_RX_SEL_MASK (0x7 << 4)
#define RT1308_I2S_DL_RX_SEL_SFT 4
#define RT1308_I2S_DL_RX_SEL_16B (0x0 << 4)
#define RT1308_I2S_DL_RX_SEL_20B (0x1 << 4)
#define RT1308_I2S_DL_RX_SEL_24B (0x2 << 4)
#define RT1308_I2S_DL_RX_SEL_32B (0x3 << 4)
#define RT1308_I2S_DL_RX_SEL_8B (0x4 << 4)
#define RT1308_I2S_DL_TX_SEL_MASK (0x7 << 0)
#define RT1308_I2S_DL_TX_SEL_SFT 0
#define RT1308_I2S_DL_TX_SEL_16B (0x0 << 0)
#define RT1308_I2S_DL_TX_SEL_20B (0x1 << 0)
#define RT1308_I2S_DL_TX_SEL_24B (0x2 << 0)
#define RT1308_I2S_DL_TX_SEL_32B (0x3 << 0)
#define RT1308_I2S_DL_TX_SEL_8B (0x4 << 0)
/* I2S Setting-2 (0x16) */
#define RT1308_I2S_DL_SEL_MASK (0x7 << 24)
#define RT1308_I2S_DL_SEL_SFT 24
#define RT1308_I2S_DL_SEL_16B (0x0 << 24)
#define RT1308_I2S_DL_SEL_20B (0x1 << 24)
#define RT1308_I2S_DL_SEL_24B (0x2 << 24)
#define RT1308_I2S_DL_SEL_32B (0x3 << 24)
#define RT1308_I2S_DL_SEL_8B (0x4 << 24)
#define RT1308_I2S_BCLK_MASK (0x1 << 14)
#define RT1308_I2S_BCLK_SFT 14
#define RT1308_I2S_BCLK_NORMAL (0x0 << 14)
#define RT1308_I2S_BCLK_INV (0x1 << 14)
/* Power Control-1 (0x32) */
#define RT1308_POW_MBIAS20U (0x1 << 31)
#define RT1308_POW_MBIAS20U_BIT 31
#define RT1308_POW_ALDO (0x1 << 30)
#define RT1308_POW_ALDO_BIT 30
#define RT1308_POW_DBG (0x1 << 29)
#define RT1308_POW_DBG_BIT 29
#define RT1308_POW_DACL (0x1 << 28)
#define RT1308_POW_DACL_BIT 28
#define RT1308_POW_DAC1 (0x1 << 27)
#define RT1308_POW_DAC1_BIT 27
#define RT1308_POW_CLK25M (0x1 << 26)
#define RT1308_POW_CLK25M_BIT 26
#define RT1308_POW_ADC_R (0x1 << 25)
#define RT1308_POW_ADC_R_BIT 25
#define RT1308_POW_ADC_L (0x1 << 24)
#define RT1308_POW_ADC_L_BIT 24
#define RT1308_POW_DLDO (0x1 << 21)
#define RT1308_POW_DLDO_BIT 21
#define RT1308_POW_VREF (0x1 << 20)
#define RT1308_POW_VREF_BIT 20
#define RT1308_POW_MIXER_R (0x1 << 18)
#define RT1308_POW_MIXER_R_BIT 18
#define RT1308_POW_MIXER_L (0x1 << 17)
#define RT1308_POW_MIXER_L_BIT 17
#define RT1308_POW_MBIAS4U (0x1 << 16)
#define RT1308_POW_MBIAS4U_BIT 16
#define RT1308_POW_PLL2_LDO_EN (0x1 << 12)
#define RT1308_POW_PLL2_LDO_EN_BIT 12
#define RT1308_POW_PLL2B_EN (0x1 << 11)
#define RT1308_POW_PLL2B_EN_BIT 11
#define RT1308_POW_PLL2F_EN (0x1 << 10)
#define RT1308_POW_PLL2F_EN_BIT 10
#define RT1308_POW_PLL2F2_EN (0x1 << 9)
#define RT1308_POW_PLL2F2_EN_BIT 9
#define RT1308_POW_PLL2B2_EN (0x1 << 8)
#define RT1308_POW_PLL2B2_EN_BIT 8
/* Power Control-2 (0x36) */
#define RT1308_POW_PDB_SRC_BIT (0x1 << 27)
#define RT1308_POW_PDB_MN_BIT (0x1 << 25)
#define RT1308_POW_PDB_REG_BIT (0x1 << 24)
/* System Clock Source */
enum {
RT1308_FS_SYS_S_MCLK,
RT1308_FS_SYS_S_BCLK,
RT1308_FS_SYS_S_PLL,
RT1308_FS_SYS_S_RCCLK, /* 25.0 MHz */
};
/* PLL Source */
enum {
RT1308_PLL_S_MCLK,
RT1308_PLL_S_BCLK,
RT1308_PLL_S_RCCLK,
};
enum {
RT1308_AIF1,
RT1308_AIFS
};
#endif /* end of _RT1308_H_ */

View file

@ -470,9 +470,7 @@ static int __maybe_unused rt5514_suspend(struct device *dev)
static int __maybe_unused rt5514_resume(struct device *dev)
{
struct snd_soc_component *component = snd_soc_lookup_component(dev, DRV_NAME);
struct rt5514_dsp *rt5514_dsp =
snd_soc_component_get_drvdata(component);
struct rt5514_dsp *rt5514_dsp = dev_get_drvdata(dev);
int irq = to_spi_device(dev)->irq;
u8 buf[8];

View file

@ -1478,7 +1478,7 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct rt5665_priv *rt5665 = snd_soc_component_get_drvdata(component);
int pd, idx = -EINVAL;
int pd, idx;
pd = rl6231_get_pre_div(rt5665->regmap,
RT5665_ADDA_CLK_1, RT5665_I2S_PD1_SFT);

View file

@ -26,6 +26,8 @@
#include "rt5677-spi.h"
#define DRV_NAME "rt5677spi"
#define RT5677_SPI_BURST_LEN 240
#define RT5677_SPI_HEADER 5
#define RT5677_SPI_FREQ 6000000
@ -230,7 +232,7 @@ MODULE_DEVICE_TABLE(acpi, rt5677_spi_acpi_id);
static struct spi_driver rt5677_spi_driver = {
.driver = {
.name = "rt5677",
.name = DRV_NAME,
.acpi_match_table = ACPI_PTR(rt5677_spi_acpi_id),
},
.probe = rt5677_spi_probe,

View file

@ -20,6 +20,10 @@
#include <linux/firmware.h>
#include <linux/of_device.h>
#include <linux/property.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/workqueue.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@ -829,13 +833,13 @@ static const struct snd_kcontrol_new rt5677_snd_controls[] = {
/* DAC Digital Volume */
SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5677_DAC1_DIG_VOL,
RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 87, 0, dac_vol_tlv),
RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 127, 0, dac_vol_tlv),
SOC_DOUBLE_TLV("DAC2 Playback Volume", RT5677_DAC2_DIG_VOL,
RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 87, 0, dac_vol_tlv),
RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 127, 0, dac_vol_tlv),
SOC_DOUBLE_TLV("DAC3 Playback Volume", RT5677_DAC3_DIG_VOL,
RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 87, 0, dac_vol_tlv),
RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 127, 0, dac_vol_tlv),
SOC_DOUBLE_TLV("DAC4 Playback Volume", RT5677_DAC4_DIG_VOL,
RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 87, 0, dac_vol_tlv),
RT5677_L_VOL_SFT, RT5677_R_VOL_SFT, 127, 0, dac_vol_tlv),
/* IN1/IN2 Control */
SOC_SINGLE_TLV("IN1 Boost", RT5677_IN1, RT5677_BST_SFT1, 8, 0, bst_tlv),
@ -2604,7 +2608,8 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5677_ASRC_1, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("I2S3 ASRC", 1, RT5677_ASRC_1, 2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("I2S4 ASRC", 1, RT5677_ASRC_1, 3, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("DAC STO ASRC", 1, RT5677_ASRC_2, 14, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("DAC STO ASRC", 1, RT5677_ASRC_2, 14, 0,
rt5677_filter_power_event, SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY_S("DAC MONO2 L ASRC", 1, RT5677_ASRC_2, 13, 0, NULL,
0),
SND_SOC_DAPM_SUPPLY_S("DAC MONO2 R ASRC", 1, RT5677_ASRC_2, 12, 0, NULL,
@ -4617,7 +4622,6 @@ static void rt5677_gpio_config(struct rt5677_priv *rt5677, unsigned offset,
static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct rt5677_priv *rt5677 = gpiochip_get_data(chip);
struct regmap_irq_chip_data *data = rt5677->irq_data;
int irq;
if ((rt5677->pdata.jd1_gpio == 1 && offset == RT5677_GPIO1) ||
@ -4643,11 +4647,11 @@ static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset)
return -ENXIO;
}
return regmap_irq_get_virq(data, irq);
return irq_create_mapping(rt5677->domain, irq);
}
static const struct gpio_chip rt5677_template_chip = {
.label = "rt5677",
.label = RT5677_DRV_NAME,
.owner = THIS_MODULE,
.direction_output = rt5677_gpio_direction_out,
.set = rt5677_gpio_set,
@ -4713,37 +4717,13 @@ static int rt5677_probe(struct snd_soc_component *component)
snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
regmap_write(rt5677->regmap, RT5677_DIG_MISC, 0x0020);
regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC,
~RT5677_IRQ_DEBOUNCE_SEL_MASK, 0x0020);
regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x0c00);
for (i = 0; i < RT5677_GPIO_NUM; i++)
rt5677_gpio_config(rt5677, i, rt5677->pdata.gpio_config[i]);
if (rt5677->irq_data) {
regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL1, 0x8000,
0x8000);
regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x0018,
0x0008);
if (rt5677->pdata.jd1_gpio)
regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1,
RT5677_SEL_GPIO_JD1_MASK,
rt5677->pdata.jd1_gpio <<
RT5677_SEL_GPIO_JD1_SFT);
if (rt5677->pdata.jd2_gpio)
regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1,
RT5677_SEL_GPIO_JD2_MASK,
rt5677->pdata.jd2_gpio <<
RT5677_SEL_GPIO_JD2_SFT);
if (rt5677->pdata.jd3_gpio)
regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1,
RT5677_SEL_GPIO_JD3_MASK,
rt5677->pdata.jd3_gpio <<
RT5677_SEL_GPIO_JD3_SFT);
}
mutex_init(&rt5677->dsp_cmd_lock);
mutex_init(&rt5677->dsp_pri_lock);
@ -4955,6 +4935,7 @@ static struct snd_soc_dai_driver rt5677_dai[] = {
};
static const struct snd_soc_component_driver soc_component_dev_rt5677 = {
.name = RT5677_DRV_NAME,
.probe = rt5677_probe,
.remove = rt5677_remove,
.suspend = rt5677_suspend,
@ -5016,80 +4997,202 @@ static const struct acpi_device_id rt5677_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, rt5677_acpi_match);
static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677,
static void rt5677_read_device_properties(struct rt5677_priv *rt5677,
struct device *dev)
{
u32 val;
if (!device_property_read_u32(dev, "DCLK", &val))
rt5677->pdata.dmic2_clk_pin = val;
rt5677->pdata.in1_diff =
device_property_read_bool(dev, "IN1") ||
device_property_read_bool(dev, "realtek,in1-differential");
rt5677->pdata.in1_diff = device_property_read_bool(dev, "IN1");
rt5677->pdata.in2_diff = device_property_read_bool(dev, "IN2");
rt5677->pdata.lout1_diff = device_property_read_bool(dev, "OUT1");
rt5677->pdata.lout2_diff = device_property_read_bool(dev, "OUT2");
rt5677->pdata.lout3_diff = device_property_read_bool(dev, "OUT3");
rt5677->pdata.in2_diff =
device_property_read_bool(dev, "IN2") ||
device_property_read_bool(dev, "realtek,in2-differential");
device_property_read_u32(dev, "JD1", &rt5677->pdata.jd1_gpio);
device_property_read_u32(dev, "JD2", &rt5677->pdata.jd2_gpio);
device_property_read_u32(dev, "JD3", &rt5677->pdata.jd3_gpio);
}
rt5677->pdata.lout1_diff =
device_property_read_bool(dev, "OUT1") ||
device_property_read_bool(dev, "realtek,lout1-differential");
static void rt5677_read_device_properties(struct rt5677_priv *rt5677,
struct device *dev)
{
rt5677->pdata.in1_diff = device_property_read_bool(dev,
"realtek,in1-differential");
rt5677->pdata.in2_diff = device_property_read_bool(dev,
"realtek,in2-differential");
rt5677->pdata.lout1_diff = device_property_read_bool(dev,
"realtek,lout1-differential");
rt5677->pdata.lout2_diff = device_property_read_bool(dev,
"realtek,lout2-differential");
rt5677->pdata.lout3_diff = device_property_read_bool(dev,
"realtek,lout3-differential");
rt5677->pdata.lout2_diff =
device_property_read_bool(dev, "OUT2") ||
device_property_read_bool(dev, "realtek,lout2-differential");
rt5677->pdata.lout3_diff =
device_property_read_bool(dev, "OUT3") ||
device_property_read_bool(dev, "realtek,lout3-differential");
device_property_read_u8_array(dev, "realtek,gpio-config",
rt5677->pdata.gpio_config, RT5677_GPIO_NUM);
rt5677->pdata.gpio_config,
RT5677_GPIO_NUM);
device_property_read_u32(dev, "realtek,jd1-gpio",
&rt5677->pdata.jd1_gpio);
device_property_read_u32(dev, "realtek,jd2-gpio",
&rt5677->pdata.jd2_gpio);
device_property_read_u32(dev, "realtek,jd3-gpio",
&rt5677->pdata.jd3_gpio);
if (!device_property_read_u32(dev, "DCLK", &val) ||
!device_property_read_u32(dev, "realtek,dmic2_clk_pin", &val))
rt5677->pdata.dmic2_clk_pin = val;
if (!device_property_read_u32(dev, "JD1", &val) ||
!device_property_read_u32(dev, "realtek,jd1-gpio", &val))
rt5677->pdata.jd1_gpio = val;
if (!device_property_read_u32(dev, "JD2", &val) ||
!device_property_read_u32(dev, "realtek,jd2-gpio", &val))
rt5677->pdata.jd2_gpio = val;
if (!device_property_read_u32(dev, "JD3", &val) ||
!device_property_read_u32(dev, "realtek,jd3-gpio", &val))
rt5677->pdata.jd3_gpio = val;
}
static struct regmap_irq rt5677_irqs[] = {
struct rt5677_irq_desc {
unsigned int enable_mask;
unsigned int status_mask;
unsigned int polarity_mask;
};
static const struct rt5677_irq_desc rt5677_irq_descs[] = {
[RT5677_IRQ_JD1] = {
.reg_offset = 0,
.mask = RT5677_EN_IRQ_GPIO_JD1,
.enable_mask = RT5677_EN_IRQ_GPIO_JD1,
.status_mask = RT5677_STA_GPIO_JD1,
.polarity_mask = RT5677_INV_GPIO_JD1,
},
[RT5677_IRQ_JD2] = {
.reg_offset = 0,
.mask = RT5677_EN_IRQ_GPIO_JD2,
.enable_mask = RT5677_EN_IRQ_GPIO_JD2,
.status_mask = RT5677_STA_GPIO_JD2,
.polarity_mask = RT5677_INV_GPIO_JD2,
},
[RT5677_IRQ_JD3] = {
.reg_offset = 0,
.mask = RT5677_EN_IRQ_GPIO_JD3,
.enable_mask = RT5677_EN_IRQ_GPIO_JD3,
.status_mask = RT5677_STA_GPIO_JD3,
.polarity_mask = RT5677_INV_GPIO_JD3,
},
};
static struct regmap_irq_chip rt5677_irq_chip = {
.name = "rt5677",
.irqs = rt5677_irqs,
.num_irqs = ARRAY_SIZE(rt5677_irqs),
static irqreturn_t rt5677_irq(int unused, void *data)
{
struct rt5677_priv *rt5677 = data;
int ret = 0, loop, i, reg_irq, virq;
bool irq_fired = false;
.num_regs = 1,
.status_base = RT5677_IRQ_CTRL1,
.mask_base = RT5677_IRQ_CTRL1,
.mask_invert = 1,
mutex_lock(&rt5677->irq_lock);
/*
* Loop to handle interrupts until the last i2c read shows no pending
* irqs. The interrupt line is shared by multiple interrupt sources.
* After the regmap_read() below, a new interrupt source line may
* become high before the regmap_write() finishes, so there isn't a
* rising edge on the shared interrupt line for the new interrupt. Thus,
* the loop is needed to avoid missing irqs.
*
* A safeguard of 20 loops is used to avoid hanging in the irq handler
* if there is something wrong with the interrupt status update. The
* interrupt sources here are audio jack plug/unplug events which
* shouldn't happen at a high frequency for a long period of time.
* Empirically, more than 3 loops have never been seen.
*/
for (loop = 0; loop < 20; loop++) {
/* Read interrupt status */
ret = regmap_read(rt5677->regmap, RT5677_IRQ_CTRL1, &reg_irq);
if (ret) {
dev_err(rt5677->dev, "failed reading IRQ status: %d\n",
ret);
goto exit;
}
irq_fired = false;
for (i = 0; i < RT5677_IRQ_NUM; i++) {
if (reg_irq & rt5677_irq_descs[i].status_mask) {
irq_fired = true;
virq = irq_find_mapping(rt5677->domain, i);
if (virq)
handle_nested_irq(virq);
/* Clear the interrupt by flipping the polarity
* of the interrupt source line that fired
*/
reg_irq ^= rt5677_irq_descs[i].polarity_mask;
}
}
if (!irq_fired)
goto exit;
ret = regmap_write(rt5677->regmap, RT5677_IRQ_CTRL1, reg_irq);
if (ret) {
dev_err(rt5677->dev, "failed updating IRQ status: %d\n",
ret);
goto exit;
}
}
exit:
mutex_unlock(&rt5677->irq_lock);
if (irq_fired)
return IRQ_HANDLED;
else
return IRQ_NONE;
}
static void rt5677_irq_bus_lock(struct irq_data *data)
{
struct rt5677_priv *rt5677 = irq_data_get_irq_chip_data(data);
mutex_lock(&rt5677->irq_lock);
}
static void rt5677_irq_bus_sync_unlock(struct irq_data *data)
{
struct rt5677_priv *rt5677 = irq_data_get_irq_chip_data(data);
// Set the enable/disable bits for the jack detect IRQs.
regmap_update_bits(rt5677->regmap, RT5677_IRQ_CTRL1,
RT5677_EN_IRQ_GPIO_JD1 | RT5677_EN_IRQ_GPIO_JD2 |
RT5677_EN_IRQ_GPIO_JD3, rt5677->irq_en);
mutex_unlock(&rt5677->irq_lock);
}
static void rt5677_irq_enable(struct irq_data *data)
{
struct rt5677_priv *rt5677 = irq_data_get_irq_chip_data(data);
rt5677->irq_en |= rt5677_irq_descs[data->hwirq].enable_mask;
}
static void rt5677_irq_disable(struct irq_data *data)
{
struct rt5677_priv *rt5677 = irq_data_get_irq_chip_data(data);
rt5677->irq_en &= ~rt5677_irq_descs[data->hwirq].enable_mask;
}
static struct irq_chip rt5677_irq_chip = {
.name = "rt5677_irq_chip",
.irq_bus_lock = rt5677_irq_bus_lock,
.irq_bus_sync_unlock = rt5677_irq_bus_sync_unlock,
.irq_disable = rt5677_irq_disable,
.irq_enable = rt5677_irq_enable,
};
static int rt5677_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
struct rt5677_priv *rt5677 = h->host_data;
irq_set_chip_data(virq, rt5677);
irq_set_chip(virq, &rt5677_irq_chip);
irq_set_nested_thread(virq, 1);
irq_set_noprobe(virq);
return 0;
}
static const struct irq_domain_ops rt5677_domain_ops = {
.map = rt5677_irq_map,
.xlate = irq_domain_xlate_twocell,
};
static int rt5677_init_irq(struct i2c_client *i2c)
{
int ret;
struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c);
unsigned int jd_mask = 0, jd_val = 0;
if (!rt5677->pdata.jd1_gpio &&
!rt5677->pdata.jd2_gpio &&
@ -5101,24 +5204,53 @@ static int rt5677_init_irq(struct i2c_client *i2c)
return -EINVAL;
}
ret = regmap_add_irq_chip(rt5677->regmap, i2c->irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 0,
&rt5677_irq_chip, &rt5677->irq_data);
mutex_init(&rt5677->irq_lock);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to register IRQ chip: %d\n", ret);
return ret;
/*
* Select RC as the debounce clock so that GPIO works even when
* MCLK is gated which happens when there is no audio stream
* (SND_SOC_BIAS_OFF).
*/
regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC,
RT5677_IRQ_DEBOUNCE_SEL_MASK,
RT5677_IRQ_DEBOUNCE_SEL_RC);
/* Enable auto power on RC when GPIO states are changed */
regmap_update_bits(rt5677->regmap, RT5677_GEN_CTRL1, 0xff, 0xff);
/* Select and enable jack detection sources per platform data */
if (rt5677->pdata.jd1_gpio) {
jd_mask |= RT5677_SEL_GPIO_JD1_MASK;
jd_val |= rt5677->pdata.jd1_gpio << RT5677_SEL_GPIO_JD1_SFT;
}
if (rt5677->pdata.jd2_gpio) {
jd_mask |= RT5677_SEL_GPIO_JD2_MASK;
jd_val |= rt5677->pdata.jd2_gpio << RT5677_SEL_GPIO_JD2_SFT;
}
if (rt5677->pdata.jd3_gpio) {
jd_mask |= RT5677_SEL_GPIO_JD3_MASK;
jd_val |= rt5677->pdata.jd3_gpio << RT5677_SEL_GPIO_JD3_SFT;
}
regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1, jd_mask, jd_val);
/* Set GPIO1 pin to be IRQ output */
regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL1,
RT5677_GPIO1_PIN_MASK, RT5677_GPIO1_PIN_IRQ);
/* Ready to listen for interrupts */
rt5677->domain = irq_domain_add_linear(i2c->dev.of_node,
RT5677_IRQ_NUM, &rt5677_domain_ops, rt5677);
if (!rt5677->domain) {
dev_err(&i2c->dev, "Failed to create IRQ domain\n");
return -ENOMEM;
}
return 0;
}
ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, rt5677_irq,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"rt5677", rt5677);
if (ret)
dev_err(&i2c->dev, "Failed to request IRQ: %d\n", ret);
static void rt5677_free_irq(struct i2c_client *i2c)
{
struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c);
if (rt5677->irq_data)
regmap_del_irq_chip(i2c->irq, rt5677->irq_data);
return ret;
}
static int rt5677_i2c_probe(struct i2c_client *i2c)
@ -5132,6 +5264,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c)
if (rt5677 == NULL)
return -ENOMEM;
rt5677->dev = &i2c->dev;
i2c_set_clientdata(i2c, rt5677);
if (i2c->dev.of_node) {
@ -5140,20 +5273,18 @@ static int rt5677_i2c_probe(struct i2c_client *i2c)
match_id = of_match_device(rt5677_of_match, &i2c->dev);
if (match_id)
rt5677->type = (enum rt5677_type)match_id->data;
rt5677_read_device_properties(rt5677, &i2c->dev);
} else if (ACPI_HANDLE(&i2c->dev)) {
const struct acpi_device_id *acpi_id;
acpi_id = acpi_match_device(rt5677_acpi_match, &i2c->dev);
if (acpi_id)
rt5677->type = (enum rt5677_type)acpi_id->driver_data;
rt5677_read_acpi_properties(rt5677, &i2c->dev);
} else {
return -EINVAL;
}
rt5677_read_device_properties(rt5677, &i2c->dev);
/* pow-ldo2 and reset are optional. The codec pins may be statically
* connected on the board without gpios. If the gpio device property
* isn't specified, devm_gpiod_get_optional returns NULL.
@ -5247,7 +5378,9 @@ static int rt5677_i2c_probe(struct i2c_client *i2c)
RT5677_MICBIAS1_CTRL_VDD_3_3V);
rt5677_init_gpio(i2c);
rt5677_init_irq(i2c);
ret = rt5677_init_irq(i2c);
if (ret)
dev_err(&i2c->dev, "Failed to initialize irq: %d\n", ret);
return devm_snd_soc_register_component(&i2c->dev,
&soc_component_dev_rt5677,
@ -5256,7 +5389,6 @@ static int rt5677_i2c_probe(struct i2c_client *i2c)
static int rt5677_i2c_remove(struct i2c_client *i2c)
{
rt5677_free_irq(i2c);
rt5677_free_gpio(i2c);
return 0;
@ -5264,7 +5396,7 @@ static int rt5677_i2c_remove(struct i2c_client *i2c)
static struct i2c_driver rt5677_i2c_driver = {
.driver = {
.name = "rt5677",
.name = RT5677_DRV_NAME,
.of_match_table = rt5677_of_match,
.acpi_match_table = ACPI_PTR(rt5677_acpi_match),
},

View file

@ -1453,9 +1453,37 @@
#define RT5677_I2S4_CLK_SEL_MASK (0xf)
#define RT5677_I2S4_CLK_SEL_SFT 0
/* VAD Function Control 1 (0x9c) */
#define RT5677_VAD_MIN_DUR_MASK (0x3 << 13)
#define RT5677_VAD_MIN_DUR_SFT 13
#define RT5677_VAD_ADPCM_BYPASS (1 << 10)
#define RT5677_VAD_ADPCM_BYPASS_BIT 10
#define RT5677_VAD_FG2ENC (1 << 9)
#define RT5677_VAD_FG2ENC_BIT 9
#define RT5677_VAD_BUF_OW (1 << 8)
#define RT5677_VAD_BUF_OW_BIT 8
#define RT5677_VAD_CLR_FLAG (1 << 7)
#define RT5677_VAD_CLR_FLAG_BIT 7
#define RT5677_VAD_BUF_POP (1 << 6)
#define RT5677_VAD_BUF_POP_BIT 6
#define RT5677_VAD_BUF_PUSH (1 << 5)
#define RT5677_VAD_BUF_PUSH_BIT 5
#define RT5677_VAD_DET_ENABLE (1 << 4)
#define RT5677_VAD_DET_ENABLE_BIT 4
#define RT5677_VAD_FUNC_ENABLE (1 << 3)
#define RT5677_VAD_FUNC_ENABLE_BIT 3
#define RT5677_VAD_FUNC_RESET (1 << 2)
#define RT5677_VAD_FUNC_RESET_BIT 2
/* VAD Function Control 4 (0x9f) */
#define RT5677_VAD_SRC_MASK (0x7 << 8)
#define RT5677_VAD_OUT_SRC_RATE_MASK (0x1 << 11)
#define RT5677_VAD_OUT_SRC_RATE_SFT 11
#define RT5677_VAD_OUT_SRC_MASK (0x1 << 10)
#define RT5677_VAD_OUT_SRC_SFT 10
#define RT5677_VAD_SRC_MASK (0x3 << 8)
#define RT5677_VAD_SRC_SFT 8
#define RT5677_VAD_LV_DIFF_MASK (0xff << 0)
#define RT5677_VAD_LV_DIFF_SFT 0
/* DSP InBound Control (0xa3) */
#define RT5677_IB01_SRC_MASK (0x7 << 12)
@ -1633,6 +1661,12 @@
#define RT5677_GPIO6_P_NOR (0x0 << 0)
#define RT5677_GPIO6_P_INV (0x1 << 0)
/* General Control (0xfa) */
#define RT5677_IRQ_DEBOUNCE_SEL_MASK (0x3 << 3)
#define RT5677_IRQ_DEBOUNCE_SEL_MCLK (0x0 << 3)
#define RT5677_IRQ_DEBOUNCE_SEL_RC (0x1 << 3)
#define RT5677_IRQ_DEBOUNCE_SEL_SLIM (0x2 << 3)
/* Virtual DSP Mixer Control (0xf7 0xf8 0xf9) */
#define RT5677_DSP_IB_01_H (0x1 << 15)
#define RT5677_DSP_IB_01_H_SFT 15
@ -1671,6 +1705,8 @@
#define RT5677_FIRMWARE1 "rt5677_dsp_fw1.bin"
#define RT5677_FIRMWARE2 "rt5677_dsp_fw2.bin"
#define RT5677_DRV_NAME "rt5677"
/* System Clock Source */
enum {
RT5677_SCLK_S_MCLK,
@ -1710,6 +1746,7 @@ enum {
RT5677_IRQ_JD1,
RT5677_IRQ_JD2,
RT5677_IRQ_JD3,
RT5677_IRQ_NUM,
};
enum rt5677_type {
@ -1788,6 +1825,7 @@ struct rt5677_platform_data {
struct rt5677_priv {
struct snd_soc_component *component;
struct device *dev;
struct rt5677_platform_data pdata;
struct regmap *regmap, *regmap_physical;
const struct firmware *fw1, *fw2;
@ -1808,9 +1846,13 @@ struct rt5677_priv {
struct gpio_chip gpio_chip;
#endif
bool dsp_vad_en;
struct regmap_irq_chip_data *irq_data;
bool is_dsp_mode;
bool is_vref_slow;
/* Interrupt handling */
struct irq_domain *domain;
struct mutex irq_lock;
unsigned int irq_en;
};
int rt5677_sel_asrc_clk_src(struct snd_soc_component *component,

View file

@ -2662,15 +2662,9 @@ static int rt5682_i2c_probe(struct i2c_client *i2c,
}
return snd_soc_register_component(&i2c->dev, &soc_component_dev_rt5682,
rt5682_dai, ARRAY_SIZE(rt5682_dai));
}
static int rt5682_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_component(&i2c->dev);
return 0;
return devm_snd_soc_register_component(&i2c->dev,
&soc_component_dev_rt5682,
rt5682_dai, ARRAY_SIZE(rt5682_dai));
}
static void rt5682_i2c_shutdown(struct i2c_client *client)
@ -2703,7 +2697,6 @@ static struct i2c_driver rt5682_i2c_driver = {
.acpi_match_table = ACPI_PTR(rt5682_acpi_match),
},
.probe = rt5682_i2c_probe,
.remove = rt5682_i2c_remove,
.shutdown = rt5682_i2c_shutdown,
.id_table = rt5682_i2c_id,
};

View file

@ -721,8 +721,8 @@ static const struct regmap_config tas5721_regmap_config = {
static const struct tas571x_chip tas5721_chip = {
.supply_names = tas5721_supply_names,
.num_supply_names = ARRAY_SIZE(tas5721_supply_names),
.controls = tas5711_controls,
.num_controls = ARRAY_SIZE(tas5711_controls),
.controls = tas5721_controls,
.num_controls = ARRAY_SIZE(tas5721_controls),
.regmap_config = &tas5721_regmap_config,
.vol_reg_size = 1,
};

View file

@ -321,6 +321,9 @@ static DECLARE_TLV_DB_SCALE(adc_tlv, 0, 50, 0);
*/
static DECLARE_TLV_DB_SCALE(output_stage_tlv, -5900, 50, 1);
/* Output volumes. From 0 to 9 dB in 1 dB steps */
static const DECLARE_TLV_DB_SCALE(out_tlv, 0, 100, 0);
static const struct snd_kcontrol_new aic3x_snd_controls[] = {
/* Output */
SOC_DOUBLE_R_TLV("PCM Playback Volume",
@ -383,11 +386,17 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL,
0, 118, 1, output_stage_tlv),
/* Output pin mute controls */
/* Output pin controls */
SOC_DOUBLE_R_TLV("Line Playback Volume", LLOPM_CTRL, RLOPM_CTRL, 4,
9, 0, out_tlv),
SOC_DOUBLE_R("Line Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3,
0x01, 0),
SOC_DOUBLE_R_TLV("HP Playback Volume", HPLOUT_CTRL, HPROUT_CTRL, 4,
9, 0, out_tlv),
SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3,
0x01, 0),
SOC_DOUBLE_R_TLV("HPCOM Playback Volume", HPLCOM_CTRL, HPRCOM_CTRL,
4, 9, 0, out_tlv),
SOC_DOUBLE_R("HPCOM Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3,
0x01, 0),
@ -469,6 +478,9 @@ static const struct snd_kcontrol_new aic3x_mono_controls[] = {
0, 118, 1, output_stage_tlv),
SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0),
SOC_SINGLE_TLV("Mono Playback Volume", MONOLOPM_CTRL, 4, 9, 0,
out_tlv),
};
/*

View file

@ -86,11 +86,6 @@
#define WCD9335_DEC_PWR_LVL_HP 0x04
#define WCD9335_DEC_PWR_LVL_DF 0x00
#define TX_HPF_CUT_OFF_FREQ_MASK 0x60
#define CF_MIN_3DB_4HZ 0x0
#define CF_MIN_3DB_75HZ 0x1
#define CF_MIN_3DB_150HZ 0x2
#define WCD9335_SLIM_RX_CH(p) \
{.port = p + WCD9335_RX_START, .shift = p,}
@ -2734,7 +2729,7 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w,
char *dec;
u8 hpf_coff_freq;
widget_name = kstrndup(w->name, 15, GFP_KERNEL);
widget_name = kmemdup_nul(w->name, 15, GFP_KERNEL);
if (!widget_name)
return -ENOMEM;

View file

@ -728,41 +728,18 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
struct dentry *root = NULL;
int i;
if (!component->debugfs_root) {
adsp_err(dsp, "No codec debugfs root\n");
goto err;
}
root = debugfs_create_dir(dsp->name, component->debugfs_root);
if (!root)
goto err;
debugfs_create_bool("booted", 0444, root, &dsp->booted);
debugfs_create_bool("running", 0444, root, &dsp->running);
debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id);
debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version);
if (!debugfs_create_bool("booted", 0444, root, &dsp->booted))
goto err;
if (!debugfs_create_bool("running", 0444, root, &dsp->running))
goto err;
if (!debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id))
goto err;
if (!debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version))
goto err;
for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i) {
if (!debugfs_create_file(wm_adsp_debugfs_fops[i].name,
0444, root, dsp,
&wm_adsp_debugfs_fops[i].fops))
goto err;
}
for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i)
debugfs_create_file(wm_adsp_debugfs_fops[i].name, 0444, root,
dsp, &wm_adsp_debugfs_fops[i].fops);
dsp->debugfs_root = root;
return;
err:
debugfs_remove_recursive(root);
adsp_err(dsp, "Failed to create debugfs\n");
}
static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)

View file

@ -29,22 +29,28 @@
#define DRV_NAME "efika-audio-fabric"
SND_SOC_DAILINK_DEFS(analog,
DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.0")),
DAILINK_COMP_ARRAY(COMP_CODEC("stac9766-codec",
"stac9766-hifi-analog")),
DAILINK_COMP_ARRAY(COMP_PLATFORM("mpc5200-pcm-audio")));
SND_SOC_DAILINK_DEFS(iec958,
DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.1")),
DAILINK_COMP_ARRAY(COMP_CODEC("stac9766-codec",
"stac9766-hifi-IEC958")),
DAILINK_COMP_ARRAY(COMP_PLATFORM("mpc5200-pcm-audio")));
static struct snd_soc_dai_link efika_fabric_dai[] = {
{
.name = "AC97",
.stream_name = "AC97 Analog",
.codec_dai_name = "stac9766-hifi-analog",
.cpu_dai_name = "mpc5200-psc-ac97.0",
.platform_name = "mpc5200-pcm-audio",
.codec_name = "stac9766-codec",
SND_SOC_DAILINK_REG(analog),
},
{
.name = "AC97",
.stream_name = "AC97 IEC958",
.codec_dai_name = "stac9766-hifi-IEC958",
.cpu_dai_name = "mpc5200-psc-ac97.1",
.platform_name = "mpc5200-pcm-audio",
.codec_name = "stac9766-codec",
SND_SOC_DAILINK_REG(iec958),
},
};

View file

@ -61,13 +61,18 @@ static const struct snd_soc_ops eukrea_tlv320_snd_ops = {
.hw_params = eukrea_tlv320_hw_params,
};
SND_SOC_DAILINK_DEFS(hifi,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic23-hifi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
static struct snd_soc_dai_link eukrea_tlv320_dai = {
.name = "tlv320aic23",
.stream_name = "TLV320AIC23",
.codec_dai_name = "tlv320aic23-hifi",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM,
.ops = &eukrea_tlv320_snd_ops,
SND_SOC_DAILINK_REG(hifi),
};
static struct snd_soc_card eukrea_tlv320 = {
@ -104,7 +109,7 @@ static int eukrea_tlv320_probe(struct platform_device *pdev)
codec_np = of_parse_phandle(ssi_np, "codec-handle", 0);
if (codec_np)
eukrea_tlv320_dai.codec_of_node = codec_np;
eukrea_tlv320_dai.codecs->of_node = codec_np;
else
dev_err(&pdev->dev, "codec-handle node missing or invalid.\n");
@ -128,12 +133,12 @@ static int eukrea_tlv320_probe(struct platform_device *pdev)
int_port--;
ext_port--;
eukrea_tlv320_dai.cpu_of_node = ssi_np;
eukrea_tlv320_dai.platform_of_node = ssi_np;
eukrea_tlv320_dai.cpus->of_node = ssi_np;
eukrea_tlv320_dai.platforms->of_node = ssi_np;
} else {
eukrea_tlv320_dai.cpu_dai_name = "imx-ssi.0";
eukrea_tlv320_dai.platform_name = "imx-ssi.0";
eukrea_tlv320_dai.codec_name = "tlv320aic23-codec.0-001a";
eukrea_tlv320_dai.cpus->dai_name = "imx-ssi.0";
eukrea_tlv320_dai.platforms->name = "imx-ssi.0";
eukrea_tlv320_dai.codecs->name = "tlv320aic23-codec.0-001a";
eukrea_tlv320.name = "cpuimx-audio";
}

View file

@ -200,32 +200,47 @@ static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0;
}
SND_SOC_DAILINK_DEFS(hifi,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hifi_fe,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hifi_be,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_DUMMY()));
static struct snd_soc_dai_link fsl_asoc_card_dai[] = {
/* Default ASoC DAI Link*/
{
.name = "HiFi",
.stream_name = "HiFi",
.ops = &fsl_asoc_card_ops,
SND_SOC_DAILINK_REG(hifi),
},
/* DPCM Link between Front-End and Back-End (Optional) */
{
.name = "HiFi-ASRC-FE",
.stream_name = "HiFi-ASRC-FE",
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
.dpcm_playback = 1,
.dpcm_capture = 1,
.dynamic = 1,
SND_SOC_DAILINK_REG(hifi_fe),
},
{
.name = "HiFi-ASRC-BE",
.stream_name = "HiFi-ASRC-BE",
.platform_name = "snd-soc-dummy",
.be_hw_params_fixup = be_hw_params_fixup,
.ops = &fsl_asoc_card_ops,
.dpcm_playback = 1,
.dpcm_capture = 1,
.no_pcm = 1,
SND_SOC_DAILINK_REG(hifi_be),
},
};
@ -616,11 +631,11 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
}
/* Normal DAI Link */
priv->dai_link[0].cpu_of_node = cpu_np;
priv->dai_link[0].codec_dai_name = codec_dai_name;
priv->dai_link[0].cpus->of_node = cpu_np;
priv->dai_link[0].codecs->dai_name = codec_dai_name;
if (!fsl_asoc_card_is_ac97(priv))
priv->dai_link[0].codec_of_node = codec_np;
priv->dai_link[0].codecs->of_node = codec_np;
else {
u32 idx;
@ -631,29 +646,29 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
goto asrc_fail;
}
priv->dai_link[0].codec_name =
priv->dai_link[0].codecs->name =
devm_kasprintf(&pdev->dev, GFP_KERNEL,
"ac97-codec.%u",
(unsigned int)idx);
if (!priv->dai_link[0].codec_name) {
if (!priv->dai_link[0].codecs->name) {
ret = -ENOMEM;
goto asrc_fail;
}
}
priv->dai_link[0].platform_of_node = cpu_np;
priv->dai_link[0].platforms->of_node = cpu_np;
priv->dai_link[0].dai_fmt = priv->dai_fmt;
priv->card.num_links = 1;
if (asrc_pdev) {
/* DPCM DAI Links only if ASRC exsits */
priv->dai_link[1].cpu_of_node = asrc_np;
priv->dai_link[1].platform_of_node = asrc_np;
priv->dai_link[2].codec_dai_name = codec_dai_name;
priv->dai_link[2].codec_of_node = codec_np;
priv->dai_link[2].codec_name =
priv->dai_link[0].codec_name;
priv->dai_link[2].cpu_of_node = cpu_np;
priv->dai_link[1].cpus->of_node = asrc_np;
priv->dai_link[1].platforms->of_node = asrc_np;
priv->dai_link[2].codecs->dai_name = codec_dai_name;
priv->dai_link[2].codecs->of_node = codec_np;
priv->dai_link[2].codecs->name =
priv->dai_link[0].codecs->name;
priv->dai_link[2].cpus->of_node = cpu_np;
priv->dai_link[2].dai_fmt = priv->dai_fmt;
priv->card.num_links = 3;

View file

@ -26,32 +26,15 @@
#define pair_dbg(fmt, ...) \
dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
/* Sample rates are aligned with that defined in pcm.h file */
static const u8 process_option[][12][2] = {
/* 8kHz 11.025kHz 16kHz 22.05kHz 32kHz 44.1kHz 48kHz 64kHz 88.2kHz 96kHz 176kHz 192kHz */
{{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 5512Hz */
{{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 8kHz */
{{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 11025Hz */
{{1, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 16kHz */
{{1, 2}, {1, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 22050Hz */
{{1, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},}, /* 32kHz */
{{2, 2}, {2, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 44.1kHz */
{{2, 2}, {2, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 48kHz */
{{2, 2}, {2, 2}, {2, 2}, {2, 1}, {1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},}, /* 64kHz */
{{2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 88.2kHz */
{{2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 96kHz */
{{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 176kHz */
{{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 192kHz */
};
/* Corresponding to process_option */
static int supported_input_rate[] = {
5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200,
96000, 176400, 192000,
static unsigned int supported_asrc_rate[] = {
5512, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
64000, 88200, 96000, 128000, 176400, 192000,
};
static int supported_asrc_rate[] = {
8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000,
static struct snd_pcm_hw_constraint_list fsl_asrc_rate_constraints = {
.count = ARRAY_SIZE(supported_asrc_rate),
.list = supported_asrc_rate,
};
/**
@ -79,6 +62,52 @@ static unsigned char output_clk_map_imx53[] = {
static unsigned char *clk_map[2];
/**
* Select the pre-processing and post-processing options
* Make sure to exclude following unsupported cases before
* calling this function:
* 1) inrate > 8.125 * outrate
* 2) inrate > 16.125 * outrate
*
* inrate: input sample rate
* outrate: output sample rate
* pre_proc: return value for pre-processing option
* post_proc: return value for post-processing option
*/
static void fsl_asrc_sel_proc(int inrate, int outrate,
int *pre_proc, int *post_proc)
{
bool post_proc_cond2;
bool post_proc_cond0;
/* select pre_proc between [0, 2] */
if (inrate * 8 > 33 * outrate)
*pre_proc = 2;
else if (inrate * 8 > 15 * outrate) {
if (inrate > 152000)
*pre_proc = 2;
else
*pre_proc = 1;
} else if (inrate < 76000)
*pre_proc = 0;
else if (inrate > 152000)
*pre_proc = 2;
else
*pre_proc = 1;
/* Condition for selection of post-processing */
post_proc_cond2 = (inrate * 15 > outrate * 16 && outrate < 56000) ||
(inrate > 56000 && outrate < 56000);
post_proc_cond0 = inrate * 23 < outrate * 8;
if (post_proc_cond2)
*post_proc = 2;
else if (post_proc_cond0)
*post_proc = 0;
else
*post_proc = 1;
}
/**
* Request ASRC pair
*
@ -239,6 +268,7 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
u32 inrate, outrate, indiv, outdiv;
u32 clk_index[2], div[2];
int in, out, channels;
int pre_proc, post_proc;
struct clk *clk;
bool ideal;
@ -264,11 +294,11 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
ideal = config->inclk == INCLK_NONE;
/* Validate input and output sample rates */
for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++)
if (inrate == supported_input_rate[in])
for (in = 0; in < ARRAY_SIZE(supported_asrc_rate); in++)
if (inrate == supported_asrc_rate[in])
break;
if (in == ARRAY_SIZE(supported_input_rate)) {
if (in == ARRAY_SIZE(supported_asrc_rate)) {
pair_err("unsupported input sample rate: %dHz\n", inrate);
return -EINVAL;
}
@ -282,7 +312,7 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
return -EINVAL;
}
if ((outrate >= 8000 && outrate <= 30000) &&
if ((outrate >= 5512 && outrate <= 30000) &&
(outrate > 24 * inrate || inrate > 8 * outrate)) {
pair_err("exceed supported ratio range [1/24, 8] for \
inrate/outrate: %d/%d\n", inrate, outrate);
@ -377,11 +407,13 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index),
ASRCTR_IDR(index) | ASRCTR_USR(index));
fsl_asrc_sel_proc(inrate, outrate, &pre_proc, &post_proc);
/* Apply configurations for pre- and post-processing */
regmap_update_bits(asrc_priv->regmap, REG_ASRCFG,
ASRCFG_PREMODi_MASK(index) | ASRCFG_POSTMODi_MASK(index),
ASRCFG_PREMOD(index, process_option[in][out][0]) |
ASRCFG_POSTMOD(index, process_option[in][out][1]));
ASRCFG_PREMOD(index, pre_proc) |
ASRCFG_POSTMOD(index, post_proc));
return fsl_asrc_set_ideal_ratio(pair, inrate, outrate);
}
@ -455,7 +487,9 @@ static int fsl_asrc_dai_startup(struct snd_pcm_substream *substream,
snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS, 2);
return 0;
return snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, &fsl_asrc_rate_constraints);
}
static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
@ -568,7 +602,6 @@ static int fsl_asrc_dai_probe(struct snd_soc_dai *dai)
return 0;
}
#define FSL_ASRC_RATES SNDRV_PCM_RATE_8000_192000
#define FSL_ASRC_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S20_3LE)
@ -579,14 +612,18 @@ static struct snd_soc_dai_driver fsl_asrc_dai = {
.stream_name = "ASRC-Playback",
.channels_min = 1,
.channels_max = 10,
.rates = FSL_ASRC_RATES,
.rate_min = 5512,
.rate_max = 192000,
.rates = SNDRV_PCM_RATE_KNOT,
.formats = FSL_ASRC_FORMATS,
},
.capture = {
.stream_name = "ASRC-Capture",
.channels_min = 1,
.channels_max = 10,
.rates = FSL_ASRC_RATES,
.rate_min = 5512,
.rate_max = 192000,
.rates = SNDRV_PCM_RATE_KNOT,
.formats = FSL_ASRC_FORMATS,
},
.ops = &fsl_asrc_dai_ops,

View file

@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/pm_runtime.h>
#include <sound/dmaengine_pcm.h>
#include <sound/pcm_params.h>
@ -466,30 +467,6 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
int ret;
/*
* Some platforms might use the same bit to gate all three or two of
* clocks, so keep all clocks open/close at the same time for safety
*/
ret = clk_prepare_enable(esai_priv->coreclk);
if (ret)
return ret;
if (!IS_ERR(esai_priv->spbaclk)) {
ret = clk_prepare_enable(esai_priv->spbaclk);
if (ret)
goto err_spbaclk;
}
if (!IS_ERR(esai_priv->extalclk)) {
ret = clk_prepare_enable(esai_priv->extalclk);
if (ret)
goto err_extalck;
}
if (!IS_ERR(esai_priv->fsysclk)) {
ret = clk_prepare_enable(esai_priv->fsysclk);
if (ret)
goto err_fsysclk;
}
if (!dai->active) {
/* Set synchronous mode */
@ -506,16 +483,6 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream,
return 0;
err_fsysclk:
if (!IS_ERR(esai_priv->extalclk))
clk_disable_unprepare(esai_priv->extalclk);
err_extalck:
if (!IS_ERR(esai_priv->spbaclk))
clk_disable_unprepare(esai_priv->spbaclk);
err_spbaclk:
clk_disable_unprepare(esai_priv->coreclk);
return ret;
}
static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
@ -576,20 +543,6 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static void fsl_esai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
if (!IS_ERR(esai_priv->fsysclk))
clk_disable_unprepare(esai_priv->fsysclk);
if (!IS_ERR(esai_priv->extalclk))
clk_disable_unprepare(esai_priv->extalclk);
if (!IS_ERR(esai_priv->spbaclk))
clk_disable_unprepare(esai_priv->spbaclk);
clk_disable_unprepare(esai_priv->coreclk);
}
static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
@ -658,7 +611,6 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
static const struct snd_soc_dai_ops fsl_esai_dai_ops = {
.startup = fsl_esai_startup,
.shutdown = fsl_esai_shutdown,
.trigger = fsl_esai_trigger,
.hw_params = fsl_esai_hw_params,
.set_sysclk = fsl_esai_set_dai_sysclk,
@ -947,6 +899,10 @@ static int fsl_esai_probe(struct platform_device *pdev)
return ret;
}
pm_runtime_enable(&pdev->dev);
regcache_cache_only(esai_priv->regmap, true);
ret = imx_pcm_dma_init(pdev, IMX_ESAI_DMABUF_SIZE);
if (ret)
dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
@ -954,6 +910,13 @@ static int fsl_esai_probe(struct platform_device *pdev)
return ret;
}
static int fsl_esai_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
return 0;
}
static const struct of_device_id fsl_esai_dt_ids[] = {
{ .compatible = "fsl,imx35-esai", },
{ .compatible = "fsl,vf610-esai", },
@ -961,22 +924,35 @@ static const struct of_device_id fsl_esai_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
#ifdef CONFIG_PM_SLEEP
static int fsl_esai_suspend(struct device *dev)
{
struct fsl_esai *esai = dev_get_drvdata(dev);
regcache_cache_only(esai->regmap, true);
regcache_mark_dirty(esai->regmap);
return 0;
}
static int fsl_esai_resume(struct device *dev)
#ifdef CONFIG_PM
static int fsl_esai_runtime_resume(struct device *dev)
{
struct fsl_esai *esai = dev_get_drvdata(dev);
int ret;
/*
* Some platforms might use the same bit to gate all three or two of
* clocks, so keep all clocks open/close at the same time for safety
*/
ret = clk_prepare_enable(esai->coreclk);
if (ret)
return ret;
if (!IS_ERR(esai->spbaclk)) {
ret = clk_prepare_enable(esai->spbaclk);
if (ret)
goto err_spbaclk;
}
if (!IS_ERR(esai->extalclk)) {
ret = clk_prepare_enable(esai->extalclk);
if (ret)
goto err_extalclk;
}
if (!IS_ERR(esai->fsysclk)) {
ret = clk_prepare_enable(esai->fsysclk);
if (ret)
goto err_fsysclk;
}
regcache_cache_only(esai->regmap, false);
/* FIFO reset for safety */
@ -987,22 +963,59 @@ static int fsl_esai_resume(struct device *dev)
ret = regcache_sync(esai->regmap);
if (ret)
return ret;
goto err_regcache_sync;
/* FIFO reset done */
regmap_update_bits(esai->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0);
regmap_update_bits(esai->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0);
return 0;
err_regcache_sync:
if (!IS_ERR(esai->fsysclk))
clk_disable_unprepare(esai->fsysclk);
err_fsysclk:
if (!IS_ERR(esai->extalclk))
clk_disable_unprepare(esai->extalclk);
err_extalclk:
if (!IS_ERR(esai->spbaclk))
clk_disable_unprepare(esai->spbaclk);
err_spbaclk:
clk_disable_unprepare(esai->coreclk);
return ret;
}
#endif /* CONFIG_PM_SLEEP */
static int fsl_esai_runtime_suspend(struct device *dev)
{
struct fsl_esai *esai = dev_get_drvdata(dev);
regcache_cache_only(esai->regmap, true);
regcache_mark_dirty(esai->regmap);
if (!IS_ERR(esai->fsysclk))
clk_disable_unprepare(esai->fsysclk);
if (!IS_ERR(esai->extalclk))
clk_disable_unprepare(esai->extalclk);
if (!IS_ERR(esai->spbaclk))
clk_disable_unprepare(esai->spbaclk);
clk_disable_unprepare(esai->coreclk);
return 0;
}
#endif /* CONFIG_PM */
static const struct dev_pm_ops fsl_esai_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(fsl_esai_suspend, fsl_esai_resume)
SET_RUNTIME_PM_OPS(fsl_esai_runtime_suspend,
fsl_esai_runtime_resume,
NULL)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};
static struct platform_driver fsl_esai_driver = {
.probe = fsl_esai_probe,
.remove = fsl_esai_remove,
.driver = {
.name = "fsl-esai-dai",
.pm = &fsl_esai_pm_ops,

View file

@ -596,15 +596,8 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
struct device *dev = &sai->pdev->dev;
int ret;
ret = clk_prepare_enable(sai->bus_clk);
if (ret) {
dev_err(dev, "failed to enable bus clock: %d\n", ret);
return ret;
}
regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE,
FSL_SAI_CR3_TRCE);
@ -621,8 +614,6 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, 0);
clk_disable_unprepare(sai->bus_clk);
}
static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
@ -935,6 +926,14 @@ static int fsl_sai_runtime_suspend(struct device *dev)
{
struct fsl_sai *sai = dev_get_drvdata(dev);
if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE))
clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]);
if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK))
clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]);
clk_disable_unprepare(sai->bus_clk);
regcache_cache_only(sai->regmap, true);
regcache_mark_dirty(sai->regmap);
@ -944,6 +943,25 @@ static int fsl_sai_runtime_suspend(struct device *dev)
static int fsl_sai_runtime_resume(struct device *dev)
{
struct fsl_sai *sai = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(sai->bus_clk);
if (ret) {
dev_err(dev, "failed to enable bus clock: %d\n", ret);
return ret;
}
if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) {
ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[1]]);
if (ret)
goto disable_bus_clk;
}
if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) {
ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[0]]);
if (ret)
goto disable_tx_clk;
}
regcache_cache_only(sai->regmap, false);
regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR);
@ -951,7 +969,23 @@ static int fsl_sai_runtime_resume(struct device *dev)
usleep_range(1000, 2000);
regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
return regcache_sync(sai->regmap);
ret = regcache_sync(sai->regmap);
if (ret)
goto disable_rx_clk;
return 0;
disable_rx_clk:
if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE))
clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]);
disable_tx_clk:
if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK))
clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]);
disable_bus_clk:
clk_disable_unprepare(sai->bus_clk);
return ret;
}
#endif /* CONFIG_PM */

View file

@ -1582,9 +1582,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
}
}
ret = fsl_ssi_debugfs_create(&ssi->dbg_stats, dev);
if (ret)
goto error_asoc_register;
fsl_ssi_debugfs_create(&ssi->dbg_stats, dev);
/* Initially configures SSI registers */
fsl_ssi_hw_init(ssi);

View file

@ -270,7 +270,6 @@ struct device;
struct fsl_ssi_dbg {
struct dentry *dbg_dir;
struct dentry *dbg_stats;
struct {
unsigned int rfrc;
@ -299,7 +298,7 @@ struct fsl_ssi_dbg {
void fsl_ssi_dbg_isr(struct fsl_ssi_dbg *ssi_dbg, u32 sisr);
int fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev);
void fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev);
void fsl_ssi_debugfs_remove(struct fsl_ssi_dbg *ssi_dbg);
@ -312,10 +311,9 @@ static inline void fsl_ssi_dbg_isr(struct fsl_ssi_dbg *stats, u32 sisr)
{
}
static inline int fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg,
struct device *dev)
static inline void fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg,
struct device *dev)
{
return 0;
}
static inline void fsl_ssi_debugfs_remove(struct fsl_ssi_dbg *ssi_dbg)

View file

@ -126,25 +126,15 @@ static int fsl_ssi_stats_show(struct seq_file *s, void *unused)
DEFINE_SHOW_ATTRIBUTE(fsl_ssi_stats);
int fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev)
void fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev)
{
ssi_dbg->dbg_dir = debugfs_create_dir(dev_name(dev), NULL);
if (!ssi_dbg->dbg_dir)
return -ENOMEM;
ssi_dbg->dbg_stats = debugfs_create_file("stats", 0444,
ssi_dbg->dbg_dir, ssi_dbg,
&fsl_ssi_stats_fops);
if (!ssi_dbg->dbg_stats) {
debugfs_remove(ssi_dbg->dbg_dir);
return -ENOMEM;
}
return 0;
debugfs_create_file("stats", 0444, ssi_dbg->dbg_dir, ssi_dbg,
&fsl_ssi_stats_fops);
}
void fsl_ssi_debugfs_remove(struct fsl_ssi_dbg *ssi_dbg)
{
debugfs_remove(ssi_dbg->dbg_stats);
debugfs_remove(ssi_dbg->dbg_dir);
debugfs_remove_recursive(ssi_dbg->dbg_dir);
}

View file

@ -57,7 +57,7 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np,
of_node_put(dma_channel_np);
return ret;
}
snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%pOFn",
snprintf((char *)dai->platforms->name, DAI_NAME_SIZE, "%llx.%pOFn",
(unsigned long long) res.start, dma_channel_np);
iprop = of_get_property(dma_channel_np, "cell-index", NULL);

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