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:
Takashi Iwai 2023-08-28 11:56:39 +02:00
commit b94a62a663
354 changed files with 9357 additions and 3902 deletions

View file

@ -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:

View 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>;
};

View file

@ -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

View file

@ -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

View file

@ -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;
};

View 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>;
};
};

View file

@ -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:

View file

@ -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>;
};
};

View file

@ -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>;
};
};

View file

@ -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 = <&amp_in>, <&amp_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
# --------------------

View 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 = <&reg_1p8v>;
CPVDD-supply = <&reg_1p8v>;
DBVDD-supply = <&reg_1p8v>;
DCVDD-supply = <&reg_1p8v>;
MICVDD-supply = <&reg_1p8v>;
};
};

View file

@ -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";
};

View file

@ -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
~~~~~~~~~~~

View file

@ -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.

View 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.

View file

@ -8,6 +8,7 @@ Card-Specific Information
cmipci
sb-live-mixer
audigy-mixer
emu-mixer
emu10k1-jack
via82xx-mixer
audiophile-usb

View file

@ -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).

View file

@ -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.

View file

@ -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

View file

@ -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,7 +866,8 @@ static int iio_channel_read_max(struct iio_channel *chan,
break;
default:
*val = vals[4];
*val2 = vals[5];
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 @@ int iio_read_max_channel_raw(struct iio_channel *chan, int *val)
}
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);

View file

@ -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

View file

@ -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>

View file

@ -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;

View file

@ -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>

View file

@ -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"

View file

@ -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},

View file

@ -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},

View file

@ -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"

View file

@ -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"

View file

@ -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>

View file

@ -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"

View file

@ -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);

View file

@ -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;

View file

@ -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>

View file

@ -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"

View file

@ -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>

View file

@ -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"

View file

@ -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>

View file

@ -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>

View file

@ -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"

View file

@ -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"

View file

@ -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>

View file

@ -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 {

View file

@ -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"

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -204,9 +204,9 @@ 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,
unsigned long count)
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);
struct solo_dev *solo_dev = solo_pcm->solo_dev;
@ -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,

View file

@ -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 */

View file

@ -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 {

View file

@ -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,
num_controls, component->name_prefix);
up_write(&card->controls_rwsem);
return err;
return gbaudio_remove_controls(card, component->dev, controls,
num_controls, component->name_prefix);
}

View file

@ -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);

View file

@ -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);

View file

@ -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>

View file

@ -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

View file

@ -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

View file

@ -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 *);

View file

@ -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;

View file

@ -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

View file

@ -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,

View file

@ -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 */

View file

@ -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);

View file

@ -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];

View file

@ -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;

View file

@ -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
*/

View file

@ -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 */

View file

@ -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 */

View file

@ -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);

View file

@ -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];

View file

@ -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;

View file

@ -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,

View file

@ -137,10 +137,10 @@ 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,
struct snd_pcm_substream *substream, int channel,
unsigned long pos, void __user *buf,
unsigned long bytes);
int (*copy)(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int channel,
unsigned long pos, struct iov_iter *buf,
unsigned long bytes);
struct page *(*page)(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
unsigned long offset);
@ -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 channel, unsigned long pos,
void __user *buf, unsigned long bytes);
int snd_soc_pcm_component_copy(struct snd_pcm_substream *substream,
int channel, unsigned long pos,
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,

View file

@ -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);

View file

@ -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, \

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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,

View file

@ -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;
}

View file

@ -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>

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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(&register_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(&register_mutex);

View file

@ -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,

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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)

View file

@ -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(&register_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(&register_mutex);
return 0;

View file

@ -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(&register_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(&register_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);
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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