mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 21:23:23 +00:00
ASoC: Updates for v4.2
The big thing this release has been Liam's addition of topology support to the core. We've also seen quite a bit of driver work and the continuation of Lars' refactoring for component support. - Support for loading ASoC topology maps from firmware, intended to be used to allow self-describing DSP firmware images to be built which can map controls added by the DSP to userspace without the kernel needing to know about individual DSP firmwares. - Lots of refactoring to avoid direct access to snd_soc_codec where it's not needed supporting future refactoring. - Big refactoring and cleanup serieses for the Wolfson ADSP and TI TAS2552 drivers. - Support for TI TAS571x power amplifiers. - Support for Qualcomm APQ8016 and ZTE ZX296702 SoCs. - Support for x86 systems with RT5650 and Qualcomm Storm. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJVddV1AAoJECTWi3JdVIfQQQsH/RG3lgOeot5jLWMsxJSKChEl KI+aaMcOw6Dj2LDccN8i6vUp8q44cKSXIc7lGLOzJW4K+OydCCGAvE+sJGyRE1dd yOHwcbvjJi4zFlt01RZchJ/Wa/S6zFucl5N9HxWsV4bEtfAA59IuhJLtospUlwsA mf9mpvSdeUAeh3lM2+AqAbXhTo6dYfD5ky5nrtpAkZjG8gqUG0u8Tpauja0lLcHi 72/3EkzKR6KHaefyPw3LdN+/H/YK79uHCVcctZnQg5xUUymcO16ReoTxKwV9cnDb lBJ6wO8RpUAO9evoG2Yj/l4p+czDCm5VkHMq0nPklHVRh7s/2PwKfox1aw4Pumg= =wolq -----END PGP SIGNATURE----- Merge tag 'asoc-v4.2' into asoc-next ASoC: Updates for v4.2 The big thing this release has been Liam's addition of topology support to the core. We've also seen quite a bit of driver work and the continuation of Lars' refactoring for component support. - Support for loading ASoC topology maps from firmware, intended to be used to allow self-describing DSP firmware images to be built which can map controls added by the DSP to userspace without the kernel needing to know about individual DSP firmwares. - Lots of refactoring to avoid direct access to snd_soc_codec where it's not needed supporting future refactoring. - Big refactoring and cleanup serieses for the Wolfson ADSP and TI TAS2552 drivers. - Support for TI TAS571x power amplifiers. - Support for Qualcomm APQ8016 and ZTE ZX296702 SoCs. - Support for x86 systems with RT5650 and Qualcomm Storm. # gpg: Signature made Mon 08 Jun 2015 18:48:37 BST using RSA key ID 5D5487D0 # gpg: Oops: keyid_from_fingerprint: no pubkey # gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>" # gpg: aka "Mark Brown <broonie@debian.org>" # gpg: aka "Mark Brown <broonie@kernel.org>" # gpg: aka "Mark Brown <broonie@tardis.ed.ac.uk>" # gpg: aka "Mark Brown <broonie@linaro.org>" # gpg: aka "Mark Brown <Mark.Brown@linaro.org>"
This commit is contained in:
commit
208a128f6b
@ -20,6 +20,8 @@ Optional properties:
|
||||
pin configurations as described in the datasheet,
|
||||
table 53. Note that the value of this property has
|
||||
to be prefixed with '/bits/ 8'.
|
||||
- avdd-supply: Power supply for AVDD, providing 3.3V
|
||||
- dvdd-supply: Power supply for DVDD, providing 3.3V
|
||||
|
||||
Examples:
|
||||
|
||||
@ -28,6 +30,8 @@ Examples:
|
||||
compatible = "adi,adau1701";
|
||||
reg = <0x34>;
|
||||
reset-gpio = <&gpio 23 0>;
|
||||
avdd-supply = <&vdd_3v3_reg>;
|
||||
dvdd-supply = <&vdd_3v3_reg>;
|
||||
adi,pll-mode-gpios = <&gpio 24 0 &gpio 25 0>;
|
||||
adi,pin-config = /bits/ 8 <0x4 0x7 0x5 0x5 0x4 0x4
|
||||
0x4 0x4 0x4 0x4 0x4 0x4>;
|
||||
|
13
Documentation/devicetree/bindings/sound/bt-sco.txt
Normal file
13
Documentation/devicetree/bindings/sound/bt-sco.txt
Normal file
@ -0,0 +1,13 @@
|
||||
Bluetooth-SCO audio CODEC
|
||||
|
||||
This device support generic Bluetooth SCO link.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "delta,dfbmcs320"
|
||||
|
||||
Example:
|
||||
|
||||
codec: bt_sco {
|
||||
compatible = "delta,dfbmcs320";
|
||||
};
|
13
Documentation/devicetree/bindings/sound/gtm601.txt
Normal file
13
Documentation/devicetree/bindings/sound/gtm601.txt
Normal file
@ -0,0 +1,13 @@
|
||||
GTM601 UMTS modem audio interface CODEC
|
||||
|
||||
This device has no configuration interface. Sample rate is fixed - 8kHz.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "option,gtm601"
|
||||
|
||||
Example:
|
||||
|
||||
codec: gtm601_codec {
|
||||
compatible = "option,gtm601";
|
||||
};
|
@ -18,6 +18,12 @@ Optional properties:
|
||||
|
||||
- maxim,dmic-freq: Frequency at which to clock DMIC
|
||||
|
||||
- maxim,micbias: Micbias voltage applies to the analog mic, valid voltages value are:
|
||||
0 - 2.2v
|
||||
1 - 2.55v
|
||||
2 - 2.4v
|
||||
3 - 2.8v
|
||||
|
||||
Pins on the device (for linking into audio routes):
|
||||
|
||||
* MIC1
|
||||
|
@ -4,12 +4,21 @@ This node models the Qualcomm Technologies Low-Power Audio SubSystem (LPASS).
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "qcom,lpass-cpu"
|
||||
- compatible : "qcom,lpass-cpu" or "qcom,apq8016-lpass-cpu"
|
||||
- clocks : Must contain an entry for each entry in clock-names.
|
||||
- clock-names : A list which must include the following entries:
|
||||
* "ahbix-clk"
|
||||
* "mi2s-osr-clk"
|
||||
* "mi2s-bit-clk"
|
||||
: required clocks for "qcom,lpass-cpu-apq8016"
|
||||
* "ahbix-clk"
|
||||
* "mi2s-bit-clk0"
|
||||
* "mi2s-bit-clk1"
|
||||
* "mi2s-bit-clk2"
|
||||
* "mi2s-bit-clk3"
|
||||
* "pcnoc-mport-clk"
|
||||
* "pcnoc-sway-clk"
|
||||
|
||||
- interrupts : Must contain an entry for each entry in
|
||||
interrupt-names.
|
||||
- interrupt-names : A list which must include the following entries:
|
||||
@ -22,6 +31,8 @@ Required properties:
|
||||
- reg-names : A list which must include the following entries:
|
||||
* "lpass-lpaif"
|
||||
|
||||
|
||||
|
||||
Optional properties:
|
||||
|
||||
- qcom,adsp : Phandle for the audio DSP node
|
||||
|
@ -48,7 +48,7 @@ DAI subnode properties:
|
||||
|
||||
Example:
|
||||
|
||||
rcar_sound: rcar_sound@ec500000 {
|
||||
rcar_sound: sound@ec500000 {
|
||||
#sound-dai-cells = <1>;
|
||||
compatible = "renesas,rcar_sound-r8a7791", "renesas,rcar_sound-gen2";
|
||||
reg = <0 0xec500000 0 0x1000>, /* SCU */
|
||||
|
@ -18,6 +18,7 @@ Required properties:
|
||||
Optional properties:
|
||||
|
||||
- realtek,pow-ldo2-gpio : The GPIO that controls the CODEC's POW_LDO2 pin.
|
||||
- realtek,reset-gpio : The GPIO that controls the CODEC's RESET pin.
|
||||
|
||||
- realtek,in1-differential
|
||||
- realtek,in2-differential
|
||||
@ -70,6 +71,7 @@ rt5677 {
|
||||
|
||||
realtek,pow-ldo2-gpio =
|
||||
<&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>;
|
||||
realtek,reset-gpio = <&gpio TEGRA_GPIO(BB, 3) GPIO_ACTIVE_LOW>;
|
||||
realtek,in1-differential = "true";
|
||||
realtek,gpio-config = /bits/ 8 <0 0 0 0 0 2>; /* pull up GPIO6 */
|
||||
realtek,jd2-gpio = <3>; /* Enables Jack detection for GPIO6 */
|
||||
|
41
Documentation/devicetree/bindings/sound/tas571x.txt
Normal file
41
Documentation/devicetree/bindings/sound/tas571x.txt
Normal file
@ -0,0 +1,41 @@
|
||||
Texas Instruments TAS5711/TAS5717/TAS5719 stereo power amplifiers
|
||||
|
||||
The codec is controlled through an I2C interface. It also has two other
|
||||
signals that can be wired up to GPIOs: reset (strongly recommended), and
|
||||
powerdown (optional).
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: "ti,tas5711", "ti,tas5717", or "ti,tas5719"
|
||||
- reg: The I2C address of the device
|
||||
- #sound-dai-cells: must be equal to 0
|
||||
|
||||
Optional properties:
|
||||
|
||||
- reset-gpios: GPIO specifier for the TAS571x's active low reset line
|
||||
- pdn-gpios: GPIO specifier for the TAS571x's active low powerdown line
|
||||
- clocks: clock phandle for the MCLK input
|
||||
- clock-names: should be "mclk"
|
||||
- AVDD-supply: regulator phandle for the AVDD supply (all chips)
|
||||
- DVDD-supply: regulator phandle for the DVDD supply (all chips)
|
||||
- HPVDD-supply: regulator phandle for the HPVDD supply (5717/5719)
|
||||
- PVDD_AB-supply: regulator phandle for the PVDD_AB supply (5717/5719)
|
||||
- PVDD_CD-supply: regulator phandle for the PVDD_CD supply (5717/5719)
|
||||
- PVDD_A-supply: regulator phandle for the PVDD_A supply (5711)
|
||||
- PVDD_B-supply: regulator phandle for the PVDD_B supply (5711)
|
||||
- PVDD_C-supply: regulator phandle for the PVDD_C supply (5711)
|
||||
- PVDD_D-supply: regulator phandle for the PVDD_D supply (5711)
|
||||
|
||||
Example:
|
||||
|
||||
tas5717: audio-codec@2a {
|
||||
compatible = "ti,tas5717";
|
||||
reg = <0x2a>;
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
|
||||
pdn-gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;
|
||||
|
||||
clocks = <&clk_core CLK_I2S>;
|
||||
clock-names = "mclk";
|
||||
};
|
@ -10,9 +10,20 @@ Required properties:
|
||||
- reg : the I2C address of the device for I2C, the chip select
|
||||
number for SPI.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- diff-mode: Differential output mode configuration. Default value for field
|
||||
DIFF in register R8 (MODE_CONTROL_2). If absent, the default is 0, shall be:
|
||||
0 = stereo
|
||||
1 = mono left
|
||||
2 = stereo reversed
|
||||
3 = mono right
|
||||
|
||||
Example:
|
||||
|
||||
codec: wm8741@1a {
|
||||
compatible = "wlf,wm8741";
|
||||
reg = <0x1a>;
|
||||
|
||||
diff-mode = <3>;
|
||||
};
|
||||
|
44
Documentation/devicetree/bindings/sound/zte,zx-i2s.txt
Normal file
44
Documentation/devicetree/bindings/sound/zte,zx-i2s.txt
Normal file
@ -0,0 +1,44 @@
|
||||
ZTE ZX296702 I2S controller
|
||||
|
||||
Required properties:
|
||||
- compatible : Must be "zte,zx296702-i2s"
|
||||
- reg : Must contain I2S core's registers location and length
|
||||
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
|
||||
- clock-names: "tx" for the clock to the I2S interface.
|
||||
- dmas: Pairs of phandle and specifier for the DMA channel that is used by
|
||||
the core. The core expects two dma channels for transmit.
|
||||
- dma-names : Must be "tx" and "rx"
|
||||
|
||||
For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
|
||||
please check:
|
||||
* resource-names.txt
|
||||
* clock/clock-bindings.txt
|
||||
* dma/dma.txt
|
||||
|
||||
Example:
|
||||
i2s0: i2s0@0b005000 {
|
||||
#sound-dai-cells = <0>;
|
||||
compatible = "zte,zx296702-i2s";
|
||||
reg = <0x0b005000 0x1000>;
|
||||
clocks = <&lsp0clk ZX296702_I2S0_DIV>;
|
||||
clock-names = "tx";
|
||||
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dma 5>, <&dma 6>;
|
||||
dma-names = "tx", "rx";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
sound {
|
||||
compatible = "simple-audio-card";
|
||||
simple-audio-card,name = "zx296702_snd";
|
||||
simple-audio-card,format = "left_j";
|
||||
simple-audio-card,bitclock-master = <&sndcodec>;
|
||||
simple-audio-card,frame-master = <&sndcodec>;
|
||||
sndcpu: simple-audio-card,cpu {
|
||||
sound-dai = <&i2s0>;
|
||||
};
|
||||
|
||||
sndcodec: simple-audio-card,codec {
|
||||
sound-dai = <&acodec>;
|
||||
};
|
||||
};
|
28
Documentation/devicetree/bindings/sound/zte,zx-spdif.txt
Normal file
28
Documentation/devicetree/bindings/sound/zte,zx-spdif.txt
Normal file
@ -0,0 +1,28 @@
|
||||
ZTE ZX296702 SPDIF controller
|
||||
|
||||
Required properties:
|
||||
- compatible : Must be "zte,zx296702-spdif"
|
||||
- reg : Must contain SPDIF core's registers location and length
|
||||
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
|
||||
- clock-names: "tx" for the clock to the SPDIF interface.
|
||||
- dmas: Pairs of phandle and specifier for the DMA channel that is used by
|
||||
the core. The core expects one dma channel for transmit.
|
||||
- dma-names : Must be "tx"
|
||||
|
||||
For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
|
||||
please check:
|
||||
* resource-names.txt
|
||||
* clock/clock-bindings.txt
|
||||
* dma/dma.txt
|
||||
|
||||
Example:
|
||||
spdif0: spdif0@0b004000 {
|
||||
compatible = "zte,zx296702-spdif";
|
||||
reg = <0x0b004000 0x1000>;
|
||||
clocks = <&lsp0clk ZX296702_SPDIF0_DIV>;
|
||||
clock-names = "tx";
|
||||
interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dma 4>;
|
||||
dma-names = "tx";
|
||||
status = "okay";
|
||||
};
|
@ -54,6 +54,7 @@ cosmic Cosmic Circuits
|
||||
crystalfontz Crystalfontz America, Inc.
|
||||
dallas Maxim Integrated Products (formerly Dallas Semiconductor)
|
||||
davicom DAVICOM Semiconductor, Inc.
|
||||
delta Delta Electronics, Inc.
|
||||
denx Denx Software Engineering
|
||||
digi Digi International Inc.
|
||||
digilent Diglent, Inc.
|
||||
|
@ -9924,6 +9924,12 @@ L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/ti/netcp*
|
||||
|
||||
TI TAS571X FAMILY ASoC CODEC DRIVER
|
||||
M: Kevin Cernekee <cernekee@chromium.org>
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
S: Odd Fixes
|
||||
F: sound/soc/codecs/tas571x*
|
||||
|
||||
TI TWL4030 SERIES SOC CODEC DRIVER
|
||||
M: Peter Ujfalusi <peter.ujfalusi@ti.com>
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
|
@ -465,6 +465,7 @@ static dma_cookie_t rcar_dmac_tx_submit(struct dma_async_tx_descriptor *tx)
|
||||
static int rcar_dmac_desc_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
|
||||
{
|
||||
struct rcar_dmac_desc_page *page;
|
||||
unsigned long flags;
|
||||
LIST_HEAD(list);
|
||||
unsigned int i;
|
||||
|
||||
@ -482,10 +483,10 @@ static int rcar_dmac_desc_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
|
||||
list_add_tail(&desc->node, &list);
|
||||
}
|
||||
|
||||
spin_lock_irq(&chan->lock);
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
list_splice_tail(&list, &chan->desc.free);
|
||||
list_add_tail(&page->node, &chan->desc.pages);
|
||||
spin_unlock_irq(&chan->lock);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -516,6 +517,7 @@ static void rcar_dmac_desc_put(struct rcar_dmac_chan *chan,
|
||||
static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan)
|
||||
{
|
||||
struct rcar_dmac_desc *desc, *_desc;
|
||||
unsigned long flags;
|
||||
LIST_HEAD(list);
|
||||
|
||||
/*
|
||||
@ -524,9 +526,9 @@ static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan)
|
||||
* list_for_each_entry_safe, isn't safe if we release the channel lock
|
||||
* around the rcar_dmac_desc_put() call.
|
||||
*/
|
||||
spin_lock_irq(&chan->lock);
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
list_splice_init(&chan->desc.wait, &list);
|
||||
spin_unlock_irq(&chan->lock);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
|
||||
list_for_each_entry_safe(desc, _desc, &list, node) {
|
||||
if (async_tx_test_ack(&desc->async_tx)) {
|
||||
@ -539,9 +541,9 @@ static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan)
|
||||
return;
|
||||
|
||||
/* Put the remaining descriptors back in the wait list. */
|
||||
spin_lock_irq(&chan->lock);
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
list_splice(&list, &chan->desc.wait);
|
||||
spin_unlock_irq(&chan->lock);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -556,12 +558,13 @@ static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan)
|
||||
static struct rcar_dmac_desc *rcar_dmac_desc_get(struct rcar_dmac_chan *chan)
|
||||
{
|
||||
struct rcar_dmac_desc *desc;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
/* Recycle acked descriptors before attempting allocation. */
|
||||
rcar_dmac_desc_recycle_acked(chan);
|
||||
|
||||
spin_lock_irq(&chan->lock);
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
|
||||
while (list_empty(&chan->desc.free)) {
|
||||
/*
|
||||
@ -570,17 +573,17 @@ static struct rcar_dmac_desc *rcar_dmac_desc_get(struct rcar_dmac_chan *chan)
|
||||
* allocated descriptors. If the allocation fails return an
|
||||
* error.
|
||||
*/
|
||||
spin_unlock_irq(&chan->lock);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
ret = rcar_dmac_desc_alloc(chan, GFP_NOWAIT);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
spin_lock_irq(&chan->lock);
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
}
|
||||
|
||||
desc = list_first_entry(&chan->desc.free, struct rcar_dmac_desc, node);
|
||||
list_del(&desc->node);
|
||||
|
||||
spin_unlock_irq(&chan->lock);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
|
||||
return desc;
|
||||
}
|
||||
@ -593,6 +596,7 @@ static struct rcar_dmac_desc *rcar_dmac_desc_get(struct rcar_dmac_chan *chan)
|
||||
static int rcar_dmac_xfer_chunk_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
|
||||
{
|
||||
struct rcar_dmac_desc_page *page;
|
||||
unsigned long flags;
|
||||
LIST_HEAD(list);
|
||||
unsigned int i;
|
||||
|
||||
@ -606,10 +610,10 @@ static int rcar_dmac_xfer_chunk_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
|
||||
list_add_tail(&chunk->node, &list);
|
||||
}
|
||||
|
||||
spin_lock_irq(&chan->lock);
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
list_splice_tail(&list, &chan->desc.chunks_free);
|
||||
list_add_tail(&page->node, &chan->desc.pages);
|
||||
spin_unlock_irq(&chan->lock);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -627,9 +631,10 @@ static struct rcar_dmac_xfer_chunk *
|
||||
rcar_dmac_xfer_chunk_get(struct rcar_dmac_chan *chan)
|
||||
{
|
||||
struct rcar_dmac_xfer_chunk *chunk;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irq(&chan->lock);
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
|
||||
while (list_empty(&chan->desc.chunks_free)) {
|
||||
/*
|
||||
@ -638,18 +643,18 @@ rcar_dmac_xfer_chunk_get(struct rcar_dmac_chan *chan)
|
||||
* allocated descriptors. If the allocation fails return an
|
||||
* error.
|
||||
*/
|
||||
spin_unlock_irq(&chan->lock);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
ret = rcar_dmac_xfer_chunk_alloc(chan, GFP_NOWAIT);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
spin_lock_irq(&chan->lock);
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
}
|
||||
|
||||
chunk = list_first_entry(&chan->desc.chunks_free,
|
||||
struct rcar_dmac_xfer_chunk, node);
|
||||
list_del(&chunk->node);
|
||||
|
||||
spin_unlock_irq(&chan->lock);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
@ -78,11 +78,6 @@ static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev,
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = regmap_update_bits(regmap, ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
|
||||
ARIZONA_SUBSYS_MAX_FREQ, val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (val)
|
||||
return 0;
|
||||
|
||||
|
9
include/dt-bindings/sound/apq8016-lpass.h
Normal file
9
include/dt-bindings/sound/apq8016-lpass.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef __DT_APQ8016_LPASS_H
|
||||
#define __DT_APQ8016_LPASS_H
|
||||
|
||||
#define MI2S_PRIMARY 0
|
||||
#define MI2S_SECONDARY 1
|
||||
#define MI2S_TERTIARY 2
|
||||
#define MI2S_QUATERNARY 3
|
||||
|
||||
#endif /* __DT_APQ8016_LPASS_H */
|
9
include/dt-bindings/sound/audio-jack-events.h
Normal file
9
include/dt-bindings/sound/audio-jack-events.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef __AUDIO_JACK_EVENTS_H
|
||||
#define __AUDIO_JACK_EVENTS_H
|
||||
|
||||
#define JACK_HEADPHONE 1
|
||||
#define JACK_MICROPHONE 2
|
||||
#define JACK_LINEOUT 3
|
||||
#define JACK_LINEIN 4
|
||||
|
||||
#endif /* __AUDIO_JACK_EVENTS_H */
|
18
include/dt-bindings/sound/tas2552.h
Normal file
18
include/dt-bindings/sound/tas2552.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef __DT_TAS2552_H
|
||||
#define __DT_TAS2552_H
|
||||
|
||||
#define TAS2552_PLL_CLKIN (0)
|
||||
#define TAS2552_PDM_CLK (1)
|
||||
#define TAS2552_CLK_TARGET_MASK (1)
|
||||
|
||||
#define TAS2552_PLL_CLKIN_MCLK ((0 << 1) | TAS2552_PLL_CLKIN)
|
||||
#define TAS2552_PLL_CLKIN_BCLK ((1 << 1) | TAS2552_PLL_CLKIN)
|
||||
#define TAS2552_PLL_CLKIN_IVCLKIN ((2 << 1) | TAS2552_PLL_CLKIN)
|
||||
#define TAS2552_PLL_CLKIN_1_8_FIXED ((3 << 1) | TAS2552_PLL_CLKIN)
|
||||
|
||||
#define TAS2552_PDM_CLK_PLL ((0 << 1) | TAS2552_PDM_CLK)
|
||||
#define TAS2552_PDM_CLK_IVCLKIN ((1 << 1) | TAS2552_PDM_CLK)
|
||||
#define TAS2552_PDM_CLK_BCLK ((2 << 1) | TAS2552_PDM_CLK)
|
||||
#define TAS2552_PDM_CLK_MCLK ((3 << 1) | TAS2552_PDM_CLK)
|
||||
|
||||
#endif /* __DT_TAS2552_H */
|
@ -90,11 +90,6 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
|
||||
* makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well.
|
||||
*/
|
||||
#define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1)
|
||||
/*
|
||||
* The platforms dmaengine driver does not support reporting the amount of
|
||||
* bytes that are still left to transfer.
|
||||
*/
|
||||
#define SND_DMAENGINE_PCM_FLAG_NO_RESIDUE BIT(2)
|
||||
/*
|
||||
* The PCM is half duplex and the DMA channel is shared between capture and
|
||||
* playback.
|
||||
|
@ -15,7 +15,6 @@ struct rt5645_platform_data {
|
||||
/* IN2 can optionally be differential */
|
||||
bool in2_diff;
|
||||
|
||||
bool dmic_en;
|
||||
unsigned int dmic1_data_pin;
|
||||
/* 0 = IN2N; 1 = GPIO5; 2 = GPIO11 */
|
||||
unsigned int dmic2_data_pin;
|
||||
@ -24,8 +23,6 @@ struct rt5645_platform_data {
|
||||
unsigned int hp_det_gpio;
|
||||
bool gpio_hp_det_active_high;
|
||||
|
||||
/* true if codec's jd function is used */
|
||||
bool en_jd_func;
|
||||
unsigned int jd_mode;
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/soc-topology.h>
|
||||
#include <sound/asoc.h>
|
||||
|
||||
struct device;
|
||||
|
||||
@ -107,6 +109,10 @@ struct device;
|
||||
{ .id = snd_soc_dapm_mux, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||
#define SND_SOC_DAPM_DEMUX(wname, wreg, wshift, winvert, wcontrols) \
|
||||
{ .id = snd_soc_dapm_demux, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||
|
||||
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
|
||||
#define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\
|
||||
@ -444,11 +450,15 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
|
||||
struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(
|
||||
struct snd_kcontrol *kcontrol);
|
||||
|
||||
int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm,
|
||||
enum snd_soc_bias_level level);
|
||||
|
||||
/* dapm widget types */
|
||||
enum snd_soc_dapm_type {
|
||||
snd_soc_dapm_input = 0, /* input pin */
|
||||
snd_soc_dapm_output, /* output pin */
|
||||
snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */
|
||||
snd_soc_dapm_demux, /* connects the input to one of multiple outputs */
|
||||
snd_soc_dapm_mixer, /* mixes several analog signals together */
|
||||
snd_soc_dapm_mixer_named_ctl, /* mixer with named controls */
|
||||
snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */
|
||||
@ -563,6 +573,7 @@ struct snd_soc_dapm_widget {
|
||||
int num_kcontrols;
|
||||
const struct snd_kcontrol_new *kcontrol_news;
|
||||
struct snd_kcontrol **kcontrols;
|
||||
struct snd_soc_dobj dobj;
|
||||
|
||||
/* widget input and outputs */
|
||||
struct list_head sources;
|
||||
@ -585,6 +596,10 @@ struct snd_soc_dapm_update {
|
||||
int val;
|
||||
};
|
||||
|
||||
struct snd_soc_dapm_wcache {
|
||||
struct snd_soc_dapm_widget *widget;
|
||||
};
|
||||
|
||||
/* DAPM context */
|
||||
struct snd_soc_dapm_context {
|
||||
enum snd_soc_bias_level bias_level;
|
||||
@ -606,6 +621,9 @@ struct snd_soc_dapm_context {
|
||||
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_source_cache;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_dapm;
|
||||
#endif
|
||||
@ -623,4 +641,35 @@ struct snd_soc_dapm_stats {
|
||||
int neighbour_checks;
|
||||
};
|
||||
|
||||
/**
|
||||
* snd_soc_dapm_init_bias_level() - Initialize DAPM bias level
|
||||
* @dapm: The DAPM context to initialize
|
||||
* @level: The DAPM level to initialize to
|
||||
*
|
||||
* This function only sets the driver internal state of the DAPM level and will
|
||||
* not modify the state of the device. Hence it should not be used during normal
|
||||
* operation, but only to synchronize the internal state to the device state.
|
||||
* E.g. during driver probe to set the DAPM level to the one corresponding with
|
||||
* the power-on reset state of the device.
|
||||
*
|
||||
* To change the DAPM state of the device use snd_soc_dapm_set_bias_level().
|
||||
*/
|
||||
static inline void snd_soc_dapm_init_bias_level(
|
||||
struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
|
||||
{
|
||||
dapm->bias_level = level;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_dapm_get_bias_level() - Get current DAPM bias level
|
||||
* @dapm: The context for which to get the bias level
|
||||
*
|
||||
* Returns: The current bias level of the passed DAPM context.
|
||||
*/
|
||||
static inline enum snd_soc_bias_level snd_soc_dapm_get_bias_level(
|
||||
struct snd_soc_dapm_context *dapm)
|
||||
{
|
||||
return dapm->bias_level;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
168
include/sound/soc-topology.h
Normal file
168
include/sound/soc-topology.h
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* linux/sound/soc-topology.h -- ALSA SoC Firmware Controls and DAPM
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments Inc.
|
||||
* Copyright (C) 2015 Intel Corporation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Simple file API to load FW that includes mixers, coefficients, DAPM graphs,
|
||||
* algorithms, equalisers, DAIs, widgets, FE caps, BE caps, codec link caps etc.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_SND_SOC_TPLG_H
|
||||
#define __LINUX_SND_SOC_TPLG_H
|
||||
|
||||
#include <sound/asoc.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
struct firmware;
|
||||
struct snd_kcontrol;
|
||||
struct snd_soc_tplg_pcm_be;
|
||||
struct snd_ctl_elem_value;
|
||||
struct snd_ctl_elem_info;
|
||||
struct snd_soc_dapm_widget;
|
||||
struct snd_soc_component;
|
||||
struct snd_soc_tplg_pcm_fe;
|
||||
struct snd_soc_dapm_context;
|
||||
struct snd_soc_card;
|
||||
|
||||
/* object scan be loaded and unloaded in groups with identfying indexes */
|
||||
#define SND_SOC_TPLG_INDEX_ALL 0 /* ID that matches all FW objects */
|
||||
|
||||
/* dynamic object type */
|
||||
enum snd_soc_dobj_type {
|
||||
SND_SOC_DOBJ_NONE = 0, /* object is not dynamic */
|
||||
SND_SOC_DOBJ_MIXER,
|
||||
SND_SOC_DOBJ_ENUM,
|
||||
SND_SOC_DOBJ_BYTES,
|
||||
SND_SOC_DOBJ_PCM,
|
||||
SND_SOC_DOBJ_DAI_LINK,
|
||||
SND_SOC_DOBJ_CODEC_LINK,
|
||||
SND_SOC_DOBJ_WIDGET,
|
||||
};
|
||||
|
||||
/* dynamic control object */
|
||||
struct snd_soc_dobj_control {
|
||||
struct snd_kcontrol *kcontrol;
|
||||
char **dtexts;
|
||||
unsigned long *dvalues;
|
||||
};
|
||||
|
||||
/* dynamic widget object */
|
||||
struct snd_soc_dobj_widget {
|
||||
unsigned int kcontrol_enum:1; /* this widget is an enum kcontrol */
|
||||
};
|
||||
|
||||
/* dynamic PCM DAI object */
|
||||
struct snd_soc_dobj_pcm_dai {
|
||||
struct snd_soc_tplg_pcm_dai *pd;
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
/* generic dynamic object - all dynamic objects belong to this struct */
|
||||
struct snd_soc_dobj {
|
||||
enum snd_soc_dobj_type type;
|
||||
unsigned int index; /* objects can belong in different groups */
|
||||
struct list_head list;
|
||||
struct snd_soc_tplg_ops *ops;
|
||||
union {
|
||||
struct snd_soc_dobj_control control;
|
||||
struct snd_soc_dobj_widget widget;
|
||||
struct snd_soc_dobj_pcm_dai pcm_dai;
|
||||
};
|
||||
void *private; /* core does not touch this */
|
||||
};
|
||||
|
||||
/*
|
||||
* Kcontrol operations - used to map handlers onto firmware based controls.
|
||||
*/
|
||||
struct snd_soc_tplg_kcontrol_ops {
|
||||
u32 id;
|
||||
int (*get)(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int (*put)(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int (*info)(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo);
|
||||
};
|
||||
|
||||
/*
|
||||
* DAPM widget event handlers - used to map handlers onto widgets.
|
||||
*/
|
||||
struct snd_soc_tplg_widget_events {
|
||||
u16 type;
|
||||
int (*event_handler)(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *k, int event);
|
||||
};
|
||||
|
||||
/*
|
||||
* Public API - Used by component drivers to load and unload dynamic objects
|
||||
* and their resources.
|
||||
*/
|
||||
struct snd_soc_tplg_ops {
|
||||
|
||||
/* external kcontrol init - used for any driver specific init */
|
||||
int (*control_load)(struct snd_soc_component *,
|
||||
struct snd_kcontrol_new *, struct snd_soc_tplg_ctl_hdr *);
|
||||
int (*control_unload)(struct snd_soc_component *,
|
||||
struct snd_soc_dobj *);
|
||||
|
||||
/* external widget init - used for any driver specific init */
|
||||
int (*widget_load)(struct snd_soc_component *,
|
||||
struct snd_soc_dapm_widget *,
|
||||
struct snd_soc_tplg_dapm_widget *);
|
||||
int (*widget_unload)(struct snd_soc_component *,
|
||||
struct snd_soc_dobj *);
|
||||
|
||||
/* FE - used for any driver specific init */
|
||||
int (*pcm_dai_load)(struct snd_soc_component *,
|
||||
struct snd_soc_tplg_pcm_dai *pcm_dai, int num_fe);
|
||||
int (*pcm_dai_unload)(struct snd_soc_component *,
|
||||
struct snd_soc_dobj *);
|
||||
|
||||
/* callback to handle vendor bespoke data */
|
||||
int (*vendor_load)(struct snd_soc_component *,
|
||||
struct snd_soc_tplg_hdr *);
|
||||
int (*vendor_unload)(struct snd_soc_component *,
|
||||
struct snd_soc_tplg_hdr *);
|
||||
|
||||
/* completion - called at completion of firmware loading */
|
||||
void (*complete)(struct snd_soc_component *);
|
||||
|
||||
/* manifest - optional to inform component of manifest */
|
||||
int (*manifest)(struct snd_soc_component *,
|
||||
struct snd_soc_tplg_manifest *);
|
||||
|
||||
/* bespoke kcontrol handlers available for binding */
|
||||
const struct snd_soc_tplg_kcontrol_ops *io_ops;
|
||||
int io_ops_count;
|
||||
};
|
||||
|
||||
/* gets a pointer to data from the firmware block header */
|
||||
static inline const void *snd_soc_tplg_get_data(struct snd_soc_tplg_hdr *hdr)
|
||||
{
|
||||
const void *ptr = hdr;
|
||||
|
||||
return ptr + sizeof(*hdr);
|
||||
}
|
||||
|
||||
/* Dynamic Object loading and removal for component drivers */
|
||||
int snd_soc_tplg_component_load(struct snd_soc_component *comp,
|
||||
struct snd_soc_tplg_ops *ops, const struct firmware *fw,
|
||||
u32 index);
|
||||
int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index);
|
||||
|
||||
/* Widget removal - widgets also removed wth component API */
|
||||
void snd_soc_tplg_widget_remove(struct snd_soc_dapm_widget *w);
|
||||
void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm,
|
||||
u32 index);
|
||||
|
||||
/* Binds event handlers to dynamic widgets */
|
||||
int snd_soc_tplg_widget_bind_event(struct snd_soc_dapm_widget *w,
|
||||
const struct snd_soc_tplg_widget_events *events, int num_events,
|
||||
u16 event_type);
|
||||
|
||||
#endif
|
@ -27,6 +27,7 @@
|
||||
#include <sound/compress_driver.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/ac97_codec.h>
|
||||
#include <sound/soc-topology.h>
|
||||
|
||||
/*
|
||||
* Convenience kcontrol builders
|
||||
@ -190,8 +191,12 @@
|
||||
#define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xitems, xtexts, xvalues) \
|
||||
{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
|
||||
.mask = xmask, .items = xitems, .texts = xtexts, .values = xvalues}
|
||||
#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xnitmes, xtexts, xvalues) \
|
||||
SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xnitmes, xtexts, xvalues)
|
||||
#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xitems, xtexts, xvalues) \
|
||||
SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xitems, xtexts, xvalues)
|
||||
#define SOC_VALUE_ENUM_SINGLE_AUTODISABLE(xreg, xshift, xmask, xitems, xtexts, xvalues) \
|
||||
{ .reg = xreg, .shift_l = xshift, .shift_r = xshift, \
|
||||
.mask = xmask, .items = xitems, .texts = xtexts, \
|
||||
.values = xvalues, .autodisable = 1}
|
||||
#define SOC_ENUM_SINGLE_VIRT(xitems, xtexts) \
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, xitems, xtexts)
|
||||
#define SOC_ENUM(xname, xenum) \
|
||||
@ -312,6 +317,11 @@
|
||||
ARRAY_SIZE(xtexts), xtexts, xvalues)
|
||||
#define SOC_VALUE_ENUM_SINGLE_DECL(name, xreg, xshift, xmask, xtexts, xvalues) \
|
||||
SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xmask, xtexts, xvalues)
|
||||
|
||||
#define SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(name, xreg, xshift, xmask, xtexts, xvalues) \
|
||||
const struct soc_enum name = SOC_VALUE_ENUM_SINGLE_AUTODISABLE(xreg, \
|
||||
xshift, xmask, ARRAY_SIZE(xtexts), xtexts, xvalues)
|
||||
|
||||
#define SOC_ENUM_SINGLE_VIRT_DECL(name, xtexts) \
|
||||
const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts)
|
||||
|
||||
@ -767,6 +777,9 @@ struct snd_soc_component {
|
||||
|
||||
struct mutex io_mutex;
|
||||
|
||||
/* attached dynamic objects */
|
||||
struct list_head dobj_list;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_root;
|
||||
#endif
|
||||
@ -819,7 +832,7 @@ struct snd_soc_codec {
|
||||
/* component */
|
||||
struct snd_soc_component component;
|
||||
|
||||
/* dapm */
|
||||
/* Don't access this directly, use snd_soc_codec_get_dapm() */
|
||||
struct snd_soc_dapm_context dapm;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
@ -961,30 +974,6 @@ struct snd_soc_dai_link {
|
||||
|
||||
enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */
|
||||
|
||||
/* Keep DAI active over suspend */
|
||||
unsigned int ignore_suspend:1;
|
||||
|
||||
/* Symmetry requirements */
|
||||
unsigned int symmetric_rates:1;
|
||||
unsigned int symmetric_channels:1;
|
||||
unsigned int symmetric_samplebits:1;
|
||||
|
||||
/* Mark this pcm with non atomic ops */
|
||||
bool nonatomic;
|
||||
|
||||
/* Do not create a PCM for this DAI link (Backend link) */
|
||||
unsigned int no_pcm:1;
|
||||
|
||||
/* This DAI link can route to other DAI links at runtime (Frontend)*/
|
||||
unsigned int dynamic:1;
|
||||
|
||||
/* DPCM capture and Playback support */
|
||||
unsigned int dpcm_capture:1;
|
||||
unsigned int dpcm_playback:1;
|
||||
|
||||
/* pmdown_time is ignored at stop */
|
||||
unsigned int ignore_pmdown_time:1;
|
||||
|
||||
/* codec/machine specific init - e.g. add machine controls */
|
||||
int (*init)(struct snd_soc_pcm_runtime *rtd);
|
||||
|
||||
@ -999,6 +988,33 @@ struct snd_soc_dai_link {
|
||||
/* For unidirectional dai links */
|
||||
bool playback_only;
|
||||
bool capture_only;
|
||||
|
||||
/* Mark this pcm with non atomic ops */
|
||||
bool nonatomic;
|
||||
|
||||
/* Keep DAI active over suspend */
|
||||
unsigned int ignore_suspend:1;
|
||||
|
||||
/* Symmetry requirements */
|
||||
unsigned int symmetric_rates:1;
|
||||
unsigned int symmetric_channels:1;
|
||||
unsigned int symmetric_samplebits:1;
|
||||
|
||||
/* Do not create a PCM for this DAI link (Backend link) */
|
||||
unsigned int no_pcm:1;
|
||||
|
||||
/* This DAI link can route to other DAI links at runtime (Frontend)*/
|
||||
unsigned int dynamic:1;
|
||||
|
||||
/* DPCM capture and Playback support */
|
||||
unsigned int dpcm_capture:1;
|
||||
unsigned int dpcm_playback:1;
|
||||
|
||||
/* DPCM used FE & BE merged format */
|
||||
unsigned int dpcm_merged_format:1;
|
||||
|
||||
/* pmdown_time is ignored at stop */
|
||||
unsigned int ignore_pmdown_time:1;
|
||||
};
|
||||
|
||||
struct snd_soc_codec_conf {
|
||||
@ -1111,6 +1127,9 @@ struct snd_soc_card {
|
||||
struct list_head dapm_list;
|
||||
struct list_head dapm_dirty;
|
||||
|
||||
/* attached dynamic objects */
|
||||
struct list_head dobj_list;
|
||||
|
||||
/* Generic DAPM context for the card */
|
||||
struct snd_soc_dapm_context dapm;
|
||||
struct snd_soc_dapm_stats dapm_stats;
|
||||
@ -1170,6 +1189,7 @@ struct soc_mixer_control {
|
||||
unsigned int sign_bit;
|
||||
unsigned int invert:1;
|
||||
unsigned int autodisable:1;
|
||||
struct snd_soc_dobj dobj;
|
||||
};
|
||||
|
||||
struct soc_bytes {
|
||||
@ -1180,6 +1200,8 @@ struct soc_bytes {
|
||||
|
||||
struct soc_bytes_ext {
|
||||
int max;
|
||||
struct snd_soc_dobj dobj;
|
||||
|
||||
/* used for TLV byte control */
|
||||
int (*get)(unsigned int __user *bytes, unsigned int size);
|
||||
int (*put)(const unsigned int __user *bytes, unsigned int size);
|
||||
@ -1200,6 +1222,8 @@ struct soc_enum {
|
||||
unsigned int mask;
|
||||
const char * const *texts;
|
||||
const unsigned int *values;
|
||||
unsigned int autodisable:1;
|
||||
struct snd_soc_dobj dobj;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1281,6 +1305,58 @@ static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm(
|
||||
return component->dapm_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_codec_get_dapm() - Returns the DAPM context for the CODEC
|
||||
* @codec: The CODEC for which to get the DAPM context
|
||||
*
|
||||
* Note: Use this function instead of directly accessing the CODEC's dapm field
|
||||
*/
|
||||
static inline struct snd_soc_dapm_context *snd_soc_codec_get_dapm(
|
||||
struct snd_soc_codec *codec)
|
||||
{
|
||||
return &codec->dapm;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_dapm_init_bias_level() - Initialize CODEC DAPM bias level
|
||||
* @dapm: The CODEC for which to initialize the DAPM bias level
|
||||
* @level: The DAPM level to initialize to
|
||||
*
|
||||
* Initializes the CODEC DAPM bias level. See snd_soc_dapm_init_bias_level().
|
||||
*/
|
||||
static inline void snd_soc_codec_init_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
snd_soc_dapm_init_bias_level(snd_soc_codec_get_dapm(codec), level);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_dapm_get_bias_level() - Get current CODEC DAPM bias level
|
||||
* @codec: The CODEC for which to get the DAPM bias level
|
||||
*
|
||||
* Returns: The current DAPM bias level of the CODEC.
|
||||
*/
|
||||
static inline enum snd_soc_bias_level snd_soc_codec_get_bias_level(
|
||||
struct snd_soc_codec *codec)
|
||||
{
|
||||
return snd_soc_dapm_get_bias_level(snd_soc_codec_get_dapm(codec));
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_codec_force_bias_level() - Set the CODEC DAPM bias level
|
||||
* @codec: The CODEC for which to set the level
|
||||
* @level: The level to set to
|
||||
*
|
||||
* Forces the CODEC bias level to a specific state. See
|
||||
* snd_soc_dapm_force_bias_level().
|
||||
*/
|
||||
static inline int snd_soc_codec_force_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
return snd_soc_dapm_force_bias_level(snd_soc_codec_get_dapm(codec),
|
||||
level);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol
|
||||
* @kcontrol: The kcontrol
|
||||
|
@ -31,12 +31,7 @@
|
||||
* ~(sizeof(unsigned int) - 1)) ....
|
||||
*/
|
||||
|
||||
#define SNDRV_CTL_TLVT_CONTAINER 0 /* one level down - group of TLVs */
|
||||
#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */
|
||||
#define SNDRV_CTL_TLVT_DB_LINEAR 2 /* linear volume */
|
||||
#define SNDRV_CTL_TLVT_DB_RANGE 3 /* dB range container */
|
||||
#define SNDRV_CTL_TLVT_DB_MINMAX 4 /* dB scale with min/max */
|
||||
#define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5 /* dB scale with min/max with mute */
|
||||
#include <uapi/sound/tlv.h>
|
||||
|
||||
#define TLV_ITEM(type, ...) \
|
||||
(type), TLV_LENGTH(__VA_ARGS__), __VA_ARGS__
|
||||
@ -90,12 +85,4 @@
|
||||
|
||||
#define TLV_DB_GAIN_MUTE -9999999
|
||||
|
||||
/*
|
||||
* channel-mapping TLV items
|
||||
* TLV length must match with num_channels
|
||||
*/
|
||||
#define SNDRV_CTL_TLVT_CHMAP_FIXED 0x101 /* fixed channel position */
|
||||
#define SNDRV_CTL_TLVT_CHMAP_VAR 0x102 /* channels freely swappable */
|
||||
#define SNDRV_CTL_TLVT_CHMAP_PAIRED 0x103 /* pair-wise swappable */
|
||||
|
||||
#endif /* __SOUND_TLV_H */
|
||||
|
388
include/uapi/sound/asoc.h
Normal file
388
include/uapi/sound/asoc.h
Normal file
@ -0,0 +1,388 @@
|
||||
/*
|
||||
* uapi/sound/asoc.h -- ALSA SoC Firmware Controls and DAPM
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments Inc.
|
||||
* Copyright (C) 2015 Intel Corporation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Simple file API to load FW that includes mixers, coefficients, DAPM graphs,
|
||||
* algorithms, equalisers, DAIs, widgets etc.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_UAPI_SND_ASOC_H
|
||||
#define __LINUX_UAPI_SND_ASOC_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <sound/asound.h>
|
||||
|
||||
/*
|
||||
* Maximum number of channels topology kcontrol can represent.
|
||||
*/
|
||||
#define SND_SOC_TPLG_MAX_CHAN 8
|
||||
|
||||
/*
|
||||
* Maximum number of PCM formats capability
|
||||
*/
|
||||
#define SND_SOC_TPLG_MAX_FORMATS 16
|
||||
|
||||
/*
|
||||
* Maximum number of PCM stream configs
|
||||
*/
|
||||
#define SND_SOC_TPLG_STREAM_CONFIG_MAX 8
|
||||
|
||||
/* individual kcontrol info types - can be mixed with other types */
|
||||
#define SND_SOC_TPLG_CTL_VOLSW 1
|
||||
#define SND_SOC_TPLG_CTL_VOLSW_SX 2
|
||||
#define SND_SOC_TPLG_CTL_VOLSW_XR_SX 3
|
||||
#define SND_SOC_TPLG_CTL_ENUM 4
|
||||
#define SND_SOC_TPLG_CTL_BYTES 5
|
||||
#define SND_SOC_TPLG_CTL_ENUM_VALUE 6
|
||||
#define SND_SOC_TPLG_CTL_RANGE 7
|
||||
#define SND_SOC_TPLG_CTL_STROBE 8
|
||||
|
||||
|
||||
/* individual widget kcontrol info types - can be mixed with other types */
|
||||
#define SND_SOC_TPLG_DAPM_CTL_VOLSW 64
|
||||
#define SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE 65
|
||||
#define SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT 66
|
||||
#define SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE 67
|
||||
#define SND_SOC_TPLG_DAPM_CTL_PIN 68
|
||||
|
||||
/* DAPM widget types - add new items to the end */
|
||||
#define SND_SOC_TPLG_DAPM_INPUT 0
|
||||
#define SND_SOC_TPLG_DAPM_OUTPUT 1
|
||||
#define SND_SOC_TPLG_DAPM_MUX 2
|
||||
#define SND_SOC_TPLG_DAPM_MIXER 3
|
||||
#define SND_SOC_TPLG_DAPM_PGA 4
|
||||
#define SND_SOC_TPLG_DAPM_OUT_DRV 5
|
||||
#define SND_SOC_TPLG_DAPM_ADC 6
|
||||
#define SND_SOC_TPLG_DAPM_DAC 7
|
||||
#define SND_SOC_TPLG_DAPM_SWITCH 8
|
||||
#define SND_SOC_TPLG_DAPM_PRE 9
|
||||
#define SND_SOC_TPLG_DAPM_POST 10
|
||||
#define SND_SOC_TPLG_DAPM_AIF_IN 11
|
||||
#define SND_SOC_TPLG_DAPM_AIF_OUT 12
|
||||
#define SND_SOC_TPLG_DAPM_DAI_IN 13
|
||||
#define SND_SOC_TPLG_DAPM_DAI_OUT 14
|
||||
#define SND_SOC_TPLG_DAPM_DAI_LINK 15
|
||||
#define SND_SOC_TPLG_DAPM_LAST SND_SOC_TPLG_DAPM_DAI_LINK
|
||||
|
||||
/* Header magic number and string sizes */
|
||||
#define SND_SOC_TPLG_MAGIC 0x41536F43 /* ASoC */
|
||||
|
||||
/* string sizes */
|
||||
#define SND_SOC_TPLG_NUM_TEXTS 16
|
||||
|
||||
/* ABI version */
|
||||
#define SND_SOC_TPLG_ABI_VERSION 0x2
|
||||
|
||||
/* Max size of TLV data */
|
||||
#define SND_SOC_TPLG_TLV_SIZE 32
|
||||
|
||||
/*
|
||||
* File and Block header data types.
|
||||
* Add new generic and vendor types to end of list.
|
||||
* Generic types are handled by the core whilst vendors types are passed
|
||||
* to the component drivers for handling.
|
||||
*/
|
||||
#define SND_SOC_TPLG_TYPE_MIXER 1
|
||||
#define SND_SOC_TPLG_TYPE_BYTES 2
|
||||
#define SND_SOC_TPLG_TYPE_ENUM 3
|
||||
#define SND_SOC_TPLG_TYPE_DAPM_GRAPH 4
|
||||
#define SND_SOC_TPLG_TYPE_DAPM_WIDGET 5
|
||||
#define SND_SOC_TPLG_TYPE_DAI_LINK 6
|
||||
#define SND_SOC_TPLG_TYPE_PCM 7
|
||||
#define SND_SOC_TPLG_TYPE_MANIFEST 8
|
||||
#define SND_SOC_TPLG_TYPE_CODEC_LINK 9
|
||||
#define SND_SOC_TPLG_TYPE_MAX SND_SOC_TPLG_TYPE_CODEC_LINK
|
||||
|
||||
/* vendor block IDs - please add new vendor types to end */
|
||||
#define SND_SOC_TPLG_TYPE_VENDOR_FW 1000
|
||||
#define SND_SOC_TPLG_TYPE_VENDOR_CONFIG 1001
|
||||
#define SND_SOC_TPLG_TYPE_VENDOR_COEFF 1002
|
||||
#define SND_SOC_TPLG_TYPEVENDOR_CODEC 1003
|
||||
|
||||
#define SND_SOC_TPLG_STREAM_PLAYBACK 0
|
||||
#define SND_SOC_TPLG_STREAM_CAPTURE 1
|
||||
|
||||
/*
|
||||
* Block Header.
|
||||
* This header preceeds all object and object arrays below.
|
||||
*/
|
||||
struct snd_soc_tplg_hdr {
|
||||
__le32 magic; /* magic number */
|
||||
__le32 abi; /* ABI version */
|
||||
__le32 version; /* optional vendor specific version details */
|
||||
__le32 type; /* SND_SOC_TPLG_TYPE_ */
|
||||
__le32 size; /* size of this structure */
|
||||
__le32 vendor_type; /* optional vendor specific type info */
|
||||
__le32 payload_size; /* data bytes, excluding this header */
|
||||
__le32 index; /* identifier for block */
|
||||
__le32 count; /* number of elements in block */
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* Private data.
|
||||
* All topology objects may have private data that can be used by the driver or
|
||||
* firmware. Core will ignore this data.
|
||||
*/
|
||||
struct snd_soc_tplg_private {
|
||||
__le32 size; /* in bytes of private data */
|
||||
char data[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* Kcontrol TLV data.
|
||||
*/
|
||||
struct snd_soc_tplg_ctl_tlv {
|
||||
__le32 size; /* in bytes aligned to 4 */
|
||||
__le32 numid; /* control element numeric identification */
|
||||
__le32 count; /* number of elem in data array */
|
||||
__le32 data[SND_SOC_TPLG_TLV_SIZE];
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* Kcontrol channel data
|
||||
*/
|
||||
struct snd_soc_tplg_channel {
|
||||
__le32 size; /* in bytes of this structure */
|
||||
__le32 reg;
|
||||
__le32 shift;
|
||||
__le32 id; /* ID maps to Left, Right, LFE etc */
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* Kcontrol Operations IDs
|
||||
*/
|
||||
struct snd_soc_tplg_kcontrol_ops_id {
|
||||
__le32 get;
|
||||
__le32 put;
|
||||
__le32 info;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* kcontrol header
|
||||
*/
|
||||
struct snd_soc_tplg_ctl_hdr {
|
||||
__le32 size; /* in bytes of this structure */
|
||||
__le32 type;
|
||||
char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
__le32 access;
|
||||
struct snd_soc_tplg_kcontrol_ops_id ops;
|
||||
__le32 tlv_size; /* non zero means control has TLV data */
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* Stream Capabilities
|
||||
*/
|
||||
struct snd_soc_tplg_stream_caps {
|
||||
__le32 size; /* in bytes of this structure */
|
||||
char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
__le64 formats[SND_SOC_TPLG_MAX_FORMATS]; /* supported formats SNDRV_PCM_FMTBIT_* */
|
||||
__le32 rates; /* supported rates SNDRV_PCM_RATE_* */
|
||||
__le32 rate_min; /* min rate */
|
||||
__le32 rate_max; /* max rate */
|
||||
__le32 channels_min; /* min channels */
|
||||
__le32 channels_max; /* max channels */
|
||||
__le32 periods_min; /* min number of periods */
|
||||
__le32 periods_max; /* max number of periods */
|
||||
__le32 period_size_min; /* min period size bytes */
|
||||
__le32 period_size_max; /* max period size bytes */
|
||||
__le32 buffer_size_min; /* min buffer size bytes */
|
||||
__le32 buffer_size_max; /* max buffer size bytes */
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* FE or BE Stream configuration supported by SW/FW
|
||||
*/
|
||||
struct snd_soc_tplg_stream {
|
||||
__le32 size; /* in bytes of this structure */
|
||||
__le64 format; /* SNDRV_PCM_FMTBIT_* */
|
||||
__le32 rate; /* SNDRV_PCM_RATE_* */
|
||||
__le32 period_bytes; /* size of period in bytes */
|
||||
__le32 buffer_bytes; /* size of buffer in bytes */
|
||||
__le32 channels; /* channels */
|
||||
__le32 tdm_slot; /* optional BE bitmask of supported TDM slots */
|
||||
__le32 dai_fmt; /* SND_SOC_DAIFMT_ */
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* Duplex stream configuration supported by SW/FW.
|
||||
*/
|
||||
struct snd_soc_tplg_stream_config {
|
||||
__le32 size; /* in bytes of this structure */
|
||||
char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
struct snd_soc_tplg_stream playback;
|
||||
struct snd_soc_tplg_stream capture;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* Manifest. List totals for each payload type. Not used in parsing, but will
|
||||
* be passed to the component driver before any other objects in order for any
|
||||
* global componnent resource allocations.
|
||||
*
|
||||
* File block representation for manifest :-
|
||||
* +-----------------------------------+----+
|
||||
* | struct snd_soc_tplg_hdr | 1 |
|
||||
* +-----------------------------------+----+
|
||||
* | struct snd_soc_tplg_manifest | 1 |
|
||||
* +-----------------------------------+----+
|
||||
*/
|
||||
struct snd_soc_tplg_manifest {
|
||||
__le32 size; /* in bytes of this structure */
|
||||
__le32 control_elems; /* number of control elements */
|
||||
__le32 widget_elems; /* number of widget elements */
|
||||
__le32 graph_elems; /* number of graph elements */
|
||||
__le32 dai_elems; /* number of DAI elements */
|
||||
__le32 dai_link_elems; /* number of DAI link elements */
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* Mixer kcontrol.
|
||||
*
|
||||
* File block representation for mixer kcontrol :-
|
||||
* +-----------------------------------+----+
|
||||
* | struct snd_soc_tplg_hdr | 1 |
|
||||
* +-----------------------------------+----+
|
||||
* | struct snd_soc_tplg_mixer_control | N |
|
||||
* +-----------------------------------+----+
|
||||
*/
|
||||
struct snd_soc_tplg_mixer_control {
|
||||
struct snd_soc_tplg_ctl_hdr hdr;
|
||||
__le32 size; /* in bytes of this structure */
|
||||
__le32 min;
|
||||
__le32 max;
|
||||
__le32 platform_max;
|
||||
__le32 invert;
|
||||
__le32 num_channels;
|
||||
struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN];
|
||||
struct snd_soc_tplg_ctl_tlv tlv;
|
||||
struct snd_soc_tplg_private priv;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* Enumerated kcontrol
|
||||
*
|
||||
* File block representation for enum kcontrol :-
|
||||
* +-----------------------------------+----+
|
||||
* | struct snd_soc_tplg_hdr | 1 |
|
||||
* +-----------------------------------+----+
|
||||
* | struct snd_soc_tplg_enum_control | N |
|
||||
* +-----------------------------------+----+
|
||||
*/
|
||||
struct snd_soc_tplg_enum_control {
|
||||
struct snd_soc_tplg_ctl_hdr hdr;
|
||||
__le32 size; /* in bytes of this structure */
|
||||
__le32 num_channels;
|
||||
struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN];
|
||||
__le32 items;
|
||||
__le32 mask;
|
||||
__le32 count;
|
||||
char texts[SND_SOC_TPLG_NUM_TEXTS][SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
__le32 values[SND_SOC_TPLG_NUM_TEXTS * SNDRV_CTL_ELEM_ID_NAME_MAXLEN / 4];
|
||||
struct snd_soc_tplg_private priv;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* Bytes kcontrol
|
||||
*
|
||||
* File block representation for bytes kcontrol :-
|
||||
* +-----------------------------------+----+
|
||||
* | struct snd_soc_tplg_hdr | 1 |
|
||||
* +-----------------------------------+----+
|
||||
* | struct snd_soc_tplg_bytes_control | N |
|
||||
* +-----------------------------------+----+
|
||||
*/
|
||||
struct snd_soc_tplg_bytes_control {
|
||||
struct snd_soc_tplg_ctl_hdr hdr;
|
||||
__le32 size; /* in bytes of this structure */
|
||||
__le32 max;
|
||||
__le32 mask;
|
||||
__le32 base;
|
||||
__le32 num_regs;
|
||||
struct snd_soc_tplg_private priv;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* DAPM Graph Element
|
||||
*
|
||||
* File block representation for DAPM graph elements :-
|
||||
* +-------------------------------------+----+
|
||||
* | struct snd_soc_tplg_hdr | 1 |
|
||||
* +-------------------------------------+----+
|
||||
* | struct snd_soc_tplg_dapm_graph_elem | N |
|
||||
* +-------------------------------------+----+
|
||||
*/
|
||||
struct snd_soc_tplg_dapm_graph_elem {
|
||||
char sink[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
char control[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
char source[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* DAPM Widget.
|
||||
*
|
||||
* File block representation for DAPM widget :-
|
||||
* +-------------------------------------+-----+
|
||||
* | struct snd_soc_tplg_hdr | 1 |
|
||||
* +-------------------------------------+-----+
|
||||
* | struct snd_soc_tplg_dapm_widget | N |
|
||||
* +-------------------------------------+-----+
|
||||
* | struct snd_soc_tplg_enum_control | 0|1 |
|
||||
* | struct snd_soc_tplg_mixer_control | 0|N |
|
||||
* +-------------------------------------+-----+
|
||||
*
|
||||
* Optional enum or mixer control can be appended to the end of each widget
|
||||
* in the block.
|
||||
*/
|
||||
struct snd_soc_tplg_dapm_widget {
|
||||
__le32 size; /* in bytes of this structure */
|
||||
__le32 id; /* SND_SOC_DAPM_CTL */
|
||||
char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
char sname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
|
||||
__le32 reg; /* negative reg = no direct dapm */
|
||||
__le32 shift; /* bits to shift */
|
||||
__le32 mask; /* non-shifted mask */
|
||||
__u32 invert; /* invert the power bit */
|
||||
__u32 ignore_suspend; /* kept enabled over suspend */
|
||||
__u16 event_flags;
|
||||
__u16 event_type;
|
||||
__u16 num_kcontrols;
|
||||
struct snd_soc_tplg_private priv;
|
||||
/*
|
||||
* kcontrols that relate to this widget
|
||||
* follow here after widget private data
|
||||
*/
|
||||
} __attribute__((packed));
|
||||
|
||||
struct snd_soc_tplg_pcm_cfg_caps {
|
||||
struct snd_soc_tplg_stream_caps caps;
|
||||
struct snd_soc_tplg_stream_config configs[SND_SOC_TPLG_STREAM_CONFIG_MAX];
|
||||
__le32 num_configs; /* number of configs */
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* Describes SW/FW specific features of PCM or DAI link.
|
||||
*
|
||||
* File block representation for PCM/DAI-Link :-
|
||||
* +-----------------------------------+-----+
|
||||
* | struct snd_soc_tplg_hdr | 1 |
|
||||
* +-----------------------------------+-----+
|
||||
* | struct snd_soc_tplg_dapm_pcm_dai | N |
|
||||
* +-----------------------------------+-----+
|
||||
*/
|
||||
struct snd_soc_tplg_pcm_dai {
|
||||
__le32 size; /* in bytes of this structure */
|
||||
char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
__le32 id; /* unique ID - used to match */
|
||||
__le32 playback; /* supports playback mode */
|
||||
__le32 capture; /* supports capture mode */
|
||||
__le32 compress; /* 1 = compressed; 0 = PCM */
|
||||
struct snd_soc_tplg_pcm_cfg_caps capconf[2]; /* capabilities and configs */
|
||||
} __attribute__((packed));
|
||||
|
||||
#endif
|
31
include/uapi/sound/tlv.h
Normal file
31
include/uapi/sound/tlv.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __UAPI_SOUND_TLV_H
|
||||
#define __UAPI_SOUND_TLV_H
|
||||
|
||||
#define SNDRV_CTL_TLVT_CONTAINER 0 /* one level down - group of TLVs */
|
||||
#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */
|
||||
#define SNDRV_CTL_TLVT_DB_LINEAR 2 /* linear volume */
|
||||
#define SNDRV_CTL_TLVT_DB_RANGE 3 /* dB range container */
|
||||
#define SNDRV_CTL_TLVT_DB_MINMAX 4 /* dB scale with min/max */
|
||||
#define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5 /* dB scale with min/max with mute */
|
||||
|
||||
/*
|
||||
* channel-mapping TLV items
|
||||
* TLV length must match with num_channels
|
||||
*/
|
||||
#define SNDRV_CTL_TLVT_CHMAP_FIXED 0x101 /* fixed channel position */
|
||||
#define SNDRV_CTL_TLVT_CHMAP_VAR 0x102 /* channels freely swappable */
|
||||
#define SNDRV_CTL_TLVT_CHMAP_PAIRED 0x103 /* pair-wise swappable */
|
||||
|
||||
#endif
|
@ -57,6 +57,7 @@ source "sound/soc/tegra/Kconfig"
|
||||
source "sound/soc/txx9/Kconfig"
|
||||
source "sound/soc/ux500/Kconfig"
|
||||
source "sound/soc/xtensa/Kconfig"
|
||||
source "sound/soc/zte/Kconfig"
|
||||
|
||||
# Supported codecs
|
||||
source "sound/soc/codecs/Kconfig"
|
||||
|
@ -1,5 +1,6 @@
|
||||
snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
|
||||
snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o soc-devres.o soc-ops.o
|
||||
snd-soc-core-objs += soc-topology.o
|
||||
|
||||
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
|
||||
snd-soc-core-objs += soc-generic-dmaengine-pcm.o
|
||||
@ -38,3 +39,4 @@ obj-$(CONFIG_SND_SOC) += tegra/
|
||||
obj-$(CONFIG_SND_SOC) += txx9/
|
||||
obj-$(CONFIG_SND_SOC) += ux500/
|
||||
obj-$(CONFIG_SND_SOC) += xtensa/
|
||||
obj-$(CONFIG_SND_SOC) += zte/
|
||||
|
@ -6,27 +6,22 @@ config SND_ATMEL_SOC
|
||||
the ATMEL SSC interface. You will also need
|
||||
to select the audio interfaces to support below.
|
||||
|
||||
if SND_ATMEL_SOC
|
||||
|
||||
config SND_ATMEL_SOC_PDC
|
||||
tristate
|
||||
depends on SND_ATMEL_SOC
|
||||
bool
|
||||
|
||||
config SND_ATMEL_SOC_DMA
|
||||
tristate
|
||||
depends on SND_ATMEL_SOC
|
||||
bool
|
||||
select SND_SOC_GENERIC_DMAENGINE_PCM
|
||||
|
||||
config SND_ATMEL_SOC_SSC
|
||||
tristate
|
||||
depends on SND_ATMEL_SOC
|
||||
help
|
||||
Say Y or M if you want to add support for codecs the
|
||||
ATMEL SSC interface. You will also needs to select the individual
|
||||
machine drivers to support below.
|
||||
|
||||
config SND_AT91_SOC_SAM9G20_WM8731
|
||||
tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
|
||||
depends on ARCH_AT91 || COMPILE_TEST
|
||||
depends on ATMEL_SSC && SND_ATMEL_SOC && SND_SOC_I2C_AND_SPI
|
||||
depends on ATMEL_SSC && SND_SOC_I2C_AND_SPI
|
||||
select SND_ATMEL_SOC_PDC
|
||||
select SND_ATMEL_SOC_SSC
|
||||
select SND_SOC_WM8731
|
||||
@ -37,7 +32,7 @@ config SND_AT91_SOC_SAM9G20_WM8731
|
||||
config SND_ATMEL_SOC_WM8904
|
||||
tristate "Atmel ASoC driver for boards using WM8904 codec"
|
||||
depends on ARCH_AT91 || COMPILE_TEST
|
||||
depends on ATMEL_SSC && SND_ATMEL_SOC && I2C
|
||||
depends on ATMEL_SSC && I2C
|
||||
select SND_ATMEL_SOC_SSC
|
||||
select SND_ATMEL_SOC_DMA
|
||||
select SND_SOC_WM8904
|
||||
@ -48,10 +43,11 @@ config SND_ATMEL_SOC_WM8904
|
||||
config SND_AT91_SOC_SAM9X5_WM8731
|
||||
tristate "SoC Audio support for WM8731-based at91sam9x5 board"
|
||||
depends on ARCH_AT91 || COMPILE_TEST
|
||||
depends on ATMEL_SSC && SND_ATMEL_SOC && SND_SOC_I2C_AND_SPI
|
||||
depends on ATMEL_SSC && SND_SOC_I2C_AND_SPI
|
||||
select SND_ATMEL_SOC_SSC
|
||||
select SND_ATMEL_SOC_DMA
|
||||
select SND_SOC_WM8731
|
||||
help
|
||||
Say Y if you want to add support for audio SoC on an
|
||||
at91sam9x5 based board that is using WM8731 codec.
|
||||
endif
|
||||
|
@ -1,10 +1,8 @@
|
||||
# AT91 Platform Support
|
||||
snd-soc-atmel-pcm-pdc-objs := atmel-pcm-pdc.o
|
||||
snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o
|
||||
snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
|
||||
snd-soc-atmel-pcm-$(CONFIG_SND_ATMEL_SOC_PDC) := atmel-pcm-pdc.o
|
||||
snd-soc-atmel-pcm-$(CONFIG_SND_ATMEL_SOC_DMA) += atmel-pcm-dma.o
|
||||
snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o $(snd-soc-atmel-pcm-y)
|
||||
|
||||
obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o
|
||||
obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o
|
||||
obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
|
||||
|
||||
# AT91 Machine Support
|
||||
|
@ -124,8 +124,7 @@ static const struct snd_dmaengine_pcm_config atmel_dmaengine_pcm_config = {
|
||||
|
||||
int atmel_pcm_dma_platform_register(struct device *dev)
|
||||
{
|
||||
return snd_dmaengine_pcm_register(dev, &atmel_dmaengine_pcm_config,
|
||||
SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);
|
||||
return snd_dmaengine_pcm_register(dev, &atmel_dmaengine_pcm_config, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(atmel_pcm_dma_platform_register);
|
||||
|
||||
|
@ -95,8 +95,9 @@ static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = {
|
||||
|
||||
static const struct snd_soc_dapm_route intercon[] = {
|
||||
|
||||
/* speaker connected to LHPOUT */
|
||||
/* speaker connected to LHPOUT/RHPOUT */
|
||||
{"Ext Spk", NULL, "LHPOUT"},
|
||||
{"Ext Spk", NULL, "RHPOUT"},
|
||||
|
||||
/* mic is connected to Mic Jack, with WM8731 Mic Bias */
|
||||
{"MICIN", NULL, "Mic Bias"},
|
||||
@ -108,9 +109,7 @@ static const struct snd_soc_dapm_route intercon[] = {
|
||||
*/
|
||||
static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int ret;
|
||||
|
||||
printk(KERN_DEBUG
|
||||
@ -124,10 +123,6 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* not connected */
|
||||
snd_soc_dapm_nc_pin(dapm, "RLINEIN");
|
||||
snd_soc_dapm_nc_pin(dapm, "LLINEIN");
|
||||
|
||||
#ifndef ENABLE_MIC_INPUT
|
||||
snd_soc_dapm_nc_pin(&rtd->card->dapm, "Int Mic");
|
||||
#endif
|
||||
@ -158,6 +153,7 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = {
|
||||
.num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets),
|
||||
.dapm_routes = intercon,
|
||||
.num_dapm_routes = ARRAY_SIZE(intercon),
|
||||
.fully_routed = true,
|
||||
};
|
||||
|
||||
static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "../codecs/wm8731.h"
|
||||
#include "psc.h"
|
||||
|
||||
static struct platform_device_id db1200_pids[] = {
|
||||
static const struct platform_device_id db1200_pids[] = {
|
||||
{
|
||||
.name = "db1200-ac97",
|
||||
.driver_data = 0,
|
||||
|
@ -60,7 +60,6 @@ int devm_ep93xx_pcm_platform_register(struct device *dev)
|
||||
{
|
||||
return devm_snd_dmaengine_pcm_register(dev,
|
||||
&ep93xx_dmaengine_pcm_config,
|
||||
SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
|
||||
SND_DMAENGINE_PCM_FLAG_NO_DT |
|
||||
SND_DMAENGINE_PCM_FLAG_COMPAT);
|
||||
}
|
||||
|
@ -1140,7 +1140,7 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
/* Enable Audio PLL & Audio section */
|
||||
data = AUDIO_PLL | AUDIO_SECTION_ON;
|
||||
pm860x_reg_write(pm860x->i2c, REG_MISC2, data);
|
||||
@ -1156,7 +1156,6 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec,
|
||||
pm860x_set_bits(pm860x->i2c, REG_MISC2, data, 0);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_88PM860X if MFD_88PM860X
|
||||
select SND_SOC_L3
|
||||
select SND_SOC_AB8500_CODEC if ABX500_CORE
|
||||
select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
|
||||
select SND_SOC_AC97_CODEC
|
||||
select SND_SOC_AD1836 if SPI_MASTER
|
||||
select SND_SOC_AD193X_SPI if SPI_MASTER
|
||||
select SND_SOC_AD193X_I2C if I2C
|
||||
@ -54,7 +54,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_CS4271_SPI if SPI_MASTER
|
||||
select SND_SOC_CS42XX8_I2C if I2C
|
||||
select SND_SOC_CX20442 if TTY
|
||||
select SND_SOC_DA7210 if I2C
|
||||
select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_DA7213 if I2C
|
||||
select SND_SOC_DA732X if I2C
|
||||
select SND_SOC_DA9055 if I2C
|
||||
@ -104,6 +104,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
|
||||
select SND_SOC_TAS2552 if I2C
|
||||
select SND_SOC_TAS5086 if I2C
|
||||
select SND_SOC_TAS571X if I2C
|
||||
select SND_SOC_TFA9879 if I2C
|
||||
select SND_SOC_TLV320AIC23_I2C if I2C
|
||||
select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
|
||||
@ -211,8 +212,9 @@ config SND_SOC_AB8500_CODEC
|
||||
tristate
|
||||
|
||||
config SND_SOC_AC97_CODEC
|
||||
tristate
|
||||
tristate "Build generic ASoC AC97 CODEC driver"
|
||||
select SND_AC97_CODEC
|
||||
select SND_SOC_AC97_BUS
|
||||
|
||||
config SND_SOC_AD1836
|
||||
tristate
|
||||
@ -611,6 +613,10 @@ config SND_SOC_TAS5086
|
||||
tristate "Texas Instruments TAS5086 speaker amplifier"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_TAS571X
|
||||
tristate "Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_TFA9879
|
||||
tristate "NXP Semiconductors TFA9879 amplifier"
|
||||
depends on I2C
|
||||
|
@ -106,6 +106,7 @@ snd-soc-sta350-objs := sta350.o
|
||||
snd-soc-sta529-objs := sta529.o
|
||||
snd-soc-stac9766-objs := stac9766.o
|
||||
snd-soc-tas5086-objs := tas5086.o
|
||||
snd-soc-tas571x-objs := tas571x.o
|
||||
snd-soc-tfa9879-objs := tfa9879.o
|
||||
snd-soc-tlv320aic23-objs := tlv320aic23.o
|
||||
snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
|
||||
@ -288,6 +289,7 @@ obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
|
||||
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
|
||||
obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o
|
||||
obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
|
||||
obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o
|
||||
obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o
|
||||
|
@ -1209,6 +1209,7 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
|
||||
struct device *dev = codec->dev;
|
||||
bool apply_fir, apply_iir;
|
||||
@ -1234,15 +1235,14 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol,
|
||||
apply_fir = req == ANC_APPLY_FIR || req == ANC_APPLY_FIR_IIR;
|
||||
apply_iir = req == ANC_APPLY_IIR || req == ANC_APPLY_FIR_IIR;
|
||||
|
||||
status = snd_soc_dapm_force_enable_pin(&codec->dapm,
|
||||
"ANC Configure Input");
|
||||
status = snd_soc_dapm_force_enable_pin(dapm, "ANC Configure Input");
|
||||
if (status < 0) {
|
||||
dev_err(dev,
|
||||
"%s: ERROR: Failed to enable power (status = %d)!\n",
|
||||
__func__, status);
|
||||
goto cleanup;
|
||||
}
|
||||
snd_soc_dapm_sync(&codec->dapm);
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
anc_configure(codec, apply_fir, apply_iir);
|
||||
|
||||
@ -1259,8 +1259,8 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol,
|
||||
drvdata->anc_status = ANC_IIR_CONFIGURED;
|
||||
}
|
||||
|
||||
status = snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input");
|
||||
snd_soc_dapm_sync(&codec->dapm);
|
||||
status = snd_soc_dapm_disable_pin(dapm, "ANC Configure Input");
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
cleanup:
|
||||
mutex_unlock(&drvdata->ctrl_lock);
|
||||
@ -1947,6 +1947,7 @@ static int ab8500_audio_init_audioblock(struct snd_soc_codec *codec)
|
||||
static int ab8500_audio_setup_mics(struct snd_soc_codec *codec,
|
||||
struct amic_settings *amics)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
u8 value8;
|
||||
unsigned int value;
|
||||
int status;
|
||||
@ -1973,15 +1974,15 @@ static int ab8500_audio_setup_mics(struct snd_soc_codec *codec,
|
||||
dev_dbg(codec->dev, "%s: Mic 1a regulator: %s\n", __func__,
|
||||
amic_micbias_str(amics->mic1a_micbias));
|
||||
route = &ab8500_dapm_routes_mic1a_vamicx[amics->mic1a_micbias];
|
||||
status = snd_soc_dapm_add_routes(&codec->dapm, route, 1);
|
||||
status = snd_soc_dapm_add_routes(dapm, route, 1);
|
||||
dev_dbg(codec->dev, "%s: Mic 1b regulator: %s\n", __func__,
|
||||
amic_micbias_str(amics->mic1b_micbias));
|
||||
route = &ab8500_dapm_routes_mic1b_vamicx[amics->mic1b_micbias];
|
||||
status |= snd_soc_dapm_add_routes(&codec->dapm, route, 1);
|
||||
status |= snd_soc_dapm_add_routes(dapm, route, 1);
|
||||
dev_dbg(codec->dev, "%s: Mic 2 regulator: %s\n", __func__,
|
||||
amic_micbias_str(amics->mic2_micbias));
|
||||
route = &ab8500_dapm_routes_mic2_vamicx[amics->mic2_micbias];
|
||||
status |= snd_soc_dapm_add_routes(&codec->dapm, route, 1);
|
||||
status |= snd_soc_dapm_add_routes(dapm, route, 1);
|
||||
if (status < 0) {
|
||||
dev_err(codec->dev,
|
||||
"%s: Failed to add AMic-regulator DAPM-routes (%d).\n",
|
||||
@ -2461,6 +2462,7 @@ static void ab8500_codec_of_probe(struct device *dev, struct device_node *np,
|
||||
|
||||
static int ab8500_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct device *dev = codec->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
@ -2541,7 +2543,7 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec)
|
||||
&ab8500_filter_controls[AB8500_FILTER_SID_FIR].private_value;
|
||||
drvdata->sid_fir_values = (long *)fc->value;
|
||||
|
||||
(void)snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input");
|
||||
snd_soc_dapm_disable_pin(dapm, "ANC Configure Input");
|
||||
|
||||
mutex_init(&drvdata->ctrl_lock);
|
||||
|
||||
|
@ -44,10 +44,6 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
|
||||
return snd_ac97_set_rate(ac97, reg, substream->runtime->rate);
|
||||
}
|
||||
|
||||
#define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
|
||||
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
|
||||
SNDRV_PCM_RATE_48000)
|
||||
|
||||
static const struct snd_soc_dai_ops ac97_dai_ops = {
|
||||
.prepare = ac97_prepare,
|
||||
};
|
||||
@ -58,13 +54,13 @@ static struct snd_soc_dai_driver ac97_dai = {
|
||||
.stream_name = "AC97 Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = STD_AC97_RATES,
|
||||
.rates = SNDRV_PCM_RATE_KNOT,
|
||||
.formats = SND_SOC_STD_AC97_FMTS,},
|
||||
.capture = {
|
||||
.stream_name = "AC97 Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = STD_AC97_RATES,
|
||||
.rates = SNDRV_PCM_RATE_KNOT,
|
||||
.formats = SND_SOC_STD_AC97_FMTS,},
|
||||
.ops = &ac97_dai_ops,
|
||||
};
|
||||
|
@ -251,7 +251,7 @@ static int ad1836_resume(struct snd_soc_codec *codec)
|
||||
static int ad1836_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
int num_dacs, num_adcs;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
@ -1444,7 +1444,6 @@ static int adau1373_set_bias_level(struct snd_soc_codec *codec,
|
||||
ADAU1373_PWDN_CTRL3_PWR_EN, 0);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
@ -101,6 +102,10 @@
|
||||
|
||||
#define ADAU1701_FIRMWARE "adau1701.bin"
|
||||
|
||||
static const char * const supply_names[] = {
|
||||
"dvdd", "avdd"
|
||||
};
|
||||
|
||||
struct adau1701 {
|
||||
int gpio_nreset;
|
||||
int gpio_pll_mode[2];
|
||||
@ -112,6 +117,7 @@ struct adau1701 {
|
||||
u8 pin_config[12];
|
||||
|
||||
struct sigmadsp *sigmadsp;
|
||||
struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new adau1701_controls[] = {
|
||||
@ -565,7 +571,6 @@ static int adau1701_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -669,6 +674,13 @@ static int adau1701_probe(struct snd_soc_codec *codec)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies),
|
||||
adau1701->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to enable regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Let the pll_clkdiv variable default to something that won't happen
|
||||
* at runtime. That way, we can postpone the firmware download from
|
||||
@ -680,7 +692,7 @@ static int adau1701_probe(struct snd_soc_codec *codec)
|
||||
/* initalize with pre-configured pll mode settings */
|
||||
ret = adau1701_reset(codec, adau1701->pll_clkdiv, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto exit_regulators_disable;
|
||||
|
||||
/* set up pin config */
|
||||
val = 0;
|
||||
@ -696,10 +708,60 @@ static int adau1701_probe(struct snd_soc_codec *codec)
|
||||
regmap_write(adau1701->regmap, ADAU1701_PINCONF_1, val);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_regulators_disable:
|
||||
|
||||
regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adau1701_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (gpio_is_valid(adau1701->gpio_nreset))
|
||||
gpio_set_value_cansleep(adau1701->gpio_nreset, 0);
|
||||
|
||||
regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int adau1701_suspend(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies),
|
||||
adau1701->supplies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adau1701_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies),
|
||||
adau1701->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to enable regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return adau1701_reset(codec, adau1701->pll_clkdiv, 0);
|
||||
}
|
||||
#else
|
||||
#define adau1701_resume NULL
|
||||
#define adau1701_suspend NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct snd_soc_codec_driver adau1701_codec_drv = {
|
||||
.probe = adau1701_probe,
|
||||
.remove = adau1701_remove,
|
||||
.resume = adau1701_resume,
|
||||
.suspend = adau1701_suspend,
|
||||
.set_bias_level = adau1701_set_bias_level,
|
||||
.idle_bias_off = true,
|
||||
|
||||
@ -730,32 +792,58 @@ static int adau1701_i2c_probe(struct i2c_client *client,
|
||||
struct device *dev = &client->dev;
|
||||
int gpio_nreset = -EINVAL;
|
||||
int gpio_pll_mode[2] = { -EINVAL, -EINVAL };
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
adau1701 = devm_kzalloc(dev, sizeof(*adau1701), GFP_KERNEL);
|
||||
if (!adau1701)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
|
||||
adau1701->supplies[i].supply = supply_names[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(adau1701->supplies),
|
||||
adau1701->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to get regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies),
|
||||
adau1701->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulators: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
adau1701->client = client;
|
||||
adau1701->regmap = devm_regmap_init(dev, NULL, client,
|
||||
&adau1701_regmap);
|
||||
if (IS_ERR(adau1701->regmap))
|
||||
return PTR_ERR(adau1701->regmap);
|
||||
if (IS_ERR(adau1701->regmap)) {
|
||||
ret = PTR_ERR(adau1701->regmap);
|
||||
goto exit_regulators_disable;
|
||||
}
|
||||
|
||||
|
||||
if (dev->of_node) {
|
||||
gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0);
|
||||
if (gpio_nreset < 0 && gpio_nreset != -ENOENT)
|
||||
return gpio_nreset;
|
||||
if (gpio_nreset < 0 && gpio_nreset != -ENOENT) {
|
||||
ret = gpio_nreset;
|
||||
goto exit_regulators_disable;
|
||||
}
|
||||
|
||||
gpio_pll_mode[0] = of_get_named_gpio(dev->of_node,
|
||||
"adi,pll-mode-gpios", 0);
|
||||
if (gpio_pll_mode[0] < 0 && gpio_pll_mode[0] != -ENOENT)
|
||||
return gpio_pll_mode[0];
|
||||
if (gpio_pll_mode[0] < 0 && gpio_pll_mode[0] != -ENOENT) {
|
||||
ret = gpio_pll_mode[0];
|
||||
goto exit_regulators_disable;
|
||||
}
|
||||
|
||||
gpio_pll_mode[1] = of_get_named_gpio(dev->of_node,
|
||||
"adi,pll-mode-gpios", 1);
|
||||
if (gpio_pll_mode[1] < 0 && gpio_pll_mode[1] != -ENOENT)
|
||||
return gpio_pll_mode[1];
|
||||
if (gpio_pll_mode[1] < 0 && gpio_pll_mode[1] != -ENOENT) {
|
||||
ret = gpio_pll_mode[1];
|
||||
goto exit_regulators_disable;
|
||||
}
|
||||
|
||||
of_property_read_u32(dev->of_node, "adi,pll-clkdiv",
|
||||
&adau1701->pll_clkdiv);
|
||||
@ -769,7 +857,7 @@ static int adau1701_i2c_probe(struct i2c_client *client,
|
||||
ret = devm_gpio_request_one(dev, gpio_nreset, GPIOF_OUT_INIT_LOW,
|
||||
"ADAU1701 Reset");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto exit_regulators_disable;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(gpio_pll_mode[0]) &&
|
||||
@ -778,13 +866,13 @@ static int adau1701_i2c_probe(struct i2c_client *client,
|
||||
GPIOF_OUT_INIT_LOW,
|
||||
"ADAU1701 PLL mode 0");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto exit_regulators_disable;
|
||||
|
||||
ret = devm_gpio_request_one(dev, gpio_pll_mode[1],
|
||||
GPIOF_OUT_INIT_LOW,
|
||||
"ADAU1701 PLL mode 1");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto exit_regulators_disable;
|
||||
}
|
||||
|
||||
adau1701->gpio_nreset = gpio_nreset;
|
||||
@ -795,11 +883,17 @@ static int adau1701_i2c_probe(struct i2c_client *client,
|
||||
|
||||
adau1701->sigmadsp = devm_sigmadsp_init_i2c(client,
|
||||
&adau1701_sigmadsp_ops, ADAU1701_FIRMWARE);
|
||||
if (IS_ERR(adau1701->sigmadsp))
|
||||
return PTR_ERR(adau1701->sigmadsp);
|
||||
if (IS_ERR(adau1701->sigmadsp)) {
|
||||
ret = PTR_ERR(adau1701->sigmadsp);
|
||||
goto exit_regulators_disable;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv,
|
||||
&adau1701_dai, 1);
|
||||
|
||||
exit_regulators_disable:
|
||||
|
||||
regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -466,7 +466,6 @@ static int adau1761_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -483,6 +482,7 @@ static enum adau1761_output_mode adau1761_get_lineout_mode(
|
||||
|
||||
static int adau1761_setup_digmic_jackdetect(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct adau1761_platform_data *pdata = codec->dev->platform_data;
|
||||
struct adau *adau = snd_soc_codec_get_drvdata(codec);
|
||||
enum adau1761_digmic_jackdet_pin_mode mode;
|
||||
@ -515,21 +515,18 @@ static int adau1761_setup_digmic_jackdetect(struct snd_soc_codec *codec)
|
||||
if (ret)
|
||||
return ret;
|
||||
case ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE: /* fallthrough */
|
||||
ret = snd_soc_dapm_add_routes(&codec->dapm,
|
||||
adau1761_no_dmic_routes,
|
||||
ret = snd_soc_dapm_add_routes(dapm, adau1761_no_dmic_routes,
|
||||
ARRAY_SIZE(adau1761_no_dmic_routes));
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC:
|
||||
ret = snd_soc_dapm_new_controls(&codec->dapm,
|
||||
adau1761_dmic_widgets,
|
||||
ret = snd_soc_dapm_new_controls(dapm, adau1761_dmic_widgets,
|
||||
ARRAY_SIZE(adau1761_dmic_widgets));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = snd_soc_dapm_add_routes(&codec->dapm,
|
||||
adau1761_dmic_routes,
|
||||
ret = snd_soc_dapm_add_routes(dapm, adau1761_dmic_routes,
|
||||
ARRAY_SIZE(adau1761_dmic_routes));
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -547,6 +544,7 @@ static int adau1761_setup_digmic_jackdetect(struct snd_soc_codec *codec)
|
||||
|
||||
static int adau1761_setup_headphone_mode(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct adau *adau = snd_soc_codec_get_drvdata(codec);
|
||||
struct adau1761_platform_data *pdata = codec->dev->platform_data;
|
||||
enum adau1761_output_mode mode;
|
||||
@ -577,12 +575,12 @@ static int adau1761_setup_headphone_mode(struct snd_soc_codec *codec)
|
||||
}
|
||||
|
||||
if (mode == ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS) {
|
||||
ret = snd_soc_dapm_new_controls(&codec->dapm,
|
||||
ret = snd_soc_dapm_new_controls(dapm,
|
||||
adau1761_capless_dapm_widgets,
|
||||
ARRAY_SIZE(adau1761_capless_dapm_widgets));
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = snd_soc_dapm_add_routes(&codec->dapm,
|
||||
ret = snd_soc_dapm_add_routes(dapm,
|
||||
adau1761_capless_dapm_routes,
|
||||
ARRAY_SIZE(adau1761_capless_dapm_routes));
|
||||
} else {
|
||||
@ -590,12 +588,12 @@ static int adau1761_setup_headphone_mode(struct snd_soc_codec *codec)
|
||||
ARRAY_SIZE(adau1761_mono_controls));
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = snd_soc_dapm_new_controls(&codec->dapm,
|
||||
ret = snd_soc_dapm_new_controls(dapm,
|
||||
adau1761_mono_dapm_widgets,
|
||||
ARRAY_SIZE(adau1761_mono_dapm_widgets));
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = snd_soc_dapm_add_routes(&codec->dapm,
|
||||
ret = snd_soc_dapm_add_routes(dapm,
|
||||
adau1761_mono_dapm_routes,
|
||||
ARRAY_SIZE(adau1761_mono_dapm_routes));
|
||||
}
|
||||
@ -640,6 +638,7 @@ static bool adau1761_readable_register(struct device *dev, unsigned int reg)
|
||||
|
||||
static int adau1761_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct adau1761_platform_data *pdata = codec->dev->platform_data;
|
||||
struct adau *adau = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
@ -692,14 +691,12 @@ static int adau1761_codec_probe(struct snd_soc_codec *codec)
|
||||
return ret;
|
||||
|
||||
if (adau->type == ADAU1761) {
|
||||
ret = snd_soc_dapm_new_controls(&codec->dapm,
|
||||
adau1761_dapm_widgets,
|
||||
ret = snd_soc_dapm_new_controls(dapm, adau1761_dapm_widgets,
|
||||
ARRAY_SIZE(adau1761_dapm_widgets));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = snd_soc_dapm_add_routes(&codec->dapm,
|
||||
adau1761_dapm_routes,
|
||||
ret = snd_soc_dapm_add_routes(dapm, adau1761_dapm_routes,
|
||||
ARRAY_SIZE(adau1761_dapm_routes));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -339,7 +339,6 @@ static int adau1781_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -383,6 +382,7 @@ static int adau1781_set_input_mode(struct adau *adau, unsigned int reg,
|
||||
|
||||
static int adau1781_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct adau1781_platform_data *pdata = dev_get_platdata(codec->dev);
|
||||
struct adau *adau = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
@ -403,19 +403,17 @@ static int adau1781_codec_probe(struct snd_soc_codec *codec)
|
||||
}
|
||||
|
||||
if (pdata && pdata->use_dmic) {
|
||||
ret = snd_soc_dapm_new_controls(&codec->dapm,
|
||||
ret = snd_soc_dapm_new_controls(dapm,
|
||||
adau1781_dmic_dapm_widgets,
|
||||
ARRAY_SIZE(adau1781_dmic_dapm_widgets));
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = snd_soc_dapm_add_routes(&codec->dapm,
|
||||
adau1781_dmic_dapm_routes,
|
||||
ret = snd_soc_dapm_add_routes(dapm, adau1781_dmic_dapm_routes,
|
||||
ARRAY_SIZE(adau1781_dmic_dapm_routes));
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
ret = snd_soc_dapm_add_routes(&codec->dapm,
|
||||
adau1781_adc_dapm_routes,
|
||||
ret = snd_soc_dapm_add_routes(dapm, adau1781_adc_dapm_routes,
|
||||
ARRAY_SIZE(adau1781_adc_dapm_routes));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -155,6 +155,7 @@ static int adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct adau *adau = snd_soc_codec_get_drvdata(codec);
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
struct snd_soc_dapm_update update;
|
||||
@ -188,7 +189,7 @@ static int adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol,
|
||||
update.reg = reg;
|
||||
update.val = val;
|
||||
|
||||
snd_soc_dapm_mux_update_power(&codec->dapm, kcontrol,
|
||||
snd_soc_dapm_mux_update_power(dapm, kcontrol,
|
||||
ucontrol->value.enumerated.item[0], e, &update);
|
||||
}
|
||||
|
||||
@ -444,8 +445,8 @@ static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id,
|
||||
static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai,
|
||||
int clk_id, unsigned int freq, int dir)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(dai->codec);
|
||||
struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
|
||||
struct snd_soc_dapm_context *dapm = &dai->codec->dapm;
|
||||
|
||||
switch (clk_id) {
|
||||
case ADAU17X1_CLK_SRC_MCLK:
|
||||
@ -804,6 +805,7 @@ EXPORT_SYMBOL_GPL(adau17x1_setup_firmware);
|
||||
|
||||
int adau17x1_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct adau *adau = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
@ -811,14 +813,13 @@ int adau17x1_add_widgets(struct snd_soc_codec *codec)
|
||||
ARRAY_SIZE(adau17x1_controls));
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = snd_soc_dapm_new_controls(&codec->dapm, adau17x1_dapm_widgets,
|
||||
ret = snd_soc_dapm_new_controls(dapm, adau17x1_dapm_widgets,
|
||||
ARRAY_SIZE(adau17x1_dapm_widgets));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (adau17x1_has_dsp(adau)) {
|
||||
ret = snd_soc_dapm_new_controls(&codec->dapm,
|
||||
adau17x1_dsp_dapm_widgets,
|
||||
ret = snd_soc_dapm_new_controls(dapm, adau17x1_dsp_dapm_widgets,
|
||||
ARRAY_SIZE(adau17x1_dsp_dapm_widgets));
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -840,21 +841,20 @@ EXPORT_SYMBOL_GPL(adau17x1_add_widgets);
|
||||
|
||||
int adau17x1_add_routes(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct adau *adau = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_dapm_add_routes(&codec->dapm, adau17x1_dapm_routes,
|
||||
ret = snd_soc_dapm_add_routes(dapm, adau17x1_dapm_routes,
|
||||
ARRAY_SIZE(adau17x1_dapm_routes));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (adau17x1_has_dsp(adau)) {
|
||||
ret = snd_soc_dapm_add_routes(&codec->dapm,
|
||||
adau17x1_dsp_dapm_routes,
|
||||
ret = snd_soc_dapm_add_routes(dapm, adau17x1_dsp_dapm_routes,
|
||||
ARRAY_SIZE(adau17x1_dsp_dapm_routes));
|
||||
} else {
|
||||
ret = snd_soc_dapm_add_routes(&codec->dapm,
|
||||
adau17x1_no_dsp_dapm_routes,
|
||||
ret = snd_soc_dapm_add_routes(dapm, adau17x1_no_dsp_dapm_routes,
|
||||
ARRAY_SIZE(adau17x1_no_dsp_dapm_routes));
|
||||
}
|
||||
return ret;
|
||||
|
@ -202,7 +202,7 @@ static const struct snd_soc_dapm_route adau1977_dapm_routes[] = {
|
||||
ADAU1977_REG_DC_HPF_CAL, (x) - 1, 1, 0)
|
||||
|
||||
#define ADAU1977_DC_SUB_SWITCH(x) \
|
||||
SOC_SINGLE("ADC" #x " DC Substraction Capture Switch", \
|
||||
SOC_SINGLE("ADC" #x " DC Subtraction Capture Switch", \
|
||||
ADAU1977_REG_DC_HPF_CAL, (x) + 3, 1, 0)
|
||||
|
||||
static const struct snd_kcontrol_new adau1977_snd_controls[] = {
|
||||
@ -485,7 +485,7 @@ static int adau1977_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
|
||||
ret = adau1977_power_enable(adau1977);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
@ -493,12 +493,7 @@ static int adau1977_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adau1977_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
|
||||
@ -853,12 +848,13 @@ static int adau1977_set_sysclk(struct snd_soc_codec *codec,
|
||||
|
||||
static int adau1977_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
switch (adau1977->type) {
|
||||
case ADAU1977:
|
||||
ret = snd_soc_dapm_new_controls(&codec->dapm,
|
||||
ret = snd_soc_dapm_new_controls(dapm,
|
||||
adau1977_micbias_dapm_widgets,
|
||||
ARRAY_SIZE(adau1977_micbias_dapm_widgets));
|
||||
if (ret < 0)
|
||||
|
@ -539,7 +539,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
|
||||
unsigned int freq, int dir)
|
||||
{
|
||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
|
||||
if (dir == SND_SOC_CLOCK_IN) {
|
||||
switch (clk_id) {
|
||||
@ -622,6 +622,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
|
||||
static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id,
|
||||
int source, unsigned int freq_in, unsigned int freq_out)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int pll_ctrl1 = 0;
|
||||
unsigned int pll_ctrl2 = 0;
|
||||
@ -687,7 +688,7 @@ static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id,
|
||||
|
||||
adav80x->pll_src = source;
|
||||
|
||||
snd_soc_dapm_sync(&codec->dapm);
|
||||
snd_soc_dapm_sync(dapm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -714,7 +715,6 @@ static int adav80x_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -801,11 +801,12 @@ static struct snd_soc_dai_driver adav80x_dais[] = {
|
||||
|
||||
static int adav80x_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
/* Force PLLs on for SYSCLK output */
|
||||
snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1");
|
||||
snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2");
|
||||
snd_soc_dapm_force_enable_pin(dapm, "PLL1");
|
||||
snd_soc_dapm_force_enable_pin(dapm, "PLL2");
|
||||
|
||||
/* Power down S/PDIF receiver, since it is currently not supported */
|
||||
regmap_write(adav80x->regmap, ADAV80X_PLL_OUTE, 0x20);
|
||||
|
@ -341,7 +341,6 @@ static int ak4535_set_bias_level(struct snd_soc_codec *codec,
|
||||
snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -412,7 +412,7 @@ static int ak4641_set_bias_level(struct snd_soc_codec *codec,
|
||||
snd_soc_update_bits(codec, AK4641_DAC, 0x20, 0x20);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
if (pdata && gpio_is_valid(pdata->gpio_power))
|
||||
gpio_set_value(pdata->gpio_power, 1);
|
||||
mdelay(1);
|
||||
@ -439,7 +439,6 @@ static int ak4641_set_bias_level(struct snd_soc_codec *codec,
|
||||
regcache_mark_dirty(ak4641->regmap);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -482,7 +482,6 @@ static int ak4642_set_bias_level(struct snd_soc_codec *codec,
|
||||
snd_soc_update_bits(codec, PW_MGMT1, PMVCM, PMVCM);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -577,7 +577,6 @@ static int ak4671_set_bias_level(struct snd_soc_codec *codec,
|
||||
snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -826,7 +826,6 @@ static int alc5623_set_bias_level(struct snd_soc_codec *codec,
|
||||
snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1, 0);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -894,7 +893,7 @@ static int alc5623_resume(struct snd_soc_codec *codec)
|
||||
static int alc5623_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
|
||||
alc5623_reset(codec);
|
||||
|
||||
|
@ -1000,7 +1000,6 @@ static int alc5632_set_bias_level(struct snd_soc_codec *codec,
|
||||
ALC5632_PWR_MANAG_ADD1_MASK, 0);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -208,11 +208,12 @@ static const struct snd_soc_dapm_widget arizona_spkr =
|
||||
|
||||
int arizona_init_spk(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkl, 1);
|
||||
ret = snd_soc_dapm_new_controls(dapm, &arizona_spkl, 1);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
@ -220,8 +221,7 @@ int arizona_init_spk(struct snd_soc_codec *codec)
|
||||
case WM8997:
|
||||
break;
|
||||
default:
|
||||
ret = snd_soc_dapm_new_controls(&codec->dapm,
|
||||
&arizona_spkr, 1);
|
||||
ret = snd_soc_dapm_new_controls(dapm, &arizona_spkr, 1);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
break;
|
||||
@ -258,13 +258,14 @@ static const struct snd_soc_dapm_route arizona_mono_routes[] = {
|
||||
|
||||
int arizona_init_mono(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARIZONA_MAX_OUTPUT; ++i) {
|
||||
if (arizona->pdata.out_mono[i])
|
||||
snd_soc_dapm_add_routes(&codec->dapm,
|
||||
snd_soc_dapm_add_routes(dapm,
|
||||
&arizona_mono_routes[i], 1);
|
||||
}
|
||||
|
||||
@ -274,6 +275,7 @@ EXPORT_SYMBOL_GPL(arizona_init_mono);
|
||||
|
||||
int arizona_init_gpio(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
int i;
|
||||
@ -281,23 +283,21 @@ int arizona_init_gpio(struct snd_soc_codec *codec)
|
||||
switch (arizona->type) {
|
||||
case WM5110:
|
||||
case WM8280:
|
||||
snd_soc_dapm_disable_pin(&codec->dapm, "DRC2 Signal Activity");
|
||||
snd_soc_dapm_disable_pin(dapm, "DRC2 Signal Activity");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
snd_soc_dapm_disable_pin(&codec->dapm, "DRC1 Signal Activity");
|
||||
snd_soc_dapm_disable_pin(dapm, "DRC1 Signal Activity");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {
|
||||
switch (arizona->pdata.gpio_defaults[i] & ARIZONA_GPN_FN_MASK) {
|
||||
case ARIZONA_GP_FN_DRC1_SIGNAL_DETECT:
|
||||
snd_soc_dapm_enable_pin(&codec->dapm,
|
||||
"DRC1 Signal Activity");
|
||||
snd_soc_dapm_enable_pin(dapm, "DRC1 Signal Activity");
|
||||
break;
|
||||
case ARIZONA_GP_FN_DRC2_SIGNAL_DETECT:
|
||||
snd_soc_dapm_enable_pin(&codec->dapm,
|
||||
"DRC2 Signal Activity");
|
||||
snd_soc_dapm_enable_pin(dapm, "DRC2 Signal Activity");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -851,6 +851,134 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_hp_ev);
|
||||
|
||||
static int arizona_dvfs_enable(struct snd_soc_codec *codec)
|
||||
{
|
||||
const struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
int ret;
|
||||
|
||||
ret = regulator_set_voltage(arizona->dcvdd, 1800000, 1800000);
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "Failed to boost DCVDD: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(arizona->regmap,
|
||||
ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
|
||||
ARIZONA_SUBSYS_MAX_FREQ,
|
||||
ARIZONA_SUBSYS_MAX_FREQ);
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "Failed to enable subsys max: %d\n", ret);
|
||||
regulator_set_voltage(arizona->dcvdd, 1200000, 1800000);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arizona_dvfs_disable(struct snd_soc_codec *codec)
|
||||
{
|
||||
const struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(arizona->regmap,
|
||||
ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
|
||||
ARIZONA_SUBSYS_MAX_FREQ, 0);
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "Failed to disable subsys max: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_set_voltage(arizona->dcvdd, 1200000, 1800000);
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "Failed to unboost DCVDD: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arizona_dvfs_up(struct snd_soc_codec *codec, unsigned int flags)
|
||||
{
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&priv->dvfs_lock);
|
||||
|
||||
if (!priv->dvfs_cached && !priv->dvfs_reqs) {
|
||||
ret = arizona_dvfs_enable(codec);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
priv->dvfs_reqs |= flags;
|
||||
err:
|
||||
mutex_unlock(&priv->dvfs_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_dvfs_up);
|
||||
|
||||
int arizona_dvfs_down(struct snd_soc_codec *codec, unsigned int flags)
|
||||
{
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int old_reqs;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&priv->dvfs_lock);
|
||||
|
||||
old_reqs = priv->dvfs_reqs;
|
||||
priv->dvfs_reqs &= ~flags;
|
||||
|
||||
if (!priv->dvfs_cached && old_reqs && !priv->dvfs_reqs)
|
||||
ret = arizona_dvfs_disable(codec);
|
||||
|
||||
mutex_unlock(&priv->dvfs_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_dvfs_down);
|
||||
|
||||
int arizona_dvfs_sysclk_ev(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&priv->dvfs_lock);
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
if (priv->dvfs_reqs)
|
||||
ret = arizona_dvfs_enable(codec);
|
||||
|
||||
priv->dvfs_cached = false;
|
||||
break;
|
||||
case SND_SOC_DAPM_PRE_PMD:
|
||||
/* We must ensure DVFS is disabled before the codec goes into
|
||||
* suspend so that we are never in an illegal state of DVFS
|
||||
* enabled without enough DCVDD
|
||||
*/
|
||||
priv->dvfs_cached = true;
|
||||
|
||||
if (priv->dvfs_reqs)
|
||||
ret = arizona_dvfs_disable(codec);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->dvfs_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_dvfs_sysclk_ev);
|
||||
|
||||
void arizona_init_dvfs(struct arizona_priv *priv)
|
||||
{
|
||||
mutex_init(&priv->dvfs_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_init_dvfs);
|
||||
|
||||
static unsigned int arizona_sysclk_48k_rates[] = {
|
||||
6144000,
|
||||
12288000,
|
||||
@ -1266,7 +1394,7 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
|
||||
int base = dai->driver->base;
|
||||
int i, sr_val;
|
||||
int i, sr_val, ret;
|
||||
|
||||
/*
|
||||
* We will need to be more flexible than this in future,
|
||||
@ -1282,6 +1410,23 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
|
||||
}
|
||||
sr_val = i;
|
||||
|
||||
switch (priv->arizona->type) {
|
||||
case WM5102:
|
||||
case WM8997:
|
||||
if (arizona_sr_vals[sr_val] >= 88200)
|
||||
ret = arizona_dvfs_up(codec, ARIZONA_DVFS_SR1_RQ);
|
||||
else
|
||||
ret = arizona_dvfs_down(codec, ARIZONA_DVFS_SR1_RQ);
|
||||
|
||||
if (ret) {
|
||||
arizona_aif_err(dai, "Failed to change DVFS %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (dai_priv->clk) {
|
||||
case ARIZONA_CLK_SYSCLK:
|
||||
switch (priv->arizona->type) {
|
||||
@ -1474,6 +1619,7 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
|
||||
int clk_id, unsigned int freq, int dir)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
|
||||
struct snd_soc_dapm_route routes[2];
|
||||
@ -1504,15 +1650,15 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
|
||||
|
||||
routes[0].source = arizona_dai_clk_str(dai_priv->clk);
|
||||
routes[1].source = arizona_dai_clk_str(dai_priv->clk);
|
||||
snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
|
||||
snd_soc_dapm_del_routes(dapm, routes, ARRAY_SIZE(routes));
|
||||
|
||||
routes[0].source = arizona_dai_clk_str(clk_id);
|
||||
routes[1].source = arizona_dai_clk_str(clk_id);
|
||||
snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
|
||||
snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
|
||||
|
||||
dai_priv->clk = clk_id;
|
||||
|
||||
return snd_soc_dapm_sync(&codec->dapm);
|
||||
return snd_soc_dapm_sync(dapm);
|
||||
}
|
||||
|
||||
static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
|
||||
|
@ -60,6 +60,9 @@
|
||||
#define ARIZONA_MAX_DAI 6
|
||||
#define ARIZONA_MAX_ADSP 4
|
||||
|
||||
#define ARIZONA_DVFS_SR1_RQ 0x001
|
||||
#define ARIZONA_DVFS_ADSP1_RQ 0x100
|
||||
|
||||
struct arizona;
|
||||
struct wm_adsp;
|
||||
|
||||
@ -84,6 +87,10 @@ struct arizona_priv {
|
||||
|
||||
unsigned int spk_ena:2;
|
||||
unsigned int spk_ena_pending:1;
|
||||
|
||||
unsigned int dvfs_reqs;
|
||||
struct mutex dvfs_lock;
|
||||
bool dvfs_cached;
|
||||
};
|
||||
|
||||
#define ARIZONA_NUM_MIXER_INPUTS 103
|
||||
@ -107,8 +114,8 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
|
||||
arizona_mixer_tlv)
|
||||
|
||||
#define ARIZONA_MUX_ENUM_DECL(name, reg) \
|
||||
SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \
|
||||
arizona_mixer_texts, arizona_mixer_values)
|
||||
SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL( \
|
||||
name, reg, 0, 0xff, arizona_mixer_texts, arizona_mixer_values)
|
||||
|
||||
#define ARIZONA_MUX_CTL_DECL(name) \
|
||||
const struct snd_kcontrol_new name##_mux = \
|
||||
@ -245,6 +252,12 @@ struct arizona_fll {
|
||||
char clock_ok_name[ARIZONA_FLL_NAME_LEN];
|
||||
};
|
||||
|
||||
extern int arizona_dvfs_up(struct snd_soc_codec *codec, unsigned int flags);
|
||||
extern int arizona_dvfs_down(struct snd_soc_codec *codec, unsigned int flags);
|
||||
extern int arizona_dvfs_sysclk_ev(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event);
|
||||
extern void arizona_init_dvfs(struct arizona_priv *priv);
|
||||
|
||||
extern int arizona_init_fll(struct arizona *arizona, int id, int base,
|
||||
int lock_irq, int ok_irq, struct arizona_fll *fll);
|
||||
extern int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
|
||||
|
@ -63,7 +63,7 @@ static int bt_sco_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_device_id bt_sco_driver_ids[] = {
|
||||
static const struct platform_device_id bt_sco_driver_ids[] = {
|
||||
{
|
||||
.name = "dfbmcs320",
|
||||
},
|
||||
@ -74,9 +74,18 @@ static struct platform_device_id bt_sco_driver_ids[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, bt_sco_driver_ids);
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
static const struct of_device_id bt_sco_codec_of_match[] = {
|
||||
{ .compatible = "delta,dfbmcs320", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bt_sco_codec_of_match);
|
||||
#endif
|
||||
|
||||
static struct platform_driver bt_sco_driver = {
|
||||
.driver = {
|
||||
.name = "bt-sco",
|
||||
.of_match_table = of_match_ptr(bt_sco_codec_of_match),
|
||||
},
|
||||
.probe = bt_sco_probe,
|
||||
.remove = bt_sco_remove,
|
||||
|
@ -92,7 +92,6 @@ static int cq93vc_set_bias_level(struct snd_soc_codec *codec,
|
||||
DAVINCI_VC_REG12_POWER_ALL_OFF);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
|
@ -503,7 +503,6 @@ static int cs4265_set_bias_level(struct snd_soc_codec *codec,
|
||||
CS4265_PWRCTL_PDN);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -897,7 +897,7 @@ static int cs42l52_set_bias_level(struct snd_soc_codec *codec,
|
||||
CS42L52_PWRCTL1_PDN_CODEC, 0);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
regcache_cache_only(cs42l52->regmap, false);
|
||||
regcache_sync(cs42l52->regmap);
|
||||
}
|
||||
@ -908,7 +908,6 @@ static int cs42l52_set_bias_level(struct snd_soc_codec *codec,
|
||||
regcache_cache_only(cs42l52->regmap, true);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -956,7 +955,7 @@ static void cs42l52_beep_work(struct work_struct *work)
|
||||
struct cs42l52_private *cs42l52 =
|
||||
container_of(work, struct cs42l52_private, beep_work);
|
||||
struct snd_soc_codec *codec = cs42l52->codec;
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
int i;
|
||||
int val = 0;
|
||||
int best = 0;
|
||||
|
@ -953,7 +953,7 @@ static int cs42l56_set_bias_level(struct snd_soc_codec *codec,
|
||||
CS42L56_PDN_ALL_MASK, 0);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
regcache_cache_only(cs42l56->regmap, false);
|
||||
regcache_sync(cs42l56->regmap);
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(cs42l56->supplies),
|
||||
@ -978,7 +978,6 @@ static int cs42l56_set_bias_level(struct snd_soc_codec *codec,
|
||||
cs42l56->supplies);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1026,7 +1025,7 @@ static void cs42l56_beep_work(struct work_struct *work)
|
||||
struct cs42l56_private *cs42l56 =
|
||||
container_of(work, struct cs42l56_private, beep_work);
|
||||
struct snd_soc_codec *codec = cs42l56->codec;
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
int i;
|
||||
int val = 0;
|
||||
int best = 0;
|
||||
|
@ -1208,7 +1208,7 @@ static int cs42l73_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
regcache_cache_only(cs42l73->regmap, false);
|
||||
regcache_sync(cs42l73->regmap);
|
||||
}
|
||||
@ -1228,7 +1228,6 @@ static int cs42l73_set_bias_level(struct snd_soc_codec *codec,
|
||||
snd_soc_update_bits(codec, CS42L73_DMMCC, CS42L73_MCLKDIS, 1);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -380,7 +380,7 @@ EXPORT_SYMBOL_GPL(cs42xx8_regmap_config);
|
||||
static int cs42xx8_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
|
||||
switch (cs42xx8->drvdata->num_adcs) {
|
||||
case 3:
|
||||
|
@ -333,7 +333,7 @@ static int cx20442_set_bias_level(struct snd_soc_codec *codec,
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
if (codec->dapm.bias_level != SND_SOC_BIAS_STANDBY)
|
||||
if (snd_soc_codec_get_bias_level(codec) != SND_SOC_BIAS_STANDBY)
|
||||
break;
|
||||
if (IS_ERR(cx20442->por))
|
||||
err = PTR_ERR(cx20442->por);
|
||||
@ -341,7 +341,7 @@ static int cx20442_set_bias_level(struct snd_soc_codec *codec,
|
||||
err = regulator_enable(cx20442->por);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level != SND_SOC_BIAS_PREPARE)
|
||||
if (snd_soc_codec_get_bias_level(codec) != SND_SOC_BIAS_PREPARE)
|
||||
break;
|
||||
if (IS_ERR(cx20442->por))
|
||||
err = PTR_ERR(cx20442->por);
|
||||
@ -351,8 +351,6 @@ static int cx20442_set_bias_level(struct snd_soc_codec *codec,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!err)
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -1374,7 +1374,7 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
/* Enable VMID reference & master bias */
|
||||
snd_soc_update_bits(codec, DA7213_REFERENCES,
|
||||
DA7213_VMID_EN | DA7213_BIAS_EN,
|
||||
@ -1387,7 +1387,6 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec,
|
||||
DA7213_VMID_EN | DA7213_BIAS_EN, 0);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1432,7 +1432,7 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
/* Init Codec */
|
||||
snd_soc_write(codec, DA732X_REG_REF1,
|
||||
DA732X_VMID_FASTCHG);
|
||||
@ -1502,8 +1502,6 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1364,7 +1364,7 @@ static int da9055_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
/* Enable VMID reference & master bias */
|
||||
snd_soc_update_bits(codec, DA9055_REFERENCES,
|
||||
DA9055_VMID_EN | DA9055_BIAS_EN,
|
||||
@ -1377,7 +1377,6 @@ static int da9055_set_bias_level(struct snd_soc_codec *codec,
|
||||
DA9055_VMID_EN | DA9055_BIAS_EN, 0);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -536,7 +536,7 @@ static int es8328_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
snd_soc_update_bits(codec, ES8328_CONTROL1,
|
||||
ES8328_CONTROL1_VMIDSEL_MASK |
|
||||
ES8328_CONTROL1_ENREF,
|
||||
@ -566,7 +566,6 @@ static int es8328_set_bias_level(struct snd_soc_codec *codec,
|
||||
0);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -909,8 +909,6 @@ static int isabelle_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -258,7 +258,7 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
/* The only way to clear the suspend flag is to reset the codec */
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
|
||||
jz4740_codec_wakeup(regmap);
|
||||
|
||||
mask = JZ4740_CODEC_1_VREF_DISABLE |
|
||||
@ -281,8 +281,6 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -23,11 +23,6 @@
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
struct lm4857 {
|
||||
struct regmap *regmap;
|
||||
uint8_t mode;
|
||||
};
|
||||
|
||||
static const struct reg_default lm4857_default_regs[] = {
|
||||
{ 0x0, 0x00 },
|
||||
{ 0x1, 0x00 },
|
||||
@ -46,66 +41,33 @@ static const struct reg_default lm4857_default_regs[] = {
|
||||
#define LM4857_WAKEUP 5
|
||||
#define LM4857_EPGAIN 4
|
||||
|
||||
static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
|
||||
static const unsigned int lm4857_mode_values[] = {
|
||||
0,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
};
|
||||
|
||||
ucontrol->value.integer.value[0] = lm4857->mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
|
||||
uint8_t value = ucontrol->value.integer.value[0];
|
||||
|
||||
lm4857->mode = value;
|
||||
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
|
||||
regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, value + 6);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lm4857_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F,
|
||||
lm4857->mode + 6);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *lm4857_mode[] = {
|
||||
static const char * const lm4857_mode_texts[] = {
|
||||
"Off",
|
||||
"Earpiece",
|
||||
"Loudspeaker",
|
||||
"Loudspeaker + Headphone",
|
||||
"Headphone",
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(lm4857_mode_enum, lm4857_mode);
|
||||
static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(lm4857_mode_enum,
|
||||
LM4857_CTRL, 0, 0xf, lm4857_mode_texts, lm4857_mode_values);
|
||||
|
||||
static const struct snd_kcontrol_new lm4857_mode_ctrl =
|
||||
SOC_DAPM_ENUM("Mode", lm4857_mode_enum);
|
||||
|
||||
static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("IN"),
|
||||
|
||||
SND_SOC_DAPM_DEMUX("Mode", SND_SOC_NOPM, 0, 0, &lm4857_mode_ctrl),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("LS"),
|
||||
SND_SOC_DAPM_OUTPUT("HP"),
|
||||
SND_SOC_DAPM_OUTPUT("EP"),
|
||||
@ -127,24 +89,18 @@ static const struct snd_kcontrol_new lm4857_controls[] = {
|
||||
LM4857_WAKEUP, 1, 0),
|
||||
SOC_SINGLE("Earpiece 6dB Playback Switch", LM4857_CTRL,
|
||||
LM4857_EPGAIN, 1, 0),
|
||||
|
||||
SOC_ENUM_EXT("Mode", lm4857_mode_enum,
|
||||
lm4857_get_mode, lm4857_set_mode),
|
||||
};
|
||||
|
||||
/* There is a demux between the input signal and the output signals.
|
||||
* Currently there is no easy way to model it in ASoC and since it does not make
|
||||
* much of a difference in practice simply connect the input direclty to the
|
||||
* outputs. */
|
||||
static const struct snd_soc_dapm_route lm4857_routes[] = {
|
||||
{"LS", NULL, "IN"},
|
||||
{"HP", NULL, "IN"},
|
||||
{"EP", NULL, "IN"},
|
||||
{ "Mode", NULL, "IN" },
|
||||
{ "LS", "Loudspeaker", "Mode" },
|
||||
{ "LS", "Loudspeaker + Headphone", "Mode" },
|
||||
{ "HP", "Headphone", "Mode" },
|
||||
{ "HP", "Loudspeaker + Headphone", "Mode" },
|
||||
{ "EP", "Earpiece", "Mode" },
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_lm4857 = {
|
||||
.set_bias_level = lm4857_set_bias_level,
|
||||
|
||||
static struct snd_soc_component_driver lm4857_component_driver = {
|
||||
.controls = lm4857_controls,
|
||||
.num_controls = ARRAY_SIZE(lm4857_controls),
|
||||
.dapm_widgets = lm4857_dapm_widgets,
|
||||
@ -167,25 +123,14 @@ static const struct regmap_config lm4857_regmap_config = {
|
||||
static int lm4857_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct lm4857 *lm4857;
|
||||
struct regmap *regmap;
|
||||
|
||||
lm4857 = devm_kzalloc(&i2c->dev, sizeof(*lm4857), GFP_KERNEL);
|
||||
if (!lm4857)
|
||||
return -ENOMEM;
|
||||
regmap = devm_regmap_init_i2c(i2c, &lm4857_regmap_config);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
i2c_set_clientdata(i2c, lm4857);
|
||||
|
||||
lm4857->regmap = devm_regmap_init_i2c(i2c, &lm4857_regmap_config);
|
||||
if (IS_ERR(lm4857->regmap))
|
||||
return PTR_ERR(lm4857->regmap);
|
||||
|
||||
return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0);
|
||||
}
|
||||
|
||||
static int lm4857_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
snd_soc_unregister_codec(&i2c->dev);
|
||||
return 0;
|
||||
return devm_snd_soc_register_component(&i2c->dev,
|
||||
&lm4857_component_driver, NULL, 0);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id lm4857_i2c_id[] = {
|
||||
@ -200,7 +145,6 @@ static struct i2c_driver lm4857_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = lm4857_i2c_probe,
|
||||
.remove = lm4857_i2c_remove,
|
||||
.id_table = lm4857_i2c_id,
|
||||
};
|
||||
|
||||
|
@ -1271,7 +1271,7 @@ static int lm49453_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
|
||||
regcache_sync(lm49453->regmap);
|
||||
|
||||
snd_soc_update_bits(codec, LM49453_P0_PMC_SETUP_REG,
|
||||
@ -1284,8 +1284,6 @@ static int lm49453_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1571,7 +1571,7 @@ static int max98088_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
|
||||
regcache_sync(max98088->regmap);
|
||||
|
||||
snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
|
||||
@ -1584,7 +1584,6 @@ static int max98088_set_bias_level(struct snd_soc_codec *codec,
|
||||
regcache_mark_dirty(max98088->regmap);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1500,7 +1500,7 @@ static const struct snd_soc_dapm_route max98091_dapm_routes[] = {
|
||||
static int max98090_add_widgets(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
|
||||
snd_soc_add_codec_controls(codec, max98090_snd_controls,
|
||||
ARRAY_SIZE(max98090_snd_controls));
|
||||
@ -1798,16 +1798,17 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec,
|
||||
* away from ON. Disable the clock in that case, otherwise
|
||||
* enable it.
|
||||
*/
|
||||
if (!IS_ERR(max98090->mclk)) {
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
|
||||
clk_disable_unprepare(max98090->mclk);
|
||||
else
|
||||
clk_prepare_enable(max98090->mclk);
|
||||
}
|
||||
if (IS_ERR(max98090->mclk))
|
||||
break;
|
||||
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON)
|
||||
clk_disable_unprepare(max98090->mclk);
|
||||
else
|
||||
clk_prepare_enable(max98090->mclk);
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
ret = regcache_sync(max98090->regmap);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev,
|
||||
@ -1824,7 +1825,6 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec,
|
||||
regcache_mark_dirty(max98090->regmap);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2187,7 +2187,6 @@ static void max98090_jack_work(struct work_struct *work)
|
||||
struct max98090_priv,
|
||||
jack_work.work);
|
||||
struct snd_soc_codec *codec = max98090->codec;
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int status = 0;
|
||||
int reg;
|
||||
|
||||
@ -2266,8 +2265,6 @@ static void max98090_jack_work(struct work_struct *work)
|
||||
|
||||
snd_soc_jack_report(max98090->jack, status,
|
||||
SND_JACK_HEADSET | SND_JACK_BTN_0);
|
||||
|
||||
snd_soc_dapm_sync(dapm);
|
||||
}
|
||||
|
||||
static irqreturn_t max98090_interrupt(int irq, void *data)
|
||||
@ -2422,6 +2419,8 @@ static int max98090_probe(struct snd_soc_codec *codec)
|
||||
struct max98090_cdata *cdata;
|
||||
enum max98090_type devtype;
|
||||
int ret = 0;
|
||||
int err;
|
||||
unsigned int micbias;
|
||||
|
||||
dev_dbg(codec->dev, "max98090_probe\n");
|
||||
|
||||
@ -2506,8 +2505,17 @@ static int max98090_probe(struct snd_soc_codec *codec)
|
||||
snd_soc_write(codec, M98090_REG_BIAS_CONTROL,
|
||||
M98090_VCM_MODE_MASK);
|
||||
|
||||
err = device_property_read_u32(codec->dev, "maxim,micbias", &micbias);
|
||||
if (err) {
|
||||
micbias = M98090_MBVSEL_2V8;
|
||||
dev_info(codec->dev, "use default 2.8v micbias\n");
|
||||
} else if (micbias < M98090_MBVSEL_2V2 || micbias > M98090_MBVSEL_2V8) {
|
||||
dev_err(codec->dev, "micbias out of range 0x%x\n", micbias);
|
||||
micbias = M98090_MBVSEL_2V8;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE,
|
||||
M98090_MBVSEL_MASK, M98090_MBVSEL_2V8);
|
||||
M98090_MBVSEL_MASK, micbias);
|
||||
|
||||
max98090_add_widgets(codec);
|
||||
|
||||
|
@ -1650,16 +1650,17 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec,
|
||||
* away from ON. Disable the clock in that case, otherwise
|
||||
* enable it.
|
||||
*/
|
||||
if (!IS_ERR(max98095->mclk)) {
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
|
||||
clk_disable_unprepare(max98095->mclk);
|
||||
else
|
||||
clk_prepare_enable(max98095->mclk);
|
||||
}
|
||||
if (IS_ERR(max98095->mclk))
|
||||
break;
|
||||
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON)
|
||||
clk_disable_unprepare(max98095->mclk);
|
||||
else
|
||||
clk_prepare_enable(max98095->mclk);
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
ret = regcache_sync(max98095->regmap);
|
||||
|
||||
if (ret != 0) {
|
||||
@ -1678,7 +1679,6 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec,
|
||||
regcache_mark_dirty(max98095->regmap);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2198,7 +2198,7 @@ static int max98095_suspend(struct snd_soc_codec *codec)
|
||||
if (max98095->headphone_jack || max98095->mic_jack)
|
||||
max98095_jack_detect_disable(codec);
|
||||
|
||||
max98095_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2208,7 +2208,7 @@ static int max98095_resume(struct snd_soc_codec *codec)
|
||||
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
|
||||
struct i2c_client *client = to_i2c_client(codec->dev);
|
||||
|
||||
max98095_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
if (max98095->headphone_jack || max98095->mic_jack) {
|
||||
max98095_jack_detect_enable(codec);
|
||||
@ -2301,8 +2301,8 @@ static int max98095_probe(struct snd_soc_codec *codec)
|
||||
/* register an audio interrupt */
|
||||
ret = request_threaded_irq(client->irq, NULL,
|
||||
max98095_report_jack,
|
||||
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
|
||||
"max98095", codec);
|
||||
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
|
||||
IRQF_ONESHOT, "max98095", codec);
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "Failed to request IRQ: %d\n", ret);
|
||||
goto err_access;
|
||||
|
@ -60,13 +60,12 @@ static int max98357a_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct gpio_desc *sdmode;
|
||||
|
||||
sdmode = devm_gpiod_get(codec->dev, "sdmode");
|
||||
sdmode = devm_gpiod_get(codec->dev, "sdmode", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(sdmode)) {
|
||||
dev_err(codec->dev, "%s() unable to get sdmode GPIO: %ld\n",
|
||||
__func__, PTR_ERR(sdmode));
|
||||
return PTR_ERR(sdmode);
|
||||
}
|
||||
gpiod_direction_output(sdmode, 0);
|
||||
snd_soc_codec_set_drvdata(codec, sdmode);
|
||||
|
||||
return 0;
|
||||
|
@ -252,7 +252,7 @@ static int max9850_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
ret = regcache_sync(max9850->regmap);
|
||||
if (ret) {
|
||||
dev_err(codec->dev,
|
||||
@ -264,7 +264,6 @@ static int max9850_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_OFF:
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -523,7 +523,7 @@ static int ml26124_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
/* VMID ON */
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
snd_soc_update_bits(codec, ML26124_PW_REF_PW_MNG,
|
||||
ML26124_VMID, ML26124_VMID);
|
||||
msleep(500);
|
||||
@ -536,7 +536,6 @@ static int ml26124_set_bias_level(struct snd_soc_codec *codec,
|
||||
ML26124_VMID, 0);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -242,7 +242,7 @@ static int pcm512x_overclock_pll_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
switch (codec->dapm.bias_level) {
|
||||
switch (snd_soc_codec_get_bias_level(codec)) {
|
||||
case SND_SOC_BIAS_OFF:
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
break;
|
||||
@ -270,7 +270,7 @@ static int pcm512x_overclock_dsp_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
switch (codec->dapm.bias_level) {
|
||||
switch (snd_soc_codec_get_bias_level(codec)) {
|
||||
case SND_SOC_BIAS_OFF:
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
break;
|
||||
@ -298,7 +298,7 @@ static int pcm512x_overclock_dac_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
switch (codec->dapm.bias_level) {
|
||||
switch (snd_soc_codec_get_bias_level(codec)) {
|
||||
case SND_SOC_BIAS_OFF:
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
break;
|
||||
@ -641,8 +641,6 @@ static int pcm512x_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -301,6 +301,7 @@ static int rt286_support_power_controls[] = {
|
||||
|
||||
static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm;
|
||||
unsigned int val, buf;
|
||||
|
||||
*hp = false;
|
||||
@ -308,6 +309,9 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic)
|
||||
|
||||
if (!rt286->codec)
|
||||
return -EINVAL;
|
||||
|
||||
dapm = snd_soc_codec_get_dapm(rt286->codec);
|
||||
|
||||
if (rt286->pdata.cbj_en) {
|
||||
regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf);
|
||||
*hp = buf & 0x80000000;
|
||||
@ -316,14 +320,11 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic)
|
||||
regmap_update_bits(rt286->regmap,
|
||||
RT286_DC_GAIN, 0x200, 0x200);
|
||||
|
||||
snd_soc_dapm_force_enable_pin(&rt286->codec->dapm,
|
||||
"HV");
|
||||
snd_soc_dapm_force_enable_pin(&rt286->codec->dapm,
|
||||
"VREF");
|
||||
snd_soc_dapm_force_enable_pin(dapm, "HV");
|
||||
snd_soc_dapm_force_enable_pin(dapm, "VREF");
|
||||
/* power LDO1 */
|
||||
snd_soc_dapm_force_enable_pin(&rt286->codec->dapm,
|
||||
"LDO1");
|
||||
snd_soc_dapm_sync(&rt286->codec->dapm);
|
||||
snd_soc_dapm_force_enable_pin(dapm, "LDO1");
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24);
|
||||
msleep(50);
|
||||
@ -360,11 +361,11 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic)
|
||||
*mic = buf & 0x80000000;
|
||||
}
|
||||
|
||||
snd_soc_dapm_disable_pin(&rt286->codec->dapm, "HV");
|
||||
snd_soc_dapm_disable_pin(&rt286->codec->dapm, "VREF");
|
||||
snd_soc_dapm_disable_pin(dapm, "HV");
|
||||
snd_soc_dapm_disable_pin(dapm, "VREF");
|
||||
if (!*hp)
|
||||
snd_soc_dapm_disable_pin(&rt286->codec->dapm, "LDO1");
|
||||
snd_soc_dapm_sync(&rt286->codec->dapm);
|
||||
snd_soc_dapm_disable_pin(dapm, "LDO1");
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -391,6 +392,7 @@ static void rt286_jack_detect_work(struct work_struct *work)
|
||||
|
||||
int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
rt286->jack = jack;
|
||||
@ -398,7 +400,7 @@ int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
|
||||
if (jack) {
|
||||
/* enable IRQ */
|
||||
if (rt286->jack->status & SND_JACK_HEADPHONE)
|
||||
snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO1");
|
||||
snd_soc_dapm_force_enable_pin(dapm, "LDO1");
|
||||
regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x2, 0x2);
|
||||
/* Send an initial empty report */
|
||||
snd_soc_jack_report(rt286->jack, rt286->jack->status,
|
||||
@ -406,9 +408,9 @@ int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
|
||||
} else {
|
||||
/* disable IRQ */
|
||||
regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x2, 0x0);
|
||||
snd_soc_dapm_disable_pin(&codec->dapm, "LDO1");
|
||||
snd_soc_dapm_disable_pin(dapm, "LDO1");
|
||||
}
|
||||
snd_soc_dapm_sync(&codec->dapm);
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -985,7 +987,7 @@ static int rt286_set_bias_level(struct snd_soc_codec *codec,
|
||||
{
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) {
|
||||
if (SND_SOC_BIAS_STANDBY == snd_soc_codec_get_bias_level(codec)) {
|
||||
snd_soc_write(codec,
|
||||
RT286_SET_AUDIO_POWER, AC_PWRST_D0);
|
||||
snd_soc_update_bits(codec,
|
||||
@ -1012,7 +1014,6 @@ static int rt286_set_bias_level(struct snd_soc_codec *codec,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1546,7 +1546,7 @@ static int rt5631_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
|
||||
RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS,
|
||||
RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS);
|
||||
@ -1569,7 +1569,6 @@ static int rt5631_set_bias_level(struct snd_soc_codec *codec,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1615,7 +1614,7 @@ static int rt5631_probe(struct snd_soc_codec *codec)
|
||||
RT5631_DMIC_R_CH_LATCH_RISING);
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = SND_SOC_BIAS_STANDBY;
|
||||
snd_soc_codec_init_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1870,7 +1870,7 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec,
|
||||
{
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) {
|
||||
if (SND_SOC_BIAS_OFF == snd_soc_codec_get_bias_level(codec)) {
|
||||
snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
|
||||
RT5640_PWR_VREF1 | RT5640_PWR_MB |
|
||||
RT5640_PWR_BG | RT5640_PWR_VREF2,
|
||||
@ -1902,7 +1902,6 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1935,11 +1934,12 @@ EXPORT_SYMBOL_GPL(rt5640_dmic_enable);
|
||||
|
||||
static int rt5640_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
rt5640->codec = codec;
|
||||
|
||||
rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
|
||||
snd_soc_update_bits(codec, RT5640_DUMMY1, 0x0301, 0x0301);
|
||||
snd_soc_update_bits(codec, RT5640_MICBIAS, 0x0030, 0x0030);
|
||||
@ -1951,18 +1951,18 @@ static int rt5640_probe(struct snd_soc_codec *codec)
|
||||
snd_soc_add_codec_controls(codec,
|
||||
rt5640_specific_snd_controls,
|
||||
ARRAY_SIZE(rt5640_specific_snd_controls));
|
||||
snd_soc_dapm_new_controls(&codec->dapm,
|
||||
snd_soc_dapm_new_controls(dapm,
|
||||
rt5640_specific_dapm_widgets,
|
||||
ARRAY_SIZE(rt5640_specific_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(&codec->dapm,
|
||||
snd_soc_dapm_add_routes(dapm,
|
||||
rt5640_specific_dapm_routes,
|
||||
ARRAY_SIZE(rt5640_specific_dapm_routes));
|
||||
break;
|
||||
case RT5640_ID_5639:
|
||||
snd_soc_dapm_new_controls(&codec->dapm,
|
||||
snd_soc_dapm_new_controls(dapm,
|
||||
rt5639_specific_dapm_widgets,
|
||||
ARRAY_SIZE(rt5639_specific_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(&codec->dapm,
|
||||
snd_soc_dapm_add_routes(dapm,
|
||||
rt5639_specific_dapm_routes,
|
||||
ARRAY_SIZE(rt5639_specific_dapm_routes));
|
||||
break;
|
||||
@ -1991,7 +1991,7 @@ static int rt5640_suspend(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
rt5640_reset(codec);
|
||||
regcache_cache_only(rt5640->regmap, true);
|
||||
regcache_mark_dirty(rt5640->regmap);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -105,6 +105,7 @@
|
||||
#define RT5645_TDM_CTRL_1 0x77
|
||||
#define RT5645_TDM_CTRL_2 0x78
|
||||
#define RT5645_TDM_CTRL_3 0x79
|
||||
#define RT5650_TDM_CTRL_4 0x7a
|
||||
|
||||
/* Function - Analog */
|
||||
#define RT5645_GLB_CLK 0x80
|
||||
@ -942,10 +943,6 @@
|
||||
#define RT5645_I2S2_SDI_I2S2 (0x1 << 6)
|
||||
|
||||
/* ADC/DAC Clock Control 1 (0x73) */
|
||||
#define RT5645_I2S_BCLK_MS1_MASK (0x1 << 15)
|
||||
#define RT5645_I2S_BCLK_MS1_SFT 15
|
||||
#define RT5645_I2S_BCLK_MS1_32 (0x0 << 15)
|
||||
#define RT5645_I2S_BCLK_MS1_64 (0x1 << 15)
|
||||
#define RT5645_I2S_PD1_MASK (0x7 << 12)
|
||||
#define RT5645_I2S_PD1_SFT 12
|
||||
#define RT5645_I2S_PD1_1 (0x0 << 12)
|
||||
@ -1067,13 +1064,14 @@
|
||||
#define RT5645_SCLK_SRC_SFT 14
|
||||
#define RT5645_SCLK_SRC_MCLK (0x0 << 14)
|
||||
#define RT5645_SCLK_SRC_PLL1 (0x1 << 14)
|
||||
#define RT5645_SCLK_SRC_RCCLK (0x2 << 14) /* 15MHz */
|
||||
#define RT5645_PLL1_SRC_MASK (0x3 << 12)
|
||||
#define RT5645_PLL1_SRC_SFT 12
|
||||
#define RT5645_PLL1_SRC_MCLK (0x0 << 12)
|
||||
#define RT5645_PLL1_SRC_BCLK1 (0x1 << 12)
|
||||
#define RT5645_PLL1_SRC_BCLK2 (0x2 << 12)
|
||||
#define RT5645_PLL1_SRC_BCLK3 (0x3 << 12)
|
||||
#define RT5645_SCLK_SRC_RCCLK (0x2 << 14)
|
||||
#define RT5645_PLL1_SRC_MASK (0x7 << 11)
|
||||
#define RT5645_PLL1_SRC_SFT 11
|
||||
#define RT5645_PLL1_SRC_MCLK (0x0 << 11)
|
||||
#define RT5645_PLL1_SRC_BCLK1 (0x1 << 11)
|
||||
#define RT5645_PLL1_SRC_BCLK2 (0x2 << 11)
|
||||
#define RT5645_PLL1_SRC_BCLK3 (0x3 << 11)
|
||||
#define RT5645_PLL1_SRC_RCCLK (0x4 << 11)
|
||||
#define RT5645_PLL1_PD_MASK (0x1 << 3)
|
||||
#define RT5645_PLL1_PD_SFT 3
|
||||
#define RT5645_PLL1_PD_1 (0x0 << 3)
|
||||
@ -2147,6 +2145,7 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5645_DMIC1_DISABLE,
|
||||
RT5645_DMIC_DATA_IN2P,
|
||||
RT5645_DMIC_DATA_GPIO6,
|
||||
RT5645_DMIC_DATA_GPIO10,
|
||||
@ -2154,6 +2153,7 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5645_DMIC2_DISABLE,
|
||||
RT5645_DMIC_DATA_IN2N,
|
||||
RT5645_DMIC_DATA_GPIO5,
|
||||
RT5645_DMIC_DATA_GPIO11,
|
||||
@ -2184,6 +2184,7 @@ struct rt5645_priv {
|
||||
struct i2c_client *i2c;
|
||||
struct snd_soc_jack *hp_jack;
|
||||
struct snd_soc_jack *mic_jack;
|
||||
struct snd_soc_jack *btn_jack;
|
||||
struct delayed_work jack_detect_work;
|
||||
|
||||
int codec_type;
|
||||
@ -2196,9 +2197,12 @@ struct rt5645_priv {
|
||||
int pll_src;
|
||||
int pll_in;
|
||||
int pll_out;
|
||||
|
||||
int jack_type;
|
||||
bool en_button_func;
|
||||
};
|
||||
|
||||
int rt5645_set_jack_detect(struct snd_soc_codec *codec,
|
||||
struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack);
|
||||
|
||||
struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack,
|
||||
struct snd_soc_jack *btn_jack);
|
||||
#endif /* __RT5645_H__ */
|
||||
|
@ -1571,7 +1571,7 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
|
||||
{
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) {
|
||||
if (SND_SOC_BIAS_STANDBY == snd_soc_codec_get_bias_level(codec)) {
|
||||
snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
|
||||
RT5651_PWR_VREF1 | RT5651_PWR_MB |
|
||||
RT5651_PWR_BG | RT5651_PWR_VREF2,
|
||||
@ -1604,7 +1604,6 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1625,7 +1624,7 @@ static int rt5651_probe(struct snd_soc_codec *codec)
|
||||
RT5651_PWR_FV1 | RT5651_PWR_FV2,
|
||||
RT5651_PWR_FV1 | RT5651_PWR_FV2);
|
||||
|
||||
rt5651_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -416,12 +416,12 @@ static bool rt5670_readable_register(struct device *dev, unsigned int reg)
|
||||
static int rt5670_headset_detect(struct snd_soc_codec *codec, int jack_insert)
|
||||
{
|
||||
int val;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (jack_insert) {
|
||||
snd_soc_dapm_force_enable_pin(&codec->dapm,
|
||||
"Mic Det Power");
|
||||
snd_soc_dapm_sync(&codec->dapm);
|
||||
snd_soc_dapm_force_enable_pin(dapm, "Mic Det Power");
|
||||
snd_soc_dapm_sync(dapm);
|
||||
snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x0);
|
||||
snd_soc_update_bits(codec, RT5670_CJ_CTRL2,
|
||||
RT5670_CBJ_DET_MODE | RT5670_CBJ_MN_JD,
|
||||
@ -447,15 +447,15 @@ static int rt5670_headset_detect(struct snd_soc_codec *codec, int jack_insert)
|
||||
} else {
|
||||
snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x4);
|
||||
rt5670->jack_type = SND_JACK_HEADPHONE;
|
||||
snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power");
|
||||
snd_soc_dapm_sync(&codec->dapm);
|
||||
snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
|
||||
snd_soc_dapm_sync(dapm);
|
||||
}
|
||||
} else {
|
||||
snd_soc_update_bits(codec, RT5670_INT_IRQ_ST, 0x8, 0x0);
|
||||
snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x4);
|
||||
rt5670->jack_type = 0;
|
||||
snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power");
|
||||
snd_soc_dapm_sync(&codec->dapm);
|
||||
snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
|
||||
snd_soc_dapm_sync(dapm);
|
||||
}
|
||||
|
||||
return rt5670->jack_type;
|
||||
@ -2603,7 +2603,7 @@ static int rt5670_set_bias_level(struct snd_soc_codec *codec,
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) {
|
||||
if (SND_SOC_BIAS_STANDBY == snd_soc_codec_get_bias_level(codec)) {
|
||||
snd_soc_update_bits(codec, RT5670_PWR_ANLG1,
|
||||
RT5670_PWR_VREF1 | RT5670_PWR_MB |
|
||||
RT5670_PWR_BG | RT5670_PWR_VREF2,
|
||||
@ -2647,30 +2647,30 @@ static int rt5670_set_bias_level(struct snd_soc_codec *codec,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5670_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
switch (snd_soc_read(codec, RT5670_RESET) & RT5670_ID_MASK) {
|
||||
case RT5670_ID_5670:
|
||||
case RT5670_ID_5671:
|
||||
snd_soc_dapm_new_controls(&codec->dapm,
|
||||
snd_soc_dapm_new_controls(dapm,
|
||||
rt5670_specific_dapm_widgets,
|
||||
ARRAY_SIZE(rt5670_specific_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(&codec->dapm,
|
||||
snd_soc_dapm_add_routes(dapm,
|
||||
rt5670_specific_dapm_routes,
|
||||
ARRAY_SIZE(rt5670_specific_dapm_routes));
|
||||
break;
|
||||
case RT5670_ID_5672:
|
||||
snd_soc_dapm_new_controls(&codec->dapm,
|
||||
snd_soc_dapm_new_controls(dapm,
|
||||
rt5672_specific_dapm_widgets,
|
||||
ARRAY_SIZE(rt5672_specific_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(&codec->dapm,
|
||||
snd_soc_dapm_add_routes(dapm,
|
||||
rt5672_specific_dapm_routes,
|
||||
ARRAY_SIZE(rt5672_specific_dapm_routes));
|
||||
break;
|
||||
|
@ -820,7 +820,7 @@ static int rt5677_dsp_vad_put(struct snd_kcontrol *kcontrol,
|
||||
|
||||
rt5677->dsp_vad_en = !!ucontrol->value.integer.value[0];
|
||||
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
|
||||
rt5677_set_dsp_vad(codec, rt5677->dsp_vad_en);
|
||||
|
||||
return 0;
|
||||
@ -1060,6 +1060,7 @@ int rt5677_sel_asrc_clk_src(struct snd_soc_codec *codec,
|
||||
unsigned int asrc5_mask = 0, asrc5_value = 0;
|
||||
unsigned int asrc6_mask = 0, asrc6_value = 0;
|
||||
unsigned int asrc7_mask = 0, asrc7_value = 0;
|
||||
unsigned int asrc8_mask = 0, asrc8_value = 0;
|
||||
|
||||
switch (clk_src) {
|
||||
case RT5677_CLK_SEL_SYS:
|
||||
@ -1196,10 +1197,108 @@ int rt5677_sel_asrc_clk_src(struct snd_soc_codec *codec,
|
||||
regmap_update_bits(rt5677->regmap, RT5677_ASRC_7, asrc7_mask,
|
||||
asrc7_value);
|
||||
|
||||
/* ASRC 8 */
|
||||
if (filter_mask & RT5677_I2S1_SOURCE) {
|
||||
asrc8_mask |= RT5677_I2S1_CLK_SEL_MASK;
|
||||
asrc8_value = (asrc8_value & ~RT5677_I2S1_CLK_SEL_MASK)
|
||||
| ((clk_src - 1) << RT5677_I2S1_CLK_SEL_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5677_I2S2_SOURCE) {
|
||||
asrc8_mask |= RT5677_I2S2_CLK_SEL_MASK;
|
||||
asrc8_value = (asrc8_value & ~RT5677_I2S2_CLK_SEL_MASK)
|
||||
| ((clk_src - 1) << RT5677_I2S2_CLK_SEL_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5677_I2S3_SOURCE) {
|
||||
asrc8_mask |= RT5677_I2S3_CLK_SEL_MASK;
|
||||
asrc8_value = (asrc8_value & ~RT5677_I2S3_CLK_SEL_MASK)
|
||||
| ((clk_src - 1) << RT5677_I2S3_CLK_SEL_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5677_I2S4_SOURCE) {
|
||||
asrc8_mask |= RT5677_I2S4_CLK_SEL_MASK;
|
||||
asrc8_value = (asrc8_value & ~RT5677_I2S4_CLK_SEL_MASK)
|
||||
| ((clk_src - 1) << RT5677_I2S4_CLK_SEL_SFT);
|
||||
}
|
||||
|
||||
if (asrc8_mask)
|
||||
regmap_update_bits(rt5677->regmap, RT5677_ASRC_8, asrc8_mask,
|
||||
asrc8_value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt5677_sel_asrc_clk_src);
|
||||
|
||||
static int rt5677_dmic_use_asrc(struct snd_soc_dapm_widget *source,
|
||||
struct snd_soc_dapm_widget *sink)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
|
||||
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int asrc_setting;
|
||||
|
||||
switch (source->shift) {
|
||||
case 11:
|
||||
regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting);
|
||||
asrc_setting = (asrc_setting & RT5677_AD_STO1_CLK_SEL_MASK) >>
|
||||
RT5677_AD_STO1_CLK_SEL_SFT;
|
||||
if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
|
||||
asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case 10:
|
||||
regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting);
|
||||
asrc_setting = (asrc_setting & RT5677_AD_STO2_CLK_SEL_MASK) >>
|
||||
RT5677_AD_STO2_CLK_SEL_SFT;
|
||||
if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
|
||||
asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting);
|
||||
asrc_setting = (asrc_setting & RT5677_AD_STO3_CLK_SEL_MASK) >>
|
||||
RT5677_AD_STO3_CLK_SEL_SFT;
|
||||
if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
|
||||
asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting);
|
||||
asrc_setting = (asrc_setting & RT5677_AD_STO4_CLK_SEL_MASK) >>
|
||||
RT5677_AD_STO4_CLK_SEL_SFT;
|
||||
if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
|
||||
asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
regmap_read(rt5677->regmap, RT5677_ASRC_6, &asrc_setting);
|
||||
asrc_setting = (asrc_setting & RT5677_AD_MONOL_CLK_SEL_MASK) >>
|
||||
RT5677_AD_MONOL_CLK_SEL_SFT;
|
||||
if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
|
||||
asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
regmap_read(rt5677->regmap, RT5677_ASRC_6, &asrc_setting);
|
||||
asrc_setting = (asrc_setting & RT5677_AD_MONOR_CLK_SEL_MASK) >>
|
||||
RT5677_AD_MONOR_CLK_SEL_SFT;
|
||||
if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC &&
|
||||
asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC)
|
||||
return 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Digital Mixer */
|
||||
static const struct snd_kcontrol_new rt5677_sto1_adc_l_mix[] = {
|
||||
SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO1_ADC_MIXER,
|
||||
@ -2479,7 +2578,7 @@ static int rt5677_vref_event(struct snd_soc_dapm_widget *w,
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
if (codec->dapm.bias_level != SND_SOC_BIAS_ON &&
|
||||
if (snd_soc_codec_get_bias_level(codec) != SND_SOC_BIAS_ON &&
|
||||
!rt5677->is_vref_slow) {
|
||||
mdelay(20);
|
||||
regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1,
|
||||
@ -3057,12 +3156,12 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = {
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route rt5677_dapm_routes[] = {
|
||||
{ "Stereo1 DMIC Mux", NULL, "DMIC STO1 ASRC", can_use_asrc },
|
||||
{ "Stereo2 DMIC Mux", NULL, "DMIC STO2 ASRC", can_use_asrc },
|
||||
{ "Stereo3 DMIC Mux", NULL, "DMIC STO3 ASRC", can_use_asrc },
|
||||
{ "Stereo4 DMIC Mux", NULL, "DMIC STO4 ASRC", can_use_asrc },
|
||||
{ "Mono DMIC L Mux", NULL, "DMIC MONO L ASRC", can_use_asrc },
|
||||
{ "Mono DMIC R Mux", NULL, "DMIC MONO R ASRC", can_use_asrc },
|
||||
{ "Stereo1 DMIC Mux", NULL, "DMIC STO1 ASRC", rt5677_dmic_use_asrc },
|
||||
{ "Stereo2 DMIC Mux", NULL, "DMIC STO2 ASRC", rt5677_dmic_use_asrc },
|
||||
{ "Stereo3 DMIC Mux", NULL, "DMIC STO3 ASRC", rt5677_dmic_use_asrc },
|
||||
{ "Stereo4 DMIC Mux", NULL, "DMIC STO4 ASRC", rt5677_dmic_use_asrc },
|
||||
{ "Mono DMIC L Mux", NULL, "DMIC MONO L ASRC", rt5677_dmic_use_asrc },
|
||||
{ "Mono DMIC R Mux", NULL, "DMIC MONO R ASRC", rt5677_dmic_use_asrc },
|
||||
{ "I2S1", NULL, "I2S1 ASRC", can_use_asrc},
|
||||
{ "I2S2", NULL, "I2S2 ASRC", can_use_asrc},
|
||||
{ "I2S3", NULL, "I2S3 ASRC", can_use_asrc},
|
||||
@ -4353,7 +4452,7 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) {
|
||||
rt5677_set_dsp_vad(codec, false);
|
||||
|
||||
regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1,
|
||||
@ -4395,7 +4494,6 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -4606,22 +4704,23 @@ static void rt5677_free_gpio(struct i2c_client *i2c)
|
||||
|
||||
static int rt5677_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
|
||||
int i;
|
||||
|
||||
rt5677->codec = codec;
|
||||
|
||||
if (rt5677->pdata.dmic2_clk_pin == RT5677_DMIC_CLK2) {
|
||||
snd_soc_dapm_add_routes(&codec->dapm,
|
||||
snd_soc_dapm_add_routes(dapm,
|
||||
rt5677_dmic2_clk_2,
|
||||
ARRAY_SIZE(rt5677_dmic2_clk_2));
|
||||
} else { /*use dmic1 clock by default*/
|
||||
snd_soc_dapm_add_routes(&codec->dapm,
|
||||
snd_soc_dapm_add_routes(dapm,
|
||||
rt5677_dmic2_clk_1,
|
||||
ARRAY_SIZE(rt5677_dmic2_clk_1));
|
||||
}
|
||||
|
||||
rt5677_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
|
||||
regmap_write(rt5677->regmap, RT5677_DIG_MISC, 0x0020);
|
||||
regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x0c00);
|
||||
@ -4667,6 +4766,8 @@ static int rt5677_remove(struct snd_soc_codec *codec)
|
||||
regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec);
|
||||
if (gpio_is_valid(rt5677->pow_ldo2))
|
||||
gpio_set_value_cansleep(rt5677->pow_ldo2, 0);
|
||||
if (gpio_is_valid(rt5677->reset_pin))
|
||||
gpio_set_value_cansleep(rt5677->reset_pin, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -4682,6 +4783,8 @@ static int rt5677_suspend(struct snd_soc_codec *codec)
|
||||
|
||||
if (gpio_is_valid(rt5677->pow_ldo2))
|
||||
gpio_set_value_cansleep(rt5677->pow_ldo2, 0);
|
||||
if (gpio_is_valid(rt5677->reset_pin))
|
||||
gpio_set_value_cansleep(rt5677->reset_pin, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -4692,10 +4795,13 @@ static int rt5677_resume(struct snd_soc_codec *codec)
|
||||
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (!rt5677->dsp_vad_en) {
|
||||
if (gpio_is_valid(rt5677->pow_ldo2)) {
|
||||
if (gpio_is_valid(rt5677->pow_ldo2))
|
||||
gpio_set_value_cansleep(rt5677->pow_ldo2, 1);
|
||||
if (gpio_is_valid(rt5677->reset_pin))
|
||||
gpio_set_value_cansleep(rt5677->reset_pin, 1);
|
||||
if (gpio_is_valid(rt5677->pow_ldo2) ||
|
||||
gpio_is_valid(rt5677->reset_pin))
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
regcache_cache_only(rt5677->regmap, false);
|
||||
regcache_sync(rt5677->regmap);
|
||||
@ -4933,6 +5039,8 @@ static int rt5677_parse_dt(struct rt5677_priv *rt5677, struct device_node *np)
|
||||
|
||||
rt5677->pow_ldo2 = of_get_named_gpio(np,
|
||||
"realtek,pow-ldo2-gpio", 0);
|
||||
rt5677->reset_pin = of_get_named_gpio(np,
|
||||
"realtek,reset-gpio", 0);
|
||||
|
||||
/*
|
||||
* POW_LDO2 is optional (it may be statically tied on the board).
|
||||
@ -4943,6 +5051,9 @@ static int rt5677_parse_dt(struct rt5677_priv *rt5677, struct device_node *np)
|
||||
if (!gpio_is_valid(rt5677->pow_ldo2) &&
|
||||
(rt5677->pow_ldo2 != -ENOENT))
|
||||
return rt5677->pow_ldo2;
|
||||
if (!gpio_is_valid(rt5677->reset_pin) &&
|
||||
(rt5677->reset_pin != -ENOENT))
|
||||
return rt5677->reset_pin;
|
||||
|
||||
of_property_read_u8_array(np, "realtek,gpio-config",
|
||||
rt5677->pdata.gpio_config, RT5677_GPIO_NUM);
|
||||
@ -5044,6 +5155,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
|
||||
}
|
||||
} else {
|
||||
rt5677->pow_ldo2 = -EINVAL;
|
||||
rt5677->reset_pin = -EINVAL;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(rt5677->pow_ldo2)) {
|
||||
@ -5055,6 +5167,21 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
|
||||
rt5677->pow_ldo2, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (gpio_is_valid(rt5677->reset_pin)) {
|
||||
ret = devm_gpio_request_one(&i2c->dev, rt5677->reset_pin,
|
||||
GPIOF_OUT_INIT_HIGH,
|
||||
"RT5677 RESET");
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c->dev, "Failed to request RESET %d: %d\n",
|
||||
rt5677->reset_pin, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (gpio_is_valid(rt5677->pow_ldo2) ||
|
||||
gpio_is_valid(rt5677->reset_pin)) {
|
||||
/* Wait a while until I2C bus becomes available. The datasheet
|
||||
* does not specify the exact we should wait but startup
|
||||
* sequence mentiones at least a few milliseconds.
|
||||
|
@ -1446,6 +1446,16 @@
|
||||
#define RT5677_DSP_OB_4_7_CLK_SEL_MASK (0xf << 8)
|
||||
#define RT5677_DSP_OB_4_7_CLK_SEL_SFT 8
|
||||
|
||||
/* ASRC Control 8 (0x8a) */
|
||||
#define RT5677_I2S1_CLK_SEL_MASK (0xf << 12)
|
||||
#define RT5677_I2S1_CLK_SEL_SFT 12
|
||||
#define RT5677_I2S2_CLK_SEL_MASK (0xf << 8)
|
||||
#define RT5677_I2S2_CLK_SEL_SFT 8
|
||||
#define RT5677_I2S3_CLK_SEL_MASK (0xf << 4)
|
||||
#define RT5677_I2S3_CLK_SEL_SFT 4
|
||||
#define RT5677_I2S4_CLK_SEL_MASK (0xf)
|
||||
#define RT5677_I2S4_CLK_SEL_SFT 0
|
||||
|
||||
/* VAD Function Control 4 (0x9f) */
|
||||
#define RT5677_VAD_SRC_MASK (0x7 << 8)
|
||||
#define RT5677_VAD_SRC_SFT 8
|
||||
@ -1744,6 +1754,10 @@ enum {
|
||||
RT5677_AD_MONO_R_FILTER = (0x1 << 12),
|
||||
RT5677_DSP_OB_0_3_FILTER = (0x1 << 13),
|
||||
RT5677_DSP_OB_4_7_FILTER = (0x1 << 14),
|
||||
RT5677_I2S1_SOURCE = (0x1 << 15),
|
||||
RT5677_I2S2_SOURCE = (0x1 << 16),
|
||||
RT5677_I2S3_SOURCE = (0x1 << 17),
|
||||
RT5677_I2S4_SOURCE = (0x1 << 18),
|
||||
};
|
||||
|
||||
struct rt5677_priv {
|
||||
@ -1762,6 +1776,7 @@ struct rt5677_priv {
|
||||
int pll_in;
|
||||
int pll_out;
|
||||
int pow_ldo2; /* POW_LDO2 pin */
|
||||
int reset_pin; /* RESET pin */
|
||||
enum rt5677_type type;
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
struct gpio_chip gpio_chip;
|
||||
|
@ -948,7 +948,7 @@ static int sgtl5000_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
ret = regulator_bulk_enable(
|
||||
ARRAY_SIZE(sgtl5000->supplies),
|
||||
sgtl5000->supplies);
|
||||
@ -979,7 +979,6 @@ static int sgtl5000_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1091,6 +1090,19 @@ static bool sgtl5000_readable(struct device *dev, unsigned int reg)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This precalculated table contains all (vag_val * 100 / lo_calcntrl) results
|
||||
* to select an appropriate lo_vol_* in SGTL5000_CHIP_LINE_OUT_VOL
|
||||
* The calculatation was done for all possible register values which
|
||||
* is the array index and the following formula: 10^((idx−15)/40) * 100
|
||||
*/
|
||||
static const u8 vol_quot_table[] = {
|
||||
42, 45, 47, 50, 53, 56, 60, 63,
|
||||
67, 71, 75, 79, 84, 89, 94, 100,
|
||||
106, 112, 119, 126, 133, 141, 150, 158,
|
||||
168, 178, 188, 200, 211, 224, 237, 251
|
||||
};
|
||||
|
||||
/*
|
||||
* sgtl5000 has 3 internal power supplies:
|
||||
* 1. VAG, normally set to vdda/2
|
||||
@ -1111,6 +1123,10 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
|
||||
u16 ana_pwr;
|
||||
u16 lreg_ctrl;
|
||||
int vag;
|
||||
int lo_vag;
|
||||
int vol_quot;
|
||||
int lo_vol;
|
||||
size_t i;
|
||||
struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
vdda = regulator_get_voltage(sgtl5000->supplies[VDDA].consumer);
|
||||
@ -1198,23 +1214,45 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
|
||||
SGTL5000_ANA_GND_MASK, vag << SGTL5000_ANA_GND_SHIFT);
|
||||
|
||||
/* set line out VAG to vddio / 2, in range (0.8v, 1.675v) */
|
||||
vag = vddio / 2;
|
||||
if (vag <= SGTL5000_LINE_OUT_GND_BASE)
|
||||
vag = 0;
|
||||
else if (vag >= SGTL5000_LINE_OUT_GND_BASE +
|
||||
lo_vag = vddio / 2;
|
||||
if (lo_vag <= SGTL5000_LINE_OUT_GND_BASE)
|
||||
lo_vag = 0;
|
||||
else if (lo_vag >= SGTL5000_LINE_OUT_GND_BASE +
|
||||
SGTL5000_LINE_OUT_GND_STP * SGTL5000_LINE_OUT_GND_MAX)
|
||||
vag = SGTL5000_LINE_OUT_GND_MAX;
|
||||
lo_vag = SGTL5000_LINE_OUT_GND_MAX;
|
||||
else
|
||||
vag = (vag - SGTL5000_LINE_OUT_GND_BASE) /
|
||||
lo_vag = (lo_vag - SGTL5000_LINE_OUT_GND_BASE) /
|
||||
SGTL5000_LINE_OUT_GND_STP;
|
||||
|
||||
snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
|
||||
SGTL5000_LINE_OUT_CURRENT_MASK |
|
||||
SGTL5000_LINE_OUT_GND_MASK,
|
||||
vag << SGTL5000_LINE_OUT_GND_SHIFT |
|
||||
lo_vag << SGTL5000_LINE_OUT_GND_SHIFT |
|
||||
SGTL5000_LINE_OUT_CURRENT_360u <<
|
||||
SGTL5000_LINE_OUT_CURRENT_SHIFT);
|
||||
|
||||
/*
|
||||
* Set lineout output level in range (0..31)
|
||||
* the same value is used for right and left channel
|
||||
*
|
||||
* Searching for a suitable index solving this formula:
|
||||
* idx = 40 * log10(vag_val / lo_cagcntrl) + 15
|
||||
*/
|
||||
vol_quot = (vag * 100) / lo_vag;
|
||||
lo_vol = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(vol_quot_table); i++) {
|
||||
if (vol_quot >= vol_quot_table[i])
|
||||
lo_vol = i;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_VOL,
|
||||
SGTL5000_LINE_OUT_VOL_RIGHT_MASK |
|
||||
SGTL5000_LINE_OUT_VOL_LEFT_MASK,
|
||||
lo_vol << SGTL5000_LINE_OUT_VOL_RIGHT_SHIFT |
|
||||
lo_vol << SGTL5000_LINE_OUT_VOL_LEFT_SHIFT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -395,7 +395,7 @@ struct snd_soc_dai_driver sirf_audio_codec_dai = {
|
||||
|
||||
static int sirf_audio_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
|
||||
pm_runtime_enable(codec->dev);
|
||||
|
||||
|
@ -194,7 +194,7 @@ static int sn95031_set_vaud_bias(struct snd_soc_codec *codec,
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) {
|
||||
pr_debug("vaud_bias powering up pll\n");
|
||||
/* power up the pll */
|
||||
snd_soc_write(codec, SN95031_AUDPLLCTRL, BIT(5));
|
||||
@ -205,17 +205,22 @@ static int sn95031_set_vaud_bias(struct snd_soc_codec *codec,
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
switch (snd_soc_codec_get_bias_level(codec)) {
|
||||
case SND_SOC_BIAS_OFF:
|
||||
pr_debug("vaud_bias power up rail\n");
|
||||
/* power up the rail */
|
||||
snd_soc_write(codec, SN95031_VAUD,
|
||||
BIT(2)|BIT(1)|BIT(0));
|
||||
msleep(1);
|
||||
} else if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) {
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
/* turn off pcm */
|
||||
pr_debug("vaud_bias power dn pcm\n");
|
||||
snd_soc_update_bits(codec, SN95031_PCM2C2, BIT(0), 0);
|
||||
snd_soc_write(codec, SN95031_AUDPLLCTRL, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -226,7 +231,6 @@ static int sn95031_set_vaud_bias(struct snd_soc_codec *codec,
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -510,7 +510,7 @@ static int ssm2518_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
|
||||
ret = ssm2518_set_power(ssm2518, true);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
@ -518,12 +518,7 @@ static int ssm2518_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ssm2518_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
|
||||
|
@ -473,7 +473,6 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -524,8 +523,8 @@ static int ssm2602_resume(struct snd_soc_codec *codec)
|
||||
|
||||
static int ssm2602_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int ret;
|
||||
|
||||
regmap_update_bits(ssm2602->regmap, SSM2602_LOUT1V,
|
||||
@ -549,7 +548,7 @@ static int ssm2602_codec_probe(struct snd_soc_codec *codec)
|
||||
|
||||
static int ssm2604_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_dapm_new_controls(dapm, ssm2604_dapm_widgets,
|
||||
|
@ -353,7 +353,7 @@ static int ssm4567_set_bias_level(struct snd_soc_codec *codec,
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
|
||||
ret = ssm4567_set_power(ssm4567, true);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
@ -361,12 +361,7 @@ static int ssm4567_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops ssm4567_dai_ops = {
|
||||
|
@ -819,7 +819,7 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies),
|
||||
sta32x->supplies);
|
||||
if (ret != 0) {
|
||||
@ -854,7 +854,6 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec,
|
||||
sta32x->supplies);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -970,7 +969,7 @@ static int sta32x_probe(struct snd_soc_codec *codec)
|
||||
if (sta32x->pdata->needs_esd_watchdog)
|
||||
INIT_DELAYED_WORK(&sta32x->watchdog_work, sta32x_watchdog);
|
||||
|
||||
sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
/* Bias level configuration will have done an extra enable */
|
||||
regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
|
||||
|
||||
@ -1096,16 +1095,10 @@ static int sta32x_i2c_probe(struct i2c_client *i2c,
|
||||
#endif
|
||||
|
||||
/* GPIOs */
|
||||
sta32x->gpiod_nreset = devm_gpiod_get(dev, "reset");
|
||||
if (IS_ERR(sta32x->gpiod_nreset)) {
|
||||
ret = PTR_ERR(sta32x->gpiod_nreset);
|
||||
if (ret != -ENOENT && ret != -ENOSYS)
|
||||
return ret;
|
||||
|
||||
sta32x->gpiod_nreset = NULL;
|
||||
} else {
|
||||
gpiod_direction_output(sta32x->gpiod_nreset, 0);
|
||||
}
|
||||
sta32x->gpiod_nreset = devm_gpiod_get_optional(dev, "reset",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(sta32x->gpiod_nreset))
|
||||
return PTR_ERR(sta32x->gpiod_nreset);
|
||||
|
||||
/* regulators */
|
||||
for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++)
|
||||
|
@ -853,7 +853,7 @@ static int sta350_set_bias_level(struct snd_soc_codec *codec,
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
ret = regulator_bulk_enable(
|
||||
ARRAY_SIZE(sta350->supplies),
|
||||
sta350->supplies);
|
||||
@ -890,7 +890,6 @@ static int sta350_set_bias_level(struct snd_soc_codec *codec,
|
||||
sta350->supplies);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1037,7 +1036,7 @@ static int sta350_probe(struct snd_soc_codec *codec)
|
||||
sta350->coef_shadow[60] = 0x400000;
|
||||
sta350->coef_shadow[61] = 0x400000;
|
||||
|
||||
sta350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
/* Bias level configuration will have done an extra enable */
|
||||
regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies);
|
||||
|
||||
@ -1218,8 +1217,8 @@ static int sta350_i2c_probe(struct i2c_client *i2c,
|
||||
if (IS_ERR(sta350->gpiod_nreset))
|
||||
return PTR_ERR(sta350->gpiod_nreset);
|
||||
|
||||
sta350->gpiod_power_down = devm_gpiod_get(dev, "power-down",
|
||||
GPIOD_OUT_LOW);
|
||||
sta350->gpiod_power_down = devm_gpiod_get_optional(dev, "power-down",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(sta350->gpiod_power_down))
|
||||
return PTR_ERR(sta350->gpiod_power_down);
|
||||
|
||||
|
@ -165,7 +165,7 @@ static int sta529_set_bias_level(struct snd_soc_codec *codec, enum
|
||||
FFX_CLK_ENB);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
|
||||
regcache_sync(sta529->regmap);
|
||||
snd_soc_update_bits(codec, STA529_FFXCFG0,
|
||||
POWER_CNTLMSAK, POWER_STDBY);
|
||||
@ -179,12 +179,6 @@ static int sta529_set_bias_level(struct snd_soc_codec *codec, enum
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* store the label for powers down audio subsystem for suspend.This is
|
||||
* used by soc core layer
|
||||
*/
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -236,7 +236,6 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec,
|
||||
stac9766_ac97_write(codec, AC97_POWERDOWN, 0xffff);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/tas2552-plat.h>
|
||||
#include <dt-bindings/sound/tas2552.h>
|
||||
|
||||
#include "tas2552.h"
|
||||
|
||||
@ -45,7 +46,7 @@ static struct reg_default tas2552_reg_defs[] = {
|
||||
{TAS2552_PDM_CFG, 0x01},
|
||||
{TAS2552_PGA_GAIN, 0x00},
|
||||
{TAS2552_BOOST_PT_CTRL, 0x0f},
|
||||
{TAS2552_RESERVED_0D, 0x00},
|
||||
{TAS2552_RESERVED_0D, 0xbe},
|
||||
{TAS2552_LIMIT_RATE_HYS, 0x08},
|
||||
{TAS2552_CFG_2, 0xef},
|
||||
{TAS2552_SER_CTRL_1, 0x00},
|
||||
@ -75,20 +76,45 @@ struct tas2552_data {
|
||||
struct regulator_bulk_data supplies[TAS2552_NUM_SUPPLIES];
|
||||
struct gpio_desc *enable_gpio;
|
||||
unsigned char regs[TAS2552_VBAT_DATA];
|
||||
unsigned int mclk;
|
||||
unsigned int pll_clkin;
|
||||
unsigned int pdm_clk;
|
||||
|
||||
unsigned int dai_fmt;
|
||||
unsigned int tdm_delay;
|
||||
};
|
||||
|
||||
static int tas2552_post_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
snd_soc_write(codec, TAS2552_RESERVED_0D, 0xc0);
|
||||
snd_soc_update_bits(codec, TAS2552_LIMIT_RATE_HYS, (1 << 5),
|
||||
(1 << 5));
|
||||
snd_soc_update_bits(codec, TAS2552_CFG_2, 1, 0);
|
||||
snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_SWS, 0);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_SWS,
|
||||
TAS2552_SWS);
|
||||
snd_soc_update_bits(codec, TAS2552_CFG_2, 1, 1);
|
||||
snd_soc_update_bits(codec, TAS2552_LIMIT_RATE_HYS, (1 << 5), 0);
|
||||
snd_soc_write(codec, TAS2552_RESERVED_0D, 0xbe);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Input mux controls */
|
||||
static const char *tas2552_input_texts[] = {
|
||||
"Digital", "Analog"
|
||||
};
|
||||
|
||||
static const char * const tas2552_input_texts[] = {
|
||||
"Digital", "Analog" };
|
||||
static SOC_ENUM_SINGLE_DECL(tas2552_input_mux_enum, TAS2552_CFG_3, 7,
|
||||
tas2552_input_texts);
|
||||
|
||||
static const struct snd_kcontrol_new tas2552_input_mux_control[] = {
|
||||
SOC_DAPM_ENUM("Input selection", tas2552_input_mux_enum)
|
||||
};
|
||||
static const struct snd_kcontrol_new tas2552_input_mux_control =
|
||||
SOC_DAPM_ENUM("Route", tas2552_input_mux_enum);
|
||||
|
||||
static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] =
|
||||
{
|
||||
@ -96,12 +122,13 @@ static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] =
|
||||
|
||||
/* MUX Controls */
|
||||
SND_SOC_DAPM_MUX("Input selection", SND_SOC_NOPM, 0, 0,
|
||||
tas2552_input_mux_control),
|
||||
&tas2552_input_mux_control),
|
||||
|
||||
SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0),
|
||||
SND_SOC_DAPM_POST("Post Event", tas2552_post_event),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("OUT")
|
||||
};
|
||||
@ -118,15 +145,16 @@ static const struct snd_soc_dapm_route tas2552_audio_map[] = {
|
||||
#ifdef CONFIG_PM
|
||||
static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown)
|
||||
{
|
||||
u8 cfg1_reg;
|
||||
u8 cfg1_reg = 0;
|
||||
|
||||
if (!tas_data->codec)
|
||||
return;
|
||||
|
||||
if (sw_shutdown)
|
||||
cfg1_reg = 0;
|
||||
else
|
||||
cfg1_reg = TAS2552_SWS_MASK;
|
||||
cfg1_reg = TAS2552_SWS;
|
||||
|
||||
snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1,
|
||||
TAS2552_SWS_MASK, cfg1_reg);
|
||||
snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1, TAS2552_SWS,
|
||||
cfg1_reg);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -138,15 +166,92 @@ static int tas2552_hw_params(struct snd_pcm_substream *substream,
|
||||
struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
|
||||
int sample_rate, pll_clk;
|
||||
int d;
|
||||
int cpf;
|
||||
u8 p, j;
|
||||
u8 ser_ctrl1_reg, wclk_rate;
|
||||
|
||||
if (!tas2552->mclk)
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
ser_ctrl1_reg = TAS2552_WORDLENGTH_16BIT;
|
||||
cpf = 32 + tas2552->tdm_delay;
|
||||
break;
|
||||
case 20:
|
||||
ser_ctrl1_reg = TAS2552_WORDLENGTH_20BIT;
|
||||
cpf = 64 + tas2552->tdm_delay;
|
||||
break;
|
||||
case 24:
|
||||
ser_ctrl1_reg = TAS2552_WORDLENGTH_24BIT;
|
||||
cpf = 64 + tas2552->tdm_delay;
|
||||
break;
|
||||
case 32:
|
||||
ser_ctrl1_reg = TAS2552_WORDLENGTH_32BIT;
|
||||
cpf = 64 + tas2552->tdm_delay;
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "Not supported sample size: %d\n",
|
||||
params_width(params));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cpf <= 32)
|
||||
ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_32;
|
||||
else if (cpf <= 64)
|
||||
ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_64;
|
||||
else if (cpf <= 128)
|
||||
ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_128;
|
||||
else
|
||||
ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_256;
|
||||
|
||||
snd_soc_update_bits(codec, TAS2552_SER_CTRL_1,
|
||||
TAS2552_WORDLENGTH_MASK | TAS2552_CLKSPERFRAME_MASK,
|
||||
ser_ctrl1_reg);
|
||||
|
||||
switch (params_rate(params)) {
|
||||
case 8000:
|
||||
wclk_rate = TAS2552_WCLK_FREQ_8KHZ;
|
||||
break;
|
||||
case 11025:
|
||||
case 12000:
|
||||
wclk_rate = TAS2552_WCLK_FREQ_11_12KHZ;
|
||||
break;
|
||||
case 16000:
|
||||
wclk_rate = TAS2552_WCLK_FREQ_16KHZ;
|
||||
break;
|
||||
case 22050:
|
||||
case 24000:
|
||||
wclk_rate = TAS2552_WCLK_FREQ_22_24KHZ;
|
||||
break;
|
||||
case 32000:
|
||||
wclk_rate = TAS2552_WCLK_FREQ_32KHZ;
|
||||
break;
|
||||
case 44100:
|
||||
case 48000:
|
||||
wclk_rate = TAS2552_WCLK_FREQ_44_48KHZ;
|
||||
break;
|
||||
case 88200:
|
||||
case 96000:
|
||||
wclk_rate = TAS2552_WCLK_FREQ_88_96KHZ;
|
||||
break;
|
||||
case 176400:
|
||||
case 192000:
|
||||
wclk_rate = TAS2552_WCLK_FREQ_176_192KHZ;
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "Not supported sample rate: %d\n",
|
||||
params_rate(params));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, TAS2552_CFG_3, TAS2552_WCLK_FREQ_MASK,
|
||||
wclk_rate);
|
||||
|
||||
if (!tas2552->pll_clkin)
|
||||
return -EINVAL;
|
||||
|
||||
snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0);
|
||||
|
||||
if (tas2552->mclk == TAS2552_245MHZ_CLK ||
|
||||
tas2552->mclk == TAS2552_225MHZ_CLK) {
|
||||
if (tas2552->pll_clkin == TAS2552_245MHZ_CLK ||
|
||||
tas2552->pll_clkin == TAS2552_225MHZ_CLK) {
|
||||
/* By pass the PLL configuration */
|
||||
snd_soc_update_bits(codec, TAS2552_PLL_CTRL_2,
|
||||
TAS2552_PLL_BYPASS_MASK,
|
||||
@ -170,8 +275,8 @@ static int tas2552_hw_params(struct snd_pcm_substream *substream,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
j = (pll_clk * 2 * (1 << p)) / tas2552->mclk;
|
||||
d = (pll_clk * 2 * (1 << p)) % tas2552->mclk;
|
||||
j = (pll_clk * 2 * (1 << p)) / tas2552->pll_clkin;
|
||||
d = (pll_clk * 2 * (1 << p)) % tas2552->pll_clkin;
|
||||
|
||||
snd_soc_update_bits(codec, TAS2552_PLL_CTRL_1,
|
||||
TAS2552_PLL_J_MASK, j);
|
||||
@ -185,56 +290,74 @@ static int tas2552_hw_params(struct snd_pcm_substream *substream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TAS2552_DAI_FMT_MASK (TAS2552_BCLKDIR | \
|
||||
TAS2552_WCLKDIR | \
|
||||
TAS2552_DATAFORMAT_MASK)
|
||||
static int tas2552_prepare(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
|
||||
int delay = 0;
|
||||
|
||||
/* TDM slot selection only valid in DSP_A/_B mode */
|
||||
if (tas2552->dai_fmt == SND_SOC_DAIFMT_DSP_A)
|
||||
delay += (tas2552->tdm_delay + 1);
|
||||
else if (tas2552->dai_fmt == SND_SOC_DAIFMT_DSP_B)
|
||||
delay += tas2552->tdm_delay;
|
||||
|
||||
/* Configure data delay */
|
||||
snd_soc_write(codec, TAS2552_SER_CTRL_2, delay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tas2552_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
|
||||
u8 serial_format;
|
||||
u8 serial_control_mask;
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
serial_format = 0x00;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBS_CFM:
|
||||
serial_format = TAS2552_WORD_CLK_MASK;
|
||||
serial_format = TAS2552_WCLKDIR;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBM_CFS:
|
||||
serial_format = TAS2552_BIT_CLK_MASK;
|
||||
serial_format = TAS2552_BCLKDIR;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
serial_format = (TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK);
|
||||
serial_format = (TAS2552_BCLKDIR | TAS2552_WCLKDIR);
|
||||
break;
|
||||
default:
|
||||
dev_vdbg(codec->dev, "DAI Format master is not found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
serial_control_mask = TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK;
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
serial_format &= TAS2552_DAIFMT_I2S_MASK;
|
||||
switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK |
|
||||
SND_SOC_DAIFMT_INV_MASK)) {
|
||||
case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF):
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
serial_format |= TAS2552_DAIFMT_DSP;
|
||||
case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF):
|
||||
case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF):
|
||||
serial_format |= TAS2552_DATAFORMAT_DSP;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
serial_format |= TAS2552_DAIFMT_RIGHT_J;
|
||||
case (SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_NB_NF):
|
||||
serial_format |= TAS2552_DATAFORMAT_RIGHT_J;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
serial_format |= TAS2552_DAIFMT_LEFT_J;
|
||||
case (SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF):
|
||||
serial_format |= TAS2552_DATAFORMAT_LEFT_J;
|
||||
break;
|
||||
default:
|
||||
dev_vdbg(codec->dev, "DAI Format is not found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
tas2552->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
|
||||
|
||||
if (fmt & SND_SOC_DAIFMT_FORMAT_MASK)
|
||||
serial_control_mask |= TAS2552_DATA_FORMAT_MASK;
|
||||
|
||||
snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, serial_control_mask,
|
||||
serial_format);
|
||||
|
||||
snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, TAS2552_DAI_FMT_MASK,
|
||||
serial_format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -243,23 +366,75 @@ static int tas2552_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
|
||||
u8 reg, mask, val;
|
||||
|
||||
tas2552->mclk = freq;
|
||||
switch (clk_id) {
|
||||
case TAS2552_PLL_CLKIN_MCLK:
|
||||
case TAS2552_PLL_CLKIN_BCLK:
|
||||
case TAS2552_PLL_CLKIN_IVCLKIN:
|
||||
case TAS2552_PLL_CLKIN_1_8_FIXED:
|
||||
mask = TAS2552_PLL_SRC_MASK;
|
||||
val = (clk_id << 3) & mask; /* bit 4:5 in the register */
|
||||
reg = TAS2552_CFG_1;
|
||||
tas2552->pll_clkin = freq;
|
||||
break;
|
||||
case TAS2552_PDM_CLK_PLL:
|
||||
case TAS2552_PDM_CLK_IVCLKIN:
|
||||
case TAS2552_PDM_CLK_BCLK:
|
||||
case TAS2552_PDM_CLK_MCLK:
|
||||
mask = TAS2552_PDM_CLK_SEL_MASK;
|
||||
val = (clk_id >> 1) & mask; /* bit 0:1 in the register */
|
||||
reg = TAS2552_PDM_CFG;
|
||||
tas2552->pdm_clk = freq;
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "Invalid clk id: %d\n", clk_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, reg, mask, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tas2552_set_dai_tdm_slot(struct snd_soc_dai *dai,
|
||||
unsigned int tx_mask, unsigned int rx_mask,
|
||||
int slots, int slot_width)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int lsb;
|
||||
|
||||
if (unlikely(!tx_mask)) {
|
||||
dev_err(codec->dev, "tx masks need to be non 0\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* TDM based on DSP mode requires slots to be adjacent */
|
||||
lsb = __ffs(tx_mask);
|
||||
if ((lsb + 1) != __fls(tx_mask)) {
|
||||
dev_err(codec->dev, "Invalid mask, slots must be adjacent\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tas2552->tdm_delay = lsb * slot_width;
|
||||
|
||||
/* DOUT in high-impedance on inactive bit clocks */
|
||||
snd_soc_update_bits(codec, TAS2552_DOUT,
|
||||
TAS2552_SDOUT_TRISTATE, TAS2552_SDOUT_TRISTATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tas2552_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
u8 cfg1_reg;
|
||||
u8 cfg1_reg = 0;
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
|
||||
if (mute)
|
||||
cfg1_reg = TAS2552_MUTE_MASK;
|
||||
else
|
||||
cfg1_reg = ~TAS2552_MUTE_MASK;
|
||||
cfg1_reg |= TAS2552_MUTE;
|
||||
|
||||
snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK, cfg1_reg);
|
||||
snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE, cfg1_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -269,7 +444,7 @@ static int tas2552_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct tas2552_data *tas2552 = dev_get_drvdata(dev);
|
||||
|
||||
tas2552_sw_shutdown(tas2552, 0);
|
||||
tas2552_sw_shutdown(tas2552, 1);
|
||||
|
||||
regcache_cache_only(tas2552->regmap, true);
|
||||
regcache_mark_dirty(tas2552->regmap);
|
||||
@ -287,7 +462,7 @@ static int tas2552_runtime_resume(struct device *dev)
|
||||
if (tas2552->enable_gpio)
|
||||
gpiod_set_value(tas2552->enable_gpio, 1);
|
||||
|
||||
tas2552_sw_shutdown(tas2552, 1);
|
||||
tas2552_sw_shutdown(tas2552, 0);
|
||||
|
||||
regcache_cache_only(tas2552->regmap, false);
|
||||
regcache_sync(tas2552->regmap);
|
||||
@ -303,8 +478,10 @@ static const struct dev_pm_ops tas2552_pm = {
|
||||
|
||||
static struct snd_soc_dai_ops tas2552_speaker_dai_ops = {
|
||||
.hw_params = tas2552_hw_params,
|
||||
.prepare = tas2552_prepare,
|
||||
.set_sysclk = tas2552_set_dai_sysclk,
|
||||
.set_fmt = tas2552_set_dai_fmt,
|
||||
.set_tdm_slot = tas2552_set_dai_tdm_slot,
|
||||
.digital_mute = tas2552_mute,
|
||||
};
|
||||
|
||||
@ -330,16 +507,11 @@ static struct snd_soc_dai_driver tas2552_dai[] = {
|
||||
/*
|
||||
* DAC digital volumes. From -7 to 24 dB in 1 dB steps
|
||||
*/
|
||||
static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 24);
|
||||
static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 0);
|
||||
|
||||
static const struct snd_kcontrol_new tas2552_snd_controls[] = {
|
||||
SOC_SINGLE_TLV("Speaker Driver Playback Volume",
|
||||
TAS2552_PGA_GAIN, 0, 0x1f, 1, dac_tlv),
|
||||
SOC_DAPM_SINGLE("Playback AMP", SND_SOC_NOPM, 0, 1, 0),
|
||||
};
|
||||
|
||||
static const struct reg_default tas2552_init_regs[] = {
|
||||
{ TAS2552_RESERVED_0D, 0xc0 },
|
||||
TAS2552_PGA_GAIN, 0, 0x1f, 0, dac_tlv),
|
||||
};
|
||||
|
||||
static int tas2552_codec_probe(struct snd_soc_codec *codec)
|
||||
@ -368,31 +540,19 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec)
|
||||
goto probe_fail;
|
||||
}
|
||||
|
||||
snd_soc_write(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK |
|
||||
TAS2552_PLL_SRC_BCLK);
|
||||
snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE, TAS2552_MUTE);
|
||||
snd_soc_write(codec, TAS2552_CFG_3, TAS2552_I2S_OUT_SEL |
|
||||
TAS2552_DIN_SRC_SEL_AVG_L_R | TAS2552_88_96KHZ);
|
||||
TAS2552_DIN_SRC_SEL_AVG_L_R);
|
||||
snd_soc_write(codec, TAS2552_DOUT, TAS2552_PDM_DATA_I);
|
||||
snd_soc_write(codec, TAS2552_OUTPUT_DATA, TAS2552_PDM_DATA_V_I | 0x8);
|
||||
snd_soc_write(codec, TAS2552_PDM_CFG, TAS2552_PDM_BCLK_SEL);
|
||||
snd_soc_write(codec, TAS2552_BOOST_PT_CTRL, TAS2552_APT_DELAY_200 |
|
||||
TAS2552_APT_THRESH_2_1_7);
|
||||
|
||||
ret = regmap_register_patch(tas2552->regmap, tas2552_init_regs,
|
||||
ARRAY_SIZE(tas2552_init_regs));
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to write init registers: %d\n",
|
||||
ret);
|
||||
goto patch_fail;
|
||||
}
|
||||
|
||||
snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN |
|
||||
TAS2552_APT_EN | TAS2552_LIM_EN);
|
||||
|
||||
return 0;
|
||||
|
||||
patch_fail:
|
||||
pm_runtime_put(codec->dev);
|
||||
probe_fail:
|
||||
if (tas2552->enable_gpio)
|
||||
gpiod_set_value(tas2552->enable_gpio, 0);
|
||||
@ -454,6 +614,8 @@ static struct snd_soc_codec_driver soc_codec_dev_tas2552 = {
|
||||
.remove = tas2552_codec_remove,
|
||||
.suspend = tas2552_suspend,
|
||||
.resume = tas2552_resume,
|
||||
.ignore_pmdown_time = true,
|
||||
|
||||
.controls = tas2552_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(tas2552_snd_controls),
|
||||
.dapm_widgets = tas2552_dapm_widgets,
|
||||
@ -486,8 +648,12 @@ static int tas2552_probe(struct i2c_client *client,
|
||||
return -ENOMEM;
|
||||
|
||||
data->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(data->enable_gpio))
|
||||
return PTR_ERR(data->enable_gpio);
|
||||
if (IS_ERR(data->enable_gpio)) {
|
||||
if (PTR_ERR(data->enable_gpio) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
data->enable_gpio = NULL;;
|
||||
}
|
||||
|
||||
data->tas2552_client = client;
|
||||
data->regmap = devm_regmap_init_i2c(client, &tas2552_regmap_config);
|
||||
|
@ -45,10 +45,14 @@
|
||||
#define TAS2552_MAX_REG 0x20
|
||||
|
||||
/* CFG1 Register Masks */
|
||||
#define TAS2552_MUTE_MASK (1 << 2)
|
||||
#define TAS2552_SWS_MASK (1 << 1)
|
||||
#define TAS2552_WCLK_MASK 0x07
|
||||
#define TAS2552_CLASSD_EN_MASK (1 << 7)
|
||||
#define TAS2552_DEV_RESET (1 << 0)
|
||||
#define TAS2552_SWS (1 << 1)
|
||||
#define TAS2552_MUTE (1 << 2)
|
||||
#define TAS2552_PLL_SRC_MCLK (0x0 << 4)
|
||||
#define TAS2552_PLL_SRC_BCLK (0x1 << 4)
|
||||
#define TAS2552_PLL_SRC_IVCLKIN (0x2 << 4)
|
||||
#define TAS2552_PLL_SRC_1_8_FIXED (0x3 << 4)
|
||||
#define TAS2552_PLL_SRC_MASK TAS2552_PLL_SRC_1_8_FIXED
|
||||
|
||||
/* CFG2 Register Masks */
|
||||
#define TAS2552_CLASSD_EN (1 << 7)
|
||||
@ -59,38 +63,44 @@
|
||||
#define TAS2552_IVSENSE_EN (1 << 1)
|
||||
|
||||
/* CFG3 Register Masks */
|
||||
#define TAS2552_WORD_CLK_MASK (1 << 7)
|
||||
#define TAS2552_BIT_CLK_MASK (1 << 6)
|
||||
#define TAS2552_DATA_FORMAT_MASK (0x11 << 2)
|
||||
|
||||
#define TAS2552_DAIFMT_I2S_MASK 0xf3
|
||||
#define TAS2552_DAIFMT_DSP (1 << 3)
|
||||
#define TAS2552_DAIFMT_RIGHT_J (1 << 4)
|
||||
#define TAS2552_DAIFMT_LEFT_J (0x11 << 3)
|
||||
|
||||
#define TAS2552_PLL_SRC_MCLK 0x00
|
||||
#define TAS2552_PLL_SRC_BCLK (1 << 3)
|
||||
#define TAS2552_PLL_SRC_IVCLKIN (1 << 4)
|
||||
#define TAS2552_PLL_SRC_1_8_FIXED (0x11 << 3)
|
||||
|
||||
#define TAS2552_DIN_SRC_SEL_MUTED 0x00
|
||||
#define TAS2552_DIN_SRC_SEL_LEFT (1 << 4)
|
||||
#define TAS2552_DIN_SRC_SEL_RIGHT (1 << 5)
|
||||
#define TAS2552_DIN_SRC_SEL_AVG_L_R (0x11 << 4)
|
||||
|
||||
#define TAS2552_WCLK_FREQ_8KHZ (0x0 << 0)
|
||||
#define TAS2552_WCLK_FREQ_11_12KHZ (0x1 << 0)
|
||||
#define TAS2552_WCLK_FREQ_16KHZ (0x2 << 0)
|
||||
#define TAS2552_WCLK_FREQ_22_24KHZ (0x3 << 0)
|
||||
#define TAS2552_WCLK_FREQ_32KHZ (0x4 << 0)
|
||||
#define TAS2552_WCLK_FREQ_44_48KHZ (0x5 << 0)
|
||||
#define TAS2552_WCLK_FREQ_88_96KHZ (0x6 << 0)
|
||||
#define TAS2552_WCLK_FREQ_176_192KHZ (0x7 << 0)
|
||||
#define TAS2552_WCLK_FREQ_MASK TAS2552_WCLK_FREQ_176_192KHZ
|
||||
#define TAS2552_DIN_SRC_SEL_MUTED (0x0 << 3)
|
||||
#define TAS2552_DIN_SRC_SEL_LEFT (0x1 << 3)
|
||||
#define TAS2552_DIN_SRC_SEL_RIGHT (0x2 << 3)
|
||||
#define TAS2552_DIN_SRC_SEL_AVG_L_R (0x3 << 3)
|
||||
#define TAS2552_PDM_IN_SEL (1 << 5)
|
||||
#define TAS2552_I2S_OUT_SEL (1 << 6)
|
||||
#define TAS2552_ANALOG_IN_SEL (1 << 7)
|
||||
#define TAS2552_ANALOG_IN_SEL (1 << 7)
|
||||
|
||||
/* CFG3 WCLK Dividers */
|
||||
#define TAS2552_8KHZ 0x00
|
||||
#define TAS2552_11_12KHZ (1 << 1)
|
||||
#define TAS2552_16KHZ (1 << 2)
|
||||
#define TAS2552_22_24KHZ (1 << 3)
|
||||
#define TAS2552_32KHZ (1 << 4)
|
||||
#define TAS2552_44_48KHZ (1 << 5)
|
||||
#define TAS2552_88_96KHZ (1 << 6)
|
||||
#define TAS2552_176_192KHZ (1 << 7)
|
||||
/* DOUT Register Masks */
|
||||
#define TAS2552_SDOUT_TRISTATE (1 << 2)
|
||||
|
||||
/* Serial Interface Control Register Masks */
|
||||
#define TAS2552_WORDLENGTH_16BIT (0x0 << 0)
|
||||
#define TAS2552_WORDLENGTH_20BIT (0x1 << 0)
|
||||
#define TAS2552_WORDLENGTH_24BIT (0x2 << 0)
|
||||
#define TAS2552_WORDLENGTH_32BIT (0x3 << 0)
|
||||
#define TAS2552_WORDLENGTH_MASK TAS2552_WORDLENGTH_32BIT
|
||||
#define TAS2552_DATAFORMAT_I2S (0x0 << 2)
|
||||
#define TAS2552_DATAFORMAT_DSP (0x1 << 2)
|
||||
#define TAS2552_DATAFORMAT_RIGHT_J (0x2 << 2)
|
||||
#define TAS2552_DATAFORMAT_LEFT_J (0x3 << 2)
|
||||
#define TAS2552_DATAFORMAT_MASK TAS2552_DATAFORMAT_LEFT_J
|
||||
#define TAS2552_CLKSPERFRAME_32 (0x0 << 4)
|
||||
#define TAS2552_CLKSPERFRAME_64 (0x1 << 4)
|
||||
#define TAS2552_CLKSPERFRAME_128 (0x2 << 4)
|
||||
#define TAS2552_CLKSPERFRAME_256 (0x3 << 4)
|
||||
#define TAS2552_CLKSPERFRAME_MASK TAS2552_CLKSPERFRAME_256
|
||||
#define TAS2552_BCLKDIR (1 << 6)
|
||||
#define TAS2552_WCLKDIR (1 << 7)
|
||||
|
||||
/* OUTPUT_DATA register */
|
||||
#define TAS2552_PDM_DATA_I 0x00
|
||||
@ -99,12 +109,12 @@
|
||||
#define TAS2552_PDM_DATA_V_I (0x11 << 6)
|
||||
|
||||
/* PDM CFG Register */
|
||||
#define TAS2552_PDM_DATA_ES_RISE 0x4
|
||||
|
||||
#define TAS2552_PDM_PLL_CLK_SEL 0x00
|
||||
#define TAS2552_PDM_IV_CLK_SEL (1 << 1)
|
||||
#define TAS2552_PDM_BCLK_SEL (1 << 2)
|
||||
#define TAS2552_PDM_MCLK_SEL (1 << 3)
|
||||
#define TAS2552_PDM_CLK_SEL_PLL (0x0 << 0)
|
||||
#define TAS2552_PDM_CLK_SEL_IVCLKIN (0x1 << 0)
|
||||
#define TAS2552_PDM_CLK_SEL_BCLK (0x2 << 0)
|
||||
#define TAS2552_PDM_CLK_SEL_MCLK (0x3 << 0)
|
||||
#define TAS2552_PDM_CLK_SEL_MASK TAS2552_PDM_CLK_SEL_MCLK
|
||||
#define TAS2552_PDM_DATA_ES (1 << 2)
|
||||
|
||||
/* Boost pass-through register */
|
||||
#define TAS2552_APT_DELAY_50 0x00
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user