提交 126f7051 编写于 作者: L Linus Torvalds

Merge tag 'sound-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound updates from Takashi Iwai:
 "We've got many code additions at this cycle as a result of quite a few
  new drivers. Below are highlights:

  Core stuff:
   - Fix the long-standing issue with the device registration order; the
     control device is now registered at last
   - PCM locking code cleanups for RT kernels
   - Fixes for possible races in ALSA timer resolution accesses
   - TLV offset definitions in uapi

  ASoC:
   - Many fixes for the topology stuff, including fixes for v4 ABI
     compatibility
   - Lots of cleanups / quirks for Intel platforms based on Realtek
     CODECs
   - Continued componentization works, removing legacy CODEC stuff
   - Conversion of OMAP DMA to the new, more standard SDMA-PCM driver
   - Fixes and updates to Cirrus Logic SoC drivers
   - New Qualcomm DSP support
   - New drivers for Analog SSM2305, Atmel I2S controllers, Mediatek
     MT6351, MT6797 and MT7622, Qualcomm DSPs, Realtek RT1305, RT1306
     and RT5668 and TI TSCS454

  HD-audio:
   - Finally better support for some CA0132 boards, allowing Windows
     firmware
   - HP Spectre x360 support along with a bulk of COEF stuff
   - Blacklisting power save default some known boards reported on
     Fedora

  USB-audio:
   - Continued improvements on UAC3 support; now BADD is supported
   - Fixes / improvements for Dell WD15 dock
   - Allow DMA coherent pages for PCM buffers for ARCH, MIPS & co

  Others:
   - New Xen sound frontend driver support
   - Cache implementation and other improvements for FireWire DICE
   - Conversions to octal permissions in allover places"

* tag 'sound-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (386 commits)
  ASoC: dapm: delete dapm_kcontrol_data paths list before freeing it
  ALSA: usb-audio: remove redundant check on err
  ASoC: topology: Move skl-tplg-interface.h to uapi
  ASoC: topology: Move v4 manifest header data structures to uapi
  ASoC: topology: Improve backwards compatibility with v4 topology files
  ALSA: pci/hda: Remove unused, broken, header file
  ASoC: TSCS454: Add Support
  ASoC: Intel: kbl: Move codec sysclk config to codec_init function
  ASoC: simple-card: set cpu dai clk in hw_params
  ALSA: hda - Handle kzalloc() failure in snd_hda_attach_pcm_stream()
  ALSA: oxygen: use match_string() helper
  ASoC: dapm: use match_string() helper
  ASoC: max98095: use match_string() helper
  ASoC: max98088: use match_string() helper
  ASoC: Intel: bytcr_rt5651: Set card long_name based on quirks
  ASoC: mt6797-mt6351: add hostless phone call path
  ASoC: mt6797: add Hostless DAI
  ASoC: mt6797: add PCM interface
  ASoC: mediatek: export mtk-afe symbols as needed
  ASoC: codecs: PCM1789: include gpio/consumer.h
  ...
......@@ -186,6 +186,9 @@ Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
Uwe Kleine-König <ukl@pengutronix.de>
Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
Vinod Koul <vkoul@kernel.org> <vinod.koul@intel.com>
Vinod Koul <vkoul@kernel.org> <vinod.koul@linux.intel.com>
Vinod Koul <vkoul@kernel.org> <vkoul@infradead.org>
Viresh Kumar <vireshk@kernel.org> <viresh.kumar@st.com>
Viresh Kumar <vireshk@kernel.org> <viresh.linux@gmail.com>
Viresh Kumar <vireshk@kernel.org> <viresh.kumar2@arm.com>
......
Qualcomm APR (Asynchronous Packet Router) binding
This binding describes the Qualcomm APR. APR is a IPC protocol for
communication between Application processor and QDSP. APR is mainly
used for audio/voice services on the QDSP.
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,apr-v<VERSION-NUMBER>", example "qcom,apr-v2"
- reg
Usage: required
Value type: <u32>
Definition: Destination processor ID.
Possible values are :
1 - APR simulator
2 - PC
3 - MODEM
4 - ADSP
5 - APPS
6 - MODEM2
7 - APPS2
= APR SERVICES
Each subnode of the APR node represents service tied to this apr. The name
of the nodes are not important. The properties of these nodes are defined
by the individual bindings for the specific service
- All APR services MUST contain the following property:
- reg
Usage: required
Value type: <u32>
Definition: APR Service ID
Possible values are :
3 - DSP Core Service
4 - Audio Front End Service.
5 - Voice Stream Manager Service.
6 - Voice processing manager.
7 - Audio Stream Manager Service.
8 - Audio Device Manager Service.
9 - Multimode voice manager.
10 - Core voice stream.
11 - Core voice processor.
12 - Ultrasound stream manager.
13 - Listen stream manager.
= EXAMPLE
The following example represents a QDSP based sound card on a MSM8996 device
which uses apr as communication between Apps and QDSP.
apr@4 {
compatible = "qcom,apr-v2";
reg = <APR_DOMAIN_ADSP>;
q6core@3 {
compatible = "qcom,q6core";
reg = <APR_SVC_ADSP_CORE>;
};
q6afe@4 {
compatible = "qcom,q6afe";
reg = <APR_SVC_AFE>;
dais {
#sound-dai-cells = <1>;
hdmi@1 {
reg = <1>;
};
};
};
q6asm@7 {
compatible = "qcom,q6asm";
reg = <APR_SVC_ASM>;
...
};
q6adm@8 {
compatible = "qcom,q6adm";
reg = <APR_SVC_ADM>;
...
};
};
Analog Devices SSM2305 Speaker Amplifier
========================================
Required properties:
- compatible : "adi,ssm2305"
- shutdown-gpios : The gpio connected to the shutdown pin.
The gpio signal is ACTIVE_LOW.
Example:
ssm2305: analog-amplifier {
compatible = "adi,ssm2305";
shutdown-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>;
};
* Atmel I2S controller
Required properties:
- compatible: Should be "atmel,sama5d2-i2s".
- reg: Should be the physical base address of the controller and the
length of memory mapped region.
- interrupts: Should contain the interrupt for the controller.
- dmas: Should be one per channel name listed in the dma-names property,
as described in atmel-dma.txt and dma.txt files.
- dma-names: Two dmas have to be defined, "tx" and "rx".
This IP also supports one shared channel for both rx and tx;
if this mode is used, one "rx-tx" name must be used.
- clocks: Must contain an entry for each entry in clock-names.
Please refer to clock-bindings.txt.
- 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:
- pinctrl-0: Should specify pin control groups used for this controller.
- 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.
Example:
i2s@f8050000 {
compatible = "atmel,sama5d2-i2s";
reg = <0xf8050000 0x300>;
interrupts = <54 IRQ_TYPE_LEVEL_HIGH 7>;
dmas = <&dma0
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
AT91_XDMAC_DT_PERID(31))>,
<&dma0
(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";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2s0_default>;
};
......@@ -16,7 +16,7 @@ Required properties:
Example:
codec: cs42888@48 {
cs42888: codec@48 {
compatible = "cirrus,cs42888";
reg = <0x48>;
clocks = <&codec_mclk 0>;
......
......@@ -31,14 +31,16 @@ Required properties:
it. This property is optional depending on the SoC
design.
- big-endian : If this property is absent, the little endian mode
will be in use as default. Otherwise, the big endian
mode will be in use for all the device registers.
- fsl,asrc-rate : Defines a mutual sample rate used by DPCM Back Ends.
- fsl,asrc-width : Defines a mutual sample width used by DPCM Back Ends.
Optional properties:
- big-endian : If this property is absent, the little endian mode
will be in use as default. Otherwise, the big endian
mode will be in use for all the device registers.
Example:
asrc: asrc@2034000 {
......
......@@ -42,6 +42,8 @@ Required properties:
means all the settings for Receiving would be
duplicated from Transmition related registers.
Optional properties:
- big-endian : If this property is absent, the native endian mode
will be in use as default, or the big endian mode
will be in use for all the device registers.
......
......@@ -33,6 +33,8 @@ Required properties:
it. This property is optional depending on the SoC
design.
Optional properties:
- big-endian : If this property is absent, the native endian mode
will be in use as default, or the big endian mode
will be in use for all the device registers.
......
......@@ -28,9 +28,6 @@ Required properties:
pinctrl-names. See ../pinctrl/pinctrl-bindings.txt
for details of the property values.
- big-endian : Boolean property, required if all the FTM_PWM
registers are big-endian rather than little-endian.
- lsb-first : Configures whether the LSB or the MSB is transmitted
first for the fifo data. If this property is absent,
the MSB is transmitted first as default, or the LSB
......@@ -48,6 +45,11 @@ Required properties:
receive data by following their own bit clocks and
frame sync clocks separately.
Optional properties:
- big-endian : Boolean property, required if all the SAI
registers are big-endian rather than little-endian.
Optional properties (for mx6ul):
- fsl,sai-mclk-direction-output: This is a boolean property. If present,
......
Mediatek AFE PCM controller for mt2701
Required properties:
- compatible = "mediatek,mt2701-audio";
- compatible: should be one of the followings.
- "mediatek,mt2701-audio"
- "mediatek,mt7622-audio"
- interrupts: should contain AFE and ASYS interrupts
- interrupt-names: should be "afe" and "asys"
- power-domains: should define the power domain
......
Mediatek MT6351 Audio Codec
The communication between MT6351 and SoC is through Mediatek PMIC wrapper.
For more detail, please visit Mediatek PMIC wrapper documentation.
Must be a child node of PMIC wrapper.
Required properties:
- compatible : "mediatek,mt6351-sound".
Example:
mt6351_snd {
compatible = "mediatek,mt6351-sound";
};
Mediatek AFE PCM controller for mt6797
Required properties:
- compatible = "mediatek,mt6797-audio";
- reg: register location and size
- interrupts: should contain AFE interrupt
- power-domains: should define the power domain
- clocks: Must contain an entry for each entry in clock-names
- clock-names: should have these clock names:
"infra_sys_audio_clk",
"infra_sys_audio_26m",
"mtkaif_26m_clk",
"top_mux_audio",
"top_mux_aud_intbus",
"top_sys_pll3_d4",
"top_sys_pll1_d4",
"top_clk26m_clk";
Example:
afe: mt6797-afe-pcm@11220000 {
compatible = "mediatek,mt6797-audio";
reg = <0 0x11220000 0 0x1000>;
interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT6797_POWER_DOMAIN_AUDIO>;
clocks = <&infrasys CLK_INFRA_AUDIO>,
<&infrasys CLK_INFRA_AUDIO_26M>,
<&infrasys CLK_INFRA_AUDIO_26M_PAD_TOP>,
<&topckgen CLK_TOP_MUX_AUDIO>,
<&topckgen CLK_TOP_MUX_AUD_INTBUS>,
<&topckgen CLK_TOP_SYSPLL3_D4>,
<&topckgen CLK_TOP_SYSPLL1_D4>,
<&clk26m>;
clock-names = "infra_sys_audio_clk",
"infra_sys_audio_26m",
"mtkaif_26m_clk",
"top_mux_audio",
"top_mux_aud_intbus",
"top_sys_pll3_d4",
"top_sys_pll1_d4",
"top_clk26m_clk";
};
MT6797 with MT6351 CODEC
Required properties:
- compatible: "mediatek,mt6797-mt6351-sound"
- mediatek,platform: the phandle of MT6797 ASoC platform
- mediatek,audio-codec: the phandles of MT6351 codec
Example:
sound {
compatible = "mediatek,mt6797-mt6351-sound";
mediatek,audio-codec = <&mt6351_snd>;
mediatek,platform = <&afe>;
};
* Qualcomm Technologies APQ8096 ASoC sound card driver
This binding describes the APQ8096 sound card, which uses qdsp for audio.
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,apq8096-sndcard"
- qcom,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:
Valid names include:
Board Connectors:
"Headphone Left"
"Headphone Right"
"Earphone"
"Line Out1"
"Line Out2"
"Line Out3"
"Line Out4"
"Analog Mic1"
"Analog Mic2"
"Analog Mic3"
"Analog Mic4"
"Analog Mic5"
"Analog Mic6"
"Digital Mic2"
"Digital Mic3"
Audio pins and MicBias on WCD9335 Codec:
"MIC_BIAS1
"MIC_BIAS2"
"MIC_BIAS3"
"MIC_BIAS4"
"AMIC1"
"AMIC2"
"AMIC3"
"AMIC4"
"AMIC5"
"AMIC6"
"AMIC6"
"DMIC1"
"DMIC2"
"DMIC3"
= 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: Optional
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 with arguments>
Definition: dai phandle/s and port of CPU/CODEC/PLATFORM node.
Example:
audio {
compatible = "qcom,apq8096-sndcard";
qcom,model = "DB820c";
mm1-dai-link {
link-name = "MultiMedia1";
cpu {
sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
};
};
hdmi-dai-link {
link-name = "HDMI Playback";
cpu {
sound-dai = <&q6afe HDMI_RX>;
};
platform {
sound-dai = <&q6adm>;
};
codec {
sound-dai = <&hdmi 0>;
};
};
};
Qualcomm Audio Device Manager (Q6ADM) binding
Q6ADM is one of the APR audio service on Q6DSP.
Please refer to qcom,apr.txt for details of the coommon apr service bindings
used by the apr service device.
- but must contain the following property:
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,q6adm-v<MAJOR-NUMBER>.<MINOR-NUMBER>".
Or "qcom,q6adm" where the version number can be queried
from DSP.
example "qcom,q6adm-v2.0"
= ADM routing
"routing" subnode of the ADM node represents adm routing specific configuration
- #sound-dai-cells
Usage: required
Value type: <u32>
Definition: Must be 0
= EXAMPLE
q6adm@8 {
compatible = "qcom,q6adm";
reg = <APR_SVC_ADM>;
q6routing: routing {
#sound-dai-cells = <0>;
};
};
Qualcomm Audio Front End (Q6AFE) binding
AFE is one of the APR audio service on Q6DSP
Please refer to qcom,apr.txt for details of the common apr service bindings
used by all apr services. Must contain the following properties.
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,q6afe-v<MAJOR-NUMBER>.<MINOR-NUMBER>"
Or "qcom,q6afe" where the version number can be queried
from DSP.
example "qcom,q6afe"
= AFE DAIs (Digial Audio Interface)
"dais" subnode of the AFE node. It represents afe dais, each afe dai is a
subnode of "dais" representing board specific dai setup.
"dais" node should have following properties followed by dai children.
- #sound-dai-cells
Usage: required
Value type: <u32>
Definition: Must be 1
- #address-cells
Usage: required
Value type: <u32>
Definition: Must be 1
- #size-cells
Usage: required
Value type: <u32>
Definition: Must be 0
== AFE DAI is subnode of "dais" and represent a dai, it includes board specific
configuration of each dai. Must contain the following properties.
- reg
Usage: required
Value type: <u32>
Definition: Must be dai id
- qcom,sd-lines
Usage: required for mi2s interface
Value type: <prop-encoded-array>
Definition: Must be list of serial data lines used by this dai.
should be one or more of the 1-4 sd lines.
- qcom,tdm-sync-mode:
Usage: required for tdm interface
Value type: <prop-encoded-array>
Definition: Synchronization mode.
0 - Short sync bit mode
1 - Long sync mode
2 - Short sync slot mode
- qcom,tdm-sync-src:
Usage: required for tdm interface
Value type: <prop-encoded-array>
Definition: Synchronization source.
0 - External source
1 - Internal source
- qcom,tdm-data-out:
Usage: required for tdm interface
Value type: <prop-encoded-array>
Definition: Data out signal to drive with other masters.
0 - Disable
1 - Enable
- qcom,tdm-invert-sync:
Usage: required for tdm interface
Value type: <prop-encoded-array>
Definition: Invert the sync.
0 - Normal
1 - Invert
- qcom,tdm-data-delay:
Usage: required for tdm interface
Value type: <prop-encoded-array>
Definition: Number of bit clock to delay data
with respect to sync edge.
0 - 0 bit clock cycle
1 - 1 bit clock cycle
2 - 2 bit clock cycle
- qcom,tdm-data-align:
Usage: required for tdm interface
Value type: <prop-encoded-array>
Definition: Indicate how data is packed
within the slot. For example, 32 slot width in case of
sample bit width is 24.
0 - MSB
1 - LSB
= EXAMPLE
q6afe@4 {
compatible = "qcom,q6afe";
reg = <APR_SVC_AFE>;
dais {
#sound-dai-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
hdmi@1 {
reg = <1>;
};
tdm@24 {
reg = <24>;
qcom,tdm-sync-mode = <1>:
qcom,tdm-sync-src = <1>;
qcom,tdm-data-out = <0>;
qcom,tdm-invert-sync = <1>;
qcom,tdm-data-delay = <1>;
qcom,tdm-data-align = <0>;
};
tdm@25 {
reg = <25>;
qcom,tdm-sync-mode = <1>:
qcom,tdm-sync-src = <1>;
qcom,tdm-data-out = <0>;
qcom,tdm-invert-sync = <1>;
qcom,tdm-data-delay <1>:
qcom,tdm-data-align = <0>;
};
prim-mi2s-rx@16 {
reg = <16>;
qcom,sd-lines = <1 3>;
};
prim-mi2s-tx@17 {
reg = <17>;
qcom,sd-lines = <2>;
};
sec-mi2s-rx@18 {
reg = <18>;
qcom,sd-lines = <1 4>;
};
sec-mi2s-tx@19 {
reg = <19>;
qcom,sd-lines = <2>;
};
tert-mi2s-rx@20 {
reg = <20>;
qcom,sd-lines = <2 4>;
};
tert-mi2s-tx@21 {
reg = <21>;
qcom,sd-lines = <1>;
};
quat-mi2s-rx@22 {
reg = <22>;
qcom,sd-lines = <1>;
};
quat-mi2s-tx@23 {
reg = <23>;
qcom,sd-lines = <2>;
};
};
};
Qualcomm Audio Stream Manager (Q6ASM) binding
Q6ASM is one of the APR audio service on Q6DSP.
Please refer to qcom,apr.txt for details of the common apr service bindings
used by the apr service device.
- but must contain the following property:
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,q6asm-v<MAJOR-NUMBER>.<MINOR-NUMBER>".
Or "qcom,q6asm" where the version number can be queried
from DSP.
example "qcom,q6asm-v2.0"
= ASM DAIs (Digial Audio Interface)
"dais" subnode of the ASM node represents dai specific configuration
- #sound-dai-cells
Usage: required
Value type: <u32>
Definition: Must be 1
= EXAMPLE
q6asm@7 {
compatible = "qcom,q6asm";
reg = <APR_SVC_ASM>;
q6asmdai: dais {
#sound-dai-cells = <1>;
};
};
Qualcomm ADSP Core service binding
Q6CORE is one of the APR audio service on Q6DSP.
Please refer to qcom,apr.txt for details of the common apr service bindings
used by the apr service device.
- but must contain the following property:
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,q6core-v<MAJOR-NUMBER>.<MINOR-NUMBER>".
Or "qcom,q6core" where the version number can be queried
from DSP.
example "qcom,q6core-v2.0"
= EXAMPLE
q6core@3 {
compatible = "qcom,q6core";
reg = <APR_SVC_ADSP_CORE>;
};
......@@ -26,7 +26,7 @@ Pins on the device (for linking into audio routes) for RT274:
Example:
codec: rt274@1c {
rt274: codec@1c {
compatible = "realtek,rt274";
reg = <0x1c>;
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
......
......@@ -32,7 +32,7 @@ Pins on the device (for linking into audio routes) for I2C:
Example:
codec: rt5514@57 {
rt5514: codec@57 {
compatible = "realtek,rt5514";
reg = <0x57>;
};
......@@ -26,7 +26,7 @@ Pins on the device (for linking into audio routes) for RT5616:
Example:
codec: rt5616@1b {
rt5616: codec@1b {
compatible = "realtek,rt5616";
reg = <0x1b>;
};
......@@ -22,6 +22,41 @@ Optional properties:
- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
- realtek,dmic1-data-pin
0: dmic1 is not used
1: using IN1P pin as dmic1 data pin
2: using GPIO3 pin as dmic1 data pin
- realtek,dmic2-data-pin
0: dmic2 is not used
1: using IN1N pin as dmic2 data pin
2: using GPIO4 pin as dmic2 data pin
- realtek,jack-detect-source
u32. Valid values:
0: jack-detect is not used
1: Use GPIO1 for jack-detect
2: Use JD1_IN4P for jack-detect
3: Use JD2_IN4N for jack-detect
4: Use GPIO2 for jack-detect
5: Use GPIO3 for jack-detect
6: Use GPIO4 for jack-detect
- realtek,jack-detect-not-inverted
bool. Normal jack-detect switches give an inverted signal, set this bool
in the rare case you've a jack-detect switch which is not inverted.
- realtek,over-current-threshold-microamp
u32, micbias over-current detection threshold in µA, valid values are
600, 1500 and 2000µA.
- realtek,over-current-scale-factor
u32, micbias over-current detection scale-factor, valid values are:
0: Scale current by 0.5
1: Scale current by 0.75
2: Scale current by 1.0
3: Scale current by 1.5
Pins on the device (for linking into audio routes) for RT5639/RT5640:
* DMIC1
......
......@@ -69,4 +69,4 @@ codec: rt5650@1a {
realtek,dmic-en = "true";
realtek,en-jd-func = "true";
realtek,jd-mode = <3>;
};
\ No newline at end of file
};
......@@ -50,7 +50,7 @@ Pins on the device (for linking into audio routes) for RT5651:
Example:
codec: rt5651@1a {
rt5651: codec@1a {
compatible = "realtek,rt5651";
reg = <0x1a>;
realtek,dmic-en = "true";
......
......@@ -47,7 +47,7 @@ Pins on the device (for linking into audio routes) for RT5663:
Example:
codec: rt5663@12 {
rt5663: codec@12 {
compatible = "realtek,rt5663";
reg = <0x12>;
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
......
RT5668B audio CODEC
This device supports I2C only.
Required properties:
- compatible : "realtek,rt5668b"
- 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 RT5668B:
* DMIC L1
* DMIC R1
* IN1P
* HPOL
* HPOR
Example:
rt5668 {
compatible = "realtek,rt5668b";
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>;
};
......@@ -39,7 +39,7 @@ VDDIO 1.8V 2.5V 3.3V
Example:
codec: sgtl5000@a {
sgtl5000: codec@a {
compatible = "fsl,sgtl5000";
reg = <0x0a>;
#sound-dai-cells = <0>;
......
......@@ -86,6 +86,11 @@ Optional CPU/CODEC subnodes properties:
in dai startup() and disabled with
clk_disable_unprepare() in dai
shutdown().
If a clock is specified and a
multiplication factor is given with
mclk-fs, the clock will be set to the
calculated mclk frequency when the
stream starts.
- system-clock-direction-out : specifies clock direction as 'out' on
initialization. It is useful for some aCPUs with
fixed clocks.
......
......@@ -6,6 +6,8 @@ Required properties:
- compatible: "ti,tas6424" - TAS6424
- reg: I2C slave address
- sound-dai-cells: must be equal to 0
- standby-gpios: GPIO used to shut the TAS6424 down.
- mute-gpios: GPIO used to mute all the outputs
Example:
......
......@@ -8,9 +8,15 @@ Required Properties:
- reg : <0x71> for analog mic
<0x69> for digital mic
- clock-names: Must one of the following "mclk1", "xtal", "mclk2"
- clocks: phandle of the clock that provides the codec sysclk
Example:
wookie: codec@69 {
compatible = "tempo,tscs42A2";
reg = <0x69>;
clock-names = "xtal";
clocks = <&audio_xtal>;
};
TSCS454 Audio CODEC
Required Properties:
- compatible : "tempo,tscs454"
- reg : <0x69>
- clock-names: Must one of the following "xtal", "mclk1", "mclk2"
- clocks: phandle of the clock that provides the codec sysclk
Note: If clock is not provided then bit clock is assumed
Example:
redwood: codec@69 {
#sound-dai-cells = <1>;
compatible = "tempo,tscs454";
reg = <0x69>;
clock-names = "mclk1";
clocks = <&audio_mclk>;
};
......@@ -12,7 +12,7 @@ Required properties:
Example:
codec: wm8510@1a {
wm8510: codec@1a {
compatible = "wlf,wm8510";
reg = <0x1a>;
};
......@@ -10,7 +10,7 @@ Required properties:
Example:
codec: wm8523@1a {
wm8523: codec@1a {
compatible = "wlf,wm8523";
reg = <0x1a>;
};
......@@ -10,7 +10,7 @@ Required properties:
Example:
codec: wm8524 {
wm8524: codec {
compatible = "wlf,wm8524";
wlf,mute-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
};
......@@ -10,7 +10,7 @@ Required properties:
Example:
codec: wm8580@1a {
wm8580: codec@1a {
compatible = "wlf,wm8580";
reg = <0x1a>;
};
......@@ -12,7 +12,7 @@ Required properties:
Example:
codec: wm8711@1a {
wm8711: codec@1a {
compatible = "wlf,wm8711";
reg = <0x1a>;
};
......@@ -12,7 +12,7 @@ Required properties:
Example:
codec: wm8728@1a {
wm8728: codec@1a {
compatible = "wlf,wm8728";
reg = <0x1a>;
};
......@@ -12,7 +12,7 @@ Required properties:
Example:
codec: wm8731@1a {
wm8731: codec@1a {
compatible = "wlf,wm8731";
reg = <0x1a>;
};
......
......@@ -12,7 +12,7 @@ Required properties:
Example:
codec: wm8737@1a {
wm8737: codec@1a {
compatible = "wlf,wm8737";
reg = <0x1a>;
};
......@@ -21,7 +21,7 @@ Optional properties:
Example:
codec: wm8741@1a {
wm8741: codec@1a {
compatible = "wlf,wm8741";
reg = <0x1a>;
......
......@@ -12,7 +12,7 @@ Required properties:
Example:
codec: wm8750@1a {
wm8750: codec@1a {
compatible = "wlf,wm8750";
reg = <0x1a>;
};
......@@ -34,7 +34,7 @@ Pins on the device (for linking into audio routes):
Example:
codec: wm8753@1a {
wm8753: codec@1a {
compatible = "wlf,wm8753";
reg = <0x1a>;
};
......@@ -10,7 +10,7 @@ Required properties:
Example:
codec: wm8770@1 {
wm8770: codec@1 {
compatible = "wlf,wm8770";
reg = <1>;
};
......@@ -12,7 +12,7 @@ Required properties:
Example:
codec: wm8776@1a {
wm8776: codec@1a {
compatible = "wlf,wm8776";
reg = <0x1a>;
};
......@@ -19,7 +19,7 @@ Optional properties:
Example:
codec: wm8804@1a {
wm8804: codec@1a {
compatible = "wlf,wm8804";
reg = <0x1a>;
};
......@@ -57,7 +57,7 @@ Pins on the device (for linking into audio routes):
Example:
codec: wm8903@1a {
wm8903: codec@1a {
compatible = "wlf,wm8903";
reg = <0x1a>;
interrupts = < 347 >;
......
......@@ -23,7 +23,7 @@ Optional properties:
Example:
codec: wm8960@1a {
wm8960: codec@1a {
compatible = "wlf,wm8960";
reg = <0x1a>;
......
......@@ -24,7 +24,7 @@ Optional properties:
Example:
codec: wm8962@1a {
wm8962: codec@1a {
compatible = "wlf,wm8962";
reg = <0x1a>;
......
......@@ -59,7 +59,7 @@ Optional properties:
Example:
codec: wm8994@1a {
wm8994: codec@1a {
compatible = "wlf,wm8994";
reg = <0x1a>;
......
......@@ -2224,6 +2224,13 @@ quirk_alias
Quirk alias list, pass strings like ``0123abcd:5678beef``, which
applies the existing quirk for the device 5678:beef to a new
device 0123:abcd.
use_vmalloc
Use vmalloc() for allocations of the PCM buffers (default: yes).
For architectures with non-coherent memory like ARM or MIPS, the
mmap access may give inconsistent results with vmalloc'ed
buffers. If mmap is used on such architectures, turn off this
option, so that the DMA-coherent buffers are allocated and used
instead.
This module supports multiple devices, autoprobe and hotplugging.
......
......@@ -263,6 +263,8 @@ hp-dock
HP dock support
mute-led-gpio
Mute LED control via GPIO
hp-mic-fix
Fix for headset mic pin on HP boxes
STAC9200
========
......
......@@ -179,12 +179,12 @@ i.e.
static int wm8974_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
u16 mute_reg = snd_soc_read(codec, WM8974_DAC) & 0xffbf;
struct snd_soc_component *component = dai->component;
u16 mute_reg = snd_soc_component_read32(component, WM8974_DAC) & 0xffbf;
if (mute)
snd_soc_write(codec, WM8974_DAC, mute_reg | 0x40);
snd_soc_component_write(component, WM8974_DAC, mute_reg | 0x40);
else
snd_soc_write(codec, WM8974_DAC, mute_reg);
snd_soc_component_write(component, WM8974_DAC, mute_reg);
return 0;
}
......@@ -23,30 +23,26 @@ The platform DMA driver optionally supports the following ALSA operations:-
};
The platform driver exports its DMA functionality via struct
snd_soc_platform_driver:-
snd_soc_component_driver:-
::
struct snd_soc_platform_driver {
char *name;
struct snd_soc_component_driver {
const char *name;
int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev);
int (*suspend)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
int (*resume)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
...
int (*probe)(struct snd_soc_component *);
void (*remove)(struct snd_soc_component *);
int (*suspend)(struct snd_soc_component *);
int (*resume)(struct snd_soc_component *);
/* pcm creation and destruction */
int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *, struct snd_pcm *);
int (*pcm_new)(struct snd_soc_pcm_runtime *);
void (*pcm_free)(struct snd_pcm *);
/*
* For platform caused delay reporting.
* Optional.
*/
snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
struct snd_soc_dai *);
/* platform stream ops */
struct snd_pcm_ops *pcm_ops;
...
const struct snd_pcm_ops *ops;
const struct snd_compr_ops *compr_ops;
...
};
Please refer to the ALSA driver documentation for details of audio DMA.
......
......@@ -7082,14 +7082,13 @@ L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/fbdev/i810/
INTEL ASoC BDW/HSW DRIVERS
INTEL ASoC DRIVERS
M: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
M: Liam Girdwood <liam.r.girdwood@linux.intel.com>
M: Jie Yang <yang.jie@linux.intel.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Supported
F: sound/soc/intel/common/sst-dsp*
F: sound/soc/intel/common/sst-firmware.c
F: sound/soc/intel/boards/broadwell.c
F: sound/soc/intel/haswell/
F: sound/soc/intel/
INTEL C600 SERIES SAS CONTROLLER DRIVER
M: Intel SCU Linux support <intel-linux-scu@intel.com>
......@@ -15542,6 +15541,13 @@ S: Supported
F: arch/x86/xen/*swiotlb*
F: drivers/xen/*swiotlb*
XEN SOUND FRONTEND DRIVER
M: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Supported
F: sound/xen/*
XFS FILESYSTEM
M: Darrick J. Wong <darrick.wong@oracle.com>
M: linux-xfs@vger.kernel.org
......
......@@ -635,6 +635,7 @@ EXPORT_SYMBOL(ep93xx_keypad_release_gpio);
*************************************************************************/
static struct resource ep93xx_i2s_resource[] = {
DEFINE_RES_MEM(EP93XX_I2S_PHYS_BASE, 0x100),
DEFINE_RES_IRQ(IRQ_EP93XX_SAI),
};
static struct platform_device ep93xx_i2s_device = {
......
......@@ -2444,7 +2444,7 @@ static int tda1997x_pcm_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct tda1997x_state *state = snd_soc_dai_get_drvdata(dai);
struct snd_soc_codec *codec = dai->codec;
struct snd_soc_component *component = dai->component;
struct snd_pcm_runtime *rtd = substream->runtime;
int rate, err;
......@@ -2452,11 +2452,11 @@ static int tda1997x_pcm_startup(struct snd_pcm_substream *substream,
err = snd_pcm_hw_constraint_minmax(rtd, SNDRV_PCM_HW_PARAM_RATE,
rate, rate);
if (err < 0) {
dev_err(codec->dev, "failed to constrain samplerate to %dHz\n",
dev_err(component->dev, "failed to constrain samplerate to %dHz\n",
rate);
return err;
}
dev_info(codec->dev, "set samplerate constraint to %dHz\n", rate);
dev_info(component->dev, "set samplerate constraint to %dHz\n", rate);
return 0;
}
......@@ -2479,20 +2479,22 @@ static struct snd_soc_dai_driver tda1997x_audio_dai = {
.ops = &tda1997x_dai_ops,
};
static int tda1997x_codec_probe(struct snd_soc_codec *codec)
static int tda1997x_codec_probe(struct snd_soc_component *component)
{
return 0;
}
static int tda1997x_codec_remove(struct snd_soc_codec *codec)
static void tda1997x_codec_remove(struct snd_soc_component *component)
{
return 0;
}
static struct snd_soc_codec_driver tda1997x_codec_driver = {
.probe = tda1997x_codec_probe,
.remove = tda1997x_codec_remove,
.reg_word_size = sizeof(u16),
static struct snd_soc_component_driver tda1997x_codec_driver = {
.probe = tda1997x_codec_probe,
.remove = tda1997x_codec_remove,
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static int tda1997x_probe(struct i2c_client *client,
......@@ -2737,7 +2739,7 @@ static int tda1997x_probe(struct i2c_client *client,
else
formats = SNDRV_PCM_FMTBIT_S16_LE;
tda1997x_audio_dai.capture.formats = formats;
ret = snd_soc_register_codec(&state->client->dev,
ret = devm_snd_soc_register_component(&state->client->dev,
&tda1997x_codec_driver,
&tda1997x_audio_dai, 1);
if (ret) {
......@@ -2782,7 +2784,6 @@ static int tda1997x_remove(struct i2c_client *client)
struct tda1997x_platform_data *pdata = &state->pdata;
if (pdata->audout_format) {
snd_soc_unregister_codec(&client->dev);
mutex_destroy(&state->audio_lock);
}
......
......@@ -108,4 +108,13 @@ config QCOM_WCNSS_CTRL
Client driver for the WCNSS_CTRL SMD channel, used to download nv
firmware to a newly booted WCNSS chip.
config QCOM_APR
tristate "Qualcomm APR Bus (Asynchronous Packet Router)"
depends on ARCH_QCOM
depends on RPMSG
help
Enable APR IPC protocol support between
application processor and QDSP6. APR is
used by audio driver to configure QDSP6
ASM, ADM and AFE modules.
endmenu
......@@ -12,3 +12,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
obj-$(CONFIG_QCOM_SMP2P) += smp2p.o
obj-$(CONFIG_QCOM_SMSM) += smsm.o
obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
obj-$(CONFIG_QCOM_APR) += apr.o
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
// Copyright (c) 2018, Linaro Limited
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/spinlock.h>
#include <linux/idr.h>
#include <linux/slab.h>
#include <linux/of_device.h>
#include <linux/soc/qcom/apr.h>
#include <linux/rpmsg.h>
#include <linux/of.h>
struct apr {
struct rpmsg_endpoint *ch;
struct device *dev;
spinlock_t svcs_lock;
struct idr svcs_idr;
int dest_domain_id;
};
/**
* apr_send_pkt() - Send a apr message from apr device
*
* @adev: Pointer to previously registered apr device.
* @pkt: Pointer to apr packet to send
*
* Return: Will be an negative on packet size on success.
*/
int apr_send_pkt(struct apr_device *adev, struct apr_pkt *pkt)
{
struct apr *apr = dev_get_drvdata(adev->dev.parent);
struct apr_hdr *hdr;
unsigned long flags;
int ret;
spin_lock_irqsave(&adev->lock, flags);
hdr = &pkt->hdr;
hdr->src_domain = APR_DOMAIN_APPS;
hdr->src_svc = adev->svc_id;
hdr->dest_domain = adev->domain_id;
hdr->dest_svc = adev->svc_id;
ret = rpmsg_trysend(apr->ch, pkt, hdr->pkt_size);
spin_unlock_irqrestore(&adev->lock, flags);
return ret ? ret : hdr->pkt_size;
}
EXPORT_SYMBOL_GPL(apr_send_pkt);
static void apr_dev_release(struct device *dev)
{
struct apr_device *adev = to_apr_device(dev);
kfree(adev);
}
static int apr_callback(struct rpmsg_device *rpdev, void *buf,
int len, void *priv, u32 addr)
{
struct apr *apr = dev_get_drvdata(&rpdev->dev);
uint16_t hdr_size, msg_type, ver, svc_id;
struct apr_device *svc = NULL;
struct apr_driver *adrv = NULL;
struct apr_resp_pkt resp;
struct apr_hdr *hdr;
unsigned long flags;
if (len <= APR_HDR_SIZE) {
dev_err(apr->dev, "APR: Improper apr pkt received:%p %d\n",
buf, len);
return -EINVAL;
}
hdr = buf;
ver = APR_HDR_FIELD_VER(hdr->hdr_field);
if (ver > APR_PKT_VER + 1)
return -EINVAL;
hdr_size = APR_HDR_FIELD_SIZE_BYTES(hdr->hdr_field);
if (hdr_size < APR_HDR_SIZE) {
dev_err(apr->dev, "APR: Wrong hdr size:%d\n", hdr_size);
return -EINVAL;
}
if (hdr->pkt_size < APR_HDR_SIZE || hdr->pkt_size != len) {
dev_err(apr->dev, "APR: Wrong paket size\n");
return -EINVAL;
}
msg_type = APR_HDR_FIELD_MT(hdr->hdr_field);
if (msg_type >= APR_MSG_TYPE_MAX) {
dev_err(apr->dev, "APR: Wrong message type: %d\n", msg_type);
return -EINVAL;
}
if (hdr->src_domain >= APR_DOMAIN_MAX ||
hdr->dest_domain >= APR_DOMAIN_MAX ||
hdr->src_svc >= APR_SVC_MAX ||
hdr->dest_svc >= APR_SVC_MAX) {
dev_err(apr->dev, "APR: Wrong APR header\n");
return -EINVAL;
}
svc_id = hdr->dest_svc;
spin_lock_irqsave(&apr->svcs_lock, flags);
svc = idr_find(&apr->svcs_idr, svc_id);
if (svc && svc->dev.driver)
adrv = to_apr_driver(svc->dev.driver);
spin_unlock_irqrestore(&apr->svcs_lock, flags);
if (!adrv) {
dev_err(apr->dev, "APR: service is not registered\n");
return -EINVAL;
}
resp.hdr = *hdr;
resp.payload_size = hdr->pkt_size - hdr_size;
/*
* NOTE: hdr_size is not same as APR_HDR_SIZE as remote can include
* optional headers in to apr_hdr which should be ignored
*/
if (resp.payload_size > 0)
resp.payload = buf + hdr_size;
adrv->callback(svc, &resp);
return 0;
}
static int apr_device_match(struct device *dev, struct device_driver *drv)
{
struct apr_device *adev = to_apr_device(dev);
struct apr_driver *adrv = to_apr_driver(drv);
const struct apr_device_id *id = adrv->id_table;
/* Attempt an OF style match first */
if (of_driver_match_device(dev, drv))
return 1;
if (!id)
return 0;
while (id->domain_id != 0 || id->svc_id != 0) {
if (id->domain_id == adev->domain_id &&
id->svc_id == adev->svc_id)
return 1;
id++;
}
return 0;
}
static int apr_device_probe(struct device *dev)
{
struct apr_device *adev = to_apr_device(dev);
struct apr_driver *adrv = to_apr_driver(dev->driver);
return adrv->probe(adev);
}
static int apr_device_remove(struct device *dev)
{
struct apr_device *adev = to_apr_device(dev);
struct apr_driver *adrv;
struct apr *apr = dev_get_drvdata(adev->dev.parent);
if (dev->driver) {
adrv = to_apr_driver(dev->driver);
if (adrv->remove)
adrv->remove(adev);
spin_lock(&apr->svcs_lock);
idr_remove(&apr->svcs_idr, adev->svc_id);
spin_unlock(&apr->svcs_lock);
}
return 0;
}
static int apr_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct apr_device *adev = to_apr_device(dev);
int ret;
ret = of_device_uevent_modalias(dev, env);
if (ret != -ENODEV)
return ret;
return add_uevent_var(env, "MODALIAS=apr:%s", adev->name);
}
struct bus_type aprbus = {
.name = "aprbus",
.match = apr_device_match,
.probe = apr_device_probe,
.uevent = apr_uevent,
.remove = apr_device_remove,
};
EXPORT_SYMBOL_GPL(aprbus);
static int apr_add_device(struct device *dev, struct device_node *np,
const struct apr_device_id *id)
{
struct apr *apr = dev_get_drvdata(dev);
struct apr_device *adev = NULL;
int ret;
adev = kzalloc(sizeof(*adev), GFP_KERNEL);
if (!adev)
return -ENOMEM;
spin_lock_init(&adev->lock);
adev->svc_id = id->svc_id;
adev->domain_id = id->domain_id;
adev->version = id->svc_version;
if (np)
strncpy(adev->name, np->name, APR_NAME_SIZE);
else
strncpy(adev->name, id->name, APR_NAME_SIZE);
dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name,
id->domain_id, id->svc_id);
adev->dev.bus = &aprbus;
adev->dev.parent = dev;
adev->dev.of_node = np;
adev->dev.release = apr_dev_release;
adev->dev.driver = NULL;
spin_lock(&apr->svcs_lock);
idr_alloc(&apr->svcs_idr, adev, id->svc_id,
id->svc_id + 1, GFP_ATOMIC);
spin_unlock(&apr->svcs_lock);
dev_info(dev, "Adding APR dev: %s\n", dev_name(&adev->dev));
ret = device_register(&adev->dev);
if (ret) {
dev_err(dev, "device_register failed: %d\n", ret);
put_device(&adev->dev);
}
return ret;
}
static void of_register_apr_devices(struct device *dev)
{
struct apr *apr = dev_get_drvdata(dev);
struct device_node *node;
for_each_child_of_node(dev->of_node, node) {
struct apr_device_id id = { {0} };
if (of_property_read_u32(node, "reg", &id.svc_id))
continue;
id.domain_id = apr->dest_domain_id;
if (apr_add_device(dev, node, &id))
dev_err(dev, "Failed to add apr %d svc\n", id.svc_id);
}
}
static int apr_probe(struct rpmsg_device *rpdev)
{
struct device *dev = &rpdev->dev;
struct apr *apr;
int ret;
apr = devm_kzalloc(dev, sizeof(*apr), GFP_KERNEL);
if (!apr)
return -ENOMEM;
ret = of_property_read_u32(dev->of_node, "reg", &apr->dest_domain_id);
if (ret) {
dev_err(dev, "APR Domain ID not specified in DT\n");
return ret;
}
dev_set_drvdata(dev, apr);
apr->ch = rpdev->ept;
apr->dev = dev;
spin_lock_init(&apr->svcs_lock);
idr_init(&apr->svcs_idr);
of_register_apr_devices(dev);
return 0;
}
static int apr_remove_device(struct device *dev, void *null)
{
struct apr_device *adev = to_apr_device(dev);
device_unregister(&adev->dev);
return 0;
}
static void apr_remove(struct rpmsg_device *rpdev)
{
device_for_each_child(&rpdev->dev, NULL, apr_remove_device);
}
/*
* __apr_driver_register() - Client driver registration with aprbus
*
* @drv:Client driver to be associated with client-device.
* @owner: owning module/driver
*
* This API will register the client driver with the aprbus
* It is called from the driver's module-init function.
*/
int __apr_driver_register(struct apr_driver *drv, struct module *owner)
{
drv->driver.bus = &aprbus;
drv->driver.owner = owner;
return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(__apr_driver_register);
/*
* apr_driver_unregister() - Undo effect of apr_driver_register
*
* @drv: Client driver to be unregistered
*/
void apr_driver_unregister(struct apr_driver *drv)
{
driver_unregister(&drv->driver);
}
EXPORT_SYMBOL_GPL(apr_driver_unregister);
static const struct of_device_id apr_of_match[] = {
{ .compatible = "qcom,apr"},
{ .compatible = "qcom,apr-v2"},
{}
};
MODULE_DEVICE_TABLE(of, apr_of_match);
static struct rpmsg_driver apr_driver = {
.probe = apr_probe,
.remove = apr_remove,
.callback = apr_callback,
.drv = {
.name = "qcom,apr",
.of_match_table = apr_of_match,
},
};
static int __init apr_init(void)
{
int ret;
ret = bus_register(&aprbus);
if (!ret)
ret = register_rpmsg_driver(&apr_driver);
else
bus_unregister(&aprbus);
return ret;
}
static void __exit apr_exit(void)
{
bus_unregister(&aprbus);
unregister_rpmsg_driver(&apr_driver);
}
subsys_initcall(apr_init);
module_exit(apr_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Qualcomm APR Bus");
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __DT_BINDINGS_QCOM_APR_H
#define __DT_BINDINGS_QCOM_APR_H
/* Domain IDs */
#define APR_DOMAIN_SIM 0x1
#define APR_DOMAIN_PC 0x2
#define APR_DOMAIN_MODEM 0x3
#define APR_DOMAIN_ADSP 0x4
#define APR_DOMAIN_APPS 0x5
#define APR_DOMAIN_MAX 0x6
/* ADSP service IDs */
#define APR_SVC_ADSP_CORE 0x3
#define APR_SVC_AFE 0x4
#define APR_SVC_VSM 0x5
#define APR_SVC_VPM 0x6
#define APR_SVC_ASM 0x7
#define APR_SVC_ADM 0x8
#define APR_SVC_ADSP_MVM 0x09
#define APR_SVC_ADSP_CVS 0x0A
#define APR_SVC_ADSP_CVP 0x0B
#define APR_SVC_USM 0x0C
#define APR_SVC_LSM 0x0D
#define APR_SVC_VIDC 0x16
#define APR_SVC_MAX 0x17
#endif /* __DT_BINDINGS_QCOM_APR_H */
......@@ -25,6 +25,13 @@
#define MX51_AUDMUX_PORT6 5
#define MX51_AUDMUX_PORT7 6
/*
* TFCSEL/RFCSEL (i.MX27) or TFSEL/TCSEL/RFSEL/RCSEL (i.MX31/51/53/6Q)
* can be sourced from Rx/Tx.
*/
#define IMX_AUDMUX_RXFS 0x8
#define IMX_AUDMUX_RXCLK 0x8
/* Register definitions for the i.MX21/27 Digital Audio Multiplexer */
#define IMX_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff)
#define IMX_AUDMUX_V1_PCR_INMEN (1 << 8)
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __DT_BINDINGS_Q6_AFE_H__
#define __DT_BINDINGS_Q6_AFE_H__
/* Audio Front End (AFE) virtual ports IDs */
#define HDMI_RX 1
#define SLIMBUS_0_RX 2
#define SLIMBUS_0_TX 3
#define SLIMBUS_1_RX 4
#define SLIMBUS_1_TX 5
#define SLIMBUS_2_RX 6
#define SLIMBUS_2_TX 7
#define SLIMBUS_3_RX 8
#define SLIMBUS_3_TX 9
#define SLIMBUS_4_RX 10
#define SLIMBUS_4_TX 11
#define SLIMBUS_5_RX 12
#define SLIMBUS_5_TX 13
#define SLIMBUS_6_RX 14
#define SLIMBUS_6_TX 15
#define PRIMARY_MI2S_RX 16
#define PRIMARY_MI2S_TX 17
#define SECONDARY_MI2S_RX 18
#define SECONDARY_MI2S_TX 19
#define TERTIARY_MI2S_RX 20
#define TERTIARY_MI2S_TX 21
#define QUATERNARY_MI2S_RX 22
#define QUATERNARY_MI2S_TX 23
#define PRIMARY_TDM_RX_0 24
#define PRIMARY_TDM_TX_0 25
#define PRIMARY_TDM_RX_1 26
#define PRIMARY_TDM_TX_1 27
#define PRIMARY_TDM_RX_2 28
#define PRIMARY_TDM_TX_2 29
#define PRIMARY_TDM_RX_3 30
#define PRIMARY_TDM_TX_3 31
#define PRIMARY_TDM_RX_4 32
#define PRIMARY_TDM_TX_4 33
#define PRIMARY_TDM_RX_5 34
#define PRIMARY_TDM_TX_5 35
#define PRIMARY_TDM_RX_6 36
#define PRIMARY_TDM_TX_6 37
#define PRIMARY_TDM_RX_7 38
#define PRIMARY_TDM_TX_7 39
#define SECONDARY_TDM_RX_0 40
#define SECONDARY_TDM_TX_0 41
#define SECONDARY_TDM_RX_1 42
#define SECONDARY_TDM_TX_1 43
#define SECONDARY_TDM_RX_2 44
#define SECONDARY_TDM_TX_2 45
#define SECONDARY_TDM_RX_3 46
#define SECONDARY_TDM_TX_3 47
#define SECONDARY_TDM_RX_4 48
#define SECONDARY_TDM_TX_4 49
#define SECONDARY_TDM_RX_5 50
#define SECONDARY_TDM_TX_5 51
#define SECONDARY_TDM_RX_6 52
#define SECONDARY_TDM_TX_6 53
#define SECONDARY_TDM_RX_7 54
#define SECONDARY_TDM_TX_7 55
#define TERTIARY_TDM_RX_0 56
#define TERTIARY_TDM_TX_0 57
#define TERTIARY_TDM_RX_1 58
#define TERTIARY_TDM_TX_1 59
#define TERTIARY_TDM_RX_2 60
#define TERTIARY_TDM_TX_2 61
#define TERTIARY_TDM_RX_3 62
#define TERTIARY_TDM_TX_3 63
#define TERTIARY_TDM_RX_4 64
#define TERTIARY_TDM_TX_4 65
#define TERTIARY_TDM_RX_5 66
#define TERTIARY_TDM_TX_5 67
#define TERTIARY_TDM_RX_6 68
#define TERTIARY_TDM_TX_6 69
#define TERTIARY_TDM_RX_7 70
#define TERTIARY_TDM_TX_7 71
#define QUATERNARY_TDM_RX_0 72
#define QUATERNARY_TDM_TX_0 73
#define QUATERNARY_TDM_RX_1 74
#define QUATERNARY_TDM_TX_1 75
#define QUATERNARY_TDM_RX_2 76
#define QUATERNARY_TDM_TX_2 77
#define QUATERNARY_TDM_RX_3 78
#define QUATERNARY_TDM_TX_3 79
#define QUATERNARY_TDM_RX_4 80
#define QUATERNARY_TDM_TX_4 81
#define QUATERNARY_TDM_RX_5 82
#define QUATERNARY_TDM_TX_5 83
#define QUATERNARY_TDM_RX_6 84
#define QUATERNARY_TDM_TX_6 85
#define QUATERNARY_TDM_RX_7 86
#define QUATERNARY_TDM_TX_7 87
#define QUINARY_TDM_RX_0 88
#define QUINARY_TDM_TX_0 89
#define QUINARY_TDM_RX_1 90
#define QUINARY_TDM_TX_1 91
#define QUINARY_TDM_RX_2 92
#define QUINARY_TDM_TX_2 93
#define QUINARY_TDM_RX_3 94
#define QUINARY_TDM_TX_3 95
#define QUINARY_TDM_RX_4 96
#define QUINARY_TDM_TX_4 97
#define QUINARY_TDM_RX_5 98
#define QUINARY_TDM_TX_5 99
#define QUINARY_TDM_RX_6 100
#define QUINARY_TDM_TX_6 101
#define QUINARY_TDM_RX_7 102
#define QUINARY_TDM_TX_7 103
#endif /* __DT_BINDINGS_Q6_AFE_H__ */
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __DT_BINDINGS_Q6_ASM_H__
#define __DT_BINDINGS_Q6_ASM_H__
#define MSM_FRONTEND_DAI_MULTIMEDIA1 0
#define MSM_FRONTEND_DAI_MULTIMEDIA2 1
#define MSM_FRONTEND_DAI_MULTIMEDIA3 2
#define MSM_FRONTEND_DAI_MULTIMEDIA4 3
#define MSM_FRONTEND_DAI_MULTIMEDIA5 4
#define MSM_FRONTEND_DAI_MULTIMEDIA6 5
#define MSM_FRONTEND_DAI_MULTIMEDIA7 6
#define MSM_FRONTEND_DAI_MULTIMEDIA8 7
#define MSM_FRONTEND_DAI_MULTIMEDIA9 8
#define MSM_FRONTEND_DAI_MULTIMEDIA10 9
#define MSM_FRONTEND_DAI_MULTIMEDIA11 10
#define MSM_FRONTEND_DAI_MULTIMEDIA12 11
#define MSM_FRONTEND_DAI_MULTIMEDIA13 12
#define MSM_FRONTEND_DAI_MULTIMEDIA14 13
#define MSM_FRONTEND_DAI_MULTIMEDIA15 14
#define MSM_FRONTEND_DAI_MULTIMEDIA16 15
#endif /* __DT_BINDINGS_Q6_ASM_H__ */
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __DT_RT5640_H
#define __DT_RT5640_H
#define RT5640_DMIC1_DATA_PIN_NONE 0
#define RT5640_DMIC1_DATA_PIN_IN1P 1
#define RT5640_DMIC1_DATA_PIN_GPIO3 2
#define RT5640_DMIC2_DATA_PIN_NONE 0
#define RT5640_DMIC2_DATA_PIN_IN1N 1
#define RT5640_DMIC2_DATA_PIN_GPIO4 2
#define RT5640_JD_SRC_GPIO1 1
#define RT5640_JD_SRC_JD1_IN4P 2
#define RT5640_JD_SRC_JD2_IN4N 3
#define RT5640_JD_SRC_GPIO2 4
#define RT5640_JD_SRC_GPIO3 5
#define RT5640_JD_SRC_GPIO4 6
#define RT5640_OVCD_SF_0P5 0
#define RT5640_OVCD_SF_0P75 1
#define RT5640_OVCD_SF_1P0 2
#define RT5640_OVCD_SF_1P5 3
#endif /* __DT_RT5640_H */
......@@ -617,11 +617,8 @@ struct wm8350_audio_platform_data {
u32 codec_current_charge:2; /* codec current @ vmid charge */
};
struct snd_soc_codec;
struct wm8350_codec {
struct platform_device *pdev;
struct snd_soc_codec *codec;
struct wm8350_audio_platform_data *platform_data;
};
......
......@@ -471,6 +471,17 @@ struct slim_device_id {
kernel_ulong_t driver_data;
};
#define APR_NAME_SIZE 32
#define APR_MODULE_PREFIX "apr:"
struct apr_device_id {
char name[APR_NAME_SIZE];
__u32 domain_id;
__u32 svc_id;
__u32 svc_version;
kernel_ulong_t driver_data; /* Data private to the driver */
};
#define SPMI_NAME_SIZE 32
#define SPMI_MODULE_PREFIX "spmi:"
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __QCOM_APR_H_
#define __QCOM_APR_H_
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <dt-bindings/soc/qcom,apr.h>
extern struct bus_type aprbus;
#define APR_HDR_LEN(hdr_len) ((hdr_len)/4)
/*
* HEADER field
* version:0:3
* header_size : 4:7
* message_type : 8:9
* reserved: 10:15
*/
#define APR_HDR_FIELD(msg_type, hdr_len, ver)\
(((msg_type & 0x3) << 8) | ((hdr_len & 0xF) << 4) | (ver & 0xF))
#define APR_HDR_SIZE sizeof(struct apr_hdr)
#define APR_SEQ_CMD_HDR_FIELD APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
APR_HDR_LEN(APR_HDR_SIZE), \
APR_PKT_VER)
/* Version */
#define APR_PKT_VER 0x0
/* Command and Response Types */
#define APR_MSG_TYPE_EVENT 0x0
#define APR_MSG_TYPE_CMD_RSP 0x1
#define APR_MSG_TYPE_SEQ_CMD 0x2
#define APR_MSG_TYPE_NSEQ_CMD 0x3
#define APR_MSG_TYPE_MAX 0x04
/* APR Basic Response Message */
#define APR_BASIC_RSP_RESULT 0x000110E8
#define APR_RSP_ACCEPTED 0x000100BE
struct aprv2_ibasic_rsp_result_t {
uint32_t opcode;
uint32_t status;
};
/* hdr field Ver [0:3], Size [4:7], Message type [8:10] */
#define APR_HDR_FIELD_VER(h) (h & 0x000F)
#define APR_HDR_FIELD_SIZE(h) ((h & 0x00F0) >> 4)
#define APR_HDR_FIELD_SIZE_BYTES(h) (((h & 0x00F0) >> 4) * 4)
#define APR_HDR_FIELD_MT(h) ((h & 0x0300) >> 8)
struct apr_hdr {
uint16_t hdr_field;
uint16_t pkt_size;
uint8_t src_svc;
uint8_t src_domain;
uint16_t src_port;
uint8_t dest_svc;
uint8_t dest_domain;
uint16_t dest_port;
uint32_t token;
uint32_t opcode;
} __packed;
struct apr_pkt {
struct apr_hdr hdr;
uint8_t payload[];
};
struct apr_resp_pkt {
struct apr_hdr hdr;
void *payload;
int payload_size;
};
/* Bits 0 to 15 -- Minor version, Bits 16 to 31 -- Major version */
#define APR_SVC_MAJOR_VERSION(v) ((v >> 16) & 0xFF)
#define APR_SVC_MINOR_VERSION(v) (v & 0xFF)
struct apr_device {
struct device dev;
uint16_t svc_id;
uint16_t domain_id;
uint32_t version;
char name[APR_NAME_SIZE];
spinlock_t lock;
struct list_head node;
};
#define to_apr_device(d) container_of(d, struct apr_device, dev)
struct apr_driver {
int (*probe)(struct apr_device *sl);
int (*remove)(struct apr_device *sl);
int (*callback)(struct apr_device *a,
struct apr_resp_pkt *d);
struct device_driver driver;
const struct apr_device_id *id_table;
};
#define to_apr_driver(d) container_of(d, struct apr_driver, driver)
/*
* use a macro to avoid include chaining to get THIS_MODULE
*/
#define apr_driver_register(drv) __apr_driver_register(drv, THIS_MODULE)
int __apr_driver_register(struct apr_driver *drv, struct module *owner);
void apr_driver_unregister(struct apr_driver *drv);
/**
* module_apr_driver() - Helper macro for registering a aprbus driver
* @__aprbus_driver: aprbus_driver struct
*
* Helper macro for aprbus drivers which do not do anything special in
* module init/exit. This eliminates a lot of boilerplate. Each module
* may only use this macro once, and calling it replaces module_init()
* and module_exit()
*/
#define module_apr_driver(__apr_driver) \
module_driver(__apr_driver, apr_driver_register, \
apr_driver_unregister)
int apr_send_pkt(struct apr_device *adev, struct apr_pkt *pkt);
#endif /* __QCOM_APR_H_ */
......@@ -189,6 +189,13 @@ struct uac2_iso_endpoint_descriptor {
#define UAC2_CONTROL_DATA_OVERRUN (3 << 2)
#define UAC2_CONTROL_DATA_UNDERRUN (3 << 4)
/* 5.2.5.4.2 Connector Control Parameter Block */
struct uac2_connectors_ctl_blk {
__u8 bNrChannels;
__le32 bmChannelConfig;
__u8 iChannelNames;
} __attribute__((packed));
/* 6.1 Interrupt Data Message */
#define UAC2_INTERRUPT_DATA_MSG_VENDOR (1 << 0)
......
......@@ -221,6 +221,12 @@ struct uac3_iso_endpoint_descriptor {
__le16 wLockDelay;
} __attribute__((packed));
/* 5.2.1.6.1 INSERTION CONTROL PARAMETER BLOCK */
struct uac3_insertion_ctl_blk {
__u8 bSize;
__u8 bmConInserted;
} __attribute__ ((packed));
/* 6.1 INTERRUPT DATA MESSAGE */
struct uac3_interrupt_data_msg {
__u8 bInfo;
......@@ -392,4 +398,38 @@ struct uac3_interrupt_data_msg {
#define UAC3_AC_ACTIVE_INTERFACE_CONTROL 0x01
#define UAC3_AC_POWER_DOMAIN_CONTROL 0x02
/* A.23.5 TERMINAL CONTROL SELECTORS */
#define UAC3_TE_UNDEFINED 0x00
#define UAC3_TE_INSERTION 0x01
#define UAC3_TE_OVERLOAD 0x02
#define UAC3_TE_UNDERFLOW 0x03
#define UAC3_TE_OVERFLOW 0x04
#define UAC3_TE_LATENCY 0x05
/* BADD predefined Unit/Terminal values */
#define UAC3_BADD_IT_ID1 1 /* Input Terminal ID1: bTerminalID = 1 */
#define UAC3_BADD_FU_ID2 2 /* Feature Unit ID2: bUnitID = 2 */
#define UAC3_BADD_OT_ID3 3 /* Output Terminal ID3: bTerminalID = 3 */
#define UAC3_BADD_IT_ID4 4 /* Input Terminal ID4: bTerminalID = 4 */
#define UAC3_BADD_FU_ID5 5 /* Feature Unit ID5: bUnitID = 5 */
#define UAC3_BADD_OT_ID6 6 /* Output Terminal ID6: bTerminalID = 6 */
#define UAC3_BADD_FU_ID7 7 /* Feature Unit ID7: bUnitID = 7 */
#define UAC3_BADD_MU_ID8 8 /* Mixer Unit ID8: bUnitID = 8 */
#define UAC3_BADD_CS_ID9 9 /* Clock Source Entity ID9: bClockID = 9 */
#define UAC3_BADD_PD_ID10 10 /* Power Domain ID10: bPowerDomainID = 10 */
#define UAC3_BADD_PD_ID11 11 /* Power Domain ID11: bPowerDomainID = 11 */
/* BADD wMaxPacketSize of AS endpoints */
#define UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16 0x0060
#define UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16 0x0062
#define UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24 0x0090
#define UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24 0x0093
#define UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16 0x00C0
#define UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16 0x00C4
#define UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24 0x0120
#define UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24 0x0126
/* BADD sample rate is always fixed to 48kHz */
#define UAC3_BADD_SAMPLING_RATE 48000
#endif /* __LINUX_USB_AUDIO_V3_H */
......@@ -51,7 +51,6 @@ struct completion;
*/
enum snd_device_type {
SNDRV_DEV_LOWLEVEL,
SNDRV_DEV_CONTROL,
SNDRV_DEV_INFO,
SNDRV_DEV_BUS,
SNDRV_DEV_CODEC,
......@@ -62,6 +61,7 @@ enum snd_device_type {
SNDRV_DEV_SEQUENCER,
SNDRV_DEV_HWDEP,
SNDRV_DEV_JACK,
SNDRV_DEV_CONTROL, /* NOTE: this must be the last one */
};
enum snd_device_state {
......
......@@ -1610,7 +1610,7 @@ struct snd_emu10k1_fx8010_pcm {
struct snd_pcm_indirect pcm_rec;
unsigned int tram_pos;
unsigned int tram_shift;
struct snd_emu10k1_fx8010_irq *irq;
struct snd_emu10k1_fx8010_irq irq;
};
struct snd_emu10k1_fx8010 {
......@@ -1902,7 +1902,7 @@ int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu,
snd_fx8010_irq_handler_t *handler,
unsigned char gpr_running,
void *private_data,
struct snd_emu10k1_fx8010_irq **r_irq);
struct snd_emu10k1_fx8010_irq *irq);
int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu,
struct snd_emu10k1_fx8010_irq *irq);
......
......@@ -571,4 +571,9 @@ static inline unsigned int snd_array_index(struct snd_array *array, void *ptr)
return (unsigned long)(ptr - array->list) / array->elem_size;
}
/* a helper macro to iterate for each snd_array element */
#define snd_array_for_each(array, idx, ptr) \
for ((idx) = 0, (ptr) = (array)->list; (idx) < (array)->used; \
(ptr) = snd_array_elem(array, ++(idx)))
#endif /* __SOUND_HDAUDIO_H */
......@@ -34,11 +34,9 @@ struct snd_dma_device {
struct device *dev; /* generic device */
};
#ifndef snd_dma_pci_data
#define snd_dma_pci_data(pci) (&(pci)->dev)
#define snd_dma_isa_data() NULL
#define snd_dma_continuous_data(x) ((struct device *)(__force unsigned long)(x))
#endif
/*
......
/*
* omap-pcm.h - OMAP PCM driver
*
* Copyright (C) 2014 Texas Instruments, Inc.
*
* Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#ifndef __OMAP_PCM_H__
#define __OMAP_PCM_H__
#if IS_ENABLED(CONFIG_SND_OMAP_SOC)
int omap_pcm_platform_register(struct device *dev);
#else
static inline int omap_pcm_platform_register(struct device *dev)
{
return 0;
}
#endif /* CONFIG_SND_OMAP_SOC */
#endif /* __OMAP_PCM_H__ */
/*
* linux/sound/rt5640.h -- Platform data for RT5640
* linux/sound/rt5668.h -- Platform data for RT5668
*
* Copyright 2011 Realtek Microelectronics
* 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_RT5640_H
#define __LINUX_SND_RT5640_H
#ifndef __LINUX_SND_RT5668_H
#define __LINUX_SND_RT5668_H
struct rt5640_platform_data {
/* IN1 & IN2 & IN3 can optionally be differential */
bool in1_diff;
bool in2_diff;
bool in3_diff;
enum rt5668_dmic1_data_pin {
RT5668_DMIC1_NULL,
RT5668_DMIC1_DATA_GPIO2,
RT5668_DMIC1_DATA_GPIO5,
};
enum rt5668_dmic1_clk_pin {
RT5668_DMIC1_CLK_GPIO1,
RT5668_DMIC1_CLK_GPIO3,
};
bool dmic_en;
bool dmic1_data_pin; /* 0 = IN1P; 1 = GPIO3 */
bool dmic2_data_pin; /* 0 = IN1N; 1 = GPIO4 */
enum rt5668_jd_src {
RT5668_JD_NULL,
RT5668_JD1,
};
struct rt5668_platform_data {
int ldo1_en; /* GPIO for LDO1_EN */
enum rt5668_dmic1_data_pin dmic1_data_pin;
enum rt5668_dmic1_clk_pin dmic1_clk_pin;
enum rt5668_jd_src jd_src;
};
#endif
......@@ -296,8 +296,8 @@ struct snd_soc_dai {
struct snd_soc_dai_driver *driver;
/* DAI runtime info */
unsigned int capture_active:1; /* stream is in use */
unsigned int playback_active:1; /* stream is in use */
unsigned int capture_active; /* stream usage count */
unsigned int playback_active; /* stream usage count */
unsigned int probed:1;
unsigned int active;
......@@ -315,7 +315,6 @@ struct snd_soc_dai {
unsigned int sample_bits;
/* parent platform/codec */
struct snd_soc_codec *codec;
struct snd_soc_component *component;
/* CODEC TDM slot masks and params (for fixup) */
......
此差异已折叠。
......@@ -12,7 +12,6 @@
#define DAPM_ARROW(dir) (((dir) == SND_SOC_DAPM_DIR_OUT) ? "->" : "<-")
struct snd_soc_jack;
struct snd_soc_codec;
struct snd_soc_card;
struct snd_soc_dapm_widget;
struct snd_soc_dapm_path;
......
......@@ -285,9 +285,22 @@ static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor
static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc,
int protocol)
{
return (protocol == UAC_VERSION_1) ?
&desc->baSourceID[desc->bNrInPins + 4] :
&desc->baSourceID[desc->bNrInPins + 6];
switch (protocol) {
case UAC_VERSION_1:
return &desc->baSourceID[desc->bNrInPins + 4];
case UAC_VERSION_2:
return &desc->baSourceID[desc->bNrInPins + 6];
case UAC_VERSION_3:
return &desc->baSourceID[desc->bNrInPins + 2];
default:
return NULL;
}
}
static inline __u16 uac3_mixer_unit_wClusterDescrID(struct uac_mixer_unit_descriptor *desc)
{
return (desc->baSourceID[desc->bNrInPins + 1] << 8) |
desc->baSourceID[desc->bNrInPins];
}
static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc)
......
......@@ -139,6 +139,15 @@
#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS (1 << 1)
#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2)
/* DAI clock gating */
#define SND_SOC_TPLG_DAI_CLK_GATE_UNDEFINED 0
#define SND_SOC_TPLG_DAI_CLK_GATE_GATED 1
#define SND_SOC_TPLG_DAI_CLK_GATE_CONT 2
/* DAI mclk_direction */
#define SND_SOC_TPLG_MCLK_CO 0 /* for codec, mclk is output */
#define SND_SOC_TPLG_MCLK_CI 1 /* for codec, mclk is input */
/* DAI physical PCM data formats.
* Add new formats to the end of the list.
*/
......@@ -160,6 +169,18 @@
#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2)
#define SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP (1 << 3)
/* DAI topology BCLK parameter
* For the backwards capability, by default codec is bclk master
*/
#define SND_SOC_TPLG_BCLK_CM 0 /* codec is bclk master */
#define SND_SOC_TPLG_BCLK_CS 1 /* codec is bclk slave */
/* DAI topology FSYNC parameter
* For the backwards capability, by default codec is fsync master
*/
#define SND_SOC_TPLG_FSYNC_CM 0 /* codec is fsync master */
#define SND_SOC_TPLG_FSYNC_CS 1 /* codec is fsync slave */
/*
* Block Header.
* This header precedes all object and object arrays below.
......@@ -312,12 +333,12 @@ struct snd_soc_tplg_hw_config {
__le32 size; /* in bytes of this structure */
__le32 id; /* unique ID - - used to match */
__le32 fmt; /* SND_SOC_DAI_FORMAT_ format value */
__u8 clock_gated; /* 1 if clock can be gated to save power */
__u8 clock_gated; /* SND_SOC_TPLG_DAI_CLK_GATE_ value */
__u8 invert_bclk; /* 1 for inverted BCLK, 0 for normal */
__u8 invert_fsync; /* 1 for inverted frame clock, 0 for normal */
__u8 bclk_master; /* 1 for master of BCLK, 0 for slave */
__u8 fsync_master; /* 1 for master of FSYNC, 0 for slave */
__u8 mclk_direction; /* 0 for input, 1 for output */
__u8 bclk_master; /* SND_SOC_TPLG_BCLK_ value */
__u8 fsync_master; /* SND_SOC_TPLG_FSYNC_ value */
__u8 mclk_direction; /* SND_SOC_TPLG_MCLK_ value */
__le16 reserved; /* for 32bit alignment */
__le32 mclk_rate; /* MCLK or SYSCLK freqency in Hz */
__le32 bclk_rate; /* BCLK freqency in Hz */
......@@ -552,4 +573,61 @@ struct snd_soc_tplg_dai {
__le32 flags; /* SND_SOC_TPLG_DAI_FLGBIT_* */
struct snd_soc_tplg_private priv;
} __attribute__((packed));
/*
* Old version of ABI structs, supported for backward compatibility.
*/
/* Manifest v4 */
struct snd_soc_tplg_manifest_v4 {
__le32 size; /* in bytes of this structure */
__le32 control_elems; /* number of control elements */
__le32 widget_elems; /* number of widget elements */
__le32 graph_elems; /* number of graph elements */
__le32 pcm_elems; /* number of PCM elements */
__le32 dai_link_elems; /* number of DAI link elements */
struct snd_soc_tplg_private priv;
} __packed;
/* Stream Capabilities v4 */
struct snd_soc_tplg_stream_caps_v4 {
__le32 size; /* in bytes of this structure */
char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
__le64 formats; /* supported formats SNDRV_PCM_FMTBIT_* */
__le32 rates; /* supported rates SNDRV_PCM_RATE_* */
__le32 rate_min; /* min rate */
__le32 rate_max; /* max rate */
__le32 channels_min; /* min channels */
__le32 channels_max; /* max channels */
__le32 periods_min; /* min number of periods */
__le32 periods_max; /* max number of periods */
__le32 period_size_min; /* min period size bytes */
__le32 period_size_max; /* max period size bytes */
__le32 buffer_size_min; /* min buffer size bytes */
__le32 buffer_size_max; /* max buffer size bytes */
} __packed;
/* PCM v4 */
struct snd_soc_tplg_pcm_v4 {
__le32 size; /* in bytes of this structure */
char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
__le32 pcm_id; /* unique ID - used to match with DAI link */
__le32 dai_id; /* unique ID - used to match */
__le32 playback; /* supports playback mode */
__le32 capture; /* supports capture mode */
__le32 compress; /* 1 = compressed; 0 = PCM */
struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* for DAI link */
__le32 num_streams; /* number of streams */
struct snd_soc_tplg_stream_caps_v4 caps[2]; /* playback and capture for DAI */
} __packed;
/* Physical link config v4 */
struct snd_soc_tplg_link_config_v4 {
__le32 size; /* in bytes of this structure */
__le32 id; /* unique ID - used to match */
struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */
__le32 num_streams; /* number of streams */
} __packed;
#endif
/* SPDX-License-Identifier: GPL-2.0 */
/*
* skl-tplg-interface.h - Intel DSP FW private data interface
*
* Copyright (C) 2015 Intel Corp
* Author: Jeeja KP <jeeja.kp@intel.com>
* Nilofer, Samreen <samreen.nilofer@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 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 __HDA_TPLG_INTERFACE_H__
......@@ -169,4 +160,78 @@ enum skl_tuple_type {
SKL_TYPE_DATA
};
/* v4 configuration data */
struct skl_dfw_v4_module_pin {
u16 module_id;
u16 instance_id;
} __packed;
struct skl_dfw_v4_module_fmt {
u32 channels;
u32 freq;
u32 bit_depth;
u32 valid_bit_depth;
u32 ch_cfg;
u32 interleaving_style;
u32 sample_type;
u32 ch_map;
} __packed;
struct skl_dfw_v4_module_caps {
u32 set_params:2;
u32 rsvd:30;
u32 param_id;
u32 caps_size;
u32 caps[HDA_SST_CFG_MAX];
} __packed;
struct skl_dfw_v4_pipe {
u8 pipe_id;
u8 pipe_priority;
u16 conn_type:4;
u16 rsvd:4;
u16 memory_pages:8;
} __packed;
struct skl_dfw_v4_module {
char uuid[SKL_UUID_STR_SZ];
u16 module_id;
u16 instance_id;
u32 max_mcps;
u32 mem_pages;
u32 obs;
u32 ibs;
u32 vbus_id;
u32 max_in_queue:8;
u32 max_out_queue:8;
u32 time_slot:8;
u32 core_id:4;
u32 rsvd1:4;
u32 module_type:8;
u32 conn_type:4;
u32 dev_type:4;
u32 hw_conn_type:4;
u32 rsvd2:12;
u32 params_fixup:8;
u32 converter:8;
u32 input_pin_type:1;
u32 output_pin_type:1;
u32 is_dynamic_in_pin:1;
u32 is_dynamic_out_pin:1;
u32 is_loadable:1;
u32 rsvd3:11;
struct skl_dfw_v4_pipe pipe;
struct skl_dfw_v4_module_fmt in_fmt[MAX_IN_QUEUE];
struct skl_dfw_v4_module_fmt out_fmt[MAX_OUT_QUEUE];
struct skl_dfw_v4_module_pin in_pin[MAX_IN_QUEUE];
struct skl_dfw_v4_module_pin out_pin[MAX_OUT_QUEUE];
struct skl_dfw_v4_module_caps caps;
} __packed;
#endif
......@@ -42,6 +42,10 @@
#define SNDRV_CTL_TLVD_LENGTH(...) \
((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ }))
/* Accessor offsets for TLV data items */
#define SNDRV_CTL_TLVO_TYPE 0
#define SNDRV_CTL_TLVO_LEN 1
#define SNDRV_CTL_TLVD_CONTAINER_ITEM(...) \
SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__)
#define SNDRV_CTL_TLVD_DECLARE_CONTAINER(name, ...) \
......@@ -61,6 +65,10 @@
SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \
}
/* Accessor offsets for min, mute and step items in dB scale type TLV */
#define SNDRV_CTL_TLVO_DB_SCALE_MIN 2
#define SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP 3
/* dB scale specified with min/max values instead of step */
#define SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \
SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB))
......@@ -75,6 +83,10 @@
SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \
}
/* Accessor offsets for min, max items in db-minmax types of TLV. */
#define SNDRV_CTL_TLVO_DB_MINMAX_MIN 2
#define SNDRV_CTL_TLVO_DB_MINMAX_MAX 3
/* linear volume between min_dB and max_dB (.01dB unit) */
#define SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \
SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB))
......@@ -83,6 +95,10 @@
SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \
}
/* Accessor offsets for min, max items in db-linear type of TLV. */
#define SNDRV_CTL_TLVO_DB_LINEAR_MIN 2
#define SNDRV_CTL_TLVO_DB_LINEAR_MAX 3
/* dB range container:
* Items in dB range container must be ordered by their values and by their
* dB values. This implies that larger values must correspond with larger
......
......@@ -96,6 +96,8 @@ source "sound/x86/Kconfig"
source "sound/synth/Kconfig"
source "sound/xen/Kconfig"
endif # SND
endif # !UML
......
......@@ -5,7 +5,7 @@
obj-$(CONFIG_SOUND) += soundcore.o
obj-$(CONFIG_DMASOUND) += oss/dmasound/
obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ hda/ x86/
firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ hda/ x86/ xen/
obj-$(CONFIG_SND_AOA) += aoa/
# This one must be compilable even if sound is configured out
......
......@@ -1001,7 +1001,7 @@ static int snd_compress_proc_init(struct snd_compr *compr)
compr->card->proc_root);
if (!entry)
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
entry->mode = S_IFDIR | 0555;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM;
......
......@@ -240,6 +240,15 @@ void snd_device_free_all(struct snd_card *card)
if (snd_BUG_ON(!card))
return;
list_for_each_entry_safe_reverse(dev, next, &card->devices, list) {
/* exception: free ctl and lowlevel stuff later */
if (dev->type == SNDRV_DEV_CONTROL ||
dev->type == SNDRV_DEV_LOWLEVEL)
continue;
__snd_device_free(dev);
}
/* free all */
list_for_each_entry_safe_reverse(dev, next, &card->devices, list)
__snd_device_free(dev);
}
......@@ -454,7 +454,7 @@ static struct snd_info_entry *create_subdir(struct module *mod,
entry = snd_info_create_module_entry(mod, name, NULL);
if (!entry)
return NULL;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
entry->mode = S_IFDIR | 0555;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return NULL;
......@@ -470,7 +470,7 @@ int __init snd_info_init(void)
snd_proc_root = snd_info_create_entry("asound", NULL);
if (!snd_proc_root)
return -ENOMEM;
snd_proc_root->mode = S_IFDIR | S_IRUGO | S_IXUGO;
snd_proc_root->mode = S_IFDIR | 0555;
snd_proc_root->p = proc_mkdir("asound", NULL);
if (!snd_proc_root->p)
goto error;
......@@ -716,7 +716,7 @@ snd_info_create_entry(const char *name, struct snd_info_entry *parent)
kfree(entry);
return NULL;
}
entry->mode = S_IFREG | S_IRUGO;
entry->mode = S_IFREG | 0444;
entry->content = SNDRV_INFO_CONTENT_TEXT;
mutex_init(&entry->access);
INIT_LIST_HEAD(&entry->children);
......
......@@ -703,7 +703,7 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
return count;
}
static DEVICE_ATTR(id, S_IRUGO | S_IWUSR, card_id_show_attr, card_id_store_attr);
static DEVICE_ATTR(id, 0644, card_id_show_attr, card_id_store_attr);
static ssize_t
card_number_show_attr(struct device *dev,
......@@ -713,7 +713,7 @@ card_number_show_attr(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "%i\n", card->number);
}
static DEVICE_ATTR(number, S_IRUGO, card_number_show_attr, NULL);
static DEVICE_ATTR(number, 0444, card_number_show_attr, NULL);
static struct attribute *card_dev_attrs[] = {
&dev_attr_id.attr,
......
......@@ -1247,7 +1247,7 @@ static void snd_mixer_oss_proc_init(struct snd_mixer_oss *mixer)
if (! entry)
return;
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
entry->mode = S_IFREG | 0644;
entry->c.text.read = snd_mixer_oss_proc_read;
entry->c.text.write = snd_mixer_oss_proc_write;
entry->private_data = mixer;
......
......@@ -3045,7 +3045,7 @@ static void snd_pcm_oss_proc_init(struct snd_pcm *pcm)
continue;
if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) {
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
entry->mode = S_IFREG | 0644;
entry->c.text.read = snd_pcm_oss_proc_read;
entry->c.text.write = snd_pcm_oss_proc_write;
entry->private_data = pstr;
......
......@@ -530,7 +530,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
pcm->card->proc_root);
if (!entry)
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
entry->mode = S_IFDIR | 0555;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM;
......@@ -552,7 +552,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
if (entry) {
entry->c.text.read = snd_pcm_xrun_debug_read;
entry->c.text.write = snd_pcm_xrun_debug_write;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
entry->private_data = pstr;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
......@@ -590,7 +590,7 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
substream->pstr->proc_root);
if (!entry)
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
entry->mode = S_IFDIR | 0555;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM;
......@@ -647,7 +647,7 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
entry->private_data = substream;
entry->c.text.read = NULL;
entry->c.text.write = snd_pcm_xrun_injection_write;
entry->mode = S_IFREG | S_IWUSR;
entry->mode = S_IFREG | 0200;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;
......@@ -1087,7 +1087,7 @@ static ssize_t show_pcm_class(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%s\n", str);
}
static DEVICE_ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL);
static DEVICE_ATTR(pcm_class, 0444, show_pcm_class, NULL);
static struct attribute *pcm_dev_attrs[] = {
&dev_attr_pcm_class.attr,
NULL
......
......@@ -45,10 +45,7 @@ static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream,
if (get_user(frames, src))
return -EFAULT;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
err = snd_pcm_playback_rewind(substream, frames);
else
err = snd_pcm_capture_rewind(substream, frames);
err = snd_pcm_rewind(substream, frames);
if (put_user(err, src))
return -EFAULT;
return err < 0 ? err : 0;
......@@ -62,10 +59,7 @@ static int snd_pcm_ioctl_forward_compat(struct snd_pcm_substream *substream,
if (get_user(frames, src))
return -EFAULT;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
err = snd_pcm_playback_forward(substream, frames);
else
err = snd_pcm_capture_forward(substream, frames);
err = snd_pcm_forward(substream, frames);
if (put_user(err, src))
return -EFAULT;
return err < 0 ? err : 0;
......
......@@ -191,10 +191,7 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
{
snd_pcm_uframes_t avail;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
avail = snd_pcm_playback_avail(runtime);
else
avail = snd_pcm_capture_avail(runtime);
avail = snd_pcm_avail(substream);
if (avail > runtime->avail_max)
runtime->avail_max = avail;
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
......@@ -1856,10 +1853,7 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
* This check must happen after been added to the waitqueue
* and having current state be INTERRUPTIBLE.
*/
if (is_playback)
avail = snd_pcm_playback_avail(runtime);
else
avail = snd_pcm_capture_avail(runtime);
avail = snd_pcm_avail(substream);
if (avail >= runtime->twake)
break;
snd_pcm_stream_unlock_irq(substream);
......@@ -2175,10 +2169,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
runtime->twake = runtime->control->avail_min ? : 1;
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
if (is_playback)
avail = snd_pcm_playback_avail(runtime);
else
avail = snd_pcm_capture_avail(runtime);
avail = snd_pcm_avail(substream);
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
snd_pcm_uframes_t cont;
......
......@@ -36,6 +36,24 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
void snd_pcm_playback_silence(struct snd_pcm_substream *substream,
snd_pcm_uframes_t new_hw_ptr);
static inline snd_pcm_uframes_t
snd_pcm_avail(struct snd_pcm_substream *substream)
{
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
return snd_pcm_playback_avail(substream->runtime);
else
return snd_pcm_capture_avail(substream->runtime);
}
static inline snd_pcm_uframes_t
snd_pcm_hw_avail(struct snd_pcm_substream *substream)
{
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
return snd_pcm_playback_hw_avail(substream->runtime);
else
return snd_pcm_capture_hw_avail(substream->runtime);
}
#ifdef CONFIG_SND_PCM_TIMER
void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream);
void snd_pcm_timer_init(struct snd_pcm_substream *substream);
......
......@@ -201,7 +201,7 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream)
if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) {
entry->c.text.read = snd_pcm_lib_preallocate_proc_read;
entry->c.text.write = snd_pcm_lib_preallocate_proc_write;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
entry->private_data = substream;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
......
......@@ -99,6 +99,57 @@ static inline void down_write_nonblock(struct rw_semaphore *lock)
cond_resched();
}
#define PCM_LOCK_DEFAULT 0
#define PCM_LOCK_IRQ 1
#define PCM_LOCK_IRQSAVE 2
static unsigned long __snd_pcm_stream_lock_mode(struct snd_pcm_substream *substream,
unsigned int mode)
{
unsigned long flags = 0;
if (substream->pcm->nonatomic) {
down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);
mutex_lock(&substream->self_group.mutex);
} else {
switch (mode) {
case PCM_LOCK_DEFAULT:
read_lock(&snd_pcm_link_rwlock);
break;
case PCM_LOCK_IRQ:
read_lock_irq(&snd_pcm_link_rwlock);
break;
case PCM_LOCK_IRQSAVE:
read_lock_irqsave(&snd_pcm_link_rwlock, flags);
break;
}
spin_lock(&substream->self_group.lock);
}
return flags;
}
static void __snd_pcm_stream_unlock_mode(struct snd_pcm_substream *substream,
unsigned int mode, unsigned long flags)
{
if (substream->pcm->nonatomic) {
mutex_unlock(&substream->self_group.mutex);
up_read(&snd_pcm_link_rwsem);
} else {
spin_unlock(&substream->self_group.lock);
switch (mode) {
case PCM_LOCK_DEFAULT:
read_unlock(&snd_pcm_link_rwlock);
break;
case PCM_LOCK_IRQ:
read_unlock_irq(&snd_pcm_link_rwlock);
break;
case PCM_LOCK_IRQSAVE:
read_unlock_irqrestore(&snd_pcm_link_rwlock, flags);
break;
}
}
}
/**
* snd_pcm_stream_lock - Lock the PCM stream
* @substream: PCM substream
......@@ -109,13 +160,7 @@ static inline void down_write_nonblock(struct rw_semaphore *lock)
*/
void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
{
if (substream->pcm->nonatomic) {
down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);
mutex_lock(&substream->self_group.mutex);
} else {
read_lock(&snd_pcm_link_rwlock);
spin_lock(&substream->self_group.lock);
}
__snd_pcm_stream_lock_mode(substream, PCM_LOCK_DEFAULT);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
......@@ -127,13 +172,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
*/
void snd_pcm_stream_unlock(struct snd_pcm_substream *substream)
{
if (substream->pcm->nonatomic) {
mutex_unlock(&substream->self_group.mutex);
up_read(&snd_pcm_link_rwsem);
} else {
spin_unlock(&substream->self_group.lock);
read_unlock(&snd_pcm_link_rwlock);
}
__snd_pcm_stream_unlock_mode(substream, PCM_LOCK_DEFAULT, 0);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
......@@ -147,9 +186,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
*/
void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
{
if (!substream->pcm->nonatomic)
local_irq_disable();
snd_pcm_stream_lock(substream);
__snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQ);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
......@@ -161,19 +198,13 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
*/
void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream)
{
snd_pcm_stream_unlock(substream);
if (!substream->pcm->nonatomic)
local_irq_enable();
__snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQ, 0);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq);
unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream)
{
unsigned long flags = 0;
if (!substream->pcm->nonatomic)
local_irq_save(flags);
snd_pcm_stream_lock(substream);
return flags;
return __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQSAVE);
}
EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
......@@ -187,9 +218,7 @@ EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
unsigned long flags)
{
snd_pcm_stream_unlock(substream);
if (!substream->pcm->nonatomic)
local_irq_restore(flags);
__snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQSAVE, flags);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
......@@ -857,6 +886,18 @@ static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream,
return err;
}
static inline snd_pcm_uframes_t
snd_pcm_calc_delay(struct snd_pcm_substream *substream)
{
snd_pcm_uframes_t delay;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
delay = snd_pcm_playback_hw_avail(substream->runtime);
else
delay = snd_pcm_capture_avail(substream->runtime);
return delay + substream->runtime->delay;
}
int snd_pcm_status(struct snd_pcm_substream *substream,
struct snd_pcm_status *status)
{
......@@ -908,21 +949,9 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
_tstamp_end:
status->appl_ptr = runtime->control->appl_ptr;
status->hw_ptr = runtime->status->hw_ptr;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
status->avail = snd_pcm_playback_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
status->delay = runtime->buffer_size - status->avail;
status->delay += runtime->delay;
} else
status->delay = 0;
} else {
status->avail = snd_pcm_capture_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
status->delay = status->avail + runtime->delay;
else
status->delay = 0;
}
status->avail = snd_pcm_avail(substream);
status->delay = snd_pcm_running(substream) ?
snd_pcm_calc_delay(substream) : 0;
status->avail_max = runtime->avail_max;
status->overrange = runtime->overrange;
runtime->avail_max = 0;
......@@ -2610,10 +2639,9 @@ static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
return ret < 0 ? 0 : frames;
}
static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
snd_pcm_uframes_t frames)
static snd_pcm_sframes_t snd_pcm_rewind(struct snd_pcm_substream *substream,
snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t ret;
if (frames == 0)
......@@ -2623,33 +2651,14 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst
ret = do_pcm_hwsync(substream);
if (!ret)
ret = rewind_appl_ptr(substream, frames,
snd_pcm_playback_hw_avail(runtime));
snd_pcm_hw_avail(substream));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream,
snd_pcm_uframes_t frames)
static snd_pcm_sframes_t snd_pcm_forward(struct snd_pcm_substream *substream,
snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t ret;
if (frames == 0)
return 0;
snd_pcm_stream_lock_irq(substream);
ret = do_pcm_hwsync(substream);
if (!ret)
ret = rewind_appl_ptr(substream, frames,
snd_pcm_capture_hw_avail(runtime));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *substream,
snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t ret;
if (frames == 0)
......@@ -2659,25 +2668,7 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs
ret = do_pcm_hwsync(substream);
if (!ret)
ret = forward_appl_ptr(substream, frames,
snd_pcm_playback_avail(runtime));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *substream,
snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t ret;
if (frames == 0)
return 0;
snd_pcm_stream_lock_irq(substream);
ret = do_pcm_hwsync(substream);
if (!ret)
ret = forward_appl_ptr(substream, frames,
snd_pcm_capture_avail(runtime));
snd_pcm_avail(substream));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
......@@ -2695,19 +2686,13 @@ static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
static int snd_pcm_delay(struct snd_pcm_substream *substream,
snd_pcm_sframes_t *delay)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int err;
snd_pcm_sframes_t n = 0;
snd_pcm_stream_lock_irq(substream);
err = do_pcm_hwsync(substream);
if (!err) {
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
n = snd_pcm_playback_hw_avail(runtime);
else
n = snd_pcm_capture_avail(runtime);
n += runtime->delay;
}
if (!err)
n = snd_pcm_calc_delay(substream);
snd_pcm_stream_unlock_irq(substream);
if (!err)
*delay = n;
......@@ -2834,10 +2819,7 @@ static int snd_pcm_rewind_ioctl(struct snd_pcm_substream *substream,
return -EFAULT;
if (put_user(0, _frames))
return -EFAULT;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
result = snd_pcm_playback_rewind(substream, frames);
else
result = snd_pcm_capture_rewind(substream, frames);
result = snd_pcm_rewind(substream, frames);
__put_user(result, _frames);
return result < 0 ? result : 0;
}
......@@ -2852,10 +2834,7 @@ static int snd_pcm_forward_ioctl(struct snd_pcm_substream *substream,
return -EFAULT;
if (put_user(0, _frames))
return -EFAULT;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
result = snd_pcm_playback_forward(substream, frames);
else
result = snd_pcm_capture_forward(substream, frames);
result = snd_pcm_forward(substream, frames);
__put_user(result, _frames);
return result < 0 ? result : 0;
}
......@@ -2998,7 +2977,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
/* provided only for OSS; capture-only and no value returned */
if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
return -EINVAL;
result = snd_pcm_capture_forward(substream, *frames);
result = snd_pcm_forward(substream, *frames);
return result < 0 ? result : 0;
}
case SNDRV_PCM_IOCTL_HW_PARAMS:
......@@ -3140,82 +3119,46 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
return result;
}
static __poll_t snd_pcm_playback_poll(struct file *file, poll_table * wait)
static __poll_t snd_pcm_poll(struct file *file, poll_table *wait)
{
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
__poll_t mask;
__poll_t mask, ok;
snd_pcm_uframes_t avail;
pcm_file = file->private_data;
substream = pcm_file->substream;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
ok = EPOLLOUT | EPOLLWRNORM;
else
ok = EPOLLIN | EPOLLRDNORM;
if (PCM_RUNTIME_CHECK(substream))
return EPOLLOUT | EPOLLWRNORM | EPOLLERR;
runtime = substream->runtime;
poll_wait(file, &runtime->sleep, wait);
return ok | EPOLLERR;
snd_pcm_stream_lock_irq(substream);
avail = snd_pcm_playback_avail(runtime);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
if (avail >= runtime->control->avail_min) {
mask = EPOLLOUT | EPOLLWRNORM;
break;
}
/* Fall through */
case SNDRV_PCM_STATE_DRAINING:
mask = 0;
break;
default:
mask = EPOLLOUT | EPOLLWRNORM | EPOLLERR;
break;
}
snd_pcm_stream_unlock_irq(substream);
return mask;
}
static __poll_t snd_pcm_capture_poll(struct file *file, poll_table * wait)
{
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
__poll_t mask;
snd_pcm_uframes_t avail;
pcm_file = file->private_data;
substream = pcm_file->substream;
if (PCM_RUNTIME_CHECK(substream))
return EPOLLIN | EPOLLRDNORM | EPOLLERR;
runtime = substream->runtime;
poll_wait(file, &runtime->sleep, wait);
mask = 0;
snd_pcm_stream_lock_irq(substream);
avail = snd_pcm_capture_avail(runtime);
avail = snd_pcm_avail(substream);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
if (avail >= runtime->control->avail_min) {
mask = EPOLLIN | EPOLLRDNORM;
break;
}
mask = 0;
if (avail >= runtime->control->avail_min)
mask = ok;
break;
case SNDRV_PCM_STATE_DRAINING:
if (avail > 0) {
mask = EPOLLIN | EPOLLRDNORM;
break;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
mask = ok;
if (!avail)
mask |= EPOLLERR;
}
/* Fall through */
break;
default:
mask = EPOLLIN | EPOLLRDNORM | EPOLLERR;
mask = ok | EPOLLERR;
break;
}
snd_pcm_stream_unlock_irq(substream);
......@@ -3707,7 +3650,7 @@ const struct file_operations snd_pcm_f_ops[2] = {
.open = snd_pcm_playback_open,
.release = snd_pcm_release,
.llseek = no_llseek,
.poll = snd_pcm_playback_poll,
.poll = snd_pcm_poll,
.unlocked_ioctl = snd_pcm_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
......@@ -3721,7 +3664,7 @@ const struct file_operations snd_pcm_f_ops[2] = {
.open = snd_pcm_capture_open,
.release = snd_pcm_release,
.llseek = no_llseek,
.poll = snd_pcm_capture_poll,
.poll = snd_pcm_poll,
.unlocked_ioctl = snd_pcm_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
......
......@@ -669,7 +669,7 @@ int snd_seq_event_port_attach(int client,
/* Set up the port */
memset(&portinfo, 0, sizeof(portinfo));
portinfo.addr.client = client;
strlcpy(portinfo.name, portname ? portname : "Unamed port",
strlcpy(portinfo.name, portname ? portname : "Unnamed port",
sizeof(portinfo.name));
portinfo.capability = cap;
......
......@@ -371,9 +371,7 @@ static int initialize_timer(struct snd_seq_timer *tmr)
tmr->ticks = 1;
if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) {
unsigned long r = t->hw.resolution;
if (! r && t->hw.c_resolution)
r = t->hw.c_resolution(t);
unsigned long r = snd_timer_resolution(tmr->timeri);
if (r) {
tmr->ticks = (unsigned int)(1000000000uL / (r * freq));
if (! tmr->ticks)
......
......@@ -427,25 +427,35 @@ int snd_timer_close(struct snd_timer_instance *timeri)
}
EXPORT_SYMBOL(snd_timer_close);
static unsigned long snd_timer_hw_resolution(struct snd_timer *timer)
{
if (timer->hw.c_resolution)
return timer->hw.c_resolution(timer);
else
return timer->hw.resolution;
}
unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
{
struct snd_timer * timer;
unsigned long ret = 0;
unsigned long flags;
if (timeri == NULL)
return 0;
timer = timeri->timer;
if (timer) {
if (timer->hw.c_resolution)
return timer->hw.c_resolution(timer);
return timer->hw.resolution;
spin_lock_irqsave(&timer->lock, flags);
ret = snd_timer_hw_resolution(timer);
spin_unlock_irqrestore(&timer->lock, flags);
}
return 0;
return ret;
}
EXPORT_SYMBOL(snd_timer_resolution);
static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
{
struct snd_timer *timer;
struct snd_timer *timer = ti->timer;
unsigned long resolution = 0;
struct snd_timer_instance *ts;
struct timespec tstamp;
......@@ -457,14 +467,14 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START ||
event > SNDRV_TIMER_EVENT_PAUSE))
return;
if (event == SNDRV_TIMER_EVENT_START ||
event == SNDRV_TIMER_EVENT_CONTINUE)
resolution = snd_timer_resolution(ti);
if (timer &&
(event == SNDRV_TIMER_EVENT_START ||
event == SNDRV_TIMER_EVENT_CONTINUE))
resolution = snd_timer_hw_resolution(timer);
if (ti->ccallback)
ti->ccallback(ti, event, &tstamp, resolution);
if (ti->flags & SNDRV_TIMER_IFLG_SLAVE)
return;
timer = ti->timer;
if (timer == NULL)
return;
if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
......@@ -771,10 +781,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
spin_lock_irqsave(&timer->lock, flags);
/* remember the current resolution */
if (timer->hw.c_resolution)
resolution = timer->hw.c_resolution(timer);
else
resolution = timer->hw.resolution;
resolution = snd_timer_hw_resolution(timer);
/* loop for all active instances
* Here we cannot use list_for_each_entry because the active_list of a
......@@ -1014,12 +1021,8 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam
spin_lock_irqsave(&timer->lock, flags);
if (event == SNDRV_TIMER_EVENT_MSTART ||
event == SNDRV_TIMER_EVENT_MCONTINUE ||
event == SNDRV_TIMER_EVENT_MRESUME) {
if (timer->hw.c_resolution)
resolution = timer->hw.c_resolution(timer);
else
resolution = timer->hw.resolution;
}
event == SNDRV_TIMER_EVENT_MRESUME)
resolution = snd_timer_hw_resolution(timer);
list_for_each_entry(ti, &timer->active_list_head, active_list) {
if (ti->ccallback)
ti->ccallback(ti, event, tstamp, resolution);
......@@ -1656,10 +1659,8 @@ static int snd_timer_user_gstatus(struct file *file,
mutex_lock(&register_mutex);
t = snd_timer_find(&tid);
if (t != NULL) {
if (t->hw.c_resolution)
gstatus.resolution = t->hw.c_resolution(t);
else
gstatus.resolution = t->hw.resolution;
spin_lock_irq(&t->lock);
gstatus.resolution = snd_timer_hw_resolution(t);
if (t->hw.precise_resolution) {
t->hw.precise_resolution(t, &gstatus.resolution_num,
&gstatus.resolution_den);
......@@ -1667,6 +1668,7 @@ static int snd_timer_user_gstatus(struct file *file,
gstatus.resolution_num = gstatus.resolution;
gstatus.resolution_den = 1000000000uL;
}
spin_unlock_irq(&t->lock);
} else {
err = -ENODEV;
}
......
......@@ -421,13 +421,15 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
kctl->private_free = master_free;
/* additional (constant) TLV read */
if (tlv &&
(tlv[0] == SNDRV_CTL_TLVT_DB_SCALE ||
tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX ||
tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX_MUTE)) {
kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
memcpy(master->tlv, tlv, sizeof(master->tlv));
kctl->tlv.p = master->tlv;
if (tlv) {
unsigned int type = tlv[SNDRV_CTL_TLVO_TYPE];
if (type == SNDRV_CTL_TLVT_DB_SCALE ||
type == SNDRV_CTL_TLVT_DB_MINMAX ||
type == SNDRV_CTL_TLVT_DB_MINMAX_MUTE) {
kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
memcpy(master->tlv, tlv, sizeof(master->tlv));
kctl->tlv.p = master->tlv;
}
}
return kctl;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册