Merge branch 'asoc-4.19' into asoc-next

This commit is contained in:
Mark Brown 2018-08-09 14:47:05 +01:00
commit 4aa5db22d3
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
312 changed files with 15510 additions and 4310 deletions

View File

@ -0,0 +1,23 @@
* Amlogic Audio FIFO controllers
Required properties:
- compatible: 'amlogic,axg-toddr' or
'amlogic,axg-frddr'
- reg: physical base address of the controller and length of memory
mapped region.
- interrupts: interrupt specifier for the fifo.
- clocks: phandle to the fifo peripheral clock provided by the audio
clock controller.
- resets: phandle to memory ARB line provided by the arb reset controller.
- #sound-dai-cells: must be 0.
Example of FRDDR A on the A113 SoC:
frddr_a: audio-controller@1c0 {
compatible = "amlogic,axg-frddr";
reg = <0x0 0x1c0 0x0 0x1c>;
#sound-dai-cells = <0>;
interrupts = <GIC_SPI 88 IRQ_TYPE_EDGE_RISING>;
clocks = <&clkc_audio AUD_CLKID_FRDDR_A>;
resets = <&arb AXG_ARB_FRDDR_A>;
};

View File

@ -0,0 +1,124 @@
Amlogic AXG sound card:
Required properties:
- compatible: "amlogic,axg-sound-card"
- model : User specified audio sound card name, one string
Optional properties:
- audio-aux-devs : List of phandles pointing to auxiliary devices
- audio-widgets : Please refer to widgets.txt.
- audio-routing : A list of the connections between audio components.
Subnodes:
- dai-link: Container for dai-link level properties and the CODEC
sub-nodes. There should be at least one (and probably more)
subnode of this type.
Required dai-link properties:
- sound-dai: phandle and port of the CPU DAI.
Required TDM Backend dai-link properties:
- dai-format : CPU/CODEC common audio format
Optional TDM Backend dai-link properties:
- dai-tdm-slot-rx-mask-{0,1,2,3}: Receive direction slot masks
- dai-tdm-slot-tx-mask-{0,1,2,3}: Transmit direction slot masks
When omitted, mask is assumed to have to no
slots. A valid must have at one slot, so at
least one these mask should be provided with
an enabled slot.
- dai-tdm-slot-num : Please refer to tdm-slot.txt.
If omitted, slot number is set to accommodate the largest
mask provided.
- dai-tdm-slot-width : Please refer to tdm-slot.txt. default to 32 if omitted.
- mclk-fs : Multiplication factor between stream rate and mclk
Backend dai-link subnodes:
- codec: dai-link representing backend links should have at least one subnode.
One subnode for each codec of the dai-link.
dai-link representing frontend links have no codec, therefore have no
subnodes
Required codec subnodes properties:
- sound-dai: phandle and port of the CODEC DAI.
Optional codec subnodes properties:
- dai-tdm-slot-tx-mask : Please refer to tdm-slot.txt.
- dai-tdm-slot-rx-mask : Please refer to tdm-slot.txt.
Example:
sound {
compatible = "amlogic,axg-sound-card";
model = "AXG-S420";
audio-aux-devs = <&tdmin_a>, <&tdmout_c>;
audio-widgets = "Line", "Lineout",
"Line", "Linein",
"Speaker", "Speaker1 Left",
"Speaker", "Speaker1 Right";
"Speaker", "Speaker2 Left",
"Speaker", "Speaker2 Right";
audio-routing = "TDMOUT_C IN 0", "FRDDR_A OUT 2",
"SPDIFOUT IN 0", "FRDDR_A OUT 3",
"TDM_C Playback", "TDMOUT_C OUT",
"TDMIN_A IN 2", "TDM_C Capture",
"TDMIN_A IN 5", "TDM_C Loopback",
"TODDR_A IN 0", "TDMIN_A OUT",
"Lineout", "Lineout AOUTL",
"Lineout", "Lineout AOUTR",
"Speaker1 Left", "SPK1 OUT_A",
"Speaker2 Left", "SPK2 OUT_A",
"Speaker1 Right", "SPK1 OUT_B",
"Speaker2 Right", "SPK2 OUT_B",
"Linein AINL", "Linein",
"Linein AINR", "Linein";
dai-link@0 {
sound-dai = <&frddr_a>;
};
dai-link@1 {
sound-dai = <&toddr_a>;
};
dai-link@2 {
sound-dai = <&tdmif_c>;
dai-format = "i2s";
dai-tdm-slot-tx-mask-2 = <1 1>;
dai-tdm-slot-tx-mask-3 = <1 1>;
dai-tdm-slot-rx-mask-1 = <1 1>;
mclk-fs = <256>;
codec@0 {
sound-dai = <&lineout>;
};
codec@1 {
sound-dai = <&speaker_amp1>;
};
codec@2 {
sound-dai = <&speaker_amp2>;
};
codec@3 {
sound-dai = <&linein>;
};
};
dai-link@3 {
sound-dai = <&spdifout>;
codec {
sound-dai = <&spdif_dit>;
};
};
};

View File

@ -0,0 +1,20 @@
* Amlogic Audio SPDIF Output
Required properties:
- compatible: 'amlogic,axg-spdifout'
- clocks: list of clock phandle, one for each entry clock-names.
- clock-names: should contain the following:
* "pclk" : peripheral clock.
* "mclk" : master clock
- #sound-dai-cells: must be 0.
Example on the A113 SoC:
spdifout: audio-controller@480 {
compatible = "amlogic,axg-spdifout";
reg = <0x0 0x480 0x0 0x50>;
#sound-dai-cells = <0>;
clocks = <&clkc_audio AUD_CLKID_SPDIFOUT>,
<&clkc_audio AUD_CLKID_SPDIFOUT_CLK>;
clock-names = "pclk", "mclk";
};

View File

@ -0,0 +1,28 @@
* Amlogic Audio TDM formatters
Required properties:
- compatible: 'amlogic,axg-tdmin' or
'amlogic,axg-tdmout'
- reg: physical base address of the controller and length of memory
mapped region.
- clocks: list of clock phandle, one for each entry clock-names.
- clock-names: should contain the following:
* "pclk" : peripheral clock.
* "sclk" : bit clock.
* "sclk_sel" : bit clock input multiplexer.
* "lrclk" : sample clock
* "lrclk_sel": sample clock input multiplexer
Example of TDMOUT_A on the A113 SoC:
tdmout_a: audio-controller@500 {
compatible = "amlogic,axg-tdmout";
reg = <0x0 0x500 0x0 0x40>;
clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>,
<&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>,
<&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>,
<&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>,
<&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>;
clock-names = "pclk", "sclk", "sclk_sel",
"lrclk", "lrclk_sel";
};

View File

@ -0,0 +1,22 @@
* Amlogic Audio TDM Interfaces
Required properties:
- compatible: 'amlogic,axg-tdm-iface'
- clocks: list of clock phandle, one for each entry clock-names.
- clock-names: should contain the following:
* "sclk" : bit clock.
* "lrclk": sample clock
* "mclk" : master clock
-> optional if the interface is in clock slave mode.
- #sound-dai-cells: must be 0.
Example of TDM_A on the A113 SoC:
tdmif_a: audio-controller@0 {
compatible = "amlogic,axg-tdm-iface";
#sound-dai-cells = <0>;
clocks = <&clkc_audio AUD_CLKID_MST_A_MCLK>,
<&clkc_audio AUD_CLKID_MST_A_SCLK>,
<&clkc_audio AUD_CLKID_MST_A_LRCLK>;
clock-names = "mclk", "sclk", "lrclk";
};

View File

@ -15,7 +15,6 @@ Required properties:
- clock-names: Should be one of each entry matching the clocks phandles list:
- "pclk" (peripheral clock) Required.
- "gclk" (generated clock) Optional (1).
- "aclk" (Audio PLL clock) Optional (1).
- "muxclk" (I2S mux clock) Optional (1).
Optional properties:
@ -23,9 +22,9 @@ Optional properties:
- princtrl-names: Should contain only one value - "default".
(1) : Only the peripheral clock is required. The generated clock, the Audio
PLL clock adn the I2S mux clock are optional and should only be set
together, when Master Mode is required.
(1) : Only the peripheral clock is required. The generated clock and the I2S
mux clock are optional and should only be set together, when Master Mode
is required.
Example:
@ -40,8 +39,8 @@ Example:
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
AT91_XDMAC_DT_PERID(32))>;
dma-names = "tx", "rx";
clocks = <&i2s0_clk>, <&i2s0_gclk>, <&audio_pll_pmc>, <&i2s0muxck>;
clock-names = "pclk", "gclk", "aclk", "muxclk";
clocks = <&i2s0_clk>, <&i2s0_gclk>, <&i2s0muxck>;
clock-names = "pclk", "gclk", "muxclk";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2s0_default>;
};

View File

@ -18,6 +18,8 @@ Below are same as Simple-Card.
- bitclock-inversion
- frame-inversion
- mclk-fs
- hp-det-gpio
- mic-det-gpio
- dai-tdm-slot-num
- dai-tdm-slot-width
- clocks / system-clock-frequency

View File

@ -1,12 +0,0 @@
DIO2125 Audio Driver
Required properties:
- compatible : "dioo,dio2125"
- enable-gpios : the gpio connected to the enable pin of the dio2125
Example:
amp: analog-amplifier {
compatible = "dioo,dio2125";
enable-gpios = <&gpio GPIOH_3 0>;
};

View File

@ -1,10 +1,15 @@
ES7134 i2s DA converter
Required properties:
- compatible : "everest,es7134" or "everest,es7144"
- compatible : "everest,es7134" or
"everest,es7144" or
"everest,es7154"
- VDD-supply : regulator phandle for the VDD supply
- PVDD-supply: regulator phandle for the PVDD supply for the es7154
Example:
i2s_codec: external-codec {
compatible = "everest,es7134";
VDD-supply = <&vcc_5v>;
};

View File

@ -0,0 +1,28 @@
ES7241 i2s AD converter
Required properties:
- compatible : "everest,es7241"
- VDDP-supply: regulator phandle for the VDDA supply
- VDDA-supply: regulator phandle for the VDDP supply
- VDDD-supply: regulator phandle for the VDDD supply
Optional properties:
- reset-gpios: gpio connected to the reset pin
- m0-gpios : gpio connected to the m0 pin
- m1-gpios : gpio connected to the m1 pin
- everest,sdout-pull-down:
Format used by the serial interface is controlled by pulling
the sdout. If the sdout is pulled down, leftj format is used.
If this property is not provided, sdout is assumed to pulled
up and i2s format is used
Example:
linein: audio-codec@2 {
#sound-dai-cells = <0>;
compatible = "everest,es7241";
VDDA-supply = <&vcc_3v3>;
VDDP-supply = <&vcc_3v3>;
VDDD-supply = <&vcc_3v3>;
reset-gpios = <&gpio GPIOH_42>;
};

View File

@ -0,0 +1,27 @@
Marvell PXA2xx audio complex
This descriptions matches the AC97 controller found in pxa2xx and pxa3xx series.
Required properties:
- compatible: should be one of the following:
"marvell,pxa250-ac97"
"marvell,pxa270-ac97"
"marvell,pxa300-ac97"
- reg: device MMIO address space
- interrupts: single interrupt generated by AC97 IP
- clocks: input clock of the AC97 IP, refer to clock-bindings.txt
Optional properties:
- pinctrl-names, pinctrl-0: refer to pinctrl-bindings.txt
- reset-gpios: gpio used for AC97 reset, refer to gpio.txt
Example:
ac97: sound@40500000 {
compatible = "marvell,pxa250-ac97";
reg = < 0x40500000 0x1000 >;
interrupts = <14>;
reset-gpios = <&gpio 113 GPIO_ACTIVE_HIGH>;
#sound-dai-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = < &pmux_ac97_default >;
};

View File

@ -5,6 +5,14 @@ Required properties:
compatible Must be "mrvl,pxa-ssp-dai"
port A phandle reference to a PXA ssp upstream device
Optional properties:
clock-names
clocks Through "clock-names" and "clocks", external clocks
can be configured. If a clock names "extclk" exists,
it will be set to the mclk rate of the audio stream
and be used as clock provider of the DAI.
Example:
/* upstream device */

View File

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

View File

@ -0,0 +1,24 @@
Name prefix:
Card implementing the routing property define the connection between
audio components as list of string pair. Component using the same
sink/source names may use the name prefix property to prepend the
name of their sinks/sources with the provided string.
Optional name prefix property:
- sound-name-prefix : string using as prefix for the sink/source names of
the component.
Example: Two instances of the same component.
amp0: analog-amplifier@0 {
compatible = "simple-audio-amplifier";
enable-gpios = <&gpio GPIOH_3 0>;
sound-name-prefix = "FRONT";
};
amp1: analog-amplifier@1 {
compatible = "simple-audio-amplifier";
enable-gpios = <&gpio GPIOH_4 0>;
sound-name-prefix = "BACK";
};

View File

@ -7,7 +7,7 @@ This binding describes the APQ8096 sound card, which uses qdsp for audio.
Value type: <stringlist>
Definition: must be "qcom,apq8096-sndcard"
- qcom,audio-routing:
- audio-routing:
Usage: Optional
Value type: <stringlist>
Definition: A list of the connections between audio components.
@ -49,6 +49,12 @@ This binding describes the APQ8096 sound card, which uses qdsp for audio.
"DMIC1"
"DMIC2"
"DMIC3"
- model:
Usage: required
Value type: <stringlist>
Definition: The user-visible name of this sound card.
= dailinks
Each subnode of sndcard represents either a dailink, and subnodes of each
dailinks would be cpu/codec/platform dais.
@ -79,11 +85,16 @@ dailinks would be cpu/codec/platform dais.
Value type: <phandle with arguments>
Definition: dai phandle/s and port of CPU/CODEC/PLATFORM node.
Obsolete:
qcom,model: String for soundcard name (Use model instead)
qcom,audio-routing: A list of the connections between audio components.
(Use audio-routing instead)
Example:
audio {
compatible = "qcom,apq8096-sndcard";
qcom,model = "DB820c";
model = "DB820c";
mm1-dai-link {
link-name = "MultiMedia1";

View File

@ -18,6 +18,11 @@ used by the apr service device.
= ADM routing
"routing" subnode of the ADM node represents adm routing specific configuration
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,q6adm-routing".
- #sound-dai-cells
Usage: required
Value type: <u32>
@ -28,6 +33,7 @@ q6adm@8 {
compatible = "qcom,q6adm";
reg = <APR_SVC_ADM>;
q6routing: routing {
compatible = "qcom,q6adm-routing";
#sound-dai-cells = <0>;
};
};

View File

@ -17,6 +17,11 @@ used by all apr services. Must contain the following properties.
subnode of "dais" representing board specific dai setup.
"dais" node should have following properties followed by dai children.
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,q6afe-dais"
- #sound-dai-cells
Usage: required
Value type: <u32>
@ -100,6 +105,7 @@ q6afe@4 {
reg = <APR_SVC_AFE>;
dais {
compatible = "qcom,q6afe-dais";
#sound-dai-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -17,6 +17,11 @@ used by the apr service device.
= ASM DAIs (Digial Audio Interface)
"dais" subnode of the ASM node represents dai specific configuration
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,q6asm-dais".
- #sound-dai-cells
Usage: required
Value type: <u32>
@ -28,6 +33,7 @@ q6asm@7 {
compatible = "qcom,q6asm";
reg = <APR_SVC_ASM>;
q6asmdai: dais {
compatible = "qcom,q6asm-dais";
#sound-dai-cells = <1>;
};
};

View File

@ -0,0 +1,80 @@
* Qualcomm Technologies Inc. SDM845 ASoC sound card driver
This binding describes the SDM845 sound card, which uses qdsp for audio.
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,sdm845-sndcard"
- audio-routing:
Usage: Optional
Value type: <stringlist>
Definition: 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 could be power supplies, MicBias
of codec and the jacks on the board.
- model:
Usage: required
Value type: <stringlist>
Definition: The user-visible name of this sound card.
= dailinks
Each subnode of sndcard represents either a dailink, and subnodes of each
dailinks would be cpu/codec/platform dais.
- link-name:
Usage: required
Value type: <string>
Definition: User friendly name for dai link
= CPU, PLATFORM, CODEC dais subnodes
- cpu:
Usage: required
Value type: <subnode>
Definition: cpu dai sub-node
- codec:
Usage: required
Value type: <subnode>
Definition: codec dai sub-node
- platform:
Usage: Optional
Value type: <subnode>
Definition: platform dai sub-node
- sound-dai:
Usage: required
Value type: <phandle>
Definition: dai phandle/s and port of CPU/CODEC/PLATFORM node.
Example:
audio {
compatible = "qcom,sdm845-sndcard";
model = "sdm845-snd-card";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&pri_mi2s_active &pri_mi2s_ws_active>;
pinctrl-1 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep>;
mm1-dai-link {
link-name = "MultiMedia1";
cpu {
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
};
};
pri-mi2s-dai-link {
link-name = "PRI MI2S Playback";
cpu {
sound-dai = <&q6afedai PRIMARY_MI2S_RX>;
};
platform {
sound-dai = <&q6routing>;
};
};
};

View File

@ -0,0 +1,123 @@
QCOM WCD9335 Codec
Qualcomm WCD9335 Codec is a standalone Hi-Fi audio codec IC, supports
Qualcomm Technologies, Inc. (QTI) multimedia solutions, including
the MSM8996, MSM8976, and MSM8956 chipsets. It has in-built
Soundwire controller, interrupt mux. It supports both I2S/I2C and
SLIMbus audio interfaces.
Required properties with SLIMbus Interface:
- compatible:
Usage: required
Value type: <stringlist>
Definition: For SLIMbus interface it should be "slimMID,PID",
textual representation of Manufacturer ID, Product Code,
shall be in lower case hexadecimal with leading zeroes
suppressed. Refer to slimbus/bus.txt for details.
Should be:
"slim217,1a0" for MSM8996 and APQ8096 SoCs with SLIMbus.
- reg
Usage: required
Value type: <u32 u32>
Definition: Should be ('Device index', 'Instance ID')
- interrupts
Usage: required
Value type: <prop-encoded-array>
Definition: Interrupts via WCD INTR1 and INTR2 pins
- interrupt-names:
Usage: required
Value type: <String array>
Definition: Interrupt names of WCD INTR1 and INTR2
Should be: "intr1", "intr2"
- reset-gpio:
Usage: required
Value type: <String Array>
Definition: Reset gpio line
- qcom,ifd:
Usage: required
Value type: <phandle>
Definition: SLIM interface device
- clocks:
Usage: required
Value type: <prop-encoded-array>
Definition: See clock-bindings.txt section "consumers". List of
three clock specifiers for mclk, mclk2 and slimbus clock.
- clock-names:
Usage: required
Value type: <string>
Definition: Must contain "mclk", "mclk2" and "slimbus" strings.
- vdd-buck-supply:
Usage: required
Value type: <phandle>
Definition: Should contain a reference to the 1.8V buck supply
- vdd-buck-sido-supply:
Usage: required
Value type: <phandle>
Definition: Should contain a reference to the 1.8V SIDO buck supply
- vdd-rx-supply:
Usage: required
Value type: <phandle>
Definition: Should contain a reference to the 1.8V rx supply
- vdd-tx-supply:
Usage: required
Value type: <phandle>
Definition: Should contain a reference to the 1.8V tx supply
- vdd-vbat-supply:
Usage: Optional
Value type: <phandle>
Definition: Should contain a reference to the vbat supply
- vdd-micbias-supply:
Usage: required
Value type: <phandle>
Definition: Should contain a reference to the micbias supply
- vdd-io-supply:
Usage: required
Value type: <phandle>
Definition: Should contain a reference to the 1.8V io supply
- interrupt-controller:
Usage: required
Definition: Indicating that this is a interrupt controller
- #interrupt-cells:
Usage: required
Value type: <int>
Definition: should be 1
#sound-dai-cells
Usage: required
Value type: <u32>
Definition: Must be 1
codec@1{
compatible = "slim217,1a0";
reg = <1 0>;
interrupts = <&msmgpio 54 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "intr2"
reset-gpio = <&msmgpio 64 0>;
qcom,ifd = <&wc9335_ifd>;
clock-names = "mclk", "native";
clocks = <&rpmcc RPM_SMD_DIV_CLK1>,
<&rpmcc RPM_SMD_BB_CLK1>;
vdd-buck-supply = <&pm8994_s4>;
vdd-rx-supply = <&pm8994_s4>;
vdd-buck-sido-supply = <&pm8994_s4>;
vdd-tx-supply = <&pm8994_s4>;
vdd-io-supply = <&pm8994_s4>;
#sound-dai-cells = <1>;
}

View File

@ -352,6 +352,7 @@ Required properties:
- "renesas,rcar_sound-r8a7794" (R-Car E2)
- "renesas,rcar_sound-r8a7795" (R-Car H3)
- "renesas,rcar_sound-r8a7796" (R-Car M3-W)
- "renesas,rcar_sound-r8a77965" (R-Car M3-N)
- reg : Should contain the register physical address.
required register is
SRU/ADG/SSI if generation1

View File

@ -7,6 +7,7 @@ Required properties:
- compatible: should be one of the following:
- "rockchip,rk3066-i2s": for rk3066
- "rockchip,px30-i2s", "rockchip,rk3066-i2s": for px30
- "rockchip,rk3036-i2s", "rockchip,rk3066-i2s": for rk3036
- "rockchip,rk3188-i2s", "rockchip,rk3066-i2s": for rk3188
- "rockchip,rk3228-i2s", "rockchip,rk3066-i2s": for rk3228

View File

@ -0,0 +1,50 @@
RT5682 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "realtek,rt5682" or "realtek,rt5682i"
- reg : The I2C address of the device.
Optional properties:
- interrupts : The CODEC's interrupt output.
- realtek,dmic1-data-pin
0: dmic1 is not used
1: using GPIO2 pin as dmic1 data pin
2: using GPIO5 pin as dmic1 data pin
- realtek,dmic1-clk-pin
0: using GPIO1 pin as dmic1 clock pin
1: using GPIO3 pin as dmic1 clock pin
- realtek,jd-src
0: No JD is used
1: using JD1 as JD source
- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
Pins on the device (for linking into audio routes) for RT5682:
* DMIC L1
* DMIC R1
* IN1P
* HPOL
* HPOR
Example:
rt5682 {
compatible = "realtek,rt5682i";
reg = <0x1a>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(U, 6) GPIO_ACTIVE_HIGH>;
realtek,ldo1-en-gpios =
<&gpio TEGRA_GPIO(R, 2) GPIO_ACTIVE_HIGH>;
realtek,dmic1-data-pin = <1>;
realtek,dmic1-clk-pin = <1>;
realtek,jd-src = <1>;
};

View File

@ -17,7 +17,7 @@ Optional properties:
- VDDD-supply : the regulator provider of VDDD
- micbias-resistor-k-ohms : the bias resistor to be used in kOmhs
- micbias-resistor-k-ohms : the bias resistor to be used in kOhms
The resistor can take values of 2k, 4k or 8k.
If set to 0 it will be off.
If this node is not mentioned or if the value is unknown, then

View File

@ -0,0 +1,12 @@
Simple Amplifier Audio Driver
Required properties:
- compatible : "dioo,dio2125" or "simple-audio-amplifier"
- enable-gpios : the gpio connected to the enable pin of the simple amplifier
Example:
amp: analog-amplifier {
compatible = "simple-audio-amplifier";
enable-gpios = <&gpio GPIOH_3 0>;
};

View File

@ -7,6 +7,7 @@ powerdown (optional).
Required properties:
- compatible: should be one of the following:
- "ti,tas5707"
- "ti,tas5711",
- "ti,tas5717",
- "ti,tas5719",

View File

@ -254,9 +254,7 @@ configuration.
channels->min = channels->max = 2;
/* set DAI0 to 16 bit */
snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
SNDRV_PCM_HW_PARAM_FIRST_MASK],
SNDRV_PCM_FORMAT_S16_LE);
params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
return 0;
}

View File

@ -13575,6 +13575,13 @@ L: linux-block@vger.kernel.org
S: Maintained
F: drivers/block/skd*[ch]
STI AUDIO (ASoC) DRIVERS
M: Arnaud Pouliquen <arnaud.pouliquen@st.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt
F: sound/soc/sti/
STI CEC DRIVER
M: Benjamin Gaignard <benjamin.gaignard@linaro.org>
S: Maintained
@ -13588,6 +13595,14 @@ T: git git://linuxtv.org/media_tree.git
S: Maintained
F: drivers/media/usb/stk1160/
STM32 AUDIO (ASoC) DRIVERS
M: Olivier Moysan <olivier.moysan@st.com>
M: Arnaud Pouliquen <arnaud.pouliquen@st.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/sound/st,stm32-*.txt
F: sound/soc/stm/
STM32 TIMER/LPTIMER DRIVERS
M: Fabrice Gasnier <fabrice.gasnier@st.com>
S: Maintained

View File

@ -4,6 +4,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/spi/pxa2xx_spi.h>
#include <linux/platform_data/i2c-pxa.h>
@ -59,16 +60,6 @@ static struct resource pxamci_resources[] = {
.end = IRQ_MMC,
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = 21,
.end = 21,
.flags = IORESOURCE_DMA,
},
[3] = {
.start = 22,
.end = 22,
.flags = IORESOURCE_DMA,
},
};
static u64 pxamci_dmamask = 0xffffffffUL;
@ -406,16 +397,6 @@ static struct resource pxa_ir_resources[] = {
.end = 0x40700023,
.flags = IORESOURCE_MEM,
},
[5] = {
.start = 17,
.end = 17,
.flags = IORESOURCE_DMA,
},
[6] = {
.start = 18,
.end = 18,
.flags = IORESOURCE_DMA,
},
};
struct platform_device pxa_device_ficp = {
@ -544,18 +525,6 @@ static struct resource pxa25x_resource_ssp[] = {
.end = IRQ_SSP,
.flags = IORESOURCE_IRQ,
},
[2] = {
/* DRCMR for RX */
.start = 13,
.end = 13,
.flags = IORESOURCE_DMA,
},
[3] = {
/* DRCMR for TX */
.start = 14,
.end = 14,
.flags = IORESOURCE_DMA,
},
};
struct platform_device pxa25x_device_ssp = {
@ -582,18 +551,6 @@ static struct resource pxa25x_resource_nssp[] = {
.end = IRQ_NSSP,
.flags = IORESOURCE_IRQ,
},
[2] = {
/* DRCMR for RX */
.start = 15,
.end = 15,
.flags = IORESOURCE_DMA,
},
[3] = {
/* DRCMR for TX */
.start = 16,
.end = 16,
.flags = IORESOURCE_DMA,
},
};
struct platform_device pxa25x_device_nssp = {
@ -620,18 +577,6 @@ static struct resource pxa25x_resource_assp[] = {
.end = IRQ_ASSP,
.flags = IORESOURCE_IRQ,
},
[2] = {
/* DRCMR for RX */
.start = 23,
.end = 23,
.flags = IORESOURCE_DMA,
},
[3] = {
/* DRCMR for TX */
.start = 24,
.end = 24,
.flags = IORESOURCE_DMA,
},
};
struct platform_device pxa25x_device_assp = {
@ -750,18 +695,6 @@ static struct resource pxa27x_resource_ssp1[] = {
.end = IRQ_SSP,
.flags = IORESOURCE_IRQ,
},
[2] = {
/* DRCMR for RX */
.start = 13,
.end = 13,
.flags = IORESOURCE_DMA,
},
[3] = {
/* DRCMR for TX */
.start = 14,
.end = 14,
.flags = IORESOURCE_DMA,
},
};
struct platform_device pxa27x_device_ssp1 = {
@ -788,18 +721,6 @@ static struct resource pxa27x_resource_ssp2[] = {
.end = IRQ_SSP2,
.flags = IORESOURCE_IRQ,
},
[2] = {
/* DRCMR for RX */
.start = 15,
.end = 15,
.flags = IORESOURCE_DMA,
},
[3] = {
/* DRCMR for TX */
.start = 16,
.end = 16,
.flags = IORESOURCE_DMA,
},
};
struct platform_device pxa27x_device_ssp2 = {
@ -826,18 +747,6 @@ static struct resource pxa27x_resource_ssp3[] = {
.end = IRQ_SSP3,
.flags = IORESOURCE_IRQ,
},
[2] = {
/* DRCMR for RX */
.start = 66,
.end = 66,
.flags = IORESOURCE_DMA,
},
[3] = {
/* DRCMR for TX */
.start = 67,
.end = 67,
.flags = IORESOURCE_DMA,
},
};
struct platform_device pxa27x_device_ssp3 = {
@ -894,16 +803,6 @@ static struct resource pxa3xx_resources_mci2[] = {
.end = IRQ_MMC2,
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = 93,
.end = 93,
.flags = IORESOURCE_DMA,
},
[3] = {
.start = 94,
.end = 94,
.flags = IORESOURCE_DMA,
},
};
struct platform_device pxa3xx_device_mci2 = {
@ -933,16 +832,6 @@ static struct resource pxa3xx_resources_mci3[] = {
.end = IRQ_MMC3,
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = 100,
.end = 100,
.flags = IORESOURCE_DMA,
},
[3] = {
.start = 101,
.end = 101,
.flags = IORESOURCE_DMA,
},
};
struct platform_device pxa3xx_device_mci3 = {
@ -1020,18 +909,6 @@ static struct resource pxa3xx_resources_nand[] = {
.end = IRQ_NAND,
.flags = IORESOURCE_IRQ,
},
[2] = {
/* DRCMR for Data DMA */
.start = 97,
.end = 97,
.flags = IORESOURCE_DMA,
},
[3] = {
/* DRCMR for Command DMA */
.start = 99,
.end = 99,
.flags = IORESOURCE_DMA,
},
};
static u64 pxa3xx_nand_dma_mask = DMA_BIT_MASK(32);
@ -1065,18 +942,6 @@ static struct resource pxa3xx_resource_ssp4[] = {
.end = IRQ_SSP4,
.flags = IORESOURCE_IRQ,
},
[2] = {
/* DRCMR for RX */
.start = 2,
.end = 2,
.flags = IORESOURCE_DMA,
},
[3] = {
/* DRCMR for TX */
.start = 3,
.end = 3,
.flags = IORESOURCE_DMA,
},
};
/*
@ -1202,11 +1067,6 @@ void __init pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info)
platform_device_add(pd);
}
static struct mmp_dma_platdata pxa_dma_pdata = {
.dma_channels = 0,
.nb_requestors = 0,
};
static struct resource pxa_dma_resource[] = {
[0] = {
.start = 0x40000000,
@ -1233,9 +1093,7 @@ static struct platform_device pxa2xx_pxa_dma = {
.resource = pxa_dma_resource,
};
void __init pxa2xx_set_dmac_info(int nb_channels, int nb_requestors)
void __init pxa2xx_set_dmac_info(struct mmp_dma_platdata *dma_pdata)
{
pxa_dma_pdata.dma_channels = nb_channels;
pxa_dma_pdata.nb_requestors = nb_requestors;
pxa_register_device(&pxa2xx_pxa_dma, &pxa_dma_pdata);
pxa_register_device(&pxa2xx_pxa_dma, dma_pdata);
}

View File

@ -1,4 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
#define PDMA_FILTER_PARAM(_prio, _requestor) (&(struct pxad_param) { \
.prio = PXAD_PRIO_##_prio, .drcmr = _requestor })
struct mmp_dma_platdata;
extern struct platform_device pxa_device_pmu;
extern struct platform_device pxa_device_mci;
extern struct platform_device pxa3xx_device_mci2;
@ -55,7 +59,7 @@ extern struct platform_device pxa3xx_device_gpio;
extern struct platform_device pxa93x_device_gpio;
void __init pxa_register_device(struct platform_device *dev, void *data);
void __init pxa2xx_set_dmac_info(int nb_channels, int nb_requestors);
void __init pxa2xx_set_dmac_info(struct mmp_dma_platdata *dma_pdata);
struct i2c_pxa_platform_data;
extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info);

View File

@ -16,6 +16,8 @@
* initialization stuff for PXA machines which can be overridden later if
* need be.
*/
#include <linux/dmaengine.h>
#include <linux/dma/pxa-dma.h>
#include <linux/gpio.h>
#include <linux/gpio-pxa.h>
#include <linux/module.h>
@ -26,6 +28,7 @@
#include <linux/syscore_ops.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/platform_data/mmp_dma.h>
#include <asm/mach/map.h>
#include <asm/suspend.h>
@ -201,6 +204,39 @@ static struct platform_device *pxa25x_devices[] __initdata = {
&pxa_device_asoc_platform,
};
static const struct dma_slave_map pxa25x_slave_map[] = {
/* PXA25x, PXA27x and PXA3xx common entries */
{ "pxa2xx-ac97", "pcm_pcm_mic_mono", PDMA_FILTER_PARAM(LOWEST, 8) },
{ "pxa2xx-ac97", "pcm_pcm_aux_mono_in", PDMA_FILTER_PARAM(LOWEST, 9) },
{ "pxa2xx-ac97", "pcm_pcm_aux_mono_out",
PDMA_FILTER_PARAM(LOWEST, 10) },
{ "pxa2xx-ac97", "pcm_pcm_stereo_in", PDMA_FILTER_PARAM(LOWEST, 11) },
{ "pxa2xx-ac97", "pcm_pcm_stereo_out", PDMA_FILTER_PARAM(LOWEST, 12) },
{ "pxa-ssp-dai.1", "rx", PDMA_FILTER_PARAM(LOWEST, 13) },
{ "pxa-ssp-dai.1", "tx", PDMA_FILTER_PARAM(LOWEST, 14) },
{ "pxa-ssp-dai.2", "rx", PDMA_FILTER_PARAM(LOWEST, 15) },
{ "pxa-ssp-dai.2", "tx", PDMA_FILTER_PARAM(LOWEST, 16) },
{ "pxa2xx-ir", "rx", PDMA_FILTER_PARAM(LOWEST, 17) },
{ "pxa2xx-ir", "tx", PDMA_FILTER_PARAM(LOWEST, 18) },
{ "pxa2xx-mci.0", "rx", PDMA_FILTER_PARAM(LOWEST, 21) },
{ "pxa2xx-mci.0", "tx", PDMA_FILTER_PARAM(LOWEST, 22) },
/* PXA25x specific map */
{ "pxa25x-ssp.0", "rx", PDMA_FILTER_PARAM(LOWEST, 13) },
{ "pxa25x-ssp.0", "tx", PDMA_FILTER_PARAM(LOWEST, 14) },
{ "pxa25x-nssp.1", "rx", PDMA_FILTER_PARAM(LOWEST, 15) },
{ "pxa25x-nssp.1", "tx", PDMA_FILTER_PARAM(LOWEST, 16) },
{ "pxa25x-nssp.2", "rx", PDMA_FILTER_PARAM(LOWEST, 23) },
{ "pxa25x-nssp.2", "tx", PDMA_FILTER_PARAM(LOWEST, 24) },
};
static struct mmp_dma_platdata pxa25x_dma_pdata = {
.dma_channels = 16,
.nb_requestors = 40,
.slave_map = pxa25x_slave_map,
.slave_map_cnt = ARRAY_SIZE(pxa25x_slave_map),
};
static int __init pxa25x_init(void)
{
int ret = 0;
@ -215,7 +251,7 @@ static int __init pxa25x_init(void)
register_syscore_ops(&pxa2xx_mfp_syscore_ops);
if (!of_have_populated_dt()) {
pxa2xx_set_dmac_info(16, 40);
pxa2xx_set_dmac_info(&pxa25x_dma_pdata);
pxa_register_device(&pxa25x_device_gpio, &pxa25x_gpio_info);
ret = platform_add_devices(pxa25x_devices,
ARRAY_SIZE(pxa25x_devices));

View File

@ -11,6 +11,8 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/dmaengine.h>
#include <linux/dma/pxa-dma.h>
#include <linux/gpio.h>
#include <linux/gpio-pxa.h>
#include <linux/module.h>
@ -23,6 +25,7 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/platform_data/i2c-pxa.h>
#include <linux/platform_data/mmp_dma.h>
#include <asm/mach/map.h>
#include <mach/hardware.h>
@ -297,6 +300,40 @@ static struct platform_device *devices[] __initdata = {
&pxa27x_device_pwm1,
};
static const struct dma_slave_map pxa27x_slave_map[] = {
/* PXA25x, PXA27x and PXA3xx common entries */
{ "pxa2xx-ac97", "pcm_pcm_mic_mono", PDMA_FILTER_PARAM(LOWEST, 8) },
{ "pxa2xx-ac97", "pcm_pcm_aux_mono_in", PDMA_FILTER_PARAM(LOWEST, 9) },
{ "pxa2xx-ac97", "pcm_pcm_aux_mono_out",
PDMA_FILTER_PARAM(LOWEST, 10) },
{ "pxa2xx-ac97", "pcm_pcm_stereo_in", PDMA_FILTER_PARAM(LOWEST, 11) },
{ "pxa2xx-ac97", "pcm_pcm_stereo_out", PDMA_FILTER_PARAM(LOWEST, 12) },
{ "pxa-ssp-dai.0", "rx", PDMA_FILTER_PARAM(LOWEST, 13) },
{ "pxa-ssp-dai.0", "tx", PDMA_FILTER_PARAM(LOWEST, 14) },
{ "pxa-ssp-dai.1", "rx", PDMA_FILTER_PARAM(LOWEST, 15) },
{ "pxa-ssp-dai.1", "tx", PDMA_FILTER_PARAM(LOWEST, 16) },
{ "pxa2xx-ir", "rx", PDMA_FILTER_PARAM(LOWEST, 17) },
{ "pxa2xx-ir", "tx", PDMA_FILTER_PARAM(LOWEST, 18) },
{ "pxa2xx-mci.0", "rx", PDMA_FILTER_PARAM(LOWEST, 21) },
{ "pxa2xx-mci.0", "tx", PDMA_FILTER_PARAM(LOWEST, 22) },
{ "pxa-ssp-dai.2", "rx", PDMA_FILTER_PARAM(LOWEST, 66) },
{ "pxa-ssp-dai.2", "tx", PDMA_FILTER_PARAM(LOWEST, 67) },
/* PXA27x specific map */
{ "pxa2xx-i2s", "rx", PDMA_FILTER_PARAM(LOWEST, 2) },
{ "pxa2xx-i2s", "tx", PDMA_FILTER_PARAM(LOWEST, 3) },
{ "pxa27x-camera.0", "CI_Y", PDMA_FILTER_PARAM(HIGHEST, 68) },
{ "pxa27x-camera.0", "CI_U", PDMA_FILTER_PARAM(HIGHEST, 69) },
{ "pxa27x-camera.0", "CI_V", PDMA_FILTER_PARAM(HIGHEST, 70) },
};
static struct mmp_dma_platdata pxa27x_dma_pdata = {
.dma_channels = 32,
.nb_requestors = 75,
.slave_map = pxa27x_slave_map,
.slave_map_cnt = ARRAY_SIZE(pxa27x_slave_map),
};
static int __init pxa27x_init(void)
{
int ret = 0;
@ -313,7 +350,7 @@ static int __init pxa27x_init(void)
if (!of_have_populated_dt()) {
pxa_register_device(&pxa27x_device_gpio,
&pxa27x_gpio_info);
pxa2xx_set_dmac_info(32, 75);
pxa2xx_set_dmac_info(&pxa27x_dma_pdata);
ret = platform_add_devices(devices,
ARRAY_SIZE(devices));
}

View File

@ -12,6 +12,8 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/dmaengine.h>
#include <linux/dma/pxa-dma.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@ -24,6 +26,7 @@
#include <linux/of.h>
#include <linux/syscore_ops.h>
#include <linux/platform_data/i2c-pxa.h>
#include <linux/platform_data/mmp_dma.h>
#include <asm/mach/map.h>
#include <asm/suspend.h>
@ -421,6 +424,42 @@ static struct platform_device *devices[] __initdata = {
&pxa27x_device_pwm1,
};
static const struct dma_slave_map pxa3xx_slave_map[] = {
/* PXA25x, PXA27x and PXA3xx common entries */
{ "pxa2xx-ac97", "pcm_pcm_mic_mono", PDMA_FILTER_PARAM(LOWEST, 8) },
{ "pxa2xx-ac97", "pcm_pcm_aux_mono_in", PDMA_FILTER_PARAM(LOWEST, 9) },
{ "pxa2xx-ac97", "pcm_pcm_aux_mono_out",
PDMA_FILTER_PARAM(LOWEST, 10) },
{ "pxa2xx-ac97", "pcm_pcm_stereo_in", PDMA_FILTER_PARAM(LOWEST, 11) },
{ "pxa2xx-ac97", "pcm_pcm_stereo_out", PDMA_FILTER_PARAM(LOWEST, 12) },
{ "pxa-ssp-dai.0", "rx", PDMA_FILTER_PARAM(LOWEST, 13) },
{ "pxa-ssp-dai.0", "tx", PDMA_FILTER_PARAM(LOWEST, 14) },
{ "pxa-ssp-dai.1", "rx", PDMA_FILTER_PARAM(LOWEST, 15) },
{ "pxa-ssp-dai.1", "tx", PDMA_FILTER_PARAM(LOWEST, 16) },
{ "pxa2xx-ir", "rx", PDMA_FILTER_PARAM(LOWEST, 17) },
{ "pxa2xx-ir", "tx", PDMA_FILTER_PARAM(LOWEST, 18) },
{ "pxa2xx-mci.0", "rx", PDMA_FILTER_PARAM(LOWEST, 21) },
{ "pxa2xx-mci.0", "tx", PDMA_FILTER_PARAM(LOWEST, 22) },
{ "pxa-ssp-dai.2", "rx", PDMA_FILTER_PARAM(LOWEST, 66) },
{ "pxa-ssp-dai.2", "tx", PDMA_FILTER_PARAM(LOWEST, 67) },
/* PXA3xx specific map */
{ "pxa-ssp-dai.3", "rx", PDMA_FILTER_PARAM(LOWEST, 2) },
{ "pxa-ssp-dai.3", "tx", PDMA_FILTER_PARAM(LOWEST, 3) },
{ "pxa2xx-mci.1", "rx", PDMA_FILTER_PARAM(LOWEST, 93) },
{ "pxa2xx-mci.1", "tx", PDMA_FILTER_PARAM(LOWEST, 94) },
{ "pxa3xx-nand", "data", PDMA_FILTER_PARAM(LOWEST, 97) },
{ "pxa2xx-mci.2", "rx", PDMA_FILTER_PARAM(LOWEST, 100) },
{ "pxa2xx-mci.2", "tx", PDMA_FILTER_PARAM(LOWEST, 101) },
};
static struct mmp_dma_platdata pxa3xx_dma_pdata = {
.dma_channels = 32,
.nb_requestors = 100,
.slave_map = pxa3xx_slave_map,
.slave_map_cnt = ARRAY_SIZE(pxa3xx_slave_map),
};
static int __init pxa3xx_init(void)
{
int ret = 0;
@ -456,7 +495,7 @@ static int __init pxa3xx_init(void)
if (of_have_populated_dt())
return 0;
pxa2xx_set_dmac_info(32, 100);
pxa2xx_set_dmac_info(&pxa3xx_dma_pdata);
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
if (ret)
return ret;

View File

@ -127,53 +127,6 @@ static int pxa_ssp_probe(struct platform_device *pdev)
if (IS_ERR(ssp->clk))
return PTR_ERR(ssp->clk);
if (dev->of_node) {
struct of_phandle_args dma_spec;
struct device_node *np = dev->of_node;
int ret;
/*
* FIXME: we should allocate the DMA channel from this
* context and pass the channel down to the ssp users.
* For now, we lookup the rx and tx indices manually
*/
/* rx */
ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells",
0, &dma_spec);
if (ret) {
dev_err(dev, "Can't parse dmas property\n");
return -ENODEV;
}
ssp->drcmr_rx = dma_spec.args[0];
of_node_put(dma_spec.np);
/* tx */
ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells",
1, &dma_spec);
if (ret) {
dev_err(dev, "Can't parse dmas property\n");
return -ENODEV;
}
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;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(dev, "no memory resource defined\n");

View File

@ -25,7 +25,6 @@
#include <linux/libata.h>
#include <linux/platform_device.h>
#include <linux/dmaengine.h>
#include <linux/dma/pxa-dma.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/completion.h>
@ -180,8 +179,6 @@ static int pxa_ata_probe(struct platform_device *pdev)
struct resource *irq_res;
struct pata_pxa_pdata *pdata = dev_get_platdata(&pdev->dev);
struct dma_slave_config config;
dma_cap_mask_t mask;
struct pxad_param param;
int ret = 0;
/*
@ -278,10 +275,6 @@ static int pxa_ata_probe(struct platform_device *pdev)
ap->private_data = data;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
param.prio = PXAD_PRIO_LOWEST;
param.drcmr = pdata->dma_dreq;
memset(&config, 0, sizeof(config));
config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
@ -294,8 +287,7 @@ static int pxa_ata_probe(struct platform_device *pdev)
* Request the DMA channel
*/
data->dma_chan =
dma_request_slave_channel_compat(mask, pxad_filter_fn,
&param, &pdev->dev, "data");
dma_request_slave_channel(&pdev->dev, "data");
if (!data->dma_chan)
return -EBUSY;
ret = dmaengine_slave_config(data->dma_chan, &config);

View File

@ -67,6 +67,7 @@ struct clk_core {
unsigned long max_rate;
unsigned long accuracy;
int phase;
struct clk_duty duty;
struct hlist_head children;
struct hlist_node child_node;
struct hlist_head clks;
@ -2401,6 +2402,172 @@ int clk_get_phase(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_get_phase);
static void clk_core_reset_duty_cycle_nolock(struct clk_core *core)
{
/* Assume a default value of 50% */
core->duty.num = 1;
core->duty.den = 2;
}
static int clk_core_update_duty_cycle_parent_nolock(struct clk_core *core);
static int clk_core_update_duty_cycle_nolock(struct clk_core *core)
{
struct clk_duty *duty = &core->duty;
int ret = 0;
if (!core->ops->get_duty_cycle)
return clk_core_update_duty_cycle_parent_nolock(core);
ret = core->ops->get_duty_cycle(core->hw, duty);
if (ret)
goto reset;
/* Don't trust the clock provider too much */
if (duty->den == 0 || duty->num > duty->den) {
ret = -EINVAL;
goto reset;
}
return 0;
reset:
clk_core_reset_duty_cycle_nolock(core);
return ret;
}
static int clk_core_update_duty_cycle_parent_nolock(struct clk_core *core)
{
int ret = 0;
if (core->parent &&
core->flags & CLK_DUTY_CYCLE_PARENT) {
ret = clk_core_update_duty_cycle_nolock(core->parent);
memcpy(&core->duty, &core->parent->duty, sizeof(core->duty));
} else {
clk_core_reset_duty_cycle_nolock(core);
}
return ret;
}
static int clk_core_set_duty_cycle_parent_nolock(struct clk_core *core,
struct clk_duty *duty);
static int clk_core_set_duty_cycle_nolock(struct clk_core *core,
struct clk_duty *duty)
{
int ret;
lockdep_assert_held(&prepare_lock);
if (clk_core_rate_is_protected(core))
return -EBUSY;
trace_clk_set_duty_cycle(core, duty);
if (!core->ops->set_duty_cycle)
return clk_core_set_duty_cycle_parent_nolock(core, duty);
ret = core->ops->set_duty_cycle(core->hw, duty);
if (!ret)
memcpy(&core->duty, duty, sizeof(*duty));
trace_clk_set_duty_cycle_complete(core, duty);
return ret;
}
static int clk_core_set_duty_cycle_parent_nolock(struct clk_core *core,
struct clk_duty *duty)
{
int ret = 0;
if (core->parent &&
core->flags & (CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT)) {
ret = clk_core_set_duty_cycle_nolock(core->parent, duty);
memcpy(&core->duty, &core->parent->duty, sizeof(core->duty));
}
return ret;
}
/**
* clk_set_duty_cycle - adjust the duty cycle ratio of a clock signal
* @clk: clock signal source
* @num: numerator of the duty cycle ratio to be applied
* @den: denominator of the duty cycle ratio to be applied
*
* Apply the duty cycle ratio if the ratio is valid and the clock can
* perform this operation
*
* Returns (0) on success, a negative errno otherwise.
*/
int clk_set_duty_cycle(struct clk *clk, unsigned int num, unsigned int den)
{
int ret;
struct clk_duty duty;
if (!clk)
return 0;
/* sanity check the ratio */
if (den == 0 || num > den)
return -EINVAL;
duty.num = num;
duty.den = den;
clk_prepare_lock();
if (clk->exclusive_count)
clk_core_rate_unprotect(clk->core);
ret = clk_core_set_duty_cycle_nolock(clk->core, &duty);
if (clk->exclusive_count)
clk_core_rate_protect(clk->core);
clk_prepare_unlock();
return ret;
}
EXPORT_SYMBOL_GPL(clk_set_duty_cycle);
static int clk_core_get_scaled_duty_cycle(struct clk_core *core,
unsigned int scale)
{
struct clk_duty *duty = &core->duty;
int ret;
clk_prepare_lock();
ret = clk_core_update_duty_cycle_nolock(core);
if (!ret)
ret = mult_frac(scale, duty->num, duty->den);
clk_prepare_unlock();
return ret;
}
/**
* clk_get_scaled_duty_cycle - return the duty cycle ratio of a clock signal
* @clk: clock signal source
* @scale: scaling factor to be applied to represent the ratio as an integer
*
* Returns the duty cycle ratio of a clock node multiplied by the provided
* scaling factor, or negative errno on error.
*/
int clk_get_scaled_duty_cycle(struct clk *clk, unsigned int scale)
{
if (!clk)
return 0;
return clk_core_get_scaled_duty_cycle(clk->core, scale);
}
EXPORT_SYMBOL_GPL(clk_get_scaled_duty_cycle);
/**
* clk_is_match - check if two clk's point to the same hardware clock
* @p: clk compared against q
@ -2454,12 +2621,13 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
if (!c)
return;
seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu %-3d\n",
seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu %5d %6d\n",
level * 3 + 1, "",
30 - level * 3, c->name,
c->enable_count, c->prepare_count, c->protect_count,
clk_core_get_rate(c), clk_core_get_accuracy(c),
clk_core_get_phase(c));
clk_core_get_phase(c),
clk_core_get_scaled_duty_cycle(c, 100000));
}
static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
@ -2481,9 +2649,9 @@ static int clk_summary_show(struct seq_file *s, void *data)
struct clk_core *c;
struct hlist_head **lists = (struct hlist_head **)s->private;
seq_puts(s, " enable prepare protect \n");
seq_puts(s, " clock count count count rate accuracy phase\n");
seq_puts(s, "----------------------------------------------------------------------------------------\n");
seq_puts(s, " enable prepare protect duty\n");
seq_puts(s, " clock count count count rate accuracy phase cycle\n");
seq_puts(s, "---------------------------------------------------------------------------------------------\n");
clk_prepare_lock();
@ -2510,6 +2678,8 @@ static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
seq_printf(s, "\"duty_cycle\": %u",
clk_core_get_scaled_duty_cycle(c, 100000));
}
static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
@ -2571,6 +2741,7 @@ static const struct {
ENTRY(CLK_SET_RATE_UNGATE),
ENTRY(CLK_IS_CRITICAL),
ENTRY(CLK_OPS_PARENT_ENABLE),
ENTRY(CLK_DUTY_CYCLE_PARENT),
#undef ENTRY
};
@ -2609,6 +2780,17 @@ static int possible_parents_show(struct seq_file *s, void *data)
}
DEFINE_SHOW_ATTRIBUTE(possible_parents);
static int clk_duty_cycle_show(struct seq_file *s, void *data)
{
struct clk_core *core = s->private;
struct clk_duty *duty = &core->duty;
seq_printf(s, "%u/%u\n", duty->num, duty->den);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(clk_duty_cycle);
static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
{
struct dentry *root;
@ -2627,6 +2809,8 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
debugfs_create_u32("clk_enable_count", 0444, root, &core->enable_count);
debugfs_create_u32("clk_protect_count", 0444, root, &core->protect_count);
debugfs_create_u32("clk_notifier_count", 0444, root, &core->notifier_count);
debugfs_create_file("clk_duty_cycle", 0444, root, core,
&clk_duty_cycle_fops);
if (core->num_parents > 1)
debugfs_create_file("clk_possible_parents", 0444, root, core,
@ -2844,6 +3028,11 @@ static int __clk_core_init(struct clk_core *core)
else
core->phase = 0;
/*
* Set clk's duty cycle.
*/
clk_core_update_duty_cycle_nolock(core);
/*
* Set clk's rate. The preferred method is to use .recalc_rate. For
* simple clocks and lazy developers the default fallback is to use the

View File

@ -179,6 +179,8 @@ static unsigned int pxad_drcmr(unsigned int line)
return 0x1000 + line * 4;
}
bool pxad_filter_fn(struct dma_chan *chan, void *param);
/*
* Debug fs
*/
@ -760,6 +762,8 @@ static void pxad_free_chan_resources(struct dma_chan *dchan)
dma_pool_destroy(chan->desc_pool);
chan->desc_pool = NULL;
chan->drcmr = U32_MAX;
chan->prio = PXAD_PRIO_LOWEST;
}
static void pxad_free_desc(struct virt_dma_desc *vd)
@ -1384,6 +1388,9 @@ static int pxad_init_dmadev(struct platform_device *op,
c = devm_kzalloc(&op->dev, sizeof(*c), GFP_KERNEL);
if (!c)
return -ENOMEM;
c->drcmr = U32_MAX;
c->prio = PXAD_PRIO_LOWEST;
c->vc.desc_free = pxad_free_desc;
vchan_init(&c->vc, &pdev->slave);
init_waitqueue_head(&c->wq_state);
@ -1396,9 +1403,10 @@ static int pxad_probe(struct platform_device *op)
{
struct pxad_device *pdev;
const struct of_device_id *of_id;
const struct dma_slave_map *slave_map = NULL;
struct mmp_dma_platdata *pdata = dev_get_platdata(&op->dev);
struct resource *iores;
int ret, dma_channels = 0, nb_requestors = 0;
int ret, dma_channels = 0, nb_requestors = 0, slave_map_cnt = 0;
const enum dma_slave_buswidth widths =
DMA_SLAVE_BUSWIDTH_1_BYTE | DMA_SLAVE_BUSWIDTH_2_BYTES |
DMA_SLAVE_BUSWIDTH_4_BYTES;
@ -1429,6 +1437,8 @@ static int pxad_probe(struct platform_device *op)
} else if (pdata && pdata->dma_channels) {
dma_channels = pdata->dma_channels;
nb_requestors = pdata->nb_requestors;
slave_map = pdata->slave_map;
slave_map_cnt = pdata->slave_map_cnt;
} else {
dma_channels = 32; /* default 32 channel */
}
@ -1440,6 +1450,9 @@ static int pxad_probe(struct platform_device *op)
pdev->slave.device_prep_dma_memcpy = pxad_prep_memcpy;
pdev->slave.device_prep_slave_sg = pxad_prep_slave_sg;
pdev->slave.device_prep_dma_cyclic = pxad_prep_dma_cyclic;
pdev->slave.filter.map = slave_map;
pdev->slave.filter.mapcnt = slave_map_cnt;
pdev->slave.filter.fn = pxad_filter_fn;
pdev->slave.copy_align = PDMA_ALIGNMENT;
pdev->slave.src_addr_widths = widths;

View File

@ -23,6 +23,7 @@ config DRM_I915
select SYNC_FILE
select IOSF_MBI
select CRC32
select SND_HDA_I915 if SND_HDA_CORE
help
Choose this option if you have a system that has "Intel Graphics
Media Accelerator" or "HD Graphics" integrated graphics,

View File

@ -639,11 +639,12 @@ void intel_audio_codec_enable(struct intel_encoder *encoder,
dev_priv->av_enc_map[pipe] = encoder;
mutex_unlock(&dev_priv->av_mutex);
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) {
if (acomp && acomp->base.audio_ops &&
acomp->base.audio_ops->pin_eld_notify) {
/* audio drivers expect pipe = -1 to indicate Non-MST cases */
if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST))
pipe = -1;
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr,
acomp->base.audio_ops->pin_eld_notify(acomp->base.audio_ops->audio_ptr,
(int) port, (int) pipe);
}
@ -681,11 +682,12 @@ void intel_audio_codec_disable(struct intel_encoder *encoder,
dev_priv->av_enc_map[pipe] = NULL;
mutex_unlock(&dev_priv->av_mutex);
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) {
if (acomp && acomp->base.audio_ops &&
acomp->base.audio_ops->pin_eld_notify) {
/* audio drivers expect pipe = -1 to indicate Non-MST cases */
if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST))
pipe = -1;
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr,
acomp->base.audio_ops->pin_eld_notify(acomp->base.audio_ops->audio_ptr,
(int) port, (int) pipe);
}
@ -880,7 +882,7 @@ static int i915_audio_component_get_eld(struct device *kdev, int port,
return ret;
}
static const struct i915_audio_component_ops i915_audio_component_ops = {
static const struct drm_audio_component_ops i915_audio_component_ops = {
.owner = THIS_MODULE,
.get_power = i915_audio_component_get_power,
.put_power = i915_audio_component_put_power,
@ -897,12 +899,12 @@ static int i915_audio_component_bind(struct device *i915_kdev,
struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev);
int i;
if (WARN_ON(acomp->ops || acomp->dev))
if (WARN_ON(acomp->base.ops || acomp->base.dev))
return -EEXIST;
drm_modeset_lock_all(&dev_priv->drm);
acomp->ops = &i915_audio_component_ops;
acomp->dev = i915_kdev;
acomp->base.ops = &i915_audio_component_ops;
acomp->base.dev = i915_kdev;
BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS);
for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++)
acomp->aud_sample_rate[i] = 0;
@ -919,8 +921,8 @@ static void i915_audio_component_unbind(struct device *i915_kdev,
struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev);
drm_modeset_lock_all(&dev_priv->drm);
acomp->ops = NULL;
acomp->dev = NULL;
acomp->base.ops = NULL;
acomp->base.dev = NULL;
dev_priv->audio_component = NULL;
drm_modeset_unlock_all(&dev_priv->drm);
}

View File

@ -2375,8 +2375,6 @@ static int pxa_camera_probe(struct platform_device *pdev)
.src_maxburst = 8,
.direction = DMA_DEV_TO_MEM,
};
dma_cap_mask_t mask;
struct pxad_param params;
char clk_name[V4L2_CLK_NAME_SIZE];
int irq;
int err = 0, i;
@ -2450,34 +2448,20 @@ static int pxa_camera_probe(struct platform_device *pdev)
pcdev->base = base;
/* request dma */
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
dma_cap_set(DMA_PRIVATE, mask);
params.prio = 0;
params.drcmr = 68;
pcdev->dma_chans[0] =
dma_request_slave_channel_compat(mask, pxad_filter_fn,
&params, &pdev->dev, "CI_Y");
pcdev->dma_chans[0] = dma_request_slave_channel(&pdev->dev, "CI_Y");
if (!pcdev->dma_chans[0]) {
dev_err(&pdev->dev, "Can't request DMA for Y\n");
return -ENODEV;
}
params.drcmr = 69;
pcdev->dma_chans[1] =
dma_request_slave_channel_compat(mask, pxad_filter_fn,
&params, &pdev->dev, "CI_U");
pcdev->dma_chans[1] = dma_request_slave_channel(&pdev->dev, "CI_U");
if (!pcdev->dma_chans[1]) {
dev_err(&pdev->dev, "Can't request DMA for Y\n");
err = -ENODEV;
goto exit_free_dma_y;
}
params.drcmr = 70;
pcdev->dma_chans[2] =
dma_request_slave_channel_compat(mask, pxad_filter_fn,
&params, &pdev->dev, "CI_V");
pcdev->dma_chans[2] = dma_request_slave_channel(&pdev->dev, "CI_V");
if (!pcdev->dma_chans[2]) {
dev_err(&pdev->dev, "Can't request DMA for V\n");
err = -ENODEV;

View File

@ -24,7 +24,6 @@
#include <linux/interrupt.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/dma/pxa-dma.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/mmc/host.h>
@ -637,10 +636,8 @@ static int pxamci_probe(struct platform_device *pdev)
{
struct mmc_host *mmc;
struct pxamci_host *host = NULL;
struct resource *r, *dmarx, *dmatx;
struct pxad_param param_rx, param_tx;
struct resource *r;
int ret, irq, gpio_cd = -1, gpio_ro = -1, gpio_power = -1;
dma_cap_mask_t mask;
ret = pxamci_of_init(pdev);
if (ret)
@ -739,34 +736,14 @@ static int pxamci_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mmc);
if (!pdev->dev.of_node) {
dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
if (!dmarx || !dmatx) {
ret = -ENXIO;
goto out;
}
param_rx.prio = PXAD_PRIO_LOWEST;
param_rx.drcmr = dmarx->start;
param_tx.prio = PXAD_PRIO_LOWEST;
param_tx.drcmr = dmatx->start;
}
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
host->dma_chan_rx =
dma_request_slave_channel_compat(mask, pxad_filter_fn,
&param_rx, &pdev->dev, "rx");
host->dma_chan_rx = dma_request_slave_channel(&pdev->dev, "rx");
if (host->dma_chan_rx == NULL) {
dev_err(&pdev->dev, "unable to request rx dma channel\n");
ret = -ENODEV;
goto out;
}
host->dma_chan_tx =
dma_request_slave_channel_compat(mask, pxad_filter_fn,
&param_tx, &pdev->dev, "tx");
host->dma_chan_tx = dma_request_slave_channel(&pdev->dev, "tx");
if (host->dma_chan_tx == NULL) {
dev_err(&pdev->dev, "unable to request tx dma channel\n");
ret = -ENODEV;

View File

@ -2612,8 +2612,6 @@ static int marvell_nfc_init_dma(struct marvell_nfc *nfc)
dev);
struct dma_slave_config config = {};
struct resource *r;
dma_cap_mask_t mask;
struct pxad_param param;
int ret;
if (!IS_ENABLED(CONFIG_PXA_DMA)) {
@ -2626,20 +2624,7 @@ static int marvell_nfc_init_dma(struct marvell_nfc *nfc)
if (ret)
return ret;
r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (!r) {
dev_err(nfc->dev, "No resource defined for data DMA\n");
return -ENXIO;
}
param.drcmr = r->start;
param.prio = PXAD_PRIO_LOWEST;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
nfc->dma_chan =
dma_request_slave_channel_compat(mask, pxad_filter_fn,
&param, nfc->dev,
"data");
nfc->dma_chan = dma_request_slave_channel(nfc->dev, "data");
if (!nfc->dma_chan) {
dev_err(nfc->dev,
"Unable to request data DMA channel\n");

View File

@ -0,0 +1,118 @@
// SPDX-License-Identifier: MIT
// Copyright © 2014 Intel Corporation
#ifndef _DRM_AUDIO_COMPONENT_H_
#define _DRM_AUDIO_COMPONENT_H_
struct drm_audio_component;
/**
* struct drm_audio_component_ops - Ops implemented by DRM driver, called by hda driver
*/
struct drm_audio_component_ops {
/**
* @owner: drm module to pin down
*/
struct module *owner;
/**
* @get_power: get the POWER_DOMAIN_AUDIO power well
*
* Request the power well to be turned on.
*/
void (*get_power)(struct device *);
/**
* @put_power: put the POWER_DOMAIN_AUDIO power well
*
* Allow the power well to be turned off.
*/
void (*put_power)(struct device *);
/**
* @codec_wake_override: Enable/disable codec wake signal
*/
void (*codec_wake_override)(struct device *, bool enable);
/**
* @get_cdclk_freq: Get the Core Display Clock in kHz
*/
int (*get_cdclk_freq)(struct device *);
/**
* @sync_audio_rate: set n/cts based on the sample rate
*
* Called from audio driver. After audio driver sets the
* sample rate, it will call this function to set n/cts
*/
int (*sync_audio_rate)(struct device *, int port, int pipe, int rate);
/**
* @get_eld: fill the audio state and ELD bytes for the given port
*
* Called from audio driver to get the HDMI/DP audio state of the given
* digital port, and also fetch ELD bytes to the given pointer.
*
* It returns the byte size of the original ELD (not the actually
* copied size), zero for an invalid ELD, or a negative error code.
*
* Note that the returned size may be over @max_bytes. Then it
* implies that only a part of ELD has been copied to the buffer.
*/
int (*get_eld)(struct device *, int port, int pipe, bool *enabled,
unsigned char *buf, int max_bytes);
};
/**
* struct drm_audio_component_audio_ops - Ops implemented by hda driver, called by DRM driver
*/
struct drm_audio_component_audio_ops {
/**
* @audio_ptr: Pointer to be used in call to pin_eld_notify
*/
void *audio_ptr;
/**
* @pin_eld_notify: Notify the HDA driver that pin sense and/or ELD information has changed
*
* Called when the DRM driver has set up audio pipeline or has just
* begun to tear it down. This allows the HDA driver to update its
* status accordingly (even when the HDA controller is in power save
* mode).
*/
void (*pin_eld_notify)(void *audio_ptr, int port, int pipe);
/**
* @pin2port: Check and convert from pin node to port number
*
* Called by HDA driver to check and convert from the pin widget node
* number to a port number in the graphics side.
*/
int (*pin2port)(void *audio_ptr, int pin);
/**
* @master_bind: (Optional) component master bind callback
*
* Called at binding master component, for HDA codec-specific
* handling of dynamic binding.
*/
int (*master_bind)(struct device *dev, struct drm_audio_component *);
/**
* @master_unbind: (Optional) component master unbind callback
*
* Called at unbinding master component, for HDA codec-specific
* handling of dynamic unbinding.
*/
void (*master_unbind)(struct device *dev, struct drm_audio_component *);
};
/**
* struct drm_audio_component - Used for direct communication between DRM and hda drivers
*/
struct drm_audio_component {
/**
* @dev: DRM device, used as parameter for ops
*/
struct device *dev;
/**
* @ops: Ops implemented by DRM driver, called by hda driver
*/
const struct drm_audio_component_ops *ops;
/**
* @audio_ops: Ops implemented by hda driver, called by DRM driver
*/
const struct drm_audio_component_audio_ops *audio_ops;
};
#endif /* _DRM_AUDIO_COMPONENT_H_ */

View File

@ -24,101 +24,26 @@
#ifndef _I915_COMPONENT_H_
#define _I915_COMPONENT_H_
#include "drm_audio_component.h"
/* MAX_PORT is the number of port
* It must be sync with I915_MAX_PORTS defined i915_drv.h
*/
#define MAX_PORTS 6
/**
* struct i915_audio_component_ops - Ops implemented by i915 driver, called by hda driver
*/
struct i915_audio_component_ops {
/**
* @owner: i915 module
*/
struct module *owner;
/**
* @get_power: get the POWER_DOMAIN_AUDIO power well
*
* Request the power well to be turned on.
*/
void (*get_power)(struct device *);
/**
* @put_power: put the POWER_DOMAIN_AUDIO power well
*
* Allow the power well to be turned off.
*/
void (*put_power)(struct device *);
/**
* @codec_wake_override: Enable/disable codec wake signal
*/
void (*codec_wake_override)(struct device *, bool enable);
/**
* @get_cdclk_freq: Get the Core Display Clock in kHz
*/
int (*get_cdclk_freq)(struct device *);
/**
* @sync_audio_rate: set n/cts based on the sample rate
*
* Called from audio driver. After audio driver sets the
* sample rate, it will call this function to set n/cts
*/
int (*sync_audio_rate)(struct device *, int port, int pipe, int rate);
/**
* @get_eld: fill the audio state and ELD bytes for the given port
*
* Called from audio driver to get the HDMI/DP audio state of the given
* digital port, and also fetch ELD bytes to the given pointer.
*
* It returns the byte size of the original ELD (not the actually
* copied size), zero for an invalid ELD, or a negative error code.
*
* Note that the returned size may be over @max_bytes. Then it
* implies that only a part of ELD has been copied to the buffer.
*/
int (*get_eld)(struct device *, int port, int pipe, bool *enabled,
unsigned char *buf, int max_bytes);
};
/**
* struct i915_audio_component_audio_ops - Ops implemented by hda driver, called by i915 driver
*/
struct i915_audio_component_audio_ops {
/**
* @audio_ptr: Pointer to be used in call to pin_eld_notify
*/
void *audio_ptr;
/**
* @pin_eld_notify: Notify the HDA driver that pin sense and/or ELD information has changed
*
* Called when the i915 driver has set up audio pipeline or has just
* begun to tear it down. This allows the HDA driver to update its
* status accordingly (even when the HDA controller is in power save
* mode).
*/
void (*pin_eld_notify)(void *audio_ptr, int port, int pipe);
};
/**
* struct i915_audio_component - Used for direct communication between i915 and hda drivers
*/
struct i915_audio_component {
/**
* @dev: i915 device, used as parameter for ops
* @base: the drm_audio_component base class
*/
struct device *dev;
struct drm_audio_component base;
/**
* @aud_sample_rate: the array of audio sample rate per port
*/
int aud_sample_rate[MAX_PORTS];
/**
* @ops: Ops implemented by i915 driver, called by hda driver
*/
const struct i915_audio_component_ops *ops;
/**
* @audio_ops: Ops implemented by hda driver, called by i915 driver
*/
const struct i915_audio_component_audio_ops *audio_ops;
};
#endif /* _I915_COMPONENT_H_ */

View File

@ -38,6 +38,8 @@
#define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */
/* parents need enable during gate/ungate, set rate and re-parent */
#define CLK_OPS_PARENT_ENABLE BIT(12)
/* duty cycle call may be forwarded to the parent clock */
#define CLK_DUTY_CYCLE_PARENT BIT(13)
struct clk;
struct clk_hw;
@ -66,6 +68,17 @@ struct clk_rate_request {
struct clk_hw *best_parent_hw;
};
/**
* struct clk_duty - Struture encoding the duty cycle ratio of a clock
*
* @num: Numerator of the duty cycle ratio
* @den: Denominator of the duty cycle ratio
*/
struct clk_duty {
unsigned int num;
unsigned int den;
};
/**
* struct clk_ops - Callback operations for hardware clocks; these are to
* be provided by the clock implementation, and will be called by drivers
@ -169,6 +182,15 @@ struct clk_rate_request {
* by the second argument. Valid values for degrees are
* 0-359. Return 0 on success, otherwise -EERROR.
*
* @get_duty_cycle: Queries the hardware to get the current duty cycle ratio
* of a clock. Returned values denominator cannot be 0 and must be
* superior or equal to the numerator.
*
* @set_duty_cycle: Apply the duty cycle ratio to this clock signal specified by
* the numerator (2nd argurment) and denominator (3rd argument).
* Argument must be a valid ratio (denominator > 0
* and >= numerator) Return 0 on success, otherwise -EERROR.
*
* @init: Perform platform-specific initialization magic.
* This is not not used by any of the basic clock types.
* Please consider other ways of solving initialization problems
@ -218,6 +240,10 @@ struct clk_ops {
unsigned long parent_accuracy);
int (*get_phase)(struct clk_hw *hw);
int (*set_phase)(struct clk_hw *hw, int degrees);
int (*get_duty_cycle)(struct clk_hw *hw,
struct clk_duty *duty);
int (*set_duty_cycle)(struct clk_hw *hw,
struct clk_duty *duty);
void (*init)(struct clk_hw *hw);
void (*debug_init)(struct clk_hw *hw, struct dentry *dentry);
};

View File

@ -141,6 +141,27 @@ int clk_set_phase(struct clk *clk, int degrees);
*/
int clk_get_phase(struct clk *clk);
/**
* clk_set_duty_cycle - adjust the duty cycle ratio of a clock signal
* @clk: clock signal source
* @num: numerator of the duty cycle ratio to be applied
* @den: denominator of the duty cycle ratio to be applied
*
* Adjust the duty cycle of a clock signal by the specified ratio. Returns 0 on
* success, -EERROR otherwise.
*/
int clk_set_duty_cycle(struct clk *clk, unsigned int num, unsigned int den);
/**
* clk_get_duty_cycle - return the duty cycle ratio of a clock signal
* @clk: clock signal source
* @scale: scaling factor to be applied to represent the ratio as an integer
*
* Returns the duty cycle ratio multiplied by the scale provided, otherwise
* returns -EERROR.
*/
int clk_get_scaled_duty_cycle(struct clk *clk, unsigned int scale);
/**
* clk_is_match - check if two clk's point to the same hardware clock
* @p: clk compared against q
@ -183,6 +204,18 @@ static inline long clk_get_phase(struct clk *clk)
return -ENOTSUPP;
}
static inline int clk_set_duty_cycle(struct clk *clk, unsigned int num,
unsigned int den)
{
return -ENOTSUPP;
}
static inline unsigned int clk_get_scaled_duty_cycle(struct clk *clk,
unsigned int scale)
{
return 0;
}
static inline bool clk_is_match(const struct clk *p, const struct clk *q)
{
return p == q;

View File

@ -9,6 +9,15 @@ enum pxad_chan_prio {
PXAD_PRIO_LOWEST,
};
/**
* struct pxad_param - dma channel request parameters
* @drcmr: requestor line number
* @prio: minimal mandatory priority of the channel
*
* If a requested channel is granted, its priority will be at least @prio,
* ie. if PXAD_PRIO_LOW is required, the requested channel will be either
* PXAD_PRIO_LOW, PXAD_PRIO_NORMAL or PXAD_PRIO_HIGHEST.
*/
struct pxad_param {
unsigned int drcmr;
enum pxad_chan_prio prio;

View File

@ -12,9 +12,13 @@
#ifndef MMP_DMA_H
#define MMP_DMA_H
struct dma_slave_map;
struct mmp_dma_platdata {
int dma_channels;
int nb_requestors;
int slave_map_cnt;
const struct dma_slave_map *slave_map;
};
#endif /* MMP_DMA_H */

View File

@ -171,6 +171,14 @@
#define SSACD_SCDB (1 << 3) /* SSPSYSCLK Divider Bypass */
#define SSACD_ACPS(x) ((x) << 4) /* Audio clock PLL select */
#define SSACD_ACDS(x) ((x) << 0) /* Audio clock divider select */
#define SSACD_ACDS_1 (0)
#define SSACD_ACDS_2 (1)
#define SSACD_ACDS_4 (2)
#define SSACD_ACDS_8 (3)
#define SSACD_ACDS_16 (4)
#define SSACD_ACDS_32 (5)
#define SSACD_SCDB_4X (0)
#define SSACD_SCDB_1X (1)
#define SSACD_SCDX8 (1 << 7) /* SYSCLK division ratio select */
/* LPSS SSP */
@ -212,8 +220,6 @@ struct ssp_device {
int type;
int use_count;
int irq;
int drcmr_rx;
int drcmr_tx;
struct device_node *of_node;
};

View File

@ -1,10 +1,8 @@
/*
* Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr>
/* SPDX-License-Identifier: GPL-2.0
*
* 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.
* Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr>
*/
#ifndef __SOUND_AC97_CODEC2_H
#define __SOUND_AC97_CODEC2_H

View File

@ -1,14 +1,11 @@
/*
* Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr>
/* SPDX-License-Identifier: GPL-2.0
*
* 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.
* Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr>
*
* This file is for backward compatibility with snd_ac97 structure and its
* multiple usages, such as the snd_ac97_bus and snd_ac97_build_ops.
*
*/
#ifndef AC97_COMPAT_H
#define AC97_COMPAT_H

View File

@ -1,10 +1,8 @@
/*
* Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr>
/* SPDX-License-Identifier: GPL-2.0
*
* 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.
* Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr>
*/
#ifndef AC97_CONTROLLER_H
#define AC97_CONTROLLER_H

View File

@ -1,27 +1,11 @@
/*
/* SPDX-License-Identifier: GPL-2.0+
*
* Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.1
* by Intel Corporation (http://developer.intel.com).
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/*
* AC'97 codec registers
*/

View File

@ -1,30 +1,15 @@
#ifndef __SOUND_AC97_CODEC_H
#define __SOUND_AC97_CODEC_H
/*
/* SPDX-License-Identifier: GPL-2.0+
*
* Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.1
* by Intel Corporation (http://developer.intel.com).
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __SOUND_AC97_CODEC_H
#define __SOUND_AC97_CODEC_H
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/workqueue.h>

View File

@ -1,27 +1,12 @@
/*
/* SPDX-License-Identifier: GPL-2.0
*
* compress_driver.h - compress offload driver definations
*
* Copyright (C) 2011 Intel Corporation
* Authors: Vinod Koul <vinod.koul@linux.intel.com>
* Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.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; version 2 of the License.
*
* 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*/
#ifndef __COMPRESS_DRIVER_H
#define __COMPRESS_DRIVER_H

View File

@ -1,17 +1,9 @@
/*
/* SPDX-License-Identifier: GPL-2.0+
*
* Copyright (C) 2012, Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* 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.
*
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __SOUND_DMAENGINE_PCM_H__
#define __SOUND_DMAENGINE_PCM_H__

View File

@ -0,0 +1,61 @@
// SPDX-License-Identifier: GPL-2.0
// HD-Audio helpers to sync with DRM driver
#ifndef __SOUND_HDA_COMPONENT_H
#define __SOUND_HDA_COMPONENT_H
#include <drm/drm_audio_component.h>
#ifdef CONFIG_SND_HDA_COMPONENT
int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable);
int snd_hdac_display_power(struct hdac_bus *bus, bool enable);
int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
int dev_id, int rate);
int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
bool *audio_enabled, char *buffer, int max_bytes);
int snd_hdac_acomp_init(struct hdac_bus *bus,
const struct drm_audio_component_audio_ops *aops,
int (*match_master)(struct device *, void *),
size_t extra_size);
int snd_hdac_acomp_exit(struct hdac_bus *bus);
int snd_hdac_acomp_register_notifier(struct hdac_bus *bus,
const struct drm_audio_component_audio_ops *ops);
#else
static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
{
return 0;
}
static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
{
return 0;
}
static inline int snd_hdac_sync_audio_rate(struct hdac_device *codec,
hda_nid_t nid, int dev_id, int rate)
{
return 0;
}
static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid,
int dev_id, bool *audio_enabled,
char *buffer, int max_bytes)
{
return -ENODEV;
}
static inline int snd_hdac_acomp_init(struct hdac_bus *bus,
const struct drm_audio_component_audio_ops *aops,
int (*match_master)(struct device *, void *),
size_t extra_size)
{
return -ENODEV;
}
static inline int snd_hdac_acomp_exit(struct hdac_bus *bus)
{
return 0;
}
static inline int snd_hdac_acomp_register_notifier(struct hdac_bus *bus,
const struct drm_audio_component_audio_ops *ops)
{
return -ENODEV;
}
#endif
#endif /* __SOUND_HDA_COMPONENT_H */

View File

@ -5,54 +5,23 @@
#ifndef __SOUND_HDA_I915_H
#define __SOUND_HDA_I915_H
#include <drm/i915_component.h>
#include "hda_component.h"
#ifdef CONFIG_SND_HDA_I915
int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable);
int snd_hdac_display_power(struct hdac_bus *bus, bool enable);
void snd_hdac_i915_set_bclk(struct hdac_bus *bus);
int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
int dev_id, int rate);
int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
bool *audio_enabled, char *buffer, int max_bytes);
int snd_hdac_i915_init(struct hdac_bus *bus);
int snd_hdac_i915_exit(struct hdac_bus *bus);
int snd_hdac_i915_register_notifier(const struct i915_audio_component_audio_ops *);
#else
static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
{
return 0;
}
static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
{
return 0;
}
static inline void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
{
}
static inline int snd_hdac_sync_audio_rate(struct hdac_device *codec,
hda_nid_t nid, int dev_id, int rate)
{
return 0;
}
static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid,
int dev_id, bool *audio_enabled,
char *buffer, int max_bytes)
{
return -ENODEV;
}
static inline int snd_hdac_i915_init(struct hdac_bus *bus)
{
return -ENODEV;
}
#endif
static inline int snd_hdac_i915_exit(struct hdac_bus *bus)
{
return 0;
return snd_hdac_acomp_exit(bus);
}
static inline int snd_hdac_i915_register_notifier(const struct i915_audio_component_audio_ops *ops)
{
return -ENODEV;
}
#endif
#endif /* __SOUND_HDA_I915_H */

View File

@ -188,6 +188,11 @@ struct hdac_driver {
const struct hda_device_id *id_table;
int (*match)(struct hdac_device *dev, struct hdac_driver *drv);
void (*unsol_event)(struct hdac_device *dev, unsigned int event);
/* fields used by ext bus APIs */
int (*probe)(struct hdac_device *dev);
int (*remove)(struct hdac_device *dev);
void (*shutdown)(struct hdac_device *dev);
};
#define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver)
@ -208,6 +213,14 @@ struct hdac_bus_ops {
int (*link_power)(struct hdac_bus *bus, bool enable);
};
/*
* ops used for ASoC HDA codec drivers
*/
struct hdac_ext_bus_ops {
int (*hdev_attach)(struct hdac_device *hdev);
int (*hdev_detach)(struct hdac_device *hdev);
};
/*
* Lowlevel I/O operators
*/
@ -250,11 +263,17 @@ struct hdac_rb {
* @mlcap: MultiLink capabilities pointer
* @gtscap: gts capabilities pointer
* @drsmcap: dma resume capabilities pointer
* @num_streams: streams supported
* @idx: HDA link index
* @hlink_list: link list of HDA links
* @lock: lock for link mgmt
* @cmd_dma_state: state of cmd DMAs: CORB and RIRB
*/
struct hdac_bus {
struct device *dev;
const struct hdac_bus_ops *ops;
const struct hdac_io_ops *io_ops;
const struct hdac_ext_bus_ops *ext_ops;
/* h/w resources */
unsigned long addr;
@ -314,9 +333,19 @@ struct hdac_bus {
spinlock_t reg_lock;
struct mutex cmd_mutex;
/* i915 component interface */
struct i915_audio_component *audio_component;
int i915_power_refcount;
/* DRM component interface */
struct drm_audio_component *audio_component;
int drm_power_refcount;
/* parameters required for enhanced capabilities */
int num_streams;
int idx;
struct list_head hlink_list;
struct mutex lock;
bool cmd_dma_state;
};
int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,

View File

@ -4,38 +4,16 @@
#include <sound/hdaudio.h>
/**
* hdac_ext_bus: HDAC extended bus for extended HDA caps
*
* @bus: hdac bus
* @num_streams: streams supported
* @hlink_list: link list of HDA links
* @lock: lock for link mgmt
* @cmd_dma_state: state of cmd DMAs: CORB and RIRB
*/
struct hdac_ext_bus {
struct hdac_bus bus;
int num_streams;
int idx;
struct list_head hlink_list;
struct mutex lock;
bool cmd_dma_state;
};
int snd_hdac_ext_bus_init(struct hdac_ext_bus *sbus, struct device *dev,
int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev,
const struct hdac_bus_ops *ops,
const struct hdac_io_ops *io_ops);
const struct hdac_io_ops *io_ops,
const struct hdac_ext_bus_ops *ext_ops);
void snd_hdac_ext_bus_exit(struct hdac_ext_bus *sbus);
int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *sbus, int addr);
void snd_hdac_ext_bus_exit(struct hdac_bus *bus);
int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr,
struct hdac_device *hdev);
void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev);
void snd_hdac_ext_bus_device_remove(struct hdac_ext_bus *ebus);
#define ebus_to_hbus(ebus) (&(ebus)->bus)
#define hbus_to_ebus(_bus) \
container_of(_bus, struct hdac_ext_bus, bus)
void snd_hdac_ext_bus_device_remove(struct hdac_bus *bus);
#define HDA_CODEC_REV_EXT_ENTRY(_vid, _rev, _name, drv_data) \
{ .vendor_id = (_vid), .rev_id = (_rev), .name = (_name), \
@ -44,14 +22,14 @@ void snd_hdac_ext_bus_device_remove(struct hdac_ext_bus *ebus);
#define HDA_CODEC_EXT_ENTRY(_vid, _revid, _name, _drv_data) \
HDA_CODEC_REV_EXT_ENTRY(_vid, _revid, _name, _drv_data)
void snd_hdac_ext_bus_ppcap_enable(struct hdac_ext_bus *chip, bool enable);
void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_ext_bus *chip, bool enable);
void snd_hdac_ext_bus_ppcap_enable(struct hdac_bus *chip, bool enable);
void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_bus *chip, bool enable);
void snd_hdac_ext_stream_spbcap_enable(struct hdac_ext_bus *chip,
void snd_hdac_ext_stream_spbcap_enable(struct hdac_bus *chip,
bool enable, int index);
int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *bus);
struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_ext_bus *bus,
int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_bus *bus);
struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_bus *bus,
const char *codec_name);
enum hdac_ext_stream_type {
@ -100,28 +78,28 @@ struct hdac_ext_stream {
#define stream_to_hdac_ext_stream(s) \
container_of(s, struct hdac_ext_stream, hstream)
void snd_hdac_ext_stream_init(struct hdac_ext_bus *bus,
void snd_hdac_ext_stream_init(struct hdac_bus *bus,
struct hdac_ext_stream *stream, int idx,
int direction, int tag);
int snd_hdac_ext_stream_init_all(struct hdac_ext_bus *ebus, int start_idx,
int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx,
int num_stream, int dir);
void snd_hdac_stream_free_all(struct hdac_ext_bus *ebus);
void snd_hdac_link_free_all(struct hdac_ext_bus *ebus);
struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_ext_bus *bus,
void snd_hdac_stream_free_all(struct hdac_bus *bus);
void snd_hdac_link_free_all(struct hdac_bus *bus);
struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus,
struct snd_pcm_substream *substream,
int type);
void snd_hdac_ext_stream_release(struct hdac_ext_stream *azx_dev, int type);
void snd_hdac_ext_stream_decouple(struct hdac_ext_bus *bus,
void snd_hdac_ext_stream_decouple(struct hdac_bus *bus,
struct hdac_ext_stream *azx_dev, bool decouple);
void snd_hdac_ext_stop_streams(struct hdac_ext_bus *sbus);
void snd_hdac_ext_stop_streams(struct hdac_bus *bus);
int snd_hdac_ext_stream_set_spib(struct hdac_ext_bus *ebus,
int snd_hdac_ext_stream_set_spib(struct hdac_bus *bus,
struct hdac_ext_stream *stream, u32 value);
int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_ext_bus *ebus,
int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_bus *bus,
struct hdac_ext_stream *stream);
void snd_hdac_ext_stream_drsm_enable(struct hdac_ext_bus *ebus,
void snd_hdac_ext_stream_drsm_enable(struct hdac_bus *bus,
bool enable, int index);
int snd_hdac_ext_stream_set_dpibr(struct hdac_ext_bus *ebus,
int snd_hdac_ext_stream_set_dpibr(struct hdac_bus *bus,
struct hdac_ext_stream *stream, u32 value);
int snd_hdac_ext_stream_set_lpib(struct hdac_ext_stream *stream, u32 value);
@ -144,17 +122,15 @@ struct hdac_ext_link {
int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *link);
int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *link);
int snd_hdac_ext_bus_link_power_up_all(struct hdac_ext_bus *ebus);
int snd_hdac_ext_bus_link_power_down_all(struct hdac_ext_bus *ebus);
int snd_hdac_ext_bus_link_power_up_all(struct hdac_bus *bus);
int snd_hdac_ext_bus_link_power_down_all(struct hdac_bus *bus);
void snd_hdac_ext_link_set_stream_id(struct hdac_ext_link *link,
int stream);
void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link,
int stream);
int snd_hdac_ext_bus_link_get(struct hdac_ext_bus *ebus,
struct hdac_ext_link *link);
int snd_hdac_ext_bus_link_put(struct hdac_ext_bus *ebus,
struct hdac_ext_link *link);
int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, struct hdac_ext_link *link);
int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *link);
/* update register macro */
#define snd_hdac_updatel(addr, reg, mask, val) \
@ -181,53 +157,12 @@ struct hda_dai_map {
u32 maxbps;
};
#define HDA_MAX_NIDS 16
/**
* struct hdac_ext_device - HDAC Ext device
*
* @hdac: hdac core device
* @nid_list - the dai map which matches the dai-name with the nid
* @map_cur_idx - the idx in use in dai_map
* @ops - the hda codec ops common to all codec drivers
* @pvt_data - private data, for asoc contains asoc codec object
*/
struct hdac_ext_device {
struct hdac_device hdev;
struct hdac_ext_bus *ebus;
/* soc-dai to nid map */
struct hda_dai_map nid_list[HDA_MAX_NIDS];
unsigned int map_cur_idx;
/* codec ops */
struct hdac_ext_codec_ops ops;
struct snd_card *card;
void *scodec;
void *private_data;
};
struct hdac_ext_dma_params {
u32 format;
u8 stream_tag;
};
#define to_ehdac_device(dev) (container_of((dev), \
struct hdac_ext_device, hdev))
/*
* HD-audio codec base driver
*/
struct hdac_ext_driver {
struct hdac_driver hdac;
int (*probe)(struct hdac_ext_device *dev);
int (*remove)(struct hdac_ext_device *dev);
void (*shutdown)(struct hdac_ext_device *dev);
};
int snd_hda_ext_driver_register(struct hdac_ext_driver *drv);
void snd_hda_ext_driver_unregister(struct hdac_ext_driver *drv);
#define to_ehdac_driver(_drv) container_of(_drv, struct hdac_ext_driver, hdac)
int snd_hda_ext_driver_register(struct hdac_driver *drv);
void snd_hda_ext_driver_unregister(struct hdac_driver *drv);
#endif /* __SOUND_HDAUDIO_EXT_H */

View File

@ -24,6 +24,8 @@
#ifndef __SOUND_MEMALLOC_H
#define __SOUND_MEMALLOC_H
#include <asm/page.h>
struct device;
/*
@ -67,6 +69,14 @@ struct snd_dma_buffer {
void *private_data; /* private for allocator; don't touch */
};
/*
* return the pages matching with the given byte size
*/
static inline unsigned int snd_sgbuf_aligned_pages(size_t size)
{
return (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
}
#ifdef CONFIG_SND_DMA_SGBUF
/*
* Scatter-Gather generic device pages
@ -90,14 +100,6 @@ struct snd_sg_buf {
struct device *dev;
};
/*
* return the pages matching with the given byte size
*/
static inline unsigned int snd_sgbuf_aligned_pages(size_t size)
{
return (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
}
/*
* return the physical address at the corresponding offset
*/

View File

@ -87,6 +87,13 @@ static inline void snd_mask_set(struct snd_mask *mask, unsigned int val)
mask->bits[MASK_OFS(val)] |= MASK_BIT(val);
}
/* Most of drivers need only this one */
static inline void snd_mask_set_format(struct snd_mask *mask,
snd_pcm_format_t format)
{
snd_mask_set(mask, (__force unsigned int)format);
}
static inline void snd_mask_reset(struct snd_mask *mask, unsigned int val)
{
mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val);
@ -369,8 +376,7 @@ static inline int params_physical_width(const struct snd_pcm_hw_params *p)
static inline void
params_set_format(struct snd_pcm_hw_params *p, snd_pcm_format_t fmt)
{
snd_mask_set(hw_param_mask(p, SNDRV_PCM_HW_PARAM_FORMAT),
(__force int)fmt);
snd_mask_set_format(hw_param_mask(p, SNDRV_PCM_HW_PARAM_FORMAT), fmt);
}
#endif /* __SOUND_PCM_PARAMS_H */

View File

@ -8,20 +8,23 @@
/* PCM */
struct snd_pcm_substream;
struct snd_pcm_hw_params;
struct snd_soc_pcm_runtime;
struct snd_pcm;
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);
extern int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream);
extern int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream);
extern int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
extern snd_pcm_uframes_t pxa2xx_pcm_pointer(struct snd_pcm_substream *substream);
extern int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream);
extern int __pxa2xx_pcm_open(struct snd_pcm_substream *substream);
extern int __pxa2xx_pcm_close(struct snd_pcm_substream *substream);
extern int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream);
extern int pxa2xx_pcm_open(struct snd_pcm_substream *substream);
extern int pxa2xx_pcm_close(struct snd_pcm_substream *substream);
extern int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma);
extern int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream);
extern void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm);
extern int pxa2xx_soc_pcm_new(struct snd_soc_pcm_runtime *rtd);
extern const struct snd_pcm_ops pxa2xx_pcm_ops;
/* AC97 */

40
include/sound/rt5682.h Normal file
View File

@ -0,0 +1,40 @@
/*
* linux/sound/rt5682.h -- Platform data for RT5682
*
* Copyright 2018 Realtek Microelectronics
*
* 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 __LINUX_SND_RT5682_H
#define __LINUX_SND_RT5682_H
enum rt5682_dmic1_data_pin {
RT5682_DMIC1_NULL,
RT5682_DMIC1_DATA_GPIO2,
RT5682_DMIC1_DATA_GPIO5,
};
enum rt5682_dmic1_clk_pin {
RT5682_DMIC1_CLK_GPIO1,
RT5682_DMIC1_CLK_GPIO3,
};
enum rt5682_jd_src {
RT5682_JD_NULL,
RT5682_JD1,
};
struct rt5682_platform_data {
int ldo1_en; /* GPIO for LDO1_EN */
enum rt5682_dmic1_data_pin dmic1_data_pin;
enum rt5682_dmic1_clk_pin dmic1_clk_pin;
enum rt5682_jd_src jd_src;
};
#endif

View File

@ -1,16 +1,13 @@
#ifndef __SOUND_FSI_H
#define __SOUND_FSI_H
/*
/* SPDX-License-Identifier: GPL-2.0
*
* Fifo-attached Serial Interface (FSI) support for SH7724
*
* Copyright (C) 2009 Renesas Solutions Corp.
* Kuninori Morimoto <morimoto.kuninori@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 __SOUND_FSI_H
#define __SOUND_FSI_H
#include <linux/clk.h>
#include <sound/soc.h>

View File

@ -1,12 +1,9 @@
/*
/* SPDX-License-Identifier: GPL-2.0
*
* ASoC simple sound card support
*
* Copyright (C) 2012 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 __SIMPLE_CARD_H

View File

@ -1,17 +1,20 @@
/*
/* SPDX-License-Identifier: GPL-2.0
*
* simple_card_utils.h
*
* Copyright (c) 2016 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 __SIMPLE_CARD_UTILS_H
#define __SIMPLE_CARD_UTILS_H
#include <sound/soc.h>
#define asoc_simple_card_init_hp(card, sjack, prefix) \
asoc_simple_card_init_jack(card, sjack, 1, prefix)
#define asoc_simple_card_init_mic(card, sjack, prefix) \
asoc_simple_card_init_jack(card, sjack, 0, prefix)
struct asoc_simple_dai {
const char *name;
unsigned int sysclk;
@ -28,6 +31,12 @@ struct asoc_simple_card_data {
u32 convert_channels;
};
struct asoc_simple_jack {
struct snd_soc_jack jack;
struct snd_soc_jack_pin pin;
struct snd_soc_jack_gpio gpio;
};
int asoc_simple_card_parse_daifmt(struct device *dev,
struct device_node *node,
struct device_node *codec,
@ -107,4 +116,8 @@ int asoc_simple_card_of_parse_routing(struct snd_soc_card *card,
int asoc_simple_card_of_parse_widgets(struct snd_soc_card *card,
char *prefix);
int asoc_simple_card_init_jack(struct snd_soc_card *card,
struct asoc_simple_jack *sjack,
int is_hp, char *prefix);
#endif /* __SIMPLE_CARD_UTILS_H */

View File

@ -1,16 +1,6 @@
/*
/* SPDX-License-Identifier: GPL-2.0
*
* Copyright (C) 2017, Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __LINUX_SND_SOC_ACPI_INTEL_MATCH_H
@ -29,5 +19,10 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_broadwell_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_baytrail_legacy_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_baytrail_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cherrytrail_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_skl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[];
#endif

View File

@ -1,15 +1,6 @@
/*
/* SPDX-License-Identifier: GPL-2.0
*
* Copyright (C) 2013-15, Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __LINUX_SND_SOC_ACPI_H

View File

@ -1,12 +1,9 @@
/*
/* SPDX-License-Identifier: GPL-2.0
*
* linux/sound/soc-dai.h -- ALSA SoC Layer
*
* Copyright: 2005-2008 Wolfson Microelectronics. PLC.
*
* 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.
*
* Digital Audio Interface (DAI) API.
*/
@ -141,6 +138,11 @@ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
int direction);
int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai,
unsigned int *tx_num, unsigned int *tx_slot,
unsigned int *rx_num, unsigned int *rx_slot);
int snd_soc_dai_is_dummy(struct snd_soc_dai *dai);
struct snd_soc_dai_ops {
@ -168,6 +170,9 @@ struct snd_soc_dai_ops {
int (*set_channel_map)(struct snd_soc_dai *dai,
unsigned int tx_num, unsigned int *tx_slot,
unsigned int rx_num, unsigned int *rx_slot);
int (*get_channel_map)(struct snd_soc_dai *dai,
unsigned int *tx_num, unsigned int *tx_slot,
unsigned int *rx_num, unsigned int *rx_slot);
int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
int (*set_sdw_stream)(struct snd_soc_dai *dai,

View File

@ -1,13 +1,10 @@
/*
/* SPDX-License-Identifier: GPL-2.0
*
* linux/sound/soc-dapm.h -- ALSA SoC Dynamic Audio Power Management
*
* Author: Liam Girdwood
* Created: Aug 11th 2005
* Author: Liam Girdwood
* Created: Aug 11th 2005
* Copyright: Wolfson Microelectronics. PLC.
*
* 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 __LINUX_SND_SOC_DAPM_H

View File

@ -1,11 +1,8 @@
/*
/* SPDX-License-Identifier: GPL-2.0
*
* linux/sound/soc-dpcm.h -- ALSA SoC Dynamic PCM Support
*
* Author: Liam Girdwood <lrg@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.
*/
#ifndef __LINUX_SND_SOC_DPCM_H

View File

@ -1,13 +1,10 @@
/*
/* SPDX-License-Identifier: GPL-2.0
*
* linux/sound/soc-topology.h -- ALSA SoC Firmware Controls and DAPM
*
* Copyright (C) 2012 Texas Instruments Inc.
* Copyright (C) 2015 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Simple file API to load FW that includes mixers, coefficients, DAPM graphs,
* algorithms, equalisers, DAIs, widgets, FE caps, BE caps, codec link caps etc.
*/
@ -30,6 +27,9 @@ struct snd_soc_dapm_context;
struct snd_soc_card;
struct snd_kcontrol_new;
struct snd_soc_dai_link;
struct snd_soc_dai_driver;
struct snd_soc_dai;
struct snd_soc_dapm_route;
/* object scan be loaded and unloaded in groups with identfying indexes */
#define SND_SOC_TPLG_INDEX_ALL 0 /* ID that matches all FW objects */
@ -109,35 +109,44 @@ struct snd_soc_tplg_widget_events {
struct snd_soc_tplg_ops {
/* external kcontrol init - used for any driver specific init */
int (*control_load)(struct snd_soc_component *,
int (*control_load)(struct snd_soc_component *, int index,
struct snd_kcontrol_new *, struct snd_soc_tplg_ctl_hdr *);
int (*control_unload)(struct snd_soc_component *,
struct snd_soc_dobj *);
/* DAPM graph route element loading and unloading */
int (*dapm_route_load)(struct snd_soc_component *, int index,
struct snd_soc_dapm_route *route);
int (*dapm_route_unload)(struct snd_soc_component *,
struct snd_soc_dobj *);
/* external widget init - used for any driver specific init */
int (*widget_load)(struct snd_soc_component *,
int (*widget_load)(struct snd_soc_component *, int index,
struct snd_soc_dapm_widget *,
struct snd_soc_tplg_dapm_widget *);
int (*widget_ready)(struct snd_soc_component *,
int (*widget_ready)(struct snd_soc_component *, int index,
struct snd_soc_dapm_widget *,
struct snd_soc_tplg_dapm_widget *);
int (*widget_unload)(struct snd_soc_component *,
struct snd_soc_dobj *);
/* FE DAI - used for any driver specific init */
int (*dai_load)(struct snd_soc_component *,
struct snd_soc_dai_driver *dai_drv);
int (*dai_load)(struct snd_soc_component *, int index,
struct snd_soc_dai_driver *dai_drv,
struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai);
int (*dai_unload)(struct snd_soc_component *,
struct snd_soc_dobj *);
/* DAI link - used for any driver specific init */
int (*link_load)(struct snd_soc_component *,
struct snd_soc_dai_link *link);
int (*link_load)(struct snd_soc_component *, int index,
struct snd_soc_dai_link *link,
struct snd_soc_tplg_link_config *cfg);
int (*link_unload)(struct snd_soc_component *,
struct snd_soc_dobj *);
/* callback to handle vendor bespoke data */
int (*vendor_load)(struct snd_soc_component *,
int (*vendor_load)(struct snd_soc_component *, int index,
struct snd_soc_tplg_hdr *);
int (*vendor_unload)(struct snd_soc_component *,
struct snd_soc_tplg_hdr *);
@ -146,7 +155,7 @@ struct snd_soc_tplg_ops {
void (*complete)(struct snd_soc_component *);
/* manifest - optional to inform component of manifest */
int (*manifest)(struct snd_soc_component *,
int (*manifest)(struct snd_soc_component *, int index,
struct snd_soc_tplg_manifest *);
/* vendor specific kcontrol handlers available for binding */

View File

@ -1,13 +1,10 @@
/*
/* SPDX-License-Identifier: GPL-2.0
*
* linux/sound/soc.h -- ALSA SoC Layer
*
* Author: Liam Girdwood
* Created: Aug 11th 2005
* Author: Liam Girdwood
* Created: Aug 11th 2005
* Copyright: Wolfson Microelectronics. PLC.
*
* 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 __LINUX_SND_SOC_H
@ -806,6 +803,14 @@ struct snd_soc_component_driver {
unsigned int use_pmdown_time:1; /* care pmdown_time at stop */
unsigned int endianness:1;
unsigned int non_legacy_dai_naming:1;
/* this component uses topology and ignore machine driver FEs */
const char *ignore_machine;
const char *topology_name_prefix;
int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
bool use_dai_pcm_id; /* use the DAI link PCM ID as PCM device number */
int be_pcm_base; /* base device ID for all BE PCMs */
};
struct snd_soc_component {
@ -957,10 +962,17 @@ struct snd_soc_dai_link {
/* DPCM used FE & BE merged format */
unsigned int dpcm_merged_format:1;
/* DPCM used FE & BE merged channel */
unsigned int dpcm_merged_chan:1;
/* DPCM used FE & BE merged rate */
unsigned int dpcm_merged_rate:1;
/* pmdown_time is ignored at stop */
unsigned int ignore_pmdown_time:1;
/* Do not create a PCM for this DAI link (Backend link) */
unsigned int ignore:1;
struct list_head list; /* DAI link list of the soc card */
struct snd_soc_dobj dobj; /* For topology */
};
@ -1000,6 +1012,7 @@ struct snd_soc_card {
const char *long_name;
const char *driver_name;
char dmi_longname[80];
char topology_shortname[32];
struct device *dev;
struct snd_card *snd_card;
@ -1009,6 +1022,7 @@ struct snd_soc_card {
struct mutex dapm_mutex;
bool instantiated;
bool topology_shortname_created;
int (*probe)(struct snd_soc_card *card);
int (*late_probe)(struct snd_soc_card *card);
@ -1412,6 +1426,9 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card,
const char *propname);
int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
const char *propname);
int snd_soc_of_get_slot_mask(struct device_node *np,
const char *prop_name,
unsigned int *mask);
int snd_soc_of_parse_tdm_slot(struct device_node *np,
unsigned int *tx_mask,
unsigned int *rx_mask,

View File

@ -192,6 +192,42 @@ DEFINE_EVENT(clk_phase, clk_set_phase_complete,
TP_ARGS(core, phase)
);
DECLARE_EVENT_CLASS(clk_duty_cycle,
TP_PROTO(struct clk_core *core, struct clk_duty *duty),
TP_ARGS(core, duty),
TP_STRUCT__entry(
__string( name, core->name )
__field( unsigned int, num )
__field( unsigned int, den )
),
TP_fast_assign(
__assign_str(name, core->name);
__entry->num = duty->num;
__entry->den = duty->den;
),
TP_printk("%s %u/%u", __get_str(name), (unsigned int)__entry->num,
(unsigned int)__entry->den)
);
DEFINE_EVENT(clk_duty_cycle, clk_set_duty_cycle,
TP_PROTO(struct clk_core *core, struct clk_duty *duty),
TP_ARGS(core, duty)
);
DEFINE_EVENT(clk_duty_cycle, clk_set_duty_cycle_complete,
TP_PROTO(struct clk_core *core, struct clk_duty *duty),
TP_ARGS(core, duty)
);
#endif /* _TRACE_CLK_H */
/* This part must be outside protection */

View File

@ -17,14 +17,9 @@ config SND_ARMAACI
select SND_PCM
select SND_AC97_CODEC
config SND_PXA2XX_PCM
tristate
select SND_PCM
config SND_PXA2XX_AC97
tristate "AC97 driver for the Intel PXA2xx chip"
depends on ARCH_PXA
select SND_PXA2XX_PCM
select SND_AC97_CODEC
select SND_PXA2XX_LIB
select SND_PXA2XX_LIB_AC97

View File

@ -6,9 +6,6 @@
obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o
snd-aaci-objs := aaci.o
obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o
snd-pxa2xx-pcm-objs := pxa2xx-pcm.o
obj-$(CONFIG_SND_PXA2XX_LIB) += snd-pxa2xx-lib.o
snd-pxa2xx-lib-y := pxa2xx-pcm-lib.o
snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o

View File

@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <sound/pxa2xx-lib.h>
@ -337,6 +338,17 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev)
dev_err(&dev->dev, "Invalid reset GPIO %d\n",
pdata->reset_gpio);
}
} else if (!pdata && dev->dev.of_node) {
pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
pdata->reset_gpio = of_get_named_gpio(dev->dev.of_node,
"reset-gpios", 0);
if (pdata->reset_gpio == -ENOENT)
pdata->reset_gpio = -1;
else if (pdata->reset_gpio < 0)
return pdata->reset_gpio;
reset_gpio = pdata->reset_gpio;
} else {
if (cpu_is_pxa27x())
reset_gpio = 113;

View File

@ -15,7 +15,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/dmaengine.h>
#include <linux/dma/pxa-dma.h>
#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/pcm.h>
@ -27,8 +27,6 @@
#include <mach/regs-ac97.h>
#include <mach/audio.h>
#include "pxa2xx-pcm.h"
static void pxa2xx_ac97_legacy_reset(struct snd_ac97 *ac97)
{
if (!pxa2xx_ac97_try_cold_reset())
@ -63,61 +61,46 @@ static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
.reset = pxa2xx_ac97_legacy_reset,
};
static struct pxad_param pxa2xx_ac97_pcm_out_req = {
.prio = PXAD_PRIO_LOWEST,
.drcmr = 12,
};
static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_out = {
.addr = __PREG(PCDR),
.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
.maxburst = 32,
.filter_data = &pxa2xx_ac97_pcm_out_req,
};
static struct pxad_param pxa2xx_ac97_pcm_in_req = {
.prio = PXAD_PRIO_LOWEST,
.drcmr = 11,
};
static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_in = {
.addr = __PREG(PCDR),
.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
.maxburst = 32,
.filter_data = &pxa2xx_ac97_pcm_in_req,
};
static struct snd_pcm *pxa2xx_ac97_pcm;
static struct snd_ac97 *pxa2xx_ac97_ac97;
static int pxa2xx_ac97_pcm_startup(struct snd_pcm_substream *substream)
static int pxa2xx_ac97_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
pxa2xx_audio_ops_t *platform_ops;
int r;
int ret, i;
ret = pxa2xx_pcm_open(substream);
if (ret)
return ret;
runtime->hw.channels_min = 2;
runtime->hw.channels_max = 2;
r = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
AC97_RATES_FRONT_DAC : AC97_RATES_ADC;
runtime->hw.rates = pxa2xx_ac97_ac97->rates[r];
i = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
AC97_RATES_FRONT_DAC : AC97_RATES_ADC;
runtime->hw.rates = pxa2xx_ac97_ac97->rates[i];
snd_pcm_limit_hw_rates(runtime);
platform_ops = substream->pcm->card->dev->platform_data;
if (platform_ops && platform_ops->startup)
return platform_ops->startup(substream, platform_ops->priv);
else
return 0;
platform_ops = substream->pcm->card->dev->platform_data;
if (platform_ops && platform_ops->startup) {
ret = platform_ops->startup(substream, platform_ops->priv);
if (ret < 0)
pxa2xx_pcm_close(substream);
}
return ret;
}
static void pxa2xx_ac97_pcm_shutdown(struct snd_pcm_substream *substream)
static int pxa2xx_ac97_pcm_close(struct snd_pcm_substream *substream)
{
pxa2xx_audio_ops_t *platform_ops;
platform_ops = substream->pcm->card->dev->platform_data;
platform_ops = substream->pcm->card->dev->platform_data;
if (platform_ops && platform_ops->shutdown)
platform_ops->shutdown(substream, platform_ops->priv);
return 0;
}
static int pxa2xx_ac97_pcm_prepare(struct snd_pcm_substream *substream)
@ -125,17 +108,15 @@ static int pxa2xx_ac97_pcm_prepare(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
int ret;
ret = pxa2xx_pcm_prepare(substream);
if (ret < 0)
return ret;
return snd_ac97_set_rate(pxa2xx_ac97_ac97, reg, runtime->rate);
}
static struct pxa2xx_pcm_client pxa2xx_ac97_pcm_client = {
.playback_params = &pxa2xx_ac97_pcm_out,
.capture_params = &pxa2xx_ac97_pcm_in,
.startup = pxa2xx_ac97_pcm_startup,
.shutdown = pxa2xx_ac97_pcm_shutdown,
.prepare = pxa2xx_ac97_pcm_prepare,
};
#ifdef CONFIG_PM_SLEEP
static int pxa2xx_ac97_do_suspend(struct snd_card *card)
@ -193,6 +174,53 @@ static int pxa2xx_ac97_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops, pxa2xx_ac97_suspend, pxa2xx_ac97_resume);
#endif
static const struct snd_pcm_ops pxa2xx_ac97_pcm_ops = {
.open = pxa2xx_ac97_pcm_open,
.close = pxa2xx_ac97_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pxa2xx_pcm_hw_params,
.hw_free = pxa2xx_pcm_hw_free,
.prepare = pxa2xx_ac97_pcm_prepare,
.trigger = pxa2xx_pcm_trigger,
.pointer = pxa2xx_pcm_pointer,
.mmap = pxa2xx_pcm_mmap,
};
static int pxa2xx_ac97_pcm_new(struct snd_card *card)
{
struct snd_pcm *pcm;
int stream, ret;
ret = snd_pcm_new(card, "PXA2xx-PCM", 0, 1, 1, &pcm);
if (ret)
goto out;
pcm->private_free = pxa2xx_pcm_free_dma_buffers;
ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
if (ret)
goto out;
stream = SNDRV_PCM_STREAM_PLAYBACK;
snd_pcm_set_ops(pcm, stream, &pxa2xx_ac97_pcm_ops);
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
if (ret)
goto out;
stream = SNDRV_PCM_STREAM_CAPTURE;
snd_pcm_set_ops(pcm, stream, &pxa2xx_ac97_pcm_ops);
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
if (ret)
goto out;
pxa2xx_ac97_pcm = pcm;
ret = 0;
out:
return ret;
}
static int pxa2xx_ac97_probe(struct platform_device *dev)
{
struct snd_card *card;
@ -214,7 +242,7 @@ static int pxa2xx_ac97_probe(struct platform_device *dev)
strlcpy(card->driver, dev->dev.driver->name, sizeof(card->driver));
ret = pxa2xx_pcm_new(card, &pxa2xx_ac97_pcm_client, &pxa2xx_ac97_pcm);
ret = pxa2xx_ac97_pcm_new(card);
if (ret)
goto err;

View File

@ -16,8 +16,6 @@
#include <sound/pxa2xx-lib.h>
#include <sound/dmaengine_pcm.h>
#include "pxa2xx-pcm.h"
static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@ -25,8 +23,8 @@ static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_RESUME,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
.period_bytes_min = 32,
.period_bytes_max = 8192 - 32,
.periods_min = 1,
@ -35,8 +33,8 @@ static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
.fifo_size = 32,
};
int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@ -64,14 +62,14 @@ int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
EXPORT_SYMBOL(__pxa2xx_pcm_hw_params);
EXPORT_SYMBOL(pxa2xx_pcm_hw_params);
int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
{
snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
}
EXPORT_SYMBOL(__pxa2xx_pcm_hw_free);
EXPORT_SYMBOL(pxa2xx_pcm_hw_free);
int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
@ -86,13 +84,13 @@ pxa2xx_pcm_pointer(struct snd_pcm_substream *substream)
}
EXPORT_SYMBOL(pxa2xx_pcm_pointer);
int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
{
return 0;
}
EXPORT_SYMBOL(__pxa2xx_pcm_prepare);
EXPORT_SYMBOL(pxa2xx_pcm_prepare);
int __pxa2xx_pcm_open(struct snd_pcm_substream *substream)
int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
@ -125,17 +123,17 @@ int __pxa2xx_pcm_open(struct snd_pcm_substream *substream)
if (ret < 0)
return ret;
return snd_dmaengine_pcm_open_request_chan(substream,
pxad_filter_fn,
dma_params->filter_data);
return snd_dmaengine_pcm_open(
substream, dma_request_slave_channel(rtd->cpu_dai->dev,
dma_params->chan_name));
}
EXPORT_SYMBOL(__pxa2xx_pcm_open);
EXPORT_SYMBOL(pxa2xx_pcm_open);
int __pxa2xx_pcm_close(struct snd_pcm_substream *substream)
int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
{
return snd_dmaengine_pcm_close_release_chan(substream);
}
EXPORT_SYMBOL(__pxa2xx_pcm_close);
EXPORT_SYMBOL(pxa2xx_pcm_close);
int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
@ -181,6 +179,47 @@ void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
}
EXPORT_SYMBOL(pxa2xx_pcm_free_dma_buffers);
int pxa2xx_soc_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
int ret;
ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
goto out;
}
out:
return ret;
}
EXPORT_SYMBOL(pxa2xx_soc_pcm_new);
const struct snd_pcm_ops pxa2xx_pcm_ops = {
.open = pxa2xx_pcm_open,
.close = pxa2xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pxa2xx_pcm_hw_params,
.hw_free = pxa2xx_pcm_hw_free,
.prepare = pxa2xx_pcm_prepare,
.trigger = pxa2xx_pcm_trigger,
.pointer = pxa2xx_pcm_pointer,
.mmap = pxa2xx_pcm_mmap,
};
EXPORT_SYMBOL(pxa2xx_pcm_ops);
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("Intel PXA2xx sound library");
MODULE_LICENSE("GPL");

View File

@ -1,129 +0,0 @@
/*
* linux/sound/arm/pxa2xx-pcm.c -- ALSA PCM interface for the Intel PXA2xx chip
*
* Author: Nicolas Pitre
* Created: Nov 30, 2004
* Copyright: (C) 2004 MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <mach/dma.h>
#include <sound/core.h>
#include <sound/pxa2xx-lib.h>
#include <sound/dmaengine_pcm.h>
#include "pxa2xx-pcm.h"
static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
{
struct pxa2xx_pcm_client *client = substream->private_data;
__pxa2xx_pcm_prepare(substream);
return client->prepare(substream);
}
static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
{
struct pxa2xx_pcm_client *client = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
struct pxa2xx_runtime_data *rtd;
int ret;
ret = __pxa2xx_pcm_open(substream);
if (ret)
goto out;
rtd = runtime->private_data;
rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
client->playback_params : client->capture_params;
ret = client->startup(substream);
if (!ret)
goto err2;
return 0;
err2:
__pxa2xx_pcm_close(substream);
out:
return ret;
}
static int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
{
struct pxa2xx_pcm_client *client = substream->private_data;
client->shutdown(substream);
return __pxa2xx_pcm_close(substream);
}
static const struct snd_pcm_ops pxa2xx_pcm_ops = {
.open = pxa2xx_pcm_open,
.close = pxa2xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = __pxa2xx_pcm_hw_params,
.hw_free = __pxa2xx_pcm_hw_free,
.prepare = pxa2xx_pcm_prepare,
.trigger = pxa2xx_pcm_trigger,
.pointer = pxa2xx_pcm_pointer,
.mmap = pxa2xx_pcm_mmap,
};
int pxa2xx_pcm_new(struct snd_card *card, struct pxa2xx_pcm_client *client,
struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int play = client->playback_params ? 1 : 0;
int capt = client->capture_params ? 1 : 0;
int ret;
ret = snd_pcm_new(card, "PXA2xx-PCM", 0, play, capt, &pcm);
if (ret)
goto out;
pcm->private_data = client;
pcm->private_free = pxa2xx_pcm_free_dma_buffers;
ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
if (ret)
goto out;
if (play) {
int stream = SNDRV_PCM_STREAM_PLAYBACK;
snd_pcm_set_ops(pcm, stream, &pxa2xx_pcm_ops);
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
if (ret)
goto out;
}
if (capt) {
int stream = SNDRV_PCM_STREAM_CAPTURE;
snd_pcm_set_ops(pcm, stream, &pxa2xx_pcm_ops);
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
if (ret)
goto out;
}
if (rpcm)
*rpcm = pcm;
ret = 0;
out:
return ret;
}
EXPORT_SYMBOL(pxa2xx_pcm_new);
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
MODULE_LICENSE("GPL");

View File

@ -1,27 +0,0 @@
/*
* linux/sound/arm/pxa2xx-pcm.h -- ALSA PCM interface for the Intel PXA2xx chip
*
* Author: Nicolas Pitre
* Created: Nov 30, 2004
* Copyright: MontaVista Software, Inc.
*
* 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.
*/
struct pxa2xx_runtime_data {
int dma_ch;
struct snd_dmaengine_dai_dma_data *params;
};
struct pxa2xx_pcm_client {
struct snd_dmaengine_dai_dma_data *playback_params;
struct snd_dmaengine_dai_dma_data *capture_params;
int (*startup)(struct snd_pcm_substream *);
void (*shutdown)(struct snd_pcm_substream *);
int (*prepare)(struct snd_pcm_substream *);
};
extern int pxa2xx_pcm_new(struct snd_card *, struct pxa2xx_pcm_client *, struct snd_pcm **);

View File

@ -5,11 +5,12 @@ config SND_HDA_CORE
config SND_HDA_DSP_LOADER
bool
config SND_HDA_COMPONENT
bool
config SND_HDA_I915
bool
default y
depends on DRM_I915
depends on SND_HDA_CORE
select SND_HDA_COMPONENT
config SND_HDA_EXT_CORE
tristate

View File

@ -6,6 +6,7 @@ snd-hda-core-objs += trace.o
CFLAGS_trace.o := -I$(src)
# for sync with i915 gfx driver
snd-hda-core-$(CONFIG_SND_HDA_COMPONENT) += hdac_component.o
snd-hda-core-$(CONFIG_SND_HDA_I915) += hdac_i915.o
obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o

View File

@ -87,9 +87,10 @@ static const struct hdac_io_ops hdac_ext_default_io = {
*
* Returns 0 if successful, or a negative error code.
*/
int snd_hdac_ext_bus_init(struct hdac_ext_bus *ebus, struct device *dev,
int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev,
const struct hdac_bus_ops *ops,
const struct hdac_io_ops *io_ops)
const struct hdac_io_ops *io_ops,
const struct hdac_ext_bus_ops *ext_ops)
{
int ret;
static int idx;
@ -98,15 +99,16 @@ int snd_hdac_ext_bus_init(struct hdac_ext_bus *ebus, struct device *dev,
if (io_ops == NULL)
io_ops = &hdac_ext_default_io;
ret = snd_hdac_bus_init(&ebus->bus, dev, ops, io_ops);
ret = snd_hdac_bus_init(bus, dev, ops, io_ops);
if (ret < 0)
return ret;
INIT_LIST_HEAD(&ebus->hlink_list);
ebus->idx = idx++;
bus->ext_ops = ext_ops;
INIT_LIST_HEAD(&bus->hlink_list);
bus->idx = idx++;
mutex_init(&ebus->lock);
ebus->cmd_dma_state = true;
mutex_init(&bus->lock);
bus->cmd_dma_state = true;
return 0;
}
@ -116,10 +118,10 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_init);
* snd_hdac_ext_bus_exit - clean up a HD-audio extended bus
* @ebus: the pointer to extended bus object
*/
void snd_hdac_ext_bus_exit(struct hdac_ext_bus *ebus)
void snd_hdac_ext_bus_exit(struct hdac_bus *bus)
{
snd_hdac_bus_exit(&ebus->bus);
WARN_ON(!list_empty(&ebus->hlink_list));
snd_hdac_bus_exit(bus);
WARN_ON(!list_empty(&bus->hlink_list));
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_exit);
@ -135,21 +137,15 @@ static void default_release(struct device *dev)
*
* Returns zero for success or a negative error code.
*/
int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *ebus, int addr)
int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr,
struct hdac_device *hdev)
{
struct hdac_ext_device *edev;
struct hdac_device *hdev = NULL;
struct hdac_bus *bus = ebus_to_hbus(ebus);
char name[15];
int ret;
edev = kzalloc(sizeof(*edev), GFP_KERNEL);
if (!edev)
return -ENOMEM;
hdev = &edev->hdev;
edev->ebus = ebus;
hdev->bus = bus;
snprintf(name, sizeof(name), "ehdaudio%dD%d", ebus->idx, addr);
snprintf(name, sizeof(name), "ehdaudio%dD%d", bus->idx, addr);
ret = snd_hdac_device_init(hdev, bus, name, addr);
if (ret < 0) {
@ -176,10 +172,8 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_init);
*/
void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev)
{
struct hdac_ext_device *edev = to_ehdac_device(hdev);
snd_hdac_device_exit(hdev);
kfree(edev);
kfree(hdev);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit);
@ -188,14 +182,14 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit);
*
* @ebus: HD-audio extended bus
*/
void snd_hdac_ext_bus_device_remove(struct hdac_ext_bus *ebus)
void snd_hdac_ext_bus_device_remove(struct hdac_bus *bus)
{
struct hdac_device *codec, *__codec;
/*
* we need to remove all the codec devices objects created in the
* snd_hdac_ext_bus_device_init
*/
list_for_each_entry_safe(codec, __codec, &ebus->bus.codec_list, list) {
list_for_each_entry_safe(codec, __codec, &bus->codec_list, list) {
snd_hdac_device_unregister(codec);
put_device(&codec->dev);
}
@ -204,35 +198,31 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_remove);
#define dev_to_hdac(dev) (container_of((dev), \
struct hdac_device, dev))
static inline struct hdac_ext_driver *get_edrv(struct device *dev)
static inline struct hdac_driver *get_hdrv(struct device *dev)
{
struct hdac_driver *hdrv = drv_to_hdac_driver(dev->driver);
struct hdac_ext_driver *edrv = to_ehdac_driver(hdrv);
return edrv;
return hdrv;
}
static inline struct hdac_ext_device *get_edev(struct device *dev)
static inline struct hdac_device *get_hdev(struct device *dev)
{
struct hdac_device *hdev = dev_to_hdac_dev(dev);
struct hdac_ext_device *edev = to_ehdac_device(hdev);
return edev;
return hdev;
}
static int hda_ext_drv_probe(struct device *dev)
{
return (get_edrv(dev))->probe(get_edev(dev));
return (get_hdrv(dev))->probe(get_hdev(dev));
}
static int hdac_ext_drv_remove(struct device *dev)
{
return (get_edrv(dev))->remove(get_edev(dev));
return (get_hdrv(dev))->remove(get_hdev(dev));
}
static void hdac_ext_drv_shutdown(struct device *dev)
{
return (get_edrv(dev))->shutdown(get_edev(dev));
return (get_hdrv(dev))->shutdown(get_hdev(dev));
}
/**
@ -240,20 +230,20 @@ static void hdac_ext_drv_shutdown(struct device *dev)
*
* @drv: ext hda driver structure
*/
int snd_hda_ext_driver_register(struct hdac_ext_driver *drv)
int snd_hda_ext_driver_register(struct hdac_driver *drv)
{
drv->hdac.type = HDA_DEV_ASOC;
drv->hdac.driver.bus = &snd_hda_bus_type;
drv->type = HDA_DEV_ASOC;
drv->driver.bus = &snd_hda_bus_type;
/* we use default match */
if (drv->probe)
drv->hdac.driver.probe = hda_ext_drv_probe;
drv->driver.probe = hda_ext_drv_probe;
if (drv->remove)
drv->hdac.driver.remove = hdac_ext_drv_remove;
drv->driver.remove = hdac_ext_drv_remove;
if (drv->shutdown)
drv->hdac.driver.shutdown = hdac_ext_drv_shutdown;
drv->driver.shutdown = hdac_ext_drv_shutdown;
return driver_register(&drv->hdac.driver);
return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(snd_hda_ext_driver_register);
@ -262,8 +252,8 @@ EXPORT_SYMBOL_GPL(snd_hda_ext_driver_register);
*
* @drv: ext hda driver structure
*/
void snd_hda_ext_driver_unregister(struct hdac_ext_driver *drv)
void snd_hda_ext_driver_unregister(struct hdac_driver *drv)
{
driver_unregister(&drv->hdac.driver);
driver_unregister(&drv->driver);
}
EXPORT_SYMBOL_GPL(snd_hda_ext_driver_unregister);

View File

@ -39,9 +39,8 @@
* @ebus: HD-audio extended core bus
* @enable: flag to turn on/off the capability
*/
void snd_hdac_ext_bus_ppcap_enable(struct hdac_ext_bus *ebus, bool enable)
void snd_hdac_ext_bus_ppcap_enable(struct hdac_bus *bus, bool enable)
{
struct hdac_bus *bus = &ebus->bus;
if (!bus->ppcap) {
dev_err(bus->dev, "Address of PP capability is NULL");
@ -60,9 +59,8 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_enable);
* @ebus: HD-audio extended core bus
* @enable: flag to enable/disable interrupt
*/
void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_ext_bus *ebus, bool enable)
void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_bus *bus, bool enable)
{
struct hdac_bus *bus = &ebus->bus;
if (!bus->ppcap) {
dev_err(bus->dev, "Address of PP capability is NULL\n");
@ -89,12 +87,11 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_int_enable);
* in hlink_list of extended hdac bus
* Note: this will be freed on bus exit by driver
*/
int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *ebus)
int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_bus *bus)
{
int idx;
u32 link_count;
struct hdac_ext_link *hlink;
struct hdac_bus *bus = &ebus->bus;
link_count = readl(bus->mlcap + AZX_REG_ML_MLCD) + 1;
@ -114,7 +111,7 @@ int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *ebus)
/* since link in On, update the ref */
hlink->ref_count = 1;
list_add_tail(&hlink->list, &ebus->hlink_list);
list_add_tail(&hlink->list, &bus->hlink_list);
}
return 0;
@ -127,12 +124,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_get_ml_capabilities);
* @ebus: HD-audio ext core bus
*/
void snd_hdac_link_free_all(struct hdac_ext_bus *ebus)
void snd_hdac_link_free_all(struct hdac_bus *bus)
{
struct hdac_ext_link *l;
while (!list_empty(&ebus->hlink_list)) {
l = list_first_entry(&ebus->hlink_list, struct hdac_ext_link, list);
while (!list_empty(&bus->hlink_list)) {
l = list_first_entry(&bus->hlink_list, struct hdac_ext_link, list);
list_del(&l->list);
kfree(l);
}
@ -144,7 +141,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_link_free_all);
* @ebus: HD-audio extended core bus
* @codec_name: codec name
*/
struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_ext_bus *ebus,
struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_bus *bus,
const char *codec_name)
{
int i;
@ -153,10 +150,10 @@ struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_ext_bus *ebus,
if (sscanf(codec_name, "ehdaudio%dD%d", &bus_idx, &addr) != 2)
return NULL;
if (ebus->idx != bus_idx)
if (bus->idx != bus_idx)
return NULL;
list_for_each_entry(hlink, &ebus->hlink_list, list) {
list_for_each_entry(hlink, &bus->hlink_list, list) {
for (i = 0; i < HDA_MAX_CODECS; i++) {
if (hlink->lsdiid & (0x1 << addr))
return hlink;
@ -219,12 +216,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down);
* snd_hdac_ext_bus_link_power_up_all -power up all hda link
* @ebus: HD-audio extended bus
*/
int snd_hdac_ext_bus_link_power_up_all(struct hdac_ext_bus *ebus)
int snd_hdac_ext_bus_link_power_up_all(struct hdac_bus *bus)
{
struct hdac_ext_link *hlink = NULL;
int ret;
list_for_each_entry(hlink, &ebus->hlink_list, list) {
list_for_each_entry(hlink, &bus->hlink_list, list) {
snd_hdac_updatel(hlink->ml_addr,
AZX_REG_ML_LCTL, 0, AZX_MLCTL_SPA);
ret = check_hdac_link_power_active(hlink, true);
@ -240,12 +237,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_up_all);
* snd_hdac_ext_bus_link_power_down_all -power down all hda link
* @ebus: HD-audio extended bus
*/
int snd_hdac_ext_bus_link_power_down_all(struct hdac_ext_bus *ebus)
int snd_hdac_ext_bus_link_power_down_all(struct hdac_bus *bus)
{
struct hdac_ext_link *hlink = NULL;
int ret;
list_for_each_entry(hlink, &ebus->hlink_list, list) {
list_for_each_entry(hlink, &bus->hlink_list, list) {
snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, AZX_MLCTL_SPA, 0);
ret = check_hdac_link_power_active(hlink, false);
if (ret < 0)
@ -256,39 +253,48 @@ int snd_hdac_ext_bus_link_power_down_all(struct hdac_ext_bus *ebus)
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down_all);
int snd_hdac_ext_bus_link_get(struct hdac_ext_bus *ebus,
int snd_hdac_ext_bus_link_get(struct hdac_bus *bus,
struct hdac_ext_link *link)
{
int ret = 0;
mutex_lock(&ebus->lock);
mutex_lock(&bus->lock);
/*
* if we move from 0 to 1, count will be 1 so power up this link
* as well, also check the dma status and trigger that
*/
if (++link->ref_count == 1) {
if (!ebus->cmd_dma_state) {
snd_hdac_bus_init_cmd_io(&ebus->bus);
ebus->cmd_dma_state = true;
if (!bus->cmd_dma_state) {
snd_hdac_bus_init_cmd_io(bus);
bus->cmd_dma_state = true;
}
ret = snd_hdac_ext_bus_link_power_up(link);
/*
* wait for 521usec for codec to report status
* HDA spec section 4.3 - Codec Discovery
*/
udelay(521);
bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS);
dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask);
snd_hdac_chip_writew(bus, STATESTS, bus->codec_mask);
}
mutex_unlock(&ebus->lock);
mutex_unlock(&bus->lock);
return ret;
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_get);
int snd_hdac_ext_bus_link_put(struct hdac_ext_bus *ebus,
int snd_hdac_ext_bus_link_put(struct hdac_bus *bus,
struct hdac_ext_link *link)
{
int ret = 0;
struct hdac_ext_link *hlink;
bool link_up = false;
mutex_lock(&ebus->lock);
mutex_lock(&bus->lock);
/*
* if we move from 1 to 0, count will be 0
@ -301,7 +307,7 @@ int snd_hdac_ext_bus_link_put(struct hdac_ext_bus *ebus,
* now check if all links are off, if so turn off
* cmd dma as well
*/
list_for_each_entry(hlink, &ebus->hlink_list, list) {
list_for_each_entry(hlink, &bus->hlink_list, list) {
if (hlink->ref_count) {
link_up = true;
break;
@ -309,12 +315,12 @@ int snd_hdac_ext_bus_link_put(struct hdac_ext_bus *ebus,
}
if (!link_up) {
snd_hdac_bus_stop_cmd_io(&ebus->bus);
ebus->cmd_dma_state = false;
snd_hdac_bus_stop_cmd_io(bus);
bus->cmd_dma_state = false;
}
}
mutex_unlock(&ebus->lock);
mutex_unlock(&bus->lock);
return ret;
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_put);

View File

@ -25,7 +25,7 @@
/**
* snd_hdac_ext_stream_init - initialize each stream (aka device)
* @ebus: HD-audio ext core bus
* @bus: HD-audio core bus
* @stream: HD-audio ext core stream object to initialize
* @idx: stream index number
* @direction: stream direction (SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE)
@ -34,18 +34,16 @@
* initialize the stream, if ppcap is enabled then init those and then
* invoke hdac stream initialization routine
*/
void snd_hdac_ext_stream_init(struct hdac_ext_bus *ebus,
void snd_hdac_ext_stream_init(struct hdac_bus *bus,
struct hdac_ext_stream *stream,
int idx, int direction, int tag)
{
struct hdac_bus *bus = &ebus->bus;
if (bus->ppcap) {
stream->pphc_addr = bus->ppcap + AZX_PPHC_BASE +
AZX_PPHC_INTERVAL * idx;
stream->pplc_addr = bus->ppcap + AZX_PPLC_BASE +
AZX_PPLC_MULTI * ebus->num_streams +
AZX_PPLC_MULTI * bus->num_streams +
AZX_PPLC_INTERVAL * idx;
}
@ -71,12 +69,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init);
/**
* snd_hdac_ext_stream_init_all - create and initialize the stream objects
* for an extended hda bus
* @ebus: HD-audio ext core bus
* @bus: HD-audio core bus
* @start_idx: start index for streams
* @num_stream: number of streams to initialize
* @dir: direction of streams
*/
int snd_hdac_ext_stream_init_all(struct hdac_ext_bus *ebus, int start_idx,
int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx,
int num_stream, int dir)
{
int stream_tag = 0;
@ -88,7 +86,7 @@ int snd_hdac_ext_stream_init_all(struct hdac_ext_bus *ebus, int start_idx,
if (!stream)
return -ENOMEM;
tag = ++stream_tag;
snd_hdac_ext_stream_init(ebus, stream, idx, dir, tag);
snd_hdac_ext_stream_init(bus, stream, idx, dir, tag);
idx++;
}
@ -100,17 +98,16 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init_all);
/**
* snd_hdac_stream_free_all - free hdac extended stream objects
*
* @ebus: HD-audio ext core bus
* @bus: HD-audio core bus
*/
void snd_hdac_stream_free_all(struct hdac_ext_bus *ebus)
void snd_hdac_stream_free_all(struct hdac_bus *bus)
{
struct hdac_stream *s, *_s;
struct hdac_ext_stream *stream;
struct hdac_bus *bus = ebus_to_hbus(ebus);
list_for_each_entry_safe(s, _s, &bus->stream_list, list) {
stream = stream_to_hdac_ext_stream(s);
snd_hdac_ext_stream_decouple(ebus, stream, false);
snd_hdac_ext_stream_decouple(bus, stream, false);
list_del(&s->list);
kfree(stream);
}
@ -119,15 +116,14 @@ EXPORT_SYMBOL_GPL(snd_hdac_stream_free_all);
/**
* snd_hdac_ext_stream_decouple - decouple the hdac stream
* @ebus: HD-audio ext core bus
* @bus: HD-audio core bus
* @stream: HD-audio ext core stream object to initialize
* @decouple: flag to decouple
*/
void snd_hdac_ext_stream_decouple(struct hdac_ext_bus *ebus,
void snd_hdac_ext_stream_decouple(struct hdac_bus *bus,
struct hdac_ext_stream *stream, bool decouple)
{
struct hdac_stream *hstream = &stream->hstream;
struct hdac_bus *bus = &ebus->bus;
u32 val;
int mask = AZX_PPCTL_PROCEN(hstream->index);
@ -251,19 +247,18 @@ void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link,
EXPORT_SYMBOL_GPL(snd_hdac_ext_link_clear_stream_id);
static struct hdac_ext_stream *
hdac_ext_link_stream_assign(struct hdac_ext_bus *ebus,
hdac_ext_link_stream_assign(struct hdac_bus *bus,
struct snd_pcm_substream *substream)
{
struct hdac_ext_stream *res = NULL;
struct hdac_stream *stream = NULL;
struct hdac_bus *hbus = &ebus->bus;
if (!hbus->ppcap) {
dev_err(hbus->dev, "stream type not supported\n");
if (!bus->ppcap) {
dev_err(bus->dev, "stream type not supported\n");
return NULL;
}
list_for_each_entry(stream, &hbus->stream_list, list) {
list_for_each_entry(stream, &bus->stream_list, list) {
struct hdac_ext_stream *hstream = container_of(stream,
struct hdac_ext_stream,
hstream);
@ -277,34 +272,33 @@ hdac_ext_link_stream_assign(struct hdac_ext_bus *ebus,
}
if (!hstream->link_locked) {
snd_hdac_ext_stream_decouple(ebus, hstream, true);
snd_hdac_ext_stream_decouple(bus, hstream, true);
res = hstream;
break;
}
}
if (res) {
spin_lock_irq(&hbus->reg_lock);
spin_lock_irq(&bus->reg_lock);
res->link_locked = 1;
res->link_substream = substream;
spin_unlock_irq(&hbus->reg_lock);
spin_unlock_irq(&bus->reg_lock);
}
return res;
}
static struct hdac_ext_stream *
hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus,
hdac_ext_host_stream_assign(struct hdac_bus *bus,
struct snd_pcm_substream *substream)
{
struct hdac_ext_stream *res = NULL;
struct hdac_stream *stream = NULL;
struct hdac_bus *hbus = &ebus->bus;
if (!hbus->ppcap) {
dev_err(hbus->dev, "stream type not supported\n");
if (!bus->ppcap) {
dev_err(bus->dev, "stream type not supported\n");
return NULL;
}
list_for_each_entry(stream, &hbus->stream_list, list) {
list_for_each_entry(stream, &bus->stream_list, list) {
struct hdac_ext_stream *hstream = container_of(stream,
struct hdac_ext_stream,
hstream);
@ -313,17 +307,17 @@ hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus,
if (!stream->opened) {
if (!hstream->decoupled)
snd_hdac_ext_stream_decouple(ebus, hstream, true);
snd_hdac_ext_stream_decouple(bus, hstream, true);
res = hstream;
break;
}
}
if (res) {
spin_lock_irq(&hbus->reg_lock);
spin_lock_irq(&bus->reg_lock);
res->hstream.opened = 1;
res->hstream.running = 0;
res->hstream.substream = substream;
spin_unlock_irq(&hbus->reg_lock);
spin_unlock_irq(&bus->reg_lock);
}
return res;
@ -331,7 +325,7 @@ hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus,
/**
* snd_hdac_ext_stream_assign - assign a stream for the PCM
* @ebus: HD-audio ext core bus
* @bus: HD-audio core bus
* @substream: PCM substream to assign
* @type: type of stream (coupled, host or link stream)
*
@ -346,27 +340,26 @@ hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus,
* the same stream object when it's used beforehand. when a stream is
* decoupled, it becomes a host stream and link stream.
*/
struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_ext_bus *ebus,
struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus,
struct snd_pcm_substream *substream,
int type)
{
struct hdac_ext_stream *hstream = NULL;
struct hdac_stream *stream = NULL;
struct hdac_bus *hbus = &ebus->bus;
switch (type) {
case HDAC_EXT_STREAM_TYPE_COUPLED:
stream = snd_hdac_stream_assign(hbus, substream);
stream = snd_hdac_stream_assign(bus, substream);
if (stream)
hstream = container_of(stream,
struct hdac_ext_stream, hstream);
return hstream;
case HDAC_EXT_STREAM_TYPE_HOST:
return hdac_ext_host_stream_assign(ebus, substream);
return hdac_ext_host_stream_assign(bus, substream);
case HDAC_EXT_STREAM_TYPE_LINK:
return hdac_ext_link_stream_assign(ebus, substream);
return hdac_ext_link_stream_assign(bus, substream);
default:
return NULL;
@ -384,7 +377,6 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_assign);
void snd_hdac_ext_stream_release(struct hdac_ext_stream *stream, int type)
{
struct hdac_bus *bus = stream->hstream.bus;
struct hdac_ext_bus *ebus = hbus_to_ebus(bus);
switch (type) {
case HDAC_EXT_STREAM_TYPE_COUPLED:
@ -393,13 +385,13 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *stream, int type)
case HDAC_EXT_STREAM_TYPE_HOST:
if (stream->decoupled && !stream->link_locked)
snd_hdac_ext_stream_decouple(ebus, stream, false);
snd_hdac_ext_stream_decouple(bus, stream, false);
snd_hdac_stream_release(&stream->hstream);
break;
case HDAC_EXT_STREAM_TYPE_LINK:
if (stream->decoupled && !stream->hstream.opened)
snd_hdac_ext_stream_decouple(ebus, stream, false);
snd_hdac_ext_stream_decouple(bus, stream, false);
spin_lock_irq(&bus->reg_lock);
stream->link_locked = 0;
stream->link_substream = NULL;
@ -415,16 +407,15 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_release);
/**
* snd_hdac_ext_stream_spbcap_enable - enable SPIB for a stream
* @ebus: HD-audio ext core bus
* @bus: HD-audio core bus
* @enable: flag to enable/disable SPIB
* @index: stream index for which SPIB need to be enabled
*/
void snd_hdac_ext_stream_spbcap_enable(struct hdac_ext_bus *ebus,
void snd_hdac_ext_stream_spbcap_enable(struct hdac_bus *bus,
bool enable, int index)
{
u32 mask = 0;
u32 register_mask = 0;
struct hdac_bus *bus = &ebus->bus;
if (!bus->spbcap) {
dev_err(bus->dev, "Address of SPB capability is NULL\n");
@ -446,14 +437,13 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_spbcap_enable);
/**
* snd_hdac_ext_stream_set_spib - sets the spib value of a stream
* @ebus: HD-audio ext core bus
* @bus: HD-audio core bus
* @stream: hdac_ext_stream
* @value: spib value to set
*/
int snd_hdac_ext_stream_set_spib(struct hdac_ext_bus *ebus,
int snd_hdac_ext_stream_set_spib(struct hdac_bus *bus,
struct hdac_ext_stream *stream, u32 value)
{
struct hdac_bus *bus = &ebus->bus;
if (!bus->spbcap) {
dev_err(bus->dev, "Address of SPB capability is NULL\n");
@ -468,15 +458,14 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_spib);
/**
* snd_hdac_ext_stream_get_spbmaxfifo - gets the spib value of a stream
* @ebus: HD-audio ext core bus
* @bus: HD-audio core bus
* @stream: hdac_ext_stream
*
* Return maxfifo for the stream
*/
int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_ext_bus *ebus,
int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_bus *bus,
struct hdac_ext_stream *stream)
{
struct hdac_bus *bus = &ebus->bus;
if (!bus->spbcap) {
dev_err(bus->dev, "Address of SPB capability is NULL\n");
@ -490,11 +479,10 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_get_spbmaxfifo);
/**
* snd_hdac_ext_stop_streams - stop all stream if running
* @ebus: HD-audio ext core bus
* @bus: HD-audio core bus
*/
void snd_hdac_ext_stop_streams(struct hdac_ext_bus *ebus)
void snd_hdac_ext_stop_streams(struct hdac_bus *bus)
{
struct hdac_bus *bus = ebus_to_hbus(ebus);
struct hdac_stream *stream;
if (bus->chip_init) {
@ -507,16 +495,15 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stop_streams);
/**
* snd_hdac_ext_stream_drsm_enable - enable DMA resume for a stream
* @ebus: HD-audio ext core bus
* @bus: HD-audio core bus
* @enable: flag to enable/disable DRSM
* @index: stream index for which DRSM need to be enabled
*/
void snd_hdac_ext_stream_drsm_enable(struct hdac_ext_bus *ebus,
void snd_hdac_ext_stream_drsm_enable(struct hdac_bus *bus,
bool enable, int index)
{
u32 mask = 0;
u32 register_mask = 0;
struct hdac_bus *bus = &ebus->bus;
if (!bus->drsmcap) {
dev_err(bus->dev, "Address of DRSM capability is NULL\n");
@ -538,14 +525,13 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_drsm_enable);
/**
* snd_hdac_ext_stream_set_dpibr - sets the dpibr value of a stream
* @ebus: HD-audio ext core bus
* @bus: HD-audio core bus
* @stream: hdac_ext_stream
* @value: dpib value to set
*/
int snd_hdac_ext_stream_set_dpibr(struct hdac_ext_bus *ebus,
int snd_hdac_ext_stream_set_dpibr(struct hdac_bus *bus,
struct hdac_ext_stream *stream, u32 value)
{
struct hdac_bus *bus = &ebus->bus;
if (!bus->drsmcap) {
dev_err(bus->dev, "Address of DRSM capability is NULL\n");
@ -560,7 +546,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_dpibr);
/**
* snd_hdac_ext_stream_set_lpib - sets the lpib value of a stream
* @ebus: HD-audio ext core bus
* @bus: HD-audio core bus
* @stream: hdac_ext_stream
* @value: lpib value to set
*/

335
sound/hda/hdac_component.c Normal file
View File

@ -0,0 +1,335 @@
// SPDX-License-Identifier: GPL-2.0
// hdac_component.c - routines for sync between HD-A core and DRM driver
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/component.h>
#include <sound/core.h>
#include <sound/hdaudio.h>
#include <sound/hda_component.h>
#include <sound/hda_register.h>
static void hdac_acomp_release(struct device *dev, void *res)
{
}
static struct drm_audio_component *hdac_get_acomp(struct device *dev)
{
return devres_find(dev, hdac_acomp_release, NULL, NULL);
}
/**
* snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup
* @bus: HDA core bus
* @enable: enable or disable the wakeup
*
* This function is supposed to be used only by a HD-audio controller
* driver that needs the interaction with graphics driver.
*
* This function should be called during the chip reset, also called at
* resume for updating STATESTS register read.
*
* Returns zero for success or a negative error code.
*/
int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
{
struct drm_audio_component *acomp = bus->audio_component;
if (!acomp || !acomp->ops)
return -ENODEV;
if (!acomp->ops->codec_wake_override)
return 0;
dev_dbg(bus->dev, "%s codec wakeup\n",
enable ? "enable" : "disable");
acomp->ops->codec_wake_override(acomp->dev, enable);
return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup);
/**
* snd_hdac_display_power - Power up / down the power refcount
* @bus: HDA core bus
* @enable: power up or down
*
* This function is supposed to be used only by a HD-audio controller
* driver that needs the interaction with graphics driver.
*
* This function manages a refcount and calls the get_power() and
* put_power() ops accordingly, toggling the codec wakeup, too.
*
* Returns zero for success or a negative error code.
*/
int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
{
struct drm_audio_component *acomp = bus->audio_component;
if (!acomp || !acomp->ops)
return -ENODEV;
dev_dbg(bus->dev, "display power %s\n",
enable ? "enable" : "disable");
if (enable) {
if (!bus->drm_power_refcount++) {
if (acomp->ops->get_power)
acomp->ops->get_power(acomp->dev);
snd_hdac_set_codec_wakeup(bus, true);
snd_hdac_set_codec_wakeup(bus, false);
}
} else {
WARN_ON(!bus->drm_power_refcount);
if (!--bus->drm_power_refcount)
if (acomp->ops->put_power)
acomp->ops->put_power(acomp->dev);
}
return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_display_power);
/**
* snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate
* @codec: HDA codec
* @nid: the pin widget NID
* @dev_id: device identifier
* @rate: the sample rate to set
*
* This function is supposed to be used only by a HD-audio controller
* driver that needs the interaction with graphics driver.
*
* This function sets N/CTS value based on the given sample rate.
* Returns zero for success, or a negative error code.
*/
int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
int dev_id, int rate)
{
struct hdac_bus *bus = codec->bus;
struct drm_audio_component *acomp = bus->audio_component;
int port, pipe;
if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate)
return -ENODEV;
port = nid;
if (acomp->audio_ops && acomp->audio_ops->pin2port) {
port = acomp->audio_ops->pin2port(codec, nid);
if (port < 0)
return -EINVAL;
}
pipe = dev_id;
return acomp->ops->sync_audio_rate(acomp->dev, port, pipe, rate);
}
EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate);
/**
* snd_hdac_acomp_get_eld - Get the audio state and ELD via component
* @codec: HDA codec
* @nid: the pin widget NID
* @dev_id: device identifier
* @audio_enabled: the pointer to store the current audio state
* @buffer: the buffer pointer to store ELD bytes
* @max_bytes: the max bytes to be stored on @buffer
*
* This function is supposed to be used only by a HD-audio controller
* driver that needs the interaction with graphics driver.
*
* This function queries the current state of the audio on the given
* digital port and fetches the ELD bytes onto the given buffer.
* It returns the number of bytes for the total ELD data, zero for
* invalid ELD, or a negative error code.
*
* The return size is the total bytes required for the whole ELD bytes,
* thus it may be over @max_bytes. If it's over @max_bytes, it implies
* that only a part of ELD bytes have been fetched.
*/
int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
bool *audio_enabled, char *buffer, int max_bytes)
{
struct hdac_bus *bus = codec->bus;
struct drm_audio_component *acomp = bus->audio_component;
int port, pipe;
if (!acomp || !acomp->ops || !acomp->ops->get_eld)
return -ENODEV;
port = nid;
if (acomp->audio_ops && acomp->audio_ops->pin2port) {
port = acomp->audio_ops->pin2port(codec, nid);
if (port < 0)
return -EINVAL;
}
pipe = dev_id;
return acomp->ops->get_eld(acomp->dev, port, pipe, audio_enabled,
buffer, max_bytes);
}
EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld);
static int hdac_component_master_bind(struct device *dev)
{
struct drm_audio_component *acomp = hdac_get_acomp(dev);
int ret;
if (WARN_ON(!acomp))
return -EINVAL;
ret = component_bind_all(dev, acomp);
if (ret < 0)
return ret;
if (WARN_ON(!(acomp->dev && acomp->ops))) {
ret = -EINVAL;
goto out_unbind;
}
/* pin the module to avoid dynamic unbinding, but only if given */
if (!try_module_get(acomp->ops->owner)) {
ret = -ENODEV;
goto out_unbind;
}
if (acomp->audio_ops && acomp->audio_ops->master_bind) {
ret = acomp->audio_ops->master_bind(dev, acomp);
if (ret < 0)
goto module_put;
}
return 0;
module_put:
module_put(acomp->ops->owner);
out_unbind:
component_unbind_all(dev, acomp);
return ret;
}
static void hdac_component_master_unbind(struct device *dev)
{
struct drm_audio_component *acomp = hdac_get_acomp(dev);
if (acomp->audio_ops && acomp->audio_ops->master_unbind)
acomp->audio_ops->master_unbind(dev, acomp);
module_put(acomp->ops->owner);
component_unbind_all(dev, acomp);
WARN_ON(acomp->ops || acomp->dev);
}
static const struct component_master_ops hdac_component_master_ops = {
.bind = hdac_component_master_bind,
.unbind = hdac_component_master_unbind,
};
/**
* snd_hdac_acomp_register_notifier - Register audio component ops
* @bus: HDA core bus
* @aops: audio component ops
*
* This function is supposed to be used only by a HD-audio controller
* driver that needs the interaction with graphics driver.
*
* This function sets the given ops to be called by the graphics driver.
*
* Returns zero for success or a negative error code.
*/
int snd_hdac_acomp_register_notifier(struct hdac_bus *bus,
const struct drm_audio_component_audio_ops *aops)
{
if (!bus->audio_component)
return -ENODEV;
bus->audio_component->audio_ops = aops;
return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier);
/**
* snd_hdac_acomp_init - Initialize audio component
* @bus: HDA core bus
* @match_master: match function for finding components
* @extra_size: Extra bytes to allocate
*
* This function is supposed to be used only by a HD-audio controller
* driver that needs the interaction with graphics driver.
*
* This function initializes and sets up the audio component to communicate
* with graphics driver.
*
* Unlike snd_hdac_i915_init(), this function doesn't synchronize with the
* binding with the DRM component. Each caller needs to sync via master_bind
* audio_ops.
*
* Returns zero for success or a negative error code.
*/
int snd_hdac_acomp_init(struct hdac_bus *bus,
const struct drm_audio_component_audio_ops *aops,
int (*match_master)(struct device *, void *),
size_t extra_size)
{
struct component_match *match = NULL;
struct device *dev = bus->dev;
struct drm_audio_component *acomp;
int ret;
if (WARN_ON(hdac_get_acomp(dev)))
return -EBUSY;
acomp = devres_alloc(hdac_acomp_release, sizeof(*acomp) + extra_size,
GFP_KERNEL);
if (!acomp)
return -ENOMEM;
acomp->audio_ops = aops;
bus->audio_component = acomp;
devres_add(dev, acomp);
component_match_add(dev, &match, match_master, bus);
ret = component_master_add_with_match(dev, &hdac_component_master_ops,
match);
if (ret < 0)
goto out_err;
return 0;
out_err:
bus->audio_component = NULL;
devres_destroy(dev, hdac_acomp_release, NULL, NULL);
dev_info(dev, "failed to add audio component master (%d)\n", ret);
return ret;
}
EXPORT_SYMBOL_GPL(snd_hdac_acomp_init);
/**
* snd_hdac_acomp_exit - Finalize audio component
* @bus: HDA core bus
*
* This function is supposed to be used only by a HD-audio controller
* driver that needs the interaction with graphics driver.
*
* This function releases the audio component that has been used.
*
* Returns zero for success or a negative error code.
*/
int snd_hdac_acomp_exit(struct hdac_bus *bus)
{
struct device *dev = bus->dev;
struct drm_audio_component *acomp = bus->audio_component;
if (!acomp)
return 0;
WARN_ON(bus->drm_power_refcount);
if (bus->drm_power_refcount > 0 && acomp->ops)
acomp->ops->put_power(acomp->dev);
component_master_del(dev, &hdac_component_master_ops);
bus->audio_component = NULL;
devres_destroy(dev, hdac_acomp_release, NULL, NULL);
return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_acomp_exit);

View File

@ -15,89 +15,11 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/component.h>
#include <drm/i915_component.h>
#include <sound/core.h>
#include <sound/hdaudio.h>
#include <sound/hda_i915.h>
#include <sound/hda_register.h>
static struct i915_audio_component *hdac_acomp;
/**
* snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup
* @bus: HDA core bus
* @enable: enable or disable the wakeup
*
* This function is supposed to be used only by a HD-audio controller
* driver that needs the interaction with i915 graphics.
*
* This function should be called during the chip reset, also called at
* resume for updating STATESTS register read.
*
* Returns zero for success or a negative error code.
*/
int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
{
struct i915_audio_component *acomp = bus->audio_component;
if (!acomp || !acomp->ops)
return -ENODEV;
if (!acomp->ops->codec_wake_override) {
dev_warn(bus->dev,
"Invalid codec wake callback\n");
return 0;
}
dev_dbg(bus->dev, "%s codec wakeup\n",
enable ? "enable" : "disable");
acomp->ops->codec_wake_override(acomp->dev, enable);
return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup);
/**
* snd_hdac_display_power - Power up / down the power refcount
* @bus: HDA core bus
* @enable: power up or down
*
* This function is supposed to be used only by a HD-audio controller
* driver that needs the interaction with i915 graphics.
*
* This function manages a refcount and calls the i915 get_power() and
* put_power() ops accordingly, toggling the codec wakeup, too.
*
* Returns zero for success or a negative error code.
*/
int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
{
struct i915_audio_component *acomp = bus->audio_component;
if (!acomp || !acomp->ops)
return -ENODEV;
dev_dbg(bus->dev, "display power %s\n",
enable ? "enable" : "disable");
if (enable) {
if (!bus->i915_power_refcount++) {
acomp->ops->get_power(acomp->dev);
snd_hdac_set_codec_wakeup(bus, true);
snd_hdac_set_codec_wakeup(bus, false);
}
} else {
WARN_ON(!bus->i915_power_refcount);
if (!--bus->i915_power_refcount)
acomp->ops->put_power(acomp->dev);
}
return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_display_power);
#define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \
((pci)->device == 0x0c0c) || \
((pci)->device == 0x0d0c) || \
@ -119,7 +41,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_display_power);
*/
void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
{
struct i915_audio_component *acomp = bus->audio_component;
struct drm_audio_component *acomp = bus->audio_component;
struct pci_dev *pci = to_pci_dev(bus->dev);
int cdclk_freq;
unsigned int bclk_m, bclk_n;
@ -158,181 +80,11 @@ void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
}
EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk);
/* There is a fixed mapping between audio pin node and display port.
* on SNB, IVY, HSW, BSW, SKL, BXT, KBL:
* Pin Widget 5 - PORT B (port = 1 in i915 driver)
* Pin Widget 6 - PORT C (port = 2 in i915 driver)
* Pin Widget 7 - PORT D (port = 3 in i915 driver)
*
* on VLV, ILK:
* Pin Widget 4 - PORT B (port = 1 in i915 driver)
* Pin Widget 5 - PORT C (port = 2 in i915 driver)
* Pin Widget 6 - PORT D (port = 3 in i915 driver)
*/
static int pin2port(struct hdac_device *codec, hda_nid_t pin_nid)
static int i915_component_master_match(struct device *dev, void *data)
{
int base_nid;
switch (codec->vendor_id) {
case 0x80860054: /* ILK */
case 0x80862804: /* ILK */
case 0x80862882: /* VLV */
base_nid = 3;
break;
default:
base_nid = 4;
break;
}
if (WARN_ON(pin_nid <= base_nid || pin_nid > base_nid + 3))
return -1;
return pin_nid - base_nid;
}
/**
* snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate
* @codec: HDA codec
* @nid: the pin widget NID
* @dev_id: device identifier
* @rate: the sample rate to set
*
* This function is supposed to be used only by a HD-audio controller
* driver that needs the interaction with i915 graphics.
*
* This function sets N/CTS value based on the given sample rate.
* Returns zero for success, or a negative error code.
*/
int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
int dev_id, int rate)
{
struct hdac_bus *bus = codec->bus;
struct i915_audio_component *acomp = bus->audio_component;
int port, pipe;
if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate)
return -ENODEV;
port = pin2port(codec, nid);
if (port < 0)
return -EINVAL;
pipe = dev_id;
return acomp->ops->sync_audio_rate(acomp->dev, port, pipe, rate);
}
EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate);
/**
* snd_hdac_acomp_get_eld - Get the audio state and ELD via component
* @codec: HDA codec
* @nid: the pin widget NID
* @dev_id: device identifier
* @audio_enabled: the pointer to store the current audio state
* @buffer: the buffer pointer to store ELD bytes
* @max_bytes: the max bytes to be stored on @buffer
*
* This function is supposed to be used only by a HD-audio controller
* driver that needs the interaction with i915 graphics.
*
* This function queries the current state of the audio on the given
* digital port and fetches the ELD bytes onto the given buffer.
* It returns the number of bytes for the total ELD data, zero for
* invalid ELD, or a negative error code.
*
* The return size is the total bytes required for the whole ELD bytes,
* thus it may be over @max_bytes. If it's over @max_bytes, it implies
* that only a part of ELD bytes have been fetched.
*/
int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
bool *audio_enabled, char *buffer, int max_bytes)
{
struct hdac_bus *bus = codec->bus;
struct i915_audio_component *acomp = bus->audio_component;
int port, pipe;
if (!acomp || !acomp->ops || !acomp->ops->get_eld)
return -ENODEV;
port = pin2port(codec, nid);
if (port < 0)
return -EINVAL;
pipe = dev_id;
return acomp->ops->get_eld(acomp->dev, port, pipe, audio_enabled,
buffer, max_bytes);
}
EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld);
static int hdac_component_master_bind(struct device *dev)
{
struct i915_audio_component *acomp = hdac_acomp;
int ret;
ret = component_bind_all(dev, acomp);
if (ret < 0)
return ret;
if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power &&
acomp->ops->put_power && acomp->ops->get_cdclk_freq))) {
ret = -EINVAL;
goto out_unbind;
}
/*
* Atm, we don't support dynamic unbinding initiated by the child
* component, so pin its containing module until we unbind.
*/
if (!try_module_get(acomp->ops->owner)) {
ret = -ENODEV;
goto out_unbind;
}
return 0;
out_unbind:
component_unbind_all(dev, acomp);
return ret;
}
static void hdac_component_master_unbind(struct device *dev)
{
struct i915_audio_component *acomp = hdac_acomp;
module_put(acomp->ops->owner);
component_unbind_all(dev, acomp);
WARN_ON(acomp->ops || acomp->dev);
}
static const struct component_master_ops hdac_component_master_ops = {
.bind = hdac_component_master_bind,
.unbind = hdac_component_master_unbind,
};
static int hdac_component_master_match(struct device *dev, void *data)
{
/* i915 is the only supported component */
return !strcmp(dev->driver->name, "i915");
}
/**
* snd_hdac_i915_register_notifier - Register i915 audio component ops
* @aops: i915 audio component ops
*
* This function is supposed to be used only by a HD-audio controller
* driver that needs the interaction with i915 graphics.
*
* This function sets the given ops to be called by the i915 graphics driver.
*
* Returns zero for success or a negative error code.
*/
int snd_hdac_i915_register_notifier(const struct i915_audio_component_audio_ops *aops)
{
if (!hdac_acomp)
return -ENODEV;
hdac_acomp->audio_ops = aops;
return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_i915_register_notifier);
/* check whether intel graphics is present */
static bool i915_gfx_present(void)
{
@ -359,83 +111,26 @@ static bool i915_gfx_present(void)
*/
int snd_hdac_i915_init(struct hdac_bus *bus)
{
struct component_match *match = NULL;
struct device *dev = bus->dev;
struct i915_audio_component *acomp;
int ret;
if (WARN_ON(hdac_acomp))
return -EBUSY;
struct drm_audio_component *acomp;
int err;
if (!i915_gfx_present())
return -ENODEV;
acomp = kzalloc(sizeof(*acomp), GFP_KERNEL);
err = snd_hdac_acomp_init(bus, NULL,
i915_component_master_match,
sizeof(struct i915_audio_component) - sizeof(*acomp));
if (err < 0)
return err;
acomp = bus->audio_component;
if (!acomp)
return -ENOMEM;
bus->audio_component = acomp;
hdac_acomp = acomp;
component_match_add(dev, &match, hdac_component_master_match, bus);
ret = component_master_add_with_match(dev, &hdac_component_master_ops,
match);
if (ret < 0)
goto out_err;
/*
* Atm, we don't support deferring the component binding, so make sure
* i915 is loaded and that the binding successfully completes.
*/
request_module("i915");
return -ENODEV;
if (!acomp->ops)
request_module("i915");
if (!acomp->ops) {
ret = -ENODEV;
goto out_master_del;
snd_hdac_acomp_exit(bus);
return -ENODEV;
}
dev_dbg(dev, "bound to i915 component master\n");
return 0;
out_master_del:
component_master_del(dev, &hdac_component_master_ops);
out_err:
kfree(acomp);
bus->audio_component = NULL;
hdac_acomp = NULL;
dev_info(dev, "failed to add i915 component master (%d)\n", ret);
return ret;
}
EXPORT_SYMBOL_GPL(snd_hdac_i915_init);
/**
* snd_hdac_i915_exit - Finalize i915 audio component
* @bus: HDA core bus
*
* This function is supposed to be used only by a HD-audio controller
* driver that needs the interaction with i915 graphics.
*
* This function releases the i915 audio component that has been used.
*
* Returns zero for success or a negative error code.
*/
int snd_hdac_i915_exit(struct hdac_bus *bus)
{
struct device *dev = bus->dev;
struct i915_audio_component *acomp = bus->audio_component;
if (!acomp)
return 0;
WARN_ON(bus->i915_power_refcount);
if (bus->i915_power_refcount > 0 && acomp->ops)
acomp->ops->put_power(acomp->dev);
component_master_del(dev, &hdac_component_master_ops);
kfree(acomp);
bus->audio_component = NULL;
hdac_acomp = NULL;
return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_i915_exit);

View File

@ -858,6 +858,39 @@ static void snd_hda_codec_dev_release(struct device *dev)
kfree(codec);
}
#define DEV_NAME_LEN 31
static int snd_hda_codec_device_init(struct hda_bus *bus, struct snd_card *card,
unsigned int codec_addr, struct hda_codec **codecp)
{
char name[DEV_NAME_LEN];
struct hda_codec *codec;
int err;
dev_dbg(card->dev, "%s: entry\n", __func__);
if (snd_BUG_ON(!bus))
return -EINVAL;
if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
return -EINVAL;
codec = kzalloc(sizeof(*codec), GFP_KERNEL);
if (!codec)
return -ENOMEM;
sprintf(name, "hdaudioC%dD%d", card->number, codec_addr);
err = snd_hdac_device_init(&codec->core, &bus->core, name, codec_addr);
if (err < 0) {
kfree(codec);
return err;
}
codec->core.type = HDA_DEV_LEGACY;
*codecp = codec;
return err;
}
/**
* snd_hda_codec_new - create a HDA codec
* @bus: the bus to assign
@ -869,7 +902,19 @@ static void snd_hda_codec_dev_release(struct device *dev)
int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
unsigned int codec_addr, struct hda_codec **codecp)
{
struct hda_codec *codec;
int ret;
ret = snd_hda_codec_device_init(bus, card, codec_addr, codecp);
if (ret < 0)
return ret;
return snd_hda_codec_device_new(bus, card, codec_addr, *codecp);
}
EXPORT_SYMBOL_GPL(snd_hda_codec_new);
int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card,
unsigned int codec_addr, struct hda_codec *codec)
{
char component[31];
hda_nid_t fg;
int err;
@ -879,25 +924,14 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
.dev_free = snd_hda_codec_dev_free,
};
dev_dbg(card->dev, "%s: entry\n", __func__);
if (snd_BUG_ON(!bus))
return -EINVAL;
if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
return -EINVAL;
codec = kzalloc(sizeof(*codec), GFP_KERNEL);
if (!codec)
return -ENOMEM;
sprintf(component, "hdaudioC%dD%d", card->number, codec_addr);
err = snd_hdac_device_init(&codec->core, &bus->core, component,
codec_addr);
if (err < 0) {
kfree(codec);
return err;
}
codec->core.dev.release = snd_hda_codec_dev_release;
codec->core.type = HDA_DEV_LEGACY;
codec->core.exec_verb = codec_exec_verb;
codec->bus = bus;
@ -957,15 +991,13 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
if (err < 0)
goto error;
if (codecp)
*codecp = codec;
return 0;
error:
put_device(hda_codec_dev(codec));
return err;
}
EXPORT_SYMBOL_GPL(snd_hda_codec_new);
EXPORT_SYMBOL_GPL(snd_hda_codec_device_new);
/**
* snd_hda_codec_update_widgets - Refresh widget caps and pin defaults
@ -2992,6 +3024,7 @@ int snd_hda_codec_build_controls(struct hda_codec *codec)
sync_power_up_states(codec);
return 0;
}
EXPORT_SYMBOL_GPL(snd_hda_codec_build_controls);
/*
* PCM stuff
@ -3197,6 +3230,7 @@ int snd_hda_codec_parse_pcms(struct hda_codec *codec)
return 0;
}
EXPORT_SYMBOL_GPL(snd_hda_codec_parse_pcms);
/* assign all PCMs of the given codec */
int snd_hda_codec_build_pcms(struct hda_codec *codec)

View File

@ -308,6 +308,8 @@ struct hda_codec {
*/
int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
unsigned int codec_addr, struct hda_codec **codecp);
int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card,
unsigned int codec_addr, struct hda_codec *codec);
int snd_hda_codec_configure(struct hda_codec *codec);
int snd_hda_codec_update_widgets(struct hda_codec *codec);

View File

@ -177,13 +177,13 @@ struct hdmi_spec {
/* i915/powerwell (Haswell+/Valleyview+) specific */
bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */
struct i915_audio_component_audio_ops i915_audio_ops;
struct drm_audio_component_audio_ops drm_audio_ops;
struct hdac_chmap chmap;
hda_nid_t vendor_nid;
};
#ifdef CONFIG_SND_HDA_I915
#ifdef CONFIG_SND_HDA_COMPONENT
static inline bool codec_has_acomp(struct hda_codec *codec)
{
struct hdmi_spec *spec = codec->spec;
@ -2288,7 +2288,7 @@ static void generic_hdmi_free(struct hda_codec *codec)
int pin_idx, pcm_idx;
if (codec_has_acomp(codec))
snd_hdac_i915_register_notifier(NULL);
snd_hdac_acomp_register_notifier(&codec->bus->core, NULL);
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
@ -2471,6 +2471,38 @@ static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg,
snd_hda_codec_set_power_to_all(codec, fg, power_state);
}
/* There is a fixed mapping between audio pin node and display port.
* on SNB, IVY, HSW, BSW, SKL, BXT, KBL:
* Pin Widget 5 - PORT B (port = 1 in i915 driver)
* Pin Widget 6 - PORT C (port = 2 in i915 driver)
* Pin Widget 7 - PORT D (port = 3 in i915 driver)
*
* on VLV, ILK:
* Pin Widget 4 - PORT B (port = 1 in i915 driver)
* Pin Widget 5 - PORT C (port = 2 in i915 driver)
* Pin Widget 6 - PORT D (port = 3 in i915 driver)
*/
static int intel_base_nid(struct hda_codec *codec)
{
switch (codec->core.vendor_id) {
case 0x80860054: /* ILK */
case 0x80862804: /* ILK */
case 0x80862882: /* VLV */
return 4;
default:
return 5;
}
}
static int intel_pin2port(void *audio_ptr, int pin_nid)
{
int base_nid = intel_base_nid(audio_ptr);
if (WARN_ON(pin_nid < base_nid || pin_nid >= base_nid + 3))
return -1;
return pin_nid - base_nid + 1; /* intel port is 1-based */
}
static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
{
struct hda_codec *codec = audio_ptr;
@ -2481,16 +2513,7 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
if (port < 1 || port > 3)
return;
switch (codec->core.vendor_id) {
case 0x80860054: /* ILK */
case 0x80862804: /* ILK */
case 0x80862882: /* VLV */
pin_nid = port + 0x03;
break;
default:
pin_nid = port + 0x04;
break;
}
pin_nid = port + intel_base_nid(codec) - 1; /* intel port is 1-based */
/* skip notification during system suspend (but not in runtime PM);
* the state will be updated at resume
@ -2511,14 +2534,16 @@ static void register_i915_notifier(struct hda_codec *codec)
struct hdmi_spec *spec = codec->spec;
spec->use_acomp_notifier = true;
spec->i915_audio_ops.audio_ptr = codec;
spec->drm_audio_ops.audio_ptr = codec;
/* intel_audio_codec_enable() or intel_audio_codec_disable()
* will call pin_eld_notify with using audio_ptr pointer
* We need make sure audio_ptr is really setup
*/
wmb();
spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify;
snd_hdac_i915_register_notifier(&spec->i915_audio_ops);
spec->drm_audio_ops.pin2port = intel_pin2port;
spec->drm_audio_ops.pin_eld_notify = intel_pin_eld_notify;
snd_hdac_acomp_register_notifier(&codec->bus->core,
&spec->drm_audio_ops);
}
/* setup_stream ops override for HSW+ */

View File

@ -57,6 +57,7 @@ source "sound/soc/kirkwood/Kconfig"
source "sound/soc/img/Kconfig"
source "sound/soc/intel/Kconfig"
source "sound/soc/mediatek/Kconfig"
source "sound/soc/meson/Kconfig"
source "sound/soc/mxs/Kconfig"
source "sound/soc/pxa/Kconfig"
source "sound/soc/qcom/Kconfig"

View File

@ -38,6 +38,7 @@ obj-$(CONFIG_SND_SOC) += jz4740/
obj-$(CONFIG_SND_SOC) += img/
obj-$(CONFIG_SND_SOC) += intel/
obj-$(CONFIG_SND_SOC) += mediatek/
obj-$(CONFIG_SND_SOC) += meson/
obj-$(CONFIG_SND_SOC) += mxs/
obj-$(CONFIG_SND_SOC) += nuc900/
obj-$(CONFIG_SND_SOC) += omap/

View File

@ -8,6 +8,7 @@ config SND_SOC_AMD_CZ_DA7219MX98357_MACH
select SND_SOC_DA7219
select SND_SOC_MAX98357A
select SND_SOC_ADAU7002
select REGULATOR
depends on SND_SOC_AMD_ACP && I2C
help
This option enables machine driver for DA7219 and MAX9835.

View File

@ -32,6 +32,8 @@
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/driver.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/acpi.h>
@ -148,7 +150,8 @@ static int cz_da7219_startup(struct snd_pcm_substream *substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
machine->i2s_instance = I2S_BT_INSTANCE;
machine->i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL1;
return da7219_clk_enable(substream);
}
@ -163,7 +166,7 @@ static int cz_max_startup(struct snd_pcm_substream *substream)
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
machine->i2s_instance = I2S_SP_INSTANCE;
machine->i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
}
@ -172,13 +175,24 @@ static void cz_max_shutdown(struct snd_pcm_substream *substream)
da7219_clk_disable();
}
static int cz_dmic_startup(struct snd_pcm_substream *substream)
static int cz_dmic0_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
machine->i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
}
static int cz_dmic1_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
machine->i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL0;
return da7219_clk_enable(substream);
}
@ -197,23 +211,39 @@ static const struct snd_soc_ops cz_max_play_ops = {
.shutdown = cz_max_shutdown,
};
static const struct snd_soc_ops cz_dmic_cap_ops = {
.startup = cz_dmic_startup,
static const struct snd_soc_ops cz_dmic0_cap_ops = {
.startup = cz_dmic0_startup,
.shutdown = cz_dmic_shutdown,
};
static const struct snd_soc_ops cz_dmic1_cap_ops = {
.startup = cz_dmic1_startup,
.shutdown = cz_dmic_shutdown,
};
static struct snd_soc_dai_link cz_dai_7219_98357[] = {
{
.name = "amd-da7219-play-cap",
.stream_name = "Playback and Capture",
.name = "amd-da7219-play",
.stream_name = "Playback",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.3.auto",
.cpu_dai_name = "designware-i2s.1.auto",
.codec_dai_name = "da7219-hifi",
.codec_name = "i2c-DLGS7219:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.init = cz_da7219_init,
.dpcm_playback = 1,
.ops = &cz_da7219_cap_ops,
},
{
.name = "amd-da7219-cap",
.stream_name = "Capture",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.2.auto",
.codec_dai_name = "da7219-hifi",
.codec_name = "i2c-DLGS7219:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1,
.ops = &cz_da7219_cap_ops,
},
@ -221,7 +251,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
.name = "amd-max98357-play",
.stream_name = "HiFi Playback",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.1.auto",
.cpu_dai_name = "designware-i2s.3.auto",
.codec_dai_name = "HiFi",
.codec_name = "MX98357A:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
@ -230,8 +260,22 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
.ops = &cz_max_play_ops,
},
{
.name = "dmic",
.stream_name = "DMIC Capture",
/* C panel DMIC */
.name = "dmic0",
.stream_name = "DMIC0 Capture",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.3.auto",
.codec_dai_name = "adau7002-hifi",
.codec_name = "ADAU7002:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1,
.ops = &cz_dmic0_cap_ops,
},
{
/* A/B panel DMIC */
.name = "dmic1",
.stream_name = "DMIC1 Capture",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.2.auto",
.codec_dai_name = "adau7002-hifi",
@ -239,7 +283,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1,
.ops = &cz_dmic_cap_ops,
.ops = &cz_dmic1_cap_ops,
},
};
@ -278,11 +322,52 @@ static struct snd_soc_card cz_card = {
.num_controls = ARRAY_SIZE(cz_mc_controls),
};
static struct regulator_consumer_supply acp_da7219_supplies[] = {
REGULATOR_SUPPLY("VDD", "i2c-DLGS7219:00"),
REGULATOR_SUPPLY("VDDMIC", "i2c-DLGS7219:00"),
REGULATOR_SUPPLY("VDDIO", "i2c-DLGS7219:00"),
REGULATOR_SUPPLY("IOVDD", "ADAU7002:00"),
};
static struct regulator_init_data acp_da7219_data = {
.constraints = {
.always_on = 1,
},
.num_consumer_supplies = ARRAY_SIZE(acp_da7219_supplies),
.consumer_supplies = acp_da7219_supplies,
};
static struct regulator_config acp_da7219_cfg = {
.init_data = &acp_da7219_data,
};
static struct regulator_ops acp_da7219_ops = {
};
static struct regulator_desc acp_da7219_desc = {
.name = "reg-fixed-1.8V",
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.ops = &acp_da7219_ops,
.fixed_uV = 1800000, /* 1.8V */
.n_voltages = 1,
};
static int cz_probe(struct platform_device *pdev)
{
int ret;
struct snd_soc_card *card;
struct acp_platform_info *machine;
struct regulator_dev *rdev;
acp_da7219_cfg.dev = &pdev->dev;
rdev = devm_regulator_register(&pdev->dev, &acp_da7219_desc,
&acp_da7219_cfg);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "Failed to register regulator: %d\n",
(int)PTR_ERR(rdev));
return -EINVAL;
}
machine = devm_kzalloc(&pdev->dev, sizeof(struct acp_platform_info),
GFP_KERNEL);

View File

@ -224,13 +224,11 @@ static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio,
switch (asic_type) {
case CHIP_STONEY:
dmadscr[i].xfer_val |=
BIT(22) |
(ACP_DMA_ATTR_SHARED_MEM_TO_DAGB_GARLIC << 16) |
(size / 2);
break;
default:
dmadscr[i].xfer_val |=
BIT(22) |
(ACP_DMA_ATTR_SHAREDMEM_TO_DAGB_ONION << 16) |
(size / 2);
}
@ -322,22 +320,87 @@ static void config_acp_dma(void __iomem *acp_mmio,
struct audio_substream_data *rtd,
u32 asic_type)
{
u16 ch_acp_sysmem, ch_acp_i2s;
acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages,
rtd->pte_offset);
if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) {
ch_acp_sysmem = rtd->ch1;
ch_acp_i2s = rtd->ch2;
} else {
ch_acp_i2s = rtd->ch1;
ch_acp_sysmem = rtd->ch2;
}
/* Configure System memory <-> ACP SRAM DMA descriptors */
set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size,
rtd->direction, rtd->pte_offset,
rtd->ch1, rtd->sram_bank,
ch_acp_sysmem, rtd->sram_bank,
rtd->dma_dscr_idx_1, asic_type);
/* Configure ACP SRAM <-> I2S DMA descriptors */
set_acp_to_i2s_dma_descriptors(acp_mmio, rtd->size,
rtd->direction, rtd->sram_bank,
rtd->destination, rtd->ch2,
rtd->destination, ch_acp_i2s,
rtd->dma_dscr_idx_2, asic_type);
}
static void acp_dma_cap_channel_enable(void __iomem *acp_mmio,
u16 cap_channel)
{
u32 val, ch_reg, imr_reg, res_reg;
switch (cap_channel) {
case CAP_CHANNEL1:
ch_reg = mmACP_I2SMICSP_RER1;
res_reg = mmACP_I2SMICSP_RCR1;
imr_reg = mmACP_I2SMICSP_IMR1;
break;
case CAP_CHANNEL0:
default:
ch_reg = mmACP_I2SMICSP_RER0;
res_reg = mmACP_I2SMICSP_RCR0;
imr_reg = mmACP_I2SMICSP_IMR0;
break;
}
val = acp_reg_read(acp_mmio,
mmACP_I2S_16BIT_RESOLUTION_EN);
if (val & ACP_I2S_MIC_16BIT_RESOLUTION_EN) {
acp_reg_write(0x0, acp_mmio, ch_reg);
/* Set 16bit resolution on capture */
acp_reg_write(0x2, acp_mmio, res_reg);
}
val = acp_reg_read(acp_mmio, imr_reg);
val &= ~ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM_MASK;
val &= ~ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM_MASK;
acp_reg_write(val, acp_mmio, imr_reg);
acp_reg_write(0x1, acp_mmio, ch_reg);
}
static void acp_dma_cap_channel_disable(void __iomem *acp_mmio,
u16 cap_channel)
{
u32 val, ch_reg, imr_reg;
switch (cap_channel) {
case CAP_CHANNEL1:
imr_reg = mmACP_I2SMICSP_IMR1;
ch_reg = mmACP_I2SMICSP_RER1;
break;
case CAP_CHANNEL0:
default:
imr_reg = mmACP_I2SMICSP_IMR0;
ch_reg = mmACP_I2SMICSP_RER0;
break;
}
val = acp_reg_read(acp_mmio, imr_reg);
val |= ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM_MASK;
val |= ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM_MASK;
acp_reg_write(val, acp_mmio, imr_reg);
acp_reg_write(0x0, acp_mmio, ch_reg);
}
/* Start a given DMA channel transfer */
static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num, bool is_circular)
{
u32 dma_ctrl;
@ -356,10 +419,8 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
switch (ch_num) {
case ACP_TO_I2S_DMA_CH_NUM:
case ACP_TO_SYSRAM_CH_NUM:
case I2S_TO_ACP_DMA_CH_NUM:
case ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM:
case ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM:
case I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM:
dma_ctrl |= ACP_DMA_CNTL_0__DMAChIOCEn_MASK;
break;
@ -368,8 +429,11 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
break;
}
/* circular for both DMA channel */
dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
/* enable for ACP to SRAM DMA channel */
if (is_circular == true)
dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
else
dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
}
@ -613,6 +677,7 @@ static int acp_deinit(void __iomem *acp_mmio)
/* ACP DMA irq handler routine for playback, capture usecases */
static irqreturn_t dma_irq_handler(int irq, void *arg)
{
u16 dscr_idx;
u32 intr_flag, ext_intr_status;
struct audio_drv_data *irq_data;
void __iomem *acp_mmio;
@ -644,32 +709,39 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
valid_irq = true;
if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_14) ==
CAPTURE_START_DMA_DESCR_CH15)
dscr_idx = CAPTURE_END_DMA_DESCR_CH14;
else
dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, dscr_idx,
1, 0);
acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false);
snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) {
valid_irq = true;
acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16,
acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_10) ==
CAPTURE_START_DMA_DESCR_CH11)
dscr_idx = CAPTURE_END_DMA_DESCR_CH10;
else
dscr_idx = CAPTURE_START_DMA_DESCR_CH10;
config_acp_dma_channel(acp_mmio,
ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM,
dscr_idx, 1, 0);
acp_dma_start(acp_mmio, ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM,
false);
snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream);
acp_reg_write((intr_flag &
BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
if ((intr_flag & BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
acp_reg_write((intr_flag &
BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) << 16,
acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
if (valid_irq)
return IRQ_HANDLED;
else
@ -773,8 +845,10 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
if (WARN_ON(!rtd))
return -EINVAL;
if (pinfo)
if (pinfo) {
rtd->i2s_instance = pinfo->i2s_instance;
rtd->capture_channel = pinfo->capture_channel;
}
if (adata->asic_type == CHIP_STONEY) {
val = acp_reg_read(adata->acp_mmio,
mmACP_I2S_16BIT_RESOLUTION_EN);
@ -842,8 +916,8 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
switch (rtd->i2s_instance) {
case I2S_BT_INSTANCE:
rtd->pte_offset = ACP_ST_BT_CAPTURE_PTE_OFFSET;
rtd->ch1 = ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM;
rtd->ch2 = I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM;
rtd->ch1 = I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM;
rtd->ch2 = ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM;
rtd->sram_bank = ACP_SRAM_BANK_4_ADDRESS;
rtd->destination = FROM_BLUETOOTH;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10;
@ -852,13 +926,14 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH;
rtd->byte_cnt_low_reg_offset =
mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW;
rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_11;
adata->capture_i2sbt_stream = substream;
break;
case I2S_SP_INSTANCE:
default:
rtd->pte_offset = ACP_CAPTURE_PTE_OFFSET;
rtd->ch1 = ACP_TO_SYSRAM_CH_NUM;
rtd->ch2 = I2S_TO_ACP_DMA_CH_NUM;
rtd->ch1 = I2S_TO_ACP_DMA_CH_NUM;
rtd->ch2 = ACP_TO_SYSRAM_CH_NUM;
switch (adata->asic_type) {
case CHIP_STONEY:
rtd->pte_offset = ACP_ST_CAPTURE_PTE_OFFSET;
@ -875,6 +950,7 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
mmACP_I2S_RECEIVED_BYTE_CNT_HIGH;
rtd->byte_cnt_low_reg_offset =
mmACP_I2S_RECEIVED_BYTE_CNT_LOW;
rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_15;
adata->capture_i2ssp_stream = substream;
}
}
@ -928,6 +1004,8 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream)
u32 buffersize;
u32 pos = 0;
u64 bytescount = 0;
u16 dscr;
u32 period_bytes, delay;
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
@ -935,12 +1013,25 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream)
if (!rtd)
return -EINVAL;
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
bytescount = acp_get_byte_count(rtd);
if (bytescount > rtd->bytescount)
bytescount -= rtd->bytescount;
pos = do_div(bytescount, buffersize);
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
period_bytes = frames_to_bytes(runtime, runtime->period_size);
dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr);
if (dscr == rtd->dma_dscr_idx_1)
pos = period_bytes;
else
pos = 0;
bytescount = acp_get_byte_count(rtd);
if (bytescount > rtd->bytescount)
bytescount -= rtd->bytescount;
delay = do_div(bytescount, period_bytes);
runtime->delay = bytes_to_frames(runtime, delay);
} else {
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
bytescount = acp_get_byte_count(rtd);
if (bytescount > rtd->bytescount)
bytescount -= rtd->bytescount;
pos = do_div(bytescount, buffersize);
}
return bytes_to_frames(runtime, pos);
}
@ -954,16 +1045,24 @@ static int acp_dma_prepare(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
u16 ch_acp_sysmem, ch_acp_i2s;
if (!rtd)
return -EINVAL;
if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) {
ch_acp_sysmem = rtd->ch1;
ch_acp_i2s = rtd->ch2;
} else {
ch_acp_i2s = rtd->ch1;
ch_acp_sysmem = rtd->ch2;
}
config_acp_dma_channel(rtd->acp_mmio,
rtd->ch1,
ch_acp_sysmem,
rtd->dma_dscr_idx_1,
NUM_DSCRS_PER_CHANNEL, 0);
config_acp_dma_channel(rtd->acp_mmio,
rtd->ch2,
ch_acp_i2s,
rtd->dma_dscr_idx_2,
NUM_DSCRS_PER_CHANNEL, 0);
return 0;
@ -972,7 +1071,6 @@ static int acp_dma_prepare(struct snd_pcm_substream *substream)
static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd)
{
int ret;
u64 bytescount = 0;
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
@ -983,37 +1081,32 @@ static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
bytescount = acp_get_byte_count(rtd);
if (rtd->bytescount == 0)
rtd->bytescount = bytescount;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
acp_dma_start(rtd->acp_mmio, rtd->ch1);
acp_dma_start(rtd->acp_mmio, rtd->ch2);
rtd->bytescount = acp_get_byte_count(rtd);
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
if (rtd->capture_channel == CAP_CHANNEL0) {
acp_dma_cap_channel_disable(rtd->acp_mmio,
CAP_CHANNEL1);
acp_dma_cap_channel_enable(rtd->acp_mmio,
CAP_CHANNEL0);
}
if (rtd->capture_channel == CAP_CHANNEL1) {
acp_dma_cap_channel_disable(rtd->acp_mmio,
CAP_CHANNEL0);
acp_dma_cap_channel_enable(rtd->acp_mmio,
CAP_CHANNEL1);
}
acp_dma_start(rtd->acp_mmio, rtd->ch1, true);
} else {
acp_dma_start(rtd->acp_mmio, rtd->ch2);
acp_dma_start(rtd->acp_mmio, rtd->ch1);
acp_dma_start(rtd->acp_mmio, rtd->ch1, true);
acp_dma_start(rtd->acp_mmio, rtd->ch2, true);
}
ret = 0;
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
/* For playback, non circular dma should be stopped first
* i.e Sysram to acp dma transfer channel(rtd->ch1) should be
* stopped before stopping cirular dma which is acp sram to i2s
* fifo dma transfer channel(rtd->ch2). Where as in Capture
* scenario, i2s fifo to acp sram dma channel(rtd->ch2) stopped
* first before stopping acp sram to sysram which is circular
* dma(rtd->ch1).
*/
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
acp_dma_stop(rtd->acp_mmio, rtd->ch1);
ret = acp_dma_stop(rtd->acp_mmio, rtd->ch2);
} else {
acp_dma_stop(rtd->acp_mmio, rtd->ch2);
ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1);
}
rtd->bytescount = 0;
acp_dma_stop(rtd->acp_mmio, rtd->ch2);
ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1);
break;
default:
ret = -EINVAL;

View File

@ -55,6 +55,8 @@
#define I2S_SP_INSTANCE 0x01
#define I2S_BT_INSTANCE 0x02
#define CAP_CHANNEL0 0x00
#define CAP_CHANNEL1 0x01
#define ACP_TILE_ON_MASK 0x03
#define ACP_TILE_OFF_MASK 0x02
@ -72,16 +74,16 @@
#define ACP_TO_I2S_DMA_CH_NUM 13
/* Capture DMA channels */
#define ACP_TO_SYSRAM_CH_NUM 14
#define I2S_TO_ACP_DMA_CH_NUM 15
#define I2S_TO_ACP_DMA_CH_NUM 14
#define ACP_TO_SYSRAM_CH_NUM 15
/* Playback DMA Channels for I2S BT instance */
#define SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM 8
#define ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM 9
/* Capture DMA Channels for I2S BT Instance */
#define ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM 10
#define I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM 11
#define I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM 10
#define ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM 11
#define NUM_DSCRS_PER_CHANNEL 2
@ -125,6 +127,7 @@ struct audio_substream_data {
unsigned int order;
u16 num_of_pages;
u16 i2s_instance;
u16 capture_channel;
u16 direction;
u16 ch1;
u16 ch2;
@ -135,6 +138,7 @@ struct audio_substream_data {
u32 sram_bank;
u32 byte_cnt_high_reg_offset;
u32 byte_cnt_low_reg_offset;
u32 dma_curr_dscr;
uint64_t size;
u64 bytescount;
void __iomem *acp_mmio;
@ -155,6 +159,7 @@ struct audio_drv_data {
*/
struct acp_platform_info {
u16 i2s_instance;
u16 capture_channel;
};
union acp_dma_count {

View File

@ -206,7 +206,6 @@ struct atmel_i2s_dev {
struct regmap *regmap;
struct clk *pclk;
struct clk *gclk;
struct clk *aclk;
struct snd_dmaengine_dai_dma_data playback;
struct snd_dmaengine_dai_dma_data capture;
unsigned int fmt;
@ -303,7 +302,7 @@ static int atmel_i2s_get_gck_param(struct atmel_i2s_dev *dev, int fs)
{
int i, best;
if (!dev->gclk || !dev->aclk) {
if (!dev->gclk) {
dev_err(dev->dev, "cannot generate the I2S Master Clock\n");
return -EINVAL;
}
@ -421,7 +420,7 @@ static int atmel_i2s_switch_mck_generator(struct atmel_i2s_dev *dev,
bool enabled)
{
unsigned int mr, mr_mask;
unsigned long aclk_rate;
unsigned long gclk_rate;
int ret;
mr = 0;
@ -445,35 +444,18 @@ static int atmel_i2s_switch_mck_generator(struct atmel_i2s_dev *dev,
/* Disable/unprepare the PMC generated clock. */
clk_disable_unprepare(dev->gclk);
/* Disable/unprepare the PLL audio clock. */
clk_disable_unprepare(dev->aclk);
return 0;
}
if (!dev->gck_param)
return -EINVAL;
aclk_rate = dev->gck_param->mck * (dev->gck_param->imckdiv + 1);
gclk_rate = dev->gck_param->mck * (dev->gck_param->imckdiv + 1);
/* Fist change the PLL audio clock frequency ... */
ret = clk_set_rate(dev->aclk, aclk_rate);
ret = clk_set_rate(dev->gclk, gclk_rate);
if (ret)
return ret;
/*
* ... then set the PMC generated clock rate to the very same frequency
* to set the gclk parent to aclk.
*/
ret = clk_set_rate(dev->gclk, aclk_rate);
if (ret)
return ret;
/* Prepare and enable the PLL audio clock first ... */
ret = clk_prepare_enable(dev->aclk);
if (ret)
return ret;
/* ... then prepare and enable the PMC generated clock. */
ret = clk_prepare_enable(dev->gclk);
if (ret)
return ret;
@ -668,28 +650,14 @@ static int atmel_i2s_probe(struct platform_device *pdev)
return err;
}
/* Get audio clocks to generate the I2S Master Clock (I2S_MCK) */
dev->aclk = devm_clk_get(&pdev->dev, "aclk");
/* Get audio clock to generate the I2S Master Clock (I2S_MCK) */
dev->gclk = devm_clk_get(&pdev->dev, "gclk");
if (IS_ERR(dev->aclk) && IS_ERR(dev->gclk)) {
if (PTR_ERR(dev->aclk) == -EPROBE_DEFER ||
PTR_ERR(dev->gclk) == -EPROBE_DEFER)
if (IS_ERR(dev->gclk)) {
if (PTR_ERR(dev->gclk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
/* Master Mode not supported */
dev->aclk = NULL;
dev->gclk = NULL;
} else if (IS_ERR(dev->gclk)) {
err = PTR_ERR(dev->gclk);
dev_err(&pdev->dev,
"failed to get the PMC generated clock: %d\n", err);
return err;
} else if (IS_ERR(dev->aclk)) {
err = PTR_ERR(dev->aclk);
dev_err(&pdev->dev,
"failed to get the PLL audio clock: %d\n", err);
return err;
}
dev->dev = &pdev->dev;
dev->regmap = regmap;
platform_set_drvdata(pdev, dev);

View File

@ -74,12 +74,12 @@ config SND_SOC_ALL_CODECS
select SND_SOC_DA7219 if I2C
select SND_SOC_DA732X if I2C
select SND_SOC_DA9055 if I2C
select SND_SOC_DIO2125
select SND_SOC_DMIC if GPIOLIB
select SND_SOC_ES8316 if I2C
select SND_SOC_ES8328_SPI if SPI_MASTER
select SND_SOC_ES8328_I2C if I2C
select SND_SOC_ES7134
select SND_SOC_ES7241
select SND_SOC_GTM601
select SND_SOC_HDAC_HDMI
select SND_SOC_ICS43432
@ -141,8 +141,10 @@ config SND_SOC_ALL_CODECS
select SND_SOC_RT5668 if I2C
select SND_SOC_RT5670 if I2C
select SND_SOC_RT5677 if I2C && SPI_MASTER
select SND_SOC_RT5682 if I2C
select SND_SOC_SGTL5000 if I2C
select SND_SOC_SI476X if MFD_SI476X_CORE
select SND_SOC_SIMPLE_AMPLIFIER
select SND_SOC_SIRF_AUDIO_CODEC
select SND_SOC_SPDIF
select SND_SOC_SSM2305
@ -572,10 +574,6 @@ config SND_SOC_DA732X
config SND_SOC_DA9055
tristate
config SND_SOC_DIO2125
tristate "Dioo DIO2125 Amplifier"
select GPIOLIB
config SND_SOC_DMIC
tristate
@ -588,6 +586,9 @@ config SND_SOC_HDMI_CODEC
config SND_SOC_ES7134
tristate "Everest Semi ES7134 CODEC"
config SND_SOC_ES7241
tristate "Everest Semi ES7241 CODEC"
config SND_SOC_ES8316
tristate "Everest Semi ES8316 CODEC"
depends on I2C
@ -778,6 +779,7 @@ config SND_SOC_RL6231
default y if SND_SOC_RT5668=y
default y if SND_SOC_RT5670=y
default y if SND_SOC_RT5677=y
default y if SND_SOC_RT5682=y
default y if SND_SOC_RT1305=y
default m if SND_SOC_RT5514=m
default m if SND_SOC_RT5616=m
@ -791,6 +793,7 @@ config SND_SOC_RL6231
default m if SND_SOC_RT5668=m
default m if SND_SOC_RT5670=m
default m if SND_SOC_RT5677=m
default m if SND_SOC_RT5682=m
default m if SND_SOC_RT1305=m
config SND_SOC_RL6347A
@ -871,6 +874,9 @@ config SND_SOC_RT5677_SPI
tristate
default SND_SOC_RT5677 && SPI
config SND_SOC_RT5682
tristate
#Freescale sgtl5000 codec
config SND_SOC_SGTL5000
tristate "Freescale SGTL5000 CODEC"
@ -891,6 +897,10 @@ config SND_SOC_SIGMADSP_REGMAP
tristate
select SND_SOC_SIGMADSP
config SND_SOC_SIMPLE_AMPLIFIER
tristate "Simple Audio Amplifier"
select GPIOLIB
config SND_SOC_SIRF_AUDIO_CODEC
tristate "SiRF SoC internal audio codec"
select REGMAP_MMIO
@ -953,8 +963,11 @@ config SND_SOC_TAS5086
depends on I2C
config SND_SOC_TAS571X
tristate "Texas Instruments TAS5711/TAS5717/TAS5719/TAS5721 power amplifiers"
tristate "Texas Instruments TAS571x power amplifiers"
depends on I2C
help
Enable support for Texas Instruments TAS5707, TAS5711, TAS5717,
TAS5719 and TAS5721 power amplifiers
config SND_SOC_TAS5720
tristate "Texas Instruments TAS5720 Mono Audio amplifier"

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