Merge branch 'asoc-5.4' into asoc-next

This commit is contained in:
Mark Brown 2019-09-15 10:31:44 +01:00
commit a54f848572
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
273 changed files with 12154 additions and 6887 deletions

View File

@ -0,0 +1,88 @@
# 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>;
};

View File

@ -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:

View File

@ -0,0 +1,39 @@
# 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>;
};
...

View File

@ -0,0 +1,57 @@
# 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";
};
...

View File

@ -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:

View File

@ -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:
* "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 {

View File

@ -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:
* "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 {

View File

@ -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 {

View File

@ -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.

View File

@ -1,10 +1,12 @@
* 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 {
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':

View File

@ -0,0 +1,23 @@
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";
};

View File

@ -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.

View File

@ -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.

View File

@ -1,14 +0,0 @@
* 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>;
};

View File

@ -1,63 +0,0 @@
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";
};
};

View File

@ -0,0 +1,17 @@
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>;
};

View File

@ -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 {
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 {
/* 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 {
}; };
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,
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,
/* /*
* 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) \

View File

@ -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);

View File

@ -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 {
*/ */
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 {
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__ */

View File

@ -1,18 +1,17 @@
/* 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 {
#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 {
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

View File

@ -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 {
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)

View File

@ -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

View File

@ -0,0 +1,387 @@
/* 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 */

View File

@ -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 {
/* 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 {
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;

View File

@ -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,
/* 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 {
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 {
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;

View File

@ -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,

View File

@ -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);
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 {
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 {
#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 {
}; };
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 {
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 {
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 {
#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 {
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 {
#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 {
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 {
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)
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,
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)
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

View File

@ -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 {
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

View File

@ -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 {
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;

View File

@ -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 */

View File

@ -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 @@
/* 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

View File

@ -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 = {

View File

@ -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
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.

View File

@ -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

View File

@ -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;

View File

@ -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 = {
* 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,
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,
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 */

View File

@ -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)
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)
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);

View File

@ -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,
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,
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);

107
sound/hda/intel-nhlt.c Normal file
View File

@ -0,0 +1,107 @@
// 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");

View File

@ -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
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

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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];
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);
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)
/* /*
* 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,
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)
} }
#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)
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,
#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,
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);

View File

@ -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,
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;

View File

@ -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"

View File

@ -1,5 +1,5 @@
# 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/
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/

View File

@ -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);

View File

@ -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"

View File

@ -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)) {

View File

@ -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)) {

View File

@ -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,
/* /*
* 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;
switch (ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_LEFT_J:
fs_osync = SSC_FSOS_POSITIVE;
fs_edge = SSC_START_RISING_RF;
rcmr = SSC_BF(RCMR_STTDLY, 0);
tcmr = SSC_BF(TCMR_STTDLY, 0);
break;
case SND_SOC_DAIFMT_I2S:
fs_osync = SSC_FSOS_NEGATIVE;
fs_edge = SSC_START_FALLING_RF;
rcmr = SSC_BF(RCMR_STTDLY, 1);
tcmr = SSC_BF(TCMR_STTDLY, 1);
break;
case SND_SOC_DAIFMT_DSP_A:
/* /*
* I2S format, SSC provides BCLK and LRC clocks. * DSP/PCM Mode A format
*
* 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) {
dev_err(dai->dev,
"sample size %d is too large for SSC device\n",
bits);
return -EINVAL;
}
fslen_ext = (bits - 1) / 16;
fslen = (bits - 1) % 16;
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_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;
case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFS:
/* I2S format, CODEC supplies BCLK, SSC supplies LRCLK. */
if (bits > 16 && !ssc->pdata->has_fslen_ext) {
dev_err(dai->dev,
"sample size %d is too large for SSC device\n",
bits);
return -EINVAL;
}
fslen_ext = (bits - 1) / 16;
fslen = (bits - 1) % 16;
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;
case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
/*
* DSP/PCM Mode A format, CODEC supplies BCLK and LRC clocks.
* *
* 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)
| SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ?
SSC_CKS_PIN : SSC_CKS_CLOCK);
rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) rcmr = SSC_BF(RCMR_STTDLY, 1);
| SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) tcmr = SSC_BF(TCMR_STTDLY, 1);
| 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,
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);

View File

@ -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,
(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,
} }
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,
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,
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,
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,
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; return ret;
} }
ret = clk_prepare(dev->gclk);
if (ret < 0) {
dev_err(dev->dev, "unable to prepare GCLK: %d\n", 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) {

View File

@ -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)
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);

View File

@ -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)
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);

View File

@ -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)
} }
/* 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);

View File

@ -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,
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)
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)
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)

View File

@ -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) {

View File

@ -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)
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);

View File

@ -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);

View File

@ -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 =
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",

View File

@ -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
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
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
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
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
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

View File

@ -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
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
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
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

View File

@ -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)
{ 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);
}
} }
} }

View File

@ -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,
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;
} }

View File

@ -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"};

View File

@ -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);

View File

@ -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);

1490
sound/soc/codecs/cs47l15.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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),

View File

@ -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)
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]);
} }

2039
sound/soc/codecs/cs47l92.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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[] = {
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,
{ {
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,
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,
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,
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)
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),

View File

@ -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);

View File

@ -7,6 +7,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/jack.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
@ -274,6 +275,8 @@ struct hdmi_codec_priv {
struct snd_pcm_chmap *chmap_info; struct snd_pcm_chmap *chmap_info;
unsigned int chmap_idx; unsigned int chmap_idx;
struct mutex lock; struct mutex lock;
struct snd_soc_jack *jack;
unsigned int jack_status;
}; };
static const struct snd_soc_dapm_widget hdmi_widgets[] = { static const struct snd_soc_dapm_widget hdmi_widgets[] = {
@ -663,6 +666,49 @@ static int hdmi_dai_probe(struct snd_soc_dai *dai)
return 0; return 0;
} }
static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
unsigned int jack_status)
{
if (hcp->jack && jack_status != hcp->jack_status) {
snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
hcp->jack_status = jack_status;
}
}
static void plugged_cb(struct device *dev, bool plugged)
{
struct hdmi_codec_priv *hcp = dev_get_drvdata(dev);
if (plugged)
hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);
else
hdmi_codec_jack_report(hcp, 0);
}
/**
* hdmi_codec_set_jack_detect - register HDMI plugged callback
* @component: the hdmi-codec instance
* @jack: ASoC jack to report (dis)connection events on
*/
int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
struct snd_soc_jack *jack)
{
struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
int ret = -EOPNOTSUPP;
if (hcp->hcd.ops->hook_plugged_cb) {
hcp->jack = jack;
ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
hcp->hcd.data,
plugged_cb,
component->dev);
if (ret)
hcp->jack = NULL;
}
return ret;
}
EXPORT_SYMBOL_GPL(hdmi_codec_set_jack_detect);
static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai) static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)
{ {
struct hdmi_codec_daifmt *cf = dai->playback_dma_data; struct hdmi_codec_daifmt *cf = dai->playback_dma_data;

View File

@ -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)
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);

View File

@ -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);

View File

@ -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)
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);

View File

@ -87,6 +87,16 @@
#define MADERA_FLLAO_MIN_N 4 #define MADERA_FLLAO_MIN_N 4
#define MADERA_FLLAO_MAX_N 1023 #define MADERA_FLLAO_MAX_N 1023
#define MADERA_FLLAO_MAX_FBDIV 254 #define MADERA_FLLAO_MAX_FBDIV 254
#define MADERA_FLLHJ_INT_MAX_N 1023
#define MADERA_FLLHJ_INT_MIN_N 1
#define MADERA_FLLHJ_FRAC_MAX_N 255
#define MADERA_FLLHJ_FRAC_MIN_N 4
#define MADERA_FLLHJ_LOW_THRESH 192000
#define MADERA_FLLHJ_MID_THRESH 1152000
#define MADERA_FLLHJ_MAX_THRESH 13000000
#define MADERA_FLLHJ_LOW_GAINS 0x23f0
#define MADERA_FLLHJ_MID_GAINS 0x22f2
#define MADERA_FLLHJ_HIGH_GAINS 0x21f0
#define MADERA_FLL_SYNCHRONISER_OFFS 0x10 #define MADERA_FLL_SYNCHRONISER_OFFS 0x10
#define CS47L35_FLL_SYNCHRONISER_OFFS 0xE #define CS47L35_FLL_SYNCHRONISER_OFFS 0xE
@ -96,6 +106,7 @@
#define MADERA_FLL_CONTROL_4_OFFS 0x4 #define MADERA_FLL_CONTROL_4_OFFS 0x4
#define MADERA_FLL_CONTROL_5_OFFS 0x5 #define MADERA_FLL_CONTROL_5_OFFS 0x5
#define MADERA_FLL_CONTROL_6_OFFS 0x6 #define MADERA_FLL_CONTROL_6_OFFS 0x6
#define MADERA_FLL_GAIN_OFFS 0x8
#define MADERA_FLL_CONTROL_7_OFFS 0x9 #define MADERA_FLL_CONTROL_7_OFFS 0x9
#define MADERA_FLL_EFS_2_OFFS 0xA #define MADERA_FLL_EFS_2_OFFS 0xA
#define MADERA_FLL_SYNCHRONISER_1_OFFS 0x1 #define MADERA_FLL_SYNCHRONISER_1_OFFS 0x1
@ -107,6 +118,9 @@
#define MADERA_FLL_SYNCHRONISER_7_OFFS 0x7 #define MADERA_FLL_SYNCHRONISER_7_OFFS 0x7
#define MADERA_FLL_SPREAD_SPECTRUM_OFFS 0x9 #define MADERA_FLL_SPREAD_SPECTRUM_OFFS 0x9
#define MADERA_FLL_GPIO_CLOCK_OFFS 0xA #define MADERA_FLL_GPIO_CLOCK_OFFS 0xA
#define MADERA_FLL_CONTROL_10_OFFS 0xA
#define MADERA_FLL_CONTROL_11_OFFS 0xB
#define MADERA_FLL1_DIGITAL_TEST_1_OFFS 0xD
#define MADERA_FLLAO_CONTROL_1_OFFS 0x1 #define MADERA_FLLAO_CONTROL_1_OFFS 0x1
#define MADERA_FLLAO_CONTROL_2_OFFS 0x2 #define MADERA_FLLAO_CONTROL_2_OFFS 0x2
@ -300,6 +314,100 @@ int madera_free_overheat(struct madera_priv *priv)
} }
EXPORT_SYMBOL_GPL(madera_free_overheat); EXPORT_SYMBOL_GPL(madera_free_overheat);
static int madera_get_variable_u32_array(struct device *dev,
const char *propname,
u32 *dest, int n_max,
int multiple)
{
int n, ret;
n = device_property_count_u32(dev, propname);
if (n < 0) {
if (n == -EINVAL)
return 0; /* missing, ignore */
dev_warn(dev, "%s malformed (%d)\n", propname, n);
return n;
} else if ((n % multiple) != 0) {
dev_warn(dev, "%s not a multiple of %d entries\n",
propname, multiple);
return -EINVAL;
}
if (n > n_max)
n = n_max;
ret = device_property_read_u32_array(dev, propname, dest, n);
if (ret < 0)
return ret;
return n;
}
static void madera_prop_get_inmode(struct madera_priv *priv)
{
struct madera *madera = priv->madera;
struct madera_codec_pdata *pdata = &madera->pdata.codec;
u32 tmp[MADERA_MAX_INPUT * MADERA_MAX_MUXED_CHANNELS];
int n, i, in_idx, ch_idx;
BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode) != MADERA_MAX_INPUT);
BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode[0]) != MADERA_MAX_MUXED_CHANNELS);
n = madera_get_variable_u32_array(madera->dev, "cirrus,inmode",
tmp, ARRAY_SIZE(tmp),
MADERA_MAX_MUXED_CHANNELS);
if (n < 0)
return;
in_idx = 0;
ch_idx = 0;
for (i = 0; i < n; ++i) {
pdata->inmode[in_idx][ch_idx] = tmp[i];
if (++ch_idx == MADERA_MAX_MUXED_CHANNELS) {
ch_idx = 0;
++in_idx;
}
}
}
static void madera_prop_get_pdata(struct madera_priv *priv)
{
struct madera *madera = priv->madera;
struct madera_codec_pdata *pdata = &madera->pdata.codec;
u32 out_mono[ARRAY_SIZE(pdata->out_mono)];
int i, n;
madera_prop_get_inmode(priv);
n = madera_get_variable_u32_array(madera->dev, "cirrus,out-mono",
out_mono, ARRAY_SIZE(out_mono), 1);
if (n > 0)
for (i = 0; i < n; ++i)
pdata->out_mono[i] = !!out_mono[i];
madera_get_variable_u32_array(madera->dev,
"cirrus,max-channels-clocked",
pdata->max_channels_clocked,
ARRAY_SIZE(pdata->max_channels_clocked),
1);
madera_get_variable_u32_array(madera->dev, "cirrus,pdm-fmt",
pdata->pdm_fmt,
ARRAY_SIZE(pdata->pdm_fmt), 1);
madera_get_variable_u32_array(madera->dev, "cirrus,pdm-mute",
pdata->pdm_mute,
ARRAY_SIZE(pdata->pdm_mute), 1);
madera_get_variable_u32_array(madera->dev, "cirrus,dmic-ref",
pdata->dmic_ref,
ARRAY_SIZE(pdata->dmic_ref), 1);
}
int madera_core_init(struct madera_priv *priv) int madera_core_init(struct madera_priv *priv)
{ {
int i; int i;
@ -308,6 +416,9 @@ int madera_core_init(struct madera_priv *priv)
BUILD_BUG_ON(!madera_mixer_texts[MADERA_NUM_MIXER_INPUTS - 1]); BUILD_BUG_ON(!madera_mixer_texts[MADERA_NUM_MIXER_INPUTS - 1]);
BUILD_BUG_ON(!madera_mixer_values[MADERA_NUM_MIXER_INPUTS - 1]); BUILD_BUG_ON(!madera_mixer_values[MADERA_NUM_MIXER_INPUTS - 1]);
if (!dev_get_platdata(priv->madera->dev))
madera_prop_get_pdata(priv);
mutex_init(&priv->rate_lock); mutex_init(&priv->rate_lock);
for (i = 0; i < MADERA_MAX_HP_OUTPUT; i++) for (i = 0; i < MADERA_MAX_HP_OUTPUT; i++)
@ -944,6 +1055,10 @@ static void madera_configure_input_mode(struct madera *madera)
int max_analogue_inputs, max_dmic_sup, i; int max_analogue_inputs, max_dmic_sup, i;
switch (madera->type) { switch (madera->type) {
case CS47L15:
max_analogue_inputs = 1;
max_dmic_sup = 2;
break;
case CS47L35: case CS47L35:
max_analogue_inputs = 2; max_analogue_inputs = 2;
max_dmic_sup = 2; max_dmic_sup = 2;
@ -1770,6 +1885,18 @@ const struct soc_enum madera_asrc1_rate[] = {
}; };
EXPORT_SYMBOL_GPL(madera_asrc1_rate); EXPORT_SYMBOL_GPL(madera_asrc1_rate);
const struct soc_enum madera_asrc1_bidir_rate[] = {
SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE1,
MADERA_ASRC1_RATE1_SHIFT, 0xf,
MADERA_RATE_ENUM_SIZE,
madera_rate_text, madera_rate_val),
SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE2,
MADERA_ASRC1_RATE2_SHIFT, 0xf,
MADERA_RATE_ENUM_SIZE,
madera_rate_text, madera_rate_val),
};
EXPORT_SYMBOL_GPL(madera_asrc1_bidir_rate);
const struct soc_enum madera_asrc2_rate[] = { const struct soc_enum madera_asrc2_rate[] = {
SOC_VALUE_ENUM_SINGLE(MADERA_ASRC2_RATE1, SOC_VALUE_ENUM_SINGLE(MADERA_ASRC2_RATE1,
MADERA_ASRC2_RATE1_SHIFT, 0xf, MADERA_ASRC2_RATE1_SHIFT, 0xf,
@ -2149,6 +2276,9 @@ int madera_out_ev(struct snd_soc_dapm_widget *w,
switch (madera->type) { switch (madera->type) {
case CS47L90: case CS47L90:
case CS47L91: case CS47L91:
case CS42L92:
case CS47L92:
case CS47L93:
out_up_delay = 6; out_up_delay = 6;
break; break;
default: default:
@ -2264,9 +2394,17 @@ int madera_hp_ev(struct snd_soc_dapm_widget *w,
madera->hp_ena &= ~mask; madera->hp_ena &= ~mask;
madera->hp_ena |= val; madera->hp_ena |= val;
/* if OUT1 is routed to EPOUT, ignore HP clamp and impedance */ switch (madera->type) {
regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &ep_sel); case CS42L92:
ep_sel &= MADERA_EP_SEL_MASK; case CS47L92:
case CS47L93:
break;
default:
/* if OUT1 is routed to EPOUT, ignore HP clamp and impedance */
regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &ep_sel);
ep_sel &= MADERA_EP_SEL_MASK;
break;
}
/* Force off if HPDET has disabled the clamp for this output */ /* Force off if HPDET has disabled the clamp for this output */
if (!ep_sel && if (!ep_sel &&
@ -2442,6 +2580,58 @@ static int madera_get_dspclk_setting(struct madera *madera,
} }
} }
static int madera_set_outclk(struct snd_soc_component *component,
unsigned int source, unsigned int freq)
{
int div, div_inc, rate;
switch (source) {
case MADERA_OUTCLK_SYSCLK:
dev_dbg(component->dev, "Configured OUTCLK to SYSCLK\n");
snd_soc_component_update_bits(component, MADERA_OUTPUT_RATE_1,
MADERA_OUT_CLK_SRC_MASK, source);
return 0;
case MADERA_OUTCLK_ASYNCCLK:
dev_dbg(component->dev, "Configured OUTCLK to ASYNCCLK\n");
snd_soc_component_update_bits(component, MADERA_OUTPUT_RATE_1,
MADERA_OUT_CLK_SRC_MASK, source);
return 0;
case MADERA_OUTCLK_MCLK1:
case MADERA_OUTCLK_MCLK2:
case MADERA_OUTCLK_MCLK3:
break;
default:
return -EINVAL;
}
if (freq % 4000)
rate = 5644800;
else
rate = 6144000;
div = 1;
div_inc = 0;
while (div <= 8) {
if (freq / div == rate && !(freq % div)) {
dev_dbg(component->dev, "Configured %dHz OUTCLK\n", rate);
snd_soc_component_update_bits(component,
MADERA_OUTPUT_RATE_1,
MADERA_OUT_EXT_CLK_DIV_MASK |
MADERA_OUT_CLK_SRC_MASK,
(div_inc << MADERA_OUT_EXT_CLK_DIV_SHIFT) |
source);
return 0;
}
div_inc++;
div *= 2;
}
dev_err(component->dev,
"Unable to generate %dHz OUTCLK from %dHz MCLK\n",
rate, freq);
return -EINVAL;
}
int madera_set_sysclk(struct snd_soc_component *component, int clk_id, int madera_set_sysclk(struct snd_soc_component *component, int clk_id,
int source, unsigned int freq, int dir) int source, unsigned int freq, int dir)
{ {
@ -2478,6 +2668,8 @@ int madera_set_sysclk(struct snd_soc_component *component, int clk_id,
case MADERA_CLK_OPCLK: case MADERA_CLK_OPCLK:
case MADERA_CLK_ASYNC_OPCLK: case MADERA_CLK_ASYNC_OPCLK:
return madera_set_opclk(component, clk_id, freq); return madera_set_opclk(component, clk_id, freq);
case MADERA_CLK_OUTCLK:
return madera_set_outclk(component, source, freq);
default: default:
return -EINVAL; return -EINVAL;
} }
@ -2691,6 +2883,10 @@ static const unsigned int madera_sr_vals[] = {
#define MADERA_192K_44K1_RATE_MASK 0x003E00 #define MADERA_192K_44K1_RATE_MASK 0x003E00
#define MADERA_192K_RATE_MASK (MADERA_192K_48K_RATE_MASK | \ #define MADERA_192K_RATE_MASK (MADERA_192K_48K_RATE_MASK | \
MADERA_192K_44K1_RATE_MASK) MADERA_192K_44K1_RATE_MASK)
#define MADERA_384K_48K_RATE_MASK 0x0F007E
#define MADERA_384K_44K1_RATE_MASK 0x007E00
#define MADERA_384K_RATE_MASK (MADERA_384K_48K_RATE_MASK | \
MADERA_384K_44K1_RATE_MASK)
static const struct snd_pcm_hw_constraint_list madera_constraint = { static const struct snd_pcm_hw_constraint_list madera_constraint = {
.count = ARRAY_SIZE(madera_sr_vals), .count = ARRAY_SIZE(madera_sr_vals),
@ -2703,6 +2899,7 @@ static int madera_startup(struct snd_pcm_substream *substream,
struct snd_soc_component *component = dai->component; struct snd_soc_component *component = dai->component;
struct madera_priv *priv = snd_soc_component_get_drvdata(component); struct madera_priv *priv = snd_soc_component_get_drvdata(component);
struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1]; struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1];
struct madera *madera = priv->madera;
unsigned int base_rate; unsigned int base_rate;
if (!substream->runtime) if (!substream->runtime)
@ -2722,12 +2919,26 @@ static int madera_startup(struct snd_pcm_substream *substream,
return 0; return 0;
} }
if (base_rate == 0) switch (madera->type) {
dai_priv->constraint.mask = MADERA_192K_RATE_MASK; case CS42L92:
else if (base_rate % 4000) case CS47L92:
dai_priv->constraint.mask = MADERA_192K_44K1_RATE_MASK; case CS47L93:
else if (base_rate == 0)
dai_priv->constraint.mask = MADERA_192K_48K_RATE_MASK; dai_priv->constraint.mask = MADERA_384K_RATE_MASK;
else if (base_rate % 4000)
dai_priv->constraint.mask = MADERA_384K_44K1_RATE_MASK;
else
dai_priv->constraint.mask = MADERA_384K_48K_RATE_MASK;
break;
default:
if (base_rate == 0)
dai_priv->constraint.mask = MADERA_192K_RATE_MASK;
else if (base_rate % 4000)
dai_priv->constraint.mask = MADERA_192K_44K1_RATE_MASK;
else
dai_priv->constraint.mask = MADERA_192K_48K_RATE_MASK;
break;
}
return snd_pcm_hw_constraint_list(substream->runtime, 0, return snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, SNDRV_PCM_HW_PARAM_RATE,
@ -4048,6 +4259,308 @@ int madera_set_fll_ao_refclk(struct madera_fll *fll, int source,
} }
EXPORT_SYMBOL_GPL(madera_set_fll_ao_refclk); EXPORT_SYMBOL_GPL(madera_set_fll_ao_refclk);
static int madera_fllhj_disable(struct madera_fll *fll)
{
struct madera *madera = fll->madera;
bool change;
madera_fll_dbg(fll, "Disabling FLL\n");
/* Disable lockdet, but don't set ctrl_upd update but. This allows the
* lock status bit to clear as normal, but should the FLL be enabled
* again due to a control clock being required, the lock won't re-assert
* as the FLL config registers are automatically applied when the FLL
* enables.
*/
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_11_OFFS,
MADERA_FLL1_LOCKDET_MASK, 0);
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_1_OFFS,
MADERA_FLL1_HOLD_MASK, MADERA_FLL1_HOLD_MASK);
regmap_update_bits_check(madera->regmap,
fll->base + MADERA_FLL_CONTROL_1_OFFS,
MADERA_FLL1_ENA_MASK, 0, &change);
madera_wait_for_fll(fll, false);
/* ctrl_up gates the writes to all the fll's registers, setting it to 0
* here ensures that after a runtime suspend/resume cycle when one
* enables the fll then ctrl_up is the last bit that is configured
* by the fll enable code rather than the cache sync operation which
* would have updated it much earlier before writing out all fll
* registers
*/
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_2_OFFS,
MADERA_FLL1_CTRL_UPD_MASK, 0);
if (change)
pm_runtime_put_autosuspend(madera->dev);
return 0;
}
static int madera_fllhj_apply(struct madera_fll *fll, int fin)
{
struct madera *madera = fll->madera;
int refdiv, fref, fout, lockdet_thr, fbdiv, hp, fast_clk, fllgcd;
bool frac = false;
unsigned int fll_n, min_n, max_n, ratio, theta, lambda;
unsigned int gains, val, num;
madera_fll_dbg(fll, "fin=%d, fout=%d\n", fin, fll->fout);
for (refdiv = 0; refdiv < 4; refdiv++)
if ((fin / (1 << refdiv)) <= MADERA_FLLHJ_MAX_THRESH)
break;
fref = fin / (1 << refdiv);
/* Use simple heuristic approach to find a configuration that
* should work for most input clocks.
*/
fast_clk = 0;
fout = fll->fout;
frac = fout % fref;
if (fref < MADERA_FLLHJ_LOW_THRESH) {
lockdet_thr = 2;
gains = MADERA_FLLHJ_LOW_GAINS;
if (frac)
fbdiv = 256;
else
fbdiv = 4;
} else if (fref < MADERA_FLLHJ_MID_THRESH) {
lockdet_thr = 8;
gains = MADERA_FLLHJ_MID_GAINS;
fbdiv = 1;
} else {
lockdet_thr = 8;
gains = MADERA_FLLHJ_HIGH_GAINS;
fbdiv = 1;
/* For high speed input clocks, enable 300MHz fast oscillator
* when we're in fractional divider mode.
*/
if (frac) {
fast_clk = 0x3;
fout = fll->fout * 6;
}
}
/* Use high performance mode for fractional configurations. */
if (frac) {
hp = 0x3;
min_n = MADERA_FLLHJ_FRAC_MIN_N;
max_n = MADERA_FLLHJ_FRAC_MAX_N;
} else {
hp = 0x0;
min_n = MADERA_FLLHJ_INT_MIN_N;
max_n = MADERA_FLLHJ_INT_MAX_N;
}
ratio = fout / fref;
madera_fll_dbg(fll, "refdiv=%d, fref=%d, frac:%d\n",
refdiv, fref, frac);
while (ratio / fbdiv < min_n) {
fbdiv /= 2;
if (fbdiv < 1) {
madera_fll_err(fll, "FBDIV (%d) must be >= 1\n", fbdiv);
return -EINVAL;
}
}
while (frac && (ratio / fbdiv > max_n)) {
fbdiv *= 2;
if (fbdiv >= 1024) {
madera_fll_err(fll, "FBDIV (%u) >= 1024\n", fbdiv);
return -EINVAL;
}
}
madera_fll_dbg(fll, "lockdet=%d, hp=0x%x, fbdiv:%d\n",
lockdet_thr, hp, fbdiv);
/* Calculate N.K values */
fllgcd = gcd(fout, fbdiv * fref);
num = fout / fllgcd;
lambda = (fref * fbdiv) / fllgcd;
fll_n = num / lambda;
theta = num % lambda;
madera_fll_dbg(fll, "fll_n=%d, gcd=%d, theta=%d, lambda=%d\n",
fll_n, fllgcd, theta, lambda);
/* Some sanity checks before any registers are written. */
if (fll_n < min_n || fll_n > max_n) {
madera_fll_err(fll, "N not in valid %s mode range %d-%d: %d\n",
frac ? "fractional" : "integer", min_n, max_n,
fll_n);
return -EINVAL;
}
if (fbdiv < 1 || (frac && fbdiv >= 1024) || (!frac && fbdiv >= 256)) {
madera_fll_err(fll, "Invalid fbdiv for %s mode (%u)\n",
frac ? "fractional" : "integer", fbdiv);
return -EINVAL;
}
/* clear the ctrl_upd bit to guarantee we write to it later. */
regmap_write(madera->regmap,
fll->base + MADERA_FLL_CONTROL_2_OFFS,
fll_n << MADERA_FLL1_N_SHIFT);
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_3_OFFS,
MADERA_FLL1_THETA_MASK,
theta << MADERA_FLL1_THETA_SHIFT);
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_4_OFFS,
MADERA_FLL1_LAMBDA_MASK,
lambda << MADERA_FLL1_LAMBDA_SHIFT);
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_5_OFFS,
MADERA_FLL1_FB_DIV_MASK,
fbdiv << MADERA_FLL1_FB_DIV_SHIFT);
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_6_OFFS,
MADERA_FLL1_REFCLK_DIV_MASK,
refdiv << MADERA_FLL1_REFCLK_DIV_SHIFT);
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_GAIN_OFFS,
0xffff,
gains);
val = hp << MADERA_FLL1_HP_SHIFT;
val |= 1 << MADERA_FLL1_PHASEDET_ENA_SHIFT;
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_10_OFFS,
MADERA_FLL1_HP_MASK | MADERA_FLL1_PHASEDET_ENA_MASK,
val);
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_11_OFFS,
MADERA_FLL1_LOCKDET_THR_MASK,
lockdet_thr << MADERA_FLL1_LOCKDET_THR_SHIFT);
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL1_DIGITAL_TEST_1_OFFS,
MADERA_FLL1_SYNC_EFS_ENA_MASK |
MADERA_FLL1_CLK_VCO_FAST_SRC_MASK,
fast_clk);
return 0;
}
static int madera_fllhj_enable(struct madera_fll *fll)
{
struct madera *madera = fll->madera;
int already_enabled = madera_is_enabled_fll(fll, fll->base);
int ret;
if (already_enabled < 0)
return already_enabled;
if (!already_enabled)
pm_runtime_get_sync(madera->dev);
madera_fll_dbg(fll, "Enabling FLL, initially %s\n",
already_enabled ? "enabled" : "disabled");
/* FLLn_HOLD must be set before configuring any registers */
regmap_update_bits(fll->madera->regmap,
fll->base + MADERA_FLL_CONTROL_1_OFFS,
MADERA_FLL1_HOLD_MASK,
MADERA_FLL1_HOLD_MASK);
/* Apply refclk */
ret = madera_fllhj_apply(fll, fll->ref_freq);
if (ret) {
madera_fll_err(fll, "Failed to set FLL: %d\n", ret);
goto out;
}
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_1_OFFS,
CS47L92_FLL1_REFCLK_SRC_MASK,
fll->ref_src << CS47L92_FLL1_REFCLK_SRC_SHIFT);
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_1_OFFS,
MADERA_FLL1_ENA_MASK,
MADERA_FLL1_ENA_MASK);
out:
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_11_OFFS,
MADERA_FLL1_LOCKDET_MASK,
MADERA_FLL1_LOCKDET_MASK);
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_2_OFFS,
MADERA_FLL1_CTRL_UPD_MASK,
MADERA_FLL1_CTRL_UPD_MASK);
/* Release the hold so that flln locks to external frequency */
regmap_update_bits(madera->regmap,
fll->base + MADERA_FLL_CONTROL_1_OFFS,
MADERA_FLL1_HOLD_MASK,
0);
if (!already_enabled)
madera_wait_for_fll(fll, true);
return 0;
}
static int madera_fllhj_validate(struct madera_fll *fll,
unsigned int ref_in,
unsigned int fout)
{
if (fout && !ref_in) {
madera_fll_err(fll, "fllout set without valid input clk\n");
return -EINVAL;
}
if (fll->fout && fout != fll->fout) {
madera_fll_err(fll, "Can't change output on active FLL\n");
return -EINVAL;
}
if (ref_in / MADERA_FLL_MAX_REFDIV > MADERA_FLLHJ_MAX_THRESH) {
madera_fll_err(fll, "Can't scale %dMHz to <=13MHz\n", ref_in);
return -EINVAL;
}
return 0;
}
int madera_fllhj_set_refclk(struct madera_fll *fll, int source,
unsigned int fin, unsigned int fout)
{
int ret = 0;
/* To remain consistent with previous FLLs, we expect fout to be
* provided in the form of the required sysclk rate, which is
* 2x the calculated fll out.
*/
if (fout)
fout /= 2;
if (fll->ref_src == source && fll->ref_freq == fin &&
fll->fout == fout)
return 0;
if (fin && fout && madera_fllhj_validate(fll, fin, fout))
return -EINVAL;
fll->ref_src = source;
fll->ref_freq = fin;
fll->fout = fout;
if (fout)
ret = madera_fllhj_enable(fll);
else
madera_fllhj_disable(fll);
return ret;
}
EXPORT_SYMBOL_GPL(madera_fllhj_set_refclk);
/** /**
* madera_set_output_mode - Set the mode of the specified output * madera_set_output_mode - Set the mode of the specified output
* *

View File

@ -47,6 +47,7 @@
#define MADERA_CLK_SYSCLK_3 6 #define MADERA_CLK_SYSCLK_3 6
#define MADERA_CLK_ASYNCCLK_2 7 #define MADERA_CLK_ASYNCCLK_2 7
#define MADERA_CLK_DSPCLK 8 #define MADERA_CLK_DSPCLK 8
#define MADERA_CLK_OUTCLK 9
#define MADERA_CLK_SRC_MCLK1 0x0 #define MADERA_CLK_SRC_MCLK1 0x0
#define MADERA_CLK_SRC_MCLK2 0x1 #define MADERA_CLK_SRC_MCLK2 0x1
@ -61,6 +62,12 @@
#define MADERA_CLK_SRC_AIF4BCLK 0xB #define MADERA_CLK_SRC_AIF4BCLK 0xB
#define MADERA_CLK_SRC_FLLAO 0xF #define MADERA_CLK_SRC_FLLAO 0xF
#define MADERA_OUTCLK_SYSCLK 0
#define MADERA_OUTCLK_ASYNCCLK 1
#define MADERA_OUTCLK_MCLK1 4
#define MADERA_OUTCLK_MCLK2 5
#define MADERA_OUTCLK_MCLK3 6
#define MADERA_MIXER_VOL_MASK 0x00FE #define MADERA_MIXER_VOL_MASK 0x00FE
#define MADERA_MIXER_VOL_SHIFT 1 #define MADERA_MIXER_VOL_SHIFT 1
#define MADERA_MIXER_VOL_WIDTH 7 #define MADERA_MIXER_VOL_WIDTH 7
@ -326,6 +333,7 @@ extern const struct soc_enum madera_sample_rate[];
extern const struct soc_enum madera_isrc_fsl[]; extern const struct soc_enum madera_isrc_fsl[];
extern const struct soc_enum madera_isrc_fsh[]; extern const struct soc_enum madera_isrc_fsh[];
extern const struct soc_enum madera_asrc1_rate[]; extern const struct soc_enum madera_asrc1_rate[];
extern const struct soc_enum madera_asrc1_bidir_rate[];
extern const struct soc_enum madera_asrc2_rate[]; extern const struct soc_enum madera_asrc2_rate[];
extern const struct soc_enum madera_dfc_width[]; extern const struct soc_enum madera_dfc_width[];
extern const struct soc_enum madera_dfc_type[]; extern const struct soc_enum madera_dfc_type[];
@ -403,6 +411,8 @@ int madera_set_fll_syncclk(struct madera_fll *fll, int source,
unsigned int fref, unsigned int fout); unsigned int fref, unsigned int fout);
int madera_set_fll_ao_refclk(struct madera_fll *fll, int source, int madera_set_fll_ao_refclk(struct madera_fll *fll, int source,
unsigned int fin, unsigned int fout); unsigned int fin, unsigned int fout);
int madera_fllhj_set_refclk(struct madera_fll *fll, int source,
unsigned int fin, unsigned int fout);
int madera_core_init(struct madera_priv *priv); int madera_core_init(struct madera_priv *priv);
int madera_core_free(struct madera_priv *priv); int madera_core_free(struct madera_priv *priv);

View File

@ -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[] = {

View File

@ -12,6 +12,7 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <sound/tlv.h> #include <sound/tlv.h>
#include "max98373.h" #include "max98373.h"
@ -901,6 +902,17 @@ static void max98373_slot_config(struct i2c_client *i2c,
else else
max98373->i_slot = 1; max98373->i_slot = 1;
max98373->reset_gpio = of_get_named_gpio(dev->of_node,
"maxim,reset-gpio", 0);
if (!gpio_is_valid(max98373->reset_gpio)) {
dev_err(dev, "Looking up %s property in node %s failed %d\n",
"maxim,reset-gpio", dev->of_node->full_name,
max98373->reset_gpio);
} else {
dev_dbg(dev, "maxim,reset-gpio=%d",
max98373->reset_gpio);
}
if (!device_property_read_u32(dev, "maxim,spkfb-slot-no", &value)) if (!device_property_read_u32(dev, "maxim,spkfb-slot-no", &value))
max98373->spkfb_slot = value & 0xF; max98373->spkfb_slot = value & 0xF;
else else
@ -929,7 +941,6 @@ static int max98373_i2c_probe(struct i2c_client *i2c,
else else
max98373->interleave_mode = false; max98373->interleave_mode = false;
/* regmap initialization */ /* regmap initialization */
max98373->regmap max98373->regmap
= devm_regmap_init_i2c(i2c, &max98373_regmap); = devm_regmap_init_i2c(i2c, &max98373_regmap);
@ -940,6 +951,24 @@ static int max98373_i2c_probe(struct i2c_client *i2c,
return ret; return ret;
} }
/* voltage/current slot & gpio configuration */
max98373_slot_config(i2c, max98373);
/* Power on device */
if (gpio_is_valid(max98373->reset_gpio)) {
ret = gpio_request(max98373->reset_gpio, "MAX98373_RESET");
if (ret) {
dev_err(&i2c->dev, "%s: Failed to request gpio %d\n",
__func__, max98373->reset_gpio);
gpio_free(max98373->reset_gpio);
return -EINVAL;
}
gpio_direction_output(max98373->reset_gpio, 0);
msleep(50);
gpio_direction_output(max98373->reset_gpio, 1);
msleep(20);
}
/* Check Revision ID */ /* Check Revision ID */
ret = regmap_read(max98373->regmap, ret = regmap_read(max98373->regmap,
MAX98373_R21FF_REV_ID, &reg); MAX98373_R21FF_REV_ID, &reg);
@ -950,9 +979,6 @@ static int max98373_i2c_probe(struct i2c_client *i2c,
} }
dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg); dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg);
/* voltage/current slot configuration */
max98373_slot_config(i2c, max98373);
/* codec registeration */ /* codec registeration */
ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_max98373, ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_max98373,
max98373_dai, ARRAY_SIZE(max98373_dai)); max98373_dai, ARRAY_SIZE(max98373_dai));

View File

@ -205,6 +205,7 @@
struct max98373_priv { struct max98373_priv {
struct regmap *regmap; struct regmap *regmap;
int reset_gpio;
unsigned int v_slot; unsigned int v_slot;
unsigned int i_slot; unsigned int i_slot;
unsigned int spkfb_slot; unsigned int spkfb_slot;

View File

@ -27,19 +27,6 @@ struct max9850_priv {
unsigned int sysclk; unsigned int sysclk;
}; };
/* max9850 register cache */
static const struct reg_default max9850_reg[] = {
{ 2, 0x0c },
{ 3, 0x00 },
{ 4, 0x00 },
{ 5, 0x00 },
{ 6, 0x00 },
{ 7, 0x00 },
{ 8, 0x00 },
{ 9, 0x00 },
{ 10, 0x00 },
};
/* these registers are not used at the moment but provided for the sake of /* these registers are not used at the moment but provided for the sake of
* completeness */ * completeness */
static bool max9850_volatile_register(struct device *dev, unsigned int reg) static bool max9850_volatile_register(struct device *dev, unsigned int reg)

View File

@ -20,15 +20,6 @@ static const char * const max98926_boost_voltage_txt[] = {
"6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V" "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V"
}; };
static const char * const max98926_boost_current_txt[] = {
"0.6", "0.8", "1.0", "1.2", "1.4", "1.6", "1.8", "2.0",
"2.2", "2.4", "2.6", "2.8", "3.2", "3.6", "4.0", "4.4"
};
static const char *const max98926_dai_txt[] = {
"Left", "Right", "LeftRight", "LeftRightDiv2",
};
static const char *const max98926_pdm_ch_text[] = { static const char *const max98926_pdm_ch_text[] = {
"Current", "Voltage", "Current", "Voltage",
}; };

View File

@ -56,7 +56,6 @@ static const DECLARE_TLV_DB_SCALE(alclvl, -2250, 150, 0);
static const DECLARE_TLV_DB_SCALE(mingain, -1200, 600, 0); static const DECLARE_TLV_DB_SCALE(mingain, -1200, 600, 0);
static const DECLARE_TLV_DB_SCALE(maxgain, -675, 600, 0); static const DECLARE_TLV_DB_SCALE(maxgain, -675, 600, 0);
static const DECLARE_TLV_DB_SCALE(boost_vol, -1200, 75, 0); static const DECLARE_TLV_DB_SCALE(boost_vol, -1200, 75, 0);
static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0);
static const char * const ml26124_companding[] = {"16bit PCM", "u-law", static const char * const ml26124_companding[] = {"16bit PCM", "u-law",
"A-law"}; "A-law"};

View File

@ -1185,10 +1185,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
} }
irq = platform_get_irq_byname(pdev, "mbhc_switch_int"); irq = platform_get_irq_byname(pdev, "mbhc_switch_int");
if (irq < 0) { if (irq < 0)
dev_err(dev, "failed to get mbhc switch irq\n");
return irq; return irq;
}
ret = devm_request_threaded_irq(dev, irq, NULL, ret = devm_request_threaded_irq(dev, irq, NULL,
pm8916_mbhc_switch_irq_handler, pm8916_mbhc_switch_irq_handler,
@ -1200,10 +1198,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
if (priv->mbhc_btn_enabled) { if (priv->mbhc_btn_enabled) {
irq = platform_get_irq_byname(pdev, "mbhc_but_press_det"); irq = platform_get_irq_byname(pdev, "mbhc_but_press_det");
if (irq < 0) { if (irq < 0)
dev_err(dev, "failed to get button press irq\n");
return irq; return irq;
}
ret = devm_request_threaded_irq(dev, irq, NULL, ret = devm_request_threaded_irq(dev, irq, NULL,
mbhc_btn_press_irq_handler, mbhc_btn_press_irq_handler,
@ -1214,10 +1210,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
dev_err(dev, "cannot request mbhc button press irq\n"); dev_err(dev, "cannot request mbhc button press irq\n");
irq = platform_get_irq_byname(pdev, "mbhc_but_rel_det"); irq = platform_get_irq_byname(pdev, "mbhc_but_rel_det");
if (irq < 0) { if (irq < 0)
dev_err(dev, "failed to get button release irq\n");
return irq; return irq;
}
ret = devm_request_threaded_irq(dev, irq, NULL, ret = devm_request_threaded_irq(dev, irq, NULL,
mbhc_btn_release_irq_handler, mbhc_btn_release_irq_handler,

View File

@ -1143,7 +1143,6 @@ static int msm8916_wcd_digital_probe(struct platform_device *pdev)
struct msm8916_wcd_digital_priv *priv; struct msm8916_wcd_digital_priv *priv;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
void __iomem *base; void __iomem *base;
struct resource *mem_res;
struct regmap *digital_map; struct regmap *digital_map;
int ret; int ret;
@ -1151,8 +1150,7 @@ static int msm8916_wcd_digital_probe(struct platform_device *pdev)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_platform_ioremap_resource(pdev, 0);
base = devm_ioremap_resource(&pdev->dev, mem_res);
if (IS_ERR(base)) if (IS_ERR(base))
return PTR_ERR(base); return PTR_ERR(base);

View File

@ -1066,11 +1066,6 @@ static int mt_mic_bias_2_event(struct snd_soc_dapm_widget *w,
return 0; return 0;
} }
/* DAPM Kcontrols */
static const struct snd_kcontrol_new mt_lineout_control =
SOC_DAPM_SINGLE("Switch", MT6351_AUDDEC_ANA_CON3,
RG_AUDLOLPWRUP_VAUDP32_BIT, 1, 0);
/* DAPM Widgets */ /* DAPM Widgets */
static const struct snd_soc_dapm_widget mt6351_dapm_widgets[] = { static const struct snd_soc_dapm_widget mt6351_dapm_widgets[] = {
/* Digital Clock */ /* Digital Clock */

View File

@ -1730,6 +1730,10 @@ static int mt6358_dmic_enable(struct mt6358_priv *priv)
/* UL turn on */ /* UL turn on */
regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_L, 0x0003); regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_L, 0x0003);
/* Prevent pop noise form dmic hw */
msleep(100);
return 0; return 0;
} }
@ -2255,10 +2259,8 @@ static struct snd_soc_dai_driver mt6358_dai_driver[] = {
}, },
}; };
static int mt6358_codec_init_reg(struct mt6358_priv *priv) static void mt6358_codec_init_reg(struct mt6358_priv *priv)
{ {
int ret = 0;
/* Disable HeadphoneL/HeadphoneR short circuit protection */ /* Disable HeadphoneL/HeadphoneR short circuit protection */
regmap_update_bits(priv->regmap, MT6358_AUDDEC_ANA_CON0, regmap_update_bits(priv->regmap, MT6358_AUDDEC_ANA_CON0,
RG_AUDHPLSCDISABLE_VAUDP15_MASK_SFT, RG_AUDHPLSCDISABLE_VAUDP15_MASK_SFT,
@ -2285,8 +2287,6 @@ static int mt6358_codec_init_reg(struct mt6358_priv *priv)
/* set gpio */ /* set gpio */
playback_gpio_reset(priv); playback_gpio_reset(priv);
capture_gpio_reset(priv); capture_gpio_reset(priv);
return ret;
} }
static int mt6358_codec_probe(struct snd_soc_component *cmpnt) static int mt6358_codec_probe(struct snd_soc_component *cmpnt)

View File

@ -44,18 +44,25 @@ static const char *const pcm3168a_supply_names[PCM3168A_NUM_SUPPLIES] = {
"VCCDA2" "VCCDA2"
}; };
#define PCM3168A_DAI_DAC 0
#define PCM3168A_DAI_ADC 1
/* ADC/DAC side parameters */
struct pcm3168a_io_params {
bool master_mode;
unsigned int fmt;
int tdm_slots;
u32 tdm_mask;
int slot_width;
};
struct pcm3168a_priv { struct pcm3168a_priv {
struct regulator_bulk_data supplies[PCM3168A_NUM_SUPPLIES]; struct regulator_bulk_data supplies[PCM3168A_NUM_SUPPLIES];
struct regmap *regmap; struct regmap *regmap;
struct clk *scki; struct clk *scki;
bool adc_master_mode;
bool dac_master_mode;
unsigned long sysclk; unsigned long sysclk;
unsigned int adc_fmt;
unsigned int dac_fmt; struct pcm3168a_io_params io_params[2];
int tdm_slots;
u32 tdm_mask[2];
int slot_width;
}; };
static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" }; static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" };
@ -263,7 +270,7 @@ static unsigned int pcm3168a_scki_ratios[] = {
#define PCM3168A_NUM_SCKI_RATIOS_DAC ARRAY_SIZE(pcm3168a_scki_ratios) #define PCM3168A_NUM_SCKI_RATIOS_DAC ARRAY_SIZE(pcm3168a_scki_ratios)
#define PCM3168A_NUM_SCKI_RATIOS_ADC (ARRAY_SIZE(pcm3168a_scki_ratios) - 2) #define PCM3168A_NUM_SCKI_RATIOS_ADC (ARRAY_SIZE(pcm3168a_scki_ratios) - 2)
#define PCM1368A_MAX_SYSCLK 36864000 #define PCM3168A_MAX_SYSCLK 36864000
static int pcm3168a_reset(struct pcm3168a_priv *pcm3168a) static int pcm3168a_reset(struct pcm3168a_priv *pcm3168a)
{ {
@ -296,7 +303,7 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai,
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(dai->component); struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(dai->component);
int ret; int ret;
if (freq > PCM1368A_MAX_SYSCLK) if (freq > PCM3168A_MAX_SYSCLK)
return -EINVAL; return -EINVAL;
ret = clk_set_rate(pcm3168a->scki, freq); ret = clk_set_rate(pcm3168a->scki, freq);
@ -308,8 +315,7 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai,
return 0; return 0;
} }
static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format)
unsigned int format, bool dac)
{ {
struct snd_soc_component *component = dai->component; struct snd_soc_component *component = dai->component;
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
@ -356,43 +362,31 @@ static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai,
return -EINVAL; return -EINVAL;
} }
if (dac) { if (dai->id == PCM3168A_DAI_DAC) {
reg = PCM3168A_DAC_PWR_MST_FMT; reg = PCM3168A_DAC_PWR_MST_FMT;
mask = PCM3168A_DAC_FMT_MASK; mask = PCM3168A_DAC_FMT_MASK;
shift = PCM3168A_DAC_FMT_SHIFT; shift = PCM3168A_DAC_FMT_SHIFT;
pcm3168a->dac_master_mode = master_mode;
pcm3168a->dac_fmt = fmt;
} else { } else {
reg = PCM3168A_ADC_MST_FMT; reg = PCM3168A_ADC_MST_FMT;
mask = PCM3168A_ADC_FMTAD_MASK; mask = PCM3168A_ADC_FMTAD_MASK;
shift = PCM3168A_ADC_FMTAD_SHIFT; shift = PCM3168A_ADC_FMTAD_SHIFT;
pcm3168a->adc_master_mode = master_mode;
pcm3168a->adc_fmt = fmt;
} }
pcm3168a->io_params[dai->id].master_mode = master_mode;
pcm3168a->io_params[dai->id].fmt = fmt;
regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift); regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift);
return 0; return 0;
} }
static int pcm3168a_set_dai_fmt_dac(struct snd_soc_dai *dai,
unsigned int format)
{
return pcm3168a_set_dai_fmt(dai, format, true);
}
static int pcm3168a_set_dai_fmt_adc(struct snd_soc_dai *dai,
unsigned int format)
{
return pcm3168a_set_dai_fmt(dai, format, false);
}
static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
unsigned int rx_mask, int slots, unsigned int rx_mask, int slots,
int slot_width) int slot_width)
{ {
struct snd_soc_component *component = dai->component; struct snd_soc_component *component = dai->component;
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id];
if (tx_mask >= (1<<slots) || rx_mask >= (1<<slots)) { if (tx_mask >= (1<<slots) || rx_mask >= (1<<slots)) {
dev_err(component->dev, dev_err(component->dev,
@ -408,22 +402,13 @@ static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
return -EINVAL; return -EINVAL;
} }
if (pcm3168a->tdm_slots && pcm3168a->tdm_slots != slots) { io_params->tdm_slots = slots;
dev_err(component->dev, "Not matching slots %d vs %d\n", io_params->slot_width = slot_width;
pcm3168a->tdm_slots, slots); /* Ignore the not relevant mask for the DAI/direction */
return -EINVAL; if (dai->id == PCM3168A_DAI_DAC)
} io_params->tdm_mask = tx_mask;
else
if (pcm3168a->slot_width && pcm3168a->slot_width != slot_width) { io_params->tdm_mask = rx_mask;
dev_err(component->dev, "Not matching slot_width %d vs %d\n",
pcm3168a->slot_width, slot_width);
return -EINVAL;
}
pcm3168a->tdm_slots = slots;
pcm3168a->slot_width = slot_width;
pcm3168a->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
pcm3168a->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;
return 0; return 0;
} }
@ -434,7 +419,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
{ {
struct snd_soc_component *component = dai->component; struct snd_soc_component *component = dai->component;
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
bool tx, master_mode; struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id];
bool master_mode;
u32 val, mask, shift, reg; u32 val, mask, shift, reg;
unsigned int rate, fmt, ratio, max_ratio; unsigned int rate, fmt, ratio, max_ratio;
unsigned int tdm_slots; unsigned int tdm_slots;
@ -444,23 +430,21 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
ratio = pcm3168a->sysclk / rate; ratio = pcm3168a->sysclk / rate;
tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; if (dai->id == PCM3168A_DAI_DAC) {
if (tx) {
max_ratio = PCM3168A_NUM_SCKI_RATIOS_DAC; max_ratio = PCM3168A_NUM_SCKI_RATIOS_DAC;
reg = PCM3168A_DAC_PWR_MST_FMT; reg = PCM3168A_DAC_PWR_MST_FMT;
mask = PCM3168A_DAC_MSDA_MASK; mask = PCM3168A_DAC_MSDA_MASK;
shift = PCM3168A_DAC_MSDA_SHIFT; shift = PCM3168A_DAC_MSDA_SHIFT;
master_mode = pcm3168a->dac_master_mode;
fmt = pcm3168a->dac_fmt;
} else { } else {
max_ratio = PCM3168A_NUM_SCKI_RATIOS_ADC; max_ratio = PCM3168A_NUM_SCKI_RATIOS_ADC;
reg = PCM3168A_ADC_MST_FMT; reg = PCM3168A_ADC_MST_FMT;
mask = PCM3168A_ADC_MSAD_MASK; mask = PCM3168A_ADC_MSAD_MASK;
shift = PCM3168A_ADC_MSAD_SHIFT; shift = PCM3168A_ADC_MSAD_SHIFT;
master_mode = pcm3168a->adc_master_mode;
fmt = pcm3168a->adc_fmt;
} }
master_mode = io_params->master_mode;
fmt = io_params->fmt;
for (i = 0; i < max_ratio; i++) { for (i = 0; i < max_ratio; i++) {
if (pcm3168a_scki_ratios[i] == ratio) if (pcm3168a_scki_ratios[i] == ratio)
break; break;
@ -471,8 +455,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
if (pcm3168a->slot_width) if (io_params->slot_width)
slot_width = pcm3168a->slot_width; slot_width = io_params->slot_width;
else else
slot_width = params_width(params); slot_width = params_width(params);
@ -497,8 +481,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
if (pcm3168a->tdm_slots) if (io_params->tdm_slots)
tdm_slots = pcm3168a->tdm_slots; tdm_slots = io_params->tdm_slots;
else else
tdm_slots = params_channels(params); tdm_slots = params_channels(params);
@ -534,7 +518,7 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
regmap_update_bits(pcm3168a->regmap, reg, mask, val); regmap_update_bits(pcm3168a->regmap, reg, mask, val);
if (tx) { if (dai->id == PCM3168A_DAI_DAC) {
mask = PCM3168A_DAC_FMT_MASK; mask = PCM3168A_DAC_FMT_MASK;
shift = PCM3168A_DAC_FMT_SHIFT; shift = PCM3168A_DAC_FMT_SHIFT;
} else { } else {
@ -552,20 +536,13 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream,
{ {
struct snd_soc_component *component = dai->component; struct snd_soc_component *component = dai->component;
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
unsigned int fmt;
unsigned int sample_min; unsigned int sample_min;
unsigned int channel_max; unsigned int channel_max;
unsigned int channel_maxs[] = { unsigned int channel_maxs[] = {
6, /* rx */ 8, /* DAC */
8 /* tx */ 6 /* ADC */
}; };
if (tx)
fmt = pcm3168a->dac_fmt;
else
fmt = pcm3168a->adc_fmt;
/* /*
* Available Data Bits * Available Data Bits
* *
@ -578,7 +555,7 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream,
* I2S * I2S
* LEFT_J * LEFT_J
*/ */
switch (fmt) { switch (pcm3168a->io_params[dai->id].fmt) {
case PCM3168A_FMT_RIGHT_J: case PCM3168A_FMT_RIGHT_J:
sample_min = 16; sample_min = 16;
channel_max = 2; channel_max = 2;
@ -588,7 +565,7 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream,
case PCM3168A_FMT_DSP_A: case PCM3168A_FMT_DSP_A:
case PCM3168A_FMT_DSP_B: case PCM3168A_FMT_DSP_B:
sample_min = 24; sample_min = 24;
channel_max = channel_maxs[tx]; channel_max = channel_maxs[dai->id];
break; break;
default: default:
sample_min = 24; sample_min = 24;
@ -599,32 +576,29 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream,
SNDRV_PCM_HW_PARAM_SAMPLE_BITS, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
sample_min, 32); sample_min, 32);
/* Allow all channels in multi DIN/DOUT mode */
if (pcm3168a->io_params[dai->id].tdm_slots == 2)
channel_max = channel_maxs[dai->id];
snd_pcm_hw_constraint_minmax(substream->runtime, snd_pcm_hw_constraint_minmax(substream->runtime,
SNDRV_PCM_HW_PARAM_CHANNELS, SNDRV_PCM_HW_PARAM_CHANNELS,
2, channel_max); 2, channel_max);
return 0; return 0;
} }
static const struct snd_soc_dai_ops pcm3168a_dac_dai_ops = { static const struct snd_soc_dai_ops pcm3168a_dai_ops = {
.startup = pcm3168a_startup, .startup = pcm3168a_startup,
.set_fmt = pcm3168a_set_dai_fmt_dac, .set_fmt = pcm3168a_set_dai_fmt,
.set_sysclk = pcm3168a_set_dai_sysclk, .set_sysclk = pcm3168a_set_dai_sysclk,
.hw_params = pcm3168a_hw_params, .hw_params = pcm3168a_hw_params,
.digital_mute = pcm3168a_digital_mute, .digital_mute = pcm3168a_digital_mute,
.set_tdm_slot = pcm3168a_set_tdm_slot, .set_tdm_slot = pcm3168a_set_tdm_slot,
}; };
static const struct snd_soc_dai_ops pcm3168a_adc_dai_ops = {
.startup = pcm3168a_startup,
.set_fmt = pcm3168a_set_dai_fmt_adc,
.set_sysclk = pcm3168a_set_dai_sysclk,
.hw_params = pcm3168a_hw_params,
.set_tdm_slot = pcm3168a_set_tdm_slot,
};
static struct snd_soc_dai_driver pcm3168a_dais[] = { static struct snd_soc_dai_driver pcm3168a_dais[] = {
{ {
.name = "pcm3168a-dac", .name = "pcm3168a-dac",
.id = PCM3168A_DAI_DAC,
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
.channels_min = 1, .channels_min = 1,
@ -632,10 +606,11 @@ static struct snd_soc_dai_driver pcm3168a_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000, .rates = SNDRV_PCM_RATE_8000_192000,
.formats = PCM3168A_FORMATS .formats = PCM3168A_FORMATS
}, },
.ops = &pcm3168a_dac_dai_ops .ops = &pcm3168a_dai_ops
}, },
{ {
.name = "pcm3168a-adc", .name = "pcm3168a-adc",
.id = PCM3168A_DAI_ADC,
.capture = { .capture = {
.stream_name = "Capture", .stream_name = "Capture",
.channels_min = 1, .channels_min = 1,
@ -643,7 +618,7 @@ static struct snd_soc_dai_driver pcm3168a_dais[] = {
.rates = SNDRV_PCM_RATE_8000_96000, .rates = SNDRV_PCM_RATE_8000_96000,
.formats = PCM3168A_FORMATS .formats = PCM3168A_FORMATS
}, },
.ops = &pcm3168a_adc_dai_ops .ops = &pcm3168a_dai_ops
}, },
}; };

View File

@ -432,7 +432,6 @@ static int rk3328_platform_probe(struct platform_device *pdev)
{ {
struct device_node *rk3328_np = pdev->dev.of_node; struct device_node *rk3328_np = pdev->dev.of_node;
struct rk3328_codec_priv *rk3328; struct rk3328_codec_priv *rk3328;
struct resource *res;
struct regmap *grf; struct regmap *grf;
void __iomem *base; void __iomem *base;
int ret = 0; int ret = 0;
@ -482,8 +481,7 @@ static int rk3328_platform_probe(struct platform_device *pdev)
return ret; return ret;
} }
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);

View File

@ -978,9 +978,6 @@ static bool rt1011_readable_register(struct device *dev, unsigned int reg)
} }
} }
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -9435, 37, 0);
static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1739, 37, 0);
static const char * const rt1011_din_source_select[] = { static const char * const rt1011_din_source_select[] = {
"Left", "Left",
"Right", "Right",
@ -1029,6 +1026,8 @@ static const char * const rt1011_tdm_adc_swap_select[] = {
static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc1_1_enum, RT1011_TDM1_SET_3, 6, static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc1_1_enum, RT1011_TDM1_SET_3, 6,
rt1011_tdm_adc_swap_select); rt1011_tdm_adc_swap_select);
static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc2_1_enum, RT1011_TDM1_SET_3, 4,
rt1011_tdm_adc_swap_select);
static void rt1011_reset(struct regmap *regmap) static void rt1011_reset(struct regmap *regmap)
{ {
@ -1223,7 +1222,10 @@ static int rt1011_bq_drc_info(struct snd_kcontrol *kcontrol,
static int rt1011_r0_cali_get(struct snd_kcontrol *kcontrol, static int rt1011_r0_cali_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
ucontrol->value.integer.value[0] = 0; struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
ucontrol->value.integer.value[0] = rt1011->cali_done;
return 0; return 0;
} }
@ -1237,6 +1239,7 @@ static int rt1011_r0_cali_put(struct snd_kcontrol *kcontrol,
if (!component->card->instantiated) if (!component->card->instantiated)
return 0; return 0;
rt1011->cali_done = 0;
if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF && if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF &&
ucontrol->value.integer.value[0]) ucontrol->value.integer.value[0])
rt1011_calibrate(rt1011, 1); rt1011_calibrate(rt1011, 1);
@ -1333,7 +1336,8 @@ static const struct snd_kcontrol_new rt1011_snd_controls[] = {
/* TDM1 Data Out Selection */ /* TDM1 Data Out Selection */
SOC_ENUM("TDM1 DOUT Source", rt1011_tdm1_adc1_dat_enum), SOC_ENUM("TDM1 DOUT Source", rt1011_tdm1_adc1_dat_enum),
SOC_ENUM("TDM1 DOUT Location", rt1011_tdm1_adc1_loc_enum), SOC_ENUM("TDM1 DOUT Location", rt1011_tdm1_adc1_loc_enum),
SOC_ENUM("TDM1 ADCDAT Swap Select", rt1011_tdm_adc1_1_enum), SOC_ENUM("TDM1 ADC1DAT Swap Select", rt1011_tdm_adc1_1_enum),
SOC_ENUM("TDM1 ADC2DAT Swap Select", rt1011_tdm_adc2_1_enum),
/* Data Out Mode */ /* Data Out Mode */
SOC_ENUM("I2S ADC DOUT Mode", rt1011_adc_dout_mode_enum), SOC_ENUM("I2S ADC DOUT Mode", rt1011_adc_dout_mode_enum),
@ -1355,6 +1359,10 @@ static const struct snd_kcontrol_new rt1011_snd_controls[] = {
SOC_SINGLE_EXT("R0 Calibration", SND_SOC_NOPM, 0, 1, 0, SOC_SINGLE_EXT("R0 Calibration", SND_SOC_NOPM, 0, 1, 0,
rt1011_r0_cali_get, rt1011_r0_cali_put), rt1011_r0_cali_get, rt1011_r0_cali_put),
RT1011_R0_LOAD("R0 Load Mode"), RT1011_R0_LOAD("R0 Load Mode"),
/* R0 temperature */
SOC_SINGLE("R0 Temperature", RT1011_STP_INITIAL_RESISTANCE_TEMP,
2, 255, 0),
}; };
static int rt1011_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, static int rt1011_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
@ -1511,7 +1519,8 @@ static const struct snd_soc_dapm_route rt1011_dapm_routes[] = {
static int rt1011_get_clk_info(int sclk, int rate) static int rt1011_get_clk_info(int sclk, int rate)
{ {
int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; int i;
static const int pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
if (sclk <= 0 || rate <= 0) if (sclk <= 0 || rate <= 0)
return -EINVAL; return -EINVAL;
@ -2139,6 +2148,7 @@ static int rt1011_calibrate(struct rt1011_priv *rt1011, unsigned char cali_flag)
r0_factor = ((format / r0[0] * 100) / 128) r0_factor = ((format / r0[0] * 100) / 128)
- (r0_integer * 100); - (r0_integer * 100);
rt1011->r0_reg = r0[0]; rt1011->r0_reg = r0[0];
rt1011->cali_done = 1;
dev_info(dev, "r0 resistance about %d.%02d ohm, reg=0x%X\n", dev_info(dev, "r0 resistance about %d.%02d ohm, reg=0x%X\n",
r0_integer, r0_factor, r0[0]); r0_integer, r0_factor, r0[0]);
} }
@ -2189,6 +2199,13 @@ static void rt1011_calibration_work(struct work_struct *work)
rt1011_calibrate(rt1011, 1); rt1011_calibrate(rt1011, 1);
/*
* This flag should reset after booting.
* The factory test will do calibration again and use this flag to check
* whether the calibration completed
*/
rt1011->cali_done = 0;
/* initial */ /* initial */
rt1011_reg_init(component); rt1011_reg_init(component);
} }

View File

@ -227,6 +227,7 @@
#define RT1011_STP_CALIB_RS_TEMP 0x152a #define RT1011_STP_CALIB_RS_TEMP 0x152a
#define RT1011_INIT_RECIPROCAL_REG_24_16 0x1538 #define RT1011_INIT_RECIPROCAL_REG_24_16 0x1538
#define RT1011_INIT_RECIPROCAL_REG_15_0 0x1539 #define RT1011_INIT_RECIPROCAL_REG_15_0 0x1539
#define RT1011_STP_INITIAL_RESISTANCE_TEMP 0x153c
#define RT1011_STP_ALPHA_RECIPROCAL_MSB 0x153e #define RT1011_STP_ALPHA_RECIPROCAL_MSB 0x153e
#define RT1011_SPK_RESISTANCE_1 0x1544 #define RT1011_SPK_RESISTANCE_1 0x1544
#define RT1011_SPK_RESISTANCE_2 0x1546 #define RT1011_SPK_RESISTANCE_2 0x1546
@ -665,7 +666,7 @@ struct rt1011_priv {
int pll_out; int pll_out;
int bq_drc_set; int bq_drc_set;
unsigned int r0_reg; unsigned int r0_reg, cali_done;
int recv_spk_mode; int recv_spk_mode;
}; };

View File

@ -608,7 +608,8 @@ static const struct snd_soc_dapm_route rt1305_dapm_routes[] = {
static int rt1305_get_clk_info(int sclk, int rate) static int rt1305_get_clk_info(int sclk, int rate)
{ {
int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; int i;
static const int pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
if (sclk <= 0 || rate <= 0) if (sclk <= 0 || rate <= 0)
return -EINVAL; return -EINVAL;

View File

@ -1,13 +1,10 @@
/* // SPDX-License-Identifier: GPL-2.0
* rt1308.c -- RT1308 ALSA SoC amplifier component driver //
* // rt1308.c -- RT1308 ALSA SoC amplifier component driver
* Copyright 2019 Realtek Semiconductor Corp. //
* Author: Derek Fang <derek.fang@realtek.com> // Copyright 2019 Realtek Semiconductor Corp.
* // Author: Derek Fang <derek.fang@realtek.com>
* This program is free software; you can redistribute it and/or modify //
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
@ -40,10 +37,10 @@ static const struct reg_sequence init_list[] = {
{ RT1308_VREF, 0x18100000 }, { RT1308_VREF, 0x18100000 },
{ RT1308_IV_SENSE, 0x87010000 }, { RT1308_IV_SENSE, 0x87010000 },
{ RT1308_DUMMY_REG, 0x00000200 }, { RT1308_DUMMY_REG, 0x00000200 },
{ RT1308_SIL_DET, 0x61c30000 }, { RT1308_SIL_DET, 0xe1c30000 },
{ RT1308_DC_CAL_2, 0x00ffff00 }, { RT1308_DC_CAL_2, 0x00ffff00 },
{ RT1308_CLK_DET, 0x01000000 }, { RT1308_CLK_DET, 0x01000000 },
{ RT1308_POWER_STATUS, 0x00800000 }, { RT1308_POWER_STATUS, 0x08800000 },
{ RT1308_DAC_SET, 0xafaf0700 }, { RT1308_DAC_SET, 0xafaf0700 },
}; };
@ -308,12 +305,13 @@ static int rt1308_classd_event(struct snd_soc_dapm_widget *w,
case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_POST_PMU:
msleep(30); msleep(30);
snd_soc_component_update_bits(component, RT1308_POWER_STATUS, snd_soc_component_update_bits(component, RT1308_POWER_STATUS,
RT1308_POW_PDB_REG_BIT, RT1308_POW_PDB_REG_BIT); RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT,
RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT);
msleep(40); msleep(40);
break; break;
case SND_SOC_DAPM_PRE_PMD: case SND_SOC_DAPM_PRE_PMD:
snd_soc_component_update_bits(component, RT1308_POWER_STATUS, snd_soc_component_update_bits(component, RT1308_POWER_STATUS,
RT1308_POW_PDB_REG_BIT, 0); RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT, 0);
usleep_range(150000, 200000); usleep_range(150000, 200000);
break; break;
@ -438,7 +436,8 @@ static const struct snd_soc_dapm_route rt1308_dapm_routes[] = {
static int rt1308_get_clk_info(int sclk, int rate) static int rt1308_get_clk_info(int sclk, int rate)
{ {
int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; int i;
static const int pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
if (sclk <= 0 || rate <= 0) if (sclk <= 0 || rate <= 0)
return -EINVAL; return -EINVAL;
@ -808,33 +807,11 @@ static void rt1308_efuse(struct rt1308_priv *rt1308)
{ {
regmap_write(rt1308->regmap, RT1308_RESET, 0); regmap_write(rt1308->regmap, RT1308_RESET, 0);
regmap_write(rt1308->regmap, RT1308_POWER, 0xff371600);
regmap_write(rt1308->regmap, RT1308_CLK_1, 0x52100000);
regmap_write(rt1308->regmap, RT1308_I2C_I2S_SDW_SET, 0x01014005);
regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x227f5501);
regmap_write(rt1308->regmap, RT1308_PADS_1, 0x50150505);
regmap_write(rt1308->regmap, RT1308_VREF, 0x18100000);
regmap_write(rt1308->regmap, RT1308_IV_SENSE, 0x87010000);
regmap_write(rt1308->regmap, RT1308_DUMMY_REG, 0x00000200);
regmap_write(rt1308->regmap, RT1308_SIL_DET, 0x61c30000);
regmap_write(rt1308->regmap, RT1308_CLK_DET, 0x03700000);
regmap_write(rt1308->regmap, RT1308_SINE_TONE_GEN_1, 0x50022f00);
regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x01800000); regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x01800000);
regmap_write(rt1308->regmap, RT1308_DC_CAL_2, 0x00ffff00);
regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x607e5501);
regmap_write(rt1308->regmap, RT1308_CLK_2, 0x0060e000);
regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x04fe0f00);
msleep(100); msleep(100);
regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x44fe0f00); regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x44fe0f00);
msleep(20); msleep(20);
regmap_write(rt1308->regmap, RT1308_PVDD_OFFSET_CTL, 0x10000000); regmap_write(rt1308->regmap, RT1308_PVDD_OFFSET_CTL, 0x10000000);
regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x00800000);
regmap_write(rt1308->regmap, RT1308_POWER, 0x0);
regmap_write(rt1308->regmap, RT1308_CLK_1, 0x52000000);
regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x227f5501);
regmap_write(rt1308->regmap, RT1308_SINE_TONE_GEN_1, 0x10022f00);
} }
static int rt1308_i2c_probe(struct i2c_client *i2c, static int rt1308_i2c_probe(struct i2c_client *i2c,

View File

@ -1,12 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* /*
* RT1308.h -- RT1308 ALSA SoC amplifier component driver * rt1308.h -- RT1308 ALSA SoC amplifier component driver
* *
* Copyright 2019 Realtek Semiconductor Corp. * Copyright 2019 Realtek Semiconductor Corp.
* Author: Derek Fang <derek.fang@realtek.com> * Author: Derek Fang <derek.fang@realtek.com>
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/ */
#ifndef _RT1308_H_ #ifndef _RT1308_H_

View File

@ -2566,7 +2566,7 @@ static int set_dmic_power(struct snd_soc_dapm_widget *w,
return 0; return 0;
} }
static int rt5655_set_verf(struct snd_soc_dapm_widget *w, static int rt5665_set_verf(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event) struct snd_kcontrol *kcontrol, int event)
{ {
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
@ -2686,11 +2686,11 @@ static const struct snd_soc_dapm_widget rt5665_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5665_PWR_VOL, SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5665_PWR_VOL,
RT5665_PWR_MIC_DET_BIT, 0, NULL, 0), RT5665_PWR_MIC_DET_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Vref1", RT5665_PWR_ANLG_1, RT5665_PWR_VREF1_BIT, 0, SND_SOC_DAPM_SUPPLY("Vref1", RT5665_PWR_ANLG_1, RT5665_PWR_VREF1_BIT, 0,
rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), rt5665_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("Vref2", RT5665_PWR_ANLG_1, RT5665_PWR_VREF2_BIT, 0, SND_SOC_DAPM_SUPPLY("Vref2", RT5665_PWR_ANLG_1, RT5665_PWR_VREF2_BIT, 0,
rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), rt5665_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("Vref3", RT5665_PWR_ANLG_1, RT5665_PWR_VREF3_BIT, 0, SND_SOC_DAPM_SUPPLY("Vref3", RT5665_PWR_ANLG_1, RT5665_PWR_VREF3_BIT, 0,
rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), rt5665_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
/* ASRC */ /* ASRC */
SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5665_ASRC_1, SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5665_ASRC_1,

View File

@ -691,10 +691,12 @@ static void rt5677_set_dsp_mode(struct snd_soc_component *component, bool on)
struct rt5677_priv *rt5677 = snd_soc_component_get_drvdata(component); struct rt5677_priv *rt5677 = snd_soc_component_get_drvdata(component);
if (on) { if (on) {
regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, 0x2, 0x2); regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1,
RT5677_PWR_DSP, RT5677_PWR_DSP);
rt5677->is_dsp_mode = true; rt5677->is_dsp_mode = true;
} else { } else {
regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, 0x2, 0x0); regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1,
RT5677_PWR_DSP, 0x0);
rt5677->is_dsp_mode = false; rt5677->is_dsp_mode = false;
} }
} }
@ -4466,7 +4468,8 @@ static int rt5677_set_bias_level(struct snd_soc_component *component,
regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1, regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1,
RT5677_LDO1_SEL_MASK | RT5677_LDO2_SEL_MASK, RT5677_LDO1_SEL_MASK | RT5677_LDO2_SEL_MASK,
0x0055); 5 << RT5677_LDO1_SEL_SFT |
5 << RT5677_LDO2_SEL_SFT);
regmap_update_bits(rt5677->regmap, regmap_update_bits(rt5677->regmap,
RT5677_PR_BASE + RT5677_BIAS_CUR4, RT5677_PR_BASE + RT5677_BIAS_CUR4,
0x0f00, 0x0f00); 0x0f00, 0x0f00);
@ -4490,9 +4493,11 @@ static int rt5677_set_bias_level(struct snd_soc_component *component,
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x1, 0x0); regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x1, 0x0);
regmap_write(rt5677->regmap, RT5677_PWR_DIG1, 0x0000); regmap_write(rt5677->regmap, RT5677_PWR_DIG1, 0x0000);
regmap_write(rt5677->regmap, RT5677_PWR_DIG2, 0x0000); regmap_write(rt5677->regmap, RT5677_PWR_ANLG1,
regmap_write(rt5677->regmap, RT5677_PWR_ANLG1, 0x0022); 2 << RT5677_LDO1_SEL_SFT |
regmap_write(rt5677->regmap, RT5677_PWR_ANLG2, 0x0000); 2 << RT5677_LDO2_SEL_SFT);
regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2,
RT5677_PWR_CORE, 0);
regmap_update_bits(rt5677->regmap, regmap_update_bits(rt5677->regmap,
RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0000); RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0000);
@ -4719,7 +4724,8 @@ static int rt5677_probe(struct snd_soc_component *component)
regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC,
~RT5677_IRQ_DEBOUNCE_SEL_MASK, 0x0020); ~RT5677_IRQ_DEBOUNCE_SEL_MASK, 0x0020);
regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x0c00); regmap_write(rt5677->regmap, RT5677_PWR_DSP2,
RT5677_PWR_SLIM_ISO | RT5677_PWR_CORE_ISO);
for (i = 0; i < RT5677_GPIO_NUM; i++) for (i = 0; i < RT5677_GPIO_NUM; i++)
rt5677_gpio_config(rt5677, i, rt5677->pdata.gpio_config[i]); rt5677_gpio_config(rt5677, i, rt5677->pdata.gpio_config[i]);

View File

@ -31,6 +31,13 @@
#define SGTL5000_DAP_REG_OFFSET 0x0100 #define SGTL5000_DAP_REG_OFFSET 0x0100
#define SGTL5000_MAX_REG_OFFSET 0x013A #define SGTL5000_MAX_REG_OFFSET 0x013A
/* Delay for the VAG ramp up */
#define SGTL5000_VAG_POWERUP_DELAY 500 /* ms */
/* Delay for the VAG ramp down */
#define SGTL5000_VAG_POWERDOWN_DELAY 500 /* ms */
#define SGTL5000_OUTPUTS_MUTE (SGTL5000_HP_MUTE | SGTL5000_LINE_OUT_MUTE)
/* default value of sgtl5000 registers */ /* default value of sgtl5000 registers */
static const struct reg_default sgtl5000_reg_defaults[] = { static const struct reg_default sgtl5000_reg_defaults[] = {
{ SGTL5000_CHIP_DIG_POWER, 0x0000 }, { SGTL5000_CHIP_DIG_POWER, 0x0000 },
@ -123,6 +130,13 @@ enum {
I2S_SCLK_STRENGTH_HIGH, I2S_SCLK_STRENGTH_HIGH,
}; };
enum {
HP_POWER_EVENT,
DAC_POWER_EVENT,
ADC_POWER_EVENT,
LAST_POWER_EVENT = ADC_POWER_EVENT
};
/* sgtl5000 private structure in codec */ /* sgtl5000 private structure in codec */
struct sgtl5000_priv { struct sgtl5000_priv {
int sysclk; /* sysclk rate */ int sysclk; /* sysclk rate */
@ -137,8 +151,109 @@ struct sgtl5000_priv {
u8 micbias_voltage; u8 micbias_voltage;
u8 lrclk_strength; u8 lrclk_strength;
u8 sclk_strength; u8 sclk_strength;
u16 mute_state[LAST_POWER_EVENT + 1];
}; };
static inline int hp_sel_input(struct snd_soc_component *component)
{
return (snd_soc_component_read32(component, SGTL5000_CHIP_ANA_CTRL) &
SGTL5000_HP_SEL_MASK) >> SGTL5000_HP_SEL_SHIFT;
}
static inline u16 mute_output(struct snd_soc_component *component,
u16 mute_mask)
{
u16 mute_reg = snd_soc_component_read32(component,
SGTL5000_CHIP_ANA_CTRL);
snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL,
mute_mask, mute_mask);
return mute_reg;
}
static inline void restore_output(struct snd_soc_component *component,
u16 mute_mask, u16 mute_reg)
{
snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL,
mute_mask, mute_reg);
}
static void vag_power_on(struct snd_soc_component *component, u32 source)
{
if (snd_soc_component_read32(component, SGTL5000_CHIP_ANA_POWER) &
SGTL5000_VAG_POWERUP)
return;
snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER,
SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP);
/* When VAG powering on to get local loop from Line-In, the sleep
* is required to avoid loud pop.
*/
if (hp_sel_input(component) == SGTL5000_HP_SEL_LINE_IN &&
source == HP_POWER_EVENT)
msleep(SGTL5000_VAG_POWERUP_DELAY);
}
static int vag_power_consumers(struct snd_soc_component *component,
u16 ana_pwr_reg, u32 source)
{
int consumers = 0;
/* count dac/adc consumers unconditional */
if (ana_pwr_reg & SGTL5000_DAC_POWERUP)
consumers++;
if (ana_pwr_reg & SGTL5000_ADC_POWERUP)
consumers++;
/*
* If the event comes from HP and Line-In is selected,
* current action is 'DAC to be powered down'.
* As HP_POWERUP is not set when HP muxed to line-in,
* we need to keep VAG power ON.
*/
if (source == HP_POWER_EVENT) {
if (hp_sel_input(component) == SGTL5000_HP_SEL_LINE_IN)
consumers++;
} else {
if (ana_pwr_reg & SGTL5000_HP_POWERUP)
consumers++;
}
return consumers;
}
static void vag_power_off(struct snd_soc_component *component, u32 source)
{
u16 ana_pwr = snd_soc_component_read32(component,
SGTL5000_CHIP_ANA_POWER);
if (!(ana_pwr & SGTL5000_VAG_POWERUP))
return;
/*
* This function calls when any of VAG power consumers is disappearing.
* Thus, if there is more than one consumer at the moment, as minimum
* one consumer will definitely stay after the end of the current
* event.
* Don't clear VAG_POWERUP if 2 or more consumers of VAG present:
* - LINE_IN (for HP events) / HP (for DAC/ADC events)
* - DAC
* - ADC
* (the current consumer is disappearing right now)
*/
if (vag_power_consumers(component, ana_pwr, source) >= 2)
return;
snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER,
SGTL5000_VAG_POWERUP, 0);
/* In power down case, we need wait 400-1000 ms
* when VAG fully ramped down.
* As longer we wait, as smaller pop we've got.
*/
msleep(SGTL5000_VAG_POWERDOWN_DELAY);
}
/* /*
* mic_bias power on/off share the same register bits with * mic_bias power on/off share the same register bits with
* output impedance of mic bias, when power on mic bias, we * output impedance of mic bias, when power on mic bias, we
@ -170,36 +285,46 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w,
return 0; return 0;
} }
/* static int vag_and_mute_control(struct snd_soc_component *component,
* As manual described, ADC/DAC only works when VAG powerup, int event, int event_source)
* So enabled VAG before ADC/DAC up.
* In power down case, we need wait 400ms when vag fully ramped down.
*/
static int power_vag_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{ {
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); static const u16 mute_mask[] = {
const u32 mask = SGTL5000_DAC_POWERUP | SGTL5000_ADC_POWERUP; /*
* Mask for HP_POWER_EVENT.
* Muxing Headphones have to be wrapped with mute/unmute
* headphones only.
*/
SGTL5000_HP_MUTE,
/*
* Masks for DAC_POWER_EVENT/ADC_POWER_EVENT.
* Muxing DAC or ADC block have to wrapped with mute/unmute
* both headphones and line-out.
*/
SGTL5000_OUTPUTS_MUTE,
SGTL5000_OUTPUTS_MUTE
};
struct sgtl5000_priv *sgtl5000 =
snd_soc_component_get_drvdata(component);
switch (event) { switch (event) {
case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_PRE_PMU:
snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER, sgtl5000->mute_state[event_source] =
SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); mute_output(component, mute_mask[event_source]);
msleep(400); break;
case SND_SOC_DAPM_POST_PMU:
vag_power_on(component, event_source);
restore_output(component, mute_mask[event_source],
sgtl5000->mute_state[event_source]);
break; break;
case SND_SOC_DAPM_PRE_PMD: case SND_SOC_DAPM_PRE_PMD:
/* sgtl5000->mute_state[event_source] =
* Don't clear VAG_POWERUP, when both DAC and ADC are mute_output(component, mute_mask[event_source]);
* operational to prevent inadvertently starving the vag_power_off(component, event_source);
* other one of them. break;
*/ case SND_SOC_DAPM_POST_PMD:
if ((snd_soc_component_read32(component, SGTL5000_CHIP_ANA_POWER) & restore_output(component, mute_mask[event_source],
mask) != mask) { sgtl5000->mute_state[event_source]);
snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER,
SGTL5000_VAG_POWERUP, 0);
msleep(400);
}
break; break;
default: default:
break; break;
@ -208,6 +333,41 @@ static int power_vag_event(struct snd_soc_dapm_widget *w,
return 0; return 0;
} }
/*
* Mute Headphone when power it up/down.
* Control VAG power on HP power path.
*/
static int headphone_pga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
return vag_and_mute_control(component, event, HP_POWER_EVENT);
}
/* As manual describes, ADC/DAC powering up/down requires
* to mute outputs to avoid pops.
* Control VAG power on ADC/DAC power path.
*/
static int adc_updown_depop(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
return vag_and_mute_control(component, event, ADC_POWER_EVENT);
}
static int dac_updown_depop(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
return vag_and_mute_control(component, event, DAC_POWER_EVENT);
}
/* input sources for ADC */ /* input sources for ADC */
static const char *adc_mux_text[] = { static const char *adc_mux_text[] = {
"MIC_IN", "LINE_IN" "MIC_IN", "LINE_IN"
@ -280,7 +440,10 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = {
mic_bias_event, mic_bias_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_PGA("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0), SND_SOC_DAPM_PGA_E("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0,
headphone_pga_event,
SND_SOC_DAPM_PRE_POST_PMU |
SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_PGA("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0),
SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, &adc_mux), SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, &adc_mux),
@ -301,11 +464,12 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = {
0, SGTL5000_CHIP_DIG_POWER, 0, SGTL5000_CHIP_DIG_POWER,
1, 0), 1, 0),
SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0), SND_SOC_DAPM_ADC_E("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0,
SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0), adc_updown_depop, SND_SOC_DAPM_PRE_POST_PMU |
SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_PRE("VAG_POWER_PRE", power_vag_event), SND_SOC_DAPM_DAC_E("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0,
SND_SOC_DAPM_POST("VAG_POWER_POST", power_vag_event), dac_updown_depop, SND_SOC_DAPM_PRE_POST_PMU |
SND_SOC_DAPM_PRE_POST_PMD),
}; };
/* routes for sgtl5000 */ /* routes for sgtl5000 */
@ -556,6 +720,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = {
SGTL5000_CHIP_ANA_ADC_CTRL, SGTL5000_CHIP_ANA_ADC_CTRL,
8, 1, 0, capture_6db_attenuate), 8, 1, 0, capture_6db_attenuate),
SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0), SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0),
SOC_SINGLE("Capture Switch", SGTL5000_CHIP_ANA_CTRL, 0, 1, 1),
SOC_DOUBLE_TLV("Headphone Playback Volume", SOC_DOUBLE_TLV("Headphone Playback Volume",
SGTL5000_CHIP_ANA_HP_CTRL, SGTL5000_CHIP_ANA_HP_CTRL,
@ -1173,12 +1338,17 @@ static int sgtl5000_set_power_regs(struct snd_soc_component *component)
SGTL5000_INT_OSC_EN); SGTL5000_INT_OSC_EN);
/* Enable VDDC charge pump */ /* Enable VDDC charge pump */
ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP; ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP;
} else if (vddio >= 3100 && vdda >= 3100) { } else {
ana_pwr &= ~SGTL5000_VDDC_CHRGPMP_POWERUP; ana_pwr &= ~SGTL5000_VDDC_CHRGPMP_POWERUP;
/* VDDC use VDDIO rail */ /*
lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD; * if vddio == vdda the source of charge pump should be
lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO << * assigned manually to VDDIO
SGTL5000_VDDC_MAN_ASSN_SHIFT; */
if (vddio == vdda) {
lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD;
lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO <<
SGTL5000_VDDC_MAN_ASSN_SHIFT;
}
} }
snd_soc_component_write(component, SGTL5000_CHIP_LINREG_CTRL, lreg_ctrl); snd_soc_component_write(component, SGTL5000_CHIP_LINREG_CTRL, lreg_ctrl);
@ -1288,6 +1458,7 @@ static int sgtl5000_probe(struct snd_soc_component *component)
int ret; int ret;
u16 reg; u16 reg;
struct sgtl5000_priv *sgtl5000 = snd_soc_component_get_drvdata(component); struct sgtl5000_priv *sgtl5000 = snd_soc_component_get_drvdata(component);
unsigned int zcd_mask = SGTL5000_HP_ZCD_EN | SGTL5000_ADC_ZCD_EN;
/* power up sgtl5000 */ /* power up sgtl5000 */
ret = sgtl5000_set_power_regs(component); ret = sgtl5000_set_power_regs(component);
@ -1296,7 +1467,7 @@ static int sgtl5000_probe(struct snd_soc_component *component)
/* enable small pop, introduce 400ms delay in turning off */ /* enable small pop, introduce 400ms delay in turning off */
snd_soc_component_update_bits(component, SGTL5000_CHIP_REF_CTRL, snd_soc_component_update_bits(component, SGTL5000_CHIP_REF_CTRL,
SGTL5000_SMALL_POP, 1); SGTL5000_SMALL_POP, SGTL5000_SMALL_POP);
/* disable short cut detector */ /* disable short cut detector */
snd_soc_component_write(component, SGTL5000_CHIP_SHORT_CTRL, 0); snd_soc_component_write(component, SGTL5000_CHIP_SHORT_CTRL, 0);
@ -1315,9 +1486,8 @@ static int sgtl5000_probe(struct snd_soc_component *component)
0x1f); 0x1f);
snd_soc_component_write(component, SGTL5000_CHIP_PAD_STRENGTH, reg); snd_soc_component_write(component, SGTL5000_CHIP_PAD_STRENGTH, reg);
snd_soc_component_write(component, SGTL5000_CHIP_ANA_CTRL, snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL,
SGTL5000_HP_ZCD_EN | zcd_mask, zcd_mask);
SGTL5000_ADC_ZCD_EN);
snd_soc_component_update_bits(component, SGTL5000_CHIP_MIC_CTRL, snd_soc_component_update_bits(component, SGTL5000_CHIP_MIC_CTRL,
SGTL5000_BIAS_R_MASK, SGTL5000_BIAS_R_MASK,

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