mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-18 02:46:06 +00:00
Merge branch 'for-next' into for-linus
Pull materials for 6.5 merge window. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
commit
b94a62a663
@ -162,8 +162,11 @@ Base 2 log and power Functions
|
||||
.. kernel-doc:: include/linux/log2.h
|
||||
:internal:
|
||||
|
||||
Integer power Functions
|
||||
-----------------------
|
||||
Integer log and power Functions
|
||||
-------------------------------
|
||||
|
||||
.. kernel-doc:: include/linux/int_log.h
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: lib/math/int_pow.c
|
||||
:export:
|
||||
|
64
Documentation/devicetree/bindings/sound/audio-iio-aux.yaml
Normal file
64
Documentation/devicetree/bindings/sound/audio-iio-aux.yaml
Normal file
@ -0,0 +1,64 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/audio-iio-aux.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Audio IIO auxiliary
|
||||
|
||||
maintainers:
|
||||
- Herve Codina <herve.codina@bootlin.com>
|
||||
|
||||
description:
|
||||
Auxiliary device based on Industrial I/O device channels
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: audio-iio-aux
|
||||
|
||||
io-channels:
|
||||
description:
|
||||
Industrial I/O device channels used
|
||||
|
||||
io-channel-names:
|
||||
description:
|
||||
Industrial I/O channel names related to io-channels.
|
||||
These names are used to provides sound controls, widgets and routes names.
|
||||
|
||||
snd-control-invert-range:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description: |
|
||||
A list of 0/1 flags defining whether or not the related channel is
|
||||
inverted
|
||||
items:
|
||||
enum: [0, 1]
|
||||
default: 0
|
||||
description: |
|
||||
Invert the sound control value compared to the IIO channel raw value.
|
||||
- 1: The related sound control value is inverted meaning that the
|
||||
minimum sound control value correspond to the maximum IIO channel
|
||||
raw value and the maximum sound control value correspond to the
|
||||
minimum IIO channel raw value.
|
||||
- 0: The related sound control value is not inverted meaning that the
|
||||
minimum (resp maximum) sound control value correspond to the
|
||||
minimum (resp maximum) IIO channel raw value.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- io-channels
|
||||
- io-channel-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
iio-aux {
|
||||
compatible = "audio-iio-aux";
|
||||
io-channels = <&iio 0>, <&iio 1>, <&iio 2>, <&iio 3>;
|
||||
io-channel-names = "CH0", "CH1", "CH2", "CH3";
|
||||
/* Invert CH1 and CH2 */
|
||||
snd-control-invert-range = <0 1 1 0>;
|
||||
};
|
@ -25,6 +25,7 @@ properties:
|
||||
- fsl,imx8mm-rpmsg-audio
|
||||
- fsl,imx8mp-rpmsg-audio
|
||||
- fsl,imx8ulp-rpmsg-audio
|
||||
- fsl,imx93-rpmsg-audio
|
||||
|
||||
model:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
|
@ -25,6 +25,12 @@ properties:
|
||||
reset-names:
|
||||
const: audiosys
|
||||
|
||||
memory-region:
|
||||
maxItems: 1
|
||||
description: |
|
||||
Shared memory region for AFE memif. A "shared-dma-pool".
|
||||
See ../reserved-memory/reserved-memory.yaml for details.
|
||||
|
||||
mediatek,topckgen:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: The phandle of the mediatek topckgen controller
|
||||
@ -176,6 +182,7 @@ examples:
|
||||
interrupts = <GIC_SPI 822 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||
resets = <&watchdog 14>;
|
||||
reset-names = "audiosys";
|
||||
memory-region = <&snd_dma_mem_reserved>;
|
||||
mediatek,topckgen = <&topckgen>;
|
||||
mediatek,infracfg = <&infracfg_ao>;
|
||||
power-domains = <&spm 13>; //MT8188_POWER_DOMAIN_AUDIO
|
||||
|
@ -1,55 +0,0 @@
|
||||
Nuvoton NAU88L21 audio codec
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
- compatible : Must be "nuvoton,nau8821"
|
||||
|
||||
- reg : the I2C address of the device. This is either 0x1B (CSB=0) or 0x54 (CSB=1).
|
||||
|
||||
Optional properties:
|
||||
- nuvoton,jkdet-enable: Enable jack detection via JKDET pin.
|
||||
- nuvoton,jkdet-pull-enable: Enable JKDET pin pull. If set - pin pull enabled,
|
||||
otherwise pin in high impedance state.
|
||||
- nuvoton,jkdet-pull-up: Pull-up JKDET pin. If set then JKDET pin is pull up, otherwise pull down.
|
||||
- nuvoton,jkdet-polarity: JKDET pin polarity. 0 - active high, 1 - active low.
|
||||
|
||||
- nuvoton,vref-impedance: VREF Impedance selection
|
||||
0 - Open
|
||||
1 - 25 kOhm
|
||||
2 - 125 kOhm
|
||||
3 - 2.5 kOhm
|
||||
|
||||
- nuvoton,micbias-voltage: Micbias voltage level.
|
||||
0 - VDDA
|
||||
1 - VDDA
|
||||
2 - VDDA * 1.1
|
||||
3 - VDDA * 1.2
|
||||
4 - VDDA * 1.3
|
||||
5 - VDDA * 1.4
|
||||
6 - VDDA * 1.53
|
||||
7 - VDDA * 1.53
|
||||
|
||||
- nuvoton,jack-insert-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms
|
||||
- nuvoton,jack-eject-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms
|
||||
|
||||
- nuvoton,dmic-clk-threshold: the ADC threshold of DMIC clock.
|
||||
- nuvoton,key_enable: Headset button detection switch.
|
||||
|
||||
Example:
|
||||
|
||||
headset: nau8821@1b {
|
||||
compatible = "nuvoton,nau8821";
|
||||
reg = <0x1b>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <23 IRQ_TYPE_LEVEL_LOW>;
|
||||
nuvoton,jkdet-enable;
|
||||
nuvoton,jkdet-pull-enable;
|
||||
nuvoton,jkdet-pull-up;
|
||||
nuvoton,jkdet-polarity = <GPIO_ACTIVE_LOW>;
|
||||
nuvoton,vref-impedance = <2>;
|
||||
nuvoton,micbias-voltage = <6>;
|
||||
nuvoton,jack-insert-debounce = <7>;
|
||||
nuvoton,jack-eject-debounce = <7>;
|
||||
nuvoton,dmic-clk-threshold = 3072000;
|
||||
};
|
125
Documentation/devicetree/bindings/sound/nuvoton,nau8821.yaml
Normal file
125
Documentation/devicetree/bindings/sound/nuvoton,nau8821.yaml
Normal file
@ -0,0 +1,125 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/nuvoton,nau8821.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NAU88L21 audio codec
|
||||
|
||||
maintainers:
|
||||
- Seven Lee <wtli@nuvoton.com>
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: nuvoton,nau8821
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
nuvoton,jkdet-enable:
|
||||
description: Enable jack detection via JKDET pin.
|
||||
type: boolean
|
||||
|
||||
nuvoton,jkdet-pull-enable:
|
||||
description: Enable JKDET pin pull. If set - pin pull enabled,
|
||||
otherwise pin in high impedance state.
|
||||
type: boolean
|
||||
|
||||
nuvoton,jkdet-pull-up:
|
||||
description: Pull-up JKDET pin. If set then JKDET pin is pull up,
|
||||
otherwise pull down.
|
||||
type: boolean
|
||||
|
||||
nuvoton,key-enable:
|
||||
description: handles key press detection.
|
||||
type: boolean
|
||||
|
||||
nuvoton,jkdet-polarity:
|
||||
description: JKDET pin polarity.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 0 # active high
|
||||
- 1 # active low
|
||||
default: 1
|
||||
|
||||
nuvoton,micbias-voltage:
|
||||
description: MICBIAS output level select.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 0 # VDDA
|
||||
- 1 # VDDA * 1
|
||||
- 2 # VDDA * 1.1
|
||||
- 3 # VDDA * 1.2
|
||||
- 4 # VDDA * 1.3
|
||||
- 5 # VDDA * 1.4
|
||||
- 6 # VDDA * 1.53
|
||||
- 7 # VDDA * 1.53
|
||||
default: 6
|
||||
|
||||
nuvoton,vref-impedance:
|
||||
description: VMID Tie-off impedance select.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 0 # open
|
||||
- 1 # 25KOhms
|
||||
- 2 # 125KOhms
|
||||
- 3 # 2.5KOhms
|
||||
default: 2
|
||||
|
||||
nuvoton,jack-insert-debounce:
|
||||
description: number from 0 to 7 that sets debounce time to 2^(n+2)ms.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
maximum: 7
|
||||
default: 7
|
||||
|
||||
nuvoton,jack-eject-debounce:
|
||||
description: number from 0 to 7 that sets debounce time to 2^(n+2)ms.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
maximum: 7
|
||||
default: 0
|
||||
|
||||
nuvoton,dmic-clk-threshold:
|
||||
description: DMIC clock speed expected value. Unit is Hz.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
default: 3072000
|
||||
|
||||
'#sound-dai-cells':
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
codec@1b {
|
||||
compatible = "nuvoton,nau8821";
|
||||
reg = <0x1b>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <23 IRQ_TYPE_LEVEL_LOW>;
|
||||
nuvoton,jkdet-enable;
|
||||
nuvoton,jkdet-pull-enable;
|
||||
nuvoton,jkdet-pull-up;
|
||||
nuvoton,key-enable;
|
||||
nuvoton,jkdet-polarity = <GPIO_ACTIVE_LOW>;
|
||||
nuvoton,micbias-voltage = <6>;
|
||||
nuvoton,vref-impedance = <2>;
|
||||
nuvoton,jack-insert-debounce = <7>;
|
||||
nuvoton,jack-eject-debounce = <0>;
|
||||
nuvoton,dmic-clk-threshold = <3072000>;
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
};
|
@ -21,6 +21,15 @@ properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
const: mclk
|
||||
|
||||
nuvoton,spk-btl:
|
||||
description:
|
||||
If set, configure the two loudspeaker outputs as a Bridge Tied Load output
|
||||
@ -31,6 +40,9 @@ required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
@ -1,101 +0,0 @@
|
||||
msm8916 analog audio CODEC
|
||||
|
||||
Bindings for codec Analog IP which is integrated in pmic pm8916,
|
||||
|
||||
## Bindings for codec core on pmic:
|
||||
|
||||
Required properties
|
||||
- compatible = "qcom,pm8916-wcd-analog-codec";
|
||||
- reg: represents the slave base address provided to the peripheral.
|
||||
- interrupts: List of interrupts in given SPMI peripheral.
|
||||
- interrupt-names: Names specified to above list of interrupts in same
|
||||
order. List of supported interrupt names are:
|
||||
"cdc_spk_cnp_int" - Speaker click and pop interrupt.
|
||||
"cdc_spk_clip_int" - Speaker clip interrupt.
|
||||
"cdc_spk_ocp_int" - Speaker over current protect interrupt.
|
||||
"mbhc_ins_rem_det1" - jack insert removal detect interrupt 1.
|
||||
"mbhc_but_rel_det" - button release interrupt.
|
||||
"mbhc_but_press_det" - button press event
|
||||
"mbhc_ins_rem_det" - jack insert removal detect interrupt.
|
||||
"mbhc_switch_int" - multi button headset interrupt.
|
||||
"cdc_ear_ocp_int" - Earphone over current protect interrupt.
|
||||
"cdc_hphr_ocp_int" - Headphone R over current protect interrupt.
|
||||
"cdc_hphl_ocp_det" - Headphone L over current protect interrupt.
|
||||
"cdc_ear_cnp_int" - earphone cnp interrupt.
|
||||
"cdc_hphr_cnp_int" - hphr click and pop interrupt.
|
||||
"cdc_hphl_cnp_int" - hphl click and pop interrupt.
|
||||
|
||||
- clocks: Handle to mclk.
|
||||
- clock-names: should be "mclk"
|
||||
- vdd-cdc-io-supply: phandle to VDD_CDC_IO regulator DT node.
|
||||
- vdd-cdc-tx-rx-cx-supply: phandle to VDD_CDC_TX/RX/CX regulator DT node.
|
||||
- vdd-micbias-supply: phandle of VDD_MICBIAS supply's regulator DT node.
|
||||
|
||||
Optional Properties:
|
||||
- qcom,mbhc-vthreshold-low: Array of 5 threshold voltages in mV for 5 buttons
|
||||
detection on headset when the mbhc is powered up
|
||||
by internal current source, this is a low power.
|
||||
- qcom,mbhc-vthreshold-high: Array of 5 thresold voltages in mV for 5 buttons
|
||||
detection on headset when mbhc is powered up
|
||||
from micbias.
|
||||
- qcom,micbias-lvl: Voltage (mV) for Mic Bias
|
||||
- qcom,hphl-jack-type-normally-open: boolean, present if hphl pin on jack is a
|
||||
NO (Normally Open). If not specified, then
|
||||
its assumed that hphl pin on jack is NC
|
||||
(Normally Closed).
|
||||
- qcom,gnd-jack-type-normally-open: boolean, present if gnd pin on jack is
|
||||
NO (Normally Open). If not specified, then
|
||||
its assumed that gnd pin on jack is NC
|
||||
(Normally Closed).
|
||||
- qcom,micbias1-ext-cap: boolean, present if micbias1 has external capacitor
|
||||
connected.
|
||||
- qcom,micbias2-ext-cap: boolean, present if micbias2 has external capacitor
|
||||
connected.
|
||||
|
||||
Example:
|
||||
|
||||
spmi_bus {
|
||||
...
|
||||
audio-codec@f000{
|
||||
compatible = "qcom,pm8916-wcd-analog-codec";
|
||||
reg = <0xf000 0x200>;
|
||||
reg-names = "pmic-codec-core";
|
||||
clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>;
|
||||
clock-names = "mclk";
|
||||
qcom,mbhc-vthreshold-low = <75 150 237 450 500>;
|
||||
qcom,mbhc-vthreshold-high = <75 150 237 450 500>;
|
||||
interrupt-parent = <&spmi_bus>;
|
||||
interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf0 0x1 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf0 0x2 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf0 0x3 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf0 0x4 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf0 0x5 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf0 0x6 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf0 0x7 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf1 0x0 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf1 0x1 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf1 0x2 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf1 0x3 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf1 0x4 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf1 0x5 IRQ_TYPE_NONE>;
|
||||
interrupt-names = "cdc_spk_cnp_int",
|
||||
"cdc_spk_clip_int",
|
||||
"cdc_spk_ocp_int",
|
||||
"mbhc_ins_rem_det1",
|
||||
"mbhc_but_rel_det",
|
||||
"mbhc_but_press_det",
|
||||
"mbhc_ins_rem_det",
|
||||
"mbhc_switch_int",
|
||||
"cdc_ear_ocp_int",
|
||||
"cdc_hphr_ocp_int",
|
||||
"cdc_hphl_ocp_det",
|
||||
"cdc_ear_cnp_int",
|
||||
"cdc_hphr_cnp_int",
|
||||
"cdc_hphl_cnp_int";
|
||||
vdd-cdc-io-supply = <&pm8916_l5>;
|
||||
vdd-cdc-tx-rx-cx-supply = <&pm8916_l5>;
|
||||
vdd-micbias-supply = <&pm8916_l13>;
|
||||
#sound-dai-cells = <1>;
|
||||
};
|
||||
};
|
@ -0,0 +1,153 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/qcom,pm8916-wcd-analog-codec.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm PM8916 WCD Analog Audio Codec
|
||||
|
||||
maintainers:
|
||||
- Konrad Dybcio <konradybcio@kernel.org>
|
||||
|
||||
description:
|
||||
The analog WCD audio codec found on Qualcomm PM8916 PMIC.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,pm8916-wcd-analog-codec
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 14
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: cdc_spk_cnp_int
|
||||
- const: cdc_spk_clip_int
|
||||
- const: cdc_spk_ocp_int
|
||||
- const: mbhc_ins_rem_det1
|
||||
- const: mbhc_but_rel_det
|
||||
- const: mbhc_but_press_det
|
||||
- const: mbhc_ins_rem_det
|
||||
- const: mbhc_switch_int
|
||||
- const: cdc_ear_ocp_int
|
||||
- const: cdc_hphr_ocp_int
|
||||
- const: cdc_hphl_ocp_det
|
||||
- const: cdc_ear_cnp_int
|
||||
- const: cdc_hphr_cnp_int
|
||||
- const: cdc_hphl_cnp_int
|
||||
|
||||
vdd-cdc-io-supply:
|
||||
description: 1.8V buck supply
|
||||
|
||||
vdd-cdc-tx-rx-cx-supply:
|
||||
description: 1.8V SIDO buck supply
|
||||
|
||||
vdd-micbias-supply:
|
||||
description: micbias supply
|
||||
|
||||
qcom,mbhc-vthreshold-low:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description:
|
||||
Array of 5 threshold voltages in mV for 5-button detection on
|
||||
headset when MBHC is powered by an internal current source.
|
||||
minItems: 5
|
||||
maxItems: 5
|
||||
|
||||
qcom,mbhc-vthreshold-high:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description:
|
||||
Array of 5 threshold voltages in mV for 5-button detection on
|
||||
headset when MBHC is powered from micbias.
|
||||
minItems: 5
|
||||
maxItems: 5
|
||||
|
||||
qcom,micbias-lvl:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
Voltage (mV) for Mic Bias
|
||||
|
||||
qcom,hphl-jack-type-normally-open:
|
||||
type: boolean
|
||||
description:
|
||||
True if the HPHL pin on the jack is NO (Normally Open), false if it's
|
||||
NC (Normally Closed).
|
||||
|
||||
qcom,gnd-jack-type-normally-open:
|
||||
type: boolean
|
||||
description:
|
||||
True if the GND pin on the jack is NO (Normally Open), false if it's
|
||||
NC (Normally Closed).
|
||||
|
||||
qcom,micbias1-ext-cap:
|
||||
type: boolean
|
||||
description:
|
||||
True if micbias1 has an external capacitor.
|
||||
|
||||
qcom,micbias2-ext-cap:
|
||||
type: boolean
|
||||
description:
|
||||
True if micbias2 has an external capacitor.
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/spmi/spmi.h>
|
||||
|
||||
pmic@1 {
|
||||
compatible = "qcom,pm8916", "qcom,spmi-pmic";
|
||||
reg = <0x1 SPMI_USID>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
audio-codec@f000 {
|
||||
compatible = "qcom,pm8916-wcd-analog-codec";
|
||||
reg = <0xf000>;
|
||||
qcom,mbhc-vthreshold-low = <75 150 237 450 500>;
|
||||
qcom,mbhc-vthreshold-high = <75 150 237 450 500>;
|
||||
interrupt-parent = <&spmi_bus>;
|
||||
interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf0 0x1 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf0 0x2 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf0 0x3 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf0 0x4 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf0 0x5 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf0 0x6 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf0 0x7 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf1 0x0 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf1 0x1 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf1 0x2 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf1 0x3 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf1 0x4 IRQ_TYPE_NONE>,
|
||||
<0x1 0xf1 0x5 IRQ_TYPE_NONE>;
|
||||
interrupt-names = "cdc_spk_cnp_int",
|
||||
"cdc_spk_clip_int",
|
||||
"cdc_spk_ocp_int",
|
||||
"mbhc_ins_rem_det1",
|
||||
"mbhc_but_rel_det",
|
||||
"mbhc_but_press_det",
|
||||
"mbhc_ins_rem_det",
|
||||
"mbhc_switch_int",
|
||||
"cdc_ear_ocp_int",
|
||||
"cdc_hphr_ocp_int",
|
||||
"cdc_hphl_ocp_det",
|
||||
"cdc_ear_cnp_int",
|
||||
"cdc_hphr_cnp_int",
|
||||
"cdc_hphl_cnp_int";
|
||||
vdd-cdc-io-supply = <&pm8916_l5>;
|
||||
vdd-cdc-tx-rx-cx-supply = <&pm8916_l5>;
|
||||
vdd-micbias-supply = <&pm8916_l13>;
|
||||
#sound-dai-cells = <1>;
|
||||
};
|
||||
};
|
@ -148,6 +148,15 @@ definitions:
|
||||
required:
|
||||
- sound-dai
|
||||
|
||||
additional-devs:
|
||||
type: object
|
||||
description:
|
||||
Additional devices used by the simple audio card.
|
||||
patternProperties:
|
||||
'^iio-aux(-.+)?$':
|
||||
type: object
|
||||
$ref: audio-iio-aux.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
@ -187,6 +196,8 @@ properties:
|
||||
$ref: "#/definitions/mclk-fs"
|
||||
simple-audio-card,aux-devs:
|
||||
$ref: "#/definitions/aux-devs"
|
||||
simple-audio-card,additional-devs:
|
||||
$ref: "#/definitions/additional-devs"
|
||||
simple-audio-card,convert-rate:
|
||||
$ref: "#/definitions/convert-rate"
|
||||
simple-audio-card,convert-channels:
|
||||
@ -359,6 +370,48 @@ examples:
|
||||
};
|
||||
};
|
||||
|
||||
# --------------------
|
||||
# route audio to/from a codec through an amplifier
|
||||
# designed with a potentiometer driven by IIO:
|
||||
# --------------------
|
||||
- |
|
||||
sound {
|
||||
compatible = "simple-audio-card";
|
||||
|
||||
simple-audio-card,aux-devs = <&_in>, <&_out>;
|
||||
simple-audio-card,routing =
|
||||
"CODEC LEFTIN", "AMP_IN LEFT OUT",
|
||||
"CODEC RIGHTIN", "AMP_IN RIGHT OUT",
|
||||
"AMP_OUT LEFT IN", "CODEC LEFTOUT",
|
||||
"AMP_OUT RIGHT IN", "CODEC RIGHTOUT";
|
||||
|
||||
simple-audio-card,additional-devs {
|
||||
amp_out: iio-aux-out {
|
||||
compatible = "audio-iio-aux";
|
||||
io-channels = <&pot_out 0>, <&pot_out 1>;
|
||||
io-channel-names = "LEFT", "RIGHT";
|
||||
snd-control-invert-range = <1 1>;
|
||||
sound-name-prefix = "AMP_OUT";
|
||||
};
|
||||
|
||||
amp_in: iio_aux-in {
|
||||
compatible = "audio-iio-aux";
|
||||
io-channels = <&pot_in 0>, <&pot_in 1>;
|
||||
io-channel-names = "LEFT", "RIGHT";
|
||||
sound-name-prefix = "AMP_IN";
|
||||
};
|
||||
};
|
||||
|
||||
simple-audio-card,cpu {
|
||||
sound-dai = <&cpu>;
|
||||
};
|
||||
|
||||
simple-audio-card,codec {
|
||||
sound-dai = <&codec>;
|
||||
clocks = <&clocks>;
|
||||
};
|
||||
};
|
||||
|
||||
# --------------------
|
||||
# Sampling Rate Conversion
|
||||
# --------------------
|
||||
|
74
Documentation/devicetree/bindings/sound/wlf,wm8904.yaml
Normal file
74
Documentation/devicetree/bindings/sound/wlf,wm8904.yaml
Normal file
@ -0,0 +1,74 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/wlf,wm8904.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Wolfson WM8904/WM8912 audio codecs
|
||||
|
||||
maintainers:
|
||||
- patches@opensource.cirrus.com
|
||||
|
||||
description: |
|
||||
Pins on the device (for linking into audio routes):
|
||||
IN1L, IN1R, IN2L, IN2R, IN3L, IN3R, HPOUTL, HPOUTR, LINEOUTL, LINEOUTR,
|
||||
MICBIAS
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- wlf,wm8904
|
||||
- wlf,wm8912
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
const: mclk
|
||||
|
||||
AVDD-supply: true
|
||||
CPVDD-supply: true
|
||||
DBVDD-supply: true
|
||||
DCVDD-supply: true
|
||||
MICVDD-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- AVDD-supply
|
||||
- CPVDD-supply
|
||||
- DBVDD-supply
|
||||
- DCVDD-supply
|
||||
- MICVDD-supply
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
codec@1a {
|
||||
compatible = "wlf,wm8904";
|
||||
reg = <0x1a>;
|
||||
clocks = <&pck0>;
|
||||
clock-names = "mclk";
|
||||
AVDD-supply = <®_1p8v>;
|
||||
CPVDD-supply = <®_1p8v>;
|
||||
DBVDD-supply = <®_1p8v>;
|
||||
DCVDD-supply = <®_1p8v>;
|
||||
MICVDD-supply = <®_1p8v>;
|
||||
};
|
||||
};
|
@ -1,33 +0,0 @@
|
||||
WM8904 audio CODEC
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
- compatible: "wlf,wm8904" or "wlf,wm8912"
|
||||
- reg: the I2C address of the device.
|
||||
- clock-names: "mclk"
|
||||
- clocks: reference to
|
||||
<Documentation/devicetree/bindings/clock/clock-bindings.txt>
|
||||
|
||||
Pins on the device (for linking into audio routes):
|
||||
|
||||
* IN1L
|
||||
* IN1R
|
||||
* IN2L
|
||||
* IN2R
|
||||
* IN3L
|
||||
* IN3R
|
||||
* HPOUTL
|
||||
* HPOUTR
|
||||
* LINEOUTL
|
||||
* LINEOUTR
|
||||
* MICBIAS
|
||||
|
||||
Examples:
|
||||
|
||||
codec: wm8904@1a {
|
||||
compatible = "wlf,wm8904";
|
||||
reg = <0x1a>;
|
||||
clocks = <&pck0>;
|
||||
clock-names = "mclk";
|
||||
};
|
@ -3,15 +3,6 @@
|
||||
Digital TV Common functions
|
||||
---------------------------
|
||||
|
||||
Math functions
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Provide some commonly-used math functions, usually required in order to
|
||||
estimate signal strength and signal to noise measurements in dB.
|
||||
|
||||
.. kernel-doc:: include/media/dvb_math.h
|
||||
|
||||
|
||||
DVB devices
|
||||
~~~~~~~~~~~
|
||||
|
||||
|
@ -46,157 +46,158 @@ FX-bus
|
||||
|
||||
name='PCM Front Playback Volume',index=0
|
||||
----------------------------------------
|
||||
This control is used to attenuate samples for left and right front PCM FX-bus
|
||||
This control is used to attenuate samples from left and right front PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 8 and 9 for left and right front PCM
|
||||
samples for 5.1 playback. The result samples are forwarded to the front DAC PCM
|
||||
slots of the Philips DAC.
|
||||
samples for 5.1 playback. The result samples are forwarded to the front speakers.
|
||||
|
||||
name='PCM Surround Playback Volume',index=0
|
||||
-------------------------------------------
|
||||
This control is used to attenuate samples for left and right surround PCM FX-bus
|
||||
This control is used to attenuate samples from left and right surround PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 2 and 3 for left and right surround PCM
|
||||
samples for 5.1 playback. The result samples are forwarded to the surround DAC PCM
|
||||
slots of the Philips DAC.
|
||||
samples for 5.1 playback. The result samples are forwarded to the surround (rear)
|
||||
speakers.
|
||||
|
||||
name='PCM Side Playback Volume',index=0
|
||||
---------------------------------------
|
||||
This control is used to attenuate samples from left and right side PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 14 and 15 for left and right side PCM
|
||||
samples for 7.1 playback. The result samples are forwarded to the side speakers.
|
||||
|
||||
name='PCM Center Playback Volume',index=0
|
||||
-----------------------------------------
|
||||
This control is used to attenuate samples for center PCM FX-bus accumulator.
|
||||
ALSA uses accumulator 6 for center PCM sample for 5.1 playback. The result sample
|
||||
is forwarded to the center DAC PCM slot of the Philips DAC.
|
||||
This control is used to attenuate samples from center PCM FX-bus accumulator.
|
||||
ALSA uses accumulator 6 for center PCM samples for 5.1 playback. The result
|
||||
samples are forwarded to the center speaker.
|
||||
|
||||
name='PCM LFE Playback Volume',index=0
|
||||
--------------------------------------
|
||||
This control is used to attenuate sample for LFE PCM FX-bus accumulator.
|
||||
ALSA uses accumulator 7 for LFE PCM sample for 5.1 playback. The result sample
|
||||
is forwarded to the LFE DAC PCM slot of the Philips DAC.
|
||||
ALSA uses accumulator 7 for LFE PCM samples for 5.1 playback. The result
|
||||
samples are forwarded to the subwoofer.
|
||||
|
||||
name='PCM Playback Volume',index=0
|
||||
----------------------------------
|
||||
This control is used to attenuate samples for left and right PCM FX-bus
|
||||
This control is used to attenuate samples from left and right PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples for
|
||||
stereo playback. The result samples are forwarded to the front DAC PCM slots
|
||||
of the Philips DAC.
|
||||
stereo playback. The result samples are forwarded to the front speakers.
|
||||
|
||||
name='PCM Capture Volume',index=0
|
||||
---------------------------------
|
||||
This control is used to attenuate samples for left and right PCM FX-bus
|
||||
accumulator. ALSA uses accumulators 0 and 1 for left and right PCM.
|
||||
The result is forwarded to the ADC capture FIFO (thus to the standard capture
|
||||
PCM device).
|
||||
This control is used to attenuate samples from left and right PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples for
|
||||
stereo playback. The result is forwarded to the standard capture PCM device.
|
||||
|
||||
name='Music Playback Volume',index=0
|
||||
------------------------------------
|
||||
This control is used to attenuate samples for left and right MIDI FX-bus
|
||||
This control is used to attenuate samples from left and right MIDI FX-bus
|
||||
accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
|
||||
The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
|
||||
The result samples are forwarded to the virtual stereo mixer.
|
||||
|
||||
name='Music Capture Volume',index=0
|
||||
-----------------------------------
|
||||
These controls are used to attenuate samples for left and right MIDI FX-bus
|
||||
accumulator. ALSA uses accumulators 4 and 5 for left and right PCM.
|
||||
The result is forwarded to the ADC capture FIFO (thus to the standard capture
|
||||
PCM device).
|
||||
These controls are used to attenuate samples from left and right MIDI FX-bus
|
||||
accumulator. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
|
||||
The result is forwarded to the standard capture PCM device.
|
||||
|
||||
name='Mic Playback Volume',index=0
|
||||
----------------------------------
|
||||
This control is used to attenuate samples for left and right Mic input.
|
||||
For Mic input is used AC97 codec. The result samples are forwarded to
|
||||
the front DAC PCM slots of the Philips DAC. Samples are forwarded to Mic
|
||||
capture FIFO (device 1 - 16bit/8KHz mono) too without volume control.
|
||||
This control is used to attenuate samples from left and right Mic input of
|
||||
the AC97 codec. The result samples are forwarded to the virtual stereo mixer.
|
||||
|
||||
name='Mic Capture Volume',index=0
|
||||
---------------------------------
|
||||
This control is used to attenuate samples for left and right Mic input.
|
||||
The result is forwarded to the ADC capture FIFO (thus to the standard capture
|
||||
PCM device).
|
||||
This control is used to attenuate samples from left and right Mic input of
|
||||
the AC97 codec. The result is forwarded to the standard capture PCM device.
|
||||
|
||||
The original samples are also forwarded to the Mic capture PCM device (device 1;
|
||||
16bit/8KHz mono) without volume control.
|
||||
|
||||
name='Audigy CD Playback Volume',index=0
|
||||
----------------------------------------
|
||||
This control is used to attenuate samples from left and right IEC958 TTL
|
||||
digital inputs (usually used by a CDROM drive). The result samples are
|
||||
forwarded to the front DAC PCM slots of the Philips DAC.
|
||||
forwarded to the virtual stereo mixer.
|
||||
|
||||
name='Audigy CD Capture Volume',index=0
|
||||
---------------------------------------
|
||||
This control is used to attenuate samples from left and right IEC958 TTL
|
||||
digital inputs (usually used by a CDROM drive). The result samples are
|
||||
forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
|
||||
digital inputs (usually used by a CDROM drive). The result is forwarded
|
||||
to the standard capture PCM device.
|
||||
|
||||
name='IEC958 Optical Playback Volume',index=0
|
||||
---------------------------------------------
|
||||
This control is used to attenuate samples from left and right IEC958 optical
|
||||
digital input. The result samples are forwarded to the front DAC PCM slots
|
||||
of the Philips DAC.
|
||||
digital input. The result samples are forwarded to the virtual stereo mixer.
|
||||
|
||||
name='IEC958 Optical Capture Volume',index=0
|
||||
--------------------------------------------
|
||||
This control is used to attenuate samples from left and right IEC958 optical
|
||||
digital inputs. The result samples are forwarded to the ADC capture FIFO
|
||||
(thus to the standard capture PCM device).
|
||||
digital inputs. The result is forwarded to the standard capture PCM device.
|
||||
|
||||
name='Line2 Playback Volume',index=0
|
||||
------------------------------------
|
||||
This control is used to attenuate samples from left and right I2S ADC
|
||||
inputs (on the AudigyDrive). The result samples are forwarded to the front
|
||||
DAC PCM slots of the Philips DAC.
|
||||
inputs (on the AudigyDrive). The result samples are forwarded to the virtual
|
||||
stereo mixer.
|
||||
|
||||
name='Line2 Capture Volume',index=1
|
||||
-----------------------------------
|
||||
This control is used to attenuate samples from left and right I2S ADC
|
||||
inputs (on the AudigyDrive). The result samples are forwarded to the ADC
|
||||
capture FIFO (thus to the standard capture PCM device).
|
||||
inputs (on the AudigyDrive). The result is forwarded to the standard capture
|
||||
PCM device.
|
||||
|
||||
name='Analog Mix Playback Volume',index=0
|
||||
-----------------------------------------
|
||||
This control is used to attenuate samples from left and right I2S ADC
|
||||
inputs from Philips ADC. The result samples are forwarded to the front
|
||||
DAC PCM slots of the Philips DAC. This contains mix from analog sources
|
||||
like CD, Line In, Aux, ....
|
||||
inputs from Philips ADC. The result samples are forwarded to the virtual
|
||||
stereo mixer. This contains mix from analog sources like CD, Line In, Aux, ....
|
||||
|
||||
name='Analog Mix Capture Volume',index=1
|
||||
----------------------------------------
|
||||
This control is used to attenuate samples from left and right I2S ADC
|
||||
inputs Philips ADC. The result samples are forwarded to the ADC
|
||||
capture FIFO (thus to the standard capture PCM device).
|
||||
inputs Philips ADC. The result is forwarded to the standard capture PCM device.
|
||||
|
||||
name='Aux2 Playback Volume',index=0
|
||||
-----------------------------------
|
||||
This control is used to attenuate samples from left and right I2S ADC
|
||||
inputs (on the AudigyDrive). The result samples are forwarded to the front
|
||||
DAC PCM slots of the Philips DAC.
|
||||
inputs (on the AudigyDrive). The result samples are forwarded to the virtual
|
||||
stereo mixer.
|
||||
|
||||
name='Aux2 Capture Volume',index=1
|
||||
----------------------------------
|
||||
This control is used to attenuate samples from left and right I2S ADC
|
||||
inputs (on the AudigyDrive). The result samples are forwarded to the ADC
|
||||
capture FIFO (thus to the standard capture PCM device).
|
||||
inputs (on the AudigyDrive). The result is forwarded to the standard capture
|
||||
PCM device.
|
||||
|
||||
name='Front Playback Volume',index=0
|
||||
------------------------------------
|
||||
All stereo signals are mixed together and mirrored to surround, center and LFE.
|
||||
This control is used to attenuate samples for left and right front speakers of
|
||||
this mix.
|
||||
This control is used to attenuate samples from the virtual stereo mixer.
|
||||
The result samples are forwarded to the front speakers.
|
||||
|
||||
name='Surround Playback Volume',index=0
|
||||
---------------------------------------
|
||||
All stereo signals are mixed together and mirrored to surround, center and LFE.
|
||||
This control is used to attenuate samples for left and right surround speakers of
|
||||
this mix.
|
||||
This control is used to attenuate samples from the virtual stereo mixer.
|
||||
The result samples are forwarded to the surround (rear) speakers.
|
||||
|
||||
name='Side Playback Volume',index=0
|
||||
-----------------------------------
|
||||
This control is used to attenuate samples from the virtual stereo mixer.
|
||||
The result samples are forwarded to the side speakers.
|
||||
|
||||
name='Center Playback Volume',index=0
|
||||
-------------------------------------
|
||||
All stereo signals are mixed together and mirrored to surround, center and LFE.
|
||||
This control is used to attenuate sample for center speaker of this mix.
|
||||
This control is used to attenuate samples from the virtual stereo mixer.
|
||||
The result samples are forwarded to the center speaker.
|
||||
|
||||
name='LFE Playback Volume',index=0
|
||||
----------------------------------
|
||||
All stereo signals are mixed together and mirrored to surround, center and LFE.
|
||||
This control is used to attenuate sample for LFE speaker of this mix.
|
||||
This control is used to attenuate samples from the virtual stereo mixer.
|
||||
The result samples are forwarded to the subwoofer.
|
||||
|
||||
name='Tone Control - Switch',index=0
|
||||
------------------------------------
|
||||
This control turns the tone control on or off. The samples for front, rear
|
||||
and center / LFE outputs are affected.
|
||||
This control turns the tone control on or off. The samples forwarded to
|
||||
the speaker outputs are affected.
|
||||
|
||||
name='Tone Control - Bass',index=0
|
||||
----------------------------------
|
||||
@ -212,8 +213,7 @@ The closest value to pure signal is 20.
|
||||
|
||||
name='Master Playback Volume',index=0
|
||||
-------------------------------------
|
||||
This control is used to attenuate samples for front, surround, center and
|
||||
LFE outputs.
|
||||
This control is used to attenuate samples forwarded to the speaker outputs.
|
||||
|
||||
name='IEC958 Optical Raw Playback Switch',index=0
|
||||
-------------------------------------------------
|
||||
@ -303,69 +303,4 @@ The channel mapping is following:
|
||||
MANUALS/PATENTS
|
||||
===============
|
||||
|
||||
ftp://opensource.creative.com/pub/doc
|
||||
-------------------------------------
|
||||
|
||||
Note that the site is defunct, but the documents are available
|
||||
from various other locations.
|
||||
|
||||
LM4545.pdf
|
||||
AC97 Codec
|
||||
|
||||
m2049.pdf
|
||||
The EMU10K1 Digital Audio Processor
|
||||
|
||||
hog63.ps
|
||||
FX8010 - A DSP Chip Architecture for Audio Effects
|
||||
|
||||
|
||||
WIPO Patents
|
||||
------------
|
||||
|
||||
WO 9901813 (A1)
|
||||
Audio Effects Processor with multiple asynchronous streams
|
||||
(Jan. 14, 1999)
|
||||
|
||||
WO 9901814 (A1)
|
||||
Processor with Instruction Set for Audio Effects (Jan. 14, 1999)
|
||||
|
||||
WO 9901953 (A1)
|
||||
Audio Effects Processor having Decoupled Instruction
|
||||
Execution and Audio Data Sequencing (Jan. 14, 1999)
|
||||
|
||||
|
||||
US Patents (https://www.uspto.gov/)
|
||||
-----------------------------------
|
||||
|
||||
US 5925841
|
||||
Digital Sampling Instrument employing cache memory (Jul. 20, 1999)
|
||||
|
||||
US 5928342
|
||||
Audio Effects Processor integrated on a single chip
|
||||
with a multiport memory onto which multiple asynchronous
|
||||
digital sound samples can be concurrently loaded
|
||||
(Jul. 27, 1999)
|
||||
|
||||
US 5930158
|
||||
Processor with Instruction Set for Audio Effects (Jul. 27, 1999)
|
||||
|
||||
US 6032235
|
||||
Memory initialization circuit (Tram) (Feb. 29, 2000)
|
||||
|
||||
US 6138207
|
||||
Interpolation looping of audio samples in cache connected to
|
||||
system bus with prioritization and modification of bus transfers
|
||||
in accordance with loop ends and minimum block sizes
|
||||
(Oct. 24, 2000)
|
||||
|
||||
US 6151670
|
||||
Method for conserving memory storage using a
|
||||
pool of short term memory registers
|
||||
(Nov. 21, 2000)
|
||||
|
||||
US 6195715
|
||||
Interrupt control for multiple programs communicating with
|
||||
a common interrupt by associating programs to GP registers,
|
||||
defining interrupt register, polling GP registers, and invoking
|
||||
callback routine associated with defined interrupt register
|
||||
(Feb. 27, 2001)
|
||||
See sb-live-mixer.rst.
|
||||
|
226
Documentation/sound/cards/emu-mixer.rst
Normal file
226
Documentation/sound/cards/emu-mixer.rst
Normal file
@ -0,0 +1,226 @@
|
||||
==================================================
|
||||
E-MU Digital Audio System mixer / default DSP code
|
||||
==================================================
|
||||
|
||||
This document covers the E-MU 0404/1010/1212/1616/1820 PCI/PCI-e/CardBus
|
||||
cards.
|
||||
|
||||
These cards use regular EMU10K2 (SoundBlaster Audigy) chips, but with an
|
||||
alternative front-end geared towards semi-professional studio recording.
|
||||
|
||||
This document is based on audigy-mixer.rst.
|
||||
|
||||
|
||||
Hardware compatibility
|
||||
======================
|
||||
|
||||
The EMU10K2 chips have a very short capture FIFO, which makes recording
|
||||
unreliable if the card's PCI bus requests are not handled with the
|
||||
appropriate priority.
|
||||
This is the case on more modern motherboards, where the PCI bus is only a
|
||||
secondary peripheral, rather than the actual arbiter of device access.
|
||||
In particular, I got recording glitches during simultaneous playback on an
|
||||
Intel DP55 board (memory controller in the CPU), but had success with an
|
||||
Intel DP45 board (memory controller in the north bridge).
|
||||
|
||||
The PCI Express variants of these cards (which have a PCI bridge on board,
|
||||
but are otherwise identical) may be less problematic.
|
||||
|
||||
|
||||
Driver capabilities
|
||||
===================
|
||||
|
||||
This driver supports only 16-bit 44.1/48 kHz operation. The multi-channel
|
||||
device (see emu10k1-jack.rst) additionally supports 24-bit capture.
|
||||
|
||||
A patchset to enhance the driver is available from `a GitHub repository
|
||||
<https://github.com/ossilator/linux/tree/ossis-emu10k1>`_.
|
||||
Its multi-channel device supports 24-bit for both playback and capture,
|
||||
and also supports full 88.2/96/176.4/192 kHz operation.
|
||||
It is not going to be upstreamed due to a fundamental disagreement about
|
||||
what constitutes a good user experience.
|
||||
|
||||
|
||||
Digital mixer controls
|
||||
======================
|
||||
|
||||
Note that the controls work as attenuators: the maximum value is the neutral
|
||||
position leaving the signal unchanged. Note that if the same destination is
|
||||
mentioned in multiple controls, the signal is accumulated and can be clipped
|
||||
(set to maximal or minimal value without checking for overflow).
|
||||
|
||||
Explanation of used abbreviations:
|
||||
|
||||
DAC
|
||||
digital to analog converter
|
||||
ADC
|
||||
analog to digital converter
|
||||
LFE
|
||||
low frequency effects (used as subwoofer signal)
|
||||
IEC958
|
||||
S/PDIF
|
||||
FX-bus
|
||||
the EMU10K2 chip has an effect bus containing 64 accumulators.
|
||||
Each of the synthesizer voices can feed its output to these accumulators
|
||||
and the DSP microcontroller can operate with the resulting sum.
|
||||
|
||||
name='Clock Source',index=0
|
||||
---------------------------
|
||||
This control allows switching the word clock between interally generated
|
||||
44.1 or 48 kHz, or a number of external sources.
|
||||
|
||||
Note: the sources for the 1616 CardBus card are unclear. Please report your
|
||||
findings.
|
||||
|
||||
name='Clock Fallback',index=0
|
||||
-----------------------------
|
||||
This control determines the internal clock which the card switches to when
|
||||
the selected external clock source is/becomes invalid.
|
||||
|
||||
name='DAC1 0202 14dB PAD',index=0, etc.
|
||||
---------------------------------------
|
||||
Output attenuation controls. Not available on 0404 cards.
|
||||
|
||||
name='ADC1 14dB PAD 0202',index=0, etc.
|
||||
---------------------------------------
|
||||
Input attenuation controls. Not available on 0404 cards.
|
||||
|
||||
name='Optical Output Mode',index=0
|
||||
----------------------------------
|
||||
Switches the TOSLINK output port between S/PDIF and ADAT.
|
||||
Not available on 0404 cards (fixed to S/PDIF).
|
||||
|
||||
name='Optical Input Mode',index=0
|
||||
---------------------------------
|
||||
Switches the TOSLINK input port between S/PDIF and ADAT.
|
||||
Not available on 0404 cards (fixed to S/PDIF).
|
||||
|
||||
name='PCM Front Playback Volume',index=0
|
||||
----------------------------------------
|
||||
This control is used to attenuate samples from left and right front PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 8 and 9 for left and right front PCM
|
||||
samples for 5.1 playback. The result samples are forwarded to the DSP 0 & 1
|
||||
playback channels.
|
||||
|
||||
name='PCM Surround Playback Volume',index=0
|
||||
-------------------------------------------
|
||||
This control is used to attenuate samples from left and right surround PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 2 and 3 for left and right surround PCM
|
||||
samples for 5.1 playback. The result samples are forwarded to the DSP 2 & 3
|
||||
playback channels.
|
||||
|
||||
name='PCM Side Playback Volume',index=0
|
||||
---------------------------------------
|
||||
This control is used to attenuate samples from left and right side PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 14 and 15 for left and right side PCM
|
||||
samples for 7.1 playback. The result samples are forwarded to the DSP 6 & 7
|
||||
playback channels.
|
||||
|
||||
name='PCM Center Playback Volume',index=0
|
||||
-----------------------------------------
|
||||
This control is used to attenuate samples from the center PCM FX-bus accumulator.
|
||||
ALSA uses accumulator 6 for center PCM samples for 5.1 playback. The result samples
|
||||
are forwarded to the DSP 4 playback channel.
|
||||
|
||||
name='PCM LFE Playback Volume',index=0
|
||||
--------------------------------------
|
||||
This control is used to attenuate samples from the LFE PCM FX-bus accumulator.
|
||||
ALSA uses accumulator 7 for LFE PCM samples for 5.1 playback. The result samples
|
||||
are forwarded to the DSP 5 playback channel.
|
||||
|
||||
name='PCM Playback Volume',index=0
|
||||
----------------------------------
|
||||
This control is used to attenuate samples from left and right PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples for
|
||||
stereo playback. The result samples are forwarded to the virtual stereo mixer.
|
||||
|
||||
name='PCM Capture Volume',index=0
|
||||
---------------------------------
|
||||
This control is used to attenuate samples from left and right PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 0 and 1 for left and right PCM.
|
||||
The result is forwarded to the standard capture PCM device.
|
||||
|
||||
name='Music Playback Volume',index=0
|
||||
------------------------------------
|
||||
This control is used to attenuate samples from left and right MIDI FX-bus
|
||||
accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
|
||||
The result samples are forwarded to the virtual stereo mixer.
|
||||
|
||||
name='Music Capture Volume',index=0
|
||||
-----------------------------------
|
||||
These controls are used to attenuate samples from left and right MIDI FX-bus
|
||||
accumulator. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
|
||||
The result is forwarded to the standard capture PCM device.
|
||||
|
||||
name='Front Playback Volume',index=0
|
||||
------------------------------------
|
||||
This control is used to attenuate samples from the virtual stereo mixer.
|
||||
The result samples are forwarded to the DSP 0 & 1 playback channels.
|
||||
|
||||
name='Surround Playback Volume',index=0
|
||||
---------------------------------------
|
||||
This control is used to attenuate samples from the virtual stereo mixer.
|
||||
The result samples are forwarded to the DSP 2 & 3 playback channels.
|
||||
|
||||
name='Side Playback Volume',index=0
|
||||
-----------------------------------
|
||||
This control is used to attenuate samples from the virtual stereo mixer.
|
||||
The result samples are forwarded to the DSP 6 & 7 playback channels.
|
||||
|
||||
name='Center Playback Volume',index=0
|
||||
-------------------------------------
|
||||
This control is used to attenuate samples from the virtual stereo mixer.
|
||||
The result samples are forwarded to the DSP 4 playback channel.
|
||||
|
||||
name='LFE Playback Volume',index=0
|
||||
----------------------------------
|
||||
This control is used to attenuate samples from the virtual stereo mixer.
|
||||
The result samples are forwarded to the DSP 5 playback channel.
|
||||
|
||||
name='Tone Control - Switch',index=0
|
||||
------------------------------------
|
||||
This control turns the tone control on or off. The samples forwarded to
|
||||
the DSP playback channels are affected.
|
||||
|
||||
name='Tone Control - Bass',index=0
|
||||
----------------------------------
|
||||
This control sets the bass intensity. There is no neutral value!!
|
||||
When the tone control code is activated, the samples are always modified.
|
||||
The closest value to pure signal is 20.
|
||||
|
||||
name='Tone Control - Treble',index=0
|
||||
------------------------------------
|
||||
This control sets the treble intensity. There is no neutral value!!
|
||||
When the tone control code is activated, the samples are always modified.
|
||||
The closest value to pure signal is 20.
|
||||
|
||||
name='Master Playback Volume',index=0
|
||||
-------------------------------------
|
||||
This control is used to attenuate samples for all DSP playback channels.
|
||||
|
||||
name='EMU Capture Volume',index=0
|
||||
----------------------------------
|
||||
This control is used to attenuate samples from the DSP 0 & 1 capture channels.
|
||||
The result is forwarded to the standard capture PCM device.
|
||||
|
||||
name='DAC Left',index=0, etc.
|
||||
-----------------------------
|
||||
Select the source for the given physical audio output. These may be physical
|
||||
inputs, playback channels (DSP xx, specified as a decimal number), or silence.
|
||||
|
||||
name='DSP x',index=0
|
||||
--------------------
|
||||
Select the source for the given capture channel (specified as a hexadecimal
|
||||
digit). Same options as for the physical audio outputs.
|
||||
|
||||
|
||||
PCM stream related controls
|
||||
===========================
|
||||
|
||||
These controls are described in audigy-mixer.rst.
|
||||
|
||||
|
||||
MANUALS/PATENTS
|
||||
===============
|
||||
|
||||
See sb-live-mixer.rst.
|
@ -8,6 +8,7 @@ Card-Specific Information
|
||||
cmipci
|
||||
sb-live-mixer
|
||||
audigy-mixer
|
||||
emu-mixer
|
||||
emu10k1-jack
|
||||
via82xx-mixer
|
||||
audiophile-usb
|
||||
|
@ -61,61 +61,61 @@ FX-bus
|
||||
|
||||
``name='Wave Playback Volume',index=0``
|
||||
---------------------------------------
|
||||
This control is used to attenuate samples for left and right PCM FX-bus
|
||||
This control is used to attenuate samples from left and right PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
|
||||
The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
|
||||
|
||||
``name='Wave Surround Playback Volume',index=0``
|
||||
------------------------------------------------
|
||||
This control is used to attenuate samples for left and right PCM FX-bus
|
||||
This control is used to attenuate samples from left and right PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
|
||||
The result samples are forwarded to the rear I2S DACs. These DACs operates
|
||||
separately (they are not inside the AC97 codec).
|
||||
|
||||
``name='Wave Center Playback Volume',index=0``
|
||||
----------------------------------------------
|
||||
This control is used to attenuate samples for left and right PCM FX-bus
|
||||
This control is used to attenuate samples from left and right PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
|
||||
The result is mixed to mono signal (single channel) and forwarded to
|
||||
the ??rear?? right DAC PCM slot of the AC97 codec.
|
||||
|
||||
``name='Wave LFE Playback Volume',index=0``
|
||||
-------------------------------------------
|
||||
This control is used to attenuate samples for left and right PCM FX-bus
|
||||
This control is used to attenuate samples from left and right PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 0 and 1 for left and right PCM.
|
||||
The result is mixed to mono signal (single channel) and forwarded to
|
||||
the ??rear?? left DAC PCM slot of the AC97 codec.
|
||||
|
||||
``name='Wave Capture Volume',index=0``, ``name='Wave Capture Switch',index=0``
|
||||
------------------------------------------------------------------------------
|
||||
These controls are used to attenuate samples for left and right PCM FX-bus
|
||||
These controls are used to attenuate samples from left and right PCM FX-bus
|
||||
accumulator. ALSA uses accumulators 0 and 1 for left and right PCM.
|
||||
The result is forwarded to the ADC capture FIFO (thus to the standard capture
|
||||
PCM device).
|
||||
|
||||
``name='Synth Playback Volume',index=0``
|
||||
----------------------------------------
|
||||
This control is used to attenuate samples for left and right MIDI FX-bus
|
||||
This control is used to attenuate samples from left and right MIDI FX-bus
|
||||
accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
|
||||
The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
|
||||
|
||||
``name='Synth Capture Volume',index=0``, ``name='Synth Capture Switch',index=0``
|
||||
--------------------------------------------------------------------------------
|
||||
These controls are used to attenuate samples for left and right MIDI FX-bus
|
||||
accumulator. ALSA uses accumulators 4 and 5 for left and right PCM.
|
||||
These controls are used to attenuate samples from left and right MIDI FX-bus
|
||||
accumulator. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
|
||||
The result is forwarded to the ADC capture FIFO (thus to the standard capture
|
||||
PCM device).
|
||||
|
||||
``name='Surround Playback Volume',index=0``
|
||||
-------------------------------------------
|
||||
This control is used to attenuate samples for left and right rear PCM FX-bus
|
||||
This control is used to attenuate samples from left and right rear PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 2 and 3 for left and right rear PCM samples.
|
||||
The result samples are forwarded to the rear I2S DACs. These DACs operate
|
||||
separately (they are not inside the AC97 codec).
|
||||
|
||||
``name='Surround Capture Volume',index=0``, ``name='Surround Capture Switch',index=0``
|
||||
--------------------------------------------------------------------------------------
|
||||
These controls are used to attenuate samples for left and right rear PCM FX-bus
|
||||
These controls are used to attenuate samples from left and right rear PCM FX-bus
|
||||
accumulators. ALSA uses accumulators 2 and 3 for left and right rear PCM samples.
|
||||
The result is forwarded to the ADC capture FIFO (thus to the standard capture
|
||||
PCM device).
|
||||
@ -134,7 +134,7 @@ to the ??rear?? left DAC PCM slot of the AC97 codec.
|
||||
|
||||
``name='AC97 Playback Volume',index=0``
|
||||
---------------------------------------
|
||||
This control is used to attenuate samples for left and right front ADC PCM slots
|
||||
This control is used to attenuate samples from left and right front ADC PCM slots
|
||||
of the AC97 codec. The result samples are forwarded to the front DAC PCM
|
||||
slots of the AC97 codec.
|
||||
|
||||
@ -145,7 +145,7 @@ slots of the AC97 codec.
|
||||
|
||||
``name='AC97 Capture Volume',index=0``
|
||||
--------------------------------------
|
||||
This control is used to attenuate samples for left and right front ADC PCM slots
|
||||
This control is used to attenuate samples from left and right front ADC PCM slots
|
||||
of the AC97 codec. The result is forwarded to the ADC capture FIFO (thus to
|
||||
the standard capture PCM device).
|
||||
|
||||
|
@ -376,3 +376,191 @@ Sequencer API Extensions
|
||||
name and attributes accordingly, and notifies the changes via the
|
||||
announcement to the ALSA sequencer system port, similarly like the
|
||||
normal port change notification.
|
||||
|
||||
|
||||
MIDI2 USB Gadget Function Driver
|
||||
================================
|
||||
|
||||
The latest kernel contains the support for USB MIDI 2.0 gadget
|
||||
function driver, which can be used for prototyping and debugging MIDI
|
||||
2.0 features.
|
||||
|
||||
`CONFIG_USB_GADGET`, `CONFIG_USB_CONFIGFS` and
|
||||
`CONFIG_USB_CONFIGFS_F_MIDI2` need to be enabled for the MIDI2 gadget
|
||||
driver.
|
||||
|
||||
In addition, for using a gadget driver, you need a working UDC driver.
|
||||
In the example below, we use `dummy_hcd` driver (enabled via
|
||||
`CONFIG_USB_DUMMY_HCD`) that is available on PC and VM for debugging
|
||||
purpose. There are other UDC drivers depending on the platform, and
|
||||
those can be used for a real device, instead, too.
|
||||
|
||||
At first, on a system to run the gadget, load `libcomposite` module::
|
||||
|
||||
% modprobe libcomposite
|
||||
|
||||
and you'll have `usb_gadget` subdirectory under configfs space
|
||||
(typically `/sys/kernel/config` on modern OS). Then create a gadget
|
||||
instance and add configurations there, for example::
|
||||
|
||||
% cd /sys/kernel/config
|
||||
% mkdir usb_gadget/g1
|
||||
|
||||
% cd usb_gadget/g1
|
||||
% mkdir configs/c.1
|
||||
% mkdir functions/midi2.usb0
|
||||
|
||||
% echo 0x0004 > idProduct
|
||||
% echo 0x17b3 > idVendor
|
||||
% mkdir strings/0x409
|
||||
% echo "ACME Enterprises" > strings/0x409/manufacturer
|
||||
% echo "ACMESynth" > strings/0x409/product
|
||||
% echo "ABCD12345" > strings/0x409/serialnumber
|
||||
|
||||
% mkdir configs/c.1/strings/0x409
|
||||
% echo "Monosynth" > configs/c.1/strings/0x409/configuration
|
||||
% echo 120 > configs/c.1/MaxPower
|
||||
|
||||
At this point, there must be a subdirectory `ep.0`, and that is the
|
||||
configuration for a UMP Endpoint. You can fill the Endpoint
|
||||
information like::
|
||||
|
||||
% echo "ACMESynth" > functions/midi2.usb0/iface_name
|
||||
% echo "ACMESynth" > functions/midi2.usb0/ep.0/ep_name
|
||||
% echo "ABCD12345" > functions/midi2.usb0/ep.0/product_id
|
||||
% echo 0x0123 > functions/midi2.usb0/ep.0/family
|
||||
% echo 0x4567 > functions/midi2.usb0/ep.0/model
|
||||
% echo 0x123456 > functions/midi2.usb0/ep.0/manufacturer
|
||||
% echo 0x12345678 > functions/midi2.usb0/ep.0/sw_revision
|
||||
|
||||
The default MIDI protocol can be set either 1 or 2::
|
||||
|
||||
% echo 2 > functions/midi2.usb0/ep.0/protocol
|
||||
|
||||
And, you can find a subdirectory `block.0` under this Endpoint
|
||||
subdirectory. This defines the Function Block information::
|
||||
|
||||
% echo "Monosynth" > functions/midi2.usb0/ep.0/block.0/name
|
||||
% echo 0 > functions/midi2.usb0/ep.0/block.0/first_group
|
||||
% echo 1 > functions/midi2.usb0/ep.0/block.0/num_groups
|
||||
|
||||
Finally, link the configuration and enable it::
|
||||
|
||||
% ln -s functions/midi2.usb0 configs/c.1
|
||||
% echo dummy_udc.0 > UDC
|
||||
|
||||
where `dummy_udc.0` is an example case and it differs depending on the
|
||||
system. You can find the UDC instances in `/sys/class/udc` and pass
|
||||
the found name instead::
|
||||
|
||||
% ls /sys/class/udc
|
||||
dummy_udc.0
|
||||
|
||||
Now, the MIDI 2.0 gadget device is enabled, and the gadget host
|
||||
creates a new sound card instance containing a UMP rawmidi device by
|
||||
`f_midi2` driver::
|
||||
|
||||
% cat /proc/asound/cards
|
||||
....
|
||||
1 [Gadget ]: f_midi2 - MIDI 2.0 Gadget
|
||||
MIDI 2.0 Gadget
|
||||
|
||||
And on the connected host, a similar card should appear, too, but with
|
||||
the card and device names given in the configfs above::
|
||||
|
||||
% cat /proc/asound/cards
|
||||
....
|
||||
2 [ACMESynth ]: USB-Audio - ACMESynth
|
||||
ACME Enterprises ACMESynth at usb-dummy_hcd.0-1, high speed
|
||||
|
||||
You can play a MIDI file on the gadget side::
|
||||
|
||||
% aplaymidi -p 20:1 to_host.mid
|
||||
|
||||
and this will appear as an input from a MIDI device on the connected
|
||||
host::
|
||||
|
||||
% aseqdump -p 20:0 -u 2
|
||||
|
||||
Vice versa, a playback on the connected host will work as an input on
|
||||
the gadget, too.
|
||||
|
||||
Each Function Block may have different direction and UI-hint,
|
||||
specified via `direction` and `ui_hint` attributes.
|
||||
Passing `1` is for input-only, `2` for out-only and `3` for
|
||||
bidirectional (the default value). For example::
|
||||
|
||||
% echo 2 > functions/midi2.usb0/ep.0/block.0/direction
|
||||
% echo 2 > functions/midi2.usb0/ep.0/block.0/ui_hint
|
||||
|
||||
When you need more than one Function Blocks, you can create
|
||||
subdirectories `block.1`, `block.2`, etc dynamically, and configure
|
||||
them in the configuration procedure above before linking.
|
||||
For example, to create a second Function Block for a keyboard::
|
||||
|
||||
% mkdir functions/midi2.usb0/ep.0/block.1
|
||||
% echo "Keyboard" > functions/midi2.usb0/ep.0/block.1/name
|
||||
% echo 1 > functions/midi2.usb0/ep.0/block.1/first_group
|
||||
% echo 1 > functions/midi2.usb0/ep.0/block.1/num_groups
|
||||
% echo 1 > functions/midi2.usb0/ep.0/block.1/direction
|
||||
% echo 1 > functions/midi2.usb0/ep.0/block.1/ui_hint
|
||||
|
||||
The `block.*` subdirectories can be removed dynamically, too (except
|
||||
for `block.0` which is persistent).
|
||||
|
||||
For assigning a Function Block for MIDI 1.0 I/O, set up in `is_midi1`
|
||||
attribute. 1 is for MIDI 1.0, and 2 is for MIDI 1.0 with low speed
|
||||
connection::
|
||||
|
||||
% echo 2 > functions/midi2.usb0/ep.0/block.1/is_midi1
|
||||
|
||||
For disabling the processing of UMP Stream messages in the gadget
|
||||
driver, pass `0` to `process_ump` attribute in the top-level config::
|
||||
|
||||
% echo 0 > functions/midi2.usb0/process_ump
|
||||
|
||||
The MIDI 1.0 interface at altset 0 is supported by the gadget driver,
|
||||
too. When MIDI 1.0 interface is selected by the connected host, the
|
||||
UMP I/O on the gadget is translated from/to USB MIDI 1.0 packets
|
||||
accordingly while the gadget driver keeps communicating with the
|
||||
user-space over UMP rawmidi.
|
||||
|
||||
MIDI 1.0 ports are set up from the config in each Function Block.
|
||||
For example::
|
||||
|
||||
% echo 0 > functions/midi2.usb0/ep.0/block.0/midi1_first_group
|
||||
% echo 1 > functions/midi2.usb0/ep.0/block.0/midi1_num_groups
|
||||
|
||||
The configuration above will enable the Group 1 (the index 0) for MIDI
|
||||
1.0 interface. Note that those groups must be in the groups defined
|
||||
for the Function Block itself.
|
||||
|
||||
The gadget driver supports more than one UMP Endpoints, too.
|
||||
Similarly like the Function Blocks, you can create a new subdirectory
|
||||
`ep.1` (but under the card top-level config) to enable a new Endpoint::
|
||||
|
||||
% mkdir functions/midi2.usb0/ep.1
|
||||
|
||||
and create a new Function Block there. For example, to create 4
|
||||
Groups for the Function Block of this new Endpoint::
|
||||
|
||||
% mkdir functions/midi2.usb0/ep.1/block.0
|
||||
% echo 4 > functions/midi2.usb0/ep.1/block.0/num_groups
|
||||
|
||||
Now, you'll have 4 rawmidi devices in total: the first two are UMP
|
||||
rawmidi devices for Endpoint 0 and Endpoint 1, and other two for the
|
||||
legacy MIDI 1.0 rawmidi devices corresponding to both EP 0 and EP 1.
|
||||
|
||||
The current altsetting on the gadget can be informed via a control
|
||||
element "Operation Mode" with `RAWMIDI` iface. e.g. you can read it
|
||||
via `amixer` program running on the gadget host like::
|
||||
|
||||
% amixer -c1 cget iface=RAWMIDI,name='Operation Mode'
|
||||
; type=INTEGER,access=r--v----,values=1,min=0,max=2,step=0
|
||||
: values=2
|
||||
|
||||
The value (shown in the second returned line with `: values=`)
|
||||
indicates 1 for MIDI 1.0 (altset 0), 2 for MIDI 2.0 (altset 1) and 0
|
||||
for unset.
|
||||
|
||||
As of now, the configurations can't be changed after binding.
|
||||
|
@ -2018,8 +2018,8 @@ sleeping poll threads, etc.
|
||||
|
||||
This callback is also atomic by default.
|
||||
|
||||
copy_user, copy_kernel and fill_silence ops
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
copy and fill_silence ops
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
These callbacks are not mandatory, and can be omitted in most cases.
|
||||
These callbacks are used when the hardware buffer cannot be in the
|
||||
@ -3444,8 +3444,8 @@ external hardware buffer in interrupts (or in tasklets, preferably).
|
||||
|
||||
The first case works fine if the external hardware buffer is large
|
||||
enough. This method doesn't need any extra buffers and thus is more
|
||||
efficient. You need to define the ``copy_user`` and ``copy_kernel``
|
||||
callbacks for the data transfer, in addition to the ``fill_silence``
|
||||
efficient. You need to define the ``copy`` callback
|
||||
for the data transfer, in addition to the ``fill_silence``
|
||||
callback for playback. However, there is a drawback: it cannot be
|
||||
mmapped. The examples are GUS's GF1 PCM or emu8000's wavetable PCM.
|
||||
|
||||
@ -3458,22 +3458,22 @@ Another case is when the chip uses a PCI memory-map region for the
|
||||
buffer instead of the host memory. In this case, mmap is available only
|
||||
on certain architectures like the Intel one. In non-mmap mode, the data
|
||||
cannot be transferred as in the normal way. Thus you need to define the
|
||||
``copy_user``, ``copy_kernel`` and ``fill_silence`` callbacks as well,
|
||||
``copy`` and ``fill_silence`` callbacks as well,
|
||||
as in the cases above. Examples are found in ``rme32.c`` and
|
||||
``rme96.c``.
|
||||
|
||||
The implementation of the ``copy_user``, ``copy_kernel`` and
|
||||
The implementation of the ``copy`` and
|
||||
``silence`` callbacks depends upon whether the hardware supports
|
||||
interleaved or non-interleaved samples. The ``copy_user`` callback is
|
||||
interleaved or non-interleaved samples. The ``copy`` callback is
|
||||
defined like below, a bit differently depending on whether the direction
|
||||
is playback or capture::
|
||||
|
||||
static int playback_copy_user(struct snd_pcm_substream *substream,
|
||||
static int playback_copy(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long pos,
|
||||
void __user *src, unsigned long count);
|
||||
static int capture_copy_user(struct snd_pcm_substream *substream,
|
||||
struct iov_iter *src, unsigned long count);
|
||||
static int capture_copy(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long pos,
|
||||
void __user *dst, unsigned long count);
|
||||
struct iov_iter *dst, unsigned long count);
|
||||
|
||||
In the case of interleaved samples, the second argument (``channel``) is
|
||||
not used. The third argument (``pos``) specifies the position in bytes.
|
||||
@ -3490,18 +3490,17 @@ of data (``count``) at the specified pointer (``src``) to the specified
|
||||
offset (``pos``) in the hardware buffer. When coded like memcpy-like
|
||||
way, the copy would look like::
|
||||
|
||||
my_memcpy_from_user(my_buffer + pos, src, count);
|
||||
my_memcpy_from_iter(my_buffer + pos, src, count);
|
||||
|
||||
For the capture direction, you copy the given amount of data (``count``)
|
||||
at the specified offset (``pos``) in the hardware buffer to the
|
||||
specified pointer (``dst``)::
|
||||
|
||||
my_memcpy_to_user(dst, my_buffer + pos, count);
|
||||
my_memcpy_to_iter(dst, my_buffer + pos, count);
|
||||
|
||||
Here the functions are named ``from_user`` and ``to_user`` because
|
||||
it's the user-space buffer that is passed to these callbacks. That
|
||||
is, the callback is supposed to copy data from/to the user-space
|
||||
directly to/from the hardware buffer.
|
||||
The given ``src`` or ``dst`` a struct iov_iter pointer containing the
|
||||
pointer and the size. Use the existing helpers to copy or access the
|
||||
data as defined in ``linux/uio.h``.
|
||||
|
||||
Careful readers might notice that these callbacks receive the
|
||||
arguments in bytes, not in frames like other callbacks. It's because
|
||||
@ -3519,25 +3518,6 @@ the given user-space buffer, but only for the given channel. For
|
||||
details, please check ``isa/gus/gus_pcm.c`` or ``pci/rme9652/rme9652.c``
|
||||
as examples.
|
||||
|
||||
The above callbacks are the copies from/to the user-space buffer. There
|
||||
are some cases where we want to copy from/to the kernel-space buffer
|
||||
instead. In such a case, the ``copy_kernel`` callback is called. It'd
|
||||
look like::
|
||||
|
||||
static int playback_copy_kernel(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long pos,
|
||||
void *src, unsigned long count);
|
||||
static int capture_copy_kernel(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long pos,
|
||||
void *dst, unsigned long count);
|
||||
|
||||
As found easily, the only difference is that the buffer pointer is
|
||||
without a ``__user`` prefix; that is, a kernel-buffer pointer is passed
|
||||
in the fourth argument. Correspondingly, the implementation would be
|
||||
a version without the user-copy, such as::
|
||||
|
||||
my_memcpy(my_buffer + pos, src, count);
|
||||
|
||||
Usually for the playback, another callback ``fill_silence`` is
|
||||
defined. It's implemented in a similar way as the copy callbacks
|
||||
above::
|
||||
@ -3545,10 +3525,10 @@ above::
|
||||
static int silence(struct snd_pcm_substream *substream, int channel,
|
||||
unsigned long pos, unsigned long count);
|
||||
|
||||
The meanings of arguments are the same as in the ``copy_user`` and
|
||||
``copy_kernel`` callbacks, although there is no buffer pointer
|
||||
The meanings of arguments are the same as in the ``copy`` callback,
|
||||
although there is no buffer pointer
|
||||
argument. In the case of interleaved samples, the channel argument has
|
||||
no meaning, as for the ``copy_*`` callbacks.
|
||||
no meaning, as for the ``copy`` callback.
|
||||
|
||||
The role of the ``fill_silence`` callback is to set the given amount
|
||||
(``count``) of silence data at the specified offset (``pos``) in the
|
||||
|
@ -5,9 +5,10 @@
|
||||
*/
|
||||
#include <linux/err.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/iio-opaque.h>
|
||||
@ -849,15 +850,14 @@ static int iio_channel_read_max(struct iio_channel *chan,
|
||||
int *val, int *val2, int *type,
|
||||
enum iio_chan_info_enum info)
|
||||
{
|
||||
int unused;
|
||||
const int *vals;
|
||||
int length;
|
||||
int ret;
|
||||
|
||||
if (!val2)
|
||||
val2 = &unused;
|
||||
|
||||
ret = iio_channel_read_avail(chan, &vals, type, &length, info);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (ret) {
|
||||
case IIO_AVAIL_RANGE:
|
||||
switch (*type) {
|
||||
@ -866,6 +866,7 @@ static int iio_channel_read_max(struct iio_channel *chan,
|
||||
break;
|
||||
default:
|
||||
*val = vals[4];
|
||||
if (val2)
|
||||
*val2 = vals[5];
|
||||
}
|
||||
return 0;
|
||||
@ -875,20 +876,16 @@ static int iio_channel_read_max(struct iio_channel *chan,
|
||||
return -EINVAL;
|
||||
switch (*type) {
|
||||
case IIO_VAL_INT:
|
||||
*val = vals[--length];
|
||||
while (length) {
|
||||
if (vals[--length] > *val)
|
||||
*val = vals[length];
|
||||
}
|
||||
*val = max_array(vals, length);
|
||||
break;
|
||||
default:
|
||||
/* FIXME: learn about max for other iio values */
|
||||
/* TODO: learn about max for other iio values */
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return ret;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -912,6 +909,69 @@ err_unlock:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_read_max_channel_raw);
|
||||
|
||||
static int iio_channel_read_min(struct iio_channel *chan,
|
||||
int *val, int *val2, int *type,
|
||||
enum iio_chan_info_enum info)
|
||||
{
|
||||
const int *vals;
|
||||
int length;
|
||||
int ret;
|
||||
|
||||
ret = iio_channel_read_avail(chan, &vals, type, &length, info);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (ret) {
|
||||
case IIO_AVAIL_RANGE:
|
||||
switch (*type) {
|
||||
case IIO_VAL_INT:
|
||||
*val = vals[0];
|
||||
break;
|
||||
default:
|
||||
*val = vals[0];
|
||||
if (val2)
|
||||
*val2 = vals[1];
|
||||
}
|
||||
return 0;
|
||||
|
||||
case IIO_AVAIL_LIST:
|
||||
if (length <= 0)
|
||||
return -EINVAL;
|
||||
switch (*type) {
|
||||
case IIO_VAL_INT:
|
||||
*val = min_array(vals, length);
|
||||
break;
|
||||
default:
|
||||
/* TODO: learn about min for other iio values */
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int iio_read_min_channel_raw(struct iio_channel *chan, int *val)
|
||||
{
|
||||
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev);
|
||||
int ret;
|
||||
int type;
|
||||
|
||||
mutex_lock(&iio_dev_opaque->info_exist_lock);
|
||||
if (!chan->indio_dev->info) {
|
||||
ret = -ENODEV;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
ret = iio_channel_read_min(chan, val, NULL, &type, IIO_CHAN_INFO_RAW);
|
||||
err_unlock:
|
||||
mutex_unlock(&iio_dev_opaque->info_exist_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_read_min_channel_raw);
|
||||
|
||||
int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type)
|
||||
{
|
||||
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev);
|
||||
|
@ -8,6 +8,6 @@ dvb-vb2-$(CONFIG_DVB_MMAP) := dvb_vb2.o
|
||||
|
||||
dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \
|
||||
dvb_ca_en50221.o dvb_frontend.o \
|
||||
$(dvb-net-y) dvb_ringbuffer.o $(dvb-vb2-y) dvb_math.o
|
||||
$(dvb-net-y) dvb_ringbuffer.o $(dvb-vb2-y)
|
||||
|
||||
obj-$(CONFIG_DVB_CORE) += dvb-core.o
|
||||
|
@ -12,7 +12,7 @@
|
||||
#define AF9013_PRIV_H
|
||||
|
||||
#include <media/dvb_frontend.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include "af9013.h"
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <linux/math64.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
|
||||
struct reg_val {
|
||||
u32 reg;
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#include <linux/dvb/version.h>
|
||||
#include <media/dvb_frontend.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include "cxd2820r.h"
|
||||
#include <linux/gpio/driver.h> /* For gpio_chip */
|
||||
#include <linux/math64.h>
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <linux/dynamic_debug.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include <media/dvb_frontend.h>
|
||||
#include "cxd2841er.h"
|
||||
#include "cxd2841er_priv.h"
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "cxd2880_tnrdmd_dvbt2.h"
|
||||
#include "cxd2880_tnrdmd_dvbt2_mon.h"
|
||||
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
|
||||
static const int ref_dbm_1000[4][8] = {
|
||||
{-96000, -95000, -94000, -93000, -92000, -92000, -98000, -97000},
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "cxd2880_tnrdmd_dvbt.h"
|
||||
#include "cxd2880_tnrdmd_dvbt_mon.h"
|
||||
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
|
||||
static const int ref_dbm_1000[3][5] = {
|
||||
{-93000, -91000, -90000, -89000, -88000},
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include <media/dvb_frontend.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
|
||||
#include "cxd2880.h"
|
||||
#include "cxd2880_tnrdmd_mon.h"
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include <media/dvb_frontend.h>
|
||||
|
||||
#include "dib7000p.h"
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
|
||||
#include <media/dvb_frontend.h>
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include <media/dvb_frontend.h>
|
||||
|
||||
#include "dib9000.h"
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <media/dvb_frontend.h>
|
||||
#include "drxk.h"
|
||||
#include "drxk_hard.h"
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
|
||||
static int power_down_dvbt(struct drxk_state *state, bool set_power_mode);
|
||||
static int power_down_qam(struct drxk_state *state);
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <asm/div64.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <linux/slab.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include "lgdt3305.h"
|
||||
|
||||
static int debug;
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <asm/div64.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include "lgdt3306a.h"
|
||||
#include <linux/i2c-mux.h>
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include <media/dvb_frontend.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include "lgdt330x_priv.h"
|
||||
#include "lgdt330x.h"
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include <media/dvb_frontend.h>
|
||||
#include "m88ds3103.h"
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/regmap.h>
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
|
||||
#include "mn88443x.h"
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#define MN88472_PRIV_H
|
||||
|
||||
#include <media/dvb_frontend.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include "mn88472.h"
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/regmap.h>
|
||||
|
@ -9,7 +9,7 @@
|
||||
#define MN88473_PRIV_H
|
||||
|
||||
#include <media/dvb_frontend.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include "mn88473.h"
|
||||
#include <linux/math64.h>
|
||||
#include <linux/firmware.h>
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include <media/dvb_frontend.h>
|
||||
#include "or51132.h"
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include <media/dvb_frontend.h>
|
||||
#include "or51211.h"
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#define RTL2830_PRIV_H
|
||||
|
||||
#include <media/dvb_frontend.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include "rtl2830.h"
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/math64.h>
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <media/dvb_frontend.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include "rtl2832.h"
|
||||
|
||||
struct rtl2832_dev {
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <media/dvb_frontend.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include "si2165_priv.h"
|
||||
#include "si2165.h"
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
|
||||
#include "stv0367.h"
|
||||
#include "stv0367_defs.h"
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include "tc90522.h"
|
||||
|
||||
#define TC90522_I2C_THRU_REG 0xfe
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <linux/math64.h>
|
||||
#include <asm/div64.h>
|
||||
#include <media/dvb_frontend.h>
|
||||
#include <media/dvb_math.h>
|
||||
#include <linux/int_log.h>
|
||||
#include "tda10048.h"
|
||||
|
||||
#define TDA10048_DEFAULT_FIRMWARE "dvb-fe-tda10048-1.0.fw"
|
||||
|
@ -204,8 +204,8 @@ static snd_pcm_uframes_t snd_solo_pcm_pointer(struct snd_pcm_substream *ss)
|
||||
return idx * G723_FRAMES_PER_PAGE;
|
||||
}
|
||||
|
||||
static int snd_solo_pcm_copy_user(struct snd_pcm_substream *ss, int channel,
|
||||
unsigned long pos, void __user *dst,
|
||||
static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel,
|
||||
unsigned long pos, struct iov_iter *dst,
|
||||
unsigned long count)
|
||||
{
|
||||
struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
|
||||
@ -223,35 +223,9 @@ static int snd_solo_pcm_copy_user(struct snd_pcm_substream *ss, int channel,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (copy_to_user(dst, solo_pcm->g723_buf, G723_PERIOD_BYTES))
|
||||
if (copy_to_iter(solo_pcm->g723_buf, G723_PERIOD_BYTES, dst) !=
|
||||
G723_PERIOD_BYTES)
|
||||
return -EFAULT;
|
||||
dst += G723_PERIOD_BYTES;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_solo_pcm_copy_kernel(struct snd_pcm_substream *ss, int channel,
|
||||
unsigned long pos, void *dst,
|
||||
unsigned long count)
|
||||
{
|
||||
struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
|
||||
struct solo_dev *solo_dev = solo_pcm->solo_dev;
|
||||
int err, i;
|
||||
|
||||
for (i = 0; i < (count / G723_FRAMES_PER_PAGE); i++) {
|
||||
int page = (pos / G723_FRAMES_PER_PAGE) + i;
|
||||
|
||||
err = solo_p2m_dma_t(solo_dev, 0, solo_pcm->g723_dma,
|
||||
SOLO_G723_EXT_ADDR(solo_dev) +
|
||||
(page * G723_PERIOD_BLOCK) +
|
||||
(ss->number * G723_PERIOD_BYTES),
|
||||
G723_PERIOD_BYTES, 0, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memcpy(dst, solo_pcm->g723_buf, G723_PERIOD_BYTES);
|
||||
dst += G723_PERIOD_BYTES;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -263,8 +237,7 @@ static const struct snd_pcm_ops snd_solo_pcm_ops = {
|
||||
.prepare = snd_solo_pcm_prepare,
|
||||
.trigger = snd_solo_pcm_trigger,
|
||||
.pointer = snd_solo_pcm_pointer,
|
||||
.copy_user = snd_solo_pcm_copy_user,
|
||||
.copy_kernel = snd_solo_pcm_copy_kernel,
|
||||
.copy = snd_solo_pcm_copy,
|
||||
};
|
||||
|
||||
static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol,
|
||||
|
@ -807,7 +807,6 @@ int gbaudio_register_module(struct gbaudio_module_info *module)
|
||||
{
|
||||
int ret;
|
||||
struct snd_soc_component *comp;
|
||||
struct snd_card *card;
|
||||
struct gbaudio_jack *jack = NULL;
|
||||
|
||||
if (!gbcodec) {
|
||||
@ -816,21 +815,20 @@ int gbaudio_register_module(struct gbaudio_module_info *module)
|
||||
}
|
||||
|
||||
comp = gbcodec->component;
|
||||
card = comp->card->snd_card;
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
mutex_lock(&gbcodec->register_mutex);
|
||||
|
||||
if (module->num_dais) {
|
||||
dev_err(gbcodec->dev,
|
||||
"%d:DAIs not supported via gbcodec driver\n",
|
||||
module->num_dais);
|
||||
up_write(&card->controls_rwsem);
|
||||
mutex_unlock(&gbcodec->register_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = gbaudio_init_jack(module, comp->card);
|
||||
if (ret) {
|
||||
up_write(&card->controls_rwsem);
|
||||
mutex_unlock(&gbcodec->register_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -867,7 +865,7 @@ int gbaudio_register_module(struct gbaudio_module_info *module)
|
||||
ret = snd_soc_dapm_new_widgets(comp->card);
|
||||
dev_dbg(comp->dev, "Registered %s module\n", module->name);
|
||||
|
||||
up_write(&card->controls_rwsem);
|
||||
mutex_unlock(&gbcodec->register_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(gbaudio_register_module);
|
||||
@ -935,13 +933,12 @@ static void gbaudio_codec_cleanup(struct gbaudio_module_info *module)
|
||||
void gbaudio_unregister_module(struct gbaudio_module_info *module)
|
||||
{
|
||||
struct snd_soc_component *comp = gbcodec->component;
|
||||
struct snd_card *card = comp->card->snd_card;
|
||||
struct gbaudio_jack *jack, *n;
|
||||
int mask;
|
||||
|
||||
dev_dbg(comp->dev, "Unregister %s module\n", module->name);
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
mutex_lock(&gbcodec->register_mutex);
|
||||
mutex_lock(&gbcodec->lock);
|
||||
gbaudio_codec_cleanup(module);
|
||||
list_del(&module->list);
|
||||
@ -978,10 +975,8 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module)
|
||||
dev_dbg(comp->dev, "Removing %d controls\n",
|
||||
module->num_controls);
|
||||
/* release control semaphore */
|
||||
up_write(&card->controls_rwsem);
|
||||
gbaudio_remove_component_controls(comp, module->controls,
|
||||
module->num_controls);
|
||||
down_write(&card->controls_rwsem);
|
||||
}
|
||||
if (module->dapm_widgets) {
|
||||
dev_dbg(comp->dev, "Removing %d widgets\n",
|
||||
@ -992,7 +987,7 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module)
|
||||
|
||||
dev_dbg(comp->dev, "Unregistered %s module\n", module->name);
|
||||
|
||||
up_write(&card->controls_rwsem);
|
||||
mutex_unlock(&gbcodec->register_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(gbaudio_unregister_module);
|
||||
|
||||
@ -1012,6 +1007,7 @@ static int gbcodec_probe(struct snd_soc_component *comp)
|
||||
info->dev = comp->dev;
|
||||
INIT_LIST_HEAD(&info->module_list);
|
||||
mutex_init(&info->lock);
|
||||
mutex_init(&info->register_mutex);
|
||||
INIT_LIST_HEAD(&info->dai_list);
|
||||
|
||||
/* init dai_list used to maintain runtime stream info */
|
||||
|
@ -71,6 +71,7 @@ struct gbaudio_codec_info {
|
||||
/* to maintain runtime stream params for each DAI */
|
||||
struct list_head dai_list;
|
||||
struct mutex lock;
|
||||
struct mutex register_mutex;
|
||||
};
|
||||
|
||||
struct gbaudio_widget {
|
||||
|
@ -149,7 +149,6 @@ static int gbaudio_remove_controls(struct snd_card *card, struct device *dev,
|
||||
for (i = 0; i < num_controls; i++) {
|
||||
const struct snd_kcontrol_new *control = &controls[i];
|
||||
struct snd_ctl_elem_id id;
|
||||
struct snd_kcontrol *kctl;
|
||||
|
||||
if (prefix)
|
||||
snprintf(id.name, sizeof(id.name), "%s %s", prefix,
|
||||
@ -161,17 +160,10 @@ static int gbaudio_remove_controls(struct snd_card *card, struct device *dev,
|
||||
id.device = control->device;
|
||||
id.subdevice = control->subdevice;
|
||||
id.index = control->index;
|
||||
kctl = snd_ctl_find_id(card, &id);
|
||||
if (!kctl) {
|
||||
dev_err(dev, "Failed to find %s\n", control->name);
|
||||
continue;
|
||||
}
|
||||
err = snd_ctl_remove(card, kctl);
|
||||
if (err < 0) {
|
||||
err = snd_ctl_remove_id(card, &id);
|
||||
if (err < 0)
|
||||
dev_err(dev, "%d: Failed to remove %s\n", err,
|
||||
control->name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -181,11 +173,7 @@ int gbaudio_remove_component_controls(struct snd_soc_component *component,
|
||||
unsigned int num_controls)
|
||||
{
|
||||
struct snd_card *card = component->card->snd_card;
|
||||
int err;
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
err = gbaudio_remove_controls(card, component->dev, controls,
|
||||
return gbaudio_remove_controls(card, component->dev, controls,
|
||||
num_controls, component->name_prefix);
|
||||
up_write(&card->controls_rwsem);
|
||||
return err;
|
||||
}
|
||||
|
@ -349,6 +349,7 @@ unsigned long devm_get_free_pages(struct device *dev,
|
||||
gfp_t gfp_mask, unsigned int order);
|
||||
void devm_free_pages(struct device *dev, unsigned long addr);
|
||||
|
||||
#ifdef CONFIG_HAS_IOMEM
|
||||
void __iomem *devm_ioremap_resource(struct device *dev,
|
||||
const struct resource *res);
|
||||
void __iomem *devm_ioremap_resource_wc(struct device *dev,
|
||||
@ -357,6 +358,31 @@ void __iomem *devm_ioremap_resource_wc(struct device *dev,
|
||||
void __iomem *devm_of_iomap(struct device *dev,
|
||||
struct device_node *node, int index,
|
||||
resource_size_t *size);
|
||||
#else
|
||||
|
||||
static inline
|
||||
void __iomem *devm_ioremap_resource(struct device *dev,
|
||||
const struct resource *res)
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline
|
||||
void __iomem *devm_ioremap_resource_wc(struct device *dev,
|
||||
const struct resource *res)
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline
|
||||
void __iomem *devm_of_iomap(struct device *dev,
|
||||
struct device_node *node, int index,
|
||||
resource_size_t *size)
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* allows to add/remove a custom action to devres stack */
|
||||
void devm_remove_action(struct device *dev, void (*action)(void *), void *data);
|
||||
|
@ -201,8 +201,9 @@ struct iio_dev
|
||||
* @chan: The channel being queried.
|
||||
* @val: Value read back.
|
||||
*
|
||||
* Note raw reads from iio channels are in adc counts and hence
|
||||
* scale will need to be applied if standard units required.
|
||||
* Note, if standard units are required, raw reads from iio channels
|
||||
* need the offset (default 0) and scale (default 1) to be applied
|
||||
* as (raw + offset) * scale.
|
||||
*/
|
||||
int iio_read_channel_raw(struct iio_channel *chan,
|
||||
int *val);
|
||||
@ -212,8 +213,9 @@ int iio_read_channel_raw(struct iio_channel *chan,
|
||||
* @chan: The channel being queried.
|
||||
* @val: Value read back.
|
||||
*
|
||||
* Note raw reads from iio channels are in adc counts and hence
|
||||
* scale will need to be applied if standard units required.
|
||||
* Note, if standard units are required, raw reads from iio channels
|
||||
* need the offset (default 0) and scale (default 1) to be applied
|
||||
* as (raw + offset) * scale.
|
||||
*
|
||||
* In opposit to the normal iio_read_channel_raw this function
|
||||
* returns the average of multiple reads.
|
||||
@ -281,8 +283,9 @@ int iio_read_channel_attribute(struct iio_channel *chan, int *val,
|
||||
* @chan: The channel being queried.
|
||||
* @val: Value being written.
|
||||
*
|
||||
* Note raw writes to iio channels are in dac counts and hence
|
||||
* scale will need to be applied if standard units required.
|
||||
* Note that for raw writes to iio channels, if the value provided is
|
||||
* in standard units, the affect of the scale and offset must be removed
|
||||
* as (value / scale) - offset.
|
||||
*/
|
||||
int iio_write_channel_raw(struct iio_channel *chan, int val);
|
||||
|
||||
@ -292,11 +295,24 @@ int iio_write_channel_raw(struct iio_channel *chan, int val);
|
||||
* @chan: The channel being queried.
|
||||
* @val: Value read back.
|
||||
*
|
||||
* Note raw reads from iio channels are in adc counts and hence
|
||||
* scale will need to be applied if standard units are required.
|
||||
* Note, if standard units are required, raw reads from iio channels
|
||||
* need the offset (default 0) and scale (default 1) to be applied
|
||||
* as (raw + offset) * scale.
|
||||
*/
|
||||
int iio_read_max_channel_raw(struct iio_channel *chan, int *val);
|
||||
|
||||
/**
|
||||
* iio_read_min_channel_raw() - read minimum available raw value from a given
|
||||
* channel, i.e. the minimum possible value.
|
||||
* @chan: The channel being queried.
|
||||
* @val: Value read back.
|
||||
*
|
||||
* Note, if standard units are required, raw reads from iio channels
|
||||
* need the offset (default 0) and scale (default 1) to be applied
|
||||
* as (raw + offset) * scale.
|
||||
*/
|
||||
int iio_read_min_channel_raw(struct iio_channel *chan, int *val);
|
||||
|
||||
/**
|
||||
* iio_read_avail_channel_raw() - read available raw values from a given channel
|
||||
* @chan: The channel being queried.
|
||||
@ -308,8 +324,9 @@ int iio_read_max_channel_raw(struct iio_channel *chan, int *val);
|
||||
* For ranges, three vals are always returned; min, step and max.
|
||||
* For lists, all the possible values are enumerated.
|
||||
*
|
||||
* Note raw available values from iio channels are in adc counts and
|
||||
* hence scale will need to be applied if standard units are required.
|
||||
* Note, if standard units are required, raw available values from iio
|
||||
* channels need the offset (default 0) and scale (default 1) to be applied
|
||||
* as (raw + offset) * scale.
|
||||
*/
|
||||
int iio_read_avail_channel_raw(struct iio_channel *chan,
|
||||
const int **vals, int *length);
|
||||
|
@ -1,22 +1,12 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* dvb-math provides some complex fixed-point math
|
||||
* operations shared between the dvb related stuff
|
||||
* Provides fixed-point logarithm operations.
|
||||
*
|
||||
* Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __DVB_MATH_H
|
||||
#define __DVB_MATH_H
|
||||
#ifndef __LINUX_INT_LOG_H
|
||||
#define __LINUX_INT_LOG_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
@ -133,6 +133,70 @@
|
||||
*/
|
||||
#define max_t(type, x, y) __careful_cmp((type)(x), (type)(y), >)
|
||||
|
||||
/*
|
||||
* Remove a const qualifier from integer types
|
||||
* _Generic(foo, type-name: association, ..., default: association) performs a
|
||||
* comparison against the foo type (not the qualified type).
|
||||
* Do not use the const keyword in the type-name as it will not match the
|
||||
* unqualified type of foo.
|
||||
*/
|
||||
#define __unconst_integer_type_cases(type) \
|
||||
unsigned type: (unsigned type)0, \
|
||||
signed type: (signed type)0
|
||||
|
||||
#define __unconst_integer_typeof(x) typeof( \
|
||||
_Generic((x), \
|
||||
char: (char)0, \
|
||||
__unconst_integer_type_cases(char), \
|
||||
__unconst_integer_type_cases(short), \
|
||||
__unconst_integer_type_cases(int), \
|
||||
__unconst_integer_type_cases(long), \
|
||||
__unconst_integer_type_cases(long long), \
|
||||
default: (x)))
|
||||
|
||||
/*
|
||||
* Do not check the array parameter using __must_be_array().
|
||||
* In the following legit use-case where the "array" passed is a simple pointer,
|
||||
* __must_be_array() will return a failure.
|
||||
* --- 8< ---
|
||||
* int *buff
|
||||
* ...
|
||||
* min = min_array(buff, nb_items);
|
||||
* --- 8< ---
|
||||
*
|
||||
* The first typeof(&(array)[0]) is needed in order to support arrays of both
|
||||
* 'int *buff' and 'int buff[N]' types.
|
||||
*
|
||||
* The array can be an array of const items.
|
||||
* typeof() keeps the const qualifier. Use __unconst_integer_typeof() in order
|
||||
* to discard the const qualifier for the __element variable.
|
||||
*/
|
||||
#define __minmax_array(op, array, len) ({ \
|
||||
typeof(&(array)[0]) __array = (array); \
|
||||
typeof(len) __len = (len); \
|
||||
__unconst_integer_typeof(__array[0]) __element = __array[--__len]; \
|
||||
while (__len--) \
|
||||
__element = op(__element, __array[__len]); \
|
||||
__element; })
|
||||
|
||||
/**
|
||||
* min_array - return minimum of values present in an array
|
||||
* @array: array
|
||||
* @len: array length
|
||||
*
|
||||
* Note that @len must not be zero (empty array).
|
||||
*/
|
||||
#define min_array(array, len) __minmax_array(min, array, len)
|
||||
|
||||
/**
|
||||
* max_array - return maximum of values present in an array
|
||||
* @array: array
|
||||
* @len: array length
|
||||
*
|
||||
* Note that @len must not be zero (empty array).
|
||||
*/
|
||||
#define max_array(array, len) __minmax_array(max, array, len)
|
||||
|
||||
/**
|
||||
* clamp_t - return a value clamped to a given range using a given type
|
||||
* @type: the type of variable to use
|
||||
|
@ -2644,6 +2644,7 @@
|
||||
|
||||
#define PCI_VENDOR_ID_INTEL 0x8086
|
||||
#define PCI_DEVICE_ID_INTEL_EESSC 0x0008
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_CML_LP 0x02c8
|
||||
#define PCI_DEVICE_ID_INTEL_PXHD_0 0x0320
|
||||
#define PCI_DEVICE_ID_INTEL_PXHD_1 0x0321
|
||||
#define PCI_DEVICE_ID_INTEL_PXH_0 0x0329
|
||||
@ -2659,8 +2660,10 @@
|
||||
#define PCI_DEVICE_ID_INTEL_82424 0x0483
|
||||
#define PCI_DEVICE_ID_INTEL_82378 0x0484
|
||||
#define PCI_DEVICE_ID_INTEL_82425 0x0486
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_CML_H 0x06c8
|
||||
#define PCI_DEVICE_ID_INTEL_MRST_SD0 0x0807
|
||||
#define PCI_DEVICE_ID_INTEL_MRST_SD1 0x0808
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_OAKTRAIL 0x080a
|
||||
#define PCI_DEVICE_ID_INTEL_MFD_SD 0x0820
|
||||
#define PCI_DEVICE_ID_INTEL_MFD_SDIO1 0x0821
|
||||
#define PCI_DEVICE_ID_INTEL_MFD_SDIO2 0x0822
|
||||
@ -2670,15 +2673,19 @@
|
||||
#define PCI_DEVICE_ID_INTEL_QUARK_X1000_ILB 0x095e
|
||||
#define PCI_DEVICE_ID_INTEL_I960 0x0960
|
||||
#define PCI_DEVICE_ID_INTEL_I960RM 0x0962
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_HSW_0 0x0a0c
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_HSW_2 0x0c0c
|
||||
#define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_HSW_3 0x0d0c
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_BYT 0x0f04
|
||||
#define PCI_DEVICE_ID_INTEL_SST_BYT 0x0f28
|
||||
#define PCI_DEVICE_ID_INTEL_8257X_SOL 0x1062
|
||||
#define PCI_DEVICE_ID_INTEL_82573E_SOL 0x1085
|
||||
#define PCI_DEVICE_ID_INTEL_82573L_SOL 0x108f
|
||||
#define PCI_DEVICE_ID_INTEL_82815_MC 0x1130
|
||||
#define PCI_DEVICE_ID_INTEL_82815_CGC 0x1132
|
||||
#define PCI_DEVICE_ID_INTEL_SST_TNG 0x119a
|
||||
#define PCI_DEVICE_ID_INTEL_82092AA_0 0x1221
|
||||
#define PCI_DEVICE_ID_INTEL_7505_0 0x2550
|
||||
#define PCI_DEVICE_ID_INTEL_7205_0 0x255d
|
||||
#define PCI_DEVICE_ID_INTEL_82437 0x122d
|
||||
#define PCI_DEVICE_ID_INTEL_82371FB_0 0x122e
|
||||
#define PCI_DEVICE_ID_INTEL_82371FB_1 0x1230
|
||||
@ -2704,20 +2711,26 @@
|
||||
#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE 0x1576
|
||||
#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_NHI 0x1577
|
||||
#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE 0x1578
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_BDW 0x160c
|
||||
#define PCI_DEVICE_ID_INTEL_80960_RP 0x1960
|
||||
#define PCI_DEVICE_ID_INTEL_QAT_C3XXX 0x19e2
|
||||
#define PCI_DEVICE_ID_INTEL_QAT_C3XXX_VF 0x19e3
|
||||
#define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21
|
||||
#define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT 0x1a38
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_CPT 0x1c20
|
||||
#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN 0x1c41
|
||||
#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX 0x1c5f
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_PBG 0x1d20
|
||||
#define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0 0x1d40
|
||||
#define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_1 0x1d41
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_PPT 0x1e20
|
||||
#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI 0x1e31
|
||||
#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN 0x1e40
|
||||
#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX 0x1e5f
|
||||
#define PCI_DEVICE_ID_INTEL_VMD_201D 0x201d
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_BSW 0x2284
|
||||
#define PCI_DEVICE_ID_INTEL_SST_BSW 0x22a8
|
||||
#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN 0x2310
|
||||
#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX 0x231f
|
||||
#define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410
|
||||
@ -2772,6 +2785,8 @@
|
||||
#define PCI_DEVICE_ID_INTEL_82850_HB 0x2530
|
||||
#define PCI_DEVICE_ID_INTEL_82860_HB 0x2531
|
||||
#define PCI_DEVICE_ID_INTEL_E7501_MCH 0x254c
|
||||
#define PCI_DEVICE_ID_INTEL_7505_0 0x2550
|
||||
#define PCI_DEVICE_ID_INTEL_7205_0 0x255d
|
||||
#define PCI_DEVICE_ID_INTEL_82845G_HB 0x2560
|
||||
#define PCI_DEVICE_ID_INTEL_82845G_IG 0x2562
|
||||
#define PCI_DEVICE_ID_INTEL_82865_HB 0x2570
|
||||
@ -2793,12 +2808,14 @@
|
||||
#define PCI_DEVICE_ID_INTEL_ICH6_0 0x2640
|
||||
#define PCI_DEVICE_ID_INTEL_ICH6_1 0x2641
|
||||
#define PCI_DEVICE_ID_INTEL_ICH6_2 0x2642
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ICH6 0x2668
|
||||
#define PCI_DEVICE_ID_INTEL_ICH6_16 0x266a
|
||||
#define PCI_DEVICE_ID_INTEL_ICH6_17 0x266d
|
||||
#define PCI_DEVICE_ID_INTEL_ICH6_18 0x266e
|
||||
#define PCI_DEVICE_ID_INTEL_ICH6_19 0x266f
|
||||
#define PCI_DEVICE_ID_INTEL_ESB2_0 0x2670
|
||||
#define PCI_DEVICE_ID_INTEL_ESB2_14 0x2698
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ESB2 0x269a
|
||||
#define PCI_DEVICE_ID_INTEL_ESB2_17 0x269b
|
||||
#define PCI_DEVICE_ID_INTEL_ESB2_18 0x269e
|
||||
#define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770
|
||||
@ -2806,11 +2823,12 @@
|
||||
#define PCI_DEVICE_ID_INTEL_3000_HB 0x2778
|
||||
#define PCI_DEVICE_ID_INTEL_82945GM_HB 0x27a0
|
||||
#define PCI_DEVICE_ID_INTEL_82945GM_IG 0x27a2
|
||||
#define PCI_DEVICE_ID_INTEL_ICH7_30 0x27b0
|
||||
#define PCI_DEVICE_ID_INTEL_ICH7_0 0x27b8
|
||||
#define PCI_DEVICE_ID_INTEL_ICH7_1 0x27b9
|
||||
#define PCI_DEVICE_ID_INTEL_ICH7_30 0x27b0
|
||||
#define PCI_DEVICE_ID_INTEL_TGP_LPC 0x27bc
|
||||
#define PCI_DEVICE_ID_INTEL_ICH7_31 0x27bd
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ICH7 0x27d8
|
||||
#define PCI_DEVICE_ID_INTEL_ICH7_17 0x27da
|
||||
#define PCI_DEVICE_ID_INTEL_ICH7_19 0x27dd
|
||||
#define PCI_DEVICE_ID_INTEL_ICH7_20 0x27de
|
||||
@ -2821,17 +2839,20 @@
|
||||
#define PCI_DEVICE_ID_INTEL_ICH8_3 0x2814
|
||||
#define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815
|
||||
#define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ICH8 0x284b
|
||||
#define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850
|
||||
#define PCI_DEVICE_ID_INTEL_VMD_28C0 0x28c0
|
||||
#define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910
|
||||
#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917
|
||||
#define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912
|
||||
#define PCI_DEVICE_ID_INTEL_ICH9_3 0x2913
|
||||
#define PCI_DEVICE_ID_INTEL_ICH9_4 0x2914
|
||||
#define PCI_DEVICE_ID_INTEL_ICH9_7 0x2916
|
||||
#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917
|
||||
#define PCI_DEVICE_ID_INTEL_ICH9_8 0x2918
|
||||
#define PCI_DEVICE_ID_INTEL_ICH9_5 0x2919
|
||||
#define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930
|
||||
#define PCI_DEVICE_ID_INTEL_ICH9_7 0x2916
|
||||
#define PCI_DEVICE_ID_INTEL_ICH9_8 0x2918
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ICH9_0 0x293e
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ICH9_1 0x293f
|
||||
#define PCI_DEVICE_ID_INTEL_I7_MCR 0x2c18
|
||||
#define PCI_DEVICE_ID_INTEL_I7_MC_TAD 0x2c19
|
||||
#define PCI_DEVICE_ID_INTEL_I7_MC_RAS 0x2c1a
|
||||
@ -2848,8 +2869,8 @@
|
||||
#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR 0x2c31
|
||||
#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK 0x2c32
|
||||
#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC 0x2c33
|
||||
#define PCI_DEVICE_ID_INTEL_I7_NONCORE 0x2c41
|
||||
#define PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT 0x2c40
|
||||
#define PCI_DEVICE_ID_INTEL_I7_NONCORE 0x2c41
|
||||
#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE 0x2c50
|
||||
#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT 0x2c51
|
||||
#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2 0x2c70
|
||||
@ -2883,6 +2904,7 @@
|
||||
#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2 0x2db1
|
||||
#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2 0x2db2
|
||||
#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2 0x2db3
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_GML 0x3198
|
||||
#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_TBG4 0x3429
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a
|
||||
@ -2893,12 +2915,13 @@
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_TBG1 0x3431
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_TBG2 0x3432
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_TBG3 0x3433
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ICL_LP 0x34c8
|
||||
#define PCI_DEVICE_ID_INTEL_82830_HB 0x3575
|
||||
#define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577
|
||||
#define PCI_DEVICE_ID_INTEL_82854_HB 0x358c
|
||||
#define PCI_DEVICE_ID_INTEL_82854_IG 0x358e
|
||||
#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580
|
||||
#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582
|
||||
#define PCI_DEVICE_ID_INTEL_82854_HB 0x358c
|
||||
#define PCI_DEVICE_ID_INTEL_82854_IG 0x358e
|
||||
#define PCI_DEVICE_ID_INTEL_E7520_MCH 0x3590
|
||||
#define PCI_DEVICE_ID_INTEL_E7320_MCH 0x3592
|
||||
#define PCI_DEVICE_ID_INTEL_MCH_PA 0x3595
|
||||
@ -2908,11 +2931,11 @@
|
||||
#define PCI_DEVICE_ID_INTEL_MCH_PC 0x3599
|
||||
#define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a
|
||||
#define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_CNB 0x360b
|
||||
#define PCI_DEVICE_ID_INTEL_FBD_CNB 0x360c
|
||||
#define PCI_DEVICE_ID_INTEL_I7300_MCH_ERR 0x360c
|
||||
#define PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 0x360f
|
||||
#define PCI_DEVICE_ID_INTEL_I7300_MCH_FB1 0x3610
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_CNB 0x360b
|
||||
#define PCI_DEVICE_ID_INTEL_FBD_CNB 0x360c
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_JSF0 0x3710
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_JSF1 0x3711
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_JSF2 0x3712
|
||||
@ -2925,14 +2948,19 @@
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_JSF9 0x3719
|
||||
#define PCI_DEVICE_ID_INTEL_QAT_C62X 0x37c8
|
||||
#define PCI_DEVICE_ID_INTEL_QAT_C62X_VF 0x37c9
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ICL_N 0x38c8
|
||||
#define PCI_DEVICE_ID_INTEL_ICH10_0 0x3a14
|
||||
#define PCI_DEVICE_ID_INTEL_ICH10_1 0x3a16
|
||||
#define PCI_DEVICE_ID_INTEL_ICH10_2 0x3a18
|
||||
#define PCI_DEVICE_ID_INTEL_ICH10_3 0x3a1a
|
||||
#define PCI_DEVICE_ID_INTEL_ICH10_4 0x3a30
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ICH10_0 0x3a3e
|
||||
#define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ICH10_1 0x3a6e
|
||||
#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN 0x3b00
|
||||
#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX 0x3b1f
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_5_3400_SERIES_0 0x3b56
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_5_3400_SERIES_1 0x3b57
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_SNB0 0x3c20
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_SNB1 0x3c21
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_SNB2 0x3c22
|
||||
@ -2943,16 +2971,12 @@
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_SNB7 0x3c27
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_SNB8 0x3c2e
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_SNB9 0x3c2f
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_HA 0x3c46
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_IMC0 0x3cb0
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_IMC1 0x3cb1
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_IMC2 0x3cb4
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_IMC3 0x3cb5
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_QPI0 0x3c41
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_QPI1 0x3c42
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_R2PCIE 0x3c43
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_R3QPI0 0x3c44
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_R3QPI1 0x3c45
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_HA 0x3c46
|
||||
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS 0x3c71 /* 15.1 */
|
||||
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR0 0x3c72 /* 16.2 */
|
||||
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR1 0x3c73 /* 16.3 */
|
||||
@ -2964,17 +2988,40 @@
|
||||
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1 0x3cab /* 15.3 */
|
||||
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2 0x3cac /* 15.4 */
|
||||
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3 0x3cad /* 15.5 */
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_IMC0 0x3cb0
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_IMC1 0x3cb1
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_IMC2 0x3cb4
|
||||
#define PCI_DEVICE_ID_INTEL_UNC_IMC3 0x3cb5
|
||||
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO 0x3cb8 /* 17.0 */
|
||||
#define PCI_DEVICE_ID_INTEL_JAKETOWN_UBOX 0x3ce0
|
||||
#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0 0x3cf4 /* 12.6 */
|
||||
#define PCI_DEVICE_ID_INTEL_SBRIDGE_BR 0x3cf5 /* 13.6 */
|
||||
#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1 0x3cf6 /* 12.7 */
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ICL_H 0x3dc8
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f
|
||||
#define PCI_DEVICE_ID_INTEL_5400_ERR 0x4030
|
||||
#define PCI_DEVICE_ID_INTEL_5400_FBD0 0x4035
|
||||
#define PCI_DEVICE_ID_INTEL_5400_FBD1 0x4036
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_TGL_H 0x43c8
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_DG1 0x490d
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_EHL_0 0x4b55
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_EHL_3 0x4b58
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_JSL_N 0x4dc8
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_DG2_0 0x4f90
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_DG2_1 0x4f91
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_DG2_2 0x4f92
|
||||
#define PCI_DEVICE_ID_INTEL_EP80579_0 0x5031
|
||||
#define PCI_DEVICE_ID_INTEL_EP80579_1 0x5032
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ADL_P 0x51c8
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ADL_PS 0x51c9
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_RPL_P_0 0x51ca
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_RPL_P_1 0x51cb
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ADL_M 0x51cc
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ADL_PX 0x51cd
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_RPL_M 0x51ce
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_RPL_PX 0x51cf
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ADL_N 0x54c8
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_APL 0x5a98
|
||||
#define PCI_DEVICE_ID_INTEL_5100_16 0x65f0
|
||||
#define PCI_DEVICE_ID_INTEL_5100_19 0x65f3
|
||||
#define PCI_DEVICE_ID_INTEL_5100_21 0x65f5
|
||||
@ -3008,8 +3055,13 @@
|
||||
#define PCI_DEVICE_ID_INTEL_82443GX_0 0x71a0
|
||||
#define PCI_DEVICE_ID_INTEL_82443GX_2 0x71a2
|
||||
#define PCI_DEVICE_ID_INTEL_82372FB_1 0x7601
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_RPL_S 0x7a50
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ADL_S 0x7ad0
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_MTL 0x7e28
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_ARL_S 0x7f50
|
||||
#define PCI_DEVICE_ID_INTEL_SCH_LPC 0x8119
|
||||
#define PCI_DEVICE_ID_INTEL_SCH_IDE 0x811a
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_POULSBO 0x811b
|
||||
#define PCI_DEVICE_ID_INTEL_E6XX_CU 0x8183
|
||||
#define PCI_DEVICE_ID_INTEL_ITC_LPC 0x8186
|
||||
#define PCI_DEVICE_ID_INTEL_82454GX 0x84c4
|
||||
@ -3018,9 +3070,31 @@
|
||||
#define PCI_DEVICE_ID_INTEL_82454NX 0x84cb
|
||||
#define PCI_DEVICE_ID_INTEL_84460GX 0x84ea
|
||||
#define PCI_DEVICE_ID_INTEL_IXP4XX 0x8500
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_LPT 0x8c20
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_9_SERIES 0x8ca0
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_WBG_0 0x8d20
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_WBG_1 0x8d21
|
||||
#define PCI_DEVICE_ID_INTEL_IXP2800 0x9004
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_LKF 0x98c8
|
||||
#define PCI_DEVICE_ID_INTEL_VMD_9A0B 0x9a0b
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_LPT_LP_0 0x9c20
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_LPT_LP_1 0x9c21
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_WPT_LP 0x9ca0
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_SKL_LP 0x9d70
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_KBL_LP 0x9d71
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_CNL_LP 0x9dc8
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_TGL_LP 0xa0c8
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_SKL 0xa170
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_KBL 0xa171
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_LBG_0 0xa1f0
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_LBG_1 0xa270
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_KBL_H 0xa2f0
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_CNL_H 0xa348
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_CML_S 0xa3f0
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_LNL_P 0xa828
|
||||
#define PCI_DEVICE_ID_INTEL_S21152BB 0xb152
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_CML_R 0xf0c8
|
||||
#define PCI_DEVICE_ID_INTEL_HDA_RKL_S 0xf1c8
|
||||
|
||||
#define PCI_VENDOR_ID_WANGXUN 0x8088
|
||||
|
||||
|
@ -63,6 +63,8 @@ extern struct resource *platform_get_mem_or_io(struct platform_device *,
|
||||
extern struct device *
|
||||
platform_find_device_by_driver(struct device *start,
|
||||
const struct device_driver *drv);
|
||||
|
||||
#ifdef CONFIG_HAS_IOMEM
|
||||
extern void __iomem *
|
||||
devm_platform_get_and_ioremap_resource(struct platform_device *pdev,
|
||||
unsigned int index, struct resource **res);
|
||||
@ -72,6 +74,32 @@ devm_platform_ioremap_resource(struct platform_device *pdev,
|
||||
extern void __iomem *
|
||||
devm_platform_ioremap_resource_byname(struct platform_device *pdev,
|
||||
const char *name);
|
||||
#else
|
||||
|
||||
static inline void __iomem *
|
||||
devm_platform_get_and_ioremap_resource(struct platform_device *pdev,
|
||||
unsigned int index, struct resource **res)
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
|
||||
static inline void __iomem *
|
||||
devm_platform_ioremap_resource(struct platform_device *pdev,
|
||||
unsigned int index)
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline void __iomem *
|
||||
devm_platform_ioremap_resource_byname(struct platform_device *pdev,
|
||||
const char *name)
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern int platform_get_irq(struct platform_device *, unsigned int);
|
||||
extern int platform_get_irq_optional(struct platform_device *, unsigned int);
|
||||
extern int platform_irq_count(struct platform_device *);
|
||||
|
@ -148,7 +148,7 @@ struct snd_compr_ops {
|
||||
*/
|
||||
struct snd_compr {
|
||||
const char *name;
|
||||
struct device dev;
|
||||
struct device *dev;
|
||||
struct snd_compr_ops *ops;
|
||||
void *private_data;
|
||||
struct snd_card *card;
|
||||
|
@ -140,8 +140,32 @@ int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id);
|
||||
int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id);
|
||||
void snd_ctl_rename(struct snd_card *card, struct snd_kcontrol *kctl, const char *name);
|
||||
int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, int active);
|
||||
struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid);
|
||||
struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id);
|
||||
struct snd_kcontrol *snd_ctl_find_numid_locked(struct snd_card *card, unsigned int numid);
|
||||
struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid);
|
||||
struct snd_kcontrol *snd_ctl_find_id_locked(struct snd_card *card, const struct snd_ctl_elem_id *id);
|
||||
struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, const struct snd_ctl_elem_id *id);
|
||||
|
||||
/**
|
||||
* snd_ctl_find_id_mixer - find the control instance with the given name string
|
||||
* @card: the card instance
|
||||
* @name: the name string
|
||||
*
|
||||
* Finds the control instance with the given name and
|
||||
* @SNDRV_CTL_ELEM_IFACE_MIXER. Other fields are set to zero.
|
||||
*
|
||||
* This is merely a wrapper to snd_ctl_find_id().
|
||||
*
|
||||
* Return: The pointer of the instance if found, or %NULL if not.
|
||||
*/
|
||||
static inline struct snd_kcontrol *
|
||||
snd_ctl_find_id_mixer(struct snd_card *card, const char *name)
|
||||
{
|
||||
struct snd_ctl_elem_id id = {};
|
||||
|
||||
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strscpy(id.name, name, sizeof(id.name));
|
||||
return snd_ctl_find_id(card, &id);
|
||||
}
|
||||
|
||||
int snd_ctl_create(struct snd_card *card);
|
||||
|
||||
@ -238,6 +262,9 @@ snd_ctl_add_follower(struct snd_kcontrol *master, struct snd_kcontrol *follower)
|
||||
return _snd_ctl_add_follower(master, follower, 0);
|
||||
}
|
||||
|
||||
int snd_ctl_add_followers(struct snd_card *card, struct snd_kcontrol *master,
|
||||
const char * const *list);
|
||||
|
||||
/**
|
||||
* snd_ctl_add_follower_uncached - Add a virtual follower control
|
||||
* @master: vmaster element
|
||||
|
@ -96,7 +96,7 @@ struct snd_card {
|
||||
private data */
|
||||
struct list_head devices; /* devices */
|
||||
|
||||
struct device ctl_dev; /* control device */
|
||||
struct device *ctl_dev; /* control device */
|
||||
unsigned int last_numid; /* last used numeric ID */
|
||||
struct rw_semaphore controls_rwsem; /* controls lock (list and values) */
|
||||
rwlock_t ctl_files_rwlock; /* ctl_files list lock */
|
||||
@ -239,7 +239,7 @@ extern struct dentry *sound_debugfs_root;
|
||||
|
||||
void snd_request_card(int card);
|
||||
|
||||
void snd_device_initialize(struct device *dev, struct snd_card *card);
|
||||
int snd_device_alloc(struct device **dev_p, struct snd_card *card);
|
||||
|
||||
int snd_register_device(int type, struct snd_card *card, int dev,
|
||||
const struct file_operations *f_ops,
|
||||
|
@ -829,6 +829,7 @@ enum cs35l41_cspl_mbox_cmd {
|
||||
CSPL_MBOX_CMD_STOP_PRE_REINIT = 4,
|
||||
CSPL_MBOX_CMD_HIBERNATE = 5,
|
||||
CSPL_MBOX_CMD_OUT_OF_HIBERNATE = 6,
|
||||
CSPL_MBOX_CMD_SPK_OUT_ENABLE = 7,
|
||||
CSPL_MBOX_CMD_UNKNOWN_CMD = -1,
|
||||
CSPL_MBOX_CMD_INVALID_SEQUENCE = -2,
|
||||
};
|
||||
@ -901,7 +902,7 @@ int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap);
|
||||
int cs35l41_init_boost(struct device *dev, struct regmap *regmap,
|
||||
struct cs35l41_hw_cfg *hw_cfg);
|
||||
bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type);
|
||||
int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable,
|
||||
struct completion *pll_lock);
|
||||
int cs35l41_global_enable(struct device *dev, struct regmap *regmap, enum cs35l41_boost_type b_type,
|
||||
int enable, struct completion *pll_lock, bool firmware_running);
|
||||
|
||||
#endif /* __CS35L41_H */
|
||||
|
@ -252,15 +252,40 @@
|
||||
#define CS35L56_NUM_BULK_SUPPLIES 3
|
||||
#define CS35L56_NUM_DSP_REGIONS 5
|
||||
|
||||
struct cs35l56_base {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
int irq;
|
||||
struct mutex irq_lock;
|
||||
u8 rev;
|
||||
bool init_done;
|
||||
bool fw_patched;
|
||||
bool secured;
|
||||
bool can_hibernate;
|
||||
struct gpio_desc *reset_gpio;
|
||||
};
|
||||
|
||||
extern struct regmap_config cs35l56_regmap_i2c;
|
||||
extern struct regmap_config cs35l56_regmap_spi;
|
||||
extern struct regmap_config cs35l56_regmap_sdw;
|
||||
|
||||
extern const struct cs_dsp_region cs35l56_dsp1_regions[CS35L56_NUM_DSP_REGIONS];
|
||||
extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC];
|
||||
extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC];
|
||||
|
||||
void cs35l56_reread_firmware_registers(struct device *dev, struct regmap *regmap);
|
||||
int cs35l56_set_patch(struct cs35l56_base *cs35l56_base);
|
||||
int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command);
|
||||
int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base);
|
||||
int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base);
|
||||
void cs35l56_wait_control_port_ready(void);
|
||||
void cs35l56_wait_min_reset_pulse(void);
|
||||
void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire);
|
||||
int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq);
|
||||
irqreturn_t cs35l56_irq(int irq, void *data);
|
||||
int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base);
|
||||
int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base);
|
||||
int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire);
|
||||
void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp);
|
||||
int cs35l56_hw_init(struct cs35l56_base *cs35l56_base);
|
||||
int cs35l56_get_bclk_freq_id(unsigned int freq);
|
||||
void cs35l56_fill_supply_names(struct regulator_bulk_data *data);
|
||||
|
||||
|
@ -142,7 +142,7 @@ struct snd_dmaengine_pcm_config {
|
||||
struct snd_pcm_substream *substream);
|
||||
int (*process)(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long hwoff,
|
||||
void *buf, unsigned long bytes);
|
||||
struct iov_iter *buf, unsigned long bytes);
|
||||
dma_filter_fn compat_filter_fn;
|
||||
struct device *dma_dev;
|
||||
const char *chan_names[SNDRV_PCM_STREAM_LAST + 1];
|
||||
|
@ -902,6 +902,11 @@ SUB_REG_NC(A_EHC, A_I2S_CAPTURE_RATE, 0x00000e00) /* This sets the capture PCM
|
||||
#define A_TTDA 0x7a /* Tank Table DMA Address */
|
||||
#define A_TTDD 0x7b /* Tank Table DMA Data */
|
||||
|
||||
// In A_FXRT1 & A_FXRT2, the 0x80 bit of each byte completely disables the
|
||||
// filter (CVCF_CURRENTFILTER) for the corresponding channel. There is no
|
||||
// effect on the volume (CVCF_CURRENTVOLUME) or the interpolator's filter
|
||||
// (CCCA_INTERPROM_MASK).
|
||||
|
||||
#define A_FXRT2 0x7c
|
||||
#define A_FXRT_CHANNELE 0x0000003f /* Effects send bus number for channel's effects send E */
|
||||
#define A_FXRT_CHANNELF 0x00003f00 /* Effects send bus number for channel's effects send F */
|
||||
@ -914,8 +919,6 @@ SUB_REG_NC(A_EHC, A_I2S_CAPTURE_RATE, 0x00000e00) /* This sets the capture PCM
|
||||
#define A_FXSENDAMOUNT_G_MASK 0x0000FF00
|
||||
#define A_FXSENDAMOUNT_H_MASK 0x000000FF
|
||||
|
||||
/* 0x7c, 0x7e "high bit is used for filtering" */
|
||||
|
||||
/* The send amounts for this one are the same as used with the emu10k1 */
|
||||
#define A_FXRT1 0x7e
|
||||
#define A_FXRT_CHANNELA 0x0000003f
|
||||
@ -992,6 +995,9 @@ SUB_REG_NC(A_EHC, A_I2S_CAPTURE_RATE, 0x00000e00) /* This sets the capture PCM
|
||||
#define EMU_HANA_WCLOCK_4X 0x10
|
||||
#define EMU_HANA_WCLOCK_MULT_RESERVED 0x18
|
||||
|
||||
// If the selected external clock source is/becomes invalid or incompatible
|
||||
// with the clock multiplier, the clock source is reset to this value, and
|
||||
// a WCLK_CHANGED interrupt is raised.
|
||||
#define EMU_HANA_DEFCLOCK 0x06 /* 000000x 1 bits Default Word Clock */
|
||||
#define EMU_HANA_DEFCLOCK_48K 0x00
|
||||
#define EMU_HANA_DEFCLOCK_44_1K 0x01
|
||||
@ -1523,10 +1529,10 @@ struct snd_emu10k1_pcm_mixer {
|
||||
((route[0] | (route[1] << 4) | (route[2] << 8) | (route[3] << 12)) << 16)
|
||||
|
||||
#define snd_emu10k1_compose_audigy_fxrt1(route) \
|
||||
((unsigned int)route[0] | ((unsigned int)route[1] << 8) | ((unsigned int)route[2] << 16) | ((unsigned int)route[3] << 24))
|
||||
((unsigned int)route[0] | ((unsigned int)route[1] << 8) | ((unsigned int)route[2] << 16) | ((unsigned int)route[3] << 24) | 0x80808080)
|
||||
|
||||
#define snd_emu10k1_compose_audigy_fxrt2(route) \
|
||||
((unsigned int)route[4] | ((unsigned int)route[5] << 8) | ((unsigned int)route[6] << 16) | ((unsigned int)route[7] << 24))
|
||||
((unsigned int)route[4] | ((unsigned int)route[5] << 8) | ((unsigned int)route[6] << 16) | ((unsigned int)route[7] << 24) | 0x80808080)
|
||||
|
||||
#define snd_emu10k1_compose_audigy_sendamounts(vol) \
|
||||
(((unsigned int)vol[4] << 24) | ((unsigned int)vol[5] << 16) | ((unsigned int)vol[6] << 8) | (unsigned int)vol[7])
|
||||
@ -1678,8 +1684,8 @@ struct snd_emu1010 {
|
||||
unsigned int clock_fallback;
|
||||
unsigned int optical_in; /* 0:SPDIF, 1:ADAT */
|
||||
unsigned int optical_out; /* 0:SPDIF, 1:ADAT */
|
||||
struct delayed_work firmware_work;
|
||||
u32 last_reg;
|
||||
struct work_struct firmware_work;
|
||||
struct work_struct clock_work;
|
||||
};
|
||||
|
||||
struct snd_emu10k1 {
|
||||
@ -1754,6 +1760,7 @@ struct snd_emu10k1 {
|
||||
struct snd_kcontrol *ctl_efx_send_routing;
|
||||
struct snd_kcontrol *ctl_efx_send_volume;
|
||||
struct snd_kcontrol *ctl_efx_attn;
|
||||
struct snd_kcontrol *ctl_clock_source;
|
||||
|
||||
void (*hwvol_interrupt)(struct snd_emu10k1 *emu, unsigned int status);
|
||||
void (*capture_interrupt)(struct snd_emu10k1 *emu, unsigned int status);
|
||||
@ -1761,6 +1768,7 @@ struct snd_emu10k1 {
|
||||
void (*capture_efx_interrupt)(struct snd_emu10k1 *emu, unsigned int status);
|
||||
void (*spdif_interrupt)(struct snd_emu10k1 *emu, unsigned int status);
|
||||
void (*dsp_interrupt)(struct snd_emu10k1 *emu);
|
||||
void (*gpio_interrupt)(struct snd_emu10k1 *emu);
|
||||
void (*p16v_interrupt)(struct snd_emu10k1 *emu);
|
||||
|
||||
struct snd_pcm_substream *pcm_capture_substream;
|
||||
|
@ -18,9 +18,6 @@
|
||||
#include <sound/hda_verbs.h>
|
||||
#include <sound/hda_regmap.h>
|
||||
|
||||
#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
|
||||
#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348)
|
||||
|
||||
/*
|
||||
* Structures
|
||||
*/
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/io-64-nonatomic-lo-hi.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/timecounter.h>
|
||||
#include <sound/core.h>
|
||||
@ -704,4 +705,29 @@ static inline unsigned int snd_array_index(struct snd_array *array, void *ptr)
|
||||
for ((idx) = 0, (ptr) = (array)->list; (idx) < (array)->used; \
|
||||
(ptr) = snd_array_elem(array, ++(idx)))
|
||||
|
||||
/*
|
||||
* Device matching
|
||||
*/
|
||||
|
||||
#define HDA_CONTROLLER_IS_HSW(pci) (pci_match_id((struct pci_device_id []){ \
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_HSW_0) }, \
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_HSW_2) }, \
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_HSW_3) }, \
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_BDW) }, \
|
||||
{ } \
|
||||
}, pci))
|
||||
|
||||
#define HDA_CONTROLLER_IS_APL(pci) (pci_match_id((struct pci_device_id []){ \
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_APL) }, \
|
||||
{ } \
|
||||
}, pci))
|
||||
|
||||
#define HDA_CONTROLLER_IN_GPU(pci) (pci_match_id((struct pci_device_id []){ \
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG1) }, \
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG2_0) }, \
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG2_1) }, \
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG2_2) }, \
|
||||
{ } \
|
||||
}, pci) || HDA_CONTROLLER_IS_HSW(pci))
|
||||
|
||||
#endif /* __SOUND_HDAUDIO_H */
|
||||
|
@ -53,7 +53,7 @@ struct snd_hwdep {
|
||||
wait_queue_head_t open_wait;
|
||||
void *private_data;
|
||||
void (*private_free) (struct snd_hwdep *hwdep);
|
||||
struct device dev;
|
||||
struct device *dev;
|
||||
|
||||
struct mutex open_mutex;
|
||||
int used; /* reference counter */
|
||||
|
@ -118,8 +118,6 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
|
||||
const char *name,
|
||||
struct snd_info_entry *parent);
|
||||
void snd_info_free_entry(struct snd_info_entry *entry);
|
||||
int snd_info_store_text(struct snd_info_entry *entry);
|
||||
int snd_info_restore_text(struct snd_info_entry *entry);
|
||||
|
||||
int snd_info_card_create(struct snd_card *card);
|
||||
int snd_info_card_register(struct snd_card *card);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/refcount.h>
|
||||
#include <linux/uio.h>
|
||||
|
||||
#define snd_pcm_substream_chip(substream) ((substream)->private_data)
|
||||
#define snd_pcm_chip(pcm) ((pcm)->private_data)
|
||||
@ -68,11 +69,8 @@ struct snd_pcm_ops {
|
||||
struct snd_pcm_audio_tstamp_report *audio_tstamp_report);
|
||||
int (*fill_silence)(struct snd_pcm_substream *substream, int channel,
|
||||
unsigned long pos, unsigned long bytes);
|
||||
int (*copy_user)(struct snd_pcm_substream *substream, int channel,
|
||||
unsigned long pos, void __user *buf,
|
||||
unsigned long bytes);
|
||||
int (*copy_kernel)(struct snd_pcm_substream *substream, int channel,
|
||||
unsigned long pos, void *buf, unsigned long bytes);
|
||||
int (*copy)(struct snd_pcm_substream *substream, int channel,
|
||||
unsigned long pos, struct iov_iter *iter, unsigned long bytes);
|
||||
struct page *(*page)(struct snd_pcm_substream *substream,
|
||||
unsigned long offset);
|
||||
int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
|
||||
@ -510,7 +508,7 @@ struct snd_pcm_str {
|
||||
#endif
|
||||
#endif
|
||||
struct snd_kcontrol *chmap_kctl; /* channel-mapping controls */
|
||||
struct device dev;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
struct snd_pcm {
|
||||
@ -1556,6 +1554,11 @@ 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)
|
||||
|
||||
/* helpers for copying between iov_iter and iomem */
|
||||
int copy_to_iter_fromio(struct iov_iter *itert, const void __iomem *src,
|
||||
size_t count);
|
||||
int copy_from_iter_toio(void __iomem *dst, struct iov_iter *iter, size_t count);
|
||||
|
||||
struct snd_pcm_status64 {
|
||||
snd_pcm_state_t state; /* stream state */
|
||||
u8 rsvd[4];
|
||||
|
@ -135,7 +135,7 @@ struct snd_rawmidi {
|
||||
struct mutex open_mutex;
|
||||
wait_queue_head_t open_wait;
|
||||
|
||||
struct device dev;
|
||||
struct device *dev;
|
||||
|
||||
struct snd_info_entry *proc_entry;
|
||||
|
||||
|
@ -192,9 +192,8 @@ int asoc_simple_remove(struct platform_device *pdev);
|
||||
|
||||
int asoc_graph_card_probe(struct snd_soc_card *card);
|
||||
int asoc_graph_is_ports0(struct device_node *port);
|
||||
int asoc_graph_parse_dai(struct device_node *ep,
|
||||
struct snd_soc_dai_link_component *dlc,
|
||||
int *is_single_link);
|
||||
int asoc_graph_parse_dai(struct device *dev, struct device_node *ep,
|
||||
struct snd_soc_dai_link_component *dlc, int *is_single_link);
|
||||
|
||||
#ifdef DEBUG
|
||||
static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
|
||||
|
@ -137,9 +137,9 @@ struct snd_soc_component_driver {
|
||||
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,
|
||||
int (*copy)(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream, int channel,
|
||||
unsigned long pos, void __user *buf,
|
||||
unsigned long pos, struct iov_iter *buf,
|
||||
unsigned long bytes);
|
||||
struct page *(*page)(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream,
|
||||
@ -509,9 +509,9 @@ int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream);
|
||||
int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream,
|
||||
unsigned int cmd, void *arg);
|
||||
int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream);
|
||||
int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream,
|
||||
int snd_soc_pcm_component_copy(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long pos,
|
||||
void __user *buf, unsigned long bytes);
|
||||
struct iov_iter *buf, unsigned long bytes);
|
||||
struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream,
|
||||
unsigned long offset);
|
||||
int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream,
|
||||
|
@ -271,6 +271,8 @@ int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai,
|
||||
struct snd_compr_stream *cstream,
|
||||
struct snd_compr_metadata *metadata);
|
||||
|
||||
const char *snd_soc_dai_name_get(struct snd_soc_dai *dai);
|
||||
|
||||
struct snd_soc_dai_ops {
|
||||
/*
|
||||
* DAI clocking configuration, all optional.
|
||||
@ -397,6 +399,7 @@ struct snd_soc_dai_driver {
|
||||
unsigned int id;
|
||||
unsigned int base;
|
||||
struct snd_soc_dobj dobj;
|
||||
struct of_phandle_args *dai_args;
|
||||
|
||||
/* DAI driver callbacks */
|
||||
int (*probe)(struct snd_soc_dai *dai);
|
||||
|
@ -42,36 +42,45 @@ struct soc_enum;
|
||||
|
||||
/* codec domain */
|
||||
#define SND_SOC_DAPM_VMID(wname) \
|
||||
{ .id = snd_soc_dapm_vmid, .name = wname, .kcontrol_news = NULL, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_vmid, .name = wname, .kcontrol_news = NULL, \
|
||||
.num_kcontrols = 0}
|
||||
|
||||
/* platform domain */
|
||||
#define SND_SOC_DAPM_SIGGEN(wname) \
|
||||
{ .id = snd_soc_dapm_siggen, .name = wname, .kcontrol_news = NULL, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_siggen, .name = wname, .kcontrol_news = NULL, \
|
||||
.num_kcontrols = 0, .reg = SND_SOC_NOPM }
|
||||
#define SND_SOC_DAPM_SINK(wname) \
|
||||
{ .id = snd_soc_dapm_sink, .name = wname, .kcontrol_news = NULL, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_sink, .name = wname, .kcontrol_news = NULL, \
|
||||
.num_kcontrols = 0, .reg = SND_SOC_NOPM }
|
||||
#define SND_SOC_DAPM_INPUT(wname) \
|
||||
{ .id = snd_soc_dapm_input, .name = wname, .kcontrol_news = NULL, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_input, .name = wname, .kcontrol_news = NULL, \
|
||||
.num_kcontrols = 0, .reg = SND_SOC_NOPM }
|
||||
#define SND_SOC_DAPM_OUTPUT(wname) \
|
||||
{ .id = snd_soc_dapm_output, .name = wname, .kcontrol_news = NULL, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_output, .name = wname, .kcontrol_news = NULL, \
|
||||
.num_kcontrols = 0, .reg = SND_SOC_NOPM }
|
||||
#define SND_SOC_DAPM_MIC(wname, wevent) \
|
||||
{ .id = snd_soc_dapm_mic, .name = wname, .kcontrol_news = NULL, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_mic, .name = wname, .kcontrol_news = NULL, \
|
||||
.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
|
||||
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
|
||||
#define SND_SOC_DAPM_HP(wname, wevent) \
|
||||
{ .id = snd_soc_dapm_hp, .name = wname, .kcontrol_news = NULL, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_hp, .name = wname, .kcontrol_news = NULL, \
|
||||
.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
|
||||
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
|
||||
#define SND_SOC_DAPM_SPK(wname, wevent) \
|
||||
{ .id = snd_soc_dapm_spk, .name = wname, .kcontrol_news = NULL, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_spk, .name = wname, .kcontrol_news = NULL, \
|
||||
.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
|
||||
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
|
||||
#define SND_SOC_DAPM_LINE(wname, wevent) \
|
||||
{ .id = snd_soc_dapm_line, .name = wname, .kcontrol_news = NULL, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_line, .name = wname, .kcontrol_news = NULL, \
|
||||
.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
|
||||
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
|
||||
|
||||
@ -82,93 +91,110 @@ struct soc_enum;
|
||||
/* path domain */
|
||||
#define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\
|
||||
wcontrols, wncontrols) \
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_pga, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
||||
#define SND_SOC_DAPM_OUT_DRV(wname, wreg, wshift, winvert,\
|
||||
wcontrols, wncontrols) \
|
||||
{ .id = snd_soc_dapm_out_drv, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_out_drv, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
||||
#define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \
|
||||
wcontrols, wncontrols)\
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_mixer, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
||||
#define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \
|
||||
wcontrols, wncontrols)\
|
||||
{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
|
||||
/* DEPRECATED: use SND_SOC_DAPM_SUPPLY */
|
||||
#define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \
|
||||
{ .id = snd_soc_dapm_micbias, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_micbias, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = NULL, .num_kcontrols = 0}
|
||||
#define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \
|
||||
{ .id = snd_soc_dapm_switch, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_switch, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||
#define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
|
||||
{ .id = snd_soc_dapm_mux, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_mux, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||
#define SND_SOC_DAPM_DEMUX(wname, wreg, wshift, winvert, wcontrols) \
|
||||
{ .id = snd_soc_dapm_demux, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_demux, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1}
|
||||
|
||||
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
|
||||
#define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\
|
||||
wcontrols) \
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_pga, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
|
||||
#define SOC_MIXER_ARRAY(wname, wreg, wshift, winvert, \
|
||||
wcontrols)\
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_mixer, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
|
||||
#define SOC_MIXER_NAMED_CTL_ARRAY(wname, wreg, wshift, winvert, \
|
||||
wcontrols)\
|
||||
{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
|
||||
|
||||
/* path domain with event - event handler must return 0 for success */
|
||||
#define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wncontrols, wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_pga, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wncontrols, wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_out_drv, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_out_drv, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wncontrols, wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_mixer, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \
|
||||
wcontrols, wncontrols, wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_mixer, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, \
|
||||
.num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_switch, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_switch, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1, \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_mux, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_mux, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = 1, \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
@ -176,101 +202,121 @@ struct soc_enum;
|
||||
/* additional sequencing control within an event type */
|
||||
#define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_pga, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.event = wevent, .event_flags = wflags, \
|
||||
.subseq = wsubseq}
|
||||
#define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \
|
||||
wflags) \
|
||||
{ .id = snd_soc_dapm_supply, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_supply, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.event = wevent, .event_flags = wflags, .subseq = wsubseq}
|
||||
|
||||
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
|
||||
#define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_pga, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_pga, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SOC_MIXER_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_mixer, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SOC_MIXER_NAMED_CTL_E_ARRAY(wname, wreg, wshift, winvert, \
|
||||
wcontrols, wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_mixer, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_mixer, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
|
||||
/* events that are pre and post DAPM */
|
||||
#define SND_SOC_DAPM_PRE(wname, wevent) \
|
||||
{ .id = snd_soc_dapm_pre, .name = wname, .kcontrol_news = NULL, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_pre, .name = wname, .kcontrol_news = NULL, \
|
||||
.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
|
||||
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD}
|
||||
#define SND_SOC_DAPM_POST(wname, wevent) \
|
||||
{ .id = snd_soc_dapm_post, .name = wname, .kcontrol_news = NULL, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_post, .name = wname, .kcontrol_news = NULL, \
|
||||
.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
|
||||
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD}
|
||||
|
||||
/* stream domain */
|
||||
#define SND_SOC_DAPM_AIF_IN(wname, stname, wchan, wreg, wshift, winvert) \
|
||||
{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
|
||||
.channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
|
||||
#define SND_SOC_DAPM_AIF_IN_E(wname, stname, wchan, wreg, wshift, winvert, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
|
||||
.channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.event = wevent, .event_flags = wflags }
|
||||
#define SND_SOC_DAPM_AIF_OUT(wname, stname, wchan, wreg, wshift, winvert) \
|
||||
{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
|
||||
.channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
|
||||
#define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wchan, wreg, wshift, winvert, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
|
||||
.channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.event = wevent, .event_flags = wflags }
|
||||
#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
|
||||
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) }
|
||||
#define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
|
||||
#define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \
|
||||
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
|
||||
#define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \
|
||||
wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \
|
||||
{ .id = snd_soc_dapm_clock_supply, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_clock_supply, .name = wname, \
|
||||
.reg = SND_SOC_NOPM, .event = dapm_clock_event, \
|
||||
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }
|
||||
|
||||
/* generic widgets */
|
||||
#define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \
|
||||
{ .id = wid, .name = wname, .kcontrol_news = NULL, .num_kcontrols = 0, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = wid, .name = wname, .kcontrol_news = NULL, .num_kcontrols = 0, \
|
||||
.reg = wreg, .shift = wshift, .mask = wmask, \
|
||||
.on_val = won_val, .off_val = woff_val, }
|
||||
#define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \
|
||||
{ .id = snd_soc_dapm_supply, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_supply, .name = wname, \
|
||||
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
|
||||
.event = wevent, .event_flags = wflags}
|
||||
#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \
|
||||
{ .id = snd_soc_dapm_regulator_supply, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_regulator_supply, .name = wname, \
|
||||
.reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \
|
||||
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \
|
||||
.on_val = wflags}
|
||||
#define SND_SOC_DAPM_PINCTRL(wname, active, sleep) \
|
||||
{ .id = snd_soc_dapm_pinctrl, .name = wname, \
|
||||
(struct snd_soc_dapm_widget) { \
|
||||
.id = snd_soc_dapm_pinctrl, .name = wname, \
|
||||
.priv = (&(struct snd_soc_dapm_pinctrl_priv) \
|
||||
{ .active_state = active, .sleep_state = sleep,}), \
|
||||
.reg = SND_SOC_NOPM, .event = dapm_pinctrl_event, \
|
||||
|
@ -651,6 +651,7 @@ struct snd_soc_dai_link_component {
|
||||
const char *name;
|
||||
struct device_node *of_node;
|
||||
const char *dai_name;
|
||||
struct of_phandle_args *dai_args;
|
||||
};
|
||||
|
||||
struct snd_soc_dai_link_codec_ch_map {
|
||||
@ -1335,6 +1336,11 @@ int snd_soc_add_pcm_runtimes(struct snd_soc_card *card,
|
||||
void snd_soc_remove_pcm_runtime(struct snd_soc_card *card,
|
||||
struct snd_soc_pcm_runtime *rtd);
|
||||
|
||||
void snd_soc_dlc_use_cpu_as_platform(struct snd_soc_dai_link_component *platforms,
|
||||
struct snd_soc_dai_link_component *cpus);
|
||||
struct of_phandle_args *snd_soc_copy_dai_args(struct device *dev,
|
||||
struct of_phandle_args *args);
|
||||
struct snd_soc_dai *snd_soc_get_dai_via_args(struct of_phandle_args *dai_args);
|
||||
struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component,
|
||||
struct snd_soc_dai_driver *dai_drv,
|
||||
bool legacy_dai_naming);
|
||||
|
@ -45,6 +45,7 @@ struct snd_ump_endpoint {
|
||||
spinlock_t legacy_locks[2];
|
||||
struct snd_rawmidi *legacy_rmidi;
|
||||
struct snd_rawmidi_substream *legacy_substreams[2][SNDRV_UMP_MAX_GROUPS];
|
||||
unsigned char legacy_mapping[SNDRV_UMP_MAX_GROUPS];
|
||||
|
||||
/* for legacy output; need to open the actual substream unlike input */
|
||||
int legacy_out_opens;
|
||||
|
@ -1544,6 +1544,7 @@ int import_ubuf(int rw, void __user *buf, size_t len, struct iov_iter *i)
|
||||
iov_iter_ubuf(i, rw, buf, len);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(import_ubuf);
|
||||
|
||||
/**
|
||||
* iov_iter_restore() - Restore a &struct iov_iter to the same state as when
|
||||
|
@ -1,5 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-y += div64.o gcd.o lcm.o int_pow.o int_sqrt.o reciprocal_div.o
|
||||
obj-y += div64.o gcd.o lcm.o int_log.o int_pow.o int_sqrt.o reciprocal_div.o
|
||||
|
||||
obj-$(CONFIG_CORDIC) += cordic.o
|
||||
obj-$(CONFIG_PRIME_NUMBERS) += prime_numbers.o
|
||||
|
@ -1,25 +1,17 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/*
|
||||
* dvb-math provides some complex fixed-point math
|
||||
* operations shared between the dvb related stuff
|
||||
* Provides fixed-point logarithm operations.
|
||||
*
|
||||
* Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/int_log.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/bug.h>
|
||||
#include <media/dvb_math.h>
|
||||
|
||||
static const unsigned short logtable[256] = {
|
||||
0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7,
|
||||
@ -53,7 +45,7 @@ static const unsigned short logtable[256] = {
|
||||
0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83,
|
||||
0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387,
|
||||
0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973,
|
||||
0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47
|
||||
0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47,
|
||||
};
|
||||
|
||||
unsigned int intlog2(u32 value)
|
||||
@ -90,7 +82,7 @@ unsigned int intlog2(u32 value)
|
||||
* so we would use the entry 0x18
|
||||
*/
|
||||
significand = value << (31 - msb);
|
||||
logentry = (significand >> 23) & 0xff;
|
||||
logentry = (significand >> 23) % ARRAY_SIZE(logtable);
|
||||
|
||||
/**
|
||||
* last step we do is interpolation because of the
|
||||
@ -108,7 +100,7 @@ unsigned int intlog2(u32 value)
|
||||
* logtable_next is 256
|
||||
*/
|
||||
interpolation = ((significand & 0x7fffff) *
|
||||
((logtable[(logentry + 1) & 0xff] -
|
||||
((logtable[(logentry + 1) % ARRAY_SIZE(logtable)] -
|
||||
logtable[logentry]) & 0xffff)) >> 15;
|
||||
|
||||
/* now we return the result */
|
@ -39,8 +39,6 @@ config SOUND_OSS_CORE_PRECLAIM
|
||||
|
||||
source "sound/oss/dmasound/Kconfig"
|
||||
|
||||
if !UML
|
||||
|
||||
menuconfig SND
|
||||
tristate "Advanced Linux Sound Architecture"
|
||||
help
|
||||
@ -103,8 +101,6 @@ source "sound/virtio/Kconfig"
|
||||
|
||||
endif # SND
|
||||
|
||||
endif # !UML
|
||||
|
||||
endif # SOUND
|
||||
|
||||
config AC97_BUS
|
||||
|
@ -462,7 +462,7 @@ static ssize_t vendor_id_show(struct device *dev,
|
||||
|
||||
return sysfs_emit(buf, "%08x", codec->vendor_id);
|
||||
}
|
||||
DEVICE_ATTR_RO(vendor_id);
|
||||
static DEVICE_ATTR_RO(vendor_id);
|
||||
|
||||
static struct attribute *ac97_dev_attrs[] = {
|
||||
&dev_attr_vendor_id.attr,
|
||||
|
@ -972,7 +972,7 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
|
||||
goto out_put_ci_module;
|
||||
snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK,
|
||||
&i2sbus_playback_ops);
|
||||
dev->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].dev.parent =
|
||||
dev->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].dev->parent =
|
||||
&dev->ofdev.dev;
|
||||
i2sdev->out.created = 1;
|
||||
}
|
||||
@ -989,7 +989,7 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
|
||||
goto out_put_ci_module;
|
||||
snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE,
|
||||
&i2sbus_record_ops);
|
||||
dev->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].dev.parent =
|
||||
dev->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].dev->parent =
|
||||
&dev->ofdev.dev;
|
||||
i2sdev->in.created = 1;
|
||||
}
|
||||
|
@ -12,13 +12,12 @@
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/initval.h>
|
||||
|
@ -546,7 +546,7 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
|
||||
if (stream->runtime->dma_buffer_p) {
|
||||
|
||||
if (buffer_size > stream->runtime->dma_buffer_p->bytes)
|
||||
dev_err(&stream->device->dev,
|
||||
dev_err(stream->device->dev,
|
||||
"Not enough DMA buffer");
|
||||
else
|
||||
buffer = stream->runtime->dma_buffer_p->area;
|
||||
@ -1070,7 +1070,7 @@ static int snd_compress_dev_register(struct snd_device *device)
|
||||
/* register compressed device */
|
||||
ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS,
|
||||
compr->card, compr->device,
|
||||
&snd_compr_file_ops, compr, &compr->dev);
|
||||
&snd_compr_file_ops, compr, compr->dev);
|
||||
if (ret < 0) {
|
||||
pr_err("snd_register_device failed %d\n", ret);
|
||||
return ret;
|
||||
@ -1084,7 +1084,7 @@ static int snd_compress_dev_disconnect(struct snd_device *device)
|
||||
struct snd_compr *compr;
|
||||
|
||||
compr = device->device_data;
|
||||
snd_unregister_device(&compr->dev);
|
||||
snd_unregister_device(compr->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1158,7 +1158,7 @@ static int snd_compress_dev_free(struct snd_device *device)
|
||||
|
||||
compr = device->device_data;
|
||||
snd_compress_proc_done(compr);
|
||||
put_device(&compr->dev);
|
||||
put_device(compr->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1189,12 +1189,16 @@ int snd_compress_new(struct snd_card *card, int device,
|
||||
|
||||
snd_compress_set_id(compr, id);
|
||||
|
||||
snd_device_initialize(&compr->dev, card);
|
||||
dev_set_name(&compr->dev, "comprC%iD%i", card->number, device);
|
||||
ret = snd_device_alloc(&compr->dev, card);
|
||||
if (ret)
|
||||
return ret;
|
||||
dev_set_name(compr->dev, "comprC%iD%i", card->number, device);
|
||||
|
||||
ret = snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops);
|
||||
if (ret == 0)
|
||||
snd_compress_proc_init(compr);
|
||||
else
|
||||
put_device(compr->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -39,6 +39,9 @@ static LIST_HEAD(snd_control_compat_ioctls);
|
||||
#endif
|
||||
static struct snd_ctl_layer_ops *snd_ctl_layer;
|
||||
|
||||
static int snd_ctl_remove_locked(struct snd_card *card,
|
||||
struct snd_kcontrol *kcontrol);
|
||||
|
||||
static int snd_ctl_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
unsigned long flags;
|
||||
@ -466,11 +469,13 @@ static int __snd_ctl_add_replace(struct snd_card *card,
|
||||
struct snd_kcontrol *old;
|
||||
int err;
|
||||
|
||||
lockdep_assert_held_write(&card->controls_rwsem);
|
||||
|
||||
id = kcontrol->id;
|
||||
if (id.index > UINT_MAX - kcontrol->count)
|
||||
return -EINVAL;
|
||||
|
||||
old = snd_ctl_find_id(card, &id);
|
||||
old = snd_ctl_find_id_locked(card, &id);
|
||||
if (!old) {
|
||||
if (mode == CTL_REPLACE)
|
||||
return -EINVAL;
|
||||
@ -483,7 +488,7 @@ static int __snd_ctl_add_replace(struct snd_card *card,
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
err = snd_ctl_remove(card, old);
|
||||
err = snd_ctl_remove_locked(card, old);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
@ -575,6 +580,8 @@ static int __snd_ctl_remove(struct snd_card *card,
|
||||
{
|
||||
unsigned int idx;
|
||||
|
||||
lockdep_assert_held_write(&card->controls_rwsem);
|
||||
|
||||
if (snd_BUG_ON(!card || !kcontrol))
|
||||
return -EINVAL;
|
||||
list_del(&kcontrol->list);
|
||||
@ -589,20 +596,32 @@ static int __snd_ctl_remove(struct snd_card *card,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int snd_ctl_remove_locked(struct snd_card *card,
|
||||
struct snd_kcontrol *kcontrol)
|
||||
{
|
||||
return __snd_ctl_remove(card, kcontrol, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_ctl_remove - remove the control from the card and release it
|
||||
* @card: the card instance
|
||||
* @kcontrol: the control instance to remove
|
||||
*
|
||||
* Removes the control from the card and then releases the instance.
|
||||
* You don't need to call snd_ctl_free_one(). You must be in
|
||||
* the write lock - down_write(&card->controls_rwsem).
|
||||
* You don't need to call snd_ctl_free_one().
|
||||
*
|
||||
* Return: 0 if successful, or a negative error code on failure.
|
||||
*
|
||||
* Note that this function takes card->controls_rwsem lock internally.
|
||||
*/
|
||||
int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol)
|
||||
{
|
||||
return __snd_ctl_remove(card, kcontrol, true);
|
||||
int ret;
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
ret = snd_ctl_remove_locked(card, kcontrol);
|
||||
up_write(&card->controls_rwsem);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_ctl_remove);
|
||||
|
||||
@ -622,12 +641,12 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
|
||||
int ret;
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, id);
|
||||
kctl = snd_ctl_find_id_locked(card, id);
|
||||
if (kctl == NULL) {
|
||||
up_write(&card->controls_rwsem);
|
||||
return -ENOENT;
|
||||
}
|
||||
ret = snd_ctl_remove(card, kctl);
|
||||
ret = snd_ctl_remove_locked(card, kctl);
|
||||
up_write(&card->controls_rwsem);
|
||||
return ret;
|
||||
}
|
||||
@ -651,7 +670,7 @@ static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
|
||||
int idx, ret;
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, id);
|
||||
kctl = snd_ctl_find_id_locked(card, id);
|
||||
if (kctl == NULL) {
|
||||
ret = -ENOENT;
|
||||
goto error;
|
||||
@ -665,7 +684,7 @@ static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
|
||||
ret = -EBUSY;
|
||||
goto error;
|
||||
}
|
||||
ret = snd_ctl_remove(card, kctl);
|
||||
ret = snd_ctl_remove_locked(card, kctl);
|
||||
error:
|
||||
up_write(&card->controls_rwsem);
|
||||
return ret;
|
||||
@ -692,7 +711,7 @@ int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
|
||||
int ret;
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, id);
|
||||
kctl = snd_ctl_find_id_locked(card, id);
|
||||
if (kctl == NULL) {
|
||||
ret = -ENOENT;
|
||||
goto unlock;
|
||||
@ -746,7 +765,7 @@ int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id,
|
||||
int saved_numid;
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, src_id);
|
||||
kctl = snd_ctl_find_id_locked(card, src_id);
|
||||
if (kctl == NULL) {
|
||||
up_write(&card->controls_rwsem);
|
||||
return -ENOENT;
|
||||
@ -769,11 +788,12 @@ EXPORT_SYMBOL(snd_ctl_rename_id);
|
||||
*
|
||||
* Renames the specified control on the card to the new name.
|
||||
*
|
||||
* Make sure to take the control write lock - down_write(&card->controls_rwsem).
|
||||
* Note that this function takes card->controls_rwsem lock internally.
|
||||
*/
|
||||
void snd_ctl_rename(struct snd_card *card, struct snd_kcontrol *kctl,
|
||||
const char *name)
|
||||
{
|
||||
down_write(&card->controls_rwsem);
|
||||
remove_hash_entries(card, kctl);
|
||||
|
||||
if (strscpy(kctl->id.name, name, sizeof(kctl->id.name)) < 0)
|
||||
@ -781,6 +801,7 @@ void snd_ctl_rename(struct snd_card *card, struct snd_kcontrol *kctl,
|
||||
name, kctl->id.name);
|
||||
|
||||
add_hash_entries(card, kctl);
|
||||
up_write(&card->controls_rwsem);
|
||||
}
|
||||
EXPORT_SYMBOL(snd_ctl_rename);
|
||||
|
||||
@ -799,7 +820,7 @@ snd_ctl_find_numid_slow(struct snd_card *card, unsigned int numid)
|
||||
#endif /* !CONFIG_SND_CTL_FAST_LOOKUP */
|
||||
|
||||
/**
|
||||
* snd_ctl_find_numid - find the control instance with the given number-id
|
||||
* snd_ctl_find_numid_locked - find the control instance with the given number-id
|
||||
* @card: the card instance
|
||||
* @numid: the number-id to search
|
||||
*
|
||||
@ -809,22 +830,46 @@ snd_ctl_find_numid_slow(struct snd_card *card, unsigned int numid)
|
||||
* (if the race condition can happen).
|
||||
*
|
||||
* Return: The pointer of the instance if found, or %NULL if not.
|
||||
*
|
||||
*/
|
||||
struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid)
|
||||
struct snd_kcontrol *
|
||||
snd_ctl_find_numid_locked(struct snd_card *card, unsigned int numid)
|
||||
{
|
||||
if (snd_BUG_ON(!card || !numid))
|
||||
return NULL;
|
||||
lockdep_assert_held(&card->controls_rwsem);
|
||||
#ifdef CONFIG_SND_CTL_FAST_LOOKUP
|
||||
return xa_load(&card->ctl_numids, numid);
|
||||
#else
|
||||
return snd_ctl_find_numid_slow(card, numid);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(snd_ctl_find_numid_locked);
|
||||
|
||||
/**
|
||||
* snd_ctl_find_numid - find the control instance with the given number-id
|
||||
* @card: the card instance
|
||||
* @numid: the number-id to search
|
||||
*
|
||||
* Finds the control instance with the given number-id from the card.
|
||||
*
|
||||
* Return: The pointer of the instance if found, or %NULL if not.
|
||||
*
|
||||
* Note that this function takes card->controls_rwsem lock internally.
|
||||
*/
|
||||
struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card,
|
||||
unsigned int numid)
|
||||
{
|
||||
struct snd_kcontrol *kctl;
|
||||
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_numid_locked(card, numid);
|
||||
up_read(&card->controls_rwsem);
|
||||
return kctl;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_ctl_find_numid);
|
||||
|
||||
/**
|
||||
* snd_ctl_find_id - find the control instance with the given id
|
||||
* snd_ctl_find_id_locked - find the control instance with the given id
|
||||
* @card: the card instance
|
||||
* @id: the id to search
|
||||
*
|
||||
@ -834,17 +879,17 @@ EXPORT_SYMBOL(snd_ctl_find_numid);
|
||||
* (if the race condition can happen).
|
||||
*
|
||||
* Return: The pointer of the instance if found, or %NULL if not.
|
||||
*
|
||||
*/
|
||||
struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
|
||||
struct snd_ctl_elem_id *id)
|
||||
struct snd_kcontrol *snd_ctl_find_id_locked(struct snd_card *card,
|
||||
const struct snd_ctl_elem_id *id)
|
||||
{
|
||||
struct snd_kcontrol *kctl;
|
||||
|
||||
if (snd_BUG_ON(!card || !id))
|
||||
return NULL;
|
||||
lockdep_assert_held(&card->controls_rwsem);
|
||||
if (id->numid != 0)
|
||||
return snd_ctl_find_numid(card, id->numid);
|
||||
return snd_ctl_find_numid_locked(card, id->numid);
|
||||
#ifdef CONFIG_SND_CTL_FAST_LOOKUP
|
||||
kctl = xa_load(&card->ctl_hash, get_ctl_id_hash(id));
|
||||
if (kctl && elem_id_matches(kctl, id))
|
||||
@ -859,6 +904,29 @@ struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_ctl_find_id_locked);
|
||||
|
||||
/**
|
||||
* snd_ctl_find_id - find the control instance with the given id
|
||||
* @card: the card instance
|
||||
* @id: the id to search
|
||||
*
|
||||
* Finds the control instance with the given id from the card.
|
||||
*
|
||||
* Return: The pointer of the instance if found, or %NULL if not.
|
||||
*
|
||||
* Note that this function takes card->controls_rwsem lock internally.
|
||||
*/
|
||||
struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
|
||||
const struct snd_ctl_elem_id *id)
|
||||
{
|
||||
struct snd_kcontrol *kctl;
|
||||
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id_locked(card, id);
|
||||
up_read(&card->controls_rwsem);
|
||||
return kctl;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_ctl_find_id);
|
||||
|
||||
static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
|
||||
@ -1173,7 +1241,7 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
|
||||
int result;
|
||||
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, &info->id);
|
||||
kctl = snd_ctl_find_id_locked(card, &info->id);
|
||||
if (kctl == NULL)
|
||||
result = -ENOENT;
|
||||
else
|
||||
@ -1212,7 +1280,7 @@ static int snd_ctl_elem_read(struct snd_card *card,
|
||||
int ret;
|
||||
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, &control->id);
|
||||
kctl = snd_ctl_find_id_locked(card, &control->id);
|
||||
if (kctl == NULL) {
|
||||
ret = -ENOENT;
|
||||
goto unlock;
|
||||
@ -1289,7 +1357,7 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
|
||||
int result;
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, &control->id);
|
||||
kctl = snd_ctl_find_id_locked(card, &control->id);
|
||||
if (kctl == NULL) {
|
||||
up_write(&card->controls_rwsem);
|
||||
return -ENOENT;
|
||||
@ -1370,7 +1438,7 @@ static int snd_ctl_elem_lock(struct snd_ctl_file *file,
|
||||
if (copy_from_user(&id, _id, sizeof(id)))
|
||||
return -EFAULT;
|
||||
down_write(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, &id);
|
||||
kctl = snd_ctl_find_id_locked(card, &id);
|
||||
if (kctl == NULL) {
|
||||
result = -ENOENT;
|
||||
} else {
|
||||
@ -1398,7 +1466,7 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file,
|
||||
if (copy_from_user(&id, _id, sizeof(id)))
|
||||
return -EFAULT;
|
||||
down_write(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, &id);
|
||||
kctl = snd_ctl_find_id_locked(card, &id);
|
||||
if (kctl == NULL) {
|
||||
result = -ENOENT;
|
||||
} else {
|
||||
@ -1507,6 +1575,8 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
|
||||
int i;
|
||||
int change;
|
||||
|
||||
lockdep_assert_held_write(&ue->card->controls_rwsem);
|
||||
|
||||
if (size > 1024 * 128) /* sane value */
|
||||
return -EINVAL;
|
||||
|
||||
@ -1583,6 +1653,8 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
|
||||
unsigned int i;
|
||||
const uintptr_t user_ptrval = ue->info.value.enumerated.names_ptr;
|
||||
|
||||
lockdep_assert_held_write(&ue->card->controls_rwsem);
|
||||
|
||||
buf_len = ue->info.value.enumerated.names_length;
|
||||
if (buf_len > 64 * 1024)
|
||||
return -EINVAL;
|
||||
@ -1887,6 +1959,8 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
|
||||
struct snd_ctl_elem_id id;
|
||||
struct snd_kcontrol_volatile *vd;
|
||||
|
||||
lockdep_assert_held(&file->card->controls_rwsem);
|
||||
|
||||
if (copy_from_user(&header, buf, sizeof(header)))
|
||||
return -EFAULT;
|
||||
|
||||
@ -1900,7 +1974,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
|
||||
container_size = header.length;
|
||||
container = buf->tlv;
|
||||
|
||||
kctl = snd_ctl_find_numid(file->card, header.numid);
|
||||
kctl = snd_ctl_find_numid_locked(file->card, header.numid);
|
||||
if (kctl == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
@ -2315,7 +2389,7 @@ static int snd_ctl_dev_register(struct snd_device *device)
|
||||
int err;
|
||||
|
||||
err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
|
||||
&snd_ctl_f_ops, card, &card->ctl_dev);
|
||||
&snd_ctl_f_ops, card, card->ctl_dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
down_read(&card->controls_rwsem);
|
||||
@ -2351,7 +2425,7 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
|
||||
up_read(&snd_ctl_layer_rwsem);
|
||||
up_read(&card->controls_rwsem);
|
||||
|
||||
return snd_unregister_device(&card->ctl_dev);
|
||||
return snd_unregister_device(card->ctl_dev);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2373,7 +2447,7 @@ static int snd_ctl_dev_free(struct snd_device *device)
|
||||
xa_destroy(&card->ctl_hash);
|
||||
#endif
|
||||
up_write(&card->controls_rwsem);
|
||||
put_device(&card->ctl_dev);
|
||||
put_device(card->ctl_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2395,12 +2469,14 @@ int snd_ctl_create(struct snd_card *card)
|
||||
if (snd_BUG_ON(card->number < 0 || card->number >= SNDRV_CARDS))
|
||||
return -ENXIO;
|
||||
|
||||
snd_device_initialize(&card->ctl_dev, card);
|
||||
dev_set_name(&card->ctl_dev, "controlC%d", card->number);
|
||||
err = snd_device_alloc(&card->ctl_dev, card);
|
||||
if (err < 0)
|
||||
return err;
|
||||
dev_set_name(card->ctl_dev, "controlC%d", card->number);
|
||||
|
||||
err = snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);
|
||||
if (err < 0)
|
||||
put_device(&card->ctl_dev);
|
||||
put_device(card->ctl_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,7 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
|
||||
int err;
|
||||
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, id);
|
||||
kctl = snd_ctl_find_id_locked(card, id);
|
||||
if (! kctl) {
|
||||
up_read(&card->controls_rwsem);
|
||||
return -ENOENT;
|
||||
|
@ -251,7 +251,7 @@ static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id,
|
||||
card = snd_card_ref(card_number);
|
||||
if (card) {
|
||||
down_write(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, id);
|
||||
kctl = snd_ctl_find_id_locked(card, id);
|
||||
if (kctl) {
|
||||
ioff = snd_ctl_get_ioff(kctl, id);
|
||||
vd = &kctl->vd[ioff];
|
||||
@ -688,7 +688,7 @@ static void snd_ctl_led_sysfs_add(struct snd_card *card)
|
||||
goto cerr;
|
||||
led->cards[card->number] = led_card;
|
||||
snprintf(link_name, sizeof(link_name), "led-%s", led->name);
|
||||
WARN(sysfs_create_link(&card->ctl_dev.kobj, &led_card->dev.kobj, link_name),
|
||||
WARN(sysfs_create_link(&card->ctl_dev->kobj, &led_card->dev.kobj, link_name),
|
||||
"can't create symlink to controlC%i device\n", card->number);
|
||||
WARN(sysfs_create_link(&led_card->dev.kobj, &card->card_dev.kobj, "card"),
|
||||
"can't create symlink to card%i\n", card->number);
|
||||
@ -714,7 +714,7 @@ static void snd_ctl_led_sysfs_remove(struct snd_card *card)
|
||||
if (!led_card)
|
||||
continue;
|
||||
snprintf(link_name, sizeof(link_name), "led-%s", led->name);
|
||||
sysfs_remove_link(&card->ctl_dev.kobj, link_name);
|
||||
sysfs_remove_link(&card->ctl_dev->kobj, link_name);
|
||||
sysfs_remove_link(&led_card->dev.kobj, "card");
|
||||
device_unregister(&led_card->dev);
|
||||
led->cards[card->number] = NULL;
|
||||
|
@ -338,9 +338,14 @@ static const struct file_operations snd_hwdep_f_ops =
|
||||
.mmap = snd_hwdep_mmap,
|
||||
};
|
||||
|
||||
static void release_hwdep_device(struct device *dev)
|
||||
static void snd_hwdep_free(struct snd_hwdep *hwdep)
|
||||
{
|
||||
kfree(container_of(dev, struct snd_hwdep, dev));
|
||||
if (!hwdep)
|
||||
return;
|
||||
if (hwdep->private_free)
|
||||
hwdep->private_free(hwdep);
|
||||
put_device(hwdep->dev);
|
||||
kfree(hwdep);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -382,16 +387,20 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device,
|
||||
if (id)
|
||||
strscpy(hwdep->id, id, sizeof(hwdep->id));
|
||||
|
||||
snd_device_initialize(&hwdep->dev, card);
|
||||
hwdep->dev.release = release_hwdep_device;
|
||||
dev_set_name(&hwdep->dev, "hwC%iD%i", card->number, device);
|
||||
err = snd_device_alloc(&hwdep->dev, card);
|
||||
if (err < 0) {
|
||||
snd_hwdep_free(hwdep);
|
||||
return err;
|
||||
}
|
||||
|
||||
dev_set_name(hwdep->dev, "hwC%iD%i", card->number, device);
|
||||
#ifdef CONFIG_SND_OSSEMUL
|
||||
hwdep->oss_type = -1;
|
||||
#endif
|
||||
|
||||
err = snd_device_new(card, SNDRV_DEV_HWDEP, hwdep, &ops);
|
||||
if (err < 0) {
|
||||
put_device(&hwdep->dev);
|
||||
snd_hwdep_free(hwdep);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -403,12 +412,7 @@ EXPORT_SYMBOL(snd_hwdep_new);
|
||||
|
||||
static int snd_hwdep_dev_free(struct snd_device *device)
|
||||
{
|
||||
struct snd_hwdep *hwdep = device->device_data;
|
||||
if (!hwdep)
|
||||
return 0;
|
||||
if (hwdep->private_free)
|
||||
hwdep->private_free(hwdep);
|
||||
put_device(&hwdep->dev);
|
||||
snd_hwdep_free(device->device_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -426,9 +430,9 @@ static int snd_hwdep_dev_register(struct snd_device *device)
|
||||
list_add_tail(&hwdep->list, &snd_hwdep_devices);
|
||||
err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP,
|
||||
hwdep->card, hwdep->device,
|
||||
&snd_hwdep_f_ops, hwdep, &hwdep->dev);
|
||||
&snd_hwdep_f_ops, hwdep, hwdep->dev);
|
||||
if (err < 0) {
|
||||
dev_err(&hwdep->dev, "unable to register\n");
|
||||
dev_err(hwdep->dev, "unable to register\n");
|
||||
list_del(&hwdep->list);
|
||||
mutex_unlock(®ister_mutex);
|
||||
return err;
|
||||
@ -439,12 +443,12 @@ static int snd_hwdep_dev_register(struct snd_device *device)
|
||||
if (hwdep->oss_type >= 0) {
|
||||
if (hwdep->oss_type == SNDRV_OSS_DEVICE_TYPE_DMFM &&
|
||||
hwdep->device)
|
||||
dev_warn(&hwdep->dev,
|
||||
dev_warn(hwdep->dev,
|
||||
"only hwdep device 0 can be registered as OSS direct FM device!\n");
|
||||
else if (snd_register_oss_device(hwdep->oss_type,
|
||||
card, hwdep->device,
|
||||
&snd_hwdep_f_ops, hwdep) < 0)
|
||||
dev_warn(&hwdep->dev,
|
||||
dev_warn(hwdep->dev,
|
||||
"unable to register OSS compatibility device\n");
|
||||
else
|
||||
hwdep->ossreg = 1;
|
||||
@ -471,7 +475,7 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device)
|
||||
if (hwdep->ossreg)
|
||||
snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);
|
||||
#endif
|
||||
snd_unregister_device(&hwdep->dev);
|
||||
snd_unregister_device(hwdep->dev);
|
||||
list_del_init(&hwdep->list);
|
||||
mutex_unlock(&hwdep->open_mutex);
|
||||
mutex_unlock(®ister_mutex);
|
||||
|
@ -111,28 +111,36 @@ static int get_slot_from_bitmask(int mask, int (*check)(struct module *, int),
|
||||
return mask; /* unchanged */
|
||||
}
|
||||
|
||||
/* the default release callback set in snd_device_initialize() below;
|
||||
* this is just NOP for now, as almost all jobs are already done in
|
||||
* dev_free callback of snd_device chain instead.
|
||||
*/
|
||||
static void default_release(struct device *dev)
|
||||
/* the default release callback set in snd_device_alloc() */
|
||||
static void default_release_alloc(struct device *dev)
|
||||
{
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_device_initialize - Initialize struct device for sound devices
|
||||
* @dev: device to initialize
|
||||
* snd_device_alloc - Allocate and initialize struct device for sound devices
|
||||
* @dev_p: pointer to store the allocated device
|
||||
* @card: card to assign, optional
|
||||
*
|
||||
* For releasing the allocated device, call put_device().
|
||||
*/
|
||||
void snd_device_initialize(struct device *dev, struct snd_card *card)
|
||||
int snd_device_alloc(struct device **dev_p, struct snd_card *card)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
*dev_p = NULL;
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
device_initialize(dev);
|
||||
if (card)
|
||||
dev->parent = &card->card_dev;
|
||||
dev->class = &sound_class;
|
||||
dev->release = default_release;
|
||||
dev->release = default_release_alloc;
|
||||
*dev_p = dev;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_device_initialize);
|
||||
EXPORT_SYMBOL_GPL(snd_device_alloc);
|
||||
|
||||
static int snd_card_init(struct snd_card *card, struct device *parent,
|
||||
int idx, const char *xid, struct module *module,
|
||||
|
@ -66,12 +66,10 @@ static int snd_jack_dev_free(struct snd_device *device)
|
||||
struct snd_card *card = device->card;
|
||||
struct snd_jack_kctl *jack_kctl, *tmp_jack_kctl;
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
list_for_each_entry_safe(jack_kctl, tmp_jack_kctl, &jack->kctl_list, list) {
|
||||
list_del_init(&jack_kctl->list);
|
||||
snd_ctl_remove(card, jack_kctl->kctl);
|
||||
}
|
||||
up_write(&card->controls_rwsem);
|
||||
|
||||
if (jack->private_free)
|
||||
jack->private_free(jack);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
||||
/**
|
||||
* copy_to_user_fromio - copy data from mmio-space to user-space
|
||||
@ -21,9 +22,30 @@
|
||||
* Return: Zero if successful, or non-zero on failure.
|
||||
*/
|
||||
int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count)
|
||||
{
|
||||
struct iov_iter iter;
|
||||
|
||||
if (import_ubuf(ITER_DEST, dst, count, &iter))
|
||||
return -EFAULT;
|
||||
return copy_to_iter_fromio(&iter, (const void __iomem *)src, count);
|
||||
}
|
||||
EXPORT_SYMBOL(copy_to_user_fromio);
|
||||
|
||||
/**
|
||||
* copy_to_iter_fromio - copy data from mmio-space to iov_iter
|
||||
* @dst: the destination iov_iter
|
||||
* @src: the source pointer on mmio
|
||||
* @count: the data size to copy in bytes
|
||||
*
|
||||
* Copies the data from mmio-space to iov_iter.
|
||||
*
|
||||
* Return: Zero if successful, or non-zero on failure.
|
||||
*/
|
||||
int copy_to_iter_fromio(struct iov_iter *dst, const void __iomem *src,
|
||||
size_t count)
|
||||
{
|
||||
#if defined(__i386__) || defined(CONFIG_SPARC32)
|
||||
return copy_to_user(dst, (const void __force*)src, count) ? -EFAULT : 0;
|
||||
return copy_to_iter((const void __force *)src, count, dst) == count ? 0 : -EFAULT;
|
||||
#else
|
||||
char buf[256];
|
||||
while (count) {
|
||||
@ -31,16 +53,15 @@ int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size
|
||||
if (c > sizeof(buf))
|
||||
c = sizeof(buf);
|
||||
memcpy_fromio(buf, (void __iomem *)src, c);
|
||||
if (copy_to_user(dst, buf, c))
|
||||
if (copy_to_iter(buf, c, dst) != c)
|
||||
return -EFAULT;
|
||||
count -= c;
|
||||
dst += c;
|
||||
src += c;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(copy_to_user_fromio);
|
||||
EXPORT_SYMBOL(copy_to_iter_fromio);
|
||||
|
||||
/**
|
||||
* copy_from_user_toio - copy data from user-space to mmio-space
|
||||
@ -53,23 +74,42 @@ EXPORT_SYMBOL(copy_to_user_fromio);
|
||||
* Return: Zero if successful, or non-zero on failure.
|
||||
*/
|
||||
int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count)
|
||||
{
|
||||
struct iov_iter iter;
|
||||
|
||||
if (import_ubuf(ITER_SOURCE, (void __user *)src, count, &iter))
|
||||
return -EFAULT;
|
||||
return copy_from_iter_toio((void __iomem *)dst, &iter, count);
|
||||
}
|
||||
EXPORT_SYMBOL(copy_from_user_toio);
|
||||
|
||||
/**
|
||||
* copy_from_iter_toio - copy data from iov_iter to mmio-space
|
||||
* @dst: the destination pointer on mmio-space
|
||||
* @src: the source iov_iter
|
||||
* @count: the data size to copy in bytes
|
||||
*
|
||||
* Copies the data from iov_iter to mmio-space.
|
||||
*
|
||||
* Return: Zero if successful, or non-zero on failure.
|
||||
*/
|
||||
int copy_from_iter_toio(void __iomem *dst, struct iov_iter *src, size_t count)
|
||||
{
|
||||
#if defined(__i386__) || defined(CONFIG_SPARC32)
|
||||
return copy_from_user((void __force *)dst, src, count) ? -EFAULT : 0;
|
||||
return copy_from_iter((void __force *)dst, count, src) == count ? 0 : -EFAULT;
|
||||
#else
|
||||
char buf[256];
|
||||
while (count) {
|
||||
size_t c = count;
|
||||
if (c > sizeof(buf))
|
||||
c = sizeof(buf);
|
||||
if (copy_from_user(buf, src, c))
|
||||
if (copy_from_iter(buf, c, src) != c)
|
||||
return -EFAULT;
|
||||
memcpy_toio(dst, buf, c);
|
||||
count -= c;
|
||||
dst += c;
|
||||
src += c;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(copy_from_user_toio);
|
||||
EXPORT_SYMBOL(copy_from_iter_toio);
|
||||
|
@ -524,7 +524,7 @@ static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, c
|
||||
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strscpy(id.name, name, sizeof(id.name));
|
||||
id.index = index;
|
||||
return snd_ctl_find_id(card, &id);
|
||||
return snd_ctl_find_id_locked(card, &id);
|
||||
}
|
||||
|
||||
static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
|
||||
@ -540,7 +540,7 @@ static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
|
||||
if (numid == ID_UNKNOWN)
|
||||
return;
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_numid(card, numid);
|
||||
kctl = snd_ctl_find_numid_locked(card, numid);
|
||||
if (!kctl) {
|
||||
up_read(&card->controls_rwsem);
|
||||
return;
|
||||
@ -579,7 +579,7 @@ static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer,
|
||||
if (numid == ID_UNKNOWN)
|
||||
return;
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_numid(card, numid);
|
||||
kctl = snd_ctl_find_numid_locked(card, numid);
|
||||
if (!kctl) {
|
||||
up_read(&card->controls_rwsem);
|
||||
return;
|
||||
@ -645,7 +645,7 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
|
||||
if (numid == ID_UNKNOWN)
|
||||
return;
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_numid(card, numid);
|
||||
kctl = snd_ctl_find_numid_locked(card, numid);
|
||||
if (!kctl) {
|
||||
up_read(&card->controls_rwsem);
|
||||
return;
|
||||
@ -688,7 +688,7 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
|
||||
if (numid == ID_UNKNOWN)
|
||||
return;
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_numid(card, numid);
|
||||
kctl = snd_ctl_find_numid_locked(card, numid);
|
||||
if (!kctl) {
|
||||
up_read(&card->controls_rwsem);
|
||||
return;
|
||||
|
@ -604,7 +604,7 @@ static const struct attribute_group *pcm_dev_attr_groups[];
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int do_pcm_suspend(struct device *dev)
|
||||
{
|
||||
struct snd_pcm_str *pstr = container_of(dev, struct snd_pcm_str, dev);
|
||||
struct snd_pcm_str *pstr = dev_get_drvdata(dev);
|
||||
|
||||
if (!pstr->pcm->no_device_suspend)
|
||||
snd_pcm_suspend_all(pstr->pcm);
|
||||
@ -650,11 +650,14 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
|
||||
if (!substream_count)
|
||||
return 0;
|
||||
|
||||
snd_device_initialize(&pstr->dev, pcm->card);
|
||||
pstr->dev.groups = pcm_dev_attr_groups;
|
||||
pstr->dev.type = &pcm_dev_type;
|
||||
dev_set_name(&pstr->dev, "pcmC%iD%i%c", pcm->card->number, pcm->device,
|
||||
err = snd_device_alloc(&pstr->dev, pcm->card);
|
||||
if (err < 0)
|
||||
return err;
|
||||
dev_set_name(pstr->dev, "pcmC%iD%i%c", pcm->card->number, pcm->device,
|
||||
stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c');
|
||||
pstr->dev->groups = pcm_dev_attr_groups;
|
||||
pstr->dev->type = &pcm_dev_type;
|
||||
dev_set_drvdata(pstr->dev, pstr);
|
||||
|
||||
if (!pcm->internal) {
|
||||
err = snd_pcm_stream_proc_init(pstr);
|
||||
@ -814,9 +817,7 @@ static void free_chmap(struct snd_pcm_str *pstr)
|
||||
if (pstr->chmap_kctl) {
|
||||
struct snd_card *card = pstr->pcm->card;
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
snd_ctl_remove(card, pstr->chmap_kctl);
|
||||
up_write(&card->controls_rwsem);
|
||||
pstr->chmap_kctl = NULL;
|
||||
}
|
||||
}
|
||||
@ -847,7 +848,7 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
|
||||
#endif
|
||||
free_chmap(pstr);
|
||||
if (pstr->substream_count)
|
||||
put_device(&pstr->dev);
|
||||
put_device(pstr->dev);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
|
||||
@ -1017,7 +1018,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
|
||||
static ssize_t pcm_class_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct snd_pcm_str *pstr = container_of(dev, struct snd_pcm_str, dev);
|
||||
struct snd_pcm_str *pstr = dev_get_drvdata(dev);
|
||||
struct snd_pcm *pcm = pstr->pcm;
|
||||
const char *str;
|
||||
static const char *strs[SNDRV_PCM_CLASS_LAST + 1] = {
|
||||
@ -1078,7 +1079,7 @@ static int snd_pcm_dev_register(struct snd_device *device)
|
||||
/* register pcm */
|
||||
err = snd_register_device(devtype, pcm->card, pcm->device,
|
||||
&snd_pcm_f_ops[cidx], pcm,
|
||||
&pcm->streams[cidx].dev);
|
||||
pcm->streams[cidx].dev);
|
||||
if (err < 0) {
|
||||
list_del_init(&pcm->list);
|
||||
goto unlock;
|
||||
@ -1125,7 +1126,8 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
|
||||
|
||||
pcm_call_notify(pcm, n_disconnect);
|
||||
for (cidx = 0; cidx < 2; cidx++) {
|
||||
snd_unregister_device(&pcm->streams[cidx].dev);
|
||||
if (pcm->streams[cidx].dev)
|
||||
snd_unregister_device(pcm->streams[cidx].dev);
|
||||
free_chmap(&pcm->streams[cidx]);
|
||||
}
|
||||
mutex_unlock(&pcm->open_mutex);
|
||||
|
@ -1973,10 +1973,11 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
|
||||
|
||||
typedef int (*pcm_transfer_f)(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long hwoff,
|
||||
void *buf, unsigned long bytes);
|
||||
struct iov_iter *iter, unsigned long bytes);
|
||||
|
||||
typedef int (*pcm_copy_f)(struct snd_pcm_substream *, snd_pcm_uframes_t, void *,
|
||||
snd_pcm_uframes_t, snd_pcm_uframes_t, pcm_transfer_f);
|
||||
snd_pcm_uframes_t, snd_pcm_uframes_t, pcm_transfer_f,
|
||||
bool);
|
||||
|
||||
/* calculate the target DMA-buffer position to be written/read */
|
||||
static void *get_dma_ptr(struct snd_pcm_runtime *runtime,
|
||||
@ -1986,32 +1987,24 @@ static void *get_dma_ptr(struct snd_pcm_runtime *runtime,
|
||||
channel * (runtime->dma_bytes / runtime->channels);
|
||||
}
|
||||
|
||||
/* default copy_user ops for write; used for both interleaved and non- modes */
|
||||
/* default copy ops for write; used for both interleaved and non- modes */
|
||||
static int default_write_copy(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long hwoff,
|
||||
void *buf, unsigned long bytes)
|
||||
struct iov_iter *iter, unsigned long bytes)
|
||||
{
|
||||
if (copy_from_user(get_dma_ptr(substream->runtime, channel, hwoff),
|
||||
(void __user *)buf, bytes))
|
||||
if (!copy_from_iter(get_dma_ptr(substream->runtime, channel, hwoff),
|
||||
bytes, iter))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* default copy_kernel ops for write */
|
||||
static int default_write_copy_kernel(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long hwoff,
|
||||
void *buf, unsigned long bytes)
|
||||
{
|
||||
memcpy(get_dma_ptr(substream->runtime, channel, hwoff), buf, bytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fill silence instead of copy data; called as a transfer helper
|
||||
* from __snd_pcm_lib_write() or directly from noninterleaved_copy() when
|
||||
* a NULL buffer is passed
|
||||
*/
|
||||
static int fill_silence(struct snd_pcm_substream *substream, int channel,
|
||||
unsigned long hwoff, void *buf, unsigned long bytes)
|
||||
unsigned long hwoff, struct iov_iter *iter,
|
||||
unsigned long bytes)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
|
||||
@ -2027,25 +2020,41 @@ static int fill_silence(struct snd_pcm_substream *substream, int channel,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* default copy_user ops for read; used for both interleaved and non- modes */
|
||||
/* default copy ops for read; used for both interleaved and non- modes */
|
||||
static int default_read_copy(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long hwoff,
|
||||
void *buf, unsigned long bytes)
|
||||
struct iov_iter *iter, unsigned long bytes)
|
||||
{
|
||||
if (copy_to_user((void __user *)buf,
|
||||
get_dma_ptr(substream->runtime, channel, hwoff),
|
||||
bytes))
|
||||
if (!copy_to_iter(get_dma_ptr(substream->runtime, channel, hwoff),
|
||||
bytes, iter))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* default copy_kernel ops for read */
|
||||
static int default_read_copy_kernel(struct snd_pcm_substream *substream,
|
||||
int channel, unsigned long hwoff,
|
||||
void *buf, unsigned long bytes)
|
||||
/* call transfer with the filled iov_iter */
|
||||
static int do_transfer(struct snd_pcm_substream *substream, int c,
|
||||
unsigned long hwoff, void *data, unsigned long bytes,
|
||||
pcm_transfer_f transfer, bool in_kernel)
|
||||
{
|
||||
memcpy(buf, get_dma_ptr(substream->runtime, channel, hwoff), bytes);
|
||||
return 0;
|
||||
struct iov_iter iter;
|
||||
int err, type;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
type = ITER_SOURCE;
|
||||
else
|
||||
type = ITER_DEST;
|
||||
|
||||
if (in_kernel) {
|
||||
struct kvec kvec = { data, bytes };
|
||||
|
||||
iov_iter_kvec(&iter, type, &kvec, 1, bytes);
|
||||
return transfer(substream, c, hwoff, &iter, bytes);
|
||||
}
|
||||
|
||||
err = import_ubuf(type, (__force void __user *)data, bytes, &iter);
|
||||
if (err)
|
||||
return err;
|
||||
return transfer(substream, c, hwoff, &iter, bytes);
|
||||
}
|
||||
|
||||
/* call transfer function with the converted pointers and sizes;
|
||||
@ -2055,7 +2064,8 @@ static int interleaved_copy(struct snd_pcm_substream *substream,
|
||||
snd_pcm_uframes_t hwoff, void *data,
|
||||
snd_pcm_uframes_t off,
|
||||
snd_pcm_uframes_t frames,
|
||||
pcm_transfer_f transfer)
|
||||
pcm_transfer_f transfer,
|
||||
bool in_kernel)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
|
||||
@ -2063,7 +2073,9 @@ static int interleaved_copy(struct snd_pcm_substream *substream,
|
||||
hwoff = frames_to_bytes(runtime, hwoff);
|
||||
off = frames_to_bytes(runtime, off);
|
||||
frames = frames_to_bytes(runtime, frames);
|
||||
return transfer(substream, 0, hwoff, data + off, frames);
|
||||
|
||||
return do_transfer(substream, 0, hwoff, data + off, frames, transfer,
|
||||
in_kernel);
|
||||
}
|
||||
|
||||
/* call transfer function with the converted pointers and sizes for each
|
||||
@ -2073,7 +2085,8 @@ static int noninterleaved_copy(struct snd_pcm_substream *substream,
|
||||
snd_pcm_uframes_t hwoff, void *data,
|
||||
snd_pcm_uframes_t off,
|
||||
snd_pcm_uframes_t frames,
|
||||
pcm_transfer_f transfer)
|
||||
pcm_transfer_f transfer,
|
||||
bool in_kernel)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
int channels = runtime->channels;
|
||||
@ -2091,8 +2104,8 @@ static int noninterleaved_copy(struct snd_pcm_substream *substream,
|
||||
if (!data || !*bufs)
|
||||
err = fill_silence(substream, c, hwoff, NULL, frames);
|
||||
else
|
||||
err = transfer(substream, c, hwoff, *bufs + off,
|
||||
frames);
|
||||
err = do_transfer(substream, c, hwoff, *bufs + off,
|
||||
frames, transfer, in_kernel);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
@ -2108,10 +2121,10 @@ static int fill_silence_frames(struct snd_pcm_substream *substream,
|
||||
if (substream->runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
|
||||
substream->runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED)
|
||||
return interleaved_copy(substream, off, NULL, 0, frames,
|
||||
fill_silence);
|
||||
fill_silence, true);
|
||||
else
|
||||
return noninterleaved_copy(substream, off, NULL, 0, frames,
|
||||
fill_silence);
|
||||
fill_silence, true);
|
||||
}
|
||||
|
||||
/* sanity-check for read/write methods */
|
||||
@ -2121,7 +2134,7 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream)
|
||||
if (PCM_RUNTIME_CHECK(substream))
|
||||
return -ENXIO;
|
||||
runtime = substream->runtime;
|
||||
if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
|
||||
if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area))
|
||||
return -EINVAL;
|
||||
if (runtime->state == SNDRV_PCM_STATE_OPEN)
|
||||
return -EBADFD;
|
||||
@ -2226,15 +2239,9 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
|
||||
transfer = fill_silence;
|
||||
else
|
||||
return -EINVAL;
|
||||
} else if (in_kernel) {
|
||||
if (substream->ops->copy_kernel)
|
||||
transfer = substream->ops->copy_kernel;
|
||||
else
|
||||
transfer = is_playback ?
|
||||
default_write_copy_kernel : default_read_copy_kernel;
|
||||
} else {
|
||||
if (substream->ops->copy_user)
|
||||
transfer = (pcm_transfer_f)substream->ops->copy_user;
|
||||
if (substream->ops->copy)
|
||||
transfer = substream->ops->copy;
|
||||
else
|
||||
transfer = is_playback ?
|
||||
default_write_copy : default_read_copy;
|
||||
@ -2307,7 +2314,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
|
||||
if (!is_playback)
|
||||
snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_CPU);
|
||||
err = writer(substream, appl_ofs, data, offset, frames,
|
||||
transfer);
|
||||
transfer, in_kernel);
|
||||
if (is_playback)
|
||||
snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
|
@ -809,7 +809,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
runtime->boundary *= 2;
|
||||
|
||||
/* clear the buffer for avoiding possible kernel info leaks */
|
||||
if (runtime->dma_area && !substream->ops->copy_user) {
|
||||
if (runtime->dma_area && !substream->ops->copy) {
|
||||
size_t size = runtime->dma_bytes;
|
||||
|
||||
if (runtime->info & SNDRV_PCM_INFO_MMAP)
|
||||
|
@ -44,11 +44,11 @@ static LIST_HEAD(snd_rawmidi_devices);
|
||||
static DEFINE_MUTEX(register_mutex);
|
||||
|
||||
#define rmidi_err(rmidi, fmt, args...) \
|
||||
dev_err(&(rmidi)->dev, fmt, ##args)
|
||||
dev_err((rmidi)->dev, fmt, ##args)
|
||||
#define rmidi_warn(rmidi, fmt, args...) \
|
||||
dev_warn(&(rmidi)->dev, fmt, ##args)
|
||||
dev_warn((rmidi)->dev, fmt, ##args)
|
||||
#define rmidi_dbg(rmidi, fmt, args...) \
|
||||
dev_dbg(&(rmidi)->dev, fmt, ##args)
|
||||
dev_dbg((rmidi)->dev, fmt, ##args)
|
||||
|
||||
struct snd_rawmidi_status32 {
|
||||
s32 stream;
|
||||
@ -1877,11 +1877,6 @@ static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void release_rawmidi_device(struct device *dev)
|
||||
{
|
||||
kfree(container_of(dev, struct snd_rawmidi, dev));
|
||||
}
|
||||
|
||||
/* used for both rawmidi and ump */
|
||||
int snd_rawmidi_init(struct snd_rawmidi *rmidi,
|
||||
struct snd_card *card, char *id, int device,
|
||||
@ -1906,12 +1901,13 @@ int snd_rawmidi_init(struct snd_rawmidi *rmidi,
|
||||
if (id != NULL)
|
||||
strscpy(rmidi->id, id, sizeof(rmidi->id));
|
||||
|
||||
snd_device_initialize(&rmidi->dev, card);
|
||||
rmidi->dev.release = release_rawmidi_device;
|
||||
err = snd_device_alloc(&rmidi->dev, card);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (rawmidi_is_ump(rmidi))
|
||||
dev_set_name(&rmidi->dev, "umpC%iD%i", card->number, device);
|
||||
dev_set_name(rmidi->dev, "umpC%iD%i", card->number, device);
|
||||
else
|
||||
dev_set_name(&rmidi->dev, "midiC%iD%i", card->number, device);
|
||||
dev_set_name(rmidi->dev, "midiC%iD%i", card->number, device);
|
||||
|
||||
err = snd_rawmidi_alloc_substreams(rmidi,
|
||||
&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT],
|
||||
@ -1996,7 +1992,8 @@ int snd_rawmidi_free(struct snd_rawmidi *rmidi)
|
||||
snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]);
|
||||
if (rmidi->private_free)
|
||||
rmidi->private_free(rmidi);
|
||||
put_device(&rmidi->dev);
|
||||
put_device(rmidi->dev);
|
||||
kfree(rmidi);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_rawmidi_free);
|
||||
@ -2038,7 +2035,7 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
|
||||
|
||||
err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI,
|
||||
rmidi->card, rmidi->device,
|
||||
&snd_rawmidi_f_ops, rmidi, &rmidi->dev);
|
||||
&snd_rawmidi_f_ops, rmidi, rmidi->dev);
|
||||
if (err < 0) {
|
||||
rmidi_err(rmidi, "unable to register\n");
|
||||
goto error;
|
||||
@ -2103,7 +2100,7 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
|
||||
return 0;
|
||||
|
||||
error_unregister:
|
||||
snd_unregister_device(&rmidi->dev);
|
||||
snd_unregister_device(rmidi->dev);
|
||||
error:
|
||||
mutex_lock(®ister_mutex);
|
||||
list_del(&rmidi->list);
|
||||
@ -2142,7 +2139,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)
|
||||
rmidi->ossreg = 0;
|
||||
}
|
||||
#endif /* CONFIG_SND_OSSEMUL */
|
||||
snd_unregister_device(&rmidi->dev);
|
||||
snd_unregister_device(rmidi->dev);
|
||||
mutex_unlock(&rmidi->open_mutex);
|
||||
mutex_unlock(®ister_mutex);
|
||||
return 0;
|
||||
|
@ -2721,7 +2721,7 @@ static const struct file_operations snd_seq_f_ops =
|
||||
.compat_ioctl = snd_seq_ioctl_compat,
|
||||
};
|
||||
|
||||
static struct device seq_dev;
|
||||
static struct device *seq_dev;
|
||||
|
||||
/*
|
||||
* register sequencer device
|
||||
@ -2730,15 +2730,17 @@ int __init snd_sequencer_device_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
snd_device_initialize(&seq_dev, NULL);
|
||||
dev_set_name(&seq_dev, "seq");
|
||||
err = snd_device_alloc(&seq_dev, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
dev_set_name(seq_dev, "seq");
|
||||
|
||||
mutex_lock(®ister_mutex);
|
||||
err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0,
|
||||
&snd_seq_f_ops, NULL, &seq_dev);
|
||||
&snd_seq_f_ops, NULL, seq_dev);
|
||||
mutex_unlock(®ister_mutex);
|
||||
if (err < 0) {
|
||||
put_device(&seq_dev);
|
||||
put_device(seq_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -2752,6 +2754,6 @@ int __init snd_sequencer_device_init(void)
|
||||
*/
|
||||
void snd_sequencer_device_done(void)
|
||||
{
|
||||
snd_unregister_device(&seq_dev);
|
||||
put_device(&seq_dev);
|
||||
snd_unregister_device(seq_dev);
|
||||
put_device(seq_dev);
|
||||
}
|
||||
|
@ -2301,7 +2301,7 @@ static void snd_timer_free_all(void)
|
||||
snd_timer_free(timer);
|
||||
}
|
||||
|
||||
static struct device timer_dev;
|
||||
static struct device *timer_dev;
|
||||
|
||||
/*
|
||||
* ENTRY functions
|
||||
@ -2311,8 +2311,10 @@ static int __init alsa_timer_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
snd_device_initialize(&timer_dev, NULL);
|
||||
dev_set_name(&timer_dev, "timer");
|
||||
err = snd_device_alloc(&timer_dev, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
dev_set_name(timer_dev, "timer");
|
||||
|
||||
#ifdef SNDRV_OSS_INFO_DEV_TIMERS
|
||||
snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1,
|
||||
@ -2326,7 +2328,7 @@ static int __init alsa_timer_init(void)
|
||||
}
|
||||
|
||||
err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0,
|
||||
&snd_timer_f_ops, NULL, &timer_dev);
|
||||
&snd_timer_f_ops, NULL, timer_dev);
|
||||
if (err < 0) {
|
||||
pr_err("ALSA: unable to register timer device (%i)\n", err);
|
||||
snd_timer_free_all();
|
||||
@ -2337,15 +2339,15 @@ static int __init alsa_timer_init(void)
|
||||
return 0;
|
||||
|
||||
put_timer:
|
||||
put_device(&timer_dev);
|
||||
put_device(timer_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit alsa_timer_exit(void)
|
||||
{
|
||||
snd_unregister_device(&timer_dev);
|
||||
snd_unregister_device(timer_dev);
|
||||
snd_timer_free_all();
|
||||
put_device(&timer_dev);
|
||||
put_device(timer_dev);
|
||||
snd_timer_proc_done();
|
||||
#ifdef SNDRV_OSS_INFO_DEV_TIMERS
|
||||
snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1);
|
||||
|
@ -13,10 +13,10 @@
|
||||
#include <sound/ump.h>
|
||||
#include <sound/ump_convert.h>
|
||||
|
||||
#define ump_err(ump, fmt, args...) dev_err(&(ump)->core.dev, fmt, ##args)
|
||||
#define ump_warn(ump, fmt, args...) dev_warn(&(ump)->core.dev, fmt, ##args)
|
||||
#define ump_info(ump, fmt, args...) dev_info(&(ump)->core.dev, fmt, ##args)
|
||||
#define ump_dbg(ump, fmt, args...) dev_dbg(&(ump)->core.dev, fmt, ##args)
|
||||
#define ump_err(ump, fmt, args...) dev_err((ump)->core.dev, fmt, ##args)
|
||||
#define ump_warn(ump, fmt, args...) dev_warn((ump)->core.dev, fmt, ##args)
|
||||
#define ump_info(ump, fmt, args...) dev_info((ump)->core.dev, fmt, ##args)
|
||||
#define ump_dbg(ump, fmt, args...) dev_dbg((ump)->core.dev, fmt, ##args)
|
||||
|
||||
static int snd_ump_dev_register(struct snd_rawmidi *rmidi);
|
||||
static int snd_ump_dev_unregister(struct snd_rawmidi *rmidi);
|
||||
@ -984,7 +984,7 @@ static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream)
|
||||
{
|
||||
struct snd_ump_endpoint *ump = substream->rmidi->private_data;
|
||||
int dir = substream->stream;
|
||||
int group = substream->number;
|
||||
int group = ump->legacy_mapping[substream->number];
|
||||
int err;
|
||||
|
||||
mutex_lock(&ump->open_mutex);
|
||||
@ -1016,7 +1016,7 @@ static int snd_ump_legacy_close(struct snd_rawmidi_substream *substream)
|
||||
{
|
||||
struct snd_ump_endpoint *ump = substream->rmidi->private_data;
|
||||
int dir = substream->stream;
|
||||
int group = substream->number;
|
||||
int group = ump->legacy_mapping[substream->number];
|
||||
|
||||
mutex_lock(&ump->open_mutex);
|
||||
spin_lock_irq(&ump->legacy_locks[dir]);
|
||||
@ -1123,21 +1123,62 @@ static void process_legacy_input(struct snd_ump_endpoint *ump, const u32 *src,
|
||||
spin_unlock_irqrestore(&ump->legacy_locks[dir], flags);
|
||||
}
|
||||
|
||||
/* Fill ump->legacy_mapping[] for groups to be used for legacy rawmidi */
|
||||
static int fill_legacy_mapping(struct snd_ump_endpoint *ump)
|
||||
{
|
||||
struct snd_ump_block *fb;
|
||||
unsigned int group_maps = 0;
|
||||
int i, num;
|
||||
|
||||
if (ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS) {
|
||||
list_for_each_entry(fb, &ump->block_list, list) {
|
||||
for (i = 0; i < fb->info.num_groups; i++)
|
||||
group_maps |= 1U << (fb->info.first_group + i);
|
||||
}
|
||||
if (!group_maps)
|
||||
ump_info(ump, "No UMP Group is found in FB\n");
|
||||
}
|
||||
|
||||
/* use all groups for non-static case */
|
||||
if (!group_maps)
|
||||
group_maps = (1U << SNDRV_UMP_MAX_GROUPS) - 1;
|
||||
|
||||
num = 0;
|
||||
for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++)
|
||||
if (group_maps & (1U << i))
|
||||
ump->legacy_mapping[num++] = i;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static void fill_substream_names(struct snd_ump_endpoint *ump,
|
||||
struct snd_rawmidi *rmidi, int dir)
|
||||
{
|
||||
struct snd_rawmidi_substream *s;
|
||||
|
||||
list_for_each_entry(s, &rmidi->streams[dir].substreams, list)
|
||||
snprintf(s->name, sizeof(s->name), "Group %d (%.16s)",
|
||||
ump->legacy_mapping[s->number] + 1, ump->info.name);
|
||||
}
|
||||
|
||||
int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
|
||||
char *id, int device)
|
||||
{
|
||||
struct snd_rawmidi *rmidi;
|
||||
bool input, output;
|
||||
int err;
|
||||
int err, num;
|
||||
|
||||
ump->out_cvts = kcalloc(16, sizeof(*ump->out_cvts), GFP_KERNEL);
|
||||
ump->out_cvts = kcalloc(SNDRV_UMP_MAX_GROUPS,
|
||||
sizeof(*ump->out_cvts), GFP_KERNEL);
|
||||
if (!ump->out_cvts)
|
||||
return -ENOMEM;
|
||||
|
||||
num = fill_legacy_mapping(ump);
|
||||
|
||||
input = ump->core.info_flags & SNDRV_RAWMIDI_INFO_INPUT;
|
||||
output = ump->core.info_flags & SNDRV_RAWMIDI_INFO_OUTPUT;
|
||||
err = snd_rawmidi_new(ump->core.card, id, device,
|
||||
output ? 16 : 0, input ? 16 : 0,
|
||||
output ? num : 0, input ? num : 0,
|
||||
&rmidi);
|
||||
if (err < 0) {
|
||||
kfree(ump->out_cvts);
|
||||
@ -1150,10 +1191,17 @@ int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
|
||||
if (output)
|
||||
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
|
||||
&snd_ump_legacy_output_ops);
|
||||
snprintf(rmidi->name, sizeof(rmidi->name), "%.68s (MIDI 1.0)",
|
||||
ump->info.name);
|
||||
rmidi->info_flags = ump->core.info_flags & ~SNDRV_RAWMIDI_INFO_UMP;
|
||||
rmidi->ops = &snd_ump_legacy_ops;
|
||||
rmidi->private_data = ump;
|
||||
ump->legacy_rmidi = rmidi;
|
||||
if (input)
|
||||
fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_INPUT);
|
||||
if (output)
|
||||
fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT);
|
||||
|
||||
ump_dbg(ump, "Created a legacy rawmidi #%d (%s)\n", device, id);
|
||||
return 0;
|
||||
}
|
||||
|
@ -280,6 +280,34 @@ int _snd_ctl_add_follower(struct snd_kcontrol *master,
|
||||
}
|
||||
EXPORT_SYMBOL(_snd_ctl_add_follower);
|
||||
|
||||
/**
|
||||
* snd_ctl_add_followers - add multiple followers to vmaster
|
||||
* @card: card instance
|
||||
* @master: the target vmaster kcontrol object
|
||||
* @list: NULL-terminated list of name strings of followers to be added
|
||||
*
|
||||
* Adds the multiple follower kcontrols with the given names.
|
||||
* Returns 0 for success or a negative error code.
|
||||
*/
|
||||
int snd_ctl_add_followers(struct snd_card *card, struct snd_kcontrol *master,
|
||||
const char * const *list)
|
||||
{
|
||||
struct snd_kcontrol *follower;
|
||||
int err;
|
||||
|
||||
for (; *list; list++) {
|
||||
follower = snd_ctl_find_id_mixer(card, *list);
|
||||
if (follower) {
|
||||
err = snd_ctl_add_follower(master, follower);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_ctl_add_followers);
|
||||
|
||||
/*
|
||||
* ctl callbacks for master controls
|
||||
*/
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user