未验证 提交 a54f8485 编写于 作者: M Mark Brown

Merge branch 'asoc-5.4' into asoc-next

# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP i.MX8 DSP core
maintainers:
- Daniel Baluta <daniel.baluta@nxp.com>
description: |
Some boards from i.MX8 family contain a DSP core used for
advanced pre- and post- audio processing.
properties:
compatible:
enum:
- fsl,imx8qxp-dsp
reg:
description: Should contain register location and length
clocks:
items:
- description: ipg clock
- description: ocram clock
- description: core clock
clock-names:
items:
- const: ipg
- const: ocram
- const: core
power-domains:
description:
List of phandle and PM domain specifier as documented in
Documentation/devicetree/bindings/power/power_domain.txt
maxItems: 4
mboxes:
description:
List of <&phandle type channel> - 2 channels for TXDB, 2 channels for RXDB
(see mailbox/fsl,mu.txt)
maxItems: 4
mbox-names:
items:
- const: txdb0
- const: txdb1
- const: rxdb0
- const: rxdb1
memory-region:
description:
phandle to a node describing reserved memory (System RAM memory)
used by DSP (see bindings/reserved-memory/reserved-memory.txt)
maxItems: 1
required:
- compatible
- reg
- clocks
- clock-names
- power-domains
- mboxes
- mbox-names
- memory-region
examples:
- |
#include <dt-bindings/firmware/imx/rsrc.h>
#include <dt-bindings/clock/imx8-clock.h>
dsp@596e8000 {
compatible = "fsl,imx8qxp-dsp";
reg = <0x596e8000 0x88000>;
clocks = <&adma_lpcg IMX_ADMA_LPCG_DSP_IPG_CLK>,
<&adma_lpcg IMX_ADMA_LPCG_OCRAM_IPG_CLK>,
<&adma_lpcg IMX_ADMA_LPCG_DSP_CORE_CLK>;
clock-names = "ipg", "ocram", "core";
power-domains = <&pd IMX_SC_R_MU_13A>,
<&pd IMX_SC_R_MU_13B>,
<&pd IMX_SC_R_DSP>,
<&pd IMX_SC_R_DSP_RAM>;
mbox-names = "txdb0", "txdb1", "rxdb0", "rxdb1";
mboxes = <&lsio_mu13 2 0>, <&lsio_mu13 2 1>, <&lsio_mu13 3 0>, <&lsio_mu13 3 1>;
};
...@@ -70,7 +70,9 @@ allOf: ...@@ -70,7 +70,9 @@ allOf:
properties: properties:
compatible: compatible:
contains: contains:
const: allwinner,sun8i-h3-spdif enum:
- allwinner,sun8i-h3-spdif
- allwinner,sun50i-h6-spdif
then: then:
properties: properties:
......
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/allwinner,sun50i-a64-codec-analog.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A64 Analog Codec Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <maxime.ripard@bootlin.com>
properties:
compatible:
const: allwinner,sun50i-a64-codec-analog
reg:
maxItems: 1
cpvdd-supply:
description:
Regulator for the headphone amplifier
required:
- compatible
- reg
- cpvdd-supply
additionalProperties: false
examples:
- |
codec_analog: codec-analog@1f015c0 {
compatible = "allwinner,sun50i-a64-codec-analog";
reg = <0x01f015c0 0x4>;
cpvdd-supply = <&reg_eldo1>;
};
...
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/allwinner,sun8i-a33-codec.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A33 Codec Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <maxime.ripard@bootlin.com>
properties:
"#sound-dai-cells":
const: 0
compatible:
const: allwinner,sun8i-a33-codec
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: Bus Clock
- description: Module Clock
clock-names:
items:
- const: bus
- const: mod
required:
- "#sound-dai-cells"
- compatible
- reg
- interrupts
- clocks
- clock-names
additionalProperties: false
examples:
- |
audio-codec@1c22e00 {
#sound-dai-cells = <0>;
compatible = "allwinner,sun8i-a33-codec";
reg = <0x01c22e00 0x400>;
interrupts = <0 29 4>;
clocks = <&ccu 47>, <&ccu 92>;
clock-names = "bus", "mod";
};
...
...@@ -4,13 +4,18 @@ Required properties: ...@@ -4,13 +4,18 @@ Required properties:
- compatible: 'amlogic,axg-toddr' or - compatible: 'amlogic,axg-toddr' or
'amlogic,axg-toddr' or 'amlogic,axg-toddr' or
'amlogic,g12a-frddr' or 'amlogic,g12a-frddr' or
'amlogic,g12a-toddr' 'amlogic,g12a-toddr' or
'amlogic,sm1-frddr' or
'amlogic,sm1-toddr'
- reg: physical base address of the controller and length of memory - reg: physical base address of the controller and length of memory
mapped region. mapped region.
- interrupts: interrupt specifier for the fifo. - interrupts: interrupt specifier for the fifo.
- clocks: phandle to the fifo peripheral clock provided by the audio - clocks: phandle to the fifo peripheral clock provided by the audio
clock controller. clock controller.
- resets: phandle to memory ARB line provided by the arb reset controller. - resets: list of reset phandle, one for each entry reset-names.
- reset-names: should contain the following:
* "arb" : memory ARB line (required)
* "rst" : dedicated device reset line (optional)
- #sound-dai-cells: must be 0. - #sound-dai-cells: must be 0.
Example of FRDDR A on the A113 SoC: Example of FRDDR A on the A113 SoC:
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
Required properties: Required properties:
- compatible: 'amlogic,axg-pdm' or - compatible: 'amlogic,axg-pdm' or
'amlogic,g12a-pdm' 'amlogic,g12a-pdm' or
'amlogic,sm1-pdm'
- reg: physical base address of the controller and length of memory - reg: physical base address of the controller and length of memory
mapped region. mapped region.
- clocks: list of clock phandle, one for each entry clock-names. - clocks: list of clock phandle, one for each entry clock-names.
...@@ -12,6 +13,9 @@ Required properties: ...@@ -12,6 +13,9 @@ Required properties:
* "sysclk" : dsp system clock * "sysclk" : dsp system clock
- #sound-dai-cells: must be 0. - #sound-dai-cells: must be 0.
Optional property:
- resets: phandle to the dedicated reset line of the pdm input.
Example of PDM on the A113 SoC: Example of PDM on the A113 SoC:
pdm: audio-controller@ff632000 { pdm: audio-controller@ff632000 {
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
Required properties: Required properties:
- compatible: 'amlogic,axg-spdifin' or - compatible: 'amlogic,axg-spdifin' or
'amlogic,g12a-spdifin' 'amlogic,g12a-spdifin' or
'amlogic,sm1-spdifin'
- interrupts: interrupt specifier for the spdif input. - interrupts: interrupt specifier for the spdif input.
- clocks: list of clock phandle, one for each entry clock-names. - clocks: list of clock phandle, one for each entry clock-names.
- clock-names: should contain the following: - clock-names: should contain the following:
...@@ -10,6 +11,9 @@ Required properties: ...@@ -10,6 +11,9 @@ Required properties:
* "refclk" : spdif input reference clock * "refclk" : spdif input reference clock
- #sound-dai-cells: must be 0. - #sound-dai-cells: must be 0.
Optional property:
- resets: phandle to the dedicated reset line of the spdif input.
Example on the A113 SoC: Example on the A113 SoC:
spdifin: audio-controller@400 { spdifin: audio-controller@400 {
......
...@@ -2,13 +2,17 @@ ...@@ -2,13 +2,17 @@
Required properties: Required properties:
- compatible: 'amlogic,axg-spdifout' or - compatible: 'amlogic,axg-spdifout' or
'amlogic,g12a-spdifout' 'amlogic,g12a-spdifout' or
'amlogic,sm1-spdifout'
- clocks: list of clock phandle, one for each entry clock-names. - clocks: list of clock phandle, one for each entry clock-names.
- clock-names: should contain the following: - clock-names: should contain the following:
* "pclk" : peripheral clock. * "pclk" : peripheral clock.
* "mclk" : master clock * "mclk" : master clock
- #sound-dai-cells: must be 0. - #sound-dai-cells: must be 0.
Optional property:
- resets: phandle to the dedicated reset line of the spdif output.
Example on the A113 SoC: Example on the A113 SoC:
spdifout: audio-controller@480 { spdifout: audio-controller@480 {
......
...@@ -4,7 +4,9 @@ Required properties: ...@@ -4,7 +4,9 @@ Required properties:
- compatible: 'amlogic,axg-tdmin' or - compatible: 'amlogic,axg-tdmin' or
'amlogic,axg-tdmout' or 'amlogic,axg-tdmout' or
'amlogic,g12a-tdmin' or 'amlogic,g12a-tdmin' or
'amlogic,g12a-tdmout' 'amlogic,g12a-tdmout' or
'amlogic,sm1-tdmin' or
'amlogic,sm1-tdmout
- reg: physical base address of the controller and length of memory - reg: physical base address of the controller and length of memory
mapped region. mapped region.
- clocks: list of clock phandle, one for each entry clock-names. - clocks: list of clock phandle, one for each entry clock-names.
......
* Amlogic HDMI Tx control glue * Amlogic HDMI Tx control glue
Required properties: Required properties:
- compatible: "amlogic,g12a-tohdmitx" - compatible: "amlogic,g12a-tohdmitx" or
"amlogic,sm1-tohdmitx"
- reg: physical base address of the controller and length of memory - reg: physical base address of the controller and length of memory
mapped region. mapped region.
- #sound-dai-cells: should be 1. - #sound-dai-cells: should be 1.
- resets: phandle to the dedicated reset line of the hdmitx glue.
Example on the S905X2 SoC: Example on the S905X2 SoC:
...@@ -12,6 +14,7 @@ tohdmitx: audio-controller@744 { ...@@ -12,6 +14,7 @@ tohdmitx: audio-controller@744 {
compatible = "amlogic,g12a-tohdmitx"; compatible = "amlogic,g12a-tohdmitx";
reg = <0x0 0x744 0x0 0x4>; reg = <0x0 0x744 0x0 0x4>;
#sound-dai-cells = <1>; #sound-dai-cells = <1>;
resets = <&clkc_audio AUD_RESET_TOHDMITX>;
}; };
Example of an 'amlogic,axg-sound-card': Example of an 'amlogic,axg-sound-card':
......
Everest ES8316 audio CODEC
This device supports both I2C and SPI.
Required properties:
- compatible : should be "everest,es8316"
- reg : the I2C address of the device for I2C
Optional properties:
- clocks : a list of phandle, should contain entries for clock-names
- clock-names : should include as follows:
"mclk" : master clock (MCLK) of the device
Example:
es8316: codec@11 {
compatible = "everest,es8316";
reg = <0x11>;
clocks = <&clks 10>;
clock-names = "mclk";
};
...@@ -7,8 +7,11 @@ other DSPs. It has up to six transmitters and four receivers. ...@@ -7,8 +7,11 @@ other DSPs. It has up to six transmitters and four receivers.
Required properties: Required properties:
- compatible : Compatible list, must contain "fsl,imx35-esai" or - compatible : Compatible list, should contain one of the following
"fsl,vf610-esai" compatibles:
"fsl,imx35-esai",
"fsl,vf610-esai",
"fsl,imx6ull-esai",
- reg : Offset and length of the register set for the device. - reg : Offset and length of the register set for the device.
......
...@@ -8,7 +8,9 @@ codec/DSP interfaces. ...@@ -8,7 +8,9 @@ codec/DSP interfaces.
Required properties: Required properties:
- compatible : Compatible list, contains "fsl,vf610-sai", - compatible : Compatible list, contains "fsl,vf610-sai",
"fsl,imx6sx-sai" or "fsl,imx6ul-sai" "fsl,imx6sx-sai", "fsl,imx6ul-sai",
"fsl,imx7ulp-sai", "fsl,imx8mq-sai" or
"fsl,imx8qm-sai".
- reg : Offset and length of the register set for the device. - reg : Offset and length of the register set for the device.
......
* Allwinner A64 Codec Analog Controls
Required properties:
- compatible: must be one of the following compatibles:
- "allwinner,sun50i-a64-codec-analog"
- reg: must contain the registers location and length
- cpvdd-supply: Regulator supply for the headphone amplifier
Example:
codec_analog: codec-analog@1f015c0 {
compatible = "allwinner,sun50i-a64-codec-analog";
reg = <0x01f015c0 0x4>;
cpvdd-supply = <&reg_eldo1>;
};
Allwinner SUN8I audio codec
------------------------------------
On Sun8i-A33 SoCs, the audio is separated in different parts:
- A DAI driver. It uses the "sun4i-i2s" driver which is
documented here:
Documentation/devicetree/bindings/sound/sun4i-i2s.txt
- An analog part of the codec which is handled as PRCM registers.
See Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt
- An digital part of the codec which is documented in this current
binding documentation.
- And finally, an audio card which links all the above components.
The simple-audio card will be used.
See Documentation/devicetree/bindings/sound/simple-card.txt
This bindings documentation exposes Sun8i codec (digital part).
Required properties:
- compatible: must be "allwinner,sun8i-a33-codec"
- reg: must contain the registers location and length
- interrupts: must contain the codec interrupt
- clocks: a list of phandle + clock-specifer pairs, one for each entry
in clock-names.
- clock-names: should contain followings:
- "bus": the parent APB clock for this controller
- "mod": the parent module clock
Here is an example to add a sound card and the codec binding on sun8i SoCs that
are similar to A33 using simple-card:
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "sun8i-a33-audio";
simple-audio-card,format = "i2s";
simple-audio-card,frame-master = <&link_codec>;
simple-audio-card,bitclock-master = <&link_codec>;
simple-audio-card,mclk-fs = <512>;
simple-audio-card,aux-devs = <&codec_analog>;
simple-audio-card,routing =
"Left DAC", "Digital Left DAC",
"Right DAC", "Digital Right DAC";
simple-audio-card,cpu {
sound-dai = <&dai>;
};
link_codec: simple-audio-card,codec {
sound-dai = <&codec>;
};
soc@1c00000 {
[...]
audio-codec@1c22e00 {
#sound-dai-cells = <0>;
compatible = "allwinner,sun8i-a33-codec";
reg = <0x01c22e00 0x400>;
interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>;
clock-names = "bus", "mod";
};
};
UDA1334 audio CODEC
This device uses simple GPIO pins for controlling codec settings.
Required properties:
- compatible : "nxp,uda1334"
- nxp,mute-gpios: a GPIO spec for the MUTE pin.
- nxp,deemph-gpios: a GPIO spec for the De-emphasis pin
Example:
uda1334: audio-codec {
compatible = "nxp,uda1334";
nxp,mute-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
nxp,deemph-gpios = <&gpio3 3 GPIO_ACTIVE_LOW>;
};
...@@ -253,24 +253,6 @@ struct hdac_ext_bus_ops { ...@@ -253,24 +253,6 @@ struct hdac_ext_bus_ops {
int (*hdev_detach)(struct hdac_device *hdev); int (*hdev_detach)(struct hdac_device *hdev);
}; };
/*
* Lowlevel I/O operators
*/
struct hdac_io_ops {
/* mapped register accesses */
void (*reg_writel)(u32 value, u32 __iomem *addr);
u32 (*reg_readl)(u32 __iomem *addr);
void (*reg_writew)(u16 value, u16 __iomem *addr);
u16 (*reg_readw)(u16 __iomem *addr);
void (*reg_writeb)(u8 value, u8 __iomem *addr);
u8 (*reg_readb)(u8 __iomem *addr);
/* Allocation ops */
int (*dma_alloc_pages)(struct hdac_bus *bus, int type, size_t size,
struct snd_dma_buffer *buf);
void (*dma_free_pages)(struct hdac_bus *bus,
struct snd_dma_buffer *buf);
};
#define HDA_UNSOL_QUEUE_SIZE 64 #define HDA_UNSOL_QUEUE_SIZE 64
#define HDA_MAX_CODECS 8 /* limit by controller side */ #define HDA_MAX_CODECS 8 /* limit by controller side */
...@@ -304,7 +286,6 @@ struct hdac_rb { ...@@ -304,7 +286,6 @@ struct hdac_rb {
struct hdac_bus { struct hdac_bus {
struct device *dev; struct device *dev;
const struct hdac_bus_ops *ops; const struct hdac_bus_ops *ops;
const struct hdac_io_ops *io_ops;
const struct hdac_ext_bus_ops *ext_ops; const struct hdac_ext_bus_ops *ext_ops;
/* h/w resources */ /* h/w resources */
...@@ -344,6 +325,7 @@ struct hdac_bus { ...@@ -344,6 +325,7 @@ struct hdac_bus {
/* CORB/RIRB and position buffers */ /* CORB/RIRB and position buffers */
struct snd_dma_buffer rb; struct snd_dma_buffer rb;
struct snd_dma_buffer posbuf; struct snd_dma_buffer posbuf;
int dma_type; /* SNDRV_DMA_TYPE_XXX for CORB/RIRB */
/* hdac_stream linked list */ /* hdac_stream linked list */
struct list_head stream_list; struct list_head stream_list;
...@@ -384,8 +366,7 @@ struct hdac_bus { ...@@ -384,8 +366,7 @@ struct hdac_bus {
}; };
int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
const struct hdac_bus_ops *ops, const struct hdac_bus_ops *ops);
const struct hdac_io_ops *io_ops);
void snd_hdac_bus_exit(struct hdac_bus *bus); void snd_hdac_bus_exit(struct hdac_bus *bus);
int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr,
unsigned int cmd, unsigned int *res); unsigned int cmd, unsigned int *res);
...@@ -429,21 +410,38 @@ int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, ...@@ -429,21 +410,38 @@ int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus); int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus);
void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus); void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus);
#ifdef CONFIG_SND_HDA_ALIGNED_MMIO
unsigned int snd_hdac_aligned_read(void __iomem *addr, unsigned int mask);
void snd_hdac_aligned_write(unsigned int val, void __iomem *addr,
unsigned int mask);
#define snd_hdac_reg_writeb(v, addr) snd_hdac_aligned_write(v, addr, 0xff)
#define snd_hdac_reg_writew(v, addr) snd_hdac_aligned_write(v, addr, 0xffff)
#define snd_hdac_reg_readb(addr) snd_hdac_aligned_read(addr, 0xff)
#define snd_hdac_reg_readw(addr) snd_hdac_aligned_read(addr, 0xffff)
#else /* CONFIG_SND_HDA_ALIGNED_MMIO */
#define snd_hdac_reg_writeb(val, addr) writeb(val, addr)
#define snd_hdac_reg_writew(val, addr) writew(val, addr)
#define snd_hdac_reg_readb(addr) readb(addr)
#define snd_hdac_reg_readw(addr) readw(addr)
#endif /* CONFIG_SND_HDA_ALIGNED_MMIO */
#define snd_hdac_reg_writel(val, addr) writel(val, addr)
#define snd_hdac_reg_readl(addr) readl(addr)
/* /*
* macros for easy use * macros for easy use
*/ */
#define _snd_hdac_chip_writeb(chip, reg, value) \ #define _snd_hdac_chip_writeb(chip, reg, value) \
((chip)->io_ops->reg_writeb(value, (chip)->remap_addr + (reg))) snd_hdac_reg_writeb(value, (chip)->remap_addr + (reg))
#define _snd_hdac_chip_readb(chip, reg) \ #define _snd_hdac_chip_readb(chip, reg) \
((chip)->io_ops->reg_readb((chip)->remap_addr + (reg))) snd_hdac_reg_readb((chip)->remap_addr + (reg))
#define _snd_hdac_chip_writew(chip, reg, value) \ #define _snd_hdac_chip_writew(chip, reg, value) \
((chip)->io_ops->reg_writew(value, (chip)->remap_addr + (reg))) snd_hdac_reg_writew(value, (chip)->remap_addr + (reg))
#define _snd_hdac_chip_readw(chip, reg) \ #define _snd_hdac_chip_readw(chip, reg) \
((chip)->io_ops->reg_readw((chip)->remap_addr + (reg))) snd_hdac_reg_readw((chip)->remap_addr + (reg))
#define _snd_hdac_chip_writel(chip, reg, value) \ #define _snd_hdac_chip_writel(chip, reg, value) \
((chip)->io_ops->reg_writel(value, (chip)->remap_addr + (reg))) snd_hdac_reg_writel(value, (chip)->remap_addr + (reg))
#define _snd_hdac_chip_readl(chip, reg) \ #define _snd_hdac_chip_readl(chip, reg) \
((chip)->io_ops->reg_readl((chip)->remap_addr + (reg))) snd_hdac_reg_readl((chip)->remap_addr + (reg))
/* read/write a register, pass without AZX_REG_ prefix */ /* read/write a register, pass without AZX_REG_ prefix */
#define snd_hdac_chip_writel(chip, reg, value) \ #define snd_hdac_chip_writel(chip, reg, value) \
...@@ -548,24 +546,19 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus, ...@@ -548,24 +546,19 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
/* /*
* macros for easy use * macros for easy use
*/ */
#define _snd_hdac_stream_write(type, dev, reg, value) \
((dev)->bus->io_ops->reg_write ## type(value, (dev)->sd_addr + (reg)))
#define _snd_hdac_stream_read(type, dev, reg) \
((dev)->bus->io_ops->reg_read ## type((dev)->sd_addr + (reg)))
/* read/write a register, pass without AZX_REG_ prefix */ /* read/write a register, pass without AZX_REG_ prefix */
#define snd_hdac_stream_writel(dev, reg, value) \ #define snd_hdac_stream_writel(dev, reg, value) \
_snd_hdac_stream_write(l, dev, AZX_REG_ ## reg, value) snd_hdac_reg_writel(value, (dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_writew(dev, reg, value) \ #define snd_hdac_stream_writew(dev, reg, value) \
_snd_hdac_stream_write(w, dev, AZX_REG_ ## reg, value) snd_hdac_reg_writew(value, (dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_writeb(dev, reg, value) \ #define snd_hdac_stream_writeb(dev, reg, value) \
_snd_hdac_stream_write(b, dev, AZX_REG_ ## reg, value) snd_hdac_reg_writeb(value, (dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_readl(dev, reg) \ #define snd_hdac_stream_readl(dev, reg) \
_snd_hdac_stream_read(l, dev, AZX_REG_ ## reg) snd_hdac_reg_readl((dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_readw(dev, reg) \ #define snd_hdac_stream_readw(dev, reg) \
_snd_hdac_stream_read(w, dev, AZX_REG_ ## reg) snd_hdac_reg_readw((dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_readb(dev, reg) \ #define snd_hdac_stream_readb(dev, reg) \
_snd_hdac_stream_read(b, dev, AZX_REG_ ## reg) snd_hdac_reg_readb((dev)->sd_addr + AZX_REG_ ## reg)
/* update a register, pass without AZX_REG_ prefix */ /* update a register, pass without AZX_REG_ prefix */
#define snd_hdac_stream_updatel(dev, reg, mask, val) \ #define snd_hdac_stream_updatel(dev, reg, mask, val) \
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev,
const struct hdac_bus_ops *ops, const struct hdac_bus_ops *ops,
const struct hdac_io_ops *io_ops,
const struct hdac_ext_bus_ops *ext_ops); const struct hdac_ext_bus_ops *ext_ops);
void snd_hdac_ext_bus_exit(struct hdac_bus *bus); void snd_hdac_ext_bus_exit(struct hdac_bus *bus);
......
...@@ -47,6 +47,9 @@ struct hdmi_codec_params { ...@@ -47,6 +47,9 @@ struct hdmi_codec_params {
int channels; int channels;
}; };
typedef void (*hdmi_codec_plugged_cb)(struct device *dev,
bool plugged);
struct hdmi_codec_pdata; struct hdmi_codec_pdata;
struct hdmi_codec_ops { struct hdmi_codec_ops {
/* /*
...@@ -88,6 +91,14 @@ struct hdmi_codec_ops { ...@@ -88,6 +91,14 @@ struct hdmi_codec_ops {
*/ */
int (*get_dai_id)(struct snd_soc_component *comment, int (*get_dai_id)(struct snd_soc_component *comment,
struct device_node *endpoint); struct device_node *endpoint);
/*
* Hook callback function to handle connector plug event.
* Optional
*/
int (*hook_plugged_cb)(struct device *dev, void *data,
hdmi_codec_plugged_cb fn,
struct device *codec_dev);
}; };
/* HDMI codec initalization data */ /* HDMI codec initalization data */
...@@ -99,6 +110,12 @@ struct hdmi_codec_pdata { ...@@ -99,6 +110,12 @@ struct hdmi_codec_pdata {
void *data; void *data;
}; };
struct snd_soc_component;
struct snd_soc_jack;
int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
struct snd_soc_jack *jack);
#define HDMI_CODEC_DRV_NAME "hdmi-audio-codec" #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec"
#endif /* __HDMI_CODEC_H__ */ #endif /* __HDMI_CODEC_H__ */
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* skl-nhlt.h - Intel HDA Platform NHLT header * intel-nhlt.h - Intel HDA Platform NHLT header
* *
* Copyright (C) 2015 Intel Corp * Copyright (c) 2015-2019 Intel Corporation
* Author: Sanjiv Kumar <sanjiv.kumar@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
#ifndef __SKL_NHLT_H__
#define __SKL_NHLT_H__ #ifndef __INTEL_NHLT_H__
#define __INTEL_NHLT_H__
#include <linux/acpi.h> #include <linux/acpi.h>
#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT)
struct wav_fmt { struct wav_fmt {
u16 fmt_tag; u16 fmt_tag;
u16 channels; u16 channels;
...@@ -97,16 +96,22 @@ struct nhlt_resource_desc { ...@@ -97,16 +96,22 @@ struct nhlt_resource_desc {
#define MIC_ARRAY_2CH 2 #define MIC_ARRAY_2CH 2
#define MIC_ARRAY_4CH 4 #define MIC_ARRAY_4CH 4
struct nhlt_tdm_config { struct nhlt_device_specific_config {
u8 virtual_slot; u8 virtual_slot;
u8 config_type; u8 config_type;
} __packed; } __packed;
struct nhlt_dmic_array_config { struct nhlt_dmic_array_config {
struct nhlt_tdm_config tdm_config; struct nhlt_device_specific_config device_config;
u8 array_type; u8 array_type;
} __packed; } __packed;
struct nhlt_vendor_dmic_array_config {
struct nhlt_dmic_array_config dmic_config;
u8 nb_mics;
/* TODO add vendor mic config */
} __packed;
enum { enum {
NHLT_MIC_ARRAY_2CH_SMALL = 0xa, NHLT_MIC_ARRAY_2CH_SMALL = 0xa,
NHLT_MIC_ARRAY_2CH_BIG = 0xb, NHLT_MIC_ARRAY_2CH_BIG = 0xb,
...@@ -116,4 +121,30 @@ enum { ...@@ -116,4 +121,30 @@ enum {
NHLT_MIC_ARRAY_VENDOR_DEFINED = 0xf, NHLT_MIC_ARRAY_VENDOR_DEFINED = 0xf,
}; };
struct nhlt_acpi_table *intel_nhlt_init(struct device *dev);
void intel_nhlt_free(struct nhlt_acpi_table *addr);
int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt);
#else
struct nhlt_acpi_table;
static inline struct nhlt_acpi_table *intel_nhlt_init(struct device *dev)
{
return NULL;
}
static inline void intel_nhlt_free(struct nhlt_acpi_table *addr)
{
}
static inline int intel_nhlt_get_dmic_geo(struct device *dev,
struct nhlt_acpi_table *nhlt)
{
return 0;
}
#endif
#endif #endif
...@@ -117,6 +117,8 @@ struct snd_pcm_ops { ...@@ -117,6 +117,8 @@ struct snd_pcm_ops {
#define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */ #define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */
#define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */ #define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */
#define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */ #define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */
#define SNDRV_PCM_RATE_352800 (1<<13) /* 352800Hz */
#define SNDRV_PCM_RATE_384000 (1<<14) /* 384000Hz */
#define SNDRV_PCM_RATE_CONTINUOUS (1<<30) /* continuous range */ #define SNDRV_PCM_RATE_CONTINUOUS (1<<30) /* continuous range */
#define SNDRV_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */ #define SNDRV_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */
...@@ -129,6 +131,9 @@ struct snd_pcm_ops { ...@@ -129,6 +131,9 @@ struct snd_pcm_ops {
SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000)
#define SNDRV_PCM_RATE_8000_192000 (SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\ #define SNDRV_PCM_RATE_8000_192000 (SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\
SNDRV_PCM_RATE_192000) SNDRV_PCM_RATE_192000)
#define SNDRV_PCM_RATE_8000_384000 (SNDRV_PCM_RATE_8000_192000|\
SNDRV_PCM_RATE_352800|\
SNDRV_PCM_RATE_384000)
#define _SNDRV_PCM_FMTBIT(fmt) (1ULL << (__force int)SNDRV_PCM_FORMAT_##fmt) #define _SNDRV_PCM_FMTBIT(fmt) (1ULL << (__force int)SNDRV_PCM_FORMAT_##fmt)
#define SNDRV_PCM_FMTBIT_S8 _SNDRV_PCM_FMTBIT(S8) #define SNDRV_PCM_FMTBIT_S8 _SNDRV_PCM_FMTBIT(S8)
#define SNDRV_PCM_FMTBIT_U8 _SNDRV_PCM_FMTBIT(U8) #define SNDRV_PCM_FMTBIT_U8 _SNDRV_PCM_FMTBIT(U8)
......
...@@ -25,6 +25,8 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[]; ...@@ -25,6 +25,8 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[];
/* /*
* generic table used for HDA codec-based platforms, possibly with * generic table used for HDA codec-based platforms, possibly with
......
/* SPDX-License-Identifier: GPL-2.0
*
* soc-component.h
*
* Copyright (c) 2019 Kuninori Morimoto <kuninori.morimoto.gx@renesas.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 __SOC_COMPONENT_H
#define __SOC_COMPONENT_H
#include <sound/soc.h>
/*
* Component probe and remove ordering levels for components with runtime
* dependencies.
*/
#define SND_SOC_COMP_ORDER_FIRST -2
#define SND_SOC_COMP_ORDER_EARLY -1
#define SND_SOC_COMP_ORDER_NORMAL 0
#define SND_SOC_COMP_ORDER_LATE 1
#define SND_SOC_COMP_ORDER_LAST 2
#define for_each_comp_order(order) \
for (order = SND_SOC_COMP_ORDER_FIRST; \
order <= SND_SOC_COMP_ORDER_LAST; \
order++)
/* component interface */
struct snd_soc_component_driver {
const char *name;
/* Default control and setup, added after probe() is run */
const struct snd_kcontrol_new *controls;
unsigned int num_controls;
const struct snd_soc_dapm_widget *dapm_widgets;
unsigned int num_dapm_widgets;
const struct snd_soc_dapm_route *dapm_routes;
unsigned int num_dapm_routes;
int (*probe)(struct snd_soc_component *component);
void (*remove)(struct snd_soc_component *component);
int (*suspend)(struct snd_soc_component *component);
int (*resume)(struct snd_soc_component *component);
unsigned int (*read)(struct snd_soc_component *component,
unsigned int reg);
int (*write)(struct snd_soc_component *component,
unsigned int reg, unsigned int val);
/* pcm creation and destruction */
int (*pcm_new)(struct snd_soc_pcm_runtime *rtd);
void (*pcm_free)(struct snd_pcm *pcm);
/* component wide operations */
int (*set_sysclk)(struct snd_soc_component *component,
int clk_id, int source, unsigned int freq, int dir);
int (*set_pll)(struct snd_soc_component *component, int pll_id,
int source, unsigned int freq_in, unsigned int freq_out);
int (*set_jack)(struct snd_soc_component *component,
struct snd_soc_jack *jack, void *data);
/* DT */
int (*of_xlate_dai_name)(struct snd_soc_component *component,
struct of_phandle_args *args,
const char **dai_name);
int (*of_xlate_dai_id)(struct snd_soc_component *comment,
struct device_node *endpoint);
void (*seq_notifier)(struct snd_soc_component *component,
enum snd_soc_dapm_type type, int subseq);
int (*stream_event)(struct snd_soc_component *component, int event);
int (*set_bias_level)(struct snd_soc_component *component,
enum snd_soc_bias_level level);
const struct snd_pcm_ops *ops;
const struct snd_compr_ops *compr_ops;
/* probe ordering - for components with runtime dependencies */
int probe_order;
int remove_order;
/*
* signal if the module handling the component should not be removed
* if a pcm is open. Setting this would prevent the module
* refcount being incremented in probe() but allow it be incremented
* when a pcm is opened and decremented when it is closed.
*/
unsigned int module_get_upon_open:1;
/* bits */
unsigned int idle_bias_on:1;
unsigned int suspend_bias_off:1;
unsigned int use_pmdown_time:1; /* care pmdown_time at stop */
unsigned int endianness:1;
unsigned int non_legacy_dai_naming:1;
/* this component uses topology and ignore machine driver FEs */
const char *ignore_machine;
const char *topology_name_prefix;
int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
bool use_dai_pcm_id; /* use DAI link PCM ID as PCM device number */
int be_pcm_base; /* base device ID for all BE PCMs */
};
struct snd_soc_component {
const char *name;
int id;
const char *name_prefix;
struct device *dev;
struct snd_soc_card *card;
unsigned int active;
unsigned int suspended:1; /* is in suspend PM state */
struct list_head list;
struct list_head card_aux_list; /* for auxiliary bound components */
struct list_head card_list;
const struct snd_soc_component_driver *driver;
struct list_head dai_list;
int num_dai;
struct regmap *regmap;
int val_bytes;
struct mutex io_mutex;
/* attached dynamic objects */
struct list_head dobj_list;
/*
* DO NOT use any of the fields below in drivers, they are temporary and
* are going to be removed again soon. If you use them in driver code
* the driver will be marked as BROKEN when these fields are removed.
*/
/* Don't use these, use snd_soc_component_get_dapm() */
struct snd_soc_dapm_context dapm;
/* machine specific init */
int (*init)(struct snd_soc_component *component);
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_root;
const char *debugfs_prefix;
#endif
};
#define for_each_component_dais(component, dai)\
list_for_each_entry(dai, &(component)->dai_list, list)
#define for_each_component_dais_safe(component, dai, _dai)\
list_for_each_entry_safe(dai, _dai, &(component)->dai_list, list)
/**
* snd_soc_dapm_to_component() - Casts a DAPM context to the component it is
* embedded in
* @dapm: The DAPM context to cast to the component
*
* This function must only be used on DAPM contexts that are known to be part of
* a component (e.g. in a component driver). Otherwise the behavior is
* undefined.
*/
static inline struct snd_soc_component *snd_soc_dapm_to_component(
struct snd_soc_dapm_context *dapm)
{
return container_of(dapm, struct snd_soc_component, dapm);
}
/**
* snd_soc_component_get_dapm() - Returns the DAPM context associated with a
* component
* @component: The component for which to get the DAPM context
*/
static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm(
struct snd_soc_component *component)
{
return &component->dapm;
}
/**
* snd_soc_component_init_bias_level() - Initialize COMPONENT DAPM bias level
* @component: The COMPONENT for which to initialize the DAPM bias level
* @level: The DAPM level to initialize to
*
* Initializes the COMPONENT DAPM bias level. See snd_soc_dapm_init_bias_level()
*/
static inline void
snd_soc_component_init_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
snd_soc_dapm_init_bias_level(
snd_soc_component_get_dapm(component), level);
}
/**
* snd_soc_component_get_bias_level() - Get current COMPONENT DAPM bias level
* @component: The COMPONENT for which to get the DAPM bias level
*
* Returns: The current DAPM bias level of the COMPONENT.
*/
static inline enum snd_soc_bias_level
snd_soc_component_get_bias_level(struct snd_soc_component *component)
{
return snd_soc_dapm_get_bias_level(
snd_soc_component_get_dapm(component));
}
/**
* snd_soc_component_force_bias_level() - Set the COMPONENT DAPM bias level
* @component: The COMPONENT for which to set the level
* @level: The level to set to
*
* Forces the COMPONENT bias level to a specific state. See
* snd_soc_dapm_force_bias_level().
*/
static inline int
snd_soc_component_force_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
return snd_soc_dapm_force_bias_level(
snd_soc_component_get_dapm(component),
level);
}
/**
* snd_soc_dapm_kcontrol_component() - Returns the component associated to a
* kcontrol
* @kcontrol: The kcontrol
*
* This function must only be used on DAPM contexts that are known to be part of
* a COMPONENT (e.g. in a COMPONENT driver). Otherwise the behavior is undefined
*/
static inline struct snd_soc_component *snd_soc_dapm_kcontrol_component(
struct snd_kcontrol *kcontrol)
{
return snd_soc_dapm_to_component(snd_soc_dapm_kcontrol_dapm(kcontrol));
}
/**
* snd_soc_component_cache_sync() - Sync the register cache with the hardware
* @component: COMPONENT to sync
*
* Note: This function will call regcache_sync()
*/
static inline int snd_soc_component_cache_sync(
struct snd_soc_component *component)
{
return regcache_sync(component->regmap);
}
/* component IO */
int snd_soc_component_read(struct snd_soc_component *component,
unsigned int reg, unsigned int *val);
unsigned int snd_soc_component_read32(struct snd_soc_component *component,
unsigned int reg);
int snd_soc_component_write(struct snd_soc_component *component,
unsigned int reg, unsigned int val);
int snd_soc_component_update_bits(struct snd_soc_component *component,
unsigned int reg, unsigned int mask,
unsigned int val);
int snd_soc_component_update_bits_async(struct snd_soc_component *component,
unsigned int reg, unsigned int mask,
unsigned int val);
void snd_soc_component_async_complete(struct snd_soc_component *component);
int snd_soc_component_test_bits(struct snd_soc_component *component,
unsigned int reg, unsigned int mask,
unsigned int value);
/* component wide operations */
int snd_soc_component_set_sysclk(struct snd_soc_component *component,
int clk_id, int source,
unsigned int freq, int dir);
int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id,
int source, unsigned int freq_in,
unsigned int freq_out);
int snd_soc_component_set_jack(struct snd_soc_component *component,
struct snd_soc_jack *jack, void *data);
void snd_soc_component_seq_notifier(struct snd_soc_component *component,
enum snd_soc_dapm_type type, int subseq);
int snd_soc_component_stream_event(struct snd_soc_component *component,
int event);
int snd_soc_component_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level);
#ifdef CONFIG_REGMAP
void snd_soc_component_init_regmap(struct snd_soc_component *component,
struct regmap *regmap);
void snd_soc_component_exit_regmap(struct snd_soc_component *component);
#endif
#define snd_soc_component_module_get_when_probe(component)\
snd_soc_component_module_get(component, 0)
#define snd_soc_component_module_get_when_open(component) \
snd_soc_component_module_get(component, 1)
int snd_soc_component_module_get(struct snd_soc_component *component,
int upon_open);
#define snd_soc_component_module_put_when_remove(component) \
snd_soc_component_module_put(component, 0)
#define snd_soc_component_module_put_when_close(component) \
snd_soc_component_module_put(component, 1)
void snd_soc_component_module_put(struct snd_soc_component *component,
int upon_open);
static inline void snd_soc_component_set_drvdata(struct snd_soc_component *c,
void *data)
{
dev_set_drvdata(c->dev, data);
}
static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c)
{
return dev_get_drvdata(c->dev);
}
static inline bool snd_soc_component_is_active(
struct snd_soc_component *component)
{
return component->active != 0;
}
/* component pin */
int snd_soc_component_enable_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_disable_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_nc_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_get_pin_status(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_force_enable_pin_unlocked(
struct snd_soc_component *component,
const char *pin);
/* component driver ops */
int snd_soc_component_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int snd_soc_component_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int snd_soc_component_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int snd_soc_component_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
int snd_soc_component_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int snd_soc_component_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
int cmd);
void snd_soc_component_suspend(struct snd_soc_component *component);
void snd_soc_component_resume(struct snd_soc_component *component);
int snd_soc_component_is_suspended(struct snd_soc_component *component);
int snd_soc_component_probe(struct snd_soc_component *component);
void snd_soc_component_remove(struct snd_soc_component *component);
int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component,
struct device_node *ep);
int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component,
struct of_phandle_args *args,
const char **dai_name);
int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream);
int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg);
int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream,
int channel, unsigned long pos,
void __user *buf, unsigned long bytes);
struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream,
unsigned long offset);
int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma);
int snd_soc_pcm_component_new(struct snd_pcm *pcm);
void snd_soc_pcm_component_free(struct snd_pcm *pcm);
#endif /* __SOC_COMPONENT_H */
...@@ -145,6 +145,31 @@ int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai, ...@@ -145,6 +145,31 @@ int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai,
int snd_soc_dai_is_dummy(struct snd_soc_dai *dai); int snd_soc_dai_is_dummy(struct snd_soc_dai *dai);
int snd_soc_dai_hw_params(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
void snd_soc_dai_hw_free(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream);
int snd_soc_dai_startup(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream);
void snd_soc_dai_shutdown(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream);
int snd_soc_dai_prepare(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream);
int snd_soc_dai_trigger(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream, int cmd);
int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream, int cmd);
snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai,
struct snd_pcm_substream *substream);
void snd_soc_dai_suspend(struct snd_soc_dai *dai);
void snd_soc_dai_resume(struct snd_soc_dai *dai);
int snd_soc_dai_probe(struct snd_soc_dai *dai);
int snd_soc_dai_remove(struct snd_soc_dai *dai);
int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
struct snd_soc_pcm_runtime *rtd, int num);
bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream);
struct snd_soc_dai_ops { struct snd_soc_dai_ops {
/* /*
* DAI clocking configuration, all optional. * DAI clocking configuration, all optional.
...@@ -268,8 +293,6 @@ struct snd_soc_dai_driver { ...@@ -268,8 +293,6 @@ struct snd_soc_dai_driver {
/* Optional Callback used at pcm creation*/ /* Optional Callback used at pcm creation*/
int (*pcm_new)(struct snd_soc_pcm_runtime *rtd, int (*pcm_new)(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_dai *dai); struct snd_soc_dai *dai);
/* DAI is also used for the control bus */
bool bus_control;
/* ops */ /* ops */
const struct snd_soc_dai_ops *ops; const struct snd_soc_dai_ops *ops;
...@@ -281,6 +304,7 @@ struct snd_soc_dai_driver { ...@@ -281,6 +304,7 @@ struct snd_soc_dai_driver {
unsigned int symmetric_rates:1; unsigned int symmetric_rates:1;
unsigned int symmetric_channels:1; unsigned int symmetric_channels:1;
unsigned int symmetric_samplebits:1; unsigned int symmetric_samplebits:1;
unsigned int bus_control:1; /* DAI is also used for the control bus */
/* probe ordering - for components with runtime dependencies */ /* probe ordering - for components with runtime dependencies */
int probe_order; int probe_order;
......
...@@ -353,6 +353,8 @@ struct device; ...@@ -353,6 +353,8 @@ struct device;
#define SND_SOC_DAPM_WILL_PMD 0x80 /* called at start of sequence */ #define SND_SOC_DAPM_WILL_PMD 0x80 /* called at start of sequence */
#define SND_SOC_DAPM_PRE_POST_PMD \ #define SND_SOC_DAPM_PRE_POST_PMD \
(SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD) (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD)
#define SND_SOC_DAPM_PRE_POST_PMU \
(SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU)
/* convenience event type detection */ /* convenience event type detection */
#define SND_SOC_DAPM_EVENT_ON(e) \ #define SND_SOC_DAPM_EVENT_ON(e) \
...@@ -417,6 +419,9 @@ int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream, ...@@ -417,6 +419,9 @@ int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream,
/* dapm path setup */ /* dapm path setup */
int snd_soc_dapm_new_widgets(struct snd_soc_card *card); int snd_soc_dapm_new_widgets(struct snd_soc_card *card);
void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm); void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm);
void snd_soc_dapm_init(struct snd_soc_dapm_context *dapm,
struct snd_soc_card *card,
struct snd_soc_component *component);
int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route, int num); const struct snd_soc_dapm_route *route, int num);
int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm,
...@@ -662,8 +667,6 @@ struct snd_soc_dapm_context { ...@@ -662,8 +667,6 @@ struct snd_soc_dapm_context {
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
/* Go to BIAS_OFF in suspend if the DAPM context is idle */ /* Go to BIAS_OFF in suspend if the DAPM context is idle */
unsigned int suspend_bias_off:1; unsigned int suspend_bias_off:1;
void (*seq_notifier)(struct snd_soc_dapm_context *,
enum snd_soc_dapm_type, int);
struct device *dev; /* from parent - for debug */ struct device *dev; /* from parent - for debug */
struct snd_soc_component *component; /* parent component */ struct snd_soc_component *component; /* parent component */
...@@ -673,10 +676,6 @@ struct snd_soc_dapm_context { ...@@ -673,10 +676,6 @@ struct snd_soc_dapm_context {
enum snd_soc_bias_level target_bias_level; enum snd_soc_bias_level target_bias_level;
struct list_head list; struct list_head list;
int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
int (*set_bias_level)(struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level);
struct snd_soc_dapm_wcache path_sink_cache; struct snd_soc_dapm_wcache path_sink_cache;
struct snd_soc_dapm_wcache path_source_cache; struct snd_soc_dapm_wcache path_source_cache;
......
...@@ -142,9 +142,16 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream, ...@@ -142,9 +142,16 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream,
/* internal use only */ /* internal use only */
int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute); int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
int soc_dpcm_runtime_update(struct snd_soc_card *); int soc_dpcm_runtime_update(struct snd_soc_card *);
#ifdef CONFIG_DEBUG_FS
void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
#else
static inline void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
{
}
#endif
int dpcm_path_get(struct snd_soc_pcm_runtime *fe, int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
int stream, struct snd_soc_dapm_widget_list **list_); int stream, struct snd_soc_dapm_widget_list **list_);
int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
......
...@@ -362,21 +362,6 @@ ...@@ -362,21 +362,6 @@
#define SOC_ENUM_SINGLE_VIRT_DECL(name, xtexts) \ #define SOC_ENUM_SINGLE_VIRT_DECL(name, xtexts) \
const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts) const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts)
/*
* Component probe and remove ordering levels for components with runtime
* dependencies.
*/
#define SND_SOC_COMP_ORDER_FIRST -2
#define SND_SOC_COMP_ORDER_EARLY -1
#define SND_SOC_COMP_ORDER_NORMAL 0
#define SND_SOC_COMP_ORDER_LATE 1
#define SND_SOC_COMP_ORDER_LAST 2
#define for_each_comp_order(order) \
for (order = SND_SOC_COMP_ORDER_FIRST; \
order <= SND_SOC_COMP_ORDER_LAST; \
order++)
/* /*
* Bias levels * Bias levels
* *
...@@ -505,10 +490,6 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *parms); ...@@ -505,10 +490,6 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *parms);
int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
const struct snd_pcm_hardware *hw); const struct snd_pcm_hardware *hw);
int soc_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai);
/* Jack reporting */ /* Jack reporting */
int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type,
struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins,
...@@ -751,132 +732,6 @@ struct snd_soc_compr_ops { ...@@ -751,132 +732,6 @@ struct snd_soc_compr_ops {
int (*trigger)(struct snd_compr_stream *); int (*trigger)(struct snd_compr_stream *);
}; };
/* component interface */
struct snd_soc_component_driver {
const char *name;
/* Default control and setup, added after probe() is run */
const struct snd_kcontrol_new *controls;
unsigned int num_controls;
const struct snd_soc_dapm_widget *dapm_widgets;
unsigned int num_dapm_widgets;
const struct snd_soc_dapm_route *dapm_routes;
unsigned int num_dapm_routes;
int (*probe)(struct snd_soc_component *);
void (*remove)(struct snd_soc_component *);
int (*suspend)(struct snd_soc_component *);
int (*resume)(struct snd_soc_component *);
unsigned int (*read)(struct snd_soc_component *, unsigned int);
int (*write)(struct snd_soc_component *, unsigned int, unsigned int);
/* pcm creation and destruction */
int (*pcm_new)(struct snd_soc_pcm_runtime *);
void (*pcm_free)(struct snd_pcm *);
/* component wide operations */
int (*set_sysclk)(struct snd_soc_component *component,
int clk_id, int source, unsigned int freq, int dir);
int (*set_pll)(struct snd_soc_component *component, int pll_id,
int source, unsigned int freq_in, unsigned int freq_out);
int (*set_jack)(struct snd_soc_component *component,
struct snd_soc_jack *jack, void *data);
/* DT */
int (*of_xlate_dai_name)(struct snd_soc_component *component,
struct of_phandle_args *args,
const char **dai_name);
int (*of_xlate_dai_id)(struct snd_soc_component *comment,
struct device_node *endpoint);
void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type,
int subseq);
int (*stream_event)(struct snd_soc_component *, int event);
int (*set_bias_level)(struct snd_soc_component *component,
enum snd_soc_bias_level level);
const struct snd_pcm_ops *ops;
const struct snd_compr_ops *compr_ops;
/* probe ordering - for components with runtime dependencies */
int probe_order;
int remove_order;
/*
* signal if the module handling the component should not be removed
* if a pcm is open. Setting this would prevent the module
* refcount being incremented in probe() but allow it be incremented
* when a pcm is opened and decremented when it is closed.
*/
unsigned int module_get_upon_open:1;
/* bits */
unsigned int idle_bias_on:1;
unsigned int suspend_bias_off:1;
unsigned int use_pmdown_time:1; /* care pmdown_time at stop */
unsigned int endianness:1;
unsigned int non_legacy_dai_naming:1;
/* this component uses topology and ignore machine driver FEs */
const char *ignore_machine;
const char *topology_name_prefix;
int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
bool use_dai_pcm_id; /* use the DAI link PCM ID as PCM device number */
int be_pcm_base; /* base device ID for all BE PCMs */
};
struct snd_soc_component {
const char *name;
int id;
const char *name_prefix;
struct device *dev;
struct snd_soc_card *card;
unsigned int active;
unsigned int suspended:1; /* is in suspend PM state */
struct list_head list;
struct list_head card_aux_list; /* for auxiliary bound components */
struct list_head card_list;
const struct snd_soc_component_driver *driver;
struct list_head dai_list;
int num_dai;
struct regmap *regmap;
int val_bytes;
struct mutex io_mutex;
/* attached dynamic objects */
struct list_head dobj_list;
/*
* DO NOT use any of the fields below in drivers, they are temporary and
* are going to be removed again soon. If you use them in driver code the
* driver will be marked as BROKEN when these fields are removed.
*/
/* Don't use these, use snd_soc_component_get_dapm() */
struct snd_soc_dapm_context dapm;
/* machine specific init */
int (*init)(struct snd_soc_component *component);
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_root;
const char *debugfs_prefix;
#endif
};
#define for_each_component_dais(component, dai)\
list_for_each_entry(dai, &(component)->dai_list, list)
#define for_each_component_dais_safe(component, dai, _dai)\
list_for_each_entry_safe(dai, _dai, &(component)->dai_list, list)
struct snd_soc_rtdcom_list { struct snd_soc_rtdcom_list {
struct snd_soc_component *component; struct snd_soc_component *component;
struct list_head list; /* rtd::component_list */ struct list_head list; /* rtd::component_list */
...@@ -1086,6 +941,7 @@ struct snd_soc_dai_link { ...@@ -1086,6 +941,7 @@ struct snd_soc_dai_link {
#define COMP_CPU(_dai) { .dai_name = _dai, } #define COMP_CPU(_dai) { .dai_name = _dai, }
#define COMP_CODEC(_name, _dai) { .name = _name, .dai_name = _dai, } #define COMP_CODEC(_name, _dai) { .name = _name, .dai_name = _dai, }
#define COMP_PLATFORM(_name) { .name = _name } #define COMP_PLATFORM(_name) { .name = _name }
#define COMP_AUX(_name) { .name = _name }
#define COMP_DUMMY() { .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", } #define COMP_DUMMY() { .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", }
extern struct snd_soc_dai_link_component null_dailink_component[0]; extern struct snd_soc_dai_link_component null_dailink_component[0];
...@@ -1107,14 +963,11 @@ struct snd_soc_codec_conf { ...@@ -1107,14 +963,11 @@ struct snd_soc_codec_conf {
}; };
struct snd_soc_aux_dev { struct snd_soc_aux_dev {
const char *name; /* Codec name */
/* /*
* specify multi-codec either by device name, or by * specify multi-codec either by device name, or by
* DT/OF node, but not both. * DT/OF node, but not both.
*/ */
const char *codec_name; struct snd_soc_dai_link_component dlc;
struct device_node *codec_of_node;
/* codec/machine specific init - e.g. add machine controls */ /* codec/machine specific init - e.g. add machine controls */
int (*init)(struct snd_soc_component *component); int (*init)(struct snd_soc_component *component);
...@@ -1135,6 +988,10 @@ struct snd_soc_card { ...@@ -1135,6 +988,10 @@ struct snd_soc_card {
struct mutex mutex; struct mutex mutex;
struct mutex dapm_mutex; struct mutex dapm_mutex;
/* Mutex for PCM operations */
struct mutex pcm_mutex;
enum snd_soc_pcm_subclass pcm_subclass;
spinlock_t dpcm_lock; spinlock_t dpcm_lock;
bool instantiated; bool instantiated;
...@@ -1203,8 +1060,6 @@ struct snd_soc_card { ...@@ -1203,8 +1060,6 @@ struct snd_soc_card {
int num_of_dapm_routes; int num_of_dapm_routes;
bool fully_routed; bool fully_routed;
struct work_struct deferred_resume_work;
/* lists of probed devices belonging to this card */ /* lists of probed devices belonging to this card */
struct list_head component_dev_list; struct list_head component_dev_list;
struct list_head list; struct list_head list;
...@@ -1224,7 +1079,9 @@ struct snd_soc_card { ...@@ -1224,7 +1079,9 @@ struct snd_soc_card {
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_card_root; struct dentry *debugfs_card_root;
struct dentry *debugfs_pop_time; #endif
#ifdef CONFIG_PM_SLEEP
struct work_struct deferred_resume_work;
#endif #endif
u32 pop_time; u32 pop_time;
...@@ -1234,6 +1091,10 @@ struct snd_soc_card { ...@@ -1234,6 +1091,10 @@ struct snd_soc_card {
for ((i) = 0; \ for ((i) = 0; \
((i) < (card)->num_links) && ((link) = &(card)->dai_link[i]); \ ((i) < (card)->num_links) && ((link) = &(card)->dai_link[i]); \
(i)++) (i)++)
#define for_each_card_pre_auxs(card, i, aux) \
for ((i) = 0; \
((i) < (card)->num_aux_devs) && ((aux) = &(card)->aux_dev[i]); \
(i)++)
#define for_each_card_links(card, link) \ #define for_each_card_links(card, link) \
list_for_each_entry(link, &(card)->dai_link_list, list) list_for_each_entry(link, &(card)->dai_link_list, list)
...@@ -1245,6 +1106,12 @@ struct snd_soc_card { ...@@ -1245,6 +1106,12 @@ struct snd_soc_card {
#define for_each_card_rtds_safe(card, rtd, _rtd) \ #define for_each_card_rtds_safe(card, rtd, _rtd) \
list_for_each_entry_safe(rtd, _rtd, &(card)->rtd_list, list) list_for_each_entry_safe(rtd, _rtd, &(card)->rtd_list, list)
#define for_each_card_auxs(card, component) \
list_for_each_entry(component, &card->aux_comp_list, card_aux_list)
#define for_each_card_auxs_safe(card, component, _comp) \
list_for_each_entry_safe(component, _comp, \
&card->aux_comp_list, card_aux_list)
#define for_each_card_components(card, component) \ #define for_each_card_components(card, component) \
list_for_each_entry(component, &(card)->component_dev_list, card_list) list_for_each_entry(component, &(card)->component_dev_list, card_list)
...@@ -1253,8 +1120,6 @@ struct snd_soc_pcm_runtime { ...@@ -1253,8 +1120,6 @@ struct snd_soc_pcm_runtime {
struct device *dev; struct device *dev;
struct snd_soc_card *card; struct snd_soc_card *card;
struct snd_soc_dai_link *dai_link; struct snd_soc_dai_link *dai_link;
struct mutex pcm_mutex;
enum snd_soc_pcm_subclass pcm_subclass;
struct snd_pcm_ops ops; struct snd_pcm_ops ops;
unsigned int params_select; /* currently selected param for dai link */ unsigned int params_select; /* currently selected param for dai link */
...@@ -1342,134 +1207,6 @@ struct soc_enum { ...@@ -1342,134 +1207,6 @@ struct soc_enum {
struct snd_soc_dobj dobj; struct snd_soc_dobj dobj;
}; };
/**
* snd_soc_dapm_to_component() - Casts a DAPM context to the component it is
* embedded in
* @dapm: The DAPM context to cast to the component
*
* This function must only be used on DAPM contexts that are known to be part of
* a component (e.g. in a component driver). Otherwise the behavior is
* undefined.
*/
static inline struct snd_soc_component *snd_soc_dapm_to_component(
struct snd_soc_dapm_context *dapm)
{
return container_of(dapm, struct snd_soc_component, dapm);
}
/**
* snd_soc_component_get_dapm() - Returns the DAPM context associated with a
* component
* @component: The component for which to get the DAPM context
*/
static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm(
struct snd_soc_component *component)
{
return &component->dapm;
}
/**
* snd_soc_component_init_bias_level() - Initialize COMPONENT DAPM bias level
* @component: The COMPONENT for which to initialize the DAPM bias level
* @level: The DAPM level to initialize to
*
* Initializes the COMPONENT DAPM bias level. See snd_soc_dapm_init_bias_level().
*/
static inline void
snd_soc_component_init_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
snd_soc_dapm_init_bias_level(
snd_soc_component_get_dapm(component), level);
}
/**
* snd_soc_component_get_bias_level() - Get current COMPONENT DAPM bias level
* @component: The COMPONENT for which to get the DAPM bias level
*
* Returns: The current DAPM bias level of the COMPONENT.
*/
static inline enum snd_soc_bias_level
snd_soc_component_get_bias_level(struct snd_soc_component *component)
{
return snd_soc_dapm_get_bias_level(
snd_soc_component_get_dapm(component));
}
/**
* snd_soc_component_force_bias_level() - Set the COMPONENT DAPM bias level
* @component: The COMPONENT for which to set the level
* @level: The level to set to
*
* Forces the COMPONENT bias level to a specific state. See
* snd_soc_dapm_force_bias_level().
*/
static inline int
snd_soc_component_force_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
return snd_soc_dapm_force_bias_level(
snd_soc_component_get_dapm(component),
level);
}
/**
* snd_soc_dapm_kcontrol_component() - Returns the component associated to a kcontrol
* @kcontrol: The kcontrol
*
* This function must only be used on DAPM contexts that are known to be part of
* a COMPONENT (e.g. in a COMPONENT driver). Otherwise the behavior is undefined.
*/
static inline struct snd_soc_component *snd_soc_dapm_kcontrol_component(
struct snd_kcontrol *kcontrol)
{
return snd_soc_dapm_to_component(snd_soc_dapm_kcontrol_dapm(kcontrol));
}
/**
* snd_soc_component_cache_sync() - Sync the register cache with the hardware
* @component: COMPONENT to sync
*
* Note: This function will call regcache_sync()
*/
static inline int snd_soc_component_cache_sync(
struct snd_soc_component *component)
{
return regcache_sync(component->regmap);
}
/* component IO */
int snd_soc_component_read(struct snd_soc_component *component,
unsigned int reg, unsigned int *val);
unsigned int snd_soc_component_read32(struct snd_soc_component *component,
unsigned int reg);
int snd_soc_component_write(struct snd_soc_component *component,
unsigned int reg, unsigned int val);
int snd_soc_component_update_bits(struct snd_soc_component *component,
unsigned int reg, unsigned int mask, unsigned int val);
int snd_soc_component_update_bits_async(struct snd_soc_component *component,
unsigned int reg, unsigned int mask, unsigned int val);
void snd_soc_component_async_complete(struct snd_soc_component *component);
int snd_soc_component_test_bits(struct snd_soc_component *component,
unsigned int reg, unsigned int mask, unsigned int value);
/* component wide operations */
int snd_soc_component_set_sysclk(struct snd_soc_component *component,
int clk_id, int source, unsigned int freq, int dir);
int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id,
int source, unsigned int freq_in,
unsigned int freq_out);
int snd_soc_component_set_jack(struct snd_soc_component *component,
struct snd_soc_jack *jack, void *data);
#ifdef CONFIG_REGMAP
void snd_soc_component_init_regmap(struct snd_soc_component *component,
struct regmap *regmap);
void snd_soc_component_exit_regmap(struct snd_soc_component *component);
#endif
/* device driver data */ /* device driver data */
static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card,
...@@ -1483,27 +1220,6 @@ static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) ...@@ -1483,27 +1220,6 @@ static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card)
return card->drvdata; return card->drvdata;
} }
static inline void snd_soc_component_set_drvdata(struct snd_soc_component *c,
void *data)
{
dev_set_drvdata(c->dev, data);
}
static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c)
{
return dev_get_drvdata(c->dev);
}
static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
{
INIT_LIST_HEAD(&card->widgets);
INIT_LIST_HEAD(&card->paths);
INIT_LIST_HEAD(&card->dapm_list);
INIT_LIST_HEAD(&card->aux_comp_list);
INIT_LIST_HEAD(&card->component_dev_list);
INIT_LIST_HEAD(&card->list);
}
static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
{ {
if (mc->reg == mc->rreg && mc->shift == mc->rshift) if (mc->reg == mc->rreg && mc->shift == mc->rshift)
...@@ -1540,12 +1256,6 @@ static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e, ...@@ -1540,12 +1256,6 @@ static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e,
return e->values[item]; return e->values[item];
} }
static inline bool snd_soc_component_is_active(
struct snd_soc_component *component)
{
return component->active != 0;
}
/** /**
* snd_soc_kcontrol_component() - Returns the component that registered the * snd_soc_kcontrol_component() - Returns the component that registered the
* control * control
...@@ -1681,24 +1391,6 @@ static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm) ...@@ -1681,24 +1391,6 @@ static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm)
mutex_unlock(&dapm->card->dapm_mutex); mutex_unlock(&dapm->card->dapm_mutex);
} }
int snd_soc_component_enable_pin(struct snd_soc_component *component, #include <sound/soc-component.h>
const char *pin);
int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_disable_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_nc_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_get_pin_status(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_force_enable_pin_unlocked(
struct snd_soc_component *component,
const char *pin);
#endif #endif
...@@ -76,6 +76,9 @@ struct sof_ipc_dai_ssp_params { ...@@ -76,6 +76,9 @@ struct sof_ipc_dai_ssp_params {
uint16_t tdm_per_slot_padding_flag; uint16_t tdm_per_slot_padding_flag;
uint32_t clks_control; uint32_t clks_control;
uint32_t quirks; uint32_t quirks;
uint32_t bclk_delay; /* guaranteed time (ms) for which BCLK
* will be driven, before sending data
*/
} __packed; } __packed;
/* HDA Configuration Request - SOF_IPC_DAI_HDA_CONFIG */ /* HDA Configuration Request - SOF_IPC_DAI_HDA_CONFIG */
...@@ -176,4 +179,13 @@ struct sof_ipc_dai_dmic_params { ...@@ -176,4 +179,13 @@ struct sof_ipc_dai_dmic_params {
struct sof_ipc_dai_dmic_pdm_ctrl pdm[0]; struct sof_ipc_dai_dmic_pdm_ctrl pdm[0];
} __packed; } __packed;
/* ALH Configuration Request - SOF_IPC_DAI_ALH_CONFIG */
struct sof_ipc_dai_alh_params {
struct sof_ipc_hdr hdr;
uint32_t stream_id;
/* reserved for future use */
uint32_t reserved[15];
} __packed;
#endif #endif
...@@ -49,7 +49,9 @@ enum sof_ipc_dai_type { ...@@ -49,7 +49,9 @@ enum sof_ipc_dai_type {
SOF_DAI_INTEL_SSP, /**< Intel SSP */ SOF_DAI_INTEL_SSP, /**< Intel SSP */
SOF_DAI_INTEL_DMIC, /**< Intel DMIC */ SOF_DAI_INTEL_DMIC, /**< Intel DMIC */
SOF_DAI_INTEL_HDA, /**< Intel HD/A */ SOF_DAI_INTEL_HDA, /**< Intel HD/A */
SOF_DAI_INTEL_SOUNDWIRE, /**< Intel SoundWire */ SOF_DAI_INTEL_ALH, /**< Intel ALH */
SOF_DAI_IMX_SAI, /**< i.MX SAI */
SOF_DAI_IMX_ESAI, /**< i.MX ESAI */
}; };
/* general purpose DAI configuration */ /* general purpose DAI configuration */
...@@ -70,6 +72,7 @@ struct sof_ipc_dai_config { ...@@ -70,6 +72,7 @@ struct sof_ipc_dai_config {
struct sof_ipc_dai_ssp_params ssp; struct sof_ipc_dai_ssp_params ssp;
struct sof_ipc_dai_dmic_params dmic; struct sof_ipc_dai_dmic_params dmic;
struct sof_ipc_dai_hda_params hda; struct sof_ipc_dai_hda_params hda;
struct sof_ipc_dai_alh_params alh;
}; };
} __packed; } __packed;
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
/* SOF ABI version major, minor and patch numbers */ /* SOF ABI version major, minor and patch numbers */
#define SOF_ABI_MAJOR 3 #define SOF_ABI_MAJOR 3
#define SOF_ABI_MINOR 8 #define SOF_ABI_MINOR 10
#define SOF_ABI_PATCH 0 #define SOF_ABI_PATCH 0
/* SOF ABI version number. Format within 32bit word is MMmmmppp */ /* SOF ABI version number. Format within 32bit word is MMmmmppp */
......
...@@ -75,6 +75,7 @@ ...@@ -75,6 +75,7 @@
#define SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH 503 #define SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH 503
#define SOF_TKN_INTEL_SSP_QUIRKS 504 #define SOF_TKN_INTEL_SSP_QUIRKS 504
#define SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT 505 #define SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT 505
#define SOF_TKN_INTEL_SSP_BCLK_DELAY 506
/* DMIC */ /* DMIC */
#define SOF_TKN_INTEL_DMIC_DRIVER_VERSION 600 #define SOF_TKN_INTEL_DMIC_DRIVER_VERSION 600
...@@ -105,4 +106,12 @@ ...@@ -105,4 +106,12 @@
/* for backward compatibility */ /* for backward compatibility */
#define SOF_TKN_EFFECT_TYPE SOF_TKN_PROCESS_TYPE #define SOF_TKN_EFFECT_TYPE SOF_TKN_PROCESS_TYPE
/* SAI */
#define SOF_TKN_IMX_SAI_FIRST_TOKEN 1000
/* TODO: Add SAI tokens */
/* ESAI */
#define SOF_TKN_IMX_ESAI_FIRST_TOKEN 1100
/* TODO: Add ESAI tokens */
#endif #endif
...@@ -2170,7 +2170,7 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, ...@@ -2170,7 +2170,7 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
static const unsigned int rates[] = { static const unsigned int rates[] = {
5512, 8000, 11025, 16000, 22050, 32000, 44100, 5512, 8000, 11025, 16000, 22050, 32000, 44100,
48000, 64000, 88200, 96000, 176400, 192000 48000, 64000, 88200, 96000, 176400, 192000, 352800, 384000
}; };
const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
......
...@@ -6,6 +6,9 @@ config SND_HDA_CORE ...@@ -6,6 +6,9 @@ config SND_HDA_CORE
config SND_HDA_DSP_LOADER config SND_HDA_DSP_LOADER
bool bool
config SND_HDA_ALIGNED_MMIO
bool
config SND_HDA_COMPONENT config SND_HDA_COMPONENT
bool bool
...@@ -29,3 +32,8 @@ config SND_HDA_PREALLOC_SIZE ...@@ -29,3 +32,8 @@ config SND_HDA_PREALLOC_SIZE
Note that the pre-allocation size can be changed dynamically Note that the pre-allocation size can be changed dynamically
via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too. via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too.
config SND_INTEL_NHLT
tristate
# this config should be selected only for Intel ACPI platforms.
# A fallback is provided so that the code compiles in all cases.
\ No newline at end of file
...@@ -13,3 +13,6 @@ obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o ...@@ -13,3 +13,6 @@ obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o
#extended hda #extended hda
obj-$(CONFIG_SND_HDA_EXT_CORE) += ext/ obj-$(CONFIG_SND_HDA_EXT_CORE) += ext/
snd-intel-nhlt-objs := intel-nhlt.o
obj-$(CONFIG_SND_INTEL_NHLT) += snd-intel-nhlt.o
...@@ -17,80 +17,22 @@ ...@@ -17,80 +17,22 @@
MODULE_DESCRIPTION("HDA extended core"); MODULE_DESCRIPTION("HDA extended core");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
static void hdac_ext_writel(u32 value, u32 __iomem *addr)
{
writel(value, addr);
}
static u32 hdac_ext_readl(u32 __iomem *addr)
{
return readl(addr);
}
static void hdac_ext_writew(u16 value, u16 __iomem *addr)
{
writew(value, addr);
}
static u16 hdac_ext_readw(u16 __iomem *addr)
{
return readw(addr);
}
static void hdac_ext_writeb(u8 value, u8 __iomem *addr)
{
writeb(value, addr);
}
static u8 hdac_ext_readb(u8 __iomem *addr)
{
return readb(addr);
}
static int hdac_ext_dma_alloc_pages(struct hdac_bus *bus, int type,
size_t size, struct snd_dma_buffer *buf)
{
return snd_dma_alloc_pages(type, bus->dev, size, buf);
}
static void hdac_ext_dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf)
{
snd_dma_free_pages(buf);
}
static const struct hdac_io_ops hdac_ext_default_io = {
.reg_writel = hdac_ext_writel,
.reg_readl = hdac_ext_readl,
.reg_writew = hdac_ext_writew,
.reg_readw = hdac_ext_readw,
.reg_writeb = hdac_ext_writeb,
.reg_readb = hdac_ext_readb,
.dma_alloc_pages = hdac_ext_dma_alloc_pages,
.dma_free_pages = hdac_ext_dma_free_pages,
};
/** /**
* snd_hdac_ext_bus_init - initialize a HD-audio extended bus * snd_hdac_ext_bus_init - initialize a HD-audio extended bus
* @ebus: the pointer to extended bus object * @ebus: the pointer to extended bus object
* @dev: device pointer * @dev: device pointer
* @ops: bus verb operators * @ops: bus verb operators
* @io_ops: lowlevel I/O operators, can be NULL. If NULL core will use
* default ops * default ops
* *
* Returns 0 if successful, or a negative error code. * Returns 0 if successful, or a negative error code.
*/ */
int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev,
const struct hdac_bus_ops *ops, const struct hdac_bus_ops *ops,
const struct hdac_io_ops *io_ops,
const struct hdac_ext_bus_ops *ext_ops) const struct hdac_ext_bus_ops *ext_ops)
{ {
int ret; int ret;
/* check if io ops are provided, if not load the defaults */ ret = snd_hdac_bus_init(bus, dev, ops);
if (io_ops == NULL)
io_ops = &hdac_ext_default_io;
ret = snd_hdac_bus_init(bus, dev, ops, io_ops);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/export.h> #include <linux/export.h>
...@@ -19,13 +20,11 @@ static const struct hdac_bus_ops default_ops = { ...@@ -19,13 +20,11 @@ static const struct hdac_bus_ops default_ops = {
* snd_hdac_bus_init - initialize a HD-audio bas bus * snd_hdac_bus_init - initialize a HD-audio bas bus
* @bus: the pointer to bus object * @bus: the pointer to bus object
* @ops: bus verb operators * @ops: bus verb operators
* @io_ops: lowlevel I/O operators
* *
* Returns 0 if successful, or a negative error code. * Returns 0 if successful, or a negative error code.
*/ */
int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
const struct hdac_bus_ops *ops, const struct hdac_bus_ops *ops)
const struct hdac_io_ops *io_ops)
{ {
memset(bus, 0, sizeof(*bus)); memset(bus, 0, sizeof(*bus));
bus->dev = dev; bus->dev = dev;
...@@ -33,7 +32,7 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, ...@@ -33,7 +32,7 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
bus->ops = ops; bus->ops = ops;
else else
bus->ops = &default_ops; bus->ops = &default_ops;
bus->io_ops = io_ops; bus->dma_type = SNDRV_DMA_TYPE_DEV;
INIT_LIST_HEAD(&bus->stream_list); INIT_LIST_HEAD(&bus->stream_list);
INIT_LIST_HEAD(&bus->codec_list); INIT_LIST_HEAD(&bus->codec_list);
INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events); INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events);
...@@ -217,3 +216,33 @@ void snd_hdac_bus_remove_device(struct hdac_bus *bus, ...@@ -217,3 +216,33 @@ void snd_hdac_bus_remove_device(struct hdac_bus *bus,
flush_work(&bus->unsol_work); flush_work(&bus->unsol_work);
} }
EXPORT_SYMBOL_GPL(snd_hdac_bus_remove_device); EXPORT_SYMBOL_GPL(snd_hdac_bus_remove_device);
#ifdef CONFIG_SND_HDA_ALIGNED_MMIO
/* Helpers for aligned read/write of mmio space, for Tegra */
unsigned int snd_hdac_aligned_read(void __iomem *addr, unsigned int mask)
{
void __iomem *aligned_addr =
(void __iomem *)((unsigned long)(addr) & ~0x3);
unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
unsigned int v;
v = readl(aligned_addr);
return (v >> shift) & mask;
}
EXPORT_SYMBOL_GPL(snd_hdac_aligned_read);
void snd_hdac_aligned_write(unsigned int val, void __iomem *addr,
unsigned int mask)
{
void __iomem *aligned_addr =
(void __iomem *)((unsigned long)(addr) & ~0x3);
unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
unsigned int v;
v = readl(aligned_addr);
v &= ~(mask << shift);
v |= val << shift;
writel(v, aligned_addr);
}
EXPORT_SYMBOL_GPL(snd_hdac_aligned_write);
#endif /* CONFIG_SND_HDA_ALIGNED_MMIO */
...@@ -575,12 +575,13 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus) ...@@ -575,12 +575,13 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus)
{ {
struct hdac_stream *s; struct hdac_stream *s;
int num_streams = 0; int num_streams = 0;
int dma_type = bus->dma_type ? bus->dma_type : SNDRV_DMA_TYPE_DEV;
int err; int err;
list_for_each_entry(s, &bus->stream_list, list) { list_for_each_entry(s, &bus->stream_list, list) {
/* allocate memory for the BDL for each stream */ /* allocate memory for the BDL for each stream */
err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, err = snd_dma_alloc_pages(dma_type, bus->dev,
BDL_SIZE, &s->bdl); BDL_SIZE, &s->bdl);
num_streams++; num_streams++;
if (err < 0) if (err < 0)
return -ENOMEM; return -ENOMEM;
...@@ -589,16 +590,15 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus) ...@@ -589,16 +590,15 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus)
if (WARN_ON(!num_streams)) if (WARN_ON(!num_streams))
return -EINVAL; return -EINVAL;
/* allocate memory for the position buffer */ /* allocate memory for the position buffer */
err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, err = snd_dma_alloc_pages(dma_type, bus->dev,
num_streams * 8, &bus->posbuf); num_streams * 8, &bus->posbuf);
if (err < 0) if (err < 0)
return -ENOMEM; return -ENOMEM;
list_for_each_entry(s, &bus->stream_list, list) list_for_each_entry(s, &bus->stream_list, list)
s->posbuf = (__le32 *)(bus->posbuf.area + s->index * 8); s->posbuf = (__le32 *)(bus->posbuf.area + s->index * 8);
/* single page (at least 4096 bytes) must suffice for both ringbuffes */ /* single page (at least 4096 bytes) must suffice for both ringbuffes */
return bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, return snd_dma_alloc_pages(dma_type, bus->dev, PAGE_SIZE, &bus->rb);
PAGE_SIZE, &bus->rb);
} }
EXPORT_SYMBOL_GPL(snd_hdac_bus_alloc_stream_pages); EXPORT_SYMBOL_GPL(snd_hdac_bus_alloc_stream_pages);
...@@ -612,12 +612,12 @@ void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus) ...@@ -612,12 +612,12 @@ void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus)
list_for_each_entry(s, &bus->stream_list, list) { list_for_each_entry(s, &bus->stream_list, list) {
if (s->bdl.area) if (s->bdl.area)
bus->io_ops->dma_free_pages(bus, &s->bdl); snd_dma_free_pages(&s->bdl);
} }
if (bus->rb.area) if (bus->rb.area)
bus->io_ops->dma_free_pages(bus, &bus->rb); snd_dma_free_pages(&bus->rb);
if (bus->posbuf.area) if (bus->posbuf.area)
bus->io_ops->dma_free_pages(bus, &bus->posbuf); snd_dma_free_pages(&bus->posbuf);
} }
EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages); EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages);
...@@ -680,8 +680,8 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, ...@@ -680,8 +680,8 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
azx_dev->locked = true; azx_dev->locked = true;
spin_unlock_irq(&bus->reg_lock); spin_unlock_irq(&bus->reg_lock);
err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV_SG, err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev,
byte_size, bufp); byte_size, bufp);
if (err < 0) if (err < 0)
goto err_alloc; goto err_alloc;
...@@ -707,7 +707,7 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, ...@@ -707,7 +707,7 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
return azx_dev->stream_tag; return azx_dev->stream_tag;
error: error:
bus->io_ops->dma_free_pages(bus, bufp); snd_dma_free_pages(bufp);
err_alloc: err_alloc:
spin_lock_irq(&bus->reg_lock); spin_lock_irq(&bus->reg_lock);
azx_dev->locked = false; azx_dev->locked = false;
...@@ -754,7 +754,7 @@ void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev, ...@@ -754,7 +754,7 @@ void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev,
azx_dev->period_bytes = 0; azx_dev->period_bytes = 0;
azx_dev->format_val = 0; azx_dev->format_val = 0;
bus->io_ops->dma_free_pages(bus, dmab); snd_dma_free_pages(dmab);
dmab->area = NULL; dmab->area = NULL;
spin_lock_irq(&bus->reg_lock); spin_lock_irq(&bus->reg_lock);
......
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2015-2019 Intel Corporation
#include <linux/acpi.h>
#include <sound/intel-nhlt.h>
#define NHLT_ACPI_HEADER_SIG "NHLT"
/* Unique identification for getting NHLT blobs */
static guid_t osc_guid =
GUID_INIT(0xA69F886E, 0x6CEB, 0x4594,
0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53);
struct nhlt_acpi_table *intel_nhlt_init(struct device *dev)
{
acpi_handle handle;
union acpi_object *obj;
struct nhlt_resource_desc *nhlt_ptr;
struct nhlt_acpi_table *nhlt_table = NULL;
handle = ACPI_HANDLE(dev);
if (!handle) {
dev_err(dev, "Didn't find ACPI_HANDLE\n");
return NULL;
}
obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL);
if (!obj)
return NULL;
if (obj->type != ACPI_TYPE_BUFFER) {
dev_dbg(dev, "No NHLT table found\n");
ACPI_FREE(obj);
return NULL;
}
nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer;
if (nhlt_ptr->length)
nhlt_table = (struct nhlt_acpi_table *)
memremap(nhlt_ptr->min_addr, nhlt_ptr->length,
MEMREMAP_WB);
ACPI_FREE(obj);
if (nhlt_table &&
(strncmp(nhlt_table->header.signature,
NHLT_ACPI_HEADER_SIG,
strlen(NHLT_ACPI_HEADER_SIG)) != 0)) {
memunmap(nhlt_table);
dev_err(dev, "NHLT ACPI header signature incorrect\n");
return NULL;
}
return nhlt_table;
}
EXPORT_SYMBOL_GPL(intel_nhlt_init);
void intel_nhlt_free(struct nhlt_acpi_table *nhlt)
{
memunmap((void *)nhlt);
}
EXPORT_SYMBOL_GPL(intel_nhlt_free);
int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
{
struct nhlt_endpoint *epnt;
struct nhlt_dmic_array_config *cfg;
struct nhlt_vendor_dmic_array_config *cfg_vendor;
unsigned int dmic_geo = 0;
u8 j;
if (!nhlt)
return 0;
epnt = (struct nhlt_endpoint *)nhlt->desc;
for (j = 0; j < nhlt->endpoint_count; j++) {
if (epnt->linktype == NHLT_LINK_DMIC) {
cfg = (struct nhlt_dmic_array_config *)
(epnt->config.caps);
switch (cfg->array_type) {
case NHLT_MIC_ARRAY_2CH_SMALL:
case NHLT_MIC_ARRAY_2CH_BIG:
dmic_geo = MIC_ARRAY_2CH;
break;
case NHLT_MIC_ARRAY_4CH_1ST_GEOM:
case NHLT_MIC_ARRAY_4CH_L_SHAPED:
case NHLT_MIC_ARRAY_4CH_2ND_GEOM:
dmic_geo = MIC_ARRAY_4CH;
break;
case NHLT_MIC_ARRAY_VENDOR_DEFINED:
cfg_vendor = (struct nhlt_vendor_dmic_array_config *)cfg;
dmic_geo = cfg_vendor->nb_mics;
break;
default:
dev_warn(dev, "undefined DMIC array_type 0x%0x\n",
cfg->array_type);
}
}
epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
}
return dmic_geo;
}
EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel NHLT driver");
...@@ -12,6 +12,7 @@ config SND_HDA_INTEL ...@@ -12,6 +12,7 @@ config SND_HDA_INTEL
tristate "HD Audio PCI" tristate "HD Audio PCI"
depends on SND_PCI depends on SND_PCI
select SND_HDA select SND_HDA
select SND_INTEL_NHLT if ACPI
help help
Say Y here to include support for Intel "High Definition Say Y here to include support for Intel "High Definition
Audio" (Azalia) and its compatible devices. Audio" (Azalia) and its compatible devices.
...@@ -22,10 +23,20 @@ config SND_HDA_INTEL ...@@ -22,10 +23,20 @@ config SND_HDA_INTEL
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called snd-hda-intel. will be called snd-hda-intel.
config SND_HDA_INTEL_DETECT_DMIC
bool "DMIC detection and probe abort"
depends on SND_HDA_INTEL
help
Say Y to detect digital microphones on SKL+ devices. DMICs
cannot be handled by the HDaudio legacy driver and are
currently only supported by the SOF driver.
If unsure say N.
config SND_HDA_TEGRA config SND_HDA_TEGRA
tristate "NVIDIA Tegra HD Audio" tristate "NVIDIA Tegra HD Audio"
depends on ARCH_TEGRA depends on ARCH_TEGRA
select SND_HDA select SND_HDA
select SND_HDA_ALIGNED_MMIO
help help
Say Y here to support the HDA controller present in NVIDIA Say Y here to support the HDA controller present in NVIDIA
Tegra SoCs Tegra SoCs
......
...@@ -846,7 +846,13 @@ static void snd_hda_codec_dev_release(struct device *dev) ...@@ -846,7 +846,13 @@ static void snd_hda_codec_dev_release(struct device *dev)
snd_hda_sysfs_clear(codec); snd_hda_sysfs_clear(codec);
kfree(codec->modelname); kfree(codec->modelname);
kfree(codec->wcaps); kfree(codec->wcaps);
kfree(codec);
/*
* In the case of ASoC HD-audio, hda_codec is device managed.
* It will be freed when the ASoC device is removed.
*/
if (codec->core.type == HDA_DEV_LEGACY)
kfree(codec);
} }
#define DEV_NAME_LEN 31 #define DEV_NAME_LEN 31
......
...@@ -1207,14 +1207,12 @@ void snd_hda_bus_reset(struct hda_bus *bus) ...@@ -1207,14 +1207,12 @@ void snd_hda_bus_reset(struct hda_bus *bus)
} }
/* HD-audio bus initialization */ /* HD-audio bus initialization */
int azx_bus_init(struct azx *chip, const char *model, int azx_bus_init(struct azx *chip, const char *model)
const struct hdac_io_ops *io_ops)
{ {
struct hda_bus *bus = &chip->bus; struct hda_bus *bus = &chip->bus;
int err; int err;
err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops, err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops);
io_ops);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -206,8 +206,7 @@ void azx_stop_chip(struct azx *chip); ...@@ -206,8 +206,7 @@ void azx_stop_chip(struct azx *chip);
irqreturn_t azx_interrupt(int irq, void *dev_id); irqreturn_t azx_interrupt(int irq, void *dev_id);
/* Codec interface */ /* Codec interface */
int azx_bus_init(struct azx *chip, const char *model, int azx_bus_init(struct azx *chip, const char *model);
const struct hdac_io_ops *io_ops);
int azx_probe_codecs(struct azx *chip, unsigned int max_slots); int azx_probe_codecs(struct azx *chip, unsigned int max_slots);
int azx_codec_configure(struct azx *chip); int azx_codec_configure(struct azx *chip);
int azx_init_streams(struct azx *chip); int azx_init_streams(struct azx *chip);
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/hdaudio.h> #include <sound/hdaudio.h>
#include <sound/hda_i915.h> #include <sound/hda_i915.h>
#include <sound/intel-nhlt.h>
#include <linux/vgaarb.h> #include <linux/vgaarb.h>
#include <linux/vga_switcheroo.h> #include <linux/vga_switcheroo.h>
#include <linux/firmware.h> #include <linux/firmware.h>
...@@ -125,6 +126,7 @@ static char *patch[SNDRV_CARDS]; ...@@ -125,6 +126,7 @@ static char *patch[SNDRV_CARDS];
static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] =
CONFIG_SND_HDA_INPUT_BEEP_MODE}; CONFIG_SND_HDA_INPUT_BEEP_MODE};
#endif #endif
static bool dmic_detect = IS_ENABLED(CONFIG_SND_HDA_INTEL_DETECT_DMIC);
module_param_array(index, int, NULL, 0444); module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
...@@ -159,6 +161,8 @@ module_param_array(beep_mode, bool, NULL, 0444); ...@@ -159,6 +161,8 @@ module_param_array(beep_mode, bool, NULL, 0444);
MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode "
"(0=off, 1=on) (default=1)."); "(0=off, 1=on) (default=1).");
#endif #endif
module_param(dmic_detect, bool, 0444);
MODULE_PARM_DESC(dmic_detect, "DMIC detect on SKL+ platforms");
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int param_set_xint(const char *val, const struct kernel_param *kp); static int param_set_xint(const char *val, const struct kernel_param *kp);
...@@ -1684,7 +1688,6 @@ static int default_bdl_pos_adj(struct azx *chip) ...@@ -1684,7 +1688,6 @@ static int default_bdl_pos_adj(struct azx *chip)
/* /*
* constructor * constructor
*/ */
static const struct hdac_io_ops pci_hda_io_ops;
static const struct hda_controller_ops pci_hda_ops; static const struct hda_controller_ops pci_hda_ops;
static int azx_create(struct snd_card *card, struct pci_dev *pci, static int azx_create(struct snd_card *card, struct pci_dev *pci,
...@@ -1744,13 +1747,17 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, ...@@ -1744,13 +1747,17 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
else else
chip->bdl_pos_adj = bdl_pos_adj[dev]; chip->bdl_pos_adj = bdl_pos_adj[dev];
err = azx_bus_init(chip, model[dev], &pci_hda_io_ops); err = azx_bus_init(chip, model[dev]);
if (err < 0) { if (err < 0) {
kfree(hda); kfree(hda);
pci_disable_device(pci); pci_disable_device(pci);
return err; return err;
} }
/* use the non-cached pages in non-snoop mode */
if (!azx_snoop(chip))
azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_UC;
/* Workaround for a communication error on CFL (bko#199007) and CNL */ /* Workaround for a communication error on CFL (bko#199007) and CNL */
if (IS_CFL(pci) || IS_CNL(pci)) if (IS_CFL(pci) || IS_CNL(pci))
azx_bus(chip)->polling_mode = 1; azx_bus(chip)->polling_mode = 1;
...@@ -1985,41 +1992,6 @@ static void azx_firmware_cb(const struct firmware *fw, void *context) ...@@ -1985,41 +1992,6 @@ static void azx_firmware_cb(const struct firmware *fw, void *context)
} }
#endif #endif
/*
* HDA controller ops.
*/
/* PCI register access. */
static void pci_azx_writel(u32 value, u32 __iomem *addr)
{
writel(value, addr);
}
static u32 pci_azx_readl(u32 __iomem *addr)
{
return readl(addr);
}
static void pci_azx_writew(u16 value, u16 __iomem *addr)
{
writew(value, addr);
}
static u16 pci_azx_readw(u16 __iomem *addr)
{
return readw(addr);
}
static void pci_azx_writeb(u8 value, u8 __iomem *addr)
{
writeb(value, addr);
}
static u8 pci_azx_readb(u8 __iomem *addr)
{
return readb(addr);
}
static int disable_msi_reset_irq(struct azx *chip) static int disable_msi_reset_irq(struct azx *chip)
{ {
struct hdac_bus *bus = azx_bus(chip); struct hdac_bus *bus = azx_bus(chip);
...@@ -2036,24 +2008,6 @@ static int disable_msi_reset_irq(struct azx *chip) ...@@ -2036,24 +2008,6 @@ static int disable_msi_reset_irq(struct azx *chip)
return 0; return 0;
} }
/* DMA page allocation helpers. */
static int dma_alloc_pages(struct hdac_bus *bus,
int type,
size_t size,
struct snd_dma_buffer *buf)
{
struct azx *chip = bus_to_azx(bus);
if (!azx_snoop(chip) && type == SNDRV_DMA_TYPE_DEV)
type = SNDRV_DMA_TYPE_DEV_UC;
return snd_dma_alloc_pages(type, bus->dev, size, buf);
}
static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf)
{
snd_dma_free_pages(buf);
}
static void pcm_mmap_prepare(struct snd_pcm_substream *substream, static void pcm_mmap_prepare(struct snd_pcm_substream *substream,
struct vm_area_struct *area) struct vm_area_struct *area)
{ {
...@@ -2065,23 +2019,31 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream, ...@@ -2065,23 +2019,31 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream,
#endif #endif
} }
static const struct hdac_io_ops pci_hda_io_ops = {
.reg_writel = pci_azx_writel,
.reg_readl = pci_azx_readl,
.reg_writew = pci_azx_writew,
.reg_readw = pci_azx_readw,
.reg_writeb = pci_azx_writeb,
.reg_readb = pci_azx_readb,
.dma_alloc_pages = dma_alloc_pages,
.dma_free_pages = dma_free_pages,
};
static const struct hda_controller_ops pci_hda_ops = { static const struct hda_controller_ops pci_hda_ops = {
.disable_msi_reset_irq = disable_msi_reset_irq, .disable_msi_reset_irq = disable_msi_reset_irq,
.pcm_mmap_prepare = pcm_mmap_prepare, .pcm_mmap_prepare = pcm_mmap_prepare,
.position_check = azx_position_check, .position_check = azx_position_check,
}; };
static int azx_check_dmic(struct pci_dev *pci, struct azx *chip)
{
struct nhlt_acpi_table *nhlt;
int ret = 0;
if (chip->driver_type == AZX_DRIVER_SKL &&
pci->class != 0x040300) {
nhlt = intel_nhlt_init(&pci->dev);
if (nhlt) {
if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt)) {
ret = -ENODEV;
dev_info(&pci->dev, "Digital mics found on Skylake+ platform, aborting probe\n");
}
intel_nhlt_free(nhlt);
}
}
return ret;
}
static int azx_probe(struct pci_dev *pci, static int azx_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id) const struct pci_device_id *pci_id)
{ {
...@@ -2112,6 +2074,17 @@ static int azx_probe(struct pci_dev *pci, ...@@ -2112,6 +2074,17 @@ static int azx_probe(struct pci_dev *pci,
card->private_data = chip; card->private_data = chip;
hda = container_of(chip, struct hda_intel, chip); hda = container_of(chip, struct hda_intel, chip);
/*
* stop probe if digital microphones detected on Skylake+ platform
* with the DSP enabled. This is an opt-in behavior defined at build
* time or at run-time with a module parameter
*/
if (dmic_detect) {
err = azx_check_dmic(pci, chip);
if (err < 0)
goto out_free;
}
pci_set_drvdata(pci, card); pci_set_drvdata(pci, card);
err = register_vga_switcheroo(chip); err = register_vga_switcheroo(chip);
......
...@@ -75,88 +75,6 @@ MODULE_PARM_DESC(power_save, ...@@ -75,88 +75,6 @@ MODULE_PARM_DESC(power_save,
#define power_save 0 #define power_save 0
#endif #endif
/*
* DMA page allocation ops.
*/
static int dma_alloc_pages(struct hdac_bus *bus, int type, size_t size,
struct snd_dma_buffer *buf)
{
return snd_dma_alloc_pages(type, bus->dev, size, buf);
}
static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf)
{
snd_dma_free_pages(buf);
}
/*
* Register access ops. Tegra HDA register access is DWORD only.
*/
static void hda_tegra_writel(u32 value, u32 __iomem *addr)
{
writel(value, addr);
}
static u32 hda_tegra_readl(u32 __iomem *addr)
{
return readl(addr);
}
static void hda_tegra_writew(u16 value, u16 __iomem *addr)
{
unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3);
u32 v;
v = readl(dword_addr);
v &= ~(0xffff << shift);
v |= value << shift;
writel(v, dword_addr);
}
static u16 hda_tegra_readw(u16 __iomem *addr)
{
unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3);
u32 v;
v = readl(dword_addr);
return (v >> shift) & 0xffff;
}
static void hda_tegra_writeb(u8 value, u8 __iomem *addr)
{
unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3);
u32 v;
v = readl(dword_addr);
v &= ~(0xff << shift);
v |= value << shift;
writel(v, dword_addr);
}
static u8 hda_tegra_readb(u8 __iomem *addr)
{
unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3);
u32 v;
v = readl(dword_addr);
return (v >> shift) & 0xff;
}
static const struct hdac_io_ops hda_tegra_io_ops = {
.reg_writel = hda_tegra_writel,
.reg_readl = hda_tegra_readl,
.reg_writew = hda_tegra_writew,
.reg_readw = hda_tegra_readw,
.reg_writeb = hda_tegra_writeb,
.reg_readb = hda_tegra_readb,
.dma_alloc_pages = dma_alloc_pages,
.dma_free_pages = dma_free_pages,
};
static const struct hda_controller_ops hda_tegra_ops; /* nothing special */ static const struct hda_controller_ops hda_tegra_ops; /* nothing special */
static void hda_tegra_init(struct hda_tegra *hda) static void hda_tegra_init(struct hda_tegra *hda)
...@@ -475,7 +393,7 @@ static int hda_tegra_create(struct snd_card *card, ...@@ -475,7 +393,7 @@ static int hda_tegra_create(struct snd_card *card,
INIT_WORK(&hda->probe_work, hda_tegra_probe_work); INIT_WORK(&hda->probe_work, hda_tegra_probe_work);
err = azx_bus_init(chip, NULL, &hda_tegra_io_ops); err = azx_bus_init(chip, NULL);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -51,7 +51,6 @@ source "sound/soc/dwc/Kconfig" ...@@ -51,7 +51,6 @@ source "sound/soc/dwc/Kconfig"
source "sound/soc/fsl/Kconfig" source "sound/soc/fsl/Kconfig"
source "sound/soc/hisilicon/Kconfig" source "sound/soc/hisilicon/Kconfig"
source "sound/soc/jz4740/Kconfig" source "sound/soc/jz4740/Kconfig"
source "sound/soc/nuc900/Kconfig"
source "sound/soc/kirkwood/Kconfig" source "sound/soc/kirkwood/Kconfig"
source "sound/soc/img/Kconfig" source "sound/soc/img/Kconfig"
source "sound/soc/intel/Kconfig" source "sound/soc/intel/Kconfig"
......
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o soc-component.o
snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o
snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o
...@@ -39,7 +39,6 @@ obj-$(CONFIG_SND_SOC) += intel/ ...@@ -39,7 +39,6 @@ obj-$(CONFIG_SND_SOC) += intel/
obj-$(CONFIG_SND_SOC) += mediatek/ obj-$(CONFIG_SND_SOC) += mediatek/
obj-$(CONFIG_SND_SOC) += meson/ obj-$(CONFIG_SND_SOC) += meson/
obj-$(CONFIG_SND_SOC) += mxs/ obj-$(CONFIG_SND_SOC) += mxs/
obj-$(CONFIG_SND_SOC) += nuc900/
obj-$(CONFIG_SND_SOC) += kirkwood/ obj-$(CONFIG_SND_SOC) += kirkwood/
obj-$(CONFIG_SND_SOC) += pxa/ obj-$(CONFIG_SND_SOC) += pxa/
obj-$(CONFIG_SND_SOC) += qcom/ obj-$(CONFIG_SND_SOC) += qcom/
......
...@@ -1251,8 +1251,7 @@ static int acp_audio_probe(struct platform_device *pdev) ...@@ -1251,8 +1251,7 @@ static int acp_audio_probe(struct platform_device *pdev)
if (!audio_drv_data) if (!audio_drv_data)
return -ENOMEM; return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); audio_drv_data->acp_mmio = devm_platform_ioremap_resource(pdev, 0);
audio_drv_data->acp_mmio = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(audio_drv_data->acp_mmio)) if (IS_ERR(audio_drv_data->acp_mmio))
return PTR_ERR(audio_drv_data->acp_mmio); return PTR_ERR(audio_drv_data->acp_mmio);
......
...@@ -12,25 +12,31 @@ if SND_ATMEL_SOC ...@@ -12,25 +12,31 @@ if SND_ATMEL_SOC
config SND_ATMEL_SOC_PDC config SND_ATMEL_SOC_PDC
tristate tristate
depends on HAS_DMA depends on HAS_DMA
default m if SND_ATMEL_SOC_SSC_PDC=m && SND_ATMEL_SOC_SSC=m
default y if SND_ATMEL_SOC_SSC_PDC=y || (SND_ATMEL_SOC_SSC_PDC=m && SND_ATMEL_SOC_SSC=y)
config SND_ATMEL_SOC_SSC_PDC
tristate
config SND_ATMEL_SOC_DMA config SND_ATMEL_SOC_DMA
tristate tristate
select SND_SOC_GENERIC_DMAENGINE_PCM select SND_SOC_GENERIC_DMAENGINE_PCM
default m if SND_ATMEL_SOC_SSC_DMA=m && SND_ATMEL_SOC_SSC=m
default y if SND_ATMEL_SOC_SSC_DMA=y || (SND_ATMEL_SOC_SSC_DMA=m && SND_ATMEL_SOC_SSC=y)
config SND_ATMEL_SOC_SSC_DMA
tristate
config SND_ATMEL_SOC_SSC config SND_ATMEL_SOC_SSC
tristate tristate
default y if SND_ATMEL_SOC_SSC_DMA=y || SND_ATMEL_SOC_SSC_PDC=y
default m if SND_ATMEL_SOC_SSC_DMA=m || SND_ATMEL_SOC_SSC_PDC=m config SND_ATMEL_SOC_SSC_PDC
tristate "SoC PCM DAI support for AT91 SSC controller using PDC"
depends on ATMEL_SSC
select SND_ATMEL_SOC_PDC
select SND_ATMEL_SOC_SSC
help
Say Y or M if you want to add support for Atmel SSC interface
in PDC mode configured using audio-graph-card in device-tree.
config SND_ATMEL_SOC_SSC_DMA
tristate "SoC PCM DAI support for AT91 SSC controller using DMA"
depends on ATMEL_SSC
select SND_ATMEL_SOC_DMA
select SND_ATMEL_SOC_SSC
help
Say Y or M if you want to add support for Atmel SSC interface
in DMA mode configured using audio-graph-card in device-tree.
config SND_AT91_SOC_SAM9G20_WM8731 config SND_AT91_SOC_SAM9G20_WM8731
tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board" tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
......
...@@ -571,11 +571,8 @@ static int atmel_classd_probe(struct platform_device *pdev) ...@@ -571,11 +571,8 @@ static int atmel_classd_probe(struct platform_device *pdev)
dd->pdata = pdata; dd->pdata = pdata;
dd->irq = platform_get_irq(pdev, 0); dd->irq = platform_get_irq(pdev, 0);
if (dd->irq < 0) { if (dd->irq < 0)
ret = dd->irq; return dd->irq;
dev_err(dev, "failed to could not get irq: %d\n", ret);
return ret;
}
dd->pclk = devm_clk_get(dev, "pclk"); dd->pclk = devm_clk_get(dev, "pclk");
if (IS_ERR(dd->pclk)) { if (IS_ERR(dd->pclk)) {
......
...@@ -612,11 +612,8 @@ static int atmel_pdmic_probe(struct platform_device *pdev) ...@@ -612,11 +612,8 @@ static int atmel_pdmic_probe(struct platform_device *pdev)
dd->dev = dev; dd->dev = dev;
dd->irq = platform_get_irq(pdev, 0); dd->irq = platform_get_irq(pdev, 0);
if (dd->irq < 0) { if (dd->irq < 0)
ret = dd->irq; return dd->irq;
dev_err(dev, "failed to get irq: %d\n", ret);
return ret;
}
dd->pclk = devm_clk_get(dev, "pclk"); dd->pclk = devm_clk_get(dev, "pclk");
if (IS_ERR(dd->pclk)) { if (IS_ERR(dd->pclk)) {
......
...@@ -471,7 +471,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, ...@@ -471,7 +471,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
int dir, channels, bits; int dir, channels, bits;
u32 tfmr, rfmr, tcmr, rcmr; u32 tfmr, rfmr, tcmr, rcmr;
int ret; int ret;
int fslen, fslen_ext; int fslen, fslen_ext, fs_osync, fs_edge;
u32 cmr_div; u32 cmr_div;
u32 tcmr_period; u32 tcmr_period;
u32 rcmr_period; u32 rcmr_period;
...@@ -558,226 +558,45 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, ...@@ -558,226 +558,45 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
/* /*
* Compute SSC register settings. * Compute SSC register settings.
*/ */
switch (ssc_p->daifmt
& (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: fslen_ext = (bits - 1) / 16;
/* fslen = (bits - 1) % 16;
* I2S format, SSC provides BCLK and LRC clocks.
*
* The SSC transmit and receive clocks are generated
* from the MCK divider, and the BCLK signal
* is output on the SSC TK line.
*/
if (bits > 16 && !ssc->pdata->has_fslen_ext) { switch (ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) {
dev_err(dai->dev,
"sample size %d is too large for SSC device\n",
bits);
return -EINVAL;
}
fslen_ext = (bits - 1) / 16; case SND_SOC_DAIFMT_LEFT_J:
fslen = (bits - 1) % 16; fs_osync = SSC_FSOS_POSITIVE;
fs_edge = SSC_START_RISING_RF;
rcmr = SSC_BF(RCMR_PERIOD, rcmr_period)
| SSC_BF(RCMR_STTDLY, START_DELAY) rcmr = SSC_BF(RCMR_STTDLY, 0);
| SSC_BF(RCMR_START, SSC_START_FALLING_RF) tcmr = SSC_BF(TCMR_STTDLY, 0);
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext)
| SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
| SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
| SSC_BF(RFMR_FSLEN, fslen)
| SSC_BF(RFMR_DATNB, (channels - 1))
| SSC_BIT(RFMR_MSBF)
| SSC_BF(RFMR_LOOP, 0)
| SSC_BF(RFMR_DATLEN, (bits - 1));
tcmr = SSC_BF(TCMR_PERIOD, tcmr_period)
| SSC_BF(TCMR_STTDLY, START_DELAY)
| SSC_BF(TCMR_START, SSC_START_FALLING_RF)
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
| SSC_BF(TCMR_CKS, SSC_CKS_DIV);
tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext)
| SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
| SSC_BF(TFMR_FSDEN, 0)
| SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
| SSC_BF(TFMR_FSLEN, fslen)
| SSC_BF(TFMR_DATNB, (channels - 1))
| SSC_BIT(TFMR_MSBF)
| SSC_BF(TFMR_DATDEF, 0)
| SSC_BF(TFMR_DATLEN, (bits - 1));
break;
case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
/* I2S format, CODEC supplies BCLK and LRC clocks. */
rcmr = SSC_BF(RCMR_PERIOD, 0)
| SSC_BF(RCMR_STTDLY, START_DELAY)
| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
| SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ?
SSC_CKS_PIN : SSC_CKS_CLOCK);
rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
| SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
| SSC_BF(RFMR_FSLEN, 0)
| SSC_BF(RFMR_DATNB, (channels - 1))
| SSC_BIT(RFMR_MSBF)
| SSC_BF(RFMR_LOOP, 0)
| SSC_BF(RFMR_DATLEN, (bits - 1));
tcmr = SSC_BF(TCMR_PERIOD, 0)
| SSC_BF(TCMR_STTDLY, START_DELAY)
| SSC_BF(TCMR_START, SSC_START_FALLING_RF)
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
| SSC_BF(TCMR_CKO, SSC_CKO_NONE)
| SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ?
SSC_CKS_CLOCK : SSC_CKS_PIN);
tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
| SSC_BF(TFMR_FSDEN, 0)
| SSC_BF(TFMR_FSOS, SSC_FSOS_NONE)
| SSC_BF(TFMR_FSLEN, 0)
| SSC_BF(TFMR_DATNB, (channels - 1))
| SSC_BIT(TFMR_MSBF)
| SSC_BF(TFMR_DATDEF, 0)
| SSC_BF(TFMR_DATLEN, (bits - 1));
break; break;
case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFS: case SND_SOC_DAIFMT_I2S:
/* I2S format, CODEC supplies BCLK, SSC supplies LRCLK. */ fs_osync = SSC_FSOS_NEGATIVE;
if (bits > 16 && !ssc->pdata->has_fslen_ext) { fs_edge = SSC_START_FALLING_RF;
dev_err(dai->dev,
"sample size %d is too large for SSC device\n",
bits);
return -EINVAL;
}
fslen_ext = (bits - 1) / 16; rcmr = SSC_BF(RCMR_STTDLY, 1);
fslen = (bits - 1) % 16; tcmr = SSC_BF(TCMR_STTDLY, 1);
rcmr = SSC_BF(RCMR_PERIOD, rcmr_period)
| SSC_BF(RCMR_STTDLY, START_DELAY)
| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
| SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ?
SSC_CKS_PIN : SSC_CKS_CLOCK);
rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext)
| SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
| SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
| SSC_BF(RFMR_FSLEN, fslen)
| SSC_BF(RFMR_DATNB, (channels - 1))
| SSC_BIT(RFMR_MSBF)
| SSC_BF(RFMR_LOOP, 0)
| SSC_BF(RFMR_DATLEN, (bits - 1));
tcmr = SSC_BF(TCMR_PERIOD, tcmr_period)
| SSC_BF(TCMR_STTDLY, START_DELAY)
| SSC_BF(TCMR_START, SSC_START_FALLING_RF)
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
| SSC_BF(TCMR_CKO, SSC_CKO_NONE)
| SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ?
SSC_CKS_CLOCK : SSC_CKS_PIN);
tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext)
| SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_NEGATIVE)
| SSC_BF(TFMR_FSDEN, 0)
| SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
| SSC_BF(TFMR_FSLEN, fslen)
| SSC_BF(TFMR_DATNB, (channels - 1))
| SSC_BIT(TFMR_MSBF)
| SSC_BF(TFMR_DATDEF, 0)
| SSC_BF(TFMR_DATLEN, (bits - 1));
break;
case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
/*
* DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
*
* The SSC transmit and receive clocks are generated from the
* MCK divider, and the BCLK signal is output
* on the SSC TK line.
*/
rcmr = SSC_BF(RCMR_PERIOD, rcmr_period)
| SSC_BF(RCMR_STTDLY, 1)
| SSC_BF(RCMR_START, SSC_START_RISING_RF)
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
| SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE)
| SSC_BF(RFMR_FSLEN, 0)
| SSC_BF(RFMR_DATNB, (channels - 1))
| SSC_BIT(RFMR_MSBF)
| SSC_BF(RFMR_LOOP, 0)
| SSC_BF(RFMR_DATLEN, (bits - 1));
tcmr = SSC_BF(TCMR_PERIOD, tcmr_period)
| SSC_BF(TCMR_STTDLY, 1)
| SSC_BF(TCMR_START, SSC_START_RISING_RF)
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
| SSC_BF(TCMR_CKS, SSC_CKS_DIV);
tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
| SSC_BF(TFMR_FSDEN, 0)
| SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE)
| SSC_BF(TFMR_FSLEN, 0)
| SSC_BF(TFMR_DATNB, (channels - 1))
| SSC_BIT(TFMR_MSBF)
| SSC_BF(TFMR_DATDEF, 0)
| SSC_BF(TFMR_DATLEN, (bits - 1));
break; break;
case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: case SND_SOC_DAIFMT_DSP_A:
/* /*
* DSP/PCM Mode A format, CODEC supplies BCLK and LRC clocks. * DSP/PCM Mode A format
* *
* Data is transferred on first BCLK after LRC pulse rising * Data is transferred on first BCLK after LRC pulse rising
* edge.If stereo, the right channel data is contiguous with * edge.If stereo, the right channel data is contiguous with
* the left channel data. * the left channel data.
*/ */
rcmr = SSC_BF(RCMR_PERIOD, 0) fs_osync = SSC_FSOS_POSITIVE;
| SSC_BF(RCMR_STTDLY, START_DELAY) fs_edge = SSC_START_RISING_RF;
| SSC_BF(RCMR_START, SSC_START_RISING_RF) fslen = fslen_ext = 0;
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
| SSC_BF(RCMR_CKO, SSC_CKO_NONE) rcmr = SSC_BF(RCMR_STTDLY, 1);
| SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? tcmr = SSC_BF(TCMR_STTDLY, 1);
SSC_CKS_PIN : SSC_CKS_CLOCK);
rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
| SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
| SSC_BF(RFMR_FSLEN, 0)
| SSC_BF(RFMR_DATNB, (channels - 1))
| SSC_BIT(RFMR_MSBF)
| SSC_BF(RFMR_LOOP, 0)
| SSC_BF(RFMR_DATLEN, (bits - 1));
tcmr = SSC_BF(TCMR_PERIOD, 0)
| SSC_BF(TCMR_STTDLY, START_DELAY)
| SSC_BF(TCMR_START, SSC_START_RISING_RF)
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
| SSC_BF(TCMR_CKO, SSC_CKO_NONE)
| SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ?
SSC_CKS_CLOCK : SSC_CKS_PIN);
tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
| SSC_BF(TFMR_FSDEN, 0)
| SSC_BF(TFMR_FSOS, SSC_FSOS_NONE)
| SSC_BF(TFMR_FSLEN, 0)
| SSC_BF(TFMR_DATNB, (channels - 1))
| SSC_BIT(TFMR_MSBF)
| SSC_BF(TFMR_DATDEF, 0)
| SSC_BF(TFMR_DATLEN, (bits - 1));
break; break;
default: default:
...@@ -785,6 +604,70 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, ...@@ -785,6 +604,70 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
ssc_p->daifmt); ssc_p->daifmt);
return -EINVAL; return -EINVAL;
} }
if (!atmel_ssc_cfs(ssc_p)) {
fslen = fslen_ext = 0;
rcmr_period = tcmr_period = 0;
fs_osync = SSC_FSOS_NONE;
}
rcmr |= SSC_BF(RCMR_START, fs_edge);
tcmr |= SSC_BF(TCMR_START, fs_edge);
if (atmel_ssc_cbs(ssc_p)) {
/*
* SSC provides BCLK
*
* The SSC transmit and receive clocks are generated from the
* MCK divider, and the BCLK signal is output
* on the SSC TK line.
*/
rcmr |= SSC_BF(RCMR_CKS, SSC_CKS_DIV)
| SSC_BF(RCMR_CKO, SSC_CKO_NONE);
tcmr |= SSC_BF(TCMR_CKS, SSC_CKS_DIV)
| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS);
} else {
rcmr |= SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ?
SSC_CKS_PIN : SSC_CKS_CLOCK)
| SSC_BF(RCMR_CKO, SSC_CKO_NONE);
tcmr |= SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ?
SSC_CKS_CLOCK : SSC_CKS_PIN)
| SSC_BF(TCMR_CKO, SSC_CKO_NONE);
}
rcmr |= SSC_BF(RCMR_PERIOD, rcmr_period)
| SSC_BF(RCMR_CKI, SSC_CKI_RISING);
tcmr |= SSC_BF(TCMR_PERIOD, tcmr_period)
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING);
rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext)
| SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
| SSC_BF(RFMR_FSOS, fs_osync)
| SSC_BF(RFMR_FSLEN, fslen)
| SSC_BF(RFMR_DATNB, (channels - 1))
| SSC_BIT(RFMR_MSBF)
| SSC_BF(RFMR_LOOP, 0)
| SSC_BF(RFMR_DATLEN, (bits - 1));
tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext)
| SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
| SSC_BF(TFMR_FSDEN, 0)
| SSC_BF(TFMR_FSOS, fs_osync)
| SSC_BF(TFMR_FSLEN, fslen)
| SSC_BF(TFMR_DATNB, (channels - 1))
| SSC_BIT(TFMR_MSBF)
| SSC_BF(TFMR_DATDEF, 0)
| SSC_BF(TFMR_DATLEN, (bits - 1));
if (fslen_ext && !ssc->pdata->has_fslen_ext) {
dev_err(dai->dev, "sample size %d is too large for SSC device\n",
bits);
return -EINVAL;
}
pr_debug("atmel_ssc_hw_params: " pr_debug("atmel_ssc_hw_params: "
"RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
rcmr, rfmr, tcmr, tfmr); rcmr, rfmr, tcmr, tfmr);
......
...@@ -392,11 +392,11 @@ static int mchp_i2s_mcc_clk_get_rate_diff(struct clk *clk, ...@@ -392,11 +392,11 @@ static int mchp_i2s_mcc_clk_get_rate_diff(struct clk *clk,
} }
static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev, static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev,
unsigned int bclk, unsigned int *mra) unsigned int bclk, unsigned int *mra,
unsigned long *best_rate)
{ {
unsigned long clk_rate; unsigned long clk_rate;
unsigned long lcm_rate; unsigned long lcm_rate;
unsigned long best_rate = 0;
unsigned long best_diff_rate = ~0; unsigned long best_diff_rate = ~0;
unsigned int sysclk; unsigned int sysclk;
struct clk *best_clk = NULL; struct clk *best_clk = NULL;
...@@ -423,7 +423,7 @@ static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev, ...@@ -423,7 +423,7 @@ static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev,
(clk_rate == bclk || clk_rate / (bclk * 2) <= GENMASK(5, 0)); (clk_rate == bclk || clk_rate / (bclk * 2) <= GENMASK(5, 0));
clk_rate += lcm_rate) { clk_rate += lcm_rate) {
ret = mchp_i2s_mcc_clk_get_rate_diff(dev->gclk, clk_rate, ret = mchp_i2s_mcc_clk_get_rate_diff(dev->gclk, clk_rate,
&best_clk, &best_rate, &best_clk, best_rate,
&best_diff_rate); &best_diff_rate);
if (ret) { if (ret) {
dev_err(dev->dev, "gclk error for rate %lu: %d", dev_err(dev->dev, "gclk error for rate %lu: %d",
...@@ -437,7 +437,7 @@ static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev, ...@@ -437,7 +437,7 @@ static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev,
} }
ret = mchp_i2s_mcc_clk_get_rate_diff(dev->pclk, clk_rate, ret = mchp_i2s_mcc_clk_get_rate_diff(dev->pclk, clk_rate,
&best_clk, &best_rate, &best_clk, best_rate,
&best_diff_rate); &best_diff_rate);
if (ret) { if (ret) {
dev_err(dev->dev, "pclk error for rate %lu: %d", dev_err(dev->dev, "pclk error for rate %lu: %d",
...@@ -459,33 +459,17 @@ static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev, ...@@ -459,33 +459,17 @@ static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev,
dev_dbg(dev->dev, "source CLK is %s with rate %lu, diff %lu\n", dev_dbg(dev->dev, "source CLK is %s with rate %lu, diff %lu\n",
best_clk == dev->pclk ? "pclk" : "gclk", best_clk == dev->pclk ? "pclk" : "gclk",
best_rate, best_diff_rate); *best_rate, best_diff_rate);
/* set the rate */
ret = clk_set_rate(best_clk, best_rate);
if (ret) {
dev_err(dev->dev, "unable to set rate %lu to %s: %d\n",
best_rate, best_clk == dev->pclk ? "PCLK" : "GCLK",
ret);
return ret;
}
/* Configure divisors */ /* Configure divisors */
if (dev->sysclk) if (dev->sysclk)
*mra |= MCHP_I2SMCC_MRA_IMCKDIV(best_rate / (2 * sysclk)); *mra |= MCHP_I2SMCC_MRA_IMCKDIV(*best_rate / (2 * sysclk));
*mra |= MCHP_I2SMCC_MRA_ISCKDIV(best_rate / (2 * bclk)); *mra |= MCHP_I2SMCC_MRA_ISCKDIV(*best_rate / (2 * bclk));
if (best_clk == dev->gclk) { if (best_clk == dev->gclk)
*mra |= MCHP_I2SMCC_MRA_SRCCLK_GCLK; *mra |= MCHP_I2SMCC_MRA_SRCCLK_GCLK;
ret = clk_prepare(dev->gclk); else
if (ret < 0)
dev_err(dev->dev, "unable to prepare GCLK: %d\n", ret);
else
dev->gclk_use = 1;
} else {
*mra |= MCHP_I2SMCC_MRA_SRCCLK_PCLK; *mra |= MCHP_I2SMCC_MRA_SRCCLK_PCLK;
dev->gclk_use = 0;
}
return 0; return 0;
} }
...@@ -502,6 +486,7 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream, ...@@ -502,6 +486,7 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
unsigned long rate = 0;
struct mchp_i2s_mcc_dev *dev = snd_soc_dai_get_drvdata(dai); struct mchp_i2s_mcc_dev *dev = snd_soc_dai_get_drvdata(dai);
u32 mra = 0; u32 mra = 0;
u32 mrb = 0; u32 mrb = 0;
...@@ -640,6 +625,17 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream, ...@@ -640,6 +625,17 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
if (set_divs) {
bclk_rate = frame_length * params_rate(params);
ret = mchp_i2s_mcc_config_divs(dev, bclk_rate, &mra,
&rate);
if (ret) {
dev_err(dev->dev,
"unable to configure the divisors: %d\n", ret);
return ret;
}
}
/* /*
* If we are already running, the wanted setup must be * If we are already running, the wanted setup must be
* the same with the one that's currently ongoing * the same with the one that's currently ongoing
...@@ -656,19 +652,27 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream, ...@@ -656,19 +652,27 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream,
return 0; return 0;
} }
/* Save the number of channels to know what interrupts to enable */ if (mra & MCHP_I2SMCC_MRA_SRCCLK_GCLK && !dev->gclk_use) {
dev->channels = channels; /* set the rate */
ret = clk_set_rate(dev->gclk, rate);
if (set_divs) {
bclk_rate = frame_length * params_rate(params);
ret = mchp_i2s_mcc_config_divs(dev, bclk_rate, &mra);
if (ret) { if (ret) {
dev_err(dev->dev, "unable to configure the divisors: %d\n", dev_err(dev->dev,
ret); "unable to set rate %lu to GCLK: %d\n",
rate, ret);
return ret;
}
ret = clk_prepare(dev->gclk);
if (ret < 0) {
dev_err(dev->dev, "unable to prepare GCLK: %d\n", ret);
return ret; return ret;
} }
dev->gclk_use = 1;
} }
/* Save the number of channels to know what interrupts to enable */
dev->channels = channels;
ret = regmap_write(dev->regmap, MCHP_I2SMCC_MRA, mra); ret = regmap_write(dev->regmap, MCHP_I2SMCC_MRA, mra);
if (ret < 0) { if (ret < 0) {
if (dev->gclk_use) { if (dev->gclk_use) {
......
...@@ -363,7 +363,7 @@ static const struct snd_soc_component_driver au1xpsc_ac97_component = { ...@@ -363,7 +363,7 @@ static const struct snd_soc_component_driver au1xpsc_ac97_component = {
static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
{ {
int ret; int ret;
struct resource *iores, *dmares; struct resource *dmares;
unsigned long sel; unsigned long sel;
struct au1xpsc_audio_data *wd; struct au1xpsc_audio_data *wd;
...@@ -374,8 +374,7 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) ...@@ -374,8 +374,7 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
mutex_init(&wd->lock); mutex_init(&wd->lock);
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); wd->mmio = devm_platform_ioremap_resource(pdev, 0);
wd->mmio = devm_ioremap_resource(&pdev->dev, iores);
if (IS_ERR(wd->mmio)) if (IS_ERR(wd->mmio))
return PTR_ERR(wd->mmio); return PTR_ERR(wd->mmio);
......
...@@ -291,7 +291,7 @@ static const struct snd_soc_component_driver au1xpsc_i2s_component = { ...@@ -291,7 +291,7 @@ static const struct snd_soc_component_driver au1xpsc_i2s_component = {
static int au1xpsc_i2s_drvprobe(struct platform_device *pdev) static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
{ {
struct resource *iores, *dmares; struct resource *dmares;
unsigned long sel; unsigned long sel;
struct au1xpsc_audio_data *wd; struct au1xpsc_audio_data *wd;
...@@ -300,8 +300,7 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev) ...@@ -300,8 +300,7 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
if (!wd) if (!wd)
return -ENOMEM; return -ENOMEM;
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); wd->mmio = devm_platform_ioremap_resource(pdev, 0);
wd->mmio = devm_ioremap_resource(&pdev->dev, iores);
if (IS_ERR(wd->mmio)) if (IS_ERR(wd->mmio))
return PTR_ERR(wd->mmio); return PTR_ERR(wd->mmio);
......
...@@ -828,7 +828,6 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) ...@@ -828,7 +828,6 @@ static int bcm2835_i2s_probe(struct platform_device *pdev)
{ {
struct bcm2835_i2s_dev *dev; struct bcm2835_i2s_dev *dev;
int ret; int ret;
struct resource *mem;
void __iomem *base; void __iomem *base;
const __be32 *addr; const __be32 *addr;
dma_addr_t dma_base; dma_addr_t dma_base;
...@@ -848,8 +847,7 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) ...@@ -848,8 +847,7 @@ static int bcm2835_i2s_probe(struct platform_device *pdev)
} }
/* Request ioarea */ /* Request ioarea */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_platform_ioremap_resource(pdev, 0);
base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(base)) if (IS_ERR(base))
return PTR_ERR(base); return PTR_ERR(base);
......
...@@ -639,7 +639,6 @@ static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -639,7 +639,6 @@ static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct cygnus_aio_port *aio; struct cygnus_aio_port *aio;
int ret = 0;
aio = cygnus_dai_get_dma_data(substream); aio = cygnus_dai_get_dma_data(substream);
dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum); dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum);
...@@ -647,7 +646,7 @@ static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -647,7 +646,7 @@ static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream,
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
runtime->dma_bytes = params_buffer_bytes(params); runtime->dma_bytes = params_buffer_bytes(params);
return ret; return 0;
} }
static int cygnus_pcm_hw_free(struct snd_pcm_substream *substream) static int cygnus_pcm_hw_free(struct snd_pcm_substream *substream)
...@@ -668,7 +667,6 @@ static int cygnus_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -668,7 +667,6 @@ static int cygnus_pcm_prepare(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct cygnus_aio_port *aio; struct cygnus_aio_port *aio;
unsigned long bufsize, periodsize; unsigned long bufsize, periodsize;
int ret = 0;
bool is_play; bool is_play;
u32 start; u32 start;
struct ringbuf_regs *p_rbuf = NULL; struct ringbuf_regs *p_rbuf = NULL;
...@@ -693,7 +691,7 @@ static int cygnus_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -693,7 +691,7 @@ static int cygnus_pcm_prepare(struct snd_pcm_substream *substream)
ringbuf_set_initial(aio->cygaud->audio, p_rbuf, is_play, start, ringbuf_set_initial(aio->cygaud->audio, p_rbuf, is_play, start,
periodsize, bufsize); periodsize, bufsize);
return ret; return 0;
} }
static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_pcm_substream *substream) static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_pcm_substream *substream)
......
...@@ -1342,11 +1342,8 @@ static int cygnus_ssp_probe(struct platform_device *pdev) ...@@ -1342,11 +1342,8 @@ static int cygnus_ssp_probe(struct platform_device *pdev)
} }
cygaud->irq_num = platform_get_irq(pdev, 0); cygaud->irq_num = platform_get_irq(pdev, 0);
if (cygaud->irq_num <= 0) { if (cygaud->irq_num <= 0)
dev_err(dev, "platform_get_irq failed\n"); return cygaud->irq_num;
err = cygaud->irq_num;
return err;
}
err = audio_clk_init(pdev, cygaud); err = audio_clk_init(pdev, cygaud);
if (err) { if (err) {
......
...@@ -362,7 +362,6 @@ static const struct snd_soc_component_driver ep93xx_ac97_component = { ...@@ -362,7 +362,6 @@ static const struct snd_soc_component_driver ep93xx_ac97_component = {
static int ep93xx_ac97_probe(struct platform_device *pdev) static int ep93xx_ac97_probe(struct platform_device *pdev)
{ {
struct ep93xx_ac97_info *info; struct ep93xx_ac97_info *info;
struct resource *res;
int irq; int irq;
int ret; int ret;
...@@ -370,8 +369,7 @@ static int ep93xx_ac97_probe(struct platform_device *pdev) ...@@ -370,8 +369,7 @@ static int ep93xx_ac97_probe(struct platform_device *pdev)
if (!info) if (!info)
return -ENOMEM; return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); info->regs = devm_platform_ioremap_resource(pdev, 0);
info->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(info->regs)) if (IS_ERR(info->regs))
return PTR_ERR(info->regs); return PTR_ERR(info->regs);
......
...@@ -430,15 +430,13 @@ static const struct snd_soc_component_driver ep93xx_i2s_component = { ...@@ -430,15 +430,13 @@ static const struct snd_soc_component_driver ep93xx_i2s_component = {
static int ep93xx_i2s_probe(struct platform_device *pdev) static int ep93xx_i2s_probe(struct platform_device *pdev)
{ {
struct ep93xx_i2s_info *info; struct ep93xx_i2s_info *info;
struct resource *res;
int err; int err;
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
return -ENOMEM; return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); info->regs = devm_platform_ioremap_resource(pdev, 0);
info->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(info->regs)) if (IS_ERR(info->regs))
return PTR_ERR(info->regs); return PTR_ERR(info->regs);
......
...@@ -529,10 +529,6 @@ static const struct snd_kcontrol_new pm860x_snd_controls[] = { ...@@ -529,10 +529,6 @@ static const struct snd_kcontrol_new pm860x_snd_controls[] = {
* DAPM Controls * DAPM Controls
*/ */
/* PCM Switch / PCM Interface */
static const struct snd_kcontrol_new pcm_switch_controls =
SOC_DAPM_SINGLE("Switch", PM860X_ADC_EN_2, 0, 1, 0);
/* AUX1 Switch */ /* AUX1 Switch */
static const struct snd_kcontrol_new aux1_switch_controls = static const struct snd_kcontrol_new aux1_switch_controls =
SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 4, 1, 0); SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 4, 1, 0);
...@@ -549,17 +545,6 @@ static const struct snd_kcontrol_new lepa_switch_controls = ...@@ -549,17 +545,6 @@ static const struct snd_kcontrol_new lepa_switch_controls =
static const struct snd_kcontrol_new repa_switch_controls = static const struct snd_kcontrol_new repa_switch_controls =
SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 1, 1, 0); SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 1, 1, 0);
/* PCM Mux / Mux7 */
static const char *aif1_text[] = {
"PCM L", "PCM R",
};
static SOC_ENUM_SINGLE_DECL(aif1_enum,
PM860X_PCM_IFACE_3, 6, aif1_text);
static const struct snd_kcontrol_new aif1_mux =
SOC_DAPM_ENUM("PCM Mux", aif1_enum);
/* I2S Mux / Mux9 */ /* I2S Mux / Mux9 */
static const char *i2s_din_text[] = { static const char *i2s_din_text[] = {
"DIN", "DIN1", "DIN", "DIN1",
......
...@@ -70,10 +70,12 @@ config SND_SOC_ALL_CODECS ...@@ -70,10 +70,12 @@ config SND_SOC_ALL_CODECS
select SND_SOC_CS43130 if I2C select SND_SOC_CS43130 if I2C
select SND_SOC_CS4341 if SND_SOC_I2C_AND_SPI select SND_SOC_CS4341 if SND_SOC_I2C_AND_SPI
select SND_SOC_CS4349 if I2C select SND_SOC_CS4349 if I2C
select SND_SOC_CS47L15 if MFD_CS47L15
select SND_SOC_CS47L24 if MFD_CS47L24 select SND_SOC_CS47L24 if MFD_CS47L24
select SND_SOC_CS47L35 if MFD_CS47L35 select SND_SOC_CS47L35 if MFD_CS47L35
select SND_SOC_CS47L85 if MFD_CS47L85 select SND_SOC_CS47L85 if MFD_CS47L85
select SND_SOC_CS47L90 if MFD_CS47L90 select SND_SOC_CS47L90 if MFD_CS47L90
select SND_SOC_CS47L92 if MFD_CS47L92
select SND_SOC_CS53L30 if I2C select SND_SOC_CS53L30 if I2C
select SND_SOC_CX20442 if TTY select SND_SOC_CX20442 if TTY
select SND_SOC_CX2072X if I2C select SND_SOC_CX2072X if I2C
...@@ -197,6 +199,7 @@ config SND_SOC_ALL_CODECS ...@@ -197,6 +199,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_TS3A227E if I2C select SND_SOC_TS3A227E if I2C
select SND_SOC_TWL4030 if TWL4030_CORE select SND_SOC_TWL4030 if TWL4030_CORE
select SND_SOC_TWL6040 if TWL6040_CORE select SND_SOC_TWL6040 if TWL6040_CORE
select SND_SOC_UDA1334 if GPIOLIB
select SND_SOC_UDA134X select SND_SOC_UDA134X
select SND_SOC_UDA1380 if I2C select SND_SOC_UDA1380 if I2C
select SND_SOC_WCD9335 if SLIMBUS select SND_SOC_WCD9335 if SLIMBUS
...@@ -581,6 +584,9 @@ config SND_SOC_CS4349 ...@@ -581,6 +584,9 @@ config SND_SOC_CS4349
tristate "Cirrus Logic CS4349 CODEC" tristate "Cirrus Logic CS4349 CODEC"
depends on I2C depends on I2C
config SND_SOC_CS47L15
tristate
config SND_SOC_CS47L24 config SND_SOC_CS47L24
tristate tristate
...@@ -593,6 +599,9 @@ config SND_SOC_CS47L85 ...@@ -593,6 +599,9 @@ config SND_SOC_CS47L85
config SND_SOC_CS47L90 config SND_SOC_CS47L90
tristate tristate
config SND_SOC_CS47L92
tristate
# Cirrus Logic Quad-Channel ADC # Cirrus Logic Quad-Channel ADC
config SND_SOC_CS53L30 config SND_SOC_CS53L30
tristate "Cirrus Logic CS53L30 CODEC" tristate "Cirrus Logic CS53L30 CODEC"
...@@ -722,12 +731,16 @@ config SND_SOC_LOCHNAGAR_SC ...@@ -722,12 +731,16 @@ config SND_SOC_LOCHNAGAR_SC
config SND_SOC_MADERA config SND_SOC_MADERA
tristate tristate
default y if SND_SOC_CS47L15=y
default y if SND_SOC_CS47L35=y default y if SND_SOC_CS47L35=y
default y if SND_SOC_CS47L85=y default y if SND_SOC_CS47L85=y
default y if SND_SOC_CS47L90=y default y if SND_SOC_CS47L90=y
default y if SND_SOC_CS47L92=y
default m if SND_SOC_CS47L15=m
default m if SND_SOC_CS47L35=m default m if SND_SOC_CS47L35=m
default m if SND_SOC_CS47L85=m default m if SND_SOC_CS47L85=m
default m if SND_SOC_CS47L90=m default m if SND_SOC_CS47L90=m
default m if SND_SOC_CS47L92=m
config SND_SOC_MAX98088 config SND_SOC_MAX98088
tristate "Maxim MAX98088/9 Low-Power, Stereo Audio Codec" tristate "Maxim MAX98088/9 Low-Power, Stereo Audio Codec"
...@@ -1195,6 +1208,14 @@ config SND_SOC_TWL4030 ...@@ -1195,6 +1208,14 @@ config SND_SOC_TWL4030
config SND_SOC_TWL6040 config SND_SOC_TWL6040
tristate tristate
config SND_SOC_UDA1334
tristate "NXP UDA1334 DAC"
depends on GPIOLIB
help
The UDA1334 is an NXP audio codec, supports the I2S-bus data format
and has basic features such as de-emphasis (at 44.1 kHz sampling
rate) and mute.
config SND_SOC_UDA134X config SND_SOC_UDA134X
tristate tristate
......
...@@ -64,10 +64,12 @@ snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o ...@@ -64,10 +64,12 @@ snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o
snd-soc-cs43130-objs := cs43130.o snd-soc-cs43130-objs := cs43130.o
snd-soc-cs4341-objs := cs4341.o snd-soc-cs4341-objs := cs4341.o
snd-soc-cs4349-objs := cs4349.o snd-soc-cs4349-objs := cs4349.o
snd-soc-cs47l15-objs := cs47l15.o
snd-soc-cs47l24-objs := cs47l24.o snd-soc-cs47l24-objs := cs47l24.o
snd-soc-cs47l35-objs := cs47l35.o snd-soc-cs47l35-objs := cs47l35.o
snd-soc-cs47l85-objs := cs47l85.o snd-soc-cs47l85-objs := cs47l85.o
snd-soc-cs47l90-objs := cs47l90.o snd-soc-cs47l90-objs := cs47l90.o
snd-soc-cs47l92-objs := cs47l92.o
snd-soc-cs53l30-objs := cs53l30.o snd-soc-cs53l30-objs := cs53l30.o
snd-soc-cx20442-objs := cx20442.o snd-soc-cx20442-objs := cx20442.o
snd-soc-cx2072x-objs := cx2072x.o snd-soc-cx2072x-objs := cx2072x.o
...@@ -210,6 +212,7 @@ snd-soc-tscs454-objs := tscs454.o ...@@ -210,6 +212,7 @@ snd-soc-tscs454-objs := tscs454.o
snd-soc-ts3a227e-objs := ts3a227e.o snd-soc-ts3a227e-objs := ts3a227e.o
snd-soc-twl4030-objs := twl4030.o snd-soc-twl4030-objs := twl4030.o
snd-soc-twl6040-objs := twl6040.o snd-soc-twl6040-objs := twl6040.o
snd-soc-uda1334-objs := uda1334.o
snd-soc-uda134x-objs := uda134x.o snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o snd-soc-uda1380-objs := uda1380.o
snd-soc-wcd9335-objs := wcd-clsh-v2.o wcd9335.o snd-soc-wcd9335-objs := wcd-clsh-v2.o wcd9335.o
...@@ -346,9 +349,11 @@ obj-$(CONFIG_SND_SOC_CS43130) += snd-soc-cs43130.o ...@@ -346,9 +349,11 @@ obj-$(CONFIG_SND_SOC_CS43130) += snd-soc-cs43130.o
obj-$(CONFIG_SND_SOC_CS4341) += snd-soc-cs4341.o obj-$(CONFIG_SND_SOC_CS4341) += snd-soc-cs4341.o
obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o
obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o
obj-$(CONFIG_SND_SOC_CS47L15) += snd-soc-cs47l15.o
obj-$(CONFIG_SND_SOC_CS47L35) += snd-soc-cs47l35.o obj-$(CONFIG_SND_SOC_CS47L35) += snd-soc-cs47l35.o
obj-$(CONFIG_SND_SOC_CS47L85) += snd-soc-cs47l85.o obj-$(CONFIG_SND_SOC_CS47L85) += snd-soc-cs47l85.o
obj-$(CONFIG_SND_SOC_CS47L90) += snd-soc-cs47l90.o obj-$(CONFIG_SND_SOC_CS47L90) += snd-soc-cs47l90.o
obj-$(CONFIG_SND_SOC_CS47L92) += snd-soc-cs47l92.o
obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o
obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
obj-$(CONFIG_SND_SOC_CX2072X) += snd-soc-cx2072x.o obj-$(CONFIG_SND_SOC_CX2072X) += snd-soc-cx2072x.o
...@@ -490,6 +495,7 @@ obj-$(CONFIG_SND_SOC_TSCS454) += snd-soc-tscs454.o ...@@ -490,6 +495,7 @@ obj-$(CONFIG_SND_SOC_TSCS454) += snd-soc-tscs454.o
obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o
obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
obj-$(CONFIG_SND_SOC_UDA1334) += snd-soc-uda1334.o
obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o
......
...@@ -413,15 +413,10 @@ static struct snd_soc_dai_driver ad193x_no_adc_dai = { ...@@ -413,15 +413,10 @@ static struct snd_soc_dai_driver ad193x_no_adc_dai = {
.ops = &ad193x_dai_ops, .ops = &ad193x_dai_ops,
}; };
struct ad193x_reg_default {
unsigned int reg;
unsigned int val;
};
/* codec register values to set after reset */ /* codec register values to set after reset */
static void ad193x_reg_default_init(struct ad193x_priv *ad193x) static void ad193x_reg_default_init(struct ad193x_priv *ad193x)
{ {
const struct ad193x_reg_default reg_init[] = { static const struct reg_sequence reg_init[] = {
{ 0, 0x99 }, /* PLL_CLK_CTRL0: pll input: mclki/xi 12.288Mhz */ { 0, 0x99 }, /* PLL_CLK_CTRL0: pll input: mclki/xi 12.288Mhz */
{ 1, 0x04 }, /* PLL_CLK_CTRL1: no on-chip Vref */ { 1, 0x04 }, /* PLL_CLK_CTRL1: no on-chip Vref */
{ 2, 0x40 }, /* DAC_CTRL0: TDM mode */ { 2, 0x40 }, /* DAC_CTRL0: TDM mode */
...@@ -437,21 +432,17 @@ static void ad193x_reg_default_init(struct ad193x_priv *ad193x) ...@@ -437,21 +432,17 @@ static void ad193x_reg_default_init(struct ad193x_priv *ad193x)
{ 12, 0x00 }, /* DAC_L4_VOL: no attenuation */ { 12, 0x00 }, /* DAC_L4_VOL: no attenuation */
{ 13, 0x00 }, /* DAC_R4_VOL: no attenuation */ { 13, 0x00 }, /* DAC_R4_VOL: no attenuation */
}; };
const struct ad193x_reg_default reg_adc_init[] = { static const struct reg_sequence reg_adc_init[] = {
{ 14, 0x03 }, /* ADC_CTRL0: high-pass filter enable */ { 14, 0x03 }, /* ADC_CTRL0: high-pass filter enable */
{ 15, 0x43 }, /* ADC_CTRL1: sata delay=1, adc aux mode */ { 15, 0x43 }, /* ADC_CTRL1: sata delay=1, adc aux mode */
{ 16, 0x00 }, /* ADC_CTRL2: reset */ { 16, 0x00 }, /* ADC_CTRL2: reset */
}; };
int i;
for (i = 0; i < ARRAY_SIZE(reg_init); i++) regmap_multi_reg_write(ad193x->regmap, reg_init, ARRAY_SIZE(reg_init));
regmap_write(ad193x->regmap, reg_init[i].reg, reg_init[i].val);
if (ad193x_has_adc(ad193x)) { if (ad193x_has_adc(ad193x)) {
for (i = 0; i < ARRAY_SIZE(reg_adc_init); i++) { regmap_multi_reg_write(ad193x->regmap, reg_adc_init,
regmap_write(ad193x->regmap, reg_adc_init[i].reg, ARRAY_SIZE(reg_adc_init));
reg_adc_init[i].val);
}
} }
} }
......
...@@ -334,7 +334,7 @@ static struct cs4271_clk_cfg cs4271_clk_tab[] = { ...@@ -334,7 +334,7 @@ static struct cs4271_clk_cfg cs4271_clk_tab[] = {
{0, CS4271_MODE1_MODE_4X, 256, CS4271_MODE1_DIV_2}, {0, CS4271_MODE1_MODE_4X, 256, CS4271_MODE1_DIV_2},
}; };
#define CS4171_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab) #define CS4271_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab)
static int cs4271_hw_params(struct snd_pcm_substream *substream, static int cs4271_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
...@@ -383,13 +383,13 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream, ...@@ -383,13 +383,13 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
val = CS4271_MODE1_MODE_4X; val = CS4271_MODE1_MODE_4X;
ratio = cs4271->mclk / cs4271->rate; ratio = cs4271->mclk / cs4271->rate;
for (i = 0; i < CS4171_NR_RATIOS; i++) for (i = 0; i < CS4271_NR_RATIOS; i++)
if ((cs4271_clk_tab[i].master == cs4271->master) && if ((cs4271_clk_tab[i].master == cs4271->master) &&
(cs4271_clk_tab[i].speed_mode == val) && (cs4271_clk_tab[i].speed_mode == val) &&
(cs4271_clk_tab[i].ratio == ratio)) (cs4271_clk_tab[i].ratio == ratio))
break; break;
if (i == CS4171_NR_RATIOS) { if (i == CS4271_NR_RATIOS) {
dev_err(component->dev, "Invalid sample rate\n"); dev_err(component->dev, "Invalid sample rate\n");
return -EINVAL; return -EINVAL;
} }
......
...@@ -199,14 +199,6 @@ static const struct soc_enum beep_bass_enum = ...@@ -199,14 +199,6 @@ static const struct soc_enum beep_bass_enum =
SOC_ENUM_SINGLE(CS42L56_BEEP_TONE_CFG, 1, SOC_ENUM_SINGLE(CS42L56_BEEP_TONE_CFG, 1,
ARRAY_SIZE(beep_bass_text), beep_bass_text); ARRAY_SIZE(beep_bass_text), beep_bass_text);
static const char * const adc_swap_text[] = {
"None", "A+B/2", "A-B/2", "Swap"
};
static const struct soc_enum adc_swap_enum =
SOC_ENUM_SINGLE(CS42L56_MISC_ADC_CTL, 3,
ARRAY_SIZE(adc_swap_text), adc_swap_text);
static const char * const pgaa_mux_text[] = { static const char * const pgaa_mux_text[] = {
"AIN1A", "AIN2A", "AIN3A"}; "AIN1A", "AIN2A", "AIN3A"};
......
...@@ -273,12 +273,6 @@ static SOC_ENUM_SINGLE_DECL(xsp_output_mux_enum, ...@@ -273,12 +273,6 @@ static SOC_ENUM_SINGLE_DECL(xsp_output_mux_enum,
CS42L73_MIXERCTL, 4, CS42L73_MIXERCTL, 4,
cs42l73_spo_mixer_text); cs42l73_spo_mixer_text);
static const struct snd_kcontrol_new vsp_output_mux =
SOC_DAPM_ENUM("Route", vsp_output_mux_enum);
static const struct snd_kcontrol_new xsp_output_mux =
SOC_DAPM_ENUM("Route", xsp_output_mux_enum);
static const struct snd_kcontrol_new hp_amp_ctl = static const struct snd_kcontrol_new hp_amp_ctl =
SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 0, 1, 1); SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 0, 1, 1);
......
...@@ -684,6 +684,8 @@ static int cs42xx8_runtime_suspend(struct device *dev) ...@@ -684,6 +684,8 @@ static int cs42xx8_runtime_suspend(struct device *dev)
#endif #endif
const struct dev_pm_ops cs42xx8_pm = { const struct dev_pm_ops cs42xx8_pm = {
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL) SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL)
}; };
EXPORT_SYMBOL_GPL(cs42xx8_pm); EXPORT_SYMBOL_GPL(cs42xx8_pm);
......
此差异已折叠。
...@@ -524,7 +524,7 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, ...@@ -524,7 +524,7 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK,
MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, 6, SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT,
0, NULL, 0), 0, NULL, 0),
SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0),
......
...@@ -2402,13 +2402,6 @@ static irqreturn_t cs47l90_adsp2_irq(int irq, void *data) ...@@ -2402,13 +2402,6 @@ static irqreturn_t cs47l90_adsp2_irq(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t cs47l90_dsp_bus_error(int irq, void *data)
{
struct wm_adsp *dsp = (struct wm_adsp *)data;
return wm_adsp2_bus_error(dsp);
}
static int cs47l90_component_probe(struct snd_soc_component *component) static int cs47l90_component_probe(struct snd_soc_component *component)
{ {
struct cs47l90 *cs47l90 = snd_soc_component_get_drvdata(component); struct cs47l90 *cs47l90 = snd_soc_component_get_drvdata(component);
...@@ -2558,7 +2551,7 @@ static int cs47l90_probe(struct platform_device *pdev) ...@@ -2558,7 +2551,7 @@ static int cs47l90_probe(struct platform_device *pdev)
if (ret == 0) { if (ret == 0) {
ret = madera_init_bus_error_irq(&cs47l90->core, i, ret = madera_init_bus_error_irq(&cs47l90->core, i,
cs47l90_dsp_bus_error); wm_adsp2_bus_error);
if (ret != 0) if (ret != 0)
wm_adsp2_remove(&cs47l90->core.adsp[i]); wm_adsp2_remove(&cs47l90->core.adsp[i]);
} }
......
此差异已折叠。
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
...@@ -33,6 +34,7 @@ static const unsigned int supported_mclk_lrck_ratios[] = { ...@@ -33,6 +34,7 @@ static const unsigned int supported_mclk_lrck_ratios[] = {
struct es8316_priv { struct es8316_priv {
struct mutex lock; struct mutex lock;
struct clk *mclk;
struct regmap *regmap; struct regmap *regmap;
struct snd_soc_component *component; struct snd_soc_component *component;
struct snd_soc_jack *jack; struct snd_soc_jack *jack;
...@@ -363,13 +365,21 @@ static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -363,13 +365,21 @@ static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai,
{ {
struct snd_soc_component *component = codec_dai->component; struct snd_soc_component *component = codec_dai->component;
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
int i; int i, ret;
int count = 0; int count = 0;
es8316->sysclk = freq; es8316->sysclk = freq;
if (freq == 0) if (freq == 0) {
es8316->sysclk_constraints.list = NULL;
es8316->sysclk_constraints.count = 0;
return 0; return 0;
}
ret = clk_set_rate(es8316->mclk, freq);
if (ret)
return ret;
/* Limit supported sample rates to ones that can be autodetected /* Limit supported sample rates to ones that can be autodetected
* by the codec running in slave mode. * by the codec running in slave mode.
...@@ -444,17 +454,10 @@ static int es8316_pcm_startup(struct snd_pcm_substream *substream, ...@@ -444,17 +454,10 @@ static int es8316_pcm_startup(struct snd_pcm_substream *substream,
struct snd_soc_component *component = dai->component; struct snd_soc_component *component = dai->component;
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
if (es8316->sysclk == 0) { if (es8316->sysclk_constraints.list)
dev_err(component->dev, "No sysclk provided\n"); snd_pcm_hw_constraint_list(substream->runtime, 0,
return -EINVAL; SNDRV_PCM_HW_PARAM_RATE,
} &es8316->sysclk_constraints);
/* The set of sample rates that can be supported depends on the
* MCLK supplied to the CODEC.
*/
snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&es8316->sysclk_constraints);
return 0; return 0;
} }
...@@ -466,11 +469,19 @@ static int es8316_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -466,11 +469,19 @@ static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_component *component = dai->component; struct snd_soc_component *component = dai->component;
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
u8 wordlen = 0; u8 wordlen = 0;
int i;
if (!es8316->sysclk) { /* Validate supported sample rates that are autodetected from MCLK */
dev_err(component->dev, "No MCLK configured\n"); for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) {
return -EINVAL; const unsigned int ratio = supported_mclk_lrck_ratios[i];
if (es8316->sysclk % ratio != 0)
continue;
if (es8316->sysclk / ratio == params_rate(params))
break;
} }
if (i == NR_SUPPORTED_MCLK_LRCK_RATIOS)
return -EINVAL;
switch (params_format(params)) { switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE: case SNDRV_PCM_FORMAT_S16_LE:
...@@ -700,9 +711,24 @@ static int es8316_set_jack(struct snd_soc_component *component, ...@@ -700,9 +711,24 @@ static int es8316_set_jack(struct snd_soc_component *component,
static int es8316_probe(struct snd_soc_component *component) static int es8316_probe(struct snd_soc_component *component)
{ {
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
int ret;
es8316->component = component; es8316->component = component;
es8316->mclk = devm_clk_get_optional(component->dev, "mclk");
if (IS_ERR(es8316->mclk)) {
dev_err(component->dev, "unable to get mclk\n");
return PTR_ERR(es8316->mclk);
}
if (!es8316->mclk)
dev_warn(component->dev, "assuming static mclk\n");
ret = clk_prepare_enable(es8316->mclk);
if (ret) {
dev_err(component->dev, "unable to enable mclk\n");
return ret;
}
/* Reset codec and enable current state machine */ /* Reset codec and enable current state machine */
snd_soc_component_write(component, ES8316_RESET, 0x3f); snd_soc_component_write(component, ES8316_RESET, 0x3f);
usleep_range(5000, 5500); usleep_range(5000, 5500);
...@@ -725,8 +751,16 @@ static int es8316_probe(struct snd_soc_component *component) ...@@ -725,8 +751,16 @@ static int es8316_probe(struct snd_soc_component *component)
return 0; return 0;
} }
static void es8316_remove(struct snd_soc_component *component)
{
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
clk_disable_unprepare(es8316->mclk);
}
static const struct snd_soc_component_driver soc_component_dev_es8316 = { static const struct snd_soc_component_driver soc_component_dev_es8316 = {
.probe = es8316_probe, .probe = es8316_probe,
.remove = es8316_remove,
.set_jack = es8316_set_jack, .set_jack = es8316_set_jack,
.controls = es8316_snd_controls, .controls = es8316_snd_controls,
.num_controls = ARRAY_SIZE(es8316_snd_controls), .num_controls = ARRAY_SIZE(es8316_snd_controls),
......
...@@ -99,7 +99,6 @@ static SOC_ENUM_SINGLE_DECL(adcpol, ...@@ -99,7 +99,6 @@ static SOC_ENUM_SINGLE_DECL(adcpol,
static const DECLARE_TLV_DB_SCALE(play_tlv, -3000, 100, 0); static const DECLARE_TLV_DB_SCALE(play_tlv, -3000, 100, 0);
static const DECLARE_TLV_DB_SCALE(dac_adc_tlv, -9600, 50, 0); static const DECLARE_TLV_DB_SCALE(dac_adc_tlv, -9600, 50, 0);
static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0);
static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 300, 0); static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 300, 0);
......
此差异已折叠。
...@@ -405,7 +405,6 @@ static int rk3036_codec_platform_probe(struct platform_device *pdev) ...@@ -405,7 +405,6 @@ static int rk3036_codec_platform_probe(struct platform_device *pdev)
{ {
struct rk3036_codec_priv *priv; struct rk3036_codec_priv *priv;
struct device_node *of_node = pdev->dev.of_node; struct device_node *of_node = pdev->dev.of_node;
struct resource *res;
void __iomem *base; void __iomem *base;
struct regmap *grf; struct regmap *grf;
int ret; int ret;
...@@ -414,8 +413,7 @@ static int rk3036_codec_platform_probe(struct platform_device *pdev) ...@@ -414,8 +413,7 @@ static int rk3036_codec_platform_probe(struct platform_device *pdev)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_platform_ioremap_resource(pdev, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base)) if (IS_ERR(base))
return PTR_ERR(base); return PTR_ERR(base);
......
...@@ -545,15 +545,13 @@ static int jz4725b_codec_probe(struct platform_device *pdev) ...@@ -545,15 +545,13 @@ static int jz4725b_codec_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct jz_icdc *icdc; struct jz_icdc *icdc;
struct resource *mem;
int ret; int ret;
icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL); icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL);
if (!icdc) if (!icdc)
return -ENOMEM; return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); icdc->base = devm_platform_ioremap_resource(pdev, 0);
icdc->base = devm_ioremap_resource(dev, mem);
if (IS_ERR(icdc->base)) if (IS_ERR(icdc->base))
return PTR_ERR(icdc->base); return PTR_ERR(icdc->base);
......
...@@ -318,7 +318,6 @@ static int jz4740_codec_probe(struct platform_device *pdev) ...@@ -318,7 +318,6 @@ static int jz4740_codec_probe(struct platform_device *pdev)
{ {
int ret; int ret;
struct jz4740_codec *jz4740_codec; struct jz4740_codec *jz4740_codec;
struct resource *mem;
void __iomem *base; void __iomem *base;
jz4740_codec = devm_kzalloc(&pdev->dev, sizeof(*jz4740_codec), jz4740_codec = devm_kzalloc(&pdev->dev, sizeof(*jz4740_codec),
...@@ -326,8 +325,7 @@ static int jz4740_codec_probe(struct platform_device *pdev) ...@@ -326,8 +325,7 @@ static int jz4740_codec_probe(struct platform_device *pdev)
if (!jz4740_codec) if (!jz4740_codec)
return -ENOMEM; return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_platform_ioremap_resource(pdev, 0);
base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(base)) if (IS_ERR(base))
return PTR_ERR(base); return PTR_ERR(base);
......
此差异已折叠。
此差异已折叠。
...@@ -154,10 +154,6 @@ static const DECLARE_TLV_DB_RANGE(max98371_gain_tlv, ...@@ -154,10 +154,6 @@ static const DECLARE_TLV_DB_RANGE(max98371_gain_tlv,
8, 10, TLV_DB_SCALE_ITEM(400, 100, 0) 8, 10, TLV_DB_SCALE_ITEM(400, 100, 0)
); );
static const DECLARE_TLV_DB_RANGE(max98371_noload_gain_tlv,
0, 11, TLV_DB_SCALE_ITEM(950, 100, 0),
);
static const DECLARE_TLV_DB_SCALE(digital_tlv, -6300, 50, 1); static const DECLARE_TLV_DB_SCALE(digital_tlv, -6300, 50, 1);
static const struct snd_kcontrol_new max98371_snd_controls[] = { static const struct snd_kcontrol_new max98371_snd_controls[] = {
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册