sound updates for 3.12-rc1
- HDPM: Updates for AIO/RayDAT support, TCO/sync support - RME96: Add PCM sync support - HD-audio: * A few HDMI/DP audio updates (CA assignment fix, stream switching fix, Intel DP device list support) * Device specific fixes (ASUS/CXT HP mic support, Thinkpad mic improvements, Chromebook fixes, STAC9228 Dell fixes) * Replace the all static quirks for AD codecs with the generic parser * WAKEEN support for handling irqs in the power saving mode - USB-audio: Clean up implicit fb handling and related codes - DAPM is now mandatory for ASoC CODEC drivers; all existing drivers have had some level of DAPM support added. In addition, a lot of cleanups and improvements in DAPM. - Support for ASoC cross-platform compile test - New drivers and support for Analog Devices ADAU1702 and ADAU1401(a), Asahi Kasei Microdevices AK4554, Atmel AT91ASM9x5 and WM8904 based machines, Freescale S/PDIF and SSI AC'97, Renesas R-Car SoCs, Samsung Exynos5420 SoCs, Texas Instruments PCM1681 and PCM1792A and Wolfson Microelectronics WM8997 - DT bindings for kirkwood and i.MX S/PDIF - Clean up and bug fixes: ssm2602, rt5640 and sgtl5000. - Core helpers for bitbanged AC'97 reset -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABAgAGBQJSJ2E+AAoJEGwxgFQ9KSmkQQgP/izfCaTbvFsFOCwn8V8qgKCv fBnakk1IQp7vaMxx1g0wall9clZbnae7sCgst5aCeLjCglzIUHqgsX5xr23QQfPF WEVzW2LhrTmrRIVDnG0v1W5gUaYJk8H6qyMOkVWGtZvpn1M88TbJDv+P2ff3VqqU G1yqeogXGduForHkhDw2TCvnu5WNQGWtvd5O+QtT8kqWqUWqM5sWBbdl1oMpQUnm 0/YmFDSkNRSi8tXerYnfUf1qQuh40efHJ2oql3vfh8+I8nwPqZWScl5e+IwfgBPb azF0oeQM++R8/iZ89vk3hwndKzSN1y6Ok47gM2v+PwcJYoaEGDuIP8mVklUNQR9v ZK1n6AwlyxGH8snBKBX9upqcuT2xycBleh4sYw/t61/T4ne9L7WYY6a69dIetZ5e ALbzI1UP12S0oWiot/mqOcVLEneRNgKAD+K6Xcq7MYEA4g3MXbwWNrQRKRk3Hy5b BDWh39lb7Uh/v+D81UJEfy1UgsSOunUdsGV6AAsam9THW47+2+gO10MvALNueJhH QGOUVapLS553i6i7dZPj1tdumM8AKiqTRE9Bgsn4nWS3jOLtaO7EajOHoBha1JuG S9IxAMgI8y6h2ZXBTcdGrTFBjvbN9o0S3xYTAG0Z1hWGPTbKCxkpopZdbmHs1qJi Xsy9nBk9Dg2DEKDnZ555 =wbLt -----END PGP SIGNATURE----- Merge tag 'sound-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound updates from Takashi Iwai: "Changes are seen in a wide range of codes, mainly due to ASoC DAPM requirements; HD-audio shows a high peak in diffstat, it's just a removal of bunch of old static quirks. Some highlights: - HDPM: Updates for AIO/RayDAT support, TCO/sync support - RME96: Add PCM sync support - HD-audio: * A few HDMI/DP audio updates (CA assignment fix, stream switching fix, Intel DP device list support) * Device specific fixes (ASUS/CXT HP mic support, Thinkpad mic improvements, Chromebook fixes, STAC9228 Dell fixes) * Replace the all static quirks for AD codecs with the generic parser * WAKEEN support for handling irqs in the power saving mode - USB-audio: Clean up implicit fb handling and related codes - DAPM is now mandatory for ASoC CODEC drivers; all existing drivers have had some level of DAPM support added. In addition, a lot of cleanups and improvements in DAPM. - Support for ASoC cross-platform compile test - New drivers and support for Analog Devices ADAU1702 and ADAU1401(a), Asahi Kasei Microdevices AK4554, Atmel AT91ASM9x5 and WM8904 based machines, Freescale S/PDIF and SSI AC'97, Renesas R-Car SoCs, Samsung Exynos5420 SoCs, Texas Instruments PCM1681 and PCM1792A and Wolfson Microelectronics WM8997 - DT bindings for kirkwood and i.MX S/PDIF - Clean up and bug fixes: ssm2602, rt5640 and sgtl5000. - Core helpers for bitbanged AC'97 reset" * tag 'sound-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (375 commits) ALSA: hda - Re-setup HDMI pin and audio infoframe on stream switches ALSA: hda - hdmi: Fallback to ALSA allocation when selecting CA ASoC: mxs-sgtl5000: Configure the dai_links as unidirectional ASoC: soc-pcm: Allow to specify unidirectional dai_link ASoC: fsl_spdif: Staticse non-exported symbols ASoC: ssm2602: Fix cache sync ASoC: Remove unused sysfs_registered field from snd_soc_codec struct ASoC: Remove unused debugfs_dapm field from snd_soc_{platform,codec} struct ASoC: Remove unused control_type field from snd_soc_codec struct ASoC: fsl: Add one blank space after ':=' in Makefile ASoC: fsl: Add wrapping for dev_dbg() in fsl_spdif.c ASoC: rt5640: change widget sequence for depop ASoC: dapm: Fix auto-disable for inverted controls ASoC: fsl: Drop SND_SOC_FSL_UTILS from SND_SOC_IMX_SPDIF ASoC: Samsung: Do not queue cyclic buffers multiple times ASoC: ep93xx-i2s: Remove unnecessary dev_set_drvdata() ASoC: designware_i2s: Remove unnecessary dev_set_drvdata() ASoC: fsl_spdif: remove redundant dev_err call in fsl_spdif_probe() ASoC: fsl: Add S/PDIF machine driver ASoc: kirkwood: Use the Kirkwood audio driver in Dove boards ...
This commit is contained in:
commit
977dbfcf8e
|
@ -7,9 +7,30 @@ Required properties:
|
||||||
- reg: Should contain SSC registers location and length
|
- reg: Should contain SSC registers location and length
|
||||||
- interrupts: Should contain SSC interrupt
|
- 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 {
|
ssc0: ssc@fffbc000 {
|
||||||
compatible = "atmel,at91rm9200-ssc";
|
compatible = "atmel,at91rm9200-ssc";
|
||||||
reg = <0xfffbc000 0x4000>;
|
reg = <0xfffbc000 0x4000>;
|
||||||
interrupts = <14 4 5>;
|
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";
|
||||||
|
};
|
||||||
|
|
|
@ -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";
|
||||||
|
};
|
||||||
|
|
|
@ -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
|
- #gpio-cells : Should be two. The first cell is the pin number and the
|
||||||
second cell is used to specify optional parameters (currently unused).
|
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:
|
Example:
|
||||||
|
|
||||||
alc5632: alc5632@1e {
|
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>;
|
||||||
|
};
|
|
@ -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>;
|
||||||
|
};
|
|
@ -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,
|
together. This would still allow different sample sizes,
|
||||||
but not different sample rates.
|
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:
|
Optional properties:
|
||||||
- codec-handle: Phandle to a 'codec' node that defines an audio
|
- codec-handle: Phandle to a 'codec' node that defines an audio
|
||||||
codec connected to this SSI. This node is typically
|
codec connected to this SSI. This node is typically
|
||||||
a child of an I2C or other control node.
|
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:
|
Child 'codec' node required properties:
|
||||||
- compatible: Compatible list, contains the name of the codec
|
- compatible: Compatible list, contains the name of the codec
|
|
@ -0,0 +1,34 @@
|
||||||
|
Freescale i.MX audio complex with S/PDIF transceiver
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
|
||||||
|
- compatible : "fsl,imx-audio-spdif"
|
||||||
|
|
||||||
|
- model : The user-visible name of this sound complex
|
||||||
|
|
||||||
|
- spdif-controller : The phandle of the i.MX S/PDIF controller
|
||||||
|
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
|
||||||
|
- spdif-out : This is a boolean property. If present, the transmitting
|
||||||
|
function of S/PDIF will be enabled, indicating there's a physical
|
||||||
|
S/PDIF out connector/jack on the board or it's connecting to some
|
||||||
|
other IP block, such as an HDMI encoder/display-controller.
|
||||||
|
|
||||||
|
- spdif-in : This is a boolean property. If present, the receiving
|
||||||
|
function of S/PDIF will be enabled, indicating there's a physical
|
||||||
|
S/PDIF in connector/jack on the board.
|
||||||
|
|
||||||
|
* Note: At least one of these two properties should be set in the DT binding.
|
||||||
|
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
sound-spdif {
|
||||||
|
compatible = "fsl,imx-audio-spdif";
|
||||||
|
model = "imx-spdif";
|
||||||
|
spdif-controller = <&spdif>;
|
||||||
|
spdif-out;
|
||||||
|
spdif-in;
|
||||||
|
};
|
|
@ -5,6 +5,15 @@ Required properties:
|
||||||
or "fsl,imx31-audmux" for the version firstly used on i.MX31.
|
or "fsl,imx31-audmux" for the version firstly used on i.MX31.
|
||||||
- reg : Should contain AUDMUX registers location and length
|
- 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:
|
Example:
|
||||||
|
|
||||||
audmux@021d8000 {
|
audmux@021d8000 {
|
||||||
|
|
|
@ -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>;
|
||||||
|
};
|
||||||
|
|
|
@ -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";
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
* mvebu (Kirkwood, Dove, Armada 370) audio controller
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
|
||||||
|
- compatible: "marvell,mvebu-audio"
|
||||||
|
|
||||||
|
- reg: physical base address of the controller and length of memory mapped
|
||||||
|
region.
|
||||||
|
|
||||||
|
- interrupts: list of two irq numbers.
|
||||||
|
The first irq is used for data flow and the second one is used for errors.
|
||||||
|
|
||||||
|
- clocks: one or two phandles.
|
||||||
|
The first one is mandatory and defines the internal clock.
|
||||||
|
The second one is optional and defines an external clock.
|
||||||
|
|
||||||
|
- clock-names: names associated to the clocks:
|
||||||
|
"internal" for the internal clock
|
||||||
|
"extclk" for the external clock
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
i2s1: audio-controller@b4000 {
|
||||||
|
compatible = "marvell,mvebu-audio";
|
||||||
|
reg = <0xb4000 0x2210>;
|
||||||
|
interrupts = <21>, <22>;
|
||||||
|
clocks = <&gate_clk 13>;
|
||||||
|
clock-names = "internal";
|
||||||
|
};
|
|
@ -11,28 +11,8 @@ Required properties:
|
||||||
- nvidia,audio-routing : A list of the connections between audio components.
|
- 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,
|
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
|
the second being the connection's source. Valid names for sources and
|
||||||
sinks are the ALC5632's pins:
|
sinks are the ALC5632's pins as documented in the binding for the device
|
||||||
|
and:
|
||||||
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:
|
|
||||||
|
|
||||||
* Headset Stereophone
|
* Headset Stereophone
|
||||||
* Int Spk
|
* Int Spk
|
||||||
|
|
|
@ -11,32 +11,12 @@ Required properties:
|
||||||
- nvidia,audio-routing : A list of the connections between audio components.
|
- 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,
|
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
|
the second being the connection's source. Valid names for sources and
|
||||||
sinks are the RT5640's pins, and the jacks on the board:
|
sinks are the RT5640's pins (as documented in its binding), 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:
|
|
||||||
|
|
||||||
* Headphones
|
* Headphones
|
||||||
* Speakers
|
* Speakers
|
||||||
|
* Mic Jack
|
||||||
|
|
||||||
- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
|
- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
|
||||||
connected to the CODEC.
|
connected to the CODEC.
|
||||||
|
|
|
@ -11,31 +11,8 @@ Required properties:
|
||||||
- nvidia,audio-routing : A list of the connections between audio components.
|
- 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,
|
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
|
the second being the connection's source. Valid names for sources and
|
||||||
sinks are the WM8753's pins, and the jacks on the board:
|
sinks are the WM8753's pins as documented in the binding for the WM8753,
|
||||||
|
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:
|
|
||||||
|
|
||||||
* Headphone Jack
|
* Headphone Jack
|
||||||
* Mic Jack
|
* Mic Jack
|
||||||
|
|
|
@ -11,28 +11,8 @@ Required properties:
|
||||||
- nvidia,audio-routing : A list of the connections between audio components.
|
- 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,
|
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
|
the second being the connection's source. Valid names for sources and
|
||||||
sinks are the WM8903's pins, and the jacks on the board:
|
sinks are the WM8903's pins (documented in the WM8903 binding document),
|
||||||
|
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:
|
|
||||||
|
|
||||||
* Headphone Jack
|
* Headphone Jack
|
||||||
* Int Spk
|
* Int Spk
|
||||||
|
|
|
@ -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.
|
- 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:
|
Example:
|
||||||
|
|
||||||
rt5640 {
|
rt5640 {
|
||||||
|
|
|
@ -2,7 +2,15 @@
|
||||||
|
|
||||||
Required SoC Specific Properties:
|
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
|
- reg: physical base address of the controller and length of memory mapped
|
||||||
region.
|
region.
|
||||||
- dmas: list of DMA controller phandle and DMA request line ordered pairs.
|
- dmas: list of DMA controller phandle and DMA request line ordered pairs.
|
||||||
|
@ -21,13 +29,6 @@ Required SoC Specific Properties:
|
||||||
|
|
||||||
Optional 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
|
- samsung,idma-addr: Internal DMA register base address of the audio
|
||||||
sub system(used in secondary sound source).
|
sub system(used in secondary sound source).
|
||||||
- pinctrl-0: Should specify pin control groups used for this controller.
|
- pinctrl-0: Should specify pin control groups used for this controller.
|
||||||
|
@ -36,7 +37,7 @@ Optional SoC Specific Properties:
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
i2s0: i2s@03830000 {
|
i2s0: i2s@03830000 {
|
||||||
compatible = "samsung,i2s-v5";
|
compatible = "samsung,s5pv210-i2s";
|
||||||
reg = <0x03830000 0x100>;
|
reg = <0x03830000 0x100>;
|
||||||
dmas = <&pdma0 10
|
dmas = <&pdma0 10
|
||||||
&pdma0 9
|
&pdma0 9
|
||||||
|
@ -46,9 +47,6 @@ i2s0: i2s@03830000 {
|
||||||
<&clock_audss EXYNOS_I2S_BUS>,
|
<&clock_audss EXYNOS_I2S_BUS>,
|
||||||
<&clock_audss EXYNOS_SCLK_I2S>;
|
<&clock_audss EXYNOS_SCLK_I2S>;
|
||||||
clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
|
clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
|
||||||
samsung,supports-6ch;
|
|
||||||
samsung,supports-rstclr;
|
|
||||||
samsung,supports-secdai;
|
|
||||||
samsung,idma-addr = <0x03000000>;
|
samsung,idma-addr = <0x03000000>;
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&i2s0_bus>;
|
pinctrl-0 = <&i2s0_bus>;
|
||||||
|
|
|
@ -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>;
|
||||||
|
|
||||||
|
...
|
||||||
|
};
|
|
@ -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
|
The tlv320aic3x serial control bus communicates through I2C protocols
|
||||||
|
|
||||||
Required properties:
|
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
|
- reg - <int> - I2C slave address
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,3 +16,12 @@ codec: wm8731@1a {
|
||||||
compatible = "wlf,wm8731";
|
compatible = "wlf,wm8731";
|
||||||
reg = <0x1a>;
|
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
|
- reg : the I2C address of the device for I2C, the chip select
|
||||||
number for SPI.
|
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:
|
Example:
|
||||||
|
|
||||||
codec: wm8737@1a {
|
codec: wm8753@1a {
|
||||||
compatible = "wlf,wm8753";
|
compatible = "wlf,wm8753";
|
||||||
reg = <0x1a>;
|
reg = <0x1a>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,6 +28,25 @@ Optional properties:
|
||||||
performed. If any entry has the value 0xffffffff, that GPIO's
|
performed. If any entry has the value 0xffffffff, that GPIO's
|
||||||
configuration will not be modified.
|
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:
|
Example:
|
||||||
|
|
||||||
codec: wm8903@1a {
|
codec: wm8903@1a {
|
||||||
|
|
|
@ -32,6 +32,10 @@ Optional properties:
|
||||||
The second cell is the flags, encoded as the trigger masks from
|
The second cell is the flags, encoded as the trigger masks from
|
||||||
Documentation/devicetree/bindings/interrupts.txt
|
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,
|
- wlf,gpio-cfg : A list of GPIO configuration register values. If absent,
|
||||||
no configuration of these registers is performed. If any value is
|
no configuration of these registers is performed. If any value is
|
||||||
over 0xffff then the register will be left as default. If present 11
|
over 0xffff then the register will be left as default. If present 11
|
||||||
|
|
|
@ -244,6 +244,7 @@ STAC9227/9228/9229/927x
|
||||||
5stack-no-fp D965 5stack without front panel
|
5stack-no-fp D965 5stack without front panel
|
||||||
dell-3stack Dell Dimension E520
|
dell-3stack Dell Dimension E520
|
||||||
dell-bios Fixes with Dell BIOS setup
|
dell-bios Fixes with Dell BIOS setup
|
||||||
|
dell-bios-amic Fixes with Dell BIOS setup including analog mic
|
||||||
volknob Fixes with volume-knob widget 0x24
|
volknob Fixes with volume-knob widget 0x24
|
||||||
auto BIOS setup (default)
|
auto BIOS setup (default)
|
||||||
|
|
||||||
|
|
|
@ -454,6 +454,8 @@ The generic parser supports the following hints:
|
||||||
- need_dac_fix (bool): limits the DACs depending on the channel count
|
- need_dac_fix (bool): limits the DACs depending on the channel count
|
||||||
- primary_hp (bool): probe headphone jacks as the primary outputs;
|
- primary_hp (bool): probe headphone jacks as the primary outputs;
|
||||||
default true
|
default true
|
||||||
|
- multi_io (bool): try probing multi-I/O config (e.g. shared
|
||||||
|
line-in/surround, mic/clfe jacks)
|
||||||
- multi_cap_vol (bool): provide multiple capture volumes
|
- multi_cap_vol (bool): provide multiple capture volumes
|
||||||
- inv_dmic_split (bool): provide split internal mic volume/switch for
|
- inv_dmic_split (bool): provide split internal mic volume/switch for
|
||||||
phase-inverted digital mics
|
phase-inverted digital mics
|
||||||
|
|
13
MAINTAINERS
13
MAINTAINERS
|
@ -595,6 +595,7 @@ S: Supported
|
||||||
F: sound/soc/codecs/adau*
|
F: sound/soc/codecs/adau*
|
||||||
F: sound/soc/codecs/adav*
|
F: sound/soc/codecs/adav*
|
||||||
F: sound/soc/codecs/ad1*
|
F: sound/soc/codecs/ad1*
|
||||||
|
F: sound/soc/codecs/ad7*
|
||||||
F: sound/soc/codecs/ssm*
|
F: sound/soc/codecs/ssm*
|
||||||
F: sound/soc/codecs/sigmadsp.*
|
F: sound/soc/codecs/sigmadsp.*
|
||||||
|
|
||||||
|
@ -7694,6 +7695,17 @@ F: include/sound/
|
||||||
F: include/uapi/sound/
|
F: include/uapi/sound/
|
||||||
F: sound/
|
F: sound/
|
||||||
|
|
||||||
|
SOUND - COMPRESSED AUDIO
|
||||||
|
M: Vinod Koul <vinod.koul@intel.com>
|
||||||
|
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||||
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
|
||||||
|
S: Supported
|
||||||
|
F: Documentation/sound/alsa/compress_offload.txt
|
||||||
|
F: include/sound/compress_driver.h
|
||||||
|
F: include/uapi/sound/compress_*
|
||||||
|
F: sound/core/compress_offload.c
|
||||||
|
F: sound/soc/soc-compress.c
|
||||||
|
|
||||||
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
|
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
|
||||||
M: Liam Girdwood <lgirdwood@gmail.com>
|
M: Liam Girdwood <lgirdwood@gmail.com>
|
||||||
M: Mark Brown <broonie@kernel.org>
|
M: Mark Brown <broonie@kernel.org>
|
||||||
|
@ -7701,6 +7713,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)
|
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||||
W: http://alsa-project.org/main/index.php/ASoC
|
W: http://alsa-project.org/main/index.php/ASoC
|
||||||
S: Supported
|
S: Supported
|
||||||
|
F: Documentation/sound/alsa/soc/
|
||||||
F: sound/soc/
|
F: sound/soc/
|
||||||
F: include/sound/soc*
|
F: include/sound/soc*
|
||||||
|
|
||||||
|
|
|
@ -405,7 +405,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
i2s0: i2s@03830000 {
|
i2s0: i2s@03830000 {
|
||||||
compatible = "samsung,i2s-v5";
|
compatible = "samsung,s5pv210-i2s";
|
||||||
reg = <0x03830000 0x100>;
|
reg = <0x03830000 0x100>;
|
||||||
dmas = <&pdma0 10
|
dmas = <&pdma0 10
|
||||||
&pdma0 9
|
&pdma0 9
|
||||||
|
@ -415,16 +415,13 @@
|
||||||
<&clock_audss EXYNOS_I2S_BUS>,
|
<&clock_audss EXYNOS_I2S_BUS>,
|
||||||
<&clock_audss EXYNOS_SCLK_I2S>;
|
<&clock_audss EXYNOS_SCLK_I2S>;
|
||||||
clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
|
clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
|
||||||
samsung,supports-6ch;
|
|
||||||
samsung,supports-rstclr;
|
|
||||||
samsung,supports-secdai;
|
|
||||||
samsung,idma-addr = <0x03000000>;
|
samsung,idma-addr = <0x03000000>;
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&i2s0_bus>;
|
pinctrl-0 = <&i2s0_bus>;
|
||||||
};
|
};
|
||||||
|
|
||||||
i2s1: i2s@12D60000 {
|
i2s1: i2s@12D60000 {
|
||||||
compatible = "samsung,i2s-v5";
|
compatible = "samsung,s3c6410-i2s";
|
||||||
reg = <0x12D60000 0x100>;
|
reg = <0x12D60000 0x100>;
|
||||||
dmas = <&pdma1 12
|
dmas = <&pdma1 12
|
||||||
&pdma1 11>;
|
&pdma1 11>;
|
||||||
|
@ -436,7 +433,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
i2s2: i2s@12D70000 {
|
i2s2: i2s@12D70000 {
|
||||||
compatible = "samsung,i2s-v5";
|
compatible = "samsung,s3c6410-i2s";
|
||||||
reg = <0x12D70000 0x100>;
|
reg = <0x12D70000 0x100>;
|
||||||
dmas = <&pdma0 12
|
dmas = <&pdma0 12
|
||||||
&pdma0 11>;
|
&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, "sdhci-dove.1", sdio1);
|
||||||
orion_clkdev_add(NULL, "orion_nand", nand);
|
orion_clkdev_add(NULL, "orion_nand", nand);
|
||||||
orion_clkdev_add(NULL, "cafe1000-ccic.0", camera);
|
orion_clkdev_add(NULL, "cafe1000-ccic.0", camera);
|
||||||
orion_clkdev_add(NULL, "kirkwood-i2s.0", i2s0);
|
orion_clkdev_add(NULL, "mvebu-audio.0", i2s0);
|
||||||
orion_clkdev_add(NULL, "kirkwood-i2s.1", i2s1);
|
orion_clkdev_add(NULL, "mvebu-audio.1", i2s1);
|
||||||
orion_clkdev_add(NULL, "mv_crypto", crypto);
|
orion_clkdev_add(NULL, "mv_crypto", crypto);
|
||||||
orion_clkdev_add(NULL, "dove-ac97", ac97);
|
orion_clkdev_add(NULL, "dove-ac97", ac97);
|
||||||
orion_clkdev_add(NULL, "dove-pdma", pdma);
|
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(NULL, MV_XOR_NAME ".1", xor1);
|
||||||
orion_clkdev_add("0", "pcie", pex0);
|
orion_clkdev_add("0", "pcie", pex0);
|
||||||
orion_clkdev_add("1", "pcie", pex1);
|
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 ".0", runit);
|
||||||
orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".1", runit);
|
orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".1", runit);
|
||||||
|
|
||||||
|
@ -560,7 +560,7 @@ void __init kirkwood_timer_init(void)
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Audio
|
* Audio
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static struct resource kirkwood_i2s_resources[] = {
|
static struct resource kirkwood_audio_resources[] = {
|
||||||
[0] = {
|
[0] = {
|
||||||
.start = AUDIO_PHYS_BASE,
|
.start = AUDIO_PHYS_BASE,
|
||||||
.end = AUDIO_PHYS_BASE + SZ_16K - 1,
|
.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,
|
.burst = 128,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct platform_device kirkwood_i2s_device = {
|
static struct platform_device kirkwood_audio_device = {
|
||||||
.name = "kirkwood-i2s",
|
.name = "mvebu-audio",
|
||||||
.id = -1,
|
.id = -1,
|
||||||
.num_resources = ARRAY_SIZE(kirkwood_i2s_resources),
|
.num_resources = ARRAY_SIZE(kirkwood_audio_resources),
|
||||||
.resource = kirkwood_i2s_resources,
|
.resource = kirkwood_audio_resources,
|
||||||
.dev = {
|
.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)
|
void __init kirkwood_audio_init(void)
|
||||||
{
|
{
|
||||||
platform_device_register(&kirkwood_i2s_device);
|
platform_device_register(&kirkwood_audio_device);
|
||||||
platform_device_register(&kirkwood_pcm_device);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/spi/pxa2xx_spi.h>
|
#include <linux/spi/pxa2xx_spi.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <mach/hardware.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);
|
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)
|
void pxa_ssp_free(struct ssp_device *ssp)
|
||||||
{
|
{
|
||||||
mutex_lock(&ssp_lock);
|
mutex_lock(&ssp_lock);
|
||||||
|
@ -72,96 +98,126 @@ void pxa_ssp_free(struct ssp_device *ssp)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(pxa_ssp_free);
|
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)
|
static int pxa_ssp_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
const struct platform_device_id *id = platform_get_device_id(pdev);
|
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
struct ssp_device *ssp;
|
struct ssp_device *ssp;
|
||||||
int ret = 0;
|
struct device *dev = &pdev->dev;
|
||||||
|
|
||||||
ssp = kzalloc(sizeof(struct ssp_device), GFP_KERNEL);
|
ssp = devm_kzalloc(dev, sizeof(struct ssp_device), GFP_KERNEL);
|
||||||
if (ssp == NULL) {
|
if (ssp == NULL)
|
||||||
dev_err(&pdev->dev, "failed to allocate memory");
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
ssp->pdev = pdev;
|
ssp->pdev = pdev;
|
||||||
|
|
||||||
ssp->clk = clk_get(&pdev->dev, NULL);
|
ssp->clk = devm_clk_get(dev, NULL);
|
||||||
if (IS_ERR(ssp->clk)) {
|
if (IS_ERR(ssp->clk))
|
||||||
ret = PTR_ERR(ssp->clk);
|
return PTR_ERR(ssp->clk);
|
||||||
goto err_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
|
if (dev->of_node) {
|
||||||
if (res == NULL) {
|
struct of_phandle_args dma_spec;
|
||||||
dev_err(&pdev->dev, "no SSP RX DRCMR defined\n");
|
struct device_node *np = dev->of_node;
|
||||||
ret = -ENODEV;
|
|
||||||
goto err_free_clk;
|
|
||||||
}
|
|
||||||
ssp->drcmr_rx = res->start;
|
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
|
/*
|
||||||
if (res == NULL) {
|
* FIXME: we should allocate the DMA channel from this
|
||||||
dev_err(&pdev->dev, "no SSP TX DRCMR defined\n");
|
* context and pass the channel down to the ssp users.
|
||||||
ret = -ENODEV;
|
* For now, we lookup the rx and tx indices manually
|
||||||
goto err_free_clk;
|
*/
|
||||||
|
|
||||||
|
/* 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(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(dev, "no SSP TX DRCMR defined\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
ssp->drcmr_tx = res->start;
|
||||||
}
|
}
|
||||||
ssp->drcmr_tx = res->start;
|
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (res == NULL) {
|
if (res == NULL) {
|
||||||
dev_err(&pdev->dev, "no memory resource defined\n");
|
dev_err(dev, "no memory resource defined\n");
|
||||||
ret = -ENODEV;
|
return -ENODEV;
|
||||||
goto err_free_clk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = request_mem_region(res->start, resource_size(res),
|
res = devm_request_mem_region(dev, res->start, resource_size(res),
|
||||||
pdev->name);
|
pdev->name);
|
||||||
if (res == NULL) {
|
if (res == NULL) {
|
||||||
dev_err(&pdev->dev, "failed to request memory resource\n");
|
dev_err(dev, "failed to request memory resource\n");
|
||||||
ret = -EBUSY;
|
return -EBUSY;
|
||||||
goto err_free_clk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssp->phys_base = res->start;
|
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) {
|
if (ssp->mmio_base == NULL) {
|
||||||
dev_err(&pdev->dev, "failed to ioremap() registers\n");
|
dev_err(dev, "failed to ioremap() registers\n");
|
||||||
ret = -ENODEV;
|
return -ENODEV;
|
||||||
goto err_free_mem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssp->irq = platform_get_irq(pdev, 0);
|
ssp->irq = platform_get_irq(pdev, 0);
|
||||||
if (ssp->irq < 0) {
|
if (ssp->irq < 0) {
|
||||||
dev_err(&pdev->dev, "no IRQ resource defined\n");
|
dev_err(dev, "no IRQ resource defined\n");
|
||||||
ret = -ENODEV;
|
return -ENODEV;
|
||||||
goto err_free_io;
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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->use_count = 0;
|
||||||
ssp->type = (int)id->driver_data;
|
ssp->of_node = dev->of_node;
|
||||||
|
|
||||||
mutex_lock(&ssp_lock);
|
mutex_lock(&ssp_lock);
|
||||||
list_add(&ssp->node, &ssp_list);
|
list_add(&ssp->node, &ssp_list);
|
||||||
mutex_unlock(&ssp_lock);
|
mutex_unlock(&ssp_lock);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, ssp);
|
platform_set_drvdata(pdev, ssp);
|
||||||
return 0;
|
|
||||||
|
|
||||||
err_free_io:
|
return 0;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pxa_ssp_remove(struct platform_device *pdev)
|
static int pxa_ssp_remove(struct platform_device *pdev)
|
||||||
|
@ -201,8 +257,9 @@ static struct platform_driver pxa_ssp_driver = {
|
||||||
.probe = pxa_ssp_probe,
|
.probe = pxa_ssp_probe,
|
||||||
.remove = pxa_ssp_remove,
|
.remove = pxa_ssp_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = "pxa2xx-ssp",
|
.name = "pxa2xx-ssp",
|
||||||
|
.of_match_table = of_match_ptr(pxa_ssp_of_ids),
|
||||||
},
|
},
|
||||||
.id_table = ssp_id_table,
|
.id_table = ssp_id_table,
|
||||||
};
|
};
|
||||||
|
|
|
@ -82,7 +82,8 @@ static int s3c_dma_config(unsigned ch, struct samsung_dma_config *param)
|
||||||
static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep *param)
|
static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep *param)
|
||||||
{
|
{
|
||||||
struct cb_data *data;
|
struct cb_data *data;
|
||||||
int len = (param->cap == DMA_CYCLIC) ? param->period : param->len;
|
dma_addr_t pos = param->buf;
|
||||||
|
dma_addr_t end = param->buf + param->len;
|
||||||
|
|
||||||
list_for_each_entry(data, &dma_list, node)
|
list_for_each_entry(data, &dma_list, node)
|
||||||
if (data->ch == ch)
|
if (data->ch == ch)
|
||||||
|
@ -94,7 +95,15 @@ static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep *param)
|
||||||
data->fp_param = param->fp_param;
|
data->fp_param = param->fp_param;
|
||||||
}
|
}
|
||||||
|
|
||||||
s3c2410_dma_enqueue(ch, (void *)data, param->buf, len);
|
if (param->cap != DMA_CYCLIC) {
|
||||||
|
s3c2410_dma_enqueue(ch, (void *)data, param->buf, param->len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pos < end) {
|
||||||
|
s3c2410_dma_enqueue(ch, (void *)data, pos, param->period);
|
||||||
|
pos += param->period;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ssc_device {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
resource_size_t phybase;
|
dma_addr_t phybase;
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
struct atmel_ssc_platform_data *pdata;
|
struct atmel_ssc_platform_data *pdata;
|
||||||
|
|
|
@ -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_NO_MUXPSR (1 << 2)
|
||||||
#define QUIRK_NEED_RSTCLR (1 << 3)
|
#define QUIRK_NEED_RSTCLR (1 << 3)
|
||||||
|
#define QUIRK_SUPPORTS_TDM (1 << 4)
|
||||||
/* Quirks of the I2S controller */
|
/* Quirks of the I2S controller */
|
||||||
u32 quirks;
|
u32 quirks;
|
||||||
dma_addr_t idma_addr;
|
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/list.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SSP Serial Port Registers
|
* SSP Serial Port Registers
|
||||||
|
@ -190,6 +192,8 @@ struct ssp_device {
|
||||||
int irq;
|
int irq;
|
||||||
int drcmr_rx;
|
int drcmr_rx;
|
||||||
int drcmr_tx;
|
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
|
#ifdef CONFIG_ARCH_PXA
|
||||||
struct ssp_device *pxa_ssp_request(int port, const char *label);
|
struct ssp_device *pxa_ssp_request(int port, const char *label);
|
||||||
void pxa_ssp_free(struct ssp_device *);
|
void pxa_ssp_free(struct ssp_device *);
|
||||||
|
struct ssp_device *pxa_ssp_request_of(const struct device_node *of_node,
|
||||||
|
const char *label);
|
||||||
#else
|
#else
|
||||||
static inline struct ssp_device *pxa_ssp_request(int port, const char *label)
|
static inline struct ssp_device *pxa_ssp_request(int port, const char *label)
|
||||||
{
|
{
|
||||||
return NULL;
|
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) {}
|
static inline void pxa_ssp_free(struct ssp_device *ssp) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <linux/rwsem.h> /* struct rw_semaphore */
|
#include <linux/rwsem.h> /* struct rw_semaphore */
|
||||||
#include <linux/pm.h> /* pm_message_t */
|
#include <linux/pm.h> /* pm_message_t */
|
||||||
#include <linux/stringify.h>
|
#include <linux/stringify.h>
|
||||||
|
#include <linux/printk.h>
|
||||||
|
|
||||||
/* number of supported soundcards */
|
/* number of supported soundcards */
|
||||||
#ifdef CONFIG_SND_DYNAMIC_MINORS
|
#ifdef CONFIG_SND_DYNAMIC_MINORS
|
||||||
|
@ -375,6 +376,11 @@ void __snd_printk(unsigned int level, const char *file, int line,
|
||||||
*/
|
*/
|
||||||
#define snd_BUG() WARN(1, "BUG?\n")
|
#define snd_BUG() WARN(1, "BUG?\n")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suppress high rates of output when CONFIG_SND_DEBUG is enabled.
|
||||||
|
*/
|
||||||
|
#define snd_printd_ratelimit() printk_ratelimit()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_BUG_ON - debugging check macro
|
* snd_BUG_ON - debugging check macro
|
||||||
* @cond: condition to evaluate
|
* @cond: condition to evaluate
|
||||||
|
@ -398,6 +404,8 @@ static inline void _snd_printd(int level, const char *format, ...) {}
|
||||||
unlikely(__ret_warn_on); \
|
unlikely(__ret_warn_on); \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
static inline bool snd_printd_ratelimit(void) { return false; }
|
||||||
|
|
||||||
#endif /* CONFIG_SND_DEBUG */
|
#endif /* CONFIG_SND_DEBUG */
|
||||||
|
|
||||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||||
|
|
|
@ -6,13 +6,6 @@
|
||||||
|
|
||||||
/* PCM */
|
/* 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,
|
extern int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||||
struct snd_pcm_hw_params *params);
|
struct snd_pcm_hw_params *params);
|
||||||
extern int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream);
|
extern int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream);
|
||||||
|
|
|
@ -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, \
|
.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
|
||||||
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
|
.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 */
|
/* path domain */
|
||||||
#define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\
|
#define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\
|
||||||
wcontrols, wncontrols) \
|
wcontrols, wncontrols) \
|
||||||
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
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,\
|
#define SND_SOC_DAPM_OUT_DRV(wname, wreg, wshift, winvert,\
|
||||||
wcontrols, wncontrols) \
|
wcontrols, wncontrols) \
|
||||||
{ .id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_out_drv, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
|
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
||||||
#define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \
|
#define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \
|
||||||
wcontrols, wncontrols)\
|
wcontrols, wncontrols)\
|
||||||
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
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, \
|
#define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \
|
||||||
wcontrols, wncontrols)\
|
wcontrols, wncontrols)\
|
||||||
{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \
|
{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
|
||||||
.shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
.num_kcontrols = wncontrols}
|
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
||||||
#define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \
|
#define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \
|
||||||
{ .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_micbias, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = NULL, .num_kcontrols = 0}
|
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) \
|
#define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \
|
||||||
{ .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_switch, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1}
|
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) \
|
#define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
|
||||||
{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1}
|
.kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||||
#define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \
|
#define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \
|
||||||
{ .id = snd_soc_dapm_virt_mux, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_virt_mux, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1}
|
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) \
|
#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \
|
||||||
{ .id = snd_soc_dapm_value_mux, .name = wname, .reg = wreg, \
|
{ .id = snd_soc_dapm_value_mux, .name = wname, \
|
||||||
.shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
.num_kcontrols = 1}
|
.kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||||
|
|
||||||
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
|
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
|
||||||
#define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\
|
#define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\
|
||||||
wcontrols) \
|
wcontrols) \
|
||||||
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
|
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, \
|
#define SOC_MIXER_ARRAY(wname, wreg, wshift, winvert, \
|
||||||
wcontrols)\
|
wcontrols)\
|
||||||
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
|
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, \
|
#define SOC_MIXER_NAMED_CTL_ARRAY(wname, wreg, wshift, winvert, \
|
||||||
wcontrols)\
|
wcontrols)\
|
||||||
{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \
|
{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
|
||||||
.shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
.num_kcontrols = ARRAY_SIZE(wcontrols)}
|
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
|
||||||
|
|
||||||
/* path domain with event - event handler must return 0 for success */
|
/* path domain with event - event handler must return 0 for success */
|
||||||
#define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \
|
#define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||||
wncontrols, wevent, wflags) \
|
wncontrols, wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
|
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
||||||
.event = wevent, .event_flags = wflags}
|
.event = wevent, .event_flags = wflags}
|
||||||
#define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \
|
#define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||||
wncontrols, wevent, wflags) \
|
wncontrols, wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_out_drv, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
|
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
||||||
.event = wevent, .event_flags = wflags}
|
.event = wevent, .event_flags = wflags}
|
||||||
#define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \
|
#define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||||
wncontrols, wevent, wflags) \
|
wncontrols, wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
|
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
||||||
.event = wevent, .event_flags = wflags}
|
.event = wevent, .event_flags = wflags}
|
||||||
#define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \
|
#define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \
|
||||||
wcontrols, wncontrols, wevent, wflags) \
|
wcontrols, wncontrols, wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
|
.kcontrol_news = wcontrols, \
|
||||||
.num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags}
|
.num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags}
|
||||||
#define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \
|
#define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||||
wevent, wflags) \
|
wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_switch, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
|
.kcontrol_news = wcontrols, .num_kcontrols = 1, \
|
||||||
.event = wevent, .event_flags = wflags}
|
.event = wevent, .event_flags = wflags}
|
||||||
#define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
|
#define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||||
wevent, wflags) \
|
wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_mux, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
|
.kcontrol_news = wcontrols, .num_kcontrols = 1, \
|
||||||
.event = wevent, .event_flags = wflags}
|
.event = wevent, .event_flags = wflags}
|
||||||
#define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
|
#define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||||
wevent, wflags) \
|
wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_virt_mux, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_virt_mux, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
|
.kcontrol_news = wcontrols, .num_kcontrols = 1, \
|
||||||
.event = wevent, .event_flags = wflags}
|
.event = wevent, .event_flags = wflags}
|
||||||
|
|
||||||
/* additional sequencing control within an event type */
|
/* additional sequencing control within an event type */
|
||||||
#define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \
|
#define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \
|
||||||
wevent, wflags) \
|
wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||||
.invert = winvert, .event = wevent, .event_flags = wflags, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
|
.event = wevent, .event_flags = wflags, \
|
||||||
.subseq = wsubseq}
|
.subseq = wsubseq}
|
||||||
#define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \
|
#define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \
|
||||||
wflags) \
|
wflags) \
|
||||||
{ .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \
|
{ .id = snd_soc_dapm_supply, .name = wname, \
|
||||||
.shift = wshift, .invert = winvert, .event = wevent, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
.event_flags = wflags, .subseq = wsubseq}
|
.event = wevent, .event_flags = wflags, .subseq = wsubseq}
|
||||||
|
|
||||||
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
|
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
|
||||||
#define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
|
#define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
|
||||||
wevent, wflags) \
|
wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
|
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
|
||||||
.event = wevent, .event_flags = wflags}
|
.event = wevent, .event_flags = wflags}
|
||||||
#define SOC_MIXER_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
|
#define SOC_MIXER_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
|
||||||
wevent, wflags) \
|
wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
|
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
|
||||||
.event = wevent, .event_flags = wflags}
|
.event = wevent, .event_flags = wflags}
|
||||||
#define SOC_MIXER_NAMED_CTL_E_ARRAY(wname, wreg, wshift, winvert, \
|
#define SOC_MIXER_NAMED_CTL_E_ARRAY(wname, wreg, wshift, winvert, \
|
||||||
wcontrols, wevent, wflags) \
|
wcontrols, wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
|
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||||
.invert = winvert, .kcontrol_news = wcontrols, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
.num_kcontrols = ARRAY_SIZE(wcontrols), .event = wevent, .event_flags = wflags}
|
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
|
||||||
|
.event = wevent, .event_flags = wflags}
|
||||||
|
|
||||||
/* events that are pre and post DAPM */
|
/* events that are pre and post DAPM */
|
||||||
#define SND_SOC_DAPM_PRE(wname, wevent) \
|
#define SND_SOC_DAPM_PRE(wname, wevent) \
|
||||||
|
@ -199,35 +222,36 @@ struct device;
|
||||||
/* stream domain */
|
/* stream domain */
|
||||||
#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \
|
#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \
|
||||||
{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
|
{ .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, \
|
#define SND_SOC_DAPM_AIF_IN_E(wname, stname, wslot, wreg, wshift, winvert, \
|
||||||
wevent, wflags) \
|
wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
|
{ .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 }
|
.event = wevent, .event_flags = wflags }
|
||||||
#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \
|
#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \
|
||||||
{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
|
{ .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, \
|
#define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wslot, wreg, wshift, winvert, \
|
||||||
wevent, wflags) \
|
wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
|
{ .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 }
|
.event = wevent, .event_flags = wflags }
|
||||||
#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
|
#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
|
||||||
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \
|
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
|
||||||
.shift = wshift, .invert = winvert}
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) }
|
||||||
#define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \
|
#define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \
|
||||||
wevent, wflags) \
|
wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \
|
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
|
||||||
.shift = wshift, .invert = winvert, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
.event = wevent, .event_flags = wflags}
|
.event = wevent, .event_flags = wflags}
|
||||||
|
|
||||||
#define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \
|
#define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \
|
||||||
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
|
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
|
||||||
.shift = wshift, .invert = winvert}
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
|
||||||
#define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \
|
#define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \
|
||||||
wevent, wflags) \
|
wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
|
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
|
||||||
.shift = wshift, .invert = winvert, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
.event = wevent, .event_flags = wflags}
|
.event = wevent, .event_flags = wflags}
|
||||||
#define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \
|
#define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \
|
||||||
{ .id = snd_soc_dapm_clock_supply, .name = 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, \
|
.on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \
|
||||||
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
|
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
|
||||||
#define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \
|
#define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \
|
||||||
{ .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \
|
{ .id = snd_soc_dapm_supply, .name = wname, \
|
||||||
.shift = wshift, .invert = winvert, .event = wevent, \
|
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||||
.event_flags = wflags}
|
.event = wevent, .event_flags = wflags}
|
||||||
#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \
|
#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \
|
||||||
{ .id = snd_soc_dapm_regulator_supply, .name = wname, \
|
{ .id = snd_soc_dapm_regulator_supply, .name = wname, \
|
||||||
.reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \
|
.reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \
|
||||||
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \
|
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \
|
||||||
.invert = wflags}
|
.on_val = wflags}
|
||||||
|
|
||||||
|
|
||||||
/* dapm kcontrol types */
|
/* dapm kcontrol types */
|
||||||
|
@ -256,14 +280,26 @@ struct device;
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||||
.info = snd_soc_info_volsw, \
|
.info = snd_soc_info_volsw, \
|
||||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_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) \
|
#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||||
.info = snd_soc_info_volsw, \
|
.info = snd_soc_info_volsw, \
|
||||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||||
.tlv.p = (tlv_array), \
|
.tlv.p = (tlv_array), \
|
||||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_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_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) \
|
#define SOC_DAPM_ENUM(xname, xenum) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||||
.info = snd_soc_info_enum_double, \
|
.info = snd_soc_info_enum_double, \
|
||||||
|
@ -333,6 +369,7 @@ struct snd_soc_dapm_route;
|
||||||
struct snd_soc_dapm_context;
|
struct snd_soc_dapm_context;
|
||||||
struct regulator;
|
struct regulator;
|
||||||
struct snd_soc_dapm_widget_list;
|
struct snd_soc_dapm_widget_list;
|
||||||
|
struct snd_soc_dapm_update;
|
||||||
|
|
||||||
int dapm_reg_event(struct snd_soc_dapm_widget *w,
|
int dapm_reg_event(struct snd_soc_dapm_widget *w,
|
||||||
struct snd_kcontrol *kcontrol, int event);
|
struct snd_kcontrol *kcontrol, int event);
|
||||||
|
@ -376,7 +413,7 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
|
||||||
struct snd_soc_dapm_widget *sink);
|
struct snd_soc_dapm_widget *sink);
|
||||||
|
|
||||||
/* dapm path setup */
|
/* dapm path setup */
|
||||||
int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm);
|
int snd_soc_dapm_new_widgets(struct snd_soc_card *card);
|
||||||
void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm);
|
void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm);
|
||||||
int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
|
int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
|
||||||
const struct snd_soc_dapm_route *route, int num);
|
const struct snd_soc_dapm_route *route, int num);
|
||||||
|
@ -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);
|
void snd_soc_dapm_shutdown(struct snd_soc_card *card);
|
||||||
|
|
||||||
/* external DAPM widget events */
|
/* external DAPM widget events */
|
||||||
int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
|
int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
|
||||||
struct snd_kcontrol *kcontrol, int connect);
|
struct snd_kcontrol *kcontrol, int connect,
|
||||||
int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
|
struct snd_soc_dapm_update *update);
|
||||||
struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e);
|
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 */
|
/* dapm sys fs - used by the core */
|
||||||
int snd_soc_dapm_sys_add(struct device *dev);
|
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,
|
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_dapm_widget_list **list);
|
||||||
|
|
||||||
|
struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol);
|
||||||
|
|
||||||
/* dapm widget types */
|
/* dapm widget types */
|
||||||
enum snd_soc_dapm_type {
|
enum snd_soc_dapm_type {
|
||||||
snd_soc_dapm_input = 0, /* input pin */
|
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_in, /* link to DAI structure */
|
||||||
snd_soc_dapm_dai_out,
|
snd_soc_dapm_dai_out,
|
||||||
snd_soc_dapm_dai_link, /* link between two DAI structures */
|
snd_soc_dapm_dai_link, /* link between two DAI structures */
|
||||||
|
snd_soc_dapm_kcontrol, /* Auto-disabled kcontrol */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum snd_soc_dapm_subclass {
|
enum snd_soc_dapm_subclass {
|
||||||
|
@ -485,7 +527,6 @@ struct snd_soc_dapm_path {
|
||||||
/* source (input) and sink (output) widgets */
|
/* source (input) and sink (output) widgets */
|
||||||
struct snd_soc_dapm_widget *source;
|
struct snd_soc_dapm_widget *source;
|
||||||
struct snd_soc_dapm_widget *sink;
|
struct snd_soc_dapm_widget *sink;
|
||||||
struct snd_kcontrol *kcontrol;
|
|
||||||
|
|
||||||
/* status */
|
/* status */
|
||||||
u32 connect:1; /* source and sink widgets are connected */
|
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_source;
|
||||||
struct list_head list_sink;
|
struct list_head list_sink;
|
||||||
|
struct list_head list_kcontrol;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -518,12 +560,10 @@ struct snd_soc_dapm_widget {
|
||||||
/* dapm control */
|
/* dapm control */
|
||||||
int reg; /* negative reg = no direct dapm */
|
int reg; /* negative reg = no direct dapm */
|
||||||
unsigned char shift; /* bits to shift */
|
unsigned char shift; /* bits to shift */
|
||||||
unsigned int value; /* widget current value */
|
|
||||||
unsigned int mask; /* non-shifted mask */
|
unsigned int mask; /* non-shifted mask */
|
||||||
unsigned int on_val; /* on state value */
|
unsigned int on_val; /* on state value */
|
||||||
unsigned int off_val; /* off state value */
|
unsigned int off_val; /* off state value */
|
||||||
unsigned char power:1; /* block power status */
|
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 active:1; /* active stream on DAC, ADC's */
|
||||||
unsigned char connected:1; /* connected codec pin */
|
unsigned char connected:1; /* connected codec pin */
|
||||||
unsigned char new:1; /* cnew complete */
|
unsigned char new:1; /* cnew complete */
|
||||||
|
@ -559,7 +599,6 @@ struct snd_soc_dapm_widget {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct snd_soc_dapm_update {
|
struct snd_soc_dapm_update {
|
||||||
struct snd_soc_dapm_widget *widget;
|
|
||||||
struct snd_kcontrol *kcontrol;
|
struct snd_kcontrol *kcontrol;
|
||||||
int reg;
|
int reg;
|
||||||
int mask;
|
int mask;
|
||||||
|
@ -573,8 +612,6 @@ struct snd_soc_dapm_context {
|
||||||
struct delayed_work delayed_work;
|
struct delayed_work delayed_work;
|
||||||
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
|
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 *,
|
void (*seq_notifier)(struct snd_soc_dapm_context *,
|
||||||
enum snd_soc_dapm_type, int);
|
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 */
|
/* internal use only */
|
||||||
int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
|
int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
|
||||||
int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
|
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
|
#endif
|
||||||
|
|
|
@ -30,13 +30,13 @@
|
||||||
/*
|
/*
|
||||||
* Convenience kcontrol builders
|
* 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) \
|
((unsigned long)&(struct soc_mixer_control) \
|
||||||
{.reg = xreg, .rreg = xreg, .shift = shift_left, \
|
{.reg = xreg, .rreg = xreg, .shift = shift_left, \
|
||||||
.rshift = shift_right, .max = xmax, .platform_max = xmax, \
|
.rshift = shift_right, .max = xmax, .platform_max = xmax, \
|
||||||
.invert = xinvert})
|
.invert = xinvert, .autodisable = xautodisable})
|
||||||
#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
|
#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \
|
||||||
SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert)
|
SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable)
|
||||||
#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
|
#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
|
||||||
((unsigned long)&(struct soc_mixer_control) \
|
((unsigned long)&(struct soc_mixer_control) \
|
||||||
{.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert})
|
{.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert})
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
|
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
|
||||||
.put = snd_soc_put_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) \
|
#define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||||
.info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \
|
.info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \
|
||||||
|
@ -68,7 +68,7 @@
|
||||||
.tlv.p = (tlv_array), \
|
.tlv.p = (tlv_array), \
|
||||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
|
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
|
||||||
.put = snd_soc_put_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) \
|
#define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
|
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
||||||
.put = snd_soc_put_volsw, \
|
.put = snd_soc_put_volsw, \
|
||||||
.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
|
.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) \
|
#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||||
.info = snd_soc_info_volsw, \
|
.info = snd_soc_info_volsw, \
|
||||||
|
@ -119,7 +119,7 @@
|
||||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
||||||
.put = snd_soc_put_volsw, \
|
.put = snd_soc_put_volsw, \
|
||||||
.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
|
.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) \
|
#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||||
|
@ -190,14 +190,14 @@
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||||
.info = snd_soc_info_volsw, \
|
.info = snd_soc_info_volsw, \
|
||||||
.get = xhandler_get, .put = xhandler_put, \
|
.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,\
|
#define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\
|
||||||
xhandler_get, xhandler_put) \
|
xhandler_get, xhandler_put) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||||
.info = snd_soc_info_volsw, \
|
.info = snd_soc_info_volsw, \
|
||||||
.get = xhandler_get, .put = xhandler_put, \
|
.get = xhandler_get, .put = xhandler_put, \
|
||||||
.private_value = \
|
.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,\
|
#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
|
||||||
xhandler_get, xhandler_put, tlv_array) \
|
xhandler_get, xhandler_put, tlv_array) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||||
|
@ -206,7 +206,7 @@
|
||||||
.tlv.p = (tlv_array), \
|
.tlv.p = (tlv_array), \
|
||||||
.info = snd_soc_info_volsw, \
|
.info = snd_soc_info_volsw, \
|
||||||
.get = xhandler_get, .put = xhandler_put, \
|
.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,\
|
#define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\
|
||||||
xhandler_get, xhandler_put, tlv_array) \
|
xhandler_get, xhandler_put, tlv_array) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||||
|
@ -216,7 +216,7 @@
|
||||||
.info = snd_soc_info_volsw, \
|
.info = snd_soc_info_volsw, \
|
||||||
.get = xhandler_get, .put = xhandler_put, \
|
.get = xhandler_get, .put = xhandler_put, \
|
||||||
.private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \
|
.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,\
|
#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
|
||||||
xhandler_get, xhandler_put, tlv_array) \
|
xhandler_get, xhandler_put, tlv_array) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||||
|
@ -234,7 +234,7 @@
|
||||||
.private_value = xdata }
|
.private_value = xdata }
|
||||||
#define SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
|
#define SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
{ .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, \
|
.get = xhandler_get, .put = xhandler_put, \
|
||||||
.private_value = (unsigned long)&xenum }
|
.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);
|
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(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
|
*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,
|
struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
|
||||||
void *data, const char *long_name,
|
void *data, const char *long_name,
|
||||||
const char *prefix);
|
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,
|
int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
|
||||||
const struct snd_kcontrol_new *controls, int num_controls);
|
const struct snd_kcontrol_new *controls, int num_controls);
|
||||||
int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
|
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);
|
const struct snd_kcontrol_new *controls, int num_controls);
|
||||||
int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
|
int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_info *uinfo);
|
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,
|
int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_value *ucontrol);
|
struct snd_ctl_elem_value *ucontrol);
|
||||||
int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
|
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);
|
struct snd_ctl_elem_value *ucontrol);
|
||||||
int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
|
int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_info *uinfo);
|
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
|
#define snd_soc_info_bool_ext snd_ctl_boolean_mono_info
|
||||||
int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
|
int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_value *ucontrol);
|
struct snd_ctl_elem_value *ucontrol);
|
||||||
|
@ -697,7 +697,6 @@ struct snd_soc_codec {
|
||||||
unsigned int probed:1; /* Codec has been probed */
|
unsigned int probed:1; /* Codec has been probed */
|
||||||
unsigned int ac97_registered:1; /* Codec has been AC97 registered */
|
unsigned int ac97_registered:1; /* Codec has been AC97 registered */
|
||||||
unsigned int ac97_created:1; /* Codec has been created by SoC */
|
unsigned int ac97_created:1; /* Codec has been created by SoC */
|
||||||
unsigned int sysfs_registered:1; /* codec has been sysfs registered */
|
|
||||||
unsigned int cache_init:1; /* codec cache has been initialized */
|
unsigned int cache_init:1; /* codec cache has been initialized */
|
||||||
unsigned int using_regmap:1; /* using regmap access */
|
unsigned int using_regmap:1; /* using regmap access */
|
||||||
u32 cache_only; /* Suppress writes to hardware */
|
u32 cache_only; /* Suppress writes to hardware */
|
||||||
|
@ -705,7 +704,6 @@ struct snd_soc_codec {
|
||||||
|
|
||||||
/* codec IO */
|
/* codec IO */
|
||||||
void *control_data; /* codec control (i2c/3wire) data */
|
void *control_data; /* codec control (i2c/3wire) data */
|
||||||
enum snd_soc_control_type control_type;
|
|
||||||
hw_write_t hw_write;
|
hw_write_t hw_write;
|
||||||
unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int);
|
unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int);
|
||||||
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
|
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
|
||||||
|
@ -724,7 +722,6 @@ struct snd_soc_codec {
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
struct dentry *debugfs_codec_root;
|
struct dentry *debugfs_codec_root;
|
||||||
struct dentry *debugfs_reg;
|
struct dentry *debugfs_reg;
|
||||||
struct dentry *debugfs_dapm;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -849,7 +846,6 @@ struct snd_soc_platform {
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
struct dentry *debugfs_platform_root;
|
struct dentry *debugfs_platform_root;
|
||||||
struct dentry *debugfs_dapm;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -934,6 +930,10 @@ struct snd_soc_dai_link {
|
||||||
/* machine stream operations */
|
/* machine stream operations */
|
||||||
const struct snd_soc_ops *ops;
|
const struct snd_soc_ops *ops;
|
||||||
const struct snd_soc_compr_ops *compr_ops;
|
const struct snd_soc_compr_ops *compr_ops;
|
||||||
|
|
||||||
|
/* For unidirectional dai links */
|
||||||
|
bool playback_only;
|
||||||
|
bool capture_only;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct snd_soc_codec_conf {
|
struct snd_soc_codec_conf {
|
||||||
|
@ -1042,6 +1042,7 @@ struct snd_soc_card {
|
||||||
/* Generic DAPM context for the card */
|
/* Generic DAPM context for the card */
|
||||||
struct snd_soc_dapm_context dapm;
|
struct snd_soc_dapm_context dapm;
|
||||||
struct snd_soc_dapm_stats dapm_stats;
|
struct snd_soc_dapm_stats dapm_stats;
|
||||||
|
struct snd_soc_dapm_update *update;
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
struct dentry *debugfs_card_root;
|
struct dentry *debugfs_card_root;
|
||||||
|
@ -1087,7 +1088,9 @@ struct snd_soc_pcm_runtime {
|
||||||
/* mixer control */
|
/* mixer control */
|
||||||
struct soc_mixer_control {
|
struct soc_mixer_control {
|
||||||
int min, max, platform_max;
|
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 {
|
struct soc_bytes {
|
||||||
|
|
|
@ -111,7 +111,7 @@ struct hdspm_ltc {
|
||||||
enum hdspm_ltc_input_format input_format;
|
enum hdspm_ltc_input_format input_format;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SNDRV_HDSPM_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspm_mixer_ioctl)
|
#define SNDRV_HDSPM_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspm_ltc)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The status data reflects the device's current state
|
* The status data reflects the device's current state
|
||||||
|
|
|
@ -14,12 +14,14 @@
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/dmaengine.h>
|
||||||
|
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/pcm.h>
|
#include <sound/pcm.h>
|
||||||
#include <sound/ac97_codec.h>
|
#include <sound/ac97_codec.h>
|
||||||
#include <sound/initval.h>
|
#include <sound/initval.h>
|
||||||
#include <sound/pxa2xx-lib.h>
|
#include <sound/pxa2xx-lib.h>
|
||||||
|
#include <sound/dmaengine_pcm.h>
|
||||||
|
|
||||||
#include <mach/regs-ac97.h>
|
#include <mach/regs-ac97.h>
|
||||||
#include <mach/audio.h>
|
#include <mach/audio.h>
|
||||||
|
@ -41,20 +43,20 @@ static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
|
||||||
.reset = pxa2xx_ac97_reset,
|
.reset = pxa2xx_ac97_reset,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_out = {
|
static unsigned long pxa2xx_ac97_pcm_out_req = 12;
|
||||||
.name = "AC97 PCM out",
|
static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_out = {
|
||||||
.dev_addr = __PREG(PCDR),
|
.addr = __PREG(PCDR),
|
||||||
.drcmr = &DRCMR(12),
|
.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
|
||||||
.dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
|
.maxburst = 32,
|
||||||
DCMD_BURST32 | DCMD_WIDTH4,
|
.filter_data = &pxa2xx_ac97_pcm_out_req,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_in = {
|
static unsigned long pxa2xx_ac97_pcm_in_req = 11;
|
||||||
.name = "AC97 PCM in",
|
static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_in = {
|
||||||
.dev_addr = __PREG(PCDR),
|
.addr = __PREG(PCDR),
|
||||||
.drcmr = &DRCMR(11),
|
.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
|
||||||
.dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
|
.maxburst = 32,
|
||||||
DCMD_BURST32 | DCMD_WIDTH4,
|
.filter_data = &pxa2xx_ac97_pcm_in_req,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_pcm *pxa2xx_ac97_pcm;
|
static struct snd_pcm *pxa2xx_ac97_pcm;
|
||||||
|
|
|
@ -7,11 +7,13 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/dmaengine.h>
|
||||||
|
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/pcm.h>
|
#include <sound/pcm.h>
|
||||||
#include <sound/pcm_params.h>
|
#include <sound/pcm_params.h>
|
||||||
#include <sound/pxa2xx-lib.h>
|
#include <sound/pxa2xx-lib.h>
|
||||||
|
#include <sound/dmaengine_pcm.h>
|
||||||
|
|
||||||
#include <mach/dma.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);
|
size_t period = params_period_bytes(params);
|
||||||
pxa_dma_desc *dma_desc;
|
pxa_dma_desc *dma_desc;
|
||||||
dma_addr_t dma_buff_phys, next_desc_phys;
|
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);
|
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
|
||||||
runtime->dma_bytes = totsize;
|
runtime->dma_bytes = totsize;
|
||||||
|
@ -55,14 +86,14 @@ int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||||
dma_desc->ddadr = next_desc_phys;
|
dma_desc->ddadr = next_desc_phys;
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
dma_desc->dsadr = dma_buff_phys;
|
dma_desc->dsadr = dma_buff_phys;
|
||||||
dma_desc->dtadr = rtd->params->dev_addr;
|
dma_desc->dtadr = rtd->params->addr;
|
||||||
} else {
|
} else {
|
||||||
dma_desc->dsadr = rtd->params->dev_addr;
|
dma_desc->dsadr = rtd->params->addr;
|
||||||
dma_desc->dtadr = dma_buff_phys;
|
dma_desc->dtadr = dma_buff_phys;
|
||||||
}
|
}
|
||||||
if (period > totsize)
|
if (period > totsize)
|
||||||
period = totsize;
|
period = totsize;
|
||||||
dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN;
|
dma_desc->dcmd = dcmd | period | DCMD_ENDIRQEN;
|
||||||
dma_desc++;
|
dma_desc++;
|
||||||
dma_buff_phys += period;
|
dma_buff_phys += period;
|
||||||
} while (totsize -= 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;
|
struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
|
||||||
|
|
||||||
if (rtd && rtd->params && rtd->params->drcmr)
|
if (rtd && rtd->params && rtd->params->filter_data) {
|
||||||
*rtd->params->drcmr = 0;
|
unsigned long req = *(unsigned long *) rtd->params->filter_data;
|
||||||
|
DRCMR(req) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
snd_pcm_set_runtime_buffer(substream, NULL);
|
snd_pcm_set_runtime_buffer(substream, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -136,6 +169,7 @@ EXPORT_SYMBOL(pxa2xx_pcm_pointer);
|
||||||
int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
|
int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
|
struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
|
||||||
|
unsigned long req;
|
||||||
|
|
||||||
if (!prtd || !prtd->params)
|
if (!prtd || !prtd->params)
|
||||||
return 0;
|
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) &= ~DCSR_RUN;
|
||||||
DCSR(prtd->dma_ch) = 0;
|
DCSR(prtd->dma_ch) = 0;
|
||||||
DCMD(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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -155,7 +190,6 @@ EXPORT_SYMBOL(__pxa2xx_pcm_prepare);
|
||||||
void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
|
void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
|
||||||
{
|
{
|
||||||
struct snd_pcm_substream *substream = dev_id;
|
struct snd_pcm_substream *substream = dev_id;
|
||||||
struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
|
|
||||||
int dcsr;
|
int dcsr;
|
||||||
|
|
||||||
dcsr = DCSR(dma_ch);
|
dcsr = DCSR(dma_ch);
|
||||||
|
@ -164,8 +198,8 @@ void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
|
||||||
if (dcsr & DCSR_ENDINTR) {
|
if (dcsr & DCSR_ENDINTR) {
|
||||||
snd_pcm_period_elapsed(substream);
|
snd_pcm_period_elapsed(substream);
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
|
printk(KERN_ERR "DMA error on channel %d (DCSR=%#x)\n",
|
||||||
rtd->params->name, dma_ch, dcsr);
|
dma_ch, dcsr);
|
||||||
snd_pcm_stream_lock(substream);
|
snd_pcm_stream_lock(substream);
|
||||||
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
|
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
|
||||||
snd_pcm_stream_unlock(substream);
|
snd_pcm_stream_unlock(substream);
|
||||||
|
|
|
@ -11,8 +11,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/dmaengine.h>
|
||||||
|
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/pxa2xx-lib.h>
|
#include <sound/pxa2xx-lib.h>
|
||||||
|
#include <sound/dmaengine_pcm.h>
|
||||||
|
|
||||||
#include "pxa2xx-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) ?
|
rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
|
||||||
client->playback_params : client->capture_params;
|
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);
|
pxa2xx_pcm_dma_irq, substream);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err2;
|
goto err2;
|
||||||
|
|
|
@ -13,14 +13,14 @@
|
||||||
|
|
||||||
struct pxa2xx_runtime_data {
|
struct pxa2xx_runtime_data {
|
||||||
int dma_ch;
|
int dma_ch;
|
||||||
struct pxa2xx_pcm_dma_params *params;
|
struct snd_dmaengine_dai_dma_data *params;
|
||||||
pxa_dma_desc *dma_desc_array;
|
pxa_dma_desc *dma_desc_array;
|
||||||
dma_addr_t dma_desc_array_phys;
|
dma_addr_t dma_desc_array_phys;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pxa2xx_pcm_client {
|
struct pxa2xx_pcm_client {
|
||||||
struct pxa2xx_pcm_dma_params *playback_params;
|
struct snd_dmaengine_dai_dma_data *playback_params;
|
||||||
struct pxa2xx_pcm_dma_params *capture_params;
|
struct snd_dmaengine_dai_dma_data *capture_params;
|
||||||
int (*startup)(struct snd_pcm_substream *);
|
int (*startup)(struct snd_pcm_substream *);
|
||||||
void (*shutdown)(struct snd_pcm_substream *);
|
void (*shutdown)(struct snd_pcm_substream *);
|
||||||
int (*prepare)(struct snd_pcm_substream *);
|
int (*prepare)(struct snd_pcm_substream *);
|
||||||
|
|
|
@ -6,6 +6,9 @@ config SND_PCM
|
||||||
tristate
|
tristate
|
||||||
select SND_TIMER
|
select SND_TIMER
|
||||||
|
|
||||||
|
config SND_DMAENGINE_PCM
|
||||||
|
tristate
|
||||||
|
|
||||||
config SND_HWDEP
|
config SND_HWDEP
|
||||||
tristate
|
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 \
|
snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
|
||||||
pcm_memory.o
|
pcm_memory.o
|
||||||
|
|
||||||
|
snd-pcm-dmaengine-objs := pcm_dmaengine.o
|
||||||
|
|
||||||
snd-page-alloc-y := memalloc.o
|
snd-page-alloc-y := memalloc.o
|
||||||
snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.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_HRTIMER) += snd-hrtimer.o
|
||||||
obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o
|
obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o
|
||||||
obj-$(CONFIG_SND_PCM) += snd-pcm.o snd-page-alloc.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_RAWMIDI) += snd-rawmidi.o
|
||||||
|
|
||||||
obj-$(CONFIG_SND_OSSEMUL) += oss/
|
obj-$(CONFIG_SND_OSSEMUL) += oss/
|
||||||
|
|
|
@ -184,7 +184,7 @@ static void xrun(struct snd_pcm_substream *substream)
|
||||||
do { \
|
do { \
|
||||||
if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { \
|
if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { \
|
||||||
xrun_log_show(substream); \
|
xrun_log_show(substream); \
|
||||||
if (printk_ratelimit()) { \
|
if (snd_printd_ratelimit()) { \
|
||||||
snd_printd("PCM: " fmt, ##args); \
|
snd_printd("PCM: " fmt, ##args); \
|
||||||
} \
|
} \
|
||||||
dump_stack_on_xrun(substream); \
|
dump_stack_on_xrun(substream); \
|
||||||
|
@ -342,7 +342,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
}
|
}
|
||||||
if (pos >= runtime->buffer_size) {
|
if (pos >= runtime->buffer_size) {
|
||||||
if (printk_ratelimit()) {
|
if (snd_printd_ratelimit()) {
|
||||||
char name[16];
|
char name[16];
|
||||||
snd_pcm_debug_name(substream, name, sizeof(name));
|
snd_pcm_debug_name(substream, name, sizeof(name));
|
||||||
xrun_log_show(substream);
|
xrun_log_show(substream);
|
||||||
|
|
|
@ -1022,7 +1022,7 @@ static void dummy_proc_write(struct snd_info_entry *entry,
|
||||||
if (i >= ARRAY_SIZE(fields))
|
if (i >= ARRAY_SIZE(fields))
|
||||||
continue;
|
continue;
|
||||||
snd_info_get_str(item, ptr, sizeof(item));
|
snd_info_get_str(item, ptr, sizeof(item));
|
||||||
if (strict_strtoull(item, 0, &val))
|
if (kstrtoull(item, 0, &val))
|
||||||
continue;
|
continue;
|
||||||
if (fields[i].size == sizeof(int))
|
if (fields[i].size == sizeof(int))
|
||||||
*get_dummy_int_ptr(dummy, fields[i].offset) = val;
|
*get_dummy_int_ptr(dummy, fields[i].offset) = val;
|
||||||
|
|
|
@ -49,7 +49,6 @@ struct fwspk {
|
||||||
struct snd_card *card;
|
struct snd_card *card;
|
||||||
struct fw_unit *unit;
|
struct fw_unit *unit;
|
||||||
const struct device_info *device_info;
|
const struct device_info *device_info;
|
||||||
struct snd_pcm_substream *pcm;
|
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
struct cmp_connection connection;
|
struct cmp_connection connection;
|
||||||
struct amdtp_out_stream stream;
|
struct amdtp_out_stream stream;
|
||||||
|
@ -363,8 +362,7 @@ static int fwspk_create_pcm(struct fwspk *fwspk)
|
||||||
return err;
|
return err;
|
||||||
pcm->private_data = fwspk;
|
pcm->private_data = fwspk;
|
||||||
strcpy(pcm->name, fwspk->device_info->short_name);
|
strcpy(pcm->name, fwspk->device_info->short_name);
|
||||||
fwspk->pcm = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
|
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ops);
|
||||||
fwspk->pcm->ops = &ops;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -443,8 +443,7 @@ static void snd_interwave_detect_memory(struct snd_gus_card *gus)
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
iwave[i] = snd_gf1_peek(gus, bank_pos + i);
|
iwave[i] = snd_gf1_peek(gus, bank_pos + i);
|
||||||
#ifdef CONFIG_SND_DEBUG_ROM
|
#ifdef CONFIG_SND_DEBUG_ROM
|
||||||
printk(KERN_DEBUG "ROM at 0x%06x = %*phC\n", bank_pos,
|
printk(KERN_DEBUG "ROM at 0x%06x = %8phC\n", bank_pos, iwave);
|
||||||
8, iwave);
|
|
||||||
#endif
|
#endif
|
||||||
if (strncmp(iwave, "INTRWAVE", 8))
|
if (strncmp(iwave, "INTRWAVE", 8))
|
||||||
continue; /* first check */
|
continue; /* first check */
|
||||||
|
|
|
@ -557,7 +557,6 @@ int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int err = 0, n = 0;
|
int err = 0, n = 0;
|
||||||
struct dma_buffparms *dmap = adev->dmap_in;
|
struct dma_buffparms *dmap = adev->dmap_in;
|
||||||
int go;
|
|
||||||
|
|
||||||
if (!(adev->open_mode & OPEN_READ))
|
if (!(adev->open_mode & OPEN_READ))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
@ -584,7 +583,7 @@ int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock)
|
||||||
spin_unlock_irqrestore(&dmap->lock,flags);
|
spin_unlock_irqrestore(&dmap->lock,flags);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
if ((go = adev->go))
|
if (adev->go)
|
||||||
timeout = dmabuf_timeout(dmap);
|
timeout = dmabuf_timeout(dmap);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&dmap->lock,flags);
|
spin_unlock_irqrestore(&dmap->lock,flags);
|
||||||
|
|
|
@ -152,14 +152,9 @@ config SND_HDA_CODEC_HDMI
|
||||||
This module is automatically loaded at probing.
|
This module is automatically loaded at probing.
|
||||||
|
|
||||||
config SND_HDA_I915
|
config SND_HDA_I915
|
||||||
bool "Build Display HD-audio controller/codec power well support for i915 cards"
|
bool
|
||||||
|
default y
|
||||||
depends on DRM_I915
|
depends on DRM_I915
|
||||||
help
|
|
||||||
Say Y here to include full HDMI and DisplayPort HD-audio controller/codec
|
|
||||||
power-well support for Intel Haswell graphics cards based on the i915 driver.
|
|
||||||
|
|
||||||
Note that this option must be enabled for Intel Haswell C+ stepping machines, otherwise
|
|
||||||
the GPU audio controller/codecs will not be initialized or damaged when exit from S3 mode.
|
|
||||||
|
|
||||||
config SND_HDA_CODEC_CIRRUS
|
config SND_HDA_CODEC_CIRRUS
|
||||||
bool "Build Cirrus Logic codec support"
|
bool "Build Cirrus Logic codec support"
|
||||||
|
|
|
@ -666,6 +666,64 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_HDA(snd_hda_get_conn_index);
|
EXPORT_SYMBOL_HDA(snd_hda_get_conn_index);
|
||||||
|
|
||||||
|
|
||||||
|
/* return DEVLIST_LEN parameter of the given widget */
|
||||||
|
static unsigned int get_num_devices(struct hda_codec *codec, hda_nid_t nid)
|
||||||
|
{
|
||||||
|
unsigned int wcaps = get_wcaps(codec, nid);
|
||||||
|
unsigned int parm;
|
||||||
|
|
||||||
|
if (!codec->dp_mst || !(wcaps & AC_WCAP_DIGITAL) ||
|
||||||
|
get_wcaps_type(wcaps) != AC_WID_PIN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
parm = snd_hda_param_read(codec, nid, AC_PAR_DEVLIST_LEN);
|
||||||
|
if (parm == -1 && codec->bus->rirb_error)
|
||||||
|
parm = 0;
|
||||||
|
return parm & AC_DEV_LIST_LEN_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* snd_hda_get_devices - copy device list without cache
|
||||||
|
* @codec: the HDA codec
|
||||||
|
* @nid: NID of the pin to parse
|
||||||
|
* @dev_list: device list array
|
||||||
|
* @max_devices: max. number of devices to store
|
||||||
|
*
|
||||||
|
* Copy the device list. This info is dynamic and so not cached.
|
||||||
|
* Currently called only from hda_proc.c, so not exported.
|
||||||
|
*/
|
||||||
|
int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
|
||||||
|
u8 *dev_list, int max_devices)
|
||||||
|
{
|
||||||
|
unsigned int parm;
|
||||||
|
int i, dev_len, devices;
|
||||||
|
|
||||||
|
parm = get_num_devices(codec, nid);
|
||||||
|
if (!parm) /* not multi-stream capable */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
dev_len = parm + 1;
|
||||||
|
dev_len = dev_len < max_devices ? dev_len : max_devices;
|
||||||
|
|
||||||
|
devices = 0;
|
||||||
|
while (devices < dev_len) {
|
||||||
|
parm = snd_hda_codec_read(codec, nid, 0,
|
||||||
|
AC_VERB_GET_DEVICE_LIST, devices);
|
||||||
|
if (parm == -1 && codec->bus->rirb_error)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
dev_list[devices] = (u8)parm;
|
||||||
|
parm >>= 4;
|
||||||
|
devices++;
|
||||||
|
if (devices >= dev_len)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_hda_queue_unsol_event - add an unsolicited event to queue
|
* snd_hda_queue_unsol_event - add an unsolicited event to queue
|
||||||
* @bus: the BUS
|
* @bus: the BUS
|
||||||
|
@ -1216,11 +1274,13 @@ static void hda_jackpoll_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct hda_codec *codec =
|
struct hda_codec *codec =
|
||||||
container_of(work, struct hda_codec, jackpoll_work.work);
|
container_of(work, struct hda_codec, jackpoll_work.work);
|
||||||
if (!codec->jackpoll_interval)
|
|
||||||
return;
|
|
||||||
|
|
||||||
snd_hda_jack_set_dirty_all(codec);
|
snd_hda_jack_set_dirty_all(codec);
|
||||||
snd_hda_jack_poll_all(codec);
|
snd_hda_jack_poll_all(codec);
|
||||||
|
|
||||||
|
if (!codec->jackpoll_interval)
|
||||||
|
return;
|
||||||
|
|
||||||
queue_delayed_work(codec->bus->workq, &codec->jackpoll_work,
|
queue_delayed_work(codec->bus->workq, &codec->jackpoll_work,
|
||||||
codec->jackpoll_interval);
|
codec->jackpoll_interval);
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,8 @@ enum {
|
||||||
#define AC_VERB_GET_HDMI_DIP_XMIT 0x0f32
|
#define AC_VERB_GET_HDMI_DIP_XMIT 0x0f32
|
||||||
#define AC_VERB_GET_HDMI_CP_CTRL 0x0f33
|
#define AC_VERB_GET_HDMI_CP_CTRL 0x0f33
|
||||||
#define AC_VERB_GET_HDMI_CHAN_SLOT 0x0f34
|
#define AC_VERB_GET_HDMI_CHAN_SLOT 0x0f34
|
||||||
|
#define AC_VERB_GET_DEVICE_SEL 0xf35
|
||||||
|
#define AC_VERB_GET_DEVICE_LIST 0xf36
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SET verbs
|
* SET verbs
|
||||||
|
@ -133,6 +135,7 @@ enum {
|
||||||
#define AC_VERB_SET_HDMI_DIP_XMIT 0x732
|
#define AC_VERB_SET_HDMI_DIP_XMIT 0x732
|
||||||
#define AC_VERB_SET_HDMI_CP_CTRL 0x733
|
#define AC_VERB_SET_HDMI_CP_CTRL 0x733
|
||||||
#define AC_VERB_SET_HDMI_CHAN_SLOT 0x734
|
#define AC_VERB_SET_HDMI_CHAN_SLOT 0x734
|
||||||
|
#define AC_VERB_SET_DEVICE_SEL 0x735
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parameter IDs
|
* Parameter IDs
|
||||||
|
@ -154,6 +157,7 @@ enum {
|
||||||
#define AC_PAR_GPIO_CAP 0x11
|
#define AC_PAR_GPIO_CAP 0x11
|
||||||
#define AC_PAR_AMP_OUT_CAP 0x12
|
#define AC_PAR_AMP_OUT_CAP 0x12
|
||||||
#define AC_PAR_VOL_KNB_CAP 0x13
|
#define AC_PAR_VOL_KNB_CAP 0x13
|
||||||
|
#define AC_PAR_DEVLIST_LEN 0x15
|
||||||
#define AC_PAR_HDMI_LPCM_CAP 0x20
|
#define AC_PAR_HDMI_LPCM_CAP 0x20
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -251,6 +255,11 @@ enum {
|
||||||
#define AC_UNSOL_RES_TAG_SHIFT 26
|
#define AC_UNSOL_RES_TAG_SHIFT 26
|
||||||
#define AC_UNSOL_RES_SUBTAG (0x1f<<21)
|
#define AC_UNSOL_RES_SUBTAG (0x1f<<21)
|
||||||
#define AC_UNSOL_RES_SUBTAG_SHIFT 21
|
#define AC_UNSOL_RES_SUBTAG_SHIFT 21
|
||||||
|
#define AC_UNSOL_RES_DE (0x3f<<15) /* Device Entry
|
||||||
|
* (for DP1.2 MST)
|
||||||
|
*/
|
||||||
|
#define AC_UNSOL_RES_DE_SHIFT 15
|
||||||
|
#define AC_UNSOL_RES_IA (1<<2) /* Inactive (for DP1.2 MST) */
|
||||||
#define AC_UNSOL_RES_ELDV (1<<1) /* ELD Data valid (for HDMI) */
|
#define AC_UNSOL_RES_ELDV (1<<1) /* ELD Data valid (for HDMI) */
|
||||||
#define AC_UNSOL_RES_PD (1<<0) /* pinsense detect */
|
#define AC_UNSOL_RES_PD (1<<0) /* pinsense detect */
|
||||||
#define AC_UNSOL_RES_CP_STATE (1<<1) /* content protection */
|
#define AC_UNSOL_RES_CP_STATE (1<<1) /* content protection */
|
||||||
|
@ -352,6 +361,10 @@ enum {
|
||||||
#define AC_LPCMCAP_44K (1<<30) /* 44.1kHz support */
|
#define AC_LPCMCAP_44K (1<<30) /* 44.1kHz support */
|
||||||
#define AC_LPCMCAP_44K_MS (1<<31) /* 44.1kHz-multiplies support */
|
#define AC_LPCMCAP_44K_MS (1<<31) /* 44.1kHz-multiplies support */
|
||||||
|
|
||||||
|
/* Display pin's device list length */
|
||||||
|
#define AC_DEV_LIST_LEN_MASK 0x3f
|
||||||
|
#define AC_MAX_DEV_LIST_LEN 64
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Control Parameters
|
* Control Parameters
|
||||||
*/
|
*/
|
||||||
|
@ -460,6 +473,11 @@ enum {
|
||||||
#define AC_DEFCFG_PORT_CONN (0x3<<30)
|
#define AC_DEFCFG_PORT_CONN (0x3<<30)
|
||||||
#define AC_DEFCFG_PORT_CONN_SHIFT 30
|
#define AC_DEFCFG_PORT_CONN_SHIFT 30
|
||||||
|
|
||||||
|
/* Display pin's device list entry */
|
||||||
|
#define AC_DE_PD (1<<0)
|
||||||
|
#define AC_DE_ELDV (1<<1)
|
||||||
|
#define AC_DE_IA (1<<2)
|
||||||
|
|
||||||
/* device device types (0x0-0xf) */
|
/* device device types (0x0-0xf) */
|
||||||
enum {
|
enum {
|
||||||
AC_JACK_LINE_OUT,
|
AC_JACK_LINE_OUT,
|
||||||
|
@ -885,6 +903,7 @@ struct hda_codec {
|
||||||
unsigned int pcm_format_first:1; /* PCM format must be set first */
|
unsigned int pcm_format_first:1; /* PCM format must be set first */
|
||||||
unsigned int epss:1; /* supporting EPSS? */
|
unsigned int epss:1; /* supporting EPSS? */
|
||||||
unsigned int cached_write:1; /* write only to caches */
|
unsigned int cached_write:1; /* write only to caches */
|
||||||
|
unsigned int dp_mst:1; /* support DP1.2 Multi-stream transport */
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
unsigned int power_on :1; /* current (global) power-state */
|
unsigned int power_on :1; /* current (global) power-state */
|
||||||
unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */
|
unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */
|
||||||
|
@ -972,6 +991,8 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums,
|
||||||
const hda_nid_t *list);
|
const hda_nid_t *list);
|
||||||
int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
|
int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
|
||||||
hda_nid_t nid, int recursive);
|
hda_nid_t nid, int recursive);
|
||||||
|
int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
|
||||||
|
u8 *dev_list, int max_devices);
|
||||||
int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
|
int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
|
||||||
u32 *ratesp, u64 *formatsp, unsigned int *bpsp);
|
u32 *ratesp, u64 *formatsp, unsigned int *bpsp);
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,9 @@ static void parse_user_hints(struct hda_codec *codec)
|
||||||
val = snd_hda_get_bool_hint(codec, "primary_hp");
|
val = snd_hda_get_bool_hint(codec, "primary_hp");
|
||||||
if (val >= 0)
|
if (val >= 0)
|
||||||
spec->no_primary_hp = !val;
|
spec->no_primary_hp = !val;
|
||||||
|
val = snd_hda_get_bool_hint(codec, "multi_io");
|
||||||
|
if (val >= 0)
|
||||||
|
spec->no_multi_io = !val;
|
||||||
val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
|
val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
|
||||||
if (val >= 0)
|
if (val >= 0)
|
||||||
spec->multi_cap_vol = !!val;
|
spec->multi_cap_vol = !!val;
|
||||||
|
@ -813,6 +816,8 @@ static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
|
||||||
|
|
||||||
static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
|
static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_value *ucontrol);
|
struct snd_ctl_elem_value *ucontrol);
|
||||||
|
static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
HDA_CTL_WIDGET_VOL,
|
HDA_CTL_WIDGET_VOL,
|
||||||
|
@ -830,7 +835,13 @@ static const struct snd_kcontrol_new control_templates[] = {
|
||||||
.put = hda_gen_mixer_mute_put, /* replaced */
|
.put = hda_gen_mixer_mute_put, /* replaced */
|
||||||
.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
|
.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
|
||||||
},
|
},
|
||||||
HDA_BIND_MUTE(NULL, 0, 0, 0),
|
{
|
||||||
|
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||||
|
.info = snd_hda_mixer_amp_switch_info,
|
||||||
|
.get = snd_hda_mixer_bind_switch_get,
|
||||||
|
.put = hda_gen_bind_mute_put, /* replaced */
|
||||||
|
.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* add dynamic controls from template */
|
/* add dynamic controls from template */
|
||||||
|
@ -937,8 +948,8 @@ static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* playback mute control with the software mute bit check */
|
/* playback mute control with the software mute bit check */
|
||||||
static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
|
static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_value *ucontrol)
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
struct hda_gen_spec *spec = codec->spec;
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
|
@ -949,10 +960,22 @@ static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
|
||||||
ucontrol->value.integer.value[0] &= enabled;
|
ucontrol->value.integer.value[0] &= enabled;
|
||||||
ucontrol->value.integer.value[1] &= enabled;
|
ucontrol->value.integer.value[1] &= enabled;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
sync_auto_mute_bits(kcontrol, ucontrol);
|
||||||
return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
|
return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
sync_auto_mute_bits(kcontrol, ucontrol);
|
||||||
|
return snd_hda_mixer_bind_switch_put(kcontrol, ucontrol);
|
||||||
|
}
|
||||||
|
|
||||||
/* any ctl assigned to the path with the given index? */
|
/* any ctl assigned to the path with the given index? */
|
||||||
static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
|
static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
|
||||||
{
|
{
|
||||||
|
@ -1541,7 +1564,8 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
|
||||||
cfg->speaker_pins,
|
cfg->speaker_pins,
|
||||||
spec->multiout.extra_out_nid,
|
spec->multiout.extra_out_nid,
|
||||||
spec->speaker_paths);
|
spec->speaker_paths);
|
||||||
if (fill_mio_first && cfg->line_outs == 1 &&
|
if (!spec->no_multi_io &&
|
||||||
|
fill_mio_first && cfg->line_outs == 1 &&
|
||||||
cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
||||||
err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
|
err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
|
||||||
if (!err)
|
if (!err)
|
||||||
|
@ -1554,7 +1578,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
|
||||||
spec->private_dac_nids, spec->out_paths,
|
spec->private_dac_nids, spec->out_paths,
|
||||||
spec->main_out_badness);
|
spec->main_out_badness);
|
||||||
|
|
||||||
if (fill_mio_first &&
|
if (!spec->no_multi_io && fill_mio_first &&
|
||||||
cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
||||||
/* try to fill multi-io first */
|
/* try to fill multi-io first */
|
||||||
err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
|
err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
|
||||||
|
@ -1582,7 +1606,8 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
|
||||||
return err;
|
return err;
|
||||||
badness += err;
|
badness += err;
|
||||||
}
|
}
|
||||||
if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
if (!spec->no_multi_io &&
|
||||||
|
cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
||||||
err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
|
err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
@ -1600,7 +1625,8 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
|
||||||
check_aamix_out_path(codec, spec->speaker_paths[0]);
|
check_aamix_out_path(codec, spec->speaker_paths[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
|
if (!spec->no_multi_io &&
|
||||||
|
cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
|
||||||
if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
|
if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
|
||||||
spec->multi_ios = 1; /* give badness */
|
spec->multi_ios = 1; /* give badness */
|
||||||
|
|
||||||
|
@ -3724,7 +3750,8 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
|
||||||
/* check each pin in the given array; returns true if any of them is plugged */
|
/* check each pin in the given array; returns true if any of them is plugged */
|
||||||
static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
|
static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
|
||||||
{
|
{
|
||||||
int i, present = 0;
|
int i;
|
||||||
|
bool present = false;
|
||||||
|
|
||||||
for (i = 0; i < num_pins; i++) {
|
for (i = 0; i < num_pins; i++) {
|
||||||
hda_nid_t nid = pins[i];
|
hda_nid_t nid = pins[i];
|
||||||
|
@ -3733,14 +3760,15 @@ static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
|
||||||
/* don't detect pins retasked as inputs */
|
/* don't detect pins retasked as inputs */
|
||||||
if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
|
if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
|
||||||
continue;
|
continue;
|
||||||
present |= snd_hda_jack_detect(codec, nid);
|
if (snd_hda_jack_detect_state(codec, nid) == HDA_JACK_PRESENT)
|
||||||
|
present = true;
|
||||||
}
|
}
|
||||||
return present;
|
return present;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* standard HP/line-out auto-mute helper */
|
/* standard HP/line-out auto-mute helper */
|
||||||
static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
|
static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
|
||||||
bool mute)
|
int *paths, bool mute)
|
||||||
{
|
{
|
||||||
struct hda_gen_spec *spec = codec->spec;
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
int i;
|
int i;
|
||||||
|
@ -3752,10 +3780,19 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (spec->auto_mute_via_amp) {
|
if (spec->auto_mute_via_amp) {
|
||||||
|
struct nid_path *path;
|
||||||
|
hda_nid_t mute_nid;
|
||||||
|
|
||||||
|
path = snd_hda_get_path_from_idx(codec, paths[i]);
|
||||||
|
if (!path)
|
||||||
|
continue;
|
||||||
|
mute_nid = get_amp_nid_(path->ctls[NID_PATH_MUTE_CTL]);
|
||||||
|
if (!mute_nid)
|
||||||
|
continue;
|
||||||
if (mute)
|
if (mute)
|
||||||
spec->mute_bits |= (1ULL << nid);
|
spec->mute_bits |= (1ULL << mute_nid);
|
||||||
else
|
else
|
||||||
spec->mute_bits &= ~(1ULL << nid);
|
spec->mute_bits &= ~(1ULL << mute_nid);
|
||||||
set_pin_eapd(codec, nid, !mute);
|
set_pin_eapd(codec, nid, !mute);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -3786,14 +3823,19 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
|
||||||
void snd_hda_gen_update_outputs(struct hda_codec *codec)
|
void snd_hda_gen_update_outputs(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
struct hda_gen_spec *spec = codec->spec;
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
|
int *paths;
|
||||||
int on;
|
int on;
|
||||||
|
|
||||||
/* Control HP pins/amps depending on master_mute state;
|
/* Control HP pins/amps depending on master_mute state;
|
||||||
* in general, HP pins/amps control should be enabled in all cases,
|
* in general, HP pins/amps control should be enabled in all cases,
|
||||||
* but currently set only for master_mute, just to be safe
|
* but currently set only for master_mute, just to be safe
|
||||||
*/
|
*/
|
||||||
|
if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
|
||||||
|
paths = spec->out_paths;
|
||||||
|
else
|
||||||
|
paths = spec->hp_paths;
|
||||||
do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
|
do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
|
||||||
spec->autocfg.hp_pins, spec->master_mute);
|
spec->autocfg.hp_pins, paths, spec->master_mute);
|
||||||
|
|
||||||
if (!spec->automute_speaker)
|
if (!spec->automute_speaker)
|
||||||
on = 0;
|
on = 0;
|
||||||
|
@ -3801,8 +3843,12 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec)
|
||||||
on = spec->hp_jack_present | spec->line_jack_present;
|
on = spec->hp_jack_present | spec->line_jack_present;
|
||||||
on |= spec->master_mute;
|
on |= spec->master_mute;
|
||||||
spec->speaker_muted = on;
|
spec->speaker_muted = on;
|
||||||
|
if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
|
||||||
|
paths = spec->out_paths;
|
||||||
|
else
|
||||||
|
paths = spec->speaker_paths;
|
||||||
do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
|
do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
|
||||||
spec->autocfg.speaker_pins, on);
|
spec->autocfg.speaker_pins, paths, on);
|
||||||
|
|
||||||
/* toggle line-out mutes if needed, too */
|
/* toggle line-out mutes if needed, too */
|
||||||
/* if LO is a copy of either HP or Speaker, don't need to handle it */
|
/* if LO is a copy of either HP or Speaker, don't need to handle it */
|
||||||
|
@ -3815,8 +3861,9 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec)
|
||||||
on = spec->hp_jack_present;
|
on = spec->hp_jack_present;
|
||||||
on |= spec->master_mute;
|
on |= spec->master_mute;
|
||||||
spec->line_out_muted = on;
|
spec->line_out_muted = on;
|
||||||
|
paths = spec->out_paths;
|
||||||
do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
|
do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
|
||||||
spec->autocfg.line_out_pins, on);
|
spec->autocfg.line_out_pins, paths, on);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
|
EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
|
||||||
|
|
||||||
|
@ -3887,7 +3934,7 @@ void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *ja
|
||||||
/* don't detect pins retasked as outputs */
|
/* don't detect pins retasked as outputs */
|
||||||
if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
|
if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
|
||||||
continue;
|
continue;
|
||||||
if (snd_hda_jack_detect(codec, pin)) {
|
if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
|
||||||
mux_select(codec, 0, spec->am_entry[i].idx);
|
mux_select(codec, 0, spec->am_entry[i].idx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,6 +220,7 @@ struct hda_gen_spec {
|
||||||
unsigned int hp_mic:1; /* Allow HP as a mic-in */
|
unsigned int hp_mic:1; /* Allow HP as a mic-in */
|
||||||
unsigned int suppress_hp_mic_detect:1; /* Don't detect HP/mic */
|
unsigned int suppress_hp_mic_detect:1; /* Don't detect HP/mic */
|
||||||
unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */
|
unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */
|
||||||
|
unsigned int no_multi_io:1; /* Don't try multi I/O config */
|
||||||
unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */
|
unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */
|
||||||
unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
|
unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
|
||||||
unsigned int own_eapd_ctl:1; /* set EAPD by own function */
|
unsigned int own_eapd_ctl:1; /* set EAPD by own function */
|
||||||
|
|
|
@ -295,7 +295,7 @@ static ssize_t type##_store(struct device *dev, \
|
||||||
struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
|
struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
|
||||||
struct hda_codec *codec = hwdep->private_data; \
|
struct hda_codec *codec = hwdep->private_data; \
|
||||||
unsigned long val; \
|
unsigned long val; \
|
||||||
int err = strict_strtoul(buf, 0, &val); \
|
int err = kstrtoul(buf, 0, &val); \
|
||||||
if (err < 0) \
|
if (err < 0) \
|
||||||
return err; \
|
return err; \
|
||||||
codec->type = val; \
|
codec->type = val; \
|
||||||
|
@ -654,7 +654,7 @@ int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp)
|
||||||
p = snd_hda_get_hint(codec, key);
|
p = snd_hda_get_hint(codec, key);
|
||||||
if (!p)
|
if (!p)
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
else if (strict_strtoul(p, 0, &val))
|
else if (kstrtoul(p, 0, &val))
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
else {
|
else {
|
||||||
*valp = val;
|
*valp = val;
|
||||||
|
@ -751,7 +751,7 @@ static void parse_##name##_mode(char *buf, struct hda_bus *bus, \
|
||||||
struct hda_codec **codecp) \
|
struct hda_codec **codecp) \
|
||||||
{ \
|
{ \
|
||||||
unsigned long val; \
|
unsigned long val; \
|
||||||
if (!strict_strtoul(buf, 0, &val)) \
|
if (!kstrtoul(buf, 0, &val)) \
|
||||||
(*codecp)->name = val; \
|
(*codecp)->name = val; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1160,7 +1160,7 @@ static int azx_reset(struct azx *chip, int full_reset)
|
||||||
goto __skip;
|
goto __skip;
|
||||||
|
|
||||||
/* clear STATESTS */
|
/* clear STATESTS */
|
||||||
azx_writeb(chip, STATESTS, STATESTS_INT_MASK);
|
azx_writew(chip, STATESTS, STATESTS_INT_MASK);
|
||||||
|
|
||||||
/* reset controller */
|
/* reset controller */
|
||||||
azx_enter_link_reset(chip);
|
azx_enter_link_reset(chip);
|
||||||
|
@ -1242,7 +1242,7 @@ static void azx_int_clear(struct azx *chip)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clear STATESTS */
|
/* clear STATESTS */
|
||||||
azx_writeb(chip, STATESTS, STATESTS_INT_MASK);
|
azx_writew(chip, STATESTS, STATESTS_INT_MASK);
|
||||||
|
|
||||||
/* clear rirb status */
|
/* clear rirb status */
|
||||||
azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
|
azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
|
||||||
|
@ -1451,8 +1451,8 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* clear state status int */
|
/* clear state status int */
|
||||||
if (azx_readb(chip, STATESTS) & 0x04)
|
if (azx_readw(chip, STATESTS) & 0x04)
|
||||||
azx_writeb(chip, STATESTS, 0x04);
|
azx_writew(chip, STATESTS, 0x04);
|
||||||
#endif
|
#endif
|
||||||
spin_unlock(&chip->reg_lock);
|
spin_unlock(&chip->reg_lock);
|
||||||
|
|
||||||
|
@ -2971,6 +2971,10 @@ static int azx_runtime_suspend(struct device *dev)
|
||||||
struct snd_card *card = dev_get_drvdata(dev);
|
struct snd_card *card = dev_get_drvdata(dev);
|
||||||
struct azx *chip = card->private_data;
|
struct azx *chip = card->private_data;
|
||||||
|
|
||||||
|
/* enable controller wake up event */
|
||||||
|
azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) |
|
||||||
|
STATESTS_INT_MASK);
|
||||||
|
|
||||||
azx_stop_chip(chip);
|
azx_stop_chip(chip);
|
||||||
azx_enter_link_reset(chip);
|
azx_enter_link_reset(chip);
|
||||||
azx_clear_irq_pending(chip);
|
azx_clear_irq_pending(chip);
|
||||||
|
@ -2983,11 +2987,31 @@ static int azx_runtime_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct snd_card *card = dev_get_drvdata(dev);
|
struct snd_card *card = dev_get_drvdata(dev);
|
||||||
struct azx *chip = card->private_data;
|
struct azx *chip = card->private_data;
|
||||||
|
struct hda_bus *bus;
|
||||||
|
struct hda_codec *codec;
|
||||||
|
int status;
|
||||||
|
|
||||||
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
|
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
|
||||||
hda_display_power(true);
|
hda_display_power(true);
|
||||||
|
|
||||||
|
/* Read STATESTS before controller reset */
|
||||||
|
status = azx_readw(chip, STATESTS);
|
||||||
|
|
||||||
azx_init_pci(chip);
|
azx_init_pci(chip);
|
||||||
azx_init_chip(chip, 1);
|
azx_init_chip(chip, 1);
|
||||||
|
|
||||||
|
bus = chip->bus;
|
||||||
|
if (status && bus) {
|
||||||
|
list_for_each_entry(codec, &bus->codec_list, list)
|
||||||
|
if (status & (1 << codec->addr))
|
||||||
|
queue_delayed_work(codec->bus->workq,
|
||||||
|
&codec->jackpoll_work, codec->jackpoll_interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* disable controller Wake Up event*/
|
||||||
|
azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
|
||||||
|
~STATESTS_INT_MASK);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3831,11 +3855,13 @@ static int azx_probe_continue(struct azx *chip)
|
||||||
|
|
||||||
/* Request power well for Haswell HDA controller and codec */
|
/* Request power well for Haswell HDA controller and codec */
|
||||||
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
|
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
|
||||||
|
#ifdef CONFIG_SND_HDA_I915
|
||||||
err = hda_i915_init();
|
err = hda_i915_init();
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
snd_printk(KERN_ERR SFX "Error request power-well from i915\n");
|
snd_printk(KERN_ERR SFX "Error request power-well from i915\n");
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
hda_display_power(true);
|
hda_display_power(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -194,18 +194,24 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
|
||||||
EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
|
EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_hda_jack_detect - query pin Presence Detect status
|
* snd_hda_jack_detect_state - query pin Presence Detect status
|
||||||
* @codec: the CODEC to sense
|
* @codec: the CODEC to sense
|
||||||
* @nid: the pin NID to sense
|
* @nid: the pin NID to sense
|
||||||
*
|
*
|
||||||
* Query and return the pin's Presence Detect status.
|
* Query and return the pin's Presence Detect status, as either
|
||||||
|
* HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT or HDA_JACK_PHANTOM.
|
||||||
*/
|
*/
|
||||||
int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
|
int snd_hda_jack_detect_state(struct hda_codec *codec, hda_nid_t nid)
|
||||||
{
|
{
|
||||||
u32 sense = snd_hda_pin_sense(codec, nid);
|
struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
|
||||||
return get_jack_plug_state(sense);
|
if (jack && jack->phantom_jack)
|
||||||
|
return HDA_JACK_PHANTOM;
|
||||||
|
else if (snd_hda_pin_sense(codec, nid) & AC_PINSENSE_PRESENCE)
|
||||||
|
return HDA_JACK_PRESENT;
|
||||||
|
else
|
||||||
|
return HDA_JACK_NOT_PRESENT;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
|
EXPORT_SYMBOL_HDA(snd_hda_jack_detect_state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_hda_jack_detect_enable - enable the jack-detection
|
* snd_hda_jack_detect_enable - enable the jack-detection
|
||||||
|
@ -247,8 +253,8 @@ EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
|
||||||
int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
|
int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
|
||||||
hda_nid_t gating_nid)
|
hda_nid_t gating_nid)
|
||||||
{
|
{
|
||||||
struct hda_jack_tbl *gated = snd_hda_jack_tbl_get(codec, gated_nid);
|
struct hda_jack_tbl *gated = snd_hda_jack_tbl_new(codec, gated_nid);
|
||||||
struct hda_jack_tbl *gating = snd_hda_jack_tbl_get(codec, gating_nid);
|
struct hda_jack_tbl *gating = snd_hda_jack_tbl_new(codec, gating_nid);
|
||||||
|
|
||||||
if (!gated || !gating)
|
if (!gated || !gating)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -75,7 +75,18 @@ int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
|
||||||
hda_nid_t gating_nid);
|
hda_nid_t gating_nid);
|
||||||
|
|
||||||
u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
|
u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
|
||||||
int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
|
|
||||||
|
/* the jack state returned from snd_hda_jack_detect_state() */
|
||||||
|
enum {
|
||||||
|
HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT, HDA_JACK_PHANTOM,
|
||||||
|
};
|
||||||
|
|
||||||
|
int snd_hda_jack_detect_state(struct hda_codec *codec, hda_nid_t nid);
|
||||||
|
|
||||||
|
static inline bool snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
|
||||||
|
{
|
||||||
|
return snd_hda_jack_detect_state(codec, nid) != HDA_JACK_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid);
|
bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid);
|
||||||
|
|
||||||
|
|
|
@ -582,6 +582,36 @@ static void print_gpio(struct snd_info_buffer *buffer,
|
||||||
print_nid_array(buffer, codec, nid, &codec->nids);
|
print_nid_array(buffer, codec, nid, &codec->nids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void print_device_list(struct snd_info_buffer *buffer,
|
||||||
|
struct hda_codec *codec, hda_nid_t nid)
|
||||||
|
{
|
||||||
|
int i, curr = -1;
|
||||||
|
u8 dev_list[AC_MAX_DEV_LIST_LEN];
|
||||||
|
int devlist_len;
|
||||||
|
|
||||||
|
devlist_len = snd_hda_get_devices(codec, nid, dev_list,
|
||||||
|
AC_MAX_DEV_LIST_LEN);
|
||||||
|
snd_iprintf(buffer, " Devices: %d\n", devlist_len);
|
||||||
|
if (devlist_len <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
curr = snd_hda_codec_read(codec, nid, 0,
|
||||||
|
AC_VERB_GET_DEVICE_SEL, 0);
|
||||||
|
|
||||||
|
for (i = 0; i < devlist_len; i++) {
|
||||||
|
if (i == curr)
|
||||||
|
snd_iprintf(buffer, " *");
|
||||||
|
else
|
||||||
|
snd_iprintf(buffer, " ");
|
||||||
|
|
||||||
|
snd_iprintf(buffer,
|
||||||
|
"Dev %02d: PD = %d, ELDV = %d, IA = %d\n", i,
|
||||||
|
!!(dev_list[i] & AC_DE_PD),
|
||||||
|
!!(dev_list[i] & AC_DE_ELDV),
|
||||||
|
!!(dev_list[i] & AC_DE_IA));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void print_codec_info(struct snd_info_entry *entry,
|
static void print_codec_info(struct snd_info_entry *entry,
|
||||||
struct snd_info_buffer *buffer)
|
struct snd_info_buffer *buffer)
|
||||||
{
|
{
|
||||||
|
@ -751,6 +781,9 @@ static void print_codec_info(struct snd_info_entry *entry,
|
||||||
(wid_caps & AC_WCAP_DELAY) >>
|
(wid_caps & AC_WCAP_DELAY) >>
|
||||||
AC_WCAP_DELAY_SHIFT);
|
AC_WCAP_DELAY_SHIFT);
|
||||||
|
|
||||||
|
if (wid_type == AC_WID_PIN && codec->dp_mst)
|
||||||
|
print_device_list(buffer, codec, nid);
|
||||||
|
|
||||||
if (wid_caps & AC_WCAP_CONN_LIST)
|
if (wid_caps & AC_WCAP_CONN_LIST)
|
||||||
print_conn_list(buffer, codec, nid, wid_type,
|
print_conn_list(buffer, codec, nid, wid_type,
|
||||||
conn, conn_len);
|
conn, conn_len);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -66,6 +66,8 @@ struct conexant_spec {
|
||||||
hda_nid_t eapds[4];
|
hda_nid_t eapds[4];
|
||||||
bool dynamic_eapd;
|
bool dynamic_eapd;
|
||||||
|
|
||||||
|
unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
|
||||||
|
|
||||||
#ifdef ENABLE_CXT_STATIC_QUIRKS
|
#ifdef ENABLE_CXT_STATIC_QUIRKS
|
||||||
const struct snd_kcontrol_new *mixers[5];
|
const struct snd_kcontrol_new *mixers[5];
|
||||||
int num_mixers;
|
int num_mixers;
|
||||||
|
@ -3200,6 +3202,9 @@ static int cx_auto_init(struct hda_codec *codec)
|
||||||
snd_hda_gen_init(codec);
|
snd_hda_gen_init(codec);
|
||||||
if (!spec->dynamic_eapd)
|
if (!spec->dynamic_eapd)
|
||||||
cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
|
cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
|
||||||
|
|
||||||
|
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3224,6 +3229,8 @@ enum {
|
||||||
CXT_PINCFG_LEMOTE_A1205,
|
CXT_PINCFG_LEMOTE_A1205,
|
||||||
CXT_FIXUP_STEREO_DMIC,
|
CXT_FIXUP_STEREO_DMIC,
|
||||||
CXT_FIXUP_INC_MIC_BOOST,
|
CXT_FIXUP_INC_MIC_BOOST,
|
||||||
|
CXT_FIXUP_HEADPHONE_MIC_PIN,
|
||||||
|
CXT_FIXUP_HEADPHONE_MIC,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
|
static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
|
||||||
|
@ -3246,6 +3253,59 @@ static void cxt5066_increase_mic_boost(struct hda_codec *codec,
|
||||||
(0 << AC_AMPCAP_MUTE_SHIFT));
|
(0 << AC_AMPCAP_MUTE_SHIFT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cxt_update_headset_mode(struct hda_codec *codec)
|
||||||
|
{
|
||||||
|
/* The verbs used in this function were tested on a Conexant CX20751/2 codec. */
|
||||||
|
int i;
|
||||||
|
bool mic_mode = false;
|
||||||
|
struct conexant_spec *spec = codec->spec;
|
||||||
|
struct auto_pin_cfg *cfg = &spec->gen.autocfg;
|
||||||
|
|
||||||
|
hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
|
||||||
|
|
||||||
|
for (i = 0; i < cfg->num_inputs; i++)
|
||||||
|
if (cfg->inputs[i].pin == mux_pin) {
|
||||||
|
mic_mode = !!cfg->inputs[i].is_headphone_mic;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mic_mode) {
|
||||||
|
snd_hda_codec_write_cache(codec, 0x1c, 0, 0x410, 0x7c); /* enable merged mode for analog int-mic */
|
||||||
|
spec->gen.hp_jack_present = false;
|
||||||
|
} else {
|
||||||
|
snd_hda_codec_write_cache(codec, 0x1c, 0, 0x410, 0x54); /* disable merged mode for analog int-mic */
|
||||||
|
spec->gen.hp_jack_present = snd_hda_jack_detect(codec, spec->gen.autocfg.hp_pins[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
snd_hda_gen_update_outputs(codec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cxt_update_headset_mode_hook(struct hda_codec *codec,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
cxt_update_headset_mode(codec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cxt_fixup_headphone_mic(struct hda_codec *codec,
|
||||||
|
const struct hda_fixup *fix, int action)
|
||||||
|
{
|
||||||
|
struct conexant_spec *spec = codec->spec;
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case HDA_FIXUP_ACT_PRE_PROBE:
|
||||||
|
spec->parse_flags |= HDA_PINCFG_HEADPHONE_MIC;
|
||||||
|
break;
|
||||||
|
case HDA_FIXUP_ACT_PROBE:
|
||||||
|
spec->gen.cap_sync_hook = cxt_update_headset_mode_hook;
|
||||||
|
spec->gen.automute_hook = cxt_update_headset_mode;
|
||||||
|
break;
|
||||||
|
case HDA_FIXUP_ACT_INIT:
|
||||||
|
cxt_update_headset_mode(codec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ThinkPad X200 & co with cxt5051 */
|
/* ThinkPad X200 & co with cxt5051 */
|
||||||
static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
|
static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
|
||||||
{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
|
{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
|
||||||
|
@ -3302,6 +3362,19 @@ static const struct hda_fixup cxt_fixups[] = {
|
||||||
.type = HDA_FIXUP_FUNC,
|
.type = HDA_FIXUP_FUNC,
|
||||||
.v.func = cxt5066_increase_mic_boost,
|
.v.func = cxt5066_increase_mic_boost,
|
||||||
},
|
},
|
||||||
|
[CXT_FIXUP_HEADPHONE_MIC_PIN] = {
|
||||||
|
.type = HDA_FIXUP_PINS,
|
||||||
|
.chained = true,
|
||||||
|
.chain_id = CXT_FIXUP_HEADPHONE_MIC,
|
||||||
|
.v.pins = (const struct hda_pintbl[]) {
|
||||||
|
{ 0x18, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[CXT_FIXUP_HEADPHONE_MIC] = {
|
||||||
|
.type = HDA_FIXUP_FUNC,
|
||||||
|
.v.func = cxt_fixup_headphone_mic,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct snd_pci_quirk cxt5051_fixups[] = {
|
static const struct snd_pci_quirk cxt5051_fixups[] = {
|
||||||
|
@ -3311,6 +3384,7 @@ static const struct snd_pci_quirk cxt5051_fixups[] = {
|
||||||
|
|
||||||
static const struct snd_pci_quirk cxt5066_fixups[] = {
|
static const struct snd_pci_quirk cxt5066_fixups[] = {
|
||||||
SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
|
SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
|
||||||
|
SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
|
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410),
|
SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
|
SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
|
||||||
|
@ -3395,7 +3469,8 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
||||||
|
|
||||||
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
|
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
|
||||||
|
|
||||||
err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
|
err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL,
|
||||||
|
spec->parse_flags);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
@ -3416,6 +3491,8 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
||||||
codec->bus->allow_bus_reset = 1;
|
codec->bus->allow_bus_reset = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
|
@ -67,6 +67,8 @@ struct hdmi_spec_per_pin {
|
||||||
struct delayed_work work;
|
struct delayed_work work;
|
||||||
struct snd_kcontrol *eld_ctl;
|
struct snd_kcontrol *eld_ctl;
|
||||||
int repoll_count;
|
int repoll_count;
|
||||||
|
bool setup; /* the stream has been set up by prepare callback */
|
||||||
|
int channels; /* current number of channels */
|
||||||
bool non_pcm;
|
bool non_pcm;
|
||||||
bool chmap_set; /* channel-map override by ALSA API? */
|
bool chmap_set; /* channel-map override by ALSA API? */
|
||||||
unsigned char chmap[8]; /* ALSA API channel-map */
|
unsigned char chmap[8]; /* ALSA API channel-map */
|
||||||
|
@ -551,6 +553,17 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ca) {
|
||||||
|
/* if there was no match, select the regular ALSA channel
|
||||||
|
* allocation with the matching number of channels */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
|
||||||
|
if (channels == channel_allocations[i].channels) {
|
||||||
|
ca = channel_allocations[i].ca_index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf));
|
snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf));
|
||||||
snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
|
snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
|
||||||
ca, channels, buf);
|
ca, channels, buf);
|
||||||
|
@ -868,18 +881,19 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx,
|
static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
|
||||||
bool non_pcm,
|
struct hdmi_spec_per_pin *per_pin,
|
||||||
struct snd_pcm_substream *substream)
|
bool non_pcm)
|
||||||
{
|
{
|
||||||
struct hdmi_spec *spec = codec->spec;
|
|
||||||
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
|
||||||
hda_nid_t pin_nid = per_pin->pin_nid;
|
hda_nid_t pin_nid = per_pin->pin_nid;
|
||||||
int channels = substream->runtime->channels;
|
int channels = per_pin->channels;
|
||||||
struct hdmi_eld *eld;
|
struct hdmi_eld *eld;
|
||||||
int ca;
|
int ca;
|
||||||
union audio_infoframe ai;
|
union audio_infoframe ai;
|
||||||
|
|
||||||
|
if (!channels)
|
||||||
|
return;
|
||||||
|
|
||||||
eld = &per_pin->sink_eld;
|
eld = &per_pin->sink_eld;
|
||||||
if (!eld->monitor_present)
|
if (!eld->monitor_present)
|
||||||
return;
|
return;
|
||||||
|
@ -959,6 +973,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
|
||||||
int pin_nid;
|
int pin_nid;
|
||||||
int pin_idx;
|
int pin_idx;
|
||||||
struct hda_jack_tbl *jack;
|
struct hda_jack_tbl *jack;
|
||||||
|
int dev_entry = (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT;
|
||||||
|
|
||||||
jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
|
jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
|
||||||
if (!jack)
|
if (!jack)
|
||||||
|
@ -967,8 +982,8 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
|
||||||
jack->jack_dirty = 1;
|
jack->jack_dirty = 1;
|
||||||
|
|
||||||
_snd_printd(SND_PR_VERBOSE,
|
_snd_printd(SND_PR_VERBOSE,
|
||||||
"HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
|
"HDMI hot plug event: Codec=%d Pin=%d Device=%d Inactive=%d Presence_Detect=%d ELD_Valid=%d\n",
|
||||||
codec->addr, pin_nid,
|
codec->addr, pin_nid, dev_entry, !!(res & AC_UNSOL_RES_IA),
|
||||||
!!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV));
|
!!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV));
|
||||||
|
|
||||||
pin_idx = pin_nid_to_pin_index(spec, pin_nid);
|
pin_idx = pin_nid_to_pin_index(spec, pin_nid);
|
||||||
|
@ -1329,6 +1344,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
|
||||||
eld_changed = true;
|
eld_changed = true;
|
||||||
}
|
}
|
||||||
if (update_eld) {
|
if (update_eld) {
|
||||||
|
bool old_eld_valid = pin_eld->eld_valid;
|
||||||
pin_eld->eld_valid = eld->eld_valid;
|
pin_eld->eld_valid = eld->eld_valid;
|
||||||
eld_changed = pin_eld->eld_size != eld->eld_size ||
|
eld_changed = pin_eld->eld_size != eld->eld_size ||
|
||||||
memcmp(pin_eld->eld_buffer, eld->eld_buffer,
|
memcmp(pin_eld->eld_buffer, eld->eld_buffer,
|
||||||
|
@ -1338,6 +1354,18 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
|
||||||
eld->eld_size);
|
eld->eld_size);
|
||||||
pin_eld->eld_size = eld->eld_size;
|
pin_eld->eld_size = eld->eld_size;
|
||||||
pin_eld->info = eld->info;
|
pin_eld->info = eld->info;
|
||||||
|
|
||||||
|
/* Haswell-specific workaround: re-setup when the transcoder is
|
||||||
|
* changed during the stream playback
|
||||||
|
*/
|
||||||
|
if (codec->vendor_id == 0x80862807 &&
|
||||||
|
eld->eld_valid && !old_eld_valid && per_pin->setup) {
|
||||||
|
snd_hda_codec_write(codec, pin_nid, 0,
|
||||||
|
AC_VERB_SET_AMP_GAIN_MUTE,
|
||||||
|
AMP_OUT_UNMUTE);
|
||||||
|
hdmi_setup_audio_infoframe(codec, per_pin,
|
||||||
|
per_pin->non_pcm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&pin_eld->lock);
|
mutex_unlock(&pin_eld->lock);
|
||||||
|
|
||||||
|
@ -1510,14 +1538,17 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
|
||||||
hda_nid_t cvt_nid = hinfo->nid;
|
hda_nid_t cvt_nid = hinfo->nid;
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
int pin_idx = hinfo_to_pin_index(spec, hinfo);
|
int pin_idx = hinfo_to_pin_index(spec, hinfo);
|
||||||
hda_nid_t pin_nid = get_pin(spec, pin_idx)->pin_nid;
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||||
|
hda_nid_t pin_nid = per_pin->pin_nid;
|
||||||
bool non_pcm;
|
bool non_pcm;
|
||||||
|
|
||||||
non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
|
non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
|
||||||
|
per_pin->channels = substream->runtime->channels;
|
||||||
|
per_pin->setup = true;
|
||||||
|
|
||||||
hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels);
|
hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels);
|
||||||
|
|
||||||
hdmi_setup_audio_infoframe(codec, pin_idx, non_pcm, substream);
|
hdmi_setup_audio_infoframe(codec, per_pin, non_pcm);
|
||||||
|
|
||||||
return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);
|
return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);
|
||||||
}
|
}
|
||||||
|
@ -1557,6 +1588,9 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
|
||||||
snd_hda_spdif_ctls_unassign(codec, pin_idx);
|
snd_hda_spdif_ctls_unassign(codec, pin_idx);
|
||||||
per_pin->chmap_set = false;
|
per_pin->chmap_set = false;
|
||||||
memset(per_pin->chmap, 0, sizeof(per_pin->chmap));
|
memset(per_pin->chmap, 0, sizeof(per_pin->chmap));
|
||||||
|
|
||||||
|
per_pin->setup = false;
|
||||||
|
per_pin->channels = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1692,8 +1726,7 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
|
||||||
per_pin->chmap_set = true;
|
per_pin->chmap_set = true;
|
||||||
memcpy(per_pin->chmap, chmap, sizeof(chmap));
|
memcpy(per_pin->chmap, chmap, sizeof(chmap));
|
||||||
if (prepared)
|
if (prepared)
|
||||||
hdmi_setup_audio_infoframe(codec, pin_idx, per_pin->non_pcm,
|
hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
|
||||||
substream);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1992,8 +2025,10 @@ static int patch_generic_hdmi(struct hda_codec *codec)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
codec->patch_ops = generic_hdmi_patch_ops;
|
codec->patch_ops = generic_hdmi_patch_ops;
|
||||||
if (codec->vendor_id == 0x80862807)
|
if (codec->vendor_id == 0x80862807) {
|
||||||
codec->patch_ops.set_power_state = haswell_set_power_state;
|
codec->patch_ops.set_power_state = haswell_set_power_state;
|
||||||
|
codec->dp_mst = true;
|
||||||
|
}
|
||||||
|
|
||||||
generic_hdmi_init_per_pins(codec);
|
generic_hdmi_init_per_pins(codec);
|
||||||
|
|
||||||
|
|
|
@ -282,6 +282,7 @@ static void alc_eapd_shutup(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
alc_auto_setup_eapd(codec, false);
|
alc_auto_setup_eapd(codec, false);
|
||||||
msleep(200);
|
msleep(200);
|
||||||
|
snd_hda_shutup_pins(codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generic EAPD initialization */
|
/* generic EAPD initialization */
|
||||||
|
@ -826,7 +827,8 @@ static inline void alc_shutup(struct hda_codec *codec)
|
||||||
|
|
||||||
if (spec && spec->shutup)
|
if (spec && spec->shutup)
|
||||||
spec->shutup(codec);
|
spec->shutup(codec);
|
||||||
snd_hda_shutup_pins(codec);
|
else
|
||||||
|
snd_hda_shutup_pins(codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define alc_free snd_hda_gen_free
|
#define alc_free snd_hda_gen_free
|
||||||
|
@ -1853,8 +1855,10 @@ static void alc882_fixup_no_primary_hp(struct hda_codec *codec,
|
||||||
const struct hda_fixup *fix, int action)
|
const struct hda_fixup *fix, int action)
|
||||||
{
|
{
|
||||||
struct alc_spec *spec = codec->spec;
|
struct alc_spec *spec = codec->spec;
|
||||||
if (action == HDA_FIXUP_ACT_PRE_PROBE)
|
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
|
||||||
spec->gen.no_primary_hp = 1;
|
spec->gen.no_primary_hp = 1;
|
||||||
|
spec->gen.no_multi_io = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct hda_fixup alc882_fixups[] = {
|
static const struct hda_fixup alc882_fixups[] = {
|
||||||
|
@ -2533,6 +2537,7 @@ enum {
|
||||||
ALC269_TYPE_ALC269VD,
|
ALC269_TYPE_ALC269VD,
|
||||||
ALC269_TYPE_ALC280,
|
ALC269_TYPE_ALC280,
|
||||||
ALC269_TYPE_ALC282,
|
ALC269_TYPE_ALC282,
|
||||||
|
ALC269_TYPE_ALC283,
|
||||||
ALC269_TYPE_ALC284,
|
ALC269_TYPE_ALC284,
|
||||||
ALC269_TYPE_ALC286,
|
ALC269_TYPE_ALC286,
|
||||||
};
|
};
|
||||||
|
@ -2558,6 +2563,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
|
||||||
case ALC269_TYPE_ALC269VB:
|
case ALC269_TYPE_ALC269VB:
|
||||||
case ALC269_TYPE_ALC269VD:
|
case ALC269_TYPE_ALC269VD:
|
||||||
case ALC269_TYPE_ALC282:
|
case ALC269_TYPE_ALC282:
|
||||||
|
case ALC269_TYPE_ALC283:
|
||||||
case ALC269_TYPE_ALC286:
|
case ALC269_TYPE_ALC286:
|
||||||
ssids = alc269_ssids;
|
ssids = alc269_ssids;
|
||||||
break;
|
break;
|
||||||
|
@ -2583,15 +2589,81 @@ static void alc269_shutup(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
struct alc_spec *spec = codec->spec;
|
struct alc_spec *spec = codec->spec;
|
||||||
|
|
||||||
if (spec->codec_variant != ALC269_TYPE_ALC269VB)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (spec->codec_variant == ALC269_TYPE_ALC269VB)
|
if (spec->codec_variant == ALC269_TYPE_ALC269VB)
|
||||||
alc269vb_toggle_power_output(codec, 0);
|
alc269vb_toggle_power_output(codec, 0);
|
||||||
if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
|
if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
|
||||||
(alc_get_coef0(codec) & 0x00ff) == 0x018) {
|
(alc_get_coef0(codec) & 0x00ff) == 0x018) {
|
||||||
msleep(150);
|
msleep(150);
|
||||||
}
|
}
|
||||||
|
snd_hda_shutup_pins(codec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void alc283_init(struct hda_codec *codec)
|
||||||
|
{
|
||||||
|
struct alc_spec *spec = codec->spec;
|
||||||
|
hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
|
||||||
|
bool hp_pin_sense;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
if (!hp_pin)
|
||||||
|
return;
|
||||||
|
hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
|
||||||
|
|
||||||
|
/* Index 0x43 Direct Drive HP AMP LPM Control 1 */
|
||||||
|
/* Headphone capless set to high power mode */
|
||||||
|
alc_write_coef_idx(codec, 0x43, 0x9004);
|
||||||
|
|
||||||
|
snd_hda_codec_write(codec, hp_pin, 0,
|
||||||
|
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
|
||||||
|
|
||||||
|
if (hp_pin_sense)
|
||||||
|
msleep(85);
|
||||||
|
|
||||||
|
snd_hda_codec_write(codec, hp_pin, 0,
|
||||||
|
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
|
||||||
|
|
||||||
|
if (hp_pin_sense)
|
||||||
|
msleep(85);
|
||||||
|
/* Index 0x46 Combo jack auto switch control 2 */
|
||||||
|
/* 3k pull low control for Headset jack. */
|
||||||
|
val = alc_read_coef_idx(codec, 0x46);
|
||||||
|
alc_write_coef_idx(codec, 0x46, val & ~(3 << 12));
|
||||||
|
/* Headphone capless set to normal mode */
|
||||||
|
alc_write_coef_idx(codec, 0x43, 0x9614);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void alc283_shutup(struct hda_codec *codec)
|
||||||
|
{
|
||||||
|
struct alc_spec *spec = codec->spec;
|
||||||
|
hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
|
||||||
|
bool hp_pin_sense;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
if (!hp_pin) {
|
||||||
|
alc269_shutup(codec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
|
||||||
|
|
||||||
|
alc_write_coef_idx(codec, 0x43, 0x9004);
|
||||||
|
|
||||||
|
snd_hda_codec_write(codec, hp_pin, 0,
|
||||||
|
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
|
||||||
|
|
||||||
|
if (hp_pin_sense)
|
||||||
|
msleep(85);
|
||||||
|
|
||||||
|
snd_hda_codec_write(codec, hp_pin, 0,
|
||||||
|
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
||||||
|
|
||||||
|
val = alc_read_coef_idx(codec, 0x46);
|
||||||
|
alc_write_coef_idx(codec, 0x46, val | (3 << 12));
|
||||||
|
|
||||||
|
if (hp_pin_sense)
|
||||||
|
msleep(85);
|
||||||
|
snd_hda_shutup_pins(codec);
|
||||||
|
alc_write_coef_idx(codec, 0x43, 0x9614);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
|
static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
|
||||||
|
@ -2722,6 +2794,7 @@ static int alc269_resume(struct hda_codec *codec)
|
||||||
hda_call_check_power_status(codec, 0x01);
|
hda_call_check_power_status(codec, 0x01);
|
||||||
if (spec->has_alc5505_dsp)
|
if (spec->has_alc5505_dsp)
|
||||||
alc5505_dsp_resume(codec);
|
alc5505_dsp_resume(codec);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
@ -3261,6 +3334,28 @@ static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
|
||||||
alc_fixup_headset_mode(codec, fix, action);
|
alc_fixup_headset_mode(codec, fix, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns the nid of the external mic input pin, or 0 if it cannot be found. */
|
||||||
|
static int find_ext_mic_pin(struct hda_codec *codec)
|
||||||
|
{
|
||||||
|
struct alc_spec *spec = codec->spec;
|
||||||
|
struct auto_pin_cfg *cfg = &spec->gen.autocfg;
|
||||||
|
hda_nid_t nid;
|
||||||
|
unsigned int defcfg;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < cfg->num_inputs; i++) {
|
||||||
|
if (cfg->inputs[i].type != AUTO_PIN_MIC)
|
||||||
|
continue;
|
||||||
|
nid = cfg->inputs[i].pin;
|
||||||
|
defcfg = snd_hda_codec_get_pincfg(codec, nid);
|
||||||
|
if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
|
||||||
|
continue;
|
||||||
|
return nid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
|
static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
|
||||||
const struct hda_fixup *fix,
|
const struct hda_fixup *fix,
|
||||||
int action)
|
int action)
|
||||||
|
@ -3268,11 +3363,12 @@ static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
|
||||||
struct alc_spec *spec = codec->spec;
|
struct alc_spec *spec = codec->spec;
|
||||||
|
|
||||||
if (action == HDA_FIXUP_ACT_PROBE) {
|
if (action == HDA_FIXUP_ACT_PROBE) {
|
||||||
if (snd_BUG_ON(!spec->gen.am_entry[1].pin ||
|
int mic_pin = find_ext_mic_pin(codec);
|
||||||
!spec->gen.autocfg.hp_pins[0]))
|
int hp_pin = spec->gen.autocfg.hp_pins[0];
|
||||||
|
|
||||||
|
if (snd_BUG_ON(!mic_pin || !hp_pin))
|
||||||
return;
|
return;
|
||||||
snd_hda_jack_set_gating_jack(codec, spec->gen.am_entry[1].pin,
|
snd_hda_jack_set_gating_jack(codec, mic_pin, hp_pin);
|
||||||
spec->gen.autocfg.hp_pins[0]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3308,6 +3404,45 @@ static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void alc283_hp_automute_hook(struct hda_codec *codec,
|
||||||
|
struct hda_jack_tbl *jack)
|
||||||
|
{
|
||||||
|
struct alc_spec *spec = codec->spec;
|
||||||
|
int vref;
|
||||||
|
|
||||||
|
msleep(200);
|
||||||
|
snd_hda_gen_hp_automute(codec, jack);
|
||||||
|
|
||||||
|
vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
|
||||||
|
|
||||||
|
msleep(600);
|
||||||
|
snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
|
||||||
|
vref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void alc283_chromebook_caps(struct hda_codec *codec)
|
||||||
|
{
|
||||||
|
snd_hda_override_wcaps(codec, 0x03, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void alc283_fixup_chromebook(struct hda_codec *codec,
|
||||||
|
const struct hda_fixup *fix, int action)
|
||||||
|
{
|
||||||
|
struct alc_spec *spec = codec->spec;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case HDA_FIXUP_ACT_PRE_PROBE:
|
||||||
|
alc283_chromebook_caps(codec);
|
||||||
|
spec->gen.hp_automute_hook = alc283_hp_automute_hook;
|
||||||
|
/* MIC2-VREF control */
|
||||||
|
/* Set to manual mode */
|
||||||
|
val = alc_read_coef_idx(codec, 0x06);
|
||||||
|
alc_write_coef_idx(codec, 0x06, val & ~0x000c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ALC269_FIXUP_SONY_VAIO,
|
ALC269_FIXUP_SONY_VAIO,
|
||||||
ALC275_FIXUP_SONY_VAIO_GPIO2,
|
ALC275_FIXUP_SONY_VAIO_GPIO2,
|
||||||
|
@ -3344,6 +3479,7 @@ enum {
|
||||||
ALC269_FIXUP_ACER_AC700,
|
ALC269_FIXUP_ACER_AC700,
|
||||||
ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
|
ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
|
||||||
ALC269VB_FIXUP_ORDISSIMO_EVE2,
|
ALC269VB_FIXUP_ORDISSIMO_EVE2,
|
||||||
|
ALC283_FIXUP_CHROME_BOOK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct hda_fixup alc269_fixups[] = {
|
static const struct hda_fixup alc269_fixups[] = {
|
||||||
|
@ -3595,11 +3731,20 @@ static const struct hda_fixup alc269_fixups[] = {
|
||||||
{ }
|
{ }
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
[ALC283_FIXUP_CHROME_BOOK] = {
|
||||||
|
.type = HDA_FIXUP_FUNC,
|
||||||
|
.v.func = alc283_fixup_chromebook,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||||
SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC),
|
SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC),
|
||||||
SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
|
SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
|
||||||
|
SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
|
||||||
|
SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
|
||||||
|
SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
|
||||||
|
SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
|
||||||
|
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
|
||||||
SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
|
SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
|
||||||
SND_PCI_QUIRK(0x1028, 0x05be, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
|
SND_PCI_QUIRK(0x1028, 0x05be, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
|
||||||
SND_PCI_QUIRK(0x1028, 0x05c4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
SND_PCI_QUIRK(0x1028, 0x05c4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||||
|
@ -3637,6 +3782,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||||
SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
|
SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
|
||||||
SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||||
SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||||
|
SND_PCI_QUIRK(0x103c, 0x21ed, "HP Falco Chromebook", ALC283_FIXUP_CHROME_BOOK),
|
||||||
SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
|
SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
|
||||||
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
|
@ -3655,11 +3801,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||||
SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
|
SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
|
||||||
SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
|
SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
|
||||||
SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
|
SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
|
||||||
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
|
|
||||||
SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
|
|
||||||
SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
|
|
||||||
SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
|
|
||||||
SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
|
|
||||||
SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
|
SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
|
SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
|
SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
|
||||||
|
@ -3670,8 +3811,16 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||||
SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
|
SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
|
SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
|
SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
|
|
||||||
SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
|
SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
|
||||||
|
SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
|
||||||
|
SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
|
SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
|
SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
|
SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
|
SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
|
SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
|
SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
|
SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
|
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
|
SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
|
||||||
SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
|
SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
|
||||||
|
@ -3840,11 +3989,15 @@ static int patch_alc269(struct hda_codec *codec)
|
||||||
case 0x10ec0290:
|
case 0x10ec0290:
|
||||||
spec->codec_variant = ALC269_TYPE_ALC280;
|
spec->codec_variant = ALC269_TYPE_ALC280;
|
||||||
break;
|
break;
|
||||||
case 0x10ec0233:
|
|
||||||
case 0x10ec0282:
|
case 0x10ec0282:
|
||||||
case 0x10ec0283:
|
|
||||||
spec->codec_variant = ALC269_TYPE_ALC282;
|
spec->codec_variant = ALC269_TYPE_ALC282;
|
||||||
break;
|
break;
|
||||||
|
case 0x10ec0233:
|
||||||
|
case 0x10ec0283:
|
||||||
|
spec->codec_variant = ALC269_TYPE_ALC283;
|
||||||
|
spec->shutup = alc283_shutup;
|
||||||
|
spec->init_hook = alc283_init;
|
||||||
|
break;
|
||||||
case 0x10ec0284:
|
case 0x10ec0284:
|
||||||
case 0x10ec0292:
|
case 0x10ec0292:
|
||||||
spec->codec_variant = ALC269_TYPE_ALC284;
|
spec->codec_variant = ALC269_TYPE_ALC284;
|
||||||
|
@ -3872,7 +4025,8 @@ static int patch_alc269(struct hda_codec *codec)
|
||||||
codec->patch_ops.suspend = alc269_suspend;
|
codec->patch_ops.suspend = alc269_suspend;
|
||||||
codec->patch_ops.resume = alc269_resume;
|
codec->patch_ops.resume = alc269_resume;
|
||||||
#endif
|
#endif
|
||||||
spec->shutup = alc269_shutup;
|
if (!spec->shutup)
|
||||||
|
spec->shutup = alc269_shutup;
|
||||||
|
|
||||||
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
|
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,7 @@ enum {
|
||||||
STAC_D965_VERBS,
|
STAC_D965_VERBS,
|
||||||
STAC_DELL_3ST,
|
STAC_DELL_3ST,
|
||||||
STAC_DELL_BIOS,
|
STAC_DELL_BIOS,
|
||||||
|
STAC_DELL_BIOS_AMIC,
|
||||||
STAC_DELL_BIOS_SPDIF,
|
STAC_DELL_BIOS_SPDIF,
|
||||||
STAC_927X_DELL_DMIC,
|
STAC_927X_DELL_DMIC,
|
||||||
STAC_927X_VOLKNOB,
|
STAC_927X_VOLKNOB,
|
||||||
|
@ -3231,8 +3232,6 @@ static const struct hda_fixup stac927x_fixups[] = {
|
||||||
[STAC_DELL_BIOS] = {
|
[STAC_DELL_BIOS] = {
|
||||||
.type = HDA_FIXUP_PINS,
|
.type = HDA_FIXUP_PINS,
|
||||||
.v.pins = (const struct hda_pintbl[]) {
|
.v.pins = (const struct hda_pintbl[]) {
|
||||||
/* configure the analog microphone on some laptops */
|
|
||||||
{ 0x0c, 0x90a79130 },
|
|
||||||
/* correct the front output jack as a hp out */
|
/* correct the front output jack as a hp out */
|
||||||
{ 0x0f, 0x0221101f },
|
{ 0x0f, 0x0221101f },
|
||||||
/* correct the front input jack as a mic */
|
/* correct the front input jack as a mic */
|
||||||
|
@ -3242,6 +3241,16 @@ static const struct hda_fixup stac927x_fixups[] = {
|
||||||
.chained = true,
|
.chained = true,
|
||||||
.chain_id = STAC_927X_DELL_DMIC,
|
.chain_id = STAC_927X_DELL_DMIC,
|
||||||
},
|
},
|
||||||
|
[STAC_DELL_BIOS_AMIC] = {
|
||||||
|
.type = HDA_FIXUP_PINS,
|
||||||
|
.v.pins = (const struct hda_pintbl[]) {
|
||||||
|
/* configure the analog microphone on some laptops */
|
||||||
|
{ 0x0c, 0x90a79130 },
|
||||||
|
{}
|
||||||
|
},
|
||||||
|
.chained = true,
|
||||||
|
.chain_id = STAC_DELL_BIOS,
|
||||||
|
},
|
||||||
[STAC_DELL_BIOS_SPDIF] = {
|
[STAC_DELL_BIOS_SPDIF] = {
|
||||||
.type = HDA_FIXUP_PINS,
|
.type = HDA_FIXUP_PINS,
|
||||||
.v.pins = (const struct hda_pintbl[]) {
|
.v.pins = (const struct hda_pintbl[]) {
|
||||||
|
@ -3270,6 +3279,7 @@ static const struct hda_model_fixup stac927x_models[] = {
|
||||||
{ .id = STAC_D965_5ST_NO_FP, .name = "5stack-no-fp" },
|
{ .id = STAC_D965_5ST_NO_FP, .name = "5stack-no-fp" },
|
||||||
{ .id = STAC_DELL_3ST, .name = "dell-3stack" },
|
{ .id = STAC_DELL_3ST, .name = "dell-3stack" },
|
||||||
{ .id = STAC_DELL_BIOS, .name = "dell-bios" },
|
{ .id = STAC_DELL_BIOS, .name = "dell-bios" },
|
||||||
|
{ .id = STAC_DELL_BIOS_AMIC, .name = "dell-bios-amic" },
|
||||||
{ .id = STAC_927X_VOLKNOB, .name = "volknob" },
|
{ .id = STAC_927X_VOLKNOB, .name = "volknob" },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
|
@ -207,9 +207,9 @@ static void vt1708_stop_hp_work(struct hda_codec *codec)
|
||||||
return;
|
return;
|
||||||
if (spec->hp_work_active) {
|
if (spec->hp_work_active) {
|
||||||
snd_hda_codec_write(codec, 0x1, 0, 0xf81, 1);
|
snd_hda_codec_write(codec, 0x1, 0, 0xf81, 1);
|
||||||
|
codec->jackpoll_interval = 0;
|
||||||
cancel_delayed_work_sync(&codec->jackpoll_work);
|
cancel_delayed_work_sync(&codec->jackpoll_work);
|
||||||
spec->hp_work_active = false;
|
spec->hp_work_active = false;
|
||||||
codec->jackpoll_interval = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/info.h>
|
#include <sound/info.h>
|
||||||
|
@ -198,6 +199,31 @@ MODULE_PARM_DESC(enable, "Enable RME Digi96 soundcard.");
|
||||||
#define RME96_AD1852_VOL_BITS 14
|
#define RME96_AD1852_VOL_BITS 14
|
||||||
#define RME96_AD1855_VOL_BITS 10
|
#define RME96_AD1855_VOL_BITS 10
|
||||||
|
|
||||||
|
/* Defines for snd_rme96_trigger */
|
||||||
|
#define RME96_TB_START_PLAYBACK 1
|
||||||
|
#define RME96_TB_START_CAPTURE 2
|
||||||
|
#define RME96_TB_STOP_PLAYBACK 4
|
||||||
|
#define RME96_TB_STOP_CAPTURE 8
|
||||||
|
#define RME96_TB_RESET_PLAYPOS 16
|
||||||
|
#define RME96_TB_RESET_CAPTUREPOS 32
|
||||||
|
#define RME96_TB_CLEAR_PLAYBACK_IRQ 64
|
||||||
|
#define RME96_TB_CLEAR_CAPTURE_IRQ 128
|
||||||
|
#define RME96_RESUME_PLAYBACK (RME96_TB_START_PLAYBACK)
|
||||||
|
#define RME96_RESUME_CAPTURE (RME96_TB_START_CAPTURE)
|
||||||
|
#define RME96_RESUME_BOTH (RME96_RESUME_PLAYBACK \
|
||||||
|
| RME96_RESUME_CAPTURE)
|
||||||
|
#define RME96_START_PLAYBACK (RME96_TB_START_PLAYBACK \
|
||||||
|
| RME96_TB_RESET_PLAYPOS)
|
||||||
|
#define RME96_START_CAPTURE (RME96_TB_START_CAPTURE \
|
||||||
|
| RME96_TB_RESET_CAPTUREPOS)
|
||||||
|
#define RME96_START_BOTH (RME96_START_PLAYBACK \
|
||||||
|
| RME96_START_CAPTURE)
|
||||||
|
#define RME96_STOP_PLAYBACK (RME96_TB_STOP_PLAYBACK \
|
||||||
|
| RME96_TB_CLEAR_PLAYBACK_IRQ)
|
||||||
|
#define RME96_STOP_CAPTURE (RME96_TB_STOP_CAPTURE \
|
||||||
|
| RME96_TB_CLEAR_CAPTURE_IRQ)
|
||||||
|
#define RME96_STOP_BOTH (RME96_STOP_PLAYBACK \
|
||||||
|
| RME96_STOP_CAPTURE)
|
||||||
|
|
||||||
struct rme96 {
|
struct rme96 {
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
@ -214,6 +240,13 @@ struct rme96 {
|
||||||
|
|
||||||
u8 rev; /* card revision number */
|
u8 rev; /* card revision number */
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
u32 playback_pointer;
|
||||||
|
u32 capture_pointer;
|
||||||
|
void *playback_suspend_buffer;
|
||||||
|
void *capture_suspend_buffer;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct snd_pcm_substream *playback_substream;
|
struct snd_pcm_substream *playback_substream;
|
||||||
struct snd_pcm_substream *capture_substream;
|
struct snd_pcm_substream *capture_substream;
|
||||||
|
|
||||||
|
@ -344,6 +377,8 @@ static struct snd_pcm_hardware snd_rme96_playback_spdif_info =
|
||||||
{
|
{
|
||||||
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
|
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
|
||||||
SNDRV_PCM_INFO_MMAP_VALID |
|
SNDRV_PCM_INFO_MMAP_VALID |
|
||||||
|
SNDRV_PCM_INFO_SYNC_START |
|
||||||
|
SNDRV_PCM_INFO_RESUME |
|
||||||
SNDRV_PCM_INFO_INTERLEAVED |
|
SNDRV_PCM_INFO_INTERLEAVED |
|
||||||
SNDRV_PCM_INFO_PAUSE),
|
SNDRV_PCM_INFO_PAUSE),
|
||||||
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
||||||
|
@ -373,6 +408,8 @@ static struct snd_pcm_hardware snd_rme96_capture_spdif_info =
|
||||||
{
|
{
|
||||||
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
|
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
|
||||||
SNDRV_PCM_INFO_MMAP_VALID |
|
SNDRV_PCM_INFO_MMAP_VALID |
|
||||||
|
SNDRV_PCM_INFO_SYNC_START |
|
||||||
|
SNDRV_PCM_INFO_RESUME |
|
||||||
SNDRV_PCM_INFO_INTERLEAVED |
|
SNDRV_PCM_INFO_INTERLEAVED |
|
||||||
SNDRV_PCM_INFO_PAUSE),
|
SNDRV_PCM_INFO_PAUSE),
|
||||||
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
||||||
|
@ -402,6 +439,8 @@ static struct snd_pcm_hardware snd_rme96_playback_adat_info =
|
||||||
{
|
{
|
||||||
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
|
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
|
||||||
SNDRV_PCM_INFO_MMAP_VALID |
|
SNDRV_PCM_INFO_MMAP_VALID |
|
||||||
|
SNDRV_PCM_INFO_SYNC_START |
|
||||||
|
SNDRV_PCM_INFO_RESUME |
|
||||||
SNDRV_PCM_INFO_INTERLEAVED |
|
SNDRV_PCM_INFO_INTERLEAVED |
|
||||||
SNDRV_PCM_INFO_PAUSE),
|
SNDRV_PCM_INFO_PAUSE),
|
||||||
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
||||||
|
@ -427,6 +466,8 @@ static struct snd_pcm_hardware snd_rme96_capture_adat_info =
|
||||||
{
|
{
|
||||||
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
|
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
|
||||||
SNDRV_PCM_INFO_MMAP_VALID |
|
SNDRV_PCM_INFO_MMAP_VALID |
|
||||||
|
SNDRV_PCM_INFO_SYNC_START |
|
||||||
|
SNDRV_PCM_INFO_RESUME |
|
||||||
SNDRV_PCM_INFO_INTERLEAVED |
|
SNDRV_PCM_INFO_INTERLEAVED |
|
||||||
SNDRV_PCM_INFO_PAUSE),
|
SNDRV_PCM_INFO_PAUSE),
|
||||||
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
||||||
|
@ -1045,54 +1086,35 @@ snd_rme96_capture_hw_params(struct snd_pcm_substream *substream,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
snd_rme96_playback_start(struct rme96 *rme96,
|
snd_rme96_trigger(struct rme96 *rme96,
|
||||||
int from_pause)
|
int op)
|
||||||
{
|
{
|
||||||
if (!from_pause) {
|
if (op & RME96_TB_RESET_PLAYPOS)
|
||||||
writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS);
|
writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS);
|
||||||
}
|
if (op & RME96_TB_RESET_CAPTUREPOS)
|
||||||
|
|
||||||
rme96->wcreg |= RME96_WCR_START;
|
|
||||||
writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
snd_rme96_capture_start(struct rme96 *rme96,
|
|
||||||
int from_pause)
|
|
||||||
{
|
|
||||||
if (!from_pause) {
|
|
||||||
writel(0, rme96->iobase + RME96_IO_RESET_REC_POS);
|
writel(0, rme96->iobase + RME96_IO_RESET_REC_POS);
|
||||||
|
if (op & RME96_TB_CLEAR_PLAYBACK_IRQ) {
|
||||||
|
rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER);
|
||||||
|
if (rme96->rcreg & RME96_RCR_IRQ)
|
||||||
|
writel(0, rme96->iobase + RME96_IO_CONFIRM_PLAY_IRQ);
|
||||||
}
|
}
|
||||||
|
if (op & RME96_TB_CLEAR_CAPTURE_IRQ) {
|
||||||
rme96->wcreg |= RME96_WCR_START_2;
|
rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER);
|
||||||
|
if (rme96->rcreg & RME96_RCR_IRQ_2)
|
||||||
|
writel(0, rme96->iobase + RME96_IO_CONFIRM_REC_IRQ);
|
||||||
|
}
|
||||||
|
if (op & RME96_TB_START_PLAYBACK)
|
||||||
|
rme96->wcreg |= RME96_WCR_START;
|
||||||
|
if (op & RME96_TB_STOP_PLAYBACK)
|
||||||
|
rme96->wcreg &= ~RME96_WCR_START;
|
||||||
|
if (op & RME96_TB_START_CAPTURE)
|
||||||
|
rme96->wcreg |= RME96_WCR_START_2;
|
||||||
|
if (op & RME96_TB_STOP_CAPTURE)
|
||||||
|
rme96->wcreg &= ~RME96_WCR_START_2;
|
||||||
writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
|
writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
snd_rme96_playback_stop(struct rme96 *rme96)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Check if there is an unconfirmed IRQ, if so confirm it, or else
|
|
||||||
* the hardware will not stop generating interrupts
|
|
||||||
*/
|
|
||||||
rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER);
|
|
||||||
if (rme96->rcreg & RME96_RCR_IRQ) {
|
|
||||||
writel(0, rme96->iobase + RME96_IO_CONFIRM_PLAY_IRQ);
|
|
||||||
}
|
|
||||||
rme96->wcreg &= ~RME96_WCR_START;
|
|
||||||
writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
snd_rme96_capture_stop(struct rme96 *rme96)
|
|
||||||
{
|
|
||||||
rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER);
|
|
||||||
if (rme96->rcreg & RME96_RCR_IRQ_2) {
|
|
||||||
writel(0, rme96->iobase + RME96_IO_CONFIRM_REC_IRQ);
|
|
||||||
}
|
|
||||||
rme96->wcreg &= ~RME96_WCR_START_2;
|
|
||||||
writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
static irqreturn_t
|
static irqreturn_t
|
||||||
snd_rme96_interrupt(int irq,
|
snd_rme96_interrupt(int irq,
|
||||||
|
@ -1155,6 +1177,7 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream)
|
||||||
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
|
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
|
|
||||||
|
snd_pcm_set_sync(substream);
|
||||||
spin_lock_irq(&rme96->lock);
|
spin_lock_irq(&rme96->lock);
|
||||||
if (rme96->playback_substream != NULL) {
|
if (rme96->playback_substream != NULL) {
|
||||||
spin_unlock_irq(&rme96->lock);
|
spin_unlock_irq(&rme96->lock);
|
||||||
|
@ -1191,6 +1214,7 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream)
|
||||||
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
|
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
|
|
||||||
|
snd_pcm_set_sync(substream);
|
||||||
runtime->hw = snd_rme96_capture_spdif_info;
|
runtime->hw = snd_rme96_capture_spdif_info;
|
||||||
if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG &&
|
if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG &&
|
||||||
(rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0)
|
(rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0)
|
||||||
|
@ -1222,6 +1246,7 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream)
|
||||||
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
|
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
|
|
||||||
|
snd_pcm_set_sync(substream);
|
||||||
spin_lock_irq(&rme96->lock);
|
spin_lock_irq(&rme96->lock);
|
||||||
if (rme96->playback_substream != NULL) {
|
if (rme96->playback_substream != NULL) {
|
||||||
spin_unlock_irq(&rme96->lock);
|
spin_unlock_irq(&rme96->lock);
|
||||||
|
@ -1253,6 +1278,7 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream)
|
||||||
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
|
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
|
|
||||||
|
snd_pcm_set_sync(substream);
|
||||||
runtime->hw = snd_rme96_capture_adat_info;
|
runtime->hw = snd_rme96_capture_adat_info;
|
||||||
if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) {
|
if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) {
|
||||||
/* makes no sense to use analog input. Note that analog
|
/* makes no sense to use analog input. Note that analog
|
||||||
|
@ -1288,7 +1314,7 @@ snd_rme96_playback_close(struct snd_pcm_substream *substream)
|
||||||
|
|
||||||
spin_lock_irq(&rme96->lock);
|
spin_lock_irq(&rme96->lock);
|
||||||
if (RME96_ISPLAYING(rme96)) {
|
if (RME96_ISPLAYING(rme96)) {
|
||||||
snd_rme96_playback_stop(rme96);
|
snd_rme96_trigger(rme96, RME96_STOP_PLAYBACK);
|
||||||
}
|
}
|
||||||
rme96->playback_substream = NULL;
|
rme96->playback_substream = NULL;
|
||||||
rme96->playback_periodsize = 0;
|
rme96->playback_periodsize = 0;
|
||||||
|
@ -1309,7 +1335,7 @@ snd_rme96_capture_close(struct snd_pcm_substream *substream)
|
||||||
|
|
||||||
spin_lock_irq(&rme96->lock);
|
spin_lock_irq(&rme96->lock);
|
||||||
if (RME96_ISRECORDING(rme96)) {
|
if (RME96_ISRECORDING(rme96)) {
|
||||||
snd_rme96_capture_stop(rme96);
|
snd_rme96_trigger(rme96, RME96_STOP_CAPTURE);
|
||||||
}
|
}
|
||||||
rme96->capture_substream = NULL;
|
rme96->capture_substream = NULL;
|
||||||
rme96->capture_periodsize = 0;
|
rme96->capture_periodsize = 0;
|
||||||
|
@ -1324,7 +1350,7 @@ snd_rme96_playback_prepare(struct snd_pcm_substream *substream)
|
||||||
|
|
||||||
spin_lock_irq(&rme96->lock);
|
spin_lock_irq(&rme96->lock);
|
||||||
if (RME96_ISPLAYING(rme96)) {
|
if (RME96_ISPLAYING(rme96)) {
|
||||||
snd_rme96_playback_stop(rme96);
|
snd_rme96_trigger(rme96, RME96_STOP_PLAYBACK);
|
||||||
}
|
}
|
||||||
writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS);
|
writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS);
|
||||||
spin_unlock_irq(&rme96->lock);
|
spin_unlock_irq(&rme96->lock);
|
||||||
|
@ -1338,7 +1364,7 @@ snd_rme96_capture_prepare(struct snd_pcm_substream *substream)
|
||||||
|
|
||||||
spin_lock_irq(&rme96->lock);
|
spin_lock_irq(&rme96->lock);
|
||||||
if (RME96_ISRECORDING(rme96)) {
|
if (RME96_ISRECORDING(rme96)) {
|
||||||
snd_rme96_capture_stop(rme96);
|
snd_rme96_trigger(rme96, RME96_STOP_CAPTURE);
|
||||||
}
|
}
|
||||||
writel(0, rme96->iobase + RME96_IO_RESET_REC_POS);
|
writel(0, rme96->iobase + RME96_IO_RESET_REC_POS);
|
||||||
spin_unlock_irq(&rme96->lock);
|
spin_unlock_irq(&rme96->lock);
|
||||||
|
@ -1350,41 +1376,55 @@ snd_rme96_playback_trigger(struct snd_pcm_substream *substream,
|
||||||
int cmd)
|
int cmd)
|
||||||
{
|
{
|
||||||
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
|
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
|
||||||
|
struct snd_pcm_substream *s;
|
||||||
|
bool sync;
|
||||||
|
|
||||||
|
snd_pcm_group_for_each_entry(s, substream) {
|
||||||
|
if (snd_pcm_substream_chip(s) == rme96)
|
||||||
|
snd_pcm_trigger_done(s, substream);
|
||||||
|
}
|
||||||
|
|
||||||
|
sync = (rme96->playback_substream && rme96->capture_substream) &&
|
||||||
|
(rme96->playback_substream->group ==
|
||||||
|
rme96->capture_substream->group);
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SNDRV_PCM_TRIGGER_START:
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
if (!RME96_ISPLAYING(rme96)) {
|
if (!RME96_ISPLAYING(rme96)) {
|
||||||
if (substream != rme96->playback_substream) {
|
if (substream != rme96->playback_substream)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
snd_rme96_trigger(rme96, sync ? RME96_START_BOTH
|
||||||
snd_rme96_playback_start(rme96, 0);
|
: RME96_START_PLAYBACK);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||||
case SNDRV_PCM_TRIGGER_STOP:
|
case SNDRV_PCM_TRIGGER_STOP:
|
||||||
if (RME96_ISPLAYING(rme96)) {
|
if (RME96_ISPLAYING(rme96)) {
|
||||||
if (substream != rme96->playback_substream) {
|
if (substream != rme96->playback_substream)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH
|
||||||
snd_rme96_playback_stop(rme96);
|
: RME96_STOP_PLAYBACK);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||||
if (RME96_ISPLAYING(rme96)) {
|
if (RME96_ISPLAYING(rme96))
|
||||||
snd_rme96_playback_stop(rme96);
|
snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH
|
||||||
}
|
: RME96_STOP_PLAYBACK);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SNDRV_PCM_TRIGGER_RESUME:
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||||
if (!RME96_ISPLAYING(rme96)) {
|
if (!RME96_ISPLAYING(rme96))
|
||||||
snd_rme96_playback_start(rme96, 1);
|
snd_rme96_trigger(rme96, sync ? RME96_RESUME_BOTH
|
||||||
}
|
: RME96_RESUME_PLAYBACK);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1393,36 +1433,49 @@ snd_rme96_capture_trigger(struct snd_pcm_substream *substream,
|
||||||
int cmd)
|
int cmd)
|
||||||
{
|
{
|
||||||
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
|
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
|
||||||
|
struct snd_pcm_substream *s;
|
||||||
|
bool sync;
|
||||||
|
|
||||||
|
snd_pcm_group_for_each_entry(s, substream) {
|
||||||
|
if (snd_pcm_substream_chip(s) == rme96)
|
||||||
|
snd_pcm_trigger_done(s, substream);
|
||||||
|
}
|
||||||
|
|
||||||
|
sync = (rme96->playback_substream && rme96->capture_substream) &&
|
||||||
|
(rme96->playback_substream->group ==
|
||||||
|
rme96->capture_substream->group);
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SNDRV_PCM_TRIGGER_START:
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
if (!RME96_ISRECORDING(rme96)) {
|
if (!RME96_ISRECORDING(rme96)) {
|
||||||
if (substream != rme96->capture_substream) {
|
if (substream != rme96->capture_substream)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
snd_rme96_trigger(rme96, sync ? RME96_START_BOTH
|
||||||
snd_rme96_capture_start(rme96, 0);
|
: RME96_START_CAPTURE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||||
case SNDRV_PCM_TRIGGER_STOP:
|
case SNDRV_PCM_TRIGGER_STOP:
|
||||||
if (RME96_ISRECORDING(rme96)) {
|
if (RME96_ISRECORDING(rme96)) {
|
||||||
if (substream != rme96->capture_substream) {
|
if (substream != rme96->capture_substream)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH
|
||||||
snd_rme96_capture_stop(rme96);
|
: RME96_STOP_CAPTURE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||||
if (RME96_ISRECORDING(rme96)) {
|
if (RME96_ISRECORDING(rme96))
|
||||||
snd_rme96_capture_stop(rme96);
|
snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH
|
||||||
}
|
: RME96_STOP_CAPTURE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SNDRV_PCM_TRIGGER_RESUME:
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||||
if (!RME96_ISRECORDING(rme96)) {
|
if (!RME96_ISRECORDING(rme96))
|
||||||
snd_rme96_capture_start(rme96, 1);
|
snd_rme96_trigger(rme96, sync ? RME96_RESUME_BOTH
|
||||||
}
|
: RME96_RESUME_CAPTURE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1505,8 +1558,7 @@ snd_rme96_free(void *private_data)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (rme96->irq >= 0) {
|
if (rme96->irq >= 0) {
|
||||||
snd_rme96_playback_stop(rme96);
|
snd_rme96_trigger(rme96, RME96_STOP_BOTH);
|
||||||
snd_rme96_capture_stop(rme96);
|
|
||||||
rme96->areg &= ~RME96_AR_DAC_EN;
|
rme96->areg &= ~RME96_AR_DAC_EN;
|
||||||
writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);
|
writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);
|
||||||
free_irq(rme96->irq, (void *)rme96);
|
free_irq(rme96->irq, (void *)rme96);
|
||||||
|
@ -1520,6 +1572,10 @@ snd_rme96_free(void *private_data)
|
||||||
pci_release_regions(rme96->pci);
|
pci_release_regions(rme96->pci);
|
||||||
rme96->port = 0;
|
rme96->port = 0;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
vfree(rme96->playback_suspend_buffer);
|
||||||
|
vfree(rme96->capture_suspend_buffer);
|
||||||
|
#endif
|
||||||
pci_disable_device(rme96->pci);
|
pci_disable_device(rme96->pci);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1606,8 +1662,7 @@ snd_rme96_create(struct rme96 *rme96)
|
||||||
rme96->capture_periodsize = 0;
|
rme96->capture_periodsize = 0;
|
||||||
|
|
||||||
/* make sure playback/capture is stopped, if by some reason active */
|
/* make sure playback/capture is stopped, if by some reason active */
|
||||||
snd_rme96_playback_stop(rme96);
|
snd_rme96_trigger(rme96, RME96_STOP_BOTH);
|
||||||
snd_rme96_capture_stop(rme96);
|
|
||||||
|
|
||||||
/* set default values in registers */
|
/* set default values in registers */
|
||||||
rme96->wcreg =
|
rme96->wcreg =
|
||||||
|
@ -2319,6 +2374,87 @@ snd_rme96_create_switches(struct snd_card *card,
|
||||||
* Card initialisation
|
* Card initialisation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
|
||||||
|
static int
|
||||||
|
snd_rme96_suspend(struct pci_dev *pci,
|
||||||
|
pm_message_t state)
|
||||||
|
{
|
||||||
|
struct snd_card *card = pci_get_drvdata(pci);
|
||||||
|
struct rme96 *rme96 = card->private_data;
|
||||||
|
|
||||||
|
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
|
||||||
|
snd_pcm_suspend(rme96->playback_substream);
|
||||||
|
snd_pcm_suspend(rme96->capture_substream);
|
||||||
|
|
||||||
|
/* save capture & playback pointers */
|
||||||
|
rme96->playback_pointer = readl(rme96->iobase + RME96_IO_GET_PLAY_POS)
|
||||||
|
& RME96_RCR_AUDIO_ADDR_MASK;
|
||||||
|
rme96->capture_pointer = readl(rme96->iobase + RME96_IO_GET_REC_POS)
|
||||||
|
& RME96_RCR_AUDIO_ADDR_MASK;
|
||||||
|
|
||||||
|
/* save playback and capture buffers */
|
||||||
|
memcpy_fromio(rme96->playback_suspend_buffer,
|
||||||
|
rme96->iobase + RME96_IO_PLAY_BUFFER, RME96_BUFFER_SIZE);
|
||||||
|
memcpy_fromio(rme96->capture_suspend_buffer,
|
||||||
|
rme96->iobase + RME96_IO_REC_BUFFER, RME96_BUFFER_SIZE);
|
||||||
|
|
||||||
|
/* disable the DAC */
|
||||||
|
rme96->areg &= ~RME96_AR_DAC_EN;
|
||||||
|
writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);
|
||||||
|
|
||||||
|
pci_disable_device(pci);
|
||||||
|
pci_save_state(pci);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
snd_rme96_resume(struct pci_dev *pci)
|
||||||
|
{
|
||||||
|
struct snd_card *card = pci_get_drvdata(pci);
|
||||||
|
struct rme96 *rme96 = card->private_data;
|
||||||
|
|
||||||
|
pci_restore_state(pci);
|
||||||
|
if (pci_enable_device(pci) < 0) {
|
||||||
|
printk(KERN_ERR "rme96: pci_enable_device failed, disabling device\n");
|
||||||
|
snd_card_disconnect(card);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset playback and record buffer pointers */
|
||||||
|
writel(0, rme96->iobase + RME96_IO_SET_PLAY_POS
|
||||||
|
+ rme96->playback_pointer);
|
||||||
|
writel(0, rme96->iobase + RME96_IO_SET_REC_POS
|
||||||
|
+ rme96->capture_pointer);
|
||||||
|
|
||||||
|
/* restore playback and capture buffers */
|
||||||
|
memcpy_toio(rme96->iobase + RME96_IO_PLAY_BUFFER,
|
||||||
|
rme96->playback_suspend_buffer, RME96_BUFFER_SIZE);
|
||||||
|
memcpy_toio(rme96->iobase + RME96_IO_REC_BUFFER,
|
||||||
|
rme96->capture_suspend_buffer, RME96_BUFFER_SIZE);
|
||||||
|
|
||||||
|
/* reset the ADC */
|
||||||
|
writel(rme96->areg | RME96_AR_PD2,
|
||||||
|
rme96->iobase + RME96_IO_ADDITIONAL_REG);
|
||||||
|
writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);
|
||||||
|
|
||||||
|
/* reset and enable DAC, restore analog volume */
|
||||||
|
snd_rme96_reset_dac(rme96);
|
||||||
|
rme96->areg |= RME96_AR_DAC_EN;
|
||||||
|
writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);
|
||||||
|
if (RME96_HAS_ANALOG_OUT(rme96)) {
|
||||||
|
usleep_range(3000, 10000);
|
||||||
|
snd_rme96_apply_dac_volume(rme96);
|
||||||
|
}
|
||||||
|
|
||||||
|
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static void snd_rme96_card_free(struct snd_card *card)
|
static void snd_rme96_card_free(struct snd_card *card)
|
||||||
{
|
{
|
||||||
snd_rme96_free(card->private_data);
|
snd_rme96_free(card->private_data);
|
||||||
|
@ -2355,6 +2491,23 @@ snd_rme96_probe(struct pci_dev *pci,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
rme96->playback_suspend_buffer = vmalloc(RME96_BUFFER_SIZE);
|
||||||
|
if (!rme96->playback_suspend_buffer) {
|
||||||
|
snd_printk(KERN_ERR
|
||||||
|
"Failed to allocate playback suspend buffer!\n");
|
||||||
|
snd_card_free(card);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
rme96->capture_suspend_buffer = vmalloc(RME96_BUFFER_SIZE);
|
||||||
|
if (!rme96->capture_suspend_buffer) {
|
||||||
|
snd_printk(KERN_ERR
|
||||||
|
"Failed to allocate capture suspend buffer!\n");
|
||||||
|
snd_card_free(card);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
strcpy(card->driver, "Digi96");
|
strcpy(card->driver, "Digi96");
|
||||||
switch (rme96->pci->device) {
|
switch (rme96->pci->device) {
|
||||||
case PCI_DEVICE_ID_RME_DIGI96:
|
case PCI_DEVICE_ID_RME_DIGI96:
|
||||||
|
@ -2397,6 +2550,10 @@ static struct pci_driver rme96_driver = {
|
||||||
.id_table = snd_rme96_ids,
|
.id_table = snd_rme96_ids,
|
||||||
.probe = snd_rme96_probe,
|
.probe = snd_rme96_probe,
|
||||||
.remove = snd_rme96_remove,
|
.remove = snd_rme96_remove,
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.suspend = snd_rme96_suspend,
|
||||||
|
.resume = snd_rme96_resume,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
module_pci_driver(rme96_driver);
|
module_pci_driver(rme96_driver);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -26,12 +26,9 @@ if SND_SOC
|
||||||
config SND_SOC_AC97_BUS
|
config SND_SOC_AC97_BUS
|
||||||
bool
|
bool
|
||||||
|
|
||||||
config SND_SOC_DMAENGINE_PCM
|
|
||||||
bool
|
|
||||||
|
|
||||||
config SND_SOC_GENERIC_DMAENGINE_PCM
|
config SND_SOC_GENERIC_DMAENGINE_PCM
|
||||||
bool
|
bool
|
||||||
select SND_SOC_DMAENGINE_PCM
|
select SND_DMAENGINE_PCM
|
||||||
|
|
||||||
# All the supported SoCs
|
# All the supported SoCs
|
||||||
source "sound/soc/atmel/Kconfig"
|
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-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
|
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),)
|
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
|
||||||
snd-soc-core-objs += soc-generic-dmaengine-pcm.o
|
snd-soc-core-objs += soc-generic-dmaengine-pcm.o
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -13,6 +13,7 @@ config SND_ATMEL_SOC_PDC
|
||||||
config SND_ATMEL_SOC_DMA
|
config SND_ATMEL_SOC_DMA
|
||||||
tristate
|
tristate
|
||||||
depends on SND_ATMEL_SOC
|
depends on SND_ATMEL_SOC
|
||||||
|
select SND_SOC_GENERIC_DMAENGINE_PCM
|
||||||
|
|
||||||
config SND_ATMEL_SOC_SSC
|
config SND_ATMEL_SOC_SSC
|
||||||
tristate
|
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
|
Say Y if you want to add support for SoC audio on WM8731-based
|
||||||
AT91sam9g20 evaluation board.
|
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
|
config SND_AT91_SOC_AFEB9260
|
||||||
tristate "SoC Audio support for AFEB9260 board"
|
tristate "SoC Audio support for AFEB9260 board"
|
||||||
depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC
|
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
|
# AT91 Machine Support
|
||||||
snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
|
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_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
|
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,
|
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 ssc_device *ssc;
|
||||||
struct dma_chan *dma_chan;
|
|
||||||
struct dma_slave_config slave_config;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||||
ssc = prtd->ssc;
|
ssc = prtd->ssc;
|
||||||
|
|
||||||
ret = snd_hwparams_to_dma_slave_config(substream, params,
|
ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config);
|
||||||
&slave_config);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("atmel-pcm: hwparams to dma slave configure failed\n");
|
pr_err("atmel-pcm: hwparams to dma slave configure failed\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
slave_config.dst_addr = (dma_addr_t)ssc->phybase + SSC_THR;
|
slave_config->dst_addr = ssc->phybase + SSC_THR;
|
||||||
slave_config.dst_maxburst = 1;
|
slave_config->dst_maxburst = 1;
|
||||||
} else {
|
} else {
|
||||||
slave_config.src_addr = (dma_addr_t)ssc->phybase + SSC_RHR;
|
slave_config->src_addr = ssc->phybase + SSC_RHR;
|
||||||
slave_config.src_maxburst = 1;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prtd->dma_intr_handler = atmel_pcm_dma_irq;
|
prtd->dma_intr_handler = atmel_pcm_dma_irq;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
|
||||||
snd_dmaengine_pcm_close_release_chan(substream);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream)
|
static const struct snd_dmaengine_pcm_config atmel_dmaengine_pcm_config = {
|
||||||
{
|
.prepare_slave_config = atmel_pcm_configure_dma,
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
.pcm_hardware = &atmel_pcm_dma_hardware,
|
||||||
struct atmel_pcm_dma_params *prtd;
|
.prealloc_buffer_size = ATMEL_SSC_DMABUF_SIZE,
|
||||||
|
|
||||||
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,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int atmel_pcm_dma_platform_register(struct device *dev)
|
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);
|
EXPORT_SYMBOL(atmel_pcm_dma_platform_register);
|
||||||
|
|
||||||
void atmel_pcm_dma_platform_unregister(struct device *dev)
|
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);
|
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_disable = SSC_BIT(CR_TXDIS),
|
||||||
.ssc_endx = SSC_BIT(SR_ENDTX),
|
.ssc_endx = SSC_BIT(SR_ENDTX),
|
||||||
.ssc_endbuf = SSC_BIT(SR_TXBUFE),
|
.ssc_endbuf = SSC_BIT(SR_TXBUFE),
|
||||||
|
.ssc_error = SSC_BIT(SR_OVRUN),
|
||||||
.pdc_enable = ATMEL_PDC_TXTEN,
|
.pdc_enable = ATMEL_PDC_TXTEN,
|
||||||
.pdc_disable = ATMEL_PDC_TXTDIS,
|
.pdc_disable = ATMEL_PDC_TXTDIS,
|
||||||
};
|
};
|
||||||
|
@ -82,6 +83,7 @@ static struct atmel_ssc_mask ssc_rx_mask = {
|
||||||
.ssc_disable = SSC_BIT(CR_RXDIS),
|
.ssc_disable = SSC_BIT(CR_RXDIS),
|
||||||
.ssc_endx = SSC_BIT(SR_ENDRX),
|
.ssc_endx = SSC_BIT(SR_ENDRX),
|
||||||
.ssc_endbuf = SSC_BIT(SR_RXBUFF),
|
.ssc_endbuf = SSC_BIT(SR_RXBUFF),
|
||||||
|
.ssc_error = SSC_BIT(SR_OVRUN),
|
||||||
.pdc_enable = ATMEL_PDC_RXTEN,
|
.pdc_enable = ATMEL_PDC_RXTEN,
|
||||||
.pdc_disable = ATMEL_PDC_RXTDIS,
|
.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 snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
|
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",
|
pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
|
||||||
ssc_readl(ssc_p->ssc->regs, SR));
|
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;
|
dir_mask = SSC_DIR_MASK_PLAYBACK;
|
||||||
else
|
} else {
|
||||||
|
dir = 1;
|
||||||
dir_mask = SSC_DIR_MASK_CAPTURE;
|
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);
|
spin_lock_irq(&ssc_p->lock);
|
||||||
if (ssc_p->dir_mask & dir_mask) {
|
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_pcm_hw_params *params,
|
||||||
struct snd_soc_dai *dai)
|
struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
|
|
||||||
int id = dai->id;
|
int id = dai->id;
|
||||||
struct atmel_ssc_info *ssc_p = &ssc_info[id];
|
struct atmel_ssc_info *ssc_p = &ssc_info[id];
|
||||||
struct atmel_pcm_dma_params *dma_params;
|
struct atmel_pcm_dma_params *dma_params;
|
||||||
|
@ -344,19 +357,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
||||||
else
|
else
|
||||||
dir = 1;
|
dir = 1;
|
||||||
|
|
||||||
dma_params = &ssc_dma_params[id][dir];
|
dma_params = ssc_p->dma_params[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);
|
|
||||||
|
|
||||||
channels = params_channels(params);
|
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];
|
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, CR, dma_params->mask->ssc_enable);
|
||||||
|
ssc_writel(ssc_p->ssc->regs, IER, dma_params->mask->ssc_error);
|
||||||
|
|
||||||
pr_debug("%s enabled SSC_SR=0x%08x\n",
|
pr_debug("%s enabled SSC_SR=0x%08x\n",
|
||||||
dir ? "receive" : "transmit",
|
dir ? "receive" : "transmit",
|
||||||
|
|
|
@ -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");
|
|
@ -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 = {
|
static struct snd_soc_card db1300_ac97_machine = {
|
||||||
.name = "DB1300_AC97",
|
.name = "DB1300_AC97",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
.dai_link = &db1300_ac97_dai,
|
.dai_link = &db1300_ac97_dai,
|
||||||
.num_links = 1,
|
.num_links = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_soc_card db1550_ac97_machine = {
|
static struct snd_soc_card db1550_ac97_machine = {
|
||||||
.name = "DB1550_AC97",
|
.name = "DB1550_AC97",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
.dai_link = &db1200_ac97_dai,
|
.dai_link = &db1200_ac97_dai,
|
||||||
.num_links = 1,
|
.num_links = 1,
|
||||||
};
|
};
|
||||||
|
@ -145,6 +147,7 @@ static struct snd_soc_dai_link db1300_i2s_dai = {
|
||||||
|
|
||||||
static struct snd_soc_card db1300_i2s_machine = {
|
static struct snd_soc_card db1300_i2s_machine = {
|
||||||
.name = "DB1300_I2S",
|
.name = "DB1300_I2S",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
.dai_link = &db1300_i2s_dai,
|
.dai_link = &db1300_i2s_dai,
|
||||||
.num_links = 1,
|
.num_links = 1,
|
||||||
};
|
};
|
||||||
|
@ -161,6 +164,7 @@ static struct snd_soc_dai_link db1550_i2s_dai = {
|
||||||
|
|
||||||
static struct snd_soc_card db1550_i2s_machine = {
|
static struct snd_soc_card db1550_i2s_machine = {
|
||||||
.name = "DB1550_I2S",
|
.name = "DB1550_I2S",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
.dai_link = &db1550_i2s_dai,
|
.dai_link = &db1550_i2s_dai,
|
||||||
.num_links = 1,
|
.num_links = 1,
|
||||||
};
|
};
|
||||||
|
|
|
@ -379,9 +379,6 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
|
||||||
mutex_init(&wd->lock);
|
mutex_init(&wd->lock);
|
||||||
|
|
||||||
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (!iores)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
wd->mmio = devm_ioremap_resource(&pdev->dev, iores);
|
wd->mmio = devm_ioremap_resource(&pdev->dev, iores);
|
||||||
if (IS_ERR(wd->mmio))
|
if (IS_ERR(wd->mmio))
|
||||||
return PTR_ERR(wd->mmio);
|
return PTR_ERR(wd->mmio);
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#ifndef _BF5XX_AC97_H
|
#ifndef _BF5XX_AC97_H
|
||||||
#define _BF5XX_AC97_H
|
#define _BF5XX_AC97_H
|
||||||
|
|
||||||
extern struct snd_ac97 *ac97;
|
|
||||||
/* Frame format in memory, only support stereo currently */
|
/* Frame format in memory, only support stereo currently */
|
||||||
struct ac97_frame {
|
struct ac97_frame {
|
||||||
u16 ac97_tag; /* slot 0 */
|
u16 ac97_tag; /* slot 0 */
|
||||||
|
|
|
@ -363,9 +363,6 @@ static int ep93xx_ac97_probe(struct platform_device *pdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (!res)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
info->regs = devm_ioremap_resource(&pdev->dev, res);
|
info->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||||
if (IS_ERR(info->regs))
|
if (IS_ERR(info->regs))
|
||||||
return PTR_ERR(info->regs);
|
return PTR_ERR(info->regs);
|
||||||
|
|
|
@ -376,9 +376,6 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (!res)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
info->regs = devm_ioremap_resource(&pdev->dev, res);
|
info->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||||
if (IS_ERR(info->regs))
|
if (IS_ERR(info->regs))
|
||||||
return PTR_ERR(info->regs);
|
return PTR_ERR(info->regs);
|
||||||
|
@ -411,7 +408,6 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_put_lrclk:
|
fail_put_lrclk:
|
||||||
dev_set_drvdata(&pdev->dev, NULL);
|
|
||||||
clk_put(info->lrclk);
|
clk_put(info->lrclk);
|
||||||
fail_put_sclk:
|
fail_put_sclk:
|
||||||
clk_put(info->sclk);
|
clk_put(info->sclk);
|
||||||
|
@ -426,7 +422,6 @@ static int ep93xx_i2s_remove(struct platform_device *pdev)
|
||||||
struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
|
struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
|
||||||
|
|
||||||
snd_soc_unregister_component(&pdev->dev);
|
snd_soc_unregister_component(&pdev->dev);
|
||||||
dev_set_drvdata(&pdev->dev, NULL);
|
|
||||||
clk_put(info->lrclk);
|
clk_put(info->lrclk);
|
||||||
clk_put(info->sclk);
|
clk_put(info->sclk);
|
||||||
clk_put(info->mclk);
|
clk_put(info->mclk);
|
||||||
|
|
|
@ -10,6 +10,7 @@ config SND_SOC_I2C_AND_SPI
|
||||||
|
|
||||||
config SND_SOC_ALL_CODECS
|
config SND_SOC_ALL_CODECS
|
||||||
tristate "Build all ASoC CODEC drivers"
|
tristate "Build all ASoC CODEC drivers"
|
||||||
|
depends on COMPILE_TEST
|
||||||
select SND_SOC_88PM860X if MFD_88PM860X
|
select SND_SOC_88PM860X if MFD_88PM860X
|
||||||
select SND_SOC_L3
|
select SND_SOC_L3
|
||||||
select SND_SOC_AB8500_CODEC if ABX500_CORE
|
select SND_SOC_AB8500_CODEC if ABX500_CORE
|
||||||
|
@ -20,6 +21,7 @@ config SND_SOC_ALL_CODECS
|
||||||
select SND_SOC_AD73311
|
select SND_SOC_AD73311
|
||||||
select SND_SOC_ADAU1373 if I2C
|
select SND_SOC_ADAU1373 if I2C
|
||||||
select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI
|
select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI
|
||||||
|
select SND_SOC_ADAU1701 if I2C
|
||||||
select SND_SOC_ADS117X
|
select SND_SOC_ADS117X
|
||||||
select SND_SOC_AK4104 if SPI_MASTER
|
select SND_SOC_AK4104 if SPI_MASTER
|
||||||
select SND_SOC_AK4535 if I2C
|
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_MC13783 if MFD_MC13XXX
|
||||||
select SND_SOC_ML26124 if I2C
|
select SND_SOC_ML26124 if I2C
|
||||||
select SND_SOC_HDMI_CODEC
|
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_PCM3008
|
||||||
select SND_SOC_RT5631 if I2C
|
select SND_SOC_RT5631 if I2C
|
||||||
select SND_SOC_RT5640 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_WM8994 if MFD_WM8994
|
||||||
select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI
|
select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI
|
||||||
select SND_SOC_WM8996 if I2C
|
select SND_SOC_WM8996 if I2C
|
||||||
|
select SND_SOC_WM8997 if MFD_WM8997
|
||||||
select SND_SOC_WM9081 if I2C
|
select SND_SOC_WM9081 if I2C
|
||||||
select SND_SOC_WM9090 if I2C
|
select SND_SOC_WM9090 if I2C
|
||||||
select SND_SOC_WM9705 if SND_SOC_AC97_BUS
|
select SND_SOC_WM9705 if SND_SOC_AC97_BUS
|
||||||
|
@ -145,8 +150,10 @@ config SND_SOC_ARIZONA
|
||||||
tristate
|
tristate
|
||||||
default y if SND_SOC_WM5102=y
|
default y if SND_SOC_WM5102=y
|
||||||
default y if SND_SOC_WM5110=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_WM5102=m
|
||||||
default m if SND_SOC_WM5110=m
|
default m if SND_SOC_WM5110=m
|
||||||
|
default m if SND_SOC_WM8997=m
|
||||||
|
|
||||||
config SND_SOC_WM_HUBS
|
config SND_SOC_WM_HUBS
|
||||||
tristate
|
tristate
|
||||||
|
@ -198,6 +205,9 @@ config SND_SOC_AK4104
|
||||||
config SND_SOC_AK4535
|
config SND_SOC_AK4535
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
|
config SND_SOC_AK4554
|
||||||
|
tristate
|
||||||
|
|
||||||
config SND_SOC_AK4641
|
config SND_SOC_AK4641
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
|
@ -292,6 +302,12 @@ config SND_SOC_MAX9850
|
||||||
config SND_SOC_HDMI_CODEC
|
config SND_SOC_HDMI_CODEC
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
|
config SND_SOC_PCM1681
|
||||||
|
tristate
|
||||||
|
|
||||||
|
config SND_SOC_PCM1792A
|
||||||
|
tristate
|
||||||
|
|
||||||
config SND_SOC_PCM3008
|
config SND_SOC_PCM3008
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
|
@ -500,6 +516,9 @@ config SND_SOC_WM8995
|
||||||
config SND_SOC_WM8996
|
config SND_SOC_WM8996
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
|
config SND_SOC_WM8997
|
||||||
|
tristate
|
||||||
|
|
||||||
config SND_SOC_WM9081
|
config SND_SOC_WM9081
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ snd-soc-adav80x-objs := adav80x.o
|
||||||
snd-soc-ads117x-objs := ads117x.o
|
snd-soc-ads117x-objs := ads117x.o
|
||||||
snd-soc-ak4104-objs := ak4104.o
|
snd-soc-ak4104-objs := ak4104.o
|
||||||
snd-soc-ak4535-objs := ak4535.o
|
snd-soc-ak4535-objs := ak4535.o
|
||||||
|
snd-soc-ak4554-objs := ak4554.o
|
||||||
snd-soc-ak4641-objs := ak4641.o
|
snd-soc-ak4641-objs := ak4641.o
|
||||||
snd-soc-ak4642-objs := ak4642.o
|
snd-soc-ak4642-objs := ak4642.o
|
||||||
snd-soc-ak4671-objs := ak4671.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-mc13783-objs := mc13783.o
|
||||||
snd-soc-ml26124-objs := ml26124.o
|
snd-soc-ml26124-objs := ml26124.o
|
||||||
snd-soc-hdmi-codec-objs := hdmi.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-pcm3008-objs := pcm3008.o
|
||||||
snd-soc-rt5631-objs := rt5631.o
|
snd-soc-rt5631-objs := rt5631.o
|
||||||
snd-soc-rt5640-objs := rt5640.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-wm8993-objs := wm8993.o
|
||||||
snd-soc-wm8994-objs := wm8994.o wm8958-dsp2.o
|
snd-soc-wm8994-objs := wm8994.o wm8958-dsp2.o
|
||||||
snd-soc-wm8995-objs := wm8995.o
|
snd-soc-wm8995-objs := wm8995.o
|
||||||
|
snd-soc-wm8997-objs := wm8997.o
|
||||||
snd-soc-wm9081-objs := wm9081.o
|
snd-soc-wm9081-objs := wm9081.o
|
||||||
snd-soc-wm9090-objs := wm9090.o
|
snd-soc-wm9090-objs := wm9090.o
|
||||||
snd-soc-wm9705-objs := wm9705.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_ADS117X) += snd-soc-ads117x.o
|
||||||
obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
|
obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
|
||||||
obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.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_AK4641) += snd-soc-ak4641.o
|
||||||
obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
|
obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
|
||||||
obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.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_MC13783) += snd-soc-mc13783.o
|
||||||
obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.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_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_PCM3008) += snd-soc-pcm3008.o
|
||||||
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
|
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
|
||||||
obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.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_WM8993) += snd-soc-wm8993.o
|
||||||
obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o
|
obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o
|
||||||
obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.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_WM9081) += snd-soc-wm9081.o
|
||||||
obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o
|
obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o
|
||||||
obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
|
obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
|
||||||
|
|
|
@ -23,6 +23,16 @@
|
||||||
#include <sound/initval.h>
|
#include <sound/initval.h>
|
||||||
#include <sound/soc.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,
|
static int ac97_prepare(struct snd_pcm_substream *substream,
|
||||||
struct snd_soc_dai *dai)
|
struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
|
@ -117,6 +127,11 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
|
||||||
.probe = ac97_soc_probe,
|
.probe = ac97_soc_probe,
|
||||||
.suspend = ac97_soc_suspend,
|
.suspend = ac97_soc_suspend,
|
||||||
.resume = ac97_soc_resume,
|
.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)
|
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),
|
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,
|
static unsigned int ac97_read(struct snd_soc_codec *codec,
|
||||||
unsigned int reg)
|
unsigned int reg)
|
||||||
{
|
{
|
||||||
|
@ -253,6 +291,11 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
|
||||||
.reg_cache_step = 2,
|
.reg_cache_step = 2,
|
||||||
.write = ac97_write,
|
.write = ac97_write,
|
||||||
.read = ac97_read,
|
.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)
|
static int ad1980_probe(struct platform_device *pdev)
|
||||||
|
|
|
@ -23,6 +23,21 @@
|
||||||
|
|
||||||
#include "ad73311.h"
|
#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 = {
|
static struct snd_soc_dai_driver ad73311_dai = {
|
||||||
.name = "ad73311-hifi",
|
.name = "ad73311-hifi",
|
||||||
.playback = {
|
.playback = {
|
||||||
|
@ -39,7 +54,12 @@ static struct snd_soc_dai_driver ad73311_dai = {
|
||||||
.formats = SNDRV_PCM_FMTBIT_S16_LE, },
|
.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)
|
static int ad73311_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,7 +91,7 @@
|
||||||
#define ADAU1701_OSCIPOW_OPD 0x04
|
#define ADAU1701_OSCIPOW_OPD 0x04
|
||||||
#define ADAU1701_DACSET_DACINIT 1
|
#define ADAU1701_DACSET_DACINIT 1
|
||||||
|
|
||||||
#define ADAU1707_CLKDIV_UNSET (-1UL)
|
#define ADAU1707_CLKDIV_UNSET (-1U)
|
||||||
|
|
||||||
#define ADAU1701_FIRMWARE "adau1701.bin"
|
#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])) {
|
gpio_is_valid(adau1701->gpio_pll_mode[1])) {
|
||||||
switch (clkdiv) {
|
switch (clkdiv) {
|
||||||
case 64:
|
case 64:
|
||||||
gpio_set_value(adau1701->gpio_pll_mode[0], 0);
|
gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 0);
|
||||||
gpio_set_value(adau1701->gpio_pll_mode[1], 0);
|
gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 0);
|
||||||
break;
|
break;
|
||||||
case 256:
|
case 256:
|
||||||
gpio_set_value(adau1701->gpio_pll_mode[0], 0);
|
gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 0);
|
||||||
gpio_set_value(adau1701->gpio_pll_mode[1], 1);
|
gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 1);
|
||||||
break;
|
break;
|
||||||
case 384:
|
case 384:
|
||||||
gpio_set_value(adau1701->gpio_pll_mode[0], 1);
|
gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 1);
|
||||||
gpio_set_value(adau1701->gpio_pll_mode[1], 0);
|
gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 0);
|
||||||
break;
|
break;
|
||||||
case 0: /* fallback */
|
case 0: /* fallback */
|
||||||
case 512:
|
case 512:
|
||||||
gpio_set_value(adau1701->gpio_pll_mode[0], 1);
|
gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 1);
|
||||||
gpio_set_value(adau1701->gpio_pll_mode[1], 1);
|
gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -269,10 +269,10 @@ static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv)
|
||||||
adau1701->pll_clkdiv = clkdiv;
|
adau1701->pll_clkdiv = clkdiv;
|
||||||
|
|
||||||
if (gpio_is_valid(adau1701->gpio_nreset)) {
|
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 */
|
/* minimum reset time is 20ns */
|
||||||
udelay(1);
|
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 */
|
/* power-up time may be as long as 85ms */
|
||||||
mdelay(85);
|
mdelay(85);
|
||||||
}
|
}
|
||||||
|
@ -734,7 +734,10 @@ static int adau1701_i2c_remove(struct i2c_client *client)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct i2c_device_id adau1701_i2c_id[] = {
|
static const struct i2c_device_id adau1701_i2c_id[] = {
|
||||||
|
{ "adau1401", 0 },
|
||||||
|
{ "adau1401a", 0 },
|
||||||
{ "adau1701", 0 },
|
{ "adau1701", 0 },
|
||||||
|
{ "adau1702", 0 },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id);
|
MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id);
|
||||||
|
|
|
@ -868,6 +868,12 @@ static int adav80x_bus_remove(struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_SPI_MASTER)
|
#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)
|
static int adav80x_spi_probe(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
return adav80x_bus_probe(&spi->dev, SND_SOC_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,
|
.probe = adav80x_spi_probe,
|
||||||
.remove = adav80x_spi_remove,
|
.remove = adav80x_spi_remove,
|
||||||
|
.id_table = adav80x_spi_id,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
#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 },
|
{ "adav803", 0 },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, adav80x_id);
|
MODULE_DEVICE_TABLE(i2c, adav80x_i2c_id);
|
||||||
|
|
||||||
static int adav80x_i2c_probe(struct i2c_client *client,
|
static int adav80x_i2c_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
|
@ -913,7 +920,7 @@ static struct i2c_driver adav80x_i2c_driver = {
|
||||||
},
|
},
|
||||||
.probe = adav80x_i2c_probe,
|
.probe = adav80x_i2c_probe,
|
||||||
.remove = adav80x_i2c_remove,
|
.remove = adav80x_i2c_remove,
|
||||||
.id_table = adav80x_id,
|
.id_table = adav80x_i2c_id,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,28 @@
|
||||||
#define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000)
|
#define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000)
|
||||||
#define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
|
#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 = {
|
static struct snd_soc_dai_driver ads117x_dai = {
|
||||||
/* ADC */
|
/* ADC */
|
||||||
.name = "ads117x-hifi",
|
.name = "ads117x-hifi",
|
||||||
|
@ -34,7 +56,12 @@ static struct snd_soc_dai_driver ads117x_dai = {
|
||||||
.formats = ADS117X_FORMATS,},
|
.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)
|
static int ads117x_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,6 +51,17 @@ struct ak4104_private {
|
||||||
struct regmap *regmap;
|
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,
|
static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||||
unsigned int format)
|
unsigned int format)
|
||||||
{
|
{
|
||||||
|
@ -138,29 +149,11 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
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;
|
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 = {
|
static const struct snd_soc_dai_ops ak4101_dai_ops = {
|
||||||
.hw_params = ak4104_hw_params,
|
.hw_params = ak4104_hw_params,
|
||||||
.hw_free = ak4104_hw_free,
|
|
||||||
.set_fmt = ak4104_set_dai_fmt,
|
.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 = {
|
static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
|
||||||
.probe = ak4104_probe,
|
.probe = ak4104_probe,
|
||||||
.remove = ak4104_remove,
|
.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 = {
|
static const struct regmap_config ak4104_regmap = {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue