mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 04:34:08 +08:00
Merge branch 'asoc-4.19' into asoc-next
This commit is contained in:
commit
4aa5db22d3
23
Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt
Normal file
23
Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt
Normal 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>;
|
||||
};
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
@ -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";
|
||||
};
|
@ -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";
|
||||
};
|
@ -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";
|
||||
};
|
@ -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>;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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>;
|
||||
};
|
@ -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>;
|
||||
};
|
||||
|
28
Documentation/devicetree/bindings/sound/everest,es7241.txt
Normal file
28
Documentation/devicetree/bindings/sound/everest,es7241.txt
Normal 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>;
|
||||
};
|
@ -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 >;
|
||||
};
|
@ -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 */
|
||||
|
@ -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";
|
||||
};
|
||||
|
24
Documentation/devicetree/bindings/sound/name-prefix.txt
Normal file
24
Documentation/devicetree/bindings/sound/name-prefix.txt
Normal 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";
|
||||
};
|
@ -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";
|
||||
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
@ -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>;
|
||||
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
80
Documentation/devicetree/bindings/sound/qcom,sdm845.txt
Normal file
80
Documentation/devicetree/bindings/sound/qcom,sdm845.txt
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
123
Documentation/devicetree/bindings/sound/qcom,wcd9335.txt
Normal file
123
Documentation/devicetree/bindings/sound/qcom,wcd9335.txt
Normal 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>;
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
50
Documentation/devicetree/bindings/sound/rt5682.txt
Normal file
50
Documentation/devicetree/bindings/sound/rt5682.txt
Normal 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>;
|
||||
};
|
@ -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
|
||||
|
12
Documentation/devicetree/bindings/sound/simple-amplifier.txt
Normal file
12
Documentation/devicetree/bindings/sound/simple-amplifier.txt
Normal 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>;
|
||||
};
|
@ -7,6 +7,7 @@ powerdown (optional).
|
||||
Required properties:
|
||||
|
||||
- compatible: should be one of the following:
|
||||
- "ti,tas5707"
|
||||
- "ti,tas5711",
|
||||
- "ti,tas5717",
|
||||
- "ti,tas5719",
|
||||
|
@ -254,9 +254,7 @@ configuration.
|
||||
channels->min = channels->max = 2;
|
||||
|
||||
/* set DAI0 to 16 bit */
|
||||
snd_mask_set(¶ms->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;
|
||||
}
|
||||
|
||||
|
15
MAINTAINERS
15
MAINTAINERS
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
¶m, &pdev->dev, "data");
|
||||
dma_request_slave_channel(&pdev->dev, "data");
|
||||
if (!data->dma_chan)
|
||||
return -EBUSY;
|
||||
ret = dmaengine_slave_config(data->dma_chan, &config);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
¶ms, &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,
|
||||
¶ms, &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,
|
||||
¶ms, &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;
|
||||
|
@ -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,
|
||||
¶m_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,
|
||||
¶m_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;
|
||||
|
@ -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,
|
||||
¶m, 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");
|
||||
|
118
include/drm/drm_audio_component.h
Normal file
118
include/drm/drm_audio_component.h
Normal 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_ */
|
@ -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_ */
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
||||
|
@ -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__
|
||||
|
||||
|
61
include/sound/hda_component.h
Normal file
61
include/sound/hda_component.h
Normal 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 */
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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 */
|
||||
|
@ -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
40
include/sound/rt5682.h
Normal 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
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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");
|
@ -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 **);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
335
sound/hda/hdac_component.c
Normal 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);
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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+ */
|
||||
|
@ -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"
|
||||
|
@ -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/
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user