forked from Minki/linux
sound updates for 5.6-rc1
As diffstat shows we've had again a lot of works done for this cycle: majority of changes are the continued componentization and code refactoring in ASoC, the tree-wide PCM API updates and cleanups and SOF updates while a few ASoC driver updates are seen, too. Here we go, some highlights: Core: - Finally y2038 support landed to ALSA ABI; some ioctls have been extended and lots of tricks were applied - Applying the new managed PCM buffer API to all drivers; the API itself was already merged in 5.5 - The already deprecated dimension support in ALSA control API is dropped completely now - Verification of ALSA control elements to catch API misuses ASoC: - Further code refactorings and moving things to the component level - Lots of updates and improvements on SOF / Intel drivers; now including common HDMI driver and SoundWire support - New driver support for Ingenic JZ4770, Mediatek MT6660, Qualcomm WCD934x and WSA881x, and Realtek RT700, RT711, RT715, RT1011, RT1015 and RT1308 HD-audio: - Improved ring-buffer communications using waitqueue - Drop the superfluous buffer preallocation on x86 Others: - Many code cleanups, mostly constifications over the whole tree - USB-audio: quirks for MOTU, Corsair Virtuoso, Line6 Helix - FireWire: code refactoring for oxfw and dice drivers -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAl4v7qsOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE9s7hAAoeqwRF+WffBaSMZKShDyFD5L7Z/YeXxh2b81 ErnVaSbXmWMhzgx7G7dj3bchkJWYsqAH//j3/AHYCF22slJdeTof0cpqaRgC0qEv eIj9ALu2Hh+z5jJHOlbpcYevtK89frY9zu4Su/5YAfZloUNLqAbl59SNOiS99/hu SR5rF0UCGngHf+pjiBpruQv2hahD5Y0a4rIGMaZB/GAa3p7eQ42koMmIEje/rjF0 bSpiYmmAwGJ62RlTUFCBNlj9w78eUfqrf8SHr91d7zNHUZpHR9GoFswmLGM0UtGS 5gIm+6UkBmTQcqgKhYsLl2eT/PSLVHpbYUeABjP62EqxWpksOl2/fQfrGuVT1Vjm QVoc345dKoKcNxVH1iuVg+/JYsmuPIpSmviFCKbH5IUlTWWyOYzWxZVdrZ/gIyXh fY/vDL2yOdR9mTnHYAfsJ8IB2ABY4pDahC6Dbvh5JoN/vmsND2Wv2l+HIIdLTarj R/n7+Rn6HLQmCJvgIWLniG6FxYxx4gqd/VVVaL7eJKYrcqvQq6VNZ/36Fgh3Ahdi HnKxyer3K7vC8CGM3cNH/Dq/iGTNgTcX6pnhVepl/elSZTMDrxZcWbbA0nPhBe8J 5SWGEstv11OBi/JL3vGdTmV4ceZ/yIBg9pIGg4j0rH3hKT83G7O5E++PixKCmmMc fZPCeAg= =PGgQ -----END PGP SIGNATURE----- Merge tag 'sound-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound updates from Takashi Iwai: "As the diffstat shows we've had again a lot of works done for this cycle: the majority of changes are the continued componentization and code refactoring in ASoC, the tree-wide PCM API updates and cleanups and SOF updates while a few ASoC driver updates are seen, too. Here we go, some highlights: Core: - Finally y2038 support landed to ALSA ABI; some ioctls have been extended and lots of tricks were applied - Applying the new managed PCM buffer API to all drivers; the API itself was already merged in 5.5 - The already deprecated dimension support in ALSA control API is dropped completely now - Verification of ALSA control elements to catch API misuses ASoC: - Further code refactorings and moving things to the component level - Lots of updates and improvements on SOF / Intel drivers; now including common HDMI driver and SoundWire support - New driver support for Ingenic JZ4770, Mediatek MT6660, Qualcomm WCD934x and WSA881x, and Realtek RT700, RT711, RT715, RT1011, RT1015 and RT1308 HD-audio: - Improved ring-buffer communications using waitqueue - Drop the superfluous buffer preallocation on x86 Others: - Many code cleanups, mostly constifications over the whole tree - USB-audio: quirks for MOTU, Corsair Virtuoso, Line6 Helix - FireWire: code refactoring for oxfw and dice drivers" * tag 'sound-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (638 commits) ALSA: usb-audio: add quirks for Line6 Helix devices fw>=2.82 ALSA: hda: Add Clevo W65_67SB the power_save blacklist ASoC: soc-core: remove null_snd_soc_ops ASoC: soc-pcm: add soc_rtd_trigger() ASoC: soc-pcm: add soc_rtd_hw_free() ASoC: soc-pcm: add soc_rtd_hw_params() ASoC: soc-pcm: add soc_rtd_prepare() ASoC: soc-pcm: add soc_rtd_shutdown() ASoC: soc-pcm: add soc_rtd_startup() ASoC: rt1015: add rt1015 amplifier driver ASoC: madera: Correct some kernel doc ASoC: topology: fix soc_tplg_fe_link_create() - link->dobj initialization order ASoC: Intel: skl_hda_dsp_common: Fix global-out-of-bounds bug ASoC: madera: Correct DMIC only input hook ups ALSA: cs46xx: fix spelling mistake "to" -> "too" ALSA: hda - Add docking station support for Lenovo Thinkpad T420s ASoC: Add MediaTek MT6660 Speaker Amp Driver ASoC: dt-bindings: rt5645: add suppliers ASoC: max98090: fix deadlock in max98090_dapm_put_enum_double() ASoC: dapm: add snd_soc_dapm_put_enum_double_locked ...
This commit is contained in:
commit
fb95aae6e6
@ -17,6 +17,9 @@ Required properties:
|
||||
* "arb" : memory ARB line (required)
|
||||
* "rst" : dedicated device reset line (optional)
|
||||
- #sound-dai-cells: must be 0.
|
||||
- amlogic,fifo-depth: The size of the controller's fifo in bytes. This
|
||||
is useful for determining certain configuration such
|
||||
as the flush threshold of the fifo
|
||||
|
||||
Example of FRDDR A on the A113 SoC:
|
||||
|
||||
@ -27,4 +30,5 @@ frddr_a: audio-controller@1c0 {
|
||||
interrupts = <GIC_SPI 88 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&clkc_audio AUD_CLKID_FRDDR_A>;
|
||||
resets = <&arb AXG_ARB_FRDDR_A>;
|
||||
fifo-depth = <512>;
|
||||
};
|
||||
|
@ -8,7 +8,12 @@ three substreams within totally 10 channels.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : Contains "fsl,imx35-asrc" or "fsl,imx53-asrc".
|
||||
- compatible : Compatible list, should contain one of the following
|
||||
compatibles:
|
||||
"fsl,imx35-asrc",
|
||||
"fsl,imx53-asrc",
|
||||
"fsl,imx8qm-asrc",
|
||||
"fsl,imx8qxp-asrc",
|
||||
|
||||
- reg : Offset and length of the register set for the device.
|
||||
|
||||
@ -35,6 +40,11 @@ Required properties:
|
||||
|
||||
- fsl,asrc-width : Defines a mutual sample width used by DPCM Back Ends.
|
||||
|
||||
- fsl,asrc-clk-map : Defines clock map used in driver. which is required
|
||||
by imx8qm/imx8qxp platform
|
||||
<0> - select the map for asrc0 in imx8qm/imx8qxp
|
||||
<1> - select the map for asrc1 in imx8qm/imx8qxp
|
||||
|
||||
Optional properties:
|
||||
|
||||
- big-endian : If this property is absent, the little endian mode
|
||||
|
@ -1,10 +1,16 @@
|
||||
GTM601 UMTS modem audio interface CODEC
|
||||
|
||||
This device has no configuration interface. Sample rate is fixed - 8kHz.
|
||||
This device has no configuration interface. The sample rate and channels are
|
||||
based on the compatible string
|
||||
"option,gtm601" = 8kHz mono
|
||||
"broadmobi,bm818" = 48KHz stereo
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "option,gtm601"
|
||||
- compatible : one of
|
||||
"option,gtm601"
|
||||
"broadmobi,bm818"
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
|
55
Documentation/devicetree/bindings/sound/ingenic,codec.yaml
Normal file
55
Documentation/devicetree/bindings/sound/ingenic,codec.yaml
Normal file
@ -0,0 +1,55 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/ingenic,codec.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Ingenic JZ47xx internal codec DT bindings
|
||||
|
||||
maintainers:
|
||||
- Paul Cercueil <paul@crapouillou.net>
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: '^audio-codec@.*'
|
||||
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: ingenic,jz4770-codec
|
||||
- const: ingenic,jz4725b-codec
|
||||
- const: ingenic,jz4740-codec
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: aic
|
||||
|
||||
'#sound-dai-cells':
|
||||
const: 0
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#sound-dai-cells'
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/jz4740-cgu.h>
|
||||
codec: audio-codec@10020080 {
|
||||
compatible = "ingenic,jz4740-codec";
|
||||
reg = <0x10020080 0x8>;
|
||||
#sound-dai-cells = <0>;
|
||||
clocks = <&cgu JZ4740_CLK_AIC>;
|
||||
clock-names = "aic";
|
||||
};
|
||||
|
||||
...
|
@ -1,20 +0,0 @@
|
||||
Ingenic JZ4725B codec controller
|
||||
|
||||
Required properties:
|
||||
- compatible : "ingenic,jz4725b-codec"
|
||||
- reg : codec registers location and length
|
||||
- clocks : phandle to the AIC clock.
|
||||
- clock-names: must be set to "aic".
|
||||
- #sound-dai-cells: Must be set to 0.
|
||||
|
||||
Example:
|
||||
|
||||
codec: audio-codec@100200a4 {
|
||||
compatible = "ingenic,jz4725b-codec";
|
||||
reg = <0x100200a4 0x8>;
|
||||
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
clocks = <&cgu JZ4725B_CLK_AIC>;
|
||||
clock-names = "aic";
|
||||
};
|
@ -1,20 +0,0 @@
|
||||
Ingenic JZ4740 codec controller
|
||||
|
||||
Required properties:
|
||||
- compatible : "ingenic,jz4740-codec"
|
||||
- reg : codec registers location and length
|
||||
- clocks : phandle to the AIC clock.
|
||||
- clock-names: must be set to "aic".
|
||||
- #sound-dai-cells: Must be set to 0.
|
||||
|
||||
Example:
|
||||
|
||||
codec: audio-codec@10020080 {
|
||||
compatible = "ingenic,jz4740-codec";
|
||||
reg = <0x10020080 0x8>;
|
||||
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
clocks = <&cgu JZ4740_CLK_AIC>;
|
||||
clock-names = "aic";
|
||||
};
|
@ -5,7 +5,10 @@ This binding describes the SDM845 sound card, which uses qdsp for audio.
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: must be "qcom,sdm845-sndcard"
|
||||
Definition: must be one of this
|
||||
"qcom,sdm845-sndcard"
|
||||
"qcom,db845c-sndcard"
|
||||
"lenovo,yoga-c630-sndcard"
|
||||
|
||||
- audio-routing:
|
||||
Usage: Optional
|
||||
|
175
Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml
Normal file
175
Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml
Normal file
@ -0,0 +1,175 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/qcom,wcd934x.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Bindings for Qualcomm WCD9340/WCD9341 Audio Codec
|
||||
|
||||
maintainers:
|
||||
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
|
||||
description: |
|
||||
Qualcomm WCD9340/WCD9341 Codec is a standalone Hi-Fi audio codec IC.
|
||||
It has in-built Soundwire controller, pin controller, interrupt mux and
|
||||
supports both I2S/I2C and SLIMbus audio interfaces.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: slim217,250
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: GPIO spec for reset line to use
|
||||
maxItems: 1
|
||||
|
||||
slim-ifc-dev: true
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
const: extclk
|
||||
|
||||
vdd-buck-supply:
|
||||
description: A reference to the 1.8V buck supply
|
||||
|
||||
vdd-buck-sido-supply:
|
||||
description: A reference to the 1.8V SIDO buck supply
|
||||
|
||||
vdd-rx-supply:
|
||||
description: A reference to the 1.8V rx supply
|
||||
|
||||
vdd-tx-supply:
|
||||
description: A reference to the 1.8V tx supply
|
||||
|
||||
vdd-vbat-supply:
|
||||
description: A reference to the vbat supply
|
||||
|
||||
vdd-io-supply:
|
||||
description: A reference to the 1.8V I/O supply
|
||||
|
||||
vdd-micbias-supply:
|
||||
description: A reference to the micbias supply
|
||||
|
||||
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
|
||||
|
||||
clock-output-names:
|
||||
const: mclk
|
||||
|
||||
clock-frequency:
|
||||
description: Clock frequency of output clk in Hz
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
'#interrupt-cells':
|
||||
const: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 0
|
||||
|
||||
'#sound-dai-cells':
|
||||
const: 1
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
gpio@42:
|
||||
type: object
|
||||
allOf:
|
||||
- $ref: ../gpio/qcom,wcd934x-gpio.yaml#
|
||||
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+$":
|
||||
type: object
|
||||
description: |
|
||||
WCD934x subnode for each slave devices. Bindings of each subnodes
|
||||
depends on the specific driver providing the functionality and
|
||||
documented in their respective bindings.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reset-gpios
|
||||
- slim-ifc-dev
|
||||
- interrupts
|
||||
- interrupt-controller
|
||||
- clock-frequency
|
||||
- clock-output-names
|
||||
- qcom,micbias1-microvolt
|
||||
- qcom,micbias2-microvolt
|
||||
- qcom,micbias3-microvolt
|
||||
- qcom,micbias4-microvolt
|
||||
- "#interrupt-cells"
|
||||
- "#clock-cells"
|
||||
- "#sound-dai-cells"
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
|
||||
examples:
|
||||
- |
|
||||
codec@1,0{
|
||||
compatible = "slim217,250";
|
||||
reg = <1 0>;
|
||||
reset-gpios = <&tlmm 64 0>;
|
||||
slim-ifc-dev = <&wcd9340_ifd>;
|
||||
#sound-dai-cells = <1>;
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <54 4>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <9600000>;
|
||||
clock-output-names = "mclk";
|
||||
qcom,micbias1-microvolt = <1800000>;
|
||||
qcom,micbias2-microvolt = <1800000>;
|
||||
qcom,micbias3-microvolt = <1800000>;
|
||||
qcom,micbias4-microvolt = <1800000>;
|
||||
clock-names = "extclk";
|
||||
clocks = <&rpmhcc 2>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
gpio@42 {
|
||||
compatible = "qcom,wcd9340-gpio";
|
||||
reg = <0x42 0x2>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
68
Documentation/devicetree/bindings/sound/qcom,wsa881x.yaml
Normal file
68
Documentation/devicetree/bindings/sound/qcom,wsa881x.yaml
Normal file
@ -0,0 +1,68 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/qcom,wsa881x.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Bindings for Qualcomm WSA8810/WSA8815 Class-D Smart Speaker Amplifier
|
||||
|
||||
maintainers:
|
||||
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
|
||||
description: |
|
||||
WSA8810 is a class-D smart speaker amplifier and WSA8815
|
||||
is a high-output power class-D smart speaker amplifier.
|
||||
Their primary operating mode uses a SoundWire digital audio
|
||||
interface. This binding is for SoundWire interface.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sdw10217201000
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
powerdown-gpios:
|
||||
description: GPIO spec for Powerdown/Shutdown line to use
|
||||
maxItems: 1
|
||||
|
||||
'#thermal-sensor-cells':
|
||||
const: 0
|
||||
|
||||
'#sound-dai-cells':
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- powerdown-gpios
|
||||
- "#thermal-sensor-cells"
|
||||
- "#sound-dai-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
soundwire@c2d0000 {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x0c2d0000 0x2000>;
|
||||
|
||||
speaker@0,1 {
|
||||
compatible = "sdw10217201000";
|
||||
reg = <0 1>;
|
||||
powerdown-gpios = <&wcdpinctrl 2 0>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
|
||||
speaker@0,2 {
|
||||
compatible = "sdw10217201000";
|
||||
reg = <0 2>;
|
||||
powerdown-gpios = <&wcdpinctrl 2 0>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
17
Documentation/devicetree/bindings/sound/rt1015.txt
Normal file
17
Documentation/devicetree/bindings/sound/rt1015.txt
Normal file
@ -0,0 +1,17 @@
|
||||
RT1015 Mono Class D Audio Amplifier
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "realtek,rt1015".
|
||||
|
||||
- reg : The I2C address of the device.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
rt1015: codec@28 {
|
||||
compatible = "realtek,rt1015";
|
||||
reg = <0x28>;
|
||||
};
|
@ -10,6 +10,10 @@ Required properties:
|
||||
|
||||
- interrupts : The CODEC's interrupt output.
|
||||
|
||||
- avdd-supply: Power supply for AVDD, providing 1.8V.
|
||||
|
||||
- cpvdd-supply: Power supply for CPVDD, providing 3.5V.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- hp-detect-gpios:
|
||||
|
@ -495,7 +495,8 @@ Module for C-Media CMI8338/8738/8768/8770 PCI sound cards.
|
||||
mpu_port
|
||||
port address of MIDI interface (8338 only):
|
||||
0x300,0x310,0x320,0x330 = legacy port,
|
||||
0 = disable (default)
|
||||
1 = integrated PCI port (default on 8738),
|
||||
0 = disable
|
||||
fm_port
|
||||
port address of OPL-3 FM synthesizer (8x38 only):
|
||||
0x388 = legacy port,
|
||||
|
@ -259,7 +259,7 @@ to details explained in the following section.
|
||||
{
|
||||
struct mychip *chip;
|
||||
int err;
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_free = snd_mychip_dev_free,
|
||||
};
|
||||
|
||||
@ -675,7 +675,7 @@ low-level device with a specified ``ops``,
|
||||
|
||||
::
|
||||
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_free = snd_mychip_dev_free,
|
||||
};
|
||||
....
|
||||
@ -761,7 +761,7 @@ destructor and PCI entries. Example code is shown first, below.
|
||||
{
|
||||
struct mychip *chip;
|
||||
int err;
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_free = snd_mychip_dev_free,
|
||||
};
|
||||
|
||||
@ -3912,7 +3912,7 @@ For a raw-data proc-file, set the attributes as follows:
|
||||
|
||||
::
|
||||
|
||||
static struct snd_info_entry_ops my_file_io_ops = {
|
||||
static const struct snd_info_entry_ops my_file_io_ops = {
|
||||
.read = my_file_io_read,
|
||||
};
|
||||
|
||||
|
@ -529,17 +529,24 @@ intel_pdi_alh_configure(struct sdw_intel *sdw, struct sdw_cdns_pdi *pdi)
|
||||
intel_writel(alh, SDW_ALH_STRMZCFG(pdi->intel_alh_id), conf);
|
||||
}
|
||||
|
||||
static int intel_config_stream(struct sdw_intel *sdw,
|
||||
static int intel_params_stream(struct sdw_intel *sdw,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai,
|
||||
struct snd_pcm_hw_params *hw_params, int link_id)
|
||||
struct snd_pcm_hw_params *hw_params,
|
||||
int link_id, int alh_stream_id)
|
||||
{
|
||||
struct sdw_intel_link_res *res = sdw->res;
|
||||
struct sdw_intel_stream_params_data params_data;
|
||||
|
||||
if (res->ops && res->ops->config_stream && res->arg)
|
||||
return res->ops->config_stream(res->arg,
|
||||
substream, dai, hw_params, link_id);
|
||||
params_data.substream = substream;
|
||||
params_data.dai = dai;
|
||||
params_data.hw_params = hw_params;
|
||||
params_data.link_id = link_id;
|
||||
params_data.alh_stream_id = alh_stream_id;
|
||||
|
||||
if (res->ops && res->ops->params_stream && res->dev)
|
||||
return res->ops->params_stream(res->dev,
|
||||
¶ms_data);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -654,7 +661,8 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
|
||||
/* Inform DSP about PDI stream number */
|
||||
ret = intel_config_stream(sdw, substream, dai, params,
|
||||
ret = intel_params_stream(sdw, substream, dai, params,
|
||||
sdw->instance,
|
||||
pdi->intel_alh_id);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
@ -5,23 +5,26 @@
|
||||
#define __SDW_INTEL_LOCAL_H
|
||||
|
||||
/**
|
||||
* struct sdw_intel_link_res - Soundwire link resources
|
||||
* struct sdw_intel_link_res - Soundwire Intel link resource structure,
|
||||
* typically populated by the controller driver.
|
||||
* @pdev: platform_device
|
||||
* @mmio_base: mmio base of SoundWire registers
|
||||
* @registers: Link IO registers base
|
||||
* @shim: Audio shim pointer
|
||||
* @alh: ALH (Audio Link Hub) pointer
|
||||
* @irq: Interrupt line
|
||||
* @ops: Shim callback ops
|
||||
* @arg: Shim callback ops argument
|
||||
*
|
||||
* This is set as pdata for each link instance.
|
||||
* @dev: device implementing hw_params and free callbacks
|
||||
*/
|
||||
struct sdw_intel_link_res {
|
||||
struct platform_device *pdev;
|
||||
void __iomem *mmio_base; /* not strictly needed, useful for debug */
|
||||
void __iomem *registers;
|
||||
void __iomem *shim;
|
||||
void __iomem *alh;
|
||||
int irq;
|
||||
const struct sdw_intel_ops *ops;
|
||||
void *arg;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
#endif /* __SDW_INTEL_LOCAL_H */
|
||||
|
@ -27,19 +27,9 @@ static int link_mask;
|
||||
module_param_named(sdw_link_mask, link_mask, int, 0444);
|
||||
MODULE_PARM_DESC(sdw_link_mask, "Intel link mask (one bit per link)");
|
||||
|
||||
struct sdw_link_data {
|
||||
struct sdw_intel_link_res res;
|
||||
struct platform_device *pdev;
|
||||
};
|
||||
|
||||
struct sdw_intel_ctx {
|
||||
int count;
|
||||
struct sdw_link_data *links;
|
||||
};
|
||||
|
||||
static int sdw_intel_cleanup_pdev(struct sdw_intel_ctx *ctx)
|
||||
{
|
||||
struct sdw_link_data *link = ctx->links;
|
||||
struct sdw_intel_link_res *link = ctx->links;
|
||||
int i;
|
||||
|
||||
if (!link)
|
||||
@ -62,7 +52,7 @@ static struct sdw_intel_ctx
|
||||
{
|
||||
struct platform_device_info pdevinfo;
|
||||
struct platform_device *pdev;
|
||||
struct sdw_link_data *link;
|
||||
struct sdw_intel_link_res *link;
|
||||
struct sdw_intel_ctx *ctx;
|
||||
struct acpi_device *adev;
|
||||
int ret, i;
|
||||
@ -123,14 +113,13 @@ static struct sdw_intel_ctx
|
||||
continue;
|
||||
}
|
||||
|
||||
link->res.irq = res->irq;
|
||||
link->res.registers = res->mmio_base + SDW_LINK_BASE
|
||||
link->registers = res->mmio_base + SDW_LINK_BASE
|
||||
+ (SDW_LINK_SIZE * i);
|
||||
link->res.shim = res->mmio_base + SDW_SHIM_BASE;
|
||||
link->res.alh = res->mmio_base + SDW_ALH_BASE;
|
||||
link->shim = res->mmio_base + SDW_SHIM_BASE;
|
||||
link->alh = res->mmio_base + SDW_ALH_BASE;
|
||||
|
||||
link->res.ops = res->ops;
|
||||
link->res.arg = res->arg;
|
||||
link->ops = res->ops;
|
||||
link->dev = res->dev;
|
||||
|
||||
memset(&pdevinfo, 0, sizeof(pdevinfo));
|
||||
|
||||
@ -138,8 +127,6 @@ static struct sdw_intel_ctx
|
||||
pdevinfo.name = "int-sdw";
|
||||
pdevinfo.id = i;
|
||||
pdevinfo.fwnode = acpi_fwnode_handle(adev);
|
||||
pdevinfo.data = &link->res;
|
||||
pdevinfo.size_data = sizeof(link->res);
|
||||
|
||||
pdev = platform_device_register_full(&pdevinfo);
|
||||
if (IS_ERR(pdev)) {
|
||||
@ -216,7 +203,6 @@ void *sdw_intel_init(acpi_handle *parent_handle, struct sdw_intel_res *res)
|
||||
|
||||
return sdw_intel_add_controller(res);
|
||||
}
|
||||
EXPORT_SYMBOL(sdw_intel_init);
|
||||
|
||||
/**
|
||||
* sdw_intel_exit() - SoundWire Intel exit
|
||||
@ -224,10 +210,8 @@ EXPORT_SYMBOL(sdw_intel_init);
|
||||
*
|
||||
* Delete the controller instances created and cleanup
|
||||
*/
|
||||
void sdw_intel_exit(void *arg)
|
||||
void sdw_intel_exit(struct sdw_intel_ctx *ctx)
|
||||
{
|
||||
struct sdw_intel_ctx *ctx = arg;
|
||||
|
||||
sdw_intel_cleanup_pdev(ctx);
|
||||
kfree(ctx);
|
||||
}
|
||||
|
@ -547,6 +547,20 @@ struct sdw_slave_ops {
|
||||
* @node: node for bus list
|
||||
* @port_ready: Port ready completion flag for each Slave port
|
||||
* @dev_num: Device Number assigned by Bus
|
||||
* @probed: boolean tracking driver state
|
||||
* @probe_complete: completion utility to control potential races
|
||||
* on startup between driver probe/initialization and SoundWire
|
||||
* Slave state changes/implementation-defined interrupts
|
||||
* @enumeration_complete: completion utility to control potential races
|
||||
* on startup between device enumeration and read/write access to the
|
||||
* Slave device
|
||||
* @initialization_complete: completion utility to control potential races
|
||||
* on startup between device enumeration and settings being restored
|
||||
* @unattach_request: mask field to keep track why the Slave re-attached and
|
||||
* was re-initialized. This is useful to deal with potential race conditions
|
||||
* between the Master suspending and the codec resuming, and make sure that
|
||||
* when the Master triggered a reset the Slave is properly enumerated and
|
||||
* initialized
|
||||
*/
|
||||
struct sdw_slave {
|
||||
struct sdw_slave_id id;
|
||||
@ -561,6 +575,11 @@ struct sdw_slave {
|
||||
struct list_head node;
|
||||
struct completion *port_ready;
|
||||
u16 dev_num;
|
||||
bool probed;
|
||||
struct completion probe_complete;
|
||||
struct completion enumeration_complete;
|
||||
struct completion initialization_complete;
|
||||
u32 unattach_request;
|
||||
};
|
||||
|
||||
#define dev_to_sdw_dev(_dev) container_of(_dev, struct sdw_slave, dev)
|
||||
|
@ -4,36 +4,174 @@
|
||||
#ifndef __SDW_INTEL_H
|
||||
#define __SDW_INTEL_H
|
||||
|
||||
#include <linux/irqreturn.h>
|
||||
|
||||
/**
|
||||
* struct sdw_intel_ops: Intel audio driver callback ops
|
||||
*
|
||||
* @config_stream: configure the stream with the hw_params
|
||||
* the first argument containing the context is mandatory
|
||||
* struct sdw_intel_stream_params_data: configuration passed during
|
||||
* the @params_stream callback, e.g. for interaction with DSP
|
||||
* firmware.
|
||||
*/
|
||||
struct sdw_intel_ops {
|
||||
int (*config_stream)(void *arg, void *substream,
|
||||
void *dai, void *hw_params, int stream_num);
|
||||
struct sdw_intel_stream_params_data {
|
||||
struct snd_pcm_substream *substream;
|
||||
struct snd_soc_dai *dai;
|
||||
struct snd_pcm_hw_params *hw_params;
|
||||
int link_id;
|
||||
int alh_stream_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sdw_intel_res - Soundwire Intel resource structure
|
||||
* struct sdw_intel_stream_free_data: configuration passed during
|
||||
* the @free_stream callback, e.g. for interaction with DSP
|
||||
* firmware.
|
||||
*/
|
||||
struct sdw_intel_stream_free_data {
|
||||
struct snd_pcm_substream *substream;
|
||||
struct snd_soc_dai *dai;
|
||||
int link_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sdw_intel_ops: Intel audio driver callback ops
|
||||
*
|
||||
*/
|
||||
struct sdw_intel_ops {
|
||||
int (*params_stream)(struct device *dev,
|
||||
struct sdw_intel_stream_params_data *params_data);
|
||||
int (*free_stream)(struct device *dev,
|
||||
struct sdw_intel_stream_free_data *free_data);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sdw_intel_acpi_info - Soundwire Intel information found in ACPI tables
|
||||
* @handle: ACPI controller handle
|
||||
* @count: link count found with "sdw-master-count" property
|
||||
* @link_mask: bit-wise mask listing links enabled by BIOS menu
|
||||
*
|
||||
* this structure could be expanded to e.g. provide all the _ADR
|
||||
* information in case the link_mask is not sufficient to identify
|
||||
* platform capabilities.
|
||||
*/
|
||||
struct sdw_intel_acpi_info {
|
||||
acpi_handle handle;
|
||||
int count;
|
||||
u32 link_mask;
|
||||
};
|
||||
|
||||
struct sdw_intel_link_res;
|
||||
|
||||
/* Intel clock-stop/pm_runtime quirk definitions */
|
||||
|
||||
/*
|
||||
* Force the clock to remain on during pm_runtime suspend. This might
|
||||
* be needed if Slave devices do not have an alternate clock source or
|
||||
* if the latency requirements are very strict.
|
||||
*/
|
||||
#define SDW_INTEL_CLK_STOP_NOT_ALLOWED BIT(0)
|
||||
|
||||
/*
|
||||
* Stop the bus during pm_runtime suspend. If set, a complete bus
|
||||
* reset and re-enumeration will be performed when the bus
|
||||
* restarts. This mode shall not be used if Slave devices can generate
|
||||
* in-band wakes.
|
||||
*/
|
||||
#define SDW_INTEL_CLK_STOP_TEARDOWN BIT(1)
|
||||
|
||||
/*
|
||||
* Stop the bus during pm_suspend if Slaves are not wake capable
|
||||
* (e.g. speaker amplifiers). The clock-stop mode is typically
|
||||
* slightly higher power than when the IP is completely powered-off.
|
||||
*/
|
||||
#define SDW_INTEL_CLK_STOP_WAKE_CAPABLE_ONLY BIT(2)
|
||||
|
||||
/*
|
||||
* Require a bus reset (and complete re-enumeration) when exiting
|
||||
* clock stop modes. This may be needed if the controller power was
|
||||
* turned off and all context lost. This quirk shall not be used if a
|
||||
* Slave device needs to remain enumerated and keep its context,
|
||||
* e.g. to provide the reasons for the wake, report acoustic events or
|
||||
* pass a history buffer.
|
||||
*/
|
||||
#define SDW_INTEL_CLK_STOP_BUS_RESET BIT(3)
|
||||
|
||||
/**
|
||||
* struct sdw_intel_ctx - context allocated by the controller
|
||||
* driver probe
|
||||
* @count: link count
|
||||
* @mmio_base: mmio base of SoundWire registers, only used to check
|
||||
* hardware capabilities after all power dependencies are settled.
|
||||
* @link_mask: bit-wise mask listing SoundWire links reported by the
|
||||
* Controller
|
||||
* @handle: ACPI parent handle
|
||||
* @links: information for each link (controller-specific and kept
|
||||
* opaque here)
|
||||
* @link_list: list to handle interrupts across all links
|
||||
* @shim_lock: mutex to handle concurrent rmw access to shared SHIM registers.
|
||||
*/
|
||||
struct sdw_intel_ctx {
|
||||
int count;
|
||||
void __iomem *mmio_base;
|
||||
u32 link_mask;
|
||||
acpi_handle handle;
|
||||
struct sdw_intel_link_res *links;
|
||||
struct list_head link_list;
|
||||
struct mutex shim_lock; /* lock for access to shared SHIM registers */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sdw_intel_res - Soundwire Intel global resource structure,
|
||||
* typically populated by the DSP driver
|
||||
*
|
||||
* @count: link count
|
||||
* @mmio_base: mmio base of SoundWire registers
|
||||
* @irq: interrupt number
|
||||
* @handle: ACPI parent handle
|
||||
* @parent: parent device
|
||||
* @ops: callback ops
|
||||
* @arg: callback arg
|
||||
* @dev: device implementing hwparams and free callbacks
|
||||
* @link_mask: bit-wise mask listing links selected by the DSP driver
|
||||
* This mask may be a subset of the one reported by the controller since
|
||||
* machine-specific quirks are handled in the DSP driver.
|
||||
* @clock_stop_quirks: mask array of possible behaviors requested by the
|
||||
* DSP driver. The quirks are common for all links for now.
|
||||
*/
|
||||
struct sdw_intel_res {
|
||||
int count;
|
||||
void __iomem *mmio_base;
|
||||
int irq;
|
||||
acpi_handle handle;
|
||||
struct device *parent;
|
||||
const struct sdw_intel_ops *ops;
|
||||
void *arg;
|
||||
struct device *dev;
|
||||
u32 link_mask;
|
||||
u32 clock_stop_quirks;
|
||||
};
|
||||
|
||||
void *sdw_intel_init(acpi_handle *parent_handle, struct sdw_intel_res *res);
|
||||
void sdw_intel_exit(void *arg);
|
||||
/*
|
||||
* On Intel platforms, the SoundWire IP has dependencies on power
|
||||
* rails shared with the DSP, and the initialization steps are split
|
||||
* in three. First an ACPI scan to check what the firmware describes
|
||||
* in DSDT tables, then an allocation step (with no hardware
|
||||
* configuration but with all the relevant devices created) and last
|
||||
* the actual hardware configuration. The final stage is a global
|
||||
* interrupt enable which is controlled by the DSP driver. Splitting
|
||||
* these phases helps simplify the boot flow and make early decisions
|
||||
* on e.g. which machine driver to select (I2S mode, HDaudio or
|
||||
* SoundWire).
|
||||
*/
|
||||
int sdw_intel_acpi_scan(acpi_handle *parent_handle,
|
||||
struct sdw_intel_acpi_info *info);
|
||||
|
||||
void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx);
|
||||
|
||||
struct sdw_intel_ctx *
|
||||
sdw_intel_probe(struct sdw_intel_res *res);
|
||||
|
||||
int sdw_intel_startup(struct sdw_intel_ctx *ctx);
|
||||
|
||||
void sdw_intel_exit(struct sdw_intel_ctx *ctx);
|
||||
|
||||
void sdw_intel_enable_irq(void __iomem *mmio_base, bool enable);
|
||||
|
||||
irqreturn_t sdw_intel_thread(int irq, void *dev_id);
|
||||
|
||||
#endif
|
||||
|
@ -197,7 +197,7 @@ struct snd_ac97_bus_ops {
|
||||
|
||||
struct snd_ac97_bus {
|
||||
/* -- lowlevel (hardware) driver specific -- */
|
||||
struct snd_ac97_bus_ops *ops;
|
||||
const struct snd_ac97_bus_ops *ops;
|
||||
void *private_data;
|
||||
void (*private_free) (struct snd_ac97_bus *bus);
|
||||
/* --- */
|
||||
@ -310,7 +310,8 @@ static inline int ac97_can_spdif(struct snd_ac97 * ac97)
|
||||
|
||||
/* functions */
|
||||
/* create new AC97 bus */
|
||||
int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops,
|
||||
int snd_ac97_bus(struct snd_card *card, int num,
|
||||
const struct snd_ac97_bus_ops *ops,
|
||||
void *private_data, struct snd_ac97_bus **rbus);
|
||||
/* create mixer controls */
|
||||
int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template,
|
||||
|
@ -22,6 +22,16 @@ typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol,
|
||||
unsigned int size,
|
||||
unsigned int __user *tlv);
|
||||
|
||||
/* internal flag for skipping validations */
|
||||
#ifdef CONFIG_SND_CTL_VALIDATION
|
||||
#define SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK (1 << 27)
|
||||
#define snd_ctl_skip_validation(info) \
|
||||
((info)->access & SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK)
|
||||
#else
|
||||
#define SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK 0
|
||||
#define snd_ctl_skip_validation(info) true
|
||||
#endif
|
||||
|
||||
enum {
|
||||
SNDRV_CTL_TLV_OP_READ = 0,
|
||||
SNDRV_CTL_TLV_OP_WRITE = 1,
|
||||
|
@ -69,7 +69,7 @@ struct snd_device {
|
||||
enum snd_device_state state; /* state of the device */
|
||||
enum snd_device_type type; /* device type */
|
||||
void *device_data; /* device structure */
|
||||
struct snd_device_ops *ops; /* operations */
|
||||
const struct snd_device_ops *ops; /* operations */
|
||||
};
|
||||
|
||||
#define snd_device(n) list_entry(n, struct snd_device, list)
|
||||
@ -120,6 +120,9 @@ struct snd_card {
|
||||
int sync_irq; /* assigned irq, used for PCM sync */
|
||||
wait_queue_head_t remove_sleep;
|
||||
|
||||
size_t total_pcm_alloc_bytes; /* total amount of allocated buffers */
|
||||
struct mutex memory_mutex; /* protection for the above */
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
unsigned int power_state; /* power state */
|
||||
wait_queue_head_t power_sleep;
|
||||
@ -256,7 +259,7 @@ static inline void snd_card_unref(struct snd_card *card)
|
||||
/* device.c */
|
||||
|
||||
int snd_device_new(struct snd_card *card, enum snd_device_type type,
|
||||
void *device_data, struct snd_device_ops *ops);
|
||||
void *device_data, const struct snd_device_ops *ops);
|
||||
int snd_device_register(struct snd_card *card, void *device_data);
|
||||
int snd_device_register_all(struct snd_card *card);
|
||||
void snd_device_disconnect(struct snd_card *card, void *device_data);
|
||||
|
@ -51,7 +51,6 @@ struct hda_bus {
|
||||
DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES);
|
||||
|
||||
/* misc op flags */
|
||||
unsigned int needs_damn_long_delay :1;
|
||||
unsigned int allow_bus_reset:1; /* allow bus reset at fatal error */
|
||||
/* status for codec/controller */
|
||||
unsigned int shutdown :1; /* being unloaded */
|
||||
|
@ -24,6 +24,9 @@ int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg,
|
||||
unsigned int val);
|
||||
int snd_hdac_regmap_update_raw(struct hdac_device *codec, unsigned int reg,
|
||||
unsigned int mask, unsigned int val);
|
||||
int snd_hdac_regmap_update_raw_once(struct hdac_device *codec, unsigned int reg,
|
||||
unsigned int mask, unsigned int val);
|
||||
void snd_hdac_regmap_sync(struct hdac_device *codec);
|
||||
|
||||
/**
|
||||
* snd_hdac_regmap_encode_verb - encode the verb to a pseudo register
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/timecounter.h>
|
||||
#include <sound/core.h>
|
||||
@ -86,6 +87,7 @@ struct hdac_device {
|
||||
|
||||
/* regmap */
|
||||
struct regmap *regmap;
|
||||
struct mutex regmap_lock;
|
||||
struct snd_array vendor_verbs;
|
||||
bool lazy_cache:1; /* don't wake up for writes */
|
||||
bool caps_overwriting:1; /* caps overwrite being in process */
|
||||
@ -317,6 +319,7 @@ struct hdac_bus {
|
||||
struct hdac_rb corb;
|
||||
struct hdac_rb rirb;
|
||||
unsigned int last_cmd[HDA_MAX_CODECS]; /* last sent command */
|
||||
wait_queue_head_t rirb_wq;
|
||||
|
||||
/* CORB/RIRB and position buffers */
|
||||
struct snd_dma_buffer rb;
|
||||
@ -330,6 +333,7 @@ struct hdac_bus {
|
||||
bool chip_init:1; /* h/w initialized */
|
||||
|
||||
/* behavior flags */
|
||||
bool aligned_mmio:1; /* aligned MMIO access */
|
||||
bool sync_write:1; /* sync after verb write */
|
||||
bool use_posbuf:1; /* use position buffer */
|
||||
bool snoop:1; /* enable snooping */
|
||||
@ -337,6 +341,7 @@ struct hdac_bus {
|
||||
bool reverse_assign:1; /* assign devices in reverse order */
|
||||
bool corbrp_self_clear:1; /* CORBRP clears itself after reset */
|
||||
bool polling_mode:1;
|
||||
bool needs_damn_long_delay:1;
|
||||
|
||||
int poll_count;
|
||||
|
||||
@ -405,34 +410,61 @@ void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus);
|
||||
unsigned int snd_hdac_aligned_read(void __iomem *addr, unsigned int mask);
|
||||
void snd_hdac_aligned_write(unsigned int val, void __iomem *addr,
|
||||
unsigned int mask);
|
||||
#define snd_hdac_reg_writeb(v, addr) snd_hdac_aligned_write(v, addr, 0xff)
|
||||
#define snd_hdac_reg_writew(v, addr) snd_hdac_aligned_write(v, addr, 0xffff)
|
||||
#define snd_hdac_reg_readb(addr) snd_hdac_aligned_read(addr, 0xff)
|
||||
#define snd_hdac_reg_readw(addr) snd_hdac_aligned_read(addr, 0xffff)
|
||||
#else /* CONFIG_SND_HDA_ALIGNED_MMIO */
|
||||
#define snd_hdac_reg_writeb(val, addr) writeb(val, addr)
|
||||
#define snd_hdac_reg_writew(val, addr) writew(val, addr)
|
||||
#define snd_hdac_reg_readb(addr) readb(addr)
|
||||
#define snd_hdac_reg_readw(addr) readw(addr)
|
||||
#endif /* CONFIG_SND_HDA_ALIGNED_MMIO */
|
||||
#define snd_hdac_reg_writel(val, addr) writel(val, addr)
|
||||
#define snd_hdac_reg_readl(addr) readl(addr)
|
||||
#define snd_hdac_aligned_mmio(bus) (bus)->aligned_mmio
|
||||
#else
|
||||
#define snd_hdac_aligned_mmio(bus) false
|
||||
#define snd_hdac_aligned_read(addr, mask) 0
|
||||
#define snd_hdac_aligned_write(val, addr, mask) do {} while (0)
|
||||
#endif
|
||||
|
||||
static inline void snd_hdac_reg_writeb(struct hdac_bus *bus, void __iomem *addr,
|
||||
u8 val)
|
||||
{
|
||||
if (snd_hdac_aligned_mmio(bus))
|
||||
snd_hdac_aligned_write(val, addr, 0xff);
|
||||
else
|
||||
writeb(val, addr);
|
||||
}
|
||||
|
||||
static inline void snd_hdac_reg_writew(struct hdac_bus *bus, void __iomem *addr,
|
||||
u16 val)
|
||||
{
|
||||
if (snd_hdac_aligned_mmio(bus))
|
||||
snd_hdac_aligned_write(val, addr, 0xffff);
|
||||
else
|
||||
writew(val, addr);
|
||||
}
|
||||
|
||||
static inline u8 snd_hdac_reg_readb(struct hdac_bus *bus, void __iomem *addr)
|
||||
{
|
||||
return snd_hdac_aligned_mmio(bus) ?
|
||||
snd_hdac_aligned_read(addr, 0xff) : readb(addr);
|
||||
}
|
||||
|
||||
static inline u16 snd_hdac_reg_readw(struct hdac_bus *bus, void __iomem *addr)
|
||||
{
|
||||
return snd_hdac_aligned_mmio(bus) ?
|
||||
snd_hdac_aligned_read(addr, 0xffff) : readw(addr);
|
||||
}
|
||||
|
||||
#define snd_hdac_reg_writel(bus, addr, val) writel(val, addr)
|
||||
#define snd_hdac_reg_readl(bus, addr) readl(addr)
|
||||
|
||||
/*
|
||||
* macros for easy use
|
||||
*/
|
||||
#define _snd_hdac_chip_writeb(chip, reg, value) \
|
||||
snd_hdac_reg_writeb(value, (chip)->remap_addr + (reg))
|
||||
snd_hdac_reg_writeb(chip, (chip)->remap_addr + (reg), value)
|
||||
#define _snd_hdac_chip_readb(chip, reg) \
|
||||
snd_hdac_reg_readb((chip)->remap_addr + (reg))
|
||||
snd_hdac_reg_readb(chip, (chip)->remap_addr + (reg))
|
||||
#define _snd_hdac_chip_writew(chip, reg, value) \
|
||||
snd_hdac_reg_writew(value, (chip)->remap_addr + (reg))
|
||||
snd_hdac_reg_writew(chip, (chip)->remap_addr + (reg), value)
|
||||
#define _snd_hdac_chip_readw(chip, reg) \
|
||||
snd_hdac_reg_readw((chip)->remap_addr + (reg))
|
||||
snd_hdac_reg_readw(chip, (chip)->remap_addr + (reg))
|
||||
#define _snd_hdac_chip_writel(chip, reg, value) \
|
||||
snd_hdac_reg_writel(value, (chip)->remap_addr + (reg))
|
||||
snd_hdac_reg_writel(chip, (chip)->remap_addr + (reg), value)
|
||||
#define _snd_hdac_chip_readl(chip, reg) \
|
||||
snd_hdac_reg_readl((chip)->remap_addr + (reg))
|
||||
snd_hdac_reg_readl(chip, (chip)->remap_addr + (reg))
|
||||
|
||||
/* read/write a register, pass without AZX_REG_ prefix */
|
||||
#define snd_hdac_chip_writel(chip, reg, value) \
|
||||
@ -540,17 +572,17 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
|
||||
*/
|
||||
/* read/write a register, pass without AZX_REG_ prefix */
|
||||
#define snd_hdac_stream_writel(dev, reg, value) \
|
||||
snd_hdac_reg_writel(value, (dev)->sd_addr + AZX_REG_ ## reg)
|
||||
snd_hdac_reg_writel((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)
|
||||
#define snd_hdac_stream_writew(dev, reg, value) \
|
||||
snd_hdac_reg_writew(value, (dev)->sd_addr + AZX_REG_ ## reg)
|
||||
snd_hdac_reg_writew((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)
|
||||
#define snd_hdac_stream_writeb(dev, reg, value) \
|
||||
snd_hdac_reg_writeb(value, (dev)->sd_addr + AZX_REG_ ## reg)
|
||||
snd_hdac_reg_writeb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)
|
||||
#define snd_hdac_stream_readl(dev, reg) \
|
||||
snd_hdac_reg_readl((dev)->sd_addr + AZX_REG_ ## reg)
|
||||
snd_hdac_reg_readl((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
|
||||
#define snd_hdac_stream_readw(dev, reg) \
|
||||
snd_hdac_reg_readw((dev)->sd_addr + AZX_REG_ ## reg)
|
||||
snd_hdac_reg_readw((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
|
||||
#define snd_hdac_stream_readb(dev, reg) \
|
||||
snd_hdac_reg_readb((dev)->sd_addr + AZX_REG_ ## reg)
|
||||
snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
|
||||
|
||||
/* update a register, pass without AZX_REG_ prefix */
|
||||
#define snd_hdac_stream_updatel(dev, reg, mask, val) \
|
||||
|
@ -64,7 +64,7 @@ struct snd_info_entry {
|
||||
unsigned short content;
|
||||
union {
|
||||
struct snd_info_entry_text text;
|
||||
struct snd_info_entry_ops *ops;
|
||||
const struct snd_info_entry_ops *ops;
|
||||
} c;
|
||||
struct snd_info_entry *parent;
|
||||
struct module *module;
|
||||
|
@ -37,7 +37,7 @@
|
||||
#define SNDRV_DEFAULT_PTR SNDRV_DEFAULT_STR
|
||||
|
||||
#ifdef SNDRV_LEGACY_FIND_FREE_IOPORT
|
||||
static long snd_legacy_find_free_ioport(long *port_table, long size)
|
||||
static long snd_legacy_find_free_ioport(const long *port_table, long size)
|
||||
{
|
||||
while (*port_table != -1) {
|
||||
if (request_region(*port_table, size, "ALSA test")) {
|
||||
@ -58,7 +58,7 @@ static irqreturn_t snd_legacy_empty_irq_handler(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int snd_legacy_find_free_irq(int *irq_table)
|
||||
static int snd_legacy_find_free_irq(const int *irq_table)
|
||||
{
|
||||
while (*irq_table != -1) {
|
||||
if (!request_irq(*irq_table, snd_legacy_empty_irq_handler,
|
||||
@ -74,7 +74,7 @@ static int snd_legacy_find_free_irq(int *irq_table)
|
||||
#endif
|
||||
|
||||
#ifdef SNDRV_LEGACY_FIND_FREE_DMA
|
||||
static int snd_legacy_find_free_dma(int *dma_table)
|
||||
static int snd_legacy_find_free_dma(const int *dma_table)
|
||||
{
|
||||
while (*dma_table != -1) {
|
||||
if (!request_dma(*dma_table, "ALSA Test DMA")) {
|
||||
|
@ -44,6 +44,7 @@ struct snd_pcm_hardware {
|
||||
size_t fifo_size; /* fifo size in bytes */
|
||||
};
|
||||
|
||||
struct snd_pcm_status64;
|
||||
struct snd_pcm_substream;
|
||||
|
||||
struct snd_pcm_audio_tstamp_config; /* definitions further down */
|
||||
@ -62,7 +63,7 @@ struct snd_pcm_ops {
|
||||
int (*sync_stop)(struct snd_pcm_substream *substream);
|
||||
snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream);
|
||||
int (*get_time_info)(struct snd_pcm_substream *substream,
|
||||
struct timespec *system_ts, struct timespec *audio_ts,
|
||||
struct timespec64 *system_ts, struct timespec64 *audio_ts,
|
||||
struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
|
||||
struct snd_pcm_audio_tstamp_report *audio_tstamp_report);
|
||||
int (*fill_silence)(struct snd_pcm_substream *substream, int channel,
|
||||
@ -343,7 +344,7 @@ static inline void snd_pcm_pack_audio_tstamp_report(__u32 *data, __u32 *accuracy
|
||||
struct snd_pcm_runtime {
|
||||
/* -- Status -- */
|
||||
struct snd_pcm_substream *trigger_master;
|
||||
struct timespec trigger_tstamp; /* trigger timestamp */
|
||||
struct timespec64 trigger_tstamp; /* trigger timestamp */
|
||||
bool trigger_tstamp_latched; /* trigger timestamp latched in low-level driver/hardware */
|
||||
int overrange;
|
||||
snd_pcm_uframes_t avail_max;
|
||||
@ -421,7 +422,7 @@ struct snd_pcm_runtime {
|
||||
/* -- audio timestamp config -- */
|
||||
struct snd_pcm_audio_tstamp_config audio_tstamp_config;
|
||||
struct snd_pcm_audio_tstamp_report audio_tstamp_report;
|
||||
struct timespec driver_tstamp;
|
||||
struct timespec64 driver_tstamp;
|
||||
|
||||
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
|
||||
/* -- OSS things -- */
|
||||
@ -558,8 +559,8 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree);
|
||||
int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info);
|
||||
int snd_pcm_info_user(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_info __user *info);
|
||||
int snd_pcm_status(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_status *status);
|
||||
int snd_pcm_status64(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_status64 *status);
|
||||
int snd_pcm_start(struct snd_pcm_substream *substream);
|
||||
int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t status);
|
||||
int snd_pcm_drain_done(struct snd_pcm_substream *substream);
|
||||
@ -1155,22 +1156,22 @@ static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substrea
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_pcm_gettime - Fill the timespec depending on the timestamp mode
|
||||
* snd_pcm_gettime - Fill the timespec64 depending on the timestamp mode
|
||||
* @runtime: PCM runtime instance
|
||||
* @tv: timespec to fill
|
||||
* @tv: timespec64 to fill
|
||||
*/
|
||||
static inline void snd_pcm_gettime(struct snd_pcm_runtime *runtime,
|
||||
struct timespec *tv)
|
||||
struct timespec64 *tv)
|
||||
{
|
||||
switch (runtime->tstamp_type) {
|
||||
case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC:
|
||||
ktime_get_ts(tv);
|
||||
ktime_get_ts64(tv);
|
||||
break;
|
||||
case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW:
|
||||
getrawmonotonic(tv);
|
||||
ktime_get_raw_ts64(tv);
|
||||
break;
|
||||
default:
|
||||
getnstimeofday(tv);
|
||||
ktime_get_real_ts64(tv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1422,4 +1423,55 @@ static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format)
|
||||
#define pcm_dbg(pcm, fmt, args...) \
|
||||
dev_dbg((pcm)->card->dev, fmt, ##args)
|
||||
|
||||
struct snd_pcm_status64 {
|
||||
snd_pcm_state_t state; /* stream state */
|
||||
u8 rsvd[4];
|
||||
s64 trigger_tstamp_sec; /* time when stream was started/stopped/paused */
|
||||
s64 trigger_tstamp_nsec;
|
||||
s64 tstamp_sec; /* reference timestamp */
|
||||
s64 tstamp_nsec;
|
||||
snd_pcm_uframes_t appl_ptr; /* appl ptr */
|
||||
snd_pcm_uframes_t hw_ptr; /* hw ptr */
|
||||
snd_pcm_sframes_t delay; /* current delay in frames */
|
||||
snd_pcm_uframes_t avail; /* number of frames available */
|
||||
snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */
|
||||
snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
|
||||
snd_pcm_state_t suspended_state; /* suspended stream state */
|
||||
__u32 audio_tstamp_data; /* needed for 64-bit alignment, used for configs/report to/from userspace */
|
||||
s64 audio_tstamp_sec; /* sample counter, wall clock, PHC or on-demand sync'ed */
|
||||
s64 audio_tstamp_nsec;
|
||||
s64 driver_tstamp_sec; /* useful in case reference system tstamp is reported with delay */
|
||||
s64 driver_tstamp_nsec;
|
||||
__u32 audio_tstamp_accuracy; /* in ns units, only valid if indicated in audio_tstamp_data */
|
||||
unsigned char reserved[52-4*sizeof(s64)]; /* must be filled with zero */
|
||||
};
|
||||
|
||||
#define SNDRV_PCM_IOCTL_STATUS64 _IOR('A', 0x20, struct snd_pcm_status64)
|
||||
#define SNDRV_PCM_IOCTL_STATUS_EXT64 _IOWR('A', 0x24, struct snd_pcm_status64)
|
||||
|
||||
struct snd_pcm_status32 {
|
||||
s32 state; /* stream state */
|
||||
s32 trigger_tstamp_sec; /* time when stream was started/stopped/paused */
|
||||
s32 trigger_tstamp_nsec;
|
||||
s32 tstamp_sec; /* reference timestamp */
|
||||
s32 tstamp_nsec;
|
||||
u32 appl_ptr; /* appl ptr */
|
||||
u32 hw_ptr; /* hw ptr */
|
||||
s32 delay; /* current delay in frames */
|
||||
u32 avail; /* number of frames available */
|
||||
u32 avail_max; /* max frames available on hw since last status */
|
||||
u32 overrange; /* count of ADC (capture) overrange detections from last status */
|
||||
s32 suspended_state; /* suspended stream state */
|
||||
u32 audio_tstamp_data; /* needed for 64-bit alignment, used for configs/report to/from userspace */
|
||||
s32 audio_tstamp_sec; /* sample counter, wall clock, PHC or on-demand sync'ed */
|
||||
s32 audio_tstamp_nsec;
|
||||
s32 driver_tstamp_sec; /* useful in case reference system tstamp is reported with delay */
|
||||
s32 driver_tstamp_nsec;
|
||||
u32 audio_tstamp_accuracy; /* in ns units, only valid if indicated in audio_tstamp_data */
|
||||
unsigned char reserved[52-4*sizeof(s32)]; /* must be filled with zero */
|
||||
};
|
||||
|
||||
#define SNDRV_PCM_IOCTL_STATUS32 _IOR('A', 0x20, struct snd_pcm_status32)
|
||||
#define SNDRV_PCM_IOCTL_STATUS_EXT32 _IOWR('A', 0x24, struct snd_pcm_status32)
|
||||
|
||||
#endif /* __SOUND_PCM_H */
|
||||
|
@ -174,7 +174,8 @@ enum {
|
||||
};
|
||||
|
||||
/* Prototypes for midi_process.c */
|
||||
void snd_midi_process_event(struct snd_midi_op *ops, struct snd_seq_event *ev,
|
||||
void snd_midi_process_event(const struct snd_midi_op *ops,
|
||||
struct snd_seq_event *ev,
|
||||
struct snd_midi_channel_set *chanset);
|
||||
void snd_midi_channel_set_clear(struct snd_midi_channel_set *chset);
|
||||
struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n);
|
||||
|
@ -31,6 +31,12 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[];
|
||||
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_sdw_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_sdw_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_sdw_machines[];
|
||||
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[];
|
||||
|
||||
/*
|
||||
* generic table used for HDA codec-based platforms, possibly with
|
||||
* additional ACPI-enumerated codecs
|
||||
|
@ -61,6 +61,8 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
|
||||
* @platform: string used for HDaudio codec support
|
||||
* @codec_mask: used for HDAudio support
|
||||
* @common_hdmi_codec_drv: use commom HDAudio HDMI codec driver
|
||||
* @link_mask: links enabled on the board
|
||||
* @links: array of link _ADR descriptors, null terminated
|
||||
*/
|
||||
struct snd_soc_acpi_mach_params {
|
||||
u32 acpi_ipc_irq_index;
|
||||
@ -68,6 +70,23 @@ struct snd_soc_acpi_mach_params {
|
||||
u32 codec_mask;
|
||||
u32 dmic_num;
|
||||
bool common_hdmi_codec_drv;
|
||||
u32 link_mask;
|
||||
const struct snd_soc_acpi_link_adr *links;
|
||||
};
|
||||
|
||||
/**
|
||||
* snd_soc_acpi_link_adr: ACPI-based list of _ADR, with a variable
|
||||
* number of devices per link
|
||||
*
|
||||
* @mask: one bit set indicates the link this list applies to
|
||||
* @num_adr: ARRAY_SIZE of adr
|
||||
* @adr: array of _ADR (represented as u64).
|
||||
*/
|
||||
|
||||
struct snd_soc_acpi_link_adr {
|
||||
const u32 mask;
|
||||
const u32 num_adr;
|
||||
const u64 *adr;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -78,6 +97,7 @@ struct snd_soc_acpi_mach_params {
|
||||
*
|
||||
* @id: ACPI ID (usually the codec's) used to find a matching machine driver.
|
||||
* @link_mask: describes required board layout, e.g. for SoundWire.
|
||||
* @links: array of link _ADR descriptors, null terminated.
|
||||
* @drv_name: machine driver name
|
||||
* @fw_filename: firmware file name. Used when SOF is not enabled.
|
||||
* @board: board name
|
||||
@ -94,6 +114,7 @@ struct snd_soc_acpi_mach_params {
|
||||
struct snd_soc_acpi_mach {
|
||||
const u8 id[ACPI_ID_LEN];
|
||||
const u32 link_mask;
|
||||
const struct snd_soc_acpi_link_adr *links;
|
||||
const char *drv_name;
|
||||
const char *fw_filename;
|
||||
const char *board;
|
||||
|
@ -93,8 +93,8 @@ struct snd_soc_component_driver {
|
||||
snd_pcm_uframes_t (*pointer)(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream);
|
||||
int (*get_time_info)(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream, struct timespec *system_ts,
|
||||
struct timespec *audio_ts,
|
||||
struct snd_pcm_substream *substream, struct timespec64 *system_ts,
|
||||
struct timespec64 *audio_ts,
|
||||
struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
|
||||
struct snd_pcm_audio_tstamp_report *audio_tstamp_report);
|
||||
int (*copy_user)(struct snd_soc_component *component,
|
||||
|
@ -286,8 +286,6 @@ struct snd_soc_dai_driver {
|
||||
/* DAI driver callbacks */
|
||||
int (*probe)(struct snd_soc_dai *dai);
|
||||
int (*remove)(struct snd_soc_dai *dai);
|
||||
int (*suspend)(struct snd_soc_dai *dai);
|
||||
int (*resume)(struct snd_soc_dai *dai);
|
||||
/* compress dai */
|
||||
int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int num);
|
||||
/* Optional Callback used at pcm creation*/
|
||||
@ -304,7 +302,6 @@ struct snd_soc_dai_driver {
|
||||
unsigned int symmetric_rates:1;
|
||||
unsigned int symmetric_channels:1;
|
||||
unsigned int symmetric_samplebits:1;
|
||||
unsigned int bus_control:1; /* DAI is also used for the control bus */
|
||||
|
||||
/* probe ordering - for components with runtime dependencies */
|
||||
int probe_order;
|
||||
|
@ -392,6 +392,8 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_dapm_put_enum_double_locked(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo);
|
||||
int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
|
||||
@ -434,6 +436,7 @@ void snd_soc_dapm_reset_cache(struct snd_soc_dapm_context *dapm);
|
||||
/* dapm events */
|
||||
void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
|
||||
int event);
|
||||
void snd_soc_dapm_stream_stop(struct snd_soc_pcm_runtime *rtd, int stream);
|
||||
void snd_soc_dapm_shutdown(struct snd_soc_card *card);
|
||||
|
||||
/* external DAPM widget events */
|
||||
|
@ -464,10 +464,8 @@ static inline int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
|
||||
|
||||
void snd_soc_disconnect_sync(struct device *dev);
|
||||
|
||||
struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
|
||||
const char *dai_link, int stream);
|
||||
struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
|
||||
const char *dai_link);
|
||||
struct snd_soc_dai_link *dai_link);
|
||||
|
||||
bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd);
|
||||
void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream);
|
||||
@ -738,19 +736,9 @@ struct snd_soc_compr_ops {
|
||||
int (*trigger)(struct snd_compr_stream *);
|
||||
};
|
||||
|
||||
struct snd_soc_rtdcom_list {
|
||||
struct snd_soc_component *component;
|
||||
struct list_head list; /* rtd::component_list */
|
||||
};
|
||||
struct snd_soc_component*
|
||||
snd_soc_rtdcom_lookup(struct snd_soc_pcm_runtime *rtd,
|
||||
const char *driver_name);
|
||||
#define for_each_rtd_components(rtd, rtdcom, _component) \
|
||||
for (rtdcom = list_first_entry(&(rtd)->component_list, \
|
||||
typeof(*rtdcom), list); \
|
||||
(&rtdcom->list != &(rtd)->component_list) && \
|
||||
(_component = rtdcom->component); \
|
||||
rtdcom = list_next_entry(rtdcom, list))
|
||||
|
||||
struct snd_soc_dai_link_component {
|
||||
const char *name;
|
||||
@ -852,7 +840,6 @@ struct snd_soc_dai_link {
|
||||
/* Do not create a PCM for this DAI link (Backend link) */
|
||||
unsigned int ignore:1;
|
||||
|
||||
struct list_head list; /* DAI link list of the soc card */
|
||||
#ifdef CONFIG_SND_SOC_TOPOLOGY
|
||||
struct snd_soc_dobj dobj; /* For topology */
|
||||
#endif
|
||||
@ -952,6 +939,7 @@ struct snd_soc_dai_link {
|
||||
#define COMP_CODEC(_name, _dai) { .name = _name, .dai_name = _dai, }
|
||||
#define COMP_PLATFORM(_name) { .name = _name }
|
||||
#define COMP_AUX(_name) { .name = _name }
|
||||
#define COMP_CODEC_CONF(_name) { .name = _name }
|
||||
#define COMP_DUMMY() { .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", }
|
||||
|
||||
extern struct snd_soc_dai_link_component null_dailink_component[0];
|
||||
@ -962,8 +950,7 @@ struct snd_soc_codec_conf {
|
||||
* specify device either by device name, or by
|
||||
* DT/OF node, but not both.
|
||||
*/
|
||||
const char *dev_name;
|
||||
struct device_node *of_node;
|
||||
struct snd_soc_dai_link_component dlc;
|
||||
|
||||
/*
|
||||
* optional map of kcontrol, widget and path name prefixes that are
|
||||
@ -989,7 +976,9 @@ struct snd_soc_card {
|
||||
const char *long_name;
|
||||
const char *driver_name;
|
||||
const char *components;
|
||||
#ifdef CONFIG_DMI
|
||||
char dmi_longname[80];
|
||||
#endif /* CONFIG_DMI */
|
||||
char topology_shortname[32];
|
||||
|
||||
struct device *dev;
|
||||
@ -1037,7 +1026,6 @@ struct snd_soc_card {
|
||||
/* CPU <--> Codec DAI links */
|
||||
struct snd_soc_dai_link *dai_link; /* predefined links only */
|
||||
int num_links; /* predefined links only */
|
||||
struct list_head dai_link_list; /* all links */
|
||||
|
||||
struct list_head rtd_list;
|
||||
int num_rtd;
|
||||
@ -1107,11 +1095,6 @@ struct snd_soc_card {
|
||||
((i) < (card)->num_aux_devs) && ((aux) = &(card)->aux_dev[i]); \
|
||||
(i)++)
|
||||
|
||||
#define for_each_card_links(card, link) \
|
||||
list_for_each_entry(link, &(card)->dai_link_list, list)
|
||||
#define for_each_card_links_safe(card, link, _link) \
|
||||
list_for_each_entry_safe(link, _link, &(card)->dai_link_list, list)
|
||||
|
||||
#define for_each_card_rtds(card, rtd) \
|
||||
list_for_each_entry(rtd, &(card)->rtd_list, list)
|
||||
#define for_each_card_rtds_safe(card, rtd, _rtd) \
|
||||
@ -1157,12 +1140,18 @@ struct snd_soc_pcm_runtime {
|
||||
|
||||
unsigned int num; /* 0-based and monotonic increasing */
|
||||
struct list_head list; /* rtd list of the soc card */
|
||||
struct list_head component_list; /* list of connected components */
|
||||
|
||||
/* bit field */
|
||||
unsigned int pop_wait:1;
|
||||
unsigned int fe_compr:1; /* for Dynamic PCM */
|
||||
|
||||
int num_components;
|
||||
struct snd_soc_component *components[0]; /* CPU/Codec/Platform */
|
||||
};
|
||||
#define for_each_rtd_components(rtd, i, component) \
|
||||
for ((i) = 0; \
|
||||
((i) < rtd->num_components) && ((component) = rtd->components[i]);\
|
||||
(i)++)
|
||||
#define for_each_rtd_codec_dai(rtd, i, dai)\
|
||||
for ((i) = 0; \
|
||||
((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \
|
||||
@ -1170,6 +1159,7 @@ struct snd_soc_pcm_runtime {
|
||||
#define for_each_rtd_codec_dai_rollback(rtd, i, dai) \
|
||||
for (; ((--i) >= 0) && ((dai) = rtd->codec_dais[i]);)
|
||||
|
||||
void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd);
|
||||
|
||||
/* mixer control */
|
||||
struct soc_mixer_control {
|
||||
@ -1333,13 +1323,10 @@ int snd_soc_of_get_dai_link_codecs(struct device *dev,
|
||||
struct snd_soc_dai_link *dai_link);
|
||||
void snd_soc_of_put_dai_link_codecs(struct snd_soc_dai_link *dai_link);
|
||||
|
||||
int snd_soc_add_dai_link(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_link);
|
||||
void snd_soc_remove_dai_link(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_link);
|
||||
struct snd_soc_dai_link *snd_soc_find_dai_link(struct snd_soc_card *card,
|
||||
int id, const char *name,
|
||||
const char *stream_name);
|
||||
int snd_soc_add_pcm_runtime(struct snd_soc_card *card,
|
||||
struct snd_soc_dai_link *dai_link);
|
||||
void snd_soc_remove_pcm_runtime(struct snd_soc_card *card,
|
||||
struct snd_soc_pcm_runtime *rtd);
|
||||
|
||||
struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component,
|
||||
struct snd_soc_dai_driver *dai_drv,
|
||||
@ -1409,11 +1396,6 @@ static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm)
|
||||
mutex_unlock(&dapm->card->dapm_mutex);
|
||||
}
|
||||
|
||||
/* bypass */
|
||||
int snd_soc_pcm_lib_ioctl(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream,
|
||||
unsigned int cmd, void *arg);
|
||||
|
||||
#include <sound/soc-component.h>
|
||||
|
||||
#endif
|
||||
|
@ -22,7 +22,6 @@ struct snd_sof_dsp_ops;
|
||||
*/
|
||||
struct snd_sof_pdata {
|
||||
const struct firmware *fw;
|
||||
const char *drv_name;
|
||||
const char *name;
|
||||
const char *platform;
|
||||
|
||||
@ -84,20 +83,18 @@ struct sof_dev_desc {
|
||||
const void *chip_info;
|
||||
|
||||
/* defaults for no codec mode */
|
||||
const char *nocodec_fw_filename;
|
||||
const char *nocodec_tplg_filename;
|
||||
|
||||
/* defaults paths for firmware and topology files */
|
||||
const char *default_fw_path;
|
||||
const char *default_tplg_path;
|
||||
|
||||
/* default firmware name */
|
||||
const char *default_fw_filename;
|
||||
|
||||
const struct snd_sof_dsp_ops *ops;
|
||||
const struct sof_arch_ops *arch_ops;
|
||||
};
|
||||
|
||||
int sof_nocodec_setup(struct device *dev,
|
||||
struct snd_sof_pdata *sof_pdata,
|
||||
struct snd_soc_acpi_mach *mach,
|
||||
const struct sof_dev_desc *desc,
|
||||
const struct snd_sof_dsp_ops *ops);
|
||||
#endif
|
||||
|
61
include/sound/sof/channel_map.h
Normal file
61
include/sound/sof/channel_map.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* Copyright(c) 2019 Intel Corporation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __IPC_CHANNEL_MAP_H__
|
||||
#define __IPC_CHANNEL_MAP_H__
|
||||
|
||||
#include <uapi/sound/sof/header.h>
|
||||
#include <sound/sof/header.h>
|
||||
|
||||
/**
|
||||
* \brief Channel map, specifies transformation of one-to-many or many-to-one.
|
||||
*
|
||||
* In case of one-to-many specifies how the output channels are computed out of
|
||||
* a single source channel,
|
||||
* in case of many-to-one specifies how a single target channel is computed
|
||||
* from a multichannel input stream.
|
||||
*
|
||||
* Channel index specifies position of the channel in the stream on the 'one'
|
||||
* side.
|
||||
*
|
||||
* Ext ID is the identifier of external part of the transformation. Depending
|
||||
* on the context, it may be pipeline ID, dai ID, ...
|
||||
*
|
||||
* Channel mask describes which channels are taken into account on the "many"
|
||||
* side. Bit[i] set to 1 means that i-th channel is used for computation
|
||||
* (either as source or as a target).
|
||||
*
|
||||
* Channel mask is followed by array of coefficients in Q2.30 format,
|
||||
* one per each channel set in the mask (left to right, LS bit set in the
|
||||
* mask corresponds to ch_coeffs[0]).
|
||||
*/
|
||||
struct sof_ipc_channel_map {
|
||||
uint32_t ch_index;
|
||||
uint32_t ext_id;
|
||||
uint32_t ch_mask;
|
||||
uint32_t reserved;
|
||||
int32_t ch_coeffs[0];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* \brief Complete map for each channel of a multichannel stream.
|
||||
*
|
||||
* num_ch_map Specifies number of items in the ch_map.
|
||||
* More than one transformation per a single channel is allowed (in case
|
||||
* multiple external entities are transformed).
|
||||
* A channel may be skipped in the transformation list, then it is filled
|
||||
* with 0's by the transformation function.
|
||||
*/
|
||||
struct sof_ipc_stream_map {
|
||||
struct sof_ipc_cmd_hdr hdr;
|
||||
uint32_t num_ch_map;
|
||||
uint32_t reserved[3];
|
||||
struct sof_ipc_channel_map ch_map[0];
|
||||
} __packed;
|
||||
|
||||
#endif /* __IPC_CHANNEL_MAP_H__ */
|
@ -31,4 +31,24 @@ struct sof_ipc_dai_esai_params {
|
||||
uint16_t reserved2; /* alignment */
|
||||
} __packed;
|
||||
|
||||
/* SAI Configuration Request - SOF_IPC_DAI_SAI_CONFIG */
|
||||
struct sof_ipc_dai_sai_params {
|
||||
struct sof_ipc_hdr hdr;
|
||||
|
||||
/* MCLK */
|
||||
uint16_t reserved1;
|
||||
uint16_t mclk_id;
|
||||
uint32_t mclk_direction;
|
||||
|
||||
uint32_t mclk_rate; /* MCLK frequency in Hz */
|
||||
uint32_t fsync_rate; /* FSYNC frequency in Hz */
|
||||
uint32_t bclk_rate; /* BCLK frequency in Hz */
|
||||
|
||||
/* TDM */
|
||||
uint32_t tdm_slots;
|
||||
uint32_t rx_slots;
|
||||
uint32_t tx_slots;
|
||||
uint16_t tdm_slot_width;
|
||||
uint16_t reserved2; /* alignment */
|
||||
} __packed;
|
||||
#endif
|
||||
|
@ -75,6 +75,7 @@ struct sof_ipc_dai_config {
|
||||
struct sof_ipc_dai_hda_params hda;
|
||||
struct sof_ipc_dai_alh_params alh;
|
||||
struct sof_ipc_dai_esai_params esai;
|
||||
struct sof_ipc_dai_sai_params sai;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
enum sof_ipc_ext_data {
|
||||
SOF_IPC_EXT_DMA_BUFFER = 0,
|
||||
SOF_IPC_EXT_WINDOW,
|
||||
SOF_IPC_EXT_CC_INFO,
|
||||
};
|
||||
|
||||
/* FW version - SOF_IPC_GLB_VERSION */
|
||||
@ -115,4 +116,18 @@ struct sof_ipc_window {
|
||||
struct sof_ipc_window_elem window[];
|
||||
} __packed;
|
||||
|
||||
struct sof_ipc_cc_version {
|
||||
struct sof_ipc_ext_data_hdr ext_hdr;
|
||||
uint32_t major;
|
||||
uint32_t minor;
|
||||
uint32_t micro;
|
||||
|
||||
/* reserved for future use */
|
||||
uint32_t reserved[4];
|
||||
|
||||
char name[16]; /* null terminated compiler name */
|
||||
char optim[4]; /* null terminated compiler -O flag value */
|
||||
char desc[]; /* null terminated compiler description */
|
||||
} __packed;
|
||||
|
||||
#endif
|
||||
|
@ -36,6 +36,7 @@ enum sof_comp_type {
|
||||
SOF_COMP_KPB, /* A key phrase buffer component */
|
||||
SOF_COMP_SELECTOR, /**< channel selector component */
|
||||
SOF_COMP_DEMUX,
|
||||
SOF_COMP_ASRC, /**< Asynchronous sample rate converter */
|
||||
/* keep FILEREAD/FILEWRITE as the last ones */
|
||||
SOF_COMP_FILEREAD = 10000, /**< host test based file IO */
|
||||
SOF_COMP_FILEWRITE = 10001, /**< host test based file IO */
|
||||
@ -147,6 +148,32 @@ struct sof_ipc_comp_src {
|
||||
uint32_t rate_mask; /**< SOF_RATE_ supported rates */
|
||||
} __packed;
|
||||
|
||||
/* generic ASRC component */
|
||||
struct sof_ipc_comp_asrc {
|
||||
struct sof_ipc_comp comp;
|
||||
struct sof_ipc_comp_config config;
|
||||
/* either source or sink rate must be non zero */
|
||||
uint32_t source_rate; /**< Define fixed source rate or */
|
||||
/**< use 0 to indicate need to get */
|
||||
/**< the rate from stream */
|
||||
uint32_t sink_rate; /**< Define fixed sink rate or */
|
||||
/**< use 0 to indicate need to get */
|
||||
/**< the rate from stream */
|
||||
uint32_t asynchronous_mode; /**< synchronous 0, asynchronous 1 */
|
||||
/**< When 1 the ASRC tracks and */
|
||||
/**< compensates for drift. */
|
||||
uint32_t operation_mode; /**< push 0, pull 1, In push mode the */
|
||||
/**< ASRC consumes a defined number */
|
||||
/**< of frames at input, with varying */
|
||||
/**< number of frames at output. */
|
||||
/**< In pull mode the ASRC outputs */
|
||||
/**< a defined number of frames while */
|
||||
/**< number of input frames varies. */
|
||||
|
||||
/* reserved for future use */
|
||||
uint32_t reserved[4];
|
||||
} __attribute__((packed));
|
||||
|
||||
/* generic MUX component */
|
||||
struct sof_ipc_comp_mux {
|
||||
struct sof_ipc_comp comp;
|
||||
|
@ -89,7 +89,7 @@ struct snd_timer_instance {
|
||||
unsigned long ticks, unsigned long resolution);
|
||||
void (*ccallback) (struct snd_timer_instance * timeri,
|
||||
int event,
|
||||
struct timespec * tstamp,
|
||||
struct timespec64 * tstamp,
|
||||
unsigned long resolution);
|
||||
void (*disconnect)(struct snd_timer_instance *timeri);
|
||||
void *callback_data;
|
||||
@ -113,7 +113,7 @@ struct snd_timer_instance {
|
||||
*/
|
||||
|
||||
int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, struct snd_timer **rtimer);
|
||||
void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp);
|
||||
void snd_timer_notify(struct snd_timer *timer, int event, struct timespec64 *tstamp);
|
||||
int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer);
|
||||
int snd_timer_global_free(struct snd_timer *timer);
|
||||
int snd_timer_global_register(struct snd_timer *timer);
|
||||
|
@ -147,8 +147,8 @@ struct vx_core {
|
||||
/* ports are defined externally */
|
||||
|
||||
/* low-level functions */
|
||||
struct snd_vx_hardware *hw;
|
||||
struct snd_vx_ops *ops;
|
||||
const struct snd_vx_hardware *hw;
|
||||
const struct snd_vx_ops *ops;
|
||||
|
||||
struct mutex lock;
|
||||
|
||||
@ -193,8 +193,9 @@ struct vx_core {
|
||||
/*
|
||||
* constructor
|
||||
*/
|
||||
struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw,
|
||||
struct snd_vx_ops *ops, int extra_size);
|
||||
struct vx_core *snd_vx_create(struct snd_card *card,
|
||||
const struct snd_vx_hardware *hw,
|
||||
const struct snd_vx_ops *ops, int extra_size);
|
||||
int snd_vx_setup_firmware(struct vx_core *chip);
|
||||
int snd_vx_load_boot_image(struct vx_core *chip, const struct firmware *dsp);
|
||||
int snd_vx_dsp_boot(struct vx_core *chip, const struct firmware *dsp);
|
||||
|
@ -17,7 +17,6 @@
|
||||
#define __LINUX_UAPI_SND_ASOC_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <sound/asound.h>
|
||||
|
||||
/*
|
||||
* Maximum number of channels topology kcontrol can represent.
|
||||
|
@ -26,7 +26,9 @@
|
||||
|
||||
#if defined(__KERNEL__) || defined(__linux__)
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#else
|
||||
#include <endian.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
@ -154,7 +156,7 @@ struct snd_hwdep_dsp_image {
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 14)
|
||||
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 15)
|
||||
|
||||
typedef unsigned long snd_pcm_uframes_t;
|
||||
typedef signed long snd_pcm_sframes_t;
|
||||
@ -301,7 +303,9 @@ typedef int __bitwise snd_pcm_subformat_t;
|
||||
#define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */
|
||||
#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */
|
||||
|
||||
|
||||
#if (__BITS_PER_LONG == 32 && defined(__USE_TIME_BITS64)) || defined __KERNEL__
|
||||
#define __SND_STRUCT_TIME64
|
||||
#endif
|
||||
|
||||
typedef int __bitwise snd_pcm_state_t;
|
||||
#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */
|
||||
@ -317,8 +321,17 @@ typedef int __bitwise snd_pcm_state_t;
|
||||
|
||||
enum {
|
||||
SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
|
||||
SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
|
||||
SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
|
||||
SNDRV_PCM_MMAP_OFFSET_STATUS_OLD = 0x80000000,
|
||||
SNDRV_PCM_MMAP_OFFSET_CONTROL_OLD = 0x81000000,
|
||||
SNDRV_PCM_MMAP_OFFSET_STATUS_NEW = 0x82000000,
|
||||
SNDRV_PCM_MMAP_OFFSET_CONTROL_NEW = 0x83000000,
|
||||
#ifdef __SND_STRUCT_TIME64
|
||||
SNDRV_PCM_MMAP_OFFSET_STATUS = SNDRV_PCM_MMAP_OFFSET_STATUS_NEW,
|
||||
SNDRV_PCM_MMAP_OFFSET_CONTROL = SNDRV_PCM_MMAP_OFFSET_CONTROL_NEW,
|
||||
#else
|
||||
SNDRV_PCM_MMAP_OFFSET_STATUS = SNDRV_PCM_MMAP_OFFSET_STATUS_OLD,
|
||||
SNDRV_PCM_MMAP_OFFSET_CONTROL = SNDRV_PCM_MMAP_OFFSET_CONTROL_OLD,
|
||||
#endif
|
||||
};
|
||||
|
||||
union snd_pcm_sync_id {
|
||||
@ -456,8 +469,13 @@ enum {
|
||||
SNDRV_PCM_AUDIO_TSTAMP_TYPE_LAST = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED
|
||||
};
|
||||
|
||||
#ifndef __KERNEL__
|
||||
/* explicit padding avoids incompatibility between i386 and x86-64 */
|
||||
typedef struct { unsigned char pad[sizeof(time_t) - sizeof(int)]; } __time_pad;
|
||||
|
||||
struct snd_pcm_status {
|
||||
snd_pcm_state_t state; /* stream state */
|
||||
__time_pad pad1; /* align to timespec */
|
||||
struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
|
||||
struct timespec tstamp; /* reference timestamp */
|
||||
snd_pcm_uframes_t appl_ptr; /* appl ptr */
|
||||
@ -473,17 +491,48 @@ struct snd_pcm_status {
|
||||
__u32 audio_tstamp_accuracy; /* in ns units, only valid if indicated in audio_tstamp_data */
|
||||
unsigned char reserved[52-2*sizeof(struct timespec)]; /* must be filled with zero */
|
||||
};
|
||||
#endif
|
||||
|
||||
struct snd_pcm_mmap_status {
|
||||
/*
|
||||
* For mmap operations, we need the 64-bit layout, both for compat mode,
|
||||
* and for y2038 compatibility. For 64-bit applications, the two definitions
|
||||
* are identical, so we keep the traditional version.
|
||||
*/
|
||||
#ifdef __SND_STRUCT_TIME64
|
||||
#define __snd_pcm_mmap_status64 snd_pcm_mmap_status
|
||||
#define __snd_pcm_mmap_control64 snd_pcm_mmap_control
|
||||
#define __snd_pcm_sync_ptr64 snd_pcm_sync_ptr
|
||||
#ifdef __KERNEL__
|
||||
#define __snd_timespec64 __kernel_timespec
|
||||
#else
|
||||
#define __snd_timespec64 timespec
|
||||
#endif
|
||||
struct __snd_timespec {
|
||||
__s32 tv_sec;
|
||||
__s32 tv_nsec;
|
||||
};
|
||||
#else
|
||||
#define __snd_pcm_mmap_status snd_pcm_mmap_status
|
||||
#define __snd_pcm_mmap_control snd_pcm_mmap_control
|
||||
#define __snd_pcm_sync_ptr snd_pcm_sync_ptr
|
||||
#define __snd_timespec timespec
|
||||
struct __snd_timespec64 {
|
||||
__s64 tv_sec;
|
||||
__s64 tv_nsec;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct __snd_pcm_mmap_status {
|
||||
snd_pcm_state_t state; /* RO: state - SNDRV_PCM_STATE_XXXX */
|
||||
int pad1; /* Needed for 64 bit alignment */
|
||||
snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
|
||||
struct timespec tstamp; /* Timestamp */
|
||||
struct __snd_timespec tstamp; /* Timestamp */
|
||||
snd_pcm_state_t suspended_state; /* RO: suspended stream state */
|
||||
struct timespec audio_tstamp; /* from sample counter or wall clock */
|
||||
struct __snd_timespec audio_tstamp; /* from sample counter or wall clock */
|
||||
};
|
||||
|
||||
struct snd_pcm_mmap_control {
|
||||
struct __snd_pcm_mmap_control {
|
||||
snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */
|
||||
snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */
|
||||
};
|
||||
@ -492,14 +541,59 @@ struct snd_pcm_mmap_control {
|
||||
#define SNDRV_PCM_SYNC_PTR_APPL (1<<1) /* get appl_ptr from driver (r/w op) */
|
||||
#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2) /* get avail_min from driver */
|
||||
|
||||
struct snd_pcm_sync_ptr {
|
||||
struct __snd_pcm_sync_ptr {
|
||||
unsigned int flags;
|
||||
union {
|
||||
struct snd_pcm_mmap_status status;
|
||||
struct __snd_pcm_mmap_status status;
|
||||
unsigned char reserved[64];
|
||||
} s;
|
||||
union {
|
||||
struct snd_pcm_mmap_control control;
|
||||
struct __snd_pcm_mmap_control control;
|
||||
unsigned char reserved[64];
|
||||
} c;
|
||||
};
|
||||
|
||||
#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __BIG_ENDIAN : defined(__BIG_ENDIAN)
|
||||
typedef char __pad_before_uframe[sizeof(__u64) - sizeof(snd_pcm_uframes_t)];
|
||||
typedef char __pad_after_uframe[0];
|
||||
#endif
|
||||
|
||||
#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
|
||||
typedef char __pad_before_uframe[0];
|
||||
typedef char __pad_after_uframe[sizeof(__u64) - sizeof(snd_pcm_uframes_t)];
|
||||
#endif
|
||||
|
||||
struct __snd_pcm_mmap_status64 {
|
||||
__s32 state; /* RO: state - SNDRV_PCM_STATE_XXXX */
|
||||
__u32 pad1; /* Needed for 64 bit alignment */
|
||||
__pad_before_uframe __pad1;
|
||||
snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
|
||||
__pad_after_uframe __pad2;
|
||||
struct __snd_timespec64 tstamp; /* Timestamp */
|
||||
__s32 suspended_state; /* RO: suspended stream state */
|
||||
__u32 pad3; /* Needed for 64 bit alignment */
|
||||
struct __snd_timespec64 audio_tstamp; /* sample counter or wall clock */
|
||||
};
|
||||
|
||||
struct __snd_pcm_mmap_control64 {
|
||||
__pad_before_uframe __pad1;
|
||||
snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */
|
||||
__pad_before_uframe __pad2;
|
||||
|
||||
__pad_before_uframe __pad3;
|
||||
snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */
|
||||
__pad_after_uframe __pad4;
|
||||
};
|
||||
|
||||
struct __snd_pcm_sync_ptr64 {
|
||||
__u32 flags;
|
||||
__u32 pad1;
|
||||
union {
|
||||
struct __snd_pcm_mmap_status64 status;
|
||||
unsigned char reserved[64];
|
||||
} s;
|
||||
union {
|
||||
struct __snd_pcm_mmap_control64 control;
|
||||
unsigned char reserved[64];
|
||||
} c;
|
||||
};
|
||||
@ -584,6 +678,8 @@ enum {
|
||||
#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status)
|
||||
#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
|
||||
#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
|
||||
#define __SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct __snd_pcm_sync_ptr)
|
||||
#define __SNDRV_PCM_IOCTL_SYNC_PTR64 _IOWR('A', 0x23, struct __snd_pcm_sync_ptr64)
|
||||
#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
|
||||
#define SNDRV_PCM_IOCTL_STATUS_EXT _IOWR('A', 0x24, struct snd_pcm_status)
|
||||
#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
|
||||
@ -614,7 +710,7 @@ enum {
|
||||
* Raw MIDI section - /dev/snd/midi??
|
||||
*/
|
||||
|
||||
#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0)
|
||||
#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 1)
|
||||
|
||||
enum {
|
||||
SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
|
||||
@ -648,13 +744,16 @@ struct snd_rawmidi_params {
|
||||
unsigned char reserved[16]; /* reserved for future use */
|
||||
};
|
||||
|
||||
#ifndef __KERNEL__
|
||||
struct snd_rawmidi_status {
|
||||
int stream;
|
||||
__time_pad pad1;
|
||||
struct timespec tstamp; /* Timestamp */
|
||||
size_t avail; /* available bytes */
|
||||
size_t xruns; /* count of overruns since last status (in bytes) */
|
||||
unsigned char reserved[16]; /* reserved for future use */
|
||||
};
|
||||
#endif
|
||||
|
||||
#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int)
|
||||
#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info)
|
||||
@ -667,7 +766,7 @@ struct snd_rawmidi_status {
|
||||
* Timer section - /dev/snd/timer
|
||||
*/
|
||||
|
||||
#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
|
||||
#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7)
|
||||
|
||||
enum {
|
||||
SNDRV_TIMER_CLASS_NONE = -1,
|
||||
@ -761,6 +860,7 @@ struct snd_timer_params {
|
||||
unsigned char reserved[60]; /* reserved */
|
||||
};
|
||||
|
||||
#ifndef __KERNEL__
|
||||
struct snd_timer_status {
|
||||
struct timespec tstamp; /* Timestamp - last update */
|
||||
unsigned int resolution; /* current period resolution in ns */
|
||||
@ -769,10 +869,11 @@ struct snd_timer_status {
|
||||
unsigned int queue; /* used queue size */
|
||||
unsigned char reserved[64]; /* reserved */
|
||||
};
|
||||
#endif
|
||||
|
||||
#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
|
||||
#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
|
||||
#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int)
|
||||
#define SNDRV_TIMER_IOCTL_TREAD_OLD _IOW('T', 0x02, int)
|
||||
#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo)
|
||||
#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams)
|
||||
#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus)
|
||||
@ -785,6 +886,15 @@ struct snd_timer_status {
|
||||
#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1)
|
||||
#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
|
||||
#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
|
||||
#define SNDRV_TIMER_IOCTL_TREAD64 _IOW('T', 0xa4, int)
|
||||
|
||||
#if __BITS_PER_LONG == 64
|
||||
#define SNDRV_TIMER_IOCTL_TREAD SNDRV_TIMER_IOCTL_TREAD_OLD
|
||||
#else
|
||||
#define SNDRV_TIMER_IOCTL_TREAD ((sizeof(__kernel_long_t) >= sizeof(time_t)) ? \
|
||||
SNDRV_TIMER_IOCTL_TREAD_OLD : \
|
||||
SNDRV_TIMER_IOCTL_TREAD64)
|
||||
#endif
|
||||
|
||||
struct snd_timer_read {
|
||||
unsigned int resolution;
|
||||
@ -810,11 +920,15 @@ enum {
|
||||
SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
|
||||
};
|
||||
|
||||
#ifndef __KERNEL__
|
||||
struct snd_timer_tread {
|
||||
int event;
|
||||
__time_pad pad1;
|
||||
struct timespec tstamp;
|
||||
unsigned int val;
|
||||
__time_pad pad2;
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* *
|
||||
@ -822,7 +936,7 @@ struct snd_timer_tread {
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7)
|
||||
#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 8)
|
||||
|
||||
struct snd_ctl_card_info {
|
||||
int card; /* card number */
|
||||
@ -860,7 +974,7 @@ typedef int __bitwise snd_ctl_elem_iface_t;
|
||||
#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
|
||||
#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
|
||||
#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2) /* control value may be changed without a notification */
|
||||
#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3) /* when was control changed */
|
||||
// (1 << 3) is unused.
|
||||
#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4) /* TLV read is possible */
|
||||
#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5) /* TLV write is possible */
|
||||
#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
|
||||
@ -926,11 +1040,7 @@ struct snd_ctl_elem_info {
|
||||
} enumerated;
|
||||
unsigned char reserved[128];
|
||||
} value;
|
||||
union {
|
||||
unsigned short d[4]; /* dimensions */
|
||||
unsigned short *d_ptr; /* indirect - obsoleted */
|
||||
} dimen;
|
||||
unsigned char reserved[64-4*sizeof(unsigned short)];
|
||||
unsigned char reserved[64];
|
||||
};
|
||||
|
||||
struct snd_ctl_elem_value {
|
||||
@ -955,8 +1065,7 @@ struct snd_ctl_elem_value {
|
||||
} bytes;
|
||||
struct snd_aes_iec958 iec958;
|
||||
} value; /* RO */
|
||||
struct timespec tstamp;
|
||||
unsigned char reserved[128-sizeof(struct timespec)];
|
||||
unsigned char reserved[128];
|
||||
};
|
||||
|
||||
struct snd_ctl_tlv {
|
||||
|
@ -23,8 +23,9 @@
|
||||
#ifndef _UAPI__SOUND_EMU10K1_H
|
||||
#define _UAPI__SOUND_EMU10K1_H
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/types.h>
|
||||
#include <sound/asound.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ---- FX8010 ----
|
||||
@ -282,8 +283,22 @@ struct snd_emu10k1_fx8010_info {
|
||||
#define EMU10K1_GPR_TRANSLATION_TREBLE 3
|
||||
#define EMU10K1_GPR_TRANSLATION_ONOFF 4
|
||||
|
||||
enum emu10k1_ctl_elem_iface {
|
||||
EMU10K1_CTL_ELEM_IFACE_MIXER = 2, /* virtual mixer device */
|
||||
EMU10K1_CTL_ELEM_IFACE_PCM = 3, /* PCM device */
|
||||
};
|
||||
|
||||
struct emu10k1_ctl_elem_id {
|
||||
unsigned int pad; /* don't use */
|
||||
int iface; /* interface identifier */
|
||||
unsigned int device; /* device/client number */
|
||||
unsigned int subdevice; /* subdevice (substream) number */
|
||||
unsigned char name[44]; /* ASCII name of item */
|
||||
unsigned int index; /* index of item */
|
||||
};
|
||||
|
||||
struct snd_emu10k1_fx8010_control_gpr {
|
||||
struct snd_ctl_elem_id id; /* full control ID definition */
|
||||
struct emu10k1_ctl_elem_id id; /* full control ID definition */
|
||||
unsigned int vcount; /* visible count */
|
||||
unsigned int count; /* count of GPR (1..16) */
|
||||
unsigned short gpr[32]; /* GPR number(s) */
|
||||
@ -296,7 +311,7 @@ struct snd_emu10k1_fx8010_control_gpr {
|
||||
|
||||
/* old ABI without TLV support */
|
||||
struct snd_emu10k1_fx8010_control_old_gpr {
|
||||
struct snd_ctl_elem_id id;
|
||||
struct emu10k1_ctl_elem_id id;
|
||||
unsigned int vcount;
|
||||
unsigned int count;
|
||||
unsigned short gpr[32];
|
||||
@ -310,24 +325,24 @@ struct snd_emu10k1_fx8010_code {
|
||||
char name[128];
|
||||
|
||||
__EMU10K1_DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */
|
||||
__u32 __user *gpr_map; /* initializers */
|
||||
__u32 *gpr_map; /* initializers */
|
||||
|
||||
unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
|
||||
struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */
|
||||
struct snd_emu10k1_fx8010_control_gpr *gpr_add_controls; /* GPR controls to add/replace */
|
||||
|
||||
unsigned int gpr_del_control_count; /* count of GPR controls to remove */
|
||||
struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */
|
||||
struct emu10k1_ctl_elem_id *gpr_del_controls; /* IDs of GPR controls to remove */
|
||||
|
||||
unsigned int gpr_list_control_count; /* count of GPR controls to list */
|
||||
unsigned int gpr_list_control_total; /* total count of GPR controls */
|
||||
struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */
|
||||
struct snd_emu10k1_fx8010_control_gpr *gpr_list_controls; /* listed GPR controls */
|
||||
|
||||
__EMU10K1_DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */
|
||||
__u32 __user *tram_data_map; /* data initializers */
|
||||
__u32 __user *tram_addr_map; /* map initializers */
|
||||
__u32 *tram_data_map; /* data initializers */
|
||||
__u32 *tram_addr_map; /* map initializers */
|
||||
|
||||
__EMU10K1_DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */
|
||||
__u32 __user *code; /* one instruction - 64 bits */
|
||||
__u32 *code; /* one instruction - 64 bits */
|
||||
};
|
||||
|
||||
struct snd_emu10k1_fx8010_tram {
|
||||
@ -371,11 +386,4 @@ struct snd_emu10k1_fx8010_pcm_rec {
|
||||
#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP _IOW ('H', 0x83, int)
|
||||
#define SNDRV_EMU10K1_IOCTL_DBG_READ _IOR ('H', 0x84, int)
|
||||
|
||||
/* typedefs for compatibility to user-space */
|
||||
typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
|
||||
typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
|
||||
typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
|
||||
typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
|
||||
typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
|
||||
|
||||
#endif /* _UAPI__SOUND_EMU10K1_H */
|
||||
|
@ -20,7 +20,9 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/types.h>
|
||||
#endif
|
||||
|
||||
#define HDSP_MATRIX_MIXER_SIZE 2048
|
||||
|
||||
@ -74,7 +76,7 @@ struct hdsp_config_info {
|
||||
#define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, struct hdsp_config_info)
|
||||
|
||||
struct hdsp_firmware {
|
||||
void __user *firmware_data; /* 24413 x 4 bytes */
|
||||
void *firmware_data; /* 24413 x 4 bytes */
|
||||
};
|
||||
|
||||
#define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, struct hdsp_firmware)
|
||||
@ -99,13 +101,4 @@ struct hdsp_9632_aeb {
|
||||
|
||||
#define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, struct hdsp_9632_aeb)
|
||||
|
||||
/* typedefs for compatibility to user-space */
|
||||
typedef enum HDSP_IO_Type HDSP_IO_Type;
|
||||
typedef struct hdsp_peak_rms hdsp_peak_rms_t;
|
||||
typedef struct hdsp_config_info hdsp_config_info_t;
|
||||
typedef struct hdsp_firmware hdsp_firmware_t;
|
||||
typedef struct hdsp_version hdsp_version_t;
|
||||
typedef struct hdsp_mixer hdsp_mixer_t;
|
||||
typedef struct hdsp_9632_aeb hdsp_9632_aeb_t;
|
||||
|
||||
#endif /* __SOUND_HDSP_H */
|
||||
|
@ -21,7 +21,9 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/types.h>
|
||||
#endif
|
||||
|
||||
/* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
|
||||
#define HDSPM_MAX_CHANNELS 64
|
||||
@ -221,12 +223,4 @@ struct hdspm_mixer_ioctl {
|
||||
/* use indirect access due to the limit of ioctl bit size */
|
||||
#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdspm_mixer_ioctl)
|
||||
|
||||
/* typedefs for compatibility to user-space */
|
||||
typedef struct hdspm_peak_rms hdspm_peak_rms_t;
|
||||
typedef struct hdspm_config_info hdspm_config_info_t;
|
||||
typedef struct hdspm_version hdspm_version_t;
|
||||
typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
|
||||
typedef struct hdspm_mixer hdspm_mixer_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
/* SOF ABI version major, minor and patch numbers */
|
||||
#define SOF_ABI_MAJOR 3
|
||||
#define SOF_ABI_MINOR 11
|
||||
#define SOF_ABI_MINOR 12
|
||||
#define SOF_ABI_PATCH 0
|
||||
|
||||
/* SOF ABI version number. Format within 32bit word is MMmmmppp */
|
||||
|
@ -57,6 +57,12 @@
|
||||
#define SOF_TKN_SRC_RATE_IN 300
|
||||
#define SOF_TKN_SRC_RATE_OUT 301
|
||||
|
||||
/* ASRC */
|
||||
#define SOF_TKN_ASRC_RATE_IN 320
|
||||
#define SOF_TKN_ASRC_RATE_OUT 321
|
||||
#define SOF_TKN_ASRC_ASYNCHRONOUS_MODE 322
|
||||
#define SOF_TKN_ASRC_OPERATION_MODE 323
|
||||
|
||||
/* PCM */
|
||||
#define SOF_TKN_PCM_DMAC_CONFIG 353
|
||||
|
||||
@ -107,8 +113,7 @@
|
||||
#define SOF_TKN_EFFECT_TYPE SOF_TKN_PROCESS_TYPE
|
||||
|
||||
/* SAI */
|
||||
#define SOF_TKN_IMX_SAI_FIRST_TOKEN 1000
|
||||
/* TODO: Add SAI tokens */
|
||||
#define SOF_TKN_IMX_SAI_MCLK_ID 1000
|
||||
|
||||
/* ESAI */
|
||||
#define SOF_TKN_IMX_ESAI_MCLK_ID 1100
|
||||
|
@ -53,7 +53,7 @@ static unsigned short compat_ac97_read(struct snd_ac97 *ac97,
|
||||
return actrl->ops->read(actrl, ac97->num, reg);
|
||||
}
|
||||
|
||||
static struct snd_ac97_bus_ops compat_snd_ac97_bus_ops = {
|
||||
static const struct snd_ac97_bus_ops compat_snd_ac97_bus_ops = {
|
||||
.reset = compat_ac97_reset,
|
||||
.warm_reset = compat_ac97_warm_reset,
|
||||
.write = compat_ac97_write,
|
||||
|
@ -55,7 +55,7 @@ static bool snd_ac97_check_id(struct snd_ac97 *ac97, unsigned int id,
|
||||
int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id,
|
||||
unsigned int id_mask)
|
||||
{
|
||||
struct snd_ac97_bus_ops *ops = ac97->bus->ops;
|
||||
const struct snd_ac97_bus_ops *ops = ac97->bus->ops;
|
||||
|
||||
if (try_warm && ops->warm_reset) {
|
||||
ops->warm_reset(ac97);
|
||||
|
@ -116,7 +116,7 @@ struct aoa_card {
|
||||
};
|
||||
|
||||
extern int aoa_snd_device_new(enum snd_device_type type,
|
||||
void * device_data, struct snd_device_ops * ops);
|
||||
void *device_data, const struct snd_device_ops *ops);
|
||||
extern struct snd_card *aoa_get_card(void);
|
||||
extern int aoa_snd_ctl_add(struct snd_kcontrol* control);
|
||||
|
||||
|
@ -97,7 +97,7 @@ static int onyx_dev_register(struct snd_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_register = onyx_dev_register,
|
||||
};
|
||||
|
||||
@ -413,7 +413,7 @@ static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol,
|
||||
}
|
||||
|
||||
#define SINGLE_BIT(n, type, description, address, mask, flags) \
|
||||
static struct snd_kcontrol_new n##_control = { \
|
||||
static const struct snd_kcontrol_new n##_control = { \
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_##type, \
|
||||
.name = description, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
|
||||
@ -543,7 +543,7 @@ static const struct snd_kcontrol_new onyx_spdif_ctrl = {
|
||||
|
||||
/* our registers */
|
||||
|
||||
static u8 register_map[] = {
|
||||
static const u8 register_map[] = {
|
||||
ONYX_REG_DAC_ATTEN_LEFT,
|
||||
ONYX_REG_DAC_ATTEN_RIGHT,
|
||||
ONYX_REG_CONTROL,
|
||||
@ -559,7 +559,7 @@ static u8 register_map[] = {
|
||||
ONYX_REG_DIG_INFO4
|
||||
};
|
||||
|
||||
static u8 initial_values[ARRAY_SIZE(register_map)] = {
|
||||
static const u8 initial_values[ARRAY_SIZE(register_map)] = {
|
||||
0x80, 0x80, /* muted */
|
||||
ONYX_MRST | ONYX_SRST, /* but handled specially! */
|
||||
ONYX_MUTE_LEFT | ONYX_MUTE_RIGHT,
|
||||
|
@ -13,7 +13,7 @@
|
||||
#define TAS3004_TREBLE_ZERO 36
|
||||
#define TAS3004_BASS_ZERO 36
|
||||
|
||||
static u8 tas3004_treble_table[] = {
|
||||
static const u8 tas3004_treble_table[] = {
|
||||
150, /* -18 dB */
|
||||
149,
|
||||
148,
|
||||
@ -99,7 +99,7 @@ static inline u8 tas3004_treble(int idx)
|
||||
* I have also ignored completely differences of
|
||||
* +/- 1
|
||||
*/
|
||||
static s8 tas3004_bass_diff_to_treble[] = {
|
||||
static const s8 tas3004_bass_diff_to_treble[] = {
|
||||
2, /* 7 dB, offset 50 */
|
||||
2,
|
||||
2,
|
||||
|
@ -27,7 +27,7 @@ int main() {
|
||||
* as easy as calculating
|
||||
* hwvalue = 1048576.0*exp(0.057564628*dB*2)
|
||||
* :) */
|
||||
static int tas_gaintable[] = {
|
||||
static const int tas_gaintable[] = {
|
||||
0x000000, /* -infinity dB */
|
||||
0x00014b, /* -70.0 dB */
|
||||
0x00015f, /* -69.5 dB */
|
||||
|
@ -217,7 +217,7 @@ static int tas_dev_register(struct snd_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_register = tas_dev_register,
|
||||
};
|
||||
|
||||
@ -369,7 +369,7 @@ static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol,
|
||||
}
|
||||
|
||||
#define MIXER_CONTROL(n,descr,idx) \
|
||||
static struct snd_kcontrol_new n##_control = { \
|
||||
static const struct snd_kcontrol_new n##_control = { \
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
|
||||
.name = descr " Playback Volume", \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
|
||||
|
@ -30,7 +30,7 @@ static int toonie_dev_register(struct snd_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_register = toonie_dev_register,
|
||||
};
|
||||
|
||||
|
@ -59,7 +59,7 @@ void aoa_alsa_cleanup(void)
|
||||
}
|
||||
|
||||
int aoa_snd_device_new(enum snd_device_type type,
|
||||
void * device_data, struct snd_device_ops * ops)
|
||||
void *device_data, const struct snd_device_ops *ops)
|
||||
{
|
||||
struct snd_card *card = aoa_get_card();
|
||||
int err;
|
||||
|
@ -655,7 +655,7 @@ static int n##_control_put(struct snd_kcontrol *kcontrol, \
|
||||
!!ucontrol->value.integer.value[0]); \
|
||||
return 1; \
|
||||
} \
|
||||
static struct snd_kcontrol_new n##_ctl = { \
|
||||
static const struct snd_kcontrol_new n##_ctl = { \
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
|
||||
.name = description, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
|
||||
|
@ -160,7 +160,7 @@ static int i2sbus_add_dev(struct macio_dev *macio,
|
||||
static const char *rnames[] = { "i2sbus: %pOFn (control)",
|
||||
"i2sbus: %pOFn (tx)",
|
||||
"i2sbus: %pOFn (rx)" };
|
||||
static irq_handler_t ints[] = {
|
||||
static const irq_handler_t ints[] = {
|
||||
i2sbus_bus_intr,
|
||||
i2sbus_tx_intr,
|
||||
i2sbus_rx_intr
|
||||
|
@ -294,12 +294,6 @@ void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int i2sbus_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
|
||||
}
|
||||
|
||||
static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)
|
||||
{
|
||||
struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
|
||||
@ -308,7 +302,6 @@ static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)
|
||||
get_pcm_info(i2sdev, in, &pi, NULL);
|
||||
if (pi->dbdma_ring.stopping)
|
||||
i2sbus_wait_for_stop(i2sdev, pi);
|
||||
snd_pcm_lib_free_pages(substream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -780,8 +773,6 @@ static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substream
|
||||
static const struct snd_pcm_ops i2sbus_playback_ops = {
|
||||
.open = i2sbus_playback_open,
|
||||
.close = i2sbus_playback_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = i2sbus_hw_params,
|
||||
.hw_free = i2sbus_playback_hw_free,
|
||||
.prepare = i2sbus_playback_prepare,
|
||||
.trigger = i2sbus_playback_trigger,
|
||||
@ -850,8 +841,6 @@ static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substream
|
||||
static const struct snd_pcm_ops i2sbus_record_ops = {
|
||||
.open = i2sbus_record_open,
|
||||
.close = i2sbus_record_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = i2sbus_hw_params,
|
||||
.hw_free = i2sbus_record_hw_free,
|
||||
.prepare = i2sbus_record_prepare,
|
||||
.trigger = i2sbus_record_trigger,
|
||||
@ -1026,7 +1015,7 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
|
||||
dev->pcm->private_free = i2sbus_private_free;
|
||||
|
||||
/* well, we really should support scatter/gather DMA */
|
||||
snd_pcm_lib_preallocate_pages_for_all(
|
||||
snd_pcm_set_managed_buffer_all(
|
||||
dev->pcm, SNDRV_DMA_TYPE_DEV,
|
||||
&macio_get_pci_dev(i2sdev->macio)->dev,
|
||||
64 * 1024, 64 * 1024);
|
||||
|
@ -380,7 +380,7 @@ static const struct snd_pcm_hardware aaci_hw_info = {
|
||||
static int aaci_rule_channels(struct snd_pcm_hw_params *p,
|
||||
struct snd_pcm_hw_rule *rule)
|
||||
{
|
||||
static unsigned int channel_list[] = { 2, 4, 6 };
|
||||
static const unsigned int channel_list[] = { 2, 4, 6 };
|
||||
struct aaci *aaci = rule->private;
|
||||
unsigned int mask = 1 << 0, slots;
|
||||
|
||||
@ -483,11 +483,6 @@ static int aaci_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
snd_ac97_pcm_close(aacirun->pcm);
|
||||
aacirun->pcm_open = 0;
|
||||
|
||||
/*
|
||||
* Clear out the DMA and any allocated buffers.
|
||||
*/
|
||||
snd_pcm_lib_free_pages(substream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -502,6 +497,7 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct aaci_runtime *aacirun = substream->runtime->private_data;
|
||||
struct aaci *aaci = substream->private_data;
|
||||
unsigned int channels = params_channels(params);
|
||||
unsigned int rate = params_rate(params);
|
||||
int dbl = rate > 48000;
|
||||
@ -517,25 +513,19 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
if (dbl && channels != 2)
|
||||
return -EINVAL;
|
||||
|
||||
err = snd_pcm_lib_malloc_pages(substream,
|
||||
params_buffer_bytes(params));
|
||||
if (err >= 0) {
|
||||
struct aaci *aaci = substream->private_data;
|
||||
err = snd_ac97_pcm_open(aacirun->pcm, rate, channels,
|
||||
aacirun->pcm->r[dbl].slots);
|
||||
|
||||
err = snd_ac97_pcm_open(aacirun->pcm, rate, channels,
|
||||
aacirun->pcm->r[dbl].slots);
|
||||
aacirun->pcm_open = err == 0;
|
||||
aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
|
||||
aacirun->cr |= channels_to_slotmask[channels + dbl * 2];
|
||||
|
||||
aacirun->pcm_open = err == 0;
|
||||
aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
|
||||
aacirun->cr |= channels_to_slotmask[channels + dbl * 2];
|
||||
|
||||
/*
|
||||
* fifo_bytes is the number of bytes we transfer to/from
|
||||
* the FIFO, including padding. So that's x4. As we're
|
||||
* in compact mode, the FIFO is half the size.
|
||||
*/
|
||||
aacirun->fifo_bytes = aaci->fifo_depth * 4 / 2;
|
||||
}
|
||||
/*
|
||||
* fifo_bytes is the number of bytes we transfer to/from
|
||||
* the FIFO, including padding. So that's x4. As we're
|
||||
* in compact mode, the FIFO is half the size.
|
||||
*/
|
||||
aacirun->fifo_bytes = aaci->fifo_depth * 4 / 2;
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -635,7 +625,6 @@ static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cm
|
||||
static const struct snd_pcm_ops aaci_playback_ops = {
|
||||
.open = aaci_pcm_open,
|
||||
.close = aaci_pcm_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = aaci_pcm_hw_params,
|
||||
.hw_free = aaci_pcm_hw_free,
|
||||
.prepare = aaci_pcm_prepare,
|
||||
@ -738,7 +727,6 @@ static int aaci_pcm_capture_prepare(struct snd_pcm_substream *substream)
|
||||
static const struct snd_pcm_ops aaci_capture_ops = {
|
||||
.open = aaci_pcm_open,
|
||||
.close = aaci_pcm_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = aaci_pcm_hw_params,
|
||||
.hw_free = aaci_pcm_hw_free,
|
||||
.prepare = aaci_pcm_capture_prepare,
|
||||
@ -823,7 +811,7 @@ static const struct ac97_pcm ac97_defs[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct snd_ac97_bus_ops aaci_bus_ops = {
|
||||
static const struct snd_ac97_bus_ops aaci_bus_ops = {
|
||||
.write = aaci_ac97_write,
|
||||
.read = aaci_ac97_read,
|
||||
};
|
||||
@ -937,9 +925,9 @@ static int aaci_init_pcm(struct aaci *aaci)
|
||||
|
||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
|
||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
aaci->card->dev,
|
||||
0, 64 * 1024);
|
||||
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
aaci->card->dev,
|
||||
0, 64 * 1024);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -52,7 +52,7 @@ static void pxa2xx_ac97_legacy_write(struct snd_ac97 *ac97,
|
||||
ret = pxa2xx_ac97_write(ac97->num, reg, val);
|
||||
}
|
||||
|
||||
static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
|
||||
static const struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
|
||||
.read = pxa2xx_ac97_legacy_read,
|
||||
.write = pxa2xx_ac97_legacy_write,
|
||||
.reset = pxa2xx_ac97_legacy_reset,
|
||||
@ -173,7 +173,6 @@ static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops, pxa2xx_ac97_suspend, pxa2xx_ac97_re
|
||||
static const struct snd_pcm_ops pxa2xx_ac97_pcm_ops = {
|
||||
.open = pxa2xx_ac97_pcm_open,
|
||||
.close = pxa2xx_ac97_pcm_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = pxa2xx_pcm_hw_params,
|
||||
.hw_free = pxa2xx_pcm_hw_free,
|
||||
.prepare = pxa2xx_ac97_pcm_prepare,
|
||||
|
@ -159,12 +159,6 @@ static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *hw_params)
|
||||
{
|
||||
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
|
||||
int retval;
|
||||
|
||||
retval = snd_pcm_lib_malloc_pages(substream,
|
||||
params_buffer_bytes(hw_params));
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
/* Set restrictions to params. */
|
||||
mutex_lock(&opened_mutex);
|
||||
@ -172,19 +166,13 @@ static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream,
|
||||
chip->cur_format = params_format(hw_params);
|
||||
mutex_unlock(&opened_mutex);
|
||||
|
||||
return retval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *hw_params)
|
||||
{
|
||||
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
|
||||
int retval;
|
||||
|
||||
retval = snd_pcm_lib_malloc_pages(substream,
|
||||
params_buffer_bytes(hw_params));
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
/* Set restrictions to params. */
|
||||
mutex_lock(&opened_mutex);
|
||||
@ -192,7 +180,7 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream,
|
||||
chip->cur_format = params_format(hw_params);
|
||||
mutex_unlock(&opened_mutex);
|
||||
|
||||
return retval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
|
||||
@ -459,9 +447,7 @@ atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream)
|
||||
static const struct snd_pcm_ops atmel_ac97_playback_ops = {
|
||||
.open = atmel_ac97c_playback_open,
|
||||
.close = atmel_ac97c_playback_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = atmel_ac97c_playback_hw_params,
|
||||
.hw_free = snd_pcm_lib_free_pages,
|
||||
.prepare = atmel_ac97c_playback_prepare,
|
||||
.trigger = atmel_ac97c_playback_trigger,
|
||||
.pointer = atmel_ac97c_playback_pointer,
|
||||
@ -470,9 +456,7 @@ static const struct snd_pcm_ops atmel_ac97_playback_ops = {
|
||||
static const struct snd_pcm_ops atmel_ac97_capture_ops = {
|
||||
.open = atmel_ac97c_capture_open,
|
||||
.close = atmel_ac97c_capture_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = atmel_ac97c_capture_hw_params,
|
||||
.hw_free = snd_pcm_lib_free_pages,
|
||||
.prepare = atmel_ac97c_capture_prepare,
|
||||
.trigger = atmel_ac97c_capture_trigger,
|
||||
.pointer = atmel_ac97c_capture_pointer,
|
||||
@ -600,7 +584,7 @@ static int atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
|
||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &atmel_ac97_capture_ops);
|
||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_ac97_playback_ops);
|
||||
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
&chip->pdev->dev, hw.periods_min * hw.period_bytes_min,
|
||||
hw.buffer_bytes_max);
|
||||
|
||||
@ -718,7 +702,7 @@ static int atmel_ac97c_probe(struct platform_device *pdev)
|
||||
struct atmel_ac97c *chip;
|
||||
struct resource *regs;
|
||||
struct clk *pclk;
|
||||
static struct snd_ac97_bus_ops ops = {
|
||||
static const struct snd_ac97_bus_ops ops = {
|
||||
.write = atmel_ac97c_write,
|
||||
.read = atmel_ac97c_read,
|
||||
};
|
||||
|
@ -178,6 +178,15 @@ config SND_PCM_XRUN_DEBUG
|
||||
sound clicking when system is loaded, it may help to determine
|
||||
the process or driver which causes the scheduling gaps.
|
||||
|
||||
config SND_CTL_VALIDATION
|
||||
bool "Perform sanity-checks for each control element access"
|
||||
depends on SND_DEBUG
|
||||
help
|
||||
Say Y to enable the additional validation of each control element
|
||||
access, including sanity-checks like whether the values returned
|
||||
from the driver are in the proper ranges or the check of the invalid
|
||||
access at out-of-array areas.
|
||||
|
||||
config SND_VMASTER
|
||||
bool
|
||||
|
||||
|
@ -1099,7 +1099,7 @@ static int snd_compress_dev_free(struct snd_device *device)
|
||||
int snd_compress_new(struct snd_card *card, int device,
|
||||
int dirn, const char *id, struct snd_compr *compr)
|
||||
{
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_free = snd_compress_dev_free,
|
||||
.dev_register = snd_compress_dev_register,
|
||||
.dev_disconnect = snd_compress_dev_disconnect,
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/minors.h>
|
||||
@ -248,7 +249,8 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
|
||||
SNDRV_CTL_ELEM_ACCESS_INACTIVE |
|
||||
SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE |
|
||||
SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND |
|
||||
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
|
||||
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK |
|
||||
SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK);
|
||||
|
||||
err = snd_ctl_new(&kctl, count, access, NULL);
|
||||
if (err < 0)
|
||||
@ -758,51 +760,199 @@ static int snd_ctl_elem_list(struct snd_card *card,
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool validate_element_member_dimension(struct snd_ctl_elem_info *info)
|
||||
/* Check whether the given kctl info is valid */
|
||||
static int snd_ctl_check_elem_info(struct snd_card *card,
|
||||
const struct snd_ctl_elem_info *info)
|
||||
{
|
||||
unsigned int members;
|
||||
unsigned int i;
|
||||
static const unsigned int max_value_counts[] = {
|
||||
[SNDRV_CTL_ELEM_TYPE_BOOLEAN] = 128,
|
||||
[SNDRV_CTL_ELEM_TYPE_INTEGER] = 128,
|
||||
[SNDRV_CTL_ELEM_TYPE_ENUMERATED] = 128,
|
||||
[SNDRV_CTL_ELEM_TYPE_BYTES] = 512,
|
||||
[SNDRV_CTL_ELEM_TYPE_IEC958] = 1,
|
||||
[SNDRV_CTL_ELEM_TYPE_INTEGER64] = 64,
|
||||
};
|
||||
|
||||
if (info->dimen.d[0] == 0)
|
||||
return true;
|
||||
|
||||
members = 1;
|
||||
for (i = 0; i < ARRAY_SIZE(info->dimen.d); ++i) {
|
||||
if (info->dimen.d[i] == 0)
|
||||
break;
|
||||
members *= info->dimen.d[i];
|
||||
|
||||
/*
|
||||
* info->count should be validated in advance, to guarantee
|
||||
* calculation soundness.
|
||||
*/
|
||||
if (members > info->count)
|
||||
return false;
|
||||
if (info->type < SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
|
||||
info->type > SNDRV_CTL_ELEM_TYPE_INTEGER64) {
|
||||
if (card)
|
||||
dev_err(card->dev,
|
||||
"control %i:%i:%i:%s:%i: invalid type %d\n",
|
||||
info->id.iface, info->id.device,
|
||||
info->id.subdevice, info->id.name,
|
||||
info->id.index, info->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED &&
|
||||
info->value.enumerated.items == 0) {
|
||||
if (card)
|
||||
dev_err(card->dev,
|
||||
"control %i:%i:%i:%s:%i: zero enum items\n",
|
||||
info->id.iface, info->id.device,
|
||||
info->id.subdevice, info->id.name,
|
||||
info->id.index);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (info->count > max_value_counts[info->type]) {
|
||||
if (card)
|
||||
dev_err(card->dev,
|
||||
"control %i:%i:%i:%s:%i: invalid count %d\n",
|
||||
info->id.iface, info->id.device,
|
||||
info->id.subdevice, info->id.name,
|
||||
info->id.index, info->count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (++i; i < ARRAY_SIZE(info->dimen.d); ++i) {
|
||||
if (info->dimen.d[i] > 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return members == info->count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
|
||||
struct snd_ctl_elem_info *info)
|
||||
/* The capacity of struct snd_ctl_elem_value.value.*/
|
||||
static const unsigned int value_sizes[] = {
|
||||
[SNDRV_CTL_ELEM_TYPE_BOOLEAN] = sizeof(long),
|
||||
[SNDRV_CTL_ELEM_TYPE_INTEGER] = sizeof(long),
|
||||
[SNDRV_CTL_ELEM_TYPE_ENUMERATED] = sizeof(unsigned int),
|
||||
[SNDRV_CTL_ELEM_TYPE_BYTES] = sizeof(unsigned char),
|
||||
[SNDRV_CTL_ELEM_TYPE_IEC958] = sizeof(struct snd_aes_iec958),
|
||||
[SNDRV_CTL_ELEM_TYPE_INTEGER64] = sizeof(long long),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SND_CTL_VALIDATION
|
||||
/* fill the remaining snd_ctl_elem_value data with the given pattern */
|
||||
static void fill_remaining_elem_value(struct snd_ctl_elem_value *control,
|
||||
struct snd_ctl_elem_info *info,
|
||||
u32 pattern)
|
||||
{
|
||||
size_t offset = value_sizes[info->type] * info->count;
|
||||
|
||||
offset = (offset + sizeof(u32) - 1) / sizeof(u32);
|
||||
memset32((u32 *)control->value.bytes.data + offset, pattern,
|
||||
sizeof(control->value) / sizeof(u32) - offset);
|
||||
}
|
||||
|
||||
/* check whether the given integer ctl value is valid */
|
||||
static int sanity_check_int_value(struct snd_card *card,
|
||||
const struct snd_ctl_elem_value *control,
|
||||
const struct snd_ctl_elem_info *info,
|
||||
int i)
|
||||
{
|
||||
long long lval, lmin, lmax, lstep;
|
||||
u64 rem;
|
||||
|
||||
switch (info->type) {
|
||||
default:
|
||||
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
|
||||
lval = control->value.integer.value[i];
|
||||
lmin = 0;
|
||||
lmax = 1;
|
||||
lstep = 0;
|
||||
break;
|
||||
case SNDRV_CTL_ELEM_TYPE_INTEGER:
|
||||
lval = control->value.integer.value[i];
|
||||
lmin = info->value.integer.min;
|
||||
lmax = info->value.integer.max;
|
||||
lstep = info->value.integer.step;
|
||||
break;
|
||||
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
|
||||
lval = control->value.integer64.value[i];
|
||||
lmin = info->value.integer64.min;
|
||||
lmax = info->value.integer64.max;
|
||||
lstep = info->value.integer64.step;
|
||||
break;
|
||||
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
|
||||
lval = control->value.enumerated.item[i];
|
||||
lmin = 0;
|
||||
lmax = info->value.enumerated.items - 1;
|
||||
lstep = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (lval < lmin || lval > lmax) {
|
||||
dev_err(card->dev,
|
||||
"control %i:%i:%i:%s:%i: value out of range %lld (%lld/%lld) at count %i\n",
|
||||
control->id.iface, control->id.device,
|
||||
control->id.subdevice, control->id.name,
|
||||
control->id.index, lval, lmin, lmax, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (lstep) {
|
||||
div64_u64_rem(lval, lstep, &rem);
|
||||
if (rem) {
|
||||
dev_err(card->dev,
|
||||
"control %i:%i:%i:%s:%i: unaligned value %lld (step %lld) at count %i\n",
|
||||
control->id.iface, control->id.device,
|
||||
control->id.subdevice, control->id.name,
|
||||
control->id.index, lval, lstep, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* perform sanity checks to the given snd_ctl_elem_value object */
|
||||
static int sanity_check_elem_value(struct snd_card *card,
|
||||
const struct snd_ctl_elem_value *control,
|
||||
const struct snd_ctl_elem_info *info,
|
||||
u32 pattern)
|
||||
{
|
||||
size_t offset;
|
||||
int i, ret = 0;
|
||||
u32 *p;
|
||||
|
||||
switch (info->type) {
|
||||
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
|
||||
case SNDRV_CTL_ELEM_TYPE_INTEGER:
|
||||
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
|
||||
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
|
||||
for (i = 0; i < info->count; i++) {
|
||||
ret = sanity_check_int_value(card, control, info, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* check whether the remaining area kept untouched */
|
||||
offset = value_sizes[info->type] * info->count;
|
||||
offset = (offset + sizeof(u32) - 1) / sizeof(u32);
|
||||
p = (u32 *)control->value.bytes.data + offset;
|
||||
for (; offset < sizeof(control->value) / sizeof(u32); offset++, p++) {
|
||||
if (*p != pattern) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
*p = 0; /* clear the checked area */
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static inline void fill_remaining_elem_value(struct snd_ctl_elem_value *control,
|
||||
struct snd_ctl_elem_info *info,
|
||||
u32 pattern)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int sanity_check_elem_value(struct snd_card *card,
|
||||
struct snd_ctl_elem_value *control,
|
||||
struct snd_ctl_elem_info *info,
|
||||
u32 pattern)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __snd_ctl_elem_info(struct snd_card *card,
|
||||
struct snd_kcontrol *kctl,
|
||||
struct snd_ctl_elem_info *info,
|
||||
struct snd_ctl_file *ctl)
|
||||
{
|
||||
struct snd_card *card = ctl->card;
|
||||
struct snd_kcontrol *kctl;
|
||||
struct snd_kcontrol_volatile *vd;
|
||||
unsigned int index_offset;
|
||||
int result;
|
||||
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, &info->id);
|
||||
if (kctl == NULL) {
|
||||
up_read(&card->controls_rwsem);
|
||||
return -ENOENT;
|
||||
}
|
||||
#ifdef CONFIG_SND_DEBUG
|
||||
info->access = 0;
|
||||
#endif
|
||||
@ -821,7 +971,26 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
|
||||
} else {
|
||||
info->owner = -1;
|
||||
}
|
||||
if (!snd_ctl_skip_validation(info) &&
|
||||
snd_ctl_check_elem_info(card, info) < 0)
|
||||
result = -EINVAL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
|
||||
struct snd_ctl_elem_info *info)
|
||||
{
|
||||
struct snd_card *card = ctl->card;
|
||||
struct snd_kcontrol *kctl;
|
||||
int result;
|
||||
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, &info->id);
|
||||
if (kctl == NULL)
|
||||
result = -ENOENT;
|
||||
else
|
||||
result = __snd_ctl_elem_info(card, kctl, info, ctl);
|
||||
up_read(&card->controls_rwsem);
|
||||
return result;
|
||||
}
|
||||
@ -840,6 +1009,8 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
|
||||
result = snd_ctl_elem_info(ctl, &info);
|
||||
if (result < 0)
|
||||
return result;
|
||||
/* drop internal access flags */
|
||||
info.access &= ~SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK;
|
||||
if (copy_to_user(_info, &info, sizeof(info)))
|
||||
return -EFAULT;
|
||||
return result;
|
||||
@ -851,6 +1022,9 @@ static int snd_ctl_elem_read(struct snd_card *card,
|
||||
struct snd_kcontrol *kctl;
|
||||
struct snd_kcontrol_volatile *vd;
|
||||
unsigned int index_offset;
|
||||
struct snd_ctl_elem_info info;
|
||||
const u32 pattern = 0xdeadbeef;
|
||||
int ret;
|
||||
|
||||
kctl = snd_ctl_find_id(card, &control->id);
|
||||
if (kctl == NULL)
|
||||
@ -862,7 +1036,31 @@ static int snd_ctl_elem_read(struct snd_card *card,
|
||||
return -EPERM;
|
||||
|
||||
snd_ctl_build_ioff(&control->id, kctl, index_offset);
|
||||
return kctl->get(kctl, control);
|
||||
|
||||
#ifdef CONFIG_SND_CTL_VALIDATION
|
||||
/* info is needed only for validation */
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.id = control->id;
|
||||
ret = __snd_ctl_elem_info(card, kctl, &info, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
if (!snd_ctl_skip_validation(&info))
|
||||
fill_remaining_elem_value(control, &info, pattern);
|
||||
ret = kctl->get(kctl, control);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!snd_ctl_skip_validation(&info) &&
|
||||
sanity_check_elem_value(card, control, &info, pattern) < 0) {
|
||||
dev_err(card->dev,
|
||||
"control %i:%i:%i:%s:%i: access overflow\n",
|
||||
control->id.iface, control->id.device,
|
||||
control->id.subdevice, control->id.name,
|
||||
control->id.index);
|
||||
return -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int snd_ctl_elem_read_user(struct snd_card *card,
|
||||
@ -1203,23 +1401,6 @@ static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol)
|
||||
static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
||||
struct snd_ctl_elem_info *info, int replace)
|
||||
{
|
||||
/* The capacity of struct snd_ctl_elem_value.value.*/
|
||||
static const unsigned int value_sizes[] = {
|
||||
[SNDRV_CTL_ELEM_TYPE_BOOLEAN] = sizeof(long),
|
||||
[SNDRV_CTL_ELEM_TYPE_INTEGER] = sizeof(long),
|
||||
[SNDRV_CTL_ELEM_TYPE_ENUMERATED] = sizeof(unsigned int),
|
||||
[SNDRV_CTL_ELEM_TYPE_BYTES] = sizeof(unsigned char),
|
||||
[SNDRV_CTL_ELEM_TYPE_IEC958] = sizeof(struct snd_aes_iec958),
|
||||
[SNDRV_CTL_ELEM_TYPE_INTEGER64] = sizeof(long long),
|
||||
};
|
||||
static const unsigned int max_value_counts[] = {
|
||||
[SNDRV_CTL_ELEM_TYPE_BOOLEAN] = 128,
|
||||
[SNDRV_CTL_ELEM_TYPE_INTEGER] = 128,
|
||||
[SNDRV_CTL_ELEM_TYPE_ENUMERATED] = 128,
|
||||
[SNDRV_CTL_ELEM_TYPE_BYTES] = 512,
|
||||
[SNDRV_CTL_ELEM_TYPE_IEC958] = 1,
|
||||
[SNDRV_CTL_ELEM_TYPE_INTEGER64] = 64,
|
||||
};
|
||||
struct snd_card *card = file->card;
|
||||
struct snd_kcontrol *kctl;
|
||||
unsigned int count;
|
||||
@ -1271,16 +1452,12 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
||||
* Check information and calculate the size of data specific to
|
||||
* this userspace control.
|
||||
*/
|
||||
if (info->type < SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
|
||||
info->type > SNDRV_CTL_ELEM_TYPE_INTEGER64)
|
||||
return -EINVAL;
|
||||
if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED &&
|
||||
info->value.enumerated.items == 0)
|
||||
return -EINVAL;
|
||||
if (info->count < 1 ||
|
||||
info->count > max_value_counts[info->type])
|
||||
return -EINVAL;
|
||||
if (!validate_element_member_dimension(info))
|
||||
/* pass NULL to card for suppressing error messages */
|
||||
err = snd_ctl_check_elem_info(NULL, info);
|
||||
if (err < 0)
|
||||
return err;
|
||||
/* user-space control doesn't allow zero-size data */
|
||||
if (info->count < 1)
|
||||
return -EINVAL;
|
||||
private_size = value_sizes[info->type] * info->count;
|
||||
|
||||
@ -1430,8 +1607,9 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
|
||||
if (kctl->tlv.c == NULL)
|
||||
return -ENXIO;
|
||||
|
||||
/* When locked, this is unavailable. */
|
||||
if (vd->owner != NULL && vd->owner != file)
|
||||
/* Write and command operations are not allowed for locked element. */
|
||||
if (op_flag != SNDRV_CTL_TLV_OP_READ &&
|
||||
vd->owner != NULL && vd->owner != file)
|
||||
return -EPERM;
|
||||
|
||||
return kctl->tlv.c(kctl, op_flag, size, buf);
|
||||
@ -1854,7 +2032,7 @@ static int snd_ctl_dev_free(struct snd_device *device)
|
||||
*/
|
||||
int snd_ctl_create(struct snd_card *card)
|
||||
{
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_free = snd_ctl_dev_free,
|
||||
.dev_register = snd_ctl_dev_register,
|
||||
.dev_disconnect = snd_ctl_dev_disconnect,
|
||||
|
@ -27,7 +27,7 @@
|
||||
* Return: Zero if successful, or a negative error code on failure.
|
||||
*/
|
||||
int snd_device_new(struct snd_card *card, enum snd_device_type type,
|
||||
void *device_data, struct snd_device_ops *ops)
|
||||
void *device_data, const struct snd_device_ops *ops)
|
||||
{
|
||||
struct snd_device *dev;
|
||||
struct list_head *p;
|
||||
|
@ -353,7 +353,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device,
|
||||
{
|
||||
struct snd_hwdep *hwdep;
|
||||
int err;
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_free = snd_hwdep_dev_free,
|
||||
.dev_register = snd_hwdep_dev_register,
|
||||
.dev_disconnect = snd_hwdep_dev_disconnect,
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
int snd_info_check_reserved_words(const char *str)
|
||||
{
|
||||
static char *reserved[] =
|
||||
static const char * const reserved[] =
|
||||
{
|
||||
"version",
|
||||
"meminfo",
|
||||
@ -35,7 +35,7 @@ int snd_info_check_reserved_words(const char *str)
|
||||
"seq",
|
||||
NULL
|
||||
};
|
||||
char **xstr = reserved;
|
||||
const char * const *xstr = reserved;
|
||||
|
||||
while (*xstr) {
|
||||
if (!strcmp(*xstr, str))
|
||||
|
@ -211,6 +211,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
|
||||
INIT_LIST_HEAD(&card->ctl_files);
|
||||
spin_lock_init(&card->files_lock);
|
||||
INIT_LIST_HEAD(&card->files_list);
|
||||
mutex_init(&card->memory_mutex);
|
||||
#ifdef CONFIG_PM
|
||||
init_waitqueue_head(&card->power_sleep);
|
||||
#endif
|
||||
|
@ -19,7 +19,7 @@ struct snd_jack_kctl {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SND_JACK_INPUT_DEV
|
||||
static int jack_switch_types[SND_JACK_SWITCH_TYPES] = {
|
||||
static const int jack_switch_types[SND_JACK_SWITCH_TYPES] = {
|
||||
SW_HEADPHONE_INSERT,
|
||||
SW_MICROPHONE_INSERT,
|
||||
SW_LINEOUT_INSERT,
|
||||
@ -201,7 +201,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
|
||||
struct snd_jack *jack;
|
||||
struct snd_jack_kctl *jack_kctl = NULL;
|
||||
int err;
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_free = snd_jack_dev_free,
|
||||
#ifdef CONFIG_SND_JACK_INPUT_DEV
|
||||
.dev_register = snd_jack_dev_register,
|
||||
|
@ -486,7 +486,7 @@ struct slot {
|
||||
unsigned int channels;
|
||||
unsigned int numid[SNDRV_MIXER_OSS_ITEM_COUNT];
|
||||
unsigned int capture_item;
|
||||
struct snd_mixer_oss_assign_table *assigned;
|
||||
const struct snd_mixer_oss_assign_table *assigned;
|
||||
unsigned int allocated: 1;
|
||||
};
|
||||
|
||||
@ -934,8 +934,8 @@ static void snd_mixer_oss_slot_free(struct snd_mixer_oss_slot *chn)
|
||||
struct slot *p = chn->private_data;
|
||||
if (p) {
|
||||
if (p->allocated && p->assigned) {
|
||||
kfree(p->assigned->name);
|
||||
kfree(p->assigned);
|
||||
kfree_const(p->assigned->name);
|
||||
kfree_const(p->assigned);
|
||||
}
|
||||
kfree(p);
|
||||
}
|
||||
@ -953,7 +953,7 @@ static void mixer_slot_clear(struct snd_mixer_oss_slot *rslot)
|
||||
/* In a separate function to keep gcc 3.2 happy - do NOT merge this in
|
||||
snd_mixer_oss_build_input! */
|
||||
static int snd_mixer_oss_build_test_all(struct snd_mixer_oss *mixer,
|
||||
struct snd_mixer_oss_assign_table *ptr,
|
||||
const struct snd_mixer_oss_assign_table *ptr,
|
||||
struct slot *slot)
|
||||
{
|
||||
char str[64];
|
||||
@ -1017,7 +1017,9 @@ static int snd_mixer_oss_build_test_all(struct snd_mixer_oss *mixer,
|
||||
* ptr_allocated means the entry is dynamically allocated (change via proc file).
|
||||
* when replace_old = 1, the old entry is replaced with the new one.
|
||||
*/
|
||||
static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mixer_oss_assign_table *ptr, int ptr_allocated, int replace_old)
|
||||
static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer,
|
||||
const struct snd_mixer_oss_assign_table *ptr,
|
||||
int ptr_allocated, int replace_old)
|
||||
{
|
||||
struct slot slot;
|
||||
struct slot *pslot;
|
||||
@ -1107,7 +1109,7 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mix
|
||||
/*
|
||||
*/
|
||||
#define MIXER_VOL(name) [SOUND_MIXER_##name] = #name
|
||||
static char *oss_mixer_names[SNDRV_OSS_MAX_MIXERS] = {
|
||||
static const char * const oss_mixer_names[SNDRV_OSS_MAX_MIXERS] = {
|
||||
MIXER_VOL(VOLUME),
|
||||
MIXER_VOL(BASS),
|
||||
MIXER_VOL(TREBLE),
|
||||
@ -1255,7 +1257,7 @@ static void snd_mixer_oss_proc_done(struct snd_mixer_oss *mixer)
|
||||
|
||||
static void snd_mixer_oss_build(struct snd_mixer_oss *mixer)
|
||||
{
|
||||
static struct snd_mixer_oss_assign_table table[] = {
|
||||
static const struct snd_mixer_oss_assign_table table[] = {
|
||||
{ SOUND_MIXER_VOLUME, "Master", 0 },
|
||||
{ SOUND_MIXER_VOLUME, "Front", 0 }, /* fallback */
|
||||
{ SOUND_MIXER_BASS, "Tone Control - Bass", 0 },
|
||||
|
@ -288,7 +288,7 @@ static int snd_pcm_plug_formats(const struct snd_mask *mask,
|
||||
return snd_mask_test(&formats, (__force int)format);
|
||||
}
|
||||
|
||||
static snd_pcm_format_t preferred_formats[] = {
|
||||
static const snd_pcm_format_t preferred_formats[] = {
|
||||
SNDRV_PCM_FORMAT_S16_LE,
|
||||
SNDRV_PCM_FORMAT_S16_BE,
|
||||
SNDRV_PCM_FORMAT_U16_LE,
|
||||
|
@ -163,7 +163,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
|
||||
|
||||
#define FORMAT(v) [SNDRV_PCM_FORMAT_##v] = #v
|
||||
|
||||
static char *snd_pcm_format_names[] = {
|
||||
static const char * const snd_pcm_format_names[] = {
|
||||
FORMAT(S8),
|
||||
FORMAT(U8),
|
||||
FORMAT(S16_LE),
|
||||
@ -237,12 +237,12 @@ EXPORT_SYMBOL_GPL(snd_pcm_format_name);
|
||||
#define START(v) [SNDRV_PCM_START_##v] = #v
|
||||
#define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v
|
||||
|
||||
static char *snd_pcm_stream_names[] = {
|
||||
static const char * const snd_pcm_stream_names[] = {
|
||||
STREAM(PLAYBACK),
|
||||
STREAM(CAPTURE),
|
||||
};
|
||||
|
||||
static char *snd_pcm_state_names[] = {
|
||||
static const char * const snd_pcm_state_names[] = {
|
||||
STATE(OPEN),
|
||||
STATE(SETUP),
|
||||
STATE(PREPARED),
|
||||
@ -253,7 +253,7 @@ static char *snd_pcm_state_names[] = {
|
||||
STATE(SUSPENDED),
|
||||
};
|
||||
|
||||
static char *snd_pcm_access_names[] = {
|
||||
static const char * const snd_pcm_access_names[] = {
|
||||
ACCESS(MMAP_INTERLEAVED),
|
||||
ACCESS(MMAP_NONINTERLEAVED),
|
||||
ACCESS(MMAP_COMPLEX),
|
||||
@ -261,11 +261,11 @@ static char *snd_pcm_access_names[] = {
|
||||
ACCESS(RW_NONINTERLEAVED),
|
||||
};
|
||||
|
||||
static char *snd_pcm_subformat_names[] = {
|
||||
static const char * const snd_pcm_subformat_names[] = {
|
||||
SUBFORMAT(STD),
|
||||
};
|
||||
|
||||
static char *snd_pcm_tstamp_mode_names[] = {
|
||||
static const char * const snd_pcm_tstamp_mode_names[] = {
|
||||
TSTAMP(NONE),
|
||||
TSTAMP(ENABLE),
|
||||
};
|
||||
@ -443,7 +443,7 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
|
||||
{
|
||||
struct snd_pcm_substream *substream = entry->private_data;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
struct snd_pcm_status status;
|
||||
struct snd_pcm_status64 status;
|
||||
int err;
|
||||
|
||||
mutex_lock(&substream->pcm->open_mutex);
|
||||
@ -453,17 +453,17 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
|
||||
goto unlock;
|
||||
}
|
||||
memset(&status, 0, sizeof(status));
|
||||
err = snd_pcm_status(substream, &status);
|
||||
err = snd_pcm_status64(substream, &status);
|
||||
if (err < 0) {
|
||||
snd_iprintf(buffer, "error %d\n", err);
|
||||
goto unlock;
|
||||
}
|
||||
snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state));
|
||||
snd_iprintf(buffer, "owner_pid : %d\n", pid_vnr(substream->pid));
|
||||
snd_iprintf(buffer, "trigger_time: %ld.%09ld\n",
|
||||
status.trigger_tstamp.tv_sec, status.trigger_tstamp.tv_nsec);
|
||||
snd_iprintf(buffer, "tstamp : %ld.%09ld\n",
|
||||
status.tstamp.tv_sec, status.tstamp.tv_nsec);
|
||||
snd_iprintf(buffer, "trigger_time: %lld.%09lld\n",
|
||||
status.trigger_tstamp_sec, status.trigger_tstamp_nsec);
|
||||
snd_iprintf(buffer, "tstamp : %lld.%09lld\n",
|
||||
status.tstamp_sec, status.tstamp_nsec);
|
||||
snd_iprintf(buffer, "delay : %ld\n", status.delay);
|
||||
snd_iprintf(buffer, "avail : %ld\n", status.avail);
|
||||
snd_iprintf(buffer, "avail_max : %ld\n", status.avail_max);
|
||||
@ -706,12 +706,12 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
|
||||
{
|
||||
struct snd_pcm *pcm;
|
||||
int err;
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_free = snd_pcm_dev_free,
|
||||
.dev_register = snd_pcm_dev_register,
|
||||
.dev_disconnect = snd_pcm_dev_disconnect,
|
||||
};
|
||||
static struct snd_device_ops internal_ops = {
|
||||
static const struct snd_device_ops internal_ops = {
|
||||
.dev_free = snd_pcm_dev_free,
|
||||
};
|
||||
|
||||
|
@ -83,19 +83,6 @@ struct snd_pcm_sw_params32 {
|
||||
unsigned char reserved[56];
|
||||
};
|
||||
|
||||
/* recalcuate the boundary within 32bit */
|
||||
static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime)
|
||||
{
|
||||
snd_pcm_uframes_t boundary;
|
||||
|
||||
if (! runtime->buffer_size)
|
||||
return 0;
|
||||
boundary = runtime->buffer_size;
|
||||
while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
|
||||
boundary *= 2;
|
||||
return boundary;
|
||||
}
|
||||
|
||||
static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_sw_params32 __user *src)
|
||||
{
|
||||
@ -168,10 +155,13 @@ static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
|
||||
snd_pcm_channel_info_user(s, p)
|
||||
#endif /* CONFIG_X86_X32 */
|
||||
|
||||
struct snd_pcm_status32 {
|
||||
struct compat_snd_pcm_status64 {
|
||||
s32 state;
|
||||
struct compat_timespec trigger_tstamp;
|
||||
struct compat_timespec tstamp;
|
||||
u8 rsvd[4]; /* alignment */
|
||||
s64 trigger_tstamp_sec;
|
||||
s64 trigger_tstamp_nsec;
|
||||
s64 tstamp_sec;
|
||||
s64 tstamp_nsec;
|
||||
u32 appl_ptr;
|
||||
u32 hw_ptr;
|
||||
s32 delay;
|
||||
@ -180,85 +170,24 @@ struct snd_pcm_status32 {
|
||||
u32 overrange;
|
||||
s32 suspended_state;
|
||||
u32 audio_tstamp_data;
|
||||
struct compat_timespec audio_tstamp;
|
||||
struct compat_timespec driver_tstamp;
|
||||
s64 audio_tstamp_sec;
|
||||
s64 audio_tstamp_nsec;
|
||||
s64 driver_tstamp_sec;
|
||||
s64 driver_tstamp_nsec;
|
||||
u32 audio_tstamp_accuracy;
|
||||
unsigned char reserved[52-2*sizeof(struct compat_timespec)];
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_status32 __user *src,
|
||||
bool ext)
|
||||
{
|
||||
struct snd_pcm_status status;
|
||||
int err;
|
||||
|
||||
memset(&status, 0, sizeof(status));
|
||||
/*
|
||||
* with extension, parameters are read/write,
|
||||
* get audio_tstamp_data from user,
|
||||
* ignore rest of status structure
|
||||
*/
|
||||
if (ext && get_user(status.audio_tstamp_data,
|
||||
(u32 __user *)(&src->audio_tstamp_data)))
|
||||
return -EFAULT;
|
||||
err = snd_pcm_status(substream, &status);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (clear_user(src, sizeof(*src)))
|
||||
return -EFAULT;
|
||||
if (put_user(status.state, &src->state) ||
|
||||
compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) ||
|
||||
compat_put_timespec(&status.tstamp, &src->tstamp) ||
|
||||
put_user(status.appl_ptr, &src->appl_ptr) ||
|
||||
put_user(status.hw_ptr, &src->hw_ptr) ||
|
||||
put_user(status.delay, &src->delay) ||
|
||||
put_user(status.avail, &src->avail) ||
|
||||
put_user(status.avail_max, &src->avail_max) ||
|
||||
put_user(status.overrange, &src->overrange) ||
|
||||
put_user(status.suspended_state, &src->suspended_state) ||
|
||||
put_user(status.audio_tstamp_data, &src->audio_tstamp_data) ||
|
||||
compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp) ||
|
||||
compat_put_timespec(&status.driver_tstamp, &src->driver_tstamp) ||
|
||||
put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy))
|
||||
return -EFAULT;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_X32
|
||||
/* X32 ABI has 64bit timespec and 64bit alignment */
|
||||
struct snd_pcm_status_x32 {
|
||||
s32 state;
|
||||
u32 rsvd; /* alignment */
|
||||
struct timespec trigger_tstamp;
|
||||
struct timespec tstamp;
|
||||
u32 appl_ptr;
|
||||
u32 hw_ptr;
|
||||
s32 delay;
|
||||
u32 avail;
|
||||
u32 avail_max;
|
||||
u32 overrange;
|
||||
s32 suspended_state;
|
||||
u32 audio_tstamp_data;
|
||||
struct timespec audio_tstamp;
|
||||
struct timespec driver_tstamp;
|
||||
u32 audio_tstamp_accuracy;
|
||||
unsigned char reserved[52-2*sizeof(struct timespec)];
|
||||
unsigned char reserved[52-4*sizeof(s64)];
|
||||
} __packed;
|
||||
|
||||
#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst))
|
||||
|
||||
static int snd_pcm_status_user_x32(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_status_x32 __user *src,
|
||||
bool ext)
|
||||
static int snd_pcm_status_user_compat64(struct snd_pcm_substream *substream,
|
||||
struct compat_snd_pcm_status64 __user *src,
|
||||
bool ext)
|
||||
{
|
||||
struct snd_pcm_status status;
|
||||
struct snd_pcm_status64 status;
|
||||
struct compat_snd_pcm_status64 compat_status64;
|
||||
int err;
|
||||
|
||||
memset(&status, 0, sizeof(status));
|
||||
memset(&compat_status64, 0, sizeof(compat_status64));
|
||||
/*
|
||||
* with extension, parameters are read/write,
|
||||
* get audio_tstamp_data from user,
|
||||
@ -267,31 +196,39 @@ static int snd_pcm_status_user_x32(struct snd_pcm_substream *substream,
|
||||
if (ext && get_user(status.audio_tstamp_data,
|
||||
(u32 __user *)(&src->audio_tstamp_data)))
|
||||
return -EFAULT;
|
||||
err = snd_pcm_status(substream, &status);
|
||||
err = snd_pcm_status64(substream, &status);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (clear_user(src, sizeof(*src)))
|
||||
return -EFAULT;
|
||||
if (put_user(status.state, &src->state) ||
|
||||
put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) ||
|
||||
put_timespec(&status.tstamp, &src->tstamp) ||
|
||||
put_user(status.appl_ptr, &src->appl_ptr) ||
|
||||
put_user(status.hw_ptr, &src->hw_ptr) ||
|
||||
put_user(status.delay, &src->delay) ||
|
||||
put_user(status.avail, &src->avail) ||
|
||||
put_user(status.avail_max, &src->avail_max) ||
|
||||
put_user(status.overrange, &src->overrange) ||
|
||||
put_user(status.suspended_state, &src->suspended_state) ||
|
||||
put_user(status.audio_tstamp_data, &src->audio_tstamp_data) ||
|
||||
put_timespec(&status.audio_tstamp, &src->audio_tstamp) ||
|
||||
put_timespec(&status.driver_tstamp, &src->driver_tstamp) ||
|
||||
put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy))
|
||||
|
||||
compat_status64 = (struct compat_snd_pcm_status64) {
|
||||
.state = status.state,
|
||||
.trigger_tstamp_sec = status.trigger_tstamp_sec,
|
||||
.trigger_tstamp_nsec = status.trigger_tstamp_nsec,
|
||||
.tstamp_sec = status.tstamp_sec,
|
||||
.tstamp_nsec = status.tstamp_nsec,
|
||||
.appl_ptr = status.appl_ptr,
|
||||
.hw_ptr = status.hw_ptr,
|
||||
.delay = status.delay,
|
||||
.avail = status.avail,
|
||||
.avail_max = status.avail_max,
|
||||
.overrange = status.overrange,
|
||||
.suspended_state = status.suspended_state,
|
||||
.audio_tstamp_data = status.audio_tstamp_data,
|
||||
.audio_tstamp_sec = status.audio_tstamp_sec,
|
||||
.audio_tstamp_nsec = status.audio_tstamp_nsec,
|
||||
.driver_tstamp_sec = status.audio_tstamp_sec,
|
||||
.driver_tstamp_nsec = status.audio_tstamp_nsec,
|
||||
.audio_tstamp_accuracy = status.audio_tstamp_accuracy,
|
||||
};
|
||||
|
||||
if (copy_to_user(src, &compat_status64, sizeof(compat_status64)))
|
||||
return -EFAULT;
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_X86_X32 */
|
||||
|
||||
/* both for HW_PARAMS and HW_REFINE */
|
||||
static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
|
||||
@ -436,91 +373,6 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
struct snd_pcm_mmap_status32 {
|
||||
s32 state;
|
||||
s32 pad1;
|
||||
u32 hw_ptr;
|
||||
struct compat_timespec tstamp;
|
||||
s32 suspended_state;
|
||||
struct compat_timespec audio_tstamp;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct snd_pcm_mmap_control32 {
|
||||
u32 appl_ptr;
|
||||
u32 avail_min;
|
||||
};
|
||||
|
||||
struct snd_pcm_sync_ptr32 {
|
||||
u32 flags;
|
||||
union {
|
||||
struct snd_pcm_mmap_status32 status;
|
||||
unsigned char reserved[64];
|
||||
} s;
|
||||
union {
|
||||
struct snd_pcm_mmap_control32 control;
|
||||
unsigned char reserved[64];
|
||||
} c;
|
||||
} __attribute__((packed));
|
||||
|
||||
static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_sync_ptr32 __user *src)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
volatile struct snd_pcm_mmap_status *status;
|
||||
volatile struct snd_pcm_mmap_control *control;
|
||||
u32 sflags;
|
||||
struct snd_pcm_mmap_control scontrol;
|
||||
struct snd_pcm_mmap_status sstatus;
|
||||
snd_pcm_uframes_t boundary;
|
||||
int err;
|
||||
|
||||
if (snd_BUG_ON(!runtime))
|
||||
return -EINVAL;
|
||||
|
||||
if (get_user(sflags, &src->flags) ||
|
||||
get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
|
||||
get_user(scontrol.avail_min, &src->c.control.avail_min))
|
||||
return -EFAULT;
|
||||
if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
|
||||
err = snd_pcm_hwsync(substream);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
status = runtime->status;
|
||||
control = runtime->control;
|
||||
boundary = recalculate_boundary(runtime);
|
||||
if (! boundary)
|
||||
boundary = 0x7fffffff;
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
/* FIXME: we should consider the boundary for the sync from app */
|
||||
if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
|
||||
control->appl_ptr = scontrol.appl_ptr;
|
||||
else
|
||||
scontrol.appl_ptr = control->appl_ptr % boundary;
|
||||
if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
|
||||
control->avail_min = scontrol.avail_min;
|
||||
else
|
||||
scontrol.avail_min = control->avail_min;
|
||||
sstatus.state = status->state;
|
||||
sstatus.hw_ptr = status->hw_ptr % boundary;
|
||||
sstatus.tstamp = status->tstamp;
|
||||
sstatus.suspended_state = status->suspended_state;
|
||||
sstatus.audio_tstamp = status->audio_tstamp;
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
if (put_user(sstatus.state, &src->s.status.state) ||
|
||||
put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
|
||||
compat_put_timespec(&sstatus.tstamp, &src->s.status.tstamp) ||
|
||||
put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
|
||||
compat_put_timespec(&sstatus.audio_tstamp,
|
||||
&src->s.status.audio_tstamp) ||
|
||||
put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
|
||||
put_user(scontrol.avail_min, &src->c.control.avail_min))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_X32
|
||||
/* X32 ABI has 64bit timespec and 64bit alignment */
|
||||
struct snd_pcm_mmap_status_x32 {
|
||||
@ -528,10 +380,12 @@ struct snd_pcm_mmap_status_x32 {
|
||||
s32 pad1;
|
||||
u32 hw_ptr;
|
||||
u32 pad2; /* alignment */
|
||||
struct timespec tstamp;
|
||||
s64 tstamp_sec;
|
||||
s64 tstamp_nsec;
|
||||
s32 suspended_state;
|
||||
s32 pad3;
|
||||
struct timespec audio_tstamp;
|
||||
s64 audio_tstamp_sec;
|
||||
s64 audio_tstamp_nsec;
|
||||
} __packed;
|
||||
|
||||
struct snd_pcm_mmap_control_x32 {
|
||||
@ -599,9 +453,11 @@ static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream,
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
if (put_user(sstatus.state, &src->s.status.state) ||
|
||||
put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
|
||||
put_timespec(&sstatus.tstamp, &src->s.status.tstamp) ||
|
||||
put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp_sec) ||
|
||||
put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp_nsec) ||
|
||||
put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
|
||||
put_timespec(&sstatus.audio_tstamp, &src->s.status.audio_tstamp) ||
|
||||
put_user(sstatus.audio_tstamp.tv_sec, &src->s.status.audio_tstamp_sec) ||
|
||||
put_user(sstatus.audio_tstamp.tv_nsec, &src->s.status.audio_tstamp_nsec) ||
|
||||
put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
|
||||
put_user(scontrol.avail_min, &src->c.control.avail_min))
|
||||
return -EFAULT;
|
||||
@ -616,8 +472,8 @@ enum {
|
||||
SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct snd_pcm_hw_params32),
|
||||
SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32),
|
||||
SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32),
|
||||
SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct snd_pcm_status32),
|
||||
SNDRV_PCM_IOCTL_STATUS_EXT32 = _IOWR('A', 0x24, struct snd_pcm_status32),
|
||||
SNDRV_PCM_IOCTL_STATUS_COMPAT32 = _IOR('A', 0x20, struct snd_pcm_status32),
|
||||
SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32 = _IOWR('A', 0x24, struct snd_pcm_status32),
|
||||
SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32),
|
||||
SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32),
|
||||
SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32),
|
||||
@ -626,11 +482,10 @@ enum {
|
||||
SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct snd_xferi32),
|
||||
SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32),
|
||||
SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32),
|
||||
SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32),
|
||||
SNDRV_PCM_IOCTL_STATUS_COMPAT64 = _IOR('A', 0x20, struct compat_snd_pcm_status64),
|
||||
SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64 = _IOWR('A', 0x24, struct compat_snd_pcm_status64),
|
||||
#ifdef CONFIG_X86_X32
|
||||
SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info),
|
||||
SNDRV_PCM_IOCTL_STATUS_X32 = _IOR('A', 0x20, struct snd_pcm_status_x32),
|
||||
SNDRV_PCM_IOCTL_STATUS_EXT_X32 = _IOWR('A', 0x24, struct snd_pcm_status_x32),
|
||||
SNDRV_PCM_IOCTL_SYNC_PTR_X32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr_x32),
|
||||
#endif /* CONFIG_X86_X32 */
|
||||
};
|
||||
@ -650,8 +505,8 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
|
||||
|
||||
/*
|
||||
* When PCM is used on 32bit mode, we need to disable
|
||||
* mmap of PCM status/control records because of the size
|
||||
* incompatibility.
|
||||
* mmap of the old PCM status/control records because
|
||||
* of the size incompatibility.
|
||||
*/
|
||||
pcm_file->no_compat_mmap = 1;
|
||||
|
||||
@ -673,6 +528,13 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
|
||||
case SNDRV_PCM_IOCTL_XRUN:
|
||||
case SNDRV_PCM_IOCTL_LINK:
|
||||
case SNDRV_PCM_IOCTL_UNLINK:
|
||||
case __SNDRV_PCM_IOCTL_SYNC_PTR32:
|
||||
return snd_pcm_common_ioctl(file, substream, cmd, argp);
|
||||
case __SNDRV_PCM_IOCTL_SYNC_PTR64:
|
||||
#ifdef CONFIG_X86_X32
|
||||
if (in_x32_syscall())
|
||||
return snd_pcm_ioctl_sync_ptr_x32(substream, argp);
|
||||
#endif /* CONFIG_X86_X32 */
|
||||
return snd_pcm_common_ioctl(file, substream, cmd, argp);
|
||||
case SNDRV_PCM_IOCTL_HW_REFINE32:
|
||||
return snd_pcm_ioctl_hw_params_compat(substream, 1, argp);
|
||||
@ -680,12 +542,10 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
|
||||
return snd_pcm_ioctl_hw_params_compat(substream, 0, argp);
|
||||
case SNDRV_PCM_IOCTL_SW_PARAMS32:
|
||||
return snd_pcm_ioctl_sw_params_compat(substream, argp);
|
||||
case SNDRV_PCM_IOCTL_STATUS32:
|
||||
return snd_pcm_status_user_compat(substream, argp, false);
|
||||
case SNDRV_PCM_IOCTL_STATUS_EXT32:
|
||||
return snd_pcm_status_user_compat(substream, argp, true);
|
||||
case SNDRV_PCM_IOCTL_SYNC_PTR32:
|
||||
return snd_pcm_ioctl_sync_ptr_compat(substream, argp);
|
||||
case SNDRV_PCM_IOCTL_STATUS_COMPAT32:
|
||||
return snd_pcm_status_user32(substream, argp, false);
|
||||
case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32:
|
||||
return snd_pcm_status_user32(substream, argp, true);
|
||||
case SNDRV_PCM_IOCTL_CHANNEL_INFO32:
|
||||
return snd_pcm_ioctl_channel_info_compat(substream, argp);
|
||||
case SNDRV_PCM_IOCTL_WRITEI_FRAMES32:
|
||||
@ -702,13 +562,11 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
|
||||
return snd_pcm_ioctl_rewind_compat(substream, argp);
|
||||
case SNDRV_PCM_IOCTL_FORWARD32:
|
||||
return snd_pcm_ioctl_forward_compat(substream, argp);
|
||||
case SNDRV_PCM_IOCTL_STATUS_COMPAT64:
|
||||
return snd_pcm_status_user_compat64(substream, argp, false);
|
||||
case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64:
|
||||
return snd_pcm_status_user_compat64(substream, argp, true);
|
||||
#ifdef CONFIG_X86_X32
|
||||
case SNDRV_PCM_IOCTL_STATUS_X32:
|
||||
return snd_pcm_status_user_x32(substream, argp, false);
|
||||
case SNDRV_PCM_IOCTL_STATUS_EXT_X32:
|
||||
return snd_pcm_status_user_x32(substream, argp, true);
|
||||
case SNDRV_PCM_IOCTL_SYNC_PTR_X32:
|
||||
return snd_pcm_ioctl_sync_ptr_x32(substream, argp);
|
||||
case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32:
|
||||
return snd_pcm_ioctl_channel_info_x32(substream, argp);
|
||||
#endif /* CONFIG_X86_X32 */
|
||||
|
@ -144,8 +144,13 @@ void __snd_pcm_xrun(struct snd_pcm_substream *substream)
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
|
||||
trace_xrun(substream);
|
||||
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
|
||||
snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
|
||||
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
|
||||
struct timespec64 tstamp;
|
||||
|
||||
snd_pcm_gettime(runtime, &tstamp);
|
||||
runtime->status->tstamp.tv_sec = tstamp.tv_sec;
|
||||
runtime->status->tstamp.tv_nsec = tstamp.tv_nsec;
|
||||
}
|
||||
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
|
||||
if (xrun_debug(substream, XRUN_DEBUG_BASIC)) {
|
||||
char name[16];
|
||||
@ -200,12 +205,12 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
|
||||
}
|
||||
|
||||
static void update_audio_tstamp(struct snd_pcm_substream *substream,
|
||||
struct timespec *curr_tstamp,
|
||||
struct timespec *audio_tstamp)
|
||||
struct timespec64 *curr_tstamp,
|
||||
struct timespec64 *audio_tstamp)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
u64 audio_frames, audio_nsecs;
|
||||
struct timespec driver_tstamp;
|
||||
struct timespec64 driver_tstamp;
|
||||
|
||||
if (runtime->tstamp_mode != SNDRV_PCM_TSTAMP_ENABLE)
|
||||
return;
|
||||
@ -229,18 +234,23 @@ static void update_audio_tstamp(struct snd_pcm_substream *substream,
|
||||
}
|
||||
audio_nsecs = div_u64(audio_frames * 1000000000LL,
|
||||
runtime->rate);
|
||||
*audio_tstamp = ns_to_timespec(audio_nsecs);
|
||||
*audio_tstamp = ns_to_timespec64(audio_nsecs);
|
||||
}
|
||||
if (!timespec_equal(&runtime->status->audio_tstamp, audio_tstamp)) {
|
||||
runtime->status->audio_tstamp = *audio_tstamp;
|
||||
runtime->status->tstamp = *curr_tstamp;
|
||||
|
||||
if (runtime->status->audio_tstamp.tv_sec != audio_tstamp->tv_sec ||
|
||||
runtime->status->audio_tstamp.tv_nsec != audio_tstamp->tv_nsec) {
|
||||
runtime->status->audio_tstamp.tv_sec = audio_tstamp->tv_sec;
|
||||
runtime->status->audio_tstamp.tv_nsec = audio_tstamp->tv_nsec;
|
||||
runtime->status->tstamp.tv_sec = curr_tstamp->tv_sec;
|
||||
runtime->status->tstamp.tv_nsec = curr_tstamp->tv_nsec;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* re-take a driver timestamp to let apps detect if the reference tstamp
|
||||
* read by low-level hardware was provided with a delay
|
||||
*/
|
||||
snd_pcm_gettime(substream->runtime, (struct timespec *)&driver_tstamp);
|
||||
snd_pcm_gettime(substream->runtime, &driver_tstamp);
|
||||
runtime->driver_tstamp = driver_tstamp;
|
||||
}
|
||||
|
||||
@ -253,8 +263,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
|
||||
snd_pcm_sframes_t hdelta, delta;
|
||||
unsigned long jdelta;
|
||||
unsigned long curr_jiffies;
|
||||
struct timespec curr_tstamp;
|
||||
struct timespec audio_tstamp;
|
||||
struct timespec64 curr_tstamp;
|
||||
struct timespec64 audio_tstamp;
|
||||
int crossed_boundary = 0;
|
||||
|
||||
old_hw_ptr = runtime->status->hw_ptr;
|
||||
@ -277,9 +287,9 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
|
||||
|
||||
/* re-test in case tstamp type is not supported in hardware and was demoted to DEFAULT */
|
||||
if (runtime->audio_tstamp_report.actual_type == SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT)
|
||||
snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp);
|
||||
snd_pcm_gettime(runtime, &curr_tstamp);
|
||||
} else
|
||||
snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp);
|
||||
snd_pcm_gettime(runtime, &curr_tstamp);
|
||||
}
|
||||
|
||||
if (pos == SNDRV_PCM_POS_XRUN) {
|
||||
@ -1442,7 +1452,7 @@ EXPORT_SYMBOL(snd_pcm_hw_constraint_step);
|
||||
|
||||
static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
|
||||
{
|
||||
static unsigned int pow2_sizes[] = {
|
||||
static const unsigned int pow2_sizes[] = {
|
||||
1<<0, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7,
|
||||
1<<8, 1<<9, 1<<10, 1<<11, 1<<12, 1<<13, 1<<14, 1<<15,
|
||||
1<<16, 1<<17, 1<<18, 1<<19, 1<<20, 1<<21, 1<<22, 1<<23,
|
||||
@ -2308,7 +2318,6 @@ static int pcm_chmap_ctl_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->count = 0;
|
||||
uinfo->count = info->max_channels;
|
||||
uinfo->value.integer.min = 0;
|
||||
uinfo->value.integer.max = SNDRV_CHMAP_LAST;
|
||||
@ -2332,7 +2341,7 @@ static int pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
|
||||
if (!substream)
|
||||
return -ENODEV;
|
||||
memset(ucontrol->value.integer.value, 0,
|
||||
sizeof(ucontrol->value.integer.value));
|
||||
sizeof(long) * info->max_channels);
|
||||
if (!substream->runtime)
|
||||
return 0; /* no channels set */
|
||||
for (map = info->chmap; map->channels; map++) {
|
||||
|
@ -20,9 +20,6 @@ void snd_interval_muldivk(const struct snd_interval *a,
|
||||
void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
|
||||
const struct snd_interval *b, struct snd_interval *c);
|
||||
|
||||
int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream);
|
||||
int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream);
|
||||
|
||||
int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime,
|
||||
snd_pcm_hw_param_t var, u_int32_t mask);
|
||||
|
||||
|
@ -27,6 +27,38 @@ MODULE_PARM_DESC(maximum_substreams, "Maximum substreams with preallocated DMA m
|
||||
|
||||
static const size_t snd_minimum_buffer = 16384;
|
||||
|
||||
static unsigned long max_alloc_per_card = 32UL * 1024UL * 1024UL;
|
||||
module_param(max_alloc_per_card, ulong, 0644);
|
||||
MODULE_PARM_DESC(max_alloc_per_card, "Max total allocation bytes per card.");
|
||||
|
||||
static int do_alloc_pages(struct snd_card *card, int type, struct device *dev,
|
||||
size_t size, struct snd_dma_buffer *dmab)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (max_alloc_per_card &&
|
||||
card->total_pcm_alloc_bytes + size > max_alloc_per_card)
|
||||
return -ENOMEM;
|
||||
err = snd_dma_alloc_pages(type, dev, size, dmab);
|
||||
if (!err) {
|
||||
mutex_lock(&card->memory_mutex);
|
||||
card->total_pcm_alloc_bytes += dmab->bytes;
|
||||
mutex_unlock(&card->memory_mutex);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void do_free_pages(struct snd_card *card, struct snd_dma_buffer *dmab)
|
||||
{
|
||||
if (!dmab->area)
|
||||
return;
|
||||
mutex_lock(&card->memory_mutex);
|
||||
WARN_ON(card->total_pcm_alloc_bytes < dmab->bytes);
|
||||
card->total_pcm_alloc_bytes -= dmab->bytes;
|
||||
mutex_unlock(&card->memory_mutex);
|
||||
snd_dma_free_pages(dmab);
|
||||
dmab->area = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* try to allocate as the large pages as possible.
|
||||
@ -37,16 +69,15 @@ static const size_t snd_minimum_buffer = 16384;
|
||||
static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t size)
|
||||
{
|
||||
struct snd_dma_buffer *dmab = &substream->dma_buffer;
|
||||
struct snd_card *card = substream->pcm->card;
|
||||
size_t orig_size = size;
|
||||
int err;
|
||||
|
||||
do {
|
||||
if ((err = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev,
|
||||
size, dmab)) < 0) {
|
||||
if (err != -ENOMEM)
|
||||
return err; /* fatal error */
|
||||
} else
|
||||
return 0;
|
||||
err = do_alloc_pages(card, dmab->dev.type, dmab->dev.dev,
|
||||
size, dmab);
|
||||
if (err != -ENOMEM)
|
||||
return err;
|
||||
size >>= 1;
|
||||
} while (size >= snd_minimum_buffer);
|
||||
dmab->bytes = 0; /* tell error */
|
||||
@ -62,10 +93,7 @@ static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t siz
|
||||
*/
|
||||
static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
if (substream->dma_buffer.area == NULL)
|
||||
return;
|
||||
snd_dma_free_pages(&substream->dma_buffer);
|
||||
substream->dma_buffer.area = NULL;
|
||||
do_free_pages(substream->pcm->card, &substream->dma_buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,6 +158,7 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
struct snd_pcm_substream *substream = entry->private_data;
|
||||
struct snd_card *card = substream->pcm->card;
|
||||
char line[64], str[64];
|
||||
size_t size;
|
||||
struct snd_dma_buffer new_dmab;
|
||||
@ -150,9 +179,10 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
|
||||
memset(&new_dmab, 0, sizeof(new_dmab));
|
||||
new_dmab.dev = substream->dma_buffer.dev;
|
||||
if (size > 0) {
|
||||
if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
|
||||
substream->dma_buffer.dev.dev,
|
||||
size, &new_dmab) < 0) {
|
||||
if (do_alloc_pages(card,
|
||||
substream->dma_buffer.dev.type,
|
||||
substream->dma_buffer.dev.dev,
|
||||
size, &new_dmab) < 0) {
|
||||
buffer->error = -ENOMEM;
|
||||
return;
|
||||
}
|
||||
@ -161,7 +191,7 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
|
||||
substream->buffer_bytes_max = UINT_MAX;
|
||||
}
|
||||
if (substream->dma_buffer.area)
|
||||
snd_dma_free_pages(&substream->dma_buffer);
|
||||
do_free_pages(card, &substream->dma_buffer);
|
||||
substream->dma_buffer = new_dmab;
|
||||
} else {
|
||||
buffer->error = -EINVAL;
|
||||
@ -346,6 +376,7 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne
|
||||
*/
|
||||
int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
|
||||
{
|
||||
struct snd_card *card = substream->pcm->card;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
struct snd_dma_buffer *dmab = NULL;
|
||||
|
||||
@ -374,9 +405,10 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
|
||||
if (! dmab)
|
||||
return -ENOMEM;
|
||||
dmab->dev = substream->dma_buffer.dev;
|
||||
if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
|
||||
substream->dma_buffer.dev.dev,
|
||||
size, dmab) < 0) {
|
||||
if (do_alloc_pages(card,
|
||||
substream->dma_buffer.dev.type,
|
||||
substream->dma_buffer.dev.dev,
|
||||
size, dmab) < 0) {
|
||||
kfree(dmab);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -397,6 +429,7 @@ EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
|
||||
*/
|
||||
int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_card *card = substream->pcm->card;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
|
||||
if (PCM_RUNTIME_CHECK(substream))
|
||||
@ -406,7 +439,7 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
|
||||
return 0;
|
||||
if (runtime->dma_buffer_p != &substream->dma_buffer) {
|
||||
/* it's a newly allocated buffer. release it now. */
|
||||
snd_dma_free_pages(runtime->dma_buffer_p);
|
||||
do_free_pages(card, runtime->dma_buffer_p);
|
||||
kfree(runtime->dma_buffer_p);
|
||||
}
|
||||
snd_pcm_set_runtime_buffer(substream, NULL);
|
||||
|
@ -42,7 +42,7 @@ struct pcm_format_data {
|
||||
/* we do lots of calculations on snd_pcm_format_t; shut up sparse */
|
||||
#define INT __force int
|
||||
|
||||
static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
|
||||
static const struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
|
||||
[SNDRV_PCM_FORMAT_S8] = {
|
||||
.width = 8, .phys = 8, .le = -1, .signd = 1,
|
||||
.silence = {},
|
||||
@ -415,7 +415,8 @@ EXPORT_SYMBOL(snd_pcm_format_silence_64);
|
||||
int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
|
||||
{
|
||||
int width;
|
||||
unsigned char *dst, *pat;
|
||||
unsigned char *dst;
|
||||
const unsigned char *pat;
|
||||
|
||||
if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
|
||||
return -EINVAL;
|
||||
|
@ -4,6 +4,7 @@
|
||||
* Copyright (c) by Jaroslav Kysela <perex@perex.cz>
|
||||
*/
|
||||
|
||||
#include <linux/compat.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/file.h>
|
||||
@ -895,8 +896,8 @@ snd_pcm_calc_delay(struct snd_pcm_substream *substream)
|
||||
return delay + substream->runtime->delay;
|
||||
}
|
||||
|
||||
int snd_pcm_status(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_status *status)
|
||||
int snd_pcm_status64(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_status64 *status)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
|
||||
@ -922,14 +923,22 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
|
||||
status->suspended_state = runtime->status->suspended_state;
|
||||
if (status->state == SNDRV_PCM_STATE_OPEN)
|
||||
goto _end;
|
||||
status->trigger_tstamp = runtime->trigger_tstamp;
|
||||
status->trigger_tstamp_sec = runtime->trigger_tstamp.tv_sec;
|
||||
status->trigger_tstamp_nsec = runtime->trigger_tstamp.tv_nsec;
|
||||
if (snd_pcm_running(substream)) {
|
||||
snd_pcm_update_hw_ptr(substream);
|
||||
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
|
||||
status->tstamp = runtime->status->tstamp;
|
||||
status->driver_tstamp = runtime->driver_tstamp;
|
||||
status->audio_tstamp =
|
||||
runtime->status->audio_tstamp;
|
||||
status->tstamp_sec = runtime->status->tstamp.tv_sec;
|
||||
status->tstamp_nsec =
|
||||
runtime->status->tstamp.tv_nsec;
|
||||
status->driver_tstamp_sec =
|
||||
runtime->driver_tstamp.tv_sec;
|
||||
status->driver_tstamp_nsec =
|
||||
runtime->driver_tstamp.tv_nsec;
|
||||
status->audio_tstamp_sec =
|
||||
runtime->status->audio_tstamp.tv_sec;
|
||||
status->audio_tstamp_nsec =
|
||||
runtime->status->audio_tstamp.tv_nsec;
|
||||
if (runtime->audio_tstamp_report.valid == 1)
|
||||
/* backwards compatibility, no report provided in COMPAT mode */
|
||||
snd_pcm_pack_audio_tstamp_report(&status->audio_tstamp_data,
|
||||
@ -940,8 +949,13 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
|
||||
}
|
||||
} else {
|
||||
/* get tstamp only in fallback mode and only if enabled */
|
||||
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
|
||||
snd_pcm_gettime(runtime, &status->tstamp);
|
||||
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
|
||||
struct timespec64 tstamp;
|
||||
|
||||
snd_pcm_gettime(runtime, &tstamp);
|
||||
status->tstamp_sec = tstamp.tv_sec;
|
||||
status->tstamp_nsec = tstamp.tv_nsec;
|
||||
}
|
||||
}
|
||||
_tstamp_end:
|
||||
status->appl_ptr = runtime->control->appl_ptr;
|
||||
@ -958,11 +972,11 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_status_user(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_status __user * _status,
|
||||
bool ext)
|
||||
static int snd_pcm_status_user64(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_status64 __user * _status,
|
||||
bool ext)
|
||||
{
|
||||
struct snd_pcm_status status;
|
||||
struct snd_pcm_status64 status;
|
||||
int res;
|
||||
|
||||
memset(&status, 0, sizeof(status));
|
||||
@ -974,7 +988,7 @@ static int snd_pcm_status_user(struct snd_pcm_substream *substream,
|
||||
if (ext && get_user(status.audio_tstamp_data,
|
||||
(u32 __user *)(&_status->audio_tstamp_data)))
|
||||
return -EFAULT;
|
||||
res = snd_pcm_status(substream, &status);
|
||||
res = snd_pcm_status64(substream, &status);
|
||||
if (res < 0)
|
||||
return res;
|
||||
if (copy_to_user(_status, &status, sizeof(status)))
|
||||
@ -982,6 +996,55 @@ static int snd_pcm_status_user(struct snd_pcm_substream *substream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_status_user32(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_status32 __user * _status,
|
||||
bool ext)
|
||||
{
|
||||
struct snd_pcm_status64 status64;
|
||||
struct snd_pcm_status32 status32;
|
||||
int res;
|
||||
|
||||
memset(&status64, 0, sizeof(status64));
|
||||
memset(&status32, 0, sizeof(status32));
|
||||
/*
|
||||
* with extension, parameters are read/write,
|
||||
* get audio_tstamp_data from user,
|
||||
* ignore rest of status structure
|
||||
*/
|
||||
if (ext && get_user(status64.audio_tstamp_data,
|
||||
(u32 __user *)(&_status->audio_tstamp_data)))
|
||||
return -EFAULT;
|
||||
res = snd_pcm_status64(substream, &status64);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
status32 = (struct snd_pcm_status32) {
|
||||
.state = status64.state,
|
||||
.trigger_tstamp_sec = status64.trigger_tstamp_sec,
|
||||
.trigger_tstamp_nsec = status64.trigger_tstamp_nsec,
|
||||
.tstamp_sec = status64.tstamp_sec,
|
||||
.tstamp_nsec = status64.tstamp_nsec,
|
||||
.appl_ptr = status64.appl_ptr,
|
||||
.hw_ptr = status64.hw_ptr,
|
||||
.delay = status64.delay,
|
||||
.avail = status64.avail,
|
||||
.avail_max = status64.avail_max,
|
||||
.overrange = status64.overrange,
|
||||
.suspended_state = status64.suspended_state,
|
||||
.audio_tstamp_data = status64.audio_tstamp_data,
|
||||
.audio_tstamp_sec = status64.audio_tstamp_sec,
|
||||
.audio_tstamp_nsec = status64.audio_tstamp_nsec,
|
||||
.driver_tstamp_sec = status64.audio_tstamp_sec,
|
||||
.driver_tstamp_nsec = status64.audio_tstamp_nsec,
|
||||
.audio_tstamp_accuracy = status64.audio_tstamp_accuracy,
|
||||
};
|
||||
|
||||
if (copy_to_user(_status, &status32, sizeof(status32)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_channel_info(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_channel_info * info)
|
||||
{
|
||||
@ -2245,7 +2308,7 @@ static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params,
|
||||
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
|
||||
}
|
||||
|
||||
int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
|
||||
static int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
|
||||
@ -2369,7 +2432,7 @@ int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
|
||||
static int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_pcm_hardware *hw = &runtime->hw;
|
||||
@ -2830,6 +2893,107 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_pcm_mmap_status32 {
|
||||
s32 state;
|
||||
s32 pad1;
|
||||
u32 hw_ptr;
|
||||
s32 tstamp_sec;
|
||||
s32 tstamp_nsec;
|
||||
s32 suspended_state;
|
||||
s32 audio_tstamp_sec;
|
||||
s32 audio_tstamp_nsec;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct snd_pcm_mmap_control32 {
|
||||
u32 appl_ptr;
|
||||
u32 avail_min;
|
||||
};
|
||||
|
||||
struct snd_pcm_sync_ptr32 {
|
||||
u32 flags;
|
||||
union {
|
||||
struct snd_pcm_mmap_status32 status;
|
||||
unsigned char reserved[64];
|
||||
} s;
|
||||
union {
|
||||
struct snd_pcm_mmap_control32 control;
|
||||
unsigned char reserved[64];
|
||||
} c;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* recalcuate the boundary within 32bit */
|
||||
static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime)
|
||||
{
|
||||
snd_pcm_uframes_t boundary;
|
||||
|
||||
if (! runtime->buffer_size)
|
||||
return 0;
|
||||
boundary = runtime->buffer_size;
|
||||
while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
|
||||
boundary *= 2;
|
||||
return boundary;
|
||||
}
|
||||
|
||||
static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_sync_ptr32 __user *src)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
volatile struct snd_pcm_mmap_status *status;
|
||||
volatile struct snd_pcm_mmap_control *control;
|
||||
u32 sflags;
|
||||
struct snd_pcm_mmap_control scontrol;
|
||||
struct snd_pcm_mmap_status sstatus;
|
||||
snd_pcm_uframes_t boundary;
|
||||
int err;
|
||||
|
||||
if (snd_BUG_ON(!runtime))
|
||||
return -EINVAL;
|
||||
|
||||
if (get_user(sflags, &src->flags) ||
|
||||
get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
|
||||
get_user(scontrol.avail_min, &src->c.control.avail_min))
|
||||
return -EFAULT;
|
||||
if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
|
||||
err = snd_pcm_hwsync(substream);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
status = runtime->status;
|
||||
control = runtime->control;
|
||||
boundary = recalculate_boundary(runtime);
|
||||
if (! boundary)
|
||||
boundary = 0x7fffffff;
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
/* FIXME: we should consider the boundary for the sync from app */
|
||||
if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
|
||||
control->appl_ptr = scontrol.appl_ptr;
|
||||
else
|
||||
scontrol.appl_ptr = control->appl_ptr % boundary;
|
||||
if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
|
||||
control->avail_min = scontrol.avail_min;
|
||||
else
|
||||
scontrol.avail_min = control->avail_min;
|
||||
sstatus.state = status->state;
|
||||
sstatus.hw_ptr = status->hw_ptr % boundary;
|
||||
sstatus.tstamp = status->tstamp;
|
||||
sstatus.suspended_state = status->suspended_state;
|
||||
sstatus.audio_tstamp = status->audio_tstamp;
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
if (put_user(sstatus.state, &src->s.status.state) ||
|
||||
put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
|
||||
put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp_sec) ||
|
||||
put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp_nsec) ||
|
||||
put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
|
||||
put_user(sstatus.audio_tstamp.tv_sec, &src->s.status.audio_tstamp_sec) ||
|
||||
put_user(sstatus.audio_tstamp.tv_nsec, &src->s.status.audio_tstamp_nsec) ||
|
||||
put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
|
||||
put_user(scontrol.avail_min, &src->c.control.avail_min))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#define __SNDRV_PCM_IOCTL_SYNC_PTR32 _IOWR('A', 0x23, struct snd_pcm_sync_ptr32)
|
||||
|
||||
static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
@ -2959,10 +3123,14 @@ static int snd_pcm_common_ioctl(struct file *file,
|
||||
return snd_pcm_hw_free(substream);
|
||||
case SNDRV_PCM_IOCTL_SW_PARAMS:
|
||||
return snd_pcm_sw_params_user(substream, arg);
|
||||
case SNDRV_PCM_IOCTL_STATUS:
|
||||
return snd_pcm_status_user(substream, arg, false);
|
||||
case SNDRV_PCM_IOCTL_STATUS_EXT:
|
||||
return snd_pcm_status_user(substream, arg, true);
|
||||
case SNDRV_PCM_IOCTL_STATUS32:
|
||||
return snd_pcm_status_user32(substream, arg, false);
|
||||
case SNDRV_PCM_IOCTL_STATUS_EXT32:
|
||||
return snd_pcm_status_user32(substream, arg, true);
|
||||
case SNDRV_PCM_IOCTL_STATUS64:
|
||||
return snd_pcm_status_user64(substream, arg, false);
|
||||
case SNDRV_PCM_IOCTL_STATUS_EXT64:
|
||||
return snd_pcm_status_user64(substream, arg, true);
|
||||
case SNDRV_PCM_IOCTL_CHANNEL_INFO:
|
||||
return snd_pcm_channel_info_user(substream, arg);
|
||||
case SNDRV_PCM_IOCTL_PREPARE:
|
||||
@ -2994,7 +3162,9 @@ static int snd_pcm_common_ioctl(struct file *file,
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
case SNDRV_PCM_IOCTL_SYNC_PTR:
|
||||
case __SNDRV_PCM_IOCTL_SYNC_PTR32:
|
||||
return snd_pcm_ioctl_sync_ptr_compat(substream, arg);
|
||||
case __SNDRV_PCM_IOCTL_SYNC_PTR64:
|
||||
return snd_pcm_sync_ptr(substream, arg);
|
||||
#ifdef CONFIG_SND_SUPPORT_OLD_API
|
||||
case SNDRV_PCM_IOCTL_HW_REFINE_OLD:
|
||||
@ -3332,8 +3502,6 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
|
||||
|
||||
static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
|
||||
{
|
||||
if (pcm_file->no_compat_mmap)
|
||||
return false;
|
||||
/* See pcm_control_mmap_allowed() below.
|
||||
* Since older alsa-lib requires both status and control mmaps to be
|
||||
* coupled, we have to disable the status mmap for old alsa-lib, too.
|
||||
@ -3558,11 +3726,19 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
|
||||
|
||||
offset = area->vm_pgoff << PAGE_SHIFT;
|
||||
switch (offset) {
|
||||
case SNDRV_PCM_MMAP_OFFSET_STATUS:
|
||||
case SNDRV_PCM_MMAP_OFFSET_STATUS_OLD:
|
||||
if (pcm_file->no_compat_mmap || !IS_ENABLED(CONFIG_64BIT))
|
||||
return -ENXIO;
|
||||
/* fallthrough */
|
||||
case SNDRV_PCM_MMAP_OFFSET_STATUS_NEW:
|
||||
if (!pcm_status_mmap_allowed(pcm_file))
|
||||
return -ENXIO;
|
||||
return snd_pcm_mmap_status(substream, file, area);
|
||||
case SNDRV_PCM_MMAP_OFFSET_CONTROL:
|
||||
case SNDRV_PCM_MMAP_OFFSET_CONTROL_OLD:
|
||||
if (pcm_file->no_compat_mmap || !IS_ENABLED(CONFIG_64BIT))
|
||||
return -ENXIO;
|
||||
/* fallthrough */
|
||||
case SNDRV_PCM_MMAP_OFFSET_CONTROL_NEW:
|
||||
if (!pcm_control_mmap_allowed(pcm_file))
|
||||
return -ENXIO;
|
||||
return snd_pcm_mmap_control(substream, file, area);
|
||||
@ -3722,9 +3898,9 @@ static unsigned long snd_pcm_get_unmapped_area(struct file *file,
|
||||
unsigned long offset = pgoff << PAGE_SHIFT;
|
||||
|
||||
switch (offset) {
|
||||
case SNDRV_PCM_MMAP_OFFSET_STATUS:
|
||||
case SNDRV_PCM_MMAP_OFFSET_STATUS_NEW:
|
||||
return (unsigned long)runtime->status;
|
||||
case SNDRV_PCM_MMAP_OFFSET_CONTROL:
|
||||
case SNDRV_PCM_MMAP_OFFSET_CONTROL_NEW:
|
||||
return (unsigned long)runtime->control;
|
||||
default:
|
||||
return (unsigned long)runtime->dma_area + offset;
|
||||
|
@ -75,7 +75,7 @@ static int snd_pcm_timer_stop(struct snd_timer * timer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_timer_hardware snd_pcm_timer =
|
||||
static const struct snd_timer_hardware snd_pcm_timer =
|
||||
{
|
||||
.flags = SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_SLAVE,
|
||||
.resolution = 0,
|
||||
|
@ -50,6 +50,29 @@ static DEFINE_MUTEX(register_mutex);
|
||||
#define rmidi_dbg(rmidi, fmt, args...) \
|
||||
dev_dbg(&(rmidi)->dev, fmt, ##args)
|
||||
|
||||
struct snd_rawmidi_status32 {
|
||||
s32 stream;
|
||||
s32 tstamp_sec; /* Timestamp */
|
||||
s32 tstamp_nsec;
|
||||
u32 avail; /* available bytes */
|
||||
u32 xruns; /* count of overruns since last status (in bytes) */
|
||||
unsigned char reserved[16]; /* reserved for future use */
|
||||
};
|
||||
|
||||
#define SNDRV_RAWMIDI_IOCTL_STATUS32 _IOWR('W', 0x20, struct snd_rawmidi_status32)
|
||||
|
||||
struct snd_rawmidi_status64 {
|
||||
int stream;
|
||||
u8 rsvd[4]; /* alignment */
|
||||
s64 tstamp_sec; /* Timestamp */
|
||||
s64 tstamp_nsec;
|
||||
size_t avail; /* available bytes */
|
||||
size_t xruns; /* count of overruns since last status (in bytes) */
|
||||
unsigned char reserved[16]; /* reserved for future use */
|
||||
};
|
||||
|
||||
#define SNDRV_RAWMIDI_IOCTL_STATUS64 _IOWR('W', 0x20, struct snd_rawmidi_status64)
|
||||
|
||||
static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device)
|
||||
{
|
||||
struct snd_rawmidi *rawmidi;
|
||||
@ -226,7 +249,7 @@ static int assign_substream(struct snd_rawmidi *rmidi, int subdevice,
|
||||
{
|
||||
struct snd_rawmidi_substream *substream;
|
||||
struct snd_rawmidi_str *s = &rmidi->streams[stream];
|
||||
static unsigned int info_flags[2] = {
|
||||
static const unsigned int info_flags[2] = {
|
||||
[SNDRV_RAWMIDI_STREAM_OUTPUT] = SNDRV_RAWMIDI_INFO_OUTPUT,
|
||||
[SNDRV_RAWMIDI_STREAM_INPUT] = SNDRV_RAWMIDI_INFO_INPUT,
|
||||
};
|
||||
@ -677,7 +700,7 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
|
||||
EXPORT_SYMBOL(snd_rawmidi_input_params);
|
||||
|
||||
static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream,
|
||||
struct snd_rawmidi_status *status)
|
||||
struct snd_rawmidi_status64 *status)
|
||||
{
|
||||
struct snd_rawmidi_runtime *runtime = substream->runtime;
|
||||
|
||||
@ -690,7 +713,7 @@ static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream,
|
||||
}
|
||||
|
||||
static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream,
|
||||
struct snd_rawmidi_status *status)
|
||||
struct snd_rawmidi_status64 *status)
|
||||
{
|
||||
struct snd_rawmidi_runtime *runtime = substream->runtime;
|
||||
|
||||
@ -704,6 +727,80 @@ static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_rawmidi_ioctl_status32(struct snd_rawmidi_file *rfile,
|
||||
struct snd_rawmidi_status32 __user *argp)
|
||||
{
|
||||
int err = 0;
|
||||
struct snd_rawmidi_status32 __user *status = argp;
|
||||
struct snd_rawmidi_status32 status32;
|
||||
struct snd_rawmidi_status64 status64;
|
||||
|
||||
if (copy_from_user(&status32, argp,
|
||||
sizeof(struct snd_rawmidi_status32)))
|
||||
return -EFAULT;
|
||||
|
||||
switch (status32.stream) {
|
||||
case SNDRV_RAWMIDI_STREAM_OUTPUT:
|
||||
if (rfile->output == NULL)
|
||||
return -EINVAL;
|
||||
err = snd_rawmidi_output_status(rfile->output, &status64);
|
||||
break;
|
||||
case SNDRV_RAWMIDI_STREAM_INPUT:
|
||||
if (rfile->input == NULL)
|
||||
return -EINVAL;
|
||||
err = snd_rawmidi_input_status(rfile->input, &status64);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
status32 = (struct snd_rawmidi_status32) {
|
||||
.stream = status64.stream,
|
||||
.tstamp_sec = status64.tstamp_sec,
|
||||
.tstamp_nsec = status64.tstamp_nsec,
|
||||
.avail = status64.avail,
|
||||
.xruns = status64.xruns,
|
||||
};
|
||||
|
||||
if (copy_to_user(status, &status32, sizeof(*status)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_rawmidi_ioctl_status64(struct snd_rawmidi_file *rfile,
|
||||
struct snd_rawmidi_status64 __user *argp)
|
||||
{
|
||||
int err = 0;
|
||||
struct snd_rawmidi_status64 status;
|
||||
|
||||
if (copy_from_user(&status, argp, sizeof(struct snd_rawmidi_status64)))
|
||||
return -EFAULT;
|
||||
|
||||
switch (status.stream) {
|
||||
case SNDRV_RAWMIDI_STREAM_OUTPUT:
|
||||
if (rfile->output == NULL)
|
||||
return -EINVAL;
|
||||
err = snd_rawmidi_output_status(rfile->output, &status);
|
||||
break;
|
||||
case SNDRV_RAWMIDI_STREAM_INPUT:
|
||||
if (rfile->input == NULL)
|
||||
return -EINVAL;
|
||||
err = snd_rawmidi_input_status(rfile->input, &status);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (copy_to_user(argp, &status,
|
||||
sizeof(struct snd_rawmidi_status64)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct snd_rawmidi_file *rfile;
|
||||
@ -750,33 +847,10 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
case SNDRV_RAWMIDI_IOCTL_STATUS:
|
||||
{
|
||||
int err = 0;
|
||||
struct snd_rawmidi_status status;
|
||||
|
||||
if (copy_from_user(&status, argp, sizeof(struct snd_rawmidi_status)))
|
||||
return -EFAULT;
|
||||
switch (status.stream) {
|
||||
case SNDRV_RAWMIDI_STREAM_OUTPUT:
|
||||
if (rfile->output == NULL)
|
||||
return -EINVAL;
|
||||
err = snd_rawmidi_output_status(rfile->output, &status);
|
||||
break;
|
||||
case SNDRV_RAWMIDI_STREAM_INPUT:
|
||||
if (rfile->input == NULL)
|
||||
return -EINVAL;
|
||||
err = snd_rawmidi_input_status(rfile->input, &status);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (copy_to_user(argp, &status, sizeof(struct snd_rawmidi_status)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
case SNDRV_RAWMIDI_IOCTL_STATUS32:
|
||||
return snd_rawmidi_ioctl_status32(rfile, argp);
|
||||
case SNDRV_RAWMIDI_IOCTL_STATUS64:
|
||||
return snd_rawmidi_ioctl_status64(rfile, argp);
|
||||
case SNDRV_RAWMIDI_IOCTL_DROP:
|
||||
{
|
||||
int val;
|
||||
@ -1547,7 +1621,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,
|
||||
{
|
||||
struct snd_rawmidi *rmidi;
|
||||
int err;
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_free = snd_rawmidi_dev_free,
|
||||
.dev_register = snd_rawmidi_dev_register,
|
||||
.dev_disconnect = snd_rawmidi_dev_disconnect,
|
||||
|
@ -41,19 +41,22 @@ static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct snd_rawmidi_status32 {
|
||||
struct compat_snd_rawmidi_status64 {
|
||||
s32 stream;
|
||||
struct compat_timespec tstamp;
|
||||
u8 rsvd[4]; /* alignment */
|
||||
s64 tstamp_sec;
|
||||
s64 tstamp_nsec;
|
||||
u32 avail;
|
||||
u32 xruns;
|
||||
unsigned char reserved[16];
|
||||
} __attribute__((packed));
|
||||
|
||||
static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile,
|
||||
struct snd_rawmidi_status32 __user *src)
|
||||
static int snd_rawmidi_ioctl_status_compat64(struct snd_rawmidi_file *rfile,
|
||||
struct compat_snd_rawmidi_status64 __user *src)
|
||||
{
|
||||
int err;
|
||||
struct snd_rawmidi_status status;
|
||||
struct snd_rawmidi_status64 status;
|
||||
struct compat_snd_rawmidi_status64 compat_status;
|
||||
|
||||
if (get_user(status.stream, &src->stream))
|
||||
return -EFAULT;
|
||||
@ -75,68 +78,24 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (compat_put_timespec(&status.tstamp, &src->tstamp) ||
|
||||
put_user(status.avail, &src->avail) ||
|
||||
put_user(status.xruns, &src->xruns))
|
||||
compat_status = (struct compat_snd_rawmidi_status64) {
|
||||
.stream = status.stream,
|
||||
.tstamp_sec = status.tstamp_sec,
|
||||
.tstamp_nsec = status.tstamp_nsec,
|
||||
.avail = status.avail,
|
||||
.xruns = status.xruns,
|
||||
};
|
||||
|
||||
if (copy_to_user(src, &compat_status, sizeof(*src)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_X32
|
||||
/* X32 ABI has 64bit timespec and 64bit alignment */
|
||||
struct snd_rawmidi_status_x32 {
|
||||
s32 stream;
|
||||
u32 rsvd; /* alignment */
|
||||
struct timespec tstamp;
|
||||
u32 avail;
|
||||
u32 xruns;
|
||||
unsigned char reserved[16];
|
||||
} __attribute__((packed));
|
||||
|
||||
#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst))
|
||||
|
||||
static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile,
|
||||
struct snd_rawmidi_status_x32 __user *src)
|
||||
{
|
||||
int err;
|
||||
struct snd_rawmidi_status status;
|
||||
|
||||
if (get_user(status.stream, &src->stream))
|
||||
return -EFAULT;
|
||||
|
||||
switch (status.stream) {
|
||||
case SNDRV_RAWMIDI_STREAM_OUTPUT:
|
||||
if (!rfile->output)
|
||||
return -EINVAL;
|
||||
err = snd_rawmidi_output_status(rfile->output, &status);
|
||||
break;
|
||||
case SNDRV_RAWMIDI_STREAM_INPUT:
|
||||
if (!rfile->input)
|
||||
return -EINVAL;
|
||||
err = snd_rawmidi_input_status(rfile->input, &status);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (put_timespec(&status.tstamp, &src->tstamp) ||
|
||||
put_user(status.avail, &src->avail) ||
|
||||
put_user(status.xruns, &src->xruns))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_X86_X32 */
|
||||
|
||||
enum {
|
||||
SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32),
|
||||
SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
|
||||
#ifdef CONFIG_X86_X32
|
||||
SNDRV_RAWMIDI_IOCTL_STATUS_X32 = _IOWR('W', 0x20, struct snd_rawmidi_status_x32),
|
||||
#endif /* CONFIG_X86_X32 */
|
||||
SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
|
||||
SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64 = _IOWR('W', 0x20, struct compat_snd_rawmidi_status64),
|
||||
};
|
||||
|
||||
static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
@ -153,12 +112,10 @@ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsign
|
||||
return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp);
|
||||
case SNDRV_RAWMIDI_IOCTL_PARAMS32:
|
||||
return snd_rawmidi_ioctl_params_compat(rfile, argp);
|
||||
case SNDRV_RAWMIDI_IOCTL_STATUS32:
|
||||
return snd_rawmidi_ioctl_status_compat(rfile, argp);
|
||||
#ifdef CONFIG_X86_X32
|
||||
case SNDRV_RAWMIDI_IOCTL_STATUS_X32:
|
||||
return snd_rawmidi_ioctl_status_x32(rfile, argp);
|
||||
#endif /* CONFIG_X86_X32 */
|
||||
case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32:
|
||||
return snd_rawmidi_ioctl_status32(rfile, argp);
|
||||
case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64:
|
||||
return snd_rawmidi_ioctl_status_compat64(rfile, argp);
|
||||
}
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
@ -460,10 +460,10 @@ enabled_str(int bool)
|
||||
return bool ? "enabled" : "disabled";
|
||||
}
|
||||
|
||||
static char *
|
||||
static const char *
|
||||
filemode_str(int val)
|
||||
{
|
||||
static char *str[] = {
|
||||
static const char * const str[] = {
|
||||
"none", "read", "write", "read/write",
|
||||
};
|
||||
return str[val & SNDRV_SEQ_OSS_FILE_ACMODE];
|
||||
|
@ -30,22 +30,25 @@ MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI emulation."
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* Prototypes for static functions */
|
||||
static void note_off(struct snd_midi_op *ops, void *drv,
|
||||
static void note_off(const struct snd_midi_op *ops, void *drv,
|
||||
struct snd_midi_channel *chan,
|
||||
int note, int vel);
|
||||
static void do_control(struct snd_midi_op *ops, void *private,
|
||||
static void do_control(const struct snd_midi_op *ops, void *private,
|
||||
struct snd_midi_channel_set *chset,
|
||||
struct snd_midi_channel *chan,
|
||||
int control, int value);
|
||||
static void rpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
|
||||
static void rpn(const struct snd_midi_op *ops, void *drv,
|
||||
struct snd_midi_channel *chan,
|
||||
struct snd_midi_channel_set *chset);
|
||||
static void nrpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
|
||||
static void nrpn(const struct snd_midi_op *ops, void *drv,
|
||||
struct snd_midi_channel *chan,
|
||||
struct snd_midi_channel_set *chset);
|
||||
static void sysex(struct snd_midi_op *ops, void *private, unsigned char *sysex,
|
||||
static void sysex(const struct snd_midi_op *ops, void *private,
|
||||
unsigned char *sysex,
|
||||
int len, struct snd_midi_channel_set *chset);
|
||||
static void all_sounds_off(struct snd_midi_op *ops, void *private,
|
||||
static void all_sounds_off(const struct snd_midi_op *ops, void *private,
|
||||
struct snd_midi_channel *chan);
|
||||
static void all_notes_off(struct snd_midi_op *ops, void *private,
|
||||
static void all_notes_off(const struct snd_midi_op *ops, void *private,
|
||||
struct snd_midi_channel *chan);
|
||||
static void snd_midi_reset_controllers(struct snd_midi_channel *chan);
|
||||
static void reset_all_channels(struct snd_midi_channel_set *chset);
|
||||
@ -66,7 +69,7 @@ static void reset_all_channels(struct snd_midi_channel_set *chset);
|
||||
* be interpreted.
|
||||
*/
|
||||
void
|
||||
snd_midi_process_event(struct snd_midi_op *ops,
|
||||
snd_midi_process_event(const struct snd_midi_op *ops,
|
||||
struct snd_seq_event *ev,
|
||||
struct snd_midi_channel_set *chanset)
|
||||
{
|
||||
@ -229,7 +232,8 @@ EXPORT_SYMBOL(snd_midi_process_event);
|
||||
* release note
|
||||
*/
|
||||
static void
|
||||
note_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
|
||||
note_off(const struct snd_midi_op *ops, void *drv,
|
||||
struct snd_midi_channel *chan,
|
||||
int note, int vel)
|
||||
{
|
||||
if (chan->gm_hold) {
|
||||
@ -251,7 +255,8 @@ note_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
|
||||
* events that need to take place immediately to the driver.
|
||||
*/
|
||||
static void
|
||||
do_control(struct snd_midi_op *ops, void *drv, struct snd_midi_channel_set *chset,
|
||||
do_control(const struct snd_midi_op *ops, void *drv,
|
||||
struct snd_midi_channel_set *chset,
|
||||
struct snd_midi_channel *chan, int control, int value)
|
||||
{
|
||||
int i;
|
||||
@ -402,7 +407,7 @@ EXPORT_SYMBOL(snd_midi_channel_set_clear);
|
||||
* Process a rpn message.
|
||||
*/
|
||||
static void
|
||||
rpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
|
||||
rpn(const struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
|
||||
struct snd_midi_channel_set *chset)
|
||||
{
|
||||
int type;
|
||||
@ -442,7 +447,7 @@ rpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
|
||||
* Process an nrpn message.
|
||||
*/
|
||||
static void
|
||||
nrpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
|
||||
nrpn(const struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
|
||||
struct snd_midi_channel_set *chset)
|
||||
{
|
||||
/* parse XG NRPNs here if possible */
|
||||
@ -470,15 +475,15 @@ get_channel(unsigned char cmd)
|
||||
* Process a sysex message.
|
||||
*/
|
||||
static void
|
||||
sysex(struct snd_midi_op *ops, void *private, unsigned char *buf, int len,
|
||||
sysex(const struct snd_midi_op *ops, void *private, unsigned char *buf, int len,
|
||||
struct snd_midi_channel_set *chset)
|
||||
{
|
||||
/* GM on */
|
||||
static unsigned char gm_on_macro[] = {
|
||||
static const unsigned char gm_on_macro[] = {
|
||||
0x7e,0x7f,0x09,0x01,
|
||||
};
|
||||
/* XG on */
|
||||
static unsigned char xg_on_macro[] = {
|
||||
static const unsigned char xg_on_macro[] = {
|
||||
0x43,0x10,0x4c,0x00,0x00,0x7e,0x00,
|
||||
};
|
||||
/* GS prefix
|
||||
@ -487,7 +492,7 @@ sysex(struct snd_midi_op *ops, void *private, unsigned char *buf, int len,
|
||||
* chorus mode: XX=0x01, YY=0x38, ZZ=0-7
|
||||
* master vol: XX=0x00, YY=0x04, ZZ=0-127
|
||||
*/
|
||||
static unsigned char gs_pfx_macro[] = {
|
||||
static const unsigned char gs_pfx_macro[] = {
|
||||
0x41,0x10,0x42,0x12,0x40,/*XX,YY,ZZ*/
|
||||
};
|
||||
|
||||
@ -584,7 +589,8 @@ sysex(struct snd_midi_op *ops, void *private, unsigned char *buf, int len,
|
||||
* all sound off
|
||||
*/
|
||||
static void
|
||||
all_sounds_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan)
|
||||
all_sounds_off(const struct snd_midi_op *ops, void *drv,
|
||||
struct snd_midi_channel *chan)
|
||||
{
|
||||
int n;
|
||||
|
||||
@ -602,7 +608,8 @@ all_sounds_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan
|
||||
* all notes off
|
||||
*/
|
||||
static void
|
||||
all_notes_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan)
|
||||
all_notes_off(const struct snd_midi_op *ops, void *drv,
|
||||
struct snd_midi_channel *chan)
|
||||
{
|
||||
int n;
|
||||
|
||||
|
@ -422,12 +422,12 @@ static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf,
|
||||
int count, struct snd_seq_event *ev)
|
||||
{
|
||||
unsigned char cmd;
|
||||
char *cbytes;
|
||||
static char cbytes_nrpn[4] = { MIDI_CTL_NONREG_PARM_NUM_MSB,
|
||||
const char *cbytes;
|
||||
static const char cbytes_nrpn[4] = { MIDI_CTL_NONREG_PARM_NUM_MSB,
|
||||
MIDI_CTL_NONREG_PARM_NUM_LSB,
|
||||
MIDI_CTL_MSB_DATA_ENTRY,
|
||||
MIDI_CTL_LSB_DATA_ENTRY };
|
||||
static char cbytes_rpn[4] = { MIDI_CTL_REGIST_PARM_NUM_MSB,
|
||||
static const char cbytes_rpn[4] = { MIDI_CTL_REGIST_PARM_NUM_MSB,
|
||||
MIDI_CTL_REGIST_PARM_NUM_LSB,
|
||||
MIDI_CTL_MSB_DATA_ENTRY,
|
||||
MIDI_CTL_LSB_DATA_ENTRY };
|
||||
|
@ -193,7 +193,7 @@ int snd_seq_device_new(struct snd_card *card, int device, const char *id,
|
||||
{
|
||||
struct snd_seq_device *dev;
|
||||
int err;
|
||||
static struct snd_device_ops dops = {
|
||||
static const struct snd_device_ops dops = {
|
||||
.dev_free = snd_seq_device_dev_free,
|
||||
.dev_register = snd_seq_device_dev_register,
|
||||
.dev_disconnect = snd_seq_device_dev_disconnect,
|
||||
|
@ -44,6 +44,28 @@ MODULE_PARM_DESC(timer_tstamp_monotonic, "Use posix monotonic clock source for t
|
||||
MODULE_ALIAS_CHARDEV(CONFIG_SND_MAJOR, SNDRV_MINOR_TIMER);
|
||||
MODULE_ALIAS("devname:snd/timer");
|
||||
|
||||
enum timer_tread_format {
|
||||
TREAD_FORMAT_NONE = 0,
|
||||
TREAD_FORMAT_TIME64,
|
||||
TREAD_FORMAT_TIME32,
|
||||
};
|
||||
|
||||
struct snd_timer_tread32 {
|
||||
int event;
|
||||
s32 tstamp_sec;
|
||||
s32 tstamp_nsec;
|
||||
unsigned int val;
|
||||
};
|
||||
|
||||
struct snd_timer_tread64 {
|
||||
int event;
|
||||
u8 pad1[4];
|
||||
s64 tstamp_sec;
|
||||
s64 tstamp_nsec;
|
||||
unsigned int val;
|
||||
u8 pad2[4];
|
||||
};
|
||||
|
||||
struct snd_timer_user {
|
||||
struct snd_timer_instance *timeri;
|
||||
int tread; /* enhanced read with timestamps and events */
|
||||
@ -55,16 +77,40 @@ struct snd_timer_user {
|
||||
int queue_size;
|
||||
bool disconnected;
|
||||
struct snd_timer_read *queue;
|
||||
struct snd_timer_tread *tqueue;
|
||||
struct snd_timer_tread64 *tqueue;
|
||||
spinlock_t qlock;
|
||||
unsigned long last_resolution;
|
||||
unsigned int filter;
|
||||
struct timespec tstamp; /* trigger tstamp */
|
||||
struct timespec64 tstamp; /* trigger tstamp */
|
||||
wait_queue_head_t qchange_sleep;
|
||||
struct fasync_struct *fasync;
|
||||
struct mutex ioctl_lock;
|
||||
};
|
||||
|
||||
struct snd_timer_status32 {
|
||||
s32 tstamp_sec; /* Timestamp - last update */
|
||||
s32 tstamp_nsec;
|
||||
unsigned int resolution; /* current period resolution in ns */
|
||||
unsigned int lost; /* counter of master tick lost */
|
||||
unsigned int overrun; /* count of read queue overruns */
|
||||
unsigned int queue; /* used queue size */
|
||||
unsigned char reserved[64]; /* reserved */
|
||||
};
|
||||
|
||||
#define SNDRV_TIMER_IOCTL_STATUS32 _IOR('T', 0x14, struct snd_timer_status32)
|
||||
|
||||
struct snd_timer_status64 {
|
||||
s64 tstamp_sec; /* Timestamp - last update */
|
||||
s64 tstamp_nsec;
|
||||
unsigned int resolution; /* current period resolution in ns */
|
||||
unsigned int lost; /* counter of master tick lost */
|
||||
unsigned int overrun; /* count of read queue overruns */
|
||||
unsigned int queue; /* used queue size */
|
||||
unsigned char reserved[64]; /* reserved */
|
||||
};
|
||||
|
||||
#define SNDRV_TIMER_IOCTL_STATUS64 _IOR('T', 0x14, struct snd_timer_status64)
|
||||
|
||||
/* list of timers */
|
||||
static LIST_HEAD(snd_timer_list);
|
||||
|
||||
@ -453,12 +499,12 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
|
||||
struct snd_timer *timer = ti->timer;
|
||||
unsigned long resolution = 0;
|
||||
struct snd_timer_instance *ts;
|
||||
struct timespec tstamp;
|
||||
struct timespec64 tstamp;
|
||||
|
||||
if (timer_tstamp_monotonic)
|
||||
ktime_get_ts(&tstamp);
|
||||
ktime_get_ts64(&tstamp);
|
||||
else
|
||||
getnstimeofday(&tstamp);
|
||||
ktime_get_real_ts64(&tstamp);
|
||||
if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START ||
|
||||
event > SNDRV_TIMER_EVENT_PAUSE))
|
||||
return;
|
||||
@ -890,7 +936,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
|
||||
{
|
||||
struct snd_timer *timer;
|
||||
int err;
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_free = snd_timer_dev_free,
|
||||
.dev_register = snd_timer_dev_register,
|
||||
.dev_disconnect = snd_timer_dev_disconnect,
|
||||
@ -1025,7 +1071,7 @@ static int snd_timer_dev_disconnect(struct snd_device *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp)
|
||||
void snd_timer_notify(struct snd_timer *timer, int event, struct timespec64 *tstamp)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long resolution = 0;
|
||||
@ -1153,7 +1199,7 @@ static int snd_timer_s_close(struct snd_timer *timer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_timer_hardware snd_timer_system =
|
||||
static const struct snd_timer_hardware snd_timer_system =
|
||||
{
|
||||
.flags = SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_TASKLET,
|
||||
.resolution = 1000000000L / HZ,
|
||||
@ -1305,7 +1351,7 @@ static void snd_timer_user_interrupt(struct snd_timer_instance *timeri,
|
||||
}
|
||||
|
||||
static void snd_timer_user_append_to_tqueue(struct snd_timer_user *tu,
|
||||
struct snd_timer_tread *tread)
|
||||
struct snd_timer_tread64 *tread)
|
||||
{
|
||||
if (tu->qused >= tu->queue_size) {
|
||||
tu->overrun++;
|
||||
@ -1318,11 +1364,11 @@ static void snd_timer_user_append_to_tqueue(struct snd_timer_user *tu,
|
||||
|
||||
static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
|
||||
int event,
|
||||
struct timespec *tstamp,
|
||||
struct timespec64 *tstamp,
|
||||
unsigned long resolution)
|
||||
{
|
||||
struct snd_timer_user *tu = timeri->callback_data;
|
||||
struct snd_timer_tread r1;
|
||||
struct snd_timer_tread64 r1;
|
||||
unsigned long flags;
|
||||
|
||||
if (event >= SNDRV_TIMER_EVENT_START &&
|
||||
@ -1332,7 +1378,8 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
|
||||
return;
|
||||
memset(&r1, 0, sizeof(r1));
|
||||
r1.event = event;
|
||||
r1.tstamp = *tstamp;
|
||||
r1.tstamp_sec = tstamp->tv_sec;
|
||||
r1.tstamp_nsec = tstamp->tv_nsec;
|
||||
r1.val = resolution;
|
||||
spin_lock_irqsave(&tu->qlock, flags);
|
||||
snd_timer_user_append_to_tqueue(tu, &r1);
|
||||
@ -1354,8 +1401,8 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
|
||||
unsigned long ticks)
|
||||
{
|
||||
struct snd_timer_user *tu = timeri->callback_data;
|
||||
struct snd_timer_tread *r, r1;
|
||||
struct timespec tstamp;
|
||||
struct snd_timer_tread64 *r, r1;
|
||||
struct timespec64 tstamp;
|
||||
int prev, append = 0;
|
||||
|
||||
memset(&r1, 0, sizeof(r1));
|
||||
@ -1368,14 +1415,15 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
|
||||
}
|
||||
if (tu->last_resolution != resolution || ticks > 0) {
|
||||
if (timer_tstamp_monotonic)
|
||||
ktime_get_ts(&tstamp);
|
||||
ktime_get_ts64(&tstamp);
|
||||
else
|
||||
getnstimeofday(&tstamp);
|
||||
ktime_get_real_ts64(&tstamp);
|
||||
}
|
||||
if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) &&
|
||||
tu->last_resolution != resolution) {
|
||||
r1.event = SNDRV_TIMER_EVENT_RESOLUTION;
|
||||
r1.tstamp = tstamp;
|
||||
r1.tstamp_sec = tstamp.tv_sec;
|
||||
r1.tstamp_nsec = tstamp.tv_nsec;
|
||||
r1.val = resolution;
|
||||
snd_timer_user_append_to_tqueue(tu, &r1);
|
||||
tu->last_resolution = resolution;
|
||||
@ -1389,14 +1437,16 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
|
||||
prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1;
|
||||
r = &tu->tqueue[prev];
|
||||
if (r->event == SNDRV_TIMER_EVENT_TICK) {
|
||||
r->tstamp = tstamp;
|
||||
r->tstamp_sec = tstamp.tv_sec;
|
||||
r->tstamp_nsec = tstamp.tv_nsec;
|
||||
r->val += ticks;
|
||||
append++;
|
||||
goto __wake;
|
||||
}
|
||||
}
|
||||
r1.event = SNDRV_TIMER_EVENT_TICK;
|
||||
r1.tstamp = tstamp;
|
||||
r1.tstamp_sec = tstamp.tv_sec;
|
||||
r1.tstamp_nsec = tstamp.tv_nsec;
|
||||
r1.val = ticks;
|
||||
snd_timer_user_append_to_tqueue(tu, &r1);
|
||||
append++;
|
||||
@ -1411,7 +1461,7 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
|
||||
static int realloc_user_queue(struct snd_timer_user *tu, int size)
|
||||
{
|
||||
struct snd_timer_read *queue = NULL;
|
||||
struct snd_timer_tread *tqueue = NULL;
|
||||
struct snd_timer_tread64 *tqueue = NULL;
|
||||
|
||||
if (tu->tread) {
|
||||
tqueue = kcalloc(size, sizeof(*tqueue), GFP_KERNEL);
|
||||
@ -1850,11 +1900,11 @@ static int snd_timer_user_params(struct file *file,
|
||||
tu->qhead = tu->qtail = tu->qused = 0;
|
||||
if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) {
|
||||
if (tu->tread) {
|
||||
struct snd_timer_tread tread;
|
||||
struct snd_timer_tread64 tread;
|
||||
memset(&tread, 0, sizeof(tread));
|
||||
tread.event = SNDRV_TIMER_EVENT_EARLY;
|
||||
tread.tstamp.tv_sec = 0;
|
||||
tread.tstamp.tv_nsec = 0;
|
||||
tread.tstamp_sec = 0;
|
||||
tread.tstamp_nsec = 0;
|
||||
tread.val = 0;
|
||||
snd_timer_user_append_to_tqueue(tu, &tread);
|
||||
} else {
|
||||
@ -1875,17 +1925,41 @@ static int snd_timer_user_params(struct file *file,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int snd_timer_user_status(struct file *file,
|
||||
struct snd_timer_status __user *_status)
|
||||
{
|
||||
static int snd_timer_user_status32(struct file *file,
|
||||
struct snd_timer_status32 __user *_status)
|
||||
{
|
||||
struct snd_timer_user *tu;
|
||||
struct snd_timer_status status;
|
||||
struct snd_timer_status32 status;
|
||||
|
||||
tu = file->private_data;
|
||||
if (!tu->timeri)
|
||||
return -EBADFD;
|
||||
memset(&status, 0, sizeof(status));
|
||||
status.tstamp = tu->tstamp;
|
||||
status.tstamp_sec = tu->tstamp.tv_sec;
|
||||
status.tstamp_nsec = tu->tstamp.tv_nsec;
|
||||
status.resolution = snd_timer_resolution(tu->timeri);
|
||||
status.lost = tu->timeri->lost;
|
||||
status.overrun = tu->overrun;
|
||||
spin_lock_irq(&tu->qlock);
|
||||
status.queue = tu->qused;
|
||||
spin_unlock_irq(&tu->qlock);
|
||||
if (copy_to_user(_status, &status, sizeof(status)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_timer_user_status64(struct file *file,
|
||||
struct snd_timer_status64 __user *_status)
|
||||
{
|
||||
struct snd_timer_user *tu;
|
||||
struct snd_timer_status64 status;
|
||||
|
||||
tu = file->private_data;
|
||||
if (!tu->timeri)
|
||||
return -EBADFD;
|
||||
memset(&status, 0, sizeof(status));
|
||||
status.tstamp_sec = tu->tstamp.tv_sec;
|
||||
status.tstamp_nsec = tu->tstamp.tv_nsec;
|
||||
status.resolution = snd_timer_resolution(tu->timeri);
|
||||
status.lost = tu->timeri->lost;
|
||||
status.overrun = tu->overrun;
|
||||
@ -1960,6 +2034,36 @@ static int snd_timer_user_pause(struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_timer_user_tread(void __user *argp, struct snd_timer_user *tu,
|
||||
unsigned int cmd, bool compat)
|
||||
{
|
||||
int __user *p = argp;
|
||||
int xarg, old_tread;
|
||||
|
||||
if (tu->timeri) /* too late */
|
||||
return -EBUSY;
|
||||
if (get_user(xarg, p))
|
||||
return -EFAULT;
|
||||
|
||||
old_tread = tu->tread;
|
||||
|
||||
if (!xarg)
|
||||
tu->tread = TREAD_FORMAT_NONE;
|
||||
else if (cmd == SNDRV_TIMER_IOCTL_TREAD64 ||
|
||||
(IS_ENABLED(CONFIG_64BIT) && !compat))
|
||||
tu->tread = TREAD_FORMAT_TIME64;
|
||||
else
|
||||
tu->tread = TREAD_FORMAT_TIME32;
|
||||
|
||||
if (tu->tread != old_tread &&
|
||||
realloc_user_queue(tu, tu->queue_size) < 0) {
|
||||
tu->tread = old_tread;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum {
|
||||
SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20),
|
||||
SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21),
|
||||
@ -1968,7 +2072,7 @@ enum {
|
||||
};
|
||||
|
||||
static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
unsigned long arg, bool compat)
|
||||
{
|
||||
struct snd_timer_user *tu;
|
||||
void __user *argp = (void __user *)arg;
|
||||
@ -1980,23 +2084,9 @@ static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
|
||||
return put_user(SNDRV_TIMER_VERSION, p) ? -EFAULT : 0;
|
||||
case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
|
||||
return snd_timer_user_next_device(argp);
|
||||
case SNDRV_TIMER_IOCTL_TREAD:
|
||||
{
|
||||
int xarg, old_tread;
|
||||
|
||||
if (tu->timeri) /* too late */
|
||||
return -EBUSY;
|
||||
if (get_user(xarg, p))
|
||||
return -EFAULT;
|
||||
old_tread = tu->tread;
|
||||
tu->tread = xarg ? 1 : 0;
|
||||
if (tu->tread != old_tread &&
|
||||
realloc_user_queue(tu, tu->queue_size) < 0) {
|
||||
tu->tread = old_tread;
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case SNDRV_TIMER_IOCTL_TREAD_OLD:
|
||||
case SNDRV_TIMER_IOCTL_TREAD64:
|
||||
return snd_timer_user_tread(argp, tu, cmd, compat);
|
||||
case SNDRV_TIMER_IOCTL_GINFO:
|
||||
return snd_timer_user_ginfo(file, argp);
|
||||
case SNDRV_TIMER_IOCTL_GPARAMS:
|
||||
@ -2009,8 +2099,10 @@ static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
|
||||
return snd_timer_user_info(file, argp);
|
||||
case SNDRV_TIMER_IOCTL_PARAMS:
|
||||
return snd_timer_user_params(file, argp);
|
||||
case SNDRV_TIMER_IOCTL_STATUS:
|
||||
return snd_timer_user_status(file, argp);
|
||||
case SNDRV_TIMER_IOCTL_STATUS32:
|
||||
return snd_timer_user_status32(file, argp);
|
||||
case SNDRV_TIMER_IOCTL_STATUS64:
|
||||
return snd_timer_user_status64(file, argp);
|
||||
case SNDRV_TIMER_IOCTL_START:
|
||||
case SNDRV_TIMER_IOCTL_START_OLD:
|
||||
return snd_timer_user_start(file);
|
||||
@ -2034,7 +2126,7 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
|
||||
long ret;
|
||||
|
||||
mutex_lock(&tu->ioctl_lock);
|
||||
ret = __snd_timer_user_ioctl(file, cmd, arg);
|
||||
ret = __snd_timer_user_ioctl(file, cmd, arg, false);
|
||||
mutex_unlock(&tu->ioctl_lock);
|
||||
return ret;
|
||||
}
|
||||
@ -2050,13 +2142,29 @@ static int snd_timer_user_fasync(int fd, struct file * file, int on)
|
||||
static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
|
||||
size_t count, loff_t *offset)
|
||||
{
|
||||
struct snd_timer_tread64 *tread;
|
||||
struct snd_timer_tread32 tread32;
|
||||
struct snd_timer_user *tu;
|
||||
long result = 0, unit;
|
||||
int qhead;
|
||||
int err = 0;
|
||||
|
||||
tu = file->private_data;
|
||||
unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read);
|
||||
switch (tu->tread) {
|
||||
case TREAD_FORMAT_TIME64:
|
||||
unit = sizeof(struct snd_timer_tread64);
|
||||
break;
|
||||
case TREAD_FORMAT_TIME32:
|
||||
unit = sizeof(struct snd_timer_tread32);
|
||||
break;
|
||||
case TREAD_FORMAT_NONE:
|
||||
unit = sizeof(struct snd_timer_read);
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(1, "Corrupt snd_timer_user\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
mutex_lock(&tu->ioctl_lock);
|
||||
spin_lock_irq(&tu->qlock);
|
||||
while ((long)count - result >= unit) {
|
||||
@ -2095,14 +2203,34 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
|
||||
tu->qused--;
|
||||
spin_unlock_irq(&tu->qlock);
|
||||
|
||||
if (tu->tread) {
|
||||
if (copy_to_user(buffer, &tu->tqueue[qhead],
|
||||
sizeof(struct snd_timer_tread)))
|
||||
tread = &tu->tqueue[qhead];
|
||||
|
||||
switch (tu->tread) {
|
||||
case TREAD_FORMAT_TIME64:
|
||||
if (copy_to_user(buffer, tread,
|
||||
sizeof(struct snd_timer_tread64)))
|
||||
err = -EFAULT;
|
||||
} else {
|
||||
break;
|
||||
case TREAD_FORMAT_TIME32:
|
||||
memset(&tread32, 0, sizeof(tread32));
|
||||
tread32 = (struct snd_timer_tread32) {
|
||||
.event = tread->event,
|
||||
.tstamp_sec = tread->tstamp_sec,
|
||||
.tstamp_nsec = tread->tstamp_nsec,
|
||||
.val = tread->val,
|
||||
};
|
||||
|
||||
if (copy_to_user(buffer, &tread32, sizeof(tread32)))
|
||||
err = -EFAULT;
|
||||
break;
|
||||
case TREAD_FORMAT_NONE:
|
||||
if (copy_to_user(buffer, &tu->queue[qhead],
|
||||
sizeof(struct snd_timer_read)))
|
||||
err = -EFAULT;
|
||||
break;
|
||||
default:
|
||||
err = -ENOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irq(&tu->qlock);
|
||||
|
@ -69,54 +69,11 @@ static int snd_timer_user_info_compat(struct file *file,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_timer_status32 {
|
||||
struct compat_timespec tstamp;
|
||||
u32 resolution;
|
||||
u32 lost;
|
||||
u32 overrun;
|
||||
u32 queue;
|
||||
unsigned char reserved[64];
|
||||
};
|
||||
|
||||
static int snd_timer_user_status_compat(struct file *file,
|
||||
struct snd_timer_status32 __user *_status)
|
||||
{
|
||||
struct snd_timer_user *tu;
|
||||
struct snd_timer_status32 status;
|
||||
|
||||
tu = file->private_data;
|
||||
if (!tu->timeri)
|
||||
return -EBADFD;
|
||||
memset(&status, 0, sizeof(status));
|
||||
status.tstamp.tv_sec = tu->tstamp.tv_sec;
|
||||
status.tstamp.tv_nsec = tu->tstamp.tv_nsec;
|
||||
status.resolution = snd_timer_resolution(tu->timeri);
|
||||
status.lost = tu->timeri->lost;
|
||||
status.overrun = tu->overrun;
|
||||
spin_lock_irq(&tu->qlock);
|
||||
status.queue = tu->qused;
|
||||
spin_unlock_irq(&tu->qlock);
|
||||
if (copy_to_user(_status, &status, sizeof(status)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_X32
|
||||
/* X32 ABI has the same struct as x86-64 */
|
||||
#define snd_timer_user_status_x32(file, s) \
|
||||
snd_timer_user_status(file, s)
|
||||
#endif /* CONFIG_X86_X32 */
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
enum {
|
||||
SNDRV_TIMER_IOCTL_GPARAMS32 = _IOW('T', 0x04, struct snd_timer_gparams32),
|
||||
SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),
|
||||
SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32),
|
||||
#ifdef CONFIG_X86_X32
|
||||
SNDRV_TIMER_IOCTL_STATUS_X32 = _IOW('T', 0x14, struct snd_timer_status),
|
||||
#endif /* CONFIG_X86_X32 */
|
||||
SNDRV_TIMER_IOCTL_STATUS_COMPAT32 = _IOW('T', 0x14, struct snd_timer_status32),
|
||||
SNDRV_TIMER_IOCTL_STATUS_COMPAT64 = _IOW('T', 0x14, struct snd_timer_status64),
|
||||
};
|
||||
|
||||
static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,
|
||||
@ -126,7 +83,8 @@ static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_TIMER_IOCTL_PVERSION:
|
||||
case SNDRV_TIMER_IOCTL_TREAD:
|
||||
case SNDRV_TIMER_IOCTL_TREAD_OLD:
|
||||
case SNDRV_TIMER_IOCTL_TREAD64:
|
||||
case SNDRV_TIMER_IOCTL_GINFO:
|
||||
case SNDRV_TIMER_IOCTL_GSTATUS:
|
||||
case SNDRV_TIMER_IOCTL_SELECT:
|
||||
@ -140,17 +98,15 @@ static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,
|
||||
case SNDRV_TIMER_IOCTL_PAUSE:
|
||||
case SNDRV_TIMER_IOCTL_PAUSE_OLD:
|
||||
case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
|
||||
return __snd_timer_user_ioctl(file, cmd, (unsigned long)argp);
|
||||
return __snd_timer_user_ioctl(file, cmd, (unsigned long)argp, true);
|
||||
case SNDRV_TIMER_IOCTL_GPARAMS32:
|
||||
return snd_timer_user_gparams_compat(file, argp);
|
||||
case SNDRV_TIMER_IOCTL_INFO32:
|
||||
return snd_timer_user_info_compat(file, argp);
|
||||
case SNDRV_TIMER_IOCTL_STATUS32:
|
||||
return snd_timer_user_status_compat(file, argp);
|
||||
#ifdef CONFIG_X86_X32
|
||||
case SNDRV_TIMER_IOCTL_STATUS_X32:
|
||||
return snd_timer_user_status_x32(file, argp);
|
||||
#endif /* CONFIG_X86_X32 */
|
||||
case SNDRV_TIMER_IOCTL_STATUS_COMPAT32:
|
||||
return snd_timer_user_status32(file, argp);
|
||||
case SNDRV_TIMER_IOCTL_STATUS_COMPAT64:
|
||||
return snd_timer_user_status64(file, argp);
|
||||
}
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
@ -804,7 +804,7 @@ static void loopback_snd_timer_tasklet(unsigned long arg)
|
||||
|
||||
static void loopback_snd_timer_event(struct snd_timer_instance *timeri,
|
||||
int event,
|
||||
struct timespec *tstamp,
|
||||
struct timespec64 *tstamp,
|
||||
unsigned long resolution)
|
||||
{
|
||||
/* Do not lock cable->lock here because timer->lock is already hold.
|
||||
@ -905,12 +905,6 @@ static void loopback_runtime_free(struct snd_pcm_runtime *runtime)
|
||||
kfree(dpcm);
|
||||
}
|
||||
|
||||
static int loopback_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
|
||||
}
|
||||
|
||||
static int loopback_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
@ -920,7 +914,7 @@ static int loopback_hw_free(struct snd_pcm_substream *substream)
|
||||
mutex_lock(&dpcm->loopback->cable_lock);
|
||||
cable->valid &= ~(1 << substream->stream);
|
||||
mutex_unlock(&dpcm->loopback->cable_lock);
|
||||
return snd_pcm_lib_free_pages(substream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int get_cable_index(struct snd_pcm_substream *substream)
|
||||
@ -1305,8 +1299,6 @@ static int loopback_close(struct snd_pcm_substream *substream)
|
||||
static const struct snd_pcm_ops loopback_pcm_ops = {
|
||||
.open = loopback_open,
|
||||
.close = loopback_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = loopback_hw_params,
|
||||
.hw_free = loopback_hw_free,
|
||||
.prepare = loopback_prepare,
|
||||
.trigger = loopback_trigger,
|
||||
@ -1325,8 +1317,7 @@ static int loopback_pcm_new(struct loopback *loopback,
|
||||
return err;
|
||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &loopback_pcm_ops);
|
||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &loopback_pcm_ops);
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
|
||||
NULL, 0, 0);
|
||||
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
|
||||
|
||||
pcm->private_data = loopback;
|
||||
pcm->info_flags = 0;
|
||||
@ -1505,7 +1496,7 @@ static int loopback_channels_get(struct snd_kcontrol *kcontrol,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_kcontrol_new loopback_controls[] = {
|
||||
static const struct snd_kcontrol_new loopback_controls[] = {
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
|
||||
.name = "PCM Rate Shift 100000",
|
||||
|
@ -117,7 +117,7 @@ struct dummy_model {
|
||||
|
||||
struct snd_dummy {
|
||||
struct snd_card *card;
|
||||
struct dummy_model *model;
|
||||
const struct dummy_model *model;
|
||||
struct snd_pcm *pcm;
|
||||
struct snd_pcm_hardware pcm_hw;
|
||||
spinlock_t mixer_lock;
|
||||
@ -144,13 +144,13 @@ static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dummy_model model_emu10k1 = {
|
||||
static const struct dummy_model model_emu10k1 = {
|
||||
.name = "emu10k1",
|
||||
.playback_constraints = emu10k1_playback_constraints,
|
||||
.buffer_bytes_max = 128 * 1024,
|
||||
};
|
||||
|
||||
static struct dummy_model model_rme9652 = {
|
||||
static const struct dummy_model model_rme9652 = {
|
||||
.name = "rme9652",
|
||||
.buffer_bytes_max = 26 * 64 * 1024,
|
||||
.formats = SNDRV_PCM_FMTBIT_S32_LE,
|
||||
@ -160,7 +160,7 @@ static struct dummy_model model_rme9652 = {
|
||||
.periods_max = 2,
|
||||
};
|
||||
|
||||
static struct dummy_model model_ice1712 = {
|
||||
static const struct dummy_model model_ice1712 = {
|
||||
.name = "ice1712",
|
||||
.buffer_bytes_max = 256 * 1024,
|
||||
.formats = SNDRV_PCM_FMTBIT_S32_LE,
|
||||
@ -170,7 +170,7 @@ static struct dummy_model model_ice1712 = {
|
||||
.periods_max = 1024,
|
||||
};
|
||||
|
||||
static struct dummy_model model_uda1341 = {
|
||||
static const struct dummy_model model_uda1341 = {
|
||||
.name = "uda1341",
|
||||
.buffer_bytes_max = 16380,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
@ -180,7 +180,7 @@ static struct dummy_model model_uda1341 = {
|
||||
.periods_max = 255,
|
||||
};
|
||||
|
||||
static struct dummy_model model_ac97 = {
|
||||
static const struct dummy_model model_ac97 = {
|
||||
.name = "ac97",
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.channels_min = 2,
|
||||
@ -190,7 +190,7 @@ static struct dummy_model model_ac97 = {
|
||||
.rate_max = 48000,
|
||||
};
|
||||
|
||||
static struct dummy_model model_ca0106 = {
|
||||
static const struct dummy_model model_ca0106 = {
|
||||
.name = "ca0106",
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.buffer_bytes_max = ((65536-64)*8),
|
||||
@ -204,7 +204,7 @@ static struct dummy_model model_ca0106 = {
|
||||
.rate_max = 192000,
|
||||
};
|
||||
|
||||
static struct dummy_model *dummy_models[] = {
|
||||
static const struct dummy_model *dummy_models[] = {
|
||||
&model_emu10k1,
|
||||
&model_rme9652,
|
||||
&model_ice1712,
|
||||
@ -529,21 +529,13 @@ static int dummy_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
substream->runtime->dma_bytes = params_buffer_bytes(hw_params);
|
||||
return 0;
|
||||
}
|
||||
return snd_pcm_lib_malloc_pages(substream,
|
||||
params_buffer_bytes(hw_params));
|
||||
}
|
||||
|
||||
static int dummy_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
if (fake_buffer)
|
||||
return 0;
|
||||
return snd_pcm_lib_free_pages(substream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_pcm_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
|
||||
struct dummy_model *model = dummy->model;
|
||||
const struct dummy_model *model = dummy->model;
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
const struct dummy_timer_ops *ops;
|
||||
int err;
|
||||
@ -652,23 +644,19 @@ static struct page *dummy_pcm_page(struct snd_pcm_substream *substream,
|
||||
return virt_to_page(dummy_page[substream->stream]); /* the same page */
|
||||
}
|
||||
|
||||
static struct snd_pcm_ops dummy_pcm_ops = {
|
||||
static const struct snd_pcm_ops dummy_pcm_ops = {
|
||||
.open = dummy_pcm_open,
|
||||
.close = dummy_pcm_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = dummy_pcm_hw_params,
|
||||
.hw_free = dummy_pcm_hw_free,
|
||||
.prepare = dummy_pcm_prepare,
|
||||
.trigger = dummy_pcm_trigger,
|
||||
.pointer = dummy_pcm_pointer,
|
||||
};
|
||||
|
||||
static struct snd_pcm_ops dummy_pcm_ops_no_buf = {
|
||||
static const struct snd_pcm_ops dummy_pcm_ops_no_buf = {
|
||||
.open = dummy_pcm_open,
|
||||
.close = dummy_pcm_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = dummy_pcm_hw_params,
|
||||
.hw_free = dummy_pcm_hw_free,
|
||||
.prepare = dummy_pcm_prepare,
|
||||
.trigger = dummy_pcm_trigger,
|
||||
.pointer = dummy_pcm_pointer,
|
||||
@ -682,7 +670,7 @@ static int snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
|
||||
int substreams)
|
||||
{
|
||||
struct snd_pcm *pcm;
|
||||
struct snd_pcm_ops *ops;
|
||||
const struct snd_pcm_ops *ops;
|
||||
int err;
|
||||
|
||||
err = snd_pcm_new(dummy->card, "Dummy PCM", device,
|
||||
@ -700,7 +688,7 @@ static int snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
|
||||
pcm->info_flags = 0;
|
||||
strcpy(pcm->name, "Dummy PCM");
|
||||
if (!fake_buffer) {
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm,
|
||||
snd_pcm_set_managed_buffer_all(pcm,
|
||||
SNDRV_DMA_TYPE_CONTINUOUS,
|
||||
NULL,
|
||||
0, 64*1024);
|
||||
@ -861,7 +849,7 @@ static int snd_dummy_iobox_put(struct snd_kcontrol *kcontrol,
|
||||
return changed;
|
||||
}
|
||||
|
||||
static struct snd_kcontrol_new snd_dummy_controls[] = {
|
||||
static const struct snd_kcontrol_new snd_dummy_controls[] = {
|
||||
DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER),
|
||||
DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER),
|
||||
DUMMY_VOLUME("Synth Volume", 0, MIXER_ADDR_SYNTH),
|
||||
@ -924,7 +912,7 @@ static void print_formats(struct snd_dummy *dummy,
|
||||
static void print_rates(struct snd_dummy *dummy,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
static int rates[] = {
|
||||
static const int rates[] = {
|
||||
5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000,
|
||||
64000, 88200, 96000, 176400, 192000,
|
||||
};
|
||||
@ -956,7 +944,7 @@ struct dummy_hw_field {
|
||||
.offset = offsetof(struct snd_pcm_hardware, item), \
|
||||
.size = sizeof(dummy_pcm_hardware.item) }
|
||||
|
||||
static struct dummy_hw_field fields[] = {
|
||||
static const struct dummy_hw_field fields[] = {
|
||||
FIELD_ENTRY(formats, "%#llx"),
|
||||
FIELD_ENTRY(rates, "%#x"),
|
||||
FIELD_ENTRY(rate_min, "%d"),
|
||||
@ -1034,7 +1022,7 @@ static int snd_dummy_probe(struct platform_device *devptr)
|
||||
{
|
||||
struct snd_card *card;
|
||||
struct snd_dummy *dummy;
|
||||
struct dummy_model *m = NULL, **mdl;
|
||||
const struct dummy_model *m = NULL, **mdl;
|
||||
int idx, err;
|
||||
int dev = devptr->id;
|
||||
|
||||
|
@ -670,23 +670,6 @@ snd_ml403_ac97cr_pcm_capture_prepare(struct snd_pcm_substream *substream)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_ml403_ac97cr_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
PDEBUG(WORK_INFO, "hw_free()\n");
|
||||
return snd_pcm_lib_free_pages(substream);
|
||||
}
|
||||
|
||||
static int
|
||||
snd_ml403_ac97cr_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *hw_params)
|
||||
{
|
||||
PDEBUG(WORK_INFO, "hw_params(): desired buffer bytes=%d, desired "
|
||||
"period bytes=%d\n",
|
||||
params_buffer_bytes(hw_params), params_period_bytes(hw_params));
|
||||
return snd_pcm_lib_malloc_pages(substream,
|
||||
params_buffer_bytes(hw_params));
|
||||
}
|
||||
|
||||
static int snd_ml403_ac97cr_playback_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_ml403_ac97cr *ml403_ac97cr;
|
||||
@ -748,9 +731,6 @@ static int snd_ml403_ac97cr_capture_close(struct snd_pcm_substream *substream)
|
||||
static const struct snd_pcm_ops snd_ml403_ac97cr_playback_ops = {
|
||||
.open = snd_ml403_ac97cr_playback_open,
|
||||
.close = snd_ml403_ac97cr_playback_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = snd_ml403_ac97cr_hw_params,
|
||||
.hw_free = snd_ml403_ac97cr_hw_free,
|
||||
.prepare = snd_ml403_ac97cr_pcm_playback_prepare,
|
||||
.trigger = snd_ml403_ac97cr_pcm_playback_trigger,
|
||||
.pointer = snd_ml403_ac97cr_pcm_pointer,
|
||||
@ -759,9 +739,6 @@ static const struct snd_pcm_ops snd_ml403_ac97cr_playback_ops = {
|
||||
static const struct snd_pcm_ops snd_ml403_ac97cr_capture_ops = {
|
||||
.open = snd_ml403_ac97cr_capture_open,
|
||||
.close = snd_ml403_ac97cr_capture_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = snd_ml403_ac97cr_hw_params,
|
||||
.hw_free = snd_ml403_ac97cr_hw_free,
|
||||
.prepare = snd_ml403_ac97cr_pcm_capture_prepare,
|
||||
.trigger = snd_ml403_ac97cr_pcm_capture_trigger,
|
||||
.pointer = snd_ml403_ac97cr_pcm_pointer,
|
||||
@ -1099,7 +1076,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
|
||||
{
|
||||
struct snd_ml403_ac97cr *ml403_ac97cr;
|
||||
int err;
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_free = snd_ml403_ac97cr_dev_free,
|
||||
};
|
||||
struct resource *resource;
|
||||
@ -1195,7 +1172,7 @@ snd_ml403_ac97cr_mixer(struct snd_ml403_ac97cr *ml403_ac97cr)
|
||||
struct snd_ac97_bus *bus;
|
||||
struct snd_ac97_template ac97;
|
||||
int err;
|
||||
static struct snd_ac97_bus_ops ops = {
|
||||
static const struct snd_ac97_bus_ops ops = {
|
||||
.write = snd_ml403_ac97cr_codec_write,
|
||||
.read = snd_ml403_ac97cr_codec_read,
|
||||
};
|
||||
@ -1241,10 +1218,10 @@ snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device)
|
||||
strcpy(pcm->name, "ML403AC97CR DAC/ADC");
|
||||
ml403_ac97cr->pcm = pcm;
|
||||
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
|
||||
NULL,
|
||||
64 * 1024,
|
||||
128 * 1024);
|
||||
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
|
||||
NULL,
|
||||
64 * 1024,
|
||||
128 * 1024);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -261,7 +261,7 @@ static int mts64_device_close(struct mts64 *mts)
|
||||
*/
|
||||
static u8 mts64_map_midi_input(u8 c)
|
||||
{
|
||||
static u8 map[] = { 0, 1, 4, 2, 3 };
|
||||
static const u8 map[] = { 0, 1, 4, 2, 3 };
|
||||
|
||||
return map[c];
|
||||
}
|
||||
@ -353,7 +353,7 @@ static void mts64_smpte_start(struct parport *p,
|
||||
u8 seconds, u8 frames,
|
||||
u8 idx)
|
||||
{
|
||||
static u8 fps[5] = { MTS64_CMD_SMPTE_FPS_24,
|
||||
static const u8 fps[5] = { MTS64_CMD_SMPTE_FPS_24,
|
||||
MTS64_CMD_SMPTE_FPS_25,
|
||||
MTS64_CMD_SMPTE_FPS_2997,
|
||||
MTS64_CMD_SMPTE_FPS_30D,
|
||||
@ -467,7 +467,7 @@ __out:
|
||||
return changed;
|
||||
}
|
||||
|
||||
static struct snd_kcontrol_new mts64_ctl_smpte_switch = {
|
||||
static const struct snd_kcontrol_new mts64_ctl_smpte_switch = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
|
||||
.name = "SMPTE Playback Switch",
|
||||
.index = 0,
|
||||
@ -540,7 +540,7 @@ static int snd_mts64_ctl_smpte_time_put(struct snd_kcontrol *kctl,
|
||||
return changed;
|
||||
}
|
||||
|
||||
static struct snd_kcontrol_new mts64_ctl_smpte_time_hours = {
|
||||
static const struct snd_kcontrol_new mts64_ctl_smpte_time_hours = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
|
||||
.name = "SMPTE Time Hours",
|
||||
.index = 0,
|
||||
@ -551,7 +551,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_hours = {
|
||||
.put = snd_mts64_ctl_smpte_time_put
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes = {
|
||||
static const struct snd_kcontrol_new mts64_ctl_smpte_time_minutes = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
|
||||
.name = "SMPTE Time Minutes",
|
||||
.index = 0,
|
||||
@ -562,7 +562,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes = {
|
||||
.put = snd_mts64_ctl_smpte_time_put
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds = {
|
||||
static const struct snd_kcontrol_new mts64_ctl_smpte_time_seconds = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
|
||||
.name = "SMPTE Time Seconds",
|
||||
.index = 0,
|
||||
@ -573,7 +573,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds = {
|
||||
.put = snd_mts64_ctl_smpte_time_put
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new mts64_ctl_smpte_time_frames = {
|
||||
static const struct snd_kcontrol_new mts64_ctl_smpte_time_frames = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
|
||||
.name = "SMPTE Time Frames",
|
||||
.index = 0,
|
||||
@ -625,7 +625,7 @@ static int snd_mts64_ctl_smpte_fps_put(struct snd_kcontrol *kctl,
|
||||
return changed;
|
||||
}
|
||||
|
||||
static struct snd_kcontrol_new mts64_ctl_smpte_fps = {
|
||||
static const struct snd_kcontrol_new mts64_ctl_smpte_fps = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
|
||||
.name = "SMPTE Fps",
|
||||
.index = 0,
|
||||
@ -641,7 +641,7 @@ static int snd_mts64_ctl_create(struct snd_card *card,
|
||||
struct mts64 *mts)
|
||||
{
|
||||
int err, i;
|
||||
static struct snd_kcontrol_new *control[] = {
|
||||
static const struct snd_kcontrol_new *control[] = {
|
||||
&mts64_ctl_smpte_switch,
|
||||
&mts64_ctl_smpte_time_hours,
|
||||
&mts64_ctl_smpte_time_minutes,
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include "opl3_voice.h"
|
||||
|
||||
static char snd_opl3_drum_table[47] =
|
||||
static const char snd_opl3_drum_table[47] =
|
||||
{
|
||||
OPL3_BASSDRUM_ON, OPL3_BASSDRUM_ON, OPL3_HIHAT_ON, /* 35 - 37 */
|
||||
OPL3_SNAREDRUM_ON, OPL3_HIHAT_ON, OPL3_SNAREDRUM_ON, /* 38 - 40 */
|
||||
@ -47,25 +47,25 @@ struct snd_opl3_drum_note {
|
||||
unsigned char feedback_connection;
|
||||
};
|
||||
|
||||
static struct snd_opl3_drum_voice bass_op0 = {6, 0, 0x00, 0x32, 0xf8, 0x66, 0x30, 0x00};
|
||||
static struct snd_opl3_drum_voice bass_op1 = {6, 1, 0x00, 0x03, 0xf6, 0x57, 0x30, 0x00};
|
||||
static struct snd_opl3_drum_note bass_note = {6, 0x90, 0x09};
|
||||
static const struct snd_opl3_drum_voice bass_op0 = {6, 0, 0x00, 0x32, 0xf8, 0x66, 0x30, 0x00};
|
||||
static const struct snd_opl3_drum_voice bass_op1 = {6, 1, 0x00, 0x03, 0xf6, 0x57, 0x30, 0x00};
|
||||
static const struct snd_opl3_drum_note bass_note = {6, 0x90, 0x09};
|
||||
|
||||
static struct snd_opl3_drum_voice hihat = {7, 0, 0x00, 0x03, 0xf0, 0x06, 0x20, 0x00};
|
||||
static const struct snd_opl3_drum_voice hihat = {7, 0, 0x00, 0x03, 0xf0, 0x06, 0x20, 0x00};
|
||||
|
||||
static struct snd_opl3_drum_voice snare = {7, 1, 0x00, 0x03, 0xf0, 0x07, 0x20, 0x02};
|
||||
static struct snd_opl3_drum_note snare_note = {7, 0xf4, 0x0d};
|
||||
static const struct snd_opl3_drum_voice snare = {7, 1, 0x00, 0x03, 0xf0, 0x07, 0x20, 0x02};
|
||||
static const struct snd_opl3_drum_note snare_note = {7, 0xf4, 0x0d};
|
||||
|
||||
static struct snd_opl3_drum_voice tomtom = {8, 0, 0x02, 0x03, 0xf0, 0x06, 0x10, 0x00};
|
||||
static struct snd_opl3_drum_note tomtom_note = {8, 0xf4, 0x09};
|
||||
static const struct snd_opl3_drum_voice tomtom = {8, 0, 0x02, 0x03, 0xf0, 0x06, 0x10, 0x00};
|
||||
static const struct snd_opl3_drum_note tomtom_note = {8, 0xf4, 0x09};
|
||||
|
||||
static struct snd_opl3_drum_voice cymbal = {8, 1, 0x04, 0x03, 0xf0, 0x06, 0x10, 0x00};
|
||||
static const struct snd_opl3_drum_voice cymbal = {8, 1, 0x04, 0x03, 0xf0, 0x06, 0x10, 0x00};
|
||||
|
||||
/*
|
||||
* set drum voice characteristics
|
||||
*/
|
||||
static void snd_opl3_drum_voice_set(struct snd_opl3 *opl3,
|
||||
struct snd_opl3_drum_voice *data)
|
||||
const struct snd_opl3_drum_voice *data)
|
||||
{
|
||||
unsigned char op_offset = snd_opl3_regmap[data->voice][data->op];
|
||||
unsigned char voice_offset = data->voice;
|
||||
@ -100,7 +100,7 @@ static void snd_opl3_drum_voice_set(struct snd_opl3 *opl3,
|
||||
* Set drum voice pitch
|
||||
*/
|
||||
static void snd_opl3_drum_note_set(struct snd_opl3 *opl3,
|
||||
struct snd_opl3_drum_note *data)
|
||||
const struct snd_opl3_drum_note *data)
|
||||
{
|
||||
unsigned char voice_offset = data->voice;
|
||||
unsigned short opl3_reg;
|
||||
@ -118,7 +118,7 @@ static void snd_opl3_drum_note_set(struct snd_opl3 *opl3,
|
||||
* Set drum voice volume and position
|
||||
*/
|
||||
static void snd_opl3_drum_vol_set(struct snd_opl3 *opl3,
|
||||
struct snd_opl3_drum_voice *data,
|
||||
const struct snd_opl3_drum_voice *data,
|
||||
int vel, struct snd_midi_channel *chan)
|
||||
{
|
||||
unsigned char op_offset = snd_opl3_regmap[data->voice][data->op];
|
||||
@ -170,7 +170,7 @@ void snd_opl3_drum_switch(struct snd_opl3 *opl3, int note, int vel, int on_off,
|
||||
struct snd_midi_channel *chan)
|
||||
{
|
||||
unsigned char drum_mask;
|
||||
struct snd_opl3_drum_voice *drum_voice;
|
||||
const struct snd_opl3_drum_voice *drum_voice;
|
||||
|
||||
if (!(opl3->drum_reg & OPL3_PERCUSSION_ENABLE))
|
||||
return;
|
||||
|
@ -214,7 +214,7 @@ static int snd_opl3_timer2_stop(struct snd_timer * timer)
|
||||
|
||||
*/
|
||||
|
||||
static struct snd_timer_hardware snd_opl3_timer1 =
|
||||
static const struct snd_timer_hardware snd_opl3_timer1 =
|
||||
{
|
||||
.flags = SNDRV_TIMER_HW_STOP,
|
||||
.resolution = 80000,
|
||||
@ -223,7 +223,7 @@ static struct snd_timer_hardware snd_opl3_timer1 =
|
||||
.stop = snd_opl3_timer1_stop,
|
||||
};
|
||||
|
||||
static struct snd_timer_hardware snd_opl3_timer2 =
|
||||
static const struct snd_timer_hardware snd_opl3_timer2 =
|
||||
{
|
||||
.flags = SNDRV_TIMER_HW_STOP,
|
||||
.resolution = 320000,
|
||||
@ -332,7 +332,7 @@ int snd_opl3_new(struct snd_card *card,
|
||||
unsigned short hardware,
|
||||
struct snd_opl3 **ropl3)
|
||||
{
|
||||
static struct snd_device_ops ops = {
|
||||
static const struct snd_device_ops ops = {
|
||||
.dev_free = snd_opl3_dev_free,
|
||||
};
|
||||
struct snd_opl3 *opl3;
|
||||
|
@ -23,7 +23,7 @@ static void snd_opl3_note_off_unsafe(void *p, int note, int vel,
|
||||
* it saves a lot of log() calculations. (Rob Hooft <hooft@chem.ruu.nl>)
|
||||
*/
|
||||
|
||||
static char opl3_volume_table[128] =
|
||||
static const char opl3_volume_table[128] =
|
||||
{
|
||||
-63, -48, -40, -35, -32, -29, -27, -26,
|
||||
-24, -23, -21, -20, -19, -18, -18, -17,
|
||||
@ -69,7 +69,7 @@ void snd_opl3_calc_volume(unsigned char *volbyte, int vel,
|
||||
/*
|
||||
* Converts the note frequency to block and fnum values for the FM chip
|
||||
*/
|
||||
static short opl3_note_table[16] =
|
||||
static const short opl3_note_table[16] =
|
||||
{
|
||||
305, 323, /* for pitch bending, -2 semitones */
|
||||
343, 363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647,
|
||||
@ -266,7 +266,7 @@ static void snd_opl3_start_timer(struct snd_opl3 *opl3)
|
||||
/* ------------------------------ */
|
||||
|
||||
|
||||
static int snd_opl3_oss_map[MAX_OPL3_VOICES] = {
|
||||
static const int snd_opl3_oss_map[MAX_OPL3_VOICES] = {
|
||||
0, 1, 2, 9, 10, 11, 6, 7, 8, 15, 16, 17, 3, 4 ,5, 12, 13, 14
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@ static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg);
|
||||
|
||||
/* operators */
|
||||
|
||||
static struct snd_seq_oss_callback oss_callback = {
|
||||
static const struct snd_seq_oss_callback oss_callback = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = snd_opl3_open_seq_oss,
|
||||
.close = snd_opl3_close_seq_oss,
|
||||
|
@ -128,7 +128,7 @@ static int snd_opl3_synth_unuse(void *private_data, struct snd_seq_port_subscrib
|
||||
/*
|
||||
* MIDI emulation operators
|
||||
*/
|
||||
struct snd_midi_op opl3_ops = {
|
||||
const struct snd_midi_op opl3_ops = {
|
||||
.note_on = snd_opl3_note_on,
|
||||
.note_off = snd_opl3_note_off,
|
||||
.key_press = snd_opl3_key_press,
|
||||
|
@ -41,6 +41,6 @@ void snd_opl3_free_seq_oss(struct snd_opl3 *opl3);
|
||||
|
||||
extern char snd_opl3_regmap[MAX_OPL2_VOICES][4];
|
||||
extern bool use_internal_drums;
|
||||
extern struct snd_midi_op opl3_ops;
|
||||
extern const struct snd_midi_op opl3_ops;
|
||||
|
||||
#endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user