提交 d6b63b5b 编写于 作者: L Linus Torvalds

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

Pull sound updates from Takashi Iwai:
 "As the diffstat scatters over the tree, we've got many tree-wide small
  changes, but also got quite a few intrusive changes in the core side.
  The only ABI-visible core change is the new rawmidi framing mode
  support while others are kernel-internal, mostly code refactoring
  and/or nice improvements.

  Here are some highlights:

  Core:
   - A new framing access mode for rawmidi to get timestamps
   - Cleanup / refactoring of buffer memory management helper code
   - Support for automatic negotiation of ASoC DAI formats
   - Revival of software suspend for PCM and control core, as a
     preliminary work for PCI BAR rescan support

  ASoC:
   - Accessory detection support for several Qualcomm parts
   - Support for IEC958 control with hdmi-codec
   - Merging of Tegra machine drivers into a single driver
   - Support for AmLogic SM1 TOACODEC, Intel AlderLake-M, several NXP
     i.MX8 variants, NXP TFA1 and TDF9897, Rockchip RK817, Qualcomm
     Quinary MI2S, Texas Instruments TAS2505

  USB-audio:
   - Reduction of latency at playback start
   - Code cleanup / fixes of usx2y driver
   - Scarlett2 mixer code fixes and enhancements
   - Quirks for Ozone and Denon devices

  HD-audio:
   - A few quirks for HP and ASUS machines
   - Display power management fixes

  Others:
   - FireWire code refactoring and enhancements
   - Tree-wide trivial coding-style fixes"

* tag 'sound-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (594 commits)
  ALSA: usb-audio: scarlett2: Fix for loop increment in scarlett2_usb_get_config
  ALSA: hda/realtek: fix mute/micmute LEDs for HP ProBook 630 G8
  ALSA: hda/realtek: fix mute/micmute LEDs for HP ProBook 445 G8
  ALSA: hda/realtek: fix mute/micmute LEDs for HP ProBook 450 G8
  ALSA: hda/realtek - Add ALC285 HP init procedure
  ALSA: hda/realtek - Add type for ALC287
  ALSA: scarlett2: Fix scarlett2_*_ctl_put() return values again
  ALSA: scarlett2: Fix pad count for 18i8 Gen 3
  ALSA: hda/realtek: fix mute/micmute LEDs for HP EliteBook 830 G8 Notebook PC
  ALSA: firewire-lib: Fix 'amdtp_domain_start()' when no AMDTP_OUT_STREAM stream is found
  ASoC: qcom: lpass-cpu: mark IRQ_CLEAR register as volatile and readable
  ALSA: hda: Release codec display power during shutdown/reboot
  ALSA: hda: Release controller display power during shutdown/reboot
  ALSA: hda/realtek: Apply LED fixup for HP Dragonfly G1, too
  ASoC: fsl: remove unnecessary oom message
  ASoC: tlv320aic32x4: dt-bindings: add TAS2505 to compatible
  ASoC: tlv320aic32x4: add support for TAS2505
  ASoC: tlv320aic32x4: add type to device private data struct
  ASoC: tegra30: ahub: Use devm_platform_get_and_ioremap_resource()
  ASoC: tegra: tegra210_admaif: Use devm_platform_get_and_ioremap_resource()
  ...
...@@ -23,6 +23,7 @@ Optional properties: ...@@ -23,6 +23,7 @@ Optional properties:
default output clock name default output clock name
- rockchip,system-power-controller: Telling whether or not this pmic is controlling - rockchip,system-power-controller: Telling whether or not this pmic is controlling
the system power. the system power.
- wakeup-source: Device can be used as a wakeup source.
Optional RK805 properties: Optional RK805 properties:
- vcc1-supply: The input supply for DCDC_REG1 - vcc1-supply: The input supply for DCDC_REG1
...@@ -63,8 +64,18 @@ Optional RK809 properties: ...@@ -63,8 +64,18 @@ Optional RK809 properties:
- vcc9-supply: The input supply for DCDC_REG5, SWITCH_REG2 - vcc9-supply: The input supply for DCDC_REG5, SWITCH_REG2
Optional RK817 properties: Optional RK817 properties:
- clocks: The input clock for the audio codec
- clock-names: The clock name for the codec clock. Should be "mclk".
- #sound-dai-cells: Needed for the interpretation of sound dais. Should be 0.
- vcc8-supply: The input supply for BOOST - vcc8-supply: The input supply for BOOST
- vcc9-supply: The input supply for OTG_SWITCH - vcc9-supply: The input supply for OTG_SWITCH
- codec: The child node for the codec to hold additional properties.
If no additional properties are required for the codec, this
node can be omitted.
- rockchip,mic-in-differential: Telling if the microphone uses differential
mode. Should be under the codec child node.
Optional RK818 properties: Optional RK818 properties:
- vcc1-supply: The input supply for DCDC_REG1 - vcc1-supply: The input supply for DCDC_REG1
...@@ -275,3 +286,180 @@ Example: ...@@ -275,3 +286,180 @@ Example:
}; };
}; };
}; };
rk817: pmic@20 {
compatible = "rockchip,rk817";
reg = <0x20>;
interrupt-parent = <&gpio0>;
interrupts = <RK_PB2 IRQ_TYPE_LEVEL_LOW>;
clock-output-names = "rk808-clkout1", "xin32k";
clock-names = "mclk";
clocks = <&cru SCLK_I2S1_OUT>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>;
wakeup-source;
#clock-cells = <1>;
#sound-dai-cells = <0>;
vcc1-supply = <&vccsys>;
vcc2-supply = <&vccsys>;
vcc3-supply = <&vccsys>;
vcc4-supply = <&vccsys>;
vcc5-supply = <&vccsys>;
vcc6-supply = <&vccsys>;
vcc7-supply = <&vccsys>;
regulators {
vdd_logic: DCDC_REG1 {
regulator-name = "vdd_logic";
regulator-min-microvolt = <950000>;
regulator-max-microvolt = <1150000>;
regulator-ramp-delay = <6001>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <950000>;
};
};
vdd_arm: DCDC_REG2 {
regulator-name = "vdd_arm";
regulator-min-microvolt = <950000>;
regulator-max-microvolt = <1350000>;
regulator-ramp-delay = <6001>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-off-in-suspend;
regulator-suspend-microvolt = <950000>;
};
};
vcc_ddr: DCDC_REG3 {
regulator-name = "vcc_ddr";
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
};
};
vcc_3v3: DCDC_REG4 {
regulator-name = "vcc_3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-off-in-suspend;
regulator-suspend-microvolt = <3300000>;
};
};
vcc_1v8: LDO_REG2 {
regulator-name = "vcc_1v8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <1800000>;
};
};
vdd_1v0: LDO_REG3 {
regulator-name = "vdd_1v0";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <1000000>;
};
};
vcc3v3_pmu: LDO_REG4 {
regulator-name = "vcc3v3_pmu";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <3300000>;
};
};
vccio_sd: LDO_REG5 {
regulator-name = "vccio_sd";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <3300000>;
};
};
vcc_sd: LDO_REG6 {
regulator-name = "vcc_sd";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <3300000>;
};
};
vcc_bl: LDO_REG7 {
regulator-name = "vcc_bl";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-state-mem {
regulator-off-in-suspend;
regulator-suspend-microvolt = <3300000>;
};
};
vcc_lcd: LDO_REG8 {
regulator-name = "vcc_lcd";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
regulator-state-mem {
regulator-off-in-suspend;
regulator-suspend-microvolt = <2800000>;
};
};
vcc_cam: LDO_REG9 {
regulator-name = "vcc_cam";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
regulator-state-mem {
regulator-off-in-suspend;
regulator-suspend-microvolt = <3000000>;
};
};
};
rk817_codec: codec {
rockchip,mic-in-differential;
};
};
...@@ -12,7 +12,11 @@ maintainers: ...@@ -12,7 +12,11 @@ maintainers:
properties: properties:
"#sound-dai-cells": "#sound-dai-cells":
const: 0 minimum: 0
maximum: 1
description:
A value of 0 is deprecated. When used, it only allows access to
the ADC/DAC and AIF1 (the CPU DAI), not the other two AIFs/DAIs.
compatible: compatible:
oneOf: oneOf:
...@@ -50,7 +54,7 @@ additionalProperties: false ...@@ -50,7 +54,7 @@ additionalProperties: false
examples: examples:
- | - |
audio-codec@1c22e00 { audio-codec@1c22e00 {
#sound-dai-cells = <0>; #sound-dai-cells = <1>;
compatible = "allwinner,sun8i-a33-codec"; compatible = "allwinner,sun8i-a33-codec";
reg = <0x01c22e00 0x400>; reg = <0x01c22e00 0x400>;
interrupts = <0 29 4>; interrupts = <0 29 4>;
......
...@@ -81,6 +81,13 @@ Optional properties: ...@@ -81,6 +81,13 @@ Optional properties:
< x1 x2 x3 x4 > < x1 x2 x3 x4 >
Default = < 15 8 4 1> Default = < 15 8 4 1>
- cirrus,hs-bias-sense-disable: This is boolean property. If present the
HSBIAS sense is disabled. Configures HSBIAS output current sense through
the external 2.21-k resistor. HSBIAS_SENSE is hardware feature to reduce
the potential pop noise during the headset plug out slowly. But on some
platforms ESD voltage will affect it causing test to fail, especially
with CTIA headset type. For different hardware setups, a designer might
want to tweak default behavior.
Example: Example:
......
...@@ -25,6 +25,7 @@ properties: ...@@ -25,6 +25,7 @@ properties:
- fsl,imx8mq-spdif - fsl,imx8mq-spdif
- fsl,imx8mm-spdif - fsl,imx8mm-spdif
- fsl,imx8mn-spdif - fsl,imx8mn-spdif
- fsl,imx8ulp-spdif
reg: reg:
maxItems: 1 maxItems: 1
......
...@@ -9,8 +9,10 @@ Required properties: ...@@ -9,8 +9,10 @@ Required properties:
- compatible : Compatible list, contains "fsl,vf610-sai", - compatible : Compatible list, contains "fsl,vf610-sai",
"fsl,imx6sx-sai", "fsl,imx6ul-sai", "fsl,imx6sx-sai", "fsl,imx6ul-sai",
"fsl,imx7ulp-sai", "fsl,imx8mq-sai" or "fsl,imx7ulp-sai", "fsl,imx8mq-sai",
"fsl,imx8qm-sai". "fsl,imx8qm-sai", "fsl,imx8mm-sai",
"fsl,imx8mn-sai", "fsl,imx8mp-sai", or
"fsl,imx8ulp-sai".
- reg : Offset and length of the register set for the device. - reg : Offset and length of the register set for the device.
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/imx-audio-card.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP i.MX audio sound card.
maintainers:
- Shengjiu Wang <shengjiu.wang@nxp.com>
properties:
compatible:
enum:
- fsl,imx-audio-card
model:
$ref: /schemas/types.yaml#/definitions/string
description: User specified audio sound card name
audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description:
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.
patternProperties:
".*-dai-link$":
description:
Each subnode represents a dai link. Subnodes of each dai links would be
cpu/codec dais.
type: object
properties:
link-name:
description: Indicates dai-link name and PCM stream name.
$ref: /schemas/types.yaml#/definitions/string
maxItems: 1
format:
description: audio format.
items:
enum:
- i2s
- dsp_b
dai-tdm-slot-num:
description: see tdm-slot.txt.
$ref: /schemas/types.yaml#/definitions/uint32
dai-tdm-slot-width:
description: see tdm-slot.txt.
$ref: /schemas/types.yaml#/definitions/uint32
cpu:
description: Holds subnode which indicates cpu dai.
type: object
properties:
sound-dai: true
codec:
description: Holds subnode which indicates codec dai.
type: object
properties:
sound-dai: true
fsl,mclk-equal-bclk:
description: Indicates mclk can be equal to bclk, especially for sai interface
$ref: /schemas/types.yaml#/definitions/flag
required:
- link-name
- cpu
additionalProperties: false
required:
- compatible
- model
additionalProperties: false
examples:
- |
sound-ak4458 {
compatible = "fsl,imx-audio-card";
model = "ak4458-audio";
pri-dai-link {
link-name = "akcodec";
format = "i2s";
fsl,mclk-equal-bclk;
cpu {
sound-dai = <&sai1>;
};
codec {
sound-dai = <&ak4458_1>, <&ak4458_2>;
};
};
fe-dai-link {
link-name = "HiFi-ASRC-FE";
format = "i2s";
cpu {
sound-dai = <&easrc>;
};
};
be-dai-link {
link-name = "HiFi-ASRC-BE";
format = "dsp_b";
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
fsl,mclk-equal-bclk;
cpu {
sound-dai = <&sai1>;
};
codec {
sound-dai = <&ak4458_1>, <&ak4458_2>;
};
};
};
Freescale Digital Audio Mux (AUDMUX) device
Required properties:
- compatible : "fsl,imx21-audmux" for AUDMUX version firstly used
on i.MX21, or "fsl,imx31-audmux" for the version
firstly used on i.MX31.
- reg : Should contain AUDMUX registers location and length.
An initial configuration can be setup using child nodes.
Required properties of optional child nodes:
- fsl,audmux-port : Integer of the audmux port that is configured by this
child node.
- fsl,port-config : List of configuration options for the specific port.
For imx31-audmux and above, it is a list of tuples
<ptcr pdcr>. For imx21-audmux it is a list of pcr
values.
Example:
audmux@21d8000 {
compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux";
reg = <0x021d8000 0x4000>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/imx-audmux.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale Digital Audio Mux device
maintainers:
- Oleksij Rempel <o.rempel@pengutronix.de>
properties:
compatible:
oneOf:
- items:
- enum:
- fsl,imx27-audmux
- const: fsl,imx21-audmux
- items:
- enum:
- fsl,imx25-audmux
- fsl,imx35-audmux
- fsl,imx50-audmux
- fsl,imx51-audmux
- fsl,imx53-audmux
- fsl,imx6q-audmux
- fsl,imx6sl-audmux
- fsl,imx6sll-audmux
- fsl,imx6sx-audmux
- const: fsl,imx31-audmux
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
items:
- const: audmux
patternProperties:
"^mux-[0-9a-z]*$":
type: object
properties:
fsl,audmux-port:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Integer of the audmux port that is configured by this child node
fsl,port-config:
$ref: /schemas/types.yaml#/definitions/uint32-array
description: |
List of configuration options for the specific port.
For imx31-audmux and above, it is a list of tuples ptcr pdcr.
For imx21-audmux it is a list of pcr values.
required:
- fsl,audmux-port
- fsl,port-config
additionalProperties: false
required:
- compatible
- reg
additionalProperties: false
examples:
- |
audmux@21d8000 {
compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux";
reg = <0x021d8000 0x4000>;
};
- |
audmux@10016000 {
compatible = "fsl,imx27-audmux", "fsl,imx21-audmux";
reg = <0x10016000 0x1000>;
clocks = <&clks 1>;
clock-names = "audmux";
mux-ssi0 {
fsl,audmux-port = <0>;
fsl,port-config = <0xcb205000>;
};
mux-pins4 {
fsl,audmux-port = <2>;
fsl,port-config = <0x00001000>;
};
};
- |
#include <dt-bindings/sound/fsl-imx-audmux.h>
audmux@21d8000 {
compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux";
reg = <0x021d8000 0x4000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audmux>;
mux-ssi1 {
fsl,audmux-port = <0>;
fsl,port-config = <
IMX_AUDMUX_V2_PTCR_SYN 0
IMX_AUDMUX_V2_PTCR_TFSEL(2) 0
IMX_AUDMUX_V2_PTCR_TCSEL(2) 0
IMX_AUDMUX_V2_PTCR_TFSDIR 0
IMX_AUDMUX_V2_PTCR_TCLKDIR IMX_AUDMUX_V2_PDCR_RXDSEL(2)
>;
};
mux-pins3 {
fsl,audmux-port = <2>;
fsl,port-config = <
IMX_AUDMUX_V2_PTCR_SYN IMX_AUDMUX_V2_PDCR_RXDSEL(0)
0 IMX_AUDMUX_V2_PDCR_TXRXEN
>;
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nxp,tfa989x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP/Goodix TFA989X (TFA1) Audio Amplifiers
maintainers:
- Stephan Gerhold <stephan@gerhold.net>
properties:
compatible:
enum:
- nxp,tfa9895
- nxp,tfa9897
reg:
maxItems: 1
'#sound-dai-cells':
const: 0
sound-name-prefix:
$ref: /schemas/types.yaml#/definitions/string
description:
Used as prefix for sink/source names of the component. Must be a
unique string among multiple instances of the same component.
vddd-supply:
description: regulator phandle for the VDDD power supply.
required:
- compatible
- reg
- '#sound-dai-cells'
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@34 {
compatible = "nxp,tfa9895";
reg = <0x34>;
sound-name-prefix = "Speaker Left";
#sound-dai-cells = <0>;
};
audio-codec@36 {
compatible = "nxp,tfa9895";
reg = <0x36>;
sound-name-prefix = "Speaker Right";
#sound-dai-cells = <0>;
};
};
...@@ -77,6 +77,31 @@ properties: ...@@ -77,6 +77,31 @@ properties:
minimum: 1800000 minimum: 1800000
maximum: 2850000 maximum: 2850000
qcom,hphl-jack-type-normally-closed:
description: Indicates that HPHL jack switch type is normally closed
type: boolean
qcom,ground-jack-type-normally-closed:
description: Indicates that Headset Ground switch type is normally closed
type: boolean
qcom,mbhc-headset-vthreshold-microvolt:
description: Voltage threshold value for headset detection
minimum: 0
maximum: 2850000
qcom,mbhc-headphone-vthreshold-microvolt:
description: Voltage threshold value for headphone detection
minimum: 0
maximum: 2850000
qcom,mbhc-buttons-vthreshold-microvolt:
description:
Array of 8 Voltage threshold values corresponding to headset
button0 - button7
minItems: 8
maxItems: 8
clock-output-names: clock-output-names:
const: mclk const: mclk
...@@ -159,6 +184,11 @@ examples: ...@@ -159,6 +184,11 @@ examples:
qcom,micbias2-microvolt = <1800000>; qcom,micbias2-microvolt = <1800000>;
qcom,micbias3-microvolt = <1800000>; qcom,micbias3-microvolt = <1800000>;
qcom,micbias4-microvolt = <1800000>; qcom,micbias4-microvolt = <1800000>;
qcom,hphl-jack-type-normally-closed;
qcom,ground-jack-type-normally-closed;
qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 500000 500000 500000 500000>;
qcom,mbhc-headset-vthreshold-microvolt = <1700000>;
qcom,mbhc-headphone-vthreshold-microvolt = <50000>;
clock-names = "extclk"; clock-names = "extclk";
clocks = <&rpmhcc 2>; clocks = <&rpmhcc 2>;
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,wcd938x-sdw.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Bindings for Qualcomm SoundWire Slave devices on WCD9380/WCD9385
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
description: |
Qualcomm WCD9380/WCD9385 Codec is a standalone Hi-Fi audio codec IC.
It has RX and TX Soundwire slave devices. This bindings is for the
slave devices.
properties:
compatible:
const: sdw20217010d00
reg:
maxItems: 1
qcom,tx-port-mapping:
description: |
Specifies static port mapping between slave and master tx ports.
In the order of slave port index.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 4
maxItems: 4
qcom,rx-port-mapping:
description: |
Specifies static port mapping between slave and master rx ports.
In the order of slave port index.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 5
maxItems: 5
required:
- compatible
- reg
additionalProperties: false
examples:
- |
soundwire@3210000 {
#address-cells = <2>;
#size-cells = <0>;
reg = <0x03210000 0x2000>;
wcd938x_rx: codec@0,4 {
compatible = "sdw20217010d00";
reg = <0 4>;
qcom,rx-port-mapping = <1 2 3 4 5>;
};
};
soundwire@3230000 {
#address-cells = <2>;
#size-cells = <0>;
reg = <0x03230000 0x2000>;
wcd938x_tx: codec@0,3 {
compatible = "sdw20217010d00";
reg = <0 3>;
qcom,tx-port-mapping = <2 3 4 5>;
};
};
...
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,wcd938x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Bindings for Qualcomm WCD9380/WCD9385 Audio Codec
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
description: |
Qualcomm WCD9380/WCD9385 Codec is a standalone Hi-Fi audio codec IC.
It has RX and TX Soundwire slave devices.
properties:
compatible:
enum:
- qcom,wcd9380-codec
- qcom,wcd9385-codec
reset-gpios:
description: GPIO spec for reset line to use
maxItems: 1
vdd-buck-supply:
description: A reference to the 1.8V buck supply
vdd-rxtx-supply:
description: A reference to the 1.8V rx supply
vdd-io-supply:
description: A reference to the 1.8V I/O supply
qcom,tx-device:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: A reference to Soundwire tx device phandle
qcom,rx-device:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: A reference to Soundwire rx device phandle
qcom,micbias1-microvolt:
description: micbias1 voltage
minimum: 1800000
maximum: 2850000
qcom,micbias2-microvolt:
description: micbias2 voltage
minimum: 1800000
maximum: 2850000
qcom,micbias3-microvolt:
description: micbias3 voltage
minimum: 1800000
maximum: 2850000
qcom,micbias4-microvolt:
description: micbias4 voltage
minimum: 1800000
maximum: 2850000
qcom,hphl-jack-type-normally-closed:
description: Indicates that HPHL jack switch type is normally closed
type: boolean
qcom,ground-jack-type-normally-closed:
description: Indicates that Headset Ground switch type is normally closed
type: boolean
qcom,mbhc-headset-vthreshold-microvolt:
description: Voltage threshold value for headset detection
minimum: 0
maximum: 2850000
qcom,mbhc-headphone-vthreshold-microvolt:
description: Voltage threshold value for headphone detection
minimum: 0
maximum: 2850000
qcom,mbhc-buttons-vthreshold-microvolt:
description:
Array of 8 Voltage threshold values corresponding to headset
button0 - button7
minItems: 8
maxItems: 8
'#sound-dai-cells':
const: 1
required:
- compatible
- reset-gpios
- qcom,tx-device
- qcom,rx-device
- qcom,micbias1-microvolt
- qcom,micbias2-microvolt
- qcom,micbias3-microvolt
- qcom,micbias4-microvolt
- "#sound-dai-cells"
additionalProperties: false
examples:
- |
codec {
compatible = "qcom,wcd9380-codec";
reset-gpios = <&tlmm 32 0>;
#sound-dai-cells = <1>;
qcom,tx-device = <&wcd938x_tx>;
qcom,rx-device = <&wcd938x_rx>;
qcom,micbias1-microvolt = <1800000>;
qcom,micbias2-microvolt = <1800000>;
qcom,micbias3-microvolt = <1800000>;
qcom,micbias4-microvolt = <1800000>;
qcom,hphl-jack-type-normally-closed;
qcom,ground-jack-type-normally-closed;
qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 500000 500000 500000 500000>;
qcom,mbhc-headphone-vthreshold-microvolt = <50000>;
};
/* ... */
soundwire@3210000 {
#address-cells = <2>;
#size-cells = <0>;
reg = <0x03210000 0x2000>;
wcd938x_rx: codec@0,4 {
compatible = "sdw20217010d00";
reg = <0 4>;
qcom,rx-port-mapping = <1 2 3 4 5>;
};
};
soundwire@3230000 {
#address-cells = <2>;
#size-cells = <0>;
reg = <0x03230000 0x2000>;
wcd938x_tx: codec@0,3 {
compatible = "sdw20217010d00";
reg = <0 3>;
qcom,tx-port-mapping = <2 3 4 5>;
};
};
...
...@@ -86,9 +86,11 @@ properties: ...@@ -86,9 +86,11 @@ properties:
power-domains: true power-domains: true
resets: resets:
minItems: 1
maxItems: 11 maxItems: 11
reset-names: reset-names:
minItems: 1
maxItems: 11 maxItems: 11
clocks: clocks:
...@@ -110,6 +112,13 @@ properties: ...@@ -110,6 +112,13 @@ properties:
- pattern: '^dvc\.[0-1]$' - pattern: '^dvc\.[0-1]$'
- pattern: '^clk_(a|b|c|i)$' - pattern: '^clk_(a|b|c|i)$'
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port(@[0-9a-f]+)?:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
port: port:
$ref: audio-graph-port.yaml# $ref: audio-graph-port.yaml#
unevaluatedProperties: false unevaluatedProperties: false
...@@ -257,7 +266,6 @@ required: ...@@ -257,7 +266,6 @@ required:
- "#sound-dai-cells" - "#sound-dai-cells"
allOf: allOf:
- $ref: audio-graph.yaml#
- if: - if:
properties: properties:
compatible: compatible:
......
...@@ -75,6 +75,10 @@ properties: ...@@ -75,6 +75,10 @@ properties:
$ref: "/schemas/types.yaml#/definitions/uint32" $ref: "/schemas/types.yaml#/definitions/uint32"
enum: [ 0, 1, 2, 3 ] enum: [ 0, 1, 2, 3 ]
port:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
required: required:
- compatible - compatible
- reg - reg
......
...@@ -6,6 +6,7 @@ Required properties: ...@@ -6,6 +6,7 @@ Required properties:
- compatible - "string" - One of: - compatible - "string" - One of:
"ti,tlv320aic32x4" TLV320AIC3204 "ti,tlv320aic32x4" TLV320AIC3204
"ti,tlv320aic32x6" TLV320AIC3206, TLV320AIC3256 "ti,tlv320aic32x6" TLV320AIC3206, TLV320AIC3256
"ti,tas2505" TAS2505, TAS2521
- reg: I2C slave address - reg: I2C slave address
- supply-*: Required supply regulators are: - supply-*: Required supply regulators are:
"iov" - digital IO power supply "iov" - digital IO power supply
......
WM8750 and WM8987 audio CODECs
These devices support both I2C and SPI (configured with pin strapping
on the board).
Required properties:
- compatible : "wlf,wm8750" or "wlf,wm8987"
- reg : the I2C address of the device for I2C, the chip select
number for SPI.
Example:
wm8750: codec@1a {
compatible = "wlf,wm8750";
reg = <0x1a>;
};
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/wm8750.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: WM8750 and WM8987 audio CODECs
description: |
These devices support both I2C and SPI (configured with pin strapping
on the board).
maintainers:
- Mark Brown <broonie@kernel.org>
properties:
compatible:
enum:
- wlf,wm8750
- wlf,wm8987
reg:
description:
The I2C address of the device for I2C, the chip select number for SPI
maxItems: 1
additionalProperties: false
required:
- reg
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
codec@1a {
compatible = "wlf,wm8750";
reg = <0x1a>;
};
};
...@@ -102,7 +102,7 @@ Conexant codecs ...@@ -102,7 +102,7 @@ Conexant codecs
--------------- ---------------
Auto-Mute Mode Auto-Mute Mode
See Reatek codecs. See Realtek codecs.
Analog codecs Analog codecs
......
...@@ -3508,14 +3508,15 @@ field must be set, though). ...@@ -3508,14 +3508,15 @@ field must be set, though).
“IEC958 Playback Con Mask” is used to return the bit-mask for the IEC958 “IEC958 Playback Con Mask” is used to return the bit-mask for the IEC958
status bits of consumer mode. Similarly, “IEC958 Playback Pro Mask” status bits of consumer mode. Similarly, “IEC958 Playback Pro Mask”
returns the bitmask for professional mode. They are read-only controls, returns the bitmask for professional mode. They are read-only controls.
and are defined as MIXER controls (iface =
``SNDRV_CTL_ELEM_IFACE_MIXER``).
Meanwhile, “IEC958 Playback Default” control is defined for getting and Meanwhile, “IEC958 Playback Default” control is defined for getting and
setting the current default IEC958 bits. Note that this one is usually setting the current default IEC958 bits.
defined as a PCM control (iface = ``SNDRV_CTL_ELEM_IFACE_PCM``),
although in some places it's defined as a MIXER control. Due to historical reasons, both variants of the Playback Mask and the
Playback Default controls can be implemented on either a
``SNDRV_CTL_ELEM_IFACE_PCM`` or a ``SNDRV_CTL_ELEM_IFACE_MIXER`` iface.
Drivers should expose the mask and default on the same iface though.
In addition, you can define the control switches to enable/disable or to In addition, you can define the control switches to enable/disable or to
set the raw bit mode. The implementation will depend on the chip, but set the raw bit mode. The implementation will depend on the chip, but
......
...@@ -7179,6 +7179,13 @@ L: linux-input@vger.kernel.org ...@@ -7179,6 +7179,13 @@ L: linux-input@vger.kernel.org
S: Maintained S: Maintained
F: drivers/input/joystick/fsia6b.c F: drivers/input/joystick/fsia6b.c
FOCUSRITE SCARLETT GEN 2/3 MIXER DRIVER
M: Geoffrey D. Bennett <g@b4.vu>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
F: sound/usb/mixer_scarlett_gen2.c
FORCEDETH GIGABIT ETHERNET DRIVER FORCEDETH GIGABIT ETHERNET DRIVER
M: Rain River <rain.1986.08.12@gmail.com> M: Rain River <rain.1986.08.12@gmail.com>
M: Zhu Yanjun <zyjzyj2000@gmail.com> M: Zhu Yanjun <zyjzyj2000@gmail.com>
...@@ -13321,6 +13328,13 @@ S: Maintained ...@@ -13321,6 +13328,13 @@ S: Maintained
F: Documentation/devicetree/bindings/sound/tfa9879.txt F: Documentation/devicetree/bindings/sound/tfa9879.txt
F: sound/soc/codecs/tfa9879* F: sound/soc/codecs/tfa9879*
NXP/Goodix TFA989X (TFA1) DRIVER
M: Stephan Gerhold <stephan@gerhold.net>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml
F: sound/soc/codecs/tfa989x.c
NXP-NCI NFC DRIVER NXP-NCI NFC DRIVER
R: Charles Gorand <charles.gorand@effinnov.com> R: Charles Gorand <charles.gorand@effinnov.com>
L: linux-nfc@lists.01.org (subscribers-only) L: linux-nfc@lists.01.org (subscribers-only)
......
...@@ -65,6 +65,7 @@ static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg) ...@@ -65,6 +65,7 @@ static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
switch (reg) { switch (reg) {
case RK817_SECONDS_REG ... RK817_WEEKS_REG: case RK817_SECONDS_REG ... RK817_WEEKS_REG:
case RK817_RTC_STATUS_REG: case RK817_RTC_STATUS_REG:
case RK817_CODEC_DTOP_LPT_SRST:
case RK817_INT_STS_REG0: case RK817_INT_STS_REG0:
case RK817_INT_STS_REG1: case RK817_INT_STS_REG1:
case RK817_INT_STS_REG2: case RK817_INT_STS_REG2:
...@@ -163,6 +164,7 @@ static const struct mfd_cell rk817s[] = { ...@@ -163,6 +164,7 @@ static const struct mfd_cell rk817s[] = {
.num_resources = ARRAY_SIZE(rk817_rtc_resources), .num_resources = ARRAY_SIZE(rk817_rtc_resources),
.resources = &rk817_rtc_resources[0], .resources = &rk817_rtc_resources[0],
}, },
{ .name = "rk817-codec",},
}; };
static const struct mfd_cell rk818s[] = { static const struct mfd_cell rk818s[] = {
...@@ -201,6 +203,85 @@ static const struct rk808_reg_data rk808_pre_init_reg[] = { ...@@ -201,6 +203,85 @@ static const struct rk808_reg_data rk808_pre_init_reg[] = {
static const struct rk808_reg_data rk817_pre_init_reg[] = { static const struct rk808_reg_data rk817_pre_init_reg[] = {
{RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, {RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP},
/* Codec specific registers */
{ RK817_CODEC_DTOP_VUCTL, MASK_ALL, 0x03 },
{ RK817_CODEC_DTOP_VUCTIME, MASK_ALL, 0x00 },
{ RK817_CODEC_DTOP_LPT_SRST, MASK_ALL, 0x00 },
{ RK817_CODEC_DTOP_DIGEN_CLKE, MASK_ALL, 0x00 },
/* from vendor driver, CODEC_AREF_RTCFG0 not defined in data sheet */
{ RK817_CODEC_AREF_RTCFG0, MASK_ALL, 0x00 },
{ RK817_CODEC_AREF_RTCFG1, MASK_ALL, 0x06 },
{ RK817_CODEC_AADC_CFG0, MASK_ALL, 0xc8 },
/* from vendor driver, CODEC_AADC_CFG1 not defined in data sheet */
{ RK817_CODEC_AADC_CFG1, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_VOLL, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_VOLR, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_SR_ACL0, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_ALC1, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_ALC2, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_NG, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_HPF, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_RVOLL, MASK_ALL, 0xff },
{ RK817_CODEC_DADC_RVOLR, MASK_ALL, 0xff },
{ RK817_CODEC_AMIC_CFG0, MASK_ALL, 0x70 },
{ RK817_CODEC_AMIC_CFG1, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_PGA_GAIN, MASK_ALL, 0x66 },
{ RK817_CODEC_DMIC_LMT1, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_LMT2, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_NG1, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_NG2, MASK_ALL, 0x00 },
/* from vendor driver, CODEC_ADAC_CFG0 not defined in data sheet */
{ RK817_CODEC_ADAC_CFG0, MASK_ALL, 0x00 },
{ RK817_CODEC_ADAC_CFG1, MASK_ALL, 0x07 },
{ RK817_CODEC_DDAC_POPD_DACST, MASK_ALL, 0x82 },
{ RK817_CODEC_DDAC_VOLL, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_VOLR, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_SR_LMT0, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_LMT1, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_LMT2, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_MUTE_MIXCTL, MASK_ALL, 0xa0 },
{ RK817_CODEC_DDAC_RVOLL, MASK_ALL, 0xff },
{ RK817_CODEC_DADC_RVOLR, MASK_ALL, 0xff },
{ RK817_CODEC_AMIC_CFG0, MASK_ALL, 0x70 },
{ RK817_CODEC_AMIC_CFG1, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_PGA_GAIN, MASK_ALL, 0x66 },
{ RK817_CODEC_DMIC_LMT1, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_LMT2, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_NG1, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_NG2, MASK_ALL, 0x00 },
/* from vendor driver, CODEC_ADAC_CFG0 not defined in data sheet */
{ RK817_CODEC_ADAC_CFG0, MASK_ALL, 0x00 },
{ RK817_CODEC_ADAC_CFG1, MASK_ALL, 0x07 },
{ RK817_CODEC_DDAC_POPD_DACST, MASK_ALL, 0x82 },
{ RK817_CODEC_DDAC_VOLL, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_VOLR, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_SR_LMT0, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_LMT1, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_LMT2, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_MUTE_MIXCTL, MASK_ALL, 0xa0 },
{ RK817_CODEC_DDAC_RVOLL, MASK_ALL, 0xff },
{ RK817_CODEC_DDAC_RVOLR, MASK_ALL, 0xff },
{ RK817_CODEC_AHP_ANTI0, MASK_ALL, 0x00 },
{ RK817_CODEC_AHP_ANTI1, MASK_ALL, 0x00 },
{ RK817_CODEC_AHP_CFG0, MASK_ALL, 0xe0 },
{ RK817_CODEC_AHP_CFG1, MASK_ALL, 0x1f },
{ RK817_CODEC_AHP_CP, MASK_ALL, 0x09 },
{ RK817_CODEC_ACLASSD_CFG1, MASK_ALL, 0x69 },
{ RK817_CODEC_ACLASSD_CFG2, MASK_ALL, 0x44 },
{ RK817_CODEC_APLL_CFG0, MASK_ALL, 0x04 },
{ RK817_CODEC_APLL_CFG1, MASK_ALL, 0x00 },
{ RK817_CODEC_APLL_CFG2, MASK_ALL, 0x30 },
{ RK817_CODEC_APLL_CFG3, MASK_ALL, 0x19 },
{ RK817_CODEC_APLL_CFG4, MASK_ALL, 0x65 },
{ RK817_CODEC_APLL_CFG5, MASK_ALL, 0x01 },
{ RK817_CODEC_DI2S_CKM, MASK_ALL, 0x01 },
{ RK817_CODEC_DI2S_RSD, MASK_ALL, 0x00 },
{ RK817_CODEC_DI2S_RXCR1, MASK_ALL, 0x00 },
{ RK817_CODEC_DI2S_RXCR2, MASK_ALL, 0x17 },
{ RK817_CODEC_DI2S_RXCMD_TSD, MASK_ALL, 0x00 },
{ RK817_CODEC_DI2S_TXCR1, MASK_ALL, 0x00 },
{ RK817_CODEC_DI2S_TXCR2, MASK_ALL, 0x17 },
{ RK817_CODEC_DI2S_TXCR3_TXCMD, MASK_ALL, 0x00 },
{RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L}, {RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L},
{RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK, {RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK,
RK817_HOTDIE_105 | RK817_TSD_140}, RK817_HOTDIE_105 | RK817_TSD_140},
......
...@@ -492,7 +492,7 @@ int sdw_read_no_pm(struct sdw_slave *slave, u32 addr) ...@@ -492,7 +492,7 @@ int sdw_read_no_pm(struct sdw_slave *slave, u32 addr)
} }
EXPORT_SYMBOL(sdw_read_no_pm); EXPORT_SYMBOL(sdw_read_no_pm);
static int sdw_update_no_pm(struct sdw_slave *slave, u32 addr, u8 mask, u8 val) int sdw_update_no_pm(struct sdw_slave *slave, u32 addr, u8 mask, u8 val)
{ {
int tmp; int tmp;
...@@ -503,6 +503,21 @@ static int sdw_update_no_pm(struct sdw_slave *slave, u32 addr, u8 mask, u8 val) ...@@ -503,6 +503,21 @@ static int sdw_update_no_pm(struct sdw_slave *slave, u32 addr, u8 mask, u8 val)
tmp = (tmp & ~mask) | val; tmp = (tmp & ~mask) | val;
return sdw_write_no_pm(slave, addr, tmp); return sdw_write_no_pm(slave, addr, tmp);
} }
EXPORT_SYMBOL(sdw_update_no_pm);
/* Read-Modify-Write Slave register */
int sdw_update(struct sdw_slave *slave, u32 addr, u8 mask, u8 val)
{
int tmp;
tmp = sdw_read(slave, addr);
if (tmp < 0)
return tmp;
tmp = (tmp & ~mask) | val;
return sdw_write(slave, addr, tmp);
}
EXPORT_SYMBOL(sdw_update);
/** /**
* sdw_nread() - Read "n" contiguous SDW Slave registers * sdw_nread() - Read "n" contiguous SDW Slave registers
......
...@@ -201,19 +201,6 @@ static inline void sdw_fill_port_params(struct sdw_port_params *params, ...@@ -201,19 +201,6 @@ static inline void sdw_fill_port_params(struct sdw_port_params *params,
params->data_mode = data_mode; params->data_mode = data_mode;
} }
/* Read-Modify-Write Slave register */
static inline int sdw_update(struct sdw_slave *slave, u32 addr, u8 mask, u8 val)
{
int tmp;
tmp = sdw_read(slave, addr);
if (tmp < 0)
return tmp;
tmp = (tmp & ~mask) | val;
return sdw_write(slave, addr, tmp);
}
/* broadcast read/write for tests */ /* broadcast read/write for tests */
int sdw_bread_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr); int sdw_bread_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr);
int sdw_bwrite_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr, u8 value); int sdw_bwrite_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr, u8 value);
......
...@@ -129,6 +129,8 @@ ...@@ -129,6 +129,8 @@
#define TX_CODEC_DMA_TX_5 124 #define TX_CODEC_DMA_TX_5 124
#define RX_CODEC_DMA_RX_6 125 #define RX_CODEC_DMA_RX_6 125
#define RX_CODEC_DMA_RX_7 126 #define RX_CODEC_DMA_RX_7 126
#define QUINARY_MI2S_RX 127
#define QUINARY_MI2S_TX 128
#define LPASS_CLK_ID_PRI_MI2S_IBIT 1 #define LPASS_CLK_ID_PRI_MI2S_IBIT 1
#define LPASS_CLK_ID_PRI_MI2S_EBIT 2 #define LPASS_CLK_ID_PRI_MI2S_EBIT 2
......
...@@ -437,6 +437,87 @@ enum rk809_reg_id { ...@@ -437,6 +437,87 @@ enum rk809_reg_id {
#define RK817_RTC_COMP_LSB_REG 0x10 #define RK817_RTC_COMP_LSB_REG 0x10
#define RK817_RTC_COMP_MSB_REG 0x11 #define RK817_RTC_COMP_MSB_REG 0x11
/* RK817 Codec Registers */
#define RK817_CODEC_DTOP_VUCTL 0x12
#define RK817_CODEC_DTOP_VUCTIME 0x13
#define RK817_CODEC_DTOP_LPT_SRST 0x14
#define RK817_CODEC_DTOP_DIGEN_CLKE 0x15
#define RK817_CODEC_AREF_RTCFG0 0x16
#define RK817_CODEC_AREF_RTCFG1 0x17
#define RK817_CODEC_AADC_CFG0 0x18
#define RK817_CODEC_AADC_CFG1 0x19
#define RK817_CODEC_DADC_VOLL 0x1a
#define RK817_CODEC_DADC_VOLR 0x1b
#define RK817_CODEC_DADC_SR_ACL0 0x1e
#define RK817_CODEC_DADC_ALC1 0x1f
#define RK817_CODEC_DADC_ALC2 0x20
#define RK817_CODEC_DADC_NG 0x21
#define RK817_CODEC_DADC_HPF 0x22
#define RK817_CODEC_DADC_RVOLL 0x23
#define RK817_CODEC_DADC_RVOLR 0x24
#define RK817_CODEC_AMIC_CFG0 0x27
#define RK817_CODEC_AMIC_CFG1 0x28
#define RK817_CODEC_DMIC_PGA_GAIN 0x29
#define RK817_CODEC_DMIC_LMT1 0x2a
#define RK817_CODEC_DMIC_LMT2 0x2b
#define RK817_CODEC_DMIC_NG1 0x2c
#define RK817_CODEC_DMIC_NG2 0x2d
#define RK817_CODEC_ADAC_CFG0 0x2e
#define RK817_CODEC_ADAC_CFG1 0x2f
#define RK817_CODEC_DDAC_POPD_DACST 0x30
#define RK817_CODEC_DDAC_VOLL 0x31
#define RK817_CODEC_DDAC_VOLR 0x32
#define RK817_CODEC_DDAC_SR_LMT0 0x35
#define RK817_CODEC_DDAC_LMT1 0x36
#define RK817_CODEC_DDAC_LMT2 0x37
#define RK817_CODEC_DDAC_MUTE_MIXCTL 0x38
#define RK817_CODEC_DDAC_RVOLL 0x39
#define RK817_CODEC_DDAC_RVOLR 0x3a
#define RK817_CODEC_AHP_ANTI0 0x3b
#define RK817_CODEC_AHP_ANTI1 0x3c
#define RK817_CODEC_AHP_CFG0 0x3d
#define RK817_CODEC_AHP_CFG1 0x3e
#define RK817_CODEC_AHP_CP 0x3f
#define RK817_CODEC_ACLASSD_CFG1 0x40
#define RK817_CODEC_ACLASSD_CFG2 0x41
#define RK817_CODEC_APLL_CFG0 0x42
#define RK817_CODEC_APLL_CFG1 0x43
#define RK817_CODEC_APLL_CFG2 0x44
#define RK817_CODEC_APLL_CFG3 0x45
#define RK817_CODEC_APLL_CFG4 0x46
#define RK817_CODEC_APLL_CFG5 0x47
#define RK817_CODEC_DI2S_CKM 0x48
#define RK817_CODEC_DI2S_RSD 0x49
#define RK817_CODEC_DI2S_RXCR1 0x4a
#define RK817_CODEC_DI2S_RXCR2 0x4b
#define RK817_CODEC_DI2S_RXCMD_TSD 0x4c
#define RK817_CODEC_DI2S_TXCR1 0x4d
#define RK817_CODEC_DI2S_TXCR2 0x4e
#define RK817_CODEC_DI2S_TXCR3_TXCMD 0x4f
/* RK817_CODEC_DI2S_CKM */
#define RK817_I2S_MODE_MASK (0x1 << 0)
#define RK817_I2S_MODE_MST (0x1 << 0)
#define RK817_I2S_MODE_SLV (0x0 << 0)
/* RK817_CODEC_DDAC_MUTE_MIXCTL */
#define DACMT_MASK (0x1 << 0)
#define DACMT_ENABLE (0x1 << 0)
#define DACMT_DISABLE (0x0 << 0)
/* RK817_CODEC_DI2S_RXCR2 */
#define VDW_RX_24BITS (0x17)
#define VDW_RX_16BITS (0x0f)
/* RK817_CODEC_DI2S_TXCR2 */
#define VDW_TX_24BITS (0x17)
#define VDW_TX_16BITS (0x0f)
/* RK817_CODEC_AMIC_CFG0 */
#define MIC_DIFF_MASK (0x1 << 7)
#define MIC_DIFF_DIS (0x0 << 7)
#define MIC_DIFF_EN (0x1 << 7)
#define RK817_POWER_EN_REG(i) (0xb1 + (i)) #define RK817_POWER_EN_REG(i) (0xb1 + (i))
#define RK817_POWER_SLP_EN_REG(i) (0xb5 + (i)) #define RK817_POWER_SLP_EN_REG(i) (0xb5 + (i))
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#define WCD934X_EFUSE_SENSE_STATE_DEF 0x10 #define WCD934X_EFUSE_SENSE_STATE_DEF 0x10
#define WCD934X_EFUSE_SENSE_EN_MASK BIT(0) #define WCD934X_EFUSE_SENSE_EN_MASK BIT(0)
#define WCD934X_EFUSE_SENSE_ENABLE BIT(0) #define WCD934X_EFUSE_SENSE_ENABLE BIT(0)
#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT1 0x002a
#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT2 0x002b
#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT14 0x0037 #define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT14 0x0037
#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT15 0x0038 #define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT15 0x0038
#define WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS 0x0039 #define WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS 0x0039
...@@ -103,21 +105,58 @@ ...@@ -103,21 +105,58 @@
#define WCD934X_ANA_AMIC3 0x0610 #define WCD934X_ANA_AMIC3 0x0610
#define WCD934X_ANA_AMIC4 0x0611 #define WCD934X_ANA_AMIC4 0x0611
#define WCD934X_ANA_MBHC_MECH 0x0614 #define WCD934X_ANA_MBHC_MECH 0x0614
#define WCD934X_MBHC_L_DET_EN_MASK BIT(7)
#define WCD934X_MBHC_L_DET_EN BIT(7)
#define WCD934X_MBHC_GND_DET_EN_MASK BIT(6)
#define WCD934X_MBHC_MECH_DETECT_TYPE_MASK BIT(5)
#define WCD934X_MBHC_MECH_DETECT_TYPE_INS 1
#define WCD934X_MBHC_HPHL_PLUG_TYPE_MASK BIT(4)
#define WCD934X_MBHC_HPHL_PLUG_TYPE_NO 1
#define WCD934X_MBHC_GND_PLUG_TYPE_MASK BIT(3)
#define WCD934X_MBHC_GND_PLUG_TYPE_NO 1
#define WCD934X_MBHC_HSL_PULLUP_COMP_EN BIT(2)
#define WCD934X_MBHC_HSG_PULLUP_COMP_EN BIT(1)
#define WCD934X_MBHC_HPHL_100K_TO_GND_EN BIT(0)
#define WCD934X_ANA_MBHC_ELECT 0x0615 #define WCD934X_ANA_MBHC_ELECT 0x0615
#define WCD934X_ANA_MBHC_BIAS_EN_MASK BIT(0)
#define WCD934X_ANA_MBHC_BIAS_EN BIT(0)
#define WCD934X_ANA_MBHC_ZDET 0x0616 #define WCD934X_ANA_MBHC_ZDET 0x0616
#define WCD934X_ANA_MBHC_RESULT_1 0x0617 #define WCD934X_ANA_MBHC_RESULT_1 0x0617
#define WCD934X_ANA_MBHC_RESULT_2 0x0618 #define WCD934X_ANA_MBHC_RESULT_2 0x0618
#define WCD934X_ANA_MBHC_RESULT_3 0x0619 #define WCD934X_ANA_MBHC_RESULT_3 0x0619
#define WCD934X_ANA_MBHC_BTN0 0x061a
#define WCD934X_VTH_MASK GENMASK(7, 2)
#define WCD934X_ANA_MBHC_BTN1 0x061b
#define WCD934X_ANA_MBHC_BTN2 0x061c
#define WCD934X_ANA_MBHC_BTN3 0x061d
#define WCD934X_ANA_MBHC_BTN4 0x061e
#define WCD934X_ANA_MBHC_BTN5 0x061f
#define WCD934X_ANA_MBHC_BTN6 0x0620
#define WCD934X_ANA_MBHC_BTN7 0x0621
#define WCD934X_MBHC_BTN_VTH_MASK GENMASK(7, 2)
#define WCD934X_ANA_MICB1 0x0622 #define WCD934X_ANA_MICB1 0x0622
#define WCD934X_MICB_VAL_MASK GENMASK(5, 0) #define WCD934X_MICB_VAL_MASK GENMASK(5, 0)
#define WCD934X_ANA_MICB_EN_MASK GENMASK(7, 6) #define WCD934X_ANA_MICB_EN_MASK GENMASK(7, 6)
#define WCD934X_MICB_DISABLE 0
#define WCD934X_MICB_ENABLE 1
#define WCD934X_MICB_PULL_UP 2
#define WCD934X_MICB_PULL_DOWN 3
#define WCD934X_ANA_MICB_PULL_UP 0x80 #define WCD934X_ANA_MICB_PULL_UP 0x80
#define WCD934X_ANA_MICB_ENABLE 0x40 #define WCD934X_ANA_MICB_ENABLE 0x40
#define WCD934X_ANA_MICB_DISABLE 0x0 #define WCD934X_ANA_MICB_DISABLE 0x0
#define WCD934X_ANA_MICB2 0x0623 #define WCD934X_ANA_MICB2 0x0623
#define WCD934X_ANA_MICB2_ENABLE BIT(6)
#define WCD934X_ANA_MICB2_ENABLE_MASK GENMASK(7, 6)
#define WCD934X_ANA_MICB2_VOUT_MASK GENMASK(5, 0)
#define WCD934X_ANA_MICB2_RAMP 0x0624
#define WCD934X_RAMP_EN_MASK BIT(7)
#define WCD934X_RAMP_SHIFT_CTRL_MASK GENMASK(4, 2)
#define WCD934X_ANA_MICB3 0x0625 #define WCD934X_ANA_MICB3 0x0625
#define WCD934X_ANA_MICB4 0x0626 #define WCD934X_ANA_MICB4 0x0626
#define WCD934X_BIAS_VBG_FINE_ADJ 0x0629 #define WCD934X_BIAS_VBG_FINE_ADJ 0x0629
#define WCD934X_MBHC_CTL_CLK 0x0656
#define WCD934X_MBHC_CTL_BCS 0x065a
#define WCD934X_MBHC_STATUS_SPARE_1 0x065b
#define WCD934X_MICB1_TEST_CTL_1 0x066b #define WCD934X_MICB1_TEST_CTL_1 0x066b
#define WCD934X_MICB1_TEST_CTL_2 0x066c #define WCD934X_MICB1_TEST_CTL_2 0x066c
#define WCD934X_MICB2_TEST_CTL_1 0x066e #define WCD934X_MICB2_TEST_CTL_1 0x066e
...@@ -141,7 +180,11 @@ ...@@ -141,7 +180,11 @@
#define WCD934X_HPH_CNP_WG_CTL 0x06cc #define WCD934X_HPH_CNP_WG_CTL 0x06cc
#define WCD934X_HPH_GM3_BOOST_EN_MASK BIT(7) #define WCD934X_HPH_GM3_BOOST_EN_MASK BIT(7)
#define WCD934X_HPH_GM3_BOOST_ENABLE BIT(7) #define WCD934X_HPH_GM3_BOOST_ENABLE BIT(7)
#define WCD934X_HPH_CNP_WG_TIME 0x06cd
#define WCD934X_HPH_OCP_CTL 0x06ce #define WCD934X_HPH_OCP_CTL 0x06ce
#define WCD934X_HPH_PA_CTL2 0x06d2
#define WCD934X_HPHPA_GND_R_MASK BIT(6)
#define WCD934X_HPHPA_GND_L_MASK BIT(4)
#define WCD934X_HPH_L_EN 0x06d3 #define WCD934X_HPH_L_EN 0x06d3
#define WCD934X_HPH_GAIN_SRC_SEL_MASK BIT(5) #define WCD934X_HPH_GAIN_SRC_SEL_MASK BIT(5)
#define WCD934X_HPH_GAIN_SRC_SEL_COMPANDER 0 #define WCD934X_HPH_GAIN_SRC_SEL_COMPANDER 0
...@@ -152,6 +195,8 @@ ...@@ -152,6 +195,8 @@
#define WCD934X_HPH_OCP_DET_MASK BIT(0) #define WCD934X_HPH_OCP_DET_MASK BIT(0)
#define WCD934X_HPH_OCP_DET_ENABLE BIT(0) #define WCD934X_HPH_OCP_DET_ENABLE BIT(0)
#define WCD934X_HPH_OCP_DET_DISABLE 0 #define WCD934X_HPH_OCP_DET_DISABLE 0
#define WCD934X_HPH_R_ATEST 0x06d8
#define WCD934X_HPHPA_GND_OVR_MASK BIT(1)
#define WCD934X_DIFF_LO_LO2_COMPANDER 0x06ea #define WCD934X_DIFF_LO_LO2_COMPANDER 0x06ea
#define WCD934X_DIFF_LO_LO1_COMPANDER 0x06eb #define WCD934X_DIFF_LO_LO1_COMPANDER 0x06eb
#define WCD934X_CLK_SYS_MCLK_PRG 0x0711 #define WCD934X_CLK_SYS_MCLK_PRG 0x0711
...@@ -172,7 +217,19 @@ ...@@ -172,7 +217,19 @@
#define WCD934X_SIDO_NEW_VOUT_D_FREQ2 0x071e #define WCD934X_SIDO_NEW_VOUT_D_FREQ2 0x071e
#define WCD934X_SIDO_RIPPLE_FREQ_EN_MASK BIT(0) #define WCD934X_SIDO_RIPPLE_FREQ_EN_MASK BIT(0)
#define WCD934X_SIDO_RIPPLE_FREQ_ENABLE BIT(0) #define WCD934X_SIDO_RIPPLE_FREQ_ENABLE BIT(0)
#define WCD934X_MBHC_NEW_CTL_1 0x0720
#define WCD934X_MBHC_CTL_RCO_EN_MASK BIT(7)
#define WCD935X_MBHC_CTL_RCO_EN BIT(7)
#define WCD934X_MBHC_NEW_CTL_2 0x0721 #define WCD934X_MBHC_NEW_CTL_2 0x0721
#define WCD934X_M_RTH_CTL_MASK GENMASK(3, 2)
#define WCD934X_MBHC_NEW_PLUG_DETECT_CTL 0x0722
#define WCD934X_HSDET_PULLUP_C_MASK GENMASK(7, 6)
#define WCD934X_MBHC_NEW_ZDET_ANA_CTL 0x0723
#define WCD934X_ZDET_RANGE_CTL_MASK GENMASK(3, 0)
#define WCD934X_ZDET_MAXV_CTL_MASK GENMASK(6, 4)
#define WCD934X_MBHC_NEW_ZDET_RAMP_CTL 0x0724
#define WCD934X_MBHC_NEW_FSM_STATUS 0x0725
#define WCD934X_MBHC_NEW_ADC_RESULT 0x0726
#define WCD934X_TX_NEW_AMIC_4_5_SEL 0x0727 #define WCD934X_TX_NEW_AMIC_4_5_SEL 0x0727
#define WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L 0x0733 #define WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L 0x0733
#define WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL 0x0735 #define WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL 0x0735
......
...@@ -1041,6 +1041,9 @@ int sdw_write_no_pm(struct sdw_slave *slave, u32 addr, u8 value); ...@@ -1041,6 +1041,9 @@ int sdw_write_no_pm(struct sdw_slave *slave, u32 addr, u8 value);
int sdw_read_no_pm(struct sdw_slave *slave, u32 addr); int sdw_read_no_pm(struct sdw_slave *slave, u32 addr);
int sdw_nread(struct sdw_slave *slave, u32 addr, size_t count, u8 *val); int sdw_nread(struct sdw_slave *slave, u32 addr, size_t count, u8 *val);
int sdw_nwrite(struct sdw_slave *slave, u32 addr, size_t count, u8 *val); int sdw_nwrite(struct sdw_slave *slave, u32 addr, size_t count, u8 *val);
int sdw_update(struct sdw_slave *slave, u32 addr, u8 mask, u8 val);
int sdw_update_no_pm(struct sdw_slave *slave, u32 addr, u8 mask, u8 val);
int sdw_compare_devid(struct sdw_slave *slave, struct sdw_slave_id id); int sdw_compare_devid(struct sdw_slave *slave, struct sdw_slave_id id);
void sdw_extract_slave_id(struct sdw_bus *bus, u64 addr, struct sdw_slave_id *id); void sdw_extract_slave_id(struct sdw_bus *bus, u64 addr, struct sdw_slave_id *id);
......
...@@ -128,7 +128,9 @@ struct snd_card { ...@@ -128,7 +128,9 @@ struct snd_card {
#ifdef CONFIG_PM #ifdef CONFIG_PM
unsigned int power_state; /* power state */ unsigned int power_state; /* power state */
atomic_t power_ref;
wait_queue_head_t power_sleep; wait_queue_head_t power_sleep;
wait_queue_head_t power_ref_sleep;
#endif #endif
#if IS_ENABLED(CONFIG_SND_MIXER_OSS) #if IS_ENABLED(CONFIG_SND_MIXER_OSS)
...@@ -142,21 +144,61 @@ struct snd_card { ...@@ -142,21 +144,61 @@ struct snd_card {
#ifdef CONFIG_PM #ifdef CONFIG_PM
static inline unsigned int snd_power_get_state(struct snd_card *card) static inline unsigned int snd_power_get_state(struct snd_card *card)
{ {
return card->power_state; return READ_ONCE(card->power_state);
} }
static inline void snd_power_change_state(struct snd_card *card, unsigned int state) static inline void snd_power_change_state(struct snd_card *card, unsigned int state)
{ {
card->power_state = state; WRITE_ONCE(card->power_state, state);
wake_up(&card->power_sleep); wake_up(&card->power_sleep);
} }
/**
* snd_power_ref - Take the reference count for power control
* @card: sound card object
*
* The power_ref reference of the card is used for managing to block
* the snd_power_sync_ref() operation. This function increments the reference.
* The counterpart snd_power_unref() has to be called appropriately later.
*/
static inline void snd_power_ref(struct snd_card *card)
{
atomic_inc(&card->power_ref);
}
/**
* snd_power_unref - Release the reference count for power control
* @card: sound card object
*/
static inline void snd_power_unref(struct snd_card *card)
{
if (atomic_dec_and_test(&card->power_ref))
wake_up(&card->power_ref_sleep);
}
/**
* snd_power_sync_ref - wait until the card power_ref is freed
* @card: sound card object
*
* This function is used to synchronize with the pending power_ref being
* released.
*/
static inline void snd_power_sync_ref(struct snd_card *card)
{
wait_event(card->power_ref_sleep, !atomic_read(&card->power_ref));
}
/* init.c */ /* init.c */
int snd_power_wait(struct snd_card *card, unsigned int power_state); int snd_power_wait(struct snd_card *card);
int snd_power_ref_and_wait(struct snd_card *card);
#else /* ! CONFIG_PM */ #else /* ! CONFIG_PM */
static inline int snd_power_wait(struct snd_card *card, unsigned int state) { return 0; } static inline int snd_power_wait(struct snd_card *card) { return 0; }
static inline void snd_power_ref(struct snd_card *card) {}
static inline void snd_power_unref(struct snd_card *card) {}
static inline int snd_power_ref_and_wait(struct snd_card *card) { return 0; }
static inline void snd_power_sync_ref(struct snd_card *card) {}
#define snd_power_get_state(card) ({ (void)(card); SNDRV_CTL_POWER_D0; }) #define snd_power_get_state(card) ({ (void)(card); SNDRV_CTL_POWER_D0; })
#define snd_power_change_state(card, state) do { (void)(card); } while (0) #define snd_power_change_state(card, state) do { (void)(card); } while (0)
......
...@@ -65,12 +65,22 @@ struct hdmi_codec_ops { ...@@ -65,12 +65,22 @@ struct hdmi_codec_ops {
/* /*
* Configures HDMI-encoder for audio stream. * Configures HDMI-encoder for audio stream.
* Mandatory * Having either prepare or hw_params is mandatory.
*/ */
int (*hw_params)(struct device *dev, void *data, int (*hw_params)(struct device *dev, void *data,
struct hdmi_codec_daifmt *fmt, struct hdmi_codec_daifmt *fmt,
struct hdmi_codec_params *hparms); struct hdmi_codec_params *hparms);
/*
* Configures HDMI-encoder for audio stream. Can be called
* multiple times for each setup.
*
* Having either prepare or hw_params is mandatory.
*/
int (*prepare)(struct device *dev, void *data,
struct hdmi_codec_daifmt *fmt,
struct hdmi_codec_params *hparms);
/* /*
* Shuts down the audio stream. * Shuts down the audio stream.
* Mandatory * Mandatory
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <asm/page.h> #include <asm/page.h>
struct device; struct device;
struct vm_area_struct;
/* /*
* buffer device info * buffer device info
...@@ -64,84 +65,19 @@ static inline unsigned int snd_sgbuf_aligned_pages(size_t size) ...@@ -64,84 +65,19 @@ static inline unsigned int snd_sgbuf_aligned_pages(size_t size)
return (size + PAGE_SIZE - 1) >> PAGE_SHIFT; return (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
} }
#ifdef CONFIG_SND_DMA_SGBUF
/*
* Scatter-Gather generic device pages
*/
void *snd_malloc_sgbuf_pages(struct device *device,
size_t size, struct snd_dma_buffer *dmab,
size_t *res_size);
int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab);
struct snd_sg_page {
void *buf;
dma_addr_t addr;
};
struct snd_sg_buf {
int size; /* allocated byte size */
int pages; /* allocated pages */
int tblsize; /* allocated table size */
struct snd_sg_page *table; /* address table */
struct page **page_table; /* page table (for vmap/vunmap) */
struct device *dev;
};
/*
* return the physical address at the corresponding offset
*/
static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab,
size_t offset)
{
struct snd_sg_buf *sgbuf = dmab->private_data;
dma_addr_t addr;
if (!sgbuf)
return dmab->addr + offset;
addr = sgbuf->table[offset >> PAGE_SHIFT].addr;
addr &= ~((dma_addr_t)PAGE_SIZE - 1);
return addr + offset % PAGE_SIZE;
}
/*
* return the virtual address at the corresponding offset
*/
static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab,
size_t offset)
{
struct snd_sg_buf *sgbuf = dmab->private_data;
if (!sgbuf)
return dmab->area + offset;
return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE;
}
unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
unsigned int ofs, unsigned int size);
#else
/* non-SG versions */
static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab,
size_t offset)
{
return dmab->addr + offset;
}
static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab,
size_t offset)
{
return dmab->area + offset;
}
#define snd_sgbuf_get_chunk_size(dmab, ofs, size) (size)
#endif /* CONFIG_SND_DMA_SGBUF */
/* allocate/release a buffer */ /* allocate/release a buffer */
int snd_dma_alloc_pages(int type, struct device *dev, size_t size, int snd_dma_alloc_pages(int type, struct device *dev, size_t size,
struct snd_dma_buffer *dmab); struct snd_dma_buffer *dmab);
int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size, int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size,
struct snd_dma_buffer *dmab); struct snd_dma_buffer *dmab);
void snd_dma_free_pages(struct snd_dma_buffer *dmab); void snd_dma_free_pages(struct snd_dma_buffer *dmab);
int snd_dma_buffer_mmap(struct snd_dma_buffer *dmab,
struct vm_area_struct *area);
dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab, size_t offset);
struct page *snd_sgbuf_get_page(struct snd_dma_buffer *dmab, size_t offset);
unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
unsigned int ofs, unsigned int size);
#endif /* __SOUND_MEMALLOC_H */ #endif /* __SOUND_MEMALLOC_H */
...@@ -1066,6 +1066,7 @@ void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, ...@@ -1066,6 +1066,7 @@ void snd_pcm_set_ops(struct snd_pcm * pcm, int direction,
void snd_pcm_set_sync(struct snd_pcm_substream *substream); void snd_pcm_set_sync(struct snd_pcm_substream *substream);
int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg); unsigned int cmd, void *arg);
void snd_pcm_period_elapsed_under_stream_lock(struct snd_pcm_substream *substream);
void snd_pcm_period_elapsed(struct snd_pcm_substream *substream); void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
void *buf, bool interleaved, void *buf, bool interleaved,
...@@ -1253,14 +1254,6 @@ static inline int snd_pcm_lib_alloc_vmalloc_32_buffer ...@@ -1253,14 +1254,6 @@ static inline int snd_pcm_lib_alloc_vmalloc_32_buffer
#define snd_pcm_get_dma_buf(substream) ((substream)->runtime->dma_buffer_p) #define snd_pcm_get_dma_buf(substream) ((substream)->runtime->dma_buffer_p)
#ifdef CONFIG_SND_DMA_SGBUF
/*
* SG-buffer handling
*/
#define snd_pcm_substream_sgbuf(substream) \
snd_pcm_get_dma_buf(substream)->private_data
#endif /* SND_DMA_SGBUF */
/** /**
* snd_pcm_sgbuf_get_addr - Get the DMA address at the corresponding offset * snd_pcm_sgbuf_get_addr - Get the DMA address at the corresponding offset
* @substream: PCM substream * @substream: PCM substream
...@@ -1272,17 +1265,6 @@ snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs) ...@@ -1272,17 +1265,6 @@ snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs)
return snd_sgbuf_get_addr(snd_pcm_get_dma_buf(substream), ofs); return snd_sgbuf_get_addr(snd_pcm_get_dma_buf(substream), ofs);
} }
/**
* snd_pcm_sgbuf_get_ptr - Get the virtual address at the corresponding offset
* @substream: PCM substream
* @ofs: byte offset
*/
static inline void *
snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs)
{
return snd_sgbuf_get_ptr(snd_pcm_get_dma_buf(substream), ofs);
}
/** /**
* snd_pcm_sgbuf_get_chunk_size - Compute the max size that fits within the * snd_pcm_sgbuf_get_chunk_size - Compute the max size that fits within the
* contig. page from the given size * contig. page from the given size
......
...@@ -4,6 +4,14 @@ ...@@ -4,6 +4,14 @@
#include <linux/types.h> #include <linux/types.h>
int snd_pcm_create_iec958_consumer_default(u8 *cs, size_t len);
int snd_pcm_fill_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
size_t len);
int snd_pcm_fill_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
u8 *cs, size_t len);
int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
size_t len); size_t len);
......
...@@ -81,6 +81,8 @@ struct snd_rawmidi_substream { ...@@ -81,6 +81,8 @@ struct snd_rawmidi_substream {
bool opened; /* open flag */ bool opened; /* open flag */
bool append; /* append flag (merge more streams) */ bool append; /* append flag (merge more streams) */
bool active_sensing; /* send active sensing when close */ bool active_sensing; /* send active sensing when close */
unsigned int framing; /* whether to frame input data */
unsigned int clock_type; /* clock source to use for input framing */
int use_count; /* use counter (for output) */ int use_count; /* use counter (for output) */
size_t bytes; size_t bytes;
struct snd_rawmidi *rmidi; struct snd_rawmidi *rmidi;
......
...@@ -36,6 +36,22 @@ struct snd_compr_stream; ...@@ -36,6 +36,22 @@ struct snd_compr_stream;
#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J #define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
#define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J #define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J
/* Describes the possible PCM format */
/*
* use SND_SOC_DAI_FORMAT_xx as eash shift.
* see
* snd_soc_runtime_get_dai_fmt()
*/
#define SND_SOC_POSSIBLE_DAIFMT_FORMAT_SHIFT 0
#define SND_SOC_POSSIBLE_DAIFMT_FORMAT_MASK (0xFFFF << SND_SOC_POSSIBLE_DAIFMT_FORMAT_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_I2S (1 << SND_SOC_DAI_FORMAT_I2S)
#define SND_SOC_POSSIBLE_DAIFMT_RIGHT_J (1 << SND_SOC_DAI_FORMAT_RIGHT_J)
#define SND_SOC_POSSIBLE_DAIFMT_LEFT_J (1 << SND_SOC_DAI_FORMAT_LEFT_J)
#define SND_SOC_POSSIBLE_DAIFMT_DSP_A (1 << SND_SOC_DAI_FORMAT_DSP_A)
#define SND_SOC_POSSIBLE_DAIFMT_DSP_B (1 << SND_SOC_DAI_FORMAT_DSP_B)
#define SND_SOC_POSSIBLE_DAIFMT_AC97 (1 << SND_SOC_DAI_FORMAT_AC97)
#define SND_SOC_POSSIBLE_DAIFMT_PDM (1 << SND_SOC_DAI_FORMAT_PDM)
/* /*
* DAI Clock gating. * DAI Clock gating.
* *
...@@ -45,6 +61,17 @@ struct snd_compr_stream; ...@@ -45,6 +61,17 @@ struct snd_compr_stream;
#define SND_SOC_DAIFMT_CONT (1 << 4) /* continuous clock */ #define SND_SOC_DAIFMT_CONT (1 << 4) /* continuous clock */
#define SND_SOC_DAIFMT_GATED (0 << 4) /* clock is gated */ #define SND_SOC_DAIFMT_GATED (0 << 4) /* clock is gated */
/* Describes the possible PCM format */
/*
* define GATED -> CONT. GATED will be selected if both are selected.
* see
* snd_soc_runtime_get_dai_fmt()
*/
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT 16
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_MASK (0xFFFF << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_GATED (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_CONT (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
/* /*
* DAI hardware signal polarity. * DAI hardware signal polarity.
* *
...@@ -71,6 +98,14 @@ struct snd_compr_stream; ...@@ -71,6 +98,14 @@ struct snd_compr_stream;
#define SND_SOC_DAIFMT_IB_NF (3 << 8) /* invert BCLK + nor FRM */ #define SND_SOC_DAIFMT_IB_NF (3 << 8) /* invert BCLK + nor FRM */
#define SND_SOC_DAIFMT_IB_IF (4 << 8) /* invert BCLK + FRM */ #define SND_SOC_DAIFMT_IB_IF (4 << 8) /* invert BCLK + FRM */
/* Describes the possible PCM format */
#define SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT 32
#define SND_SOC_POSSIBLE_DAIFMT_INV_MASK (0xFFFFULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_NB_NF (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_NB_IF (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_IB_NF (0x4ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_IB_IF (0x8ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
/* /*
* DAI hardware clock providers/consumers * DAI hardware clock providers/consumers
* *
...@@ -89,6 +124,14 @@ struct snd_compr_stream; ...@@ -89,6 +124,14 @@ struct snd_compr_stream;
#define SND_SOC_DAIFMT_CBM_CFS SND_SOC_DAIFMT_CBP_CFC #define SND_SOC_DAIFMT_CBM_CFS SND_SOC_DAIFMT_CBP_CFC
#define SND_SOC_DAIFMT_CBS_CFS SND_SOC_DAIFMT_CBC_CFC #define SND_SOC_DAIFMT_CBS_CFS SND_SOC_DAIFMT_CBC_CFC
/* Describes the possible PCM format */
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT 48
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_MASK (0xFFFFULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_CBP_CFP (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_CBC_CFP (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_CBP_CFC (0x4ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_CBC_CFC (0x8ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f #define SND_SOC_DAIFMT_FORMAT_MASK 0x000f
#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0 #define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0
#define SND_SOC_DAIFMT_INV_MASK 0x0f00 #define SND_SOC_DAIFMT_INV_MASK 0x0f00
...@@ -131,6 +174,8 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai, ...@@ -131,6 +174,8 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio); int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio);
/* Digital Audio interface formatting */ /* Digital Audio interface formatting */
int snd_soc_dai_get_fmt_max_priority(struct snd_soc_pcm_runtime *rtd);
u64 snd_soc_dai_get_fmt(struct snd_soc_dai *dai, int priority);
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt); int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
...@@ -292,6 +337,16 @@ struct snd_soc_dai_ops { ...@@ -292,6 +337,16 @@ struct snd_soc_dai_ops {
snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *, snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
struct snd_soc_dai *); struct snd_soc_dai *);
/*
* Format list for auto selection.
* Format will be increased if priority format was
* not selected.
* see
* snd_soc_dai_get_fmt()
*/
u64 *auto_selectable_formats;
int num_auto_selectable_formats;
/* bit field */ /* bit field */
unsigned int no_capture_mute:1; unsigned int no_capture_mute:1;
}; };
......
...@@ -54,7 +54,7 @@ struct snd_soc_dobj_control { ...@@ -54,7 +54,7 @@ struct snd_soc_dobj_control {
/* dynamic widget object */ /* dynamic widget object */
struct snd_soc_dobj_widget { struct snd_soc_dobj_widget {
unsigned int kcontrol_type; /* kcontrol type: mixer, enum, bytes */ unsigned int *kcontrol_type; /* kcontrol type: mixer, enum, bytes */
}; };
/* generic dynamic object - all dynamic objects belong to this struct */ /* generic dynamic object - all dynamic objects belong to this struct */
......
...@@ -1232,10 +1232,23 @@ void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card, ...@@ -1232,10 +1232,23 @@ void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
const char *propname); const char *propname);
int snd_soc_of_parse_aux_devs(struct snd_soc_card *card, const char *propname); int snd_soc_of_parse_aux_devs(struct snd_soc_card *card, const char *propname);
unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
const char *prefix, unsigned int snd_soc_daifmt_clock_provider_fliped(unsigned int dai_fmt);
struct device_node **bitclkmaster, unsigned int snd_soc_daifmt_clock_provider_from_bitmap(unsigned int bit_frame);
struct device_node **framemaster);
unsigned int snd_soc_daifmt_parse_format(struct device_node *np, const char *prefix);
unsigned int snd_soc_daifmt_parse_clock_provider_raw(struct device_node *np,
const char *prefix,
struct device_node **bitclkmaster,
struct device_node **framemaster);
#define snd_soc_daifmt_parse_clock_provider_as_bitmap(np, prefix) \
snd_soc_daifmt_parse_clock_provider_raw(np, prefix, NULL, NULL)
#define snd_soc_daifmt_parse_clock_provider_as_phandle \
snd_soc_daifmt_parse_clock_provider_raw
#define snd_soc_daifmt_parse_clock_provider_as_flag(np, prefix) \
snd_soc_daifmt_clock_provider_from_bitmap( \
snd_soc_daifmt_parse_clock_provider_as_bitmap(np, prefix))
int snd_soc_get_dai_id(struct device_node *ep); int snd_soc_get_dai_id(struct device_node *ep);
int snd_soc_get_dai_name(const struct of_phandle_args *args, int snd_soc_get_dai_name(const struct of_phandle_args *args,
const char **dai_name); const char **dai_name);
......
...@@ -710,7 +710,7 @@ enum { ...@@ -710,7 +710,7 @@ enum {
* Raw MIDI section - /dev/snd/midi?? * Raw MIDI section - /dev/snd/midi??
*/ */
#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 1) #define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 2)
enum { enum {
SNDRV_RAWMIDI_STREAM_OUTPUT = 0, SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
...@@ -736,12 +736,38 @@ struct snd_rawmidi_info { ...@@ -736,12 +736,38 @@ struct snd_rawmidi_info {
unsigned char reserved[64]; /* reserved for future use */ unsigned char reserved[64]; /* reserved for future use */
}; };
#define SNDRV_RAWMIDI_MODE_FRAMING_MASK (7<<0)
#define SNDRV_RAWMIDI_MODE_FRAMING_SHIFT 0
#define SNDRV_RAWMIDI_MODE_FRAMING_NONE (0<<0)
#define SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP (1<<0)
#define SNDRV_RAWMIDI_MODE_CLOCK_MASK (7<<3)
#define SNDRV_RAWMIDI_MODE_CLOCK_SHIFT 3
#define SNDRV_RAWMIDI_MODE_CLOCK_NONE (0<<3)
#define SNDRV_RAWMIDI_MODE_CLOCK_REALTIME (1<<3)
#define SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC (2<<3)
#define SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC_RAW (3<<3)
#define SNDRV_RAWMIDI_FRAMING_DATA_LENGTH 16
struct snd_rawmidi_framing_tstamp {
/* For now, frame_type is always 0. Midi 2.0 is expected to add new
* types here. Applications are expected to skip unknown frame types.
*/
__u8 frame_type;
__u8 length; /* number of valid bytes in data field */
__u8 reserved[2];
__u32 tv_nsec; /* nanoseconds */
__u64 tv_sec; /* seconds */
__u8 data[SNDRV_RAWMIDI_FRAMING_DATA_LENGTH];
} __packed;
struct snd_rawmidi_params { struct snd_rawmidi_params {
int stream; int stream;
size_t buffer_size; /* queue size in bytes */ size_t buffer_size; /* queue size in bytes */
size_t avail_min; /* minimum avail bytes for wakeup */ size_t avail_min; /* minimum avail bytes for wakeup */
unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */ unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */
unsigned char reserved[16]; /* reserved for future use */ unsigned int mode; /* For input data only, frame incoming data */
unsigned char reserved[12]; /* reserved for future use */
}; };
#ifndef __KERNEL__ #ifndef __KERNEL__
......
...@@ -520,7 +520,7 @@ static int ac97_bus_remove(struct device *dev) ...@@ -520,7 +520,7 @@ static int ac97_bus_remove(struct device *dev)
struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver); struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver);
int ret; int ret;
ret = pm_runtime_get_sync(dev); ret = pm_runtime_resume_and_get(dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -918,10 +918,8 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, ...@@ -918,10 +918,8 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
} }
cii = kzalloc(sizeof(struct codec_info_item), GFP_KERNEL); cii = kzalloc(sizeof(struct codec_info_item), GFP_KERNEL);
if (!cii) { if (!cii)
printk(KERN_DEBUG "i2sbus: failed to allocate cii\n");
return -ENOMEM; return -ENOMEM;
}
/* use the private data to point to the codec info */ /* use the private data to point to the codec info */
cii->sdev = soundbus_dev_get(dev); cii->sdev = soundbus_dev_get(dev);
......
...@@ -47,9 +47,7 @@ static unsigned short pxa2xx_ac97_legacy_read(struct snd_ac97 *ac97, ...@@ -47,9 +47,7 @@ static unsigned short pxa2xx_ac97_legacy_read(struct snd_ac97 *ac97,
static void pxa2xx_ac97_legacy_write(struct snd_ac97 *ac97, static void pxa2xx_ac97_legacy_write(struct snd_ac97 *ac97,
unsigned short reg, unsigned short val) unsigned short reg, unsigned short val)
{ {
int __always_unused ret; pxa2xx_ac97_write(ac97->num, reg, val);
ret = pxa2xx_ac97_write(ac97->num, reg, val);
} }
static const struct snd_ac97_bus_ops pxa2xx_ac97_ops = { static const struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
......
...@@ -995,7 +995,10 @@ static int __snd_ctl_elem_info(struct snd_card *card, ...@@ -995,7 +995,10 @@ static int __snd_ctl_elem_info(struct snd_card *card,
#ifdef CONFIG_SND_DEBUG #ifdef CONFIG_SND_DEBUG
info->access = 0; info->access = 0;
#endif #endif
result = kctl->info(kctl, info); result = snd_power_ref_and_wait(card);
if (!result)
result = kctl->info(kctl, info);
snd_power_unref(card);
if (result >= 0) { if (result >= 0) {
snd_BUG_ON(info->access); snd_BUG_ON(info->access);
index_offset = snd_ctl_get_ioff(kctl, &info->id); index_offset = snd_ctl_get_ioff(kctl, &info->id);
...@@ -1042,9 +1045,6 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl, ...@@ -1042,9 +1045,6 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
if (copy_from_user(&info, _info, sizeof(info))) if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT; return -EFAULT;
result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
if (result < 0)
return result;
result = snd_ctl_elem_info(ctl, &info); result = snd_ctl_elem_info(ctl, &info);
if (result < 0) if (result < 0)
return result; return result;
...@@ -1088,7 +1088,10 @@ static int snd_ctl_elem_read(struct snd_card *card, ...@@ -1088,7 +1088,10 @@ static int snd_ctl_elem_read(struct snd_card *card,
if (!snd_ctl_skip_validation(&info)) if (!snd_ctl_skip_validation(&info))
fill_remaining_elem_value(control, &info, pattern); fill_remaining_elem_value(control, &info, pattern);
ret = kctl->get(kctl, control); ret = snd_power_ref_and_wait(card);
if (!ret)
ret = kctl->get(kctl, control);
snd_power_unref(card);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!snd_ctl_skip_validation(&info) && if (!snd_ctl_skip_validation(&info) &&
...@@ -1113,10 +1116,6 @@ static int snd_ctl_elem_read_user(struct snd_card *card, ...@@ -1113,10 +1116,6 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
if (IS_ERR(control)) if (IS_ERR(control))
return PTR_ERR(control); return PTR_ERR(control);
result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (result < 0)
goto error;
down_read(&card->controls_rwsem); down_read(&card->controls_rwsem);
result = snd_ctl_elem_read(card, control); result = snd_ctl_elem_read(card, control);
up_read(&card->controls_rwsem); up_read(&card->controls_rwsem);
...@@ -1154,7 +1153,10 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, ...@@ -1154,7 +1153,10 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
} }
snd_ctl_build_ioff(&control->id, kctl, index_offset); snd_ctl_build_ioff(&control->id, kctl, index_offset);
result = kctl->put(kctl, control); result = snd_power_ref_and_wait(card);
if (!result)
result = kctl->put(kctl, control);
snd_power_unref(card);
if (result < 0) { if (result < 0) {
up_write(&card->controls_rwsem); up_write(&card->controls_rwsem);
return result; return result;
...@@ -1183,10 +1185,6 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file, ...@@ -1183,10 +1185,6 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
return PTR_ERR(control); return PTR_ERR(control);
card = file->card; card = file->card;
result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (result < 0)
goto error;
result = snd_ctl_elem_write(card, file, control); result = snd_ctl_elem_write(card, file, control);
if (result < 0) if (result < 0)
goto error; goto error;
...@@ -1669,7 +1667,7 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag, ...@@ -1669,7 +1667,7 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
{SNDRV_CTL_TLV_OP_CMD, SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND}, {SNDRV_CTL_TLV_OP_CMD, SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND},
}; };
struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)]; struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)];
int i; int i, ret;
/* Check support of the request for this element. */ /* Check support of the request for this element. */
for (i = 0; i < ARRAY_SIZE(pairs); ++i) { for (i = 0; i < ARRAY_SIZE(pairs); ++i) {
...@@ -1687,7 +1685,11 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag, ...@@ -1687,7 +1685,11 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
vd->owner != NULL && vd->owner != file) vd->owner != NULL && vd->owner != file)
return -EPERM; return -EPERM;
return kctl->tlv.c(kctl, op_flag, size, buf); ret = snd_power_ref_and_wait(file->card);
if (!ret)
ret = kctl->tlv.c(kctl, op_flag, size, buf);
snd_power_unref(file->card);
return ret;
} }
static int read_tlv_buf(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id, static int read_tlv_buf(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id,
...@@ -1815,11 +1817,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg ...@@ -1815,11 +1817,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
case SNDRV_CTL_IOCTL_POWER: case SNDRV_CTL_IOCTL_POWER:
return -ENOPROTOOPT; return -ENOPROTOOPT;
case SNDRV_CTL_IOCTL_POWER_STATE: case SNDRV_CTL_IOCTL_POWER_STATE:
#ifdef CONFIG_PM
return put_user(card->power_state, ip) ? -EFAULT : 0;
#else
return put_user(SNDRV_CTL_POWER_D0, ip) ? -EFAULT : 0; return put_user(SNDRV_CTL_POWER_D0, ip) ? -EFAULT : 0;
#endif
} }
down_read(&snd_ioctl_rwsem); down_read(&snd_ioctl_rwsem);
list_for_each_entry(p, &snd_control_ioctls, list) { list_for_each_entry(p, &snd_control_ioctls, list) {
......
...@@ -96,9 +96,6 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl, ...@@ -96,9 +96,6 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
if (get_user(data->value.enumerated.item, &data32->value.enumerated.item)) if (get_user(data->value.enumerated.item, &data32->value.enumerated.item))
goto error; goto error;
err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
if (err < 0)
goto error;
err = snd_ctl_elem_info(ctl, data); err = snd_ctl_elem_info(ctl, data);
if (err < 0) if (err < 0)
goto error; goto error;
...@@ -187,7 +184,10 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, ...@@ -187,7 +184,10 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
return -ENOMEM; return -ENOMEM;
} }
info->id = *id; info->id = *id;
err = kctl->info(kctl, info); err = snd_power_ref_and_wait(card);
if (!err)
err = kctl->info(kctl, info);
snd_power_unref(card);
up_read(&card->controls_rwsem); up_read(&card->controls_rwsem);
if (err >= 0) { if (err >= 0) {
err = info->type; err = info->type;
...@@ -298,9 +298,6 @@ static int ctl_elem_read_user(struct snd_card *card, ...@@ -298,9 +298,6 @@ static int ctl_elem_read_user(struct snd_card *card,
if (err < 0) if (err < 0)
goto error; goto error;
err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (err < 0)
goto error;
err = snd_ctl_elem_read(card, data); err = snd_ctl_elem_read(card, data);
if (err < 0) if (err < 0)
goto error; goto error;
...@@ -326,9 +323,6 @@ static int ctl_elem_write_user(struct snd_ctl_file *file, ...@@ -326,9 +323,6 @@ static int ctl_elem_write_user(struct snd_ctl_file *file,
if (err < 0) if (err < 0)
goto error; goto error;
err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (err < 0)
goto error;
err = snd_ctl_elem_write(card, file, data); err = snd_ctl_elem_write(card, file, data);
if (err < 0) if (err < 0)
goto error; goto error;
......
...@@ -393,11 +393,11 @@ static void snd_ctl_led_dev_release(struct device *dev) ...@@ -393,11 +393,11 @@ static void snd_ctl_led_dev_release(struct device *dev)
* sysfs * sysfs
*/ */
static ssize_t show_mode(struct device *dev, static ssize_t mode_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev); struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev);
const char *str; const char *str = NULL;
switch (led->mode) { switch (led->mode) {
case MODE_FOLLOW_MUTE: str = "follow-mute"; break; case MODE_FOLLOW_MUTE: str = "follow-mute"; break;
...@@ -408,7 +408,8 @@ static ssize_t show_mode(struct device *dev, ...@@ -408,7 +408,8 @@ static ssize_t show_mode(struct device *dev,
return sprintf(buf, "%s\n", str); return sprintf(buf, "%s\n", str);
} }
static ssize_t store_mode(struct device *dev, struct device_attribute *attr, static ssize_t mode_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev); struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev);
...@@ -437,7 +438,7 @@ static ssize_t store_mode(struct device *dev, struct device_attribute *attr, ...@@ -437,7 +438,7 @@ static ssize_t store_mode(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
static ssize_t show_brightness(struct device *dev, static ssize_t brightness_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev); struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev);
...@@ -445,8 +446,8 @@ static ssize_t show_brightness(struct device *dev, ...@@ -445,8 +446,8 @@ static ssize_t show_brightness(struct device *dev,
return sprintf(buf, "%u\n", ledtrig_audio_get(led->trigger_type)); return sprintf(buf, "%u\n", ledtrig_audio_get(led->trigger_type));
} }
static DEVICE_ATTR(mode, 0644, show_mode, store_mode); static DEVICE_ATTR_RW(mode);
static DEVICE_ATTR(brightness, 0444, show_brightness, NULL); static DEVICE_ATTR_RO(brightness);
static struct attribute *snd_ctl_led_dev_attrs[] = { static struct attribute *snd_ctl_led_dev_attrs[] = {
&dev_attr_mode.attr, &dev_attr_mode.attr,
...@@ -580,22 +581,25 @@ static ssize_t set_led_id(struct snd_ctl_led_card *led_card, const char *buf, si ...@@ -580,22 +581,25 @@ static ssize_t set_led_id(struct snd_ctl_led_card *led_card, const char *buf, si
return count; return count;
} }
static ssize_t parse_attach(struct device *dev, struct device_attribute *attr, static ssize_t attach_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev); struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
return set_led_id(led_card, buf, count, true); return set_led_id(led_card, buf, count, true);
} }
static ssize_t parse_detach(struct device *dev, struct device_attribute *attr, static ssize_t detach_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev); struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
return set_led_id(led_card, buf, count, false); return set_led_id(led_card, buf, count, false);
} }
static ssize_t ctl_reset(struct device *dev, struct device_attribute *attr, static ssize_t reset_store(struct device *dev,
const char *buf, size_t count) struct device_attribute *attr,
const char *buf, size_t count)
{ {
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev); struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
int err; int err;
...@@ -608,8 +612,8 @@ static ssize_t ctl_reset(struct device *dev, struct device_attribute *attr, ...@@ -608,8 +612,8 @@ static ssize_t ctl_reset(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
static ssize_t ctl_list(struct device *dev, static ssize_t list_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev); struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
struct snd_card *card; struct snd_card *card;
...@@ -642,10 +646,10 @@ static ssize_t ctl_list(struct device *dev, ...@@ -642,10 +646,10 @@ static ssize_t ctl_list(struct device *dev,
return buf2 - buf; return buf2 - buf;
} }
static DEVICE_ATTR(attach, 0200, NULL, parse_attach); static DEVICE_ATTR_WO(attach);
static DEVICE_ATTR(detach, 0200, NULL, parse_detach); static DEVICE_ATTR_WO(detach);
static DEVICE_ATTR(reset, 0200, NULL, ctl_reset); static DEVICE_ATTR_WO(reset);
static DEVICE_ATTR(list, 0444, ctl_list, NULL); static DEVICE_ATTR_RO(list);
static struct attribute *snd_ctl_led_card_attrs[] = { static struct attribute *snd_ctl_led_card_attrs[] = {
&dev_attr_attach.attr, &dev_attr_attach.attr,
......
...@@ -195,7 +195,8 @@ static int snd_hwdep_dsp_status(struct snd_hwdep *hw, ...@@ -195,7 +195,8 @@ static int snd_hwdep_dsp_status(struct snd_hwdep *hw,
return -ENXIO; return -ENXIO;
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
info.dsp_loaded = hw->dsp_loaded; info.dsp_loaded = hw->dsp_loaded;
if ((err = hw->ops.dsp_status(hw, &info)) < 0) err = hw->ops.dsp_status(hw, &info);
if (err < 0)
return err; return err;
if (copy_to_user(_info, &info, sizeof(info))) if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT; return -EFAULT;
...@@ -500,7 +501,8 @@ static void __init snd_hwdep_proc_init(void) ...@@ -500,7 +501,8 @@ static void __init snd_hwdep_proc_init(void)
{ {
struct snd_info_entry *entry; struct snd_info_entry *entry;
if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) { entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL);
if (entry) {
entry->c.text.read = snd_hwdep_proc_read; entry->c.text.read = snd_hwdep_proc_read;
if (snd_info_register(entry) < 0) { if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry); snd_info_free_entry(entry);
......
...@@ -31,7 +31,8 @@ int snd_oss_info_register(int dev, int num, char *string) ...@@ -31,7 +31,8 @@ int snd_oss_info_register(int dev, int num, char *string)
return -ENXIO; return -ENXIO;
mutex_lock(&strings); mutex_lock(&strings);
if (string == NULL) { if (string == NULL) {
if ((x = snd_sndstat_strings[num][dev]) != NULL) { x = snd_sndstat_strings[num][dev];
if (x) {
kfree(x); kfree(x);
x = NULL; x = NULL;
} }
......
...@@ -220,6 +220,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid, ...@@ -220,6 +220,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
mutex_init(&card->memory_mutex); mutex_init(&card->memory_mutex);
#ifdef CONFIG_PM #ifdef CONFIG_PM
init_waitqueue_head(&card->power_sleep); init_waitqueue_head(&card->power_sleep);
init_waitqueue_head(&card->power_ref_sleep);
atomic_set(&card->power_ref, 0);
#endif #endif
init_waitqueue_head(&card->remove_sleep); init_waitqueue_head(&card->remove_sleep);
card->sync_irq = -1; card->sync_irq = -1;
...@@ -442,6 +444,7 @@ int snd_card_disconnect(struct snd_card *card) ...@@ -442,6 +444,7 @@ int snd_card_disconnect(struct snd_card *card)
#ifdef CONFIG_PM #ifdef CONFIG_PM
wake_up(&card->power_sleep); wake_up(&card->power_sleep);
snd_power_sync_ref(card);
#endif #endif
return 0; return 0;
} }
...@@ -662,17 +665,15 @@ void snd_card_set_id(struct snd_card *card, const char *nid) ...@@ -662,17 +665,15 @@ void snd_card_set_id(struct snd_card *card, const char *nid)
} }
EXPORT_SYMBOL(snd_card_set_id); EXPORT_SYMBOL(snd_card_set_id);
static ssize_t static ssize_t id_show(struct device *dev,
card_id_show_attr(struct device *dev, struct device_attribute *attr, char *buf)
struct device_attribute *attr, char *buf)
{ {
struct snd_card *card = container_of(dev, struct snd_card, card_dev); struct snd_card *card = container_of(dev, struct snd_card, card_dev);
return scnprintf(buf, PAGE_SIZE, "%s\n", card->id); return scnprintf(buf, PAGE_SIZE, "%s\n", card->id);
} }
static ssize_t static ssize_t id_store(struct device *dev, struct device_attribute *attr,
card_id_store_attr(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
const char *buf, size_t count)
{ {
struct snd_card *card = container_of(dev, struct snd_card, card_dev); struct snd_card *card = container_of(dev, struct snd_card, card_dev);
char buf1[sizeof(card->id)]; char buf1[sizeof(card->id)];
...@@ -700,17 +701,16 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr, ...@@ -700,17 +701,16 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
static DEVICE_ATTR(id, 0644, card_id_show_attr, card_id_store_attr); static DEVICE_ATTR_RW(id);
static ssize_t static ssize_t number_show(struct device *dev,
card_number_show_attr(struct device *dev, struct device_attribute *attr, char *buf)
struct device_attribute *attr, char *buf)
{ {
struct snd_card *card = container_of(dev, struct snd_card, card_dev); struct snd_card *card = container_of(dev, struct snd_card, card_dev);
return scnprintf(buf, PAGE_SIZE, "%i\n", card->number); return scnprintf(buf, PAGE_SIZE, "%i\n", card->number);
} }
static DEVICE_ATTR(number, 0444, card_number_show_attr, NULL); static DEVICE_ATTR_RO(number);
static struct attribute *card_dev_attrs[] = { static struct attribute *card_dev_attrs[] = {
&dev_attr_id.attr, &dev_attr_id.attr,
...@@ -770,7 +770,8 @@ int snd_card_register(struct snd_card *card) ...@@ -770,7 +770,8 @@ int snd_card_register(struct snd_card *card)
card->registered = true; card->registered = true;
} }
if ((err = snd_device_register_all(card)) < 0) err = snd_device_register_all(card);
if (err < 0)
return err; return err;
mutex_lock(&snd_card_mutex); mutex_lock(&snd_card_mutex);
if (snd_cards[card->number]) { if (snd_cards[card->number]) {
...@@ -813,7 +814,8 @@ static void snd_card_info_read(struct snd_info_entry *entry, ...@@ -813,7 +814,8 @@ static void snd_card_info_read(struct snd_info_entry *entry,
for (idx = count = 0; idx < SNDRV_CARDS; idx++) { for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
mutex_lock(&snd_card_mutex); mutex_lock(&snd_card_mutex);
if ((card = snd_cards[idx]) != NULL) { card = snd_cards[idx];
if (card) {
count++; count++;
snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n", snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n",
idx, idx,
...@@ -837,7 +839,8 @@ void snd_card_info_read_oss(struct snd_info_buffer *buffer) ...@@ -837,7 +839,8 @@ void snd_card_info_read_oss(struct snd_info_buffer *buffer)
for (idx = count = 0; idx < SNDRV_CARDS; idx++) { for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
mutex_lock(&snd_card_mutex); mutex_lock(&snd_card_mutex);
if ((card = snd_cards[idx]) != NULL) { card = snd_cards[idx];
if (card) {
count++; count++;
snd_iprintf(buffer, "%s\n", card->longname); snd_iprintf(buffer, "%s\n", card->longname);
} }
...@@ -859,7 +862,8 @@ static void snd_card_module_info_read(struct snd_info_entry *entry, ...@@ -859,7 +862,8 @@ static void snd_card_module_info_read(struct snd_info_entry *entry,
for (idx = 0; idx < SNDRV_CARDS; idx++) { for (idx = 0; idx < SNDRV_CARDS; idx++) {
mutex_lock(&snd_card_mutex); mutex_lock(&snd_card_mutex);
if ((card = snd_cards[idx]) != NULL) card = snd_cards[idx];
if (card)
snd_iprintf(buffer, "%2i %s\n", snd_iprintf(buffer, "%2i %s\n",
idx, card->module->name); idx, card->module->name);
mutex_unlock(&snd_card_mutex); mutex_unlock(&snd_card_mutex);
...@@ -1002,21 +1006,28 @@ EXPORT_SYMBOL(snd_card_file_remove); ...@@ -1002,21 +1006,28 @@ EXPORT_SYMBOL(snd_card_file_remove);
#ifdef CONFIG_PM #ifdef CONFIG_PM
/** /**
* snd_power_wait - wait until the power-state is changed. * snd_power_ref_and_wait - wait until the card gets powered up
* @card: soundcard structure * @card: soundcard structure
* @power_state: expected power state *
* Take the power_ref reference count of the given card, and
* wait until the card gets powered up to SNDRV_CTL_POWER_D0 state.
* The refcount is down again while sleeping until power-up, hence this
* function can be used for syncing the floating control ops accesses,
* typically around calling control ops.
* *
* Waits until the power-state is changed. * The caller needs to pull down the refcount via snd_power_unref() later
* no matter whether the error is returned from this function or not.
* *
* Return: Zero if successful, or a negative error code. * Return: Zero if successful, or a negative error code.
*/ */
int snd_power_wait(struct snd_card *card, unsigned int power_state) int snd_power_ref_and_wait(struct snd_card *card)
{ {
wait_queue_entry_t wait; wait_queue_entry_t wait;
int result = 0; int result = 0;
snd_power_ref(card);
/* fastpath */ /* fastpath */
if (snd_power_get_state(card) == power_state) if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0)
return 0; return 0;
init_waitqueue_entry(&wait, current); init_waitqueue_entry(&wait, current);
add_wait_queue(&card->power_sleep, &wait); add_wait_queue(&card->power_sleep, &wait);
...@@ -1025,13 +1036,33 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state) ...@@ -1025,13 +1036,33 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state)
result = -ENODEV; result = -ENODEV;
break; break;
} }
if (snd_power_get_state(card) == power_state) if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0)
break; break;
snd_power_unref(card);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(30 * HZ); schedule_timeout(30 * HZ);
snd_power_ref(card);
} }
remove_wait_queue(&card->power_sleep, &wait); remove_wait_queue(&card->power_sleep, &wait);
return result; return result;
} }
EXPORT_SYMBOL_GPL(snd_power_ref_and_wait);
/**
* snd_power_wait - wait until the card gets powered up (old form)
* @card: soundcard structure
*
* Wait until the card gets powered up to SNDRV_CTL_POWER_D0 state.
*
* Return: Zero if successful, or a negative error code.
*/
int snd_power_wait(struct snd_card *card)
{
int ret;
ret = snd_power_ref_and_wait(card);
snd_power_unref(card);
return ret;
}
EXPORT_SYMBOL(snd_power_wait); EXPORT_SYMBOL(snd_power_wait);
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
...@@ -15,99 +15,27 @@ ...@@ -15,99 +15,27 @@
#include <asm/set_memory.h> #include <asm/set_memory.h>
#endif #endif
#include <sound/memalloc.h> #include <sound/memalloc.h>
#include "memalloc_local.h"
/* static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab);
*
* Bus-specific memory allocators
*
*/
#ifdef CONFIG_HAS_DMA
/* allocate the coherent DMA pages */
static void snd_malloc_dev_pages(struct snd_dma_buffer *dmab, size_t size)
{
gfp_t gfp_flags;
gfp_flags = GFP_KERNEL /* a cast to gfp flag from the dev pointer; for CONTINUOUS and VMALLOC types */
| __GFP_COMP /* compound page lets parts be mapped */ static inline gfp_t snd_mem_get_gfp_flags(const struct snd_dma_buffer *dmab,
| __GFP_NORETRY /* don't trigger OOM-killer */ gfp_t default_gfp)
| __GFP_NOWARN; /* no stack trace print - this call is non-critical */
dmab->area = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr,
gfp_flags);
#ifdef CONFIG_X86
if (dmab->area && dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC)
set_memory_wc((unsigned long)dmab->area,
PAGE_ALIGN(size) >> PAGE_SHIFT);
#endif
}
/* free the coherent DMA pages */
static void snd_free_dev_pages(struct snd_dma_buffer *dmab)
{
#ifdef CONFIG_X86
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC)
set_memory_wb((unsigned long)dmab->area,
PAGE_ALIGN(dmab->bytes) >> PAGE_SHIFT);
#endif
dma_free_coherent(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
}
#ifdef CONFIG_GENERIC_ALLOCATOR
/**
* snd_malloc_dev_iram - allocate memory from on-chip internal ram
* @dmab: buffer allocation record to store the allocated data
* @size: number of bytes to allocate from the iram
*
* This function requires iram phandle provided via of_node
*/
static void snd_malloc_dev_iram(struct snd_dma_buffer *dmab, size_t size)
{ {
struct device *dev = dmab->dev.dev; if (!dmab->dev.dev)
struct gen_pool *pool = NULL; return default_gfp;
else
dmab->area = NULL; return (__force gfp_t)(unsigned long)dmab->dev.dev;
dmab->addr = 0;
if (dev->of_node)
pool = of_gen_pool_get(dev->of_node, "iram", 0);
if (!pool)
return;
/* Assign the pool into private_data field */
dmab->private_data = pool;
dmab->area = gen_pool_dma_alloc_align(pool, size, &dmab->addr,
PAGE_SIZE);
} }
/** static int __snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size)
* snd_free_dev_iram - free allocated specific memory from on-chip internal ram
* @dmab: buffer allocation record to store the allocated data
*/
static void snd_free_dev_iram(struct snd_dma_buffer *dmab)
{ {
struct gen_pool *pool = dmab->private_data; const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab);
if (pool && dmab->area)
gen_pool_free(pool, (unsigned long)dmab->area, dmab->bytes);
}
#endif /* CONFIG_GENERIC_ALLOCATOR */
#endif /* CONFIG_HAS_DMA */
/*
*
* ALSA generic memory management
*
*/
static inline gfp_t snd_mem_get_gfp_flags(const struct device *dev, if (WARN_ON_ONCE(!ops || !ops->alloc))
gfp_t default_gfp) return -EINVAL;
{ return ops->alloc(dmab, size);
if (!dev)
return default_gfp;
else
return (__force gfp_t)(unsigned long)dev;
} }
/** /**
...@@ -126,7 +54,7 @@ static inline gfp_t snd_mem_get_gfp_flags(const struct device *dev, ...@@ -126,7 +54,7 @@ static inline gfp_t snd_mem_get_gfp_flags(const struct device *dev,
int snd_dma_alloc_pages(int type, struct device *device, size_t size, int snd_dma_alloc_pages(int type, struct device *device, size_t size,
struct snd_dma_buffer *dmab) struct snd_dma_buffer *dmab)
{ {
gfp_t gfp; int err;
if (WARN_ON(!size)) if (WARN_ON(!size))
return -ENXIO; return -ENXIO;
...@@ -140,43 +68,10 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, ...@@ -140,43 +68,10 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
dmab->area = NULL; dmab->area = NULL;
dmab->addr = 0; dmab->addr = 0;
dmab->private_data = NULL; dmab->private_data = NULL;
switch (type) { err = __snd_dma_alloc_pages(dmab, size);
case SNDRV_DMA_TYPE_CONTINUOUS: if (err < 0)
gfp = snd_mem_get_gfp_flags(device, GFP_KERNEL); return err;
dmab->area = alloc_pages_exact(size, gfp); if (!dmab->area)
break;
case SNDRV_DMA_TYPE_VMALLOC:
gfp = snd_mem_get_gfp_flags(device, GFP_KERNEL | __GFP_HIGHMEM);
dmab->area = __vmalloc(size, gfp);
break;
#ifdef CONFIG_HAS_DMA
#ifdef CONFIG_GENERIC_ALLOCATOR
case SNDRV_DMA_TYPE_DEV_IRAM:
snd_malloc_dev_iram(dmab, size);
if (dmab->area)
break;
/* Internal memory might have limited size and no enough space,
* so if we fail to malloc, try to fetch memory traditionally.
*/
dmab->dev.type = SNDRV_DMA_TYPE_DEV;
fallthrough;
#endif /* CONFIG_GENERIC_ALLOCATOR */
case SNDRV_DMA_TYPE_DEV:
case SNDRV_DMA_TYPE_DEV_UC:
snd_malloc_dev_pages(dmab, size);
break;
#endif
#ifdef CONFIG_SND_DMA_SGBUF
case SNDRV_DMA_TYPE_DEV_SG:
case SNDRV_DMA_TYPE_DEV_UC_SG:
snd_malloc_sgbuf_pages(device, size, dmab, NULL);
break;
#endif
default:
pr_err("snd-malloc: invalid device type %d\n", type);
return -ENXIO;
}
if (! dmab->area)
return -ENOMEM; return -ENOMEM;
dmab->bytes = size; dmab->bytes = size;
return 0; return 0;
...@@ -217,7 +112,6 @@ int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size, ...@@ -217,7 +112,6 @@ int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
} }
EXPORT_SYMBOL(snd_dma_alloc_pages_fallback); EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
/** /**
* snd_dma_free_pages - release the allocated buffer * snd_dma_free_pages - release the allocated buffer
* @dmab: the buffer allocation record to release * @dmab: the buffer allocation record to release
...@@ -226,32 +120,288 @@ EXPORT_SYMBOL(snd_dma_alloc_pages_fallback); ...@@ -226,32 +120,288 @@ EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
*/ */
void snd_dma_free_pages(struct snd_dma_buffer *dmab) void snd_dma_free_pages(struct snd_dma_buffer *dmab)
{ {
switch (dmab->dev.type) { const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab);
case SNDRV_DMA_TYPE_CONTINUOUS:
free_pages_exact(dmab->area, dmab->bytes); if (ops && ops->free)
break; ops->free(dmab);
case SNDRV_DMA_TYPE_VMALLOC: }
vfree(dmab->area); EXPORT_SYMBOL(snd_dma_free_pages);
break;
/**
* snd_dma_buffer_mmap - perform mmap of the given DMA buffer
* @dmab: buffer allocation information
* @area: VM area information
*/
int snd_dma_buffer_mmap(struct snd_dma_buffer *dmab,
struct vm_area_struct *area)
{
const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab);
if (ops && ops->mmap)
return ops->mmap(dmab, area);
else
return -ENOENT;
}
EXPORT_SYMBOL(snd_dma_buffer_mmap);
/**
* snd_sgbuf_get_addr - return the physical address at the corresponding offset
* @dmab: buffer allocation information
* @offset: offset in the ring buffer
*/
dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab, size_t offset)
{
const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab);
if (ops && ops->get_addr)
return ops->get_addr(dmab, offset);
else
return dmab->addr + offset;
}
EXPORT_SYMBOL(snd_sgbuf_get_addr);
/**
* snd_sgbuf_get_page - return the physical page at the corresponding offset
* @dmab: buffer allocation information
* @offset: offset in the ring buffer
*/
struct page *snd_sgbuf_get_page(struct snd_dma_buffer *dmab, size_t offset)
{
const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab);
if (ops && ops->get_page)
return ops->get_page(dmab, offset);
else
return virt_to_page(dmab->area + offset);
}
EXPORT_SYMBOL(snd_sgbuf_get_page);
/**
* snd_sgbuf_get_chunk_size - compute the max chunk size with continuous pages
* on sg-buffer
* @dmab: buffer allocation information
* @ofs: offset in the ring buffer
* @size: the requested size
*/
unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
unsigned int ofs, unsigned int size)
{
const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab);
if (ops && ops->get_chunk_size)
return ops->get_chunk_size(dmab, ofs, size);
else
return size;
}
EXPORT_SYMBOL(snd_sgbuf_get_chunk_size);
/*
* Continuous pages allocator
*/
static int snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
{
gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL);
dmab->area = alloc_pages_exact(size, gfp);
return 0;
}
static void snd_dma_continuous_free(struct snd_dma_buffer *dmab)
{
free_pages_exact(dmab->area, dmab->bytes);
}
static int snd_dma_continuous_mmap(struct snd_dma_buffer *dmab,
struct vm_area_struct *area)
{
return remap_pfn_range(area, area->vm_start,
dmab->addr >> PAGE_SHIFT,
area->vm_end - area->vm_start,
area->vm_page_prot);
}
static const struct snd_malloc_ops snd_dma_continuous_ops = {
.alloc = snd_dma_continuous_alloc,
.free = snd_dma_continuous_free,
.mmap = snd_dma_continuous_mmap,
};
/*
* VMALLOC allocator
*/
static int snd_dma_vmalloc_alloc(struct snd_dma_buffer *dmab, size_t size)
{
gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL | __GFP_HIGHMEM);
dmab->area = __vmalloc(size, gfp);
return 0;
}
static void snd_dma_vmalloc_free(struct snd_dma_buffer *dmab)
{
vfree(dmab->area);
}
static int snd_dma_vmalloc_mmap(struct snd_dma_buffer *dmab,
struct vm_area_struct *area)
{
return remap_vmalloc_range(area, dmab->area, 0);
}
static dma_addr_t snd_dma_vmalloc_get_addr(struct snd_dma_buffer *dmab,
size_t offset)
{
return page_to_phys(vmalloc_to_page(dmab->area + offset)) +
offset % PAGE_SIZE;
}
static struct page *snd_dma_vmalloc_get_page(struct snd_dma_buffer *dmab,
size_t offset)
{
return vmalloc_to_page(dmab->area + offset);
}
static unsigned int
snd_dma_vmalloc_get_chunk_size(struct snd_dma_buffer *dmab,
unsigned int ofs, unsigned int size)
{
ofs %= PAGE_SIZE;
size += ofs;
if (size > PAGE_SIZE)
size = PAGE_SIZE;
return size - ofs;
}
static const struct snd_malloc_ops snd_dma_vmalloc_ops = {
.alloc = snd_dma_vmalloc_alloc,
.free = snd_dma_vmalloc_free,
.mmap = snd_dma_vmalloc_mmap,
.get_addr = snd_dma_vmalloc_get_addr,
.get_page = snd_dma_vmalloc_get_page,
.get_chunk_size = snd_dma_vmalloc_get_chunk_size,
};
#ifdef CONFIG_HAS_DMA #ifdef CONFIG_HAS_DMA
/*
* IRAM allocator
*/
#ifdef CONFIG_GENERIC_ALLOCATOR #ifdef CONFIG_GENERIC_ALLOCATOR
case SNDRV_DMA_TYPE_DEV_IRAM: static int snd_dma_iram_alloc(struct snd_dma_buffer *dmab, size_t size)
snd_free_dev_iram(dmab); {
break; struct device *dev = dmab->dev.dev;
struct gen_pool *pool;
if (dev->of_node) {
pool = of_gen_pool_get(dev->of_node, "iram", 0);
/* Assign the pool into private_data field */
dmab->private_data = pool;
dmab->area = gen_pool_dma_alloc_align(pool, size, &dmab->addr,
PAGE_SIZE);
if (dmab->area)
return 0;
}
/* Internal memory might have limited size and no enough space,
* so if we fail to malloc, try to fetch memory traditionally.
*/
dmab->dev.type = SNDRV_DMA_TYPE_DEV;
return __snd_dma_alloc_pages(dmab, size);
}
static void snd_dma_iram_free(struct snd_dma_buffer *dmab)
{
struct gen_pool *pool = dmab->private_data;
if (pool && dmab->area)
gen_pool_free(pool, (unsigned long)dmab->area, dmab->bytes);
}
static int snd_dma_iram_mmap(struct snd_dma_buffer *dmab,
struct vm_area_struct *area)
{
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
return remap_pfn_range(area, area->vm_start,
dmab->addr >> PAGE_SHIFT,
area->vm_end - area->vm_start,
area->vm_page_prot);
}
static const struct snd_malloc_ops snd_dma_iram_ops = {
.alloc = snd_dma_iram_alloc,
.free = snd_dma_iram_free,
.mmap = snd_dma_iram_mmap,
};
#endif /* CONFIG_GENERIC_ALLOCATOR */ #endif /* CONFIG_GENERIC_ALLOCATOR */
case SNDRV_DMA_TYPE_DEV:
case SNDRV_DMA_TYPE_DEV_UC: /*
snd_free_dev_pages(dmab); * Coherent device pages allocator
break; */
static int snd_dma_dev_alloc(struct snd_dma_buffer *dmab, size_t size)
{
gfp_t gfp_flags;
gfp_flags = GFP_KERNEL
| __GFP_COMP /* compound page lets parts be mapped */
| __GFP_NORETRY /* don't trigger OOM-killer */
| __GFP_NOWARN; /* no stack trace print - this call is non-critical */
dmab->area = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr,
gfp_flags);
#ifdef CONFIG_X86
if (dmab->area && dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC)
set_memory_wc((unsigned long)dmab->area,
PAGE_ALIGN(size) >> PAGE_SHIFT);
#endif #endif
return 0;
}
static void snd_dma_dev_free(struct snd_dma_buffer *dmab)
{
#ifdef CONFIG_X86
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC)
set_memory_wb((unsigned long)dmab->area,
PAGE_ALIGN(dmab->bytes) >> PAGE_SHIFT);
#endif
dma_free_coherent(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
}
static int snd_dma_dev_mmap(struct snd_dma_buffer *dmab,
struct vm_area_struct *area)
{
return dma_mmap_coherent(dmab->dev.dev, area,
dmab->area, dmab->addr, dmab->bytes);
}
static const struct snd_malloc_ops snd_dma_dev_ops = {
.alloc = snd_dma_dev_alloc,
.free = snd_dma_dev_free,
.mmap = snd_dma_dev_mmap,
};
#endif /* CONFIG_HAS_DMA */
/*
* Entry points
*/
static const struct snd_malloc_ops *dma_ops[] = {
[SNDRV_DMA_TYPE_CONTINUOUS] = &snd_dma_continuous_ops,
[SNDRV_DMA_TYPE_VMALLOC] = &snd_dma_vmalloc_ops,
#ifdef CONFIG_HAS_DMA
[SNDRV_DMA_TYPE_DEV] = &snd_dma_dev_ops,
[SNDRV_DMA_TYPE_DEV_UC] = &snd_dma_dev_ops,
#ifdef CONFIG_GENERIC_ALLOCATOR
[SNDRV_DMA_TYPE_DEV_IRAM] = &snd_dma_iram_ops,
#endif /* CONFIG_GENERIC_ALLOCATOR */
#endif /* CONFIG_HAS_DMA */
#ifdef CONFIG_SND_DMA_SGBUF #ifdef CONFIG_SND_DMA_SGBUF
case SNDRV_DMA_TYPE_DEV_SG: [SNDRV_DMA_TYPE_DEV_SG] = &snd_dma_sg_ops,
case SNDRV_DMA_TYPE_DEV_UC_SG: [SNDRV_DMA_TYPE_DEV_UC_SG] = &snd_dma_sg_ops,
snd_free_sgbuf_pages(dmab);
break;
#endif #endif
default: };
pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type);
} static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab)
{
if (WARN_ON_ONCE(dmab->dev.type <= SNDRV_DMA_TYPE_UNKNOWN ||
dmab->dev.type >= ARRAY_SIZE(dma_ops)))
return NULL;
return dma_ops[dmab->dev.type];
} }
EXPORT_SYMBOL(snd_dma_free_pages);
// SPDX-License-Identifier: GPL-2.0-only
#ifndef __MEMALLOC_LOCAL_H
#define __MEMALLOC_LOCAL_H
struct snd_malloc_ops {
int (*alloc)(struct snd_dma_buffer *dmab, size_t size);
void (*free)(struct snd_dma_buffer *dmab);
dma_addr_t (*get_addr)(struct snd_dma_buffer *dmab, size_t offset);
struct page *(*get_page)(struct snd_dma_buffer *dmab, size_t offset);
unsigned int (*get_chunk_size)(struct snd_dma_buffer *dmab,
unsigned int ofs, unsigned int size);
int (*mmap)(struct snd_dma_buffer *dmab, struct vm_area_struct *area);
};
#ifdef CONFIG_SND_DMA_SGBUF
extern const struct snd_malloc_ops snd_dma_sg_ops;
#endif
#endif /* __MEMALLOC_LOCAL_H */
...@@ -185,7 +185,8 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer) ...@@ -185,7 +185,8 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer)
if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */ if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */
int err; int err;
unsigned int index; unsigned int index;
if ((err = mixer->get_recsrc(fmixer, &index)) < 0) err = mixer->get_recsrc(fmixer, &index);
if (err < 0)
return err; return err;
result = 1 << index; result = 1 << index;
} else { } else {
...@@ -517,7 +518,8 @@ static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer, ...@@ -517,7 +518,8 @@ static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
if (numid == ID_UNKNOWN) if (numid == ID_UNKNOWN)
return; return;
down_read(&card->controls_rwsem); down_read(&card->controls_rwsem);
if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { kctl = snd_ctl_find_numid(card, numid);
if (!kctl) {
up_read(&card->controls_rwsem); up_read(&card->controls_rwsem);
return; return;
} }
...@@ -555,7 +557,8 @@ static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer, ...@@ -555,7 +557,8 @@ static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer,
if (numid == ID_UNKNOWN) if (numid == ID_UNKNOWN)
return; return;
down_read(&card->controls_rwsem); down_read(&card->controls_rwsem);
if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { kctl = snd_ctl_find_numid(card, numid);
if (!kctl) {
up_read(&card->controls_rwsem); up_read(&card->controls_rwsem);
return; return;
} }
...@@ -620,7 +623,8 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer, ...@@ -620,7 +623,8 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
if (numid == ID_UNKNOWN) if (numid == ID_UNKNOWN)
return; return;
down_read(&card->controls_rwsem); down_read(&card->controls_rwsem);
if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { kctl = snd_ctl_find_numid(card, numid);
if (!kctl) {
up_read(&card->controls_rwsem); up_read(&card->controls_rwsem);
return; return;
} }
...@@ -636,7 +640,8 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer, ...@@ -636,7 +640,8 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max); uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max);
if (uinfo->count > 1) if (uinfo->count > 1)
uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max); uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max);
if ((res = kctl->put(kctl, uctl)) < 0) res = kctl->put(kctl, uctl);
if (res < 0)
goto __unalloc; goto __unalloc;
if (res > 0) if (res > 0)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
...@@ -661,7 +666,8 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer, ...@@ -661,7 +666,8 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
if (numid == ID_UNKNOWN) if (numid == ID_UNKNOWN)
return; return;
down_read(&card->controls_rwsem); down_read(&card->controls_rwsem);
if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { kctl = snd_ctl_find_numid(card, numid);
if (!kctl) {
up_read(&card->controls_rwsem); up_read(&card->controls_rwsem);
return; return;
} }
...@@ -681,7 +687,8 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer, ...@@ -681,7 +687,8 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
} else { } else {
uctl->value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0; uctl->value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0;
} }
if ((res = kctl->put(kctl, uctl)) < 0) res = kctl->put(kctl, uctl);
if (res < 0)
goto __unalloc; goto __unalloc;
if (res > 0) if (res > 0)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
...@@ -809,9 +816,11 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned ...@@ -809,9 +816,11 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
err = -ENOENT; err = -ENOENT;
goto __unlock; goto __unlock;
} }
if ((err = kctl->info(kctl, uinfo)) < 0) err = kctl->info(kctl, uinfo);
if (err < 0)
goto __unlock; goto __unlock;
if ((err = kctl->get(kctl, uctl)) < 0) err = kctl->get(kctl, uctl);
if (err < 0)
goto __unlock; goto __unlock;
for (idx = 0; idx < 32; idx++) { for (idx = 0; idx < 32; idx++) {
if (!(mixer->mask_recsrc & (1 << idx))) if (!(mixer->mask_recsrc & (1 << idx)))
...@@ -860,7 +869,8 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned ...@@ -860,7 +869,8 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
err = -ENOENT; err = -ENOENT;
goto __unlock; goto __unlock;
} }
if ((err = kctl->info(kctl, uinfo)) < 0) err = kctl->info(kctl, uinfo);
if (err < 0)
goto __unlock; goto __unlock;
for (idx = 0; idx < 32; idx++) { for (idx = 0; idx < 32; idx++) {
if (!(mixer->mask_recsrc & (1 << idx))) if (!(mixer->mask_recsrc & (1 << idx)))
...@@ -915,7 +925,8 @@ static int snd_mixer_oss_build_test(struct snd_mixer_oss *mixer, struct slot *sl ...@@ -915,7 +925,8 @@ static int snd_mixer_oss_build_test(struct snd_mixer_oss *mixer, struct slot *sl
up_read(&card->controls_rwsem); up_read(&card->controls_rwsem);
return -ENOMEM; return -ENOMEM;
} }
if ((err = kcontrol->info(kcontrol, info)) < 0) { err = kcontrol->info(kcontrol, info);
if (err < 0) {
up_read(&card->controls_rwsem); up_read(&card->controls_rwsem);
kfree(info); kfree(info);
return err; return err;
...@@ -1036,7 +1047,10 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, ...@@ -1036,7 +1047,10 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer,
if (snd_mixer_oss_build_test_all(mixer, ptr, &slot)) if (snd_mixer_oss_build_test_all(mixer, ptr, &slot))
return 0; return 0;
down_read(&mixer->card->controls_rwsem); down_read(&mixer->card->controls_rwsem);
if (ptr->index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0)) != NULL) { kctl = NULL;
if (!ptr->index)
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
if (kctl) {
struct snd_ctl_elem_info *uinfo; struct snd_ctl_elem_info *uinfo;
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
...@@ -1343,9 +1357,10 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd) ...@@ -1343,9 +1357,10 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd)
if (mixer == NULL) if (mixer == NULL)
return -ENOMEM; return -ENOMEM;
mutex_init(&mixer->reg_mutex); mutex_init(&mixer->reg_mutex);
if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER,
card, 0, card, 0,
&snd_mixer_oss_f_ops, card)) < 0) { &snd_mixer_oss_f_ops, card);
if (err < 0) {
dev_err(card->dev, dev_err(card->dev,
"unable to register OSS mixer device %i:%i\n", "unable to register OSS mixer device %i:%i\n",
card->number, 0); card->number, 0);
......
...@@ -955,9 +955,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) ...@@ -955,9 +955,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
if (!direct) { if (!direct) {
/* add necessary plugins */ /* add necessary plugins */
snd_pcm_oss_plugin_clear(substream); snd_pcm_oss_plugin_clear(substream);
if ((err = snd_pcm_plug_format_plugins(substream, err = snd_pcm_plug_format_plugins(substream, params, sparams);
params, if (err < 0) {
sparams)) < 0) {
pcm_dbg(substream->pcm, pcm_dbg(substream->pcm,
"snd_pcm_plug_format_plugins failed: %i\n", err); "snd_pcm_plug_format_plugins failed: %i\n", err);
snd_pcm_oss_plugin_clear(substream); snd_pcm_oss_plugin_clear(substream);
...@@ -965,7 +964,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) ...@@ -965,7 +964,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
} }
if (runtime->oss.plugin_first) { if (runtime->oss.plugin_first) {
struct snd_pcm_plugin *plugin; struct snd_pcm_plugin *plugin;
if ((err = snd_pcm_plugin_build_io(substream, sparams, &plugin)) < 0) { err = snd_pcm_plugin_build_io(substream, sparams, &plugin);
if (err < 0) {
pcm_dbg(substream->pcm, pcm_dbg(substream->pcm,
"snd_pcm_plugin_build_io failed: %i\n", err); "snd_pcm_plugin_build_io failed: %i\n", err);
snd_pcm_oss_plugin_clear(substream); snd_pcm_oss_plugin_clear(substream);
...@@ -1011,7 +1011,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) ...@@ -1011,7 +1011,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
sw_params->silence_size = frames; sw_params->silence_size = frames;
} }
if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) { err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params);
if (err < 0) {
pcm_dbg(substream->pcm, "SW_PARAMS failed: %i\n", err); pcm_dbg(substream->pcm, "SW_PARAMS failed: %i\n", err);
goto failure; goto failure;
} }
...@@ -1573,7 +1574,8 @@ static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file) ...@@ -1573,7 +1574,8 @@ static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file)
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
if (substream != NULL) { if (substream != NULL) {
if ((err = snd_pcm_oss_make_ready(substream)) < 0) err = snd_pcm_oss_make_ready(substream);
if (err < 0)
return err; return err;
snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL); snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
} }
...@@ -1645,7 +1647,8 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) ...@@ -1645,7 +1647,8 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
runtime = substream->runtime; runtime = substream->runtime;
if (atomic_read(&substream->mmap_count)) if (atomic_read(&substream->mmap_count))
goto __direct; goto __direct;
if ((err = snd_pcm_oss_make_ready(substream)) < 0) err = snd_pcm_oss_make_ready(substream);
if (err < 0)
return err; return err;
atomic_inc(&runtime->oss.rw_ref); atomic_inc(&runtime->oss.rw_ref);
if (mutex_lock_interruptible(&runtime->oss.params_lock)) { if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
...@@ -1711,7 +1714,8 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) ...@@ -1711,7 +1714,8 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
if (substream != NULL) { if (substream != NULL) {
if ((err = snd_pcm_oss_make_ready(substream)) < 0) err = snd_pcm_oss_make_ready(substream);
if (err < 0)
return err; return err;
runtime = substream->runtime; runtime = substream->runtime;
err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
...@@ -1758,7 +1762,8 @@ static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file) ...@@ -1758,7 +1762,8 @@ static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file)
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
int err; int err;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream);
if (err < 0)
return err; return err;
return substream->runtime->oss.rate; return substream->runtime->oss.rate;
} }
...@@ -1795,7 +1800,8 @@ static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file) ...@@ -1795,7 +1800,8 @@ static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file)
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
int err; int err;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream);
if (err < 0)
return err; return err;
return substream->runtime->oss.channels; return substream->runtime->oss.channels;
} }
...@@ -1805,7 +1811,8 @@ static int snd_pcm_oss_get_block_size(struct snd_pcm_oss_file *pcm_oss_file) ...@@ -1805,7 +1811,8 @@ static int snd_pcm_oss_get_block_size(struct snd_pcm_oss_file *pcm_oss_file)
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
int err; int err;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream);
if (err < 0)
return err; return err;
return substream->runtime->oss.period_bytes; return substream->runtime->oss.period_bytes;
} }
...@@ -1820,7 +1827,8 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) ...@@ -1820,7 +1827,8 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
const struct snd_mask *format_mask; const struct snd_mask *format_mask;
int fmt; int fmt;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream);
if (err < 0)
return err; return err;
if (atomic_read(&substream->mmap_count)) if (atomic_read(&substream->mmap_count))
direct = 1; direct = 1;
...@@ -1890,7 +1898,8 @@ static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file) ...@@ -1890,7 +1898,8 @@ static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file)
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
int err; int err;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream);
if (err < 0)
return err; return err;
return substream->runtime->oss.format; return substream->runtime->oss.format;
} }
...@@ -2050,11 +2059,13 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr ...@@ -2050,11 +2059,13 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
if (psubstream) { if (psubstream) {
if ((err = snd_pcm_oss_make_ready(psubstream)) < 0) err = snd_pcm_oss_make_ready(psubstream);
if (err < 0)
return err; return err;
} }
if (csubstream) { if (csubstream) {
if ((err = snd_pcm_oss_make_ready(csubstream)) < 0) err = snd_pcm_oss_make_ready(csubstream);
if (err < 0)
return err; return err;
} }
if (psubstream) { if (psubstream) {
...@@ -2141,7 +2152,8 @@ static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file) ...@@ -2141,7 +2152,8 @@ static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file)
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
if (substream == NULL) if (substream == NULL)
return -EINVAL; return -EINVAL;
if ((err = snd_pcm_oss_make_ready(substream)) < 0) err = snd_pcm_oss_make_ready(substream);
if (err < 0)
return err; return err;
runtime = substream->runtime; runtime = substream->runtime;
if (runtime->oss.params || runtime->oss.prepare) if (runtime->oss.params || runtime->oss.prepare)
...@@ -2168,7 +2180,8 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream ...@@ -2168,7 +2180,8 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream
substream = pcm_oss_file->streams[stream]; substream = pcm_oss_file->streams[stream];
if (substream == NULL) if (substream == NULL)
return -EINVAL; return -EINVAL;
if ((err = snd_pcm_oss_make_ready(substream)) < 0) err = snd_pcm_oss_make_ready(substream);
if (err < 0)
return err; return err;
runtime = substream->runtime; runtime = substream->runtime;
if (runtime->oss.params || runtime->oss.prepare) { if (runtime->oss.params || runtime->oss.prepare) {
...@@ -2239,9 +2252,11 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre ...@@ -2239,9 +2252,11 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre
return -EINVAL; return -EINVAL;
runtime = substream->runtime; runtime = substream->runtime;
if (runtime->oss.params && if (runtime->oss.params) {
(err = snd_pcm_oss_change_params(substream, false)) < 0) err = snd_pcm_oss_change_params(substream, false);
return err; if (err < 0)
return err;
}
info.fragsize = runtime->oss.period_bytes; info.fragsize = runtime->oss.period_bytes;
info.fragstotal = runtime->periods; info.fragstotal = runtime->periods;
...@@ -2601,7 +2616,8 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long ...@@ -2601,7 +2616,8 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long
case SNDCTL_DSP_SPEED: case SNDCTL_DSP_SPEED:
if (get_user(res, p)) if (get_user(res, p))
return -EFAULT; return -EFAULT;
if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0) res = snd_pcm_oss_set_rate(pcm_oss_file, res);
if (res < 0)
return res; return res;
return put_user(res, p); return put_user(res, p);
case SOUND_PCM_READ_RATE: case SOUND_PCM_READ_RATE:
...@@ -2613,7 +2629,8 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long ...@@ -2613,7 +2629,8 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long
if (get_user(res, p)) if (get_user(res, p))
return -EFAULT; return -EFAULT;
res = res > 0 ? 2 : 1; res = res > 0 ? 2 : 1;
if ((res = snd_pcm_oss_set_channels(pcm_oss_file, res)) < 0) res = snd_pcm_oss_set_channels(pcm_oss_file, res);
if (res < 0)
return res; return res;
return put_user(--res, p); return put_user(--res, p);
case SNDCTL_DSP_GETBLKSIZE: case SNDCTL_DSP_GETBLKSIZE:
...@@ -2829,7 +2846,8 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait) ...@@ -2829,7 +2846,8 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
snd_pcm_state_t ostate; snd_pcm_state_t ostate;
poll_wait(file, &runtime->sleep, wait); poll_wait(file, &runtime->sleep, wait);
snd_pcm_stream_lock_irq(csubstream); snd_pcm_stream_lock_irq(csubstream);
if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING || ostate = runtime->status->state;
if (ostate != SNDRV_PCM_STATE_RUNNING ||
snd_pcm_oss_capture_ready(csubstream)) snd_pcm_oss_capture_ready(csubstream))
mask |= EPOLLIN | EPOLLRDNORM; mask |= EPOLLIN | EPOLLRDNORM;
snd_pcm_stream_unlock_irq(csubstream); snd_pcm_stream_unlock_irq(csubstream);
...@@ -3043,7 +3061,8 @@ static void snd_pcm_oss_proc_init(struct snd_pcm *pcm) ...@@ -3043,7 +3061,8 @@ static void snd_pcm_oss_proc_init(struct snd_pcm *pcm)
struct snd_pcm_str *pstr = &pcm->streams[stream]; struct snd_pcm_str *pstr = &pcm->streams[stream];
if (pstr->substream_count == 0) if (pstr->substream_count == 0)
continue; continue;
if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) { entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root);
if (entry) {
entry->content = SNDRV_INFO_CONTENT_TEXT; entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->mode = S_IFREG | 0644; entry->mode = S_IFREG | 0644;
entry->c.text.read = snd_pcm_oss_proc_read; entry->c.text.read = snd_pcm_oss_proc_read;
...@@ -3191,7 +3210,8 @@ static int __init alsa_pcm_oss_init(void) ...@@ -3191,7 +3210,8 @@ static int __init alsa_pcm_oss_init(void)
adsp_map[i] = 1; adsp_map[i] = 1;
} }
} }
if ((err = snd_pcm_notify(&snd_pcm_oss_notify, 0)) < 0) err = snd_pcm_notify(&snd_pcm_oss_notify, 0);
if (err < 0)
return err; return err;
return 0; return 0;
} }
......
...@@ -59,7 +59,8 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t ...@@ -59,7 +59,8 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t
} else { } else {
format = &plugin->dst_format; format = &plugin->dst_format;
} }
if ((width = snd_pcm_format_physical_width(format->format)) < 0) width = snd_pcm_format_physical_width(format->format);
if (width < 0)
return width; return width;
size = frames * format->channels * width; size = frames * format->channels * width;
if (snd_BUG_ON(size % 8)) if (snd_BUG_ON(size % 8))
...@@ -572,7 +573,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plu ...@@ -572,7 +573,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plu
} }
v = plugin->buf_channels; v = plugin->buf_channels;
*channels = v; *channels = v;
if ((width = snd_pcm_format_physical_width(format->format)) < 0) width = snd_pcm_format_physical_width(format->format);
if (width < 0)
return width; return width;
nchannels = format->channels; nchannels = format->channels;
if (snd_BUG_ON(plugin->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && if (snd_BUG_ON(plugin->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
...@@ -600,16 +602,17 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, st ...@@ -600,16 +602,17 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, st
while (plugin) { while (plugin) {
if (frames <= 0) if (frames <= 0)
return frames; return frames;
if ((next = plugin->next) != NULL) { next = plugin->next;
if (next) {
snd_pcm_sframes_t frames1 = frames; snd_pcm_sframes_t frames1 = frames;
if (plugin->dst_frames) { if (plugin->dst_frames) {
frames1 = plugin->dst_frames(plugin, frames); frames1 = plugin->dst_frames(plugin, frames);
if (frames1 <= 0) if (frames1 <= 0)
return frames1; return frames1;
} }
if ((err = next->client_channels(next, frames1, &dst_channels)) < 0) { err = next->client_channels(next, frames1, &dst_channels);
if (err < 0)
return err; return err;
}
if (err != frames1) { if (err != frames1) {
frames = err; frames = err;
if (plugin->src_frames) { if (plugin->src_frames) {
...@@ -621,7 +624,8 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, st ...@@ -621,7 +624,8 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, st
} else } else
dst_channels = NULL; dst_channels = NULL;
pdprintf("write plugin: %s, %li\n", plugin->name, frames); pdprintf("write plugin: %s, %li\n", plugin->name, frames);
if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) frames = plugin->transfer(plugin, src_channels, dst_channels, frames);
if (frames < 0)
return frames; return frames;
src_channels = dst_channels; src_channels = dst_channels;
plugin = next; plugin = next;
...@@ -643,16 +647,18 @@ snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, str ...@@ -643,16 +647,18 @@ snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, str
src_channels = NULL; src_channels = NULL;
plugin = snd_pcm_plug_first(plug); plugin = snd_pcm_plug_first(plug);
while (plugin && frames > 0) { while (plugin && frames > 0) {
if ((next = plugin->next) != NULL) { next = plugin->next;
if ((err = plugin->client_channels(plugin, frames, &dst_channels)) < 0) { if (next) {
err = plugin->client_channels(plugin, frames, &dst_channels);
if (err < 0)
return err; return err;
}
frames = err; frames = err;
} else { } else {
dst_channels = dst_channels_final; dst_channels = dst_channels_final;
} }
pdprintf("read plugin: %s, %li\n", plugin->name, frames); pdprintf("read plugin: %s, %li\n", plugin->name, frames);
if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) frames = plugin->transfer(plugin, src_channels, dst_channels, frames);
if (frames < 0)
return frames; return frames;
plugin = next; plugin = next;
src_channels = dst_channels; src_channels = dst_channels;
......
...@@ -1004,7 +1004,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) ...@@ -1004,7 +1004,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
substream->pstr->substream_opened--; substream->pstr->substream_opened--;
} }
static ssize_t show_pcm_class(struct device *dev, static ssize_t pcm_class_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct snd_pcm_str *pstr = container_of(dev, struct snd_pcm_str, dev); struct snd_pcm_str *pstr = container_of(dev, struct snd_pcm_str, dev);
...@@ -1024,7 +1024,7 @@ static ssize_t show_pcm_class(struct device *dev, ...@@ -1024,7 +1024,7 @@ static ssize_t show_pcm_class(struct device *dev,
return sprintf(buf, "%s\n", str); return sprintf(buf, "%s\n", str);
} }
static DEVICE_ATTR(pcm_class, 0444, show_pcm_class, NULL); static DEVICE_ATTR_RO(pcm_class);
static struct attribute *pcm_dev_attrs[] = { static struct attribute *pcm_dev_attrs[] = {
&dev_attr_pcm_class.attr, &dev_attr_pcm_class.attr,
NULL NULL
......
...@@ -239,7 +239,8 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, ...@@ -239,7 +239,8 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
int err; int err;
if (! (runtime = substream->runtime)) runtime = substream->runtime;
if (!runtime)
return -ENOTTY; return -ENOTTY;
data = kmalloc(sizeof(*data), GFP_KERNEL); data = kmalloc(sizeof(*data), GFP_KERNEL);
...@@ -343,7 +344,8 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, ...@@ -343,7 +344,8 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD; return -EBADFD;
if ((ch = substream->runtime->channels) > 128) ch = substream->runtime->channels;
if (ch > 128)
return -EINVAL; return -EINVAL;
if (get_user(buf, &data32->bufs) || if (get_user(buf, &data32->bufs) ||
get_user(frames, &data32->frames)) get_user(frames, &data32->frames))
......
...@@ -9,41 +9,85 @@ ...@@ -9,41 +9,85 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/pcm_iec958.h> #include <sound/pcm_iec958.h>
static int create_iec958_consumer(uint rate, uint sample_width, /**
u8 *cs, size_t len) * snd_pcm_create_iec958_consumer_default - create default consumer format IEC958 channel status
* @cs: channel status buffer, at least four bytes
* @len: length of channel status buffer
*
* Create the consumer format channel status data in @cs of maximum size
* @len. When relevant, the configuration-dependant bits will be set as
* unspecified.
*
* Drivers should then call einter snd_pcm_fill_iec958_consumer() or
* snd_pcm_fill_iec958_consumer_hw_params() to replace these unspecified
* bits by their actual values.
*
* Drivers may wish to tweak the contents of the buffer after creation.
*
* Returns: length of buffer, or negative error code if something failed.
*/
int snd_pcm_create_iec958_consumer_default(u8 *cs, size_t len)
{ {
unsigned int fs, ws;
if (len < 4) if (len < 4)
return -EINVAL; return -EINVAL;
switch (rate) { memset(cs, 0, len);
case 32000:
fs = IEC958_AES3_CON_FS_32000; cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
break; cs[1] = IEC958_AES1_CON_GENERAL;
case 44100: cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
fs = IEC958_AES3_CON_FS_44100; cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | IEC958_AES3_CON_FS_NOTID;
break;
case 48000: if (len > 4)
fs = IEC958_AES3_CON_FS_48000; cs[4] = IEC958_AES4_CON_WORDLEN_NOTID;
break;
case 88200: return len;
fs = IEC958_AES3_CON_FS_88200; }
break; EXPORT_SYMBOL_GPL(snd_pcm_create_iec958_consumer_default);
case 96000:
fs = IEC958_AES3_CON_FS_96000; static int fill_iec958_consumer(uint rate, uint sample_width,
break; u8 *cs, size_t len)
case 176400: {
fs = IEC958_AES3_CON_FS_176400; if (len < 4)
break;
case 192000:
fs = IEC958_AES3_CON_FS_192000;
break;
default:
return -EINVAL; return -EINVAL;
if ((cs[3] & IEC958_AES3_CON_FS) == IEC958_AES3_CON_FS_NOTID) {
unsigned int fs;
switch (rate) {
case 32000:
fs = IEC958_AES3_CON_FS_32000;
break;
case 44100:
fs = IEC958_AES3_CON_FS_44100;
break;
case 48000:
fs = IEC958_AES3_CON_FS_48000;
break;
case 88200:
fs = IEC958_AES3_CON_FS_88200;
break;
case 96000:
fs = IEC958_AES3_CON_FS_96000;
break;
case 176400:
fs = IEC958_AES3_CON_FS_176400;
break;
case 192000:
fs = IEC958_AES3_CON_FS_192000;
break;
default:
return -EINVAL;
}
cs[3] &= ~IEC958_AES3_CON_FS;
cs[3] |= fs;
} }
if (len > 4) { if (len > 4 &&
(cs[4] & IEC958_AES4_CON_WORDLEN) == IEC958_AES4_CON_WORDLEN_NOTID) {
unsigned int ws;
switch (sample_width) { switch (sample_width) {
case 16: case 16:
ws = IEC958_AES4_CON_WORDLEN_20_16; ws = IEC958_AES4_CON_WORDLEN_20_16;
...@@ -64,20 +108,57 @@ static int create_iec958_consumer(uint rate, uint sample_width, ...@@ -64,20 +108,57 @@ static int create_iec958_consumer(uint rate, uint sample_width,
default: default:
return -EINVAL; return -EINVAL;
} }
}
memset(cs, 0, len); cs[4] &= ~IEC958_AES4_CON_WORDLEN;
cs[4] |= ws;
}
cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE; return len;
cs[1] = IEC958_AES1_CON_GENERAL; }
cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | fs;
if (len > 4) /**
cs[4] = ws; * snd_pcm_fill_iec958_consumer - Fill consumer format IEC958 channel status
* @runtime: pcm runtime structure with ->rate filled in
* @cs: channel status buffer, at least four bytes
* @len: length of channel status buffer
*
* Fill the unspecified bits in an IEC958 status bits array using the
* parameters of the PCM runtime @runtime.
*
* Drivers may wish to tweak the contents of the buffer after its been
* filled.
*
* Returns: length of buffer, or negative error code if something failed.
*/
int snd_pcm_fill_iec958_consumer(struct snd_pcm_runtime *runtime,
u8 *cs, size_t len)
{
return fill_iec958_consumer(runtime->rate,
snd_pcm_format_width(runtime->format),
cs, len);
}
EXPORT_SYMBOL_GPL(snd_pcm_fill_iec958_consumer);
return len; /**
* snd_pcm_fill_iec958_consumer_hw_params - Fill consumer format IEC958 channel status
* @params: the hw_params instance for extracting rate and sample format
* @cs: channel status buffer, at least four bytes
* @len: length of channel status buffer
*
* Fill the unspecified bits in an IEC958 status bits array using the
* parameters of the PCM hardware parameters @params.
*
* Drivers may wish to tweak the contents of the buffer after its been
* filled..
*
* Returns: length of buffer, or negative error code if something failed.
*/
int snd_pcm_fill_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
u8 *cs, size_t len)
{
return fill_iec958_consumer(params_rate(params), params_width(params), cs, len);
} }
EXPORT_SYMBOL_GPL(snd_pcm_fill_iec958_consumer_hw_params);
/** /**
* snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status
...@@ -95,9 +176,13 @@ static int create_iec958_consumer(uint rate, uint sample_width, ...@@ -95,9 +176,13 @@ static int create_iec958_consumer(uint rate, uint sample_width,
int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
size_t len) size_t len)
{ {
return create_iec958_consumer(runtime->rate, int ret;
snd_pcm_format_width(runtime->format),
cs, len); ret = snd_pcm_create_iec958_consumer_default(cs, len);
if (ret < 0)
return ret;
return snd_pcm_fill_iec958_consumer(runtime, cs, len);
} }
EXPORT_SYMBOL(snd_pcm_create_iec958_consumer); EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
...@@ -117,7 +202,12 @@ EXPORT_SYMBOL(snd_pcm_create_iec958_consumer); ...@@ -117,7 +202,12 @@ EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params, int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
u8 *cs, size_t len) u8 *cs, size_t len)
{ {
return create_iec958_consumer(params_rate(params), params_width(params), int ret;
cs, len);
ret = snd_pcm_create_iec958_consumer_default(cs, len);
if (ret < 0)
return ret;
return fill_iec958_consumer(params_rate(params), params_width(params), cs, len);
} }
EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params); EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params);
...@@ -1778,27 +1778,38 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, ...@@ -1778,27 +1778,38 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
EXPORT_SYMBOL(snd_pcm_lib_ioctl); EXPORT_SYMBOL(snd_pcm_lib_ioctl);
/** /**
* snd_pcm_period_elapsed - update the pcm status for the next period * snd_pcm_period_elapsed_under_stream_lock() - update the status of runtime for the next period
* @substream: the pcm substream instance * under acquired lock of PCM substream.
* @substream: the instance of pcm substream.
*
* This function is called when the batch of audio data frames as the same size as the period of
* buffer is already processed in audio data transmission.
*
* The call of function updates the status of runtime with the latest position of audio data
* transmission, checks overrun and underrun over buffer, awaken user processes from waiting for
* available audio data frames, sampling audio timestamp, and performs stop or drain the PCM
* substream according to configured threshold.
*
* The function is intended to use for the case that PCM driver operates audio data frames under
* acquired lock of PCM substream; e.g. in callback of any operation of &snd_pcm_ops in process
* context. In any interrupt context, it's preferrable to use ``snd_pcm_period_elapsed()`` instead
* since lock of PCM substream should be acquired in advance.
* *
* This function is called from the interrupt handler when the * Developer should pay enough attention that some callbacks in &snd_pcm_ops are done by the call of
* PCM has processed the period size. It will update the current * function:
* pointer, wake up sleepers, etc.
* *
* Even if more than one periods have elapsed since the last call, you * - .pointer - to retrieve current position of audio data transmission by frame count or XRUN state.
* have to call this only once. * - .trigger - with SNDRV_PCM_TRIGGER_STOP at XRUN or DRAINING state.
* - .get_time_info - to retrieve audio time stamp if needed.
*
* Even if more than one periods have elapsed since the last call, you have to call this only once.
*/ */
void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) void snd_pcm_period_elapsed_under_stream_lock(struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
unsigned long flags;
if (snd_BUG_ON(!substream))
return;
snd_pcm_stream_lock_irqsave(substream, flags);
if (PCM_RUNTIME_CHECK(substream)) if (PCM_RUNTIME_CHECK(substream))
goto _unlock; return;
runtime = substream->runtime; runtime = substream->runtime;
if (!snd_pcm_running(substream) || if (!snd_pcm_running(substream) ||
...@@ -1811,7 +1822,30 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) ...@@ -1811,7 +1822,30 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
#endif #endif
_end: _end:
kill_fasync(&runtime->fasync, SIGIO, POLL_IN); kill_fasync(&runtime->fasync, SIGIO, POLL_IN);
_unlock: }
EXPORT_SYMBOL(snd_pcm_period_elapsed_under_stream_lock);
/**
* snd_pcm_period_elapsed() - update the status of runtime for the next period by acquiring lock of
* PCM substream.
* @substream: the instance of PCM substream.
*
* This function is mostly similar to ``snd_pcm_period_elapsed_under_stream_lock()`` except for
* acquiring lock of PCM substream voluntarily.
*
* It's typically called by any type of IRQ handler when hardware IRQ occurs to notify event that
* the batch of audio data frames as the same size as the period of buffer is already processed in
* audio data transmission.
*/
void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
{
unsigned long flags;
if (snd_BUG_ON(!substream))
return;
snd_pcm_stream_lock_irqsave(substream, flags);
snd_pcm_period_elapsed_under_stream_lock(substream);
snd_pcm_stream_unlock_irqrestore(substream, flags); snd_pcm_stream_unlock_irqrestore(substream, flags);
} }
EXPORT_SYMBOL(snd_pcm_period_elapsed); EXPORT_SYMBOL(snd_pcm_period_elapsed);
......
...@@ -65,11 +65,6 @@ void __snd_pcm_xrun(struct snd_pcm_substream *substream); ...@@ -65,11 +65,6 @@ void __snd_pcm_xrun(struct snd_pcm_substream *substream);
void snd_pcm_group_init(struct snd_pcm_group *group); void snd_pcm_group_init(struct snd_pcm_group *group);
void snd_pcm_sync_stop(struct snd_pcm_substream *substream, bool sync_irq); void snd_pcm_sync_stop(struct snd_pcm_substream *substream, bool sync_irq);
#ifdef CONFIG_SND_DMA_SGBUF
struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream,
unsigned long offset);
#endif
#define PCM_RUNTIME_CHECK(sub) snd_BUG_ON(!(sub) || !(sub)->runtime) #define PCM_RUNTIME_CHECK(sub) snd_BUG_ON(!(sub) || !(sub)->runtime)
/* loop over all PCM substreams */ /* loop over all PCM substreams */
......
...@@ -337,27 +337,6 @@ void snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type, ...@@ -337,27 +337,6 @@ void snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
} }
EXPORT_SYMBOL(snd_pcm_set_managed_buffer_all); EXPORT_SYMBOL(snd_pcm_set_managed_buffer_all);
#ifdef CONFIG_SND_DMA_SGBUF
/*
* snd_pcm_sgbuf_ops_page - get the page struct at the given offset
* @substream: the pcm substream instance
* @offset: the buffer offset
*
* Used as the page callback of PCM ops.
*
* Return: The page struct at the given buffer offset. %NULL on failure.
*/
struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset)
{
struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
unsigned int idx = offset >> PAGE_SHIFT;
if (idx >= (unsigned int)sgbuf->pages)
return NULL;
return sgbuf->page_table[idx];
}
#endif /* CONFIG_SND_DMA_SGBUF */
/** /**
* snd_pcm_lib_malloc_pages - allocate the DMA buffer * snd_pcm_lib_malloc_pages - allocate the DMA buffer
* @substream: the substream to allocate the DMA buffer to * @substream: the substream to allocate the DMA buffer to
......
...@@ -266,7 +266,8 @@ int snd_pcm_format_signed(snd_pcm_format_t format) ...@@ -266,7 +266,8 @@ int snd_pcm_format_signed(snd_pcm_format_t format)
int val; int val;
if (!valid_format(format)) if (!valid_format(format))
return -EINVAL; return -EINVAL;
if ((val = pcm_formats[(INT)format].signd) < 0) val = pcm_formats[(INT)format].signd;
if (val < 0)
return -EINVAL; return -EINVAL;
return val; return val;
} }
...@@ -314,7 +315,8 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format) ...@@ -314,7 +315,8 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format)
int val; int val;
if (!valid_format(format)) if (!valid_format(format))
return -EINVAL; return -EINVAL;
if ((val = pcm_formats[(INT)format].le) < 0) val = pcm_formats[(INT)format].le;
if (val < 0)
return -EINVAL; return -EINVAL;
return val; return val;
} }
...@@ -350,7 +352,8 @@ int snd_pcm_format_width(snd_pcm_format_t format) ...@@ -350,7 +352,8 @@ int snd_pcm_format_width(snd_pcm_format_t format)
int val; int val;
if (!valid_format(format)) if (!valid_format(format))
return -EINVAL; return -EINVAL;
if ((val = pcm_formats[(INT)format].width) == 0) val = pcm_formats[(INT)format].width;
if (!val)
return -EINVAL; return -EINVAL;
return val; return val;
} }
...@@ -368,7 +371,8 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format) ...@@ -368,7 +371,8 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format)
int val; int val;
if (!valid_format(format)) if (!valid_format(format))
return -EINVAL; return -EINVAL;
if ((val = pcm_formats[(INT)format].phys) == 0) val = pcm_formats[(INT)format].phys;
if (!val)
return -EINVAL; return -EINVAL;
return val; return val;
} }
......
...@@ -768,7 +768,8 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -768,7 +768,8 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
if (cpu_latency_qos_request_active(&substream->latency_pm_qos_req)) if (cpu_latency_qos_request_active(&substream->latency_pm_qos_req))
cpu_latency_qos_remove_request(&substream->latency_pm_qos_req); cpu_latency_qos_remove_request(&substream->latency_pm_qos_req);
if ((usecs = period_to_usecs(runtime)) >= 0) usecs = period_to_usecs(runtime);
if (usecs >= 0)
cpu_latency_qos_add_request(&substream->latency_pm_qos_req, cpu_latency_qos_add_request(&substream->latency_pm_qos_req,
usecs); usecs);
return 0; return 0;
...@@ -2658,7 +2659,8 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, ...@@ -2658,7 +2659,8 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
goto error; goto error;
} }
if ((err = substream->ops->open(substream)) < 0) err = substream->ops->open(substream);
if (err < 0)
goto error; goto error;
substream->hw_opened = 1; substream->hw_opened = 1;
...@@ -2799,6 +2801,10 @@ static int snd_pcm_release(struct inode *inode, struct file *file) ...@@ -2799,6 +2801,10 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
if (snd_BUG_ON(!substream)) if (snd_BUG_ON(!substream))
return -ENXIO; return -ENXIO;
pcm = substream->pcm; pcm = substream->pcm;
/* block until the device gets woken up as it may touch the hardware */
snd_power_wait(pcm->card);
mutex_lock(&pcm->open_mutex); mutex_lock(&pcm->open_mutex);
snd_pcm_release_substream(substream); snd_pcm_release_substream(substream);
kfree(pcm_file); kfree(pcm_file);
...@@ -3193,7 +3199,7 @@ static int snd_pcm_common_ioctl(struct file *file, ...@@ -3193,7 +3199,7 @@ static int snd_pcm_common_ioctl(struct file *file,
if (PCM_RUNTIME_CHECK(substream)) if (PCM_RUNTIME_CHECK(substream))
return -ENXIO; return -ENXIO;
res = snd_power_wait(substream->pcm->card, SNDRV_CTL_POWER_D0); res = snd_power_wait(substream->pcm->card);
if (res < 0) if (res < 0)
return res; return res;
...@@ -3638,24 +3644,6 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file ...@@ -3638,24 +3644,6 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
} }
#endif /* coherent mmap */ #endif /* coherent mmap */
static inline struct page *
snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs)
{
void *vaddr = substream->runtime->dma_area + ofs;
switch (substream->dma_buffer.dev.type) {
#ifdef CONFIG_SND_DMA_SGBUF
case SNDRV_DMA_TYPE_DEV_SG:
case SNDRV_DMA_TYPE_DEV_UC_SG:
return snd_pcm_sgbuf_ops_page(substream, ofs);
#endif /* CONFIG_SND_DMA_SGBUF */
case SNDRV_DMA_TYPE_VMALLOC:
return vmalloc_to_page(vaddr);
default:
return virt_to_page(vaddr);
}
}
/* /*
* fault callback for mmapping a RAM page * fault callback for mmapping a RAM page
*/ */
...@@ -3677,7 +3665,7 @@ static vm_fault_t snd_pcm_mmap_data_fault(struct vm_fault *vmf) ...@@ -3677,7 +3665,7 @@ static vm_fault_t snd_pcm_mmap_data_fault(struct vm_fault *vmf)
if (substream->ops->page) if (substream->ops->page)
page = substream->ops->page(substream, offset); page = substream->ops->page(substream, offset);
else else
page = snd_pcm_default_page_ops(substream, offset); page = snd_sgbuf_get_page(snd_pcm_get_dma_buf(substream), offset);
if (!page) if (!page)
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
get_page(page); get_page(page);
...@@ -3712,22 +3700,9 @@ int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream, ...@@ -3712,22 +3700,9 @@ int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *area) struct vm_area_struct *area)
{ {
area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
#ifdef CONFIG_GENERIC_ALLOCATOR if (!substream->ops->page &&
if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_IRAM) { !snd_dma_buffer_mmap(snd_pcm_get_dma_buf(substream), area))
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot); return 0;
return remap_pfn_range(area, area->vm_start,
substream->dma_buffer.addr >> PAGE_SHIFT,
area->vm_end - area->vm_start, area->vm_page_prot);
}
#endif /* CONFIG_GENERIC_ALLOCATOR */
if (IS_ENABLED(CONFIG_HAS_DMA) && !substream->ops->page &&
(substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV ||
substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_UC))
return dma_mmap_coherent(substream->dma_buffer.dev.dev,
area,
substream->runtime->dma_area,
substream->runtime->dma_addr,
substream->runtime->dma_bytes);
/* mmap with fault handler */ /* mmap with fault handler */
area->vm_ops = &snd_pcm_vm_ops_data_fault; area->vm_ops = &snd_pcm_vm_ops_data_fault;
return 0; return 0;
......
...@@ -680,9 +680,12 @@ static int resize_runtime_buffer(struct snd_rawmidi_runtime *runtime, ...@@ -680,9 +680,12 @@ static int resize_runtime_buffer(struct snd_rawmidi_runtime *runtime,
bool is_input) bool is_input)
{ {
char *newbuf, *oldbuf; char *newbuf, *oldbuf;
unsigned int framing = params->mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK;
if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L)
return -EINVAL; return -EINVAL;
if (framing == SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP && (params->buffer_size & 0x1f) != 0)
return -EINVAL;
if (params->avail_min < 1 || params->avail_min > params->buffer_size) if (params->avail_min < 1 || params->avail_min > params->buffer_size)
return -EINVAL; return -EINVAL;
if (params->buffer_size != runtime->buffer_size) { if (params->buffer_size != runtime->buffer_size) {
...@@ -720,8 +723,24 @@ EXPORT_SYMBOL(snd_rawmidi_output_params); ...@@ -720,8 +723,24 @@ EXPORT_SYMBOL(snd_rawmidi_output_params);
int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
struct snd_rawmidi_params *params) struct snd_rawmidi_params *params)
{ {
unsigned int framing = params->mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK;
unsigned int clock_type = params->mode & SNDRV_RAWMIDI_MODE_CLOCK_MASK;
int err;
if (framing == SNDRV_RAWMIDI_MODE_FRAMING_NONE && clock_type != SNDRV_RAWMIDI_MODE_CLOCK_NONE)
return -EINVAL;
else if (clock_type > SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC_RAW)
return -EINVAL;
if (framing > SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP)
return -EINVAL;
snd_rawmidi_drain_input(substream); snd_rawmidi_drain_input(substream);
return resize_runtime_buffer(substream->runtime, params, true); err = resize_runtime_buffer(substream->runtime, params, true);
if (err < 0)
return err;
substream->framing = framing;
substream->clock_type = clock_type;
return 0;
} }
EXPORT_SYMBOL(snd_rawmidi_input_params); EXPORT_SYMBOL(snd_rawmidi_input_params);
...@@ -963,6 +982,62 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card, ...@@ -963,6 +982,62 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
static int receive_with_tstamp_framing(struct snd_rawmidi_substream *substream,
const unsigned char *buffer, int src_count, const struct timespec64 *tstamp)
{
struct snd_rawmidi_runtime *runtime = substream->runtime;
struct snd_rawmidi_framing_tstamp *dest_ptr;
struct snd_rawmidi_framing_tstamp frame = { .tv_sec = tstamp->tv_sec, .tv_nsec = tstamp->tv_nsec };
int dest_frames = 0;
int orig_count = src_count;
int frame_size = sizeof(struct snd_rawmidi_framing_tstamp);
BUILD_BUG_ON(frame_size != 0x20);
if (snd_BUG_ON((runtime->hw_ptr & 0x1f) != 0))
return -EINVAL;
while (src_count > 0) {
if ((int)(runtime->buffer_size - runtime->avail) < frame_size) {
runtime->xruns += src_count;
break;
}
if (src_count >= SNDRV_RAWMIDI_FRAMING_DATA_LENGTH)
frame.length = SNDRV_RAWMIDI_FRAMING_DATA_LENGTH;
else {
frame.length = src_count;
memset(frame.data, 0, SNDRV_RAWMIDI_FRAMING_DATA_LENGTH);
}
memcpy(frame.data, buffer, frame.length);
buffer += frame.length;
src_count -= frame.length;
dest_ptr = (struct snd_rawmidi_framing_tstamp *) (runtime->buffer + runtime->hw_ptr);
*dest_ptr = frame;
runtime->avail += frame_size;
runtime->hw_ptr += frame_size;
runtime->hw_ptr %= runtime->buffer_size;
dest_frames++;
}
return orig_count - src_count;
}
static struct timespec64 get_framing_tstamp(struct snd_rawmidi_substream *substream)
{
struct timespec64 ts64 = {0, 0};
switch (substream->clock_type) {
case SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC_RAW:
ktime_get_raw_ts64(&ts64);
break;
case SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC:
ktime_get_ts64(&ts64);
break;
case SNDRV_RAWMIDI_MODE_CLOCK_REALTIME:
ktime_get_real_ts64(&ts64);
break;
}
return ts64;
}
/** /**
* snd_rawmidi_receive - receive the input data from the device * snd_rawmidi_receive - receive the input data from the device
* @substream: the rawmidi substream * @substream: the rawmidi substream
...@@ -977,6 +1052,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream, ...@@ -977,6 +1052,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
const unsigned char *buffer, int count) const unsigned char *buffer, int count)
{ {
unsigned long flags; unsigned long flags;
struct timespec64 ts64 = get_framing_tstamp(substream);
int result = 0, count1; int result = 0, count1;
struct snd_rawmidi_runtime *runtime = substream->runtime; struct snd_rawmidi_runtime *runtime = substream->runtime;
...@@ -987,8 +1063,11 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream, ...@@ -987,8 +1063,11 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
"snd_rawmidi_receive: input is not active!!!\n"); "snd_rawmidi_receive: input is not active!!!\n");
return -EINVAL; return -EINVAL;
} }
spin_lock_irqsave(&runtime->lock, flags); spin_lock_irqsave(&runtime->lock, flags);
if (count == 1) { /* special case, faster code */ if (substream->framing == SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP) {
result = receive_with_tstamp_framing(substream, buffer, count, &ts64);
} else if (count == 1) { /* special case, faster code */
substream->bytes++; substream->bytes++;
if (runtime->avail < runtime->buffer_size) { if (runtime->avail < runtime->buffer_size) {
runtime->buffer[runtime->hw_ptr++] = buffer[0]; runtime->buffer[runtime->hw_ptr++] = buffer[0];
...@@ -1541,6 +1620,8 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, ...@@ -1541,6 +1620,8 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
struct snd_rawmidi_substream *substream; struct snd_rawmidi_substream *substream;
struct snd_rawmidi_runtime *runtime; struct snd_rawmidi_runtime *runtime;
unsigned long buffer_size, avail, xruns; unsigned long buffer_size, avail, xruns;
unsigned int clock_type;
static const char *clock_names[4] = { "none", "realtime", "monotonic", "monotonic raw" };
rmidi = entry->private_data; rmidi = entry->private_data;
snd_iprintf(buffer, "%s\n\n", rmidi->name); snd_iprintf(buffer, "%s\n\n", rmidi->name);
...@@ -1596,6 +1677,14 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, ...@@ -1596,6 +1677,14 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
" Avail : %lu\n" " Avail : %lu\n"
" Overruns : %lu\n", " Overruns : %lu\n",
buffer_size, avail, xruns); buffer_size, avail, xruns);
if (substream->framing == SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP) {
clock_type = substream->clock_type >> SNDRV_RAWMIDI_MODE_CLOCK_SHIFT;
if (!snd_BUG_ON(clock_type >= ARRAY_SIZE(clock_names)))
snd_iprintf(buffer,
" Framing : tstamp\n"
" Clock type : %s\n",
clock_names[clock_type]);
}
} }
} }
} }
......
...@@ -13,7 +13,8 @@ struct snd_rawmidi_params32 { ...@@ -13,7 +13,8 @@ struct snd_rawmidi_params32 {
u32 buffer_size; u32 buffer_size;
u32 avail_min; u32 avail_min;
unsigned int no_active_sensing; /* avoid bit-field */ unsigned int no_active_sensing; /* avoid bit-field */
unsigned char reserved[16]; unsigned int mode;
unsigned char reserved[12];
} __attribute__((packed)); } __attribute__((packed));
static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile, static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile,
...@@ -25,6 +26,7 @@ static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile, ...@@ -25,6 +26,7 @@ static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile,
if (get_user(params.stream, &src->stream) || if (get_user(params.stream, &src->stream) ||
get_user(params.buffer_size, &src->buffer_size) || get_user(params.buffer_size, &src->buffer_size) ||
get_user(params.avail_min, &src->avail_min) || get_user(params.avail_min, &src->avail_min) ||
get_user(params.mode, &src->mode) ||
get_user(val, &src->no_active_sensing)) get_user(val, &src->no_active_sensing))
return -EFAULT; return -EFAULT;
params.no_active_sensing = val; params.no_active_sensing = val;
......
...@@ -67,13 +67,16 @@ static int __init alsa_seq_oss_init(void) ...@@ -67,13 +67,16 @@ static int __init alsa_seq_oss_init(void)
{ {
int rc; int rc;
if ((rc = register_device()) < 0) rc = register_device();
if (rc < 0)
goto error; goto error;
if ((rc = register_proc()) < 0) { rc = register_proc();
if (rc < 0) {
unregister_device(); unregister_device();
goto error; goto error;
} }
if ((rc = snd_seq_oss_create_client()) < 0) { rc = snd_seq_oss_create_client();
if (rc < 0) {
unregister_proc(); unregister_proc();
unregister_device(); unregister_device();
goto error; goto error;
...@@ -133,7 +136,8 @@ odev_release(struct inode *inode, struct file *file) ...@@ -133,7 +136,8 @@ odev_release(struct inode *inode, struct file *file)
{ {
struct seq_oss_devinfo *dp; struct seq_oss_devinfo *dp;
if ((dp = file->private_data) == NULL) dp = file->private_data;
if (!dp)
return 0; return 0;
mutex_lock(&register_mutex); mutex_lock(&register_mutex);
...@@ -226,16 +230,18 @@ register_device(void) ...@@ -226,16 +230,18 @@ register_device(void)
int rc; int rc;
mutex_lock(&register_mutex); mutex_lock(&register_mutex);
if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
NULL, 0, NULL, 0,
&seq_oss_f_ops, NULL)) < 0) { &seq_oss_f_ops, NULL);
if (rc < 0) {
pr_err("ALSA: seq_oss: can't register device seq\n"); pr_err("ALSA: seq_oss: can't register device seq\n");
mutex_unlock(&register_mutex); mutex_unlock(&register_mutex);
return rc; return rc;
} }
if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC,
NULL, 0, NULL, 0,
&seq_oss_f_ops, NULL)) < 0) { &seq_oss_f_ops, NULL);
if (rc < 0) {
pr_err("ALSA: seq_oss: can't register device music\n"); pr_err("ALSA: seq_oss: can't register device music\n");
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0); snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
mutex_unlock(&register_mutex); mutex_unlock(&register_mutex);
......
...@@ -94,10 +94,10 @@ snd_seq_oss_create_client(void) ...@@ -94,10 +94,10 @@ snd_seq_oss_create_client(void)
port_callback.event_input = receive_announce; port_callback.event_input = receive_announce;
port->kernel = &port_callback; port->kernel = &port_callback;
call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port); if (call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port) >= 0) {
if ((system_port = port->addr.port) >= 0) {
struct snd_seq_port_subscribe subs; struct snd_seq_port_subscribe subs;
system_port = port->addr.port;
memset(&subs, 0, sizeof(subs)); memset(&subs, 0, sizeof(subs));
subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM; subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM;
subs.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; subs.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
...@@ -354,7 +354,8 @@ alloc_seq_queue(struct seq_oss_devinfo *dp) ...@@ -354,7 +354,8 @@ alloc_seq_queue(struct seq_oss_devinfo *dp)
qinfo.owner = system_client; qinfo.owner = system_client;
qinfo.locked = 1; qinfo.locked = 1;
strcpy(qinfo.name, "OSS Sequencer Emulation"); strcpy(qinfo.name, "OSS Sequencer Emulation");
if ((rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_QUEUE, &qinfo)) < 0) rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_QUEUE, &qinfo);
if (rc < 0)
return rc; return rc;
dp->queue = qinfo.queue; dp->queue = qinfo.queue;
return 0; return 0;
...@@ -485,7 +486,8 @@ snd_seq_oss_system_info_read(struct snd_info_buffer *buf) ...@@ -485,7 +486,8 @@ snd_seq_oss_system_info_read(struct snd_info_buffer *buf)
snd_iprintf(buf, "\nNumber of applications: %d\n", num_clients); snd_iprintf(buf, "\nNumber of applications: %d\n", num_clients);
for (i = 0; i < num_clients; i++) { for (i = 0; i < num_clients; i++) {
snd_iprintf(buf, "\nApplication %d: ", i); snd_iprintf(buf, "\nApplication %d: ", i);
if ((dp = client_table[i]) == NULL) { dp = client_table[i];
if (!dp) {
snd_iprintf(buf, "*empty*\n"); snd_iprintf(buf, "*empty*\n");
continue; continue;
} }
......
...@@ -152,7 +152,8 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo) ...@@ -152,7 +152,8 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
/* /*
* look for the identical slot * look for the identical slot
*/ */
if ((mdev = find_slot(pinfo->addr.client, pinfo->addr.port)) != NULL) { mdev = find_slot(pinfo->addr.client, pinfo->addr.port);
if (mdev) {
/* already exists */ /* already exists */
snd_use_lock_free(&mdev->use_lock); snd_use_lock_free(&mdev->use_lock);
return 0; return 0;
...@@ -218,7 +219,8 @@ snd_seq_oss_midi_check_exit_port(int client, int port) ...@@ -218,7 +219,8 @@ snd_seq_oss_midi_check_exit_port(int client, int port)
unsigned long flags; unsigned long flags;
int index; int index;
if ((mdev = find_slot(client, port)) != NULL) { mdev = find_slot(client, port);
if (mdev) {
spin_lock_irqsave(&register_lock, flags); spin_lock_irqsave(&register_lock, flags);
midi_devs[mdev->seq_device] = NULL; midi_devs[mdev->seq_device] = NULL;
spin_unlock_irqrestore(&register_lock, flags); spin_unlock_irqrestore(&register_lock, flags);
...@@ -250,7 +252,8 @@ snd_seq_oss_midi_clear_all(void) ...@@ -250,7 +252,8 @@ snd_seq_oss_midi_clear_all(void)
spin_lock_irqsave(&register_lock, flags); spin_lock_irqsave(&register_lock, flags);
for (i = 0; i < max_midi_devs; i++) { for (i = 0; i < max_midi_devs; i++) {
if ((mdev = midi_devs[i]) != NULL) { mdev = midi_devs[i];
if (mdev) {
snd_midi_event_free(mdev->coder); snd_midi_event_free(mdev->coder);
kfree(mdev); kfree(mdev);
midi_devs[i] = NULL; midi_devs[i] = NULL;
...@@ -318,7 +321,8 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode) ...@@ -318,7 +321,8 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
struct seq_oss_midi *mdev; struct seq_oss_midi *mdev;
struct snd_seq_port_subscribe subs; struct snd_seq_port_subscribe subs;
if ((mdev = get_mididev(dp, dev)) == NULL) mdev = get_mididev(dp, dev);
if (!mdev)
return -ENODEV; return -ENODEV;
/* already used? */ /* already used? */
...@@ -384,7 +388,8 @@ snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev) ...@@ -384,7 +388,8 @@ snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
struct seq_oss_midi *mdev; struct seq_oss_midi *mdev;
struct snd_seq_port_subscribe subs; struct snd_seq_port_subscribe subs;
if ((mdev = get_mididev(dp, dev)) == NULL) mdev = get_mididev(dp, dev);
if (!mdev)
return -ENODEV; return -ENODEV;
if (! mdev->opened || mdev->devinfo != dp) { if (! mdev->opened || mdev->devinfo != dp) {
snd_use_lock_free(&mdev->use_lock); snd_use_lock_free(&mdev->use_lock);
...@@ -421,7 +426,8 @@ snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev) ...@@ -421,7 +426,8 @@ snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
struct seq_oss_midi *mdev; struct seq_oss_midi *mdev;
int mode; int mode;
if ((mdev = get_mididev(dp, dev)) == NULL) mdev = get_mididev(dp, dev);
if (!mdev)
return 0; return 0;
mode = 0; mode = 0;
...@@ -443,7 +449,8 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev) ...@@ -443,7 +449,8 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
{ {
struct seq_oss_midi *mdev; struct seq_oss_midi *mdev;
if ((mdev = get_mididev(dp, dev)) == NULL) mdev = get_mididev(dp, dev);
if (!mdev)
return; return;
if (! mdev->opened) { if (! mdev->opened) {
snd_use_lock_free(&mdev->use_lock); snd_use_lock_free(&mdev->use_lock);
...@@ -491,7 +498,8 @@ snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_ad ...@@ -491,7 +498,8 @@ snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_ad
{ {
struct seq_oss_midi *mdev; struct seq_oss_midi *mdev;
if ((mdev = get_mididev(dp, dev)) == NULL) mdev = get_mididev(dp, dev);
if (!mdev)
return; return;
addr->client = mdev->client; addr->client = mdev->client;
addr->port = mdev->port; addr->port = mdev->port;
...@@ -511,7 +519,8 @@ snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private_data) ...@@ -511,7 +519,8 @@ snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private_data)
if (dp->readq == NULL) if (dp->readq == NULL)
return 0; return 0;
if ((mdev = find_slot(ev->source.client, ev->source.port)) == NULL) mdev = find_slot(ev->source.client, ev->source.port);
if (!mdev)
return 0; return 0;
if (! (mdev->opened & PERM_READ)) { if (! (mdev->opened & PERM_READ)) {
snd_use_lock_free(&mdev->use_lock); snd_use_lock_free(&mdev->use_lock);
...@@ -623,7 +632,8 @@ snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, stru ...@@ -623,7 +632,8 @@ snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, stru
{ {
struct seq_oss_midi *mdev; struct seq_oss_midi *mdev;
if ((mdev = get_mididev(dp, dev)) == NULL) mdev = get_mididev(dp, dev);
if (!mdev)
return -ENODEV; return -ENODEV;
if (snd_midi_event_encode_byte(mdev->coder, c, ev)) { if (snd_midi_event_encode_byte(mdev->coder, c, ev)) {
snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port); snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port);
...@@ -642,7 +652,8 @@ snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info ...@@ -642,7 +652,8 @@ snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info
{ {
struct seq_oss_midi *mdev; struct seq_oss_midi *mdev;
if ((mdev = get_mididev(dp, dev)) == NULL) mdev = get_mididev(dp, dev);
if (!mdev)
return -ENXIO; return -ENXIO;
inf->device = dev; inf->device = dev;
inf->dev_type = 0; /* FIXME: ?? */ inf->dev_type = 0; /* FIXME: ?? */
......
...@@ -132,7 +132,8 @@ snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int count, ...@@ -132,7 +132,8 @@ snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int count,
} }
/* insert queue */ /* insert queue */
if ((err = insert_queue(dp, &rec, opt)) < 0) err = insert_queue(dp, &rec, opt);
if (err < 0)
break; break;
result += ev_size; result += ev_size;
......
...@@ -451,7 +451,8 @@ snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt, ...@@ -451,7 +451,8 @@ snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
if (info->is_midi) if (info->is_midi)
return 0; return 0;
if ((rec = get_synthdev(dp, dev)) == NULL) rec = get_synthdev(dp, dev);
if (!rec)
return -ENXIO; return -ENXIO;
if (rec->oper.load_patch == NULL) if (rec->oper.load_patch == NULL)
...@@ -569,7 +570,8 @@ snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, u ...@@ -569,7 +570,8 @@ snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, u
info = get_synthinfo_nospec(dp, dev); info = get_synthinfo_nospec(dp, dev);
if (!info || info->is_midi) if (!info || info->is_midi)
return -ENXIO; return -ENXIO;
if ((rec = get_synthdev(dp, dev)) == NULL) rec = get_synthdev(dp, dev);
if (!rec)
return -ENXIO; return -ENXIO;
if (rec->oper.ioctl == NULL) if (rec->oper.ioctl == NULL)
rc = -ENXIO; rc = -ENXIO;
...@@ -619,7 +621,8 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in ...@@ -619,7 +621,8 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
inf->device = dev; inf->device = dev;
strscpy(inf->name, minf.name, sizeof(inf->name)); strscpy(inf->name, minf.name, sizeof(inf->name));
} else { } else {
if ((rec = get_synthdev(dp, dev)) == NULL) rec = get_synthdev(dp, dev);
if (!rec)
return -ENXIO; return -ENXIO;
inf->synth_type = rec->synth_type; inf->synth_type = rec->synth_type;
inf->synth_subtype = rec->synth_subtype; inf->synth_subtype = rec->synth_subtype;
......
...@@ -27,7 +27,8 @@ snd_seq_oss_writeq_new(struct seq_oss_devinfo *dp, int maxlen) ...@@ -27,7 +27,8 @@ snd_seq_oss_writeq_new(struct seq_oss_devinfo *dp, int maxlen)
struct seq_oss_writeq *q; struct seq_oss_writeq *q;
struct snd_seq_client_pool pool; struct snd_seq_client_pool pool;
if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL) q = kzalloc(sizeof(*q), GFP_KERNEL);
if (!q)
return NULL; return NULL;
q->dp = dp; q->dp = dp;
q->maxlen = maxlen; q->maxlen = maxlen;
......
...@@ -416,7 +416,10 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, ...@@ -416,7 +416,10 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,
if (snd_BUG_ON(!client)) if (snd_BUG_ON(!client))
return -ENXIO; return -ENXIO;
if (!client->accept_input || (fifo = client->data.user.fifo) == NULL) if (!client->accept_input)
return -ENXIO;
fifo = client->data.user.fifo;
if (!fifo)
return -ENXIO; return -ENXIO;
if (atomic_read(&fifo->overflow) > 0) { if (atomic_read(&fifo->overflow) > 0) {
...@@ -435,9 +438,9 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, ...@@ -435,9 +438,9 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,
int nonblock; int nonblock;
nonblock = (file->f_flags & O_NONBLOCK) || result > 0; nonblock = (file->f_flags & O_NONBLOCK) || result > 0;
if ((err = snd_seq_fifo_cell_out(fifo, &cell, nonblock)) < 0) { err = snd_seq_fifo_cell_out(fifo, &cell, nonblock);
if (err < 0)
break; break;
}
if (snd_seq_ev_is_variable(&cell->event)) { if (snd_seq_ev_is_variable(&cell->event)) {
struct snd_seq_event tmpev; struct snd_seq_event tmpev;
tmpev = cell->event; tmpev = cell->event;
...@@ -970,7 +973,8 @@ static int snd_seq_client_enqueue_event(struct snd_seq_client *client, ...@@ -970,7 +973,8 @@ static int snd_seq_client_enqueue_event(struct snd_seq_client *client,
return err; return err;
/* we got a cell. enqueue it. */ /* we got a cell. enqueue it. */
if ((err = snd_seq_enqueue_event(cell, atomic, hop)) < 0) { err = snd_seq_enqueue_event(cell, atomic, hop);
if (err < 0) {
snd_seq_cell_free(cell); snd_seq_cell_free(cell);
return err; return err;
} }
...@@ -1312,7 +1316,8 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg) ...@@ -1312,7 +1316,8 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
return -EINVAL; return -EINVAL;
} }
if (client->type == KERNEL_CLIENT) { if (client->type == KERNEL_CLIENT) {
if ((callback = info->kernel) != NULL) { callback = info->kernel;
if (callback) {
if (callback->owner) if (callback->owner)
port->owner = callback->owner; port->owner = callback->owner;
port->private_data = callback->private_data; port->private_data = callback->private_data;
...@@ -1466,13 +1471,17 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client, ...@@ -1466,13 +1471,17 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
struct snd_seq_client *receiver = NULL, *sender = NULL; struct snd_seq_client *receiver = NULL, *sender = NULL;
struct snd_seq_client_port *sport = NULL, *dport = NULL; struct snd_seq_client_port *sport = NULL, *dport = NULL;
if ((receiver = snd_seq_client_use_ptr(subs->dest.client)) == NULL) receiver = snd_seq_client_use_ptr(subs->dest.client);
if (!receiver)
goto __end; goto __end;
if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) sender = snd_seq_client_use_ptr(subs->sender.client);
if (!sender)
goto __end; goto __end;
if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) sport = snd_seq_port_use_ptr(sender, subs->sender.port);
if (!sport)
goto __end; goto __end;
if ((dport = snd_seq_port_use_ptr(receiver, subs->dest.port)) == NULL) dport = snd_seq_port_use_ptr(receiver, subs->dest.port);
if (!dport)
goto __end; goto __end;
result = check_subscription_permission(client, sport, dport, subs); result = check_subscription_permission(client, sport, dport, subs);
...@@ -1508,13 +1517,17 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client, ...@@ -1508,13 +1517,17 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
struct snd_seq_client *receiver = NULL, *sender = NULL; struct snd_seq_client *receiver = NULL, *sender = NULL;
struct snd_seq_client_port *sport = NULL, *dport = NULL; struct snd_seq_client_port *sport = NULL, *dport = NULL;
if ((receiver = snd_seq_client_use_ptr(subs->dest.client)) == NULL) receiver = snd_seq_client_use_ptr(subs->dest.client);
if (!receiver)
goto __end; goto __end;
if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) sender = snd_seq_client_use_ptr(subs->sender.client);
if (!sender)
goto __end; goto __end;
if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) sport = snd_seq_port_use_ptr(sender, subs->sender.port);
if (!sport)
goto __end; goto __end;
if ((dport = snd_seq_port_use_ptr(receiver, subs->dest.port)) == NULL) dport = snd_seq_port_use_ptr(receiver, subs->dest.port);
if (!dport)
goto __end; goto __end;
result = check_subscription_permission(client, sport, dport, subs); result = check_subscription_permission(client, sport, dport, subs);
...@@ -1926,9 +1939,11 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, ...@@ -1926,9 +1939,11 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
struct snd_seq_client_port *sport = NULL; struct snd_seq_client_port *sport = NULL;
result = -EINVAL; result = -EINVAL;
if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) sender = snd_seq_client_use_ptr(subs->sender.client);
if (!sender)
goto __end; goto __end;
if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) sport = snd_seq_port_use_ptr(sender, subs->sender.port);
if (!sport)
goto __end; goto __end;
result = snd_seq_port_get_subscription(&sport->c_src, &subs->dest, result = snd_seq_port_get_subscription(&sport->c_src, &subs->dest,
subs); subs);
...@@ -1955,9 +1970,11 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg) ...@@ -1955,9 +1970,11 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg)
struct list_head *p; struct list_head *p;
int i; int i;
if ((cptr = snd_seq_client_use_ptr(subs->root.client)) == NULL) cptr = snd_seq_client_use_ptr(subs->root.client);
if (!cptr)
goto __end; goto __end;
if ((port = snd_seq_port_use_ptr(cptr, subs->root.port)) == NULL) port = snd_seq_port_use_ptr(cptr, subs->root.port);
if (!port)
goto __end; goto __end;
switch (subs->type) { switch (subs->type) {
......
...@@ -109,7 +109,8 @@ create_port(int idx, int type) ...@@ -109,7 +109,8 @@ create_port(int idx, int type)
struct snd_seq_port_callback pcb; struct snd_seq_port_callback pcb;
struct snd_seq_dummy_port *rec; struct snd_seq_dummy_port *rec;
if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL) rec = kzalloc(sizeof(*rec), GFP_KERNEL);
if (!rec)
return NULL; return NULL;
rec->client = my_client; rec->client = my_client;
......
...@@ -143,7 +143,8 @@ static struct snd_seq_event_cell *fifo_cell_out(struct snd_seq_fifo *f) ...@@ -143,7 +143,8 @@ static struct snd_seq_event_cell *fifo_cell_out(struct snd_seq_fifo *f)
{ {
struct snd_seq_event_cell *cell; struct snd_seq_event_cell *cell;
if ((cell = f->head) != NULL) { cell = f->head;
if (cell) {
f->head = cell->next; f->head = cell->next;
/* reset tail if this was the last element */ /* reset tail if this was the last element */
......
...@@ -69,7 +69,8 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event, ...@@ -69,7 +69,8 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event,
int len, err; int len, err;
struct snd_seq_event_cell *cell; struct snd_seq_event_cell *cell;
if ((len = get_var_len(event)) <= 0) len = get_var_len(event);
if (len <= 0)
return len; return len;
if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) { if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
...@@ -133,7 +134,8 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char ...@@ -133,7 +134,8 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char
int len, newlen; int len, newlen;
int err; int err;
if ((len = get_var_len(event)) < 0) len = get_var_len(event);
if (len < 0)
return len; return len;
newlen = len; newlen = len;
if (size_aligned > 0) if (size_aligned > 0)
......
...@@ -101,7 +101,8 @@ static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, i ...@@ -101,7 +101,8 @@ static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, i
if (snd_BUG_ON(!substream || !buf)) if (snd_BUG_ON(!substream || !buf))
return -EINVAL; return -EINVAL;
runtime = substream->runtime; runtime = substream->runtime;
if ((tmp = runtime->avail) < count) { tmp = runtime->avail;
if (tmp < count) {
if (printk_ratelimit()) if (printk_ratelimit())
pr_err("ALSA: seq_midi: MIDI output buffer overrun\n"); pr_err("ALSA: seq_midi: MIDI output buffer overrun\n");
return -ENOMEM; return -ENOMEM;
...@@ -167,10 +168,11 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe ...@@ -167,10 +168,11 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe
struct snd_rawmidi_params params; struct snd_rawmidi_params params;
/* open midi port */ /* open midi port */
if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device, err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
msynth->subdevice, msynth->subdevice,
SNDRV_RAWMIDI_LFLG_INPUT, SNDRV_RAWMIDI_LFLG_INPUT,
&msynth->input_rfile)) < 0) { &msynth->input_rfile);
if (err < 0) {
pr_debug("ALSA: seq_midi: midi input open failed!!!\n"); pr_debug("ALSA: seq_midi: midi input open failed!!!\n");
return err; return err;
} }
...@@ -178,7 +180,8 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe ...@@ -178,7 +180,8 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
params.avail_min = 1; params.avail_min = 1;
params.buffer_size = input_buffer_size; params.buffer_size = input_buffer_size;
if ((err = snd_rawmidi_input_params(msynth->input_rfile.input, &params)) < 0) { err = snd_rawmidi_input_params(msynth->input_rfile.input, &params);
if (err < 0) {
snd_rawmidi_kernel_release(&msynth->input_rfile); snd_rawmidi_kernel_release(&msynth->input_rfile);
return err; return err;
} }
...@@ -209,10 +212,11 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info ...@@ -209,10 +212,11 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
struct snd_rawmidi_params params; struct snd_rawmidi_params params;
/* open midi port */ /* open midi port */
if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device, err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
msynth->subdevice, msynth->subdevice,
SNDRV_RAWMIDI_LFLG_OUTPUT, SNDRV_RAWMIDI_LFLG_OUTPUT,
&msynth->output_rfile)) < 0) { &msynth->output_rfile);
if (err < 0) {
pr_debug("ALSA: seq_midi: midi output open failed!!!\n"); pr_debug("ALSA: seq_midi: midi output open failed!!!\n");
return err; return err;
} }
...@@ -220,7 +224,8 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info ...@@ -220,7 +224,8 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
params.avail_min = 1; params.avail_min = 1;
params.buffer_size = output_buffer_size; params.buffer_size = output_buffer_size;
params.no_active_sensing = 1; params.no_active_sensing = 1;
if ((err = snd_rawmidi_output_params(msynth->output_rfile.output, &params)) < 0) { err = snd_rawmidi_output_params(msynth->output_rfile.output, &params);
if (err < 0) {
snd_rawmidi_kernel_release(&msynth->output_rfile); snd_rawmidi_kernel_release(&msynth->output_rfile);
return err; return err;
} }
......
...@@ -222,7 +222,8 @@ struct snd_seq_queue *snd_seq_queue_find_name(char *name) ...@@ -222,7 +222,8 @@ struct snd_seq_queue *snd_seq_queue_find_name(char *name)
struct snd_seq_queue *q; struct snd_seq_queue *q;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
if ((q = queueptr(i)) != NULL) { q = queueptr(i);
if (q) {
if (strncmp(q->name, name, sizeof(q->name)) == 0) if (strncmp(q->name, name, sizeof(q->name)) == 0)
return q; return q;
queuefree(q); queuefree(q);
...@@ -432,7 +433,8 @@ int snd_seq_queue_timer_open(int queueid) ...@@ -432,7 +433,8 @@ int snd_seq_queue_timer_open(int queueid)
if (queue == NULL) if (queue == NULL)
return -EINVAL; return -EINVAL;
tmr = queue->timer; tmr = queue->timer;
if ((result = snd_seq_timer_open(queue)) < 0) { result = snd_seq_timer_open(queue);
if (result < 0) {
snd_seq_timer_defaults(tmr); snd_seq_timer_defaults(tmr);
result = snd_seq_timer_open(queue); result = snd_seq_timer_open(queue);
} }
...@@ -548,7 +550,8 @@ void snd_seq_queue_client_leave(int client) ...@@ -548,7 +550,8 @@ void snd_seq_queue_client_leave(int client)
/* delete own queues from queue list */ /* delete own queues from queue list */
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
if ((q = queue_list_remove(i, client)) != NULL) q = queue_list_remove(i, client);
if (q)
queue_delete(q); queue_delete(q);
} }
...@@ -556,7 +559,8 @@ void snd_seq_queue_client_leave(int client) ...@@ -556,7 +559,8 @@ void snd_seq_queue_client_leave(int client)
* they are not owned by this client * they are not owned by this client
*/ */
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
if ((q = queueptr(i)) == NULL) q = queueptr(i);
if (!q)
continue; continue;
if (test_bit(client, q->clients_bitmap)) { if (test_bit(client, q->clients_bitmap)) {
snd_seq_prioq_leave(q->tickq, client, 0); snd_seq_prioq_leave(q->tickq, client, 0);
...@@ -578,7 +582,8 @@ void snd_seq_queue_client_leave_cells(int client) ...@@ -578,7 +582,8 @@ void snd_seq_queue_client_leave_cells(int client)
struct snd_seq_queue *q; struct snd_seq_queue *q;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
if ((q = queueptr(i)) == NULL) q = queueptr(i);
if (!q)
continue; continue;
snd_seq_prioq_leave(q->tickq, client, 0); snd_seq_prioq_leave(q->tickq, client, 0);
snd_seq_prioq_leave(q->timeq, client, 0); snd_seq_prioq_leave(q->timeq, client, 0);
...@@ -593,7 +598,8 @@ void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info) ...@@ -593,7 +598,8 @@ void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info)
struct snd_seq_queue *q; struct snd_seq_queue *q;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
if ((q = queueptr(i)) == NULL) q = queueptr(i);
if (!q)
continue; continue;
if (test_bit(client, q->clients_bitmap) && if (test_bit(client, q->clients_bitmap) &&
(! (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) || (! (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) ||
...@@ -724,7 +730,8 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry, ...@@ -724,7 +730,8 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry,
int owner; int owner;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
if ((q = queueptr(i)) == NULL) q = queueptr(i);
if (!q)
continue; continue;
tmr = q->timer; tmr = q->timer;
......
...@@ -482,10 +482,11 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi ...@@ -482,10 +482,11 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi
int err; int err;
*rrmidi = NULL; *rrmidi = NULL;
if ((err = snd_rawmidi_new(card, "VirMidi", device, err = snd_rawmidi_new(card, "VirMidi", device,
16, /* may be configurable */ 16, /* may be configurable */
16, /* may be configurable */ 16, /* may be configurable */
&rmidi)) < 0) &rmidi);
if (err < 0)
return err; return err;
strcpy(rmidi->name, rmidi->id); strcpy(rmidi->name, rmidi->id);
rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
......
...@@ -10,20 +10,34 @@ ...@@ -10,20 +10,34 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/export.h> #include <linux/export.h>
#include <sound/memalloc.h> #include <sound/memalloc.h>
#include "memalloc_local.h"
struct snd_sg_page {
void *buf;
dma_addr_t addr;
};
struct snd_sg_buf {
int size; /* allocated byte size */
int pages; /* allocated pages */
int tblsize; /* allocated table size */
struct snd_sg_page *table; /* address table */
struct page **page_table; /* page table (for vmap/vunmap) */
struct device *dev;
};
/* table entries are align to 32 */ /* table entries are align to 32 */
#define SGBUF_TBL_ALIGN 32 #define SGBUF_TBL_ALIGN 32
#define sgbuf_align_table(tbl) ALIGN((tbl), SGBUF_TBL_ALIGN) #define sgbuf_align_table(tbl) ALIGN((tbl), SGBUF_TBL_ALIGN)
int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab) static void snd_dma_sg_free(struct snd_dma_buffer *dmab)
{ {
struct snd_sg_buf *sgbuf = dmab->private_data; struct snd_sg_buf *sgbuf = dmab->private_data;
struct snd_dma_buffer tmpb; struct snd_dma_buffer tmpb;
int i; int i;
if (! sgbuf) if (!sgbuf)
return -EINVAL; return;
vunmap(dmab->area); vunmap(dmab->area);
dmab->area = NULL; dmab->area = NULL;
...@@ -45,15 +59,11 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab) ...@@ -45,15 +59,11 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab)
kfree(sgbuf->page_table); kfree(sgbuf->page_table);
kfree(sgbuf); kfree(sgbuf);
dmab->private_data = NULL; dmab->private_data = NULL;
return 0;
} }
#define MAX_ALLOC_PAGES 32 #define MAX_ALLOC_PAGES 32
void *snd_malloc_sgbuf_pages(struct device *device, static int snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
size_t size, struct snd_dma_buffer *dmab,
size_t *res_size)
{ {
struct snd_sg_buf *sgbuf; struct snd_sg_buf *sgbuf;
unsigned int i, pages, chunk, maxpages; unsigned int i, pages, chunk, maxpages;
...@@ -63,18 +73,16 @@ void *snd_malloc_sgbuf_pages(struct device *device, ...@@ -63,18 +73,16 @@ void *snd_malloc_sgbuf_pages(struct device *device,
int type = SNDRV_DMA_TYPE_DEV; int type = SNDRV_DMA_TYPE_DEV;
pgprot_t prot = PAGE_KERNEL; pgprot_t prot = PAGE_KERNEL;
dmab->area = NULL;
dmab->addr = 0;
dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL); dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
if (! sgbuf) if (!sgbuf)
return NULL; return -ENOMEM;
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC_SG) { if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC_SG) {
type = SNDRV_DMA_TYPE_DEV_UC; type = SNDRV_DMA_TYPE_DEV_UC;
#ifdef pgprot_noncached #ifdef pgprot_noncached
prot = pgprot_noncached(PAGE_KERNEL); prot = pgprot_noncached(PAGE_KERNEL);
#endif #endif
} }
sgbuf->dev = device; sgbuf->dev = dmab->dev.dev;
pages = snd_sgbuf_aligned_pages(size); pages = snd_sgbuf_aligned_pages(size);
sgbuf->tblsize = sgbuf_align_table(pages); sgbuf->tblsize = sgbuf_align_table(pages);
table = kcalloc(sgbuf->tblsize, sizeof(*table), GFP_KERNEL); table = kcalloc(sgbuf->tblsize, sizeof(*table), GFP_KERNEL);
...@@ -94,12 +102,10 @@ void *snd_malloc_sgbuf_pages(struct device *device, ...@@ -94,12 +102,10 @@ void *snd_malloc_sgbuf_pages(struct device *device,
if (chunk > maxpages) if (chunk > maxpages)
chunk = maxpages; chunk = maxpages;
chunk <<= PAGE_SHIFT; chunk <<= PAGE_SHIFT;
if (snd_dma_alloc_pages_fallback(type, device, if (snd_dma_alloc_pages_fallback(type, dmab->dev.dev,
chunk, &tmpb) < 0) { chunk, &tmpb) < 0) {
if (!sgbuf->pages) if (!sgbuf->pages)
goto _failed; goto _failed;
if (!res_size)
goto _failed;
size = sgbuf->pages * PAGE_SIZE; size = sgbuf->pages * PAGE_SIZE;
break; break;
} }
...@@ -124,27 +130,42 @@ void *snd_malloc_sgbuf_pages(struct device *device, ...@@ -124,27 +130,42 @@ void *snd_malloc_sgbuf_pages(struct device *device,
dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, prot); dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, prot);
if (! dmab->area) if (! dmab->area)
goto _failed; goto _failed;
if (res_size) return 0;
*res_size = sgbuf->size;
return dmab->area;
_failed: _failed:
snd_free_sgbuf_pages(dmab); /* free the table */ snd_dma_sg_free(dmab); /* free the table */
return NULL; return -ENOMEM;
} }
/* static dma_addr_t snd_dma_sg_get_addr(struct snd_dma_buffer *dmab,
* compute the max chunk size with continuous pages on sg-buffer size_t offset)
*/ {
unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab, struct snd_sg_buf *sgbuf = dmab->private_data;
unsigned int ofs, unsigned int size) dma_addr_t addr;
addr = sgbuf->table[offset >> PAGE_SHIFT].addr;
addr &= ~((dma_addr_t)PAGE_SIZE - 1);
return addr + offset % PAGE_SIZE;
}
static struct page *snd_dma_sg_get_page(struct snd_dma_buffer *dmab,
size_t offset)
{
struct snd_sg_buf *sgbuf = dmab->private_data;
unsigned int idx = offset >> PAGE_SHIFT;
if (idx >= (unsigned int)sgbuf->pages)
return NULL;
return sgbuf->page_table[idx];
}
static unsigned int snd_dma_sg_get_chunk_size(struct snd_dma_buffer *dmab,
unsigned int ofs,
unsigned int size)
{ {
struct snd_sg_buf *sg = dmab->private_data; struct snd_sg_buf *sg = dmab->private_data;
unsigned int start, end, pg; unsigned int start, end, pg;
if (!sg)
return size;
start = ofs >> PAGE_SHIFT; start = ofs >> PAGE_SHIFT;
end = (ofs + size - 1) >> PAGE_SHIFT; end = (ofs + size - 1) >> PAGE_SHIFT;
/* check page continuity */ /* check page continuity */
...@@ -160,4 +181,11 @@ unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab, ...@@ -160,4 +181,11 @@ unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
/* ok, all on continuous pages */ /* ok, all on continuous pages */
return size; return size;
} }
EXPORT_SYMBOL(snd_sgbuf_get_chunk_size);
const struct snd_malloc_ops snd_dma_sg_ops = {
.alloc = snd_dma_sg_alloc,
.free = snd_dma_sg_free,
.get_addr = snd_dma_sg_get_addr,
.get_page = snd_dma_sg_get_page,
.get_chunk_size = snd_dma_sg_get_chunk_size,
};
...@@ -357,7 +357,8 @@ static void snd_minor_info_read(struct snd_info_entry *entry, struct snd_info_bu ...@@ -357,7 +357,8 @@ static void snd_minor_info_read(struct snd_info_entry *entry, struct snd_info_bu
mutex_lock(&sound_mutex); mutex_lock(&sound_mutex);
for (minor = 0; minor < SNDRV_OS_MINORS; ++minor) { for (minor = 0; minor < SNDRV_OS_MINORS; ++minor) {
if (!(mptr = snd_minors[minor])) mptr = snd_minors[minor];
if (!mptr)
continue; continue;
if (mptr->card >= 0) { if (mptr->card >= 0) {
if (mptr->device >= 0) if (mptr->device >= 0)
......
...@@ -217,7 +217,8 @@ static void snd_minor_info_oss_read(struct snd_info_entry *entry, ...@@ -217,7 +217,8 @@ static void snd_minor_info_oss_read(struct snd_info_entry *entry,
mutex_lock(&sound_oss_mutex); mutex_lock(&sound_oss_mutex);
for (minor = 0; minor < SNDRV_OSS_MINORS; ++minor) { for (minor = 0; minor < SNDRV_OSS_MINORS; ++minor) {
if (!(mptr = snd_oss_minors[minor])) mptr = snd_oss_minors[minor];
if (!mptr)
continue; continue;
if (mptr->card >= 0) if (mptr->card >= 0)
snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", minor, snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", minor,
......
...@@ -104,7 +104,8 @@ static int snd_mpu401_probe(struct platform_device *devptr) ...@@ -104,7 +104,8 @@ static int snd_mpu401_probe(struct platform_device *devptr)
err = snd_mpu401_create(&devptr->dev, dev, &card); err = snd_mpu401_create(&devptr->dev, dev, &card);
if (err < 0) if (err < 0)
return err; return err;
if ((err = snd_card_register(card)) < 0) { err = snd_card_register(card);
if (err < 0) {
snd_card_free(card); snd_card_free(card);
return err; return err;
} }
...@@ -182,7 +183,8 @@ static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev, ...@@ -182,7 +183,8 @@ static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
err = snd_mpu401_create(&pnp_dev->dev, dev, &card); err = snd_mpu401_create(&pnp_dev->dev, dev, &card);
if (err < 0) if (err < 0)
return err; return err;
if ((err = snd_card_register(card)) < 0) { err = snd_card_register(card);
if (err < 0) {
snd_card_free(card); snd_card_free(card);
return err; return err;
} }
...@@ -227,7 +229,8 @@ static int __init alsa_card_mpu401_init(void) ...@@ -227,7 +229,8 @@ static int __init alsa_card_mpu401_init(void)
{ {
int i, err; int i, err;
if ((err = platform_driver_register(&snd_mpu401_driver)) < 0) err = platform_driver_register(&snd_mpu401_driver);
if (err < 0)
return err; return err;
for (i = 0; i < SNDRV_CARDS; i++) { for (i = 0; i < SNDRV_CARDS; i++) {
......
...@@ -271,8 +271,11 @@ static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream) ...@@ -271,8 +271,11 @@ static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream)
int err; int err;
mpu = substream->rmidi->private_data; mpu = substream->rmidi->private_data;
if (mpu->open_input && (err = mpu->open_input(mpu)) < 0) if (mpu->open_input) {
return err; err = mpu->open_input(mpu);
if (err < 0)
return err;
}
if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) { if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
if (snd_mpu401_do_reset(mpu) < 0) if (snd_mpu401_do_reset(mpu) < 0)
goto error_out; goto error_out;
...@@ -293,8 +296,11 @@ static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream) ...@@ -293,8 +296,11 @@ static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
int err; int err;
mpu = substream->rmidi->private_data; mpu = substream->rmidi->private_data;
if (mpu->open_output && (err = mpu->open_output(mpu)) < 0) if (mpu->open_output) {
return err; err = mpu->open_output(mpu);
if (err < 0)
return err;
}
if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) { if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
if (snd_mpu401_do_reset(mpu) < 0) if (snd_mpu401_do_reset(mpu) < 0)
goto error_out; goto error_out;
...@@ -524,8 +530,9 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, ...@@ -524,8 +530,9 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
info_flags |= MPU401_INFO_INPUT | MPU401_INFO_OUTPUT; info_flags |= MPU401_INFO_INPUT | MPU401_INFO_OUTPUT;
in_enable = (info_flags & MPU401_INFO_INPUT) ? 1 : 0; in_enable = (info_flags & MPU401_INFO_INPUT) ? 1 : 0;
out_enable = (info_flags & MPU401_INFO_OUTPUT) ? 1 : 0; out_enable = (info_flags & MPU401_INFO_OUTPUT) ? 1 : 0;
if ((err = snd_rawmidi_new(card, "MPU-401U", device, err = snd_rawmidi_new(card, "MPU-401U", device,
out_enable, in_enable, &rmidi)) < 0) out_enable, in_enable, &rmidi);
if (err < 0)
return err; return err;
mpu = kzalloc(sizeof(*mpu), GFP_KERNEL); mpu = kzalloc(sizeof(*mpu), GFP_KERNEL);
if (!mpu) { if (!mpu) {
......
...@@ -566,7 +566,8 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id) ...@@ -566,7 +566,8 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id)
*/ */
static int snd_mtpav_get_ISA(struct mtpav *mcard) static int snd_mtpav_get_ISA(struct mtpav *mcard)
{ {
if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) { mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI");
if (!mcard->res_port) {
snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port); snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port);
return -EBUSY; return -EBUSY;
} }
...@@ -628,10 +629,11 @@ static int snd_mtpav_get_RAWMIDI(struct mtpav *mcard) ...@@ -628,10 +629,11 @@ static int snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
hwports = 8; hwports = 8;
mcard->num_ports = hwports; mcard->num_ports = hwports;
if ((rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0, rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0,
mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1, mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1,
mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1, mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1,
&mcard->rmidi)) < 0) &mcard->rmidi);
if (rval < 0)
return rval; return rval;
rawmidi = mcard->rmidi; rawmidi = mcard->rmidi;
rawmidi->private_data = mcard; rawmidi->private_data = mcard;
...@@ -744,7 +746,8 @@ static int __init alsa_card_mtpav_init(void) ...@@ -744,7 +746,8 @@ static int __init alsa_card_mtpav_init(void)
{ {
int err; int err;
if ((err = platform_driver_register(&snd_mtpav_driver)) < 0) err = platform_driver_register(&snd_mtpav_driver);
if (err < 0)
return err; return err;
device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0); device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0);
......
...@@ -950,7 +950,8 @@ static int snd_mts64_probe(struct platform_device *pdev) ...@@ -950,7 +950,8 @@ static int snd_mts64_probe(struct platform_device *pdev)
goto free_pardev; goto free_pardev;
} }
if ((err = snd_mts64_create(card, pardev, &mts)) < 0) { err = snd_mts64_create(card, pardev, &mts);
if (err < 0) {
snd_printd("Cannot create main component\n"); snd_printd("Cannot create main component\n");
goto release_pardev; goto release_pardev;
} }
...@@ -963,19 +964,22 @@ static int snd_mts64_probe(struct platform_device *pdev) ...@@ -963,19 +964,22 @@ static int snd_mts64_probe(struct platform_device *pdev)
goto __err; goto __err;
} }
if ((err = snd_mts64_rawmidi_create(card)) < 0) { err = snd_mts64_rawmidi_create(card);
if (err < 0) {
snd_printd("Creating Rawmidi component failed\n"); snd_printd("Creating Rawmidi component failed\n");
goto __err; goto __err;
} }
/* init device */ /* init device */
if ((err = mts64_device_init(p)) < 0) err = mts64_device_init(p);
if (err < 0)
goto __err; goto __err;
platform_set_drvdata(pdev, card); platform_set_drvdata(pdev, card);
/* At this point card will be usable */ /* At this point card will be usable */
if ((err = snd_card_register(card)) < 0) { err = snd_card_register(card);
if (err < 0) {
snd_printd("Cannot register card\n"); snd_printd("Cannot register card\n");
goto __err; goto __err;
} }
...@@ -1031,7 +1035,8 @@ static int __init snd_mts64_module_init(void) ...@@ -1031,7 +1035,8 @@ static int __init snd_mts64_module_init(void)
{ {
int err; int err;
if ((err = platform_driver_register(&snd_mts64_driver)) < 0) err = platform_driver_register(&snd_mts64_driver);
if (err < 0)
return err; return err;
if (parport_register_driver(&mts64_parport_driver) != 0) { if (parport_register_driver(&mts64_parport_driver) != 0) {
......
...@@ -243,7 +243,8 @@ static int snd_opl3_timer1_init(struct snd_opl3 * opl3, int timer_no) ...@@ -243,7 +243,8 @@ static int snd_opl3_timer1_init(struct snd_opl3 * opl3, int timer_no)
tid.card = opl3->card->number; tid.card = opl3->card->number;
tid.device = timer_no; tid.device = timer_no;
tid.subdevice = 0; tid.subdevice = 0;
if ((err = snd_timer_new(opl3->card, "AdLib timer #1", &tid, &timer)) >= 0) { err = snd_timer_new(opl3->card, "AdLib timer #1", &tid, &timer);
if (err >= 0) {
strcpy(timer->name, "AdLib timer #1"); strcpy(timer->name, "AdLib timer #1");
timer->private_data = opl3; timer->private_data = opl3;
timer->hw = snd_opl3_timer1; timer->hw = snd_opl3_timer1;
...@@ -263,7 +264,8 @@ static int snd_opl3_timer2_init(struct snd_opl3 * opl3, int timer_no) ...@@ -263,7 +264,8 @@ static int snd_opl3_timer2_init(struct snd_opl3 * opl3, int timer_no)
tid.card = opl3->card->number; tid.card = opl3->card->number;
tid.device = timer_no; tid.device = timer_no;
tid.subdevice = 0; tid.subdevice = 0;
if ((err = snd_timer_new(opl3->card, "AdLib timer #2", &tid, &timer)) >= 0) { err = snd_timer_new(opl3->card, "AdLib timer #2", &tid, &timer);
if (err >= 0) {
strcpy(timer->name, "AdLib timer #2"); strcpy(timer->name, "AdLib timer #2");
timer->private_data = opl3; timer->private_data = opl3;
timer->hw = snd_opl3_timer2; timer->hw = snd_opl3_timer2;
...@@ -348,7 +350,8 @@ int snd_opl3_new(struct snd_card *card, ...@@ -348,7 +350,8 @@ int snd_opl3_new(struct snd_card *card,
spin_lock_init(&opl3->reg_lock); spin_lock_init(&opl3->reg_lock);
spin_lock_init(&opl3->timer_lock); spin_lock_init(&opl3->timer_lock);
if ((err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops)) < 0) { err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops);
if (err < 0) {
snd_opl3_free(opl3); snd_opl3_free(opl3);
return err; return err;
} }
...@@ -396,19 +399,23 @@ int snd_opl3_create(struct snd_card *card, ...@@ -396,19 +399,23 @@ int snd_opl3_create(struct snd_card *card,
int err; int err;
*ropl3 = NULL; *ropl3 = NULL;
if ((err = snd_opl3_new(card, hardware, &opl3)) < 0) err = snd_opl3_new(card, hardware, &opl3);
if (err < 0)
return err; return err;
if (! integrated) { if (! integrated) {
if ((opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)")) == NULL) { opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)");
if (!opl3->res_l_port) {
snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port); snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port);
snd_device_free(card, opl3); snd_device_free(card, opl3);
return -EBUSY; return -EBUSY;
} }
if (r_port != 0 && if (r_port != 0) {
(opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)")) == NULL) { opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)");
snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port); if (!opl3->res_r_port) {
snd_device_free(card, opl3); snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port);
return -EBUSY; snd_device_free(card, opl3);
return -EBUSY;
}
} }
} }
opl3->l_port = l_port; opl3->l_port = l_port;
...@@ -423,7 +430,8 @@ int snd_opl3_create(struct snd_card *card, ...@@ -423,7 +430,8 @@ int snd_opl3_create(struct snd_card *card,
break; break;
default: default:
opl3->command = &snd_opl2_command; opl3->command = &snd_opl2_command;
if ((err = snd_opl3_detect(opl3)) < 0) { err = snd_opl3_detect(opl3);
if (err < 0) {
snd_printd("OPL2/3 chip not detected at 0x%lx/0x%lx\n", snd_printd("OPL2/3 chip not detected at 0x%lx/0x%lx\n",
opl3->l_port, opl3->r_port); opl3->l_port, opl3->r_port);
snd_device_free(card, opl3); snd_device_free(card, opl3);
...@@ -449,11 +457,14 @@ int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev) ...@@ -449,11 +457,14 @@ int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev)
{ {
int err; int err;
if (timer1_dev >= 0) if (timer1_dev >= 0) {
if ((err = snd_opl3_timer1_init(opl3, timer1_dev)) < 0) err = snd_opl3_timer1_init(opl3, timer1_dev);
if (err < 0)
return err; return err;
}
if (timer2_dev >= 0) { if (timer2_dev >= 0) {
if ((err = snd_opl3_timer2_init(opl3, timer2_dev)) < 0) { err = snd_opl3_timer2_init(opl3, timer2_dev);
if (err < 0) {
snd_device_free(opl3->card, opl3->timer1); snd_device_free(opl3->card, opl3->timer1);
opl3->timer1 = NULL; opl3->timer1 = NULL;
return err; return err;
...@@ -477,7 +488,8 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3, ...@@ -477,7 +488,8 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3,
/* create hardware dependent device (direct FM) */ /* create hardware dependent device (direct FM) */
if ((err = snd_hwdep_new(card, "OPL2/OPL3", device, &hw)) < 0) { err = snd_hwdep_new(card, "OPL2/OPL3", device, &hw);
if (err < 0) {
snd_device_free(card, opl3); snd_device_free(card, opl3);
return err; return err;
} }
......
...@@ -180,8 +180,7 @@ static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op, ...@@ -180,8 +180,7 @@ static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op,
if (vp2->state == SNDRV_OPL3_ST_ON_2OP) { if (vp2->state == SNDRV_OPL3_ST_ON_2OP) {
/* kill two voices, EXPENSIVE */ /* kill two voices, EXPENSIVE */
bp++; bp++;
voice_time = (voice_time > vp->time) ? voice_time = max(voice_time, vp2->time);
voice_time : vp->time;
} }
} else { } else {
/* allocate 2op voice */ /* allocate 2op voice */
......
...@@ -136,7 +136,8 @@ static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) ...@@ -136,7 +136,8 @@ static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
if (snd_BUG_ON(!arg)) if (snd_BUG_ON(!arg))
return -ENXIO; return -ENXIO;
if ((err = snd_opl3_synth_setup(opl3)) < 0) err = snd_opl3_synth_setup(opl3);
if (err < 0)
return err; return err;
/* fill the argument data */ /* fill the argument data */
...@@ -144,7 +145,8 @@ static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) ...@@ -144,7 +145,8 @@ static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
arg->addr.client = opl3->oss_chset->client; arg->addr.client = opl3->oss_chset->client;
arg->addr.port = opl3->oss_chset->port; arg->addr.port = opl3->oss_chset->port;
if ((err = snd_opl3_synth_use_inc(opl3)) < 0) err = snd_opl3_synth_use_inc(opl3);
if (err < 0)
return err; return err;
opl3->synth_mode = SNDRV_OPL3_MODE_SYNTH; opl3->synth_mode = SNDRV_OPL3_MODE_SYNTH;
......
...@@ -92,7 +92,8 @@ static int snd_opl3_synth_use(void *private_data, struct snd_seq_port_subscribe ...@@ -92,7 +92,8 @@ static int snd_opl3_synth_use(void *private_data, struct snd_seq_port_subscribe
struct snd_opl3 *opl3 = private_data; struct snd_opl3 *opl3 = private_data;
int err; int err;
if ((err = snd_opl3_synth_setup(opl3)) < 0) err = snd_opl3_synth_setup(opl3);
if (err < 0)
return err; return err;
if (use_internal_drums) { if (use_internal_drums) {
...@@ -107,7 +108,8 @@ static int snd_opl3_synth_use(void *private_data, struct snd_seq_port_subscribe ...@@ -107,7 +108,8 @@ static int snd_opl3_synth_use(void *private_data, struct snd_seq_port_subscribe
} }
if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) { if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) {
if ((err = snd_opl3_synth_use_inc(opl3)) < 0) err = snd_opl3_synth_use_inc(opl3);
if (err < 0)
return err; return err;
} }
opl3->synth_mode = SNDRV_OPL3_MODE_SEQ; opl3->synth_mode = SNDRV_OPL3_MODE_SEQ;
...@@ -227,7 +229,8 @@ static int snd_opl3_seq_probe(struct device *_dev) ...@@ -227,7 +229,8 @@ static int snd_opl3_seq_probe(struct device *_dev)
if (client < 0) if (client < 0)
return client; return client;
if ((err = snd_opl3_synth_create_port(opl3)) < 0) { err = snd_opl3_synth_create_port(opl3);
if (err < 0) {
snd_seq_delete_kernel_client(client); snd_seq_delete_kernel_client(client);
opl3->seq_client = -1; opl3->seq_client = -1;
return err; return err;
......
...@@ -749,7 +749,8 @@ static int snd_portman_probe(struct platform_device *pdev) ...@@ -749,7 +749,8 @@ static int snd_portman_probe(struct platform_device *pdev)
goto free_pardev; goto free_pardev;
} }
if ((err = portman_create(card, pardev, &pm)) < 0) { err = portman_create(card, pardev, &pm);
if (err < 0) {
snd_printd("Cannot create main component\n"); snd_printd("Cannot create main component\n");
goto release_pardev; goto release_pardev;
} }
...@@ -762,19 +763,22 @@ static int snd_portman_probe(struct platform_device *pdev) ...@@ -762,19 +763,22 @@ static int snd_portman_probe(struct platform_device *pdev)
goto __err; goto __err;
} }
if ((err = snd_portman_rawmidi_create(card)) < 0) { err = snd_portman_rawmidi_create(card);
if (err < 0) {
snd_printd("Creating Rawmidi component failed\n"); snd_printd("Creating Rawmidi component failed\n");
goto __err; goto __err;
} }
/* init device */ /* init device */
if ((err = portman_device_init(pm)) < 0) err = portman_device_init(pm);
if (err < 0)
goto __err; goto __err;
platform_set_drvdata(pdev, card); platform_set_drvdata(pdev, card);
/* At this point card will be usable */ /* At this point card will be usable */
if ((err = snd_card_register(card)) < 0) { err = snd_card_register(card);
if (err < 0) {
snd_printd("Cannot register card\n"); snd_printd("Cannot register card\n");
goto __err; goto __err;
} }
...@@ -831,7 +835,8 @@ static int __init snd_portman_module_init(void) ...@@ -831,7 +835,8 @@ static int __init snd_portman_module_init(void)
{ {
int err; int err;
if ((err = platform_driver_register(&snd_portman_driver)) < 0) err = platform_driver_register(&snd_portman_driver);
if (err < 0)
return err; return err;
if (parport_register_driver(&portman_parport_driver) != 0) { if (parport_register_driver(&portman_parport_driver) != 0) {
......
...@@ -783,7 +783,8 @@ static int snd_uart16550_create(struct snd_card *card, ...@@ -783,7 +783,8 @@ static int snd_uart16550_create(struct snd_card *card,
int err; int err;
if ((uart = kzalloc(sizeof(*uart), GFP_KERNEL)) == NULL) uart = kzalloc(sizeof(*uart), GFP_KERNEL);
if (!uart)
return -ENOMEM; return -ENOMEM;
uart->adaptor = adaptor; uart->adaptor = adaptor;
uart->card = card; uart->card = card;
...@@ -792,7 +793,8 @@ static int snd_uart16550_create(struct snd_card *card, ...@@ -792,7 +793,8 @@ static int snd_uart16550_create(struct snd_card *card,
uart->base = iobase; uart->base = iobase;
uart->drop_on_full = droponfull; uart->drop_on_full = droponfull;
if ((err = snd_uart16550_detect(uart)) <= 0) { err = snd_uart16550_detect(uart);
if (err <= 0) {
printk(KERN_ERR "no UART detected at 0x%lx\n", iobase); printk(KERN_ERR "no UART detected at 0x%lx\n", iobase);
snd_uart16550_free(uart); snd_uart16550_free(uart);
return -ENODEV; return -ENODEV;
...@@ -818,7 +820,8 @@ static int snd_uart16550_create(struct snd_card *card, ...@@ -818,7 +820,8 @@ static int snd_uart16550_create(struct snd_card *card,
uart->timer_running = 0; uart->timer_running = 0;
/* Register device */ /* Register device */
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, uart, &ops)) < 0) { err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, uart, &ops);
if (err < 0) {
snd_uart16550_free(uart); snd_uart16550_free(uart);
return err; return err;
} }
...@@ -932,14 +935,10 @@ static int snd_serial_probe(struct platform_device *devptr) ...@@ -932,14 +935,10 @@ static int snd_serial_probe(struct platform_device *devptr)
strcpy(card->driver, "Serial"); strcpy(card->driver, "Serial");
strcpy(card->shortname, "Serial MIDI (UART16550A)"); strcpy(card->shortname, "Serial MIDI (UART16550A)");
if ((err = snd_uart16550_create(card, err = snd_uart16550_create(card, port[dev], irq[dev], speed[dev],
port[dev], base[dev], adaptor[dev], droponfull[dev],
irq[dev], &uart);
speed[dev], if (err < 0)
base[dev],
adaptor[dev],
droponfull[dev],
&uart)) < 0)
goto _err; goto _err;
err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi); err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi);
...@@ -952,7 +951,8 @@ static int snd_serial_probe(struct platform_device *devptr) ...@@ -952,7 +951,8 @@ static int snd_serial_probe(struct platform_device *devptr)
uart->base, uart->base,
uart->irq); uart->irq);
if ((err = snd_card_register(card)) < 0) err = snd_card_register(card);
if (err < 0)
goto _err; goto _err;
platform_set_drvdata(devptr, card); platform_set_drvdata(devptr, card);
...@@ -992,7 +992,8 @@ static int __init alsa_card_serial_init(void) ...@@ -992,7 +992,8 @@ static int __init alsa_card_serial_init(void)
{ {
int i, cards, err; int i, cards, err;
if ((err = platform_driver_register(&snd_serial_driver)) < 0) err = platform_driver_register(&snd_serial_driver);
if (err < 0)
return err; return err;
cards = 0; cards = 0;
......
...@@ -110,20 +110,25 @@ static int vx_transfer_end(struct vx_core *chip, int cmd) ...@@ -110,20 +110,25 @@ static int vx_transfer_end(struct vx_core *chip, int cmd)
{ {
int err; int err;
if ((err = vx_reset_chk(chip)) < 0) err = vx_reset_chk(chip);
if (err < 0)
return err; return err;
/* irq MESS_READ/WRITE_END */ /* irq MESS_READ/WRITE_END */
if ((err = vx_send_irq_dsp(chip, cmd)) < 0) err = vx_send_irq_dsp(chip, cmd);
if (err < 0)
return err; return err;
/* Wait CHK = 1 */ /* Wait CHK = 1 */
if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) err = vx_wait_isr_bit(chip, ISR_CHK);
if (err < 0)
return err; return err;
/* If error, Read RX */ /* If error, Read RX */
if ((err = vx_inb(chip, ISR)) & ISR_ERR) { err = vx_inb(chip, ISR);
if ((err = vx_wait_for_rx_full(chip)) < 0) { if (err & ISR_ERR) {
err = vx_wait_for_rx_full(chip);
if (err < 0) {
snd_printd(KERN_DEBUG "transfer_end: error in rx_full\n"); snd_printd(KERN_DEBUG "transfer_end: error in rx_full\n");
return err; return err;
} }
...@@ -232,7 +237,8 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) ...@@ -232,7 +237,8 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
if (chip->chip_status & VX_STAT_IS_STALE) if (chip->chip_status & VX_STAT_IS_STALE)
return -EBUSY; return -EBUSY;
if ((err = vx_reset_chk(chip)) < 0) { err = vx_reset_chk(chip);
if (err < 0) {
snd_printd(KERN_DEBUG "vx_send_msg: vx_reset_chk error\n"); snd_printd(KERN_DEBUG "vx_send_msg: vx_reset_chk error\n");
return err; return err;
} }
...@@ -254,7 +260,8 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) ...@@ -254,7 +260,8 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
rmh->Cmd[0] &= MASK_1_WORD_COMMAND; rmh->Cmd[0] &= MASK_1_WORD_COMMAND;
/* Wait for TX empty */ /* Wait for TX empty */
if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) { err = vx_wait_isr_bit(chip, ISR_TX_EMPTY);
if (err < 0) {
snd_printd(KERN_DEBUG "vx_send_msg: wait tx empty error\n"); snd_printd(KERN_DEBUG "vx_send_msg: wait tx empty error\n");
return err; return err;
} }
...@@ -265,18 +272,21 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) ...@@ -265,18 +272,21 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
vx_outb(chip, TXL, rmh->Cmd[0] & 0xff); vx_outb(chip, TXL, rmh->Cmd[0] & 0xff);
/* Trigger irq MESSAGE */ /* Trigger irq MESSAGE */
if ((err = vx_send_irq_dsp(chip, IRQ_MESSAGE)) < 0) { err = vx_send_irq_dsp(chip, IRQ_MESSAGE);
if (err < 0) {
snd_printd(KERN_DEBUG "vx_send_msg: send IRQ_MESSAGE error\n"); snd_printd(KERN_DEBUG "vx_send_msg: send IRQ_MESSAGE error\n");
return err; return err;
} }
/* Wait for CHK = 1 */ /* Wait for CHK = 1 */
if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) err = vx_wait_isr_bit(chip, ISR_CHK);
if (err < 0)
return err; return err;
/* If error, get error value from RX */ /* If error, get error value from RX */
if (vx_inb(chip, ISR) & ISR_ERR) { if (vx_inb(chip, ISR) & ISR_ERR) {
if ((err = vx_wait_for_rx_full(chip)) < 0) { err = vx_wait_for_rx_full(chip);
if (err < 0) {
snd_printd(KERN_DEBUG "vx_send_msg: rx_full read error\n"); snd_printd(KERN_DEBUG "vx_send_msg: rx_full read error\n");
return err; return err;
} }
...@@ -292,7 +302,8 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) ...@@ -292,7 +302,8 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
if (rmh->LgCmd > 1) { if (rmh->LgCmd > 1) {
for (i = 1; i < rmh->LgCmd; i++) { for (i = 1; i < rmh->LgCmd; i++) {
/* Wait for TX ready */ /* Wait for TX ready */
if ((err = vx_wait_isr_bit(chip, ISR_TX_READY)) < 0) { err = vx_wait_isr_bit(chip, ISR_TX_READY);
if (err < 0) {
snd_printd(KERN_DEBUG "vx_send_msg: tx_ready error\n"); snd_printd(KERN_DEBUG "vx_send_msg: tx_ready error\n");
return err; return err;
} }
...@@ -303,13 +314,15 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) ...@@ -303,13 +314,15 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
vx_outb(chip, TXL, rmh->Cmd[i] & 0xff); vx_outb(chip, TXL, rmh->Cmd[i] & 0xff);
/* Trigger irq MESS_READ_NEXT */ /* Trigger irq MESS_READ_NEXT */
if ((err = vx_send_irq_dsp(chip, IRQ_MESS_READ_NEXT)) < 0) { err = vx_send_irq_dsp(chip, IRQ_MESS_READ_NEXT);
if (err < 0) {
snd_printd(KERN_DEBUG "vx_send_msg: IRQ_READ_NEXT error\n"); snd_printd(KERN_DEBUG "vx_send_msg: IRQ_READ_NEXT error\n");
return err; return err;
} }
} }
/* Wait for TX empty */ /* Wait for TX empty */
if ((err = vx_wait_isr_bit(chip, ISR_TX_READY)) < 0) { err = vx_wait_isr_bit(chip, ISR_TX_READY);
if (err < 0) {
snd_printd(KERN_DEBUG "vx_send_msg: TX_READY error\n"); snd_printd(KERN_DEBUG "vx_send_msg: TX_READY error\n");
return err; return err;
} }
...@@ -362,17 +375,21 @@ int vx_send_rih_nolock(struct vx_core *chip, int cmd) ...@@ -362,17 +375,21 @@ int vx_send_rih_nolock(struct vx_core *chip, int cmd)
#if 0 #if 0
printk(KERN_DEBUG "send_rih: cmd = 0x%x\n", cmd); printk(KERN_DEBUG "send_rih: cmd = 0x%x\n", cmd);
#endif #endif
if ((err = vx_reset_chk(chip)) < 0) err = vx_reset_chk(chip);
if (err < 0)
return err; return err;
/* send the IRQ */ /* send the IRQ */
if ((err = vx_send_irq_dsp(chip, cmd)) < 0) err = vx_send_irq_dsp(chip, cmd);
if (err < 0)
return err; return err;
/* Wait CHK = 1 */ /* Wait CHK = 1 */
if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) err = vx_wait_isr_bit(chip, ISR_CHK);
if (err < 0)
return err; return err;
/* If error, read RX */ /* If error, read RX */
if (vx_inb(chip, ISR) & ISR_ERR) { if (vx_inb(chip, ISR) & ISR_ERR) {
if ((err = vx_wait_for_rx_full(chip)) < 0) err = vx_wait_for_rx_full(chip);
if (err < 0)
return err; return err;
err = vx_inb(chip, RXH) << 16; err = vx_inb(chip, RXH) << 16;
err |= vx_inb(chip, RXM) << 8; err |= vx_inb(chip, RXM) << 8;
...@@ -648,7 +665,8 @@ int snd_vx_dsp_boot(struct vx_core *chip, const struct firmware *boot) ...@@ -648,7 +665,8 @@ int snd_vx_dsp_boot(struct vx_core *chip, const struct firmware *boot)
vx_reset_board(chip, cold_reset); vx_reset_board(chip, cold_reset);
vx_validate_irq(chip, 0); vx_validate_irq(chip, 0);
if ((err = snd_vx_load_boot_image(chip, boot)) < 0) err = snd_vx_load_boot_image(chip, boot);
if (err < 0)
return err; return err;
msleep(10); msleep(10);
...@@ -678,7 +696,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp) ...@@ -678,7 +696,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp)
for (i = 0; i < dsp->size; i += 3) { for (i = 0; i < dsp->size; i += 3) {
image = dsp->data + i; image = dsp->data + i;
/* Wait DSP ready for a new read */ /* Wait DSP ready for a new read */
if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) { err = vx_wait_isr_bit(chip, ISR_TX_EMPTY);
if (err < 0) {
printk(KERN_ERR printk(KERN_ERR
"dsp loading error at position %d\n", i); "dsp loading error at position %d\n", i);
return err; return err;
...@@ -698,7 +717,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp) ...@@ -698,7 +717,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp)
msleep(200); msleep(200);
if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) err = vx_wait_isr_bit(chip, ISR_CHK);
if (err < 0)
return err; return err;
vx_toggle_dac_mute(chip, 0); vx_toggle_dac_mute(chip, 0);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -410,10 +410,10 @@ static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, ...@@ -410,10 +410,10 @@ static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s,
* @s: the AMDTP stream to initialize * @s: the AMDTP stream to initialize
* @unit: the target of the stream * @unit: the target of the stream
* @dir: the direction of stream * @dir: the direction of stream
* @flags: the packet transmission method to use * @flags: the details of the streaming protocol consist of cip_flags enumeration-constants.
*/ */
int amdtp_am824_init(struct amdtp_stream *s, struct fw_unit *unit, int amdtp_am824_init(struct amdtp_stream *s, struct fw_unit *unit,
enum amdtp_stream_direction dir, enum cip_flags flags) enum amdtp_stream_direction dir, unsigned int flags)
{ {
amdtp_stream_process_ctx_payloads_t process_ctx_payloads; amdtp_stream_process_ctx_payloads_t process_ctx_payloads;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册