sound updates for 5.13
No surprises in this development cycle, and most of works are about the fixes and the improvements of the existing code, while a new LED control layer and a few new drivers have been introduced. Here are some highlights: Core: - A common mute-LED framework was introduced; used by HD-audio for now, more adaption will follow later. The former "Mic Mute-LED Mode" mixer control has been replaced with the corresponding sysfs now. - User-control management was changed to count consumed bytes instead of capping by number of elements; this will allow more controls in the normal usage pattern while avoiding the possible memory exhaustion DoS ASoC: - Continued refactoring and cleanups in ASoC core and generic card drivers - Wide range of small cppcheck and warning fixes - New drivers for Freescale i.MX DMA over rpmsg, Mediatek MT6358 accessory detection, and Realtek RT1019, RT1316, RT711 and RT715 USB-audio: - Continued improvements and fixes of the implicit feedback mode, including better support for Pioneer and Roland/BOSS devices HD-audio: - Default back to non-buffer preallocation on x86 - Cirrus codec improvements, more quirks for Realtek codecs Others: - New virtio sound driver - FireWire Bebob updates Note that this PR includes a couple of changes in reset and SPI drivers, too, and some merge conflicts might happen. -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmCMJaAOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE/T6A//Ti0SAWYnAr5l/7ccuwS4zljHcuHngwvIxRPY BokU1ZUlagi+Ro2HLUq13G8T4AlUAQ8r2ecz7EJQHHl9tkrIg7Cc0+fiBPHju1Yu 0F3Vjc78/JsJHvAR2DPll2rwhsdD3usSQXFo181k38J098X02iNcrzsj3kW5Bpzb DBvXzOBIAg/PPfPa4edSYsSurqYeZTkhshedTohlwOCnVbW9NN5b5T9yoXP+t5na rvK1Vhu0He8nVMBPDrzjKgE5rjm7Kn0FNXZ6CMDekU9sRVzm/PbgAqqmRnn6bUKa GDpcQzlaiDrw8a7/uTVgUZy85F9kMXMMnfYpBy4bBXOt6RWOplXY1yMxy1RXV+op 3qC9k5R+IsjSWFQZ2z5bIHtGBNCG0698z9fQcvpsWTv+R68rUyfj+jeO/G9zzvpi qpQTloBfI28NoP+iGis7wtrlQ15ut47YMCQS8QiOEvLmd5/3xKXRut4Ac/VmvDpS q7fLivL8MZ/SMoXY74q/kByMBkXNpryQCAN+xAslaJ5P0aefNYJJdBt/sJlsDd9J Ya2VIxHoP+Sb1MG6OLq1Y8c53Di9lwY80pOtF3plcz/ZWgzipirf6BhFj0OttiKP a6+VewXA7zZcWEdw+Ik4dWP2dybWL+CuNl7Bwug8SyG9iWqg8Ph7FgoCTWAi93Fx KKUJxsc= =YT3U -----END PGP SIGNATURE----- Merge tag 'sound-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound updates from Takashi Iwai: "No surprises in this development cycle, and most of work is about the fixes and the improvements of the existing code, while a new LED control layer and a few new drivers have been introduced. Here are some highlights: Core: - A common mute-LED framework was introduced. It is used by HD-audio for now, more adaption will follow later. The former "Mic Mute-LED Mode" mixer control has been replaced with the corresponding sysfs now. - User-control management was changed to count consumed bytes instead of capping by number of elements; this will allow more controls in the normal usage pattern while avoiding the possible memory exhaustion DoS ASoC: - Continued refactoring and cleanups in ASoC core and generic card drivers - Wide range of small cppcheck and warning fixes - New drivers for Freescale i.MX DMA over rpmsg, Mediatek MT6358 accessory detection, and Realtek RT1019, RT1316, RT711 and RT715 USB-audio: - Continued improvements and fixes of the implicit feedback mode, including better support for Pioneer and Roland/BOSS devices HD-audio: - Default back to non-buffer preallocation on x86 - Cirrus codec improvements, more quirks for Realtek codecs Others: - New virtio sound driver - FireWire Bebob updates" * tag 'sound-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (587 commits) ALSA: hda/conexant: Re-order CX5066 quirk table entries ALSA: hda/realtek: Remove redundant entry for ALC861 Haier/Uniwill devices ALSA: hda/realtek: Re-order ALC662 quirk table entries ALSA: hda/realtek: Re-order remaining ALC269 quirk table entries ALSA: hda/realtek: Re-order ALC269 Lenovo quirk table entries ALSA: hda/realtek: Re-order ALC269 Sony quirk table entries ALSA: hda/realtek: Re-order ALC269 ASUS quirk table entries ALSA: hda/realtek: Re-order ALC269 Dell quirk table entries ALSA: hda/realtek: Re-order ALC269 Acer quirk table entries ALSA: hda/realtek: Re-order ALC269 HP quirk table entries ALSA: hda/realtek: Re-order ALC882 Clevo quirk table entries ALSA: hda/realtek: Re-order ALC882 Sony quirk table entries ALSA: hda/realtek: Re-order ALC882 Acer quirk table entries ALSA: usb-audio: Remove redundant assignment to len ALSA: hda/realtek: Add quirk for Intel Clevo PCx0Dx ALSA: virtio: fix kernel-doc ALSA: hda/cirrus: Use CS8409 filter to fix abnormal sounds on Bullseye ALSA: hda/cirrus: Set Initial DMIC volume for Bullseye to -26 dB ALSA: sb: Fix two use after free in snd_sb_qsound_build ALSA: emu8000: Fix a use after free in snd_emu8000_create_mixer ...
This commit is contained in:
commit
b71428d7ab
@ -4,7 +4,7 @@ This device supports I2C mode only.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "asahi-kasei,ak5558"
|
||||
- compatible : "asahi-kasei,ak5558" or "asahi-kasei,ak5552".
|
||||
- reg : The I2C address of the device.
|
||||
|
||||
Optional properties:
|
||||
|
@ -11,71 +11,59 @@ maintainers:
|
||||
|
||||
select: false
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/graph.yaml#/$defs/port-base
|
||||
|
||||
properties:
|
||||
port:
|
||||
description: single OF-Graph subnode
|
||||
type: object
|
||||
prefix:
|
||||
description: "device name prefix"
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
convert-rate:
|
||||
description: CPU to Codec rate convert.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
convert-channels:
|
||||
description: CPU to Codec rate channels.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
patternProperties:
|
||||
"^endpoint(@[0-9a-f]+)?":
|
||||
$ref: /schemas/graph.yaml#/$defs/endpoint-base
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
prefix:
|
||||
description: "device name prefix"
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
mclk-fs:
|
||||
description: |
|
||||
Multiplication factor between stream rate and codec mclk.
|
||||
When defined, mclk-fs property defined in dai-link sub nodes are
|
||||
ignored.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
frame-inversion:
|
||||
description: dai-link uses frame clock inversion
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
bitclock-inversion:
|
||||
description: dai-link uses bit clock inversion
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
frame-master:
|
||||
description: Indicates dai-link frame master.
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
bitclock-master:
|
||||
description: Indicates dai-link bit clock master
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
dai-format:
|
||||
description: audio format.
|
||||
items:
|
||||
enum:
|
||||
- i2s
|
||||
- right_j
|
||||
- left_j
|
||||
- dsp_a
|
||||
- dsp_b
|
||||
- ac97
|
||||
- pdm
|
||||
- msb
|
||||
- lsb
|
||||
convert-rate:
|
||||
description: CPU to Codec rate convert.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
convert-channels:
|
||||
description: CPU to Codec rate channels.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
patternProperties:
|
||||
"^endpoint(@[0-9a-f]+)?":
|
||||
type: object
|
||||
properties:
|
||||
remote-endpoint:
|
||||
maxItems: 1
|
||||
mclk-fs:
|
||||
description: |
|
||||
Multiplication factor between stream rate and codec mclk.
|
||||
When defined, mclk-fs property defined in dai-link sub nodes are
|
||||
ignored.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
frame-inversion:
|
||||
description: dai-link uses frame clock inversion
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
bitclock-inversion:
|
||||
description: dai-link uses bit clock inversion
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
frame-master:
|
||||
description: Indicates dai-link frame master.
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
bitclock-master:
|
||||
description: Indicates dai-link bit clock master
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
dai-format:
|
||||
description: audio format.
|
||||
items:
|
||||
enum:
|
||||
- i2s
|
||||
- right_j
|
||||
- left_j
|
||||
- dsp_a
|
||||
- dsp_b
|
||||
- ac97
|
||||
- pdm
|
||||
- msb
|
||||
- lsb
|
||||
convert-rate:
|
||||
description: CPU to Codec rate convert.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
convert-channels:
|
||||
description: CPU to Codec rate channels.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
ports:
|
||||
description: multi OF-Graph subnode
|
||||
type: object
|
||||
patternProperties:
|
||||
"^port(@[0-9a-f]+)?":
|
||||
$ref: "#/properties/port"
|
||||
|
||||
additionalProperties: true
|
||||
|
108
Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
Normal file
108
Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
Normal file
@ -0,0 +1,108 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/fsl,rpmsg.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NXP Audio RPMSG CPU DAI Controller
|
||||
|
||||
maintainers:
|
||||
- Shengjiu Wang <shengjiu.wang@nxp.com>
|
||||
|
||||
description: |
|
||||
fsl_rpmsg is a virtual audio device. Mapping to real hardware devices
|
||||
are SAI, DMA controlled by Cortex M core. What we see from Linux
|
||||
side is a device which provides audio service by rpmsg channel.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fsl,imx7ulp-rpmsg-audio
|
||||
- fsl,imx8mn-rpmsg-audio
|
||||
- fsl,imx8mm-rpmsg-audio
|
||||
- fsl,imx8mp-rpmsg-audio
|
||||
|
||||
model:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description: User specified audio sound card name
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Peripheral clock for register access
|
||||
- description: Master clock
|
||||
- description: DMA clock for DMA register access
|
||||
- description: Parent clock for multiple of 8kHz sample rates
|
||||
- description: Parent clock for multiple of 11kHz sample rates
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ipg
|
||||
- const: mclk
|
||||
- const: dma
|
||||
- const: pll8k
|
||||
- const: pll11k
|
||||
|
||||
power-domains:
|
||||
description:
|
||||
List of phandle and PM domain specifier as documented in
|
||||
Documentation/devicetree/bindings/power/power_domain.txt
|
||||
maxItems: 1
|
||||
|
||||
memory-region:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
phandle to a node describing reserved memory (System RAM memory)
|
||||
The M core can't access all the DDR memory space on some platform,
|
||||
So reserved a specific memory for dma buffer which M core can
|
||||
access.
|
||||
(see bindings/reserved-memory/reserved-memory.txt)
|
||||
|
||||
audio-codec:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: The phandle to a node of audio codec
|
||||
|
||||
audio-routing:
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
description: |
|
||||
A list of the connections between audio components. Each entry is a
|
||||
pair of strings, the first being the connection's sink, the second
|
||||
being the connection's source.
|
||||
|
||||
fsl,enable-lpa:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description: enable low power audio path.
|
||||
|
||||
fsl,rpmsg-out:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description: |
|
||||
This is a boolean property. If present, the transmitting function
|
||||
will be enabled.
|
||||
|
||||
fsl,rpmsg-in:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description: |
|
||||
This is a boolean property. If present, the receiving function
|
||||
will be enabled.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- model
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx8mn-clock.h>
|
||||
|
||||
rpmsg_audio: rpmsg_audio {
|
||||
compatible = "fsl,imx8mn-rpmsg-audio";
|
||||
model = "wm8524-audio";
|
||||
fsl,enable-lpa;
|
||||
fsl,rpmsg-out;
|
||||
clocks = <&clk IMX8MN_CLK_SAI3_IPG>,
|
||||
<&clk IMX8MN_CLK_SAI3_ROOT>,
|
||||
<&clk IMX8MN_CLK_SDMA3_ROOT>,
|
||||
<&clk IMX8MN_AUDIO_PLL1_OUT>,
|
||||
<&clk IMX8MN_AUDIO_PLL2_OUT>;
|
||||
clock-names = "ipg", "mclk", "dma", "pll8k", "pll11k";
|
||||
};
|
@ -42,6 +42,8 @@ The compatible list for this generic sound card currently:
|
||||
|
||||
"fsl,imx-audio-si476x"
|
||||
|
||||
"fsl,imx-audio-wm8958"
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : Contains one of entries in the compatible list.
|
||||
|
@ -81,6 +81,6 @@ examples:
|
||||
interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-names = "osc", "apb_clk";
|
||||
clocks = <&scmi_clk KEEM_BAY_PSS_AUX_I2S3>, <&scmi_clk KEEM_BAY_PSS_I2S3>;
|
||||
dmas = <&axi_dma0 29 &axi_dma0 33>;
|
||||
dmas = <&axi_dma0 29>, <&axi_dma0 33>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
@ -9,9 +9,6 @@ title: Marvel SSPA Digital Audio Interface Bindings
|
||||
maintainers:
|
||||
- Lubomir Rintel <lkundrak@v3.sk>
|
||||
|
||||
allOf:
|
||||
- $ref: audio-graph-port.yaml#
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^audio-controller(@.*)?$"
|
||||
@ -54,7 +51,8 @@ properties:
|
||||
- const: rx
|
||||
|
||||
port:
|
||||
type: object
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
|
108
Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
Normal file
108
Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
Normal file
@ -0,0 +1,108 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/mchp,i2s-mcc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Microchip I2S Multi-Channel Controller
|
||||
|
||||
maintainers:
|
||||
- Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
|
||||
|
||||
description:
|
||||
The I2SMCC complies with the Inter-IC Sound (I2S) bus specification and
|
||||
supports a Time Division Multiplexed (TDM) interface with external
|
||||
multi-channel audio codecs. It consists of a receiver, a transmitter and a
|
||||
common clock generator that can be enabled separately to provide Adapter,
|
||||
Client or Controller modes with receiver and/or transmitter active.
|
||||
On later I2SMCC versions (starting with Microchip's SAMA7G5) I2S
|
||||
multi-channel is supported by using multiple data pins, output and
|
||||
input, without TDM.
|
||||
|
||||
properties:
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
compatible:
|
||||
enum:
|
||||
- microchip,sam9x60-i2smcc
|
||||
- microchip,sama7g5-i2smcc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Peripheral Bus Clock
|
||||
- description: Generic Clock (Optional). Should be set mostly when Master
|
||||
Mode is required.
|
||||
minItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
- const: gclk
|
||||
minItems: 1
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: TX DMA Channel
|
||||
- description: RX DMA Channel
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: tx
|
||||
- const: rx
|
||||
|
||||
microchip,tdm-data-pair:
|
||||
description:
|
||||
Represents the DIN/DOUT pair pins that are used to receive/send
|
||||
TDM data. It is optional and it is only needed if the controller
|
||||
uses the TDM mode.
|
||||
$ref: /schemas/types.yaml#/definitions/uint8
|
||||
enum: [0, 1, 2, 3]
|
||||
default: 0
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
const: microchip,sam9x60-i2smcc
|
||||
then:
|
||||
properties:
|
||||
microchip,tdm-data-pair: false
|
||||
|
||||
required:
|
||||
- "#sound-dai-cells"
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- dmas
|
||||
- dma-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/dma/at91.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
i2s@f001c000 {
|
||||
#sound-dai-cells = <0>;
|
||||
compatible = "microchip,sam9x60-i2smcc";
|
||||
reg = <0xf001c000 0x100>;
|
||||
interrupts = <34 IRQ_TYPE_LEVEL_HIGH 7>;
|
||||
dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
|
||||
AT91_XDMAC_DT_PERID(36))>,
|
||||
<&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
|
||||
AT91_XDMAC_DT_PERID(37))>;
|
||||
dma-names = "tx", "rx";
|
||||
clocks = <&i2s_clk>, <&i2s_gclk>;
|
||||
clock-names = "pclk", "gclk";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_i2s_default>;
|
||||
};
|
@ -1,43 +0,0 @@
|
||||
* Microchip I2S Multi-Channel Controller
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "microchip,sam9x60-i2smcc".
|
||||
- reg: Should be the physical base address of the controller and the
|
||||
length of memory mapped region.
|
||||
- interrupts: Should contain the interrupt for the controller.
|
||||
- dmas: Should be one per channel name listed in the dma-names property,
|
||||
as described in atmel-dma.txt and dma.txt files.
|
||||
- dma-names: Identifier string for each DMA request line in the dmas property.
|
||||
Two dmas have to be defined, "tx" and "rx".
|
||||
- clocks: Must contain an entry for each entry in clock-names.
|
||||
Please refer to clock-bindings.txt.
|
||||
- clock-names: Should be one of each entry matching the clocks phandles list:
|
||||
- "pclk" (peripheral clock) Required.
|
||||
- "gclk" (generated clock) Optional (1).
|
||||
|
||||
Optional properties:
|
||||
- pinctrl-0: Should specify pin control groups used for this controller.
|
||||
- princtrl-names: Should contain only one value - "default".
|
||||
|
||||
|
||||
(1) : Only the peripheral clock is required. The generated clock is optional
|
||||
and should be set mostly when Master Mode is required.
|
||||
|
||||
Example:
|
||||
|
||||
i2s@f001c000 {
|
||||
compatible = "microchip,sam9x60-i2smcc";
|
||||
reg = <0xf001c000 0x100>;
|
||||
interrupts = <34 IRQ_TYPE_LEVEL_HIGH 7>;
|
||||
dmas = <&dma0
|
||||
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
|
||||
AT91_XDMAC_DT_PERID(36))>,
|
||||
<&dma0
|
||||
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
|
||||
AT91_XDMAC_DT_PERID(37))>;
|
||||
dma-names = "tx", "rx";
|
||||
clocks = <&i2s_clk>, <&i2s_gclk>;
|
||||
clock-names = "pclk", "gclk";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_i2s_default>;
|
||||
};
|
@ -4,6 +4,7 @@ Required properties:
|
||||
- compatible : "mediatek,mt8183_mt6358_ts3a227_max98357" for MAX98357A codec
|
||||
"mediatek,mt8183_mt6358_ts3a227_max98357b" for MAX98357B codec
|
||||
"mediatek,mt8183_mt6358_ts3a227_rt1015" for RT1015 codec
|
||||
"mediatek,mt8183_mt6358_ts3a227_rt1015p" for RT1015P codec
|
||||
- mediatek,platform: the phandle of MT8183 ASoC platform
|
||||
|
||||
Optional properties:
|
||||
|
@ -17,9 +17,6 @@ maintainers:
|
||||
- Jon Hunter <jonathanh@nvidia.com>
|
||||
- Sameer Pujar <spujar@nvidia.com>
|
||||
|
||||
allOf:
|
||||
- $ref: audio-graph-port.yaml#
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^dspk@[0-9a-f]*$"
|
||||
@ -59,14 +56,18 @@ properties:
|
||||
available instances on a Tegra SoC.
|
||||
|
||||
ports:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
properties:
|
||||
port@0:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: |
|
||||
DSPK ACIF (Audio Client Interface) port connected to the
|
||||
corresponding AHUB (Audio Hub) ACIF port.
|
||||
|
||||
port@1:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: |
|
||||
DSPK DAP (Digital Audio Port) interface which can be connected
|
||||
to external audio codec for playback.
|
||||
@ -80,7 +81,7 @@ required:
|
||||
- assigned-clock-parents
|
||||
- sound-name-prefix
|
||||
|
||||
unevaluatedProperties: false
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
@ -17,9 +17,6 @@ maintainers:
|
||||
- Jon Hunter <jonathanh@nvidia.com>
|
||||
- Sameer Pujar <spujar@nvidia.com>
|
||||
|
||||
allOf:
|
||||
- $ref: audio-graph-port.yaml#
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^admaif@[0-9a-f]*$"
|
||||
@ -41,6 +38,7 @@ properties:
|
||||
dma-names: true
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description: |
|
||||
Contains list of ACIF (Audio CIF) port nodes for ADMAIF channels.
|
||||
The number of port nodes depends on the number of ADMAIF channels
|
||||
@ -48,6 +46,11 @@ properties:
|
||||
in AHUB (Audio Hub). Each port is capable of data transfers in
|
||||
both directions.
|
||||
|
||||
patternProperties:
|
||||
'^port@[0-9]':
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
@ -92,7 +95,7 @@ required:
|
||||
- dmas
|
||||
- dma-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
@ -17,9 +17,6 @@ maintainers:
|
||||
- Jon Hunter <jonathanh@nvidia.com>
|
||||
- Sameer Pujar <spujar@nvidia.com>
|
||||
|
||||
allOf:
|
||||
- $ref: audio-graph-port.yaml#
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^ahub@[0-9a-f]*$"
|
||||
@ -60,12 +57,34 @@ properties:
|
||||
ranges: true
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description: |
|
||||
Contains list of ACIF (Audio CIF) port nodes for AHUB (Audio Hub).
|
||||
These are connected to ACIF interfaces of AHUB clients. Thus the
|
||||
number of port nodes depend on the number of clients that AHUB may
|
||||
have depending on the SoC revision.
|
||||
|
||||
patternProperties:
|
||||
'^port@[0-9]':
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
patternProperties:
|
||||
'^i2s@[0-9a-f]+$':
|
||||
type: object
|
||||
|
||||
'^dmic@[0-9a-f]+$':
|
||||
type: object
|
||||
$ref: nvidia,tegra210-dmic.yaml#
|
||||
|
||||
'^admaif@[0-9a-f]+$':
|
||||
type: object
|
||||
$ref: nvidia,tegra210-admaif.yaml#
|
||||
|
||||
'^dspk@[0-9a-f]+$':
|
||||
type: object
|
||||
$ref: nvidia,tegra186-dspk.yaml#
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@ -77,7 +96,7 @@ required:
|
||||
- "#size-cells"
|
||||
- ranges
|
||||
|
||||
unevaluatedProperties: false
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
@ -16,9 +16,6 @@ maintainers:
|
||||
- Jon Hunter <jonathanh@nvidia.com>
|
||||
- Sameer Pujar <spujar@nvidia.com>
|
||||
|
||||
allOf:
|
||||
- $ref: audio-graph-port.yaml#
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^dmic@[0-9a-f]*$"
|
||||
@ -60,14 +57,18 @@ properties:
|
||||
on the maximum available instances on a Tegra SoC.
|
||||
|
||||
ports:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
properties:
|
||||
port@0:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: |
|
||||
DMIC ACIF (Audio Client Interface) port connected to the
|
||||
corresponding AHUB (Audio Hub) ACIF port.
|
||||
|
||||
port@1:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: |
|
||||
DMIC DAP (Digital Audio Port) interface which can be connected
|
||||
to external audio codec for capture.
|
||||
@ -80,7 +81,7 @@ required:
|
||||
- assigned-clocks
|
||||
- assigned-clock-parents
|
||||
|
||||
unevaluatedProperties: false
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
@ -16,9 +16,6 @@ maintainers:
|
||||
- Jon Hunter <jonathanh@nvidia.com>
|
||||
- Sameer Pujar <spujar@nvidia.com>
|
||||
|
||||
allOf:
|
||||
- $ref: audio-graph-port.yaml#
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^i2s@[0-9a-f]*$"
|
||||
@ -78,14 +75,18 @@ properties:
|
||||
on the maximum available instances on a Tegra SoC.
|
||||
|
||||
ports:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
properties:
|
||||
port@0:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: |
|
||||
I2S ACIF (Audio Client Interface) port connected to the
|
||||
corresponding AHUB (Audio Hub) ACIF port.
|
||||
|
||||
port@1:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: |
|
||||
I2S DAP (Digital Audio Port) interface which can be connected
|
||||
to external audio codec for playback or capture.
|
||||
@ -98,7 +99,7 @@ required:
|
||||
- assigned-clocks
|
||||
- assigned-clock-parents
|
||||
|
||||
unevaluatedProperties: false
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
@ -110,7 +110,9 @@ properties:
|
||||
- pattern: '^dvc\.[0-1]$'
|
||||
- pattern: '^clk_(a|b|c|i)$'
|
||||
|
||||
port: true
|
||||
port:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
# use patternProperties to avoid naming "xxx,yyy" issue
|
||||
patternProperties:
|
||||
@ -256,7 +258,6 @@ required:
|
||||
|
||||
allOf:
|
||||
- $ref: audio-graph.yaml#
|
||||
- $ref: audio-graph-port.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
35
Documentation/devicetree/bindings/sound/rt1019.yaml
Normal file
35
Documentation/devicetree/bindings/sound/rt1019.yaml
Normal file
@ -0,0 +1,35 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/rt1019.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: RT1019 Mono Class-D Audio Amplifier
|
||||
|
||||
maintainers:
|
||||
- jack.yu@realtek.com
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: realtek,rt1019
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
description: I2C address of the device.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
rt1019: codec@28 {
|
||||
compatible = "realtek,rt1019";
|
||||
reg = <0x28>;
|
||||
};
|
||||
};
|
@ -44,7 +44,7 @@ Optional properties:
|
||||
- realtek,dmic-delay-ms : Set the delay time (ms) for the requirement of
|
||||
the particular DMIC.
|
||||
|
||||
- realtek,dmic-clk-driving-high : Set the high drving of the DMIC clock out.
|
||||
- realtek,dmic-clk-driving-high : Set the high driving of the DMIC clock out.
|
||||
|
||||
Pins on the device (for linking into audio routes) for RT5682:
|
||||
|
||||
|
@ -46,11 +46,9 @@ properties:
|
||||
|
||||
patternProperties:
|
||||
"^port@[0-9]$":
|
||||
type: object
|
||||
properties:
|
||||
endpoint: true
|
||||
required:
|
||||
- endpoint
|
||||
description: FIXME, Need to define what each port is.
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
@ -40,11 +40,9 @@ properties:
|
||||
|
||||
patternProperties:
|
||||
"^port@[0-9]$":
|
||||
type: object
|
||||
properties:
|
||||
endpoint: true
|
||||
required:
|
||||
- endpoint
|
||||
description: FIXME, Need to define what each port is.
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
Texas Instruments - tlv320aic3x Codec module
|
||||
|
||||
The tlv320aic3x serial control bus communicates through I2C protocols
|
||||
The tlv320aic3x serial control bus communicates through both I2C and SPI bus protocols
|
||||
|
||||
Required properties:
|
||||
|
||||
@ -63,7 +63,7 @@ CODEC input pins for other compatible codecs:
|
||||
|
||||
The pins can be used in referring sound node's audio-routing property.
|
||||
|
||||
Example:
|
||||
I2C example:
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
@ -78,3 +78,20 @@ tlv320aic3x: tlv320aic3x@1b {
|
||||
DRVDD-supply = <®ulator>;
|
||||
DVDD-supply = <®ulator>;
|
||||
};
|
||||
|
||||
SPI example:
|
||||
|
||||
spi0: spi@f0000000 {
|
||||
tlv320aic3x: codec@0 {
|
||||
compatible = "ti,tlv320aic3x";
|
||||
reg = <0>; /* CS number */
|
||||
#sound-dai-cells = <0>;
|
||||
spi-max-frequency = <1000000>;
|
||||
|
||||
AVDD-supply = <®ulator>;
|
||||
IOVDD-supply = <®ulator>;
|
||||
DRVDD-supply = <®ulator>;
|
||||
DVDD-supply = <®ulator>;
|
||||
ai3x-ocmv = <0>;
|
||||
};
|
||||
};
|
||||
|
@ -19335,6 +19335,15 @@ W: https://virtio-mem.gitlab.io/
|
||||
F: drivers/virtio/virtio_mem.c
|
||||
F: include/uapi/linux/virtio_mem.h
|
||||
|
||||
VIRTIO SOUND DRIVER
|
||||
M: Anton Yakovlev <anton.yakovlev@opensynergy.com>
|
||||
M: "Michael S. Tsirkin" <mst@redhat.com>
|
||||
L: virtualization@lists.linux-foundation.org
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: include/uapi/linux/virtio_snd.h
|
||||
F: sound/virtio/*
|
||||
|
||||
VIRTUAL BOX GUEST DEVICE DRIVER
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
M: Arnd Bergmann <arnd@arndb.de>
|
||||
|
@ -166,6 +166,7 @@ static int __init dmi_checksum(const u8 *buf, u8 len)
|
||||
static const char *dmi_ident[DMI_STRING_MAX];
|
||||
static LIST_HEAD(dmi_devices);
|
||||
int dmi_available;
|
||||
EXPORT_SYMBOL_GPL(dmi_available);
|
||||
|
||||
/*
|
||||
* Save a DMI string
|
||||
|
@ -358,6 +358,30 @@ int reset_control_reset(struct reset_control *rstc)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_reset);
|
||||
|
||||
/**
|
||||
* reset_control_bulk_reset - reset the controlled devices in order
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset controls set
|
||||
*
|
||||
* Issue a reset on all provided reset controls, in order.
|
||||
*
|
||||
* See also: reset_control_reset()
|
||||
*/
|
||||
int reset_control_bulk_reset(int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < num_rstcs; i++) {
|
||||
ret = reset_control_reset(rstcs[i].rstc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_bulk_reset);
|
||||
|
||||
/**
|
||||
* reset_control_rearm - allow shared reset line to be re-triggered"
|
||||
* @rstc: reset controller
|
||||
@ -461,6 +485,36 @@ int reset_control_assert(struct reset_control *rstc)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_assert);
|
||||
|
||||
/**
|
||||
* reset_control_bulk_assert - asserts the reset lines in order
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset controls set
|
||||
*
|
||||
* Assert the reset lines for all provided reset controls, in order.
|
||||
* If an assertion fails, already asserted resets are deasserted again.
|
||||
*
|
||||
* See also: reset_control_assert()
|
||||
*/
|
||||
int reset_control_bulk_assert(int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < num_rstcs; i++) {
|
||||
ret = reset_control_assert(rstcs[i].rstc);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
while (i--)
|
||||
reset_control_deassert(rstcs[i].rstc);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_bulk_assert);
|
||||
|
||||
/**
|
||||
* reset_control_deassert - deasserts the reset line
|
||||
* @rstc: reset controller
|
||||
@ -511,6 +565,36 @@ int reset_control_deassert(struct reset_control *rstc)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_deassert);
|
||||
|
||||
/**
|
||||
* reset_control_bulk_deassert - deasserts the reset lines in reverse order
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset controls set
|
||||
*
|
||||
* Deassert the reset lines for all provided reset controls, in reverse order.
|
||||
* If a deassertion fails, already deasserted resets are asserted again.
|
||||
*
|
||||
* See also: reset_control_deassert()
|
||||
*/
|
||||
int reset_control_bulk_deassert(int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = num_rstcs - 1; i >= 0; i--) {
|
||||
ret = reset_control_deassert(rstcs[i].rstc);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
while (i < num_rstcs)
|
||||
reset_control_assert(rstcs[i++].rstc);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_bulk_deassert);
|
||||
|
||||
/**
|
||||
* reset_control_status - returns a negative errno if not supported, a
|
||||
* positive value if the reset line is asserted, or zero if the reset
|
||||
@ -588,6 +672,36 @@ int reset_control_acquire(struct reset_control *rstc)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_acquire);
|
||||
|
||||
/**
|
||||
* reset_control_bulk_acquire - acquires reset controls for exclusive use
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset controls set
|
||||
*
|
||||
* This is used to explicitly acquire reset controls requested with
|
||||
* reset_control_bulk_get_exclusive_release() for temporary exclusive use.
|
||||
*
|
||||
* See also: reset_control_acquire(), reset_control_bulk_release()
|
||||
*/
|
||||
int reset_control_bulk_acquire(int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < num_rstcs; i++) {
|
||||
ret = reset_control_acquire(rstcs[i].rstc);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
while (i--)
|
||||
reset_control_release(rstcs[i].rstc);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_bulk_acquire);
|
||||
|
||||
/**
|
||||
* reset_control_release() - releases exclusive access to a reset control
|
||||
* @rstc: reset control
|
||||
@ -610,6 +724,26 @@ void reset_control_release(struct reset_control *rstc)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_release);
|
||||
|
||||
/**
|
||||
* reset_control_bulk_release() - releases exclusive access to reset controls
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset controls set
|
||||
*
|
||||
* Releases exclusive access right to reset controls previously obtained by a
|
||||
* call to reset_control_bulk_acquire().
|
||||
*
|
||||
* See also: reset_control_release(), reset_control_bulk_acquire()
|
||||
*/
|
||||
void reset_control_bulk_release(int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_rstcs; i++)
|
||||
reset_control_release(rstcs[i].rstc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_bulk_release);
|
||||
|
||||
static struct reset_control *__reset_control_get_internal(
|
||||
struct reset_controller_dev *rcdev,
|
||||
unsigned int index, bool shared, bool acquired)
|
||||
@ -814,6 +948,32 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__reset_control_get);
|
||||
|
||||
int __reset_control_bulk_get(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs,
|
||||
bool shared, bool optional, bool acquired)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < num_rstcs; i++) {
|
||||
rstcs[i].rstc = __reset_control_get(dev, rstcs[i].id, 0,
|
||||
shared, optional, acquired);
|
||||
if (IS_ERR(rstcs[i].rstc)) {
|
||||
ret = PTR_ERR(rstcs[i].rstc);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
mutex_lock(&reset_list_mutex);
|
||||
while (i--)
|
||||
__reset_control_put_internal(rstcs[i].rstc);
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__reset_control_bulk_get);
|
||||
|
||||
static void reset_control_array_put(struct reset_control_array *resets)
|
||||
{
|
||||
int i;
|
||||
@ -845,6 +1005,23 @@ void reset_control_put(struct reset_control *rstc)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_put);
|
||||
|
||||
/**
|
||||
* reset_control_bulk_put - free the reset controllers
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset controls set
|
||||
*/
|
||||
void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
mutex_lock(&reset_list_mutex);
|
||||
while (num_rstcs--) {
|
||||
if (IS_ERR_OR_NULL(rstcs[num_rstcs].rstc))
|
||||
continue;
|
||||
__reset_control_put_internal(rstcs[num_rstcs].rstc);
|
||||
}
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_bulk_put);
|
||||
|
||||
static void devm_reset_control_release(struct device *dev, void *res)
|
||||
{
|
||||
reset_control_put(*(struct reset_control **)res);
|
||||
@ -874,6 +1051,44 @@ struct reset_control *__devm_reset_control_get(struct device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__devm_reset_control_get);
|
||||
|
||||
struct reset_control_bulk_devres {
|
||||
int num_rstcs;
|
||||
struct reset_control_bulk_data *rstcs;
|
||||
};
|
||||
|
||||
static void devm_reset_control_bulk_release(struct device *dev, void *res)
|
||||
{
|
||||
struct reset_control_bulk_devres *devres = res;
|
||||
|
||||
reset_control_bulk_put(devres->num_rstcs, devres->rstcs);
|
||||
}
|
||||
|
||||
int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs,
|
||||
bool shared, bool optional, bool acquired)
|
||||
{
|
||||
struct reset_control_bulk_devres *ptr;
|
||||
int ret;
|
||||
|
||||
ptr = devres_alloc(devm_reset_control_bulk_release, sizeof(*ptr),
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = __reset_control_bulk_get(dev, num_rstcs, rstcs, shared, optional, acquired);
|
||||
if (ret < 0) {
|
||||
devres_free(ptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ptr->num_rstcs = num_rstcs;
|
||||
ptr->rstcs = rstcs;
|
||||
devres_add(dev, ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__devm_reset_control_bulk_get);
|
||||
|
||||
/**
|
||||
* __device_reset - find reset controller associated with the device
|
||||
* and perform reset
|
||||
|
@ -1553,13 +1553,12 @@ static int spi_imx_slave_abort(struct spi_master *master)
|
||||
static int spi_imx_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(spi_imx_dt_ids, &pdev->dev);
|
||||
struct spi_master *master;
|
||||
struct spi_imx_data *spi_imx;
|
||||
struct resource *res;
|
||||
int ret, irq, spi_drctl;
|
||||
const struct spi_imx_devtype_data *devtype_data = of_id->data;
|
||||
const struct spi_imx_devtype_data *devtype_data =
|
||||
of_device_get_match_data(&pdev->dev);
|
||||
bool slave_mode;
|
||||
u32 val;
|
||||
|
||||
|
@ -1,12 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __PLATFORM_DATA_ASOC_MX27VIS_H
|
||||
#define __PLATFORM_DATA_ASOC_MX27VIS_H
|
||||
|
||||
struct snd_mx27vis_platform_data {
|
||||
int amp_gain0_gpio;
|
||||
int amp_gain1_gpio;
|
||||
int amp_mutel_gpio;
|
||||
int amp_muter_gpio;
|
||||
};
|
||||
|
||||
#endif /* __PLATFORM_DATA_ASOC_MX27VIS_H */
|
@ -10,6 +10,21 @@ struct device;
|
||||
struct device_node;
|
||||
struct reset_control;
|
||||
|
||||
/**
|
||||
* struct reset_control_bulk_data - Data used for bulk reset control operations.
|
||||
*
|
||||
* @id: reset control consumer ID
|
||||
* @rstc: struct reset_control * to store the associated reset control
|
||||
*
|
||||
* The reset APIs provide a series of reset_control_bulk_*() API calls as
|
||||
* a convenience to consumers which require multiple reset controls.
|
||||
* This structure is used to manage data for these calls.
|
||||
*/
|
||||
struct reset_control_bulk_data {
|
||||
const char *id;
|
||||
struct reset_control *rstc;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RESET_CONTROLLER
|
||||
|
||||
int reset_control_reset(struct reset_control *rstc);
|
||||
@ -20,6 +35,12 @@ int reset_control_status(struct reset_control *rstc);
|
||||
int reset_control_acquire(struct reset_control *rstc);
|
||||
void reset_control_release(struct reset_control *rstc);
|
||||
|
||||
int reset_control_bulk_reset(int num_rstcs, struct reset_control_bulk_data *rstcs);
|
||||
int reset_control_bulk_assert(int num_rstcs, struct reset_control_bulk_data *rstcs);
|
||||
int reset_control_bulk_deassert(int num_rstcs, struct reset_control_bulk_data *rstcs);
|
||||
int reset_control_bulk_acquire(int num_rstcs, struct reset_control_bulk_data *rstcs);
|
||||
void reset_control_bulk_release(int num_rstcs, struct reset_control_bulk_data *rstcs);
|
||||
|
||||
struct reset_control *__of_reset_control_get(struct device_node *node,
|
||||
const char *id, int index, bool shared,
|
||||
bool optional, bool acquired);
|
||||
@ -27,10 +48,18 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id,
|
||||
int index, bool shared,
|
||||
bool optional, bool acquired);
|
||||
void reset_control_put(struct reset_control *rstc);
|
||||
int __reset_control_bulk_get(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs,
|
||||
bool shared, bool optional, bool acquired);
|
||||
void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs);
|
||||
|
||||
int __device_reset(struct device *dev, bool optional);
|
||||
struct reset_control *__devm_reset_control_get(struct device *dev,
|
||||
const char *id, int index, bool shared,
|
||||
bool optional, bool acquired);
|
||||
int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs,
|
||||
bool shared, bool optional, bool acquired);
|
||||
|
||||
struct reset_control *devm_reset_control_array_get(struct device *dev,
|
||||
bool shared, bool optional);
|
||||
@ -96,6 +125,48 @@ static inline struct reset_control *__reset_control_get(
|
||||
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
static inline int
|
||||
reset_control_bulk_reset(int num_rstcs, struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
reset_control_bulk_assert(int num_rstcs, struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
reset_control_bulk_deassert(int num_rstcs, struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
reset_control_bulk_acquire(int num_rstcs, struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
reset_control_bulk_release(int num_rstcs, struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int
|
||||
__reset_control_bulk_get(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs,
|
||||
bool shared, bool optional, bool acquired)
|
||||
{
|
||||
return optional ? 0 : -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void
|
||||
reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct reset_control *__devm_reset_control_get(
|
||||
struct device *dev, const char *id,
|
||||
int index, bool shared, bool optional,
|
||||
@ -104,6 +175,14 @@ static inline struct reset_control *__devm_reset_control_get(
|
||||
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
static inline int
|
||||
__devm_reset_control_bulk_get(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs,
|
||||
bool shared, bool optional, bool acquired)
|
||||
{
|
||||
return optional ? 0 : -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline struct reset_control *
|
||||
devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
|
||||
{
|
||||
@ -155,6 +234,23 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id)
|
||||
return __reset_control_get(dev, id, 0, false, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* reset_control_bulk_get_exclusive - Lookup and obtain exclusive references to
|
||||
* multiple reset controllers.
|
||||
* @dev: device to be reset by the controller
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset line names set
|
||||
*
|
||||
* Fills the rstcs array with pointers to exclusive reset controls and
|
||||
* returns 0, or an IS_ERR() condition containing errno.
|
||||
*/
|
||||
static inline int __must_check
|
||||
reset_control_bulk_get_exclusive(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* reset_control_get_exclusive_released - Lookup and obtain a temoprarily
|
||||
* exclusive reference to a reset
|
||||
@ -176,6 +272,48 @@ __must_check reset_control_get_exclusive_released(struct device *dev,
|
||||
return __reset_control_get(dev, id, 0, false, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* reset_control_bulk_get_exclusive_released - Lookup and obtain temporarily
|
||||
* exclusive references to multiple reset
|
||||
* controllers.
|
||||
* @dev: device to be reset by the controller
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset line names set
|
||||
*
|
||||
* Fills the rstcs array with pointers to exclusive reset controls and
|
||||
* returns 0, or an IS_ERR() condition containing errno.
|
||||
* reset-controls returned by this function must be acquired via
|
||||
* reset_control_bulk_acquire() before they can be used and should be released
|
||||
* via reset_control_bulk_release() afterwards.
|
||||
*/
|
||||
static inline int __must_check
|
||||
reset_control_bulk_get_exclusive_released(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* reset_control_bulk_get_optional_exclusive_released - Lookup and obtain optional
|
||||
* temporarily exclusive references to multiple
|
||||
* reset controllers.
|
||||
* @dev: device to be reset by the controller
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset line names set
|
||||
*
|
||||
* Optional variant of reset_control_bulk_get_exclusive_released(). If the
|
||||
* requested reset is not specified in the device tree, this function returns 0
|
||||
* instead of an error and missing rtsc is set to NULL.
|
||||
*
|
||||
* See reset_control_bulk_get_exclusive_released() for more information.
|
||||
*/
|
||||
static inline int __must_check
|
||||
reset_control_bulk_get_optional_exclusive_released(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* reset_control_get_shared - Lookup and obtain a shared reference to a
|
||||
* reset controller.
|
||||
@ -204,6 +342,23 @@ static inline struct reset_control *reset_control_get_shared(
|
||||
return __reset_control_get(dev, id, 0, true, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* reset_control_bulk_get_shared - Lookup and obtain shared references to
|
||||
* multiple reset controllers.
|
||||
* @dev: device to be reset by the controller
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset line names set
|
||||
*
|
||||
* Fills the rstcs array with pointers to shared reset controls and
|
||||
* returns 0, or an IS_ERR() condition containing errno.
|
||||
*/
|
||||
static inline int __must_check
|
||||
reset_control_bulk_get_shared(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* reset_control_get_optional_exclusive - optional reset_control_get_exclusive()
|
||||
* @dev: device to be reset by the controller
|
||||
@ -221,6 +376,26 @@ static inline struct reset_control *reset_control_get_optional_exclusive(
|
||||
return __reset_control_get(dev, id, 0, false, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* reset_control_bulk_get_optional_exclusive - optional
|
||||
* reset_control_bulk_get_exclusive()
|
||||
* @dev: device to be reset by the controller
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset line names set
|
||||
*
|
||||
* Optional variant of reset_control_bulk_get_exclusive(). If any of the
|
||||
* requested resets are not specified in the device tree, this function sets
|
||||
* them to NULL instead of returning an error.
|
||||
*
|
||||
* See reset_control_bulk_get_exclusive() for more information.
|
||||
*/
|
||||
static inline int __must_check
|
||||
reset_control_bulk_get_optional_exclusive(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* reset_control_get_optional_shared - optional reset_control_get_shared()
|
||||
* @dev: device to be reset by the controller
|
||||
@ -238,6 +413,26 @@ static inline struct reset_control *reset_control_get_optional_shared(
|
||||
return __reset_control_get(dev, id, 0, true, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* reset_control_bulk_get_optional_shared - optional
|
||||
* reset_control_bulk_get_shared()
|
||||
* @dev: device to be reset by the controller
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset line names set
|
||||
*
|
||||
* Optional variant of reset_control_bulk_get_shared(). If the requested resets
|
||||
* are not specified in the device tree, this function sets them to NULL
|
||||
* instead of returning an error.
|
||||
*
|
||||
* See reset_control_bulk_get_shared() for more information.
|
||||
*/
|
||||
static inline int __must_check
|
||||
reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __reset_control_bulk_get(dev, num_rstcs, rstcs, true, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* of_reset_control_get_exclusive - Lookup and obtain an exclusive reference
|
||||
* to a reset controller.
|
||||
@ -343,6 +538,26 @@ __must_check devm_reset_control_get_exclusive(struct device *dev,
|
||||
return __devm_reset_control_get(dev, id, 0, false, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_bulk_get_exclusive - resource managed
|
||||
* reset_control_bulk_get_exclusive()
|
||||
* @dev: device to be reset by the controller
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset line names set
|
||||
*
|
||||
* Managed reset_control_bulk_get_exclusive(). For reset controllers returned
|
||||
* from this function, reset_control_put() is called automatically on driver
|
||||
* detach.
|
||||
*
|
||||
* See reset_control_bulk_get_exclusive() for more information.
|
||||
*/
|
||||
static inline int __must_check
|
||||
devm_reset_control_bulk_get_exclusive(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_exclusive_released - resource managed
|
||||
* reset_control_get_exclusive_released()
|
||||
@ -362,6 +577,26 @@ __must_check devm_reset_control_get_exclusive_released(struct device *dev,
|
||||
return __devm_reset_control_get(dev, id, 0, false, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_bulk_get_exclusive_released - resource managed
|
||||
* reset_control_bulk_get_exclusive_released()
|
||||
* @dev: device to be reset by the controller
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset line names set
|
||||
*
|
||||
* Managed reset_control_bulk_get_exclusive_released(). For reset controllers
|
||||
* returned from this function, reset_control_put() is called automatically on
|
||||
* driver detach.
|
||||
*
|
||||
* See reset_control_bulk_get_exclusive_released() for more information.
|
||||
*/
|
||||
static inline int __must_check
|
||||
devm_reset_control_bulk_get_exclusive_released(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_optional_exclusive_released - resource managed
|
||||
* reset_control_get_optional_exclusive_released()
|
||||
@ -381,6 +616,26 @@ __must_check devm_reset_control_get_optional_exclusive_released(struct device *d
|
||||
return __devm_reset_control_get(dev, id, 0, false, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_bulk_get_optional_exclusive_released - resource managed
|
||||
* reset_control_bulk_optional_get_exclusive_released()
|
||||
* @dev: device to be reset by the controller
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset line names set
|
||||
*
|
||||
* Managed reset_control_bulk_optional_get_exclusive_released(). For reset
|
||||
* controllers returned from this function, reset_control_put() is called
|
||||
* automatically on driver detach.
|
||||
*
|
||||
* See reset_control_bulk_optional_get_exclusive_released() for more information.
|
||||
*/
|
||||
static inline int __must_check
|
||||
devm_reset_control_bulk_get_optional_exclusive_released(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_shared - resource managed reset_control_get_shared()
|
||||
* @dev: device to be reset by the controller
|
||||
@ -396,6 +651,26 @@ static inline struct reset_control *devm_reset_control_get_shared(
|
||||
return __devm_reset_control_get(dev, id, 0, true, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_bulk_get_shared - resource managed
|
||||
* reset_control_bulk_get_shared()
|
||||
* @dev: device to be reset by the controller
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset line names set
|
||||
*
|
||||
* Managed reset_control_bulk_get_shared(). For reset controllers returned
|
||||
* from this function, reset_control_put() is called automatically on driver
|
||||
* detach.
|
||||
*
|
||||
* See reset_control_bulk_get_shared() for more information.
|
||||
*/
|
||||
static inline int __must_check
|
||||
devm_reset_control_bulk_get_shared(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_optional_exclusive - resource managed
|
||||
* reset_control_get_optional_exclusive()
|
||||
@ -414,6 +689,26 @@ static inline struct reset_control *devm_reset_control_get_optional_exclusive(
|
||||
return __devm_reset_control_get(dev, id, 0, false, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_bulk_get_optional_exclusive - resource managed
|
||||
* reset_control_bulk_get_optional_exclusive()
|
||||
* @dev: device to be reset by the controller
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset line names set
|
||||
*
|
||||
* Managed reset_control_bulk_get_optional_exclusive(). For reset controllers
|
||||
* returned from this function, reset_control_put() is called automatically on
|
||||
* driver detach.
|
||||
*
|
||||
* See reset_control_bulk_get_optional_exclusive() for more information.
|
||||
*/
|
||||
static inline int __must_check
|
||||
devm_reset_control_bulk_get_optional_exclusive(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_optional_shared - resource managed
|
||||
* reset_control_get_optional_shared()
|
||||
@ -432,6 +727,26 @@ static inline struct reset_control *devm_reset_control_get_optional_shared(
|
||||
return __devm_reset_control_get(dev, id, 0, true, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_bulk_get_optional_shared - resource managed
|
||||
* reset_control_bulk_get_optional_shared()
|
||||
* @dev: device to be reset by the controller
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset line names set
|
||||
*
|
||||
* Managed reset_control_bulk_get_optional_shared(). For reset controllers
|
||||
* returned from this function, reset_control_put() is called automatically on
|
||||
* driver detach.
|
||||
*
|
||||
* See reset_control_bulk_get_optional_shared() for more information.
|
||||
*/
|
||||
static inline int __must_check
|
||||
devm_reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_exclusive_by_index - resource managed
|
||||
* reset_control_get_exclusive()
|
||||
|
@ -24,7 +24,7 @@ typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol,
|
||||
|
||||
/* internal flag for skipping validations */
|
||||
#ifdef CONFIG_SND_CTL_VALIDATION
|
||||
#define SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK (1 << 27)
|
||||
#define SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK (1 << 24)
|
||||
#define snd_ctl_skip_validation(info) \
|
||||
((info)->access & SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK)
|
||||
#else
|
||||
@ -32,6 +32,12 @@ typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol,
|
||||
#define snd_ctl_skip_validation(info) true
|
||||
#endif
|
||||
|
||||
/* kernel only - LED bits */
|
||||
#define SNDRV_CTL_ELEM_ACCESS_LED_SHIFT 25
|
||||
#define SNDRV_CTL_ELEM_ACCESS_LED_MASK (7<<25) /* kernel three bits - LED group */
|
||||
#define SNDRV_CTL_ELEM_ACCESS_SPK_LED (1<<25) /* kernel speaker (output) LED flag */
|
||||
#define SNDRV_CTL_ELEM_ACCESS_MIC_LED (2<<25) /* kernel microphone (input) LED flag */
|
||||
|
||||
enum {
|
||||
SNDRV_CTL_TLV_OP_READ = 0,
|
||||
SNDRV_CTL_TLV_OP_WRITE = 1,
|
||||
@ -108,6 +114,14 @@ struct snd_ctl_file {
|
||||
struct list_head events; /* waiting events for read */
|
||||
};
|
||||
|
||||
struct snd_ctl_layer_ops {
|
||||
struct snd_ctl_layer_ops *next;
|
||||
const char *module_name;
|
||||
void (*lregister)(struct snd_card *card);
|
||||
void (*ldisconnect)(struct snd_card *card);
|
||||
void (*lnotify)(struct snd_card *card, unsigned int mask, struct snd_kcontrol *kctl, unsigned int ioff);
|
||||
};
|
||||
|
||||
#define snd_ctl_file(n) list_entry(n, struct snd_ctl_file, list)
|
||||
|
||||
typedef int (*snd_kctl_ioctl_func_t) (struct snd_card * card,
|
||||
@ -115,6 +129,7 @@ typedef int (*snd_kctl_ioctl_func_t) (struct snd_card * card,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
void snd_ctl_notify(struct snd_card * card, unsigned int mask, struct snd_ctl_elem_id * id);
|
||||
void snd_ctl_notify_one(struct snd_card * card, unsigned int mask, struct snd_kcontrol * kctl, unsigned int ioff);
|
||||
|
||||
struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, void * private_data);
|
||||
void snd_ctl_free_one(struct snd_kcontrol * kcontrol);
|
||||
@ -123,8 +138,7 @@ int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol);
|
||||
int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, bool add_on_replace);
|
||||
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);
|
||||
int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
|
||||
int active);
|
||||
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);
|
||||
|
||||
@ -140,6 +154,10 @@ int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
|
||||
#define snd_ctl_unregister_ioctl_compat(fcn)
|
||||
#endif
|
||||
|
||||
int snd_ctl_request_layer(const char *module_name);
|
||||
void snd_ctl_register_layer(struct snd_ctl_layer_ops *lops);
|
||||
void snd_ctl_disconnect_layer(struct snd_ctl_layer_ops *lops);
|
||||
|
||||
int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type);
|
||||
|
||||
static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
|
||||
@ -253,6 +271,17 @@ int snd_ctl_apply_vmaster_followers(struct snd_kcontrol *kctl,
|
||||
void *arg),
|
||||
void *arg);
|
||||
|
||||
/*
|
||||
* Control LED trigger layer
|
||||
*/
|
||||
#define SND_CTL_LAYER_MODULE_LED "snd-ctl-led"
|
||||
|
||||
#if IS_MODULE(CONFIG_SND_CTL_LED)
|
||||
static inline int snd_ctl_led_request(void) { return snd_ctl_request_layer(SND_CTL_LAYER_MODULE_LED); }
|
||||
#else
|
||||
static inline int snd_ctl_led_request(void) { return 0; }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper functions for jack-detection controls
|
||||
*/
|
||||
|
@ -100,7 +100,7 @@ struct snd_card {
|
||||
struct rw_semaphore controls_rwsem; /* controls list lock */
|
||||
rwlock_t ctl_files_rwlock; /* ctl_files list lock */
|
||||
int controls_count; /* count of all controls */
|
||||
int user_ctl_count; /* count of all user controls */
|
||||
size_t user_ctl_alloc_size; // current memory allocation by user controls.
|
||||
struct list_head controls; /* all controls for this card */
|
||||
struct list_head ctl_files; /* active control files */
|
||||
|
||||
|
@ -9,10 +9,6 @@
|
||||
|
||||
#include <sound/simple_card_utils.h>
|
||||
|
||||
int audio_graph_card_probe(struct snd_soc_card *card);
|
||||
|
||||
int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev);
|
||||
|
||||
int audio_graph_remove(struct platform_device *pdev);
|
||||
|
||||
#endif /* __GRAPH_CARD_H */
|
||||
|
@ -140,8 +140,12 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
|
||||
#define BDL_SIZE 4096
|
||||
#define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16)
|
||||
#define AZX_MAX_FRAG 32
|
||||
/* max buffer size - no h/w limit, you can increase as you like */
|
||||
#define AZX_MAX_BUF_SIZE (1024*1024*1024)
|
||||
/*
|
||||
* max buffer size - artificial 4MB limit per stream to avoid big allocations
|
||||
* In theory it can be really big, but as it is per stream on systems with many streams memory could
|
||||
* be quickly saturated if userspace requests maximum buffer size for each of them.
|
||||
*/
|
||||
#define AZX_MAX_BUF_SIZE (4*1024*1024)
|
||||
|
||||
/* RIRB int mask: overrun[2], response[0] */
|
||||
#define RIRB_INT_RESPONSE 0x01
|
||||
|
@ -1,32 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* linux/sound/rt5645.h -- Platform data for RT5645
|
||||
*
|
||||
* Copyright 2013 Realtek Microelectronics
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_SND_RT5645_H
|
||||
#define __LINUX_SND_RT5645_H
|
||||
|
||||
struct rt5645_platform_data {
|
||||
/* IN2 can optionally be differential */
|
||||
bool in2_diff;
|
||||
|
||||
unsigned int dmic1_data_pin;
|
||||
/* 0 = IN2N; 1 = GPIO5; 2 = GPIO11 */
|
||||
unsigned int dmic2_data_pin;
|
||||
/* 0 = IN2P; 1 = GPIO6; 2 = GPIO10; 3 = GPIO12 */
|
||||
|
||||
unsigned int jd_mode;
|
||||
/* Use level triggered irq */
|
||||
bool level_trigger_irq;
|
||||
/* Invert JD1_1 status polarity */
|
||||
bool inv_jd1_1;
|
||||
/* Invert HP detect status polarity */
|
||||
bool inv_hp_pol;
|
||||
|
||||
/* Value to asign to snd_soc_card.long_name */
|
||||
const char *long_name;
|
||||
};
|
||||
|
||||
#endif
|
@ -38,22 +38,31 @@ struct asoc_simple_jack {
|
||||
struct snd_soc_jack_gpio gpio;
|
||||
};
|
||||
|
||||
struct prop_nums {
|
||||
int cpus;
|
||||
int codecs;
|
||||
int platforms;
|
||||
};
|
||||
|
||||
struct asoc_simple_priv {
|
||||
struct snd_soc_card snd_card;
|
||||
struct simple_dai_props {
|
||||
struct asoc_simple_dai *cpu_dai;
|
||||
struct asoc_simple_dai *codec_dai;
|
||||
struct snd_soc_dai_link_component cpus; /* single cpu */
|
||||
struct snd_soc_dai_link_component codecs; /* single codec */
|
||||
struct snd_soc_dai_link_component platforms;
|
||||
struct snd_soc_dai_link_component *cpus;
|
||||
struct snd_soc_dai_link_component *codecs;
|
||||
struct snd_soc_dai_link_component *platforms;
|
||||
struct asoc_simple_data adata;
|
||||
struct snd_soc_codec_conf *codec_conf;
|
||||
struct prop_nums num;
|
||||
unsigned int mclk_fs;
|
||||
} *dai_props;
|
||||
struct asoc_simple_jack hp_jack;
|
||||
struct asoc_simple_jack mic_jack;
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
struct asoc_simple_dai *dais;
|
||||
struct snd_soc_dai_link_component *dlcs;
|
||||
struct snd_soc_dai_link_component dummy;
|
||||
struct snd_soc_codec_conf *codec_conf;
|
||||
struct gpio_desc *pa_gpio;
|
||||
const struct snd_soc_ops *ops;
|
||||
@ -65,11 +74,53 @@ struct asoc_simple_priv {
|
||||
#define simple_priv_to_dev(priv) (simple_priv_to_card(priv)->dev)
|
||||
#define simple_priv_to_link(priv, i) (simple_priv_to_card(priv)->dai_link + (i))
|
||||
|
||||
#define simple_props_to_dlc_cpu(props, i) ((props)->cpus + i)
|
||||
#define simple_props_to_dlc_codec(props, i) ((props)->codecs + i)
|
||||
#define simple_props_to_dlc_platform(props, i) ((props)->platforms + i)
|
||||
|
||||
#define simple_props_to_dai_cpu(props, i) ((props)->cpu_dai + i)
|
||||
#define simple_props_to_dai_codec(props, i) ((props)->codec_dai + i)
|
||||
#define simple_props_to_codec_conf(props, i) ((props)->codec_conf + i)
|
||||
|
||||
#define for_each_prop_dlc_cpus(props, i, cpu) \
|
||||
for ((i) = 0; \
|
||||
((i) < (props)->num.cpus) && \
|
||||
((cpu) = simple_props_to_dlc_cpu(props, i)); \
|
||||
(i)++)
|
||||
#define for_each_prop_dlc_codecs(props, i, codec) \
|
||||
for ((i) = 0; \
|
||||
((i) < (props)->num.codecs) && \
|
||||
((codec) = simple_props_to_dlc_codec(props, i)); \
|
||||
(i)++)
|
||||
#define for_each_prop_dlc_platforms(props, i, platform) \
|
||||
for ((i) = 0; \
|
||||
((i) < (props)->num.platforms) && \
|
||||
((platform) = simple_props_to_dlc_platform(props, i)); \
|
||||
(i)++)
|
||||
#define for_each_prop_codec_conf(props, i, conf) \
|
||||
for ((i) = 0; \
|
||||
((i) < (props)->num.codecs) && \
|
||||
(props)->codec_conf && \
|
||||
((conf) = simple_props_to_codec_conf(props, i)); \
|
||||
(i)++)
|
||||
|
||||
#define for_each_prop_dai_cpu(props, i, cpu) \
|
||||
for ((i) = 0; \
|
||||
((i) < (props)->num.cpus) && \
|
||||
((cpu) = simple_props_to_dai_cpu(props, i)); \
|
||||
(i)++)
|
||||
#define for_each_prop_dai_codec(props, i, codec) \
|
||||
for ((i) = 0; \
|
||||
((i) < (props)->num.codecs) && \
|
||||
((codec) = simple_props_to_dai_codec(props, i)); \
|
||||
(i)++)
|
||||
|
||||
#define SNDRV_MAX_LINKS 128
|
||||
|
||||
struct link_info {
|
||||
int dais; /* number of dai */
|
||||
int link; /* number of link */
|
||||
int conf; /* number of codec_conf */
|
||||
int cpu; /* turn for CPU / Codec */
|
||||
struct prop_nums num[SNDRV_MAX_LINKS];
|
||||
};
|
||||
|
||||
int asoc_simple_parse_daifmt(struct device *dev,
|
||||
@ -84,10 +135,6 @@ int asoc_simple_set_dailink_name(struct device *dev,
|
||||
int asoc_simple_parse_card_name(struct snd_soc_card *card,
|
||||
char *prefix);
|
||||
|
||||
#define asoc_simple_parse_clk_cpu(dev, node, dai_link, simple_dai) \
|
||||
asoc_simple_parse_clk(dev, node, simple_dai, dai_link->cpus)
|
||||
#define asoc_simple_parse_clk_codec(dev, node, dai_link, simple_dai) \
|
||||
asoc_simple_parse_clk(dev, node, simple_dai, dai_link->codecs)
|
||||
int asoc_simple_parse_clk(struct device *dev,
|
||||
struct device_node *node,
|
||||
struct asoc_simple_dai *simple_dai,
|
||||
@ -100,29 +147,22 @@ int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd);
|
||||
int asoc_simple_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hw_params *params);
|
||||
|
||||
#define asoc_simple_parse_cpu(node, dai_link, is_single_link) \
|
||||
asoc_simple_parse_dai(node, dai_link->cpus, is_single_link)
|
||||
#define asoc_simple_parse_codec(node, dai_link) \
|
||||
asoc_simple_parse_dai(node, dai_link->codecs, NULL)
|
||||
#define asoc_simple_parse_platform(node, dai_link) \
|
||||
asoc_simple_parse_dai(node, dai_link->platforms, NULL)
|
||||
|
||||
#define asoc_simple_parse_tdm(np, dai) \
|
||||
snd_soc_of_parse_tdm_slot(np, &(dai)->tx_slot_mask, \
|
||||
&(dai)->rx_slot_mask, \
|
||||
&(dai)->slots, \
|
||||
&(dai)->slot_width);
|
||||
|
||||
void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link);
|
||||
void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link *dai_link,
|
||||
int is_single_links);
|
||||
void asoc_simple_canonicalize_platform(struct snd_soc_dai_link_component *platforms,
|
||||
struct snd_soc_dai_link_component *cpus);
|
||||
void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link_component *cpus,
|
||||
int is_single_links);
|
||||
|
||||
int asoc_simple_clean_reference(struct snd_soc_card *card);
|
||||
|
||||
void asoc_simple_convert_fixup(struct asoc_simple_data *data,
|
||||
struct snd_pcm_hw_params *params);
|
||||
void asoc_simple_parse_convert(struct device *dev,
|
||||
struct device_node *np, char *prefix,
|
||||
void asoc_simple_parse_convert(struct device_node *np, char *prefix,
|
||||
struct asoc_simple_data *data);
|
||||
|
||||
int asoc_simple_parse_routing(struct snd_soc_card *card,
|
||||
@ -137,6 +177,9 @@ int asoc_simple_init_jack(struct snd_soc_card *card,
|
||||
int is_hp, char *prefix, char *pin);
|
||||
int asoc_simple_init_priv(struct asoc_simple_priv *priv,
|
||||
struct link_info *li);
|
||||
int asoc_simple_remove(struct platform_device *pdev);
|
||||
|
||||
int asoc_graph_card_probe(struct snd_soc_card *card);
|
||||
|
||||
#ifdef DEBUG
|
||||
static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
|
||||
@ -152,12 +195,6 @@ static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
|
||||
if (dai->name)
|
||||
dev_dbg(dev, "%s dai name = %s\n",
|
||||
name, dai->name);
|
||||
if (dai->sysclk)
|
||||
dev_dbg(dev, "%s sysclk = %d\n",
|
||||
name, dai->sysclk);
|
||||
|
||||
dev_dbg(dev, "%s direction = %s\n",
|
||||
name, dai->clk_direction ? "OUT" : "IN");
|
||||
|
||||
if (dai->slots)
|
||||
dev_dbg(dev, "%s slots = %d\n", name, dai->slots);
|
||||
@ -169,6 +206,12 @@ static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
|
||||
dev_dbg(dev, "%s rx slot mask = %d\n", name, dai->rx_slot_mask);
|
||||
if (dai->clk)
|
||||
dev_dbg(dev, "%s clk %luHz\n", name, clk_get_rate(dai->clk));
|
||||
if (dai->sysclk)
|
||||
dev_dbg(dev, "%s sysclk = %dHz\n",
|
||||
name, dai->sysclk);
|
||||
if (dai->clk || dai->sysclk)
|
||||
dev_dbg(dev, "%s direction = %s\n",
|
||||
name, dai->clk_direction ? "OUT" : "IN");
|
||||
}
|
||||
|
||||
static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv)
|
||||
@ -184,29 +227,32 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv)
|
||||
for (i = 0; i < card->num_links; i++) {
|
||||
struct simple_dai_props *props = simple_priv_to_props(priv, i);
|
||||
struct snd_soc_dai_link *link = simple_priv_to_link(priv, i);
|
||||
struct asoc_simple_dai *dai;
|
||||
struct snd_soc_codec_conf *cnf;
|
||||
int j;
|
||||
|
||||
dev_dbg(dev, "DAI%d\n", i);
|
||||
|
||||
asoc_simple_debug_dai(priv, "cpu", props->cpu_dai);
|
||||
asoc_simple_debug_dai(priv, "codec", props->codec_dai);
|
||||
dev_dbg(dev, "cpu num = %d\n", link->num_cpus);
|
||||
for_each_prop_dai_cpu(props, j, dai)
|
||||
asoc_simple_debug_dai(priv, "cpu", dai);
|
||||
dev_dbg(dev, "codec num = %d\n", link->num_codecs);
|
||||
for_each_prop_dai_codec(props, j, dai)
|
||||
asoc_simple_debug_dai(priv, "codec", dai);
|
||||
|
||||
if (link->name)
|
||||
dev_dbg(dev, "dai name = %s\n", link->name);
|
||||
|
||||
dev_dbg(dev, "dai format = %04x\n", link->dai_fmt);
|
||||
|
||||
if (link->dai_fmt)
|
||||
dev_dbg(dev, "dai format = %04x\n", link->dai_fmt);
|
||||
if (props->adata.convert_rate)
|
||||
dev_dbg(dev, "convert_rate = %d\n",
|
||||
props->adata.convert_rate);
|
||||
dev_dbg(dev, "convert_rate = %d\n", props->adata.convert_rate);
|
||||
if (props->adata.convert_channels)
|
||||
dev_dbg(dev, "convert_channels = %d\n",
|
||||
props->adata.convert_channels);
|
||||
if (props->codec_conf && props->codec_conf->name_prefix)
|
||||
dev_dbg(dev, "name prefix = %s\n",
|
||||
props->codec_conf->name_prefix);
|
||||
dev_dbg(dev, "convert_channels = %d\n", props->adata.convert_channels);
|
||||
for_each_prop_codec_conf(props, j, cnf)
|
||||
if (cnf->name_prefix)
|
||||
dev_dbg(dev, "name prefix = %s\n", cnf->name_prefix);
|
||||
if (props->mclk_fs)
|
||||
dev_dbg(dev, "mclk-fs = %d\n",
|
||||
props->mclk_fs);
|
||||
dev_dbg(dev, "mclk-fs = %d\n", props->mclk_fs);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -63,6 +63,8 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
|
||||
* @common_hdmi_codec_drv: use commom HDAudio HDMI codec driver
|
||||
* @link_mask: links enabled on the board
|
||||
* @links: array of link _ADR descriptors, null terminated
|
||||
* @num_dai_drivers: number of elements in @dai_drivers
|
||||
* @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode
|
||||
*/
|
||||
struct snd_soc_acpi_mach_params {
|
||||
u32 acpi_ipc_irq_index;
|
||||
@ -72,6 +74,8 @@ struct snd_soc_acpi_mach_params {
|
||||
bool common_hdmi_codec_drv;
|
||||
u32 link_mask;
|
||||
const struct snd_soc_acpi_link_adr *links;
|
||||
u32 num_dai_drivers;
|
||||
struct snd_soc_dai_driver *dai_drivers;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -101,7 +101,7 @@ struct snd_soc_component_driver {
|
||||
|
||||
/* DT */
|
||||
int (*of_xlate_dai_name)(struct snd_soc_component *component,
|
||||
struct of_phandle_args *args,
|
||||
const struct of_phandle_args *args,
|
||||
const char **dai_name);
|
||||
int (*of_xlate_dai_id)(struct snd_soc_component *comment,
|
||||
struct device_node *endpoint);
|
||||
@ -146,6 +146,8 @@ struct snd_soc_component_driver {
|
||||
int (*mmap)(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct vm_area_struct *vma);
|
||||
int (*ack)(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream);
|
||||
|
||||
const struct snd_compress_ops *compress_ops;
|
||||
|
||||
@ -336,6 +338,7 @@ static inline int snd_soc_component_cache_sync(
|
||||
void snd_soc_component_set_aux(struct snd_soc_component *component,
|
||||
struct snd_soc_aux_dev *aux);
|
||||
int snd_soc_component_init(struct snd_soc_component *component);
|
||||
int snd_soc_component_is_dummy(struct snd_soc_component *component);
|
||||
|
||||
/* component IO */
|
||||
unsigned int snd_soc_component_read(struct snd_soc_component *component,
|
||||
@ -450,7 +453,7 @@ void snd_soc_component_remove(struct snd_soc_component *component);
|
||||
int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component,
|
||||
struct device_node *ep);
|
||||
int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component,
|
||||
struct of_phandle_args *args,
|
||||
const struct of_phandle_args *args,
|
||||
const char **dai_name);
|
||||
int snd_soc_component_compr_open(struct snd_compr_stream *cstream);
|
||||
void snd_soc_component_compr_free(struct snd_compr_stream *cstream,
|
||||
@ -498,5 +501,6 @@ int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,
|
||||
void *stream);
|
||||
void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
|
||||
void *stream, int rollback);
|
||||
int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream);
|
||||
|
||||
#endif /* __SOC_COMPONENT_H */
|
||||
|
@ -149,14 +149,20 @@ void dpcm_path_put(struct snd_soc_dapm_widget_list **list);
|
||||
int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
|
||||
int stream, struct snd_soc_dapm_widget_list **list, int new);
|
||||
int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream);
|
||||
int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream);
|
||||
void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream,
|
||||
int do_hw_free, struct snd_soc_dpcm *last);
|
||||
void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream);
|
||||
void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream);
|
||||
int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream);
|
||||
void dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream);
|
||||
int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int tream);
|
||||
int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd);
|
||||
int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream);
|
||||
int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
|
||||
int event);
|
||||
|
||||
#define dpcm_be_dai_startup_rollback(fe, stream, last) \
|
||||
dpcm_be_dai_stop(fe, stream, 0, last)
|
||||
#define dpcm_be_dai_startup_unwind(fe, stream) dpcm_be_dai_stop(fe, stream, 0, NULL)
|
||||
#define dpcm_be_dai_shutdown(fe, stream) dpcm_be_dai_stop(fe, stream, 1, NULL)
|
||||
|
||||
#endif
|
||||
|
@ -716,20 +716,38 @@ struct snd_soc_dai_link {
|
||||
struct snd_soc_dobj dobj; /* For topology */
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline struct snd_soc_dai_link_component*
|
||||
asoc_link_to_cpu(struct snd_soc_dai_link *link, int n) {
|
||||
return &(link)->cpus[n];
|
||||
}
|
||||
|
||||
static inline struct snd_soc_dai_link_component*
|
||||
asoc_link_to_codec(struct snd_soc_dai_link *link, int n) {
|
||||
return &(link)->codecs[n];
|
||||
}
|
||||
|
||||
static inline struct snd_soc_dai_link_component*
|
||||
asoc_link_to_platform(struct snd_soc_dai_link *link, int n) {
|
||||
return &(link)->platforms[n];
|
||||
}
|
||||
|
||||
#define for_each_link_codecs(link, i, codec) \
|
||||
for ((i) = 0; \
|
||||
((i) < link->num_codecs) && ((codec) = &link->codecs[i]); \
|
||||
((i) < link->num_codecs) && \
|
||||
((codec) = asoc_link_to_codec(link, i)); \
|
||||
(i)++)
|
||||
|
||||
#define for_each_link_platforms(link, i, platform) \
|
||||
for ((i) = 0; \
|
||||
((i) < link->num_platforms) && \
|
||||
((platform) = &link->platforms[i]); \
|
||||
((platform) = asoc_link_to_platform(link, i)); \
|
||||
(i)++)
|
||||
|
||||
#define for_each_link_cpus(link, i, cpu) \
|
||||
for ((i) = 0; \
|
||||
((i) < link->num_cpus) && ((cpu) = &link->cpus[i]); \
|
||||
((i) < link->num_cpus) && \
|
||||
((cpu) = asoc_link_to_cpu(link, i)); \
|
||||
(i)++)
|
||||
|
||||
/*
|
||||
@ -1219,7 +1237,7 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
|
||||
struct device_node **bitclkmaster,
|
||||
struct device_node **framemaster);
|
||||
int snd_soc_get_dai_id(struct device_node *ep);
|
||||
int snd_soc_get_dai_name(struct of_phandle_args *args,
|
||||
int snd_soc_get_dai_name(const struct of_phandle_args *args,
|
||||
const char **dai_name);
|
||||
int snd_soc_of_get_dai_name(struct device_node *of_node,
|
||||
const char **dai_name);
|
||||
@ -1262,13 +1280,17 @@ int snd_soc_fixup_dai_links_platform_name(struct snd_soc_card *card,
|
||||
|
||||
/* set platform name for each dailink */
|
||||
for_each_card_prelinks(card, i, dai_link) {
|
||||
name = devm_kstrdup(card->dev, platform_name, GFP_KERNEL);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
/* only single platform is supported for now */
|
||||
if (dai_link->num_platforms != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (!dai_link->platforms)
|
||||
return -EINVAL;
|
||||
|
||||
name = devm_kstrdup(card->dev, platform_name, GFP_KERNEL);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
/* only single platform is supported for now */
|
||||
dai_link->platforms->name = name;
|
||||
}
|
||||
|
@ -100,8 +100,6 @@ struct sof_dev_desc {
|
||||
const struct snd_sof_dsp_ops *ops;
|
||||
};
|
||||
|
||||
int sof_nocodec_setup(struct device *dev, const struct snd_sof_dsp_ops *ops,
|
||||
int (*pcm_dai_link_fixup)(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hw_params *params));
|
||||
int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd);
|
||||
|
||||
#endif
|
||||
|
@ -51,6 +51,7 @@
|
||||
#define VIRTIO_ID_PSTORE 22 /* virtio pstore device */
|
||||
#define VIRTIO_ID_IOMMU 23 /* virtio IOMMU */
|
||||
#define VIRTIO_ID_MEM 24 /* virtio mem */
|
||||
#define VIRTIO_ID_SOUND 25 /* virtio sound */
|
||||
#define VIRTIO_ID_FS 26 /* virtio filesystem */
|
||||
#define VIRTIO_ID_PMEM 27 /* virtio pmem */
|
||||
#define VIRTIO_ID_BT 28 /* virtio bluetooth */
|
||||
|
334
include/uapi/linux/virtio_snd.h
Normal file
334
include/uapi/linux/virtio_snd.h
Normal file
@ -0,0 +1,334 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2021 OpenSynergy GmbH
|
||||
*/
|
||||
#ifndef VIRTIO_SND_IF_H
|
||||
#define VIRTIO_SND_IF_H
|
||||
|
||||
#include <linux/virtio_types.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* CONFIGURATION SPACE
|
||||
*/
|
||||
struct virtio_snd_config {
|
||||
/* # of available physical jacks */
|
||||
__le32 jacks;
|
||||
/* # of available PCM streams */
|
||||
__le32 streams;
|
||||
/* # of available channel maps */
|
||||
__le32 chmaps;
|
||||
};
|
||||
|
||||
enum {
|
||||
/* device virtqueue indexes */
|
||||
VIRTIO_SND_VQ_CONTROL = 0,
|
||||
VIRTIO_SND_VQ_EVENT,
|
||||
VIRTIO_SND_VQ_TX,
|
||||
VIRTIO_SND_VQ_RX,
|
||||
/* # of device virtqueues */
|
||||
VIRTIO_SND_VQ_MAX
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* COMMON DEFINITIONS
|
||||
*/
|
||||
|
||||
/* supported dataflow directions */
|
||||
enum {
|
||||
VIRTIO_SND_D_OUTPUT = 0,
|
||||
VIRTIO_SND_D_INPUT
|
||||
};
|
||||
|
||||
enum {
|
||||
/* jack control request types */
|
||||
VIRTIO_SND_R_JACK_INFO = 1,
|
||||
VIRTIO_SND_R_JACK_REMAP,
|
||||
|
||||
/* PCM control request types */
|
||||
VIRTIO_SND_R_PCM_INFO = 0x0100,
|
||||
VIRTIO_SND_R_PCM_SET_PARAMS,
|
||||
VIRTIO_SND_R_PCM_PREPARE,
|
||||
VIRTIO_SND_R_PCM_RELEASE,
|
||||
VIRTIO_SND_R_PCM_START,
|
||||
VIRTIO_SND_R_PCM_STOP,
|
||||
|
||||
/* channel map control request types */
|
||||
VIRTIO_SND_R_CHMAP_INFO = 0x0200,
|
||||
|
||||
/* jack event types */
|
||||
VIRTIO_SND_EVT_JACK_CONNECTED = 0x1000,
|
||||
VIRTIO_SND_EVT_JACK_DISCONNECTED,
|
||||
|
||||
/* PCM event types */
|
||||
VIRTIO_SND_EVT_PCM_PERIOD_ELAPSED = 0x1100,
|
||||
VIRTIO_SND_EVT_PCM_XRUN,
|
||||
|
||||
/* common status codes */
|
||||
VIRTIO_SND_S_OK = 0x8000,
|
||||
VIRTIO_SND_S_BAD_MSG,
|
||||
VIRTIO_SND_S_NOT_SUPP,
|
||||
VIRTIO_SND_S_IO_ERR
|
||||
};
|
||||
|
||||
/* common header */
|
||||
struct virtio_snd_hdr {
|
||||
__le32 code;
|
||||
};
|
||||
|
||||
/* event notification */
|
||||
struct virtio_snd_event {
|
||||
/* VIRTIO_SND_EVT_XXX */
|
||||
struct virtio_snd_hdr hdr;
|
||||
/* optional event data */
|
||||
__le32 data;
|
||||
};
|
||||
|
||||
/* common control request to query an item information */
|
||||
struct virtio_snd_query_info {
|
||||
/* VIRTIO_SND_R_XXX_INFO */
|
||||
struct virtio_snd_hdr hdr;
|
||||
/* item start identifier */
|
||||
__le32 start_id;
|
||||
/* item count to query */
|
||||
__le32 count;
|
||||
/* item information size in bytes */
|
||||
__le32 size;
|
||||
};
|
||||
|
||||
/* common item information header */
|
||||
struct virtio_snd_info {
|
||||
/* function group node id (High Definition Audio Specification 7.1.2) */
|
||||
__le32 hda_fn_nid;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* JACK CONTROL MESSAGES
|
||||
*/
|
||||
struct virtio_snd_jack_hdr {
|
||||
/* VIRTIO_SND_R_JACK_XXX */
|
||||
struct virtio_snd_hdr hdr;
|
||||
/* 0 ... virtio_snd_config::jacks - 1 */
|
||||
__le32 jack_id;
|
||||
};
|
||||
|
||||
/* supported jack features */
|
||||
enum {
|
||||
VIRTIO_SND_JACK_F_REMAP = 0
|
||||
};
|
||||
|
||||
struct virtio_snd_jack_info {
|
||||
/* common header */
|
||||
struct virtio_snd_info hdr;
|
||||
/* supported feature bit map (1 << VIRTIO_SND_JACK_F_XXX) */
|
||||
__le32 features;
|
||||
/* pin configuration (High Definition Audio Specification 7.3.3.31) */
|
||||
__le32 hda_reg_defconf;
|
||||
/* pin capabilities (High Definition Audio Specification 7.3.4.9) */
|
||||
__le32 hda_reg_caps;
|
||||
/* current jack connection status (0: disconnected, 1: connected) */
|
||||
__u8 connected;
|
||||
|
||||
__u8 padding[7];
|
||||
};
|
||||
|
||||
/* jack remapping control request */
|
||||
struct virtio_snd_jack_remap {
|
||||
/* .code = VIRTIO_SND_R_JACK_REMAP */
|
||||
struct virtio_snd_jack_hdr hdr;
|
||||
/* selected association number */
|
||||
__le32 association;
|
||||
/* selected sequence number */
|
||||
__le32 sequence;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* PCM CONTROL MESSAGES
|
||||
*/
|
||||
struct virtio_snd_pcm_hdr {
|
||||
/* VIRTIO_SND_R_PCM_XXX */
|
||||
struct virtio_snd_hdr hdr;
|
||||
/* 0 ... virtio_snd_config::streams - 1 */
|
||||
__le32 stream_id;
|
||||
};
|
||||
|
||||
/* supported PCM stream features */
|
||||
enum {
|
||||
VIRTIO_SND_PCM_F_SHMEM_HOST = 0,
|
||||
VIRTIO_SND_PCM_F_SHMEM_GUEST,
|
||||
VIRTIO_SND_PCM_F_MSG_POLLING,
|
||||
VIRTIO_SND_PCM_F_EVT_SHMEM_PERIODS,
|
||||
VIRTIO_SND_PCM_F_EVT_XRUNS
|
||||
};
|
||||
|
||||
/* supported PCM sample formats */
|
||||
enum {
|
||||
/* analog formats (width / physical width) */
|
||||
VIRTIO_SND_PCM_FMT_IMA_ADPCM = 0, /* 4 / 4 bits */
|
||||
VIRTIO_SND_PCM_FMT_MU_LAW, /* 8 / 8 bits */
|
||||
VIRTIO_SND_PCM_FMT_A_LAW, /* 8 / 8 bits */
|
||||
VIRTIO_SND_PCM_FMT_S8, /* 8 / 8 bits */
|
||||
VIRTIO_SND_PCM_FMT_U8, /* 8 / 8 bits */
|
||||
VIRTIO_SND_PCM_FMT_S16, /* 16 / 16 bits */
|
||||
VIRTIO_SND_PCM_FMT_U16, /* 16 / 16 bits */
|
||||
VIRTIO_SND_PCM_FMT_S18_3, /* 18 / 24 bits */
|
||||
VIRTIO_SND_PCM_FMT_U18_3, /* 18 / 24 bits */
|
||||
VIRTIO_SND_PCM_FMT_S20_3, /* 20 / 24 bits */
|
||||
VIRTIO_SND_PCM_FMT_U20_3, /* 20 / 24 bits */
|
||||
VIRTIO_SND_PCM_FMT_S24_3, /* 24 / 24 bits */
|
||||
VIRTIO_SND_PCM_FMT_U24_3, /* 24 / 24 bits */
|
||||
VIRTIO_SND_PCM_FMT_S20, /* 20 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_U20, /* 20 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_S24, /* 24 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_U24, /* 24 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_S32, /* 32 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_U32, /* 32 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_FLOAT, /* 32 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_FLOAT64, /* 64 / 64 bits */
|
||||
/* digital formats (width / physical width) */
|
||||
VIRTIO_SND_PCM_FMT_DSD_U8, /* 8 / 8 bits */
|
||||
VIRTIO_SND_PCM_FMT_DSD_U16, /* 16 / 16 bits */
|
||||
VIRTIO_SND_PCM_FMT_DSD_U32, /* 32 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_IEC958_SUBFRAME /* 32 / 32 bits */
|
||||
};
|
||||
|
||||
/* supported PCM frame rates */
|
||||
enum {
|
||||
VIRTIO_SND_PCM_RATE_5512 = 0,
|
||||
VIRTIO_SND_PCM_RATE_8000,
|
||||
VIRTIO_SND_PCM_RATE_11025,
|
||||
VIRTIO_SND_PCM_RATE_16000,
|
||||
VIRTIO_SND_PCM_RATE_22050,
|
||||
VIRTIO_SND_PCM_RATE_32000,
|
||||
VIRTIO_SND_PCM_RATE_44100,
|
||||
VIRTIO_SND_PCM_RATE_48000,
|
||||
VIRTIO_SND_PCM_RATE_64000,
|
||||
VIRTIO_SND_PCM_RATE_88200,
|
||||
VIRTIO_SND_PCM_RATE_96000,
|
||||
VIRTIO_SND_PCM_RATE_176400,
|
||||
VIRTIO_SND_PCM_RATE_192000,
|
||||
VIRTIO_SND_PCM_RATE_384000
|
||||
};
|
||||
|
||||
struct virtio_snd_pcm_info {
|
||||
/* common header */
|
||||
struct virtio_snd_info hdr;
|
||||
/* supported feature bit map (1 << VIRTIO_SND_PCM_F_XXX) */
|
||||
__le32 features;
|
||||
/* supported sample format bit map (1 << VIRTIO_SND_PCM_FMT_XXX) */
|
||||
__le64 formats;
|
||||
/* supported frame rate bit map (1 << VIRTIO_SND_PCM_RATE_XXX) */
|
||||
__le64 rates;
|
||||
/* dataflow direction (VIRTIO_SND_D_XXX) */
|
||||
__u8 direction;
|
||||
/* minimum # of supported channels */
|
||||
__u8 channels_min;
|
||||
/* maximum # of supported channels */
|
||||
__u8 channels_max;
|
||||
|
||||
__u8 padding[5];
|
||||
};
|
||||
|
||||
/* set PCM stream format */
|
||||
struct virtio_snd_pcm_set_params {
|
||||
/* .code = VIRTIO_SND_R_PCM_SET_PARAMS */
|
||||
struct virtio_snd_pcm_hdr hdr;
|
||||
/* size of the hardware buffer */
|
||||
__le32 buffer_bytes;
|
||||
/* size of the hardware period */
|
||||
__le32 period_bytes;
|
||||
/* selected feature bit map (1 << VIRTIO_SND_PCM_F_XXX) */
|
||||
__le32 features;
|
||||
/* selected # of channels */
|
||||
__u8 channels;
|
||||
/* selected sample format (VIRTIO_SND_PCM_FMT_XXX) */
|
||||
__u8 format;
|
||||
/* selected frame rate (VIRTIO_SND_PCM_RATE_XXX) */
|
||||
__u8 rate;
|
||||
|
||||
__u8 padding;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* PCM I/O MESSAGES
|
||||
*/
|
||||
|
||||
/* I/O request header */
|
||||
struct virtio_snd_pcm_xfer {
|
||||
/* 0 ... virtio_snd_config::streams - 1 */
|
||||
__le32 stream_id;
|
||||
};
|
||||
|
||||
/* I/O request status */
|
||||
struct virtio_snd_pcm_status {
|
||||
/* VIRTIO_SND_S_XXX */
|
||||
__le32 status;
|
||||
/* current device latency */
|
||||
__le32 latency_bytes;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* CHANNEL MAP CONTROL MESSAGES
|
||||
*/
|
||||
struct virtio_snd_chmap_hdr {
|
||||
/* VIRTIO_SND_R_CHMAP_XXX */
|
||||
struct virtio_snd_hdr hdr;
|
||||
/* 0 ... virtio_snd_config::chmaps - 1 */
|
||||
__le32 chmap_id;
|
||||
};
|
||||
|
||||
/* standard channel position definition */
|
||||
enum {
|
||||
VIRTIO_SND_CHMAP_NONE = 0, /* undefined */
|
||||
VIRTIO_SND_CHMAP_NA, /* silent */
|
||||
VIRTIO_SND_CHMAP_MONO, /* mono stream */
|
||||
VIRTIO_SND_CHMAP_FL, /* front left */
|
||||
VIRTIO_SND_CHMAP_FR, /* front right */
|
||||
VIRTIO_SND_CHMAP_RL, /* rear left */
|
||||
VIRTIO_SND_CHMAP_RR, /* rear right */
|
||||
VIRTIO_SND_CHMAP_FC, /* front center */
|
||||
VIRTIO_SND_CHMAP_LFE, /* low frequency (LFE) */
|
||||
VIRTIO_SND_CHMAP_SL, /* side left */
|
||||
VIRTIO_SND_CHMAP_SR, /* side right */
|
||||
VIRTIO_SND_CHMAP_RC, /* rear center */
|
||||
VIRTIO_SND_CHMAP_FLC, /* front left center */
|
||||
VIRTIO_SND_CHMAP_FRC, /* front right center */
|
||||
VIRTIO_SND_CHMAP_RLC, /* rear left center */
|
||||
VIRTIO_SND_CHMAP_RRC, /* rear right center */
|
||||
VIRTIO_SND_CHMAP_FLW, /* front left wide */
|
||||
VIRTIO_SND_CHMAP_FRW, /* front right wide */
|
||||
VIRTIO_SND_CHMAP_FLH, /* front left high */
|
||||
VIRTIO_SND_CHMAP_FCH, /* front center high */
|
||||
VIRTIO_SND_CHMAP_FRH, /* front right high */
|
||||
VIRTIO_SND_CHMAP_TC, /* top center */
|
||||
VIRTIO_SND_CHMAP_TFL, /* top front left */
|
||||
VIRTIO_SND_CHMAP_TFR, /* top front right */
|
||||
VIRTIO_SND_CHMAP_TFC, /* top front center */
|
||||
VIRTIO_SND_CHMAP_TRL, /* top rear left */
|
||||
VIRTIO_SND_CHMAP_TRR, /* top rear right */
|
||||
VIRTIO_SND_CHMAP_TRC, /* top rear center */
|
||||
VIRTIO_SND_CHMAP_TFLC, /* top front left center */
|
||||
VIRTIO_SND_CHMAP_TFRC, /* top front right center */
|
||||
VIRTIO_SND_CHMAP_TSL, /* top side left */
|
||||
VIRTIO_SND_CHMAP_TSR, /* top side right */
|
||||
VIRTIO_SND_CHMAP_LLFE, /* left LFE */
|
||||
VIRTIO_SND_CHMAP_RLFE, /* right LFE */
|
||||
VIRTIO_SND_CHMAP_BC, /* bottom center */
|
||||
VIRTIO_SND_CHMAP_BLC, /* bottom left center */
|
||||
VIRTIO_SND_CHMAP_BRC /* bottom right center */
|
||||
};
|
||||
|
||||
/* maximum possible number of channels */
|
||||
#define VIRTIO_SND_CHMAP_MAX_SIZE 18
|
||||
|
||||
struct virtio_snd_chmap_info {
|
||||
/* common header */
|
||||
struct virtio_snd_info hdr;
|
||||
/* dataflow direction (VIRTIO_SND_D_XXX) */
|
||||
__u8 direction;
|
||||
/* # of valid channel position values */
|
||||
__u8 channels;
|
||||
/* channel position values (VIRTIO_SND_CHMAP_XXX) */
|
||||
__u8 positions[VIRTIO_SND_CHMAP_MAX_SIZE];
|
||||
};
|
||||
|
||||
#endif /* VIRTIO_SND_IF_H */
|
@ -99,6 +99,8 @@ source "sound/synth/Kconfig"
|
||||
|
||||
source "sound/xen/Kconfig"
|
||||
|
||||
source "sound/virtio/Kconfig"
|
||||
|
||||
endif # SND
|
||||
|
||||
endif # !UML
|
||||
|
@ -5,7 +5,8 @@
|
||||
obj-$(CONFIG_SOUND) += soundcore.o
|
||||
obj-$(CONFIG_DMASOUND) += oss/dmasound/
|
||||
obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
|
||||
firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ hda/ x86/ xen/
|
||||
firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ hda/ x86/ xen/ \
|
||||
virtio/
|
||||
obj-$(CONFIG_SND_AOA) += aoa/
|
||||
|
||||
# This one must be compilable even if sound is configured out
|
||||
|
@ -203,4 +203,10 @@ config SND_DMA_SGBUF
|
||||
def_bool y
|
||||
depends on X86
|
||||
|
||||
config SND_CTL_LED
|
||||
tristate
|
||||
select NEW_LEDS if SND_CTL_LED
|
||||
select LEDS_TRIGGERS if SND_CTL_LED
|
||||
select LEDS_TRIGGER_AUDIO if SND_CTL_LED
|
||||
|
||||
source "sound/core/seq/Kconfig"
|
||||
|
@ -27,6 +27,7 @@ CFLAGS_pcm_native.o := -I$(src)
|
||||
|
||||
snd-pcm-dmaengine-objs := pcm_dmaengine.o
|
||||
|
||||
snd-ctl-led-objs := control_led.o
|
||||
snd-rawmidi-objs := rawmidi.o
|
||||
snd-timer-objs := timer.o
|
||||
snd-hrtimer-objs := hrtimer.o
|
||||
@ -37,6 +38,7 @@ snd-seq-device-objs := seq_device.o
|
||||
snd-compress-objs := compress_offload.o
|
||||
|
||||
obj-$(CONFIG_SND) += snd.o
|
||||
obj-$(CONFIG_SND_CTL_LED) += snd-ctl-led.o
|
||||
obj-$(CONFIG_SND_HWDEP) += snd-hwdep.o
|
||||
obj-$(CONFIG_SND_TIMER) += snd-timer.o
|
||||
obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <linux/threads.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/time.h>
|
||||
@ -18,8 +19,11 @@
|
||||
#include <sound/info.h>
|
||||
#include <sound/control.h>
|
||||
|
||||
/* max number of user-defined controls */
|
||||
#define MAX_USER_CONTROLS 32
|
||||
// Max allocation size for user controls.
|
||||
static int max_user_ctl_alloc_size = 8 * 1024 * 1024;
|
||||
module_param_named(max_user_ctl_alloc_size, max_user_ctl_alloc_size, int, 0444);
|
||||
MODULE_PARM_DESC(max_user_ctl_alloc_size, "Max allocation size for user controls");
|
||||
|
||||
#define MAX_CONTROL_COUNT 1028
|
||||
|
||||
struct snd_kctl_ioctl {
|
||||
@ -28,10 +32,12 @@ struct snd_kctl_ioctl {
|
||||
};
|
||||
|
||||
static DECLARE_RWSEM(snd_ioctl_rwsem);
|
||||
static DECLARE_RWSEM(snd_ctl_layer_rwsem);
|
||||
static LIST_HEAD(snd_control_ioctls);
|
||||
#ifdef CONFIG_COMPAT
|
||||
static LIST_HEAD(snd_control_compat_ioctls);
|
||||
#endif
|
||||
static struct snd_ctl_layer_ops *snd_ctl_layer;
|
||||
|
||||
static int snd_ctl_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
@ -181,6 +187,32 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
|
||||
}
|
||||
EXPORT_SYMBOL(snd_ctl_notify);
|
||||
|
||||
/**
|
||||
* snd_ctl_notify_one - Send notification to user-space for a control change
|
||||
* @card: the card to send notification
|
||||
* @mask: the event mask, SNDRV_CTL_EVENT_*
|
||||
* @kctl: the pointer with the control instance
|
||||
* @ioff: the additional offset to the control index
|
||||
*
|
||||
* This function calls snd_ctl_notify() and does additional jobs
|
||||
* like LED state changes.
|
||||
*/
|
||||
void snd_ctl_notify_one(struct snd_card *card, unsigned int mask,
|
||||
struct snd_kcontrol *kctl, unsigned int ioff)
|
||||
{
|
||||
struct snd_ctl_elem_id id = kctl->id;
|
||||
struct snd_ctl_layer_ops *lops;
|
||||
|
||||
id.index += ioff;
|
||||
id.numid += ioff;
|
||||
snd_ctl_notify(card, mask, &id);
|
||||
down_read(&snd_ctl_layer_rwsem);
|
||||
for (lops = snd_ctl_layer; lops; lops = lops->next)
|
||||
lops->lnotify(card, mask, kctl, ioff);
|
||||
up_read(&snd_ctl_layer_rwsem);
|
||||
}
|
||||
EXPORT_SYMBOL(snd_ctl_notify_one);
|
||||
|
||||
/**
|
||||
* snd_ctl_new - create a new control instance with some elements
|
||||
* @kctl: the pointer to store new control instance
|
||||
@ -250,6 +282,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
|
||||
SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE |
|
||||
SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND |
|
||||
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK |
|
||||
SNDRV_CTL_ELEM_ACCESS_LED_MASK |
|
||||
SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK);
|
||||
|
||||
err = snd_ctl_new(&kctl, count, access, NULL);
|
||||
@ -342,7 +375,6 @@ static int __snd_ctl_add_replace(struct snd_card *card,
|
||||
{
|
||||
struct snd_ctl_elem_id id;
|
||||
unsigned int idx;
|
||||
unsigned int count;
|
||||
struct snd_kcontrol *old;
|
||||
int err;
|
||||
|
||||
@ -376,10 +408,8 @@ static int __snd_ctl_add_replace(struct snd_card *card,
|
||||
kcontrol->id.numid = card->last_numid + 1;
|
||||
card->last_numid += kcontrol->count;
|
||||
|
||||
id = kcontrol->id;
|
||||
count = kcontrol->count;
|
||||
for (idx = 0; idx < count; idx++, id.index++, id.numid++)
|
||||
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
|
||||
for (idx = 0; idx < kcontrol->count; idx++)
|
||||
snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_ADD, kcontrol, idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -462,16 +492,14 @@ EXPORT_SYMBOL(snd_ctl_replace);
|
||||
*/
|
||||
int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol)
|
||||
{
|
||||
struct snd_ctl_elem_id id;
|
||||
unsigned int idx;
|
||||
|
||||
if (snd_BUG_ON(!card || !kcontrol))
|
||||
return -EINVAL;
|
||||
list_del(&kcontrol->list);
|
||||
card->controls_count -= kcontrol->count;
|
||||
id = kcontrol->id;
|
||||
for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
|
||||
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_REMOVE, &id);
|
||||
for (idx = 0; idx < kcontrol->count; idx++)
|
||||
snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_REMOVE, kcontrol, idx);
|
||||
snd_ctl_free_one(kcontrol);
|
||||
return 0;
|
||||
}
|
||||
@ -537,9 +565,6 @@ static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
|
||||
goto error;
|
||||
}
|
||||
ret = snd_ctl_remove(card, kctl);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
card->user_ctl_count--;
|
||||
error:
|
||||
up_write(&card->controls_rwsem);
|
||||
return ret;
|
||||
@ -584,11 +609,13 @@ int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
|
||||
vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
|
||||
}
|
||||
snd_ctl_build_ioff(id, kctl, index_offset);
|
||||
ret = 1;
|
||||
downgrade_write(&card->controls_rwsem);
|
||||
snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_INFO, kctl, index_offset);
|
||||
up_read(&card->controls_rwsem);
|
||||
return 1;
|
||||
|
||||
unlock:
|
||||
up_write(&card->controls_rwsem);
|
||||
if (ret > 0)
|
||||
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, id);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_ctl_activate_id);
|
||||
@ -1022,7 +1049,8 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
|
||||
if (result < 0)
|
||||
return result;
|
||||
/* drop internal access flags */
|
||||
info.access &= ~SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK;
|
||||
info.access &= ~(SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK|
|
||||
SNDRV_CTL_ELEM_ACCESS_LED_MASK);
|
||||
if (copy_to_user(_info, &info, sizeof(info)))
|
||||
return -EFAULT;
|
||||
return result;
|
||||
@ -1110,25 +1138,34 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
|
||||
unsigned int index_offset;
|
||||
int result;
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, &control->id);
|
||||
if (kctl == NULL)
|
||||
if (kctl == NULL) {
|
||||
up_write(&card->controls_rwsem);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
index_offset = snd_ctl_get_ioff(kctl, &control->id);
|
||||
vd = &kctl->vd[index_offset];
|
||||
if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || kctl->put == NULL ||
|
||||
(file && vd->owner && vd->owner != file)) {
|
||||
up_write(&card->controls_rwsem);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
snd_ctl_build_ioff(&control->id, kctl, index_offset);
|
||||
result = kctl->put(kctl, control);
|
||||
if (result < 0)
|
||||
if (result < 0) {
|
||||
up_write(&card->controls_rwsem);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (result > 0) {
|
||||
struct snd_ctl_elem_id id = control->id;
|
||||
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
|
||||
downgrade_write(&card->controls_rwsem);
|
||||
snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_VALUE, kctl, index_offset);
|
||||
up_read(&card->controls_rwsem);
|
||||
} else {
|
||||
up_write(&card->controls_rwsem);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1150,9 +1187,7 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
|
||||
if (result < 0)
|
||||
goto error;
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
result = snd_ctl_elem_write(card, file, control);
|
||||
up_write(&card->controls_rwsem);
|
||||
if (result < 0)
|
||||
goto error;
|
||||
|
||||
@ -1231,6 +1266,12 @@ struct user_element {
|
||||
void *priv_data; /* private data (like strings for enumerated type) */
|
||||
};
|
||||
|
||||
// check whether the addition (in bytes) of user ctl element may overflow the limit.
|
||||
static bool check_user_elem_overflow(struct snd_card *card, ssize_t add)
|
||||
{
|
||||
return (ssize_t)card->user_ctl_alloc_size + add > max_user_ctl_alloc_size;
|
||||
}
|
||||
|
||||
static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
@ -1296,12 +1337,12 @@ static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol,
|
||||
return change;
|
||||
}
|
||||
|
||||
/* called in controls_rwsem write lock */
|
||||
static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
|
||||
unsigned int size)
|
||||
{
|
||||
struct user_element *ue = kctl->private_data;
|
||||
unsigned int *container;
|
||||
struct snd_ctl_elem_id id;
|
||||
unsigned int mask = 0;
|
||||
int i;
|
||||
int change;
|
||||
@ -1309,6 +1350,10 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
|
||||
if (size > 1024 * 128) /* sane value */
|
||||
return -EINVAL;
|
||||
|
||||
// does the TLV size change cause overflow?
|
||||
if (check_user_elem_overflow(ue->card, (ssize_t)(size - ue->tlv_data_size)))
|
||||
return -ENOMEM;
|
||||
|
||||
container = vmemdup_user(buf, size);
|
||||
if (IS_ERR(container))
|
||||
return PTR_ERR(container);
|
||||
@ -1326,17 +1371,20 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
|
||||
for (i = 0; i < kctl->count; ++i)
|
||||
kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
|
||||
mask = SNDRV_CTL_EVENT_MASK_INFO;
|
||||
} else {
|
||||
ue->card->user_ctl_alloc_size -= ue->tlv_data_size;
|
||||
ue->tlv_data_size = 0;
|
||||
kvfree(ue->tlv_data);
|
||||
}
|
||||
|
||||
kvfree(ue->tlv_data);
|
||||
ue->tlv_data = container;
|
||||
ue->tlv_data_size = size;
|
||||
// decremented at private_free.
|
||||
ue->card->user_ctl_alloc_size += size;
|
||||
|
||||
mask |= SNDRV_CTL_EVENT_MASK_TLV;
|
||||
for (i = 0; i < kctl->count; ++i) {
|
||||
snd_ctl_build_ioff(&id, kctl, i);
|
||||
snd_ctl_notify(ue->card, mask, &id);
|
||||
}
|
||||
for (i = 0; i < kctl->count; ++i)
|
||||
snd_ctl_notify_one(ue->card, mask, kctl, i);
|
||||
|
||||
return change;
|
||||
}
|
||||
@ -1367,6 +1415,7 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kctl, int op_flag,
|
||||
return read_user_tlv(kctl, buf, size);
|
||||
}
|
||||
|
||||
/* called in controls_rwsem write lock */
|
||||
static int snd_ctl_elem_init_enum_names(struct user_element *ue)
|
||||
{
|
||||
char *names, *p;
|
||||
@ -1374,16 +1423,17 @@ 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;
|
||||
|
||||
if (ue->info.value.enumerated.names_length > 64 * 1024)
|
||||
buf_len = ue->info.value.enumerated.names_length;
|
||||
if (buf_len > 64 * 1024)
|
||||
return -EINVAL;
|
||||
|
||||
names = vmemdup_user((const void __user *)user_ptrval,
|
||||
ue->info.value.enumerated.names_length);
|
||||
if (check_user_elem_overflow(ue->card, buf_len))
|
||||
return -ENOMEM;
|
||||
names = vmemdup_user((const void __user *)user_ptrval, buf_len);
|
||||
if (IS_ERR(names))
|
||||
return PTR_ERR(names);
|
||||
|
||||
/* check that there are enough valid names */
|
||||
buf_len = ue->info.value.enumerated.names_length;
|
||||
p = names;
|
||||
for (i = 0; i < ue->info.value.enumerated.items; ++i) {
|
||||
name_len = strnlen(p, buf_len);
|
||||
@ -1397,14 +1447,27 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
|
||||
|
||||
ue->priv_data = names;
|
||||
ue->info.value.enumerated.names_ptr = 0;
|
||||
// increment the allocation size; decremented again at private_free.
|
||||
ue->card->user_ctl_alloc_size += ue->info.value.enumerated.names_length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t compute_user_elem_size(size_t size, unsigned int count)
|
||||
{
|
||||
return sizeof(struct user_element) + size * count;
|
||||
}
|
||||
|
||||
static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol)
|
||||
{
|
||||
struct user_element *ue = kcontrol->private_data;
|
||||
|
||||
// decrement the allocation size.
|
||||
ue->card->user_ctl_alloc_size -= compute_user_elem_size(ue->elem_data_size, kcontrol->count);
|
||||
ue->card->user_ctl_alloc_size -= ue->tlv_data_size;
|
||||
if (ue->priv_data)
|
||||
ue->card->user_ctl_alloc_size -= ue->info.value.enumerated.names_length;
|
||||
|
||||
kvfree(ue->tlv_data);
|
||||
kvfree(ue->priv_data);
|
||||
kfree(ue);
|
||||
@ -1418,6 +1481,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
||||
unsigned int count;
|
||||
unsigned int access;
|
||||
long private_size;
|
||||
size_t alloc_size;
|
||||
struct user_element *ue;
|
||||
unsigned int offset;
|
||||
int err;
|
||||
@ -1435,13 +1499,6 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* The number of userspace controls are counted control by control,
|
||||
* not element by element.
|
||||
*/
|
||||
if (card->user_ctl_count + 1 > MAX_USER_CONTROLS)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Check the number of elements for this userspace control. */
|
||||
count = info->owner;
|
||||
if (count == 0)
|
||||
@ -1472,6 +1529,13 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
||||
if (info->count < 1)
|
||||
return -EINVAL;
|
||||
private_size = value_sizes[info->type] * info->count;
|
||||
alloc_size = compute_user_elem_size(private_size, count);
|
||||
|
||||
down_write(&card->controls_rwsem);
|
||||
if (check_user_elem_overflow(card, alloc_size)) {
|
||||
err = -ENOMEM;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep memory object for this userspace control. After passing this
|
||||
@ -1481,18 +1545,21 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
||||
*/
|
||||
err = snd_ctl_new(&kctl, count, access, file);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto unlock;
|
||||
memcpy(&kctl->id, &info->id, sizeof(kctl->id));
|
||||
kctl->private_data = kzalloc(sizeof(struct user_element) + private_size * count,
|
||||
GFP_KERNEL);
|
||||
if (kctl->private_data == NULL) {
|
||||
ue = kzalloc(alloc_size, GFP_KERNEL);
|
||||
if (!ue) {
|
||||
kfree(kctl);
|
||||
return -ENOMEM;
|
||||
err = -ENOMEM;
|
||||
goto unlock;
|
||||
}
|
||||
kctl->private_data = ue;
|
||||
kctl->private_free = snd_ctl_elem_user_free;
|
||||
|
||||
// increment the allocated size; decremented again at private_free.
|
||||
card->user_ctl_alloc_size += alloc_size;
|
||||
|
||||
/* Set private data for this userspace control. */
|
||||
ue = (struct user_element *)kctl->private_data;
|
||||
ue->card = card;
|
||||
ue->info = *info;
|
||||
ue->info.access = 0;
|
||||
@ -1502,7 +1569,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
||||
err = snd_ctl_elem_init_enum_names(ue);
|
||||
if (err < 0) {
|
||||
snd_ctl_free_one(kctl);
|
||||
return err;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1519,7 +1586,6 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
||||
kctl->tlv.c = snd_ctl_elem_user_tlv;
|
||||
|
||||
/* This function manage to free the instance on failure. */
|
||||
down_write(&card->controls_rwsem);
|
||||
err = __snd_ctl_add_replace(card, kctl, CTL_ADD_EXCLUSIVE);
|
||||
if (err < 0) {
|
||||
snd_ctl_free_one(kctl);
|
||||
@ -1534,9 +1600,6 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
||||
* applications because the field originally means PID of a process
|
||||
* which locks the element.
|
||||
*/
|
||||
|
||||
card->user_ctl_count++;
|
||||
|
||||
unlock:
|
||||
up_write(&card->controls_rwsem);
|
||||
return err;
|
||||
@ -1975,6 +2038,88 @@ EXPORT_SYMBOL_GPL(snd_ctl_get_preferred_subdevice);
|
||||
#define snd_ctl_ioctl_compat NULL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* control layers (audio LED etc.)
|
||||
*/
|
||||
|
||||
/**
|
||||
* snd_ctl_request_layer - request to use the layer
|
||||
* @module_name: Name of the kernel module (NULL == build-in)
|
||||
*
|
||||
* Return an error code when the module cannot be loaded.
|
||||
*/
|
||||
int snd_ctl_request_layer(const char *module_name)
|
||||
{
|
||||
struct snd_ctl_layer_ops *lops;
|
||||
|
||||
if (module_name == NULL)
|
||||
return 0;
|
||||
down_read(&snd_ctl_layer_rwsem);
|
||||
for (lops = snd_ctl_layer; lops; lops = lops->next)
|
||||
if (strcmp(lops->module_name, module_name) == 0)
|
||||
break;
|
||||
up_read(&snd_ctl_layer_rwsem);
|
||||
if (lops)
|
||||
return 0;
|
||||
return request_module(module_name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_ctl_request_layer);
|
||||
|
||||
/**
|
||||
* snd_ctl_register_layer - register new control layer
|
||||
* @lops: operation structure
|
||||
*
|
||||
* The new layer can track all control elements and do additional
|
||||
* operations on top (like audio LED handling).
|
||||
*/
|
||||
void snd_ctl_register_layer(struct snd_ctl_layer_ops *lops)
|
||||
{
|
||||
struct snd_card *card;
|
||||
int card_number;
|
||||
|
||||
down_write(&snd_ctl_layer_rwsem);
|
||||
lops->next = snd_ctl_layer;
|
||||
snd_ctl_layer = lops;
|
||||
up_write(&snd_ctl_layer_rwsem);
|
||||
for (card_number = 0; card_number < SNDRV_CARDS; card_number++) {
|
||||
card = snd_card_ref(card_number);
|
||||
if (card) {
|
||||
down_read(&card->controls_rwsem);
|
||||
lops->lregister(card);
|
||||
up_read(&card->controls_rwsem);
|
||||
snd_card_unref(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_ctl_register_layer);
|
||||
|
||||
/**
|
||||
* snd_ctl_disconnect_layer - disconnect control layer
|
||||
* @lops: operation structure
|
||||
*
|
||||
* It is expected that the information about tracked cards
|
||||
* is freed before this call (the disconnect callback is
|
||||
* not called here).
|
||||
*/
|
||||
void snd_ctl_disconnect_layer(struct snd_ctl_layer_ops *lops)
|
||||
{
|
||||
struct snd_ctl_layer_ops *lops2, *prev_lops2;
|
||||
|
||||
down_write(&snd_ctl_layer_rwsem);
|
||||
for (lops2 = snd_ctl_layer, prev_lops2 = NULL; lops2; lops2 = lops2->next) {
|
||||
if (lops2 == lops) {
|
||||
if (!prev_lops2)
|
||||
snd_ctl_layer = lops->next;
|
||||
else
|
||||
prev_lops2->next = lops->next;
|
||||
break;
|
||||
}
|
||||
prev_lops2 = lops2;
|
||||
}
|
||||
up_write(&snd_ctl_layer_rwsem);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_ctl_disconnect_layer);
|
||||
|
||||
/*
|
||||
* INIT PART
|
||||
*/
|
||||
@ -1998,9 +2143,20 @@ static const struct file_operations snd_ctl_f_ops =
|
||||
static int snd_ctl_dev_register(struct snd_device *device)
|
||||
{
|
||||
struct snd_card *card = device->device_data;
|
||||
struct snd_ctl_layer_ops *lops;
|
||||
int err;
|
||||
|
||||
return snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
|
||||
&snd_ctl_f_ops, card, &card->ctl_dev);
|
||||
err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
|
||||
&snd_ctl_f_ops, card, &card->ctl_dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
down_read(&card->controls_rwsem);
|
||||
down_read(&snd_ctl_layer_rwsem);
|
||||
for (lops = snd_ctl_layer; lops; lops = lops->next)
|
||||
lops->lregister(card);
|
||||
up_read(&snd_ctl_layer_rwsem);
|
||||
up_read(&card->controls_rwsem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2010,6 +2166,7 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
|
||||
{
|
||||
struct snd_card *card = device->device_data;
|
||||
struct snd_ctl_file *ctl;
|
||||
struct snd_ctl_layer_ops *lops;
|
||||
unsigned long flags;
|
||||
|
||||
read_lock_irqsave(&card->ctl_files_rwlock, flags);
|
||||
@ -2019,6 +2176,13 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
|
||||
}
|
||||
read_unlock_irqrestore(&card->ctl_files_rwlock, flags);
|
||||
|
||||
down_read(&card->controls_rwsem);
|
||||
down_read(&snd_ctl_layer_rwsem);
|
||||
for (lops = snd_ctl_layer; lops; lops = lops->next)
|
||||
lops->ldisconnect(card);
|
||||
up_read(&snd_ctl_layer_rwsem);
|
||||
up_read(&card->controls_rwsem);
|
||||
|
||||
return snd_unregister_device(&card->ctl_dev);
|
||||
}
|
||||
|
||||
|
777
sound/core/control_led.c
Normal file
777
sound/core/control_led.c
Normal file
@ -0,0 +1,777 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* LED state routines for driver control interface
|
||||
* Copyright (c) 2021 by Jaroslav Kysela <perex@perex.cz>
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/leds.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/control.h>
|
||||
|
||||
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
|
||||
MODULE_DESCRIPTION("ALSA control interface to LED trigger code.");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#define MAX_LED (((SNDRV_CTL_ELEM_ACCESS_MIC_LED - SNDRV_CTL_ELEM_ACCESS_SPK_LED) \
|
||||
>> SNDRV_CTL_ELEM_ACCESS_LED_SHIFT) + 1)
|
||||
|
||||
enum snd_ctl_led_mode {
|
||||
MODE_FOLLOW_MUTE = 0,
|
||||
MODE_FOLLOW_ROUTE,
|
||||
MODE_OFF,
|
||||
MODE_ON,
|
||||
};
|
||||
|
||||
struct snd_ctl_led_card {
|
||||
struct device dev;
|
||||
int number;
|
||||
struct snd_ctl_led *led;
|
||||
};
|
||||
|
||||
struct snd_ctl_led {
|
||||
struct device dev;
|
||||
struct list_head controls;
|
||||
const char *name;
|
||||
unsigned int group;
|
||||
enum led_audio trigger_type;
|
||||
enum snd_ctl_led_mode mode;
|
||||
struct snd_ctl_led_card *cards[SNDRV_CARDS];
|
||||
};
|
||||
|
||||
struct snd_ctl_led_ctl {
|
||||
struct list_head list;
|
||||
struct snd_card *card;
|
||||
unsigned int access;
|
||||
struct snd_kcontrol *kctl;
|
||||
unsigned int index_offset;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(snd_ctl_led_mutex);
|
||||
static bool snd_ctl_led_card_valid[SNDRV_CARDS];
|
||||
static struct snd_ctl_led snd_ctl_leds[MAX_LED] = {
|
||||
{
|
||||
.name = "speaker",
|
||||
.group = (SNDRV_CTL_ELEM_ACCESS_SPK_LED >> SNDRV_CTL_ELEM_ACCESS_LED_SHIFT) - 1,
|
||||
.trigger_type = LED_AUDIO_MUTE,
|
||||
.mode = MODE_FOLLOW_MUTE,
|
||||
},
|
||||
{
|
||||
.name = "mic",
|
||||
.group = (SNDRV_CTL_ELEM_ACCESS_MIC_LED >> SNDRV_CTL_ELEM_ACCESS_LED_SHIFT) - 1,
|
||||
.trigger_type = LED_AUDIO_MICMUTE,
|
||||
.mode = MODE_FOLLOW_MUTE,
|
||||
},
|
||||
};
|
||||
|
||||
static void snd_ctl_led_sysfs_add(struct snd_card *card);
|
||||
static void snd_ctl_led_sysfs_remove(struct snd_card *card);
|
||||
|
||||
#define UPDATE_ROUTE(route, cb) \
|
||||
do { \
|
||||
int route2 = (cb); \
|
||||
if (route2 >= 0) \
|
||||
route = route < 0 ? route2 : (route | route2); \
|
||||
} while (0)
|
||||
|
||||
static inline unsigned int access_to_group(unsigned int access)
|
||||
{
|
||||
return ((access & SNDRV_CTL_ELEM_ACCESS_LED_MASK) >>
|
||||
SNDRV_CTL_ELEM_ACCESS_LED_SHIFT) - 1;
|
||||
}
|
||||
|
||||
static inline unsigned int group_to_access(unsigned int group)
|
||||
{
|
||||
return (group + 1) << SNDRV_CTL_ELEM_ACCESS_LED_SHIFT;
|
||||
}
|
||||
|
||||
static struct snd_ctl_led *snd_ctl_led_get_by_access(unsigned int access)
|
||||
{
|
||||
unsigned int group = access_to_group(access);
|
||||
if (group >= MAX_LED)
|
||||
return NULL;
|
||||
return &snd_ctl_leds[group];
|
||||
}
|
||||
|
||||
/*
|
||||
* A note for callers:
|
||||
* The two static variables info and value are protected using snd_ctl_led_mutex.
|
||||
*/
|
||||
static int snd_ctl_led_get(struct snd_ctl_led_ctl *lctl)
|
||||
{
|
||||
static struct snd_ctl_elem_info info;
|
||||
static struct snd_ctl_elem_value value;
|
||||
struct snd_kcontrol *kctl = lctl->kctl;
|
||||
unsigned int i;
|
||||
int result;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.id = kctl->id;
|
||||
info.id.index += lctl->index_offset;
|
||||
info.id.numid += lctl->index_offset;
|
||||
result = kctl->info(kctl, &info);
|
||||
if (result < 0)
|
||||
return -1;
|
||||
memset(&value, 0, sizeof(value));
|
||||
value.id = info.id;
|
||||
result = kctl->get(kctl, &value);
|
||||
if (result < 0)
|
||||
return -1;
|
||||
if (info.type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
|
||||
info.type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
|
||||
for (i = 0; i < info.count; i++)
|
||||
if (value.value.integer.value[i] != info.value.integer.min)
|
||||
return 1;
|
||||
} else if (info.type == SNDRV_CTL_ELEM_TYPE_INTEGER64) {
|
||||
for (i = 0; i < info.count; i++)
|
||||
if (value.value.integer64.value[i] != info.value.integer64.min)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void snd_ctl_led_set_state(struct snd_card *card, unsigned int access,
|
||||
struct snd_kcontrol *kctl, unsigned int ioff)
|
||||
{
|
||||
struct snd_ctl_led *led;
|
||||
struct snd_ctl_led_ctl *lctl;
|
||||
int route;
|
||||
bool found;
|
||||
|
||||
led = snd_ctl_led_get_by_access(access);
|
||||
if (!led)
|
||||
return;
|
||||
route = -1;
|
||||
found = false;
|
||||
mutex_lock(&snd_ctl_led_mutex);
|
||||
/* the card may not be registered (active) at this point */
|
||||
if (card && !snd_ctl_led_card_valid[card->number]) {
|
||||
mutex_unlock(&snd_ctl_led_mutex);
|
||||
return;
|
||||
}
|
||||
list_for_each_entry(lctl, &led->controls, list) {
|
||||
if (lctl->kctl == kctl && lctl->index_offset == ioff)
|
||||
found = true;
|
||||
UPDATE_ROUTE(route, snd_ctl_led_get(lctl));
|
||||
}
|
||||
if (!found && kctl && card) {
|
||||
lctl = kzalloc(sizeof(*lctl), GFP_KERNEL);
|
||||
if (lctl) {
|
||||
lctl->card = card;
|
||||
lctl->access = access;
|
||||
lctl->kctl = kctl;
|
||||
lctl->index_offset = ioff;
|
||||
list_add(&lctl->list, &led->controls);
|
||||
UPDATE_ROUTE(route, snd_ctl_led_get(lctl));
|
||||
}
|
||||
}
|
||||
mutex_unlock(&snd_ctl_led_mutex);
|
||||
switch (led->mode) {
|
||||
case MODE_OFF: route = 1; break;
|
||||
case MODE_ON: route = 0; break;
|
||||
case MODE_FOLLOW_ROUTE: if (route >= 0) route ^= 1; break;
|
||||
case MODE_FOLLOW_MUTE: /* noop */ break;
|
||||
}
|
||||
if (route >= 0)
|
||||
ledtrig_audio_set(led->trigger_type, route ? LED_OFF : LED_ON);
|
||||
}
|
||||
|
||||
static struct snd_ctl_led_ctl *snd_ctl_led_find(struct snd_kcontrol *kctl, unsigned int ioff)
|
||||
{
|
||||
struct list_head *controls;
|
||||
struct snd_ctl_led_ctl *lctl;
|
||||
unsigned int group;
|
||||
|
||||
for (group = 0; group < MAX_LED; group++) {
|
||||
controls = &snd_ctl_leds[group].controls;
|
||||
list_for_each_entry(lctl, controls, list)
|
||||
if (lctl->kctl == kctl && lctl->index_offset == ioff)
|
||||
return lctl;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned int snd_ctl_led_remove(struct snd_kcontrol *kctl, unsigned int ioff,
|
||||
unsigned int access)
|
||||
{
|
||||
struct snd_ctl_led_ctl *lctl;
|
||||
unsigned int ret = 0;
|
||||
|
||||
mutex_lock(&snd_ctl_led_mutex);
|
||||
lctl = snd_ctl_led_find(kctl, ioff);
|
||||
if (lctl && (access == 0 || access != lctl->access)) {
|
||||
ret = lctl->access;
|
||||
list_del(&lctl->list);
|
||||
kfree(lctl);
|
||||
}
|
||||
mutex_unlock(&snd_ctl_led_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void snd_ctl_led_notify(struct snd_card *card, unsigned int mask,
|
||||
struct snd_kcontrol *kctl, unsigned int ioff)
|
||||
{
|
||||
struct snd_kcontrol_volatile *vd;
|
||||
unsigned int access, access2;
|
||||
|
||||
if (mask == SNDRV_CTL_EVENT_MASK_REMOVE) {
|
||||
access = snd_ctl_led_remove(kctl, ioff, 0);
|
||||
if (access)
|
||||
snd_ctl_led_set_state(card, access, NULL, 0);
|
||||
} else if (mask & SNDRV_CTL_EVENT_MASK_INFO) {
|
||||
vd = &kctl->vd[ioff];
|
||||
access = vd->access & SNDRV_CTL_ELEM_ACCESS_LED_MASK;
|
||||
access2 = snd_ctl_led_remove(kctl, ioff, access);
|
||||
if (access2)
|
||||
snd_ctl_led_set_state(card, access2, NULL, 0);
|
||||
if (access)
|
||||
snd_ctl_led_set_state(card, access, kctl, ioff);
|
||||
} else if ((mask & (SNDRV_CTL_EVENT_MASK_ADD |
|
||||
SNDRV_CTL_EVENT_MASK_VALUE)) != 0) {
|
||||
vd = &kctl->vd[ioff];
|
||||
access = vd->access & SNDRV_CTL_ELEM_ACCESS_LED_MASK;
|
||||
if (access)
|
||||
snd_ctl_led_set_state(card, access, kctl, ioff);
|
||||
}
|
||||
}
|
||||
|
||||
static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id,
|
||||
unsigned int group, bool set)
|
||||
{
|
||||
struct snd_card *card;
|
||||
struct snd_kcontrol *kctl;
|
||||
struct snd_kcontrol_volatile *vd;
|
||||
unsigned int ioff, access, new_access;
|
||||
int err = 0;
|
||||
|
||||
card = snd_card_ref(card_number);
|
||||
if (card) {
|
||||
down_write(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, id);
|
||||
if (kctl) {
|
||||
ioff = snd_ctl_get_ioff(kctl, id);
|
||||
vd = &kctl->vd[ioff];
|
||||
access = vd->access & SNDRV_CTL_ELEM_ACCESS_LED_MASK;
|
||||
if (access != 0 && access != group_to_access(group)) {
|
||||
err = -EXDEV;
|
||||
goto unlock;
|
||||
}
|
||||
new_access = vd->access & ~SNDRV_CTL_ELEM_ACCESS_LED_MASK;
|
||||
if (set)
|
||||
new_access |= group_to_access(group);
|
||||
if (new_access != vd->access) {
|
||||
vd->access = new_access;
|
||||
snd_ctl_led_notify(card, SNDRV_CTL_EVENT_MASK_INFO, kctl, ioff);
|
||||
}
|
||||
} else {
|
||||
err = -ENOENT;
|
||||
}
|
||||
unlock:
|
||||
up_write(&card->controls_rwsem);
|
||||
snd_card_unref(card);
|
||||
} else {
|
||||
err = -ENXIO;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void snd_ctl_led_refresh(void)
|
||||
{
|
||||
unsigned int group;
|
||||
|
||||
for (group = 0; group < MAX_LED; group++)
|
||||
snd_ctl_led_set_state(NULL, group_to_access(group), NULL, 0);
|
||||
}
|
||||
|
||||
static void snd_ctl_led_ctl_destroy(struct snd_ctl_led_ctl *lctl)
|
||||
{
|
||||
list_del(&lctl->list);
|
||||
kfree(lctl);
|
||||
}
|
||||
|
||||
static void snd_ctl_led_clean(struct snd_card *card)
|
||||
{
|
||||
unsigned int group;
|
||||
struct snd_ctl_led *led;
|
||||
struct snd_ctl_led_ctl *lctl;
|
||||
|
||||
for (group = 0; group < MAX_LED; group++) {
|
||||
led = &snd_ctl_leds[group];
|
||||
repeat:
|
||||
list_for_each_entry(lctl, &led->controls, list)
|
||||
if (!card || lctl->card == card) {
|
||||
snd_ctl_led_ctl_destroy(lctl);
|
||||
goto repeat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int snd_ctl_led_reset(int card_number, unsigned int group)
|
||||
{
|
||||
struct snd_card *card;
|
||||
struct snd_ctl_led *led;
|
||||
struct snd_ctl_led_ctl *lctl;
|
||||
struct snd_kcontrol_volatile *vd;
|
||||
bool change = false;
|
||||
|
||||
card = snd_card_ref(card_number);
|
||||
if (!card)
|
||||
return -ENXIO;
|
||||
|
||||
mutex_lock(&snd_ctl_led_mutex);
|
||||
if (!snd_ctl_led_card_valid[card_number]) {
|
||||
mutex_unlock(&snd_ctl_led_mutex);
|
||||
snd_card_unref(card);
|
||||
return -ENXIO;
|
||||
}
|
||||
led = &snd_ctl_leds[group];
|
||||
repeat:
|
||||
list_for_each_entry(lctl, &led->controls, list)
|
||||
if (lctl->card == card) {
|
||||
vd = &lctl->kctl->vd[lctl->index_offset];
|
||||
vd->access &= ~group_to_access(group);
|
||||
snd_ctl_led_ctl_destroy(lctl);
|
||||
change = true;
|
||||
goto repeat;
|
||||
}
|
||||
mutex_unlock(&snd_ctl_led_mutex);
|
||||
if (change)
|
||||
snd_ctl_led_set_state(NULL, group_to_access(group), NULL, 0);
|
||||
snd_card_unref(card);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void snd_ctl_led_register(struct snd_card *card)
|
||||
{
|
||||
struct snd_kcontrol *kctl;
|
||||
unsigned int ioff;
|
||||
|
||||
if (snd_BUG_ON(card->number < 0 ||
|
||||
card->number >= ARRAY_SIZE(snd_ctl_led_card_valid)))
|
||||
return;
|
||||
mutex_lock(&snd_ctl_led_mutex);
|
||||
snd_ctl_led_card_valid[card->number] = true;
|
||||
mutex_unlock(&snd_ctl_led_mutex);
|
||||
/* the register callback is already called with held card->controls_rwsem */
|
||||
list_for_each_entry(kctl, &card->controls, list)
|
||||
for (ioff = 0; ioff < kctl->count; ioff++)
|
||||
snd_ctl_led_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, kctl, ioff);
|
||||
snd_ctl_led_refresh();
|
||||
snd_ctl_led_sysfs_add(card);
|
||||
}
|
||||
|
||||
static void snd_ctl_led_disconnect(struct snd_card *card)
|
||||
{
|
||||
snd_ctl_led_sysfs_remove(card);
|
||||
mutex_lock(&snd_ctl_led_mutex);
|
||||
snd_ctl_led_card_valid[card->number] = false;
|
||||
snd_ctl_led_clean(card);
|
||||
mutex_unlock(&snd_ctl_led_mutex);
|
||||
snd_ctl_led_refresh();
|
||||
}
|
||||
|
||||
/*
|
||||
* sysfs
|
||||
*/
|
||||
|
||||
static ssize_t show_mode(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev);
|
||||
const char *str;
|
||||
|
||||
switch (led->mode) {
|
||||
case MODE_FOLLOW_MUTE: str = "follow-mute"; break;
|
||||
case MODE_FOLLOW_ROUTE: str = "follow-route"; break;
|
||||
case MODE_ON: str = "on"; break;
|
||||
case MODE_OFF: str = "off"; break;
|
||||
}
|
||||
return sprintf(buf, "%s\n", str);
|
||||
}
|
||||
|
||||
static ssize_t store_mode(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev);
|
||||
char _buf[16];
|
||||
size_t l = min(count, sizeof(_buf) - 1);
|
||||
enum snd_ctl_led_mode mode;
|
||||
|
||||
memcpy(_buf, buf, l);
|
||||
_buf[l] = '\0';
|
||||
if (strstr(_buf, "mute"))
|
||||
mode = MODE_FOLLOW_MUTE;
|
||||
else if (strstr(_buf, "route"))
|
||||
mode = MODE_FOLLOW_ROUTE;
|
||||
else if (strncmp(_buf, "off", 3) == 0 || strncmp(_buf, "0", 1) == 0)
|
||||
mode = MODE_OFF;
|
||||
else if (strncmp(_buf, "on", 2) == 0 || strncmp(_buf, "1", 1) == 0)
|
||||
mode = MODE_ON;
|
||||
else
|
||||
return count;
|
||||
|
||||
mutex_lock(&snd_ctl_led_mutex);
|
||||
led->mode = mode;
|
||||
mutex_unlock(&snd_ctl_led_mutex);
|
||||
|
||||
snd_ctl_led_set_state(NULL, group_to_access(led->group), NULL, 0);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_brightness(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev);
|
||||
|
||||
return sprintf(buf, "%u\n", ledtrig_audio_get(led->trigger_type));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(mode, 0644, show_mode, store_mode);
|
||||
static DEVICE_ATTR(brightness, 0444, show_brightness, NULL);
|
||||
|
||||
static struct attribute *snd_ctl_led_dev_attrs[] = {
|
||||
&dev_attr_mode.attr,
|
||||
&dev_attr_brightness.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group snd_ctl_led_dev_attr_group = {
|
||||
.attrs = snd_ctl_led_dev_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *snd_ctl_led_dev_attr_groups[] = {
|
||||
&snd_ctl_led_dev_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static char *find_eos(char *s)
|
||||
{
|
||||
while (*s && *s != ',')
|
||||
s++;
|
||||
if (*s)
|
||||
s++;
|
||||
return s;
|
||||
}
|
||||
|
||||
static char *parse_uint(char *s, unsigned int *val)
|
||||
{
|
||||
unsigned long long res;
|
||||
if (kstrtoull(s, 10, &res))
|
||||
res = 0;
|
||||
*val = res;
|
||||
return find_eos(s);
|
||||
}
|
||||
|
||||
static char *parse_string(char *s, char *val, size_t val_size)
|
||||
{
|
||||
if (*s == '"' || *s == '\'') {
|
||||
char c = *s;
|
||||
s++;
|
||||
while (*s && *s != c) {
|
||||
if (val_size > 1) {
|
||||
*val++ = *s;
|
||||
val_size--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
} else {
|
||||
while (*s && *s != ',') {
|
||||
if (val_size > 1) {
|
||||
*val++ = *s;
|
||||
val_size--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
}
|
||||
*val = '\0';
|
||||
if (*s)
|
||||
s++;
|
||||
return s;
|
||||
}
|
||||
|
||||
static char *parse_iface(char *s, unsigned int *val)
|
||||
{
|
||||
if (!strncasecmp(s, "card", 4))
|
||||
*val = SNDRV_CTL_ELEM_IFACE_CARD;
|
||||
else if (!strncasecmp(s, "mixer", 5))
|
||||
*val = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
return find_eos(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* These types of input strings are accepted:
|
||||
*
|
||||
* unsigned integer - numid (equivaled to numid=UINT)
|
||||
* string - basic mixer name (equivalent to iface=MIXER,name=STR)
|
||||
* numid=UINT
|
||||
* [iface=MIXER,][device=UINT,][subdevice=UINT,]name=STR[,index=UINT]
|
||||
*/
|
||||
static ssize_t set_led_id(struct snd_ctl_led_card *led_card, const char *buf, size_t count,
|
||||
bool attach)
|
||||
{
|
||||
char buf2[256], *s, *os;
|
||||
size_t len = max(sizeof(s) - 1, count);
|
||||
struct snd_ctl_elem_id id;
|
||||
int err;
|
||||
|
||||
strncpy(buf2, buf, len);
|
||||
buf2[len] = '\0';
|
||||
memset(&id, 0, sizeof(id));
|
||||
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
s = buf2;
|
||||
while (*s) {
|
||||
os = s;
|
||||
if (!strncasecmp(s, "numid=", 6)) {
|
||||
s = parse_uint(s + 6, &id.numid);
|
||||
} else if (!strncasecmp(s, "iface=", 6)) {
|
||||
s = parse_iface(s + 6, &id.iface);
|
||||
} else if (!strncasecmp(s, "device=", 7)) {
|
||||
s = parse_uint(s + 7, &id.device);
|
||||
} else if (!strncasecmp(s, "subdevice=", 10)) {
|
||||
s = parse_uint(s + 10, &id.subdevice);
|
||||
} else if (!strncasecmp(s, "name=", 5)) {
|
||||
s = parse_string(s + 5, id.name, sizeof(id.name));
|
||||
} else if (!strncasecmp(s, "index=", 6)) {
|
||||
s = parse_uint(s + 6, &id.index);
|
||||
} else if (s == buf2) {
|
||||
while (*s) {
|
||||
if (*s < '0' || *s > '9')
|
||||
break;
|
||||
s++;
|
||||
}
|
||||
if (*s == '\0')
|
||||
parse_uint(buf2, &id.numid);
|
||||
else {
|
||||
for (; *s >= ' '; s++);
|
||||
*s = '\0';
|
||||
strlcpy(id.name, buf2, sizeof(id.name));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (*s == ',')
|
||||
s++;
|
||||
if (s == os)
|
||||
break;
|
||||
}
|
||||
|
||||
err = snd_ctl_led_set_id(led_card->number, &id, led_card->led->group, attach);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t parse_attach(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
|
||||
return set_led_id(led_card, buf, count, true);
|
||||
}
|
||||
|
||||
static ssize_t parse_detach(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
|
||||
return set_led_id(led_card, buf, count, false);
|
||||
}
|
||||
|
||||
static ssize_t ctl_reset(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
|
||||
int err;
|
||||
|
||||
if (count > 0 && buf[0] == '1') {
|
||||
err = snd_ctl_led_reset(led_card->number, led_card->led->group);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ctl_list(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
|
||||
struct snd_card *card;
|
||||
struct snd_ctl_led_ctl *lctl;
|
||||
char *buf2 = buf;
|
||||
size_t l;
|
||||
|
||||
card = snd_card_ref(led_card->number);
|
||||
if (!card)
|
||||
return -ENXIO;
|
||||
down_read(&card->controls_rwsem);
|
||||
mutex_lock(&snd_ctl_led_mutex);
|
||||
if (snd_ctl_led_card_valid[led_card->number]) {
|
||||
list_for_each_entry(lctl, &led_card->led->controls, list)
|
||||
if (lctl->card == card) {
|
||||
if (buf2 - buf > PAGE_SIZE - 16)
|
||||
break;
|
||||
if (buf2 != buf)
|
||||
*buf2++ = ' ';
|
||||
l = scnprintf(buf2, 15, "%u",
|
||||
lctl->kctl->id.numid +
|
||||
lctl->index_offset);
|
||||
buf2[l] = '\0';
|
||||
buf2 += l + 1;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&snd_ctl_led_mutex);
|
||||
up_read(&card->controls_rwsem);
|
||||
snd_card_unref(card);
|
||||
return buf2 - buf;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(attach, 0200, NULL, parse_attach);
|
||||
static DEVICE_ATTR(detach, 0200, NULL, parse_detach);
|
||||
static DEVICE_ATTR(reset, 0200, NULL, ctl_reset);
|
||||
static DEVICE_ATTR(list, 0444, ctl_list, NULL);
|
||||
|
||||
static struct attribute *snd_ctl_led_card_attrs[] = {
|
||||
&dev_attr_attach.attr,
|
||||
&dev_attr_detach.attr,
|
||||
&dev_attr_reset.attr,
|
||||
&dev_attr_list.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group snd_ctl_led_card_attr_group = {
|
||||
.attrs = snd_ctl_led_card_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *snd_ctl_led_card_attr_groups[] = {
|
||||
&snd_ctl_led_card_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct device snd_ctl_led_dev;
|
||||
|
||||
static void snd_ctl_led_sysfs_add(struct snd_card *card)
|
||||
{
|
||||
unsigned int group;
|
||||
struct snd_ctl_led_card *led_card;
|
||||
struct snd_ctl_led *led;
|
||||
char link_name[32];
|
||||
|
||||
for (group = 0; group < MAX_LED; group++) {
|
||||
led = &snd_ctl_leds[group];
|
||||
led_card = kzalloc(sizeof(*led_card), GFP_KERNEL);
|
||||
if (!led_card)
|
||||
goto cerr2;
|
||||
led_card->number = card->number;
|
||||
led_card->led = led;
|
||||
device_initialize(&led_card->dev);
|
||||
if (dev_set_name(&led_card->dev, "card%d", card->number) < 0)
|
||||
goto cerr;
|
||||
led_card->dev.parent = &led->dev;
|
||||
led_card->dev.groups = snd_ctl_led_card_attr_groups;
|
||||
if (device_add(&led_card->dev))
|
||||
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),
|
||||
"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);
|
||||
|
||||
continue;
|
||||
cerr:
|
||||
put_device(&led_card->dev);
|
||||
cerr2:
|
||||
printk(KERN_ERR "snd_ctl_led: unable to add card%d", card->number);
|
||||
kfree(led_card);
|
||||
}
|
||||
}
|
||||
|
||||
static void snd_ctl_led_sysfs_remove(struct snd_card *card)
|
||||
{
|
||||
unsigned int group;
|
||||
struct snd_ctl_led_card *led_card;
|
||||
struct snd_ctl_led *led;
|
||||
char link_name[32];
|
||||
|
||||
for (group = 0; group < MAX_LED; group++) {
|
||||
led = &snd_ctl_leds[group];
|
||||
led_card = led->cards[card->number];
|
||||
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(&led_card->dev.kobj, "card");
|
||||
device_del(&led_card->dev);
|
||||
kfree(led_card);
|
||||
led->cards[card->number] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Control layer registration
|
||||
*/
|
||||
static struct snd_ctl_layer_ops snd_ctl_led_lops = {
|
||||
.module_name = SND_CTL_LAYER_MODULE_LED,
|
||||
.lregister = snd_ctl_led_register,
|
||||
.ldisconnect = snd_ctl_led_disconnect,
|
||||
.lnotify = snd_ctl_led_notify,
|
||||
};
|
||||
|
||||
static int __init snd_ctl_led_init(void)
|
||||
{
|
||||
struct snd_ctl_led *led;
|
||||
unsigned int group;
|
||||
|
||||
device_initialize(&snd_ctl_led_dev);
|
||||
snd_ctl_led_dev.class = sound_class;
|
||||
dev_set_name(&snd_ctl_led_dev, "ctl-led");
|
||||
if (device_add(&snd_ctl_led_dev)) {
|
||||
put_device(&snd_ctl_led_dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (group = 0; group < MAX_LED; group++) {
|
||||
led = &snd_ctl_leds[group];
|
||||
INIT_LIST_HEAD(&led->controls);
|
||||
device_initialize(&led->dev);
|
||||
led->dev.parent = &snd_ctl_led_dev;
|
||||
led->dev.groups = snd_ctl_led_dev_attr_groups;
|
||||
dev_set_name(&led->dev, led->name);
|
||||
if (device_add(&led->dev)) {
|
||||
put_device(&led->dev);
|
||||
for (; group > 0; group--) {
|
||||
led = &snd_ctl_leds[group - 1];
|
||||
device_del(&led->dev);
|
||||
}
|
||||
device_del(&snd_ctl_led_dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
snd_ctl_register_layer(&snd_ctl_led_lops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit snd_ctl_led_exit(void)
|
||||
{
|
||||
struct snd_ctl_led *led;
|
||||
struct snd_card *card;
|
||||
unsigned int group, card_number;
|
||||
|
||||
snd_ctl_disconnect_layer(&snd_ctl_led_lops);
|
||||
for (card_number = 0; card_number < SNDRV_CARDS; card_number++) {
|
||||
if (!snd_ctl_led_card_valid[card_number])
|
||||
continue;
|
||||
card = snd_card_ref(card_number);
|
||||
if (card) {
|
||||
snd_ctl_led_sysfs_remove(card);
|
||||
snd_card_unref(card);
|
||||
}
|
||||
}
|
||||
for (group = 0; group < MAX_LED; group++) {
|
||||
led = &snd_ctl_leds[group];
|
||||
device_del(&led->dev);
|
||||
}
|
||||
device_del(&snd_ctl_led_dev);
|
||||
snd_ctl_led_clean(NULL);
|
||||
}
|
||||
|
||||
module_init(snd_ctl_led_init)
|
||||
module_exit(snd_ctl_led_exit)
|
@ -398,10 +398,8 @@ int snd_card_disconnect(struct snd_card *card)
|
||||
return 0;
|
||||
}
|
||||
card->shutdown = 1;
|
||||
spin_unlock(&card->files_lock);
|
||||
|
||||
/* replace file->f_op with special dummy operations */
|
||||
spin_lock(&card->files_lock);
|
||||
list_for_each_entry(mfile, &card->files_list, list) {
|
||||
/* it's critical part, use endless loop */
|
||||
/* we have no room to fail */
|
||||
|
@ -3069,8 +3069,12 @@ static void snd_pcm_oss_proc_done(struct snd_pcm *pcm)
|
||||
}
|
||||
}
|
||||
#else /* !CONFIG_SND_VERBOSE_PROCFS */
|
||||
#define snd_pcm_oss_proc_init(pcm)
|
||||
#define snd_pcm_oss_proc_done(pcm)
|
||||
static inline void snd_pcm_oss_proc_init(struct snd_pcm *pcm)
|
||||
{
|
||||
}
|
||||
static inline void snd_pcm_oss_proc_done(struct snd_pcm *pcm)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_SND_VERBOSE_PROCFS */
|
||||
|
||||
/*
|
||||
|
@ -176,6 +176,10 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
|
||||
substream->dma_buffer.dev.dev,
|
||||
size, &new_dmab) < 0) {
|
||||
buffer->error = -ENOMEM;
|
||||
pr_debug("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",
|
||||
substream->pcm->card->number, substream->pcm->device,
|
||||
substream->stream ? 'c' : 'p', substream->number,
|
||||
substream->pcm->name, size);
|
||||
return;
|
||||
}
|
||||
substream->buffer_bytes_max = size;
|
||||
@ -210,7 +214,9 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream)
|
||||
}
|
||||
|
||||
#else /* !CONFIG_SND_VERBOSE_PROCFS */
|
||||
#define preallocate_info_init(s)
|
||||
static inline void preallocate_info_init(struct snd_pcm_substream *substream)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_SND_VERBOSE_PROCFS */
|
||||
|
||||
/*
|
||||
@ -400,6 +406,10 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
|
||||
substream->dma_buffer.dev.dev,
|
||||
size, dmab) < 0) {
|
||||
kfree(dmab);
|
||||
pr_debug("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",
|
||||
substream->pcm->card->number, substream->pcm->device,
|
||||
substream->stream ? 'c' : 'p', substream->number,
|
||||
substream->pcm->name, size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
@ -1425,7 +1425,7 @@ static int snd_pcm_do_stop(struct snd_pcm_substream *substream,
|
||||
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
|
||||
substream->runtime->stop_operating = true;
|
||||
}
|
||||
return 0; /* unconditonally stop all substreams */
|
||||
return 0; /* unconditionally stop all substreams */
|
||||
}
|
||||
|
||||
static void snd_pcm_post_stop(struct snd_pcm_substream *substream,
|
||||
@ -1469,7 +1469,7 @@ EXPORT_SYMBOL(snd_pcm_stop);
|
||||
* After stopping, the state is changed to SETUP.
|
||||
* Unlike snd_pcm_stop(), this affects only the given stream.
|
||||
*
|
||||
* Return: Zero if succesful, or a negative error code.
|
||||
* Return: Zero if successful, or a negative error code.
|
||||
*/
|
||||
int snd_pcm_drain_done(struct snd_pcm_substream *substream)
|
||||
{
|
||||
|
@ -133,10 +133,19 @@ void snd_seq_device_load_drivers(void)
|
||||
flush_work(&autoload_work);
|
||||
}
|
||||
EXPORT_SYMBOL(snd_seq_device_load_drivers);
|
||||
#define cancel_autoload_drivers() cancel_work_sync(&autoload_work)
|
||||
|
||||
static inline void cancel_autoload_drivers(void)
|
||||
{
|
||||
cancel_work_sync(&autoload_work);
|
||||
}
|
||||
#else
|
||||
#define queue_autoload_drivers() /* NOP */
|
||||
#define cancel_autoload_drivers() /* NOP */
|
||||
static inline void queue_autoload_drivers(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void cancel_autoload_drivers(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -402,7 +402,7 @@ int vx_send_rih(struct vx_core *chip, int cmd)
|
||||
#define END_OF_RESET_WAIT_TIME 500 /* us */
|
||||
|
||||
/**
|
||||
* snd_vx_boot_xilinx - boot up the xilinx interface
|
||||
* snd_vx_load_boot_image - boot up the xilinx interface
|
||||
* @chip: VX core instance
|
||||
* @boot: the boot record to load
|
||||
*/
|
||||
|
@ -200,6 +200,8 @@ int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit,
|
||||
int avc_bridgeco_get_plug_type(struct fw_unit *unit,
|
||||
u8 addr[AVC_BRIDGECO_ADDR_BYTES],
|
||||
enum avc_bridgeco_plug_type *type);
|
||||
int avc_bridgeco_get_plug_ch_count(struct fw_unit *unit, u8 addr[AVC_BRIDGECO_ADDR_BYTES],
|
||||
unsigned int *ch_count);
|
||||
int avc_bridgeco_get_plug_section_type(struct fw_unit *unit,
|
||||
u8 addr[AVC_BRIDGECO_ADDR_BYTES],
|
||||
unsigned int id, u8 *type);
|
||||
|
@ -143,6 +143,42 @@ end:
|
||||
return err;
|
||||
}
|
||||
|
||||
int avc_bridgeco_get_plug_ch_count(struct fw_unit *unit, u8 addr[AVC_BRIDGECO_ADDR_BYTES],
|
||||
unsigned int *ch_count)
|
||||
{
|
||||
u8 *buf;
|
||||
int err;
|
||||
|
||||
buf = kzalloc(12, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
// Info type is 'plug type'.
|
||||
avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x02);
|
||||
|
||||
err = fcp_avc_transaction(unit, buf, 12, buf, 12,
|
||||
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
|
||||
BIT(6) | BIT(7) | BIT(9));
|
||||
if (err < 0)
|
||||
;
|
||||
else if (err < 11)
|
||||
err = -EIO;
|
||||
else if (buf[0] == 0x08) // NOT IMPLEMENTED
|
||||
err = -ENOSYS;
|
||||
else if (buf[0] == 0x0a) // REJECTED
|
||||
err = -EINVAL;
|
||||
else if (buf[0] == 0x0b) // IN TRANSITION
|
||||
err = -EAGAIN;
|
||||
if (err < 0)
|
||||
goto end;
|
||||
|
||||
*ch_count = buf[10];
|
||||
err = 0;
|
||||
end:
|
||||
kfree(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit,
|
||||
u8 addr[AVC_BRIDGECO_ADDR_BYTES],
|
||||
u8 *buf, unsigned int len)
|
||||
|
@ -517,20 +517,22 @@ int snd_bebob_stream_init_duplex(struct snd_bebob *bebob)
|
||||
static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream,
|
||||
unsigned int rate, unsigned int index)
|
||||
{
|
||||
struct snd_bebob_stream_formation *formation;
|
||||
unsigned int pcm_channels;
|
||||
unsigned int midi_ports;
|
||||
struct cmp_connection *conn;
|
||||
int err;
|
||||
|
||||
if (stream == &bebob->tx_stream) {
|
||||
formation = bebob->tx_stream_formations + index;
|
||||
pcm_channels = bebob->tx_stream_formations[index].pcm;
|
||||
midi_ports = bebob->midi_input_ports;
|
||||
conn = &bebob->out_conn;
|
||||
} else {
|
||||
formation = bebob->rx_stream_formations + index;
|
||||
pcm_channels = bebob->rx_stream_formations[index].pcm;
|
||||
midi_ports = bebob->midi_output_ports;
|
||||
conn = &bebob->in_conn;
|
||||
}
|
||||
|
||||
err = amdtp_am824_set_parameters(stream, rate, formation->pcm,
|
||||
formation->midi, false);
|
||||
err = amdtp_am824_set_parameters(stream, rate, pcm_channels, midi_ports, false);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@ -796,42 +798,42 @@ parse_stream_formation(u8 *buf, unsigned int len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fill_stream_formations(struct snd_bebob *bebob, enum avc_bridgeco_plug_dir dir,
|
||||
unsigned short pid)
|
||||
static int fill_stream_formations(struct snd_bebob *bebob, u8 addr[AVC_BRIDGECO_ADDR_BYTES],
|
||||
enum avc_bridgeco_plug_dir plug_dir, unsigned int plug_id,
|
||||
struct snd_bebob_stream_formation *formations)
|
||||
{
|
||||
enum avc_bridgeco_plug_type plug_type;
|
||||
u8 *buf;
|
||||
struct snd_bebob_stream_formation *formations;
|
||||
unsigned int len, eid;
|
||||
u8 addr[AVC_BRIDGECO_ADDR_BYTES];
|
||||
int err;
|
||||
|
||||
avc_bridgeco_fill_unit_addr(addr, plug_dir, AVC_BRIDGECO_PLUG_UNIT_ISOC, plug_id);
|
||||
|
||||
err = avc_bridgeco_get_plug_type(bebob->unit, addr, &plug_type);
|
||||
if (err < 0) {
|
||||
dev_err(&bebob->unit->device,
|
||||
"Fail to get type for isoc %d plug 0: %d\n", plug_dir, err);
|
||||
return err;
|
||||
} else if (plug_type != AVC_BRIDGECO_PLUG_TYPE_ISOC)
|
||||
return -ENXIO;
|
||||
|
||||
buf = kmalloc(FORMAT_MAXIMUM_LENGTH, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (dir == AVC_BRIDGECO_PLUG_DIR_IN)
|
||||
formations = bebob->rx_stream_formations;
|
||||
else
|
||||
formations = bebob->tx_stream_formations;
|
||||
for (eid = 0; eid < SND_BEBOB_STRM_FMT_ENTRIES; ++eid) {
|
||||
avc_bridgeco_fill_unit_addr(addr, plug_dir, AVC_BRIDGECO_PLUG_UNIT_ISOC, plug_id);
|
||||
|
||||
for (eid = 0; eid < SND_BEBOB_STRM_FMT_ENTRIES; eid++) {
|
||||
len = FORMAT_MAXIMUM_LENGTH;
|
||||
avc_bridgeco_fill_unit_addr(addr, dir,
|
||||
AVC_BRIDGECO_PLUG_UNIT_ISOC, pid);
|
||||
err = avc_bridgeco_get_plug_strm_fmt(bebob->unit, addr, buf,
|
||||
&len, eid);
|
||||
/* No entries remained. */
|
||||
err = avc_bridgeco_get_plug_strm_fmt(bebob->unit, addr, buf, &len, eid);
|
||||
// No entries remained.
|
||||
if (err == -EINVAL && eid > 0) {
|
||||
err = 0;
|
||||
break;
|
||||
} else if (err < 0) {
|
||||
dev_err(&bebob->unit->device,
|
||||
"fail to get stream format %d for isoc %s plug %d:%d\n",
|
||||
eid,
|
||||
(dir == AVC_BRIDGECO_PLUG_DIR_IN) ? "in" :
|
||||
"out",
|
||||
pid, err);
|
||||
"fail to get stream format %d for isoc %d plug %d:%d\n",
|
||||
eid, plug_dir, plug_id, err);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -844,6 +846,49 @@ fill_stream_formations(struct snd_bebob *bebob, enum avc_bridgeco_plug_dir dir,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int detect_midi_ports(struct snd_bebob *bebob,
|
||||
const struct snd_bebob_stream_formation *formats,
|
||||
u8 addr[AVC_BRIDGECO_ADDR_BYTES], enum avc_bridgeco_plug_dir plug_dir,
|
||||
unsigned int plug_count, unsigned int *midi_ports)
|
||||
{
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
*midi_ports = 0;
|
||||
|
||||
/// Detect the number of available MIDI ports when packet has MIDI conformant data channel.
|
||||
for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; ++i) {
|
||||
if (formats[i].midi > 0)
|
||||
break;
|
||||
}
|
||||
if (i >= SND_BEBOB_STRM_FMT_ENTRIES)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < plug_count; ++i) {
|
||||
enum avc_bridgeco_plug_type plug_type;
|
||||
unsigned int ch_count;
|
||||
|
||||
avc_bridgeco_fill_unit_addr(addr, plug_dir, AVC_BRIDGECO_PLUG_UNIT_EXT, i);
|
||||
|
||||
err = avc_bridgeco_get_plug_type(bebob->unit, addr, &plug_type);
|
||||
if (err < 0) {
|
||||
dev_err(&bebob->unit->device,
|
||||
"fail to get type for external %d plug %d: %d\n",
|
||||
plug_dir, i, err);
|
||||
break;
|
||||
} else if (plug_type != AVC_BRIDGECO_PLUG_TYPE_MIDI) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = avc_bridgeco_get_plug_ch_count(bebob->unit, addr, &ch_count);
|
||||
if (err < 0)
|
||||
break;
|
||||
*midi_ports += ch_count;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
seek_msu_sync_input_plug(struct snd_bebob *bebob)
|
||||
{
|
||||
@ -886,8 +931,6 @@ int snd_bebob_stream_discover(struct snd_bebob *bebob)
|
||||
{
|
||||
const struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock;
|
||||
u8 plugs[AVC_PLUG_INFO_BUF_BYTES], addr[AVC_BRIDGECO_ADDR_BYTES];
|
||||
enum avc_bridgeco_plug_type type;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
/* the number of plugs for isoc in/out, ext in/out */
|
||||
@ -908,67 +951,25 @@ int snd_bebob_stream_discover(struct snd_bebob *bebob)
|
||||
goto end;
|
||||
}
|
||||
|
||||
avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN,
|
||||
AVC_BRIDGECO_PLUG_UNIT_ISOC, 0);
|
||||
err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type);
|
||||
if (err < 0) {
|
||||
dev_err(&bebob->unit->device,
|
||||
"fail to get type for isoc in plug 0: %d\n", err);
|
||||
goto end;
|
||||
} else if (type != AVC_BRIDGECO_PLUG_TYPE_ISOC) {
|
||||
err = -ENOSYS;
|
||||
goto end;
|
||||
}
|
||||
err = fill_stream_formations(bebob, AVC_BRIDGECO_PLUG_DIR_IN, 0);
|
||||
err = fill_stream_formations(bebob, addr, AVC_BRIDGECO_PLUG_DIR_IN, 0,
|
||||
bebob->rx_stream_formations);
|
||||
if (err < 0)
|
||||
goto end;
|
||||
|
||||
avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_OUT,
|
||||
AVC_BRIDGECO_PLUG_UNIT_ISOC, 0);
|
||||
err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type);
|
||||
if (err < 0) {
|
||||
dev_err(&bebob->unit->device,
|
||||
"fail to get type for isoc out plug 0: %d\n", err);
|
||||
goto end;
|
||||
} else if (type != AVC_BRIDGECO_PLUG_TYPE_ISOC) {
|
||||
err = -ENOSYS;
|
||||
goto end;
|
||||
}
|
||||
err = fill_stream_formations(bebob, AVC_BRIDGECO_PLUG_DIR_OUT, 0);
|
||||
err = fill_stream_formations(bebob, addr, AVC_BRIDGECO_PLUG_DIR_OUT, 0,
|
||||
bebob->tx_stream_formations);
|
||||
if (err < 0)
|
||||
goto end;
|
||||
|
||||
/* count external input plugs for MIDI */
|
||||
bebob->midi_input_ports = 0;
|
||||
for (i = 0; i < plugs[2]; i++) {
|
||||
avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN,
|
||||
AVC_BRIDGECO_PLUG_UNIT_EXT, i);
|
||||
err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type);
|
||||
if (err < 0) {
|
||||
dev_err(&bebob->unit->device,
|
||||
"fail to get type for external in plug %d: %d\n",
|
||||
i, err);
|
||||
goto end;
|
||||
} else if (type == AVC_BRIDGECO_PLUG_TYPE_MIDI) {
|
||||
bebob->midi_input_ports++;
|
||||
}
|
||||
}
|
||||
err = detect_midi_ports(bebob, bebob->rx_stream_formations, addr, AVC_BRIDGECO_PLUG_DIR_IN,
|
||||
plugs[2], &bebob->midi_input_ports);
|
||||
if (err < 0)
|
||||
goto end;
|
||||
|
||||
/* count external output plugs for MIDI */
|
||||
bebob->midi_output_ports = 0;
|
||||
for (i = 0; i < plugs[3]; i++) {
|
||||
avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_OUT,
|
||||
AVC_BRIDGECO_PLUG_UNIT_EXT, i);
|
||||
err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type);
|
||||
if (err < 0) {
|
||||
dev_err(&bebob->unit->device,
|
||||
"fail to get type for external out plug %d: %d\n",
|
||||
i, err);
|
||||
goto end;
|
||||
} else if (type == AVC_BRIDGECO_PLUG_TYPE_MIDI) {
|
||||
bebob->midi_output_ports++;
|
||||
}
|
||||
}
|
||||
err = detect_midi_ports(bebob, bebob->tx_stream_formations, addr, AVC_BRIDGECO_PLUG_DIR_OUT,
|
||||
plugs[3], &bebob->midi_output_ports);
|
||||
if (err < 0)
|
||||
goto end;
|
||||
|
||||
/* for check source of clock later */
|
||||
if (!clk_spec)
|
||||
|
@ -21,17 +21,16 @@ config SND_HDA_EXT_CORE
|
||||
select SND_HDA_CORE
|
||||
|
||||
config SND_HDA_PREALLOC_SIZE
|
||||
int "Pre-allocated buffer size for HD-audio driver"
|
||||
int "Pre-allocated buffer size for HD-audio driver" if !SND_DMA_SGBUF
|
||||
range 0 32768
|
||||
default 2048 if SND_DMA_SGBUF
|
||||
default 0 if SND_DMA_SGBUF
|
||||
default 64 if !SND_DMA_SGBUF
|
||||
help
|
||||
Specifies the default pre-allocated buffer-size in kB for the
|
||||
HD-audio driver. A larger buffer (e.g. 2048) is preferred
|
||||
for systems using PulseAudio. The default 64 is chosen just
|
||||
for compatibility reasons.
|
||||
On x86 systems, the default is 2048 as a reasonable value for
|
||||
most of modern systems.
|
||||
On x86 systems, the default is zero as we need no preallocation.
|
||||
|
||||
Note that the pre-allocation size can be changed dynamically
|
||||
via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too.
|
||||
|
@ -618,7 +618,7 @@ void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set,
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_stream_sync_trigger);
|
||||
|
||||
/**
|
||||
* snd_hdac_stream_sync - sync with start/strop trigger operation
|
||||
* snd_hdac_stream_sync - sync with start/stop trigger operation
|
||||
* @azx_dev: HD-audio core stream (master stream)
|
||||
* @start: true = start, false = stop
|
||||
* @streams: bit flags of streams to sync
|
||||
|
@ -1029,8 +1029,10 @@ snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
|
||||
|
||||
memset(emu->controls, 0, sizeof(emu->controls));
|
||||
for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
|
||||
if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0)
|
||||
if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0) {
|
||||
emu->controls[i] = NULL;
|
||||
goto __error;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
@ -1045,10 +1045,14 @@ static int snd_sb_qsound_build(struct snd_sb_csp * p)
|
||||
|
||||
spin_lock_init(&p->q_lock);
|
||||
|
||||
if ((err = snd_ctl_add(card, p->qsound_switch = snd_ctl_new1(&snd_sb_qsound_switch, p))) < 0)
|
||||
if ((err = snd_ctl_add(card, p->qsound_switch = snd_ctl_new1(&snd_sb_qsound_switch, p))) < 0) {
|
||||
p->qsound_switch = NULL;
|
||||
goto __error;
|
||||
if ((err = snd_ctl_add(card, p->qsound_space = snd_ctl_new1(&snd_sb_qsound_space, p))) < 0)
|
||||
}
|
||||
if ((err = snd_ctl_add(card, p->qsound_space = snd_ctl_new1(&snd_sb_qsound_space, p))) < 0) {
|
||||
p->qsound_space = NULL;
|
||||
goto __error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
|
||||
AudioScience HPI driver
|
||||
Copyright (C) 1997-2014 AudioScience Inc. <support@audioscience.com>
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/***********************************************************************/
|
||||
/**
|
||||
/*
|
||||
|
||||
AudioScience HPI driver
|
||||
Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*/
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*/
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctamixer.c
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctamixer.h
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctatc.c
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctatc.h
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctdaio.c
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctdaio.h
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File cthardware.h
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File cthw20k1.h
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File cthw20k2.h
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctimap.h
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctmixer.h
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctpcm.h
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctresource.c
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctresource.h
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctsrc.c
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctsrc.h
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctvmem.c
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
|
||||
*
|
||||
* @File ctvmem.h
|
||||
|
@ -221,10 +221,8 @@ comment "Set to Y if you want auto-loading the codec driver"
|
||||
|
||||
config SND_HDA_GENERIC
|
||||
tristate "Enable generic HD-audio codec parser"
|
||||
select NEW_LEDS if SND_HDA_GENERIC_LEDS
|
||||
select SND_CTL_LED if SND_HDA_GENERIC_LEDS
|
||||
select LEDS_CLASS if SND_HDA_GENERIC_LEDS
|
||||
select LEDS_TRIGGERS if SND_HDA_GENERIC_LEDS
|
||||
select LEDS_TRIGGER_AUDIO if SND_HDA_GENERIC_LEDS
|
||||
help
|
||||
Say Y or M here to enable the generic HD-audio codec parser
|
||||
in snd-hda-intel driver.
|
||||
|
@ -27,7 +27,7 @@ enum {
|
||||
};
|
||||
|
||||
#define AUTO_CFG_MAX_OUTS HDA_MAX_OUTS
|
||||
#define AUTO_CFG_MAX_INS 8
|
||||
#define AUTO_CFG_MAX_INS 18
|
||||
|
||||
struct auto_pin_cfg_item {
|
||||
hda_nid_t pin;
|
||||
|
@ -1938,6 +1938,7 @@ static int add_follower(struct hda_codec *codec,
|
||||
* @followers: follower control names (optional)
|
||||
* @suffix: suffix string to each follower name (optional)
|
||||
* @init_follower_vol: initialize followers to unmute/0dB
|
||||
* @access: kcontrol access rights
|
||||
* @ctl_ret: store the vmaster kcontrol in return
|
||||
*
|
||||
* Create a virtual master control with the given name. The TLV data
|
||||
@ -1952,7 +1953,7 @@ static int add_follower(struct hda_codec *codec,
|
||||
int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
|
||||
unsigned int *tlv, const char * const *followers,
|
||||
const char *suffix, bool init_follower_vol,
|
||||
struct snd_kcontrol **ctl_ret)
|
||||
unsigned int access, struct snd_kcontrol **ctl_ret)
|
||||
{
|
||||
struct snd_kcontrol *kctl;
|
||||
int err;
|
||||
@ -1968,6 +1969,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
|
||||
kctl = snd_ctl_make_virtual_master(name, tlv);
|
||||
if (!kctl)
|
||||
return -ENOMEM;
|
||||
kctl->vd[0].access |= access;
|
||||
err = snd_hda_ctl_add(codec, 0, kctl);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -1994,87 +1996,29 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__snd_hda_add_vmaster);
|
||||
|
||||
/*
|
||||
* mute-LED control using vmaster
|
||||
*/
|
||||
static int vmaster_mute_mode_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
static const char * const texts[] = {
|
||||
"On", "Off", "Follow Master"
|
||||
};
|
||||
|
||||
return snd_ctl_enum_info(uinfo, 1, 3, texts);
|
||||
}
|
||||
|
||||
static int vmaster_mute_mode_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol);
|
||||
ucontrol->value.enumerated.item[0] = hook->mute_mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vmaster_mute_mode_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol);
|
||||
unsigned int old_mode = hook->mute_mode;
|
||||
|
||||
hook->mute_mode = ucontrol->value.enumerated.item[0];
|
||||
if (hook->mute_mode > HDA_VMUTE_FOLLOW_MASTER)
|
||||
hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
|
||||
if (old_mode == hook->mute_mode)
|
||||
return 0;
|
||||
snd_hda_sync_vmaster_hook(hook);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new vmaster_mute_mode = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.name = "Mute-LED Mode",
|
||||
.info = vmaster_mute_mode_info,
|
||||
.get = vmaster_mute_mode_get,
|
||||
.put = vmaster_mute_mode_put,
|
||||
};
|
||||
|
||||
/* meta hook to call each driver's vmaster hook */
|
||||
static void vmaster_hook(void *private_data, int enabled)
|
||||
{
|
||||
struct hda_vmaster_mute_hook *hook = private_data;
|
||||
|
||||
if (hook->mute_mode != HDA_VMUTE_FOLLOW_MASTER)
|
||||
enabled = hook->mute_mode;
|
||||
hook->hook(hook->codec, enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_hda_add_vmaster_hook - Add a vmaster hook for mute-LED
|
||||
* snd_hda_add_vmaster_hook - Add a vmaster hw specific hook
|
||||
* @codec: the HDA codec
|
||||
* @hook: the vmaster hook object
|
||||
* @expose_enum_ctl: flag to create an enum ctl
|
||||
*
|
||||
* Add a mute-LED hook with the given vmaster switch kctl.
|
||||
* When @expose_enum_ctl is set, "Mute-LED Mode" control is automatically
|
||||
* created and associated with the given hook.
|
||||
* Add a hw specific hook (like EAPD) with the given vmaster switch kctl.
|
||||
*/
|
||||
int snd_hda_add_vmaster_hook(struct hda_codec *codec,
|
||||
struct hda_vmaster_mute_hook *hook,
|
||||
bool expose_enum_ctl)
|
||||
struct hda_vmaster_mute_hook *hook)
|
||||
{
|
||||
struct snd_kcontrol *kctl;
|
||||
|
||||
if (!hook->hook || !hook->sw_kctl)
|
||||
return 0;
|
||||
hook->codec = codec;
|
||||
hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
|
||||
snd_ctl_add_vmaster_hook(hook->sw_kctl, vmaster_hook, hook);
|
||||
if (!expose_enum_ctl)
|
||||
return 0;
|
||||
kctl = snd_ctl_new1(&vmaster_mute_mode, hook);
|
||||
if (!kctl)
|
||||
return -ENOMEM;
|
||||
return snd_hda_ctl_add(codec, 0, kctl);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_add_vmaster_hook);
|
||||
|
||||
|
@ -981,6 +981,8 @@ add_control(struct hda_gen_spec *spec, int type, const char *name,
|
||||
knew->index = cidx;
|
||||
if (get_amp_nid_(val))
|
||||
knew->subdevice = HDA_SUBDEV_AMP_FLAG;
|
||||
if (knew->access == 0)
|
||||
knew->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
|
||||
knew->private_value = val;
|
||||
return knew;
|
||||
}
|
||||
@ -3618,8 +3620,11 @@ static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
|
||||
amp_val_replace_channels(ctl, chs));
|
||||
if (!knew)
|
||||
return -ENOMEM;
|
||||
if (is_switch)
|
||||
if (is_switch) {
|
||||
knew->put = cap_single_sw_put;
|
||||
if (spec->mic_mute_led)
|
||||
knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
|
||||
}
|
||||
if (!inv_dmic)
|
||||
return 0;
|
||||
|
||||
@ -3634,8 +3639,11 @@ static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
|
||||
amp_val_replace_channels(ctl, 2));
|
||||
if (!knew)
|
||||
return -ENOMEM;
|
||||
if (is_switch)
|
||||
if (is_switch) {
|
||||
knew->put = cap_single_sw_put;
|
||||
if (spec->mic_mute_led)
|
||||
knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3676,6 +3684,8 @@ static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
|
||||
knew->index = idx;
|
||||
knew->private_value = sw_ctl;
|
||||
knew->subdevice = HDA_SUBDEV_AMP_FLAG;
|
||||
if (spec->mic_mute_led)
|
||||
knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -3917,11 +3927,6 @@ static int create_mute_led_cdev(struct hda_codec *codec,
|
||||
return devm_led_classdev_register(&codec->core.dev, cdev);
|
||||
}
|
||||
|
||||
static void vmaster_update_mute_led(void *private_data, int enabled)
|
||||
{
|
||||
ledtrig_audio_set(LED_AUDIO_MUTE, enabled ? LED_OFF : LED_ON);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_hda_gen_add_mute_led_cdev - Create a LED classdev and enable as vmaster mute LED
|
||||
* @codec: the HDA codec
|
||||
@ -3945,134 +3950,11 @@ int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
|
||||
if (spec->vmaster_mute.hook)
|
||||
codec_err(codec, "vmaster hook already present before cdev!\n");
|
||||
|
||||
spec->vmaster_mute.hook = vmaster_update_mute_led;
|
||||
spec->vmaster_mute_enum = 1;
|
||||
spec->vmaster_mute_led = 1;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_gen_add_mute_led_cdev);
|
||||
|
||||
/*
|
||||
* mic mute LED hook helpers
|
||||
*/
|
||||
enum {
|
||||
MICMUTE_LED_ON,
|
||||
MICMUTE_LED_OFF,
|
||||
MICMUTE_LED_FOLLOW_CAPTURE,
|
||||
MICMUTE_LED_FOLLOW_MUTE,
|
||||
};
|
||||
|
||||
static void call_micmute_led_update(struct hda_codec *codec)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
unsigned int val;
|
||||
|
||||
switch (spec->micmute_led.led_mode) {
|
||||
case MICMUTE_LED_ON:
|
||||
val = 1;
|
||||
break;
|
||||
case MICMUTE_LED_OFF:
|
||||
val = 0;
|
||||
break;
|
||||
case MICMUTE_LED_FOLLOW_CAPTURE:
|
||||
val = !!spec->micmute_led.capture;
|
||||
break;
|
||||
case MICMUTE_LED_FOLLOW_MUTE:
|
||||
default:
|
||||
val = !spec->micmute_led.capture;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val == spec->micmute_led.led_value)
|
||||
return;
|
||||
spec->micmute_led.led_value = val;
|
||||
ledtrig_audio_set(LED_AUDIO_MICMUTE,
|
||||
spec->micmute_led.led_value ? LED_ON : LED_OFF);
|
||||
}
|
||||
|
||||
static void update_micmute_led(struct hda_codec *codec,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
unsigned int mask;
|
||||
|
||||
if (spec->micmute_led.old_hook)
|
||||
spec->micmute_led.old_hook(codec, kcontrol, ucontrol);
|
||||
|
||||
if (!ucontrol)
|
||||
return;
|
||||
mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
|
||||
if (!strcmp("Capture Switch", ucontrol->id.name)) {
|
||||
/* TODO: How do I verify if it's a mono or stereo here? */
|
||||
if (ucontrol->value.integer.value[0] ||
|
||||
ucontrol->value.integer.value[1])
|
||||
spec->micmute_led.capture |= mask;
|
||||
else
|
||||
spec->micmute_led.capture &= ~mask;
|
||||
call_micmute_led_update(codec);
|
||||
}
|
||||
}
|
||||
|
||||
static int micmute_led_mode_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
static const char * const texts[] = {
|
||||
"On", "Off", "Follow Capture", "Follow Mute",
|
||||
};
|
||||
|
||||
return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
|
||||
}
|
||||
|
||||
static int micmute_led_mode_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
|
||||
ucontrol->value.enumerated.item[0] = spec->micmute_led.led_mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int micmute_led_mode_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
unsigned int mode;
|
||||
|
||||
mode = ucontrol->value.enumerated.item[0];
|
||||
if (mode > MICMUTE_LED_FOLLOW_MUTE)
|
||||
mode = MICMUTE_LED_FOLLOW_MUTE;
|
||||
if (mode == spec->micmute_led.led_mode)
|
||||
return 0;
|
||||
spec->micmute_led.led_mode = mode;
|
||||
call_micmute_led_update(codec);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new micmute_led_mode_ctl = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.name = "Mic Mute-LED Mode",
|
||||
.info = micmute_led_mode_info,
|
||||
.get = micmute_led_mode_get,
|
||||
.put = micmute_led_mode_put,
|
||||
};
|
||||
|
||||
/* Set up the capture sync hook for controlling the mic-mute LED */
|
||||
static int add_micmute_led_hook(struct hda_codec *codec)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
|
||||
spec->micmute_led.led_mode = MICMUTE_LED_FOLLOW_MUTE;
|
||||
spec->micmute_led.capture = 0;
|
||||
spec->micmute_led.led_value = -1;
|
||||
spec->micmute_led.old_hook = spec->cap_sync_hook;
|
||||
spec->cap_sync_hook = update_micmute_led;
|
||||
if (!snd_hda_gen_add_kctl(spec, NULL, &micmute_led_mode_ctl))
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_hda_gen_add_micmute_led_cdev - Create a LED classdev and enable as mic-mute LED
|
||||
* @codec: the HDA codec
|
||||
@ -4091,6 +3973,7 @@ int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
|
||||
int (*callback)(struct led_classdev *,
|
||||
enum led_brightness))
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
int err;
|
||||
|
||||
if (callback) {
|
||||
@ -4101,7 +3984,8 @@ int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
|
||||
}
|
||||
}
|
||||
|
||||
return add_micmute_led_hook(codec);
|
||||
spec->mic_mute_led = 1;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led_cdev);
|
||||
#endif /* CONFIG_SND_HDA_GENERIC_LEDS */
|
||||
@ -5060,6 +4944,9 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
|
||||
|
||||
parse_user_hints(codec);
|
||||
|
||||
if (spec->vmaster_mute_led || spec->mic_mute_led)
|
||||
snd_ctl_led_request();
|
||||
|
||||
if (spec->mixer_nid && !spec->mixer_merge_nid)
|
||||
spec->mixer_merge_nid = spec->mixer_nid;
|
||||
|
||||
@ -5291,7 +5178,7 @@ int snd_hda_gen_build_controls(struct hda_codec *codec)
|
||||
!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
|
||||
err = snd_hda_add_vmaster(codec, "Master Playback Volume",
|
||||
spec->vmaster_tlv, follower_pfxs,
|
||||
"Playback Volume");
|
||||
"Playback Volume", 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
@ -5299,13 +5186,14 @@ int snd_hda_gen_build_controls(struct hda_codec *codec)
|
||||
!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
|
||||
err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
|
||||
NULL, follower_pfxs,
|
||||
"Playback Switch",
|
||||
true, &spec->vmaster_mute.sw_kctl);
|
||||
"Playback Switch", true,
|
||||
spec->vmaster_mute_led ?
|
||||
SNDRV_CTL_ELEM_ACCESS_SPK_LED : 0,
|
||||
&spec->vmaster_mute.sw_kctl);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (spec->vmaster_mute.hook) {
|
||||
snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
|
||||
spec->vmaster_mute_enum);
|
||||
snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute);
|
||||
snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
|
||||
}
|
||||
}
|
||||
|
@ -84,15 +84,6 @@ struct badness_table {
|
||||
extern const struct badness_table hda_main_out_badness;
|
||||
extern const struct badness_table hda_extra_out_badness;
|
||||
|
||||
struct hda_micmute_hook {
|
||||
unsigned int led_mode;
|
||||
unsigned int capture;
|
||||
unsigned int led_value;
|
||||
void (*old_hook)(struct hda_codec *codec,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
};
|
||||
|
||||
struct hda_gen_spec {
|
||||
char stream_name_analog[32]; /* analog PCM stream */
|
||||
const struct hda_pcm_stream *stream_analog_playback;
|
||||
@ -229,7 +220,8 @@ struct hda_gen_spec {
|
||||
unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
|
||||
unsigned int own_eapd_ctl:1; /* set EAPD by own function */
|
||||
unsigned int keep_eapd_on:1; /* don't turn off EAPD automatically */
|
||||
unsigned int vmaster_mute_enum:1; /* add vmaster mute mode enum */
|
||||
unsigned int vmaster_mute_led:1; /* add SPK-LED flag to vmaster mute switch */
|
||||
unsigned int mic_mute_led:1; /* add MIC-LED flag to capture mute switch */
|
||||
unsigned int indep_hp:1; /* independent HP supported */
|
||||
unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */
|
||||
unsigned int add_stereo_mix_input:2; /* add aamix as a capture src */
|
||||
@ -285,9 +277,6 @@ struct hda_gen_spec {
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
||||
/* mic mute LED hook; called via cap_sync_hook */
|
||||
struct hda_micmute_hook micmute_led;
|
||||
|
||||
/* PCM hooks */
|
||||
void (*pcm_playback_hook)(struct hda_pcm_stream *hinfo,
|
||||
struct hda_codec *codec,
|
||||
|
@ -388,6 +388,69 @@ int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_jack_set_gating_jack);
|
||||
|
||||
/**
|
||||
* snd_hda_jack_bind_keymap - bind keys generated from one NID to another jack.
|
||||
* @codec: the HDA codec
|
||||
* @key_nid: key event is generated by this pin NID
|
||||
* @keymap: map of key type and key code
|
||||
* @jack_nid: key reports to the jack of this pin NID
|
||||
*
|
||||
* This function is used in the case of key is generated from one NID while is
|
||||
* reported to the jack of another NID.
|
||||
*/
|
||||
int snd_hda_jack_bind_keymap(struct hda_codec *codec, hda_nid_t key_nid,
|
||||
const struct hda_jack_keymap *keymap,
|
||||
hda_nid_t jack_nid)
|
||||
{
|
||||
const struct hda_jack_keymap *map;
|
||||
struct hda_jack_tbl *key_gen = snd_hda_jack_tbl_get(codec, key_nid);
|
||||
struct hda_jack_tbl *report_to = snd_hda_jack_tbl_get(codec, jack_nid);
|
||||
|
||||
WARN_ON(codec->dp_mst);
|
||||
|
||||
if (!key_gen || !report_to || !report_to->jack)
|
||||
return -EINVAL;
|
||||
|
||||
key_gen->key_report_jack = jack_nid;
|
||||
|
||||
if (keymap)
|
||||
for (map = keymap; map->type; map++)
|
||||
snd_jack_set_key(report_to->jack, map->type, map->key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_jack_bind_keymap);
|
||||
|
||||
/**
|
||||
* snd_hda_jack_set_button_state - report button event to the hda_jack_tbl button_state.
|
||||
* @codec: the HDA codec
|
||||
* @jack_nid: the button event reports to the jack_tbl of this NID
|
||||
* @button_state: the button event captured by codec
|
||||
*
|
||||
* Codec driver calls this function to report the button event.
|
||||
*/
|
||||
void snd_hda_jack_set_button_state(struct hda_codec *codec, hda_nid_t jack_nid,
|
||||
int button_state)
|
||||
{
|
||||
struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, jack_nid);
|
||||
|
||||
if (!jack)
|
||||
return;
|
||||
|
||||
if (jack->key_report_jack) {
|
||||
struct hda_jack_tbl *report_to =
|
||||
snd_hda_jack_tbl_get(codec, jack->key_report_jack);
|
||||
|
||||
if (report_to) {
|
||||
report_to->button_state = button_state;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
jack->button_state = button_state;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_jack_set_button_state);
|
||||
|
||||
/**
|
||||
* snd_hda_jack_report_sync - sync the states of all jacks and report if changed
|
||||
* @codec: the HDA codec
|
||||
@ -651,7 +714,15 @@ void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res)
|
||||
}
|
||||
if (!event)
|
||||
return;
|
||||
event->jack_dirty = 1;
|
||||
|
||||
if (event->key_report_jack) {
|
||||
struct hda_jack_tbl *report_to =
|
||||
snd_hda_jack_tbl_get_mst(codec, event->key_report_jack,
|
||||
event->dev_id);
|
||||
if (report_to)
|
||||
report_to->jack_dirty = 1;
|
||||
} else
|
||||
event->jack_dirty = 1;
|
||||
|
||||
call_jack_callback(codec, res, event);
|
||||
snd_hda_jack_report_sync(codec);
|
||||
|
@ -40,6 +40,7 @@ struct hda_jack_tbl {
|
||||
unsigned int block_report:1; /* in a transitional state - do not report to userspace */
|
||||
hda_nid_t gating_jack; /* valid when gating jack plugged */
|
||||
hda_nid_t gated_jack; /* gated is dependent on this jack */
|
||||
hda_nid_t key_report_jack; /* key reports to this jack */
|
||||
int type;
|
||||
int button_state;
|
||||
struct snd_jack *jack;
|
||||
@ -99,6 +100,13 @@ snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
|
||||
int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
|
||||
hda_nid_t gating_nid);
|
||||
|
||||
int snd_hda_jack_bind_keymap(struct hda_codec *codec, hda_nid_t key_nid,
|
||||
const struct hda_jack_keymap *keymap,
|
||||
hda_nid_t jack_nid);
|
||||
|
||||
void snd_hda_jack_set_button_state(struct hda_codec *codec, hda_nid_t jack_nid,
|
||||
int button_state);
|
||||
|
||||
u32 snd_hda_jack_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id);
|
||||
|
||||
/* the jack state returned from snd_hda_jack_detect_state() */
|
||||
|
@ -131,21 +131,15 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
|
||||
int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
|
||||
unsigned int *tlv, const char * const *followers,
|
||||
const char *suffix, bool init_follower_vol,
|
||||
struct snd_kcontrol **ctl_ret);
|
||||
#define snd_hda_add_vmaster(codec, name, tlv, followers, suffix) \
|
||||
__snd_hda_add_vmaster(codec, name, tlv, followers, suffix, true, NULL)
|
||||
unsigned int access, struct snd_kcontrol **ctl_ret);
|
||||
#define snd_hda_add_vmaster(codec, name, tlv, followers, suffix, access) \
|
||||
__snd_hda_add_vmaster(codec, name, tlv, followers, suffix, true, access, NULL)
|
||||
int snd_hda_codec_reset(struct hda_codec *codec);
|
||||
void snd_hda_codec_register(struct hda_codec *codec);
|
||||
void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec);
|
||||
|
||||
#define snd_hda_regmap_sync(codec) snd_hdac_regmap_sync(&(codec)->core)
|
||||
|
||||
enum {
|
||||
HDA_VMUTE_OFF,
|
||||
HDA_VMUTE_ON,
|
||||
HDA_VMUTE_FOLLOW_MASTER,
|
||||
};
|
||||
|
||||
struct hda_vmaster_mute_hook {
|
||||
/* below two fields must be filled by the caller of
|
||||
* snd_hda_add_vmaster_hook() beforehand
|
||||
@ -153,13 +147,11 @@ struct hda_vmaster_mute_hook {
|
||||
struct snd_kcontrol *sw_kctl;
|
||||
void (*hook)(void *, int);
|
||||
/* below are initialized automatically */
|
||||
unsigned int mute_mode; /* HDA_VMUTE_XXX */
|
||||
struct hda_codec *codec;
|
||||
};
|
||||
|
||||
int snd_hda_add_vmaster_hook(struct hda_codec *codec,
|
||||
struct hda_vmaster_mute_hook *hook,
|
||||
bool expose_enum_ctl);
|
||||
struct hda_vmaster_mute_hook *hook);
|
||||
void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook);
|
||||
|
||||
/* amp value bits */
|
||||
@ -180,7 +172,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid);
|
||||
/*
|
||||
* input MUX helper
|
||||
*/
|
||||
#define HDA_MAX_NUM_INPUTS 16
|
||||
#define HDA_MAX_NUM_INPUTS 36
|
||||
struct hda_input_mux_item {
|
||||
char label[32];
|
||||
unsigned int index;
|
||||
|
492
sound/pci/hda/ideapad_s740_helper.c
Normal file
492
sound/pci/hda/ideapad_s740_helper.c
Normal file
@ -0,0 +1,492 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Fixes for Lenovo Ideapad S740, to be included from codec driver */
|
||||
|
||||
static const struct hda_verb alc285_ideapad_s740_coefs[] = {
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x10 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0320 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0041 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0041 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001d },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x004e },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001d },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x004e },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x002a },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x002a },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0046 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0046 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0044 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0044 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
||||
{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
||||
{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
||||
{}
|
||||
};
|
||||
|
||||
static void alc285_fixup_ideapad_s740_coef(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix,
|
||||
int action)
|
||||
{
|
||||
switch (action) {
|
||||
case HDA_FIXUP_ACT_PRE_PROBE:
|
||||
snd_hda_add_verbs(codec, alc285_ideapad_s740_coefs);
|
||||
break;
|
||||
}
|
||||
}
|
@ -7041,11 +7041,11 @@ static int ca0132_build_controls(struct hda_codec *codec)
|
||||
spec->tlv);
|
||||
snd_hda_add_vmaster(codec, "Master Playback Volume",
|
||||
spec->tlv, ca0132_alt_follower_pfxs,
|
||||
"Playback Volume");
|
||||
"Playback Volume", 0);
|
||||
err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
|
||||
NULL, ca0132_alt_follower_pfxs,
|
||||
"Playback Switch",
|
||||
true, &spec->vmaster_mute.sw_kctl);
|
||||
true, 0, &spec->vmaster_mute.sw_kctl);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -930,18 +930,18 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x8079, "HP EliteBook 840 G3", CXT_FIXUP_HP_DOCK),
|
||||
SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK),
|
||||
SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK),
|
||||
SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC),
|
||||
SND_PCI_QUIRK(0x103c, 0x814f, "HP ZBook 15u G3", CXT_FIXUP_MUTE_LED_GPIO),
|
||||
SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
|
||||
SND_PCI_QUIRK(0x103c, 0x822e, "HP ProBook 440 G4", CXT_FIXUP_MUTE_LED_GPIO),
|
||||
SND_PCI_QUIRK(0x103c, 0x828c, "HP EliteBook 840 G4", CXT_FIXUP_HP_DOCK),
|
||||
SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x836e, "HP ProBook 455 G5", CXT_FIXUP_MUTE_LED_GPIO),
|
||||
SND_PCI_QUIRK(0x103c, 0x837f, "HP ProBook 470 G5", CXT_FIXUP_MUTE_LED_GPIO),
|
||||
SND_PCI_QUIRK(0x103c, 0x83b2, "HP EliteBook 840 G5", CXT_FIXUP_HP_DOCK),
|
||||
SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK),
|
||||
SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK),
|
||||
SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
|
||||
SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC),
|
||||
SND_PCI_QUIRK(0x103c, 0x814f, "HP ZBook 15u G3", CXT_FIXUP_MUTE_LED_GPIO),
|
||||
SND_PCI_QUIRK(0x103c, 0x822e, "HP ProBook 440 G4", CXT_FIXUP_MUTE_LED_GPIO),
|
||||
SND_PCI_QUIRK(0x103c, 0x836e, "HP ProBook 455 G5", CXT_FIXUP_MUTE_LED_GPIO),
|
||||
SND_PCI_QUIRK(0x103c, 0x837f, "HP ProBook 470 G5", CXT_FIXUP_MUTE_LED_GPIO),
|
||||
SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x8402, "HP ProBook 645 G4", CXT_FIXUP_MUTE_LED_GPIO),
|
||||
SND_PCI_QUIRK(0x103c, 0x8427, "HP ZBook Studio G5", CXT_FIXUP_HP_ZBOOK_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x844f, "HP ZBook Studio G5", CXT_FIXUP_HP_ZBOOK_MUTE_LED),
|
||||
|
@ -1848,16 +1848,12 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
|
||||
*/
|
||||
if (spec->intel_hsw_fixup) {
|
||||
/*
|
||||
* On Intel platforms, device entries number is
|
||||
* changed dynamically. If there is a DP MST
|
||||
* hub connected, the device entries number is 3.
|
||||
* Otherwise, it is 1.
|
||||
* Here we manually set dev_num to 3, so that
|
||||
* we can initialize all the device entries when
|
||||
* bootup statically.
|
||||
* On Intel platforms, device entries count returned
|
||||
* by AC_PAR_DEVLIST_LEN is dynamic, and depends on
|
||||
* the type of receiver that is connected. Allocate pin
|
||||
* structures based on worst case.
|
||||
*/
|
||||
dev_num = 3;
|
||||
spec->dev_num = 3;
|
||||
dev_num = spec->dev_num;
|
||||
} else if (spec->dyn_pcm_assign && codec->dp_mst) {
|
||||
dev_num = snd_hda_get_num_devices(codec, pin_nid) + 1;
|
||||
/*
|
||||
@ -2658,7 +2654,7 @@ static void generic_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id)
|
||||
/* skip notification during system suspend (but not in runtime PM);
|
||||
* the state will be updated at resume
|
||||
*/
|
||||
if (snd_power_get_state(codec->card) != SNDRV_CTL_POWER_D0)
|
||||
if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND)
|
||||
return;
|
||||
/* ditto during suspend/resume process itself */
|
||||
if (snd_hdac_is_in_pm(&codec->core))
|
||||
@ -2844,7 +2840,7 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
|
||||
/* skip notification during system suspend (but not in runtime PM);
|
||||
* the state will be updated at resume
|
||||
*/
|
||||
if (snd_power_get_state(codec->card) != SNDRV_CTL_POWER_D0)
|
||||
if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND)
|
||||
return;
|
||||
/* ditto during suspend/resume process itself */
|
||||
if (snd_hdac_is_in_pm(&codec->core))
|
||||
@ -2942,7 +2938,7 @@ static int parse_intel_hdmi(struct hda_codec *codec)
|
||||
|
||||
/* Intel Haswell and onwards; audio component with eld notifier */
|
||||
static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
|
||||
const int *port_map, int port_num)
|
||||
const int *port_map, int port_num, int dev_num)
|
||||
{
|
||||
struct hdmi_spec *spec;
|
||||
int err;
|
||||
@ -2957,6 +2953,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
|
||||
spec->port_map = port_map;
|
||||
spec->port_num = port_num;
|
||||
spec->intel_hsw_fixup = true;
|
||||
spec->dev_num = dev_num;
|
||||
|
||||
intel_haswell_enable_all_pins(codec, true);
|
||||
intel_haswell_fixup_enable_dp12(codec);
|
||||
@ -2982,12 +2979,12 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
|
||||
|
||||
static int patch_i915_hsw_hdmi(struct hda_codec *codec)
|
||||
{
|
||||
return intel_hsw_common_init(codec, 0x08, NULL, 0);
|
||||
return intel_hsw_common_init(codec, 0x08, NULL, 0, 3);
|
||||
}
|
||||
|
||||
static int patch_i915_glk_hdmi(struct hda_codec *codec)
|
||||
{
|
||||
return intel_hsw_common_init(codec, 0x0b, NULL, 0);
|
||||
return intel_hsw_common_init(codec, 0x0b, NULL, 0, 3);
|
||||
}
|
||||
|
||||
static int patch_i915_icl_hdmi(struct hda_codec *codec)
|
||||
@ -2998,7 +2995,7 @@ static int patch_i915_icl_hdmi(struct hda_codec *codec)
|
||||
*/
|
||||
static const int map[] = {0x0, 0x4, 0x6, 0x8, 0xa, 0xb};
|
||||
|
||||
return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map));
|
||||
return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 3);
|
||||
}
|
||||
|
||||
static int patch_i915_tgl_hdmi(struct hda_codec *codec)
|
||||
@ -3010,7 +3007,7 @@ static int patch_i915_tgl_hdmi(struct hda_codec *codec)
|
||||
static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
|
||||
int ret;
|
||||
|
||||
ret = intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map));
|
||||
ret = intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 4);
|
||||
if (!ret) {
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
|
||||
|
@ -292,7 +292,7 @@ static void alc_fixup_gpio4(struct hda_codec *codec,
|
||||
static void alc_fixup_micmute_led(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
if (action == HDA_FIXUP_ACT_PROBE)
|
||||
if (action == HDA_FIXUP_ACT_PRE_PROBE)
|
||||
snd_hda_gen_add_micmute_led_cdev(codec, NULL);
|
||||
}
|
||||
|
||||
@ -2470,13 +2470,13 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
|
||||
ALC882_FIXUP_ACER_ASPIRE_8930G),
|
||||
SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
|
||||
ALC882_FIXUP_ACER_ASPIRE_8930G),
|
||||
SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
|
||||
ALC882_FIXUP_ACER_ASPIRE_4930G),
|
||||
SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
|
||||
SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
|
||||
ALC882_FIXUP_ACER_ASPIRE_4930G),
|
||||
SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
|
||||
ALC882_FIXUP_ACER_ASPIRE_4930G),
|
||||
SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
|
||||
ALC882_FIXUP_ACER_ASPIRE_4930G),
|
||||
SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
|
||||
SND_PCI_QUIRK(0x1025, 0x021e, "Acer Aspire 5739G",
|
||||
ALC882_FIXUP_ACER_ASPIRE_4930G),
|
||||
SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),
|
||||
@ -2489,11 +2489,11 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
|
||||
SND_PCI_QUIRK(0x1043, 0x84bc, "ASUS ET2700", ALC887_FIXUP_ASUS_BASS),
|
||||
SND_PCI_QUIRK(0x1043, 0x8691, "ASUS ROG Ranger VIII", ALC882_FIXUP_GPIO3),
|
||||
SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
|
||||
SND_PCI_QUIRK(0x104d, 0x9044, "Sony VAIO AiO", ALC882_FIXUP_NO_PRIMARY_HP),
|
||||
SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
|
||||
SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
|
||||
SND_PCI_QUIRK(0x104d, 0x9060, "Sony Vaio VPCL14M1R", ALC882_FIXUP_NO_PRIMARY_HP),
|
||||
SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
|
||||
SND_PCI_QUIRK(0x104d, 0x9044, "Sony VAIO AiO", ALC882_FIXUP_NO_PRIMARY_HP),
|
||||
|
||||
/* All Apple entries are in codec SSIDs */
|
||||
SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
|
||||
@ -2536,9 +2536,19 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
|
||||
SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
|
||||
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
|
||||
SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x65d2, "Clevo PB51R[CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x65e1, "Clevo PB51[ED][DF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x65e5, "Clevo PC50D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950),
|
||||
SND_PCI_QUIRK(0x1558, 0x9506, "Clevo P955HQ", ALC1220_FIXUP_CLEVO_P950),
|
||||
SND_PCI_QUIRK(0x1558, 0x950A, "Clevo P955H[PR]", ALC1220_FIXUP_CLEVO_P950),
|
||||
SND_PCI_QUIRK(0x1558, 0x950a, "Clevo P955H[PR]", ALC1220_FIXUP_CLEVO_P950),
|
||||
SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950),
|
||||
SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950),
|
||||
SND_PCI_QUIRK(0x1558, 0x95e3, "Clevo P955[ER]T", ALC1220_FIXUP_CLEVO_P950),
|
||||
@ -2548,14 +2558,6 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1558, 0x96e1, "Clevo P960[ER][CDFN]-K", ALC1220_FIXUP_CLEVO_P950),
|
||||
SND_PCI_QUIRK(0x1558, 0x97e1, "Clevo P970[ER][CDFN]", ALC1220_FIXUP_CLEVO_P950),
|
||||
SND_PCI_QUIRK(0x1558, 0x97e2, "Clevo P970RC-M", ALC1220_FIXUP_CLEVO_P950),
|
||||
SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x65d2, "Clevo PB51R[CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x65e1, "Clevo PB51[ED][DF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
|
||||
SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
|
||||
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
|
||||
@ -3103,7 +3105,7 @@ static void alc_headset_btn_callback(struct hda_codec *codec,
|
||||
if (jack->unsol_res & (7 << 10))
|
||||
report |= SND_JACK_BTN_3;
|
||||
|
||||
jack->jack->button_state = report;
|
||||
snd_hda_jack_set_button_state(codec, jack->nid, report);
|
||||
}
|
||||
|
||||
static void alc_disable_headset_jack_key(struct hda_codec *codec)
|
||||
@ -3164,16 +3166,23 @@ static void alc_fixup_headset_jack(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
hda_nid_t hp_pin;
|
||||
|
||||
switch (action) {
|
||||
case HDA_FIXUP_ACT_PRE_PROBE:
|
||||
spec->has_hs_key = 1;
|
||||
snd_hda_jack_detect_enable_callback(codec, 0x55,
|
||||
alc_headset_btn_callback);
|
||||
snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack", false,
|
||||
SND_JACK_HEADSET, alc_headset_btn_keymap);
|
||||
break;
|
||||
case HDA_FIXUP_ACT_INIT:
|
||||
case HDA_FIXUP_ACT_BUILD:
|
||||
hp_pin = alc_get_hp_pin(spec);
|
||||
if (!hp_pin || snd_hda_jack_bind_keymap(codec, 0x55,
|
||||
alc_headset_btn_keymap,
|
||||
hp_pin))
|
||||
snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack",
|
||||
false, SND_JACK_HEADSET,
|
||||
alc_headset_btn_keymap);
|
||||
|
||||
alc_enable_headset_jack_key(codec);
|
||||
break;
|
||||
}
|
||||
@ -4438,6 +4447,25 @@ static void alc236_fixup_hp_mute_led(struct hda_codec *codec,
|
||||
alc236_fixup_hp_coef_micmute_led(codec, fix, action);
|
||||
}
|
||||
|
||||
static void alc236_fixup_hp_micmute_led_vref(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
|
||||
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
|
||||
spec->cap_mute_led_nid = 0x1a;
|
||||
snd_hda_gen_add_micmute_led_cdev(codec, vref_micmute_led_set);
|
||||
codec->power_filter = led_power_filter;
|
||||
}
|
||||
}
|
||||
|
||||
static void alc236_fixup_hp_mute_led_micmute_vref(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
alc236_fixup_hp_mute_led_coefbit(codec, fix, action);
|
||||
alc236_fixup_hp_micmute_led_vref(codec, fix, action);
|
||||
}
|
||||
|
||||
#if IS_REACHABLE(CONFIG_INPUT)
|
||||
static void gpio2_mic_hotkey_event(struct hda_codec *codec,
|
||||
struct hda_jack_callback *event)
|
||||
@ -6232,6 +6260,9 @@ static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
|
||||
/* for alc295_fixup_hp_top_speakers */
|
||||
#include "hp_x360_helper.c"
|
||||
|
||||
/* for alc285_fixup_ideapad_s740_coef() */
|
||||
#include "ideapad_s740_helper.c"
|
||||
|
||||
enum {
|
||||
ALC269_FIXUP_GPIO2,
|
||||
ALC269_FIXUP_SONY_VAIO,
|
||||
@ -6400,6 +6431,7 @@ enum {
|
||||
ALC285_FIXUP_HP_MUTE_LED,
|
||||
ALC236_FIXUP_HP_GPIO_LED,
|
||||
ALC236_FIXUP_HP_MUTE_LED,
|
||||
ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
|
||||
ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
|
||||
ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
|
||||
ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS,
|
||||
@ -6415,6 +6447,8 @@ enum {
|
||||
ALC269_FIXUP_LEMOTE_A1802,
|
||||
ALC269_FIXUP_LEMOTE_A190X,
|
||||
ALC256_FIXUP_INTEL_NUC8_RUGGED,
|
||||
ALC233_FIXUP_INTEL_NUC8_DMIC,
|
||||
ALC233_FIXUP_INTEL_NUC8_BOOST,
|
||||
ALC256_FIXUP_INTEL_NUC10,
|
||||
ALC255_FIXUP_XIAOMI_HEADSET_MIC,
|
||||
ALC274_FIXUP_HP_MIC,
|
||||
@ -6427,6 +6461,8 @@ enum {
|
||||
ALC282_FIXUP_ACER_DISABLE_LINEOUT,
|
||||
ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST,
|
||||
ALC256_FIXUP_ACER_HEADSET_MIC,
|
||||
ALC285_FIXUP_IDEAPAD_S740_COEF,
|
||||
ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST,
|
||||
};
|
||||
|
||||
static const struct hda_fixup alc269_fixups[] = {
|
||||
@ -7136,6 +7172,16 @@ static const struct hda_fixup alc269_fixups[] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc233_fixup_lenovo_line2_mic_hotkey,
|
||||
},
|
||||
[ALC233_FIXUP_INTEL_NUC8_DMIC] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc_fixup_inv_dmic,
|
||||
.chained = true,
|
||||
.chain_id = ALC233_FIXUP_INTEL_NUC8_BOOST,
|
||||
},
|
||||
[ALC233_FIXUP_INTEL_NUC8_BOOST] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc269_fixup_limit_int_mic_boost
|
||||
},
|
||||
[ALC255_FIXUP_DELL_SPK_NOISE] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc_fixup_disable_aamix,
|
||||
@ -7646,6 +7692,10 @@ static const struct hda_fixup alc269_fixups[] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc236_fixup_hp_mute_led,
|
||||
},
|
||||
[ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc236_fixup_hp_mute_led_micmute_vref,
|
||||
},
|
||||
[ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
|
||||
.type = HDA_FIXUP_VERBS,
|
||||
.v.verbs = (const struct hda_verb[]) {
|
||||
@ -7901,6 +7951,18 @@ static const struct hda_fixup alc269_fixups[] = {
|
||||
.chained = true,
|
||||
.chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
|
||||
},
|
||||
[ALC285_FIXUP_IDEAPAD_S740_COEF] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc285_fixup_ideapad_s740_coef,
|
||||
.chained = true,
|
||||
.chain_id = ALC269_FIXUP_THINKPAD_ACPI,
|
||||
},
|
||||
[ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc269_fixup_limit_int_mic_boost,
|
||||
.chained = true,
|
||||
.chain_id = ALC285_FIXUP_HP_MUTE_LED,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
@ -7909,12 +7971,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
|
||||
SND_PCI_QUIRK(0x1025, 0x072d, "Acer Aspire V5-571G", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
|
||||
SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
|
||||
SND_PCI_QUIRK(0x1025, 0x0762, "Acer Aspire E1-472", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
|
||||
SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
|
||||
SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS),
|
||||
SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x0840, "Acer Aspire E1", ALC269VB_FIXUP_ASPIRE_E1_COEF),
|
||||
SND_PCI_QUIRK(0x1025, 0x101c, "Acer Veriton N2510G", ALC269_FIXUP_LIFEBOOK),
|
||||
SND_PCI_QUIRK(0x1025, 0x102b, "Acer Aspire C24-860", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
|
||||
@ -7970,8 +8032,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1028, 0x0738, "Dell Precision 5820", ALC269_FIXUP_NO_SHUTUP),
|
||||
SND_PCI_QUIRK(0x1028, 0x075c, "Dell XPS 27 7760", ALC298_FIXUP_SPK_VOLUME),
|
||||
SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME),
|
||||
SND_PCI_QUIRK(0x1028, 0x07b0, "Dell Precision 7520", ALC295_FIXUP_DISABLE_DAC3),
|
||||
SND_PCI_QUIRK(0x1028, 0x0798, "Dell Inspiron 17 7000 Gaming", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER),
|
||||
SND_PCI_QUIRK(0x1028, 0x07b0, "Dell Precision 7520", ALC295_FIXUP_DISABLE_DAC3),
|
||||
SND_PCI_QUIRK(0x1028, 0x080c, "Dell WYSE", ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1028, 0x084b, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
|
||||
SND_PCI_QUIRK(0x1028, 0x084e, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
|
||||
@ -7981,8 +8043,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1028, 0x08ad, "Dell WYSE AIO", ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1028, 0x08ae, "Dell WYSE NB", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
|
||||
SND_PCI_QUIRK(0x1028, 0x097e, "Dell Precision", ALC289_FIXUP_DUAL_SPK),
|
||||
SND_PCI_QUIRK(0x1028, 0x097d, "Dell Precision", ALC289_FIXUP_DUAL_SPK),
|
||||
SND_PCI_QUIRK(0x1028, 0x097e, "Dell Precision", ALC289_FIXUP_DUAL_SPK),
|
||||
SND_PCI_QUIRK(0x1028, 0x098d, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1028, 0x09bf, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0a2e, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC),
|
||||
@ -7993,35 +8055,18 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
|
||||
SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x225f, "HP", ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY),
|
||||
/* ALC282 */
|
||||
SND_PCI_QUIRK(0x103c, 0x21f9, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2210, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2237, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2238, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2239, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x224b, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x226e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2271, "HP", ALC286_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC280_FIXUP_HP_DOCK_PINS),
|
||||
SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC280_FIXUP_HP_DOCK_PINS),
|
||||
SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC280_FIXUP_HP_9480M),
|
||||
SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
/* ALC290 */
|
||||
SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2253, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2254, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2255, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
@ -8029,28 +8074,45 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x225f, "HP", ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY),
|
||||
SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x226e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2271, "HP", ALC286_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC280_FIXUP_HP_DOCK_PINS),
|
||||
SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC280_FIXUP_HP_DOCK_PINS),
|
||||
SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2282, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x228b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x228e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22c5, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22c7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22c8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC280_FIXUP_HP_9480M),
|
||||
SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2334, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x103c, 0x802e, "HP Z240 SFF", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x802f, "HP Z240", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x8077, "HP", ALC256_FIXUP_HP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x103c, 0x8158, "HP", ALC256_FIXUP_HP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x103c, 0x820d, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
SND_PCI_QUIRK(0x103c, 0x8256, "HP", ALC221_FIXUP_HP_FRONT_MIC),
|
||||
SND_PCI_QUIRK(0x103c, 0x827e, "HP x360", ALC295_FIXUP_HP_X360),
|
||||
@ -8063,6 +8125,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8724, "HP EliteBook 850 G7", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8729, "HP", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8730, "HP ProBook 445 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
|
||||
SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
||||
SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED),
|
||||
@ -8079,6 +8142,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
|
||||
SND_PCI_QUIRK(0x103c, 0x8846, "HP EliteBook 850 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x884c, "HP EliteBook 840 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8898, "HP EliteBook 845 G8 Notebook PC", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
|
||||
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
@ -8087,16 +8151,18 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x125e, "ASUS Q524UQK", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1271, "ASUS X430UN", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x12a0, "ASUS X441UV", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
|
||||
SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
|
||||
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
|
||||
SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
|
||||
SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x194e, "ASUS UX563FD", ALC294_FIXUP_ASUS_HPE),
|
||||
@ -8109,31 +8175,31 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x1043, 0x125e, "ASUS Q524UQK", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401),
|
||||
SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401),
|
||||
SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
|
||||
SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
|
||||
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101),
|
||||
SND_PCI_QUIRK(0x104d, 0x90b5, "Sony VAIO Pro 11", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
|
||||
SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
|
||||
SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
|
||||
SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX),
|
||||
SND_PCI_QUIRK(0x104d, 0x90b5, "Sony VAIO Pro 11", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
|
||||
SND_PCI_QUIRK(0x10cf, 0x159f, "Lifebook E780", ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT),
|
||||
SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN),
|
||||
SND_PCI_QUIRK(0x10cf, 0x1757, "Lifebook E752", ALC269_FIXUP_LIFEBOOK_HP_PIN),
|
||||
SND_PCI_QUIRK(0x10cf, 0x1629, "Lifebook U7x7", ALC255_FIXUP_LIFEBOOK_U7x7_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x10cf, 0x1757, "Lifebook E752", ALC269_FIXUP_LIFEBOOK_HP_PIN),
|
||||
SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
|
||||
SND_PCI_QUIRK(0x10ec, 0x10f2, "Intel Reference board", ALC700_FIXUP_INTEL_REFERENCE),
|
||||
SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x10ec, 0x1230, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
|
||||
SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
|
||||
SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
|
||||
@ -8143,9 +8209,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
|
||||
SND_PCI_QUIRK(0x144d, 0xc189, "Samsung Galaxy Flex Book (NT950QCG-X716)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
|
||||
SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NP930XCJ-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
|
||||
SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
|
||||
SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
|
||||
SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
|
||||
SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
|
||||
SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
|
||||
@ -8201,9 +8267,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
|
||||
SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
|
||||
SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
|
||||
SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK_LIMIT_BOOST),
|
||||
SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
|
||||
@ -8244,9 +8310,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
|
||||
SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC),
|
||||
SND_PCI_QUIRK(0x17aa, 0x501e, "Thinkpad L440", ALC292_FIXUP_TPT440_DOCK),
|
||||
@ -8265,20 +8333,19 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x17aa, 0x511e, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x511f, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
|
||||
SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
|
||||
SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
|
||||
SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20),
|
||||
SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI),
|
||||
SND_PCI_QUIRK(0x1b35, 0x1237, "CZC L101", ALC269_FIXUP_CZC_L101),
|
||||
SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
|
||||
SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802),
|
||||
SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X),
|
||||
SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802),
|
||||
SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X),
|
||||
SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
|
||||
SND_PCI_QUIRK(0x8086, 0x2080, "Intel NUC 8 Rugged", ALC256_FIXUP_INTEL_NUC8_RUGGED),
|
||||
SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", ALC256_FIXUP_INTEL_NUC10),
|
||||
|
||||
@ -8733,12 +8800,7 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
|
||||
{0x12, 0x90a60130},
|
||||
{0x19, 0x03a11020},
|
||||
{0x21, 0x0321101f}),
|
||||
SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK,
|
||||
{0x14, 0x90170110},
|
||||
{0x19, 0x04a11040},
|
||||
{0x21, 0x04211020}),
|
||||
SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE,
|
||||
{0x12, 0x90a60130},
|
||||
{0x14, 0x90170110},
|
||||
{0x19, 0x04a11040},
|
||||
{0x21, 0x04211020}),
|
||||
@ -8909,6 +8971,10 @@ static const struct snd_hda_pin_quirk alc269_fallback_pin_fixup_tbl[] = {
|
||||
SND_HDA_PIN_QUIRK(0x10ec0274, 0x1028, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB,
|
||||
{0x19, 0x40000000},
|
||||
{0x1a, 0x40000000}),
|
||||
SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK,
|
||||
{0x14, 0x90170110},
|
||||
{0x19, 0x04a11040},
|
||||
{0x21, 0x04211020}),
|
||||
{}
|
||||
};
|
||||
|
||||
@ -9224,8 +9290,7 @@ static const struct snd_pci_quirk alc861_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
|
||||
SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
|
||||
SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
|
||||
SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", ALC861_FIXUP_AMP_VREF_0F),
|
||||
SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", ALC861_FIXUP_AMP_VREF_0F),
|
||||
SND_PCI_QUIRK_VENDOR(0x1584, "Haier/Uniwill", ALC861_FIXUP_AMP_VREF_0F),
|
||||
SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505),
|
||||
{}
|
||||
};
|
||||
@ -10020,6 +10085,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
|
||||
SND_PCI_QUIRK(0x1025, 0x0566, "Acer Aspire Ethos 8951G", ALC669_FIXUP_ACER_ASPIRE_ETHOS),
|
||||
SND_PCI_QUIRK(0x1025, 0x123c, "Acer Nitro N50-600", ALC662_FIXUP_ACER_NITRO_HEADSET_MODE),
|
||||
SND_PCI_QUIRK(0x1025, 0x124e, "Acer 2660G", ALC662_FIXUP_ACER_X2660G_HEADSET_MODE),
|
||||
SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
|
||||
@ -10036,9 +10102,9 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x873e, "HP", ALC671_FIXUP_HP_HEADSET_MIC2),
|
||||
SND_PCI_QUIRK(0x1043, 0x1080, "Asus UX501VW", ALC668_FIXUP_HEADSET_MODE),
|
||||
SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50),
|
||||
SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A),
|
||||
SND_PCI_QUIRK(0x1043, 0x129d, "Asus N750", ALC662_FIXUP_ASUS_Nx50),
|
||||
SND_PCI_QUIRK(0x1043, 0x12ff, "ASUS G751", ALC668_FIXUP_ASUS_G751),
|
||||
SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A),
|
||||
SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
|
||||
SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16),
|
||||
SND_PCI_QUIRK(0x1043, 0x177d, "ASUS N551", ALC668_FIXUP_ASUS_Nx51),
|
||||
@ -10058,7 +10124,6 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1b0a, 0x01b8, "ACER Veriton", ALC662_FIXUP_ACER_VERITON),
|
||||
SND_PCI_QUIRK(0x1b35, 0x1234, "CZC ET26", ALC662_FIXUP_CZC_ET26),
|
||||
SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
|
||||
SND_PCI_QUIRK(0x1025, 0x0566, "Acer Aspire Ethos 8951G", ALC669_FIXUP_ACER_ASPIRE_ETHOS),
|
||||
|
||||
#if 0
|
||||
/* Below is a quirk table taken from the old code.
|
||||
|
@ -4277,6 +4277,9 @@ static int stac_parse_auto_config(struct hda_codec *codec)
|
||||
|
||||
spec->gen.automute_hook = stac_update_outputs;
|
||||
|
||||
if (spec->gpio_led)
|
||||
snd_hda_gen_add_mute_led_cdev(codec, stac_vmaster_hook);
|
||||
|
||||
err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -4318,9 +4321,6 @@ static int stac_parse_auto_config(struct hda_codec *codec)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (spec->gpio_led)
|
||||
snd_hda_gen_add_mute_led_cdev(codec, stac_vmaster_hook);
|
||||
|
||||
if (spec->aloopback_ctl &&
|
||||
snd_hda_get_bool_hint(codec, "loopback") == 1) {
|
||||
unsigned int wr_verb =
|
||||
|
@ -18,7 +18,7 @@ static bool is_thinkpad(struct hda_codec *codec)
|
||||
static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
if (action == HDA_FIXUP_ACT_PROBE) {
|
||||
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
|
||||
if (!is_thinkpad(codec))
|
||||
return;
|
||||
snd_hda_gen_add_mute_led_cdev(codec, NULL);
|
||||
|
@ -22,7 +22,8 @@
|
||||
|
||||
|
||||
/**
|
||||
* wait for a value on a peudo register, exit with a timeout
|
||||
* mixart_wait_nice_for_register_value - wait for a value on a peudo register,
|
||||
* exit with a timeout
|
||||
*
|
||||
* @mgr: pointer to miXart manager structure
|
||||
* @offset: unsigned pseudo_register base + offset of value
|
||||
|
@ -5390,7 +5390,8 @@ static int snd_hdsp_free(struct hdsp *hdsp)
|
||||
if (hdsp->port)
|
||||
pci_release_regions(hdsp->pci);
|
||||
|
||||
pci_disable_device(hdsp->pci);
|
||||
if (pci_is_enabled(hdsp->pci))
|
||||
pci_disable_device(hdsp->pci);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -6883,7 +6883,8 @@ static int snd_hdspm_free(struct hdspm * hdspm)
|
||||
if (hdspm->port)
|
||||
pci_release_regions(hdspm->pci);
|
||||
|
||||
pci_disable_device(hdspm->pci);
|
||||
if (pci_is_enabled(hdspm->pci))
|
||||
pci_disable_device(hdspm->pci);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1731,7 +1731,8 @@ static int snd_rme9652_free(struct snd_rme9652 *rme9652)
|
||||
if (rme9652->port)
|
||||
pci_release_regions(rme9652->pci);
|
||||
|
||||
pci_disable_device(rme9652->pci);
|
||||
if (pci_is_enabled(rme9652->pci))
|
||||
pci_disable_device(rme9652->pci);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user