sound updates for 5.14
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 -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmDezZ8OHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE8kxhAAhWyQBU9HX7xo/132J0SsP0tqT0NhePr217T7 RSmRre3kD8iNDtpe9P9eziyN5q5TB8+InY52yUiDiWdSxCHOBDKBPwzzDeVRdOGg /BdQqCtEAtdgzsnPEsXxvK+y3LayLwlkCyN1kMLCl4KGFfMg8fQgMbXobEOfyKwT r23Xgbkb8jIFyjEAmvJnbvPXjkUjv2ew0+RB+cqV80m9h+KdNN/k/8+0wdWaQBEd 6oRSE8ApYclgyLf4TYCkLAwTP3NQ8SuvYSuZ9tFGy7vjz7l69xPWS/6ndbfrJvEP pO615dYWKTWQKi2SjStnjFUH7ODirbPZzyDqU9tvEAGbKj0l07LNXy0JrbwJ8VB2 JBfsdTlmSwHcAXmj0JB7IhflmG96W9azUKf1a8YNJLw7UgHoXjDZC0NFtOanaB7x PEdf+27Ty1pZaNbtJpwdzEyc06UNA8dNRAr6FsSMphRTnBBzcUz2uEAfWbevS7Yl Q5IOZd2lqKIUHPB6j2r0iDiCKScXzlHVhFzOLj3vHS4L8vjfbVshxkIkSY0HeA9r HINbkby2mpk901oyqaFwTLkoatXBk5zDX2m2ow7rQLLUIdF0hWBXrE5Xrl3c/T/x aFXuDxJfZm4YibJiBAOO5xv03DzVBNJz01E020oyum2m0NHhB1xD3RK428pcjshV zgXJaZg= =IN9G -----END PGP SIGNATURE----- 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() ...
This commit is contained in:
commit
d6b63b5b7d
|
@ -23,6 +23,7 @@ Optional properties:
|
|||
default output clock name
|
||||
- rockchip,system-power-controller: Telling whether or not this pmic is controlling
|
||||
the system power.
|
||||
- wakeup-source: Device can be used as a wakeup source.
|
||||
|
||||
Optional RK805 properties:
|
||||
- vcc1-supply: The input supply for DCDC_REG1
|
||||
|
@ -63,8 +64,18 @@ Optional RK809 properties:
|
|||
- vcc9-supply: The input supply for DCDC_REG5, SWITCH_REG2
|
||||
|
||||
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
|
||||
- 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:
|
||||
- vcc1-supply: The input supply for DCDC_REG1
|
||||
|
@ -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:
|
|||
|
||||
properties:
|
||||
"#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:
|
||||
oneOf:
|
||||
|
@ -50,7 +54,7 @@ additionalProperties: false
|
|||
examples:
|
||||
- |
|
||||
audio-codec@1c22e00 {
|
||||
#sound-dai-cells = <0>;
|
||||
#sound-dai-cells = <1>;
|
||||
compatible = "allwinner,sun8i-a33-codec";
|
||||
reg = <0x01c22e00 0x400>;
|
||||
interrupts = <0 29 4>;
|
||||
|
|
|
@ -81,6 +81,13 @@ Optional properties:
|
|||
< x1 x2 x3 x4 >
|
||||
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:
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ properties:
|
|||
- fsl,imx8mq-spdif
|
||||
- fsl,imx8mm-spdif
|
||||
- fsl,imx8mn-spdif
|
||||
- fsl,imx8ulp-spdif
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
@ -9,8 +9,10 @@ Required properties:
|
|||
|
||||
- compatible : Compatible list, contains "fsl,vf610-sai",
|
||||
"fsl,imx6sx-sai", "fsl,imx6ul-sai",
|
||||
"fsl,imx7ulp-sai", "fsl,imx8mq-sai" or
|
||||
"fsl,imx8qm-sai".
|
||||
"fsl,imx7ulp-sai", "fsl,imx8mq-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.
|
||||
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
# 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>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -1,28 +0,0 @@
|
|||
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>;
|
||||
};
|
|
@ -0,0 +1,119 @@
|
|||
# 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
|
||||
>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,58 @@
|
|||
# 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:
|
|||
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
|
||||
|
||||
clock-output-names:
|
||||
const: mclk
|
||||
|
||||
|
@ -159,6 +184,11 @@ examples:
|
|||
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-headset-vthreshold-microvolt = <1700000>;
|
||||
qcom,mbhc-headphone-vthreshold-microvolt = <50000>;
|
||||
clock-names = "extclk";
|
||||
clocks = <&rpmhcc 2>;
|
||||
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
# 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>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,146 @@
|
|||
# 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:
|
|||
power-domains: true
|
||||
|
||||
resets:
|
||||
minItems: 1
|
||||
maxItems: 11
|
||||
|
||||
reset-names:
|
||||
minItems: 1
|
||||
maxItems: 11
|
||||
|
||||
clocks:
|
||||
|
@ -110,6 +112,13 @@ properties:
|
|||
- pattern: '^dvc\.[0-1]$'
|
||||
- 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:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
@ -257,7 +266,6 @@ required:
|
|||
- "#sound-dai-cells"
|
||||
|
||||
allOf:
|
||||
- $ref: audio-graph.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
|
|
@ -75,6 +75,10 @@ properties:
|
|||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
enum: [ 0, 1, 2, 3 ]
|
||||
|
||||
port:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
@ -6,6 +6,7 @@ Required properties:
|
|||
- compatible - "string" - One of:
|
||||
"ti,tlv320aic32x4" TLV320AIC3204
|
||||
"ti,tlv320aic32x6" TLV320AIC3206, TLV320AIC3256
|
||||
"ti,tas2505" TAS2505, TAS2521
|
||||
- reg: I2C slave address
|
||||
- supply-*: Required supply regulators are:
|
||||
"iov" - digital IO power supply
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
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>;
|
||||
};
|
|
@ -0,0 +1,42 @@
|
|||
# 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
|
|||
---------------
|
||||
|
||||
Auto-Mute Mode
|
||||
See Reatek codecs.
|
||||
See Realtek codecs.
|
||||
|
||||
|
||||
Analog codecs
|
||||
|
|
|
@ -3508,14 +3508,15 @@ field must be set, though).
|
|||
|
||||
“IEC958 Playback Con Mask” is used to return the bit-mask for the IEC958
|
||||
status bits of consumer mode. Similarly, “IEC958 Playback Pro Mask”
|
||||
returns the bitmask for professional mode. They are read-only controls,
|
||||
and are defined as MIXER controls (iface =
|
||||
``SNDRV_CTL_ELEM_IFACE_MIXER``).
|
||||
returns the bitmask for professional mode. They are read-only controls.
|
||||
|
||||
Meanwhile, “IEC958 Playback Default” control is defined for getting and
|
||||
setting the current default IEC958 bits. Note that this one is usually
|
||||
defined as a PCM control (iface = ``SNDRV_CTL_ELEM_IFACE_PCM``),
|
||||
although in some places it's defined as a MIXER control.
|
||||
setting the current default IEC958 bits.
|
||||
|
||||
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
|
||||
set the raw bit mode. The implementation will depend on the chip, but
|
||||
|
|
14
MAINTAINERS
14
MAINTAINERS
|
@ -7179,6 +7179,13 @@ L: linux-input@vger.kernel.org
|
|||
S: Maintained
|
||||
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
|
||||
M: Rain River <rain.1986.08.12@gmail.com>
|
||||
M: Zhu Yanjun <zyjzyj2000@gmail.com>
|
||||
|
@ -13321,6 +13328,13 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/sound/tfa9879.txt
|
||||
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
|
||||
R: Charles Gorand <charles.gorand@effinnov.com>
|
||||
L: linux-nfc@lists.01.org (subscribers-only)
|
||||
|
|
|
@ -65,6 +65,7 @@ static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
|
|||
switch (reg) {
|
||||
case RK817_SECONDS_REG ... RK817_WEEKS_REG:
|
||||
case RK817_RTC_STATUS_REG:
|
||||
case RK817_CODEC_DTOP_LPT_SRST:
|
||||
case RK817_INT_STS_REG0:
|
||||
case RK817_INT_STS_REG1:
|
||||
case RK817_INT_STS_REG2:
|
||||
|
@ -163,6 +164,7 @@ static const struct mfd_cell rk817s[] = {
|
|||
.num_resources = ARRAY_SIZE(rk817_rtc_resources),
|
||||
.resources = &rk817_rtc_resources[0],
|
||||
},
|
||||
{ .name = "rk817-codec",},
|
||||
};
|
||||
|
||||
static const struct mfd_cell rk818s[] = {
|
||||
|
@ -201,6 +203,85 @@ static const struct rk808_reg_data rk808_pre_init_reg[] = {
|
|||
|
||||
static const struct rk808_reg_data rk817_pre_init_reg[] = {
|
||||
{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_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK,
|
||||
RK817_HOTDIE_105 | RK817_TSD_140},
|
||||
|
|
|
@ -492,7 +492,7 @@ int sdw_read_no_pm(struct sdw_slave *slave, u32 addr)
|
|||
}
|
||||
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;
|
||||
|
||||
|
@ -503,6 +503,21 @@ static int sdw_update_no_pm(struct sdw_slave *slave, u32 addr, u8 mask, u8 val)
|
|||
tmp = (tmp & ~mask) | val;
|
||||
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
|
||||
|
|
|
@ -201,19 +201,6 @@ static inline void sdw_fill_port_params(struct sdw_port_params *params,
|
|||
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 */
|
||||
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);
|
||||
|
|
|
@ -129,6 +129,8 @@
|
|||
#define TX_CODEC_DMA_TX_5 124
|
||||
#define RX_CODEC_DMA_RX_6 125
|
||||
#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_EBIT 2
|
||||
|
|
|
@ -437,6 +437,87 @@ enum rk809_reg_id {
|
|||
#define RK817_RTC_COMP_LSB_REG 0x10
|
||||
#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_SLP_EN_REG(i) (0xb5 + (i))
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#define WCD934X_EFUSE_SENSE_STATE_DEF 0x10
|
||||
#define WCD934X_EFUSE_SENSE_EN_MASK 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_OUT15 0x0038
|
||||
#define WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS 0x0039
|
||||
|
@ -103,21 +105,58 @@
|
|||
#define WCD934X_ANA_AMIC3 0x0610
|
||||
#define WCD934X_ANA_AMIC4 0x0611
|
||||
#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_BIAS_EN_MASK BIT(0)
|
||||
#define WCD934X_ANA_MBHC_BIAS_EN BIT(0)
|
||||
#define WCD934X_ANA_MBHC_ZDET 0x0616
|
||||
#define WCD934X_ANA_MBHC_RESULT_1 0x0617
|
||||
#define WCD934X_ANA_MBHC_RESULT_2 0x0618
|
||||
#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_MICB_VAL_MASK GENMASK(5, 0)
|
||||
#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_ENABLE 0x40
|
||||
#define WCD934X_ANA_MICB_DISABLE 0x0
|
||||
#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_MICB4 0x0626
|
||||
#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_2 0x066c
|
||||
#define WCD934X_MICB2_TEST_CTL_1 0x066e
|
||||
|
@ -141,7 +180,11 @@
|
|||
#define WCD934X_HPH_CNP_WG_CTL 0x06cc
|
||||
#define WCD934X_HPH_GM3_BOOST_EN_MASK 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_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_GAIN_SRC_SEL_MASK BIT(5)
|
||||
#define WCD934X_HPH_GAIN_SRC_SEL_COMPANDER 0
|
||||
|
@ -152,6 +195,8 @@
|
|||
#define WCD934X_HPH_OCP_DET_MASK BIT(0)
|
||||
#define WCD934X_HPH_OCP_DET_ENABLE BIT(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_LO1_COMPANDER 0x06eb
|
||||
#define WCD934X_CLK_SYS_MCLK_PRG 0x0711
|
||||
|
@ -172,7 +217,19 @@
|
|||
#define WCD934X_SIDO_NEW_VOUT_D_FREQ2 0x071e
|
||||
#define WCD934X_SIDO_RIPPLE_FREQ_EN_MASK 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_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_HPH_NEW_INT_RDAC_HD2_CTL_L 0x0733
|
||||
#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);
|
|||
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_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);
|
||||
void sdw_extract_slave_id(struct sdw_bus *bus, u64 addr, struct sdw_slave_id *id);
|
||||
|
||||
|
|
|
@ -128,7 +128,9 @@ struct snd_card {
|
|||
|
||||
#ifdef CONFIG_PM
|
||||
unsigned int power_state; /* power state */
|
||||
atomic_t power_ref;
|
||||
wait_queue_head_t power_sleep;
|
||||
wait_queue_head_t power_ref_sleep;
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
|
||||
|
@ -142,21 +144,61 @@ struct snd_card {
|
|||
#ifdef CONFIG_PM
|
||||
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)
|
||||
{
|
||||
card->power_state = state;
|
||||
WRITE_ONCE(card->power_state, state);
|
||||
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 */
|
||||
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 */
|
||||
|
||||
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_change_state(card, state) do { (void)(card); } while (0)
|
||||
|
||||
|
|
|
@ -65,12 +65,22 @@ struct hdmi_codec_ops {
|
|||
|
||||
/*
|
||||
* Configures HDMI-encoder for audio stream.
|
||||
* Mandatory
|
||||
* Having either prepare or hw_params is mandatory.
|
||||
*/
|
||||
int (*hw_params)(struct device *dev, void *data,
|
||||
struct hdmi_codec_daifmt *fmt,
|
||||
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.
|
||||
* Mandatory
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <asm/page.h>
|
||||
|
||||
struct device;
|
||||
struct vm_area_struct;
|
||||
|
||||
/*
|
||||
* buffer device info
|
||||
|
@ -64,84 +65,19 @@ static inline unsigned int snd_sgbuf_aligned_pages(size_t size)
|
|||
return (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SND_DMA_SGBUF
|
||||
/*
|
||||
* Scatter-Gather generic device pages
|
||||
*/
|
||||
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 */
|
||||
int snd_dma_alloc_pages(int type, struct device *dev, size_t size,
|
||||
struct snd_dma_buffer *dmab);
|
||||
int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size,
|
||||
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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
|
||||
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);
|
||||
snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
|
||||
void *buf, bool interleaved,
|
||||
|
@ -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)
|
||||
|
||||
#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
|
||||
* @substream: PCM substream
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* contig. page from the given size
|
||||
|
|
|
@ -4,6 +4,14 @@
|
|||
|
||||
#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,
|
||||
size_t len);
|
||||
|
||||
|
|
|
@ -81,6 +81,8 @@ struct snd_rawmidi_substream {
|
|||
bool opened; /* open flag */
|
||||
bool append; /* append flag (merge more streams) */
|
||||
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) */
|
||||
size_t bytes;
|
||||
struct snd_rawmidi *rmidi;
|
||||
|
|
|
@ -36,6 +36,22 @@ struct snd_compr_stream;
|
|||
#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_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.
|
||||
*
|
||||
|
@ -45,6 +61,17 @@ struct snd_compr_stream;
|
|||
#define SND_SOC_DAIFMT_CONT (1 << 4) /* continuous clock */
|
||||
#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.
|
||||
*
|
||||
|
@ -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_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
|
||||
*
|
||||
|
@ -89,6 +124,14 @@ struct snd_compr_stream;
|
|||
#define SND_SOC_DAIFMT_CBM_CFS SND_SOC_DAIFMT_CBP_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_CLOCK_MASK 0x00f0
|
||||
#define SND_SOC_DAIFMT_INV_MASK 0x0f00
|
||||
|
@ -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);
|
||||
|
||||
/* 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_tdm_slot(struct snd_soc_dai *dai,
|
||||
|
@ -292,6 +337,16 @@ struct snd_soc_dai_ops {
|
|||
snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
|
||||
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 */
|
||||
unsigned int no_capture_mute:1;
|
||||
};
|
||||
|
|
|
@ -54,7 +54,7 @@ struct snd_soc_dobj_control {
|
|||
|
||||
/* dynamic widget object */
|
||||
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 */
|
||||
|
|
|
@ -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,
|
||||
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,
|
||||
|
||||
unsigned int snd_soc_daifmt_clock_provider_fliped(unsigned int dai_fmt);
|
||||
unsigned int snd_soc_daifmt_clock_provider_from_bitmap(unsigned int bit_frame);
|
||||
|
||||
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_name(const struct of_phandle_args *args,
|
||||
const char **dai_name);
|
||||
|
|
|
@ -710,7 +710,7 @@ enum {
|
|||
* 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 {
|
||||
SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
|
||||
|
@ -736,12 +736,38 @@ struct snd_rawmidi_info {
|
|||
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 {
|
||||
int stream;
|
||||
size_t buffer_size; /* queue size in bytes */
|
||||
size_t avail_min; /* minimum avail bytes for wakeup */
|
||||
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__
|
||||
|
|
|
@ -520,7 +520,7 @@ static int ac97_bus_remove(struct device *dev)
|
|||
struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver);
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -918,10 +918,8 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
|
|||
}
|
||||
|
||||
cii = kzalloc(sizeof(struct codec_info_item), GFP_KERNEL);
|
||||
if (!cii) {
|
||||
printk(KERN_DEBUG "i2sbus: failed to allocate cii\n");
|
||||
if (!cii)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* use the private data to point to the codec info */
|
||||
cii->sdev = soundbus_dev_get(dev);
|
||||
|
|
|
@ -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,
|
||||
unsigned short reg, unsigned short val)
|
||||
{
|
||||
int __always_unused ret;
|
||||
|
||||
ret = pxa2xx_ac97_write(ac97->num, reg, val);
|
||||
pxa2xx_ac97_write(ac97->num, reg, val);
|
||||
}
|
||||
|
||||
static const struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
|
||||
|
|
|
@ -995,7 +995,10 @@ static int __snd_ctl_elem_info(struct snd_card *card,
|
|||
#ifdef CONFIG_SND_DEBUG
|
||||
info->access = 0;
|
||||
#endif
|
||||
result = snd_power_ref_and_wait(card);
|
||||
if (!result)
|
||||
result = kctl->info(kctl, info);
|
||||
snd_power_unref(card);
|
||||
if (result >= 0) {
|
||||
snd_BUG_ON(info->access);
|
||||
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,
|
|||
|
||||
if (copy_from_user(&info, _info, sizeof(info)))
|
||||
return -EFAULT;
|
||||
result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
|
||||
if (result < 0)
|
||||
return result;
|
||||
result = snd_ctl_elem_info(ctl, &info);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
@ -1088,7 +1088,10 @@ static int snd_ctl_elem_read(struct snd_card *card,
|
|||
|
||||
if (!snd_ctl_skip_validation(&info))
|
||||
fill_remaining_elem_value(control, &info, pattern);
|
||||
ret = snd_power_ref_and_wait(card);
|
||||
if (!ret)
|
||||
ret = kctl->get(kctl, control);
|
||||
snd_power_unref(card);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!snd_ctl_skip_validation(&info) &&
|
||||
|
@ -1113,10 +1116,6 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
|
|||
if (IS_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);
|
||||
result = snd_ctl_elem_read(card, control);
|
||||
up_read(&card->controls_rwsem);
|
||||
|
@ -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);
|
||||
result = snd_power_ref_and_wait(card);
|
||||
if (!result)
|
||||
result = kctl->put(kctl, control);
|
||||
snd_power_unref(card);
|
||||
if (result < 0) {
|
||||
up_write(&card->controls_rwsem);
|
||||
return result;
|
||||
|
@ -1183,10 +1185,6 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
|
|||
return PTR_ERR(control);
|
||||
|
||||
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);
|
||||
if (result < 0)
|
||||
goto error;
|
||||
|
@ -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},
|
||||
};
|
||||
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. */
|
||||
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,
|
|||
vd->owner != NULL && vd->owner != file)
|
||||
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,
|
||||
|
@ -1815,11 +1817,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
|
|||
case SNDRV_CTL_IOCTL_POWER:
|
||||
return -ENOPROTOOPT;
|
||||
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;
|
||||
#endif
|
||||
}
|
||||
down_read(&snd_ioctl_rwsem);
|
||||
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,
|
|||
if (get_user(data->value.enumerated.item, &data32->value.enumerated.item))
|
||||
goto error;
|
||||
|
||||
err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
err = snd_ctl_elem_info(ctl, data);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
@ -187,7 +184,10 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
|
|||
return -ENOMEM;
|
||||
}
|
||||
info->id = *id;
|
||||
err = snd_power_ref_and_wait(card);
|
||||
if (!err)
|
||||
err = kctl->info(kctl, info);
|
||||
snd_power_unref(card);
|
||||
up_read(&card->controls_rwsem);
|
||||
if (err >= 0) {
|
||||
err = info->type;
|
||||
|
@ -298,9 +298,6 @@ static int ctl_elem_read_user(struct snd_card *card,
|
|||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
err = snd_ctl_elem_read(card, data);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
@ -326,9 +323,6 @@ static int ctl_elem_write_user(struct snd_ctl_file *file,
|
|||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
err = snd_ctl_elem_write(card, file, data);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
|
|
@ -393,11 +393,11 @@ static void snd_ctl_led_dev_release(struct device *dev)
|
|||
* sysfs
|
||||
*/
|
||||
|
||||
static ssize_t show_mode(struct device *dev,
|
||||
static ssize_t mode_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev);
|
||||
const char *str;
|
||||
const char *str = NULL;
|
||||
|
||||
switch (led->mode) {
|
||||
case MODE_FOLLOW_MUTE: str = "follow-mute"; break;
|
||||
|
@ -408,7 +408,8 @@ static ssize_t show_mode(struct device *dev,
|
|||
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)
|
||||
{
|
||||
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,
|
|||
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 snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev);
|
||||
|
@ -445,8 +446,8 @@ static ssize_t show_brightness(struct device *dev,
|
|||
return sprintf(buf, "%u\n", ledtrig_audio_get(led->trigger_type));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(mode, 0644, show_mode, store_mode);
|
||||
static DEVICE_ATTR(brightness, 0444, show_brightness, NULL);
|
||||
static DEVICE_ATTR_RW(mode);
|
||||
static DEVICE_ATTR_RO(brightness);
|
||||
|
||||
static struct attribute *snd_ctl_led_dev_attrs[] = {
|
||||
&dev_attr_mode.attr,
|
||||
|
@ -580,21 +581,24 @@ static ssize_t set_led_id(struct snd_ctl_led_card *led_card, const char *buf, si
|
|||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static ssize_t ctl_reset(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t reset_store(struct device *dev,
|
||||
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);
|
||||
|
@ -608,7 +612,7 @@ static ssize_t ctl_reset(struct device *dev, struct device_attribute *attr,
|
|||
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 snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
|
||||
|
@ -642,10 +646,10 @@ static ssize_t ctl_list(struct device *dev,
|
|||
return buf2 - buf;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(attach, 0200, NULL, parse_attach);
|
||||
static DEVICE_ATTR(detach, 0200, NULL, parse_detach);
|
||||
static DEVICE_ATTR(reset, 0200, NULL, ctl_reset);
|
||||
static DEVICE_ATTR(list, 0444, ctl_list, NULL);
|
||||
static DEVICE_ATTR_WO(attach);
|
||||
static DEVICE_ATTR_WO(detach);
|
||||
static DEVICE_ATTR_WO(reset);
|
||||
static DEVICE_ATTR_RO(list);
|
||||
|
||||
static struct attribute *snd_ctl_led_card_attrs[] = {
|
||||
&dev_attr_attach.attr,
|
||||
|
|
|
@ -195,7 +195,8 @@ static int snd_hwdep_dsp_status(struct snd_hwdep *hw,
|
|||
return -ENXIO;
|
||||
memset(&info, 0, sizeof(info));
|
||||
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;
|
||||
if (copy_to_user(_info, &info, sizeof(info)))
|
||||
return -EFAULT;
|
||||
|
@ -500,7 +501,8 @@ static void __init snd_hwdep_proc_init(void)
|
|||
{
|
||||
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;
|
||||
if (snd_info_register(entry) < 0) {
|
||||
snd_info_free_entry(entry);
|
||||
|
|
|
@ -31,7 +31,8 @@ int snd_oss_info_register(int dev, int num, char *string)
|
|||
return -ENXIO;
|
||||
mutex_lock(&strings);
|
||||
if (string == NULL) {
|
||||
if ((x = snd_sndstat_strings[num][dev]) != NULL) {
|
||||
x = snd_sndstat_strings[num][dev];
|
||||
if (x) {
|
||||
kfree(x);
|
||||
x = NULL;
|
||||
}
|
||||
|
|
|
@ -220,6 +220,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
|
|||
mutex_init(&card->memory_mutex);
|
||||
#ifdef CONFIG_PM
|
||||
init_waitqueue_head(&card->power_sleep);
|
||||
init_waitqueue_head(&card->power_ref_sleep);
|
||||
atomic_set(&card->power_ref, 0);
|
||||
#endif
|
||||
init_waitqueue_head(&card->remove_sleep);
|
||||
card->sync_irq = -1;
|
||||
|
@ -442,6 +444,7 @@ int snd_card_disconnect(struct snd_card *card)
|
|||
|
||||
#ifdef CONFIG_PM
|
||||
wake_up(&card->power_sleep);
|
||||
snd_power_sync_ref(card);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -662,16 +665,14 @@ void snd_card_set_id(struct snd_card *card, const char *nid)
|
|||
}
|
||||
EXPORT_SYMBOL(snd_card_set_id);
|
||||
|
||||
static ssize_t
|
||||
card_id_show_attr(struct device *dev,
|
||||
static ssize_t id_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct snd_card *card = container_of(dev, struct snd_card, card_dev);
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", card->id);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
card_id_store_attr(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t id_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct snd_card *card = container_of(dev, struct snd_card, card_dev);
|
||||
|
@ -700,17 +701,16 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
|
|||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(id, 0644, card_id_show_attr, card_id_store_attr);
|
||||
static DEVICE_ATTR_RW(id);
|
||||
|
||||
static ssize_t
|
||||
card_number_show_attr(struct device *dev,
|
||||
static ssize_t number_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct snd_card *card = container_of(dev, struct snd_card, card_dev);
|
||||
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[] = {
|
||||
&dev_attr_id.attr,
|
||||
|
@ -770,7 +770,8 @@ int snd_card_register(struct snd_card *card)
|
|||
card->registered = true;
|
||||
}
|
||||
|
||||
if ((err = snd_device_register_all(card)) < 0)
|
||||
err = snd_device_register_all(card);
|
||||
if (err < 0)
|
||||
return err;
|
||||
mutex_lock(&snd_card_mutex);
|
||||
if (snd_cards[card->number]) {
|
||||
|
@ -813,7 +814,8 @@ static void snd_card_info_read(struct snd_info_entry *entry,
|
|||
|
||||
for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
|
||||
mutex_lock(&snd_card_mutex);
|
||||
if ((card = snd_cards[idx]) != NULL) {
|
||||
card = snd_cards[idx];
|
||||
if (card) {
|
||||
count++;
|
||||
snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n",
|
||||
idx,
|
||||
|
@ -837,7 +839,8 @@ void snd_card_info_read_oss(struct snd_info_buffer *buffer)
|
|||
|
||||
for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
|
||||
mutex_lock(&snd_card_mutex);
|
||||
if ((card = snd_cards[idx]) != NULL) {
|
||||
card = snd_cards[idx];
|
||||
if (card) {
|
||||
count++;
|
||||
snd_iprintf(buffer, "%s\n", card->longname);
|
||||
}
|
||||
|
@ -859,7 +862,8 @@ static void snd_card_module_info_read(struct snd_info_entry *entry,
|
|||
|
||||
for (idx = 0; idx < SNDRV_CARDS; idx++) {
|
||||
mutex_lock(&snd_card_mutex);
|
||||
if ((card = snd_cards[idx]) != NULL)
|
||||
card = snd_cards[idx];
|
||||
if (card)
|
||||
snd_iprintf(buffer, "%2i %s\n",
|
||||
idx, card->module->name);
|
||||
mutex_unlock(&snd_card_mutex);
|
||||
|
@ -1002,21 +1006,28 @@ EXPORT_SYMBOL(snd_card_file_remove);
|
|||
|
||||
#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
|
||||
* @power_state: expected power state
|
||||
*
|
||||
* Waits until the power-state is changed.
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
int result = 0;
|
||||
|
||||
snd_power_ref(card);
|
||||
/* fastpath */
|
||||
if (snd_power_get_state(card) == power_state)
|
||||
if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0)
|
||||
return 0;
|
||||
init_waitqueue_entry(&wait, current);
|
||||
add_wait_queue(&card->power_sleep, &wait);
|
||||
|
@ -1025,13 +1036,33 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state)
|
|||
result = -ENODEV;
|
||||
break;
|
||||
}
|
||||
if (snd_power_get_state(card) == power_state)
|
||||
if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0)
|
||||
break;
|
||||
snd_power_unref(card);
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(30 * HZ);
|
||||
snd_power_ref(card);
|
||||
}
|
||||
remove_wait_queue(&card->power_sleep, &wait);
|
||||
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);
|
||||
#endif /* CONFIG_PM */
|
||||
|
|
|
@ -15,99 +15,27 @@
|
|||
#include <asm/set_memory.h>
|
||||
#endif
|
||||
#include <sound/memalloc.h>
|
||||
#include "memalloc_local.h"
|
||||
|
||||
/*
|
||||
*
|
||||
* Bus-specific memory allocators
|
||||
*
|
||||
*/
|
||||
static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab);
|
||||
|
||||
#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
|
||||
| __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
|
||||
}
|
||||
|
||||
/* 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;
|
||||
struct gen_pool *pool = NULL;
|
||||
|
||||
dmab->area = NULL;
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
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,
|
||||
/* a cast to gfp flag from the dev pointer; for CONTINUOUS and VMALLOC types */
|
||||
static inline gfp_t snd_mem_get_gfp_flags(const struct snd_dma_buffer *dmab,
|
||||
gfp_t default_gfp)
|
||||
{
|
||||
if (!dev)
|
||||
if (!dmab->dev.dev)
|
||||
return default_gfp;
|
||||
else
|
||||
return (__force gfp_t)(unsigned long)dev;
|
||||
return (__force gfp_t)(unsigned long)dmab->dev.dev;
|
||||
}
|
||||
|
||||
static int __snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size)
|
||||
{
|
||||
const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab);
|
||||
|
||||
if (WARN_ON_ONCE(!ops || !ops->alloc))
|
||||
return -EINVAL;
|
||||
return ops->alloc(dmab, size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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,
|
||||
struct snd_dma_buffer *dmab)
|
||||
{
|
||||
gfp_t gfp;
|
||||
int err;
|
||||
|
||||
if (WARN_ON(!size))
|
||||
return -ENXIO;
|
||||
|
@ -140,43 +68,10 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
|
|||
dmab->area = NULL;
|
||||
dmab->addr = 0;
|
||||
dmab->private_data = NULL;
|
||||
switch (type) {
|
||||
case SNDRV_DMA_TYPE_CONTINUOUS:
|
||||
gfp = snd_mem_get_gfp_flags(device, GFP_KERNEL);
|
||||
dmab->area = alloc_pages_exact(size, gfp);
|
||||
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)
|
||||
err = __snd_dma_alloc_pages(dmab, size);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (!dmab->area)
|
||||
return -ENOMEM;
|
||||
dmab->bytes = size;
|
||||
return 0;
|
||||
|
@ -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);
|
||||
|
||||
|
||||
/**
|
||||
* snd_dma_free_pages - release the allocated buffer
|
||||
* @dmab: the buffer allocation record to release
|
||||
|
@ -226,32 +120,288 @@ EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
|
|||
*/
|
||||
void snd_dma_free_pages(struct snd_dma_buffer *dmab)
|
||||
{
|
||||
switch (dmab->dev.type) {
|
||||
case SNDRV_DMA_TYPE_CONTINUOUS:
|
||||
free_pages_exact(dmab->area, dmab->bytes);
|
||||
break;
|
||||
case SNDRV_DMA_TYPE_VMALLOC:
|
||||
vfree(dmab->area);
|
||||
break;
|
||||
#ifdef CONFIG_HAS_DMA
|
||||
#ifdef CONFIG_GENERIC_ALLOCATOR
|
||||
case SNDRV_DMA_TYPE_DEV_IRAM:
|
||||
snd_free_dev_iram(dmab);
|
||||
break;
|
||||
#endif /* CONFIG_GENERIC_ALLOCATOR */
|
||||
case SNDRV_DMA_TYPE_DEV:
|
||||
case SNDRV_DMA_TYPE_DEV_UC:
|
||||
snd_free_dev_pages(dmab);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SND_DMA_SGBUF
|
||||
case SNDRV_DMA_TYPE_DEV_SG:
|
||||
case SNDRV_DMA_TYPE_DEV_UC_SG:
|
||||
snd_free_sgbuf_pages(dmab);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type);
|
||||
}
|
||||
const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab);
|
||||
|
||||
if (ops && ops->free)
|
||||
ops->free(dmab);
|
||||
}
|
||||
EXPORT_SYMBOL(snd_dma_free_pages);
|
||||
|
||||
/**
|
||||
* 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
|
||||
/*
|
||||
* IRAM allocator
|
||||
*/
|
||||
#ifdef CONFIG_GENERIC_ALLOCATOR
|
||||
static int snd_dma_iram_alloc(struct snd_dma_buffer *dmab, size_t size)
|
||||
{
|
||||
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 */
|
||||
|
||||
/*
|
||||
* Coherent device pages allocator
|
||||
*/
|
||||
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
|
||||
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
|
||||
[SNDRV_DMA_TYPE_DEV_SG] = &snd_dma_sg_ops,
|
||||
[SNDRV_DMA_TYPE_DEV_UC_SG] = &snd_dma_sg_ops,
|
||||
#endif
|
||||
};
|
||||
|
||||
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];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// 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)
|
|||
if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */
|
||||
int err;
|
||||
unsigned int index;
|
||||
if ((err = mixer->get_recsrc(fmixer, &index)) < 0)
|
||||
err = mixer->get_recsrc(fmixer, &index);
|
||||
if (err < 0)
|
||||
return err;
|
||||
result = 1 << index;
|
||||
} else {
|
||||
|
@ -517,7 +518,8 @@ static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
|
|||
if (numid == ID_UNKNOWN)
|
||||
return;
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -555,7 +557,8 @@ static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer,
|
|||
if (numid == ID_UNKNOWN)
|
||||
return;
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -620,7 +623,8 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
|
|||
if (numid == ID_UNKNOWN)
|
||||
return;
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -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);
|
||||
if (uinfo->count > 1)
|
||||
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;
|
||||
if (res > 0)
|
||||
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,
|
|||
if (numid == ID_UNKNOWN)
|
||||
return;
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -681,7 +687,8 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
|
|||
} else {
|
||||
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;
|
||||
if (res > 0)
|
||||
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
|
|||
err = -ENOENT;
|
||||
goto __unlock;
|
||||
}
|
||||
if ((err = kctl->info(kctl, uinfo)) < 0)
|
||||
err = kctl->info(kctl, uinfo);
|
||||
if (err < 0)
|
||||
goto __unlock;
|
||||
if ((err = kctl->get(kctl, uctl)) < 0)
|
||||
err = kctl->get(kctl, uctl);
|
||||
if (err < 0)
|
||||
goto __unlock;
|
||||
for (idx = 0; idx < 32; 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
|
|||
err = -ENOENT;
|
||||
goto __unlock;
|
||||
}
|
||||
if ((err = kctl->info(kctl, uinfo)) < 0)
|
||||
err = kctl->info(kctl, uinfo);
|
||||
if (err < 0)
|
||||
goto __unlock;
|
||||
for (idx = 0; idx < 32; 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
|
|||
up_read(&card->controls_rwsem);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if ((err = kcontrol->info(kcontrol, info)) < 0) {
|
||||
err = kcontrol->info(kcontrol, info);
|
||||
if (err < 0) {
|
||||
up_read(&card->controls_rwsem);
|
||||
kfree(info);
|
||||
return err;
|
||||
|
@ -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))
|
||||
return 0;
|
||||
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;
|
||||
|
||||
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
|
||||
|
@ -1343,9 +1357,10 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd)
|
|||
if (mixer == NULL)
|
||||
return -ENOMEM;
|
||||
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,
|
||||
&snd_mixer_oss_f_ops, card)) < 0) {
|
||||
&snd_mixer_oss_f_ops, card);
|
||||
if (err < 0) {
|
||||
dev_err(card->dev,
|
||||
"unable to register OSS mixer device %i:%i\n",
|
||||
card->number, 0);
|
||||
|
|
|
@ -955,9 +955,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
|
|||
if (!direct) {
|
||||
/* add necessary plugins */
|
||||
snd_pcm_oss_plugin_clear(substream);
|
||||
if ((err = snd_pcm_plug_format_plugins(substream,
|
||||
params,
|
||||
sparams)) < 0) {
|
||||
err = snd_pcm_plug_format_plugins(substream, params, sparams);
|
||||
if (err < 0) {
|
||||
pcm_dbg(substream->pcm,
|
||||
"snd_pcm_plug_format_plugins failed: %i\n", err);
|
||||
snd_pcm_oss_plugin_clear(substream);
|
||||
|
@ -965,7 +964,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
|
|||
}
|
||||
if (runtime->oss.plugin_first) {
|
||||
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,
|
||||
"snd_pcm_plugin_build_io failed: %i\n", err);
|
||||
snd_pcm_oss_plugin_clear(substream);
|
||||
|
@ -1011,7 +1011,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
|
|||
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);
|
||||
goto failure;
|
||||
}
|
||||
|
@ -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];
|
||||
if (substream != NULL) {
|
||||
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
|
||||
err = snd_pcm_oss_make_ready(substream);
|
||||
if (err < 0)
|
||||
return err;
|
||||
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)
|
|||
runtime = substream->runtime;
|
||||
if (atomic_read(&substream->mmap_count))
|
||||
goto __direct;
|
||||
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
|
||||
err = snd_pcm_oss_make_ready(substream);
|
||||
if (err < 0)
|
||||
return err;
|
||||
atomic_inc(&runtime->oss.rw_ref);
|
||||
if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
|
||||
|
@ -1711,7 +1714,8 @@ unlock:
|
|||
|
||||
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
|
||||
if (substream != NULL) {
|
||||
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
|
||||
err = snd_pcm_oss_make_ready(substream);
|
||||
if (err < 0)
|
||||
return err;
|
||||
runtime = substream->runtime;
|
||||
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)
|
|||
struct snd_pcm_substream *substream;
|
||||
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 substream->runtime->oss.rate;
|
||||
}
|
||||
|
@ -1795,7 +1800,8 @@ static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file)
|
|||
struct snd_pcm_substream *substream;
|
||||
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 substream->runtime->oss.channels;
|
||||
}
|
||||
|
@ -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;
|
||||
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 substream->runtime->oss.period_bytes;
|
||||
}
|
||||
|
@ -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;
|
||||
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;
|
||||
if (atomic_read(&substream->mmap_count))
|
||||
direct = 1;
|
||||
|
@ -1890,7 +1898,8 @@ static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file)
|
|||
struct snd_pcm_substream *substream;
|
||||
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 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
|
|||
csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
|
||||
|
||||
if (psubstream) {
|
||||
if ((err = snd_pcm_oss_make_ready(psubstream)) < 0)
|
||||
err = snd_pcm_oss_make_ready(psubstream);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (csubstream) {
|
||||
if ((err = snd_pcm_oss_make_ready(csubstream)) < 0)
|
||||
err = snd_pcm_oss_make_ready(csubstream);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (psubstream) {
|
||||
|
@ -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];
|
||||
if (substream == NULL)
|
||||
return -EINVAL;
|
||||
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
|
||||
err = snd_pcm_oss_make_ready(substream);
|
||||
if (err < 0)
|
||||
return err;
|
||||
runtime = substream->runtime;
|
||||
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
|
|||
substream = pcm_oss_file->streams[stream];
|
||||
if (substream == NULL)
|
||||
return -EINVAL;
|
||||
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
|
||||
err = snd_pcm_oss_make_ready(substream);
|
||||
if (err < 0)
|
||||
return err;
|
||||
runtime = substream->runtime;
|
||||
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
|
|||
return -EINVAL;
|
||||
runtime = substream->runtime;
|
||||
|
||||
if (runtime->oss.params &&
|
||||
(err = snd_pcm_oss_change_params(substream, false)) < 0)
|
||||
if (runtime->oss.params) {
|
||||
err = snd_pcm_oss_change_params(substream, false);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
info.fragsize = runtime->oss.period_bytes;
|
||||
info.fragstotal = runtime->periods;
|
||||
|
@ -2601,7 +2616,8 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long
|
|||
case SNDCTL_DSP_SPEED:
|
||||
if (get_user(res, p))
|
||||
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 put_user(res, p);
|
||||
case SOUND_PCM_READ_RATE:
|
||||
|
@ -2613,7 +2629,8 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long
|
|||
if (get_user(res, p))
|
||||
return -EFAULT;
|
||||
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 put_user(--res, p);
|
||||
case SNDCTL_DSP_GETBLKSIZE:
|
||||
|
@ -2829,7 +2846,8 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
|
|||
snd_pcm_state_t ostate;
|
||||
poll_wait(file, &runtime->sleep, wait);
|
||||
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))
|
||||
mask |= EPOLLIN | EPOLLRDNORM;
|
||||
snd_pcm_stream_unlock_irq(csubstream);
|
||||
|
@ -3043,7 +3061,8 @@ static void snd_pcm_oss_proc_init(struct snd_pcm *pcm)
|
|||
struct snd_pcm_str *pstr = &pcm->streams[stream];
|
||||
if (pstr->substream_count == 0)
|
||||
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->mode = S_IFREG | 0644;
|
||||
entry->c.text.read = snd_pcm_oss_proc_read;
|
||||
|
@ -3191,7 +3210,8 @@ static int __init alsa_pcm_oss_init(void)
|
|||
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 0;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,8 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t
|
|||
} else {
|
||||
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;
|
||||
size = frames * format->channels * width;
|
||||
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
|
|||
}
|
||||
v = plugin->buf_channels;
|
||||
*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;
|
||||
nchannels = format->channels;
|
||||
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
|
|||
while (plugin) {
|
||||
if (frames <= 0)
|
||||
return frames;
|
||||
if ((next = plugin->next) != NULL) {
|
||||
next = plugin->next;
|
||||
if (next) {
|
||||
snd_pcm_sframes_t frames1 = frames;
|
||||
if (plugin->dst_frames) {
|
||||
frames1 = plugin->dst_frames(plugin, frames);
|
||||
if (frames1 <= 0)
|
||||
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;
|
||||
}
|
||||
if (err != frames1) {
|
||||
frames = err;
|
||||
if (plugin->src_frames) {
|
||||
|
@ -621,7 +624,8 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, st
|
|||
} else
|
||||
dst_channels = NULL;
|
||||
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;
|
||||
src_channels = dst_channels;
|
||||
plugin = next;
|
||||
|
@ -643,16 +647,18 @@ snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, str
|
|||
src_channels = NULL;
|
||||
plugin = snd_pcm_plug_first(plug);
|
||||
while (plugin && frames > 0) {
|
||||
if ((next = plugin->next) != NULL) {
|
||||
if ((err = plugin->client_channels(plugin, frames, &dst_channels)) < 0) {
|
||||
next = plugin->next;
|
||||
if (next) {
|
||||
err = plugin->client_channels(plugin, frames, &dst_channels);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
frames = err;
|
||||
} else {
|
||||
dst_channels = dst_channels_final;
|
||||
}
|
||||
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;
|
||||
plugin = next;
|
||||
src_channels = dst_channels;
|
||||
|
|
|
@ -1004,7 +1004,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
|
|||
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 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,
|
|||
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[] = {
|
||||
&dev_attr_pcm_class.attr,
|
||||
NULL
|
||||
|
|
|
@ -239,7 +239,8 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
|
|||
struct snd_pcm_runtime *runtime;
|
||||
int err;
|
||||
|
||||
if (! (runtime = substream->runtime))
|
||||
runtime = substream->runtime;
|
||||
if (!runtime)
|
||||
return -ENOTTY;
|
||||
|
||||
data = kmalloc(sizeof(*data), GFP_KERNEL);
|
||||
|
@ -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)
|
||||
return -EBADFD;
|
||||
|
||||
if ((ch = substream->runtime->channels) > 128)
|
||||
ch = substream->runtime->channels;
|
||||
if (ch > 128)
|
||||
return -EINVAL;
|
||||
if (get_user(buf, &data32->bufs) ||
|
||||
get_user(frames, &data32->frames))
|
||||
|
|
|
@ -9,14 +9,51 @@
|
|||
#include <sound/pcm_params.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)
|
||||
return -EINVAL;
|
||||
|
||||
memset(cs, 0, len);
|
||||
|
||||
cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
|
||||
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 | IEC958_AES3_CON_FS_NOTID;
|
||||
|
||||
if (len > 4)
|
||||
cs[4] = IEC958_AES4_CON_WORDLEN_NOTID;
|
||||
|
||||
return len;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_pcm_create_iec958_consumer_default);
|
||||
|
||||
static int fill_iec958_consumer(uint rate, uint sample_width,
|
||||
u8 *cs, size_t len)
|
||||
{
|
||||
if (len < 4)
|
||||
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;
|
||||
|
@ -43,7 +80,14 @@ static int create_iec958_consumer(uint rate, uint sample_width,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (len > 4) {
|
||||
cs[3] &= ~IEC958_AES3_CON_FS;
|
||||
cs[3] |= fs;
|
||||
}
|
||||
|
||||
if (len > 4 &&
|
||||
(cs[4] & IEC958_AES4_CON_WORDLEN) == IEC958_AES4_CON_WORDLEN_NOTID) {
|
||||
unsigned int ws;
|
||||
|
||||
switch (sample_width) {
|
||||
case 16:
|
||||
ws = IEC958_AES4_CON_WORDLEN_20_16;
|
||||
|
@ -64,21 +108,58 @@ static int create_iec958_consumer(uint rate, uint sample_width,
|
|||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cs[4] &= ~IEC958_AES4_CON_WORDLEN;
|
||||
cs[4] |= ws;
|
||||
}
|
||||
|
||||
memset(cs, 0, len);
|
||||
|
||||
cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
|
||||
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;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @runtime: pcm runtime structure with ->rate filled in
|
||||
|
@ -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,
|
||||
size_t len)
|
||||
{
|
||||
return create_iec958_consumer(runtime->rate,
|
||||
snd_pcm_format_width(runtime->format),
|
||||
cs, len);
|
||||
int ret;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -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,
|
||||
u8 *cs, size_t len)
|
||||
{
|
||||
return create_iec958_consumer(params_rate(params), params_width(params),
|
||||
cs, len);
|
||||
int ret;
|
||||
|
||||
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);
|
||||
|
|
|
@ -1778,27 +1778,38 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
|
|||
EXPORT_SYMBOL(snd_pcm_lib_ioctl);
|
||||
|
||||
/**
|
||||
* snd_pcm_period_elapsed - update the pcm status for the next period
|
||||
* @substream: the pcm substream instance
|
||||
* snd_pcm_period_elapsed_under_stream_lock() - update the status of runtime for the next period
|
||||
* under acquired lock of PCM substream.
|
||||
* @substream: the instance of pcm substream.
|
||||
*
|
||||
* This function is called from the interrupt handler when the
|
||||
* PCM has processed the period size. It will update the current
|
||||
* pointer, wake up sleepers, etc.
|
||||
* 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.
|
||||
*
|
||||
* Even if more than one periods have elapsed since the last call, you
|
||||
* have to call this only once.
|
||||
* 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.
|
||||
*
|
||||
* Developer should pay enough attention that some callbacks in &snd_pcm_ops are done by the call of
|
||||
* function:
|
||||
*
|
||||
* - .pointer - to retrieve current position of audio data transmission by frame count or XRUN state.
|
||||
* - .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;
|
||||
unsigned long flags;
|
||||
|
||||
if (snd_BUG_ON(!substream))
|
||||
return;
|
||||
|
||||
snd_pcm_stream_lock_irqsave(substream, flags);
|
||||
if (PCM_RUNTIME_CHECK(substream))
|
||||
goto _unlock;
|
||||
return;
|
||||
runtime = substream->runtime;
|
||||
|
||||
if (!snd_pcm_running(substream) ||
|
||||
|
@ -1811,7 +1822,30 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
|
|||
#endif
|
||||
_end:
|
||||
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);
|
||||
}
|
||||
EXPORT_SYMBOL(snd_pcm_period_elapsed);
|
||||
|
|
|
@ -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_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)
|
||||
|
||||
/* loop over all PCM substreams */
|
||||
|
|
|
@ -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);
|
||||
|
||||
#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
|
||||
* @substream: the substream to allocate the DMA buffer to
|
||||
|
|
|
@ -266,7 +266,8 @@ int snd_pcm_format_signed(snd_pcm_format_t format)
|
|||
int val;
|
||||
if (!valid_format(format))
|
||||
return -EINVAL;
|
||||
if ((val = pcm_formats[(INT)format].signd) < 0)
|
||||
val = pcm_formats[(INT)format].signd;
|
||||
if (val < 0)
|
||||
return -EINVAL;
|
||||
return val;
|
||||
}
|
||||
|
@ -314,7 +315,8 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format)
|
|||
int val;
|
||||
if (!valid_format(format))
|
||||
return -EINVAL;
|
||||
if ((val = pcm_formats[(INT)format].le) < 0)
|
||||
val = pcm_formats[(INT)format].le;
|
||||
if (val < 0)
|
||||
return -EINVAL;
|
||||
return val;
|
||||
}
|
||||
|
@ -350,7 +352,8 @@ int snd_pcm_format_width(snd_pcm_format_t format)
|
|||
int val;
|
||||
if (!valid_format(format))
|
||||
return -EINVAL;
|
||||
if ((val = pcm_formats[(INT)format].width) == 0)
|
||||
val = pcm_formats[(INT)format].width;
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
return val;
|
||||
}
|
||||
|
@ -368,7 +371,8 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format)
|
|||
int val;
|
||||
if (!valid_format(format))
|
||||
return -EINVAL;
|
||||
if ((val = pcm_formats[(INT)format].phys) == 0)
|
||||
val = pcm_formats[(INT)format].phys;
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
return val;
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
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,
|
||||
usecs);
|
||||
return 0;
|
||||
|
@ -2658,7 +2659,8 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
|
|||
goto error;
|
||||
}
|
||||
|
||||
if ((err = substream->ops->open(substream)) < 0)
|
||||
err = substream->ops->open(substream);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
substream->hw_opened = 1;
|
||||
|
@ -2799,6 +2801,10 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
|
|||
if (snd_BUG_ON(!substream))
|
||||
return -ENXIO;
|
||||
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);
|
||||
snd_pcm_release_substream(substream);
|
||||
kfree(pcm_file);
|
||||
|
@ -3193,7 +3199,7 @@ static int snd_pcm_common_ioctl(struct file *file,
|
|||
if (PCM_RUNTIME_CHECK(substream))
|
||||
return -ENXIO;
|
||||
|
||||
res = snd_power_wait(substream->pcm->card, SNDRV_CTL_POWER_D0);
|
||||
res = snd_power_wait(substream->pcm->card);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
|
@ -3638,24 +3644,6 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
|
|||
}
|
||||
#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
|
||||
*/
|
||||
|
@ -3677,7 +3665,7 @@ static vm_fault_t snd_pcm_mmap_data_fault(struct vm_fault *vmf)
|
|||
if (substream->ops->page)
|
||||
page = substream->ops->page(substream, offset);
|
||||
else
|
||||
page = snd_pcm_default_page_ops(substream, offset);
|
||||
page = snd_sgbuf_get_page(snd_pcm_get_dma_buf(substream), offset);
|
||||
if (!page)
|
||||
return VM_FAULT_SIGBUS;
|
||||
get_page(page);
|
||||
|
@ -3712,22 +3700,9 @@ int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream,
|
|||
struct vm_area_struct *area)
|
||||
{
|
||||
area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
|
||||
#ifdef CONFIG_GENERIC_ALLOCATOR
|
||||
if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_IRAM) {
|
||||
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
|
||||
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);
|
||||
if (!substream->ops->page &&
|
||||
!snd_dma_buffer_mmap(snd_pcm_get_dma_buf(substream), area))
|
||||
return 0;
|
||||
/* mmap with fault handler */
|
||||
area->vm_ops = &snd_pcm_vm_ops_data_fault;
|
||||
return 0;
|
||||
|
|
|
@ -680,9 +680,12 @@ static int resize_runtime_buffer(struct snd_rawmidi_runtime *runtime,
|
|||
bool is_input)
|
||||
{
|
||||
char *newbuf, *oldbuf;
|
||||
unsigned int framing = params->mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK;
|
||||
|
||||
if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L)
|
||||
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)
|
||||
return -EINVAL;
|
||||
if (params->buffer_size != runtime->buffer_size) {
|
||||
|
@ -720,8 +723,24 @@ EXPORT_SYMBOL(snd_rawmidi_output_params);
|
|||
int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
|
||||
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);
|
||||
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);
|
||||
|
||||
|
@ -963,6 +982,62 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
|
|||
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
|
||||
* @substream: the rawmidi substream
|
||||
|
@ -977,6 +1052,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
|
|||
const unsigned char *buffer, int count)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct timespec64 ts64 = get_framing_tstamp(substream);
|
||||
int result = 0, count1;
|
||||
struct snd_rawmidi_runtime *runtime = substream->runtime;
|
||||
|
||||
|
@ -987,8 +1063,11 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
|
|||
"snd_rawmidi_receive: input is not active!!!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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++;
|
||||
if (runtime->avail < runtime->buffer_size) {
|
||||
runtime->buffer[runtime->hw_ptr++] = buffer[0];
|
||||
|
@ -1541,6 +1620,8 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
|
|||
struct snd_rawmidi_substream *substream;
|
||||
struct snd_rawmidi_runtime *runtime;
|
||||
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;
|
||||
snd_iprintf(buffer, "%s\n\n", rmidi->name);
|
||||
|
@ -1596,6 +1677,14 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
|
|||
" Avail : %lu\n"
|
||||
" Overruns : %lu\n",
|
||||
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 {
|
|||
u32 buffer_size;
|
||||
u32 avail_min;
|
||||
unsigned int no_active_sensing; /* avoid bit-field */
|
||||
unsigned char reserved[16];
|
||||
unsigned int mode;
|
||||
unsigned char reserved[12];
|
||||
} __attribute__((packed));
|
||||
|
||||
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) ||
|
||||
get_user(params.buffer_size, &src->buffer_size) ||
|
||||
get_user(params.avail_min, &src->avail_min) ||
|
||||
get_user(params.mode, &src->mode) ||
|
||||
get_user(val, &src->no_active_sensing))
|
||||
return -EFAULT;
|
||||
params.no_active_sensing = val;
|
||||
|
|
|
@ -67,13 +67,16 @@ static int __init alsa_seq_oss_init(void)
|
|||
{
|
||||
int rc;
|
||||
|
||||
if ((rc = register_device()) < 0)
|
||||
rc = register_device();
|
||||
if (rc < 0)
|
||||
goto error;
|
||||
if ((rc = register_proc()) < 0) {
|
||||
rc = register_proc();
|
||||
if (rc < 0) {
|
||||
unregister_device();
|
||||
goto error;
|
||||
}
|
||||
if ((rc = snd_seq_oss_create_client()) < 0) {
|
||||
rc = snd_seq_oss_create_client();
|
||||
if (rc < 0) {
|
||||
unregister_proc();
|
||||
unregister_device();
|
||||
goto error;
|
||||
|
@ -133,7 +136,8 @@ odev_release(struct inode *inode, struct file *file)
|
|||
{
|
||||
struct seq_oss_devinfo *dp;
|
||||
|
||||
if ((dp = file->private_data) == NULL)
|
||||
dp = file->private_data;
|
||||
if (!dp)
|
||||
return 0;
|
||||
|
||||
mutex_lock(®ister_mutex);
|
||||
|
@ -226,16 +230,18 @@ register_device(void)
|
|||
int rc;
|
||||
|
||||
mutex_lock(®ister_mutex);
|
||||
if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
|
||||
rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
|
||||
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");
|
||||
mutex_unlock(®ister_mutex);
|
||||
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,
|
||||
&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");
|
||||
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
|
||||
mutex_unlock(®ister_mutex);
|
||||
|
|
|
@ -94,10 +94,10 @@ snd_seq_oss_create_client(void)
|
|||
port_callback.event_input = receive_announce;
|
||||
port->kernel = &port_callback;
|
||||
|
||||
call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port);
|
||||
if ((system_port = port->addr.port) >= 0) {
|
||||
if (call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port) >= 0) {
|
||||
struct snd_seq_port_subscribe subs;
|
||||
|
||||
system_port = port->addr.port;
|
||||
memset(&subs, 0, sizeof(subs));
|
||||
subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM;
|
||||
subs.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
|
||||
|
@ -354,7 +354,8 @@ alloc_seq_queue(struct seq_oss_devinfo *dp)
|
|||
qinfo.owner = system_client;
|
||||
qinfo.locked = 1;
|
||||
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;
|
||||
dp->queue = qinfo.queue;
|
||||
return 0;
|
||||
|
@ -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);
|
||||
for (i = 0; i < num_clients; i++) {
|
||||
snd_iprintf(buf, "\nApplication %d: ", i);
|
||||
if ((dp = client_table[i]) == NULL) {
|
||||
dp = client_table[i];
|
||||
if (!dp) {
|
||||
snd_iprintf(buf, "*empty*\n");
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -152,7 +152,8 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
|
|||
/*
|
||||
* 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 */
|
||||
snd_use_lock_free(&mdev->use_lock);
|
||||
return 0;
|
||||
|
@ -218,7 +219,8 @@ snd_seq_oss_midi_check_exit_port(int client, int port)
|
|||
unsigned long flags;
|
||||
int index;
|
||||
|
||||
if ((mdev = find_slot(client, port)) != NULL) {
|
||||
mdev = find_slot(client, port);
|
||||
if (mdev) {
|
||||
spin_lock_irqsave(®ister_lock, flags);
|
||||
midi_devs[mdev->seq_device] = NULL;
|
||||
spin_unlock_irqrestore(®ister_lock, flags);
|
||||
|
@ -250,7 +252,8 @@ snd_seq_oss_midi_clear_all(void)
|
|||
|
||||
spin_lock_irqsave(®ister_lock, flags);
|
||||
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);
|
||||
kfree(mdev);
|
||||
midi_devs[i] = NULL;
|
||||
|
@ -318,7 +321,8 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
|
|||
struct seq_oss_midi *mdev;
|
||||
struct snd_seq_port_subscribe subs;
|
||||
|
||||
if ((mdev = get_mididev(dp, dev)) == NULL)
|
||||
mdev = get_mididev(dp, dev);
|
||||
if (!mdev)
|
||||
return -ENODEV;
|
||||
|
||||
/* already used? */
|
||||
|
@ -384,7 +388,8 @@ snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
|
|||
struct seq_oss_midi *mdev;
|
||||
struct snd_seq_port_subscribe subs;
|
||||
|
||||
if ((mdev = get_mididev(dp, dev)) == NULL)
|
||||
mdev = get_mididev(dp, dev);
|
||||
if (!mdev)
|
||||
return -ENODEV;
|
||||
if (! mdev->opened || mdev->devinfo != dp) {
|
||||
snd_use_lock_free(&mdev->use_lock);
|
||||
|
@ -421,7 +426,8 @@ snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
|
|||
struct seq_oss_midi *mdev;
|
||||
int mode;
|
||||
|
||||
if ((mdev = get_mididev(dp, dev)) == NULL)
|
||||
mdev = get_mididev(dp, dev);
|
||||
if (!mdev)
|
||||
return 0;
|
||||
|
||||
mode = 0;
|
||||
|
@ -443,7 +449,8 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
|
|||
{
|
||||
struct seq_oss_midi *mdev;
|
||||
|
||||
if ((mdev = get_mididev(dp, dev)) == NULL)
|
||||
mdev = get_mididev(dp, dev);
|
||||
if (!mdev)
|
||||
return;
|
||||
if (! mdev->opened) {
|
||||
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
|
|||
{
|
||||
struct seq_oss_midi *mdev;
|
||||
|
||||
if ((mdev = get_mididev(dp, dev)) == NULL)
|
||||
mdev = get_mididev(dp, dev);
|
||||
if (!mdev)
|
||||
return;
|
||||
addr->client = mdev->client;
|
||||
addr->port = mdev->port;
|
||||
|
@ -511,7 +519,8 @@ snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private_data)
|
|||
|
||||
if (dp->readq == NULL)
|
||||
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;
|
||||
if (! (mdev->opened & PERM_READ)) {
|
||||
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
|
|||
{
|
||||
struct seq_oss_midi *mdev;
|
||||
|
||||
if ((mdev = get_mididev(dp, dev)) == NULL)
|
||||
mdev = get_mididev(dp, dev);
|
||||
if (!mdev)
|
||||
return -ENODEV;
|
||||
if (snd_midi_event_encode_byte(mdev->coder, c, ev)) {
|
||||
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
|
|||
{
|
||||
struct seq_oss_midi *mdev;
|
||||
|
||||
if ((mdev = get_mididev(dp, dev)) == NULL)
|
||||
mdev = get_mididev(dp, dev);
|
||||
if (!mdev)
|
||||
return -ENXIO;
|
||||
inf->device = dev;
|
||||
inf->dev_type = 0; /* FIXME: ?? */
|
||||
|
|
|
@ -132,7 +132,8 @@ snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int count,
|
|||
}
|
||||
|
||||
/* insert queue */
|
||||
if ((err = insert_queue(dp, &rec, opt)) < 0)
|
||||
err = insert_queue(dp, &rec, opt);
|
||||
if (err < 0)
|
||||
break;
|
||||
|
||||
result += ev_size;
|
||||
|
|
|
@ -451,7 +451,8 @@ snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
|
|||
|
||||
if (info->is_midi)
|
||||
return 0;
|
||||
if ((rec = get_synthdev(dp, dev)) == NULL)
|
||||
rec = get_synthdev(dp, dev);
|
||||
if (!rec)
|
||||
return -ENXIO;
|
||||
|
||||
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
|
|||
info = get_synthinfo_nospec(dp, dev);
|
||||
if (!info || info->is_midi)
|
||||
return -ENXIO;
|
||||
if ((rec = get_synthdev(dp, dev)) == NULL)
|
||||
rec = get_synthdev(dp, dev);
|
||||
if (!rec)
|
||||
return -ENXIO;
|
||||
if (rec->oper.ioctl == NULL)
|
||||
rc = -ENXIO;
|
||||
|
@ -619,7 +621,8 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
|
|||
inf->device = dev;
|
||||
strscpy(inf->name, minf.name, sizeof(inf->name));
|
||||
} else {
|
||||
if ((rec = get_synthdev(dp, dev)) == NULL)
|
||||
rec = get_synthdev(dp, dev);
|
||||
if (!rec)
|
||||
return -ENXIO;
|
||||
inf->synth_type = rec->synth_type;
|
||||
inf->synth_subtype = rec->synth_subtype;
|
||||
|
|
|
@ -27,7 +27,8 @@ snd_seq_oss_writeq_new(struct seq_oss_devinfo *dp, int maxlen)
|
|||
struct seq_oss_writeq *q;
|
||||
struct snd_seq_client_pool pool;
|
||||
|
||||
if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL)
|
||||
q = kzalloc(sizeof(*q), GFP_KERNEL);
|
||||
if (!q)
|
||||
return NULL;
|
||||
q->dp = dp;
|
||||
q->maxlen = maxlen;
|
||||
|
|
|
@ -416,7 +416,10 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,
|
|||
if (snd_BUG_ON(!client))
|
||||
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;
|
||||
|
||||
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,
|
|||
int nonblock;
|
||||
|
||||
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;
|
||||
}
|
||||
if (snd_seq_ev_is_variable(&cell->event)) {
|
||||
struct snd_seq_event tmpev;
|
||||
tmpev = cell->event;
|
||||
|
@ -970,7 +973,8 @@ static int snd_seq_client_enqueue_event(struct snd_seq_client *client,
|
|||
return err;
|
||||
|
||||
/* 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);
|
||||
return err;
|
||||
}
|
||||
|
@ -1312,7 +1316,8 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
|
|||
return -EINVAL;
|
||||
}
|
||||
if (client->type == KERNEL_CLIENT) {
|
||||
if ((callback = info->kernel) != NULL) {
|
||||
callback = info->kernel;
|
||||
if (callback) {
|
||||
if (callback->owner)
|
||||
port->owner = callback->owner;
|
||||
port->private_data = callback->private_data;
|
||||
|
@ -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_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;
|
||||
if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL)
|
||||
sender = snd_seq_client_use_ptr(subs->sender.client);
|
||||
if (!sender)
|
||||
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;
|
||||
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;
|
||||
|
||||
result = check_subscription_permission(client, sport, dport, subs);
|
||||
|
@ -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_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;
|
||||
if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL)
|
||||
sender = snd_seq_client_use_ptr(subs->sender.client);
|
||||
if (!sender)
|
||||
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;
|
||||
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;
|
||||
|
||||
result = check_subscription_permission(client, sport, dport, subs);
|
||||
|
@ -1926,9 +1939,11 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
|
|||
struct snd_seq_client_port *sport = NULL;
|
||||
|
||||
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;
|
||||
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;
|
||||
result = snd_seq_port_get_subscription(&sport->c_src, &subs->dest,
|
||||
subs);
|
||||
|
@ -1955,9 +1970,11 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg)
|
|||
struct list_head *p;
|
||||
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;
|
||||
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;
|
||||
|
||||
switch (subs->type) {
|
||||
|
|
|
@ -109,7 +109,8 @@ create_port(int idx, int type)
|
|||
struct snd_seq_port_callback pcb;
|
||||
struct snd_seq_dummy_port *rec;
|
||||
|
||||
if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL)
|
||||
rec = kzalloc(sizeof(*rec), GFP_KERNEL);
|
||||
if (!rec)
|
||||
return NULL;
|
||||
|
||||
rec->client = my_client;
|
||||
|
|
|
@ -143,7 +143,8 @@ static struct snd_seq_event_cell *fifo_cell_out(struct snd_seq_fifo *f)
|
|||
{
|
||||
struct snd_seq_event_cell *cell;
|
||||
|
||||
if ((cell = f->head) != NULL) {
|
||||
cell = f->head;
|
||||
if (cell) {
|
||||
f->head = cell->next;
|
||||
|
||||
/* reset tail if this was the last element */
|
||||
|
|
|
@ -69,7 +69,8 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event,
|
|||
int len, err;
|
||||
struct snd_seq_event_cell *cell;
|
||||
|
||||
if ((len = get_var_len(event)) <= 0)
|
||||
len = get_var_len(event);
|
||||
if (len <= 0)
|
||||
return len;
|
||||
|
||||
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
|
|||
int len, newlen;
|
||||
int err;
|
||||
|
||||
if ((len = get_var_len(event)) < 0)
|
||||
len = get_var_len(event);
|
||||
if (len < 0)
|
||||
return len;
|
||||
newlen = len;
|
||||
if (size_aligned > 0)
|
||||
|
|
|
@ -101,7 +101,8 @@ static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, i
|
|||
if (snd_BUG_ON(!substream || !buf))
|
||||
return -EINVAL;
|
||||
runtime = substream->runtime;
|
||||
if ((tmp = runtime->avail) < count) {
|
||||
tmp = runtime->avail;
|
||||
if (tmp < count) {
|
||||
if (printk_ratelimit())
|
||||
pr_err("ALSA: seq_midi: MIDI output buffer overrun\n");
|
||||
return -ENOMEM;
|
||||
|
@ -167,10 +168,11 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe
|
|||
struct snd_rawmidi_params params;
|
||||
|
||||
/* open midi port */
|
||||
if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
|
||||
err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
|
||||
msynth->subdevice,
|
||||
SNDRV_RAWMIDI_LFLG_INPUT,
|
||||
&msynth->input_rfile)) < 0) {
|
||||
&msynth->input_rfile);
|
||||
if (err < 0) {
|
||||
pr_debug("ALSA: seq_midi: midi input open failed!!!\n");
|
||||
return err;
|
||||
}
|
||||
|
@ -178,7 +180,8 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe
|
|||
memset(¶ms, 0, sizeof(params));
|
||||
params.avail_min = 1;
|
||||
params.buffer_size = input_buffer_size;
|
||||
if ((err = snd_rawmidi_input_params(msynth->input_rfile.input, ¶ms)) < 0) {
|
||||
err = snd_rawmidi_input_params(msynth->input_rfile.input, ¶ms);
|
||||
if (err < 0) {
|
||||
snd_rawmidi_kernel_release(&msynth->input_rfile);
|
||||
return err;
|
||||
}
|
||||
|
@ -209,10 +212,11 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
|
|||
struct snd_rawmidi_params params;
|
||||
|
||||
/* open midi port */
|
||||
if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
|
||||
err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
|
||||
msynth->subdevice,
|
||||
SNDRV_RAWMIDI_LFLG_OUTPUT,
|
||||
&msynth->output_rfile)) < 0) {
|
||||
&msynth->output_rfile);
|
||||
if (err < 0) {
|
||||
pr_debug("ALSA: seq_midi: midi output open failed!!!\n");
|
||||
return err;
|
||||
}
|
||||
|
@ -220,7 +224,8 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
|
|||
params.avail_min = 1;
|
||||
params.buffer_size = output_buffer_size;
|
||||
params.no_active_sensing = 1;
|
||||
if ((err = snd_rawmidi_output_params(msynth->output_rfile.output, ¶ms)) < 0) {
|
||||
err = snd_rawmidi_output_params(msynth->output_rfile.output, ¶ms);
|
||||
if (err < 0) {
|
||||
snd_rawmidi_kernel_release(&msynth->output_rfile);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -222,7 +222,8 @@ struct snd_seq_queue *snd_seq_queue_find_name(char *name)
|
|||
struct snd_seq_queue *q;
|
||||
|
||||
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)
|
||||
return q;
|
||||
queuefree(q);
|
||||
|
@ -432,7 +433,8 @@ int snd_seq_queue_timer_open(int queueid)
|
|||
if (queue == NULL)
|
||||
return -EINVAL;
|
||||
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);
|
||||
result = snd_seq_timer_open(queue);
|
||||
}
|
||||
|
@ -548,7 +550,8 @@ void snd_seq_queue_client_leave(int client)
|
|||
|
||||
/* delete own queues from queue list */
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -556,7 +559,8 @@ void snd_seq_queue_client_leave(int client)
|
|||
* they are not owned by this client
|
||||
*/
|
||||
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
|
||||
if ((q = queueptr(i)) == NULL)
|
||||
q = queueptr(i);
|
||||
if (!q)
|
||||
continue;
|
||||
if (test_bit(client, q->clients_bitmap)) {
|
||||
snd_seq_prioq_leave(q->tickq, client, 0);
|
||||
|
@ -578,7 +582,8 @@ void snd_seq_queue_client_leave_cells(int client)
|
|||
struct snd_seq_queue *q;
|
||||
|
||||
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
|
||||
if ((q = queueptr(i)) == NULL)
|
||||
q = queueptr(i);
|
||||
if (!q)
|
||||
continue;
|
||||
snd_seq_prioq_leave(q->tickq, 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)
|
|||
struct snd_seq_queue *q;
|
||||
|
||||
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
|
||||
if ((q = queueptr(i)) == NULL)
|
||||
q = queueptr(i);
|
||||
if (!q)
|
||||
continue;
|
||||
if (test_bit(client, q->clients_bitmap) &&
|
||||
(! (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) ||
|
||||
|
@ -724,7 +730,8 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry,
|
|||
int owner;
|
||||
|
||||
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
|
||||
if ((q = queueptr(i)) == NULL)
|
||||
q = queueptr(i);
|
||||
if (!q)
|
||||
continue;
|
||||
|
||||
tmr = q->timer;
|
||||
|
|
|
@ -482,10 +482,11 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi
|
|||
int err;
|
||||
|
||||
*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 */
|
||||
&rmidi)) < 0)
|
||||
&rmidi);
|
||||
if (err < 0)
|
||||
return err;
|
||||
strcpy(rmidi->name, rmidi->id);
|
||||
rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
|
||||
|
|
|
@ -10,20 +10,34 @@
|
|||
#include <linux/vmalloc.h>
|
||||
#include <linux/export.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 */
|
||||
#define SGBUF_TBL_ALIGN 32
|
||||
#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_dma_buffer tmpb;
|
||||
int i;
|
||||
|
||||
if (! sgbuf)
|
||||
return -EINVAL;
|
||||
if (!sgbuf)
|
||||
return;
|
||||
|
||||
vunmap(dmab->area);
|
||||
dmab->area = NULL;
|
||||
|
@ -45,15 +59,11 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab)
|
|||
kfree(sgbuf->page_table);
|
||||
kfree(sgbuf);
|
||||
dmab->private_data = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_ALLOC_PAGES 32
|
||||
|
||||
void *snd_malloc_sgbuf_pages(struct device *device,
|
||||
size_t size, struct snd_dma_buffer *dmab,
|
||||
size_t *res_size)
|
||||
static int snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
|
||||
{
|
||||
struct snd_sg_buf *sgbuf;
|
||||
unsigned int i, pages, chunk, maxpages;
|
||||
|
@ -63,18 +73,16 @@ void *snd_malloc_sgbuf_pages(struct device *device,
|
|||
int type = SNDRV_DMA_TYPE_DEV;
|
||||
pgprot_t prot = PAGE_KERNEL;
|
||||
|
||||
dmab->area = NULL;
|
||||
dmab->addr = 0;
|
||||
dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
|
||||
if (! sgbuf)
|
||||
return NULL;
|
||||
if (!sgbuf)
|
||||
return -ENOMEM;
|
||||
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC_SG) {
|
||||
type = SNDRV_DMA_TYPE_DEV_UC;
|
||||
#ifdef pgprot_noncached
|
||||
prot = pgprot_noncached(PAGE_KERNEL);
|
||||
#endif
|
||||
}
|
||||
sgbuf->dev = device;
|
||||
sgbuf->dev = dmab->dev.dev;
|
||||
pages = snd_sgbuf_aligned_pages(size);
|
||||
sgbuf->tblsize = sgbuf_align_table(pages);
|
||||
table = kcalloc(sgbuf->tblsize, sizeof(*table), GFP_KERNEL);
|
||||
|
@ -94,12 +102,10 @@ void *snd_malloc_sgbuf_pages(struct device *device,
|
|||
if (chunk > maxpages)
|
||||
chunk = maxpages;
|
||||
chunk <<= PAGE_SHIFT;
|
||||
if (snd_dma_alloc_pages_fallback(type, device,
|
||||
if (snd_dma_alloc_pages_fallback(type, dmab->dev.dev,
|
||||
chunk, &tmpb) < 0) {
|
||||
if (!sgbuf->pages)
|
||||
goto _failed;
|
||||
if (!res_size)
|
||||
goto _failed;
|
||||
size = sgbuf->pages * PAGE_SIZE;
|
||||
break;
|
||||
}
|
||||
|
@ -124,27 +130,42 @@ void *snd_malloc_sgbuf_pages(struct device *device,
|
|||
dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, prot);
|
||||
if (! dmab->area)
|
||||
goto _failed;
|
||||
if (res_size)
|
||||
*res_size = sgbuf->size;
|
||||
return dmab->area;
|
||||
return 0;
|
||||
|
||||
_failed:
|
||||
snd_free_sgbuf_pages(dmab); /* free the table */
|
||||
return NULL;
|
||||
snd_dma_sg_free(dmab); /* free the table */
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* compute the max chunk size with continuous pages on sg-buffer
|
||||
*/
|
||||
unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
|
||||
unsigned int ofs, unsigned int size)
|
||||
static dma_addr_t snd_dma_sg_get_addr(struct snd_dma_buffer *dmab,
|
||||
size_t offset)
|
||||
{
|
||||
struct snd_sg_buf *sgbuf = dmab->private_data;
|
||||
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;
|
||||
unsigned int start, end, pg;
|
||||
|
||||
if (!sg)
|
||||
return size;
|
||||
|
||||
start = ofs >> PAGE_SHIFT;
|
||||
end = (ofs + size - 1) >> PAGE_SHIFT;
|
||||
/* check page continuity */
|
||||
|
@ -160,4 +181,11 @@ unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
|
|||
/* ok, all on continuous pages */
|
||||
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
|
|||
|
||||
mutex_lock(&sound_mutex);
|
||||
for (minor = 0; minor < SNDRV_OS_MINORS; ++minor) {
|
||||
if (!(mptr = snd_minors[minor]))
|
||||
mptr = snd_minors[minor];
|
||||
if (!mptr)
|
||||
continue;
|
||||
if (mptr->card >= 0) {
|
||||
if (mptr->device >= 0)
|
||||
|
|
|
@ -217,7 +217,8 @@ static void snd_minor_info_oss_read(struct snd_info_entry *entry,
|
|||
|
||||
mutex_lock(&sound_oss_mutex);
|
||||
for (minor = 0; minor < SNDRV_OSS_MINORS; ++minor) {
|
||||
if (!(mptr = snd_oss_minors[minor]))
|
||||
mptr = snd_oss_minors[minor];
|
||||
if (!mptr)
|
||||
continue;
|
||||
if (mptr->card >= 0)
|
||||
snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", minor,
|
||||
|
|
|
@ -104,7 +104,8 @@ static int snd_mpu401_probe(struct platform_device *devptr)
|
|||
err = snd_mpu401_create(&devptr->dev, dev, &card);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if ((err = snd_card_register(card)) < 0) {
|
||||
err = snd_card_register(card);
|
||||
if (err < 0) {
|
||||
snd_card_free(card);
|
||||
return err;
|
||||
}
|
||||
|
@ -182,7 +183,8 @@ static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
|
|||
err = snd_mpu401_create(&pnp_dev->dev, dev, &card);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if ((err = snd_card_register(card)) < 0) {
|
||||
err = snd_card_register(card);
|
||||
if (err < 0) {
|
||||
snd_card_free(card);
|
||||
return err;
|
||||
}
|
||||
|
@ -227,7 +229,8 @@ static int __init alsa_card_mpu401_init(void)
|
|||
{
|
||||
int i, err;
|
||||
|
||||
if ((err = platform_driver_register(&snd_mpu401_driver)) < 0)
|
||||
err = platform_driver_register(&snd_mpu401_driver);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < SNDRV_CARDS; i++) {
|
||||
|
|
|
@ -271,8 +271,11 @@ static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream)
|
|||
int err;
|
||||
|
||||
mpu = substream->rmidi->private_data;
|
||||
if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
|
||||
if (mpu->open_input) {
|
||||
err = mpu->open_input(mpu);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
|
||||
if (snd_mpu401_do_reset(mpu) < 0)
|
||||
goto error_out;
|
||||
|
@ -293,8 +296,11 @@ static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
|
|||
int err;
|
||||
|
||||
mpu = substream->rmidi->private_data;
|
||||
if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
|
||||
if (mpu->open_output) {
|
||||
err = mpu->open_output(mpu);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
|
||||
if (snd_mpu401_do_reset(mpu) < 0)
|
||||
goto error_out;
|
||||
|
@ -524,8 +530,9 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
|
|||
info_flags |= MPU401_INFO_INPUT | MPU401_INFO_OUTPUT;
|
||||
in_enable = (info_flags & MPU401_INFO_INPUT) ? 1 : 0;
|
||||
out_enable = (info_flags & MPU401_INFO_OUTPUT) ? 1 : 0;
|
||||
if ((err = snd_rawmidi_new(card, "MPU-401U", device,
|
||||
out_enable, in_enable, &rmidi)) < 0)
|
||||
err = snd_rawmidi_new(card, "MPU-401U", device,
|
||||
out_enable, in_enable, &rmidi);
|
||||
if (err < 0)
|
||||
return err;
|
||||
mpu = kzalloc(sizeof(*mpu), GFP_KERNEL);
|
||||
if (!mpu) {
|
||||
|
|
|
@ -566,7 +566,8 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id)
|
|||
*/
|
||||
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);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
@ -628,10 +629,11 @@ static int snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
|
|||
hwports = 8;
|
||||
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->rmidi)) < 0)
|
||||
&mcard->rmidi);
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
rawmidi = mcard->rmidi;
|
||||
rawmidi->private_data = mcard;
|
||||
|
@ -744,7 +746,8 @@ static int __init alsa_card_mtpav_init(void)
|
|||
{
|
||||
int err;
|
||||
|
||||
if ((err = platform_driver_register(&snd_mtpav_driver)) < 0)
|
||||
err = platform_driver_register(&snd_mtpav_driver);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0);
|
||||
|
|
|
@ -950,7 +950,8 @@ static int snd_mts64_probe(struct platform_device *pdev)
|
|||
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");
|
||||
goto release_pardev;
|
||||
}
|
||||
|
@ -963,19 +964,22 @@ static int snd_mts64_probe(struct platform_device *pdev)
|
|||
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");
|
||||
goto __err;
|
||||
}
|
||||
|
||||
/* init device */
|
||||
if ((err = mts64_device_init(p)) < 0)
|
||||
err = mts64_device_init(p);
|
||||
if (err < 0)
|
||||
goto __err;
|
||||
|
||||
platform_set_drvdata(pdev, card);
|
||||
|
||||
/* 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");
|
||||
goto __err;
|
||||
}
|
||||
|
@ -1031,7 +1035,8 @@ static int __init snd_mts64_module_init(void)
|
|||
{
|
||||
int err;
|
||||
|
||||
if ((err = platform_driver_register(&snd_mts64_driver)) < 0)
|
||||
err = platform_driver_register(&snd_mts64_driver);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
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)
|
|||
tid.card = opl3->card->number;
|
||||
tid.device = timer_no;
|
||||
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");
|
||||
timer->private_data = opl3;
|
||||
timer->hw = snd_opl3_timer1;
|
||||
|
@ -263,7 +264,8 @@ static int snd_opl3_timer2_init(struct snd_opl3 * opl3, int timer_no)
|
|||
tid.card = opl3->card->number;
|
||||
tid.device = timer_no;
|
||||
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");
|
||||
timer->private_data = opl3;
|
||||
timer->hw = snd_opl3_timer2;
|
||||
|
@ -348,7 +350,8 @@ int snd_opl3_new(struct snd_card *card,
|
|||
spin_lock_init(&opl3->reg_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);
|
||||
return err;
|
||||
}
|
||||
|
@ -396,21 +399,25 @@ int snd_opl3_create(struct snd_card *card,
|
|||
int err;
|
||||
|
||||
*ropl3 = NULL;
|
||||
if ((err = snd_opl3_new(card, hardware, &opl3)) < 0)
|
||||
err = snd_opl3_new(card, hardware, &opl3);
|
||||
if (err < 0)
|
||||
return err;
|
||||
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_device_free(card, opl3);
|
||||
return -EBUSY;
|
||||
}
|
||||
if (r_port != 0 &&
|
||||
(opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)")) == NULL) {
|
||||
if (r_port != 0) {
|
||||
opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)");
|
||||
if (!opl3->res_r_port) {
|
||||
snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port);
|
||||
snd_device_free(card, opl3);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
}
|
||||
opl3->l_port = l_port;
|
||||
opl3->r_port = r_port;
|
||||
|
||||
|
@ -423,7 +430,8 @@ int snd_opl3_create(struct snd_card *card,
|
|||
break;
|
||||
default:
|
||||
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",
|
||||
opl3->l_port, opl3->r_port);
|
||||
snd_device_free(card, opl3);
|
||||
|
@ -449,11 +457,14 @@ int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev)
|
|||
{
|
||||
int err;
|
||||
|
||||
if (timer1_dev >= 0)
|
||||
if ((err = snd_opl3_timer1_init(opl3, timer1_dev)) < 0)
|
||||
if (timer1_dev >= 0) {
|
||||
err = snd_opl3_timer1_init(opl3, timer1_dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
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);
|
||||
opl3->timer1 = NULL;
|
||||
return err;
|
||||
|
@ -477,7 +488,8 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3,
|
|||
|
||||
/* 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);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -180,8 +180,7 @@ static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op,
|
|||
if (vp2->state == SNDRV_OPL3_ST_ON_2OP) {
|
||||
/* kill two voices, EXPENSIVE */
|
||||
bp++;
|
||||
voice_time = (voice_time > vp->time) ?
|
||||
voice_time : vp->time;
|
||||
voice_time = max(voice_time, vp2->time);
|
||||
}
|
||||
} else {
|
||||
/* allocate 2op voice */
|
||||
|
|
|
@ -136,7 +136,8 @@ static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
|
|||
if (snd_BUG_ON(!arg))
|
||||
return -ENXIO;
|
||||
|
||||
if ((err = snd_opl3_synth_setup(opl3)) < 0)
|
||||
err = snd_opl3_synth_setup(opl3);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* fill the argument data */
|
||||
|
@ -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.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;
|
||||
|
||||
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
|
|||
struct snd_opl3 *opl3 = private_data;
|
||||
int err;
|
||||
|
||||
if ((err = snd_opl3_synth_setup(opl3)) < 0)
|
||||
err = snd_opl3_synth_setup(opl3);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (use_internal_drums) {
|
||||
|
@ -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 ((err = snd_opl3_synth_use_inc(opl3)) < 0)
|
||||
err = snd_opl3_synth_use_inc(opl3);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
opl3->synth_mode = SNDRV_OPL3_MODE_SEQ;
|
||||
|
@ -227,7 +229,8 @@ static int snd_opl3_seq_probe(struct device *_dev)
|
|||
if (client < 0)
|
||||
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);
|
||||
opl3->seq_client = -1;
|
||||
return err;
|
||||
|
|
|
@ -749,7 +749,8 @@ static int snd_portman_probe(struct platform_device *pdev)
|
|||
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");
|
||||
goto release_pardev;
|
||||
}
|
||||
|
@ -762,19 +763,22 @@ static int snd_portman_probe(struct platform_device *pdev)
|
|||
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");
|
||||
goto __err;
|
||||
}
|
||||
|
||||
/* init device */
|
||||
if ((err = portman_device_init(pm)) < 0)
|
||||
err = portman_device_init(pm);
|
||||
if (err < 0)
|
||||
goto __err;
|
||||
|
||||
platform_set_drvdata(pdev, card);
|
||||
|
||||
/* 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");
|
||||
goto __err;
|
||||
}
|
||||
|
@ -831,7 +835,8 @@ static int __init snd_portman_module_init(void)
|
|||
{
|
||||
int err;
|
||||
|
||||
if ((err = platform_driver_register(&snd_portman_driver)) < 0)
|
||||
err = platform_driver_register(&snd_portman_driver);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (parport_register_driver(&portman_parport_driver) != 0) {
|
||||
|
|
|
@ -783,7 +783,8 @@ static int snd_uart16550_create(struct snd_card *card,
|
|||
int err;
|
||||
|
||||
|
||||
if ((uart = kzalloc(sizeof(*uart), GFP_KERNEL)) == NULL)
|
||||
uart = kzalloc(sizeof(*uart), GFP_KERNEL);
|
||||
if (!uart)
|
||||
return -ENOMEM;
|
||||
uart->adaptor = adaptor;
|
||||
uart->card = card;
|
||||
|
@ -792,7 +793,8 @@ static int snd_uart16550_create(struct snd_card *card,
|
|||
uart->base = iobase;
|
||||
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);
|
||||
snd_uart16550_free(uart);
|
||||
return -ENODEV;
|
||||
|
@ -818,7 +820,8 @@ static int snd_uart16550_create(struct snd_card *card,
|
|||
uart->timer_running = 0;
|
||||
|
||||
/* 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);
|
||||
return err;
|
||||
}
|
||||
|
@ -932,14 +935,10 @@ static int snd_serial_probe(struct platform_device *devptr)
|
|||
strcpy(card->driver, "Serial");
|
||||
strcpy(card->shortname, "Serial MIDI (UART16550A)");
|
||||
|
||||
if ((err = snd_uart16550_create(card,
|
||||
port[dev],
|
||||
irq[dev],
|
||||
speed[dev],
|
||||
base[dev],
|
||||
adaptor[dev],
|
||||
droponfull[dev],
|
||||
&uart)) < 0)
|
||||
err = snd_uart16550_create(card, port[dev], irq[dev], speed[dev],
|
||||
base[dev], adaptor[dev], droponfull[dev],
|
||||
&uart);
|
||||
if (err < 0)
|
||||
goto _err;
|
||||
|
||||
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)
|
|||
uart->base,
|
||||
uart->irq);
|
||||
|
||||
if ((err = snd_card_register(card)) < 0)
|
||||
err = snd_card_register(card);
|
||||
if (err < 0)
|
||||
goto _err;
|
||||
|
||||
platform_set_drvdata(devptr, card);
|
||||
|
@ -992,7 +992,8 @@ static int __init alsa_card_serial_init(void)
|
|||
{
|
||||
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;
|
||||
|
||||
cards = 0;
|
||||
|
|
|
@ -110,20 +110,25 @@ static int vx_transfer_end(struct vx_core *chip, int cmd)
|
|||
{
|
||||
int err;
|
||||
|
||||
if ((err = vx_reset_chk(chip)) < 0)
|
||||
err = vx_reset_chk(chip);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* If error, Read RX */
|
||||
if ((err = vx_inb(chip, ISR)) & ISR_ERR) {
|
||||
if ((err = vx_wait_for_rx_full(chip)) < 0) {
|
||||
err = vx_inb(chip, ISR);
|
||||
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");
|
||||
return err;
|
||||
}
|
||||
|
@ -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)
|
||||
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");
|
||||
return err;
|
||||
}
|
||||
|
@ -254,7 +260,8 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
|
|||
rmh->Cmd[0] &= MASK_1_WORD_COMMAND;
|
||||
|
||||
/* 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");
|
||||
return err;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
/* 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");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* If error, get error value from RX */
|
||||
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");
|
||||
return err;
|
||||
}
|
||||
|
@ -292,7 +302,8 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
|
|||
if (rmh->LgCmd > 1) {
|
||||
for (i = 1; i < rmh->LgCmd; i++) {
|
||||
/* 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");
|
||||
return err;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
/* 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");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
/* 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");
|
||||
return err;
|
||||
}
|
||||
|
@ -362,17 +375,21 @@ int vx_send_rih_nolock(struct vx_core *chip, int cmd)
|
|||
#if 0
|
||||
printk(KERN_DEBUG "send_rih: cmd = 0x%x\n", cmd);
|
||||
#endif
|
||||
if ((err = vx_reset_chk(chip)) < 0)
|
||||
err = vx_reset_chk(chip);
|
||||
if (err < 0)
|
||||
return err;
|
||||
/* send the IRQ */
|
||||
if ((err = vx_send_irq_dsp(chip, cmd)) < 0)
|
||||
err = vx_send_irq_dsp(chip, cmd);
|
||||
if (err < 0)
|
||||
return err;
|
||||
/* 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;
|
||||
/* If error, read RX */
|
||||
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;
|
||||
err = vx_inb(chip, RXH) << 16;
|
||||
err |= vx_inb(chip, RXM) << 8;
|
||||
|
@ -648,7 +665,8 @@ int snd_vx_dsp_boot(struct vx_core *chip, const struct firmware *boot)
|
|||
vx_reset_board(chip, cold_reset);
|
||||
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;
|
||||
msleep(10);
|
||||
|
||||
|
@ -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) {
|
||||
image = dsp->data + i;
|
||||
/* 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
|
||||
"dsp loading error at position %d\n", i);
|
||||
return err;
|
||||
|
@ -698,7 +717,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp)
|
|||
|
||||
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;
|
||||
|
||||
vx_toggle_dac_mute(chip, 0);
|
||||
|
|
|
@ -78,15 +78,19 @@ int snd_vx_setup_firmware(struct vx_core *chip)
|
|||
|
||||
/* ok, we reached to the last one */
|
||||
/* create the devices if not built yet */
|
||||
if ((err = snd_vx_pcm_new(chip)) < 0)
|
||||
err = snd_vx_pcm_new(chip);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if ((err = snd_vx_mixer_new(chip)) < 0)
|
||||
err = snd_vx_mixer_new(chip);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (chip->ops->add_controls)
|
||||
if ((err = chip->ops->add_controls(chip)) < 0)
|
||||
if (chip->ops->add_controls) {
|
||||
err = chip->ops->add_controls(chip);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
chip->chip_status |= VX_STAT_DEVICE_INIT;
|
||||
chip->chip_status |= VX_STAT_CHIP_INIT;
|
||||
|
|
|
@ -910,7 +910,8 @@ int snd_vx_mixer_new(struct vx_core *chip)
|
|||
temp = vx_control_output_level;
|
||||
temp.index = i;
|
||||
temp.tlv.p = chip->hw->output_level_db_scale;
|
||||
if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
|
||||
err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -921,22 +922,26 @@ int snd_vx_mixer_new(struct vx_core *chip)
|
|||
temp.index = i;
|
||||
temp.name = "PCM Playback Volume";
|
||||
temp.private_value = val;
|
||||
if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
|
||||
err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
temp = vx_control_output_switch;
|
||||
temp.index = i;
|
||||
temp.private_value = val;
|
||||
if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
|
||||
err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
temp = vx_control_monitor_gain;
|
||||
temp.index = i;
|
||||
temp.private_value = val;
|
||||
if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
|
||||
err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
temp = vx_control_monitor_switch;
|
||||
temp.index = i;
|
||||
temp.private_value = val;
|
||||
if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
|
||||
err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
for (i = 0; i < chip->hw->num_outs; i++) {
|
||||
|
@ -944,20 +949,25 @@ int snd_vx_mixer_new(struct vx_core *chip)
|
|||
temp.index = i;
|
||||
temp.name = "PCM Capture Volume";
|
||||
temp.private_value = (i * 2) | (1 << 8);
|
||||
if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
|
||||
err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Audio source */
|
||||
if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip))) < 0)
|
||||
err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
/* clock mode */
|
||||
if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip))) < 0)
|
||||
err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
/* IEC958 controls */
|
||||
if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip))) < 0)
|
||||
err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958, chip))) < 0)
|
||||
err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958, chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
/* VU, peak, saturation meters */
|
||||
for (c = 0; c < 2; c++) {
|
||||
|
@ -968,7 +978,8 @@ int snd_vx_mixer_new(struct vx_core *chip)
|
|||
temp = vx_control_saturation;
|
||||
temp.index = i;
|
||||
temp.private_value = val;
|
||||
if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
|
||||
err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
sprintf(name, "%s VU Meter", dir[c]);
|
||||
|
@ -976,14 +987,16 @@ int snd_vx_mixer_new(struct vx_core *chip)
|
|||
temp.index = i;
|
||||
temp.name = name;
|
||||
temp.private_value = val;
|
||||
if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
|
||||
err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
sprintf(name, "%s Peak Meter", dir[c]);
|
||||
temp = vx_control_peak_meter;
|
||||
temp.index = i;
|
||||
temp.name = name;
|
||||
temp.private_value = val;
|
||||
if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
|
||||
err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -341,10 +341,12 @@ static int vx_toggle_pipe(struct vx_core *chip, struct vx_pipe *pipe, int state)
|
|||
}
|
||||
}
|
||||
|
||||
if ((err = vx_conf_pipe(chip, pipe)) < 0)
|
||||
err = vx_conf_pipe(chip, pipe);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if ((err = vx_send_irqa(chip)) < 0)
|
||||
err = vx_send_irqa(chip);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* If it completes successfully, wait for the pipes
|
||||
|
@ -680,8 +682,9 @@ static void vx_pcm_playback_transfer(struct vx_core *chip,
|
|||
if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE))
|
||||
return;
|
||||
for (i = 0; i < nchunks; i++) {
|
||||
if ((err = vx_pcm_playback_transfer_chunk(chip, runtime, pipe,
|
||||
chip->ibl.size)) < 0)
|
||||
err = vx_pcm_playback_transfer_chunk(chip, runtime, pipe,
|
||||
chip->ibl.size);
|
||||
if (err < 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -698,7 +701,8 @@ static void vx_pcm_playback_update(struct vx_core *chip,
|
|||
struct snd_pcm_runtime *runtime = subs->runtime;
|
||||
|
||||
if (pipe->running && ! (chip->chip_status & VX_STAT_IS_STALE)) {
|
||||
if ((err = vx_update_pipe_position(chip, runtime, pipe)) < 0)
|
||||
err = vx_update_pipe_position(chip, runtime, pipe);
|
||||
if (err < 0)
|
||||
return;
|
||||
if (pipe->transferred >= (int)runtime->period_size) {
|
||||
pipe->transferred %= runtime->period_size;
|
||||
|
@ -747,11 +751,13 @@ static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
|
|||
pipe->running = 0;
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
if ((err = vx_toggle_pipe(chip, pipe, 0)) < 0)
|
||||
err = vx_toggle_pipe(chip, pipe, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0)
|
||||
err = vx_toggle_pipe(chip, pipe, 1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
break;
|
||||
default:
|
||||
|
@ -792,13 +798,15 @@ static int vx_pcm_prepare(struct snd_pcm_substream *subs)
|
|||
snd_printdd(KERN_DEBUG "reopen the pipe with data_mode = %d\n", data_mode);
|
||||
vx_init_rmh(&rmh, CMD_FREE_PIPE);
|
||||
vx_set_pipe_cmd_params(&rmh, 0, pipe->number, 0);
|
||||
if ((err = vx_send_msg(chip, &rmh)) < 0)
|
||||
err = vx_send_msg(chip, &rmh);
|
||||
if (err < 0)
|
||||
return err;
|
||||
vx_init_rmh(&rmh, CMD_RES_PIPE);
|
||||
vx_set_pipe_cmd_params(&rmh, 0, pipe->number, pipe->channels);
|
||||
if (data_mode)
|
||||
rmh.Cmd[0] |= BIT_DATA_MODE;
|
||||
if ((err = vx_send_msg(chip, &rmh)) < 0)
|
||||
err = vx_send_msg(chip, &rmh);
|
||||
if (err < 0)
|
||||
return err;
|
||||
pipe->data_mode = data_mode;
|
||||
}
|
||||
|
@ -810,7 +818,8 @@ static int vx_pcm_prepare(struct snd_pcm_substream *subs)
|
|||
}
|
||||
vx_set_clock(chip, runtime->rate);
|
||||
|
||||
if ((err = vx_set_format(chip, pipe, runtime)) < 0)
|
||||
err = vx_set_format(chip, pipe, runtime);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (vx_is_pcmcia(chip)) {
|
||||
|
@ -1187,7 +1196,8 @@ int snd_vx_pcm_new(struct vx_core *chip)
|
|||
unsigned int i;
|
||||
int err;
|
||||
|
||||
if ((err = vx_init_audio_io(chip)) < 0)
|
||||
err = vx_init_audio_io(chip);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < chip->hw->num_codecs; i++) {
|
||||
|
|
|
@ -18,8 +18,25 @@ config SND_DICE
|
|||
select SND_HWDEP
|
||||
select SND_FIREWIRE_LIB
|
||||
help
|
||||
Say Y here to include support for many DACs based on the DICE
|
||||
chip family (DICE-II/Jr/Mini) which TC Applied Technologies produces.
|
||||
Say Y here to include support for devices based on the DICE chip family
|
||||
(DICE-II/TCD2210(Mini)/TCD2220(Jr.)) which TC Applied Technologies (TCAT) produced.
|
||||
* Allen and Heath Zed R16
|
||||
* Alesis iO 14/26 FireWire, MasterControl, MultiMix 8/12/16 FireWire
|
||||
* Avid Mbox 3 Pro
|
||||
* FlexRadio Systems FLEX-3000, FLEX-5000
|
||||
* Focusrite Liquid Saffire 56
|
||||
* Focusrite Saffire Pro 14, Pro 24, Pro 24 DSP, Pro 26, Pro 40(TCD2220)
|
||||
* Harman Music Group Lexicon I-ONIX FW810S
|
||||
* Loud Technologies Mackie Onyx Blackbird, Onyx 820i/1220i/1620i/1640i (latter models)
|
||||
* M-Audio ProFire 610/2626
|
||||
* Mytek Stereo192-DSD DAC
|
||||
* Midas Klark Teknik VeniceF series
|
||||
* PreSonus FireStudio, FireStudio Mobile, FireStudio Project, FireStudio Tube
|
||||
* PreSonus StudioLive 16.4.2, 16.0.2, 24.4.2, 32.4.2
|
||||
* Solid State Logic Duende Classic, Duende Mini
|
||||
* TC Electronic Studio Konnekt 48, Konnekt 24D, Konnekt Live, Impact Twin
|
||||
* TC Electronic Digital Konnekt x32, Desktop Konnekt 6
|
||||
* Weiss Engineering ADC2, Vesta, Minerva, AFI1, DAC1, INT202, DAC202
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-dice.
|
||||
|
@ -38,7 +55,7 @@ config SND_OXFW
|
|||
* Mackie(Loud) Onyx 1640i (former model)
|
||||
* Mackie(Loud) Onyx Satellite
|
||||
* Mackie(Loud) Tapco Link.Firewire
|
||||
* Mackie(Loud) d.4 pro
|
||||
* Mackie(Loud) d.2 pro/d.4 pro (built-in FireWire card with OXFW971 ASIC)
|
||||
* Mackie(Loud) U.420/U.420d
|
||||
* TASCAM FireOne
|
||||
* Stanton Controllers & Systems 1 Deck/Mixer
|
||||
|
@ -84,7 +101,7 @@ config SND_BEBOB
|
|||
* PreSonus FIREBOX/FIREPOD/FP10/Inspire1394
|
||||
* BridgeCo RDAudio1/Audio5
|
||||
* Mackie Onyx 1220/1620/1640 (FireWire I/O Card)
|
||||
* Mackie d.2 (FireWire Option) and d.2 Pro
|
||||
* Mackie d.2 (optional FireWire card with DM1000 ASIC)
|
||||
* Stanton FinalScratch 2 (ScratchAmp)
|
||||
* Tascam IF-FW/DM
|
||||
* Behringer XENIX UFX 1204/1604
|
||||
|
@ -110,6 +127,7 @@ config SND_BEBOB
|
|||
* M-Audio Ozonic/NRV10/ProfireLightBridge
|
||||
* M-Audio FireWire 1814/ProjectMix IO
|
||||
* Digidesign Mbox 2 Pro
|
||||
* ToneWeal FW66
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-bebob.
|
||||
|
@ -148,12 +166,16 @@ config SND_FIREWIRE_MOTU
|
|||
select SND_HWDEP
|
||||
help
|
||||
Say Y here to enable support for FireWire devices which MOTU produced:
|
||||
* 828
|
||||
* 896
|
||||
* 828mk2
|
||||
* Traveler
|
||||
* Ultralite
|
||||
* 8pre
|
||||
* 828mk3 (FireWire only)
|
||||
* 828mk3 (Hybrid)
|
||||
* Ultralite mk3 (FireWire only)
|
||||
* Ultralite mk3 (Hybrid)
|
||||
* Audio Express
|
||||
* 4pre
|
||||
|
||||
|
|
|
@ -410,10 +410,10 @@ static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s,
|
|||
* @s: the AMDTP stream to initialize
|
||||
* @unit: the target of the 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,
|
||||
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;
|
||||
|
||||
|
|
|
@ -45,5 +45,5 @@ void amdtp_am824_midi_trigger(struct amdtp_stream *s, unsigned int port,
|
|||
struct snd_rawmidi_substream *midi);
|
||||
|
||||
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);
|
||||
#endif
|
||||
|
|
|
@ -49,7 +49,7 @@ TRACE_EVENT(amdtp_packet,
|
|||
__entry->data_blocks = data_blocks;
|
||||
__entry->data_block_counter = data_block_counter,
|
||||
__entry->packet_index = packet_index;
|
||||
__entry->irq = !!in_interrupt();
|
||||
__entry->irq = !!in_softirq();
|
||||
__entry->index = index;
|
||||
),
|
||||
TP_printk(
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -35,6 +35,8 @@
|
|||
* @CIP_NO_HEADERS: a lack of headers in packets
|
||||
* @CIP_UNALIGHED_DBC: Only for in-stream. The value of dbc is not alighed to
|
||||
* the value of current SYT_INTERVAL; e.g. initial value is not zero.
|
||||
* @CIP_UNAWARE_SYT: For outgoing packet, the value in SYT field of CIP is 0xffff.
|
||||
* For incoming packet, the value in SYT field of CIP is not handled.
|
||||
*/
|
||||
enum cip_flags {
|
||||
CIP_NONBLOCKING = 0x00,
|
||||
|
@ -48,6 +50,7 @@ enum cip_flags {
|
|||
CIP_HEADER_WITHOUT_EOH = 0x80,
|
||||
CIP_NO_HEADER = 0x100,
|
||||
CIP_UNALIGHED_DBC = 0x200,
|
||||
CIP_UNAWARE_SYT = 0x400,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -112,7 +115,8 @@ typedef unsigned int (*amdtp_stream_process_ctx_payloads_t)(
|
|||
struct amdtp_domain;
|
||||
struct amdtp_stream {
|
||||
struct fw_unit *unit;
|
||||
enum cip_flags flags;
|
||||
// The combination of cip_flags enumeration-constants.
|
||||
unsigned int flags;
|
||||
enum amdtp_stream_direction direction;
|
||||
struct mutex mutex;
|
||||
|
||||
|
@ -134,19 +138,37 @@ struct amdtp_stream {
|
|||
// Fixed interval of dbc between previos/current
|
||||
// packets.
|
||||
unsigned int dbc_interval;
|
||||
|
||||
// The device starts multiplexing events to the packet.
|
||||
bool event_starts;
|
||||
|
||||
struct {
|
||||
struct seq_desc *descs;
|
||||
unsigned int size;
|
||||
unsigned int tail;
|
||||
} cache;
|
||||
} tx;
|
||||
struct {
|
||||
// To calculate CIP data blocks and tstamp.
|
||||
unsigned int transfer_delay;
|
||||
unsigned int seq_index;
|
||||
|
||||
// To generate CIP header.
|
||||
unsigned int fdf;
|
||||
int syt_override;
|
||||
|
||||
// To generate constant hardware IRQ.
|
||||
unsigned int event_count;
|
||||
unsigned int events_per_period;
|
||||
|
||||
// To calculate CIP data blocks and tstamp.
|
||||
struct {
|
||||
struct seq_desc *descs;
|
||||
unsigned int size;
|
||||
unsigned int tail;
|
||||
unsigned int head;
|
||||
} seq;
|
||||
|
||||
unsigned int data_block_state;
|
||||
unsigned int syt_offset_state;
|
||||
unsigned int last_syt_offset;
|
||||
|
||||
struct amdtp_stream *replay_target;
|
||||
unsigned int cache_head;
|
||||
} rx;
|
||||
} ctx_data;
|
||||
|
||||
|
@ -157,20 +179,21 @@ struct amdtp_stream {
|
|||
unsigned int sph;
|
||||
unsigned int fmt;
|
||||
|
||||
/* Internal flags. */
|
||||
// Internal flags.
|
||||
unsigned int transfer_delay;
|
||||
enum cip_sfc sfc;
|
||||
unsigned int syt_interval;
|
||||
|
||||
/* For a PCM substream processing. */
|
||||
struct snd_pcm_substream *pcm;
|
||||
struct work_struct period_work;
|
||||
snd_pcm_uframes_t pcm_buffer_pointer;
|
||||
unsigned int pcm_period_pointer;
|
||||
|
||||
/* To wait for first packet. */
|
||||
bool callbacked;
|
||||
wait_queue_head_t callback_wait;
|
||||
u32 start_cycle;
|
||||
// To start processing content of packets at the same cycle in several contexts for
|
||||
// each direction.
|
||||
bool ready_processing;
|
||||
wait_queue_head_t ready_wait;
|
||||
unsigned int next_cycle;
|
||||
|
||||
/* For backends to process data blocks. */
|
||||
void *protocol;
|
||||
|
@ -184,7 +207,7 @@ struct amdtp_stream {
|
|||
};
|
||||
|
||||
int amdtp_stream_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,
|
||||
unsigned int fmt,
|
||||
amdtp_stream_process_ctx_payloads_t process_ctx_payloads,
|
||||
unsigned int protocol_size);
|
||||
|
@ -259,21 +282,6 @@ static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc)
|
|||
return sfc & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdtp_stream_wait_callback - sleep till callbacked or timeout
|
||||
* @s: the AMDTP stream
|
||||
* @timeout: msec till timeout
|
||||
*
|
||||
* If this function return false, the AMDTP stream should be stopped.
|
||||
*/
|
||||
static inline bool amdtp_stream_wait_callback(struct amdtp_stream *s,
|
||||
unsigned int timeout)
|
||||
{
|
||||
return wait_event_timeout(s->callback_wait,
|
||||
s->callbacked,
|
||||
msecs_to_jiffies(timeout)) > 0;
|
||||
}
|
||||
|
||||
struct seq_desc {
|
||||
unsigned int syt_offset;
|
||||
unsigned int data_blocks;
|
||||
|
@ -287,13 +295,16 @@ struct amdtp_domain {
|
|||
|
||||
struct amdtp_stream *irq_target;
|
||||
|
||||
struct seq_desc *seq_descs;
|
||||
unsigned int seq_size;
|
||||
unsigned int seq_tail;
|
||||
struct {
|
||||
unsigned int tx_init_skip;
|
||||
unsigned int tx_start;
|
||||
unsigned int rx_start;
|
||||
} processing_cycle;
|
||||
|
||||
unsigned int data_block_state;
|
||||
unsigned int syt_offset_state;
|
||||
unsigned int last_syt_offset;
|
||||
struct {
|
||||
bool enable:1;
|
||||
bool on_the_fly:1;
|
||||
} replay;
|
||||
};
|
||||
|
||||
int amdtp_domain_init(struct amdtp_domain *d);
|
||||
|
@ -302,7 +313,8 @@ void amdtp_domain_destroy(struct amdtp_domain *d);
|
|||
int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s,
|
||||
int channel, int speed);
|
||||
|
||||
int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle);
|
||||
int amdtp_domain_start(struct amdtp_domain *d, unsigned int tx_init_skip_cycles, bool replay_seq,
|
||||
bool replay_on_the_fly);
|
||||
void amdtp_domain_stop(struct amdtp_domain *d);
|
||||
|
||||
static inline int amdtp_domain_set_events_per_period(struct amdtp_domain *d,
|
||||
|
@ -319,4 +331,25 @@ unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d,
|
|||
struct amdtp_stream *s);
|
||||
int amdtp_domain_stream_pcm_ack(struct amdtp_domain *d, struct amdtp_stream *s);
|
||||
|
||||
/**
|
||||
* amdtp_domain_wait_ready - sleep till being ready to process packets or timeout
|
||||
* @d: the AMDTP domain
|
||||
* @timeout_ms: msec till timeout
|
||||
*
|
||||
* If this function return false, the AMDTP domain should be stopped.
|
||||
*/
|
||||
static inline bool amdtp_domain_wait_ready(struct amdtp_domain *d, unsigned int timeout_ms)
|
||||
{
|
||||
struct amdtp_stream *s;
|
||||
|
||||
list_for_each_entry(s, &d->streams, list) {
|
||||
unsigned int j = msecs_to_jiffies(timeout_ms);
|
||||
|
||||
if (wait_event_interruptible_timeout(s->ready_wait, s->ready_processing, j) <= 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,14 +40,12 @@ static DECLARE_BITMAP(devices_used, SNDRV_CARDS);
|
|||
#define VEN_EDIROL 0x000040ab
|
||||
#define VEN_PRESONUS 0x00000a92
|
||||
#define VEN_BRIDGECO 0x000007f5
|
||||
#define VEN_MACKIE1 0x0000000f
|
||||
#define VEN_MACKIE2 0x00000ff2
|
||||
#define VEN_MACKIE 0x00000ff2
|
||||
#define VEN_STANTON 0x00001260
|
||||
#define VEN_TASCAM 0x0000022e
|
||||
#define VEN_BEHRINGER 0x00001564
|
||||
#define VEN_APOGEE 0x000003db
|
||||
#define VEN_ESI 0x00000f1b
|
||||
#define VEN_ACOUSTIC 0x00000002
|
||||
#define VEN_CME 0x0000000a
|
||||
#define VEN_PHONIC 0x00001496
|
||||
#define VEN_LYNX 0x000019e5
|
||||
|
@ -56,14 +54,15 @@ static DECLARE_BITMAP(devices_used, SNDRV_CARDS);
|
|||
#define VEN_TERRATEC 0x00000aac
|
||||
#define VEN_YAMAHA 0x0000a0de
|
||||
#define VEN_FOCUSRITE 0x0000130e
|
||||
#define VEN_MAUDIO1 0x00000d6c
|
||||
#define VEN_MAUDIO2 0x000007f5
|
||||
#define VEN_MAUDIO 0x00000d6c
|
||||
#define VEN_DIGIDESIGN 0x00a07e
|
||||
#define OUI_SHOUYO 0x002327
|
||||
|
||||
#define MODEL_FOCUSRITE_SAFFIRE_BOTH 0x00000000
|
||||
#define MODEL_MAUDIO_AUDIOPHILE_BOTH 0x00010060
|
||||
#define MODEL_MAUDIO_FW1814 0x00010071
|
||||
#define MODEL_MAUDIO_PROJECTMIX 0x00010091
|
||||
#define MODEL_MAUDIO_PROFIRELIGHTBRIDGE 0x000100a1
|
||||
|
||||
static int
|
||||
name_device(struct snd_bebob *bebob)
|
||||
|
@ -74,7 +73,6 @@ name_device(struct snd_bebob *bebob)
|
|||
u32 hw_id;
|
||||
u32 data[2] = {0};
|
||||
u32 revision;
|
||||
u32 version;
|
||||
int err;
|
||||
|
||||
/* get vendor name from root directory */
|
||||
|
@ -107,12 +105,6 @@ name_device(struct snd_bebob *bebob)
|
|||
if (err < 0)
|
||||
goto end;
|
||||
|
||||
err = snd_bebob_read_quad(bebob->unit, INFO_OFFSET_BEBOB_VERSION,
|
||||
&version);
|
||||
if (err < 0)
|
||||
goto end;
|
||||
bebob->version = version;
|
||||
|
||||
strcpy(bebob->card->driver, "BeBoB");
|
||||
strcpy(bebob->card->shortname, model);
|
||||
strcpy(bebob->card->mixername, model);
|
||||
|
@ -135,6 +127,9 @@ bebob_card_free(struct snd_card *card)
|
|||
mutex_unlock(&devices_mutex);
|
||||
|
||||
snd_bebob_stream_destroy_duplex(bebob);
|
||||
|
||||
mutex_destroy(&bebob->mutex);
|
||||
fw_unit_put(bebob->unit);
|
||||
}
|
||||
|
||||
static const struct snd_bebob_spec *
|
||||
|
@ -162,16 +157,55 @@ check_audiophile_booted(struct fw_unit *unit)
|
|||
return strncmp(name, "FW Audiophile Bootloader", 24) != 0;
|
||||
}
|
||||
|
||||
static void
|
||||
do_registration(struct work_struct *work)
|
||||
static int detect_quirks(struct snd_bebob *bebob, const struct ieee1394_device_id *entry)
|
||||
{
|
||||
if (entry->vendor_id == VEN_MAUDIO) {
|
||||
switch (entry->model_id) {
|
||||
case MODEL_MAUDIO_PROFIRELIGHTBRIDGE:
|
||||
// M-Audio ProFire Lightbridge has a quirk to transfer packets with
|
||||
// discontinuous cycle or data block counter in early stage of packet
|
||||
// streaming. The cycle span from the first packet with event is variable.
|
||||
bebob->quirks |= SND_BEBOB_QUIRK_INITIAL_DISCONTINUOUS_DBC;
|
||||
break;
|
||||
case MODEL_MAUDIO_FW1814:
|
||||
case MODEL_MAUDIO_PROJECTMIX:
|
||||
// At high sampling rate, M-Audio special firmware transmits empty packet
|
||||
// with the value of dbc incremented by 8.
|
||||
bebob->quirks |= SND_BEBOB_QUIRK_WRONG_DBC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bebob_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry)
|
||||
{
|
||||
struct snd_bebob *bebob =
|
||||
container_of(work, struct snd_bebob, dwork.work);
|
||||
unsigned int card_index;
|
||||
struct snd_card *card;
|
||||
struct snd_bebob *bebob;
|
||||
const struct snd_bebob_spec *spec;
|
||||
int err;
|
||||
|
||||
if (bebob->registered)
|
||||
return;
|
||||
if (entry->vendor_id == VEN_FOCUSRITE &&
|
||||
entry->model_id == MODEL_FOCUSRITE_SAFFIRE_BOTH)
|
||||
spec = get_saffire_spec(unit);
|
||||
else if (entry->vendor_id == VEN_MAUDIO &&
|
||||
entry->model_id == MODEL_MAUDIO_AUDIOPHILE_BOTH &&
|
||||
!check_audiophile_booted(unit))
|
||||
spec = NULL;
|
||||
else
|
||||
spec = (const struct snd_bebob_spec *)entry->driver_data;
|
||||
|
||||
if (spec == NULL) {
|
||||
// To boot up M-Audio models.
|
||||
if (entry->vendor_id == VEN_MAUDIO || entry->vendor_id == VEN_BRIDGECO)
|
||||
return snd_bebob_maudio_load_firmware(unit);
|
||||
else
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mutex_lock(&devices_mutex);
|
||||
for (card_index = 0; card_index < SNDRV_CARDS; card_index++) {
|
||||
|
@ -180,27 +214,40 @@ do_registration(struct work_struct *work)
|
|||
}
|
||||
if (card_index >= SNDRV_CARDS) {
|
||||
mutex_unlock(&devices_mutex);
|
||||
return;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
err = snd_card_new(&bebob->unit->device, index[card_index],
|
||||
id[card_index], THIS_MODULE, 0, &bebob->card);
|
||||
err = snd_card_new(&unit->device, index[card_index], id[card_index], THIS_MODULE,
|
||||
sizeof(*bebob), &card);
|
||||
if (err < 0) {
|
||||
mutex_unlock(&devices_mutex);
|
||||
return;
|
||||
return err;
|
||||
}
|
||||
card->private_free = bebob_card_free;
|
||||
set_bit(card_index, devices_used);
|
||||
mutex_unlock(&devices_mutex);
|
||||
|
||||
bebob->card->private_free = bebob_card_free;
|
||||
bebob->card->private_data = bebob;
|
||||
bebob = card->private_data;
|
||||
bebob->unit = fw_unit_get(unit);
|
||||
dev_set_drvdata(&unit->device, bebob);
|
||||
bebob->card = card;
|
||||
bebob->card_index = card_index;
|
||||
|
||||
bebob->spec = spec;
|
||||
mutex_init(&bebob->mutex);
|
||||
spin_lock_init(&bebob->lock);
|
||||
init_waitqueue_head(&bebob->hwdep_wait);
|
||||
|
||||
err = name_device(bebob);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = detect_quirks(bebob, entry);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
if (bebob->spec == &maudio_special_spec) {
|
||||
if (bebob->entry->model_id == MODEL_MAUDIO_FW1814)
|
||||
if (entry->model_id == MODEL_MAUDIO_FW1814)
|
||||
err = snd_bebob_maudio_special_discover(bebob, true);
|
||||
else
|
||||
err = snd_bebob_maudio_special_discover(bebob, false);
|
||||
|
@ -230,80 +277,26 @@ do_registration(struct work_struct *work)
|
|||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = snd_card_register(bebob->card);
|
||||
err = snd_card_register(card);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
bebob->registered = true;
|
||||
|
||||
return;
|
||||
error:
|
||||
snd_card_free(bebob->card);
|
||||
dev_info(&bebob->unit->device,
|
||||
"Sound card registration failed: %d\n", err);
|
||||
}
|
||||
|
||||
static int
|
||||
bebob_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry)
|
||||
{
|
||||
struct snd_bebob *bebob;
|
||||
const struct snd_bebob_spec *spec;
|
||||
|
||||
if (entry->vendor_id == VEN_FOCUSRITE &&
|
||||
entry->model_id == MODEL_FOCUSRITE_SAFFIRE_BOTH)
|
||||
spec = get_saffire_spec(unit);
|
||||
else if (entry->vendor_id == VEN_MAUDIO1 &&
|
||||
entry->model_id == MODEL_MAUDIO_AUDIOPHILE_BOTH &&
|
||||
!check_audiophile_booted(unit))
|
||||
spec = NULL;
|
||||
else
|
||||
spec = (const struct snd_bebob_spec *)entry->driver_data;
|
||||
|
||||
if (spec == NULL) {
|
||||
if (entry->vendor_id == VEN_MAUDIO1 ||
|
||||
entry->vendor_id == VEN_MAUDIO2)
|
||||
return snd_bebob_maudio_load_firmware(unit);
|
||||
else
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Allocate this independent of sound card instance. */
|
||||
bebob = devm_kzalloc(&unit->device, sizeof(struct snd_bebob),
|
||||
GFP_KERNEL);
|
||||
if (!bebob)
|
||||
return -ENOMEM;
|
||||
bebob->unit = fw_unit_get(unit);
|
||||
dev_set_drvdata(&unit->device, bebob);
|
||||
|
||||
bebob->entry = entry;
|
||||
bebob->spec = spec;
|
||||
mutex_init(&bebob->mutex);
|
||||
spin_lock_init(&bebob->lock);
|
||||
init_waitqueue_head(&bebob->hwdep_wait);
|
||||
|
||||
/* Allocate and register this sound card later. */
|
||||
INIT_DEFERRABLE_WORK(&bebob->dwork, do_registration);
|
||||
|
||||
if (entry->vendor_id != VEN_MAUDIO1 ||
|
||||
(entry->model_id != MODEL_MAUDIO_FW1814 &&
|
||||
entry->model_id != MODEL_MAUDIO_PROJECTMIX)) {
|
||||
snd_fw_schedule_registration(unit, &bebob->dwork);
|
||||
} else {
|
||||
/*
|
||||
* This is a workaround. This bus reset seems to have an effect
|
||||
* to make devices correctly handling transactions. Without
|
||||
* this, the devices have gap_count mismatch. This causes much
|
||||
* failure of transaction.
|
||||
*
|
||||
* Just after registration, user-land application receive
|
||||
* signals from dbus and starts I/Os. To avoid I/Os till the
|
||||
* future bus reset, registration is done in next update().
|
||||
*/
|
||||
fw_schedule_bus_reset(fw_parent_device(bebob->unit)->card,
|
||||
false, true);
|
||||
if (entry->vendor_id == VEN_MAUDIO &&
|
||||
(entry->model_id == MODEL_MAUDIO_FW1814 || entry->model_id == MODEL_MAUDIO_PROJECTMIX)) {
|
||||
// This is a workaround. This bus reset seems to have an effect to make devices
|
||||
// correctly handling transactions. Without this, the devices have gap_count
|
||||
// mismatch. This causes much failure of transaction.
|
||||
//
|
||||
// Just after registration, user-land application receive signals from dbus and
|
||||
// starts I/Os. To avoid I/Os till the future bus reset, registration is done in
|
||||
// next update().
|
||||
fw_schedule_bus_reset(fw_parent_device(bebob->unit)->card, false, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
snd_card_free(card);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -330,10 +323,6 @@ bebob_update(struct fw_unit *unit)
|
|||
if (bebob == NULL)
|
||||
return;
|
||||
|
||||
/* Postpone a workqueue for deferred registration. */
|
||||
if (!bebob->registered)
|
||||
snd_fw_schedule_registration(unit, &bebob->dwork);
|
||||
else
|
||||
fcp_bus_reset(bebob->unit);
|
||||
}
|
||||
|
||||
|
@ -344,20 +333,8 @@ static void bebob_remove(struct fw_unit *unit)
|
|||
if (bebob == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Confirm to stop the work for registration before the sound card is
|
||||
* going to be released. The work is not scheduled again because bus
|
||||
* reset handler is not called anymore.
|
||||
*/
|
||||
cancel_delayed_work_sync(&bebob->dwork);
|
||||
|
||||
if (bebob->registered) {
|
||||
// Block till all of ALSA character devices are released.
|
||||
snd_card_free(bebob->card);
|
||||
}
|
||||
|
||||
mutex_destroy(&bebob->mutex);
|
||||
fw_unit_put(bebob->unit);
|
||||
}
|
||||
|
||||
static const struct snd_bebob_rate_spec normal_rate_spec = {
|
||||
|
@ -370,6 +347,22 @@ static const struct snd_bebob_spec spec_normal = {
|
|||
.meter = NULL
|
||||
};
|
||||
|
||||
#define SPECIFIER_1394TA 0x00a02d
|
||||
|
||||
// The immediate entry for version in unit directory differs depending on models:
|
||||
// * 0x010001
|
||||
// * 0x014001
|
||||
#define SND_BEBOB_DEV_ENTRY(vendor, model, data) \
|
||||
{ \
|
||||
.match_flags = IEEE1394_MATCH_VENDOR_ID | \
|
||||
IEEE1394_MATCH_MODEL_ID | \
|
||||
IEEE1394_MATCH_SPECIFIER_ID, \
|
||||
.vendor_id = vendor, \
|
||||
.model_id = model, \
|
||||
.specifier_id = SPECIFIER_1394TA, \
|
||||
.driver_data = (kernel_ulong_t)data \
|
||||
}
|
||||
|
||||
static const struct ieee1394_device_id bebob_id_table[] = {
|
||||
/* Edirol, FA-66 */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_EDIROL, 0x00010049, &spec_normal),
|
||||
|
@ -386,9 +379,9 @@ static const struct ieee1394_device_id bebob_id_table[] = {
|
|||
/* BridgeCo, Audio5 */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010049, &spec_normal),
|
||||
/* Mackie, Onyx 1220/1620/1640 (Firewire I/O Card) */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MACKIE2, 0x00010065, &spec_normal),
|
||||
// Mackie, d.2 (Firewire option card) and d.2 Pro (the card is built-in).
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MACKIE1, 0x00010067, &spec_normal),
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MACKIE, 0x00010065, &spec_normal),
|
||||
// Mackie, d.2 (optional Firewire card with DM1000).
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MACKIE, 0x00010067, &spec_normal),
|
||||
/* Stanton, ScratchAmp */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_STANTON, 0x00000001, &spec_normal),
|
||||
/* Tascam, IF-FW DM */
|
||||
|
@ -410,17 +403,20 @@ static const struct ieee1394_device_id bebob_id_table[] = {
|
|||
SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x01eeee, &spec_normal),
|
||||
/* ESI, Quatafire610 */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_ESI, 0x00010064, &spec_normal),
|
||||
/* AcousticReality, eARMasterOne */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_ACOUSTIC, 0x00000002, &spec_normal),
|
||||
// AcousticReality, eARMasterOne. Terratec OEM.
|
||||
SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000002, &spec_normal),
|
||||
/* CME, MatrixKFW */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_CME, 0x00030000, &spec_normal),
|
||||
/* Phonic, Helix Board 12 MkII */
|
||||
// Phonic Helix Board 12 FireWire MkII.
|
||||
SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00050000, &spec_normal),
|
||||
/* Phonic, Helix Board 18 MkII */
|
||||
// Phonic Helix Board 18 FireWire MkII.
|
||||
SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00060000, &spec_normal),
|
||||
/* Phonic, Helix Board 24 MkII */
|
||||
// Phonic Helix Board 24 FireWire MkII.
|
||||
SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00070000, &spec_normal),
|
||||
/* Phonic, Helix Board 12 Universal/18 Universal/24 Universal */
|
||||
// Phonic FireFly 808 FireWire.
|
||||
SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00080000, &spec_normal),
|
||||
// Phonic FireFly 202, 302, 808 Universal.
|
||||
// Phinic Helix Board 12/18/24 FireWire, 12/18/24 Universal
|
||||
SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00000000, &spec_normal),
|
||||
/* Lynx, Aurora 8/16 (LT-FW) */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_LYNX, 0x00000001, &spec_normal),
|
||||
|
@ -447,45 +443,35 @@ static const struct ieee1394_device_id bebob_id_table[] = {
|
|||
/* Focusrite, SaffirePro 26 I/O */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x00000003, &saffirepro_26_spec),
|
||||
/* Focusrite, SaffirePro 10 I/O */
|
||||
{
|
||||
// The combination of vendor_id and model_id is the same as the
|
||||
// same as the one of Liquid Saffire 56.
|
||||
.match_flags = IEEE1394_MATCH_VENDOR_ID |
|
||||
IEEE1394_MATCH_MODEL_ID |
|
||||
IEEE1394_MATCH_SPECIFIER_ID |
|
||||
IEEE1394_MATCH_VERSION,
|
||||
.vendor_id = VEN_FOCUSRITE,
|
||||
.model_id = 0x000006,
|
||||
.specifier_id = 0x00a02d,
|
||||
.version = 0x010001,
|
||||
.driver_data = (kernel_ulong_t)&saffirepro_10_spec,
|
||||
},
|
||||
SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x000006, &saffirepro_10_spec),
|
||||
/* Focusrite, Saffire(no label and LE) */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, MODEL_FOCUSRITE_SAFFIRE_BOTH,
|
||||
&saffire_spec),
|
||||
/* M-Audio, Firewire 410 */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO2, 0x00010058, NULL), /* bootloader */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO2, 0x00010046, &maudio_fw410_spec),
|
||||
// M-Audio, Firewire 410. The vendor field is left as BridgeCo. AG.
|
||||
SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010058, NULL),
|
||||
SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010046, &maudio_fw410_spec),
|
||||
/* M-Audio, Firewire Audiophile */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_AUDIOPHILE_BOTH,
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, MODEL_MAUDIO_AUDIOPHILE_BOTH,
|
||||
&maudio_audiophile_spec),
|
||||
/* M-Audio, Firewire Solo */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x00010062, &maudio_solo_spec),
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, 0x00010062, &maudio_solo_spec),
|
||||
/* M-Audio, Ozonic */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x0000000a, &maudio_ozonic_spec),
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, 0x0000000a, &maudio_ozonic_spec),
|
||||
/* M-Audio NRV10 */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x00010081, &maudio_nrv10_spec),
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, 0x00010081, &maudio_nrv10_spec),
|
||||
/* M-Audio, ProFireLightbridge */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x000100a1, &spec_normal),
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, MODEL_MAUDIO_PROFIRELIGHTBRIDGE, &spec_normal),
|
||||
/* Firewire 1814 */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x00010070, NULL), /* bootloader */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_FW1814,
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, 0x00010070, NULL), /* bootloader */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, MODEL_MAUDIO_FW1814,
|
||||
&maudio_special_spec),
|
||||
/* M-Audio ProjectMix */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_PROJECTMIX,
|
||||
SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, MODEL_MAUDIO_PROJECTMIX,
|
||||
&maudio_special_spec),
|
||||
/* Digidesign Mbox 2 Pro */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_DIGIDESIGN, 0x0000a9, &spec_normal),
|
||||
// Toneweal FW66.
|
||||
SND_BEBOB_DEV_ENTRY(OUI_SHOUYO, 0x020002, &spec_normal),
|
||||
/* IDs are unknown but able to be supported */
|
||||
/* Apogee, Mini-ME Firewire */
|
||||
/* Apogee, Mini-DAC Firewire */
|
||||
|
@ -496,11 +482,6 @@ static const struct ieee1394_device_id bebob_id_table[] = {
|
|||
/* Infrasonic, Windy6 */
|
||||
/* Mackie, Digital X Bus x.200 */
|
||||
/* Mackie, Digital X Bus x.400 */
|
||||
/* Phonic, HB 12 */
|
||||
/* Phonic, HB 24 */
|
||||
/* Phonic, HB 18 */
|
||||
/* Phonic, FireFly 202 */
|
||||
/* Phonic, FireFly 302 */
|
||||
/* Rolf Spuler, Firewire Guitar */
|
||||
{}
|
||||
};
|
||||
|
|
|
@ -75,6 +75,11 @@ struct snd_bebob_spec {
|
|||
const struct snd_bebob_meter_spec *meter;
|
||||
};
|
||||
|
||||
enum snd_bebob_quirk {
|
||||
SND_BEBOB_QUIRK_INITIAL_DISCONTINUOUS_DBC = (1 << 0),
|
||||
SND_BEBOB_QUIRK_WRONG_DBC = (1 << 1),
|
||||
};
|
||||
|
||||
struct snd_bebob {
|
||||
struct snd_card *card;
|
||||
struct fw_unit *unit;
|
||||
|
@ -83,11 +88,8 @@ struct snd_bebob {
|
|||
struct mutex mutex;
|
||||
spinlock_t lock;
|
||||
|
||||
bool registered;
|
||||
struct delayed_work dwork;
|
||||
|
||||
const struct ieee1394_device_id *entry;
|
||||
const struct snd_bebob_spec *spec;
|
||||
unsigned int quirks; // Combination of snd_bebob_quirk enumerations.
|
||||
|
||||
unsigned int midi_input_ports;
|
||||
unsigned int midi_output_ports;
|
||||
|
@ -113,9 +115,6 @@ struct snd_bebob {
|
|||
/* for M-Audio special devices */
|
||||
void *maudio_special_quirk;
|
||||
|
||||
/* For BeBoB version quirk. */
|
||||
unsigned int version;
|
||||
|
||||
struct amdtp_domain domain;
|
||||
};
|
||||
|
||||
|
@ -254,13 +253,4 @@ extern const struct snd_bebob_spec maudio_special_spec;
|
|||
int snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814);
|
||||
int snd_bebob_maudio_load_firmware(struct fw_unit *unit);
|
||||
|
||||
#define SND_BEBOB_DEV_ENTRY(vendor, model, data) \
|
||||
{ \
|
||||
.match_flags = IEEE1394_MATCH_VENDOR_ID | \
|
||||
IEEE1394_MATCH_MODEL_ID, \
|
||||
.vendor_id = vendor, \
|
||||
.model_id = model, \
|
||||
.driver_data = (kernel_ulong_t)data \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
|
||||
#include "./bebob.h"
|
||||
|
||||
#define CALLBACK_TIMEOUT 2500
|
||||
#define FW_ISO_RESOURCE_DELAY 1000
|
||||
#define READY_TIMEOUT_MS 4000
|
||||
|
||||
/*
|
||||
* NOTE;
|
||||
|
@ -402,12 +401,6 @@ static void break_both_connections(struct snd_bebob *bebob)
|
|||
{
|
||||
cmp_connection_break(&bebob->in_conn);
|
||||
cmp_connection_break(&bebob->out_conn);
|
||||
|
||||
// These models seem to be in transition state for a longer time. When
|
||||
// accessing in the state, any transactions is corrupted. In the worst
|
||||
// case, the device is going to reboot.
|
||||
if (bebob->version < 2)
|
||||
msleep(600);
|
||||
}
|
||||
|
||||
static int start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream)
|
||||
|
@ -437,6 +430,7 @@ static int start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream)
|
|||
|
||||
static int init_stream(struct snd_bebob *bebob, struct amdtp_stream *stream)
|
||||
{
|
||||
unsigned int flags = CIP_BLOCKING;
|
||||
enum amdtp_stream_direction dir_stream;
|
||||
struct cmp_connection *conn;
|
||||
enum cmp_direction dir_conn;
|
||||
|
@ -452,32 +446,21 @@ static int init_stream(struct snd_bebob *bebob, struct amdtp_stream *stream)
|
|||
dir_conn = CMP_INPUT;
|
||||
}
|
||||
|
||||
if (stream == &bebob->tx_stream) {
|
||||
if (bebob->quirks & SND_BEBOB_QUIRK_WRONG_DBC)
|
||||
flags |= CIP_EMPTY_HAS_WRONG_DBC;
|
||||
}
|
||||
|
||||
err = cmp_connection_init(conn, bebob->unit, dir_conn, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = amdtp_am824_init(stream, bebob->unit, dir_stream, CIP_BLOCKING);
|
||||
err = amdtp_am824_init(stream, bebob->unit, dir_stream, flags);
|
||||
if (err < 0) {
|
||||
cmp_connection_destroy(conn);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (stream == &bebob->tx_stream) {
|
||||
// BeBoB v3 transfers packets with these qurks:
|
||||
// - In the beginning of streaming, the value of dbc is
|
||||
// incremented even if no data blocks are transferred.
|
||||
// - The value of dbc is reset suddenly.
|
||||
if (bebob->version > 2)
|
||||
bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC |
|
||||
CIP_SKIP_DBC_ZERO_CHECK;
|
||||
|
||||
// At high sampling rate, M-Audio special firmware transmits
|
||||
// empty packet with the value of dbc incremented by 8 but the
|
||||
// others are valid to IEC 61883-1.
|
||||
if (bebob->maudio_special_quirk)
|
||||
bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -624,9 +607,8 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob)
|
|||
|
||||
if (!amdtp_stream_running(&bebob->rx_stream)) {
|
||||
enum snd_bebob_clock_type src;
|
||||
struct amdtp_stream *master, *slave;
|
||||
unsigned int curr_rate;
|
||||
unsigned int ir_delay_cycle;
|
||||
unsigned int tx_init_skip_cycles;
|
||||
|
||||
if (bebob->maudio_special_quirk) {
|
||||
err = bebob->spec->rate->get(bebob, &curr_rate);
|
||||
|
@ -638,36 +620,28 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob)
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (src != SND_BEBOB_CLOCK_TYPE_SYT) {
|
||||
master = &bebob->tx_stream;
|
||||
slave = &bebob->rx_stream;
|
||||
} else {
|
||||
master = &bebob->rx_stream;
|
||||
slave = &bebob->tx_stream;
|
||||
}
|
||||
|
||||
err = start_stream(bebob, master);
|
||||
err = start_stream(bebob, &bebob->rx_stream);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = start_stream(bebob, slave);
|
||||
err = start_stream(bebob, &bebob->tx_stream);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
// The device postpones start of transmission mostly for 1 sec
|
||||
// after receives packets firstly. For safe, IR context starts
|
||||
// 0.4 sec (=3200 cycles) later to version 1 or 2 firmware,
|
||||
// 2.0 sec (=16000 cycles) for version 3 firmware. This is
|
||||
// within 2.5 sec (=CALLBACK_TIMEOUT).
|
||||
// Furthermore, some devices transfer isoc packets with
|
||||
// discontinuous counter in the beginning of packet streaming.
|
||||
// The delay has an effect to avoid detection of this
|
||||
// discontinuity.
|
||||
if (bebob->version < 2)
|
||||
ir_delay_cycle = 3200;
|
||||
if (!(bebob->quirks & SND_BEBOB_QUIRK_INITIAL_DISCONTINUOUS_DBC))
|
||||
tx_init_skip_cycles = 0;
|
||||
else
|
||||
ir_delay_cycle = 16000;
|
||||
err = amdtp_domain_start(&bebob->domain, ir_delay_cycle);
|
||||
tx_init_skip_cycles = 16000;
|
||||
|
||||
// MEMO: Some devices start packet transmission long enough after establishment of
|
||||
// CMP connection. In the early stage of packet streaming, any device transfers
|
||||
// NODATA packets. After several hundred cycles, it begins to multiplex event into
|
||||
// the packet with adequate value of syt field in CIP header. Some devices are
|
||||
// strictly to generate any discontinuity in the sequence of tx packet when they
|
||||
// receives inadequate sequence of value in syt field of CIP header. In the case,
|
||||
// the request to break CMP connection is often corrupted, then any transaction
|
||||
// results in unrecoverable error, sometimes generate bus-reset.
|
||||
err = amdtp_domain_start(&bebob->domain, tx_init_skip_cycles, true, false);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
|
@ -684,10 +658,9 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob)
|
|||
}
|
||||
}
|
||||
|
||||
if (!amdtp_stream_wait_callback(&bebob->rx_stream,
|
||||
CALLBACK_TIMEOUT) ||
|
||||
!amdtp_stream_wait_callback(&bebob->tx_stream,
|
||||
CALLBACK_TIMEOUT)) {
|
||||
// Some devices postpone start of transmission mostly for 1 sec after receives
|
||||
// packets firstly.
|
||||
if (!amdtp_domain_wait_ready(&bebob->domain, READY_TIMEOUT_MS)) {
|
||||
err = -ETIMEDOUT;
|
||||
goto error;
|
||||
}
|
||||
|
@ -883,6 +856,11 @@ static int detect_midi_ports(struct snd_bebob *bebob,
|
|||
err = avc_bridgeco_get_plug_ch_count(bebob->unit, addr, &ch_count);
|
||||
if (err < 0)
|
||||
break;
|
||||
// Yamaha GO44, GO46, Terratec Phase 24, Phase x24 reports 0 for the number of
|
||||
// channels in external output plug 3 (MIDI type) even if it has a pair of physical
|
||||
// MIDI jacks. As a workaround, assume it as one.
|
||||
if (ch_count == 0)
|
||||
ch_count = 1;
|
||||
*midi_ports += ch_count;
|
||||
}
|
||||
|
||||
|
@ -961,12 +939,12 @@ int snd_bebob_stream_discover(struct snd_bebob *bebob)
|
|||
if (err < 0)
|
||||
goto end;
|
||||
|
||||
err = detect_midi_ports(bebob, bebob->rx_stream_formations, addr, AVC_BRIDGECO_PLUG_DIR_IN,
|
||||
err = detect_midi_ports(bebob, bebob->tx_stream_formations, addr, AVC_BRIDGECO_PLUG_DIR_IN,
|
||||
plugs[2], &bebob->midi_input_ports);
|
||||
if (err < 0)
|
||||
goto end;
|
||||
|
||||
err = detect_midi_ports(bebob, bebob->tx_stream_formations, addr, AVC_BRIDGECO_PLUG_DIR_OUT,
|
||||
err = detect_midi_ports(bebob, bebob->rx_stream_formations, addr, AVC_BRIDGECO_PLUG_DIR_OUT,
|
||||
plugs[3], &bebob->midi_output_ports);
|
||||
if (err < 0)
|
||||
goto end;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue