Merge remote-tracking branch 'asoc/fix/atmel' into asoc-linus
This commit is contained in:
commit
29dc5dd229
193 changed files with 10287 additions and 2369 deletions
|
@ -7,9 +7,30 @@ Required properties:
|
|||
- reg: Should contain SSC registers location and length
|
||||
- interrupts: Should contain SSC interrupt
|
||||
|
||||
Example:
|
||||
|
||||
Required properties for devices compatible with "atmel,at91sam9g45-ssc":
|
||||
- dmas: DMA specifier, consisting of a phandle to DMA controller node,
|
||||
the memory interface and SSC DMA channel ID (for tx and rx).
|
||||
See Documentation/devicetree/bindings/dma/atmel-dma.txt for details.
|
||||
- dma-names: Must be "tx", "rx".
|
||||
|
||||
Examples:
|
||||
- PDC transfer:
|
||||
ssc0: ssc@fffbc000 {
|
||||
compatible = "atmel,at91rm9200-ssc";
|
||||
reg = <0xfffbc000 0x4000>;
|
||||
interrupts = <14 4 5>;
|
||||
};
|
||||
|
||||
- DMA transfer:
|
||||
ssc0: ssc@f0010000 {
|
||||
compatible = "atmel,at91sam9g45-ssc";
|
||||
reg = <0xf0010000 0x4000>;
|
||||
interrupts = <28 4 5>;
|
||||
dmas = <&dma0 1 13>,
|
||||
<&dma0 1 14>;
|
||||
dma-names = "tx", "rx";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
65
Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
Normal file
65
Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
Normal file
|
@ -0,0 +1,65 @@
|
|||
Device tree bindings for Marvell PXA SSP ports
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: Must be one of
|
||||
mrvl,pxa25x-ssp
|
||||
mvrl,pxa25x-nssp
|
||||
mrvl,pxa27x-ssp
|
||||
mrvl,pxa3xx-ssp
|
||||
mvrl,pxa168-ssp
|
||||
mrvl,pxa910-ssp
|
||||
mrvl,ce4100-ssp
|
||||
mrvl,lpss-ssp
|
||||
|
||||
- reg: The memory base
|
||||
- dmas: Two dma phandles, one for rx, one for tx
|
||||
- dma-names: Must be "rx", "tx"
|
||||
|
||||
|
||||
Example for PXA3xx:
|
||||
|
||||
ssp0: ssp@41000000 {
|
||||
compatible = "mrvl,pxa3xx-ssp";
|
||||
reg = <0x41000000 0x40>;
|
||||
ssp-id = <1>;
|
||||
interrupts = <24>;
|
||||
clock-names = "pxa27x-ssp.0";
|
||||
dmas = <&dma 13
|
||||
&dma 14>;
|
||||
dma-names = "rx", "tx";
|
||||
};
|
||||
|
||||
ssp1: ssp@41700000 {
|
||||
compatible = "mrvl,pxa3xx-ssp";
|
||||
reg = <0x41700000 0x40>;
|
||||
ssp-id = <2>;
|
||||
interrupts = <16>;
|
||||
clock-names = "pxa27x-ssp.1";
|
||||
dmas = <&dma 15
|
||||
&dma 16>;
|
||||
dma-names = "rx", "tx";
|
||||
};
|
||||
|
||||
ssp2: ssp@41900000 {
|
||||
compatibl3 = "mrvl,pxa3xx-ssp";
|
||||
reg = <0x41900000 0x40>;
|
||||
ssp-id = <3>;
|
||||
interrupts = <0>;
|
||||
clock-names = "pxa27x-ssp.2";
|
||||
dmas = <&dma 66
|
||||
&dma 67>;
|
||||
dma-names = "rx", "tx";
|
||||
};
|
||||
|
||||
ssp3: ssp@41a00000 {
|
||||
compatible = "mrvl,pxa3xx-ssp";
|
||||
reg = <0x41a00000 0x40>;
|
||||
ssp-id = <4>;
|
||||
interrupts = <13>;
|
||||
clock-names = "pxa27x-ssp.3";
|
||||
dmas = <&dma 2
|
||||
&dma 3>;
|
||||
dma-names = "rx", "tx";
|
||||
};
|
||||
|
11
Documentation/devicetree/bindings/sound/ak4554.c
Normal file
11
Documentation/devicetree/bindings/sound/ak4554.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
AK4554 ADC/DAC
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "asahi-kasei,ak4554"
|
||||
|
||||
Example:
|
||||
|
||||
ak4554-adc-dac {
|
||||
compatible = "asahi-kasei,ak4554";
|
||||
};
|
|
@ -13,6 +13,25 @@ Required properties:
|
|||
- #gpio-cells : Should be two. The first cell is the pin number and the
|
||||
second cell is used to specify optional parameters (currently unused).
|
||||
|
||||
Pins on the device (for linking into audio routes):
|
||||
|
||||
* SPK_OUTP
|
||||
* SPK_OUTN
|
||||
* HP_OUT_L
|
||||
* HP_OUT_R
|
||||
* AUX_OUT_P
|
||||
* AUX_OUT_N
|
||||
* LINE_IN_L
|
||||
* LINE_IN_R
|
||||
* PHONE_P
|
||||
* PHONE_N
|
||||
* MIC1_P
|
||||
* MIC1_N
|
||||
* MIC2_P
|
||||
* MIC2_N
|
||||
* MICBIAS1
|
||||
* DMICDAT
|
||||
|
||||
Example:
|
||||
|
||||
alc5632: alc5632@1e {
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
* Atmel at91sam9x5ek wm8731 audio complex
|
||||
|
||||
Required properties:
|
||||
- compatible: "atmel,sam9x5-wm8731-audio"
|
||||
- atmel,model: The user-visible name of this sound complex.
|
||||
- atmel,ssc-controller: The phandle of the SSC controller
|
||||
- atmel,audio-codec: The phandle of the WM8731 audio codec
|
||||
- atmel,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.
|
||||
|
||||
Available audio endpoints for the audio-routing table:
|
||||
|
||||
Board connectors:
|
||||
* Headphone Jack
|
||||
* Line In Jack
|
||||
|
||||
wm8731 pins:
|
||||
cf Documentation/devicetree/bindings/sound/wm8731.txt
|
||||
|
||||
Example:
|
||||
sound {
|
||||
compatible = "atmel,sam9x5-wm8731-audio";
|
||||
|
||||
atmel,model = "wm8731 @ AT91SAM9X5EK";
|
||||
|
||||
atmel,audio-routing =
|
||||
"Headphone Jack", "RHPOUT",
|
||||
"Headphone Jack", "LHPOUT",
|
||||
"LLINEIN", "Line In Jack",
|
||||
"RLINEIN", "Line In Jack";
|
||||
|
||||
atmel,ssc-controller = <&ssc0>;
|
||||
atmel,audio-codec = <&wm8731>;
|
||||
};
|
55
Documentation/devicetree/bindings/sound/atmel-wm8904.txt
Normal file
55
Documentation/devicetree/bindings/sound/atmel-wm8904.txt
Normal file
|
@ -0,0 +1,55 @@
|
|||
Atmel ASoC driver with wm8904 audio codec complex
|
||||
|
||||
Required properties:
|
||||
- compatible: "atmel,asoc-wm8904"
|
||||
- atmel,model: The user-visible name of this sound complex.
|
||||
- atmel,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 WM8904's pins, and the jacks on the board:
|
||||
|
||||
WM8904 pins:
|
||||
|
||||
* IN1L
|
||||
* IN1R
|
||||
* IN2L
|
||||
* IN2R
|
||||
* IN3L
|
||||
* IN3R
|
||||
* HPOUTL
|
||||
* HPOUTR
|
||||
* LINEOUTL
|
||||
* LINEOUTR
|
||||
* MICBIAS
|
||||
|
||||
Board connectors:
|
||||
|
||||
* Headphone Jack
|
||||
* Line In Jack
|
||||
* Mic
|
||||
|
||||
- atmel,ssc-controller: The phandle of the SSC controller
|
||||
- atmel,audio-codec: The phandle of the WM8904 audio codec
|
||||
|
||||
Optional properties:
|
||||
- pinctrl-names, pinctrl-0: Please refer to pinctrl-bindings.txt
|
||||
|
||||
Example:
|
||||
sound {
|
||||
compatible = "atmel,asoc-wm8904";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_pck0_as_mck>;
|
||||
|
||||
atmel,model = "wm8904 @ AT91SAM9N12EK";
|
||||
|
||||
atmel,audio-routing =
|
||||
"Headphone Jack", "HPOUTL",
|
||||
"Headphone Jack", "HPOUTR",
|
||||
"IN2L", "Line In Jack",
|
||||
"IN2R", "Line In Jack",
|
||||
"Mic", "MICBIAS",
|
||||
"IN1L", "Mic";
|
||||
|
||||
atmel,ssc-controller = <&ssc0>;
|
||||
atmel,audio-codec = <&wm8904>;
|
||||
};
|
54
Documentation/devicetree/bindings/sound/fsl,spdif.txt
Normal file
54
Documentation/devicetree/bindings/sound/fsl,spdif.txt
Normal file
|
@ -0,0 +1,54 @@
|
|||
Freescale Sony/Philips Digital Interface Format (S/PDIF) Controller
|
||||
|
||||
The Freescale S/PDIF audio block is a stereo transceiver that allows the
|
||||
processor to receive and transmit digital audio via an coaxial cable or
|
||||
a fibre cable.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : Compatible list, must contain "fsl,imx35-spdif".
|
||||
|
||||
- reg : Offset and length of the register set for the device.
|
||||
|
||||
- interrupts : Contains the spdif interrupt.
|
||||
|
||||
- dmas : Generic dma devicetree binding as described in
|
||||
Documentation/devicetree/bindings/dma/dma.txt.
|
||||
|
||||
- dma-names : Two dmas have to be defined, "tx" and "rx".
|
||||
|
||||
- clocks : Contains an entry for each entry in clock-names.
|
||||
|
||||
- clock-names : Includes the following entries:
|
||||
"core" The core clock of spdif controller
|
||||
"rxtx<0-7>" Clock source list for tx and rx clock.
|
||||
This clock list should be identical to
|
||||
the source list connecting to the spdif
|
||||
clock mux in "SPDIF Transceiver Clock
|
||||
Diagram" of SoC reference manual. It
|
||||
can also be referred to TxClk_Source
|
||||
bit of register SPDIF_STC.
|
||||
|
||||
Example:
|
||||
|
||||
spdif: spdif@02004000 {
|
||||
compatible = "fsl,imx35-spdif";
|
||||
reg = <0x02004000 0x4000>;
|
||||
interrupts = <0 52 0x04>;
|
||||
dmas = <&sdma 14 18 0>,
|
||||
<&sdma 15 18 0>;
|
||||
dma-names = "rx", "tx";
|
||||
|
||||
clocks = <&clks 197>, <&clks 3>,
|
||||
<&clks 197>, <&clks 107>,
|
||||
<&clks 0>, <&clks 118>,
|
||||
<&clks 62>, <&clks 139>,
|
||||
<&clks 0>;
|
||||
clock-names = "core", "rxtx0",
|
||||
"rxtx1", "rxtx2",
|
||||
"rxtx3", "rxtx4",
|
||||
"rxtx5", "rxtx6",
|
||||
"rxtx7";
|
||||
|
||||
status = "okay";
|
||||
};
|
|
@ -43,10 +43,22 @@ Required properties:
|
|||
together. This would still allow different sample sizes,
|
||||
but not different sample rates.
|
||||
|
||||
Required are also ac97 link bindings if ac97 is used. See
|
||||
Documentation/devicetree/bindings/sound/soc-ac97link.txt for the necessary
|
||||
bindings.
|
||||
|
||||
Optional properties:
|
||||
- codec-handle: Phandle to a 'codec' node that defines an audio
|
||||
codec connected to this SSI. This node is typically
|
||||
a child of an I2C or other control node.
|
||||
- fsl,fiq-stream-filter: Bool property. Disabled DMA and use FIQ instead to
|
||||
filter the codec stream. This is necessary for some boards
|
||||
where an incompatible codec is connected to this SSI, e.g.
|
||||
on pca100 and pcm043.
|
||||
- dmas: Generic dma devicetree binding as described in
|
||||
Documentation/devicetree/bindings/dma/dma.txt.
|
||||
- dma-names: Two dmas have to be defined, "tx" and "rx", if fsl,imx-fiq
|
||||
is not defined.
|
||||
|
||||
Child 'codec' node required properties:
|
||||
- compatible: Compatible list, contains the name of the codec
|
|
@ -5,6 +5,15 @@ Required properties:
|
|||
or "fsl,imx31-audmux" for the version firstly used on i.MX31.
|
||||
- reg : Should contain AUDMUX registers location and length
|
||||
|
||||
An initial configuration can be setup using child nodes.
|
||||
|
||||
Required properties of optional child nodes:
|
||||
- fsl,audmux-port : Integer of the audmux port that is configured by this
|
||||
child node.
|
||||
- fsl,port-config : List of configuration options for the specific port. For
|
||||
imx31-audmux and above, it is a list of tuples <ptcr pdcr>. For
|
||||
imx21-audmux it is a list of pcr values.
|
||||
|
||||
Example:
|
||||
|
||||
audmux@021d8000 {
|
||||
|
|
28
Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt
Normal file
28
Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt
Normal file
|
@ -0,0 +1,28 @@
|
|||
Marvell PXA SSP CPU DAI bindings
|
||||
|
||||
Required properties:
|
||||
|
||||
compatible Must be "mrvl,pxa-ssp-dai"
|
||||
port A phandle reference to a PXA ssp upstream device
|
||||
|
||||
Example:
|
||||
|
||||
/* upstream device */
|
||||
|
||||
ssp0: ssp@41000000 {
|
||||
compatible = "mrvl,pxa3xx-ssp";
|
||||
reg = <0x41000000 0x40>;
|
||||
interrupts = <24>;
|
||||
clock-names = "pxa27x-ssp.0";
|
||||
dmas = <&dma 13
|
||||
&dma 14>;
|
||||
dma-names = "rx", "tx";
|
||||
};
|
||||
|
||||
/* DAI as user */
|
||||
|
||||
ssp_dai0: ssp_dai@0 {
|
||||
compatible = "mrvl,pxa-ssp-dai";
|
||||
port = <&ssp0>;
|
||||
};
|
||||
|
15
Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt
Normal file
15
Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
DT bindings for ARM PXA2xx PCM platform driver
|
||||
|
||||
This is just a dummy driver that registers the PXA ASoC platform driver.
|
||||
It does not have any resources assigned.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible 'mrvl,pxa-pcm-audio'
|
||||
|
||||
Example:
|
||||
|
||||
pxa_pcm_audio: snd_soc_pxa_audio {
|
||||
compatible = "mrvl,pxa-pcm-audio";
|
||||
};
|
||||
|
|
@ -11,28 +11,8 @@ Required properties:
|
|||
- nvidia,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 ALC5632's pins:
|
||||
|
||||
ALC5632 pins:
|
||||
|
||||
* SPK_OUTP
|
||||
* SPK_OUTN
|
||||
* HP_OUT_L
|
||||
* HP_OUT_R
|
||||
* AUX_OUT_P
|
||||
* AUX_OUT_N
|
||||
* LINE_IN_L
|
||||
* LINE_IN_R
|
||||
* PHONE_P
|
||||
* PHONE_N
|
||||
* MIC1_P
|
||||
* MIC1_N
|
||||
* MIC2_P
|
||||
* MIC2_N
|
||||
* MICBIAS1
|
||||
* DMICDAT
|
||||
|
||||
Board connectors:
|
||||
sinks are the ALC5632's pins as documented in the binding for the device
|
||||
and:
|
||||
|
||||
* Headset Stereophone
|
||||
* Int Spk
|
||||
|
|
|
@ -11,32 +11,12 @@ Required properties:
|
|||
- nvidia,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 RT5640's pins, and the jacks on the board:
|
||||
|
||||
RT5640 pins:
|
||||
|
||||
* DMIC1
|
||||
* DMIC2
|
||||
* MICBIAS1
|
||||
* IN1P
|
||||
* IN1R
|
||||
* IN2P
|
||||
* IN2R
|
||||
* HPOL
|
||||
* HPOR
|
||||
* LOUTL
|
||||
* LOUTR
|
||||
* MONOP
|
||||
* MONON
|
||||
* SPOLP
|
||||
* SPOLN
|
||||
* SPORP
|
||||
* SPORN
|
||||
|
||||
Board connectors:
|
||||
sinks are the RT5640's pins (as documented in its binding), and the jacks
|
||||
on the board:
|
||||
|
||||
* Headphones
|
||||
* Speakers
|
||||
* Mic Jack
|
||||
|
||||
- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
|
||||
connected to the CODEC.
|
||||
|
|
|
@ -11,31 +11,8 @@ Required properties:
|
|||
- nvidia,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 WM8753's pins, and the jacks on the board:
|
||||
|
||||
WM8753 pins:
|
||||
|
||||
* LOUT1
|
||||
* LOUT2
|
||||
* ROUT1
|
||||
* ROUT2
|
||||
* MONO1
|
||||
* MONO2
|
||||
* OUT3
|
||||
* OUT4
|
||||
* LINE1
|
||||
* LINE2
|
||||
* RXP
|
||||
* RXN
|
||||
* ACIN
|
||||
* ACOP
|
||||
* MIC1N
|
||||
* MIC1
|
||||
* MIC2N
|
||||
* MIC2
|
||||
* Mic Bias
|
||||
|
||||
Board connectors:
|
||||
sinks are the WM8753's pins as documented in the binding for the WM8753,
|
||||
and the jacks on the board:
|
||||
|
||||
* Headphone Jack
|
||||
* Mic Jack
|
||||
|
|
|
@ -11,28 +11,8 @@ Required properties:
|
|||
- nvidia,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 WM8903's pins, and the jacks on the board:
|
||||
|
||||
WM8903 pins:
|
||||
|
||||
* IN1L
|
||||
* IN1R
|
||||
* IN2L
|
||||
* IN2R
|
||||
* IN3L
|
||||
* IN3R
|
||||
* DMICDAT
|
||||
* HPOUTL
|
||||
* HPOUTR
|
||||
* LINEOUTL
|
||||
* LINEOUTR
|
||||
* LOP
|
||||
* LON
|
||||
* ROP
|
||||
* RON
|
||||
* MICBIAS
|
||||
|
||||
Board connectors:
|
||||
sinks are the WM8903's pins (documented in the WM8903 binding document),
|
||||
and the jacks on the board:
|
||||
|
||||
* Headphone Jack
|
||||
* Int Spk
|
||||
|
|
18
Documentation/devicetree/bindings/sound/pcm1792a.txt
Normal file
18
Documentation/devicetree/bindings/sound/pcm1792a.txt
Normal file
|
@ -0,0 +1,18 @@
|
|||
Texas Instruments pcm1792a DT bindings
|
||||
|
||||
This driver supports the SPI bus.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: "ti,pcm1792a"
|
||||
|
||||
For required properties on SPI, please consult
|
||||
Documentation/devicetree/bindings/spi/spi-bus.txt
|
||||
|
||||
Examples:
|
||||
|
||||
codec_spi: 1792a@0 {
|
||||
compatible = "ti,pcm1792a";
|
||||
spi-max-frequency = <600000>;
|
||||
};
|
||||
|
|
@ -18,6 +18,26 @@ Optional properties:
|
|||
|
||||
- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
|
||||
|
||||
Pins on the device (for linking into audio routes):
|
||||
|
||||
* DMIC1
|
||||
* DMIC2
|
||||
* MICBIAS1
|
||||
* IN1P
|
||||
* IN1R
|
||||
* IN2P
|
||||
* IN2R
|
||||
* HPOL
|
||||
* HPOR
|
||||
* LOUTL
|
||||
* LOUTR
|
||||
* MONOP
|
||||
* MONON
|
||||
* SPOLP
|
||||
* SPOLN
|
||||
* SPORP
|
||||
* SPORN
|
||||
|
||||
Example:
|
||||
|
||||
rt5640 {
|
||||
|
|
|
@ -2,7 +2,15 @@
|
|||
|
||||
Required SoC Specific Properties:
|
||||
|
||||
- compatible : "samsung,i2s-v5"
|
||||
- compatible : should be one of the following.
|
||||
- samsung,s3c6410-i2s: for 8/16/24bit stereo I2S.
|
||||
- samsung,s5pv210-i2s: for 8/16/24bit multichannel(5.1) I2S with
|
||||
secondary fifo, s/w reset control and internal mux for root clk src.
|
||||
- samsung,exynos5420-i2s: for 8/16/24bit multichannel(7.1) I2S with
|
||||
secondary fifo, s/w reset control, internal mux for root clk src and
|
||||
TDM support. TDM (Time division multiplexing) is to allow transfer of
|
||||
multiple channel audio data on single data line.
|
||||
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- dmas: list of DMA controller phandle and DMA request line ordered pairs.
|
||||
|
@ -21,13 +29,6 @@ Required SoC Specific Properties:
|
|||
|
||||
Optional SoC Specific Properties:
|
||||
|
||||
- samsung,supports-6ch: If the I2S Primary sound source has 5.1 Channel
|
||||
support, this flag is enabled.
|
||||
- samsung,supports-rstclr: This flag should be set if I2S software reset bit
|
||||
control is required. When this flag is set I2S software reset bit will be
|
||||
enabled or disabled based on need.
|
||||
- samsung,supports-secdai:If I2S block has a secondary FIFO and internal DMA,
|
||||
then this flag is enabled.
|
||||
- samsung,idma-addr: Internal DMA register base address of the audio
|
||||
sub system(used in secondary sound source).
|
||||
- pinctrl-0: Should specify pin control groups used for this controller.
|
||||
|
@ -36,7 +37,7 @@ Optional SoC Specific Properties:
|
|||
Example:
|
||||
|
||||
i2s0: i2s@03830000 {
|
||||
compatible = "samsung,i2s-v5";
|
||||
compatible = "samsung,s5pv210-i2s";
|
||||
reg = <0x03830000 0x100>;
|
||||
dmas = <&pdma0 10
|
||||
&pdma0 9
|
||||
|
@ -46,9 +47,6 @@ i2s0: i2s@03830000 {
|
|||
<&clock_audss EXYNOS_I2S_BUS>,
|
||||
<&clock_audss EXYNOS_SCLK_I2S>;
|
||||
clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
|
||||
samsung,supports-6ch;
|
||||
samsung,supports-rstclr;
|
||||
samsung,supports-secdai;
|
||||
samsung,idma-addr = <0x03000000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s0_bus>;
|
||||
|
|
28
Documentation/devicetree/bindings/sound/soc-ac97link.txt
Normal file
28
Documentation/devicetree/bindings/sound/soc-ac97link.txt
Normal file
|
@ -0,0 +1,28 @@
|
|||
AC97 link bindings
|
||||
|
||||
These bindings can be included within any other device node.
|
||||
|
||||
Required properties:
|
||||
- pinctrl-names: Has to contain following states to setup the correct
|
||||
pinmuxing for the used gpios:
|
||||
"ac97-running": AC97-link is active
|
||||
"ac97-reset": AC97-link reset state
|
||||
"ac97-warm-reset": AC97-link warm reset state
|
||||
- ac97-gpios: List of gpio phandles with args in the order ac97-sync,
|
||||
ac97-sdata, ac97-reset
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
ssi {
|
||||
...
|
||||
|
||||
pinctrl-names = "default", "ac97-running", "ac97-reset", "ac97-warm-reset";
|
||||
pinctrl-0 = <&ac97link_running>;
|
||||
pinctrl-1 = <&ac97link_running>;
|
||||
pinctrl-2 = <&ac97link_reset>;
|
||||
pinctrl-3 = <&ac97link_warm_reset>;
|
||||
ac97-gpios = <&gpio3 20 0 &gpio3 22 0 &gpio3 28 0>;
|
||||
|
||||
...
|
||||
};
|
15
Documentation/devicetree/bindings/sound/ti,pcm1681.txt
Normal file
15
Documentation/devicetree/bindings/sound/ti,pcm1681.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
Texas Instruments PCM1681 8-channel PWM Processor
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: Should contain "ti,pcm1681".
|
||||
- reg: The i2c address. Should contain <0x4c>.
|
||||
|
||||
Examples:
|
||||
|
||||
i2c_bus {
|
||||
pcm1681@4c {
|
||||
compatible = "ti,pcm1681";
|
||||
reg = <0x4c>;
|
||||
};
|
||||
};
|
|
@ -3,7 +3,14 @@ Texas Instruments - tlv320aic3x Codec module
|
|||
The tlv320aic3x serial control bus communicates through I2C protocols
|
||||
|
||||
Required properties:
|
||||
- compatible - "string" - "ti,tlv320aic3x"
|
||||
|
||||
- compatible - "string" - One of:
|
||||
"ti,tlv320aic3x" - Generic TLV320AIC3x device
|
||||
"ti,tlv320aic33" - TLV320AIC33
|
||||
"ti,tlv320aic3007" - TLV320AIC3007
|
||||
"ti,tlv320aic3106" - TLV320AIC3106
|
||||
|
||||
|
||||
- reg - <int> - I2C slave address
|
||||
|
||||
|
||||
|
|
|
@ -16,3 +16,12 @@ codec: wm8731@1a {
|
|||
compatible = "wlf,wm8731";
|
||||
reg = <0x1a>;
|
||||
};
|
||||
|
||||
Available audio endpoints for an audio-routing table:
|
||||
* LOUT: Left Channel Line Output
|
||||
* ROUT: Right Channel Line Output
|
||||
* LHPOUT: Left Channel Headphone Output
|
||||
* RHPOUT: Right Channel Headphone Output
|
||||
* LLINEIN: Left Channel Line Input
|
||||
* RLINEIN: Right Channel Line Input
|
||||
* MICIN: Microphone Input
|
||||
|
|
|
@ -10,9 +10,31 @@ Required properties:
|
|||
- reg : the I2C address of the device for I2C, the chip select
|
||||
number for SPI.
|
||||
|
||||
Pins on the device (for linking into audio routes):
|
||||
|
||||
* LOUT1
|
||||
* LOUT2
|
||||
* ROUT1
|
||||
* ROUT2
|
||||
* MONO1
|
||||
* MONO2
|
||||
* OUT3
|
||||
* OUT4
|
||||
* LINE1
|
||||
* LINE2
|
||||
* RXP
|
||||
* RXN
|
||||
* ACIN
|
||||
* ACOP
|
||||
* MIC1N
|
||||
* MIC1
|
||||
* MIC2N
|
||||
* MIC2
|
||||
* Mic Bias
|
||||
|
||||
Example:
|
||||
|
||||
codec: wm8737@1a {
|
||||
codec: wm8753@1a {
|
||||
compatible = "wlf,wm8753";
|
||||
reg = <0x1a>;
|
||||
};
|
||||
|
|
|
@ -28,6 +28,25 @@ Optional properties:
|
|||
performed. If any entry has the value 0xffffffff, that GPIO's
|
||||
configuration will not be modified.
|
||||
|
||||
Pins on the device (for linking into audio routes):
|
||||
|
||||
* IN1L
|
||||
* IN1R
|
||||
* IN2L
|
||||
* IN2R
|
||||
* IN3L
|
||||
* IN3R
|
||||
* DMICDAT
|
||||
* HPOUTL
|
||||
* HPOUTR
|
||||
* LINEOUTL
|
||||
* LINEOUTR
|
||||
* LOP
|
||||
* LON
|
||||
* ROP
|
||||
* RON
|
||||
* MICBIAS
|
||||
|
||||
Example:
|
||||
|
||||
codec: wm8903@1a {
|
||||
|
|
|
@ -32,6 +32,10 @@ Optional properties:
|
|||
The second cell is the flags, encoded as the trigger masks from
|
||||
Documentation/devicetree/bindings/interrupts.txt
|
||||
|
||||
- clocks : A list of up to two phandle and clock specifier pairs
|
||||
- clock-names : A list of clock names sorted in the same order as clocks.
|
||||
Valid clock names are "MCLK1" and "MCLK2".
|
||||
|
||||
- wlf,gpio-cfg : A list of GPIO configuration register values. If absent,
|
||||
no configuration of these registers is performed. If any value is
|
||||
over 0xffff then the register will be left as default. If present 11
|
||||
|
|
|
@ -595,6 +595,7 @@ S: Supported
|
|||
F: sound/soc/codecs/adau*
|
||||
F: sound/soc/codecs/adav*
|
||||
F: sound/soc/codecs/ad1*
|
||||
F: sound/soc/codecs/ad7*
|
||||
F: sound/soc/codecs/ssm*
|
||||
F: sound/soc/codecs/sigmadsp.*
|
||||
|
||||
|
@ -7682,6 +7683,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
|
|||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
W: http://alsa-project.org/main/index.php/ASoC
|
||||
S: Supported
|
||||
F: Documentation/sound/alsa/soc/
|
||||
F: sound/soc/
|
||||
F: include/sound/soc*
|
||||
|
||||
|
|
|
@ -405,7 +405,7 @@
|
|||
};
|
||||
|
||||
i2s0: i2s@03830000 {
|
||||
compatible = "samsung,i2s-v5";
|
||||
compatible = "samsung,s5pv210-i2s";
|
||||
reg = <0x03830000 0x100>;
|
||||
dmas = <&pdma0 10
|
||||
&pdma0 9
|
||||
|
@ -415,16 +415,13 @@
|
|||
<&clock_audss EXYNOS_I2S_BUS>,
|
||||
<&clock_audss EXYNOS_SCLK_I2S>;
|
||||
clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
|
||||
samsung,supports-6ch;
|
||||
samsung,supports-rstclr;
|
||||
samsung,supports-secdai;
|
||||
samsung,idma-addr = <0x03000000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s0_bus>;
|
||||
};
|
||||
|
||||
i2s1: i2s@12D60000 {
|
||||
compatible = "samsung,i2s-v5";
|
||||
compatible = "samsung,s3c6410-i2s";
|
||||
reg = <0x12D60000 0x100>;
|
||||
dmas = <&pdma1 12
|
||||
&pdma1 11>;
|
||||
|
@ -436,7 +433,7 @@
|
|||
};
|
||||
|
||||
i2s2: i2s@12D70000 {
|
||||
compatible = "samsung,i2s-v5";
|
||||
compatible = "samsung,s3c6410-i2s";
|
||||
reg = <0x12D70000 0x100>;
|
||||
dmas = <&pdma0 12
|
||||
&pdma0 11>;
|
||||
|
|
|
@ -108,8 +108,8 @@ static void __init dove_clk_init(void)
|
|||
orion_clkdev_add(NULL, "sdhci-dove.1", sdio1);
|
||||
orion_clkdev_add(NULL, "orion_nand", nand);
|
||||
orion_clkdev_add(NULL, "cafe1000-ccic.0", camera);
|
||||
orion_clkdev_add(NULL, "kirkwood-i2s.0", i2s0);
|
||||
orion_clkdev_add(NULL, "kirkwood-i2s.1", i2s1);
|
||||
orion_clkdev_add(NULL, "mvebu-audio.0", i2s0);
|
||||
orion_clkdev_add(NULL, "mvebu-audio.1", i2s1);
|
||||
orion_clkdev_add(NULL, "mv_crypto", crypto);
|
||||
orion_clkdev_add(NULL, "dove-ac97", ac97);
|
||||
orion_clkdev_add(NULL, "dove-pdma", pdma);
|
||||
|
|
|
@ -264,7 +264,7 @@ void __init kirkwood_clk_init(void)
|
|||
orion_clkdev_add(NULL, MV_XOR_NAME ".1", xor1);
|
||||
orion_clkdev_add("0", "pcie", pex0);
|
||||
orion_clkdev_add("1", "pcie", pex1);
|
||||
orion_clkdev_add(NULL, "kirkwood-i2s", audio);
|
||||
orion_clkdev_add(NULL, "mvebu-audio", audio);
|
||||
orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".0", runit);
|
||||
orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".1", runit);
|
||||
|
||||
|
@ -560,7 +560,7 @@ void __init kirkwood_timer_init(void)
|
|||
/*****************************************************************************
|
||||
* Audio
|
||||
****************************************************************************/
|
||||
static struct resource kirkwood_i2s_resources[] = {
|
||||
static struct resource kirkwood_audio_resources[] = {
|
||||
[0] = {
|
||||
.start = AUDIO_PHYS_BASE,
|
||||
.end = AUDIO_PHYS_BASE + SZ_16K - 1,
|
||||
|
@ -573,29 +573,23 @@ static struct resource kirkwood_i2s_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct kirkwood_asoc_platform_data kirkwood_i2s_data = {
|
||||
static struct kirkwood_asoc_platform_data kirkwood_audio_data = {
|
||||
.burst = 128,
|
||||
};
|
||||
|
||||
static struct platform_device kirkwood_i2s_device = {
|
||||
.name = "kirkwood-i2s",
|
||||
static struct platform_device kirkwood_audio_device = {
|
||||
.name = "mvebu-audio",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(kirkwood_i2s_resources),
|
||||
.resource = kirkwood_i2s_resources,
|
||||
.num_resources = ARRAY_SIZE(kirkwood_audio_resources),
|
||||
.resource = kirkwood_audio_resources,
|
||||
.dev = {
|
||||
.platform_data = &kirkwood_i2s_data,
|
||||
.platform_data = &kirkwood_audio_data,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device kirkwood_pcm_device = {
|
||||
.name = "kirkwood-pcm-audio",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
void __init kirkwood_audio_init(void)
|
||||
{
|
||||
platform_device_register(&kirkwood_i2s_device);
|
||||
platform_device_register(&kirkwood_pcm_device);
|
||||
platform_device_register(&kirkwood_audio_device);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/pxa2xx_spi.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <mach/hardware.h>
|
||||
|
@ -60,6 +62,30 @@ struct ssp_device *pxa_ssp_request(int port, const char *label)
|
|||
}
|
||||
EXPORT_SYMBOL(pxa_ssp_request);
|
||||
|
||||
struct ssp_device *pxa_ssp_request_of(const struct device_node *of_node,
|
||||
const char *label)
|
||||
{
|
||||
struct ssp_device *ssp = NULL;
|
||||
|
||||
mutex_lock(&ssp_lock);
|
||||
|
||||
list_for_each_entry(ssp, &ssp_list, node) {
|
||||
if (ssp->of_node == of_node && ssp->use_count == 0) {
|
||||
ssp->use_count++;
|
||||
ssp->label = label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&ssp_lock);
|
||||
|
||||
if (&ssp->node == &ssp_list)
|
||||
return NULL;
|
||||
|
||||
return ssp;
|
||||
}
|
||||
EXPORT_SYMBOL(pxa_ssp_request_of);
|
||||
|
||||
void pxa_ssp_free(struct ssp_device *ssp)
|
||||
{
|
||||
mutex_lock(&ssp_lock);
|
||||
|
@ -72,96 +98,126 @@ void pxa_ssp_free(struct ssp_device *ssp)
|
|||
}
|
||||
EXPORT_SYMBOL(pxa_ssp_free);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id pxa_ssp_of_ids[] = {
|
||||
{ .compatible = "mrvl,pxa25x-ssp", .data = (void *) PXA25x_SSP },
|
||||
{ .compatible = "mvrl,pxa25x-nssp", .data = (void *) PXA25x_NSSP },
|
||||
{ .compatible = "mrvl,pxa27x-ssp", .data = (void *) PXA27x_SSP },
|
||||
{ .compatible = "mrvl,pxa3xx-ssp", .data = (void *) PXA3xx_SSP },
|
||||
{ .compatible = "mvrl,pxa168-ssp", .data = (void *) PXA168_SSP },
|
||||
{ .compatible = "mrvl,pxa910-ssp", .data = (void *) PXA910_SSP },
|
||||
{ .compatible = "mrvl,ce4100-ssp", .data = (void *) CE4100_SSP },
|
||||
{ .compatible = "mrvl,lpss-ssp", .data = (void *) LPSS_SSP },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pxa_ssp_of_ids);
|
||||
#endif
|
||||
|
||||
static int pxa_ssp_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct platform_device_id *id = platform_get_device_id(pdev);
|
||||
struct resource *res;
|
||||
struct ssp_device *ssp;
|
||||
int ret = 0;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
ssp = kzalloc(sizeof(struct ssp_device), GFP_KERNEL);
|
||||
if (ssp == NULL) {
|
||||
dev_err(&pdev->dev, "failed to allocate memory");
|
||||
ssp = devm_kzalloc(dev, sizeof(struct ssp_device), GFP_KERNEL);
|
||||
if (ssp == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ssp->pdev = pdev;
|
||||
|
||||
ssp->clk = clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(ssp->clk)) {
|
||||
ret = PTR_ERR(ssp->clk);
|
||||
goto err_free;
|
||||
}
|
||||
ssp->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(ssp->clk))
|
||||
return PTR_ERR(ssp->clk);
|
||||
|
||||
if (dev->of_node) {
|
||||
struct of_phandle_args dma_spec;
|
||||
struct device_node *np = dev->of_node;
|
||||
|
||||
/*
|
||||
* FIXME: we should allocate the DMA channel from this
|
||||
* context and pass the channel down to the ssp users.
|
||||
* For now, we lookup the rx and tx indices manually
|
||||
*/
|
||||
|
||||
/* rx */
|
||||
of_parse_phandle_with_args(np, "dmas", "#dma-cells",
|
||||
0, &dma_spec);
|
||||
ssp->drcmr_rx = dma_spec.args[0];
|
||||
of_node_put(dma_spec.np);
|
||||
|
||||
/* tx */
|
||||
of_parse_phandle_with_args(np, "dmas", "#dma-cells",
|
||||
1, &dma_spec);
|
||||
ssp->drcmr_tx = dma_spec.args[0];
|
||||
of_node_put(dma_spec.np);
|
||||
} else {
|
||||
res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "no SSP RX DRCMR defined\n");
|
||||
ret = -ENODEV;
|
||||
goto err_free_clk;
|
||||
dev_err(dev, "no SSP RX DRCMR defined\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
ssp->drcmr_rx = res->start;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "no SSP TX DRCMR defined\n");
|
||||
ret = -ENODEV;
|
||||
goto err_free_clk;
|
||||
dev_err(dev, "no SSP TX DRCMR defined\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
ssp->drcmr_tx = res->start;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "no memory resource defined\n");
|
||||
ret = -ENODEV;
|
||||
goto err_free_clk;
|
||||
dev_err(dev, "no memory resource defined\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
res = request_mem_region(res->start, resource_size(res),
|
||||
res = devm_request_mem_region(dev, res->start, resource_size(res),
|
||||
pdev->name);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "failed to request memory resource\n");
|
||||
ret = -EBUSY;
|
||||
goto err_free_clk;
|
||||
dev_err(dev, "failed to request memory resource\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ssp->phys_base = res->start;
|
||||
|
||||
ssp->mmio_base = ioremap(res->start, resource_size(res));
|
||||
ssp->mmio_base = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (ssp->mmio_base == NULL) {
|
||||
dev_err(&pdev->dev, "failed to ioremap() registers\n");
|
||||
ret = -ENODEV;
|
||||
goto err_free_mem;
|
||||
dev_err(dev, "failed to ioremap() registers\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ssp->irq = platform_get_irq(pdev, 0);
|
||||
if (ssp->irq < 0) {
|
||||
dev_err(&pdev->dev, "no IRQ resource defined\n");
|
||||
ret = -ENODEV;
|
||||
goto err_free_io;
|
||||
dev_err(dev, "no IRQ resource defined\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (dev->of_node) {
|
||||
const struct of_device_id *id =
|
||||
of_match_device(of_match_ptr(pxa_ssp_of_ids), dev);
|
||||
ssp->type = (int) id->data;
|
||||
} else {
|
||||
const struct platform_device_id *id =
|
||||
platform_get_device_id(pdev);
|
||||
ssp->type = (int) id->driver_data;
|
||||
|
||||
/* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id
|
||||
* starts from 0, do a translation here
|
||||
*/
|
||||
ssp->port_id = pdev->id + 1;
|
||||
}
|
||||
|
||||
ssp->use_count = 0;
|
||||
ssp->type = (int)id->driver_data;
|
||||
ssp->of_node = dev->of_node;
|
||||
|
||||
mutex_lock(&ssp_lock);
|
||||
list_add(&ssp->node, &ssp_list);
|
||||
mutex_unlock(&ssp_lock);
|
||||
|
||||
platform_set_drvdata(pdev, ssp);
|
||||
return 0;
|
||||
|
||||
err_free_io:
|
||||
iounmap(ssp->mmio_base);
|
||||
err_free_mem:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
err_free_clk:
|
||||
clk_put(ssp->clk);
|
||||
err_free:
|
||||
kfree(ssp);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pxa_ssp_remove(struct platform_device *pdev)
|
||||
|
@ -203,6 +259,7 @@ static struct platform_driver pxa_ssp_driver = {
|
|||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "pxa2xx-ssp",
|
||||
.of_match_table = of_match_ptr(pxa_ssp_of_ids),
|
||||
},
|
||||
.id_table = ssp_id_table,
|
||||
};
|
||||
|
|
56
include/dt-bindings/sound/fsl-imx-audmux.h
Normal file
56
include/dt-bindings/sound/fsl-imx-audmux.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
#ifndef __DT_FSL_IMX_AUDMUX_H
|
||||
#define __DT_FSL_IMX_AUDMUX_H
|
||||
|
||||
#define MX27_AUDMUX_HPCR1_SSI0 0
|
||||
#define MX27_AUDMUX_HPCR2_SSI1 1
|
||||
#define MX27_AUDMUX_HPCR3_SSI_PINS_4 2
|
||||
#define MX27_AUDMUX_PPCR1_SSI_PINS_1 3
|
||||
#define MX27_AUDMUX_PPCR2_SSI_PINS_2 4
|
||||
#define MX27_AUDMUX_PPCR3_SSI_PINS_3 5
|
||||
|
||||
#define MX31_AUDMUX_PORT1_SSI0 0
|
||||
#define MX31_AUDMUX_PORT2_SSI1 1
|
||||
#define MX31_AUDMUX_PORT3_SSI_PINS_3 2
|
||||
#define MX31_AUDMUX_PORT4_SSI_PINS_4 3
|
||||
#define MX31_AUDMUX_PORT5_SSI_PINS_5 4
|
||||
#define MX31_AUDMUX_PORT6_SSI_PINS_6 5
|
||||
#define MX31_AUDMUX_PORT7_SSI_PINS_7 6
|
||||
|
||||
#define MX51_AUDMUX_PORT1_SSI0 0
|
||||
#define MX51_AUDMUX_PORT2_SSI1 1
|
||||
#define MX51_AUDMUX_PORT3 2
|
||||
#define MX51_AUDMUX_PORT4 3
|
||||
#define MX51_AUDMUX_PORT5 4
|
||||
#define MX51_AUDMUX_PORT6 5
|
||||
#define MX51_AUDMUX_PORT7 6
|
||||
|
||||
/* Register definitions for the i.MX21/27 Digital Audio Multiplexer */
|
||||
#define IMX_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff)
|
||||
#define IMX_AUDMUX_V1_PCR_INMEN (1 << 8)
|
||||
#define IMX_AUDMUX_V1_PCR_TXRXEN (1 << 10)
|
||||
#define IMX_AUDMUX_V1_PCR_SYN (1 << 12)
|
||||
#define IMX_AUDMUX_V1_PCR_RXDSEL(x) (((x) & 0x7) << 13)
|
||||
#define IMX_AUDMUX_V1_PCR_RFCSEL(x) (((x) & 0xf) << 20)
|
||||
#define IMX_AUDMUX_V1_PCR_RCLKDIR (1 << 24)
|
||||
#define IMX_AUDMUX_V1_PCR_RFSDIR (1 << 25)
|
||||
#define IMX_AUDMUX_V1_PCR_TFCSEL(x) (((x) & 0xf) << 26)
|
||||
#define IMX_AUDMUX_V1_PCR_TCLKDIR (1 << 30)
|
||||
#define IMX_AUDMUX_V1_PCR_TFSDIR (1 << 31)
|
||||
|
||||
/* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */
|
||||
#define IMX_AUDMUX_V2_PTCR_TFSDIR (1 << 31)
|
||||
#define IMX_AUDMUX_V2_PTCR_TFSEL(x) (((x) & 0xf) << 27)
|
||||
#define IMX_AUDMUX_V2_PTCR_TCLKDIR (1 << 26)
|
||||
#define IMX_AUDMUX_V2_PTCR_TCSEL(x) (((x) & 0xf) << 22)
|
||||
#define IMX_AUDMUX_V2_PTCR_RFSDIR (1 << 21)
|
||||
#define IMX_AUDMUX_V2_PTCR_RFSEL(x) (((x) & 0xf) << 17)
|
||||
#define IMX_AUDMUX_V2_PTCR_RCLKDIR (1 << 16)
|
||||
#define IMX_AUDMUX_V2_PTCR_RCSEL(x) (((x) & 0xf) << 12)
|
||||
#define IMX_AUDMUX_V2_PTCR_SYN (1 << 11)
|
||||
|
||||
#define IMX_AUDMUX_V2_PDCR_RXDSEL(x) (((x) & 0x7) << 13)
|
||||
#define IMX_AUDMUX_V2_PDCR_TXRXEN (1 << 12)
|
||||
#define IMX_AUDMUX_V2_PDCR_MODE(x) (((x) & 0x3) << 8)
|
||||
#define IMX_AUDMUX_V2_PDCR_INMMASK(x) ((x) & 0xff)
|
||||
|
||||
#endif /* __DT_FSL_IMX_AUDMUX_H */
|
|
@ -11,7 +11,7 @@ struct atmel_ssc_platform_data {
|
|||
|
||||
struct ssc_device {
|
||||
struct list_head list;
|
||||
resource_size_t phybase;
|
||||
dma_addr_t phybase;
|
||||
void __iomem *regs;
|
||||
struct platform_device *pdev;
|
||||
struct atmel_ssc_platform_data *pdata;
|
||||
|
|
96
include/linux/mfd/arizona/gpio.h
Normal file
96
include/linux/mfd/arizona/gpio.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* GPIO configuration for Arizona devices
|
||||
*
|
||||
* Copyright 2013 Wolfson Microelectronics. PLC.
|
||||
*
|
||||
* Author: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _ARIZONA_GPIO_H
|
||||
#define _ARIZONA_GPIO_H
|
||||
|
||||
#define ARIZONA_GP_FN_TXLRCLK 0x00
|
||||
#define ARIZONA_GP_FN_GPIO 0x01
|
||||
#define ARIZONA_GP_FN_IRQ1 0x02
|
||||
#define ARIZONA_GP_FN_IRQ2 0x03
|
||||
#define ARIZONA_GP_FN_OPCLK 0x04
|
||||
#define ARIZONA_GP_FN_FLL1_OUT 0x05
|
||||
#define ARIZONA_GP_FN_FLL2_OUT 0x06
|
||||
#define ARIZONA_GP_FN_PWM1 0x08
|
||||
#define ARIZONA_GP_FN_PWM2 0x09
|
||||
#define ARIZONA_GP_FN_SYSCLK_UNDERCLOCKED 0x0A
|
||||
#define ARIZONA_GP_FN_ASYNCCLK_UNDERCLOCKED 0x0B
|
||||
#define ARIZONA_GP_FN_FLL1_LOCK 0x0C
|
||||
#define ARIZONA_GP_FN_FLL2_LOCK 0x0D
|
||||
#define ARIZONA_GP_FN_FLL1_CLOCK_OK 0x0F
|
||||
#define ARIZONA_GP_FN_FLL2_CLOCK_OK 0x10
|
||||
#define ARIZONA_GP_FN_HEADPHONE_DET 0x12
|
||||
#define ARIZONA_GP_FN_MIC_DET 0x13
|
||||
#define ARIZONA_GP_FN_WSEQ_STATUS 0x15
|
||||
#define ARIZONA_GP_FN_CIF_ADDRESS_ERROR 0x16
|
||||
#define ARIZONA_GP_FN_ASRC1_LOCK 0x1A
|
||||
#define ARIZONA_GP_FN_ASRC2_LOCK 0x1B
|
||||
#define ARIZONA_GP_FN_ASRC_CONFIG_ERROR 0x1C
|
||||
#define ARIZONA_GP_FN_DRC1_SIGNAL_DETECT 0x1D
|
||||
#define ARIZONA_GP_FN_DRC1_ANTICLIP 0x1E
|
||||
#define ARIZONA_GP_FN_DRC1_DECAY 0x1F
|
||||
#define ARIZONA_GP_FN_DRC1_NOISE 0x20
|
||||
#define ARIZONA_GP_FN_DRC1_QUICK_RELEASE 0x21
|
||||
#define ARIZONA_GP_FN_DRC2_SIGNAL_DETECT 0x22
|
||||
#define ARIZONA_GP_FN_DRC2_ANTICLIP 0x23
|
||||
#define ARIZONA_GP_FN_DRC2_DECAY 0x24
|
||||
#define ARIZONA_GP_FN_DRC2_NOISE 0x25
|
||||
#define ARIZONA_GP_FN_DRC2_QUICK_RELEASE 0x26
|
||||
#define ARIZONA_GP_FN_MIXER_DROPPED_SAMPLE 0x27
|
||||
#define ARIZONA_GP_FN_AIF1_CONFIG_ERROR 0x28
|
||||
#define ARIZONA_GP_FN_AIF2_CONFIG_ERROR 0x29
|
||||
#define ARIZONA_GP_FN_AIF3_CONFIG_ERROR 0x2A
|
||||
#define ARIZONA_GP_FN_SPK_TEMP_SHUTDOWN 0x2B
|
||||
#define ARIZONA_GP_FN_SPK_TEMP_WARNING 0x2C
|
||||
#define ARIZONA_GP_FN_UNDERCLOCKED 0x2D
|
||||
#define ARIZONA_GP_FN_OVERCLOCKED 0x2E
|
||||
#define ARIZONA_GP_FN_DSP_IRQ1 0x35
|
||||
#define ARIZONA_GP_FN_DSP_IRQ2 0x36
|
||||
#define ARIZONA_GP_FN_ASYNC_OPCLK 0x3D
|
||||
#define ARIZONA_GP_FN_BOOT_DONE 0x44
|
||||
#define ARIZONA_GP_FN_DSP1_RAM_READY 0x45
|
||||
#define ARIZONA_GP_FN_SYSCLK_ENA_STATUS 0x4B
|
||||
#define ARIZONA_GP_FN_ASYNCCLK_ENA_STATUS 0x4C
|
||||
|
||||
#define ARIZONA_GPN_DIR 0x8000 /* GPN_DIR */
|
||||
#define ARIZONA_GPN_DIR_MASK 0x8000 /* GPN_DIR */
|
||||
#define ARIZONA_GPN_DIR_SHIFT 15 /* GPN_DIR */
|
||||
#define ARIZONA_GPN_DIR_WIDTH 1 /* GPN_DIR */
|
||||
#define ARIZONA_GPN_PU 0x4000 /* GPN_PU */
|
||||
#define ARIZONA_GPN_PU_MASK 0x4000 /* GPN_PU */
|
||||
#define ARIZONA_GPN_PU_SHIFT 14 /* GPN_PU */
|
||||
#define ARIZONA_GPN_PU_WIDTH 1 /* GPN_PU */
|
||||
#define ARIZONA_GPN_PD 0x2000 /* GPN_PD */
|
||||
#define ARIZONA_GPN_PD_MASK 0x2000 /* GPN_PD */
|
||||
#define ARIZONA_GPN_PD_SHIFT 13 /* GPN_PD */
|
||||
#define ARIZONA_GPN_PD_WIDTH 1 /* GPN_PD */
|
||||
#define ARIZONA_GPN_LVL 0x0800 /* GPN_LVL */
|
||||
#define ARIZONA_GPN_LVL_MASK 0x0800 /* GPN_LVL */
|
||||
#define ARIZONA_GPN_LVL_SHIFT 11 /* GPN_LVL */
|
||||
#define ARIZONA_GPN_LVL_WIDTH 1 /* GPN_LVL */
|
||||
#define ARIZONA_GPN_POL 0x0400 /* GPN_POL */
|
||||
#define ARIZONA_GPN_POL_MASK 0x0400 /* GPN_POL */
|
||||
#define ARIZONA_GPN_POL_SHIFT 10 /* GPN_POL */
|
||||
#define ARIZONA_GPN_POL_WIDTH 1 /* GPN_POL */
|
||||
#define ARIZONA_GPN_OP_CFG 0x0200 /* GPN_OP_CFG */
|
||||
#define ARIZONA_GPN_OP_CFG_MASK 0x0200 /* GPN_OP_CFG */
|
||||
#define ARIZONA_GPN_OP_CFG_SHIFT 9 /* GPN_OP_CFG */
|
||||
#define ARIZONA_GPN_OP_CFG_WIDTH 1 /* GPN_OP_CFG */
|
||||
#define ARIZONA_GPN_DB 0x0100 /* GPN_DB */
|
||||
#define ARIZONA_GPN_DB_MASK 0x0100 /* GPN_DB */
|
||||
#define ARIZONA_GPN_DB_SHIFT 8 /* GPN_DB */
|
||||
#define ARIZONA_GPN_DB_WIDTH 1 /* GPN_DB */
|
||||
#define ARIZONA_GPN_FN_MASK 0x007F /* GPN_DB */
|
||||
#define ARIZONA_GPN_FN_SHIFT 0 /* GPN_DB */
|
||||
#define ARIZONA_GPN_FN_WIDTH 7 /* GPN_DB */
|
||||
|
||||
#endif
|
|
@ -36,6 +36,7 @@ struct samsung_i2s {
|
|||
*/
|
||||
#define QUIRK_NO_MUXPSR (1 << 2)
|
||||
#define QUIRK_NEED_RSTCLR (1 << 3)
|
||||
#define QUIRK_SUPPORTS_TDM (1 << 4)
|
||||
/* Quirks of the I2S controller */
|
||||
u32 quirks;
|
||||
dma_addr_t idma_addr;
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
/**
|
||||
* omap-abe-twl6040.h - ASoC machine driver OMAP4+ devices, header.
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _OMAP_ABE_TWL6040_H_
|
||||
#define _OMAP_ABE_TWL6040_H_
|
||||
|
||||
/* To select if only one channel is connected in a stereo port */
|
||||
#define ABE_TWL6040_LEFT (1 << 0)
|
||||
#define ABE_TWL6040_RIGHT (1 << 1)
|
||||
|
||||
struct omap_abe_twl6040_data {
|
||||
char *card_name;
|
||||
/* Feature flags for connected audio pins */
|
||||
u8 has_hs;
|
||||
u8 has_hf;
|
||||
bool has_ep;
|
||||
u8 has_aux;
|
||||
u8 has_vibra;
|
||||
bool has_dmic;
|
||||
bool has_hsmic;
|
||||
bool has_mainmic;
|
||||
bool has_submic;
|
||||
u8 has_afm;
|
||||
/* Other features */
|
||||
bool jack_detection; /* board can detect jack events */
|
||||
int mclk_freq; /* MCLK frequency speed for twl6040 */
|
||||
};
|
||||
|
||||
#endif /* _OMAP_ABE_TWL6040_H_ */
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include <linux/list.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
|
||||
/*
|
||||
* SSP Serial Port Registers
|
||||
|
@ -190,6 +192,8 @@ struct ssp_device {
|
|||
int irq;
|
||||
int drcmr_rx;
|
||||
int drcmr_tx;
|
||||
|
||||
struct device_node *of_node;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -218,11 +222,18 @@ static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg)
|
|||
#ifdef CONFIG_ARCH_PXA
|
||||
struct ssp_device *pxa_ssp_request(int port, const char *label);
|
||||
void pxa_ssp_free(struct ssp_device *);
|
||||
struct ssp_device *pxa_ssp_request_of(const struct device_node *of_node,
|
||||
const char *label);
|
||||
#else
|
||||
static inline struct ssp_device *pxa_ssp_request(int port, const char *label)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline struct ssp_device *pxa_ssp_request_of(const struct device_node *n,
|
||||
const char *name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline void pxa_ssp_free(struct ssp_device *ssp) {}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -6,13 +6,6 @@
|
|||
|
||||
/* PCM */
|
||||
|
||||
struct pxa2xx_pcm_dma_params {
|
||||
char *name; /* stream identifier */
|
||||
u32 dcmd; /* DMA descriptor dcmd field */
|
||||
volatile u32 *drcmr; /* the DMA request channel to use */
|
||||
u32 dev_addr; /* device physical address for DMA */
|
||||
};
|
||||
|
||||
extern int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params);
|
||||
extern int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream);
|
||||
|
|
84
include/sound/rcar_snd.h
Normal file
84
include/sound/rcar_snd.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Renesas R-Car SRU/SCU/SSIU/SSI support
|
||||
*
|
||||
* Copyright (C) 2013 Renesas Solutions Corp.
|
||||
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef RCAR_SND_H
|
||||
#define RCAR_SND_H
|
||||
|
||||
#include <linux/sh_clk.h>
|
||||
|
||||
#define RSND_GEN1_SRU 0
|
||||
#define RSND_GEN1_ADG 1
|
||||
#define RSND_GEN1_SSI 2
|
||||
|
||||
#define RSND_GEN2_SRU 0
|
||||
#define RSND_GEN2_ADG 1
|
||||
#define RSND_GEN2_SSIU 2
|
||||
#define RSND_GEN2_SSI 3
|
||||
|
||||
#define RSND_BASE_MAX 4
|
||||
|
||||
/*
|
||||
* flags
|
||||
*
|
||||
* 0xAB000000
|
||||
*
|
||||
* A : clock sharing settings
|
||||
* B : SSI direction
|
||||
*/
|
||||
#define RSND_SSI_CLK_PIN_SHARE (1 << 31)
|
||||
#define RSND_SSI_CLK_FROM_ADG (1 << 30) /* clock parent is master */
|
||||
#define RSND_SSI_SYNC (1 << 29) /* SSI34_sync etc */
|
||||
#define RSND_SSI_DEPENDENT (1 << 28) /* SSI needs SRU/SCU */
|
||||
|
||||
#define RSND_SSI_PLAY (1 << 24)
|
||||
|
||||
#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 dma_id;
|
||||
int pio_irq;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* flags
|
||||
*/
|
||||
#define RSND_SCU_USB_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */
|
||||
|
||||
struct rsnd_scu_platform_info {
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* flags
|
||||
*
|
||||
* 0x0000000A
|
||||
*
|
||||
* A : generation
|
||||
*/
|
||||
#define RSND_GEN1 (1 << 0) /* fixme */
|
||||
#define RSND_GEN2 (2 << 0) /* fixme */
|
||||
|
||||
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;
|
||||
int (*start)(int id);
|
||||
int (*stop)(int id);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -70,121 +70,144 @@ struct device;
|
|||
.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
|
||||
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
|
||||
|
||||
#define SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) \
|
||||
.reg = wreg, .mask = 1, .shift = wshift, \
|
||||
.on_val = winvert ? 0 : 1, .off_val = winvert ? 1 : 0
|
||||
|
||||
/* path domain */
|
||||
#define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\
|
||||
wcontrols, wncontrols) \
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
||||
#define SND_SOC_DAPM_OUT_DRV(wname, wreg, wshift, winvert,\
|
||||
wcontrols, wncontrols) \
|
||||
{ .id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
||||
{ .id = snd_soc_dapm_out_drv, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
||||
#define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \
|
||||
wcontrols, wncontrols)\
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
||||
#define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \
|
||||
wcontrols, wncontrols)\
|
||||
{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \
|
||||
.shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \
|
||||
.num_kcontrols = wncontrols}
|
||||
{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
||||
#define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \
|
||||
{ .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = NULL, .num_kcontrols = 0}
|
||||
{ .id = snd_soc_dapm_micbias, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = NULL, .num_kcontrols = 0}
|
||||
#define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \
|
||||
{ .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||
{ .id = snd_soc_dapm_switch, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||
#define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
|
||||
{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||
{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, \
|
||||
.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, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||
{ .id = snd_soc_dapm_virt_mux, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||
#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \
|
||||
{ .id = snd_soc_dapm_value_mux, .name = wname, .reg = wreg, \
|
||||
.shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \
|
||||
.num_kcontrols = 1}
|
||||
{ .id = snd_soc_dapm_value_mux, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||
|
||||
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
|
||||
#define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\
|
||||
wcontrols) \
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
|
||||
#define SOC_MIXER_ARRAY(wname, wreg, wshift, winvert, \
|
||||
wcontrols)\
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
|
||||
#define SOC_MIXER_NAMED_CTL_ARRAY(wname, wreg, wshift, winvert, \
|
||||
wcontrols)\
|
||||
{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \
|
||||
.shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \
|
||||
.num_kcontrols = ARRAY_SIZE(wcontrols)}
|
||||
{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
|
||||
|
||||
/* path domain with event - event handler must return 0 for success */
|
||||
#define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wncontrols, wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wncontrols, wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
||||
{ .id = snd_soc_dapm_out_drv, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wncontrols, wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \
|
||||
wcontrols, wncontrols, wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, \
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, \
|
||||
.num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \
|
||||
{ .id = snd_soc_dapm_switch, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1, \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \
|
||||
{ .id = snd_soc_dapm_mux, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1, \
|
||||
.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, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \
|
||||
{ .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}
|
||||
|
||||
/* additional sequencing control within an event type */
|
||||
#define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .event = wevent, .event_flags = wflags, \
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.event = wevent, .event_flags = wflags, \
|
||||
.subseq = wsubseq}
|
||||
#define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \
|
||||
wflags) \
|
||||
{ .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \
|
||||
.shift = wshift, .invert = winvert, .event = wevent, \
|
||||
.event_flags = wflags, .subseq = wsubseq}
|
||||
{ .id = snd_soc_dapm_supply, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.event = wevent, .event_flags = wflags, .subseq = wsubseq}
|
||||
|
||||
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
|
||||
#define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SOC_MIXER_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SOC_MIXER_NAMED_CTL_E_ARRAY(wname, wreg, wshift, winvert, \
|
||||
wcontrols, wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
|
||||
.invert = winvert, .kcontrol_news = wcontrols, \
|
||||
.num_kcontrols = ARRAY_SIZE(wcontrols), .event = wevent, .event_flags = wflags}
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
|
||||
/* events that are pre and post DAPM */
|
||||
#define SND_SOC_DAPM_PRE(wname, wevent) \
|
||||
|
@ -199,35 +222,36 @@ struct device;
|
|||
/* stream domain */
|
||||
#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \
|
||||
{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
|
||||
.reg = wreg, .shift = wshift, .invert = winvert }
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
|
||||
#define SND_SOC_DAPM_AIF_IN_E(wname, stname, wslot, wreg, wshift, winvert, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
|
||||
.reg = wreg, .shift = wshift, .invert = winvert, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.event = wevent, .event_flags = wflags }
|
||||
#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \
|
||||
{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
|
||||
.reg = wreg, .shift = wshift, .invert = winvert }
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
|
||||
#define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wslot, wreg, wshift, winvert, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
|
||||
.reg = wreg, .shift = wshift, .invert = winvert, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.event = wevent, .event_flags = wflags }
|
||||
#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
|
||||
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \
|
||||
.shift = wshift, .invert = winvert}
|
||||
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) }
|
||||
#define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \
|
||||
.shift = wshift, .invert = winvert, \
|
||||
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
|
||||
#define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \
|
||||
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
|
||||
.shift = wshift, .invert = winvert}
|
||||
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
|
||||
#define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
|
||||
.shift = wshift, .invert = winvert, \
|
||||
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \
|
||||
{ .id = snd_soc_dapm_clock_supply, .name = wname, \
|
||||
|
@ -241,14 +265,14 @@ struct device;
|
|||
.on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \
|
||||
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
|
||||
#define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \
|
||||
.shift = wshift, .invert = winvert, .event = wevent, \
|
||||
.event_flags = wflags}
|
||||
{ .id = snd_soc_dapm_supply, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \
|
||||
{ .id = snd_soc_dapm_regulator_supply, .name = wname, \
|
||||
.reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \
|
||||
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \
|
||||
.invert = wflags}
|
||||
.on_val = wflags}
|
||||
|
||||
|
||||
/* dapm kcontrol types */
|
||||
|
@ -256,14 +280,26 @@ struct device;
|
|||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
|
||||
#define SOC_DAPM_SINGLE_AUTODISABLE(xname, reg, shift, max, invert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
|
||||
#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
|
||||
#define SOC_DAPM_SINGLE_TLV_AUTODISABLE(xname, reg, shift, max, invert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
|
||||
#define SOC_DAPM_ENUM(xname, xenum) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_enum_double, \
|
||||
|
@ -333,6 +369,7 @@ struct snd_soc_dapm_route;
|
|||
struct snd_soc_dapm_context;
|
||||
struct regulator;
|
||||
struct snd_soc_dapm_widget_list;
|
||||
struct snd_soc_dapm_update;
|
||||
|
||||
int dapm_reg_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event);
|
||||
|
@ -391,10 +428,12 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
|
|||
void snd_soc_dapm_shutdown(struct snd_soc_card *card);
|
||||
|
||||
/* external DAPM widget events */
|
||||
int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
|
||||
struct snd_kcontrol *kcontrol, int connect);
|
||||
int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
|
||||
struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e);
|
||||
int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
|
||||
struct snd_kcontrol *kcontrol, int connect,
|
||||
struct snd_soc_dapm_update *update);
|
||||
int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm,
|
||||
struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e,
|
||||
struct snd_soc_dapm_update *update);
|
||||
|
||||
/* dapm sys fs - used by the core */
|
||||
int snd_soc_dapm_sys_add(struct device *dev);
|
||||
|
@ -424,6 +463,8 @@ void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm);
|
|||
int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
|
||||
struct snd_soc_dapm_widget_list **list);
|
||||
|
||||
struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol);
|
||||
|
||||
/* dapm widget types */
|
||||
enum snd_soc_dapm_type {
|
||||
snd_soc_dapm_input = 0, /* input pin */
|
||||
|
@ -455,6 +496,7 @@ enum snd_soc_dapm_type {
|
|||
snd_soc_dapm_dai_in, /* link to DAI structure */
|
||||
snd_soc_dapm_dai_out,
|
||||
snd_soc_dapm_dai_link, /* link between two DAI structures */
|
||||
snd_soc_dapm_kcontrol, /* Auto-disabled kcontrol */
|
||||
};
|
||||
|
||||
enum snd_soc_dapm_subclass {
|
||||
|
@ -485,7 +527,6 @@ struct snd_soc_dapm_path {
|
|||
/* source (input) and sink (output) widgets */
|
||||
struct snd_soc_dapm_widget *source;
|
||||
struct snd_soc_dapm_widget *sink;
|
||||
struct snd_kcontrol *kcontrol;
|
||||
|
||||
/* status */
|
||||
u32 connect:1; /* source and sink widgets are connected */
|
||||
|
@ -498,6 +539,7 @@ struct snd_soc_dapm_path {
|
|||
|
||||
struct list_head list_source;
|
||||
struct list_head list_sink;
|
||||
struct list_head list_kcontrol;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
|
@ -518,12 +560,10 @@ struct snd_soc_dapm_widget {
|
|||
/* dapm control */
|
||||
int reg; /* negative reg = no direct dapm */
|
||||
unsigned char shift; /* bits to shift */
|
||||
unsigned int value; /* widget current value */
|
||||
unsigned int mask; /* non-shifted mask */
|
||||
unsigned int on_val; /* on state value */
|
||||
unsigned int off_val; /* off state value */
|
||||
unsigned char power:1; /* block power status */
|
||||
unsigned char invert:1; /* invert the power bit */
|
||||
unsigned char active:1; /* active stream on DAC, ADC's */
|
||||
unsigned char connected:1; /* connected codec pin */
|
||||
unsigned char new:1; /* cnew complete */
|
||||
|
@ -559,7 +599,6 @@ struct snd_soc_dapm_widget {
|
|||
};
|
||||
|
||||
struct snd_soc_dapm_update {
|
||||
struct snd_soc_dapm_widget *widget;
|
||||
struct snd_kcontrol *kcontrol;
|
||||
int reg;
|
||||
int mask;
|
||||
|
@ -573,8 +612,6 @@ struct snd_soc_dapm_context {
|
|||
struct delayed_work delayed_work;
|
||||
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
|
||||
|
||||
struct snd_soc_dapm_update *update;
|
||||
|
||||
void (*seq_notifier)(struct snd_soc_dapm_context *,
|
||||
enum snd_soc_dapm_type, int);
|
||||
|
||||
|
|
|
@ -133,6 +133,6 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream,
|
|||
/* internal use only */
|
||||
int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
|
||||
int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
|
||||
int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *);
|
||||
int soc_dpcm_runtime_update(struct snd_soc_card *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,13 +30,13 @@
|
|||
/*
|
||||
* Convenience kcontrol builders
|
||||
*/
|
||||
#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert) \
|
||||
#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert, xautodisable) \
|
||||
((unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .rreg = xreg, .shift = shift_left, \
|
||||
.rshift = shift_right, .max = xmax, .platform_max = xmax, \
|
||||
.invert = xinvert})
|
||||
#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
|
||||
SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert)
|
||||
.invert = xinvert, .autodisable = xautodisable})
|
||||
#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \
|
||||
SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable)
|
||||
#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
|
||||
((unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert})
|
||||
|
@ -52,7 +52,7 @@
|
|||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
|
||||
#define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \
|
||||
|
@ -68,7 +68,7 @@
|
|||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
|
||||
#define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
|
||||
|
@ -97,7 +97,7 @@
|
|||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
|
||||
max, invert) }
|
||||
max, invert, 0) }
|
||||
#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.info = snd_soc_info_volsw, \
|
||||
|
@ -119,7 +119,7 @@
|
|||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
|
||||
max, invert) }
|
||||
max, invert, 0) }
|
||||
#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
|
@ -190,14 +190,14 @@
|
|||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) }
|
||||
#define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\
|
||||
xhandler_get, xhandler_put) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = \
|
||||
SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert) }
|
||||
SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert, 0) }
|
||||
#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
|
||||
xhandler_get, xhandler_put, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
|
@ -206,7 +206,7 @@
|
|||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) }
|
||||
#define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\
|
||||
xhandler_get, xhandler_put, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
|
@ -216,7 +216,7 @@
|
|||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \
|
||||
xmax, xinvert) }
|
||||
xmax, xinvert, 0) }
|
||||
#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
|
||||
xhandler_get, xhandler_put, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
|
@ -234,7 +234,7 @@
|
|||
.private_value = xdata }
|
||||
#define SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_enum_ext, \
|
||||
.info = snd_soc_info_enum_double, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = (unsigned long)&xenum }
|
||||
|
||||
|
@ -468,6 +468,8 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
|
|||
void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
|
||||
|
||||
int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops);
|
||||
int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops,
|
||||
struct platform_device *pdev);
|
||||
|
||||
/*
|
||||
*Controls
|
||||
|
@ -475,6 +477,8 @@ int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops);
|
|||
struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
|
||||
void *data, const char *long_name,
|
||||
const char *prefix);
|
||||
struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
|
||||
const char *name);
|
||||
int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
|
||||
const struct snd_kcontrol_new *controls, int num_controls);
|
||||
int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
|
||||
|
@ -485,8 +489,6 @@ int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
|
|||
const struct snd_kcontrol_new *controls, int num_controls);
|
||||
int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo);
|
||||
int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo);
|
||||
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,
|
||||
|
@ -497,8 +499,6 @@ 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);
|
||||
int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo);
|
||||
#define snd_soc_info_bool_ext snd_ctl_boolean_mono_info
|
||||
int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
@ -1042,6 +1042,7 @@ struct snd_soc_card {
|
|||
/* Generic DAPM context for the card */
|
||||
struct snd_soc_dapm_context dapm;
|
||||
struct snd_soc_dapm_stats dapm_stats;
|
||||
struct snd_soc_dapm_update *update;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_card_root;
|
||||
|
@ -1087,7 +1088,9 @@ struct snd_soc_pcm_runtime {
|
|||
/* mixer control */
|
||||
struct soc_mixer_control {
|
||||
int min, max, platform_max;
|
||||
unsigned int reg, rreg, shift, rshift, invert;
|
||||
unsigned int reg, rreg, shift, rshift;
|
||||
unsigned int invert:1;
|
||||
unsigned int autodisable:1;
|
||||
};
|
||||
|
||||
struct soc_bytes {
|
||||
|
|
|
@ -14,12 +14,14 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dmaengine.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/ac97_codec.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/pxa2xx-lib.h>
|
||||
#include <sound/dmaengine_pcm.h>
|
||||
|
||||
#include <mach/regs-ac97.h>
|
||||
#include <mach/audio.h>
|
||||
|
@ -41,20 +43,20 @@ static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
|
|||
.reset = pxa2xx_ac97_reset,
|
||||
};
|
||||
|
||||
static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_out = {
|
||||
.name = "AC97 PCM out",
|
||||
.dev_addr = __PREG(PCDR),
|
||||
.drcmr = &DRCMR(12),
|
||||
.dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
|
||||
DCMD_BURST32 | DCMD_WIDTH4,
|
||||
static unsigned long pxa2xx_ac97_pcm_out_req = 12;
|
||||
static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_out = {
|
||||
.addr = __PREG(PCDR),
|
||||
.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
|
||||
.maxburst = 32,
|
||||
.filter_data = &pxa2xx_ac97_pcm_out_req,
|
||||
};
|
||||
|
||||
static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_in = {
|
||||
.name = "AC97 PCM in",
|
||||
.dev_addr = __PREG(PCDR),
|
||||
.drcmr = &DRCMR(11),
|
||||
.dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
|
||||
DCMD_BURST32 | DCMD_WIDTH4,
|
||||
static unsigned long pxa2xx_ac97_pcm_in_req = 11;
|
||||
static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_in = {
|
||||
.addr = __PREG(PCDR),
|
||||
.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
|
||||
.maxburst = 32,
|
||||
.filter_data = &pxa2xx_ac97_pcm_in_req,
|
||||
};
|
||||
|
||||
static struct snd_pcm *pxa2xx_ac97_pcm;
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmaengine.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/pxa2xx-lib.h>
|
||||
#include <sound/dmaengine_pcm.h>
|
||||
|
||||
#include <mach/dma.h>
|
||||
|
||||
|
@ -43,6 +45,35 @@ int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
size_t period = params_period_bytes(params);
|
||||
pxa_dma_desc *dma_desc;
|
||||
dma_addr_t dma_buff_phys, next_desc_phys;
|
||||
u32 dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG;
|
||||
|
||||
/* temporary transition hack */
|
||||
switch (rtd->params->addr_width) {
|
||||
case DMA_SLAVE_BUSWIDTH_1_BYTE:
|
||||
dcmd |= DCMD_WIDTH1;
|
||||
break;
|
||||
case DMA_SLAVE_BUSWIDTH_2_BYTES:
|
||||
dcmd |= DCMD_WIDTH2;
|
||||
break;
|
||||
case DMA_SLAVE_BUSWIDTH_4_BYTES:
|
||||
dcmd |= DCMD_WIDTH4;
|
||||
break;
|
||||
default:
|
||||
/* can't happen */
|
||||
break;
|
||||
}
|
||||
|
||||
switch (rtd->params->maxburst) {
|
||||
case 8:
|
||||
dcmd |= DCMD_BURST8;
|
||||
break;
|
||||
case 16:
|
||||
dcmd |= DCMD_BURST16;
|
||||
break;
|
||||
case 32:
|
||||
dcmd |= DCMD_BURST32;
|
||||
break;
|
||||
}
|
||||
|
||||
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
|
||||
runtime->dma_bytes = totsize;
|
||||
|
@ -55,14 +86,14 @@ int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
dma_desc->ddadr = next_desc_phys;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
dma_desc->dsadr = dma_buff_phys;
|
||||
dma_desc->dtadr = rtd->params->dev_addr;
|
||||
dma_desc->dtadr = rtd->params->addr;
|
||||
} else {
|
||||
dma_desc->dsadr = rtd->params->dev_addr;
|
||||
dma_desc->dsadr = rtd->params->addr;
|
||||
dma_desc->dtadr = dma_buff_phys;
|
||||
}
|
||||
if (period > totsize)
|
||||
period = totsize;
|
||||
dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN;
|
||||
dma_desc->dcmd = dcmd | period | DCMD_ENDIRQEN;
|
||||
dma_desc++;
|
||||
dma_buff_phys += period;
|
||||
} while (totsize -= period);
|
||||
|
@ -76,8 +107,10 @@ int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
|
|||
{
|
||||
struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
|
||||
|
||||
if (rtd && rtd->params && rtd->params->drcmr)
|
||||
*rtd->params->drcmr = 0;
|
||||
if (rtd && rtd->params && rtd->params->filter_data) {
|
||||
unsigned long req = *(unsigned long *) rtd->params->filter_data;
|
||||
DRCMR(req) = 0;
|
||||
}
|
||||
|
||||
snd_pcm_set_runtime_buffer(substream, NULL);
|
||||
return 0;
|
||||
|
@ -136,6 +169,7 @@ EXPORT_SYMBOL(pxa2xx_pcm_pointer);
|
|||
int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
|
||||
unsigned long req;
|
||||
|
||||
if (!prtd || !prtd->params)
|
||||
return 0;
|
||||
|
@ -146,7 +180,8 @@ int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
|
|||
DCSR(prtd->dma_ch) &= ~DCSR_RUN;
|
||||
DCSR(prtd->dma_ch) = 0;
|
||||
DCMD(prtd->dma_ch) = 0;
|
||||
*prtd->params->drcmr = prtd->dma_ch | DRCMR_MAPVLD;
|
||||
req = *(unsigned long *) prtd->params->filter_data;
|
||||
DRCMR(req) = prtd->dma_ch | DRCMR_MAPVLD;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -155,7 +190,6 @@ EXPORT_SYMBOL(__pxa2xx_pcm_prepare);
|
|||
void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
|
||||
{
|
||||
struct snd_pcm_substream *substream = dev_id;
|
||||
struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
|
||||
int dcsr;
|
||||
|
||||
dcsr = DCSR(dma_ch);
|
||||
|
@ -164,8 +198,8 @@ void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
|
|||
if (dcsr & DCSR_ENDINTR) {
|
||||
snd_pcm_period_elapsed(substream);
|
||||
} else {
|
||||
printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
|
||||
rtd->params->name, dma_ch, dcsr);
|
||||
printk(KERN_ERR "DMA error on channel %d (DCSR=%#x)\n",
|
||||
dma_ch, dcsr);
|
||||
snd_pcm_stream_lock(substream);
|
||||
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
|
||||
snd_pcm_stream_unlock(substream);
|
||||
|
|
|
@ -11,8 +11,11 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/dmaengine.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pxa2xx-lib.h>
|
||||
#include <sound/dmaengine_pcm.h>
|
||||
|
||||
#include "pxa2xx-pcm.h"
|
||||
|
||||
|
@ -40,7 +43,7 @@ static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
|
|||
|
||||
rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
|
||||
client->playback_params : client->capture_params;
|
||||
ret = pxa_request_dma(rtd->params->name, DMA_PRIO_LOW,
|
||||
ret = pxa_request_dma("dma", DMA_PRIO_LOW,
|
||||
pxa2xx_pcm_dma_irq, substream);
|
||||
if (ret < 0)
|
||||
goto err2;
|
||||
|
|
|
@ -13,14 +13,14 @@
|
|||
|
||||
struct pxa2xx_runtime_data {
|
||||
int dma_ch;
|
||||
struct pxa2xx_pcm_dma_params *params;
|
||||
struct snd_dmaengine_dai_dma_data *params;
|
||||
pxa_dma_desc *dma_desc_array;
|
||||
dma_addr_t dma_desc_array_phys;
|
||||
};
|
||||
|
||||
struct pxa2xx_pcm_client {
|
||||
struct pxa2xx_pcm_dma_params *playback_params;
|
||||
struct pxa2xx_pcm_dma_params *capture_params;
|
||||
struct snd_dmaengine_dai_dma_data *playback_params;
|
||||
struct snd_dmaengine_dai_dma_data *capture_params;
|
||||
int (*startup)(struct snd_pcm_substream *);
|
||||
void (*shutdown)(struct snd_pcm_substream *);
|
||||
int (*prepare)(struct snd_pcm_substream *);
|
||||
|
|
|
@ -6,6 +6,9 @@ config SND_PCM
|
|||
tristate
|
||||
select SND_TIMER
|
||||
|
||||
config SND_DMAENGINE_PCM
|
||||
tristate
|
||||
|
||||
config SND_HWDEP
|
||||
tristate
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ snd-$(CONFIG_SND_JACK) += jack.o
|
|||
snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
|
||||
pcm_memory.o
|
||||
|
||||
snd-pcm-dmaengine-objs := pcm_dmaengine.o
|
||||
|
||||
snd-page-alloc-y := memalloc.o
|
||||
snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
|
||||
|
||||
|
@ -30,6 +32,7 @@ obj-$(CONFIG_SND_TIMER) += snd-timer.o
|
|||
obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o
|
||||
obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o
|
||||
obj-$(CONFIG_SND_PCM) += snd-pcm.o snd-page-alloc.o
|
||||
obj-$(CONFIG_SND_DMAENGINE_PCM) += snd-pcm-dmaengine.o
|
||||
obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
|
||||
|
||||
obj-$(CONFIG_SND_OSSEMUL) += oss/
|
||||
|
|
|
@ -26,12 +26,9 @@ if SND_SOC
|
|||
config SND_SOC_AC97_BUS
|
||||
bool
|
||||
|
||||
config SND_SOC_DMAENGINE_PCM
|
||||
bool
|
||||
|
||||
config SND_SOC_GENERIC_DMAENGINE_PCM
|
||||
bool
|
||||
select SND_SOC_DMAENGINE_PCM
|
||||
select SND_DMAENGINE_PCM
|
||||
|
||||
# All the supported SoCs
|
||||
source "sound/soc/atmel/Kconfig"
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
|
||||
snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o
|
||||
|
||||
ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),)
|
||||
snd-soc-core-objs += soc-dmaengine-pcm.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
|
||||
snd-soc-core-objs += soc-generic-dmaengine-pcm.o
|
||||
endif
|
||||
|
|
|
@ -13,6 +13,7 @@ config SND_ATMEL_SOC_PDC
|
|||
config SND_ATMEL_SOC_DMA
|
||||
tristate
|
||||
depends on SND_ATMEL_SOC
|
||||
select SND_SOC_GENERIC_DMAENGINE_PCM
|
||||
|
||||
config SND_ATMEL_SOC_SSC
|
||||
tristate
|
||||
|
@ -32,6 +33,26 @@ config SND_AT91_SOC_SAM9G20_WM8731
|
|||
Say Y if you want to add support for SoC audio on WM8731-based
|
||||
AT91sam9g20 evaluation board.
|
||||
|
||||
config SND_ATMEL_SOC_WM8904
|
||||
tristate "Atmel ASoC driver for boards using WM8904 codec"
|
||||
depends on ARCH_AT91 && ATMEL_SSC && SND_ATMEL_SOC
|
||||
select SND_ATMEL_SOC_SSC
|
||||
select SND_ATMEL_SOC_DMA
|
||||
select SND_SOC_WM8904
|
||||
help
|
||||
Say Y if you want to add support for Atmel ASoC driver for boards using
|
||||
WM8904 codec.
|
||||
|
||||
config SND_AT91_SOC_SAM9X5_WM8731
|
||||
tristate "SoC Audio support for WM8731-based at91sam9x5 board"
|
||||
depends on ATMEL_SSC && SND_ATMEL_SOC && SOC_AT91SAM9X5
|
||||
select SND_ATMEL_SOC_SSC
|
||||
select SND_ATMEL_SOC_DMA
|
||||
select SND_SOC_WM8731
|
||||
help
|
||||
Say Y if you want to add support for audio SoC on an
|
||||
at91sam9x5 based board that is using WM8731 codec.
|
||||
|
||||
config SND_AT91_SOC_AFEB9260
|
||||
tristate "SoC Audio support for AFEB9260 board"
|
||||
depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC
|
||||
|
|
|
@ -11,6 +11,10 @@ obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
|
|||
|
||||
# AT91 Machine Support
|
||||
snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
|
||||
snd-atmel-soc-wm8904-objs := atmel_wm8904.o
|
||||
snd-soc-sam9x5-wm8731-objs := sam9x5_wm8731.o
|
||||
|
||||
obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
|
||||
obj-$(CONFIG_SND_ATMEL_SOC_WM8904) += snd-atmel-soc-wm8904.o
|
||||
obj-$(CONFIG_SND_AT91_SOC_SAM9X5_WM8731) += snd-soc-sam9x5-wm8731.o
|
||||
obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o
|
||||
|
|
|
@ -91,138 +91,52 @@ static void atmel_pcm_dma_irq(u32 ssc_sr,
|
|||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*\
|
||||
* DMAENGINE operations
|
||||
\*--------------------------------------------------------------------------*/
|
||||
static bool filter(struct dma_chan *chan, void *slave)
|
||||
{
|
||||
struct at_dma_slave *sl = slave;
|
||||
|
||||
if (sl->dma_dev == chan->device->dev) {
|
||||
chan->private = sl;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params, struct atmel_pcm_dma_params *prtd)
|
||||
struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct atmel_pcm_dma_params *prtd;
|
||||
struct ssc_device *ssc;
|
||||
struct dma_chan *dma_chan;
|
||||
struct dma_slave_config slave_config;
|
||||
int ret;
|
||||
|
||||
prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
ssc = prtd->ssc;
|
||||
|
||||
ret = snd_hwparams_to_dma_slave_config(substream, params,
|
||||
&slave_config);
|
||||
ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config);
|
||||
if (ret) {
|
||||
pr_err("atmel-pcm: hwparams to dma slave configure failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
slave_config.dst_addr = (dma_addr_t)ssc->phybase + SSC_THR;
|
||||
slave_config.dst_maxburst = 1;
|
||||
slave_config->dst_addr = ssc->phybase + SSC_THR;
|
||||
slave_config->dst_maxburst = 1;
|
||||
} else {
|
||||
slave_config.src_addr = (dma_addr_t)ssc->phybase + SSC_RHR;
|
||||
slave_config.src_maxburst = 1;
|
||||
}
|
||||
|
||||
dma_chan = snd_dmaengine_pcm_get_chan(substream);
|
||||
if (dmaengine_slave_config(dma_chan, &slave_config)) {
|
||||
pr_err("atmel-pcm: failed to configure dma channel\n");
|
||||
ret = -EBUSY;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct atmel_pcm_dma_params *prtd;
|
||||
struct ssc_device *ssc;
|
||||
struct at_dma_slave *sdata = NULL;
|
||||
int ret;
|
||||
|
||||
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
|
||||
|
||||
prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
ssc = prtd->ssc;
|
||||
if (ssc->pdev)
|
||||
sdata = ssc->pdev->dev.platform_data;
|
||||
|
||||
ret = snd_dmaengine_pcm_open_request_chan(substream, filter, sdata);
|
||||
if (ret) {
|
||||
pr_err("atmel-pcm: dmaengine pcm open failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = atmel_pcm_configure_dma(substream, params, prtd);
|
||||
if (ret) {
|
||||
pr_err("atmel-pcm: failed to configure dmai\n");
|
||||
goto err;
|
||||
slave_config->src_addr = ssc->phybase + SSC_RHR;
|
||||
slave_config->src_maxburst = 1;
|
||||
}
|
||||
|
||||
prtd->dma_intr_handler = atmel_pcm_dma_irq;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
snd_dmaengine_pcm_close_release_chan(substream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct atmel_pcm_dma_params *prtd;
|
||||
|
||||
prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
|
||||
ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error);
|
||||
ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int atmel_pcm_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
snd_soc_set_runtime_hwparams(substream, &atmel_pcm_dma_hardware);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_pcm_ops atmel_pcm_ops = {
|
||||
.open = atmel_pcm_open,
|
||||
.close = snd_dmaengine_pcm_close_release_chan,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = atmel_pcm_hw_params,
|
||||
.prepare = atmel_pcm_dma_prepare,
|
||||
.trigger = snd_dmaengine_pcm_trigger,
|
||||
.pointer = snd_dmaengine_pcm_pointer_no_residue,
|
||||
.mmap = atmel_pcm_mmap,
|
||||
};
|
||||
|
||||
static struct snd_soc_platform_driver atmel_soc_platform = {
|
||||
.ops = &atmel_pcm_ops,
|
||||
.pcm_new = atmel_pcm_new,
|
||||
.pcm_free = atmel_pcm_free,
|
||||
static const struct snd_dmaengine_pcm_config atmel_dmaengine_pcm_config = {
|
||||
.prepare_slave_config = atmel_pcm_configure_dma,
|
||||
.pcm_hardware = &atmel_pcm_dma_hardware,
|
||||
.prealloc_buffer_size = ATMEL_SSC_DMABUF_SIZE,
|
||||
};
|
||||
|
||||
int atmel_pcm_dma_platform_register(struct device *dev)
|
||||
{
|
||||
return snd_soc_register_platform(dev, &atmel_soc_platform);
|
||||
return snd_dmaengine_pcm_register(dev, &atmel_dmaengine_pcm_config,
|
||||
SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);
|
||||
}
|
||||
EXPORT_SYMBOL(atmel_pcm_dma_platform_register);
|
||||
|
||||
void atmel_pcm_dma_platform_unregister(struct device *dev)
|
||||
{
|
||||
snd_soc_unregister_platform(dev);
|
||||
snd_dmaengine_pcm_unregister(dev);
|
||||
}
|
||||
EXPORT_SYMBOL(atmel_pcm_dma_platform_unregister);
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ static struct atmel_ssc_mask ssc_tx_mask = {
|
|||
.ssc_disable = SSC_BIT(CR_TXDIS),
|
||||
.ssc_endx = SSC_BIT(SR_ENDTX),
|
||||
.ssc_endbuf = SSC_BIT(SR_TXBUFE),
|
||||
.ssc_error = SSC_BIT(SR_OVRUN),
|
||||
.pdc_enable = ATMEL_PDC_TXTEN,
|
||||
.pdc_disable = ATMEL_PDC_TXTDIS,
|
||||
};
|
||||
|
@ -82,6 +83,7 @@ static struct atmel_ssc_mask ssc_rx_mask = {
|
|||
.ssc_disable = SSC_BIT(CR_RXDIS),
|
||||
.ssc_endx = SSC_BIT(SR_ENDRX),
|
||||
.ssc_endbuf = SSC_BIT(SR_RXBUFF),
|
||||
.ssc_error = SSC_BIT(SR_OVRUN),
|
||||
.pdc_enable = ATMEL_PDC_RXTEN,
|
||||
.pdc_disable = ATMEL_PDC_RXTDIS,
|
||||
};
|
||||
|
@ -196,15 +198,27 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
|
||||
int dir_mask;
|
||||
struct atmel_pcm_dma_params *dma_params;
|
||||
int dir, dir_mask;
|
||||
|
||||
pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
|
||||
ssc_readl(ssc_p->ssc->regs, SR));
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
dir = 0;
|
||||
dir_mask = SSC_DIR_MASK_PLAYBACK;
|
||||
else
|
||||
} else {
|
||||
dir = 1;
|
||||
dir_mask = SSC_DIR_MASK_CAPTURE;
|
||||
}
|
||||
|
||||
dma_params = &ssc_dma_params[dai->id][dir];
|
||||
dma_params->ssc = ssc_p->ssc;
|
||||
dma_params->substream = substream;
|
||||
|
||||
ssc_p->dma_params[dir] = dma_params;
|
||||
|
||||
snd_soc_dai_set_dma_data(dai, substream, dma_params);
|
||||
|
||||
spin_lock_irq(&ssc_p->lock);
|
||||
if (ssc_p->dir_mask & dir_mask) {
|
||||
|
@ -325,7 +339,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
|
||||
int id = dai->id;
|
||||
struct atmel_ssc_info *ssc_p = &ssc_info[id];
|
||||
struct atmel_pcm_dma_params *dma_params;
|
||||
|
@ -344,19 +357,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
else
|
||||
dir = 1;
|
||||
|
||||
dma_params = &ssc_dma_params[id][dir];
|
||||
dma_params->ssc = ssc_p->ssc;
|
||||
dma_params->substream = substream;
|
||||
|
||||
ssc_p->dma_params[dir] = dma_params;
|
||||
|
||||
/*
|
||||
* The snd_soc_pcm_stream->dma_data field is only used to communicate
|
||||
* the appropriate DMA parameters to the pcm driver hw_params()
|
||||
* function. It should not be used for other purposes
|
||||
* as it is common to all substreams.
|
||||
*/
|
||||
snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_params);
|
||||
dma_params = ssc_p->dma_params[dir];
|
||||
|
||||
channels = params_channels(params);
|
||||
|
||||
|
@ -648,6 +649,7 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
|
|||
dma_params = ssc_p->dma_params[dir];
|
||||
|
||||
ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
|
||||
ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error);
|
||||
|
||||
pr_debug("%s enabled SSC_SR=0x%08x\n",
|
||||
dir ? "receive" : "transmit",
|
||||
|
|
254
sound/soc/atmel/atmel_wm8904.c
Normal file
254
sound/soc/atmel/atmel_wm8904.c
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* atmel_wm8904 - Atmel ASoC driver for boards with WM8904 codec.
|
||||
*
|
||||
* Copyright (C) 2012 Atmel
|
||||
*
|
||||
* Author: Bo Shen <voice.shen@atmel.com>
|
||||
*
|
||||
* GPLv2 or later
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "../codecs/wm8904.h"
|
||||
#include "atmel_ssc_dai.h"
|
||||
|
||||
#define MCLK_RATE 32768
|
||||
|
||||
static struct clk *mclk;
|
||||
|
||||
static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphone Jack", NULL),
|
||||
SND_SOC_DAPM_MIC("Mic", NULL),
|
||||
SND_SOC_DAPM_LINE("Line In Jack", NULL),
|
||||
};
|
||||
|
||||
static int atmel_asoc_wm8904_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_dai_set_pll(codec_dai, WM8904_FLL_MCLK, WM8904_FLL_MCLK,
|
||||
32768, params_rate(params) * 256);
|
||||
if (ret < 0) {
|
||||
pr_err("%s - failed to set wm8904 codec PLL.", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* As here wm8904 use FLL output as its system clock
|
||||
* so calling set_sysclk won't care freq parameter
|
||||
* then we pass 0
|
||||
*/
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, WM8904_CLK_FLL,
|
||||
0, SND_SOC_CLOCK_IN);
|
||||
if (ret < 0) {
|
||||
pr_err("%s -failed to set wm8904 SYSCLK\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_ops atmel_asoc_wm8904_ops = {
|
||||
.hw_params = atmel_asoc_wm8904_hw_params,
|
||||
};
|
||||
|
||||
static int atmel_set_bias_level(struct snd_soc_card *card,
|
||||
struct snd_soc_dapm_context *dapm,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
clk_prepare_enable(mclk);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
clk_disable_unprepare(mclk);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = {
|
||||
.name = "WM8904",
|
||||
.stream_name = "WM8904 PCM",
|
||||
.codec_dai_name = "wm8904-hifi",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S
|
||||
| SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.ops = &atmel_asoc_wm8904_ops,
|
||||
};
|
||||
|
||||
static struct snd_soc_card atmel_asoc_wm8904_card = {
|
||||
.name = "atmel_asoc_wm8904",
|
||||
.owner = THIS_MODULE,
|
||||
.set_bias_level = atmel_set_bias_level,
|
||||
.dai_link = &atmel_asoc_wm8904_dailink,
|
||||
.num_links = 1,
|
||||
.dapm_widgets = atmel_asoc_wm8904_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(atmel_asoc_wm8904_dapm_widgets),
|
||||
.fully_routed = true,
|
||||
};
|
||||
|
||||
static int atmel_asoc_wm8904_dt_init(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device_node *codec_np, *cpu_np;
|
||||
struct snd_soc_card *card = &atmel_asoc_wm8904_card;
|
||||
struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
|
||||
int ret;
|
||||
|
||||
if (!np) {
|
||||
dev_err(&pdev->dev, "only device tree supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = snd_soc_of_parse_card_name(card, "atmel,model");
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to parse card name\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_of_parse_audio_routing(card, "atmel,audio-routing");
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to parse audio routing\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
|
||||
if (!cpu_np) {
|
||||
dev_err(&pdev->dev, "failed to get dai and pcm info\n");
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
dailink->cpu_of_node = cpu_np;
|
||||
dailink->platform_of_node = cpu_np;
|
||||
of_node_put(cpu_np);
|
||||
|
||||
codec_np = of_parse_phandle(np, "atmel,audio-codec", 0);
|
||||
if (!codec_np) {
|
||||
dev_err(&pdev->dev, "failed to get codec info\n");
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
dailink->codec_of_node = codec_np;
|
||||
of_node_put(codec_np);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int atmel_asoc_wm8904_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = &atmel_asoc_wm8904_card;
|
||||
struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
|
||||
struct clk *clk_src;
|
||||
struct pinctrl *pinctrl;
|
||||
int id, ret;
|
||||
|
||||
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
|
||||
if (IS_ERR(pinctrl)) {
|
||||
dev_err(&pdev->dev, "failed to request pinctrl\n");
|
||||
return PTR_ERR(pinctrl);
|
||||
}
|
||||
|
||||
card->dev = &pdev->dev;
|
||||
ret = atmel_asoc_wm8904_dt_init(pdev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to init dt info\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
id = of_alias_get_id((struct device_node *)dailink->cpu_of_node, "ssc");
|
||||
ret = atmel_ssc_set_audio(id);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "failed to set SSC %d for audio\n", id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mclk = clk_get(NULL, "pck0");
|
||||
if (IS_ERR(mclk)) {
|
||||
dev_err(&pdev->dev, "failed to get pck0\n");
|
||||
ret = PTR_ERR(mclk);
|
||||
goto err_set_audio;
|
||||
}
|
||||
|
||||
clk_src = clk_get(NULL, "clk32k");
|
||||
if (IS_ERR(clk_src)) {
|
||||
dev_err(&pdev->dev, "failed to get clk32k\n");
|
||||
ret = PTR_ERR(clk_src);
|
||||
goto err_set_audio;
|
||||
}
|
||||
|
||||
ret = clk_set_parent(mclk, clk_src);
|
||||
clk_put(clk_src);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "failed to set MCLK parent\n");
|
||||
goto err_set_audio;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "setting pck0 to %dHz\n", MCLK_RATE);
|
||||
clk_set_rate(mclk, MCLK_RATE);
|
||||
|
||||
ret = snd_soc_register_card(card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "snd_soc_register_card failed\n");
|
||||
goto err_set_audio;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_set_audio:
|
||||
atmel_ssc_put_audio(id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int atmel_asoc_wm8904_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
||||
struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
|
||||
int id;
|
||||
|
||||
id = of_alias_get_id((struct device_node *)dailink->cpu_of_node, "ssc");
|
||||
|
||||
snd_soc_unregister_card(card);
|
||||
atmel_ssc_put_audio(id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id atmel_asoc_wm8904_dt_ids[] = {
|
||||
{ .compatible = "atmel,asoc-wm8904", },
|
||||
{ }
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct platform_driver atmel_asoc_wm8904_driver = {
|
||||
.driver = {
|
||||
.name = "atmel-wm8904-audio",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(atmel_asoc_wm8904_dt_ids),
|
||||
},
|
||||
.probe = atmel_asoc_wm8904_probe,
|
||||
.remove = atmel_asoc_wm8904_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(atmel_asoc_wm8904_driver);
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>");
|
||||
MODULE_DESCRIPTION("ALSA SoC machine driver for Atmel EK with WM8904 codec");
|
||||
MODULE_LICENSE("GPL");
|
208
sound/soc/atmel/sam9x5_wm8731.c
Normal file
208
sound/soc/atmel/sam9x5_wm8731.c
Normal file
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* sam9x5_wm8731 -- SoC audio for AT91SAM9X5-based boards
|
||||
* that are using WM8731 as codec.
|
||||
*
|
||||
* Copyright (C) 2011 Atmel,
|
||||
* Nicolas Ferre <nicolas.ferre@atmel.com>
|
||||
*
|
||||
* Copyright (C) 2013 Paratronic,
|
||||
* Richard Genoud <richard.genoud@gmail.com>
|
||||
*
|
||||
* Based on sam9g20_wm8731.c by:
|
||||
* Sedji Gaouaou <sedji.gaouaou@atmel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
#include <linux/of.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dai.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
|
||||
#include "../codecs/wm8731.h"
|
||||
#include "atmel_ssc_dai.h"
|
||||
|
||||
|
||||
#define MCLK_RATE 12288000
|
||||
|
||||
#define DRV_NAME "sam9x5-snd-wm8731"
|
||||
|
||||
struct sam9x5_drvdata {
|
||||
int ssc_id;
|
||||
};
|
||||
|
||||
/*
|
||||
* Logic for a wm8731 as connected on a at91sam9x5ek based board.
|
||||
*/
|
||||
static int sam9x5_wm8731_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct device *dev = rtd->dev;
|
||||
int ret;
|
||||
|
||||
dev_dbg(dev, "ASoC: %s called\n", __func__);
|
||||
|
||||
/* set the codec system clock for DAC and ADC */
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
|
||||
MCLK_RATE, SND_SOC_CLOCK_IN);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "ASoC: Failed to set WM8731 SYSCLK: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Audio paths on at91sam9x5ek board:
|
||||
*
|
||||
* |A| ------------> | | ---R----> Headphone Jack
|
||||
* |T| <----\ | WM | ---L--/
|
||||
* |9| ---> CLK <--> | 8731 | <--R----- Line In Jack
|
||||
* |1| <------------ | | <--L--/
|
||||
*/
|
||||
static const struct snd_soc_dapm_widget sam9x5_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphone Jack", NULL),
|
||||
SND_SOC_DAPM_LINE("Line In Jack", NULL),
|
||||
};
|
||||
|
||||
static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device_node *codec_np, *cpu_np;
|
||||
struct snd_soc_card *card;
|
||||
struct snd_soc_dai_link *dai;
|
||||
struct sam9x5_drvdata *priv;
|
||||
int ret;
|
||||
|
||||
if (!np) {
|
||||
dev_err(&pdev->dev, "No device node supplied\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL);
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
dai = devm_kzalloc(&pdev->dev, sizeof(*dai), GFP_KERNEL);
|
||||
if (!dai || !card || !priv) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
card->dev = &pdev->dev;
|
||||
card->owner = THIS_MODULE;
|
||||
card->dai_link = dai;
|
||||
card->num_links = 1;
|
||||
card->dapm_widgets = sam9x5_dapm_widgets;
|
||||
card->num_dapm_widgets = ARRAY_SIZE(sam9x5_dapm_widgets);
|
||||
dai->name = "WM8731";
|
||||
dai->stream_name = "WM8731 PCM";
|
||||
dai->codec_dai_name = "wm8731-hifi";
|
||||
dai->init = sam9x5_wm8731_init;
|
||||
dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM;
|
||||
|
||||
ret = snd_soc_of_parse_card_name(card, "atmel,model");
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "atmel,model node missing\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = snd_soc_of_parse_audio_routing(card, "atmel,audio-routing");
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "atmel,audio-routing node missing\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
codec_np = of_parse_phandle(np, "atmel,audio-codec", 0);
|
||||
if (!codec_np) {
|
||||
dev_err(&pdev->dev, "atmel,audio-codec node missing\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dai->codec_of_node = codec_np;
|
||||
|
||||
cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
|
||||
if (!cpu_np) {
|
||||
dev_err(&pdev->dev, "atmel,ssc-controller node missing\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
dai->cpu_of_node = cpu_np;
|
||||
dai->platform_of_node = cpu_np;
|
||||
|
||||
priv->ssc_id = of_alias_get_id(cpu_np, "ssc");
|
||||
|
||||
ret = atmel_ssc_set_audio(priv->ssc_id);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"ASoC: Failed to set SSC %d for audio: %d\n",
|
||||
ret, priv->ssc_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
of_node_put(codec_np);
|
||||
of_node_put(cpu_np);
|
||||
|
||||
platform_set_drvdata(pdev, card);
|
||||
|
||||
ret = snd_soc_register_card(card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"ASoC: Platform device allocation failed\n");
|
||||
goto out_put_audio;
|
||||
}
|
||||
|
||||
dev_dbg(&pdev->dev, "ASoC: %s ok\n", __func__);
|
||||
|
||||
return ret;
|
||||
|
||||
out_put_audio:
|
||||
atmel_ssc_put_audio(priv->ssc_id);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sam9x5_wm8731_driver_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
||||
struct sam9x5_drvdata *priv = card->drvdata;
|
||||
|
||||
snd_soc_unregister_card(card);
|
||||
atmel_ssc_put_audio(priv->ssc_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id sam9x5_wm8731_of_match[] = {
|
||||
{ .compatible = "atmel,sam9x5-wm8731-audio", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sam9x5_wm8731_of_match);
|
||||
|
||||
static struct platform_driver sam9x5_wm8731_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(sam9x5_wm8731_of_match),
|
||||
},
|
||||
.probe = sam9x5_wm8731_driver_probe,
|
||||
.remove = sam9x5_wm8731_driver_remove,
|
||||
};
|
||||
module_platform_driver(sam9x5_wm8731_driver);
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
|
||||
MODULE_AUTHOR("Richard Genoud <richard.genoud@gmail.com>");
|
||||
MODULE_DESCRIPTION("ALSA SoC machine driver for AT91SAM9x5 - WM8731");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
|
@ -73,12 +73,14 @@ static struct snd_soc_dai_link db1300_ac97_dai = {
|
|||
|
||||
static struct snd_soc_card db1300_ac97_machine = {
|
||||
.name = "DB1300_AC97",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = &db1300_ac97_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
||||
static struct snd_soc_card db1550_ac97_machine = {
|
||||
.name = "DB1550_AC97",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = &db1200_ac97_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
@ -145,6 +147,7 @@ static struct snd_soc_dai_link db1300_i2s_dai = {
|
|||
|
||||
static struct snd_soc_card db1300_i2s_machine = {
|
||||
.name = "DB1300_I2S",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = &db1300_i2s_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
@ -161,6 +164,7 @@ static struct snd_soc_dai_link db1550_i2s_dai = {
|
|||
|
||||
static struct snd_soc_card db1550_i2s_machine = {
|
||||
.name = "DB1550_I2S",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = &db1550_i2s_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
|
|
@ -379,9 +379,6 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
|
|||
mutex_init(&wd->lock);
|
||||
|
||||
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!iores)
|
||||
return -ENODEV;
|
||||
|
||||
wd->mmio = devm_ioremap_resource(&pdev->dev, iores);
|
||||
if (IS_ERR(wd->mmio))
|
||||
return PTR_ERR(wd->mmio);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#ifndef _BF5XX_AC97_H
|
||||
#define _BF5XX_AC97_H
|
||||
|
||||
extern struct snd_ac97 *ac97;
|
||||
/* Frame format in memory, only support stereo currently */
|
||||
struct ac97_frame {
|
||||
u16 ac97_tag; /* slot 0 */
|
||||
|
|
|
@ -363,9 +363,6 @@ static int ep93xx_ac97_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -ENODEV;
|
||||
|
||||
info->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(info->regs))
|
||||
return PTR_ERR(info->regs);
|
||||
|
|
|
@ -376,9 +376,6 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -ENODEV;
|
||||
|
||||
info->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(info->regs))
|
||||
return PTR_ERR(info->regs);
|
||||
|
|
|
@ -10,6 +10,7 @@ config SND_SOC_I2C_AND_SPI
|
|||
|
||||
config SND_SOC_ALL_CODECS
|
||||
tristate "Build all ASoC CODEC drivers"
|
||||
depends on COMPILE_TEST
|
||||
select SND_SOC_88PM860X if MFD_88PM860X
|
||||
select SND_SOC_L3
|
||||
select SND_SOC_AB8500_CODEC if ABX500_CORE
|
||||
|
@ -20,6 +21,7 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_AD73311
|
||||
select SND_SOC_ADAU1373 if I2C
|
||||
select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_ADAU1701 if I2C
|
||||
select SND_SOC_ADS117X
|
||||
select SND_SOC_AK4104 if SPI_MASTER
|
||||
select SND_SOC_AK4535 if I2C
|
||||
|
@ -54,6 +56,8 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_MC13783 if MFD_MC13XXX
|
||||
select SND_SOC_ML26124 if I2C
|
||||
select SND_SOC_HDMI_CODEC
|
||||
select SND_SOC_PCM1681 if I2C
|
||||
select SND_SOC_PCM1792A if SPI_MASTER
|
||||
select SND_SOC_PCM3008
|
||||
select SND_SOC_RT5631 if I2C
|
||||
select SND_SOC_RT5640 if I2C
|
||||
|
@ -122,6 +126,7 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_WM8994 if MFD_WM8994
|
||||
select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_WM8996 if I2C
|
||||
select SND_SOC_WM8997 if MFD_WM8997
|
||||
select SND_SOC_WM9081 if I2C
|
||||
select SND_SOC_WM9090 if I2C
|
||||
select SND_SOC_WM9705 if SND_SOC_AC97_BUS
|
||||
|
@ -145,8 +150,10 @@ config SND_SOC_ARIZONA
|
|||
tristate
|
||||
default y if SND_SOC_WM5102=y
|
||||
default y if SND_SOC_WM5110=y
|
||||
default y if SND_SOC_WM8997=y
|
||||
default m if SND_SOC_WM5102=m
|
||||
default m if SND_SOC_WM5110=m
|
||||
default m if SND_SOC_WM8997=m
|
||||
|
||||
config SND_SOC_WM_HUBS
|
||||
tristate
|
||||
|
@ -198,6 +205,9 @@ config SND_SOC_AK4104
|
|||
config SND_SOC_AK4535
|
||||
tristate
|
||||
|
||||
config SND_SOC_AK4554
|
||||
tristate
|
||||
|
||||
config SND_SOC_AK4641
|
||||
tristate
|
||||
|
||||
|
@ -292,6 +302,12 @@ config SND_SOC_MAX9850
|
|||
config SND_SOC_HDMI_CODEC
|
||||
tristate
|
||||
|
||||
config SND_SOC_PCM1681
|
||||
tristate
|
||||
|
||||
config SND_SOC_PCM1792A
|
||||
tristate
|
||||
|
||||
config SND_SOC_PCM3008
|
||||
tristate
|
||||
|
||||
|
@ -500,6 +516,9 @@ config SND_SOC_WM8995
|
|||
config SND_SOC_WM8996
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM8997
|
||||
tristate
|
||||
|
||||
config SND_SOC_WM9081
|
||||
tristate
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ snd-soc-adav80x-objs := adav80x.o
|
|||
snd-soc-ads117x-objs := ads117x.o
|
||||
snd-soc-ak4104-objs := ak4104.o
|
||||
snd-soc-ak4535-objs := ak4535.o
|
||||
snd-soc-ak4554-objs := ak4554.o
|
||||
snd-soc-ak4641-objs := ak4641.o
|
||||
snd-soc-ak4642-objs := ak4642.o
|
||||
snd-soc-ak4671-objs := ak4671.o
|
||||
|
@ -42,6 +43,8 @@ snd-soc-max9850-objs := max9850.o
|
|||
snd-soc-mc13783-objs := mc13783.o
|
||||
snd-soc-ml26124-objs := ml26124.o
|
||||
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-rt5631-objs := rt5631.o
|
||||
snd-soc-rt5640-objs := rt5640.o
|
||||
|
@ -114,6 +117,7 @@ snd-soc-wm8991-objs := wm8991.o
|
|||
snd-soc-wm8993-objs := wm8993.o
|
||||
snd-soc-wm8994-objs := wm8994.o wm8958-dsp2.o
|
||||
snd-soc-wm8995-objs := wm8995.o
|
||||
snd-soc-wm8997-objs := wm8997.o
|
||||
snd-soc-wm9081-objs := wm9081.o
|
||||
snd-soc-wm9090-objs := wm9090.o
|
||||
snd-soc-wm9705-objs := wm9705.o
|
||||
|
@ -138,6 +142,7 @@ obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.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
|
||||
obj-$(CONFIG_SND_SOC_AK4554) += snd-soc-ak4554.o
|
||||
obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o
|
||||
obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
|
||||
obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
|
||||
|
@ -171,6 +176,8 @@ obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
|
|||
obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
|
||||
obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o
|
||||
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_RT5631) += snd-soc-rt5631.o
|
||||
obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
|
||||
|
@ -239,6 +246,7 @@ obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o
|
|||
obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o
|
||||
obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o
|
||||
obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o
|
||||
obj-$(CONFIG_SND_SOC_WM8997) += snd-soc-wm8997.o
|
||||
obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o
|
||||
obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o
|
||||
obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
|
||||
|
|
|
@ -23,6 +23,16 @@
|
|||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
static const struct snd_soc_dapm_widget ac97_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("RX"),
|
||||
SND_SOC_DAPM_OUTPUT("TX"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route ac97_routes[] = {
|
||||
{ "AC97 Capture", NULL, "RX" },
|
||||
{ "TX", NULL, "AC97 Playback" },
|
||||
};
|
||||
|
||||
static int ac97_prepare(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
|
@ -117,6 +127,11 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
|
|||
.probe = ac97_soc_probe,
|
||||
.suspend = ac97_soc_suspend,
|
||||
.resume = ac97_soc_resume,
|
||||
|
||||
.dapm_widgets = ac97_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(ac97_widgets),
|
||||
.dapm_routes = ac97_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(ac97_routes),
|
||||
};
|
||||
|
||||
static int ac97_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -96,6 +96,44 @@ SOC_ENUM("Capture Source", ad1980_cap_src),
|
|||
SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget ad1980_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("MIC1"),
|
||||
SND_SOC_DAPM_INPUT("MIC2"),
|
||||
SND_SOC_DAPM_INPUT("CD_L"),
|
||||
SND_SOC_DAPM_INPUT("CD_R"),
|
||||
SND_SOC_DAPM_INPUT("AUX_L"),
|
||||
SND_SOC_DAPM_INPUT("AUX_R"),
|
||||
SND_SOC_DAPM_INPUT("LINE_IN_L"),
|
||||
SND_SOC_DAPM_INPUT("LINE_IN_R"),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("LFE_OUT"),
|
||||
SND_SOC_DAPM_OUTPUT("CENTER_OUT"),
|
||||
SND_SOC_DAPM_OUTPUT("LINE_OUT_L"),
|
||||
SND_SOC_DAPM_OUTPUT("LINE_OUT_R"),
|
||||
SND_SOC_DAPM_OUTPUT("MONO_OUT"),
|
||||
SND_SOC_DAPM_OUTPUT("HP_OUT_L"),
|
||||
SND_SOC_DAPM_OUTPUT("HP_OUT_R"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route ad1980_dapm_routes[] = {
|
||||
{ "Capture", NULL, "MIC1" },
|
||||
{ "Capture", NULL, "MIC2" },
|
||||
{ "Capture", NULL, "CD_L" },
|
||||
{ "Capture", NULL, "CD_R" },
|
||||
{ "Capture", NULL, "AUX_L" },
|
||||
{ "Capture", NULL, "AUX_R" },
|
||||
{ "Capture", NULL, "LINE_IN_L" },
|
||||
{ "Capture", NULL, "LINE_IN_R" },
|
||||
|
||||
{ "LFE_OUT", NULL, "Playback" },
|
||||
{ "CENTER_OUT", NULL, "Playback" },
|
||||
{ "LINE_OUT_L", NULL, "Playback" },
|
||||
{ "LINE_OUT_R", NULL, "Playback" },
|
||||
{ "MONO_OUT", NULL, "Playback" },
|
||||
{ "HP_OUT_L", NULL, "Playback" },
|
||||
{ "HP_OUT_R", NULL, "Playback" },
|
||||
};
|
||||
|
||||
static unsigned int ac97_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
|
@ -253,6 +291,11 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
|
|||
.reg_cache_step = 2,
|
||||
.write = ac97_write,
|
||||
.read = ac97_read,
|
||||
|
||||
.dapm_widgets = ad1980_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(ad1980_dapm_widgets),
|
||||
.dapm_routes = ad1980_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(ad1980_dapm_routes),
|
||||
};
|
||||
|
||||
static int ad1980_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -23,6 +23,21 @@
|
|||
|
||||
#include "ad73311.h"
|
||||
|
||||
static const struct snd_soc_dapm_widget ad73311_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("VINP"),
|
||||
SND_SOC_DAPM_INPUT("VINN"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUTN"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUTP"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route ad73311_dapm_routes[] = {
|
||||
{ "Capture", NULL, "VINP" },
|
||||
{ "Capture", NULL, "VINN" },
|
||||
|
||||
{ "VOUTN", NULL, "Playback" },
|
||||
{ "VOUTP", NULL, "Playback" },
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver ad73311_dai = {
|
||||
.name = "ad73311-hifi",
|
||||
.playback = {
|
||||
|
@ -39,7 +54,12 @@ static struct snd_soc_dai_driver ad73311_dai = {
|
|||
.formats = SNDRV_PCM_FMTBIT_S16_LE, },
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_ad73311;
|
||||
static struct snd_soc_codec_driver soc_codec_dev_ad73311 = {
|
||||
.dapm_widgets = ad73311_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(ad73311_dapm_widgets),
|
||||
.dapm_routes = ad73311_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(ad73311_dapm_routes),
|
||||
};
|
||||
|
||||
static int ad73311_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
#define ADAU1701_OSCIPOW_OPD 0x04
|
||||
#define ADAU1701_DACSET_DACINIT 1
|
||||
|
||||
#define ADAU1707_CLKDIV_UNSET (-1UL)
|
||||
#define ADAU1707_CLKDIV_UNSET (-1U)
|
||||
|
||||
#define ADAU1701_FIRMWARE "adau1701.bin"
|
||||
|
||||
|
@ -247,21 +247,21 @@ static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv)
|
|||
gpio_is_valid(adau1701->gpio_pll_mode[1])) {
|
||||
switch (clkdiv) {
|
||||
case 64:
|
||||
gpio_set_value(adau1701->gpio_pll_mode[0], 0);
|
||||
gpio_set_value(adau1701->gpio_pll_mode[1], 0);
|
||||
gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 0);
|
||||
gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 0);
|
||||
break;
|
||||
case 256:
|
||||
gpio_set_value(adau1701->gpio_pll_mode[0], 0);
|
||||
gpio_set_value(adau1701->gpio_pll_mode[1], 1);
|
||||
gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 0);
|
||||
gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 1);
|
||||
break;
|
||||
case 384:
|
||||
gpio_set_value(adau1701->gpio_pll_mode[0], 1);
|
||||
gpio_set_value(adau1701->gpio_pll_mode[1], 0);
|
||||
gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 1);
|
||||
gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 0);
|
||||
break;
|
||||
case 0: /* fallback */
|
||||
case 512:
|
||||
gpio_set_value(adau1701->gpio_pll_mode[0], 1);
|
||||
gpio_set_value(adau1701->gpio_pll_mode[1], 1);
|
||||
gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 1);
|
||||
gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -269,10 +269,10 @@ static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv)
|
|||
adau1701->pll_clkdiv = clkdiv;
|
||||
|
||||
if (gpio_is_valid(adau1701->gpio_nreset)) {
|
||||
gpio_set_value(adau1701->gpio_nreset, 0);
|
||||
gpio_set_value_cansleep(adau1701->gpio_nreset, 0);
|
||||
/* minimum reset time is 20ns */
|
||||
udelay(1);
|
||||
gpio_set_value(adau1701->gpio_nreset, 1);
|
||||
gpio_set_value_cansleep(adau1701->gpio_nreset, 1);
|
||||
/* power-up time may be as long as 85ms */
|
||||
mdelay(85);
|
||||
}
|
||||
|
@ -734,7 +734,10 @@ static int adau1701_i2c_remove(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id adau1701_i2c_id[] = {
|
||||
{ "adau1401", 0 },
|
||||
{ "adau1401a", 0 },
|
||||
{ "adau1701", 0 },
|
||||
{ "adau1702", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id);
|
||||
|
|
|
@ -868,6 +868,12 @@ static int adav80x_bus_remove(struct device *dev)
|
|||
}
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
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, SND_SOC_SPI);
|
||||
|
@ -885,15 +891,16 @@ static struct spi_driver adav80x_spi_driver = {
|
|||
},
|
||||
.probe = adav80x_spi_probe,
|
||||
.remove = adav80x_spi_remove,
|
||||
.id_table = adav80x_spi_id,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
static const struct i2c_device_id adav80x_id[] = {
|
||||
static const struct i2c_device_id adav80x_i2c_id[] = {
|
||||
{ "adav803", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adav80x_id);
|
||||
MODULE_DEVICE_TABLE(i2c, adav80x_i2c_id);
|
||||
|
||||
static int adav80x_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
|
@ -913,7 +920,7 @@ static struct i2c_driver adav80x_i2c_driver = {
|
|||
},
|
||||
.probe = adav80x_i2c_probe,
|
||||
.remove = adav80x_i2c_remove,
|
||||
.id_table = adav80x_id,
|
||||
.id_table = adav80x_i2c_id,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -23,6 +23,28 @@
|
|||
#define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000)
|
||||
#define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
|
||||
|
||||
static const struct snd_soc_dapm_widget ads117x_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("Input1"),
|
||||
SND_SOC_DAPM_INPUT("Input2"),
|
||||
SND_SOC_DAPM_INPUT("Input3"),
|
||||
SND_SOC_DAPM_INPUT("Input4"),
|
||||
SND_SOC_DAPM_INPUT("Input5"),
|
||||
SND_SOC_DAPM_INPUT("Input6"),
|
||||
SND_SOC_DAPM_INPUT("Input7"),
|
||||
SND_SOC_DAPM_INPUT("Input8"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route ads117x_dapm_routes[] = {
|
||||
{ "Capture", NULL, "Input1" },
|
||||
{ "Capture", NULL, "Input2" },
|
||||
{ "Capture", NULL, "Input3" },
|
||||
{ "Capture", NULL, "Input4" },
|
||||
{ "Capture", NULL, "Input5" },
|
||||
{ "Capture", NULL, "Input6" },
|
||||
{ "Capture", NULL, "Input7" },
|
||||
{ "Capture", NULL, "Input8" },
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver ads117x_dai = {
|
||||
/* ADC */
|
||||
.name = "ads117x-hifi",
|
||||
|
@ -34,7 +56,12 @@ static struct snd_soc_dai_driver ads117x_dai = {
|
|||
.formats = ADS117X_FORMATS,},
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_ads117x;
|
||||
static struct snd_soc_codec_driver soc_codec_dev_ads117x = {
|
||||
.dapm_widgets = ads117x_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(ads117x_dapm_widgets),
|
||||
.dapm_routes = ads117x_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(ads117x_dapm_routes),
|
||||
};
|
||||
|
||||
static int ads117x_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
|
|
@ -51,6 +51,17 @@ struct ak4104_private {
|
|||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget ak4104_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_PGA("TXE", AK4104_REG_TX, AK4104_TX_TXE, 0, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("TX"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route ak4104_dapm_routes[] = {
|
||||
{ "TXE", NULL, "Playback" },
|
||||
{ "TX", NULL, "TXE" },
|
||||
};
|
||||
|
||||
static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
unsigned int format)
|
||||
{
|
||||
|
@ -138,29 +149,11 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* enable transmitter */
|
||||
ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
|
||||
AK4104_TX_TXE, AK4104_TX_TXE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ak4104_hw_free(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
/* disable transmitter */
|
||||
return regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
|
||||
AK4104_TX_TXE, 0);
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops ak4101_dai_ops = {
|
||||
.hw_params = ak4104_hw_params,
|
||||
.hw_free = ak4104_hw_free,
|
||||
.set_fmt = ak4104_set_dai_fmt,
|
||||
};
|
||||
|
||||
|
@ -214,6 +207,11 @@ static int ak4104_remove(struct snd_soc_codec *codec)
|
|||
static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
|
||||
.probe = ak4104_probe,
|
||||
.remove = ak4104_remove,
|
||||
|
||||
.dapm_widgets = ak4104_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(ak4104_dapm_widgets),
|
||||
.dapm_routes = ak4104_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(ak4104_dapm_routes),
|
||||
};
|
||||
|
||||
static const struct regmap_config ak4104_regmap = {
|
||||
|
|
106
sound/soc/codecs/ak4554.c
Normal file
106
sound/soc/codecs/ak4554.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* ak4554.c
|
||||
*
|
||||
* Copyright (C) 2013 Renesas Solutions Corp.
|
||||
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
/*
|
||||
* ak4554 is very simple DA/AD converter which has no setting register.
|
||||
*
|
||||
* CAUTION
|
||||
*
|
||||
* ak4554 playback format is SND_SOC_DAIFMT_RIGHT_J,
|
||||
* and, capture format is SND_SOC_DAIFMT_LEFT_J
|
||||
* on same bit clock, LR clock.
|
||||
* But, this driver doesn't have snd_soc_dai_ops :: set_fmt
|
||||
*
|
||||
* CPU/Codec DAI image
|
||||
*
|
||||
* CPU-DAI1 (plaback only fmt = RIGHT_J) --+-- ak4554
|
||||
* |
|
||||
* CPU-DAI2 (capture only fmt = LEFT_J) ---+
|
||||
*/
|
||||
|
||||
static const struct snd_soc_dapm_widget ak4554_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("AINL"),
|
||||
SND_SOC_DAPM_INPUT("AINR"),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("AOUTL"),
|
||||
SND_SOC_DAPM_OUTPUT("AOUTR"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route ak4554_dapm_routes[] = {
|
||||
{ "Capture", NULL, "AINL" },
|
||||
{ "Capture", NULL, "AINR" },
|
||||
|
||||
{ "AOUTL", NULL, "Playback" },
|
||||
{ "AOUTR", NULL, "Playback" },
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver ak4554_dai = {
|
||||
.name = "ak4554-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_48000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_48000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
},
|
||||
.symmetric_rates = 1,
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_ak4554 = {
|
||||
.dapm_widgets = ak4554_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(ak4554_dapm_widgets),
|
||||
.dapm_routes = ak4554_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(ak4554_dapm_routes),
|
||||
};
|
||||
|
||||
static int ak4554_soc_probe(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_register_codec(&pdev->dev,
|
||||
&soc_codec_dev_ak4554,
|
||||
&ak4554_dai, 1);
|
||||
}
|
||||
|
||||
static int ak4554_soc_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id ak4554_of_match[] = {
|
||||
{ .compatible = "asahi-kasei,ak4554" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ak4554_of_match);
|
||||
|
||||
static struct platform_driver ak4554_driver = {
|
||||
.driver = {
|
||||
.name = "ak4554-adc-dac",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = ak4554_of_match,
|
||||
},
|
||||
.probe = ak4554_soc_probe,
|
||||
.remove = ak4554_soc_remove,
|
||||
};
|
||||
module_platform_driver(ak4554_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("SoC AK4554 driver");
|
||||
MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
|
|
@ -22,7 +22,22 @@ struct ak5386_priv {
|
|||
int reset_gpio;
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_ak5386;
|
||||
static const struct snd_soc_dapm_widget ak5386_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("AINL"),
|
||||
SND_SOC_DAPM_INPUT("AINR"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route ak5386_dapm_routes[] = {
|
||||
{ "Capture", NULL, "AINL" },
|
||||
{ "Capture", NULL, "AINR" },
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_ak5386 = {
|
||||
.dapm_widgets = ak5386_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets),
|
||||
.dapm_routes = ak5386_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(ak5386_dapm_routes),
|
||||
};
|
||||
|
||||
static int ak5386_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
unsigned int format)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <sound/tlv.h>
|
||||
|
||||
#include <linux/mfd/arizona/core.h>
|
||||
#include <linux/mfd/arizona/gpio.h>
|
||||
#include <linux/mfd/arizona/registers.h>
|
||||
|
||||
#include "arizona.h"
|
||||
|
@ -199,9 +200,16 @@ int arizona_init_spk(struct snd_soc_codec *codec)
|
|||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkr, 1);
|
||||
switch (arizona->type) {
|
||||
case WM8997:
|
||||
break;
|
||||
default:
|
||||
ret = snd_soc_dapm_new_controls(&codec->dapm,
|
||||
&arizona_spkr, 1);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN_WARN,
|
||||
"Thermal warning", arizona_thermal_warn,
|
||||
|
@ -223,6 +231,41 @@ int arizona_init_spk(struct snd_soc_codec *codec)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_init_spk);
|
||||
|
||||
int arizona_init_gpio(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
int i;
|
||||
|
||||
switch (arizona->type) {
|
||||
case WM5110:
|
||||
snd_soc_dapm_disable_pin(&codec->dapm, "DRC2 Signal Activity");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
snd_soc_dapm_disable_pin(&codec->dapm, "DRC1 Signal Activity");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {
|
||||
switch (arizona->pdata.gpio_defaults[i] & ARIZONA_GPN_FN_MASK) {
|
||||
case ARIZONA_GP_FN_DRC1_SIGNAL_DETECT:
|
||||
snd_soc_dapm_enable_pin(&codec->dapm,
|
||||
"DRC1 Signal Activity");
|
||||
break;
|
||||
case ARIZONA_GP_FN_DRC2_SIGNAL_DETECT:
|
||||
snd_soc_dapm_enable_pin(&codec->dapm,
|
||||
"DRC2 Signal Activity");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_init_gpio);
|
||||
|
||||
const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
|
||||
"None",
|
||||
"Tone Generator 1",
|
||||
|
@ -517,6 +560,26 @@ const struct soc_enum arizona_ng_hold =
|
|||
4, arizona_ng_hold_text);
|
||||
EXPORT_SYMBOL_GPL(arizona_ng_hold);
|
||||
|
||||
static const char * const arizona_in_dmic_osr_text[] = {
|
||||
"1.536MHz", "3.072MHz", "6.144MHz",
|
||||
};
|
||||
|
||||
const struct soc_enum arizona_in_dmic_osr[] = {
|
||||
SOC_ENUM_SINGLE(ARIZONA_IN1L_CONTROL, ARIZONA_IN1_OSR_SHIFT,
|
||||
ARRAY_SIZE(arizona_in_dmic_osr_text),
|
||||
arizona_in_dmic_osr_text),
|
||||
SOC_ENUM_SINGLE(ARIZONA_IN2L_CONTROL, ARIZONA_IN2_OSR_SHIFT,
|
||||
ARRAY_SIZE(arizona_in_dmic_osr_text),
|
||||
arizona_in_dmic_osr_text),
|
||||
SOC_ENUM_SINGLE(ARIZONA_IN3L_CONTROL, ARIZONA_IN3_OSR_SHIFT,
|
||||
ARRAY_SIZE(arizona_in_dmic_osr_text),
|
||||
arizona_in_dmic_osr_text),
|
||||
SOC_ENUM_SINGLE(ARIZONA_IN4L_CONTROL, ARIZONA_IN4_OSR_SHIFT,
|
||||
ARRAY_SIZE(arizona_in_dmic_osr_text),
|
||||
arizona_in_dmic_osr_text),
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(arizona_in_dmic_osr);
|
||||
|
||||
static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
|
||||
{
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
|
|
|
@ -150,7 +150,8 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
|
|||
ARIZONA_MUX(name_str " Aux 5", &name##_aux5_mux), \
|
||||
ARIZONA_MUX(name_str " Aux 6", &name##_aux6_mux)
|
||||
|
||||
#define ARIZONA_MUX_ROUTES(name) \
|
||||
#define ARIZONA_MUX_ROUTES(widget, name) \
|
||||
{ widget, NULL, name " Input" }, \
|
||||
ARIZONA_MIXER_INPUT_ROUTES(name " Input")
|
||||
|
||||
#define ARIZONA_MIXER_ROUTES(widget, name) \
|
||||
|
@ -198,6 +199,7 @@ extern const struct soc_enum arizona_lhpf3_mode;
|
|||
extern const struct soc_enum arizona_lhpf4_mode;
|
||||
|
||||
extern const struct soc_enum arizona_ng_hold;
|
||||
extern const struct soc_enum arizona_in_dmic_osr[];
|
||||
|
||||
extern int arizona_in_ev(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
|
@ -242,6 +244,7 @@ extern int arizona_set_fll(struct arizona_fll *fll, int source,
|
|||
unsigned int Fref, unsigned int Fout);
|
||||
|
||||
extern int arizona_init_spk(struct snd_soc_codec *codec);
|
||||
extern int arizona_init_gpio(struct snd_soc_codec *codec);
|
||||
|
||||
extern int arizona_init_dai(struct arizona_priv *priv, int dai);
|
||||
|
||||
|
|
|
@ -15,15 +15,27 @@
|
|||
|
||||
#include <sound/soc.h>
|
||||
|
||||
static const struct snd_soc_dapm_widget bt_sco_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("RX"),
|
||||
SND_SOC_DAPM_OUTPUT("TX"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route bt_sco_routes[] = {
|
||||
{ "Capture", NULL, "RX" },
|
||||
{ "TX", NULL, "Playback" },
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver bt_sco_dai = {
|
||||
.name = "bt-sco-pcm",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 1,
|
||||
.rates = SNDRV_PCM_RATE_8000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 1,
|
||||
.rates = SNDRV_PCM_RATE_8000,
|
||||
|
@ -31,7 +43,12 @@ static struct snd_soc_dai_driver bt_sco_dai = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_bt_sco;
|
||||
static struct snd_soc_codec_driver soc_codec_dev_bt_sco = {
|
||||
.dapm_widgets = bt_sco_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(bt_sco_widgets),
|
||||
.dapm_routes = bt_sco_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(bt_sco_routes),
|
||||
};
|
||||
|
||||
static int bt_sco_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -50,6 +67,9 @@ static struct platform_device_id bt_sco_driver_ids[] = {
|
|||
{
|
||||
.name = "dfbmcs320",
|
||||
},
|
||||
{
|
||||
.name = "bt-sco",
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, bt_sco_driver_ids);
|
||||
|
|
|
@ -139,6 +139,22 @@ struct cs4270_private {
|
|||
struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget cs4270_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("AINL"),
|
||||
SND_SOC_DAPM_INPUT("AINR"),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("AOUTL"),
|
||||
SND_SOC_DAPM_OUTPUT("AOUTR"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route cs4270_dapm_routes[] = {
|
||||
{ "Capture", NULL, "AINA" },
|
||||
{ "Capture", NULL, "AINB" },
|
||||
|
||||
{ "AOUTA", NULL, "Playback" },
|
||||
{ "AOUTB", NULL, "Playback" },
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cs4270_mode_ratios - clock ratio tables
|
||||
* @ratio: the ratio of MCLK to the sample rate
|
||||
|
@ -612,6 +628,10 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = {
|
|||
|
||||
.controls = cs4270_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(cs4270_snd_controls),
|
||||
.dapm_widgets = cs4270_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(cs4270_dapm_widgets),
|
||||
.dapm_routes = cs4270_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(cs4270_dapm_routes),
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -173,6 +173,26 @@ struct cs4271_private {
|
|||
bool enable_soft_reset;
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget cs4271_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("AINA"),
|
||||
SND_SOC_DAPM_INPUT("AINB"),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("AOUTA+"),
|
||||
SND_SOC_DAPM_OUTPUT("AOUTA-"),
|
||||
SND_SOC_DAPM_OUTPUT("AOUTB+"),
|
||||
SND_SOC_DAPM_OUTPUT("AOUTB-"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route cs4271_dapm_routes[] = {
|
||||
{ "Capture", NULL, "AINA" },
|
||||
{ "Capture", NULL, "AINB" },
|
||||
|
||||
{ "AOUTA+", NULL, "Playback" },
|
||||
{ "AOUTA-", NULL, "Playback" },
|
||||
{ "AOUTB+", NULL, "Playback" },
|
||||
{ "AOUTB-", NULL, "Playback" },
|
||||
};
|
||||
|
||||
/*
|
||||
* @freq is the desired MCLK rate
|
||||
* MCLK rate should (c) be the sample rate, multiplied by one of the
|
||||
|
@ -576,8 +596,7 @@ static int cs4271_probe(struct snd_soc_codec *codec)
|
|||
CS4271_MODE2_MUTECAEQUB,
|
||||
CS4271_MODE2_MUTECAEQUB);
|
||||
|
||||
return snd_soc_add_codec_controls(codec, cs4271_snd_controls,
|
||||
ARRAY_SIZE(cs4271_snd_controls));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs4271_remove(struct snd_soc_codec *codec)
|
||||
|
@ -596,6 +615,13 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
|
|||
.remove = cs4271_remove,
|
||||
.suspend = cs4271_soc_suspend,
|
||||
.resume = cs4271_soc_resume,
|
||||
|
||||
.controls = cs4271_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(cs4271_snd_controls),
|
||||
.dapm_widgets = cs4271_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(cs4271_dapm_widgets),
|
||||
.dapm_routes = cs4271_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(cs4271_dapm_routes),
|
||||
};
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
|
|
|
@ -23,11 +23,20 @@
|
|||
|
||||
#define DRV_NAME "hdmi-audio-codec"
|
||||
|
||||
static struct snd_soc_codec_driver hdmi_codec;
|
||||
static const struct snd_soc_dapm_widget hdmi_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("RX"),
|
||||
SND_SOC_DAPM_OUTPUT("TX"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route hdmi_routes[] = {
|
||||
{ "Capture", NULL, "RX" },
|
||||
{ "TX", NULL, "Playback" },
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver hdmi_codec_dai = {
|
||||
.name = "hdmi-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 8,
|
||||
.rates = SNDRV_PCM_RATE_32000 |
|
||||
|
@ -37,6 +46,25 @@ static struct snd_soc_dai_driver hdmi_codec_dai = {
|
|||
.formats = SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S24_LE,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_32000 |
|
||||
SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
|
||||
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
|
||||
SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S24_LE,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver hdmi_codec = {
|
||||
.dapm_widgets = hdmi_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(hdmi_widgets),
|
||||
.dapm_routes = hdmi_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(hdmi_routes),
|
||||
};
|
||||
|
||||
static int hdmi_codec_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
|
@ -23,12 +24,15 @@
|
|||
#include <sound/tlv.h>
|
||||
|
||||
struct lm4857 {
|
||||
struct i2c_client *i2c;
|
||||
struct regmap *regmap;
|
||||
uint8_t mode;
|
||||
};
|
||||
|
||||
static const uint8_t lm4857_default_regs[] = {
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
static const struct reg_default lm4857_default_regs[] = {
|
||||
{ 0x0, 0x00 },
|
||||
{ 0x1, 0x00 },
|
||||
{ 0x2, 0x00 },
|
||||
{ 0x3, 0x00 },
|
||||
};
|
||||
|
||||
/* The register offsets in the cache array */
|
||||
|
@ -42,39 +46,6 @@ static const uint8_t lm4857_default_regs[] = {
|
|||
#define LM4857_WAKEUP 5
|
||||
#define LM4857_EPGAIN 4
|
||||
|
||||
static int lm4857_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
uint8_t data;
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_cache_write(codec, reg, value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
data = (reg << 6) | value;
|
||||
ret = i2c_master_send(codec->control_data, &data, 1);
|
||||
if (ret != 1) {
|
||||
dev_err(codec->dev, "Failed to write register: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int lm4857_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_cache_read(codec, reg, &val);
|
||||
if (ret)
|
||||
return -1;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
|
@ -96,7 +67,7 @@ static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
|
|||
lm4857->mode = value;
|
||||
|
||||
if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
|
||||
snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, value + 6);
|
||||
regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, value + 6);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -108,10 +79,11 @@ static int lm4857_set_bias_level(struct snd_soc_codec *codec,
|
|||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, lm4857->mode + 6);
|
||||
regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F,
|
||||
lm4857->mode + 6);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, 0);
|
||||
regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -171,49 +143,32 @@ static const struct snd_soc_dapm_route lm4857_routes[] = {
|
|||
{"EP", NULL, "IN"},
|
||||
};
|
||||
|
||||
static int lm4857_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
int ret;
|
||||
|
||||
codec->control_data = lm4857->i2c;
|
||||
|
||||
ret = snd_soc_add_codec_controls(codec, lm4857_controls,
|
||||
ARRAY_SIZE(lm4857_controls));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = snd_soc_dapm_new_controls(dapm, lm4857_dapm_widgets,
|
||||
ARRAY_SIZE(lm4857_dapm_widgets));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = snd_soc_dapm_add_routes(dapm, lm4857_routes,
|
||||
ARRAY_SIZE(lm4857_routes));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
snd_soc_dapm_new_widgets(dapm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_lm4857 = {
|
||||
.write = lm4857_write,
|
||||
.read = lm4857_read,
|
||||
.probe = lm4857_probe,
|
||||
.reg_cache_size = ARRAY_SIZE(lm4857_default_regs),
|
||||
.reg_word_size = sizeof(uint8_t),
|
||||
.reg_cache_default = lm4857_default_regs,
|
||||
.set_bias_level = lm4857_set_bias_level,
|
||||
|
||||
.controls = lm4857_controls,
|
||||
.num_controls = ARRAY_SIZE(lm4857_controls),
|
||||
.dapm_widgets = lm4857_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(lm4857_dapm_widgets),
|
||||
.dapm_routes = lm4857_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(lm4857_routes),
|
||||
};
|
||||
|
||||
static const struct regmap_config lm4857_regmap_config = {
|
||||
.val_bits = 6,
|
||||
.reg_bits = 2,
|
||||
|
||||
.max_register = LM4857_CTRL,
|
||||
|
||||
.cache_type = REGCACHE_FLAT,
|
||||
.reg_defaults = lm4857_default_regs,
|
||||
.num_reg_defaults = ARRAY_SIZE(lm4857_default_regs),
|
||||
};
|
||||
|
||||
static int lm4857_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct lm4857 *lm4857;
|
||||
int ret;
|
||||
|
||||
lm4857 = devm_kzalloc(&i2c->dev, sizeof(*lm4857), GFP_KERNEL);
|
||||
if (!lm4857)
|
||||
|
@ -221,11 +176,11 @@ static int lm4857_i2c_probe(struct i2c_client *i2c,
|
|||
|
||||
i2c_set_clientdata(i2c, lm4857);
|
||||
|
||||
lm4857->i2c = i2c;
|
||||
lm4857->regmap = devm_regmap_init_i2c(i2c, &lm4857_regmap_config);
|
||||
if (IS_ERR(lm4857->regmap))
|
||||
return PTR_ERR(lm4857->regmap);
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0);
|
||||
|
||||
return ret;
|
||||
return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0);
|
||||
}
|
||||
|
||||
static int lm4857_i2c_remove(struct i2c_client *i2c)
|
||||
|
|
|
@ -118,6 +118,18 @@ static const struct snd_kcontrol_new max9768_mute[] = {
|
|||
SOC_SINGLE_BOOL_EXT("Playback Switch", 0, max9768_get_gpio, max9768_set_gpio),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget max9768_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("IN"),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("OUT+"),
|
||||
SND_SOC_DAPM_OUTPUT("OUT-"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route max9768_dapm_routes[] = {
|
||||
{ "OUT+", NULL, "IN" },
|
||||
{ "OUT-", NULL, "IN" },
|
||||
};
|
||||
|
||||
static int max9768_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
|
||||
|
@ -148,6 +160,10 @@ static struct snd_soc_codec_driver max9768_codec_driver = {
|
|||
.probe = max9768_probe,
|
||||
.controls = max9768_volume,
|
||||
.num_controls = ARRAY_SIZE(max9768_volume),
|
||||
.dapm_widgets = max9768_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(max9768_dapm_widgets),
|
||||
.dapm_routes = max9768_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(max9768_dapm_routes),
|
||||
};
|
||||
|
||||
static const struct regmap_config max9768_i2c_regmap_config = {
|
||||
|
|
|
@ -2084,7 +2084,8 @@ static irqreturn_t max98090_interrupt(int irq, void *data)
|
|||
|
||||
pm_wakeup_event(codec->dev, 100);
|
||||
|
||||
schedule_delayed_work(&max98090->jack_work,
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&max98090->jack_work,
|
||||
msecs_to_jiffies(100));
|
||||
}
|
||||
|
||||
|
@ -2132,7 +2133,8 @@ int max98090_mic_detect(struct snd_soc_codec *codec,
|
|||
snd_soc_jack_report(max98090->jack, 0,
|
||||
SND_JACK_HEADSET | SND_JACK_BTN_0);
|
||||
|
||||
schedule_delayed_work(&max98090->jack_work,
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&max98090->jack_work,
|
||||
msecs_to_jiffies(100));
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -14,170 +14,21 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "max9877.h"
|
||||
|
||||
static struct i2c_client *i2c;
|
||||
static struct regmap *regmap;
|
||||
|
||||
static u8 max9877_regs[5] = { 0x40, 0x00, 0x00, 0x00, 0x49 };
|
||||
|
||||
static void max9877_write_regs(void)
|
||||
{
|
||||
unsigned int i;
|
||||
u8 data[6];
|
||||
|
||||
data[0] = MAX9877_INPUT_MODE;
|
||||
for (i = 0; i < ARRAY_SIZE(max9877_regs); i++)
|
||||
data[i + 1] = max9877_regs[i];
|
||||
|
||||
if (i2c_master_send(i2c, data, 6) != 6)
|
||||
dev_err(&i2c->dev, "i2c write failed\n");
|
||||
}
|
||||
|
||||
static int max9877_get_reg(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
unsigned int reg = mc->reg;
|
||||
unsigned int shift = mc->shift;
|
||||
unsigned int mask = mc->max;
|
||||
unsigned int invert = mc->invert;
|
||||
|
||||
ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask;
|
||||
|
||||
if (invert)
|
||||
ucontrol->value.integer.value[0] =
|
||||
mask - ucontrol->value.integer.value[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max9877_set_reg(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
unsigned int reg = mc->reg;
|
||||
unsigned int shift = mc->shift;
|
||||
unsigned int mask = mc->max;
|
||||
unsigned int invert = mc->invert;
|
||||
unsigned int val = (ucontrol->value.integer.value[0] & mask);
|
||||
|
||||
if (invert)
|
||||
val = mask - val;
|
||||
|
||||
if (((max9877_regs[reg] >> shift) & mask) == val)
|
||||
return 0;
|
||||
|
||||
max9877_regs[reg] &= ~(mask << shift);
|
||||
max9877_regs[reg] |= val << shift;
|
||||
max9877_write_regs();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int max9877_get_2reg(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
unsigned int reg = mc->reg;
|
||||
unsigned int reg2 = mc->rreg;
|
||||
unsigned int shift = mc->shift;
|
||||
unsigned int mask = mc->max;
|
||||
|
||||
ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask;
|
||||
ucontrol->value.integer.value[1] = (max9877_regs[reg2] >> shift) & mask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max9877_set_2reg(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
unsigned int reg = mc->reg;
|
||||
unsigned int reg2 = mc->rreg;
|
||||
unsigned int shift = mc->shift;
|
||||
unsigned int mask = mc->max;
|
||||
unsigned int val = (ucontrol->value.integer.value[0] & mask);
|
||||
unsigned int val2 = (ucontrol->value.integer.value[1] & mask);
|
||||
unsigned int change = 0;
|
||||
|
||||
if (((max9877_regs[reg] >> shift) & mask) != val)
|
||||
change = 1;
|
||||
|
||||
if (((max9877_regs[reg2] >> shift) & mask) != val2)
|
||||
change = 1;
|
||||
|
||||
if (change) {
|
||||
max9877_regs[reg] &= ~(mask << shift);
|
||||
max9877_regs[reg] |= val << shift;
|
||||
max9877_regs[reg2] &= ~(mask << shift);
|
||||
max9877_regs[reg2] |= val2 << shift;
|
||||
max9877_write_regs();
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
static int max9877_get_out_mode(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
u8 value = max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK;
|
||||
|
||||
if (value)
|
||||
value -= 1;
|
||||
|
||||
ucontrol->value.integer.value[0] = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max9877_set_out_mode(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
u8 value = ucontrol->value.integer.value[0];
|
||||
|
||||
value += 1;
|
||||
|
||||
if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK) == value)
|
||||
return 0;
|
||||
|
||||
max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OUTMODE_MASK;
|
||||
max9877_regs[MAX9877_OUTPUT_MODE] |= value;
|
||||
max9877_write_regs();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int max9877_get_osc_mode(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
u8 value = (max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK);
|
||||
|
||||
value = value >> MAX9877_OSC_OFFSET;
|
||||
|
||||
ucontrol->value.integer.value[0] = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max9877_set_osc_mode(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
u8 value = ucontrol->value.integer.value[0];
|
||||
|
||||
value = value << MAX9877_OSC_OFFSET;
|
||||
if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK) == value)
|
||||
return 0;
|
||||
|
||||
max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OSC_MASK;
|
||||
max9877_regs[MAX9877_OUTPUT_MODE] |= value;
|
||||
max9877_write_regs();
|
||||
return 1;
|
||||
}
|
||||
static struct reg_default max9877_regs[] = {
|
||||
{ 0, 0x40 },
|
||||
{ 1, 0x00 },
|
||||
{ 2, 0x00 },
|
||||
{ 3, 0x00 },
|
||||
{ 4, 0x49 },
|
||||
};
|
||||
|
||||
static const unsigned int max9877_pgain_tlv[] = {
|
||||
TLV_DB_RANGE_HEAD(2),
|
||||
|
@ -212,65 +63,104 @@ static const char *max9877_osc_mode[] = {
|
|||
};
|
||||
|
||||
static const struct soc_enum max9877_enum[] = {
|
||||
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_out_mode), max9877_out_mode),
|
||||
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode),
|
||||
SOC_ENUM_SINGLE(MAX9877_OUTPUT_MODE, 0, ARRAY_SIZE(max9877_out_mode),
|
||||
max9877_out_mode),
|
||||
SOC_ENUM_SINGLE(MAX9877_OUTPUT_MODE, MAX9877_OSC_OFFSET,
|
||||
ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new max9877_controls[] = {
|
||||
SOC_SINGLE_EXT_TLV("MAX9877 PGAINA Playback Volume",
|
||||
MAX9877_INPUT_MODE, 0, 2, 0,
|
||||
max9877_get_reg, max9877_set_reg, max9877_pgain_tlv),
|
||||
SOC_SINGLE_EXT_TLV("MAX9877 PGAINB Playback Volume",
|
||||
MAX9877_INPUT_MODE, 2, 2, 0,
|
||||
max9877_get_reg, max9877_set_reg, max9877_pgain_tlv),
|
||||
SOC_SINGLE_EXT_TLV("MAX9877 Amp Speaker Playback Volume",
|
||||
MAX9877_SPK_VOLUME, 0, 31, 0,
|
||||
max9877_get_reg, max9877_set_reg, max9877_output_tlv),
|
||||
SOC_DOUBLE_R_EXT_TLV("MAX9877 Amp HP Playback Volume",
|
||||
SOC_SINGLE_TLV("MAX9877 PGAINA Playback Volume",
|
||||
MAX9877_INPUT_MODE, 0, 2, 0, max9877_pgain_tlv),
|
||||
SOC_SINGLE_TLV("MAX9877 PGAINB Playback Volume",
|
||||
MAX9877_INPUT_MODE, 2, 2, 0, max9877_pgain_tlv),
|
||||
SOC_SINGLE_TLV("MAX9877 Amp Speaker Playback Volume",
|
||||
MAX9877_SPK_VOLUME, 0, 31, 0, max9877_output_tlv),
|
||||
SOC_DOUBLE_R_TLV("MAX9877 Amp HP Playback Volume",
|
||||
MAX9877_HPL_VOLUME, MAX9877_HPR_VOLUME, 0, 31, 0,
|
||||
max9877_get_2reg, max9877_set_2reg, max9877_output_tlv),
|
||||
SOC_SINGLE_EXT("MAX9877 INB Stereo Switch",
|
||||
MAX9877_INPUT_MODE, 4, 1, 1,
|
||||
max9877_get_reg, max9877_set_reg),
|
||||
SOC_SINGLE_EXT("MAX9877 INA Stereo Switch",
|
||||
MAX9877_INPUT_MODE, 5, 1, 1,
|
||||
max9877_get_reg, max9877_set_reg),
|
||||
SOC_SINGLE_EXT("MAX9877 Zero-crossing detection Switch",
|
||||
MAX9877_INPUT_MODE, 6, 1, 0,
|
||||
max9877_get_reg, max9877_set_reg),
|
||||
SOC_SINGLE_EXT("MAX9877 Bypass Mode Switch",
|
||||
MAX9877_OUTPUT_MODE, 6, 1, 0,
|
||||
max9877_get_reg, max9877_set_reg),
|
||||
SOC_SINGLE_EXT("MAX9877 Shutdown Mode Switch",
|
||||
MAX9877_OUTPUT_MODE, 7, 1, 1,
|
||||
max9877_get_reg, max9877_set_reg),
|
||||
SOC_ENUM_EXT("MAX9877 Output Mode", max9877_enum[0],
|
||||
max9877_get_out_mode, max9877_set_out_mode),
|
||||
SOC_ENUM_EXT("MAX9877 Oscillator Mode", max9877_enum[1],
|
||||
max9877_get_osc_mode, max9877_set_osc_mode),
|
||||
max9877_output_tlv),
|
||||
SOC_SINGLE("MAX9877 INB Stereo Switch",
|
||||
MAX9877_INPUT_MODE, 4, 1, 1),
|
||||
SOC_SINGLE("MAX9877 INA Stereo Switch",
|
||||
MAX9877_INPUT_MODE, 5, 1, 1),
|
||||
SOC_SINGLE("MAX9877 Zero-crossing detection Switch",
|
||||
MAX9877_INPUT_MODE, 6, 1, 0),
|
||||
SOC_SINGLE("MAX9877 Bypass Mode Switch",
|
||||
MAX9877_OUTPUT_MODE, 6, 1, 0),
|
||||
SOC_ENUM("MAX9877 Output Mode", max9877_enum[0]),
|
||||
SOC_ENUM("MAX9877 Oscillator Mode", max9877_enum[1]),
|
||||
};
|
||||
|
||||
/* This function is called from ASoC machine driver */
|
||||
int max9877_add_controls(struct snd_soc_codec *codec)
|
||||
{
|
||||
return snd_soc_add_codec_controls(codec, max9877_controls,
|
||||
ARRAY_SIZE(max9877_controls));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(max9877_add_controls);
|
||||
static const struct snd_soc_dapm_widget max9877_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("INA1"),
|
||||
SND_SOC_DAPM_INPUT("INA2"),
|
||||
SND_SOC_DAPM_INPUT("INB1"),
|
||||
SND_SOC_DAPM_INPUT("INB2"),
|
||||
SND_SOC_DAPM_INPUT("RXIN+"),
|
||||
SND_SOC_DAPM_INPUT("RXIN-"),
|
||||
|
||||
SND_SOC_DAPM_PGA("SHDN", MAX9877_OUTPUT_MODE, 7, 1, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("OUT+"),
|
||||
SND_SOC_DAPM_OUTPUT("OUT-"),
|
||||
SND_SOC_DAPM_OUTPUT("HPL"),
|
||||
SND_SOC_DAPM_OUTPUT("HPR"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route max9877_dapm_routes[] = {
|
||||
{ "SHDN", NULL, "INA1" },
|
||||
{ "SHDN", NULL, "INA2" },
|
||||
{ "SHDN", NULL, "INB1" },
|
||||
{ "SHDN", NULL, "INB2" },
|
||||
|
||||
{ "OUT+", NULL, "RXIN+" },
|
||||
{ "OUT+", NULL, "SHDN" },
|
||||
|
||||
{ "OUT-", NULL, "SHDN" },
|
||||
{ "OUT-", NULL, "RXIN-" },
|
||||
|
||||
{ "HPL", NULL, "SHDN" },
|
||||
{ "HPR", NULL, "SHDN" },
|
||||
};
|
||||
|
||||
static const struct snd_soc_codec_driver max9877_codec = {
|
||||
.controls = max9877_controls,
|
||||
.num_controls = ARRAY_SIZE(max9877_controls),
|
||||
|
||||
.dapm_widgets = max9877_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(max9877_dapm_widgets),
|
||||
.dapm_routes = max9877_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(max9877_dapm_routes),
|
||||
};
|
||||
|
||||
static const struct regmap_config max9877_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
.reg_defaults = max9877_regs,
|
||||
.num_reg_defaults = ARRAY_SIZE(max9877_regs),
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int max9877_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
i2c = client;
|
||||
int i;
|
||||
|
||||
max9877_write_regs();
|
||||
regmap = devm_regmap_init_i2c(client, &max9877_regmap);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
return 0;
|
||||
/* Ensure the device is in reset state */
|
||||
for (i = 0; i < ARRAY_SIZE(max9877_regs); i++)
|
||||
regmap_write(regmap, max9877_regs[i].reg, max9877_regs[i].def);
|
||||
|
||||
return snd_soc_register_codec(&client->dev, &max9877_codec, NULL, 0);
|
||||
}
|
||||
|
||||
static int max9877_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
i2c = NULL;
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -94,7 +94,6 @@
|
|||
#define AUDIO_DAC_CFS_DLY_B (1 << 10)
|
||||
|
||||
struct mc13783_priv {
|
||||
struct snd_soc_codec codec;
|
||||
struct mc13xxx *mc13xxx;
|
||||
|
||||
enum mc13783_ssi_port adc_ssi_port;
|
||||
|
|
339
sound/soc/codecs/pcm1681.c
Normal file
339
sound/soc/codecs/pcm1681.c
Normal file
|
@ -0,0 +1,339 @@
|
|||
/*
|
||||
* PCM1681 ASoC codec driver
|
||||
*
|
||||
* Copyright (c) StreamUnlimited GmbH 2013
|
||||
* Marek Belisko <marek.belisko@streamunlimited.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#define PCM1681_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
|
||||
SNDRV_PCM_FMTBIT_S24_LE)
|
||||
|
||||
#define PCM1681_PCM_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \
|
||||
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
|
||||
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \
|
||||
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
|
||||
|
||||
#define PCM1681_SOFT_MUTE_ALL 0xff
|
||||
#define PCM1681_DEEMPH_RATE_MASK 0x18
|
||||
#define PCM1681_DEEMPH_MASK 0x01
|
||||
|
||||
#define PCM1681_ATT_CONTROL(X) (X <= 6 ? X : X + 9) /* Attenuation level */
|
||||
#define PCM1681_SOFT_MUTE 0x07 /* Soft mute control register */
|
||||
#define PCM1681_DAC_CONTROL 0x08 /* DAC operation control */
|
||||
#define PCM1681_FMT_CONTROL 0x09 /* Audio interface data format */
|
||||
#define PCM1681_DEEMPH_CONTROL 0x0a /* De-emphasis control */
|
||||
#define PCM1681_ZERO_DETECT_STATUS 0x0e /* Zero detect status reg */
|
||||
|
||||
static const struct reg_default pcm1681_reg_defaults[] = {
|
||||
{ 0x01, 0xff },
|
||||
{ 0x02, 0xff },
|
||||
{ 0x03, 0xff },
|
||||
{ 0x04, 0xff },
|
||||
{ 0x05, 0xff },
|
||||
{ 0x06, 0xff },
|
||||
{ 0x07, 0x00 },
|
||||
{ 0x08, 0x00 },
|
||||
{ 0x09, 0x06 },
|
||||
{ 0x0A, 0x00 },
|
||||
{ 0x0B, 0xff },
|
||||
{ 0x0C, 0x0f },
|
||||
{ 0x0D, 0x00 },
|
||||
{ 0x10, 0xff },
|
||||
{ 0x11, 0xff },
|
||||
{ 0x12, 0x00 },
|
||||
{ 0x13, 0x00 },
|
||||
};
|
||||
|
||||
static bool pcm1681_accessible_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return !((reg == 0x00) || (reg == 0x0f));
|
||||
}
|
||||
|
||||
static bool pcm1681_writeable_reg(struct device *dev, unsigned register reg)
|
||||
{
|
||||
return pcm1681_accessible_reg(dev, reg) &&
|
||||
(reg != PCM1681_ZERO_DETECT_STATUS);
|
||||
}
|
||||
|
||||
struct pcm1681_private {
|
||||
struct regmap *regmap;
|
||||
unsigned int format;
|
||||
/* Current deemphasis status */
|
||||
unsigned int deemph;
|
||||
/* Current rate for deemphasis control */
|
||||
unsigned int rate;
|
||||
};
|
||||
|
||||
static const int pcm1681_deemph[] = { 44100, 48000, 32000 };
|
||||
|
||||
static int pcm1681_set_deemph(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int i = 0, val = -1, enable = 0;
|
||||
|
||||
if (priv->deemph)
|
||||
for (i = 0; i < ARRAY_SIZE(pcm1681_deemph); i++)
|
||||
if (pcm1681_deemph[i] == priv->rate)
|
||||
val = i;
|
||||
|
||||
if (val != -1) {
|
||||
regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL,
|
||||
PCM1681_DEEMPH_RATE_MASK, val);
|
||||
enable = 1;
|
||||
} else
|
||||
enable = 0;
|
||||
|
||||
/* enable/disable deemphasis functionality */
|
||||
return regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL,
|
||||
PCM1681_DEEMPH_MASK, enable);
|
||||
}
|
||||
|
||||
static int pcm1681_get_deemph(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = priv->deemph;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm1681_put_deemph(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
priv->deemph = ucontrol->value.enumerated.item[0];
|
||||
|
||||
return pcm1681_set_deemph(codec);
|
||||
}
|
||||
|
||||
static int pcm1681_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
unsigned int format)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
/* The PCM1681 can only be slave to all clocks */
|
||||
if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
|
||||
dev_err(codec->dev, "Invalid clocking mode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->format = format;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm1681_digital_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int val;
|
||||
|
||||
if (mute)
|
||||
val = PCM1681_SOFT_MUTE_ALL;
|
||||
else
|
||||
val = 0;
|
||||
|
||||
return regmap_write(priv->regmap, PCM1681_SOFT_MUTE, val);
|
||||
}
|
||||
|
||||
static int pcm1681_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
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;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
val = 0x04;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
val = 0x05;
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "Invalid DAI format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(priv->regmap, PCM1681_FMT_CONTROL, 0x0f, val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return pcm1681_set_deemph(codec);
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops pcm1681_dai_ops = {
|
||||
.set_fmt = pcm1681_set_dai_fmt,
|
||||
.hw_params = pcm1681_hw_params,
|
||||
.digital_mute = pcm1681_digital_mute,
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget pcm1681_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_OUTPUT("VOUT1"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUT2"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUT3"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUT4"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUT5"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUT6"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUT7"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUT8"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route pcm1681_dapm_routes[] = {
|
||||
{ "VOUT1", NULL, "Playback" },
|
||||
{ "VOUT2", NULL, "Playback" },
|
||||
{ "VOUT3", NULL, "Playback" },
|
||||
{ "VOUT4", NULL, "Playback" },
|
||||
{ "VOUT5", NULL, "Playback" },
|
||||
{ "VOUT6", NULL, "Playback" },
|
||||
{ "VOUT7", NULL, "Playback" },
|
||||
{ "VOUT8", NULL, "Playback" },
|
||||
};
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(pcm1681_dac_tlv, -6350, 50, 1);
|
||||
|
||||
static const struct snd_kcontrol_new pcm1681_controls[] = {
|
||||
SOC_DOUBLE_R_TLV("Channel 1/2 Playback Volume",
|
||||
PCM1681_ATT_CONTROL(1), PCM1681_ATT_CONTROL(2), 0,
|
||||
0x7f, 0, pcm1681_dac_tlv),
|
||||
SOC_DOUBLE_R_TLV("Channel 3/4 Playback Volume",
|
||||
PCM1681_ATT_CONTROL(3), PCM1681_ATT_CONTROL(4), 0,
|
||||
0x7f, 0, pcm1681_dac_tlv),
|
||||
SOC_DOUBLE_R_TLV("Channel 5/6 Playback Volume",
|
||||
PCM1681_ATT_CONTROL(5), PCM1681_ATT_CONTROL(6), 0,
|
||||
0x7f, 0, pcm1681_dac_tlv),
|
||||
SOC_DOUBLE_R_TLV("Channel 7/8 Playback Volume",
|
||||
PCM1681_ATT_CONTROL(7), PCM1681_ATT_CONTROL(8), 0,
|
||||
0x7f, 0, pcm1681_dac_tlv),
|
||||
SOC_SINGLE_BOOL_EXT("De-emphasis Switch", 0,
|
||||
pcm1681_get_deemph, pcm1681_put_deemph),
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver pcm1681_dai = {
|
||||
.name = "pcm1681-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 8,
|
||||
.rates = PCM1681_PCM_RATES,
|
||||
.formats = PCM1681_PCM_FORMATS,
|
||||
},
|
||||
.ops = &pcm1681_dai_ops,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id pcm1681_dt_ids[] = {
|
||||
{ .compatible = "ti,pcm1681", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pcm1681_dt_ids);
|
||||
#endif
|
||||
|
||||
static const struct regmap_config pcm1681_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = ARRAY_SIZE(pcm1681_reg_defaults) + 1,
|
||||
.reg_defaults = pcm1681_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(pcm1681_reg_defaults),
|
||||
.writeable_reg = pcm1681_writeable_reg,
|
||||
.readable_reg = pcm1681_accessible_reg,
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_pcm1681 = {
|
||||
.controls = pcm1681_controls,
|
||||
.num_controls = ARRAY_SIZE(pcm1681_controls),
|
||||
.dapm_widgets = pcm1681_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(pcm1681_dapm_widgets),
|
||||
.dapm_routes = pcm1681_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(pcm1681_dapm_routes),
|
||||
};
|
||||
|
||||
static const struct i2c_device_id pcm1681_i2c_id[] = {
|
||||
{"pcm1681", 0},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pcm1681_i2c_id);
|
||||
|
||||
static int pcm1681_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
struct pcm1681_private *priv;
|
||||
|
||||
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->regmap = devm_regmap_init_i2c(client, &pcm1681_regmap);
|
||||
if (IS_ERR(priv->regmap)) {
|
||||
ret = PTR_ERR(priv->regmap);
|
||||
dev_err(&client->dev, "Failed to create regmap: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, priv);
|
||||
|
||||
return snd_soc_register_codec(&client->dev, &soc_codec_dev_pcm1681,
|
||||
&pcm1681_dai, 1);
|
||||
}
|
||||
|
||||
static int pcm1681_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver pcm1681_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "pcm1681",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(pcm1681_dt_ids),
|
||||
},
|
||||
.id_table = pcm1681_i2c_id,
|
||||
.probe = pcm1681_i2c_probe,
|
||||
.remove = pcm1681_i2c_remove,
|
||||
};
|
||||
|
||||
module_i2c_driver(pcm1681_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Texas Instruments PCM1681 ALSA SoC Codec Driver");
|
||||
MODULE_AUTHOR("Marek Belisko <marek.belisko@streamunlimited.com>");
|
||||
MODULE_LICENSE("GPL");
|
257
sound/soc/codecs/pcm1792a.c
Normal file
257
sound/soc/codecs/pcm1792a.c
Normal file
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* PCM1792A ASoC codec driver
|
||||
*
|
||||
* Copyright (c) Amarula Solutions B.V. 2013
|
||||
*
|
||||
* Michael Trimarchi <michael@amarulasolutions.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include "pcm1792a.h"
|
||||
|
||||
#define PCM1792A_DAC_VOL_LEFT 0x10
|
||||
#define PCM1792A_DAC_VOL_RIGHT 0x11
|
||||
#define PCM1792A_FMT_CONTROL 0x12
|
||||
#define PCM1792A_SOFT_MUTE PCM1792A_FMT_CONTROL
|
||||
|
||||
#define PCM1792A_FMT_MASK 0x70
|
||||
#define PCM1792A_FMT_SHIFT 4
|
||||
#define PCM1792A_MUTE_MASK 0x01
|
||||
#define PCM1792A_MUTE_SHIFT 0
|
||||
#define PCM1792A_ATLD_ENABLE (1 << 7)
|
||||
|
||||
static const struct reg_default pcm1792a_reg_defaults[] = {
|
||||
{ 0x10, 0xff },
|
||||
{ 0x11, 0xff },
|
||||
{ 0x12, 0x50 },
|
||||
{ 0x13, 0x00 },
|
||||
{ 0x14, 0x00 },
|
||||
{ 0x15, 0x01 },
|
||||
{ 0x16, 0x00 },
|
||||
{ 0x17, 0x00 },
|
||||
};
|
||||
|
||||
static bool pcm1792a_accessible_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return reg >= 0x10 && reg <= 0x17;
|
||||
}
|
||||
|
||||
static bool pcm1792a_writeable_reg(struct device *dev, unsigned register reg)
|
||||
{
|
||||
bool accessible;
|
||||
|
||||
accessible = pcm1792a_accessible_reg(dev, reg);
|
||||
|
||||
return accessible && reg != 0x16 && reg != 0x17;
|
||||
}
|
||||
|
||||
struct pcm1792a_private {
|
||||
struct regmap *regmap;
|
||||
unsigned int format;
|
||||
unsigned int rate;
|
||||
};
|
||||
|
||||
static int pcm1792a_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
unsigned int format)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
priv->format = format;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm1792a_digital_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(priv->regmap, PCM1792A_SOFT_MUTE,
|
||||
PCM1792A_MUTE_MASK, !!mute);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm1792a_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
break;
|
||||
default:
|
||||
dev_err(codec->dev, "Invalid DAI format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val = val << PCM1792A_FMT_SHIFT | PCM1792A_ATLD_ENABLE;
|
||||
|
||||
ret = regmap_update_bits(priv->regmap, PCM1792A_FMT_CONTROL,
|
||||
PCM1792A_FMT_MASK | PCM1792A_ATLD_ENABLE, val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops pcm1792a_dai_ops = {
|
||||
.set_fmt = pcm1792a_set_dai_fmt,
|
||||
.hw_params = pcm1792a_hw_params,
|
||||
.digital_mute = pcm1792a_digital_mute,
|
||||
};
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(pcm1792a_dac_tlv, -12000, 50, 1);
|
||||
|
||||
static const struct snd_kcontrol_new pcm1792a_controls[] = {
|
||||
SOC_DOUBLE_R_RANGE_TLV("DAC Playback Volume", PCM1792A_DAC_VOL_LEFT,
|
||||
PCM1792A_DAC_VOL_RIGHT, 0, 0xf, 0xff, 0,
|
||||
pcm1792a_dac_tlv),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget pcm1792a_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_OUTPUT("IOUTL+"),
|
||||
SND_SOC_DAPM_OUTPUT("IOUTL-"),
|
||||
SND_SOC_DAPM_OUTPUT("IOUTR+"),
|
||||
SND_SOC_DAPM_OUTPUT("IOUTR-"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route pcm1792a_dapm_routes[] = {
|
||||
{ "IOUTL+", NULL, "Playback" },
|
||||
{ "IOUTL-", NULL, "Playback" },
|
||||
{ "IOUTR+", NULL, "Playback" },
|
||||
{ "IOUTR-", NULL, "Playback" },
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver pcm1792a_dai = {
|
||||
.name = "pcm1792a-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = PCM1792A_RATES,
|
||||
.formats = PCM1792A_FORMATS, },
|
||||
.ops = &pcm1792a_dai_ops,
|
||||
};
|
||||
|
||||
static const struct of_device_id pcm1792a_of_match[] = {
|
||||
{ .compatible = "ti,pcm1792a", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pcm1792a_of_match);
|
||||
|
||||
static const struct regmap_config pcm1792a_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 24,
|
||||
.reg_defaults = pcm1792a_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(pcm1792a_reg_defaults),
|
||||
.writeable_reg = pcm1792a_writeable_reg,
|
||||
.readable_reg = pcm1792a_accessible_reg,
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_pcm1792a = {
|
||||
.controls = pcm1792a_controls,
|
||||
.num_controls = ARRAY_SIZE(pcm1792a_controls),
|
||||
.dapm_widgets = pcm1792a_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(pcm1792a_dapm_widgets),
|
||||
.dapm_routes = pcm1792a_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(pcm1792a_dapm_routes),
|
||||
};
|
||||
|
||||
static int pcm1792a_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct pcm1792a_private *pcm1792a;
|
||||
int ret;
|
||||
|
||||
pcm1792a = devm_kzalloc(&spi->dev, sizeof(struct pcm1792a_private),
|
||||
GFP_KERNEL);
|
||||
if (!pcm1792a)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_drvdata(spi, pcm1792a);
|
||||
|
||||
pcm1792a->regmap = devm_regmap_init_spi(spi, &pcm1792a_regmap);
|
||||
if (IS_ERR(pcm1792a->regmap)) {
|
||||
ret = PTR_ERR(pcm1792a->regmap);
|
||||
dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return snd_soc_register_codec(&spi->dev,
|
||||
&soc_codec_dev_pcm1792a, &pcm1792a_dai, 1);
|
||||
}
|
||||
|
||||
static int pcm1792a_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id pcm1792a_spi_ids[] = {
|
||||
{ "pcm1792a", 0 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, pcm1792a_spi_ids);
|
||||
|
||||
static struct spi_driver pcm1792a_codec_driver = {
|
||||
.driver = {
|
||||
.name = "pcm1792a",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(pcm1792a_of_match),
|
||||
},
|
||||
.id_table = pcm1792a_spi_ids,
|
||||
.probe = pcm1792a_spi_probe,
|
||||
.remove = pcm1792a_spi_remove,
|
||||
};
|
||||
|
||||
module_spi_driver(pcm1792a_codec_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC PCM1792A driver");
|
||||
MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
|
||||
MODULE_LICENSE("GPL");
|
26
sound/soc/codecs/pcm1792a.h
Normal file
26
sound/soc/codecs/pcm1792a.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* definitions for PCM1792A
|
||||
*
|
||||
* Copyright 2013 Amarula Solutions
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __PCM1792A_H__
|
||||
#define __PCM1792A_H__
|
||||
|
||||
#define PCM1792A_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_8000_48000 | \
|
||||
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
|
||||
|
||||
#define PCM1792A_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \
|
||||
SNDRV_PCM_FMTBIT_S16_LE)
|
||||
|
||||
#endif
|
|
@ -28,7 +28,54 @@
|
|||
|
||||
#include "pcm3008.h"
|
||||
|
||||
#define PCM3008_VERSION "0.2"
|
||||
static int pcm3008_dac_ev(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
int event)
|
||||
{
|
||||
struct snd_soc_codec *codec = w->codec;
|
||||
struct pcm3008_setup_data *setup = codec->dev->platform_data;
|
||||
|
||||
gpio_set_value_cansleep(setup->pdda_pin,
|
||||
SND_SOC_DAPM_EVENT_ON(event));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm3008_adc_ev(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
int event)
|
||||
{
|
||||
struct snd_soc_codec *codec = w->codec;
|
||||
struct pcm3008_setup_data *setup = codec->dev->platform_data;
|
||||
|
||||
gpio_set_value_cansleep(setup->pdad_pin,
|
||||
SND_SOC_DAPM_EVENT_ON(event));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget pcm3008_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("VINL"),
|
||||
SND_SOC_DAPM_INPUT("VINR"),
|
||||
|
||||
SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, pcm3008_dac_ev,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_ADC_E("ADC", NULL, SND_SOC_NOPM, 0, 0, pcm3008_adc_ev,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("VOUTL"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUTR"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route pcm3008_dapm_routes[] = {
|
||||
{ "PCM3008 Capture", NULL, "ADC" },
|
||||
{ "ADC", NULL, "VINL" },
|
||||
{ "ADC", NULL, "VINR" },
|
||||
|
||||
{ "DAC", NULL, "PCM3008 Playback" },
|
||||
{ "VOUTL", NULL, "DAC" },
|
||||
{ "VOUTR", NULL, "DAC" },
|
||||
};
|
||||
|
||||
#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
|
||||
SNDRV_PCM_RATE_48000)
|
||||
|
@ -51,20 +98,20 @@ static struct snd_soc_dai_driver pcm3008_dai = {
|
|||
},
|
||||
};
|
||||
|
||||
static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
|
||||
{
|
||||
gpio_free(setup->dem0_pin);
|
||||
gpio_free(setup->dem1_pin);
|
||||
gpio_free(setup->pdad_pin);
|
||||
gpio_free(setup->pdda_pin);
|
||||
}
|
||||
static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
|
||||
.dapm_widgets = pcm3008_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(pcm3008_dapm_widgets),
|
||||
.dapm_routes = pcm3008_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(pcm3008_dapm_routes),
|
||||
};
|
||||
|
||||
static int pcm3008_soc_probe(struct snd_soc_codec *codec)
|
||||
static int pcm3008_codec_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct pcm3008_setup_data *setup = codec->dev->platform_data;
|
||||
int ret = 0;
|
||||
struct pcm3008_setup_data *setup = pdev->dev.platform_data;
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION);
|
||||
if (!setup)
|
||||
return -EINVAL;
|
||||
|
||||
/* DEM1 DEM0 DE-EMPHASIS_MODE
|
||||
* Low Low De-emphasis 44.1 kHz ON
|
||||
|
@ -74,83 +121,29 @@ static int pcm3008_soc_probe(struct snd_soc_codec *codec)
|
|||
*/
|
||||
|
||||
/* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */
|
||||
ret = gpio_request(setup->dem0_pin, "codec_dem0");
|
||||
if (ret == 0)
|
||||
ret = gpio_direction_output(setup->dem0_pin, 1);
|
||||
ret = devm_gpio_request_one(&pdev->dev, setup->dem0_pin,
|
||||
GPIOF_OUT_INIT_HIGH, "codec_dem0");
|
||||
if (ret != 0)
|
||||
goto gpio_err;
|
||||
return ret;
|
||||
|
||||
/* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */
|
||||
ret = gpio_request(setup->dem1_pin, "codec_dem1");
|
||||
if (ret == 0)
|
||||
ret = gpio_direction_output(setup->dem1_pin, 0);
|
||||
ret = devm_gpio_request_one(&pdev->dev, setup->dem1_pin,
|
||||
GPIOF_OUT_INIT_LOW, "codec_dem1");
|
||||
if (ret != 0)
|
||||
goto gpio_err;
|
||||
return ret;
|
||||
|
||||
/* Configure PDAD GPIO. */
|
||||
ret = gpio_request(setup->pdad_pin, "codec_pdad");
|
||||
if (ret == 0)
|
||||
ret = gpio_direction_output(setup->pdad_pin, 1);
|
||||
ret = devm_gpio_request_one(&pdev->dev, setup->pdad_pin,
|
||||
GPIOF_OUT_INIT_LOW, "codec_pdad");
|
||||
if (ret != 0)
|
||||
goto gpio_err;
|
||||
return ret;
|
||||
|
||||
/* Configure PDDA GPIO. */
|
||||
ret = gpio_request(setup->pdda_pin, "codec_pdda");
|
||||
if (ret == 0)
|
||||
ret = gpio_direction_output(setup->pdda_pin, 1);
|
||||
ret = devm_gpio_request_one(&pdev->dev, setup->pdda_pin,
|
||||
GPIOF_OUT_INIT_LOW, "codec_pdda");
|
||||
if (ret != 0)
|
||||
goto gpio_err;
|
||||
|
||||
return ret;
|
||||
|
||||
gpio_err:
|
||||
pcm3008_gpio_free(setup);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pcm3008_soc_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct pcm3008_setup_data *setup = codec->dev->platform_data;
|
||||
|
||||
pcm3008_gpio_free(setup);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int pcm3008_soc_suspend(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct pcm3008_setup_data *setup = codec->dev->platform_data;
|
||||
|
||||
gpio_set_value(setup->pdad_pin, 0);
|
||||
gpio_set_value(setup->pdda_pin, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm3008_soc_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct pcm3008_setup_data *setup = codec->dev->platform_data;
|
||||
|
||||
gpio_set_value(setup->pdad_pin, 1);
|
||||
gpio_set_value(setup->pdda_pin, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define pcm3008_soc_suspend NULL
|
||||
#define pcm3008_soc_resume NULL
|
||||
#endif
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
|
||||
.probe = pcm3008_soc_probe,
|
||||
.remove = pcm3008_soc_remove,
|
||||
.suspend = pcm3008_soc_suspend,
|
||||
.resume = pcm3008_soc_resume,
|
||||
};
|
||||
|
||||
static int pcm3008_codec_probe(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_register_codec(&pdev->dev,
|
||||
&soc_codec_dev_pcm3008, &pcm3008_dai, 1);
|
||||
}
|
||||
|
@ -158,6 +151,7 @@ static int pcm3008_codec_probe(struct platform_device *pdev)
|
|||
static int pcm3008_codec_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -737,29 +737,6 @@ static const struct snd_kcontrol_new rt5640_mono_mix[] = {
|
|||
RT5640_M_BST1_MM_SFT, 1, 1),
|
||||
};
|
||||
|
||||
/* INL/R source */
|
||||
static const char * const rt5640_inl_src[] = {
|
||||
"IN2P", "MONOP"
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5640_inl_enum, RT5640_INL_INR_VOL,
|
||||
RT5640_INL_SEL_SFT, rt5640_inl_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5640_inl_mux =
|
||||
SOC_DAPM_ENUM("INL source", rt5640_inl_enum);
|
||||
|
||||
static const char * const rt5640_inr_src[] = {
|
||||
"IN2N", "MONON"
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(
|
||||
rt5640_inr_enum, RT5640_INL_INR_VOL,
|
||||
RT5640_INR_SEL_SFT, rt5640_inr_src);
|
||||
|
||||
static const struct snd_kcontrol_new rt5640_inr_mux =
|
||||
SOC_DAPM_ENUM("INR source", rt5640_inr_enum);
|
||||
|
||||
/* Stereo ADC source */
|
||||
static const char * const rt5640_stereo_adc1_src[] = {
|
||||
"DIG MIX", "ADC"
|
||||
|
@ -1005,9 +982,6 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
|
|||
RT5640_PWR_IN_L_BIT, 0, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("INR VOL", RT5640_PWR_VOL,
|
||||
RT5640_PWR_IN_R_BIT, 0, NULL, 0),
|
||||
/* IN Mux */
|
||||
SND_SOC_DAPM_MUX("INL Mux", SND_SOC_NOPM, 0, 0, &rt5640_inl_mux),
|
||||
SND_SOC_DAPM_MUX("INR Mux", SND_SOC_NOPM, 0, 0, &rt5640_inr_mux),
|
||||
/* REC Mixer */
|
||||
SND_SOC_DAPM_MIXER("RECMIXL", RT5640_PWR_MIXER, RT5640_PWR_RM_L_BIT, 0,
|
||||
rt5640_rec_l_mix, ARRAY_SIZE(rt5640_rec_l_mix)),
|
||||
|
|
|
@ -654,16 +654,19 @@ static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate)
|
|||
snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
|
||||
SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP,
|
||||
SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP);
|
||||
|
||||
/* if using pll, clk_ctrl must be set after pll power up */
|
||||
snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl);
|
||||
} else {
|
||||
/* otherwise, clk_ctrl must be set before pll power down */
|
||||
snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl);
|
||||
|
||||
/* power down pll */
|
||||
snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
|
||||
SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP,
|
||||
0);
|
||||
}
|
||||
|
||||
/* if using pll, clk_ctrl must be set after pll power up */
|
||||
snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1480,6 +1483,7 @@ static struct snd_soc_codec_driver sgtl5000_driver = {
|
|||
static const struct regmap_config sgtl5000_regmap = {
|
||||
.reg_bits = 16,
|
||||
.val_bits = 16,
|
||||
.reg_stride = 2,
|
||||
|
||||
.max_register = SGTL5000_MAX_REG_OFFSET,
|
||||
.volatile_reg = sgtl5000_volatile,
|
||||
|
|
|
@ -102,6 +102,16 @@ static int si476x_codec_write(struct snd_soc_codec *codec,
|
|||
return err;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget si476x_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_OUTPUT("LOUT"),
|
||||
SND_SOC_DAPM_OUTPUT("ROUT"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route si476x_dapm_routes[] = {
|
||||
{ "Capture", NULL, "LOUT" },
|
||||
{ "Capture", NULL, "ROUT" },
|
||||
};
|
||||
|
||||
static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
unsigned int fmt)
|
||||
{
|
||||
|
@ -260,6 +270,10 @@ static struct snd_soc_codec_driver soc_codec_dev_si476x = {
|
|||
.probe = si476x_codec_probe,
|
||||
.read = si476x_codec_read,
|
||||
.write = si476x_codec_write,
|
||||
.dapm_widgets = si476x_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(si476x_dapm_widgets),
|
||||
.dapm_routes = si476x_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(si476x_dapm_routes),
|
||||
};
|
||||
|
||||
static int si476x_platform_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -23,11 +23,26 @@
|
|||
#include <sound/initval.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
static const struct snd_soc_dapm_widget dir_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("spdif-in"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route dir_routes[] = {
|
||||
{ "Capture", NULL, "spdif-in" },
|
||||
};
|
||||
|
||||
#define STUB_RATES SNDRV_PCM_RATE_8000_192000
|
||||
#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
|
||||
SNDRV_PCM_FMTBIT_S20_3LE | \
|
||||
SNDRV_PCM_FMTBIT_S24_LE | \
|
||||
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_spdif_dir;
|
||||
static struct snd_soc_codec_driver soc_codec_spdif_dir = {
|
||||
.dapm_widgets = dir_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(dir_widgets),
|
||||
.dapm_routes = dir_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(dir_routes),
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver dir_stub_dai = {
|
||||
.name = "dir-hifi",
|
||||
|
|
|
@ -25,10 +25,24 @@
|
|||
#define DRV_NAME "spdif-dit"
|
||||
|
||||
#define STUB_RATES SNDRV_PCM_RATE_8000_96000
|
||||
#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE
|
||||
#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
|
||||
SNDRV_PCM_FMTBIT_S20_3LE | \
|
||||
SNDRV_PCM_FMTBIT_S24_LE)
|
||||
|
||||
static const struct snd_soc_dapm_widget dit_widgets[] = {
|
||||
SND_SOC_DAPM_OUTPUT("spdif-out"),
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_spdif_dit;
|
||||
static const struct snd_soc_dapm_route dit_routes[] = {
|
||||
{ "spdif-out", NULL, "Playback" },
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_spdif_dit = {
|
||||
.dapm_widgets = dit_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(dit_widgets),
|
||||
.dapm_routes = dit_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(dit_routes),
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver dit_stub_dai = {
|
||||
.name = "dit-hifi",
|
||||
|
|
|
@ -363,7 +363,8 @@ static void sta32x_watchdog(struct work_struct *work)
|
|||
}
|
||||
|
||||
if (!sta32x->shutdown)
|
||||
schedule_delayed_work(&sta32x->watchdog_work,
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&sta32x->watchdog_work,
|
||||
round_jiffies_relative(HZ));
|
||||
}
|
||||
|
||||
|
@ -371,7 +372,8 @@ static void sta32x_watchdog_start(struct sta32x_priv *sta32x)
|
|||
{
|
||||
if (sta32x->pdata->needs_esd_watchdog) {
|
||||
sta32x->shutdown = 0;
|
||||
schedule_delayed_work(&sta32x->watchdog_work,
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&sta32x->watchdog_work,
|
||||
round_jiffies_relative(HZ));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ MODULE_LICENSE("GPL");
|
|||
/* AIC26 driver private data */
|
||||
struct aic26 {
|
||||
struct spi_device *spi;
|
||||
struct snd_soc_codec codec;
|
||||
struct snd_soc_codec *codec;
|
||||
int master;
|
||||
int datfm;
|
||||
int mclk;
|
||||
|
@ -119,6 +119,22 @@ static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget tlv320aic26_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("MICIN"),
|
||||
SND_SOC_DAPM_INPUT("AUX"),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("HPL"),
|
||||
SND_SOC_DAPM_OUTPUT("HPR"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route tlv320aic26_dapm_routes[] = {
|
||||
{ "Capture", NULL, "MICIN" },
|
||||
{ "Capture", NULL, "AUX" },
|
||||
|
||||
{ "HPL", NULL, "Playback" },
|
||||
{ "HPR", NULL, "Playback" },
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Digital Audio Interface Operations
|
||||
*/
|
||||
|
@ -174,9 +190,9 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
|
|||
dev_dbg(&aic26->spi->dev, "Setting PLLM to %d.%04d\n", jval, dval);
|
||||
qval = 0;
|
||||
reg = 0x8000 | qval << 11 | pval << 8 | jval << 2;
|
||||
aic26_reg_write(codec, AIC26_REG_PLL_PROG1, reg);
|
||||
snd_soc_write(codec, AIC26_REG_PLL_PROG1, reg);
|
||||
reg = dval << 2;
|
||||
aic26_reg_write(codec, AIC26_REG_PLL_PROG2, reg);
|
||||
snd_soc_write(codec, AIC26_REG_PLL_PROG2, reg);
|
||||
|
||||
/* Audio Control 3 (master mode, fsref rate) */
|
||||
reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL3);
|
||||
|
@ -185,13 +201,13 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
|
|||
reg |= 0x0800;
|
||||
if (fsref == 48000)
|
||||
reg |= 0x2000;
|
||||
aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
|
||||
snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
|
||||
|
||||
/* Audio Control 1 (FSref divisor) */
|
||||
reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL1);
|
||||
reg &= ~0x0fff;
|
||||
reg |= wlen | aic26->datfm | (divisor << 3) | divisor;
|
||||
aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL1, reg);
|
||||
snd_soc_write(codec, AIC26_REG_AUDIO_CTRL1, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -212,7 +228,7 @@ static int aic26_mute(struct snd_soc_dai *dai, int mute)
|
|||
reg |= 0x8080;
|
||||
else
|
||||
reg &= ~0x8080;
|
||||
aic26_reg_write(codec, AIC26_REG_DAC_GAIN, reg);
|
||||
snd_soc_write(codec, AIC26_REG_DAC_GAIN, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -330,7 +346,7 @@ static ssize_t aic26_keyclick_show(struct device *dev,
|
|||
struct aic26 *aic26 = dev_get_drvdata(dev);
|
||||
int val, amp, freq, len;
|
||||
|
||||
val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2);
|
||||
val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2);
|
||||
amp = (val >> 12) & 0x7;
|
||||
freq = (125 << ((val >> 8) & 0x7)) >> 1;
|
||||
len = 2 * (1 + ((val >> 4) & 0xf));
|
||||
|
@ -346,9 +362,9 @@ static ssize_t aic26_keyclick_set(struct device *dev,
|
|||
struct aic26 *aic26 = dev_get_drvdata(dev);
|
||||
int val;
|
||||
|
||||
val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2);
|
||||
val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2);
|
||||
val |= 0x8000;
|
||||
aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL2, val);
|
||||
snd_soc_write(aic26->codec, AIC26_REG_AUDIO_CTRL2, val);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -360,25 +376,26 @@ static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);
|
|||
*/
|
||||
static int aic26_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct aic26 *aic26 = dev_get_drvdata(codec->dev);
|
||||
int ret, err, i, reg;
|
||||
|
||||
dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n");
|
||||
aic26->codec = codec;
|
||||
|
||||
/* Reset the codec to power on defaults */
|
||||
aic26_reg_write(codec, AIC26_REG_RESET, 0xBB00);
|
||||
snd_soc_write(codec, AIC26_REG_RESET, 0xBB00);
|
||||
|
||||
/* Power up CODEC */
|
||||
aic26_reg_write(codec, AIC26_REG_POWER_CTRL, 0);
|
||||
snd_soc_write(codec, AIC26_REG_POWER_CTRL, 0);
|
||||
|
||||
/* Audio Control 3 (master mode, fsref rate) */
|
||||
reg = aic26_reg_read(codec, AIC26_REG_AUDIO_CTRL3);
|
||||
reg = snd_soc_read(codec, AIC26_REG_AUDIO_CTRL3);
|
||||
reg &= ~0xf800;
|
||||
reg |= 0x0800; /* set master mode */
|
||||
aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
|
||||
snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
|
||||
|
||||
/* Fill register cache */
|
||||
for (i = 0; i < codec->driver->reg_cache_size; i++)
|
||||
aic26_reg_read(codec, i);
|
||||
snd_soc_read(codec, i);
|
||||
|
||||
/* Register the sysfs files for debugging */
|
||||
/* Create SysFS files */
|
||||
|
@ -401,6 +418,10 @@ static struct snd_soc_codec_driver aic26_soc_codec_dev = {
|
|||
.write = aic26_reg_write,
|
||||
.reg_cache_size = AIC26_NUM_REGS,
|
||||
.reg_word_size = sizeof(u16),
|
||||
.dapm_widgets = tlv320aic26_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(tlv320aic26_dapm_widgets),
|
||||
.dapm_routes = tlv320aic26_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(tlv320aic26_dapm_routes),
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
|
|
@ -138,8 +138,7 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
|
|||
static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
|
||||
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
unsigned int reg = mc->reg;
|
||||
|
@ -147,10 +146,9 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
|
|||
int max = mc->max;
|
||||
unsigned int mask = (1 << fls(max)) - 1;
|
||||
unsigned int invert = mc->invert;
|
||||
unsigned short val, val_mask;
|
||||
int ret;
|
||||
struct snd_soc_dapm_path *path;
|
||||
int found = 0;
|
||||
unsigned short val;
|
||||
struct snd_soc_dapm_update update;
|
||||
int connect, change;
|
||||
|
||||
val = (ucontrol->value.integer.value[0] & mask);
|
||||
|
||||
|
@ -158,42 +156,26 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
|
|||
if (val)
|
||||
val = mask;
|
||||
|
||||
connect = !!val;
|
||||
|
||||
if (invert)
|
||||
val = mask - val;
|
||||
val_mask = mask << shift;
|
||||
val = val << shift;
|
||||
|
||||
mutex_lock(&widget->codec->mutex);
|
||||
mask <<= shift;
|
||||
val <<= shift;
|
||||
|
||||
if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) {
|
||||
/* find dapm widget path assoc with kcontrol */
|
||||
list_for_each_entry(path, &widget->dapm->card->paths, list) {
|
||||
if (path->kcontrol != kcontrol)
|
||||
continue;
|
||||
change = snd_soc_test_bits(codec, val, mask, reg);
|
||||
if (change) {
|
||||
update.kcontrol = kcontrol;
|
||||
update.reg = reg;
|
||||
update.mask = mask;
|
||||
update.val = val;
|
||||
|
||||
/* found, now check type */
|
||||
found = 1;
|
||||
if (val)
|
||||
/* new connection */
|
||||
path->connect = invert ? 0 : 1;
|
||||
else
|
||||
/* old connection must be powered down */
|
||||
path->connect = invert ? 1 : 0;
|
||||
|
||||
dapm_mark_dirty(path->source, "tlv320aic3x source");
|
||||
dapm_mark_dirty(path->sink, "tlv320aic3x sink");
|
||||
|
||||
break;
|
||||
}
|
||||
snd_soc_dapm_mixer_update_power(&codec->dapm, kcontrol, connect,
|
||||
&update);
|
||||
}
|
||||
|
||||
mutex_unlock(&widget->codec->mutex);
|
||||
|
||||
if (found)
|
||||
snd_soc_dapm_sync(widget->dapm);
|
||||
|
||||
ret = snd_soc_update_bits_locked(widget->codec, reg, val_mask, val);
|
||||
return ret;
|
||||
return change;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1492,6 +1474,7 @@ static const struct i2c_device_id aic3x_i2c_id[] = {
|
|||
{ "tlv320aic3x", AIC3X_MODEL_3X },
|
||||
{ "tlv320aic33", AIC3X_MODEL_33 },
|
||||
{ "tlv320aic3007", AIC3X_MODEL_3007 },
|
||||
{ "tlv320aic3106", AIC3X_MODEL_3X },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
|
||||
|
@ -1582,6 +1565,9 @@ static int aic3x_i2c_remove(struct i2c_client *client)
|
|||
#if defined(CONFIG_OF)
|
||||
static const struct of_device_id tlv320aic3x_of_match[] = {
|
||||
{ .compatible = "ti,tlv320aic3x", },
|
||||
{ .compatible = "ti,tlv320aic33" },
|
||||
{ .compatible = "ti,tlv320aic3007" },
|
||||
{ .compatible = "ti,tlv320aic3106" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match);
|
||||
|
|
|
@ -137,8 +137,6 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
|
|||
|
||||
/* codec private data */
|
||||
struct twl4030_priv {
|
||||
struct snd_soc_codec codec;
|
||||
|
||||
unsigned int codec_powered;
|
||||
|
||||
/* reference counts of AIF/APLL users */
|
||||
|
|
|
@ -429,7 +429,8 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data)
|
|||
struct snd_soc_codec *codec = data;
|
||||
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
schedule_delayed_work(&priv->hs_jack.work, msecs_to_jiffies(200));
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&priv->hs_jack.work, msecs_to_jiffies(200));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -437,9 +438,7 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data)
|
|||
static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
|
||||
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
|
||||
struct snd_soc_codec *codec = widget->codec;
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned int val;
|
||||
|
||||
|
|
|
@ -325,7 +325,6 @@ static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
|||
static int uda134x_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
u8 reg;
|
||||
struct uda134x_platform_data *pd = codec->control_data;
|
||||
int i;
|
||||
u8 *cache = codec->reg_cache;
|
||||
|
@ -334,23 +333,6 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,
|
|||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
/* ADC, DAC on */
|
||||
switch (pd->model) {
|
||||
case UDA134X_UDA1340:
|
||||
case UDA134X_UDA1344:
|
||||
case UDA134X_UDA1345:
|
||||
reg = uda134x_read_reg_cache(codec, UDA134X_DATA011);
|
||||
uda134x_write(codec, UDA134X_DATA011, reg | 0x03);
|
||||
break;
|
||||
case UDA134X_UDA1341:
|
||||
reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
|
||||
uda134x_write(codec, UDA134X_STATUS1, reg | 0x03);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "UDA134X SoC codec: "
|
||||
"unsupported model %d\n", pd->model);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
/* power on */
|
||||
|
@ -362,23 +344,6 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,
|
|||
}
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
/* ADC, DAC power off */
|
||||
switch (pd->model) {
|
||||
case UDA134X_UDA1340:
|
||||
case UDA134X_UDA1344:
|
||||
case UDA134X_UDA1345:
|
||||
reg = uda134x_read_reg_cache(codec, UDA134X_DATA011);
|
||||
uda134x_write(codec, UDA134X_DATA011, reg & ~(0x03));
|
||||
break;
|
||||
case UDA134X_UDA1341:
|
||||
reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
|
||||
uda134x_write(codec, UDA134X_STATUS1, reg & ~(0x03));
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "UDA134X SoC codec: "
|
||||
"unsupported model %d\n", pd->model);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
/* power off */
|
||||
|
@ -450,6 +415,37 @@ SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
|
|||
SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
|
||||
};
|
||||
|
||||
/* UDA1341 has the DAC/ADC power down in STATUS1 */
|
||||
static const struct snd_soc_dapm_widget uda1341_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_DAC("DAC", "Playback", UDA134X_STATUS1, 0, 0),
|
||||
SND_SOC_DAPM_ADC("ADC", "Capture", UDA134X_STATUS1, 1, 0),
|
||||
};
|
||||
|
||||
/* UDA1340/4/5 has the DAC/ADC pwoer down in DATA0 11 */
|
||||
static const struct snd_soc_dapm_widget uda1340_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_DAC("DAC", "Playback", UDA134X_DATA011, 0, 0),
|
||||
SND_SOC_DAPM_ADC("ADC", "Capture", UDA134X_DATA011, 1, 0),
|
||||
};
|
||||
|
||||
/* Common DAPM widgets */
|
||||
static const struct snd_soc_dapm_widget uda134x_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("VINL1"),
|
||||
SND_SOC_DAPM_INPUT("VINR1"),
|
||||
SND_SOC_DAPM_INPUT("VINL2"),
|
||||
SND_SOC_DAPM_INPUT("VINR2"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUTL"),
|
||||
SND_SOC_DAPM_OUTPUT("VOUTR"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route uda134x_dapm_routes[] = {
|
||||
{ "ADC", NULL, "VINL1" },
|
||||
{ "ADC", NULL, "VINR1" },
|
||||
{ "ADC", NULL, "VINL2" },
|
||||
{ "ADC", NULL, "VINR2" },
|
||||
{ "VOUTL", NULL, "DAC" },
|
||||
{ "VOUTR", NULL, "DAC" },
|
||||
};
|
||||
|
||||
static const struct snd_soc_dai_ops uda134x_dai_ops = {
|
||||
.startup = uda134x_startup,
|
||||
.shutdown = uda134x_shutdown,
|
||||
|
@ -485,6 +481,8 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
|
|||
{
|
||||
struct uda134x_priv *uda134x;
|
||||
struct uda134x_platform_data *pd = codec->card->dev->platform_data;
|
||||
const struct snd_soc_dapm_widget *widgets;
|
||||
unsigned num_widgets;
|
||||
|
||||
int ret;
|
||||
|
||||
|
@ -526,6 +524,22 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
|
|||
else
|
||||
uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
if (pd->model == UDA134X_UDA1341) {
|
||||
widgets = uda1341_dapm_widgets;
|
||||
num_widgets = ARRAY_SIZE(uda1341_dapm_widgets);
|
||||
} else {
|
||||
widgets = uda1340_dapm_widgets;
|
||||
num_widgets = ARRAY_SIZE(uda1340_dapm_widgets);
|
||||
}
|
||||
|
||||
ret = snd_soc_dapm_new_controls(&codec->dapm, widgets, num_widgets);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "%s failed to register dapm controls: %d",
|
||||
__func__, ret);
|
||||
kfree(uda134x);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (pd->model) {
|
||||
case UDA134X_UDA1340:
|
||||
case UDA134X_UDA1344:
|
||||
|
@ -599,6 +613,10 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
|
|||
.read = uda134x_read_reg_cache,
|
||||
.write = uda134x_write,
|
||||
.set_bias_level = uda134x_set_bias_level,
|
||||
.dapm_widgets = uda134x_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets),
|
||||
.dapm_routes = uda134x_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes),
|
||||
};
|
||||
|
||||
static int uda134x_codec_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -290,6 +290,18 @@ static const struct snd_kcontrol_new wl1273_controls[] = {
|
|||
snd_wl1273_fm_volume_get, snd_wl1273_fm_volume_put),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget wl1273_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("RX"),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("TX"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route wl1273_dapm_routes[] = {
|
||||
{ "Capture", NULL, "RX" },
|
||||
|
||||
{ "TX", NULL, "Playback" },
|
||||
};
|
||||
|
||||
static int wl1273_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
|
@ -483,6 +495,11 @@ static int wl1273_remove(struct snd_soc_codec *codec)
|
|||
static struct snd_soc_codec_driver soc_codec_dev_wl1273 = {
|
||||
.probe = wl1273_probe,
|
||||
.remove = wl1273_remove,
|
||||
|
||||
.dapm_widgets = wl1273_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(wl1273_dapm_widgets),
|
||||
.dapm_routes = wl1273_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(wl1273_dapm_routes),
|
||||
};
|
||||
|
||||
static int wl1273_platform_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -420,7 +420,7 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec)
|
|||
xfer->codec = codec;
|
||||
list_add_tail(&xfer->list, &xfer_list);
|
||||
|
||||
out = kzalloc(len, GFP_KERNEL);
|
||||
out = kzalloc(len, GFP_KERNEL | GFP_DMA);
|
||||
if (!out) {
|
||||
dev_err(codec->dev,
|
||||
"Failed to allocate RX buffer\n");
|
||||
|
@ -429,7 +429,7 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec)
|
|||
}
|
||||
xfer->t.rx_buf = out;
|
||||
|
||||
img = kzalloc(len, GFP_KERNEL);
|
||||
img = kzalloc(len, GFP_KERNEL | GFP_DMA);
|
||||
if (!img) {
|
||||
dev_err(codec->dev,
|
||||
"Failed to allocate image buffer\n");
|
||||
|
@ -523,14 +523,14 @@ static int wm0010_stage2_load(struct snd_soc_codec *codec)
|
|||
dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size);
|
||||
|
||||
/* Copy to local buffer first as vmalloc causes problems for dma */
|
||||
img = kzalloc(fw->size, GFP_KERNEL);
|
||||
img = kzalloc(fw->size, GFP_KERNEL | GFP_DMA);
|
||||
if (!img) {
|
||||
dev_err(codec->dev, "Failed to allocate image buffer\n");
|
||||
ret = -ENOMEM;
|
||||
goto abort2;
|
||||
}
|
||||
|
||||
out = kzalloc(fw->size, GFP_KERNEL);
|
||||
out = kzalloc(fw->size, GFP_KERNEL | GFP_DMA);
|
||||
if (!out) {
|
||||
dev_err(codec->dev, "Failed to allocate output buffer\n");
|
||||
ret = -ENOMEM;
|
||||
|
@ -670,14 +670,14 @@ static int wm0010_boot(struct snd_soc_codec *codec)
|
|||
|
||||
ret = -ENOMEM;
|
||||
len = pll_rec.length + 8;
|
||||
out = kzalloc(len, GFP_KERNEL);
|
||||
out = kzalloc(len, GFP_KERNEL | GFP_DMA);
|
||||
if (!out) {
|
||||
dev_err(codec->dev,
|
||||
"Failed to allocate RX buffer\n");
|
||||
goto abort;
|
||||
}
|
||||
|
||||
img_swap = kzalloc(len, GFP_KERNEL);
|
||||
img_swap = kzalloc(len, GFP_KERNEL | GFP_DMA);
|
||||
if (!img_swap) {
|
||||
dev_err(codec->dev,
|
||||
"Failed to allocate image buffer\n");
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue