ASoC: Updates for v3.15
Quite a busy release for ASoC this time, more on janitorial work than exciting new features but welcome nontheless: - Lots of cleanups from Takashi for enumerations; the original API for these was error prone so he's refactored lots of code to use more modern APIs which avoid issues. - Elimination of the ASoC level wrappers for I2C and SPI moving us closer to converting to regmap completely and avoiding some randconfig hassle. - Provide both manually and transparently locked DAPM APIs rather than a mix of the two fixing some concurrency issues. - Start converting CODEC drivers to use separate bus interface drivers rather than having them all in one file helping avoid dependency issues. - DPCM support for Intel Haswell and Bay Trail platforms. - Lots of work on improvements for simple-card, DaVinci and the Renesas rcar drivers. - New drivers for Analog Devices ADAU1977, TI PCM512x and parts of the CSR SiRF SoC. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJTIOhJAAoJELSic+t+oim90CoP/3CVTm9cWv1qhPSU6jjn6RJG /djmhntJfHd/GXo+0TiiwNK9WmZjFrJUr+5ofkDTCqSzFz1Suc90B6oHxY4dFbgF IyIpTexGwTLv3H6yDjadYAfmGDSsE9sM2dkID9oXy6aEzjNby/a1VEiBnRgx16X1 YGvMVK8AGFn/AyC/zOV6EcKJxUjdDogqZ5wkR2XHzwDoYjl9ufxK9BnSIygYABOW ABAjyrZf3xx97AH82BB6iqcZMh5GxGNTvI3hQd/vjx0r7RFUDNLqmF2cPZAMTRW/ bXWxVmtNHie1+lCldyMFm8pV/Pv09zuqDAQKbPY2TeHj2zF8CM548NlkFHqwHlp0 S9K5E1N+/2wcXMjQa1wBELohUdl6dVh1OFOAz7M8o0TJdSOZyR6PJ9r0NprP8NgS 67FBU+ZqnWIK159m9rKkFfPhnaDuDzk+rpwyK0fQxQgpdGGjLyv7OK3GhS30oTnA Z2GjEyUySM1BcEEWAtfUD5fHbjN28e1Icn53q5q4JK4gvx4DXBy08uY/vumvjXjO 8oum3q3RjRvqIhzMrJoVgs+c8RHwS/bZQhlu9Q3qNTsDNDyMnaZWHFAnP8RDqHjv ojZiMJkJdpqceZ3z1k5ZG8GWJ2JaZBikSbeNk2Ltg17/0nackq2r8ekrIoEUPVk2 ph4DJNC2s1qCFtx7tzQj =C5oo -----END PGP SIGNATURE----- Merge tag 'asoc-v3.15' into asoc-linus ASoC: Updates for v3.15 Quite a busy release for ASoC this time, more on janitorial work than exciting new features but welcome nontheless: - Lots of cleanups from Takashi for enumerations; the original API for these was error prone so he's refactored lots of code to use more modern APIs which avoid issues. - Elimination of the ASoC level wrappers for I2C and SPI moving us closer to converting to regmap completely and avoiding some randconfig hassle. - Provide both manually and transparently locked DAPM APIs rather than a mix of the two fixing some concurrency issues. - Start converting CODEC drivers to use separate bus interface drivers rather than having them all in one file helping avoid dependency issues. - DPCM support for Intel Haswell and Bay Trail platforms. - Lots of work on improvements for simple-card, DaVinci and the Renesas rcar drivers. - New drivers for Analog Devices ADAU1977, TI PCM512x and parts of the CSR SiRF SoC. # gpg: Signature made Wed 12 Mar 2014 23:05:45 GMT using RSA key ID 7EA229BD # 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
30b58f22cc
|
@ -18,6 +18,7 @@ atmel,24c02 i2c serial eeprom (24cxx)
|
|||
atmel,at97sc3204t i2c trusted platform module (TPM)
|
||||
capella,cm32181 CM32181: Ambient Light Sensor
|
||||
catalyst,24c32 i2c serial eeprom
|
||||
cirrus,cs42l51 Cirrus Logic CS42L51 audio codec
|
||||
dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock
|
||||
dallas,ds1338 I2C RTC with 56-Byte NV RAM
|
||||
dallas,ds1339 I2C Serial Real-Time Clock
|
||||
|
|
|
@ -17,6 +17,14 @@ Required properties for devices compatible with "atmel,at91sam9g45-ssc":
|
|||
See Documentation/devicetree/bindings/dma/atmel-dma.txt for details.
|
||||
- dma-names: Must be "tx", "rx".
|
||||
|
||||
Optional properties:
|
||||
- atmel,clk-from-rk-pin: bool property.
|
||||
- When SSC works in slave mode, according to the hardware design, the
|
||||
clock can get from TK pin, and also can get from RK pin. So, add
|
||||
this parameter to choose where the clock from.
|
||||
- By default the clock is from TK pin, if the clock from RK pin, this
|
||||
property is needed.
|
||||
|
||||
Examples:
|
||||
- PDC transfer:
|
||||
ssc0: ssc@fffbc000 {
|
||||
|
|
22
Documentation/devicetree/bindings/sound/da9055.txt
Normal file
22
Documentation/devicetree/bindings/sound/da9055.txt
Normal file
|
@ -0,0 +1,22 @@
|
|||
* Dialog DA9055 Audio CODEC
|
||||
|
||||
DA9055 provides Audio CODEC support (I2C only).
|
||||
|
||||
The Audio CODEC device in DA9055 has it's own I2C address which is configurable,
|
||||
so the device is instantiated separately from the PMIC (MFD) device.
|
||||
|
||||
For details on accompanying PMIC I2C device, see the following:
|
||||
Documentation/devicetree/bindings/mfd/da9055.txt
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: "dlg,da9055-codec"
|
||||
- reg: Specifies the I2C slave address
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
codec: da9055-codec@1a {
|
||||
compatible = "dlg,da9055-codec";
|
||||
reg = <0x1a>;
|
||||
};
|
|
@ -5,12 +5,19 @@ Required properties:
|
|||
- ti,model : The user-visible name of this sound complex.
|
||||
- ti,audio-codec : The phandle of the TLV320AIC3x audio codec
|
||||
- ti,mcasp-controller : The phandle of the McASP controller
|
||||
- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec
|
||||
- ti,audio-routing : A list of the connections between audio components.
|
||||
Each entry is a pair of strings, the first being the connection's sink,
|
||||
the second being the connection's source. Valid names for sources and
|
||||
sinks are the codec's pins, and the jacks on the board:
|
||||
|
||||
Optional properties:
|
||||
- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec.
|
||||
- clocks : Reference to the master clock
|
||||
- clock-names : The clock should be named "mclk"
|
||||
- Either codec-clock-rate or the codec-clock reference has to be defined. If
|
||||
the both are defined the driver attempts to set referenced clock to the
|
||||
defined rate and takes the rate from the clock reference.
|
||||
|
||||
Board connectors:
|
||||
|
||||
* Headphone Jack
|
||||
|
|
21
Documentation/devicetree/bindings/sound/eukrea-tlv320.txt
Normal file
21
Documentation/devicetree/bindings/sound/eukrea-tlv320.txt
Normal file
|
@ -0,0 +1,21 @@
|
|||
Audio complex for Eukrea boards with tlv320aic23 codec.
|
||||
|
||||
Required properties:
|
||||
- compatible : "eukrea,asoc-tlv320"
|
||||
- eukrea,model : The user-visible name of this sound complex.
|
||||
- ssi-controller : The phandle of the SSI controller.
|
||||
- fsl,mux-int-port : The internal port of the i.MX audio muxer (AUDMUX).
|
||||
- fsl,mux-ext-port : The external port of the i.MX audio muxer.
|
||||
|
||||
Note: The AUDMUX port numbering should start at 1, which is consistent with
|
||||
hardware manual.
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "eukrea,asoc-tlv320";
|
||||
eukrea,model = "imx51-eukrea-tlv320aic23";
|
||||
ssi-controller = <&ssi2>;
|
||||
fsl,mux-int-port = <2>;
|
||||
fsl,mux-ext-port = <3>;
|
||||
};
|
|
@ -34,6 +34,10 @@ Required properties:
|
|||
that ESAI would work in the synchronous mode, which means all the settings
|
||||
for Receiving would be duplicated from Transmition related registers.
|
||||
|
||||
- big-endian : If this property is absent, the native endian mode will
|
||||
be in use as default, or the big endian mode will be in use for all the
|
||||
device registers.
|
||||
|
||||
Example:
|
||||
|
||||
esai: esai@02024000 {
|
||||
|
@ -46,5 +50,6 @@ esai: esai@02024000 {
|
|||
dma-names = "rx", "tx";
|
||||
fsl,fifo-depth = <128>;
|
||||
fsl,esai-synchronous;
|
||||
big-endian;
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
|
@ -29,6 +29,10 @@ Required properties:
|
|||
can also be referred to TxClk_Source
|
||||
bit of register SPDIF_STC.
|
||||
|
||||
- big-endian : If this property is absent, the native endian mode will
|
||||
be in use as default, or the big endian mode will be in use for all the
|
||||
device registers.
|
||||
|
||||
Example:
|
||||
|
||||
spdif: spdif@02004000 {
|
||||
|
@ -50,5 +54,6 @@ spdif: spdif@02004000 {
|
|||
"rxtx5", "rxtx6",
|
||||
"rxtx7";
|
||||
|
||||
big-endian;
|
||||
status = "okay";
|
||||
};
|
||||
|
|
30
Documentation/devicetree/bindings/sound/pcm512x.txt
Normal file
30
Documentation/devicetree/bindings/sound/pcm512x.txt
Normal file
|
@ -0,0 +1,30 @@
|
|||
PCM512x audio CODECs
|
||||
|
||||
These devices support both I2C and SPI (configured with pin strapping
|
||||
on the board).
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : One of "ti,pcm5121" or "ti,pcm5122"
|
||||
|
||||
- reg : the I2C address of the device for I2C, the chip select
|
||||
number for SPI.
|
||||
|
||||
- AVDD-supply, DVDD-supply, and CPVDD-supply : power supplies for the
|
||||
device, as covered in bindings/regulator/regulator.txt
|
||||
|
||||
Optional properties:
|
||||
|
||||
- clocks : A clock specifier for the clock connected as SCLK. If this
|
||||
is absent the device will be configured to clock from BCLK.
|
||||
|
||||
Example:
|
||||
|
||||
pcm5122: pcm5122@4c {
|
||||
compatible = "ti,pcm5122";
|
||||
reg = <0x4c>;
|
||||
|
||||
AVDD-supply = <®_3v3_analog>;
|
||||
DVDD-supply = <®_1v8>;
|
||||
CPVDD-supply = <®_3v3>;
|
||||
};
|
|
@ -8,13 +8,18 @@ Required properties:
|
|||
|
||||
Optional properties:
|
||||
|
||||
- simple-audio-card,name : User specified audio sound card name, one string
|
||||
property.
|
||||
- simple-audio-card,format : CPU/CODEC common audio format.
|
||||
"i2s", "right_j", "left_j" , "dsp_a"
|
||||
"dsp_b", "ac97", "pdm", "msb", "lsb"
|
||||
- simple-audio-card,widgets : Please refer to widgets.txt.
|
||||
- simple-audio-card,routing : A list of the connections between audio components.
|
||||
Each entry is a pair of strings, the first being the
|
||||
connection's sink, the second being the connection's
|
||||
source.
|
||||
- dai-tdm-slot-num : Please refer to tdm-slot.txt.
|
||||
- dai-tdm-slot-width : Please refer to tdm-slot.txt.
|
||||
|
||||
Required subnodes:
|
||||
|
||||
|
@ -42,11 +47,19 @@ Example:
|
|||
|
||||
sound {
|
||||
compatible = "simple-audio-card";
|
||||
simple-audio-card,name = "VF610-Tower-Sound-Card";
|
||||
simple-audio-card,format = "left_j";
|
||||
simple-audio-card,widgets =
|
||||
"Microphone", "Microphone Jack",
|
||||
"Headphone", "Headphone Jack",
|
||||
"Speaker", "External Speaker";
|
||||
simple-audio-card,routing =
|
||||
"MIC_IN", "Mic Jack",
|
||||
"MIC_IN", "Microphone Jack",
|
||||
"Headphone Jack", "HP_OUT",
|
||||
"Ext Spk", "LINE_OUT";
|
||||
"External Speaker", "LINE_OUT";
|
||||
|
||||
dai-tdm-slot-num = <2>;
|
||||
dai-tdm-slot-width = <8>;
|
||||
|
||||
simple-audio-card,cpu {
|
||||
sound-dai = <&sh_fsi2 0>;
|
||||
|
|
17
Documentation/devicetree/bindings/sound/sirf-audio-codec.txt
Normal file
17
Documentation/devicetree/bindings/sound/sirf-audio-codec.txt
Normal file
|
@ -0,0 +1,17 @@
|
|||
SiRF internal audio CODEC
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "sirf,atlas6-audio-codec" or "sirf,prima2-audio-codec"
|
||||
|
||||
- reg : the register address of the device.
|
||||
|
||||
- clocks: the clock of SiRF internal audio codec
|
||||
|
||||
Example:
|
||||
|
||||
audiocodec: audiocodec@b0040000 {
|
||||
compatible = "sirf,atlas6-audio-codec";
|
||||
reg = <0xb0040000 0x10000>;
|
||||
clocks = <&clks 27>;
|
||||
};
|
20
Documentation/devicetree/bindings/sound/sirf-audio-port.txt
Normal file
20
Documentation/devicetree/bindings/sound/sirf-audio-port.txt
Normal file
|
@ -0,0 +1,20 @@
|
|||
* SiRF SoC audio port
|
||||
|
||||
Required properties:
|
||||
- compatible: "sirf,audio-port"
|
||||
- reg: Base address and size entries:
|
||||
- dmas: List of DMA controller phandle and DMA request line ordered pairs.
|
||||
- dma-names: Identifier string for each DMA request line in the dmas property.
|
||||
These strings correspond 1:1 with the ordered pairs in dmas.
|
||||
|
||||
One of the DMA channels will be responsible for transmission (should be
|
||||
named "tx") and one for reception (should be named "rx").
|
||||
|
||||
Example:
|
||||
|
||||
audioport: audioport@b0040000 {
|
||||
compatible = "sirf,audio-port";
|
||||
reg = <0xb0040000 0x10000>;
|
||||
dmas = <&dmac1 3>, <&dmac1 8>;
|
||||
dma-names = "rx", "tx";
|
||||
};
|
41
Documentation/devicetree/bindings/sound/sirf-audio.txt
Normal file
41
Documentation/devicetree/bindings/sound/sirf-audio.txt
Normal file
|
@ -0,0 +1,41 @@
|
|||
* SiRF atlas6 and prima2 internal audio codec and port based audio setups
|
||||
|
||||
Required properties:
|
||||
- compatible: "sirf,sirf-audio-card"
|
||||
- sirf,audio-platform: phandle for the platform node
|
||||
- sirf,audio-codec: phandle for the SiRF internal codec node
|
||||
|
||||
Optional properties:
|
||||
- hp-pa-gpios: Need to be present if the board need control external
|
||||
headphone amplifier.
|
||||
- spk-pa-gpios: Need to be present if the board need control external
|
||||
speaker amplifier.
|
||||
- hp-switch-gpios: Need to be present if the board capable to detect jack
|
||||
insertion, removal.
|
||||
|
||||
Available audio endpoints for the audio-routing table:
|
||||
|
||||
Board connectors:
|
||||
* Headset Stereophone
|
||||
* Ext Spk
|
||||
* Line In
|
||||
* Mic
|
||||
|
||||
SiRF internal audio codec pins:
|
||||
* HPOUTL
|
||||
* HPOUTR
|
||||
* SPKOUT
|
||||
* Ext Mic
|
||||
* Mic Bias
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "sirf,sirf-audio-card";
|
||||
sirf,audio-codec = <&audiocodec>;
|
||||
sirf,audio-platform = <&audioport>;
|
||||
hp-pa-gpios = <&gpio 44 0>;
|
||||
spk-pa-gpios = <&gpio 46 0>;
|
||||
hp-switch-gpios = <&gpio 45 0>;
|
||||
};
|
||||
|
20
Documentation/devicetree/bindings/sound/tdm-slot.txt
Normal file
20
Documentation/devicetree/bindings/sound/tdm-slot.txt
Normal file
|
@ -0,0 +1,20 @@
|
|||
TDM slot:
|
||||
|
||||
This specifies audio DAI's TDM slot.
|
||||
|
||||
TDM slot properties:
|
||||
dai-tdm-slot-num : Number of slots in use.
|
||||
dai-tdm-slot-width : Width in bits for each slot.
|
||||
|
||||
For instance:
|
||||
dai-tdm-slot-num = <2>;
|
||||
dai-tdm-slot-width = <8>;
|
||||
|
||||
And for each spcified driver, there could be one .of_xlate_tdm_slot_mask()
|
||||
to specify a explicit mapping of the channels and the slots. If it's absent
|
||||
the default snd_soc_of_xlate_tdm_slot_mask() will be used to generating the
|
||||
tx and rx masks.
|
||||
|
||||
For snd_soc_of_xlate_tdm_slot_mask(), the tx and rx masks will use a 1 bit
|
||||
for an active slot as default, and the default active bits are at the LSB of
|
||||
the masks.
|
30
Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
Normal file
30
Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
Normal file
|
@ -0,0 +1,30 @@
|
|||
Texas Instruments - tlv320aic32x4 Codec module
|
||||
|
||||
The tlv320aic32x4 serial control bus communicates through I2C protocols
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "ti,tlv320aic32x4"
|
||||
- reg: I2C slave address
|
||||
- supply-*: Required supply regulators are:
|
||||
"iov" - digital IO power supply
|
||||
"ldoin" - LDO power supply
|
||||
"dv" - Digital core power supply
|
||||
"av" - Analog core power supply
|
||||
If you supply ldoin, dv and av are optional. Otherwise they are required
|
||||
See regulator/regulator.txt for more information about the detailed binding
|
||||
format.
|
||||
|
||||
Optional properties:
|
||||
- reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt
|
||||
- clocks/clock-names: Clock named 'mclk' for the master clock of the codec.
|
||||
See clock/clock-bindings.txt for information about the detailed format.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
codec: tlv320aic32x4@18 {
|
||||
compatible = "ti,tlv320aic32x4";
|
||||
reg = <0x18>;
|
||||
clocks = <&clks 201>;
|
||||
clock-names = "mclk";
|
||||
};
|
|
@ -6,7 +6,6 @@ Required properties:
|
|||
|
||||
- compatible - "string" - One of:
|
||||
"ti,tlv320aic3x" - Generic TLV320AIC3x device
|
||||
"ti,tlv320aic32x4" - TLV320AIC32x4
|
||||
"ti,tlv320aic33" - TLV320AIC33
|
||||
"ti,tlv320aic3007" - TLV320AIC3007
|
||||
"ti,tlv320aic3106" - TLV320AIC3106
|
||||
|
|
20
Documentation/devicetree/bindings/sound/widgets.txt
Normal file
20
Documentation/devicetree/bindings/sound/widgets.txt
Normal file
|
@ -0,0 +1,20 @@
|
|||
Widgets:
|
||||
|
||||
This mainly specifies audio off-codec DAPM widgets.
|
||||
|
||||
Each entry is a pair of strings in DT:
|
||||
|
||||
"template-wname", "user-supplied-wname"
|
||||
|
||||
The "template-wname" being the template widget name and currently includes:
|
||||
"Microphone", "Line", "Headphone" and "Speaker".
|
||||
|
||||
The "user-supplied-wname" being the user specified widget name.
|
||||
|
||||
For instance:
|
||||
simple-audio-widgets =
|
||||
"Microphone", "Microphone Jack",
|
||||
"Line", "Line In Jack",
|
||||
"Line", "Line Out Jack",
|
||||
"Headphone", "Headphone Jack",
|
||||
"Speaker", "Speaker External";
|
|
@ -2240,6 +2240,18 @@ int regmap_get_val_bytes(struct regmap *map)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_get_val_bytes);
|
||||
|
||||
int regmap_parse_val(struct regmap *map, const void *buf,
|
||||
unsigned int *val)
|
||||
{
|
||||
if (!map->format.parse_val)
|
||||
return -EINVAL;
|
||||
|
||||
*val = map->format.parse_val(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_parse_val);
|
||||
|
||||
static int __init regmap_initcall(void)
|
||||
{
|
||||
regmap_debugfs_initcall();
|
||||
|
|
|
@ -150,6 +150,12 @@ static int ssc_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat;
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
ssc->clk_from_rk_pin =
|
||||
of_property_read_bool(np, "atmel,clk-from-rk-pin");
|
||||
}
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
ssc->regs = devm_ioremap_resource(&pdev->dev, regs);
|
||||
if (IS_ERR(ssc->regs))
|
||||
|
|
|
@ -18,6 +18,7 @@ struct ssc_device {
|
|||
struct clk *clk;
|
||||
int user;
|
||||
int irq;
|
||||
bool clk_from_rk_pin;
|
||||
};
|
||||
|
||||
struct ssc_device * __must_check ssc_request(unsigned int ssc_num);
|
||||
|
|
|
@ -1702,9 +1702,9 @@
|
|||
/*
|
||||
* R373 (0x175) - FLL1 Control 5
|
||||
*/
|
||||
#define ARIZONA_FLL1_FRATIO_MASK 0x0700 /* FLL1_FRATIO - [10:8] */
|
||||
#define ARIZONA_FLL1_FRATIO_SHIFT 8 /* FLL1_FRATIO - [10:8] */
|
||||
#define ARIZONA_FLL1_FRATIO_WIDTH 3 /* FLL1_FRATIO - [10:8] */
|
||||
#define ARIZONA_FLL1_FRATIO_MASK 0x0F00 /* FLL1_FRATIO - [11:8] */
|
||||
#define ARIZONA_FLL1_FRATIO_SHIFT 8 /* FLL1_FRATIO - [11:8] */
|
||||
#define ARIZONA_FLL1_FRATIO_WIDTH 4 /* FLL1_FRATIO - [11:8] */
|
||||
#define ARIZONA_FLL1_OUTDIV_MASK 0x000E /* FLL1_OUTDIV - [3:1] */
|
||||
#define ARIZONA_FLL1_OUTDIV_SHIFT 1 /* FLL1_OUTDIV - [3:1] */
|
||||
#define ARIZONA_FLL1_OUTDIV_WIDTH 3 /* FLL1_OUTDIV - [3:1] */
|
||||
|
|
45
include/linux/platform_data/adau1977.h
Normal file
45
include/linux/platform_data/adau1977.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* ADAU1977/ADAU1978/ADAU1979 driver
|
||||
*
|
||||
* Copyright 2014 Analog Devices Inc.
|
||||
* Author: Lars-Peter Clausen <lars@metafoo.de>
|
||||
*
|
||||
* Licensed under the GPL-2.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_PLATFORM_DATA_ADAU1977_H__
|
||||
#define __LINUX_PLATFORM_DATA_ADAU1977_H__
|
||||
|
||||
/**
|
||||
* enum adau1977_micbias - ADAU1977 MICBIAS pin voltage setting
|
||||
* @ADAU1977_MICBIAS_5V0: MICBIAS is set to 5.0 V
|
||||
* @ADAU1977_MICBIAS_5V5: MICBIAS is set to 5.5 V
|
||||
* @ADAU1977_MICBIAS_6V0: MICBIAS is set to 6.0 V
|
||||
* @ADAU1977_MICBIAS_6V5: MICBIAS is set to 6.5 V
|
||||
* @ADAU1977_MICBIAS_7V0: MICBIAS is set to 7.0 V
|
||||
* @ADAU1977_MICBIAS_7V5: MICBIAS is set to 7.5 V
|
||||
* @ADAU1977_MICBIAS_8V0: MICBIAS is set to 8.0 V
|
||||
* @ADAU1977_MICBIAS_8V5: MICBIAS is set to 8.5 V
|
||||
* @ADAU1977_MICBIAS_9V0: MICBIAS is set to 9.0 V
|
||||
*/
|
||||
enum adau1977_micbias {
|
||||
ADAU1977_MICBIAS_5V0 = 0x0,
|
||||
ADAU1977_MICBIAS_5V5 = 0x1,
|
||||
ADAU1977_MICBIAS_6V0 = 0x2,
|
||||
ADAU1977_MICBIAS_6V5 = 0x3,
|
||||
ADAU1977_MICBIAS_7V0 = 0x4,
|
||||
ADAU1977_MICBIAS_7V5 = 0x5,
|
||||
ADAU1977_MICBIAS_8V0 = 0x6,
|
||||
ADAU1977_MICBIAS_8V5 = 0x7,
|
||||
ADAU1977_MICBIAS_9V0 = 0x8,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct adau1977_platform_data - Platform configuration data for the ADAU1977
|
||||
* @micbias: Specifies the voltage for the MICBIAS pin
|
||||
*/
|
||||
struct adau1977_platform_data {
|
||||
enum adau1977_micbias micbias;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,5 +1,4 @@
|
|||
/* arch/arm/plat-samsung/include/plat/audio.h
|
||||
*
|
||||
/*
|
||||
* Copyright (c) 2009 Samsung Electronics Co. Ltd
|
||||
* Author: Jaswinder Singh <jassi.brar@samsung.com>
|
||||
*
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* arch/arm/plat-samsung/include/plat/audio-simtec.h
|
||||
*
|
||||
/*
|
||||
* Copyright 2008 Simtec Electronics
|
||||
* http://armlinux.simtec.co.uk/
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include <linux/genalloc.h>
|
||||
|
||||
struct snd_platform_data {
|
||||
struct davinci_mcasp_pdata {
|
||||
u32 tx_dma_offset;
|
||||
u32 rx_dma_offset;
|
||||
int asp_chan_q; /* event queue number for ASP channel */
|
||||
|
@ -87,6 +87,8 @@ struct snd_platform_data {
|
|||
int tx_dma_channel;
|
||||
int rx_dma_channel;
|
||||
};
|
||||
/* TODO: Fix arch/arm/mach-davinci/ users and remove this define */
|
||||
#define snd_platform_data davinci_mcasp_pdata
|
||||
|
||||
enum {
|
||||
MCASP_VERSION_1 = 0, /* DM646x */
|
||||
|
|
|
@ -423,6 +423,8 @@ bool regmap_check_range_table(struct regmap *map, unsigned int reg,
|
|||
|
||||
int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
|
||||
int num_regs);
|
||||
int regmap_parse_val(struct regmap *map, const void *buf,
|
||||
unsigned int *val);
|
||||
|
||||
static inline bool regmap_reg_in_range(unsigned int reg,
|
||||
const struct regmap_range *range)
|
||||
|
@ -695,6 +697,13 @@ static inline int regmap_register_patch(struct regmap *map,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int regmap_parse_val(struct regmap *map, const void *buf,
|
||||
unsigned int *val)
|
||||
{
|
||||
WARN_ONCE(1, "regmap API is disabled");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline struct regmap *dev_get_regmap(struct device *dev,
|
||||
const char *name)
|
||||
{
|
||||
|
|
|
@ -34,17 +34,17 @@
|
|||
* B : SSI direction
|
||||
*/
|
||||
#define RSND_SSI_CLK_PIN_SHARE (1 << 31)
|
||||
#define RSND_SSI_SYNC (1 << 29) /* SSI34_sync etc */
|
||||
|
||||
#define RSND_SSI_PLAY (1 << 24)
|
||||
|
||||
#define RSND_SSI(_dma_id, _pio_irq, _flags) \
|
||||
{ .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
|
||||
#define RSND_SSI_SET(_dai_id, _dma_id, _pio_irq, _flags) \
|
||||
{ .dai_id = _dai_id, .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
|
||||
#define RSND_SSI_UNUSED \
|
||||
{ .dai_id = -1, .dma_id = -1, .pio_irq = -1, .flags = 0 }
|
||||
|
||||
struct rsnd_ssi_platform_info {
|
||||
int dai_id;
|
||||
int dai_id; /* will be removed */
|
||||
int dma_id;
|
||||
int pio_irq;
|
||||
u32 flags;
|
||||
|
@ -55,9 +55,31 @@ struct rsnd_ssi_platform_info {
|
|||
*/
|
||||
#define RSND_SCU_USE_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */
|
||||
|
||||
struct rsnd_scu_platform_info {
|
||||
#define RSND_SRC(rate, _dma_id) \
|
||||
{ .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, }
|
||||
#define RSND_SRC_SET(rate, _dma_id) \
|
||||
{ .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, }
|
||||
#define RSND_SRC_UNUSED \
|
||||
{ .flags = 0, .convert_rate = 0, .dma_id = 0, }
|
||||
|
||||
#define rsnd_scu_platform_info rsnd_src_platform_info
|
||||
#define src_info scu_info
|
||||
#define src_info_nr scu_info_nr
|
||||
|
||||
struct rsnd_src_platform_info {
|
||||
u32 flags;
|
||||
u32 convert_rate; /* sampling rate convert */
|
||||
int dma_id; /* for Gen2 SCU */
|
||||
};
|
||||
|
||||
struct rsnd_dai_path_info {
|
||||
struct rsnd_ssi_platform_info *ssi;
|
||||
struct rsnd_src_platform_info *src;
|
||||
};
|
||||
|
||||
struct rsnd_dai_platform_info {
|
||||
struct rsnd_dai_path_info playback;
|
||||
struct rsnd_dai_path_info capture;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -75,8 +97,10 @@ struct rcar_snd_info {
|
|||
u32 flags;
|
||||
struct rsnd_ssi_platform_info *ssi_info;
|
||||
int ssi_info_nr;
|
||||
struct rsnd_scu_platform_info *scu_info;
|
||||
int scu_info_nr;
|
||||
struct rsnd_src_platform_info *src_info;
|
||||
int src_info_nr;
|
||||
struct rsnd_dai_platform_info *dai_info;
|
||||
int dai_info_nr;
|
||||
int (*start)(int id);
|
||||
int (*stop)(int id);
|
||||
};
|
||||
|
|
|
@ -18,6 +18,8 @@ struct asoc_simple_dai {
|
|||
const char *name;
|
||||
unsigned int fmt;
|
||||
unsigned int sysclk;
|
||||
int slots;
|
||||
int slot_width;
|
||||
};
|
||||
|
||||
struct asoc_simple_card_info {
|
||||
|
@ -29,10 +31,6 @@ struct asoc_simple_card_info {
|
|||
unsigned int daifmt;
|
||||
struct asoc_simple_dai cpu_dai;
|
||||
struct asoc_simple_dai codec_dai;
|
||||
|
||||
/* used in simple-card.c */
|
||||
struct snd_soc_dai_link snd_link;
|
||||
struct snd_soc_card snd_card;
|
||||
};
|
||||
|
||||
#endif /* __SIMPLE_CARD_H */
|
||||
|
|
|
@ -142,6 +142,8 @@ struct snd_soc_dai_ops {
|
|||
* Called by soc_card drivers, normally in their hw_params.
|
||||
*/
|
||||
int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
|
||||
int (*of_xlate_tdm_slot_mask)(unsigned int slots,
|
||||
unsigned int *tx_mask, unsigned int *rx_mask);
|
||||
int (*set_tdm_slot)(struct snd_soc_dai *dai,
|
||||
unsigned int tx_mask, unsigned int rx_mask,
|
||||
int slots, int slot_width);
|
||||
|
@ -270,6 +272,7 @@ struct snd_soc_dai {
|
|||
/* parent platform/codec */
|
||||
struct snd_soc_platform *platform;
|
||||
struct snd_soc_codec *codec;
|
||||
struct snd_soc_component *component;
|
||||
|
||||
struct snd_soc_card *card;
|
||||
|
||||
|
|
|
@ -108,13 +108,9 @@ struct device;
|
|||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||
#define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \
|
||||
{ .id = snd_soc_dapm_virt_mux, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||
SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols)
|
||||
#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \
|
||||
{ .id = snd_soc_dapm_value_mux, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||
SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols)
|
||||
|
||||
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
|
||||
#define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\
|
||||
|
@ -172,10 +168,8 @@ struct device;
|
|||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_virt_mux, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1, \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, wevent, \
|
||||
wflags)
|
||||
|
||||
/* additional sequencing control within an event type */
|
||||
#define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \
|
||||
|
@ -311,12 +305,8 @@ struct device;
|
|||
.get = snd_soc_dapm_get_enum_double, \
|
||||
.put = snd_soc_dapm_put_enum_double, \
|
||||
.private_value = (unsigned long)&xenum }
|
||||
#define SOC_DAPM_ENUM_VIRT(xname, xenum) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_enum_double, \
|
||||
.get = snd_soc_dapm_get_enum_virt, \
|
||||
.put = snd_soc_dapm_put_enum_virt, \
|
||||
.private_value = (unsigned long)&xenum }
|
||||
#define SOC_DAPM_ENUM_VIRT(xname, xenum) \
|
||||
SOC_DAPM_ENUM(xname, xenum)
|
||||
#define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_enum_double, \
|
||||
|
@ -324,11 +314,7 @@ struct device;
|
|||
.put = xput, \
|
||||
.private_value = (unsigned long)&xenum }
|
||||
#define SOC_DAPM_VALUE_ENUM(xname, xenum) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_enum_double, \
|
||||
.get = snd_soc_dapm_get_value_enum_double, \
|
||||
.put = snd_soc_dapm_put_value_enum_double, \
|
||||
.private_value = (unsigned long)&xenum }
|
||||
SOC_DAPM_ENUM(xname, xenum)
|
||||
#define SOC_DAPM_PIN_SWITCH(xname) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname " Switch", \
|
||||
.info = snd_soc_dapm_info_pin_switch, \
|
||||
|
@ -392,14 +378,6 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo);
|
||||
int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
|
||||
|
@ -461,6 +439,7 @@ int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
|
|||
int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
|
||||
const char *pin);
|
||||
int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm);
|
||||
int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm);
|
||||
int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
|
||||
const char *pin);
|
||||
int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
|
||||
|
@ -470,7 +449,6 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
|
|||
void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
|
||||
|
||||
/* Mostly internal - should not normally be used */
|
||||
void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason);
|
||||
void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm);
|
||||
|
||||
/* dapm path query */
|
||||
|
@ -484,8 +462,6 @@ 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_virt_mux, /* virtual version of snd_soc_dapm_mux */
|
||||
snd_soc_dapm_value_mux, /* selects 1 analog signal from many inputs */
|
||||
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) */
|
||||
|
|
|
@ -45,6 +45,11 @@
|
|||
((unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
|
||||
.max = xmax, .platform_max = xmax, .invert = xinvert})
|
||||
#define SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, xsign_bit, xinvert) \
|
||||
((unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
|
||||
.max = xmax, .min = xmin, .platform_max = xmax, .sign_bit = xsign_bit, \
|
||||
.invert = xinvert})
|
||||
#define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \
|
||||
((unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
|
||||
|
@ -152,6 +157,15 @@
|
|||
{.reg = xreg, .rreg = xrreg, \
|
||||
.shift = xshift, .rshift = xshift, \
|
||||
.max = xmax, .min = xmin} }
|
||||
#define SOC_DOUBLE_R_S_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_DOUBLE_R_S_VALUE(reg_left, reg_right, xshift, \
|
||||
xmin, xmax, xsign_bit, xinvert) }
|
||||
#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
|
||||
|
@ -162,30 +176,28 @@
|
|||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .min = xmin, .max = xmax, \
|
||||
.platform_max = xmax} }
|
||||
#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \
|
||||
#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xitems, xtexts) \
|
||||
{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
|
||||
.max = xmax, .texts = xtexts, \
|
||||
.mask = xmax ? roundup_pow_of_two(xmax) - 1 : 0}
|
||||
#define SOC_ENUM_SINGLE(xreg, xshift, xmax, xtexts) \
|
||||
SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts)
|
||||
#define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \
|
||||
{ .max = xmax, .texts = xtexts }
|
||||
#define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xmax, xtexts, xvalues) \
|
||||
.items = xitems, .texts = xtexts, \
|
||||
.mask = xitems ? roundup_pow_of_two(xitems) - 1 : 0}
|
||||
#define SOC_ENUM_SINGLE(xreg, xshift, xitems, xtexts) \
|
||||
SOC_ENUM_DOUBLE(xreg, xshift, xshift, xitems, xtexts)
|
||||
#define SOC_ENUM_SINGLE_EXT(xitems, xtexts) \
|
||||
{ .items = xitems, .texts = xtexts }
|
||||
#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, .max = xmax, .texts = xtexts, .values = xvalues}
|
||||
#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xmax, xtexts, xvalues) \
|
||||
SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xmax, xtexts, xvalues)
|
||||
.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_ENUM_SINGLE_VIRT(xitems, xtexts) \
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, xitems, xtexts)
|
||||
#define SOC_ENUM(xname, xenum) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
|
||||
.info = snd_soc_info_enum_double, \
|
||||
.get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \
|
||||
.private_value = (unsigned long)&xenum }
|
||||
#define SOC_VALUE_ENUM(xname, xenum) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
|
||||
.info = snd_soc_info_enum_double, \
|
||||
.get = snd_soc_get_value_enum_double, \
|
||||
.put = snd_soc_put_value_enum_double, \
|
||||
.private_value = (unsigned long)&xenum }
|
||||
SOC_ENUM(xname, xenum)
|
||||
#define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\
|
||||
xhandler_get, xhandler_put) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
|
@ -272,17 +284,19 @@
|
|||
* ARRAY_SIZE internally
|
||||
*/
|
||||
#define SOC_ENUM_DOUBLE_DECL(name, xreg, xshift_l, xshift_r, xtexts) \
|
||||
struct soc_enum name = SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, \
|
||||
const struct soc_enum name = SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, \
|
||||
ARRAY_SIZE(xtexts), xtexts)
|
||||
#define SOC_ENUM_SINGLE_DECL(name, xreg, xshift, xtexts) \
|
||||
SOC_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xtexts)
|
||||
#define SOC_ENUM_SINGLE_EXT_DECL(name, xtexts) \
|
||||
struct soc_enum name = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(xtexts), xtexts)
|
||||
const struct soc_enum name = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(xtexts), xtexts)
|
||||
#define SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift_l, xshift_r, xmask, xtexts, xvalues) \
|
||||
struct soc_enum name = SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, \
|
||||
const struct soc_enum name = SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, \
|
||||
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_ENUM_SINGLE_VIRT_DECL(name, xtexts) \
|
||||
const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts)
|
||||
|
||||
/*
|
||||
* Component probe and remove ordering levels for components with runtime
|
||||
|
@ -413,6 +427,10 @@ struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
|
|||
struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
|
||||
const char *dai_link);
|
||||
|
||||
bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd);
|
||||
void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream);
|
||||
void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream);
|
||||
|
||||
/* Utility functions to get clock rates from various things */
|
||||
int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
|
||||
int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
|
||||
|
@ -496,10 +514,6 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo);
|
||||
#define snd_soc_info_bool_ext snd_ctl_boolean_mono_info
|
||||
|
@ -656,12 +670,19 @@ struct snd_soc_component {
|
|||
const char *name;
|
||||
int id;
|
||||
struct device *dev;
|
||||
|
||||
unsigned int active;
|
||||
|
||||
unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
|
||||
|
||||
struct list_head list;
|
||||
|
||||
struct snd_soc_dai_driver *dai_drv;
|
||||
int num_dai;
|
||||
|
||||
const struct snd_soc_component_driver *driver;
|
||||
|
||||
struct list_head dai_list;
|
||||
};
|
||||
|
||||
/* SoC Audio Codec device */
|
||||
|
@ -683,7 +704,6 @@ struct snd_soc_codec {
|
|||
|
||||
/* runtime */
|
||||
struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */
|
||||
unsigned int active;
|
||||
unsigned int cache_bypass:1; /* Suppress access to the cache */
|
||||
unsigned int suspended:1; /* Codec is in suspend PM state */
|
||||
unsigned int probed:1; /* Codec has been probed */
|
||||
|
@ -709,7 +729,6 @@ struct snd_soc_codec {
|
|||
|
||||
/* dapm */
|
||||
struct snd_soc_dapm_context dapm;
|
||||
unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_codec_root;
|
||||
|
@ -1067,6 +1086,7 @@ struct soc_mixer_control {
|
|||
int min, max, platform_max;
|
||||
int reg, rreg;
|
||||
unsigned int shift, rshift;
|
||||
unsigned int sign_bit;
|
||||
unsigned int invert:1;
|
||||
unsigned int autodisable:1;
|
||||
};
|
||||
|
@ -1085,11 +1105,10 @@ struct soc_mreg_control {
|
|||
|
||||
/* enumerated kcontrol */
|
||||
struct soc_enum {
|
||||
unsigned short reg;
|
||||
unsigned short reg2;
|
||||
int reg;
|
||||
unsigned char shift_l;
|
||||
unsigned char shift_r;
|
||||
unsigned int max;
|
||||
unsigned int items;
|
||||
unsigned int mask;
|
||||
const char * const *texts;
|
||||
const unsigned int *values;
|
||||
|
@ -1168,11 +1187,51 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e,
|
||||
unsigned int val)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!e->values)
|
||||
return val;
|
||||
|
||||
for (i = 0; i < e->items; i++)
|
||||
if (val == e->values[i])
|
||||
return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e,
|
||||
unsigned int item)
|
||||
{
|
||||
if (!e->values)
|
||||
return item;
|
||||
|
||||
return e->values[item];
|
||||
}
|
||||
|
||||
static inline bool snd_soc_component_is_active(
|
||||
struct snd_soc_component *component)
|
||||
{
|
||||
return component->active != 0;
|
||||
}
|
||||
|
||||
static inline bool snd_soc_codec_is_active(struct snd_soc_codec *codec)
|
||||
{
|
||||
return snd_soc_component_is_active(&codec->component);
|
||||
}
|
||||
|
||||
int snd_soc_util_init(void);
|
||||
void snd_soc_util_exit(void);
|
||||
|
||||
int snd_soc_of_parse_card_name(struct snd_soc_card *card,
|
||||
const char *propname);
|
||||
int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
|
||||
const char *propname);
|
||||
int snd_soc_of_parse_tdm_slot(struct device_node *np,
|
||||
unsigned int *slots,
|
||||
unsigned int *slot_width);
|
||||
int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
|
||||
const char *propname);
|
||||
unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
|
||||
|
@ -1188,4 +1247,15 @@ extern struct dentry *snd_soc_debugfs_root;
|
|||
|
||||
extern const struct dev_pm_ops snd_soc_pm_ops;
|
||||
|
||||
/* Helper functions */
|
||||
static inline void snd_soc_dapm_mutex_lock(struct snd_soc_dapm_context *dapm)
|
||||
{
|
||||
mutex_lock(&dapm->card->dapm_mutex);
|
||||
}
|
||||
|
||||
static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm)
|
||||
{
|
||||
mutex_unlock(&dapm->card->dapm_mutex);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
384
include/trace/events/hswadsp.h
Normal file
384
include/trace/events/hswadsp.h
Normal file
|
@ -0,0 +1,384 @@
|
|||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM hswadsp
|
||||
|
||||
#if !defined(_TRACE_HSWADSP_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_HSWADSP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
struct sst_hsw;
|
||||
struct sst_hsw_stream;
|
||||
struct sst_hsw_ipc_stream_free_req;
|
||||
struct sst_hsw_ipc_volume_req;
|
||||
struct sst_hsw_ipc_stream_alloc_req;
|
||||
struct sst_hsw_audio_data_format_ipc;
|
||||
struct sst_hsw_ipc_stream_info_reply;
|
||||
struct sst_hsw_ipc_device_config_req;
|
||||
|
||||
DECLARE_EVENT_CLASS(sst_irq,
|
||||
|
||||
TP_PROTO(uint32_t status, uint32_t mask),
|
||||
|
||||
TP_ARGS(status, mask),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( unsigned int, status )
|
||||
__field( unsigned int, mask )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->status = status;
|
||||
__entry->mask = mask;
|
||||
),
|
||||
|
||||
TP_printk("status 0x%8.8x mask 0x%8.8x",
|
||||
(unsigned int)__entry->status, (unsigned int)__entry->mask)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sst_irq, sst_irq_busy,
|
||||
|
||||
TP_PROTO(unsigned int status, unsigned int mask),
|
||||
|
||||
TP_ARGS(status, mask)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sst_irq, sst_irq_done,
|
||||
|
||||
TP_PROTO(unsigned int status, unsigned int mask),
|
||||
|
||||
TP_ARGS(status, mask)
|
||||
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(ipc,
|
||||
|
||||
TP_PROTO(const char *name, int val),
|
||||
|
||||
TP_ARGS(name, val),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string( name, name )
|
||||
__field( unsigned int, val )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, name);
|
||||
__entry->val = val;
|
||||
),
|
||||
|
||||
TP_printk("%s 0x%8.8x", __get_str(name), (unsigned int)__entry->val)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(ipc, ipc_request,
|
||||
|
||||
TP_PROTO(const char *name, int val),
|
||||
|
||||
TP_ARGS(name, val)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(ipc, ipc_reply,
|
||||
|
||||
TP_PROTO(const char *name, int val),
|
||||
|
||||
TP_ARGS(name, val)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(ipc, ipc_pending_reply,
|
||||
|
||||
TP_PROTO(const char *name, int val),
|
||||
|
||||
TP_ARGS(name, val)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(ipc, ipc_notification,
|
||||
|
||||
TP_PROTO(const char *name, int val),
|
||||
|
||||
TP_ARGS(name, val)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(ipc, ipc_error,
|
||||
|
||||
TP_PROTO(const char *name, int val),
|
||||
|
||||
TP_ARGS(name, val)
|
||||
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(stream_position,
|
||||
|
||||
TP_PROTO(unsigned int id, unsigned int pos),
|
||||
|
||||
TP_ARGS(id, pos),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( unsigned int, id )
|
||||
__field( unsigned int, pos )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->id = id;
|
||||
__entry->pos = pos;
|
||||
),
|
||||
|
||||
TP_printk("id %d position 0x%x",
|
||||
(unsigned int)__entry->id, (unsigned int)__entry->pos)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(stream_position, stream_read_position,
|
||||
|
||||
TP_PROTO(unsigned int id, unsigned int pos),
|
||||
|
||||
TP_ARGS(id, pos)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(stream_position, stream_write_position,
|
||||
|
||||
TP_PROTO(unsigned int id, unsigned int pos),
|
||||
|
||||
TP_ARGS(id, pos)
|
||||
|
||||
);
|
||||
|
||||
TRACE_EVENT(hsw_stream_buffer,
|
||||
|
||||
TP_PROTO(struct sst_hsw_stream *stream),
|
||||
|
||||
TP_ARGS(stream),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( int, id )
|
||||
__field( int, pt_addr )
|
||||
__field( int, num_pages )
|
||||
__field( int, ring_size )
|
||||
__field( int, ring_offset )
|
||||
__field( int, first_pfn )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->id = stream->host_id;
|
||||
__entry->pt_addr = stream->request.ringinfo.ring_pt_address;
|
||||
__entry->num_pages = stream->request.ringinfo.num_pages;
|
||||
__entry->ring_size = stream->request.ringinfo.ring_size;
|
||||
__entry->ring_offset = stream->request.ringinfo.ring_offset;
|
||||
__entry->first_pfn = stream->request.ringinfo.ring_first_pfn;
|
||||
),
|
||||
|
||||
TP_printk("stream %d ring addr 0x%x pages %d size 0x%x offset 0x%x PFN 0x%x",
|
||||
(int) __entry->id, (int)__entry->pt_addr,
|
||||
(int)__entry->num_pages, (int)__entry->ring_size,
|
||||
(int)__entry->ring_offset, (int)__entry->first_pfn)
|
||||
);
|
||||
|
||||
TRACE_EVENT(hsw_stream_alloc_reply,
|
||||
|
||||
TP_PROTO(struct sst_hsw_stream *stream),
|
||||
|
||||
TP_ARGS(stream),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( int, id )
|
||||
__field( int, stream_id )
|
||||
__field( int, mixer_id )
|
||||
__field( int, peak0 )
|
||||
__field( int, peak1 )
|
||||
__field( int, vol0 )
|
||||
__field( int, vol1 )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->id = stream->host_id;
|
||||
__entry->stream_id = stream->reply.stream_hw_id;
|
||||
__entry->mixer_id = stream->reply.mixer_hw_id;
|
||||
__entry->peak0 = stream->reply.peak_meter_register_address[0];
|
||||
__entry->peak1 = stream->reply.peak_meter_register_address[1];
|
||||
__entry->vol0 = stream->reply.volume_register_address[0];
|
||||
__entry->vol1 = stream->reply.volume_register_address[1];
|
||||
),
|
||||
|
||||
TP_printk("stream %d hw id %d mixer %d peak 0x%x:0x%x vol 0x%x,0x%x",
|
||||
(int) __entry->id, (int) __entry->stream_id, (int)__entry->mixer_id,
|
||||
(int)__entry->peak0, (int)__entry->peak1,
|
||||
(int)__entry->vol0, (int)__entry->vol1)
|
||||
);
|
||||
|
||||
TRACE_EVENT(hsw_mixer_info_reply,
|
||||
|
||||
TP_PROTO(struct sst_hsw_ipc_stream_info_reply *reply),
|
||||
|
||||
TP_ARGS(reply),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( int, mixer_id )
|
||||
__field( int, peak0 )
|
||||
__field( int, peak1 )
|
||||
__field( int, vol0 )
|
||||
__field( int, vol1 )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->mixer_id = reply->mixer_hw_id;
|
||||
__entry->peak0 = reply->peak_meter_register_address[0];
|
||||
__entry->peak1 = reply->peak_meter_register_address[1];
|
||||
__entry->vol0 = reply->volume_register_address[0];
|
||||
__entry->vol1 = reply->volume_register_address[1];
|
||||
),
|
||||
|
||||
TP_printk("mixer id %d peak 0x%x:0x%x vol 0x%x,0x%x",
|
||||
(int)__entry->mixer_id,
|
||||
(int)__entry->peak0, (int)__entry->peak1,
|
||||
(int)__entry->vol0, (int)__entry->vol1)
|
||||
);
|
||||
|
||||
TRACE_EVENT(hsw_stream_data_format,
|
||||
|
||||
TP_PROTO(struct sst_hsw_stream *stream,
|
||||
struct sst_hsw_audio_data_format_ipc *req),
|
||||
|
||||
TP_ARGS(stream, req),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( uint32_t, id )
|
||||
__field( uint32_t, frequency )
|
||||
__field( uint32_t, bitdepth )
|
||||
__field( uint32_t, map )
|
||||
__field( uint32_t, config )
|
||||
__field( uint32_t, style )
|
||||
__field( uint8_t, ch_num )
|
||||
__field( uint8_t, valid_bit )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->id = stream->host_id;
|
||||
__entry->frequency = req->frequency;
|
||||
__entry->bitdepth = req->bitdepth;
|
||||
__entry->map = req->map;
|
||||
__entry->config = req->config;
|
||||
__entry->style = req->style;
|
||||
__entry->ch_num = req->ch_num;
|
||||
__entry->valid_bit = req->valid_bit;
|
||||
),
|
||||
|
||||
TP_printk("stream %d freq %d depth %d map 0x%x config 0x%x style 0x%x ch %d bits %d",
|
||||
(int) __entry->id, (uint32_t)__entry->frequency,
|
||||
(uint32_t)__entry->bitdepth, (uint32_t)__entry->map,
|
||||
(uint32_t)__entry->config, (uint32_t)__entry->style,
|
||||
(uint8_t)__entry->ch_num, (uint8_t)__entry->valid_bit)
|
||||
);
|
||||
|
||||
TRACE_EVENT(hsw_stream_alloc_request,
|
||||
|
||||
TP_PROTO(struct sst_hsw_stream *stream,
|
||||
struct sst_hsw_ipc_stream_alloc_req *req),
|
||||
|
||||
TP_ARGS(stream, req),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( uint32_t, id )
|
||||
__field( uint8_t, path_id )
|
||||
__field( uint8_t, stream_type )
|
||||
__field( uint8_t, format_id )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->id = stream->host_id;
|
||||
__entry->path_id = req->path_id;
|
||||
__entry->stream_type = req->stream_type;
|
||||
__entry->format_id = req->format_id;
|
||||
),
|
||||
|
||||
TP_printk("stream %d path %d type %d format %d",
|
||||
(int) __entry->id, (uint8_t)__entry->path_id,
|
||||
(uint8_t)__entry->stream_type, (uint8_t)__entry->format_id)
|
||||
);
|
||||
|
||||
TRACE_EVENT(hsw_stream_free_req,
|
||||
|
||||
TP_PROTO(struct sst_hsw_stream *stream,
|
||||
struct sst_hsw_ipc_stream_free_req *req),
|
||||
|
||||
TP_ARGS(stream, req),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( int, id )
|
||||
__field( int, stream_id )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->id = stream->host_id;
|
||||
__entry->stream_id = req->stream_id;
|
||||
),
|
||||
|
||||
TP_printk("stream %d hw id %d",
|
||||
(int) __entry->id, (int) __entry->stream_id)
|
||||
);
|
||||
|
||||
TRACE_EVENT(hsw_volume_req,
|
||||
|
||||
TP_PROTO(struct sst_hsw_stream *stream,
|
||||
struct sst_hsw_ipc_volume_req *req),
|
||||
|
||||
TP_ARGS(stream, req),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( int, id )
|
||||
__field( uint32_t, channel )
|
||||
__field( uint32_t, target_volume )
|
||||
__field( uint64_t, curve_duration )
|
||||
__field( uint32_t, curve_type )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->id = stream->host_id;
|
||||
__entry->channel = req->channel;
|
||||
__entry->target_volume = req->target_volume;
|
||||
__entry->curve_duration = req->curve_duration;
|
||||
__entry->curve_type = req->curve_type;
|
||||
),
|
||||
|
||||
TP_printk("stream %d chan 0x%x vol %d duration %llu type %d",
|
||||
(int) __entry->id, (uint32_t) __entry->channel,
|
||||
(uint32_t)__entry->target_volume,
|
||||
(uint64_t)__entry->curve_duration,
|
||||
(uint32_t)__entry->curve_type)
|
||||
);
|
||||
|
||||
TRACE_EVENT(hsw_device_config_req,
|
||||
|
||||
TP_PROTO(struct sst_hsw_ipc_device_config_req *req),
|
||||
|
||||
TP_ARGS(req),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( uint32_t, ssp )
|
||||
__field( uint32_t, clock_freq )
|
||||
__field( uint32_t, mode )
|
||||
__field( uint16_t, clock_divider )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->ssp = req->ssp_interface;
|
||||
__entry->clock_freq = req->clock_frequency;
|
||||
__entry->mode = req->mode;
|
||||
__entry->clock_divider = req->clock_divider;
|
||||
),
|
||||
|
||||
TP_printk("SSP %d Freq %d mode %d div %d",
|
||||
(uint32_t)__entry->ssp,
|
||||
(uint32_t)__entry->clock_freq, (uint32_t)__entry->mode,
|
||||
(uint32_t)__entry->clock_divider)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_HSWADSP_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
148
include/trace/events/intel-sst.h
Normal file
148
include/trace/events/intel-sst.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM intel-sst
|
||||
|
||||
#if !defined(_TRACE_INTEL_SST_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_INTEL_SST_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
DECLARE_EVENT_CLASS(sst_ipc_msg,
|
||||
|
||||
TP_PROTO(unsigned int val),
|
||||
|
||||
TP_ARGS(val),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( unsigned int, val )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->val = val;
|
||||
),
|
||||
|
||||
TP_printk("0x%8.8x", (unsigned int)__entry->val)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sst_ipc_msg, sst_ipc_msg_tx,
|
||||
|
||||
TP_PROTO(unsigned int val),
|
||||
|
||||
TP_ARGS(val)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sst_ipc_msg, sst_ipc_msg_rx,
|
||||
|
||||
TP_PROTO(unsigned int val),
|
||||
|
||||
TP_ARGS(val)
|
||||
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(sst_ipc_mailbox,
|
||||
|
||||
TP_PROTO(unsigned int offset, unsigned int val),
|
||||
|
||||
TP_ARGS(offset, val),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( unsigned int, offset )
|
||||
__field( unsigned int, val )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->offset = offset;
|
||||
__entry->val = val;
|
||||
),
|
||||
|
||||
TP_printk(" 0x%4.4x = 0x%8.8x",
|
||||
(unsigned int)__entry->offset, (unsigned int)__entry->val)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_inbox_rdata,
|
||||
|
||||
TP_PROTO(unsigned int offset, unsigned int val),
|
||||
|
||||
TP_ARGS(offset, val)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_inbox_wdata,
|
||||
|
||||
TP_PROTO(unsigned int offset, unsigned int val),
|
||||
|
||||
TP_ARGS(offset, val)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_outbox_rdata,
|
||||
|
||||
TP_PROTO(unsigned int offset, unsigned int val),
|
||||
|
||||
TP_ARGS(offset, val)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_outbox_wdata,
|
||||
|
||||
TP_PROTO(unsigned int offset, unsigned int val),
|
||||
|
||||
TP_ARGS(offset, val)
|
||||
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(sst_ipc_mailbox_info,
|
||||
|
||||
TP_PROTO(unsigned int size),
|
||||
|
||||
TP_ARGS(size),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( unsigned int, size )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->size = size;
|
||||
),
|
||||
|
||||
TP_printk("Mailbox bytes 0x%8.8x", (unsigned int)__entry->size)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_inbox_read,
|
||||
|
||||
TP_PROTO(unsigned int size),
|
||||
|
||||
TP_ARGS(size)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_inbox_write,
|
||||
|
||||
TP_PROTO(unsigned int size),
|
||||
|
||||
TP_ARGS(size)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_outbox_read,
|
||||
|
||||
TP_PROTO(unsigned int size),
|
||||
|
||||
TP_ARGS(size)
|
||||
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_outbox_write,
|
||||
|
||||
TP_PROTO(unsigned int size),
|
||||
|
||||
TP_ARGS(size)
|
||||
|
||||
);
|
||||
|
||||
#endif /* _TRACE_SST_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
|
@ -1242,6 +1242,7 @@ int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_par
|
|||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_pcm_hw_constraint_mask64);
|
||||
|
||||
/**
|
||||
* snd_pcm_hw_constraint_integer - apply an integer constraint to an interval
|
||||
|
|
|
@ -50,6 +50,7 @@ source "sound/soc/pxa/Kconfig"
|
|||
source "sound/soc/samsung/Kconfig"
|
||||
source "sound/soc/s6000/Kconfig"
|
||||
source "sound/soc/sh/Kconfig"
|
||||
source "sound/soc/sirf/Kconfig"
|
||||
source "sound/soc/spear/Kconfig"
|
||||
source "sound/soc/tegra/Kconfig"
|
||||
source "sound/soc/txx9/Kconfig"
|
||||
|
|
|
@ -27,6 +27,7 @@ obj-$(CONFIG_SND_SOC) += pxa/
|
|||
obj-$(CONFIG_SND_SOC) += samsung/
|
||||
obj-$(CONFIG_SND_SOC) += s6000/
|
||||
obj-$(CONFIG_SND_SOC) += sh/
|
||||
obj-$(CONFIG_SND_SOC) += sirf/
|
||||
obj-$(CONFIG_SND_SOC) += spear/
|
||||
obj-$(CONFIG_SND_SOC) += tegra/
|
||||
obj-$(CONFIG_SND_SOC) += txx9/
|
||||
|
|
|
@ -58,6 +58,6 @@ config SND_AT91_SOC_AFEB9260
|
|||
depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC
|
||||
select SND_ATMEL_SOC_PDC
|
||||
select SND_ATMEL_SOC_SSC
|
||||
select SND_SOC_TLV320AIC23
|
||||
select SND_SOC_TLV320AIC23_I2C
|
||||
help
|
||||
Say Y here to support sound on AFEB9260 board.
|
||||
|
|
|
@ -341,6 +341,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
{
|
||||
int id = dai->id;
|
||||
struct atmel_ssc_info *ssc_p = &ssc_info[id];
|
||||
struct ssc_device *ssc = ssc_p->ssc;
|
||||
struct atmel_pcm_dma_params *dma_params;
|
||||
int dir, channels, bits;
|
||||
u32 tfmr, rfmr, tcmr, rcmr;
|
||||
|
@ -466,7 +467,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
| SSC_BF(RCMR_START, start_event)
|
||||
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
|
||||
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
|
||||
| SSC_BF(RCMR_CKS, SSC_CKS_CLOCK);
|
||||
| SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ?
|
||||
SSC_CKS_PIN : SSC_CKS_CLOCK);
|
||||
|
||||
rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
||||
| SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
|
||||
|
@ -481,7 +483,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
| SSC_BF(TCMR_START, start_event)
|
||||
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
|
||||
| SSC_BF(TCMR_CKO, SSC_CKO_NONE)
|
||||
| SSC_BF(TCMR_CKS, SSC_CKS_PIN);
|
||||
| SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ?
|
||||
SSC_CKS_CLOCK : SSC_CKS_PIN);
|
||||
|
||||
tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
||||
| SSC_BF(TFMR_FSDEN, 0)
|
||||
|
@ -550,7 +553,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
| SSC_BF(RCMR_START, SSC_START_RISING_RF)
|
||||
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
|
||||
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
|
||||
| SSC_BF(RCMR_CKS, SSC_CKS_PIN);
|
||||
| SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ?
|
||||
SSC_CKS_PIN : SSC_CKS_CLOCK);
|
||||
|
||||
rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
||||
| SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
|
||||
|
@ -565,7 +569,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
| SSC_BF(TCMR_START, SSC_START_RISING_RF)
|
||||
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
|
||||
| SSC_BF(TCMR_CKO, SSC_CKO_NONE)
|
||||
| SSC_BF(TCMR_CKS, SSC_CKS_PIN);
|
||||
| SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ?
|
||||
SSC_CKS_CLOCK : SSC_CKS_PIN);
|
||||
|
||||
tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
||||
| SSC_BF(TFMR_FSDEN, 0)
|
||||
|
|
|
@ -155,25 +155,14 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Add specific widgets */
|
||||
snd_soc_dapm_new_controls(dapm, at91sam9g20ek_dapm_widgets,
|
||||
ARRAY_SIZE(at91sam9g20ek_dapm_widgets));
|
||||
/* Set up specific audio path interconnects */
|
||||
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
|
||||
|
||||
/* not connected */
|
||||
snd_soc_dapm_nc_pin(dapm, "RLINEIN");
|
||||
snd_soc_dapm_nc_pin(dapm, "LLINEIN");
|
||||
|
||||
#ifdef ENABLE_MIC_INPUT
|
||||
snd_soc_dapm_enable_pin(dapm, "Int Mic");
|
||||
#else
|
||||
snd_soc_dapm_nc_pin(dapm, "Int Mic");
|
||||
#ifndef ENABLE_MIC_INPUT
|
||||
snd_soc_dapm_nc_pin(&rtd->card->dapm, "Int Mic");
|
||||
#endif
|
||||
|
||||
/* always connected */
|
||||
snd_soc_dapm_enable_pin(dapm, "Ext Spk");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -194,6 +183,11 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = {
|
|||
.dai_link = &at91sam9g20ek_dai,
|
||||
.num_links = 1,
|
||||
.set_bias_level = at91sam9g20ek_set_bias_level,
|
||||
|
||||
.dapm_widgets = at91sam9g20ek_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets),
|
||||
.dapm_routes = intercon,
|
||||
.num_dapm_routes = ARRAY_SIZE(intercon),
|
||||
};
|
||||
|
||||
static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -14,7 +14,8 @@ config SND_BF5XX_SOC_SSM2602
|
|||
depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI
|
||||
select SND_BF5XX_SOC_I2S if !BF60x
|
||||
select SND_BF6XX_SOC_I2S if BF60x
|
||||
select SND_SOC_SSM2602
|
||||
select SND_SOC_SSM2602_SPI if SPI_MASTER
|
||||
select SND_SOC_SSM2602_I2C if I2C
|
||||
help
|
||||
Say Y if you want to add support for the Analog Devices
|
||||
SSM2602 Audio Codec Add-On Card.
|
||||
|
@ -46,7 +47,8 @@ config SND_SOC_BFIN_EVAL_ADAV80X
|
|||
tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards"
|
||||
depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI
|
||||
select SND_BF5XX_SOC_I2S
|
||||
select SND_SOC_ADAV80X
|
||||
select SND_SOC_ADAV801 if SPI_MASTER
|
||||
select SND_SOC_ADAV803 if I2C
|
||||
help
|
||||
Say Y if you want to add support for the Analog Devices EVAL-ADAV801 or
|
||||
EVAL-ADAV803 board connected to one of the Blackfin evaluation boards
|
||||
|
@ -67,7 +69,8 @@ config SND_BF5XX_SOC_AD193X
|
|||
tristate "SoC AD193X Audio support for Blackfin"
|
||||
depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI
|
||||
select SND_BF5XX_SOC_I2S
|
||||
select SND_SOC_AD193X
|
||||
select SND_SOC_AD193X_I2C if I2C
|
||||
select SND_SOC_AD193X_SPI if SPI_MASTER
|
||||
help
|
||||
Say Y if you want to add support for AD193X codec on Blackfin.
|
||||
This driver supports AD1936, AD1937, AD1938 and AD1939.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
config SND_EP93XX_SOC
|
||||
tristate "SoC Audio support for the Cirrus Logic EP93xx series"
|
||||
depends on (ARCH_EP93XX || COMPILE_TEST) && SND_SOC
|
||||
depends on ARCH_EP93XX || COMPILE_TEST
|
||||
select SND_SOC_GENERIC_DMAENGINE_PCM
|
||||
help
|
||||
Say Y or M if you want to add support for codecs attached to
|
||||
|
@ -18,7 +18,7 @@ config SND_EP93XX_SOC_SNAPPERCL15
|
|||
tristate "SoC Audio support for Bluewater Systems Snapper CL15 module"
|
||||
depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15
|
||||
select SND_EP93XX_SOC_I2S
|
||||
select SND_SOC_TLV320AIC23
|
||||
select SND_SOC_TLV320AIC23_I2C
|
||||
help
|
||||
Say Y or M here if you want to add support for I2S audio on the
|
||||
Bluewater Systems Snapper CL15 module.
|
||||
|
|
|
@ -448,38 +448,38 @@ static const char *pm860x_opamp_texts[] = {"-50%", "-25%", "0%", "75%"};
|
|||
|
||||
static const char *pm860x_pa_texts[] = {"-33%", "0%", "33%", "66%"};
|
||||
|
||||
static const struct soc_enum pm860x_hs1_opamp_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 5, 4, pm860x_opamp_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(pm860x_hs1_opamp_enum,
|
||||
PM860X_HS1_CTRL, 5, pm860x_opamp_texts);
|
||||
|
||||
static const struct soc_enum pm860x_hs2_opamp_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 5, 4, pm860x_opamp_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(pm860x_hs2_opamp_enum,
|
||||
PM860X_HS2_CTRL, 5, pm860x_opamp_texts);
|
||||
|
||||
static const struct soc_enum pm860x_hs1_pa_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 3, 4, pm860x_pa_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(pm860x_hs1_pa_enum,
|
||||
PM860X_HS1_CTRL, 3, pm860x_pa_texts);
|
||||
|
||||
static const struct soc_enum pm860x_hs2_pa_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 3, 4, pm860x_pa_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(pm860x_hs2_pa_enum,
|
||||
PM860X_HS2_CTRL, 3, pm860x_pa_texts);
|
||||
|
||||
static const struct soc_enum pm860x_lo1_opamp_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 5, 4, pm860x_opamp_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(pm860x_lo1_opamp_enum,
|
||||
PM860X_LO1_CTRL, 5, pm860x_opamp_texts);
|
||||
|
||||
static const struct soc_enum pm860x_lo2_opamp_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 5, 4, pm860x_opamp_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(pm860x_lo2_opamp_enum,
|
||||
PM860X_LO2_CTRL, 5, pm860x_opamp_texts);
|
||||
|
||||
static const struct soc_enum pm860x_lo1_pa_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 3, 4, pm860x_pa_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(pm860x_lo1_pa_enum,
|
||||
PM860X_LO1_CTRL, 3, pm860x_pa_texts);
|
||||
|
||||
static const struct soc_enum pm860x_lo2_pa_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 3, 4, pm860x_pa_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(pm860x_lo2_pa_enum,
|
||||
PM860X_LO2_CTRL, 3, pm860x_pa_texts);
|
||||
|
||||
static const struct soc_enum pm860x_spk_pa_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 5, 4, pm860x_pa_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(pm860x_spk_pa_enum,
|
||||
PM860X_EAR_CTRL_1, 5, pm860x_pa_texts);
|
||||
|
||||
static const struct soc_enum pm860x_ear_pa_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_EAR_CTRL_2, 0, 4, pm860x_pa_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(pm860x_ear_pa_enum,
|
||||
PM860X_EAR_CTRL_2, 0, pm860x_pa_texts);
|
||||
|
||||
static const struct soc_enum pm860x_spk_ear_opamp_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 3, 4, pm860x_opamp_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(pm860x_spk_ear_opamp_enum,
|
||||
PM860X_EAR_CTRL_1, 3, pm860x_opamp_texts);
|
||||
|
||||
static const struct snd_kcontrol_new pm860x_snd_controls[] = {
|
||||
SOC_DOUBLE_R_TLV("ADC Capture Volume", PM860X_ADC_ANA_2,
|
||||
|
@ -561,8 +561,8 @@ static const char *aif1_text[] = {
|
|||
"PCM L", "PCM R",
|
||||
};
|
||||
|
||||
static const struct soc_enum aif1_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 6, 2, aif1_text);
|
||||
static SOC_ENUM_SINGLE_DECL(aif1_enum,
|
||||
PM860X_PCM_IFACE_3, 6, aif1_text);
|
||||
|
||||
static const struct snd_kcontrol_new aif1_mux =
|
||||
SOC_DAPM_ENUM("PCM Mux", aif1_enum);
|
||||
|
@ -572,8 +572,8 @@ static const char *i2s_din_text[] = {
|
|||
"DIN", "DIN1",
|
||||
};
|
||||
|
||||
static const struct soc_enum i2s_din_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 1, 2, i2s_din_text);
|
||||
static SOC_ENUM_SINGLE_DECL(i2s_din_enum,
|
||||
PM860X_I2S_IFACE_3, 1, i2s_din_text);
|
||||
|
||||
static const struct snd_kcontrol_new i2s_din_mux =
|
||||
SOC_DAPM_ENUM("I2S DIN Mux", i2s_din_enum);
|
||||
|
@ -583,8 +583,8 @@ static const char *i2s_mic_text[] = {
|
|||
"Ex PA", "ADC",
|
||||
};
|
||||
|
||||
static const struct soc_enum i2s_mic_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 4, 2, i2s_mic_text);
|
||||
static SOC_ENUM_SINGLE_DECL(i2s_mic_enum,
|
||||
PM860X_I2S_IFACE_3, 4, i2s_mic_text);
|
||||
|
||||
static const struct snd_kcontrol_new i2s_mic_mux =
|
||||
SOC_DAPM_ENUM("I2S Mic Mux", i2s_mic_enum);
|
||||
|
@ -594,8 +594,8 @@ static const char *adcl_text[] = {
|
|||
"ADCR", "ADCL",
|
||||
};
|
||||
|
||||
static const struct soc_enum adcl_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 4, 2, adcl_text);
|
||||
static SOC_ENUM_SINGLE_DECL(adcl_enum,
|
||||
PM860X_PCM_IFACE_3, 4, adcl_text);
|
||||
|
||||
static const struct snd_kcontrol_new adcl_mux =
|
||||
SOC_DAPM_ENUM("ADC Left Mux", adcl_enum);
|
||||
|
@ -605,8 +605,8 @@ static const char *adcr_text[] = {
|
|||
"ADCL", "ADCR",
|
||||
};
|
||||
|
||||
static const struct soc_enum adcr_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 2, 2, adcr_text);
|
||||
static SOC_ENUM_SINGLE_DECL(adcr_enum,
|
||||
PM860X_PCM_IFACE_3, 2, adcr_text);
|
||||
|
||||
static const struct snd_kcontrol_new adcr_mux =
|
||||
SOC_DAPM_ENUM("ADC Right Mux", adcr_enum);
|
||||
|
@ -616,8 +616,8 @@ static const char *adcr_ec_text[] = {
|
|||
"ADCR", "EC",
|
||||
};
|
||||
|
||||
static const struct soc_enum adcr_ec_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_ADC_EN_2, 3, 2, adcr_ec_text);
|
||||
static SOC_ENUM_SINGLE_DECL(adcr_ec_enum,
|
||||
PM860X_ADC_EN_2, 3, adcr_ec_text);
|
||||
|
||||
static const struct snd_kcontrol_new adcr_ec_mux =
|
||||
SOC_DAPM_ENUM("ADCR EC Mux", adcr_ec_enum);
|
||||
|
@ -627,8 +627,8 @@ static const char *ec_text[] = {
|
|||
"Left", "Right", "Left + Right",
|
||||
};
|
||||
|
||||
static const struct soc_enum ec_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_EC_PATH, 1, 3, ec_text);
|
||||
static SOC_ENUM_SINGLE_DECL(ec_enum,
|
||||
PM860X_EC_PATH, 1, ec_text);
|
||||
|
||||
static const struct snd_kcontrol_new ec_mux =
|
||||
SOC_DAPM_ENUM("EC Mux", ec_enum);
|
||||
|
@ -638,36 +638,36 @@ static const char *dac_text[] = {
|
|||
};
|
||||
|
||||
/* DAC Headset 1 Mux / Mux10 */
|
||||
static const struct soc_enum dac_hs1_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 0, 4, dac_text);
|
||||
static SOC_ENUM_SINGLE_DECL(dac_hs1_enum,
|
||||
PM860X_ANA_INPUT_SEL_1, 0, dac_text);
|
||||
|
||||
static const struct snd_kcontrol_new dac_hs1_mux =
|
||||
SOC_DAPM_ENUM("DAC HS1 Mux", dac_hs1_enum);
|
||||
|
||||
/* DAC Headset 2 Mux / Mux11 */
|
||||
static const struct soc_enum dac_hs2_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 2, 4, dac_text);
|
||||
static SOC_ENUM_SINGLE_DECL(dac_hs2_enum,
|
||||
PM860X_ANA_INPUT_SEL_1, 2, dac_text);
|
||||
|
||||
static const struct snd_kcontrol_new dac_hs2_mux =
|
||||
SOC_DAPM_ENUM("DAC HS2 Mux", dac_hs2_enum);
|
||||
|
||||
/* DAC Lineout 1 Mux / Mux12 */
|
||||
static const struct soc_enum dac_lo1_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 4, 4, dac_text);
|
||||
static SOC_ENUM_SINGLE_DECL(dac_lo1_enum,
|
||||
PM860X_ANA_INPUT_SEL_1, 4, dac_text);
|
||||
|
||||
static const struct snd_kcontrol_new dac_lo1_mux =
|
||||
SOC_DAPM_ENUM("DAC LO1 Mux", dac_lo1_enum);
|
||||
|
||||
/* DAC Lineout 2 Mux / Mux13 */
|
||||
static const struct soc_enum dac_lo2_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 6, 4, dac_text);
|
||||
static SOC_ENUM_SINGLE_DECL(dac_lo2_enum,
|
||||
PM860X_ANA_INPUT_SEL_1, 6, dac_text);
|
||||
|
||||
static const struct snd_kcontrol_new dac_lo2_mux =
|
||||
SOC_DAPM_ENUM("DAC LO2 Mux", dac_lo2_enum);
|
||||
|
||||
/* DAC Spearker Earphone Mux / Mux14 */
|
||||
static const struct soc_enum dac_spk_ear_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_2, 0, 4, dac_text);
|
||||
static SOC_ENUM_SINGLE_DECL(dac_spk_ear_enum,
|
||||
PM860X_ANA_INPUT_SEL_2, 0, dac_text);
|
||||
|
||||
static const struct snd_kcontrol_new dac_spk_ear_mux =
|
||||
SOC_DAPM_ENUM("DAC SP Mux", dac_spk_ear_enum);
|
||||
|
@ -677,29 +677,29 @@ static const char *in_text[] = {
|
|||
"Digital", "Analog",
|
||||
};
|
||||
|
||||
static const struct soc_enum hs1_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 0, 2, in_text);
|
||||
static SOC_ENUM_SINGLE_DECL(hs1_enum,
|
||||
PM860X_ANA_TO_ANA, 0, in_text);
|
||||
|
||||
static const struct snd_kcontrol_new hs1_mux =
|
||||
SOC_DAPM_ENUM("Headset1 Mux", hs1_enum);
|
||||
|
||||
/* Headset 2 Mux / Mux16 */
|
||||
static const struct soc_enum hs2_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 1, 2, in_text);
|
||||
static SOC_ENUM_SINGLE_DECL(hs2_enum,
|
||||
PM860X_ANA_TO_ANA, 1, in_text);
|
||||
|
||||
static const struct snd_kcontrol_new hs2_mux =
|
||||
SOC_DAPM_ENUM("Headset2 Mux", hs2_enum);
|
||||
|
||||
/* Lineout 1 Mux / Mux17 */
|
||||
static const struct soc_enum lo1_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 2, 2, in_text);
|
||||
static SOC_ENUM_SINGLE_DECL(lo1_enum,
|
||||
PM860X_ANA_TO_ANA, 2, in_text);
|
||||
|
||||
static const struct snd_kcontrol_new lo1_mux =
|
||||
SOC_DAPM_ENUM("Lineout1 Mux", lo1_enum);
|
||||
|
||||
/* Lineout 2 Mux / Mux18 */
|
||||
static const struct soc_enum lo2_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 3, 2, in_text);
|
||||
static SOC_ENUM_SINGLE_DECL(lo2_enum,
|
||||
PM860X_ANA_TO_ANA, 3, in_text);
|
||||
|
||||
static const struct snd_kcontrol_new lo2_mux =
|
||||
SOC_DAPM_ENUM("Lineout2 Mux", lo2_enum);
|
||||
|
@ -709,8 +709,8 @@ static const char *spk_text[] = {
|
|||
"Earpiece", "Speaker",
|
||||
};
|
||||
|
||||
static const struct soc_enum spk_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 6, 2, spk_text);
|
||||
static SOC_ENUM_SINGLE_DECL(spk_enum,
|
||||
PM860X_ANA_TO_ANA, 6, spk_text);
|
||||
|
||||
static const struct snd_kcontrol_new spk_demux =
|
||||
SOC_DAPM_ENUM("Speaker Earpiece Demux", spk_enum);
|
||||
|
@ -720,8 +720,8 @@ static const char *mic_text[] = {
|
|||
"Mic 1", "Mic 2",
|
||||
};
|
||||
|
||||
static const struct soc_enum mic_enum =
|
||||
SOC_ENUM_SINGLE(PM860X_ADC_ANA_4, 4, 2, mic_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mic_enum,
|
||||
PM860X_ADC_ANA_4, 4, mic_text);
|
||||
|
||||
static const struct snd_kcontrol_new mic_mux =
|
||||
SOC_DAPM_ENUM("MIC Mux", mic_enum);
|
||||
|
|
|
@ -8,6 +8,8 @@ config SND_SOC_I2C_AND_SPI
|
|||
default y if I2C=y
|
||||
default y if SPI_MASTER=y
|
||||
|
||||
menu "CODEC drivers"
|
||||
|
||||
config SND_SOC_ALL_CODECS
|
||||
tristate "Build all ASoC CODEC drivers"
|
||||
depends on COMPILE_TEST
|
||||
|
@ -16,15 +18,20 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_AB8500_CODEC if ABX500_CORE
|
||||
select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
|
||||
select SND_SOC_AD1836 if SPI_MASTER
|
||||
select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_AD193X_SPI if SPI_MASTER
|
||||
select SND_SOC_AD193X_I2C if I2C
|
||||
select SND_SOC_AD1980 if SND_SOC_AC97_BUS
|
||||
select SND_SOC_AD73311
|
||||
select SND_SOC_ADAU1373 if I2C
|
||||
select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_ADAV801 if SPI_MASTER
|
||||
select SND_SOC_ADAV803 if I2C
|
||||
select SND_SOC_ADAU1977_SPI if SPI_MASTER
|
||||
select SND_SOC_ADAU1977_I2C if I2C
|
||||
select SND_SOC_ADAU1701 if I2C
|
||||
select SND_SOC_ADS117X
|
||||
select SND_SOC_AK4104 if SPI_MASTER
|
||||
select SND_SOC_AK4535 if I2C
|
||||
select SND_SOC_AK4554
|
||||
select SND_SOC_AK4641 if I2C
|
||||
select SND_SOC_AK4642 if I2C
|
||||
select SND_SOC_AK4671 if I2C
|
||||
|
@ -59,19 +66,24 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_PCM1681 if I2C
|
||||
select SND_SOC_PCM1792A if SPI_MASTER
|
||||
select SND_SOC_PCM3008
|
||||
select SND_SOC_PCM512x_I2C if I2C
|
||||
select SND_SOC_PCM512x_SPI if SPI_MASTER
|
||||
select SND_SOC_RT5631 if I2C
|
||||
select SND_SOC_RT5640 if I2C
|
||||
select SND_SOC_SGTL5000 if I2C
|
||||
select SND_SOC_SI476X if MFD_SI476X_CORE
|
||||
select SND_SOC_SIRF_AUDIO_CODEC
|
||||
select SND_SOC_SN95031 if INTEL_SCU_IPC
|
||||
select SND_SOC_SPDIF
|
||||
select SND_SOC_SSM2518 if I2C
|
||||
select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_SSM2602_SPI if SPI_MASTER
|
||||
select SND_SOC_SSM2602_I2C if I2C
|
||||
select SND_SOC_STA32X if I2C
|
||||
select SND_SOC_STA529 if I2C
|
||||
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
|
||||
select SND_SOC_TAS5086 if I2C
|
||||
select SND_SOC_TLV320AIC23 if I2C
|
||||
select SND_SOC_TLV320AIC23_I2C if I2C
|
||||
select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
|
||||
select SND_SOC_TLV320AIC26 if SPI_MASTER
|
||||
select SND_SOC_TLV320AIC32X4 if I2C
|
||||
select SND_SOC_TLV320AIC3X if I2C
|
||||
|
@ -182,6 +194,14 @@ config SND_SOC_AD1836
|
|||
config SND_SOC_AD193X
|
||||
tristate
|
||||
|
||||
config SND_SOC_AD193X_SPI
|
||||
tristate
|
||||
select SND_SOC_AD193X
|
||||
|
||||
config SND_SOC_AD193X_I2C
|
||||
tristate
|
||||
select SND_SOC_AD193X
|
||||
|
||||
config SND_SOC_AD1980
|
||||
tristate
|
||||
|
||||
|
@ -189,41 +209,66 @@ config SND_SOC_AD73311
|
|||
tristate
|
||||
|
||||
config SND_SOC_ADAU1701
|
||||
tristate "Analog Devices ADAU1701 CODEC"
|
||||
depends on I2C
|
||||
select SND_SOC_SIGMADSP
|
||||
tristate
|
||||
|
||||
config SND_SOC_ADAU1373
|
||||
tristate
|
||||
|
||||
config SND_SOC_ADAU1977
|
||||
tristate
|
||||
|
||||
config SND_SOC_ADAU1977_SPI
|
||||
tristate
|
||||
select SND_SOC_ADAU1977
|
||||
select REGMAP_SPI
|
||||
|
||||
config SND_SOC_ADAU1977_I2C
|
||||
tristate
|
||||
select SND_SOC_ADAU1977
|
||||
select REGMAP_I2C
|
||||
|
||||
config SND_SOC_ADAV80X
|
||||
tristate
|
||||
|
||||
config SND_SOC_ADAV801
|
||||
tristate
|
||||
select SND_SOC_ADAV80X
|
||||
|
||||
config SND_SOC_ADAV803
|
||||
tristate
|
||||
select SND_SOC_ADAV80X
|
||||
|
||||
config SND_SOC_ADS117X
|
||||
tristate
|
||||
|
||||
config SND_SOC_AK4104
|
||||
tristate
|
||||
tristate "AKM AK4104 CODEC"
|
||||
depends on SPI_MASTER
|
||||
|
||||
config SND_SOC_AK4535
|
||||
tristate
|
||||
|
||||
config SND_SOC_AK4554
|
||||
tristate
|
||||
tristate "AKM AK4554 CODEC"
|
||||
|
||||
config SND_SOC_AK4641
|
||||
tristate
|
||||
|
||||
config SND_SOC_AK4642
|
||||
tristate
|
||||
tristate "AKM AK4642 CODEC"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_AK4671
|
||||
tristate
|
||||
|
||||
config SND_SOC_AK5386
|
||||
tristate
|
||||
tristate "AKM AK5638 CODEC"
|
||||
|
||||
config SND_SOC_ALC5623
|
||||
tristate
|
||||
|
||||
config SND_SOC_ALC5632
|
||||
tristate
|
||||
|
||||
|
@ -234,14 +279,17 @@ config SND_SOC_CS42L51
|
|||
tristate
|
||||
|
||||
config SND_SOC_CS42L52
|
||||
tristate
|
||||
tristate "Cirrus Logic CS42L52 CODEC"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_CS42L73
|
||||
tristate
|
||||
tristate "Cirrus Logic CS42L73 CODEC"
|
||||
depends on I2C
|
||||
|
||||
# Cirrus Logic CS4270 Codec
|
||||
config SND_SOC_CS4270
|
||||
tristate
|
||||
tristate "Cirrus Logic CS4270 CODEC"
|
||||
depends on I2C
|
||||
|
||||
# Cirrus Logic CS4270 Codec VD = 3.3V Errata
|
||||
# Select if you are affected by the errata where the part will not function
|
||||
|
@ -252,7 +300,8 @@ config SND_SOC_CS4270_VD33_ERRATA
|
|||
depends on SND_SOC_CS4270
|
||||
|
||||
config SND_SOC_CS4271
|
||||
tristate
|
||||
tristate "Cirrus Logic CS4271 CODEC"
|
||||
depends on SND_SOC_I2C_AND_SPI
|
||||
|
||||
config SND_SOC_CX20442
|
||||
tristate
|
||||
|
@ -283,6 +332,9 @@ config SND_SOC_BT_SCO
|
|||
config SND_SOC_DMIC
|
||||
tristate
|
||||
|
||||
config SND_SOC_HDMI_CODEC
|
||||
tristate "HDMI stub CODEC"
|
||||
|
||||
config SND_SOC_ISABELLE
|
||||
tristate
|
||||
|
||||
|
@ -301,18 +353,32 @@ config SND_SOC_MAX98095
|
|||
config SND_SOC_MAX9850
|
||||
tristate
|
||||
|
||||
config SND_SOC_HDMI_CODEC
|
||||
tristate
|
||||
|
||||
config SND_SOC_PCM1681
|
||||
tristate
|
||||
tristate "Texas Instruments PCM1681 CODEC"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_PCM1792A
|
||||
tristate
|
||||
tristate "Texas Instruments PCM1792A CODEC"
|
||||
depends on SPI_MASTER
|
||||
|
||||
config SND_SOC_PCM3008
|
||||
tristate
|
||||
|
||||
config SND_SOC_PCM512x
|
||||
tristate
|
||||
|
||||
config SND_SOC_PCM512x_I2C
|
||||
tristate "Texas Instruments PCM512x CODECs - I2C"
|
||||
depends on I2C
|
||||
select SND_SOC_PCM512x
|
||||
select REGMAP_I2C
|
||||
|
||||
config SND_SOC_PCM512x_SPI
|
||||
tristate "Texas Instruments PCM512x CODECs - SPI"
|
||||
depends on SPI_MASTER
|
||||
select SND_SOC_PCM512x
|
||||
select REGMAP_SPI
|
||||
|
||||
config SND_SOC_RT5631
|
||||
tristate
|
||||
|
||||
|
@ -321,7 +387,8 @@ config SND_SOC_RT5640
|
|||
|
||||
#Freescale sgtl5000 codec
|
||||
config SND_SOC_SGTL5000
|
||||
tristate
|
||||
tristate "Freescale SGTL5000 CODEC"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_SI476X
|
||||
tristate
|
||||
|
@ -330,11 +397,15 @@ config SND_SOC_SIGMADSP
|
|||
tristate
|
||||
select CRC32
|
||||
|
||||
config SND_SOC_SIRF_AUDIO_CODEC
|
||||
tristate "SiRF SoC internal audio codec"
|
||||
select REGMAP_MMIO
|
||||
|
||||
config SND_SOC_SN95031
|
||||
tristate
|
||||
|
||||
config SND_SOC_SPDIF
|
||||
tristate
|
||||
tristate "S/PDIF CODEC"
|
||||
|
||||
config SND_SOC_SSM2518
|
||||
tristate
|
||||
|
@ -342,6 +413,14 @@ config SND_SOC_SSM2518
|
|||
config SND_SOC_SSM2602
|
||||
tristate
|
||||
|
||||
config SND_SOC_SSM2602_SPI
|
||||
select SND_SOC_SSM2602
|
||||
tristate
|
||||
|
||||
config SND_SOC_SSM2602_I2C
|
||||
select SND_SOC_SSM2602
|
||||
tristate
|
||||
|
||||
config SND_SOC_STA32X
|
||||
tristate
|
||||
|
||||
|
@ -352,11 +431,20 @@ config SND_SOC_STAC9766
|
|||
tristate
|
||||
|
||||
config SND_SOC_TAS5086
|
||||
tristate
|
||||
tristate "Texas Instruments TAS5086 speaker amplifier"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_TLV320AIC23
|
||||
tristate
|
||||
|
||||
config SND_SOC_TLV320AIC23_I2C
|
||||
tristate
|
||||
select SND_SOC_TLV320AIC23
|
||||
|
||||
config SND_SOC_TLV320AIC23_SPI
|
||||
tristate
|
||||
select SND_SOC_TLV320AIC23
|
||||
|
||||
config SND_SOC_TLV320AIC26
|
||||
tristate
|
||||
depends on SPI
|
||||
|
@ -365,7 +453,8 @@ config SND_SOC_TLV320AIC32X4
|
|||
tristate
|
||||
|
||||
config SND_SOC_TLV320AIC3X
|
||||
tristate
|
||||
tristate "Texas Instruments TLV320AIC3x CODECs"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_TLV320DAC33
|
||||
tristate
|
||||
|
@ -414,55 +503,69 @@ config SND_SOC_WM8400
|
|||
tristate
|
||||
|
||||
config SND_SOC_WM8510
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8510 CODEC"
|
||||
depends on SND_SOC_I2C_AND_SPI
|
||||
|
||||
config SND_SOC_WM8523
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8523 DAC"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_WM8580
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8523 CODEC"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_WM8711
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8711 CODEC"
|
||||
depends on SND_SOC_I2C_AND_SPI
|
||||
|
||||
config SND_SOC_WM8727
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM8728
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8728 DAC"
|
||||
depends on SND_SOC_I2C_AND_SPI
|
||||
|
||||
config SND_SOC_WM8731
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8731 CODEC"
|
||||
depends on SND_SOC_I2C_AND_SPI
|
||||
|
||||
config SND_SOC_WM8737
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8737 ADC"
|
||||
depends on SND_SOC_I2C_AND_SPI
|
||||
|
||||
config SND_SOC_WM8741
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8737 DAC"
|
||||
depends on SND_SOC_I2C_AND_SPI
|
||||
|
||||
config SND_SOC_WM8750
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8750 CODEC"
|
||||
depends on SND_SOC_I2C_AND_SPI
|
||||
|
||||
config SND_SOC_WM8753
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8753 CODEC"
|
||||
depends on SND_SOC_I2C_AND_SPI
|
||||
|
||||
config SND_SOC_WM8770
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8770 CODEC"
|
||||
depends on SPI_MASTER
|
||||
|
||||
config SND_SOC_WM8776
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8776 CODEC"
|
||||
depends on SND_SOC_I2C_AND_SPI
|
||||
|
||||
config SND_SOC_WM8782
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM8804
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8804 S/PDIF transceiver"
|
||||
depends on SND_SOC_I2C_AND_SPI
|
||||
|
||||
config SND_SOC_WM8900
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM8903
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8903 CODEC"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_WM8904
|
||||
tristate
|
||||
|
@ -480,7 +583,8 @@ config SND_SOC_WM8961
|
|||
tristate
|
||||
|
||||
config SND_SOC_WM8962
|
||||
tristate
|
||||
tristate "Wolfson Microelectronics WM8962 CODEC"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_WM8971
|
||||
tristate
|
||||
|
@ -553,4 +657,7 @@ config SND_SOC_ML26124
|
|||
tristate
|
||||
|
||||
config SND_SOC_TPA6130A2
|
||||
tristate
|
||||
tristate "Texas Instruments TPA6130A2 headphone amplifier"
|
||||
depends on I2C
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -3,11 +3,18 @@ snd-soc-ab8500-codec-objs := ab8500-codec.o
|
|||
snd-soc-ac97-objs := ac97.o
|
||||
snd-soc-ad1836-objs := ad1836.o
|
||||
snd-soc-ad193x-objs := ad193x.o
|
||||
snd-soc-ad193x-spi-objs := ad193x-spi.o
|
||||
snd-soc-ad193x-i2c-objs := ad193x-i2c.o
|
||||
snd-soc-ad1980-objs := ad1980.o
|
||||
snd-soc-ad73311-objs := ad73311.o
|
||||
snd-soc-adau1701-objs := adau1701.o
|
||||
snd-soc-adau1373-objs := adau1373.o
|
||||
snd-soc-adau1977-objs := adau1977.o
|
||||
snd-soc-adau1977-spi-objs := adau1977-spi.o
|
||||
snd-soc-adau1977-i2c-objs := adau1977-i2c.o
|
||||
snd-soc-adav80x-objs := adav80x.o
|
||||
snd-soc-adav801-objs := adav801.o
|
||||
snd-soc-adav803-objs := adav803.o
|
||||
snd-soc-ads117x-objs := ads117x.o
|
||||
snd-soc-ak4104-objs := ak4104.o
|
||||
snd-soc-ak4535-objs := ak4535.o
|
||||
|
@ -46,6 +53,9 @@ snd-soc-hdmi-codec-objs := hdmi.o
|
|||
snd-soc-pcm1681-objs := pcm1681.o
|
||||
snd-soc-pcm1792a-codec-objs := pcm1792a.o
|
||||
snd-soc-pcm3008-objs := pcm3008.o
|
||||
snd-soc-pcm512x-objs := pcm512x.o
|
||||
snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
|
||||
snd-soc-pcm512x-spi-objs := pcm512x-spi.o
|
||||
snd-soc-rt5631-objs := rt5631.o
|
||||
snd-soc-rt5640-objs := rt5640.o
|
||||
snd-soc-sgtl5000-objs := sgtl5000.o
|
||||
|
@ -53,19 +63,24 @@ snd-soc-alc5623-objs := alc5623.o
|
|||
snd-soc-alc5632-objs := alc5632.o
|
||||
snd-soc-sigmadsp-objs := sigmadsp.o
|
||||
snd-soc-si476x-objs := si476x.o
|
||||
snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o
|
||||
snd-soc-sn95031-objs := sn95031.o
|
||||
snd-soc-spdif-tx-objs := spdif_transmitter.o
|
||||
snd-soc-spdif-rx-objs := spdif_receiver.o
|
||||
snd-soc-ssm2518-objs := ssm2518.o
|
||||
snd-soc-ssm2602-objs := ssm2602.o
|
||||
snd-soc-ssm2602-spi-objs := ssm2602-spi.o
|
||||
snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o
|
||||
snd-soc-sta32x-objs := sta32x.o
|
||||
snd-soc-sta529-objs := sta529.o
|
||||
snd-soc-stac9766-objs := stac9766.o
|
||||
snd-soc-tas5086-objs := tas5086.o
|
||||
snd-soc-tlv320aic23-objs := tlv320aic23.o
|
||||
snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
|
||||
snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o
|
||||
snd-soc-tlv320aic26-objs := tlv320aic26.o
|
||||
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
|
||||
snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
|
||||
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
|
||||
snd-soc-tlv320dac33-objs := tlv320dac33.o
|
||||
snd-soc-twl4030-objs := twl4030.o
|
||||
snd-soc-twl6040-objs := twl6040.o
|
||||
|
@ -134,11 +149,18 @@ obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o
|
|||
obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
|
||||
obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
|
||||
obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o
|
||||
obj-$(CONFIG_SND_SOC_AD193X_SPI) += snd-soc-ad193x-spi.o
|
||||
obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o
|
||||
obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
|
||||
obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
|
||||
obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o
|
||||
obj-$(CONFIG_SND_SOC_ADAU1977) += snd-soc-adau1977.o
|
||||
obj-$(CONFIG_SND_SOC_ADAU1977_SPI) += snd-soc-adau1977-spi.o
|
||||
obj-$(CONFIG_SND_SOC_ADAU1977_I2C) += snd-soc-adau1977-i2c.o
|
||||
obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o
|
||||
obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o
|
||||
obj-$(CONFIG_SND_SOC_ADAV801) += snd-soc-adav801.o
|
||||
obj-$(CONFIG_SND_SOC_ADAV803) += snd-soc-adav803.o
|
||||
obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o
|
||||
obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
|
||||
obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
|
||||
|
@ -179,6 +201,9 @@ obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
|
|||
obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o
|
||||
obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o
|
||||
obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
|
||||
obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
|
||||
obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
|
||||
obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
|
||||
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
|
||||
obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
|
||||
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
|
||||
|
@ -188,14 +213,18 @@ obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
|
|||
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
|
||||
obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o
|
||||
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
|
||||
obj-$(CONFIG_SND_SOC_SSM2602_SPI) += snd-soc-ssm2602-spi.o
|
||||
obj-$(CONFIG_SND_SOC_SSM2602_I2C) += snd-soc-ssm2602-i2c.o
|
||||
obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o
|
||||
obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
|
||||
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
|
||||
obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
|
||||
obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
|
||||
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
|
||||
|
|
|
@ -40,8 +40,8 @@ struct ad1836_priv {
|
|||
*/
|
||||
static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"};
|
||||
|
||||
static const struct soc_enum ad1836_deemp_enum =
|
||||
SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp);
|
||||
static SOC_ENUM_SINGLE_DECL(ad1836_deemp_enum,
|
||||
AD1836_DAC_CTRL1, 8, ad1836_deemp);
|
||||
|
||||
#define AD1836_DAC_VOLUME(x) \
|
||||
SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \
|
||||
|
|
54
sound/soc/codecs/ad193x-i2c.c
Normal file
54
sound/soc/codecs/ad193x-i2c.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* AD1936/AD1937 audio driver
|
||||
*
|
||||
* Copyright 2014 Analog Devices Inc.
|
||||
*
|
||||
* Licensed under the GPL-2.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "ad193x.h"
|
||||
|
||||
static const struct i2c_device_id ad193x_id[] = {
|
||||
{ "ad1936", 0 },
|
||||
{ "ad1937", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ad193x_id);
|
||||
|
||||
static int ad193x_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct regmap_config config;
|
||||
|
||||
config = ad193x_regmap_config;
|
||||
config.val_bits = 8;
|
||||
config.reg_bits = 8;
|
||||
|
||||
return ad193x_probe(&client->dev, devm_regmap_init_i2c(client, &config));
|
||||
}
|
||||
|
||||
static int ad193x_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver ad193x_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "ad193x",
|
||||
},
|
||||
.probe = ad193x_i2c_probe,
|
||||
.remove = ad193x_i2c_remove,
|
||||
.id_table = ad193x_id,
|
||||
};
|
||||
module_i2c_driver(ad193x_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC AD1936/AD1937 audio CODEC driver");
|
||||
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
|
||||
MODULE_LICENSE("GPL");
|
48
sound/soc/codecs/ad193x-spi.c
Normal file
48
sound/soc/codecs/ad193x-spi.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* AD1938/AD1939 audio driver
|
||||
*
|
||||
* Copyright 2014 Analog Devices Inc.
|
||||
*
|
||||
* Licensed under the GPL-2.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "ad193x.h"
|
||||
|
||||
static int ad193x_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct regmap_config config;
|
||||
|
||||
config = ad193x_regmap_config;
|
||||
config.val_bits = 8;
|
||||
config.reg_bits = 16;
|
||||
config.read_flag_mask = 0x09;
|
||||
config.write_flag_mask = 0x08;
|
||||
|
||||
return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config));
|
||||
}
|
||||
|
||||
static int ad193x_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver ad193x_spi_driver = {
|
||||
.driver = {
|
||||
.name = "ad193x",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ad193x_spi_probe,
|
||||
.remove = ad193x_spi_remove,
|
||||
};
|
||||
module_spi_driver(ad193x_spi_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC AD1938/AD1939 audio CODEC driver");
|
||||
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -6,12 +6,10 @@
|
|||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
@ -19,6 +17,7 @@
|
|||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "ad193x.h"
|
||||
|
||||
/* codec private data */
|
||||
|
@ -32,8 +31,8 @@ struct ad193x_priv {
|
|||
*/
|
||||
static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
|
||||
|
||||
static const struct soc_enum ad193x_deemp_enum =
|
||||
SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp);
|
||||
static SOC_ENUM_SINGLE_DECL(ad193x_deemp_enum, AD193X_DAC_CTRL2, 1,
|
||||
ad193x_deemp);
|
||||
|
||||
static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0);
|
||||
|
||||
|
@ -320,7 +319,7 @@ static struct snd_soc_dai_driver ad193x_dai = {
|
|||
.ops = &ad193x_dai_ops,
|
||||
};
|
||||
|
||||
static int ad193x_probe(struct snd_soc_codec *codec)
|
||||
static int ad193x_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
@ -352,7 +351,7 @@ static int ad193x_probe(struct snd_soc_codec *codec)
|
|||
}
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
|
||||
.probe = ad193x_probe,
|
||||
.probe = ad193x_codec_probe,
|
||||
.controls = ad193x_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(ad193x_snd_controls),
|
||||
.dapm_widgets = ad193x_dapm_widgets,
|
||||
|
@ -366,140 +365,31 @@ static bool adau193x_reg_volatile(struct device *dev, unsigned int reg)
|
|||
return false;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
|
||||
static const struct regmap_config ad193x_spi_regmap_config = {
|
||||
.val_bits = 8,
|
||||
.reg_bits = 16,
|
||||
.read_flag_mask = 0x09,
|
||||
.write_flag_mask = 0x08,
|
||||
|
||||
const struct regmap_config ad193x_regmap_config = {
|
||||
.max_register = AD193X_NUM_REGS - 1,
|
||||
.volatile_reg = adau193x_reg_volatile,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ad193x_regmap_config);
|
||||
|
||||
static int ad193x_spi_probe(struct spi_device *spi)
|
||||
int ad193x_probe(struct device *dev, struct regmap *regmap)
|
||||
{
|
||||
struct ad193x_priv *ad193x;
|
||||
|
||||
ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv),
|
||||
GFP_KERNEL);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
ad193x = devm_kzalloc(dev, sizeof(*ad193x), GFP_KERNEL);
|
||||
if (ad193x == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ad193x->regmap = devm_regmap_init_spi(spi, &ad193x_spi_regmap_config);
|
||||
if (IS_ERR(ad193x->regmap))
|
||||
return PTR_ERR(ad193x->regmap);
|
||||
ad193x->regmap = regmap;
|
||||
|
||||
spi_set_drvdata(spi, ad193x);
|
||||
dev_set_drvdata(dev, ad193x);
|
||||
|
||||
return snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad193x,
|
||||
&ad193x_dai, 1);
|
||||
return snd_soc_register_codec(dev, &soc_codec_dev_ad193x,
|
||||
&ad193x_dai, 1);
|
||||
}
|
||||
|
||||
static int ad193x_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver ad193x_spi_driver = {
|
||||
.driver = {
|
||||
.name = "ad193x",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ad193x_spi_probe,
|
||||
.remove = ad193x_spi_remove,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C)
|
||||
|
||||
static const struct regmap_config ad193x_i2c_regmap_config = {
|
||||
.val_bits = 8,
|
||||
.reg_bits = 8,
|
||||
|
||||
.max_register = AD193X_NUM_REGS - 1,
|
||||
.volatile_reg = adau193x_reg_volatile,
|
||||
};
|
||||
|
||||
static const struct i2c_device_id ad193x_id[] = {
|
||||
{ "ad1936", 0 },
|
||||
{ "ad1937", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ad193x_id);
|
||||
|
||||
static int ad193x_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct ad193x_priv *ad193x;
|
||||
|
||||
ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv),
|
||||
GFP_KERNEL);
|
||||
if (ad193x == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ad193x->regmap = devm_regmap_init_i2c(client, &ad193x_i2c_regmap_config);
|
||||
if (IS_ERR(ad193x->regmap))
|
||||
return PTR_ERR(ad193x->regmap);
|
||||
|
||||
i2c_set_clientdata(client, ad193x);
|
||||
|
||||
return snd_soc_register_codec(&client->dev, &soc_codec_dev_ad193x,
|
||||
&ad193x_dai, 1);
|
||||
}
|
||||
|
||||
static int ad193x_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver ad193x_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "ad193x",
|
||||
},
|
||||
.probe = ad193x_i2c_probe,
|
||||
.remove = ad193x_i2c_remove,
|
||||
.id_table = ad193x_id,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init ad193x_modinit(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C)
|
||||
ret = i2c_add_driver(&ad193x_i2c_driver);
|
||||
if (ret != 0) {
|
||||
printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n",
|
||||
ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
ret = spi_register_driver(&ad193x_spi_driver);
|
||||
if (ret != 0) {
|
||||
printk(KERN_ERR "Failed to register AD193X SPI driver: %d\n",
|
||||
ret);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
module_init(ad193x_modinit);
|
||||
|
||||
static void __exit ad193x_modexit(void)
|
||||
{
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
spi_unregister_driver(&ad193x_spi_driver);
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C)
|
||||
i2c_del_driver(&ad193x_i2c_driver);
|
||||
#endif
|
||||
}
|
||||
module_exit(ad193x_modexit);
|
||||
EXPORT_SYMBOL_GPL(ad193x_probe);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC ad193x driver");
|
||||
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
|
||||
|
|
|
@ -9,6 +9,13 @@
|
|||
#ifndef __AD193X_H__
|
||||
#define __AD193X_H__
|
||||
|
||||
#include <linux/regmap.h>
|
||||
|
||||
struct device;
|
||||
|
||||
extern const struct regmap_config ad193x_regmap_config;
|
||||
int ad193x_probe(struct device *dev, struct regmap *regmap);
|
||||
|
||||
#define AD193X_PLL_CLK_CTRL0 0x00
|
||||
#define AD193X_PLL_POWERDOWN 0x01
|
||||
#define AD193X_PLL_INPUT_MASK 0x6
|
||||
|
|
|
@ -345,15 +345,15 @@ static const char *adau1373_fdsp_sel_text[] = {
|
|||
"Channel 5",
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum,
|
||||
ADAU1373_FDSP_SEL1, 4, adau1373_fdsp_sel_text);
|
||||
static const SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum,
|
||||
ADAU1373_FDSP_SEL1, 0, adau1373_fdsp_sel_text);
|
||||
static const SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum,
|
||||
ADAU1373_FDSP_SEL2, 0, adau1373_fdsp_sel_text);
|
||||
static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum,
|
||||
ADAU1373_FDSP_SEL3, 0, adau1373_fdsp_sel_text);
|
||||
static const SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum,
|
||||
ADAU1373_FDSP_SEL4, 4, adau1373_fdsp_sel_text);
|
||||
|
||||
static const char *adau1373_hpf_cutoff_text[] = {
|
||||
|
@ -362,7 +362,7 @@ static const char *adau1373_hpf_cutoff_text[] = {
|
|||
"800Hz",
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum,
|
||||
ADAU1373_HPF_CTRL, 3, adau1373_hpf_cutoff_text);
|
||||
|
||||
static const char *adau1373_bass_lpf_cutoff_text[] = {
|
||||
|
@ -388,14 +388,14 @@ static const unsigned int adau1373_bass_tlv[] = {
|
|||
5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0),
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum,
|
||||
ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text);
|
||||
|
||||
static const SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum,
|
||||
static SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum,
|
||||
ADAU1373_BASS1, 2, 7, adau1373_bass_clip_level_text,
|
||||
adau1373_bass_clip_level_values);
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum,
|
||||
ADAU1373_BASS1, 0, adau1373_bass_hpf_cutoff_text);
|
||||
|
||||
static const char *adau1373_3d_level_text[] = {
|
||||
|
@ -409,9 +409,9 @@ static const char *adau1373_3d_cutoff_text[] = {
|
|||
"0.16875 fs", "0.27083 fs"
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum,
|
||||
ADAU1373_3D_CTRL1, 4, adau1373_3d_level_text);
|
||||
static const SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum,
|
||||
ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text);
|
||||
|
||||
static const unsigned int adau1373_3d_tlv[] = {
|
||||
|
@ -427,11 +427,11 @@ static const char *adau1373_lr_mux_text[] = {
|
|||
"Stereo",
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum,
|
||||
ADAU1373_OUTPUT_CTRL, 4, adau1373_lr_mux_text);
|
||||
static const SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum,
|
||||
ADAU1373_OUTPUT_CTRL, 6, adau1373_lr_mux_text);
|
||||
static const SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum,
|
||||
ADAU1373_LS_CTRL, 4, adau1373_lr_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new adau1373_controls[] = {
|
||||
|
@ -576,8 +576,8 @@ static const char *adau1373_decimator_text[] = {
|
|||
"DMIC1",
|
||||
};
|
||||
|
||||
static const struct soc_enum adau1373_decimator_enum =
|
||||
SOC_ENUM_SINGLE(0, 0, 2, adau1373_decimator_text);
|
||||
static SOC_ENUM_SINGLE_VIRT_DECL(adau1373_decimator_enum,
|
||||
adau1373_decimator_text);
|
||||
|
||||
static const struct snd_kcontrol_new adau1373_decimator_mux =
|
||||
SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum);
|
||||
|
|
59
sound/soc/codecs/adau1977-i2c.c
Normal file
59
sound/soc/codecs/adau1977-i2c.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* ADAU1977/ADAU1978/ADAU1979 driver
|
||||
*
|
||||
* Copyright 2014 Analog Devices Inc.
|
||||
* Author: Lars-Peter Clausen <lars@metafoo.de>
|
||||
*
|
||||
* Licensed under the GPL-2.
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "adau1977.h"
|
||||
|
||||
static int adau1977_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct regmap_config config;
|
||||
|
||||
config = adau1977_regmap_config;
|
||||
config.val_bits = 8;
|
||||
config.reg_bits = 8;
|
||||
|
||||
return adau1977_probe(&client->dev,
|
||||
devm_regmap_init_i2c(client, &config),
|
||||
id->driver_data, NULL);
|
||||
}
|
||||
|
||||
static int adau1977_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id adau1977_i2c_ids[] = {
|
||||
{ "adau1977", ADAU1977 },
|
||||
{ "adau1978", ADAU1978 },
|
||||
{ "adau1979", ADAU1978 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adau1977_i2c_ids);
|
||||
|
||||
static struct i2c_driver adau1977_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "adau1977",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = adau1977_i2c_probe,
|
||||
.remove = adau1977_i2c_remove,
|
||||
.id_table = adau1977_i2c_ids,
|
||||
};
|
||||
module_i2c_driver(adau1977_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver");
|
||||
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
||||
MODULE_LICENSE("GPL");
|
76
sound/soc/codecs/adau1977-spi.c
Normal file
76
sound/soc/codecs/adau1977-spi.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* ADAU1977/ADAU1978/ADAU1979 driver
|
||||
*
|
||||
* Copyright 2014 Analog Devices Inc.
|
||||
* Author: Lars-Peter Clausen <lars@metafoo.de>
|
||||
*
|
||||
* Licensed under the GPL-2.
|
||||
*/
|
||||
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "adau1977.h"
|
||||
|
||||
static void adau1977_spi_switch_mode(struct device *dev)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
|
||||
/*
|
||||
* To get the device into SPI mode CLATCH has to be pulled low three
|
||||
* times. Do this by issuing three dummy reads.
|
||||
*/
|
||||
spi_w8r8(spi, 0x00);
|
||||
spi_w8r8(spi, 0x00);
|
||||
spi_w8r8(spi, 0x00);
|
||||
}
|
||||
|
||||
static int adau1977_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
const struct spi_device_id *id = spi_get_device_id(spi);
|
||||
struct regmap_config config;
|
||||
|
||||
if (!id)
|
||||
return -EINVAL;
|
||||
|
||||
config = adau1977_regmap_config;
|
||||
config.val_bits = 8;
|
||||
config.reg_bits = 16;
|
||||
config.read_flag_mask = 0x1;
|
||||
|
||||
return adau1977_probe(&spi->dev,
|
||||
devm_regmap_init_spi(spi, &config),
|
||||
id->driver_data, adau1977_spi_switch_mode);
|
||||
}
|
||||
|
||||
static int adau1977_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id adau1977_spi_ids[] = {
|
||||
{ "adau1977", ADAU1977 },
|
||||
{ "adau1978", ADAU1978 },
|
||||
{ "adau1979", ADAU1978 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, adau1977_spi_ids);
|
||||
|
||||
static struct spi_driver adau1977_spi_driver = {
|
||||
.driver = {
|
||||
.name = "adau1977",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = adau1977_spi_probe,
|
||||
.remove = adau1977_spi_remove,
|
||||
.id_table = adau1977_spi_ids,
|
||||
};
|
||||
module_spi_driver(adau1977_spi_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver");
|
||||
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
||||
MODULE_LICENSE("GPL");
|
1018
sound/soc/codecs/adau1977.c
Normal file
1018
sound/soc/codecs/adau1977.c
Normal file
File diff suppressed because it is too large
Load diff
37
sound/soc/codecs/adau1977.h
Normal file
37
sound/soc/codecs/adau1977.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* ADAU1977/ADAU1978/ADAU1979 driver
|
||||
*
|
||||
* Copyright 2014 Analog Devices Inc.
|
||||
* Author: Lars-Peter Clausen <lars@metafoo.de>
|
||||
*
|
||||
* Licensed under the GPL-2.
|
||||
*/
|
||||
|
||||
#ifndef __SOUND_SOC_CODECS_ADAU1977_H__
|
||||
#define __SOUND_SOC_CODECS_ADAU1977_H__
|
||||
|
||||
#include <linux/regmap.h>
|
||||
|
||||
struct device;
|
||||
|
||||
enum adau1977_type {
|
||||
ADAU1977,
|
||||
ADAU1978,
|
||||
ADAU1979,
|
||||
};
|
||||
|
||||
int adau1977_probe(struct device *dev, struct regmap *regmap,
|
||||
enum adau1977_type type, void (*switch_mode)(struct device *dev));
|
||||
|
||||
extern const struct regmap_config adau1977_regmap_config;
|
||||
|
||||
enum adau1977_clk_id {
|
||||
ADAU1977_SYSCLK,
|
||||
};
|
||||
|
||||
enum adau1977_sysclk_src {
|
||||
ADAU1977_SYSCLK_SRC_MCLK,
|
||||
ADAU1977_SYSCLK_SRC_LRCLK,
|
||||
};
|
||||
|
||||
#endif
|
53
sound/soc/codecs/adav801.c
Normal file
53
sound/soc/codecs/adav801.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* ADAV801 audio driver
|
||||
*
|
||||
* Copyright 2014 Analog Devices Inc.
|
||||
*
|
||||
* Licensed under the GPL-2.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "adav80x.h"
|
||||
|
||||
static const struct spi_device_id adav80x_spi_id[] = {
|
||||
{ "adav801", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, adav80x_spi_id);
|
||||
|
||||
static int adav80x_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct regmap_config config;
|
||||
|
||||
config = adav80x_regmap_config;
|
||||
config.read_flag_mask = 0x01;
|
||||
|
||||
return adav80x_bus_probe(&spi->dev, devm_regmap_init_spi(spi, &config));
|
||||
}
|
||||
|
||||
static int adav80x_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver adav80x_spi_driver = {
|
||||
.driver = {
|
||||
.name = "adav801",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = adav80x_spi_probe,
|
||||
.remove = adav80x_spi_remove,
|
||||
.id_table = adav80x_spi_id,
|
||||
};
|
||||
module_spi_driver(adav80x_spi_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC ADAV801 driver");
|
||||
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
||||
MODULE_AUTHOR("Yi Li <yi.li@analog.com>>");
|
||||
MODULE_LICENSE("GPL");
|
50
sound/soc/codecs/adav803.c
Normal file
50
sound/soc/codecs/adav803.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* ADAV803 audio driver
|
||||
*
|
||||
* Copyright 2014 Analog Devices Inc.
|
||||
*
|
||||
* Licensed under the GPL-2.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "adav80x.h"
|
||||
|
||||
static const struct i2c_device_id adav803_id[] = {
|
||||
{ "adav803", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adav803_id);
|
||||
|
||||
static int adav803_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
return adav80x_bus_probe(&client->dev,
|
||||
devm_regmap_init_i2c(client, &adav80x_regmap_config));
|
||||
}
|
||||
|
||||
static int adav803_remove(struct i2c_client *client)
|
||||
{
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver adav803_driver = {
|
||||
.driver = {
|
||||
.name = "adav803",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = adav803_probe,
|
||||
.remove = adav803_remove,
|
||||
.id_table = adav803_id,
|
||||
};
|
||||
module_i2c_driver(adav803_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC ADAV803 driver");
|
||||
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
||||
MODULE_AUTHOR("Yi Li <yi.li@analog.com>>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -8,17 +8,15 @@
|
|||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "adav80x.h"
|
||||
|
||||
|
@ -541,6 +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;
|
||||
|
||||
if (dir == SND_SOC_CLOCK_IN) {
|
||||
switch (clk_id) {
|
||||
|
@ -573,7 +572,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
|
|||
regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2,
|
||||
iclk_ctrl2);
|
||||
|
||||
snd_soc_dapm_sync(&codec->dapm);
|
||||
snd_soc_dapm_sync(dapm);
|
||||
}
|
||||
} else {
|
||||
unsigned int mask;
|
||||
|
@ -600,17 +599,21 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
|
|||
adav80x->sysclk_pd[clk_id] = false;
|
||||
}
|
||||
|
||||
snd_soc_dapm_mutex_lock(dapm);
|
||||
|
||||
if (adav80x->sysclk_pd[0])
|
||||
snd_soc_dapm_disable_pin(&codec->dapm, "PLL1");
|
||||
snd_soc_dapm_disable_pin_unlocked(dapm, "PLL1");
|
||||
else
|
||||
snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1");
|
||||
snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL1");
|
||||
|
||||
if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2])
|
||||
snd_soc_dapm_disable_pin(&codec->dapm, "PLL2");
|
||||
snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2");
|
||||
else
|
||||
snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2");
|
||||
snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2");
|
||||
|
||||
snd_soc_dapm_sync(&codec->dapm);
|
||||
snd_soc_dapm_sync_unlocked(dapm);
|
||||
|
||||
snd_soc_dapm_mutex_unlock(dapm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -722,7 +725,7 @@ static int adav80x_dai_startup(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (!codec->active || !adav80x->rate)
|
||||
if (!snd_soc_codec_is_active(codec) || !adav80x->rate)
|
||||
return 0;
|
||||
|
||||
return snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
|
@ -735,7 +738,7 @@ static void adav80x_dai_shutdown(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (!codec->active)
|
||||
if (!snd_soc_codec_is_active(codec))
|
||||
adav80x->rate = 0;
|
||||
}
|
||||
|
||||
|
@ -864,39 +867,26 @@ static struct snd_soc_codec_driver adav80x_codec_driver = {
|
|||
.num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes),
|
||||
};
|
||||
|
||||
static int adav80x_bus_probe(struct device *dev, struct regmap *regmap)
|
||||
int adav80x_bus_probe(struct device *dev, struct regmap *regmap)
|
||||
{
|
||||
struct adav80x *adav80x;
|
||||
int ret;
|
||||
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL);
|
||||
adav80x = devm_kzalloc(dev, sizeof(*adav80x), GFP_KERNEL);
|
||||
if (!adav80x)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
dev_set_drvdata(dev, adav80x);
|
||||
adav80x->regmap = regmap;
|
||||
|
||||
ret = snd_soc_register_codec(dev, &adav80x_codec_driver,
|
||||
return snd_soc_register_codec(dev, &adav80x_codec_driver,
|
||||
adav80x_dais, ARRAY_SIZE(adav80x_dais));
|
||||
if (ret)
|
||||
kfree(adav80x);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(adav80x_bus_probe);
|
||||
|
||||
static int adav80x_bus_remove(struct device *dev)
|
||||
{
|
||||
snd_soc_unregister_codec(dev);
|
||||
kfree(dev_get_drvdata(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
static const struct regmap_config adav80x_spi_regmap_config = {
|
||||
const struct regmap_config adav80x_regmap_config = {
|
||||
.val_bits = 8,
|
||||
.pad_bits = 1,
|
||||
.reg_bits = 7,
|
||||
|
@ -908,105 +898,7 @@ static const struct regmap_config adav80x_spi_regmap_config = {
|
|||
.reg_defaults = adav80x_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults),
|
||||
};
|
||||
|
||||
static const struct spi_device_id adav80x_spi_id[] = {
|
||||
{ "adav801", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, adav80x_spi_id);
|
||||
|
||||
static int adav80x_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
return adav80x_bus_probe(&spi->dev,
|
||||
devm_regmap_init_spi(spi, &adav80x_spi_regmap_config));
|
||||
}
|
||||
|
||||
static int adav80x_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
return adav80x_bus_remove(&spi->dev);
|
||||
}
|
||||
|
||||
static struct spi_driver adav80x_spi_driver = {
|
||||
.driver = {
|
||||
.name = "adav801",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = adav80x_spi_probe,
|
||||
.remove = adav80x_spi_remove,
|
||||
.id_table = adav80x_spi_id,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C)
|
||||
static const struct regmap_config adav80x_i2c_regmap_config = {
|
||||
.val_bits = 8,
|
||||
.pad_bits = 1,
|
||||
.reg_bits = 7,
|
||||
|
||||
.max_register = ADAV80X_PLL_OUTE,
|
||||
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.reg_defaults = adav80x_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults),
|
||||
};
|
||||
|
||||
static const struct i2c_device_id adav80x_i2c_id[] = {
|
||||
{ "adav803", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adav80x_i2c_id);
|
||||
|
||||
static int adav80x_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
return adav80x_bus_probe(&client->dev,
|
||||
devm_regmap_init_i2c(client, &adav80x_i2c_regmap_config));
|
||||
}
|
||||
|
||||
static int adav80x_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
return adav80x_bus_remove(&client->dev);
|
||||
}
|
||||
|
||||
static struct i2c_driver adav80x_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "adav803",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = adav80x_i2c_probe,
|
||||
.remove = adav80x_i2c_remove,
|
||||
.id_table = adav80x_i2c_id,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init adav80x_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C)
|
||||
ret = i2c_add_driver(&adav80x_i2c_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
ret = spi_register_driver(&adav80x_spi_driver);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
module_init(adav80x_init);
|
||||
|
||||
static void __exit adav80x_exit(void)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_I2C)
|
||||
i2c_del_driver(&adav80x_i2c_driver);
|
||||
#endif
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
spi_unregister_driver(&adav80x_spi_driver);
|
||||
#endif
|
||||
}
|
||||
module_exit(adav80x_exit);
|
||||
EXPORT_SYMBOL_GPL(adav80x_regmap_config);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC ADAV80x driver");
|
||||
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
||||
|
|
|
@ -9,6 +9,13 @@
|
|||
#ifndef _ADAV80X_H
|
||||
#define _ADAV80X_H
|
||||
|
||||
#include <linux/regmap.h>
|
||||
|
||||
struct device;
|
||||
|
||||
extern const struct regmap_config adav80x_regmap_config;
|
||||
int adav80x_bus_probe(struct device *dev, struct regmap *regmap);
|
||||
|
||||
enum adav80x_pll_src {
|
||||
ADAV80X_PLL_SRC_XIN,
|
||||
ADAV80X_PLL_SRC_XTAL,
|
||||
|
|
|
@ -174,8 +174,6 @@ static int ak4104_probe(struct snd_soc_codec *codec)
|
|||
struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
codec->control_data = ak4104->regmap;
|
||||
|
||||
/* set power-up and non-reset bits */
|
||||
ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
|
||||
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
|
||||
|
|
|
@ -113,14 +113,14 @@ static const DECLARE_TLV_DB_SCALE(alc_tlv, -800, 50, 0);
|
|||
static const DECLARE_TLV_DB_SCALE(aux_in_tlv, -2100, 300, 0);
|
||||
|
||||
|
||||
static const struct soc_enum ak4641_mono_out_enum =
|
||||
SOC_ENUM_SINGLE(AK4641_SIG1, 6, 2, ak4641_mono_out);
|
||||
static const struct soc_enum ak4641_hp_out_enum =
|
||||
SOC_ENUM_SINGLE(AK4641_MODE2, 2, 2, ak4641_hp_out);
|
||||
static const struct soc_enum ak4641_mic_select_enum =
|
||||
SOC_ENUM_SINGLE(AK4641_MIC, 1, 2, ak4641_mic_select);
|
||||
static const struct soc_enum ak4641_mic_or_dac_enum =
|
||||
SOC_ENUM_SINGLE(AK4641_BTIF, 4, 2, ak4641_mic_or_dac);
|
||||
static SOC_ENUM_SINGLE_DECL(ak4641_mono_out_enum,
|
||||
AK4641_SIG1, 6, ak4641_mono_out);
|
||||
static SOC_ENUM_SINGLE_DECL(ak4641_hp_out_enum,
|
||||
AK4641_MODE2, 2, ak4641_hp_out);
|
||||
static SOC_ENUM_SINGLE_DECL(ak4641_mic_select_enum,
|
||||
AK4641_MIC, 1, ak4641_mic_select);
|
||||
static SOC_ENUM_SINGLE_DECL(ak4641_mic_or_dac_enum,
|
||||
AK4641_BTIF, 4, ak4641_mic_or_dac);
|
||||
|
||||
static const struct snd_kcontrol_new ak4641_snd_controls[] = {
|
||||
SOC_ENUM("Mono 1 Output", ak4641_mono_out_enum),
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/initval.h>
|
||||
|
@ -23,104 +24,99 @@
|
|||
#include "ak4671.h"
|
||||
|
||||
|
||||
/* codec private data */
|
||||
struct ak4671_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
};
|
||||
|
||||
/* ak4671 register cache & default register settings */
|
||||
static const u8 ak4671_reg[AK4671_CACHEREGNUM] = {
|
||||
0x00, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */
|
||||
0xf6, /* AK4671_PLL_MODE_SELECT0 (0x01) */
|
||||
0x00, /* AK4671_PLL_MODE_SELECT1 (0x02) */
|
||||
0x02, /* AK4671_FORMAT_SELECT (0x03) */
|
||||
0x00, /* AK4671_MIC_SIGNAL_SELECT (0x04) */
|
||||
0x55, /* AK4671_MIC_AMP_GAIN (0x05) */
|
||||
0x00, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */
|
||||
0x00, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */
|
||||
0xb5, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */
|
||||
0x00, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */
|
||||
0x00, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */
|
||||
0x00, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */
|
||||
0x00, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */
|
||||
0x00, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */
|
||||
0x00, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */
|
||||
0x00, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */
|
||||
0x00, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */
|
||||
0x80, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */
|
||||
0x91, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */
|
||||
0x91, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */
|
||||
0xe1, /* AK4671_ALC_REFERENCE_SELECT (0x14) */
|
||||
0x00, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */
|
||||
0x00, /* AK4671_ALC_TIMER_SELECT (0x16) */
|
||||
0x00, /* AK4671_ALC_MODE_CONTROL (0x17) */
|
||||
0x02, /* AK4671_MODE_CONTROL1 (0x18) */
|
||||
0x01, /* AK4671_MODE_CONTROL2 (0x19) */
|
||||
0x18, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */
|
||||
0x18, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */
|
||||
0x00, /* AK4671_SIDETONE_A_CONTROL (0x1c) */
|
||||
0x02, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */
|
||||
0x00, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */
|
||||
0x00, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */
|
||||
0x00, /* AK4671_FIL3_COEFFICIENT2 (0x20) */
|
||||
0x00, /* AK4671_FIL3_COEFFICIENT3 (0x21) */
|
||||
0x00, /* AK4671_EQ_COEFFICIENT0 (0x22) */
|
||||
0x00, /* AK4671_EQ_COEFFICIENT1 (0x23) */
|
||||
0x00, /* AK4671_EQ_COEFFICIENT2 (0x24) */
|
||||
0x00, /* AK4671_EQ_COEFFICIENT3 (0x25) */
|
||||
0x00, /* AK4671_EQ_COEFFICIENT4 (0x26) */
|
||||
0x00, /* AK4671_EQ_COEFFICIENT5 (0x27) */
|
||||
0xa9, /* AK4671_FIL1_COEFFICIENT0 (0x28) */
|
||||
0x1f, /* AK4671_FIL1_COEFFICIENT1 (0x29) */
|
||||
0xad, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */
|
||||
0x20, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */
|
||||
0x00, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */
|
||||
0x00, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */
|
||||
0x00, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */
|
||||
0x00, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */
|
||||
0x00, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */
|
||||
0x00, /* this register not used */
|
||||
0x00, /* AK4671_E1_COEFFICIENT0 (0x32) */
|
||||
0x00, /* AK4671_E1_COEFFICIENT1 (0x33) */
|
||||
0x00, /* AK4671_E1_COEFFICIENT2 (0x34) */
|
||||
0x00, /* AK4671_E1_COEFFICIENT3 (0x35) */
|
||||
0x00, /* AK4671_E1_COEFFICIENT4 (0x36) */
|
||||
0x00, /* AK4671_E1_COEFFICIENT5 (0x37) */
|
||||
0x00, /* AK4671_E2_COEFFICIENT0 (0x38) */
|
||||
0x00, /* AK4671_E2_COEFFICIENT1 (0x39) */
|
||||
0x00, /* AK4671_E2_COEFFICIENT2 (0x3a) */
|
||||
0x00, /* AK4671_E2_COEFFICIENT3 (0x3b) */
|
||||
0x00, /* AK4671_E2_COEFFICIENT4 (0x3c) */
|
||||
0x00, /* AK4671_E2_COEFFICIENT5 (0x3d) */
|
||||
0x00, /* AK4671_E3_COEFFICIENT0 (0x3e) */
|
||||
0x00, /* AK4671_E3_COEFFICIENT1 (0x3f) */
|
||||
0x00, /* AK4671_E3_COEFFICIENT2 (0x40) */
|
||||
0x00, /* AK4671_E3_COEFFICIENT3 (0x41) */
|
||||
0x00, /* AK4671_E3_COEFFICIENT4 (0x42) */
|
||||
0x00, /* AK4671_E3_COEFFICIENT5 (0x43) */
|
||||
0x00, /* AK4671_E4_COEFFICIENT0 (0x44) */
|
||||
0x00, /* AK4671_E4_COEFFICIENT1 (0x45) */
|
||||
0x00, /* AK4671_E4_COEFFICIENT2 (0x46) */
|
||||
0x00, /* AK4671_E4_COEFFICIENT3 (0x47) */
|
||||
0x00, /* AK4671_E4_COEFFICIENT4 (0x48) */
|
||||
0x00, /* AK4671_E4_COEFFICIENT5 (0x49) */
|
||||
0x00, /* AK4671_E5_COEFFICIENT0 (0x4a) */
|
||||
0x00, /* AK4671_E5_COEFFICIENT1 (0x4b) */
|
||||
0x00, /* AK4671_E5_COEFFICIENT2 (0x4c) */
|
||||
0x00, /* AK4671_E5_COEFFICIENT3 (0x4d) */
|
||||
0x00, /* AK4671_E5_COEFFICIENT4 (0x4e) */
|
||||
0x00, /* AK4671_E5_COEFFICIENT5 (0x4f) */
|
||||
0x88, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */
|
||||
0x88, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */
|
||||
0x08, /* AK4671_EQ_CONTRO_10KHZ (0x52) */
|
||||
0x00, /* AK4671_PCM_IF_CONTROL0 (0x53) */
|
||||
0x00, /* AK4671_PCM_IF_CONTROL1 (0x54) */
|
||||
0x00, /* AK4671_PCM_IF_CONTROL2 (0x55) */
|
||||
0x18, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */
|
||||
0x18, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */
|
||||
0x00, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */
|
||||
0x00, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */
|
||||
0x00, /* AK4671_SAR_ADC_CONTROL (0x5a) */
|
||||
static const struct reg_default ak4671_reg_defaults[] = {
|
||||
{ 0x00, 0x00 }, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */
|
||||
{ 0x01, 0xf6 }, /* AK4671_PLL_MODE_SELECT0 (0x01) */
|
||||
{ 0x02, 0x00 }, /* AK4671_PLL_MODE_SELECT1 (0x02) */
|
||||
{ 0x03, 0x02 }, /* AK4671_FORMAT_SELECT (0x03) */
|
||||
{ 0x04, 0x00 }, /* AK4671_MIC_SIGNAL_SELECT (0x04) */
|
||||
{ 0x05, 0x55 }, /* AK4671_MIC_AMP_GAIN (0x05) */
|
||||
{ 0x06, 0x00 }, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */
|
||||
{ 0x07, 0x00 }, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */
|
||||
{ 0x08, 0xb5 }, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */
|
||||
{ 0x09, 0x00 }, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */
|
||||
{ 0x0a, 0x00 }, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */
|
||||
{ 0x0b, 0x00 }, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */
|
||||
{ 0x0c, 0x00 }, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */
|
||||
{ 0x0d, 0x00 }, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */
|
||||
{ 0x0e, 0x00 }, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */
|
||||
{ 0x0f, 0x00 }, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */
|
||||
{ 0x10, 0x00 }, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */
|
||||
{ 0x11, 0x80 }, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */
|
||||
{ 0x12, 0x91 }, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */
|
||||
{ 0x13, 0x91 }, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */
|
||||
{ 0x14, 0xe1 }, /* AK4671_ALC_REFERENCE_SELECT (0x14) */
|
||||
{ 0x15, 0x00 }, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */
|
||||
{ 0x16, 0x00 }, /* AK4671_ALC_TIMER_SELECT (0x16) */
|
||||
{ 0x17, 0x00 }, /* AK4671_ALC_MODE_CONTROL (0x17) */
|
||||
{ 0x18, 0x02 }, /* AK4671_MODE_CONTROL1 (0x18) */
|
||||
{ 0x19, 0x01 }, /* AK4671_MODE_CONTROL2 (0x19) */
|
||||
{ 0x1a, 0x18 }, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */
|
||||
{ 0x1b, 0x18 }, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */
|
||||
{ 0x1c, 0x00 }, /* AK4671_SIDETONE_A_CONTROL (0x1c) */
|
||||
{ 0x1d, 0x02 }, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */
|
||||
{ 0x1e, 0x00 }, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */
|
||||
{ 0x1f, 0x00 }, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */
|
||||
{ 0x20, 0x00 }, /* AK4671_FIL3_COEFFICIENT2 (0x20) */
|
||||
{ 0x21, 0x00 }, /* AK4671_FIL3_COEFFICIENT3 (0x21) */
|
||||
{ 0x22, 0x00 }, /* AK4671_EQ_COEFFICIENT0 (0x22) */
|
||||
{ 0x23, 0x00 }, /* AK4671_EQ_COEFFICIENT1 (0x23) */
|
||||
{ 0x24, 0x00 }, /* AK4671_EQ_COEFFICIENT2 (0x24) */
|
||||
{ 0x25, 0x00 }, /* AK4671_EQ_COEFFICIENT3 (0x25) */
|
||||
{ 0x26, 0x00 }, /* AK4671_EQ_COEFFICIENT4 (0x26) */
|
||||
{ 0x27, 0x00 }, /* AK4671_EQ_COEFFICIENT5 (0x27) */
|
||||
{ 0x28, 0xa9 }, /* AK4671_FIL1_COEFFICIENT0 (0x28) */
|
||||
{ 0x29, 0x1f }, /* AK4671_FIL1_COEFFICIENT1 (0x29) */
|
||||
{ 0x2a, 0xad }, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */
|
||||
{ 0x2b, 0x20 }, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */
|
||||
{ 0x2c, 0x00 }, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */
|
||||
{ 0x2d, 0x00 }, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */
|
||||
{ 0x2e, 0x00 }, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */
|
||||
{ 0x2f, 0x00 }, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */
|
||||
{ 0x30, 0x00 }, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */
|
||||
|
||||
{ 0x32, 0x00 }, /* AK4671_E1_COEFFICIENT0 (0x32) */
|
||||
{ 0x33, 0x00 }, /* AK4671_E1_COEFFICIENT1 (0x33) */
|
||||
{ 0x34, 0x00 }, /* AK4671_E1_COEFFICIENT2 (0x34) */
|
||||
{ 0x35, 0x00 }, /* AK4671_E1_COEFFICIENT3 (0x35) */
|
||||
{ 0x36, 0x00 }, /* AK4671_E1_COEFFICIENT4 (0x36) */
|
||||
{ 0x37, 0x00 }, /* AK4671_E1_COEFFICIENT5 (0x37) */
|
||||
{ 0x38, 0x00 }, /* AK4671_E2_COEFFICIENT0 (0x38) */
|
||||
{ 0x39, 0x00 }, /* AK4671_E2_COEFFICIENT1 (0x39) */
|
||||
{ 0x3a, 0x00 }, /* AK4671_E2_COEFFICIENT2 (0x3a) */
|
||||
{ 0x3b, 0x00 }, /* AK4671_E2_COEFFICIENT3 (0x3b) */
|
||||
{ 0x3c, 0x00 }, /* AK4671_E2_COEFFICIENT4 (0x3c) */
|
||||
{ 0x3d, 0x00 }, /* AK4671_E2_COEFFICIENT5 (0x3d) */
|
||||
{ 0x3e, 0x00 }, /* AK4671_E3_COEFFICIENT0 (0x3e) */
|
||||
{ 0x3f, 0x00 }, /* AK4671_E3_COEFFICIENT1 (0x3f) */
|
||||
{ 0x40, 0x00 }, /* AK4671_E3_COEFFICIENT2 (0x40) */
|
||||
{ 0x41, 0x00 }, /* AK4671_E3_COEFFICIENT3 (0x41) */
|
||||
{ 0x42, 0x00 }, /* AK4671_E3_COEFFICIENT4 (0x42) */
|
||||
{ 0x43, 0x00 }, /* AK4671_E3_COEFFICIENT5 (0x43) */
|
||||
{ 0x44, 0x00 }, /* AK4671_E4_COEFFICIENT0 (0x44) */
|
||||
{ 0x45, 0x00 }, /* AK4671_E4_COEFFICIENT1 (0x45) */
|
||||
{ 0x46, 0x00 }, /* AK4671_E4_COEFFICIENT2 (0x46) */
|
||||
{ 0x47, 0x00 }, /* AK4671_E4_COEFFICIENT3 (0x47) */
|
||||
{ 0x48, 0x00 }, /* AK4671_E4_COEFFICIENT4 (0x48) */
|
||||
{ 0x49, 0x00 }, /* AK4671_E4_COEFFICIENT5 (0x49) */
|
||||
{ 0x4a, 0x00 }, /* AK4671_E5_COEFFICIENT0 (0x4a) */
|
||||
{ 0x4b, 0x00 }, /* AK4671_E5_COEFFICIENT1 (0x4b) */
|
||||
{ 0x4c, 0x00 }, /* AK4671_E5_COEFFICIENT2 (0x4c) */
|
||||
{ 0x4d, 0x00 }, /* AK4671_E5_COEFFICIENT3 (0x4d) */
|
||||
{ 0x4e, 0x00 }, /* AK4671_E5_COEFFICIENT4 (0x4e) */
|
||||
{ 0x4f, 0x00 }, /* AK4671_E5_COEFFICIENT5 (0x4f) */
|
||||
{ 0x50, 0x88 }, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */
|
||||
{ 0x51, 0x88 }, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */
|
||||
{ 0x52, 0x08 }, /* AK4671_EQ_CONTRO_10KHZ (0x52) */
|
||||
{ 0x53, 0x00 }, /* AK4671_PCM_IF_CONTROL0 (0x53) */
|
||||
{ 0x54, 0x00 }, /* AK4671_PCM_IF_CONTROL1 (0x54) */
|
||||
{ 0x55, 0x00 }, /* AK4671_PCM_IF_CONTROL2 (0x55) */
|
||||
{ 0x56, 0x18 }, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */
|
||||
{ 0x57, 0x18 }, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */
|
||||
{ 0x58, 0x00 }, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */
|
||||
{ 0x59, 0x00 }, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */
|
||||
{ 0x5a, 0x00 }, /* AK4671_SAR_ADC_CONTROL (0x5a) */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -241,19 +237,17 @@ static const struct snd_kcontrol_new ak4671_rout3_mixer_controls[] = {
|
|||
/* Input MUXs */
|
||||
static const char *ak4671_lin_mux_texts[] =
|
||||
{"LIN1", "LIN2", "LIN3", "LIN4"};
|
||||
static const struct soc_enum ak4671_lin_mux_enum =
|
||||
SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 0,
|
||||
ARRAY_SIZE(ak4671_lin_mux_texts),
|
||||
ak4671_lin_mux_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(ak4671_lin_mux_enum,
|
||||
AK4671_MIC_SIGNAL_SELECT, 0,
|
||||
ak4671_lin_mux_texts);
|
||||
static const struct snd_kcontrol_new ak4671_lin_mux_control =
|
||||
SOC_DAPM_ENUM("Route", ak4671_lin_mux_enum);
|
||||
|
||||
static const char *ak4671_rin_mux_texts[] =
|
||||
{"RIN1", "RIN2", "RIN3", "RIN4"};
|
||||
static const struct soc_enum ak4671_rin_mux_enum =
|
||||
SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 2,
|
||||
ARRAY_SIZE(ak4671_rin_mux_texts),
|
||||
ak4671_rin_mux_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(ak4671_rin_mux_enum,
|
||||
AK4671_MIC_SIGNAL_SELECT, 2,
|
||||
ak4671_rin_mux_texts);
|
||||
static const struct snd_kcontrol_new ak4671_rin_mux_control =
|
||||
SOC_DAPM_ENUM("Route", ak4671_rin_mux_enum);
|
||||
|
||||
|
@ -619,18 +613,14 @@ static struct snd_soc_dai_driver ak4671_dai = {
|
|||
|
||||
static int ak4671_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type);
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
snd_soc_add_codec_controls(codec, ak4671_snd_controls,
|
||||
ARRAY_SIZE(ak4671_snd_controls));
|
||||
|
||||
ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return ret;
|
||||
|
@ -646,28 +636,36 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4671 = {
|
|||
.probe = ak4671_probe,
|
||||
.remove = ak4671_remove,
|
||||
.set_bias_level = ak4671_set_bias_level,
|
||||
.reg_cache_size = AK4671_CACHEREGNUM,
|
||||
.reg_word_size = sizeof(u8),
|
||||
.reg_cache_default = ak4671_reg,
|
||||
.controls = ak4671_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(ak4671_snd_controls),
|
||||
.dapm_widgets = ak4671_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets),
|
||||
.dapm_routes = ak4671_intercon,
|
||||
.num_dapm_routes = ARRAY_SIZE(ak4671_intercon),
|
||||
};
|
||||
|
||||
static const struct regmap_config ak4671_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
.max_register = AK4671_SAR_ADC_CONTROL,
|
||||
.reg_defaults = ak4671_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(ak4671_reg_defaults),
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int ak4671_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct ak4671_priv *ak4671;
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
ak4671 = devm_kzalloc(&client->dev, sizeof(struct ak4671_priv),
|
||||
GFP_KERNEL);
|
||||
if (ak4671 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, ak4671);
|
||||
ak4671->control_type = SND_SOC_I2C;
|
||||
regmap = devm_regmap_init_i2c(client, &ak4671_regmap);
|
||||
if (IS_ERR(regmap)) {
|
||||
ret = PTR_ERR(regmap);
|
||||
dev_err(&client->dev, "Failed to create regmap: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_codec(&client->dev,
|
||||
&soc_codec_dev_ak4671, &ak4671_dai, 1);
|
||||
|
|
|
@ -105,8 +105,6 @@
|
|||
#define AK4671_DIGITAL_MIXING_CONTROL2 0x59
|
||||
#define AK4671_SAR_ADC_CONTROL 0x5a
|
||||
|
||||
#define AK4671_CACHEREGNUM (AK4671_SAR_ADC_CONTROL + 1)
|
||||
|
||||
/* Bitfield Definitions */
|
||||
|
||||
/* AK4671_AD_DA_POWER_MANAGEMENT (0x00) Fields */
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
@ -38,26 +39,13 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)");
|
|||
|
||||
/* codec private data */
|
||||
struct alc5623_priv {
|
||||
enum snd_soc_control_type control_type;
|
||||
struct regmap *regmap;
|
||||
u8 id;
|
||||
unsigned int sysclk;
|
||||
u16 reg_cache[ALC5623_VENDOR_ID2+2];
|
||||
unsigned int add_ctrl;
|
||||
unsigned int jack_det_ctrl;
|
||||
};
|
||||
|
||||
static void alc5623_fill_cache(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i, step = codec->driver->reg_cache_step;
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
/* not really efficient ... */
|
||||
codec->cache_bypass = 1;
|
||||
for (i = 0 ; i < codec->driver->reg_cache_size ; i += step)
|
||||
cache[i] = snd_soc_read(codec, i);
|
||||
codec->cache_bypass = 0;
|
||||
}
|
||||
|
||||
static inline int alc5623_reset(struct snd_soc_codec *codec)
|
||||
{
|
||||
return snd_soc_write(codec, ALC5623_RESET, 0);
|
||||
|
@ -228,32 +216,37 @@ static const char *alc5623_aux_out_input_sel[] = {
|
|||
"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
|
||||
|
||||
/* auxout output mux */
|
||||
static const struct soc_enum alc5623_aux_out_input_enum =
|
||||
SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 6, 4, alc5623_aux_out_input_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(alc5623_aux_out_input_enum,
|
||||
ALC5623_OUTPUT_MIXER_CTRL, 6,
|
||||
alc5623_aux_out_input_sel);
|
||||
static const struct snd_kcontrol_new alc5623_auxout_mux_controls =
|
||||
SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum);
|
||||
|
||||
/* speaker output mux */
|
||||
static const struct soc_enum alc5623_spkout_input_enum =
|
||||
SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 10, 4, alc5623_spkout_input_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(alc5623_spkout_input_enum,
|
||||
ALC5623_OUTPUT_MIXER_CTRL, 10,
|
||||
alc5623_spkout_input_sel);
|
||||
static const struct snd_kcontrol_new alc5623_spkout_mux_controls =
|
||||
SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum);
|
||||
|
||||
/* headphone left output mux */
|
||||
static const struct soc_enum alc5623_hpl_out_input_enum =
|
||||
SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 9, 2, alc5623_hpl_out_input_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(alc5623_hpl_out_input_enum,
|
||||
ALC5623_OUTPUT_MIXER_CTRL, 9,
|
||||
alc5623_hpl_out_input_sel);
|
||||
static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls =
|
||||
SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum);
|
||||
|
||||
/* headphone right output mux */
|
||||
static const struct soc_enum alc5623_hpr_out_input_enum =
|
||||
SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 8, 2, alc5623_hpr_out_input_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(alc5623_hpr_out_input_enum,
|
||||
ALC5623_OUTPUT_MIXER_CTRL, 8,
|
||||
alc5623_hpr_out_input_sel);
|
||||
static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls =
|
||||
SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum);
|
||||
|
||||
/* speaker output N select */
|
||||
static const struct soc_enum alc5623_spk_n_sour_enum =
|
||||
SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 14, 4, alc5623_spk_n_sour_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(alc5623_spk_n_sour_enum,
|
||||
ALC5623_OUTPUT_MIXER_CTRL, 14,
|
||||
alc5623_spk_n_sour_sel);
|
||||
static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls =
|
||||
SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum);
|
||||
|
||||
|
@ -338,8 +331,9 @@ SND_SOC_DAPM_VMID("Vmid"),
|
|||
};
|
||||
|
||||
static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"};
|
||||
static const struct soc_enum alc5623_amp_enum =
|
||||
SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 13, 2, alc5623_amp_names);
|
||||
static SOC_ENUM_SINGLE_DECL(alc5623_amp_enum,
|
||||
ALC5623_OUTPUT_MIXER_CTRL, 13,
|
||||
alc5623_amp_names);
|
||||
static const struct snd_kcontrol_new alc5623_amp_mux_controls =
|
||||
SOC_DAPM_ENUM("Route", alc5623_amp_enum);
|
||||
|
||||
|
@ -869,18 +863,28 @@ static struct snd_soc_dai_driver alc5623_dai = {
|
|||
|
||||
static int alc5623_suspend(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
regcache_cache_only(alc5623->regmap, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alc5623_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i, step = codec->driver->reg_cache_step;
|
||||
u16 *cache = codec->reg_cache;
|
||||
struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
/* Sync reg_cache with the hardware */
|
||||
for (i = 2 ; i < codec->driver->reg_cache_size ; i += step)
|
||||
snd_soc_write(codec, i, cache[i]);
|
||||
regcache_cache_only(alc5623->regmap, false);
|
||||
ret = regcache_sync(alc5623->regmap);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to sync register cache: %d\n",
|
||||
ret);
|
||||
regcache_cache_only(alc5623->regmap, true);
|
||||
return ret;
|
||||
}
|
||||
|
||||
alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
|
@ -900,14 +904,14 @@ static int alc5623_probe(struct snd_soc_codec *codec)
|
|||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5623->control_type);
|
||||
codec->control_data = alc5623->regmap;
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
alc5623_reset(codec);
|
||||
alc5623_fill_cache(codec);
|
||||
|
||||
/* power on device */
|
||||
alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
@ -980,9 +984,15 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
|
|||
.suspend = alc5623_suspend,
|
||||
.resume = alc5623_resume,
|
||||
.set_bias_level = alc5623_set_bias_level,
|
||||
.reg_cache_size = ALC5623_VENDOR_ID2+2,
|
||||
.reg_word_size = sizeof(u16),
|
||||
.reg_cache_step = 2,
|
||||
};
|
||||
|
||||
static const struct regmap_config alc5623_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 16,
|
||||
.reg_stride = 2,
|
||||
|
||||
.max_register = ALC5623_VENDOR_ID2,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -996,19 +1006,32 @@ static int alc5623_i2c_probe(struct i2c_client *client,
|
|||
{
|
||||
struct alc5623_platform_data *pdata;
|
||||
struct alc5623_priv *alc5623;
|
||||
int ret, vid1, vid2;
|
||||
unsigned int vid1, vid2;
|
||||
int ret;
|
||||
|
||||
vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1);
|
||||
if (vid1 < 0) {
|
||||
dev_err(&client->dev, "failed to read I2C\n");
|
||||
return -EIO;
|
||||
alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),
|
||||
GFP_KERNEL);
|
||||
if (alc5623 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
alc5623->regmap = devm_regmap_init_i2c(client, &alc5623_regmap);
|
||||
if (IS_ERR(alc5623->regmap)) {
|
||||
ret = PTR_ERR(alc5623->regmap);
|
||||
dev_err(&client->dev, "Failed to initialise I/O: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID1, &vid1);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "failed to read vendor ID1: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8);
|
||||
|
||||
vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2);
|
||||
if (vid2 < 0) {
|
||||
dev_err(&client->dev, "failed to read I2C\n");
|
||||
return -EIO;
|
||||
ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) {
|
||||
|
@ -1021,11 +1044,6 @@ static int alc5623_i2c_probe(struct i2c_client *client,
|
|||
|
||||
dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2);
|
||||
|
||||
alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),
|
||||
GFP_KERNEL);
|
||||
if (alc5623 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
pdata = client->dev.platform_data;
|
||||
if (pdata) {
|
||||
alc5623->add_ctrl = pdata->add_ctrl;
|
||||
|
@ -1048,7 +1066,6 @@ static int alc5623_i2c_probe(struct i2c_client *client,
|
|||
}
|
||||
|
||||
i2c_set_clientdata(client, alc5623);
|
||||
alc5623->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&client->dev,
|
||||
&soc_codec_device_alc5623, &alc5623_dai, 1);
|
||||
|
|
|
@ -293,51 +293,59 @@ static const char * const alc5632_i2s_out_sel[] = {
|
|||
"ADC LR", "Voice Stereo Digital"};
|
||||
|
||||
/* auxout output mux */
|
||||
static const struct soc_enum alc5632_aux_out_input_enum =
|
||||
SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 6, 4, alc5632_aux_out_input_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(alc5632_aux_out_input_enum,
|
||||
ALC5632_OUTPUT_MIXER_CTRL, 6,
|
||||
alc5632_aux_out_input_sel);
|
||||
static const struct snd_kcontrol_new alc5632_auxout_mux_controls =
|
||||
SOC_DAPM_ENUM("AuxOut Mux", alc5632_aux_out_input_enum);
|
||||
|
||||
/* speaker output mux */
|
||||
static const struct soc_enum alc5632_spkout_input_enum =
|
||||
SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 10, 4, alc5632_spkout_input_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(alc5632_spkout_input_enum,
|
||||
ALC5632_OUTPUT_MIXER_CTRL, 10,
|
||||
alc5632_spkout_input_sel);
|
||||
static const struct snd_kcontrol_new alc5632_spkout_mux_controls =
|
||||
SOC_DAPM_ENUM("SpeakerOut Mux", alc5632_spkout_input_enum);
|
||||
|
||||
/* headphone left output mux */
|
||||
static const struct soc_enum alc5632_hpl_out_input_enum =
|
||||
SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 9, 2, alc5632_hpl_out_input_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(alc5632_hpl_out_input_enum,
|
||||
ALC5632_OUTPUT_MIXER_CTRL, 9,
|
||||
alc5632_hpl_out_input_sel);
|
||||
static const struct snd_kcontrol_new alc5632_hpl_out_mux_controls =
|
||||
SOC_DAPM_ENUM("Left Headphone Mux", alc5632_hpl_out_input_enum);
|
||||
|
||||
/* headphone right output mux */
|
||||
static const struct soc_enum alc5632_hpr_out_input_enum =
|
||||
SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 8, 2, alc5632_hpr_out_input_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(alc5632_hpr_out_input_enum,
|
||||
ALC5632_OUTPUT_MIXER_CTRL, 8,
|
||||
alc5632_hpr_out_input_sel);
|
||||
static const struct snd_kcontrol_new alc5632_hpr_out_mux_controls =
|
||||
SOC_DAPM_ENUM("Right Headphone Mux", alc5632_hpr_out_input_enum);
|
||||
|
||||
/* speaker output N select */
|
||||
static const struct soc_enum alc5632_spk_n_sour_enum =
|
||||
SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 14, 4, alc5632_spk_n_sour_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(alc5632_spk_n_sour_enum,
|
||||
ALC5632_OUTPUT_MIXER_CTRL, 14,
|
||||
alc5632_spk_n_sour_sel);
|
||||
static const struct snd_kcontrol_new alc5632_spkoutn_mux_controls =
|
||||
SOC_DAPM_ENUM("SpeakerOut N Mux", alc5632_spk_n_sour_enum);
|
||||
|
||||
/* speaker amplifier */
|
||||
static const char *alc5632_amp_names[] = {"AB Amp", "D Amp"};
|
||||
static const struct soc_enum alc5632_amp_enum =
|
||||
SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 13, 2, alc5632_amp_names);
|
||||
static SOC_ENUM_SINGLE_DECL(alc5632_amp_enum,
|
||||
ALC5632_OUTPUT_MIXER_CTRL, 13,
|
||||
alc5632_amp_names);
|
||||
static const struct snd_kcontrol_new alc5632_amp_mux_controls =
|
||||
SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum);
|
||||
|
||||
/* ADC output select */
|
||||
static const struct soc_enum alc5632_adcr_func_enum =
|
||||
SOC_ENUM_SINGLE(ALC5632_DAC_FUNC_SELECT, 5, 2, alc5632_adcr_func_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(alc5632_adcr_func_enum,
|
||||
ALC5632_DAC_FUNC_SELECT, 5,
|
||||
alc5632_adcr_func_sel);
|
||||
static const struct snd_kcontrol_new alc5632_adcr_func_controls =
|
||||
SOC_DAPM_ENUM("ADCR Mux", alc5632_adcr_func_enum);
|
||||
|
||||
/* I2S out select */
|
||||
static const struct soc_enum alc5632_i2s_out_enum =
|
||||
SOC_ENUM_SINGLE(ALC5632_I2S_OUT_CTL, 5, 2, alc5632_i2s_out_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(alc5632_i2s_out_enum,
|
||||
ALC5632_I2S_OUT_CTL, 5,
|
||||
alc5632_i2s_out_sel);
|
||||
static const struct snd_kcontrol_new alc5632_i2s_out_controls =
|
||||
SOC_DAPM_ENUM("I2SOut Mux", alc5632_i2s_out_enum);
|
||||
|
||||
|
|
|
@ -53,6 +53,14 @@
|
|||
#define ARIZONA_AIF_RX_ENABLES 0x1A
|
||||
#define ARIZONA_AIF_FORCE_WRITE 0x1B
|
||||
|
||||
#define ARIZONA_FLL_VCO_CORNER 141900000
|
||||
#define ARIZONA_FLL_MAX_FREF 13500000
|
||||
#define ARIZONA_FLL_MIN_FVCO 90000000
|
||||
#define ARIZONA_FLL_MAX_FRATIO 16
|
||||
#define ARIZONA_FLL_MAX_REFDIV 8
|
||||
#define ARIZONA_FLL_MIN_OUTDIV 2
|
||||
#define ARIZONA_FLL_MAX_OUTDIV 7
|
||||
|
||||
#define arizona_fll_err(_fll, fmt, ...) \
|
||||
dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
|
||||
#define arizona_fll_warn(_fll, fmt, ...) \
|
||||
|
@ -542,67 +550,76 @@ static const char *arizona_vol_ramp_text[] = {
|
|||
"15ms/6dB", "30ms/6dB",
|
||||
};
|
||||
|
||||
const struct soc_enum arizona_in_vd_ramp =
|
||||
SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
|
||||
ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
|
||||
SOC_ENUM_SINGLE_DECL(arizona_in_vd_ramp,
|
||||
ARIZONA_INPUT_VOLUME_RAMP,
|
||||
ARIZONA_IN_VD_RAMP_SHIFT,
|
||||
arizona_vol_ramp_text);
|
||||
EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
|
||||
|
||||
const struct soc_enum arizona_in_vi_ramp =
|
||||
SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
|
||||
ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
|
||||
SOC_ENUM_SINGLE_DECL(arizona_in_vi_ramp,
|
||||
ARIZONA_INPUT_VOLUME_RAMP,
|
||||
ARIZONA_IN_VI_RAMP_SHIFT,
|
||||
arizona_vol_ramp_text);
|
||||
EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
|
||||
|
||||
const struct soc_enum arizona_out_vd_ramp =
|
||||
SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
|
||||
ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
|
||||
SOC_ENUM_SINGLE_DECL(arizona_out_vd_ramp,
|
||||
ARIZONA_OUTPUT_VOLUME_RAMP,
|
||||
ARIZONA_OUT_VD_RAMP_SHIFT,
|
||||
arizona_vol_ramp_text);
|
||||
EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
|
||||
|
||||
const struct soc_enum arizona_out_vi_ramp =
|
||||
SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
|
||||
ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
|
||||
SOC_ENUM_SINGLE_DECL(arizona_out_vi_ramp,
|
||||
ARIZONA_OUTPUT_VOLUME_RAMP,
|
||||
ARIZONA_OUT_VI_RAMP_SHIFT,
|
||||
arizona_vol_ramp_text);
|
||||
EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
|
||||
|
||||
static const char *arizona_lhpf_mode_text[] = {
|
||||
"Low-pass", "High-pass"
|
||||
};
|
||||
|
||||
const struct soc_enum arizona_lhpf1_mode =
|
||||
SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2,
|
||||
arizona_lhpf_mode_text);
|
||||
SOC_ENUM_SINGLE_DECL(arizona_lhpf1_mode,
|
||||
ARIZONA_HPLPF1_1,
|
||||
ARIZONA_LHPF1_MODE_SHIFT,
|
||||
arizona_lhpf_mode_text);
|
||||
EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
|
||||
|
||||
const struct soc_enum arizona_lhpf2_mode =
|
||||
SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2,
|
||||
arizona_lhpf_mode_text);
|
||||
SOC_ENUM_SINGLE_DECL(arizona_lhpf2_mode,
|
||||
ARIZONA_HPLPF2_1,
|
||||
ARIZONA_LHPF2_MODE_SHIFT,
|
||||
arizona_lhpf_mode_text);
|
||||
EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
|
||||
|
||||
const struct soc_enum arizona_lhpf3_mode =
|
||||
SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2,
|
||||
arizona_lhpf_mode_text);
|
||||
SOC_ENUM_SINGLE_DECL(arizona_lhpf3_mode,
|
||||
ARIZONA_HPLPF3_1,
|
||||
ARIZONA_LHPF3_MODE_SHIFT,
|
||||
arizona_lhpf_mode_text);
|
||||
EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
|
||||
|
||||
const struct soc_enum arizona_lhpf4_mode =
|
||||
SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2,
|
||||
arizona_lhpf_mode_text);
|
||||
SOC_ENUM_SINGLE_DECL(arizona_lhpf4_mode,
|
||||
ARIZONA_HPLPF4_1,
|
||||
ARIZONA_LHPF4_MODE_SHIFT,
|
||||
arizona_lhpf_mode_text);
|
||||
EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
|
||||
|
||||
static const char *arizona_ng_hold_text[] = {
|
||||
"30ms", "120ms", "250ms", "500ms",
|
||||
};
|
||||
|
||||
const struct soc_enum arizona_ng_hold =
|
||||
SOC_ENUM_SINGLE(ARIZONA_NOISE_GATE_CONTROL, ARIZONA_NGATE_HOLD_SHIFT,
|
||||
4, arizona_ng_hold_text);
|
||||
SOC_ENUM_SINGLE_DECL(arizona_ng_hold,
|
||||
ARIZONA_NOISE_GATE_CONTROL,
|
||||
ARIZONA_NGATE_HOLD_SHIFT,
|
||||
arizona_ng_hold_text);
|
||||
EXPORT_SYMBOL_GPL(arizona_ng_hold);
|
||||
|
||||
static const char * const arizona_in_hpf_cut_text[] = {
|
||||
"2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz"
|
||||
};
|
||||
|
||||
const struct soc_enum arizona_in_hpf_cut_enum =
|
||||
SOC_ENUM_SINGLE(ARIZONA_HPF_CONTROL, ARIZONA_IN_HPF_CUT_SHIFT,
|
||||
ARRAY_SIZE(arizona_in_hpf_cut_text),
|
||||
arizona_in_hpf_cut_text);
|
||||
SOC_ENUM_SINGLE_DECL(arizona_in_hpf_cut_enum,
|
||||
ARIZONA_HPF_CONTROL,
|
||||
ARIZONA_IN_HPF_CUT_SHIFT,
|
||||
arizona_in_hpf_cut_text);
|
||||
EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum);
|
||||
|
||||
static const char * const arizona_in_dmic_osr_text[] = {
|
||||
|
@ -1377,74 +1394,147 @@ struct arizona_fll_cfg {
|
|||
int gain;
|
||||
};
|
||||
|
||||
static int arizona_validate_fll(struct arizona_fll *fll,
|
||||
unsigned int Fref,
|
||||
unsigned int Fout)
|
||||
{
|
||||
unsigned int Fvco_min;
|
||||
|
||||
if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
|
||||
arizona_fll_err(fll,
|
||||
"Can't scale %dMHz in to <=13.5MHz\n",
|
||||
Fref);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
Fvco_min = ARIZONA_FLL_MIN_FVCO * fll->vco_mult;
|
||||
if (Fout * ARIZONA_FLL_MAX_OUTDIV < Fvco_min) {
|
||||
arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
|
||||
Fout);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arizona_find_fratio(unsigned int Fref, int *fratio)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Find an appropriate FLL_FRATIO */
|
||||
for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
|
||||
if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
|
||||
if (fratio)
|
||||
*fratio = fll_fratios[i].fratio;
|
||||
return fll_fratios[i].ratio;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int arizona_calc_fratio(struct arizona_fll *fll,
|
||||
struct arizona_fll_cfg *cfg,
|
||||
unsigned int target,
|
||||
unsigned int Fref, bool sync)
|
||||
{
|
||||
int init_ratio, ratio;
|
||||
int refdiv, div;
|
||||
|
||||
/* Fref must be <=13.5MHz, find initial refdiv */
|
||||
div = 1;
|
||||
cfg->refdiv = 0;
|
||||
while (Fref > ARIZONA_FLL_MAX_FREF) {
|
||||
div *= 2;
|
||||
Fref /= 2;
|
||||
cfg->refdiv++;
|
||||
|
||||
if (div > ARIZONA_FLL_MAX_REFDIV)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Find an appropriate FLL_FRATIO */
|
||||
init_ratio = arizona_find_fratio(Fref, &cfg->fratio);
|
||||
if (init_ratio < 0) {
|
||||
arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
|
||||
Fref);
|
||||
return init_ratio;
|
||||
}
|
||||
|
||||
switch (fll->arizona->type) {
|
||||
case WM5110:
|
||||
if (fll->arizona->rev < 3 || sync)
|
||||
return init_ratio;
|
||||
break;
|
||||
default:
|
||||
return init_ratio;
|
||||
}
|
||||
|
||||
cfg->fratio = init_ratio - 1;
|
||||
|
||||
/* Adjust FRATIO/refdiv to avoid integer mode if possible */
|
||||
refdiv = cfg->refdiv;
|
||||
|
||||
while (div <= ARIZONA_FLL_MAX_REFDIV) {
|
||||
for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO;
|
||||
ratio++) {
|
||||
if (target % (ratio * Fref)) {
|
||||
cfg->refdiv = refdiv;
|
||||
cfg->fratio = ratio - 1;
|
||||
return ratio;
|
||||
}
|
||||
}
|
||||
|
||||
for (ratio = init_ratio - 1; ratio >= 0; ratio--) {
|
||||
if (ARIZONA_FLL_VCO_CORNER / (fll->vco_mult * ratio) <
|
||||
Fref)
|
||||
break;
|
||||
|
||||
if (target % (ratio * Fref)) {
|
||||
cfg->refdiv = refdiv;
|
||||
cfg->fratio = ratio - 1;
|
||||
return ratio;
|
||||
}
|
||||
}
|
||||
|
||||
div *= 2;
|
||||
Fref /= 2;
|
||||
refdiv++;
|
||||
init_ratio = arizona_find_fratio(Fref, NULL);
|
||||
}
|
||||
|
||||
arizona_fll_warn(fll, "Falling back to integer mode operation\n");
|
||||
return cfg->fratio + 1;
|
||||
}
|
||||
|
||||
static int arizona_calc_fll(struct arizona_fll *fll,
|
||||
struct arizona_fll_cfg *cfg,
|
||||
unsigned int Fref,
|
||||
unsigned int Fout)
|
||||
unsigned int Fref, bool sync)
|
||||
{
|
||||
unsigned int target, div, gcd_fll;
|
||||
int i, ratio;
|
||||
|
||||
arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
|
||||
|
||||
/* Fref must be <=13.5MHz */
|
||||
div = 1;
|
||||
cfg->refdiv = 0;
|
||||
while ((Fref / div) > 13500000) {
|
||||
div *= 2;
|
||||
cfg->refdiv++;
|
||||
|
||||
if (div > 8) {
|
||||
arizona_fll_err(fll,
|
||||
"Can't scale %dMHz in to <=13.5MHz\n",
|
||||
Fref);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply the division for our remaining calculations */
|
||||
Fref /= div;
|
||||
arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout);
|
||||
|
||||
/* Fvco should be over the targt; don't check the upper bound */
|
||||
div = 1;
|
||||
while (Fout * div < 90000000 * fll->vco_mult) {
|
||||
div = ARIZONA_FLL_MIN_OUTDIV;
|
||||
while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) {
|
||||
div++;
|
||||
if (div > 7) {
|
||||
arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
|
||||
Fout);
|
||||
if (div > ARIZONA_FLL_MAX_OUTDIV)
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
target = Fout * div / fll->vco_mult;
|
||||
target = fll->fout * div / fll->vco_mult;
|
||||
cfg->outdiv = div;
|
||||
|
||||
arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
|
||||
|
||||
/* Find an appropraite FLL_FRATIO and factor it out of the target */
|
||||
for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
|
||||
if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
|
||||
cfg->fratio = fll_fratios[i].fratio;
|
||||
ratio = fll_fratios[i].ratio;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == ARRAY_SIZE(fll_fratios)) {
|
||||
arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
|
||||
Fref);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Find an appropriate FLL_FRATIO and refdiv */
|
||||
ratio = arizona_calc_fratio(fll, cfg, target, Fref, sync);
|
||||
if (ratio < 0)
|
||||
return ratio;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
|
||||
if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
|
||||
cfg->gain = fll_gains[i].gain;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == ARRAY_SIZE(fll_gains)) {
|
||||
arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
|
||||
Fref);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Apply the division for our remaining calculations */
|
||||
Fref = Fref / (1 << cfg->refdiv);
|
||||
|
||||
cfg->n = target / (ratio * Fref);
|
||||
|
||||
|
@ -1469,6 +1559,18 @@ static int arizona_calc_fll(struct arizona_fll *fll,
|
|||
cfg->lambda >>= 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
|
||||
if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
|
||||
cfg->gain = fll_gains[i].gain;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == ARRAY_SIZE(fll_gains)) {
|
||||
arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
|
||||
Fref);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
|
||||
cfg->n, cfg->theta, cfg->lambda);
|
||||
arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
|
||||
|
@ -1496,14 +1598,18 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
|
|||
cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
|
||||
source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
|
||||
|
||||
if (sync)
|
||||
regmap_update_bits_async(arizona->regmap, base + 0x7,
|
||||
ARIZONA_FLL1_GAIN_MASK,
|
||||
cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
|
||||
else
|
||||
regmap_update_bits_async(arizona->regmap, base + 0x9,
|
||||
ARIZONA_FLL1_GAIN_MASK,
|
||||
cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
|
||||
if (sync) {
|
||||
regmap_update_bits(arizona->regmap, base + 0x7,
|
||||
ARIZONA_FLL1_GAIN_MASK,
|
||||
cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
|
||||
} else {
|
||||
regmap_update_bits(arizona->regmap, base + 0x5,
|
||||
ARIZONA_FLL1_OUTDIV_MASK,
|
||||
cfg->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
|
||||
regmap_update_bits(arizona->regmap, base + 0x9,
|
||||
ARIZONA_FLL1_GAIN_MASK,
|
||||
cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
|
||||
}
|
||||
|
||||
regmap_update_bits_async(arizona->regmap, base + 2,
|
||||
ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
|
||||
|
@ -1526,13 +1632,12 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll)
|
|||
return reg & ARIZONA_FLL1_ENA;
|
||||
}
|
||||
|
||||
static void arizona_enable_fll(struct arizona_fll *fll,
|
||||
struct arizona_fll_cfg *ref,
|
||||
struct arizona_fll_cfg *sync)
|
||||
static void arizona_enable_fll(struct arizona_fll *fll)
|
||||
{
|
||||
struct arizona *arizona = fll->arizona;
|
||||
int ret;
|
||||
bool use_sync = false;
|
||||
struct arizona_fll_cfg cfg;
|
||||
|
||||
/*
|
||||
* If we have both REFCLK and SYNCCLK then enable both,
|
||||
|
@ -1540,23 +1645,21 @@ static void arizona_enable_fll(struct arizona_fll *fll,
|
|||
*/
|
||||
if (fll->ref_src >= 0 && fll->ref_freq &&
|
||||
fll->ref_src != fll->sync_src) {
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 5,
|
||||
ARIZONA_FLL1_OUTDIV_MASK,
|
||||
ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
|
||||
arizona_calc_fll(fll, &cfg, fll->ref_freq, false);
|
||||
|
||||
arizona_apply_fll(arizona, fll->base, ref, fll->ref_src,
|
||||
arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src,
|
||||
false);
|
||||
if (fll->sync_src >= 0) {
|
||||
arizona_apply_fll(arizona, fll->base + 0x10, sync,
|
||||
arizona_calc_fll(fll, &cfg, fll->sync_freq, true);
|
||||
|
||||
arizona_apply_fll(arizona, fll->base + 0x10, &cfg,
|
||||
fll->sync_src, true);
|
||||
use_sync = true;
|
||||
}
|
||||
} else if (fll->sync_src >= 0) {
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 5,
|
||||
ARIZONA_FLL1_OUTDIV_MASK,
|
||||
sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
|
||||
arizona_calc_fll(fll, &cfg, fll->sync_freq, false);
|
||||
|
||||
arizona_apply_fll(arizona, fll->base, sync,
|
||||
arizona_apply_fll(arizona, fll->base, &cfg,
|
||||
fll->sync_src, false);
|
||||
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
|
||||
|
@ -1618,32 +1721,22 @@ static void arizona_disable_fll(struct arizona_fll *fll)
|
|||
int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
|
||||
unsigned int Fref, unsigned int Fout)
|
||||
{
|
||||
struct arizona_fll_cfg ref, sync;
|
||||
int ret;
|
||||
|
||||
if (fll->ref_src == source && fll->ref_freq == Fref)
|
||||
return 0;
|
||||
|
||||
if (fll->fout) {
|
||||
if (Fref > 0) {
|
||||
ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (fll->sync_src >= 0) {
|
||||
ret = arizona_calc_fll(fll, &sync, fll->sync_freq,
|
||||
fll->fout);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
if (fll->fout && Fref > 0) {
|
||||
ret = arizona_validate_fll(fll, Fref, fll->fout);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
fll->ref_src = source;
|
||||
fll->ref_freq = Fref;
|
||||
|
||||
if (fll->fout && Fref > 0) {
|
||||
arizona_enable_fll(fll, &ref, &sync);
|
||||
arizona_enable_fll(fll);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1653,7 +1746,6 @@ EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
|
|||
int arizona_set_fll(struct arizona_fll *fll, int source,
|
||||
unsigned int Fref, unsigned int Fout)
|
||||
{
|
||||
struct arizona_fll_cfg ref, sync;
|
||||
int ret;
|
||||
|
||||
if (fll->sync_src == source &&
|
||||
|
@ -1662,13 +1754,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
|
|||
|
||||
if (Fout) {
|
||||
if (fll->ref_src >= 0) {
|
||||
ret = arizona_calc_fll(fll, &ref, fll->ref_freq,
|
||||
Fout);
|
||||
ret = arizona_validate_fll(fll, fll->ref_freq, Fout);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = arizona_calc_fll(fll, &sync, Fref, Fout);
|
||||
ret = arizona_validate_fll(fll, Fref, Fout);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
@ -1678,7 +1769,7 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
|
|||
fll->fout = Fout;
|
||||
|
||||
if (Fout) {
|
||||
arizona_enable_fll(fll, &ref, &sync);
|
||||
arizona_enable_fll(fll);
|
||||
} else {
|
||||
arizona_disable_fll(fll);
|
||||
}
|
||||
|
|
|
@ -159,7 +159,6 @@ static bool cs4271_volatile_reg(struct device *dev, unsigned int reg)
|
|||
}
|
||||
|
||||
struct cs4271_private {
|
||||
/* SND_SOC_I2C or SND_SOC_SPI */
|
||||
unsigned int mclk;
|
||||
bool master;
|
||||
bool deemph;
|
||||
|
@ -540,14 +539,10 @@ static int cs4271_probe(struct snd_soc_codec *codec)
|
|||
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
|
||||
struct cs4271_platform_data *cs4271plat = codec->dev->platform_data;
|
||||
int ret;
|
||||
int gpio_nreset = -EINVAL;
|
||||
bool amutec_eq_bmutec = false;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
if (of_match_device(cs4271_dt_ids, codec->dev)) {
|
||||
gpio_nreset = of_get_named_gpio(codec->dev->of_node,
|
||||
"reset-gpio", 0);
|
||||
|
||||
if (of_get_property(codec->dev->of_node,
|
||||
"cirrus,amutec-eq-bmutec", NULL))
|
||||
amutec_eq_bmutec = true;
|
||||
|
@ -559,27 +554,19 @@ static int cs4271_probe(struct snd_soc_codec *codec)
|
|||
#endif
|
||||
|
||||
if (cs4271plat) {
|
||||
if (gpio_is_valid(cs4271plat->gpio_nreset))
|
||||
gpio_nreset = cs4271plat->gpio_nreset;
|
||||
|
||||
amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec;
|
||||
cs4271->enable_soft_reset = cs4271plat->enable_soft_reset;
|
||||
}
|
||||
|
||||
if (gpio_nreset >= 0)
|
||||
if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset"))
|
||||
gpio_nreset = -EINVAL;
|
||||
if (gpio_nreset >= 0) {
|
||||
if (gpio_is_valid(cs4271->gpio_nreset)) {
|
||||
/* Reset codec */
|
||||
gpio_direction_output(gpio_nreset, 0);
|
||||
gpio_direction_output(cs4271->gpio_nreset, 0);
|
||||
udelay(1);
|
||||
gpio_set_value(gpio_nreset, 1);
|
||||
gpio_set_value(cs4271->gpio_nreset, 1);
|
||||
/* Give the codec time to wake up */
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
cs4271->gpio_nreset = gpio_nreset;
|
||||
|
||||
ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
|
||||
CS4271_MODE2_PDN | CS4271_MODE2_CPEN,
|
||||
CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
|
||||
|
@ -625,6 +612,36 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
|
|||
.num_dapm_routes = ARRAY_SIZE(cs4271_dapm_routes),
|
||||
};
|
||||
|
||||
static int cs4271_common_probe(struct device *dev,
|
||||
struct cs4271_private **c)
|
||||
{
|
||||
struct cs4271_platform_data *cs4271plat = dev->platform_data;
|
||||
struct cs4271_private *cs4271;
|
||||
|
||||
cs4271 = devm_kzalloc(dev, sizeof(*cs4271), GFP_KERNEL);
|
||||
if (!cs4271)
|
||||
return -ENOMEM;
|
||||
|
||||
if (of_match_device(cs4271_dt_ids, dev))
|
||||
cs4271->gpio_nreset =
|
||||
of_get_named_gpio(dev->of_node, "reset-gpio", 0);
|
||||
|
||||
if (cs4271plat)
|
||||
cs4271->gpio_nreset = cs4271plat->gpio_nreset;
|
||||
|
||||
if (gpio_is_valid(cs4271->gpio_nreset)) {
|
||||
int ret;
|
||||
|
||||
ret = devm_gpio_request(dev, cs4271->gpio_nreset,
|
||||
"CS4271 Reset");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
*c = cs4271;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
|
||||
static const struct regmap_config cs4271_spi_regmap = {
|
||||
|
@ -644,10 +661,11 @@ static const struct regmap_config cs4271_spi_regmap = {
|
|||
static int cs4271_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct cs4271_private *cs4271;
|
||||
int ret;
|
||||
|
||||
cs4271 = devm_kzalloc(&spi->dev, sizeof(*cs4271), GFP_KERNEL);
|
||||
if (!cs4271)
|
||||
return -ENOMEM;
|
||||
ret = cs4271_common_probe(&spi->dev, &cs4271);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
spi_set_drvdata(spi, cs4271);
|
||||
cs4271->regmap = devm_regmap_init_spi(spi, &cs4271_spi_regmap);
|
||||
|
@ -698,10 +716,11 @@ static int cs4271_i2c_probe(struct i2c_client *client,
|
|||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct cs4271_private *cs4271;
|
||||
int ret;
|
||||
|
||||
cs4271 = devm_kzalloc(&client->dev, sizeof(*cs4271), GFP_KERNEL);
|
||||
if (!cs4271)
|
||||
return -ENOMEM;
|
||||
ret = cs4271_common_probe(&client->dev, &cs4271);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
i2c_set_clientdata(client, cs4271);
|
||||
cs4271->regmap = devm_regmap_init_i2c(client, &cs4271_i2c_regmap);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <sound/pcm_params.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "cs42l51.h"
|
||||
|
||||
|
@ -40,7 +41,6 @@ enum master_slave_mode {
|
|||
};
|
||||
|
||||
struct cs42l51_private {
|
||||
enum snd_soc_control_type control_type;
|
||||
unsigned int mclk;
|
||||
unsigned int audio_mode; /* The mode (I2S or left-justified) */
|
||||
enum master_slave_mode func;
|
||||
|
@ -52,24 +52,6 @@ struct cs42l51_private {
|
|||
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
|
||||
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE)
|
||||
|
||||
static int cs42l51_fill_cache(struct snd_soc_codec *codec)
|
||||
{
|
||||
u8 *cache = codec->reg_cache + 1;
|
||||
struct i2c_client *i2c_client = to_i2c_client(codec->dev);
|
||||
s32 length;
|
||||
|
||||
length = i2c_smbus_read_i2c_block_data(i2c_client,
|
||||
CS42L51_FIRSTREG | 0x80, CS42L51_NUMREGS, cache);
|
||||
if (length != CS42L51_NUMREGS) {
|
||||
dev_err(&i2c_client->dev,
|
||||
"I2C read failure, addr=0x%x (ret=%d vs %d)\n",
|
||||
i2c_client->addr, length, CS42L51_NUMREGS);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
|
@ -135,8 +117,7 @@ static const char *chan_mix[] = {
|
|||
"R L",
|
||||
};
|
||||
|
||||
static const struct soc_enum cs42l51_chan_mix =
|
||||
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(chan_mix), chan_mix);
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(cs42l51_chan_mix, chan_mix);
|
||||
|
||||
static const struct snd_kcontrol_new cs42l51_snd_controls[] = {
|
||||
SOC_DOUBLE_R_SX_TLV("PCM Playback Volume",
|
||||
|
@ -192,22 +173,22 @@ static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w,
|
|||
|
||||
static const char *cs42l51_dac_names[] = {"Direct PCM",
|
||||
"DSP PCM", "ADC"};
|
||||
static const struct soc_enum cs42l51_dac_mux_enum =
|
||||
SOC_ENUM_SINGLE(CS42L51_DAC_CTL, 6, 3, cs42l51_dac_names);
|
||||
static SOC_ENUM_SINGLE_DECL(cs42l51_dac_mux_enum,
|
||||
CS42L51_DAC_CTL, 6, cs42l51_dac_names);
|
||||
static const struct snd_kcontrol_new cs42l51_dac_mux_controls =
|
||||
SOC_DAPM_ENUM("Route", cs42l51_dac_mux_enum);
|
||||
|
||||
static const char *cs42l51_adcl_names[] = {"AIN1 Left", "AIN2 Left",
|
||||
"MIC Left", "MIC+preamp Left"};
|
||||
static const struct soc_enum cs42l51_adcl_mux_enum =
|
||||
SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 4, 4, cs42l51_adcl_names);
|
||||
static SOC_ENUM_SINGLE_DECL(cs42l51_adcl_mux_enum,
|
||||
CS42L51_ADC_INPUT, 4, cs42l51_adcl_names);
|
||||
static const struct snd_kcontrol_new cs42l51_adcl_mux_controls =
|
||||
SOC_DAPM_ENUM("Route", cs42l51_adcl_mux_enum);
|
||||
|
||||
static const char *cs42l51_adcr_names[] = {"AIN1 Right", "AIN2 Right",
|
||||
"MIC Right", "MIC+preamp Right"};
|
||||
static const struct soc_enum cs42l51_adcr_mux_enum =
|
||||
SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 6, 4, cs42l51_adcr_names);
|
||||
static SOC_ENUM_SINGLE_DECL(cs42l51_adcr_mux_enum,
|
||||
CS42L51_ADC_INPUT, 6, cs42l51_adcr_names);
|
||||
static const struct snd_kcontrol_new cs42l51_adcr_mux_controls =
|
||||
SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum);
|
||||
|
||||
|
@ -505,16 +486,9 @@ static struct snd_soc_dai_driver cs42l51_dai = {
|
|||
|
||||
static int cs42l51_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret, reg;
|
||||
|
||||
ret = cs42l51_fill_cache(codec);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "failed to fill register cache\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type);
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
|
@ -538,8 +512,6 @@ static int cs42l51_probe(struct snd_soc_codec *codec)
|
|||
|
||||
static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
|
||||
.probe = cs42l51_probe,
|
||||
.reg_cache_size = CS42L51_NUMREGS + 1,
|
||||
.reg_word_size = sizeof(u8),
|
||||
|
||||
.controls = cs42l51_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(cs42l51_snd_controls),
|
||||
|
@ -549,38 +521,53 @@ static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
|
|||
.num_dapm_routes = ARRAY_SIZE(cs42l51_routes),
|
||||
};
|
||||
|
||||
static const struct regmap_config cs42l51_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
.max_register = CS42L51_CHARGE_FREQ,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct cs42l51_private *cs42l51;
|
||||
struct regmap *regmap;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
regmap = devm_regmap_init_i2c(i2c_client, &cs42l51_regmap);
|
||||
if (IS_ERR(regmap)) {
|
||||
ret = PTR_ERR(regmap);
|
||||
dev_err(&i2c_client->dev, "Failed to create regmap: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Verify that we have a CS42L51 */
|
||||
ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID);
|
||||
ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c_client->dev, "failed to read I2C\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
|
||||
(ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
|
||||
dev_err(&i2c_client->dev, "Invalid chip id\n");
|
||||
if ((val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
|
||||
(val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
|
||||
dev_err(&i2c_client->dev, "Invalid chip id: %x\n", val);
|
||||
ret = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
|
||||
dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
|
||||
ret & 7);
|
||||
val & 7);
|
||||
|
||||
cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private),
|
||||
GFP_KERNEL);
|
||||
if (!cs42l51) {
|
||||
dev_err(&i2c_client->dev, "could not allocate codec\n");
|
||||
if (!cs42l51)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(i2c_client, cs42l51);
|
||||
cs42l51->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c_client->dev,
|
||||
&soc_codec_device_cs42l51, &cs42l51_dai, 1);
|
||||
|
@ -600,10 +587,17 @@ static const struct i2c_device_id cs42l51_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cs42l51_id);
|
||||
|
||||
static const struct of_device_id cs42l51_of_match[] = {
|
||||
{ .compatible = "cirrus,cs42l51", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cs42l51_of_match);
|
||||
|
||||
static struct i2c_driver cs42l51_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "cs42l51-codec",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = cs42l51_of_match,
|
||||
},
|
||||
.id_table = cs42l51_id,
|
||||
.probe = cs42l51_i2c_probe,
|
||||
|
|
|
@ -210,13 +210,11 @@ static const char * const cs42l52_adca_text[] = {
|
|||
static const char * const cs42l52_adcb_text[] = {
|
||||
"Input1B", "Input2B", "Input3B", "Input4B", "PGA Input Right"};
|
||||
|
||||
static const struct soc_enum adca_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_ADC_PGA_A, 5,
|
||||
ARRAY_SIZE(cs42l52_adca_text), cs42l52_adca_text);
|
||||
static SOC_ENUM_SINGLE_DECL(adca_enum,
|
||||
CS42L52_ADC_PGA_A, 5, cs42l52_adca_text);
|
||||
|
||||
static const struct soc_enum adcb_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_ADC_PGA_B, 5,
|
||||
ARRAY_SIZE(cs42l52_adcb_text), cs42l52_adcb_text);
|
||||
static SOC_ENUM_SINGLE_DECL(adcb_enum,
|
||||
CS42L52_ADC_PGA_B, 5, cs42l52_adcb_text);
|
||||
|
||||
static const struct snd_kcontrol_new adca_mux =
|
||||
SOC_DAPM_ENUM("Left ADC Input Capture Mux", adca_enum);
|
||||
|
@ -229,26 +227,22 @@ static const char * const mic_bias_level_text[] = {
|
|||
"0.8 +VA", "0.83 +VA", "0.91 +VA"
|
||||
};
|
||||
|
||||
static const struct soc_enum mic_bias_level_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_IFACE_CTL2, 0,
|
||||
ARRAY_SIZE(mic_bias_level_text), mic_bias_level_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mic_bias_level_enum,
|
||||
CS42L52_IFACE_CTL2, 0, mic_bias_level_text);
|
||||
|
||||
static const char * const cs42l52_mic_text[] = { "MIC1", "MIC2" };
|
||||
|
||||
static const struct soc_enum mica_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_MICA_CTL, 5,
|
||||
ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mica_enum,
|
||||
CS42L52_MICA_CTL, 5, cs42l52_mic_text);
|
||||
|
||||
static const struct soc_enum micb_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_MICB_CTL, 5,
|
||||
ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text);
|
||||
static SOC_ENUM_SINGLE_DECL(micb_enum,
|
||||
CS42L52_MICB_CTL, 5, cs42l52_mic_text);
|
||||
|
||||
static const char * const digital_output_mux_text[] = {"ADC", "DSP"};
|
||||
|
||||
static const struct soc_enum digital_output_mux_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_ADC_MISC_CTL, 6,
|
||||
ARRAY_SIZE(digital_output_mux_text),
|
||||
digital_output_mux_text);
|
||||
static SOC_ENUM_SINGLE_DECL(digital_output_mux_enum,
|
||||
CS42L52_ADC_MISC_CTL, 6,
|
||||
digital_output_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new digital_output_mux =
|
||||
SOC_DAPM_ENUM("Digital Output Mux", digital_output_mux_enum);
|
||||
|
@ -258,18 +252,18 @@ static const char * const hp_gain_num_text[] = {
|
|||
"0.7099", "0.8399", "1.000", "1.1430"
|
||||
};
|
||||
|
||||
static const struct soc_enum hp_gain_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_PB_CTL1, 5,
|
||||
ARRAY_SIZE(hp_gain_num_text), hp_gain_num_text);
|
||||
static SOC_ENUM_SINGLE_DECL(hp_gain_enum,
|
||||
CS42L52_PB_CTL1, 5,
|
||||
hp_gain_num_text);
|
||||
|
||||
static const char * const beep_pitch_text[] = {
|
||||
"C4", "C5", "D5", "E5", "F5", "G5", "A5", "B5",
|
||||
"C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7"
|
||||
};
|
||||
|
||||
static const struct soc_enum beep_pitch_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_BEEP_FREQ, 4,
|
||||
ARRAY_SIZE(beep_pitch_text), beep_pitch_text);
|
||||
static SOC_ENUM_SINGLE_DECL(beep_pitch_enum,
|
||||
CS42L52_BEEP_FREQ, 4,
|
||||
beep_pitch_text);
|
||||
|
||||
static const char * const beep_ontime_text[] = {
|
||||
"86 ms", "430 ms", "780 ms", "1.20 s", "1.50 s",
|
||||
|
@ -277,66 +271,66 @@ static const char * const beep_ontime_text[] = {
|
|||
"3.50 s", "3.80 s", "4.20 s", "4.50 s", "4.80 s", "5.20 s"
|
||||
};
|
||||
|
||||
static const struct soc_enum beep_ontime_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_BEEP_FREQ, 0,
|
||||
ARRAY_SIZE(beep_ontime_text), beep_ontime_text);
|
||||
static SOC_ENUM_SINGLE_DECL(beep_ontime_enum,
|
||||
CS42L52_BEEP_FREQ, 0,
|
||||
beep_ontime_text);
|
||||
|
||||
static const char * const beep_offtime_text[] = {
|
||||
"1.23 s", "2.58 s", "3.90 s", "5.20 s",
|
||||
"6.60 s", "8.05 s", "9.35 s", "10.80 s"
|
||||
};
|
||||
|
||||
static const struct soc_enum beep_offtime_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_BEEP_VOL, 5,
|
||||
ARRAY_SIZE(beep_offtime_text), beep_offtime_text);
|
||||
static SOC_ENUM_SINGLE_DECL(beep_offtime_enum,
|
||||
CS42L52_BEEP_VOL, 5,
|
||||
beep_offtime_text);
|
||||
|
||||
static const char * const beep_config_text[] = {
|
||||
"Off", "Single", "Multiple", "Continuous"
|
||||
};
|
||||
|
||||
static const struct soc_enum beep_config_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 6,
|
||||
ARRAY_SIZE(beep_config_text), beep_config_text);
|
||||
static SOC_ENUM_SINGLE_DECL(beep_config_enum,
|
||||
CS42L52_BEEP_TONE_CTL, 6,
|
||||
beep_config_text);
|
||||
|
||||
static const char * const beep_bass_text[] = {
|
||||
"50 Hz", "100 Hz", "200 Hz", "250 Hz"
|
||||
};
|
||||
|
||||
static const struct soc_enum beep_bass_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 1,
|
||||
ARRAY_SIZE(beep_bass_text), beep_bass_text);
|
||||
static SOC_ENUM_SINGLE_DECL(beep_bass_enum,
|
||||
CS42L52_BEEP_TONE_CTL, 1,
|
||||
beep_bass_text);
|
||||
|
||||
static const char * const beep_treble_text[] = {
|
||||
"5 kHz", "7 kHz", "10 kHz", " 15 kHz"
|
||||
};
|
||||
|
||||
static const struct soc_enum beep_treble_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 3,
|
||||
ARRAY_SIZE(beep_treble_text), beep_treble_text);
|
||||
static SOC_ENUM_SINGLE_DECL(beep_treble_enum,
|
||||
CS42L52_BEEP_TONE_CTL, 3,
|
||||
beep_treble_text);
|
||||
|
||||
static const char * const ng_threshold_text[] = {
|
||||
"-34dB", "-37dB", "-40dB", "-43dB",
|
||||
"-46dB", "-52dB", "-58dB", "-64dB"
|
||||
};
|
||||
|
||||
static const struct soc_enum ng_threshold_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 2,
|
||||
ARRAY_SIZE(ng_threshold_text), ng_threshold_text);
|
||||
static SOC_ENUM_SINGLE_DECL(ng_threshold_enum,
|
||||
CS42L52_NOISE_GATE_CTL, 2,
|
||||
ng_threshold_text);
|
||||
|
||||
static const char * const cs42l52_ng_delay_text[] = {
|
||||
"50ms", "100ms", "150ms", "200ms"};
|
||||
|
||||
static const struct soc_enum ng_delay_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 0,
|
||||
ARRAY_SIZE(cs42l52_ng_delay_text), cs42l52_ng_delay_text);
|
||||
static SOC_ENUM_SINGLE_DECL(ng_delay_enum,
|
||||
CS42L52_NOISE_GATE_CTL, 0,
|
||||
cs42l52_ng_delay_text);
|
||||
|
||||
static const char * const cs42l52_ng_type_text[] = {
|
||||
"Apply Specific", "Apply All"
|
||||
};
|
||||
|
||||
static const struct soc_enum ng_type_enum =
|
||||
SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 6,
|
||||
ARRAY_SIZE(cs42l52_ng_type_text), cs42l52_ng_type_text);
|
||||
static SOC_ENUM_SINGLE_DECL(ng_type_enum,
|
||||
CS42L52_NOISE_GATE_CTL, 6,
|
||||
cs42l52_ng_type_text);
|
||||
|
||||
static const char * const left_swap_text[] = {
|
||||
"Left", "LR 2", "Right"};
|
||||
|
|
|
@ -278,13 +278,13 @@ static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1);
|
|||
static const char * const cs42l73_pgaa_text[] = { "Line A", "Mic 1" };
|
||||
static const char * const cs42l73_pgab_text[] = { "Line B", "Mic 2" };
|
||||
|
||||
static const struct soc_enum pgaa_enum =
|
||||
SOC_ENUM_SINGLE(CS42L73_ADCIPC, 3,
|
||||
ARRAY_SIZE(cs42l73_pgaa_text), cs42l73_pgaa_text);
|
||||
static SOC_ENUM_SINGLE_DECL(pgaa_enum,
|
||||
CS42L73_ADCIPC, 3,
|
||||
cs42l73_pgaa_text);
|
||||
|
||||
static const struct soc_enum pgab_enum =
|
||||
SOC_ENUM_SINGLE(CS42L73_ADCIPC, 7,
|
||||
ARRAY_SIZE(cs42l73_pgab_text), cs42l73_pgab_text);
|
||||
static SOC_ENUM_SINGLE_DECL(pgab_enum,
|
||||
CS42L73_ADCIPC, 7,
|
||||
cs42l73_pgab_text);
|
||||
|
||||
static const struct snd_kcontrol_new pgaa_mux =
|
||||
SOC_DAPM_ENUM("Left Analog Input Capture Mux", pgaa_enum);
|
||||
|
@ -309,9 +309,9 @@ static const struct snd_kcontrol_new input_right_mixer[] = {
|
|||
static const char * const cs42l73_ng_delay_text[] = {
|
||||
"50ms", "100ms", "150ms", "200ms" };
|
||||
|
||||
static const struct soc_enum ng_delay_enum =
|
||||
SOC_ENUM_SINGLE(CS42L73_NGCAB, 0,
|
||||
ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text);
|
||||
static SOC_ENUM_SINGLE_DECL(ng_delay_enum,
|
||||
CS42L73_NGCAB, 0,
|
||||
cs42l73_ng_delay_text);
|
||||
|
||||
static const char * const cs42l73_mono_mix_texts[] = {
|
||||
"Left", "Right", "Mono Mix"};
|
||||
|
@ -357,19 +357,19 @@ static const struct snd_kcontrol_new esl_xsp_mixer =
|
|||
static const char * const cs42l73_ip_swap_text[] = {
|
||||
"Stereo", "Mono A", "Mono B", "Swap A-B"};
|
||||
|
||||
static const struct soc_enum ip_swap_enum =
|
||||
SOC_ENUM_SINGLE(CS42L73_MIOPC, 6,
|
||||
ARRAY_SIZE(cs42l73_ip_swap_text), cs42l73_ip_swap_text);
|
||||
static SOC_ENUM_SINGLE_DECL(ip_swap_enum,
|
||||
CS42L73_MIOPC, 6,
|
||||
cs42l73_ip_swap_text);
|
||||
|
||||
static const char * const cs42l73_spo_mixer_text[] = {"Mono", "Stereo"};
|
||||
|
||||
static const struct soc_enum vsp_output_mux_enum =
|
||||
SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 5,
|
||||
ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text);
|
||||
static SOC_ENUM_SINGLE_DECL(vsp_output_mux_enum,
|
||||
CS42L73_MIXERCTL, 5,
|
||||
cs42l73_spo_mixer_text);
|
||||
|
||||
static const struct soc_enum xsp_output_mux_enum =
|
||||
SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 4,
|
||||
ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text);
|
||||
static SOC_ENUM_SINGLE_DECL(xsp_output_mux_enum,
|
||||
CS42L73_MIXERCTL, 4,
|
||||
cs42l73_spo_mixer_text);
|
||||
|
||||
static const struct snd_kcontrol_new vsp_output_mux =
|
||||
SOC_DAPM_ENUM("Route", vsp_output_mux_enum);
|
||||
|
@ -1108,7 +1108,7 @@ static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u32 cs42l73_asrc_rates[] = {
|
||||
static const unsigned int cs42l73_asrc_rates[] = {
|
||||
8000, 11025, 12000, 16000, 22050,
|
||||
24000, 32000, 44100, 48000
|
||||
};
|
||||
|
@ -1241,7 +1241,7 @@ static int cs42l73_set_tristate(struct snd_soc_dai *dai, int tristate)
|
|||
0x7F, tristate << 7);
|
||||
}
|
||||
|
||||
static struct snd_pcm_hw_constraint_list constraints_12_24 = {
|
||||
static const struct snd_pcm_hw_constraint_list constraints_12_24 = {
|
||||
.count = ARRAY_SIZE(cs42l73_asrc_rates),
|
||||
.list = cs42l73_asrc_rates,
|
||||
};
|
||||
|
@ -1255,9 +1255,6 @@ static int cs42l73_pcm_startup(struct snd_pcm_substream *substream,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */
|
||||
#define CS42L73_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT)
|
||||
|
||||
|
||||
#define CS42L73_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
|
||||
SNDRV_PCM_FMTBIT_S24_LE)
|
||||
|
@ -1278,14 +1275,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
|
|||
.stream_name = "XSP Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = CS42L73_RATES,
|
||||
.rates = SNDRV_PCM_RATE_KNOT,
|
||||
.formats = CS42L73_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "XSP Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = CS42L73_RATES,
|
||||
.rates = SNDRV_PCM_RATE_KNOT,
|
||||
.formats = CS42L73_FORMATS,
|
||||
},
|
||||
.ops = &cs42l73_ops,
|
||||
|
@ -1298,14 +1295,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
|
|||
.stream_name = "ASP Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = CS42L73_RATES,
|
||||
.rates = SNDRV_PCM_RATE_KNOT,
|
||||
.formats = CS42L73_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "ASP Capture",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = CS42L73_RATES,
|
||||
.rates = SNDRV_PCM_RATE_KNOT,
|
||||
.formats = CS42L73_FORMATS,
|
||||
},
|
||||
.ops = &cs42l73_ops,
|
||||
|
@ -1318,14 +1315,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = {
|
|||
.stream_name = "VSP Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = CS42L73_RATES,
|
||||
.rates = SNDRV_PCM_RATE_KNOT,
|
||||
.formats = CS42L73_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "VSP Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = CS42L73_RATES,
|
||||
.rates = SNDRV_PCM_RATE_KNOT,
|
||||
.formats = CS42L73_FORMATS,
|
||||
},
|
||||
.ops = &cs42l73_ops,
|
||||
|
|
|
@ -307,29 +307,29 @@ static const char * const da7210_hpf_cutoff_txt[] = {
|
|||
"Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7210_dac_hpf_cutoff =
|
||||
SOC_ENUM_SINGLE(DA7210_DAC_HPF, 0, 4, da7210_hpf_cutoff_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7210_dac_hpf_cutoff,
|
||||
DA7210_DAC_HPF, 0, da7210_hpf_cutoff_txt);
|
||||
|
||||
static const struct soc_enum da7210_adc_hpf_cutoff =
|
||||
SOC_ENUM_SINGLE(DA7210_ADC_HPF, 0, 4, da7210_hpf_cutoff_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7210_adc_hpf_cutoff,
|
||||
DA7210_ADC_HPF, 0, da7210_hpf_cutoff_txt);
|
||||
|
||||
/* ADC and DAC voice (8kHz) high pass cutoff value */
|
||||
static const char * const da7210_vf_cutoff_txt[] = {
|
||||
"2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7210_dac_vf_cutoff =
|
||||
SOC_ENUM_SINGLE(DA7210_DAC_HPF, 4, 8, da7210_vf_cutoff_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7210_dac_vf_cutoff,
|
||||
DA7210_DAC_HPF, 4, da7210_vf_cutoff_txt);
|
||||
|
||||
static const struct soc_enum da7210_adc_vf_cutoff =
|
||||
SOC_ENUM_SINGLE(DA7210_ADC_HPF, 4, 8, da7210_vf_cutoff_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7210_adc_vf_cutoff,
|
||||
DA7210_ADC_HPF, 4, da7210_vf_cutoff_txt);
|
||||
|
||||
static const char *da7210_hp_mode_txt[] = {
|
||||
"Class H", "Class G"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7210_hp_mode_sel =
|
||||
SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7210_hp_mode_sel,
|
||||
DA7210_HP_CFG, 0, da7210_hp_mode_txt);
|
||||
|
||||
/* ALC can be enabled only if noise suppression is disabled */
|
||||
static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol,
|
||||
|
|
|
@ -63,30 +63,30 @@ static const char * const da7213_voice_hpf_corner_txt[] = {
|
|||
"2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_dac_voice_hpf_corner =
|
||||
SOC_ENUM_SINGLE(DA7213_DAC_FILTERS1, DA7213_VOICE_HPF_CORNER_SHIFT,
|
||||
DA7213_VOICE_HPF_CORNER_MAX,
|
||||
da7213_voice_hpf_corner_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_dac_voice_hpf_corner,
|
||||
DA7213_DAC_FILTERS1,
|
||||
DA7213_VOICE_HPF_CORNER_SHIFT,
|
||||
da7213_voice_hpf_corner_txt);
|
||||
|
||||
static const struct soc_enum da7213_adc_voice_hpf_corner =
|
||||
SOC_ENUM_SINGLE(DA7213_ADC_FILTERS1, DA7213_VOICE_HPF_CORNER_SHIFT,
|
||||
DA7213_VOICE_HPF_CORNER_MAX,
|
||||
da7213_voice_hpf_corner_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_adc_voice_hpf_corner,
|
||||
DA7213_ADC_FILTERS1,
|
||||
DA7213_VOICE_HPF_CORNER_SHIFT,
|
||||
da7213_voice_hpf_corner_txt);
|
||||
|
||||
/* ADC and DAC high pass filter cutoff value */
|
||||
static const char * const da7213_audio_hpf_corner_txt[] = {
|
||||
"Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_dac_audio_hpf_corner =
|
||||
SOC_ENUM_SINGLE(DA7213_DAC_FILTERS1, DA7213_AUDIO_HPF_CORNER_SHIFT,
|
||||
DA7213_AUDIO_HPF_CORNER_MAX,
|
||||
da7213_audio_hpf_corner_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_dac_audio_hpf_corner,
|
||||
DA7213_DAC_FILTERS1
|
||||
, DA7213_AUDIO_HPF_CORNER_SHIFT,
|
||||
da7213_audio_hpf_corner_txt);
|
||||
|
||||
static const struct soc_enum da7213_adc_audio_hpf_corner =
|
||||
SOC_ENUM_SINGLE(DA7213_ADC_FILTERS1, DA7213_AUDIO_HPF_CORNER_SHIFT,
|
||||
DA7213_AUDIO_HPF_CORNER_MAX,
|
||||
da7213_audio_hpf_corner_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_adc_audio_hpf_corner,
|
||||
DA7213_ADC_FILTERS1,
|
||||
DA7213_AUDIO_HPF_CORNER_SHIFT,
|
||||
da7213_audio_hpf_corner_txt);
|
||||
|
||||
/* Gain ramping rate value */
|
||||
static const char * const da7213_gain_ramp_rate_txt[] = {
|
||||
|
@ -94,52 +94,50 @@ static const char * const da7213_gain_ramp_rate_txt[] = {
|
|||
"nominal rate / 32"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_gain_ramp_rate =
|
||||
SOC_ENUM_SINGLE(DA7213_GAIN_RAMP_CTRL, DA7213_GAIN_RAMP_RATE_SHIFT,
|
||||
DA7213_GAIN_RAMP_RATE_MAX, da7213_gain_ramp_rate_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_gain_ramp_rate,
|
||||
DA7213_GAIN_RAMP_CTRL,
|
||||
DA7213_GAIN_RAMP_RATE_SHIFT,
|
||||
da7213_gain_ramp_rate_txt);
|
||||
|
||||
/* DAC noise gate setup time value */
|
||||
static const char * const da7213_dac_ng_setup_time_txt[] = {
|
||||
"256 samples", "512 samples", "1024 samples", "2048 samples"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_dac_ng_setup_time =
|
||||
SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME,
|
||||
DA7213_DAC_NG_SETUP_TIME_SHIFT,
|
||||
DA7213_DAC_NG_SETUP_TIME_MAX,
|
||||
da7213_dac_ng_setup_time_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_setup_time,
|
||||
DA7213_DAC_NG_SETUP_TIME,
|
||||
DA7213_DAC_NG_SETUP_TIME_SHIFT,
|
||||
da7213_dac_ng_setup_time_txt);
|
||||
|
||||
/* DAC noise gate rampup rate value */
|
||||
static const char * const da7213_dac_ng_rampup_txt[] = {
|
||||
"0.02 ms/dB", "0.16 ms/dB"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_dac_ng_rampup_rate =
|
||||
SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME,
|
||||
DA7213_DAC_NG_RAMPUP_RATE_SHIFT,
|
||||
DA7213_DAC_NG_RAMP_RATE_MAX,
|
||||
da7213_dac_ng_rampup_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_rampup_rate,
|
||||
DA7213_DAC_NG_SETUP_TIME,
|
||||
DA7213_DAC_NG_RAMPUP_RATE_SHIFT,
|
||||
da7213_dac_ng_rampup_txt);
|
||||
|
||||
/* DAC noise gate rampdown rate value */
|
||||
static const char * const da7213_dac_ng_rampdown_txt[] = {
|
||||
"0.64 ms/dB", "20.48 ms/dB"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_dac_ng_rampdown_rate =
|
||||
SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME,
|
||||
DA7213_DAC_NG_RAMPDN_RATE_SHIFT,
|
||||
DA7213_DAC_NG_RAMP_RATE_MAX,
|
||||
da7213_dac_ng_rampdown_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_rampdown_rate,
|
||||
DA7213_DAC_NG_SETUP_TIME,
|
||||
DA7213_DAC_NG_RAMPDN_RATE_SHIFT,
|
||||
da7213_dac_ng_rampdown_txt);
|
||||
|
||||
/* DAC soft mute rate value */
|
||||
static const char * const da7213_dac_soft_mute_rate_txt[] = {
|
||||
"1", "2", "4", "8", "16", "32", "64"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_dac_soft_mute_rate =
|
||||
SOC_ENUM_SINGLE(DA7213_DAC_FILTERS5, DA7213_DAC_SOFTMUTE_RATE_SHIFT,
|
||||
DA7213_DAC_SOFTMUTE_RATE_MAX,
|
||||
da7213_dac_soft_mute_rate_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_dac_soft_mute_rate,
|
||||
DA7213_DAC_FILTERS5,
|
||||
DA7213_DAC_SOFTMUTE_RATE_SHIFT,
|
||||
da7213_dac_soft_mute_rate_txt);
|
||||
|
||||
/* ALC Attack Rate select */
|
||||
static const char * const da7213_alc_attack_rate_txt[] = {
|
||||
|
@ -147,9 +145,10 @@ static const char * const da7213_alc_attack_rate_txt[] = {
|
|||
"5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_alc_attack_rate =
|
||||
SOC_ENUM_SINGLE(DA7213_ALC_CTRL2, DA7213_ALC_ATTACK_SHIFT,
|
||||
DA7213_ALC_ATTACK_MAX, da7213_alc_attack_rate_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_alc_attack_rate,
|
||||
DA7213_ALC_CTRL2,
|
||||
DA7213_ALC_ATTACK_SHIFT,
|
||||
da7213_alc_attack_rate_txt);
|
||||
|
||||
/* ALC Release Rate select */
|
||||
static const char * const da7213_alc_release_rate_txt[] = {
|
||||
|
@ -157,9 +156,10 @@ static const char * const da7213_alc_release_rate_txt[] = {
|
|||
"11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_alc_release_rate =
|
||||
SOC_ENUM_SINGLE(DA7213_ALC_CTRL2, DA7213_ALC_RELEASE_SHIFT,
|
||||
DA7213_ALC_RELEASE_MAX, da7213_alc_release_rate_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_alc_release_rate,
|
||||
DA7213_ALC_CTRL2,
|
||||
DA7213_ALC_RELEASE_SHIFT,
|
||||
da7213_alc_release_rate_txt);
|
||||
|
||||
/* ALC Hold Time select */
|
||||
static const char * const da7213_alc_hold_time_txt[] = {
|
||||
|
@ -168,22 +168,25 @@ static const char * const da7213_alc_hold_time_txt[] = {
|
|||
"253952/fs", "507904/fs", "1015808/fs", "2031616/fs"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_alc_hold_time =
|
||||
SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_HOLD_SHIFT,
|
||||
DA7213_ALC_HOLD_MAX, da7213_alc_hold_time_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_alc_hold_time,
|
||||
DA7213_ALC_CTRL3,
|
||||
DA7213_ALC_HOLD_SHIFT,
|
||||
da7213_alc_hold_time_txt);
|
||||
|
||||
/* ALC Input Signal Tracking rate select */
|
||||
static const char * const da7213_alc_integ_rate_txt[] = {
|
||||
"1/4", "1/16", "1/256", "1/65536"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_alc_integ_attack_rate =
|
||||
SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_INTEG_ATTACK_SHIFT,
|
||||
DA7213_ALC_INTEG_MAX, da7213_alc_integ_rate_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_attack_rate,
|
||||
DA7213_ALC_CTRL3,
|
||||
DA7213_ALC_INTEG_ATTACK_SHIFT,
|
||||
da7213_alc_integ_rate_txt);
|
||||
|
||||
static const struct soc_enum da7213_alc_integ_release_rate =
|
||||
SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_INTEG_RELEASE_SHIFT,
|
||||
DA7213_ALC_INTEG_MAX, da7213_alc_integ_rate_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_release_rate,
|
||||
DA7213_ALC_CTRL3,
|
||||
DA7213_ALC_INTEG_RELEASE_SHIFT,
|
||||
da7213_alc_integ_rate_txt);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -584,15 +587,17 @@ static const char * const da7213_mic_amp_in_sel_txt[] = {
|
|||
"Differential", "MIC_P", "MIC_N"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_mic_1_amp_in_sel =
|
||||
SOC_ENUM_SINGLE(DA7213_MIC_1_CTRL, DA7213_MIC_AMP_IN_SEL_SHIFT,
|
||||
DA7213_MIC_AMP_IN_SEL_MAX, da7213_mic_amp_in_sel_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_mic_1_amp_in_sel,
|
||||
DA7213_MIC_1_CTRL,
|
||||
DA7213_MIC_AMP_IN_SEL_SHIFT,
|
||||
da7213_mic_amp_in_sel_txt);
|
||||
static const struct snd_kcontrol_new da7213_mic_1_amp_in_sel_mux =
|
||||
SOC_DAPM_ENUM("Mic 1 Amp Source MUX", da7213_mic_1_amp_in_sel);
|
||||
|
||||
static const struct soc_enum da7213_mic_2_amp_in_sel =
|
||||
SOC_ENUM_SINGLE(DA7213_MIC_2_CTRL, DA7213_MIC_AMP_IN_SEL_SHIFT,
|
||||
DA7213_MIC_AMP_IN_SEL_MAX, da7213_mic_amp_in_sel_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_mic_2_amp_in_sel,
|
||||
DA7213_MIC_2_CTRL,
|
||||
DA7213_MIC_AMP_IN_SEL_SHIFT,
|
||||
da7213_mic_amp_in_sel_txt);
|
||||
static const struct snd_kcontrol_new da7213_mic_2_amp_in_sel_mux =
|
||||
SOC_DAPM_ENUM("Mic 2 Amp Source MUX", da7213_mic_2_amp_in_sel);
|
||||
|
||||
|
@ -601,15 +606,17 @@ static const char * const da7213_dai_src_txt[] = {
|
|||
"ADC Left", "ADC Right", "DAI Input Left", "DAI Input Right"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_dai_l_src =
|
||||
SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAI, DA7213_DAI_L_SRC_SHIFT,
|
||||
DA7213_DAI_SRC_MAX, da7213_dai_src_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_dai_l_src,
|
||||
DA7213_DIG_ROUTING_DAI,
|
||||
DA7213_DAI_L_SRC_SHIFT,
|
||||
da7213_dai_src_txt);
|
||||
static const struct snd_kcontrol_new da7213_dai_l_src_mux =
|
||||
SOC_DAPM_ENUM("DAI Left Source MUX", da7213_dai_l_src);
|
||||
|
||||
static const struct soc_enum da7213_dai_r_src =
|
||||
SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAI, DA7213_DAI_R_SRC_SHIFT,
|
||||
DA7213_DAI_SRC_MAX, da7213_dai_src_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_dai_r_src,
|
||||
DA7213_DIG_ROUTING_DAI,
|
||||
DA7213_DAI_R_SRC_SHIFT,
|
||||
da7213_dai_src_txt);
|
||||
static const struct snd_kcontrol_new da7213_dai_r_src_mux =
|
||||
SOC_DAPM_ENUM("DAI Right Source MUX", da7213_dai_r_src);
|
||||
|
||||
|
@ -619,15 +626,17 @@ static const char * const da7213_dac_src_txt[] = {
|
|||
"DAI Input Right"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_dac_l_src =
|
||||
SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAC, DA7213_DAC_L_SRC_SHIFT,
|
||||
DA7213_DAC_SRC_MAX, da7213_dac_src_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_dac_l_src,
|
||||
DA7213_DIG_ROUTING_DAC,
|
||||
DA7213_DAC_L_SRC_SHIFT,
|
||||
da7213_dac_src_txt);
|
||||
static const struct snd_kcontrol_new da7213_dac_l_src_mux =
|
||||
SOC_DAPM_ENUM("DAC Left Source MUX", da7213_dac_l_src);
|
||||
|
||||
static const struct soc_enum da7213_dac_r_src =
|
||||
SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAC, DA7213_DAC_R_SRC_SHIFT,
|
||||
DA7213_DAC_SRC_MAX, da7213_dac_src_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da7213_dac_r_src,
|
||||
DA7213_DIG_ROUTING_DAC,
|
||||
DA7213_DAC_R_SRC_SHIFT,
|
||||
da7213_dac_src_txt);
|
||||
static const struct snd_kcontrol_new da7213_dac_r_src_mux =
|
||||
SOC_DAPM_ENUM("DAC Right Source MUX", da7213_dac_r_src);
|
||||
|
||||
|
|
|
@ -269,81 +269,65 @@ static const char *da732x_hpf_voice[] = {
|
|||
"150Hz", "200Hz", "300Hz", "400Hz"
|
||||
};
|
||||
|
||||
static const struct soc_enum da732x_dac1_hpf_mode_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT,
|
||||
DA732X_HPF_MODE_MAX, da732x_hpf_mode)
|
||||
};
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_dac1_hpf_mode_enum,
|
||||
DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT,
|
||||
da732x_hpf_mode);
|
||||
|
||||
static const struct soc_enum da732x_dac2_hpf_mode_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT,
|
||||
DA732X_HPF_MODE_MAX, da732x_hpf_mode)
|
||||
};
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_dac2_hpf_mode_enum,
|
||||
DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT,
|
||||
da732x_hpf_mode);
|
||||
|
||||
static const struct soc_enum da732x_dac3_hpf_mode_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT,
|
||||
DA732X_HPF_MODE_MAX, da732x_hpf_mode)
|
||||
};
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_dac3_hpf_mode_enum,
|
||||
DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT,
|
||||
da732x_hpf_mode);
|
||||
|
||||
static const struct soc_enum da732x_adc1_hpf_mode_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT,
|
||||
DA732X_HPF_MODE_MAX, da732x_hpf_mode)
|
||||
};
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_adc1_hpf_mode_enum,
|
||||
DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT,
|
||||
da732x_hpf_mode);
|
||||
|
||||
static const struct soc_enum da732x_adc2_hpf_mode_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT,
|
||||
DA732X_HPF_MODE_MAX, da732x_hpf_mode)
|
||||
};
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_adc2_hpf_mode_enum,
|
||||
DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT,
|
||||
da732x_hpf_mode);
|
||||
|
||||
static const struct soc_enum da732x_dac1_hp_filter_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT,
|
||||
DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
|
||||
};
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_dac1_hp_filter_enum,
|
||||
DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT,
|
||||
da732x_hpf_music);
|
||||
|
||||
static const struct soc_enum da732x_dac2_hp_filter_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT,
|
||||
DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
|
||||
};
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_dac2_hp_filter_enum,
|
||||
DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT,
|
||||
da732x_hpf_music);
|
||||
|
||||
static const struct soc_enum da732x_dac3_hp_filter_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT,
|
||||
DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
|
||||
};
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_dac3_hp_filter_enum,
|
||||
DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT,
|
||||
da732x_hpf_music);
|
||||
|
||||
static const struct soc_enum da732x_adc1_hp_filter_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT,
|
||||
DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
|
||||
};
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_adc1_hp_filter_enum,
|
||||
DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT,
|
||||
da732x_hpf_music);
|
||||
|
||||
static const struct soc_enum da732x_adc2_hp_filter_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT,
|
||||
DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
|
||||
};
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_adc2_hp_filter_enum,
|
||||
DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT,
|
||||
da732x_hpf_music);
|
||||
|
||||
static const struct soc_enum da732x_dac1_voice_filter_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT,
|
||||
DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
|
||||
};
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_dac1_voice_filter_enum,
|
||||
DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT,
|
||||
da732x_hpf_voice);
|
||||
|
||||
static const struct soc_enum da732x_dac2_voice_filter_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT,
|
||||
DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
|
||||
};
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_dac2_voice_filter_enum,
|
||||
DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT,
|
||||
da732x_hpf_voice);
|
||||
|
||||
static const struct soc_enum da732x_dac3_voice_filter_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT,
|
||||
DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
|
||||
};
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_dac3_voice_filter_enum,
|
||||
DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT,
|
||||
da732x_hpf_voice);
|
||||
|
||||
static const struct soc_enum da732x_adc1_voice_filter_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT,
|
||||
DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
|
||||
};
|
||||
|
||||
static const struct soc_enum da732x_adc2_voice_filter_enum[] = {
|
||||
SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT,
|
||||
DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
|
||||
};
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_adc1_voice_filter_enum,
|
||||
DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT,
|
||||
da732x_hpf_voice);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_adc2_voice_filter_enum,
|
||||
DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT,
|
||||
da732x_hpf_voice);
|
||||
|
||||
static int da732x_hpf_set(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
|
@ -714,65 +698,65 @@ static const char *enable_text[] = {
|
|||
};
|
||||
|
||||
/* ADC1LMUX */
|
||||
static const struct soc_enum adc1l_enum =
|
||||
SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT,
|
||||
DA732X_ADCL_MUX_MAX, adcl_text);
|
||||
static SOC_ENUM_SINGLE_DECL(adc1l_enum,
|
||||
DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT,
|
||||
adcl_text);
|
||||
static const struct snd_kcontrol_new adc1l_mux =
|
||||
SOC_DAPM_ENUM("ADC Route", adc1l_enum);
|
||||
|
||||
/* ADC1RMUX */
|
||||
static const struct soc_enum adc1r_enum =
|
||||
SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT,
|
||||
DA732X_ADCR_MUX_MAX, adcr_text);
|
||||
static SOC_ENUM_SINGLE_DECL(adc1r_enum,
|
||||
DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT,
|
||||
adcr_text);
|
||||
static const struct snd_kcontrol_new adc1r_mux =
|
||||
SOC_DAPM_ENUM("ADC Route", adc1r_enum);
|
||||
|
||||
/* ADC2LMUX */
|
||||
static const struct soc_enum adc2l_enum =
|
||||
SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT,
|
||||
DA732X_ADCL_MUX_MAX, adcl_text);
|
||||
static SOC_ENUM_SINGLE_DECL(adc2l_enum,
|
||||
DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT,
|
||||
adcl_text);
|
||||
static const struct snd_kcontrol_new adc2l_mux =
|
||||
SOC_DAPM_ENUM("ADC Route", adc2l_enum);
|
||||
|
||||
/* ADC2RMUX */
|
||||
static const struct soc_enum adc2r_enum =
|
||||
SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT,
|
||||
DA732X_ADCR_MUX_MAX, adcr_text);
|
||||
static SOC_ENUM_SINGLE_DECL(adc2r_enum,
|
||||
DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT,
|
||||
adcr_text);
|
||||
|
||||
static const struct snd_kcontrol_new adc2r_mux =
|
||||
SOC_DAPM_ENUM("ADC Route", adc2r_enum);
|
||||
|
||||
static const struct soc_enum da732x_hp_left_output =
|
||||
SOC_ENUM_SINGLE(DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT,
|
||||
DA732X_DAC_EN_MAX, enable_text);
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_hp_left_output,
|
||||
DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT,
|
||||
enable_text);
|
||||
|
||||
static const struct snd_kcontrol_new hpl_mux =
|
||||
SOC_DAPM_ENUM("HPL Switch", da732x_hp_left_output);
|
||||
|
||||
static const struct soc_enum da732x_hp_right_output =
|
||||
SOC_ENUM_SINGLE(DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT,
|
||||
DA732X_DAC_EN_MAX, enable_text);
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_hp_right_output,
|
||||
DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT,
|
||||
enable_text);
|
||||
|
||||
static const struct snd_kcontrol_new hpr_mux =
|
||||
SOC_DAPM_ENUM("HPR Switch", da732x_hp_right_output);
|
||||
|
||||
static const struct soc_enum da732x_speaker_output =
|
||||
SOC_ENUM_SINGLE(DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT,
|
||||
DA732X_DAC_EN_MAX, enable_text);
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_speaker_output,
|
||||
DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT,
|
||||
enable_text);
|
||||
|
||||
static const struct snd_kcontrol_new spk_mux =
|
||||
SOC_DAPM_ENUM("SPK Switch", da732x_speaker_output);
|
||||
|
||||
static const struct soc_enum da732x_lout4_output =
|
||||
SOC_ENUM_SINGLE(DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT,
|
||||
DA732X_DAC_EN_MAX, enable_text);
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_lout4_output,
|
||||
DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT,
|
||||
enable_text);
|
||||
|
||||
static const struct snd_kcontrol_new lout4_mux =
|
||||
SOC_DAPM_ENUM("LOUT4 Switch", da732x_lout4_output);
|
||||
|
||||
static const struct soc_enum da732x_lout2_output =
|
||||
SOC_ENUM_SINGLE(DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT,
|
||||
DA732X_DAC_EN_MAX, enable_text);
|
||||
static SOC_ENUM_SINGLE_DECL(da732x_lout2_output,
|
||||
DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT,
|
||||
enable_text);
|
||||
|
||||
static const struct snd_kcontrol_new lout2_mux =
|
||||
SOC_DAPM_ENUM("LOUT2 Switch", da732x_lout2_output);
|
||||
|
@ -1499,8 +1483,8 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec,
|
|||
|
||||
da732x_hp_dc_offset_cancellation(codec);
|
||||
|
||||
regcache_cache_only(codec->control_data, false);
|
||||
regcache_sync(codec->control_data);
|
||||
regcache_cache_only(da732x->regmap, false);
|
||||
regcache_sync(da732x->regmap);
|
||||
} else {
|
||||
snd_soc_update_bits(codec, DA732X_REG_BIAS_EN,
|
||||
DA732X_BIAS_BOOST_MASK,
|
||||
|
@ -1511,7 +1495,7 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec,
|
|||
}
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
regcache_cache_only(codec->control_data, true);
|
||||
regcache_cache_only(da732x->regmap, true);
|
||||
da732x_set_charge_pump(codec, DA732X_DISABLE_CP);
|
||||
snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_EN,
|
||||
DA732X_BIAS_DIS);
|
||||
|
@ -1566,7 +1550,6 @@ static struct snd_soc_codec_driver soc_codec_dev_da732x = {
|
|||
.dapm_routes = da732x_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes),
|
||||
.set_pll = da732x_set_dai_pll,
|
||||
.reg_cache_size = ARRAY_SIZE(da732x_reg_cache),
|
||||
};
|
||||
|
||||
static int da732x_i2c_probe(struct i2c_client *i2c,
|
||||
|
|
|
@ -113,9 +113,6 @@
|
|||
#define DA732X_EQ_OVERALL_VOL_DB_MIN -1800
|
||||
#define DA732X_EQ_OVERALL_VOL_DB_INC 600
|
||||
|
||||
#define DA732X_SOC_ENUM_DOUBLE_R(xreg, xrreg, xmax, xtext) \
|
||||
{.reg = xreg, .reg2 = xrreg, .max = xmax, .texts = xtext}
|
||||
|
||||
enum da732x_sysctl {
|
||||
DA732X_SR_8KHZ = 0x1,
|
||||
DA732X_SR_11_025KHZ = 0x2,
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
|
@ -321,22 +323,22 @@ static const char * const da9055_hpf_cutoff_txt[] = {
|
|||
"Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000"
|
||||
};
|
||||
|
||||
static const struct soc_enum da9055_dac_hpf_cutoff =
|
||||
SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_dac_hpf_cutoff,
|
||||
DA9055_DAC_FILTERS1, 4, da9055_hpf_cutoff_txt);
|
||||
|
||||
static const struct soc_enum da9055_adc_hpf_cutoff =
|
||||
SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_adc_hpf_cutoff,
|
||||
DA9055_ADC_FILTERS1, 4, da9055_hpf_cutoff_txt);
|
||||
|
||||
/* ADC and DAC voice mode (8kHz) high pass cutoff value */
|
||||
static const char * const da9055_vf_cutoff_txt[] = {
|
||||
"2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
|
||||
};
|
||||
|
||||
static const struct soc_enum da9055_dac_vf_cutoff =
|
||||
SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 0, 8, da9055_vf_cutoff_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_dac_vf_cutoff,
|
||||
DA9055_DAC_FILTERS1, 0, da9055_vf_cutoff_txt);
|
||||
|
||||
static const struct soc_enum da9055_adc_vf_cutoff =
|
||||
SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 0, 8, da9055_vf_cutoff_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_adc_vf_cutoff,
|
||||
DA9055_ADC_FILTERS1, 0, da9055_vf_cutoff_txt);
|
||||
|
||||
/* Gain ramping rate value */
|
||||
static const char * const da9055_gain_ramping_txt[] = {
|
||||
|
@ -344,44 +346,44 @@ static const char * const da9055_gain_ramping_txt[] = {
|
|||
"nominal rate / 8"
|
||||
};
|
||||
|
||||
static const struct soc_enum da9055_gain_ramping_rate =
|
||||
SOC_ENUM_SINGLE(DA9055_GAIN_RAMP_CTRL, 0, 4, da9055_gain_ramping_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_gain_ramping_rate,
|
||||
DA9055_GAIN_RAMP_CTRL, 0, da9055_gain_ramping_txt);
|
||||
|
||||
/* DAC noise gate setup time value */
|
||||
static const char * const da9055_dac_ng_setup_time_txt[] = {
|
||||
"256 samples", "512 samples", "1024 samples", "2048 samples"
|
||||
};
|
||||
|
||||
static const struct soc_enum da9055_dac_ng_setup_time =
|
||||
SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 0, 4,
|
||||
da9055_dac_ng_setup_time_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_setup_time,
|
||||
DA9055_DAC_NG_SETUP_TIME, 0,
|
||||
da9055_dac_ng_setup_time_txt);
|
||||
|
||||
/* DAC noise gate rampup rate value */
|
||||
static const char * const da9055_dac_ng_rampup_txt[] = {
|
||||
"0.02 ms/dB", "0.16 ms/dB"
|
||||
};
|
||||
|
||||
static const struct soc_enum da9055_dac_ng_rampup_rate =
|
||||
SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 2, 2,
|
||||
da9055_dac_ng_rampup_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_rampup_rate,
|
||||
DA9055_DAC_NG_SETUP_TIME, 2,
|
||||
da9055_dac_ng_rampup_txt);
|
||||
|
||||
/* DAC noise gate rampdown rate value */
|
||||
static const char * const da9055_dac_ng_rampdown_txt[] = {
|
||||
"0.64 ms/dB", "20.48 ms/dB"
|
||||
};
|
||||
|
||||
static const struct soc_enum da9055_dac_ng_rampdown_rate =
|
||||
SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 3, 2,
|
||||
da9055_dac_ng_rampdown_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_rampdown_rate,
|
||||
DA9055_DAC_NG_SETUP_TIME, 3,
|
||||
da9055_dac_ng_rampdown_txt);
|
||||
|
||||
/* DAC soft mute rate value */
|
||||
static const char * const da9055_dac_soft_mute_rate_txt[] = {
|
||||
"1", "2", "4", "8", "16", "32", "64"
|
||||
};
|
||||
|
||||
static const struct soc_enum da9055_dac_soft_mute_rate =
|
||||
SOC_ENUM_SINGLE(DA9055_DAC_FILTERS5, 4, 7,
|
||||
da9055_dac_soft_mute_rate_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_dac_soft_mute_rate,
|
||||
DA9055_DAC_FILTERS5, 4,
|
||||
da9055_dac_soft_mute_rate_txt);
|
||||
|
||||
/* DAC routing select */
|
||||
static const char * const da9055_dac_src_txt[] = {
|
||||
|
@ -389,40 +391,40 @@ static const char * const da9055_dac_src_txt[] = {
|
|||
"AIF input right"
|
||||
};
|
||||
|
||||
static const struct soc_enum da9055_dac_l_src =
|
||||
SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 0, 4, da9055_dac_src_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_dac_l_src,
|
||||
DA9055_DIG_ROUTING_DAC, 0, da9055_dac_src_txt);
|
||||
|
||||
static const struct soc_enum da9055_dac_r_src =
|
||||
SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 4, 4, da9055_dac_src_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_dac_r_src,
|
||||
DA9055_DIG_ROUTING_DAC, 4, da9055_dac_src_txt);
|
||||
|
||||
/* MIC PGA Left source select */
|
||||
static const char * const da9055_mic_l_src_txt[] = {
|
||||
"MIC1_P_N", "MIC1_P", "MIC1_N", "MIC2_L"
|
||||
};
|
||||
|
||||
static const struct soc_enum da9055_mic_l_src =
|
||||
SOC_ENUM_SINGLE(DA9055_MIXIN_L_SELECT, 4, 4, da9055_mic_l_src_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_mic_l_src,
|
||||
DA9055_MIXIN_L_SELECT, 4, da9055_mic_l_src_txt);
|
||||
|
||||
/* MIC PGA Right source select */
|
||||
static const char * const da9055_mic_r_src_txt[] = {
|
||||
"MIC2_R_L", "MIC2_R", "MIC2_L"
|
||||
};
|
||||
|
||||
static const struct soc_enum da9055_mic_r_src =
|
||||
SOC_ENUM_SINGLE(DA9055_MIXIN_R_SELECT, 4, 3, da9055_mic_r_src_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_mic_r_src,
|
||||
DA9055_MIXIN_R_SELECT, 4, da9055_mic_r_src_txt);
|
||||
|
||||
/* ALC Input Signal Tracking rate select */
|
||||
static const char * const da9055_signal_tracking_rate_txt[] = {
|
||||
"1/4", "1/16", "1/256", "1/65536"
|
||||
};
|
||||
|
||||
static const struct soc_enum da9055_integ_attack_rate =
|
||||
SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 4, 4,
|
||||
da9055_signal_tracking_rate_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_integ_attack_rate,
|
||||
DA9055_ALC_CTRL3, 4,
|
||||
da9055_signal_tracking_rate_txt);
|
||||
|
||||
static const struct soc_enum da9055_integ_release_rate =
|
||||
SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 6, 4,
|
||||
da9055_signal_tracking_rate_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_integ_release_rate,
|
||||
DA9055_ALC_CTRL3, 6,
|
||||
da9055_signal_tracking_rate_txt);
|
||||
|
||||
/* ALC Attack Rate select */
|
||||
static const char * const da9055_attack_rate_txt[] = {
|
||||
|
@ -430,8 +432,8 @@ static const char * const da9055_attack_rate_txt[] = {
|
|||
"5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs"
|
||||
};
|
||||
|
||||
static const struct soc_enum da9055_attack_rate =
|
||||
SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 0, 13, da9055_attack_rate_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_attack_rate,
|
||||
DA9055_ALC_CTRL2, 0, da9055_attack_rate_txt);
|
||||
|
||||
/* ALC Release Rate select */
|
||||
static const char * const da9055_release_rate_txt[] = {
|
||||
|
@ -439,8 +441,8 @@ static const char * const da9055_release_rate_txt[] = {
|
|||
"11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs"
|
||||
};
|
||||
|
||||
static const struct soc_enum da9055_release_rate =
|
||||
SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 4, 11, da9055_release_rate_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_release_rate,
|
||||
DA9055_ALC_CTRL2, 4, da9055_release_rate_txt);
|
||||
|
||||
/* ALC Hold Time select */
|
||||
static const char * const da9055_hold_time_txt[] = {
|
||||
|
@ -449,8 +451,8 @@ static const char * const da9055_hold_time_txt[] = {
|
|||
"253952/fs", "507904/fs", "1015808/fs", "2031616/fs"
|
||||
};
|
||||
|
||||
static const struct soc_enum da9055_hold_time =
|
||||
SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 0, 16, da9055_hold_time_txt);
|
||||
static SOC_ENUM_SINGLE_DECL(da9055_hold_time,
|
||||
DA9055_ALC_CTRL3, 0, da9055_hold_time_txt);
|
||||
|
||||
static int da9055_get_alc_data(struct snd_soc_codec *codec, u8 reg_val)
|
||||
{
|
||||
|
@ -1536,11 +1538,17 @@ static const struct i2c_device_id da9055_i2c_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, da9055_i2c_id);
|
||||
|
||||
static const struct of_device_id da9055_of_match[] = {
|
||||
{ .compatible = "dlg,da9055-codec", },
|
||||
{ }
|
||||
};
|
||||
|
||||
/* I2C codec control layer */
|
||||
static struct i2c_driver da9055_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "da9055-codec",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(da9055_of_match),
|
||||
},
|
||||
.probe = da9055_i2c_probe,
|
||||
.remove = da9055_remove,
|
||||
|
|
|
@ -195,18 +195,18 @@ struct lm49453_priv {
|
|||
|
||||
static const char *lm49453_mic2mode_text[] = {"Single Ended", "Differential"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(lm49453_mic2mode_enum, LM49453_P0_MICR_REG, 5,
|
||||
lm49453_mic2mode_text);
|
||||
static SOC_ENUM_SINGLE_DECL(lm49453_mic2mode_enum, LM49453_P0_MICR_REG, 5,
|
||||
lm49453_mic2mode_text);
|
||||
|
||||
static const char *lm49453_dmic_cfg_text[] = {"DMICDAT1", "DMICDAT2"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(lm49453_dmic12_cfg_enum,
|
||||
LM49453_P0_DIGITAL_MIC1_CONFIG_REG,
|
||||
7, lm49453_dmic_cfg_text);
|
||||
static SOC_ENUM_SINGLE_DECL(lm49453_dmic12_cfg_enum,
|
||||
LM49453_P0_DIGITAL_MIC1_CONFIG_REG, 7,
|
||||
lm49453_dmic_cfg_text);
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(lm49453_dmic34_cfg_enum,
|
||||
LM49453_P0_DIGITAL_MIC2_CONFIG_REG,
|
||||
7, lm49453_dmic_cfg_text);
|
||||
static SOC_ENUM_SINGLE_DECL(lm49453_dmic34_cfg_enum,
|
||||
LM49453_P0_DIGITAL_MIC2_CONFIG_REG, 7,
|
||||
lm49453_dmic_cfg_text);
|
||||
|
||||
/* MUX Controls */
|
||||
static const char *lm49453_adcl_mux_text[] = { "MIC1", "Aux_L" };
|
||||
|
|
|
@ -1849,7 +1849,7 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec)
|
|||
|
||||
/* Now point the soc_enum to .texts array items */
|
||||
max98088->eq_enum.texts = max98088->eq_texts;
|
||||
max98088->eq_enum.max = max98088->eq_textcnt;
|
||||
max98088->eq_enum.items = max98088->eq_textcnt;
|
||||
|
||||
ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
|
||||
if (ret != 0)
|
||||
|
|
|
@ -513,65 +513,75 @@ static const char *max98090_perf_pwr_text[] =
|
|||
static const char *max98090_pwr_perf_text[] =
|
||||
{ "Low Power", "High Performance" };
|
||||
|
||||
static const struct soc_enum max98090_vcmbandgap_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_BIAS_CONTROL, M98090_VCM_MODE_SHIFT,
|
||||
ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max98090_vcmbandgap_enum,
|
||||
M98090_REG_BIAS_CONTROL,
|
||||
M98090_VCM_MODE_SHIFT,
|
||||
max98090_pwr_perf_text);
|
||||
|
||||
static const char *max98090_osr128_text[] = { "64*fs", "128*fs" };
|
||||
|
||||
static const struct soc_enum max98090_osr128_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_OSR128_SHIFT,
|
||||
ARRAY_SIZE(max98090_osr128_text), max98090_osr128_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max98090_osr128_enum,
|
||||
M98090_REG_ADC_CONTROL,
|
||||
M98090_OSR128_SHIFT,
|
||||
max98090_osr128_text);
|
||||
|
||||
static const char *max98090_mode_text[] = { "Voice", "Music" };
|
||||
|
||||
static const struct soc_enum max98090_mode_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_FILTER_CONFIG, M98090_MODE_SHIFT,
|
||||
ARRAY_SIZE(max98090_mode_text), max98090_mode_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max98090_mode_enum,
|
||||
M98090_REG_FILTER_CONFIG,
|
||||
M98090_MODE_SHIFT,
|
||||
max98090_mode_text);
|
||||
|
||||
static const struct soc_enum max98090_filter_dmic34mode_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_FILTER_CONFIG,
|
||||
M98090_FLT_DMIC34MODE_SHIFT,
|
||||
ARRAY_SIZE(max98090_mode_text), max98090_mode_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max98090_filter_dmic34mode_enum,
|
||||
M98090_REG_FILTER_CONFIG,
|
||||
M98090_FLT_DMIC34MODE_SHIFT,
|
||||
max98090_mode_text);
|
||||
|
||||
static const char *max98090_drcatk_text[] =
|
||||
{ "0.5ms", "1ms", "5ms", "10ms", "25ms", "50ms", "100ms", "200ms" };
|
||||
|
||||
static const struct soc_enum max98090_drcatk_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCATK_SHIFT,
|
||||
ARRAY_SIZE(max98090_drcatk_text), max98090_drcatk_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max98090_drcatk_enum,
|
||||
M98090_REG_DRC_TIMING,
|
||||
M98090_DRCATK_SHIFT,
|
||||
max98090_drcatk_text);
|
||||
|
||||
static const char *max98090_drcrls_text[] =
|
||||
{ "8s", "4s", "2s", "1s", "0.5s", "0.25s", "0.125s", "0.0625s" };
|
||||
|
||||
static const struct soc_enum max98090_drcrls_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCRLS_SHIFT,
|
||||
ARRAY_SIZE(max98090_drcrls_text), max98090_drcrls_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max98090_drcrls_enum,
|
||||
M98090_REG_DRC_TIMING,
|
||||
M98090_DRCRLS_SHIFT,
|
||||
max98090_drcrls_text);
|
||||
|
||||
static const char *max98090_alccmp_text[] =
|
||||
{ "1:1", "1:1.5", "1:2", "1:4", "1:INF" };
|
||||
|
||||
static const struct soc_enum max98090_alccmp_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_DRC_COMPRESSOR, M98090_DRCCMP_SHIFT,
|
||||
ARRAY_SIZE(max98090_alccmp_text), max98090_alccmp_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max98090_alccmp_enum,
|
||||
M98090_REG_DRC_COMPRESSOR,
|
||||
M98090_DRCCMP_SHIFT,
|
||||
max98090_alccmp_text);
|
||||
|
||||
static const char *max98090_drcexp_text[] = { "1:1", "2:1", "3:1" };
|
||||
|
||||
static const struct soc_enum max98090_drcexp_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_DRC_EXPANDER, M98090_DRCEXP_SHIFT,
|
||||
ARRAY_SIZE(max98090_drcexp_text), max98090_drcexp_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max98090_drcexp_enum,
|
||||
M98090_REG_DRC_EXPANDER,
|
||||
M98090_DRCEXP_SHIFT,
|
||||
max98090_drcexp_text);
|
||||
|
||||
static const struct soc_enum max98090_dac_perfmode_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_DAC_CONTROL, M98090_PERFMODE_SHIFT,
|
||||
ARRAY_SIZE(max98090_perf_pwr_text), max98090_perf_pwr_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max98090_dac_perfmode_enum,
|
||||
M98090_REG_DAC_CONTROL,
|
||||
M98090_PERFMODE_SHIFT,
|
||||
max98090_perf_pwr_text);
|
||||
|
||||
static const struct soc_enum max98090_dachp_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_DAC_CONTROL, M98090_DACHP_SHIFT,
|
||||
ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max98090_dachp_enum,
|
||||
M98090_REG_DAC_CONTROL,
|
||||
M98090_DACHP_SHIFT,
|
||||
max98090_pwr_perf_text);
|
||||
|
||||
static const struct soc_enum max98090_adchp_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_ADCHP_SHIFT,
|
||||
ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max98090_adchp_enum,
|
||||
M98090_REG_ADC_CONTROL,
|
||||
M98090_ADCHP_SHIFT,
|
||||
max98090_pwr_perf_text);
|
||||
|
||||
static const struct snd_kcontrol_new max98090_snd_controls[] = {
|
||||
SOC_ENUM("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum),
|
||||
|
@ -842,39 +852,42 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w,
|
|||
|
||||
static const char *mic1_mux_text[] = { "IN12", "IN56" };
|
||||
|
||||
static const struct soc_enum mic1_mux_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_INPUT_MODE, M98090_EXTMIC1_SHIFT,
|
||||
ARRAY_SIZE(mic1_mux_text), mic1_mux_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mic1_mux_enum,
|
||||
M98090_REG_INPUT_MODE,
|
||||
M98090_EXTMIC1_SHIFT,
|
||||
mic1_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new max98090_mic1_mux =
|
||||
SOC_DAPM_ENUM("MIC1 Mux", mic1_mux_enum);
|
||||
|
||||
static const char *mic2_mux_text[] = { "IN34", "IN56" };
|
||||
|
||||
static const struct soc_enum mic2_mux_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_INPUT_MODE, M98090_EXTMIC2_SHIFT,
|
||||
ARRAY_SIZE(mic2_mux_text), mic2_mux_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mic2_mux_enum,
|
||||
M98090_REG_INPUT_MODE,
|
||||
M98090_EXTMIC2_SHIFT,
|
||||
mic2_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new max98090_mic2_mux =
|
||||
SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum);
|
||||
|
||||
static const char *dmic_mux_text[] = { "ADC", "DMIC" };
|
||||
|
||||
static const struct soc_enum dmic_mux_enum =
|
||||
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dmic_mux_text), dmic_mux_text);
|
||||
static SOC_ENUM_SINGLE_VIRT_DECL(dmic_mux_enum, dmic_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new max98090_dmic_mux =
|
||||
SOC_DAPM_ENUM_VIRT("DMIC Mux", dmic_mux_enum);
|
||||
|
||||
static const char *max98090_micpre_text[] = { "Off", "On" };
|
||||
|
||||
static const struct soc_enum max98090_pa1en_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT,
|
||||
ARRAY_SIZE(max98090_micpre_text), max98090_micpre_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max98090_pa1en_enum,
|
||||
M98090_REG_MIC1_INPUT_LEVEL,
|
||||
M98090_MIC_PA1EN_SHIFT,
|
||||
max98090_micpre_text);
|
||||
|
||||
static const struct soc_enum max98090_pa2en_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_MIC2_INPUT_LEVEL, M98090_MIC_PA2EN_SHIFT,
|
||||
ARRAY_SIZE(max98090_micpre_text), max98090_micpre_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max98090_pa2en_enum,
|
||||
M98090_REG_MIC2_INPUT_LEVEL,
|
||||
M98090_MIC_PA2EN_SHIFT,
|
||||
max98090_micpre_text);
|
||||
|
||||
/* LINEA mixer switch */
|
||||
static const struct snd_kcontrol_new max98090_linea_mixer_controls[] = {
|
||||
|
@ -938,13 +951,15 @@ static const struct snd_kcontrol_new max98090_right_adc_mixer_controls[] = {
|
|||
|
||||
static const char *lten_mux_text[] = { "Normal", "Loopthrough" };
|
||||
|
||||
static const struct soc_enum ltenl_mux_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LTEN_SHIFT,
|
||||
ARRAY_SIZE(lten_mux_text), lten_mux_text);
|
||||
static SOC_ENUM_SINGLE_DECL(ltenl_mux_enum,
|
||||
M98090_REG_IO_CONFIGURATION,
|
||||
M98090_LTEN_SHIFT,
|
||||
lten_mux_text);
|
||||
|
||||
static const struct soc_enum ltenr_mux_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LTEN_SHIFT,
|
||||
ARRAY_SIZE(lten_mux_text), lten_mux_text);
|
||||
static SOC_ENUM_SINGLE_DECL(ltenr_mux_enum,
|
||||
M98090_REG_IO_CONFIGURATION,
|
||||
M98090_LTEN_SHIFT,
|
||||
lten_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new max98090_ltenl_mux =
|
||||
SOC_DAPM_ENUM("LTENL Mux", ltenl_mux_enum);
|
||||
|
@ -954,13 +969,15 @@ static const struct snd_kcontrol_new max98090_ltenr_mux =
|
|||
|
||||
static const char *lben_mux_text[] = { "Normal", "Loopback" };
|
||||
|
||||
static const struct soc_enum lbenl_mux_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LBEN_SHIFT,
|
||||
ARRAY_SIZE(lben_mux_text), lben_mux_text);
|
||||
static SOC_ENUM_SINGLE_DECL(lbenl_mux_enum,
|
||||
M98090_REG_IO_CONFIGURATION,
|
||||
M98090_LBEN_SHIFT,
|
||||
lben_mux_text);
|
||||
|
||||
static const struct soc_enum lbenr_mux_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LBEN_SHIFT,
|
||||
ARRAY_SIZE(lben_mux_text), lben_mux_text);
|
||||
static SOC_ENUM_SINGLE_DECL(lbenr_mux_enum,
|
||||
M98090_REG_IO_CONFIGURATION,
|
||||
M98090_LBEN_SHIFT,
|
||||
lben_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new max98090_lbenl_mux =
|
||||
SOC_DAPM_ENUM("LBENL Mux", lbenl_mux_enum);
|
||||
|
@ -972,13 +989,15 @@ static const char *stenl_mux_text[] = { "Normal", "Sidetone Left" };
|
|||
|
||||
static const char *stenr_mux_text[] = { "Normal", "Sidetone Right" };
|
||||
|
||||
static const struct soc_enum stenl_mux_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_ADC_SIDETONE, M98090_DSTSL_SHIFT,
|
||||
ARRAY_SIZE(stenl_mux_text), stenl_mux_text);
|
||||
static SOC_ENUM_SINGLE_DECL(stenl_mux_enum,
|
||||
M98090_REG_ADC_SIDETONE,
|
||||
M98090_DSTSL_SHIFT,
|
||||
stenl_mux_text);
|
||||
|
||||
static const struct soc_enum stenr_mux_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_ADC_SIDETONE, M98090_DSTSR_SHIFT,
|
||||
ARRAY_SIZE(stenr_mux_text), stenr_mux_text);
|
||||
static SOC_ENUM_SINGLE_DECL(stenr_mux_enum,
|
||||
M98090_REG_ADC_SIDETONE,
|
||||
M98090_DSTSR_SHIFT,
|
||||
stenr_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new max98090_stenl_mux =
|
||||
SOC_DAPM_ENUM("STENL Mux", stenl_mux_enum);
|
||||
|
@ -1086,9 +1105,10 @@ static const struct snd_kcontrol_new max98090_right_rcv_mixer_controls[] = {
|
|||
|
||||
static const char *linmod_mux_text[] = { "Left Only", "Left and Right" };
|
||||
|
||||
static const struct soc_enum linmod_mux_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_LOUTR_MIXER, M98090_LINMOD_SHIFT,
|
||||
ARRAY_SIZE(linmod_mux_text), linmod_mux_text);
|
||||
static SOC_ENUM_SINGLE_DECL(linmod_mux_enum,
|
||||
M98090_REG_LOUTR_MIXER,
|
||||
M98090_LINMOD_SHIFT,
|
||||
linmod_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new max98090_linmod_mux =
|
||||
SOC_DAPM_ENUM("LINMOD Mux", linmod_mux_enum);
|
||||
|
@ -1098,16 +1118,18 @@ static const char *mixhpsel_mux_text[] = { "DAC Only", "HP Mixer" };
|
|||
/*
|
||||
* This is a mux as it selects the HP output, but to DAPM it is a Mixer enable
|
||||
*/
|
||||
static const struct soc_enum mixhplsel_mux_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_HP_CONTROL, M98090_MIXHPLSEL_SHIFT,
|
||||
ARRAY_SIZE(mixhpsel_mux_text), mixhpsel_mux_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mixhplsel_mux_enum,
|
||||
M98090_REG_HP_CONTROL,
|
||||
M98090_MIXHPLSEL_SHIFT,
|
||||
mixhpsel_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new max98090_mixhplsel_mux =
|
||||
SOC_DAPM_ENUM("MIXHPLSEL Mux", mixhplsel_mux_enum);
|
||||
|
||||
static const struct soc_enum mixhprsel_mux_enum =
|
||||
SOC_ENUM_SINGLE(M98090_REG_HP_CONTROL, M98090_MIXHPRSEL_SHIFT,
|
||||
ARRAY_SIZE(mixhpsel_mux_text), mixhpsel_mux_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mixhprsel_mux_enum,
|
||||
M98090_REG_HP_CONTROL,
|
||||
M98090_MIXHPRSEL_SHIFT,
|
||||
mixhpsel_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new max98090_mixhprsel_mux =
|
||||
SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum);
|
||||
|
|
|
@ -1861,7 +1861,7 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec)
|
|||
|
||||
/* Now point the soc_enum to .texts array items */
|
||||
max98095->eq_enum.texts = max98095->eq_texts;
|
||||
max98095->eq_enum.max = max98095->eq_textcnt;
|
||||
max98095->eq_enum.items = max98095->eq_textcnt;
|
||||
|
||||
ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
|
||||
if (ret != 0)
|
||||
|
@ -2016,7 +2016,7 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec)
|
|||
|
||||
/* Now point the soc_enum to .texts array items */
|
||||
max98095->bq_enum.texts = max98095->bq_texts;
|
||||
max98095->bq_enum.max = max98095->bq_textcnt;
|
||||
max98095->bq_enum.items = max98095->bq_textcnt;
|
||||
|
||||
ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
|
||||
if (ret != 0)
|
||||
|
|
|
@ -408,8 +408,7 @@ static const char * const adcl_enum_text[] = {
|
|||
"MC1L", "RXINL",
|
||||
};
|
||||
|
||||
static const struct soc_enum adcl_enum =
|
||||
SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcl_enum_text), adcl_enum_text);
|
||||
static SOC_ENUM_SINGLE_VIRT_DECL(adcl_enum, adcl_enum_text);
|
||||
|
||||
static const struct snd_kcontrol_new left_input_mux =
|
||||
SOC_DAPM_ENUM_VIRT("Route", adcl_enum);
|
||||
|
@ -418,8 +417,7 @@ static const char * const adcr_enum_text[] = {
|
|||
"MC1R", "MC2", "RXINR", "TXIN",
|
||||
};
|
||||
|
||||
static const struct soc_enum adcr_enum =
|
||||
SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcr_enum_text), adcr_enum_text);
|
||||
static SOC_ENUM_SINGLE_VIRT_DECL(adcr_enum, adcr_enum_text);
|
||||
|
||||
static const struct snd_kcontrol_new right_input_mux =
|
||||
SOC_DAPM_ENUM_VIRT("Route", adcr_enum);
|
||||
|
@ -430,8 +428,8 @@ static const struct snd_kcontrol_new samp_ctl =
|
|||
static const char * const speaker_amp_source_text[] = {
|
||||
"CODEC", "Right"
|
||||
};
|
||||
static const SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4,
|
||||
speaker_amp_source_text);
|
||||
static SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4,
|
||||
speaker_amp_source_text);
|
||||
static const struct snd_kcontrol_new speaker_amp_source_mux =
|
||||
SOC_DAPM_ENUM("Speaker Amp Source MUX", speaker_amp_source);
|
||||
|
||||
|
@ -439,8 +437,8 @@ static const char * const headset_amp_source_text[] = {
|
|||
"CODEC", "Mixer"
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11,
|
||||
headset_amp_source_text);
|
||||
static SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11,
|
||||
headset_amp_source_text);
|
||||
static const struct snd_kcontrol_new headset_amp_source_mux =
|
||||
SOC_DAPM_ENUM("Headset Amp Source MUX", headset_amp_source);
|
||||
|
||||
|
@ -580,9 +578,9 @@ static struct snd_soc_dapm_route mc13783_routes[] = {
|
|||
static const char * const mc13783_3d_mixer[] = {"Stereo", "Phase Mix",
|
||||
"Mono", "Mono Mix"};
|
||||
|
||||
static const struct soc_enum mc13783_enum_3d_mixer =
|
||||
SOC_ENUM_SINGLE(MC13783_AUDIO_RX1, 16, ARRAY_SIZE(mc13783_3d_mixer),
|
||||
mc13783_3d_mixer);
|
||||
static SOC_ENUM_SINGLE_DECL(mc13783_enum_3d_mixer,
|
||||
MC13783_AUDIO_RX1, 16,
|
||||
mc13783_3d_mixer);
|
||||
|
||||
static struct snd_kcontrol_new mc13783_control_list[] = {
|
||||
SOC_SINGLE("Loudspeaker enable", MC13783_AUDIO_RX0, 5, 1, 0),
|
||||
|
|
|
@ -73,11 +73,11 @@ static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0);
|
|||
static const char * const ml26124_companding[] = {"16bit PCM", "u-law",
|
||||
"A-law"};
|
||||
|
||||
static const struct soc_enum ml26124_adc_companding_enum
|
||||
= SOC_ENUM_SINGLE(ML26124_SAI_TRANS_CTL, 6, 3, ml26124_companding);
|
||||
static SOC_ENUM_SINGLE_DECL(ml26124_adc_companding_enum,
|
||||
ML26124_SAI_TRANS_CTL, 6, ml26124_companding);
|
||||
|
||||
static const struct soc_enum ml26124_dac_companding_enum
|
||||
= SOC_ENUM_SINGLE(ML26124_SAI_RCV_CTL, 6, 3, ml26124_companding);
|
||||
static SOC_ENUM_SINGLE_DECL(ml26124_dac_companding_enum,
|
||||
ML26124_SAI_RCV_CTL, 6, ml26124_companding);
|
||||
|
||||
static const struct snd_kcontrol_new ml26124_snd_controls[] = {
|
||||
SOC_SINGLE_TLV("Capture Digital Volume", ML26124_RECORD_DIG_VOL, 0,
|
||||
|
@ -136,8 +136,8 @@ static const struct snd_kcontrol_new ml26124_output_mixer_controls[] = {
|
|||
static const char * const ml26124_input_select[] = {"Analog MIC SingleEnded in",
|
||||
"Digital MIC in", "Analog MIC Differential in"};
|
||||
|
||||
static const struct soc_enum ml26124_insel_enum =
|
||||
SOC_ENUM_SINGLE(ML26124_MIC_IF_CTL, 0, 3, ml26124_input_select);
|
||||
static SOC_ENUM_SINGLE_DECL(ml26124_insel_enum,
|
||||
ML26124_MIC_IF_CTL, 0, ml26124_input_select);
|
||||
|
||||
static const struct snd_kcontrol_new ml26124_input_mux_controls =
|
||||
SOC_DAPM_ENUM("Input Select", ml26124_insel_enum);
|
||||
|
|
|
@ -172,16 +172,21 @@ static int pcm1681_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int val = 0, ret;
|
||||
int pcm_format = params_format(params);
|
||||
|
||||
priv->rate = params_rate(params);
|
||||
|
||||
switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
if (pcm_format == SNDRV_PCM_FORMAT_S24_LE)
|
||||
val = 0x00;
|
||||
else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE)
|
||||
val = 0x03;
|
||||
switch (params_width(params)) {
|
||||
case 24:
|
||||
val = 0;
|
||||
break;
|
||||
case 16:
|
||||
val = 3;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
val = 0x04;
|
||||
|
|
|
@ -107,24 +107,35 @@ static int pcm1792a_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int val = 0, ret;
|
||||
int pcm_format = params_format(params);
|
||||
|
||||
priv->rate = params_rate(params);
|
||||
|
||||
switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
if (pcm_format == SNDRV_PCM_FORMAT_S24_LE ||
|
||||
pcm_format == SNDRV_PCM_FORMAT_S32_LE)
|
||||
val = 0x02;
|
||||
else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE)
|
||||
val = 0x00;
|
||||
switch (params_width(params)) {
|
||||
case 24:
|
||||
case 32:
|
||||
val = 2;
|
||||
break;
|
||||
case 16:
|
||||
val = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
if (pcm_format == SNDRV_PCM_FORMAT_S24_LE ||
|
||||
pcm_format == SNDRV_PCM_FORMAT_S32_LE)
|
||||
val = 0x05;
|
||||
else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE)
|
||||
val = 0x04;
|
||||
switch (params_width(params)) {
|
||||
case 24:
|
||||
case 32:
|
||||
val = 5;
|
||||
break;
|
||||
case 16:
|
||||
val = 4;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "Invalid DAI format\n");
|
||||
|
|
71
sound/soc/codecs/pcm512x-i2c.c
Normal file
71
sound/soc/codecs/pcm512x-i2c.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Driver for the PCM512x CODECs
|
||||
*
|
||||
* Author: Mark Brown <broonie@linaro.org>
|
||||
* Copyright 2014 Linaro Ltd
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include "pcm512x.h"
|
||||
|
||||
static int pcm512x_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct regmap *regmap;
|
||||
|
||||
regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
return pcm512x_probe(&i2c->dev, regmap);
|
||||
}
|
||||
|
||||
static int pcm512x_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
pcm512x_remove(&i2c->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id pcm512x_i2c_id[] = {
|
||||
{ "pcm5121", },
|
||||
{ "pcm5122", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id);
|
||||
|
||||
static const struct of_device_id pcm512x_of_match[] = {
|
||||
{ .compatible = "ti,pcm5121", },
|
||||
{ .compatible = "ti,pcm5122", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pcm512x_of_match);
|
||||
|
||||
static struct i2c_driver pcm512x_i2c_driver = {
|
||||
.probe = pcm512x_i2c_probe,
|
||||
.remove = pcm512x_i2c_remove,
|
||||
.id_table = pcm512x_i2c_id,
|
||||
.driver = {
|
||||
.name = "pcm512x",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = pcm512x_of_match,
|
||||
.pm = &pcm512x_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
module_i2c_driver(pcm512x_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC PCM512x codec driver - I2C");
|
||||
MODULE_AUTHOR("Mark Brown <broonie@linaro.org>");
|
||||
MODULE_LICENSE("GPL v2");
|
69
sound/soc/codecs/pcm512x-spi.c
Normal file
69
sound/soc/codecs/pcm512x-spi.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Driver for the PCM512x CODECs
|
||||
*
|
||||
* Author: Mark Brown <broonie@linaro.org>
|
||||
* Copyright 2014 Linaro Ltd
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include "pcm512x.h"
|
||||
|
||||
static int pcm512x_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
regmap = devm_regmap_init_spi(spi, &pcm512x_regmap);
|
||||
if (IS_ERR(regmap)) {
|
||||
ret = PTR_ERR(regmap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return pcm512x_probe(&spi->dev, regmap);
|
||||
}
|
||||
|
||||
static int pcm512x_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
pcm512x_remove(&spi->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id pcm512x_spi_id[] = {
|
||||
{ "pcm5121", },
|
||||
{ "pcm5122", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, pcm512x_spi_id);
|
||||
|
||||
static const struct of_device_id pcm512x_of_match[] = {
|
||||
{ .compatible = "ti,pcm5121", },
|
||||
{ .compatible = "ti,pcm5122", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pcm512x_of_match);
|
||||
|
||||
static struct spi_driver pcm512x_spi_driver = {
|
||||
.probe = pcm512x_spi_probe,
|
||||
.remove = pcm512x_spi_remove,
|
||||
.id_table = pcm512x_spi_id,
|
||||
.driver = {
|
||||
.name = "pcm512x",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = pcm512x_of_match,
|
||||
.pm = &pcm512x_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
module_spi_driver(pcm512x_spi_driver);
|
589
sound/soc/codecs/pcm512x.c
Normal file
589
sound/soc/codecs/pcm512x.c
Normal file
|
@ -0,0 +1,589 @@
|
|||
/*
|
||||
* Driver for the PCM512x CODECs
|
||||
*
|
||||
* Author: Mark Brown <broonie@linaro.org>
|
||||
* Copyright 2014 Linaro Ltd
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "pcm512x.h"
|
||||
|
||||
#define PCM512x_NUM_SUPPLIES 3
|
||||
static const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = {
|
||||
"AVDD",
|
||||
"DVDD",
|
||||
"CPVDD",
|
||||
};
|
||||
|
||||
struct pcm512x_priv {
|
||||
struct regmap *regmap;
|
||||
struct clk *sclk;
|
||||
struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES];
|
||||
struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES];
|
||||
};
|
||||
|
||||
/*
|
||||
* We can't use the same notifier block for more than one supply and
|
||||
* there's no way I can see to get from a callback to the caller
|
||||
* except container_of().
|
||||
*/
|
||||
#define PCM512x_REGULATOR_EVENT(n) \
|
||||
static int pcm512x_regulator_event_##n(struct notifier_block *nb, \
|
||||
unsigned long event, void *data) \
|
||||
{ \
|
||||
struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \
|
||||
supply_nb[n]); \
|
||||
if (event & REGULATOR_EVENT_DISABLE) { \
|
||||
regcache_mark_dirty(pcm512x->regmap); \
|
||||
regcache_cache_only(pcm512x->regmap, true); \
|
||||
} \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
PCM512x_REGULATOR_EVENT(0)
|
||||
PCM512x_REGULATOR_EVENT(1)
|
||||
PCM512x_REGULATOR_EVENT(2)
|
||||
|
||||
static const struct reg_default pcm512x_reg_defaults[] = {
|
||||
{ PCM512x_RESET, 0x00 },
|
||||
{ PCM512x_POWER, 0x00 },
|
||||
{ PCM512x_MUTE, 0x00 },
|
||||
{ PCM512x_DSP, 0x00 },
|
||||
{ PCM512x_PLL_REF, 0x00 },
|
||||
{ PCM512x_DAC_ROUTING, 0x11 },
|
||||
{ PCM512x_DSP_PROGRAM, 0x01 },
|
||||
{ PCM512x_CLKDET, 0x00 },
|
||||
{ PCM512x_AUTO_MUTE, 0x00 },
|
||||
{ PCM512x_ERROR_DETECT, 0x00 },
|
||||
{ PCM512x_DIGITAL_VOLUME_1, 0x00 },
|
||||
{ PCM512x_DIGITAL_VOLUME_2, 0x30 },
|
||||
{ PCM512x_DIGITAL_VOLUME_3, 0x30 },
|
||||
{ PCM512x_DIGITAL_MUTE_1, 0x22 },
|
||||
{ PCM512x_DIGITAL_MUTE_2, 0x00 },
|
||||
{ PCM512x_DIGITAL_MUTE_3, 0x07 },
|
||||
{ PCM512x_OUTPUT_AMPLITUDE, 0x00 },
|
||||
{ PCM512x_ANALOG_GAIN_CTRL, 0x00 },
|
||||
{ PCM512x_UNDERVOLTAGE_PROT, 0x00 },
|
||||
{ PCM512x_ANALOG_MUTE_CTRL, 0x00 },
|
||||
{ PCM512x_ANALOG_GAIN_BOOST, 0x00 },
|
||||
{ PCM512x_VCOM_CTRL_1, 0x00 },
|
||||
{ PCM512x_VCOM_CTRL_2, 0x01 },
|
||||
};
|
||||
|
||||
static bool pcm512x_readable(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case PCM512x_RESET:
|
||||
case PCM512x_POWER:
|
||||
case PCM512x_MUTE:
|
||||
case PCM512x_PLL_EN:
|
||||
case PCM512x_SPI_MISO_FUNCTION:
|
||||
case PCM512x_DSP:
|
||||
case PCM512x_GPIO_EN:
|
||||
case PCM512x_BCLK_LRCLK_CFG:
|
||||
case PCM512x_DSP_GPIO_INPUT:
|
||||
case PCM512x_MASTER_MODE:
|
||||
case PCM512x_PLL_REF:
|
||||
case PCM512x_PLL_COEFF_0:
|
||||
case PCM512x_PLL_COEFF_1:
|
||||
case PCM512x_PLL_COEFF_2:
|
||||
case PCM512x_PLL_COEFF_3:
|
||||
case PCM512x_PLL_COEFF_4:
|
||||
case PCM512x_DSP_CLKDIV:
|
||||
case PCM512x_DAC_CLKDIV:
|
||||
case PCM512x_NCP_CLKDIV:
|
||||
case PCM512x_OSR_CLKDIV:
|
||||
case PCM512x_MASTER_CLKDIV_1:
|
||||
case PCM512x_MASTER_CLKDIV_2:
|
||||
case PCM512x_FS_SPEED_MODE:
|
||||
case PCM512x_IDAC_1:
|
||||
case PCM512x_IDAC_2:
|
||||
case PCM512x_ERROR_DETECT:
|
||||
case PCM512x_I2S_1:
|
||||
case PCM512x_I2S_2:
|
||||
case PCM512x_DAC_ROUTING:
|
||||
case PCM512x_DSP_PROGRAM:
|
||||
case PCM512x_CLKDET:
|
||||
case PCM512x_AUTO_MUTE:
|
||||
case PCM512x_DIGITAL_VOLUME_1:
|
||||
case PCM512x_DIGITAL_VOLUME_2:
|
||||
case PCM512x_DIGITAL_VOLUME_3:
|
||||
case PCM512x_DIGITAL_MUTE_1:
|
||||
case PCM512x_DIGITAL_MUTE_2:
|
||||
case PCM512x_DIGITAL_MUTE_3:
|
||||
case PCM512x_GPIO_OUTPUT_1:
|
||||
case PCM512x_GPIO_OUTPUT_2:
|
||||
case PCM512x_GPIO_OUTPUT_3:
|
||||
case PCM512x_GPIO_OUTPUT_4:
|
||||
case PCM512x_GPIO_OUTPUT_5:
|
||||
case PCM512x_GPIO_OUTPUT_6:
|
||||
case PCM512x_GPIO_CONTROL_1:
|
||||
case PCM512x_GPIO_CONTROL_2:
|
||||
case PCM512x_OVERFLOW:
|
||||
case PCM512x_RATE_DET_1:
|
||||
case PCM512x_RATE_DET_2:
|
||||
case PCM512x_RATE_DET_3:
|
||||
case PCM512x_RATE_DET_4:
|
||||
case PCM512x_ANALOG_MUTE_DET:
|
||||
case PCM512x_GPIN:
|
||||
case PCM512x_DIGITAL_MUTE_DET:
|
||||
case PCM512x_OUTPUT_AMPLITUDE:
|
||||
case PCM512x_ANALOG_GAIN_CTRL:
|
||||
case PCM512x_UNDERVOLTAGE_PROT:
|
||||
case PCM512x_ANALOG_MUTE_CTRL:
|
||||
case PCM512x_ANALOG_GAIN_BOOST:
|
||||
case PCM512x_VCOM_CTRL_1:
|
||||
case PCM512x_VCOM_CTRL_2:
|
||||
case PCM512x_CRAM_CTRL:
|
||||
return true;
|
||||
default:
|
||||
/* There are 256 raw register addresses */
|
||||
return reg < 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
static bool pcm512x_volatile(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case PCM512x_PLL_EN:
|
||||
case PCM512x_OVERFLOW:
|
||||
case PCM512x_RATE_DET_1:
|
||||
case PCM512x_RATE_DET_2:
|
||||
case PCM512x_RATE_DET_3:
|
||||
case PCM512x_RATE_DET_4:
|
||||
case PCM512x_ANALOG_MUTE_DET:
|
||||
case PCM512x_GPIN:
|
||||
case PCM512x_DIGITAL_MUTE_DET:
|
||||
case PCM512x_CRAM_CTRL:
|
||||
return true;
|
||||
default:
|
||||
/* There are 256 raw register addresses */
|
||||
return reg < 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1);
|
||||
static const DECLARE_TLV_DB_SCALE(analog_tlv, -600, 600, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 80, 0);
|
||||
|
||||
static const char * const pcm512x_dsp_program_texts[] = {
|
||||
"FIR interpolation with de-emphasis",
|
||||
"Low latency IIR with de-emphasis",
|
||||
"Fixed process flow",
|
||||
"High attenuation with de-emphasis",
|
||||
"Ringing-less low latency FIR",
|
||||
};
|
||||
|
||||
static const unsigned int pcm512x_dsp_program_values[] = {
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
5,
|
||||
7,
|
||||
};
|
||||
|
||||
static SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program,
|
||||
PCM512x_DSP_PROGRAM, 0, 0x1f,
|
||||
pcm512x_dsp_program_texts,
|
||||
pcm512x_dsp_program_values);
|
||||
|
||||
static const char * const pcm512x_clk_missing_text[] = {
|
||||
"1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s"
|
||||
};
|
||||
|
||||
static const struct soc_enum pcm512x_clk_missing =
|
||||
SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 8, pcm512x_clk_missing_text);
|
||||
|
||||
static const char * const pcm512x_autom_text[] = {
|
||||
"21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s"
|
||||
};
|
||||
|
||||
static const struct soc_enum pcm512x_autom_l =
|
||||
SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 8,
|
||||
pcm512x_autom_text);
|
||||
|
||||
static const struct soc_enum pcm512x_autom_r =
|
||||
SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 8,
|
||||
pcm512x_autom_text);
|
||||
|
||||
static const char * const pcm512x_ramp_rate_text[] = {
|
||||
"1 sample/update", "2 samples/update", "4 samples/update",
|
||||
"Immediate"
|
||||
};
|
||||
|
||||
static const struct soc_enum pcm512x_vndf =
|
||||
SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4,
|
||||
pcm512x_ramp_rate_text);
|
||||
|
||||
static const struct soc_enum pcm512x_vnuf =
|
||||
SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4,
|
||||
pcm512x_ramp_rate_text);
|
||||
|
||||
static const struct soc_enum pcm512x_vedf =
|
||||
SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4,
|
||||
pcm512x_ramp_rate_text);
|
||||
|
||||
static const char * const pcm512x_ramp_step_text[] = {
|
||||
"4dB/step", "2dB/step", "1dB/step", "0.5dB/step"
|
||||
};
|
||||
|
||||
static const struct soc_enum pcm512x_vnds =
|
||||
SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4,
|
||||
pcm512x_ramp_step_text);
|
||||
|
||||
static const struct soc_enum pcm512x_vnus =
|
||||
SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4,
|
||||
pcm512x_ramp_step_text);
|
||||
|
||||
static const struct soc_enum pcm512x_veds =
|
||||
SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4,
|
||||
pcm512x_ramp_step_text);
|
||||
|
||||
static const struct snd_kcontrol_new pcm512x_controls[] = {
|
||||
SOC_DOUBLE_R_TLV("Playback Digital Volume", PCM512x_DIGITAL_VOLUME_2,
|
||||
PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv),
|
||||
SOC_DOUBLE_TLV("Playback Volume", PCM512x_ANALOG_GAIN_CTRL,
|
||||
PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv),
|
||||
SOC_DOUBLE_TLV("Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST,
|
||||
PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv),
|
||||
SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT,
|
||||
PCM512x_RQMR_SHIFT, 1, 1),
|
||||
|
||||
SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1),
|
||||
SOC_VALUE_ENUM("DSP Program", pcm512x_dsp_program),
|
||||
|
||||
SOC_ENUM("Clock Missing Period", pcm512x_clk_missing),
|
||||
SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l),
|
||||
SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r),
|
||||
SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3,
|
||||
PCM512x_ACTL_SHIFT, 1, 0),
|
||||
SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT,
|
||||
PCM512x_AMLR_SHIFT, 1, 0),
|
||||
|
||||
SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf),
|
||||
SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds),
|
||||
SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf),
|
||||
SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus),
|
||||
SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf),
|
||||
SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("OUTL"),
|
||||
SND_SOC_DAPM_OUTPUT("OUTR"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = {
|
||||
{ "DACL", NULL, "Playback" },
|
||||
{ "DACR", NULL, "Playback" },
|
||||
|
||||
{ "OUTL", NULL, "DACL" },
|
||||
{ "OUTR", NULL, "DACR" },
|
||||
};
|
||||
|
||||
static int pcm512x_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
struct pcm512x_priv *pcm512x = dev_get_drvdata(codec->dev);
|
||||
int ret;
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
|
||||
PCM512x_RQST, 0);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to remove standby: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_OFF:
|
||||
ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
|
||||
PCM512x_RQST, PCM512x_RQST);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to request standby: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
codec->dapm.bias_level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_dai_driver pcm512x_dai = {
|
||||
.name = "pcm512x-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_192000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S24_LE |
|
||||
SNDRV_PCM_FMTBIT_S32_LE
|
||||
},
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver pcm512x_codec_driver = {
|
||||
.set_bias_level = pcm512x_set_bias_level,
|
||||
.idle_bias_off = true,
|
||||
|
||||
.controls = pcm512x_controls,
|
||||
.num_controls = ARRAY_SIZE(pcm512x_controls),
|
||||
.dapm_widgets = pcm512x_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets),
|
||||
.dapm_routes = pcm512x_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes),
|
||||
};
|
||||
|
||||
static const struct regmap_range_cfg pcm512x_range = {
|
||||
.name = "Pages", .range_min = PCM512x_VIRT_BASE,
|
||||
.range_max = PCM512x_MAX_REGISTER,
|
||||
.selector_reg = PCM512x_PAGE,
|
||||
.selector_mask = 0xff,
|
||||
.window_start = 0, .window_len = 0x100,
|
||||
};
|
||||
|
||||
const struct regmap_config pcm512x_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
.readable_reg = pcm512x_readable,
|
||||
.volatile_reg = pcm512x_volatile,
|
||||
|
||||
.ranges = &pcm512x_range,
|
||||
.num_ranges = 1,
|
||||
|
||||
.max_register = PCM512x_MAX_REGISTER,
|
||||
.reg_defaults = pcm512x_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults),
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(pcm512x_regmap);
|
||||
|
||||
int pcm512x_probe(struct device *dev, struct regmap *regmap)
|
||||
{
|
||||
struct pcm512x_priv *pcm512x;
|
||||
int i, ret;
|
||||
|
||||
pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL);
|
||||
if (!pcm512x)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(dev, pcm512x);
|
||||
pcm512x->regmap = regmap;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++)
|
||||
pcm512x->supplies[i].supply = pcm512x_supply_names[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies),
|
||||
pcm512x->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to get supplies: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0;
|
||||
pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1;
|
||||
pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) {
|
||||
ret = regulator_register_notifier(pcm512x->supplies[i].consumer,
|
||||
&pcm512x->supply_nb[i]);
|
||||
if (ret != 0) {
|
||||
dev_err(dev,
|
||||
"Failed to register regulator notifier: %d\n",
|
||||
ret);
|
||||
}
|
||||
}
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
|
||||
pcm512x->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to enable supplies: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reset the device, verifying I/O in the process for I2C */
|
||||
ret = regmap_write(regmap, PCM512x_RESET,
|
||||
PCM512x_RSTM | PCM512x_RSTR);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to reset device: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = regmap_write(regmap, PCM512x_RESET, 0);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to reset device: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
pcm512x->sclk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(pcm512x->sclk)) {
|
||||
if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
dev_info(dev, "No SCLK, using BCLK: %ld\n",
|
||||
PTR_ERR(pcm512x->sclk));
|
||||
|
||||
/* Disable reporting of missing SCLK as an error */
|
||||
regmap_update_bits(regmap, PCM512x_ERROR_DETECT,
|
||||
PCM512x_IDCH, PCM512x_IDCH);
|
||||
|
||||
/* Switch PLL input to BCLK */
|
||||
regmap_update_bits(regmap, PCM512x_PLL_REF,
|
||||
PCM512x_SREF, PCM512x_SREF);
|
||||
} else {
|
||||
ret = clk_prepare_enable(pcm512x->sclk);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to enable SCLK: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Default to standby mode */
|
||||
ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
|
||||
PCM512x_RQST, PCM512x_RQST);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to request standby: %d\n",
|
||||
ret);
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_idle(dev);
|
||||
|
||||
ret = snd_soc_register_codec(dev, &pcm512x_codec_driver,
|
||||
&pcm512x_dai, 1);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to register CODEC: %d\n", ret);
|
||||
goto err_pm;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_pm:
|
||||
pm_runtime_disable(dev);
|
||||
err_clk:
|
||||
if (!IS_ERR(pcm512x->sclk))
|
||||
clk_disable_unprepare(pcm512x->sclk);
|
||||
err:
|
||||
regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
|
||||
pcm512x->supplies);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pcm512x_probe);
|
||||
|
||||
void pcm512x_remove(struct device *dev)
|
||||
{
|
||||
struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
|
||||
|
||||
snd_soc_unregister_codec(dev);
|
||||
pm_runtime_disable(dev);
|
||||
if (!IS_ERR(pcm512x->sclk))
|
||||
clk_disable_unprepare(pcm512x->sclk);
|
||||
regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
|
||||
pcm512x->supplies);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pcm512x_remove);
|
||||
|
||||
static int pcm512x_suspend(struct device *dev)
|
||||
{
|
||||
struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
|
||||
PCM512x_RQPD, PCM512x_RQPD);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to request power down: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
|
||||
pcm512x->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to disable supplies: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!IS_ERR(pcm512x->sclk))
|
||||
clk_disable_unprepare(pcm512x->sclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm512x_resume(struct device *dev)
|
||||
{
|
||||
struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
if (!IS_ERR(pcm512x->sclk)) {
|
||||
ret = clk_prepare_enable(pcm512x->sclk);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to enable SCLK: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
|
||||
pcm512x->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to enable supplies: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
regcache_cache_only(pcm512x->regmap, false);
|
||||
ret = regcache_sync(pcm512x->regmap);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to sync cache: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
|
||||
PCM512x_RQPD, 0);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to remove power down: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct dev_pm_ops pcm512x_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL)
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(pcm512x_pm_ops);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC PCM512x codec driver");
|
||||
MODULE_AUTHOR("Mark Brown <broonie@linaro.org>");
|
||||
MODULE_LICENSE("GPL v2");
|
171
sound/soc/codecs/pcm512x.h
Normal file
171
sound/soc/codecs/pcm512x.h
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Driver for the PCM512x CODECs
|
||||
*
|
||||
* Author: Mark Brown <broonie@linaro.org>
|
||||
* Copyright 2014 Linaro Ltd
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 _SND_SOC_PCM512X
|
||||
#define _SND_SOC_PCM512X
|
||||
|
||||
#include <linux/pm.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define PCM512x_VIRT_BASE 0x100
|
||||
#define PCM512x_PAGE_LEN 0x100
|
||||
#define PCM512x_PAGE_BASE(n) (PCM512x_VIRT_BASE + (PCM512x_PAGE_LEN * n))
|
||||
|
||||
#define PCM512x_PAGE 0
|
||||
|
||||
#define PCM512x_RESET (PCM512x_PAGE_BASE(0) + 1)
|
||||
#define PCM512x_POWER (PCM512x_PAGE_BASE(0) + 2)
|
||||
#define PCM512x_MUTE (PCM512x_PAGE_BASE(0) + 3)
|
||||
#define PCM512x_PLL_EN (PCM512x_PAGE_BASE(0) + 4)
|
||||
#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_BASE(0) + 6)
|
||||
#define PCM512x_DSP (PCM512x_PAGE_BASE(0) + 7)
|
||||
#define PCM512x_GPIO_EN (PCM512x_PAGE_BASE(0) + 8)
|
||||
#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_BASE(0) + 9)
|
||||
#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_BASE(0) + 10)
|
||||
#define PCM512x_MASTER_MODE (PCM512x_PAGE_BASE(0) + 12)
|
||||
#define PCM512x_PLL_REF (PCM512x_PAGE_BASE(0) + 13)
|
||||
#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_BASE(0) + 20)
|
||||
#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_BASE(0) + 21)
|
||||
#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_BASE(0) + 22)
|
||||
#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_BASE(0) + 23)
|
||||
#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_BASE(0) + 24)
|
||||
#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_BASE(0) + 27)
|
||||
#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_BASE(0) + 28)
|
||||
#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_BASE(0) + 29)
|
||||
#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_BASE(0) + 30)
|
||||
#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_BASE(0) + 32)
|
||||
#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_BASE(0) + 33)
|
||||
#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_BASE(0) + 34)
|
||||
#define PCM512x_IDAC_1 (PCM512x_PAGE_BASE(0) + 35)
|
||||
#define PCM512x_IDAC_2 (PCM512x_PAGE_BASE(0) + 36)
|
||||
#define PCM512x_ERROR_DETECT (PCM512x_PAGE_BASE(0) + 37)
|
||||
#define PCM512x_I2S_1 (PCM512x_PAGE_BASE(0) + 40)
|
||||
#define PCM512x_I2S_2 (PCM512x_PAGE_BASE(0) + 41)
|
||||
#define PCM512x_DAC_ROUTING (PCM512x_PAGE_BASE(0) + 42)
|
||||
#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_BASE(0) + 43)
|
||||
#define PCM512x_CLKDET (PCM512x_PAGE_BASE(0) + 44)
|
||||
#define PCM512x_AUTO_MUTE (PCM512x_PAGE_BASE(0) + 59)
|
||||
#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_BASE(0) + 60)
|
||||
#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_BASE(0) + 61)
|
||||
#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_BASE(0) + 62)
|
||||
#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_BASE(0) + 63)
|
||||
#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_BASE(0) + 64)
|
||||
#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_BASE(0) + 65)
|
||||
#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_BASE(0) + 80)
|
||||
#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_BASE(0) + 81)
|
||||
#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_BASE(0) + 82)
|
||||
#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_BASE(0) + 83)
|
||||
#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_BASE(0) + 84)
|
||||
#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_BASE(0) + 85)
|
||||
#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_BASE(0) + 86)
|
||||
#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_BASE(0) + 87)
|
||||
#define PCM512x_OVERFLOW (PCM512x_PAGE_BASE(0) + 90)
|
||||
#define PCM512x_RATE_DET_1 (PCM512x_PAGE_BASE(0) + 91)
|
||||
#define PCM512x_RATE_DET_2 (PCM512x_PAGE_BASE(0) + 92)
|
||||
#define PCM512x_RATE_DET_3 (PCM512x_PAGE_BASE(0) + 93)
|
||||
#define PCM512x_RATE_DET_4 (PCM512x_PAGE_BASE(0) + 94)
|
||||
#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_BASE(0) + 108)
|
||||
#define PCM512x_GPIN (PCM512x_PAGE_BASE(0) + 119)
|
||||
#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_BASE(0) + 120)
|
||||
|
||||
#define PCM512x_OUTPUT_AMPLITUDE (PCM512x_PAGE_BASE(1) + 1)
|
||||
#define PCM512x_ANALOG_GAIN_CTRL (PCM512x_PAGE_BASE(1) + 2)
|
||||
#define PCM512x_UNDERVOLTAGE_PROT (PCM512x_PAGE_BASE(1) + 5)
|
||||
#define PCM512x_ANALOG_MUTE_CTRL (PCM512x_PAGE_BASE(1) + 6)
|
||||
#define PCM512x_ANALOG_GAIN_BOOST (PCM512x_PAGE_BASE(1) + 7)
|
||||
#define PCM512x_VCOM_CTRL_1 (PCM512x_PAGE_BASE(1) + 8)
|
||||
#define PCM512x_VCOM_CTRL_2 (PCM512x_PAGE_BASE(1) + 9)
|
||||
|
||||
#define PCM512x_CRAM_CTRL (PCM512x_PAGE_BASE(44) + 1)
|
||||
|
||||
#define PCM512x_MAX_REGISTER (PCM512x_PAGE_BASE(44) + 1)
|
||||
|
||||
/* Page 0, Register 1 - reset */
|
||||
#define PCM512x_RSTR (1 << 0)
|
||||
#define PCM512x_RSTM (1 << 4)
|
||||
|
||||
/* Page 0, Register 2 - power */
|
||||
#define PCM512x_RQPD (1 << 0)
|
||||
#define PCM512x_RQPD_SHIFT 0
|
||||
#define PCM512x_RQST (1 << 4)
|
||||
#define PCM512x_RQST_SHIFT 4
|
||||
|
||||
/* Page 0, Register 3 - mute */
|
||||
#define PCM512x_RQMR_SHIFT 0
|
||||
#define PCM512x_RQML_SHIFT 4
|
||||
|
||||
/* Page 0, Register 4 - PLL */
|
||||
#define PCM512x_PLCE (1 << 0)
|
||||
#define PCM512x_RLCE_SHIFT 0
|
||||
#define PCM512x_PLCK (1 << 4)
|
||||
#define PCM512x_PLCK_SHIFT 4
|
||||
|
||||
/* Page 0, Register 7 - DSP */
|
||||
#define PCM512x_SDSL (1 << 0)
|
||||
#define PCM512x_SDSL_SHIFT 0
|
||||
#define PCM512x_DEMP (1 << 4)
|
||||
#define PCM512x_DEMP_SHIFT 4
|
||||
|
||||
/* Page 0, Register 13 - PLL reference */
|
||||
#define PCM512x_SREF (1 << 4)
|
||||
|
||||
/* Page 0, Register 37 - Error detection */
|
||||
#define PCM512x_IPLK (1 << 0)
|
||||
#define PCM512x_DCAS (1 << 1)
|
||||
#define PCM512x_IDCM (1 << 2)
|
||||
#define PCM512x_IDCH (1 << 3)
|
||||
#define PCM512x_IDSK (1 << 4)
|
||||
#define PCM512x_IDBK (1 << 5)
|
||||
#define PCM512x_IDFS (1 << 6)
|
||||
|
||||
/* Page 0, Register 42 - DAC routing */
|
||||
#define PCM512x_AUPR_SHIFT 0
|
||||
#define PCM512x_AUPL_SHIFT 4
|
||||
|
||||
/* Page 0, Register 59 - auto mute */
|
||||
#define PCM512x_ATMR_SHIFT 0
|
||||
#define PCM512x_ATML_SHIFT 4
|
||||
|
||||
/* Page 0, Register 63 - ramp rates */
|
||||
#define PCM512x_VNDF_SHIFT 6
|
||||
#define PCM512x_VNDS_SHIFT 4
|
||||
#define PCM512x_VNUF_SHIFT 2
|
||||
#define PCM512x_VNUS_SHIFT 0
|
||||
|
||||
/* Page 0, Register 64 - emergency ramp rates */
|
||||
#define PCM512x_VEDF_SHIFT 6
|
||||
#define PCM512x_VEDS_SHIFT 4
|
||||
|
||||
/* Page 0, Register 65 - Digital mute enables */
|
||||
#define PCM512x_ACTL_SHIFT 2
|
||||
#define PCM512x_AMLE_SHIFT 1
|
||||
#define PCM512x_AMLR_SHIFT 0
|
||||
|
||||
/* Page 1, Register 2 - analog volume control */
|
||||
#define PCM512x_RAGN_SHIFT 0
|
||||
#define PCM512x_LAGN_SHIFT 4
|
||||
|
||||
/* Page 1, Register 7 - analog boost control */
|
||||
#define PCM512x_AGBR_SHIFT 0
|
||||
#define PCM512x_AGBL_SHIFT 4
|
||||
|
||||
extern const struct dev_pm_ops pcm512x_pm_ops;
|
||||
extern const struct regmap_config pcm512x_regmap;
|
||||
|
||||
int pcm512x_probe(struct device *dev, struct regmap *regmap);
|
||||
void pcm512x_remove(struct device *dev);
|
||||
|
||||
#endif
|
|
@ -210,26 +210,22 @@ static int rt5631_dmic_put(struct snd_kcontrol *kcontrol,
|
|||
static const char *rt5631_input_mode[] = {
|
||||
"Single ended", "Differential"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1,
|
||||
RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1,
|
||||
RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode);
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1,
|
||||
RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1,
|
||||
RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode);
|
||||
|
||||
/* MONO Input Type */
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL,
|
||||
RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL,
|
||||
RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode);
|
||||
|
||||
/* SPK Ratio Gain Control */
|
||||
static const char *rt5631_spk_ratio[] = {"1.00x", "1.09x", "1.27x", "1.44x",
|
||||
"1.56x", "1.68x", "1.99x", "2.34x"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG,
|
||||
RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG,
|
||||
RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio);
|
||||
|
||||
static const struct snd_kcontrol_new rt5631_snd_controls[] = {
|
||||
/* MIC */
|
||||
|
@ -759,9 +755,8 @@ static const struct snd_kcontrol_new rt5631_monomix_mixer_controls[] = {
|
|||
/* Left SPK Volume Input */
|
||||
static const char *rt5631_spkvoll_sel[] = {"Vmid", "SPKMIXL"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL,
|
||||
RT5631_L_EN_SHIFT, rt5631_spkvoll_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL,
|
||||
RT5631_L_EN_SHIFT, rt5631_spkvoll_sel);
|
||||
|
||||
static const struct snd_kcontrol_new rt5631_spkvoll_mux_control =
|
||||
SOC_DAPM_ENUM("Left SPKVOL SRC", rt5631_spkvoll_enum);
|
||||
|
@ -769,9 +764,8 @@ static const struct snd_kcontrol_new rt5631_spkvoll_mux_control =
|
|||
/* Left HP Volume Input */
|
||||
static const char *rt5631_hpvoll_sel[] = {"Vmid", "OUTMIXL"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_hpvoll_enum, RT5631_HP_OUT_VOL,
|
||||
RT5631_L_EN_SHIFT, rt5631_hpvoll_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_hpvoll_enum, RT5631_HP_OUT_VOL,
|
||||
RT5631_L_EN_SHIFT, rt5631_hpvoll_sel);
|
||||
|
||||
static const struct snd_kcontrol_new rt5631_hpvoll_mux_control =
|
||||
SOC_DAPM_ENUM("Left HPVOL SRC", rt5631_hpvoll_enum);
|
||||
|
@ -779,9 +773,8 @@ static const struct snd_kcontrol_new rt5631_hpvoll_mux_control =
|
|||
/* Left Out Volume Input */
|
||||
static const char *rt5631_outvoll_sel[] = {"Vmid", "OUTMIXL"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL,
|
||||
RT5631_L_EN_SHIFT, rt5631_outvoll_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL,
|
||||
RT5631_L_EN_SHIFT, rt5631_outvoll_sel);
|
||||
|
||||
static const struct snd_kcontrol_new rt5631_outvoll_mux_control =
|
||||
SOC_DAPM_ENUM("Left OUTVOL SRC", rt5631_outvoll_enum);
|
||||
|
@ -789,9 +782,8 @@ static const struct snd_kcontrol_new rt5631_outvoll_mux_control =
|
|||
/* Right Out Volume Input */
|
||||
static const char *rt5631_outvolr_sel[] = {"Vmid", "OUTMIXR"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL,
|
||||
RT5631_R_EN_SHIFT, rt5631_outvolr_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL,
|
||||
RT5631_R_EN_SHIFT, rt5631_outvolr_sel);
|
||||
|
||||
static const struct snd_kcontrol_new rt5631_outvolr_mux_control =
|
||||
SOC_DAPM_ENUM("Right OUTVOL SRC", rt5631_outvolr_enum);
|
||||
|
@ -799,9 +791,8 @@ static const struct snd_kcontrol_new rt5631_outvolr_mux_control =
|
|||
/* Right HP Volume Input */
|
||||
static const char *rt5631_hpvolr_sel[] = {"Vmid", "OUTMIXR"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_hpvolr_enum, RT5631_HP_OUT_VOL,
|
||||
RT5631_R_EN_SHIFT, rt5631_hpvolr_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_hpvolr_enum, RT5631_HP_OUT_VOL,
|
||||
RT5631_R_EN_SHIFT, rt5631_hpvolr_sel);
|
||||
|
||||
static const struct snd_kcontrol_new rt5631_hpvolr_mux_control =
|
||||
SOC_DAPM_ENUM("Right HPVOL SRC", rt5631_hpvolr_enum);
|
||||
|
@ -809,9 +800,8 @@ static const struct snd_kcontrol_new rt5631_hpvolr_mux_control =
|
|||
/* Right SPK Volume Input */
|
||||
static const char *rt5631_spkvolr_sel[] = {"Vmid", "SPKMIXR"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL,
|
||||
RT5631_R_EN_SHIFT, rt5631_spkvolr_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL,
|
||||
RT5631_R_EN_SHIFT, rt5631_spkvolr_sel);
|
||||
|
||||
static const struct snd_kcontrol_new rt5631_spkvolr_mux_control =
|
||||
SOC_DAPM_ENUM("Right SPKVOL SRC", rt5631_spkvolr_enum);
|
||||
|
@ -820,9 +810,8 @@ static const struct snd_kcontrol_new rt5631_spkvolr_mux_control =
|
|||
static const char *rt5631_spol_src_sel[] = {
|
||||
"SPOLMIX", "MONOIN_RX", "VDAC", "DACL"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
|
||||
RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
|
||||
RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel);
|
||||
|
||||
static const struct snd_kcontrol_new rt5631_spol_mux_control =
|
||||
SOC_DAPM_ENUM("SPOL SRC", rt5631_spol_src_enum);
|
||||
|
@ -831,9 +820,8 @@ static const struct snd_kcontrol_new rt5631_spol_mux_control =
|
|||
static const char *rt5631_spor_src_sel[] = {
|
||||
"SPORMIX", "MONOIN_RX", "VDAC", "DACR"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
|
||||
RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
|
||||
RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel);
|
||||
|
||||
static const struct snd_kcontrol_new rt5631_spor_mux_control =
|
||||
SOC_DAPM_ENUM("SPOR SRC", rt5631_spor_src_enum);
|
||||
|
@ -841,9 +829,8 @@ static const struct snd_kcontrol_new rt5631_spor_mux_control =
|
|||
/* MONO Input */
|
||||
static const char *rt5631_mono_src_sel[] = {"MONOMIX", "MONOIN_RX", "VDAC"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
|
||||
RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
|
||||
RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel);
|
||||
|
||||
static const struct snd_kcontrol_new rt5631_mono_mux_control =
|
||||
SOC_DAPM_ENUM("MONO SRC", rt5631_mono_src_enum);
|
||||
|
@ -851,9 +838,8 @@ static const struct snd_kcontrol_new rt5631_mono_mux_control =
|
|||
/* Left HPO Input */
|
||||
static const char *rt5631_hpl_src_sel[] = {"Left HPVOL", "Left DAC"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
|
||||
RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
|
||||
RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel);
|
||||
|
||||
static const struct snd_kcontrol_new rt5631_hpl_mux_control =
|
||||
SOC_DAPM_ENUM("HPL SRC", rt5631_hpl_src_enum);
|
||||
|
@ -861,9 +847,8 @@ static const struct snd_kcontrol_new rt5631_hpl_mux_control =
|
|||
/* Right HPO Input */
|
||||
static const char *rt5631_hpr_src_sel[] = {"Right HPVOL", "Right DAC"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
|
||||
RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
|
||||
RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel);
|
||||
|
||||
static const struct snd_kcontrol_new rt5631_hpr_mux_control =
|
||||
SOC_DAPM_ENUM("HPR SRC", rt5631_hpr_src_enum);
|
||||
|
|
|
@ -361,25 +361,24 @@ static unsigned int bst_tlv[] = {
|
|||
static const char * const rt5640_data_select[] = {
|
||||
"Normal", "left copy to right", "right copy to left", "Swap"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA,
|
||||
RT5640_IF1_DAC_SEL_SFT, rt5640_data_select);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA,
|
||||
RT5640_IF1_DAC_SEL_SFT, rt5640_data_select);
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA,
|
||||
RT5640_IF1_ADC_SEL_SFT, rt5640_data_select);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA,
|
||||
RT5640_IF1_ADC_SEL_SFT, rt5640_data_select);
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA,
|
||||
RT5640_IF2_DAC_SEL_SFT, rt5640_data_select);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA,
|
||||
RT5640_IF2_DAC_SEL_SFT, rt5640_data_select);
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA,
|
||||
RT5640_IF2_ADC_SEL_SFT, rt5640_data_select);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA,
|
||||
RT5640_IF2_ADC_SEL_SFT, rt5640_data_select);
|
||||
|
||||
/* Class D speaker gain ratio */
|
||||
static const char * const rt5640_clsd_spk_ratio[] = {"1.66x", "1.83x", "1.94x",
|
||||
"2x", "2.11x", "2.22x", "2.33x", "2.44x", "2.55x", "2.66x", "2.77x"};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT,
|
||||
RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT,
|
||||
RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio);
|
||||
|
||||
static const struct snd_kcontrol_new rt5640_snd_controls[] = {
|
||||
/* Speaker Output Volume */
|
||||
|
@ -753,9 +752,8 @@ static const char * const rt5640_stereo_adc1_src[] = {
|
|||
"DIG MIX", "ADC"
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER,
|
||||
RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER,
|
||||
RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5640_sto_adc_1_mux =
|
||||
SOC_DAPM_ENUM("Stereo ADC1 Mux", rt5640_stereo_adc1_enum);
|
||||
|
@ -764,9 +762,8 @@ static const char * const rt5640_stereo_adc2_src[] = {
|
|||
"DMIC1", "DMIC2", "DIG MIX"
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER,
|
||||
RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER,
|
||||
RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5640_sto_adc_2_mux =
|
||||
SOC_DAPM_ENUM("Stereo ADC2 Mux", rt5640_stereo_adc2_enum);
|
||||
|
@ -776,9 +773,8 @@ static const char * const rt5640_mono_adc_l1_src[] = {
|
|||
"Mono DAC MIXL", "ADCL"
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER,
|
||||
RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER,
|
||||
RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5640_mono_adc_l1_mux =
|
||||
SOC_DAPM_ENUM("Mono ADC1 left source", rt5640_mono_adc_l1_enum);
|
||||
|
@ -787,9 +783,8 @@ static const char * const rt5640_mono_adc_l2_src[] = {
|
|||
"DMIC L1", "DMIC L2", "Mono DAC MIXL"
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER,
|
||||
RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER,
|
||||
RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5640_mono_adc_l2_mux =
|
||||
SOC_DAPM_ENUM("Mono ADC2 left source", rt5640_mono_adc_l2_enum);
|
||||
|
@ -798,9 +793,8 @@ static const char * const rt5640_mono_adc_r1_src[] = {
|
|||
"Mono DAC MIXR", "ADCR"
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER,
|
||||
RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER,
|
||||
RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5640_mono_adc_r1_mux =
|
||||
SOC_DAPM_ENUM("Mono ADC1 right source", rt5640_mono_adc_r1_enum);
|
||||
|
@ -809,9 +803,8 @@ static const char * const rt5640_mono_adc_r2_src[] = {
|
|||
"DMIC R1", "DMIC R2", "Mono DAC MIXR"
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER,
|
||||
RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER,
|
||||
RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5640_mono_adc_r2_mux =
|
||||
SOC_DAPM_ENUM("Mono ADC2 right source", rt5640_mono_adc_r2_enum);
|
||||
|
@ -826,9 +819,9 @@ static int rt5640_dac_l2_values[] = {
|
|||
3,
|
||||
};
|
||||
|
||||
static const SOC_VALUE_ENUM_SINGLE_DECL(
|
||||
rt5640_dac_l2_enum, RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT,
|
||||
0x3, rt5640_dac_l2_src, rt5640_dac_l2_values);
|
||||
static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dac_l2_enum,
|
||||
RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT,
|
||||
0x3, rt5640_dac_l2_src, rt5640_dac_l2_values);
|
||||
|
||||
static const struct snd_kcontrol_new rt5640_dac_l2_mux =
|
||||
SOC_DAPM_VALUE_ENUM("DAC2 left channel source", rt5640_dac_l2_enum);
|
||||
|
@ -841,9 +834,9 @@ static int rt5640_dac_r2_values[] = {
|
|||
0,
|
||||
};
|
||||
|
||||
static const SOC_VALUE_ENUM_SINGLE_DECL(
|
||||
rt5640_dac_r2_enum, RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT,
|
||||
0x3, rt5640_dac_r2_src, rt5640_dac_r2_values);
|
||||
static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dac_r2_enum,
|
||||
RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT,
|
||||
0x3, rt5640_dac_r2_src, rt5640_dac_r2_values);
|
||||
|
||||
static const struct snd_kcontrol_new rt5640_dac_r2_mux =
|
||||
SOC_DAPM_ENUM("DAC2 right channel source", rt5640_dac_r2_enum);
|
||||
|
@ -860,9 +853,10 @@ static int rt5640_dai_iis_map_values[] = {
|
|||
7,
|
||||
};
|
||||
|
||||
static const SOC_VALUE_ENUM_SINGLE_DECL(
|
||||
rt5640_dai_iis_map_enum, RT5640_I2S1_SDP, RT5640_I2S_IF_SFT,
|
||||
0x7, rt5640_dai_iis_map, rt5640_dai_iis_map_values);
|
||||
static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dai_iis_map_enum,
|
||||
RT5640_I2S1_SDP, RT5640_I2S_IF_SFT,
|
||||
0x7, rt5640_dai_iis_map,
|
||||
rt5640_dai_iis_map_values);
|
||||
|
||||
static const struct snd_kcontrol_new rt5640_dai_mux =
|
||||
SOC_DAPM_VALUE_ENUM("DAI select", rt5640_dai_iis_map_enum);
|
||||
|
@ -872,9 +866,8 @@ static const char * const rt5640_sdi_sel[] = {
|
|||
"IF1", "IF2"
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5640_sdi_sel_enum, RT5640_I2S2_SDP,
|
||||
RT5640_I2S2_SDI_SFT, rt5640_sdi_sel);
|
||||
static SOC_ENUM_SINGLE_DECL(rt5640_sdi_sel_enum, RT5640_I2S2_SDP,
|
||||
RT5640_I2S2_SDI_SFT, rt5640_sdi_sel);
|
||||
|
||||
static const struct snd_kcontrol_new rt5640_sdi_mux =
|
||||
SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum);
|
||||
|
|
|
@ -187,8 +187,9 @@ static const char *adc_mux_text[] = {
|
|||
"MIC_IN", "LINE_IN"
|
||||
};
|
||||
|
||||
static const struct soc_enum adc_enum =
|
||||
SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 2, 2, adc_mux_text);
|
||||
static SOC_ENUM_SINGLE_DECL(adc_enum,
|
||||
SGTL5000_CHIP_ANA_CTRL, 2,
|
||||
adc_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new adc_mux =
|
||||
SOC_DAPM_ENUM("Capture Mux", adc_enum);
|
||||
|
@ -198,8 +199,9 @@ static const char *dac_mux_text[] = {
|
|||
"DAC", "LINE_IN"
|
||||
};
|
||||
|
||||
static const struct soc_enum dac_enum =
|
||||
SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 6, 2, dac_mux_text);
|
||||
static SOC_ENUM_SINGLE_DECL(dac_enum,
|
||||
SGTL5000_CHIP_ANA_CTRL, 6,
|
||||
dac_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new dac_mux =
|
||||
SOC_DAPM_ENUM("Headphone Mux", dac_enum);
|
||||
|
|
533
sound/soc/codecs/sirf-audio-codec.c
Normal file
533
sound/soc/codecs/sirf-audio-codec.c
Normal file
|
@ -0,0 +1,533 @@
|
|||
/*
|
||||
* SiRF audio codec driver
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/dmaengine_pcm.h>
|
||||
|
||||
#include "sirf-audio-codec.h"
|
||||
|
||||
struct sirf_audio_codec {
|
||||
struct clk *clk;
|
||||
struct regmap *regmap;
|
||||
u32 reg_ctrl0, reg_ctrl1;
|
||||
};
|
||||
|
||||
static const char * const input_mode_mux[] = {"Single-ended",
|
||||
"Differential"};
|
||||
|
||||
static const struct soc_enum input_mode_mux_enum =
|
||||
SOC_ENUM_SINGLE(AUDIO_IC_CODEC_CTRL1, 4, 2, input_mode_mux);
|
||||
|
||||
static const struct snd_kcontrol_new sirf_audio_codec_input_mode_control =
|
||||
SOC_DAPM_ENUM("Route", input_mode_mux_enum);
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -12400, 100, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(capture_vol_tlv_prima2, 500, 100, 0);
|
||||
static const DECLARE_TLV_DB_RANGE(capture_vol_tlv_atlas6,
|
||||
0, 7, TLV_DB_SCALE_ITEM(-100, 100, 0),
|
||||
0x22, 0x3F, TLV_DB_SCALE_ITEM(700, 100, 0),
|
||||
);
|
||||
|
||||
static struct snd_kcontrol_new volume_controls_atlas6[] = {
|
||||
SOC_DOUBLE_TLV("Playback Volume", AUDIO_IC_CODEC_CTRL0, 21, 14,
|
||||
0x7F, 0, playback_vol_tlv),
|
||||
SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 16, 10,
|
||||
0x3F, 0, capture_vol_tlv_atlas6),
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new volume_controls_prima2[] = {
|
||||
SOC_DOUBLE_TLV("Speaker Volume", AUDIO_IC_CODEC_CTRL0, 21, 14,
|
||||
0x7F, 0, playback_vol_tlv),
|
||||
SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 15, 10,
|
||||
0x1F, 0, capture_vol_tlv_prima2),
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new left_input_path_controls[] = {
|
||||
SOC_DAPM_SINGLE("Line Left Switch", AUDIO_IC_CODEC_CTRL1, 6, 1, 0),
|
||||
SOC_DAPM_SINGLE("Mic Left Switch", AUDIO_IC_CODEC_CTRL1, 3, 1, 0),
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new right_input_path_controls[] = {
|
||||
SOC_DAPM_SINGLE("Line Right Switch", AUDIO_IC_CODEC_CTRL1, 5, 1, 0),
|
||||
SOC_DAPM_SINGLE("Mic Right Switch", AUDIO_IC_CODEC_CTRL1, 2, 1, 0),
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new left_dac_to_hp_left_amp_switch_control =
|
||||
SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 9, 1, 0);
|
||||
|
||||
static struct snd_kcontrol_new left_dac_to_hp_right_amp_switch_control =
|
||||
SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 8, 1, 0);
|
||||
|
||||
static struct snd_kcontrol_new right_dac_to_hp_left_amp_switch_control =
|
||||
SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 7, 1, 0);
|
||||
|
||||
static struct snd_kcontrol_new right_dac_to_hp_right_amp_switch_control =
|
||||
SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 6, 1, 0);
|
||||
|
||||
static struct snd_kcontrol_new left_dac_to_speaker_lineout_switch_control =
|
||||
SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 11, 1, 0);
|
||||
|
||||
static struct snd_kcontrol_new right_dac_to_speaker_lineout_switch_control =
|
||||
SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 10, 1, 0);
|
||||
|
||||
/* After enable adc, Delay 200ms to avoid pop noise */
|
||||
static int adc_enable_delay_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
msleep(200);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void enable_and_reset_codec(struct regmap *regmap,
|
||||
u32 codec_enable_bits, u32 codec_reset_bits)
|
||||
{
|
||||
regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1,
|
||||
codec_enable_bits | codec_reset_bits,
|
||||
codec_enable_bits | ~codec_reset_bits);
|
||||
msleep(20);
|
||||
regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1,
|
||||
codec_reset_bits, codec_reset_bits);
|
||||
}
|
||||
|
||||
static int atlas6_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
#define ATLAS6_CODEC_ENABLE_BITS (1 << 29)
|
||||
#define ATLAS6_CODEC_RESET_BITS (1 << 28)
|
||||
struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev);
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
enable_and_reset_codec(sirf_audio_codec->regmap,
|
||||
ATLAS6_CODEC_ENABLE_BITS, ATLAS6_CODEC_RESET_BITS);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
regmap_update_bits(sirf_audio_codec->regmap,
|
||||
AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS,
|
||||
~ATLAS6_CODEC_ENABLE_BITS);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prima2_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
#define PRIMA2_CODEC_ENABLE_BITS (1 << 27)
|
||||
#define PRIMA2_CODEC_RESET_BITS (1 << 26)
|
||||
struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev);
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
enable_and_reset_codec(sirf_audio_codec->regmap,
|
||||
PRIMA2_CODEC_ENABLE_BITS, PRIMA2_CODEC_RESET_BITS);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
regmap_update_bits(sirf_audio_codec->regmap,
|
||||
AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS,
|
||||
~PRIMA2_CODEC_ENABLE_BITS);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget atlas6_output_driver_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
|
||||
25, 0, NULL, 0),
|
||||
SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
|
||||
26, 0, NULL, 0),
|
||||
SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
|
||||
27, 0, NULL, 0),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget prima2_output_driver_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
|
||||
23, 0, NULL, 0),
|
||||
SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
|
||||
24, 0, NULL, 0),
|
||||
SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
|
||||
25, 0, NULL, 0),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget atlas6_codec_clock_dapm_widget =
|
||||
SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
|
||||
atlas6_codec_enable_and_reset_event,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
|
||||
|
||||
static const struct snd_soc_dapm_widget prima2_codec_clock_dapm_widget =
|
||||
SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
|
||||
prima2_codec_enable_and_reset_event,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
|
||||
|
||||
static const struct snd_soc_dapm_widget sirf_audio_codec_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_DAC("DAC left", NULL, AUDIO_IC_CODEC_CTRL0, 1, 0),
|
||||
SND_SOC_DAPM_DAC("DAC right", NULL, AUDIO_IC_CODEC_CTRL0, 0, 0),
|
||||
SND_SOC_DAPM_SWITCH("Left dac to hp left amp", SND_SOC_NOPM, 0, 0,
|
||||
&left_dac_to_hp_left_amp_switch_control),
|
||||
SND_SOC_DAPM_SWITCH("Left dac to hp right amp", SND_SOC_NOPM, 0, 0,
|
||||
&left_dac_to_hp_right_amp_switch_control),
|
||||
SND_SOC_DAPM_SWITCH("Right dac to hp left amp", SND_SOC_NOPM, 0, 0,
|
||||
&right_dac_to_hp_left_amp_switch_control),
|
||||
SND_SOC_DAPM_SWITCH("Right dac to hp right amp", SND_SOC_NOPM, 0, 0,
|
||||
&right_dac_to_hp_right_amp_switch_control),
|
||||
SND_SOC_DAPM_OUT_DRV("HP amp left driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
|
||||
NULL, 0),
|
||||
SND_SOC_DAPM_OUT_DRV("HP amp right driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
|
||||
NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_SWITCH("Left dac to speaker lineout", SND_SOC_NOPM, 0, 0,
|
||||
&left_dac_to_speaker_lineout_switch_control),
|
||||
SND_SOC_DAPM_SWITCH("Right dac to speaker lineout", SND_SOC_NOPM, 0, 0,
|
||||
&right_dac_to_speaker_lineout_switch_control),
|
||||
SND_SOC_DAPM_OUT_DRV("Speaker amp driver", AUDIO_IC_CODEC_CTRL0, 4, 0,
|
||||
NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("HPOUTL"),
|
||||
SND_SOC_DAPM_OUTPUT("HPOUTR"),
|
||||
SND_SOC_DAPM_OUTPUT("SPKOUT"),
|
||||
|
||||
SND_SOC_DAPM_ADC_E("ADC left", NULL, AUDIO_IC_CODEC_CTRL1, 8, 0,
|
||||
adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
|
||||
SND_SOC_DAPM_ADC_E("ADC right", NULL, AUDIO_IC_CODEC_CTRL1, 7, 0,
|
||||
adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
|
||||
SND_SOC_DAPM_MIXER("Left PGA mixer", AUDIO_IC_CODEC_CTRL1, 1, 0,
|
||||
&left_input_path_controls[0],
|
||||
ARRAY_SIZE(left_input_path_controls)),
|
||||
SND_SOC_DAPM_MIXER("Right PGA mixer", AUDIO_IC_CODEC_CTRL1, 0, 0,
|
||||
&right_input_path_controls[0],
|
||||
ARRAY_SIZE(right_input_path_controls)),
|
||||
|
||||
SND_SOC_DAPM_MUX("Mic input mode mux", SND_SOC_NOPM, 0, 0,
|
||||
&sirf_audio_codec_input_mode_control),
|
||||
SND_SOC_DAPM_MICBIAS("Mic Bias", AUDIO_IC_CODEC_PWR, 3, 0),
|
||||
SND_SOC_DAPM_INPUT("MICIN1"),
|
||||
SND_SOC_DAPM_INPUT("MICIN2"),
|
||||
SND_SOC_DAPM_INPUT("LINEIN1"),
|
||||
SND_SOC_DAPM_INPUT("LINEIN2"),
|
||||
|
||||
SND_SOC_DAPM_SUPPLY("HSL Phase Opposite", AUDIO_IC_CODEC_CTRL0,
|
||||
30, 0, NULL, 0),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route sirf_audio_codec_map[] = {
|
||||
{"SPKOUT", NULL, "Speaker Driver"},
|
||||
{"Speaker Driver", NULL, "Speaker amp driver"},
|
||||
{"Speaker amp driver", NULL, "Left dac to speaker lineout"},
|
||||
{"Speaker amp driver", NULL, "Right dac to speaker lineout"},
|
||||
{"Left dac to speaker lineout", "Switch", "DAC left"},
|
||||
{"Right dac to speaker lineout", "Switch", "DAC right"},
|
||||
{"HPOUTL", NULL, "HP Left Driver"},
|
||||
{"HPOUTR", NULL, "HP Right Driver"},
|
||||
{"HP Left Driver", NULL, "HP amp left driver"},
|
||||
{"HP Right Driver", NULL, "HP amp right driver"},
|
||||
{"HP amp left driver", NULL, "Right dac to hp left amp"},
|
||||
{"HP amp right driver", NULL , "Right dac to hp right amp"},
|
||||
{"HP amp left driver", NULL, "Left dac to hp left amp"},
|
||||
{"HP amp right driver", NULL , "Right dac to hp right amp"},
|
||||
{"Right dac to hp left amp", "Switch", "DAC left"},
|
||||
{"Right dac to hp right amp", "Switch", "DAC right"},
|
||||
{"Left dac to hp left amp", "Switch", "DAC left"},
|
||||
{"Left dac to hp right amp", "Switch", "DAC right"},
|
||||
{"DAC left", NULL, "codecclk"},
|
||||
{"DAC right", NULL, "codecclk"},
|
||||
{"DAC left", NULL, "Playback"},
|
||||
{"DAC right", NULL, "Playback"},
|
||||
{"DAC left", NULL, "HSL Phase Opposite"},
|
||||
{"DAC right", NULL, "HSL Phase Opposite"},
|
||||
|
||||
{"Capture", NULL, "ADC left"},
|
||||
{"Capture", NULL, "ADC right"},
|
||||
{"ADC left", NULL, "codecclk"},
|
||||
{"ADC right", NULL, "codecclk"},
|
||||
{"ADC left", NULL, "Left PGA mixer"},
|
||||
{"ADC right", NULL, "Right PGA mixer"},
|
||||
{"Left PGA mixer", "Line Left Switch", "LINEIN2"},
|
||||
{"Right PGA mixer", "Line Right Switch", "LINEIN1"},
|
||||
{"Left PGA mixer", "Mic Left Switch", "MICIN2"},
|
||||
{"Right PGA mixer", "Mic Right Switch", "Mic input mode mux"},
|
||||
{"Mic input mode mux", "Single-ended", "MICIN1"},
|
||||
{"Mic input mode mux", "Differential", "MICIN1"},
|
||||
};
|
||||
|
||||
static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream,
|
||||
int cmd,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
u32 val = 0;
|
||||
|
||||
/*
|
||||
* This is a workaround, When stop playback,
|
||||
* need disable HP amp, avoid the current noise.
|
||||
*/
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
if (playback)
|
||||
val = IC_HSLEN | IC_HSREN;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (playback)
|
||||
snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0,
|
||||
IC_HSLEN | IC_HSREN, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_dai_ops sirf_audio_codec_dai_ops = {
|
||||
.trigger = sirf_audio_codec_trigger,
|
||||
};
|
||||
|
||||
struct snd_soc_dai_driver sirf_audio_codec_dai = {
|
||||
.name = "sirf-audio-codec",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_48000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_48000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
},
|
||||
.ops = &sirf_audio_codec_dai_ops,
|
||||
};
|
||||
|
||||
static int sirf_audio_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
int ret;
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
pm_runtime_enable(codec->dev);
|
||||
codec->control_data = sirf_audio_codec->regmap;
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) {
|
||||
snd_soc_dapm_new_controls(dapm,
|
||||
prima2_output_driver_dapm_widgets,
|
||||
ARRAY_SIZE(prima2_output_driver_dapm_widgets));
|
||||
snd_soc_dapm_new_controls(dapm,
|
||||
&prima2_codec_clock_dapm_widget, 1);
|
||||
return snd_soc_add_codec_controls(codec,
|
||||
volume_controls_prima2,
|
||||
ARRAY_SIZE(volume_controls_prima2));
|
||||
}
|
||||
if (of_device_is_compatible(codec->dev->of_node, "sirf,atlas6-audio-codec")) {
|
||||
snd_soc_dapm_new_controls(dapm,
|
||||
atlas6_output_driver_dapm_widgets,
|
||||
ARRAY_SIZE(atlas6_output_driver_dapm_widgets));
|
||||
snd_soc_dapm_new_controls(dapm,
|
||||
&atlas6_codec_clock_dapm_widget, 1);
|
||||
return snd_soc_add_codec_controls(codec,
|
||||
volume_controls_atlas6,
|
||||
ARRAY_SIZE(volume_controls_atlas6));
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int sirf_audio_codec_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
pm_runtime_disable(codec->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_device_sirf_audio_codec = {
|
||||
.probe = sirf_audio_codec_probe,
|
||||
.remove = sirf_audio_codec_remove,
|
||||
.dapm_widgets = sirf_audio_codec_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(sirf_audio_codec_dapm_widgets),
|
||||
.dapm_routes = sirf_audio_codec_map,
|
||||
.num_dapm_routes = ARRAY_SIZE(sirf_audio_codec_map),
|
||||
.idle_bias_off = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id sirf_audio_codec_of_match[] = {
|
||||
{ .compatible = "sirf,prima2-audio-codec" },
|
||||
{ .compatible = "sirf,atlas6-audio-codec" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match);
|
||||
|
||||
static const struct regmap_config sirf_audio_codec_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.val_bits = 32,
|
||||
.max_register = AUDIO_IC_CODEC_CTRL3,
|
||||
.cache_type = REGCACHE_NONE,
|
||||
};
|
||||
|
||||
static int sirf_audio_codec_driver_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct sirf_audio_codec *sirf_audio_codec;
|
||||
void __iomem *base;
|
||||
struct resource *mem_res;
|
||||
const struct of_device_id *match;
|
||||
|
||||
match = of_match_node(sirf_audio_codec_of_match, pdev->dev.of_node);
|
||||
|
||||
sirf_audio_codec = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct sirf_audio_codec), GFP_KERNEL);
|
||||
if (!sirf_audio_codec)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, sirf_audio_codec);
|
||||
|
||||
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, mem_res);
|
||||
if (base == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
|
||||
&sirf_audio_codec_regmap_config);
|
||||
if (IS_ERR(sirf_audio_codec->regmap))
|
||||
return PTR_ERR(sirf_audio_codec->regmap);
|
||||
|
||||
sirf_audio_codec->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(sirf_audio_codec->clk)) {
|
||||
dev_err(&pdev->dev, "Get clock failed.\n");
|
||||
return PTR_ERR(sirf_audio_codec->clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(sirf_audio_codec->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Enable clock failed.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_codec(&(pdev->dev),
|
||||
&soc_codec_device_sirf_audio_codec,
|
||||
&sirf_audio_codec_dai, 1);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Register Audio Codec dai failed.\n");
|
||||
goto err_clk_put;
|
||||
}
|
||||
|
||||
/*
|
||||
* Always open charge pump, if not, when the charge pump closed the
|
||||
* adc will not stable
|
||||
*/
|
||||
regmap_update_bits(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
|
||||
IC_CPFREQ, IC_CPFREQ);
|
||||
|
||||
if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas6-audio-codec"))
|
||||
regmap_update_bits(sirf_audio_codec->regmap,
|
||||
AUDIO_IC_CODEC_CTRL0, IC_CPEN, IC_CPEN);
|
||||
return 0;
|
||||
|
||||
err_clk_put:
|
||||
clk_disable_unprepare(sirf_audio_codec->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sirf_audio_codec_driver_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct sirf_audio_codec *sirf_audio_codec = platform_get_drvdata(pdev);
|
||||
|
||||
clk_disable_unprepare(sirf_audio_codec->clk);
|
||||
snd_soc_unregister_codec(&(pdev->dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int sirf_audio_codec_suspend(struct device *dev)
|
||||
{
|
||||
struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
|
||||
|
||||
regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
|
||||
&sirf_audio_codec->reg_ctrl0);
|
||||
regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
|
||||
&sirf_audio_codec->reg_ctrl1);
|
||||
clk_disable_unprepare(sirf_audio_codec->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirf_audio_codec_resume(struct device *dev)
|
||||
{
|
||||
struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(sirf_audio_codec->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
|
||||
sirf_audio_codec->reg_ctrl0);
|
||||
regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
|
||||
sirf_audio_codec->reg_ctrl1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops sirf_audio_codec_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(sirf_audio_codec_suspend, sirf_audio_codec_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver sirf_audio_codec_driver = {
|
||||
.driver = {
|
||||
.name = "sirf-audio-codec",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = sirf_audio_codec_of_match,
|
||||
.pm = &sirf_audio_codec_pm_ops,
|
||||
},
|
||||
.probe = sirf_audio_codec_driver_probe,
|
||||
.remove = sirf_audio_codec_driver_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(sirf_audio_codec_driver);
|
||||
|
||||
MODULE_DESCRIPTION("SiRF audio codec driver");
|
||||
MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
75
sound/soc/codecs/sirf-audio-codec.h
Normal file
75
sound/soc/codecs/sirf-audio-codec.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* SiRF inner codec controllers define
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#ifndef _SIRF_AUDIO_CODEC_H
|
||||
#define _SIRF_AUDIO_CODEC_H
|
||||
|
||||
|
||||
#define AUDIO_IC_CODEC_PWR (0x00E0)
|
||||
#define AUDIO_IC_CODEC_CTRL0 (0x00E4)
|
||||
#define AUDIO_IC_CODEC_CTRL1 (0x00E8)
|
||||
#define AUDIO_IC_CODEC_CTRL2 (0x00EC)
|
||||
#define AUDIO_IC_CODEC_CTRL3 (0x00F0)
|
||||
|
||||
#define MICBIASEN (1 << 3)
|
||||
|
||||
#define IC_RDACEN (1 << 0)
|
||||
#define IC_LDACEN (1 << 1)
|
||||
#define IC_HSREN (1 << 2)
|
||||
#define IC_HSLEN (1 << 3)
|
||||
#define IC_SPEN (1 << 4)
|
||||
#define IC_CPEN (1 << 5)
|
||||
|
||||
#define IC_HPRSELR (1 << 6)
|
||||
#define IC_HPLSELR (1 << 7)
|
||||
#define IC_HPRSELL (1 << 8)
|
||||
#define IC_HPLSELL (1 << 9)
|
||||
#define IC_SPSELR (1 << 10)
|
||||
#define IC_SPSELL (1 << 11)
|
||||
|
||||
#define IC_MONOR (1 << 12)
|
||||
#define IC_MONOL (1 << 13)
|
||||
|
||||
#define IC_RXOSRSEL (1 << 28)
|
||||
#define IC_CPFREQ (1 << 29)
|
||||
#define IC_HSINVEN (1 << 30)
|
||||
|
||||
#define IC_MICINREN (1 << 0)
|
||||
#define IC_MICINLEN (1 << 1)
|
||||
#define IC_MICIN1SEL (1 << 2)
|
||||
#define IC_MICIN2SEL (1 << 3)
|
||||
#define IC_MICDIFSEL (1 << 4)
|
||||
#define IC_LINEIN1SEL (1 << 5)
|
||||
#define IC_LINEIN2SEL (1 << 6)
|
||||
#define IC_RADCEN (1 << 7)
|
||||
#define IC_LADCEN (1 << 8)
|
||||
#define IC_ALM (1 << 9)
|
||||
|
||||
#define IC_DIGMICEN (1 << 22)
|
||||
#define IC_DIGMICFREQ (1 << 23)
|
||||
#define IC_ADC14B_12 (1 << 24)
|
||||
#define IC_FIRDAC_HSL_EN (1 << 25)
|
||||
#define IC_FIRDAC_HSR_EN (1 << 26)
|
||||
#define IC_FIRDAC_LOUT_EN (1 << 27)
|
||||
#define IC_POR (1 << 28)
|
||||
#define IC_CODEC_CLK_EN (1 << 29)
|
||||
#define IC_HP_3DB_BOOST (1 << 30)
|
||||
|
||||
#define IC_ADC_LEFT_GAIN_SHIFT 16
|
||||
#define IC_ADC_RIGHT_GAIN_SHIFT 10
|
||||
#define IC_ADC_GAIN_MASK 0x3F
|
||||
#define IC_MIC_MAX_GAIN 0x39
|
||||
|
||||
#define IC_RXPGAR_MASK 0x3F
|
||||
#define IC_RXPGAR_SHIFT 14
|
||||
#define IC_RXPGAL_MASK 0x3F
|
||||
#define IC_RXPGAL_SHIFT 21
|
||||
#define IC_RXPGAR 0x7B
|
||||
#define IC_RXPGAL 0x7B
|
||||
|
||||
#endif /*__SIRF_AUDIO_CODEC_H*/
|
|
@ -312,14 +312,14 @@ static int sn95031_dmic56_event(struct snd_soc_dapm_widget *w,
|
|||
/* mux controls */
|
||||
static const char *sn95031_mic_texts[] = { "AMIC", "LineIn" };
|
||||
|
||||
static const struct soc_enum sn95031_micl_enum =
|
||||
SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 1, 2, sn95031_mic_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(sn95031_micl_enum,
|
||||
SN95031_ADCCONFIG, 1, sn95031_mic_texts);
|
||||
|
||||
static const struct snd_kcontrol_new sn95031_micl_mux_control =
|
||||
SOC_DAPM_ENUM("Route", sn95031_micl_enum);
|
||||
|
||||
static const struct soc_enum sn95031_micr_enum =
|
||||
SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 3, 2, sn95031_mic_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(sn95031_micr_enum,
|
||||
SN95031_ADCCONFIG, 3, sn95031_mic_texts);
|
||||
|
||||
static const struct snd_kcontrol_new sn95031_micr_mux_control =
|
||||
SOC_DAPM_ENUM("Route", sn95031_micr_enum);
|
||||
|
@ -328,26 +328,26 @@ static const char *sn95031_input_texts[] = { "DMIC1", "DMIC2", "DMIC3",
|
|||
"DMIC4", "DMIC5", "DMIC6",
|
||||
"ADC Left", "ADC Right" };
|
||||
|
||||
static const struct soc_enum sn95031_input1_enum =
|
||||
SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 0, 8, sn95031_input_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(sn95031_input1_enum,
|
||||
SN95031_AUDIOMUX12, 0, sn95031_input_texts);
|
||||
|
||||
static const struct snd_kcontrol_new sn95031_input1_mux_control =
|
||||
SOC_DAPM_ENUM("Route", sn95031_input1_enum);
|
||||
|
||||
static const struct soc_enum sn95031_input2_enum =
|
||||
SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 4, 8, sn95031_input_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(sn95031_input2_enum,
|
||||
SN95031_AUDIOMUX12, 4, sn95031_input_texts);
|
||||
|
||||
static const struct snd_kcontrol_new sn95031_input2_mux_control =
|
||||
SOC_DAPM_ENUM("Route", sn95031_input2_enum);
|
||||
|
||||
static const struct soc_enum sn95031_input3_enum =
|
||||
SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 0, 8, sn95031_input_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(sn95031_input3_enum,
|
||||
SN95031_AUDIOMUX34, 0, sn95031_input_texts);
|
||||
|
||||
static const struct snd_kcontrol_new sn95031_input3_mux_control =
|
||||
SOC_DAPM_ENUM("Route", sn95031_input3_enum);
|
||||
|
||||
static const struct soc_enum sn95031_input4_enum =
|
||||
SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 4, 8, sn95031_input_texts);
|
||||
static SOC_ENUM_SINGLE_DECL(sn95031_input4_enum,
|
||||
SN95031_AUDIOMUX34, 4, sn95031_input_texts);
|
||||
|
||||
static const struct snd_kcontrol_new sn95031_input4_mux_control =
|
||||
SOC_DAPM_ENUM("Route", sn95031_input4_enum);
|
||||
|
@ -359,19 +359,19 @@ static const char *sn95031_micmode_text[] = {"Single Ended", "Differential"};
|
|||
/* 0dB to 30dB in 10dB steps */
|
||||
static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 10, 0);
|
||||
|
||||
static const struct soc_enum sn95031_micmode1_enum =
|
||||
SOC_ENUM_SINGLE(SN95031_MICAMP1, 1, 2, sn95031_micmode_text);
|
||||
static const struct soc_enum sn95031_micmode2_enum =
|
||||
SOC_ENUM_SINGLE(SN95031_MICAMP2, 1, 2, sn95031_micmode_text);
|
||||
static SOC_ENUM_SINGLE_DECL(sn95031_micmode1_enum,
|
||||
SN95031_MICAMP1, 1, sn95031_micmode_text);
|
||||
static SOC_ENUM_SINGLE_DECL(sn95031_micmode2_enum,
|
||||
SN95031_MICAMP2, 1, sn95031_micmode_text);
|
||||
|
||||
static const char *sn95031_dmic_cfg_text[] = {"GPO", "DMIC"};
|
||||
|
||||
static const struct soc_enum sn95031_dmic12_cfg_enum =
|
||||
SOC_ENUM_SINGLE(SN95031_DMICMUX, 0, 2, sn95031_dmic_cfg_text);
|
||||
static const struct soc_enum sn95031_dmic34_cfg_enum =
|
||||
SOC_ENUM_SINGLE(SN95031_DMICMUX, 1, 2, sn95031_dmic_cfg_text);
|
||||
static const struct soc_enum sn95031_dmic56_cfg_enum =
|
||||
SOC_ENUM_SINGLE(SN95031_DMICMUX, 2, 2, sn95031_dmic_cfg_text);
|
||||
static SOC_ENUM_SINGLE_DECL(sn95031_dmic12_cfg_enum,
|
||||
SN95031_DMICMUX, 0, sn95031_dmic_cfg_text);
|
||||
static SOC_ENUM_SINGLE_DECL(sn95031_dmic34_cfg_enum,
|
||||
SN95031_DMICMUX, 1, sn95031_dmic_cfg_text);
|
||||
static SOC_ENUM_SINGLE_DECL(sn95031_dmic56_cfg_enum,
|
||||
SN95031_DMICMUX, 2, sn95031_dmic_cfg_text);
|
||||
|
||||
static const struct snd_kcontrol_new sn95031_snd_controls[] = {
|
||||
SOC_ENUM("Mic1Mode Capture Route", sn95031_micmode1_enum),
|
||||
|
|
|
@ -169,19 +169,19 @@ static const char * const ssm2518_drc_hold_time_text[] = {
|
|||
"682.24 ms", "1364 ms",
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum,
|
||||
SSM2518_REG_DRC_2, 4, ssm2518_drc_peak_detector_attack_time_text);
|
||||
static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum,
|
||||
SSM2518_REG_DRC_2, 0, ssm2518_drc_peak_detector_release_time_text);
|
||||
static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum,
|
||||
SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text);
|
||||
static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum,
|
||||
SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text);
|
||||
static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum,
|
||||
SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text);
|
||||
static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum,
|
||||
SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text);
|
||||
static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum,
|
||||
static SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum,
|
||||
SSM2518_REG_DRC_9, 0, ssm2518_drc_peak_detector_release_time_text);
|
||||
|
||||
static const struct snd_kcontrol_new ssm2518_snd_controls[] = {
|
||||
|
|
57
sound/soc/codecs/ssm2602-i2c.c
Normal file
57
sound/soc/codecs/ssm2602-i2c.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* SSM2602/SSM2603/SSM2604 I2C audio driver
|
||||
*
|
||||
* Copyright 2014 Analog Devices Inc.
|
||||
*
|
||||
* Licensed under the GPL-2.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "ssm2602.h"
|
||||
|
||||
/*
|
||||
* ssm2602 2 wire address is determined by GPIO5
|
||||
* state during powerup.
|
||||
* low = 0x1a
|
||||
* high = 0x1b
|
||||
*/
|
||||
static int ssm2602_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
return ssm2602_probe(&client->dev, id->driver_data,
|
||||
devm_regmap_init_i2c(client, &ssm2602_regmap_config));
|
||||
}
|
||||
|
||||
static int ssm2602_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ssm2602_i2c_id[] = {
|
||||
{ "ssm2602", SSM2602 },
|
||||
{ "ssm2603", SSM2602 },
|
||||
{ "ssm2604", SSM2604 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);
|
||||
|
||||
static struct i2c_driver ssm2602_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "ssm2602",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ssm2602_i2c_probe,
|
||||
.remove = ssm2602_i2c_remove,
|
||||
.id_table = ssm2602_i2c_id,
|
||||
};
|
||||
module_i2c_driver(ssm2602_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 I2C driver");
|
||||
MODULE_AUTHOR("Cliff Cai");
|
||||
MODULE_LICENSE("GPL");
|
41
sound/soc/codecs/ssm2602-spi.c
Normal file
41
sound/soc/codecs/ssm2602-spi.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* SSM2602 SPI audio driver
|
||||
*
|
||||
* Copyright 2014 Analog Devices Inc.
|
||||
*
|
||||
* Licensed under the GPL-2.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "ssm2602.h"
|
||||
|
||||
static int ssm2602_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
return ssm2602_probe(&spi->dev, SSM2602,
|
||||
devm_regmap_init_spi(spi, &ssm2602_regmap_config));
|
||||
}
|
||||
|
||||
static int ssm2602_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver ssm2602_spi_driver = {
|
||||
.driver = {
|
||||
.name = "ssm2602",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ssm2602_spi_probe,
|
||||
.remove = ssm2602_spi_remove,
|
||||
};
|
||||
module_spi_driver(ssm2602_spi_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC SSM2602 SPI driver");
|
||||
MODULE_AUTHOR("Cliff Cai");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -27,32 +27,20 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "ssm2602.h"
|
||||
|
||||
enum ssm2602_type {
|
||||
SSM2602,
|
||||
SSM2604,
|
||||
};
|
||||
|
||||
/* codec private data */
|
||||
struct ssm2602_priv {
|
||||
unsigned int sysclk;
|
||||
struct snd_pcm_hw_constraint_list *sysclk_constraints;
|
||||
const struct snd_pcm_hw_constraint_list *sysclk_constraints;
|
||||
|
||||
struct regmap *regmap;
|
||||
|
||||
|
@ -75,15 +63,16 @@ static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = {
|
|||
|
||||
/*Appending several "None"s just for OSS mixer use*/
|
||||
static const char *ssm2602_input_select[] = {
|
||||
"Line", "Mic", "None", "None", "None",
|
||||
"None", "None", "None",
|
||||
"Line", "Mic",
|
||||
};
|
||||
|
||||
static const char *ssm2602_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
|
||||
|
||||
static const struct soc_enum ssm2602_enum[] = {
|
||||
SOC_ENUM_SINGLE(SSM2602_APANA, 2, 2, ssm2602_input_select),
|
||||
SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, 4, ssm2602_deemph),
|
||||
SOC_ENUM_SINGLE(SSM2602_APANA, 2, ARRAY_SIZE(ssm2602_input_select),
|
||||
ssm2602_input_select),
|
||||
SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, ARRAY_SIZE(ssm2602_deemph),
|
||||
ssm2602_deemph),
|
||||
};
|
||||
|
||||
static const unsigned int ssm260x_outmix_tlv[] = {
|
||||
|
@ -197,7 +186,7 @@ static const unsigned int ssm2602_rates_12288000[] = {
|
|||
8000, 16000, 32000, 48000, 96000,
|
||||
};
|
||||
|
||||
static struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = {
|
||||
static const struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = {
|
||||
.list = ssm2602_rates_12288000,
|
||||
.count = ARRAY_SIZE(ssm2602_rates_12288000),
|
||||
};
|
||||
|
@ -206,7 +195,7 @@ static const unsigned int ssm2602_rates_11289600[] = {
|
|||
8000, 44100, 88200,
|
||||
};
|
||||
|
||||
static struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = {
|
||||
static const struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = {
|
||||
.list = ssm2602_rates_11289600,
|
||||
.count = ARRAY_SIZE(ssm2602_rates_11289600),
|
||||
};
|
||||
|
@ -529,7 +518,7 @@ static int ssm2602_resume(struct snd_soc_codec *codec)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ssm2602_probe(struct snd_soc_codec *codec)
|
||||
static int ssm2602_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
@ -554,7 +543,7 @@ static int ssm2602_probe(struct snd_soc_codec *codec)
|
|||
ARRAY_SIZE(ssm2602_routes));
|
||||
}
|
||||
|
||||
static int ssm2604_probe(struct snd_soc_codec *codec)
|
||||
static int ssm2604_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int ret;
|
||||
|
@ -568,7 +557,7 @@ static int ssm2604_probe(struct snd_soc_codec *codec)
|
|||
ARRAY_SIZE(ssm2604_routes));
|
||||
}
|
||||
|
||||
static int ssm260x_probe(struct snd_soc_codec *codec)
|
||||
static int ssm260x_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
@ -597,10 +586,10 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
|
|||
|
||||
switch (ssm2602->type) {
|
||||
case SSM2602:
|
||||
ret = ssm2602_probe(codec);
|
||||
ret = ssm2602_codec_probe(codec);
|
||||
break;
|
||||
case SSM2604:
|
||||
ret = ssm2604_probe(codec);
|
||||
ret = ssm2604_codec_probe(codec);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -620,7 +609,7 @@ static int ssm2602_remove(struct snd_soc_codec *codec)
|
|||
}
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
|
||||
.probe = ssm260x_probe,
|
||||
.probe = ssm260x_codec_probe,
|
||||
.remove = ssm2602_remove,
|
||||
.suspend = ssm2602_suspend,
|
||||
.resume = ssm2602_resume,
|
||||
|
@ -639,7 +628,7 @@ static bool ssm2602_register_volatile(struct device *dev, unsigned int reg)
|
|||
return reg == SSM2602_RESET;
|
||||
}
|
||||
|
||||
static const struct regmap_config ssm2602_regmap_config = {
|
||||
const struct regmap_config ssm2602_regmap_config = {
|
||||
.val_bits = 9,
|
||||
.reg_bits = 7,
|
||||
|
||||
|
@ -650,134 +639,28 @@ static const struct regmap_config ssm2602_regmap_config = {
|
|||
.reg_defaults_raw = ssm2602_reg,
|
||||
.num_reg_defaults_raw = ARRAY_SIZE(ssm2602_reg),
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ssm2602_regmap_config);
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
static int ssm2602_spi_probe(struct spi_device *spi)
|
||||
int ssm2602_probe(struct device *dev, enum ssm2602_type type,
|
||||
struct regmap *regmap)
|
||||
{
|
||||
struct ssm2602_priv *ssm2602;
|
||||
int ret;
|
||||
|
||||
ssm2602 = devm_kzalloc(&spi->dev, sizeof(struct ssm2602_priv),
|
||||
GFP_KERNEL);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
ssm2602 = devm_kzalloc(dev, sizeof(*ssm2602), GFP_KERNEL);
|
||||
if (ssm2602 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_drvdata(spi, ssm2602);
|
||||
dev_set_drvdata(dev, ssm2602);
|
||||
ssm2602->type = SSM2602;
|
||||
ssm2602->regmap = regmap;
|
||||
|
||||
ssm2602->regmap = devm_regmap_init_spi(spi, &ssm2602_regmap_config);
|
||||
if (IS_ERR(ssm2602->regmap))
|
||||
return PTR_ERR(ssm2602->regmap);
|
||||
|
||||
ret = snd_soc_register_codec(&spi->dev,
|
||||
&soc_codec_dev_ssm2602, &ssm2602_dai, 1);
|
||||
return ret;
|
||||
return snd_soc_register_codec(dev, &soc_codec_dev_ssm2602,
|
||||
&ssm2602_dai, 1);
|
||||
}
|
||||
|
||||
static int ssm2602_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver ssm2602_spi_driver = {
|
||||
.driver = {
|
||||
.name = "ssm2602",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ssm2602_spi_probe,
|
||||
.remove = ssm2602_spi_remove,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C)
|
||||
/*
|
||||
* ssm2602 2 wire address is determined by GPIO5
|
||||
* state during powerup.
|
||||
* low = 0x1a
|
||||
* high = 0x1b
|
||||
*/
|
||||
static int ssm2602_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct ssm2602_priv *ssm2602;
|
||||
int ret;
|
||||
|
||||
ssm2602 = devm_kzalloc(&i2c->dev, sizeof(struct ssm2602_priv),
|
||||
GFP_KERNEL);
|
||||
if (ssm2602 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, ssm2602);
|
||||
ssm2602->type = id->driver_data;
|
||||
|
||||
ssm2602->regmap = devm_regmap_init_i2c(i2c, &ssm2602_regmap_config);
|
||||
if (IS_ERR(ssm2602->regmap))
|
||||
return PTR_ERR(ssm2602->regmap);
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
&soc_codec_dev_ssm2602, &ssm2602_dai, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ssm2602_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ssm2602_i2c_id[] = {
|
||||
{ "ssm2602", SSM2602 },
|
||||
{ "ssm2603", SSM2602 },
|
||||
{ "ssm2604", SSM2604 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);
|
||||
|
||||
/* corgi i2c codec control layer */
|
||||
static struct i2c_driver ssm2602_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "ssm2602",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ssm2602_i2c_probe,
|
||||
.remove = ssm2602_i2c_remove,
|
||||
.id_table = ssm2602_i2c_id,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
static int __init ssm2602_modinit(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
ret = spi_register_driver(&ssm2602_spi_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C)
|
||||
ret = i2c_add_driver(&ssm2602_i2c_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
module_init(ssm2602_modinit);
|
||||
|
||||
static void __exit ssm2602_exit(void)
|
||||
{
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
spi_unregister_driver(&ssm2602_spi_driver);
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C)
|
||||
i2c_del_driver(&ssm2602_i2c_driver);
|
||||
#endif
|
||||
}
|
||||
module_exit(ssm2602_exit);
|
||||
EXPORT_SYMBOL_GPL(ssm2602_probe);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 driver");
|
||||
MODULE_AUTHOR("Cliff Cai");
|
||||
|
|
|
@ -28,6 +28,20 @@
|
|||
#ifndef _SSM2602_H
|
||||
#define _SSM2602_H
|
||||
|
||||
#include <linux/regmap.h>
|
||||
|
||||
struct device;
|
||||
|
||||
enum ssm2602_type {
|
||||
SSM2602,
|
||||
SSM2604,
|
||||
};
|
||||
|
||||
extern const struct regmap_config ssm2602_regmap_config;
|
||||
|
||||
int ssm2602_probe(struct device *dev, enum ssm2602_type type,
|
||||
struct regmap *regmap);
|
||||
|
||||
/* SSM2602 Codec Register definitions */
|
||||
|
||||
#define SSM2602_LINVOL 0x00
|
||||
|
|
|
@ -141,7 +141,7 @@ static const char *pwm_mode_text[] = { "Binary", "Headphone", "Ternary",
|
|||
|
||||
static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0);
|
||||
static const SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text);
|
||||
static SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text);
|
||||
|
||||
static const struct snd_kcontrol_new sta529_snd_controls[] = {
|
||||
SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0,
|
||||
|
|
|
@ -62,25 +62,25 @@ static const char *stac9766_boost1[] = {"0dB", "10dB"};
|
|||
static const char *stac9766_boost2[] = {"0dB", "20dB"};
|
||||
static const char *stac9766_stereo_mic[] = {"Off", "On"};
|
||||
|
||||
static const struct soc_enum stac9766_record_enum =
|
||||
SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, stac9766_record_mux);
|
||||
static const struct soc_enum stac9766_mono_enum =
|
||||
SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, stac9766_mono_mux);
|
||||
static const struct soc_enum stac9766_mic_enum =
|
||||
SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, stac9766_mic_mux);
|
||||
static const struct soc_enum stac9766_SPDIF_enum =
|
||||
SOC_ENUM_SINGLE(AC97_STAC_DA_CONTROL, 1, 2, stac9766_SPDIF_mux);
|
||||
static const struct soc_enum stac9766_popbypass_enum =
|
||||
SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, stac9766_popbypass_mux);
|
||||
static const struct soc_enum stac9766_record_all_enum =
|
||||
SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 12, 2,
|
||||
stac9766_record_all_mux);
|
||||
static const struct soc_enum stac9766_boost1_enum =
|
||||
SOC_ENUM_SINGLE(AC97_MIC, 6, 2, stac9766_boost1); /* 0/10dB */
|
||||
static const struct soc_enum stac9766_boost2_enum =
|
||||
SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 2, 2, stac9766_boost2); /* 0/20dB */
|
||||
static const struct soc_enum stac9766_stereo_mic_enum =
|
||||
SOC_ENUM_SINGLE(AC97_STAC_STEREO_MIC, 2, 1, stac9766_stereo_mic);
|
||||
static SOC_ENUM_DOUBLE_DECL(stac9766_record_enum,
|
||||
AC97_REC_SEL, 8, 0, stac9766_record_mux);
|
||||
static SOC_ENUM_SINGLE_DECL(stac9766_mono_enum,
|
||||
AC97_GENERAL_PURPOSE, 9, stac9766_mono_mux);
|
||||
static SOC_ENUM_SINGLE_DECL(stac9766_mic_enum,
|
||||
AC97_GENERAL_PURPOSE, 8, stac9766_mic_mux);
|
||||
static SOC_ENUM_SINGLE_DECL(stac9766_SPDIF_enum,
|
||||
AC97_STAC_DA_CONTROL, 1, stac9766_SPDIF_mux);
|
||||
static SOC_ENUM_SINGLE_DECL(stac9766_popbypass_enum,
|
||||
AC97_GENERAL_PURPOSE, 15, stac9766_popbypass_mux);
|
||||
static SOC_ENUM_SINGLE_DECL(stac9766_record_all_enum,
|
||||
AC97_STAC_ANALOG_SPECIAL, 12,
|
||||
stac9766_record_all_mux);
|
||||
static SOC_ENUM_SINGLE_DECL(stac9766_boost1_enum,
|
||||
AC97_MIC, 6, stac9766_boost1); /* 0/10dB */
|
||||
static SOC_ENUM_SINGLE_DECL(stac9766_boost2_enum,
|
||||
AC97_STAC_ANALOG_SPECIAL, 2, stac9766_boost2); /* 0/20dB */
|
||||
static SOC_ENUM_SINGLE_DECL(stac9766_stereo_mic_enum,
|
||||
AC97_STAC_STEREO_MIC, 2, stac9766_stereo_mic);
|
||||
|
||||
static const DECLARE_TLV_DB_LINEAR(master_tlv, -4600, 0);
|
||||
static const DECLARE_TLV_DB_LINEAR(record_tlv, 0, 2250);
|
||||
|
|
59
sound/soc/codecs/tlv320aic23-i2c.c
Normal file
59
sound/soc/codecs/tlv320aic23-i2c.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* ALSA SoC TLV320AIC23 codec driver I2C interface
|
||||
*
|
||||
* Author: Arun KS, <arunks@mistralsolutions.com>
|
||||
* Copyright: (C) 2008 Mistral Solutions Pvt Ltd.,
|
||||
*
|
||||
* Based on sound/soc/codecs/wm8731.c by Richard Purdie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "tlv320aic23.h"
|
||||
|
||||
static int tlv320aic23_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *i2c_id)
|
||||
{
|
||||
struct regmap *regmap;
|
||||
|
||||
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return -EINVAL;
|
||||
|
||||
regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap);
|
||||
return tlv320aic23_probe(&i2c->dev, regmap);
|
||||
}
|
||||
|
||||
static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
snd_soc_unregister_codec(&i2c->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tlv320aic23_id[] = {
|
||||
{"tlv320aic23", 0},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
|
||||
|
||||
static struct i2c_driver tlv320aic23_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "tlv320aic23-codec",
|
||||
},
|
||||
.probe = tlv320aic23_i2c_probe,
|
||||
.remove = __exit_p(tlv320aic23_i2c_remove),
|
||||
.id_table = tlv320aic23_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(tlv320aic23_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver I2C");
|
||||
MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
|
||||
MODULE_LICENSE("GPL");
|
56
sound/soc/codecs/tlv320aic23-spi.c
Normal file
56
sound/soc/codecs/tlv320aic23-spi.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* ALSA SoC TLV320AIC23 codec driver SPI interface
|
||||
*
|
||||
* Author: Arun KS, <arunks@mistralsolutions.com>
|
||||
* Copyright: (C) 2008 Mistral Solutions Pvt Ltd.,
|
||||
*
|
||||
* Based on sound/soc/codecs/wm8731.c by Richard Purdie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "tlv320aic23.h"
|
||||
|
||||
static int aic23_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
int ret;
|
||||
struct regmap *regmap;
|
||||
|
||||
dev_dbg(&spi->dev, "probing tlv320aic23 spi device\n");
|
||||
|
||||
spi->mode = SPI_MODE_0;
|
||||
ret = spi_setup(spi);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
regmap = devm_regmap_init_spi(spi, &tlv320aic23_regmap);
|
||||
return tlv320aic23_probe(&spi->dev, regmap);
|
||||
}
|
||||
|
||||
static int aic23_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver aic23_spi = {
|
||||
.driver = {
|
||||
.name = "tlv320aic23",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = aic23_spi_probe,
|
||||
.remove = aic23_spi_remove,
|
||||
};
|
||||
|
||||
module_spi_driver(aic23_spi);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver SPI");
|
||||
MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
|
||||
MODULE_LICENSE("GPL");
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue